diff --git a/base/applications/winver/CMakeLists.txt b/base/applications/winver/CMakeLists.txt index ac5b762b83ddd..55c82b76600fe 100644 --- a/base/applications/winver/CMakeLists.txt +++ b/base/applications/winver/CMakeLists.txt @@ -1,5 +1,11 @@ -add_executable(winver winver.c winver.rc) +list(APPEND SOURCE + osinfo.c + winver.c + winver_p.h) + +add_executable(winver ${SOURCE} winver.rc) set_module_type(winver win32gui UNICODE) -add_importlibs(winver shell32 comctl32 msvcrt kernel32) +add_importlibs(winver advapi32 user32 shell32 comctl32 msvcrt kernel32) +add_pch(winver winver_p.h SOURCE) add_cd_file(TARGET winver DESTINATION reactos/system32 FOR all) diff --git a/base/applications/winver/lang/en-US.rc b/base/applications/winver/lang/en-US.rc new file mode 100644 index 0000000000000..d0939b9a900e4 --- /dev/null +++ b/base/applications/winver/lang/en-US.rc @@ -0,0 +1,7 @@ +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +STRINGTABLE +BEGIN + IDS_OSINFO_COMPAT_FORMAT "Reporting NT %s (Build %s%s)" + IDS_OSINFO_SPK_FORMAT ": %s" +END diff --git a/base/applications/winver/osinfo.c b/base/applications/winver/osinfo.c new file mode 100644 index 0000000000000..b043d4ee648e0 --- /dev/null +++ b/base/applications/winver/osinfo.c @@ -0,0 +1,119 @@ +/* + * PROJECT: ReactOS Version Program + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Retrieve OS name and simple compatibility information + * COPYRIGHT: Copyright 2025 Thamatip Chitpong + */ + +#include "winver_p.h" + +#define OSINFO_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion" + +static +VOID +Winver_GetRegValueString( + _In_ HKEY hKey, + _In_ LPCWSTR lpValue, + _Out_ LPWSTR lpBuffer, + _In_ DWORD cchSize) +{ + DWORD dwType, dwSize; + LSTATUS lError; + + /* NOTE: Reserved space for a NULL terminator */ + dwSize = (cchSize - 1) * sizeof(WCHAR); + lError = RegQueryValueExW(hKey, lpValue, NULL, &dwType, (LPBYTE)lpBuffer, &dwSize); + if (lError != ERROR_SUCCESS || dwType != REG_SZ) + { + /* Return empty string on failure */ + lpBuffer[0] = UNICODE_NULL; + return; + } + + /* Ensure the returned string is NULL terminated */ + lpBuffer[cchSize - 1] = UNICODE_NULL; +} + +static +VOID +Winver_GetFormattedSpkInfo( + _In_ HKEY hKey, + _Out_ LPWSTR lpBuffer, + _In_ DWORD cchSize) +{ + WCHAR szRegValue[48]; + WCHAR szFormat[16] = L""; + + Winver_GetRegValueString(hKey, L"CSDVersion", szRegValue, _countof(szRegValue)); + if (!*szRegValue) + { + /* Return empty string on failure */ + lpBuffer[0] = UNICODE_NULL; + return; + } + + LoadStringW(GetModuleHandleW(NULL), + IDS_OSINFO_SPK_FORMAT, + szFormat, + _countof(szFormat)); + + StringCchPrintfW(lpBuffer, cchSize, szFormat, szRegValue); +} + +static +VOID +Winver_FormatCompatInfo( + _Inout_ PWINVER_OS_INFO OSInfo) +{ + WCHAR szFormat[64] = L""; + + /* Required info must be valid */ + if (!*(OSInfo->szNtVersion) || !*(OSInfo->szNtBuild)) + return; + + LoadStringW(GetModuleHandleW(NULL), + IDS_OSINFO_COMPAT_FORMAT, + szFormat, + _countof(szFormat)); + + /* NOTE: Service pack info is optional */ + StringCchPrintfW(OSInfo->szCompatInfo, _countof(OSInfo->szCompatInfo), szFormat, + OSInfo->szNtVersion, + OSInfo->szNtBuild, + OSInfo->szNtSpk); +} + +BOOL +Winver_GetOSInfo( + _Out_ PWINVER_OS_INFO OSInfo) +{ + HKEY hKey; + LSTATUS lError; + + lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + OSINFO_KEY, + 0, + KEY_QUERY_VALUE, + &hKey); + if (lError != ERROR_SUCCESS) + return FALSE; + + /* OS name */ + Winver_GetRegValueString(hKey, L"ProductName", OSInfo->szName, _countof(OSInfo->szName)); + if (!*(OSInfo->szName)) + { + /* This info must be valid */ + RegCloseKey(hKey); + return FALSE; + } + + /* Compatibility information */ + Winver_GetRegValueString(hKey, L"CurrentVersion", OSInfo->szNtVersion, _countof(OSInfo->szNtVersion)); + Winver_GetRegValueString(hKey, L"CurrentBuildNumber", OSInfo->szNtBuild, _countof(OSInfo->szNtBuild)); + Winver_GetFormattedSpkInfo(hKey, OSInfo->szNtSpk, _countof(OSInfo->szNtSpk)); + Winver_FormatCompatInfo(OSInfo); + + RegCloseKey(hKey); + + return TRUE; +} diff --git a/base/applications/winver/resource.h b/base/applications/winver/resource.h new file mode 100644 index 0000000000000..a336f0d70860c --- /dev/null +++ b/base/applications/winver/resource.h @@ -0,0 +1,4 @@ +#pragma once + +#define IDS_OSINFO_COMPAT_FORMAT 1 +#define IDS_OSINFO_SPK_FORMAT 2 diff --git a/base/applications/winver/winver.c b/base/applications/winver/winver.c index 1e22096c4eef7..eaf067b6db3a6 100644 --- a/base/applications/winver/winver.c +++ b/base/applications/winver/winver.c @@ -4,16 +4,12 @@ * FILE: base/applications/winver/winver.c */ -#include -#include -#include -#include -#include -#include +#include "winver_p.h" int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) { INITCOMMONCONTROLSEX iccx; + WINVER_OS_INFO OSInfo; UNREFERENCED_PARAMETER(hInstance); UNREFERENCED_PARAMETER(hPrevInstance); @@ -25,5 +21,12 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi iccx.dwICC = ICC_STANDARD_CLASSES | ICC_WIN95_CLASSES; InitCommonControlsEx(&iccx); - return ShellAboutW(NULL, L"ReactOS", NULL, NULL); + if (!Winver_GetOSInfo(&OSInfo)) + { + /* OS info is not available, display the default contents */ + StringCchCopyW(OSInfo.szName, _countof(OSInfo.szName), L"ReactOS"); + OSInfo.szCompatInfo[0] = UNICODE_NULL; + } + + return ShellAboutW(NULL, OSInfo.szName, OSInfo.szCompatInfo, NULL); } diff --git a/base/applications/winver/winver.rc b/base/applications/winver/winver.rc index 050ae69437015..1d9dec6f9d928 100644 --- a/base/applications/winver/winver.rc +++ b/base/applications/winver/winver.rc @@ -2,9 +2,18 @@ #include #include +#include "resource.h" + #define REACTOS_STR_FILE_DESCRIPTION "ReactOS Version Program" #define REACTOS_STR_INTERNAL_NAME "winver" #define REACTOS_STR_ORIGINAL_FILENAME "winver.exe" #include #include + +/* UTF-8 */ +#pragma code_page(65001) + +#ifdef LANGUAGE_EN_US + #include "lang/en-US.rc" +#endif diff --git a/base/applications/winver/winver_p.h b/base/applications/winver/winver_p.h new file mode 100644 index 0000000000000..4a2e0566d6709 --- /dev/null +++ b/base/applications/winver/winver_p.h @@ -0,0 +1,35 @@ +/* + * PROJECT: ReactOS Version Program + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Main header + * COPYRIGHT: Copyright 2025 Thamatip Chitpong + */ + +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "resource.h" + +typedef struct _WINVER_OS_INFO +{ + WCHAR szName[64]; + WCHAR szNtVersion[16]; + WCHAR szNtBuild[16]; + WCHAR szNtSpk[64]; + WCHAR szCompatInfo[256]; +} WINVER_OS_INFO, *PWINVER_OS_INFO; + +BOOL +Winver_GetOSInfo( + _Out_ PWINVER_OS_INFO OSInfo);