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,