//*************************************************************************** // // Copyright (c) 1998-2000 Microsoft Corporation // // NVALUE.CPP // // alanbos 15-Aug-96 Created. // // Defines the implementation of ISWbemNamedValue // //*************************************************************************** #include "precomp.h" //*************************************************************************** // // CSWbemNamedValue::CSWbemNamedValue // // DESCRIPTION: // // Constructor. // //*************************************************************************** CSWbemNamedValue::CSWbemNamedValue( CSWbemServices *pService, CSWbemNamedValueSet *pCSWbemNamedValueSet, BSTR name, bool bMutable ) : m_bMutable (bMutable), m_cRef (1), m_pCSWbemNamedValueSet (pCSWbemNamedValueSet), m_pSWbemServices (pService) { m_Dispatch.SetObj (this, IID_ISWbemNamedValue, CLSID_SWbemNamedValue, L"SWbemNamedValue"); if (m_pCSWbemNamedValueSet) m_pCSWbemNamedValueSet->AddRef (); if (m_pSWbemServices) m_pSWbemServices->AddRef (); m_name = SysAllocString (name); InterlockedIncrement(&g_cObj); } //*************************************************************************** // // CSWbemNamedValue::~CSWbemNamedValue // // DESCRIPTION: // // Destructor. // //*************************************************************************** CSWbemNamedValue::~CSWbemNamedValue(void) { InterlockedDecrement(&g_cObj); if (m_pCSWbemNamedValueSet) { m_pCSWbemNamedValueSet->Release (); m_pCSWbemNamedValueSet = NULL; } if (m_pSWbemServices) { m_pSWbemServices->Release (); m_pSWbemServices = NULL; } SysFreeString (m_name); } //*************************************************************************** // HRESULT CSWbemNamedValue::QueryInterface // long CSWbemNamedValue::AddRef // long CSWbemNamedValue::Release // // DESCRIPTION: // // Standard Com IUNKNOWN functions. // //*************************************************************************** STDMETHODIMP CSWbemNamedValue::QueryInterface ( IN REFIID riid, OUT LPVOID *ppv ) { *ppv=NULL; if (IID_IUnknown==riid) *ppv = reinterpret_cast(this); else if (IID_ISWbemNamedValue==riid) *ppv = (ISWbemNamedValue *)this; else if (IID_IDispatch==riid) *ppv = (IDispatch *)this; else if (IID_ISupportErrorInfo==riid) *ppv = (ISupportErrorInfo *)this; else if (IID_IProvideClassInfo==riid) *ppv = (IProvideClassInfo *)this; if (NULL!=*ppv) { ((LPUNKNOWN)*ppv)->AddRef(); return NOERROR; } return ResultFromScode(E_NOINTERFACE); } STDMETHODIMP_(ULONG) CSWbemNamedValue::AddRef(void) { InterlockedIncrement(&m_cRef); return m_cRef; } STDMETHODIMP_(ULONG) CSWbemNamedValue::Release(void) { InterlockedDecrement(&m_cRef); if (0L!=m_cRef) return m_cRef; delete this; return 0; } //*************************************************************************** // HRESULT CSWbemNamedValue::InterfaceSupportsErrorInfo // // DESCRIPTION: // // Standard Com ISupportErrorInfo functions. // //*************************************************************************** STDMETHODIMP CSWbemNamedValue::InterfaceSupportsErrorInfo (IN REFIID riid) { return (IID_ISWbemNamedValue == riid) ? S_OK : S_FALSE; } //*************************************************************************** // // SCODE CSWbemNamedValue::get_Value // // DESCRIPTION: // // Retrieve the value // // PARAMETERS: // // pValue holds the value on return // // RETURN VALUES: // // WBEM_S_NO_ERROR success // WBEM_E_INVALID_PARAMETER bad input parameters // WBEM_E_FAILED otherwise // //*************************************************************************** HRESULT CSWbemNamedValue::get_Value ( VARIANT *pValue ) { HRESULT hr = WBEM_E_FAILED; ResetLastErrors (); if (NULL == pValue) hr = WBEM_E_INVALID_PARAMETER; else { VariantClear (pValue); IWbemContext *pIWbemContext = m_pCSWbemNamedValueSet->GetIWbemContext (); if (pIWbemContext) { hr = pIWbemContext->GetValue (m_name, 0, pValue); pIWbemContext->Release (); } } if (FAILED(hr)) m_Dispatch.RaiseException (hr); return hr; } //*************************************************************************** // // SCODE CSWbemNamedValue::put_Value // // DESCRIPTION: // // Set the value // // PARAMETERS: // // pVal the new value // // RETURN VALUES: // // WBEM_S_NO_ERROR success // WBEM_E_INVALID_PARAMETER bad input parameters // WBEM_E_FAILED otherwise // //*************************************************************************** HRESULT CSWbemNamedValue::put_Value ( VARIANT *pVal ) { HRESULT hr = WBEM_E_FAILED; ResetLastErrors (); if (NULL == pVal) hr = WBEM_E_INVALID_PARAMETER; else if (!m_bMutable) hr = WBEM_E_READ_ONLY; else { CComPtr pIWbemContext; //Can't assign directly because the raw pointer gets AddRef'd twice and we leak, //So we use Attach() instead to prevent the smart pointer from AddRef'ing. pIWbemContext.Attach(m_pCSWbemNamedValueSet->GetIWbemContext ()); if (pIWbemContext) { CWbemPathCracker *pPathCracker = m_pCSWbemNamedValueSet->GetWbemPathCracker (); CIMTYPE newCimType = CIM_ILLEGAL; if (VT_BYREF & V_VT(pVal)) { // We must dereference all byref's VARIANT var; VariantInit (&var); if (VT_ARRAY & V_VT(pVal)) { var.vt = V_VT(pVal) & ~VT_BYREF; hr = SafeArrayCopy (*(pVal->pparray), &(var.parray)); } else hr = VariantChangeType(&var, pVal, 0, V_VT(pVal) & ~VT_BYREF); if (SUCCEEDED(hr)) { // Here the oldCimType is a "serving suggestion" - if // we need a different cimtype to match the new value // so be it, even if it's CIM_ILLEGAL newCimType = MapVariantTypeToCimType (&var, CIM_ILLEGAL); bool ok = true; // If we have a keylist, must ensure we can set it in the // keylist first if (pPathCracker) { if (pPathCracker->SetKey (m_name, (WbemCimtypeEnum) newCimType, var)) ok = false; } if (ok) { // Finally set it in the context itself hr = pIWbemContext->SetValue (m_name, 0, &var); } else hr = WBEM_E_FAILED; } VariantClear (&var); } else if ((VT_ERROR == V_VT(pVal)) && (DISP_E_PARAMNOTFOUND == pVal->scode)) { // Treat as NULL assignment pVal->vt = VT_NULL; // NULL assigments not valid for keylists if (pPathCracker) hr = WBEM_E_FAILED; else { hr = pIWbemContext->SetValue (m_name, 0, pVal); } } else { // Here the oldCimType is a "serving suggestion" - if // we need a different cimtype to match the new value // so be it, even if it's CIM_ILLEGAL newCimType = MapVariantTypeToCimType (pVal, CIM_ILLEGAL); bool ok = true; // If we have a keylist, must ensure we can set it in the // keylist first if (pPathCracker) { if (pPathCracker->SetKey (m_name, (WbemCimtypeEnum) newCimType, *pVal)) ok = false; } if (ok) { // Finally set it in the context itself hr = pIWbemContext->SetValue (m_name, 0, pVal); } else hr = WBEM_E_FAILED; } if (pPathCracker) pPathCracker->Release (); } } if (FAILED(hr)) m_Dispatch.RaiseException (hr); return hr; } //*************************************************************************** // // SCODE CSWbemNamedValue::get_Name // // DESCRIPTION: // // Retrieve the value name // // PARAMETERS: // // pName holds the name on return // // RETURN VALUES: // // WBEM_S_NO_ERROR success // WBEM_E_INVALID_PARAMETER bad input parameters // WBEM_E_FAILED otherwise // //*************************************************************************** HRESULT CSWbemNamedValue::get_Name ( BSTR *pName ) { HRESULT hr = WBEM_S_NO_ERROR; ResetLastErrors (); if (NULL == pName) hr = WBEM_E_INVALID_PARAMETER; else *pName = SysAllocString (m_name); if (FAILED(hr)) m_Dispatch.RaiseException (hr); return hr; } //*************************************************************************** // // SCODE CSWbemNamedValue::CNamedValueDispatchHelp::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 CSWbemNamedValue::CNamedValueDispatchHelp::HandleError ( DISPID dispidMember, unsigned short wFlags, DISPPARAMS FAR* pdispparams, VARIANT FAR* pvarResult, UINT FAR* puArgErr, HRESULT hr ) { /* * We are looking for calls on the default member (the Value property) which * supplied an argument. Since the Value property is of type VARIANT, this may * be legal but undetectable by the standard Dispatch mechanism, because in the * the case that the named value happens to be an array type, it is meaningful to * pass an index (the interpretation is that the index specifies an offset in * the VT_ARRAY|VT_VARIANT structure that represents the named value). */ if ((DISPID_VALUE == dispidMember) && (DISP_E_NOTACOLLECTION == hr) && (pdispparams->cArgs > 0)) { // Looks promising - get the object to try and resolve this ISWbemNamedValue *pNamedValue = NULL; // This tells us where to expect the array index to appear in the argument list UINT indexArg = (DISPATCH_PROPERTYGET & wFlags) ? 0 : 1; if (SUCCEEDED (m_pObj->QueryInterface (IID_ISWbemNamedValue, (PPVOID) &pNamedValue))) { // Extract the current named value VARIANT vNVal; VariantInit (&vNVal); if (SUCCEEDED(pNamedValue->get_Value (&vNVal)) && V_ISARRAY(&vNVal)) { 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[indexArg], 0, VT_I4)) { long lArrayPropInx = V_I4(&indexVar); // Is this a Get? There should be one argument (the array index) if (DISPATCH_PROPERTYGET & wFlags) { if (1 == pdispparams->cArgs) { // We should have a VT_ARRAY|VT_VARIANT value at this point; extract the // VARIANT VariantInit (pvarResult); hr = SafeArrayGetElement (vNVal.parray, &lArrayPropInx, pvarResult); } else hr = DISP_E_BADPARAMCOUNT; } else if (DISPATCH_PROPERTYPUT & wFlags) { if (2 == pdispparams->cArgs) { /* * Try to interpret this as an array member set operation. For * this the first argument passed is the new value, and the second * is the array index. */ VARIANT vNewVal; VariantInit(&vNewVal); if (SUCCEEDED(VariantCopy(&vNewVal, &pdispparams->rgvarg[0]))) { // Check the index is not out of bounds and, if it is, grow // the array accordingly CheckArrayBounds (vNVal.parray, lArrayPropInx); // How do we decide on the type - try to access an array // member and use that type VARTYPE expectedVarType = VT_ILLEGAL; VARIANT dummyVar; VariantInit (&dummyVar); long lBound; SafeArrayGetLBound (vNVal.parray, 1, &lBound); if (SUCCEEDED (SafeArrayGetElement (vNVal.parray, &lBound, &dummyVar))) expectedVarType = V_VT(&dummyVar); VariantClear (&dummyVar); if (S_OK == VariantChangeType (&vNewVal, &vNewVal, 0, expectedVarType)) { // Set the value into the relevant index of the named value array if (S_OK == (hr = SafeArrayPutElement (vNVal.parray, &lArrayPropInx, &vNewVal))) { // Set the entire property value if (SUCCEEDED (pNamedValue->put_Value (&vNVal))) hr = S_OK; else { hr = DISP_E_TYPEMISMATCH; if (puArgErr) *puArgErr = 0; } } } else { hr = DISP_E_TYPEMISMATCH; if (puArgErr) *puArgErr = 0; } VariantClear (&vNewVal); } } else hr = DISP_E_BADPARAMCOUNT; } } else { hr = DISP_E_TYPEMISMATCH; if (puArgErr) *puArgErr = indexArg; } VariantClear (&indexVar); } VariantClear (&vNVal); } pNamedValue->Release (); } return hr; }