https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4a1877d0f6c9d35fd007ba88106efa126cff4f63
commit 4a1877d0f6c9d35fd007ba88106efa126cff4f63 Author: Whindmar Saksit <whinds...@proton.me> AuthorDate: Wed Mar 19 00:10:46 2025 +0100 Commit: GitHub <nore...@github.com> CommitDate: Wed Mar 19 00:10:46 2025 +0100 [NTDLL][SHLWAPI][SYSDM] ReportAsWorkstation should always override the product type (#7052) Allows "ROS as a workstation" installs to report itself as a basic server to Win32 applications when the user toggles the sysdm.cpl checkbox (to unchecked in this case). --- dll/cpl/sysdm/advanced.c | 18 +++++----- dll/ntdll/rtl/version.c | 42 +++++++++++++++++----- dll/win32/shlwapi/ordinal.c | 23 +++++++++++- .../rostests/apitests/ntdll/RtlGetNtProductType.c | 25 ++++++++++++- 4 files changed, 87 insertions(+), 21 deletions(-) diff --git a/dll/cpl/sysdm/advanced.c b/dll/cpl/sysdm/advanced.c index ce8a5942235..4b8c0bd6929 100644 --- a/dll/cpl/sysdm/advanced.c +++ b/dll/cpl/sysdm/advanced.c @@ -9,6 +9,8 @@ */ #include "precomp.h" +#define WIN32_NO_STATUS +#include "pstypes.h" /* SharedUserData */ static TCHAR BugLink[] = _T("http://jira.reactos.org/";); static TCHAR ReportAsWorkstationKey[] = _T("SYSTEM\\CurrentControlSet\\Control\\ReactOS\\Settings\\Version"); @@ -51,9 +53,10 @@ static VOID OnInitSysSettingsDialog(HWND hwndDlg) { HKEY hKey; - DWORD dwVal; + DWORD dwVal = 0; DWORD dwType = REG_DWORD; DWORD cbData = sizeof(DWORD); + BOOL ReportAsWorkstation = SharedUserData->NtProductType == VER_NT_WORKSTATION; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, ReportAsWorkstationKey, @@ -68,19 +71,14 @@ OnInitSysSettingsDialog(HWND hwndDlg) (LPBYTE)&dwVal, &cbData) == ERROR_SUCCESS) { - if (dwVal != FALSE) - { - // set the check box - SendDlgItemMessageW(hwndDlg, - IDC_REPORTASWORKSTATION, - BM_SETCHECK, - BST_CHECKED, - 0); - } + if (cbData == sizeof(DWORD)) + ReportAsWorkstation = dwVal != FALSE; } RegCloseKey(hKey); } + SendDlgItemMessageW(hwndDlg, IDC_REPORTASWORKSTATION, BM_SETCHECK, + ReportAsWorkstation ? BST_CHECKED : BST_UNCHECKED, 0); } INT_PTR CALLBACK diff --git a/dll/ntdll/rtl/version.c b/dll/ntdll/rtl/version.c index 96a9be1f162..63f94592f88 100644 --- a/dll/ntdll/rtl/version.c +++ b/dll/ntdll/rtl/version.c @@ -17,6 +17,8 @@ /* FUNCTIONS ******************************************************************/ +static signed char g_ReportProductType = 0; + /* HACK: ReactOS specific changes, see bug-reports CORE-6611 and CORE-4620 (aka. #5003) */ static VOID NTAPI SetRosSpecificInfo(IN OUT PRTL_OSVERSIONINFOEXW VersionInformation) @@ -24,7 +26,6 @@ SetRosSpecificInfo(IN OUT PRTL_OSVERSIONINFOEXW VersionInformation) CHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)]; PKEY_VALUE_PARTIAL_INFORMATION kvpInfo = (PVOID)Buffer; OBJECT_ATTRIBUTES ObjectAttributes; - ULONG ReportAsWorkstation = 0; HANDLE hKey; ULONG Length; NTSTATUS Status; @@ -38,7 +39,7 @@ SetRosSpecificInfo(IN OUT PRTL_OSVERSIONINFOEXW VersionInformation) NULL); /* Don't change anything if the key doesn't exist */ - Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes); + Status = (g_ReportProductType == 0) ? NtOpenKey(&hKey, KEY_READ, &ObjectAttributes) : STATUS_CANCELLED; if (NT_SUCCESS(Status)) { /* Get the value from the registry and make sure it's a 32-bit value */ @@ -52,20 +53,28 @@ SetRosSpecificInfo(IN OUT PRTL_OSVERSIONINFOEXW VersionInformation) (kvpInfo->Type == REG_DWORD) && (kvpInfo->DataLength == sizeof(ULONG))) { - /* Is the value set? */ - ReportAsWorkstation = *(PULONG)kvpInfo->Data; - if ((VersionInformation->wProductType == VER_NT_SERVER) && - (ReportAsWorkstation != 0)) + ULONG IsWorkstation = SharedUserData->NtProductType == NtProductWinNt; + ULONG ReportAsWorkstation = (*(PULONG)kvpInfo->Data) != 0; + if (IsWorkstation != ReportAsWorkstation) { - /* It is, modify the product type to report a workstation */ - VersionInformation->wProductType = VER_NT_WORKSTATION; - DPRINT("We modified the reported OS from NtProductServer to NtProductWinNt\n"); + g_ReportProductType = ReportAsWorkstation ? NtProductWinNt : NtProductServer; } } /* Close the handle */ NtClose(hKey); } + + if (g_ReportProductType > 0) + { + VersionInformation->wProductType = g_ReportProductType; + DPRINT("We modified the reported OS product type from %d to %d\n", + SharedUserData->NtProductType, VersionInformation->wProductType); + } + else + { + g_ReportProductType = -1; + } } /********************************************************************** @@ -96,6 +105,21 @@ BOOLEAN NTAPI RtlGetNtProductType(_Out_ PNT_PRODUCT_TYPE ProductType) { *ProductType = SharedUserData->NtProductType; + + if (g_ReportProductType == 0) + { + /* Initialize cached value */ + RTL_OSVERSIONINFOEXW ovi; + ovi.dwOSVersionInfoSize = sizeof(ovi); + ovi.wProductType = *ProductType; + SetRosSpecificInfo(&ovi); + } + + if (g_ReportProductType > 0) + { + *ProductType = g_ReportProductType; + DPRINT("Overriding RtlGetNtProductType to return %d\n", *ProductType); + } return TRUE; } diff --git a/dll/win32/shlwapi/ordinal.c b/dll/win32/shlwapi/ordinal.c index 3d506b0285e..3646c54153c 100644 --- a/dll/win32/shlwapi/ordinal.c +++ b/dll/win32/shlwapi/ordinal.c @@ -4106,6 +4106,23 @@ HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id) */ BOOL WINAPI IsOS(DWORD feature) { +#ifdef __REACTOS__ + OSVERSIONINFOEXA osvi; + DWORD platform, majorv, minorv; + + osvi.dwOSVersionInfoSize = sizeof(osvi); + if (!GetVersionExA((OSVERSIONINFOA*)&osvi)) + { + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); + if (!GetVersionExA((OSVERSIONINFOA*)&osvi)) + { + ERR("GetVersionEx failed\n"); + return FALSE; + } + osvi.wProductType = VER_NT_WORKSTATION; + osvi.wSuiteMask = 0; + } +#else OSVERSIONINFOA osvi; DWORD platform, majorv, minorv; @@ -4114,7 +4131,7 @@ BOOL WINAPI IsOS(DWORD feature) ERR("GetVersionEx failed\n"); return FALSE; } - +#endif majorv = osvi.dwMajorVersion; minorv = osvi.dwMinorVersion; platform = osvi.dwPlatformId; @@ -4189,7 +4206,11 @@ BOOL WINAPI IsOS(DWORD feature) FIXME("(OS_DOMAINMEMBER) What should we return here?\n"); return TRUE; case OS_ANYSERVER: +#ifdef __REACTOS__ + ISOS_RETURN(osvi.wProductType > VER_NT_WORKSTATION) +#else ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) +#endif case OS_WOW6432: { BOOL is_wow64; diff --git a/modules/rostests/apitests/ntdll/RtlGetNtProductType.c b/modules/rostests/apitests/ntdll/RtlGetNtProductType.c index 03ac8238e07..29051810ec2 100644 --- a/modules/rostests/apitests/ntdll/RtlGetNtProductType.c +++ b/modules/rostests/apitests/ntdll/RtlGetNtProductType.c @@ -91,7 +91,7 @@ ChangeNtProductType(DWORD NtProductType) } else { - ok(FALSE, "Passed invalid product type to CHangeNtProduct: %lu", NtProductType); + ok(FALSE, "Passed invalid product type to ChangeNtProduct: %lu", NtProductType); } Result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, @@ -129,6 +129,19 @@ START_TEST(RtlGetNtProductType) DWORD ProductNtType; NT_PRODUCT_TYPE ProductType = NtProductWinNt, ProductType2; + /* Remove ReportAsWorkstation override during tests */ + DWORD ReportAsWorkstation = 0xbaadf00d; + HKEY hKey; + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\ReactOS\\Settings\\Version", + 0, KEY_READ | KEY_WRITE, &hKey) == ERROR_SUCCESS) + { + DWORD cb = sizeof(DWORD); + if (RegQueryValueExW(hKey, L"ReportAsWorkstation", NULL, NULL, (PBYTE)&ReportAsWorkstation, &cb)) + ReportAsWorkstation = 0xbaadf00d; + RegDeleteValueW(hKey, L"ReportAsWorkstation"); + RegCloseKey(hKey); + } + /* * Wrap the call in SEH. This ensures the testcase won't crash but also * it proves to us that RtlGetNtProductType() throws an exception if a NULL @@ -164,4 +177,14 @@ START_TEST(RtlGetNtProductType) ok_long(ProductType2, ProductType); ok_char(ChangeNtProductType(ProductType), TRUE); + + + /* Restore ReportAsWorkstation */ + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\ReactOS\\Settings\\Version", + 0, KEY_WRITE, &hKey) == ERROR_SUCCESS) + { + if (ReportAsWorkstation != 0xbaadf00d) + RegSetValueExW(hKey, L"ReportAsWorkstation", 0, REG_DWORD, (PBYTE)&ReportAsWorkstation, sizeof(DWORD)); + RegCloseKey(hKey); + } }