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);
+    }
 }

Reply via email to