diff --git a/src/detection/brightness/brightness_windows.cpp b/src/detection/brightness/brightness_windows.cpp index 3139fef4c..0f86ba49e 100644 --- a/src/detection/brightness/brightness_windows.cpp +++ b/src/detection/brightness/brightness_windows.cpp @@ -3,6 +3,7 @@ extern "C" #include "brightness.h" } #include "util/windows/wmi.hpp" +#include "util/windows/unicode.hpp" extern "C" const char* ffDetectBrightness(FFlist* result) @@ -13,15 +14,19 @@ const char* ffDetectBrightness(FFlist* result) while(FFWmiRecord record = query.next()) { - FFBrightnessResult* display = (FFBrightnessResult*) ffListAdd(result); - ffStrbufInit(&display->name); - record.getString(L"InstanceName", &display->name); - ffStrbufSubstrAfterFirstC(&display->name, '\\'); - ffStrbufSubstrBeforeFirstC(&display->name, '\\'); + if(FFWmiVariant vtValue = record.get(L"CurrentBrightness")) + { + FFBrightnessResult* display = (FFBrightnessResult*) ffListAdd(result); + display->value = vtValue.get(); - uint64_t brightness; - record.getUnsigned(L"CurrentBrightness", &brightness); - display->value = (float) brightness; + ffStrbufInit(&display->name); + if (FFWmiVariant vtName = record.get(L"InstanceName")) + { + ffStrbufSetWSV(&display->name, vtName.get()); + ffStrbufSubstrAfterFirstC(&display->name, '\\'); + ffStrbufSubstrBeforeFirstC(&display->name, '\\'); + } + } } return NULL; } diff --git a/src/detection/chassis/chassis_windows.cpp b/src/detection/chassis/chassis_windows.cpp index cd2d1f7f0..2332c5b31 100644 --- a/src/detection/chassis/chassis_windows.cpp +++ b/src/detection/chassis/chassis_windows.cpp @@ -3,6 +3,7 @@ extern "C" { #include "util/windows/registry.h" #include "util/smbiosHelper.h" } +#include "util/windows/unicode.hpp" #include "util/windows/wmi.hpp" static const char* detectWithRegistry(FFChassisResult* result) @@ -31,26 +32,33 @@ FF_MAYBE_UNUSED static const char* detectWithWmi(FFChassisResult* result) if (FFWmiRecord record = query.next()) { - FFWmiVariant vtProp; - if(FAILED(record.obj->Get(L"ChassisTypes", 0, &vtProp, nullptr, nullptr))) + if (auto vtProp = record.get(L"ChassisTypes")) + { + auto [arr, len] = vtProp.get>(); + if(len == 0) + return "ChassisTypes contain no data failed"; + for (uint32_t i = 0; i < len; ++i) + { + if (i > 0) + ffStrbufAppendS(&result->type, ", "); + ffStrbufAppendS(&result->type, ffChassisTypeToString((uint32_t) arr[i])); + } + } + else return "Get ChassisTypes failed"; - auto [arr, len] = (std::pair) vtProp; - - if(len == 0) - return "ChassisTypes contain no data failed"; - - for (uint32_t i = 0; i < len; ++i) + if (auto vtProp = record.get(L"Version")) { - if (i > 0) - ffStrbufAppendS(&result->type, ", "); - ffStrbufAppendS(&result->type, ffChassisTypeToString((uint32_t) arr[i])); + ffStrbufSetWSV(&result->version, vtProp.get()); + ffCleanUpSmbiosValue(&result->version); + } + + if (auto vtProp = record.get(L"Manufacturer")) + { + ffStrbufSetWSV(&result->vendor, vtProp.get()); + ffCleanUpSmbiosValue(&result->vendor); } - record.getString(L"Version", &result->version); - ffCleanUpSmbiosValue(&result->version); - record.getString(L"Manufacturer", &result->vendor); - ffCleanUpSmbiosValue(&result->vendor); return NULL; } return "No WMI result returned"; diff --git a/src/detection/os/os_windows.cpp b/src/detection/os/os_windows.cpp index 2224c5c9b..935f86153 100644 --- a/src/detection/os/os_windows.cpp +++ b/src/detection/os/os_windows.cpp @@ -1,7 +1,8 @@ extern "C" { #include "os.h" -#include "util/windows/unicode.h" +#include "common/library.h" } +#include "util/windows/unicode.hpp" #include "util/windows/wmi.hpp" static const char* getOsNameByWmi(FFstrbuf* osName) @@ -12,9 +13,13 @@ static const char* getOsNameByWmi(FFstrbuf* osName) if(FFWmiRecord record = query.next()) { - record.getString(L"Caption", osName); - ffStrbufTrimRight(osName, ' '); - return NULL; + if(auto vtCaption = record.get(L"Caption")) + { + ffStrbufSetWSV(osName, vtCaption.get()); + ffStrbufTrimRight(osName, ' '); + return NULL; + } + return "Get Caption failed"; } return "No WMI result returned"; @@ -29,9 +34,9 @@ static const char* getOsNameByWinbrand(FFstrbuf* osName) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(winbrand, BrandingFormatString); const wchar_t* rawName = ffBrandingFormatString(L"%WINDOWS_LONG%"); - ffStrbufSetWS(osName, rawName); - GlobalFree((HGLOBAL)rawName); - return NULL; + ffStrbufSetWS(osName, rawName); + GlobalFree((HGLOBAL)rawName); + return NULL; } extern "C" diff --git a/src/detection/temps/temps_windows.cpp b/src/detection/temps/temps_windows.cpp index 9c741b4cd..c9cfeac50 100644 --- a/src/detection/temps/temps_windows.cpp +++ b/src/detection/temps/temps_windows.cpp @@ -15,10 +15,21 @@ const char* ffDetectSmbiosTemp(double* current, double* critical) if(FFWmiRecord record = query.next()) { - if (current && record.getReal(L"CurrentTemperature", current)) // In tenth of degrees Kelvin - *current = *current / 10 - 273.15; - if (critical && record.getReal(L"CriticalTripPoint", critical)) // In tenth of degrees Kelvin - *critical = *critical / 10 - 273.15; + if (current) + { + if(auto vtCurrent = record.get(L"CurrentTemperature")) + *current = vtCurrent.get() / 10 - 273.15; // In tenth of degrees Kelvin + else + *current = 0.0/0.0; + } + + if (critical) + { + if(auto vtCritical = record.get(L"CriticalTripPoint")) + *critical = vtCritical.get() / 10 - 273.15; // In tenth of degrees Kelvin + else + *critical = 0.0/0.0; + } } return "No WMI result returned"; diff --git a/src/util/windows/unicode.hpp b/src/util/windows/unicode.hpp new file mode 100644 index 000000000..18441a50d --- /dev/null +++ b/src/util/windows/unicode.hpp @@ -0,0 +1,25 @@ +#pragma once + +#ifndef FASTFETCH_INCLUDED_UNICODE_HPP +#define FASTFETCH_INCLUDED_UNICODE_HPP + +#ifdef __cplusplus + +extern "C" { +#include "unicode.h" +} + +#include + +static inline void ffStrbufSetWSV(FFstrbuf* result, const std::wstring_view source) +{ + return ffStrbufSetNWS(result, (uint32_t) source.size(), source.data()); +} + +#else + + #error Must be included in C++ source file + +#endif + +#endif diff --git a/src/util/windows/wmi.cpp b/src/util/windows/wmi.cpp index 9b8103fbe..af84c7013 100644 --- a/src/util/windows/wmi.cpp +++ b/src/util/windows/wmi.cpp @@ -1,9 +1,6 @@ #include "wmi.hpp" #include "util/windows/com.hpp" - -extern "C" { -#include "util/windows/unicode.h" -} +#include "util/windows/unicode.hpp" #include #include @@ -129,21 +126,6 @@ FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error, FFWmiNamespace } } -static void ffBstrToStrbuf(BSTR bstr, FFstrbuf* strbuf) -{ - int len = (int)SysStringLen(bstr); - if(len <= 0) - { - ffStrbufClear(strbuf); - return; - } - int size_needed = WideCharToMultiByte(CP_UTF8, 0, bstr, len, nullptr, 0, nullptr, nullptr); - ffStrbufEnsureFree(strbuf, (uint32_t)size_needed); - WideCharToMultiByte(CP_UTF8, 0, bstr, len, strbuf->chars, size_needed, nullptr, nullptr); - strbuf->length = (uint32_t)size_needed; - strbuf->chars[size_needed] = '\0'; -} - bool FFWmiRecord::getString(const wchar_t* key, FFstrbuf* strbuf) { bool result = true; @@ -171,11 +153,11 @@ bool FFWmiRecord::getString(const wchar_t* key, FFstrbuf* strbuf) else if(FAILED(pDateTime->GetFileTime(VARIANT_TRUE, &dateStr))) result = false; else - ffBstrToStrbuf(dateStr, strbuf); + ffStrbufSetNWS(strbuf, SysStringLen(dateStr), dateStr); } else { - ffBstrToStrbuf(vtProp.bstrVal, strbuf); + ffStrbufSetWS(strbuf, SysStringLen(vtProp.bstrVal), vtProp.bstrVal); } break; diff --git a/src/util/windows/wmi.hpp b/src/util/windows/wmi.hpp index d5a08f62e..b31b84533 100644 --- a/src/util/windows/wmi.hpp +++ b/src/util/windows/wmi.hpp @@ -25,6 +25,133 @@ enum { FF_WMI_QUERY_TIMEOUT = 5000 }; +struct FFWmiVariant: VARIANT { + explicit FFWmiVariant() { VariantInit(this); } + ~FFWmiVariant() { VariantClear(this); } + + FFWmiVariant(const FFWmiVariant&) = delete; + FFWmiVariant(FFWmiVariant&&); // don't define it to enforce NRVO optimization + + bool hasValue() { + return this->vt != VT_EMPTY; + } + + explicit operator bool() { + return this->hasValue(); + } + + template T get(); + + // boolean + template <> bool get() { + assert(this->vt == VT_BOOL); + return this->boolVal != VARIANT_FALSE; + } + + // signed + template <> int8_t get() { + assert(this->vt == VT_I1); + return this->cVal; + } + template <> int16_t get() { + assert(vt == VT_I2); + return this->iVal; + } + template <> int32_t get() { + assert(this->vt == VT_I4 || vt == VT_INT); + return this->intVal; + } + template <> int64_t get() { + assert(this->vt == VT_I8); + return this->llVal; + } + + // unsigned + template <> uint8_t get() { + assert(this->vt == VT_UI1); + return this->bVal; + } + template <> uint16_t get() { + assert(this->vt == VT_UI2); + return this->uiVal; + } + template <> uint32_t get() { + assert(this->vt == VT_UI4 || vt == VT_UINT); + return this->uintVal; + } + template <> uint64_t get() { + assert(this->vt == VT_UI8); + return this->ullVal; + } + + // decimal + template <> float get() { + assert(this->vt == VT_R4); + return this->fltVal; + } + template <> double get() { + assert(this->vt == VT_R8); + return this->dblVal; + } + + // string + template <> std::string_view get() { + assert(this->vt == VT_LPSTR); + return this->pcVal; + } + template <> std::wstring_view get() { + assert(this->vt == VT_BSTR || this->vt == VT_LPWSTR); + if (this->vt == VT_LPWSTR) + return this->bstrVal; + else + return { this->bstrVal, SysStringLen(this->bstrVal) }; + } + + // array signed + template <> std::pair get() { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_I1); + return std::make_pair((int8_t*)this->parray->pvData, this->parray->cDims); + } + template <> std::pair get() { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_I2); + return std::make_pair((int16_t*)this->parray->pvData, this->parray->cDims); + } + template <> std::pair get() { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_I4); + return std::make_pair((int32_t*)this->parray->pvData, this->parray->cDims); + } + template <> std::pair get() { + 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 + template <> std::pair get() { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_UI1); + return std::make_pair((uint8_t*)this->parray->pvData, this->parray->cDims); + } + template <> std::pair get() { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_UI2); + return std::make_pair((uint16_t*)this->parray->pvData, this->parray->cDims); + } + template <> std::pair get() { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_UI4); + return std::make_pair((uint32_t*)this->parray->pvData, this->parray->cDims); + } + template <> std::pair get() { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_UI8); + return std::make_pair((uint64_t*)this->parray->pvData, this->parray->cDims); + } +}; + struct FFWmiRecord { IWbemClassObject* obj; @@ -51,6 +178,11 @@ struct FFWmiRecord bool getSigned(const wchar_t* key, int64_t* integer); bool getUnsigned(const wchar_t* key, uint64_t* integer); bool getReal(const wchar_t* key, double* real); + FFWmiVariant get(const wchar_t* key) { + FFWmiVariant result; + obj->Get(key, 0, &result, nullptr, nullptr); + return result; + } }; struct FFWmiQuery @@ -77,117 +209,6 @@ 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