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