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.

768 lines
23 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Windows 2000 Active Directory Service domain trust verification WMI provider
  4. //
  5. // Microsoft Windows
  6. // Copyright (C) Microsoft Corporation, 1992 - 2000
  7. //
  8. // File: trust.cpp
  9. //
  10. // Contents: Trust class implementation
  11. //
  12. // Classes: CTrustInfo
  13. //
  14. // History: 27-Mar-00 EricB created
  15. //
  16. //-----------------------------------------------------------------------------
  17. #include <stdafx.h>
  18. PCWSTR CSTR_PROP_TRUSTED_DOMAIN = L"TrustedDomain"; // String
  19. PCWSTR CSTR_PROP_FLAT_NAME = L"FlatName"; // String
  20. PCWSTR CSTR_PROP_SID = L"SID"; // String
  21. PCWSTR CSTR_PROP_TRUST_DIRECTION = L"TrustDirection"; // uint32
  22. PCWSTR CSTR_PROP_TRUST_TYPE = L"TrustType"; // uint32
  23. PCWSTR CSTR_PROP_TRUST_ATTRIBUTES = L"TrustAttributes"; // uint32
  24. PCWSTR CSTR_PROP_TRUST_STATUS = L"TrustStatus"; // uint32
  25. PCWSTR CSTR_PROP_TRUST_STATUS_STRING = L"TrustStatusString"; // String
  26. PCWSTR CSTR_PROP_TRUST_IS_OK = L"TrustIsOk"; // Boolean
  27. PCWSTR CSTR_PROP_TRUSTED_DC_NAME = L"TrustedDCName"; // String
  28. // Define NETLOGON_CONTROL_TC_VERIFY if not found so this will build for W2K.
  29. // This constant is in the Whistler version of lmaccess.h
  30. #if !defined(NETLOGON_CONTROL_TC_VERIFY)
  31. # define NETLOGON_CONTROL_TC_VERIFY (10)
  32. #endif
  33. //+----------------------------------------------------------------------------
  34. //
  35. // Class: CTrustInfo
  36. //
  37. //-----------------------------------------------------------------------------
  38. CTrustInfo::CTrustInfo() : m_ulTrustDirection(0),
  39. m_ulTrustType(0),
  40. m_ulTrustAttributes(0),
  41. m_trustStatus(ERROR_SUCCESS),
  42. m_VerifyStatus(VerifyStatusNone),
  43. m_fPwVerifySupported(TRUE)
  44. {
  45. m_liLastVerified.QuadPart = 0;
  46. }
  47. //+----------------------------------------------------------------------------
  48. //
  49. // Method: CTrustInfo::Verify
  50. //
  51. // Synopsis: Verify the status of the trust
  52. //
  53. // Returns: FALSE if the trust was not outbound.
  54. //
  55. //-----------------------------------------------------------------------------
  56. BOOL
  57. CTrustInfo::Verify(TrustCheckLevel CheckLevel)
  58. {
  59. TRACE(L"CTrustInfo::Verify, verify level %d\n", CheckLevel);
  60. NET_API_STATUS netStatus = NERR_Success;
  61. NETLOGON_INFO_2 * pNetlogonInfo2 = NULL;
  62. VerifyStatus Status = VerifyStatusNone;
  63. PCWSTR pwzTrustedDomain = GetTrustedDomain();
  64. CString strDCName, strResetTarget = GetTrustedDomain();
  65. if (DONT_VERIFY == CheckLevel)
  66. {
  67. TRACE(L"\tCheck-Level set to not verify trust.\n");
  68. SetTrustStatus(NERR_Success, VerifyStatusTrustNotChecked);
  69. return TRUE;
  70. }
  71. TRACE(L"\tVerifying trust with %s\n", GetTrustedDomain());
  72. if ((TRUST_TYPE_MIT == GetTrustType()) ||
  73. (TRUST_TYPE_DCE == GetTrustType()))
  74. {
  75. // don't verify non-Windows trusts.
  76. //
  77. TRACE(L"\tNot a windows trust, returning.\n");
  78. SetTrustStatus(NERR_Success, VerifyStatusNotWindowsTrust);
  79. SetLastVerifiedTime();
  80. return TRUE;
  81. }
  82. if (!IsTrustOutbound())
  83. {
  84. // don't verify inbound-only trusts.
  85. //
  86. TRACE(L"\tInbound-only trust, returning.\n");
  87. SetTrustStatus(NERR_Success, VerifyStatusNotOutboundTrust);
  88. SetLastVerifiedTime();
  89. return FALSE;
  90. }
  91. //
  92. // NETLOGON_CONTROL_TC_QUERY - get the status (locally) and the name of trusted DC
  93. // Note that the secure channel is set up only on demand, so it is not an error if
  94. // it is not set up. The SC_QUERY will return ERROR_NO_LOGON_SERVERS if this is the
  95. // case.
  96. //
  97. netStatus = I_NetLogonControl2(NULL,
  98. NETLOGON_CONTROL_TC_QUERY,
  99. 2,
  100. (LPBYTE)&pwzTrustedDomain,
  101. (LPBYTE *)&pNetlogonInfo2);
  102. if (NERR_Success == netStatus)
  103. {
  104. ASSERT(pNetlogonInfo2);
  105. netStatus = pNetlogonInfo2->netlog2_tc_connection_status;
  106. if (netStatus == NERR_Success)
  107. {
  108. SetTrustedDCName(pNetlogonInfo2->netlog2_trusted_dc_name);
  109. strDCName = pNetlogonInfo2->netlog2_trusted_dc_name;
  110. #if !defined(NT4_BUILD)
  111. //
  112. // Compose the domain\dc string for the reset command so it will not change
  113. // DCs as a result of the reset. This only works with NT5 or later NetLogon.
  114. //
  115. strResetTarget += L"\\";
  116. strResetTarget += pNetlogonInfo2->netlog2_trusted_dc_name + 2; // skip the UNC double slashes
  117. #endif
  118. }
  119. else
  120. {
  121. if (ERROR_NO_LOGON_SERVERS == netStatus)
  122. {
  123. // This is the error returned when the SC has not yet been set up.
  124. // It is also returned if no DCs are reachable. DsGetDcName is called with the
  125. // force flag to discover if any DCs are reachable on the net.
  126. //
  127. PDOMAIN_CONTROLLER_INFO pDCInfo = NULL;
  128. DWORD dwRet = NO_ERROR;
  129. #if !defined(NT4_BUILD)
  130. dwRet = DsGetDcName(NULL, pwzTrustedDomain, NULL, NULL, DS_FORCE_REDISCOVERY, &pDCInfo);
  131. #endif
  132. if (NO_ERROR == dwRet)
  133. {
  134. // A DC is reachable, so it is safe to assume that the SC has not yet been
  135. // set up. Treat this as success.
  136. //
  137. netStatus = NERR_Success;
  138. TRACE(L"SC_QUERY has returned ERROR_NO_LOGON_SERVERS, SC not yet set up.\n");
  139. #if !defined(NT4_BUILD)
  140. SetTrustedDCName(pDCInfo->DomainControllerName);
  141. NetApiBufferFree(pDCInfo);
  142. #endif
  143. }
  144. else
  145. {
  146. // If there are no DCs, there is nothing to be done except return the error.
  147. //
  148. TRACE(L"DsGetDcName /FORCE has returned %d, DC not found.\n", dwRet);
  149. // Save the error code and fixed by method
  150. SetTrustStatus(dwRet, VerifyStatusBroken);
  151. SetLastVerifiedTime();
  152. return TRUE;
  153. }
  154. }
  155. else
  156. {
  157. TRACE(L"SC_QUERY has returned %d.\n", netStatus);
  158. }
  159. }
  160. NetApiBufferFree(pNetlogonInfo2);
  161. }
  162. else
  163. {
  164. TRACE(L"I_NetLogonControl2 has returned %d.\n", netStatus);
  165. }
  166. //
  167. // Do a trust PW verification if the other domain supports it.
  168. //
  169. if (PW_VERIFY == CheckLevel)
  170. {
  171. if (m_fPwVerifySupported)
  172. {
  173. netStatus = I_NetLogonControl2(NULL,
  174. NETLOGON_CONTROL_TC_VERIFY,
  175. 2,
  176. (LPBYTE)&pwzTrustedDomain,
  177. (LPBYTE *)&pNetlogonInfo2);
  178. if (NERR_Success == netStatus)
  179. {
  180. ASSERT(pNetlogonInfo2);
  181. netStatus = pNetlogonInfo2->netlog2_tc_connection_status;
  182. NetApiBufferFree(pNetlogonInfo2);
  183. }
  184. if (NERR_Success == netStatus)
  185. {
  186. TRACE(L"PW Verify successful on %s\n", pwzTrustedDomain);
  187. Status = VerifyStatusTrustOK;
  188. }
  189. else
  190. {
  191. if (ERROR_INVALID_LEVEL == netStatus ||
  192. ERROR_NOT_SUPPORTED == netStatus ||
  193. RPC_S_PROCNUM_OUT_OF_RANGE == netStatus ||
  194. RPC_NT_PROCNUM_OUT_OF_RANGE == netStatus)
  195. {
  196. TRACE(L"NETLOGON_CONTROL_TC_VERIFY is not supported on %s\n", pwzTrustedDomain);
  197. m_fPwVerifySupported = FALSE;
  198. Status = VerifyStatusPwCheckNotSupported;
  199. netStatus = NERR_Success; // call it success since we don't know the true state
  200. }
  201. else
  202. {
  203. TRACE(L"NETLOGON_CONTROL_TC_VERIFY returned 0x%08x on %s\n", netStatus, pwzTrustedDomain);
  204. Status = VerifyStatusBroken;
  205. }
  206. }
  207. }
  208. else
  209. {
  210. Status = VerifyStatusPwCheckNotSupported;
  211. }
  212. }
  213. //
  214. // Try an SC Reset against the DC returned by the SC query
  215. //
  216. if (SC_RESET == CheckLevel)
  217. {
  218. PCWSTR pwzResetTarget = strResetTarget;
  219. netStatus = I_NetLogonControl2(NULL,
  220. NETLOGON_CONTROL_REDISCOVER,
  221. 2,
  222. (LPBYTE)&pwzResetTarget,
  223. (LPBYTE *)&pNetlogonInfo2);
  224. if (NERR_Success == netStatus)
  225. {
  226. ASSERT(pNetlogonInfo2);
  227. netStatus = pNetlogonInfo2->netlog2_tc_connection_status;
  228. NetApiBufferFree(pNetlogonInfo2);
  229. }
  230. if (NERR_Success == netStatus)
  231. {
  232. TRACE(L"SC_RESET successfull on %s\n", pwzResetTarget);
  233. Status = VerifyStatusRediscover;
  234. }
  235. else
  236. {
  237. TRACE(L"SC_RESET returned 0x%08x on %s\n", netStatus, pwzResetTarget);
  238. }
  239. }
  240. #ifdef NT4_BUILD
  241. //
  242. // Force trust pw replication from PDC to BDCs; only works on pre-W2K.
  243. //
  244. if (netStatus != NERR_Success)
  245. {
  246. // perform only once, ignore the result
  247. ForceReplication();
  248. }
  249. #endif
  250. //
  251. // If still in an error state, do an SC reset against any DC
  252. //
  253. if (netStatus != NERR_Success)
  254. {
  255. netStatus = ForceRediscover(NULL, &strDCName);
  256. if (NERR_Success == netStatus)
  257. {
  258. Status = VerifyStatusRediscover;
  259. SetTrustedDCName(const_cast<PWSTR>((PCWSTR)strDCName));
  260. }
  261. }
  262. //
  263. // Walk through the DCs trying to establish an SC: TRCHK_RETARGET_ON_ERROR
  264. //
  265. if (NERR_Success != netStatus)
  266. {
  267. vector<LPWSTR> dcList;
  268. LPBYTE pbuf = NULL;
  269. TRACE(L"Attempting to retarget...\n");
  270. //
  271. // Enumerate all DCs in the trusted domain
  272. // Attempt reconnecting to another DC.
  273. //
  274. // The returned value is not recorded.
  275. // (if not enumerated, skip this step)
  276. //
  277. if( NERR_Success == GetDCList(strDCName,
  278. dcList,
  279. &pbuf))
  280. {
  281. //
  282. // Try to connect to every DC until success
  283. //
  284. for (vector<LPWSTR>::iterator ppszDCName = dcList.begin();
  285. NERR_Success != netStatus && ppszDCName != dcList.end();
  286. ppszDCName++)
  287. {
  288. netStatus = ForceRediscover(*ppszDCName, &strDCName);
  289. }
  290. }
  291. if (NERR_Success == netStatus)
  292. {
  293. SetTrustedDCName(const_cast<PWSTR>((PCWSTR)strDCName));
  294. Status = VerifyStatusRetarget;
  295. }
  296. //
  297. // Clean up the DC list
  298. //
  299. if (pbuf)
  300. {
  301. VERIFY( NERR_Success == NetApiBufferFree(pbuf));
  302. }
  303. }
  304. // Save the error code and Status
  305. SetTrustStatus(netStatus, Status);
  306. SetLastVerifiedTime();
  307. return TRUE;
  308. }
  309. //+----------------------------------------------------------------------------
  310. //
  311. // Method: CTrustInfo::SetLastVerifiedTime
  312. //
  313. // Synopsis: Record the time of verification.
  314. //
  315. //-----------------------------------------------------------------------------
  316. void
  317. CTrustInfo::SetLastVerifiedTime(void)
  318. {
  319. SYSTEMTIME st;
  320. GetSystemTime(&st);
  321. SystemTimeToFileTime(&st, (LPFILETIME)&m_liLastVerified);
  322. }
  323. //+----------------------------------------------------------------------------
  324. //
  325. // Method: CTrustInfo::IsVerificationStale
  326. //
  327. // Synopsis: Checks to see if the last verification time is older than the
  328. // passed in criteria.
  329. //
  330. // Returns: TRUE if older.
  331. //
  332. // Notes: If the trust hasn't been verified (m_liLastVerified == 0),
  333. // then the verification is defined to be stale.
  334. //
  335. //-----------------------------------------------------------------------------
  336. BOOL
  337. CTrustInfo::IsVerificationStale(LARGE_INTEGER liMaxAge)
  338. {
  339. TRACE(L"CTrustInfo::IsVerificationStale(0x%08x), MaxAge = %d\n",
  340. this, liMaxAge.QuadPart / TRUSTMON_FILETIMES_PER_MINUTE);
  341. BOOL fStale = FALSE;
  342. LARGE_INTEGER liCurrentTime;
  343. SYSTEMTIME st;
  344. GetSystemTime(&st);
  345. SystemTimeToFileTime(&st, (LPFILETIME)&liCurrentTime);
  346. //TRACE(L"\tlast: %I64d, cur: %I64d, max: %I64d\n", m_liLastVerified, liCurrentTime, liMaxAge);
  347. fStale = (m_liLastVerified.QuadPart + liMaxAge.QuadPart) < liCurrentTime.QuadPart;
  348. return fStale;
  349. }
  350. //+----------------------------------------------------------------------------
  351. //
  352. // Method: CTrustInfo::GetDCList
  353. //
  354. // Synopsis: Enumerate all DCs in a domain and return a list in random order.
  355. //
  356. //-----------------------------------------------------------------------------
  357. NET_API_STATUS
  358. CTrustInfo::GetDCList(PCWSTR pszKnownServer, // OPTIONAL The server name to be placed in the end of the list
  359. vector<LPWSTR> & dcList, // Vector of PCWSTRs, pointing to the DC names inside pbufptr
  360. LPBYTE * pbufptr ) // This buffer must be freed with NetApiBufferFree when done.
  361. {
  362. TRACE(L"CTrustInfo::GetDCList\n");
  363. ASSERT( pbufptr );
  364. ASSERT( !(*pbufptr) );
  365. NET_API_STATUS netStatus = NERR_Success;
  366. DWORD dwEntriesRead = 0;
  367. DWORD dwTotalEntries = 0;
  368. DWORD dwResumeHandle = 0;
  369. DWORD dwIndKnownServer = MAXDWORD;
  370. DWORD dwInd = 0;
  371. do
  372. {
  373. // Init
  374. dcList.clear();
  375. //
  376. // Enumerate all the servers belonging to the specified domain
  377. //
  378. netStatus = NetServerEnum( NULL,
  379. 100, // SERVER_INFO_100
  380. pbufptr,
  381. MAX_PREFERRED_LENGTH,
  382. & dwEntriesRead,
  383. & dwTotalEntries,
  384. SV_TYPE_DOMAIN_CTRL | SV_TYPE_DOMAIN_BAKCTRL,
  385. GetTrustedDomain(),
  386. & dwResumeHandle );
  387. TRACE(L"NetServerEnum returned 0x%08x! (%d entries)\n", netStatus, dwEntriesRead);
  388. if( netStatus == ERROR_MORE_DATA )
  389. {
  390. // should never happen (no enum handle)
  391. ASSERT( FALSE );
  392. // process whatever NetServerEnum returned.
  393. netStatus = NERR_Success;
  394. }
  395. if( netStatus != NERR_Success ||
  396. !dwEntriesRead ||
  397. !(*pbufptr) )
  398. {
  399. TRACE(L"Failure, exiting...\n");
  400. dcList.clear();
  401. if( *pbufptr )
  402. {
  403. VERIFY( NERR_Success == NetApiBufferFree( *pbufptr ) );
  404. *pbufptr = NULL;
  405. }
  406. break;
  407. }
  408. // To simplify buffer access...
  409. PSERVER_INFO_100 pServerInfo100 = PSERVER_INFO_100( *pbufptr );
  410. // Reserve enough space for all the entries
  411. dcList.reserve( dwEntriesRead );
  412. //
  413. // Create a list of Servers
  414. //
  415. for( dwInd = 0; dwInd < dwEntriesRead; dwInd++ )
  416. {
  417. if( pszKnownServer &&
  418. !_wcsicmp( pszKnownServer, pServerInfo100[dwInd].sv100_name ) )
  419. {
  420. dwIndKnownServer = dwInd; // postpone until the end
  421. }
  422. else
  423. {
  424. dcList.push_back( pServerInfo100[dwInd].sv100_name );
  425. }
  426. }
  427. ASSERT( dwEntriesRead );
  428. //
  429. // Known server should go to the end of the list
  430. //
  431. if( MAXDWORD != dwIndKnownServer )
  432. {
  433. TRACE(L"Server %s placed @ the end\n", pszKnownServer);
  434. dcList.push_back( pServerInfo100[dwIndKnownServer].sv100_name );
  435. // Shuffling should not include the last entry
  436. dwEntriesRead--;
  437. }
  438. //
  439. // Initialize randomizer
  440. //
  441. srand( (unsigned) time( NULL ) );
  442. //
  443. // Shuffle by replacing each entry with another random entry
  444. //
  445. for( dwInd = 0; dwInd < (int) dwEntriesRead; dwInd++ )
  446. {
  447. DWORD dwRandPos = DWORD( rand() % dwEntriesRead );
  448. if( dwRandPos == dwInd )
  449. continue;
  450. // Swap!
  451. LPWSTR pstrTemp = dcList[ dwRandPos ];
  452. dcList[ dwRandPos ] = dcList[ dwInd ];
  453. dcList[ dwInd ] = pstrTemp;
  454. }
  455. } while( FALSE );
  456. return netStatus;
  457. }
  458. //+----------------------------------------------------------------------------
  459. //
  460. // Method: CTrustInfo::ForceRediscover
  461. //
  462. // Synopsis:
  463. //
  464. //-----------------------------------------------------------------------------
  465. NET_API_STATUS
  466. CTrustInfo::ForceRediscover(PCWSTR pstrDCName, CString * pstrDCNameRet)
  467. {
  468. TRACE(L"CTrustInfo::ForceRediscover\n");
  469. NET_API_STATUS netStatus = NERR_Success;
  470. NETLOGON_INFO_2 * pNetlogonInfo2 = NULL;
  471. CString strTemp;
  472. PCWSTR pstrDomainName = GetTrustedDomain();
  473. if( pstrDCName )
  474. {
  475. //
  476. // Form domain\dc request
  477. //
  478. strTemp = pstrDomainName;
  479. strTemp += L"\\";
  480. strTemp += pstrDCName;
  481. // Retarget pstrDomainName to the new string
  482. pstrDomainName = strTemp;
  483. }
  484. //
  485. // Attempt to re-establish trust
  486. //
  487. netStatus = I_NetLogonControl2( NULL,
  488. NETLOGON_CONTROL_REDISCOVER,
  489. 2,
  490. ( LPBYTE ) &pstrDomainName,
  491. ( LPBYTE *) &pNetlogonInfo2 );
  492. TRACE(L"I_NetLogonControl2:NETLOGON_CONTROL_REDISCOVER to %s returned 0x%08x\n",
  493. pstrDomainName, netStatus);
  494. //
  495. // Clean-up
  496. //
  497. if( pNetlogonInfo2 )
  498. {
  499. *pstrDCNameRet = pNetlogonInfo2->netlog2_trusted_dc_name;
  500. TRACE(L"netlog2_flags=0x%08x, netlog2_pdc_connection_status=0x%08x\n",
  501. pNetlogonInfo2->netlog2_flags,
  502. pNetlogonInfo2->netlog2_pdc_connection_status);
  503. TRACE(L"netlog2_trusted_dc_name=%s, netlog2_tc_connection_status=0x%08x\n",
  504. pNetlogonInfo2->netlog2_trusted_dc_name,
  505. pNetlogonInfo2->netlog2_tc_connection_status);
  506. NetApiBufferFree( pNetlogonInfo2 );
  507. }
  508. return netStatus;
  509. }
  510. //+----------------------------------------------------------------------------
  511. //
  512. // Method: CTrustInfo::SetTrustStatus
  513. //
  514. // Synopsis: Set the status string based on the netStatus value if an error
  515. // else based on the VerifyStatus.
  516. //
  517. //-----------------------------------------------------------------------------
  518. void
  519. CTrustInfo::SetTrustStatus(ULONG netStatus, VerifyStatus Status)
  520. {
  521. WCHAR wzBuf[512];
  522. m_trustStatus = netStatus;
  523. m_VerifyStatus = Status;
  524. if (NERR_Success == netStatus)
  525. {
  526. int nStrID;
  527. switch (Status)
  528. {
  529. case VerifyStatusNone:
  530. //
  531. // This is the default value for the Status parameter.
  532. //
  533. case VerifyStatusTrustOK:
  534. nStrID = IDS_TRUST_STATUS_OK;
  535. break;
  536. case VerifyStatusNotWindowsTrust:
  537. nStrID = IDS_MIT_TRUST_STATUS;
  538. break;
  539. case VerifyStatusNotOutboundTrust:
  540. nStrID = IDS_STATUS_INBOUND_ONLY;
  541. break;
  542. case VerifyStatusTrustNotChecked:
  543. nStrID = IDS_STATUS_NOT_CHECKED;
  544. break;
  545. case VerifyStatusPwCheckNotSupported:
  546. nStrID = IDS_PW_VERIFY_NOT_SUPPORTED;
  547. break;
  548. case VerifyStatusRetarget:
  549. nStrID = IDS_FIXED_BY_RETARGET;
  550. break;
  551. case VerifyStatusRediscover:
  552. nStrID = IDS_STATUS_REDISCOVER;
  553. break;
  554. case VerifyStatusBroken:
  555. ASSERT(FALSE); // shouldn't get here, fall through.
  556. default:
  557. nStrID = IDS_STATUS_UNKNOWN;
  558. }
  559. LoadString(_Module.GetModuleInstance(), nStrID, wzBuf, 512);
  560. m_strTrustStatus = wzBuf;
  561. }
  562. else
  563. {
  564. PWSTR pwzMsg;
  565. if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  566. FORMAT_MESSAGE_FROM_SYSTEM |
  567. FORMAT_MESSAGE_IGNORE_INSERTS,
  568. NULL,
  569. netStatus,
  570. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  571. (PWSTR)&pwzMsg,
  572. 0,
  573. NULL))
  574. {
  575. PWSTR pwzSuffix = wcsstr(pwzMsg, L"\r\n");
  576. if (pwzSuffix)
  577. {
  578. *pwzSuffix = L'\0';
  579. }
  580. m_strTrustStatus = pwzMsg;
  581. LocalFree(pwzMsg);
  582. }
  583. else
  584. {
  585. LoadString(_Module.GetModuleInstance(), IDS_TRUST_STATUS_FAILED, wzBuf, 512);
  586. m_strTrustStatus = wzBuf;
  587. }
  588. }
  589. }
  590. //+----------------------------------------------------------------------------
  591. //
  592. // Method: CTrustInfo::SetTrustDirectionFromFlags
  593. //
  594. //-----------------------------------------------------------------------------
  595. void
  596. CTrustInfo::SetTrustDirectionFromFlags(ULONG ulFlags)
  597. {
  598. m_ulTrustDirection = 0;
  599. if (DS_DOMAIN_DIRECT_OUTBOUND & ulFlags)
  600. {
  601. m_ulTrustDirection = TRUST_DIRECTION_OUTBOUND;
  602. }
  603. if (DS_DOMAIN_DIRECT_INBOUND & ulFlags)
  604. {
  605. m_ulTrustDirection |= TRUST_DIRECTION_INBOUND;
  606. }
  607. }
  608. //+----------------------------------------------------------------------------
  609. //
  610. // Method: CTrustInfo::SetSid
  611. //
  612. //-----------------------------------------------------------------------------
  613. BOOL
  614. CTrustInfo::SetSid(PSID pSid)
  615. {
  616. if (!pSid)
  617. {
  618. return TRUE;
  619. }
  620. #if !defined(NT4_BUILD)
  621. PWSTR buffer;
  622. BOOL fRet = ConvertSidToStringSid(pSid, &buffer);
  623. if (fRet)
  624. {
  625. m_strSid = buffer;
  626. LocalFree(buffer);
  627. }
  628. return fRet;
  629. #else
  630. // TODO: Code for NT4 ??
  631. #pragma message("need ConvertSidToStringSid for NT4");
  632. #endif
  633. }
  634. #ifdef NT4_BUILD
  635. //+----------------------------------------------------------------------------
  636. //
  637. // Function: ForceReplication
  638. //
  639. // Synopsis: Force local Domain Replication -- works only for NT4 domains
  640. //
  641. //-----------------------------------------------------------------------------
  642. NET_API_STATUS ForceReplication(void)
  643. {
  644. TRACE(L"ForceReplication\n");
  645. NET_API_STATUS netStatus = NERR_Success;
  646. LPBYTE pbInputDataPtr = NULL;
  647. PNETLOGON_INFO_1 pNetlogonInfo1 = NULL;
  648. netStatus = I_NetLogonControl2( NULL,
  649. NETLOGON_CONTROL_REPLICATE,
  650. 1,
  651. (LPBYTE ) &pbInputDataPtr,
  652. (LPBYTE *) &pNetlogonInfo1 );
  653. TRACE(L"I_NetLogonControl2:NETLOGON_CONTROL_REPLICATE returned 0x%08x\n", netStatus);
  654. if( pNetlogonInfo1 )
  655. {
  656. TRACE(L"netlog1_flags=0x%08x, netlog1_pdc_connection_status=0x%08x\n",
  657. pNetlogonInfo1->netlog1_flags,
  658. pNetlogonInfo1->netlog1_pdc_connection_status);
  659. NetApiBufferFree( pNetlogonInfo1 );
  660. }
  661. return netStatus;
  662. }
  663. #endif //NT4_BUILD