Store a pointer to the client-side class structure in the server and
authorAlexandre Julliard <julliard@winehq.org>
Thu, 11 Dec 2003 05:34:53 +0000 (05:34 +0000)
committerAlexandre Julliard <julliard@winehq.org>
Thu, 11 Dec 2003 05:34:53 +0000 (05:34 +0000)
return it on create_window and destroy_class.
Only create a single instance of the desktop class for the whole
session.
Added some missing locking in the client-side class management.

dlls/user/winproc.h
include/wine/server_protocol.h
server/class.c
server/protocol.def
server/trace.c
server/user.h
server/window.c
windows/class.c
windows/win.c

index 883a8fd260ea4647d7c89de677f0807f9db2408f..d68f3185013b5d26eaf9b04c4af0f736031076ce 100644 (file)
@@ -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 */
index 116be53755f6cdfe438e82b7de07b2300fa141f3..eb10a862798e8da1b7e5e0b45c5538d2e9797e09 100644 (file)
@@ -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 */
index 13d9d5cbf3b93ee964198dd78bc37af7890319a8..5f034d9b5b5a51e34b6a956d3abf669f86af15c3 100644 (file)
@@ -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 );
 }
-
index 16c6c50c6effa4d768834778508b5612451c5206..f6e40eb29fe7e8ae9c99556e29d95d39cc87d825 100644 (file)
@@ -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
 
 
index 97ec3f57a7ea7c9c0c1ba0d11b67f6e8efda57fe..20697008f1b494c4db145c842e9e7f7241b6ef4d 100644 (file)
@@ -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,
index 8c07b7f7977ad0dca0aea8fbab0b56b5d24de9e2..62bc80d8946e388a4c7a88e7d7ba4c02cd31006d 100644 (file)
@@ -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 */
index d6a1b6f41cf792bc433296e8bf720859f52bd82c..8550de11748fbe909c26f9681b7893ca6e35337c 100644 (file)
@@ -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 );
 }
 
 
index cd3261f6f99e810d7f383c948726a6d8c14ec698..19ae80690006784c2265dc0cfe13adcc4e8c17f0 100644 (file)
@@ -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;
index ce3074da59bc0d8645dcc83ff75956ab7e37d731..9d0f8941899ae378b05752889dd08307da2137a0 100644 (file)
@@ -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;
 }