mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 17:05:46 +00:00
Make registration of system window classes a bit more robust
svn path=/trunk/; revision=30492
This commit is contained in:
parent
6687385c3b
commit
bc74f1df6f
10 changed files with 189 additions and 129 deletions
|
@ -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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -105,8 +105,11 @@ DllMain(
|
|||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
User32Instance = hInstanceDll;
|
||||
if (!NtUserRegisterUserModule(hInstanceDll))
|
||||
if (!NtUserRegisterUserModule(hInstanceDll) ||
|
||||
!RegisterSystemControls())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hProcessHeap = RtlGetProcessHeap();
|
||||
if (!Init())
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
#include <wine/debug.h>
|
||||
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,
|
||||
|
|
|
@ -16,8 +16,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 );
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue