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