https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4a1877d0f6c9d35fd007b…
commit 4a1877d0f6c9d35fd007ba88106efa126cff4f63
Author: Whindmar Saksit <whindsaks(a)proton.me>
AuthorDate: Wed Mar 19 00:10:46 2025 +0100
Commit: GitHub <noreply(a)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/")rg/");
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);
+ }
}