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 INIT_ONCE init_once
= INIT_ONCE_STATIC_INIT
;
45 #define CLASS_OTHER_PROCESS ((CLASS *)1)
47 static inline const char *debugstr_us( const UNICODE_STRING
*us
)
49 if (!us
) return "<null>";
50 return debugstr_wn( us
->Buffer
, us
->Length
/ sizeof(WCHAR
) );
53 /***********************************************************************
56 static CLASS
*get_class_ptr( HWND hwnd
, BOOL write_access
)
58 WND
*ptr
= WIN_GetPtr( hwnd
);
62 if (ptr
!= WND_OTHER_PROCESS
&& ptr
!= WND_DESKTOP
) return ptr
->class;
63 if (!write_access
) return CLASS_OTHER_PROCESS
;
65 /* modifying classes in other processes is not allowed */
66 if (ptr
== WND_DESKTOP
|| IsWindow( hwnd
))
68 SetLastError( ERROR_ACCESS_DENIED
);
72 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
77 /***********************************************************************
80 static inline void release_class_ptr( CLASS
*ptr
)
86 /***********************************************************************
89 ATOM
get_int_atom_value( UNICODE_STRING
*name
)
91 const WCHAR
*ptr
= name
->Buffer
;
92 const WCHAR
*end
= ptr
+ name
->Length
/ sizeof(WCHAR
);
95 if (IS_INTRESOURCE(ptr
)) return LOWORD(ptr
);
97 if (*ptr
++ != '#') return 0;
100 if (*ptr
< '0' || *ptr
> '9') return 0;
101 ret
= ret
* 10 + *ptr
++ - '0';
102 if (ret
> 0xffff) return 0;
108 /***********************************************************************
111 static BOOL
is_comctl32_class( const WCHAR
*name
)
113 static const WCHAR
*classesW
[] =
117 L
"msctls_progress32",
118 L
"msctls_statusbar32",
119 L
"msctls_trackbar32",
124 L
"SysDateTimePick32",
137 int min
= 0, max
= ARRAY_SIZE( classesW
) - 1;
141 int res
, pos
= (min
+ max
) / 2;
142 if (!(res
= wcsicmp( name
, classesW
[pos
] ))) return TRUE
;
143 if (res
< 0) max
= pos
- 1;
149 static BOOL
is_builtin_class( const WCHAR
*name
)
151 static const WCHAR
*classesW
[] =
158 int min
= 0, max
= ARRAY_SIZE( classesW
) - 1;
162 int res
, pos
= (min
+ max
) / 2;
163 if (!(res
= wcsicmp( name
, classesW
[pos
] ))) return TRUE
;
164 if (res
< 0) max
= pos
- 1;
171 static void init_class_name( UNICODE_STRING
*str
, const WCHAR
*name
)
173 if (IS_INTRESOURCE( name
))
175 str
->Buffer
= (WCHAR
*)name
;
176 str
->Length
= str
->MaximumLength
= 0;
178 else RtlInitUnicodeString( str
, name
);
181 static BOOL
alloc_menu_nameA( struct client_menu_name
*ret
, const char *menu_name
)
183 if (!IS_INTRESOURCE(menu_name
))
185 DWORD lenA
= strlen( menu_name
) + 1;
186 DWORD lenW
= MultiByteToWideChar( CP_ACP
, 0, menu_name
, lenA
, NULL
, 0 );
187 ret
->nameW
= HeapAlloc( GetProcessHeap(), 0, lenA
+ lenW
* sizeof(WCHAR
) );
188 if (!ret
->nameW
) return FALSE
;
189 ret
->nameA
= (char *)(ret
->nameW
+ lenW
);
190 MultiByteToWideChar( CP_ACP
, 0, menu_name
, lenA
, ret
->nameW
, lenW
);
191 memcpy( ret
->nameA
, menu_name
, lenA
);
195 ret
->nameW
= (WCHAR
*)menu_name
;
196 ret
->nameA
= (char *)menu_name
;
201 static BOOL
alloc_menu_nameW( struct client_menu_name
*ret
, const WCHAR
*menu_name
)
203 if (!IS_INTRESOURCE(menu_name
))
205 DWORD lenW
= lstrlenW( menu_name
) + 1;
206 DWORD lenA
= WideCharToMultiByte( CP_ACP
, 0, menu_name
, lenW
, NULL
, 0, NULL
, NULL
);
207 ret
->nameW
= HeapAlloc( GetProcessHeap(), 0, lenA
+ lenW
* sizeof(WCHAR
) );
208 if (!ret
->nameW
) return FALSE
;
209 memcpy( ret
->nameW
, menu_name
, lenW
* sizeof(WCHAR
) );
210 WideCharToMultiByte( CP_ACP
, 0, menu_name
, lenW
, ret
->nameA
, lenA
, NULL
, NULL
);
214 ret
->nameW
= (WCHAR
*)menu_name
;
215 ret
->nameA
= (char *)menu_name
;
220 static void free_menu_name( struct client_menu_name
*name
)
222 if (!IS_INTRESOURCE(name
->nameW
)) HeapFree( GetProcessHeap(), 0, name
->nameW
);
225 static ULONG_PTR
set_menu_nameW( HWND hwnd
, INT offset
, ULONG_PTR newval
)
227 struct client_menu_name menu_name
;
228 if (!alloc_menu_nameW( &menu_name
, (const WCHAR
*)newval
)) return 0;
229 NtUserSetClassLongPtr( hwnd
, offset
, (ULONG_PTR
)&menu_name
, FALSE
);
230 free_menu_name( &menu_name
);
234 static ULONG_PTR
set_menu_nameA( HWND hwnd
, INT offset
, ULONG_PTR newval
)
236 struct client_menu_name menu_name
;
237 if (!alloc_menu_nameA( &menu_name
, (const char *)newval
)) return 0;
238 NtUserSetClassLongPtr( hwnd
, offset
, (ULONG_PTR
)&menu_name
, TRUE
);
239 free_menu_name( &menu_name
);
243 static void get_versioned_name( const WCHAR
*name
, UNICODE_STRING
*ret
, UNICODE_STRING
*version
, HMODULE
*reg_module
)
245 ACTCTX_SECTION_KEYED_DATA data
;
246 struct wndclass_redirect_data
255 const WCHAR
*module
, *ptr
;
256 UNICODE_STRING name_us
;
260 if (reg_module
) *reg_module
= 0;
261 if (version
) version
->Length
= 0;
263 if (IS_INTRESOURCE( name
) || is_comctl32_class( name
) || is_builtin_class( name
))
265 init_class_name( ret
, name
);
269 data
.cbSize
= sizeof(data
);
270 RtlInitUnicodeString(&name_us
, name
);
271 if (RtlFindActivationContextSectionString( 0, NULL
, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
,
274 init_class_name( ret
, name
);
278 wndclass
= (struct wndclass_redirect_data
*)data
.lpData
;
279 offset
= wndclass
->name_len
/ sizeof(WCHAR
) - lstrlenW(name
);
281 module
= (const WCHAR
*)((BYTE
*)data
.lpSectionBase
+ wndclass
->module_offset
);
282 if (!(hmod
= GetModuleHandleW( module
)))
283 hmod
= LoadLibraryW( module
);
285 /* Combined name is used to register versioned class name. Base name part will match exactly
286 original class name and won't be reused from context data. */
287 ptr
= (const WCHAR
*)((BYTE
*)wndclass
+ wndclass
->name_offset
);
290 WCHAR
*combined
= version
->Buffer
;
291 memcpy( combined
, ptr
, offset
* sizeof(WCHAR
) );
292 lstrcpyW( &combined
[offset
], name
);
293 version
->Length
= offset
* sizeof(WCHAR
);
297 if (reg_module
) *reg_module
= hmod
;
298 init_class_name( ret
, ptr
);
302 /***********************************************************************
305 * Register a builtin control class.
306 * This allows having both ANSI and Unicode winprocs for the same class.
308 static void register_builtin( const struct builtin_class_descr
*descr
)
310 UNICODE_STRING name
, version
= { .Length
= 0 };
311 struct client_menu_name menu_name
= { 0 };
312 WNDCLASSEXW
class = {
313 .cbSize
= sizeof(class),
314 .hInstance
= user32_module
,
315 .style
= descr
->style
,
316 .cbWndExtra
= descr
->extra
,
317 .hbrBackground
= descr
->brush
,
318 .lpfnWndProc
= BUILTIN_WINPROC( descr
->proc
),
321 if (descr
->cursor
) class.hCursor
= LoadCursorA( 0, (LPSTR
)descr
->cursor
);
323 init_class_name( &name
, descr
->name
);
324 if (!NtUserRegisterClassExWOW( &class, &name
, &version
, &menu_name
, 1, 0, NULL
) && class.hCursor
)
325 DestroyCursor( class.hCursor
);
328 static void load_uxtheme(void)
330 BOOL (WINAPI
* pIsThemeActive
)(void);
333 uxtheme
= LoadLibraryA("uxtheme.dll");
336 pIsThemeActive
= (void *)GetProcAddress(uxtheme
, "IsThemeActive");
337 if (!pIsThemeActive
|| !pIsThemeActive())
338 FreeLibrary(uxtheme
);
342 /***********************************************************************
345 static BOOL WINAPI
register_builtins( INIT_ONCE
*once
, void *param
, void **context
)
347 register_builtin( &BUTTON_builtin_class
);
348 register_builtin( &COMBO_builtin_class
);
349 register_builtin( &COMBOLBOX_builtin_class
);
350 register_builtin( &DIALOG_builtin_class
);
351 register_builtin( &EDIT_builtin_class
);
352 register_builtin( &ICONTITLE_builtin_class
);
353 register_builtin( &LISTBOX_builtin_class
);
354 register_builtin( &MDICLIENT_builtin_class
);
355 register_builtin( &MENU_builtin_class
);
356 register_builtin( &SCROLL_builtin_class
);
357 register_builtin( &STATIC_builtin_class
);
358 register_builtin( &IME_builtin_class
);
360 /* Load uxtheme.dll so that standard scrollbars and dialogs are hooked for theming support */
366 /***********************************************************************
367 * register_builtin_classes
369 void register_builtin_classes(void)
371 InitOnceExecuteOnce( &init_once
, register_builtins
, NULL
, NULL
);
375 /***********************************************************************
376 * register_desktop_class
378 void register_desktop_class(void)
380 register_builtin( &DESKTOP_builtin_class
);
381 register_builtin( &MESSAGE_builtin_class
);
385 /***********************************************************************
388 WNDPROC
get_class_winproc( CLASS
*class )
390 return class->winproc
;
394 /***********************************************************************
397 struct dce
*get_class_dce( CLASS
*class )
403 /***********************************************************************
406 struct dce
*set_class_dce( CLASS
*class, struct dce
*dce
)
408 if (class->dce
) return class->dce
; /* already set, don't change it */
414 /***********************************************************************
415 * RegisterClassA (USER32.@)
417 * Register a window class.
420 * >0: Unique identifier
423 ATOM WINAPI
RegisterClassA( const WNDCLASSA
* wc
) /* [in] Address of structure with class data */
427 wcex
.cbSize
= sizeof(wcex
);
428 wcex
.style
= wc
->style
;
429 wcex
.lpfnWndProc
= wc
->lpfnWndProc
;
430 wcex
.cbClsExtra
= wc
->cbClsExtra
;
431 wcex
.cbWndExtra
= wc
->cbWndExtra
;
432 wcex
.hInstance
= wc
->hInstance
;
433 wcex
.hIcon
= wc
->hIcon
;
434 wcex
.hCursor
= wc
->hCursor
;
435 wcex
.hbrBackground
= wc
->hbrBackground
;
436 wcex
.lpszMenuName
= wc
->lpszMenuName
;
437 wcex
.lpszClassName
= wc
->lpszClassName
;
439 return RegisterClassExA( &wcex
);
443 /***********************************************************************
444 * RegisterClassW (USER32.@)
446 * See RegisterClassA.
448 ATOM WINAPI
RegisterClassW( const WNDCLASSW
* wc
)
452 wcex
.cbSize
= sizeof(wcex
);
453 wcex
.style
= wc
->style
;
454 wcex
.lpfnWndProc
= wc
->lpfnWndProc
;
455 wcex
.cbClsExtra
= wc
->cbClsExtra
;
456 wcex
.cbWndExtra
= wc
->cbWndExtra
;
457 wcex
.hInstance
= wc
->hInstance
;
458 wcex
.hIcon
= wc
->hIcon
;
459 wcex
.hCursor
= wc
->hCursor
;
460 wcex
.hbrBackground
= wc
->hbrBackground
;
461 wcex
.lpszMenuName
= wc
->lpszMenuName
;
462 wcex
.lpszClassName
= wc
->lpszClassName
;
464 return RegisterClassExW( &wcex
);
468 /***********************************************************************
469 * RegisterClassExA (USER32.@)
471 ATOM WINAPI
RegisterClassExA( const WNDCLASSEXA
* wc
)
473 WCHAR nameW
[MAX_ATOM_LEN
+ 1], combined
[MAX_ATOM_LEN
+ 1];
474 struct client_menu_name menu_name
;
475 UNICODE_STRING name
, version
;
478 version
.Buffer
= combined
;
479 version
.MaximumLength
= sizeof(combined
);
480 if (!IS_INTRESOURCE(wc
->lpszClassName
))
482 if (!MultiByteToWideChar( CP_ACP
, 0, wc
->lpszClassName
, -1, nameW
, MAX_ATOM_LEN
+ 1 )) return 0;
483 get_versioned_name( nameW
, &name
, &version
, FALSE
);
487 init_class_name( &name
, (const WCHAR
*)wc
->lpszClassName
);
491 if (!alloc_menu_nameA( &menu_name
, wc
->lpszMenuName
)) return 0;
493 atom
= NtUserRegisterClassExWOW( (WNDCLASSEXW
*)wc
, &name
, &version
, &menu_name
, 0, 1, NULL
);
494 if (!atom
) free_menu_name( &menu_name
);
499 /***********************************************************************
500 * RegisterClassExW (USER32.@)
502 ATOM WINAPI
RegisterClassExW( const WNDCLASSEXW
* wc
)
504 WCHAR combined
[MAX_ATOM_LEN
+ 1];
505 struct client_menu_name menu_name
;
506 UNICODE_STRING name
, version
;
509 version
.Buffer
= combined
;
510 version
.MaximumLength
= sizeof(combined
);
511 get_versioned_name( wc
->lpszClassName
, &name
, &version
, FALSE
);
513 if (!alloc_menu_nameW( &menu_name
, wc
->lpszMenuName
)) return 0;
515 atom
= NtUserRegisterClassExWOW( wc
, &name
, &version
, &menu_name
, 0, 0, NULL
);
516 if (!atom
) free_menu_name( &menu_name
);
521 /***********************************************************************
522 * UnregisterClassA (USER32.@)
524 BOOL WINAPI
UnregisterClassA( LPCSTR className
, HINSTANCE hInstance
)
526 if (!IS_INTRESOURCE(className
))
528 WCHAR name
[MAX_ATOM_LEN
+ 1];
530 if (!MultiByteToWideChar( CP_ACP
, 0, className
, -1, name
, MAX_ATOM_LEN
+ 1 ))
532 return UnregisterClassW( name
, hInstance
);
534 return UnregisterClassW( (LPCWSTR
)className
, hInstance
);
537 /***********************************************************************
538 * UnregisterClassW (USER32.@)
540 BOOL WINAPI
UnregisterClassW( LPCWSTR className
, HINSTANCE hInstance
)
542 struct client_menu_name menu_name
;
546 get_versioned_name( className
, &name
, NULL
, FALSE
);
547 ret
= NtUserUnregisterClass( &name
, hInstance
, &menu_name
);
548 if (ret
) free_menu_name( &menu_name
);
553 /***********************************************************************
554 * GetClassWord (USER32.@)
556 WORD WINAPI
GetClassWord( HWND hwnd
, INT offset
)
561 if (offset
< 0) return GetClassLongA( hwnd
, offset
);
563 if (!(class = get_class_ptr( hwnd
, FALSE
))) return 0;
565 if (class == CLASS_OTHER_PROCESS
)
567 SERVER_START_REQ( set_class_info
)
569 req
->window
= wine_server_user_handle( hwnd
);
571 req
->extra_offset
= offset
;
572 req
->extra_size
= sizeof(retvalue
);
573 if (!wine_server_call_err( req
))
574 memcpy( &retvalue
, &reply
->old_extra_value
, sizeof(retvalue
) );
580 if (offset
<= class->cbClsExtra
- sizeof(WORD
))
581 memcpy( &retvalue
, (char *)(class + 1) + offset
, sizeof(retvalue
) );
583 SetLastError( ERROR_INVALID_INDEX
);
584 release_class_ptr( class );
589 /***********************************************************************
592 * Implementation of GetClassLong(Ptr)A/W
594 static ULONG_PTR
CLASS_GetClassLong( HWND hwnd
, INT offset
, UINT size
,
598 ULONG_PTR retvalue
= 0;
600 if (!(class = get_class_ptr( hwnd
, FALSE
))) return 0;
602 if (class == CLASS_OTHER_PROCESS
)
604 SERVER_START_REQ( set_class_info
)
606 req
->window
= wine_server_user_handle( hwnd
);
608 req
->extra_offset
= (offset
>= 0) ? offset
: -1;
609 req
->extra_size
= (offset
>= 0) ? size
: 0;
610 if (!wine_server_call_err( req
))
614 case GCLP_HBRBACKGROUND
:
620 FIXME( "offset %d (%s) not supported on other process window %p\n",
621 offset
, SPY_GetClassLongOffsetName(offset
), hwnd
);
622 SetLastError( ERROR_INVALID_HANDLE
);
625 retvalue
= reply
->old_style
;
628 retvalue
= reply
->old_win_extra
;
631 retvalue
= reply
->old_extra
;
634 retvalue
= (ULONG_PTR
)wine_server_get_ptr( reply
->old_instance
);
637 retvalue
= reply
->old_atom
;
642 if (size
== sizeof(DWORD
))
645 memcpy( &retdword
, &reply
->old_extra_value
, sizeof(DWORD
) );
649 memcpy( &retvalue
, &reply
->old_extra_value
,
652 else SetLastError( ERROR_INVALID_INDEX
);
663 if (offset
<= class->cbClsExtra
- size
)
665 if (size
== sizeof(DWORD
))
668 memcpy( &retdword
, (char *)(class + 1) + offset
, sizeof(DWORD
) );
672 memcpy( &retvalue
, (char *)(class + 1) + offset
, sizeof(ULONG_PTR
) );
675 SetLastError( ERROR_INVALID_INDEX
);
676 release_class_ptr( class );
682 case GCLP_HBRBACKGROUND
:
683 retvalue
= (ULONG_PTR
)class->hbrBackground
;
686 retvalue
= (ULONG_PTR
)class->hCursor
;
689 retvalue
= (ULONG_PTR
)class->hIcon
;
692 retvalue
= (ULONG_PTR
)(class->hIconSm
? class->hIconSm
: class->hIconSmIntern
);
695 retvalue
= class->style
;
698 retvalue
= class->cbWndExtra
;
701 retvalue
= class->cbClsExtra
;
704 retvalue
= class->instance
;
707 retvalue
= (ULONG_PTR
)WINPROC_GetProc( class->winproc
, unicode
);
711 retvalue
= (ULONG_PTR
)class->menu_name
.nameW
;
713 retvalue
= (ULONG_PTR
)class->menu_name
.nameA
;
716 retvalue
= class->atomName
;
719 SetLastError( ERROR_INVALID_INDEX
);
722 release_class_ptr( class );
727 /***********************************************************************
728 * GetClassLongW (USER32.@)
730 DWORD WINAPI
GetClassLongW( HWND hwnd
, INT offset
)
732 return CLASS_GetClassLong( hwnd
, offset
, sizeof(DWORD
), TRUE
);
737 /***********************************************************************
738 * GetClassLongA (USER32.@)
740 DWORD WINAPI
GetClassLongA( HWND hwnd
, INT offset
)
742 return CLASS_GetClassLong( hwnd
, offset
, sizeof(DWORD
), FALSE
);
746 /***********************************************************************
747 * SetClassLongW (USER32.@)
749 DWORD WINAPI
SetClassLongW( HWND hwnd
, INT offset
, LONG newval
)
751 if (offset
== GCLP_MENUNAME
) return set_menu_nameW( hwnd
, offset
, newval
);
752 return NtUserSetClassLong( hwnd
, offset
, newval
, FALSE
);
756 /***********************************************************************
757 * SetClassLongA (USER32.@)
759 DWORD WINAPI
SetClassLongA( HWND hwnd
, INT offset
, LONG newval
)
761 if (offset
== GCLP_MENUNAME
) return set_menu_nameA( hwnd
, offset
, newval
);
762 return NtUserSetClassLong( hwnd
, offset
, newval
, TRUE
);
766 /***********************************************************************
767 * GetClassNameA (USER32.@)
769 INT WINAPI
GetClassNameA( HWND hwnd
, LPSTR buffer
, INT count
)
771 WCHAR tmpbuf
[MAX_ATOM_LEN
+ 1];
774 if (count
<= 0) return 0;
775 if (!GetClassNameW( hwnd
, tmpbuf
, ARRAY_SIZE( tmpbuf
))) return 0;
776 RtlUnicodeToMultiByteN( buffer
, count
- 1, &len
, tmpbuf
, lstrlenW(tmpbuf
) * sizeof(WCHAR
) );
782 /***********************************************************************
783 * GetClassNameW (USER32.@)
785 INT WINAPI
GetClassNameW( HWND hwnd
, LPWSTR buffer
, INT count
)
787 UNICODE_STRING name
= { .Buffer
= buffer
, .MaximumLength
= count
* sizeof(WCHAR
) };
788 return NtUserGetClassName( hwnd
, FALSE
, &name
);
792 /***********************************************************************
793 * RealGetWindowClassA (USER32.@)
795 UINT WINAPI
RealGetWindowClassA( HWND hwnd
, LPSTR buffer
, UINT count
)
797 return GetClassNameA( hwnd
, buffer
, count
);
801 /***********************************************************************
802 * RealGetWindowClassW (USER32.@)
804 UINT WINAPI
RealGetWindowClassW( HWND hwnd
, LPWSTR buffer
, UINT count
)
806 return GetClassNameW( hwnd
, buffer
, count
);
810 /***********************************************************************
811 * GetClassInfoA (USER32.@)
813 BOOL WINAPI
GetClassInfoA( HINSTANCE hInstance
, LPCSTR name
, WNDCLASSA
*wc
)
816 UINT ret
= GetClassInfoExA( hInstance
, name
, &wcex
);
820 wc
->style
= wcex
.style
;
821 wc
->lpfnWndProc
= wcex
.lpfnWndProc
;
822 wc
->cbClsExtra
= wcex
.cbClsExtra
;
823 wc
->cbWndExtra
= wcex
.cbWndExtra
;
824 wc
->hInstance
= wcex
.hInstance
;
825 wc
->hIcon
= wcex
.hIcon
;
826 wc
->hCursor
= wcex
.hCursor
;
827 wc
->hbrBackground
= wcex
.hbrBackground
;
828 wc
->lpszMenuName
= wcex
.lpszMenuName
;
829 wc
->lpszClassName
= wcex
.lpszClassName
;
835 /***********************************************************************
836 * GetClassInfoW (USER32.@)
838 BOOL WINAPI
GetClassInfoW( HINSTANCE hInstance
, LPCWSTR name
, WNDCLASSW
*wc
)
841 UINT ret
= GetClassInfoExW( hInstance
, name
, &wcex
);
845 wc
->style
= wcex
.style
;
846 wc
->lpfnWndProc
= wcex
.lpfnWndProc
;
847 wc
->cbClsExtra
= wcex
.cbClsExtra
;
848 wc
->cbWndExtra
= wcex
.cbWndExtra
;
849 wc
->hInstance
= wcex
.hInstance
;
850 wc
->hIcon
= wcex
.hIcon
;
851 wc
->hCursor
= wcex
.hCursor
;
852 wc
->hbrBackground
= wcex
.hbrBackground
;
853 wc
->lpszMenuName
= wcex
.lpszMenuName
;
854 wc
->lpszClassName
= wcex
.lpszClassName
;
859 ATOM
get_class_info( HINSTANCE instance
, const WCHAR
*class_name
, WNDCLASSEXW
*info
,
860 UNICODE_STRING
*name_str
, BOOL ansi
)
866 get_versioned_name( class_name
, &name
, NULL
, &module
);
868 if (!name_str
&& !instance
) instance
= user32_module
;
870 while (!(atom
= NtUserGetClassInfoEx( instance
, &name
, info
, NULL
, ansi
)))
874 BOOL (WINAPI
*pRegisterClassNameW
)( const WCHAR
*class );
875 pRegisterClassNameW
= (void *)GetProcAddress( module
, "RegisterClassNameW" );
877 if (pRegisterClassNameW
)
879 TRACE( "registering %s\n", debugstr_us(&name
) );
880 pRegisterClassNameW( class_name
);
884 if (IS_INTRESOURCE( class_name
)) break;
885 if (!is_comctl32_class( class_name
)) break;
886 if (GetModuleHandleW( L
"comctl32.dll" )) break;
887 if (!LoadLibraryW( L
"comctl32.dll" )) break;
888 TRACE( "%s retrying after loading comctl32\n", debugstr_w(class_name
) );
893 TRACE( "%s %p -> not found\n", debugstr_w(class_name
), instance
);
894 SetLastError( ERROR_CLASS_DOES_NOT_EXIST
);
898 if (name_str
) *name_str
= name
;
902 /***********************************************************************
903 * GetClassInfoExA (USER32.@)
905 BOOL WINAPI
GetClassInfoExA( HINSTANCE hInstance
, LPCSTR name
, WNDCLASSEXA
*wc
)
909 TRACE("%p %s %p\n", hInstance
, debugstr_a(name
), wc
);
913 SetLastError( ERROR_NOACCESS
);
917 if (!IS_INTRESOURCE(name
))
919 WCHAR nameW
[MAX_ATOM_LEN
+ 1];
920 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, nameW
, ARRAY_SIZE( nameW
)))
922 atom
= get_class_info( hInstance
, nameW
, (WNDCLASSEXW
*)wc
, NULL
, TRUE
);
924 else atom
= get_class_info( hInstance
, (const WCHAR
*)name
, (WNDCLASSEXW
*)wc
, NULL
, TRUE
);
925 if (atom
) wc
->lpszClassName
= name
;
927 /* We must return the atom of the class here instead of just TRUE. */
932 /***********************************************************************
933 * GetClassInfoExW (USER32.@)
935 BOOL WINAPI
GetClassInfoExW( HINSTANCE hInstance
, LPCWSTR name
, WNDCLASSEXW
*wc
)
939 TRACE("%p %s %p\n", hInstance
, debugstr_w(name
), wc
);
943 SetLastError( ERROR_NOACCESS
);
947 atom
= get_class_info( hInstance
, name
, wc
, NULL
, FALSE
);
948 if (atom
) wc
->lpszClassName
= name
;
950 /* We must return the atom of the class here instead of just TRUE. */
955 #if 0 /* toolhelp is in kernel, so this cannot work */
957 /***********************************************************************
958 * ClassFirst (TOOLHELP.69)
960 BOOL16 WINAPI
ClassFirst16( CLASSENTRY
*pClassEntry
)
962 TRACE("%p\n",pClassEntry
);
963 pClassEntry
->wNext
= 1;
964 return ClassNext16( pClassEntry
);
968 /***********************************************************************
969 * ClassNext (TOOLHELP.70)
971 BOOL16 WINAPI
ClassNext16( CLASSENTRY
*pClassEntry
)
974 CLASS
*class = firstClass
;
976 TRACE("%p\n",pClassEntry
);
978 if (!pClassEntry
->wNext
) return FALSE
;
979 for (i
= 1; (i
< pClassEntry
->wNext
) && class; i
++) class = class->next
;
982 pClassEntry
->wNext
= 0;
985 pClassEntry
->hInst
= class->hInstance
;
986 pClassEntry
->wNext
++;
987 GlobalGetAtomNameA( class->atomName
, pClassEntry
->szClassName
,
988 sizeof(pClassEntry
->szClassName
) );
995 #ifdef GetClassLongPtrA
996 #undef GetClassLongPtrA
999 #ifdef GetClassLongPtrW
1000 #undef GetClassLongPtrW
1003 #ifdef SetClassLongPtrA
1004 #undef SetClassLongPtrA
1007 #ifdef SetClassLongPtrW
1008 #undef SetClassLongPtrW
1011 /***********************************************************************
1012 * GetClassLongPtrA (USER32.@)
1014 ULONG_PTR WINAPI
GetClassLongPtrA( HWND hwnd
, INT offset
)
1016 return CLASS_GetClassLong( hwnd
, offset
, sizeof(ULONG_PTR
), FALSE
);
1019 /***********************************************************************
1020 * GetClassLongPtrW (USER32.@)
1022 ULONG_PTR WINAPI
GetClassLongPtrW( HWND hwnd
, INT offset
)
1024 return CLASS_GetClassLong( hwnd
, offset
, sizeof(ULONG_PTR
), TRUE
);
1027 /***********************************************************************
1028 * SetClassLongPtrW (USER32.@)
1030 ULONG_PTR WINAPI
SetClassLongPtrW( HWND hwnd
, INT offset
, LONG_PTR newval
)
1032 if (offset
== GCLP_MENUNAME
) return set_menu_nameW( hwnd
, offset
, newval
);
1033 return NtUserSetClassLongPtr( hwnd
, offset
, newval
, FALSE
);
1036 /***********************************************************************
1037 * SetClassLongPtrA (USER32.@)
1039 ULONG_PTR WINAPI
SetClassLongPtrA( HWND hwnd
, INT offset
, LONG_PTR newval
)
1041 if (offset
== GCLP_MENUNAME
) return set_menu_nameA( hwnd
, offset
, newval
);
1042 return NtUserSetClassLongPtr( hwnd
, offset
, newval
, TRUE
);