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