windows-nt/Source/XPSP1/NT/admin/wmi/wbem/providers/dsprovider/ldapprov.cpp

1742 lines
56 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//
// 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)
{
return s_pLDAPCache->GetProperty(lpszPropertyName, ppADSIProperty, FALSE);
}
//***************************************************************************
//
// 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)))
{
// 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++;
}
}