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.

844 lines
22 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. setutl.c
  5. Abstract:
  6. Miscellaneous helper functions
  7. Author:
  8. Mac McLain (MacM) Feb 10, 1997
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include <setpch.h>
  14. #include <dssetp.h>
  15. #include <lsarpc.h>
  16. #include <samrpc.h>
  17. #include <samisrv.h>
  18. #include <db.h>
  19. #include <confname.h>
  20. #include <loadfn.h>
  21. #include <ntdsa.h>
  22. #include <dsconfig.h>
  23. #include <attids.h>
  24. #include <dsp.h>
  25. #include <lsaisrv.h>
  26. #include <malloc.h>
  27. #include <dsgetdc.h>
  28. #include <lmcons.h>
  29. #include <lmaccess.h>
  30. #include <lmapibuf.h>
  31. #include <lmerr.h>
  32. #include <netsetp.h>
  33. #include <winsock2.h>
  34. #include <nspapi.h>
  35. #include <dsgetdcp.h>
  36. #include <lmremutl.h>
  37. #include <spmgr.h> // For SetupPhase definition
  38. #include <Sddl.h>
  39. #include "secure.h"
  40. #include "lsa.h"
  41. DWORD
  42. DsRolepSetLsaInformationForReplica(
  43. IN HANDLE CallerToken,
  44. IN LPWSTR ReplicaPartner,
  45. IN LPWSTR Account,
  46. IN LPWSTR Password
  47. )
  48. /*++
  49. Routine Description:
  50. This function will set the local Lsa database information to that of the replica partner
  51. Arguments:
  52. ReplicaPartner -- Replica partner to get the information from
  53. Returns:
  54. ERROR_SUCCESS - Success
  55. --*/
  56. {
  57. DWORD Win32Err = ERROR_SUCCESS;
  58. NTSTATUS Status;
  59. UNICODE_STRING PartnerServer;
  60. HANDLE LocalPolicy = NULL , PartnerPolicy = NULL;
  61. OBJECT_ATTRIBUTES ObjectAttributes;
  62. PBYTE Buffer;
  63. ULONG i;
  64. BOOLEAN UseAdded = FALSE;
  65. PWSTR FullServerPath = NULL;
  66. POLICY_INFORMATION_CLASS InfoClasses[ ] = {
  67. PolicyDnsDomainInformation
  68. };
  69. if ( !ReplicaPartner ) {
  70. return( ERROR_INVALID_PARAMETER );
  71. }
  72. DSROLEP_CURRENT_OP1( DSROLEEVT_SET_LSA_FROM, ReplicaPartner );
  73. //
  74. // Open both lsas
  75. //
  76. RtlInitUnicodeString( &PartnerServer, ReplicaPartner );
  77. RtlZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
  78. Status = ImpLsaOpenPolicy( CallerToken,
  79. &PartnerServer,
  80. &ObjectAttributes,
  81. MAXIMUM_ALLOWED,
  82. &PartnerPolicy
  83. );
  84. if ( Status == STATUS_ACCESS_DENIED ) {
  85. WCHAR *BufPartnerServer = NULL;
  86. BufPartnerServer = (WCHAR*)malloc(PartnerServer.Length+sizeof(WCHAR));
  87. if (BufPartnerServer) {
  88. CopyMemory(BufPartnerServer,PartnerServer.Buffer,PartnerServer.Length);
  89. BufPartnerServer[PartnerServer.Length/sizeof(WCHAR)] = L'\0';
  90. DsRolepLogPrint(( DEB_TRACE,
  91. "LsaOpenPolicy on %ws failed with 0x%lx. Establishing use.\n",
  92. BufPartnerServer, Status ));
  93. free(BufPartnerServer);
  94. }
  95. //
  96. // Try establishing a session first...
  97. //
  98. if ( *ReplicaPartner != L'\\' ) {
  99. FullServerPath = RtlAllocateHeap( RtlProcessHeap(), 0,
  100. ( wcslen( ReplicaPartner ) + 3 ) * sizeof( WCHAR ) );
  101. if ( FullServerPath == NULL ) {
  102. Status = STATUS_INSUFFICIENT_RESOURCES;
  103. } else {
  104. swprintf( FullServerPath, L"\\\\%ws", ReplicaPartner );
  105. Status = STATUS_SUCCESS;
  106. }
  107. } else {
  108. FullServerPath = ReplicaPartner;
  109. Status = STATUS_SUCCESS;
  110. }
  111. if ( NT_SUCCESS( Status ) ) {
  112. Win32Err = ImpNetpManageIPCConnect( CallerToken,
  113. FullServerPath,
  114. Account,
  115. Password,
  116. NETSETUPP_CONNECT_IPC );
  117. if ( Win32Err == ERROR_SUCCESS ) {
  118. UseAdded = TRUE;
  119. Status = ImpLsaOpenPolicy( CallerToken,
  120. &PartnerServer,
  121. &ObjectAttributes,
  122. MAXIMUM_ALLOWED,
  123. &PartnerPolicy );
  124. } else {
  125. DsRolepLogPrint(( DEB_TRACE,
  126. "NetUseAdd to %ws failed with %lu\n",
  127. FullServerPath, Win32Err ));
  128. //
  129. // Temp status code so we know a failure occurred.
  130. //
  131. Status = STATUS_UNSUCCESSFUL;
  132. }
  133. }
  134. } else if ( !NT_SUCCESS( Status ) ) {
  135. WCHAR *BufPartnerServer = NULL;
  136. BufPartnerServer = (WCHAR*)malloc(PartnerServer.Length+sizeof(WCHAR));
  137. if (BufPartnerServer) {
  138. CopyMemory(BufPartnerServer,PartnerServer.Buffer,PartnerServer.Length);
  139. BufPartnerServer[PartnerServer.Length/sizeof(WCHAR)] = L'\0';
  140. DsRolepLogPrint(( DEB_TRACE,
  141. "LsaOpenPolicy on %ws failed with 0x%lx.\n",
  142. BufPartnerServer, Status ));
  143. free(BufPartnerServer);
  144. }
  145. }
  146. if ( NT_SUCCESS( Status ) ) {
  147. RtlZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
  148. Status = LsaOpenPolicy( NULL,
  149. &ObjectAttributes,
  150. MAXIMUM_ALLOWED,
  151. &LocalPolicy );
  152. if ( !NT_SUCCESS( Status ) ) {
  153. DsRolepLogPrint(( DEB_TRACE,
  154. "Local LsaOpenPoolicy returned 0x%lx\n",
  155. Status ));
  156. }
  157. }
  158. for ( i = 0;
  159. i < sizeof( InfoClasses ) / sizeof( POLICY_INFORMATION_CLASS ) && NT_SUCCESS( Status );
  160. i++ ) {
  161. Status = ImpLsaQueryInformationPolicy( CallerToken,
  162. PartnerPolicy,
  163. InfoClasses[ i ],
  164. &Buffer );
  165. if ( NT_SUCCESS( Status ) ) {
  166. Status = LsaSetInformationPolicy( LocalPolicy,
  167. InfoClasses[ i ],
  168. Buffer );
  169. LsaFreeMemory( Buffer );
  170. }
  171. DsRolepLogPrint(( DEB_TRACE,
  172. "Setting Lsa policy %lu returned 0x%lx\n",
  173. InfoClasses[ i ], Status ));
  174. }
  175. //
  176. // Now, the same for the Efs policy
  177. //
  178. if ( NT_SUCCESS( Status ) ) {
  179. Status = ImpLsaQueryDomainInformationPolicy( CallerToken,
  180. PartnerPolicy,
  181. PolicyDomainEfsInformation,
  182. &Buffer );
  183. if ( NT_SUCCESS( Status ) ) {
  184. Status = LsaSetDomainInformationPolicy( LocalPolicy,
  185. PolicyDomainEfsInformation,
  186. Buffer );
  187. DsRolepLogPrint(( DEB_TRACE,
  188. "Setting Efs policy from %ws returned 0x%lx\n",
  189. ReplicaPartner, Status ));
  190. LsaFreeMemory( Buffer );
  191. } else {
  192. DsRolepLogPrint(( DEB_TRACE,
  193. "Reading Efs policy from %ws returned 0x%lx\n",
  194. ReplicaPartner, Status ));
  195. if ( Status == STATUS_OBJECT_NAME_NOT_FOUND ) {
  196. Status = STATUS_SUCCESS;
  197. }
  198. }
  199. }
  200. if ( LocalPolicy ) {
  201. LsaClose( LocalPolicy );
  202. }
  203. if ( PartnerPolicy ) {
  204. ImpLsaClose( CallerToken, PartnerPolicy );
  205. }
  206. if ( UseAdded ) {
  207. Win32Err = ImpNetpManageIPCConnect( CallerToken,
  208. FullServerPath,
  209. Account,
  210. Password,
  211. (NETSETUPP_DISCONNECT_IPC|NETSETUPP_USE_LOTS_FORCE) );
  212. }
  213. if ( FullServerPath && FullServerPath != ReplicaPartner ) {
  214. RtlFreeHeap( RtlProcessHeap(), 0, FullServerPath );
  215. }
  216. //
  217. // We won't bother cleaning up any of the information we set on the local machine in
  218. // the failure case, since it won't hurt anything to have it here.
  219. //
  220. if ( Win32Err == ERROR_SUCCESS ) {
  221. Win32Err = RtlNtStatusToDosError( Status );
  222. }
  223. DsRoleDebugOut(( DEB_TRACE_DS, "DsRolepSetLsaInformationForReplica %lu\n", Win32Err ));
  224. DsRolepLogOnFailure( Win32Err,
  225. DsRolepLogPrint(( DEB_TRACE,
  226. "DsRolepSetLsaInformationForReplica failed with %lu\n",
  227. Win32Err )) );
  228. return( Win32Err );
  229. }
  230. DWORD
  231. DsRolepSetLsaDomainPolicyInfo(
  232. IN LPWSTR DnsDomainName,
  233. IN LPWSTR FlatDomainName,
  234. IN LPWSTR EnterpriseDnsName,
  235. IN GUID *DomainGuid,
  236. IN PSID DomainSid,
  237. DWORD InstallOptions,
  238. OUT PDSROLEP_DOMAIN_POLICY_INFO BackupDomainInfo
  239. )
  240. /*++
  241. Routine Description:
  242. This routine sets the PolicyAccountDomainInformation and
  243. PolicyDnsDomainInformation in the lsa to reflect the
  244. recent role changes.
  245. Arguments:
  246. DnsDomainName - The Dns domain name of the newly installed Domain/Dc
  247. FlatDomainName - The NetBIOS domain name of the newly installed Domain/Dc
  248. EnterpriseDnsName - The Dns domain name of the root of the enterprise
  249. DomainGuid - The new domain guid
  250. DomainSid - The new domain sid
  251. InstallOptions : this describes the kind of install (new domain, enterprise,
  252. or replica)
  253. DomainGuid - The guid of the new domain is returned here
  254. Returns:
  255. ERROR_SUCCESS - Success; win error otherwise
  256. --*/
  257. {
  258. NTSTATUS Status;
  259. OBJECT_ATTRIBUTES ObjectAttributes;
  260. POLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo;
  261. POLICY_LSA_SERVER_ROLE_INFO ServerRoleInfo;
  262. POLICY_DNS_DOMAIN_INFO DnsDomainInfo;
  263. LSA_HANDLE PolicyHandle = NULL;
  264. //
  265. // If we are setting up the replica, we don't have things like the flat domain name and
  266. // the domain sid, so we'll use the information we have backed up.
  267. //
  268. if ( FlatDomainName == NULL || DomainSid == NULL ) {
  269. RtlCopyMemory( &AccountDomainInfo.DomainName,
  270. &BackupDomainInfo->DnsDomainInfo->Name,
  271. sizeof( UNICODE_STRING ) );
  272. AccountDomainInfo.DomainSid = BackupDomainInfo->DnsDomainInfo->Sid ;
  273. } else {
  274. RtlInitUnicodeString( &AccountDomainInfo.DomainName,
  275. FlatDomainName);
  276. AccountDomainInfo.DomainSid = DomainSid;
  277. }
  278. //
  279. // Open the Lsa
  280. //
  281. RtlZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
  282. Status = LsaOpenPolicy( NULL,
  283. &ObjectAttributes,
  284. POLICY_WRITE,
  285. &PolicyHandle );
  286. //
  287. // Set the AccountDomain information first
  288. //
  289. if ( NT_SUCCESS( Status ) ) {
  290. //
  291. // Set the values in the Account Domain Policy structure.
  292. //
  293. WCHAR *BufDomainName = NULL;
  294. DsRolepLogPrint(( DEB_TRACE, "Setting AccountDomainInfo to:\n" ));
  295. BufDomainName = (WCHAR*)malloc(AccountDomainInfo.DomainName.Length+sizeof(WCHAR));
  296. if (BufDomainName) {
  297. CopyMemory(BufDomainName,AccountDomainInfo.DomainName.Buffer,AccountDomainInfo.DomainName.Length);
  298. BufDomainName[AccountDomainInfo.DomainName.Length/sizeof(WCHAR)] = L'\0';
  299. DsRolepLogPrint(( DEB_TRACE,
  300. "\tDomain: %ws\n",
  301. BufDomainName, Status ));
  302. free(BufDomainName);
  303. }
  304. DsRolepLogSid( DEB_TRACE, "\tSid: ", AccountDomainInfo.DomainSid );
  305. Status = LsaSetInformationPolicy( PolicyHandle,
  306. PolicyAccountDomainInformation,
  307. ( PVOID )&AccountDomainInfo );
  308. DsRolepLogOnFailure( RtlNtStatusToDosError( Status ),
  309. DsRolepLogPrint(( DEB_TRACE,
  310. "Setting AccountDomainInformation failed with 0x%lx\n",
  311. RtlNtStatusToDosError( Status ) )) );
  312. }
  313. //
  314. // Set the Dns domain information
  315. //
  316. if ( NT_SUCCESS( Status ) && !FLAG_ON( InstallOptions, NTDS_INSTALL_REPLICA ) ) {
  317. RtlInitUnicodeString( &DnsDomainInfo.Name, FlatDomainName );
  318. RtlInitUnicodeString( &DnsDomainInfo.DnsDomainName, DnsDomainName );
  319. RtlInitUnicodeString( &DnsDomainInfo.DnsForestName, EnterpriseDnsName );
  320. RtlCopyMemory( &DnsDomainInfo.DomainGuid, DomainGuid, sizeof( GUID ) );
  321. DnsDomainInfo.Sid = DomainSid;
  322. Status = LsaSetInformationPolicy( PolicyHandle,
  323. PolicyDnsDomainInformation,
  324. ( PVOID )&DnsDomainInfo );
  325. DsRolepLogOnFailure( RtlNtStatusToDosError( Status ),
  326. DsRolepLogPrint(( DEB_TRACE,
  327. "Setting DnsDomainInformation failed with 0x%lx\n",
  328. RtlNtStatusToDosError( Status ) )) );
  329. }
  330. //
  331. // If it isn't a replica, wipe the efs policy
  332. //
  333. if ( NT_SUCCESS( Status ) && !FLAG_ON( InstallOptions, NTDS_INSTALL_REPLICA ) ) {
  334. Status = LsaSetDomainInformationPolicy( PolicyHandle,
  335. PolicyDomainEfsInformation,
  336. NULL );
  337. if ( Status == STATUS_OBJECT_NAME_NOT_FOUND ) {
  338. Status = STATUS_SUCCESS;
  339. }
  340. DsRolepLogOnFailure( RtlNtStatusToDosError( Status ),
  341. DsRolepLogPrint(( DEB_TRACE,
  342. "Erasing EfsPolicy failed with 0x%lx\n",
  343. Status )) );
  344. }
  345. //
  346. // Now, cleanup and exit
  347. //
  348. if ( PolicyHandle ) {
  349. LsaClose( PolicyHandle );
  350. }
  351. return( RtlNtStatusToDosError( Status ) );
  352. }
  353. DWORD
  354. DsRolepBackupDomainPolicyInfo(
  355. IN PLSA_HANDLE LsaHandle, OPTIONAL
  356. OUT PDSROLEP_DOMAIN_POLICY_INFO DomainInfo
  357. )
  358. /*++
  359. Routine Description
  360. This routine reads and saves in a global the state of the
  361. account domain policy and primary domain policy so if an error
  362. occurs then the original state can be preserved.
  363. Parameters
  364. DomainInfo : pointer, to be filled in by this routine
  365. Return Values
  366. ERROR_SUCCESS if no errors; a winerror otherwise
  367. --*/
  368. {
  369. NTSTATUS Status = STATUS_SUCCESS;
  370. LSA_HANDLE PolicyHandle = NULL;
  371. OBJECT_ATTRIBUTES ObjectAttributes;
  372. ASSERT(DomainInfo);
  373. if ( DomainInfo->PolicyBackedUp ) {
  374. return( STATUS_SUCCESS );
  375. }
  376. if ( LsaHandle == NULL ) {
  377. RtlZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
  378. Status = LsaOpenPolicy( NULL,
  379. &ObjectAttributes,
  380. POLICY_VIEW_LOCAL_INFORMATION,
  381. &PolicyHandle );
  382. } else {
  383. PolicyHandle = LsaHandle;
  384. }
  385. if ( NT_SUCCESS( Status ) ) {
  386. Status = LsaQueryInformationPolicy(
  387. PolicyHandle,
  388. PolicyDnsDomainInformation,
  389. ( PVOID * )&DomainInfo->DnsDomainInfo);
  390. }
  391. if ( NT_SUCCESS( Status ) ) {
  392. Status = LsaQueryInformationPolicy(
  393. PolicyHandle,
  394. PolicyAccountDomainInformation,
  395. ( PVOID * )&DomainInfo->AccountDomainInfo);
  396. }
  397. if ( NT_SUCCESS( Status ) ) {
  398. Status = LsaQueryInformationPolicy(
  399. PolicyHandle,
  400. PolicyLsaServerRoleInformation,
  401. ( PVOID * )&DomainInfo->ServerRoleInfo);
  402. }
  403. if ( NT_SUCCESS( Status ) ) {
  404. Status = LsaQueryDomainInformationPolicy(
  405. PolicyHandle,
  406. PolicyDomainEfsInformation,
  407. ( PVOID * )&DomainInfo->EfsPolicy );
  408. if ( NT_SUCCESS( Status ) ) {
  409. DomainInfo->EfsPolicyPresent = TRUE;
  410. } else {
  411. //
  412. // It's ok for the Efs policy not to have existed
  413. //
  414. if ( Status == STATUS_OBJECT_NAME_NOT_FOUND ) {
  415. DomainInfo->EfsPolicyPresent = TRUE;
  416. Status = STATUS_SUCCESS;
  417. } else {
  418. DomainInfo->EfsPolicyPresent = FALSE;
  419. }
  420. }
  421. }
  422. if ( PolicyHandle && PolicyHandle != LsaHandle ) {
  423. LsaClose( PolicyHandle );
  424. }
  425. if ( NT_SUCCESS( Status ) ) {
  426. DomainInfo->PolicyBackedUp = TRUE;
  427. }
  428. return( RtlNtStatusToDosError( Status ) );
  429. }
  430. DWORD
  431. DsRolepRestoreDomainPolicyInfo(
  432. IN PDSROLEP_DOMAIN_POLICY_INFO DomainInfo
  433. )
  434. /*++
  435. Routine Description
  436. This routine sets the account and primary domain information to be
  437. the values that were stored of by DsRolepBackupDomainPolicyInformation.
  438. Parameters
  439. DomainInfo : pointer, expected to be filled
  440. Return Values
  441. ERROR_SUCCESS if no errors; a winerror otherwise
  442. ERROR_INVALID_DATA - The data was never successfully backed up
  443. --*/
  444. {
  445. NTSTATUS Status, Status2;
  446. HANDLE PolicyHandle;
  447. OBJECT_ATTRIBUTES ObjectAttributes;
  448. ASSERT(DomainInfo);
  449. if ( !DomainInfo->PolicyBackedUp ) {
  450. return( ERROR_INVALID_DATA );
  451. }
  452. RtlZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
  453. Status = LsaOpenPolicy( NULL,
  454. &ObjectAttributes,
  455. POLICY_WRITE,
  456. &PolicyHandle );
  457. if ( NT_SUCCESS( Status ) ) {
  458. Status = LsaSetInformationPolicy( PolicyHandle,
  459. PolicyDnsDomainInformation,
  460. ( PVOID )DomainInfo->DnsDomainInfo );
  461. Status2 = LsaSetInformationPolicy( PolicyHandle,
  462. PolicyAccountDomainInformation,
  463. ( PVOID )DomainInfo->AccountDomainInfo );
  464. if ( NT_SUCCESS( Status ) && !NT_SUCCESS( Status2 ) ) {
  465. Status = Status2;
  466. }
  467. //
  468. // Restore the Efs policy, if it exists
  469. //
  470. if ( NT_SUCCESS( Status ) && DomainInfo->EfsPolicyPresent ) {
  471. Status = LsaSetDomainInformationPolicy( PolicyHandle,
  472. PolicyDomainEfsInformation,
  473. ( PVOID )DomainInfo->EfsPolicy );
  474. }
  475. Status2 = LsaClose( PolicyHandle );
  476. if ( NT_SUCCESS( Status ) ) {
  477. Status = Status2;
  478. }
  479. }
  480. DsRolepLogOnFailure( Status,
  481. DsRolepLogPrint(( DEB_TRACE,
  482. "RestoreDomainPolicyInfo failed with 0x%lx\n",
  483. Status )) );
  484. return( RtlNtStatusToDosError( Status ) );
  485. }
  486. DWORD
  487. DsRolepFreeDomainPolicyInfo(
  488. IN PDSROLEP_DOMAIN_POLICY_INFO DomainInfo
  489. )
  490. /*++
  491. Routine Description
  492. This routine free the structures that were allocated during
  493. DsRolepBackupDomainPolicyInformation.
  494. Parameters
  495. DomainInfo : pointer, expected to be filled so the fields can be freed
  496. Return Values
  497. ERROR_SUCCESS if no errors; a winerror otherwise
  498. --*/
  499. {
  500. if ( DomainInfo->AccountDomainInfo ) {
  501. LsaFreeMemory( DomainInfo->AccountDomainInfo );
  502. }
  503. if ( DomainInfo->DnsDomainInfo ) {
  504. LsaFreeMemory( DomainInfo->DnsDomainInfo );
  505. }
  506. if ( DomainInfo->ServerRoleInfo ) {
  507. LsaFreeMemory( DomainInfo->ServerRoleInfo );
  508. }
  509. if ( DomainInfo->EfsPolicyPresent ) {
  510. LsaFreeMemory( DomainInfo->EfsPolicy );
  511. }
  512. return ERROR_SUCCESS;
  513. }
  514. DWORD
  515. DsRolepUpgradeLsaToDs(
  516. BOOLEAN InitializeLsa
  517. )
  518. /*++
  519. Routine Description:
  520. Prompts Lsa to upgrade all the information it stores in the registry into the Ds
  521. Arguments:
  522. None
  523. Returns:
  524. ERROR_SUCCESS - Success
  525. ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
  526. --*/
  527. {
  528. NTSTATUS Status = STATUS_SUCCESS;
  529. DWORD WinError = ERROR_SUCCESS;
  530. if ( InitializeLsa ) {
  531. //
  532. // Make the Lsa think that we're initialized
  533. //
  534. DSROLEP_CURRENT_OP0( DSROLEEVT_SET_LSA );
  535. //
  536. // Make the Lsa think that we're initialized
  537. //
  538. Status = LsapDsInitializeDsStateInfo( LsapDsDsSetup );
  539. if ( !NT_SUCCESS( Status ) ) {
  540. DsRolepLogPrint(( DEB_TRACE,
  541. "Failed to convince Lsa to reinitialize: 0x%lx\n",
  542. Status ));
  543. } else {
  544. Status = LsaIUpgradeRegistryToDs( FALSE );
  545. }
  546. }
  547. return( WinError == ERROR_SUCCESS ? RtlNtStatusToDosError( Status ) : WinError );
  548. }
  549. VOID
  550. DsRolepFindSelfAndParentInForest(
  551. IN PLSAPR_FOREST_TRUST_INFO ForestTrustInfo,
  552. OUT PLSAPR_TREE_TRUST_INFO CurrentEntry,
  553. IN PUNICODE_STRING LocalDomain,
  554. OUT PLSAPR_TREE_TRUST_INFO *ParentEntry,
  555. OUT PLSAPR_TREE_TRUST_INFO *OwnEntry
  556. )
  557. {
  558. DWORD WinError = ERROR_SUCCESS;
  559. ULONG i;
  560. BOOLEAN ParentKnown = FALSE;
  561. if ( *ParentEntry && *OwnEntry ) {
  562. return;
  563. }
  564. if ( ForestTrustInfo->ParentDomainReference ) {
  565. CurrentEntry = ForestTrustInfo->ParentDomainReference;
  566. ParentKnown = TRUE;
  567. }
  568. for ( i = 0; i < CurrentEntry->Children && *OwnEntry == NULL; i++ ) {
  569. if ( RtlCompareUnicodeString(
  570. ( PUNICODE_STRING )&CurrentEntry->ChildDomains[ i ].DnsDomainName,
  571. LocalDomain,
  572. TRUE ) == 0 ) {
  573. *OwnEntry = &CurrentEntry->ChildDomains[ i ];
  574. *ParentEntry = CurrentEntry;
  575. break;
  576. }
  577. if ( !ParentKnown ) {
  578. DsRolepFindSelfAndParentInForest( ForestTrustInfo,
  579. &CurrentEntry->ChildDomains[ i ],
  580. LocalDomain,
  581. ParentEntry,
  582. OwnEntry );
  583. }
  584. }
  585. return;
  586. }