From 2666e43fff70836566cee38b1c09efd62c45ab2c Mon Sep 17 00:00:00 2001 From: rekire Date: Fri, 1 Nov 2024 08:57:13 +0100 Subject: [PATCH 1/6] Detect Windows edition via WMI --- runtime/bin/platform_win.cc | 109 +++++++++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 3 deletions(-) diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc index afffde5289ee..edc8f8261024 100644 --- a/runtime/bin/platform_win.cc +++ b/runtime/bin/platform_win.cc @@ -19,6 +19,11 @@ #include "bin/thread.h" #include "bin/utils.h" #include "bin/utils_win.h" +#include +#include +#include + +#pragma comment(lib, "wbemuuid.lib") namespace dart { namespace bin { @@ -166,10 +171,108 @@ static const char* VersionNumber() { return DartUtils::ScopedCStringFormatted("%d.%d", major, minor); } +const char* getEdition() { + HRESULT hres; + + hres = CoInitializeEx(0, COINIT_MULTITHREADED); + if (FAILED(hres)) { + return nullptr; + } + + hres = CoInitializeSecurity( + nullptr, -1, nullptr, nullptr, RPC_C_AUTHN_LEVEL_DEFAULT, + RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE, nullptr); + if (FAILED(hres)) { + CoUninitialize(); + return nullptr; + } + + IWbemLocator* pLoc = nullptr; + hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, + IID_IWbemLocator, (LPVOID*)&pLoc); + if (FAILED(hres)) { + CoUninitialize(); + return nullptr; + } + + IWbemServices* pSvc = nullptr; + hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), nullptr, nullptr, 0, NULL, + 0, 0, &pSvc); + if (FAILED(hres)) { + pLoc->Release(); + CoUninitialize(); + return nullptr; + } + + hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr, + RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, + nullptr, EOAC_NONE); + if (FAILED(hres)) { + pSvc->Release(); + pLoc->Release(); + CoUninitialize(); + return nullptr; + } + + IEnumWbemClassObject* pEnumerator = nullptr; + hres = pSvc->ExecQuery(bstr_t("WQL"), + bstr_t("SELECT * FROM Win32_OperatingSystem"), + WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, + nullptr, &pEnumerator); + if (FAILED(hres)) { + pSvc->Release(); + pLoc->Release(); + CoUninitialize(); + return nullptr; + } + + IWbemClassObject* pclsObj = nullptr; + ULONG uReturn = 0; + std::wstring edition; + while (pEnumerator) { + hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); + if (0 == uReturn) { + break; + } + + VARIANT vtProp; + hres = pclsObj->Get(L"Caption", 0, &vtProp, 0, 0); + if (SUCCEEDED(hres)) { + std::wstring editionString(vtProp.bstrVal, SysStringLen(vtProp.bstrVal)); + + size_t pos = editionString.find(L"Microsoft "); + if (pos == 0) { + editionString.erase(0, wcslen(L"Microsoft ")); + } + edition = editionString.c_str(); + + VariantClear(&vtProp); + } + + pclsObj->Release(); + } + + pEnumerator->Release(); + pSvc->Release(); + pLoc->Release(); + CoUninitialize(); + + static std::string editionString; + int len = WideCharToMultiByte(CP_UTF8, 0, edition.c_str(), -1, nullptr, 0, + nullptr, nullptr); + if (len > 0) { + editionString.resize(len); + WideCharToMultiByte(CP_UTF8, 0, edition.c_str(), -1, &editionString[0], len, + nullptr, nullptr); + } + + return editionString.c_str(); +} + const char* Platform::OperatingSystemVersion() { - // Get the product name, e.g. "Windows 10 Home". - const char* name; - if (!GetCurrentVersionString(L"ProductName", &name)) { + // Get the product name, e.g. "Windows 11 Home" via WMI and fallback to the ProductName on error. + const char* name = getEdition(); + if (name == nullptr && !GetCurrentVersionString(L"ProductName", &name)) { return nullptr; } From 858eac1063e60f9cb50a69d970de1668da90a4ed Mon Sep 17 00:00:00 2001 From: rekire Date: Fri, 1 Nov 2024 11:26:08 +0100 Subject: [PATCH 2/6] Fix formatting --- runtime/bin/platform_win.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc index edc8f8261024..41180d0cb644 100644 --- a/runtime/bin/platform_win.cc +++ b/runtime/bin/platform_win.cc @@ -7,7 +7,10 @@ #include "bin/platform.h" +#include +#include #include +#include #include "bin/console.h" #include "bin/file.h" @@ -19,9 +22,6 @@ #include "bin/thread.h" #include "bin/utils.h" #include "bin/utils_win.h" -#include -#include -#include #pragma comment(lib, "wbemuuid.lib") @@ -189,7 +189,7 @@ const char* getEdition() { IWbemLocator* pLoc = nullptr; hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, - IID_IWbemLocator, (LPVOID*)&pLoc); + IID_IWbemLocator, reinterpret_cast(&pLoc)); if (FAILED(hres)) { CoUninitialize(); return nullptr; @@ -270,7 +270,8 @@ const char* getEdition() { } const char* Platform::OperatingSystemVersion() { - // Get the product name, e.g. "Windows 11 Home" via WMI and fallback to the ProductName on error. + // Get the product name, e.g. "Windows 11 Home" via WMI and fallback to the + // ProductName on error. const char* name = getEdition(); if (name == nullptr && !GetCurrentVersionString(L"ProductName", &name)) { return nullptr; From dad18dc7b945c0a85d3ffc2fb28c6e73a777c27b Mon Sep 17 00:00:00 2001 From: rekire Date: Fri, 1 Nov 2024 13:36:57 +0100 Subject: [PATCH 3/6] Apply suggestions to simplify the code --- runtime/bin/platform_win.cc | 92 ++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 53 deletions(-) diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc index 41180d0cb644..1b34aa82cf05 100644 --- a/runtime/bin/platform_win.cc +++ b/runtime/bin/platform_win.cc @@ -10,6 +10,8 @@ #include #include #include +#include +#undef interface #include #include "bin/console.h" @@ -25,6 +27,8 @@ #pragma comment(lib, "wbemuuid.lib") +using Microsoft::WRL::ComPtr; + namespace dart { namespace bin { @@ -171,7 +175,7 @@ static const char* VersionNumber() { return DartUtils::ScopedCStringFormatted("%d.%d", major, minor); } -const char* getEdition() { +static const char* GetEdition() { HRESULT hres; hres = CoInitializeEx(0, COINIT_MULTITHREADED); @@ -187,92 +191,74 @@ const char* getEdition() { return nullptr; } - IWbemLocator* pLoc = nullptr; + ComPtr locator; hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, - IID_IWbemLocator, reinterpret_cast(&pLoc)); + IID_PPV_ARGS(&locator)); if (FAILED(hres)) { CoUninitialize(); return nullptr; } - IWbemServices* pSvc = nullptr; - hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), nullptr, nullptr, 0, NULL, - 0, 0, &pSvc); + ComPtr service; + hres = locator->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), nullptr, nullptr, 0, + NULL, 0, 0, &service); if (FAILED(hres)) { - pLoc->Release(); CoUninitialize(); return nullptr; } - hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr, - RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, - nullptr, EOAC_NONE); + hres = CoSetProxyBlanket(service.Get(), RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, + nullptr, RPC_C_AUTHN_LEVEL_CALL, + RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE); if (FAILED(hres)) { - pSvc->Release(); - pLoc->Release(); CoUninitialize(); return nullptr; } - IEnumWbemClassObject* pEnumerator = nullptr; - hres = pSvc->ExecQuery(bstr_t("WQL"), - bstr_t("SELECT * FROM Win32_OperatingSystem"), - WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, - nullptr, &pEnumerator); + ComPtr enumerator; + hres = service->ExecQuery(bstr_t("WQL"), + bstr_t("SELECT * FROM Win32_OperatingSystem"), + WBEM_FLAG_FORWARD_ONLY | + WBEM_FLAG_RETURN_IMMEDIATELY, nullptr, + &enumerator); if (FAILED(hres)) { - pSvc->Release(); - pLoc->Release(); CoUninitialize(); return nullptr; } - IWbemClassObject* pclsObj = nullptr; + ComPtr query_results; ULONG uReturn = 0; - std::wstring edition; - while (pEnumerator) { - hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); - if (0 == uReturn) { - break; - } - - VARIANT vtProp; - hres = pclsObj->Get(L"Caption", 0, &vtProp, 0, 0); - if (SUCCEEDED(hres)) { - std::wstring editionString(vtProp.bstrVal, SysStringLen(vtProp.bstrVal)); - - size_t pos = editionString.find(L"Microsoft "); - if (pos == 0) { - editionString.erase(0, wcslen(L"Microsoft ")); - } - edition = editionString.c_str(); + if (FAILED(hres) || enumerator == nullptr) { + return nullptr; + } - VariantClear(&vtProp); + hres = enumerator->Next(WBEM_INFINITE, 1, &query_results, &uReturn); + + VARIANT caption; + hres = query_results->Get(L"Caption", 0, &caption, 0, 0); + char* utf8_edition = nullptr; + if (SUCCEEDED(hres)) { + // We got an edition, skip Microsoft prefix and convert to UTF8. + wchar_t* edition = caption.bstrVal; + static const wchar_t* kMicrosoftPrefix = L"Microsoft "; + static size_t kMicrosoftPrefixLen = wcslen(kMicrosoftPrefix); + if (wcsncmp(edition, kMicrosoftPrefix, kMicrosoftPrefixLen) == 0) { + edition += kMicrosoftPrefixLen; } + utf8_edition = StringUtilsWin::WideToUtf8(edition); - pclsObj->Release(); + VariantClear(&caption); } - pEnumerator->Release(); - pSvc->Release(); - pLoc->Release(); CoUninitialize(); - static std::string editionString; - int len = WideCharToMultiByte(CP_UTF8, 0, edition.c_str(), -1, nullptr, 0, - nullptr, nullptr); - if (len > 0) { - editionString.resize(len); - WideCharToMultiByte(CP_UTF8, 0, edition.c_str(), -1, &editionString[0], len, - nullptr, nullptr); - } - - return editionString.c_str(); + return utf8_edition; } const char* Platform::OperatingSystemVersion() { // Get the product name, e.g. "Windows 11 Home" via WMI and fallback to the // ProductName on error. - const char* name = getEdition(); + const char* name = GetEdition(); if (name == nullptr && !GetCurrentVersionString(L"ProductName", &name)) { return nullptr; } From 6acaf3b4264598422958db1d2d75e5563034fb0f Mon Sep 17 00:00:00 2001 From: rekire Date: Fri, 1 Nov 2024 16:36:42 +0100 Subject: [PATCH 4/6] Use CoInitializeScope to call CoUninitialize() when required --- runtime/bin/platform_win.cc | 48 +++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc index 1b34aa82cf05..4bca6492f7cc 100644 --- a/runtime/bin/platform_win.cc +++ b/runtime/bin/platform_win.cc @@ -119,6 +119,18 @@ class PlatformWin { DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformWin); }; +class CoInitializeScope : public ValueObject { + public: + CoInitializeScope() { hres = CoInitializeEx(0, COINIT_MULTITHREADED); } + + ~CoInitializeScope() { CoUninitialize(); } + + bool IsInitialized() const { return !FAILED(hres); } + + private: + HRESULT hres; +}; + bool Platform::Initialize() { PlatformWin::InitOnce(); return true; @@ -178,8 +190,8 @@ static const char* VersionNumber() { static const char* GetEdition() { HRESULT hres; - hres = CoInitializeEx(0, COINIT_MULTITHREADED); - if (FAILED(hres)) { + CoInitializeScope co_initialize_scope; + if (!co_initialize_scope.IsInitialized()) { return nullptr; } @@ -187,7 +199,6 @@ static const char* GetEdition() { nullptr, -1, nullptr, nullptr, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE, nullptr); if (FAILED(hres)) { - CoUninitialize(); return nullptr; } @@ -195,7 +206,6 @@ static const char* GetEdition() { hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&locator)); if (FAILED(hres)) { - CoUninitialize(); return nullptr; } @@ -203,7 +213,6 @@ static const char* GetEdition() { hres = locator->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), nullptr, nullptr, 0, NULL, 0, 0, &service); if (FAILED(hres)) { - CoUninitialize(); return nullptr; } @@ -211,18 +220,15 @@ static const char* GetEdition() { nullptr, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE); if (FAILED(hres)) { - CoUninitialize(); return nullptr; } ComPtr enumerator; - hres = service->ExecQuery(bstr_t("WQL"), - bstr_t("SELECT * FROM Win32_OperatingSystem"), - WBEM_FLAG_FORWARD_ONLY | - WBEM_FLAG_RETURN_IMMEDIATELY, nullptr, - &enumerator); + hres = service->ExecQuery( + bstr_t("WQL"), bstr_t("SELECT * FROM Win32_OperatingSystem"), + WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, nullptr, + &enumerator); if (FAILED(hres)) { - CoUninitialize(); return nullptr; } @@ -233,26 +239,28 @@ static const char* GetEdition() { } hres = enumerator->Next(WBEM_INFINITE, 1, &query_results, &uReturn); + if (FAILED(hres)) { + return nullptr; + } VARIANT caption; hres = query_results->Get(L"Caption", 0, &caption, 0, 0); - char* utf8_edition = nullptr; + wchar_t* edition; + if (SUCCEEDED(hres)) { // We got an edition, skip Microsoft prefix and convert to UTF8. - wchar_t* edition = caption.bstrVal; - static const wchar_t* kMicrosoftPrefix = L"Microsoft "; - static size_t kMicrosoftPrefixLen = wcslen(kMicrosoftPrefix); + edition = caption.bstrVal; + static const wchar_t kMicrosoftPrefix[] = L"Microsoft "; + static constexpr size_t kMicrosoftPrefixLen = + ARRAY_SIZE(kMicrosoftPrefix) - 1; if (wcsncmp(edition, kMicrosoftPrefix, kMicrosoftPrefixLen) == 0) { edition += kMicrosoftPrefixLen; } - utf8_edition = StringUtilsWin::WideToUtf8(edition); VariantClear(&caption); } - CoUninitialize(); - - return utf8_edition; + return StringUtilsWin::WideToUtf8(edition); } const char* Platform::OperatingSystemVersion() { From 1056ad17268af2bfebea8966f115e4f938e75438 Mon Sep 17 00:00:00 2001 From: rekire Date: Sat, 2 Nov 2024 08:26:39 +0100 Subject: [PATCH 5/6] Fix use after free issue and removed SUCCEEDED in favor of FAILED for consistency --- runtime/bin/platform_win.cc | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc index 4bca6492f7cc..fdc44e475418 100644 --- a/runtime/bin/platform_win.cc +++ b/runtime/bin/platform_win.cc @@ -245,22 +245,22 @@ static const char* GetEdition() { VARIANT caption; hres = query_results->Get(L"Caption", 0, &caption, 0, 0); - wchar_t* edition; - - if (SUCCEEDED(hres)) { - // We got an edition, skip Microsoft prefix and convert to UTF8. - edition = caption.bstrVal; - static const wchar_t kMicrosoftPrefix[] = L"Microsoft "; - static constexpr size_t kMicrosoftPrefixLen = - ARRAY_SIZE(kMicrosoftPrefix) - 1; - if (wcsncmp(edition, kMicrosoftPrefix, kMicrosoftPrefixLen) == 0) { - edition += kMicrosoftPrefixLen; - } + if (FAILED(hres)) { + return nullptr; + } - VariantClear(&caption); + // We got an edition, skip Microsoft prefix and convert to UTF8. + wchar_t* edition = caption.bstrVal; + static const wchar_t kMicrosoftPrefix[] = L"Microsoft "; + static constexpr size_t kMicrosoftPrefixLen = + ARRAY_SIZE(kMicrosoftPrefix) - 1; + if (wcsncmp(edition, kMicrosoftPrefix, kMicrosoftPrefixLen) == 0) { + edition += kMicrosoftPrefixLen; } - return StringUtilsWin::WideToUtf8(edition); + char* result = StringUtilsWin::WideToUtf8(edition); + VariantClear(&caption); + return result; } const char* Platform::OperatingSystemVersion() { From 3cf8725e3e3e72c8415c48ea2b679235da0401de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Kilczan?= Date: Mon, 4 Nov 2024 10:44:00 +0100 Subject: [PATCH 6/6] Change to lower case of header file name for Blaze --- runtime/bin/platform_win.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc index fdc44e475418..3fb78c5af3c9 100644 --- a/runtime/bin/platform_win.cc +++ b/runtime/bin/platform_win.cc @@ -7,9 +7,9 @@ #include "bin/platform.h" -#include #include #include +#include #include #undef interface #include