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