forked from reactos/reactos
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
205eadc
commit 5e0c6a8
Showing
8 changed files
with
416 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,11 @@ | ||
|
||
add_executable(winver winver.c winver.rc) | ||
list(APPEND SOURCE | ||
osinfo.c | ||
winver.c | ||
winver_exe.h) | ||
|
||
add_executable(winver ${SOURCE} winver.rc) | ||
set_module_type(winver win32gui UNICODE) | ||
add_importlibs(winver shell32 comctl32 msvcrt kernel32) | ||
add_importlibs(winver advapi32 shell32 comctl32 msvcrt kernel32) | ||
add_pch(winver winver_exe.h SOURCE) | ||
add_cd_file(TARGET winver DESTINATION reactos/system32 FOR all) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US | ||
|
||
STRINGTABLE | ||
BEGIN | ||
IDS_OSINFO_BUILD_FORMAT "Build: %s" | ||
IDS_OSINFO_COMPAT_FORMAT "Compatibility: Windows NT %s (Build %s%s)" | ||
IDS_OSINFO_INSTALL_FORMAT "Install location: %s" | ||
IDS_OSINFO_SPK_SEPARATOR ": " | ||
END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
LANGUAGE LANG_THAI, SUBLANG_DEFAULT | ||
|
||
STRINGTABLE | ||
BEGIN | ||
IDS_OSINFO_BUILD_FORMAT "Build: %s" | ||
IDS_OSINFO_COMPAT_FORMAT "Compatibility: Windows NT %s (Build %s%s)" | ||
IDS_OSINFO_INSTALL_FORMAT "Install location: %s" | ||
IDS_OSINFO_SPK_SEPARATOR ": " | ||
END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,321 @@ | ||
/* | ||
* PROJECT: ReactOS Version Program | ||
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) | ||
* PURPOSE: Retrieve simple OS build and compatibility information | ||
* COPYRIGHT: Copyright 2025 Thamatip Chitpong <[email protected]> | ||
*/ | ||
|
||
#include "winver_exe.h" | ||
|
||
#define WINVER_OSINFO_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion" | ||
|
||
static | ||
LPWSTR | ||
Winver_GetRegValueString( | ||
_In_ HKEY hKey, | ||
_In_ LPCWSTR lpValue) | ||
{ | ||
DWORD dwType = REG_NONE; | ||
DWORD dwSize; | ||
LONG lError; | ||
LPWSTR pszValue; | ||
|
||
lError = RegQueryValueExW(hKey, lpValue, NULL, &dwType, NULL, &dwSize); | ||
if (lError != ERROR_SUCCESS || dwType != REG_SZ) | ||
return NULL; | ||
|
||
/* NOTE: Reserved space for a NULL terminator */ | ||
pszValue = HeapAlloc(GetProcessHeap(), 0, dwSize + sizeof(WCHAR)); | ||
if (!pszValue) | ||
return NULL; | ||
|
||
lError = RegQueryValueExW(hKey, lpValue, NULL, &dwType, pszValue, &dwSize); | ||
if (lError != ERROR_SUCCESS) | ||
{ | ||
HeapFree(GetProcessHeap(), 0, pszValue); | ||
return NULL; | ||
} | ||
|
||
/* Ensure the returned string is NULL terminated */ | ||
pszValue[dwSize / sizeof(WCHAR)] = UNICODE_NULL; | ||
|
||
return pszValue; | ||
} | ||
|
||
static | ||
LPWSTR | ||
Winver_FormatBuildInfo( | ||
_In_ PWINVER_OS_INFO OSInfo) | ||
{ | ||
static const WCHAR szFmtSpecs[] = L"%s"; | ||
WCHAR szFormat[64]; | ||
DWORD dwLength; | ||
LPWSTR pszInfo; | ||
|
||
/* Required info must be valid */ | ||
if (!OSInfo->pszBuild) | ||
return NULL; | ||
|
||
dwLength = LoadStringW(GetModuleHandleW(NULL), | ||
IDS_OSINFO_BUILD_FORMAT, | ||
szFormat, | ||
_countof(szFormat)); | ||
if (dwLength < CONST_STR_LEN(szFmtSpecs)) | ||
{ | ||
return NULL; | ||
} | ||
dwLength -= CONST_STR_LEN(szFmtSpecs); | ||
|
||
/* NOTE: dwLength excludes format specifiers and includes a NULL terminator */ | ||
dwLength += wcslen(OSInfo->pszBuild) + 1; | ||
pszInfo = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR)); | ||
if (pszInfo) | ||
{ | ||
StringCchPrintfW(pszInfo, dwLength, szFormat, OSInfo->pszBuild); | ||
} | ||
|
||
return pszInfo; | ||
} | ||
|
||
static | ||
LPWSTR | ||
Winver_FormatCompatSpkInfo( | ||
_In_ PWINVER_OS_INFO OSInfo) | ||
{ | ||
WCHAR szSpkSep[4]; | ||
DWORD dwLength; | ||
LPWSTR pszInfo; | ||
|
||
/* Required info must be valid */ | ||
if (!OSInfo->pszCompatSpk) | ||
return NULL; | ||
|
||
dwLength = LoadStringW(GetModuleHandleW(NULL), | ||
IDS_OSINFO_SPK_SEPARATOR, | ||
szSpkSep, | ||
_countof(szSpkSep)); | ||
if (dwLength == 0) | ||
return NULL; | ||
|
||
/* NOTE: dwLength includes a NULL terminator */ | ||
dwLength += wcslen(OSInfo->pszCompatSpk) + 1; | ||
pszInfo = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR)); | ||
if (pszInfo) | ||
{ | ||
StringCchPrintfW(pszInfo, dwLength, L"%s%s", szSpkSep, OSInfo->pszCompatSpk); | ||
} | ||
|
||
return pszInfo; | ||
} | ||
|
||
static | ||
LPWSTR | ||
Winver_FormatCompatInfo( | ||
_In_ PWINVER_OS_INFO OSInfo) | ||
{ | ||
static const WCHAR szFmtSpecs[] = L"%s%s%s"; | ||
WCHAR szFormat[64]; | ||
DWORD dwLength; | ||
LPWSTR pszSpk; | ||
LPWSTR pszInfo; | ||
|
||
/* Required info must be valid */ | ||
if (!OSInfo->pszCompatVer || !OSInfo->pszCompatBuild) | ||
return NULL; | ||
|
||
dwLength = LoadStringW(GetModuleHandleW(NULL), | ||
IDS_OSINFO_COMPAT_FORMAT, | ||
szFormat, | ||
_countof(szFormat)); | ||
if (dwLength < CONST_STR_LEN(szFmtSpecs)) | ||
{ | ||
return NULL; | ||
} | ||
dwLength -= CONST_STR_LEN(szFmtSpecs); | ||
|
||
/* Service pack info is optional */ | ||
pszSpk = Winver_FormatCompatSpkInfo(OSInfo); | ||
if (pszSpk) | ||
{ | ||
dwLength += wcslen(pszSpk); | ||
} | ||
|
||
/* NOTE: dwLength excludes format specifiers and includes a NULL terminator */ | ||
dwLength += wcslen(OSInfo->pszCompatVer) + wcslen(OSInfo->pszCompatBuild) + 1; | ||
pszInfo = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR)); | ||
if (pszInfo) | ||
{ | ||
StringCchPrintfW(pszInfo, dwLength, szFormat, | ||
OSInfo->pszCompatVer, | ||
OSInfo->pszCompatBuild, | ||
pszSpk ? pszSpk : L""); | ||
} | ||
|
||
HeapFree(GetProcessHeap(), 0, pszSpk); | ||
return pszInfo; | ||
} | ||
|
||
static | ||
LPWSTR | ||
Winver_FormatInstallInfo( | ||
_In_ PWINVER_OS_INFO OSInfo) | ||
{ | ||
static const WCHAR szFmtSpecs[] = L"%s"; | ||
WCHAR szFormat[64]; | ||
DWORD dwLength; | ||
LPWSTR pszInfo; | ||
|
||
/* Required info must be valid */ | ||
if (!OSInfo->pszSystemRoot) | ||
return NULL; | ||
|
||
dwLength = LoadStringW(GetModuleHandleW(NULL), | ||
IDS_OSINFO_INSTALL_FORMAT, | ||
szFormat, | ||
_countof(szFormat)); | ||
if (dwLength < CONST_STR_LEN(szFmtSpecs)) | ||
{ | ||
return NULL; | ||
} | ||
dwLength -= CONST_STR_LEN(szFmtSpecs); | ||
|
||
/* NOTE: dwLength excludes format specifiers and includes a NULL terminator */ | ||
dwLength += wcslen(OSInfo->pszSystemRoot) + 1; | ||
pszInfo = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR)); | ||
if (pszInfo) | ||
{ | ||
StringCchPrintfW(pszInfo, dwLength, szFormat, OSInfo->pszSystemRoot); | ||
} | ||
|
||
return pszInfo; | ||
} | ||
|
||
static | ||
VOID | ||
Winver_FormatOSInfo( | ||
_Inout_ PWINVER_OS_INFO OSInfo) | ||
{ | ||
static const WCHAR szFormat[] = L"%s\n%s\n%s"; | ||
static const WCHAR szFmtSpecs[] = L"%s%s%s"; | ||
LPWSTR pszBuildInfo; | ||
LPWSTR pszCompatInfo = NULL; | ||
LPWSTR pszInstallInfo = NULL; | ||
LPWSTR pszInfo = NULL; | ||
DWORD dwLength; | ||
|
||
dwLength = CONST_STR_LEN(szFormat) - CONST_STR_LEN(szFmtSpecs); | ||
|
||
/* OS build info (line 1) */ | ||
pszBuildInfo = Winver_FormatBuildInfo(OSInfo); | ||
if (!pszBuildInfo) | ||
{ | ||
return; | ||
} | ||
dwLength += wcslen(pszBuildInfo); | ||
|
||
/* OS compatibility info (line 2) */ | ||
pszCompatInfo = Winver_FormatCompatInfo(OSInfo); | ||
if (!pszCompatInfo) | ||
{ | ||
goto Cleanup; | ||
} | ||
dwLength += wcslen(pszCompatInfo); | ||
|
||
/* OS installation info (line 3) */ | ||
pszInstallInfo = Winver_FormatInstallInfo(OSInfo); | ||
if (!pszInstallInfo) | ||
{ | ||
goto Cleanup; | ||
} | ||
dwLength += wcslen(pszInstallInfo); | ||
|
||
/* NOTE: dwLength excludes format specifiers and includes a NULL terminator */ | ||
dwLength += 1; | ||
pszInfo = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR)); | ||
if (pszInfo) | ||
{ | ||
StringCchPrintfW(pszInfo, dwLength, szFormat, | ||
pszBuildInfo, | ||
pszCompatInfo, | ||
pszInstallInfo); | ||
|
||
OSInfo->pszFormatted = pszInfo; | ||
} | ||
|
||
Cleanup: | ||
HeapFree(GetProcessHeap(), 0, pszInstallInfo); | ||
HeapFree(GetProcessHeap(), 0, pszCompatInfo); | ||
HeapFree(GetProcessHeap(), 0, pszBuildInfo); | ||
} | ||
|
||
PWINVER_OS_INFO | ||
Winver_GetOSInfo(VOID) | ||
{ | ||
HKEY hKey; | ||
LONG lError; | ||
PWINVER_OS_INFO OSInfo; | ||
|
||
OSInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*OSInfo)); | ||
if (!OSInfo) | ||
return NULL; | ||
|
||
lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, | ||
WINVER_OSINFO_KEY, | ||
0, | ||
KEY_QUERY_VALUE, | ||
&hKey); | ||
if (lError != ERROR_SUCCESS) | ||
{ | ||
HeapFree(GetProcessHeap(), 0, OSInfo); | ||
return NULL; | ||
} | ||
|
||
/* OS name */ | ||
OSInfo->pszProductName = Winver_GetRegValueString(hKey, L"ProductName"); | ||
if (!OSInfo->pszProductName) | ||
{ | ||
/* ShellAboutW: This info must be valid */ | ||
RegCloseKey(hKey); | ||
HeapFree(GetProcessHeap(), 0, OSInfo); | ||
return NULL; | ||
} | ||
|
||
/* OS build number */ | ||
OSInfo->pszBuild = Winver_GetRegValueString(hKey, L"BuildLab"); | ||
|
||
/* Compatible NT version */ | ||
OSInfo->pszCompatVer = Winver_GetRegValueString(hKey, L"CurrentVersion"); | ||
|
||
/* Compatible NT build number */ | ||
OSInfo->pszCompatBuild = Winver_GetRegValueString(hKey, L"CurrentBuildNumber"); | ||
|
||
/* Compatible NT service pack (optional) */ | ||
OSInfo->pszCompatSpk = Winver_GetRegValueString(hKey, L"CSDVersion"); | ||
|
||
/* OS install directory */ | ||
OSInfo->pszSystemRoot = Winver_GetRegValueString(hKey, L"SystemRoot"); | ||
|
||
RegCloseKey(hKey); | ||
|
||
Winver_FormatOSInfo(OSInfo); | ||
|
||
return OSInfo; | ||
} | ||
|
||
VOID | ||
Winver_FreeOSInfo( | ||
_In_ PWINVER_OS_INFO OSInfo) | ||
{ | ||
if (OSInfo) | ||
{ | ||
HeapFree(GetProcessHeap(), 0, OSInfo->pszFormatted); | ||
HeapFree(GetProcessHeap(), 0, OSInfo->pszSystemRoot); | ||
HeapFree(GetProcessHeap(), 0, OSInfo->pszCompatSpk); | ||
HeapFree(GetProcessHeap(), 0, OSInfo->pszCompatBuild); | ||
HeapFree(GetProcessHeap(), 0, OSInfo->pszCompatVer); | ||
HeapFree(GetProcessHeap(), 0, OSInfo->pszBuild); | ||
HeapFree(GetProcessHeap(), 0, OSInfo->pszProductName); | ||
|
||
HeapFree(GetProcessHeap(), 0, OSInfo); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#pragma once | ||
|
||
#define IDS_OSINFO_BUILD_FORMAT 1 | ||
#define IDS_OSINFO_COMPAT_FORMAT 2 | ||
#define IDS_OSINFO_INSTALL_FORMAT 3 | ||
#define IDS_OSINFO_SPK_SEPARATOR 4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.