1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
#include "os.h"
#include "common/strutil.h"
#include "common/windows/registry.h"
#include "common/windows/unicode.h"
#include <windows.h>
PWSTR WINAPI BrandingFormatString(PCWSTR format);
static bool getCodeName(FFOSResult* os) {
FF_AUTO_CLOSE_FD HANDLE hKey = NULL;
if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", &hKey, NULL)) {
return false;
}
if (!ffRegReadStrbuf(hKey, L"DisplayVersion", &os->codename, NULL)) {
if (!ffRegReadStrbuf(hKey, L"CSDVersion", &os->codename, NULL)) { // For Windows 7 and Windows 8
if (!ffRegReadStrbuf(hKey, L"ReleaseId", &os->codename, NULL)) { // For old Windows 10
return false;
}
}
}
return true;
}
void ffDetectOSImpl(FFOSResult* os) {
// https://dennisbabkin.com/blog/?t=how-to-tell-the-real-version-of-windows-your-app-is-running-on#ver_string
const wchar_t* rawName = BrandingFormatString(L"%WINDOWS_LONG%");
ffStrbufSetWS(&os->variant, rawName);
GlobalFree((HGLOBAL) rawName);
ffStrbufSet(&os->prettyName, &os->variant);
ffStrbufTrimRight(&os->variant, ' ');
// WMI returns the "Microsoft" prefix while BrandingFormatString doesn't. Make them consistent.
if (ffStrbufStartsWithS(&os->variant, "Microsoft ")) {
ffStrbufSubstrAfter(&os->variant, strlen("Microsoft ") - 1);
}
if (os->variant.length == 0) // Windows PE?
{
FF_AUTO_CLOSE_FD HANDLE hKey = NULL;
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", &hKey, NULL)) {
ffRegReadStrbuf(hKey, L"ProductName", &os->variant, NULL);
}
}
ffStrbufSet(&os->prettyName, &os->variant);
if (ffStrbufStartsWithS(&os->variant, "Windows ")) {
ffStrbufAppendS(&os->name, "Windows");
ffStrbufSubstrAfter(&os->variant, strlen("Windows ") - 1);
if (ffStrbufStartsWithS(&os->variant, "Server ")) {
ffStrbufAppendS(&os->name, " Server");
ffStrbufSubstrAfter(&os->variant, strlen(" Server") - 1);
} else if (ffStrbufStartsWithS(&os->variant, "Embedded ")) {
ffStrbufAppendS(&os->name, " Embedded");
ffStrbufSubstrAfter(&os->variant, strlen(" Embedded") - 1);
}
if (ffStrbufStartsWithIgnCaseS(&os->variant, "(TM) ")) {
ffStrbufSubstrAfter(&os->variant, strlen(" (TM)") - 1);
}
uint32_t index = ffStrbufFirstIndexC(&os->variant, ' ');
ffStrbufAppendNS(&os->version, index, os->variant.chars);
ffStrbufSubstrAfter(&os->variant, index);
// Windows Server 20xx Rx
if (ffStrbufEndsWithC(&os->name, 'r')) {
if (os->variant.chars[0] == 'R' &&
ffCharIsDigit(os->variant.chars[1]) &&
(os->variant.chars[2] == '\0' || os->variant.chars[2] == ' ')) {
ffStrbufAppendF(&os->version, " R%c", os->variant.chars[1]);
ffStrbufSubstrAfter(&os->variant, strlen("Rx ") - 1);
}
}
} else {
// Unknown Windows name, please report this
ffStrbufAppend(&os->name, &os->variant);
ffStrbufClear(&os->variant);
}
ffStrbufAppendF(&os->id, "%s %s", os->name.chars, os->version.chars);
ffStrbufSetStatic(&os->idLike, "Windows");
if (getCodeName(os) && os->codename.length > 0) {
ffStrbufAppendF(&os->prettyName, " (%s)", os->codename.chars);
}
}
|