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