From acb38fa3ee87ea4a0a53e4b5346587ef0b345af2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 6 Nov 2024 00:16:05 +0800 Subject: [PATCH] Bluetooth (Windows): detect battery (WIP) --- CMakeLists.txt | 2 + src/detection/bluetooth/bluetooth_windows.cpp | 31 ++++++++++++++ src/util/windows/wmi.cpp | 40 ++----------------- src/util/windows/wmi.hpp | 20 +++++++++- 4 files changed, 55 insertions(+), 38 deletions(-) create mode 100644 src/detection/bluetooth/bluetooth_windows.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f60c39b8..82db4936e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -915,6 +915,7 @@ elseif(WIN32) src/detection/battery/battery_windows.c src/detection/bios/bios_windows.c src/detection/bluetooth/bluetooth_windows.c + src/detection/bluetooth/bluetooth_windows.cpp src/detection/bluetoothradio/bluetoothradio_windows.c src/detection/board/board_windows.c src/detection/bootmgr/bootmgr_windows.c @@ -1428,6 +1429,7 @@ elseif(WIN32) PRIVATE "imagehlp" PRIVATE "cfgmgr32" PRIVATE "winbrand" + PRIVATE "propsys" ) elseif(FreeBSD) target_link_libraries(libfastfetch diff --git a/src/detection/bluetooth/bluetooth_windows.cpp b/src/detection/bluetooth/bluetooth_windows.cpp new file mode 100644 index 000000000..a0d38f8b2 --- /dev/null +++ b/src/detection/bluetooth/bluetooth_windows.cpp @@ -0,0 +1,31 @@ +extern "C" +{ +#include "bluetooth.h" +} +#include "util/windows/wmi.hpp" +#include "util/windows/unicode.hpp" + +#include + +STDAPI InitVariantFromStringArray(_In_reads_(cElems) PCWSTR *prgsz, _In_ ULONG cElems, _Out_ VARIANT *pvar); + +static const char* detectWithWmi(FFlist* result) +{ + FFWmiQuery query(L"SELECT __PATH FROM Win32_PnPEntity WHERE Service = 'BthHFEnum'", nullptr, FFWmiNamespace::CIMV2); + if(!query) + return "Query WMI service failed"; + + while(FFWmiRecord record = query.next()) + { + IWbemClassObject* pInParams = nullptr; + PCWSTR props[] = { L"{104EA319-6EE2-4701-BD47-8DDBF425BBE5} 2" }; + VARIANT devicePropertyKeys; + InitVariantFromStringArray(props, ARRAY_SIZE(props), &devicePropertyKeys); + record.obj->GetMethod(bstr_t(L"GetDeviceProperties"), 0, &pInParams, NULL); + pInParams->Put(L"devicePropertyKeys", 0, &devicePropertyKeys, CIM_FLAG_ARRAY | CIM_STRING); + IWbemCallResult* pResult = nullptr; + query.pService->ExecMethod(bstr_t(record.get(L"__PATH").bstrVal), bstr_t(L"GetDeviceProperties"), 0, nullptr, pInParams, nullptr, &pResult); + // TODO: parse result + } + return NULL; +} diff --git a/src/util/windows/wmi.cpp b/src/util/windows/wmi.cpp index 6e8db9615..34cfb06d6 100644 --- a/src/util/windows/wmi.cpp +++ b/src/util/windows/wmi.cpp @@ -6,21 +6,6 @@ #include #include -namespace -{ - // Provide our bstr_t to avoid libstdc++ dependency - struct bstr_t - { - explicit bstr_t(const wchar_t* str) noexcept: _bstr(SysAllocString(str)) {} - ~bstr_t(void) noexcept { SysFreeString(_bstr); } - explicit operator const wchar_t*(void) const noexcept { return _bstr; } - operator BSTR(void) const noexcept { return _bstr; } - - private: - BSTR _bstr; - }; -} - static const char* doInitService(const wchar_t* networkResource, IWbemServices** result) { HRESULT hres; @@ -59,30 +44,11 @@ static const char* doInitService(const wchar_t* networkResource, IWbemServices** if (FAILED(hres)) return "Could not connect WMI server"; - // Set security levels on the proxy ------------------------- - hres = CoSetProxyBlanket( - pSvc, // Indicates the proxy to set - RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx - RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx - nullptr, // Server principal name - RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx - RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx - nullptr, // client identity - EOAC_NONE // proxy capabilities - ); - - if (FAILED(hres)) - { - pSvc->Release(); - return "Could not set proxy blanket"; - } - *result = pSvc; return NULL; } FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error, FFWmiNamespace wmiNs) - : pEnumerator(nullptr) { const char* errStr; if ((errStr = ffInitCom())) @@ -95,7 +61,7 @@ FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error, FFWmiNamespace static IWbemServices* contexts[(int) FFWmiNamespace::LAST]; IWbemServices* context = contexts[(int)wmiNs]; - if (!contexts[(int)wmiNs]) + if (!context) { if ((errStr = doInitService(wmiNs == FFWmiNamespace::CIMV2 ? L"ROOT\\CIMV2" : L"ROOT\\WMI", &context))) { @@ -106,13 +72,15 @@ FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error, FFWmiNamespace contexts[(int)wmiNs] = context; } + this->pService = context; + // Use the IWbemServices pointer to make requests of WMI HRESULT hres = context->ExecQuery( bstr_t(L"WQL"), bstr_t(queryStr), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, nullptr, - &pEnumerator); + &this->pEnumerator); if (FAILED(hres)) { diff --git a/src/util/windows/wmi.hpp b/src/util/windows/wmi.hpp index f9e3e9ae3..0c7096231 100644 --- a/src/util/windows/wmi.hpp +++ b/src/util/windows/wmi.hpp @@ -20,9 +20,9 @@ enum class FFWmiNamespace { struct FFWmiRecord { - IWbemClassObject* obj; + IWbemClassObject* obj = nullptr; - explicit FFWmiRecord(IEnumWbemClassObject* pEnumerator): obj(nullptr) { + explicit FFWmiRecord(IEnumWbemClassObject* pEnumerator) { if(!pEnumerator) return; ULONG ret; @@ -53,6 +53,7 @@ struct FFWmiRecord struct FFWmiQuery { + IWbemServices* pService = nullptr; IEnumWbemClassObject* pEnumerator = nullptr; FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error = nullptr, FFWmiNamespace wmiNs = FFWmiNamespace::CIMV2); @@ -75,6 +76,21 @@ struct FFWmiQuery } }; +namespace +{ + // Provide our bstr_t to avoid libstdc++ dependency + struct bstr_t + { + explicit bstr_t(const wchar_t* str) noexcept: _bstr(SysAllocString(str)) {} + ~bstr_t(void) noexcept { SysFreeString(_bstr); } + explicit operator const wchar_t*(void) const noexcept { return _bstr; } + operator BSTR(void) const noexcept { return _bstr; } + + private: + BSTR _bstr; + }; +} + #else // Win32 COM headers requires C++ compiler #error Must be included in C++ source file