/*++ Copyright (C) 1995-2001 Microsoft Corporation Module Name: IMPDYN.CPP Abstract: Defines the virtual base class for the Dynamic Provider objects. The base class is overriden for each specific provider which provides the details of how an actual property "Put" or "Get" is done. History: a-davj 27-Sep-95 Created. --*/ #include "precomp.h" #include //#define _MT #include #include "impdyn.h" #include "CVariant.h" #include #include #include #include //*************************************************************************** // // CImpDyn::CImpDyn // // DESCRIPTION: // // Constructor. // // PARAMETERS: // // ObjectPath Full path to the namespace // User User name // Password Password // //*************************************************************************** CImpDyn::CImpDyn() : m_pGateway(NULL), m_cRef(0) { wcCLSID[0] = 0; // Set to correct value in derived class constructors } HRESULT STDMETHODCALLTYPE CImpDyn::Initialize(LPWSTR wszUser, long lFlags, LPWSTR wszNamespace, LPWSTR wszLocale, IWbemServices* pNamespace, IWbemContext* pContext, IWbemProviderInitSink* pSink) { m_pGateway = pNamespace; m_pGateway->AddRef(); pSink->SetStatus(WBEM_S_NO_ERROR, 0); return WBEM_S_NO_ERROR; } //*************************************************************************** // // CImpDyn::~CImpDyn // // DESCRIPTION: // // Destructor. // //*************************************************************************** CImpDyn::~CImpDyn(void) { if(m_pGateway) m_pGateway->Release(); return; } //*************************************************************************** // // SCODE CImpDyn::CreateInstanceEnum // // DESCRIPTION: // // Creates an enumerator object that can be used to enumerate // the instances of this class. // // PARAMETERS: // // Class Path specifying the class to be enumerated // lFlags flags to control the enumeration // phEnum returned pointer to enumerator // ppErrorObject returned pointer to error object // // RETURN VALUE: // // S_OK if all is well // WBEM_E_OUT_OF_MEMORY if not enough memory // various error codes from IWbemServices::GetObject // //*************************************************************************** SCODE CImpDyn::CreateInstanceEnum( IN const BSTR Class, IN long lFlags, IWbemContext *pCtx, OUT IN IEnumWbemClassObject FAR* FAR* phEnum) { CEnumInst * pEnumObj; SCODE sc; WCHAR * pwcClassContext = NULL; IWbemClassObject * pClassInt = NULL; CEnumInfo * pInfo = NULL; // Get the class sc = m_pGateway->GetObject(Class,0, pCtx, &pClassInt,NULL); if(sc != S_OK) return sc; // Get the class context string sc = GetAttString(pClassInt, NULL, L"classcontext", &pwcClassContext); pClassInt->Release(); if(sc != S_OK) return sc; // Get the info needed for enumeration. This is overrided by any // provider that supports dynamic instances. CProvObj ProvObj(pwcClassContext,MAIN_DELIM, NeedsEscapes()); sc = MakeEnum(pClassInt,ProvObj,&pInfo); delete pwcClassContext; if(sc != S_OK) return sc; pEnumObj=new CEnumInst(pInfo,lFlags,Class,m_pGateway,this, pCtx); if(pEnumObj == NULL) { delete pInfo; return WBEM_E_OUT_OF_MEMORY; } // Once the enumerator object is created, it owns the info object and // will free it appropriatly sc = pEnumObj->QueryInterface(IID_IEnumWbemClassObject,(void **) phEnum); if(FAILED(sc)) delete pEnumObj; return sc; } //*************************************************************************** // // CreateInstanceEnumAsyncThread // // DESCRIPTION: // // Routine for which does the work and sends the // subsequent notify for the Instance provider's CreateInstanceEnumAsync // routine. // // PARAMETERS: // // pIEnum Our enumerator // pSink Core's sink // pGateway IWbemServices pointer to the core // pCtx context to be used. // //*************************************************************************** void CreateInstanceEnumAsyncThread( IEnumWbemClassObject FAR* pIEnum, IWbemObjectSink FAR* pSink, IWbemServices FAR * pGateway, IWbemContext *pCtx) { IWbemClassObject * pNewInst = NULL; SCODE sc = S_OK; // enumerate and send each object to the notify interface while (sc == S_OK) { ULONG uRet; sc = pIEnum->Next(-1, 1,&pNewInst,&uRet); if(sc == S_OK) { pSink->Indicate(1,&pNewInst); pNewInst->Release(); } } pSink->SetStatus(0,0,NULL, NULL); } //*************************************************************************** // // SCODE CInstPro::CreateInstanceEnumAsync // // DESCRIPTION: // // Asynchronously enumeratres the instances of this class. // // PARAMETERS: // // RefStr Path which defines the object class // lFlags enumeration flags // pSink Pointer to the notify object // plAsyncRequestHandle pointer to the enumeration cancel handle (future use) // // RETURN VALUE: // // S_OK All is well // WBEM_E_INVALID_PARAMETER Bad argument // WBEM_E_OUT_OF_MEMORY Lacked resources to create a thread // otherwise, error from CreateInstanceEnum // //*************************************************************************** SCODE CImpDyn::CreateInstanceEnumAsync( IN const BSTR RefStr, IN long lFlags, IWbemContext __RPC_FAR *pCtx, OUT IWbemObjectSink FAR* pSink) { SCODE sc = S_OK; IEnumWbemClassObject * pIEnum = NULL; if(pSink == NULL || RefStr == NULL) return WBEM_E_INVALID_PARAMETER; if(IsNT() && IsDcomEnabled()) sc = WbemCoImpersonateClient(); if(sc == S_OK) sc = CreateInstanceEnum(RefStr,lFlags, pCtx, &pIEnum); if(sc != S_OK) { pSink->SetStatus(0, sc, NULL, NULL); return S_OK; } CreateInstanceEnumAsyncThread(pIEnum, pSink, m_pGateway, pCtx); pIEnum->Release(); return S_OK; } //*************************************************************************** // // SCODE CImpDyn::CreateClassEnumAsync // // DESCRIPTION: // // Asynchronously enumeratres the classes that this provider supplies. This is // acutally just a ruse to get the core to load the dll. // // PARAMETERS: // // SuperClass Parent to be enumerated. // lFlags enumeration flags // pResponseHandler Pointer to the notify object // plAsyncRequestHandle pointer to the enumeration cancel handle (future use) // // RETURN VALUE: // // S_OK All is well // //*************************************************************************** IWbemServices * gGateway; SCODE CImpDyn::CreateClassEnumAsync(BSTR Superclass, long lFlags,IWbemContext *pCtx, IWbemObjectSink FAR* pResponseHandler) { return E_NOTIMPL; } //*************************************************************************** // // SCODE CImpDyn::GetObject // // DESCRIPTION: // // Creates an instance given a particular path value. // // PARAMETERS: // // ObjectPath Object path // lFlags flags // pObj Set to point to the created object // ppErrorObject Optional error object pointer // // RETURN VALUE: // // S_OK All is well // WBEM_E_NOT_FOUND bad path // otherwise the return code from CreateInst // //*************************************************************************** SCODE CImpDyn::GetObject( IN BSTR ObjectPath, IN long lFlags, IWbemContext *pCtx, OUT IWbemClassObject FAR* FAR* pObj, IWbemCallResult **ppCallResult) { SCODE sc = S_OK; // Parse the object path. // ====================== ParsedObjectPath * pOutput = 0; CObjectPathParser p; int nStatus = p.Parse(ObjectPath, &pOutput); if(nStatus != 0) return ReturnAndSetObj(WBEM_E_NOT_FOUND, ppCallResult); WCHAR wcKeyValue[BUFF_SIZE]; sc = WBEM_E_NOT_FOUND; if(pOutput->m_dwNumKeys > 0 || pOutput->m_bSingletonObj) { if(pOutput->m_bSingletonObj) StringCchCopyW(wcKeyValue, BUFF_SIZE, L"@"); else { KeyRef *pTmp = pOutput->m_paKeys[0]; switch (V_VT(&pTmp->m_vValue)) { case VT_I4: StringCchPrintfW (wcKeyValue, BUFF_SIZE, L"%d", V_I4(&pTmp->m_vValue)); break; case VT_BSTR: wcsncpy(wcKeyValue, V_BSTR(&pTmp->m_vValue), BUFF_SIZE-1); break; default: StringCchCopyW(wcKeyValue, BUFF_SIZE, L"");; } } sc = CreateInst(m_pGateway,pOutput->m_pClass,wcKeyValue,pObj, NULL, NULL, pCtx); } // Create the instance. p.Free(pOutput); return ReturnAndSetObj(sc, ppCallResult); } //*************************************************************************** // // GetObjectAsyncThread // // DESCRIPTION: // // Routine for the thread which does the work and sends the // subsequent notify to the Instance provider's GetObjectAsync // routine. // // PARAMETERS: // // pTemp pointer to the argument structure // //*************************************************************************** void GetObjectAsyncThread(WCHAR * pObjPath, long lFlags, IWbemObjectSink FAR* pSink, CImpDyn * pThis, IWbemContext *pCtx) { IWbemClassObject FAR* pNewInst = NULL; SCODE sc = pThis->GetObject(pObjPath, lFlags, pCtx, &pNewInst, NULL); if(sc == WBEM_NO_ERROR) { pSink->Indicate(1,&pNewInst); pNewInst->Release(); } pSink->SetStatus(0, sc, NULL, NULL); } //*************************************************************************** // // SCODE CInstPro::GetObjectAsync // // DESCRIPTION: // // Asynchronously gets an instance of this class. // // PARAMETERS: // // RefStr Path which defines the object class // lFlags enumeration flags // pSink Pointer to the notify object // plAsyncRequestHandle pointer to the enumeration cancel handle (future use) // // RETURN VALUE: // // S_OK All is well // WBEM_E_INVALID_PARAMETER Bad argument // WBEM_E_OUT_OF_MEMORY Lacked resources to create a thread // //*************************************************************************** SCODE CImpDyn::GetObjectAsync( IN BSTR ObjPath, IN long lFlags, IWbemContext __RPC_FAR *pCtx, IN IWbemObjectSink FAR* pSink) { if(pSink == NULL || ObjPath == NULL) return WBEM_E_INVALID_PARAMETER; if(IsNT() && IsDcomEnabled()) { SCODE sc = WbemCoImpersonateClient(); if(sc != S_OK) { pSink->SetStatus(0, sc, NULL, NULL); return S_OK; } } GetObjectAsyncThread(ObjPath, lFlags, pSink, this, pCtx); return S_OK; } //*************************************************************************** // // SCODE CImpDyn::StartBatch // // DESCRIPTION: // // Called at the start of a batch of gets or puts. Overriden by // derived classes which need to do something. // // PARAMETERS: // // lFlags flags // pClassInt Points to an instance object // pObj Misc object pointer // bGet TRUE if we will be getting data. // // RETURN VALUE: // // S_OK //*************************************************************************** SCODE CImpDyn::StartBatch( IN long lFlags, IN IWbemClassObject FAR * pClassInt, IN CObject **pObj, IN BOOL bGet) { *pObj = NULL; return S_OK; } //*************************************************************************** // // CImpDyn::EndBatch // // DESCRIPTION: // // Called at the end of a batch of gets or puts. Overriden by // derived classes which need to do something. // // lFlags flags // pClassInt Points to an instance object // pObj Misc object pointer // bGet TRUE if we will be getting data. // // RETURN VALUE: // // S_OK //*************************************************************************** void CImpDyn::EndBatch( IN long lFlags, IN IWbemClassObject FAR * pClassInt, IN CObject *pObj, IN BOOL bGet) { if(pObj) delete pObj; } //*************************************************************************** // HRESULT CImpDyn::QueryInterface // long CImpDyn::AddRef // long CImpDyn::Release // // DESCRIPTION: // // Standard Com IUNKNOWN functions. // //*************************************************************************** STDMETHODIMP CImpDyn::QueryInterface( IN REFIID riid, OUT PPVOID ppv) { *ppv=NULL; // The only calls for IUnknown are either in a nonaggregated // case or when created in an aggregation, so in either case // always return our IUnknown for IID_IUnknown. if (IID_IUnknown==riid || IID_IWbemServices == riid) *ppv=(IWbemServices*)this; else if (IID_IWbemProviderInit==riid) *ppv=(IWbemProviderInit*)this; if (NULL!=*ppv) { ((LPUNKNOWN)*ppv)->AddRef(); return NOERROR; } return ResultFromScode(E_NOINTERFACE); } STDMETHODIMP_(ULONG) CImpDyn::AddRef(void) { return InterlockedIncrement(&m_cRef); } STDMETHODIMP_(ULONG) CImpDyn::Release(void) { long lRet = InterlockedDecrement(&m_cRef); if (0L!=lRet) return lRet; /* * Tell the housing that an object is going away so it can * shut down if appropriate. */ delete this; // do before decrementing module obj count. InterlockedDecrement(&lObj); return 0; } //*************************************************************************** // // CImpDyn::EnumPropDoFunc // // DESCRIPTION: // // This gets an objects attributes and then loops through the propeties // calling UpdateProperty or RefreshProperty to put or get the data. // // PARAMETERS: // // lFlags flags // pClassInt Object being refreshed or updated // FuncType Indicates if refresh or update // pwcKey Optional Key value of the object // pCache Option cache // // RETURN VALUE: // // S_OK all is well // otherwise an WBEMSVC type error. // //*************************************************************************** SCODE CImpDyn::EnumPropDoFunc( IN long lFlags, OUT IN IWbemClassObject FAR* pInstance, IN FUNCTYPE FuncType, IN WCHAR * pwcKey, OUT IN CIndexCache * pCache, IN IWbemClassObject * pClass) { SCODE sc; BSTR PropName; WCHAR * pwcClassContext = NULL; WCHAR * pwcKeyValue = NULL; WCHAR * pwcTemp = NULL; BOOL bClsidSetForClass = FALSE; CProvObj * pProvObj = NULL; BSTR bstrKeyName = NULL; BOOL bGotOurClass = FALSE; int iWorked = 0; int iCurr = 0; CVariant vProp; BOOL bTesterDetails = FALSE; bool bAccessDenied = false; // Make sure we have a class object. In some cases, such as enumeration, it // is passed. In others, it must be obtained if(pClass == NULL) { VARIANT var; VariantInit(&var); sc = pInstance->Get(L"__Class",0,&var,NULL,NULL); if(sc != S_OK) return sc; if(m_pGateway == NULL) return WBEM_E_FAILED; sc = m_pGateway->GetObject(var.bstrVal,0, NULL, &pClass, NULL); VariantClear(&var); if(FAILED(sc)) return sc; bGotOurClass = TRUE; } // Find out if expensive test data is desired { IWbemQualifierSet * pQualifier = NULL; CVariant var; sc = pClass->GetQualifierSet(&pQualifier); // Get instance Qualifier if(FAILED(sc)) return sc; sc = pQualifier->Get(L"TesterDetails" ,0,var.GetVarPtr(), NULL); pQualifier->Release(); // free up the interface if(sc == S_OK && var.GetType() == VT_BOOL && var.bGetBOOL()) bTesterDetails = TRUE; } CObject * pPackageObj = NULL; sc = StartBatch(lFlags,pInstance,&pPackageObj,FuncType == REFRESH); if(sc != S_OK) return WBEM_E_FAILED; sc = GetAttString(pClass, NULL, L"classcontext", &pwcClassContext); if(pwcKey) { // This is a special case and means that we are being called // as part of instance enumeration. This means that the key value // is already known, and that the class is one of ours pwcKeyValue = pwcKey; bClsidSetForClass = TRUE; } else { // Get the Key property. Note that this doesnt have to work since // there might be single instance classes supported by this provider! bstrKeyName = GetKeyName(pClass); if(bstrKeyName != NULL) { sc = pInstance->Get(bstrKeyName,0,vProp.GetVarPtr(),NULL,NULL); SysFreeString(bstrKeyName); if(sc == S_OK) { VARIANT * pTemp = vProp.GetVarPtr(); if(pTemp->vt == VT_BSTR && pTemp->bstrVal != 0) { DWORD dwLen = wcslen(vProp.GetBstr())+1; pwcKeyValue = new WCHAR[dwLen]; if(pwcKeyValue == NULL) { sc = WBEM_E_OUT_OF_MEMORY; goto EnumCleanUp; } StringCchCopyW(pwcKeyValue, dwLen, vProp.GetBstr()); } } vProp.Clear(); } } // For each property, Get the properties Qualifiers and // call the appropriate function to do the a refreshing/updating pInstance->BeginEnumeration(0); while(WBEM_NO_ERROR == pInstance->Next(0,&PropName, vProp.GetVarPtr(), NULL, NULL)) { vProp.Clear(); pwcTemp = NULL; sc = GetAttString(pClass, PropName, L"propertycontext", &pwcTemp, pCache, iCurr); iCurr++; if(sc== S_OK) { LPWSTR pwcFullContext = NULL; sc = MergeStrings(&pwcFullContext,pwcClassContext,pwcKeyValue,pwcTemp); if(pwcTemp) { delete pwcTemp; pwcTemp = NULL; } if(sc == S_OK) { if(pProvObj == NULL) { pProvObj = new CProvObj(pwcFullContext,MAIN_DELIM,NeedsEscapes()); if(pProvObj == NULL) { sc = WBEM_E_OUT_OF_MEMORY; break; } } else if (!pProvObj->Update(pwcFullContext)) { sc = WBEM_E_FAILED; break; } sc = pProvObj->dwGetStatus(iGetMinTokens()); if(FuncType == REFRESH && sc == S_OK) { sc = RefreshProperty(lFlags,pInstance, PropName, *pProvObj, pPackageObj, NULL,bTesterDetails); if(sc == S_OK) iWorked++; else if (sc == 5) bAccessDenied = true; } else if(FuncType == UPDATE && sc == S_OK) { sc = UpdateProperty(lFlags,pInstance, PropName, *pProvObj, pPackageObj, NULL); if(sc == S_OK) iWorked++; else if (sc == 5) bAccessDenied = true; } if(pwcFullContext) delete pwcFullContext; } } else sc = S_OK; // ignore props without propertyContext SysFreeString(PropName); } EnumCleanUp: if(iWorked > 0) sc = S_OK; else if(bAccessDenied) sc = WBEM_E_ACCESS_DENIED; else sc = WBEM_E_INVALID_OBJECT_PATH; if(pProvObj) delete pProvObj; if(pwcTemp) delete pwcTemp; if(pwcClassContext) delete pwcClassContext; if(pwcKeyValue && pwcKey == NULL) delete pwcKeyValue; if(bGotOurClass) pClass->Release(); EndBatch(lFlags,pInstance,pPackageObj,FuncType == REFRESH); return sc; } //*************************************************************************** // // SCODE CImpDyn::GetAttString // // DESCRIPTION: // // Gets an Qualifier string. The string is will be pointed to by // the ppResult argument and should be freed by "delete". // // PARAMETERS: // // pClassInt Class object pointer // pPropName Property Name, could be null if going after // class attribute // pAttName Attribute name // ppResult Set to point to the retuned value. // pCache Optional cache of values // iIndex Optional index in the cache // // RETURN VALUE: // // S_OK all is well // WBEM_E_OUT_OF_MEMORY // otherwise the error is set by the class object's GetQualifierSet function // or by the qualifier sets "Get" function. // //*************************************************************************** SCODE CImpDyn::GetAttString( IN IWbemClassObject FAR* pClassInt, IN LPWSTR pPropName, IN LPWSTR pAttName, OUT IN LPWSTR * ppResult, OUT IN CIndexCache * pCache, IN int iIndex) { SCODE sc; IWbemQualifierSet * pQualifier = NULL; CVariant var; if(*ppResult) delete *ppResult; *ppResult = NULL; // if there is a cache, try to get it from there if(pCache && iIndex != -1) { *ppResult = pCache->GetWString(iIndex); if(*ppResult != NULL) return S_OK; } // Get an Qualifier set interface. if(pPropName == NULL) sc = pClassInt->GetQualifierSet(&pQualifier); // Get instance Qualifier else sc = pClassInt->GetPropertyQualifierSet(pPropName,&pQualifier); // Get prop att if(FAILED(sc)) return sc; // Get the string and free the Qualifier interface sc = pQualifier->Get(pAttName,0,var.GetVarPtr(), NULL); pQualifier->Release(); // free up the interface if(FAILED(sc)) return sc; // make sure the type is OK if(var.GetType() != VT_BSTR) return WBEM_E_FAILED; // Allocate data for the buffer and copy the results DWORD dwLen = wcslen(var.GetBstr())+1; *ppResult = new WCHAR[dwLen]; if(*ppResult) { StringCchCopyW(*ppResult, dwLen, var.GetBstr()); sc = S_OK; } else sc = WBEM_E_OUT_OF_MEMORY; // If there is a cache, add this to it if(pCache && iIndex != -1 && *ppResult) { pCache->SetAt(*ppResult, iIndex); } return sc; } //*************************************************************************** // // BSTR CImpDyn::GetKeyName // // DESCRIPTION: // // Gets the name of the property with the the key Qualifier. // // PARAMETERS: // // pClassInt Class object pointer // // RETURN VALUE: // // NULL if error, // other wise a BSTR which the caller must free // //*************************************************************************** BSTR CImpDyn::GetKeyName( IN IWbemClassObject FAR* pClassInt) { IWbemQualifierSet * pQualifier = NULL; BSTR PropName = NULL; pClassInt->BeginEnumeration(WBEM_FLAG_KEYS_ONLY); // Loop through each of the properties and stop once one if found that // has a "Key" Qualifier while(WBEM_NO_ERROR == pClassInt->Next(0,&PropName,NULL, NULL, NULL)) { return PropName; } return NULL; } //*************************************************************************** // // SCODE CImpDyn::PutInstanceAsync // // DESCRIPTION: // // PutInstaceAsync writes instance data out. // // PARAMETERS: // // pClassInt Class Object pointer // lFlags flags. // pCtx Context object, not used anymore. // pResponseHandler Where to set the return code. // // RETURN VALUE: // // Set by EnumPropDoFunc // //*************************************************************************** STDMETHODIMP CImpDyn::PutInstanceAsync( /* [in] */ IWbemClassObject __RPC_FAR *pInst, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { SCODE sc = S_OK; if(pInst == NULL || pResponseHandler == NULL) return WBEM_E_INVALID_PARAMETER; if(IsNT() && IsDcomEnabled()) sc = WbemCoImpersonateClient(); if(sc == S_OK) sc = EnumPropDoFunc(lFlags,pInst,UPDATE); // Set the status pResponseHandler->SetStatus(0,sc, NULL, NULL); return sc; } //*************************************************************************** // // SCODE CImpDyn::ExecMethodAsync // // DESCRIPTION: // // Executes methods. // // PARAMETERS: // // pClassInt Class Object pointer // lFlags flags. // pCtx Context object, not used anymore. // pResponseHandler Where to set the return code. // // RETURN VALUE: // // Set by EnumPropDoFunc // //*************************************************************************** STDMETHODIMP CImpDyn::ExecMethodAsync( /* [in] */ const BSTR ObjectPath, /* [in] */ const BSTR MethodName, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemClassObject __RPC_FAR *pInParams, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler ) { return MethodAsync(ObjectPath, MethodName, lFlags,pCtx, pInParams, pResponseHandler); } //*************************************************************************** // // SCODE CImpDyn::RefreshInstance // // DESCRIPTION: // // gets fresh values for the properties. // // PARAMETERS: // // pClassInt Class Object pointer // lFlags flags. // ppErrorObject Optional error object // // RETURN VALUE: // // Set by EnumPropDoFunc // //*************************************************************************** STDMETHODIMP CImpDyn::RefreshInstance( IN long lFlags, OUT IN IWbemClassObject FAR* pClassInt) { return EnumPropDoFunc(lFlags,pClassInt,REFRESH); } //*************************************************************************** // // SCODE CImpDyn::CreateInst // // DESCRIPTION: // // Creates a new instance via the gateway provider and sets // the inital values of the properties. // // PARAMETERS: // // pGateway Pointer to WBEM // pwcClass Class Name // pKey Key value // pNewInst returned pointer to created instance // pwcKeyName Name of key property // pCache Optional cache // // RETURN VALUE: // // Return: S_OK if all is well, // otherwise an error code is returned by either GetObject(most likely) // or spawn instance. // //*************************************************************************** SCODE CImpDyn::CreateInst( IN IWbemServices * pGateway, IN LPWSTR pwcClass, IN LPWSTR pKey, OUT IN IWbemClassObject ** pNewInst, IN LPWSTR pwcKeyName, OUT IN CIndexCache * pCache, IWbemContext *pCtx) { SCODE sc; IWbemClassObject * pClass = NULL; // Create the new instance sc = pGateway->GetObject(pwcClass,0, pCtx, &pClass, NULL); if(FAILED(sc)) return sc; sc = pClass->SpawnInstance(0, pNewInst); if(FAILED(sc)) { pClass->Release(); return sc; } // Set the key value. Note that CVariant isnt used because // it assumes that the input is a TCHAR. VARIANT var; var.vt = VT_BSTR; var.bstrVal = SysAllocString(pKey); if(var.bstrVal == NULL) { (*pNewInst)->Release(); pClass->Release(); return WBEM_E_OUT_OF_MEMORY; } BSTR bstrKeyName; if(pwcKeyName == NULL) bstrKeyName = GetKeyName(*pNewInst); else bstrKeyName = SysAllocString(pwcKeyName); if(bstrKeyName != NULL) { sc = (*pNewInst)->Put(bstrKeyName,0,&var,0); SysFreeString(bstrKeyName); } VariantClear(&var); // Use the RefreshInstance routine to set all the other properties sc = EnumPropDoFunc(0,*pNewInst,REFRESH, pKey, pCache, pClass); pClass->Release(); if (FAILED(sc)) (*pNewInst)->Release(); // Clean up return sc; } //*************************************************************************** // // SCODE CImpDyn::MergeStrings // // DESCRIPTION: // // Combines the Class Context, Key, and Property Context strings. // // PARAMETERS: // // ppOut output combined string, must be freed via delete // pClassContext class context // pKey key value // pPropContext property context // // RETURN VALUE: // // S_OK if all is well, // WBEM_E_INVALID_PARAMETER no property context string or ppOut is NULL // WBEM_E_OUT_OF_MEMORY //*************************************************************************** SCODE CImpDyn::MergeStrings( OUT LPWSTR * ppOut, IN LPWSTR pClassContext, IN LPWSTR pKey, IN LPWSTR pPropContext) { // Allocate space for output int iLen = 3; if(pClassContext) iLen += wcslen(pClassContext); if(pKey) iLen += wcslen(pKey); if(pPropContext) iLen += wcslen(pPropContext); else return WBEM_E_INVALID_PARAMETER; // should always have this! if(ppOut == NULL) return WBEM_E_INVALID_PARAMETER; // should always have this! *ppOut = new WCHAR[iLen]; if(*ppOut == NULL) return WBEM_E_OUT_OF_MEMORY; // simple case is that everything is in the property context. That would // be the case when the provider is being used as a simple dynamic // property provider if(pClassContext == NULL || pKey == NULL) { StringCchCopyW(*ppOut, iLen, pPropContext); return S_OK; } // Copy the class context, then search for the delimeter StringCchCopyW(*ppOut, iLen, pClassContext); WCHAR * pTest; for(pTest = *ppOut; *pTest; pTest++) if(*pTest == MAIN_DELIM) break; // Three cases; if(*pTest == NULL) StringCchCatW(*ppOut, iLen,L"|"); // HKLM BLA VALUE add | else if( *(pTest +1)) StringCchCatW(*ppOut, iLen,L"\\"); // HKLM|BLA BLA VALUE add \ else; // HKLM| BLA VALUE do nothing! StringCchCatW(*ppOut, iLen,pKey); if(pPropContext[0] != L'|' && pPropContext[0] != L'\\') StringCchCatW(*ppOut, iLen,L"|"); StringCchCatW(*ppOut, iLen,pPropContext); return S_OK; } //*************************************************************************** // // SCODE CImpDyn::ReturnAndSetObj // // DESCRIPTION: // // Takes care of creating and setting an error object. // // PARAMETERS: // // sc value to set // ppErrorObject point which will point to the error object. // // RETURN VALUE: // // what ever was passed in. //*************************************************************************** SCODE CImpDyn::ReturnAndSetObj( IN SCODE sc, OUT IN IWbemCallResult FAR* FAR* ppCallResult) { // if(ppErrorObject) // *ppErrorObject = GetNotifyObj(m_pGateway,sc); return sc; } //*************************************************************************** // // long CImpDyn::AddRef // // DESCRIPTION: // // Adds to the reference count. // // RETURN VALUE: // // current reference count. // //*************************************************************************** long CEnumInfo::AddRef(void) { return InterlockedIncrement(&m_cRef); } //*************************************************************************** // // long CImpDyn::Release // // DESCRIPTION: // // Interface has been released. Object will be deleted if the // usage count is zero. // // RETURN VALUE: // // current reference count. // //*************************************************************************** long CEnumInfo::Release(void) { long lRet = InterlockedDecrement(&m_cRef); if (0L!=lRet) return lRet; delete this; return 0; }