diff --git a/CMakeLists.txt b/CMakeLists.txt index f2fb3fa78..426a07cab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,10 +22,6 @@ elseif(NOT APPLE AND NOT WIN32) message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}") endif() -if(WIN32) - enable_language(CXX) -endif() - ############################# # Compile time dependencies # ############################# @@ -112,7 +108,8 @@ set(CMAKE_C_STANDARD 11) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=incompatible-pointer-types -Werror=implicit-function-declaration") if(WIN32) - set(CMAKE_CXX_STANDARD 11) + enable_language(CXX) + set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS} -fno-exceptions -fno-rtti") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--tsaware -Wl,--build-id -Wl,--subsystem,console:6.1,--major-os-version,6,--minor-os-version,1") endif() @@ -532,7 +529,7 @@ elseif(WIN32) src/detection/bluetooth/bluetooth_windows.c src/detection/board/board_windows.c src/detection/brightness/brightness_windows.cpp - src/detection/chassis/chassis_windows.c + src/detection/chassis/chassis_windows.cpp src/detection/cpu/cpu_windows.c src/detection/cpuusage/cpuusage_windows.c src/detection/cursor/cursor_windows.c diff --git a/src/detection/chassis/chassis_windows.c b/src/detection/chassis/chassis_windows.c deleted file mode 100644 index 52d1337c1..000000000 --- a/src/detection/chassis/chassis_windows.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "chassis.h" -#include "util/windows/registry.h" - -const char* ffDetectChassis(FFChassisResult* result) -{ - FF_HKEY_AUTO_DESTROY hKey = NULL; - if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, NULL)) // SMBIOS - return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\BIOS\", &hKey, NULL) failed"; - - uint32_t type = 0; - if(!ffRegReadUint(hKey, L"EnclosureType", &type, NULL)) - return "\"HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\BIOS\\EnclosureType\" doesn't exist"; - - const char* typeStr = ffChassisTypeToString(type); - if(!typeStr) - return "Unknown chassis type"; - - ffStrbufAppendS(&result->type, typeStr); - return NULL; -} diff --git a/src/detection/chassis/chassis_windows.cpp b/src/detection/chassis/chassis_windows.cpp new file mode 100644 index 000000000..3264381c0 --- /dev/null +++ b/src/detection/chassis/chassis_windows.cpp @@ -0,0 +1,56 @@ +extern "C" { +#include "chassis.h" +#include "util/windows/registry.h" +} +#include "util/windows/wmi.hpp" + +static const char* detectWithRegistry(FFChassisResult* result) +{ + FF_HKEY_AUTO_DESTROY hKey = NULL; + if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, NULL)) // SMBIOS + return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\BIOS\", &hKey, NULL) failed"; + + uint32_t type = 0; + if(!ffRegReadUint(hKey, L"EnclosureType", &type, NULL)) + return "\"HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\BIOS\\EnclosureType\" doesn't exist"; + + const char* typeStr = ffChassisTypeToString(type); + if(!typeStr) + return "Unknown chassis type"; + + ffStrbufAppendS(&result->type, typeStr); + return NULL; +} + +FF_MAYBE_UNUSED static const char* detectWithWmi(FFChassisResult* result) +{ + FFWmiQuery query(L"SELECT Version, ChassisTypes, Manufacturer FROM Win32_SystemEnclosure"); + if (!query) + return "Query WMI service failed"; + + if (FFWmiRecord record = query.next()) + { + FFWmiVariant vtProp; + if(FAILED(record.obj->Get(L"ChassisTypes", 0, &vtProp, nullptr, nullptr))) + return "Get ChassisTypes failed"; + + auto [arr, len] = (std::pair) vtProp; + + if(len == 0) + return "ChassisTypes contain no data failed"; + + ffStrbufAppendS(&result->type, ffChassisTypeToString((uint32_t) *arr)); + + record.getString(L"Version", &result->version); + record.getString(L"Manufacturer", &result->vendor); + return NULL; + } + return "No WMI result returned"; +} + +extern "C" +const char* ffDetectChassis(FFChassisResult* result) +{ + return detectWithRegistry(result); + // TODO: if (instance->config.allowSlowOperations) detectWithWmi(result); +} diff --git a/src/util/windows/wmi.cpp b/src/util/windows/wmi.cpp index b8e576fd5..f1e2e10a1 100644 --- a/src/util/windows/wmi.cpp +++ b/src/util/windows/wmi.cpp @@ -1,6 +1,10 @@ #include "wmi.hpp" #include "util/windows/com.hpp" +extern "C" { +#include "util/windows/unicode.h" +} + #include #include #include @@ -144,8 +148,7 @@ bool FFWmiRecord::getString(const wchar_t* key, FFstrbuf* strbuf) { bool result = true; - VARIANT vtProp; - VariantInit(&vtProp); + FFWmiVariant vtProp; CIMTYPE type; if(FAILED(obj->Get(key, 0, &vtProp, &type, nullptr)) || vtProp.vt != VT_BSTR) @@ -180,13 +183,12 @@ bool FFWmiRecord::getString(const wchar_t* key, FFstrbuf* strbuf) ffStrbufAppendS(strbuf, vtProp.pcVal); break; - case VT_LPWSTR: // TODO + case VT_LPWSTR: default: - result = false; + ffStrbufSetWS(strbuf, vtProp.bstrVal); break; } } - VariantClear(&vtProp); return result; } @@ -194,8 +196,7 @@ bool FFWmiRecord::getSigned(const wchar_t* key, int64_t* integer) { bool result = true; - VARIANT vtProp; - VariantInit(&vtProp); + FFWmiVariant vtProp; CIMTYPE type; if(FAILED(obj->Get(key, 0, &vtProp, &type, nullptr))) @@ -221,7 +222,6 @@ bool FFWmiRecord::getSigned(const wchar_t* key, int64_t* integer) default: *integer = 0; result = false; } } - VariantClear(&vtProp); return result; } @@ -229,8 +229,7 @@ bool FFWmiRecord::getUnsigned(const wchar_t* key, uint64_t* integer) { bool result = true; - VARIANT vtProp; - VariantInit(&vtProp); + FFWmiVariant vtProp; if(FAILED(obj->Get(key, 0, &vtProp, nullptr, nullptr))) { @@ -255,7 +254,6 @@ bool FFWmiRecord::getUnsigned(const wchar_t* key, uint64_t* integer) default: *integer = 0; result = false; } } - VariantClear(&vtProp); return result; } @@ -263,8 +261,7 @@ bool FFWmiRecord::getReal(const wchar_t* key, double* real) { bool result = true; - VARIANT vtProp; - VariantInit(&vtProp); + FFWmiVariant vtProp; if(FAILED(obj->Get(key, 0, &vtProp, nullptr, nullptr))) { @@ -291,6 +288,5 @@ bool FFWmiRecord::getReal(const wchar_t* key, double* real) default: *real = NAN; result = false; } } - VariantClear(&vtProp); return result; } diff --git a/src/util/windows/wmi.hpp b/src/util/windows/wmi.hpp index 32ce0bcb4..d5a08f62e 100644 --- a/src/util/windows/wmi.hpp +++ b/src/util/windows/wmi.hpp @@ -11,6 +11,9 @@ extern "C" { #include #include +#include +#include +#include enum class FFWmiNamespace { CIMV2, @@ -74,6 +77,117 @@ struct FFWmiQuery } }; +struct FFWmiVariant: VARIANT { + explicit FFWmiVariant() { VariantInit(this); } + ~FFWmiVariant() { VariantClear(this); } + + FFWmiVariant(const FFWmiVariant&) = delete; + + // boolean + explicit operator bool() { + assert(this->vt == VT_BOOL); + return this->boolVal != VARIANT_FALSE; + } + + // signed + explicit operator int8_t() { + assert(this->vt == VT_I1); + return this->cVal; + } + explicit operator int16_t() { + assert(vt == VT_I2); + return this->iVal; + } + explicit operator int32_t() { + assert(this->vt == VT_I4 || vt == VT_INT); + return this->intVal; + } + explicit operator int64_t() { + assert(this->vt == VT_I8); + return this->llVal; + } + + // unsigned + explicit operator uint8_t() { + assert(this->vt == VT_I1); + return this->bVal; + } + explicit operator uint16_t() { + assert(this->vt == VT_I2); + return this->uiVal; + } + explicit operator uint32_t() { + assert(this->vt == VT_UI4 || vt == VT_UINT); + return this->uintVal; + } + explicit operator uint64_t() { + assert(this->vt == VT_UI8); + return this->ullVal; + } + explicit operator float() { + assert(this->vt == VT_R4); + return this->fltVal; + } + explicit operator double() { + assert(this->vt == VT_R8); + return this->dblVal; + } + + // string + explicit operator const std::string_view() { + assert(this->vt == VT_LPSTR); + return this->pcVal; + } + explicit operator const std::wstring_view() { + assert(this->vt == VT_BSTR || this->vt == VT_LPWSTR); + return this->bstrVal; + } + + // array signed + explicit operator std::pair() { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_I1); + return std::make_pair((int8_t*)this->parray->pvData, this->parray->cDims); + } + explicit operator std::pair() { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_I2); + return std::make_pair((int16_t*)this->parray->pvData, this->parray->cDims); + } + explicit operator std::pair() { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_I4); + return std::make_pair((int32_t*)this->parray->pvData, this->parray->cDims); + } + explicit operator std::pair() { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_I8); + return std::make_pair((int64_t*)this->parray->pvData, this->parray->cDims); + } + + // array unsigned + explicit operator std::pair() { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_UI1); + return std::make_pair((uint8_t*)this->parray->pvData, this->parray->cDims); + } + explicit operator std::pair() { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_UI2); + return std::make_pair((uint16_t*)this->parray->pvData, this->parray->cDims); + } + explicit operator std::pair() { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_UI4); + return std::make_pair((uint32_t*)this->parray->pvData, this->parray->cDims); + } + explicit operator std::pair() { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_UI8); + return std::make_pair((uint64_t*)this->parray->pvData, this->parray->cDims); + } +}; + #else // Win32 COM headers requires C++ compiler #error Must be included in C++ source file