When there are no pixels to scroll, ScrollWindowEx must still scroll
[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     SERVER_START_REQ( destroy_class )
745     {
746         req->atom = atom;
747         req->instance = hInstance;
748         if (!wine_server_call_err( req )) classPtr = reply->client_ptr;
749     }
750     SERVER_END_REQ;
751
752     if (classPtr) CLASS_FreeClass( classPtr );
753     return (classPtr != NULL);
754 }
755
756
757 /***********************************************************************
758  *              GetClassWord (USER32.@)
759  */
760 WORD WINAPI GetClassWord( HWND hwnd, INT offset )
761 {
762     CLASS *class;
763     WORD retvalue = 0;
764
765     if (offset < 0) return GetClassLongA( hwnd, offset );
766
767     TRACE("%p %x\n",hwnd, offset);
768
769     if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
770
771     if (class == CLASS_OTHER_PROCESS)
772     {
773         SERVER_START_REQ( set_class_info )
774         {
775             req->window = hwnd;
776             req->flags = 0;
777             req->extra_offset = offset;
778             req->extra_size = sizeof(retvalue);
779             if (!wine_server_call_err( req ))
780                 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
781         }
782         SERVER_END_REQ;
783         return retvalue;
784     }
785
786     if (offset <= class->cbClsExtra - sizeof(WORD))
787         memcpy( &retvalue, (char *)(class + 1) + offset, sizeof(retvalue) );
788     else
789         SetLastError( ERROR_INVALID_INDEX );
790     release_class_ptr( class );
791     return retvalue;
792 }
793
794
795 /***********************************************************************
796  *              GetClassLong (USER.131)
797  */
798 LONG WINAPI GetClassLong16( HWND16 hwnd16, INT16 offset )
799 {
800     CLASS *class;
801     LONG ret;
802     HWND hwnd = (HWND)(ULONG_PTR)hwnd16;  /* no need for full handle */
803
804     TRACE("%p %d\n",hwnd, offset);
805
806     switch( offset )
807     {
808     case GCL_WNDPROC:
809         if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
810         if (class == CLASS_OTHER_PROCESS) break;
811         ret = (LONG)CLASS_GetProc( class, WIN_PROC_16 );
812         release_class_ptr( class );
813         return ret;
814     case GCL_MENUNAME:
815         if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
816         if (class == CLASS_OTHER_PROCESS) break;
817         ret = (LONG)CLASS_GetMenuName16( class );
818         release_class_ptr( class );
819         return ret;
820     default:
821         return GetClassLongA( hwnd, offset );
822     }
823     FIXME( "offset %d not supported on other process window %p\n", offset, hwnd );
824     SetLastError( ERROR_INVALID_HANDLE );
825     return 0;
826 }
827
828
829 /***********************************************************************
830  *              GetClassLongW (USER32.@)
831  */
832 LONG WINAPI GetClassLongW( HWND hwnd, INT offset )
833 {
834     CLASS *class;
835     LONG retvalue = 0;
836
837     TRACE("%p %d\n", hwnd, offset);
838
839     if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
840
841     if (class == CLASS_OTHER_PROCESS)
842     {
843         SERVER_START_REQ( set_class_info )
844         {
845             req->window = hwnd;
846             req->flags = 0;
847             req->extra_offset = (offset >= 0) ? offset : -1;
848             req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
849             if (!wine_server_call_err( req ))
850             {
851                 switch(offset)
852                 {
853                 case GCL_HBRBACKGROUND:
854                 case GCL_HCURSOR:
855                 case GCL_HICON:
856                 case GCL_HICONSM:
857                 case GCL_WNDPROC:
858                 case GCL_MENUNAME:
859                     FIXME( "offset %d not supported on other process window %p\n", offset, hwnd );
860                     SetLastError( ERROR_INVALID_HANDLE );
861                     break;
862                 case GCL_STYLE:
863                     retvalue = reply->old_style;
864                     break;
865                 case GCL_CBWNDEXTRA:
866                     retvalue = reply->old_win_extra;
867                     break;
868                 case GCL_CBCLSEXTRA:
869                     retvalue = reply->old_extra;
870                     break;
871                 case GCL_HMODULE:
872                     retvalue = (LONG)reply->old_instance;
873                     break;
874                 case GCW_ATOM:
875                     retvalue = reply->old_atom;
876                     break;
877                 default:
878                     if (offset >= 0) memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
879                     else SetLastError( ERROR_INVALID_INDEX );
880                     break;
881                 }
882             }
883         }
884         SERVER_END_REQ;
885         return retvalue;
886     }
887
888     if (offset >= 0)
889     {
890         if (offset <= class->cbClsExtra - sizeof(LONG))
891             memcpy( &retvalue, (char *)(class + 1) + offset, sizeof(retvalue) );
892         else
893             SetLastError( ERROR_INVALID_INDEX );
894         release_class_ptr( class );
895         return retvalue;
896     }
897
898     switch(offset)
899     {
900     case GCL_HBRBACKGROUND:
901         retvalue = (LONG)class->hbrBackground;
902         break;
903     case GCL_HCURSOR:
904         retvalue = (LONG)class->hCursor;
905         break;
906     case GCL_HICON:
907         retvalue = (LONG)class->hIcon;
908         break;
909     case GCL_HICONSM:
910         retvalue = (LONG)class->hIconSm;
911         break;
912     case GCL_STYLE:
913         retvalue = (LONG)class->style;
914         break;
915     case GCL_CBWNDEXTRA:
916         retvalue = (LONG)class->cbWndExtra;
917         break;
918     case GCL_CBCLSEXTRA:
919         retvalue = (LONG)class->cbClsExtra;
920         break;
921     case GCL_HMODULE:
922         retvalue = (LONG)class->hInstance;
923         break;
924     case GCL_WNDPROC:
925         retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32W );
926         break;
927     case GCL_MENUNAME:
928         retvalue = (LONG)CLASS_GetMenuNameW( class );
929         break;
930     case GCW_ATOM:
931         retvalue = (DWORD)class->atomName;
932         break;
933     default:
934         SetLastError( ERROR_INVALID_INDEX );
935         break;
936     }
937     release_class_ptr( class );
938     return retvalue;
939 }
940
941
942 /***********************************************************************
943  *              GetClassLongA (USER32.@)
944  */
945 LONG WINAPI GetClassLongA( HWND hwnd, INT offset )
946 {
947     CLASS *class;
948     LONG retvalue;
949
950     if (offset != GCL_WNDPROC && offset != GCL_MENUNAME)
951         return GetClassLongW( hwnd, offset );
952
953     TRACE("%p %d\n", hwnd, offset);
954
955     if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
956
957     if (class == CLASS_OTHER_PROCESS)
958     {
959         FIXME( "offset %d not supported on other process window %p\n", offset, hwnd );
960         SetLastError( ERROR_INVALID_HANDLE );
961         return 0;
962     }
963
964     if (offset == GCL_WNDPROC)
965         retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32A );
966     else  /* GCL_MENUNAME */
967         retvalue = (LONG)CLASS_GetMenuNameA( class );
968
969     release_class_ptr( class );
970     return retvalue;
971 }
972
973
974 /***********************************************************************
975  *              SetClassWord (USER32.@)
976  */
977 WORD WINAPI SetClassWord( HWND hwnd, INT offset, WORD newval )
978 {
979     CLASS *class;
980     WORD retval = 0;
981
982     if (offset < 0) return SetClassLongA( hwnd, offset, (DWORD)newval );
983
984     TRACE("%p %d %x\n", hwnd, offset, newval);
985
986     if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
987
988     SERVER_START_REQ( set_class_info )
989     {
990         req->window = hwnd;
991         req->flags = SET_CLASS_EXTRA;
992         req->extra_offset = offset;
993         req->extra_size = sizeof(newval);
994         memcpy( &req->extra_value, &newval, sizeof(newval) );
995         if (!wine_server_call_err( req ))
996         {
997             void *ptr = (char *)(class + 1) + offset;
998             memcpy( &retval, ptr, sizeof(retval) );
999             memcpy( ptr, &newval, sizeof(newval) );
1000         }
1001     }
1002     SERVER_END_REQ;
1003     release_class_ptr( class );
1004     return retval;
1005 }
1006
1007
1008 /***********************************************************************
1009  *              SetClassLong (USER.132)
1010  */
1011 LONG WINAPI SetClassLong16( HWND16 hwnd16, INT16 offset, LONG newval )
1012 {
1013     CLASS *class;
1014     LONG retval;
1015     HWND hwnd = (HWND)(ULONG_PTR)hwnd16;  /* no need for full handle */
1016
1017     TRACE("%p %d %lx\n", hwnd, offset, newval);
1018
1019     switch(offset)
1020     {
1021     case GCL_WNDPROC:
1022         if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
1023         retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_16 );
1024         release_class_ptr( class );
1025         return retval;
1026     case GCL_MENUNAME:
1027         newval = (LONG)MapSL( newval );
1028         /* fall through */
1029     default:
1030         return SetClassLongA( hwnd, offset, newval );
1031     }
1032 }
1033
1034
1035 /***********************************************************************
1036  *              SetClassLongW (USER32.@)
1037  */
1038 LONG WINAPI SetClassLongW( HWND hwnd, INT offset, LONG newval )
1039 {
1040     CLASS *class;
1041     LONG retval = 0;
1042
1043     TRACE("%p %d %lx\n", hwnd, offset, newval);
1044
1045     if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
1046
1047     if (offset >= 0)
1048     {
1049         if (set_server_info( hwnd, offset, newval ))
1050         {
1051             void *ptr = (char *)(class + 1) + offset;
1052             memcpy( &retval, ptr, sizeof(retval) );
1053             memcpy( ptr, &newval, sizeof(newval) );
1054         }
1055     }
1056     else switch(offset)
1057     {
1058     case GCL_MENUNAME:
1059         CLASS_SetMenuNameW( class, (LPCWSTR)newval );
1060         retval = 0;  /* Old value is now meaningless anyway */
1061         break;
1062     case GCL_WNDPROC:
1063         retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32W );
1064         break;
1065     case GCL_HBRBACKGROUND:
1066         retval = (LONG)class->hbrBackground;
1067         class->hbrBackground = (HBRUSH)newval;
1068         break;
1069     case GCL_HCURSOR:
1070         retval = (LONG)class->hCursor;
1071         class->hCursor = (HCURSOR)newval;
1072         break;
1073     case GCL_HICON:
1074         retval = (LONG)class->hIcon;
1075         class->hIcon = (HICON)newval;
1076         break;
1077     case GCL_HICONSM:
1078         retval = (LONG)class->hIconSm;
1079         class->hIconSm = (HICON)newval;
1080         break;
1081     case GCL_STYLE:
1082         if (!set_server_info( hwnd, offset, newval )) break;
1083         retval = (LONG)class->style;
1084         class->style = newval;
1085         break;
1086     case GCL_CBWNDEXTRA:
1087         if (!set_server_info( hwnd, offset, newval )) break;
1088         retval = (LONG)class->cbWndExtra;
1089         class->cbWndExtra = newval;
1090         break;
1091     case GCL_HMODULE:
1092         if (!set_server_info( hwnd, offset, newval )) break;
1093         retval = (LONG)class->hInstance;
1094         class->hInstance = (HINSTANCE)newval;
1095         break;
1096     case GCW_ATOM:
1097         if (!set_server_info( hwnd, offset, newval )) break;
1098         retval = (DWORD)class->atomName;
1099         class->atomName = newval;
1100         break;
1101     case GCL_CBCLSEXTRA:  /* cannot change this one */
1102         SetLastError( ERROR_INVALID_PARAMETER );
1103         break;
1104     default:
1105         SetLastError( ERROR_INVALID_INDEX );
1106         break;
1107     }
1108     release_class_ptr( class );
1109     return retval;
1110 }
1111
1112
1113 /***********************************************************************
1114  *              SetClassLongA (USER32.@)
1115  */
1116 LONG WINAPI SetClassLongA( HWND hwnd, INT offset, LONG newval )
1117 {
1118     CLASS *class;
1119     LONG retval;
1120
1121     if (offset != GCL_WNDPROC && offset != GCL_MENUNAME)
1122         return SetClassLongW( hwnd, offset, newval );
1123
1124     TRACE("%p %d %lx\n", hwnd, offset, newval);
1125
1126     if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
1127
1128     if (offset == GCL_WNDPROC)
1129         retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32A );
1130     else  /* GCL_MENUNAME */
1131     {
1132         CLASS_SetMenuNameA( class, (LPCSTR)newval );
1133         retval = 0;  /* Old value is now meaningless anyway */
1134     }
1135     release_class_ptr( class );
1136     return retval;
1137 }
1138
1139
1140 /***********************************************************************
1141  *              GetClassNameA (USER32.@)
1142  */
1143 INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
1144 {
1145     INT ret = GlobalGetAtomNameA( GetClassLongA( hwnd, GCW_ATOM ), buffer, count );
1146
1147     TRACE("%p %s %x\n",hwnd, debugstr_a(buffer), count);
1148     return ret;
1149 }
1150
1151
1152 /***********************************************************************
1153  *              GetClassNameW (USER32.@)
1154  */
1155 INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
1156 {
1157     INT ret = GlobalGetAtomNameW( GetClassLongW( hwnd, GCW_ATOM ), buffer, count );
1158
1159     TRACE("%p %s %x\n",hwnd, debugstr_w(buffer), count);
1160     return ret;
1161 }
1162
1163
1164 /***********************************************************************
1165  *              RealGetWindowClassA (USER32.@)
1166  */
1167 UINT WINAPI RealGetWindowClassA( HWND hwnd, LPSTR buffer, UINT count )
1168 {
1169     return GetClassNameA( hwnd, buffer, count );
1170 }
1171
1172
1173 /***********************************************************************
1174  *              RealGetWindowClassW (USER32.@)
1175  */
1176 UINT WINAPI RealGetWindowClassW( HWND hwnd, LPWSTR buffer, UINT count )
1177 {
1178     return GetClassNameW( hwnd, buffer, count );
1179 }
1180
1181
1182 /***********************************************************************
1183  *              GetClassInfo (USER.404)
1184  */
1185 BOOL16 WINAPI GetClassInfo16( HINSTANCE16 hInst16, SEGPTR name, WNDCLASS16 *wc )
1186 {
1187     WNDCLASSEX16 wcex;
1188     UINT16 ret = GetClassInfoEx16( hInst16, name, &wcex );
1189
1190     if (ret)
1191     {
1192         wc->style         = wcex.style;
1193         wc->lpfnWndProc   = wcex.lpfnWndProc;
1194         wc->cbClsExtra    = wcex.cbClsExtra;
1195         wc->cbWndExtra    = wcex.cbWndExtra;
1196         wc->hInstance     = wcex.hInstance;
1197         wc->hIcon         = wcex.hIcon;
1198         wc->hCursor       = wcex.hCursor;
1199         wc->hbrBackground = wcex.hbrBackground;
1200         wc->lpszMenuName  = wcex.lpszMenuName;
1201         wc->lpszClassName = wcex.lpszClassName;
1202     }
1203     return ret;
1204 }
1205
1206
1207 /***********************************************************************
1208  *              GetClassInfoA (USER32.@)
1209  */
1210 BOOL WINAPI GetClassInfoA( HINSTANCE hInstance, LPCSTR name, WNDCLASSA *wc )
1211 {
1212     WNDCLASSEXA wcex;
1213     UINT ret = GetClassInfoExA( hInstance, name, &wcex );
1214
1215     if (ret)
1216     {
1217         wc->style         = wcex.style;
1218         wc->lpfnWndProc   = wcex.lpfnWndProc;
1219         wc->cbClsExtra    = wcex.cbClsExtra;
1220         wc->cbWndExtra    = wcex.cbWndExtra;
1221         wc->hInstance     = wcex.hInstance;
1222         wc->hIcon         = wcex.hIcon;
1223         wc->hCursor       = wcex.hCursor;
1224         wc->hbrBackground = wcex.hbrBackground;
1225         wc->lpszMenuName  = wcex.lpszMenuName;
1226         wc->lpszClassName = wcex.lpszClassName;
1227     }
1228     return ret;
1229 }
1230
1231
1232 /***********************************************************************
1233  *              GetClassInfoW (USER32.@)
1234  */
1235 BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSW *wc )
1236 {
1237     WNDCLASSEXW wcex;
1238     UINT ret = GetClassInfoExW( hInstance, name, &wcex );
1239
1240     if (ret)
1241     {
1242         wc->style         = wcex.style;
1243         wc->lpfnWndProc   = wcex.lpfnWndProc;
1244         wc->cbClsExtra    = wcex.cbClsExtra;
1245         wc->cbWndExtra    = wcex.cbWndExtra;
1246         wc->hInstance     = wcex.hInstance;
1247         wc->hIcon         = wcex.hIcon;
1248         wc->hCursor       = wcex.hCursor;
1249         wc->hbrBackground = wcex.hbrBackground;
1250         wc->lpszMenuName  = wcex.lpszMenuName;
1251         wc->lpszClassName = wcex.lpszClassName;
1252     }
1253     return ret;
1254 }
1255
1256
1257 /***********************************************************************
1258  *              GetClassInfoEx (USER.398)
1259  *
1260  * FIXME: this is just a guess, I have no idea if GetClassInfoEx() is the
1261  * same in Win16 as in Win32. --AJ
1262  */
1263 BOOL16 WINAPI GetClassInfoEx16( HINSTANCE16 hInst16, SEGPTR name, WNDCLASSEX16 *wc )
1264 {
1265     ATOM atom = HIWORD(name) ? GlobalFindAtomA( MapSL(name) ) : LOWORD(name);
1266     CLASS *classPtr;
1267     HINSTANCE hInstance;
1268
1269     if (hInst16 == GetModuleHandle16("user")) hInstance = user32_module;
1270     else hInstance = HINSTANCE_32(GetExePtr( hInst16 ));
1271
1272     TRACE("%p %s %x %p\n", hInstance, debugstr_a( MapSL(name) ), atom, wc);
1273
1274     if (!atom || !(classPtr = CLASS_FindClassByAtom( atom, hInstance ))) return FALSE;
1275     wc->style         = classPtr->style;
1276     wc->lpfnWndProc   = CLASS_GetProc( classPtr, WIN_PROC_16 );
1277     wc->cbClsExtra    = (INT16)classPtr->cbClsExtra;
1278     wc->cbWndExtra    = (INT16)classPtr->cbWndExtra;
1279     wc->hInstance     = (classPtr->hInstance == user32_module) ? GetModuleHandle16("user") : HINSTANCE_16(classPtr->hInstance);
1280     wc->hIcon         = HICON_16(classPtr->hIcon);
1281     wc->hIconSm       = HICON_16(classPtr->hIconSm);
1282     wc->hCursor       = HCURSOR_16(classPtr->hCursor);
1283     wc->hbrBackground = HBRUSH_16(classPtr->hbrBackground);
1284     wc->lpszClassName = (SEGPTR)0;
1285     wc->lpszMenuName  = CLASS_GetMenuName16( classPtr );
1286     wc->lpszClassName = name;
1287     release_class_ptr( classPtr );
1288
1289     /* We must return the atom of the class here instead of just TRUE. */
1290     return atom;
1291 }
1292
1293
1294 /***********************************************************************
1295  *              GetClassInfoExA (USER32.@)
1296  */
1297 BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name, WNDCLASSEXA *wc )
1298 {
1299     ATOM atom = HIWORD(name) ? GlobalFindAtomA( name ) : LOWORD(name);
1300     CLASS *classPtr;
1301
1302     TRACE("%p %s %x %p\n", hInstance, debugstr_a(name), atom, wc);
1303
1304     if (!hInstance) hInstance = user32_module;
1305
1306     if (!atom || !(classPtr = CLASS_FindClassByAtom( atom, hInstance )))
1307     {
1308         SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
1309         return FALSE;
1310     }
1311     wc->style         = classPtr->style;
1312     wc->lpfnWndProc   = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32A );
1313     wc->cbClsExtra    = classPtr->cbClsExtra;
1314     wc->cbWndExtra    = classPtr->cbWndExtra;
1315     wc->hInstance     = (hInstance == user32_module) ? 0 : hInstance;
1316     wc->hIcon         = (HICON)classPtr->hIcon;
1317     wc->hIconSm       = (HICON)classPtr->hIconSm;
1318     wc->hCursor       = (HCURSOR)classPtr->hCursor;
1319     wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1320     wc->lpszMenuName  = CLASS_GetMenuNameA( classPtr );
1321     wc->lpszClassName = name;
1322     release_class_ptr( classPtr );
1323
1324     /* We must return the atom of the class here instead of just TRUE. */
1325     return atom;
1326 }
1327
1328
1329 /***********************************************************************
1330  *              GetClassInfoExW (USER32.@)
1331  */
1332 BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSEXW *wc )
1333 {
1334     ATOM atom = HIWORD(name) ? GlobalFindAtomW( name ) : LOWORD(name);
1335     CLASS *classPtr;
1336
1337     TRACE("%p %s %x %p\n", hInstance, debugstr_w(name), atom, wc);
1338
1339     if (!hInstance) hInstance = user32_module;
1340
1341     if (!atom || !(classPtr = CLASS_FindClassByAtom( atom, hInstance )))
1342     {
1343         SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
1344         return FALSE;
1345     }
1346     wc->style         = classPtr->style;
1347     wc->lpfnWndProc   = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
1348     wc->cbClsExtra    = classPtr->cbClsExtra;
1349     wc->cbWndExtra    = classPtr->cbWndExtra;
1350     wc->hInstance     = (hInstance == user32_module) ? 0 : hInstance;
1351     wc->hIcon         = (HICON)classPtr->hIcon;
1352     wc->hIconSm       = (HICON)classPtr->hIconSm;
1353     wc->hCursor       = (HCURSOR)classPtr->hCursor;
1354     wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1355     wc->lpszMenuName  = CLASS_GetMenuNameW( classPtr );
1356     wc->lpszClassName = name;
1357     release_class_ptr( classPtr );
1358
1359     /* We must return the atom of the class here instead of just TRUE. */
1360     return atom;
1361 }
1362
1363
1364 #if 0  /* toolhelp is in kernel, so this cannot work */
1365
1366 /***********************************************************************
1367  *              ClassFirst (TOOLHELP.69)
1368  */
1369 BOOL16 WINAPI ClassFirst16( CLASSENTRY *pClassEntry )
1370 {
1371     TRACE("%p\n",pClassEntry);
1372     pClassEntry->wNext = 1;
1373     return ClassNext16( pClassEntry );
1374 }
1375
1376
1377 /***********************************************************************
1378  *              ClassNext (TOOLHELP.70)
1379  */
1380 BOOL16 WINAPI ClassNext16( CLASSENTRY *pClassEntry )
1381 {
1382     int i;
1383     CLASS *class = firstClass;
1384
1385     TRACE("%p\n",pClassEntry);
1386
1387     if (!pClassEntry->wNext) return FALSE;
1388     for (i = 1; (i < pClassEntry->wNext) && class; i++) class = class->next;
1389     if (!class)
1390     {
1391         pClassEntry->wNext = 0;
1392         return FALSE;
1393     }
1394     pClassEntry->hInst = class->hInstance;
1395     pClassEntry->wNext++;
1396     GlobalGetAtomNameA( class->atomName, pClassEntry->szClassName,
1397                           sizeof(pClassEntry->szClassName) );
1398     return TRUE;
1399 }
1400 #endif