// // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved // // *************************************************************************** // // Original Author: Rajesh Rao // // $Author: rajeshr $ // $Date: 6/11/98 4:43p $ // $Workfile:classpro.cpp $ // // $Modtime: 6/11/98 11:21a $ // $Revision: 1 $ // $Nokeywords: $ // // // Description: Contains implementation of the DS Class Provider class. THis is the // base class for all DS class providers // //*************************************************************************** #include "precomp.h" // Initialize the static members BSTR CDSClassProvider :: CLASS_STR = NULL; CWbemCache *CDSClassProvider :: s_pWbemCache = NULL; //*************************************************************************** // // CDSClassProvider::CDSClassProvider // CDSClassProvider::~CDSClassProvider // // Constructor Parameters: // lpLogFileName : The name of the file used for logging. The log file // name will be used in creating the log file path. The log file path // will be \logFileName. Hence the logFileName may be relative // path. For exaple if this argument is specified as wbem\logs\dsprov.txt, then // the actual log file would be c:\winnt\system32\wbem\logs\dsprov.txt on a system // where the system directory is c:\winnt\system32 // // //*************************************************************************** CDSClassProvider :: CDSClassProvider () { InterlockedIncrement(&g_lComponents); m_lReferenceCount = 0 ; m_IWbemServices = NULL; m_bInitializedSuccessfully = FALSE; } CDSClassProvider::~CDSClassProvider () { g_pLogObject->WriteW( L"CDSClassProvider :: DESTRUCTOR\r\n"); if(m_IWbemServices) { m_IWbemServices->Release(); m_IWbemServices = NULL; } InterlockedDecrement(&g_lComponents); } //*************************************************************************** // // CDSClassProvider::QueryInterface // CDSClassProvider::AddRef // CDSClassProvider::Release // // Purpose: Standard COM routines needed for all COM objects // //*************************************************************************** STDMETHODIMP CDSClassProvider :: QueryInterface ( REFIID iid , LPVOID FAR *iplpv ) { *iplpv = NULL ; if ( iid == IID_IUnknown ) { *iplpv = ( LPVOID ) (IUnknown *)(IWbemProviderInit *)this ; } else if ( iid == IID_IWbemServices ) { *iplpv = ( LPVOID ) (IWbemServices *)this ; } else if ( iid == IID_IWbemProviderInit ) { *iplpv = ( LPVOID ) (IWbemProviderInit *)this ; } else { return E_NOINTERFACE; } ( ( LPUNKNOWN ) *iplpv )->AddRef () ; return S_OK; } STDMETHODIMP_( ULONG ) CDSClassProvider :: AddRef () { return InterlockedIncrement ( & m_lReferenceCount ) ; } STDMETHODIMP_(ULONG) CDSClassProvider :: Release () { LONG ref ; if ( ( ref = InterlockedDecrement ( & m_lReferenceCount ) ) == 0 ) { delete this ; return 0 ; } else { return ref ; } } HRESULT CDSClassProvider :: Initialize( LPWSTR wszUser, LONG lFlags, LPWSTR wszNamespace, LPWSTR wszLocale, IWbemServices __RPC_FAR *pNamespace, IWbemContext __RPC_FAR *pCtx, IWbemProviderInitSink __RPC_FAR *pInitSink) { // Validate the arguments if( pNamespace == NULL || lFlags != 0 ) { g_pLogObject->WriteW( L"CDSClassProvider :: Argument validation FAILED\r\n"); pInitSink->SetStatus(WBEM_E_FAILED, 0); return WBEM_S_NO_ERROR; } // Store the IWbemServices pointer for future use m_IWbemServices = pNamespace; m_IWbemServices->AddRef(); m_bInitializedSuccessfully = TRUE; pInitSink->SetStatus(WBEM_S_INITIALIZED, 0); return WBEM_S_NO_ERROR; } HRESULT CDSClassProvider :: OpenNamespace( /* [in] */ const BSTR strNamespace, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [unique][in][out] */ IWbemServices __RPC_FAR *__RPC_FAR *ppWorkingNamespace, /* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppResult) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: CancelAsyncCall( /* [in] */ IWbemObjectSink __RPC_FAR *pSink) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: QueryObjectSink( /* [in] */ long lFlags, /* [out] */ IWbemObjectSink __RPC_FAR *__RPC_FAR *ppResponseHandler) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: GetObject( /* [in] */ const BSTR strObjectPath, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [unique][in][out] */ IWbemClassObject __RPC_FAR *__RPC_FAR *ppObject, /* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: GetObjectAsync( /* [in] */ const BSTR strObjectPath, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { if(!m_bInitializedSuccessfully) { g_pLogObject->WriteW( L"CDSClassProvider :: Initialization status is FAILED, hence returning failure\r\n"); return WBEM_E_FAILED; } // For exception handling //======================== SetStructuredExceptionHandler seh; try { if(!m_bInitializedSuccessfully) { g_pLogObject->WriteW( L"CDSClassProvider :: Initialization status is FAILED, hence returning failure\r\n"); return WBEM_E_FAILED; } g_pLogObject->WriteW( L"CDSClassProvider :: GetObjectAsync() called for %s \r\n", strObjectPath); // Impersonate the client //======================= HRESULT result; if(!SUCCEEDED(result = WbemCoImpersonateClient())) { g_pLogObject->WriteW( L"CDSClassProvider :: GetObjectAsync() CoImpersonate FAILED for %s with %x\r\n", strObjectPath, result); return WBEM_E_FAILED; } // Validate the arguments //======================== if(strObjectPath == NULL ) { g_pLogObject->WriteW( L"CDSClassProvider :: GetObjectAsync() argument validation FAILED\r\n"); return WBEM_E_INVALID_PARAMETER; } // Parse the object path //======================== CObjectPathParser theParser; ParsedObjectPath *theParsedObjectPath = NULL; switch(theParser.Parse(strObjectPath, &theParsedObjectPath)) { case CObjectPathParser::NoError: break; default: g_pLogObject->WriteW( L"CDSClassProvider :: GetObjectAsync() object path parsing FAILED\r\n"); return WBEM_E_INVALID_PARAMETER; } try { // Check to see if it one of those classes that we know that dont provide //======================================================================= if(IsUnProvidedClass(theParsedObjectPath->m_pClass)) { pResponseHandler->SetStatus(WBEM_STATUS_COMPLETE , WBEM_E_NOT_FOUND, NULL, NULL); } else { IWbemClassObject *pReturnObject = NULL; if(SUCCEEDED(result = GetClassFromCacheOrADSI(theParsedObjectPath->m_pClass, &pReturnObject, pCtx))) { result = pResponseHandler->Indicate(1, &pReturnObject); pReturnObject->Release(); pResponseHandler->SetStatus(WBEM_STATUS_COMPLETE , WBEM_S_NO_ERROR, NULL, NULL); } else { g_pLogObject->WriteW( L"CDSClassProvider :: GetObjectAsync() GetClassFromCacheOrADSI FAILED for %s with %x\r\n", strObjectPath, result); pResponseHandler->SetStatus(WBEM_STATUS_COMPLETE , WBEM_E_NOT_FOUND, NULL, NULL); } } } catch ( ... ) { theParser.Free(theParsedObjectPath); throw; } // Delete the parser allocated structures //======================================= theParser.Free(theParsedObjectPath); } catch(Heap_Exception e_HE) { pResponseHandler->SetStatus(WBEM_STATUS_COMPLETE , WBEM_E_OUT_OF_MEMORY, NULL, NULL); } return WBEM_S_NO_ERROR; } HRESULT CDSClassProvider :: PutClass( /* [in] */ IWbemClassObject __RPC_FAR *pObject, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: PutClassAsync( /* [in] */ IWbemClassObject __RPC_FAR *pObject, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: DeleteClass( /* [in] */ const BSTR strClass, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: DeleteClassAsync( /* [in] */ const BSTR strClass, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: CreateClassEnum( /* [in] */ const BSTR strSuperclass, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [out] */ IEnumWbemClassObject __RPC_FAR *__RPC_FAR *ppEnum) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: CreateClassEnumAsync( /* [in] */ const BSTR strSuperclass, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: PutInstance( /* [in] */ IWbemClassObject __RPC_FAR *pInst, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: PutInstanceAsync( /* [in] */ IWbemClassObject __RPC_FAR *pInst, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: DeleteInstance( /* [in] */ const BSTR strObjectPath, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: DeleteInstanceAsync( /* [in] */ const BSTR strObjectPath, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: CreateInstanceEnum( /* [in] */ const BSTR strClass, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [out] */ IEnumWbemClassObject __RPC_FAR *__RPC_FAR *ppEnum) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: CreateInstanceEnumAsync( /* [in] */ const BSTR strClass, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: ExecQuery( /* [in] */ const BSTR strQueryLanguage, /* [in] */ const BSTR strQuery, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [out] */ IEnumWbemClassObject __RPC_FAR *__RPC_FAR *ppEnum) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: ExecQueryAsync( /* [in] */ const BSTR strQueryLanguage, /* [in] */ const BSTR strQuery, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: ExecNotificationQuery( /* [in] */ const BSTR strQueryLanguage, /* [in] */ const BSTR strQuery, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [out] */ IEnumWbemClassObject __RPC_FAR *__RPC_FAR *ppEnum) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: ExecNotificationQueryAsync( /* [in] */ const BSTR strQueryLanguage, /* [in] */ const BSTR strQuery, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: ExecMethod( /* [in] */ const BSTR strObjectPath, /* [in] */ const BSTR strMethodName, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemClassObject __RPC_FAR *pInParams, /* [unique][in][out] */ IWbemClassObject __RPC_FAR *__RPC_FAR *ppOutParams, /* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: ExecMethodAsync( /* [in] */ const BSTR strObjectPath, /* [in] */ const BSTR strMethodName, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemClassObject __RPC_FAR *pInParams, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { return WBEM_E_NOT_SUPPORTED; } HRESULT CDSClassProvider :: GetClassFromCacheOrADSI(LPCWSTR pszWBEMClassName, IWbemClassObject **ppWbemClassObject, IWbemContext *pCtx) { HRESULT result = E_FAIL; // The algorithm is as follows: // Check whether the classname is present in the list of classes to which this user is granted access // If so // See if is present in the WBEM Cache. // If so return it. // If not, get it from ADSI. // If successful Map it to WBEM class and add the WBEM class to the WBEM cache and return // If not, if the return value is ACCESS_DENIED, remove it from the user's list // If not // Get it from ADSI. // if successful // if it is not present in the cache map it to WBEM and add the WBEM class to the cache // else discard it and return the WBEM class in the cache to the user // else // return error if(m_AccessAllowedClasses.IsNamePresent(pszWBEMClassName)) { g_pLogObject->WriteW( L"CDSClassProvider :: GetClassFromCacheOrADSI() Found class in Authenticated list for %s\r\n", pszWBEMClassName); // Check the WBEM Cache to see if it there //========================================= CWbemClass *pWbemClass = NULL; try { if(SUCCEEDED(result = s_pWbemCache->GetClass(pszWBEMClassName, &pWbemClass))) { g_pLogObject->WriteW( L"CDSClassProvider :: GetClassFromCacheOrADSI() Found class in cache for %s\r\n", pszWBEMClassName); // Get the IWbemClassObject of the cache object IWbemClassObject *pCacheObject = pWbemClass->GetWbemClass(); pWbemClass->Release(); pWbemClass = NULL; // Clone it if(!SUCCEEDED(result = pCacheObject->Clone(ppWbemClassObject))) g_pLogObject->WriteW( L"CDSClassProvider :: GetClassFromCacheOrADSI() Clone() FAILED : %x for %s\r\n", result, pszWBEMClassName); pCacheObject->Release(); } else // Could not be found in cache. Go to ADSI //========================================= { g_pLogObject->WriteW( L"CDSClassProvider :: GetClassFromCacheOrADSI() Could not find class in cache for %s. Going to ADSI\r\n", pszWBEMClassName); IWbemClassObject *pNewObject = NULL; if(SUCCEEDED(result = GetClassFromADSI(pszWBEMClassName, pCtx, &pNewObject))) { try { // Add it to the cache pWbemClass = NULL; if(pWbemClass = new CWbemClass(pszWBEMClassName, pNewObject)) { s_pWbemCache->AddClass(pWbemClass); pWbemClass->Release(); pWbemClass = NULL; g_pLogObject->WriteW( L"CDSClassProvider :: GetClassFromCacheOrADSI() Added %s to cache\r\n", pszWBEMClassName); // Clone it if(!SUCCEEDED(result = pNewObject->Clone(ppWbemClassObject))) g_pLogObject->WriteW( L"CDSClassProvider :: GetClassFromCacheOrADSI() Clone() FAILED : %x for %s\r\n", result, pszWBEMClassName); pNewObject->Release(); pNewObject = NULL; } else result = E_OUTOFMEMORY; } catch ( ... ) { if ( pNewObject ) { pNewObject->Release (); pNewObject = NULL; } throw; } } else { m_AccessAllowedClasses.RemoveName(pszWBEMClassName); g_pLogObject->WriteW( L"CDSClassProvider :: GetClassFromCacheOrADSI() GetClassFromADSI() FAILED : %x. Removing %s from user list\r\n", result, pszWBEMClassName); } } } catch ( ... ) { if ( pWbemClass ) { pWbemClass->Release (); pWbemClass = NULL; } throw; } } else // Get it from ADSI //========================================= { g_pLogObject->WriteW( L"CDSClassProvider :: GetClassFromCacheOrADSI() Could not find class in Authenticated list for %s. Going to ADSI\r\n", pszWBEMClassName); CWbemClass *pWbemClass = NULL; IWbemClassObject *pNewObject = NULL; try { if(SUCCEEDED(result = GetClassFromADSI(pszWBEMClassName, pCtx, &pNewObject))) { // Add it to the cache pWbemClass = NULL; if(pWbemClass = new CWbemClass(pszWBEMClassName, pNewObject)) { s_pWbemCache->AddClass(pWbemClass); pWbemClass->Release(); pWbemClass = NULL; g_pLogObject->WriteW( L"CDSClassProvider :: GetClassFromCacheOrADSI() GetClassFromADSI succeeded for %s Added it to cache\r\n", pszWBEMClassName); // Clone it if(!SUCCEEDED(result = pNewObject->Clone(ppWbemClassObject))) g_pLogObject->WriteW( L"CDSClassProvider :: GetClassFromCacheOrADSI() Clone() FAILED : %x for %s\r\n", result, pszWBEMClassName); pNewObject->Release(); pNewObject = NULL; // Add it to the list of classnames for this user m_AccessAllowedClasses.AddName(pszWBEMClassName); g_pLogObject->WriteW( L"CDSClassProvider :: GetClassFromCacheOrADSI() Also added to Authenticated list : %s \r\n", pszWBEMClassName); } else result = E_OUTOFMEMORY; } else g_pLogObject->WriteW( L"CDSClassProvider :: GetClassFromCacheOrADSI() GetClassFromADSI FAILED : %x for %s\r\n", result, pszWBEMClassName); } catch ( ... ) { if ( pNewObject ) { pNewObject->Release (); pNewObject = NULL; } if ( pWbemClass ) { pWbemClass->Release (); pWbemClass = NULL; } throw; } } return result; }