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