// // 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 Associations Provider class. // //*************************************************************************** #include "precomp.h" ///////////////////////////////////////// // Initialize the static members ///////////////////////////////////////// LPCWSTR CLDAPClassAsssociationsProvider :: s_LogFileName = L"wbem\\logs\\ldapascl.txt"; LPCWSTR CLDAPClassAsssociationsProvider :: CHILD_CLASS_PROPERTY = L"ChildClass"; LPCWSTR CLDAPClassAsssociationsProvider :: PARENT_CLASS_PROPERTY = L"ParentClass"; LPCWSTR CLDAPClassAsssociationsProvider :: POSSIBLE_SUPERIORS = L"PossibleSuperiors"; LPCWSTR CLDAPClassAsssociationsProvider :: SCHEMA_NAMING_CONTEXT = L"schemaNamingContext"; LPCWSTR CLDAPClassAsssociationsProvider :: LDAP_SCHEMA = L"LDAP://Schema"; LPCWSTR CLDAPClassAsssociationsProvider :: LDAP_SCHEMA_SLASH = L"LDAP://Schema/"; //*************************************************************************** // // CLDAPClassAsssociationsProvider::CLDAPClassAsssociationsProvider // CLDAPClassAsssociationsProvider::~CLDAPClassAsssociationsProvider // // Constructor Parameters: // // //*************************************************************************** CLDAPClassAsssociationsProvider :: CLDAPClassAsssociationsProvider () { InterlockedIncrement(&g_lComponents); m_lReferenceCount = 0 ; m_IWbemServices = NULL; m_pAssociationClass = NULL; m_lpszSchemaContainerSuffix = NULL; m_pDirectorySearchSchemaContainer = NULL; m_bInitializedSuccessfully = FALSE; CHILD_CLASS_PROPERTY_STR = SysAllocString(CHILD_CLASS_PROPERTY); PARENT_CLASS_PROPERTY_STR = SysAllocString(PARENT_CLASS_PROPERTY); CLASS_ASSOCIATION_CLASS_STR = SysAllocString(CLASS_ASSOCIATION_CLASS); POSSIBLE_SUPERIORS_STR = SysAllocString(POSSIBLE_SUPERIORS); } CLDAPClassAsssociationsProvider::~CLDAPClassAsssociationsProvider () { g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: DESTRUCTOR\r\n"); if(m_IWbemServices) m_IWbemServices->Release(); if(m_pDirectorySearchSchemaContainer) m_pDirectorySearchSchemaContainer->Release(); if(m_pAssociationClass) m_pAssociationClass->Release(); if (m_lpszSchemaContainerSuffix) { delete [] m_lpszSchemaContainerSuffix; } SysFreeString(CHILD_CLASS_PROPERTY_STR); SysFreeString(PARENT_CLASS_PROPERTY_STR); SysFreeString(CLASS_ASSOCIATION_CLASS_STR); SysFreeString(POSSIBLE_SUPERIORS_STR); InterlockedDecrement(&g_lComponents); } //*************************************************************************** // // CLDAPClassAsssociationsProvider::QueryInterface // CLDAPClassAsssociationsProvider::AddRef // CLDAPClassAsssociationsProvider::Release // // Purpose: Standard COM routines needed for all COM objects // //*************************************************************************** STDMETHODIMP CLDAPClassAsssociationsProvider :: 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 ) CLDAPClassAsssociationsProvider :: AddRef () { return InterlockedIncrement ( & m_lReferenceCount ) ; } STDMETHODIMP_(ULONG) CLDAPClassAsssociationsProvider :: Release () { LONG ref ; if ( ( ref = InterlockedDecrement ( & m_lReferenceCount ) ) == 0 ) { delete this ; return 0 ; } else { return ref ; } } HRESULT CLDAPClassAsssociationsProvider :: 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"CLDAPClassAsssociationsProvider :: 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(); // Do LDAP Provider initialization if(!InitializeAssociationsProvider(pCtx)) { g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: InitializeAssociationsProvider FAILED\r\n"); m_IWbemServices->Release(); m_IWbemServices = NULL; m_bInitializedSuccessfully = FALSE; } else m_bInitializedSuccessfully = TRUE; pInitSink->SetStatus(WBEM_S_INITIALIZED, 0); return WBEM_S_NO_ERROR; } HRESULT CLDAPClassAsssociationsProvider :: 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 CLDAPClassAsssociationsProvider :: CancelAsyncCall( /* [in] */ IWbemObjectSink __RPC_FAR *pSink) { return WBEM_E_NOT_SUPPORTED; } HRESULT CLDAPClassAsssociationsProvider :: QueryObjectSink( /* [in] */ long lFlags, /* [out] */ IWbemObjectSink __RPC_FAR *__RPC_FAR *ppResponseHandler) { return WBEM_E_NOT_SUPPORTED; } HRESULT CLDAPClassAsssociationsProvider :: 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 CLDAPClassAsssociationsProvider :: 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"CLDAPClassAsssociationsProvider :: Initialization status is FAILED, hence returning failure\n"); return WBEM_E_FAILED; } g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: GetObjectAsync() called for %s \r\n", strObjectPath); HRESULT result = S_OK; // Impersonate the client if(!SUCCEEDED(result = WbemCoImpersonateClient())) { g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: GetObjectAsync() CoImpersonate FAILED for %s with %x\r\n", strObjectPath, result); return WBEM_E_FAILED; } // Validate the arguments if(strObjectPath == NULL || lFlags != 0) { g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: 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"CLDAPClassAsssociationsProvider :: GetObjectAsync() object path parsing FAILED\r\n"); return WBEM_E_INVALID_PARAMETER; } // Check whether there are exactly 2 keys specified if(theParsedObjectPath->m_dwNumKeys != 2) result = WBEM_E_INVALID_PARAMETER; // Check whether these keys are KeyRef *pChildKeyRef = *(theParsedObjectPath->m_paKeys); KeyRef *pParentKeyRef = *(theParsedObjectPath->m_paKeys + 1); if(_wcsicmp(pChildKeyRef->m_pName, CHILD_CLASS_PROPERTY) != 0) { // Exchange them KeyRef *temp = pChildKeyRef; pChildKeyRef = pParentKeyRef; pParentKeyRef = pChildKeyRef; } // The status on the sink IWbemClassObject *ppReturnWbemClassObjects[1]; ppReturnWbemClassObjects[0] = NULL; if(SUCCEEDED(result)) { if(SUCCEEDED(result = IsContainedIn(pChildKeyRef->m_vValue.bstrVal, pParentKeyRef->m_vValue.bstrVal))) { if(result == S_OK) { if(SUCCEEDED(result = CreateInstance(pChildKeyRef->m_vValue.bstrVal, pParentKeyRef->m_vValue.bstrVal, ppReturnWbemClassObjects))) { result = pResponseHandler->Indicate(1, ppReturnWbemClassObjects); ppReturnWbemClassObjects[0]->Release(); } } else // the instance was not found { g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: returning WBEM_E_NOT_FOUND for %s \r\n", strObjectPath); result = WBEM_E_NOT_FOUND; } } else { g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: IsContainedIn() FAILED with %x \r\n", result); } } // Free the parser object path theParser.Free(theParsedObjectPath); // Set the status of the request result = (SUCCEEDED(result)? WBEM_S_NO_ERROR : WBEM_E_NOT_FOUND); pResponseHandler->SetStatus(WBEM_STATUS_COMPLETE , result, NULL, NULL); return result; } HRESULT CLDAPClassAsssociationsProvider :: 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 CLDAPClassAsssociationsProvider :: 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 CLDAPClassAsssociationsProvider :: 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 CLDAPClassAsssociationsProvider :: DeleteClassAsync( /* [in] */ const BSTR strClass, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { return WBEM_E_NOT_SUPPORTED; } HRESULT CLDAPClassAsssociationsProvider :: CreateClassEnum( /* [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 CLDAPClassAsssociationsProvider :: CreateClassEnumAsync( /* [in] */ const BSTR strClass, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { return WBEM_E_NOT_SUPPORTED; } HRESULT CLDAPClassAsssociationsProvider :: 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 CLDAPClassAsssociationsProvider :: 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 CLDAPClassAsssociationsProvider :: 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 CLDAPClassAsssociationsProvider :: DeleteInstanceAsync( /* [in] */ const BSTR strObjectPath, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { return WBEM_E_NOT_SUPPORTED; } HRESULT CLDAPClassAsssociationsProvider :: 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 CLDAPClassAsssociationsProvider :: CreateInstanceEnumAsync( /* [in] */ const BSTR strClass, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { if(!m_bInitializedSuccessfully) { g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: Initialization status is FAILED, hence returning failure\n"); return WBEM_E_FAILED; } g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: CreateInstanceEnumAsync() called\r\n"); HRESULT result = S_OK; // Impersonate the client if(!SUCCEEDED(result = WbemCoImpersonateClient())) { g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: CreateInstanceEnumAsync() CoImpersonate FAILED with %x\r\n", result); return WBEM_E_FAILED; } // Get all the ADSI classes result = DoEnumeration(pResponseHandler); if(SUCCEEDED(result)) { pResponseHandler->SetStatus(WBEM_STATUS_COMPLETE, WBEM_S_NO_ERROR, NULL, NULL); g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: CreateInstanceEnumAsync() enumeration succeeded\r\n"); return WBEM_S_NO_ERROR; } else { pResponseHandler->SetStatus(WBEM_STATUS_COMPLETE, WBEM_E_FAILED, NULL, NULL); g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: CreateInstanceEnumAsync() enumeration FAILED\r\n"); return WBEM_E_FAILED; } return result; } HRESULT CLDAPClassAsssociationsProvider :: 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 CLDAPClassAsssociationsProvider :: 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_PROVIDER_NOT_CAPABLE; } HRESULT CLDAPClassAsssociationsProvider :: 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 CLDAPClassAsssociationsProvider :: 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 CLDAPClassAsssociationsProvider :: 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 CLDAPClassAsssociationsProvider :: 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; } //*************************************************************************** // // CLDAPClassAsssociationsProvider::IsContainedIn // // Purpose: Checks whether a containment is valid // // Parameters: // lpszChildClass : The WBEM Name of the child class // lpszParentClass : The WBEM Name of the parent class // // Return Value: The COM status of the request // //*************************************************************************** HRESULT CLDAPClassAsssociationsProvider :: IsContainedIn(LPCWSTR lpszChildClass, LPCWSTR lpszParentClass) { LPWSTR lpszLDAPChildClass = NULL; LPWSTR lpszLDAPParentClass = NULL; lpszLDAPChildClass = CLDAPHelper::UnmangleWBEMNameToLDAP(lpszChildClass); lpszLDAPParentClass = CLDAPHelper::UnmangleWBEMNameToLDAP(lpszParentClass); // Check whether these are valid names if(!lpszLDAPChildClass || !lpszLDAPParentClass) { if (lpszLDAPChildClass) { delete [] lpszLDAPChildClass; lpszLDAPChildClass = NULL ; } if (lpszLDAPParentClass) { delete [] lpszLDAPParentClass; lpszLDAPParentClass = NULL; } return S_FALSE; } LPWSTR lpszADSIAbstractSchemaPath = new WCHAR[wcslen(LDAP_SCHEMA_SLASH) + wcslen(lpszLDAPChildClass) + 1]; wcscpy(lpszADSIAbstractSchemaPath, LDAP_SCHEMA_SLASH); wcscat(lpszADSIAbstractSchemaPath, lpszLDAPChildClass); IADsClass *pADsChildClass; HRESULT result; if(SUCCEEDED(result = ADsOpenObject(lpszADSIAbstractSchemaPath, NULL, NULL, ADS_SECURE_AUTHENTICATION, IID_IADsClass, (LPVOID *) &pADsChildClass))) { // Get the POSSIBLE_SUPERIORS_STR property. This property contains the possible superiors VARIANT variant; VariantInit(&variant); if(SUCCEEDED(result = pADsChildClass->get_PossibleSuperiors(&variant))) { // Check the lone possible superior if(variant.vt == VT_BSTR) { if(_wcsicmp(variant.bstrVal, lpszLDAPParentClass) == 0) result = S_OK; else result = S_FALSE; } else { // Go thru the list of possible superiorsV SAFEARRAY *pSafeArray = variant.parray; LONG lNumber = 0; VARIANT vTmp; if(SUCCEEDED(result = SafeArrayGetUBound(pSafeArray, 1, &lNumber)) ) { result = S_FALSE; for(LONG index=0L; index<=lNumber; index++) { if(SUCCEEDED(SafeArrayGetElement(pSafeArray, &index, &vTmp) )) { if(_wcsicmp(vTmp.bstrVal, lpszLDAPParentClass) == 0) { result = S_OK; } VariantClear(&vTmp); if(result == S_OK) break; } } } } VariantClear(&variant); } pADsChildClass->Release(); } delete [] lpszLDAPChildClass; delete [] lpszLDAPParentClass; delete [] lpszADSIAbstractSchemaPath; return result; } //*************************************************************************** // // CLDAPClassAsssociationsProvider::InitializeAssociationsProvider // // Purpose: A helper function to do the ADSI LDAP provider specific initialization. // // Parameters: // pCtx The context object used in this call initialization // // Return Value: TRUE if the function successfully finishes the initializaion. FALSE // otherwise //*************************************************************************** BOOLEAN CLDAPClassAsssociationsProvider :: InitializeAssociationsProvider(IWbemContext *pCtx) { // Get the class for which instances are provided by the provider HRESULT result = m_IWbemServices->GetObject(CLASS_ASSOCIATION_CLASS_STR, 0, pCtx, &m_pAssociationClass, NULL); if(SUCCEEDED(result)) { // Get the ADSI path of the schema container and store it for future use IADs *pRootDSE = NULL; if(SUCCEEDED(result = ADsOpenObject((LPWSTR)ROOT_DSE_PATH, NULL, NULL, ADS_SECURE_AUTHENTICATION, IID_IADs, (LPVOID *) &pRootDSE))) { // Get the location of the schema container BSTR strSchemaPropertyName = SysAllocString((LPWSTR) SCHEMA_NAMING_CONTEXT); // Get the schemaNamingContext property. This property contains the ADSI path // of the schema container VARIANT variant; VariantInit(&variant); if(SUCCEEDED(result = pRootDSE->Get(strSchemaPropertyName, &variant))) { // Store the ADSI path to the schema container m_lpszSchemaContainerSuffix = new WCHAR[wcslen(variant.bstrVal) + 1]; wcscpy(m_lpszSchemaContainerSuffix, variant.bstrVal ); g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: Got Schema Container as : %s\r\n", m_lpszSchemaContainerSuffix); // Form the schema container path LPWSTR lpszSchemaContainerPath = new WCHAR[wcslen(LDAP_PREFIX) + wcslen(m_lpszSchemaContainerSuffix) + 1]; wcscpy(lpszSchemaContainerPath, LDAP_PREFIX); wcscat(lpszSchemaContainerPath, m_lpszSchemaContainerSuffix); if(SUCCEEDED(result = ADsOpenObject(lpszSchemaContainerPath, NULL, NULL, ADS_SECURE_AUTHENTICATION, IID_IDirectorySearch, (LPVOID *) &m_pDirectorySearchSchemaContainer))) { g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: Got IDirectorySearch on Schema Container \r\n"); } else g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: FAILED to get IDirectorySearch on Schema Container : %x\r\n", result); delete[] lpszSchemaContainerPath; } else g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: Get on RootDSE FAILED : %x\r\n", result); SysFreeString(strSchemaPropertyName); VariantClear(&variant); pRootDSE->Release(); } else g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: InitializeLDAPProvider ADsOpenObject on RootDSE FAILED : %x\r\n", result); } else g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: InitializeLDAPProvider GetClass on LDAP Association class FAILED : %x\r\n", result); return SUCCEEDED(result); } HRESULT CLDAPClassAsssociationsProvider :: DoEnumeration(IWbemObjectSink *pResponseHandler) { HRESULT result = E_FAIL; // Get the IADsContainer interface on the schema container IADsContainer *pADsContainer = NULL; IUnknown *pChild = NULL; // An instance of the association IWbemClassObject *pInstance = NULL; if(SUCCEEDED(result = ADsOpenObject((LPWSTR)LDAP_SCHEMA, NULL, NULL, ADS_SECURE_AUTHENTICATION, IID_IADsContainer, (LPVOID *) &pADsContainer))) { IEnumVARIANT *pEnum = NULL; if(SUCCEEDED(result = ADsBuildEnumerator(pADsContainer, &pEnum))) { IADsClass *pADsChildClass = NULL; VARIANT v; VariantInit(&v); while (SUCCEEDED(result = ADsEnumerateNext(pEnum, 1, &v, NULL)) && result != S_FALSE) { pChild = v.punkVal; if(SUCCEEDED(result = pChild->QueryInterface(IID_IADsClass, (LPVOID *) &pADsChildClass))) { BSTR strChildClassName; if(SUCCEEDED(result = pADsChildClass->get_Name(&strChildClassName))) { // Mangle the name to WBEM LPWSTR szChildName = CLDAPHelper::MangleLDAPNameToWBEM(strChildClassName); VARIANT variant; VariantInit(&variant); if(SUCCEEDED(result = pADsChildClass->get_PossibleSuperiors(&variant))) { // Check the lone possible superior if(variant.vt == VT_BSTR) { LPWSTR szParentName = CLDAPHelper::MangleLDAPNameToWBEM(variant.bstrVal); if(SUCCEEDED(result = CreateInstance(szChildName, szParentName, &pInstance))) { pResponseHandler->Indicate(1, &pInstance); pInstance->Release(); } delete [] szParentName; } else // It is an array of variants { // Go thru the list of possible superiorsV SAFEARRAY *pSafeArray = variant.parray; VARIANT HUGEP *pVar; LONG lUbound = 0, lLbound = 0; if(SUCCEEDED(result = SafeArrayAccessData(pSafeArray, (void HUGEP* FAR*)&pVar) ) ) { if( SUCCEEDED (result = SafeArrayGetLBound(pSafeArray, 1, &lLbound)) && SUCCEEDED (result = SafeArrayGetUBound(pSafeArray, 1, &lUbound)) ) { for(LONG index=lLbound; index<=lUbound; index++) { LPWSTR szParentName = CLDAPHelper::MangleLDAPNameToWBEM(pVar[index].bstrVal); if(SUCCEEDED(result = CreateInstance(szChildName, szParentName, &pInstance))) { pResponseHandler->Indicate(1, &pInstance); pInstance->Release(); } delete [] szParentName; } } SafeArrayUnaccessData(pSafeArray); } } VariantClear(&variant); } delete [] szChildName; SysFreeString(strChildClassName); } pADsChildClass->Release(); } VariantClear(&v); } ADsFreeEnumerator(pEnum); } pADsContainer->Release(); } else g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: FAILED to get IDirectoryObject on Schema Container : %x\r\n", result); return result; } HRESULT CLDAPClassAsssociationsProvider :: CreateInstance(BSTR strChildName, BSTR strParentName, IWbemClassObject **ppInstance) { HRESULT result = E_FAIL; *ppInstance = NULL; if(SUCCEEDED(result = m_pAssociationClass->SpawnInstance(0, ppInstance))) { // Put the property values if(SUCCEEDED(result = CWBEMHelper::PutBSTRProperty(*ppInstance, CHILD_CLASS_PROPERTY_STR, strChildName, FALSE))) { if(SUCCEEDED(result = CWBEMHelper::PutBSTRProperty(*ppInstance, PARENT_CLASS_PROPERTY_STR, strParentName, FALSE))) { } else g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: CreateInstance() PutBSTRProperty on parent property FAILED %x \r\n", result); } else g_pLogObject->WriteW( L"CLDAPClassAsssociationsProvider :: CreateInstance() PutBSTRProperty on child property FAILED %x \r\n", result); } if(FAILED(result) && *ppInstance) { (*ppInstance)->Release(); *ppInstance = NULL; } return result; }