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