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