|
|
//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996
//
// File: getobj.cxx
//
// Contents: LDAP GetObject functionality
//
// History:
//----------------------------------------------------------------------------
#include "ldap.hxx"
#pragma hdrstop
DWORD GetDefaultLdapServer( LPWSTR Addresses[], LPDWORD Count, BOOL Verify, DWORD dwPort ) ;
DWORD GetDefaultServer( DWORD dwPort, BOOL fVerify, LPWSTR szDomainDnsName, LPWSTR szServerName, BOOL fWriteable );
LPWSTR gpszStickyServerName = NULL; LPWSTR gpszStickyDomainName = NULL; //
// Dont do DsGetDCName with FORCE_DISCOVERY too frequently.
// LastVerifyDefaultServer is uses to track tick count.
//
#define DC_NORETRY (1000 * 60 * 5)
DWORD LastVerifyDefaultServer = 0 ;
//+---------------------------------------------------------------------------
// Function: GetObject
//
// Synopsis: Called by ResolvePathName to return an object
//
// Arguments: [LPTSTR szBuffer]
// [LPVOID *ppObject]
//
// Returns: HRESULT
//
// Modifies: -
//
// History: 11-3-95 krishnag Created.
//
//----------------------------------------------------------------------------
HRESULT GetServerBasedObject( LPWSTR szBuffer, POBJECTINFO pObjectInfo, CCredentials& Credentials, LPVOID * ppObject ) { HRESULT hr = S_OK;
TCHAR *pszLDAPServer = NULL; TCHAR *pszLDAPDn = NULL; TCHAR *pszParent = NULL; TCHAR *pszCommonName = NULL;
TCHAR szNamespace[MAX_PATH];
IADs *pADs = NULL;
LPTSTR *aValues = NULL; LPTSTR *aValuesNamingContext = NULL; int nCount = 0;
TCHAR *pszNewADsPath = NULL; LPWSTR pszNewADsParent = NULL; LPWSTR pszNewADsCommonName = NULL;
LPWSTR pszNamingContext = NULL;
TCHAR *pszLast = NULL; BOOL fVerify = FALSE ;
DWORD dwPort = 0; ADS_LDP *ld = NULL; BOOL fGCDefaulted = FALSE; BOOL fNoDefaultNamingContext = FALSE; BOOL fFastBind = Credentials.GetAuthFlags() & ADS_FAST_BIND;
//
// Validate that this ADs pathname is to be processed by
// us - as in the provider name is LDAP:
//
hr = ValidateProvider(pObjectInfo); BAIL_ON_FAILURE(hr);
hr = ValidateObjectType(pObjectInfo); BAIL_ON_FAILURE(hr);
// Get the namespace name
wcscpy(szNamespace, pObjectInfo->NamespaceName); wcscat(szNamespace, L":");
switch (pObjectInfo->ObjectType) {
case TOKEN_NAMESPACE: //
// This means that this is a namespace object;
// instantiate the namespace object
//
hr = GetNamespaceObject( pObjectInfo, Credentials, ppObject ); BAIL_ON_FAILURE(hr);
break;
case TOKEN_ROOTDSE: //
// This means that this is a RootDSE object;
// instantiate the RootDSE object
//
hr = GetRootDSEObject( pObjectInfo, Credentials, ppObject ); BAIL_ON_FAILURE(hr);
break;
case TOKEN_SCHEMA: case TOKEN_CLASS: case TOKEN_PROPERTY: case TOKEN_SYNTAX:
hr = GetSchemaObject( pObjectInfo, Credentials, pObjectInfo->PortNumber, ppObject ); BAIL_ON_FAILURE(hr); break;
default:
hr = BuildLDAPPathFromADsPath2( szBuffer, &pszLDAPServer, &pszLDAPDn, &dwPort );
hr = LdapOpenObject2( pszLDAPServer, NULL, NULL, &ld, Credentials, dwPort ); BAIL_ON_FAILURE(hr);
if ( pszLDAPDn == NULL ) {
// If only server name is specified, we need to
// find the root of the naming context...
if (dwPort == USE_DEFAULT_GC_PORT) { pszNamingContext = NULL; fGCDefaulted = TRUE; } else { pszNamingContext = TEXT(LDAP_OPATT_DEFAULT_NAMING_CONTEXT); }
// We already have an open connection so we can do
// fast read to avoid looking up the bind cache.
if (!fGCDefaulted ) {
hr = LdapReadAttributeFast( ld, NULL, // the DN is that of the RootDSE
pszNamingContext, &aValuesNamingContext, &nCount );
if (SUCCEEDED(hr) && (nCount < 1)) { hr = HRESULT_FROM_WIN32(ERROR_DS_NO_ATTRIBUTE_OR_VALUE); } }
//
// If we fail reading the naming context then we need to continue
// if the error was no attribute or value, set some flags
//
if (FAILED(hr)) {
if ( hr != HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN) ) {
nCount = 1; pszNamingContext = NULL; hr = S_OK; fNoDefaultNamingContext = TRUE; fGCDefaulted = TRUE; } } BAIL_ON_FAILURE(hr);
//
// At this point we have either
// 1) Valid defaultNamingContext and pszNamingContext
// 2) Either a GC or a case where defaultNamingContext
// is not available - essentially just a null dn
//
hr = BuildADsPathFromLDAPPath2( TRUE, //Server is Present
szNamespace, pszLDAPServer, dwPort, pszNamingContext ? aValuesNamingContext[0] : TEXT(""), &pszNewADsPath ); BAIL_ON_FAILURE(hr);
hr = BuildADsParentPath( pszNewADsPath, &pszNewADsParent, &pszNewADsCommonName ); BAIL_ON_FAILURE(hr);
if (pszLDAPServer) { FreeADsStr(pszLDAPServer); pszLDAPServer = NULL; }
if (pszLDAPDn) { FreeADsStr(pszLDAPDn); pszLDAPDn = NULL; }
//
// Put the info from the new path build above into the
// various components - matters if we are dealing with
// a valid defaultNanmingContext
//
hr = BuildLDAPPathFromADsPath2( pszNewADsPath, &pszLDAPServer, &pszLDAPDn, &dwPort );
} nCount = 0;
// At this point we have a valid DN
// so we can go ahead and do the a fast read rather than
// just a plain read to avoid the overhead of looking upt
// the bindcache.
if (!fGCDefaulted && !fFastBind) {
hr = LdapReadAttributeFast( ld, pszLDAPDn, TEXT("objectClass"), &aValues, &nCount );
BAIL_ON_FAILURE(hr);
if (nCount == 0) { BAIL_ON_FAILURE(hr = E_ADS_BAD_PATHNAME); } }
if (fGCDefaulted) {
//
// This is either GC://server, where we want to
// set the object DN to null so that all
// searches will yield correct results.
// or the case of a server that did not have
// a default naming context in the RootDSE
//
hr = CLDAPGenObject::CreateGenericObject( pszNewADsParent, pszNewADsCommonName, L"top", Credentials, ADS_OBJECT_BOUND, IID_IADs, (void **) &pADs ); } else if (aValuesNamingContext ) {
//
// Need to create the object with new parent
// and newADsCN
//
if (fFastBind) { hr = CLDAPGenObject::CreateGenericObject( pszNewADsParent, pszNewADsCommonName, L"top", Credentials, ADS_OBJECT_BOUND, IID_IADs, (void **) &pADs, fFastBind );
} else {
hr = CLDAPGenObject::CreateGenericObject( pszNewADsParent, pszNewADsCommonName, aValues, nCount, Credentials, ADS_OBJECT_BOUND, IID_IADs, (void **) &pADs, fFastBind ); }
} else { //
// This is the default case where we build the info from
// the data passed into GetObject call
//
hr = BuildADsParentPathFromObjectInfo2( pObjectInfo, &pszParent, &pszCommonName ); BAIL_ON_FAILURE(hr);
if (fFastBind) {
hr = CLDAPGenObject::CreateGenericObject( pszParent, pszCommonName, L"top", Credentials, ADS_OBJECT_BOUND, IID_IADs, (void **) &pADs, fFastBind );
} else {
hr = CLDAPGenObject::CreateGenericObject( pszParent, pszCommonName, aValues, nCount, Credentials, ADS_OBJECT_BOUND, IID_IADs, (void **) &pADs, fFastBind ); } }
BAIL_ON_FAILURE(hr);
//
// InstantiateDerivedObject should add-ref this pointer for us.
//
hr = pADs->QueryInterface( IID_IUnknown, ppObject );
BAIL_ON_FAILURE(hr); break;
}
error:
if ( ld ){ LdapCloseObject( ld ); }
if (pADs) pADs->Release();
if ( aValuesNamingContext ) LdapValueFree( aValuesNamingContext );
if ( aValues ) LdapValueFree( aValues );
if ( pszLDAPServer ) FreeADsStr( pszLDAPServer );
if (pszLDAPDn) { FreeADsStr(pszLDAPDn); }
if ( pszNewADsPath ) FreeADsStr( pszNewADsPath );
if (pszNewADsParent) { FreeADsStr(pszNewADsParent); }
if (pszNewADsCommonName) { FreeADsStr(pszNewADsCommonName); }
if ( pszParent ) FreeADsStr( pszParent );
if ( pszCommonName ) FreeADsStr( pszCommonName );
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: GetNamespaceObject
//
// Synopsis: called by GetObject
//
// Arguments: [POBJECTINFO pObjectInfo]
// [LPVOID * ppObject]
//
// Returns: HRESULT
//
// Modifies: -
//
// History: 11-3-95 krishnag Created.
//
//----------------------------------------------------------------------------
HRESULT GetNamespaceObject( POBJECTINFO pObjectInfo, CCredentials& Credentials, LPVOID * ppObject ) { HRESULT hr; WCHAR szNamespace[MAX_PATH];
hr = ValidateNamespaceObject( pObjectInfo ); BAIL_ON_FAILURE(hr);
wsprintf(szNamespace,L"%s:", pObjectInfo->NamespaceName);
hr = CLDAPNamespace::CreateNamespace( TEXT("ADs:"), szNamespace, Credentials, ADS_OBJECT_BOUND, IID_IUnknown, ppObject );
error:
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: GetRootDSEObject
//
// Synopsis: called by GetObject
//
// Arguments: [POBJECTINFO pObjectInfo]
// [LPVOID * ppObject]
//
// Returns: HRESULT
//
// Modifies: -
//
// History: 11-3-95 krishnag Created.
//
//----------------------------------------------------------------------------
HRESULT GetRootDSEObject( POBJECTINFO pObjectInfo, CCredentials& Credentials, LPVOID * ppObject ) { HRESULT hr; LPWSTR pszParent = NULL; LPWSTR pszCommonName = NULL;
hr = ValidateRootDSEObject( pObjectInfo ); BAIL_ON_FAILURE(hr);
hr = BuildADsParentPathFromObjectInfo2( pObjectInfo, &pszParent, &pszCommonName ); BAIL_ON_FAILURE(hr);
hr = CLDAPRootDSE::CreateRootDSE( pszParent, pszCommonName, L"", Credentials, ADS_OBJECT_BOUND, IID_IUnknown, (void **)ppObject ); error:
if (pszParent) { FreeADsStr(pszParent); }
if (pszCommonName) { FreeADsStr(pszCommonName); }
RRETURN(hr); }
HRESULT ValidateRootDSEObject( POBJECTINFO pObjectInfo ) { if ( pObjectInfo->NumComponents > 1 ) { RRETURN(E_ADS_BAD_PATHNAME); }
RRETURN(S_OK); }
HRESULT ValidateNamespaceObject( POBJECTINFO pObjectInfo ) { if (_tcsicmp(pObjectInfo->NamespaceName, szLDAPNamespaceName) == 0 || _tcsicmp(pObjectInfo->NamespaceName, szGCNamespaceName) == 0) { RRETURN(S_OK); } RRETURN(E_FAIL); }
HRESULT ValidateProvider( POBJECTINFO pObjectInfo ) {
//
// The provider name is case-sensitive. This is a restriction that OLE
// has put on us.
//
if (_tcscmp(pObjectInfo->ProviderName, szProviderName) == 0) { RRETURN(S_OK); } RRETURN(E_FAIL); }
//+---------------------------------------------------------------------------
// Function: GetSchemaObject
//
// Synopsis: called by GetObject
//
// Arguments: [POBJECTINFO pObjectInfo]
// [LPVOID * ppObject]
//
// Returns: HRESULT
//
// Modifies: -
//
// History: 11-3-95 krishnag Created.
//
//----------------------------------------------------------------------------
HRESULT GetSchemaObject( POBJECTINFO pObjectInfo, CCredentials& Credentials, DWORD dwPort, LPVOID * ppObject ) { HRESULT hr = S_OK; TCHAR szDomainName[MAX_PATH]; TCHAR szServerName[MAX_PATH]; TCHAR *pszParent = NULL; TCHAR *pszCommonName = NULL; DWORD dwObjectType = 0; DWORD i,dwStatus;
LDAP_SCHEMA_HANDLE hSchema = NULL; BOOL fFound = FALSE;
hr = ValidateSchemaObject( pObjectInfo, &dwObjectType ); BAIL_ON_FAILURE(hr);
if (pObjectInfo->TreeName) { _tcscpy(szDomainName, pObjectInfo->TreeName);
}else {
LPTSTR aAddresses[5]; DWORD nCount = 5; BOOL fVerify = FALSE;
dwStatus = GetDefaultServer( dwPort, fVerify, szDomainName, szServerName, TRUE );
if (dwStatus) { hr = HRESULT_FROM_WIN32(dwStatus); BAIL_ON_FAILURE(hr); } }
hr = SchemaOpen( szDomainName, &hSchema, Credentials, dwPort ); BAIL_ON_FAILURE(hr);
hr = BuildADsParentPathFromObjectInfo2( pObjectInfo, &pszParent, &pszCommonName ); BAIL_ON_FAILURE(hr);
switch (dwObjectType) {
case LDAP_SCHEMA_ID: hr = CLDAPSchema::CreateSchema( pszParent, pszCommonName, szDomainName, Credentials, ADS_OBJECT_BOUND, IID_IUnknown, ppObject ); BAIL_ON_FAILURE(hr); break;
case LDAP_CLASS_ID: { CLASSINFO *pClassInfo = NULL;
if ( pObjectInfo->NumComponents < 2 ) { hr = E_ADS_BAD_PATHNAME; BAIL_ON_FAILURE(hr); }
//
// Look for the given class name
//
if (pObjectInfo->dwPathType == PATHTYPE_WINDOWS) { hr = SchemaGetClassInfo( hSchema, pObjectInfo->ComponentArray[1].szComponent, &pClassInfo ); }else { hr = SchemaGetClassInfo( hSchema, pObjectInfo->ComponentArray[0].szComponent, &pClassInfo); }
if ( SUCCEEDED(hr)) { if ( pClassInfo == NULL ) // could not find the class name
{ // Do not bail on failure here since we might need to fall
// through to the property case.
hr = E_ADS_BAD_PATHNAME; } }
if ( SUCCEEDED(hr)) { //
// Class name found, create and return the object
//
hr = CLDAPClass::CreateClass( pszParent, hSchema, pClassInfo->pszName, pClassInfo, Credentials, ADS_OBJECT_BOUND, IID_IUnknown, ppObject ); }
if ( SUCCEEDED(hr) || ( pObjectInfo->ObjectType == TOKEN_CLASS ) ) { BAIL_ON_FAILURE(hr); break; } hr = S_OK; // Else the exact type was not specified and we guessed it to be class
// but since CreateClass failed, we need to try and see if it is a
// property object. Hence, falls through
}
case LDAP_PROPERTY_ID: { PROPERTYINFO *pPropertyInfo = NULL;
if ( pObjectInfo->NumComponents < 2) { hr = E_ADS_BAD_PATHNAME; BAIL_ON_FAILURE(hr); }
//
// Look for the given property name
//
if (pObjectInfo->dwPathType == PATHTYPE_WINDOWS) { hr = SchemaGetPropertyInfo( hSchema, pObjectInfo->ComponentArray[1].szComponent, &pPropertyInfo ); }else{ hr = SchemaGetPropertyInfo( hSchema, pObjectInfo->ComponentArray[0].szComponent, &pPropertyInfo );
}
if ( SUCCEEDED(hr)) { if ( pPropertyInfo == NULL ) // could not find the property name
{ // Do not bail on failure here since we might need to fall
// through to the syntax case.
hr = E_ADS_BAD_PATHNAME; } }
if ( SUCCEEDED(hr)) { //
// Property name found, so create and return the object
//
hr = CLDAPProperty::CreateProperty( pszParent, hSchema, pPropertyInfo->pszPropertyName, pPropertyInfo, Credentials, ADS_OBJECT_BOUND, IID_IUnknown, ppObject ); }
if ( SUCCEEDED(hr) || ( pObjectInfo->ObjectType == TOKEN_PROPERTY ) ) { BAIL_ON_FAILURE(hr); break; } hr = S_OK; // Else the exact type was not specified and we guessed it to be
// property but since CreateProperty failed, we need to try and see if
// it is a syntax object. Hence, falls through
}
case LDAP_SYNTAX_ID: if ( pObjectInfo->NumComponents < 2 ) { hr = E_ADS_BAD_PATHNAME; BAIL_ON_FAILURE(hr); }
//
// Look for the given syntax name
//
for ( i = 0; i < g_cLDAPSyntax; i++ ) { if ( _tcsicmp( g_aLDAPSyntax[i].pszName, (pObjectInfo->dwPathType == PATHTYPE_WINDOWS)? pObjectInfo->ComponentArray[1].szComponent: pObjectInfo->ComponentArray[0].szComponent ) == 0 ) break; }
if ( i == g_cLDAPSyntax ) { hr = E_ADS_BAD_PATHNAME; BAIL_ON_FAILURE(hr); }
//
// Syntax name found, create and return the object
//
hr = CLDAPSyntax::CreateSyntax( pszParent, &(g_aLDAPSyntax[i]), Credentials, ADS_OBJECT_BOUND, IID_IUnknown, ppObject ); BAIL_ON_FAILURE(hr); break;
default: hr = E_ADS_UNKNOWN_OBJECT; break;
}
error:
if ( pszParent ) FreeADsStr( pszParent );
if ( pszCommonName ) FreeADsStr( pszCommonName );
if ( hSchema ) SchemaClose( &hSchema );
RRETURN(hr); }
HRESULT ValidateSchemaObject( POBJECTINFO pObjectInfo, PDWORD pdwObjectType ) { DWORD dwNumComponents = 0; HRESULT hr = S_OK;
switch ( pObjectInfo->ObjectType ) {
case TOKEN_CLASS: *pdwObjectType = LDAP_CLASS_ID; break;
case TOKEN_SYNTAX: *pdwObjectType = LDAP_SYNTAX_ID; break;
case TOKEN_PROPERTY: *pdwObjectType = LDAP_PROPERTY_ID; break;
case TOKEN_SCHEMA: dwNumComponents = pObjectInfo->NumComponents;
switch (dwNumComponents) {
case 1: if (!_tcsicmp(pObjectInfo->ComponentArray[0].szComponent, SCHEMA_NAME)) *pdwObjectType = LDAP_SCHEMA_ID; break;
case 2:
if (pObjectInfo->dwPathType == PATHTYPE_WINDOWS) { if (!_tcsicmp(pObjectInfo->ComponentArray[0].szComponent, SCHEMA_NAME)) *pdwObjectType = LDAP_CLASS_ID;
// Might also be a property or syntax object
// see function GetSchemaObject()
}else { if (!_tcsicmp(pObjectInfo->ComponentArray[dwNumComponents - 1].szComponent, SCHEMA_NAME)) *pdwObjectType = LDAP_CLASS_ID;
// Might also be a property or syntax object
// see function GetSchemaObject()
}
break;
default: hr = E_FAIL; break; } break;
default: hr = E_FAIL; break; }
RRETURN(hr); }
HRESULT ValidateObjectType( POBJECTINFO pObjectInfo ) {
if ( pObjectInfo->ObjectType != TOKEN_LDAPOBJECT ) { // The type has already been specified in this case using COMMA
RRETURN(S_OK); }
if ( pObjectInfo->NamespaceName && !pObjectInfo->TreeName && !pObjectInfo->NumComponents ) { pObjectInfo->ObjectType = TOKEN_NAMESPACE; } else if ( pObjectInfo->NamespaceName && pObjectInfo->TreeName && pObjectInfo->NumComponents) {
switch (pObjectInfo->dwPathType) { case PATHTYPE_WINDOWS: if (!_tcsicmp(pObjectInfo->ComponentArray[0].szComponent,SCHEMA_NAME)) pObjectInfo->ObjectType = TOKEN_SCHEMA; else if (!_tcsicmp(pObjectInfo->ComponentArray[0].szComponent,ROOTDSE_NAME)) pObjectInfo->ObjectType = TOKEN_ROOTDSE; break;
case PATHTYPE_X500: default: if (!_tcsicmp(pObjectInfo->ComponentArray[pObjectInfo->NumComponents - 1].szComponent,SCHEMA_NAME)) pObjectInfo->ObjectType = TOKEN_SCHEMA; else if (!_tcsicmp(pObjectInfo->ComponentArray[pObjectInfo->NumComponents - 1].szComponent,ROOTDSE_NAME)) pObjectInfo->ObjectType = TOKEN_ROOTDSE; break;
}
}else if ( pObjectInfo->NamespaceName && !pObjectInfo->TreeName && pObjectInfo->NumComponents) { switch (pObjectInfo->dwPathType) { case PATHTYPE_WINDOWS: if (!_tcsicmp(pObjectInfo->ComponentArray[0].szComponent,SCHEMA_NAME)) pObjectInfo->ObjectType = TOKEN_SCHEMA; else if (!_tcsicmp(pObjectInfo->ComponentArray[0].szComponent,ROOTDSE_NAME)) pObjectInfo->ObjectType = TOKEN_ROOTDSE; break;
case PATHTYPE_X500: default: if (!_tcsicmp(pObjectInfo->ComponentArray[pObjectInfo->NumComponents - 1].szComponent,SCHEMA_NAME)) pObjectInfo->ObjectType = TOKEN_SCHEMA; else if (!_tcsicmp(pObjectInfo->ComponentArray[pObjectInfo->NumComponents - 1].szComponent,ROOTDSE_NAME)) pObjectInfo->ObjectType = TOKEN_ROOTDSE; break;
}
}
RRETURN(S_OK); }
HRESULT GetServerLessBasedObject( LPWSTR szBuffer, POBJECTINFO pObjectInfo, CCredentials& Credentials, LPVOID * ppObject ) { HRESULT hr = S_OK; DWORD dwStatus = NO_ERROR;
TCHAR *pszLDAPServer = NULL; TCHAR *pszLDAPDn = NULL;
TCHAR *pszParent = NULL; TCHAR *pszCommonName = NULL;
TCHAR szADsClassName[64]; WCHAR szDomainName[MAX_PATH]; WCHAR szServerName[MAX_PATH]; WCHAR *pszServerName=NULL;
IADs *pADs = NULL;
LPTSTR *aValues = NULL; int nCount = 0;
TCHAR *pszLast = NULL; BOOL fVerify = FALSE ;
DWORD dwPort = 0; ADS_LDP *ld = NULL;
BOOL fFastBind = Credentials.GetAuthFlags() & ADS_FAST_BIND; BOOL fUseSpecifiedServer = (gpszStickyServerName != NULL);
//
// Validate that this ADs pathname is to be processed by
// us - as in the provider name is LDAP:
//
hr = ValidateProvider(pObjectInfo); BAIL_ON_FAILURE(hr);
hr = ValidateObjectType(pObjectInfo); BAIL_ON_FAILURE(hr);
switch (pObjectInfo->ObjectType) {
case TOKEN_NAMESPACE: //
// This means that this is a namespace object;
// instantiate the namespace object
//
hr = GetNamespaceObject( pObjectInfo, Credentials, ppObject ); BAIL_ON_FAILURE(hr); break;
case TOKEN_ROOTDSE: //
// This means taht this is a namespace object;
// instantiate the namespace object
//
hr = GetRootDSEObject( pObjectInfo, Credentials, ppObject ); BAIL_ON_FAILURE(hr); break;
case TOKEN_SCHEMA: case TOKEN_CLASS: case TOKEN_PROPERTY: case TOKEN_SYNTAX:
hr = GetSchemaObject( pObjectInfo, Credentials, pObjectInfo->PortNumber, ppObject ); BAIL_ON_FAILURE(hr); break;
default:
if ( pObjectInfo->TreeName == NULL ) { LPTSTR pszName; LPTSTR aAddresses[5];
//
// fVerify is initially FALSE. If TRUE DsGetDCName will hit the net.
//
RetryGetDefaultServer:
dwStatus = GetDefaultServer( pObjectInfo->PortNumber, fVerify, szDomainName, szServerName, TRUE ); if (dwStatus) { hr = HRESULT_FROM_WIN32(dwStatus); BAIL_ON_FAILURE(hr); } pszServerName=szServerName;
if (fUseSpecifiedServer) { //
// We need to change the name of the domain to be that of
// the server we want to target. The swap is made if
// 1) gpszDomainName == NULL, that implies that just
// a serverName was set and not which domain it applies to.
// 2) If a domainName is specified, then the domainName
// from above should be that set in the global pointer for
// the target server to be changed.
//
if ((gpszStickyDomainName && (!_wcsicmp(szDomainName, gpszStickyDomainName)) ) || (gpszStickyDomainName == NULL) ) { //
// We need to change the target to the server.
//
wcscpy(szDomainName,gpszStickyServerName); pszServerName = NULL; //
// Make sure if server is down we go to another
// server on the retryGetDefault server path.
//
fUseSpecifiedServer = FALSE; }
}
hr = BuildLDAPPathFromADsPath2( szBuffer, &pszLDAPServer, &pszLDAPDn, &dwPort );
nCount = 0;
// We need to open object here because we want to
// keep the handle open, read will open/close if there
// are no outstanding connections which is likely the case
hr = LdapOpenObject2( szDomainName, pszServerName, pszLDAPDn, &ld, Credentials, dwPort );
if (SUCCEEDED(hr) && !fFastBind) {
hr = LdapReadAttributeFast( ld, pszLDAPDn, TEXT("objectClass"), &aValues, &nCount );
BAIL_ON_FAILURE(hr);
}
//
// If server not present and we have NOT tried with fVerify
// set to TRUE.
//
if (((hr == HRESULT_FROM_WIN32(ERROR_BAD_NETPATH)) || (hr == HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN))) && !fVerify) { DWORD Last = LastVerifyDefaultServer ; DWORD Current = GetTickCount() ;
//
// If tick is zero, assume first time. In the very unlikely
// event we wrapped managed to get exactly zero, we pay the
// cost of the DsGetDcName (with verify).
//
if ((Last == 0) || ((Last <= Current) && ((Current-Last) > DC_NORETRY)) || ((Last > Current) && ((Current+(((DWORD)(-1))- Last)) > DC_NORETRY))) {
//
// Set the time. Note this is not critical section
// protected and in this case it is not necessary.
//
LastVerifyDefaultServer = GetTickCount() ;
fVerify = TRUE ;
goto RetryGetDefaultServer ; } } }
BAIL_ON_FAILURE(hr);
if ( (nCount == 0) && !fFastBind) { // This object exists but does not have an objectClass. We
// can't do anything without the objectClass. Hence, return
// bad path error.
hr = E_ADS_BAD_PATHNAME; BAIL_ON_FAILURE(hr); }
hr = BuildADsParentPathFromObjectInfo2( pObjectInfo, &pszParent, &pszCommonName ); BAIL_ON_FAILURE(hr);
if (fFastBind) {
hr = CLDAPGenObject::CreateGenericObject( pszParent, pszCommonName, L"Top", Credentials, ADS_OBJECT_BOUND, IID_IADs, (void **) &pADs, fFastBind );
} else {
hr = CLDAPGenObject::CreateGenericObject( pszParent, pszCommonName, aValues, nCount, Credentials, ADS_OBJECT_BOUND, IID_IADs, (void **) &pADs, fFastBind );
}
BAIL_ON_FAILURE(hr);
//
// InstantiateDerivedObject should add-ref this pointer for us.
//
hr = pADs->QueryInterface( IID_IUnknown, ppObject ); BAIL_ON_FAILURE(hr); break;
}
error:
if (pADs) pADs->Release();
if ( aValues ) LdapValueFree( aValues );
if ( pszLDAPServer ) FreeADsStr( pszLDAPServer );
if (pszLDAPDn) { FreeADsStr(pszLDAPDn); }
if ( pszParent ) FreeADsStr( pszParent );
if ( pszCommonName ) FreeADsStr( pszCommonName );
// If ld is open, we need to close it, note that if the object
// was created successfuly, the Generic object created will have
// the outstanding reference, if not the connection will be torn
// down as should be expected.
if (ld) { LdapCloseObject(ld); }
RRETURN(hr); }
HRESULT GetObject( LPTSTR szBuffer, CCredentials& Credentials, LPVOID * ppObject ) { HRESULT hr = S_OK; OBJECTINFO ObjectInfo; POBJECTINFO pObjectInfo = &ObjectInfo;
if (!szBuffer || !ppObject) { hr = E_INVALIDARG; RRETURN_EXP_IF_ERR(hr); }
memset(pObjectInfo, 0, sizeof(OBJECTINFO)); pObjectInfo->ObjectType = TOKEN_LDAPOBJECT; hr = ADsObject(szBuffer, pObjectInfo); BAIL_ON_FAILURE(hr);
switch (pObjectInfo->dwServerPresent) {
case TRUE: hr = GetServerBasedObject( szBuffer, pObjectInfo, Credentials, ppObject ); break;
case FALSE: hr = GetServerLessBasedObject( szBuffer, pObjectInfo, Credentials, ppObject );
}
BAIL_ON_FAILURE(hr);
error:
if (pObjectInfo) { FreeObjectInfo(pObjectInfo); }
RRETURN_EXP_IF_ERR(hr);
}
|