|
|
//
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
//
// ***************************************************************************
//
// Original Author: Rajesh Rao
//
// $Author: rajeshr $
// $Date: 6/11/98 4:43p $
// $Workfile:ldapprov.cpp $
//
// $Modtime: 6/11/98 11:21a $
// $Revision: 1 $
// $Nokeywords: $
//
//
// Description: Contains implementation of the DS LDAP Class Provider class.
//
//***************************************************************************
#include "precomp.h"
/////////////////////////////////////////
// Initialize the static members
/////////////////////////////////////////
CLDAPCache *CLDAPClassProvider :: s_pLDAPCache = NULL; DWORD CLDAPClassProvider::dwClassProviderCount = 0;
BSTR CLDAPClassProvider:: LDAP_BASE_CLASS_STR = NULL; BSTR CLDAPClassProvider:: LDAP_CLASS_PROVIDER_NAME = NULL; BSTR CLDAPClassProvider:: LDAP_INSTANCE_PROVIDER_NAME = NULL;
// Names of the LDAP class attributes
BSTR CLDAPClassProvider :: COMMON_NAME_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: LDAP_DISPLAY_NAME_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: GOVERNS_ID_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: SCHEMA_ID_GUID_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: MAPI_DISPLAY_TYPE_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: RDN_ATT_ID_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: SYSTEM_MUST_CONTAIN_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: MUST_CONTAIN_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: SYSTEM_MAY_CONTAIN_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: MAY_CONTAIN_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: SYSTEM_POSS_SUPERIORS_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: POSS_SUPERIORS_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: SYSTEM_AUXILIARY_CLASS_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: AUXILIARY_CLASS_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: DEFAULT_SECURITY_DESCRP_ATTR_BSTR= NULL; BSTR CLDAPClassProvider :: OBJECT_CLASS_CATEGORY_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: SYSTEM_ONLY_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: NT_SECURITY_DESCRIPTOR_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: DEFAULT_OBJECTCATEGORY_ATTR_BSTR = NULL;
// Names of the LDAP property attributes
BSTR CLDAPClassProvider :: ATTRIBUTE_SYNTAX_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: ATTRIBUTE_ID_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: MAPI_ID_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: OM_SYNTAX_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: RANGE_LOWER_ATTR_BSTR = NULL; BSTR CLDAPClassProvider :: RANGE_UPPER_ATTR_BSTR = NULL;
// Qualifiers for embedded objects
BSTR CLDAPClassProvider :: CIMTYPE_STR = NULL; BSTR CLDAPClassProvider :: EMBED_UINT8ARRAY = NULL; BSTR CLDAPClassProvider :: EMBED_DN_WITH_STRING = NULL; BSTR CLDAPClassProvider :: EMBED_DN_WITH_BINARY = NULL;
// Default Qualifier Flavour
LONG CLDAPClassProvider :: DEFAULT_QUALIFIER_FLAVOUR = WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE | WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS | WBEM_FLAVOR_OVERRIDABLE ;
// Names of WBEM Class Qualifiers
BSTR CLDAPClassProvider:: DYNAMIC_BSTR = NULL; BSTR CLDAPClassProvider:: PROVIDER_BSTR = NULL; BSTR CLDAPClassProvider:: ABSTRACT_BSTR = NULL;
// Names of WBEM Property Qualifiers
BSTR CLDAPClassProvider :: SYSTEM_BSTR = NULL; BSTR CLDAPClassProvider :: NOT_NULL_BSTR = NULL; BSTR CLDAPClassProvider :: INDEXED_BSTR = NULL;
// Names of WBEM properties
BSTR CLDAPClassProvider :: DYNASTY_BSTR = NULL;
//***************************************************************************
//
// CLDAPClassProvider::CLDAPClassProvider
// CLDAPClassProvider::~CLDAPClassProvider
//
// Constructor Parameters:
// None
//***************************************************************************
CLDAPClassProvider :: CLDAPClassProvider () : CDSClassProvider() { // Initialize the search preferences often used
m_searchInfo1.dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE; m_searchInfo1.vValue.Integer = ADS_SCOPE_ONELEVEL; m_searchInfo1.dwStatus = ADS_STATUS_S_OK;
m_pLDAPBaseClass = NULL; dwClassProviderCount++; }
CLDAPClassProvider::~CLDAPClassProvider () { g_pLogObject->WriteW( L"CLDAPClassProvider :: ~CLDAPClassProvider() Called\r\n"); dwClassProviderCount --; if(m_pLDAPBaseClass) m_pLDAPBaseClass->Release(); }
//***************************************************************************
//
// CLDAPClassProvider::Initialize
//
// Purpose:
// As defined by the IWbemProviderInit interface
//
// Parameters:
// As defined by IWbemProviderInit interface
//
// Return Value: The COM status value indicating the status of the request
//***************************************************************************
HRESULT CLDAPClassProvider :: 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"CLDAPClassProvider :: Argument validation FAILED\r\n"); pInitSink->SetStatus(WBEM_E_FAILED, 0); return WBEM_S_NO_ERROR; }
g_pLogObject->WriteW( L"CLDAPClassProvider :: Initialize() Called\r\n");
// Store the IWbemServices pointer for future use
m_IWbemServices = pNamespace; m_IWbemServices->AddRef();
// Do LDAP Provider initialization
if(!InitializeLDAPProvider(pCtx)) { g_pLogObject->WriteW( L"CLDAPClassProvider :: InitializeLDAPProvider FAILED\r\n"); m_IWbemServices->Release(); m_IWbemServices = NULL;
// Do not set the status to failed for purposes of installation (MOFCOMP fails!)
// Instead return a success but set an internal status value to FALSE
// All operations should return FAILED if this internal status value is set to FALSE
m_bInitializedSuccessfully = FALSE; } else m_bInitializedSuccessfully = TRUE;
pInitSink->SetStatus(WBEM_S_INITIALIZED, 0); return WBEM_S_NO_ERROR; }
//***************************************************************************
//
// CLDAPClassProvider::InitializeLDAPProvider
//
// 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 CLDAPClassProvider :: InitializeLDAPProvider(IWbemContext *pCtx) { // Get the static classes used by the LDAP provider
HRESULT result = WBEM_E_FAILED; if(SUCCEEDED(result = m_IWbemServices->GetObject(LDAP_BASE_CLASS_STR, 0, pCtx, &m_pLDAPBaseClass, NULL))) { result = (s_pLDAPCache->IsInitialized())? S_OK : E_FAIL; } else g_pLogObject->WriteW( L"CLDAPClassProvider :: InitializeLDAPProvider GetObject on base LDAP class FAILED : %x\r\n", result);
return SUCCEEDED(result); }
//***************************************************************************
//
// CLDAPClassProvider::GetADSIClass
//
// Purpose : To Create a CADSIClass from an ADSI classSchema object
// Parameters:
// lpszWBEMClassName : The WBEM Name of the class to be fetched.
// ppADSIClass : The address where the pointer to the CADSIClass will be stored.
// It is the caller's responsibility to Release() the object when done with it
//
// Return Value: The COM status value indicating the status of the request.
//***************************************************************************
HRESULT CLDAPClassProvider :: GetADSIClass(LPCWSTR lpszADSIClassName, CADSIClass **ppADSIClass) { // Convert the WBEM Class Name to LDAP
LPWSTR lpszWBEMClassName = CLDAPHelper::MangleLDAPNameToWBEM(lpszADSIClassName); HRESULT result = s_pLDAPCache->GetClass(lpszWBEMClassName, lpszADSIClassName, ppADSIClass);
delete[] lpszWBEMClassName; return result; }
//***************************************************************************
//
// CLDAPClassProvider::GetADSIProperty
//
// Purpose : To create an CADSIProperty object from an LDAP AttributeSchema object
// Parameters:
// lpszPropertyName : The LDAPDisplayName of the LDAP property to be fetched.
// ppADSIProperty : The address where the pointer to the IDirectoryObject interface will be stored
// It is the caller's responsibility to Release() the interface when done with it
//
// Return Value: The COM status value indicating the status of the request
//***************************************************************************
HRESULT CLDAPClassProvider :: GetADSIProperty(LPCWSTR lpszPropertyName, CADSIProperty **ppADSIProperty) { HRESULT hRes = WBEM_S_NO_ERROR;
if ( ppADSIProperty ) { if ( SUCCEEDED ( hRes = s_pLDAPCache->GetProperty(lpszPropertyName, ppADSIProperty, FALSE) ) ) { if ( NULL == *ppADSIProperty ) { hRes = WBEM_S_FALSE; } } } else { hRes = WBEM_E_INVALID_PARAMETER; }
return hRes; }
//***************************************************************************
//
// CLDAPClassProvider::GetWBEMBaseClassName
//
// Purpose : Returns the name of the class that is the base class of all classes
// provided by this provider.
//
// Parameters:
// None
//
// Return Value: The name of the base class. NULL if such a class doesnt exist.
//***************************************************************************
const BSTR CLDAPClassProvider :: GetWBEMBaseClassName() { return LDAP_BASE_CLASS_STR; }
//***************************************************************************
//
// CLDAPClassProvider::GetWBEMBaseClass
//
// Purpose : Returns a pointer to the class that is the base class of all classes
// provided by this provider.
//
// Parameters:
// None
//
// Return Value: The IWbemClassObject pointer to the base class. It is the duty of
// user to release the class when done with using it.
//***************************************************************************
IWbemClassObject * CLDAPClassProvider :: GetWBEMBaseClass() { m_pLDAPBaseClass->AddRef(); return m_pLDAPBaseClass; }
//***************************************************************************
//
// CLDAPClassProvider::GetWBEMProviderName
//
// Purpose : Returns the name of the provider. This should be the same as the
// value of the field Name in the __Win32Provider instance used for registration
// of the provider
//
// Parameters:
// None
//
// Return Value: The name of the provider
//***************************************************************************
const BSTR CLDAPClassProvider :: GetWBEMProviderName() { return LDAP_CLASS_PROVIDER_NAME; }
//***************************************************************************
//
// CLDAPClassProvider::IsUnProvidedClass
//
// Purpose : See header
//***************************************************************************
BOOLEAN CLDAPClassProvider :: IsUnProvidedClass(LPCWSTR lpszClassName) { // CHeck if it is one of the static classes
if(_wcsicmp(lpszClassName, LDAP_BASE_CLASS_STR) == 0 || _wcsicmp(lpszClassName, UINT8ARRAY_CLASS) == 0 || _wcsicmp(lpszClassName, DN_WITH_STRING_CLASS) == 0 || _wcsicmp(lpszClassName, DN_WITH_BINARY_CLASS) == 0 || _wcsicmp(lpszClassName, ROOTDSE_CLASS) == 0 || _wcsicmp(lpszClassName, CLASS_ASSOCIATION_CLASS) == 0 || _wcsicmp(lpszClassName, DN_ASSOCIATION_CLASS) == 0 || _wcsicmp(lpszClassName, DN_CLASS) == 0 || _wcsicmp(lpszClassName, INSTANCE_ASSOCIATION_CLASS) == 0) return TRUE;
// Next check if it has appropriate profixes
if(_wcsnicmp(lpszClassName, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX_LENGTH) == 0 || _wcsnicmp(lpszClassName, LDAP_CLASS_NAME_PREFIX, LDAP_CLASS_NAME_PREFIX_LENGTH) == 0 ) { return FALSE; }
return TRUE; }
//***************************************************************************
//
// CLDAPClassProvider::GetClassFromADSI
//
// Purpose : To return the IDirectoryObject interface on the schema container
//
// Parameters:
// lpszClassName : The WBEM Name of the class to be retreived
// pCtx : A pointer to the context object that was used in this call. This
// may be used by this function to make calls to CIMOM
// ppWbemClass : The resulting WBEM Class. This has to be released once the
// user is done with it.
//
//
// Return Value: The COM result representing the status.
//***************************************************************************
HRESULT CLDAPClassProvider :: GetClassFromADSI( LPCWSTR lpszWbemClassName, IWbemContext *pCtx, IWbemClassObject ** ppWbemClass ) { HRESULT result = E_FAIL; BOOLEAN bArtificialClass = FALSE; BOOLEAN bAbstractDSClass = FALSE; LPWSTR lpszADSIClassName = NULL;
// First check if this is one our "artificial" classes. All "aritificial" classes start with "ads_".
// All non artificial classes start with "ds_"
if(!(lpszADSIClassName = CLDAPHelper::UnmangleWBEMNameToLDAP(lpszWbemClassName))) { *ppWbemClass = NULL; return result; }
if(_wcsnicmp(lpszWbemClassName, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX_LENGTH) == 0) bArtificialClass = TRUE;
CADSIClass *pADSIClass = NULL; CADSIClass *pADSIParentClass = NULL;
try { if(SUCCEEDED(result = GetADSIClass(lpszADSIClassName, &pADSIClass))) { pADSIClass->SetWBEMClassName(lpszWbemClassName);
// It is an abstract class is the ADSI class type is Abstract or Auxiliary
if(pADSIClass->GetObjectClassCategory() == 2 || pADSIClass->GetObjectClassCategory() == 3) bAbstractDSClass = TRUE;
int iCaseNumber = 0;
// if the WBEM class name starts with "ADS_" and the DS class is abstract, then this is an error
if(bArtificialClass && bAbstractDSClass) result = WBEM_E_NOT_FOUND; else { // Special case for "top" since the DS returns top as the superclass of top
if(_wcsicmp(lpszWbemClassName, TOP_CLASS) == 0) iCaseNumber = 1; else { if(pADSIClass->GetSuperClassLDAPName()) { // If this is an artificial class
// Then
// Get the ParentDS Class
// If the ParentDSClass is abstract
// Then
// WMI Parent class is the non-artificial class. Case 2
// Else
// WMI Parent class is artificial. Case 3
// Else
// If the Current DS Class is abstract
// Then
// WMI Parent is non-artificial. Case 4
// Else
// WMI Parent is artificial. Case 5
//
if(bArtificialClass) { // Get the parent DS Class
if(SUCCEEDED(result = GetADSIClass(pADSIClass->GetSuperClassLDAPName(), &pADSIParentClass))) { if(pADSIParentClass->GetObjectClassCategory() == 2 || pADSIParentClass->GetObjectClassCategory() == 3) { iCaseNumber = 2; } else { iCaseNumber = 3; } } } else { if(bAbstractDSClass) { iCaseNumber = 4; } else { iCaseNumber = 5; } } } else iCaseNumber = 1; } // Map the ADSI class to a WBEM Class
if(iCaseNumber != 0 && SUCCEEDED(result = CreateWBEMClass(pADSIClass, iCaseNumber, ppWbemClass, pCtx))) { } else { result = WBEM_E_FAILED; g_pLogObject->WriteW(L"CLDAPClassProvider :: GetClassFromADSI() : CreateWBEMClass FAILED: %x for %s\r\n", result, lpszWbemClassName); } }
// Free the parent ADSI class
if(pADSIParentClass) { pADSIParentClass->Release(); pADSIParentClass = NULL; }
// Free the ADSI Class
if ( pADSIClass ) { pADSIClass->Release(); pADSIClass = NULL; } } else g_pLogObject->WriteW( L"CLDAPClassProvider :: GetClassFromADSI() GetADSIClass FAILED : %x for %s\r\n", result, lpszWbemClassName); } catch ( ... ) { // Free the parent ADSI class
if ( pADSIParentClass ) { pADSIParentClass->Release(); pADSIParentClass = NULL; }
// Free the ADSI Class
if ( pADSIClass ) { pADSIClass->Release(); pADSIClass = NULL; }
delete [] lpszADSIClassName; throw; }
delete [] lpszADSIClassName; return result; }
//***************************************************************************
//
// CLDAPClassProvider::CreateWBEMClass
//
// Purpose: Creates WBEM Class corresponding an ADSI Class
//
// Parameters:
// pADSIClass : A pointer to a CADSI class object that is to be mapped to WBEM.
// ppWbemClass : The WBEM class object retrieved. This is created by this function.
// The caller should release it when done
// pCtx : The context object that was used in this provider call
//
// Return Value: The COM value representing the return status
//
//***************************************************************************
HRESULT CLDAPClassProvider :: CreateWBEMClass (CADSIClass *pADSIClass, int iCaseNumber, IWbemClassObject **ppWbemClass, IWbemContext *pCtx) { HRESULT result;
*ppWbemClass = NULL;
// Create the WBEM class and Map the class qualifiers
if( SUCCEEDED(result = MapClassSystemProperties(pADSIClass, iCaseNumber, ppWbemClass, pCtx) ) ) { // Now that ppWbemClass has been allocated, we need to deallocate it if the return value of this function
// is not a success
//=======================================================================================================
if(iCaseNumber == 5) { // Nothing more to do except add the "provider" qualifier
IWbemQualifierSet *pQualifierSet = NULL; if(SUCCEEDED(result = (*ppWbemClass)->GetQualifierSet(&pQualifierSet))) { result = CWBEMHelper::PutBSTRQualifier(pQualifierSet, PROVIDER_BSTR, LDAP_INSTANCE_PROVIDER_NAME, DEFAULT_QUALIFIER_FLAVOUR, FALSE); pQualifierSet->Release(); } } else { if( SUCCEEDED(result = MapClassQualifiersToWBEM(pADSIClass, iCaseNumber, *ppWbemClass, pCtx) ) ) { // Map the class properties
if( SUCCEEDED(result = MapClassPropertiesToWBEM(pADSIClass, *ppWbemClass, pCtx) ) ) { } else g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateWBEMClass() MapClassPropertiesToWBEM FAILED : %x for %s\r\n", result, pADSIClass->GetWBEMClassName()); } else g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateWBEMClass() MapClassQualifiersToWBEM FAILED : %x for %s\r\n", result, pADSIClass->GetWBEMClassName()); } } else g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateWBEMClass() MapClassSystemProperties FAILED : %x for %s\r\n", result, pADSIClass->GetWBEMClassName());
if(!SUCCEEDED(result)) { if(*ppWbemClass) { (*ppWbemClass)->Release(); *ppWbemClass = NULL; } }
return result; }
//***************************************************************************
//
// CLDAPClassProvider::MapClassSystemProperties
//
// Purpose: Creates an appropriately derived WBEM class and names it (__CLASS)
//
// Parameters:
// pADSIClass : The ADSI class that is being mapped
// ppWbemClass : The WBEM class object retrieved. This is created by this function.
// The caller should release it when done
// pCtx : The context object that was used in this provider call
//
// Return Value: The COM value representing the return status
//
//***************************************************************************
HRESULT CLDAPClassProvider :: MapClassSystemProperties(CADSIClass *pADSIClass, int iCaseNumber, IWbemClassObject **ppWbemClass, IWbemContext *pCtx) { HRESULT result = WBEM_S_NO_ERROR; LPCWSTR lpszClassName = pADSIClass->GetWBEMClassName();
// Create the WBEM class first.
// This process depends on whether the ADSI class is derived from
// another ADSI class or not.
// If so, that base class has to be retrieved and the derived class
// to be spawned from that.
// If not, then the function GetWBEMBaseClass() is called and the class
// being mapped is derived from that class
IWbemClassObject *pBaseClass = NULL; if(iCaseNumber == 1) { pBaseClass = GetWBEMBaseClass(); } else { LPWSTR lpszWBEMParentClassName = NULL; switch(iCaseNumber) { case 1: { pBaseClass = GetWBEMBaseClass(); break; } case 2: case 4: { lpszWBEMParentClassName = CLDAPHelper::MangleLDAPNameToWBEM(pADSIClass->GetSuperClassLDAPName(), FALSE); break; } case 3: { lpszWBEMParentClassName = CLDAPHelper::MangleLDAPNameToWBEM(pADSIClass->GetSuperClassLDAPName(), TRUE); break; } case 5: { lpszWBEMParentClassName = CLDAPHelper::MangleLDAPNameToWBEM(pADSIClass->GetADSIClassName(), TRUE); break; } default: { result = WBEM_E_FAILED; break; } }
if(SUCCEEDED(result)) { BSTR strWBEMParentClass = SysAllocString(lpszWBEMParentClassName); delete [] lpszWBEMParentClassName; // Get the parent WBEM Class
if(FAILED(result = m_IWbemServices->GetObject(strWBEMParentClass, 0, pCtx, &pBaseClass, NULL))) g_pLogObject->WriteW( L"CLDAPClassProvider :: MapClassSystemProperties() GetObject on ADSI base class FAILED : %x for %s\r\n", result, strWBEMParentClass); SysFreeString(strWBEMParentClass); } } if(FAILED(result) || pBaseClass == NULL) return result;
// Spawn the derived class
result = pBaseClass->SpawnDerivedClass(0, ppWbemClass); pBaseClass->Release(); if(SUCCEEDED(result)) { // Create the __CLASS property
// Make sure the case of the letters is not mixed up
SanitizedClassName((LPWSTR)lpszClassName); if(SUCCEEDED(result = CWBEMHelper::PutBSTRProperty(*ppWbemClass, CLASS_STR, SysAllocString(lpszClassName), TRUE))) { } else g_pLogObject->WriteW( L"CLDAPClassProvider :: MapClassSystemProperties() on __CLASS FAILED : %x for %s\r\n", result, lpszClassName); } else g_pLogObject->WriteW( L"CLDAPClassProvider :: MapClassSystemProperties() SpawnDerived on WBEM base class FAILED : %x for %s\r\n", result, lpszClassName); return result; }
//***************************************************************************
//
// CLDAPClassProvider :: MapClassQualifiersToWBEM
//
// Purpose: Creates the class qualifiers for a WBEM class from the ADSI class
//
// Parameters:
// pADSIClass : The LDAP class that is being mapped
// pWbemClass : The WBEM class object being created. T
// pCtx : The context object that was used in this provider call
//
// Return Value: The COM value representing the return status
//
//***************************************************************************
HRESULT CLDAPClassProvider :: MapClassQualifiersToWBEM(CADSIClass *pADSIClass, int iCaseNumber, IWbemClassObject *pWbemClass, IWbemContext *pCtx) { IWbemQualifierSet *pQualifierSet = NULL; HRESULT result = pWbemClass->GetQualifierSet(&pQualifierSet);
LPCWSTR lpszTemp; BOOLEAN bIsAbstract = FALSE;
// Map each of the LDAP class attributes to WBEM class qualifiers/properties
if(SUCCEEDED(result)) { result = CWBEMHelper::PutI4Qualifier(pQualifierSet, OBJECT_CLASS_CATEGORY_ATTR_BSTR, pADSIClass->GetObjectClassCategory(), DEFAULT_QUALIFIER_FLAVOUR); // It is an abstract class is the ADSI class type is Abstract or Auxiliary
if(SUCCEEDED(result) && (pADSIClass->GetObjectClassCategory() == 2 || pADSIClass->GetObjectClassCategory() == 3) ) { bIsAbstract = TRUE; result = CWBEMHelper::PutBOOLQualifier(pQualifierSet, ABSTRACT_BSTR, VARIANT_TRUE, WBEM_FLAVOR_OVERRIDABLE); } else if (iCaseNumber == 2 || iCaseNumber == 3) { bIsAbstract = TRUE; result = CWBEMHelper::PutBOOLQualifier(pQualifierSet, ABSTRACT_BSTR, VARIANT_TRUE, WBEM_FLAVOR_OVERRIDABLE); } }
if(SUCCEEDED(result)) result = CWBEMHelper::PutBOOLQualifier(pQualifierSet, DYNAMIC_BSTR, VARIANT_TRUE, DEFAULT_QUALIFIER_FLAVOUR);
// provider qualifier is put only for non-abstract classes
if(!bIsAbstract && SUCCEEDED(result)) result = CWBEMHelper::PutBSTRQualifier(pQualifierSet, PROVIDER_BSTR, LDAP_INSTANCE_PROVIDER_NAME, DEFAULT_QUALIFIER_FLAVOUR, FALSE);
if(SUCCEEDED(result)) result = CWBEMHelper::PutBSTRQualifier(pQualifierSet, COMMON_NAME_ATTR_BSTR, SysAllocString(pADSIClass->GetCommonName()), DEFAULT_QUALIFIER_FLAVOUR);
if(SUCCEEDED(result)) result = CWBEMHelper::PutBSTRQualifier(pQualifierSet, LDAP_DISPLAY_NAME_ATTR_BSTR, SysAllocString(pADSIClass->GetName()), DEFAULT_QUALIFIER_FLAVOUR); if(SUCCEEDED(result)) result = CWBEMHelper::PutBSTRQualifier(pQualifierSet, GOVERNS_ID_ATTR_BSTR, SysAllocString(pADSIClass->GetGovernsID()), DEFAULT_QUALIFIER_FLAVOUR); // Do not map this, since this is not exposed thru the schema-management snapin
/*
if(SUCCEEDED(result)) { const LPBYTE pValues = pADSIClass->GetSchemaIDGUID(&dwTemp); result = CWBEMHelper::PutUint8ArrayQualifier(pQualifierSet, SCHEMA_ID_GUID_ATTR_BSTR, pValues, dwTemp, DEFAULT_QUALIFIER_FLAVOUR); } */ if(SUCCEEDED(result) && (lpszTemp = pADSIClass->GetDefaultSecurityDescriptor())) result = CWBEMHelper::PutBSTRQualifier(pQualifierSet, DEFAULT_SECURITY_DESCRP_ATTR_BSTR, SysAllocString(lpszTemp), DEFAULT_QUALIFIER_FLAVOUR); if(SUCCEEDED(result)) result = CWBEMHelper::PutBOOLQualifier(pQualifierSet, SYSTEM_ONLY_ATTR_BSTR, pADSIClass->GetSystemOnly(), DEFAULT_QUALIFIER_FLAVOUR);
/*
if(SUCCEEDED(result)) { const LPBYTE pValues = pADSIClass->GetNTSecurityDescriptor(&dwTemp); result = CWBEMHelper::PutUint8ArrayQualifier(pQualifierSet, NT_SECURITY_DESCRIPTOR_ATTR_BSTR, pValues, dwTemp, DEFAULT_QUALIFIER_FLAVOUR); } */
if(SUCCEEDED(result)) result = CWBEMHelper::PutBSTRQualifier(pQualifierSet, DEFAULT_OBJECTCATEGORY_ATTR_BSTR, SysAllocString(pADSIClass->GetDefaultObjectCategory()), DEFAULT_QUALIFIER_FLAVOUR);
pQualifierSet->Release(); return result; }
//***************************************************************************
//
// CLDAPClassProvider :: MapClassPropertiesToWBEM
//
// Purpose: Creates the class properties for a WBEM class from the ADSI class
//
// Parameters:
// pADSIClass : The LDAP class that is being mapped
// pWbemClass : The WBEM class object being created.
// pCtx : The context object that was used in this provider call
//
// Return Value: The COM value representing the return status
//
//***************************************************************************
HRESULT CLDAPClassProvider :: MapClassPropertiesToWBEM(CADSIClass *pADSIClass, IWbemClassObject *pWbemClass, IWbemContext *pCtx) { HRESULT result = S_OK;
//////////////////////////////////////////////////
// Go thru the set of Auxiliary Classes
//////////////////////////////////////////////////
DWORD dwCount = 0; LPCWSTR *lppszPropertyList = pADSIClass->GetAuxiliaryClasses(&dwCount); CADSIClass *pNextClass = NULL; if(dwCount) { for(DWORD dwNextClass=0; dwNextClass<dwCount; dwNextClass++) { LPWSTR lpszWBEMClassName = CLDAPHelper::MangleLDAPNameToWBEM(lppszPropertyList[dwNextClass]);
try { if(SUCCEEDED(result = s_pLDAPCache->GetClass(lpszWBEMClassName, lppszPropertyList[dwNextClass], &pNextClass))) { if(SUCCEEDED(result = MapClassPropertiesToWBEM(pNextClass, pWbemClass, pCtx))) { } pNextClass->Release(); pNextClass = NULL; } } catch ( ... ) { if ( pNextClass ) { pNextClass->Release (); pNextClass = NULL; }
delete [] lpszWBEMClassName; throw; }
delete [] lpszWBEMClassName; } } if(FAILED(result)) return result;
//////////////////////////////////////////////////
// Go thru the set of System Auxiliary Classes
//////////////////////////////////////////////////
dwCount = 0; lppszPropertyList = pADSIClass->GetSystemAuxiliaryClasses(&dwCount); pNextClass = NULL; if(dwCount) { for(DWORD dwNextClass=0; dwNextClass<dwCount; dwNextClass++) { LPWSTR lpszWBEMClassName = CLDAPHelper::MangleLDAPNameToWBEM(lppszPropertyList[dwNextClass]);
try { if(SUCCEEDED(result = s_pLDAPCache->GetClass(lpszWBEMClassName, lppszPropertyList[dwNextClass], &pNextClass))) { if(SUCCEEDED(result = MapClassPropertiesToWBEM(pNextClass, pWbemClass, pCtx))) { } pNextClass->Release(); pNextClass = NULL; } } catch ( ... ) { if ( pNextClass ) { pNextClass->Release (); pNextClass = NULL; }
delete [] lpszWBEMClassName; throw; }
delete [] lpszWBEMClassName; } } if(FAILED(result)) return result;
//////////////////////////////////////////////////
// Go thru the set of System May Contains
//////////////////////////////////////////////////
dwCount = 0; lppszPropertyList = pADSIClass->GetSystemMayContains(&dwCount); if(SUCCEEDED(result = MapPropertyListToWBEM(pWbemClass, lppszPropertyList, dwCount, TRUE, FALSE))) { //////////////////////////////////////////////////
// Go thru the set of May Contains
//////////////////////////////////////////////////
dwCount = 0; lppszPropertyList = pADSIClass->GetMayContains(&dwCount); if(SUCCEEDED(result = MapPropertyListToWBEM(pWbemClass, lppszPropertyList, dwCount, FALSE, FALSE))) { //////////////////////////////////////////////////
// Go thru the set of System Must Contains
//////////////////////////////////////////////////
dwCount = 0; lppszPropertyList = pADSIClass->GetSystemMustContains(&dwCount); if(SUCCEEDED(result = MapPropertyListToWBEM(pWbemClass, lppszPropertyList, dwCount, TRUE, TRUE))) { //////////////////////////////////////////////////
// Go thru the set of Must Contains
//////////////////////////////////////////////////
dwCount = 0; lppszPropertyList = pADSIClass->GetMustContains(&dwCount); if(SUCCEEDED(result = MapPropertyListToWBEM(pWbemClass, lppszPropertyList, dwCount, FALSE, TRUE))) {
} // MapPropertyListToWBEM
} // MapPropertyListToWBEM
} // MapPropertyListToWBEM
} // MapPropertyListToWBEM
// Do not map any other properties, if failed
if(FAILED(result)) return result;
// Map the RDN property as indexed
LPWSTR lpszRDNAttribute = NULL; lpszRDNAttribute = CLDAPHelper::MangleLDAPNameToWBEM(pADSIClass->GetRDNAttribute()); if(lpszRDNAttribute) { BSTR strRDNAttribute = SysAllocString(lpszRDNAttribute); IWbemQualifierSet *pQualifierSet = NULL; if(SUCCEEDED(result = pWbemClass->GetPropertyQualifierSet(strRDNAttribute, &pQualifierSet))) { IWbemQualifierSet *pClassQualifiers = NULL; if(SUCCEEDED(result = pWbemClass->GetQualifierSet(&pClassQualifiers))) { // ALso put a qualifier on the class that indicates that this is the RDNAttId
if(SUCCEEDED(result = CWBEMHelper::PutBSTRQualifier(pClassQualifiers, RDN_ATT_ID_ATTR_BSTR, SysAllocString(pADSIClass->GetRDNAttribute()), DEFAULT_QUALIFIER_FLAVOUR, TRUE))) { if(SUCCEEDED(result = CWBEMHelper::PutBOOLQualifier(pQualifierSet, INDEXED_BSTR, VARIANT_TRUE, DEFAULT_QUALIFIER_FLAVOUR))) {
} // It is fine if this property has already been designated as indexed in the base class
else if (result == WBEM_E_OVERRIDE_NOT_ALLOWED) result = S_OK; } pClassQualifiers->Release(); } // Release the Qualifer Set
pQualifierSet->Release(); } SysFreeString(strRDNAttribute); } delete [] lpszRDNAttribute;
return result; }
//***************************************************************************
//
// CLDAPClassProvider :: MapPropertyListToWBEM
//
// Purpose: Maps a list of class properties for a WBEM class from the ADSI class
//
// Parameters:
// pWbemClass : The WBEM class object being created.
// lppszPropertyList : A list of propery names
// dwCOunt : The number of items in the above list
// bMapSystemQualifier : Whether the "system" qualifier should be mapped
// bMapNotNullQualifier: Whether the "notNull" qualifier should be mapped
//
// Return Value: The COM value representing the return status
//
//***************************************************************************
HRESULT CLDAPClassProvider :: MapPropertyListToWBEM(IWbemClassObject *pWbemClass, LPCWSTR *lppszPropertyList, DWORD dwCount, BOOLEAN bMapSystemQualifier, BOOLEAN bMapNotNullQualifier) { HRESULT result = S_OK; CADSIProperty *pNextProperty; IWbemQualifierSet *pQualifierSet; if(dwCount) { for(DWORD dwNextProperty=0; dwNextProperty<dwCount; dwNextProperty++) { // Get the property from the cache. The name of the property will be the LDAP name
if(SUCCEEDED(result = s_pLDAPCache->GetProperty(lppszPropertyList[dwNextProperty], &pNextProperty, FALSE))) { if ( pNextProperty ) { // Map the basic property
if(SUCCEEDED(result = CreateWBEMProperty(pWbemClass, &pQualifierSet, pNextProperty))) { // Map the "system" qualifier
if(bMapSystemQualifier && SUCCEEDED(result = CWBEMHelper::PutBOOLQualifier(pQualifierSet, SYSTEM_BSTR, VARIANT_TRUE, DEFAULT_QUALIFIER_FLAVOUR))) { }
// Map the "not_null" qualifier
if(bMapNotNullQualifier && SUCCEEDED(result = CWBEMHelper::PutBOOLQualifier(pQualifierSet, NOT_NULL_BSTR, VARIANT_TRUE, DEFAULT_QUALIFIER_FLAVOUR))) { }
// Release the qualifier set
pQualifierSet->Release(); } // Release the property
pNextProperty->Release(); } } // Do not map any other properties
if(FAILED(result)) break; } }
return result; }
//***************************************************************************
//
// CLDAPClassProvider :: CreateWBEMProperty
//
// Purpose: Creates a WBEM property from an LDAP property
//
// Parameters:
// pWbemClass : The WBEM class in which the property is created
// ppQualiferSet : The address of the pointer to IWbemQualiferSet where the qualifier set
// of this property will be placed
// pADSIProperty : The ADSI Property object that is being mapped to the property being created
//
// Return Value: The COM value representing the return status
//
//***************************************************************************
HRESULT CLDAPClassProvider :: CreateWBEMProperty(IWbemClassObject *pWbemClass, IWbemQualifierSet **ppQualifierSet, CADSIProperty *pADSIProperty) { HRESULT result = E_FAIL;
// Get all the attributes of the ADSI class
LPCWSTR lpszSyntaxOid = pADSIProperty->GetSyntaxOID(); BSTR strCimTypeQualifier = NULL;
// Note that strCimTypeQualifier is not allocated in this call, so it is not freed.
CIMTYPE theCimType = MapLDAPSyntaxToWBEM(pADSIProperty, &strCimTypeQualifier);
if(lpszSyntaxOid) { // Create the property
BSTR strPropertyName = SysAllocString(pADSIProperty->GetWBEMPropertyName()); if(SUCCEEDED(result = pWbemClass->Put(strPropertyName, 0, NULL, theCimType))) { // Get the Qualifier Set in ppQualifierSet
if(SUCCEEDED(result = pWbemClass->GetPropertyQualifierSet(strPropertyName, ppQualifierSet))) { // Map the property attributes to WBEM qualifiers
if(SUCCEEDED(result = CWBEMHelper::PutBSTRQualifier(*ppQualifierSet, ATTRIBUTE_SYNTAX_ATTR_BSTR, SysAllocString(lpszSyntaxOid), DEFAULT_QUALIFIER_FLAVOUR))) { /* Commented to reduce size of classes
if(SUCCEEDED(result = CWBEMHelper::PutBSTRQualifier(*ppQualifierSet, ATTRIBUTE_ID_ATTR_BSTR, SysAllocString(pADSIProperty->GetAttributeID()), DEFAULT_QUALIFIER_FLAVOUR))) { */ if(SUCCEEDED(result = CWBEMHelper::PutBSTRQualifier(*ppQualifierSet, COMMON_NAME_ATTR_BSTR, SysAllocString(pADSIProperty->GetCommonName()), DEFAULT_QUALIFIER_FLAVOUR))) { /* Commented to reduce size of classes
if(SUCCEEDED(result = CWBEMHelper::PutI4Qualifier(*ppQualifierSet, MAPI_ID_ATTR_BSTR, pADSIProperty->GetMAPI_ID(), DEFAULT_QUALIFIER_FLAVOUR))) { if(SUCCEEDED(result = CWBEMHelper::PutI4Qualifier(*ppQualifierSet, OM_SYNTAX_ATTR_BSTR, pADSIProperty->GetOMSyntax(), DEFAULT_QUALIFIER_FLAVOUR))) { if(pADSIProperty->IsSystemOnly()) { if(SUCCEEDED(result = CWBEMHelper::PutBOOLQualifier(*ppQualifierSet, SYSTEM_ONLY_ATTR_BSTR, VARIANT_TRUE, DEFAULT_QUALIFIER_FLAVOUR))) { } } */
// If this is an embedded property, then use the cimType qualifier on the property
if(strCimTypeQualifier) { result = CWBEMHelper::PutBSTRQualifier(*ppQualifierSet, CIMTYPE_STR, strCimTypeQualifier, DEFAULT_QUALIFIER_FLAVOUR, FALSE); }
if(SUCCEEDED(result) && pADSIProperty->GetSearchFlags() == 1) { if(SUCCEEDED(result = CWBEMHelper::PutBOOLQualifier(*ppQualifierSet, INDEXED_BSTR, VARIANT_TRUE, DEFAULT_QUALIFIER_FLAVOUR))) { } else if (result == WBEM_E_OVERRIDE_NOT_ALLOWED) result = S_OK; } } /*
} } } */ } } else g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateWBEMProperty FAILED to get qualifier set for %s", pADSIProperty->GetADSIPropertyName()); } else g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateWBEMProperty FAILED to put property : %s", pADSIProperty->GetADSIPropertyName());
SysFreeString(strPropertyName); } else { g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateWBEMProperty FAILED to get Syntax OID property for %s", pADSIProperty->GetADSIPropertyName()); result = E_FAIL; }
return result; }
//***************************************************************************
//
// CLDAPClassProvider :: MapLDAPSyntaxToWBEM
//
// Purpose: See Header
//
//***************************************************************************
CIMTYPE CLDAPClassProvider :: MapLDAPSyntaxToWBEM(CADSIProperty *pADSIProperty, BSTR *pstrCimTypeQualifier) { *pstrCimTypeQualifier = NULL; LPCWSTR lpszSyntaxOid = pADSIProperty->GetSyntaxOID(); CIMTYPE retValue = (pADSIProperty->IsMultiValued())? CIM_FLAG_ARRAY : 0;
if(wcscmp(lpszSyntaxOid, UNICODE_STRING_OID) == 0) return retValue | CIM_STRING; else if(wcscmp(lpszSyntaxOid, INTEGER_OID) == 0) return retValue | CIM_SINT32; else if(wcscmp(lpszSyntaxOid, LARGE_INTEGER_OID) == 0) return retValue | CIM_SINT64; else if(wcscmp(lpszSyntaxOid, BOOLEAN_OID) == 0) return retValue | CIM_BOOLEAN; else if(wcscmp(lpszSyntaxOid, OBJECT_IDENTIFIER_OID) == 0) return retValue | CIM_STRING; else if(wcscmp(lpszSyntaxOid, DISTINGUISHED_NAME_OID) == 0) return retValue | CIM_STRING; else if(wcscmp(lpszSyntaxOid, CASE_SENSITIVE_STRING_OID) == 0) return retValue | CIM_STRING; else if(wcscmp(lpszSyntaxOid, CASE_INSENSITIVE_STRING_OID) == 0) return retValue | CIM_STRING; else if(wcscmp(lpszSyntaxOid, PRINT_CASE_STRING_OID) == 0) return retValue | CIM_STRING; else if(wcscmp(lpszSyntaxOid, OCTET_STRING_OID) == 0) { *pstrCimTypeQualifier = EMBED_UINT8ARRAY; return retValue | CIM_OBJECT; } else if(wcscmp(lpszSyntaxOid, NUMERIC_STRING_OID) == 0) return retValue | CIM_STRING; else if(wcscmp(lpszSyntaxOid, PRINT_CASE_STRING_OID) == 0) return retValue | CIM_STRING; else if(wcscmp(lpszSyntaxOid, DN_WITH_BINARY_OID) == 0) { // DN_With_Binary and OR_Name have the same syntax oid.
// They are differentiated base on the value of the OMObjectClass value
if(pADSIProperty->IsORName()) return retValue | CIM_STRING; else // It is DN_With_Binary
{ *pstrCimTypeQualifier = EMBED_DN_WITH_BINARY; return retValue | CIM_OBJECT; } } else if(wcscmp(lpszSyntaxOid, NT_SECURITY_DESCRIPTOR_OID) == 0) { *pstrCimTypeQualifier = EMBED_UINT8ARRAY; return retValue | CIM_OBJECT; } else if(wcscmp(lpszSyntaxOid, PRESENTATION_ADDRESS_OID) == 0) { *pstrCimTypeQualifier = EMBED_UINT8ARRAY; return retValue | CIM_OBJECT; } else if(wcscmp(lpszSyntaxOid, DN_WITH_STRING_OID) == 0) { *pstrCimTypeQualifier = EMBED_DN_WITH_BINARY; return retValue | CIM_OBJECT; } else if(wcscmp(lpszSyntaxOid, SID_OID) == 0) { *pstrCimTypeQualifier = EMBED_UINT8ARRAY; return retValue | CIM_OBJECT; } else if(wcscmp(lpszSyntaxOid, TIME_OID) == 0) return retValue | CIM_DATETIME; else { g_pLogObject->WriteW( L"CLDAPClassProvider :: MapLDAPSyntaxToWBEM FAILED to map syntax for OID: %s\r\n", lpszSyntaxOid); return retValue | CIM_STRING; } }
//***************************************************************************
//
// CLDAPClassProvider :: CreateClassEnumAsync
//
// Purpose: Enumerates the classes
//
// Parameters:
// Standard parmaters as described by the IWbemServices interface
//
//
// Return Value: As described by the IWbemServices interface
//
//***************************************************************************
HRESULT CLDAPClassProvider :: CreateClassEnumAsync( /* [in] */ const BSTR strSuperclass, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { if(!m_bInitializedSuccessfully) { g_pLogObject->WriteW( L"CLDAPClassProvider :: Initialization status is FAILED, hence returning failure\r\n"); return WBEM_E_FAILED; }
g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateClassEnumAsync() called for %s SuperClass and %s \r\n", ((strSuperclass)? strSuperclass : L" "), ((lFlags & WBEM_FLAG_SHALLOW)? L"SHALLOW" : L"DEEP"));
// Impersonate the client
//=======================
HRESULT result = WBEM_E_FAILED; if(!SUCCEEDED(result = WbemCoImpersonateClient())) { g_pLogObject->WriteW( L"CDSClassProvider :: CreateClassEnumAsync() CoImpersonate FAILED for %s with %x\r\n", strSuperclass, result); return WBEM_E_FAILED; }
try {
BSTR strTheSuperClass = strSuperclass; // CIMOM seems to give the strSuperClass as NULL sometimes and as "" sometimes. Make it unambiguous
if(!strTheSuperClass || wcscmp(strTheSuperClass, L"") == 0) { if( lFlags & WBEM_FLAG_SHALLOW) { // Nothing to be done since we do not provide cany classes that fit this
strTheSuperClass = NULL; result = S_OK; } else { strTheSuperClass = LDAP_BASE_CLASS_STR; // Recursive enumeration handled below
} }
// Take the special cases first
// 1. Where the strSuperClass is LDAP_BASE_CLASS_STR and lFlags is Shallow
// Nothing to be returned here, since we are not supplying the LDAP_BASE_CLASS_STR
// which is statically supplied.
//=======================================================================
if(strTheSuperClass && _wcsicmp(strTheSuperClass, LDAP_BASE_CLASS_STR) == 0 ) { // First the TOP class needs to be returned
IWbemClassObject *pReturnObject = NULL; if(SUCCEEDED(result = GetClassFromCacheOrADSI(TOP_CLASS, &pReturnObject, pCtx))) { result = pResponseHandler->Indicate(1, &pReturnObject); pReturnObject->Release();
if(SUCCEEDED(result)) { if( lFlags & WBEM_FLAG_SHALLOW) // Notheing more to be done
{ } else // We've to return all the sub classes of top too, recursively
{ if(SUCCEEDED(result = HandleRecursiveEnumeration(TOP_CLASS, pCtx, pResponseHandler))) { g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateClassEnumAsync() Recursive enumeration for %s succeeded\r\n", strTheSuperClass); } else { g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateClassEnumAsync() Recursive enumeration for %s FAILED\r\n", strTheSuperClass); } } } else g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateClassEnumAsync() Recursive enumeration for %s was CANCELLED\r\n", strTheSuperClass); } } // 2. Where the superClass is specified
//=======================================================================
else if(strTheSuperClass) { // Optimize the operation by seeing if it is one of the static classes and
// its name does not start with "ADS_" or "DS_". Then we dont know anything about it
//============================================================================
if(IsUnProvidedClass(strTheSuperClass)) { result = S_OK; } else { BOOLEAN bArtificialClass = FALSE;
// First check if this is one our "artificial" classes. All "aritificial" classes start with "ads_".
// All non artificial classes start with "ds_"
if(_wcsnicmp(strTheSuperClass, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX_LENGTH) == 0) bArtificialClass = TRUE;
// When the search is shallow
if( lFlags & WBEM_FLAG_SHALLOW) { // The ADSI classes
LPWSTR *ppADSIClasses = NULL; // The number of ADSI classes
DWORD dwNumClasses = 0;
try { if(SUCCEEDED(result = GetOneLevelDeep(strTheSuperClass, bArtificialClass, &ppADSIClasses, &dwNumClasses, pCtx))) { // Interact with CIMOM
//=====================
if(SUCCEEDED(result = WrapUpEnumeration(ppADSIClasses, dwNumClasses, pCtx, pResponseHandler))) { }
// Release the list of ADSI classes and its contents
//==================================================
for(DWORD j=0; j<dwNumClasses; j++) { delete [] ppADSIClasses[j]; ppADSIClasses[j] = NULL; }
delete[] ppADSIClasses; ppADSIClasses = NULL; } } catch ( ... ) { if ( ppADSIClasses ) { for ( DWORD j=0; j<dwNumClasses; j++ ) { delete [] ppADSIClasses[j]; ppADSIClasses[j] = NULL; }
delete[] ppADSIClasses; ppADSIClasses = NULL; }
throw; } } else // the search is deep
{ if(SUCCEEDED(result = HandleRecursiveEnumeration(strTheSuperClass, pCtx, pResponseHandler))) { g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateClassEnumAsync() Recursive enumeration for %s succeeded\r\n", strTheSuperClass); } else { g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateClassEnumAsync() Recursive enumeration for %s FAILED\r\n", strTheSuperClass); } }
} }
if(SUCCEEDED(result)) { pResponseHandler->SetStatus(WBEM_STATUS_COMPLETE, WBEM_S_NO_ERROR, NULL, NULL); g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateClassEnumAsync() Non-Recursive enumeration succeeded\r\n"); } else { pResponseHandler->SetStatus(WBEM_STATUS_COMPLETE, WBEM_E_FAILED, NULL, NULL); g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateClassEnumAsync() Non-Recursive enumeration FAILED for superclass %s \r\n", strTheSuperClass); } } catch(Heap_Exception e_HE) { pResponseHandler->SetStatus(WBEM_STATUS_COMPLETE , WBEM_E_OUT_OF_MEMORY, NULL, NULL); }
return WBEM_S_NO_ERROR; }
//***************************************************************************
//
// CLDAPClassProvider :: GetOneLevelDeep
//
// Purpose: Enumerates the sub classes of a superclass non-recursively
//
// Parameters:
//
// lpszSuperClass : The super class name
// pResponseHandler : The interface where the resulting classes are put
//
//
// Return Value: As described by the IWbemServices interface
//
//***************************************************************************
HRESULT CLDAPClassProvider :: GetOneLevelDeep( LPCWSTR lpszWBEMSuperclass, BOOLEAN bArtificialClass, LPWSTR ** pppADSIClasses, DWORD *pdwNumClasses, IWbemContext *pCtx) { // The ADSI classes
*pppADSIClasses = NULL; // The number of ADSI classes
*pdwNumClasses = 0; HRESULT result = WBEM_E_FAILED;
// See if the super class
IWbemClassObject *pSuperClass = NULL; if(!SUCCEEDED(result = GetClassFromCacheOrADSI(lpszWBEMSuperclass, &pSuperClass, pCtx))) { return WBEM_E_NOT_FOUND; } pSuperClass->Release();
// If the WBEM class is concrete, we dont need to do anything
if (SUCCEEDED(result = IsConcreteClass(lpszWBEMSuperclass, pCtx))) { if(result == S_OK) return S_OK; } else return result;
// See the cache first
//====================
CEnumInfo *pEnumInfo = NULL; try { if(SUCCEEDED(result = s_pWbemCache->GetEnumInfo(lpszWBEMSuperclass, &pEnumInfo))) { CNamesList *pNamesList = pEnumInfo->GetSubClassNames(); *pdwNumClasses = pNamesList->GetAllNames(pppADSIClasses);
pEnumInfo->Release(); pEnumInfo = NULL; } else // Go to ADSI
//============
{ // The following are the possibilities now"
// 1. The Class starts with "ADS_". It is abstract by definition. All its sub-classes except one are abstract,artificial.
// 2. The Class starts with "DS_" and it is abstract. It being concrete is ruled out since it was handled at the
// top of this function
// Get all the ADSI classes
if(SUCCEEDED(result = s_pLDAPCache->EnumerateClasses( lpszWBEMSuperclass, FALSE, pppADSIClasses, pdwNumClasses, bArtificialClass))) {
// Create a list of names for holding the subclasses
CNamesList *pNewList = new CNamesList; LPWSTR pszWBEMName = NULL;
try { // The First case in the 2 cases above
if(bArtificialClass) { // The first element is just the super class without the A
// Example if the super class is "ADS_User", the first element is DS_user
pNewList->AddName((*pppADSIClasses)[0]);
// Start from the secodn element
for(DWORD i=1; i<*pdwNumClasses; i++) { // Convert names to WBEM And add them to the new list
pszWBEMName = CLDAPHelper::MangleLDAPNameToWBEM((*pppADSIClasses)[i], TRUE); pNewList->AddName(pszWBEMName);
delete [] (*pppADSIClasses)[i]; (*pppADSIClasses)[i] = pszWBEMName; } } else // The Second case
{ for(DWORD i=0; i<*pdwNumClasses; i++) { // Convert names to WBEM And add them to the new list
pszWBEMName = CLDAPHelper::MangleLDAPNameToWBEM((*pppADSIClasses)[i], FALSE);
LPWSTR pszRealClassName = NULL;
if(SUCCEEDED(result = IsConcreteClass(pszWBEMName, pCtx))) { if(result == S_OK) { pszRealClassName = CLDAPHelper::MangleLDAPNameToWBEM((*pppADSIClasses)[i], TRUE); delete[] pszWBEMName; pNewList->AddName(pszRealClassName); delete [] (*pppADSIClasses)[i]; (*pppADSIClasses)[i] = pszRealClassName; } else { pNewList->AddName(pszWBEMName); delete [] (*pppADSIClasses)[i]; (*pppADSIClasses)[i] = pszWBEMName; } } else g_pLogObject->WriteW( L"CLDAPClassProvider :: GetOneLevelDeep() UNKNOWN FAILED for %s \r\n", lpszWBEMSuperclass); } } } catch ( ... ) { if ( pNewList ) { delete pNewList; pNewList = NULL; }
throw; }
// Add the new EnumInfo to the Enum cache
pEnumInfo = new CEnumInfo(lpszWBEMSuperclass, pNewList); s_pWbemCache->AddEnumInfo(pEnumInfo);
pEnumInfo->Release(); pEnumInfo = NULL; } else g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateClassEnumAsync() GetOneLevelDeep() FAILED for %s \r\n", lpszWBEMSuperclass); } } catch ( ... ) { if ( pEnumInfo ) { pEnumInfo->Release(); pEnumInfo = NULL; }
throw; }
return result; }
//***************************************************************************
//
// CLDAPClassProvider :: HandleRecursiveEnumeration
//
// Purpose: Enumerates the sub classes of a superclass recursively
//
// Parameters:
//
// lpszSuperClass : The super class name
// pResponseHandler : The interface where the resulting classes are put
//
//
// Return Value: As described by the IWbemServices interface
//
//***************************************************************************
HRESULT CLDAPClassProvider :: HandleRecursiveEnumeration( LPCWSTR lpszWBEMSuperclass, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler) { g_pLogObject->WriteW( L"CLDAPClassProvider :: HandleRecursiveEnumeration() called for %s SuperClass \r\n", ((lpszWBEMSuperclass)? lpszWBEMSuperclass : L" ")); HRESULT result = E_FAIL;
// The ADSI classes
LPWSTR *ppADSIClasses = NULL; // The number of ADSI classes
DWORD dwNumClasses = 0;
// First check if this is one our "artificial" classes. All "aritificial" classes start with "ads_".
// All non artificial classes start with "ds_"
BOOLEAN bArtificialClass = FALSE; if(_wcsnicmp(lpszWBEMSuperclass, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX_LENGTH) == 0) bArtificialClass = TRUE;
if(SUCCEEDED(result = GetOneLevelDeep(lpszWBEMSuperclass, bArtificialClass, &ppADSIClasses, &dwNumClasses, pCtx))) { // Interact with CIMOM
//=====================
if(FAILED(result = WrapUpEnumeration(ppADSIClasses, dwNumClasses, pCtx, pResponseHandler))) g_pLogObject->WriteW( L"CLDAPClassProvider :: HandleRecursiveEnumeration() WrapUpEnumeration() for Superclass %s FAILED with %x \r\n", ((lpszWBEMSuperclass)? lpszWBEMSuperclass : L" "), result); else { // Go thru the list of ADSI classes and its contents and Enumerate into them too
for(DWORD j=0; j<dwNumClasses; j++) { if(FAILED(result = HandleRecursiveEnumeration(ppADSIClasses[j], pCtx, pResponseHandler))) break; } }
// Go thru the list of ADSI classes and release them
for(DWORD j=0; j<dwNumClasses; j++) delete [] ppADSIClasses[j];
delete[] ppADSIClasses; } return result; }
//***************************************************************************
//
// CLDAPClassProvider :: WrapUpEnumeration
//
// Purpose: Creates WBEM classes from ADSI classes and Indicates them to CIMOM
//
// Parameters:
//
// lpszSuperClass : The super class name
// pResponseHandler : The interface where the resulting classes are put
//
//
// Return Value: As described by the IWbemServices interface
//
//***************************************************************************
HRESULT CLDAPClassProvider :: WrapUpEnumeration( LPWSTR *ppADSIClasses, DWORD dwNumClasses, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler) { // The WBEM Class objects created
IWbemClassObject **ppReturnWbemClassObjects = NULL; // The number of WBEM class objects that were successfully created
DWORD i=0; DWORD j=0; HRESULT result = S_OK; if(dwNumClasses != 0) { // Allocate an array of IWbemClassObject pointers
ppReturnWbemClassObjects = NULL; if(ppReturnWbemClassObjects = new IWbemClassObject *[dwNumClasses]) { for(i=0; i<dwNumClasses; i++) { // Get the class
if(!SUCCEEDED(result = GetClassFromCacheOrADSI(ppADSIClasses[i], ppReturnWbemClassObjects + i, pCtx))) { g_pLogObject->WriteW( L"CLDAPClassProvider :: WrapUpEnumeration() GetClassFromCacheOrADSI() FAILED with %x \r\n", result); break; } } } else result = E_OUTOFMEMORY; }
// Indicate(), but do not SetStatus()
if(SUCCEEDED(result)) { // result = pResponseHandler->Indicate(i, ppReturnWbemClassObjects);
////////////////////////////////////
//
// Break it up into 4 objects at a time - JUST FOR TESTING AGAINST BUG 39838
//
DWORD dwMaxObjectsAtATime = 4; j = 0; while ( j<i ) { DWORD dwThisIndicationsCount = ((i-j) > dwMaxObjectsAtATime)? dwMaxObjectsAtATime : (i-j); if(FAILED(result = pResponseHandler->Indicate(dwThisIndicationsCount, ppReturnWbemClassObjects + j))) { g_pLogObject->WriteW( L"CLDAPClassProvider :: WrapUpEnumeration() Indicate() FAILED with %x \r\n", result); break; }
j+= dwThisIndicationsCount; } } else g_pLogObject->WriteW( L"CLDAPClassProvider :: HandleRecursiveEnumeration() WrapUpEnumeration() FAILED with %x \r\n", result);
// Delete the list of WBEM Classes and its contents.
for(j=0; j<i; j++) (ppReturnWbemClassObjects[j])->Release(); delete[] ppReturnWbemClassObjects;
return result; }
//***************************************************************************
//
// CLDAPClassProvider :: IsConcreteClass
//
// Purpose: Find out whether a WBEM class is concrete.
//
// Parameters:
//
// pszWBEMName : The class name
//
//
// Return Value: As described by the IWbemServices interface
//
//***************************************************************************
HRESULT CLDAPClassProvider :: IsConcreteClass( LPCWSTR pszWBEMName, IWbemContext *pCtx) { // The call to IsConcreteClass is optimized if the class is artificial,
// since all artificial classes are non-concrete
if(_wcsnicmp(pszWBEMName, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX_LENGTH) == 0) return S_FALSE;
IWbemClassObject *pWbemClass = NULL; HRESULT result = E_FAIL;
if(SUCCEEDED(GetClassFromCacheOrADSI(pszWBEMName, &pWbemClass, pCtx))) { IWbemQualifierSet *pQualifierSet = NULL; if(SUCCEEDED(result = pWbemClass->GetQualifierSet(&pQualifierSet))) { VARIANT_BOOL bAbstract = VARIANT_FALSE; if(SUCCEEDED(CWBEMHelper::GetBOOLQualifier(pQualifierSet, ABSTRACT_BSTR, &bAbstract, NULL))) { if(bAbstract == VARIANT_TRUE) result = S_FALSE; else result = S_OK; } pQualifierSet->Release(); } pWbemClass->Release(); } return result; }
void CLDAPClassProvider :: SanitizedClassName(LPWSTR lpszClassName) { while(*lpszClassName) { *lpszClassName = towlower(*lpszClassName); lpszClassName++; } }
|