[ros-diffs] [weiden] 30492: Make registration of system window classes a bit more robust

weiden at svn.reactos.org weiden at svn.reactos.org
Fri Nov 16 08:13:00 CET 2007


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/regcontrol.c?rev=30492&r1=30491&r2=30492&view=diff
==============================================================================
--- 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/regcontrol.h?rev=30492&r1=30491&r2=30492&view=diff
==============================================================================
--- 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/user32p.h?rev=30492&r1=30491&r2=30492&view=diff
==============================================================================
--- 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/dllmain.c?rev=30492&r1=30491&r2=30492&view=diff
==============================================================================
--- 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/class.c?rev=30492&r1=30491&r2=30492&view=diff
==============================================================================
--- 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/window.c?rev=30492&r1=30491&r2=30492&view=diff
==============================================================================
--- 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/ntuser.h?rev=30492&r1=30491&r2=30492&view=diff
==============================================================================
--- 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/include/class.h?rev=30492&r1=30491&r2=30492&view=diff
==============================================================================
--- 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/ntuser/class.c?rev=30492&r1=30491&r2=30492&view=diff
==============================================================================
--- 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/ntuser/misc.c?rev=30492&r1=30491&r2=30492&view=diff
==============================================================================
--- 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);




More information about the Ros-diffs mailing list