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