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.
16 #include "wine/port.h"
21 #include "wine/winbase16.h"
25 #include "wine/winuser16.h"
26 #include "wine/unicode.h"
33 #include "debugtools.h"
35 DEFAULT_DEBUG_CHANNEL(class);
37 typedef struct tagCLASS
39 struct tagCLASS *next; /* Next class */
40 struct tagCLASS *prev; /* Prev class */
41 UINT cWindows; /* Count of existing windows */
42 UINT style; /* Class style */
43 HWINDOWPROC winprocA; /* Window procedure (ASCII) */
44 HWINDOWPROC winprocW; /* Window procedure (Unicode) */
45 INT cbClsExtra; /* Class extra bytes */
46 INT cbWndExtra; /* Window extra bytes */
47 LPWSTR menuName; /* Default menu name (Unicode followed by ASCII) */
48 struct tagDCE *dce; /* Class DCE (if CS_CLASSDC) */
49 HINSTANCE hInstance; /* Module that created the task */
50 HICON hIcon; /* Default icon */
51 HICON hIconSm; /* Default small icon */
52 HCURSOR hCursor; /* Default cursor */
53 HBRUSH hbrBackground; /* Default background */
54 ATOM atomName; /* Name of the class */
57 static CLASS *firstClass;
59 /***********************************************************************
62 static CLASS *get_class_ptr( HWND hwnd, BOOL write_access )
64 WND *ptr = WIN_GetPtr( hwnd );
68 if (ptr != WND_OTHER_PROCESS) return ptr->class;
69 if (IsWindow( hwnd )) /* check other processes */
73 /* modifying classes in other processes is not allowed */
74 SetLastError( ERROR_ACCESS_DENIED );
77 FIXME( "reading from class of other process window %04x\n", hwnd );
78 /* DbgBreakPoint(); */
81 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
86 /***********************************************************************
89 inline static void release_class_ptr( CLASS *ptr )
95 /***********************************************************************
98 * Get the class winproc for a given proc type
100 static WNDPROC16 CLASS_GetProc( CLASS *classPtr, WINDOWPROCTYPE type )
102 HWINDOWPROC proc = classPtr->winprocA;
104 if (classPtr->winprocW)
106 /* if we have a Unicode proc, use it if we have no ASCII proc
107 * or if we have both and Unicode was requested
109 if (!proc || type == WIN_PROC_32W) proc = classPtr->winprocW;
111 return WINPROC_GetProc( proc, type );
115 /***********************************************************************
118 * Set the class winproc for a given proc type.
119 * Returns the previous window proc.
121 static WNDPROC16 CLASS_SetProc( CLASS *classPtr, WNDPROC newproc, WINDOWPROCTYPE type )
123 HWINDOWPROC *proc = &classPtr->winprocA;
126 if (classPtr->winprocW)
128 /* if we have a Unicode proc, use it if we have no ASCII proc
129 * or if we have both and Unicode was requested
131 if (!*proc || type == WIN_PROC_32W) proc = &classPtr->winprocW;
133 ret = WINPROC_GetProc( *proc, type );
134 WINPROC_SetProc( proc, (HWINDOWPROC)newproc, type, WIN_PROC_CLASS );
135 /* now free the one that we didn't set */
136 if (classPtr->winprocA && classPtr->winprocW)
138 if (proc == &classPtr->winprocA)
140 WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
141 classPtr->winprocW = 0;
145 WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
146 classPtr->winprocA = 0;
153 /***********************************************************************
156 * Get the menu name as a ASCII string.
158 inline static LPSTR CLASS_GetMenuNameA( CLASS *classPtr )
160 if (!HIWORD(classPtr->menuName)) return (LPSTR)classPtr->menuName;
161 return (LPSTR)(classPtr->menuName + strlenW(classPtr->menuName) + 1);
165 /***********************************************************************
168 * Get the menu name as a Unicode string.
170 inline static LPWSTR CLASS_GetMenuNameW( CLASS *classPtr )
172 return classPtr->menuName;
176 /***********************************************************************
179 * Set the menu name in a class structure by copying the string.
181 static void CLASS_SetMenuNameA( CLASS *classPtr, LPCSTR name )
183 if (HIWORD(classPtr->menuName)) SEGPTR_FREE( classPtr->menuName );
186 DWORD lenA = strlen(name) + 1;
187 DWORD lenW = MultiByteToWideChar( CP_ACP, 0, name, lenA, NULL, 0 );
188 classPtr->menuName = SEGPTR_ALLOC( lenA + lenW*sizeof(WCHAR) );
189 MultiByteToWideChar( CP_ACP, 0, name, lenA, classPtr->menuName, lenW );
190 memcpy( classPtr->menuName + lenW, name, lenA );
192 else classPtr->menuName = (LPWSTR)name;
196 /***********************************************************************
199 * Set the menu name in a class structure by copying the string.
201 static void CLASS_SetMenuNameW( CLASS *classPtr, LPCWSTR name )
203 if (HIWORD(classPtr->menuName)) SEGPTR_FREE( classPtr->menuName );
206 DWORD lenW = strlenW(name) + 1;
207 DWORD lenA = WideCharToMultiByte( CP_ACP, 0, name, lenW, NULL, 0, NULL, NULL );
208 classPtr->menuName = SEGPTR_ALLOC( lenA + lenW*sizeof(WCHAR) );
209 memcpy( classPtr->menuName, name, lenW*sizeof(WCHAR) );
210 WideCharToMultiByte( CP_ACP, 0, name, lenW,
211 (char *)(classPtr->menuName + lenW), lenA, NULL, NULL );
213 else classPtr->menuName = (LPWSTR)name;
217 /***********************************************************************
220 * Free a class structure.
222 static BOOL CLASS_FreeClass( CLASS *classPtr )
224 TRACE("%p\n", classPtr);
226 /* Check if we can remove this class */
228 if (classPtr->cWindows > 0)
230 SetLastError( ERROR_CLASS_HAS_WINDOWS );
234 /* Remove the class from the linked list */
236 if (classPtr->next) classPtr->next->prev = classPtr->prev;
237 if (classPtr->prev) classPtr->prev->next = classPtr->next;
238 else firstClass = classPtr->next;
240 /* Delete the class */
242 if (classPtr->dce) DCE_FreeDCE( classPtr->dce );
243 if (classPtr->hbrBackground > (HBRUSH)(COLOR_GRADIENTINACTIVECAPTION + 1))
244 DeleteObject( classPtr->hbrBackground );
245 GlobalDeleteAtom( classPtr->atomName );
246 WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
247 WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
248 HeapFree( GetProcessHeap(), 0, classPtr->menuName );
249 HeapFree( GetProcessHeap(), 0, classPtr );
254 /***********************************************************************
255 * CLASS_FreeModuleClasses
257 void CLASS_FreeModuleClasses( HMODULE16 hModule )
261 TRACE("0x%08x\n", hModule);
264 for (ptr = firstClass; ptr; ptr = next)
267 if (ptr->hInstance == hModule) CLASS_FreeClass( ptr );
273 /***********************************************************************
274 * CLASS_FindClassByAtom
276 * Return a pointer to the class.
277 * hinstance has been normalized by the caller.
280 * 980805 a local class will be found now if registred with hInst=0
281 * and looed up with a hInst!=0. msmoney does it (jsch)
283 * Local class registered with a USER instance handle are found as if
284 * they were global classes.
286 static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance )
288 CLASS * class, *tclass = 0, *user_class = 0;
289 HINSTANCE16 hUser = GetModuleHandle16("USER");
291 TRACE("0x%08x 0x%08x\n", atom, hinstance);
293 /* First search task-specific classes */
295 for (class = firstClass; (class); class = class->next)
297 if (class->style & CS_GLOBALCLASS) continue;
298 if (class->atomName == atom)
300 if (hinstance==class->hInstance || hinstance==0xffff)
302 TRACE("-- found local %p\n", class);
305 if (class->hInstance == 0) tclass = class;
306 else if(class->hInstance == hUser)
313 /* Then search global classes */
315 for (class = firstClass; (class); class = class->next)
317 if (!(class->style & CS_GLOBALCLASS)) continue;
318 if (class->atomName == atom)
320 TRACE("-- found global %p\n", class);
325 /* Check if there was a local class registered with USER */
328 TRACE("--found local USER class %p\n", user_class);
332 /* Then check if there was a local class with hInst=0*/
335 WARN("-- found local Class registred with hInst=0\n");
339 TRACE("-- not found\n");
344 /***********************************************************************
345 * CLASS_RegisterClass
347 * The real RegisterClass() functionality.
349 static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance,
350 DWORD style, INT classExtra, INT winExtra )
354 TRACE("atom=0x%x hinst=0x%x style=0x%lx clExtr=0x%x winExtr=0x%x\n",
355 atom, hInstance, style, classExtra, winExtra );
357 /* Check if a class with this name already exists */
358 classPtr = CLASS_FindClassByAtom( atom, hInstance );
361 /* Class can be created only if it is local and */
362 /* if the class with the same name is global. */
364 if ((style & CS_GLOBALCLASS) || !(classPtr->style & CS_GLOBALCLASS))
366 SetLastError( ERROR_CLASS_ALREADY_EXISTS );
371 /* Fix the extra bytes value */
373 if (classExtra < 0) classExtra = 0;
374 else if (classExtra > 40) /* Extra bytes are limited to 40 in Win32 */
375 WARN("Class extra bytes %d is > 40\n", classExtra);
376 if (winExtra < 0) winExtra = 0;
377 else if (winExtra > 40) /* Extra bytes are limited to 40 in Win32 */
378 WARN("Win extra bytes %d is > 40\n", winExtra );
380 /* Create the class */
382 classPtr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLASS) + classExtra );
383 if (!classPtr) return NULL;
384 classPtr->style = style;
385 classPtr->cbWndExtra = winExtra;
386 classPtr->cbClsExtra = classExtra;
387 classPtr->hInstance = hInstance;
388 classPtr->atomName = atom;
389 classPtr->dce = (style & CS_CLASSDC) ? DCE_AllocDCE( 0, DCE_CLASS_DC ) : NULL;
391 /* Other non-null values must be set by caller */
393 if ((classPtr->next = firstClass)) firstClass->prev = classPtr;
394 firstClass = classPtr;
399 /***********************************************************************
400 * CLASS_UnregisterClass
402 * The real UnregisterClass() functionality.
404 static BOOL CLASS_UnregisterClass( ATOM atom, HINSTANCE hInstance )
411 (classPtr = CLASS_FindClassByAtom( atom, hInstance )) &&
412 (classPtr->hInstance == hInstance))
414 ret = CLASS_FreeClass( classPtr );
416 else SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
423 /***********************************************************************
424 * CLASS_RegisterBuiltinClass
426 * Register a builtin control class.
427 * This allows having both ASCII and Unicode winprocs for the same class.
429 ATOM CLASS_RegisterBuiltinClass( const struct builtin_class_descr *descr )
434 if (!(atom = GlobalAddAtomA( descr->name ))) return 0;
436 if (!(classPtr = CLASS_RegisterClass( atom, 0, descr->style, 0, descr->extra )))
438 GlobalDeleteAtom( atom );
442 classPtr->hCursor = LoadCursorA( 0, descr->cursor );
443 classPtr->hbrBackground = descr->brush;
445 if (descr->procA) WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)descr->procA,
446 WIN_PROC_32A, WIN_PROC_CLASS );
447 if (descr->procW) WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)descr->procW,
448 WIN_PROC_32W, WIN_PROC_CLASS );
453 /***********************************************************************
456 * Add a new window using this class, and return the necessary
457 * information for creating the window.
459 CLASS *CLASS_AddWindow( ATOM atom, HINSTANCE inst, WINDOWPROCTYPE type,
460 INT *winExtra, WNDPROC *winproc, DWORD *style, struct tagDCE **dce )
463 if (type == WIN_PROC_16) inst = GetExePtr(inst);
465 if (!(class = CLASS_FindClassByAtom( atom, inst ))) return NULL;
468 if (type == WIN_PROC_32W)
470 if (!(*winproc = class->winprocW)) *winproc = class->winprocA;
474 if (!(*winproc = class->winprocA)) *winproc = class->winprocW;
476 *winExtra = class->cbWndExtra;
477 *style = class->style;
483 /***********************************************************************
486 * Remove a window from the class window count.
488 void CLASS_RemoveWindow( CLASS *cls )
490 if (cls && cls->cWindows) cls->cWindows--;
494 /***********************************************************************
495 * RegisterClass (USER.57)
497 ATOM WINAPI RegisterClass16( const WNDCLASS16 *wc )
501 int iSmIconWidth, iSmIconHeight;
502 HINSTANCE16 hInstance=GetExePtr(wc->hInstance);
504 if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0;
505 if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
506 wc->cbClsExtra, wc->cbWndExtra )))
508 GlobalDeleteAtom( atom );
512 TRACE("atom=%04x wndproc=%08lx hinst=%04x "
513 "bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
514 atom, (DWORD)wc->lpfnWndProc, hInstance,
515 wc->hbrBackground, wc->style, wc->cbClsExtra,
516 wc->cbWndExtra, classPtr,
517 HIWORD(wc->lpszClassName) ?
518 (char *)MapSL(wc->lpszClassName) : "" );
520 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
521 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
523 classPtr->hIcon = wc->hIcon;
524 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
525 iSmIconWidth, iSmIconHeight,
526 LR_COPYFROMRESOURCE);
527 classPtr->hCursor = wc->hCursor;
528 classPtr->hbrBackground = wc->hbrBackground;
530 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
531 WIN_PROC_16, WIN_PROC_CLASS );
532 CLASS_SetMenuNameA( classPtr, MapSL(wc->lpszMenuName) );
538 /***********************************************************************
539 * RegisterClassA (USER32.@)
541 * >0: Unique identifier
544 ATOM WINAPI RegisterClassA( const WNDCLASSA* wc ) /* [in] Address of structure with class data */
547 int iSmIconWidth, iSmIconHeight;
550 if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
552 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
553 wc->cbClsExtra, wc->cbWndExtra )))
555 GlobalDeleteAtom( atom );
559 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
560 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
561 wc->hbrBackground, wc->style, wc->cbClsExtra,
562 wc->cbWndExtra, classPtr,
563 HIWORD(wc->lpszClassName) ? wc->lpszClassName : "" );
565 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
566 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
568 classPtr->hIcon = wc->hIcon;
569 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
570 iSmIconWidth, iSmIconHeight,
571 LR_COPYFROMRESOURCE);
572 classPtr->hCursor = (HCURSOR16)wc->hCursor;
573 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
575 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
576 WIN_PROC_32A, WIN_PROC_CLASS );
577 CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
582 /***********************************************************************
583 * RegisterClassW (USER32.@)
585 ATOM WINAPI RegisterClassW( const WNDCLASSW* wc )
588 int iSmIconWidth, iSmIconHeight;
591 if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
593 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
594 wc->cbClsExtra, wc->cbWndExtra )))
596 GlobalDeleteAtom( atom );
600 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
601 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
602 wc->hbrBackground, wc->style, wc->cbClsExtra,
603 wc->cbWndExtra, classPtr );
605 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
606 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
608 classPtr->hIcon = wc->hIcon;
609 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
610 iSmIconWidth, iSmIconHeight,
611 LR_COPYFROMRESOURCE);
612 classPtr->hCursor = (HCURSOR16)wc->hCursor;
613 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
615 WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)wc->lpfnWndProc,
616 WIN_PROC_32W, WIN_PROC_CLASS );
617 CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
622 /***********************************************************************
623 * RegisterClassEx (USER.397)
625 ATOM WINAPI RegisterClassEx16( const WNDCLASSEX16 *wc )
629 HINSTANCE16 hInstance = GetExePtr( wc->hInstance );
631 if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0;
632 if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
633 wc->cbClsExtra, wc->cbWndExtra )))
635 GlobalDeleteAtom( atom );
639 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
640 atom, (DWORD)wc->lpfnWndProc, hInstance,
641 wc->hbrBackground, wc->style, wc->cbClsExtra,
642 wc->cbWndExtra, classPtr );
644 classPtr->hIcon = wc->hIcon;
645 classPtr->hIconSm = wc->hIconSm;
646 classPtr->hCursor = wc->hCursor;
647 classPtr->hbrBackground = wc->hbrBackground;
649 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
650 WIN_PROC_16, WIN_PROC_CLASS );
651 CLASS_SetMenuNameA( classPtr, MapSL(wc->lpszMenuName) );
656 /***********************************************************************
657 * RegisterClassExA (USER32.@)
659 ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
664 if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
666 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
667 wc->cbClsExtra, wc->cbWndExtra )))
669 GlobalDeleteAtom( atom );
673 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
674 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
675 wc->hbrBackground, wc->style, wc->cbClsExtra,
676 wc->cbWndExtra, classPtr );
678 classPtr->hIcon = (HICON16)wc->hIcon;
679 classPtr->hIconSm = (HICON16)wc->hIconSm;
680 classPtr->hCursor = (HCURSOR16)wc->hCursor;
681 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
682 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
683 WIN_PROC_32A, WIN_PROC_CLASS );
684 CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
689 /***********************************************************************
690 * RegisterClassExW (USER32.@)
692 ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
697 if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
699 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
700 wc->cbClsExtra, wc->cbWndExtra )))
702 GlobalDeleteAtom( atom );
706 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
707 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
708 wc->hbrBackground, wc->style, wc->cbClsExtra,
709 wc->cbWndExtra, classPtr );
711 classPtr->hIcon = (HICON16)wc->hIcon;
712 classPtr->hIconSm = (HICON16)wc->hIconSm;
713 classPtr->hCursor = (HCURSOR16)wc->hCursor;
714 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
715 WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)wc->lpfnWndProc,
716 WIN_PROC_32W, WIN_PROC_CLASS );
717 CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
722 /***********************************************************************
723 * UnregisterClass (USER.403)
725 BOOL16 WINAPI UnregisterClass16( LPCSTR className, HINSTANCE16 hInstance )
727 return UnregisterClassA( className, GetExePtr( hInstance ) );
730 /***********************************************************************
731 * UnregisterClassA (USER32.@)
734 BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance )
736 TRACE("%s %x\n",debugres_a(className), hInstance);
737 return CLASS_UnregisterClass( GlobalFindAtomA( className ), hInstance );
740 /***********************************************************************
741 * UnregisterClassW (USER32.@)
743 BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance )
745 TRACE("%s %x\n",debugres_w(className), hInstance);
746 return CLASS_UnregisterClass( GlobalFindAtomW( className ), hInstance );
750 /***********************************************************************
751 * GetClassWord (USER32.@)
753 WORD WINAPI GetClassWord( HWND hwnd, INT offset )
758 if (offset < 0) return GetClassLongA( hwnd, offset );
760 TRACE("%x %x\n",hwnd, offset);
762 if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
764 if (offset <= class->cbClsExtra - sizeof(WORD))
765 retvalue = GET_WORD((char *)(class + 1) + offset);
767 SetLastError( ERROR_INVALID_INDEX );
768 release_class_ptr( class );
773 /***********************************************************************
774 * GetClassLong (USER.131)
776 LONG WINAPI GetClassLong16( HWND16 hwnd16, INT16 offset )
780 HWND hwnd = (HWND)(ULONG_PTR)hwnd16; /* no need for full handle */
782 TRACE("%x %d\n",hwnd, offset);
787 if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
788 ret = (LONG)CLASS_GetProc( class, WIN_PROC_16 );
789 release_class_ptr( class );
792 ret = GetClassLongA( hwnd, offset );
793 return (LONG)SEGPTR_GET( (void *)ret );
795 return GetClassLongA( hwnd, offset );
800 /***********************************************************************
801 * GetClassLongA (USER32.@)
803 LONG WINAPI GetClassLongA( HWND hwnd, INT offset )
808 TRACE("%x %d\n", hwnd, offset);
810 if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
814 if (offset <= class->cbClsExtra - sizeof(LONG))
815 retvalue = GET_DWORD((char *)(class + 1) + offset);
817 SetLastError( ERROR_INVALID_INDEX );
818 release_class_ptr( class );
824 case GCL_HBRBACKGROUND:
825 retvalue = (LONG)class->hbrBackground;
828 retvalue = (LONG)class->hCursor;
831 retvalue = (LONG)class->hIcon;
834 retvalue = (LONG)class->hIconSm;
837 retvalue = (LONG)class->style;
840 retvalue = (LONG)class->cbWndExtra;
843 retvalue = (LONG)class->cbClsExtra;
846 retvalue = (LONG)class->hInstance;
849 retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32A );
852 retvalue = (LONG)CLASS_GetMenuNameA( class );
855 retvalue = (DWORD)class->atomName;
858 SetLastError( ERROR_INVALID_INDEX );
861 release_class_ptr( class );
866 /***********************************************************************
867 * GetClassLongW (USER32.@)
869 LONG WINAPI GetClassLongW( HWND hwnd, INT offset )
874 if (offset != GCL_WNDPROC && offset != GCL_MENUNAME)
875 return GetClassLongA( hwnd, offset );
877 TRACE("%x %d\n", hwnd, offset);
879 if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
881 if (offset == GCL_WNDPROC)
882 retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32W );
883 else /* GCL_MENUNAME */
884 retvalue = (LONG)CLASS_GetMenuNameW( class );
886 release_class_ptr( class );
891 /***********************************************************************
892 * SetClassWord (USER32.@)
894 WORD WINAPI SetClassWord( HWND hwnd, INT offset, WORD newval )
899 if (offset < 0) return SetClassLongA( hwnd, offset, (DWORD)newval );
901 TRACE("%x %d %x\n", hwnd, offset, newval);
903 if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
905 if (offset <= class->cbClsExtra - sizeof(WORD))
907 void *ptr = (char *)(class + 1) + offset;
908 retval = GET_WORD(ptr);
909 PUT_WORD( ptr, newval );
911 else SetLastError( ERROR_INVALID_INDEX );
913 release_class_ptr( class );
918 /***********************************************************************
919 * SetClassLong (USER.132)
921 LONG WINAPI SetClassLong16( HWND16 hwnd16, INT16 offset, LONG newval )
925 HWND hwnd = (HWND)(ULONG_PTR)hwnd16; /* no need for full handle */
927 TRACE("%x %d %lx\n", hwnd, offset, newval);
932 if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
933 retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_16 );
934 release_class_ptr( class );
937 newval = (LONG)MapSL( newval );
940 return SetClassLongA( hwnd, offset, newval );
945 /***********************************************************************
946 * SetClassLongA (USER32.@)
948 LONG WINAPI SetClassLongA( HWND hwnd, INT offset, LONG newval )
953 TRACE("%x %d %lx\n", hwnd, offset, newval);
955 if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
959 if (offset <= class->cbClsExtra - sizeof(LONG))
961 void *ptr = (char *)(class + 1) + offset;
962 retval = GET_DWORD(ptr);
963 PUT_DWORD( ptr, newval );
965 else SetLastError( ERROR_INVALID_INDEX );
970 CLASS_SetMenuNameA( class, (LPCSTR)newval );
971 retval = 0; /* Old value is now meaningless anyway */
974 retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32A );
976 case GCL_HBRBACKGROUND:
977 retval = (LONG)class->hbrBackground;
978 class->hbrBackground = newval;
981 retval = (LONG)class->hCursor;
982 class->hCursor = newval;
985 retval = (LONG)class->hIcon;
986 class->hIcon = newval;
989 retval = (LONG)class->hIconSm;
990 class->hIconSm = newval;
993 retval = (LONG)class->style;
994 class->style = newval;
997 retval = (LONG)class->cbWndExtra;
998 class->cbWndExtra = newval;
1001 retval = (LONG)class->hInstance;
1002 class->hInstance = newval;
1005 retval = (DWORD)class->atomName;
1006 class->atomName = newval;
1008 case GCL_CBCLSEXTRA: /* cannot change this one */
1009 SetLastError( ERROR_INVALID_PARAMETER );
1012 SetLastError( ERROR_INVALID_INDEX );
1015 release_class_ptr( class );
1020 /***********************************************************************
1021 * SetClassLongW (USER32.@)
1023 LONG WINAPI SetClassLongW( HWND hwnd, INT offset, LONG newval )
1028 if (offset != GCL_WNDPROC && offset != GCL_MENUNAME)
1029 return SetClassLongA( hwnd, offset, newval );
1031 TRACE("%x %d %lx\n", hwnd, offset, newval);
1033 if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
1035 if (offset == GCL_WNDPROC)
1036 retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32W );
1037 else /* GCL_MENUNAME */
1039 CLASS_SetMenuNameW( class, (LPCWSTR)newval );
1040 retval = 0; /* Old value is now meaningless anyway */
1042 release_class_ptr( class );
1047 /***********************************************************************
1048 * GetClassNameA (USER32.@)
1050 INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
1052 INT ret = GlobalGetAtomNameA( GetClassLongA( hwnd, GCW_ATOM ), buffer, count );
1054 TRACE("%x %s %x\n",hwnd, debugstr_a(buffer), count);
1059 /***********************************************************************
1060 * GetClassNameW (USER32.@)
1062 INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
1064 INT ret = GlobalGetAtomNameW( GetClassLongW( hwnd, GCW_ATOM ), buffer, count );
1066 TRACE("%x %s %x\n",hwnd, debugstr_w(buffer), count);
1071 /***********************************************************************
1072 * GetClassInfo (USER.404)
1074 BOOL16 WINAPI GetClassInfo16( HINSTANCE16 hInstance, SEGPTR name, WNDCLASS16 *wc )
1079 TRACE("%x %s %p\n",hInstance, debugres_a(MapSL(name)), wc);
1081 hInstance = GetExePtr( hInstance );
1082 if (!(atom = GlobalFindAtomA( MapSL(name) )) ||
1083 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )))
1085 if ((hInstance != classPtr->hInstance) &&
1086 !(classPtr->style & CS_GLOBALCLASS)) /*BWCC likes to pass hInstance=0*/
1088 wc->style = (UINT16)classPtr->style;
1089 wc->lpfnWndProc = CLASS_GetProc( classPtr, WIN_PROC_16 );
1090 wc->cbClsExtra = (INT16)classPtr->cbClsExtra;
1091 wc->cbWndExtra = (INT16)classPtr->cbWndExtra;
1092 wc->hInstance = classPtr->style & CS_GLOBALCLASS ? GetModuleHandle16("USER") : (HINSTANCE16)classPtr->hInstance;
1093 wc->hIcon = classPtr->hIcon;
1094 wc->hCursor = classPtr->hCursor;
1095 wc->hbrBackground = classPtr->hbrBackground;
1096 wc->lpszClassName = name;
1097 wc->lpszMenuName = (SEGPTR)CLASS_GetMenuNameA( classPtr );
1098 if (HIWORD(wc->lpszMenuName)) /* Make it a SEGPTR */
1099 wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
1104 /***********************************************************************
1105 * GetClassInfoA (USER32.@)
1107 BOOL WINAPI GetClassInfoA( HINSTANCE hInstance, LPCSTR name,
1113 TRACE("%x %p %p\n",hInstance, name, wc);
1115 /* workaround: if hInstance=NULL you expect to get the system classes
1116 but this classes (as example from comctl32.dll SysListView) won't be
1117 registered with hInstance=NULL in WINE because of the late loading
1118 of this dll. fixes file dialogs in WinWord95 (jsch)*/
1120 if (!(atom=GlobalFindAtomA(name)) || !(classPtr=CLASS_FindClassByAtom(atom,hInstance)))
1123 if (!(classPtr->style & CS_GLOBALCLASS) &&
1124 classPtr->hInstance &&
1125 (hInstance != classPtr->hInstance))
1127 if (hInstance) return FALSE;
1128 WARN("systemclass %s (hInst=0) demanded but only class with hInst!=0 found\n",name);
1131 wc->style = classPtr->style;
1132 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32A );
1133 wc->cbClsExtra = classPtr->cbClsExtra;
1134 wc->cbWndExtra = classPtr->cbWndExtra;
1135 wc->hInstance = hInstance;
1136 wc->hIcon = (HICON)classPtr->hIcon;
1137 wc->hCursor = (HCURSOR)classPtr->hCursor;
1138 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1139 wc->lpszMenuName = CLASS_GetMenuNameA( classPtr );
1140 wc->lpszClassName = name;
1145 /***********************************************************************
1146 * GetClassInfoW (USER32.@)
1148 BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name,
1154 TRACE("%x %p %p\n",hInstance, name, wc);
1156 if ( !(atom=GlobalFindAtomW(name)) ||
1157 !(classPtr=CLASS_FindClassByAtom(atom,hInstance))
1161 if (!(classPtr->style & CS_GLOBALCLASS) &&
1162 classPtr->hInstance &&
1163 (hInstance != classPtr->hInstance))
1165 if (hInstance) return FALSE;
1166 WARN("systemclass %s (hInst=0) demanded but only class with hInst!=0 found\n",debugstr_w(name));
1168 wc->style = classPtr->style;
1169 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
1170 wc->cbClsExtra = classPtr->cbClsExtra;
1171 wc->cbWndExtra = classPtr->cbWndExtra;
1172 wc->hInstance = hInstance;
1173 wc->hIcon = (HICON)classPtr->hIcon;
1174 wc->hCursor = (HCURSOR)classPtr->hCursor;
1175 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1176 wc->lpszMenuName = CLASS_GetMenuNameW( classPtr );
1177 wc->lpszClassName = name;
1182 /***********************************************************************
1183 * GetClassInfoEx (USER.398)
1185 * FIXME: this is just a guess, I have no idea if GetClassInfoEx() is the
1186 * same in Win16 as in Win32. --AJ
1188 BOOL16 WINAPI GetClassInfoEx16( HINSTANCE16 hInstance, SEGPTR name, WNDCLASSEX16 *wc )
1193 TRACE("%x %s %p\n",hInstance,debugres_a( MapSL(name) ), wc);
1195 hInstance = GetExePtr( hInstance );
1196 if (!(atom = GlobalFindAtomA( MapSL(name) )) ||
1197 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1198 (hInstance != classPtr->hInstance)) return FALSE;
1199 wc->style = classPtr->style;
1200 wc->lpfnWndProc = CLASS_GetProc( classPtr, WIN_PROC_16 );
1201 wc->cbClsExtra = (INT16)classPtr->cbClsExtra;
1202 wc->cbWndExtra = (INT16)classPtr->cbWndExtra;
1203 wc->hInstance = (HINSTANCE16)classPtr->hInstance;
1204 wc->hIcon = classPtr->hIcon;
1205 wc->hIconSm = classPtr->hIconSm;
1206 wc->hCursor = classPtr->hCursor;
1207 wc->hbrBackground = classPtr->hbrBackground;
1208 wc->lpszClassName = (SEGPTR)0;
1209 wc->lpszMenuName = (SEGPTR)CLASS_GetMenuNameA( classPtr );
1210 if (HIWORD(wc->lpszMenuName)) /* Make it a SEGPTR */
1211 wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
1212 wc->lpszClassName = name;
1214 /* We must return the atom of the class here instead of just TRUE. */
1219 /***********************************************************************
1220 * GetClassInfoExA (USER32.@)
1222 BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name,
1228 TRACE("%x %p %p\n",hInstance, name, wc);
1230 if (!(atom = GlobalFindAtomA( name )) ||
1231 !(classPtr = CLASS_FindClassByAtom( atom, hInstance ))
1232 /*|| (hInstance != classPtr->hInstance) */ ) return FALSE;
1233 wc->style = classPtr->style;
1234 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32A );
1235 wc->cbClsExtra = classPtr->cbClsExtra;
1236 wc->cbWndExtra = classPtr->cbWndExtra;
1237 wc->hInstance = classPtr->hInstance;
1238 wc->hIcon = (HICON)classPtr->hIcon;
1239 wc->hIconSm = (HICON)classPtr->hIconSm;
1240 wc->hCursor = (HCURSOR)classPtr->hCursor;
1241 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1242 wc->lpszMenuName = CLASS_GetMenuNameA( classPtr );
1243 wc->lpszClassName = name;
1245 /* We must return the atom of the class here instead of just TRUE. */
1250 /***********************************************************************
1251 * GetClassInfoExW (USER32.@)
1253 BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name,
1259 TRACE("%x %p %p\n",hInstance, name, wc);
1261 if (!(atom = GlobalFindAtomW( name )) ||
1262 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1263 (hInstance != classPtr->hInstance)) return FALSE;
1264 wc->style = classPtr->style;
1265 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
1266 wc->cbClsExtra = classPtr->cbClsExtra;
1267 wc->cbWndExtra = classPtr->cbWndExtra;
1268 wc->hInstance = classPtr->hInstance;
1269 wc->hIcon = (HICON)classPtr->hIcon;
1270 wc->hIconSm = (HICON)classPtr->hIconSm;
1271 wc->hCursor = (HCURSOR)classPtr->hCursor;
1272 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1273 wc->lpszMenuName = CLASS_GetMenuNameW( classPtr );
1274 wc->lpszClassName = name;
1276 /* We must return the atom of the class here instead of just TRUE. */
1281 #if 0 /* toolhelp is in kernel, so this cannot work */
1283 /***********************************************************************
1284 * ClassFirst (TOOLHELP.69)
1286 BOOL16 WINAPI ClassFirst16( CLASSENTRY *pClassEntry )
1288 TRACE("%p\n",pClassEntry);
1289 pClassEntry->wNext = 1;
1290 return ClassNext16( pClassEntry );
1294 /***********************************************************************
1295 * ClassNext (TOOLHELP.70)
1297 BOOL16 WINAPI ClassNext16( CLASSENTRY *pClassEntry )
1300 CLASS *class = firstClass;
1302 TRACE("%p\n",pClassEntry);
1304 if (!pClassEntry->wNext) return FALSE;
1305 for (i = 1; (i < pClassEntry->wNext) && class; i++) class = class->next;
1308 pClassEntry->wNext = 0;
1311 pClassEntry->hInst = class->hInstance;
1312 pClassEntry->wNext++;
1313 GlobalGetAtomNameA( class->atomName, pClassEntry->szClassName,
1314 sizeof(pClassEntry->szClassName) );