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