2 * Window classes functions
4 * Copyright 1993, 1996, 2003 Alexandre Julliard
5 * Copyright 1998 Juergen Schmied (jsch)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include "user_private.h"
35 #include "wine/server.h"
36 #include "wine/list.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(class);
41 #define MAX_ATOM_LEN 255 /* from dlls/kernel32/atom.c */
43 static struct list class_list
= LIST_INIT( class_list
);
44 static INIT_ONCE init_once
= INIT_ONCE_STATIC_INIT
;
46 #define CLASS_OTHER_PROCESS ((CLASS *)1)
48 /***********************************************************************
51 static CLASS
*get_class_ptr( HWND hwnd
, BOOL write_access
)
53 WND
*ptr
= WIN_GetPtr( hwnd
);
57 if (ptr
!= WND_OTHER_PROCESS
&& ptr
!= WND_DESKTOP
) return ptr
->class;
58 if (!write_access
) return CLASS_OTHER_PROCESS
;
60 /* modifying classes in other processes is not allowed */
61 if (ptr
== WND_DESKTOP
|| IsWindow( hwnd
))
63 SetLastError( ERROR_ACCESS_DENIED
);
67 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
72 /***********************************************************************
75 static inline void release_class_ptr( CLASS
*ptr
)
81 /***********************************************************************
84 ATOM
get_int_atom_value( LPCWSTR name
)
88 if (IS_INTRESOURCE(name
)) return LOWORD(name
);
89 if (*name
++ != '#') return 0;
92 if (*name
< '0' || *name
> '9') return 0;
93 ret
= ret
* 10 + *name
++ - '0';
94 if (ret
> 0xffff) return 0;
100 /***********************************************************************
103 static BOOL
is_comctl32_class( const WCHAR
*name
)
105 static const WCHAR
*classesW
[] =
109 L
"msctls_progress32",
110 L
"msctls_statusbar32",
111 L
"msctls_trackbar32",
116 L
"SysDateTimePick32",
129 int min
= 0, max
= ARRAY_SIZE( classesW
) - 1;
133 int res
, pos
= (min
+ max
) / 2;
134 if (!(res
= wcsicmp( name
, classesW
[pos
] ))) return TRUE
;
135 if (res
< 0) max
= pos
- 1;
141 static BOOL
is_builtin_class( const WCHAR
*name
)
143 static const WCHAR
*classesW
[] =
150 int min
= 0, max
= ARRAY_SIZE( classesW
) - 1;
154 int res
, pos
= (min
+ max
) / 2;
155 if (!(res
= wcsicmp( name
, classesW
[pos
] ))) return TRUE
;
156 if (res
< 0) max
= pos
- 1;
162 /***********************************************************************
165 * Set class info with the wine server.
167 static BOOL
set_server_info( HWND hwnd
, INT offset
, LONG_PTR newval
, UINT size
)
171 SERVER_START_REQ( set_class_info
)
173 req
->window
= wine_server_user_handle( hwnd
);
174 req
->extra_offset
= -1;
178 req
->flags
= SET_CLASS_ATOM
;
179 req
->atom
= LOWORD(newval
);
182 req
->flags
= SET_CLASS_STYLE
;
186 req
->flags
= SET_CLASS_WINEXTRA
;
187 req
->win_extra
= newval
;
190 req
->flags
= SET_CLASS_INSTANCE
;
191 req
->instance
= wine_server_client_ptr( (void *)newval
);
194 assert( offset
>= 0 );
195 req
->flags
= SET_CLASS_EXTRA
;
196 req
->extra_offset
= offset
;
197 req
->extra_size
= size
;
198 if ( size
== sizeof(LONG
) )
200 LONG newlong
= newval
;
201 memcpy( &req
->extra_value
, &newlong
, sizeof(LONG
) );
204 memcpy( &req
->extra_value
, &newval
, sizeof(LONG_PTR
) );
207 ret
= !wine_server_call_err( req
);
214 /***********************************************************************
217 * Get the menu name as an ANSI string.
219 static inline LPSTR
CLASS_GetMenuNameA( CLASS
*classPtr
)
221 if (IS_INTRESOURCE(classPtr
->menuName
)) return (LPSTR
)classPtr
->menuName
;
222 return (LPSTR
)(classPtr
->menuName
+ lstrlenW(classPtr
->menuName
) + 1);
226 /***********************************************************************
229 * Get the menu name as a Unicode string.
231 static inline LPWSTR
CLASS_GetMenuNameW( CLASS
*classPtr
)
233 return classPtr
->menuName
;
237 /***********************************************************************
240 * Set the menu name in a class structure by copying the string.
242 static void CLASS_SetMenuNameA( CLASS
*classPtr
, LPCSTR name
)
244 if (!IS_INTRESOURCE(classPtr
->menuName
)) HeapFree( GetProcessHeap(), 0, classPtr
->menuName
);
245 if (!IS_INTRESOURCE(name
))
247 DWORD lenA
= strlen(name
) + 1;
248 DWORD lenW
= MultiByteToWideChar( CP_ACP
, 0, name
, lenA
, NULL
, 0 );
249 classPtr
->menuName
= HeapAlloc( GetProcessHeap(), 0, lenA
+ lenW
*sizeof(WCHAR
) );
250 MultiByteToWideChar( CP_ACP
, 0, name
, lenA
, classPtr
->menuName
, lenW
);
251 memcpy( classPtr
->menuName
+ lenW
, name
, lenA
);
253 else classPtr
->menuName
= (LPWSTR
)name
;
257 /***********************************************************************
260 * Set the menu name in a class structure by copying the string.
262 static void CLASS_SetMenuNameW( CLASS
*classPtr
, LPCWSTR name
)
264 if (!IS_INTRESOURCE(classPtr
->menuName
)) HeapFree( GetProcessHeap(), 0, classPtr
->menuName
);
265 if (!IS_INTRESOURCE(name
))
267 DWORD lenW
= lstrlenW(name
) + 1;
268 DWORD lenA
= WideCharToMultiByte( CP_ACP
, 0, name
, lenW
, NULL
, 0, NULL
, NULL
);
269 classPtr
->menuName
= HeapAlloc( GetProcessHeap(), 0, lenA
+ lenW
*sizeof(WCHAR
) );
270 memcpy( classPtr
->menuName
, name
, lenW
*sizeof(WCHAR
) );
271 WideCharToMultiByte( CP_ACP
, 0, name
, lenW
,
272 (char *)(classPtr
->menuName
+ lenW
), lenA
, NULL
, NULL
);
274 else classPtr
->menuName
= (LPWSTR
)name
;
278 /***********************************************************************
281 * Free a class structure.
283 static void CLASS_FreeClass( CLASS
*classPtr
)
285 TRACE("%p\n", classPtr
);
289 if (classPtr
->dce
) free_dce( classPtr
->dce
, 0 );
290 list_remove( &classPtr
->entry
);
291 if (classPtr
->hbrBackground
> (HBRUSH
)(COLOR_GRADIENTINACTIVECAPTION
+ 1))
292 DeleteObject( classPtr
->hbrBackground
);
293 DestroyIcon( classPtr
->hIconSmIntern
);
294 HeapFree( GetProcessHeap(), 0, classPtr
->menuName
);
295 HeapFree( GetProcessHeap(), 0, classPtr
);
299 static CLASS
*find_class( HINSTANCE module
, const WCHAR
*name
)
301 ATOM atom
= get_int_atom_value( name
);
302 UINT_PTR instance
= (UINT_PTR
)module
& ~0xffff;
306 LIST_FOR_EACH_ENTRY( class, &class_list
, CLASS
, entry
)
310 if (class->atomName
!= atom
) continue;
314 if (wcsicmp( class->name
, name
)) continue;
316 if (!class->local
|| (class->instance
& ~0xffff) == instance
)
318 TRACE("%s %Ix -> %p\n", debugstr_w(name
), instance
, class);
326 const WCHAR
*CLASS_GetVersionedName( const WCHAR
*name
, UINT
*basename_offset
, WCHAR
*combined
, BOOL register_class
)
328 ACTCTX_SECTION_KEYED_DATA data
;
329 struct wndclass_redirect_data
338 const WCHAR
*module
, *ret
;
339 UNICODE_STRING name_us
;
343 if (!basename_offset
)
344 basename_offset
= &offset
;
346 *basename_offset
= 0;
348 if (IS_INTRESOURCE( name
))
351 if (is_comctl32_class( name
) || is_builtin_class( name
))
354 data
.cbSize
= sizeof(data
);
355 RtlInitUnicodeString(&name_us
, name
);
356 if (RtlFindActivationContextSectionString(0, NULL
, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
,
360 wndclass
= (struct wndclass_redirect_data
*)data
.lpData
;
361 *basename_offset
= wndclass
->name_len
/ sizeof(WCHAR
) - lstrlenW(name
);
363 module
= (const WCHAR
*)((BYTE
*)data
.lpSectionBase
+ wndclass
->module_offset
);
364 if (!(hmod
= GetModuleHandleW( module
)))
365 hmod
= LoadLibraryW( module
);
367 /* Combined name is used to register versioned class name. Base name part will match exactly
368 original class name and won't be reused from context data. */
369 ret
= (const WCHAR
*)((BYTE
*)wndclass
+ wndclass
->name_offset
);
372 memcpy(combined
, ret
, *basename_offset
* sizeof(WCHAR
));
373 lstrcpyW(&combined
[*basename_offset
], name
);
377 if (register_class
&& hmod
)
381 if (!(class = find_class( hmod
, ret
)))
383 BOOL (WINAPI
*pRegisterClassNameW
)(const WCHAR
*class);
385 pRegisterClassNameW
= (void *)GetProcAddress(hmod
, "RegisterClassNameW");
386 if (pRegisterClassNameW
)
387 pRegisterClassNameW(name
);
389 else release_class_ptr( class );
395 /***********************************************************************
398 * Return a pointer to the class.
400 static CLASS
*CLASS_FindClass( LPCWSTR name
, HINSTANCE hinstance
)
404 GetDesktopWindow(); /* create the desktop window to trigger builtin class registration */
406 if (!name
) return NULL
;
408 name
= CLASS_GetVersionedName( name
, NULL
, NULL
, TRUE
);
410 while (!(class = find_class( hinstance
, name
)))
412 if (IS_INTRESOURCE( name
)) break;
413 if (!is_comctl32_class( name
)) break;
414 if (GetModuleHandleW( L
"comctl32.dll" )) break;
415 if (!LoadLibraryW( L
"comctl32.dll" )) break;
416 TRACE( "%s retrying after loading comctl32\n", debugstr_w(name
) );
419 if (!class) TRACE("%s %p -> not found\n", debugstr_w(name
), hinstance
);
423 /***********************************************************************
424 * CLASS_RegisterClass
426 * The real RegisterClass() functionality.
428 static CLASS
*CLASS_RegisterClass( LPCWSTR name
, UINT basename_offset
, HINSTANCE hInstance
, BOOL local
,
429 DWORD style
, INT classExtra
, INT winExtra
)
434 TRACE("name=%s hinst=%p style=0x%x clExtr=0x%x winExtr=0x%x\n",
435 debugstr_w(name
), hInstance
, style
, classExtra
, winExtra
);
437 /* Fix the extra bytes value */
439 if (classExtra
> 40) /* Extra bytes are limited to 40 in Win32 */
440 WARN("Class extra bytes %d is > 40\n", classExtra
);
441 if (winExtra
> 40) /* Extra bytes are limited to 40 in Win32 */
442 WARN("Win extra bytes %d is > 40\n", winExtra
);
444 classPtr
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(CLASS
) + classExtra
);
445 if (!classPtr
) return NULL
;
447 classPtr
->atomName
= get_int_atom_value( name
);
448 classPtr
->basename
= classPtr
->name
;
449 if (!classPtr
->atomName
&& name
)
451 lstrcpyW( classPtr
->name
, name
);
452 classPtr
->basename
+= basename_offset
;
454 else GlobalGetAtomNameW( classPtr
->atomName
, classPtr
->name
, ARRAY_SIZE( classPtr
->name
));
456 SERVER_START_REQ( create_class
)
460 req
->instance
= wine_server_client_ptr( hInstance
);
461 req
->extra
= classExtra
;
462 req
->win_extra
= winExtra
;
463 req
->client_ptr
= wine_server_client_ptr( classPtr
);
464 req
->atom
= classPtr
->atomName
;
465 req
->name_offset
= basename_offset
;
466 if (!req
->atom
&& name
) wine_server_add_data( req
, name
, lstrlenW(name
) * sizeof(WCHAR
) );
467 ret
= !wine_server_call_err( req
);
468 classPtr
->atomName
= reply
->atom
;
473 HeapFree( GetProcessHeap(), 0, classPtr
);
477 classPtr
->style
= style
;
478 classPtr
->local
= local
;
479 classPtr
->cbWndExtra
= winExtra
;
480 classPtr
->cbClsExtra
= classExtra
;
481 classPtr
->instance
= (UINT_PTR
)hInstance
;
483 /* Other non-null values must be set by caller */
486 if (local
) list_add_head( &class_list
, &classPtr
->entry
);
487 else list_add_tail( &class_list
, &classPtr
->entry
);
492 /***********************************************************************
495 * Register a builtin control class.
496 * This allows having both ANSI and Unicode winprocs for the same class.
498 static void register_builtin( const struct builtin_class_descr
*descr
)
503 if (descr
->cursor
) cursor
= LoadCursorA( 0, (LPSTR
)descr
->cursor
);
505 if (!(classPtr
= CLASS_RegisterClass( descr
->name
, 0, user32_module
, FALSE
,
506 descr
->style
, 0, descr
->extra
)))
508 if (cursor
) DestroyCursor( cursor
);
512 classPtr
->hCursor
= cursor
;
513 classPtr
->hbrBackground
= descr
->brush
;
514 classPtr
->winproc
= BUILTIN_WINPROC( descr
->proc
);
515 release_class_ptr( classPtr
);
518 static void load_uxtheme(void)
520 BOOL (WINAPI
* pIsThemeActive
)(void);
523 uxtheme
= LoadLibraryA("uxtheme.dll");
526 pIsThemeActive
= (void *)GetProcAddress(uxtheme
, "IsThemeActive");
527 if (!pIsThemeActive
|| !pIsThemeActive())
528 FreeLibrary(uxtheme
);
532 /***********************************************************************
535 static BOOL WINAPI
register_builtins( INIT_ONCE
*once
, void *param
, void **context
)
537 register_builtin( &BUTTON_builtin_class
);
538 register_builtin( &COMBO_builtin_class
);
539 register_builtin( &COMBOLBOX_builtin_class
);
540 register_builtin( &DIALOG_builtin_class
);
541 register_builtin( &EDIT_builtin_class
);
542 register_builtin( &ICONTITLE_builtin_class
);
543 register_builtin( &LISTBOX_builtin_class
);
544 register_builtin( &MDICLIENT_builtin_class
);
545 register_builtin( &MENU_builtin_class
);
546 register_builtin( &SCROLL_builtin_class
);
547 register_builtin( &STATIC_builtin_class
);
548 register_builtin( &IME_builtin_class
);
550 /* Load uxtheme.dll so that standard scrollbars and dialogs are hooked for theming support */
556 /***********************************************************************
557 * register_builtin_classes
559 void register_builtin_classes(void)
561 InitOnceExecuteOnce( &init_once
, register_builtins
, NULL
, NULL
);
565 /***********************************************************************
566 * register_desktop_class
568 void register_desktop_class(void)
570 register_builtin( &DESKTOP_builtin_class
);
571 register_builtin( &MESSAGE_builtin_class
);
575 /***********************************************************************
578 WNDPROC
get_class_winproc( CLASS
*class )
580 return class->winproc
;
584 /***********************************************************************
587 struct dce
*get_class_dce( CLASS
*class )
593 /***********************************************************************
596 struct dce
*set_class_dce( CLASS
*class, struct dce
*dce
)
598 if (class->dce
) return class->dce
; /* already set, don't change it */
604 /***********************************************************************
605 * RegisterClassA (USER32.@)
607 * Register a window class.
610 * >0: Unique identifier
613 ATOM WINAPI
RegisterClassA( const WNDCLASSA
* wc
) /* [in] Address of structure with class data */
617 wcex
.cbSize
= sizeof(wcex
);
618 wcex
.style
= wc
->style
;
619 wcex
.lpfnWndProc
= wc
->lpfnWndProc
;
620 wcex
.cbClsExtra
= wc
->cbClsExtra
;
621 wcex
.cbWndExtra
= wc
->cbWndExtra
;
622 wcex
.hInstance
= wc
->hInstance
;
623 wcex
.hIcon
= wc
->hIcon
;
624 wcex
.hCursor
= wc
->hCursor
;
625 wcex
.hbrBackground
= wc
->hbrBackground
;
626 wcex
.lpszMenuName
= wc
->lpszMenuName
;
627 wcex
.lpszClassName
= wc
->lpszClassName
;
629 return RegisterClassExA( &wcex
);
633 /***********************************************************************
634 * RegisterClassW (USER32.@)
636 * See RegisterClassA.
638 ATOM WINAPI
RegisterClassW( const WNDCLASSW
* wc
)
642 wcex
.cbSize
= sizeof(wcex
);
643 wcex
.style
= wc
->style
;
644 wcex
.lpfnWndProc
= wc
->lpfnWndProc
;
645 wcex
.cbClsExtra
= wc
->cbClsExtra
;
646 wcex
.cbWndExtra
= wc
->cbWndExtra
;
647 wcex
.hInstance
= wc
->hInstance
;
648 wcex
.hIcon
= wc
->hIcon
;
649 wcex
.hCursor
= wc
->hCursor
;
650 wcex
.hbrBackground
= wc
->hbrBackground
;
651 wcex
.lpszMenuName
= wc
->lpszMenuName
;
652 wcex
.lpszClassName
= wc
->lpszClassName
;
654 return RegisterClassExW( &wcex
);
658 /***********************************************************************
659 * RegisterClassExA (USER32.@)
661 ATOM WINAPI
RegisterClassExA( const WNDCLASSEXA
* wc
)
663 WCHAR name
[MAX_ATOM_LEN
+ 1], combined
[MAX_ATOM_LEN
+ 1];
664 const WCHAR
*classname
= NULL
;
669 GetDesktopWindow(); /* create the desktop window to trigger builtin class registration */
671 if (wc
->cbSize
!= sizeof(*wc
) || wc
->cbClsExtra
< 0 || wc
->cbWndExtra
< 0 ||
672 wc
->hInstance
== user32_module
) /* we can't register a class for user32 */
674 SetLastError( ERROR_INVALID_PARAMETER
);
677 if (!(instance
= wc
->hInstance
)) instance
= GetModuleHandleW( NULL
);
679 if (!IS_INTRESOURCE(wc
->lpszClassName
))
681 UINT basename_offset
;
682 if (!MultiByteToWideChar( CP_ACP
, 0, wc
->lpszClassName
, -1, name
, MAX_ATOM_LEN
+ 1 )) return 0;
683 classname
= CLASS_GetVersionedName( name
, &basename_offset
, combined
, FALSE
);
684 classPtr
= CLASS_RegisterClass( classname
, basename_offset
, instance
, !(wc
->style
& CS_GLOBALCLASS
),
685 wc
->style
, wc
->cbClsExtra
, wc
->cbWndExtra
);
689 classPtr
= CLASS_RegisterClass( (LPCWSTR
)wc
->lpszClassName
, 0, instance
,
690 !(wc
->style
& CS_GLOBALCLASS
), wc
->style
,
691 wc
->cbClsExtra
, wc
->cbWndExtra
);
693 if (!classPtr
) return 0;
694 atom
= classPtr
->atomName
;
696 TRACE("name=%s%s%s atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
697 debugstr_a(wc
->lpszClassName
), classname
!= name
? "->" : "", classname
!= name
? debugstr_w(classname
) : "",
698 atom
, wc
->lpfnWndProc
, instance
, wc
->hbrBackground
, wc
->style
, wc
->cbClsExtra
, wc
->cbWndExtra
, classPtr
);
700 classPtr
->hIcon
= wc
->hIcon
;
701 classPtr
->hIconSm
= wc
->hIconSm
;
702 classPtr
->hIconSmIntern
= wc
->hIcon
&& !wc
->hIconSm
?
703 CopyImage( wc
->hIcon
, IMAGE_ICON
,
704 GetSystemMetrics( SM_CXSMICON
),
705 GetSystemMetrics( SM_CYSMICON
),
706 LR_COPYFROMRESOURCE
) : NULL
;
707 classPtr
->hCursor
= wc
->hCursor
;
708 classPtr
->hbrBackground
= wc
->hbrBackground
;
709 classPtr
->winproc
= WINPROC_AllocProc( wc
->lpfnWndProc
, FALSE
);
710 CLASS_SetMenuNameA( classPtr
, wc
->lpszMenuName
);
711 release_class_ptr( classPtr
);
716 /***********************************************************************
717 * RegisterClassExW (USER32.@)
719 ATOM WINAPI
RegisterClassExW( const WNDCLASSEXW
* wc
)
721 WCHAR name
[MAX_ATOM_LEN
+ 1];
722 const WCHAR
*classname
;
723 UINT basename_offset
;
728 GetDesktopWindow(); /* create the desktop window to trigger builtin class registration */
730 if (wc
->cbSize
!= sizeof(*wc
) || wc
->cbClsExtra
< 0 || wc
->cbWndExtra
< 0 ||
731 wc
->hInstance
== user32_module
) /* we can't register a class for user32 */
733 SetLastError( ERROR_INVALID_PARAMETER
);
736 if (!(instance
= wc
->hInstance
)) instance
= GetModuleHandleW( NULL
);
738 classname
= CLASS_GetVersionedName( wc
->lpszClassName
, &basename_offset
, name
, FALSE
);
739 if (!(classPtr
= CLASS_RegisterClass( classname
, basename_offset
, instance
, !(wc
->style
& CS_GLOBALCLASS
),
740 wc
->style
, wc
->cbClsExtra
, wc
->cbWndExtra
)))
743 atom
= classPtr
->atomName
;
745 TRACE("name=%s%s%s atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
746 debugstr_w(wc
->lpszClassName
), classname
!= wc
->lpszClassName
? "->" : "",
747 classname
!= wc
->lpszClassName
? debugstr_w(classname
) : "", atom
, wc
->lpfnWndProc
, instance
,
748 wc
->hbrBackground
, wc
->style
, wc
->cbClsExtra
, wc
->cbWndExtra
, classPtr
);
750 classPtr
->hIcon
= wc
->hIcon
;
751 classPtr
->hIconSm
= wc
->hIconSm
;
752 classPtr
->hIconSmIntern
= wc
->hIcon
&& !wc
->hIconSm
?
753 CopyImage( wc
->hIcon
, IMAGE_ICON
,
754 GetSystemMetrics( SM_CXSMICON
),
755 GetSystemMetrics( SM_CYSMICON
),
756 LR_COPYFROMRESOURCE
) : NULL
;
757 classPtr
->hCursor
= wc
->hCursor
;
758 classPtr
->hbrBackground
= wc
->hbrBackground
;
759 classPtr
->winproc
= WINPROC_AllocProc( wc
->lpfnWndProc
, TRUE
);
760 CLASS_SetMenuNameW( classPtr
, wc
->lpszMenuName
);
761 release_class_ptr( classPtr
);
766 /***********************************************************************
767 * UnregisterClassA (USER32.@)
769 BOOL WINAPI
UnregisterClassA( LPCSTR className
, HINSTANCE hInstance
)
771 if (!IS_INTRESOURCE(className
))
773 WCHAR name
[MAX_ATOM_LEN
+ 1];
775 if (!MultiByteToWideChar( CP_ACP
, 0, className
, -1, name
, MAX_ATOM_LEN
+ 1 ))
777 return UnregisterClassW( name
, hInstance
);
779 return UnregisterClassW( (LPCWSTR
)className
, hInstance
);
782 /***********************************************************************
783 * UnregisterClassW (USER32.@)
785 BOOL WINAPI
UnregisterClassW( LPCWSTR className
, HINSTANCE hInstance
)
787 CLASS
*classPtr
= NULL
;
789 GetDesktopWindow(); /* create the desktop window to trigger builtin class registration */
791 className
= CLASS_GetVersionedName( className
, NULL
, NULL
, FALSE
);
792 SERVER_START_REQ( destroy_class
)
794 req
->instance
= wine_server_client_ptr( hInstance
);
795 if (!(req
->atom
= get_int_atom_value(className
)) && className
)
796 wine_server_add_data( req
, className
, lstrlenW(className
) * sizeof(WCHAR
) );
797 if (!wine_server_call_err( req
)) classPtr
= wine_server_get_ptr( reply
->client_ptr
);
801 if (classPtr
) CLASS_FreeClass( classPtr
);
802 return (classPtr
!= NULL
);
806 /***********************************************************************
807 * GetClassWord (USER32.@)
809 WORD WINAPI
GetClassWord( HWND hwnd
, INT offset
)
814 if (offset
< 0) return GetClassLongA( hwnd
, offset
);
816 if (!(class = get_class_ptr( hwnd
, FALSE
))) return 0;
818 if (class == CLASS_OTHER_PROCESS
)
820 SERVER_START_REQ( set_class_info
)
822 req
->window
= wine_server_user_handle( hwnd
);
824 req
->extra_offset
= offset
;
825 req
->extra_size
= sizeof(retvalue
);
826 if (!wine_server_call_err( req
))
827 memcpy( &retvalue
, &reply
->old_extra_value
, sizeof(retvalue
) );
833 if (offset
<= class->cbClsExtra
- sizeof(WORD
))
834 memcpy( &retvalue
, (char *)(class + 1) + offset
, sizeof(retvalue
) );
836 SetLastError( ERROR_INVALID_INDEX
);
837 release_class_ptr( class );
842 /***********************************************************************
845 * Implementation of GetClassLong(Ptr)A/W
847 static ULONG_PTR
CLASS_GetClassLong( HWND hwnd
, INT offset
, UINT size
,
851 ULONG_PTR retvalue
= 0;
853 if (!(class = get_class_ptr( hwnd
, FALSE
))) return 0;
855 if (class == CLASS_OTHER_PROCESS
)
857 SERVER_START_REQ( set_class_info
)
859 req
->window
= wine_server_user_handle( hwnd
);
861 req
->extra_offset
= (offset
>= 0) ? offset
: -1;
862 req
->extra_size
= (offset
>= 0) ? size
: 0;
863 if (!wine_server_call_err( req
))
867 case GCLP_HBRBACKGROUND
:
873 FIXME( "offset %d (%s) not supported on other process window %p\n",
874 offset
, SPY_GetClassLongOffsetName(offset
), hwnd
);
875 SetLastError( ERROR_INVALID_HANDLE
);
878 retvalue
= reply
->old_style
;
881 retvalue
= reply
->old_win_extra
;
884 retvalue
= reply
->old_extra
;
887 retvalue
= (ULONG_PTR
)wine_server_get_ptr( reply
->old_instance
);
890 retvalue
= reply
->old_atom
;
895 if (size
== sizeof(DWORD
))
898 memcpy( &retdword
, &reply
->old_extra_value
, sizeof(DWORD
) );
902 memcpy( &retvalue
, &reply
->old_extra_value
,
905 else SetLastError( ERROR_INVALID_INDEX
);
916 if (offset
<= class->cbClsExtra
- size
)
918 if (size
== sizeof(DWORD
))
921 memcpy( &retdword
, (char *)(class + 1) + offset
, sizeof(DWORD
) );
925 memcpy( &retvalue
, (char *)(class + 1) + offset
, sizeof(ULONG_PTR
) );
928 SetLastError( ERROR_INVALID_INDEX
);
929 release_class_ptr( class );
935 case GCLP_HBRBACKGROUND
:
936 retvalue
= (ULONG_PTR
)class->hbrBackground
;
939 retvalue
= (ULONG_PTR
)class->hCursor
;
942 retvalue
= (ULONG_PTR
)class->hIcon
;
945 retvalue
= (ULONG_PTR
)(class->hIconSm
? class->hIconSm
: class->hIconSmIntern
);
948 retvalue
= class->style
;
951 retvalue
= class->cbWndExtra
;
954 retvalue
= class->cbClsExtra
;
957 retvalue
= class->instance
;
960 retvalue
= (ULONG_PTR
)WINPROC_GetProc( class->winproc
, unicode
);
963 retvalue
= (ULONG_PTR
)CLASS_GetMenuNameW( class );
965 retvalue
= (ULONG_PTR
)CLASS_GetMenuNameW( class );
967 retvalue
= (ULONG_PTR
)CLASS_GetMenuNameA( class );
970 retvalue
= class->atomName
;
973 SetLastError( ERROR_INVALID_INDEX
);
976 release_class_ptr( class );
981 /***********************************************************************
982 * GetClassLongW (USER32.@)
984 DWORD WINAPI
GetClassLongW( HWND hwnd
, INT offset
)
986 return CLASS_GetClassLong( hwnd
, offset
, sizeof(DWORD
), TRUE
);
991 /***********************************************************************
992 * GetClassLongA (USER32.@)
994 DWORD WINAPI
GetClassLongA( HWND hwnd
, INT offset
)
996 return CLASS_GetClassLong( hwnd
, offset
, sizeof(DWORD
), FALSE
);
1000 /***********************************************************************
1001 * SetClassWord (USER32.@)
1003 WORD WINAPI
SetClassWord( HWND hwnd
, INT offset
, WORD newval
)
1008 if (offset
< 0) return SetClassLongA( hwnd
, offset
, (DWORD
)newval
);
1010 if (!(class = get_class_ptr( hwnd
, TRUE
))) return 0;
1012 SERVER_START_REQ( set_class_info
)
1014 req
->window
= wine_server_user_handle( hwnd
);
1015 req
->flags
= SET_CLASS_EXTRA
;
1016 req
->extra_offset
= offset
;
1017 req
->extra_size
= sizeof(newval
);
1018 memcpy( &req
->extra_value
, &newval
, sizeof(newval
) );
1019 if (!wine_server_call_err( req
))
1021 void *ptr
= (char *)(class + 1) + offset
;
1022 memcpy( &retval
, ptr
, sizeof(retval
) );
1023 memcpy( ptr
, &newval
, sizeof(newval
) );
1027 release_class_ptr( class );
1032 /***********************************************************************
1033 * CLASS_SetClassLong
1035 * Implementation of SetClassLong(Ptr)A/W
1037 static ULONG_PTR
CLASS_SetClassLong( HWND hwnd
, INT offset
, LONG_PTR newval
,
1038 UINT size
, BOOL unicode
)
1041 ULONG_PTR retval
= 0;
1043 if (!(class = get_class_ptr( hwnd
, TRUE
))) return 0;
1047 if (set_server_info( hwnd
, offset
, newval
, size
))
1049 void *ptr
= (char *)(class + 1) + offset
;
1050 if ( size
== sizeof(LONG
) )
1053 LONG newlong
= newval
;
1054 memcpy( &retdword
, ptr
, sizeof(DWORD
) );
1055 memcpy( ptr
, &newlong
, sizeof(LONG
) );
1060 memcpy( &retval
, ptr
, sizeof(ULONG_PTR
) );
1061 memcpy( ptr
, &newval
, sizeof(LONG_PTR
) );
1069 CLASS_SetMenuNameW( class, (LPCWSTR
)newval
);
1071 CLASS_SetMenuNameA( class, (LPCSTR
)newval
);
1072 retval
= 0; /* Old value is now meaningless anyway */
1075 retval
= (ULONG_PTR
)WINPROC_GetProc( class->winproc
, unicode
);
1076 class->winproc
= WINPROC_AllocProc( (WNDPROC
)newval
, unicode
);
1078 case GCLP_HBRBACKGROUND
:
1079 retval
= (ULONG_PTR
)class->hbrBackground
;
1080 class->hbrBackground
= (HBRUSH
)newval
;
1083 retval
= (ULONG_PTR
)class->hCursor
;
1084 class->hCursor
= (HCURSOR
)newval
;
1087 retval
= (ULONG_PTR
)class->hIcon
;
1088 if (class->hIconSmIntern
)
1090 DestroyIcon(class->hIconSmIntern
);
1091 class->hIconSmIntern
= NULL
;
1093 if (newval
&& !class->hIconSm
)
1094 class->hIconSmIntern
= CopyImage( (HICON
)newval
, IMAGE_ICON
,
1095 GetSystemMetrics( SM_CXSMICON
), GetSystemMetrics( SM_CYSMICON
),
1096 LR_COPYFROMRESOURCE
);
1097 class->hIcon
= (HICON
)newval
;
1100 retval
= (ULONG_PTR
)class->hIconSm
;
1101 if (retval
&& !newval
&& class->hIcon
)
1102 class->hIconSmIntern
= CopyImage( class->hIcon
, IMAGE_ICON
,
1103 GetSystemMetrics( SM_CXSMICON
), GetSystemMetrics( SM_CYSMICON
),
1104 LR_COPYFROMRESOURCE
);
1105 else if (newval
&& class->hIconSmIntern
)
1107 DestroyIcon(class->hIconSmIntern
);
1108 class->hIconSmIntern
= NULL
;
1110 class->hIconSm
= (HICON
)newval
;
1113 if (!set_server_info( hwnd
, offset
, newval
, size
)) break;
1114 retval
= class->style
;
1115 class->style
= newval
;
1117 case GCL_CBWNDEXTRA
:
1118 if (!set_server_info( hwnd
, offset
, newval
, size
)) break;
1119 retval
= class->cbWndExtra
;
1120 class->cbWndExtra
= newval
;
1123 if (!set_server_info( hwnd
, offset
, newval
, size
)) break;
1124 retval
= class->instance
;
1125 class->instance
= newval
;
1128 if (!set_server_info( hwnd
, offset
, newval
, size
)) break;
1129 retval
= class->atomName
;
1130 class->atomName
= newval
;
1131 GlobalGetAtomNameW( newval
, class->name
, ARRAY_SIZE( class->name
));
1133 case GCL_CBCLSEXTRA
: /* cannot change this one */
1134 SetLastError( ERROR_INVALID_PARAMETER
);
1137 SetLastError( ERROR_INVALID_INDEX
);
1140 release_class_ptr( class );
1145 /***********************************************************************
1146 * SetClassLongW (USER32.@)
1148 DWORD WINAPI
SetClassLongW( HWND hwnd
, INT offset
, LONG newval
)
1150 return CLASS_SetClassLong( hwnd
, offset
, newval
, sizeof(LONG
), TRUE
);
1154 /***********************************************************************
1155 * SetClassLongA (USER32.@)
1157 DWORD WINAPI
SetClassLongA( HWND hwnd
, INT offset
, LONG newval
)
1159 return CLASS_SetClassLong( hwnd
, offset
, newval
, sizeof(LONG
), FALSE
);
1163 /***********************************************************************
1164 * GetClassNameA (USER32.@)
1166 INT WINAPI
GetClassNameA( HWND hwnd
, LPSTR buffer
, INT count
)
1168 WCHAR tmpbuf
[MAX_ATOM_LEN
+ 1];
1171 if (count
<= 0) return 0;
1172 if (!GetClassNameW( hwnd
, tmpbuf
, ARRAY_SIZE( tmpbuf
))) return 0;
1173 RtlUnicodeToMultiByteN( buffer
, count
- 1, &len
, tmpbuf
, lstrlenW(tmpbuf
) * sizeof(WCHAR
) );
1179 /***********************************************************************
1180 * GetClassNameW (USER32.@)
1182 INT WINAPI
GetClassNameW( HWND hwnd
, LPWSTR buffer
, INT count
)
1184 UNICODE_STRING name
= { .Buffer
= buffer
, .MaximumLength
= count
* sizeof(WCHAR
) };
1185 return NtUserGetClassName( hwnd
, FALSE
, &name
);
1189 /***********************************************************************
1190 * RealGetWindowClassA (USER32.@)
1192 UINT WINAPI
RealGetWindowClassA( HWND hwnd
, LPSTR buffer
, UINT count
)
1194 return GetClassNameA( hwnd
, buffer
, count
);
1198 /***********************************************************************
1199 * RealGetWindowClassW (USER32.@)
1201 UINT WINAPI
RealGetWindowClassW( HWND hwnd
, LPWSTR buffer
, UINT count
)
1203 return GetClassNameW( hwnd
, buffer
, count
);
1207 /***********************************************************************
1208 * GetClassInfoA (USER32.@)
1210 BOOL WINAPI
GetClassInfoA( HINSTANCE hInstance
, LPCSTR name
, WNDCLASSA
*wc
)
1213 UINT ret
= GetClassInfoExA( hInstance
, name
, &wcex
);
1217 wc
->style
= wcex
.style
;
1218 wc
->lpfnWndProc
= wcex
.lpfnWndProc
;
1219 wc
->cbClsExtra
= wcex
.cbClsExtra
;
1220 wc
->cbWndExtra
= wcex
.cbWndExtra
;
1221 wc
->hInstance
= wcex
.hInstance
;
1222 wc
->hIcon
= wcex
.hIcon
;
1223 wc
->hCursor
= wcex
.hCursor
;
1224 wc
->hbrBackground
= wcex
.hbrBackground
;
1225 wc
->lpszMenuName
= wcex
.lpszMenuName
;
1226 wc
->lpszClassName
= wcex
.lpszClassName
;
1232 /***********************************************************************
1233 * GetClassInfoW (USER32.@)
1235 BOOL WINAPI
GetClassInfoW( HINSTANCE hInstance
, LPCWSTR name
, WNDCLASSW
*wc
)
1238 UINT ret
= GetClassInfoExW( hInstance
, name
, &wcex
);
1242 wc
->style
= wcex
.style
;
1243 wc
->lpfnWndProc
= wcex
.lpfnWndProc
;
1244 wc
->cbClsExtra
= wcex
.cbClsExtra
;
1245 wc
->cbWndExtra
= wcex
.cbWndExtra
;
1246 wc
->hInstance
= wcex
.hInstance
;
1247 wc
->hIcon
= wcex
.hIcon
;
1248 wc
->hCursor
= wcex
.hCursor
;
1249 wc
->hbrBackground
= wcex
.hbrBackground
;
1250 wc
->lpszMenuName
= wcex
.lpszMenuName
;
1251 wc
->lpszClassName
= wcex
.lpszClassName
;
1257 /***********************************************************************
1258 * GetClassInfoExA (USER32.@)
1260 BOOL WINAPI
GetClassInfoExA( HINSTANCE hInstance
, LPCSTR name
, WNDCLASSEXA
*wc
)
1265 TRACE("%p %s %p\n", hInstance
, debugstr_a(name
), wc
);
1269 SetLastError( ERROR_NOACCESS
);
1273 if (!hInstance
) hInstance
= user32_module
;
1275 if (!IS_INTRESOURCE(name
))
1277 WCHAR nameW
[MAX_ATOM_LEN
+ 1];
1278 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, nameW
, ARRAY_SIZE( nameW
)))
1280 classPtr
= CLASS_FindClass( nameW
, hInstance
);
1282 else classPtr
= CLASS_FindClass( (LPCWSTR
)name
, hInstance
);
1286 SetLastError( ERROR_CLASS_DOES_NOT_EXIST
);
1289 wc
->style
= classPtr
->style
;
1290 wc
->lpfnWndProc
= WINPROC_GetProc( classPtr
->winproc
, FALSE
);
1291 wc
->cbClsExtra
= classPtr
->cbClsExtra
;
1292 wc
->cbWndExtra
= classPtr
->cbWndExtra
;
1293 wc
->hInstance
= (hInstance
== user32_module
) ? 0 : hInstance
;
1294 wc
->hIcon
= classPtr
->hIcon
;
1295 wc
->hIconSm
= classPtr
->hIconSm
? classPtr
->hIconSm
: classPtr
->hIconSmIntern
;
1296 wc
->hCursor
= classPtr
->hCursor
;
1297 wc
->hbrBackground
= classPtr
->hbrBackground
;
1298 wc
->lpszMenuName
= CLASS_GetMenuNameA( classPtr
);
1299 wc
->lpszClassName
= name
;
1300 atom
= classPtr
->atomName
;
1301 release_class_ptr( classPtr
);
1303 /* We must return the atom of the class here instead of just TRUE. */
1308 /***********************************************************************
1309 * GetClassInfoExW (USER32.@)
1311 BOOL WINAPI
GetClassInfoExW( HINSTANCE hInstance
, LPCWSTR name
, WNDCLASSEXW
*wc
)
1316 TRACE("%p %s %p\n", hInstance
, debugstr_w(name
), wc
);
1320 SetLastError( ERROR_NOACCESS
);
1324 if (!hInstance
) hInstance
= user32_module
;
1326 if (!(classPtr
= CLASS_FindClass( name
, hInstance
)))
1328 SetLastError( ERROR_CLASS_DOES_NOT_EXIST
);
1331 wc
->style
= classPtr
->style
;
1332 wc
->lpfnWndProc
= WINPROC_GetProc( classPtr
->winproc
, TRUE
);
1333 wc
->cbClsExtra
= classPtr
->cbClsExtra
;
1334 wc
->cbWndExtra
= classPtr
->cbWndExtra
;
1335 wc
->hInstance
= (hInstance
== user32_module
) ? 0 : hInstance
;
1336 wc
->hIcon
= classPtr
->hIcon
;
1337 wc
->hIconSm
= classPtr
->hIconSm
? classPtr
->hIconSm
: classPtr
->hIconSmIntern
;
1338 wc
->hCursor
= classPtr
->hCursor
;
1339 wc
->hbrBackground
= classPtr
->hbrBackground
;
1340 wc
->lpszMenuName
= CLASS_GetMenuNameW( classPtr
);
1341 wc
->lpszClassName
= name
;
1342 atom
= classPtr
->atomName
;
1343 release_class_ptr( classPtr
);
1345 /* We must return the atom of the class here instead of just TRUE. */
1350 #if 0 /* toolhelp is in kernel, so this cannot work */
1352 /***********************************************************************
1353 * ClassFirst (TOOLHELP.69)
1355 BOOL16 WINAPI
ClassFirst16( CLASSENTRY
*pClassEntry
)
1357 TRACE("%p\n",pClassEntry
);
1358 pClassEntry
->wNext
= 1;
1359 return ClassNext16( pClassEntry
);
1363 /***********************************************************************
1364 * ClassNext (TOOLHELP.70)
1366 BOOL16 WINAPI
ClassNext16( CLASSENTRY
*pClassEntry
)
1369 CLASS
*class = firstClass
;
1371 TRACE("%p\n",pClassEntry
);
1373 if (!pClassEntry
->wNext
) return FALSE
;
1374 for (i
= 1; (i
< pClassEntry
->wNext
) && class; i
++) class = class->next
;
1377 pClassEntry
->wNext
= 0;
1380 pClassEntry
->hInst
= class->hInstance
;
1381 pClassEntry
->wNext
++;
1382 GlobalGetAtomNameA( class->atomName
, pClassEntry
->szClassName
,
1383 sizeof(pClassEntry
->szClassName
) );
1388 /* 64bit versions */
1390 #ifdef GetClassLongPtrA
1391 #undef GetClassLongPtrA
1394 #ifdef GetClassLongPtrW
1395 #undef GetClassLongPtrW
1398 #ifdef SetClassLongPtrA
1399 #undef SetClassLongPtrA
1402 #ifdef SetClassLongPtrW
1403 #undef SetClassLongPtrW
1406 /***********************************************************************
1407 * GetClassLongPtrA (USER32.@)
1409 ULONG_PTR WINAPI
GetClassLongPtrA( HWND hwnd
, INT offset
)
1411 return CLASS_GetClassLong( hwnd
, offset
, sizeof(ULONG_PTR
), FALSE
);
1414 /***********************************************************************
1415 * GetClassLongPtrW (USER32.@)
1417 ULONG_PTR WINAPI
GetClassLongPtrW( HWND hwnd
, INT offset
)
1419 return CLASS_GetClassLong( hwnd
, offset
, sizeof(ULONG_PTR
), TRUE
);
1422 /***********************************************************************
1423 * SetClassLongPtrW (USER32.@)
1425 ULONG_PTR WINAPI
SetClassLongPtrW( HWND hwnd
, INT offset
, LONG_PTR newval
)
1427 return CLASS_SetClassLong( hwnd
, offset
, newval
, sizeof(LONG_PTR
), TRUE
);
1430 /***********************************************************************
1431 * SetClassLongPtrA (USER32.@)
1433 ULONG_PTR WINAPI
SetClassLongPtrA( HWND hwnd
, INT offset
, LONG_PTR newval
)
1435 return CLASS_SetClassLong( hwnd
, offset
, newval
, sizeof(LONG_PTR
), FALSE
);