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