[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).
This commit is contained in:
Whindmar Saksit 2025-03-19 00:10:46 +01:00 committed by GitHub
parent 19c1f5661f
commit 4a1877d0f6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 87 additions and 21 deletions

View file

@ -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

View file

@ -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;
}

View file

@ -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;

View file

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