You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1762 lines
58 KiB
1762 lines
58 KiB
//
|
|
|
|
// 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++;
|
|
}
|
|
}
|