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