2 * Window classes functions
4 * Copyright 1993, 1996 Alexandre Julliard
5 * 1998 Juergen Schmied (jsch)
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)
11 * FIXME: There seems to be a general problem with hInstance in WINE
12 * classes are getting registered with wrong hInstance.
17 #include "wine/winbase16.h"
21 #include "wine/winuser16.h"
22 #include "wine/unicode.h"
23 #include "wine/port.h"
30 #include "debugtools.h"
32 DEFAULT_DEBUG_CHANNEL(class);
34 typedef struct tagCLASS
36 struct tagCLASS *next; /* Next class */
37 struct tagCLASS *prev; /* Prev class */
38 UINT cWindows; /* Count of existing windows */
39 UINT style; /* Class style */
40 HWINDOWPROC winprocA; /* Window procedure (ASCII) */
41 HWINDOWPROC winprocW; /* Window procedure (Unicode) */
42 INT cbClsExtra; /* Class extra bytes */
43 INT cbWndExtra; /* Window extra bytes */
44 LPWSTR menuName; /* Default menu name (Unicode followed by ASCII) */
45 struct tagDCE *dce; /* Class DCE (if CS_CLASSDC) */
46 HINSTANCE hInstance; /* Module that created the task */
47 HICON hIcon; /* Default icon */
48 HICON hIconSm; /* Default small icon */
49 HCURSOR hCursor; /* Default cursor */
50 HBRUSH hbrBackground; /* Default background */
51 ATOM atomName; /* Name of the class */
54 static CLASS *firstClass;
56 /***********************************************************************
59 static CLASS *get_class_ptr( HWND hwnd )
62 WND *ptr = WIN_GetWndPtr( hwnd );
66 if (IsWindow( hwnd )) /* check other processes */
68 ERR( "class of window %04x belongs to other process\n", hwnd );
69 /* DbgBreakPoint(); */
74 if (ptr != BAD_WND_PTR) ret = ptr->class;
75 else SetLastError( ERROR_INVALID_WINDOW_HANDLE );
81 /***********************************************************************
84 inline static void release_class_ptr( CLASS *ptr )
90 /***********************************************************************
93 * Get the class winproc for a given proc type
95 static WNDPROC16 CLASS_GetProc( CLASS *classPtr, WINDOWPROCTYPE type )
97 HWINDOWPROC proc = classPtr->winprocA;
99 if (classPtr->winprocW)
101 /* if we have a Unicode proc, use it if we have no ASCII proc
102 * or if we have both and Unicode was requested
104 if (!proc || type == WIN_PROC_32W) proc = classPtr->winprocW;
106 return WINPROC_GetProc( proc, type );
110 /***********************************************************************
113 * Set the class winproc for a given proc type.
114 * Returns the previous window proc.
116 static WNDPROC16 CLASS_SetProc( CLASS *classPtr, WNDPROC newproc, WINDOWPROCTYPE type )
118 HWINDOWPROC *proc = &classPtr->winprocA;
121 if (classPtr->winprocW)
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
126 if (!*proc || type == WIN_PROC_32W) proc = &classPtr->winprocW;
128 ret = WINPROC_GetProc( *proc, type );
129 WINPROC_SetProc( proc, (HWINDOWPROC)newproc, type, WIN_PROC_CLASS );
130 /* now free the one that we didn't set */
131 if (classPtr->winprocA && classPtr->winprocW)
133 if (proc == &classPtr->winprocA)
135 WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
136 classPtr->winprocW = 0;
140 WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
141 classPtr->winprocA = 0;
148 /***********************************************************************
151 * Get the menu name as a ASCII string.
153 inline static LPSTR CLASS_GetMenuNameA( CLASS *classPtr )
155 if (!HIWORD(classPtr->menuName)) return (LPSTR)classPtr->menuName;
156 return (LPSTR)(classPtr->menuName + strlenW(classPtr->menuName) + 1);
160 /***********************************************************************
163 * Get the menu name as a Unicode string.
165 inline static LPWSTR CLASS_GetMenuNameW( CLASS *classPtr )
167 return classPtr->menuName;
171 /***********************************************************************
174 * Set the menu name in a class structure by copying the string.
176 static void CLASS_SetMenuNameA( CLASS *classPtr, LPCSTR name )
178 if (HIWORD(classPtr->menuName)) SEGPTR_FREE( classPtr->menuName );
181 DWORD lenA = strlen(name) + 1;
182 DWORD lenW = MultiByteToWideChar( CP_ACP, 0, name, lenA, NULL, 0 );
183 classPtr->menuName = SEGPTR_ALLOC( lenA + lenW*sizeof(WCHAR) );
184 MultiByteToWideChar( CP_ACP, 0, name, lenA, classPtr->menuName, lenW );
185 memcpy( classPtr->menuName + lenW, name, lenA );
187 else classPtr->menuName = (LPWSTR)name;
191 /***********************************************************************
194 * Set the menu name in a class structure by copying the string.
196 static void CLASS_SetMenuNameW( CLASS *classPtr, LPCWSTR name )
198 if (HIWORD(classPtr->menuName)) SEGPTR_FREE( classPtr->menuName );
201 DWORD lenW = strlenW(name) + 1;
202 DWORD lenA = WideCharToMultiByte( CP_ACP, 0, name, lenW, NULL, 0, NULL, NULL );
203 classPtr->menuName = SEGPTR_ALLOC( lenA + lenW*sizeof(WCHAR) );
204 memcpy( classPtr->menuName, name, lenW*sizeof(WCHAR) );
205 WideCharToMultiByte( CP_ACP, 0, name, lenW,
206 (char *)(classPtr->menuName + lenW), lenA, NULL, NULL );
208 else classPtr->menuName = (LPWSTR)name;
212 /***********************************************************************
215 * Free a class structure.
217 static BOOL CLASS_FreeClass( CLASS *classPtr )
219 TRACE("%p\n", classPtr);
221 /* Check if we can remove this class */
223 if (classPtr->cWindows > 0)
225 SetLastError( ERROR_CLASS_HAS_WINDOWS );
229 /* Remove the class from the linked list */
231 if (classPtr->next) classPtr->next->prev = classPtr->prev;
232 if (classPtr->prev) classPtr->prev->next = classPtr->next;
233 else firstClass = classPtr->next;
235 /* Delete the class */
237 if (classPtr->dce) DCE_FreeDCE( classPtr->dce );
238 if (classPtr->hbrBackground > (HBRUSH)(COLOR_GRADIENTINACTIVECAPTION + 1))
239 DeleteObject( classPtr->hbrBackground );
240 GlobalDeleteAtom( classPtr->atomName );
241 WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
242 WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
243 HeapFree( GetProcessHeap(), 0, classPtr->menuName );
244 HeapFree( GetProcessHeap(), 0, classPtr );
249 /***********************************************************************
250 * CLASS_FreeModuleClasses
252 void CLASS_FreeModuleClasses( HMODULE16 hModule )
256 TRACE("0x%08x\n", hModule);
259 for (ptr = firstClass; ptr; ptr = next)
262 if (ptr->hInstance == hModule) CLASS_FreeClass( ptr );
268 /***********************************************************************
269 * CLASS_FindClassByAtom
271 * Return a pointer to the class.
272 * hinstance has been normalized by the caller.
275 * 980805 a local class will be found now if registred with hInst=0
276 * and looed up with a hInst!=0. msmoney does it (jsch)
278 static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance )
280 CLASS * class, *tclass=0;
282 TRACE("0x%08x 0x%08x\n", atom, hinstance);
284 /* First search task-specific classes */
286 for (class = firstClass; (class); class = class->next)
288 if (class->style & CS_GLOBALCLASS) continue;
289 if (class->atomName == atom)
291 if (hinstance==class->hInstance || hinstance==0xffff )
293 TRACE("-- found local %p\n", class);
296 if (class->hInstance==0) tclass = class;
300 /* Then search global classes */
302 for (class = firstClass; (class); class = class->next)
304 if (!(class->style & CS_GLOBALCLASS)) continue;
305 if (class->atomName == atom)
307 TRACE("-- found global %p\n", class);
312 /* Then check if there was a local class with hInst=0*/
315 WARN("-- found local Class registred with hInst=0\n");
319 TRACE("-- not found\n");
324 /***********************************************************************
325 * CLASS_RegisterClass
327 * The real RegisterClass() functionality.
329 static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance,
330 DWORD style, INT classExtra, INT winExtra )
334 TRACE("atom=0x%x hinst=0x%x style=0x%lx clExtr=0x%x winExtr=0x%x\n",
335 atom, hInstance, style, classExtra, winExtra );
337 /* Check if a class with this name already exists */
338 classPtr = CLASS_FindClassByAtom( atom, hInstance );
341 /* Class can be created only if it is local and */
342 /* if the class with the same name is global. */
344 if ((style & CS_GLOBALCLASS) || !(classPtr->style & CS_GLOBALCLASS))
346 SetLastError( ERROR_CLASS_ALREADY_EXISTS );
351 /* Fix the extra bytes value */
353 if (classExtra < 0) classExtra = 0;
354 else if (classExtra > 40) /* Extra bytes are limited to 40 in Win32 */
355 WARN("Class extra bytes %d is > 40\n", classExtra);
356 if (winExtra < 0) winExtra = 0;
357 else if (winExtra > 40) /* Extra bytes are limited to 40 in Win32 */
358 WARN("Win extra bytes %d is > 40\n", winExtra );
360 /* Create the class */
362 classPtr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLASS) + classExtra );
363 if (!classPtr) return NULL;
364 classPtr->style = style;
365 classPtr->cbWndExtra = winExtra;
366 classPtr->cbClsExtra = classExtra;
367 classPtr->hInstance = hInstance;
368 classPtr->atomName = atom;
369 classPtr->dce = (style & CS_CLASSDC) ? DCE_AllocDCE( 0, DCE_CLASS_DC ) : NULL;
371 /* Other non-null values must be set by caller */
373 if ((classPtr->next = firstClass)) firstClass->prev = classPtr;
374 firstClass = classPtr;
379 /***********************************************************************
380 * CLASS_UnregisterClass
382 * The real UnregisterClass() functionality.
384 static BOOL CLASS_UnregisterClass( ATOM atom, HINSTANCE hInstance )
391 (classPtr = CLASS_FindClassByAtom( atom, hInstance )) &&
392 (classPtr->hInstance == hInstance))
394 ret = CLASS_FreeClass( classPtr );
396 else SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
403 /***********************************************************************
404 * CLASS_RegisterBuiltinClass
406 * Register a builtin control class.
407 * This allows having both ASCII and Unicode winprocs for the same class.
409 ATOM CLASS_RegisterBuiltinClass( const struct builtin_class_descr *descr )
414 if (!(atom = GlobalAddAtomA( descr->name ))) return 0;
416 if (!(classPtr = CLASS_RegisterClass( atom, 0, descr->style, 0, descr->extra )))
418 GlobalDeleteAtom( atom );
422 classPtr->hCursor = LoadCursorA( 0, descr->cursor );
423 classPtr->hbrBackground = descr->brush;
425 if (descr->procA) WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)descr->procA,
426 WIN_PROC_32A, WIN_PROC_CLASS );
427 if (descr->procW) WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)descr->procW,
428 WIN_PROC_32W, WIN_PROC_CLASS );
433 /***********************************************************************
436 * Add a new window using this class, and return the necessary
437 * information for creating the window.
439 CLASS *CLASS_AddWindow( ATOM atom, HINSTANCE inst, WINDOWPROCTYPE type,
440 INT *winExtra, WNDPROC *winproc, DWORD *style, struct tagDCE **dce )
443 if (type == WIN_PROC_16) inst = GetExePtr(inst);
445 if (!(class = CLASS_FindClassByAtom( atom, inst ))) return NULL;
448 if (type == WIN_PROC_32W)
450 if (!(*winproc = class->winprocW)) *winproc = class->winprocA;
454 if (!(*winproc = class->winprocA)) *winproc = class->winprocW;
456 *winExtra = class->cbWndExtra;
457 *style = class->style;
463 /***********************************************************************
466 * Remove a window from the class window count.
468 void CLASS_RemoveWindow( CLASS *cls )
470 if (cls && cls->cWindows) cls->cWindows--;
474 /***********************************************************************
475 * RegisterClass (USER.57)
477 ATOM WINAPI RegisterClass16( const WNDCLASS16 *wc )
481 int iSmIconWidth, iSmIconHeight;
482 HINSTANCE16 hInstance=GetExePtr(wc->hInstance);
484 if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0;
485 if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
486 wc->cbClsExtra, wc->cbWndExtra )))
488 GlobalDeleteAtom( atom );
492 TRACE("atom=%04x wndproc=%08lx hinst=%04x "
493 "bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
494 atom, (DWORD)wc->lpfnWndProc, hInstance,
495 wc->hbrBackground, wc->style, wc->cbClsExtra,
496 wc->cbWndExtra, classPtr,
497 HIWORD(wc->lpszClassName) ?
498 (char *)MapSL(wc->lpszClassName) : "" );
500 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
501 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
503 classPtr->hIcon = wc->hIcon;
504 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
505 iSmIconWidth, iSmIconHeight,
506 LR_COPYFROMRESOURCE);
507 classPtr->hCursor = wc->hCursor;
508 classPtr->hbrBackground = wc->hbrBackground;
510 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
511 WIN_PROC_16, WIN_PROC_CLASS );
512 CLASS_SetMenuNameA( classPtr, MapSL(wc->lpszMenuName) );
518 /***********************************************************************
519 * RegisterClassA (USER32.@)
521 * >0: Unique identifier
524 ATOM WINAPI RegisterClassA( const WNDCLASSA* wc ) /* [in] Address of structure with class data */
527 int iSmIconWidth, iSmIconHeight;
530 if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
532 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
533 wc->cbClsExtra, wc->cbWndExtra )))
535 GlobalDeleteAtom( atom );
539 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
540 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
541 wc->hbrBackground, wc->style, wc->cbClsExtra,
542 wc->cbWndExtra, classPtr,
543 HIWORD(wc->lpszClassName) ? wc->lpszClassName : "" );
545 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
546 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
548 classPtr->hIcon = wc->hIcon;
549 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
550 iSmIconWidth, iSmIconHeight,
551 LR_COPYFROMRESOURCE);
552 classPtr->hCursor = (HCURSOR16)wc->hCursor;
553 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
555 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
556 WIN_PROC_32A, WIN_PROC_CLASS );
557 CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
562 /***********************************************************************
563 * RegisterClassW (USER32.@)
565 ATOM WINAPI RegisterClassW( const WNDCLASSW* wc )
568 int iSmIconWidth, iSmIconHeight;
571 if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
573 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
574 wc->cbClsExtra, wc->cbWndExtra )))
576 GlobalDeleteAtom( atom );
580 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
581 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
582 wc->hbrBackground, wc->style, wc->cbClsExtra,
583 wc->cbWndExtra, classPtr );
585 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
586 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
588 classPtr->hIcon = wc->hIcon;
589 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
590 iSmIconWidth, iSmIconHeight,
591 LR_COPYFROMRESOURCE);
592 classPtr->hCursor = (HCURSOR16)wc->hCursor;
593 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
595 WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)wc->lpfnWndProc,
596 WIN_PROC_32W, WIN_PROC_CLASS );
597 CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
602 /***********************************************************************
603 * RegisterClassEx (USER.397)
605 ATOM WINAPI RegisterClassEx16( const WNDCLASSEX16 *wc )
609 HINSTANCE16 hInstance = GetExePtr( wc->hInstance );
611 if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0;
612 if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
613 wc->cbClsExtra, wc->cbWndExtra )))
615 GlobalDeleteAtom( atom );
619 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
620 atom, (DWORD)wc->lpfnWndProc, hInstance,
621 wc->hbrBackground, wc->style, wc->cbClsExtra,
622 wc->cbWndExtra, classPtr );
624 classPtr->hIcon = wc->hIcon;
625 classPtr->hIconSm = wc->hIconSm;
626 classPtr->hCursor = wc->hCursor;
627 classPtr->hbrBackground = wc->hbrBackground;
629 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
630 WIN_PROC_16, WIN_PROC_CLASS );
631 CLASS_SetMenuNameA( classPtr, MapSL(wc->lpszMenuName) );
636 /***********************************************************************
637 * RegisterClassExA (USER32.@)
639 ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
644 if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
646 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
647 wc->cbClsExtra, wc->cbWndExtra )))
649 GlobalDeleteAtom( atom );
653 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
654 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
655 wc->hbrBackground, wc->style, wc->cbClsExtra,
656 wc->cbWndExtra, classPtr );
658 classPtr->hIcon = (HICON16)wc->hIcon;
659 classPtr->hIconSm = (HICON16)wc->hIconSm;
660 classPtr->hCursor = (HCURSOR16)wc->hCursor;
661 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
662 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
663 WIN_PROC_32A, WIN_PROC_CLASS );
664 CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
669 /***********************************************************************
670 * RegisterClassExW (USER32.@)
672 ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
677 if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
679 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
680 wc->cbClsExtra, wc->cbWndExtra )))
682 GlobalDeleteAtom( atom );
686 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
687 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
688 wc->hbrBackground, wc->style, wc->cbClsExtra,
689 wc->cbWndExtra, classPtr );
691 classPtr->hIcon = (HICON16)wc->hIcon;
692 classPtr->hIconSm = (HICON16)wc->hIconSm;
693 classPtr->hCursor = (HCURSOR16)wc->hCursor;
694 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
695 WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)wc->lpfnWndProc,
696 WIN_PROC_32W, WIN_PROC_CLASS );
697 CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
702 /***********************************************************************
703 * UnregisterClass (USER.403)
705 BOOL16 WINAPI UnregisterClass16( LPCSTR className, HINSTANCE16 hInstance )
707 return UnregisterClassA( className, GetExePtr( hInstance ) );
710 /***********************************************************************
711 * UnregisterClassA (USER32.@)
714 BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance )
716 TRACE("%s %x\n",debugres_a(className), hInstance);
717 return CLASS_UnregisterClass( GlobalFindAtomA( className ), hInstance );
720 /***********************************************************************
721 * UnregisterClassW (USER32.@)
723 BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance )
725 TRACE("%s %x\n",debugres_w(className), hInstance);
726 return CLASS_UnregisterClass( GlobalFindAtomW( className ), hInstance );
730 /***********************************************************************
731 * GetClassWord (USER32.@)
733 WORD WINAPI GetClassWord( HWND hwnd, INT offset )
738 if (offset < 0) return GetClassLongA( hwnd, offset );
740 TRACE("%x %x\n",hwnd, offset);
742 if (!(class = get_class_ptr( hwnd ))) return 0;
744 if (offset <= class->cbClsExtra - sizeof(WORD))
745 retvalue = GET_WORD((char *)(class + 1) + offset);
747 SetLastError( ERROR_INVALID_INDEX );
748 release_class_ptr( class );
753 /***********************************************************************
754 * GetClassLong (USER.131)
756 LONG WINAPI GetClassLong16( HWND16 hwnd16, INT16 offset )
760 HWND hwnd = (HWND)(ULONG_PTR)hwnd16; /* no need for full handle */
762 TRACE("%x %d\n",hwnd, offset);
767 if (!(class = get_class_ptr( hwnd ))) return 0;
768 ret = (LONG)CLASS_GetProc( class, WIN_PROC_16 );
769 release_class_ptr( class );
772 ret = GetClassLongA( hwnd, offset );
773 return (LONG)SEGPTR_GET( (void *)ret );
775 return GetClassLongA( hwnd, offset );
780 /***********************************************************************
781 * GetClassLongA (USER32.@)
783 LONG WINAPI GetClassLongA( HWND hwnd, INT offset )
788 TRACE("%x %d\n", hwnd, offset);
790 if (!(class = get_class_ptr( hwnd ))) return 0;
794 if (offset <= class->cbClsExtra - sizeof(LONG))
795 retvalue = GET_DWORD((char *)(class + 1) + offset);
797 SetLastError( ERROR_INVALID_INDEX );
798 release_class_ptr( class );
804 case GCL_HBRBACKGROUND:
805 retvalue = (LONG)class->hbrBackground;
808 retvalue = (LONG)class->hCursor;
811 retvalue = (LONG)class->hIcon;
814 retvalue = (LONG)class->hIconSm;
817 retvalue = (LONG)class->style;
820 retvalue = (LONG)class->cbWndExtra;
823 retvalue = (LONG)class->cbClsExtra;
826 retvalue = (LONG)class->hInstance;
829 retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32A );
832 retvalue = (LONG)CLASS_GetMenuNameA( class );
835 retvalue = (DWORD)class->atomName;
838 SetLastError( ERROR_INVALID_INDEX );
841 release_class_ptr( class );
846 /***********************************************************************
847 * GetClassLongW (USER32.@)
849 LONG WINAPI GetClassLongW( HWND hwnd, INT offset )
854 if (offset != GCL_WNDPROC && offset != GCL_MENUNAME)
855 return GetClassLongA( hwnd, offset );
857 TRACE("%x %d\n", hwnd, offset);
859 if (!(class = get_class_ptr( hwnd ))) return 0;
861 if (offset == GCL_WNDPROC)
862 retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32W );
863 else /* GCL_MENUNAME */
864 retvalue = (LONG)CLASS_GetMenuNameW( class );
866 release_class_ptr( class );
871 /***********************************************************************
872 * SetClassWord (USER32.@)
874 WORD WINAPI SetClassWord( HWND hwnd, INT offset, WORD newval )
879 if (offset < 0) return SetClassLongA( hwnd, offset, (DWORD)newval );
881 TRACE("%x %d %x\n", hwnd, offset, newval);
883 if (!(class = get_class_ptr( hwnd ))) return 0;
885 if (offset <= class->cbClsExtra - sizeof(WORD))
887 void *ptr = (char *)(class + 1) + offset;
888 retval = GET_WORD(ptr);
889 PUT_WORD( ptr, newval );
891 else SetLastError( ERROR_INVALID_INDEX );
893 release_class_ptr( class );
898 /***********************************************************************
899 * SetClassLong (USER.132)
901 LONG WINAPI SetClassLong16( HWND16 hwnd16, INT16 offset, LONG newval )
905 HWND hwnd = (HWND)(ULONG_PTR)hwnd16; /* no need for full handle */
907 TRACE("%x %d %lx\n", hwnd, offset, newval);
912 if (!(class = get_class_ptr( hwnd ))) return 0;
913 retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_16 );
914 release_class_ptr( class );
917 newval = (LONG)MapSL( newval );
920 return SetClassLongA( hwnd, offset, newval );
925 /***********************************************************************
926 * SetClassLongA (USER32.@)
928 LONG WINAPI SetClassLongA( HWND hwnd, INT offset, LONG newval )
933 TRACE("%x %d %lx\n", hwnd, offset, newval);
935 if (!(class = get_class_ptr( hwnd ))) return 0;
939 if (offset <= class->cbClsExtra - sizeof(LONG))
941 void *ptr = (char *)(class + 1) + offset;
942 retval = GET_DWORD(ptr);
943 PUT_DWORD( ptr, newval );
945 else SetLastError( ERROR_INVALID_INDEX );
950 CLASS_SetMenuNameA( class, (LPCSTR)newval );
951 retval = 0; /* Old value is now meaningless anyway */
954 retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32A );
956 case GCL_HBRBACKGROUND:
957 retval = (LONG)class->hbrBackground;
958 class->hbrBackground = newval;
961 retval = (LONG)class->hCursor;
962 class->hCursor = newval;
965 retval = (LONG)class->hIcon;
966 class->hIcon = newval;
969 retval = (LONG)class->hIconSm;
970 class->hIconSm = newval;
973 retval = (LONG)class->style;
974 class->style = newval;
977 retval = (LONG)class->cbWndExtra;
978 class->cbWndExtra = newval;
981 retval = (LONG)class->cbClsExtra;
982 class->cbClsExtra = newval;
985 retval = (LONG)class->hInstance;
986 class->hInstance = newval;
989 retval = (DWORD)class->atomName;
990 class->atomName = newval;
993 SetLastError( ERROR_INVALID_INDEX );
996 release_class_ptr( class );
1001 /***********************************************************************
1002 * SetClassLongW (USER32.@)
1004 LONG WINAPI SetClassLongW( HWND hwnd, INT offset, LONG newval )
1009 if (offset != GCL_WNDPROC && offset != GCL_MENUNAME)
1010 return SetClassLongA( hwnd, offset, newval );
1012 TRACE("%x %d %lx\n", hwnd, offset, newval);
1014 if (!(class = get_class_ptr( hwnd ))) return 0;
1016 if (offset == GCL_WNDPROC)
1017 retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32W );
1018 else /* GCL_MENUNAME */
1020 CLASS_SetMenuNameW( class, (LPCWSTR)newval );
1021 retval = 0; /* Old value is now meaningless anyway */
1023 release_class_ptr( class );
1028 /***********************************************************************
1029 * GetClassNameA (USER32.@)
1031 INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
1036 if (!(class = get_class_ptr( hwnd ))) return 0;
1037 ret = GlobalGetAtomNameA( class->atomName, buffer, count );
1038 release_class_ptr( class );
1040 TRACE("%x %s %x\n",hwnd, debugstr_a(buffer), count);
1045 /***********************************************************************
1046 * GetClassNameW (USER32.@)
1048 INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
1053 if (!(class = get_class_ptr( hwnd ))) return 0;
1054 ret = GlobalGetAtomNameW( class->atomName, buffer, count );
1055 release_class_ptr( class );
1057 TRACE("%x %s %x\n",hwnd, debugstr_w(buffer), count);
1062 /***********************************************************************
1063 * GetClassInfo (USER.404)
1065 BOOL16 WINAPI GetClassInfo16( HINSTANCE16 hInstance, SEGPTR name, WNDCLASS16 *wc )
1070 TRACE("%x %s %p\n",hInstance, debugres_a(MapSL(name)), wc);
1072 hInstance = GetExePtr( hInstance );
1073 if (!(atom = GlobalFindAtomA( MapSL(name) )) ||
1074 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )))
1076 if ((hInstance != classPtr->hInstance) &&
1077 !(classPtr->style & CS_GLOBALCLASS)) /*BWCC likes to pass hInstance=0*/
1079 wc->style = (UINT16)classPtr->style;
1080 wc->lpfnWndProc = CLASS_GetProc( classPtr, WIN_PROC_16 );
1081 wc->cbClsExtra = (INT16)classPtr->cbClsExtra;
1082 wc->cbWndExtra = (INT16)classPtr->cbWndExtra;
1083 wc->hInstance = (HINSTANCE16)classPtr->hInstance;
1084 wc->hIcon = classPtr->hIcon;
1085 wc->hCursor = classPtr->hCursor;
1086 wc->hbrBackground = classPtr->hbrBackground;
1087 wc->lpszClassName = name;
1088 wc->lpszMenuName = (SEGPTR)CLASS_GetMenuNameA( classPtr );
1089 if (HIWORD(wc->lpszMenuName)) /* Make it a SEGPTR */
1090 wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
1095 /***********************************************************************
1096 * GetClassInfoA (USER32.@)
1098 BOOL WINAPI GetClassInfoA( HINSTANCE hInstance, LPCSTR name,
1104 TRACE("%x %p %p\n",hInstance, name, wc);
1106 /* workaround: if hInstance=NULL you expect to get the system classes
1107 but this classes (as example from comctl32.dll SysListView) won't be
1108 registered with hInstance=NULL in WINE because of the late loading
1109 of this dll. fixes file dialogs in WinWord95 (jsch)*/
1111 if (!(atom=GlobalFindAtomA(name)) || !(classPtr=CLASS_FindClassByAtom(atom,hInstance)))
1114 if (!(classPtr->style & CS_GLOBALCLASS) &&
1115 classPtr->hInstance &&
1116 (hInstance != classPtr->hInstance))
1118 if (hInstance) return FALSE;
1119 WARN("systemclass %s (hInst=0) demanded but only class with hInst!=0 found\n",name);
1122 wc->style = classPtr->style;
1123 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32A );
1124 wc->cbClsExtra = classPtr->cbClsExtra;
1125 wc->cbWndExtra = classPtr->cbWndExtra;
1126 wc->hInstance = hInstance;
1127 wc->hIcon = (HICON)classPtr->hIcon;
1128 wc->hCursor = (HCURSOR)classPtr->hCursor;
1129 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1130 wc->lpszMenuName = CLASS_GetMenuNameA( classPtr );
1131 wc->lpszClassName = name;
1136 /***********************************************************************
1137 * GetClassInfoW (USER32.@)
1139 BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name,
1145 TRACE("%x %p %p\n",hInstance, name, wc);
1147 if ( !(atom=GlobalFindAtomW(name)) ||
1148 !(classPtr=CLASS_FindClassByAtom(atom,hInstance))
1152 if (!(classPtr->style & CS_GLOBALCLASS) &&
1153 classPtr->hInstance &&
1154 (hInstance != classPtr->hInstance))
1156 if (hInstance) return FALSE;
1157 WARN("systemclass %s (hInst=0) demanded but only class with hInst!=0 found\n",debugstr_w(name));
1159 wc->style = classPtr->style;
1160 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
1161 wc->cbClsExtra = classPtr->cbClsExtra;
1162 wc->cbWndExtra = classPtr->cbWndExtra;
1163 wc->hInstance = hInstance;
1164 wc->hIcon = (HICON)classPtr->hIcon;
1165 wc->hCursor = (HCURSOR)classPtr->hCursor;
1166 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1167 wc->lpszMenuName = CLASS_GetMenuNameW( classPtr );
1168 wc->lpszClassName = name;
1173 /***********************************************************************
1174 * GetClassInfoEx (USER.398)
1176 * FIXME: this is just a guess, I have no idea if GetClassInfoEx() is the
1177 * same in Win16 as in Win32. --AJ
1179 BOOL16 WINAPI GetClassInfoEx16( HINSTANCE16 hInstance, SEGPTR name, WNDCLASSEX16 *wc )
1184 TRACE("%x %s %p\n",hInstance,debugres_a( MapSL(name) ), wc);
1186 hInstance = GetExePtr( hInstance );
1187 if (!(atom = GlobalFindAtomA( MapSL(name) )) ||
1188 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1189 (hInstance != classPtr->hInstance)) return FALSE;
1190 wc->style = classPtr->style;
1191 wc->lpfnWndProc = CLASS_GetProc( classPtr, WIN_PROC_16 );
1192 wc->cbClsExtra = (INT16)classPtr->cbClsExtra;
1193 wc->cbWndExtra = (INT16)classPtr->cbWndExtra;
1194 wc->hInstance = (HINSTANCE16)classPtr->hInstance;
1195 wc->hIcon = classPtr->hIcon;
1196 wc->hIconSm = classPtr->hIconSm;
1197 wc->hCursor = classPtr->hCursor;
1198 wc->hbrBackground = classPtr->hbrBackground;
1199 wc->lpszClassName = (SEGPTR)0;
1200 wc->lpszMenuName = (SEGPTR)CLASS_GetMenuNameA( classPtr );
1201 if (HIWORD(wc->lpszMenuName)) /* Make it a SEGPTR */
1202 wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
1203 wc->lpszClassName = name;
1205 /* We must return the atom of the class here instead of just TRUE. */
1210 /***********************************************************************
1211 * GetClassInfoExA (USER32.@)
1213 BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name,
1219 TRACE("%x %p %p\n",hInstance, name, wc);
1221 if (!(atom = GlobalFindAtomA( 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_32A );
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_GetMenuNameA( classPtr );
1234 wc->lpszClassName = name;
1236 /* We must return the atom of the class here instead of just TRUE. */
1241 /***********************************************************************
1242 * GetClassInfoExW (USER32.@)
1244 BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name,
1250 TRACE("%x %p %p\n",hInstance, name, wc);
1252 if (!(atom = GlobalFindAtomW( name )) ||
1253 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1254 (hInstance != classPtr->hInstance)) return FALSE;
1255 wc->style = classPtr->style;
1256 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
1257 wc->cbClsExtra = classPtr->cbClsExtra;
1258 wc->cbWndExtra = classPtr->cbWndExtra;
1259 wc->hInstance = classPtr->hInstance;
1260 wc->hIcon = (HICON)classPtr->hIcon;
1261 wc->hIconSm = (HICON)classPtr->hIconSm;
1262 wc->hCursor = (HCURSOR)classPtr->hCursor;
1263 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1264 wc->lpszMenuName = CLASS_GetMenuNameW( classPtr );
1265 wc->lpszClassName = name;
1267 /* We must return the atom of the class here instead of just TRUE. */
1272 #if 0 /* toolhelp is in kernel, so this cannot work */
1274 /***********************************************************************
1275 * ClassFirst (TOOLHELP.69)
1277 BOOL16 WINAPI ClassFirst16( CLASSENTRY *pClassEntry )
1279 TRACE("%p\n",pClassEntry);
1280 pClassEntry->wNext = 1;
1281 return ClassNext16( pClassEntry );
1285 /***********************************************************************
1286 * ClassNext (TOOLHELP.70)
1288 BOOL16 WINAPI ClassNext16( CLASSENTRY *pClassEntry )
1291 CLASS *class = firstClass;
1293 TRACE("%p\n",pClassEntry);
1295 if (!pClassEntry->wNext) return FALSE;
1296 for (i = 1; (i < pClassEntry->wNext) && class; i++) class = class->next;
1299 pClassEntry->wNext = 0;
1302 pClassEntry->hInst = class->hInstance;
1303 pClassEntry->wNext++;
1304 GlobalGetAtomNameA( class->atomName, pClassEntry->szClassName,
1305 sizeof(pClassEntry->szClassName) );