Skip to content

Commit fb173b8

Browse files
rekireCommit Queue
authored and
Commit Queue
committed
Detect Windows edition via WMI
Closes #57010 GitOrigin-RevId: 5637541 Change-Id: I9344426b143aa1677a950bf3ebec3eee214f3ccf Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/393002 Reviewed-by: Slava Egorov <[email protected]> Commit-Queue: Slava Egorov <[email protected]>
1 parent 8a20458 commit fb173b8

File tree

1 file changed

+101
-3
lines changed

1 file changed

+101
-3
lines changed

runtime/bin/platform_win.cc

Lines changed: 101 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@
77

88
#include "bin/platform.h"
99

10+
#include <comdef.h>
1011
#include <crtdbg.h>
12+
#include <wbemidl.h>
13+
#include <wrl/client.h>
14+
#undef interface
15+
#include <string>
1116

1217
#include "bin/console.h"
1318
#include "bin/file.h"
@@ -20,6 +25,10 @@
2025
#include "bin/utils.h"
2126
#include "bin/utils_win.h"
2227

28+
#pragma comment(lib, "wbemuuid.lib")
29+
30+
using Microsoft::WRL::ComPtr;
31+
2332
namespace dart {
2433
namespace bin {
2534

@@ -110,6 +119,18 @@ class PlatformWin {
110119
DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformWin);
111120
};
112121

122+
class CoInitializeScope : public ValueObject {
123+
public:
124+
CoInitializeScope() { hres = CoInitializeEx(0, COINIT_MULTITHREADED); }
125+
126+
~CoInitializeScope() { CoUninitialize(); }
127+
128+
bool IsInitialized() const { return !FAILED(hres); }
129+
130+
private:
131+
HRESULT hres;
132+
};
133+
113134
bool Platform::Initialize() {
114135
PlatformWin::InitOnce();
115136
return true;
@@ -166,10 +187,87 @@ static const char* VersionNumber() {
166187
return DartUtils::ScopedCStringFormatted("%d.%d", major, minor);
167188
}
168189

190+
static const char* GetEdition() {
191+
HRESULT hres;
192+
193+
CoInitializeScope co_initialize_scope;
194+
if (!co_initialize_scope.IsInitialized()) {
195+
return nullptr;
196+
}
197+
198+
hres = CoInitializeSecurity(
199+
nullptr, -1, nullptr, nullptr, RPC_C_AUTHN_LEVEL_DEFAULT,
200+
RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE, nullptr);
201+
if (FAILED(hres)) {
202+
return nullptr;
203+
}
204+
205+
ComPtr<IWbemLocator> locator;
206+
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
207+
IID_PPV_ARGS(&locator));
208+
if (FAILED(hres)) {
209+
return nullptr;
210+
}
211+
212+
ComPtr<IWbemServices> service;
213+
hres = locator->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), nullptr, nullptr, 0,
214+
NULL, 0, 0, &service);
215+
if (FAILED(hres)) {
216+
return nullptr;
217+
}
218+
219+
hres = CoSetProxyBlanket(service.Get(), RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE,
220+
nullptr, RPC_C_AUTHN_LEVEL_CALL,
221+
RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE);
222+
if (FAILED(hres)) {
223+
return nullptr;
224+
}
225+
226+
ComPtr<IEnumWbemClassObject> enumerator;
227+
hres = service->ExecQuery(
228+
bstr_t("WQL"), bstr_t("SELECT * FROM Win32_OperatingSystem"),
229+
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, nullptr,
230+
&enumerator);
231+
if (FAILED(hres)) {
232+
return nullptr;
233+
}
234+
235+
ComPtr<IWbemClassObject> query_results;
236+
ULONG uReturn = 0;
237+
if (FAILED(hres) || enumerator == nullptr) {
238+
return nullptr;
239+
}
240+
241+
hres = enumerator->Next(WBEM_INFINITE, 1, &query_results, &uReturn);
242+
if (FAILED(hres)) {
243+
return nullptr;
244+
}
245+
246+
VARIANT caption;
247+
hres = query_results->Get(L"Caption", 0, &caption, 0, 0);
248+
if (FAILED(hres)) {
249+
return nullptr;
250+
}
251+
252+
// We got an edition, skip Microsoft prefix and convert to UTF8.
253+
wchar_t* edition = caption.bstrVal;
254+
static const wchar_t kMicrosoftPrefix[] = L"Microsoft ";
255+
static constexpr size_t kMicrosoftPrefixLen =
256+
ARRAY_SIZE(kMicrosoftPrefix) - 1;
257+
if (wcsncmp(edition, kMicrosoftPrefix, kMicrosoftPrefixLen) == 0) {
258+
edition += kMicrosoftPrefixLen;
259+
}
260+
261+
char* result = StringUtilsWin::WideToUtf8(edition);
262+
VariantClear(&caption);
263+
return result;
264+
}
265+
169266
const char* Platform::OperatingSystemVersion() {
170-
// Get the product name, e.g. "Windows 10 Home".
171-
const char* name;
172-
if (!GetCurrentVersionString(L"ProductName", &name)) {
267+
// Get the product name, e.g. "Windows 11 Home" via WMI and fallback to the
268+
// ProductName on error.
269+
const char* name = GetEdition();
270+
if (name == nullptr && !GetCurrentVersionString(L"ProductName", &name)) {
173271
return nullptr;
174272
}
175273

0 commit comments

Comments
 (0)