Author: weiden Date: Fri Nov 16 10:12:59 2007 New Revision: 30492
URL: http://svn.reactos.org/svn/reactos?rev=30492&view=rev Log: Make registration of system window classes a bit more robust
Modified: trunk/reactos/dll/win32/user32/controls/regcontrol.c trunk/reactos/dll/win32/user32/include/regcontrol.h trunk/reactos/dll/win32/user32/include/user32p.h trunk/reactos/dll/win32/user32/misc/dllmain.c trunk/reactos/dll/win32/user32/windows/class.c trunk/reactos/dll/win32/user32/windows/window.c trunk/reactos/include/reactos/win32k/ntuser.h trunk/reactos/subsystems/win32/win32k/include/class.h trunk/reactos/subsystems/win32/win32k/ntuser/class.c trunk/reactos/subsystems/win32/win32k/ntuser/misc.c
Modified: trunk/reactos/dll/win32/user32/controls/regcontrol.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/controls/r... ============================================================================== --- trunk/reactos/dll/win32/user32/controls/regcontrol.c (original) +++ trunk/reactos/dll/win32/user32/controls/regcontrol.c Fri Nov 16 10:12:59 2007 @@ -13,110 +13,51 @@
#include <wine/debug.h>
-static void RegisterBuiltinClass(const struct builtin_class_descr *Descr) +static const struct { - WNDCLASSEXW wc; - UNICODE_STRING ClassName; - UNICODE_STRING MenuName; + const struct builtin_class_descr *desc; + UINT ClsId; +} g_SysClasses[] = +{ + { &DIALOG_builtin_class, CLASS_DIALOG }, + { &POPUPMENU_builtin_class, CLASS_POPUPMENU }, + { &COMBO_builtin_class, CLASS_COMBO }, + { &COMBOLBOX_builtin_class, CLASS_COMBOLBOX }, + { &DESKTOP_builtin_class, CLASS_DESKTOP }, + { &MDICLIENT_builtin_class, CLASS_MDICLIENT }, +#if 0 + { &MENU_builtin_class, CLASS_MENU }, +#endif + { &SCROLL_builtin_class, CLASS_SCROLL }, + { &BUTTON_builtin_class, CLASS_BUTTON }, + { &LISTBOX_builtin_class, CLASS_LISTBOX }, + { &EDIT_builtin_class, CLASS_EDIT }, + { &ICONTITLE_builtin_class, CLASS_ICONTITLE }, + { &STATIC_builtin_class, CLASS_STATIC }, +};
- wc.cbSize = sizeof(WNDCLASSEXW); - wc.lpszClassName = Descr->name; - wc.lpfnWndProc = Descr->procW; - wc.style = Descr->style; - wc.hInstance = User32Instance; - wc.hIcon = NULL; - wc.hIconSm = NULL; - wc.hCursor = LoadCursorW(NULL, Descr->cursor); - wc.hbrBackground = Descr->brush; - wc.lpszMenuName = NULL; - wc.cbClsExtra = 0; - wc.cbWndExtra = Descr->extra; +BOOL WINAPI RegisterSystemControls(VOID) +{ + REGISTER_SYSCLASS cls[sizeof(g_SysClasses) / sizeof(g_SysClasses[0])]; + UINT i;
- MenuName.Length = - MenuName.MaximumLength = 0; - MenuName.Buffer = NULL; + ZeroMemory(cls, sizeof(cls));
- if (IS_ATOM(Descr->name)) - { - ClassName.Length = - ClassName.MaximumLength = 0; - ClassName.Buffer = (LPWSTR)Descr->name; - } else - { - RtlInitUnicodeString(&ClassName, Descr->name); - } + for (i = 0; i != sizeof(cls) / sizeof(cls[0]); i++) + { + if (IS_ATOM(g_SysClasses[i].desc->name)) + cls[i].ClassName.Buffer = (PWSTR)((ULONG_PTR)g_SysClasses[i].desc->name); + else + RtlInitUnicodeString(&cls[i].ClassName, g_SysClasses[i].desc->name);
- NtUserRegisterClassEx( - &wc, - &ClassName, - &MenuName, - Descr->procA, - REGISTERCLASS_SYSTEM, - NULL); -} - -/*********************************************************************** - * ControlsInit - * - * Register the classes for the builtin controls - */ -BOOL FASTCALL -ControlsInit(LPCWSTR ClassName) -{ - static const struct builtin_class_descr *ClassDescriptions[] = - { - &DIALOG_builtin_class, - &POPUPMENU_builtin_class, - &COMBO_builtin_class, - &COMBOLBOX_builtin_class, - &DESKTOP_builtin_class, - &MDICLIENT_builtin_class, -#if 0 - &MENU_builtin_class, -#endif - &SCROLL_builtin_class, - &BUTTON_builtin_class, - &LISTBOX_builtin_class, - &EDIT_builtin_class, - &ICONTITLE_builtin_class, - &STATIC_builtin_class - }; - unsigned i; - BOOL Register; - - Register = FALSE; - if (IS_ATOM(ClassName)) - { - for (i = 0; - ! Register && i < sizeof(ClassDescriptions) / sizeof(ClassDescriptions[0]); - i++) - { - if (IS_ATOM(ClassDescriptions[i]->name)) - { - Register = (ClassName == ClassDescriptions[i]->name); - } - } - } - else - { - for (i = 0; - ! Register && i < sizeof(ClassDescriptions) / sizeof(ClassDescriptions[0]); - i++) - { - if (! IS_ATOM(ClassDescriptions[i]->name)) - { - Register = (0 == _wcsicmp(ClassName, ClassDescriptions[i]->name)); - } - } + cls[i].Style = g_SysClasses[i].desc->style; + cls[i].ProcW = g_SysClasses[i].desc->procW; + cls[i].ProcA = g_SysClasses[i].desc->procA; + cls[i].ExtraBytes = g_SysClasses[i].desc->extra; + cls[i].hCursor = LoadCursorW(NULL, g_SysClasses[i].desc->cursor); + cls[i].hBrush = g_SysClasses[i].desc->brush; + cls[i].ClassId = g_SysClasses[i].ClsId; }
- if (Register) - { - for (i = 0; i < sizeof(ClassDescriptions) / sizeof(ClassDescriptions[0]); i++) - { - RegisterBuiltinClass(ClassDescriptions[i]); - } - } - - return Register; + return NtUserRegisterSystemClasses(sizeof(cls) / sizeof(cls[0]), cls); }
Modified: trunk/reactos/dll/win32/user32/include/regcontrol.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/include/re... ============================================================================== --- trunk/reactos/dll/win32/user32/include/regcontrol.h (original) +++ trunk/reactos/dll/win32/user32/include/regcontrol.h Fri Nov 16 10:12:59 2007 @@ -26,7 +26,7 @@ HBRUSH brush; /* brush or system color */ };
-extern BOOL FASTCALL ControlsInit(LPCWSTR ClassName); +BOOL WINAPI RegisterSystemControls(VOID);
extern const struct builtin_class_descr BUTTON_builtin_class; extern const struct builtin_class_descr COMBO_builtin_class;
Modified: trunk/reactos/dll/win32/user32/include/user32p.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/include/us... ============================================================================== --- trunk/reactos/dll/win32/user32/include/user32p.h (original) +++ trunk/reactos/dll/win32/user32/include/user32p.h Fri Nov 16 10:12:59 2007 @@ -129,6 +129,8 @@ #define HideCaret(hwnd) \ NtUserHideCaret(hwnd)
+#define NtUserRegisterSystemClasses(Count,SysClasses) \ + (BOOL)NtUserCallTwoParam((DWORD)Count, (DWORD)SysClasses, TWOPARAM_ROUTINE_ROS_REGSYSCLASSES)
/* Internal Thread Data */ extern HINSTANCE User32Instance;
Modified: trunk/reactos/dll/win32/user32/misc/dllmain.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/misc/dllma... ============================================================================== --- trunk/reactos/dll/win32/user32/misc/dllmain.c (original) +++ trunk/reactos/dll/win32/user32/misc/dllmain.c Fri Nov 16 10:12:59 2007 @@ -105,8 +105,11 @@ { case DLL_PROCESS_ATTACH: User32Instance = hInstanceDll; - if (!NtUserRegisterUserModule(hInstanceDll)) + if (!NtUserRegisterUserModule(hInstanceDll) || + !RegisterSystemControls()) + { return FALSE; + }
hProcessHeap = RtlGetProcessHeap(); if (!Init())
Modified: trunk/reactos/dll/win32/user32/windows/class.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/windows/cl... ============================================================================== --- trunk/reactos/dll/win32/user32/windows/class.c (original) +++ trunk/reactos/dll/win32/user32/windows/class.c Fri Nov 16 10:12:59 2007 @@ -14,8 +14,6 @@ #include <wine/debug.h> WINE_DEFAULT_DEBUG_CHANNEL(user32);
-extern BOOL ControlsInitialized; - /* * @implemented */ @@ -62,12 +60,6 @@ } }
- /* Register built-in controls if not already done */ - if (! ControlsInitialized) - { - ControlsInitialized = ControlsInit(ClassName.Buffer); - } - Ret = NtUserGetClassInfo(hInstance, &ClassName, (LPWNDCLASSEXW)lpwcx, @@ -121,12 +113,6 @@ { RtlInitUnicodeString(&ClassName, lpszClass); - } - - /* Register built-in controls if not already done */ - if (! ControlsInitialized) - { - ControlsInitialized = ControlsInit(ClassName.Buffer); }
return NtUserGetClassInfo(hInstance,
Modified: trunk/reactos/dll/win32/user32/windows/window.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/windows/wi... ============================================================================== --- trunk/reactos/dll/win32/user32/windows/window.c (original) +++ trunk/reactos/dll/win32/user32/windows/window.c Fri Nov 16 10:12:59 2007 @@ -15,8 +15,6 @@
#include <wine/debug.h> WINE_DEFAULT_DEBUG_CHANNEL(user32); - -BOOL ControlsInitialized = FALSE;
LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active); void MDI_CalcDefaultChildPos( HWND hwndClient, INT total, LPPOINT lpPos, INT delta, UINT *id ); @@ -185,12 +183,6 @@ return (HWND)0; } } - } - - /* Register built-in controls if not already done */ - if (! ControlsInitialized) - { - ControlsInitialized = ControlsInit(ClassName.Buffer); }
if (Unicode)
Modified: trunk/reactos/include/reactos/win32k/ntuser.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/win32k/ntus... ============================================================================== --- trunk/reactos/include/reactos/win32k/ntuser.h (original) +++ trunk/reactos/include/reactos/win32k/ntuser.h Fri Nov 16 10:12:59 2007 @@ -3,6 +3,20 @@
struct _W32PROCESSINFO; struct _W32THREADINFO; + +typedef struct _REGISTER_SYSCLASS +{ + /* This is a reactos specific class used to initialize the + system window classes during user32 initialization */ + UNICODE_STRING ClassName; + UINT Style; + WNDPROC ProcW; + WNDPROC ProcA; + UINT ExtraBytes; + HICON hCursor; + HBRUSH hBrush; + UINT ClassId; +} REGISTER_SYSCLASS, *PREGISTER_SYSCLASS;
typedef struct _DESKTOP { @@ -54,6 +68,23 @@ UINT System : 1; UINT Global : 1; UINT MenuNameIsString : 1; + +#define CLASS_DEFAULT 0x0 +#define CLASS_DESKTOP 0x1 +#define CLASS_DIALOG 0x2 +#define CLASS_POPUPMENU 0x3 +#define CLASS_COMBO 0x4 +#define CLASS_COMBOLBOX 0x5 +#define CLASS_MDICLIENT 0x6 +#define CLASS_MENU 0x7 +#define CLASS_SCROLL 0x8 +#define CLASS_BUTTON 0x9 +#define CLASS_LISTBOX 0xA +#define CLASS_EDIT 0xB +#define CLASS_ICONTITLE 0xC +#define CLASS_STATIC 0xD + UINT ClassId : 4; + } WINDOWCLASS, *PWINDOWCLASS;
typedef struct _WINDOW @@ -92,6 +123,9 @@ PWINDOWCLASS LocalClassList; PWINDOWCLASS GlobalClassList; PWINDOWCLASS SystemClassList; + + UINT RegisteredSysClasses : 1; + } W32PROCESSINFO, *PW32PROCESSINFO;
typedef struct _W32THREADINFO @@ -590,6 +624,7 @@ #define TWOPARAM_ROUTINE_ROS_SHOWWINDOW 0x1000 #define TWOPARAM_ROUTINE_ROS_ISACTIVEICON 0x1001 #define TWOPARAM_ROUTINE_ROS_NCDESTROY 0x1002 +#define TWOPARAM_ROUTINE_ROS_REGSYSCLASSES 0x1003 DWORD NTAPI NtUserCallTwoParam( @@ -1761,8 +1796,7 @@
/* FIXME: These flag constans aren't what Windows uses. */ #define REGISTERCLASS_ANSI 2 -#define REGISTERCLASS_SYSTEM 4 -#define REGISTERCLASS_ALL (REGISTERCLASS_ANSI | REGISTERCLASS_SYSTEM) +#define REGISTERCLASS_ALL (REGISTERCLASS_ANSI)
RTL_ATOM NTAPI NtUserRegisterClassEx(
Modified: trunk/reactos/subsystems/win32/win32k/include/class.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/class.h (original) +++ trunk/reactos/subsystems/win32/win32k/include/class.h Fri Nov 16 10:12:59 2007 @@ -74,6 +74,10 @@ IN WNDPROC WndProc, IN BOOL bUnicode);
+BOOL +UserRegisterSystemClasses(IN ULONG Count, + IN PREGISTER_SYSCLASS SystemClasses); + VOID UserAddCallProcToClass(IN OUT PWINDOWCLASS Class, IN PCALLPROC CallProc);
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/class.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/class.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/class.c Fri Nov 16 10:12:59 2007 @@ -38,6 +38,8 @@
/* WINDOWCLASS ***************************************************************/
+#define REGISTERCLASS_SYSTEM 0x4 + static VOID IntFreeClassMenuName(IN OUT PWINDOWCLASS Class) { @@ -1042,9 +1044,11 @@ { RTL_ATOM Atom = (RTL_ATOM)0;
+ ASSERT(BaseClass != NULL); + if (IntGetAtomFromStringOrAtom(ClassName, &Atom) && - BaseClass != NULL && Atom != (RTL_ATOM)0) + Atom != (RTL_ATOM)0) { PWINDOWCLASS Class;
@@ -1098,7 +1102,6 @@ NULL, &pi->SystemClassList, Link); - if (Class == NULL) { SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); @@ -1129,7 +1132,7 @@ /* NOTE: Accessing the buffers in ClassName and MenuName may raise exceptions! */
ti = GetW32ThreadInfo(); - if (ti == NULL) + if (ti == NULL || !ti->kpi->RegisteredSysClasses) { SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); return (RTL_ATOM)0; @@ -1792,6 +1795,74 @@ lpwcx->hIconSm = Class->hIconSm; /* FIXME - get handle from pointer */
return TRUE; +} + +BOOL +UserRegisterSystemClasses(IN ULONG Count, + IN PREGISTER_SYSCLASS SystemClasses) +{ + /* NOTE: This routine may raise exceptions! */ + UINT i; + UNICODE_STRING ClassName, MenuName; + PW32PROCESSINFO pi = GetW32ProcessInfo(); + WNDCLASSEXW wc; + PWINDOWCLASS Class; + BOOL Ret = TRUE; + + if (pi->RegisteredSysClasses || pi->hModUser == NULL) + return FALSE; + + RtlZeroMemory(&MenuName, sizeof(MenuName)); + + for (i = 0; i != Count; i++) + { + ClassName = ProbeForReadUnicodeString(&SystemClasses[i].ClassName); + if (ClassName.Length != 0) + { + ProbeForRead(ClassName.Buffer, + ClassName.Length, + sizeof(WCHAR)); + } + + wc.cbSize = sizeof(wc); + wc.style = SystemClasses[i].Style; + wc.lpfnWndProc = SystemClasses[i].ProcW; + wc.cbClsExtra = 0; + wc.cbWndExtra = SystemClasses[i].ExtraBytes; + wc.hInstance = pi->hModUser; + wc.hIcon = NULL; + wc.hCursor = SystemClasses[i].hCursor; + wc.hbrBackground = SystemClasses[i].hBrush; + wc.lpszMenuName = NULL; + wc.lpszClassName = ClassName.Buffer; + wc.hIconSm = NULL; + + Class = IntCreateClass(&wc, + &ClassName, + &MenuName, + SystemClasses[i].ProcA, + REGISTERCLASS_SYSTEM, + NULL, + pi); + if (Class != NULL) + { + Class->ClassId = SystemClasses[i].ClassId; + + ASSERT(Class->System); + Class->Next = pi->SystemClassList; + (void)InterlockedExchangePointer(&pi->SystemClassList, + Class); + } + else + { + WARN("!!! Registering system class failed!\n"); + Ret = FALSE; + } + } + + if (Ret) + pi->RegisteredSysClasses = TRUE; + return Ret; }
/* SYSCALLS *****************************************************************/ @@ -2179,9 +2250,9 @@ else { if (CapturedClassName.Length == 0) - WARN("Tried to get information of a non-existing class atom 0x%p\n", CapturedClassName.Buffer); + WARN("Tried to get information of a non-existing class atom 0x%p process 0x%p init: 0x%x\n", CapturedClassName.Buffer, PsGetCurrentProcessId(), pi->RegisteredSysClasses); else - WARN("Tried to get information of a non-existing class "%wZ"\n", &CapturedClassName); + WARN("Tried to get information of a non-existing class "%wZ" process 0x%p init: 0x%x\n", &CapturedClassName, PsGetCurrentProcessId(), pi->RegisteredSysClasses); SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); } }
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/misc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/misc.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/misc.c Fri Nov 16 10:12:59 2007 @@ -765,6 +765,33 @@ RETURN( Ret); }
+ case TWOPARAM_ROUTINE_ROS_REGSYSCLASSES: + { + DWORD Ret = 0; + DWORD Count = Param1; + PREGISTER_SYSCLASS RegSysClassArray = (PREGISTER_SYSCLASS)Param2; + + if (Count != 0 && RegSysClassArray != NULL) + { + _SEH_TRY + { + ProbeArrayForRead(RegSysClassArray, + sizeof(RegSysClassArray[0]), + Count, + 2); + + Ret = (DWORD)UserRegisterSystemClasses(Count, + RegSysClassArray); + } + _SEH_HANDLE + { + SetLastNtError(_SEH_GetExceptionCode()); + } + _SEH_END; + } + + RETURN( Ret); + } } DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam(), Param1=0x%x Parm2=0x%x\n", Routine, Param1, Param2);