VC++ VARINAT(可变量类型)操作

提供可变数组封装、可变类型数值/字符串获取等。

头文件:

#pragma once

#include <ccc/stdafx.h>

#include <comdef.h>
#include <comutil.h>
#include <Wbemidl.h>

namespace ccc
{
    namespace win32
    {
        bool                       Win32Variant_Callvirt(IWbemServices* services, IWbemClassObject* obj, const _bstr_t& clazz, const _bstr_t& method, ccc::function<bool(IWbemClassObject*)>&& internal_call) noexcept;
         
        inline ccc::string         VARIANT_string(BSTR& bstrVal)
        {
            ccc::string result;
            LPSTR str = _com_util::ConvertBSTRToString(bstrVal);
            if (NULL != str)
            {
                result = str;
                delete[] str;
            }

            SysFreeString(bstrVal);
            return result;
        }
         
        inline ccc::string         VARIANT_string(VARIANT& vt) noexcept
        {
            ccc::string result;
            if (vt.vt & VT_BSTR)
            {
                result = VARIANT_string(vt.bstrVal);
            }

            if (vt.vt != VT_EMPTY)
            {
                VariantClear(&vt);
            }

            return result;
        }
         
        inline ccc::string         VARIANT_string(IWbemClassObject* obj, LPCWSTR name) noexcept
        {
            VARIANT vt;
            VariantInit(&vt);

            HRESULT hr = obj->Get(name, 0, &vt, 0, 0);
            if (SUCCEEDED(hr))
            {
                ccc::string result = VARIANT_string(vt);
                VariantClear(&vt);
                return result;
            }
            else
            {
                VariantClear(&vt);
                return ccc::string();
            }
        }
         
        template <typename T>
        inline T                   VARIANT_value(VARIANT& vt, T defaultValue) noexcept
        {
            if (vt.vt == VT_I1)
            {
                return vt.cVal;
            }

            if (vt.vt == VT_I2)
            {
                return vt.iVal;
            }

            if (vt.vt == VT_I4)
            {
                return vt.intVal;
            }

            if (vt.vt == VT_I8)
            {
                return vt.llVal;
            }

            if (vt.vt == VT_UI1)
            {
                return vt.bVal;
            }

            if (vt.vt == VT_UI2)
            {
                return vt.uiVal;
            }

            if (vt.vt == VT_UI4)
            {
                return vt.uintVal;
            }

            if (vt.vt == VT_UI8)
            {
                return vt.ullVal;
            }

            if (vt.vt == VT_BOOL)
            {
                return vt.boolVal != VARIANT_FALSE ? 1 : 0;
            }

            if (vt.vt == VT_R4)
            {
                return vt.fltVal;
            }

            if (vt.vt == VT_R8)
            {
                return vt.dblVal;
            }

            if (vt.vt == VT_PTR)
            {
                return (int64_t)vt.punkVal;
            }

            if (vt.vt == VT_INT_PTR)
            {
                return vt.intVal;
            }

            if (vt.vt == VT_INT_PTR)
            {
                return vt.uintVal;
            }

            return defaultValue;
        }
         
        template <typename T>
        inline T                   VARIANT_value(IWbemClassObject* obj, LPCWSTR name, T defaultValue) noexcept
        {
            VARIANT vt;
            VariantInit(&vt);

            HRESULT hr = obj->Get(name, 0, &vt, 0, 0);
            if (SUCCEEDED(hr))
            {
                T result = VARIANT_value<T>(vt, defaultValue);
                VariantClear(&vt);
                return result;
            }
            else
            {
                VariantClear(&vt);
                return defaultValue;
            }
        }
         
        template <>
        inline bool                VARIANT_value<bool>(IWbemClassObject* obj, LPCWSTR name, bool defaultValue) noexcept
        {
            int intValue = VARIANT_value<int>(obj, name, 0);
            return intValue != 0;
        }
         
        inline bool                VARIANT_strings(VARIANT& vt, ccc::vector<ccc::string>& strings) noexcept
        {
            bool b = false;
            if (vt.vt & VT_ARRAY) /* SafeArrayDestroy */
            {
                SAFEARRAY* parray = vt.parray;
                if (vt.vt & VT_BSTR)
                {
                    LONG lBound = 0;
                    LONG uBound = 0;

                    SafeArrayGetLBound(parray, 1, &lBound);
                    SafeArrayGetUBound(parray, 1, &uBound);

                    for (LONG i = lBound; i <= uBound; i++)
                    {
                        BSTR bstrIP;
                        HRESULT hr = SafeArrayGetElement(parray, &i, &bstrIP);
                        if (SUCCEEDED(hr))
                        {
                            ccc::string str = VARIANT_string(bstrIP);
                            if (!str.empty())
                            {
                                b |= true;
                                strings.emplace_back(str);
                            }
                        }
                    }
                }
            }

            VariantClear(&vt);
            return b;
        }
         
        inline bool                VARIANT_strings(IWbemClassObject* obj, LPCWSTR name, ccc::vector<ccc::string>& strings) noexcept
        {
            VARIANT vt;
            VariantInit(&vt);

            HRESULT hr = obj->Get(name, 0, &vt, 0, 0);
            if (SUCCEEDED(hr))
            {
                bool b = VARIANT_strings(vt, strings);
                VariantClear(&vt);
                return b;
            }

            VariantClear(&vt);
            return false;
        }
         
        inline HRESULT             VARIANT_create_safe_array(VARIANT& vt, const ccc::vector<ccc::string>& list) noexcept
        {
            LONG length = list.size();
            if (length < 0)
            {
                length = 0;
            }

            SAFEARRAY* sa = SafeArrayCreateVector(VT_BSTR, 0, length);
            vt.vt = VT_ARRAY | VT_BSTR;
            vt.parray = sa;

            HRESULT hr = ERROR_SUCCESS;
            for (LONG i = 0; i < length; i++)
            {
                _bstr_t bstr(list[i].data());
                hr = SafeArrayPutElement(sa, &i, bstr.GetBSTR());
                if (FAILED(hr))
                {
                    break;
                }
            }
            return hr;
        }
         
        template <typename InternalCall>
        inline bool                Callvirt(IWbemServices* services, IWbemClassObject* obj, const _bstr_t& clazz, const _bstr_t& method, InternalCall&& internal_call) noexcept { return Win32Variant_Callvirt(services, obj, clazz, method, internal_call); }
    }
}

源文件:

#include <windows/ccc/win32/Win32Variant.h>

namespace ccc
{
    namespace win32
    {
        bool Win32Variant_Callvirt(IWbemServices* services, IWbemClassObject* obj, const _bstr_t& clazz, const _bstr_t& method, ccc::function<bool(IWbemClassObject*)>&& internal_call) noexcept
        {
            IWbemClassObject* pClass = NULL;
            IWbemClassObject* pInParamsDefinition = NULL;
            IWbemClassObject* pClassInstance = NULL;
            IWbemClassObject* pOutParams = NULL;

            VARIANT vtPATH;
            VariantInit(&vtPATH);

            VARIANT vtRET;
            VariantInit(&vtRET);

            bool ok = false;
            for (;;)
            {
                HRESULT hr = services->GetObject(clazz, 0, NULL, &pClass, NULL);
                if (FAILED(hr))
                {
                    break;
                }

                hr = pClass->GetMethod(method, 0, &pInParamsDefinition, NULL);
                if (FAILED(hr))
                {
                    break;
                }

                hr = pInParamsDefinition->SpawnInstance(0, &pClassInstance);
                if (FAILED(hr))
                {
                    break;
                }

                hr = internal_call(pClassInstance);
                if (FAILED(hr))
                {
                    break;
                }

                hr = obj->Get(L"__PATH", 0, &vtPATH, NULL, NULL);
                if (FAILED(hr))
                {
                    break;
                }

                hr = services->ExecMethod(
                    vtPATH.bstrVal,
                    method, /* BSTR(L"SetDNSServerSearchOrder") */
                    0,
                    NULL,
                    pClassInstance,
                    &pOutParams,
                    NULL);
                if (FAILED(hr))
                {
                    break; /* SUCCEEDED */
                }

                hr = pOutParams->Get(_bstr_t(L"ReturnValue"), 0, &vtRET, NULL, 0);
                if (FAILED(hr))
                {
                    break;
                }

                int err = VARIANT_value(vtRET, 0);
                if (err)
                {
                    break;
                }

                ok = true;
                break;
            }

            if (vtPATH.vt & VT_BSTR)
            {
                SysFreeString(vtPATH.bstrVal);
            }

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

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

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

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

            VariantClear(&vtRET);
            VariantClear(&vtPATH);
            return ok;
        }
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值