Source code of Windows XP (NT5)
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.

285 lines
6.6 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: dstest.cpp
  7. //
  8. // Contents: DS ping test
  9. //
  10. // History: 13-Mar-98 mattt created
  11. //
  12. //---------------------------------------------------------------------------
  13. #include "pch.cpp"
  14. #pragma hdrstop
  15. #include <winldap.h>
  16. #include <dsrole.h>
  17. #include <dsgetdc.h>
  18. #include <lmaccess.h>
  19. #include <lmapibuf.h>
  20. #include <cainfop.h>
  21. #include "csldap.h"
  22. #define __dwFILE__ __dwFILE_CERTCLIB_DSTEST_CPP__
  23. #define DS_RETEST_SECONDS 3
  24. HRESULT
  25. myDoesDSExist(
  26. IN BOOL fRetry)
  27. {
  28. HRESULT hr = S_OK;
  29. static BOOL s_fKnowDSExists = FALSE;
  30. static HRESULT s_hrDSExists = HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN);
  31. static FILETIME s_ftNextTest = {0,0};
  32. if (s_fKnowDSExists && (s_hrDSExists != S_OK) && fRetry)
  33. // s_fKnowDSExists = FALSE; // force a retry
  34. {
  35. FILETIME ftCurrent;
  36. GetSystemTimeAsFileTime(&ftCurrent);
  37. // if Compare is < 0 (next < current), force retest
  38. if (0 > CompareFileTime(&s_ftNextTest, &ftCurrent))
  39. s_fKnowDSExists = FALSE;
  40. }
  41. if (!s_fKnowDSExists)
  42. {
  43. GetSystemTimeAsFileTime(&s_ftNextTest);
  44. // set NEXT in 100ns increments
  45. ((LARGE_INTEGER *) &s_ftNextTest)->QuadPart +=
  46. (__int64) (CVT_BASE * CVT_SECONDS * 60) * DS_RETEST_SECONDS;
  47. // NetApi32 is delay loaded, so wrap to catch problems when it's not available
  48. __try
  49. {
  50. DOMAIN_CONTROLLER_INFO *pDCI;
  51. DSROLE_PRIMARY_DOMAIN_INFO_BASIC *pDsRole;
  52. // ensure we're not standalone
  53. pDsRole = NULL;
  54. hr = DsRoleGetPrimaryDomainInformation( // Delayload wrapped
  55. NULL,
  56. DsRolePrimaryDomainInfoBasic,
  57. (BYTE **) &pDsRole);
  58. _PrintIfError(hr, "DsRoleGetPrimaryDomainInformation");
  59. if (S_OK == hr &&
  60. (pDsRole->MachineRole == DsRole_RoleStandaloneServer ||
  61. pDsRole->MachineRole == DsRole_RoleStandaloneWorkstation))
  62. {
  63. hr = HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN);
  64. _PrintError(hr, "DsRoleGetPrimaryDomainInformation(no domain)");
  65. }
  66. if (NULL != pDsRole)
  67. {
  68. DsRoleFreeMemory(pDsRole); // Delayload wrapped
  69. }
  70. if (S_OK == hr)
  71. {
  72. // not standalone; return info on our DS
  73. pDCI = NULL;
  74. hr = DsGetDcName( // Delayload wrapped
  75. NULL,
  76. NULL,
  77. NULL,
  78. NULL,
  79. DS_DIRECTORY_SERVICE_PREFERRED,
  80. &pDCI);
  81. _PrintIfError(hr, "DsGetDcName");
  82. if (S_OK == hr && 0 == (pDCI->Flags & DS_DS_FLAG))
  83. {
  84. hr = HRESULT_FROM_WIN32(ERROR_CANT_ACCESS_DOMAIN_INFO);
  85. _PrintError(hr, "DsGetDcName(no domain info)");
  86. }
  87. if (NULL != pDCI)
  88. {
  89. NetApiBufferFree(pDCI); // Delayload wrapped
  90. }
  91. }
  92. s_fKnowDSExists = TRUE;
  93. }
  94. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  95. {
  96. }
  97. // else just allow users without netapi flounder with timeouts
  98. // if ds not available...
  99. s_hrDSExists = myHError(hr);
  100. _PrintIfError2(
  101. s_hrDSExists,
  102. "DsRoleGetPrimaryDomainInformation/DsGetDcName",
  103. HRESULT_FROM_WIN32(ERROR_NETWORK_UNREACHABLE));
  104. }
  105. return(s_hrDSExists);
  106. }
  107. HRESULT
  108. myRobustLdapBind(
  109. OUT LDAP **ppldap,
  110. IN BOOL fGC)
  111. {
  112. return(myRobustLdapBindEx(fGC, FALSE, LDAP_VERSION2, NULL, ppldap, NULL));
  113. }
  114. HRESULT
  115. myRobustLdapBindEx(
  116. IN BOOL fGC,
  117. IN BOOL fRediscover,
  118. IN ULONG uVersion,
  119. OPTIONAL IN WCHAR const *pwszDomainName,
  120. OUT LDAP **ppldap,
  121. OPTIONAL OUT WCHAR **ppwszForestDNSName)
  122. {
  123. HRESULT hr;
  124. ULONG ldaperr;
  125. DWORD GetDSNameFlags;
  126. LDAP *pld = NULL;
  127. GetDSNameFlags = DS_RETURN_DNS_NAME;
  128. if (fGC)
  129. {
  130. GetDSNameFlags |= DS_GC_SERVER_REQUIRED;
  131. }
  132. // bind to ds
  133. while (TRUE)
  134. {
  135. if (NULL != pld)
  136. {
  137. ldap_unbind(pld);
  138. }
  139. pld = ldap_init(
  140. const_cast<WCHAR *>(pwszDomainName),
  141. fGC? LDAP_GC_PORT : LDAP_PORT);
  142. if (NULL == pld)
  143. {
  144. hr = myHLdapLastError(NULL, NULL);
  145. if (!fRediscover)
  146. {
  147. _PrintError2(hr, "ldap_init", hr);
  148. fRediscover = TRUE;
  149. continue;
  150. }
  151. _JumpError(hr, error, "ldap_init");
  152. }
  153. if (fRediscover)
  154. {
  155. GetDSNameFlags |= DS_FORCE_REDISCOVERY;
  156. }
  157. ldaperr = ldap_set_option(
  158. pld,
  159. LDAP_OPT_GETDSNAME_FLAGS,
  160. (VOID *) &GetDSNameFlags);
  161. if (LDAP_SUCCESS != ldaperr)
  162. {
  163. hr = myHLdapError(pld, ldaperr, NULL);
  164. if (!fRediscover)
  165. {
  166. _PrintError2(hr, "ldap_set_option", hr);
  167. fRediscover = TRUE;
  168. continue;
  169. }
  170. _JumpError(hr, error, "ldap_set_option");
  171. }
  172. // do not want this to turn on if uVersion is not LDAP_VERSION2
  173. //if (LDAP_VERSION2 == uVersion)
  174. if (IsWhistler())
  175. {
  176. ldaperr = ldap_set_option(pld, LDAP_OPT_SIGN, LDAP_OPT_ON);
  177. if (LDAP_SUCCESS != ldaperr)
  178. {
  179. hr = myHLdapError2(pld, ldaperr, LDAP_PARAM_ERROR, NULL);
  180. if (!fRediscover)
  181. {
  182. _PrintError2(hr, "ldap_set_option", hr);
  183. fRediscover = TRUE;
  184. continue;
  185. }
  186. _JumpError(hr, error, "ldap_set_option");
  187. }
  188. }
  189. // set the client version. No need to set LDAP_VERSION2 since
  190. // this is the default
  191. if (LDAP_VERSION2 != uVersion)
  192. {
  193. ldaperr = ldap_set_option(pld, LDAP_OPT_VERSION, &uVersion);
  194. if (LDAP_SUCCESS != ldaperr)
  195. {
  196. hr = myHLdapError(pld, ldaperr, NULL);
  197. if (!fRediscover)
  198. {
  199. _PrintError2(hr, "ldap_set_option", hr);
  200. fRediscover = TRUE;
  201. continue;
  202. }
  203. _JumpError(hr, error, "ldap_set_option");
  204. }
  205. }
  206. ldaperr = ldap_bind_s(pld, NULL, NULL, LDAP_AUTH_NEGOTIATE);
  207. if (LDAP_SUCCESS != ldaperr)
  208. {
  209. hr = myHLdapError(pld, ldaperr, NULL);
  210. if (!fRediscover)
  211. {
  212. _PrintError2(hr, "ldap_bind_s", hr);
  213. fRediscover = TRUE;
  214. continue;
  215. }
  216. _JumpError(hr, error, "ldap_bind_s");
  217. }
  218. if (NULL != ppwszForestDNSName)
  219. {
  220. WCHAR *pwszDomainControllerName;
  221. hr = myLdapGetDSHostName(pld, &pwszDomainControllerName);
  222. if (S_OK != hr)
  223. {
  224. if (!fRediscover)
  225. {
  226. _PrintError2(hr, "myLdapGetDSHostName", hr);
  227. fRediscover = TRUE;
  228. continue;
  229. }
  230. _JumpError(hr, error, "myLdapGetDSHostName");
  231. }
  232. hr = myDupString(pwszDomainControllerName, ppwszForestDNSName);
  233. _JumpIfError(hr, error, "myDupString");
  234. }
  235. break;
  236. }
  237. *ppldap = pld;
  238. pld = NULL;
  239. hr = S_OK;
  240. error:
  241. if (NULL != pld)
  242. {
  243. ldap_unbind(pld);
  244. }
  245. return(hr);
  246. }