New debug scheme with explicit debug channels declaration.
[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 "debug.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         DUMP("%p is not a class\n", ptr );
48         return;
49     }
50
51     GlobalGetAtomNameA( ptr->atomName, className, sizeof(className) );
52
53     DUMP( "Class %p:\n", ptr );
54     DUMP( "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         DUMP( "extra bytes:" );
64         for (i = 0; i < ptr->cbClsExtra; i++)
65             DUMP( " %02x", *((BYTE *)ptr->wExtra+i) );
66         DUMP( "\n" );
67     }
68     DUMP( "\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     DUMP( " Class   Name                  Style   WndProc\n" );
83     for (ptr = firstClass; ptr; ptr = ptr->next)
84     {
85         GlobalGetAtomNameA( ptr->atomName, className, sizeof(className) );
86         DUMP( "%08x %-20.20s %08x %08x\n", (UINT)ptr, className,
87                  ptr->style, (UINT)ptr->winproc );
88     }
89     DUMP( "\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(class,"%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, "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(class,"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(class,"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(class,"-- 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(class,"-- 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(class,"-- found local Class registred with hInst=0\n");
334         return tclass;
335     }
336     
337     TRACE(class,"-- 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(class,"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, "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(class, "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(class, "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(class, "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(class, "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(class, "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(class, "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(class, "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(class,"%s %x\n",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(class,"%s %x\n",debugstr_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     
727     TRACE(class,"%x %x\n",hwnd, offset);
728     
729     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
730     if (offset >= 0)
731     {
732         if (offset <= wndPtr->class->cbClsExtra - sizeof(WORD))
733         {
734             WORD retvalue = GET_WORD(((char *)wndPtr->class->wExtra) + offset);
735             WIN_ReleaseWndPtr(wndPtr);
736             return retvalue;
737         }
738     }
739     else switch(offset)
740     {
741         case GCW_HBRBACKGROUND: return wndPtr->class->hbrBackground;
742         case GCW_HCURSOR:       return wndPtr->class->hCursor;
743         case GCW_HICON:         return wndPtr->class->hIcon;
744         case GCW_HICONSM:       return wndPtr->class->hIconSm;
745         case GCW_ATOM:          return wndPtr->class->atomName;
746         case GCW_STYLE:
747         case GCW_CBWNDEXTRA:
748         case GCW_CBCLSEXTRA:
749         case GCW_HMODULE:
750             WIN_ReleaseWndPtr(wndPtr);
751             return (WORD)GetClassLongA( hwnd, offset );
752     }
753
754     WIN_ReleaseWndPtr(wndPtr);
755     WARN(class, "Invalid offset %d\n", offset);
756     return 0;
757 }
758
759
760 /***********************************************************************
761  *           GetClassLong16    (USER.131)
762  */
763 LONG WINAPI GetClassLong16( HWND16 hwnd, INT16 offset )
764 {
765     WND *wndPtr;
766     LONG ret;
767
768     TRACE(class,"%x %x\n",hwnd, offset);
769
770     switch( offset )
771     {
772     case GCL_WNDPROC:
773         if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
774         ret = (LONG)WINPROC_GetProc( wndPtr->class->winproc, WIN_PROC_16 );
775         WIN_ReleaseWndPtr(wndPtr);
776         return ret;
777     case GCL_MENUNAME:
778         ret = GetClassLongA( hwnd, offset );
779         return (LONG)SEGPTR_GET( (void *)ret );
780     default:
781         return GetClassLongA( hwnd, offset );
782     }
783 }
784
785
786 /***********************************************************************
787  *           GetClassLong32A    (USER32.215)
788  */
789 LONG WINAPI GetClassLongA( HWND hwnd, INT offset )
790 {
791     WND * wndPtr;
792     LONG retvalue;
793     
794     TRACE(class,"%x %x\n",hwnd, offset);
795     
796     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
797     if (offset >= 0)
798     {
799         if (offset <= wndPtr->class->cbClsExtra - sizeof(LONG))
800         {
801             retvalue = GET_DWORD(((char *)wndPtr->class->wExtra) + offset);
802             goto END;
803         }
804     }
805         
806     switch(offset)
807     {
808         case GCL_STYLE:      retvalue = (LONG)wndPtr->class->style;
809                              goto END;
810         case GCL_CBWNDEXTRA: retvalue = (LONG)wndPtr->class->cbWndExtra;
811                              goto END;
812         case GCL_CBCLSEXTRA: retvalue = (LONG)wndPtr->class->cbClsExtra;
813                              goto END;
814         case GCL_HMODULE:    retvalue = (LONG)wndPtr->class->hInstance;
815                              goto END;
816         case GCL_WNDPROC:
817             retvalue = (LONG)WINPROC_GetProc(wndPtr->class->winproc, WIN_PROC_32A);
818             goto END;
819         case GCL_MENUNAME:
820             retvalue = (LONG)CLASS_GetMenuNameA( wndPtr->class );
821             goto END;
822         case GCW_ATOM:
823         case GCL_HBRBACKGROUND:
824         case GCL_HCURSOR:
825         case GCL_HICON:
826         case GCL_HICONSM:
827             retvalue = GetClassWord( hwnd, offset );
828             goto END;
829     }
830     WARN(class, "Invalid offset %d\n", offset);
831     retvalue = 0;
832 END:
833     WIN_ReleaseWndPtr(wndPtr);
834     return retvalue;
835 }
836
837
838 /***********************************************************************
839  *           GetClassLong32W    (USER32.216)
840  */
841 LONG WINAPI GetClassLongW( HWND hwnd, INT offset )
842 {
843     WND * wndPtr;
844     LONG retvalue;
845
846     TRACE(class,"%x %x\n",hwnd, offset);
847
848     switch(offset)
849     {
850     case GCL_WNDPROC:
851         if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
852         retvalue = (LONG)WINPROC_GetProc( wndPtr->class->winproc, WIN_PROC_32W );
853         WIN_ReleaseWndPtr(wndPtr);
854         return retvalue;
855     case GCL_MENUNAME:
856         if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
857         retvalue = (LONG)CLASS_GetMenuNameW( wndPtr->class );
858         WIN_ReleaseWndPtr(wndPtr);
859         return retvalue;
860     default:
861         return GetClassLongA( hwnd, offset );
862     }
863 }
864
865
866 /***********************************************************************
867  *           SetClassWord16    (USER.130)
868  */
869 WORD WINAPI SetClassWord16( HWND16 hwnd, INT16 offset, WORD newval )
870 {
871     return SetClassWord( hwnd, offset, newval );
872 }
873
874
875 /***********************************************************************
876  *           SetClassWord32    (USER32.469)
877  */
878 WORD WINAPI SetClassWord( HWND hwnd, INT offset, WORD newval )
879 {
880     WND * wndPtr;
881     WORD retval = 0;
882     void *ptr;
883     
884     TRACE(class,"%x %x %x\n",hwnd, offset, newval);
885     
886     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
887     if (offset >= 0)
888     {
889         if (offset + sizeof(WORD) <= wndPtr->class->cbClsExtra)
890             ptr = ((char *)wndPtr->class->wExtra) + offset;
891         else
892         {
893             WARN( class, "Invalid offset %d\n", offset );
894             WIN_ReleaseWndPtr(wndPtr);
895             return 0;
896         }
897     }
898     else switch(offset)
899     {
900         case GCW_STYLE:
901         case GCW_CBWNDEXTRA:
902         case GCW_CBCLSEXTRA:
903         case GCW_HMODULE:
904             WIN_ReleaseWndPtr(wndPtr);
905             return (WORD)SetClassLongA( hwnd, offset, (LONG)newval );
906         case GCW_HBRBACKGROUND: ptr = &wndPtr->class->hbrBackground; break;
907         case GCW_HCURSOR:       ptr = &wndPtr->class->hCursor; break;
908         case GCW_HICON:         ptr = &wndPtr->class->hIcon; break;
909         case GCW_HICONSM:       ptr = &wndPtr->class->hIconSm; break;
910         case GCW_ATOM:          ptr = &wndPtr->class->atomName; break;
911         default:
912             WARN( class, "Invalid offset %d\n", offset);
913             WIN_ReleaseWndPtr(wndPtr);
914             return 0;
915     }
916     retval = GET_WORD(ptr);
917     PUT_WORD( ptr, newval );
918     
919     /* Note: If the GCW_ATOM was changed, this means that the WNDCLASS className fields
920     need to be updated as well.  Problem is that we can't tell whether the atom is 
921     using wide or narrow characters.  For now, we'll just NULL out the className 
922     fields, and emit a FIXME. */
923     if (offset == GCW_ATOM)
924     {
925         CLASS_SetClassNameA( wndPtr->class, NULL );
926         FIXME(class,"GCW_ATOM changed for a class.  Not updating className, so GetClassInfoEx may not return correct className!\n");
927     }
928     WIN_ReleaseWndPtr(wndPtr);
929     return retval;
930 }
931
932
933 /***********************************************************************
934  *           SetClassLong16    (USER.132)
935  */
936 LONG WINAPI SetClassLong16( HWND16 hwnd, INT16 offset, LONG newval )
937 {
938     WND *wndPtr;
939     LONG retval;
940
941     TRACE(class,"%x %x %lx\n",hwnd, offset, newval);
942
943     switch(offset)
944     {
945     case GCL_WNDPROC:
946         if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
947         retval = (LONG)WINPROC_GetProc( wndPtr->class->winproc, WIN_PROC_16 );
948         WINPROC_SetProc( &wndPtr->class->winproc, (WNDPROC16)newval,
949                          WIN_PROC_16, WIN_PROC_CLASS );
950         WIN_ReleaseWndPtr(wndPtr);
951         return retval;
952     case GCL_MENUNAME:
953         return SetClassLongA( hwnd, offset, (LONG)PTR_SEG_TO_LIN(newval) );
954     default:
955         return SetClassLongA( hwnd, offset, newval );
956     }
957 }
958
959
960 /***********************************************************************
961  *           SetClassLong32A    (USER32.467)
962  */
963 LONG WINAPI SetClassLongA( HWND hwnd, INT offset, LONG newval )
964 {
965     WND * wndPtr;
966     LONG retval = 0;
967     void *ptr;
968     
969     TRACE(class,"%x %x %lx\n",hwnd, offset, newval);
970         
971     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
972     if (offset >= 0)
973     {
974         if (offset + sizeof(LONG) <= wndPtr->class->cbClsExtra)
975             ptr = ((char *)wndPtr->class->wExtra) + offset;
976         else
977         {
978             WARN( class, "Invalid offset %d\n", offset );
979             retval = 0;
980             goto END;
981         }
982     }
983     else switch(offset)
984     {
985         case GCL_MENUNAME:
986             CLASS_SetMenuNameA( wndPtr->class, (LPCSTR)newval );
987             retval = 0;  /* Old value is now meaningless anyway */
988             goto END;
989         case GCL_WNDPROC:
990             retval = (LONG)WINPROC_GetProc( wndPtr->class->winproc,
991                                             WIN_PROC_32A );
992             WINPROC_SetProc( &wndPtr->class->winproc, (WNDPROC16)newval,
993                              WIN_PROC_32A, WIN_PROC_CLASS );
994             goto END;
995         case GCL_HBRBACKGROUND:
996         case GCL_HCURSOR:
997         case GCL_HICON:
998         case GCL_HICONSM:
999             retval = SetClassWord( hwnd, offset, (WORD)newval );
1000             goto END;
1001         case GCL_STYLE:      ptr = &wndPtr->class->style; break;
1002         case GCL_CBWNDEXTRA: ptr = &wndPtr->class->cbWndExtra; break;
1003         case GCL_CBCLSEXTRA: ptr = &wndPtr->class->cbClsExtra; break;
1004         case GCL_HMODULE:    ptr = &wndPtr->class->hInstance; break;
1005         default:
1006             WARN( class, "Invalid offset %d\n", offset );
1007             retval = 0;
1008             goto END;
1009     }
1010     retval = GET_DWORD(ptr);
1011     PUT_DWORD( ptr, newval );
1012 END:
1013     WIN_ReleaseWndPtr(wndPtr);
1014     return retval;
1015 }
1016
1017
1018 /***********************************************************************
1019  *           SetClassLong32W    (USER32.468)
1020  */
1021 LONG WINAPI SetClassLongW( HWND hwnd, INT offset, LONG newval )
1022 {
1023     WND *wndPtr;
1024     LONG retval;
1025
1026     TRACE(class,"%x %x %lx\n",hwnd, offset, newval);
1027     
1028     switch(offset)
1029     {
1030     case GCL_WNDPROC:
1031         if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1032         retval = (LONG)WINPROC_GetProc( wndPtr->class->winproc, WIN_PROC_32W );
1033         WINPROC_SetProc( &wndPtr->class->winproc, (WNDPROC16)newval,
1034                          WIN_PROC_32W, WIN_PROC_CLASS );
1035         WIN_ReleaseWndPtr(wndPtr);
1036         return retval;
1037     case GCL_MENUNAME:
1038         if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1039         CLASS_SetMenuNameW( wndPtr->class, (LPCWSTR)newval );
1040         WIN_ReleaseWndPtr(wndPtr);
1041         return 0;  /* Old value is now meaningless anyway */
1042     default:
1043         return SetClassLongA( hwnd, offset, newval );
1044     }
1045 }
1046
1047
1048 /***********************************************************************
1049  *           GetClassName16      (USER.58)
1050  */
1051 INT16 WINAPI GetClassName16( HWND16 hwnd, LPSTR buffer, INT16 count )
1052 {
1053     WND *wndPtr;
1054     INT16 retvalue;
1055     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1056     retvalue = GlobalGetAtomName16( wndPtr->class->atomName, buffer, count );
1057     WIN_ReleaseWndPtr(wndPtr);
1058     return retvalue;
1059 }
1060
1061
1062 /***********************************************************************
1063  *           GetClassName32A      (USER32.217)
1064  */
1065 INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
1066 {   INT ret;
1067     WND *wndPtr;
1068             
1069     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1070     ret = GlobalGetAtomNameA( wndPtr->class->atomName, buffer, count );
1071
1072     WIN_ReleaseWndPtr(wndPtr);
1073     TRACE(class,"%x %s %x\n",hwnd, buffer, count);
1074     return ret;
1075 }
1076
1077
1078 /***********************************************************************
1079  *           GetClassName32W      (USER32.218)
1080  */
1081 INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
1082 {   INT ret;
1083     WND *wndPtr;
1084
1085     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1086     ret = GlobalGetAtomNameW( wndPtr->class->atomName, buffer, count );
1087     WIN_ReleaseWndPtr(wndPtr);
1088     TRACE(class,"%x %s %x\n",hwnd, debugstr_w(buffer), count);
1089     
1090     return ret;
1091 }
1092
1093
1094 /***********************************************************************
1095  *           GetClassInfo16      (USER.404)
1096  */
1097 BOOL16 WINAPI GetClassInfo16( HINSTANCE16 hInstance, SEGPTR name,
1098                               WNDCLASS16 *wc )
1099 {
1100     ATOM atom;
1101     CLASS *classPtr;
1102
1103     TRACE(class,"%x %p %p\n",hInstance, PTR_SEG_TO_LIN (name), wc);
1104     
1105     hInstance = GetExePtr( hInstance );
1106     if (!(atom = GlobalFindAtom16( name )) ||
1107         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )))
1108         return FALSE;
1109     if ((hInstance != classPtr->hInstance) &&
1110         !(classPtr->style & CS_GLOBALCLASS)) /*BWCC likes to pass hInstance=0*/
1111         return FALSE;
1112     wc->style         = (UINT16)classPtr->style;
1113     wc->lpfnWndProc   = WINPROC_GetProc( classPtr->winproc, WIN_PROC_16 );
1114     wc->cbClsExtra    = (INT16)classPtr->cbClsExtra;
1115     wc->cbWndExtra    = (INT16)classPtr->cbWndExtra;
1116     wc->hInstance     = (HINSTANCE16)classPtr->hInstance;
1117     wc->hIcon         = classPtr->hIcon;
1118     wc->hCursor       = classPtr->hCursor;
1119     wc->hbrBackground = classPtr->hbrBackground;
1120     wc->lpszClassName = (SEGPTR)CLASS_GetClassNameA( classPtr );;
1121     if (HIWORD(wc->lpszClassName))  /* Make it a SEGPTR */
1122         wc->lpszClassName = SEGPTR_GET( (LPSTR)wc->lpszClassName );
1123     wc->lpszMenuName  = (SEGPTR)CLASS_GetMenuNameA( classPtr );
1124     if (HIWORD(wc->lpszMenuName))  /* Make it a SEGPTR */
1125         wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
1126     return TRUE;
1127 }
1128
1129
1130 /***********************************************************************
1131  *           GetClassInfo32A      (USER32.211)
1132  */
1133 BOOL WINAPI GetClassInfoA( HINSTANCE hInstance, LPCSTR name,
1134                                WNDCLASSA *wc )
1135 {
1136     ATOM atom;
1137     CLASS *classPtr;
1138
1139     TRACE(class,"%x %p %p\n",hInstance, name, wc);
1140
1141     /* workaround: if hInstance=NULL you expect to get the system classes
1142     but this classes (as example from comctl32.dll SysListView) won't be
1143     registred with hInstance=NULL in WINE because of the late loading
1144     of this dll. fixes file dialogs in WinWord95 (jsch)*/
1145
1146     if (!(atom=GlobalFindAtomA(name)) || !(classPtr=CLASS_FindClassByAtom(atom,hInstance)))
1147         return FALSE;
1148
1149     if  (classPtr->hInstance && (hInstance != classPtr->hInstance))
1150     {
1151         if (hInstance) return FALSE;
1152         else    
1153             WARN(class,"systemclass %s (hInst=0) demanded but only class with hInst!=0 found\n",name);
1154     }
1155
1156     wc->style         = classPtr->style;
1157     wc->lpfnWndProc   = (WNDPROC)WINPROC_GetProc( classPtr->winproc,
1158                                                     WIN_PROC_32A );
1159     wc->cbClsExtra    = classPtr->cbClsExtra;
1160     wc->cbWndExtra    = classPtr->cbWndExtra;
1161     wc->hInstance     = classPtr->hInstance;
1162     wc->hIcon         = (HICON)classPtr->hIcon;
1163     wc->hCursor       = (HCURSOR)classPtr->hCursor;
1164     wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1165     wc->lpszMenuName  = CLASS_GetMenuNameA( classPtr );
1166     wc->lpszClassName = CLASS_GetClassNameA( classPtr );
1167     return TRUE;
1168 }
1169
1170
1171 /***********************************************************************
1172  *           GetClassInfo32W      (USER32.214)
1173  */
1174 BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name,
1175                                WNDCLASSW *wc )
1176 {
1177     ATOM atom;
1178     CLASS *classPtr;
1179
1180     TRACE(class,"%x %p %p\n",hInstance, name, wc);
1181
1182     if (!(atom = GlobalFindAtomW( name )) ||
1183         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1184         (classPtr->hInstance && (hInstance != classPtr->hInstance)))
1185         return FALSE;
1186
1187     wc->style         = classPtr->style;
1188     wc->lpfnWndProc   = (WNDPROC)WINPROC_GetProc( classPtr->winproc,
1189                                                     WIN_PROC_32W );
1190     wc->cbClsExtra    = classPtr->cbClsExtra;
1191     wc->cbWndExtra    = classPtr->cbWndExtra;
1192     wc->hInstance     = classPtr->hInstance;
1193     wc->hIcon         = (HICON)classPtr->hIcon;
1194     wc->hCursor       = (HCURSOR)classPtr->hCursor;
1195     wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1196     wc->lpszMenuName  = CLASS_GetMenuNameW( classPtr );
1197     wc->lpszClassName = CLASS_GetClassNameW( classPtr );
1198     return TRUE;
1199 }
1200
1201
1202 /***********************************************************************
1203  *           GetClassInfoEx16      (USER.398)
1204  *
1205  * FIXME: this is just a guess, I have no idea if GetClassInfoEx() is the
1206  * same in Win16 as in Win32. --AJ
1207  */
1208 BOOL16 WINAPI GetClassInfoEx16( HINSTANCE16 hInstance, SEGPTR name,
1209                                 WNDCLASSEX16 *wc )
1210 {
1211     ATOM atom;
1212     CLASS *classPtr;
1213
1214     TRACE(class,"%x %p %p\n",hInstance,PTR_SEG_TO_LIN( name ), wc);
1215     
1216     hInstance = GetExePtr( hInstance );
1217     if (!(atom = GlobalFindAtom16( name )) ||
1218         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1219         (hInstance != classPtr->hInstance)) return FALSE;
1220     wc->style         = classPtr->style;
1221     wc->lpfnWndProc   = WINPROC_GetProc( classPtr->winproc, WIN_PROC_16 );
1222     wc->cbClsExtra    = (INT16)classPtr->cbClsExtra;
1223     wc->cbWndExtra    = (INT16)classPtr->cbWndExtra;
1224     wc->hInstance     = (HINSTANCE16)classPtr->hInstance;
1225     wc->hIcon         = classPtr->hIcon;
1226     wc->hIconSm       = classPtr->hIconSm;
1227     wc->hCursor       = classPtr->hCursor;
1228     wc->hbrBackground = classPtr->hbrBackground;
1229     wc->lpszClassName = (SEGPTR)0;
1230     wc->lpszMenuName  = (SEGPTR)CLASS_GetMenuNameA( classPtr );
1231     if (HIWORD(wc->lpszMenuName))  /* Make it a SEGPTR */
1232         wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
1233     wc->lpszClassName  = (SEGPTR)CLASS_GetClassNameA( classPtr );
1234     if (HIWORD(wc->lpszClassName))  /* Make it a SEGPTR */
1235         wc->lpszClassName = SEGPTR_GET( (LPSTR)wc->lpszClassName );
1236     return TRUE;
1237 }
1238
1239
1240 /***********************************************************************
1241  *           GetClassInfoEx32A      (USER32.212)
1242  */
1243 BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name,
1244                                  WNDCLASSEXA *wc )
1245 {
1246     ATOM atom;
1247     CLASS *classPtr;
1248
1249     TRACE(class,"%x %p %p\n",hInstance, name, wc);
1250     
1251     if (!(atom = GlobalFindAtomA( name )) ||
1252         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) 
1253         /*|| (hInstance != classPtr->hInstance) */ ) return FALSE;
1254     wc->style         = classPtr->style;
1255     wc->lpfnWndProc   = (WNDPROC)WINPROC_GetProc( classPtr->winproc,
1256                                                     WIN_PROC_32A );
1257     wc->cbClsExtra    = classPtr->cbClsExtra;
1258     wc->cbWndExtra    = classPtr->cbWndExtra;
1259     wc->hInstance     = classPtr->hInstance;
1260     wc->hIcon         = (HICON)classPtr->hIcon;
1261     wc->hIconSm       = (HICON)classPtr->hIconSm;
1262     wc->hCursor       = (HCURSOR)classPtr->hCursor;
1263     wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1264     wc->lpszMenuName  = CLASS_GetMenuNameA( classPtr );
1265     wc->lpszClassName  = CLASS_GetClassNameA( classPtr );
1266     return TRUE;
1267 }
1268
1269
1270 /***********************************************************************
1271  *           GetClassInfoEx32W      (USER32.213)
1272  */
1273 BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name,
1274                                  WNDCLASSEXW *wc )
1275 {
1276     ATOM atom;
1277     CLASS *classPtr;
1278
1279     TRACE(class,"%x %p %p\n",hInstance, name, wc);
1280     
1281     if (!(atom = GlobalFindAtomW( name )) ||
1282         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1283         (hInstance != classPtr->hInstance)) return FALSE;
1284     wc->style         = classPtr->style;
1285     wc->lpfnWndProc   = (WNDPROC)WINPROC_GetProc( classPtr->winproc,
1286                                                     WIN_PROC_32W );
1287     wc->cbClsExtra    = classPtr->cbClsExtra;
1288     wc->cbWndExtra    = classPtr->cbWndExtra;
1289     wc->hInstance     = classPtr->hInstance;
1290     wc->hIcon         = (HICON)classPtr->hIcon;
1291     wc->hIconSm       = (HICON)classPtr->hIconSm;
1292     wc->hCursor       = (HCURSOR)classPtr->hCursor;
1293     wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1294     wc->lpszMenuName  = CLASS_GetMenuNameW( classPtr );
1295     wc->lpszClassName = CLASS_GetClassNameW( classPtr );;
1296     return TRUE;
1297 }
1298
1299
1300 /***********************************************************************
1301  *           ClassFirst      (TOOLHELP.69)
1302  */
1303 BOOL16 WINAPI ClassFirst16( CLASSENTRY *pClassEntry )
1304 {
1305     TRACE(class,"%p\n",pClassEntry);
1306     pClassEntry->wNext = 1;
1307     return ClassNext16( pClassEntry );
1308 }
1309
1310
1311 /***********************************************************************
1312  *           ClassNext      (TOOLHELP.70)
1313  */
1314 BOOL16 WINAPI ClassNext16( CLASSENTRY *pClassEntry )
1315 {
1316     int i;
1317     CLASS *class = firstClass;
1318
1319     TRACE(class,"%p\n",pClassEntry);
1320    
1321     if (!pClassEntry->wNext) return FALSE;
1322     for (i = 1; (i < pClassEntry->wNext) && class; i++) class = class->next;
1323     if (!class)
1324     {
1325         pClassEntry->wNext = 0;
1326         return FALSE;
1327     }
1328     pClassEntry->hInst = class->hInstance;
1329     pClassEntry->wNext++;
1330     GlobalGetAtomNameA( class->atomName, pClassEntry->szClassName,
1331                           sizeof(pClassEntry->szClassName) );
1332     return TRUE;
1333 }