1258 lines
39 KiB
C++
1258 lines
39 KiB
C++
//
|
|
|
|
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
// ***************************************************************************
|
|
//
|
|
// Original Author: Rajesh Rao
|
|
//
|
|
// $Author: rajeshr $
|
|
// $Date: 6/11/98 4:43p $
|
|
// $Workfile:ldaphelp.cpp $
|
|
//
|
|
// $Modtime: 6/11/98 11:21a $
|
|
// $Revision: 1 $
|
|
// $Nokeywords: $
|
|
//
|
|
//
|
|
// Description: Contains the implementation the CLDAPHelper class. This is
|
|
// a class that has many static helper functions pertaining to ADSI LDAP Provider
|
|
//***************************************************************************
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
LPCWSTR CLDAPHelper :: LDAP_CN_EQUALS = L"LDAP://CN=";
|
|
LPCWSTR CLDAPHelper :: LDAP_DISP_NAME_EQUALS = L"(lDAPDisplayName=";
|
|
LPCWSTR CLDAPHelper :: OBJECT_CATEGORY_EQUALS_CLASS_SCHEMA = L"(objectCategory=classSchema)";
|
|
LPCWSTR CLDAPHelper :: SUB_CLASS_OF_EQUALS = L"(subclassOf=";
|
|
LPCWSTR CLDAPHelper :: NOT_LDAP_NAME_EQUALS = L"(!ldapDisplayName=";
|
|
LPCWSTR CLDAPHelper :: LEFT_BRACKET_AND = L"(&";
|
|
LPCWSTR CLDAPHelper :: GOVERNS_ID_EQUALS = L"(governsId=";
|
|
LPCWSTR CLDAPHelper :: CLASS_SCHEMA = L"classSchema";
|
|
LPCWSTR CLDAPHelper :: CN_EQUALS = L"cn=";
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLDAPHelper :: GetLDAPClassFromLDAPName
|
|
//
|
|
// Purpose : See Header
|
|
//***************************************************************************
|
|
HRESULT CLDAPHelper :: GetLDAPClassFromLDAPName(
|
|
IDirectorySearch *pDirectorySearchSchemaContainer,
|
|
LPCWSTR lpszSchemaContainerSuffix,
|
|
PADS_SEARCHPREF_INFO pSearchInfo,
|
|
DWORD dwSearchInfoCount,
|
|
CADSIClass *pADSIClass
|
|
)
|
|
{
|
|
// We map the object from the LDAP Display name
|
|
// Hence we cannot directly do an ADsOpenObject().
|
|
// We have to send an LDAP query for the instance of ClassSchema/AttributeSchema where the
|
|
// ldapdisplayname attribute is the lpszObjectName parameter.
|
|
HRESULT result = E_FAIL;
|
|
|
|
// For the search filter;
|
|
LPCWSTR lpszLDAPObjectName = pADSIClass->GetADSIClassName();
|
|
LPWSTR lpszSearchFilter = NULL;
|
|
if(lpszSearchFilter = new WCHAR[ wcslen(LDAP_DISP_NAME_EQUALS) + wcslen(lpszLDAPObjectName) + wcslen(RIGHT_BRACKET_STR) + 1])
|
|
{
|
|
try
|
|
{
|
|
wcscpy(lpszSearchFilter, LDAP_DISP_NAME_EQUALS);
|
|
wcscat(lpszSearchFilter, lpszLDAPObjectName);
|
|
wcscat(lpszSearchFilter, RIGHT_BRACKET_STR);
|
|
ADS_SEARCH_HANDLE hADSSearch;
|
|
if(SUCCEEDED(result = pDirectorySearchSchemaContainer->ExecuteSearch(lpszSearchFilter, NULL, -1, &hADSSearch)))
|
|
{
|
|
try
|
|
{
|
|
if(SUCCEEDED(result = pDirectorySearchSchemaContainer->GetNextRow(hADSSearch)) && result != S_ADS_NOMORE_ROWS)
|
|
{
|
|
// Get the column for the CN attribute
|
|
ADS_SEARCH_COLUMN adsColumn;
|
|
|
|
// Store each of the LDAP class attributes
|
|
// Reset the LDAP and WBEM names to take care of change in case
|
|
if(SUCCEEDED(result) && SUCCEEDED(result = pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)LDAP_DISPLAY_NAME_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
{
|
|
pADSIClass->SetADSIClassName(adsColumn.pADsValues->CaseIgnoreString);
|
|
LPWSTR lpszWBEMName = CLDAPHelper::MangleLDAPNameToWBEM(adsColumn.pADsValues->CaseIgnoreString);
|
|
|
|
try
|
|
{
|
|
pADSIClass->SetWBEMClassName(lpszWBEMName);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
delete [] lpszWBEMName;
|
|
throw;
|
|
}
|
|
|
|
delete [] lpszWBEMName;
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
|
|
// Store each of the LDAP class attributes
|
|
if(SUCCEEDED(result) && SUCCEEDED(result = pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)COMMON_NAME_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
pADSIClass->SetCommonName(adsColumn.pADsValues->CaseIgnoreString);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
|
|
// Special case for top since ADSI returns "top" as the parent class of "top" and we
|
|
// will go into an infinite loop later if we dont check this
|
|
if(pADSIClass->GetCommonName() && _wcsicmp(pADSIClass->GetCommonName(), TOP_CLASS) != 0)
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
{
|
|
if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)SUB_CLASS_OF_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
pADSIClass->SetSuperClassLDAPName(adsColumn.pADsValues->CaseIgnoreString);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
}
|
|
}
|
|
|
|
if(SUCCEEDED(result) && SUCCEEDED(result = pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)GOVERNS_ID_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
pADSIClass->SetGovernsID(adsColumn.pADsValues->CaseIgnoreString);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
|
|
if(SUCCEEDED(result) && SUCCEEDED(result = pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)SCHEMA_ID_GUID_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
pADSIClass->SetSchemaIDGUID((adsColumn.pADsValues->OctetString).lpValue, (adsColumn.pADsValues->OctetString).dwLength);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
|
|
if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)RDN_ATT_ID_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
pADSIClass->SetRDNAttribute(adsColumn.pADsValues->CaseIgnoreString);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
|
|
if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)DEFAULT_SECURITY_DESCRP_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
pADSIClass->SetDefaultSecurityDescriptor(adsColumn.pADsValues->CaseIgnoreString);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
|
|
if(SUCCEEDED(result) && SUCCEEDED(result = pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)OBJECT_CLASS_CATEGORY_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
pADSIClass->SetObjectClassCategory(adsColumn.pADsValues->Integer);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
|
|
/*
|
|
if(SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)NT_SECURITY_DESCRIPTOR_ATTR, &adsColumn)))
|
|
{
|
|
pADSIClass->SetNTSecurityDescriptor((adsColumn.pADsValues->SecurityDescriptor).lpValue, (adsColumn.pADsValues->SecurityDescriptor).dwLength);
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
*/
|
|
if(SUCCEEDED(result) && SUCCEEDED(result = pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)DEFAULT_OBJECTCATEGORY_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
{
|
|
// Get the LDAPDIpslayName of the class
|
|
LPWSTR lpszLDAPName = NULL;
|
|
if(SUCCEEDED(result) && SUCCEEDED(result = GetLDAPClassNameFromCN(adsColumn.pADsValues->DNString, &lpszLDAPName)))
|
|
{
|
|
try
|
|
{
|
|
pADSIClass->SetDefaultObjectCategory(lpszLDAPName);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
delete [] lpszLDAPName;
|
|
throw;
|
|
}
|
|
|
|
delete [] lpszLDAPName;
|
|
}
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
|
|
if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)SYSTEM_ONLY_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
pADSIClass->SetSystemOnly((BOOLEAN)adsColumn.pADsValues->Boolean);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
|
|
if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)AUXILIARY_CLASS_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
pADSIClass->SetAuxiliaryClasses(adsColumn.pADsValues, adsColumn.dwNumValues);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
|
|
if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)SYSTEM_AUXILIARY_CLASS_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
pADSIClass->SetSystemAuxiliaryClasses(adsColumn.pADsValues, adsColumn.dwNumValues);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
|
|
if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)SYSTEM_MAY_CONTAIN_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
pADSIClass->SetSystemMayContains(adsColumn.pADsValues, adsColumn.dwNumValues);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)MAY_CONTAIN_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
pADSIClass->SetMayContains(adsColumn.pADsValues, adsColumn.dwNumValues);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)SYSTEM_MUST_CONTAIN_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
pADSIClass->SetSystemMustContains(adsColumn.pADsValues, adsColumn.dwNumValues);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)MUST_CONTAIN_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
pADSIClass->SetMustContains(adsColumn.pADsValues, adsColumn.dwNumValues);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)SYSTEM_POSS_SUPERIORS_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
pADSIClass->SetSystemPossibleSuperiors(adsColumn.pADsValues, adsColumn.dwNumValues);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)POSS_SUPERIORS_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
pADSIClass->SetPossibleSuperiors(adsColumn.pADsValues, adsColumn.dwNumValues);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
}
|
|
else
|
|
result = E_FAIL;
|
|
}
|
|
catch ( ... )
|
|
{
|
|
// Close the search
|
|
pDirectorySearchSchemaContainer->CloseSearchHandle(hADSSearch);
|
|
|
|
throw;
|
|
}
|
|
|
|
// Close the search
|
|
pDirectorySearchSchemaContainer->CloseSearchHandle(hADSSearch);
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
if ( lpszSearchFilter )
|
|
{
|
|
// Delete the filter
|
|
delete [] lpszSearchFilter;
|
|
lpszSearchFilter = NULL;
|
|
}
|
|
|
|
throw;
|
|
}
|
|
|
|
if ( lpszSearchFilter )
|
|
{
|
|
// Delete the filter
|
|
delete [] lpszSearchFilter;
|
|
lpszSearchFilter = NULL;
|
|
}
|
|
}
|
|
else
|
|
result = E_OUTOFMEMORY;
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLDAPHelper :: GetLDAPSchemaObjectFromCommonName
|
|
//
|
|
// Purpose : To fetch the IDirectoryObject interface on a class/property provided by the LDAP Provider
|
|
// Parameters:
|
|
// lpszSchemaContainerSuffix : The suffix to be used. The actual object fetced will be:
|
|
// LDAP://CN=<lpszCommonName>,<lpszSchemaContainerSuffix>
|
|
// lpszCommonName : The 'cn' attribute of the LDAP class or property to be fetched.
|
|
// ppLDAPObject : The address where the pointer to IDirectoryObject will be stored
|
|
// It is the caller's responsibility to delete the object when done with it
|
|
//
|
|
// Return Value: The COM status value indicating the status of the request.
|
|
//***************************************************************************
|
|
HRESULT CLDAPHelper :: GetLDAPSchemaObjectFromCommonName(
|
|
LPCWSTR lpszSchemaContainerSuffix,
|
|
LPCWSTR lpszCommonName,
|
|
IDirectoryObject **ppLDAPObject)
|
|
{
|
|
HRESULT result = S_OK;
|
|
|
|
// Form the ADSI path to the LDAP object
|
|
LPWSTR lpszLDAPObjectPath = NULL;
|
|
if(lpszLDAPObjectPath = new WCHAR[wcslen(LDAP_CN_EQUALS) + wcslen(lpszCommonName) + wcslen(COMMA_STR) + wcslen(lpszSchemaContainerSuffix) + 1])
|
|
{
|
|
wcscpy(lpszLDAPObjectPath, LDAP_CN_EQUALS);
|
|
wcscat(lpszLDAPObjectPath, lpszCommonName);
|
|
wcscat(lpszLDAPObjectPath, COMMA_STR);
|
|
wcscat(lpszLDAPObjectPath, lpszSchemaContainerSuffix);
|
|
|
|
result = ADsOpenObject(lpszLDAPObjectPath, NULL, NULL, ADS_SECURE_AUTHENTICATION, IID_IDirectoryObject, (LPVOID *)ppLDAPObject);
|
|
|
|
delete[] lpszLDAPObjectPath;
|
|
}
|
|
else
|
|
result = E_OUTOFMEMORY;
|
|
return result;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLDAPHelper :: GetLDAPClassNameFromCN
|
|
//
|
|
// Purpose : To fetch the LDAPDisplayNAme of a class from its path
|
|
// Parameters:
|
|
//
|
|
// lpszLDAPClassPath : The path to the class object without the LDAP prefix. Ex CN=user,CN=Schema, CN=COnfiguration ...
|
|
// Return Value: The COM status value indicating the status of the request. The user should delete the
|
|
// name returned, when done
|
|
//***************************************************************************
|
|
HRESULT CLDAPHelper :: GetLDAPClassNameFromCN(LPCWSTR lpszLDAPClassPath,
|
|
LPWSTR *lppszLDAPName)
|
|
{
|
|
IDirectoryObject *pLDAPClass = NULL;
|
|
|
|
// Prepend the LDAP:// perfix
|
|
LPWSTR lpszRealPath = NULL;
|
|
HRESULT result = S_OK;
|
|
if(lpszRealPath = new WCHAR[ wcslen(LDAP_PREFIX) + wcslen(lpszLDAPClassPath) + 1])
|
|
{
|
|
wcscpy(lpszRealPath, LDAP_PREFIX);
|
|
wcscat(lpszRealPath, lpszLDAPClassPath);
|
|
|
|
result = ADsOpenObject(lpszRealPath, NULL, NULL, ADS_SECURE_AUTHENTICATION, IID_IDirectoryObject, (LPVOID *)&pLDAPClass);
|
|
delete [] lpszRealPath;
|
|
}
|
|
else
|
|
result = E_OUTOFMEMORY;
|
|
|
|
// Get the attribute LDAPDisplayName
|
|
if(SUCCEEDED(result))
|
|
{
|
|
PADS_ATTR_INFO pAttributes = NULL;
|
|
DWORD dwReturnCount = 0;
|
|
if(SUCCEEDED(result = pLDAPClass->GetObjectAttributes((LPWSTR *)&LDAP_DISPLAY_NAME_ATTR, 1, &pAttributes, &dwReturnCount)) && dwReturnCount == 1)
|
|
{
|
|
if(pAttributes->pADsValues->dwType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
{
|
|
*lppszLDAPName = NULL;
|
|
if(*lppszLDAPName = new WCHAR[wcslen(pAttributes->pADsValues->DNString) + 1])
|
|
wcscpy(*lppszLDAPName, pAttributes->pADsValues->DNString);
|
|
else
|
|
result = E_OUTOFMEMORY;
|
|
}
|
|
FreeADsMem((LPVOID *)pAttributes);
|
|
}
|
|
|
|
pLDAPClass->Release();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLDAPHelper :: EnumerateClasses
|
|
//
|
|
// Purpose : See Header
|
|
//***************************************************************************
|
|
HRESULT CLDAPHelper :: EnumerateClasses(
|
|
IDirectorySearch *pDirectorySearchSchemaContainer,
|
|
LPCWSTR lpszSchemaContainerSuffix,
|
|
PADS_SEARCHPREF_INFO pSearchInfo,
|
|
DWORD dwSearchInfoCount,
|
|
LPCWSTR lpszLDAPSuperClass,
|
|
BOOLEAN bDeep,
|
|
LPWSTR **pppszClassNames,
|
|
DWORD *pdwNumRows,
|
|
BOOLEAN bArtificialClass)
|
|
{
|
|
// Initialize the return values
|
|
HRESULT result = E_FAIL;
|
|
*pdwNumRows = 0;
|
|
|
|
// The search filter;
|
|
LPWSTR lpszSearchFilter = NULL;
|
|
|
|
// There's various cases to be considered here.
|
|
// if(lpszLDAPSuperClass is NULL)
|
|
// then
|
|
// if bDeep is false, then no objects is returned (since we do not provide the LDAP base class
|
|
// else all the classes are returned using the filter (objectCategory=classSchema)
|
|
// else
|
|
// if bDeep is false, then the filter (&(objectCategory=classSchema)(subClassOf=lpszLDAPSuperClass)) is used
|
|
// else a lot of work has to be done!
|
|
if(lpszLDAPSuperClass == NULL)
|
|
{
|
|
if(!bDeep)
|
|
{
|
|
*pppszClassNames = NULL;
|
|
*pdwNumRows = 0;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
if(!(lpszSearchFilter = new WCHAR[ wcslen(OBJECT_CATEGORY_EQUALS_CLASS_SCHEMA) + 1]))
|
|
return E_OUTOFMEMORY;
|
|
wcscpy(lpszSearchFilter, OBJECT_CATEGORY_EQUALS_CLASS_SCHEMA);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!bDeep)
|
|
{
|
|
// One would imagine that a filter of the kind
|
|
//(&(objectClass=classSchema)(subClassOf=<lpszLDAPSuperClass>))
|
|
// would be enough. Unfortunately it also gives the Top class
|
|
//in the results when the value of lpszLDAPSuperClass is Top
|
|
// we dont need that. Hnce we form the filter
|
|
//(&(objectClass=classSchema)(subClassOf=<lpszLDAPSuperClass>)(!ldapDisplayName=<lpszLDAPSuperClass>))
|
|
if(lpszSearchFilter = new WCHAR[ wcslen(LEFT_BRACKET_AND) // (&
|
|
+ wcslen(OBJECT_CATEGORY_EQUALS_CLASS_SCHEMA) // (objectCategory=classSchema)
|
|
+ wcslen(SUB_CLASS_OF_EQUALS) // (subClassOf=
|
|
+ wcslen(lpszLDAPSuperClass) // superClass
|
|
+ wcslen(RIGHT_BRACKET_STR) // )
|
|
+ wcslen(NOT_LDAP_NAME_EQUALS) // (!ldapDisplayName=
|
|
+ wcslen(lpszLDAPSuperClass) // superClass
|
|
+ 2*wcslen(RIGHT_BRACKET_STR) // ))
|
|
+1])
|
|
{
|
|
wcscpy(lpszSearchFilter, LEFT_BRACKET_AND);
|
|
wcscat(lpszSearchFilter, OBJECT_CATEGORY_EQUALS_CLASS_SCHEMA);
|
|
wcscat(lpszSearchFilter, SUB_CLASS_OF_EQUALS);
|
|
wcscat(lpszSearchFilter, lpszLDAPSuperClass);
|
|
wcscat(lpszSearchFilter, RIGHT_BRACKET_STR);
|
|
wcscat(lpszSearchFilter, NOT_LDAP_NAME_EQUALS); // (!ldapDisplayName=
|
|
wcscat(lpszSearchFilter, lpszLDAPSuperClass);
|
|
wcscat(lpszSearchFilter, RIGHT_BRACKET_STR);
|
|
wcscat(lpszSearchFilter, RIGHT_BRACKET_STR);
|
|
}
|
|
else
|
|
result = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
lpszSearchFilter = NULL; // THIS SPECIAL CASE IS TACKLED LATER
|
|
}
|
|
|
|
if(lpszSearchFilter)
|
|
{
|
|
ADS_SEARCH_HANDLE hADSSearchOuter;
|
|
if(SUCCEEDED(result = pDirectorySearchSchemaContainer->ExecuteSearch(lpszSearchFilter, (LPWSTR *)&LDAP_DISPLAY_NAME_ATTR, 1, &hADSSearchOuter)))
|
|
{
|
|
*pdwNumRows = 0;
|
|
DWORD dwFirstCount = 0; // Number of rows retreived on the first count
|
|
|
|
// Calculate the number of rows first.
|
|
while(SUCCEEDED(result = pDirectorySearchSchemaContainer->GetNextRow(hADSSearchOuter)) &&
|
|
result != S_ADS_NOMORE_ROWS)
|
|
dwFirstCount ++;
|
|
|
|
// Allocate enough memory for the classes and names
|
|
*pppszClassNames = NULL;
|
|
if(bArtificialClass)
|
|
{
|
|
dwFirstCount ++;
|
|
if(*pppszClassNames = new LPWSTR [dwFirstCount])
|
|
(*pppszClassNames)[0] = NULL;
|
|
else
|
|
result = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
if(!(*pppszClassNames = new LPWSTR [dwFirstCount]))
|
|
result = E_OUTOFMEMORY;
|
|
}
|
|
|
|
// The index of the attribute being processed
|
|
DWORD dwSecondCount = 0;
|
|
if(bArtificialClass)
|
|
dwSecondCount ++;
|
|
|
|
// Get the columns for the attributes
|
|
ADS_SEARCH_COLUMN adsColumn;
|
|
|
|
// Move to the beginning of the search
|
|
if(SUCCEEDED(result = pDirectorySearchSchemaContainer->GetFirstRow(hADSSearchOuter))
|
|
&& result != S_ADS_NOMORE_ROWS)
|
|
{
|
|
// Store each of the LDAP class attributes
|
|
if(SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearchOuter, (LPWSTR)LDAP_DISPLAY_NAME_ATTR, &adsColumn)))
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
{
|
|
result = E_FAIL;
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
else
|
|
{
|
|
// Create the CADSIClass
|
|
(*pppszClassNames)[dwSecondCount] = NULL;
|
|
if((*pppszClassNames)[dwSecondCount] = new WCHAR[wcslen(adsColumn.pADsValues->CaseIgnoreString) + 1])
|
|
wcscpy((*pppszClassNames)[dwSecondCount], adsColumn.pADsValues->CaseIgnoreString);
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
|
|
dwSecondCount++;
|
|
|
|
// Get the rest of the rows
|
|
while(SUCCEEDED(result = pDirectorySearchSchemaContainer->GetNextRow(hADSSearchOuter))&&
|
|
result != S_ADS_NOMORE_ROWS)
|
|
{
|
|
// Store each of the LDAP class attributes
|
|
if(SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearchOuter, (LPWSTR)LDAP_DISPLAY_NAME_ATTR, &adsColumn)))
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
{
|
|
result = E_FAIL;
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
}
|
|
else
|
|
{
|
|
// Create the CADSIClass
|
|
(*pppszClassNames)[dwSecondCount] = NULL;
|
|
if((*pppszClassNames)[dwSecondCount] = new WCHAR[wcslen(adsColumn.pADsValues->CaseIgnoreString) + 1])
|
|
wcscpy((*pppszClassNames)[dwSecondCount], adsColumn.pADsValues->CaseIgnoreString);
|
|
pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
|
|
|
|
dwSecondCount++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Something went wrong? Release allocated resources
|
|
if(dwSecondCount != dwFirstCount)
|
|
{
|
|
// Delete the contents of the array
|
|
for(DWORD j=0; j<dwSecondCount; j++)
|
|
{
|
|
delete [] (*pppszClassNames)[j];
|
|
}
|
|
|
|
// Delete the array itself
|
|
delete [] (*pppszClassNames);
|
|
|
|
// Set return values to empty
|
|
*pppszClassNames = NULL;
|
|
*pdwNumRows = 0;
|
|
|
|
result = E_FAIL;
|
|
}
|
|
else
|
|
*pdwNumRows = dwFirstCount;
|
|
|
|
// Close the search
|
|
pDirectorySearchSchemaContainer->CloseSearchHandle(hADSSearchOuter);
|
|
|
|
} // ExecuteSearch() - Outer
|
|
delete [] lpszSearchFilter;
|
|
}
|
|
else // THIS IS THE SPECIAL CASE WHERE ALL SUBCLASSES (RECURSIVELY) OF A GIVEN CLASS ARE REQUIRED
|
|
{
|
|
// A lot of work has to be done. THis is handled by CLDAPClassProvider. Hence control shold never reach here
|
|
result = E_FAIL;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
// Gets the IDIrectoryObject interface on an ADSI instance
|
|
HRESULT CLDAPHelper :: GetADSIInstance(LPCWSTR szADSIPath, CADSIInstance **ppADSIObject, ProvDebugLog *pLogObject)
|
|
{
|
|
HRESULT result;
|
|
IDirectoryObject *pDirectoryObject;
|
|
*ppADSIObject = NULL;
|
|
|
|
try
|
|
{
|
|
if(SUCCEEDED(result = ADsOpenObject((LPWSTR)szADSIPath, NULL, NULL, ADS_SECURE_AUTHENTICATION, IID_IDirectoryObject, (LPVOID *)&pDirectoryObject)))
|
|
{
|
|
|
|
if(*ppADSIObject = new CADSIInstance(szADSIPath, pDirectoryObject))
|
|
{
|
|
PADS_ATTR_INFO pAttributeEntries;
|
|
DWORD dwNumAttributes;
|
|
if(SUCCEEDED(result = pDirectoryObject->GetObjectAttributes(NULL, -1, &pAttributeEntries, &dwNumAttributes)))
|
|
{
|
|
(*ppADSIObject)->SetAttributes(pAttributeEntries, dwNumAttributes);
|
|
PADS_OBJECT_INFO pObjectInfo = NULL;
|
|
if(SUCCEEDED(result = pDirectoryObject->GetObjectInformation(&pObjectInfo)))
|
|
{
|
|
(*ppADSIObject)->SetObjectInfo(pObjectInfo);
|
|
}
|
|
else
|
|
pLogObject->WriteW( L"CLDAPHelper :: GetADSIInstance GetObjectInformation() FAILED on %s with %x\r\n", szADSIPath, result);
|
|
}
|
|
else
|
|
pLogObject->WriteW( L"CLDAPHelper :: GetADSIInstance GetObjectAttributes() FAILED on %s with %x\r\n", szADSIPath, result);
|
|
}
|
|
else
|
|
result = E_OUTOFMEMORY;
|
|
pDirectoryObject->Release();
|
|
}
|
|
else
|
|
pLogObject->WriteW( L"CLDAPHelper :: GetADSIInstance ADsOpenObject() FAILED on %s with %x\r\n", szADSIPath, result);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
if ( *ppADSIObject )
|
|
{
|
|
delete *ppADSIObject;
|
|
*ppADSIObject = NULL;
|
|
}
|
|
|
|
throw;
|
|
}
|
|
|
|
if(!SUCCEEDED(result))
|
|
{
|
|
delete *ppADSIObject;
|
|
*ppADSIObject = NULL;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLDAPHelper :: CreateADSIPath
|
|
//
|
|
// Purpose : Forms the ADSI path from a class or property name
|
|
//
|
|
// Parameters:
|
|
// lpszLDAPSchemaObjectName : The LDAP class or property name
|
|
// lpszSchemaContainerSuffix : The suffix to be used. The actual object fetced will be:
|
|
// LDAP://CN=<lpszLDAPSchemaObjectName>,<lpszSchemaContainerSuffix>
|
|
//
|
|
// Return Value: The ADSI path to the class or property object. This has to
|
|
// be deallocated by the user
|
|
//***************************************************************************
|
|
LPWSTR CLDAPHelper :: CreateADSIPath(LPCWSTR lpszLDAPSchemaObjectName,
|
|
LPCWSTR lpszSchemaContainerSuffix)
|
|
{
|
|
LPWSTR lpszADSIObjectPath = NULL;
|
|
if(lpszADSIObjectPath = new WCHAR[wcslen(LDAP_CN_EQUALS) + wcslen(lpszLDAPSchemaObjectName) + wcslen(COMMA_STR) + wcslen(lpszSchemaContainerSuffix) + 1])
|
|
{
|
|
wcscpy(lpszADSIObjectPath, LDAP_CN_EQUALS);
|
|
wcscat(lpszADSIObjectPath, lpszLDAPSchemaObjectName);
|
|
wcscat(lpszADSIObjectPath, COMMA_STR);
|
|
wcscat(lpszADSIObjectPath, lpszSchemaContainerSuffix);
|
|
}
|
|
return lpszADSIObjectPath;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLDAPHelper :: UnmangleWBEMNameToLDAP
|
|
//
|
|
// Purpose : Converts a mangled WBEM name to LDAP
|
|
// An underscore in LDAP maps to two underscores in WBEM
|
|
// An hyphen in LDAP maps to one underscore in WBEM
|
|
//
|
|
// Parameters:
|
|
// lpszWBEMName : The WBEM class or property name
|
|
//
|
|
// Return Value: The LDAP name to the class or property object. This has to
|
|
// be deallocated by the user
|
|
//***************************************************************************
|
|
LPWSTR CLDAPHelper :: UnmangleWBEMNameToLDAP(LPCWSTR lpszWBEMName)
|
|
{
|
|
DWORD iPrefixLength = 0;
|
|
if(_wcsnicmp(lpszWBEMName, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX_LENGTH) == 0)
|
|
{
|
|
iPrefixLength = LDAP_ARTIFICIAL_CLASS_NAME_PREFIX_LENGTH;
|
|
}
|
|
else if (_wcsnicmp(lpszWBEMName, LDAP_CLASS_NAME_PREFIX, LDAP_CLASS_NAME_PREFIX_LENGTH) == 0)
|
|
{
|
|
iPrefixLength = LDAP_CLASS_NAME_PREFIX_LENGTH;
|
|
}
|
|
else
|
|
return NULL;
|
|
|
|
// The length of the resulting string (LDAP Name) is bound to be less than of equal to the length of WBEM name
|
|
// So let's allocate the same as the wbem name length
|
|
DWORD dwWbemNameLength = wcslen(lpszWBEMName) - iPrefixLength;
|
|
LPWSTR lpszLDAPName = NULL;
|
|
if(lpszLDAPName = new WCHAR[dwWbemNameLength + 1])
|
|
{
|
|
LPCWSTR lpszWBEMNameWithoutPrefix = lpszWBEMName + iPrefixLength;
|
|
|
|
DWORD j=0;
|
|
for(DWORD i=0; i<dwWbemNameLength; )
|
|
{
|
|
switch(lpszWBEMNameWithoutPrefix[i])
|
|
{
|
|
case (L'_'):
|
|
if(lpszWBEMNameWithoutPrefix[i+1] == L'_')
|
|
{
|
|
i += 2;
|
|
lpszLDAPName[j++] = L'_';
|
|
}
|
|
else
|
|
{
|
|
i++;
|
|
lpszLDAPName[j++] = L'-';
|
|
}
|
|
break;
|
|
|
|
default:
|
|
lpszLDAPName[j++] = lpszWBEMNameWithoutPrefix[i++];
|
|
|
|
}
|
|
}
|
|
lpszLDAPName[j] = NULL;
|
|
}
|
|
return lpszLDAPName;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLDAPHelper :: MangleLDAPNameToWBEM
|
|
//
|
|
// Purpose : Converts a LDAP name to WBEM by mangling it
|
|
// An underscore in LDAP maps to two underscores in WBEM
|
|
// An hyphen in LDAP maps to one underscore in WBEM
|
|
//
|
|
// Parameters:
|
|
// lpszLDAPName : The LDAP class or property name
|
|
//
|
|
// Return Value: The LDAP name to the class or property object. This has to
|
|
// be deallocated by the user
|
|
//***************************************************************************
|
|
LPWSTR CLDAPHelper :: MangleLDAPNameToWBEM(LPCWSTR lpszLDAPName, BOOLEAN bArtificalName)
|
|
{
|
|
if(!lpszLDAPName)
|
|
return NULL;
|
|
|
|
// The length of the resulting string (WBEM Name) is bound to be less than of equal to twice the length of LDAP name
|
|
// So let's allocate double the LDAP name length
|
|
DWORD dwLDAPNameLength = wcslen(lpszLDAPName);
|
|
DWORD dwPrefixLength = (bArtificalName)? LDAP_ARTIFICIAL_CLASS_NAME_PREFIX_LENGTH : LDAP_CLASS_NAME_PREFIX_LENGTH;
|
|
LPWSTR lpszWBEMName = NULL;
|
|
|
|
if(lpszWBEMName = new WCHAR[2*dwLDAPNameLength + dwPrefixLength + 1])
|
|
{
|
|
// Prefix "DS_" or "ADS_"
|
|
if(bArtificalName)
|
|
wcscpy(lpszWBEMName, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX);
|
|
else
|
|
wcscpy(lpszWBEMName, LDAP_CLASS_NAME_PREFIX);
|
|
|
|
DWORD j=dwPrefixLength;
|
|
|
|
for(DWORD i=0; i<dwLDAPNameLength; i++)
|
|
{
|
|
switch(lpszLDAPName[i])
|
|
{
|
|
case (__TEXT('-')):
|
|
lpszWBEMName[j++] = L'_';
|
|
break;
|
|
|
|
case (__TEXT('_')):
|
|
lpszWBEMName[j++] = L'_';
|
|
lpszWBEMName[j++] = L'_';
|
|
break;
|
|
|
|
default:
|
|
lpszWBEMName[j++] = lpszLDAPName[i];
|
|
|
|
}
|
|
}
|
|
lpszWBEMName[j] = NULL;
|
|
}
|
|
return lpszWBEMName;
|
|
}
|
|
|
|
void CLDAPHelper :: DeleteAttributeContents(PADS_ATTR_INFO pAttribute)
|
|
{
|
|
// delete the name
|
|
delete [] pAttribute->pszAttrName;
|
|
|
|
// Delete each value
|
|
for(DWORD i=0; i<pAttribute->dwNumValues; i++)
|
|
DeleteADsValueContents(pAttribute->pADsValues + i);
|
|
|
|
// Delete the array of values
|
|
delete [] pAttribute->pADsValues;
|
|
}
|
|
|
|
void CLDAPHelper :: DeleteADsValueContents(PADSVALUE pValue)
|
|
{
|
|
switch(pValue->dwType)
|
|
{
|
|
// Nothing to delete
|
|
case ADSTYPE_BOOLEAN:
|
|
case ADSTYPE_INTEGER:
|
|
case ADSTYPE_LARGE_INTEGER:
|
|
break;
|
|
|
|
case ADSTYPE_UTC_TIME:
|
|
case ADSTYPE_DN_STRING:
|
|
case ADSTYPE_CASE_EXACT_STRING:
|
|
case ADSTYPE_CASE_IGNORE_STRING:
|
|
case ADSTYPE_PRINTABLE_STRING:
|
|
case ADSTYPE_NUMERIC_STRING:
|
|
delete [] pValue->DNString;
|
|
break;
|
|
|
|
case ADSTYPE_OCTET_STRING:
|
|
case ADSTYPE_NT_SECURITY_DESCRIPTOR:
|
|
delete [] (pValue->OctetString.lpValue);
|
|
break;
|
|
case ADSTYPE_DN_WITH_BINARY:
|
|
delete [] (pValue->pDNWithBinary->lpBinaryValue);
|
|
delete [] (pValue->pDNWithBinary->pszDNString);
|
|
delete pValue->pDNWithBinary;
|
|
break;
|
|
|
|
case ADSTYPE_DN_WITH_STRING:
|
|
delete [] (pValue->pDNWithString->pszStringValue);
|
|
delete [] (pValue->pDNWithString->pszDNString);
|
|
delete pValue->pDNWithString;
|
|
break;
|
|
|
|
default:
|
|
// Cause a Null Pointer violation intentionally
|
|
// Otherwise we leak memory
|
|
{
|
|
assert(0);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLDAPHelper :: ExecuteQuery
|
|
//
|
|
// Purpose : See Header
|
|
//***************************************************************************
|
|
HRESULT CLDAPHelper :: ExecuteQuery(
|
|
LPCWSTR pszPathToRoot,
|
|
PADS_SEARCHPREF_INFO pSearchInfo,
|
|
DWORD dwSearchInfoCount,
|
|
LPCWSTR pszLDAPQuery,
|
|
CADSIInstance ***pppADSIInstances,
|
|
DWORD *pdwNumRows,
|
|
ProvDebugLog *pLogObject)
|
|
{
|
|
// Initialize the return values
|
|
HRESULT result = E_FAIL;
|
|
*pdwNumRows = 0;
|
|
*pppADSIInstances = NULL;
|
|
|
|
// Bind to the node from which the search should start
|
|
IDirectorySearch *pDirectorySearchContainer = NULL;
|
|
if(SUCCEEDED(result = ADsOpenObject((LPWSTR)pszPathToRoot, NULL, NULL, ADS_SECURE_AUTHENTICATION, IID_IDirectorySearch, (LPVOID *)&pDirectorySearchContainer)))
|
|
{
|
|
try
|
|
{
|
|
// Now perform a search for the attribute DISTINGUISHED_NAME_ATTR name
|
|
if(SUCCEEDED(result = pDirectorySearchContainer->SetSearchPreference(pSearchInfo, dwSearchInfoCount)))
|
|
{
|
|
ADS_SEARCH_HANDLE hADSSearchOuter;
|
|
|
|
if(SUCCEEDED(result = pDirectorySearchContainer->ExecuteSearch((LPWSTR) pszLDAPQuery, (LPWSTR *)&ADS_PATH_ATTR, 1, &hADSSearchOuter)))
|
|
{
|
|
*pdwNumRows = 0;
|
|
// Calculate the number of rows first.
|
|
while(SUCCEEDED(result = pDirectorySearchContainer->GetNextRow(hADSSearchOuter)) &&
|
|
result != S_ADS_NOMORE_ROWS)
|
|
(*pdwNumRows) ++;
|
|
|
|
try
|
|
{
|
|
// Do only if there were any rows
|
|
if(*pdwNumRows)
|
|
{
|
|
// The index of the attribute being processed
|
|
DWORD i = 0;
|
|
|
|
// Allocate enough memory for the classes and names
|
|
*pppADSIInstances = NULL;
|
|
if(*pppADSIInstances = new CADSIInstance * [*pdwNumRows])
|
|
{
|
|
try
|
|
{
|
|
// Get the columns for the attributes
|
|
ADS_SEARCH_COLUMN adsColumn;
|
|
CADSIInstance *pADSIInstance = NULL;
|
|
|
|
// Move to the first row
|
|
if (SUCCEEDED(result = pDirectorySearchContainer->GetFirstRow(hADSSearchOuter))&&
|
|
result != S_ADS_NOMORE_ROWS)
|
|
{
|
|
// Store each of the LDAP class attributes
|
|
if(SUCCEEDED(pDirectorySearchContainer->GetColumn(hADSSearchOuter, (LPWSTR)ADS_PATH_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
{
|
|
// Create the CADSIInstance
|
|
// Now get the attributes on this object
|
|
|
|
if(SUCCEEDED(result = GetADSIInstance(adsColumn.pADsValues->DNString, &pADSIInstance, pLogObject)))
|
|
{
|
|
(*pppADSIInstances)[i] = pADSIInstance;
|
|
i++;
|
|
}
|
|
else
|
|
pLogObject->WriteW( L"CLDAPHelper :: ExecuteQuery GetADSIInstance() FAILED on %s with %x\r\n", adsColumn.pADsValues->DNString, result);
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
// Free resouces
|
|
pDirectorySearchContainer->FreeColumn( &adsColumn );
|
|
}
|
|
else
|
|
pLogObject->WriteW( L"CLDAPHelper :: ExecuteQuery GetColumn() FAILED on %s with %x\r\n", pszLDAPQuery, result);
|
|
|
|
// Get the other rows now
|
|
if(SUCCEEDED(result))
|
|
{
|
|
while(SUCCEEDED(result = pDirectorySearchContainer->GetNextRow(hADSSearchOuter))&&
|
|
result != S_ADS_NOMORE_ROWS)
|
|
{
|
|
|
|
// Store each of the LDAP class attributes
|
|
if(SUCCEEDED(pDirectorySearchContainer->GetColumn(hADSSearchOuter, (LPWSTR)ADS_PATH_ATTR, &adsColumn)))
|
|
{
|
|
try
|
|
{
|
|
if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
|
|
result = E_FAIL;
|
|
else
|
|
{
|
|
// Create the CADSIInstance
|
|
// Now get the attributes on this object
|
|
if(SUCCEEDED(result = GetADSIInstance(adsColumn.pADsValues->DNString, &pADSIInstance, pLogObject)))
|
|
{
|
|
(*pppADSIInstances)[i] = pADSIInstance;
|
|
i++;
|
|
}
|
|
else
|
|
pLogObject->WriteW( L"CLDAPHelper :: ExecuteQuery GetADSIInstance() FAILED on %s with %x\r\n", adsColumn.pADsValues->DNString, result);
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchContainer->FreeColumn( &adsColumn );
|
|
throw;
|
|
}
|
|
|
|
// Free resouces
|
|
pDirectorySearchContainer->FreeColumn( &adsColumn );
|
|
}
|
|
else
|
|
pLogObject->WriteW( L"CLDAPHelper :: ExecuteQuery GetColumn() FAILED on %s with %x\r\n", pszLDAPQuery, result);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
pLogObject->WriteW( L"CLDAPHelper :: ExecuteQuery GetFirstRow() FAILED on %s with %x\r\n", pszLDAPQuery, result);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
// Delete the contents of the array
|
|
for(DWORD j=0; j<i; j++)
|
|
delete (*pppADSIInstances)[j];
|
|
|
|
// Delete the array itself
|
|
delete [] (*pppADSIInstances);
|
|
|
|
// Set return values to empty
|
|
*pppADSIInstances = NULL;
|
|
*pdwNumRows = 0;
|
|
|
|
throw;
|
|
}
|
|
}
|
|
|
|
// Something went wrong? Release allocated resources
|
|
if(i != *pdwNumRows)
|
|
{
|
|
pLogObject->WriteW( L"CLDAPHelper :: ExecuteQuery() Difference between Number of rows in 2 searches %d %d on %s Am invalidating the search as FAILED\r\n", i, *pdwNumRows, pszLDAPQuery);
|
|
|
|
// Delete the contents of the array
|
|
for(DWORD j=0; j<i; j++)
|
|
delete (*pppADSIInstances)[j];
|
|
|
|
// Delete the array itself
|
|
delete [] (*pppADSIInstances);
|
|
|
|
// Set return values to empty
|
|
*pppADSIInstances = NULL;
|
|
*pdwNumRows = 0;
|
|
|
|
result = E_FAIL;
|
|
}
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchContainer->CloseSearchHandle(hADSSearchOuter);
|
|
throw;
|
|
}
|
|
|
|
// Close the search.
|
|
pDirectorySearchContainer->CloseSearchHandle(hADSSearchOuter);
|
|
} // ExecuteSearch()
|
|
else
|
|
pLogObject->WriteW( L"CLDAPHelper :: ExecuteQuery ExecuteSearch() %s FAILED with %x\r\n", pszLDAPQuery, result);
|
|
} // SetSearchPreference()
|
|
else
|
|
pLogObject->WriteW( L"CLDAPHelper :: ExecuteQuery SetSearchPreference() on %s FAILED with %x \r\n", pszPathToRoot, result);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pDirectorySearchContainer->Release();
|
|
throw;
|
|
}
|
|
|
|
pDirectorySearchContainer->Release();
|
|
} // ADsOpenObject
|
|
else
|
|
pLogObject->WriteW( L"CLDAPHelper :: ExecuteQuery ADsOpenObject() on %s FAILED with %x \r\n", pszPathToRoot, result);
|
|
|
|
return result;
|
|
}
|
|
|