Release 970914
[wine] / windows / class.c
1 /*
2  * Window classes functions
3  *
4  * Copyright 1993, 1996 Alexandre Julliard
5  *
6  * FIXME: In win32 all classes are local. They are registered at 
7  *        program start. Processes CANNOT share classes. (Source: some
8  *        win31->NT migration book)
9  */
10
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include "class.h"
15 #include "heap.h"
16 #include "win.h"
17 #include "dce.h"
18 #include "atom.h"
19 #include "ldt.h"
20 #include "toolhelp.h"
21 #include "winproc.h"
22 #include "stddebug.h"
23 #include "debug.h"
24
25
26 static CLASS *firstClass = NULL;
27
28
29 /***********************************************************************
30  *           CLASS_DumpClass
31  *
32  * Dump the content of a class structure to stderr.
33  */
34 void CLASS_DumpClass( CLASS *ptr )
35 {
36     char className[80];
37     int i;
38
39     if (ptr->magic != CLASS_MAGIC)
40     {
41         fprintf( stderr, "%p is not a class\n", ptr );
42         return;
43     }
44
45     GlobalGetAtomName32A( ptr->atomName, className, sizeof(className) );
46
47     fprintf( stderr, "Class %p:\n", ptr );
48     fprintf( stderr,
49              "next=%p  name=%04x '%s'  style=%08x  wndProc=%08x\n"
50              "inst=%04x  dce=%08x  icon=%04x  cursor=%04x  bkgnd=%04x\n"
51              "clsExtra=%d  winExtra=%d  #windows=%d\n",
52              ptr->next, ptr->atomName, className, ptr->style,
53              (UINT32)ptr->winproc, ptr->hInstance, (UINT32)ptr->dce,
54              ptr->hIcon, ptr->hCursor, ptr->hbrBackground,
55              ptr->cbClsExtra, ptr->cbWndExtra, ptr->cWindows );
56     if (ptr->cbClsExtra)
57     {
58         fprintf( stderr, "extra bytes:" );
59         for (i = 0; i < ptr->cbClsExtra; i++)
60             fprintf( stderr, " %02x", *((BYTE *)ptr->wExtra+i) );
61         fprintf( stderr, "\n" );
62     }
63     fprintf( stderr, "\n" );
64 }
65
66
67 /***********************************************************************
68  *           CLASS_WalkClasses
69  *
70  * Walk the class list and print each class on stderr.
71  */
72 void CLASS_WalkClasses(void)
73 {
74     CLASS *ptr;
75     char className[80];
76
77     fprintf( stderr, " Class   Name                  Style   WndProc\n" );
78     for (ptr = firstClass; ptr; ptr = ptr->next)
79     {
80         GlobalGetAtomName32A( ptr->atomName, className, sizeof(className) );
81         fprintf( stderr, "%08x %-20.20s %08x %08x\n", (UINT32)ptr, className,
82                  ptr->style, (UINT32)ptr->winproc );
83     }
84     fprintf( stderr, "\n" );
85 }
86
87
88 /***********************************************************************
89  *           CLASS_GetMenuNameA
90  *
91  * Get the menu name as a ASCII string.
92  */
93 static LPSTR CLASS_GetMenuNameA( CLASS *classPtr )
94 {
95     if (!classPtr->menuNameA && classPtr->menuNameW)
96     {
97         /* We need to copy the Unicode string */
98         classPtr->menuNameA = SEGPTR_STRDUP_WtoA( classPtr->menuNameW );
99     }
100     return classPtr->menuNameA;
101 }
102
103
104 /***********************************************************************
105  *           CLASS_GetMenuNameW
106  *
107  * Get the menu name as a Unicode string.
108  */
109 static LPWSTR CLASS_GetMenuNameW( CLASS *classPtr )
110 {
111     if (!classPtr->menuNameW && classPtr->menuNameA)
112     {
113         if (!HIWORD(classPtr->menuNameA))
114             return (LPWSTR)classPtr->menuNameA;
115         /* Now we need to copy the ASCII string */
116         classPtr->menuNameW = HEAP_strdupAtoW( SystemHeap, 0,
117                                                classPtr->menuNameA );
118     }
119     return classPtr->menuNameW;
120 }
121
122
123 /***********************************************************************
124  *           CLASS_SetMenuNameA
125  *
126  * Set the menu name in a class structure by copying the string.
127  */
128 static void CLASS_SetMenuNameA( CLASS *classPtr, LPCSTR name )
129 {
130     if (HIWORD(classPtr->menuNameA)) SEGPTR_FREE( classPtr->menuNameA );
131     if (classPtr->menuNameW) HeapFree( SystemHeap, 0, classPtr->menuNameW );
132     classPtr->menuNameA = SEGPTR_STRDUP( name );
133     classPtr->menuNameW = 0;
134 }
135
136
137 /***********************************************************************
138  *           CLASS_SetMenuNameW
139  *
140  * Set the menu name in a class structure by copying the string.
141  */
142 static void CLASS_SetMenuNameW( CLASS *classPtr, LPCWSTR name )
143 {
144     if (!HIWORD(name))
145     {
146         CLASS_SetMenuNameA( classPtr, (LPCSTR)name );
147         return;
148     }
149     if (HIWORD(classPtr->menuNameA)) SEGPTR_FREE( classPtr->menuNameA );
150     if (classPtr->menuNameW) HeapFree( SystemHeap, 0, classPtr->menuNameW );
151     if ((classPtr->menuNameW = HeapAlloc( SystemHeap, 0,
152                                          (lstrlen32W(name)+1)*sizeof(WCHAR) )))
153         lstrcpy32W( classPtr->menuNameW, name );
154     classPtr->menuNameA = 0;
155 }
156
157
158 /***********************************************************************
159  *           CLASS_FreeClass
160  *
161  * Free a class structure.
162  */
163 static BOOL32 CLASS_FreeClass( CLASS *classPtr )
164 {
165     CLASS **ppClass;
166
167     /* Check if we can remove this class */
168
169     if (classPtr->cWindows > 0) return FALSE;
170
171     /* Remove the class from the linked list */
172
173     for (ppClass = &firstClass; *ppClass; ppClass = &(*ppClass)->next)
174         if (*ppClass == classPtr) break;
175     if (!*ppClass)
176     {
177         fprintf(stderr, "ERROR: Class list corrupted\n" );
178         return FALSE;
179     }
180     *ppClass = classPtr->next;
181
182     /* Delete the class */
183
184     if (classPtr->dce) DCE_FreeDCE( classPtr->dce );
185     if (classPtr->hbrBackground) DeleteObject32( classPtr->hbrBackground );
186     GlobalDeleteAtom( classPtr->atomName );
187     CLASS_SetMenuNameA( classPtr, NULL );
188     WINPROC_FreeProc( classPtr->winproc, WIN_PROC_CLASS );
189     HeapFree( SystemHeap, 0, classPtr );
190     return TRUE;
191 }
192
193
194 /***********************************************************************
195  *           CLASS_FreeModuleClasses
196  */
197 void CLASS_FreeModuleClasses( HMODULE16 hModule )
198 {
199     CLASS *ptr, *next;
200   
201     for (ptr = firstClass; ptr; ptr = next)
202     {
203         next = ptr->next;
204         if (ptr->hInstance == hModule) CLASS_FreeClass( ptr );
205     }
206 }
207
208
209 /***********************************************************************
210  *           CLASS_FindClassByAtom
211  *
212  * Return a pointer to the class.
213  * hinstance has been normalized by the caller.
214  */
215 CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE32 hinstance )
216 {
217     CLASS * class;
218
219     /* First search task-specific classes */
220
221     for (class = firstClass; (class); class = class->next)
222     {
223         if (class->style & CS_GLOBALCLASS) continue;
224         if ((class->atomName == atom) && 
225             ((hinstance == 0xffff) ||
226              (hinstance == class->hInstance))) return class;
227     }
228     
229       /* Then search global classes */
230
231     for (class = firstClass; (class); class = class->next)
232     {
233         if (!(class->style & CS_GLOBALCLASS)) continue;
234         if (class->atomName == atom) return class;
235     }
236
237     return 0;
238 }
239
240
241 /***********************************************************************
242  *           CLASS_RegisterClass
243  *
244  * The real RegisterClass() functionality.
245  */
246 static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE32 hInstance,
247                                    DWORD style, INT32 classExtra,
248                                    INT32 winExtra, WNDPROC16 wndProc,
249                                    WINDOWPROCTYPE wndProcType )
250 {
251     CLASS *classPtr;
252
253     /* Check if a class with this name already exists */
254
255     classPtr = CLASS_FindClassByAtom( atom, hInstance );
256     if (classPtr)
257     {
258         /* Class can be created only if it is local and */
259         /* if the class with the same name is global.   */
260
261         if (style & CS_GLOBALCLASS) return NULL;
262         if (!(classPtr->style & CS_GLOBALCLASS)) return NULL;
263     }
264
265     /* Fix the extra bytes value */
266
267     if (classExtra < 0) classExtra = 0;
268     else if (classExtra > 40)  /* Extra bytes are limited to 40 in Win32 */
269         fprintf(stderr, "Warning: class extra bytes %d is > 40\n", classExtra);
270     if (winExtra < 0) winExtra = 0;
271     else if (winExtra > 40)    /* Extra bytes are limited to 40 in Win32 */
272         fprintf( stderr, "Warning: win extra bytes %d is > 40\n", winExtra );
273
274     /* Create the class */
275
276     classPtr = (CLASS *)HeapAlloc( SystemHeap, 0, sizeof(CLASS) +
277                                        classExtra - sizeof(classPtr->wExtra) );
278     if (!classPtr) return NULL;
279     classPtr->next        = firstClass;
280     classPtr->magic       = CLASS_MAGIC;
281     classPtr->cWindows    = 0;  
282     classPtr->style       = style;
283     classPtr->winproc     = (HWINDOWPROC)0;
284     classPtr->cbWndExtra  = winExtra;
285     classPtr->cbClsExtra  = classExtra;
286     classPtr->hInstance   = hInstance;
287     classPtr->atomName    = atom;
288     classPtr->menuNameA   = 0;
289     classPtr->menuNameW   = 0;
290     classPtr->dce         = (style & CS_CLASSDC) ?
291                                  DCE_AllocDCE( 0, DCE_CLASS_DC ) : NULL;
292
293     WINPROC_SetProc( &classPtr->winproc, wndProc, wndProcType, WIN_PROC_CLASS);
294
295     /* Other values must be set by caller */
296
297     if (classExtra) memset( classPtr->wExtra, 0, classExtra );
298     firstClass = classPtr;
299     return classPtr;
300 }
301
302
303 /***********************************************************************
304  *           RegisterClass16    (USER.57)
305  */
306 ATOM WINAPI RegisterClass16( const WNDCLASS16 *wc )
307 {
308     ATOM atom;
309     CLASS *classPtr;
310     HINSTANCE16 hInstance=GetExePtr(wc->hInstance);
311
312     if (!(atom = GlobalAddAtom16( wc->lpszClassName ))) return 0;
313     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
314                                           wc->cbClsExtra, wc->cbWndExtra,
315                                           wc->lpfnWndProc, WIN_PROC_16 )))
316     {
317         GlobalDeleteAtom( atom );
318         return 0;
319     }
320
321     dprintf_class( stddeb, "RegisterClass16: atom=%04x wndproc=%08lx hinst=%04x
322 bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
323                    atom, (DWORD)wc->lpfnWndProc, hInstance,
324                    wc->hbrBackground, wc->style, wc->cbClsExtra,
325                    wc->cbWndExtra, classPtr,
326                    HIWORD(wc->lpszClassName) ?
327                        (char *)PTR_SEG_TO_LIN(wc->lpszClassName) : "" );
328
329     classPtr->hIcon         = wc->hIcon;
330     classPtr->hIconSm       = 0;
331     classPtr->hCursor       = wc->hCursor;
332     classPtr->hbrBackground = wc->hbrBackground;
333
334     CLASS_SetMenuNameA( classPtr, HIWORD(wc->lpszMenuName) ?
335                  PTR_SEG_TO_LIN(wc->lpszMenuName) : (LPCSTR)wc->lpszMenuName );
336     return atom;
337 }
338
339
340 /***********************************************************************
341  *           RegisterClass32A      (USER32.426)
342  */
343 ATOM WINAPI RegisterClass32A( const WNDCLASS32A* wc )
344 {
345     ATOM atom;
346     CLASS *classPtr;
347
348     if (!(atom = GlobalAddAtom32A( wc->lpszClassName ))) return 0;
349     if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
350                                           wc->cbClsExtra, wc->cbWndExtra,
351                                           (WNDPROC16)wc->lpfnWndProc,
352                                           WIN_PROC_32A )))
353     {
354         GlobalDeleteAtom( atom );
355         return 0;
356     }
357
358     dprintf_class( stddeb, "RegisterClass32A: atom=%04x wndproc=%08lx
359 hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
360                    atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
361                    wc->hbrBackground, wc->style, wc->cbClsExtra,
362                    wc->cbWndExtra, classPtr,
363                    HIWORD(wc->lpszClassName) ? wc->lpszClassName : "" );
364     
365     classPtr->hIcon         = (HICON16)wc->hIcon;
366     classPtr->hIconSm       = 0;
367     classPtr->hCursor       = (HCURSOR16)wc->hCursor;
368     classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
369     CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
370     return atom;
371 }
372
373
374 /***********************************************************************
375  *           RegisterClass32W      (USER32.429)
376  */
377 ATOM WINAPI RegisterClass32W( const WNDCLASS32W* wc )
378 {
379     ATOM atom;
380     CLASS *classPtr;
381
382     if (!(atom = GlobalAddAtom32W( wc->lpszClassName ))) return 0;
383     if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
384                                           wc->cbClsExtra, wc->cbWndExtra,
385                                           (WNDPROC16)wc->lpfnWndProc,
386                                           WIN_PROC_32W )))
387     {
388         GlobalDeleteAtom( atom );
389         return 0;
390     }
391
392     dprintf_class( stddeb, "RegisterClass32W: atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
393                    atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
394                    wc->hbrBackground, wc->style, wc->cbClsExtra,
395                    wc->cbWndExtra, classPtr );
396     
397     classPtr->hIcon         = (HICON16)wc->hIcon;
398     classPtr->hIconSm       = 0;
399     classPtr->hCursor       = (HCURSOR16)wc->hCursor;
400     classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
401     CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
402     return atom;
403 }
404
405
406 /***********************************************************************
407  *           RegisterClassEx16    (USER.397)
408  */
409 ATOM WINAPI RegisterClassEx16( const WNDCLASSEX16 *wc )
410 {
411     ATOM atom;
412     CLASS *classPtr;
413     HINSTANCE16 hInstance = GetExePtr( wc->hInstance );
414
415     if (!(atom = GlobalAddAtom16( wc->lpszClassName ))) return 0;
416     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
417                                           wc->cbClsExtra, wc->cbWndExtra,
418                                           wc->lpfnWndProc, WIN_PROC_16 )))
419     {
420         GlobalDeleteAtom( atom );
421         return 0;
422     }
423
424     dprintf_class( stddeb, "RegisterClassEx16: atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
425                    atom, (DWORD)wc->lpfnWndProc, hInstance,
426                    wc->hbrBackground, wc->style, wc->cbClsExtra,
427                    wc->cbWndExtra, classPtr );
428     
429     classPtr->hIcon         = wc->hIcon;
430     classPtr->hIconSm       = wc->hIconSm;
431     classPtr->hCursor       = wc->hCursor;
432     classPtr->hbrBackground = wc->hbrBackground;
433
434     CLASS_SetMenuNameA( classPtr, HIWORD(wc->lpszMenuName) ?
435                  PTR_SEG_TO_LIN(wc->lpszMenuName) : (LPCSTR)wc->lpszMenuName );
436     return atom;
437 }
438
439
440 /***********************************************************************
441  *           RegisterClassEx32A      (USER32.427)
442  */
443 ATOM WINAPI RegisterClassEx32A( const WNDCLASSEX32A* wc )
444 {
445     ATOM atom;
446     CLASS *classPtr;
447
448     if (!(atom = GlobalAddAtom32A( wc->lpszClassName ))) return 0;
449     if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
450                                           wc->cbClsExtra, wc->cbWndExtra,
451                                           (WNDPROC16)wc->lpfnWndProc,
452                                           WIN_PROC_32A )))
453     {
454         GlobalDeleteAtom( atom );
455         return 0;
456     }
457
458     dprintf_class( stddeb, "RegisterClassEx32A: atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
459                    atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
460                    wc->hbrBackground, wc->style, wc->cbClsExtra,
461                    wc->cbWndExtra, classPtr );
462     
463     classPtr->hIcon         = (HICON16)wc->hIcon;
464     classPtr->hIconSm       = (HICON16)wc->hIconSm;
465     classPtr->hCursor       = (HCURSOR16)wc->hCursor;
466     classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
467     CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
468     return atom;
469 }
470
471
472 /***********************************************************************
473  *           RegisterClassEx32W      (USER32.428)
474  */
475 ATOM WINAPI RegisterClassEx32W( const WNDCLASSEX32W* wc )
476 {
477     ATOM atom;
478     CLASS *classPtr;
479
480     if (!(atom = GlobalAddAtom32W( wc->lpszClassName ))) return 0;
481     if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
482                                           wc->cbClsExtra, wc->cbWndExtra,
483                                           (WNDPROC16)wc->lpfnWndProc,
484                                           WIN_PROC_32W )))
485     {
486         GlobalDeleteAtom( atom );
487         return 0;
488     }
489
490     dprintf_class( stddeb, "RegisterClassEx32W: atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
491                    atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
492                    wc->hbrBackground, wc->style, wc->cbClsExtra,
493                    wc->cbWndExtra, classPtr );
494     
495     classPtr->hIcon         = (HICON16)wc->hIcon;
496     classPtr->hIconSm       = (HICON16)wc->hIconSm;
497     classPtr->hCursor       = (HCURSOR16)wc->hCursor;
498     classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
499     CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
500     return atom;
501 }
502
503
504 /***********************************************************************
505  *           UnregisterClass16    (USER.403)
506  */
507 BOOL16 WINAPI UnregisterClass16( SEGPTR className, HINSTANCE16 hInstance )
508 {
509     CLASS *classPtr;
510     ATOM atom;
511
512     hInstance = GetExePtr( hInstance );
513     if (!(atom = GlobalFindAtom16( className ))) return FALSE;
514     if (!(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
515         (classPtr->hInstance != hInstance)) return FALSE;
516     return CLASS_FreeClass( classPtr );
517 }
518
519
520 /***********************************************************************
521  *           UnregisterClass32A    (USER32.562)
522  */
523 BOOL32 WINAPI UnregisterClass32A( LPCSTR className, HINSTANCE32 hInstance )
524 {
525     CLASS *classPtr;
526     ATOM atom;
527
528     if (!(atom = GlobalFindAtom32A( className ))) return FALSE;
529     if (!(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
530         (classPtr->hInstance != hInstance)) return FALSE;
531     return CLASS_FreeClass( classPtr );
532 }
533
534
535 /***********************************************************************
536  *           UnregisterClass32W    (USER32.563)
537  */
538 BOOL32 WINAPI UnregisterClass32W( LPCWSTR className, HINSTANCE32 hInstance )
539 {
540     CLASS *classPtr;
541     ATOM atom;
542
543     if (!(atom = GlobalFindAtom32W( className ))) return FALSE;
544     if (!(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
545         (classPtr->hInstance != hInstance)) return FALSE;
546     return CLASS_FreeClass( classPtr );
547 }
548
549
550 /***********************************************************************
551  *           GetClassWord16    (USER.129)
552  */
553 WORD WINAPI GetClassWord16( HWND16 hwnd, INT16 offset )
554 {
555     return GetClassWord32( hwnd, offset );
556 }
557
558
559 /***********************************************************************
560  *           GetClassWord32    (USER32.218)
561  */
562 WORD WINAPI GetClassWord32( HWND32 hwnd, INT32 offset )
563 {
564     WND * wndPtr;
565     
566     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
567     if (offset >= 0)
568     {
569         if (offset <= wndPtr->class->cbClsExtra - sizeof(WORD))
570             return GET_WORD(((char *)wndPtr->class->wExtra) + offset);
571     }
572     else switch(offset)
573     {
574         case GCW_HBRBACKGROUND: return wndPtr->class->hbrBackground;
575         case GCW_HCURSOR:       return wndPtr->class->hCursor;
576         case GCW_HICON:         return wndPtr->class->hIcon;
577         case GCW_HICONSM:       return wndPtr->class->hIconSm;
578         case GCW_ATOM:          return wndPtr->class->atomName;
579         case GCW_STYLE:
580         case GCW_CBWNDEXTRA:
581         case GCW_CBCLSEXTRA:
582         case GCW_HMODULE:
583             return (WORD)GetClassLong32A( hwnd, offset );
584     }
585     fprintf(stderr, "Warning: invalid offset %d for GetClassWord()\n", offset);
586     return 0;
587 }
588
589
590 /***********************************************************************
591  *           GetClassLong16    (USER.131)
592  */
593 LONG WINAPI GetClassLong16( HWND16 hwnd, INT16 offset )
594 {
595     WND *wndPtr;
596     LONG ret;
597
598     switch( offset )
599     {
600     case GCL_WNDPROC:
601         if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
602         return (LONG)WINPROC_GetProc( wndPtr->class->winproc, WIN_PROC_16 );
603     case GCL_MENUNAME:
604         ret = GetClassLong32A( hwnd, offset );
605         return (LONG)SEGPTR_GET( (void *)ret );
606     default:
607         return GetClassLong32A( hwnd, offset );
608     }
609 }
610
611
612 /***********************************************************************
613  *           GetClassLong32A    (USER32.214)
614  */
615 LONG WINAPI GetClassLong32A( HWND32 hwnd, INT32 offset )
616 {
617     WND * wndPtr;
618     
619     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
620     if (offset >= 0)
621     {
622         if (offset <= wndPtr->class->cbClsExtra - sizeof(LONG))
623             return GET_DWORD(((char *)wndPtr->class->wExtra) + offset);
624     }
625     switch(offset)
626     {
627         case GCL_STYLE:      return (LONG)wndPtr->class->style;
628         case GCL_CBWNDEXTRA: return (LONG)wndPtr->class->cbWndExtra;
629         case GCL_CBCLSEXTRA: return (LONG)wndPtr->class->cbClsExtra;
630         case GCL_HMODULE:    return (LONG)wndPtr->class->hInstance;
631         case GCL_WNDPROC:
632             return (LONG)WINPROC_GetProc(wndPtr->class->winproc, WIN_PROC_32A);
633         case GCL_MENUNAME:
634             return (LONG)CLASS_GetMenuNameA( wndPtr->class );
635         case GCL_HBRBACKGROUND:
636         case GCL_HCURSOR:
637         case GCL_HICON:
638         case GCL_HICONSM:
639             return GetClassWord32( hwnd, offset );
640     }
641     fprintf(stderr, "Warning: invalid offset %d for GetClassLong()\n", offset);
642     return 0;
643 }
644
645
646 /***********************************************************************
647  *           GetClassLong32W    (USER32.215)
648  */
649 LONG WINAPI GetClassLong32W( HWND32 hwnd, INT32 offset )
650 {
651     WND * wndPtr;
652
653     switch(offset)
654     {
655     case GCL_WNDPROC:
656         if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
657         return (LONG)WINPROC_GetProc( wndPtr->class->winproc, WIN_PROC_32W );
658     case GCL_MENUNAME:
659         if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
660         return (LONG)CLASS_GetMenuNameW( wndPtr->class );
661     default:
662         return GetClassLong32A( hwnd, offset );
663     }
664 }
665
666
667 /***********************************************************************
668  *           SetClassWord16    (USER.130)
669  */
670 WORD WINAPI SetClassWord16( HWND16 hwnd, INT16 offset, WORD newval )
671 {
672     return SetClassWord32( hwnd, offset, newval );
673 }
674
675
676 /***********************************************************************
677  *           SetClassWord32    (USER32.468)
678  */
679 WORD WINAPI SetClassWord32( HWND32 hwnd, INT32 offset, WORD newval )
680 {
681     WND * wndPtr;
682     WORD retval = 0;
683     void *ptr;
684     
685     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
686     if (offset >= 0)
687     {
688         if (offset + sizeof(WORD) <= wndPtr->class->cbClsExtra)
689             ptr = ((char *)wndPtr->class->wExtra) + offset;
690         else
691         {
692             fprintf( stderr, "Warning: invalid offset %d for SetClassWord()\n",
693                      offset );
694             return 0;
695         }
696     }
697     else switch(offset)
698     {
699         case GCW_STYLE:
700         case GCW_CBWNDEXTRA:
701         case GCW_CBCLSEXTRA:
702         case GCW_HMODULE:
703             return (WORD)SetClassLong32A( hwnd, offset, (LONG)newval );
704         case GCW_HBRBACKGROUND: ptr = &wndPtr->class->hbrBackground; break;
705         case GCW_HCURSOR:       ptr = &wndPtr->class->hCursor; break;
706         case GCW_HICON:         ptr = &wndPtr->class->hIcon; break;
707         case GCW_HICONSM:       ptr = &wndPtr->class->hIconSm; break;
708         case GCW_ATOM:          ptr = &wndPtr->class->atomName; break;
709         default:
710             fprintf( stderr, "Warning: invalid offset %d for SetClassWord()\n",
711                      offset);
712             return 0;
713     }
714     retval = GET_WORD(ptr);
715     PUT_WORD( ptr, newval );
716     return retval;
717 }
718
719
720 /***********************************************************************
721  *           SetClassLong16    (USER.132)
722  */
723 LONG WINAPI SetClassLong16( HWND16 hwnd, INT16 offset, LONG newval )
724 {
725     WND *wndPtr;
726     LONG retval;
727
728     switch(offset)
729     {
730     case GCL_WNDPROC:
731         if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
732         retval = (LONG)WINPROC_GetProc( wndPtr->class->winproc, WIN_PROC_16 );
733         WINPROC_SetProc( &wndPtr->class->winproc, (WNDPROC16)newval,
734                          WIN_PROC_16, WIN_PROC_CLASS );
735         return retval;
736     case GCL_MENUNAME:
737         return SetClassLong32A( hwnd, offset, (LONG)PTR_SEG_TO_LIN(newval) );
738     default:
739         return SetClassLong32A( hwnd, offset, newval );
740     }
741 }
742
743
744 /***********************************************************************
745  *           SetClassLong32A    (USER32.466)
746  */
747 LONG WINAPI SetClassLong32A( HWND32 hwnd, INT32 offset, LONG newval )
748 {
749     WND * wndPtr;
750     LONG retval = 0;
751     void *ptr;
752     
753     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
754     if (offset >= 0)
755     {
756         if (offset + sizeof(LONG) <= wndPtr->class->cbClsExtra)
757             ptr = ((char *)wndPtr->class->wExtra) + offset;
758         else
759         {
760             fprintf( stderr, "Warning: invalid offset %d for SetClassLong()\n",
761                      offset );
762             return 0;
763         }
764     }
765     else switch(offset)
766     {
767         case GCL_MENUNAME:
768             CLASS_SetMenuNameA( wndPtr->class, (LPCSTR)newval );
769             return 0;  /* Old value is now meaningless anyway */
770         case GCL_WNDPROC:
771             retval = (LONG)WINPROC_GetProc( wndPtr->class->winproc,
772                                             WIN_PROC_32A );
773             WINPROC_SetProc( &wndPtr->class->winproc, (WNDPROC16)newval,
774                              WIN_PROC_32A, WIN_PROC_CLASS );
775             return retval;
776         case GCL_HBRBACKGROUND:
777         case GCL_HCURSOR:
778         case GCL_HICON:
779         case GCL_HICONSM:
780             return SetClassWord32( hwnd, offset, (WORD)newval );
781         case GCL_STYLE:      ptr = &wndPtr->class->style; break;
782         case GCL_CBWNDEXTRA: ptr = &wndPtr->class->cbWndExtra; break;
783         case GCL_CBCLSEXTRA: ptr = &wndPtr->class->cbClsExtra; break;
784         case GCL_HMODULE:    ptr = &wndPtr->class->hInstance; break;
785         default:
786             fprintf( stderr, "Warning: invalid offset %d for SetClassLong()\n",
787                      offset);
788             return 0;
789     }
790     retval = GET_DWORD(ptr);
791     PUT_DWORD( ptr, newval );
792     return retval;
793 }
794
795
796 /***********************************************************************
797  *           SetClassLong32W    (USER32.467)
798  */
799 LONG WINAPI SetClassLong32W( HWND32 hwnd, INT32 offset, LONG newval )
800 {
801     WND *wndPtr;
802     LONG retval;
803
804     switch(offset)
805     {
806     case GCL_WNDPROC:
807         if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
808         retval = (LONG)WINPROC_GetProc( wndPtr->class->winproc, WIN_PROC_32W );
809         WINPROC_SetProc( &wndPtr->class->winproc, (WNDPROC16)newval,
810                          WIN_PROC_32W, WIN_PROC_CLASS );
811         return retval;
812     case GCL_MENUNAME:
813         if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
814         CLASS_SetMenuNameW( wndPtr->class, (LPCWSTR)newval );
815         return 0;  /* Old value is now meaningless anyway */
816     default:
817         return SetClassLong32A( hwnd, offset, newval );
818     }
819 }
820
821
822 /***********************************************************************
823  *           GetClassName16      (USER.58)
824  */
825 INT16 WINAPI GetClassName16( HWND16 hwnd, LPSTR buffer, INT16 count )
826 {
827     WND *wndPtr;
828     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
829     return GlobalGetAtomName16( wndPtr->class->atomName, buffer, count );
830 }
831
832
833 /***********************************************************************
834  *           GetClassName32A      (USER32.216)
835  */
836 INT32 WINAPI GetClassName32A( HWND32 hwnd, LPSTR buffer, INT32 count )
837 {
838     WND *wndPtr;
839     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
840     return GlobalGetAtomName32A( wndPtr->class->atomName, buffer, count );
841 }
842
843
844 /***********************************************************************
845  *           GetClassName32W      (USER32.217)
846  */
847 INT32 WINAPI GetClassName32W( HWND32 hwnd, LPWSTR buffer, INT32 count )
848 {
849     WND *wndPtr;
850     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
851     return GlobalGetAtomName32W( wndPtr->class->atomName, buffer, count );
852 }
853
854
855 /***********************************************************************
856  *           GetClassInfo16      (USER.404)
857  */
858 BOOL16 WINAPI GetClassInfo16( HINSTANCE16 hInstance, SEGPTR name,
859                               WNDCLASS16 *wc )
860 {
861     ATOM atom;
862     CLASS *classPtr;
863
864     hInstance = GetExePtr( hInstance );
865     if (!(atom = GlobalFindAtom16( name )) ||
866         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )))
867         return FALSE;
868     if ((hInstance != classPtr->hInstance) &&
869         !(classPtr->style & CS_GLOBALCLASS)) /*BWCC likes to pass hInstance=0*/
870         return FALSE;
871     wc->style         = (UINT16)classPtr->style;
872     wc->lpfnWndProc   = WINPROC_GetProc( classPtr->winproc, WIN_PROC_16 );
873     wc->cbClsExtra    = (INT16)classPtr->cbClsExtra;
874     wc->cbWndExtra    = (INT16)classPtr->cbWndExtra;
875     wc->hInstance     = (HINSTANCE16)classPtr->hInstance;
876     wc->hIcon         = classPtr->hIcon;
877     wc->hCursor       = classPtr->hCursor;
878     wc->hbrBackground = classPtr->hbrBackground;
879     wc->lpszClassName = (SEGPTR)0;
880     wc->lpszMenuName  = (SEGPTR)CLASS_GetMenuNameA( classPtr );
881     if (HIWORD(wc->lpszMenuName))  /* Make it a SEGPTR */
882         wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
883     return TRUE;
884 }
885
886
887 /***********************************************************************
888  *           GetClassInfo32A      (USER32.210)
889  */
890 BOOL32 WINAPI GetClassInfo32A( HINSTANCE32 hInstance, LPCSTR name,
891                                WNDCLASS32A *wc )
892 {
893     ATOM atom;
894     CLASS *classPtr;
895
896     if (!(atom = GlobalFindAtom32A( name )) ||
897         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
898         (classPtr->hInstance && (hInstance != classPtr->hInstance)))
899         return FALSE;
900
901     wc->style         = classPtr->style;
902     wc->lpfnWndProc   = (WNDPROC32)WINPROC_GetProc( classPtr->winproc,
903                                                     WIN_PROC_32A );
904     wc->cbClsExtra    = classPtr->cbClsExtra;
905     wc->cbWndExtra    = classPtr->cbWndExtra;
906     wc->hInstance     = classPtr->hInstance;
907     wc->hIcon         = (HICON32)classPtr->hIcon;
908     wc->hCursor       = (HCURSOR32)classPtr->hCursor;
909     wc->hbrBackground = (HBRUSH32)classPtr->hbrBackground;
910     wc->lpszMenuName  = CLASS_GetMenuNameA( classPtr );
911     wc->lpszClassName = NULL;
912     return TRUE;
913 }
914
915
916 /***********************************************************************
917  *           GetClassInfo32W      (USER32.213)
918  */
919 BOOL32 WINAPI GetClassInfo32W( HINSTANCE32 hInstance, LPCWSTR name,
920                                WNDCLASS32W *wc )
921 {
922     ATOM atom;
923     CLASS *classPtr;
924
925     if (!(atom = GlobalFindAtom32W( name )) ||
926         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
927         (classPtr->hInstance && (hInstance != classPtr->hInstance)))
928         return FALSE;
929
930     wc->style         = classPtr->style;
931     wc->lpfnWndProc   = (WNDPROC32)WINPROC_GetProc( classPtr->winproc,
932                                                     WIN_PROC_32W );
933     wc->cbClsExtra    = classPtr->cbClsExtra;
934     wc->cbWndExtra    = classPtr->cbWndExtra;
935     wc->hInstance     = classPtr->hInstance;
936     wc->hIcon         = (HICON32)classPtr->hIcon;
937     wc->hCursor       = (HCURSOR32)classPtr->hCursor;
938     wc->hbrBackground = (HBRUSH32)classPtr->hbrBackground;
939     wc->lpszMenuName  = CLASS_GetMenuNameW( classPtr );
940     wc->lpszClassName = NULL;
941     return TRUE;
942 }
943
944
945 /***********************************************************************
946  *           GetClassInfoEx16      (USER.398)
947  *
948  * FIXME: this is just a guess, I have no idea if GetClassInfoEx() is the
949  * same in Win16 as in Win32. --AJ
950  */
951 BOOL16 WINAPI GetClassInfoEx16( HINSTANCE16 hInstance, SEGPTR name,
952                                 WNDCLASSEX16 *wc )
953 {
954     ATOM atom;
955     CLASS *classPtr;
956
957     hInstance = GetExePtr( hInstance );
958     if (!(atom = GlobalFindAtom16( name )) ||
959         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
960         (hInstance != classPtr->hInstance)) return FALSE;
961     wc->style         = classPtr->style;
962     wc->lpfnWndProc   = WINPROC_GetProc( classPtr->winproc, WIN_PROC_16 );
963     wc->cbClsExtra    = (INT16)classPtr->cbClsExtra;
964     wc->cbWndExtra    = (INT16)classPtr->cbWndExtra;
965     wc->hInstance     = (HINSTANCE16)classPtr->hInstance;
966     wc->hIcon         = classPtr->hIcon;
967     wc->hIconSm       = classPtr->hIconSm;
968     wc->hCursor       = classPtr->hCursor;
969     wc->hbrBackground = classPtr->hbrBackground;
970     wc->lpszClassName = (SEGPTR)0;
971     wc->lpszMenuName  = (SEGPTR)CLASS_GetMenuNameA( classPtr );
972     if (HIWORD(wc->lpszMenuName))  /* Make it a SEGPTR */
973         wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
974     return TRUE;
975 }
976
977
978 /***********************************************************************
979  *           GetClassInfoEx32A      (USER32.211)
980  */
981 BOOL32 WINAPI GetClassInfoEx32A( HINSTANCE32 hInstance, LPCSTR name,
982                                  WNDCLASSEX32A *wc )
983 {
984     ATOM atom;
985     CLASS *classPtr;
986
987     if (!(atom = GlobalFindAtom32A( name )) ||
988         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
989         (hInstance != classPtr->hInstance)) return FALSE;
990     wc->style         = classPtr->style;
991     wc->lpfnWndProc   = (WNDPROC32)WINPROC_GetProc( classPtr->winproc,
992                                                     WIN_PROC_32A );
993     wc->cbClsExtra    = classPtr->cbClsExtra;
994     wc->cbWndExtra    = classPtr->cbWndExtra;
995     wc->hInstance     = classPtr->hInstance;
996     wc->hIcon         = (HICON32)classPtr->hIcon;
997     wc->hIconSm       = (HICON32)classPtr->hIconSm;
998     wc->hCursor       = (HCURSOR32)classPtr->hCursor;
999     wc->hbrBackground = (HBRUSH32)classPtr->hbrBackground;
1000     wc->lpszMenuName  = CLASS_GetMenuNameA( classPtr );
1001     wc->lpszClassName = NULL;
1002     return TRUE;
1003 }
1004
1005
1006 /***********************************************************************
1007  *           GetClassInfoEx32W      (USER32.212)
1008  */
1009 BOOL32 WINAPI GetClassInfoEx32W( HINSTANCE32 hInstance, LPCWSTR name,
1010                                  WNDCLASSEX32W *wc )
1011 {
1012     ATOM atom;
1013     CLASS *classPtr;
1014
1015     if (!(atom = GlobalFindAtom32W( name )) ||
1016         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1017         (hInstance != classPtr->hInstance)) return FALSE;
1018     wc->style         = classPtr->style;
1019     wc->lpfnWndProc   = (WNDPROC32)WINPROC_GetProc( classPtr->winproc,
1020                                                     WIN_PROC_32W );
1021     wc->cbClsExtra    = classPtr->cbClsExtra;
1022     wc->cbWndExtra    = classPtr->cbWndExtra;
1023     wc->hInstance     = classPtr->hInstance;
1024     wc->hIcon         = (HICON32)classPtr->hIcon;
1025     wc->hIconSm       = (HICON32)classPtr->hIconSm;
1026     wc->hCursor       = (HCURSOR32)classPtr->hCursor;
1027     wc->hbrBackground = (HBRUSH32)classPtr->hbrBackground;
1028     wc->lpszMenuName  = CLASS_GetMenuNameW( classPtr );
1029     wc->lpszClassName = NULL;
1030     return TRUE;
1031 }
1032
1033
1034 /***********************************************************************
1035  *           ClassFirst      (TOOLHELP.69)
1036  */
1037 BOOL16 WINAPI ClassFirst( CLASSENTRY *pClassEntry )
1038 {
1039     pClassEntry->wNext = 1;
1040     return ClassNext( pClassEntry );
1041 }
1042
1043
1044 /***********************************************************************
1045  *           ClassNext      (TOOLHELP.70)
1046  */
1047 BOOL16 WINAPI ClassNext( CLASSENTRY *pClassEntry )
1048 {
1049     int i;
1050     CLASS *class = firstClass;
1051
1052     if (!pClassEntry->wNext) return FALSE;
1053     for (i = 1; (i < pClassEntry->wNext) && class; i++) class = class->next;
1054     if (!class)
1055     {
1056         pClassEntry->wNext = 0;
1057         return FALSE;
1058     }
1059     pClassEntry->hInst = class->hInstance;
1060     pClassEntry->wNext++;
1061     GlobalGetAtomName32A( class->atomName, pClassEntry->szClassName,
1062                           sizeof(pClassEntry->szClassName) );
1063     return TRUE;
1064 }