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