WMI (Windows): code refactor

This commit is contained in:
李通洲
2023-06-25 14:16:49 +08:00
parent 8fc31c700f
commit c4c490663b
7 changed files with 223 additions and 166 deletions
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#ifndef FASTFETCH_INCLUDED_UNICODE_HPP
#define FASTFETCH_INCLUDED_UNICODE_HPP
#ifdef __cplusplus
extern "C" {
#include "unicode.h"
}
#include <string_view>
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
+3 -21
View File
@@ -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 <synchapi.h>
#include <wchar.h>
@@ -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;
+132 -111
View File
@@ -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 <typename T> T get();
// boolean
template <> bool get<bool>() {
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<const int8_t*, uint32_t> 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<const int16_t*, uint32_t> 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<const int32_t*, uint32_t> 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<const int64_t*, uint32_t> 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<const uint8_t*, uint32_t> 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<const uint16_t*, uint32_t> 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<const uint32_t*, uint32_t> 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<const uint64_t*, uint32_t> 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<const int8_t*, uint32_t>() {
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<const int16_t*, uint32_t>() {
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<const int32_t*, uint32_t>() {
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<const int64_t*, uint32_t>() {
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<const uint8_t*, uint32_t>() {
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<const uint16_t*, uint32_t>() {
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<const uint32_t*, uint32_t>() {
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<const uint64_t*, uint32_t>() {
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