286 lines
6.6 KiB
C++
286 lines
6.6 KiB
C++
//+--------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
|
//
|
|
// File: dstest.cpp
|
|
//
|
|
// Contents: DS ping test
|
|
//
|
|
// History: 13-Mar-98 mattt created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include "pch.cpp"
|
|
|
|
#pragma hdrstop
|
|
|
|
#include <winldap.h>
|
|
#include <dsrole.h>
|
|
#include <dsgetdc.h>
|
|
|
|
#include <lmaccess.h>
|
|
#include <lmapibuf.h>
|
|
#include <cainfop.h>
|
|
#include "csldap.h"
|
|
|
|
#define __dwFILE__ __dwFILE_CERTCLIB_DSTEST_CPP__
|
|
|
|
|
|
#define DS_RETEST_SECONDS 3
|
|
|
|
HRESULT
|
|
myDoesDSExist(
|
|
IN BOOL fRetry)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
static BOOL s_fKnowDSExists = FALSE;
|
|
static HRESULT s_hrDSExists = HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN);
|
|
static FILETIME s_ftNextTest = {0,0};
|
|
|
|
if (s_fKnowDSExists && (s_hrDSExists != S_OK) && fRetry)
|
|
// s_fKnowDSExists = FALSE; // force a retry
|
|
{
|
|
FILETIME ftCurrent;
|
|
GetSystemTimeAsFileTime(&ftCurrent);
|
|
|
|
// if Compare is < 0 (next < current), force retest
|
|
if (0 > CompareFileTime(&s_ftNextTest, &ftCurrent))
|
|
s_fKnowDSExists = FALSE;
|
|
}
|
|
|
|
if (!s_fKnowDSExists)
|
|
{
|
|
GetSystemTimeAsFileTime(&s_ftNextTest);
|
|
|
|
// set NEXT in 100ns increments
|
|
|
|
((LARGE_INTEGER *) &s_ftNextTest)->QuadPart +=
|
|
(__int64) (CVT_BASE * CVT_SECONDS * 60) * DS_RETEST_SECONDS;
|
|
|
|
// NetApi32 is delay loaded, so wrap to catch problems when it's not available
|
|
__try
|
|
{
|
|
DOMAIN_CONTROLLER_INFO *pDCI;
|
|
DSROLE_PRIMARY_DOMAIN_INFO_BASIC *pDsRole;
|
|
|
|
// ensure we're not standalone
|
|
pDsRole = NULL;
|
|
hr = DsRoleGetPrimaryDomainInformation( // Delayload wrapped
|
|
NULL,
|
|
DsRolePrimaryDomainInfoBasic,
|
|
(BYTE **) &pDsRole);
|
|
|
|
_PrintIfError(hr, "DsRoleGetPrimaryDomainInformation");
|
|
if (S_OK == hr &&
|
|
(pDsRole->MachineRole == DsRole_RoleStandaloneServer ||
|
|
pDsRole->MachineRole == DsRole_RoleStandaloneWorkstation))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN);
|
|
_PrintError(hr, "DsRoleGetPrimaryDomainInformation(no domain)");
|
|
}
|
|
|
|
if (NULL != pDsRole)
|
|
{
|
|
DsRoleFreeMemory(pDsRole); // Delayload wrapped
|
|
}
|
|
if (S_OK == hr)
|
|
{
|
|
// not standalone; return info on our DS
|
|
|
|
pDCI = NULL;
|
|
hr = DsGetDcName( // Delayload wrapped
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
DS_DIRECTORY_SERVICE_PREFERRED,
|
|
&pDCI);
|
|
_PrintIfError(hr, "DsGetDcName");
|
|
|
|
if (S_OK == hr && 0 == (pDCI->Flags & DS_DS_FLAG))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_CANT_ACCESS_DOMAIN_INFO);
|
|
_PrintError(hr, "DsGetDcName(no domain info)");
|
|
}
|
|
if (NULL != pDCI)
|
|
{
|
|
NetApiBufferFree(pDCI); // Delayload wrapped
|
|
}
|
|
}
|
|
s_fKnowDSExists = TRUE;
|
|
}
|
|
__except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
}
|
|
|
|
// else just allow users without netapi flounder with timeouts
|
|
// if ds not available...
|
|
|
|
s_hrDSExists = myHError(hr);
|
|
_PrintIfError2(
|
|
s_hrDSExists,
|
|
"DsRoleGetPrimaryDomainInformation/DsGetDcName",
|
|
HRESULT_FROM_WIN32(ERROR_NETWORK_UNREACHABLE));
|
|
}
|
|
return(s_hrDSExists);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
myRobustLdapBind(
|
|
OUT LDAP **ppldap,
|
|
IN BOOL fGC)
|
|
{
|
|
return(myRobustLdapBindEx(fGC, FALSE, LDAP_VERSION2, NULL, ppldap, NULL));
|
|
}
|
|
|
|
|
|
HRESULT
|
|
myRobustLdapBindEx(
|
|
IN BOOL fGC,
|
|
IN BOOL fRediscover,
|
|
IN ULONG uVersion,
|
|
OPTIONAL IN WCHAR const *pwszDomainName,
|
|
OUT LDAP **ppldap,
|
|
OPTIONAL OUT WCHAR **ppwszForestDNSName)
|
|
{
|
|
HRESULT hr;
|
|
ULONG ldaperr;
|
|
DWORD GetDSNameFlags;
|
|
LDAP *pld = NULL;
|
|
|
|
GetDSNameFlags = DS_RETURN_DNS_NAME;
|
|
if (fGC)
|
|
{
|
|
GetDSNameFlags |= DS_GC_SERVER_REQUIRED;
|
|
}
|
|
|
|
// bind to ds
|
|
|
|
while (TRUE)
|
|
{
|
|
if (NULL != pld)
|
|
{
|
|
ldap_unbind(pld);
|
|
}
|
|
|
|
pld = ldap_init(
|
|
const_cast<WCHAR *>(pwszDomainName),
|
|
fGC? LDAP_GC_PORT : LDAP_PORT);
|
|
if (NULL == pld)
|
|
{
|
|
hr = myHLdapLastError(NULL, NULL);
|
|
if (!fRediscover)
|
|
{
|
|
_PrintError2(hr, "ldap_init", hr);
|
|
fRediscover = TRUE;
|
|
continue;
|
|
}
|
|
_JumpError(hr, error, "ldap_init");
|
|
}
|
|
|
|
if (fRediscover)
|
|
{
|
|
GetDSNameFlags |= DS_FORCE_REDISCOVERY;
|
|
}
|
|
ldaperr = ldap_set_option(
|
|
pld,
|
|
LDAP_OPT_GETDSNAME_FLAGS,
|
|
(VOID *) &GetDSNameFlags);
|
|
if (LDAP_SUCCESS != ldaperr)
|
|
{
|
|
hr = myHLdapError(pld, ldaperr, NULL);
|
|
if (!fRediscover)
|
|
{
|
|
_PrintError2(hr, "ldap_set_option", hr);
|
|
fRediscover = TRUE;
|
|
continue;
|
|
}
|
|
_JumpError(hr, error, "ldap_set_option");
|
|
}
|
|
|
|
// do not want this to turn on if uVersion is not LDAP_VERSION2
|
|
|
|
//if (LDAP_VERSION2 == uVersion)
|
|
if (IsWhistler())
|
|
{
|
|
ldaperr = ldap_set_option(pld, LDAP_OPT_SIGN, LDAP_OPT_ON);
|
|
if (LDAP_SUCCESS != ldaperr)
|
|
{
|
|
hr = myHLdapError2(pld, ldaperr, LDAP_PARAM_ERROR, NULL);
|
|
if (!fRediscover)
|
|
{
|
|
_PrintError2(hr, "ldap_set_option", hr);
|
|
fRediscover = TRUE;
|
|
continue;
|
|
}
|
|
_JumpError(hr, error, "ldap_set_option");
|
|
}
|
|
}
|
|
|
|
// set the client version. No need to set LDAP_VERSION2 since
|
|
// this is the default
|
|
|
|
if (LDAP_VERSION2 != uVersion)
|
|
{
|
|
ldaperr = ldap_set_option(pld, LDAP_OPT_VERSION, &uVersion);
|
|
if (LDAP_SUCCESS != ldaperr)
|
|
{
|
|
hr = myHLdapError(pld, ldaperr, NULL);
|
|
if (!fRediscover)
|
|
{
|
|
_PrintError2(hr, "ldap_set_option", hr);
|
|
fRediscover = TRUE;
|
|
continue;
|
|
}
|
|
_JumpError(hr, error, "ldap_set_option");
|
|
}
|
|
}
|
|
|
|
ldaperr = ldap_bind_s(pld, NULL, NULL, LDAP_AUTH_NEGOTIATE);
|
|
if (LDAP_SUCCESS != ldaperr)
|
|
{
|
|
hr = myHLdapError(pld, ldaperr, NULL);
|
|
if (!fRediscover)
|
|
{
|
|
_PrintError2(hr, "ldap_bind_s", hr);
|
|
fRediscover = TRUE;
|
|
continue;
|
|
}
|
|
_JumpError(hr, error, "ldap_bind_s");
|
|
}
|
|
|
|
if (NULL != ppwszForestDNSName)
|
|
{
|
|
WCHAR *pwszDomainControllerName;
|
|
|
|
hr = myLdapGetDSHostName(pld, &pwszDomainControllerName);
|
|
if (S_OK != hr)
|
|
{
|
|
if (!fRediscover)
|
|
{
|
|
_PrintError2(hr, "myLdapGetDSHostName", hr);
|
|
fRediscover = TRUE;
|
|
continue;
|
|
}
|
|
_JumpError(hr, error, "myLdapGetDSHostName");
|
|
}
|
|
hr = myDupString(pwszDomainControllerName, ppwszForestDNSName);
|
|
_JumpIfError(hr, error, "myDupString");
|
|
}
|
|
break;
|
|
}
|
|
*ppldap = pld;
|
|
pld = NULL;
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pld)
|
|
{
|
|
ldap_unbind(pld);
|
|
}
|
|
return(hr);
|
|
}
|