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