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