769 lines
24 KiB
C++
769 lines
24 KiB
C++
|
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
// PARTICULAR PURPOSE.
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
/****************************************************************************
|
|
|
|
FILE: Windows Parental Controls utility function implementation file
|
|
|
|
PURPOSE: Common functions for COM, WMI, and generic support
|
|
|
|
FUNCTIONS:
|
|
|
|
WpcuCOMInit() - standard COM initialization
|
|
WpcuCOMCleanup() - COM uninitialization
|
|
WpcuWmiConnect() - connect to specified WMI namespace, returning services
|
|
pointer
|
|
WpcuSidStringFromUserName() - obtain SID for a given user name
|
|
WpcuSidStringForCurrentUser() - obtain SID for calling process
|
|
WpcuWmiInstancePutString() - put string value to class instance
|
|
WpcuWmiInstancePutStringArray() - put string array to class instance
|
|
WpcuWmiInstancePutDWORD() - put unsigned 32-bit value to class instance
|
|
WpcuWmiInstancePutDWORDArray() - put unsigned 32-bit array to class instance
|
|
WpcuWmiInstancePutBOOL() - put boolean value to class instance
|
|
WpcuWmiStringFromInstance() - get string value from class instance
|
|
WpcuWmiStringArrayFromInstance() - get string array from class instance
|
|
WpcuWmiDWORDFromInstance() - get unsigned 32-bit value from class instance
|
|
WpcuWmiDWORDArrayFromInstance() - get unsigned 32-bit array from class instance
|
|
WpcuWmiBOOLFromInstance() - get boolean value from class instance
|
|
|
|
COMMENTS:
|
|
WMI writes consist of Put() calls to the instance, followed by a PutInstance()
|
|
call to commit the changes. WMI reads use the Get() call.
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
#include "Utilities.h"
|
|
|
|
|
|
BOOL g_fCoInit = FALSE;
|
|
|
|
|
|
// Do one-time COM initalization per process
|
|
HRESULT WpcuCOMInit()
|
|
{
|
|
HRESULT hr = CoInitialize(NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
g_fCoInit = TRUE;
|
|
|
|
// Set general COM security levels
|
|
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
|
|
);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// Uninitialize COM
|
|
void WpcuCOMCleanup()
|
|
{
|
|
if (g_fCoInit)
|
|
{
|
|
CoUninitialize();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
// Calling function is responsible for freeing ppszSID using LocalAlloc
|
|
HRESULT WpcuSidStringFromUserName(PCWSTR pcszUserName, PWSTR* ppszSID)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (pcszUserName && ppszSID)
|
|
{
|
|
DWORD cbSID = 0, cchDomain = 0;
|
|
SID_NAME_USE SidNameUse;
|
|
|
|
// Call twice, first with null SID buffer. Retrieves required buffer
|
|
// size for domain name
|
|
LookupAccountNameW(NULL, pcszUserName, NULL, &cbSID, NULL,
|
|
&cchDomain, &SidNameUse);
|
|
if (!cbSID || !cchDomain)
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
WCHAR* pszDomain = NULL;
|
|
// Allocate properly sized buffer (with termination character)
|
|
// for domain name
|
|
pszDomain = new WCHAR[cchDomain];
|
|
if (!pszDomain)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
// Allocate properly sized buffer (with termination character)
|
|
// for PSID
|
|
PSID pSID = static_cast<PSID> (new BYTE[cbSID]); //(LocalAlloc (LMEM_FIXED, cbSID));
|
|
if (!pSID)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
// Second call with buffers allocated and sizes set
|
|
if (!LookupAccountName(NULL, pcszUserName, pSID, &cbSID,
|
|
pszDomain, &cchDomain, &SidNameUse))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
else
|
|
{
|
|
// Convert PSID to SID string
|
|
if (!ConvertSidToStringSidW(pSID, ppszSID))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
else
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
delete[] pSID; // (LocalFree (pSID);
|
|
}
|
|
delete[] pszDomain;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (hr);
|
|
}
|
|
|
|
// Calling function is responsible for freeing ppszSID using LocalAlloc
|
|
HRESULT WpcuSidStringForCurrentUser(PWSTR* ppszSID)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (ppszSID)
|
|
{
|
|
HANDLE hToken = NULL;
|
|
// Obtain token handle. Try the thread token first
|
|
if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, FALSE, &hToken))
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
if (dwErr == ERROR_NO_TOKEN)
|
|
{
|
|
// Try the process token
|
|
if (!OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &hToken))
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(dwErr);
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
TOKEN_USER* ptokenUser = NULL;
|
|
DWORD cbToken = 0;
|
|
DWORD cbSid = 0;
|
|
// Call twice. Call first time with NULL pTokenUser and 0 length to
|
|
// retrive required buffer length. Returns non-zero (normally failure)
|
|
if (!GetTokenInformation (hToken, TokenUser, ptokenUser, 0, &cbToken))
|
|
{
|
|
ptokenUser = (TOKEN_USER *) LocalAlloc (LMEM_FIXED, cbToken);
|
|
if(!ptokenUser)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
// Call second time with required buffer
|
|
if (!GetTokenInformation (hToken, TokenUser, ptokenUser, cbToken,
|
|
&cbToken))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
else
|
|
{
|
|
// Convert PSID to SID string
|
|
if (!ConvertSidToStringSidW(ptokenUser->User.Sid, ppszSID))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
else
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
LocalFree(ptokenUser);
|
|
}
|
|
}
|
|
}
|
|
if (hToken)
|
|
{
|
|
CloseHandle(hToken);
|
|
}
|
|
}
|
|
|
|
return (hr);
|
|
}
|
|
|
|
// Connect to specified namespace in WMI
|
|
HRESULT WpcuWmiConnect(PCWSTR pcszWpcNamespace, IWbemServices** ppiWmiServices)
|
|
{
|
|
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (pcszWpcNamespace && ppiWmiServices)
|
|
{
|
|
// Obtain the initial locator to WMI
|
|
IWbemLocator* pLocator = NULL;
|
|
hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
|
|
IID_IWbemLocator, (LPVOID *) &pLocator);
|
|
// Set up to connect to the WPC namespace in WMI on the local machine
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
BSTR bstrWpcNamespace = SysAllocString(pcszWpcNamespace);
|
|
|
|
if (bstrWpcNamespace == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
// Connect to the specified namespace with
|
|
// the current user and obtain pointer
|
|
// to make IWbemServices calls.
|
|
hr = pLocator->ConnectServer(
|
|
bstrWpcNamespace, // Object path of WMI namespace
|
|
NULL, // User name. NULL = current user
|
|
NULL, // User password. NULL = current
|
|
NULL, // Locale. NULL indicates current
|
|
NULL, // Security flags.
|
|
0, // Authority (e.g. Kerberos)
|
|
NULL, // Context object
|
|
ppiWmiServices // pointer to IWbemServices proxy
|
|
);
|
|
|
|
SysFreeString(bstrWpcNamespace);
|
|
}
|
|
pLocator->Release();
|
|
}
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT WpcuWmiObjectGet(IWbemServices* piWmiServices, PCWSTR pcszObjectPath,
|
|
IWbemClassObject** ppiWmiObject)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
if (piWmiServices && pcszObjectPath && ppiWmiObject)
|
|
{
|
|
BSTR bstrObjectPath = SysAllocString(pcszObjectPath);
|
|
if (bstrObjectPath == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
hr = piWmiServices->GetObject(bstrObjectPath, WBEM_FLAG_RETURN_WBEM_COMPLETE,
|
|
NULL, ppiWmiObject, NULL);
|
|
SysFreeString(bstrObjectPath);
|
|
}
|
|
}
|
|
|
|
return (hr);
|
|
}
|
|
|
|
|
|
HRESULT WpcuWmiInstancePutString(IWbemClassObject* piInstance, PCWSTR pcszProperty,
|
|
PCWSTR pcszValue)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
if (piInstance && pcszProperty && pcszValue)
|
|
{
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
var.bstrVal = SysAllocString(pcszValue);
|
|
if (!(var.bstrVal))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
var.vt = VT_BSTR;
|
|
hr = piInstance->Put(pcszProperty, 0, &var, 0);
|
|
VariantClear(&var);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// dwNumElements specifies the number of elements in the array referenced by
|
|
// ppcszValue
|
|
HRESULT WpcuWmiInstancePutStringArray(IWbemClassObject* piInstance,
|
|
PCWSTR pcszProperty,
|
|
DWORD dwNumElements,
|
|
PCWSTR* ppcszValue)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
if (piInstance && pcszProperty && ppcszValue)
|
|
{
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
// Create new SAFEARRAY
|
|
SAFEARRAYBOUND rgsaBound[1];
|
|
rgsaBound[0].cElements = dwNumElements;
|
|
rgsaBound[0].lLbound = 0;
|
|
var.parray = SafeArrayCreate(VT_BSTR, 1, rgsaBound);
|
|
if (var.parray == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
// Set proper variant type
|
|
var.vt = VT_ARRAY | VT_BSTR;
|
|
// Lock the array and obtain pointer to data
|
|
BSTR* pData;
|
|
hr = SafeArrayAccessData(var.parray, (void HUGEP**)&pData);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
for (DWORD i = 0;
|
|
i < dwNumElements && SUCCEEDED(hr);
|
|
i++)
|
|
{
|
|
// Write array data
|
|
pData[i] = SysAllocString(ppcszValue[i]);
|
|
if (pData[i] == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
// Always unlock the array
|
|
SafeArrayUnaccessData(var.parray);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = piInstance->Put(pcszProperty, 0, &var, 0);
|
|
}
|
|
}
|
|
VariantClear(&var);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT WpcuWmiInstancePutDWORD(IWbemClassObject* piInstance, PCWSTR pcszProperty,
|
|
DWORD dwValue)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
if (piInstance && pcszProperty)
|
|
{
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
// CIM represents a uint32 type within a VT_I4 automation type, which is
|
|
// referenced as an lVal
|
|
var.lVal = dwValue;
|
|
var.vt = VT_I4;
|
|
hr = piInstance->Put(pcszProperty, 0, &var, 0);
|
|
VariantClear(&var);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// dwNumElements specifies the number of elements in the array referenced by
|
|
// pdwValue
|
|
HRESULT WpcuWmiInstancePutDWORDArray(IWbemClassObject* piInstance,
|
|
PCWSTR pcszProperty,
|
|
DWORD dwNumElements,
|
|
DWORD* pdwValue)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
if (piInstance && pcszProperty && pdwValue)
|
|
{
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
// Create new SAFEARRAY
|
|
SAFEARRAYBOUND rgsaBound[1];
|
|
rgsaBound[0].cElements = dwNumElements;
|
|
rgsaBound[0].lLbound = 0;
|
|
var.parray = SafeArrayCreate(VT_I4, 1, rgsaBound);
|
|
if (var.parray == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
// Set proper variant type
|
|
var.vt = VT_ARRAY | VT_I4;
|
|
// Lock the array and obtain pointer to data
|
|
DWORD* pData;
|
|
hr = SafeArrayAccessData(var.parray, (void HUGEP**)&pData);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
for (DWORD i = 0; i < dwNumElements; i++)
|
|
{
|
|
// Write array data
|
|
pData[i] = pdwValue[i];
|
|
}
|
|
// Always unlock the array
|
|
SafeArrayUnaccessData(var.parray);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = piInstance->Put(pcszProperty, 0, &var, 0);
|
|
}
|
|
}
|
|
VariantClear(&var);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT WpcuWmiInstancePutBOOL(IWbemClassObject* piInstance, PCWSTR pcszProperty,
|
|
BOOL fValue)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
if (piInstance && pcszProperty)
|
|
{
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
var.boolVal = (fValue) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
var.vt = VT_BOOL;
|
|
hr = piInstance->Put(pcszProperty, 0, &var, 0);
|
|
VariantClear(&var);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT WpcuWmiInstancePutNULLVariant(IWbemClassObject* piInstance, PCWSTR pcszProperty)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
if (piInstance && pcszProperty)
|
|
{
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
var.vt = VT_NULL;
|
|
hr = piInstance->Put(pcszProperty, 0, &var, 0);
|
|
VariantClear(&var);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// Function returns S_OK and *ppszValue = NULL if retrieved string property is
|
|
// actually a NULL variant
|
|
HRESULT WpcuWmiStringFromInstance(IWbemClassObject* piInstance, PCWSTR pcszProperty,
|
|
PWSTR* ppszValue)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
if (piInstance && pcszProperty && ppszValue)
|
|
{
|
|
*ppszValue = NULL;
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
hr = piInstance->Get(pcszProperty, 0, &var, NULL, NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Only allow BSTR and NULL states
|
|
if (var.vt != VT_BSTR)
|
|
{
|
|
if (var.vt != VT_NULL)
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
size_t cch;
|
|
hr = StringCchLengthW(var.bstrVal, STRSAFE_MAX_CCH, &cch);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Allocate with null terminator
|
|
*ppszValue = new WCHAR[++cch];
|
|
if (!(*ppszValue))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
hr = StringCchCopyW(*ppszValue, cch, var.bstrVal);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
VariantClear(&var);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// Function returns S_OK and *pppszValue = NULL if retrieved string array property
|
|
// is actually a NULL variant
|
|
HRESULT WpcuWmiStringArrayFromInstance(IWbemClassObject* piInstance,
|
|
PCWSTR pcszProperty,
|
|
DWORD* pdwNumElements,
|
|
PWSTR** pppszValue)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
if (piInstance && pcszProperty && pdwNumElements && pppszValue)
|
|
{
|
|
*pppszValue = NULL;
|
|
*pdwNumElements = 0;
|
|
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
hr = piInstance->Get(pcszProperty, 0, &var, NULL, NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Only allow BSTR array and NULL states
|
|
if (var.vt != (VT_BSTR | VT_ARRAY))
|
|
{
|
|
if (var.vt != VT_NULL)
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Transfer array data from variant
|
|
long lUpper, lLower;
|
|
hr = SafeArrayGetUBound(var.parray, 1, &lUpper);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = SafeArrayGetLBound(var.parray, 1, &lLower);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
DWORD dwNumElements = lUpper - lLower + 1;
|
|
if (lUpper - lLower + 1 < lUpper - lLower)
|
|
{
|
|
// Overflow
|
|
hr = E_FAIL;
|
|
}
|
|
else if (dwNumElements > 0)
|
|
{
|
|
BSTR* pData;
|
|
hr = SafeArrayAccessData(var.parray,
|
|
(void HUGEP**)(&pData));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Allocate results array
|
|
*pppszValue = new PWSTR[dwNumElements];
|
|
if (*pppszValue == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
size_t cch;
|
|
for (DWORD i = 0;
|
|
i < dwNumElements && SUCCEEDED(hr);
|
|
i++)
|
|
{
|
|
hr = StringCchLengthW(pData[lLower + i],
|
|
STRSAFE_MAX_CCH,
|
|
&cch);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
(*pppszValue)[i] = new WCHAR[++cch];
|
|
if (!(*pppszValue)[i])
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
hr = StringCchCopyW((*pppszValue)[i],
|
|
cch,
|
|
pData[lLower + i]);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Successful addition
|
|
(*pdwNumElements)++;
|
|
}
|
|
else
|
|
{
|
|
delete[] (*pppszValue)[i];
|
|
(*pppszValue)[i] = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Always unlock the array
|
|
SafeArrayUnaccessData(var.parray);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
VariantClear(&var);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT WpcuWmiDWORDFromInstance(IWbemClassObject* piInstance, PCWSTR pcszProperty,
|
|
DWORD* pdwValue)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
if (piInstance && pcszProperty && pdwValue)
|
|
{
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
hr = piInstance->Get(pcszProperty, 0, &var, NULL, NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Only allow DWORD
|
|
if (var.vt != VT_I4)
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
// CIM represents a uint32 type within a VT_I4 automation
|
|
// type, which is referenced as an lVal
|
|
*pdwValue = var.lVal;
|
|
}
|
|
}
|
|
VariantClear(&var);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// Function returns S_OK and *ppdwValue = NULL if retrieved DWORD array property
|
|
// is actually a NULL variant
|
|
HRESULT WpcuWmiDWORDArrayFromInstance(IWbemClassObject* piInstance,
|
|
PCWSTR pcszProperty,
|
|
DWORD* pdwNumElements,
|
|
DWORD** ppdwValue)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
if (piInstance && pcszProperty && pdwNumElements && ppdwValue)
|
|
{
|
|
*ppdwValue = NULL;
|
|
*pdwNumElements = 0;
|
|
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
hr = piInstance->Get(pcszProperty, 0, &var, NULL, NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Only allow DWORD array and NULL states
|
|
if (var.vt != (VT_I4 | VT_ARRAY))
|
|
{
|
|
if (var.vt != VT_NULL)
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Transfer array data from variant
|
|
long lUpper = 0, lLower = 0;
|
|
hr = SafeArrayGetUBound(var.parray, 1, &lUpper);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = SafeArrayGetLBound(var.parray, 1, &lLower);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*pdwNumElements = lUpper - lLower + 1;
|
|
if (lUpper - lLower + 1 < lUpper - lLower)
|
|
{
|
|
// Overflow
|
|
hr = E_FAIL;
|
|
}
|
|
else if (*pdwNumElements > 0)
|
|
{
|
|
long* pData;
|
|
hr = SafeArrayAccessData(var.parray,
|
|
(void HUGEP**)(&pData));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*ppdwValue = new DWORD[*pdwNumElements];
|
|
if (!*ppdwValue)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
for (DWORD i = 0; i < *pdwNumElements; i++)
|
|
{
|
|
(*ppdwValue)[i] = pData[lLower + i];
|
|
}
|
|
}
|
|
// Always unlock the array
|
|
SafeArrayUnaccessData(var.parray);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
VariantClear(&var);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT WpcuWmiBOOLFromInstance(IWbemClassObject* piInstance, PCWSTR pcszProperty,
|
|
BOOL* pfValue)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
if (piInstance && pcszProperty && pfValue)
|
|
{
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
hr = piInstance->Get(pcszProperty, 0, &var, NULL, NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Only allow BOOL
|
|
if (var.vt != VT_BOOL)
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
*pfValue = var.boolVal;
|
|
}
|
|
}
|
|
VariantClear(&var);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|