Index: win32ss/user/ntuser/class.c =================================================================== --- win32ss/user/ntuser/class.c (revision 72405) +++ win32ss/user/ntuser/class.c (working copy) @@ -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)) + if (ClassName->Length > 0) { - return FALSE; + 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->atomClassName); + IntDeregisterClassAtom(Class->atomNVClassName); - Class->atomClassName = Atom; + 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; @@ -1023,6 +1042,14 @@ return NULL; } + if (!IntRegisterClassAtom(ClassVersion, + &verAtom)) + { + ERR("Failed to register version class atom!\n"); + IntDeregisterClassAtom(Atom); + return NULL; + } + ClassSize = sizeof(*Class) + lpwcx->cbClsExtra; if (MenuName->Length != 0) { @@ -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)) { @@ -2319,6 +2351,7 @@ Class = IntCreateClass( &wc, &ClassName, + &ClassName, &MenuName, DefaultServerClasses[i].fiId, Flags, @@ -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; Index: win32ss/user/ntuser/window.c =================================================================== --- win32ss/user/ntuser/window.c (revision 72405) +++ win32ss/user/ntuser/window.c (working copy) @@ -2403,7 +2403,9 @@ NTSTATUS Status; LARGE_STRING lstrWindowName; LARGE_STRING lstrClassName; + LARGE_STRING lstrClsVersion; UNICODE_STRING ustrClassName; + UNICODE_STRING ustrClsVersion; CREATESTRUCTW Cs; HWND hwnd = NULL; PWND pwnd; @@ -2410,6 +2412,7 @@ 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) { @@ -2498,6 +2527,10 @@ { ExFreePoolWithTag(lstrClassName.Buffer, TAG_STRING); } + if (lstrClsVersion.Buffer) + { + ExFreePoolWithTag(lstrClsVersion.Buffer, TAG_STRING); + } return hwnd; } Index: win32ss/user/user32/windows/class.c =================================================================== --- win32ss/user/user32/windows/class.c (revision 72405) +++ win32ss/user/user32/windows/class.c (working copy) @@ -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, Index: win32ss/user/user32/windows/window.c =================================================================== --- win32ss/user/user32/windows/window.c (revision 72405) +++ win32ss/user/user32/windows/window.c (working copy) @@ -267,7 +267,7 @@ { Handle = NtUserCreateWindowEx(dwExStyle, plstrClassName, - NULL, + plstrClassName, &WindowName, dwStyle, x,