We need to at least refresh the window menu in ChildActivate, so for
[wine] / windows / class.c
1 /*
2  * Window classes functions
3  *
4  * Copyright 1993, 1996, 2003 Alexandre Julliard
5  * Copyright 1998 Juergen Schmied (jsch)
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <assert.h>
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "wine/winbase16.h"
31 #include "winerror.h"
32 #include "windef.h"
33 #include "winbase.h"
34 #include "wingdi.h"
35 #include "wine/winuser16.h"
36 #include "wownt32.h"
37 #include "wine/unicode.h"
38 #include "win.h"
39 #include "user.h"
40 #include "controls.h"
41 #include "dce.h"
42 #include "winproc.h"
43 #include "wine/server.h"
44 #include "wine/list.h"
45 #include "wine/debug.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(class);
48
49 typedef struct tagCLASS
50 {
51     struct list      entry;         /* Entry in class list */
52     UINT             style;         /* Class style */
53     BOOL             local;         /* Local class? */
54     WNDPROC          winprocA;      /* Window procedure (ASCII) */
55     WNDPROC          winprocW;      /* Window procedure (Unicode) */
56     INT              cbClsExtra;    /* Class extra bytes */
57     INT              cbWndExtra;    /* Window extra bytes */
58     LPWSTR           menuName;      /* Default menu name (Unicode followed by ASCII) */
59     SEGPTR           segMenuName;   /* Default menu name as SEGPTR */
60     struct tagDCE   *dce;           /* Class DCE (if CS_CLASSDC) */
61     HINSTANCE        hInstance;     /* Module that created the task */
62     HICON            hIcon;         /* Default icon */
63     HICON            hIconSm;       /* Default small icon */
64     HCURSOR          hCursor;       /* Default cursor */
65     HBRUSH           hbrBackground; /* Default background */
66     ATOM             atomName;      /* Name of the class */
67 } CLASS;
68
69 static struct list class_list = LIST_INIT( class_list );
70 static CLASS *desktop_class;
71
72 #define CLASS_OTHER_PROCESS ((CLASS *)1)
73
74 /***********************************************************************
75  *           get_class_ptr
76  */
77 static CLASS *get_class_ptr( HWND hwnd, BOOL write_access )
78 {
79     WND *ptr = WIN_GetPtr( hwnd );
80
81     if (ptr)
82     {
83         if (ptr != WND_OTHER_PROCESS) return ptr->class;
84         if (write_access && IsWindow( hwnd )) /* check other processes */
85         {
86             /* modifying classes in other processes is not allowed */
87             SetLastError( ERROR_ACCESS_DENIED );
88             return NULL;
89         }
90         return CLASS_OTHER_PROCESS;
91     }
92     SetLastError( ERROR_INVALID_WINDOW_HANDLE );
93     return NULL;
94 }
95
96
97 /***********************************************************************
98  *           release_class_ptr
99  */
100 inline static void release_class_ptr( CLASS *ptr )
101 {
102     USER_Unlock();
103 }
104
105
106 /***********************************************************************
107  *           set_server_info
108  *
109  * Set class info with the wine server.
110  */
111 static BOOL set_server_info( HWND hwnd, INT offset, LONG newval )
112 {
113     BOOL ret;
114
115     SERVER_START_REQ( set_class_info )
116     {
117         req->window = hwnd;
118         req->extra_offset = -1;
119         switch(offset)
120         {
121         case GCW_ATOM:
122             req->flags = SET_CLASS_ATOM;
123             req->atom = newval;
124         case GCL_STYLE:
125             req->flags = SET_CLASS_STYLE;
126             req->style = newval;
127             break;
128         case GCL_CBWNDEXTRA:
129             req->flags = SET_CLASS_WINEXTRA;
130             req->win_extra = newval;
131             break;
132         case GCL_HMODULE:
133             req->flags = SET_CLASS_INSTANCE;
134             req->instance = (void *)newval;
135             break;
136         default:
137             assert( offset >= 0 );
138             req->flags = SET_CLASS_EXTRA;
139             req->extra_offset = offset;
140             req->extra_size = sizeof(newval);
141             memcpy( &req->extra_value, &newval, sizeof(newval) );
142             break;
143         }
144         ret = !wine_server_call_err( req );
145     }
146     SERVER_END_REQ;
147     return ret;
148 }
149
150
151 /***********************************************************************
152  *           CLASS_GetProc
153  *
154  * Get the class winproc for a given proc type
155  */
156 static WNDPROC16 CLASS_GetProc( CLASS *classPtr, WINDOWPROCTYPE type )
157 {
158     WNDPROC proc = classPtr->winprocA;
159
160     if (classPtr->winprocW)
161     {
162         /* if we have a Unicode proc, use it if we have no ASCII proc
163          * or if we have both and Unicode was requested
164          */
165         if (!proc || type == WIN_PROC_32W) proc = classPtr->winprocW;
166     }
167     return WINPROC_GetProc( proc, type );
168 }
169
170
171 /***********************************************************************
172  *           CLASS_SetProc
173  *
174  * Set the class winproc for a given proc type.
175  * Returns the previous window proc.
176  */
177 static WNDPROC16 CLASS_SetProc( CLASS *classPtr, WNDPROC newproc, WINDOWPROCTYPE type )
178 {
179     WNDPROC *proc = &classPtr->winprocA;
180     WNDPROC16 ret;
181
182     if (classPtr->winprocW)
183     {
184         /* if we have a Unicode proc, use it if we have no ASCII proc
185          * or if we have both and Unicode was requested
186          */
187         if (!*proc || type == WIN_PROC_32W) proc = &classPtr->winprocW;
188     }
189     ret = WINPROC_GetProc( *proc, type );
190     WINPROC_SetProc( proc, newproc, type, WIN_PROC_CLASS );
191     /* now free the one that we didn't set */
192     if (classPtr->winprocA && classPtr->winprocW)
193     {
194         if (proc == &classPtr->winprocA)
195         {
196             WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
197             classPtr->winprocW = 0;
198         }
199         else
200         {
201             WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
202             classPtr->winprocA = 0;
203         }
204     }
205     return ret;
206 }
207
208
209 /***********************************************************************
210  *           CLASS_GetMenuNameA
211  *
212  * Get the menu name as a ASCII string.
213  */
214 inline static LPSTR CLASS_GetMenuNameA( CLASS *classPtr )
215 {
216     if (!HIWORD(classPtr->menuName)) return (LPSTR)classPtr->menuName;
217     return (LPSTR)(classPtr->menuName + strlenW(classPtr->menuName) + 1);
218 }
219
220
221 /***********************************************************************
222  *           CLASS_GetMenuName16
223  *
224  * Get the menu name as a SEGPTR.
225  */
226 inline static SEGPTR CLASS_GetMenuName16( CLASS *classPtr )
227 {
228     if (!HIWORD(classPtr->menuName)) return (SEGPTR)classPtr->menuName;
229     if (!classPtr->segMenuName)
230         classPtr->segMenuName = MapLS( CLASS_GetMenuNameA(classPtr) );
231     return classPtr->segMenuName;
232 }
233
234
235 /***********************************************************************
236  *           CLASS_GetMenuNameW
237  *
238  * Get the menu name as a Unicode string.
239  */
240 inline static LPWSTR CLASS_GetMenuNameW( CLASS *classPtr )
241 {
242     return classPtr->menuName;
243 }
244
245
246 /***********************************************************************
247  *           CLASS_SetMenuNameA
248  *
249  * Set the menu name in a class structure by copying the string.
250  */
251 static void CLASS_SetMenuNameA( CLASS *classPtr, LPCSTR name )
252 {
253     UnMapLS( classPtr->segMenuName );
254     classPtr->segMenuName = 0;
255     if (HIWORD(classPtr->menuName)) HeapFree( GetProcessHeap(), 0, classPtr->menuName );
256     if (HIWORD(name))
257     {
258         DWORD lenA = strlen(name) + 1;
259         DWORD lenW = MultiByteToWideChar( CP_ACP, 0, name, lenA, NULL, 0 );
260         classPtr->menuName = HeapAlloc( GetProcessHeap(), 0, lenA + lenW*sizeof(WCHAR) );
261         MultiByteToWideChar( CP_ACP, 0, name, lenA, classPtr->menuName, lenW );
262         memcpy( classPtr->menuName + lenW, name, lenA );
263     }
264     else classPtr->menuName = (LPWSTR)name;
265 }
266
267
268 /***********************************************************************
269  *           CLASS_SetMenuNameW
270  *
271  * Set the menu name in a class structure by copying the string.
272  */
273 static void CLASS_SetMenuNameW( CLASS *classPtr, LPCWSTR name )
274 {
275     UnMapLS( classPtr->segMenuName );
276     classPtr->segMenuName = 0;
277     if (HIWORD(classPtr->menuName)) HeapFree( GetProcessHeap(), 0, classPtr->menuName );
278     if (HIWORD(name))
279     {
280         DWORD lenW = strlenW(name) + 1;
281         DWORD lenA = WideCharToMultiByte( CP_ACP, 0, name, lenW, NULL, 0, NULL, NULL );
282         classPtr->menuName = HeapAlloc( GetProcessHeap(), 0, lenA + lenW*sizeof(WCHAR) );
283         memcpy( classPtr->menuName, name, lenW*sizeof(WCHAR) );
284         WideCharToMultiByte( CP_ACP, 0, name, lenW,
285                              (char *)(classPtr->menuName + lenW), lenA, NULL, NULL );
286     }
287     else classPtr->menuName = (LPWSTR)name;
288 }
289
290
291 /***********************************************************************
292  *           CLASS_FreeClass
293  *
294  * Free a class structure.
295  */
296 static void CLASS_FreeClass( CLASS *classPtr )
297 {
298     TRACE("%p\n", classPtr);
299
300     USER_Lock();
301
302     list_remove( &classPtr->entry );
303     if (classPtr->dce) DCE_FreeDCE( classPtr->dce );
304     if (classPtr->hbrBackground > (HBRUSH)(COLOR_GRADIENTINACTIVECAPTION + 1))
305         DeleteObject( classPtr->hbrBackground );
306     WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
307     WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
308     UnMapLS( classPtr->segMenuName );
309     HeapFree( GetProcessHeap(), 0, classPtr->menuName );
310     HeapFree( GetProcessHeap(), 0, classPtr );
311     USER_Unlock();
312 }
313
314
315 /***********************************************************************
316  *           CLASS_FreeModuleClasses
317  */
318 void CLASS_FreeModuleClasses( HMODULE16 hModule )
319 {
320     struct list *ptr, *next;
321
322     TRACE("0x%08x\n", hModule);
323
324     USER_Lock();
325     for (ptr = list_head( &class_list ); ptr; ptr = next)
326     {
327         CLASS *class = LIST_ENTRY( ptr, CLASS, entry );
328         next = list_next( &class_list, ptr );
329         if (class->hInstance == HINSTANCE_32(hModule))
330         {
331             BOOL ret;
332
333             SERVER_START_REQ( destroy_class )
334             {
335                 req->atom = class->atomName;
336                 req->instance = class->hInstance;
337                 ret = !wine_server_call_err( req );
338             }
339             SERVER_END_REQ;
340             if (ret) CLASS_FreeClass( class );
341         }
342     }
343     USER_Unlock();
344 }
345
346
347 /***********************************************************************
348  *           CLASS_FindClassByAtom
349  *
350  * Return a pointer to the class.
351  * hinstance has been normalized by the caller.
352  */
353 static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance )
354 {
355     struct list *ptr;
356
357     USER_Lock();
358
359     LIST_FOR_EACH( ptr, &class_list )
360     {
361         CLASS *class = LIST_ENTRY( ptr, CLASS, entry );
362         if (class->atomName != atom) continue;
363         if (!hinstance || !class->local || class->hInstance == hinstance)
364         {
365             TRACE("0x%04x %p -> %p\n", atom, hinstance, class);
366             return class;
367         }
368     }
369     USER_Unlock();
370     TRACE("0x%04x %p -> not found\n", atom, hinstance);
371     return NULL;
372 }
373
374
375 /***********************************************************************
376  *           CLASS_RegisterClass
377  *
378  * The real RegisterClass() functionality.
379  * The atom is deleted no matter what.
380  */
381 static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance, BOOL local,
382                                    DWORD style, INT classExtra, INT winExtra )
383 {
384     CLASS *classPtr;
385     BOOL ret;
386
387     TRACE("atom=0x%x hinst=%p style=0x%lx clExtr=0x%x winExtr=0x%x\n",
388           atom, hInstance, style, classExtra, winExtra );
389
390     /* Fix the extra bytes value */
391
392     if (classExtra < 0) classExtra = 0;
393     else if (classExtra > 40)  /* Extra bytes are limited to 40 in Win32 */
394         WARN("Class extra bytes %d is > 40\n", classExtra);
395     if (winExtra < 0) winExtra = 0;
396     else if (winExtra > 40)    /* Extra bytes are limited to 40 in Win32 */
397         WARN("Win extra bytes %d is > 40\n", winExtra );
398
399     classPtr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLASS) + classExtra );
400     if (!classPtr)
401     {
402         GlobalDeleteAtom( atom );
403         return NULL;
404     }
405
406     SERVER_START_REQ( create_class )
407     {
408         req->local      = local;
409         req->atom       = atom;
410         req->style      = style;
411         req->instance   = hInstance;
412         req->extra      = classExtra;
413         req->win_extra  = winExtra;
414         req->client_ptr = classPtr;
415         ret = !wine_server_call_err( req );
416     }
417     SERVER_END_REQ;
418     GlobalDeleteAtom( atom );  /* the server increased the atom ref count */
419     if (!ret)
420     {
421         HeapFree( GetProcessHeap(), 0, classPtr );
422         return NULL;
423     }
424
425     classPtr->style       = style;
426     classPtr->local       = local;
427     classPtr->cbWndExtra  = winExtra;
428     classPtr->cbClsExtra  = classExtra;
429     classPtr->hInstance   = hInstance;
430     classPtr->atomName    = atom;
431     classPtr->dce         = (style & CS_CLASSDC) ? DCE_AllocDCE( 0, DCE_CLASS_DC ) : NULL;
432
433     /* Other non-null values must be set by caller */
434
435     USER_Lock();
436     if (local) list_add_head( &class_list, &classPtr->entry );
437     else list_add_tail( &class_list, &classPtr->entry );
438     return classPtr;
439 }
440
441
442 /***********************************************************************
443  *           register_builtin
444  *
445  * Register a builtin control class.
446  * This allows having both ASCII and Unicode winprocs for the same class.
447  */
448 static CLASS *register_builtin( const struct builtin_class_descr *descr )
449 {
450     ATOM atom;
451     CLASS *classPtr;
452
453     if (!(atom = GlobalAddAtomA( descr->name ))) return 0;
454
455     if (!(classPtr = CLASS_RegisterClass( atom, user32_module, FALSE,
456                                           descr->style, 0, descr->extra ))) return 0;
457
458     classPtr->hCursor       = LoadCursorA( 0, (LPSTR)descr->cursor );
459     classPtr->hbrBackground = descr->brush;
460
461     if (descr->procA) WINPROC_SetProc( &classPtr->winprocA, descr->procA,
462                                        WIN_PROC_32A, WIN_PROC_CLASS );
463     if (descr->procW) WINPROC_SetProc( &classPtr->winprocW, descr->procW,
464                                        WIN_PROC_32W, WIN_PROC_CLASS );
465     release_class_ptr( classPtr );
466     return classPtr;
467 }
468
469
470 /***********************************************************************
471  *           CLASS_RegisterBuiltinClasses
472  */
473 void CLASS_RegisterBuiltinClasses(void)
474 {
475     extern const struct builtin_class_descr BUTTON_builtin_class;
476     extern const struct builtin_class_descr COMBO_builtin_class;
477     extern const struct builtin_class_descr COMBOLBOX_builtin_class;
478     extern const struct builtin_class_descr DIALOG_builtin_class;
479     extern const struct builtin_class_descr DESKTOP_builtin_class;
480     extern const struct builtin_class_descr EDIT_builtin_class;
481     extern const struct builtin_class_descr ICONTITLE_builtin_class;
482     extern const struct builtin_class_descr LISTBOX_builtin_class;
483     extern const struct builtin_class_descr MDICLIENT_builtin_class;
484     extern const struct builtin_class_descr MENU_builtin_class;
485     extern const struct builtin_class_descr SCROLL_builtin_class;
486     extern const struct builtin_class_descr STATIC_builtin_class;
487
488     desktop_class = register_builtin( &DESKTOP_builtin_class );
489     register_builtin( &BUTTON_builtin_class );
490     register_builtin( &COMBO_builtin_class );
491     register_builtin( &COMBOLBOX_builtin_class );
492     register_builtin( &DIALOG_builtin_class );
493     register_builtin( &EDIT_builtin_class );
494     register_builtin( &ICONTITLE_builtin_class );
495     register_builtin( &LISTBOX_builtin_class );
496     register_builtin( &MDICLIENT_builtin_class );
497     register_builtin( &MENU_builtin_class );
498     register_builtin( &SCROLL_builtin_class );
499     register_builtin( &STATIC_builtin_class );
500 }
501
502
503 /***********************************************************************
504  *           CLASS_AddWindow
505  *
506  * Add a new window using this class, and set the necessary
507  * information inside the window structure.
508  */
509 void CLASS_AddWindow( CLASS *class, WND *win, WINDOWPROCTYPE type )
510 {
511     if (!class) class = desktop_class;
512
513     if (type == WIN_PROC_32W)
514     {
515         if (!(win->winproc = class->winprocW)) win->winproc = class->winprocA;
516     }
517     else
518     {
519         if (!(win->winproc = class->winprocA)) win->winproc = class->winprocW;
520     }
521     win->class    = class;
522     win->clsStyle = class->style;
523     win->dce      = class->dce;
524 }
525
526
527 /***********************************************************************
528  *              RegisterClass (USER.57)
529  */
530 ATOM WINAPI RegisterClass16( const WNDCLASS16 *wc )
531 {
532     WNDCLASSEX16 wcex;
533
534     wcex.cbSize        = sizeof(wcex);
535     wcex.style         = wc->style;
536     wcex.lpfnWndProc   = wc->lpfnWndProc;
537     wcex.cbClsExtra    = wc->cbClsExtra;
538     wcex.cbWndExtra    = wc->cbWndExtra;
539     wcex.hInstance     = wc->hInstance;
540     wcex.hIcon         = wc->hIcon;
541     wcex.hCursor       = wc->hCursor;
542     wcex.hbrBackground = wc->hbrBackground;
543     wcex.lpszMenuName  = wc->lpszMenuName;
544     wcex.lpszClassName = wc->lpszClassName;
545     wcex.hIconSm       = 0;
546     return RegisterClassEx16( &wcex );
547 }
548
549
550 /***********************************************************************
551  *              RegisterClassA (USER32.@)
552  * RETURNS
553  *      >0: Unique identifier
554  *      0: Failure
555  */
556 ATOM WINAPI RegisterClassA( const WNDCLASSA* wc ) /* [in] Address of structure with class data */
557 {
558     WNDCLASSEXA wcex;
559
560     wcex.cbSize        = sizeof(wcex);
561     wcex.style         = wc->style;
562     wcex.lpfnWndProc   = wc->lpfnWndProc;
563     wcex.cbClsExtra    = wc->cbClsExtra;
564     wcex.cbWndExtra    = wc->cbWndExtra;
565     wcex.hInstance     = wc->hInstance;
566     wcex.hIcon         = wc->hIcon;
567     wcex.hCursor       = wc->hCursor;
568     wcex.hbrBackground = wc->hbrBackground;
569     wcex.lpszMenuName  = wc->lpszMenuName;
570     wcex.lpszClassName = wc->lpszClassName;
571     wcex.hIconSm       = 0;
572     return RegisterClassExA( &wcex );
573 }
574
575
576 /***********************************************************************
577  *              RegisterClassW (USER32.@)
578  */
579 ATOM WINAPI RegisterClassW( const WNDCLASSW* wc )
580 {
581     WNDCLASSEXW wcex;
582
583     wcex.cbSize        = sizeof(wcex);
584     wcex.style         = wc->style;
585     wcex.lpfnWndProc   = wc->lpfnWndProc;
586     wcex.cbClsExtra    = wc->cbClsExtra;
587     wcex.cbWndExtra    = wc->cbWndExtra;
588     wcex.hInstance     = wc->hInstance;
589     wcex.hIcon         = wc->hIcon;
590     wcex.hCursor       = wc->hCursor;
591     wcex.hbrBackground = wc->hbrBackground;
592     wcex.lpszMenuName  = wc->lpszMenuName;
593     wcex.lpszClassName = wc->lpszClassName;
594     wcex.hIconSm       = 0;
595     return RegisterClassExW( &wcex );
596 }
597
598
599 /***********************************************************************
600  *              RegisterClassEx (USER.397)
601  */
602 ATOM WINAPI RegisterClassEx16( const WNDCLASSEX16 *wc )
603 {
604     ATOM atom;
605     CLASS *classPtr;
606     HINSTANCE hInstance;
607
608     if (!(hInstance = HINSTANCE_32(GetExePtr(wc->hInstance))))
609         hInstance = HINSTANCE_32(GetModuleHandle16(NULL));
610
611     if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0;
612     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, !(wc->style & CS_GLOBALCLASS),
613                                           wc->style, wc->cbClsExtra, wc->cbWndExtra )))
614         return 0;
615
616     TRACE("atom=%04x wndproc=%p hinst=%p bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
617           atom, wc->lpfnWndProc, hInstance,
618           wc->hbrBackground, wc->style, wc->cbClsExtra,
619           wc->cbWndExtra, classPtr );
620
621     classPtr->hIcon         = HICON_32(wc->hIcon);
622     classPtr->hIconSm       = HICON_32(wc->hIconSm);
623     classPtr->hCursor       = HCURSOR_32(wc->hCursor);
624     classPtr->hbrBackground = HBRUSH_32(wc->hbrBackground);
625
626     WINPROC_SetProc( &classPtr->winprocA, (WNDPROC)wc->lpfnWndProc,
627                      WIN_PROC_16, WIN_PROC_CLASS );
628     CLASS_SetMenuNameA( classPtr, MapSL(wc->lpszMenuName) );
629     release_class_ptr( classPtr );
630     return atom;
631 }
632
633
634 /***********************************************************************
635  *              RegisterClassExA (USER32.@)
636  */
637 ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
638 {
639     ATOM atom;
640     CLASS *classPtr;
641     HINSTANCE instance;
642
643     if (wc->hInstance == user32_module)
644     {
645         /* we can't register a class for user32 */
646         SetLastError( ERROR_INVALID_PARAMETER );
647         return 0;
648     }
649     if (!(instance = wc->hInstance)) instance = GetModuleHandleW( NULL );
650
651     if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
652
653     if (!(classPtr = CLASS_RegisterClass( atom, instance, !(wc->style & CS_GLOBALCLASS),
654                                           wc->style, wc->cbClsExtra, wc->cbWndExtra )))
655         return 0;
656
657     TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
658           atom, wc->lpfnWndProc, instance, wc->hbrBackground,
659           wc->style, wc->cbClsExtra, wc->cbWndExtra, classPtr );
660
661     classPtr->hIcon         = wc->hIcon;
662     classPtr->hIconSm       = wc->hIconSm;
663     classPtr->hCursor       = wc->hCursor;
664     classPtr->hbrBackground = wc->hbrBackground;
665     WINPROC_SetProc( &classPtr->winprocA, wc->lpfnWndProc, WIN_PROC_32A, WIN_PROC_CLASS );
666     CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
667     release_class_ptr( classPtr );
668     return atom;
669 }
670
671
672 /***********************************************************************
673  *              RegisterClassExW (USER32.@)
674  */
675 ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
676 {
677     ATOM atom;
678     CLASS *classPtr;
679     HINSTANCE instance;
680
681     if (wc->hInstance == user32_module)
682     {
683         /* we can't register a class for user32 */
684         SetLastError( ERROR_INVALID_PARAMETER );
685         return 0;
686     }
687     if (!(instance = wc->hInstance)) instance = GetModuleHandleW( NULL );
688
689     if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
690
691     if (!(classPtr = CLASS_RegisterClass( atom, instance, !(wc->style & CS_GLOBALCLASS),
692                                           wc->style, wc->cbClsExtra, wc->cbWndExtra )))
693         return 0;
694
695     TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
696           atom, wc->lpfnWndProc, instance, wc->hbrBackground,
697           wc->style, wc->cbClsExtra, wc->cbWndExtra, classPtr );
698
699     classPtr->hIcon         = wc->hIcon;
700     classPtr->hIconSm       = wc->hIconSm;
701     classPtr->hCursor       = wc->hCursor;
702     classPtr->hbrBackground = wc->hbrBackground;
703     WINPROC_SetProc( &classPtr->winprocW, wc->lpfnWndProc, WIN_PROC_32W, WIN_PROC_CLASS );
704     CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
705     release_class_ptr( classPtr );
706     return atom;
707 }
708
709
710 /***********************************************************************
711  *              UnregisterClass (USER.403)
712  */
713 BOOL16 WINAPI UnregisterClass16( LPCSTR className, HINSTANCE16 hInstance )
714 {
715     if (hInstance == GetModuleHandle16("user")) hInstance = 0;
716     return UnregisterClassA( className, HINSTANCE_32(GetExePtr( hInstance )) );
717 }
718
719 /***********************************************************************
720  *              UnregisterClassA (USER32.@)
721  */
722 BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance )
723 {
724     ATOM atom = HIWORD(className) ? GlobalFindAtomA( className ) : LOWORD(className);
725     return UnregisterClassW( MAKEINTATOMW(atom), hInstance );
726 }
727
728 /***********************************************************************
729  *              UnregisterClassW (USER32.@)
730  */
731 BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance )
732 {
733     CLASS *classPtr = NULL;
734     ATOM atom = HIWORD(className) ? GlobalFindAtomW( className ) : LOWORD(className);
735
736     TRACE("%s %p %x\n",debugstr_w(className), hInstance, atom);
737
738     if (!atom)
739     {
740         SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
741         return FALSE;
742     }
743
744     if (!hInstance) hInstance = GetModuleHandleW( NULL );
745
746     SERVER_START_REQ( destroy_class )
747     {
748         req->atom = atom;
749         req->instance = hInstance;
750         if (!wine_server_call_err( req )) classPtr = reply->client_ptr;
751     }
752     SERVER_END_REQ;
753
754     if (classPtr) CLASS_FreeClass( classPtr );
755     return (classPtr != NULL);
756 }
757
758
759 /***********************************************************************
760  *              GetClassWord (USER32.@)
761  */
762 WORD WINAPI GetClassWord( HWND hwnd, INT offset )
763 {
764     CLASS *class;
765     WORD retvalue = 0;
766
767     if (offset < 0) return GetClassLongA( hwnd, offset );
768
769     TRACE("%p %x\n",hwnd, offset);
770
771     if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
772
773     if (class == CLASS_OTHER_PROCESS)
774     {
775         SERVER_START_REQ( set_class_info )
776         {
777             req->window = hwnd;
778             req->flags = 0;
779             req->extra_offset = offset;
780             req->extra_size = sizeof(retvalue);
781             if (!wine_server_call_err( req ))
782                 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
783         }
784         SERVER_END_REQ;
785         return retvalue;
786     }
787
788     if (offset <= class->cbClsExtra - sizeof(WORD))
789         memcpy( &retvalue, (char *)(class + 1) + offset, sizeof(retvalue) );
790     else
791         SetLastError( ERROR_INVALID_INDEX );
792     release_class_ptr( class );
793     return retvalue;
794 }
795
796
797 /***********************************************************************
798  *              GetClassLong (USER.131)
799  */
800 LONG WINAPI GetClassLong16( HWND16 hwnd16, INT16 offset )
801 {
802     CLASS *class;
803     LONG ret;
804     HWND hwnd = (HWND)(ULONG_PTR)hwnd16;  /* no need for full handle */
805
806     TRACE("%p %d\n",hwnd, offset);
807
808     switch( offset )
809     {
810     case GCL_WNDPROC:
811         if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
812         if (class == CLASS_OTHER_PROCESS) break;
813         ret = (LONG)CLASS_GetProc( class, WIN_PROC_16 );
814         release_class_ptr( class );
815         return ret;
816     case GCL_MENUNAME:
817         if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
818         if (class == CLASS_OTHER_PROCESS) break;
819         ret = (LONG)CLASS_GetMenuName16( class );
820         release_class_ptr( class );
821         return ret;
822     default:
823         return GetClassLongA( hwnd, offset );
824     }
825     FIXME( "offset %d not supported on other process window %p\n", offset, hwnd );
826     SetLastError( ERROR_INVALID_HANDLE );
827     return 0;
828 }
829
830
831 /***********************************************************************
832  *              GetClassLongW (USER32.@)
833  */
834 LONG WINAPI GetClassLongW( HWND hwnd, INT offset )
835 {
836     CLASS *class;
837     LONG retvalue = 0;
838
839     TRACE("%p %d\n", hwnd, offset);
840
841     if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
842
843     if (class == CLASS_OTHER_PROCESS)
844     {
845         SERVER_START_REQ( set_class_info )
846         {
847             req->window = hwnd;
848             req->flags = 0;
849             req->extra_offset = (offset >= 0) ? offset : -1;
850             req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
851             if (!wine_server_call_err( req ))
852             {
853                 switch(offset)
854                 {
855                 case GCL_HBRBACKGROUND:
856                 case GCL_HCURSOR:
857                 case GCL_HICON:
858                 case GCL_HICONSM:
859                 case GCL_WNDPROC:
860                 case GCL_MENUNAME:
861                     FIXME( "offset %d not supported on other process window %p\n", offset, hwnd );
862                     SetLastError( ERROR_INVALID_HANDLE );
863                     break;
864                 case GCL_STYLE:
865                     retvalue = reply->old_style;
866                     break;
867                 case GCL_CBWNDEXTRA:
868                     retvalue = reply->old_win_extra;
869                     break;
870                 case GCL_CBCLSEXTRA:
871                     retvalue = reply->old_extra;
872                     break;
873                 case GCL_HMODULE:
874                     retvalue = (LONG)reply->old_instance;
875                     break;
876                 case GCW_ATOM:
877                     retvalue = reply->old_atom;
878                     break;
879                 default:
880                     if (offset >= 0) memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
881                     else SetLastError( ERROR_INVALID_INDEX );
882                     break;
883                 }
884             }
885         }
886         SERVER_END_REQ;
887         return retvalue;
888     }
889
890     if (offset >= 0)
891     {
892         if (offset <= class->cbClsExtra - sizeof(LONG))
893             memcpy( &retvalue, (char *)(class + 1) + offset, sizeof(retvalue) );
894         else
895             SetLastError( ERROR_INVALID_INDEX );
896         release_class_ptr( class );
897         return retvalue;
898     }
899
900     switch(offset)
901     {
902     case GCL_HBRBACKGROUND:
903         retvalue = (LONG)class->hbrBackground;
904         break;
905     case GCL_HCURSOR:
906         retvalue = (LONG)class->hCursor;
907         break;
908     case GCL_HICON:
909         retvalue = (LONG)class->hIcon;
910         break;
911     case GCL_HICONSM:
912         retvalue = (LONG)class->hIconSm;
913         break;
914     case GCL_STYLE:
915         retvalue = (LONG)class->style;
916         break;
917     case GCL_CBWNDEXTRA:
918         retvalue = (LONG)class->cbWndExtra;
919         break;
920     case GCL_CBCLSEXTRA:
921         retvalue = (LONG)class->cbClsExtra;
922         break;
923     case GCL_HMODULE:
924         retvalue = (LONG)class->hInstance;
925         break;
926     case GCL_WNDPROC:
927         retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32W );
928         break;
929     case GCL_MENUNAME:
930         retvalue = (LONG)CLASS_GetMenuNameW( class );
931         break;
932     case GCW_ATOM:
933         retvalue = (DWORD)class->atomName;
934         break;
935     default:
936         SetLastError( ERROR_INVALID_INDEX );
937         break;
938     }
939     release_class_ptr( class );
940     return retvalue;
941 }
942
943
944 /***********************************************************************
945  *              GetClassLongA (USER32.@)
946  */
947 LONG WINAPI GetClassLongA( HWND hwnd, INT offset )
948 {
949     CLASS *class;
950     LONG retvalue;
951
952     if (offset != GCL_WNDPROC && offset != GCL_MENUNAME)
953         return GetClassLongW( hwnd, offset );
954
955     TRACE("%p %d\n", hwnd, offset);
956
957     if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
958
959     if (class == CLASS_OTHER_PROCESS)
960     {
961         FIXME( "offset %d not supported on other process window %p\n", offset, hwnd );
962         SetLastError( ERROR_INVALID_HANDLE );
963         return 0;
964     }
965
966     if (offset == GCL_WNDPROC)
967         retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32A );
968     else  /* GCL_MENUNAME */
969         retvalue = (LONG)CLASS_GetMenuNameA( class );
970
971     release_class_ptr( class );
972     return retvalue;
973 }
974
975
976 /***********************************************************************
977  *              SetClassWord (USER32.@)
978  */
979 WORD WINAPI SetClassWord( HWND hwnd, INT offset, WORD newval )
980 {
981     CLASS *class;
982     WORD retval = 0;
983
984     if (offset < 0) return SetClassLongA( hwnd, offset, (DWORD)newval );
985
986     TRACE("%p %d %x\n", hwnd, offset, newval);
987
988     if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
989
990     SERVER_START_REQ( set_class_info )
991     {
992         req->window = hwnd;
993         req->flags = SET_CLASS_EXTRA;
994         req->extra_offset = offset;
995         req->extra_size = sizeof(newval);
996         memcpy( &req->extra_value, &newval, sizeof(newval) );
997         if (!wine_server_call_err( req ))
998         {
999             void *ptr = (char *)(class + 1) + offset;
1000             memcpy( &retval, ptr, sizeof(retval) );
1001             memcpy( ptr, &newval, sizeof(newval) );
1002         }
1003     }
1004     SERVER_END_REQ;
1005     release_class_ptr( class );
1006     return retval;
1007 }
1008
1009
1010 /***********************************************************************
1011  *              SetClassLong (USER.132)
1012  */
1013 LONG WINAPI SetClassLong16( HWND16 hwnd16, INT16 offset, LONG newval )
1014 {
1015     CLASS *class;
1016     LONG retval;
1017     HWND hwnd = (HWND)(ULONG_PTR)hwnd16;  /* no need for full handle */
1018
1019     TRACE("%p %d %lx\n", hwnd, offset, newval);
1020
1021     switch(offset)
1022     {
1023     case GCL_WNDPROC:
1024         if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
1025         retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_16 );
1026         release_class_ptr( class );
1027         return retval;
1028     case GCL_MENUNAME:
1029         newval = (LONG)MapSL( newval );
1030         /* fall through */
1031     default:
1032         return SetClassLongA( hwnd, offset, newval );
1033     }
1034 }
1035
1036
1037 /***********************************************************************
1038  *              SetClassLongW (USER32.@)
1039  */
1040 LONG WINAPI SetClassLongW( HWND hwnd, INT offset, LONG newval )
1041 {
1042     CLASS *class;
1043     LONG retval = 0;
1044
1045     TRACE("%p %d %lx\n", hwnd, offset, newval);
1046
1047     if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
1048
1049     if (offset >= 0)
1050     {
1051         if (set_server_info( hwnd, offset, newval ))
1052         {
1053             void *ptr = (char *)(class + 1) + offset;
1054             memcpy( &retval, ptr, sizeof(retval) );
1055             memcpy( ptr, &newval, sizeof(newval) );
1056         }
1057     }
1058     else switch(offset)
1059     {
1060     case GCL_MENUNAME:
1061         CLASS_SetMenuNameW( class, (LPCWSTR)newval );
1062         retval = 0;  /* Old value is now meaningless anyway */
1063         break;
1064     case GCL_WNDPROC:
1065         retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32W );
1066         break;
1067     case GCL_HBRBACKGROUND:
1068         retval = (LONG)class->hbrBackground;
1069         class->hbrBackground = (HBRUSH)newval;
1070         break;
1071     case GCL_HCURSOR:
1072         retval = (LONG)class->hCursor;
1073         class->hCursor = (HCURSOR)newval;
1074         break;
1075     case GCL_HICON:
1076         retval = (LONG)class->hIcon;
1077         class->hIcon = (HICON)newval;
1078         break;
1079     case GCL_HICONSM:
1080         retval = (LONG)class->hIconSm;
1081         class->hIconSm = (HICON)newval;
1082         break;
1083     case GCL_STYLE:
1084         if (!set_server_info( hwnd, offset, newval )) break;
1085         retval = (LONG)class->style;
1086         class->style = newval;
1087         break;
1088     case GCL_CBWNDEXTRA:
1089         if (!set_server_info( hwnd, offset, newval )) break;
1090         retval = (LONG)class->cbWndExtra;
1091         class->cbWndExtra = newval;
1092         break;
1093     case GCL_HMODULE:
1094         if (!set_server_info( hwnd, offset, newval )) break;
1095         retval = (LONG)class->hInstance;
1096         class->hInstance = (HINSTANCE)newval;
1097         break;
1098     case GCW_ATOM:
1099         if (!set_server_info( hwnd, offset, newval )) break;
1100         retval = (DWORD)class->atomName;
1101         class->atomName = newval;
1102         break;
1103     case GCL_CBCLSEXTRA:  /* cannot change this one */
1104         SetLastError( ERROR_INVALID_PARAMETER );
1105         break;
1106     default:
1107         SetLastError( ERROR_INVALID_INDEX );
1108         break;
1109     }
1110     release_class_ptr( class );
1111     return retval;
1112 }
1113
1114
1115 /***********************************************************************
1116  *              SetClassLongA (USER32.@)
1117  */
1118 LONG WINAPI SetClassLongA( HWND hwnd, INT offset, LONG newval )
1119 {
1120     CLASS *class;
1121     LONG retval;
1122
1123     if (offset != GCL_WNDPROC && offset != GCL_MENUNAME)
1124         return SetClassLongW( hwnd, offset, newval );
1125
1126     TRACE("%p %d %lx\n", hwnd, offset, newval);
1127
1128     if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
1129
1130     if (offset == GCL_WNDPROC)
1131         retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32A );
1132     else  /* GCL_MENUNAME */
1133     {
1134         CLASS_SetMenuNameA( class, (LPCSTR)newval );
1135         retval = 0;  /* Old value is now meaningless anyway */
1136     }
1137     release_class_ptr( class );
1138     return retval;
1139 }
1140
1141
1142 /***********************************************************************
1143  *              GetClassNameA (USER32.@)
1144  */
1145 INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
1146 {
1147     INT ret = GlobalGetAtomNameA( GetClassLongA( hwnd, GCW_ATOM ), buffer, count );
1148
1149     TRACE("%p %s %x\n",hwnd, debugstr_a(buffer), count);
1150     return ret;
1151 }
1152
1153
1154 /***********************************************************************
1155  *              GetClassNameW (USER32.@)
1156  */
1157 INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
1158 {
1159     INT ret = GlobalGetAtomNameW( GetClassLongW( hwnd, GCW_ATOM ), buffer, count );
1160
1161     TRACE("%p %s %x\n",hwnd, debugstr_w(buffer), count);
1162     return ret;
1163 }
1164
1165
1166 /***********************************************************************
1167  *              RealGetWindowClassA (USER32.@)
1168  */
1169 UINT WINAPI RealGetWindowClassA( HWND hwnd, LPSTR buffer, UINT count )
1170 {
1171     return GetClassNameA( hwnd, buffer, count );
1172 }
1173
1174
1175 /***********************************************************************
1176  *              RealGetWindowClassW (USER32.@)
1177  */
1178 UINT WINAPI RealGetWindowClassW( HWND hwnd, LPWSTR buffer, UINT count )
1179 {
1180     return GetClassNameW( hwnd, buffer, count );
1181 }
1182
1183
1184 /***********************************************************************
1185  *              GetClassInfo (USER.404)
1186  */
1187 BOOL16 WINAPI GetClassInfo16( HINSTANCE16 hInst16, SEGPTR name, WNDCLASS16 *wc )
1188 {
1189     WNDCLASSEX16 wcex;
1190     UINT16 ret = GetClassInfoEx16( hInst16, name, &wcex );
1191
1192     if (ret)
1193     {
1194         wc->style         = wcex.style;
1195         wc->lpfnWndProc   = wcex.lpfnWndProc;
1196         wc->cbClsExtra    = wcex.cbClsExtra;
1197         wc->cbWndExtra    = wcex.cbWndExtra;
1198         wc->hInstance     = wcex.hInstance;
1199         wc->hIcon         = wcex.hIcon;
1200         wc->hCursor       = wcex.hCursor;
1201         wc->hbrBackground = wcex.hbrBackground;
1202         wc->lpszMenuName  = wcex.lpszMenuName;
1203         wc->lpszClassName = wcex.lpszClassName;
1204     }
1205     return ret;
1206 }
1207
1208
1209 /***********************************************************************
1210  *              GetClassInfoA (USER32.@)
1211  */
1212 BOOL WINAPI GetClassInfoA( HINSTANCE hInstance, LPCSTR name, WNDCLASSA *wc )
1213 {
1214     WNDCLASSEXA wcex;
1215     UINT ret = GetClassInfoExA( hInstance, name, &wcex );
1216
1217     if (ret)
1218     {
1219         wc->style         = wcex.style;
1220         wc->lpfnWndProc   = wcex.lpfnWndProc;
1221         wc->cbClsExtra    = wcex.cbClsExtra;
1222         wc->cbWndExtra    = wcex.cbWndExtra;
1223         wc->hInstance     = wcex.hInstance;
1224         wc->hIcon         = wcex.hIcon;
1225         wc->hCursor       = wcex.hCursor;
1226         wc->hbrBackground = wcex.hbrBackground;
1227         wc->lpszMenuName  = wcex.lpszMenuName;
1228         wc->lpszClassName = wcex.lpszClassName;
1229     }
1230     return ret;
1231 }
1232
1233
1234 /***********************************************************************
1235  *              GetClassInfoW (USER32.@)
1236  */
1237 BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSW *wc )
1238 {
1239     WNDCLASSEXW wcex;
1240     UINT ret = GetClassInfoExW( hInstance, name, &wcex );
1241
1242     if (ret)
1243     {
1244         wc->style         = wcex.style;
1245         wc->lpfnWndProc   = wcex.lpfnWndProc;
1246         wc->cbClsExtra    = wcex.cbClsExtra;
1247         wc->cbWndExtra    = wcex.cbWndExtra;
1248         wc->hInstance     = wcex.hInstance;
1249         wc->hIcon         = wcex.hIcon;
1250         wc->hCursor       = wcex.hCursor;
1251         wc->hbrBackground = wcex.hbrBackground;
1252         wc->lpszMenuName  = wcex.lpszMenuName;
1253         wc->lpszClassName = wcex.lpszClassName;
1254     }
1255     return ret;
1256 }
1257
1258
1259 /***********************************************************************
1260  *              GetClassInfoEx (USER.398)
1261  *
1262  * FIXME: this is just a guess, I have no idea if GetClassInfoEx() is the
1263  * same in Win16 as in Win32. --AJ
1264  */
1265 BOOL16 WINAPI GetClassInfoEx16( HINSTANCE16 hInst16, SEGPTR name, WNDCLASSEX16 *wc )
1266 {
1267     ATOM atom = HIWORD(name) ? GlobalFindAtomA( MapSL(name) ) : LOWORD(name);
1268     CLASS *classPtr;
1269     HINSTANCE hInstance;
1270
1271     if (hInst16 == GetModuleHandle16("user")) hInstance = user32_module;
1272     else hInstance = HINSTANCE_32(GetExePtr( hInst16 ));
1273
1274     TRACE("%p %s %x %p\n", hInstance, debugstr_a( MapSL(name) ), atom, wc);
1275
1276     if (!atom || !(classPtr = CLASS_FindClassByAtom( atom, hInstance ))) return FALSE;
1277     wc->style         = classPtr->style;
1278     wc->lpfnWndProc   = CLASS_GetProc( classPtr, WIN_PROC_16 );
1279     wc->cbClsExtra    = (INT16)classPtr->cbClsExtra;
1280     wc->cbWndExtra    = (INT16)classPtr->cbWndExtra;
1281     wc->hInstance     = (classPtr->hInstance == user32_module) ? GetModuleHandle16("user") : HINSTANCE_16(classPtr->hInstance);
1282     wc->hIcon         = HICON_16(classPtr->hIcon);
1283     wc->hIconSm       = HICON_16(classPtr->hIconSm);
1284     wc->hCursor       = HCURSOR_16(classPtr->hCursor);
1285     wc->hbrBackground = HBRUSH_16(classPtr->hbrBackground);
1286     wc->lpszClassName = (SEGPTR)0;
1287     wc->lpszMenuName  = CLASS_GetMenuName16( classPtr );
1288     wc->lpszClassName = name;
1289     release_class_ptr( classPtr );
1290
1291     /* We must return the atom of the class here instead of just TRUE. */
1292     return atom;
1293 }
1294
1295
1296 /***********************************************************************
1297  *              GetClassInfoExA (USER32.@)
1298  */
1299 BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name, WNDCLASSEXA *wc )
1300 {
1301     ATOM atom = HIWORD(name) ? GlobalFindAtomA( name ) : LOWORD(name);
1302     CLASS *classPtr;
1303
1304     TRACE("%p %s %x %p\n", hInstance, debugstr_a(name), atom, wc);
1305
1306     if (!hInstance) hInstance = user32_module;
1307
1308     if (!atom || !(classPtr = CLASS_FindClassByAtom( atom, hInstance )))
1309     {
1310         SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
1311         return FALSE;
1312     }
1313     wc->style         = classPtr->style;
1314     wc->lpfnWndProc   = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32A );
1315     wc->cbClsExtra    = classPtr->cbClsExtra;
1316     wc->cbWndExtra    = classPtr->cbWndExtra;
1317     wc->hInstance     = (hInstance == user32_module) ? 0 : hInstance;
1318     wc->hIcon         = (HICON)classPtr->hIcon;
1319     wc->hIconSm       = (HICON)classPtr->hIconSm;
1320     wc->hCursor       = (HCURSOR)classPtr->hCursor;
1321     wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1322     wc->lpszMenuName  = CLASS_GetMenuNameA( classPtr );
1323     wc->lpszClassName = name;
1324     release_class_ptr( classPtr );
1325
1326     /* We must return the atom of the class here instead of just TRUE. */
1327     return atom;
1328 }
1329
1330
1331 /***********************************************************************
1332  *              GetClassInfoExW (USER32.@)
1333  */
1334 BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSEXW *wc )
1335 {
1336     ATOM atom = HIWORD(name) ? GlobalFindAtomW( name ) : LOWORD(name);
1337     CLASS *classPtr;
1338
1339     TRACE("%p %s %x %p\n", hInstance, debugstr_w(name), atom, wc);
1340
1341     if (!hInstance) hInstance = user32_module;
1342
1343     if (!atom || !(classPtr = CLASS_FindClassByAtom( atom, hInstance )))
1344     {
1345         SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
1346         return FALSE;
1347     }
1348     wc->style         = classPtr->style;
1349     wc->lpfnWndProc   = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
1350     wc->cbClsExtra    = classPtr->cbClsExtra;
1351     wc->cbWndExtra    = classPtr->cbWndExtra;
1352     wc->hInstance     = (hInstance == user32_module) ? 0 : hInstance;
1353     wc->hIcon         = (HICON)classPtr->hIcon;
1354     wc->hIconSm       = (HICON)classPtr->hIconSm;
1355     wc->hCursor       = (HCURSOR)classPtr->hCursor;
1356     wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1357     wc->lpszMenuName  = CLASS_GetMenuNameW( classPtr );
1358     wc->lpszClassName = name;
1359     release_class_ptr( classPtr );
1360
1361     /* We must return the atom of the class here instead of just TRUE. */
1362     return atom;
1363 }
1364
1365
1366 #if 0  /* toolhelp is in kernel, so this cannot work */
1367
1368 /***********************************************************************
1369  *              ClassFirst (TOOLHELP.69)
1370  */
1371 BOOL16 WINAPI ClassFirst16( CLASSENTRY *pClassEntry )
1372 {
1373     TRACE("%p\n",pClassEntry);
1374     pClassEntry->wNext = 1;
1375     return ClassNext16( pClassEntry );
1376 }
1377
1378
1379 /***********************************************************************
1380  *              ClassNext (TOOLHELP.70)
1381  */
1382 BOOL16 WINAPI ClassNext16( CLASSENTRY *pClassEntry )
1383 {
1384     int i;
1385     CLASS *class = firstClass;
1386
1387     TRACE("%p\n",pClassEntry);
1388
1389     if (!pClassEntry->wNext) return FALSE;
1390     for (i = 1; (i < pClassEntry->wNext) && class; i++) class = class->next;
1391     if (!class)
1392     {
1393         pClassEntry->wNext = 0;
1394         return FALSE;
1395     }
1396     pClassEntry->hInst = class->hInstance;
1397     pClassEntry->wNext++;
1398     GlobalGetAtomNameA( class->atomName, pClassEntry->szClassName,
1399                           sizeof(pClassEntry->szClassName) );
1400     return TRUE;
1401 }
1402 #endif