Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

786 lines
25 KiB

//
// 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");
InterlockedDecrement(&g_lComponents);
if(m_IWbemServices)
m_IWbemServices->Release();
if(m_pDirectorySearchSchemaContainer)
m_pDirectorySearchSchemaContainer->Release();
if(m_pAssociationClass)
m_pAssociationClass->Release();
delete [] m_lpszSchemaContainerSuffix;
SysFreeString(CHILD_CLASS_PROPERTY_STR);
SysFreeString(PARENT_CLASS_PROPERTY_STR);
SysFreeString(CLASS_ASSOCIATION_CLASS_STR);
SysFreeString(POSSIBLE_SUPERIORS_STR);
}
//***************************************************************************
//
// 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)
{
delete [] lpszLDAPChildClass;
delete [] lpszLDAPParentClass;
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;
}