Author: mjansen
Date: Sun Aug 21 18:28:33 2016
New Revision: 72414

URL: http://svn.reactos.org/svn/reactos?rev=72414&view=rev
Log:
[WIN32SS] Implement windows class versioning, by Sylvain Deverre. CORE-11858 
#comment Committed, thanks!

Modified:
    trunk/reactos/win32ss/user/ntuser/class.c
    trunk/reactos/win32ss/user/ntuser/window.c
    trunk/reactos/win32ss/user/user32/windows/class.c
    trunk/reactos/win32ss/user/user32/windows/window.c

Modified: trunk/reactos/win32ss/user/ntuser/class.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/class.c?rev=72414&r1=72413&r2=72414&view=diff
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/class.c   [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/class.c   [iso-8859-1] Sun Aug 21 
18:28:33 2016
@@ -255,6 +255,9 @@
         // comparisons, remove registration of the atom if not zeroed.
         if (Class->atomClassName)
             IntDeregisterClassAtom(Class->atomClassName);
+        // Dereference non-versioned class name
+        if (Class->atomNVClassName)
+            IntDeregisterClassAtom(Class->atomNVClassName);
 
         if (Class->pdce)
         {
@@ -423,22 +426,37 @@
 
     /* Update the base class first */
     Class = Class->pclsBase;
-
-    if (!IntRegisterClassAtom(ClassName,
-                              &Atom))
-    {
-        return FALSE;
-    }
-
-    IntDeregisterClassAtom(Class->atomClassName);
-
-    Class->atomClassName = Atom;
+    if (ClassName->Length > 0)
+    {
+        if (!IntRegisterClassAtom(ClassName,
+                                  &Atom))
+        {
+            ERR("RegisterClassAtom failed ! %x\n", EngGetLastError());
+            return FALSE;
+        }
+    }
+    else
+    {
+        if (IS_ATOM(ClassName->Buffer))
+        {
+            Atom = (ATOM)((ULONG_PTR)ClassName->Buffer & 0xffff); // XXX: are 
we missing refcount here ?
+        }
+        else
+        {
+            EngSetLastError(ERROR_INVALID_PARAMETER);
+            return FALSE;
+        }
+    }
+
+    IntDeregisterClassAtom(Class->atomNVClassName);
+
+    Class->atomNVClassName = Atom;
 
     /* Update the clones */
     Class = Class->pclsClone;
     while (Class != NULL)
     {
-        Class->atomClassName = Atom;
+        Class->atomNVClassName = Atom;
 
         Class = Class->pclsNext;
     }
@@ -1000,6 +1018,7 @@
 FASTCALL
 IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
                IN PUNICODE_STRING ClassName,
+               IN PUNICODE_STRING ClassVersion,
                IN PUNICODE_STRING MenuName,
                IN DWORD fnID,
                IN DWORD dwFlags,
@@ -1008,7 +1027,7 @@
 {
     SIZE_T ClassSize;
     PCLS Class = NULL;
-    RTL_ATOM Atom;
+    RTL_ATOM Atom, verAtom;
     WNDPROC WndProc;
     PWSTR pszMenuName = NULL;
     NTSTATUS Status = STATUS_SUCCESS;
@@ -1020,6 +1039,14 @@
                               &Atom))
     {
         ERR("Failed to register class atom!\n");
+        return NULL;
+    }
+
+    if (!IntRegisterClassAtom(ClassVersion,
+                              &verAtom))
+    {
+        ERR("Failed to register version class atom!\n");
+        IntDeregisterClassAtom(Atom);
         return NULL;
     }
 
@@ -1054,7 +1081,8 @@
 
         Class->rpdeskParent = Desktop;
         Class->pclsBase = Class;
-        Class->atomClassName = Atom;
+        Class->atomClassName = verAtom;
+        Class->atomNVClassName = Atom;
         Class->fnid = fnID;
         Class->CSF_flags = dwFlags;
 
@@ -1181,6 +1209,7 @@
                             Class);
             Class = NULL;
 
+            IntDeregisterClassAtom(verAtom);
             IntDeregisterClassAtom(Atom);
         }
     }
@@ -1193,12 +1222,13 @@
             UserHeapFree(pszMenuName);
 
         IntDeregisterClassAtom(Atom);
+        IntDeregisterClassAtom(verAtom);
 
         EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
     }
 
-    TRACE("Created class 0x%p with name %wZ and proc 0x%p for atom 0x%x and 
hInstance 0x%p, global %u\n",
-            Class, ClassName, Class->lpfnWndProc, Atom, Class->hModule, 
Class->Global);
+    TRACE("Created class 0x%p with name %wZ and proc 0x%p for atom 0x%x and 
version atom 0x%x and hInstance 0x%p, global %u\n",
+            Class, ClassName, Class->lpfnWndProc, Atom, verAtom, 
Class->hModule, Class->Global);
 
     return Class;
 }
@@ -1429,6 +1459,7 @@
 RTL_ATOM
 UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
                   IN PUNICODE_STRING ClassName,
+                  IN PUNICODE_STRING ClassVersion,
                   IN PUNICODE_STRING MenuName,
                   IN DWORD fnID,
                   IN DWORD dwFlags)
@@ -1446,7 +1477,7 @@
     pi = pti->ppi;
 
     // Need only to test for two conditions not four....... Fix more whine 
tests....
-    if ( IntGetAtomFromStringOrAtom( ClassName, &ClassAtom) &&
+    if ( IntGetAtomFromStringOrAtom( ClassVersion, &ClassAtom) &&
                                      ClassAtom != (RTL_ATOM)0 &&
                                     !(dwFlags & CSF_SERVERSIDEPROC) ) // 
Bypass Server Sides
     {
@@ -1481,6 +1512,7 @@
 
     Class = IntCreateClass(lpwcx,
                            ClassName,
+                           ClassVersion,
                            MenuName,
                            fnID,
                            dwFlags,
@@ -1501,7 +1533,7 @@
         (void)InterlockedExchangePointer((PVOID*)List,
                                          Class);
 
-        Ret = Class->atomClassName;
+        Ret = Class->atomNVClassName;
     }
     else
     {
@@ -1624,7 +1656,7 @@
 
                 /* Query the class name */
                 Status = RtlQueryAtomInAtomTable(gAtomTable,
-                                                 Atom ? Atom : 
Class->atomClassName,
+                                                 Atom ? Atom : 
Class->atomNVClassName,
                                                  NULL,
                                                  NULL,
                                                  szTemp,
@@ -1658,7 +1690,7 @@
 
             /* Query the atom name */
             Status = RtlQueryAtomInAtomTable(gAtomTable,
-                                             Atom ? Atom : 
Class->atomClassName,
+                                             Atom ? Atom : 
Class->atomNVClassName,
                                              NULL,
                                              NULL,
                                              ClassName->Buffer,
@@ -2165,7 +2197,7 @@
         {
             PUNICODE_STRING Value = (PUNICODE_STRING)NewLong;
 
-            Ret = (ULONG_PTR)Class->atomClassName;
+            Ret = (ULONG_PTR)Class->atomNVClassName;
             if (!IntSetClassAtom(Class,
                                  Value))
             {
@@ -2318,6 +2350,7 @@
         wc.hIconSm = NULL;
 
         Class = IntCreateClass( &wc,
+                                &ClassName,
                                 &ClassName,
                                 &MenuName,
                                  DefaultServerClasses[i].fiId,
@@ -2366,7 +2399,7 @@
  */
 {
     WNDCLASSEXW CapturedClassInfo = {0};
-    UNICODE_STRING CapturedName = {0}, CapturedMenuName = {0};
+    UNICODE_STRING CapturedName = {0}, CapturedMenuName = {0}, CapturedVersion 
= {0};
     RTL_ATOM Ret = (RTL_ATOM)0;
     PPROCESSINFO ppi = GetW32ProcessInfo();
     BOOL Exception = FALSE;
@@ -2404,6 +2437,7 @@
                       sizeof(WNDCLASSEXW));
 
         CapturedName = ProbeForReadUnicodeString(ClassName);
+        CapturedVersion = ProbeForReadUnicodeString(ClsNVersion);
 
         ProbeForRead(pClassMenuName,
                      sizeof(CLSMENUNAME),
@@ -2439,6 +2473,21 @@
             }
         }
 
+        if (CapturedVersion.Length != 0)
+        {
+            ProbeForRead(CapturedVersion.Buffer,
+                         CapturedVersion.Length,
+                         sizeof(WCHAR));
+        }
+        else
+        {
+            if (!IS_ATOM(CapturedVersion.Buffer))
+            {
+                ERR("NtUserRegisterClassExWOW ClassName Error!\n");
+                goto InvalidParameter;
+            }
+        }
+
         if (CapturedMenuName.Length != 0)
         {
             ProbeForRead(CapturedMenuName.Buffer,
@@ -2475,6 +2524,7 @@
         /* Register the class */
         Ret = UserRegisterClass(&CapturedClassInfo,
                                 &CapturedName,
+                                &CapturedVersion,
                                 &CapturedMenuName,
                                 fnID,
                                 Flags);
@@ -2520,7 +2570,18 @@
             /* Probe the parameters */
             if (Offset == GCW_ATOM || Offset == GCLP_MENUNAME)
             {
-                Value = ProbeForReadUnicodeString((PUNICODE_STRING)dwNewLong);
+                /* FIXME: Resource ID can be passed directly without 
UNICODE_STRING ? */
+                if (IS_ATOM(dwNewLong))
+                {
+                    Value.MaximumLength = 0;
+                    Value.Length = 0;
+                    Value.Buffer = (PWSTR)dwNewLong;
+                }
+                else
+                {
+                    Value = 
ProbeForReadUnicodeString((PUNICODE_STRING)dwNewLong);
+                }
+
                 if (Value.Length & 1)
                 {
                     goto InvalidParameter;

Modified: trunk/reactos/win32ss/user/ntuser/window.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/window.c?rev=72414&r1=72413&r2=72414&view=diff
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/window.c  [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/window.c  [iso-8859-1] Sun Aug 21 
18:28:33 2016
@@ -2403,13 +2403,16 @@
     NTSTATUS Status;
     LARGE_STRING lstrWindowName;
     LARGE_STRING lstrClassName;
+    LARGE_STRING lstrClsVersion;
     UNICODE_STRING ustrClassName;
+    UNICODE_STRING ustrClsVersion;
     CREATESTRUCTW Cs;
     HWND hwnd = NULL;
     PWND pwnd;
 
     lstrWindowName.Buffer = NULL;
     lstrClassName.Buffer = NULL;
+    lstrClsVersion.Buffer = NULL;
 
     ASSERT(plstrWindowName);
 
@@ -2461,6 +2464,32 @@
         ustrClassName.MaximumLength = (USHORT)min(lstrClassName.MaximumLength, 
MAXUSHORT);
     }
 
+    /* Check if the class version is an atom */
+    if (IS_ATOM(plstrClsVersion))
+    {
+        /* It is, pass the atom in the UNICODE_STRING */
+        ustrClsVersion.Buffer = (PVOID)plstrClsVersion;
+        ustrClsVersion.Length = 0;
+        ustrClsVersion.MaximumLength = 0;
+    }
+    else
+    {
+        /* It's not, capture the class name */
+        Status = ProbeAndCaptureLargeString(&lstrClsVersion, plstrClsVersion);
+        if (!NT_SUCCESS(Status))
+        {
+            ERR("NtUserCreateWindowEx: failed to capture plstrClsVersion\n");
+            /* Set last error, cleanup and return */
+            SetLastNtError(Status);
+            goto cleanup;
+        }
+
+        /* We pass it on as a UNICODE_STRING */
+        ustrClsVersion.Buffer = lstrClsVersion.Buffer;
+        ustrClsVersion.Length = (USHORT)min(lstrClsVersion.Length, MAXUSHORT); 
// FIXME: LARGE_STRING truncated
+        ustrClsVersion.MaximumLength = 
(USHORT)min(lstrClsVersion.MaximumLength, MAXUSHORT);
+    }
+
     /* Fill the CREATESTRUCTW */
     /* we will keep here the original parameters */
     Cs.style = dwStyle;
@@ -2479,7 +2508,7 @@
     UserEnterExclusive();
 
     /* Call the internal function */
-    pwnd = co_UserCreateWindowEx(&Cs, &ustrClassName, plstrWindowName, 
acbiBuffer);
+    pwnd = co_UserCreateWindowEx(&Cs, &ustrClsVersion, plstrWindowName, 
acbiBuffer);
 
     if(!pwnd)
     {
@@ -2497,6 +2526,10 @@
     if (lstrClassName.Buffer)
     {
         ExFreePoolWithTag(lstrClassName.Buffer, TAG_STRING);
+    }
+    if (lstrClsVersion.Buffer)
+    {
+        ExFreePoolWithTag(lstrClsVersion.Buffer, TAG_STRING);
     }
 
    return hwnd;

Modified: trunk/reactos/win32ss/user/user32/windows/class.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/user32/windows/class.c?rev=72414&r1=72413&r2=72414&view=diff
==============================================================================
--- trunk/reactos/win32ss/user/user32/windows/class.c   [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/user32/windows/class.c   [iso-8859-1] Sun Aug 21 
18:28:33 2016
@@ -710,7 +710,7 @@
                 break;
 
             case GCW_ATOM:
-                Ret = (ULONG_PTR)Class->atomClassName;
+                Ret = (ULONG_PTR)Class->atomNVClassName;
                 break;
 
             case GCLP_HCURSOR:
@@ -784,7 +784,7 @@
                 break;
 
             case GCW_ATOM:
-                Ret = (ULONG_PTR)Class->atomClassName;
+                Ret = (ULONG_PTR)Class->atomNVClassName;
                 break;
 
             case GCLP_HCURSOR:
@@ -1503,7 +1503,7 @@
    {
        Atom = NtUserRegisterClassExWOW( &WndClass,
                                         &ClassName,
-                                         NULL, //PUNICODE_STRING ClsNVersion,
+                                        &ClassName, //PUNICODE_STRING 
ClsNVersion,
                                         &clsMenuName,
                                          fnID,
                                          dwFlags,

Modified: trunk/reactos/win32ss/user/user32/windows/window.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/user32/windows/window.c?rev=72414&r1=72413&r2=72414&view=diff
==============================================================================
--- trunk/reactos/win32ss/user/user32/windows/window.c  [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/user32/windows/window.c  [iso-8859-1] Sun Aug 21 
18:28:33 2016
@@ -267,7 +267,7 @@
     {
        Handle = NtUserCreateWindowEx(dwExStyle,
                                      plstrClassName,
-                                     NULL,
+                                     plstrClassName,
                                      &WindowName,
                                      dwStyle,
                                      x,


Reply via email to