提供可变数组封装、可变类型数值/字符串获取等。
头文件:
#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;
}
}
}