user32: Cache the window class name on the client side.

This commit is contained in:
Alexandre Julliard 2007-11-02 11:57:35 +01:00
parent 1ee62a8d72
commit 8b42238b5b
1 changed files with 65 additions and 33 deletions

View File

@ -41,6 +41,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(class); WINE_DEFAULT_DEBUG_CHANNEL(class);
#define MAX_ATOM_LEN 255 /* from dlls/kernel32/atom.c */
typedef struct tagCLASS typedef struct tagCLASS
{ {
struct list entry; /* Entry in class list */ struct list entry; /* Entry in class list */
@ -56,12 +58,12 @@ typedef struct tagCLASS
HCURSOR hCursor; /* Default cursor */ HCURSOR hCursor; /* Default cursor */
HBRUSH hbrBackground; /* Default background */ HBRUSH hbrBackground; /* Default background */
ATOM atomName; /* Name of the class */ ATOM atomName; /* Name of the class */
WCHAR name[MAX_ATOM_LEN + 1];
} CLASS; } CLASS;
static struct list class_list = LIST_INIT( class_list ); static struct list class_list = LIST_INIT( class_list );
#define CLASS_OTHER_PROCESS ((CLASS *)1) #define CLASS_OTHER_PROCESS ((CLASS *)1)
#define MAX_ATOM_LEN 255 /* from dlls/kernel32/atom.c */
/*********************************************************************** /***********************************************************************
* get_class_ptr * get_class_ptr
@ -283,29 +285,37 @@ void CLASS_FreeModuleClasses( HMODULE16 hModule )
/*********************************************************************** /***********************************************************************
* CLASS_FindClassByAtom * CLASS_FindClass
* *
* Return a pointer to the class. * Return a pointer to the class.
* hinstance has been normalized by the caller. * hinstance has been normalized by the caller.
*/ */
static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance ) static CLASS *CLASS_FindClass( LPCWSTR name, HINSTANCE hinstance )
{ {
struct list *ptr; struct list *ptr;
ATOM atom = get_int_atom_value( name );
USER_Lock(); USER_Lock();
LIST_FOR_EACH( ptr, &class_list ) LIST_FOR_EACH( ptr, &class_list )
{ {
CLASS *class = LIST_ENTRY( ptr, CLASS, entry ); CLASS *class = LIST_ENTRY( ptr, CLASS, entry );
if (class->atomName != atom) continue; if (atom)
{
if (class->atomName != atom) continue;
}
else
{
if (!name || strcmpiW( class->name, name )) continue;
}
if (!hinstance || !class->local || class->hInstance == hinstance) if (!hinstance || !class->local || class->hInstance == hinstance)
{ {
TRACE("0x%04x %p -> %p\n", atom, hinstance, class); TRACE("%s %p -> %p\n", debugstr_w(name), hinstance, class);
return class; return class;
} }
} }
USER_Unlock(); USER_Unlock();
TRACE("0x%04x %p -> not found\n", atom, hinstance); TRACE("%s %p -> not found\n", debugstr_w(name), hinstance);
return NULL; return NULL;
} }
@ -339,6 +349,10 @@ static CLASS *CLASS_RegisterClass( LPCWSTR name, HINSTANCE hInstance, BOOL local
classPtr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLASS) + classExtra ); classPtr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLASS) + classExtra );
if (!classPtr) return NULL; if (!classPtr) return NULL;
classPtr->atomName = get_int_atom_value( name );
if (!classPtr->atomName && name) strcpyW( classPtr->name, name );
else GlobalGetAtomNameW( classPtr->atomName, classPtr->name, sizeof(classPtr->name)/sizeof(WCHAR) );
SERVER_START_REQ( create_class ) SERVER_START_REQ( create_class )
{ {
req->local = local; req->local = local;
@ -347,8 +361,8 @@ static CLASS *CLASS_RegisterClass( LPCWSTR name, HINSTANCE hInstance, BOOL local
req->extra = classExtra; req->extra = classExtra;
req->win_extra = winExtra; req->win_extra = winExtra;
req->client_ptr = classPtr; req->client_ptr = classPtr;
if (!(req->atom = get_int_atom_value(name)) && name) req->atom = classPtr->atomName;
wine_server_add_data( req, name, strlenW(name) * sizeof(WCHAR) ); if (!req->atom && name) wine_server_add_data( req, name, strlenW(name) * sizeof(WCHAR) );
ret = !wine_server_call_err( req ); ret = !wine_server_call_err( req );
classPtr->atomName = reply->atom; classPtr->atomName = reply->atom;
} }
@ -942,6 +956,7 @@ static ULONG_PTR CLASS_SetClassLong( HWND hwnd, INT offset, LONG_PTR newval,
if (!set_server_info( hwnd, offset, newval, size )) break; if (!set_server_info( hwnd, offset, newval, size )) break;
retval = class->atomName; retval = class->atomName;
class->atomName = newval; class->atomName = newval;
GlobalGetAtomNameW( newval, class->name, sizeof(class->name)/sizeof(WCHAR) );
break; break;
case GCL_CBCLSEXTRA: /* cannot change this one */ case GCL_CBCLSEXTRA: /* cannot change this one */
SetLastError( ERROR_INVALID_PARAMETER ); SetLastError( ERROR_INVALID_PARAMETER );
@ -982,21 +997,14 @@ DWORD WINAPI SetClassLongA( HWND hwnd, INT offset, LONG newval )
*/ */
INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count ) INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
{ {
char tmpbuf[MAX_ATOM_LEN + 1]; WCHAR tmpbuf[MAX_ATOM_LEN + 1];
INT ret; DWORD len;
TRACE("%p %p %d\n", hwnd, buffer, count);
if (count <= 0) return 0; if (count <= 0) return 0;
if (!GetClassNameW( hwnd, tmpbuf, sizeof(tmpbuf)/sizeof(WCHAR) )) return 0;
ret = GlobalGetAtomNameA( GetClassLongW( hwnd, GCW_ATOM ), tmpbuf, MAX_ATOM_LEN + 1 ); RtlUnicodeToMultiByteN( buffer, count - 1, &len, tmpbuf, strlenW(tmpbuf) * sizeof(WCHAR) );
if (ret) buffer[len] = 0;
{ return len;
ret = min(count - 1, ret);
memcpy(buffer, tmpbuf, ret);
buffer[ret] = 0;
}
return ret;
} }
@ -1005,19 +1013,32 @@ INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
*/ */
INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count ) INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
{ {
WCHAR tmpbuf[MAX_ATOM_LEN + 1]; CLASS *class;
INT ret; INT ret;
TRACE("%p %p %d\n", hwnd, buffer, count); TRACE("%p %p %d\n", hwnd, buffer, count);
if (count <= 0) return 0; if (count <= 0) return 0;
ret = GlobalGetAtomNameW( GetClassLongW( hwnd, GCW_ATOM ), tmpbuf, MAX_ATOM_LEN + 1 ); if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
if (ret)
if (class == CLASS_OTHER_PROCESS)
{ {
ret = min(count - 1, ret); WCHAR tmpbuf[MAX_ATOM_LEN + 1];
memcpy(buffer, tmpbuf, ret * sizeof(WCHAR));
buffer[ret] = 0; ret = GlobalGetAtomNameW( GetClassLongW( hwnd, GCW_ATOM ), tmpbuf, MAX_ATOM_LEN + 1 );
if (ret)
{
ret = min(count - 1, ret);
memcpy(buffer, tmpbuf, ret * sizeof(WCHAR));
buffer[ret] = 0;
}
}
else
{
lstrcpynW( buffer, class->name, count );
release_class_ptr( class );
ret = strlenW( buffer );
} }
return ret; return ret;
} }
@ -1096,14 +1117,23 @@ BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSW *wc )
*/ */
BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name, WNDCLASSEXA *wc ) BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name, WNDCLASSEXA *wc )
{ {
ATOM atom = HIWORD(name) ? GlobalFindAtomA( name ) : LOWORD(name); ATOM atom;
CLASS *classPtr; CLASS *classPtr;
TRACE("%p %s %x %p\n", hInstance, debugstr_a(name), atom, wc); TRACE("%p %s %p\n", hInstance, debugstr_a(name), wc);
if (!hInstance) hInstance = user32_module; if (!hInstance) hInstance = user32_module;
if (!atom || !(classPtr = CLASS_FindClassByAtom( atom, hInstance ))) if (!IS_INTRESOURCE(name))
{
WCHAR nameW[MAX_ATOM_LEN + 1];
if (!MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, sizeof(nameW)/sizeof(WCHAR) ))
return FALSE;
classPtr = CLASS_FindClass( nameW, hInstance );
}
else classPtr = CLASS_FindClass( (LPCWSTR)name, hInstance );
if (!classPtr)
{ {
SetLastError( ERROR_CLASS_DOES_NOT_EXIST ); SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
return FALSE; return FALSE;
@ -1119,6 +1149,7 @@ BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name, WNDCLASSEXA *wc )
wc->hbrBackground = (HBRUSH)classPtr->hbrBackground; wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
wc->lpszMenuName = CLASS_GetMenuNameA( classPtr ); wc->lpszMenuName = CLASS_GetMenuNameA( classPtr );
wc->lpszClassName = name; wc->lpszClassName = name;
atom = classPtr->atomName;
release_class_ptr( classPtr ); release_class_ptr( classPtr );
/* We must return the atom of the class here instead of just TRUE. */ /* We must return the atom of the class here instead of just TRUE. */
@ -1131,14 +1162,14 @@ BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name, WNDCLASSEXA *wc )
*/ */
BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSEXW *wc ) BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSEXW *wc )
{ {
ATOM atom = HIWORD(name) ? GlobalFindAtomW( name ) : LOWORD(name); ATOM atom;
CLASS *classPtr; CLASS *classPtr;
TRACE("%p %s %x %p\n", hInstance, debugstr_w(name), atom, wc); TRACE("%p %s %p\n", hInstance, debugstr_w(name), wc);
if (!hInstance) hInstance = user32_module; if (!hInstance) hInstance = user32_module;
if (!atom || !(classPtr = CLASS_FindClassByAtom( atom, hInstance ))) if (!(classPtr = CLASS_FindClass( name, hInstance )))
{ {
SetLastError( ERROR_CLASS_DOES_NOT_EXIST ); SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
return FALSE; return FALSE;
@ -1154,6 +1185,7 @@ BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSEXW *wc
wc->hbrBackground = (HBRUSH)classPtr->hbrBackground; wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
wc->lpszMenuName = CLASS_GetMenuNameW( classPtr ); wc->lpszMenuName = CLASS_GetMenuNameW( classPtr );
wc->lpszClassName = name; wc->lpszClassName = name;
atom = classPtr->atomName;
release_class_ptr( classPtr ); release_class_ptr( classPtr );
/* We must return the atom of the class here instead of just TRUE. */ /* We must return the atom of the class here instead of just TRUE. */