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