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.

912 lines
20 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  5. //
  6. // File: ldapc.hxx
  7. //
  8. // Contents:
  9. //
  10. // History: 06-16-96 yihsins Created.
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "ldapc.hxx"
  14. #pragma hdrstop
  15. CRITICAL_SECTION g_DomainDnsCache;
  16. #define ENTER_DOMAINDNS_CRITSECT() EnterCriticalSection(&g_DomainDnsCache)
  17. #define LEAVE_DOMAINDNS_CRITSECT() LeaveCriticalSection(&g_DomainDnsCache)
  18. BOOL g_fDllsLoaded = FALSE;
  19. HANDLE g_hDllNetApi32 = NULL;
  20. HANDLE g_hDllSecur32 = NULL;
  21. extern "C" {
  22. typedef struct _WKSTA_USER_INFO_1A {
  23. LPSTR wkui1_username;
  24. LPSTR wkui1_logon_domain;
  25. LPSTR wkui1_oth_domains;
  26. LPSTR wkui1_logon_server;
  27. }WKSTA_USER_INFO_1A, *PWKSTA_USER_INFO_1A, *LPWKSTA_USER_INFO_1A;
  28. NET_API_STATUS NET_API_FUNCTION
  29. NetWkstaUserGetInfoA (
  30. IN LPSTR reserved,
  31. IN DWORD level,
  32. OUT LPBYTE *bufptr
  33. );
  34. }
  35. int
  36. AnsiToUnicodeString(
  37. LPSTR pAnsi,
  38. LPWSTR pUnicode,
  39. DWORD StringLength
  40. );
  41. //
  42. // Binds to all the dll's that we need to load dynamically.
  43. // The list is
  44. // netapi32.dll
  45. // secur32.dll
  46. //
  47. // The global flag g_fDllsLoaded is updated appropriately.
  48. //
  49. void BindToDlls()
  50. {
  51. if (g_fDllsLoaded) {
  52. return;
  53. }
  54. //
  55. // Use the domaindns critical section to control access.
  56. // There is no real need to define another CS for this as this
  57. // will utmost be called once.
  58. //
  59. DWORD dwLastErr = 0;
  60. ENTER_DOMAINDNS_CRITSECT();
  61. //
  62. // In case someones came in when we were loading the dll's.
  63. //
  64. if (g_fDllsLoaded) {
  65. LEAVE_DOMAINDNS_CRITSECT();
  66. return;
  67. }
  68. //
  69. // Load dll's - each load lib could have set an error if it fails.
  70. //
  71. if (!(g_hDllNetApi32 = LoadLibrary(L"NETAPI32.DLL"))) {
  72. dwLastErr = GetLastError();
  73. }
  74. g_hDllSecur32 = LoadLibrary(L"SECUR32.DLL");
  75. //
  76. // We need to set this as the last error since one of the
  77. // loads failed. This will not work as we add more dll's
  78. // but for now should be ok. This may not even be needed
  79. // cause finally we are interested in the actual functions
  80. // not just the ability to load/unload the dll.
  81. //
  82. if (dwLastErr) {
  83. SetLastError (dwLastErr);
  84. }
  85. g_fDllsLoaded = TRUE;
  86. LEAVE_DOMAINDNS_CRITSECT();
  87. return;
  88. }
  89. //
  90. // LoadNetApi32Function
  91. //
  92. // Args:
  93. // Function to load.
  94. //
  95. // Returns: function pointer if successfully loads the function from
  96. // NETAPI32.DLL. Returns NULL otherwise.
  97. //
  98. //
  99. PVOID LoadNetApi32Function(CHAR *function)
  100. {
  101. if (!g_fDllsLoaded) {
  102. BindToDlls();
  103. }
  104. if (g_hDllNetApi32) {
  105. return ((PVOID) GetProcAddress((HMODULE)g_hDllNetApi32, function));
  106. }
  107. return NULL;
  108. }
  109. //
  110. // LoadSecur32Function
  111. //
  112. // Args:
  113. // Function to load.
  114. //
  115. // Returns: function pointer if successfully loads the function from
  116. // secur32.DLL. Returns NULL otherwise.
  117. //
  118. //
  119. PVOID LoadSecur32Function(CHAR *function)
  120. {
  121. if (!g_fDllsLoaded) {
  122. BindToDlls();
  123. }
  124. if (g_hDllSecur32) {
  125. return ((PVOID) GetProcAddress((HMODULE)g_hDllSecur32, function));
  126. }
  127. return NULL;
  128. }
  129. //
  130. // Definition for DsGetDcName
  131. //
  132. typedef DWORD (*PF_DsGetDcName) (
  133. IN LPCWSTR ComputerName OPTIONAL,
  134. IN LPCWSTR DomainName OPTIONAL,
  135. IN GUID *DomainGuid OPTIONAL,
  136. IN LPCWSTR SiteName OPTIONAL,
  137. IN ULONG Flags,
  138. OUT PDOMAIN_CONTROLLER_INFO *DomainControllerInfo
  139. );
  140. //
  141. // Definition for LsaConnectUntrusted()
  142. //
  143. typedef DWORD (*PF_LsaConnectUntrusted) (
  144. OUT PHANDLE LsaHandle
  145. );
  146. //
  147. // For LsaCallAuthenticationPackage
  148. //
  149. typedef DWORD (*PF_LsaCallAuthenticationPackage) (
  150. IN HANDLE LsaHandle,
  151. IN ULONG AuthenticationPackage,
  152. IN PVOID ProtocolSubmitBuffer,
  153. IN ULONG SubmitBufferLength,
  154. OUT PVOID *ProtocolReturnBuffer,
  155. OUT PULONG ReturnBufferLength,
  156. OUT PNTSTATUS ProtocolStatus
  157. );
  158. //
  159. // For LsaDeregisterLogonProcess
  160. //
  161. typedef DWORD (*PF_LsaDeregisterLogonProcess) (
  162. IN HANDLE LsaHandle
  163. );
  164. //
  165. // For LsaFreeReturnBuffer
  166. //
  167. typedef DWORD (*PF_LsaFreeReturnBuffer) (
  168. IN PVOID Buffer
  169. );
  170. #ifdef UNICODE
  171. #define GETDCNAME_API "DsGetDcNameW"
  172. #else
  173. #define GETDCNAME_API "DsGetDcNameA"
  174. #endif
  175. //
  176. // These are same for all entry points
  177. //
  178. #define LSACONNECT_UNTRUSTED "LsaConnectUntrusted"
  179. #define LSACALL_AUTH_PACAKAGE "LsaCallAuthenticationPackage"
  180. #define LSA_DEREG_LOGON_PROC "LsaDeregisterLogonProcess"
  181. #define LSAFREE_RET_BUFFER "LsaFreeReturnBuffer"
  182. //
  183. // We will always dynamically laod the dsgetdc api so that
  184. // we can have single binary for NT4.0 and NT5.0
  185. //
  186. DWORD
  187. DsGetDcNameWrapper(
  188. IN LPCWSTR ComputerName OPTIONAL,
  189. IN LPCWSTR DomainName OPTIONAL,
  190. IN GUID *DomainGuid OPTIONAL,
  191. IN LPCWSTR SiteName OPTIONAL,
  192. IN ULONG Flags,
  193. OUT PDOMAIN_CONTROLLER_INFO *DomainControllerInfo
  194. )
  195. {
  196. static PF_DsGetDcName pfDsGetDcName = NULL ;
  197. static BOOL f_LoadAttempted = FALSE;
  198. //
  199. // Load the function if necessary and only once.
  200. //
  201. if (pfDsGetDcName == NULL && !f_LoadAttempted) {
  202. pfDsGetDcName =
  203. (PF_DsGetDcName) LoadNetApi32Function(GETDCNAME_API) ;
  204. f_LoadAttempted = TRUE;
  205. }
  206. if (pfDsGetDcName != NULL) {
  207. return ((*pfDsGetDcName)(
  208. ComputerName,
  209. DomainName,
  210. DomainGuid,
  211. SiteName,
  212. Flags,
  213. DomainControllerInfo
  214. )
  215. );
  216. } else {
  217. //
  218. // Could not load library
  219. //
  220. return (ERROR_GEN_FAILURE);
  221. }
  222. }
  223. //
  224. // Wrapper function for LsaConnectUntrusted.
  225. //
  226. DWORD
  227. LsaConnectUntrustedWrapper(
  228. OUT PHANDLE LsaHandle
  229. )
  230. {
  231. static PF_LsaConnectUntrusted pfLsaConnectUntrusted = NULL ;
  232. static BOOL f_LoadAttempted = FALSE;
  233. //
  234. // Load the function if necessary and only once.
  235. //
  236. if (pfLsaConnectUntrusted == NULL && !f_LoadAttempted) {
  237. pfLsaConnectUntrusted =
  238. (PF_LsaConnectUntrusted) LoadSecur32Function(LSACONNECT_UNTRUSTED);
  239. f_LoadAttempted = TRUE;
  240. }
  241. if (pfLsaConnectUntrusted != NULL) {
  242. return ((*pfLsaConnectUntrusted)(
  243. LsaHandle
  244. )
  245. );
  246. }
  247. else {
  248. //
  249. // Could not load library
  250. //
  251. return (ERROR_GEN_FAILURE);
  252. }
  253. }
  254. //
  255. // Wrapper function for LsaCallAuthenticationPackage.
  256. //
  257. DWORD
  258. LsaCallAuthenticationPackageWrapper(
  259. IN HANDLE LsaHandle,
  260. IN ULONG AuthenticationPackage,
  261. IN PVOID ProtocolSubmitBuffer,
  262. IN ULONG SubmitBufferLength,
  263. OUT PVOID *ProtocolReturnBuffer,
  264. OUT PULONG ReturnBufferLength,
  265. OUT PNTSTATUS ProtocolStatus
  266. )
  267. {
  268. static PF_LsaCallAuthenticationPackage pfLsaCallAuthPackage = NULL;
  269. static BOOL f_LoadAttempted = FALSE;
  270. //
  271. // Load the function if necessary and only once.
  272. //
  273. if (pfLsaCallAuthPackage == NULL && !f_LoadAttempted) {
  274. pfLsaCallAuthPackage =
  275. (PF_LsaCallAuthenticationPackage) LoadSecur32Function(
  276. LSACALL_AUTH_PACAKAGE
  277. );
  278. f_LoadAttempted = TRUE;
  279. }
  280. if (pfLsaCallAuthPackage != NULL) {
  281. return ((*pfLsaCallAuthPackage)(
  282. LsaHandle,
  283. AuthenticationPackage,
  284. ProtocolSubmitBuffer,
  285. SubmitBufferLength,
  286. ProtocolReturnBuffer,
  287. ReturnBufferLength,
  288. ProtocolStatus
  289. )
  290. );
  291. }
  292. else {
  293. //
  294. // Could not load library
  295. //
  296. return (ERROR_GEN_FAILURE);
  297. }
  298. }
  299. //
  300. // Wrapper function for LsaDeregisterLogonProcess.
  301. //
  302. DWORD
  303. LsaDeregisterLogonProcessWrapper(
  304. IN HANDLE LsaHandle
  305. )
  306. {
  307. static PF_LsaDeregisterLogonProcess pfLsaDerefLgnProc = NULL;
  308. static BOOL f_LoadAttempted = FALSE;
  309. //
  310. // Load the function if necessary and only once.
  311. //
  312. if (pfLsaDerefLgnProc == NULL && !f_LoadAttempted) {
  313. pfLsaDerefLgnProc =
  314. (PF_LsaDeregisterLogonProcess) LoadSecur32Function(LSA_DEREG_LOGON_PROC);
  315. f_LoadAttempted = TRUE;
  316. }
  317. if (pfLsaDerefLgnProc != NULL) {
  318. return ((*pfLsaDerefLgnProc)(
  319. LsaHandle
  320. )
  321. );
  322. }
  323. else {
  324. //
  325. // Could not load library
  326. //
  327. return (ERROR_GEN_FAILURE);
  328. }
  329. }
  330. //
  331. // Wrapper function for LsaFreeReturnBuffer.
  332. //
  333. DWORD
  334. LsaFreeReturnBufferWrapper(
  335. IN PVOID Buffer
  336. )
  337. {
  338. static PF_LsaFreeReturnBuffer pfLsaFreeRetBuffer = NULL;
  339. static BOOL f_LoadAttempted = FALSE;
  340. //
  341. // Load the function if necessary and only once.
  342. //
  343. if (pfLsaFreeRetBuffer == NULL && !f_LoadAttempted) {
  344. pfLsaFreeRetBuffer =
  345. (PF_LsaFreeReturnBuffer) LoadSecur32Function(LSAFREE_RET_BUFFER);
  346. f_LoadAttempted = TRUE;
  347. }
  348. if (pfLsaFreeRetBuffer != NULL) {
  349. return ((*pfLsaFreeRetBuffer)(
  350. Buffer
  351. )
  352. );
  353. }
  354. else {
  355. //
  356. // Could not load library
  357. //
  358. return (ERROR_GEN_FAILURE);
  359. }
  360. }
  361. HANDLE g_hLsa = INVALID_HANDLE_VALUE;
  362. DWORD
  363. GetUserDomainFlatName(
  364. LPWSTR pszUserName,
  365. LPWSTR pszDomainFlatName
  366. )
  367. {
  368. NTSTATUS dwStatus = NO_ERROR, dwSubStatus = NO_ERROR;
  369. CHAR pszDomainFlatNameA[MAX_PATH];
  370. CHAR pszUserNameA[MAX_PATH];
  371. PWKSTA_USER_INFO_1 pNetWkstaUserInfo = NULL;
  372. PWKSTA_USER_INFO_1A pNetWkstaUserInfoA = NULL;
  373. PWKSTA_INFO_100 pNetWkstaInfo = NULL;
  374. NEGOTIATE_CALLER_NAME_REQUEST Req;
  375. PNEGOTIATE_CALLER_NAME_RESPONSE pResp = NULL;
  376. DWORD dwSize = 0;
  377. LPWSTR pszTempUserName = NULL;
  378. PLSA_UNICODE_STRING pLsaStrUserNameTemp = NULL;
  379. PLSA_UNICODE_STRING pLsaStrDomainNameTemp = NULL;
  380. #if (defined WIN95)
  381. dwStatus = NetWkstaUserGetInfoA(
  382. NULL,
  383. 1,
  384. (LPBYTE *)&pNetWkstaUserInfoA
  385. );
  386. if (dwStatus != NO_ERROR && dwStatus != ERROR_NO_SUCH_LOGON_SESSION) {
  387. goto error;
  388. }
  389. if (dwStatus == NO_ERROR) {
  390. AnsiToUnicodeString(
  391. pNetWkstaUserInfoA->wkui1_logon_domain,
  392. pszDomainFlatName,
  393. 0
  394. );
  395. AnsiToUnicodeString(
  396. pNetWkstaUserInfoA->wkui1_username,
  397. pszUserName,
  398. 0
  399. );
  400. }
  401. #else
  402. ENTER_DOMAINDNS_CRITSECT();
  403. if (g_hLsa == INVALID_HANDLE_VALUE) {
  404. dwStatus = LsaConnectUntrustedWrapper(&g_hLsa);
  405. }
  406. LEAVE_DOMAINDNS_CRITSECT();
  407. if (dwStatus == 0) {
  408. memset(&Req, 0, sizeof(Req));
  409. Req.MessageType = NegGetCallerName;
  410. dwStatus = LsaCallAuthenticationPackageWrapper(
  411. g_hLsa,
  412. 0,
  413. &Req,
  414. sizeof(Req),
  415. (void **)&pResp,
  416. &dwSize,
  417. &dwSubStatus
  418. );
  419. if ((dwStatus == 0)
  420. && (dwSubStatus == 0)) {
  421. dwStatus = NO_ERROR;
  422. pszTempUserName = wcschr(pResp->CallerName, L'\\');
  423. if (!pszTempUserName) {
  424. //
  425. // Looks like there was no domain default to machine then
  426. //
  427. dwStatus = ERROR_NO_SUCH_LOGON_SESSION;
  428. }
  429. else {
  430. //
  431. // Copy over the relevant information
  432. //
  433. *pszTempUserName = L'\0';
  434. wcscpy(pszDomainFlatName, pResp->CallerName);
  435. *pszTempUserName = L'\\';
  436. pszTempUserName++;
  437. wcscpy(pszUserName, pszTempUserName);
  438. LsaFreeReturnBufferWrapper(pResp);
  439. }
  440. }
  441. else {
  442. if (!dwStatus)
  443. dwStatus = dwSubStatus;
  444. }
  445. }
  446. if (dwStatus != NO_ERROR) {
  447. //
  448. // Call LsaGetUserName when there is a failure with the above.
  449. //
  450. dwStatus = LsaGetUserName(
  451. &pLsaStrUserNameTemp,
  452. &pLsaStrDomainNameTemp
  453. );
  454. if (dwStatus == NO_ERROR) {
  455. //
  456. // Unicode string may not be NULL terminated.
  457. //
  458. memcpy(
  459. pszDomainFlatName,
  460. pLsaStrDomainNameTemp->Buffer,
  461. pLsaStrDomainNameTemp->Length
  462. );
  463. pszDomainFlatName[pLsaStrDomainNameTemp->Length / sizeof(WCHAR)]
  464. = L'\0';
  465. memcpy(
  466. pszUserName,
  467. pLsaStrUserNameTemp->Buffer,
  468. pLsaStrUserNameTemp->Length
  469. );
  470. pszUserName[pLsaStrUserNameTemp->Length / sizeof(WCHAR)] = L'\0';
  471. //
  472. // Can cleanup the LsaGetUserName mem
  473. //
  474. LsaFreeMemory(pLsaStrUserNameTemp->Buffer);
  475. LsaFreeMemory(pLsaStrUserNameTemp);
  476. LsaFreeMemory(pLsaStrDomainNameTemp->Buffer);
  477. LsaFreeMemory(pLsaStrDomainNameTemp);
  478. }
  479. else if (dwStatus != ERROR_NO_SUCH_LOGON_SESSION){
  480. goto error;
  481. }
  482. }
  483. //
  484. // Make sure this is not NT AUTHORITY
  485. //
  486. if (dwStatus == NO_ERROR
  487. && !_wcsicmp(g_szNT_Authority, pszDomainFlatName)
  488. )
  489. {
  490. //
  491. // Force fallback to NetWkstaGetInfo as we want machine domain
  492. //
  493. dwStatus = ERROR_NO_SUCH_LOGON_SESSION;
  494. }
  495. if (dwStatus == NO_ERROR) {
  496. //
  497. // Do nothing here, we need the else clause already have data.
  498. //
  499. }
  500. #endif
  501. else {
  502. dwStatus = NetWkstaGetInfo(
  503. NULL,
  504. 100,
  505. (LPBYTE *)&pNetWkstaInfo
  506. );
  507. if (dwStatus) {
  508. goto error;
  509. }
  510. wcscpy(pszDomainFlatName, pNetWkstaInfo->wki100_langroup);
  511. }
  512. error:
  513. if (pNetWkstaUserInfoA) {
  514. NetApiBufferFree(pNetWkstaUserInfoA);
  515. }
  516. if (pNetWkstaUserInfo) {
  517. NetApiBufferFree(pNetWkstaUserInfo);
  518. }
  519. if (pNetWkstaInfo) {
  520. NetApiBufferFree(pNetWkstaInfo);
  521. }
  522. return(dwStatus);
  523. }
  524. DWORD
  525. GetDomainDNSNameForDomain(
  526. LPWSTR pszDomainFlatName,
  527. BOOL fVerify,
  528. BOOL fWriteable,
  529. LPWSTR pszServerName,
  530. LPWSTR pszDomainDNSName
  531. )
  532. {
  533. PDOMAIN_CONTROLLER_INFO pDomainControllerInfo = NULL;
  534. DWORD dwStatus = 0;
  535. DWORD Flags = DS_DIRECTORY_SERVICE_REQUIRED | DS_RETURN_DNS_NAME;
  536. if (fVerify)
  537. Flags |= DS_FORCE_REDISCOVERY ;
  538. if (fWriteable)
  539. Flags |= DS_WRITABLE_REQUIRED ;
  540. dwStatus = DsGetDcNameWrapper(
  541. NULL,
  542. pszDomainFlatName,
  543. NULL,
  544. NULL,
  545. Flags,
  546. &pDomainControllerInfo
  547. ) ;
  548. if (dwStatus == NO_ERROR) {
  549. wcscpy(pszServerName,pDomainControllerInfo->DomainControllerName+2);
  550. wcscpy(pszDomainDNSName,pDomainControllerInfo->DomainName);
  551. (void) NetApiBufferFree(pDomainControllerInfo) ;
  552. }
  553. return(dwStatus);
  554. }
  555. typedef struct _domaindnslist {
  556. LPWSTR pszUserName;
  557. LPWSTR pszUserDomainName;
  558. LPWSTR pszDomainDns;
  559. LPWSTR pszServer;
  560. struct _domaindnslist *pNext;
  561. } DOMAINDNSLIST, *PDOMAINDNSLIST;
  562. PDOMAINDNSLIST gpDomainDnsList = NULL;
  563. BOOL
  564. EquivalentDomains(
  565. PDOMAINDNSLIST pTemp,
  566. LPWSTR pszUserDomainName
  567. );
  568. DWORD
  569. GetDefaultDomainName(
  570. LPWSTR szDomainDnsName,
  571. LPWSTR szServerName,
  572. BOOL fWriteable,
  573. BOOL fVerify
  574. )
  575. {
  576. DWORD dwStatus = 0;
  577. WCHAR szUserDomainName[MAX_PATH];
  578. WCHAR szUserName[MAX_PATH];
  579. PDOMAINDNSLIST pTemp = NULL;
  580. PDOMAINDNSLIST pNewNode = NULL;
  581. dwStatus = GetUserDomainFlatName(
  582. szUserName,
  583. szUserDomainName
  584. );
  585. if (dwStatus) {
  586. goto error;
  587. }
  588. // We want do a DsGetDc if the fVerify flags is specified
  589. // so we do not want to look at our list if that is the case.
  590. if (!fVerify) {
  591. ENTER_DOMAINDNS_CRITSECT();
  592. pTemp = gpDomainDnsList;
  593. while (pTemp) {
  594. if (EquivalentDomains(pTemp, szUserDomainName)){
  595. wcscpy(szDomainDnsName,pTemp->pszDomainDns);
  596. wcscpy(szServerName,pTemp->pszServer);
  597. LEAVE_DOMAINDNS_CRITSECT();
  598. return(NO_ERROR);
  599. }
  600. pTemp = pTemp->pNext;
  601. }
  602. LEAVE_DOMAINDNS_CRITSECT();
  603. }
  604. // We will hit this block if either fVerify == TRUE or if
  605. // we did not find a match in our list above.
  606. dwStatus = GetDomainDNSNameForDomain(
  607. szUserDomainName,
  608. fVerify,
  609. fWriteable,
  610. szServerName,
  611. szDomainDnsName
  612. );
  613. if (dwStatus) {
  614. goto error;
  615. }
  616. ENTER_DOMAINDNS_CRITSECT();
  617. pTemp = gpDomainDnsList;
  618. while (pTemp) {
  619. if (EquivalentDomains(pTemp, szUserDomainName)) {
  620. //
  621. // Found a match -looks like someone has come in before us
  622. //
  623. wcscpy(szDomainDnsName, pTemp->pszDomainDns);
  624. wcscpy(szServerName,pTemp->pszServer);
  625. LEAVE_DOMAINDNS_CRITSECT();
  626. return(NO_ERROR);
  627. }
  628. pTemp = pTemp->pNext;
  629. }
  630. pNewNode = (PDOMAINDNSLIST)AllocADsMem(sizeof(DOMAINDNSLIST));
  631. if (!pNewNode) {
  632. LEAVE_DOMAINDNS_CRITSECT();
  633. return(dwStatus = (DWORD) E_OUTOFMEMORY);
  634. }
  635. pNewNode->pNext = gpDomainDnsList;
  636. pNewNode->pszUserName = AllocADsStr(szUserName);
  637. pNewNode->pszUserDomainName = AllocADsStr(szUserDomainName);
  638. pNewNode->pszDomainDns = AllocADsStr(szDomainDnsName);
  639. pNewNode->pszServer = AllocADsStr(szServerName);
  640. gpDomainDnsList = pNewNode;
  641. LEAVE_DOMAINDNS_CRITSECT();
  642. error:
  643. return(dwStatus);
  644. }
  645. DWORD
  646. GetGCDomainName(
  647. LPWSTR pszDomainDNSName,
  648. LPWSTR pszServerName
  649. )
  650. {
  651. PDOMAIN_CONTROLLER_INFO pDomainControllerInfo = NULL;
  652. DWORD dwStatus = 0;
  653. DWORD Flags = DS_GC_SERVER_REQUIRED | DS_RETURN_DNS_NAME;
  654. /*
  655. Flags |= DS_FORCE_REDISCOVERY ;
  656. Flags |= DS_WRITABLE_REQUIRED ;
  657. */
  658. dwStatus = DsGetDcNameWrapper(
  659. NULL,
  660. NULL,
  661. NULL,
  662. NULL,
  663. Flags,
  664. &pDomainControllerInfo
  665. ) ;
  666. if (dwStatus == NO_ERROR) {
  667. wcscpy(pszServerName,pDomainControllerInfo->DomainControllerName+2);
  668. wcscpy(pszDomainDNSName,pDomainControllerInfo->DnsForestName);
  669. (void) NetApiBufferFree(pDomainControllerInfo) ;
  670. }
  671. return(dwStatus);
  672. }
  673. DWORD
  674. GetDefaultServer(
  675. DWORD dwPort,
  676. BOOL fVerify,
  677. LPWSTR szDomainDnsName,
  678. LPWSTR szServerName,
  679. BOOL fWriteable
  680. )
  681. {
  682. LPWSTR pszAddresses[5];
  683. DWORD dwStatus = NO_ERROR;
  684. if (dwPort == USE_DEFAULT_GC_PORT) {
  685. dwStatus = GetGCDomainName(
  686. szDomainDnsName,
  687. szServerName);
  688. }
  689. else {
  690. dwStatus = GetDefaultDomainName(
  691. szDomainDnsName,
  692. szServerName,
  693. fWriteable,
  694. fVerify
  695. );
  696. }
  697. return(dwStatus);
  698. }
  699. //
  700. // Helper to see if we can use the cache for an domain DNS name
  701. // given a domain flat name.
  702. //
  703. BOOL
  704. EquivalentDomains(
  705. PDOMAINDNSLIST pTemp,
  706. LPWSTR pszUserDomainName
  707. )
  708. {
  709. if (!pszUserDomainName || !*pszUserDomainName) {
  710. return(FALSE);
  711. }
  712. #ifdef WIN95
  713. if (!_wcsicmp(pszUserDomainName, pTemp->pszUserDomainName)) {
  714. #else
  715. if (CompareStringW(
  716. LOCALE_SYSTEM_DEFAULT,
  717. NORM_IGNORECASE,
  718. pszUserDomainName,
  719. -1,
  720. pTemp->pszUserDomainName,
  721. -1
  722. ) == CSTR_EQUAL ) {
  723. #endif
  724. return(TRUE);
  725. }
  726. return(FALSE);
  727. }