Make registration of system window classes a bit more robust

svn path=/trunk/; revision=30492
This commit is contained in:
Thomas Bluemel 2007-11-16 07:12:59 +00:00
parent 6687385c3b
commit bc74f1df6f
10 changed files with 189 additions and 129 deletions

View file

@ -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);
}

View file

@ -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;

View file

@ -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;

View file

@ -105,8 +105,11 @@ DllMain(
{
case DLL_PROCESS_ATTACH:
User32Instance = hInstanceDll;
if (!NtUserRegisterUserModule(hInstanceDll))
if (!NtUserRegisterUserModule(hInstanceDll) ||
!RegisterSystemControls())
{
return FALSE;
}
hProcessHeap = RtlGetProcessHeap();
if (!Init())

View file

@ -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,

View file

@ -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

View file

@ -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(

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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);