diff --git a/reactos/dll/win32/user32/controls/regcontrol.c b/reactos/dll/win32/user32/controls/regcontrol.c index d6f528e798c..caf5ffae308 100644 --- a/reactos/dll/win32/user32/controls/regcontrol.c +++ b/reactos/dll/win32/user32/controls/regcontrol.c @@ -13,110 +13,51 @@ #include -static void RegisterBuiltinClass(const struct builtin_class_descr *Descr) +static const struct { - WNDCLASSEXW wc; - UNICODE_STRING ClassName; - UNICODE_STRING MenuName; - - 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; - - MenuName.Length = - MenuName.MaximumLength = 0; - MenuName.Buffer = NULL; - - if (IS_ATOM(Descr->name)) - { - ClassName.Length = - ClassName.MaximumLength = 0; - ClassName.Buffer = (LPWSTR)Descr->name; - } else - { - RtlInitUnicodeString(&ClassName, Descr->name); - } - - NtUserRegisterClassEx( - &wc, - &ClassName, - &MenuName, - Descr->procA, - REGISTERCLASS_SYSTEM, - NULL); -} - -/*********************************************************************** - * ControlsInit - * - * Register the classes for the builtin controls - */ -BOOL FASTCALL -ControlsInit(LPCWSTR ClassName) + const struct builtin_class_descr *desc; + UINT ClsId; +} g_SysClasses[] = { - 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, + { &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, + { &MENU_builtin_class, CLASS_MENU }, #endif - &SCROLL_builtin_class, - &BUTTON_builtin_class, - &LISTBOX_builtin_class, - &EDIT_builtin_class, - &ICONTITLE_builtin_class, - &STATIC_builtin_class - }; - unsigned i; - BOOL Register; + { &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 }, +}; - Register = FALSE; - if (IS_ATOM(ClassName)) +BOOL WINAPI RegisterSystemControls(VOID) +{ + REGISTER_SYSCLASS cls[sizeof(g_SysClasses) / sizeof(g_SysClasses[0])]; + UINT i; + + ZeroMemory(cls, sizeof(cls)); + + for (i = 0; i != sizeof(cls) / sizeof(cls[0]); i++) { - 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)); - } - } + 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); + + 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); } diff --git a/reactos/dll/win32/user32/include/regcontrol.h b/reactos/dll/win32/user32/include/regcontrol.h index 5e417de2fd3..d509a50c521 100644 --- a/reactos/dll/win32/user32/include/regcontrol.h +++ b/reactos/dll/win32/user32/include/regcontrol.h @@ -26,7 +26,7 @@ struct builtin_class_descr 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; diff --git a/reactos/dll/win32/user32/include/user32p.h b/reactos/dll/win32/user32/include/user32p.h index 29d542db6ed..c7fa3999451 100644 --- a/reactos/dll/win32/user32/include/user32p.h +++ b/reactos/dll/win32/user32/include/user32p.h @@ -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; diff --git a/reactos/dll/win32/user32/misc/dllmain.c b/reactos/dll/win32/user32/misc/dllmain.c index 5fd1b10e478..ef9ccbd17f0 100644 --- a/reactos/dll/win32/user32/misc/dllmain.c +++ b/reactos/dll/win32/user32/misc/dllmain.c @@ -105,8 +105,11 @@ DllMain( { case DLL_PROCESS_ATTACH: User32Instance = hInstanceDll; - if (!NtUserRegisterUserModule(hInstanceDll)) + if (!NtUserRegisterUserModule(hInstanceDll) || + !RegisterSystemControls()) + { return FALSE; + } hProcessHeap = RtlGetProcessHeap(); if (!Init()) diff --git a/reactos/dll/win32/user32/windows/class.c b/reactos/dll/win32/user32/windows/class.c index acd1dc1c130..6c8fcfa017a 100644 --- a/reactos/dll/win32/user32/windows/class.c +++ b/reactos/dll/win32/user32/windows/class.c @@ -14,8 +14,6 @@ #include WINE_DEFAULT_DEBUG_CHANNEL(user32); -extern BOOL ControlsInitialized; - /* * @implemented */ @@ -62,12 +60,6 @@ GetClassInfoExA( } } - /* Register built-in controls if not already done */ - if (! ControlsInitialized) - { - ControlsInitialized = ControlsInit(ClassName.Buffer); - } - Ret = NtUserGetClassInfo(hInstance, &ClassName, (LPWNDCLASSEXW)lpwcx, @@ -123,12 +115,6 @@ GetClassInfoExW( lpszClass); } - /* Register built-in controls if not already done */ - if (! ControlsInitialized) - { - ControlsInitialized = ControlsInit(ClassName.Buffer); - } - return NtUserGetClassInfo(hInstance, &ClassName, lpwcx, diff --git a/reactos/dll/win32/user32/windows/window.c b/reactos/dll/win32/user32/windows/window.c index b2705daa5f3..a989ff3ef2c 100644 --- a/reactos/dll/win32/user32/windows/window.c +++ b/reactos/dll/win32/user32/windows/window.c @@ -16,8 +16,6 @@ #include 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 ); @@ -187,12 +185,6 @@ User32CreateWindowEx(DWORD dwExStyle, } } - /* Register built-in controls if not already done */ - if (! ControlsInitialized) - { - ControlsInitialized = ControlsInit(ClassName.Buffer); - } - if (Unicode) RtlInitUnicodeString(&WindowName, (PCWSTR)lpWindowName); else diff --git a/reactos/include/reactos/win32k/ntuser.h b/reactos/include/reactos/win32k/ntuser.h index 8974c232c89..d60d06e7dba 100644 --- a/reactos/include/reactos/win32k/ntuser.h +++ b/reactos/include/reactos/win32k/ntuser.h @@ -4,6 +4,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 { HANDLE hKernelHeap; @@ -54,6 +68,23 @@ typedef struct _WINDOWCLASS 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 @@ typedef struct _W32PROCESSINFO PWINDOWCLASS LocalClassList; PWINDOWCLASS GlobalClassList; PWINDOWCLASS SystemClassList; + + UINT RegisteredSysClasses : 1; + } W32PROCESSINFO, *PW32PROCESSINFO; typedef struct _W32THREADINFO @@ -590,6 +624,7 @@ NtUserCallOneParam( #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 @@ NtUserRegisterUserApiHook( /* 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( diff --git a/reactos/subsystems/win32/win32k/include/class.h b/reactos/subsystems/win32/win32k/include/class.h index 18b98ae50fd..a57b2fbd5bb 100644 --- a/reactos/subsystems/win32/win32k/include/class.h +++ b/reactos/subsystems/win32/win32k/include/class.h @@ -74,6 +74,10 @@ UserFindCallProc(IN PWINDOWCLASS Class, IN WNDPROC WndProc, IN BOOL bUnicode); +BOOL +UserRegisterSystemClasses(IN ULONG Count, + IN PREGISTER_SYSCLASS SystemClasses); + VOID UserAddCallProcToClass(IN OUT PWINDOWCLASS Class, IN PCALLPROC CallProc); diff --git a/reactos/subsystems/win32/win32k/ntuser/class.c b/reactos/subsystems/win32/win32k/ntuser/class.c index b4dd7f421ce..00e56b1b538 100644 --- a/reactos/subsystems/win32/win32k/ntuser/class.c +++ b/reactos/subsystems/win32/win32k/ntuser/class.c @@ -38,6 +38,8 @@ /* WINDOWCLASS ***************************************************************/ +#define REGISTERCLASS_SYSTEM 0x4 + static VOID IntFreeClassMenuName(IN OUT PWINDOWCLASS Class) { @@ -1042,9 +1044,11 @@ IntGetClassAtom(IN PUNICODE_STRING ClassName, { 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 @@ IntGetClassAtom(IN PUNICODE_STRING ClassName, NULL, &pi->SystemClassList, Link); - if (Class == NULL) { SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); @@ -1129,7 +1132,7 @@ UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx, /* 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; @@ -1794,6 +1797,74 @@ UserGetClassInfo(IN PWINDOWCLASS Class, 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 @@ InvalidParameter: 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); } } diff --git a/reactos/subsystems/win32/win32k/ntuser/misc.c b/reactos/subsystems/win32/win32k/ntuser/misc.c index 49ecb892046..8982f6e931c 100644 --- a/reactos/subsystems/win32/win32k/ntuser/misc.c +++ b/reactos/subsystems/win32/win32k/ntuser/misc.c @@ -765,6 +765,33 @@ NtUserCallTwoParam( 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);