diff --git a/base/applications/winver/CMakeLists.txt b/base/applications/winver/CMakeLists.txt index ac5b762b83d..9837665d4e5 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) +add_pch(winver winver_p.h SOURCE) set_module_type(winver win32gui UNICODE) -add_importlibs(winver shell32 comctl32 msvcrt kernel32) +add_importlibs(winver advapi32 user32 shell32 comctl32 msvcrt kernel32) 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 00000000000..d4ec8dd84d9 --- /dev/null +++ b/base/applications/winver/lang/en-US.rc @@ -0,0 +1,14 @@ +/* + * PROJECT: ReactOS Version Program + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: English (United States) resource file + * TRANSLATOR: Copyright 2025 Thamatip Chitpong + */ + +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 00000000000..ff79baa3aab --- /dev/null +++ b/base/applications/winver/osinfo.c @@ -0,0 +1,126 @@ +/* + * PROJECT: ReactOS Version Program + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * 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 pValue, + _Out_ LPWSTR pBuffer, + _In_ DWORD cchSize) +{ + DWORD dwType, dwSize; + LSTATUS lError; + + /* NOTE: Reserved space for a NULL terminator */ + dwSize = (cchSize - 1) * sizeof(WCHAR); + lError = RegQueryValueExW(hKey, pValue, NULL, &dwType, (LPBYTE)pBuffer, &dwSize); + if (lError != ERROR_SUCCESS || dwType != REG_SZ) + { + /* Return empty string on failure */ + pBuffer[0] = UNICODE_NULL; + return; + } + + /* Ensure the returned string is NULL terminated */ + pBuffer[cchSize - 1] = UNICODE_NULL; +} + +static +VOID +Winver_GetFormattedSpkInfo( + _In_ HKEY hKey, + _Out_ LPWSTR pBuffer, + _In_ DWORD cchSize) +{ + WCHAR szRegValue[48]; + WCHAR szFormat[16] = L""; + + Winver_GetRegValueString(hKey, L"CSDVersion", szRegValue, _countof(szRegValue)); + if (!szRegValue[0]) + { + /* Return empty string on failure */ + pBuffer[0] = UNICODE_NULL; + return; + } + + LoadStringW(Winver_hInstance, + IDS_OSINFO_SPK_FORMAT, + szFormat, + _countof(szFormat)); + + StringCchPrintfW(pBuffer, cchSize, szFormat, szRegValue); +} + +static +VOID +Winver_FormatCompatInfo( + _In_ HKEY hKey, + _Out_ LPWSTR pBuffer, + _In_ DWORD cchSize) +{ + WCHAR szNtVersion[16]; + WCHAR szNtBuild[16]; + WCHAR szNtSpk[64]; + WCHAR szFormat[64] = L""; + + /* NOTE: Required info must be valid */ + Winver_GetRegValueString(hKey, L"CurrentVersion", szNtVersion, _countof(szNtVersion)); + Winver_GetRegValueString(hKey, L"CurrentBuildNumber", szNtBuild, _countof(szNtBuild)); + if (!szNtVersion[0] || !szNtBuild[0]) + { + /* Return empty string on failure */ + pBuffer[0] = UNICODE_NULL; + return; + } + + /* NOTE: Service pack info is optional */ + Winver_GetFormattedSpkInfo(hKey, szNtSpk, _countof(szNtSpk)); + + LoadStringW(Winver_hInstance, + IDS_OSINFO_COMPAT_FORMAT, + szFormat, + _countof(szFormat)); + + StringCchPrintfW(pBuffer, cchSize, szFormat, szNtVersion, szNtBuild, 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[0]) + { + /* This info must be valid */ + RegCloseKey(hKey); + return FALSE; + } + + /* Compatibility information */ + Winver_FormatCompatInfo(hKey, OSInfo->szCompatInfo, _countof(OSInfo->szCompatInfo)); + + RegCloseKey(hKey); + + return TRUE; +} diff --git a/base/applications/winver/resource.h b/base/applications/winver/resource.h new file mode 100644 index 00000000000..ca00ee82314 --- /dev/null +++ b/base/applications/winver/resource.h @@ -0,0 +1,11 @@ +/* + * PROJECT: ReactOS Version Program + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Resource header file + * COPYRIGHT: Copyright 2025 Thamatip Chitpong + */ + +#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 1e22096c4ee..3eb2a9e3adf 100644 --- a/base/applications/winver/winver.c +++ b/base/applications/winver/winver.c @@ -4,26 +4,32 @@ * FILE: base/applications/winver/winver.c */ -#include -#include -#include -#include -#include -#include +#include "winver_p.h" + +HINSTANCE Winver_hInstance; int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) { INITCOMMONCONTROLSEX iccx; + WINVER_OS_INFO OSInfo; - UNREFERENCED_PARAMETER(hInstance); UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); UNREFERENCED_PARAMETER(nCmdShow); + Winver_hInstance = hInstance; + /* Initialize common controls */ - iccx.dwSize = sizeof(INITCOMMONCONTROLSEX); + iccx.dwSize = sizeof(iccx); 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 050ae694370..1d9dec6f9d9 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 00000000000..b7b76ed5db9 --- /dev/null +++ b/base/applications/winver/winver_p.h @@ -0,0 +1,34 @@ +/* + * PROJECT: ReactOS Version Program + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Main header file + * 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 szCompatInfo[256]; +} WINVER_OS_INFO, *PWINVER_OS_INFO; + +extern HINSTANCE Winver_hInstance; + +BOOL +Winver_GetOSInfo( + _Out_ PWINVER_OS_INFO OSInfo);