Made all the RegisterClass and GetClassInfo variants call the
[wine] / windows / class.c
1 /*
2  * Window classes functions
3  *
4  * Copyright 1993, 1996 Alexandre Julliard
5  *           1998 Juergen Schmied (jsch)
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  * FIXME: In win32 all classes are local. They are registered at
22  *        program start. Processes CANNOT share classes. (Source: some
23  *        win31->NT migration book)
24  *
25  * FIXME: There seems to be a general problem with hInstance in WINE
26  *   classes are getting registered with wrong hInstance.
27  */
28
29 #include "config.h"
30 #include "wine/port.h"
31
32 #include <stdarg.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include "wine/winbase16.h"
37 #include "winerror.h"
38 #include "windef.h"
39 #include "winbase.h"
40 #include "wingdi.h"
41 #include "wine/winuser16.h"
42 #include "wownt32.h"
43 #include "wine/unicode.h"
44 #include "win.h"
45 #include "user.h"
46 #include "controls.h"
47 #include "dce.h"
48 #include "winproc.h"
49 #include "wine/debug.h"
50
51 WINE_DEFAULT_DEBUG_CHANNEL(class);
52
53 typedef struct tagCLASS
54 {
55     struct tagCLASS *next;          /* Next class */
56     struct tagCLASS *prev;          /* Prev class */
57     UINT             cWindows;      /* Count of existing windows */
58     UINT             style;         /* Class style */
59     WNDPROC          winprocA;      /* Window procedure (ASCII) */
60     WNDPROC          winprocW;      /* Window procedure (Unicode) */
61     INT              cbClsExtra;    /* Class extra bytes */
62     INT              cbWndExtra;    /* Window extra bytes */
63     LPWSTR           menuName;      /* Default menu name (Unicode followed by ASCII) */
64     SEGPTR           segMenuName;   /* Default menu name as SEGPTR */
65     struct tagDCE   *dce;           /* Class DCE (if CS_CLASSDC) */
66     HINSTANCE        hInstance;     /* Module that created the task */
67     HICON            hIcon;         /* Default icon */
68     HICON            hIconSm;       /* Default small icon */
69     HCURSOR          hCursor;       /* Default cursor */
70     HBRUSH           hbrBackground; /* Default background */
71     ATOM             atomName;      /* Name of the class */
72 } CLASS;
73
74 static CLASS *firstClass;
75
76 /***********************************************************************
77  *           get_class_ptr
78  */
79 static CLASS *get_class_ptr( HWND hwnd, BOOL write_access )
80 {
81     WND *ptr = WIN_GetPtr( hwnd );
82
83     if (ptr)
84     {
85         if (ptr != WND_OTHER_PROCESS) return ptr->class;
86         if (IsWindow( hwnd )) /* check other processes */
87         {
88             if (write_access)
89             {
90                 /* modifying classes in other processes is not allowed */
91                 SetLastError( ERROR_ACCESS_DENIED );
92                 return NULL;
93             }
94             FIXME( "reading from class of other process window %p\n", hwnd );
95             /* DbgBreakPoint(); */
96         }
97     }
98     SetLastError( ERROR_INVALID_WINDOW_HANDLE );
99     return NULL;
100 }
101
102
103 /***********************************************************************
104  *           release_class_ptr
105  */
106 inline static void release_class_ptr( CLASS *ptr )
107 {
108     USER_Unlock();
109 }
110
111
112 /***********************************************************************
113  *           CLASS_GetProc
114  *
115  * Get the class winproc for a given proc type
116  */
117 static WNDPROC16 CLASS_GetProc( CLASS *classPtr, WINDOWPROCTYPE type )
118 {
119     WNDPROC proc = classPtr->winprocA;
120
121     if (classPtr->winprocW)
122     {
123         /* if we have a Unicode proc, use it if we have no ASCII proc
124          * or if we have both and Unicode was requested
125          */
126         if (!proc || type == WIN_PROC_32W) proc = classPtr->winprocW;
127     }
128     return WINPROC_GetProc( proc, type );
129 }
130
131
132 /***********************************************************************
133  *           CLASS_SetProc
134  *
135  * Set the class winproc for a given proc type.
136  * Returns the previous window proc.
137  */
138 static WNDPROC16 CLASS_SetProc( CLASS *classPtr, WNDPROC newproc, WINDOWPROCTYPE type )
139 {
140     WNDPROC *proc = &classPtr->winprocA;
141     WNDPROC16 ret;
142
143     if (classPtr->winprocW)
144     {
145         /* if we have a Unicode proc, use it if we have no ASCII proc
146          * or if we have both and Unicode was requested
147          */
148         if (!*proc || type == WIN_PROC_32W) proc = &classPtr->winprocW;
149     }
150     ret = WINPROC_GetProc( *proc, type );
151     WINPROC_SetProc( proc, newproc, type, WIN_PROC_CLASS );
152     /* now free the one that we didn't set */
153     if (classPtr->winprocA && classPtr->winprocW)
154     {
155         if (proc == &classPtr->winprocA)
156         {
157             WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
158             classPtr->winprocW = 0;
159         }
160         else
161         {
162             WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
163             classPtr->winprocA = 0;
164         }
165     }
166     return ret;
167 }
168
169
170 /***********************************************************************
171  *           CLASS_GetMenuNameA
172  *
173  * Get the menu name as a ASCII string.
174  */
175 inline static LPSTR CLASS_GetMenuNameA( CLASS *classPtr )
176 {
177     if (!HIWORD(classPtr->menuName)) return (LPSTR)classPtr->menuName;
178     return (LPSTR)(classPtr->menuName + strlenW(classPtr->menuName) + 1);
179 }
180
181
182 /***********************************************************************
183  *           CLASS_GetMenuName16
184  *
185  * Get the menu name as a SEGPTR.
186  */
187 inline static SEGPTR CLASS_GetMenuName16( CLASS *classPtr )
188 {
189     if (!HIWORD(classPtr->menuName)) return (SEGPTR)classPtr->menuName;
190     if (!classPtr->segMenuName)
191         classPtr->segMenuName = MapLS( CLASS_GetMenuNameA(classPtr) );
192     return classPtr->segMenuName;
193 }
194
195
196 /***********************************************************************
197  *           CLASS_GetMenuNameW
198  *
199  * Get the menu name as a Unicode string.
200  */
201 inline static LPWSTR CLASS_GetMenuNameW( CLASS *classPtr )
202 {
203     return classPtr->menuName;
204 }
205
206
207 /***********************************************************************
208  *           CLASS_SetMenuNameA
209  *
210  * Set the menu name in a class structure by copying the string.
211  */
212 static void CLASS_SetMenuNameA( CLASS *classPtr, LPCSTR name )
213 {
214     UnMapLS( classPtr->segMenuName );
215     classPtr->segMenuName = 0;
216     if (HIWORD(classPtr->menuName)) HeapFree( GetProcessHeap(), 0, classPtr->menuName );
217     if (HIWORD(name))
218     {
219         DWORD lenA = strlen(name) + 1;
220         DWORD lenW = MultiByteToWideChar( CP_ACP, 0, name, lenA, NULL, 0 );
221         classPtr->menuName = HeapAlloc( GetProcessHeap(), 0, lenA + lenW*sizeof(WCHAR) );
222         MultiByteToWideChar( CP_ACP, 0, name, lenA, classPtr->menuName, lenW );
223         memcpy( classPtr->menuName + lenW, name, lenA );
224     }
225     else classPtr->menuName = (LPWSTR)name;
226 }
227
228
229 /***********************************************************************
230  *           CLASS_SetMenuNameW
231  *
232  * Set the menu name in a class structure by copying the string.
233  */
234 static void CLASS_SetMenuNameW( CLASS *classPtr, LPCWSTR name )
235 {
236     UnMapLS( classPtr->segMenuName );
237     classPtr->segMenuName = 0;
238     if (HIWORD(classPtr->menuName)) HeapFree( GetProcessHeap(), 0, classPtr->menuName );
239     if (HIWORD(name))
240     {
241         DWORD lenW = strlenW(name) + 1;
242         DWORD lenA = WideCharToMultiByte( CP_ACP, 0, name, lenW, NULL, 0, NULL, NULL );
243         classPtr->menuName = HeapAlloc( GetProcessHeap(), 0, lenA + lenW*sizeof(WCHAR) );
244         memcpy( classPtr->menuName, name, lenW*sizeof(WCHAR) );
245         WideCharToMultiByte( CP_ACP, 0, name, lenW,
246                              (char *)(classPtr->menuName + lenW), lenA, NULL, NULL );
247     }
248     else classPtr->menuName = (LPWSTR)name;
249 }
250
251
252 /***********************************************************************
253  *           CLASS_FreeClass
254  *
255  * Free a class structure.
256  */
257 static BOOL CLASS_FreeClass( CLASS *classPtr )
258 {
259     TRACE("%p\n", classPtr);
260
261     /* Check if we can remove this class */
262
263     if (classPtr->cWindows > 0)
264     {
265         SetLastError( ERROR_CLASS_HAS_WINDOWS );
266         return FALSE;
267     }
268
269     /* Remove the class from the linked list */
270
271     if (classPtr->next) classPtr->next->prev = classPtr->prev;
272     if (classPtr->prev) classPtr->prev->next = classPtr->next;
273     else firstClass = classPtr->next;
274
275     /* Delete the class */
276
277     if (classPtr->dce) DCE_FreeDCE( classPtr->dce );
278     if (classPtr->hbrBackground > (HBRUSH)(COLOR_GRADIENTINACTIVECAPTION + 1))
279         DeleteObject( classPtr->hbrBackground );
280     GlobalDeleteAtom( classPtr->atomName );
281     WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
282     WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
283     UnMapLS( classPtr->segMenuName );
284     HeapFree( GetProcessHeap(), 0, classPtr->menuName );
285     HeapFree( GetProcessHeap(), 0, classPtr );
286     return TRUE;
287 }
288
289
290 /***********************************************************************
291  *           CLASS_FreeModuleClasses
292  */
293 void CLASS_FreeModuleClasses( HMODULE16 hModule )
294 {
295     CLASS *ptr, *next;
296
297     TRACE("0x%08x\n", hModule);
298
299     USER_Lock();
300     for (ptr = firstClass; ptr; ptr = next)
301     {
302         next = ptr->next;
303         if (ptr->hInstance == HINSTANCE_32(hModule)) CLASS_FreeClass( ptr );
304     }
305     USER_Unlock();
306 }
307
308
309 /***********************************************************************
310  *           CLASS_FindClassByAtom
311  *
312  * Return a pointer to the class.
313  * hinstance has been normalized by the caller.
314  *
315  * NOTES
316  *  980805 a local class will be found now if registred with hInst=0
317  *  and looed up with a hInst!=0. msmoney does it (jsch)
318  *
319  *  Local class registered with a USER instance handle are found as if
320  *  they were global classes.
321  */
322 static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance )
323 {
324     CLASS * class, *tclass = 0, *user_class = 0;
325     HINSTANCE16 hUser = GetModuleHandle16("USER");
326
327     TRACE("0x%08x %p\n", atom, hinstance);
328
329     /* First search task-specific classes */
330
331     for (class = firstClass; (class); class = class->next)
332     {
333         if (class->style & CS_GLOBALCLASS) continue;
334         if (class->atomName == atom)
335         {
336             if (hinstance==class->hInstance || hinstance == (HINSTANCE)0xffff)
337             {
338                 TRACE("-- found local %p\n", class);
339                 return class;
340             }
341             if (class->hInstance == 0) tclass = class;
342             else if(class->hInstance == HINSTANCE_32(hUser))
343             {
344                 user_class = class;
345             }
346         }
347     }
348
349     /* Then search global classes */
350
351     for (class = firstClass; (class); class = class->next)
352     {
353         if (!(class->style & CS_GLOBALCLASS)) continue;
354         if (class->atomName == atom)
355         {
356             TRACE("-- found global %p\n", class);
357             return class;
358         }
359     }
360
361     /* Check if there was a local class registered with USER */
362     if( user_class )
363     {
364         TRACE("--found local USER class %p\n", user_class);
365         return user_class;
366     }
367
368     /* Then check if there was a local class with hInst=0*/
369     if ( tclass )
370     {
371         WARN("-- found local Class registred with hInst=0\n");
372         return tclass;
373     }
374
375     TRACE("-- not found\n");
376     return 0;
377 }
378
379
380 /***********************************************************************
381  *           CLASS_RegisterClass
382  *
383  * The real RegisterClass() functionality.
384  */
385 static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance,
386                                    DWORD style, INT classExtra, INT winExtra )
387 {
388     CLASS *classPtr;
389
390     TRACE("atom=0x%x hinst=%p style=0x%lx clExtr=0x%x winExtr=0x%x\n",
391           atom, hInstance, style, classExtra, winExtra );
392
393    /* Check if a class with this name already exists */
394     classPtr = CLASS_FindClassByAtom( atom, hInstance );
395     if (classPtr)
396     {
397         /* Class can be created only if it is local and */
398         /* if the class with the same name is global.   */
399
400         if ((style & CS_GLOBALCLASS) || !(classPtr->style & CS_GLOBALCLASS))
401         {
402             SetLastError( ERROR_CLASS_ALREADY_EXISTS );
403             return NULL;
404         }
405     }
406
407     /* Fix the extra bytes value */
408
409     if (classExtra < 0) classExtra = 0;
410     else if (classExtra > 40)  /* Extra bytes are limited to 40 in Win32 */
411         WARN("Class extra bytes %d is > 40\n", classExtra);
412     if (winExtra < 0) winExtra = 0;
413     else if (winExtra > 40)    /* Extra bytes are limited to 40 in Win32 */
414         WARN("Win extra bytes %d is > 40\n", winExtra );
415
416     /* Create the class */
417
418     classPtr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLASS) + classExtra );
419     if (!classPtr) return NULL;
420     classPtr->style       = style;
421     classPtr->cbWndExtra  = winExtra;
422     classPtr->cbClsExtra  = classExtra;
423     classPtr->hInstance   = hInstance;
424     classPtr->atomName    = atom;
425     classPtr->dce         = (style & CS_CLASSDC) ? DCE_AllocDCE( 0, DCE_CLASS_DC ) : NULL;
426
427     /* Other non-null values must be set by caller */
428
429     if ((classPtr->next = firstClass)) firstClass->prev = classPtr;
430     firstClass = classPtr;
431     return classPtr;
432 }
433
434
435 /***********************************************************************
436  *           CLASS_UnregisterClass
437  *
438  * The real UnregisterClass() functionality.
439  */
440 static BOOL CLASS_UnregisterClass( ATOM atom, HINSTANCE hInstance )
441 {
442     CLASS *classPtr;
443     BOOL ret = FALSE;
444
445     USER_Lock();
446     if (atom &&
447         (classPtr = CLASS_FindClassByAtom( atom, hInstance )) &&
448         (!hInstance || classPtr->hInstance == hInstance))
449     {
450         ret = CLASS_FreeClass( classPtr );
451     }
452     else SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
453
454     USER_Unlock();
455     return ret;
456 }
457
458
459 /***********************************************************************
460  *           CLASS_RegisterBuiltinClass
461  *
462  * Register a builtin control class.
463  * This allows having both ASCII and Unicode winprocs for the same class.
464  */
465 ATOM CLASS_RegisterBuiltinClass( const struct builtin_class_descr *descr )
466 {
467     ATOM atom;
468     CLASS *classPtr;
469
470     if (!(atom = GlobalAddAtomA( descr->name ))) return 0;
471
472     if (!(classPtr = CLASS_RegisterClass( atom, 0, descr->style, 0, descr->extra )))
473     {
474         GlobalDeleteAtom( atom );
475         return 0;
476     }
477
478     classPtr->hCursor       = LoadCursorA( 0, (LPSTR)descr->cursor );
479     classPtr->hbrBackground = descr->brush;
480
481     if (descr->procA) WINPROC_SetProc( &classPtr->winprocA, descr->procA,
482                                        WIN_PROC_32A, WIN_PROC_CLASS );
483     if (descr->procW) WINPROC_SetProc( &classPtr->winprocW, descr->procW,
484                                        WIN_PROC_32W, WIN_PROC_CLASS );
485     return atom;
486 }
487
488
489 /***********************************************************************
490  *           CLASS_AddWindow
491  *
492  * Add a new window using this class, and return the necessary
493  * information for creating the window.
494  */
495 CLASS *CLASS_AddWindow( ATOM atom, HINSTANCE inst, WINDOWPROCTYPE type,
496                         INT *winExtra, WNDPROC *winproc, DWORD *style, struct tagDCE **dce )
497 {
498     CLASS *class;
499     if (type == WIN_PROC_16) inst = HINSTANCE_32(GetExePtr(HINSTANCE_16(inst)));
500
501     if (!(class = CLASS_FindClassByAtom( atom, inst ))) return NULL;
502     class->cWindows++;
503
504     if (type == WIN_PROC_32W)
505     {
506         if (!(*winproc = class->winprocW)) *winproc = class->winprocA;
507     }
508     else
509     {
510         if (!(*winproc = class->winprocA)) *winproc = class->winprocW;
511     }
512     *winExtra = class->cbWndExtra;
513     *style = class->style;
514     *dce = class->dce;
515     return class;
516 }
517
518
519 /***********************************************************************
520  *           CLASS_RemoveWindow
521  *
522  * Remove a window from the class window count.
523  */
524 void CLASS_RemoveWindow( CLASS *cls )
525 {
526     if (cls && cls->cWindows) cls->cWindows--;
527 }
528
529
530 /***********************************************************************
531  *              RegisterClass (USER.57)
532  */
533 ATOM WINAPI RegisterClass16( const WNDCLASS16 *wc )
534 {
535     WNDCLASSEX16 wcex;
536
537     wcex.cbSize        = sizeof(wcex);
538     wcex.style         = wc->style;
539     wcex.lpfnWndProc   = wc->lpfnWndProc;
540     wcex.cbClsExtra    = wc->cbClsExtra;
541     wcex.cbWndExtra    = wc->cbWndExtra;
542     wcex.hInstance     = wc->hInstance;
543     wcex.hIcon         = wc->hIcon;
544     wcex.hCursor       = wc->hCursor;
545     wcex.hbrBackground = wc->hbrBackground;
546     wcex.lpszMenuName  = wc->lpszMenuName;
547     wcex.lpszClassName = wc->lpszClassName;
548     wcex.hIconSm       = 0;
549     return RegisterClassEx16( &wcex );
550 }
551
552
553 /***********************************************************************
554  *              RegisterClassA (USER32.@)
555  * RETURNS
556  *      >0: Unique identifier
557  *      0: Failure
558  */
559 ATOM WINAPI RegisterClassA( const WNDCLASSA* wc ) /* [in] Address of structure with class data */
560 {
561     WNDCLASSEXA wcex;
562
563     wcex.cbSize        = sizeof(wcex);
564     wcex.style         = wc->style;
565     wcex.lpfnWndProc   = wc->lpfnWndProc;
566     wcex.cbClsExtra    = wc->cbClsExtra;
567     wcex.cbWndExtra    = wc->cbWndExtra;
568     wcex.hInstance     = wc->hInstance;
569     wcex.hIcon         = wc->hIcon;
570     wcex.hCursor       = wc->hCursor;
571     wcex.hbrBackground = wc->hbrBackground;
572     wcex.lpszMenuName  = wc->lpszMenuName;
573     wcex.lpszClassName = wc->lpszClassName;
574     wcex.hIconSm       = 0;
575     return RegisterClassExA( &wcex );
576 }
577
578
579 /***********************************************************************
580  *              RegisterClassW (USER32.@)
581  */
582 ATOM WINAPI RegisterClassW( const WNDCLASSW* wc )
583 {
584     WNDCLASSEXW wcex;
585
586     wcex.cbSize        = sizeof(wcex);
587     wcex.style         = wc->style;
588     wcex.lpfnWndProc   = wc->lpfnWndProc;
589     wcex.cbClsExtra    = wc->cbClsExtra;
590     wcex.cbWndExtra    = wc->cbWndExtra;
591     wcex.hInstance     = wc->hInstance;
592     wcex.hIcon         = wc->hIcon;
593     wcex.hCursor       = wc->hCursor;
594     wcex.hbrBackground = wc->hbrBackground;
595     wcex.lpszMenuName  = wc->lpszMenuName;
596     wcex.lpszClassName = wc->lpszClassName;
597     wcex.hIconSm       = 0;
598     return RegisterClassExW( &wcex );
599 }
600
601
602 /***********************************************************************
603  *              RegisterClassEx (USER.397)
604  */
605 ATOM WINAPI RegisterClassEx16( const WNDCLASSEX16 *wc )
606 {
607     ATOM atom;
608     CLASS *classPtr;
609     HINSTANCE hInstance = HINSTANCE_32(GetExePtr( wc->hInstance ));
610
611     if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0;
612     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
613                                           wc->cbClsExtra, wc->cbWndExtra )))
614     {
615         GlobalDeleteAtom( atom );
616         return 0;
617     }
618
619     TRACE("atom=%04x wndproc=%p hinst=%p bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
620           atom, wc->lpfnWndProc, hInstance,
621           wc->hbrBackground, wc->style, wc->cbClsExtra,
622           wc->cbWndExtra, classPtr );
623
624     classPtr->hIcon         = HICON_32(wc->hIcon);
625     classPtr->hIconSm       = HICON_32(wc->hIconSm);
626     classPtr->hCursor       = HCURSOR_32(wc->hCursor);
627     classPtr->hbrBackground = HBRUSH_32(wc->hbrBackground);
628
629     WINPROC_SetProc( &classPtr->winprocA, (WNDPROC)wc->lpfnWndProc,
630                      WIN_PROC_16, WIN_PROC_CLASS );
631     CLASS_SetMenuNameA( classPtr, MapSL(wc->lpszMenuName) );
632     return atom;
633 }
634
635
636 /***********************************************************************
637  *              RegisterClassExA (USER32.@)
638  */
639 ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
640 {
641     ATOM atom;
642     CLASS *classPtr;
643
644     if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
645
646     if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
647                                           wc->cbClsExtra, wc->cbWndExtra )))
648     {
649         GlobalDeleteAtom( atom );
650         return 0;
651     }
652
653     TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
654           atom, wc->lpfnWndProc, wc->hInstance,
655           wc->hbrBackground, wc->style, wc->cbClsExtra,
656           wc->cbWndExtra, classPtr );
657
658     classPtr->hIcon         = wc->hIcon;
659     classPtr->hIconSm       = wc->hIconSm;
660     classPtr->hCursor       = wc->hCursor;
661     classPtr->hbrBackground = wc->hbrBackground;
662     WINPROC_SetProc( &classPtr->winprocA, wc->lpfnWndProc, WIN_PROC_32A, WIN_PROC_CLASS );
663     CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
664     return atom;
665 }
666
667
668 /***********************************************************************
669  *              RegisterClassExW (USER32.@)
670  */
671 ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
672 {
673     ATOM atom;
674     CLASS *classPtr;
675
676     if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
677
678     if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
679                                           wc->cbClsExtra, wc->cbWndExtra )))
680     {
681         GlobalDeleteAtom( atom );
682         return 0;
683     }
684
685     TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
686           atom, wc->lpfnWndProc, wc->hInstance,
687           wc->hbrBackground, wc->style, wc->cbClsExtra,
688           wc->cbWndExtra, classPtr );
689
690     classPtr->hIcon         = wc->hIcon;
691     classPtr->hIconSm       = wc->hIconSm;
692     classPtr->hCursor       = wc->hCursor;
693     classPtr->hbrBackground = wc->hbrBackground;
694     WINPROC_SetProc( &classPtr->winprocW, wc->lpfnWndProc, WIN_PROC_32W, WIN_PROC_CLASS );
695     CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
696     return atom;
697 }
698
699
700 /***********************************************************************
701  *              UnregisterClass (USER.403)
702  */
703 BOOL16 WINAPI UnregisterClass16( LPCSTR className, HINSTANCE16 hInstance )
704 {
705     return UnregisterClassA( className, HINSTANCE_32(GetExePtr( hInstance )) );
706 }
707
708 /***********************************************************************
709  *              UnregisterClassA (USER32.@)
710  *
711  */
712 BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance )
713 {
714     TRACE("%s %p\n",debugstr_a(className), hInstance);
715     return CLASS_UnregisterClass( GlobalFindAtomA( className ), hInstance );
716 }
717
718 /***********************************************************************
719  *              UnregisterClassW (USER32.@)
720  */
721 BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance )
722 {
723     TRACE("%s %p\n",debugstr_w(className), hInstance);
724     return CLASS_UnregisterClass( GlobalFindAtomW( className ), hInstance );
725 }
726
727
728 /***********************************************************************
729  *              GetClassWord (USER32.@)
730  */
731 WORD WINAPI GetClassWord( HWND hwnd, INT offset )
732 {
733     CLASS *class;
734     WORD retvalue = 0;
735
736     if (offset < 0) return GetClassLongA( hwnd, offset );
737
738     TRACE("%p %x\n",hwnd, offset);
739
740     if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
741
742     if (offset <= class->cbClsExtra - sizeof(WORD))
743         memcpy( &retvalue, (char *)(class + 1) + offset, sizeof(retvalue) );
744     else
745         SetLastError( ERROR_INVALID_INDEX );
746     release_class_ptr( class );
747     return retvalue;
748 }
749
750
751 /***********************************************************************
752  *              GetClassLong (USER.131)
753  */
754 LONG WINAPI GetClassLong16( HWND16 hwnd16, INT16 offset )
755 {
756     CLASS *class;
757     LONG ret;
758     HWND hwnd = (HWND)(ULONG_PTR)hwnd16;  /* no need for full handle */
759
760     TRACE("%p %d\n",hwnd, offset);
761
762     switch( offset )
763     {
764     case GCL_WNDPROC:
765         if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
766         ret = (LONG)CLASS_GetProc( class, WIN_PROC_16 );
767         release_class_ptr( class );
768         return ret;
769     case GCL_MENUNAME:
770         if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
771         ret = (LONG)CLASS_GetMenuName16( class );
772         release_class_ptr( class );
773         return ret;
774     default:
775         return GetClassLongA( hwnd, offset );
776     }
777 }
778
779
780 /***********************************************************************
781  *              GetClassLongW (USER32.@)
782  */
783 LONG WINAPI GetClassLongW( HWND hwnd, INT offset )
784 {
785     CLASS *class;
786     LONG retvalue = 0;
787
788     TRACE("%p %d\n", hwnd, offset);
789
790     if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
791
792     if (offset >= 0)
793     {
794         if (offset <= class->cbClsExtra - sizeof(LONG))
795             memcpy( &retvalue, (char *)(class + 1) + offset, sizeof(retvalue) );
796         else
797             SetLastError( ERROR_INVALID_INDEX );
798         release_class_ptr( class );
799         return retvalue;
800     }
801
802     switch(offset)
803     {
804     case GCL_HBRBACKGROUND:
805         retvalue = (LONG)class->hbrBackground;
806         break;
807     case GCL_HCURSOR:
808         retvalue = (LONG)class->hCursor;
809         break;
810     case GCL_HICON:
811         retvalue = (LONG)class->hIcon;
812         break;
813     case GCL_HICONSM:
814         retvalue = (LONG)class->hIconSm;
815         break;
816     case GCL_STYLE:
817         retvalue = (LONG)class->style;
818         break;
819     case GCL_CBWNDEXTRA:
820         retvalue = (LONG)class->cbWndExtra;
821         break;
822     case GCL_CBCLSEXTRA:
823         retvalue = (LONG)class->cbClsExtra;
824         break;
825     case GCL_HMODULE:
826         retvalue = (LONG)class->hInstance;
827         break;
828     case GCL_WNDPROC:
829         retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32W );
830         break;
831     case GCL_MENUNAME:
832         retvalue = (LONG)CLASS_GetMenuNameW( class );
833         break;
834     case GCW_ATOM:
835         retvalue = (DWORD)class->atomName;
836         break;
837     default:
838         SetLastError( ERROR_INVALID_INDEX );
839         break;
840     }
841     release_class_ptr( class );
842     return retvalue;
843 }
844
845
846 /***********************************************************************
847  *              GetClassLongA (USER32.@)
848  */
849 LONG WINAPI GetClassLongA( HWND hwnd, INT offset )
850 {
851     CLASS *class;
852     LONG retvalue;
853
854     if (offset != GCL_WNDPROC && offset != GCL_MENUNAME)
855         return GetClassLongW( hwnd, offset );
856
857     TRACE("%p %d\n", hwnd, offset);
858
859     if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
860
861     if (offset == GCL_WNDPROC)
862         retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32A );
863     else  /* GCL_MENUNAME */
864         retvalue = (LONG)CLASS_GetMenuNameA( class );
865
866     release_class_ptr( class );
867     return retvalue;
868 }
869
870
871 /***********************************************************************
872  *              SetClassWord (USER32.@)
873  */
874 WORD WINAPI SetClassWord( HWND hwnd, INT offset, WORD newval )
875 {
876     CLASS *class;
877     WORD retval = 0;
878
879     if (offset < 0) return SetClassLongA( hwnd, offset, (DWORD)newval );
880
881     TRACE("%p %d %x\n", hwnd, offset, newval);
882
883     if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
884
885     if (offset <= class->cbClsExtra - sizeof(WORD))
886     {
887         void *ptr = (char *)(class + 1) + offset;
888         memcpy( &retval, ptr, sizeof(retval) );
889         memcpy( ptr, &newval, sizeof(newval) );
890     }
891     else SetLastError( ERROR_INVALID_INDEX );
892
893     release_class_ptr( class );
894     return retval;
895 }
896
897
898 /***********************************************************************
899  *              SetClassLong (USER.132)
900  */
901 LONG WINAPI SetClassLong16( HWND16 hwnd16, INT16 offset, LONG newval )
902 {
903     CLASS *class;
904     LONG retval;
905     HWND hwnd = (HWND)(ULONG_PTR)hwnd16;  /* no need for full handle */
906
907     TRACE("%p %d %lx\n", hwnd, offset, newval);
908
909     switch(offset)
910     {
911     case GCL_WNDPROC:
912         if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
913         retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_16 );
914         release_class_ptr( class );
915         return retval;
916     case GCL_MENUNAME:
917         newval = (LONG)MapSL( newval );
918         /* fall through */
919     default:
920         return SetClassLongA( hwnd, offset, newval );
921     }
922 }
923
924
925 /***********************************************************************
926  *              SetClassLongW (USER32.@)
927  */
928 LONG WINAPI SetClassLongW( HWND hwnd, INT offset, LONG newval )
929 {
930     CLASS *class;
931     LONG retval = 0;
932
933     TRACE("%p %d %lx\n", hwnd, offset, newval);
934
935     if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
936
937     if (offset >= 0)
938     {
939         if (offset <= class->cbClsExtra - sizeof(LONG))
940         {
941             void *ptr = (char *)(class + 1) + offset;
942             memcpy( &retval, ptr, sizeof(retval) );
943             memcpy( ptr, &newval, sizeof(newval) );
944         }
945         else SetLastError( ERROR_INVALID_INDEX );
946     }
947     else switch(offset)
948     {
949     case GCL_MENUNAME:
950         CLASS_SetMenuNameW( class, (LPCWSTR)newval );
951         retval = 0;  /* Old value is now meaningless anyway */
952         break;
953     case GCL_WNDPROC:
954         retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32W );
955         break;
956     case GCL_HBRBACKGROUND:
957         retval = (LONG)class->hbrBackground;
958         class->hbrBackground = (HBRUSH)newval;
959         break;
960     case GCL_HCURSOR:
961         retval = (LONG)class->hCursor;
962         class->hCursor = (HCURSOR)newval;
963         break;
964     case GCL_HICON:
965         retval = (LONG)class->hIcon;
966         class->hIcon = (HICON)newval;
967         break;
968     case GCL_HICONSM:
969         retval = (LONG)class->hIconSm;
970         class->hIconSm = (HICON)newval;
971         break;
972     case GCL_STYLE:
973         retval = (LONG)class->style;
974         class->style = newval;
975         break;
976     case GCL_CBWNDEXTRA:
977         retval = (LONG)class->cbWndExtra;
978         class->cbWndExtra = newval;
979         break;
980     case GCL_HMODULE:
981         retval = (LONG)class->hInstance;
982         class->hInstance = (HINSTANCE)newval;
983         break;
984     case GCW_ATOM:
985         retval = (DWORD)class->atomName;
986         class->atomName = newval;
987         break;
988     case GCL_CBCLSEXTRA:  /* cannot change this one */
989         SetLastError( ERROR_INVALID_PARAMETER );
990         break;
991     default:
992         SetLastError( ERROR_INVALID_INDEX );
993         break;
994     }
995     release_class_ptr( class );
996     return retval;
997 }
998
999
1000 /***********************************************************************
1001  *              SetClassLongA (USER32.@)
1002  */
1003 LONG WINAPI SetClassLongA( HWND hwnd, INT offset, LONG newval )
1004 {
1005     CLASS *class;
1006     LONG retval;
1007
1008     if (offset != GCL_WNDPROC && offset != GCL_MENUNAME)
1009         return SetClassLongW( hwnd, offset, newval );
1010
1011     TRACE("%p %d %lx\n", hwnd, offset, newval);
1012
1013     if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
1014
1015     if (offset == GCL_WNDPROC)
1016         retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32A );
1017     else  /* GCL_MENUNAME */
1018     {
1019         CLASS_SetMenuNameA( class, (LPCSTR)newval );
1020         retval = 0;  /* Old value is now meaningless anyway */
1021     }
1022     release_class_ptr( class );
1023     return retval;
1024 }
1025
1026
1027 /***********************************************************************
1028  *              GetClassNameA (USER32.@)
1029  */
1030 INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
1031 {
1032     INT ret = GlobalGetAtomNameA( GetClassLongA( hwnd, GCW_ATOM ), buffer, count );
1033
1034     TRACE("%p %s %x\n",hwnd, debugstr_a(buffer), count);
1035     return ret;
1036 }
1037
1038
1039 /***********************************************************************
1040  *              GetClassNameW (USER32.@)
1041  */
1042 INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
1043 {
1044     INT ret = GlobalGetAtomNameW( GetClassLongW( hwnd, GCW_ATOM ), buffer, count );
1045
1046     TRACE("%p %s %x\n",hwnd, debugstr_w(buffer), count);
1047     return ret;
1048 }
1049
1050
1051 /***********************************************************************
1052  *              RealGetWindowClassA (USER32.@)
1053  */
1054 UINT WINAPI RealGetWindowClassA( HWND hwnd, LPSTR buffer, UINT count )
1055 {
1056     return GetClassNameA( hwnd, buffer, count );
1057 }
1058
1059
1060 /***********************************************************************
1061  *              RealGetWindowClassW (USER32.@)
1062  */
1063 UINT WINAPI RealGetWindowClassW( HWND hwnd, LPWSTR buffer, UINT count )
1064 {
1065     return GetClassNameW( hwnd, buffer, count );
1066 }
1067
1068
1069 /***********************************************************************
1070  *              GetClassInfo (USER.404)
1071  */
1072 BOOL16 WINAPI GetClassInfo16( HINSTANCE16 hInst16, SEGPTR name, WNDCLASS16 *wc )
1073 {
1074     WNDCLASSEX16 wcex;
1075     UINT16 ret = GetClassInfoEx16( hInst16, name, &wcex );
1076
1077     if (ret)
1078     {
1079         wc->style         = wcex.style;
1080         wc->lpfnWndProc   = wcex.lpfnWndProc;
1081         wc->cbClsExtra    = wcex.cbClsExtra;
1082         wc->cbWndExtra    = wcex.cbWndExtra;
1083         wc->hInstance     = wcex.hInstance;
1084         wc->hIcon         = wcex.hIcon;
1085         wc->hCursor       = wcex.hCursor;
1086         wc->hbrBackground = wcex.hbrBackground;
1087         wc->lpszMenuName  = wcex.lpszMenuName;
1088         wc->lpszClassName = wcex.lpszClassName;
1089     }
1090     return ret;
1091 }
1092
1093
1094 /***********************************************************************
1095  *              GetClassInfoA (USER32.@)
1096  */
1097 BOOL WINAPI GetClassInfoA( HINSTANCE hInstance, LPCSTR name, WNDCLASSA *wc )
1098 {
1099     WNDCLASSEXA wcex;
1100     UINT ret = GetClassInfoExA( hInstance, name, &wcex );
1101
1102     if (ret)
1103     {
1104         wc->style         = wcex.style;
1105         wc->lpfnWndProc   = wcex.lpfnWndProc;
1106         wc->cbClsExtra    = wcex.cbClsExtra;
1107         wc->cbWndExtra    = wcex.cbWndExtra;
1108         wc->hInstance     = wcex.hInstance;
1109         wc->hIcon         = wcex.hIcon;
1110         wc->hCursor       = wcex.hCursor;
1111         wc->hbrBackground = wcex.hbrBackground;
1112         wc->lpszMenuName  = wcex.lpszMenuName;
1113         wc->lpszClassName = wcex.lpszClassName;
1114     }
1115     return ret;
1116 }
1117
1118
1119 /***********************************************************************
1120  *              GetClassInfoW (USER32.@)
1121  */
1122 BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSW *wc )
1123 {
1124     WNDCLASSEXW wcex;
1125     UINT ret = GetClassInfoExW( hInstance, name, &wcex );
1126
1127     if (ret)
1128     {
1129         wc->style         = wcex.style;
1130         wc->lpfnWndProc   = wcex.lpfnWndProc;
1131         wc->cbClsExtra    = wcex.cbClsExtra;
1132         wc->cbWndExtra    = wcex.cbWndExtra;
1133         wc->hInstance     = wcex.hInstance;
1134         wc->hIcon         = wcex.hIcon;
1135         wc->hCursor       = wcex.hCursor;
1136         wc->hbrBackground = wcex.hbrBackground;
1137         wc->lpszMenuName  = wcex.lpszMenuName;
1138         wc->lpszClassName = wcex.lpszClassName;
1139     }
1140     return ret;
1141 }
1142
1143
1144 /***********************************************************************
1145  *              GetClassInfoEx (USER.398)
1146  *
1147  * FIXME: this is just a guess, I have no idea if GetClassInfoEx() is the
1148  * same in Win16 as in Win32. --AJ
1149  */
1150 BOOL16 WINAPI GetClassInfoEx16( HINSTANCE16 hInst16, SEGPTR name, WNDCLASSEX16 *wc )
1151 {
1152     ATOM atom;
1153     CLASS *classPtr;
1154     HINSTANCE hInstance = HINSTANCE_32(GetExePtr( hInst16 ));
1155
1156     TRACE("%p %s %p\n",hInstance,debugstr_a( MapSL(name) ), wc);
1157
1158     if (!(atom = GlobalFindAtomA( MapSL(name) )) ||
1159         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1160         (hInstance != classPtr->hInstance)) return FALSE;
1161     wc->style         = classPtr->style;
1162     wc->lpfnWndProc   = CLASS_GetProc( classPtr, WIN_PROC_16 );
1163     wc->cbClsExtra    = (INT16)classPtr->cbClsExtra;
1164     wc->cbWndExtra    = (INT16)classPtr->cbWndExtra;
1165     wc->hInstance     = HINSTANCE_16(classPtr->hInstance);
1166     wc->hIcon         = HICON_16(classPtr->hIcon);
1167     wc->hIconSm       = HICON_16(classPtr->hIconSm);
1168     wc->hCursor       = HCURSOR_16(classPtr->hCursor);
1169     wc->hbrBackground = HBRUSH_16(classPtr->hbrBackground);
1170     wc->lpszClassName = (SEGPTR)0;
1171     wc->lpszMenuName  = CLASS_GetMenuName16( classPtr );
1172     wc->lpszClassName = name;
1173
1174     /* We must return the atom of the class here instead of just TRUE. */
1175     return atom;
1176 }
1177
1178
1179 /***********************************************************************
1180  *              GetClassInfoExA (USER32.@)
1181  */
1182 BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name,
1183                                  WNDCLASSEXA *wc )
1184 {
1185     ATOM atom;
1186     CLASS *classPtr;
1187
1188     TRACE("%p %p %p\n",hInstance, name, wc);
1189
1190     if (!(atom = GlobalFindAtomA( name )) ||
1191         !(classPtr = CLASS_FindClassByAtom( atom, hInstance ))
1192         /*|| (hInstance != classPtr->hInstance) */ ) return FALSE;
1193     wc->style         = classPtr->style;
1194     wc->lpfnWndProc   = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32A );
1195     wc->cbClsExtra    = classPtr->cbClsExtra;
1196     wc->cbWndExtra    = classPtr->cbWndExtra;
1197     wc->hInstance     = classPtr->hInstance;
1198     wc->hIcon         = (HICON)classPtr->hIcon;
1199     wc->hIconSm       = (HICON)classPtr->hIconSm;
1200     wc->hCursor       = (HCURSOR)classPtr->hCursor;
1201     wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1202     wc->lpszMenuName  = CLASS_GetMenuNameA( classPtr );
1203     wc->lpszClassName = name;
1204
1205     /* We must return the atom of the class here instead of just TRUE. */
1206     return atom;
1207 }
1208
1209
1210 /***********************************************************************
1211  *              GetClassInfoExW (USER32.@)
1212  */
1213 BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name,
1214                                  WNDCLASSEXW *wc )
1215 {
1216     ATOM atom;
1217     CLASS *classPtr;
1218
1219     TRACE("%p %p %p\n",hInstance, name, wc);
1220
1221     if (!(atom = GlobalFindAtomW( name )) ||
1222         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1223         (hInstance != classPtr->hInstance)) return FALSE;
1224     wc->style         = classPtr->style;
1225     wc->lpfnWndProc   = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
1226     wc->cbClsExtra    = classPtr->cbClsExtra;
1227     wc->cbWndExtra    = classPtr->cbWndExtra;
1228     wc->hInstance     = classPtr->hInstance;
1229     wc->hIcon         = (HICON)classPtr->hIcon;
1230     wc->hIconSm       = (HICON)classPtr->hIconSm;
1231     wc->hCursor       = (HCURSOR)classPtr->hCursor;
1232     wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1233     wc->lpszMenuName  = CLASS_GetMenuNameW( classPtr );
1234     wc->lpszClassName = name;
1235
1236     /* We must return the atom of the class here instead of just TRUE. */
1237     return atom;
1238 }
1239
1240
1241 #if 0  /* toolhelp is in kernel, so this cannot work */
1242
1243 /***********************************************************************
1244  *              ClassFirst (TOOLHELP.69)
1245  */
1246 BOOL16 WINAPI ClassFirst16( CLASSENTRY *pClassEntry )
1247 {
1248     TRACE("%p\n",pClassEntry);
1249     pClassEntry->wNext = 1;
1250     return ClassNext16( pClassEntry );
1251 }
1252
1253
1254 /***********************************************************************
1255  *              ClassNext (TOOLHELP.70)
1256  */
1257 BOOL16 WINAPI ClassNext16( CLASSENTRY *pClassEntry )
1258 {
1259     int i;
1260     CLASS *class = firstClass;
1261
1262     TRACE("%p\n",pClassEntry);
1263
1264     if (!pClassEntry->wNext) return FALSE;
1265     for (i = 1; (i < pClassEntry->wNext) && class; i++) class = class->next;
1266     if (!class)
1267     {
1268         pClassEntry->wNext = 0;
1269         return FALSE;
1270     }
1271     pClassEntry->hInst = class->hInstance;
1272     pClassEntry->wNext++;
1273     GlobalGetAtomNameA( class->atomName, pClassEntry->szClassName,
1274                           sizeof(pClassEntry->szClassName) );
1275     return TRUE;
1276 }
1277 #endif