//*************************************************************************** // // Copyright (c) 1998-1999 Microsoft Corporation // // PROPSET.CPP // // alanbos 15-Aug-96 Created. // // Defines the implementation of ISWbemPropertySet // //*************************************************************************** #include "precomp.h" //*************************************************************************** // // CSWbemPropertySet::CSWbemPropertySet // // DESCRIPTION: // // Constructor. // //*************************************************************************** CSWbemPropertySet::CSWbemPropertySet( CSWbemServices *pService, CSWbemObject *pObject, bool bSystemProperties) : m_bSystemProperties (bSystemProperties) { m_Dispatch.SetObj (this, IID_ISWbemPropertySet, CLSID_SWbemPropertySet, L"SWbemPropertySet"); m_pSWbemObject = pObject; m_pSWbemObject->AddRef (); m_pIWbemClassObject = m_pSWbemObject->GetIWbemClassObject (); m_pSite = new CWbemObjectSite (m_pSWbemObject); m_pSWbemServices = pService; if (m_pSWbemServices) m_pSWbemServices->AddRef (); m_cRef=1; InterlockedIncrement(&g_cObj); } //*************************************************************************** // // CSWbemPropertySet::~CSWbemPropertySet // // DESCRIPTION: // // Destructor. // //*************************************************************************** CSWbemPropertySet::~CSWbemPropertySet() { InterlockedDecrement(&g_cObj); if (m_pSWbemObject) m_pSWbemObject->Release (); if (m_pIWbemClassObject) { m_pIWbemClassObject->EndEnumeration (); m_pIWbemClassObject->Release (); } if (m_pSWbemServices) m_pSWbemServices->Release (); if (m_pSite) m_pSite->Release (); } //*************************************************************************** // HRESULT CSWbemPropertySet::QueryInterface // long CSWbemPropertySet::AddRef // long CSWbemPropertySet::Release // // DESCRIPTION: // // Standard Com IUNKNOWN functions. // //*************************************************************************** STDMETHODIMP CSWbemPropertySet::QueryInterface ( IN REFIID riid, OUT LPVOID *ppv ) { *ppv=NULL; if (IID_IUnknown==riid) *ppv = reinterpret_cast(this); else if (IID_ISWbemPropertySet==riid) *ppv = (ISWbemPropertySet *)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) CSWbemPropertySet::AddRef(void) { InterlockedIncrement(&m_cRef); return m_cRef; } STDMETHODIMP_(ULONG) CSWbemPropertySet::Release(void) { LONG cRef = InterlockedDecrement(&m_cRef); if (0 != cRef) { _ASSERT(cRef > 0); return cRef; } delete this; return 0; } //*************************************************************************** // HRESULT CSWbemPropertySet::InterfaceSupportsErrorInfo // // DESCRIPTION: // // Standard Com ISupportErrorInfo functions. // //*************************************************************************** STDMETHODIMP CSWbemPropertySet::InterfaceSupportsErrorInfo (IN REFIID riid) { return (IID_ISWbemPropertySet == riid) ? S_OK : S_FALSE; } //*************************************************************************** // // SCODE CSWbemPropertySet::Item // // DESCRIPTION: // // Get a property // // PARAMETERS: // // bsName The name of the property // lFlags Flags // ppProp On successful return addresses the ISWbemProperty // // RETURN VALUES: // // WBEM_S_NO_ERROR success // WBEM_E_INVALID_PARAMETER bad input parameters // WBEM_E_FAILED otherwise // // Other WBEM error codes may be returned by ConnectServer etc., in which // case these are passed on to the caller. // //*************************************************************************** HRESULT CSWbemPropertySet::Item ( BSTR bsName, long lFlags, ISWbemProperty ** ppProp ) { HRESULT hr = WBEM_E_FAILED; ResetLastErrors (); if (NULL == ppProp) hr = WBEM_E_INVALID_PARAMETER; else { *ppProp = NULL; if (m_pIWbemClassObject) { long flavor = 0; if (WBEM_S_NO_ERROR == (hr = m_pIWbemClassObject->Get (bsName, lFlags, NULL, NULL, &flavor))) { // First we check if this is a system property. if (((WBEM_FLAVOR_ORIGIN_SYSTEM == (flavor & WBEM_FLAVOR_MASK_ORIGIN)) && m_bSystemProperties) || ((WBEM_FLAVOR_ORIGIN_SYSTEM != (flavor & WBEM_FLAVOR_MASK_ORIGIN)) && !m_bSystemProperties)) { if (!(*ppProp = new CSWbemProperty (m_pSWbemServices, m_pSWbemObject, bsName))) hr = WBEM_E_OUT_OF_MEMORY; } else hr = WBEM_E_NOT_FOUND; } } } if (FAILED(hr)) m_Dispatch.RaiseException (hr); return hr; } //*************************************************************************** // // SCODE CSWbemPropertySet::Add // // DESCRIPTION: // // Add a property. Note that the property is created with a NULL value. // If a non-NULL value is required, SetValue should // be called on the returned ISWbemProperty. // // PARAMETERS: // // bsName The name of the property // cimType The CIMTYPE (only needed for new properties, o/w // should be CIM_EMPTY). // flavor Flavor // // RETURN VALUES: // // The new property (if successful) // // WBEM_S_NO_ERROR success // WBEM_E_INVALID_PARAMETER bad input parameters // WBEM_E_FAILED otherwise // //*************************************************************************** HRESULT CSWbemPropertySet::Add ( BSTR bsName, WbemCimtypeEnum cimType, VARIANT_BOOL bIsArray, long lFlags, ISWbemProperty **ppProp ) { HRESULT hr = WBEM_E_FAILED; ResetLastErrors (); if ((NULL == ppProp) || (NULL == bsName)) hr = WBEM_E_INVALID_PARAMETER; else { *ppProp = NULL; if (m_pIWbemClassObject) { /* * If we are a system property collection we * check if the name begins "__" */ if (!m_bSystemProperties || (0 == _wcsnicmp (L"__", bsName, 2))) { /* * Create the property with the required cimtype and no value. */ CIMTYPE cimomType = (CIMTYPE) cimType; if (bIsArray) cimomType |= CIM_FLAG_ARRAY; if (SUCCEEDED(hr = m_pIWbemClassObject->Put (bsName, 0, NULL, cimomType))) { if (!(*ppProp = new CSWbemProperty (m_pSWbemServices, m_pSWbemObject, bsName))) hr = WBEM_E_OUT_OF_MEMORY; } } } } if (FAILED(hr)) m_Dispatch.RaiseException (hr); else { // Propagate the change to the owning site if (m_pSite) m_pSite->Update (); } return hr; } //*************************************************************************** // // SCODE CSWbemPropertySet::Remove // // DESCRIPTION: // // Delete a property // // PARAMETERS: // // bsName The name of the property // // RETURN VALUES: // // WBEM_S_NO_ERROR success // WBEM_E_INVALID_PARAMETER bad input parameters // WBEM_E_FAILED otherwise // //*************************************************************************** HRESULT CSWbemPropertySet::Remove ( BSTR bsName, long lFlags ) { HRESULT hr = WBEM_E_FAILED; ResetLastErrors (); if (NULL == bsName) hr = WBEM_E_INVALID_PARAMETER; else { if (m_pIWbemClassObject) hr = m_pIWbemClassObject->Delete (bsName); // Translate default reset case to an error if (WBEM_S_RESET_TO_DEFAULT == hr) hr = wbemErrResetToDefault; } if (FAILED(hr)) m_Dispatch.RaiseException (hr); if (SUCCEEDED(hr) || (wbemErrResetToDefault == hr)) { // Propagate the change to the owning site if (m_pSite) m_pSite->Update (); } return hr; } //*************************************************************************** // // SCODE CSWbemPropertySet::BeginEnumeration // // DESCRIPTION: // // Begin an enumeration of the properties // // RETURN VALUES: // // WBEM_S_NO_ERROR success // WBEM_E_INVALID_PARAMETER bad input parameters // WBEM_E_FAILED otherwise // //*************************************************************************** HRESULT CSWbemPropertySet::BeginEnumeration () { HRESULT hr = WBEM_E_FAILED; ResetLastErrors (); /* * Note that we do not expose system properties through this * API via the property set, so we supress them here. */ if (m_pIWbemClassObject) { hr = m_pIWbemClassObject->EndEnumeration (); hr = m_pIWbemClassObject->BeginEnumeration (m_bSystemProperties ? WBEM_FLAG_SYSTEM_ONLY : WBEM_FLAG_NONSYSTEM_ONLY); } if (FAILED(hr)) m_Dispatch.RaiseException (hr); return hr; } //*************************************************************************** // // SCODE CSWbemPropertySet::Next // // DESCRIPTION: // // Get next property in enumeration // // PARAMETERS: // // lFlags Flags // ppProp Next property (or NULL if end of enumeration) // // RETURN VALUES: // // WBEM_S_NO_ERROR success // WBEM_E_INVALID_PARAMETER bad input parameters // WBEM_E_FAILED otherwise // //*************************************************************************** HRESULT CSWbemPropertySet::Next ( long lFlags, ISWbemProperty ** ppProp ) { HRESULT hr = WBEM_E_FAILED; ResetLastErrors (); if (NULL == ppProp) hr = WBEM_E_INVALID_PARAMETER; else { *ppProp = NULL; if (m_pIWbemClassObject) { BSTR bsName = NULL; if (WBEM_S_NO_ERROR == (hr = m_pIWbemClassObject->Next (lFlags, &bsName, NULL, NULL, NULL))) { if (!(*ppProp = new CSWbemProperty (m_pSWbemServices, m_pSWbemObject, bsName))) hr = WBEM_E_OUT_OF_MEMORY; SysFreeString (bsName); } } } if (FAILED(hr)) m_Dispatch.RaiseException (hr); return hr; } //*************************************************************************** // // SCODE CSWbemPropertySet::get__NewEnum // // DESCRIPTION: // // Return an IEnumVARIANT-supporting interface for collections // // PARAMETERS: // // ppUnk on successful return addresses the IUnknown interface // // RETURN VALUES: // // S_OK success // E_FAIL otherwise // //*************************************************************************** HRESULT CSWbemPropertySet::get__NewEnum ( IUnknown **ppUnk ) { HRESULT hr = E_FAIL; ResetLastErrors (); if (NULL != ppUnk) { *ppUnk = NULL; CPropSetEnumVar *pEnum = new CPropSetEnumVar (this); if (!pEnum) hr = WBEM_E_OUT_OF_MEMORY; else if (FAILED(hr = pEnum->QueryInterface (IID_IUnknown, (PPVOID) ppUnk))) delete pEnum; } if (FAILED(hr)) m_Dispatch.RaiseException (hr); return hr; } //*************************************************************************** // // SCODE CSWbemPropertySet::get_Count // // DESCRIPTION: // // Return the number of items in the collection // // PARAMETERS: // // plCount on successful return addresses the count // // RETURN VALUES: // // S_OK success // E_FAIL otherwise // //*************************************************************************** HRESULT CSWbemPropertySet::get_Count ( long *plCount ) { HRESULT hr = E_FAIL; ResetLastErrors (); if (NULL != plCount) { *plCount = 0; if (m_pIWbemClassObject) { if (m_bSystemProperties) { // Rats - have to enumerate SAFEARRAY *pArray = NULL; if (WBEM_S_NO_ERROR == m_pIWbemClassObject->GetNames (NULL, WBEM_FLAG_SYSTEM_ONLY, NULL, &pArray)) { long lUBound = 0, lLBound = 0; SafeArrayGetUBound (pArray, 1, &lUBound); SafeArrayGetLBound (pArray, 1, &lLBound); *plCount = lUBound - lLBound + 1; SafeArrayDestroy (pArray); hr = S_OK; } } else { // S'easy - just use __PROPERTY_COUNT VARIANT var; VariantInit (&var); BSTR propCount = SysAllocString (OLESTR("__PROPERTY_COUNT")); if (WBEM_S_NO_ERROR == m_pIWbemClassObject->Get (propCount, 0, &var, NULL, NULL)) { *plCount = var.lVal; hr = S_OK; } VariantClear (&var); SysFreeString (propCount); } } } if (FAILED(hr)) m_Dispatch.RaiseException (hr); return hr; } //*************************************************************************** // // SCODE CSWbemPropertySet::CPropertySetDispatchHelp::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 CSWbemPropertySet::CPropertySetDispatchHelp::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 Item method) which * are PUTs that supplied an argument. These are triggered by attempts * to set a value of a property (Item) in the collection. * The first argument should be the new value for the item, and the second * argument should be the name of the item. */ if ((DISPID_VALUE == dispidMember) && (DISP_E_MEMBERNOTFOUND == hr) && (2 == pdispparams->cArgs) && (DISPATCH_PROPERTYPUT == wFlags)) { // Looks promising - get the object to try and resolve this ISWbemPropertySet *pPropertySet = NULL; if (SUCCEEDED (m_pObj->QueryInterface (IID_ISWbemPropertySet, (PPVOID) &pPropertySet))) { VARIANT valueVar; VariantInit (&valueVar); if (SUCCEEDED(VariantCopy(&valueVar, &pdispparams->rgvarg[0]))) { VARIANT nameVar; VariantInit (&nameVar); if (SUCCEEDED(VariantCopy(&nameVar, &pdispparams->rgvarg[1]))) { // Check name is a BSTR and use it to get the item if (VT_BSTR == V_VT(&nameVar)) { ISWbemProperty *pProperty = NULL; if (SUCCEEDED (pPropertySet->Item (V_BSTR(&nameVar), 0, &pProperty))) { // Try and put the value if (SUCCEEDED (pProperty->put_Value (&valueVar))) hr = S_OK; else { hr = DISP_E_TYPEMISMATCH; if (puArgErr) *puArgErr = 0; } pProperty->Release (); } } else { hr = DISP_E_TYPEMISMATCH; if (puArgErr) *puArgErr = 1; } VariantClear (&nameVar); } VariantClear (&valueVar); } pPropertySet->Release (); } } return hr; }