WindowsXP-SP1/ds/adsi/ldap/cenumns.cxx
2020-09-30 16:53:49 +02:00

465 lines
10 KiB
C++

//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996
//
// File: cenumns.cxx
//
// Contents: LDAP Enumerator Code
//
// History:
//----------------------------------------------------------------------------
#include "ldap.hxx"
#pragma hdrstop
DWORD
GetDefaultServer(
DWORD dwPort,
BOOL fVerify,
LPWSTR szDomainDnsName,
LPWSTR szServerName,
BOOL fWriteable
);
DWORD
GetDefaultLdapServer(
LPWSTR Addresses[],
LPDWORD Count,
BOOL Verify,
DWORD dwPort
) ;
//+---------------------------------------------------------------------------
//
// Function: CLDAPNamespaceEnum::Create
//
// Synopsis:
//
// Arguments: [pCollection]
// [ppEnumVariant]
//
// Returns: HRESULT
//
// Modifies:
//
// History: 01-30-95 krishnag Created.
//
//----------------------------------------------------------------------------
HRESULT
CLDAPNamespaceEnum::Create(
CLDAPNamespaceEnum FAR* FAR* ppenumvariant,
VARIANT var,
CCredentials& Credentials,
LPTSTR pszNamespace
)
{
HRESULT hr = S_OK;
CLDAPNamespaceEnum FAR* penumvariant = NULL;
penumvariant = new CLDAPNamespaceEnum();
if (penumvariant == NULL){
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
hr = ObjectTypeList::CreateObjectTypeList(
var,
&penumvariant->_pObjList
);
BAIL_ON_FAILURE(hr);
penumvariant->_Credentials = Credentials;
penumvariant->_pszNamespace = AllocADsStr(pszNamespace);
if (!(penumvariant->_pszNamespace)) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
if( IsGCNamespace(pszNamespace) )
penumvariant->_dwPort = (DWORD) USE_DEFAULT_GC_PORT;
else
penumvariant->_dwPort = (DWORD) USE_DEFAULT_LDAP_PORT;
*ppenumvariant = penumvariant;
RRETURN(hr);
error:
if (penumvariant) {
delete penumvariant;
}
RRETURN_EXP_IF_ERR(hr);
}
//+---------------------------------------------------------------------------
//
// Function: CLDAPNamespaceEnum::CLDAPNamespaceEnum
//
// Synopsis:
//
//
// Arguments:
//
//
// Returns:
//
// Modifies:
//
// History: 01-30-95 krishnag Created.
//
//----------------------------------------------------------------------------
CLDAPNamespaceEnum::CLDAPNamespaceEnum()
{
_dwIndex = 0;
_pObjList = NULL;
}
//+---------------------------------------------------------------------------
//
// Function: CLDAPNamespaceEnum::~CLDAPNamespaceEnum
//
// Synopsis:
//
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 01-30-95 krishnag Created.
//
//----------------------------------------------------------------------------
CLDAPNamespaceEnum::~CLDAPNamespaceEnum()
{
if (_pszNamespace)
FreeADsMem(_pszNamespace);
if ( _pObjList )
delete _pObjList;
}
//+---------------------------------------------------------------------------
//
// Function: CLDAPNamespaceEnum::Next
//
// Synopsis: Returns cElements number of requested ADs objects in the
// array supplied in pvar.
//
// Arguments: [cElements] -- The number of elements requested by client
// [pvar] -- ptr to array of VARIANTs to for return objects
// [pcElementFetched] -- if non-NULL, then number of elements
// -- actually returned is placed here
//
// Returns: HRESULT -- S_OK if number of elements requested are returned
// -- S_FALSE if number of elements is < requested
//
// Modifies:
//
// History:
//
//----------------------------------------------------------------------------
STDMETHODIMP
CLDAPNamespaceEnum::Next(
ULONG cElements,
VARIANT FAR* pvar,
ULONG FAR* pcElementFetched
)
{
ULONG cElementFetched = 0;
HRESULT hr = S_OK;
if ( _dwIndex > 0 ) // only your default ds will be returned, one element
{
if (pcElementFetched)
*pcElementFetched = 0;
RRETURN(S_FALSE);
}
hr = EnumObjects(
cElements,
pvar,
&cElementFetched
);
if (pcElementFetched) {
*pcElementFetched = cElementFetched;
}
RRETURN_EXP_IF_ERR(hr);
}
HRESULT
CLDAPNamespaceEnum::EnumObjects(
ULONG cElements,
VARIANT FAR* pvar,
ULONG FAR* pcElementFetched
)
{
HRESULT hr = S_FALSE;
IDispatch *pDispatch = NULL;
DWORD i = 0;
while (i < cElements) {
if ( _dwIndex > 0 ) // only your default ds will be returned,
// i.e. one element only
{
hr = S_FALSE;
break;
}
_dwIndex++;
hr = GetTreeObject(&pDispatch);
if (hr == S_FALSE) {
break;
}
VariantInit(&pvar[i]);
pvar[i].vt = VT_DISPATCH;
pvar[i].pdispVal = pDispatch;
(*pcElementFetched)++;
i++;
}
RRETURN_EXP_IF_ERR(hr);
}
HRESULT
CLDAPNamespaceEnum::GetTreeObject(
IDispatch ** ppDispatch
)
{
DWORD err = NO_ERROR;
HRESULT hr = S_OK;
LPTSTR *aValuesNamingContext = NULL;
LPTSTR *aValuesObjectClass = NULL;
int nCountValues = 0;
TCHAR *pszLDAPPathName = NULL;
TCHAR szADsClassName[64];
WCHAR szDomainName[MAX_PATH];
WCHAR szServerName[MAX_PATH];
TCHAR *pszNewADsPath = NULL;
TCHAR *pszLast = NULL;
LPWSTR pszNamingContext = NULL;
LPWSTR pszNewADsParent = NULL;
LPWSTR pszNewADsCommonName = NULL;
DWORD fVerify = FALSE;
*ppDispatch = NULL;
ADS_LDP *ld = NULL;
BOOL fGCDefaulted = FALSE;
//
// Now send back the current object
//
RetryGetDefaultServer:
if ( err = GetDefaultServer(
_dwPort,
fVerify,
szDomainName,
szServerName,
TRUE) ){
hr = HRESULT_FROM_WIN32(err);
BAIL_ON_FAILURE(hr);
}
//
// Read the naming contexts
//
if (_dwPort == USE_DEFAULT_GC_PORT) {
fGCDefaulted = TRUE;
pszNamingContext = NULL;
} else {
pszNamingContext = TEXT(LDAP_OPATT_DEFAULT_NAMING_CONTEXT);
}
hr = LdapOpenObject2(
szDomainName,
szServerName,
NULL,
&ld,
_Credentials,
_dwPort
);
if (((hr == HRESULT_FROM_WIN32(ERROR_BAD_NETPATH)) ||
(hr == HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN)))
&& !fVerify) {
fVerify = TRUE;
goto RetryGetDefaultServer ;
}
BAIL_ON_FAILURE(hr);
if (!fGCDefaulted) {
hr = LdapReadAttributeFast(
ld,
NULL,
pszNamingContext,
&aValuesNamingContext,
&nCountValues
);
BAIL_ON_FAILURE(hr);
if ( nCountValues == 0 ) {
//
// The hr will be modified at the end of the function to S_FALSE
// in case of error
BAIL_ON_FAILURE(hr = E_FAIL);
}
hr = BuildADsPathFromLDAPPath2(
FALSE, //Server is present till DSSnapin Works
_pszNamespace,
szDomainName,
_dwPort,
fGCDefaulted ?
TEXT("") :
aValuesNamingContext[0],
&pszNewADsPath
);
} else {
//
// In this case we want to force it to be GC://yourDomain
// so that all searches will be truly global
//
hr = BuildADsPathFromLDAPPath2(
TRUE, // server is present
_pszNamespace,
szDomainName,
_dwPort,
TEXT(""),
&pszNewADsPath
);
}
BAIL_ON_FAILURE(hr);
// this part is common to both code paths
hr = BuildADsParentPath(
pszNewADsPath,
&pszNewADsParent,
&pszNewADsCommonName
);
BAIL_ON_FAILURE(hr);
nCountValues = 0;
//
// Read the object class of the path if necessary
//
if (!fGCDefaulted) {
hr = LdapReadAttributeFast(
ld,
aValuesNamingContext[0],
L"objectClass",
&aValuesObjectClass,
&nCountValues
);
BAIL_ON_FAILURE(hr);
}
if ( nCountValues == 0 && !fGCDefaulted)
{
// This object exists but does not contain objectClass attribute
// which is required for all DS objects. Hence, ignore the object
// and return error.
hr = E_ADS_BAD_PATHNAME;
BAIL_ON_FAILURE(hr);
}
//
// Create the object
//
if (fGCDefaulted) {
hr = CLDAPGenObject::CreateGenericObject(
pszNewADsParent,
pszNewADsCommonName,
L"top",
_Credentials,
ADS_OBJECT_BOUND,
IID_IUnknown,
(void **) ppDispatch
);
} else {
//
// Send all the classes so we can load all extensions
//
hr = CLDAPGenObject::CreateGenericObject(
pszNewADsParent,
pszNewADsCommonName,
aValuesObjectClass,
nCountValues,
_Credentials,
ADS_OBJECT_BOUND,
IID_IDispatch,
(void **) ppDispatch
);
}
BAIL_ON_FAILURE(hr);
error:
if ( aValuesNamingContext )
LdapValueFree( aValuesNamingContext );
if ( aValuesObjectClass )
LdapValueFree( aValuesObjectClass );
if ( pszNewADsPath )
FreeADsStr( pszNewADsPath );
if ( pszNewADsParent) {
FreeADsStr(pszNewADsParent);
}
if (pszNewADsCommonName) {
FreeADsStr(pszNewADsCommonName);
}
if ( ld ){
LdapCloseObject( ld );
}
RRETURN_ENUM_STATUS(hr);
}