Release 960611
[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=%08x\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              ptr->winproc, 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, ptr->winproc );
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                                         lstrlen32W(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                                          (lstrlen32W(name)+1)*sizeof(WCHAR) )))
153         lstrcpy32W( 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 HANDLE32 CLASS_SetWndProc( CLASS *classPtr, HANDLE32 proc,
164                                   WINDOWPROCTYPE type )
165 {
166     HANDLE32 oldProc = classPtr->winproc;
167     classPtr->winproc = WINPROC_AllocWinProc( proc, type );
168     if (oldProc) WINPROC_FreeWinProc( oldProc );
169     return oldProc;
170 }
171
172
173 /***********************************************************************
174  *           CLASS_FreeClass
175  *
176  * Free a class structure.
177  */
178 static BOOL CLASS_FreeClass( CLASS *classPtr )
179 {
180     CLASS **ppClass;
181
182     /* Check if we can remove this class */
183
184     if (classPtr->cWindows > 0) return FALSE;
185
186     /* Remove the class from the linked list */
187
188     for (ppClass = &firstClass; *ppClass; ppClass = &(*ppClass)->next)
189         if (*ppClass == classPtr) break;
190     if (!*ppClass)
191     {
192         fprintf(stderr, "ERROR: Class list corrupted\n" );
193         return FALSE;
194     }
195     *ppClass = classPtr->next;
196
197     /* Delete the class */
198
199     if (classPtr->hdce) DCE_FreeDCE( classPtr->hdce );
200     if (classPtr->hbrBackground) DeleteObject( classPtr->hbrBackground );
201     GlobalDeleteAtom( classPtr->atomName );
202     CLASS_SetMenuNameA( classPtr, NULL );
203     CLASS_SetWndProc( classPtr, (WNDPROC16)0, WIN_PROC_16 );
204     HeapFree( SystemHeap, 0, classPtr );
205     return TRUE;
206 }
207
208
209 /***********************************************************************
210  *           CLASS_FreeModuleClasses
211  */
212 void CLASS_FreeModuleClasses( HMODULE hModule )
213 {
214     CLASS *ptr, *next;
215   
216     for (ptr = firstClass; ptr; ptr = next)
217     {
218         next = ptr->next;
219         if (ptr->hInstance == hModule) CLASS_FreeClass( ptr );
220     }
221 }
222
223
224 /***********************************************************************
225  *           CLASS_FindClassByAtom
226  *
227  * Return a pointer to the class.
228  */
229 CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE16 hinstance )
230 {
231     CLASS * class;
232
233       /* First search task-specific classes */
234
235     for (class = firstClass; (class); class = class->next)
236     {
237         if (class->style & CS_GLOBALCLASS) continue;
238         if ((class->atomName == atom) && 
239             ((hinstance==(HINSTANCE16)0xffff) ||
240              (hinstance == class->hInstance))) return class;
241     }
242     
243       /* Then search global classes */
244
245     for (class = firstClass; (class); class = class->next)
246     {
247         if (!(class->style & CS_GLOBALCLASS)) continue;
248         if (class->atomName == atom) return class;
249     }
250
251     return 0;
252 }
253
254
255 /***********************************************************************
256  *           CLASS_FindClassByName
257  *
258  * Return a pointer to the class.
259  */
260 CLASS *CLASS_FindClassByName( SEGPTR name, HINSTANCE hinstance )
261 {
262     ATOM atom;
263
264     if (!(atom = GlobalFindAtom16( name ))) return 0;
265     return CLASS_FindClassByAtom( atom, hinstance );
266 }
267
268
269 /***********************************************************************
270  *           CLASS_RegisterClass
271  *
272  * The real RegisterClass() functionality.
273  */
274 static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE32 hInstance,
275                                    DWORD style, INT32 classExtra,
276                                    INT32 winExtra, HANDLE32 wndProc,
277                                    WINDOWPROCTYPE wndProcType )
278 {
279     CLASS *classPtr;
280
281     /* Check if a class with this name already exists */
282
283     classPtr = CLASS_FindClassByAtom( atom, hInstance );
284     if (classPtr)
285     {
286         /* Class can be created only if it is local and */
287         /* if the class with the same name is global.   */
288
289         if (style & CS_GLOBALCLASS) return NULL;
290         if (!(classPtr->style & CS_GLOBALCLASS)) return NULL;
291     }
292
293     /* Fix the extra bytes value */
294
295     if (classExtra < 0) classExtra = 0;
296     else if (classExtra > 40)  /* Extra bytes are limited to 40 in Win32 */
297         fprintf(stderr, "Warning: class extra bytes %d is > 40\n", classExtra);
298     if (winExtra < 0) winExtra = 0;
299     else if (winExtra > 40)    /* Extra bytes are limited to 40 in Win32 */
300         fprintf( stderr, "Warning: win extra bytes %d is > 40\n", winExtra );
301
302     /* Create the class */
303
304     classPtr = (CLASS *)HeapAlloc( SystemHeap, 0, sizeof(CLASS) +
305                                        classExtra - sizeof(classPtr->wExtra) );
306     if (!classPtr) return NULL;
307     classPtr->next        = firstClass;
308     classPtr->magic       = CLASS_MAGIC;
309     classPtr->cWindows    = 0;  
310     classPtr->style       = style;
311     classPtr->winproc     = 0;
312     classPtr->cbWndExtra  = winExtra;
313     classPtr->cbClsExtra  = classExtra;
314     classPtr->hInstance   = hInstance;
315     classPtr->atomName    = atom;
316     classPtr->menuNameA   = 0;
317     classPtr->menuNameW   = 0;
318     classPtr->hdce        = (style&CS_CLASSDC) ? DCE_AllocDCE(0, DCE_CLASS_DC): 0;
319     CLASS_SetWndProc( classPtr, wndProc, wndProcType );
320     /* Other values must be set by caller */
321
322     if (classExtra) memset( classPtr->wExtra, 0, classExtra );
323     firstClass = classPtr;
324     return classPtr;
325 }
326
327
328 /***********************************************************************
329  *           RegisterClass16    (USER.57)
330  */
331 ATOM RegisterClass16( const WNDCLASS16 *wc )
332 {
333     ATOM atom;
334     CLASS *classPtr;
335
336     HINSTANCE32 hInstance = (HINSTANCE32)GetExePtr( wc->hInstance );
337
338     if (!(atom = GlobalAddAtom16( wc->lpszClassName ))) return 0;
339     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
340                                           wc->cbClsExtra, wc->cbWndExtra,
341                                           (HANDLE32)wc->lpfnWndProc,
342                                           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                                           (HANDLE32)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                                           (HANDLE32)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                                           (HANDLE32)wc->lpfnWndProc,
448                                           WIN_PROC_16 )))
449     {
450         GlobalDeleteAtom( atom );
451         return 0;
452     }
453
454     dprintf_class( stddeb, "RegisterClassEx16: atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
455                    atom, (DWORD)wc->lpfnWndProc, hInstance,
456                    wc->hbrBackground, wc->style, wc->cbClsExtra,
457                    wc->cbWndExtra, classPtr );
458     
459     classPtr->hIcon         = wc->hIcon;
460     classPtr->hIconSm       = wc->hIconSm;
461     classPtr->hCursor       = wc->hCursor;
462     classPtr->hbrBackground = wc->hbrBackground;
463
464     CLASS_SetMenuNameA( classPtr, HIWORD(wc->lpszMenuName) ?
465                  PTR_SEG_TO_LIN(wc->lpszMenuName) : (LPCSTR)wc->lpszMenuName );
466     return atom;
467 }
468
469
470 /***********************************************************************
471  *           RegisterClassEx32A      (USER32.427)
472  */
473 ATOM RegisterClassEx32A( const WNDCLASSEX32A* wc )
474 {
475     ATOM atom;
476     CLASS *classPtr;
477
478     /* FIXME: this should not be necessary for Win32 */
479     HINSTANCE32 hInstance = (HINSTANCE32)GetExePtr( wc->hInstance );
480
481     if (!(atom = GlobalAddAtom32A( wc->lpszClassName ))) return 0;
482     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
483                                           wc->cbClsExtra, wc->cbWndExtra,
484                                           (HANDLE32)wc->lpfnWndProc,
485                                           WIN_PROC_32A )))
486     {
487         GlobalDeleteAtom( atom );
488         return 0;
489     }
490
491     dprintf_class( stddeb, "RegisterClassEx32A: atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
492                    atom, (DWORD)wc->lpfnWndProc, hInstance,
493                    wc->hbrBackground, wc->style, wc->cbClsExtra,
494                    wc->cbWndExtra, classPtr );
495     
496     classPtr->hIcon         = (HICON16)wc->hIcon;
497     classPtr->hIconSm       = (HICON16)wc->hIconSm;
498     classPtr->hCursor       = (HCURSOR16)wc->hCursor;
499     classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
500     CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
501     return atom;
502 }
503
504
505 /***********************************************************************
506  *           RegisterClassEx32W      (USER32.428)
507  */
508 ATOM RegisterClassEx32W( const WNDCLASSEX32W* wc )
509 {
510     ATOM atom;
511     CLASS *classPtr;
512
513     /* FIXME: this should not be necessary for Win32 */
514     HINSTANCE32 hInstance = (HINSTANCE32)GetExePtr( wc->hInstance );
515
516     if (!(atom = GlobalAddAtom32W( wc->lpszClassName ))) return 0;
517     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
518                                           wc->cbClsExtra, wc->cbWndExtra,
519                                           (HANDLE32)wc->lpfnWndProc,
520                                           WIN_PROC_32W )))
521     {
522         GlobalDeleteAtom( atom );
523         return 0;
524     }
525
526     dprintf_class( stddeb, "RegisterClassEx32W: atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
527                    atom, (DWORD)wc->lpfnWndProc, hInstance,
528                    wc->hbrBackground, wc->style, wc->cbClsExtra,
529                    wc->cbWndExtra, classPtr );
530     
531     classPtr->hIcon         = (HICON16)wc->hIcon;
532     classPtr->hIconSm       = (HICON16)wc->hIconSm;
533     classPtr->hCursor       = (HCURSOR16)wc->hCursor;
534     classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
535     CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
536     return atom;
537 }
538
539
540 /***********************************************************************
541  *           UnregisterClass16    (USER.403)
542  */
543 BOOL16 UnregisterClass16( SEGPTR className, HINSTANCE16 hInstance )
544 {
545     CLASS *classPtr;
546     ATOM atom;
547
548     hInstance = GetExePtr( hInstance );
549     if (!(atom = GlobalFindAtom16( className ))) return FALSE;
550     if (!(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
551         (classPtr->hInstance != hInstance)) return FALSE;
552     return CLASS_FreeClass( classPtr );
553 }
554
555
556 /***********************************************************************
557  *           UnregisterClass32A    (USER32.562)
558  */
559 BOOL32 UnregisterClass32A( LPCSTR className, HINSTANCE32 hInstance )
560 {
561     CLASS *classPtr;
562     ATOM atom;
563
564     hInstance = GetExePtr( hInstance );  /* FIXME: not needed in Win32 */
565     if (!(atom = GlobalFindAtom32A( className ))) return FALSE;
566     if (!(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
567         (classPtr->hInstance != hInstance)) return FALSE;
568     return CLASS_FreeClass( classPtr );
569 }
570
571
572 /***********************************************************************
573  *           UnregisterClass32W    (USER32.563)
574  */
575 BOOL32 UnregisterClass32W( LPCWSTR className, HINSTANCE32 hInstance )
576 {
577     CLASS *classPtr;
578     ATOM atom;
579
580     hInstance = GetExePtr( hInstance );  /* FIXME: not needed in Win32 */
581     if (!(atom = GlobalFindAtom32W( className ))) return FALSE;
582     if (!(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
583         (classPtr->hInstance != hInstance)) return FALSE;
584     return CLASS_FreeClass( classPtr );
585 }
586
587
588 /***********************************************************************
589  *           GetClassWord    (USER.129) (USER32.218)
590  */
591 WORD GetClassWord( HWND32 hwnd, INT32 offset )
592 {
593     WND * wndPtr;
594     
595     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
596     if (offset >= 0)
597     {
598         if (offset <= wndPtr->class->cbClsExtra - sizeof(WORD))
599             return GET_WORD(((char *)wndPtr->class->wExtra) + offset);
600     }
601     else switch(offset)
602     {
603         case GCW_HBRBACKGROUND: return wndPtr->class->hbrBackground;
604         case GCW_HCURSOR:       return wndPtr->class->hCursor;
605         case GCW_HICON:         return wndPtr->class->hIcon;
606         case GCW_HICONSM:       return wndPtr->class->hIconSm;
607         case GCW_ATOM:          return wndPtr->class->atomName;
608         case GCW_STYLE:
609         case GCW_CBWNDEXTRA:
610         case GCW_CBCLSEXTRA:
611         case GCW_HMODULE:
612             return (WORD)GetClassLong32A( hwnd, offset );
613     }
614     fprintf(stderr, "Warning: invalid offset %d for GetClassWord()\n", offset);
615     return 0;
616 }
617
618
619 /***********************************************************************
620  *           GetClassLong16    (USER.131)
621  */
622 LONG GetClassLong16( HWND16 hwnd, INT16 offset )
623 {
624     LONG ret;
625
626     switch( offset )
627     {
628     case GCL_MENUNAME:
629         ret = GetClassLong32A( hwnd, offset );
630         return (LONG)SEGPTR_GET( (void *)ret );
631     case GCL_WNDPROC:
632         ret = GetClassLong32A( hwnd, offset );
633         return (LONG)WINPROC_GetFunc16( (HANDLE32)ret );
634     default:
635         return GetClassLong32A( hwnd, offset );
636     }
637     return (LONG)ret;
638 }
639
640
641 /***********************************************************************
642  *           GetClassLong32A    (USER32.214)
643  */
644 LONG GetClassLong32A( HWND32 hwnd, INT32 offset )
645 {
646     WND * wndPtr;
647     
648     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
649     if (offset >= 0)
650     {
651         if (offset <= wndPtr->class->cbClsExtra - sizeof(LONG))
652             return GET_DWORD(((char *)wndPtr->class->wExtra) + offset);
653     }
654     switch(offset)
655     {
656         case GCL_STYLE:      return (LONG)wndPtr->class->style;
657         case GCL_CBWNDEXTRA: return (LONG)wndPtr->class->cbWndExtra;
658         case GCL_CBCLSEXTRA: return (LONG)wndPtr->class->cbClsExtra;
659         case GCL_HMODULE:    return (LONG)wndPtr->class->hInstance;
660         case GCL_WNDPROC:
661             return (LONG)WINPROC_GetFunc32( wndPtr->class->winproc );
662         case GCL_MENUNAME:
663             return (LONG)CLASS_GetMenuNameA( wndPtr->class );
664         case GCL_HBRBACKGROUND:
665         case GCL_HCURSOR:
666         case GCL_HICON:
667         case GCL_HICONSM:
668             return GetClassWord( hwnd, offset );
669     }
670     fprintf(stderr, "Warning: invalid offset %d for GetClassLong()\n", offset);
671     return 0;
672 }
673
674
675 /***********************************************************************
676  *           GetClassLong32W    (USER32.215)
677  */
678 LONG GetClassLong32W( HWND32 hwnd, INT32 offset )
679 {
680     WND * wndPtr;
681     
682     if (offset != GCL_MENUNAME) return GetClassLong32A( hwnd, offset );
683     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
684     return (LONG)CLASS_GetMenuNameW( wndPtr->class );
685 }
686
687
688 /***********************************************************************
689  *           SetClassWord    (USER.130) (USER32.468)
690  */
691 WORD SetClassWord( HWND32 hwnd, INT32 offset, WORD newval )
692 {
693     WND * wndPtr;
694     WORD retval = 0;
695     void *ptr;
696     
697     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
698     if (offset >= 0)
699     {
700         if (offset <= wndPtr->class->cbClsExtra - sizeof(WORD))
701             ptr = ((char *)wndPtr->class->wExtra) + offset;
702         {
703             fprintf( stderr, "Warning: invalid offset %d for SetClassWord()\n",
704                      offset );
705             return 0;
706         }
707     }
708     else switch(offset)
709     {
710         case GCW_STYLE:
711         case GCW_CBWNDEXTRA:
712         case GCW_CBCLSEXTRA:
713         case GCW_HMODULE:
714             return (WORD)SetClassLong32A( hwnd, offset, (LONG)newval );
715         case GCW_HBRBACKGROUND: ptr = &wndPtr->class->hbrBackground; break;
716         case GCW_HCURSOR:       ptr = &wndPtr->class->hCursor; break;
717         case GCW_HICON:         ptr = &wndPtr->class->hIcon; break;
718         case GCW_HICONSM:       ptr = &wndPtr->class->hIconSm; break;
719         case GCW_ATOM:          ptr = &wndPtr->class->atomName; break;
720         default:
721             fprintf( stderr, "Warning: invalid offset %d for SetClassWord()\n",
722                      offset);
723             return 0;
724     }
725     retval = GET_WORD(ptr);
726     PUT_WORD( ptr, newval );
727     return retval;
728 }
729
730
731 /***********************************************************************
732  *           SetClassLong16    (USER.132)
733  */
734 LONG SetClassLong16( HWND16 hwnd, INT16 offset, LONG newval )
735 {
736     WND *wndPtr;
737
738     switch(offset)
739     {
740     case GCL_WNDPROC:
741         if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
742         return (LONG)CLASS_SetWndProc( wndPtr->class, (HANDLE32)newval,
743                                        WIN_PROC_16 );
744     case GCL_MENUNAME:
745         return SetClassLong32A( hwnd, offset, (LONG)PTR_SEG_TO_LIN(newval) );
746     default:
747         return SetClassLong32A( hwnd, offset, newval );
748     }
749 }
750
751
752 /***********************************************************************
753  *           SetClassLong32A    (USER32.466)
754  */
755 LONG SetClassLong32A( HWND32 hwnd, INT32 offset, LONG newval )
756 {
757     WND * wndPtr;
758     LONG retval = 0;
759     void *ptr;
760     
761     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
762     if (offset >= 0)
763     {
764         if (offset <= wndPtr->class->cbClsExtra - sizeof(LONG))
765             ptr = ((char *)wndPtr->class->wExtra) + offset;
766         else
767         {
768             fprintf( stderr, "Warning: invalid offset %d for SetClassLong()\n",
769                      offset );
770             return 0;
771         }
772     }
773     else switch(offset)
774     {
775         case GCL_MENUNAME:
776             CLASS_SetMenuNameA( wndPtr->class, (LPCSTR)newval );
777             return 0;  /* Old value is now meaningless anyway */
778         case GCL_WNDPROC:
779             return (LONG)CLASS_SetWndProc( wndPtr->class, (HANDLE32)newval,
780                                            WIN_PROC_32A );
781         case GCL_HBRBACKGROUND:
782         case GCL_HCURSOR:
783         case GCL_HICON:
784         case GCL_HICONSM:
785             return SetClassWord( hwnd, offset, (WORD)newval );
786         case GCL_STYLE:      ptr = &wndPtr->class->style; break;
787         case GCL_CBWNDEXTRA: ptr = &wndPtr->class->cbWndExtra; break;
788         case GCL_CBCLSEXTRA: ptr = &wndPtr->class->cbClsExtra; break;
789         case GCL_HMODULE:    ptr = &wndPtr->class->hInstance; break;
790         default:
791             fprintf( stderr, "Warning: invalid offset %d for SetClassLong()\n",
792                      offset);
793             return 0;
794     }
795     retval = GET_DWORD(ptr);
796     PUT_DWORD( ptr, newval );
797     return retval;
798 }
799
800
801 /***********************************************************************
802  *           SetClassLong32W    (USER32.467)
803  */
804 LONG SetClassLong32W( HWND32 hwnd, INT32 offset, LONG newval )
805 {
806     WND *wndPtr;
807     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
808
809     switch(offset)
810     {
811     case GCL_WNDPROC:
812         return (LONG)CLASS_SetWndProc( wndPtr->class, (HANDLE32)newval,
813                                        WIN_PROC_32W );
814     case GCL_MENUNAME:
815         CLASS_SetMenuNameW( wndPtr->class, (LPCWSTR)newval );
816         return 0;  /* Old value is now meaningless anyway */
817     default:
818         return SetClassLong32A( hwnd, offset, newval );
819     }
820 }
821
822
823 /***********************************************************************
824  *           GetClassName16      (USER.58)
825  */
826 INT16 GetClassName16( HWND16 hwnd, LPSTR buffer, INT16 count )
827 {
828     WND *wndPtr;
829     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
830     return GlobalGetAtomName16( wndPtr->class->atomName, buffer, count );
831 }
832
833
834 /***********************************************************************
835  *           GetClassName32A      (USER32.216)
836  */
837 INT32 GetClassName32A( HWND32 hwnd, LPSTR buffer, INT32 count )
838 {
839     WND *wndPtr;
840     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
841     return GlobalGetAtomName32A( wndPtr->class->atomName, buffer, count );
842 }
843
844
845 /***********************************************************************
846  *           GetClassName32W      (USER32.217)
847  */
848 INT32 GetClassName32W( HWND32 hwnd, LPWSTR buffer, INT32 count )
849 {
850     WND *wndPtr;
851     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
852     return GlobalGetAtomName32W( wndPtr->class->atomName, buffer, count );
853 }
854
855
856 /***********************************************************************
857  *           GetClassInfo16      (USER.404)
858  */
859 BOOL16 GetClassInfo16( HINSTANCE16 hInstance, SEGPTR name, 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         (hInstance != classPtr->hInstance)) return FALSE;
868     wc->style         = (UINT16)classPtr->style;
869     wc->lpfnWndProc   = WINPROC_GetFunc16( classPtr->winproc );
870     wc->cbClsExtra    = (INT16)classPtr->cbClsExtra;
871     wc->cbWndExtra    = (INT16)classPtr->cbWndExtra;
872     wc->hInstance     = (HINSTANCE16)classPtr->hInstance;
873     wc->hIcon         = classPtr->hIcon;
874     wc->hCursor       = classPtr->hCursor;
875     wc->hbrBackground = classPtr->hbrBackground;
876     wc->lpszClassName = (SEGPTR)0;
877     wc->lpszMenuName  = (SEGPTR)CLASS_GetMenuNameA( classPtr );
878     if (HIWORD(wc->lpszMenuName))  /* Make it a SEGPTR */
879         wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
880     return TRUE;
881 }
882
883
884 /***********************************************************************
885  *           GetClassInfo32A      (USER32.210)
886  */
887 BOOL32 GetClassInfo32A( HINSTANCE32 hInstance, LPCSTR name, WNDCLASS32A *wc )
888 {
889     ATOM atom;
890     CLASS *classPtr;
891
892     hInstance = GetExePtr( hInstance );  /* FIXME: not needed in Win32 */
893     if (!(atom = GlobalFindAtom32A( name )) ||
894         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
895         (hInstance != classPtr->hInstance)) return FALSE;
896     wc->style         = classPtr->style;
897     wc->lpfnWndProc   = WINPROC_GetFunc32( classPtr->winproc );
898     wc->cbClsExtra    = classPtr->cbClsExtra;
899     wc->cbWndExtra    = classPtr->cbWndExtra;
900     wc->hInstance     = classPtr->hInstance;
901     wc->hIcon         = (HICON32)classPtr->hIcon;
902     wc->hCursor       = (HCURSOR32)classPtr->hCursor;
903     wc->hbrBackground = (HBRUSH32)classPtr->hbrBackground;
904     wc->lpszMenuName  = CLASS_GetMenuNameA( classPtr );
905     wc->lpszClassName = NULL;
906     return TRUE;
907 }
908
909
910 /***********************************************************************
911  *           GetClassInfo32W      (USER32.213)
912  */
913 BOOL32 GetClassInfo32W( HINSTANCE32 hInstance, LPCWSTR name, WNDCLASS32W *wc )
914 {
915     ATOM atom;
916     CLASS *classPtr;
917
918     hInstance = GetExePtr( hInstance );  /* FIXME: not needed in Win32 */
919     if (!(atom = GlobalFindAtom32W( name )) ||
920         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
921         (hInstance != classPtr->hInstance)) return FALSE;
922     wc->style         = classPtr->style;
923     wc->lpfnWndProc   = WINPROC_GetFunc32( classPtr->winproc );
924     wc->cbClsExtra    = classPtr->cbClsExtra;
925     wc->cbWndExtra    = classPtr->cbWndExtra;
926     wc->hInstance     = classPtr->hInstance;
927     wc->hIcon         = (HICON32)classPtr->hIcon;
928     wc->hCursor       = (HCURSOR32)classPtr->hCursor;
929     wc->hbrBackground = (HBRUSH32)classPtr->hbrBackground;
930     wc->lpszMenuName  = CLASS_GetMenuNameW( classPtr );
931     wc->lpszClassName = NULL;
932     return TRUE;
933 }
934
935
936 /***********************************************************************
937  *           GetClassInfoEx16      (USER.398)
938  *
939  * FIXME: this is just a guess, I have no idea if GetClassInfoEx() is the
940  * same in Win16 as in Win32. --AJ
941  */
942 BOOL16 GetClassInfoEx16( HINSTANCE16 hInstance, SEGPTR name, WNDCLASSEX16 *wc )
943 {
944     ATOM atom;
945     CLASS *classPtr;
946
947     hInstance = GetExePtr( hInstance );
948     if (!(atom = GlobalFindAtom16( name )) ||
949         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
950         (hInstance != classPtr->hInstance)) return FALSE;
951     wc->style         = classPtr->style;
952     wc->lpfnWndProc   = WINPROC_GetFunc16( classPtr->winproc );
953     wc->cbClsExtra    = (INT16)classPtr->cbClsExtra;
954     wc->cbWndExtra    = (INT16)classPtr->cbWndExtra;
955     wc->hInstance     = (HINSTANCE16)classPtr->hInstance;
956     wc->hIcon         = classPtr->hIcon;
957     wc->hIconSm       = classPtr->hIconSm;
958     wc->hCursor       = classPtr->hCursor;
959     wc->hbrBackground = classPtr->hbrBackground;
960     wc->lpszClassName = (SEGPTR)0;
961     wc->lpszMenuName  = (SEGPTR)CLASS_GetMenuNameA( classPtr );
962     if (HIWORD(wc->lpszMenuName))  /* Make it a SEGPTR */
963         wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
964     return TRUE;
965 }
966
967
968 /***********************************************************************
969  *           GetClassInfoEx32A      (USER32.211)
970  */
971 BOOL32 GetClassInfoEx32A( HINSTANCE32 hInstance, LPCSTR name,
972                           WNDCLASSEX32A *wc )
973 {
974     ATOM atom;
975     CLASS *classPtr;
976
977     hInstance = GetExePtr( hInstance );  /* FIXME: not needed in Win32 */
978     if (!(atom = GlobalFindAtom32A( name )) ||
979         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
980         (hInstance != classPtr->hInstance)) return FALSE;
981     wc->style         = classPtr->style;
982     wc->lpfnWndProc   = WINPROC_GetFunc32( classPtr->winproc );
983     wc->cbClsExtra    = classPtr->cbClsExtra;
984     wc->cbWndExtra    = classPtr->cbWndExtra;
985     wc->hInstance     = classPtr->hInstance;
986     wc->hIcon         = (HICON32)classPtr->hIcon;
987     wc->hIconSm       = (HICON32)classPtr->hIconSm;
988     wc->hCursor       = (HCURSOR32)classPtr->hCursor;
989     wc->hbrBackground = (HBRUSH32)classPtr->hbrBackground;
990     wc->lpszMenuName  = CLASS_GetMenuNameA( classPtr );
991     wc->lpszClassName = NULL;
992     return TRUE;
993 }
994
995
996 /***********************************************************************
997  *           GetClassInfoEx32W      (USER32.212)
998  */
999 BOOL32 GetClassInfoEx32W( HINSTANCE32 hInstance, LPCWSTR name,
1000                           WNDCLASSEX32W *wc )
1001 {
1002     ATOM atom;
1003     CLASS *classPtr;
1004
1005     hInstance = GetExePtr( hInstance );  /* FIXME: not needed in Win32 */
1006     if (!(atom = GlobalFindAtom32W( name )) ||
1007         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1008         (hInstance != classPtr->hInstance)) return FALSE;
1009     wc->style         = classPtr->style;
1010     wc->lpfnWndProc   = WINPROC_GetFunc32( classPtr->winproc );
1011     wc->cbClsExtra    = classPtr->cbClsExtra;
1012     wc->cbWndExtra    = classPtr->cbWndExtra;
1013     wc->hInstance     = classPtr->hInstance;
1014     wc->hIcon         = (HICON32)classPtr->hIcon;
1015     wc->hIconSm       = (HICON32)classPtr->hIconSm;
1016     wc->hCursor       = (HCURSOR32)classPtr->hCursor;
1017     wc->hbrBackground = (HBRUSH32)classPtr->hbrBackground;
1018     wc->lpszMenuName  = CLASS_GetMenuNameW( classPtr );
1019     wc->lpszClassName = NULL;
1020     return TRUE;
1021 }
1022
1023
1024 /***********************************************************************
1025  *           ClassFirst      (TOOLHELP.69)
1026  */
1027 BOOL ClassFirst( CLASSENTRY *pClassEntry )
1028 {
1029     pClassEntry->wNext = 1;
1030     return ClassNext( pClassEntry );
1031 }
1032
1033
1034 /***********************************************************************
1035  *           ClassNext      (TOOLHELP.70)
1036  */
1037 BOOL ClassNext( CLASSENTRY *pClassEntry )
1038 {
1039     int i;
1040     CLASS *class = firstClass;
1041
1042     if (!pClassEntry->wNext) return FALSE;
1043     for (i = 1; (i < pClassEntry->wNext) && class; i++) class = class->next;
1044     if (!class)
1045     {
1046         pClassEntry->wNext = 0;
1047         return FALSE;
1048     }
1049     pClassEntry->hInst = class->hInstance;
1050     pClassEntry->wNext++;
1051     GlobalGetAtomName32A( class->atomName, pClassEntry->szClassName,
1052                           sizeof(pClassEntry->szClassName) );
1053     return TRUE;
1054 }