windows-nt/Source/XPSP1/NT/admin/wmi/wbem/scripting/cwbemdsp.cpp
2020-09-26 16:20:57 +08:00

1804 lines
47 KiB
C++

//***************************************************************************
//
// Copyright (c) 1998-2000 Microsoft Corporation.
//
// File: cwbemdsp.cpp
//
// Description :
// Implementation of the IDispatch interface for Wbem Objects.
// This is mostly standard, except for the additional support for
// specifying the name of a Wbem class property/method directly as if it
// was a property/method of the actual CWbemObject class ("dot notation")
//
// Part of : WBEM automation interface layer
//
// History:
// corinaf 4/3/98 Created
//
//***************************************************************************
#include "precomp.h"
const unsigned long CWbemDispID::s_wmiDispIdTypeMask = 0x03000000;
const unsigned long CWbemDispID::s_wmiDispIdTypeStatic = 0x00000000;
const unsigned long CWbemDispID::s_wmiDispIdTypeSchema = 0x01000000;
const unsigned long CWbemDispID::s_wmiDispIdSchemaTypeMask = 0x00800000;
const unsigned long CWbemDispID::s_wmiDispIdSchemaTypeProperty = 0x00800000;
const unsigned long CWbemDispID::s_wmiDispIdSchemaTypeMethod = 0x00000000;
const unsigned long CWbemDispID::s_wmiDispIdSchemaElementIDMask = 0x007FFFFF;
//Forward declaration
HRESULT assignArrayElementToVariant(SAFEARRAY *psa, VARTYPE vt, long inx, VARIANT *pvResult);
void assignVariantToArrayElement(SAFEARRAY *psa, VARTYPE vt, long inx, VARIANT *pvNewVal);
VARTYPE CimTypeToVtType(CIMTYPE lType);
HRESULT VariantChangeByValToByRef(VARIANT *dest, VARIANT *source, VARTYPE destType);
class CWbemSchemaIDCache
{
private:
typedef map<CComBSTR, CWbemDispID, BSTRless> DispIDNameMap;
unsigned long m_nextId;
DispIDNameMap m_cache;
CWbemDispatchMgr *m_pDispatchMgr;
bool FindPropertyName (BSTR bsName);
bool GetMethod (BSTR bstrMethodName, SAFEARRAY **ppsaInParams, SAFEARRAY **ppsaOutParams,
CComPtr<IWbemClassObject> & pInParams, CComPtr<IWbemClassObject> & pOutParams);
bool GetIdOfMethodParameter(BSTR bstrParamName, CComPtr<IWbemClassObject> & pParams, long *pId);
static bool FindMemberInArray(BSTR bstrName, SAFEARRAY *psaNames);
public:
CWbemSchemaIDCache (CWbemDispatchMgr *pDispMgr) :
m_nextId (0),
m_pDispatchMgr (pDispMgr) {}
virtual ~CWbemSchemaIDCache ();
HRESULT GetDispID (LPWSTR FAR* rgszNames, unsigned int cNames, DISPID FAR* rgdispid);
bool GetName (DISPID dispId, CComBSTR & bsName);
};
CWbemDispatchMgr::CWbemDispatchMgr(CSWbemServices *pWbemServices,
CSWbemObject *pSWbemObject) :
m_pWbemServices (pWbemServices),
m_pSWbemObject (pSWbemObject), // Backpointer to parent (not AddRef'd)
m_pWbemClass (NULL),
m_pTypeInfo (NULL),
m_pCTypeInfo (NULL),
m_hResult (S_OK)
{
m_pSchemaCache = new CWbemSchemaIDCache (this);
if (m_pWbemServices)
m_pWbemServices->AddRef ();
m_pWbemObject = pSWbemObject->GetIWbemClassObject ();
}
CWbemDispatchMgr::~CWbemDispatchMgr()
{
RELEASEANDNULL(m_pWbemServices)
RELEASEANDNULL(m_pWbemObject)
RELEASEANDNULL(m_pWbemClass)
RELEASEANDNULL(m_pTypeInfo)
RELEASEANDNULL(m_pCTypeInfo)
DELETEANDNULL(m_pSchemaCache)
}
void CWbemDispatchMgr::SetNewObject (IWbemClassObject *pNewObject)
{
if (m_pWbemObject && pNewObject)
{
m_pWbemObject->Release ();
m_pWbemObject = pNewObject;
m_pWbemObject->AddRef ();
CComVariant var;
if (SUCCEEDED(pNewObject->Get (WBEMS_SP_GENUS, 0, &var, NULL, NULL)) &&
(WBEM_GENUS_CLASS == var.lVal))
{
// This is a class, so update the class object too
if (m_pWbemClass)
m_pWbemClass->Release ();
m_pWbemClass = pNewObject;
m_pWbemClass->AddRef ();
}
// Clear out the caches
if (m_pSchemaCache)
{
delete m_pSchemaCache;
m_pSchemaCache = new CWbemSchemaIDCache (this);
}
}
}
STDMETHODIMP
CWbemDispatchMgr::GetTypeInfoCount(unsigned int FAR* pctinfo)
{
*pctinfo = 1;
return NOERROR;
}
STDMETHODIMP CWbemDispatchMgr::GetTypeInfo(unsigned int itinfo,
LCID lcid,
ITypeInfo FAR* FAR* pptinfo)
{
HRESULT hr;
ITypeLib *pTypeLib = NULL;
//If Type Info is not cached already - load the library and
//get the Type Info, then cache it for further access
if (!m_pTypeInfo)
{
// Load Type Library.
hr = LoadRegTypeLib(LIBID_WbemScripting, 1, 0, lcid, &pTypeLib);
if (FAILED(hr))
{
// if it wasn't registered, try to load it from the path
// if this succeeds, it will have registered the type library for us
// for the next time.
hr = LoadTypeLib(OLESTR("wbemdisp.tlb"), &pTypeLib);
if(FAILED(hr))
return hr;
}
// Get type information for interface of the object.
hr = pTypeLib->GetTypeInfoOfGuid(IID_ISWbemObjectEx, &m_pTypeInfo);
pTypeLib->Release();
if (FAILED(hr))
return hr;
}
//AddRef whenever returning another pointer to this
m_pTypeInfo->AddRef();
*pptinfo = m_pTypeInfo;
return NOERROR;
}
STDMETHODIMP CWbemDispatchMgr::GetClassInfo(ITypeInfo FAR* FAR* pptinfo)
{
HRESULT hr;
ITypeLib *pTypeLib = NULL;
//If Type Info is not cached already - load the library and
//get the Type Info, then cache it for further access
if (!m_pCTypeInfo)
{
// Load Type Library.
hr = LoadRegTypeLib(LIBID_WbemScripting, 1, 0, 0, &pTypeLib);
if (FAILED(hr))
{
// if it wasn't registered, try to load it from the path
// if this succeeds, it will have registered the type library for us
// for the next time.
hr = LoadTypeLib(OLESTR("wbemdisp.tlb"), &pTypeLib);
if(FAILED(hr))
return hr;
}
// Get type information for coclass of the object.
hr = pTypeLib->GetTypeInfoOfGuid(CLSID_SWbemObjectEx, &m_pCTypeInfo);
pTypeLib->Release();
if (FAILED(hr))
return hr;
}
//AddRef whenever returning another pointer to this
m_pCTypeInfo->AddRef();
*pptinfo = m_pCTypeInfo;
return NOERROR;
}
STDMETHODIMP
CWbemDispatchMgr::GetIDsOfNames(REFIID iid, //always IID_NULL
LPWSTR FAR* rgszNames,
unsigned int cNames,
LCID lcid,
DISPID FAR* rgdispid)
{
HRESULT hr = E_FAIL;
CComPtr<ITypeInfo> pITypeInfo;
if (SUCCEEDED(hr = GetTypeInfo(0, lcid, &pITypeInfo)))
{
// See if this is a static property or method
if (FAILED(hr = DispGetIDsOfNames(pITypeInfo,
rgszNames,
cNames,
rgdispid)))
{
// Not static - try schema
if (m_pSchemaCache && FAILED(hr = m_pSchemaCache->GetDispID (rgszNames, cNames, rgdispid)))
{
rgdispid[0] = DISPID_UNKNOWN;
hr = DISP_E_UNKNOWNNAME;
}
}
}
return hr;
}
STDMETHODIMP CWbemDispatchMgr::Invoke(DISPID dispidMember,
REFIID iid, LCID lcid,
unsigned short wFlags,
DISPPARAMS FAR* pdispparams,
VARIANT FAR* pvarResult,
EXCEPINFO FAR* pexcepinfo,
unsigned int FAR* puArgErr)
{
HRESULT hr;
ITypeInfo *pTypeInfo = NULL;
//Get the type info
hr = GetTypeInfo(0, lcid, &pTypeInfo);
if (FAILED(hr))
return hr;
m_hResult = S_OK;
CWbemDispID dispId (dispidMember);
// Is this a regular dispId
if (dispId.IsStatic ())
{
// Check for inbound NULLs masquerading as defaulted parameters
if (wFlags & DISPATCH_METHOD)
MapNulls (pdispparams);
hr = DispInvoke((IDispatch *) ((ISWbemObjectEx *)m_pSWbemObject),
pTypeInfo,
dispidMember,
wFlags,
pdispparams,
pvarResult,
pexcepinfo,
puArgErr
);
if (FAILED(hr))
{
// Try the error handler for this object in case it can handle this
hr = HandleError (dispidMember, wFlags, pdispparams, pvarResult, puArgErr, hr);
}
}
else if (dispId.IsSchema ())
{
//Otherwise - this is a WBEM property or method, so we implement
//the invocation ourselves...
ResetLastErrors ();
if (dispId.IsSchemaMethod ()) //WBEM method
hr = InvokeWbemMethod(dispidMember,
pdispparams,
pvarResult);
else if (dispId.IsSchemaProperty ()) //WBEM property
hr = InvokeWbemProperty(dispidMember,
wFlags,
pdispparams,
pvarResult,
pexcepinfo,
puArgErr);
else
hr = DISP_E_MEMBERNOTFOUND;
if (FAILED(hr))
RaiseException (hr);
}
if (FAILED (m_hResult))
{
if (NULL != pexcepinfo)
SetException (pexcepinfo, m_hResult, L"SWbemObjectEx");
hr = DISP_E_EXCEPTION;
}
if (pTypeInfo)
pTypeInfo->Release();
return hr;
}
HRESULT
CWbemDispatchMgr::InvokeWbemProperty(DISPID dispid,
unsigned short wFlags,
DISPPARAMS FAR* pdispparams,
VARIANT FAR* pvarResult,
EXCEPINFO FAR* pexcepinfo,
unsigned int FAR* puArgErr)
{
HRESULT hr = E_FAIL;
if (m_pSchemaCache)
{
BOOL bIsGetOperation = (DISPATCH_PROPERTYGET & wFlags);
if (bIsGetOperation)
{
//Check that the output parameter is valid
if (pvarResult == NULL)
return E_INVALIDARG;
}
else
{
//Check input parameters
if ((pdispparams->cArgs < 1) || (pdispparams->cArgs > 2))
return DISP_E_BADPARAMCOUNT;
if ((pdispparams->cNamedArgs != 1) ||
(pdispparams->cNamedArgs == 1 &&
pdispparams->rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
return DISP_E_PARAMNOTOPTIONAL;
}
//For both get & put, we need to first get the property
// (for put we need to validate the syntax)
CComBSTR bsPropertyName;
if (m_pSchemaCache->GetName (dispid, bsPropertyName))
{
SAFEARRAY *psaNames = NULL;
long inx;
VARIANT vPropVal;
long lArrayPropInx;
CIMTYPE lPropType;
//Get the value of this property
//-------------------------------------
VariantInit(&vPropVal);
if (FAILED (hr = m_pWbemObject->Get(bsPropertyName, 0, &vPropVal, &lPropType, NULL)))
{
return hr;
}
// The expected VT type for the proposed property value
VARTYPE expectedVarType = CimTypeToVtType (lPropType & ~CIM_FLAG_ARRAY);
//If we are in a get operation
//----------------------------------
if (bIsGetOperation)
{
//If the property is an embedded object, we might need to convert it from
//a VT_UNKNOWN to a VT_DISPATCH
if (SUCCEEDED(hr = MapFromCIMOMObject(m_pWbemServices, &vPropVal,
m_pSWbemObject, bsPropertyName)))
{
//If the property is an array, need to check for index and get that element
if ((lPropType & CIM_FLAG_ARRAY) && (pdispparams->cArgs > 0))
{
//Note: currently we support single dimension arrays only, so we only
// look for one index
VARIANT indexVar;
VariantInit (&indexVar);
// Attempt to coerce the index argument into a value suitable for an array index
if (S_OK == VariantChangeType (&indexVar, &pdispparams->rgvarg[0], 0, VT_I4))
{
lArrayPropInx = V_I4(&indexVar);
//Fill in the result variant with the requested array element
hr = assignArrayElementToVariant(vPropVal.parray, (V_VT(&vPropVal) & ~VT_ARRAY),
lArrayPropInx, pvarResult);
}
else
hr = DISP_E_TYPEMISMATCH;
VariantClear (&indexVar);
}
else //If it's not an array index - copy to output param and we're done
{
// Check if it's an array value and convert as necessary
if (V_ISARRAY(&vPropVal))
hr = ConvertArrayRev(pvarResult, &vPropVal);
else
hr = VariantCopy (pvarResult, &vPropVal);
}
}
} //Property Get
//Otherwise (put operation)
//---------------------------------
else
{
/*
* Need to translate this into a call to SWbemProperty.put_Value: easiest way
* to do this is to
* (A) get the SWbemProperty object for this property
* (B) Call IDispatch::Invoke on that object, passing in the value
* This way we get the error handling behavior too.
*/
CComPtr<ISWbemPropertySet> pISWbemPropertySet;
if (SUCCEEDED(hr = m_pSWbemObject->get_Properties_ (&pISWbemPropertySet)))
{
CComPtr<ISWbemProperty> pISWbemProperty;
if (SUCCEEDED(hr = pISWbemPropertySet->Item (bsPropertyName, 0, &pISWbemProperty)))
{
// NB: The Value property of ISWbemProperty is the "default" automation property
hr = pISWbemProperty->Invoke (
DISPID_VALUE,
IID_NULL,
0,
wFlags,
pdispparams,
pvarResult,
pexcepinfo,
puArgErr);
// Use our more specific error here if we have one
if (FAILED(hr) && pexcepinfo)
hr = pexcepinfo->scode;
}
}
} //Property Put
VariantClear(&vPropVal);
}
}
return hr;
}
//***************************************************************************
//
// SCODE CWbemDispatchMgr::InvokeWbemMethod
//
// DESCRIPTION:
//
// Invoke the method via direct access.
//
// PARAMETERS:
//
// dispid The dispid od the method
// pdispparams Pointer to DISPPARAMS for this invocation
// pvarResult On successful return holds return value (if any)
//
// RETURN VALUES:
//
//***************************************************************************
HRESULT CWbemDispatchMgr::InvokeWbemMethod(
DISPID dispid,
DISPPARAMS FAR* pdispparams,
VARIANT FAR* pvarResult
)
{
HRESULT hr = E_FAIL;
if (m_pWbemServices && m_pSchemaCache)
{
//Currently we don't support named arguments
if (pdispparams->cNamedArgs > 0)
return DISP_E_NONAMEDARGS;
//Map the dispid to a method name
CComBSTR bsMethodName;
if (m_pSchemaCache->GetName (dispid, bsMethodName))
{
// Build up the inparameters (if any)
CComPtr<IWbemClassObject> pInParameters;
CComPtr<IWbemClassObject> pOutParameters;
//Get the input parameters object of the method (may be NULL)
if (SUCCEEDED (hr = m_pWbemClass->GetMethod(bsMethodName, 0, &pInParameters,
&pOutParameters)))
{
CComPtr<IWbemClassObject> pInParamsInstance;
if (pInParameters)
hr = MapInParameters (pdispparams, pInParameters, &pInParamsInstance);
if (SUCCEEDED (hr))
{
CComPtr<IWbemServices> pService = m_pWbemServices->GetIWbemServices ();
if (pService)
{
// Need the RELPATH to specify the target class or instance
VARIANT vObjectPathVal;
VariantInit(&vObjectPathVal);
if (SUCCEEDED (hr = m_pWbemObject->Get
(WBEMS_SP_RELPATH, 0, &vObjectPathVal, NULL, NULL)))
{
/*
* If a "keyless" object slips through the net its __RELPATH
* value will be VT_NULL. At this point we should fail gracefully.
*/
if (VT_BSTR == V_VT(&vObjectPathVal))
{
// Execute the CIMOM method
CComPtr<IWbemClassObject> pOutParamsInstance;
bool needToResetSecurity = false;
HANDLE hThreadToken = NULL;
CSWbemSecurity *pSecurityInfo = m_pWbemServices->GetSecurityInfo ();
if (pSecurityInfo && pSecurityInfo->SetSecurity (needToResetSecurity, hThreadToken))
{
if (SUCCEEDED(hr = pService->ExecMethod(V_BSTR(&vObjectPathVal),
bsMethodName, 0, NULL,
pInParamsInstance, &pOutParamsInstance, NULL)))
hr = MapOutParameters (pdispparams, pOutParameters,
pOutParamsInstance, pvarResult);
SetWbemError (m_pWbemServices);
}
if (pSecurityInfo)
{
// Restore original privileges on this thread
if (needToResetSecurity)
pSecurityInfo->ResetSecurity (hThreadToken);
pSecurityInfo->Release ();
}
}
else
hr = WBEM_E_FAILED;
}
VariantClear (&vObjectPathVal);
}
}
}
}
}
return hr;
}
//***************************************************************************
//
// SCODE CWbemDispatchMgr::MapOutParameters
//
// DESCRIPTION:
//
// Invoke the method via direct access.
//
// PARAMETERS:
//
// dispparams Pointer to DISPPARAMS for this invocation
// pOutParameters Class template for out parameters
// pOutParamsInstance Addresses the IWbemClassObject to hold the
// out parameters (if any) - may be NULL
// pvarResult On successful return holds return value (if any)
//
// RETURN VALUES:
//
//***************************************************************************
HRESULT CWbemDispatchMgr::MapOutParameters (
DISPPARAMS FAR* pdispparams,
IWbemClassObject *pOutParameters,
IWbemClassObject *pOutParamsInstance,
VARIANT FAR* pvarResult
)
{
HRESULT hr = S_OK;
//For each "out" parameter in the output parameters object (if there is one),
//find it's id, then look for the parameter with this id in the arguments array
//and set the return parameter value accordingly
//----------------------------------------------------------------------------
if (pOutParameters && pOutParamsInstance)
{
//Start an enumeration through the "out" parameters class template
if (SUCCEEDED (hr = pOutParameters->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY)))
{
BSTR bstrId = SysAllocString(L"id");
BSTR bstrParamName = NULL;
/*
* For each property in the outparams class template, get the [id]
* to map the relevant posistional value in the pdispparams.
*/
while (WBEM_S_NO_ERROR ==
(hr != pOutParameters->Next(0, &bstrParamName, NULL, NULL, NULL)))
{
// Get the returned parameter value from the instance
VARIANT vParamVal;
VariantInit(&vParamVal);
if (SUCCEEDED (pOutParamsInstance->Get (bstrParamName, 0, &vParamVal, NULL, NULL)))
{
//If this is the return value, set it separately
if (!_wcsicmp(bstrParamName, L"ReturnValue"))
{
if (pvarResult)
hr = MapReturnValue (pvarResult, &vParamVal);
}
//Otherwise - regular out parameter
else
{
IWbemQualifierSet *pQualSet = NULL;
//Get the id of this parameter (it's the "id" qualifier)
if (SUCCEEDED (hr = pOutParameters->GetPropertyQualifierSet
(bstrParamName, &pQualSet)))
{
VARIANT vIdVal;
VariantInit(&vIdVal);
if (SUCCEEDED (hr = pQualSet->Get(bstrId, 0, &vIdVal, NULL)))
{
//Calculate the position of this id in the arguments array
long pos = (pdispparams->cArgs - 1) - V_I4(&vIdVal);
// If its out of range, too bad
if ((0 <= pos) && (pos < (long) pdispparams->cArgs))
hr = MapOutParameter (&pdispparams->rgvarg[pos], &vParamVal);
}
VariantClear(&vIdVal);
pQualSet->Release();
}
}
}
VariantClear (&vParamVal);
SysFreeString (bstrParamName);
bstrParamName = NULL;
} //while
SysFreeString (bstrId);
}
} //if pOutParameters
return hr;
}
//***************************************************************************
//
// SCODE CWbemDispatchMgr::MapReturnValue
//
// DESCRIPTION:
//
// Map the method return value
//
// PARAMETERS:
//
// pDest On successful return holds return value (if any)
// pSrc The variant value to map
//
//
// RETURN VALUES:
//
//***************************************************************************
HRESULT CWbemDispatchMgr::MapReturnValue (
VARIANT FAR* pDest,
VARIANT FAR* pSrc
)
{
HRESULT hr = S_OK;
//If the return value is a VT_UNKNOWN, we need to wrap into a
//VT_DISPATCH before passing it back
if (SUCCEEDED (hr = MapFromCIMOMObject(m_pWbemServices, pSrc)))
{
// Handle arrays correctly (must always be VT_ARRAY|VT_VARIANT)
if(V_VT(pSrc) & VT_ARRAY)
hr = ConvertArrayRev(pDest, pSrc);
else
hr = VariantCopy (pDest, pSrc);
}
return hr;
}
//***************************************************************************
//
// SCODE CWbemDispatchMgr::MapOutParameter
//
// DESCRIPTION:
//
// Map a (possibly by reference) out parameter
//
// PARAMETERS:
//
// pDest On successful return holds return value (if any)
// pVal The variant value to map
//
//
// RETURN VALUES:
//
//***************************************************************************
HRESULT CWbemDispatchMgr::MapOutParameter (
VARIANT FAR* pDest,
VARIANT FAR* pSrc
)
{
HRESULT hr = S_OK;
//If the return value is a VT_UNKNOWN, we need to wrap into a
//VT_DISPATCH before passing it back
if (SUCCEEDED (hr = MapFromCIMOMObject(m_pWbemServices, pSrc)))
{
VARIANT tempVal;
VariantInit (&tempVal);
// Handle arrays correctly (must always be VT_ARRAY|VT_VARIANT)
if(V_VT(pSrc) & VT_ARRAY)
hr = ConvertArrayRev(&tempVal, pSrc);
else
hr = VariantCopy (&tempVal, pSrc);
// Finally take care of ensuring we produce BYREFs if necessary
if (SUCCEEDED (hr))
hr = VariantChangeByValToByRef(pDest, &tempVal, V_VT(pDest));
VariantClear (&tempVal);
}
return hr;
}
//***************************************************************************
//
// SCODE CWbemDispatchMgr::MapInParameters
//
// DESCRIPTION:
//
// Map the in parameters to a method
//
// PARAMETERS:
//
// pdispparams DISPPARAMS containing the in parameters
// pInParameters Class template for method input parameters
// ppInParamsInstance On successful return holds the mapped parameters
//
// RETURN VALUES:
//
//***************************************************************************
HRESULT CWbemDispatchMgr::MapInParameters (
DISPPARAMS FAR* pdispparams,
IWbemClassObject *pInParameters,
IWbemClassObject **ppInParamsInstance
)
{
HRESULT hr = S_OK;
*ppInParamsInstance = NULL;
//Spawn an instance to fill in with values
if (SUCCEEDED (hr = pInParameters->SpawnInstance(0, ppInParamsInstance)))
{
/*
* Iterate through the "in" parameters object properties in the class to find the
* ID positional qualifier. Note we do this in the InParams class rather than
* the spawned instance to protect ourselves against the case where the [id]
* qualifier has been declared without the "propagate to instance" flavor setting,
*/
if (SUCCEEDED (hr = pInParameters->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY)))
{
BSTR bstrParamName = NULL;
BSTR bstrId = SysAllocString(L"id");
CIMTYPE lType;
//For each property in the inparams object
while (WBEM_S_NO_ERROR ==
(hr = pInParameters->Next(0, &bstrParamName, NULL, &lType, NULL)))
{
IWbemQualifierSet *pQualSet = NULL;
//Get the id of this parameter (it's the "id" qualifier)
if (SUCCEEDED(hr =
pInParameters->GetPropertyQualifierSet(bstrParamName, &pQualSet)))
{
VARIANT vIdVal;
VariantInit(&vIdVal);
if (SUCCEEDED(hr = pQualSet->Get(bstrId, 0, &vIdVal, NULL)))
{
//Calculate the position of this id in the arguments array
long pos = (pdispparams->cArgs - 1) - V_I4(&vIdVal);
// If no argument specified, we won't set it in ppInParamsInstance
// and just assume it will be defaulted
if ((0 <= pos) && (pos < (long) pdispparams->cArgs))
{
VARIANT vParamVal;
VariantInit (&vParamVal);
if (SUCCEEDED (hr = MapInParameter
(&vParamVal, &pdispparams->rgvarg[pos], lType)))
{
// If we have a VT_ERROR with DISP_E_PARAMNOTFOUND this
// is a "missing" parameter - we just fail to set it and
// let it default in the instance
if ((VT_ERROR == V_VT(&vParamVal)) && (DISP_E_PARAMNOTFOUND == vParamVal.scode))
{
// Let it default
}
else
{
//Copy the value for this parameter from the argument array
//into the inparamsinstance object property
hr = (*ppInParamsInstance)->Put(bstrParamName, 0, &vParamVal, NULL);
}
}
VariantClear (&vParamVal);
}
}
VariantClear(&vIdVal);
pQualSet->Release();
pQualSet = NULL;
}
SysFreeString (bstrParamName);
bstrParamName = NULL;
if (FAILED(hr))
break;
} //while
SysFreeString (bstrId);
}
}
return hr;
}
//***************************************************************************
//
// SCODE CWbemDispatchMgr::MapInParameter
//
// DESCRIPTION:
//
// Map a in parameter
//
// PARAMETERS:
//
// pDest On successful return holds return value
// pVal The variant value to map
// lType CIMTYPE of target property value
//
//
// RETURN VALUES:
//
//***************************************************************************
HRESULT CWbemDispatchMgr::MapInParameter (
VARIANT FAR* pDest,
VARIANT FAR* pSrc,
CIMTYPE lType
)
{
HRESULT hr = S_OK;
if ((NULL == pSrc) || (VT_EMPTY == V_VT(pSrc))
|| (VT_NULL == V_VT(pSrc)))
{
// Map all of these to a VT_NULL
pDest->vt = VT_NULL;
}
else if (((VT_ARRAY | VT_VARIANT) == V_VT(pSrc)) ||
((VT_ARRAY | VT_VARIANT | VT_BYREF) == V_VT(pSrc)))
{
// Arrays need to be mapped "down" to their raw form (and watch out
// for embedded objects!)
if (SUCCEEDED(hr = ConvertArray(pDest, pSrc)))
hr = MapToCIMOMObject(pDest);
}
else if ((CIM_FLAG_ARRAY & lType) &&
((VT_DISPATCH == V_VT(pSrc))
|| ((VT_DISPATCH|VT_BYREF) == V_VT(pSrc))))
{
// Look for a JScript-style IDispatch that needs to be mapped to an array
hr = ConvertDispatchToArray (pDest, pSrc, lType & ~CIM_FLAG_ARRAY);
}
else if ((VT_BYREF | VT_VARIANT) == V_VT(pSrc))
{
// May be used if the scripting language supports functions that can change
// the type of a reference. CIMOM won't do this, wo we unwrap the
// variant before proceeding
hr = MapInParameter (pDest, pSrc->pvarVal, lType);
}
else
{
// A "straightforward" value - all we have to watch for is an embedded object
// and a possible byRef
if (SUCCEEDED(hr = VariantCopy (pDest, pSrc)))
{
hr = MapToCIMOMObject(pDest);
// Is it byref - if so remove the indirection
if (VT_BYREF & V_VT(pDest))
hr = VariantChangeType(pDest, pDest, 0, V_VT(pDest) & ~VT_BYREF);
}
}
return hr;
}
//-------------------------------------------------------------
// CWbemDispatchMgr::RaiseException
//
// Description : signal exception to automation client
//
// Parameters : hr - HRESULT
//-------------------------------------------------------------
void CWbemDispatchMgr::RaiseException (HRESULT hr)
{
// Store the HRESULT for processing in the Invoke routine
m_hResult = hr;
// Set a WMI scripting error on this thread for the client
ICreateErrorInfo *pCreateErrorInfo = NULL;
if (SUCCEEDED (CreateErrorInfo (&pCreateErrorInfo)))
{
BSTR bsDescr = MapHresultToWmiDescription (hr);
pCreateErrorInfo->SetDescription (bsDescr);
SysFreeString (bsDescr);
pCreateErrorInfo->SetGUID (IID_ISWbemObjectEx);
pCreateErrorInfo->SetSource (L"SWbemObjectEx");
IErrorInfo *pErrorInfo = NULL;
if (SUCCEEDED (pCreateErrorInfo->QueryInterface(IID_IErrorInfo, (void**) &pErrorInfo)))
{
SetErrorInfo (0, pErrorInfo);
pErrorInfo->Release ();
}
pCreateErrorInfo->Release ();
}
}
//-------------------------------------------------------------
// Name : assignArrayElementToVariant
//
// Description : According to the type of the array elements,
// retrieves the requested element from the array
// into a variant
//
// Parameters : psa - pointer to the SAFEARRAY
// vt - vartype of array elements
// inx - index of the element in the array
// pvResult - resulting variant
//-------------------------------------------------------------
HRESULT assignArrayElementToVariant(SAFEARRAY *psa, VARTYPE vt, long inx, VARIANT *pvResult)
{
HRESULT hr = WBEM_S_NO_ERROR;
switch (vt)
{
case VT_I2 :
V_VT(pvResult) = VT_I2;
SafeArrayGetElement(psa, &inx, &V_I2(pvResult));
break;
case VT_I4 :
V_VT(pvResult) = VT_I4;
SafeArrayGetElement(psa, &inx, &V_I4(pvResult));
break;
case VT_R4 :
V_VT(pvResult) = VT_R4;
SafeArrayGetElement(psa, &inx, &V_R4(pvResult));
break;
case VT_R8 :
V_VT(pvResult) = VT_R8;
SafeArrayGetElement(psa, &inx, &V_R8(pvResult));
break;
case VT_DATE :
V_VT(pvResult) = VT_DATE;
SafeArrayGetElement(psa, &inx, &V_DATE(pvResult));
break;
case VT_BSTR :
V_VT(pvResult) = VT_BSTR;
SafeArrayGetElement(psa, &inx, &V_BSTR(pvResult));
break;
case VT_DISPATCH :
V_VT(pvResult) = VT_DISPATCH;
SafeArrayGetElement(psa, &inx, &V_DISPATCH(pvResult));
break;
case VT_UNKNOWN :
V_VT(pvResult) = VT_UNKNOWN;
SafeArrayGetElement(psa, &inx, &V_UNKNOWN(pvResult));
break;
case VT_BOOL :
V_VT(pvResult) = VT_BOOL;
SafeArrayGetElement(psa, &inx, &V_BOOL(pvResult));
break;
case VT_VARIANT :
{
V_VT(pvResult) = VT_BYREF | VT_VARIANT;
VARIANT *pVar = new VARIANT;
if (pVar)
{
VariantInit (pVar);
SafeArrayGetElement(psa, &inx, pVar);
V_VARIANTREF(pvResult) = pVar;
}
else
hr = WBEM_E_OUT_OF_MEMORY;
}
break;
case VT_UI1 :
V_VT(pvResult) = VT_UI1;
SafeArrayGetElement(psa, &inx, &V_UI1(pvResult));
break;
default :
V_VT(pvResult) = VT_ERROR;
break;
}
return hr;
}
//-------------------------------------------------------------
// Name : CheckArrayBounds
//
// Description : Check that index is within bounds and if not
// Redim the array
//
// Parameters : psa - pointer to the SAFEARRAY
// inx - putative index
//-------------------------------------------------------------
void CheckArrayBounds(SAFEARRAY *psa, long inx)
{
long lBound, uBound;
SafeArrayGetUBound (psa, 1, &uBound);
SafeArrayGetLBound (psa, 1, &lBound);
if ((inx < lBound) || (inx > uBound))
{
// Need to redim
SAFEARRAYBOUND psaBound;
psaBound.cElements = ((inx < lBound) ?
(uBound + 1 - inx) : (inx + 1 - lBound));
psaBound.lLbound = (inx < lBound) ? inx : lBound;
SafeArrayRedim (psa, &psaBound);
}
}
//-------------------------------------------------------------
// Name : assignVariantToArrayElement
//
// Description : According to the type of the array elements,
// puts the new value from the variant into the
// requested element of the array
//
// Parameters : psa - pointer to the SAFEARRAY
// vt - vartype of array elements
// inx - index of the element in the array
// pvNewVal - variant containing the new value
//-------------------------------------------------------------
void assignVariantToArrayElement(SAFEARRAY *psa, VARTYPE vt, long inx, VARIANT *pvNewVal)
{
HRESULT hr = E_FAIL;
// Firstly check for out-of-bounds case and grow accordingly
CheckArrayBounds (psa, inx);
switch (vt)
{
case VT_I2 :
hr = SafeArrayPutElement(psa, &inx, &V_I2(pvNewVal));
break;
case VT_I4 :
hr = SafeArrayPutElement(psa, &inx, &V_I4(pvNewVal));
break;
case VT_R4 :
hr = SafeArrayPutElement(psa, &inx, &V_R4(pvNewVal));
break;
case VT_R8 :
hr = SafeArrayPutElement(psa, &inx, &V_R8(pvNewVal));
break;
case VT_DATE :
hr = SafeArrayPutElement(psa, &inx, &V_DATE(pvNewVal));
break;
case VT_BSTR :
hr = SafeArrayPutElement(psa, &inx, V_BSTR(pvNewVal));
break;
case VT_DISPATCH :
hr = SafeArrayPutElement(psa, &inx, V_DISPATCH(pvNewVal));
break;
case VT_UNKNOWN:
hr = SafeArrayPutElement(psa, &inx, V_UNKNOWN(pvNewVal));
break;
case VT_BOOL :
hr = SafeArrayPutElement(psa, &inx, &V_BOOL(pvNewVal));
break;
case VT_VARIANT :
hr = SafeArrayPutElement(psa, &inx, V_VARIANTREF(pvNewVal));
break;
case VT_UI1 :
hr = SafeArrayPutElement(psa, &inx, &V_UI1(pvNewVal));
break;
default :
//????????????
break;
} //switch
}
//-------------------------------------------------------------
// Name : CimTypeToVtType
//
// Description : Returns the coresponding VARTYPE for
// a given CIMTYPE
// Parameters : lType - the CIMTYPE we want to convert
//-------------------------------------------------------------
VARTYPE CimTypeToVtType(CIMTYPE lType)
{
VARTYPE ret = VT_EMPTY;
if (lType & CIM_FLAG_ARRAY)
ret = VT_ARRAY;
switch(lType & ~CIM_FLAG_ARRAY)
{
case CIM_EMPTY : ret = (ret | VT_EMPTY); break;
case CIM_SINT8 : ret = (ret | VT_I2); break;
case CIM_UINT8 : ret = (ret | VT_UI1); break;
case CIM_SINT16 : ret = (ret | VT_I2); break;
case CIM_UINT16 : ret = (ret | VT_I4); break;
case CIM_SINT32 : ret = (ret | VT_I4); break;
case CIM_UINT32 : ret = (ret | VT_I4); break;
case CIM_SINT64 : ret = (ret | VT_BSTR); break;
case CIM_UINT64 : ret = (ret | VT_BSTR); break;
case CIM_REAL32 : ret = (ret | VT_R4); break;
case CIM_REAL64 : ret = (ret | VT_R8); break;
case CIM_BOOLEAN : ret = (ret | VT_BOOL); break;
case CIM_STRING : ret = (ret | VT_BSTR); break;
case CIM_DATETIME : ret = (ret | VT_BSTR); break;
case CIM_REFERENCE :ret = (ret | VT_BSTR); break;
case CIM_CHAR16 : ret = (ret | VT_I2); break;
case CIM_OBJECT : ret = (ret | VT_UNKNOWN); break;
default : ret = VT_ERROR;
}
return ret;
}
//-------------------------------------------------------------
// Name : VariantChangeByValToByRef
//
// Description : Copies a variant, while converting a "byval" to a
// "byref" if the destination type requires it
//
// Parameters : dest - destination variant to hold the result
// source - source variant to be copied
// destType - the VARTYPE required for the result.
// when this type is a BY_REF, the appropriate
// conversion is made from the source.
//-------------------------------------------------------------
HRESULT VariantChangeByValToByRef(VARIANT *dest, VARIANT *source, VARTYPE destType)
{
HRESULT hr = S_OK;
if (!(destType & VT_BYREF)) //the destination is not by ref. we can do a straight copy
hr = VariantCopy(dest, source);
else
{
if ((destType & ~VT_BYREF) & VT_ARRAY)
hr = SafeArrayCopy(V_ARRAY(source), V_ARRAYREF(dest));
else
{
switch (destType & ~VT_BYREF)
{
case VT_UI1 : *V_UI1REF(dest) = V_UI1(source); break;
case VT_I2 : *V_I2REF(dest) = V_I2(source); break;
case VT_I4 : *V_I4REF(dest) = V_I4(source); break;
case VT_R4 : *V_R4REF(dest) = V_R4(source); break;
case VT_R8 : *V_R8REF(dest) = V_R8(source); break;
case VT_CY : *V_CYREF(dest) = V_CY(source); break;
case VT_BSTR : SysReAllocString(V_BSTRREF(dest), V_BSTR(source)); break;
case VT_BOOL : *V_BOOLREF(dest) = V_BOOL(source); break;
case VT_DATE : *V_DATEREF(dest) = V_DATE(source); break;
case VT_DISPATCH :
//I need to addref the object behind this interface so
//that it doesn't get released when we release the original VARIANT
//that's holding it
V_DISPATCH(source)->AddRef();
*V_DISPATCHREF(dest) = V_DISPATCH(source);
break;
case VT_UNKNOWN :
//Again, need to addref so that the object doesn't get released
V_UNKNOWN(source)->AddRef();
*V_UNKNOWNREF(dest) = V_UNKNOWN(source); break;
break;
case VT_VARIANT : hr = VariantCopy(V_VARIANTREF(dest), source); break;
default : hr = DISP_E_TYPEMISMATCH;
}
}
}
return hr;
}
//***************************************************************************
//
// void CWbemDispatchMgr::EnsureClassRetrieved
//
// DESCRIPTION:
//
// Make sure we have a class pointer
//
//***************************************************************************
void CWbemDispatchMgr::EnsureClassRetrieved ()
{
if (!m_pWbemClass)
{
CComVariant vGenusVal, vClassName;
bool bIsClass;
if (SUCCEEDED(m_pWbemObject->Get(WBEMS_SP_GENUS, 0, &vGenusVal, NULL, NULL)))
{
bIsClass = (WBEM_GENUS_CLASS == vGenusVal.lVal);
//If the object is a class, point the class pointer to it as well
if (bIsClass)
{
m_pWbemClass = m_pWbemObject;
m_pWbemClass->AddRef () ;
}
//Otherwise (it's an instance) we need to get the class
else
{
// Check we have an IWbemServices pointer
if (m_pWbemServices)
{
/*
* Note we must check that returned value is a BSTR - it could be a VT_NULL if
* the __CLASS property has not yet been set.
*/
if (SUCCEEDED(m_pWbemObject->Get(WBEMS_SP_CLASS, 0, &vClassName, NULL, NULL))
&& (VT_BSTR == V_VT(&vClassName)))
{
CComPtr<IWbemServices> pIWbemServices = m_pWbemServices->GetIWbemServices ();
if (pIWbemServices)
{
CSWbemSecurity *pSecurity = m_pWbemServices->GetSecurityInfo ();
if (pSecurity)
{
bool needToResetSecurity = false;
HANDLE hThreadToken = NULL;
if (pSecurity->SetSecurity (needToResetSecurity, hThreadToken))
pIWbemServices->GetObject (vClassName.bstrVal, 0, NULL, &m_pWbemClass, NULL);
// Restore original privileges on this thread
if (needToResetSecurity)
pSecurity->ResetSecurity (hThreadToken);
pSecurity->Release ();
}
}
}
}
}
}
}
}
//***************************************************************************
//
// SCODE CWbemDispatchMgr::HandleError
//
// DESCRIPTION:
//
// Provide bespoke handling of error conditions in the bolierplate
// Dispatch implementation.
//
// PARAMETERS:
//
// dispidMember, wFlags,
// pdispparams, pvarResult,
// puArgErr, All passed directly from IDispatch::Invoke
// hr The return code from the bolierplate invoke
//
// RETURN VALUES:
// The new return code (to be ultimately returned from Invoke)
//
// WBEM_S_NO_ERROR success
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
//***************************************************************************
HRESULT CWbemDispatchMgr::HandleError (
DISPID dispidMember,
unsigned short wFlags,
DISPPARAMS FAR* pdispparams,
VARIANT FAR* pvarResult,
UINT FAR* puArgErr,
HRESULT hr
)
{
/*
* We are looking for GET calls on the Derivation_ property which
* supplied an argument. Since this property returns a SAFEARRAY, this may
* be legal but undetectable by the standard Dispatch mechanism. It is meaningful
* to pass an index (the interpretation is that the index specifies an offset in
* the SAFEARRAY structure that represents the derivation value).
*/
if ((dispidMember == WBEMS_DISPID_DERIVATION) && (DISP_E_NOTACOLLECTION == hr) && (1 == pdispparams->cArgs)
&& (DISPATCH_PROPERTYGET & wFlags))
{
// Looks promising - get the __DERIVATION property to try and resolve this
if (m_pWbemObject)
{
VARIANT var;
VariantInit (&var);
if (WBEM_S_NO_ERROR == m_pWbemObject->Get (WBEMS_SP_DERIVATION, 0, &var, NULL, NULL))
{
/* The value should be a VT_BSTR|VT_ARRAY */
if (((VT_ARRAY | VT_BSTR) == var.vt) && (NULL != var.parray))
{
VARIANT indexVar;
VariantInit (&indexVar);
// Attempt to coerce the index argument into a value suitable for an array index
if (S_OK == VariantChangeType (&indexVar, &pdispparams->rgvarg[0], 0, VT_I4))
{
long lArrayPropInx = V_I4(&indexVar);
// We should have a VT_ARRAY|VT_BSTR value at this point; extract the
// BSTR and set it into the VARIANT
VariantInit (pvarResult);
BSTR nameValue = NULL;
if (SUCCEEDED(hr = SafeArrayGetElement (var.parray, &lArrayPropInx, &nameValue)))
{
VariantInit (pvarResult);
pvarResult->vt = VT_BSTR;
pvarResult->bstrVal = nameValue;
}
}
else
{
hr = DISP_E_TYPEMISMATCH;
if (puArgErr)
*puArgErr = 0;
}
VariantClear (&indexVar);
}
}
VariantClear (&var);
}
}
return hr;
}
// IDispatchEx methods
HRESULT STDMETHODCALLTYPE CWbemDispatchMgr::GetDispID(
/* [in] */ BSTR bstrName,
/* [in] */ DWORD grfdex,
/* [out] */ DISPID __RPC_FAR *pid)
{
return GetIDsOfNames(IID_NULL, &((OLECHAR *)bstrName), 1, ENGLISH_LOCALE, pid);
}
//***************************************************************************
//
// SCODE CWbemSchemaIDCache::~CWbemSchemaIDCache
//
// DESCRIPTION:
//
// Destructor
//
//***************************************************************************
CWbemSchemaIDCache::~CWbemSchemaIDCache ()
{
DispIDNameMap::iterator next;
while ((next = m_cache.begin ()) != m_cache.end ())
next = m_cache.erase (next);
}
//***************************************************************************
//
// SCODE CWbemSchemaIDCache::GetDispID
//
// DESCRIPTION:
//
// Attempts to resolves a set of names to DISP IDs based on WMI schema.
//
// PARAMETERS:
//
// rgszNames Array of names
// cNames Length of above array
// rgdispid Pointer to array to hold resolved DISPIDs
//
// RETURN VALUES:
//
//***************************************************************************
HRESULT CWbemSchemaIDCache::GetDispID (
LPWSTR* rgszNames,
unsigned int cNames,
DISPID* rgdispid
)
{
HRESULT hr = E_FAIL;
if (0 < cNames)
{
DispIDNameMap::iterator theIterator = m_cache.find (rgszNames [0]);
if (theIterator != m_cache.end ())
{
hr = S_OK;
rgdispid [0] = (*theIterator).second;
}
else
{
if ((1 == cNames) && FindPropertyName (rgszNames [0]))
{
// Get a new dispid and add it to the cache
CWbemDispID dispId;
if (dispId.SetAsSchemaID (++m_nextId))
{
rgdispid [0] = dispId;
m_cache.insert (DispIDNameMap::value_type (rgszNames [0],
dispId));
hr = S_OK;
}
}
else
{
//If no property name matches, go on to methods
SAFEARRAY *psaInParams = NULL; //array of in parameters names
SAFEARRAY *psaOutParams = NULL; //array of out parameter names
CComPtr<IWbemClassObject> pInParams;
CComPtr<IWbemClassObject> pOutParams;
bool bMethodFound = false;
long id = 0;
bool bUnknownParameterFound = false;
//Get the names of all method parameters (in and out)
if (GetMethod (rgszNames[0], &psaInParams, &psaOutParams,
pInParams, pOutParams))
{
bMethodFound = true;
unsigned long ulParamCount;
bool ok = true;
//For each named parameter, search for it in the method parameters
for (ulParamCount=1; ok && (ulParamCount < cNames); ulParamCount++)
{
//If we find this name in the "in" parameters list, attach the id and go on
if (psaInParams && FindMemberInArray(rgszNames[ulParamCount], psaInParams))
{
if (GetIdOfMethodParameter(rgszNames[ulParamCount], //param name
pInParams,
&id))
rgdispid[ulParamCount] = id;
else
ok = false;
}
//If it's not in the "in" parameters, check the "out" parameters list
else if (psaOutParams && FindMemberInArray(rgszNames[ulParamCount], psaOutParams))
{
if (GetIdOfMethodParameter(rgszNames[ulParamCount], //param name
pOutParams,
&id))
rgdispid[ulParamCount] = id;
else
ok = false;
}
//If it's not there either - we can't find it
else
{
rgdispid[ulParamCount] = DISPID_UNKNOWN;
bUnknownParameterFound = true;
}
} //walk parameters
if (!ok)
bMethodFound = false;
}
if (psaInParams)
SafeArrayDestroy(psaInParams);
if (psaOutParams)
SafeArrayDestroy(psaOutParams);
if (!bMethodFound)
hr = E_FAIL;
else if (bUnknownParameterFound)
hr = DISP_E_UNKNOWNNAME;
else
hr = S_OK;
// Finally, if this all worked add it to the cache as a method
if (SUCCEEDED(hr))
{
CWbemDispID dispId;
if (dispId.SetAsSchemaID (++m_nextId, false))
{
rgdispid [0] = dispId;
m_cache.insert (DispIDNameMap::value_type (rgszNames [0],
dispId));
}
else
hr = E_FAIL;
}
}
}
}
return hr;
}
//***************************************************************************
//
// bool CWbemSchemaIDCache::FindPropertyName
//
// DESCRIPTION:
//
// Determine whether the property exists for this object and is not
// a system property
//
// PARAMETERS:
//
// bsName - name of specified property
//
// RETURN VALUES:
//
//***************************************************************************
bool CWbemSchemaIDCache::FindPropertyName(
BSTR bsName
)
{
bool result = false;;
if (m_pDispatchMgr)
{
CComPtr<IWbemClassObject> pIWbemClassObject = m_pDispatchMgr->GetObject ();
if (pIWbemClassObject)
{
//Note : This limits the support to non-system properties only !!!
LONG lFlavor = 0;
if (SUCCEEDED(pIWbemClassObject->Get(bsName, 0, NULL, NULL, &lFlavor))
&& !(WBEM_FLAVOR_ORIGIN_SYSTEM & lFlavor))
result = true;
}
}
return result;
}
//***************************************************************************
//
// bool CWbemSchemaIDCache::GetMethod
//
// DESCRIPTION:
//
// returns the parameter names of a method in two
// safearrays - one for in and one for out
//
// PARAMETERS:
//
// bstrMethodName - name of method requested
// ppsaInParams - pointer to safearray to return
// in parameters
// ppsaOutParams - pointer to safearray to return
// out parameters
//
// RETURN VALUES:
//
//***************************************************************************
bool CWbemSchemaIDCache::GetMethod(
BSTR bstrMethodName,
SAFEARRAY **ppsaInParams,
SAFEARRAY **ppsaOutParams,
CComPtr<IWbemClassObject> & pInParamsObject,
CComPtr<IWbemClassObject> & pOutParamsObject
)
{
bool result = false;
CComPtr<IWbemClassObject> pIWbemClassObject = m_pDispatchMgr->GetClassObject ();
if (pIWbemClassObject)
{
if (SUCCEEDED(pIWbemClassObject->GetMethod(bstrMethodName, 0, &pInParamsObject, &pOutParamsObject)))
{
*ppsaInParams = NULL;
*ppsaOutParams = NULL;
bool ok = true;
if (pInParamsObject)
{
if (FAILED(pInParamsObject->GetNames(NULL, 0, NULL, ppsaInParams)))
ok = false;
}
if (ok && pOutParamsObject)
{
if (FAILED(pOutParamsObject->GetNames(NULL, 0, NULL, ppsaOutParams)))
ok = false;
}
result = ok;
}
}
return result;
}
//***************************************************************************
//
// bool CWbemSchemaIDCache::GetIdOfMethodParameter
//
// DESCRIPTION:
//
// gets the id of a given parameter for a given method
// (this is a qualifier on the parameter property in the
// InParameters/OutParameters object)
//
// PARAMETERS:
//
// bstrParamName - parameter name
// pParams - IWbemClassObject containing parameters
// pId - pointer to long to receive the ID for this
// parameter of this method
//
// RETURN VALUES:
//
//***************************************************************************
bool CWbemSchemaIDCache::GetIdOfMethodParameter(
BSTR bstrParamName,
CComPtr<IWbemClassObject> &pParams,
long *pId
)
{
bool result = false;
if (pParams)
{
CComPtr<IWbemQualifierSet> pQualSet;
//Get qualifier set for the required parameter property
if (SUCCEEDED(pParams->GetPropertyQualifierSet(bstrParamName, &pQualSet)))
{
CComVariant vIdVal;
//Get the "id" qualifier value
if (SUCCEEDED(pQualSet->Get(L"id", 0, &vIdVal, NULL)))
{
result = true;
*pId = vIdVal.lVal;
}
}
}
return result;
}
//***************************************************************************
//
// bool CWbemSchemaIDCache::GetName
//
// DESCRIPTION:
//
// gets the name of the item given a DISPID
//
// PARAMETERS:
//
// dispId - id whose name we require
// bsName - the name (on successful return)
//
// RETURN VALUES:
//
//***************************************************************************
bool CWbemSchemaIDCache::GetName (
DISPID dispId,
CComBSTR & bsName
)
{
bool result = false;
DispIDNameMap::iterator theIterator = m_cache.begin ();
while (theIterator != m_cache.end ())
{
if (dispId == (*theIterator).second)
{
bsName = (*theIterator).first;
result = true;
break;
}
else
theIterator++;
}
return result;
}
//***************************************************************************
//
// bool CWbemSchemaIDCache::FindMemberInArray
//
// DESCRIPTION:
//
// determine whether a name is present in a SAFEARRAY
//
// PARAMETERS:
//
// bstrName - the name we're looking for
// psaNames - SAFEARRAY we're looking in
//
// RETURN VALUES:
// true if found, false o/w
//
//***************************************************************************
bool CWbemSchemaIDCache::FindMemberInArray(BSTR bstrName, SAFEARRAY *psaNames)
{
long lUBound;
long i;
//Walk the array and check if the requested name exists
SafeArrayGetUBound(psaNames, 1, &lUBound);
for (i=0; i <= lUBound; i++)
{
CComBSTR bstrMemberName;
SafeArrayGetElement(psaNames, &i, &bstrMemberName);
if (!_wcsicmp(bstrMemberName, bstrName)) //found the property
break;
}
return (i <= lUBound);
}