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.
15 #include "wine/port.h"
20 #include "wine/winbase16.h"
24 #include "wine/winuser16.h"
25 #include "wine/unicode.h"
32 #include "debugtools.h"
34 DEFAULT_DEBUG_CHANNEL(class);
36 typedef struct tagCLASS
38 struct tagCLASS *next; /* Next class */
39 struct tagCLASS *prev; /* Prev class */
40 UINT cWindows; /* Count of existing windows */
41 UINT style; /* Class style */
42 HWINDOWPROC winprocA; /* Window procedure (ASCII) */
43 HWINDOWPROC winprocW; /* Window procedure (Unicode) */
44 INT cbClsExtra; /* Class extra bytes */
45 INT cbWndExtra; /* Window extra bytes */
46 LPWSTR menuName; /* Default menu name (Unicode followed by ASCII) */
47 struct tagDCE *dce; /* Class DCE (if CS_CLASSDC) */
48 HINSTANCE hInstance; /* Module that created the task */
49 HICON hIcon; /* Default icon */
50 HICON hIconSm; /* Default small icon */
51 HCURSOR hCursor; /* Default cursor */
52 HBRUSH hbrBackground; /* Default background */
53 ATOM atomName; /* Name of the class */
56 static CLASS *firstClass;
58 /***********************************************************************
61 static CLASS *get_class_ptr( HWND hwnd, BOOL write_access )
63 WND *ptr = WIN_GetPtr( hwnd );
67 if (ptr != WND_OTHER_PROCESS) return ptr->class;
68 if (IsWindow( hwnd )) /* check other processes */
72 /* modifying classes in other processes is not allowed */
73 SetLastError( ERROR_ACCESS_DENIED );
76 FIXME( "reading from class of other process window %04x\n", hwnd );
77 /* DbgBreakPoint(); */
80 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
85 /***********************************************************************
88 inline static void release_class_ptr( CLASS *ptr )
94 /***********************************************************************
97 * Get the class winproc for a given proc type
99 static WNDPROC16 CLASS_GetProc( CLASS *classPtr, WINDOWPROCTYPE type )
101 HWINDOWPROC proc = classPtr->winprocA;
103 if (classPtr->winprocW)
105 /* if we have a Unicode proc, use it if we have no ASCII proc
106 * or if we have both and Unicode was requested
108 if (!proc || type == WIN_PROC_32W) proc = classPtr->winprocW;
110 return WINPROC_GetProc( proc, type );
114 /***********************************************************************
117 * Set the class winproc for a given proc type.
118 * Returns the previous window proc.
120 static WNDPROC16 CLASS_SetProc( CLASS *classPtr, WNDPROC newproc, WINDOWPROCTYPE type )
122 HWINDOWPROC *proc = &classPtr->winprocA;
125 if (classPtr->winprocW)
127 /* if we have a Unicode proc, use it if we have no ASCII proc
128 * or if we have both and Unicode was requested
130 if (!*proc || type == WIN_PROC_32W) proc = &classPtr->winprocW;
132 ret = WINPROC_GetProc( *proc, type );
133 WINPROC_SetProc( proc, (HWINDOWPROC)newproc, type, WIN_PROC_CLASS );
134 /* now free the one that we didn't set */
135 if (classPtr->winprocA && classPtr->winprocW)
137 if (proc == &classPtr->winprocA)
139 WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
140 classPtr->winprocW = 0;
144 WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
145 classPtr->winprocA = 0;
152 /***********************************************************************
155 * Get the menu name as a ASCII string.
157 inline static LPSTR CLASS_GetMenuNameA( CLASS *classPtr )
159 if (!HIWORD(classPtr->menuName)) return (LPSTR)classPtr->menuName;
160 return (LPSTR)(classPtr->menuName + strlenW(classPtr->menuName) + 1);
164 /***********************************************************************
167 * Get the menu name as a Unicode string.
169 inline static LPWSTR CLASS_GetMenuNameW( CLASS *classPtr )
171 return classPtr->menuName;
175 /***********************************************************************
178 * Set the menu name in a class structure by copying the string.
180 static void CLASS_SetMenuNameA( CLASS *classPtr, LPCSTR name )
182 if (HIWORD(classPtr->menuName)) SEGPTR_FREE( classPtr->menuName );
185 DWORD lenA = strlen(name) + 1;
186 DWORD lenW = MultiByteToWideChar( CP_ACP, 0, name, lenA, NULL, 0 );
187 classPtr->menuName = SEGPTR_ALLOC( lenA + lenW*sizeof(WCHAR) );
188 MultiByteToWideChar( CP_ACP, 0, name, lenA, classPtr->menuName, lenW );
189 memcpy( classPtr->menuName + lenW, name, lenA );
191 else classPtr->menuName = (LPWSTR)name;
195 /***********************************************************************
198 * Set the menu name in a class structure by copying the string.
200 static void CLASS_SetMenuNameW( CLASS *classPtr, LPCWSTR name )
202 if (HIWORD(classPtr->menuName)) SEGPTR_FREE( classPtr->menuName );
205 DWORD lenW = strlenW(name) + 1;
206 DWORD lenA = WideCharToMultiByte( CP_ACP, 0, name, lenW, NULL, 0, NULL, NULL );
207 classPtr->menuName = SEGPTR_ALLOC( lenA + lenW*sizeof(WCHAR) );
208 memcpy( classPtr->menuName, name, lenW*sizeof(WCHAR) );
209 WideCharToMultiByte( CP_ACP, 0, name, lenW,
210 (char *)(classPtr->menuName + lenW), lenA, NULL, NULL );
212 else classPtr->menuName = (LPWSTR)name;
216 /***********************************************************************
219 * Free a class structure.
221 static BOOL CLASS_FreeClass( CLASS *classPtr )
223 TRACE("%p\n", classPtr);
225 /* Check if we can remove this class */
227 if (classPtr->cWindows > 0)
229 SetLastError( ERROR_CLASS_HAS_WINDOWS );
233 /* Remove the class from the linked list */
235 if (classPtr->next) classPtr->next->prev = classPtr->prev;
236 if (classPtr->prev) classPtr->prev->next = classPtr->next;
237 else firstClass = classPtr->next;
239 /* Delete the class */
241 if (classPtr->dce) DCE_FreeDCE( classPtr->dce );
242 if (classPtr->hbrBackground > (HBRUSH)(COLOR_GRADIENTINACTIVECAPTION + 1))
243 DeleteObject( classPtr->hbrBackground );
244 GlobalDeleteAtom( classPtr->atomName );
245 WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
246 WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
247 HeapFree( GetProcessHeap(), 0, classPtr->menuName );
248 HeapFree( GetProcessHeap(), 0, classPtr );
253 /***********************************************************************
254 * CLASS_FreeModuleClasses
256 void CLASS_FreeModuleClasses( HMODULE16 hModule )
260 TRACE("0x%08x\n", hModule);
263 for (ptr = firstClass; ptr; ptr = next)
266 if (ptr->hInstance == hModule) CLASS_FreeClass( ptr );
272 /***********************************************************************
273 * CLASS_FindClassByAtom
275 * Return a pointer to the class.
276 * hinstance has been normalized by the caller.
279 * 980805 a local class will be found now if registred with hInst=0
280 * and looed up with a hInst!=0. msmoney does it (jsch)
282 static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance )
284 CLASS * class, *tclass=0;
286 TRACE("0x%08x 0x%08x\n", atom, hinstance);
288 /* First search task-specific classes */
290 for (class = firstClass; (class); class = class->next)
292 if (class->style & CS_GLOBALCLASS) continue;
293 if (class->atomName == atom)
295 if (hinstance==class->hInstance || hinstance==0xffff )
297 TRACE("-- found local %p\n", class);
300 if (class->hInstance==0) tclass = class;
304 /* Then search global classes */
306 for (class = firstClass; (class); class = class->next)
308 if (!(class->style & CS_GLOBALCLASS)) continue;
309 if (class->atomName == atom)
311 TRACE("-- found global %p\n", class);
316 /* Then check if there was a local class with hInst=0*/
319 WARN("-- found local Class registred with hInst=0\n");
323 TRACE("-- not found\n");
328 /***********************************************************************
329 * CLASS_RegisterClass
331 * The real RegisterClass() functionality.
333 static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance,
334 DWORD style, INT classExtra, INT winExtra )
338 TRACE("atom=0x%x hinst=0x%x style=0x%lx clExtr=0x%x winExtr=0x%x\n",
339 atom, hInstance, style, classExtra, winExtra );
341 /* Check if a class with this name already exists */
342 classPtr = CLASS_FindClassByAtom( atom, hInstance );
345 /* Class can be created only if it is local and */
346 /* if the class with the same name is global. */
348 if ((style & CS_GLOBALCLASS) || !(classPtr->style & CS_GLOBALCLASS))
350 SetLastError( ERROR_CLASS_ALREADY_EXISTS );
355 /* Fix the extra bytes value */
357 if (classExtra < 0) classExtra = 0;
358 else if (classExtra > 40) /* Extra bytes are limited to 40 in Win32 */
359 WARN("Class extra bytes %d is > 40\n", classExtra);
360 if (winExtra < 0) winExtra = 0;
361 else if (winExtra > 40) /* Extra bytes are limited to 40 in Win32 */
362 WARN("Win extra bytes %d is > 40\n", winExtra );
364 /* Create the class */
366 classPtr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLASS) + classExtra );
367 if (!classPtr) return NULL;
368 classPtr->style = style;
369 classPtr->cbWndExtra = winExtra;
370 classPtr->cbClsExtra = classExtra;
371 classPtr->hInstance = hInstance;
372 classPtr->atomName = atom;
373 classPtr->dce = (style & CS_CLASSDC) ? DCE_AllocDCE( 0, DCE_CLASS_DC ) : NULL;
375 /* Other non-null values must be set by caller */
377 if ((classPtr->next = firstClass)) firstClass->prev = classPtr;
378 firstClass = classPtr;
383 /***********************************************************************
384 * CLASS_UnregisterClass
386 * The real UnregisterClass() functionality.
388 static BOOL CLASS_UnregisterClass( ATOM atom, HINSTANCE hInstance )
395 (classPtr = CLASS_FindClassByAtom( atom, hInstance )) &&
396 (classPtr->hInstance == hInstance))
398 ret = CLASS_FreeClass( classPtr );
400 else SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
407 /***********************************************************************
408 * CLASS_RegisterBuiltinClass
410 * Register a builtin control class.
411 * This allows having both ASCII and Unicode winprocs for the same class.
413 ATOM CLASS_RegisterBuiltinClass( const struct builtin_class_descr *descr )
418 if (!(atom = GlobalAddAtomA( descr->name ))) return 0;
420 if (!(classPtr = CLASS_RegisterClass( atom, 0, descr->style, 0, descr->extra )))
422 GlobalDeleteAtom( atom );
426 classPtr->hCursor = LoadCursorA( 0, descr->cursor );
427 classPtr->hbrBackground = descr->brush;
429 if (descr->procA) WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)descr->procA,
430 WIN_PROC_32A, WIN_PROC_CLASS );
431 if (descr->procW) WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)descr->procW,
432 WIN_PROC_32W, WIN_PROC_CLASS );
437 /***********************************************************************
440 * Add a new window using this class, and return the necessary
441 * information for creating the window.
443 CLASS *CLASS_AddWindow( ATOM atom, HINSTANCE inst, WINDOWPROCTYPE type,
444 INT *winExtra, WNDPROC *winproc, DWORD *style, struct tagDCE **dce )
447 if (type == WIN_PROC_16) inst = GetExePtr(inst);
449 if (!(class = CLASS_FindClassByAtom( atom, inst ))) return NULL;
452 if (type == WIN_PROC_32W)
454 if (!(*winproc = class->winprocW)) *winproc = class->winprocA;
458 if (!(*winproc = class->winprocA)) *winproc = class->winprocW;
460 *winExtra = class->cbWndExtra;
461 *style = class->style;
467 /***********************************************************************
470 * Remove a window from the class window count.
472 void CLASS_RemoveWindow( CLASS *cls )
474 if (cls && cls->cWindows) cls->cWindows--;
478 /***********************************************************************
479 * RegisterClass (USER.57)
481 ATOM WINAPI RegisterClass16( const WNDCLASS16 *wc )
485 int iSmIconWidth, iSmIconHeight;
486 HINSTANCE16 hInstance=GetExePtr(wc->hInstance);
488 if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0;
489 if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
490 wc->cbClsExtra, wc->cbWndExtra )))
492 GlobalDeleteAtom( atom );
496 TRACE("atom=%04x wndproc=%08lx hinst=%04x "
497 "bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
498 atom, (DWORD)wc->lpfnWndProc, hInstance,
499 wc->hbrBackground, wc->style, wc->cbClsExtra,
500 wc->cbWndExtra, classPtr,
501 HIWORD(wc->lpszClassName) ?
502 (char *)MapSL(wc->lpszClassName) : "" );
504 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
505 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
507 classPtr->hIcon = wc->hIcon;
508 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
509 iSmIconWidth, iSmIconHeight,
510 LR_COPYFROMRESOURCE);
511 classPtr->hCursor = wc->hCursor;
512 classPtr->hbrBackground = wc->hbrBackground;
514 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
515 WIN_PROC_16, WIN_PROC_CLASS );
516 CLASS_SetMenuNameA( classPtr, MapSL(wc->lpszMenuName) );
522 /***********************************************************************
523 * RegisterClassA (USER32.@)
525 * >0: Unique identifier
528 ATOM WINAPI RegisterClassA( const WNDCLASSA* wc ) /* [in] Address of structure with class data */
531 int iSmIconWidth, iSmIconHeight;
534 if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
536 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
537 wc->cbClsExtra, wc->cbWndExtra )))
539 GlobalDeleteAtom( atom );
543 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
544 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
545 wc->hbrBackground, wc->style, wc->cbClsExtra,
546 wc->cbWndExtra, classPtr,
547 HIWORD(wc->lpszClassName) ? wc->lpszClassName : "" );
549 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
550 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
552 classPtr->hIcon = wc->hIcon;
553 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
554 iSmIconWidth, iSmIconHeight,
555 LR_COPYFROMRESOURCE);
556 classPtr->hCursor = (HCURSOR16)wc->hCursor;
557 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
559 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
560 WIN_PROC_32A, WIN_PROC_CLASS );
561 CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
566 /***********************************************************************
567 * RegisterClassW (USER32.@)
569 ATOM WINAPI RegisterClassW( const WNDCLASSW* wc )
572 int iSmIconWidth, iSmIconHeight;
575 if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
577 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
578 wc->cbClsExtra, wc->cbWndExtra )))
580 GlobalDeleteAtom( atom );
584 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
585 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
586 wc->hbrBackground, wc->style, wc->cbClsExtra,
587 wc->cbWndExtra, classPtr );
589 iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
590 iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
592 classPtr->hIcon = wc->hIcon;
593 classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
594 iSmIconWidth, iSmIconHeight,
595 LR_COPYFROMRESOURCE);
596 classPtr->hCursor = (HCURSOR16)wc->hCursor;
597 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
599 WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)wc->lpfnWndProc,
600 WIN_PROC_32W, WIN_PROC_CLASS );
601 CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
606 /***********************************************************************
607 * RegisterClassEx (USER.397)
609 ATOM WINAPI RegisterClassEx16( const WNDCLASSEX16 *wc )
613 HINSTANCE16 hInstance = GetExePtr( wc->hInstance );
615 if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0;
616 if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
617 wc->cbClsExtra, wc->cbWndExtra )))
619 GlobalDeleteAtom( atom );
623 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
624 atom, (DWORD)wc->lpfnWndProc, hInstance,
625 wc->hbrBackground, wc->style, wc->cbClsExtra,
626 wc->cbWndExtra, classPtr );
628 classPtr->hIcon = wc->hIcon;
629 classPtr->hIconSm = wc->hIconSm;
630 classPtr->hCursor = wc->hCursor;
631 classPtr->hbrBackground = wc->hbrBackground;
633 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
634 WIN_PROC_16, WIN_PROC_CLASS );
635 CLASS_SetMenuNameA( classPtr, MapSL(wc->lpszMenuName) );
640 /***********************************************************************
641 * RegisterClassExA (USER32.@)
643 ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
648 if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
650 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
651 wc->cbClsExtra, wc->cbWndExtra )))
653 GlobalDeleteAtom( atom );
657 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
658 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
659 wc->hbrBackground, wc->style, wc->cbClsExtra,
660 wc->cbWndExtra, classPtr );
662 classPtr->hIcon = (HICON16)wc->hIcon;
663 classPtr->hIconSm = (HICON16)wc->hIconSm;
664 classPtr->hCursor = (HCURSOR16)wc->hCursor;
665 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
666 WINPROC_SetProc( &classPtr->winprocA, (HWINDOWPROC)wc->lpfnWndProc,
667 WIN_PROC_32A, WIN_PROC_CLASS );
668 CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
673 /***********************************************************************
674 * RegisterClassExW (USER32.@)
676 ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
681 if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
683 if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
684 wc->cbClsExtra, wc->cbWndExtra )))
686 GlobalDeleteAtom( atom );
690 TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
691 atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
692 wc->hbrBackground, wc->style, wc->cbClsExtra,
693 wc->cbWndExtra, classPtr );
695 classPtr->hIcon = (HICON16)wc->hIcon;
696 classPtr->hIconSm = (HICON16)wc->hIconSm;
697 classPtr->hCursor = (HCURSOR16)wc->hCursor;
698 classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
699 WINPROC_SetProc( &classPtr->winprocW, (HWINDOWPROC)wc->lpfnWndProc,
700 WIN_PROC_32W, WIN_PROC_CLASS );
701 CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
706 /***********************************************************************
707 * UnregisterClass (USER.403)
709 BOOL16 WINAPI UnregisterClass16( LPCSTR className, HINSTANCE16 hInstance )
711 return UnregisterClassA( className, GetExePtr( hInstance ) );
714 /***********************************************************************
715 * UnregisterClassA (USER32.@)
718 BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance )
720 TRACE("%s %x\n",debugres_a(className), hInstance);
721 return CLASS_UnregisterClass( GlobalFindAtomA( className ), hInstance );
724 /***********************************************************************
725 * UnregisterClassW (USER32.@)
727 BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance )
729 TRACE("%s %x\n",debugres_w(className), hInstance);
730 return CLASS_UnregisterClass( GlobalFindAtomW( className ), hInstance );
734 /***********************************************************************
735 * GetClassWord (USER32.@)
737 WORD WINAPI GetClassWord( HWND hwnd, INT offset )
742 if (offset < 0) return GetClassLongA( hwnd, offset );
744 TRACE("%x %x\n",hwnd, offset);
746 if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
748 if (offset <= class->cbClsExtra - sizeof(WORD))
749 retvalue = GET_WORD((char *)(class + 1) + offset);
751 SetLastError( ERROR_INVALID_INDEX );
752 release_class_ptr( class );
757 /***********************************************************************
758 * GetClassLong (USER.131)
760 LONG WINAPI GetClassLong16( HWND16 hwnd16, INT16 offset )
764 HWND hwnd = (HWND)(ULONG_PTR)hwnd16; /* no need for full handle */
766 TRACE("%x %d\n",hwnd, offset);
771 if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
772 ret = (LONG)CLASS_GetProc( class, WIN_PROC_16 );
773 release_class_ptr( class );
776 ret = GetClassLongA( hwnd, offset );
777 return (LONG)SEGPTR_GET( (void *)ret );
779 return GetClassLongA( hwnd, offset );
784 /***********************************************************************
785 * GetClassLongA (USER32.@)
787 LONG WINAPI GetClassLongA( HWND hwnd, INT offset )
792 TRACE("%x %d\n", hwnd, offset);
794 if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
798 if (offset <= class->cbClsExtra - sizeof(LONG))
799 retvalue = GET_DWORD((char *)(class + 1) + offset);
801 SetLastError( ERROR_INVALID_INDEX );
802 release_class_ptr( class );
808 case GCL_HBRBACKGROUND:
809 retvalue = (LONG)class->hbrBackground;
812 retvalue = (LONG)class->hCursor;
815 retvalue = (LONG)class->hIcon;
818 retvalue = (LONG)class->hIconSm;
821 retvalue = (LONG)class->style;
824 retvalue = (LONG)class->cbWndExtra;
827 retvalue = (LONG)class->cbClsExtra;
830 retvalue = (LONG)class->hInstance;
833 retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32A );
836 retvalue = (LONG)CLASS_GetMenuNameA( class );
839 retvalue = (DWORD)class->atomName;
842 SetLastError( ERROR_INVALID_INDEX );
845 release_class_ptr( class );
850 /***********************************************************************
851 * GetClassLongW (USER32.@)
853 LONG WINAPI GetClassLongW( HWND hwnd, INT offset )
858 if (offset != GCL_WNDPROC && offset != GCL_MENUNAME)
859 return GetClassLongA( hwnd, offset );
861 TRACE("%x %d\n", hwnd, offset);
863 if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
865 if (offset == GCL_WNDPROC)
866 retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32W );
867 else /* GCL_MENUNAME */
868 retvalue = (LONG)CLASS_GetMenuNameW( class );
870 release_class_ptr( class );
875 /***********************************************************************
876 * SetClassWord (USER32.@)
878 WORD WINAPI SetClassWord( HWND hwnd, INT offset, WORD newval )
883 if (offset < 0) return SetClassLongA( hwnd, offset, (DWORD)newval );
885 TRACE("%x %d %x\n", hwnd, offset, newval);
887 if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
889 if (offset <= class->cbClsExtra - sizeof(WORD))
891 void *ptr = (char *)(class + 1) + offset;
892 retval = GET_WORD(ptr);
893 PUT_WORD( ptr, newval );
895 else SetLastError( ERROR_INVALID_INDEX );
897 release_class_ptr( class );
902 /***********************************************************************
903 * SetClassLong (USER.132)
905 LONG WINAPI SetClassLong16( HWND16 hwnd16, INT16 offset, LONG newval )
909 HWND hwnd = (HWND)(ULONG_PTR)hwnd16; /* no need for full handle */
911 TRACE("%x %d %lx\n", hwnd, offset, newval);
916 if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
917 retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_16 );
918 release_class_ptr( class );
921 newval = (LONG)MapSL( newval );
924 return SetClassLongA( hwnd, offset, newval );
929 /***********************************************************************
930 * SetClassLongA (USER32.@)
932 LONG WINAPI SetClassLongA( HWND hwnd, INT offset, LONG newval )
937 TRACE("%x %d %lx\n", hwnd, offset, newval);
939 if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
943 if (offset <= class->cbClsExtra - sizeof(LONG))
945 void *ptr = (char *)(class + 1) + offset;
946 retval = GET_DWORD(ptr);
947 PUT_DWORD( ptr, newval );
949 else SetLastError( ERROR_INVALID_INDEX );
954 CLASS_SetMenuNameA( class, (LPCSTR)newval );
955 retval = 0; /* Old value is now meaningless anyway */
958 retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32A );
960 case GCL_HBRBACKGROUND:
961 retval = (LONG)class->hbrBackground;
962 class->hbrBackground = newval;
965 retval = (LONG)class->hCursor;
966 class->hCursor = newval;
969 retval = (LONG)class->hIcon;
970 class->hIcon = newval;
973 retval = (LONG)class->hIconSm;
974 class->hIconSm = newval;
977 retval = (LONG)class->style;
978 class->style = newval;
981 retval = (LONG)class->cbWndExtra;
982 class->cbWndExtra = newval;
985 retval = (LONG)class->hInstance;
986 class->hInstance = newval;
989 retval = (DWORD)class->atomName;
990 class->atomName = newval;
992 case GCL_CBCLSEXTRA: /* cannot change this one */
993 SetLastError( ERROR_INVALID_PARAMETER );
996 SetLastError( ERROR_INVALID_INDEX );
999 release_class_ptr( class );
1004 /***********************************************************************
1005 * SetClassLongW (USER32.@)
1007 LONG WINAPI SetClassLongW( HWND hwnd, INT offset, LONG newval )
1012 if (offset != GCL_WNDPROC && offset != GCL_MENUNAME)
1013 return SetClassLongA( hwnd, offset, newval );
1015 TRACE("%x %d %lx\n", hwnd, offset, newval);
1017 if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
1019 if (offset == GCL_WNDPROC)
1020 retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32W );
1021 else /* GCL_MENUNAME */
1023 CLASS_SetMenuNameW( class, (LPCWSTR)newval );
1024 retval = 0; /* Old value is now meaningless anyway */
1026 release_class_ptr( class );
1031 /***********************************************************************
1032 * GetClassNameA (USER32.@)
1034 INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
1036 INT ret = GlobalGetAtomNameA( GetClassLongA( hwnd, GCW_ATOM ), buffer, count );
1038 TRACE("%x %s %x\n",hwnd, debugstr_a(buffer), count);
1043 /***********************************************************************
1044 * GetClassNameW (USER32.@)
1046 INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
1048 INT ret = GlobalGetAtomNameW( GetClassLongW( hwnd, GCW_ATOM ), buffer, count );
1050 TRACE("%x %s %x\n",hwnd, debugstr_w(buffer), count);
1055 /***********************************************************************
1056 * GetClassInfo (USER.404)
1058 BOOL16 WINAPI GetClassInfo16( HINSTANCE16 hInstance, SEGPTR name, WNDCLASS16 *wc )
1063 TRACE("%x %s %p\n",hInstance, debugres_a(MapSL(name)), wc);
1065 hInstance = GetExePtr( hInstance );
1066 if (!(atom = GlobalFindAtomA( MapSL(name) )) ||
1067 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )))
1069 if ((hInstance != classPtr->hInstance) &&
1070 !(classPtr->style & CS_GLOBALCLASS)) /*BWCC likes to pass hInstance=0*/
1072 wc->style = (UINT16)classPtr->style;
1073 wc->lpfnWndProc = CLASS_GetProc( classPtr, WIN_PROC_16 );
1074 wc->cbClsExtra = (INT16)classPtr->cbClsExtra;
1075 wc->cbWndExtra = (INT16)classPtr->cbWndExtra;
1076 wc->hInstance = (HINSTANCE16)classPtr->hInstance;
1077 wc->hIcon = classPtr->hIcon;
1078 wc->hCursor = classPtr->hCursor;
1079 wc->hbrBackground = classPtr->hbrBackground;
1080 wc->lpszClassName = name;
1081 wc->lpszMenuName = (SEGPTR)CLASS_GetMenuNameA( classPtr );
1082 if (HIWORD(wc->lpszMenuName)) /* Make it a SEGPTR */
1083 wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
1088 /***********************************************************************
1089 * GetClassInfoA (USER32.@)
1091 BOOL WINAPI GetClassInfoA( HINSTANCE hInstance, LPCSTR name,
1097 TRACE("%x %p %p\n",hInstance, name, wc);
1099 /* workaround: if hInstance=NULL you expect to get the system classes
1100 but this classes (as example from comctl32.dll SysListView) won't be
1101 registered with hInstance=NULL in WINE because of the late loading
1102 of this dll. fixes file dialogs in WinWord95 (jsch)*/
1104 if (!(atom=GlobalFindAtomA(name)) || !(classPtr=CLASS_FindClassByAtom(atom,hInstance)))
1107 if (!(classPtr->style & CS_GLOBALCLASS) &&
1108 classPtr->hInstance &&
1109 (hInstance != classPtr->hInstance))
1111 if (hInstance) return FALSE;
1112 WARN("systemclass %s (hInst=0) demanded but only class with hInst!=0 found\n",name);
1115 wc->style = classPtr->style;
1116 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32A );
1117 wc->cbClsExtra = classPtr->cbClsExtra;
1118 wc->cbWndExtra = classPtr->cbWndExtra;
1119 wc->hInstance = hInstance;
1120 wc->hIcon = (HICON)classPtr->hIcon;
1121 wc->hCursor = (HCURSOR)classPtr->hCursor;
1122 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1123 wc->lpszMenuName = CLASS_GetMenuNameA( classPtr );
1124 wc->lpszClassName = name;
1129 /***********************************************************************
1130 * GetClassInfoW (USER32.@)
1132 BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name,
1138 TRACE("%x %p %p\n",hInstance, name, wc);
1140 if ( !(atom=GlobalFindAtomW(name)) ||
1141 !(classPtr=CLASS_FindClassByAtom(atom,hInstance))
1145 if (!(classPtr->style & CS_GLOBALCLASS) &&
1146 classPtr->hInstance &&
1147 (hInstance != classPtr->hInstance))
1149 if (hInstance) return FALSE;
1150 WARN("systemclass %s (hInst=0) demanded but only class with hInst!=0 found\n",debugstr_w(name));
1152 wc->style = classPtr->style;
1153 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
1154 wc->cbClsExtra = classPtr->cbClsExtra;
1155 wc->cbWndExtra = classPtr->cbWndExtra;
1156 wc->hInstance = hInstance;
1157 wc->hIcon = (HICON)classPtr->hIcon;
1158 wc->hCursor = (HCURSOR)classPtr->hCursor;
1159 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1160 wc->lpszMenuName = CLASS_GetMenuNameW( classPtr );
1161 wc->lpszClassName = name;
1166 /***********************************************************************
1167 * GetClassInfoEx (USER.398)
1169 * FIXME: this is just a guess, I have no idea if GetClassInfoEx() is the
1170 * same in Win16 as in Win32. --AJ
1172 BOOL16 WINAPI GetClassInfoEx16( HINSTANCE16 hInstance, SEGPTR name, WNDCLASSEX16 *wc )
1177 TRACE("%x %s %p\n",hInstance,debugres_a( MapSL(name) ), wc);
1179 hInstance = GetExePtr( hInstance );
1180 if (!(atom = GlobalFindAtomA( MapSL(name) )) ||
1181 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1182 (hInstance != classPtr->hInstance)) return FALSE;
1183 wc->style = classPtr->style;
1184 wc->lpfnWndProc = CLASS_GetProc( classPtr, WIN_PROC_16 );
1185 wc->cbClsExtra = (INT16)classPtr->cbClsExtra;
1186 wc->cbWndExtra = (INT16)classPtr->cbWndExtra;
1187 wc->hInstance = (HINSTANCE16)classPtr->hInstance;
1188 wc->hIcon = classPtr->hIcon;
1189 wc->hIconSm = classPtr->hIconSm;
1190 wc->hCursor = classPtr->hCursor;
1191 wc->hbrBackground = classPtr->hbrBackground;
1192 wc->lpszClassName = (SEGPTR)0;
1193 wc->lpszMenuName = (SEGPTR)CLASS_GetMenuNameA( classPtr );
1194 if (HIWORD(wc->lpszMenuName)) /* Make it a SEGPTR */
1195 wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
1196 wc->lpszClassName = name;
1198 /* We must return the atom of the class here instead of just TRUE. */
1203 /***********************************************************************
1204 * GetClassInfoExA (USER32.@)
1206 BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name,
1212 TRACE("%x %p %p\n",hInstance, name, wc);
1214 if (!(atom = GlobalFindAtomA( name )) ||
1215 !(classPtr = CLASS_FindClassByAtom( atom, hInstance ))
1216 /*|| (hInstance != classPtr->hInstance) */ ) return FALSE;
1217 wc->style = classPtr->style;
1218 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32A );
1219 wc->cbClsExtra = classPtr->cbClsExtra;
1220 wc->cbWndExtra = classPtr->cbWndExtra;
1221 wc->hInstance = classPtr->hInstance;
1222 wc->hIcon = (HICON)classPtr->hIcon;
1223 wc->hIconSm = (HICON)classPtr->hIconSm;
1224 wc->hCursor = (HCURSOR)classPtr->hCursor;
1225 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1226 wc->lpszMenuName = CLASS_GetMenuNameA( classPtr );
1227 wc->lpszClassName = name;
1229 /* We must return the atom of the class here instead of just TRUE. */
1234 /***********************************************************************
1235 * GetClassInfoExW (USER32.@)
1237 BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name,
1243 TRACE("%x %p %p\n",hInstance, name, wc);
1245 if (!(atom = GlobalFindAtomW( name )) ||
1246 !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
1247 (hInstance != classPtr->hInstance)) return FALSE;
1248 wc->style = classPtr->style;
1249 wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
1250 wc->cbClsExtra = classPtr->cbClsExtra;
1251 wc->cbWndExtra = classPtr->cbWndExtra;
1252 wc->hInstance = classPtr->hInstance;
1253 wc->hIcon = (HICON)classPtr->hIcon;
1254 wc->hIconSm = (HICON)classPtr->hIconSm;
1255 wc->hCursor = (HCURSOR)classPtr->hCursor;
1256 wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
1257 wc->lpszMenuName = CLASS_GetMenuNameW( classPtr );
1258 wc->lpszClassName = name;
1260 /* We must return the atom of the class here instead of just TRUE. */
1265 #if 0 /* toolhelp is in kernel, so this cannot work */
1267 /***********************************************************************
1268 * ClassFirst (TOOLHELP.69)
1270 BOOL16 WINAPI ClassFirst16( CLASSENTRY *pClassEntry )
1272 TRACE("%p\n",pClassEntry);
1273 pClassEntry->wNext = 1;
1274 return ClassNext16( pClassEntry );
1278 /***********************************************************************
1279 * ClassNext (TOOLHELP.70)
1281 BOOL16 WINAPI ClassNext16( CLASSENTRY *pClassEntry )
1284 CLASS *class = firstClass;
1286 TRACE("%p\n",pClassEntry);
1288 if (!pClassEntry->wNext) return FALSE;
1289 for (i = 1; (i < pClassEntry->wNext) && class; i++) class = class->next;
1292 pClassEntry->wNext = 0;
1295 pClassEntry->hInst = class->hInstance;
1296 pClassEntry->wNext++;
1297 GlobalGetAtomNameA( class->atomName, pClassEntry->szClassName,
1298 sizeof(pClassEntry->szClassName) );