diff --git a/dlls/user/winproc.h b/dlls/user/winproc.h index 883a8fd260e..d68f3185013 100644 --- a/dlls/user/winproc.h +++ b/dlls/user/winproc.h @@ -137,11 +137,9 @@ inline static void unmap_str_16_to_32W( LPCWSTR str ) /* Class functions */ struct tagCLASS; /* opaque structure */ -struct tagDCE; +struct tagWND; extern void CLASS_RegisterBuiltinClasses( HINSTANCE inst ); -extern struct tagCLASS *CLASS_AddWindow( ATOM atom, HINSTANCE inst, WINDOWPROCTYPE type, - INT *winExtra, WNDPROC *winproc, - DWORD *style, struct tagDCE **dce ); +extern void CLASS_AddWindow( struct tagCLASS *class, struct tagWND *win, WINDOWPROCTYPE type ); extern void CLASS_FreeModuleClasses( HMODULE16 hModule ); /* Timer functions */ diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 116be53755f..eb10a862798 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2526,12 +2526,13 @@ struct create_window_request user_handle_t owner; atom_t atom; void* instance; - int extra; }; struct create_window_reply { struct reply_header __header; user_handle_t handle; + int extra; + void* class_ptr; }; @@ -3062,6 +3063,7 @@ struct create_class_request void* instance; int extra; int win_extra; + void* client_ptr; }; struct create_class_reply { @@ -3079,6 +3081,7 @@ struct destroy_class_request struct destroy_class_reply { struct reply_header __header; + void* client_ptr; }; @@ -3744,6 +3747,6 @@ union generic_reply struct set_global_windows_reply set_global_windows_reply; }; -#define SERVER_PROTOCOL_VERSION 129 +#define SERVER_PROTOCOL_VERSION 130 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/class.c b/server/class.c index 13d9d5cbf3b..5f034d9b5b5 100644 --- a/server/class.c +++ b/server/class.c @@ -44,10 +44,15 @@ struct window_class void *instance; /* module instance */ unsigned int style; /* class style */ int win_extra; /* number of window extra bytes */ + void *client_ptr; /* pointer to class in client address space */ int nb_extra_bytes; /* number of extra bytes */ char extra_bytes[1]; /* extra bytes storage */ }; +#define DESKTOP_ATOM ((atom_t)32769) + +static struct window_class *desktop_class; + static struct window_class *create_class( struct process *process, int extra_bytes, int local ) { struct window_class *class; @@ -67,6 +72,25 @@ static struct window_class *create_class( struct process *process, int extra_byt return class; } +static struct window_class *create_desktop_class( unsigned int style, int win_extra ) +{ + struct window_class *class; + + if (!(class = mem_alloc( sizeof(*class) - 1 ))) return NULL; + + class->process = NULL; + class->count = 0; + class->local = 0; + class->nb_extra_bytes = 0; + class->atom = DESKTOP_ATOM; + class->instance = NULL; + class->style = style; + class->win_extra = win_extra; + class->client_ptr = NULL; + desktop_class = class; + return class; +} + static void destroy_class( struct window_class *class ) { list_remove( &class->entry ); @@ -95,13 +119,19 @@ static struct window_class *find_class( struct process *process, atom_t atom, vo if (class->atom != atom) continue; if (!instance || !class->local || class->instance == instance) return class; } + if (atom == DESKTOP_ATOM) return desktop_class; return NULL; } -struct window_class *grab_class( struct process *process, atom_t atom, void *instance ) +struct window_class *grab_class( struct process *process, atom_t atom, + void *instance, int *extra_bytes ) { struct window_class *class = find_class( process, atom, instance ); - if (class) class->count++; + if (class) + { + class->count++; + *extra_bytes = class->win_extra; + } else set_error( STATUS_INVALID_HANDLE ); return class; } @@ -117,18 +147,31 @@ atom_t get_class_atom( struct window_class *class ) return class->atom; } +void *get_class_client_ptr( struct window_class *class ) +{ + return class->client_ptr; +} + /* create a window class */ DECL_HANDLER(create_class) { - struct window_class *class = find_class( current->process, req->atom, req->instance ); + struct window_class *class; + if (!req->local && req->atom == DESKTOP_ATOM) + { + if (!desktop_class) create_desktop_class( req->style, req->win_extra ); + return; /* silently ignore further attempts to create the desktop class */ + } + + class = find_class( current->process, req->atom, req->instance ); if (class && !class->local == !req->local) { set_win32_error( ERROR_CLASS_ALREADY_EXISTS ); return; } - if (req->extra < 0 || req->extra > 4096) /* don't allow stupid values here */ + if (req->extra < 0 || req->extra > 4096 || req->win_extra < 0 || req->win_extra > 4096) { + /* don't allow stupid values here */ set_error( STATUS_INVALID_PARAMETER ); return; } @@ -139,10 +182,11 @@ DECL_HANDLER(create_class) release_global_atom( req->atom ); return; } - class->atom = req->atom; - class->instance = req->instance; - class->style = req->style; - class->win_extra = req->win_extra; + class->atom = req->atom; + class->instance = req->instance; + class->style = req->style; + class->win_extra = req->win_extra; + class->client_ptr = req->client_ptr; } /* destroy a window class */ @@ -151,11 +195,14 @@ DECL_HANDLER(destroy_class) struct window_class *class = find_class( current->process, req->atom, req->instance ); if (!class) - set_error( STATUS_INVALID_HANDLE ); + set_win32_error( ERROR_CLASS_DOES_NOT_EXIST ); else if (class->count) set_win32_error( ERROR_CLASS_HAS_WINDOWS ); else - destroy_class( class ); + { + reply->client_ptr = class->client_ptr; + if (class != desktop_class) destroy_class( class ); + } } @@ -166,6 +213,12 @@ DECL_HANDLER(set_class_info) if (!class) return; + if (req->flags && class->process != current->process) + { + set_error( STATUS_ACCESS_DENIED ); + return; + } + if (req->extra_size > sizeof(req->extra_value) || req->extra_offset < -1 || req->extra_offset > class->nb_extra_bytes - (int)req->extra_size) @@ -173,6 +226,11 @@ DECL_HANDLER(set_class_info) set_win32_error( ERROR_INVALID_INDEX ); return; } + if ((req->flags & SET_CLASS_WINEXTRA) && (req->win_extra < 0 || req->win_extra > 4096)) + { + set_error( STATUS_INVALID_PARAMETER ); + return; + } if (req->extra_offset != -1) { memcpy( &reply->old_extra_value, class->extra_bytes + req->extra_offset, req->extra_size ); @@ -201,4 +259,3 @@ DECL_HANDLER(set_class_info) if (req->flags & SET_CLASS_EXTRA) memcpy( class->extra_bytes + req->extra_offset, &req->extra_value, req->extra_size ); } - diff --git a/server/protocol.def b/server/protocol.def index 16c6c50c6ef..f6e40eb29fe 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1781,9 +1781,10 @@ enum message_type user_handle_t owner; /* owner window */ atom_t atom; /* class atom */ void* instance; /* module instance */ - int extra; /* number of extra bytes */ @REPLY user_handle_t handle; /* created window */ + int extra; /* number of extra bytes */ + void* class_ptr; /* pointer to class in client address space */ @END @@ -2138,6 +2139,7 @@ enum message_type void* instance; /* module instance */ int extra; /* number of extra class bytes */ int win_extra; /* number of window extra bytes */ + void* client_ptr; /* pointer to class in client address space */ @END @@ -2145,6 +2147,8 @@ enum message_type @REQ(destroy_class) atom_t atom; /* class atom */ void* instance; /* module instance */ +@REPLY + void* client_ptr; /* pointer to class in client address space */ @END diff --git a/server/trace.c b/server/trace.c index 97ec3f57a7e..20697008f1b 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2096,13 +2096,14 @@ static void dump_create_window_request( const struct create_window_request *req fprintf( stderr, " parent=%p,", req->parent ); fprintf( stderr, " owner=%p,", req->owner ); fprintf( stderr, " atom=%04x,", req->atom ); - fprintf( stderr, " instance=%p,", req->instance ); - fprintf( stderr, " extra=%d", req->extra ); + fprintf( stderr, " instance=%p", req->instance ); } static void dump_create_window_reply( const struct create_window_reply *req ) { - fprintf( stderr, " handle=%p", req->handle ); + fprintf( stderr, " handle=%p,", req->handle ); + fprintf( stderr, " extra=%d,", req->extra ); + fprintf( stderr, " class_ptr=%p", req->class_ptr ); } static void dump_link_window_request( const struct link_window_request *req ) @@ -2511,7 +2512,8 @@ static void dump_create_class_request( const struct create_class_request *req ) fprintf( stderr, " style=%08x,", req->style ); fprintf( stderr, " instance=%p,", req->instance ); fprintf( stderr, " extra=%d,", req->extra ); - fprintf( stderr, " win_extra=%d", req->win_extra ); + fprintf( stderr, " win_extra=%d,", req->win_extra ); + fprintf( stderr, " client_ptr=%p", req->client_ptr ); } static void dump_destroy_class_request( const struct destroy_class_request *req ) @@ -2520,6 +2522,11 @@ static void dump_destroy_class_request( const struct destroy_class_request *req fprintf( stderr, " instance=%p", req->instance ); } +static void dump_destroy_class_reply( const struct destroy_class_reply *req ) +{ + fprintf( stderr, " client_ptr=%p", req->client_ptr ); +} + static void dump_set_class_info_request( const struct set_class_info_request *req ) { fprintf( stderr, " window=%p,", req->window ); @@ -2952,7 +2959,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)0, (dump_func)dump_get_next_hook_reply, (dump_func)0, - (dump_func)0, + (dump_func)dump_destroy_class_reply, (dump_func)dump_set_class_info_reply, (dump_func)dump_set_clipboard_info_reply, (dump_func)dump_open_token_reply, diff --git a/server/user.h b/server/user.h index 8c07b7f7977..62bc80d8946 100644 --- a/server/user.h +++ b/server/user.h @@ -78,8 +78,10 @@ extern struct window_class *get_window_class( user_handle_t window ); /* window class functions */ extern void destroy_process_classes( struct process *process ); -extern struct window_class *grab_class( struct process *process, atom_t atom, void *instance ); +extern struct window_class *grab_class( struct process *process, atom_t atom, + void *instance, int *extra_bytes ); extern void release_class( struct window_class *class ); extern atom_t get_class_atom( struct window_class *class ); +extern void *get_class_client_ptr( struct window_class *class ); #endif /* __WINE_SERVER_USER_H */ diff --git a/server/window.c b/server/window.c index d6a1b6f41cf..8550de11748 100644 --- a/server/window.c +++ b/server/window.c @@ -268,11 +268,12 @@ static void destroy_window( struct window *win ) } /* create a new window structure (note: the window is not linked in the window tree) */ -static struct window *create_window( struct window *parent, struct window *owner, atom_t atom, - void *instance, int extra_bytes ) +static struct window *create_window( struct window *parent, struct window *owner, + atom_t atom, void *instance ) { + int extra_bytes; struct window *win; - struct window_class *class = grab_class( current->process, atom, instance ); + struct window_class *class = grab_class( current->process, atom, instance, &extra_bytes ); if (!class) return NULL; @@ -474,25 +475,22 @@ struct window_class* get_window_class( user_handle_t window ) /* create a window */ DECL_HANDLER(create_window) { + struct window *win; + reply->handle = 0; - if (req->extra < 0 || req->extra > 4096) /* don't allow stupid values here */ - { - set_error( STATUS_INVALID_PARAMETER ); - return; - } if (!req->parent) /* return desktop window */ { if (!top_window) { - if (!(top_window = create_window( NULL, NULL, req->atom, req->instance, req->extra ))) return; + if (!(top_window = create_window( NULL, NULL, req->atom, req->instance ))) return; top_window->thread = NULL; /* no thread owns the desktop */ top_window->style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; } - reply->handle = top_window->handle; + win = top_window; } else { - struct window *win, *parent, *owner = NULL; + struct window *parent, *owner = NULL; if (!(parent = get_window( req->parent ))) return; if (req->owner && !(owner = get_window( req->owner ))) return; @@ -503,9 +501,11 @@ DECL_HANDLER(create_window) set_error( STATUS_ACCESS_DENIED ); return; } - if (!(win = create_window( parent, owner, req->atom, req->instance, req->extra ))) return; - reply->handle = win->handle; + if (!(win = create_window( parent, owner, req->atom, req->instance ))) return; } + reply->handle = win->handle; + reply->extra = win->nb_extra_bytes; + reply->class_ptr = get_class_client_ptr( win->class ); } diff --git a/windows/class.c b/windows/class.c index cd3261f6f99..19ae8069000 100644 --- a/windows/class.c +++ b/windows/class.c @@ -67,6 +67,7 @@ typedef struct tagCLASS } CLASS; static struct list class_list = LIST_INIT( class_list ); +static CLASS *desktop_class; static HMODULE user32_module; #define CLASS_OTHER_PROCESS ((CLASS *)1) @@ -293,37 +294,22 @@ static void CLASS_SetMenuNameW( CLASS *classPtr, LPCWSTR name ) * * Free a class structure. */ -static BOOL CLASS_FreeClass( CLASS *classPtr ) +static void CLASS_FreeClass( CLASS *classPtr ) { - BOOL ret; - TRACE("%p\n", classPtr); - SERVER_START_REQ( destroy_class ) - { - req->atom = classPtr->atomName; - req->instance = classPtr->hInstance; - ret = !wine_server_call_err( req ); - } - SERVER_END_REQ; + USER_Lock(); - if (ret) - { - list_remove( &classPtr->entry ); - - /* Delete the class */ - - if (classPtr->dce) DCE_FreeDCE( classPtr->dce ); - if (classPtr->hbrBackground > (HBRUSH)(COLOR_GRADIENTINACTIVECAPTION + 1)) - DeleteObject( classPtr->hbrBackground ); - GlobalDeleteAtom( classPtr->atomName ); - WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS ); - WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS ); - UnMapLS( classPtr->segMenuName ); - HeapFree( GetProcessHeap(), 0, classPtr->menuName ); - HeapFree( GetProcessHeap(), 0, classPtr ); - } - return ret; + list_remove( &classPtr->entry ); + if (classPtr->dce) DCE_FreeDCE( classPtr->dce ); + if (classPtr->hbrBackground > (HBRUSH)(COLOR_GRADIENTINACTIVECAPTION + 1)) + DeleteObject( classPtr->hbrBackground ); + WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS ); + WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS ); + UnMapLS( classPtr->segMenuName ); + HeapFree( GetProcessHeap(), 0, classPtr->menuName ); + HeapFree( GetProcessHeap(), 0, classPtr ); + USER_Unlock(); } @@ -341,7 +327,19 @@ void CLASS_FreeModuleClasses( HMODULE16 hModule ) { CLASS *class = LIST_ENTRY( ptr, CLASS, entry ); next = list_next( &class_list, ptr ); - if (class->hInstance == HINSTANCE_32(hModule)) CLASS_FreeClass( class ); + if (class->hInstance == HINSTANCE_32(hModule)) + { + BOOL ret; + + SERVER_START_REQ( destroy_class ) + { + req->atom = class->atomName; + req->instance = class->hInstance; + ret = !wine_server_call_err( req ); + } + SERVER_END_REQ; + if (ret) CLASS_FreeClass( class ); + } } USER_Unlock(); } @@ -357,6 +355,8 @@ static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance ) { struct list *ptr; + USER_Lock(); + LIST_FOR_EACH( ptr, &class_list ) { CLASS *class = LIST_ENTRY( ptr, CLASS, entry ); @@ -367,6 +367,7 @@ static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance ) return class; } } + USER_Unlock(); TRACE("0x%04x %p -> not found\n", atom, hinstance); return NULL; } @@ -376,6 +377,7 @@ static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance ) * CLASS_RegisterClass * * The real RegisterClass() functionality. + * The atom is deleted no matter what. */ static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance, BOOL local, DWORD style, INT classExtra, INT winExtra ) @@ -396,19 +398,25 @@ static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance, BOOL local, WARN("Win extra bytes %d is > 40\n", winExtra ); classPtr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLASS) + classExtra ); - if (!classPtr) return NULL; + if (!classPtr) + { + GlobalDeleteAtom( atom ); + return NULL; + } SERVER_START_REQ( create_class ) { - req->local = local; - req->atom = atom; - req->style = style; - req->instance = hInstance; - req->extra = classExtra; - req->win_extra = winExtra; + req->local = local; + req->atom = atom; + req->style = style; + req->instance = hInstance; + req->extra = classExtra; + req->win_extra = winExtra; + req->client_ptr = classPtr; ret = !wine_server_call_err( req ); } SERVER_END_REQ; + GlobalDeleteAtom( atom ); /* the server increased the atom ref count */ if (!ret) { HeapFree( GetProcessHeap(), 0, classPtr ); @@ -425,6 +433,7 @@ static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance, BOOL local, /* Other non-null values must be set by caller */ + USER_Lock(); if (local) list_add_head( &class_list, &classPtr->entry ); else list_add_tail( &class_list, &classPtr->entry ); return classPtr; @@ -437,7 +446,7 @@ static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance, BOOL local, * Register a builtin control class. * This allows having both ASCII and Unicode winprocs for the same class. */ -static ATOM register_builtin( const struct builtin_class_descr *descr ) +static CLASS *register_builtin( const struct builtin_class_descr *descr ) { ATOM atom; CLASS *classPtr; @@ -445,11 +454,7 @@ static ATOM register_builtin( const struct builtin_class_descr *descr ) if (!(atom = GlobalAddAtomA( descr->name ))) return 0; if (!(classPtr = CLASS_RegisterClass( atom, user32_module, FALSE, - descr->style, 0, descr->extra ))) - { - GlobalDeleteAtom( atom ); - return 0; - } + descr->style, 0, descr->extra ))) return 0; classPtr->hCursor = LoadCursorA( 0, (LPSTR)descr->cursor ); classPtr->hbrBackground = descr->brush; @@ -458,7 +463,8 @@ static ATOM register_builtin( const struct builtin_class_descr *descr ) WIN_PROC_32A, WIN_PROC_CLASS ); if (descr->procW) WINPROC_SetProc( &classPtr->winprocW, descr->procW, WIN_PROC_32W, WIN_PROC_CLASS ); - return atom; + release_class_ptr( classPtr ); + return classPtr; } @@ -481,11 +487,11 @@ void CLASS_RegisterBuiltinClasses( HMODULE user32 ) extern const struct builtin_class_descr STATIC_builtin_class; user32_module = user32; + desktop_class = register_builtin( &DESKTOP_builtin_class ); register_builtin( &BUTTON_builtin_class ); register_builtin( &COMBO_builtin_class ); register_builtin( &COMBOLBOX_builtin_class ); register_builtin( &DIALOG_builtin_class ); - register_builtin( &DESKTOP_builtin_class ); register_builtin( &EDIT_builtin_class ); register_builtin( &ICONTITLE_builtin_class ); register_builtin( &LISTBOX_builtin_class ); @@ -499,29 +505,24 @@ void CLASS_RegisterBuiltinClasses( HMODULE user32 ) /*********************************************************************** * CLASS_AddWindow * - * Add a new window using this class, and return the necessary - * information for creating the window. + * Add a new window using this class, and set the necessary + * information inside the window structure. */ -CLASS *CLASS_AddWindow( ATOM atom, HINSTANCE inst, WINDOWPROCTYPE type, - INT *winExtra, WNDPROC *winproc, DWORD *style, struct tagDCE **dce ) +void CLASS_AddWindow( CLASS *class, WND *win, WINDOWPROCTYPE type ) { - CLASS *class; - if (type == WIN_PROC_16) inst = HINSTANCE_32(GetExePtr(HINSTANCE_16(inst))); - - if (!(class = CLASS_FindClassByAtom( atom, inst ))) return NULL; + if (!class) class = desktop_class; if (type == WIN_PROC_32W) { - if (!(*winproc = class->winprocW)) *winproc = class->winprocA; + if (!(win->winproc = class->winprocW)) win->winproc = class->winprocA; } else { - if (!(*winproc = class->winprocA)) *winproc = class->winprocW; + if (!(win->winproc = class->winprocA)) win->winproc = class->winprocW; } - *winExtra = class->cbWndExtra; - *style = class->style; - *dce = class->dce; - return class; + win->class = class; + win->clsStyle = class->style; + win->dce = class->dce; } @@ -612,10 +613,7 @@ ATOM WINAPI RegisterClassEx16( const WNDCLASSEX16 *wc ) if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0; if (!(classPtr = CLASS_RegisterClass( atom, hInstance, !(wc->style & CS_GLOBALCLASS), wc->style, wc->cbClsExtra, wc->cbWndExtra ))) - { - GlobalDeleteAtom( atom ); return 0; - } TRACE("atom=%04x wndproc=%p hinst=%p bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n", atom, wc->lpfnWndProc, hInstance, @@ -630,6 +628,7 @@ ATOM WINAPI RegisterClassEx16( const WNDCLASSEX16 *wc ) WINPROC_SetProc( &classPtr->winprocA, (WNDPROC)wc->lpfnWndProc, WIN_PROC_16, WIN_PROC_CLASS ); CLASS_SetMenuNameA( classPtr, MapSL(wc->lpszMenuName) ); + release_class_ptr( classPtr ); return atom; } @@ -655,10 +654,7 @@ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc ) if (!(classPtr = CLASS_RegisterClass( atom, instance, !(wc->style & CS_GLOBALCLASS), wc->style, wc->cbClsExtra, wc->cbWndExtra ))) - { - GlobalDeleteAtom( atom ); return 0; - } TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n", atom, wc->lpfnWndProc, instance, wc->hbrBackground, @@ -670,6 +666,7 @@ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc ) classPtr->hbrBackground = wc->hbrBackground; WINPROC_SetProc( &classPtr->winprocA, wc->lpfnWndProc, WIN_PROC_32A, WIN_PROC_CLASS ); CLASS_SetMenuNameA( classPtr, wc->lpszMenuName ); + release_class_ptr( classPtr ); return atom; } @@ -695,10 +692,7 @@ ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc ) if (!(classPtr = CLASS_RegisterClass( atom, instance, !(wc->style & CS_GLOBALCLASS), wc->style, wc->cbClsExtra, wc->cbWndExtra ))) - { - GlobalDeleteAtom( atom ); return 0; - } TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n", atom, wc->lpfnWndProc, instance, wc->hbrBackground, @@ -710,6 +704,7 @@ ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc ) classPtr->hbrBackground = wc->hbrBackground; WINPROC_SetProc( &classPtr->winprocW, wc->lpfnWndProc, WIN_PROC_32W, WIN_PROC_CLASS ); CLASS_SetMenuNameW( classPtr, wc->lpszMenuName ); + release_class_ptr( classPtr ); return atom; } @@ -737,22 +732,29 @@ BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance ) */ BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance ) { - CLASS *classPtr; - BOOL ret = FALSE; + CLASS *classPtr = NULL; ATOM atom = HIWORD(className) ? GlobalFindAtomW( className ) : LOWORD(className); TRACE("%s %p %x\n",debugstr_w(className), hInstance, atom); + if (!atom) + { + SetLastError( ERROR_CLASS_DOES_NOT_EXIST ); + return FALSE; + } + if (!hInstance) hInstance = GetModuleHandleW( NULL ); - USER_Lock(); - if (atom && (classPtr = CLASS_FindClassByAtom( atom, hInstance ))) + SERVER_START_REQ( destroy_class ) { - ret = CLASS_FreeClass( classPtr ); + req->atom = atom; + req->instance = hInstance; + if (!wine_server_call_err( req )) classPtr = reply->client_ptr; } - else SetLastError( ERROR_CLASS_DOES_NOT_EXIST ); - USER_Unlock(); - return ret; + SERVER_END_REQ; + + if (classPtr) CLASS_FreeClass( classPtr ); + return (classPtr != NULL); } @@ -1286,6 +1288,7 @@ BOOL16 WINAPI GetClassInfoEx16( HINSTANCE16 hInst16, SEGPTR name, WNDCLASSEX16 * wc->lpszClassName = (SEGPTR)0; wc->lpszMenuName = CLASS_GetMenuName16( classPtr ); wc->lpszClassName = name; + release_class_ptr( classPtr ); /* We must return the atom of the class here instead of just TRUE. */ return atom; @@ -1320,6 +1323,7 @@ BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name, WNDCLASSEXA *wc ) wc->hbrBackground = (HBRUSH)classPtr->hbrBackground; wc->lpszMenuName = CLASS_GetMenuNameA( classPtr ); wc->lpszClassName = name; + release_class_ptr( classPtr ); /* We must return the atom of the class here instead of just TRUE. */ return atom; @@ -1354,6 +1358,7 @@ BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSEXW *wc wc->hbrBackground = (HBRUSH)classPtr->hbrBackground; wc->lpszMenuName = CLASS_GetMenuNameW( classPtr ); wc->lpszClassName = name; + release_class_ptr( classPtr ); /* We must return the atom of the class here instead of just TRUE. */ return atom; diff --git a/windows/win.c b/windows/win.c index ce3074da59b..9d0f8941899 100644 --- a/windows/win.c +++ b/windows/win.c @@ -65,23 +65,13 @@ static void *user_handles[NB_USER_HANDLES]; static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, HINSTANCE instance, WINDOWPROCTYPE type ) { - BOOL res; WORD index; WND *win; - DCE *dce; - INT extra_bytes; - DWORD clsStyle; - WNDPROC winproc; - struct tagCLASS *class; + struct tagCLASS *class = NULL; user_handle_t handle = 0; + int extra_bytes = 0; - if (!(class = CLASS_AddWindow( atom, instance, type, &extra_bytes, &winproc, &clsStyle, &dce ))) - return NULL; - - if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) ))) - return NULL; - - USER_Lock(); + if (type == WIN_PROC_16) instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance))); SERVER_START_REQ( create_window ) { @@ -89,29 +79,44 @@ static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, req->owner = owner; req->atom = atom; req->instance = instance; - req->extra = extra_bytes; - if ((res = !wine_server_call_err( req ))) handle = reply->handle; + if (!wine_server_call_err( req )) + { + handle = reply->handle; + extra_bytes = reply->extra; + class = reply->class_ptr; + } } SERVER_END_REQ; - if (!res) + if (!handle) { - USER_Unlock(); - HeapFree( GetProcessHeap(), 0, win ); + WARN( "error %ld creating window\n", GetLastError() ); return NULL; } + + if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) ))) + { + SERVER_START_REQ( destroy_window ) + { + req->handle = handle; + wine_server_call( req ); + } + SERVER_END_REQ; + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return NULL; + } + + USER_Lock(); + index = LOWORD(handle) - FIRST_USER_HANDLE; assert( index < NB_USER_HANDLES ); user_handles[index] = win; win->hwndSelf = handle; win->dwMagic = WND_MAGIC; win->irefCount = 1; - win->class = class; - win->winproc = winproc; - win->dce = dce; - win->clsStyle = clsStyle; win->cbWndExtra = extra_bytes; memset( win->wExtra, 0, extra_bytes ); + CLASS_AddWindow( class, win, type ); return win; }