Win32 / C++ Wmi 查询

CWmiHelper.h

#pragma once
#include <Wbemidl.h>
#include <tchar.h>
#include <atlcomcli.h>
#include <string>
#include <vector>
#include <set>
#include <functional>
#include <cstdint>

#define WMI_GET_VALUE(_obj, _out, _name) _obj.GetValue(_T(#_name), _out._name)

#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif

// ============================================================================
// 常用查询参考类
// ============================================================================
// 操作系统类
// https://learn.microsoft.com/zh-cn/windows/win32/cimwin32prov/operating-system-classes
//
// 计算机系统硬件类
// https://learn.microsoft.com/zh-cn/windows/win32/cimwin32prov/computer-system-hardware-classes

// WMI 基础类型定义
class wmi_datetime;
using wmi_boolean = bool;
using wmi_uint8 = uint8_t;
using wmi_uint8_list = std::vector<wmi_uint8>;
using wmi_sint8 = int8_t;
using wmi_sint8_list = std::vector<wmi_sint8>;
using wmi_uint16 = uint16_t;
using wmi_uint16_list = std::vector<wmi_uint16>;
using wmi_sint16 = int16_t;
using wmi_sint16_list = std::vector<wmi_sint16>;
using wmi_uint32 = uint32_t;
using wmi_uint32_list = std::vector<wmi_uint32>;
using wmi_sint32 = int32_t;
using wmi_sint32_list = std::vector<wmi_sint32>;
using wmi_uint64 = uint64_t;
using wmi_uint64_list = std::vector<wmi_uint64>;
using wmi_sint64 = int64_t;
using wmi_sint64_list = std::vector<wmi_sint64>;
using wmi_string = _tstring;
using wmi_string_list = std::vector<wmi_string>;
using wmi_float = float_t;
using wmi_float_list = std::vector<wmi_float>;
using wmi_double = double_t;
using wmi_double_list = std::vector<wmi_double>;
using wmi_real32 = wmi_float;
using wmi_real32_list = wmi_float_list;
using wmi_real64 = wmi_double;
using wmi_real64_list = wmi_double_list;
using wmi_datetime_list = std::vector<wmi_datetime>;

// WMI 时间类
class wmi_datetime
{
public:

    wmi_datetime();
    ~wmi_datetime();

    uint16_t wYear;             // 0000 - 9999
    uint16_t wMonth;            // 01 - 12
    uint16_t wDay;              // 00 - 31
    uint16_t wHour;             // 00 - 23
    uint16_t wMinute;           // 00 - 59
    uint16_t wSecond;           // 00 - 59
    uint16_t wMilliseconds;     // 000 - 999
    int16_t  nMinutesUTC;       // +/- 000 - 999
    uint32_t nMicroseconds;     // 000000 - 999999

    void Clear();
    wmi_string GetTimeString() const;
    wmi_string GetDateString() const;
};

// WMI 类辅助类
class CWmiClassHelper
{
public:
    explicit CWmiClassHelper(IWbemClassObject* pObj);

    // 获取属性类型
    CIMTYPE GetCimType(const _tstring& strName) const;
    VARTYPE GetVarType(const _tstring& strName) const;

    // 获取值
    wmi_boolean GetBoolean(const _tstring& strName, bool fTypeCheck = false) const;
    wmi_sint64 GetSInt(const _tstring& strName, bool fTypeCheck = false) const;
    wmi_uint64 GetUInt(const _tstring& strName, bool fTypeCheck = false) const;
    wmi_double GetFloat(const _tstring& strName, bool fTypeCheck = false) const;
    wmi_string GetString(const _tstring& strName, bool fTypeCheck = false) const;
    wmi_datetime GetDatetime(const _tstring& strName) const;
    bool GetValue(const _tstring& strName, wmi_boolean& val) const;
    bool GetValue(const _tstring& strName, wmi_sint8& val) const;
    bool GetValue(const _tstring& strName, wmi_uint8& val) const;
    bool GetValue(const _tstring& strName, wmi_sint16& val) const;
    bool GetValue(const _tstring& strName, wmi_uint16& val) const;
    bool GetValue(const _tstring& strName, wmi_sint32& val) const;
    bool GetValue(const _tstring& strName, wmi_uint32& val) const;
    bool GetValue(const _tstring& strName, wmi_sint64& val) const;
    bool GetValue(const _tstring& strName, wmi_uint64& val) const;
    bool GetValue(const _tstring& strName, wmi_float& val) const;
    bool GetValue(const _tstring& strName, wmi_double& val) const;
    bool GetValue(const _tstring& strName, wmi_string& val) const;
    bool GetValue(const _tstring& strName, wmi_datetime& val) const;
    bool GetValue(const _tstring& strName, wmi_sint8_list& valList) const;
    bool GetValue(const _tstring& strName, wmi_uint8_list& valList) const;
    bool GetValue(const _tstring& strName, wmi_sint16_list& valList) const;
    bool GetValue(const _tstring& strName, wmi_uint16_list& valList) const;
    bool GetValue(const _tstring& strName, wmi_sint32_list& valList) const;
    bool GetValue(const _tstring& strName, wmi_uint32_list& valList) const;
    bool GetValue(const _tstring& strName, wmi_sint64_list& valList) const;
    bool GetValue(const _tstring& strName, wmi_uint64_list& valList) const;
    bool GetValue(const _tstring& strName, wmi_float_list& valList) const;
    bool GetValue(const _tstring& strName, wmi_double_list& valList) const;
    bool GetValue(const _tstring& strName, wmi_string_list& valList) const;
    bool GetValue(const _tstring& strName, wmi_datetime_list& valList) const;

    // 获取系统属性
    wmi_string GetClass() const;
    wmi_string GetSuperClass() const;
    wmi_string GetNameSpace() const;
    wmi_string GetPath() const;
    wmi_string GetServer() const;
    wmi_string GetRelPath() const;
    wmi_sint32 GetPropertyCount() const;
    wmi_sint32 GetGenus() const;
    wmi_string GetDynasty() const;
    wmi_string GetDerivation() const;

    // 打印属性
    void PrintProperty() const;
    void PrintPropertySystemOnly() const;
    void PrintPropertyNonSystemOnly() const;
    void ConsolePrint(LPCTSTR pFormat, ...) const;

private:

    //
    // @brief:  获取值
    // @param:  strName             字段名
    // @param:  ct                  原始值类型
    // @param:  cb                  回调函数
    // @ret:    bool                操作是否成功
    bool _GetValue(
        const _tstring& strName, 
        CIMTYPE ct, 
        std::function<void(const CComVariant& vtProp)> cb
    ) const;

    //
    // @brief:  获取值列表(一维数组)
    // @param:  strName             字段名
    // @param:  ct                  元素原始值类型
    // @param:  vt                  元素值类型
    // @param:  cb                  回调函数
    // @ret:    bool                操作是否成功
    bool _GetValueList(
        const _tstring& strName, 
        CIMTYPE ct, 
        VARTYPE vt, 
        std::function<void(const void* pValue, UINT uElemsize, LONG count, VARTYPE vt)> cb
    ) const;

    // 打印
    void _PrintProperty(long lFlags) const;
    void _Print(const CComVariant& val) const;
    void _PrintList(const CComVariant& val) const;
    void _Print(const _tstring& strName) const;

private:
    IWbemClassObject* m_pObj;
};

// WMI 查询辅助类
class CWmiHelper
{
public:

    CWmiHelper();
    ~CWmiHelper();

    bool Initialize(_tstring strNamespace = _T(R"(ROOT\CIMV2)"));
    void Uninitialize();

    //
    // @brief:  查询指定类字段名集合
    // @param:  strClass            类名, 如: Win32_Bios
    // @ret:    std::set<_tstring>  字段名集合
    std::set<wmi_string> QueryClassNames(const _tstring& strClass) const;

    //
    // @brief:  查询
    // @param:  strWql              查询语句
    // @param:  cb                  结果回调
    // @ret:    bool                操作是否成功
    bool Query(
        const _tstring& strWql,
        std::function<void(const CWmiClassHelper& obj)> cb = nullptr
    ) const;

    //
    // @brief:  查询指定类属性
    // @param:  strClass            类名, 如: Win32_Bios
    // @param:  cb                  结果回调
    // @ret:    bool                操作是否成功
    bool QueryClass(
        const _tstring& strClass,
        std::function<void(const CWmiClassHelper& obj)> cb = nullptr
    ) const;

    //
    // @brief:  查询指定类属性(指定字段)
    // @param:  strClass            类名, 如: Win32_Bios
    // @param:  names               字段列表
    // @param:  cb                  结果回调
    // @ret:    bool                操作是否成功
    bool QueryClassWithNames(
        const _tstring& strClass,
        std::set<wmi_string> names = {},
        std::function<void(const CWmiClassHelper& obj)> cb = nullptr
    ) const;

    //
    // @brief:  查询指定类属性(排除字段)
    // @param:  strClass            类名, 如: Win32_Bios
    // @param:  names               排除字段集
    // @param:  cb                  结果回调
    // @ret:    bool                操作是否成功
    bool QueryClassWithoutNames(
        const _tstring& strClass,
        std::set<wmi_string> names = {},
        std::function<void(const CWmiClassHelper& obj)> cb = nullptr
    ) const;

private:
    bool m_bInit;                   // 初始化结果
    IWbemServices* m_pSvc;          // 客户端和提供程序使用的 WMI 服务
    IWbemLocator* m_pLoc;           // 指向特定主机上 WMI 的 IWbemServices 接口的初始命名空间指针
};

CWmiHelper.cpp

#include "CWmiHelper.h"
#include <comdef.h>
#include <strsafe.h>

#pragma comment(lib, "wbemuuid.lib")

#define DATETIME_FORMAT         _T("%4hd%2hd%2hd%2hd%2hd%2hd.%6d%4hd")

// https://learn.microsoft.com/zh-cn/windows/win32/wmisdk/numbers
// 数据类型     自动化类型      说明
// sint8        VT_I2           8 位有符号整数。
// sint16       VT_I2           16 位有符号整数。
// sint32       VT_I4           32 位有符号整数。
// sint64       VT_BSTR         字符串形式的有符号 64 位整数。 根据美国国家标准协会 (ANSI) C 规则,此类型遵循十六进制或十六进制格式。
// real32       VT_R4           遵循电气和电子工程师协会 (IEEE) 标准的 4 字节浮点值。
// real64       VT_R8           遵循 IEEE 标准的 8 字节浮点值。
// uint8        VT_UI1          8 位无符号整数。
// uint16       VT_I4           16 位无符号整数。
// uint32       VT_I4           32 位无符号整数。
// uint64       VT_BSTR         字符串形式的无符号 64 位整数。 根据 ANSI C 规则,此类型遵循十六进制或十进制格式。
// DATETIME     VT_BSTR         

static std::string _WStrToMultiStr(UINT CodePage, const std::wstring& str)
{
    int cbMultiByte = ::WideCharToMultiByte(CodePage, 0, str.c_str(), -1, NULL, 0, NULL, NULL);
    std::string strResult(cbMultiByte, 0);
    size_t nConverted = ::WideCharToMultiByte(CodePage, 0, str.c_str(), (int)str.size(), &strResult[0], (int)strResult.size(), NULL, NULL);
    strResult.resize(nConverted);
    return strResult;
}

static std::wstring _MultiStrToWStr(UINT CodePage, const std::string& str)
{
    int cchWideChar = ::MultiByteToWideChar(CodePage, 0, str.c_str(), -1, NULL, 0);
    std::wstring strResult(cchWideChar, 0);
    size_t nConverted = ::MultiByteToWideChar(CodePage, 0, str.c_str(), (int)str.size(), &strResult[0], (int)strResult.size());
    strResult.resize(nConverted);
    return strResult;
}

static std::wstring TStrToWStr(const _tstring& str)
{
#ifdef _UNICODE
    return str;
#else
    return _MultiStrToWStr(CP_ACP, str);
#endif
}

static wmi_string WStrToTStr(const std::wstring& str)
{
#ifdef _UNICODE
    return str;
#else
    return _WStrToMultiStr(CP_ACP, str);
#endif
}

wmi_datetime::wmi_datetime()
    :
    wYear(0),
    wMonth(0),
    wDay(0),
    wHour(0),
    wMinute(0),
    wSecond(0),
    wMilliseconds(0),
    nMinutesUTC(0),
    nMicroseconds(0)
{

}

wmi_datetime::~wmi_datetime()
{

}

void wmi_datetime::Clear()
{
    wYear = 0;
    wMonth = 0;
    wDay = 0;
    wHour = 0;
    wMinute = 0;
    wSecond = 0;
    wMilliseconds = 0;
    nMinutesUTC = 0;
    nMicroseconds = 0;
}

wmi_string wmi_datetime::GetTimeString() const
{
    TCHAR szBuf[MAX_PATH] = { 0 };

    // yyyymmddHHMMSS.mmmmmmsUUU
    ::StringCchPrintf(szBuf, _countof(szBuf),
        this->nMinutesUTC >= 0 ? _T("%.4d%.2hd%.2hd%.2hd%.2hd%.2hd.%.6d+%3d") : _T("%.4d%.2hd%.2hd%.2hd%.2hd%.2hd.%6d-%3d"),
        this->wYear, this->wMonth, this->wDay,
        this->wHour, this->wMinute, this->wSecond,
        this->nMicroseconds,
        this->nMinutesUTC
    );

    return szBuf;
}

wmi_string wmi_datetime::GetDateString() const
{
    TCHAR szBuf[MAX_PATH] = { 0 };

    // yyyymmdd
    ::StringCchPrintf(szBuf, _countof(szBuf), _T("%.4d%.2hd%.2hd"),
        this->wYear, this->wMonth, this->wDay
    );

    return szBuf;
}

void CWmiClassHelper::ConsolePrint(LPCTSTR pFormat, ...) const
{
    size_t nCchCount = MAX_PATH;
    wmi_string strResult(nCchCount, 0);
    va_list args;

    va_start(args, pFormat);

    do
    {
        //格式化输出字符串
        int nSize = _vsntprintf_s(&strResult[0], nCchCount, _TRUNCATE, pFormat, args);
        if (-1 != nSize)
        {
            HANDLE console = ::GetStdHandle(STD_OUTPUT_HANDLE);
            ::WriteConsole(console, strResult.c_str(), nSize, NULL, NULL);
            break;
        }

        //缓冲大小超限终止
        if (nCchCount >= INT32_MAX)
        {
            break;
        }

        //重新分配缓冲
        nCchCount *= 2;
        strResult.resize(nCchCount);

    } while (true);

    va_end(args);
}

void CWmiClassHelper::_PrintProperty(long lFlags) const
{
    HRESULT hr = S_OK;
    SAFEARRAY* arrayNames;

    if (!m_pObj)
    {
        return;
    }

    hr = m_pObj->GetNames(NULL, lFlags, NULL, &arrayNames);
    if (FAILED(hr))
    {
        return;
    }

    //获取数组维数
    UINT uDim = ::SafeArrayGetDim(arrayNames);

    LONG lLBound = 0;
    LONG lUBound = 0;

    //取得nDim维度的上界
    ::SafeArrayGetLBound(arrayNames, uDim, &lLBound);

    //取得nDim维度的下界
    ::SafeArrayGetUBound(arrayNames, uDim, &lUBound);

    BSTR* pvData;
    ::SafeArrayAccessData(arrayNames, (void**)&pvData);
    for (int i = 0; i <= lUBound - lLBound; i++)
    {
        wmi_string strName = WStrToTStr(*pvData).c_str();
        _Print(strName);
        ConsolePrint(_T("\r\n"));
        pvData++;
    }
    ::SafeArrayUnaccessData(arrayNames);
}

void CWmiClassHelper::_Print(const CComVariant& val) const
{
    if (VARENUM::VT_ARRAY & val.vt)
    {
        ConsolePrint(_T("{"));
        _PrintList(val);
        ConsolePrint(_T("}"));
    }
    else
    {
        switch (val.vt)
        {
        case VARENUM::VT_EMPTY:
            ConsolePrint(_T("EMPTY"));
            break;
        case VARENUM::VT_NULL:
            ConsolePrint(_T("NULL"));
            break;
        case VARENUM::VT_BOOL:
            ConsolePrint(_T("%s"), val.boolVal ? _T("TRUE") : _T("FALSE"));
            break;
        case VARENUM::VT_I1:
        case VARENUM::VT_UI1:
        case VARENUM::VT_UI2:
        case VARENUM::VT_I2:
        case VARENUM::VT_I4:
        case VARENUM::VT_INT:
            ConsolePrint(_T("%d"), val.intVal);
            break;
        case VARENUM::VT_UI4:
        case VARENUM::VT_UINT:
            ConsolePrint(_T("%u"), val.uintVal);
            break;
        case VARENUM::VT_I8:
            ConsolePrint(_T("%lld"), val.llVal);
            break;
        case VARENUM::VT_UI8:
            ConsolePrint(_T("%llu"), val.ullVal);
            break;
        case VARENUM::VT_R4:
            ConsolePrint(_T("%f"), val.fltVal);
            break;
        case VARENUM::VT_R8:
            ConsolePrint(_T("%lf"), val.dblVal);
            break;
        case VARENUM::VT_BSTR:
            ConsolePrint(_T(R"("%s")"), WStrToTStr(val.bstrVal).c_str());
            break;
        }
    }
}

void CWmiClassHelper::_PrintList(const CComVariant& val) const
{
    if (VARENUM::VT_ARRAY & val.vt)
    {
        SAFEARRAY* pArray = val.parray;
        LONG lLBound = 0;
        LONG lUBound = 0;
        UINT uDim = ::SafeArrayGetDim(pArray);

        //暂且只处理一维数组
        if (1 != uDim)
        {
            return;
        }

        UINT uElemsize = ::SafeArrayGetElemsize(pArray);
        ::SafeArrayGetLBound(pArray, uDim, &lLBound);
        ::SafeArrayGetUBound(pArray, uDim, &lUBound);
        LONG lCount = lUBound - lLBound;

        void* pElem = nullptr;
        ::SafeArrayAccessData(pArray, (void**)&pElem);

        size_t pAddr = (uint64_t)pElem;
        VARTYPE vtElem = val.vt & ~VARENUM::VT_ARRAY;
        for (LONG index = 0; index < lCount; index++)
        {
            switch (vtElem)
            {
            case VARENUM::VT_I1:
                ConsolePrint(_T("%d"), *(int8_t*)pAddr);
                break;
            case VARENUM::VT_UI1:
                ConsolePrint(_T("%d"), *(uint8_t*)pAddr);
                break;
            case VARENUM::VT_I2:
                ConsolePrint(_T("%hd"), *(int16_t*)pAddr);
                break;
            case VARENUM::VT_UI2:
                ConsolePrint(_T("%hu"), *(uint16_t*)pAddr);
                break;
            case VARENUM::VT_I4:
            case VARENUM::VT_INT:
                ConsolePrint(_T("%d"), *(int32_t*)pAddr);
                break;
            case VARENUM::VT_UI4:
            case VARENUM::VT_UINT:
                ConsolePrint(_T("%u"), *(uint32_t*)pAddr);
                break;
            case VARENUM::VT_I8:
                ConsolePrint(_T("%lld"), *(int32_t*)pAddr);
                break;
            case VARENUM::VT_UI8:
                ConsolePrint(_T("%llu"), *(uint32_t*)pAddr);
                break;
            case VARENUM::VT_R4:
                ConsolePrint(_T("%f"), *(float*)pAddr);
                break;
            case VARENUM::VT_R8:
                ConsolePrint(_T("%lf"), *(double*)pAddr);
                break;
            case VARENUM::VT_BSTR:
                ConsolePrint(_T(R"("%s")"), WStrToTStr(*(BSTR*)pAddr).c_str());
                break;
            }

            if (index < lCount - 1)
            {
                ConsolePrint(_T(", "));
            }

            pAddr += uElemsize;
        }

        ::SafeArrayUnaccessData(pArray);
    }
}

void CWmiClassHelper::_Print(const _tstring& strName) const
{
    if (!m_pObj)
    {
        return;
    }

    HRESULT hr = S_OK;

    CComVariant vtProp;
    hr = m_pObj->Get(TStrToWStr(strName).c_str(), 0, &vtProp, 0, 0);
    ConsolePrint(_T("%s = "), strName.c_str());
    _Print(vtProp);
}

CWmiClassHelper::CWmiClassHelper(IWbemClassObject* pObj)
{
    m_pObj = pObj;
}

wmi_boolean CWmiClassHelper::GetBoolean(const _tstring& strName, bool fTypeCheck/* = false*/) const
{
    HRESULT hr = S_OK;
    CComVariant vtProp;
    CIMTYPE cType = 0;
    wmi_boolean val = 0;

    if (!m_pObj)
    {
        return val;
    }

    hr = m_pObj->Get(TStrToWStr(strName).c_str(), 0, &vtProp, &cType, 0);
    if (SUCCEEDED(hr))
    {
        switch (cType)
        {
        case CIMTYPE_ENUMERATION::CIM_BOOLEAN:
            val = vtProp.boolVal;
            break;
        default:
            if (!fTypeCheck)
            {
                if (0 != vtProp.ullVal)
                {
                    val = vtProp.ullVal;
                }
            }
            break;
        }
    }
    return val;
}

wmi_sint64 CWmiClassHelper::GetSInt(const _tstring& strName, bool fTypeCheck/* = false*/) const
{
    HRESULT hr = S_OK;
    CComVariant vtProp;
    CIMTYPE cType = 0;
    wmi_sint64 val = 0;

    if (!m_pObj)
    {
        return val;
    }

    hr = m_pObj->Get(TStrToWStr(strName).c_str(), 0, &vtProp, &cType, 0);
    if (SUCCEEDED(hr))
    {
        switch (cType)
        {
        case CIMTYPE_ENUMERATION::CIM_SINT8:
        case CIMTYPE_ENUMERATION::CIM_SINT16:
        case CIMTYPE_ENUMERATION::CIM_SINT32:
        case CIMTYPE_ENUMERATION::CIM_SINT64:
            if (VARENUM::VT_BSTR == vtProp.vt)
            {
                val = _tcstoll(WStrToTStr(vtProp.bstrVal).c_str(), NULL, 10);
            }
            else
            {
                val = vtProp.llVal;
            }
            break;
        case CIMTYPE_ENUMERATION::CIM_UINT8:
        case CIMTYPE_ENUMERATION::CIM_UINT16:
        case CIMTYPE_ENUMERATION::CIM_UINT32:
        case CIMTYPE_ENUMERATION::CIM_UINT64:
            if (!fTypeCheck)
            {
                if (VARENUM::VT_BSTR == vtProp.vt)
                {
                    val = _tcstoull(WStrToTStr(vtProp.bstrVal).c_str(), NULL, 10);
                }
                else
                {
                    val = vtProp.ullVal;
                }
            }
            break;
        }
    }
    return val;
}

wmi_uint64 CWmiClassHelper::GetUInt(const _tstring& strName, bool fTypeCheck/* = false*/) const
{
    HRESULT hr = S_OK;
    CComVariant vtProp;
    CIMTYPE cType = 0;
    wmi_uint64 val = 0;

    if (!m_pObj)
    {
        return val;
    }

    hr = m_pObj->Get(TStrToWStr(strName).c_str(), 0, &vtProp, &cType, 0);
    if (SUCCEEDED(hr))
    {
        switch (cType)
        {
        case CIMTYPE_ENUMERATION::CIM_SINT8:
        case CIMTYPE_ENUMERATION::CIM_SINT16:
        case CIMTYPE_ENUMERATION::CIM_SINT32:
        case CIMTYPE_ENUMERATION::CIM_SINT64:
            if (!fTypeCheck)
            {
                if (VARENUM::VT_BSTR == vtProp.vt)
                {
                    val = _tcstoll(WStrToTStr(vtProp.bstrVal).c_str(), NULL, 10);
                }
                else
                {
                    val = vtProp.llVal;
                }
            }
            break;
        case CIMTYPE_ENUMERATION::CIM_UINT8:
        case CIMTYPE_ENUMERATION::CIM_UINT16:
        case CIMTYPE_ENUMERATION::CIM_UINT32:
        case CIMTYPE_ENUMERATION::CIM_UINT64:
            if (VARENUM::VT_BSTR == vtProp.vt)
            {
                val = _tcstoull(WStrToTStr(vtProp.bstrVal).c_str(), NULL, 10);
            }
            else
            {
                val = vtProp.ullVal;
            }
            break;
        }
    }
    return val;
}

wmi_double CWmiClassHelper::GetFloat(const _tstring& strName, bool fTypeCheck/* = false*/) const
{
    HRESULT hr = S_OK;
    CComVariant vtProp;
    CIMTYPE cType = 0;
    wmi_double val = 0.0f;

    if (!m_pObj)
    {
        return val;
    }

    hr = m_pObj->Get(TStrToWStr(strName).c_str(), 0, &vtProp, &cType, 0);
    if (SUCCEEDED(hr))
    {
        switch (cType)
        {
        case CIMTYPE_ENUMERATION::CIM_REAL32:
            val = vtProp.fltVal;
            break;
        case CIMTYPE_ENUMERATION::CIM_REAL64:
            val = vtProp.dblVal;
            break;
        case CIMTYPE_ENUMERATION::CIM_SINT8:
        case CIMTYPE_ENUMERATION::CIM_SINT16:
        case CIMTYPE_ENUMERATION::CIM_SINT32:
        case CIMTYPE_ENUMERATION::CIM_SINT64:
            if (!fTypeCheck)
            {
                if (VARENUM::VT_BSTR == vtProp.vt)
                {
                    val = _tcstoll(WStrToTStr(vtProp.bstrVal).c_str(), NULL, 10);
                }
                else
                {
                    val = vtProp.llVal;
                }
            }
            break;
        case CIMTYPE_ENUMERATION::CIM_UINT8:
        case CIMTYPE_ENUMERATION::CIM_UINT16:
        case CIMTYPE_ENUMERATION::CIM_UINT32:
        case CIMTYPE_ENUMERATION::CIM_UINT64:
            if (!fTypeCheck)
            {
                if (VARENUM::VT_BSTR == vtProp.vt)
                {
                    val = _tcstoull(WStrToTStr(vtProp.bstrVal).c_str(), NULL, 10);
                }
                else
                {
                    val = vtProp.ullVal;
                }
            }
            break;
        }
    }
    return val;
}

wmi_string CWmiClassHelper::GetString(const _tstring& strName, bool fTypeCheck/* = false*/) const
{
    HRESULT hr = S_OK;
    CComVariant vtProp;
    CIMTYPE cType = 0;
    wmi_string val;

    if (!m_pObj)
    {
        return val;
    }

    hr = m_pObj->Get(TStrToWStr(strName).c_str(), 0, &vtProp, &cType, 0);
    if (SUCCEEDED(hr))
    {
        if (VARENUM::VT_BSTR == vtProp.vt)
        {
            if (fTypeCheck)
            {
                if (CIMTYPE_ENUMERATION::CIM_STRING == cType)
                {
                    val = WStrToTStr(vtProp.bstrVal);
                }
            }
            else
            {
                val = WStrToTStr(vtProp.bstrVal);
            }
        }
    }
    return val;
}

wmi_datetime CWmiClassHelper::GetDatetime(const _tstring& strName) const
{
    HRESULT hr = S_OK;
    CComVariant vtProp;
    CIMTYPE cType = 0;
    wmi_datetime val;

    if (!m_pObj)
    {
        return val;
    }

    hr = m_pObj->Get(TStrToWStr(strName).c_str(), 0, &vtProp, &cType, nullptr);
    if (SUCCEEDED(hr))
    {
        if (CIMTYPE_ENUMERATION::CIM_DATETIME == cType && VARENUM::VT_BSTR == vtProp.vt)
        {
            _stscanf_s(WStrToTStr(vtProp.bstrVal).c_str(), DATETIME_FORMAT,
                &val.wYear, &val.wMonth, &val.wDay,
                &val.wHour, &val.wMinute, &val.wSecond,
                &val.nMicroseconds, &val.nMinutesUTC
            );
            val.wMilliseconds = val.nMicroseconds / 1000;
        }
    }
    return val;
}

bool CWmiClassHelper::_GetValue(
    const _tstring& strName,
    CIMTYPE ct,
    std::function<void(const CComVariant& vtProp)> cb
) const
{
    HRESULT hr = S_OK;
    CComVariant vtProp;
    CIMTYPE cType = 0;
    bool fResult = false;

    hr = m_pObj->Get(TStrToWStr(strName).c_str(), 0, &vtProp, &cType, 0);
    if (SUCCEEDED(hr))
    {
        if (cb && cType == ct)
        {
            cb(vtProp);
        }

        fResult = true;
    }
    return fResult;
}

bool CWmiClassHelper::_GetValueList(
    const _tstring& strName,
    CIMTYPE ct,
    VARTYPE vt,
    std::function<void(const void* pValue, UINT uElemsize, LONG count, VARTYPE vt)> cb
) const
{
    HRESULT hr = S_OK;
    CComVariant vtProp;
    CIMTYPE cType = 0;
    bool fResult = false;

    hr = m_pObj->Get(TStrToWStr(strName).c_str(), 0, &vtProp, &cType, 0);

    do
    {
        if (FAILED(hr))
        {
            break;
        }

        if (((CIM_FLAG_ARRAY | ct) == cType) && ((VARENUM::VT_ARRAY | vt) == vtProp.vt) && cb)
        {
            SAFEARRAY* pArray = vtProp.parray;
            LONG lLBound = 0;
            LONG lUBound = 0;
            UINT uDim = ::SafeArrayGetDim(pArray);
            if (1 != uDim)
            {
                break;
            }

            UINT uElemsize = ::SafeArrayGetElemsize(pArray);
            ::SafeArrayGetLBound(pArray, uDim, &lLBound);
            ::SafeArrayGetUBound(pArray, uDim, &lUBound);
            LONG lCount = lUBound - lLBound;

            void* pValue = nullptr;
            ::SafeArrayAccessData(pArray, (void**)&pValue);
            cb(pValue, uElemsize, lCount, vtProp.vt);
            ::SafeArrayUnaccessData(pArray);
        }

        fResult = true;
    } while (false);

    return fResult;
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_boolean& val) const
{
    val = false;

    if (!m_pObj)
    {
        return false;
    }

    return _GetValue(strName, CIMTYPE_ENUMERATION::CIM_BOOLEAN, [&val](const CComVariant& vtProp) {
        val = vtProp.boolVal;
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_sint8& val) const
{
    val = 0;

    if (!m_pObj)
    {
        return false;
    }

    return _GetValue(strName, CIMTYPE_ENUMERATION::CIM_SINT8, [&val](const CComVariant& vtProp) {
        val = vtProp.cVal;
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_uint8& val) const
{
    val = 0;

    if (!m_pObj)
    {
        return false;
    }

    return _GetValue(strName, CIMTYPE_ENUMERATION::CIM_UINT8, [&val](const CComVariant& vtProp) {
        val = vtProp.bVal;
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_sint16& val) const
{
    val = 0;

    if (!m_pObj)
    {
        return false;
    }

    return _GetValue(strName, CIMTYPE_ENUMERATION::CIM_SINT16, [&val](const CComVariant& vtProp) {
        val = vtProp.iVal;
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_uint16& val) const
{
    val = 0;

    if (!m_pObj)
    {
        return false;
    }

    return _GetValue(strName, CIMTYPE_ENUMERATION::CIM_UINT16, [&val](const CComVariant& vtProp) {
        val = vtProp.uiVal;
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_sint32& val) const
{
    val = 0;

    if (!m_pObj)
    {
        return false;
    }

    return _GetValue(strName, CIMTYPE_ENUMERATION::CIM_SINT32, [&val](const CComVariant& vtProp) {
        val = vtProp.intVal;
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_uint32& val) const
{
    val = 0;

    if (!m_pObj)
    {
        return false;
    }

    return _GetValue(strName, CIMTYPE_ENUMERATION::CIM_UINT32, [&val](const CComVariant& vtProp) {
        val = vtProp.uintVal;
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_sint64& val) const
{
    val = 0;

    if (!m_pObj)
    {
        return false;
    }

    return _GetValue(strName, CIMTYPE_ENUMERATION::CIM_SINT64, [&val](const CComVariant& vtProp) {
        if (VARENUM::VT_BSTR == vtProp.vt)
        {
            val = _tcstoll(WStrToTStr(vtProp.bstrVal).c_str(), NULL, 10);
        }
        else
        {
            val = vtProp.llVal;
        }
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_uint64& val) const
{
    val = 0;

    if (!m_pObj)
    {
        return false;
    }

    return _GetValue(strName, CIMTYPE_ENUMERATION::CIM_UINT64, [&val](const CComVariant& vtProp) {
        if (VARENUM::VT_BSTR == vtProp.vt)
        {
            val = _tcstoull(WStrToTStr(vtProp.bstrVal).c_str(), NULL, 10);
        }
        else
        {
            val = vtProp.ullVal;
        }
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_float& val) const
{
    val = 0.0f;

    if (!m_pObj)
    {
        return false;
    }

    return _GetValue(strName, CIMTYPE_ENUMERATION::CIM_REAL32, [&val](const CComVariant& vtProp) {
        val = vtProp.fltVal;
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_double& val) const
{
    val = 0.0f;

    if (!m_pObj)
    {
        return false;
    }

    return _GetValue(strName, CIMTYPE_ENUMERATION::CIM_REAL64, [&val](const CComVariant& vtProp) {
        if (VARENUM::VT_R8 == vtProp.vt)
        {
            val = vtProp.dblVal;
        }
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_string& val) const
{

    if (!m_pObj)
    {
        return false;
    }

    return _GetValue(strName, CIMTYPE_ENUMERATION::CIM_STRING, [&val](const CComVariant& vtProp) {
        if (VARENUM::VT_BSTR == vtProp.vt)
        {
            val = WStrToTStr(vtProp.bstrVal);
        }
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_datetime& val) const
{
    val.Clear();

    if (!m_pObj)
    {
        return false;
    }

    return _GetValue(strName, CIMTYPE_ENUMERATION::CIM_DATETIME, [&val](const CComVariant& vtProp) {
        if (VARENUM::VT_BSTR == vtProp.vt)
        {
            _stscanf_s(WStrToTStr(vtProp.bstrVal).c_str(), DATETIME_FORMAT,
                &val.wYear, &val.wMonth, &val.wDay,
                &val.wHour, &val.wMinute, &val.wSecond,
                &val.nMicroseconds, &val.nMinutesUTC
            );
            val.wMilliseconds = val.nMicroseconds / 1000;
        }
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_sint8_list& valList) const
{
    if (!m_pObj)
    {
        return false;
    }

    return _GetValueList(strName, CIMTYPE_ENUMERATION::CIM_SINT8, VARENUM::VT_I1, [&valList](const void* pValue, UINT uElemsize, LONG count, VARTYPE vt) {
        size_t pAddr = (uint64_t)pValue;
        for (LONG index = 0; index < count; index++)
        {
            valList.push_back(*(wmi_sint8*)pAddr);
            pAddr += uElemsize;
        }
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_uint8_list& valList) const
{
    if (!m_pObj)
    {
        return false;
    }

    return _GetValueList(strName, CIMTYPE_ENUMERATION::CIM_UINT8, VARENUM::VT_UI1, [&valList](const void* pValue, UINT uElemsize, LONG count, VARTYPE vt) {
        size_t pAddr = (uint64_t)pValue;
        for (LONG index = 0; index < count; index++)
        {
            valList.push_back(*(wmi_uint8*)pAddr);
            pAddr += uElemsize;
        }
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_sint16_list& valList) const
{
    if (!m_pObj)
    {
        return false;
    }

    return _GetValueList(strName, CIMTYPE_ENUMERATION::CIM_SINT16, VARENUM::VT_I4, [&valList](const void* pValue, UINT uElemsize, LONG count, VARTYPE vt) {
        size_t pAddr = (uint64_t)pValue;
        for (LONG index = 0; index < count; index++)
        {
            valList.push_back(*(wmi_sint32*)pAddr);
            pAddr += uElemsize;
        }
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_uint16_list& valList) const
{
    if (!m_pObj)
    {
        return false;
    }

    return _GetValueList(strName, CIMTYPE_ENUMERATION::CIM_UINT16, VARENUM::VT_I4, [&valList](const void* pValue, UINT uElemsize, LONG count, VARTYPE vt) {
        size_t pAddr = (uint64_t)pValue;
        for (LONG index = 0; index < count; index++)
        {
            valList.push_back(*(wmi_uint32*)pAddr);
            pAddr += uElemsize;
        }
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_sint32_list& valList) const
{
    if (!m_pObj)
    {
        return false;
    }

    return _GetValueList(strName, CIMTYPE_ENUMERATION::CIM_SINT32, VARENUM::VT_I4, [&valList](const void* pValue, UINT uElemsize, LONG count, VARTYPE vt) {
        size_t pAddr = (uint64_t)pValue;
        for (LONG index = 0; index < count; index++)
        {
            valList.push_back(*(wmi_sint32*)pAddr);
            pAddr += uElemsize;
        }
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_uint32_list& valList) const
{
    if (!m_pObj)
    {
        return false;
    }

    return _GetValueList(strName, CIMTYPE_ENUMERATION::CIM_UINT32, VARENUM::VT_UI4, [&valList](const void* pValue, UINT uElemsize, LONG count, VARTYPE vt) {
        size_t pAddr = (uint64_t)pValue;
        for (LONG index = 0; index < count; index++)
        {
            valList.push_back(*(wmi_uint32*)pAddr);
            pAddr += uElemsize;
        }
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_sint64_list& valList) const
{
    if (!m_pObj)
    {
        return false;
    }

    return _GetValueList(strName, CIMTYPE_ENUMERATION::CIM_SINT64, VARENUM::VT_BSTR, [&valList](const void* pValue, UINT uElemsize, LONG count, VARTYPE vt) {
        size_t pAddr = (uint64_t)pValue;
        for (LONG index = 0; index < count; index++)
        {
            valList.push_back(_tcstoll(WStrToTStr((BSTR)pAddr).c_str(), NULL, 10));
            pAddr += uElemsize;
        }
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_uint64_list& valList) const
{
    if (!m_pObj)
    {
        return false;
    }

    return _GetValueList(strName, CIMTYPE_ENUMERATION::CIM_UINT64, VARENUM::VT_BSTR, [&valList](const void* pValue, UINT uElemsize, LONG count, VARTYPE vt) {
        size_t pAddr = (uint64_t)pValue;
        for (LONG index = 0; index < count; index++)
        {
            valList.push_back(_tcstoull(WStrToTStr((BSTR)pAddr).c_str(), NULL, 10));
            pAddr += uElemsize;
        }
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_float_list& valList) const
{
    if (!m_pObj)
    {
        return false;
    }

    return _GetValueList(strName, CIMTYPE_ENUMERATION::CIM_REAL32, VARENUM::VT_R4, [&valList](const void* pValue, UINT uElemsize, LONG count, VARTYPE vt) {
        size_t pAddr = (uint64_t)pValue;
        for (LONG index = 0; index < count; index++)
        {
            valList.push_back(*(wmi_float*)pAddr);
            pAddr += uElemsize;
        }
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_double_list& valList) const
{
    if (!m_pObj)
    {
        return false;
    }

    return _GetValueList(strName, CIMTYPE_ENUMERATION::CIM_REAL64, VARENUM::VT_R8, [&valList](const void* pValue, UINT uElemsize, LONG count, VARTYPE vt) {
        size_t pAddr = (uint64_t)pValue;
        for (LONG index = 0; index < count; index++)
        {
            valList.push_back(*(wmi_double*)pAddr);
            pAddr += uElemsize;
        }
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_string_list& valList) const
{
    if (!m_pObj)
    {
        return false;
    }

    return _GetValueList(strName, CIMTYPE_ENUMERATION::CIM_STRING, VARENUM::VT_BSTR, [&valList](const void* pValue, UINT uElemsize, LONG count, VARTYPE vt) {
        size_t pAddr = (uint64_t)pValue;
        for (LONG index = 0; index < count; index++)
        {
            valList.push_back(WStrToTStr(*(BSTR*)pAddr));
            pAddr += uElemsize;
        }
        }
    );
}

bool CWmiClassHelper::GetValue(const _tstring& strName, wmi_datetime_list& valList) const
{
    if (!m_pObj)
    {
        return false;
    }

    return _GetValueList(strName, CIMTYPE_ENUMERATION::CIM_DATETIME, VARENUM::VT_BSTR, [&valList](const void* pValue, UINT uElemsize, LONG count, VARTYPE vt) {
        size_t pAddr = (uint64_t)pValue;
        for (LONG index = 0; index < count; index++)
        {
            wmi_datetime val;
            _stscanf_s(WStrToTStr(*(BSTR*)pAddr).c_str(), DATETIME_FORMAT,
                &val.wYear, &val.wMonth, &val.wDay,
                &val.wHour, &val.wMinute, &val.wSecond,
                &val.nMicroseconds, &val.nMinutesUTC
            );
            val.wMilliseconds = val.nMicroseconds / 1000;

            valList.push_back(val);
            pAddr += uElemsize;
        }
        }
    );
}

CIMTYPE CWmiClassHelper::GetCimType(const _tstring& strName) const
{
    if (!m_pObj)
    {
        return CIMTYPE_ENUMERATION::CIM_EMPTY;
    }

    HRESULT hr = S_OK;
    VARTYPE vType = VARENUM::VT_EMPTY;
    CIMTYPE cType = CIMTYPE_ENUMERATION::CIM_EMPTY;
    CComVariant vtProp;
    hr = m_pObj->Get(TStrToWStr(strName).c_str(), 0, &vtProp, &cType, 0);
    if (SUCCEEDED(hr))
    {
        vType = vtProp.vt;
    }
    return cType;
}

VARTYPE CWmiClassHelper::GetVarType(const _tstring& strName) const
{
    if (!m_pObj)
    {
        return VARENUM::VT_EMPTY;
    }

    HRESULT hr = S_OK;
    VARTYPE vType = VARENUM::VT_EMPTY;
    CIMTYPE cType = CIMTYPE_ENUMERATION::CIM_EMPTY;
    CComVariant vtProp;
    hr = m_pObj->Get(TStrToWStr(strName).c_str(), 0, &vtProp, &cType, 0);
    if (SUCCEEDED(hr))
    {
        vType = vtProp.vt;
    }
    return vType;
}

wmi_string CWmiClassHelper::GetClass() const
{
    return GetString(_T("__CLASS"));
}

wmi_string CWmiClassHelper::GetSuperClass() const
{
    return GetString(_T("__SUPERCLASS"));
}

wmi_string CWmiClassHelper::GetNameSpace() const
{
    return GetString(_T("__NAMESPACE"));
}

wmi_string CWmiClassHelper::GetPath() const
{
    return GetString(_T("__PATH"));
}

wmi_string CWmiClassHelper::GetServer() const
{
    return GetString(_T("__SERVER"));
}

wmi_string CWmiClassHelper::GetRelPath() const
{
    return GetString(_T("__RELPATH"));
}

wmi_sint32 CWmiClassHelper::GetPropertyCount() const
{
    return GetSInt(_T("__PROPERTY_COUNT"));
}

wmi_sint32 CWmiClassHelper::GetGenus() const
{
    return GetSInt(_T("__GENUS"));
}

wmi_string CWmiClassHelper::GetDynasty() const
{
    return GetString(_T("__DYNASTY"));
}

wmi_string CWmiClassHelper::GetDerivation() const
{
    return GetString(_T("__DERIVATION"));
}

void CWmiClassHelper::PrintPropertySystemOnly() const
{
    _PrintProperty(WBEM_FLAG_ALWAYS | WBEM_FLAG_SYSTEM_ONLY);
}

void CWmiClassHelper::PrintPropertyNonSystemOnly() const
{
    _PrintProperty(WBEM_FLAG_ALWAYS | WBEM_FLAG_NONSYSTEM_ONLY);
}

void CWmiClassHelper::PrintProperty() const
{
    _PrintProperty(WBEM_FLAG_ALWAYS);
}

CWmiHelper::CWmiHelper() :
    m_pSvc(NULL),
    m_pLoc(NULL),
    m_bInit(false)
{

}

CWmiHelper::~CWmiHelper()
{
    Uninitialize();
}

bool CWmiHelper::Initialize(_tstring strNamespace/* = _T(R"(ROOT\CIMV2)")*/)
{
    HRESULT hr = S_OK;

    if (m_bInit)
    {
        return true;
    }

    hr = ::CoInitializeEx(0, COINIT_MULTITHREADED);
    if (FAILED(hr))
    {
        return false;
    }

    do
    {
        hr = CoInitializeSecurity(
            NULL,
            -1,                          // COM authentication
            NULL,                        // Authentication services
            NULL,                        // Reserved
            RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 
            RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
            NULL,                        // Authentication info
            EOAC_NONE,                   // Additional capabilities 
            NULL                         // Reserved
        );

        hr = ::CoCreateInstance(
            CLSID_WbemLocator,
            0,
            CLSCTX_INPROC_SERVER,
            IID_IWbemLocator, (LPVOID*)&m_pLoc);
        if (FAILED(hr))
        {
            break;
        }

        hr = m_pLoc->ConnectServer(
            _bstr_t(TStrToWStr(strNamespace).c_str()),    // Object path of WMI namespace
            NULL,                       // User name. NULL = current user
            NULL,                       // User password. NULL = current
            0,                          // Locale. NULL indicates current
            NULL,                       // Security flags.
            0,                          // Authority (for example, Kerberos)
            0,                          // Context object 
            &m_pSvc                     // pointer to IWbemServices proxy
        );
        if (FAILED(hr))
        {
            break;
        }

        hr = ::CoSetProxyBlanket(
            m_pSvc,                      // Indicates the proxy to set
            RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
            RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
            NULL,                        // Server principal name 
            RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 
            RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
            NULL,                        // client identity
            EOAC_NONE                    // proxy capabilities 
        );
        if (FAILED(hr))
        {
            break;
        }

        m_bInit = true;

    } while (false);

    if (!m_bInit)
    {
        if (m_pSvc)
        {
            m_pSvc->Release();
            m_pSvc = NULL;
        }

        if (m_pLoc)
        {
            m_pLoc->Release();
            m_pLoc = NULL;
        }

        ::CoUninitialize();
    }

    return m_bInit;
}

void CWmiHelper::Uninitialize()
{
    if (m_bInit)
    {
        if (m_pSvc)
        {
            m_pSvc->Release();
            m_pSvc = NULL;
        }

        if (m_pLoc)
        {
            m_pLoc->Release();
            m_pLoc = NULL;
        }

        ::CoUninitialize();

        m_bInit = false;
    }
}

bool CWmiHelper::Query(
    const _tstring& strWql,
    std::function<void(const CWmiClassHelper& obj)> cb/* = nullptr*/
) const
{
    HRESULT hr = S_OK;
    IEnumWbemClassObject* pEnumerator = NULL;

    if (!m_bInit)
    {
        return false;
    }

    hr = m_pSvc->ExecQuery(
        bstr_t(_T("WQL")),
        bstr_t(strWql.c_str()),
        WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
        NULL,
        &pEnumerator);

    if (FAILED(hr))
    {
        return false;
    }

    IWbemClassObject* pObj = NULL;
    ULONG uReturn = 0;

    while (true)
    {
        if (FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pObj, &uReturn)))
        {
            break;
        }

        if (0 == uReturn)
        {
            break;
        }

        CWmiClassHelper classObj(pObj);
        if (cb)
        {
            cb(classObj);
        }

        pObj->Release();
    }

    pEnumerator->Release();
    pEnumerator = NULL;

    return true;
}

bool CWmiHelper::QueryClass(
    const _tstring& strClass,
    std::function<void(const CWmiClassHelper& obj)> cb/* = nullptr*/
) const
{
    wmi_string strSql = _T("SELECT * FROM ") + strClass;
    return Query(strSql, cb);
}

bool CWmiHelper::QueryClassWithNames(
    const _tstring& strClass,
    std::set<wmi_string> names/* = {}*/,
    std::function<void(const CWmiClassHelper& obj)> cb/* = nullptr*/
) const
{
    wmi_string strSql = _T("SELECT * FROM ") + strClass;
    if (!names.empty())
    {
        strSql = _T("SELECT ");

        size_t count = names.size();
        for (const auto& item : names)
        {
            strSql += item;
            count--;
            if (count)
            {
                strSql += _T(", ");
            }
        }

        strSql += _T(" FROM ");
        strSql += strClass;
    }

    return Query(strSql, cb);
}

bool CWmiHelper::QueryClassWithoutNames(
    const _tstring& strClass,
    std::set<wmi_string> names/* = {}*/,
    std::function<void(const CWmiClassHelper& obj)> cb/* = nullptr*/
) const
{
    wmi_string strSql = _T("SELECT * FROM ") + strClass;
    if (!names.empty())
    {
        std::set<wmi_string> nameList = QueryClassNames(strClass);
        for (const auto& item : names)
        {
            auto itFind = nameList.find(item);
            if (itFind != nameList.end())
            {
                nameList.erase(itFind);
            }
        }

        // 没有查询任何字段
        if (nameList.empty())
        {
            return false;
        }

        strSql = _T("SELECT ");
        size_t count = nameList.size();
        for (const auto& item : nameList)
        {
            strSql += item;
            count--;
            if (count)
            {
                strSql += _T(", ");
            }
        }

        strSql += _T(" FROM ");
        strSql += strClass;
    }

    return Query(strSql, cb);
}

std::set<wmi_string> CWmiHelper::QueryClassNames(const _tstring& strClass) const
{
    std::set<wmi_string> result;
    HRESULT hr = S_OK;

    IWbemClassObject* pClass = NULL;

    do
    {
        if (!m_bInit)
        {
            break;
        }

        hr = m_pSvc->GetObject(_bstr_t(strClass.c_str()), 0, NULL, &pClass, NULL);
        if (FAILED(hr))
        {
            break;
        }

        SAFEARRAY* pNames = NULL;
        hr = pClass->GetNames(NULL, WBEM_FLAG_ALWAYS | WBEM_FLAG_NONSYSTEM_ONLY, NULL, &pNames);
        if (FAILED(hr))
        {
            break;
        }

        LONG lLBound = 0;
        LONG lUBound = 0;
        UINT uDim = ::SafeArrayGetDim(pNames);
        ::SafeArrayGetLBound(pNames, uDim, &lLBound);
        ::SafeArrayGetUBound(pNames, uDim, &lUBound);

        BSTR* pValue;
        ::SafeArrayAccessData(pNames, (void**)&pValue);
        for (int i = 0; i <= lUBound - lLBound; i++)
        {
            result.insert(WStrToTStr(*pValue).c_str());
            pValue++;
        }
        ::SafeArrayUnaccessData(pNames);
        ::SafeArrayDestroy(pNames);
    } while (false);

    if (pClass)
    {
        pClass->Release();
    }

    return result;
}

例子

1.获取单独物理硬盘, 磁盘分区, 逻辑磁盘信息

2.获取磁盘信息(包含每个物理磁盘的分区与逻辑磁盘)

Win32_DiskDrive.h

#pragma once
#include "Win32_Define.h"

// https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-diskdrive
typedef struct _Win32_DiskDrive
{
    wmi_uint16                Availability;
    wmi_uint32                BytesPerSector;
    wmi_uint16_list           Capabilities;
    wmi_string_list           CapabilityDescriptions;
    wmi_string                Caption;
    wmi_string                CompressionMethod;
    wmi_uint32                ConfigManagerErrorCode;
    wmi_boolean               ConfigManagerUserConfig;
    wmi_string                CreationClassName;
    wmi_uint64                DefaultBlockSize;
    wmi_string                Description;
    wmi_string                DeviceID;
    wmi_boolean               ErrorCleared;
    wmi_string                ErrorDescription;
    wmi_string                ErrorMethodology;
    wmi_string                FirmwareRevision;
    wmi_uint32                Index;
    wmi_datetime              InstallDate;
    wmi_string                InterfaceType;
    wmi_uint32                LastErrorCode;
    wmi_string                Manufacturer;
    wmi_uint64                MaxBlockSize;
    wmi_uint64                MaxMediaSize;
    wmi_boolean               MediaLoaded;
    wmi_string                MediaType;
    wmi_uint64                MinBlockSize;
    wmi_string                Model;
    wmi_string                Name;
    wmi_boolean               NeedsCleaning;
    wmi_uint32                NumberOfMediaSupported;
    wmi_uint32                Partitions;
    wmi_string                PNPDeviceID;
    wmi_uint16_list           PowerManagementCapabilitiesx;
    wmi_boolean               PowerManagementSupported;
    wmi_uint32                SCSIBus;
    wmi_uint16                SCSILogicalUnit;
    wmi_uint16                SCSIPort;
    wmi_uint16                SCSITargetId;
    wmi_uint32                SectorsPerTrack;
    wmi_string                SerialNumber;
    wmi_uint32                Signature;
    wmi_uint64                Size;
    wmi_string                Status;
    wmi_uint16                StatusInfo;
    wmi_string                SystemCreationClassName;
    wmi_string                SystemName;
    wmi_uint64                TotalCylinders;
    wmi_uint32                TotalHeads;
    wmi_uint64                TotalSectors;
    wmi_uint64                TotalTracks;
    wmi_uint32                TracksPerCylinder;
}Win32_DiskDrive;

Win32_DiskPartition.h

#pragma once
#include "Win32_Define.h"

// https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-diskpartition
typedef struct _Win32_DiskPartition
{
    wmi_uint16                AdditionalAvailability;
    wmi_uint16                Availability;
    wmi_uint16_list           PowerManagementCapabilities;
    wmi_string_list           IdentifyingDescriptions;
    wmi_uint64                MaxQuiesceTime;
    wmi_uint64                OtherIdentifyingInfo;
    wmi_uint16                StatusInfo;
    wmi_uint64                PowerOnHours;
    wmi_uint64                TotalPowerOnHours;
    wmi_uint16                Access;
    wmi_uint64                BlockSize;
    wmi_boolean               Bootable;
    wmi_boolean               BootPartition;
    wmi_string                Caption;
    wmi_uint32                ConfigManagerErrorCode;
    wmi_boolean               ConfigManagerUserConfig;
    wmi_string                CreationClassName;
    wmi_string                Description;
    wmi_string                DeviceID;
    wmi_uint32                DiskIndex;
    wmi_boolean               ErrorCleared;
    wmi_string                ErrorDescription;
    wmi_string                ErrorMethodology;
    wmi_uint32                HiddenSectors;
    wmi_uint32                Index;
    wmi_datetime              InstallDate;
    wmi_uint32                LastErrorCode;
    wmi_string                Name;
    wmi_uint64                NumberOfBlocks;
    wmi_string                PNPDeviceID;
    wmi_boolean               PowerManagementSupported;
    wmi_boolean               PrimaryPartition;
    wmi_string                Purpose;
    wmi_boolean               RewritePartition;
    wmi_uint64                Size;
    wmi_uint64                StartingOffset;
    wmi_string                Status;
    wmi_string                SystemCreationClassName;
    wmi_string                SystemName;
    wmi_string                Type;
}Win32_DiskPartition;

Win32_LogicalDisk.h

#pragma once
#include "Win32_Define.h"

// https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-logicaldisk
typedef struct _Win32_LogicalDisk
{
	wmi_uint16              Access;
	wmi_uint16              Availability;
	wmi_uint64              BlockSize;
	wmi_string              Caption;
	wmi_boolean             Compressed;
	wmi_uint32              ConfigManagerErrorCode;
	wmi_boolean             ConfigManagerUserConfig;
	wmi_string              CreationClassName;
	wmi_string              Description;
	wmi_string              DeviceID;
	wmi_uint32              DriveType;
	wmi_boolean             ErrorCleared;
	wmi_string              ErrorDescription;
	wmi_string              ErrorMethodology;
	wmi_string              FileSystem;
	wmi_uint64              FreeSpace;
	wmi_datetime            InstallDate;
	wmi_uint32              LastErrorCode;
	wmi_uint32              MaximumComponentLength;
	wmi_uint32              MediaType;
	wmi_string              Name;
	wmi_uint64              NumberOfBlocks;
	wmi_string              PNPDeviceID;
	wmi_uint16_list         PowerManagementCapabilities;
	wmi_boolean             PowerManagementSupported;
	wmi_string              ProviderName;
	wmi_string              Purpose;
	wmi_boolean             QuotasDisabled;
	wmi_boolean             QuotasIncomplete;
	wmi_boolean             QuotasRebuilding;
	wmi_uint64              Size;
	wmi_string              Status;
	wmi_uint16              StatusInfo;
	wmi_boolean             SupportsDiskQuotas;
	wmi_boolean             SupportsFileBasedCompression;
	wmi_string              SystemCreationClassName;
	wmi_string              SystemName;
	wmi_boolean             VolumeDirty;
	wmi_string              VolumeName;
	wmi_string              VolumeSerialNumber;
}Win32_LogicalDisk;

 Win32_DiskPartitionInformation.h

#pragma once
#include "Win32_Define.h"
#include "Win32_DiskPartition.h"
#include "Win32_DiskDrive.h"
#include "Win32_LogicalDisk.h"

typedef struct _Win32_DiskPartitionInformation
{
	wmi_uint32 DiskIndex;
	wmi_uint32 PartitionIndex;
	wmi_string LogicalName;
	wmi_string VolumeName;
	wmi_string PartitionName;
	Win32_DiskPartition DiskPartition;
	Win32_LogicalDisk LogicalDisk;
}Win32_DiskPartitionInformation;

typedef struct _Win32_DiskInformation
{
	Win32_DiskDrive DiskDrive;
	std::map<wmi_uint32, Win32_DiskPartitionInformation> PartitionInformation;
}Win32_DiskInformation;

CWmiWin32Class.h

#pragma once
#include <vector>
#include <map>
#include "../Win32Utils/CWmiHelper.h"

#include "Win32_DiskPartition.h"
#include "Win32_DiskDrive.h"
#include "Win32_LogicalDisk.h"
#include "Win32_DiskPartitionInformation.h"

class CWmiWin32Class
{
public:

    CWmiWin32Class();
    ~CWmiWin32Class();

    std::map<wmi_string, Win32_DiskPartition> GetDiskPartition() const;
    std::map<wmi_string, Win32_DiskDrive> GetDiskDrive() const;
    std::map<wmi_string, Win32_LogicalDisk> GetLogicalDisk() const;
    std::map<wmi_uint32, Win32_DiskInformation> GetDiskInformation() const;
    std::map<wmi_uint32, Win32_DiskInformation> GetDiskInformationEx() const;

private:
    static void Get_Win32_Value(const CWmiClassHelper& obj, Win32_DiskPartition& result);
    static void Get_Win32_Value(const CWmiClassHelper& obj, Win32_DiskDrive& result);
    static void Get_Win32_Value(const CWmiClassHelper& obj, Win32_LogicalDisk& result);

private:

    CWmiHelper m_WmiHelper;
};

CWmiWin32Class.cpp

#include "CWmiWin32Class.h"

CWmiWin32Class::CWmiWin32Class()
{
    m_WmiHelper.Initialize();
}

CWmiWin32Class::~CWmiWin32Class()
{
    m_WmiHelper.Uninitialize();
}

std::map<wmi_string, Win32_DiskPartition> CWmiWin32Class::GetDiskPartition() const
{
    std::map<wmi_string, Win32_DiskPartition> resultList;
    m_WmiHelper.QueryClass(_T("Win32_DiskPartition"), [&resultList](const CWmiClassHelper& obj) {
        Win32_DiskPartition result;
        Get_Win32_Value(obj, result);
        resultList.emplace(result.DeviceID, result);
        }
    );

    return resultList;
}

std::map<wmi_string, Win32_DiskDrive> CWmiWin32Class::GetDiskDrive() const
{
    std::map<wmi_string, Win32_DiskDrive> resultList;
    m_WmiHelper.QueryClass(_T("Win32_DiskDrive"), [&resultList](const CWmiClassHelper& obj) {
        Win32_DiskDrive result;
        Get_Win32_Value(obj, result);
        resultList.emplace(result.DeviceID, result);
        }
    );

    return resultList;
}

std::map<wmi_string, Win32_LogicalDisk> CWmiWin32Class::GetLogicalDisk() const
{
    std::map<wmi_string, Win32_LogicalDisk> resultList;
    m_WmiHelper.QueryClass(_T("Win32_LogicalDisk"), [&resultList](const CWmiClassHelper& obj) {
        Win32_LogicalDisk result;
        Get_Win32_Value(obj, result);
        resultList.emplace(result.DeviceID, result);
        }
    );

    return resultList;
}

std::map<wmi_uint32, Win32_DiskInformation> CWmiWin32Class::GetDiskInformation() const
{
    std::map<wmi_uint32, Win32_DiskInformation> resultList;
    std::map<wmi_string, Win32_DiskDrive> DiskDrive = GetDiskDrive();

    for (const auto& Drive : DiskDrive)
    {
        wmi_string strWql = _T("Associators of {Win32_DiskDrive.DeviceID=\'");
        strWql += Drive.first;
        strWql += _T("\'} where AssocClass=Win32_DiskDriveToDiskPartition");
        Win32_DiskInformation DiskDriveResult;

        DiskDriveResult.DiskDrive = Drive.second;

        m_WmiHelper.Query(strWql, [this, &resultList, &DiskDriveResult](const CWmiClassHelper& obj) {
            Win32_DiskPartitionInformation DiskPartitionVolume;
            Get_Win32_Value(obj, DiskPartitionVolume.DiskPartition);
            DiskPartitionVolume.PartitionName = DiskPartitionVolume.DiskPartition.DeviceID;

            DiskPartitionVolume.DiskIndex = DiskPartitionVolume.DiskPartition.DiskIndex;
            DiskPartitionVolume.PartitionIndex = DiskPartitionVolume.DiskPartition.Index;

            CWmiClassHelper objEmpty(nullptr);
            Get_Win32_Value(objEmpty, DiskPartitionVolume.LogicalDisk);

            wmi_string strWql = _T("Associators of {Win32_DiskPartition.DeviceID=\'");
            strWql += DiskPartitionVolume.DiskPartition.DeviceID;
            strWql += _T("\'} where AssocClass=Win32_LogicalDiskToPartition");

            m_WmiHelper.Query(strWql, [&resultList, &DiskDriveResult, &DiskPartitionVolume](const CWmiClassHelper& obj) {
                Get_Win32_Value(obj, DiskPartitionVolume.LogicalDisk);
                DiskPartitionVolume.LogicalName = DiskPartitionVolume.LogicalDisk.DeviceID;
                DiskPartitionVolume.VolumeName = DiskPartitionVolume.LogicalDisk.VolumeName;

                }
            );

            DiskDriveResult.PartitionInformation.emplace(DiskPartitionVolume.DiskPartition.Index, DiskPartitionVolume);
            }
        );

        resultList.emplace(Drive.second.Index, DiskDriveResult);
    }

    return resultList;
}

std::map<wmi_uint32, Win32_DiskInformation> CWmiWin32Class::GetDiskInformationEx() const
{
    std::map<wmi_uint32, Win32_DiskInformation> resultList;
    std::map<wmi_string, Win32_DiskDrive> DiskDrive = GetDiskDrive();
    std::map<wmi_string, Win32_DiskPartition> DiskPartition = GetDiskPartition();
    std::map<wmi_string, Win32_LogicalDisk> LogicalDisk = GetLogicalDisk();
    std::map<wmi_string, wmi_string> LogicalDiskToPartition;

    // 获取 分区 -> 卷标 映射信息
    m_WmiHelper.QueryClass(_T("Win32_LogicalDiskToPartition"), [this, &LogicalDiskToPartition](const CWmiClassHelper& obj) {
        auto _GetValueFromKeyname = [](const wmi_string& val) {
            size_t nPos = val.find_last_of(_T("="));
            if (wmi_string::npos == nPos)
            {
                return wmi_string();
            }

            wmi_string result = val.substr(nPos + 1);
            if (result.size() >= 2 && _T('\"') == result.front() && _T('\"') == result.back())
            {
                result = result.substr(1, result.size() - 2);
            }

            return result;
            
            };

        wmi_string Antecedent = obj.GetString(_T("Antecedent"));
        wmi_string Dependent = obj.GetString(_T("Dependent"));
        wmi_string Partition = _GetValueFromKeyname(Antecedent);
        wmi_string Logical = _GetValueFromKeyname(Dependent);
        LogicalDiskToPartition.emplace(Partition, Logical);
        }
    );

    // 遍历磁盘信息
    for (const auto& Drive : DiskDrive)
    {
        Win32_DiskInformation DiskInformation;
        DiskInformation.DiskDrive = Drive.second;

        // 遍历分区信息
        for (const auto& Partition : DiskPartition)
        {
            // 检查磁盘所属分区
            if (Partition.second.DiskIndex != Drive.second.Index)
            {
                continue;
            }

            Win32_DiskPartitionInformation DiskPartitionInformation;
            DiskPartitionInformation.DiskPartition = Partition.second;
            DiskPartitionInformation.PartitionName = Partition.first;

            CWmiClassHelper obj(nullptr);
            Get_Win32_Value(obj, DiskPartitionInformation.LogicalDisk);
            DiskPartitionInformation.DiskIndex = Partition.second.DiskIndex;
            DiskPartitionInformation.PartitionIndex = Partition.second.Index;

            // 查找磁盘分区所在卷标
            auto itPartition = LogicalDiskToPartition.find(Partition.first);
            if (LogicalDiskToPartition.end() != itPartition)
            {
                // 查找卷标所在逻辑磁盘信息
                auto itLogical = LogicalDisk.find(itPartition->second);
                if (LogicalDisk.end() != itLogical)
                {
                    DiskPartitionInformation.LogicalName = itLogical->second.DeviceID;
                    DiskPartitionInformation.VolumeName = itLogical->second.VolumeName;
                    DiskPartitionInformation.LogicalDisk = itLogical->second;
                }
            }

            DiskInformation.PartitionInformation.emplace(Partition.second.Index, DiskPartitionInformation);
        }

        resultList.emplace(Drive.second.Index, DiskInformation);
    }

    return resultList;
}

 CWmiWin32ClassImplement.cpp

#include "CWmiWin32Class.h"

#define WMI_GET_VALUE(_obj, _out, _name) _obj.GetValue(_T(#_name), _out._name)

void CWmiWin32Class::Get_Win32_Value(const CWmiClassHelper& obj, Win32_DiskPartition& result)
{
    WMI_GET_VALUE(obj, result, AdditionalAvailability);
    WMI_GET_VALUE(obj, result, Availability);
    WMI_GET_VALUE(obj, result, PowerManagementCapabilities);
    WMI_GET_VALUE(obj, result, IdentifyingDescriptions);
    WMI_GET_VALUE(obj, result, MaxQuiesceTime);
    WMI_GET_VALUE(obj, result, OtherIdentifyingInfo);
    WMI_GET_VALUE(obj, result, StatusInfo);
    WMI_GET_VALUE(obj, result, PowerOnHours);
    WMI_GET_VALUE(obj, result, TotalPowerOnHours);
    WMI_GET_VALUE(obj, result, Access);
    WMI_GET_VALUE(obj, result, BlockSize);
    WMI_GET_VALUE(obj, result, Bootable);
    WMI_GET_VALUE(obj, result, BootPartition);
    WMI_GET_VALUE(obj, result, Caption);
    WMI_GET_VALUE(obj, result, ConfigManagerErrorCode);
    WMI_GET_VALUE(obj, result, ConfigManagerUserConfig);
    WMI_GET_VALUE(obj, result, CreationClassName);
    WMI_GET_VALUE(obj, result, Description);
    WMI_GET_VALUE(obj, result, DeviceID);
    WMI_GET_VALUE(obj, result, DiskIndex);
    WMI_GET_VALUE(obj, result, ErrorCleared);
    WMI_GET_VALUE(obj, result, ErrorDescription);
    WMI_GET_VALUE(obj, result, ErrorMethodology);
    WMI_GET_VALUE(obj, result, HiddenSectors);
    WMI_GET_VALUE(obj, result, Index);
    WMI_GET_VALUE(obj, result, InstallDate);
    WMI_GET_VALUE(obj, result, LastErrorCode);
    WMI_GET_VALUE(obj, result, Name);
    WMI_GET_VALUE(obj, result, NumberOfBlocks);
    WMI_GET_VALUE(obj, result, PNPDeviceID);
    WMI_GET_VALUE(obj, result, PowerManagementSupported);
    WMI_GET_VALUE(obj, result, PrimaryPartition);
    WMI_GET_VALUE(obj, result, Purpose);
    WMI_GET_VALUE(obj, result, RewritePartition);
    WMI_GET_VALUE(obj, result, Size);
    WMI_GET_VALUE(obj, result, StartingOffset);
    WMI_GET_VALUE(obj, result, Status);
    WMI_GET_VALUE(obj, result, SystemCreationClassName);
    WMI_GET_VALUE(obj, result, SystemName);
    WMI_GET_VALUE(obj, result, Type);
}

void CWmiWin32Class::Get_Win32_Value(const CWmiClassHelper& obj, Win32_DiskDrive& result)
{
    WMI_GET_VALUE(obj, result, Availability);
    WMI_GET_VALUE(obj, result, BytesPerSector);
    WMI_GET_VALUE(obj, result, Capabilities);
    WMI_GET_VALUE(obj, result, CapabilityDescriptions);
    WMI_GET_VALUE(obj, result, Caption);
    WMI_GET_VALUE(obj, result, CompressionMethod);
    WMI_GET_VALUE(obj, result, ConfigManagerErrorCode);
    WMI_GET_VALUE(obj, result, ConfigManagerUserConfig);
    WMI_GET_VALUE(obj, result, CreationClassName);
    WMI_GET_VALUE(obj, result, DefaultBlockSize);
    WMI_GET_VALUE(obj, result, Description);
    WMI_GET_VALUE(obj, result, DeviceID);
    WMI_GET_VALUE(obj, result, ErrorCleared);
    WMI_GET_VALUE(obj, result, ErrorDescription);
    WMI_GET_VALUE(obj, result, ErrorMethodology);
    WMI_GET_VALUE(obj, result, FirmwareRevision);
    WMI_GET_VALUE(obj, result, Index);
    WMI_GET_VALUE(obj, result, InstallDate);
    WMI_GET_VALUE(obj, result, InterfaceType);
    WMI_GET_VALUE(obj, result, LastErrorCode);
    WMI_GET_VALUE(obj, result, Manufacturer);
    WMI_GET_VALUE(obj, result, MaxBlockSize);
    WMI_GET_VALUE(obj, result, MaxMediaSize);
    WMI_GET_VALUE(obj, result, MediaLoaded);
    WMI_GET_VALUE(obj, result, MediaType);
    WMI_GET_VALUE(obj, result, MinBlockSize);
    WMI_GET_VALUE(obj, result, Model);
    WMI_GET_VALUE(obj, result, Name);
    WMI_GET_VALUE(obj, result, NeedsCleaning);
    WMI_GET_VALUE(obj, result, NumberOfMediaSupported);
    WMI_GET_VALUE(obj, result, Partitions);
    WMI_GET_VALUE(obj, result, PNPDeviceID);
    WMI_GET_VALUE(obj, result, PowerManagementCapabilitiesx);
    WMI_GET_VALUE(obj, result, PowerManagementSupported);
    WMI_GET_VALUE(obj, result, SCSIBus);
    WMI_GET_VALUE(obj, result, SCSILogicalUnit);
    WMI_GET_VALUE(obj, result, SCSIPort);
    WMI_GET_VALUE(obj, result, SCSITargetId);
    WMI_GET_VALUE(obj, result, SectorsPerTrack);
    WMI_GET_VALUE(obj, result, SerialNumber);
    WMI_GET_VALUE(obj, result, Signature);
    WMI_GET_VALUE(obj, result, Size);
    WMI_GET_VALUE(obj, result, Status);
    WMI_GET_VALUE(obj, result, StatusInfo);
    WMI_GET_VALUE(obj, result, SystemCreationClassName);
    WMI_GET_VALUE(obj, result, SystemName);
    WMI_GET_VALUE(obj, result, TotalCylinders);
    WMI_GET_VALUE(obj, result, TotalHeads);
    WMI_GET_VALUE(obj, result, TotalSectors);
    WMI_GET_VALUE(obj, result, TotalTracks);
    WMI_GET_VALUE(obj, result, TracksPerCylinder);
}

void CWmiWin32Class::Get_Win32_Value(const CWmiClassHelper& obj, Win32_LogicalDisk& result)
{
    WMI_GET_VALUE(obj, result, Access);
    WMI_GET_VALUE(obj, result, Availability);
    WMI_GET_VALUE(obj, result, BlockSize);
    WMI_GET_VALUE(obj, result, Caption);
    WMI_GET_VALUE(obj, result, Compressed);
    WMI_GET_VALUE(obj, result, ConfigManagerErrorCode);
    WMI_GET_VALUE(obj, result, ConfigManagerUserConfig);
    WMI_GET_VALUE(obj, result, CreationClassName);
    WMI_GET_VALUE(obj, result, Description);
    WMI_GET_VALUE(obj, result, DeviceID);
    WMI_GET_VALUE(obj, result, DriveType);
    WMI_GET_VALUE(obj, result, ErrorCleared);
    WMI_GET_VALUE(obj, result, ErrorDescription);
    WMI_GET_VALUE(obj, result, ErrorMethodology);
    WMI_GET_VALUE(obj, result, FileSystem);
    WMI_GET_VALUE(obj, result, FreeSpace);
    WMI_GET_VALUE(obj, result, InstallDate);
    WMI_GET_VALUE(obj, result, LastErrorCode);
    WMI_GET_VALUE(obj, result, MaximumComponentLength);
    WMI_GET_VALUE(obj, result, MediaType);
    WMI_GET_VALUE(obj, result, Name);
    WMI_GET_VALUE(obj, result, NumberOfBlocks);
    WMI_GET_VALUE(obj, result, PNPDeviceID);
    WMI_GET_VALUE(obj, result, PowerManagementCapabilities);
    WMI_GET_VALUE(obj, result, PowerManagementSupported);
    WMI_GET_VALUE(obj, result, ProviderName);
    WMI_GET_VALUE(obj, result, Purpose);
    WMI_GET_VALUE(obj, result, QuotasDisabled);
    WMI_GET_VALUE(obj, result, QuotasIncomplete);
    WMI_GET_VALUE(obj, result, QuotasRebuilding);
    WMI_GET_VALUE(obj, result, Size);
    WMI_GET_VALUE(obj, result, Status);
    WMI_GET_VALUE(obj, result, StatusInfo);
    WMI_GET_VALUE(obj, result, SupportsDiskQuotas);
    WMI_GET_VALUE(obj, result, SupportsFileBasedCompression);
    WMI_GET_VALUE(obj, result, SystemCreationClassName);
    WMI_GET_VALUE(obj, result, SystemName);
    WMI_GET_VALUE(obj, result, VolumeDirty);
    WMI_GET_VALUE(obj, result, VolumeName);
    WMI_GET_VALUE(obj, result, VolumeSerialNumber);
}

main.cpp

#include <iostream>
#include <locale>
#include "CWin32Class/CWmiWin32Class.h"

int main()
{
    CWmiWin32Class obj;

    std::map<wmi_string, Win32_DiskPartition> diskPartList;
    std::map<wmi_string, Win32_DiskDrive> diskDriveList;
    std::map<wmi_uint32, Win32_DiskInformation> DiskInformation;
    std::map<wmi_string, Win32_LogicalDisk> LogicalDisk;

    while (true)
    {
        clock_t tmBegin = ::clock();
        clock_t tmEnd = ::clock();
        for (int i = 0; i < 1; i++)
        {
            LogicalDisk = obj.GetLogicalDisk();
            DiskInformation = obj.GetDiskInformationEx();
            diskPartList = obj.GetDiskPartition();
            diskDriveList = obj.GetDiskDrive();
        }
        tmEnd = ::clock();
        printf("cost time: %d\n", tmEnd - tmBegin);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值