Leaked source code of windows server 2003
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.

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