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