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