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