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.

989 lines
26 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 "secure.h"
  39. DWORD
  40. DsRolepInstallDs(
  41. IN LPWSTR DnsDomainName,
  42. IN LPWSTR FlatDomainName,
  43. IN LPWSTR DnsTreeRoot,
  44. IN LPWSTR SiteName,
  45. IN LPWSTR DsDatabasePath,
  46. IN LPWSTR DsLogPath,
  47. IN LPWSTR RestorePath,
  48. IN LPWSTR SysVolRootPath,
  49. IN PUNICODE_STRING Bootkey,
  50. IN LPWSTR AdminAccountPassword,
  51. IN LPWSTR ParentDnsName,
  52. IN LPWSTR Server OPTIONAL,
  53. IN LPWSTR Account OPTIONAL,
  54. IN LPWSTR Password OPTIONAL,
  55. IN LPWSTR SafeModePassword OPTIONAL,
  56. IN LPWSTR SourceDomain OPTIONAL,
  57. IN ULONG Options,
  58. IN BOOLEAN Replica,
  59. IN HANDLE ImpersonateToken,
  60. OUT LPWSTR *InstalledSite,
  61. IN OUT GUID *DomainGuid,
  62. OUT PSID *NewDomainSid
  63. )
  64. /*++
  65. Routine Description:
  66. Wrapper for the routine that does the actual install.
  67. Arguments:
  68. DnsDomainName - Dns domain name of the domain to install
  69. FlatDomainName - NetBIOS domain name of the domain to install
  70. SiteName - Name of the site this DC should belong to
  71. DsDatabasePath - Absolute path on the local machine where the Ds DIT should go
  72. DsLogPath - Absolute path on the local machine where the Ds log files should go
  73. RestorePath - Location of a restored database.
  74. EnterpriseSysVolPath -- Absolute path on the local machine for the enterprise wide
  75. system volume
  76. DomainSysVolPath -- Absolute path on the local machine for the domain wide system volume
  77. AdminAccountPassword -- Administrator password to set for the domain
  78. ParentDnsName - Optional. Parent domain name
  79. Server -- Optional. Replica partner or name of Dc in parent domain
  80. Account - User account to use when setting up as a child domain
  81. Password - Password to use with the above account
  82. Replica - If TRUE, treat this as a replica install
  83. ImpersonateToken - the token of caller of the role change API
  84. InstalledSite - Name of the site the Dc was installed into
  85. DomainGuid - Where the new domain guid is returned
  86. NewDomainSid - Where the new domain sid is returned.
  87. Returns:
  88. ERROR_SUCCESS - Success
  89. --*/
  90. {
  91. DWORD Win32Err = ERROR_SUCCESS;
  92. NTDS_INSTALL_INFO DsInstallInfo;
  93. PSEC_WINNT_AUTH_IDENTITY AuthIdent = NULL;
  94. BOOL fRewindServer = FALSE;
  95. RtlZeroMemory( &DsInstallInfo, sizeof( DsInstallInfo ) );
  96. if ( !Replica ) {
  97. if ( ParentDnsName == NULL ) {
  98. DsInstallInfo.Flags = NTDS_INSTALL_ENTERPRISE;
  99. } else {
  100. DsInstallInfo.Flags = NTDS_INSTALL_DOMAIN;
  101. }
  102. } else {
  103. DsInstallInfo.Flags = NTDS_INSTALL_REPLICA;
  104. }
  105. if ( FLAG_ON( Options, DSROLE_DC_ALLOW_DC_REINSTALL ) ) {
  106. DsInstallInfo.Flags |= NTDS_INSTALL_DC_REINSTALL;
  107. }
  108. if ( FLAG_ON( Options, DSROLE_DC_ALLOW_DOMAIN_REINSTALL ) ) {
  109. DsInstallInfo.Flags |= NTDS_INSTALL_DOMAIN_REINSTALL;
  110. }
  111. if ( FLAG_ON( Options, DSROLE_DC_DOWNLEVEL_UPGRADE ) ) {
  112. DsInstallInfo.Flags |= NTDS_INSTALL_UPGRADE;
  113. }
  114. if ( FLAG_ON( Options, DSROLE_DC_TRUST_AS_ROOT ) ) {
  115. DsInstallInfo.Flags |= NTDS_INSTALL_NEW_TREE;
  116. }
  117. if ( FLAG_ON( Options, DSROLE_DC_ALLOW_ANONYMOUS_ACCESS ) ) {
  118. DsInstallInfo.Flags |= NTDS_INSTALL_ALLOW_ANONYMOUS;
  119. }
  120. if ( FLAG_ON( Options, DSROLE_DC_DEFAULT_REPAIR_PWD ) ) {
  121. DsInstallInfo.Flags |= NTDS_INSTALL_DFLT_REPAIR_PWD;
  122. }
  123. if ( FLAG_ON( Options, DSROLE_DC_SET_FOREST_CURRENT ) ) {
  124. DsInstallInfo.Flags |= NTDS_INSTALL_SET_FOREST_CURRENT;
  125. }
  126. if ( Server
  127. && Server[0] == L'\\' ) {
  128. //
  129. // Don't pass in \\
  130. //
  131. Server += 2;
  132. fRewindServer = TRUE;
  133. }
  134. DsInstallInfo.DitPath = ( PWSTR )DsDatabasePath;
  135. DsInstallInfo.LogPath = ( PWSTR )DsLogPath;
  136. DsInstallInfo.SysVolPath = (PWSTR)SysVolRootPath;
  137. DsInstallInfo.RestorePath = ( PWSTR )RestorePath;
  138. DsInstallInfo.BootKey = Bootkey->Buffer;
  139. DsInstallInfo.cbBootKey = Bootkey->Length;
  140. DsInstallInfo.SiteName = ( PWSTR )SiteName;
  141. DsInstallInfo.DnsDomainName = ( PWSTR )DnsDomainName;
  142. DsInstallInfo.FlatDomainName = ( PWSTR )FlatDomainName;
  143. DsInstallInfo.DnsTreeRoot = ( PWSTR )DnsTreeRoot;
  144. DsInstallInfo.ReplServerName = ( PWSTR )Server;
  145. DsInstallInfo.pfnUpdateStatus = DsRolepStringUpdateCallback;
  146. DsInstallInfo.pfnOperationResultFlags = DsRolepOperationResultFlagsCallBack;
  147. DsInstallInfo.AdminPassword = AdminAccountPassword;
  148. DsInstallInfo.pfnErrorStatus = DsRolepStringErrorUpdateCallback;
  149. DsInstallInfo.ClientToken = ImpersonateToken;
  150. DsInstallInfo.SafeModePassword = SafeModePassword;
  151. DsInstallInfo.SourceDomainName = SourceDomain;
  152. DsInstallInfo.Options = Options;
  153. if (DsInstallInfo.RestorePath && *DsInstallInfo.RestorePath){
  154. WCHAR *RealDNSDomainName=NULL;
  155. ULONG state=0;
  156. Win32Err = DsRolepGetDatabaseFacts(DsInstallInfo.RestorePath,
  157. &RealDNSDomainName,
  158. &state);
  159. if(ERROR_SUCCESS != Win32Err) {
  160. DSROLEP_FAIL1( Win32Err,
  161. DSROLERES_PROMO_FAILED,
  162. L"the domain information could not be retrived from the backup.");
  163. MIDL_user_free(RealDNSDomainName);
  164. return ERROR_CURRENT_DOMAIN_NOT_ALLOWED;
  165. }
  166. if(FALSE == DnsNameCompare_W(RealDNSDomainName,DsInstallInfo.DnsDomainName)) {
  167. DSROLEP_FAIL2( ERROR_CURRENT_DOMAIN_NOT_ALLOWED,
  168. DSROLERES_WRONG_DOMAIN,
  169. DsInstallInfo.DnsDomainName,
  170. RealDNSDomainName );
  171. MIDL_user_free(RealDNSDomainName);
  172. return ERROR_CURRENT_DOMAIN_NOT_ALLOWED;
  173. }
  174. MIDL_user_free(RealDNSDomainName);
  175. }
  176. //
  177. // Build the cred structure
  178. //
  179. Win32Err = DsRolepCreateAuthIdentForCreds( Account, Password, &AuthIdent );
  180. if ( Win32Err == ERROR_SUCCESS ) {
  181. DsInstallInfo.Credentials = AuthIdent;
  182. if (!DsInstallInfo.RestorePath) {
  183. Win32Err = DsRolepCopyDsDitFiles( DsDatabasePath );
  184. }
  185. if ( Win32Err == ERROR_SUCCESS ) {
  186. DSROLEP_CURRENT_OP0( DSROLEEVT_INSTALL_DS );
  187. DsRolepLogPrint(( DEB_TRACE_DS, "Calling NtdsInstall for %ws\n", DnsDomainName ));
  188. DSROLE_GET_SETUP_FUNC( Win32Err, DsrNtdsInstall );
  189. if ( Win32Err == ERROR_SUCCESS ) {
  190. DsRolepSetAndClearLog();
  191. Win32Err = ( *DsrNtdsInstall )( &DsInstallInfo,
  192. InstalledSite,
  193. DomainGuid,
  194. NewDomainSid );
  195. DsRolepSetAndClearLog();
  196. DsRolepLogPrint(( DEB_TRACE_DS, "NtdsInstall for %ws returned %lu\n",
  197. DnsDomainName, Win32Err ));
  198. #if DBG
  199. if ( Win32Err != ERROR_SUCCESS ) {
  200. DsRolepLogPrint(( DEB_TRACE_DS, "NtdsInstall parameters:\n" ));
  201. DsRolepLogPrint(( DEB_TRACE_DS, "\tFlags: %lu\n", DsInstallInfo.Flags ));
  202. DsRolepLogPrint(( DEB_TRACE_DS, "\tDitPath: %ws\n", DsInstallInfo.DitPath ));
  203. DsRolepLogPrint(( DEB_TRACE_DS, "\tLogPath: %ws\n", DsInstallInfo.LogPath ));
  204. DsRolepLogPrint(( DEB_TRACE_DS, "\tSiteName: %ws\n", DsInstallInfo.SiteName ));
  205. DsRolepLogPrint(( DEB_TRACE_DS, "\tDnsDomainName: %ws\n",
  206. DsInstallInfo.DnsDomainName ));
  207. DsRolepLogPrint(( DEB_TRACE_DS, "\tFlatDomainName: %ws\n",
  208. DsInstallInfo.FlatDomainName ));
  209. DsRolepLogPrint(( DEB_TRACE_DS, "\tDnsTreeRoot: %ws\n",
  210. DsInstallInfo.DnsTreeRoot ? DsInstallInfo.DnsTreeRoot :
  211. L"(NULL)" ));
  212. DsRolepLogPrint(( DEB_TRACE_DS, "\tReplServerName: %ws\n",
  213. DsInstallInfo.ReplServerName ?
  214. DsInstallInfo.ReplServerName : L"(NULL)" ));
  215. DsRolepLogPrint(( DEB_TRACE_DS, "\tCredentials: %p\n",
  216. DsInstallInfo.Credentials ));
  217. DsRolepLogPrint(( DEB_TRACE_DS, "\tpfnUpdateStatus: %p\n",
  218. DsInstallInfo.pfnUpdateStatus ));
  219. DsRolepLogPrint(( DEB_TRACE_DS, "\tAdminPassword: %p\n",
  220. DsInstallInfo.AdminPassword ));
  221. }
  222. #endif
  223. }
  224. }
  225. DsRolepFreeAuthIdentForCreds( AuthIdent );
  226. }
  227. DsRolepLogPrint(( DEB_TRACE,
  228. "DsRolepInstallDs returned %lu\n",
  229. Win32Err ));
  230. if ( fRewindServer ) {
  231. Server -= 2;
  232. }
  233. return( Win32Err );
  234. }
  235. DWORD
  236. DsRolepStopDs(
  237. IN BOOLEAN DsInstalled
  238. )
  239. /*++
  240. Routine Description:
  241. "Uninitinalizes" the Lsa and stops the Ds
  242. Arguments:
  243. DsInstalled -- If TRUE, stop the Ds.
  244. Returns:
  245. ERROR_SUCCESS - Success
  246. --*/
  247. {
  248. DWORD Win32Err = ERROR_SUCCESS;
  249. if ( DsInstalled ) {
  250. NTSTATUS Status = LsapDsUnitializeDsStateInfo();
  251. if ( NT_SUCCESS( Status ) ) {
  252. DSROLE_GET_SETUP_FUNC( Win32Err, DsrNtdsInstallShutdown );
  253. if ( Win32Err == ERROR_SUCCESS ) {
  254. Win32Err = ( *DsrNtdsInstallShutdown )();
  255. if ( Win32Err != ERROR_SUCCESS ) {
  256. DsRoleDebugOut(( DEB_ERROR,
  257. "NtdsInstallShutdown failed with %lu\n", Win32Err ));
  258. }
  259. }
  260. } else {
  261. Win32Err = RtlNtStatusToDosError( Status );
  262. }
  263. }
  264. DsRolepLogOnFailure( Win32Err,
  265. DsRolepLogPrint(( DEB_TRACE,
  266. "DsRolepStopDs failed with %lu\n",
  267. Win32Err )) );
  268. return( Win32Err );
  269. }
  270. DWORD
  271. DsRolepDemoteDs(
  272. IN LPWSTR DnsDomainName,
  273. IN LPWSTR Account,
  274. IN LPWSTR Password,
  275. IN LPWSTR AdminPassword,
  276. IN LPWSTR SupportDc,
  277. IN LPWSTR SupportDomain,
  278. IN HANDLE ImpersonateToken,
  279. IN BOOLEAN LastDcInDomain
  280. )
  281. /*++
  282. Routine Description:
  283. Wrapper for the routine that does the actual demotion.
  284. Arguments:
  285. DnsDomainName - Dns domain name of the domain to demote
  286. Account - Account to use for the demotion
  287. Password - Password to use with the above account
  288. AdminPassword -- Administrator password to set for the domain
  289. SupportDc - Optional. Name of a Dc in a domain (current or parent) to
  290. clean up Ds information
  291. SupportDomain - Optional. Name of the domain (current or parent) to
  292. clean up Ds information
  293. ImpersonateToken - the token of caller of the role change API
  294. LastDcInDomain - If TRUE, this is the last Dc in the domain
  295. Returns:
  296. ERROR_SUCCESS - Success
  297. --*/
  298. {
  299. DWORD Win32Err = ERROR_SUCCESS;
  300. PSEC_WINNT_AUTH_IDENTITY AuthIdent = NULL;
  301. NTSTATUS Status;
  302. DSROLEP_CURRENT_OP0( DSROLEEVT_UNINSTALL_DS );
  303. DsRoleDebugOut(( DEB_TRACE_DS, "Calling NtdsDemote for %ws\n", DnsDomainName ));
  304. DSROLE_GET_SETUP_FUNC( Win32Err, DsrNtdsDemote );
  305. if ( Win32Err == ERROR_SUCCESS ) {
  306. DsRolepSetAndClearLog();
  307. //
  308. // Build the cred structure
  309. //
  310. Win32Err = DsRolepCreateAuthIdentForCreds( Account, Password, &AuthIdent );
  311. if ( Win32Err == ERROR_SUCCESS ) {
  312. Status = LsapDsUnitializeDsStateInfo();
  313. if ( !NT_SUCCESS( Status ) ) {
  314. Win32Err = RtlNtStatusToDosError( Status );
  315. }
  316. }
  317. if ( Win32Err == ERROR_SUCCESS ) {
  318. DsRolepLogPrint(( DEB_TRACE_DS, "Invoking NtdsDemote\n" ));
  319. Win32Err = ( *DsrNtdsDemote )( AuthIdent,
  320. AdminPassword,
  321. LastDcInDomain ? NTDS_LAST_DC_IN_DOMAIN : 0,
  322. SupportDc,
  323. ImpersonateToken,
  324. DsRolepStringUpdateCallback,
  325. DsRolepStringErrorUpdateCallback );
  326. if ( Win32Err != ERROR_SUCCESS ) {
  327. //
  328. // Switch the LSA back to using the DS
  329. //
  330. LsapDsInitializeDsStateInfo( LsapDsDs );
  331. }
  332. //
  333. // Free the allocated creditials structure
  334. //
  335. DsRolepFreeAuthIdentForCreds( AuthIdent );
  336. }
  337. DsRolepSetAndClearLog();
  338. DsRolepLogPrint(( DEB_TRACE_DS, "NtdsDemote returned %lu\n",
  339. Win32Err ));
  340. }
  341. DsRolepLogPrint(( DEB_TRACE,
  342. "DsRolepDemoteDs returned %lu\n",
  343. Win32Err ));
  344. DSROLEP_FAIL0( Win32Err, DSROLERES_DEMOTE_DS );
  345. return( Win32Err );
  346. }
  347. DWORD
  348. DsRolepUninstallDs(
  349. VOID
  350. )
  351. /*++
  352. Routine Description:
  353. Uninstalls the Ds.
  354. Arguments:
  355. VOID
  356. Returns:
  357. ERROR_SUCCESS - Success
  358. --*/
  359. {
  360. DWORD Win32Err = ERROR_SUCCESS;
  361. DSROLE_GET_SETUP_FUNC( Win32Err, DsrNtdsInstallUndo );
  362. if ( Win32Err == ERROR_SUCCESS ) {
  363. Win32Err = ( *DsrNtdsInstallUndo )( );
  364. }
  365. DsRoleDebugOut(( DEB_TRACE_DS, "NtdsUnInstall returned %lu\n", Win32Err ));
  366. return( Win32Err );
  367. }
  368. DWORD
  369. DsRolepDemoteFlagsToNtdsFlags(
  370. DWORD Flags
  371. )
  372. {
  373. DWORD fl = 0;
  374. fl |= ( FLAG_ON( Flags, DSROLE_DC_DONT_DELETE_DOMAIN ) ? NTDS_DONT_DELETE_DOMAIN : 0 );
  375. return fl;
  376. }
  377. DWORD
  378. DsRolepLoadHive(
  379. IN LPWSTR Hive,
  380. IN LPWSTR KeyName
  381. )
  382. /*++
  383. Routine Description:
  384. This function will load a hive into the registry
  385. Arguments:
  386. lpRestorePath - The location of the restored files.
  387. lpDNSDomainName - This parameter will recieve the name of the domain that this backup came
  388. from
  389. State - The return Values that report How the syskey is stored and If the back was likely
  390. taken form a GC or not.
  391. Return Values:
  392. ERROR_SUCCESS - Success
  393. --*/
  394. {
  395. DWORD Win32Err = ERROR_SUCCESS;
  396. Win32Err = RegLoadKeyW(
  397. HKEY_LOCAL_MACHINE,
  398. KeyName,
  399. Hive);
  400. if (Win32Err != ERROR_SUCCESS) {
  401. DsRolepLogPrint(( DEB_WARN, "Failed to load key %ws: %lu retrying\n",
  402. Hive,
  403. Win32Err ));
  404. RegUnLoadKeyW(
  405. HKEY_LOCAL_MACHINE,
  406. KeyName);
  407. Win32Err = RegLoadKeyW(
  408. HKEY_LOCAL_MACHINE,
  409. KeyName,
  410. Hive);
  411. if (Win32Err != ERROR_SUCCESS) {
  412. DsRolepLogPrint(( DEB_ERROR, "Failed to load key %ws: %lu\n",
  413. Hive,
  414. Win32Err ));
  415. goto cleanup;
  416. }
  417. }
  418. cleanup:
  419. return Win32Err;
  420. }
  421. DWORD
  422. WINAPI
  423. DsRolepGetDatabaseFacts(
  424. IN LPWSTR lpRestorePath,
  425. OUT LPWSTR *lpDNSDomainName,
  426. OUT PULONG State
  427. )
  428. /*++
  429. Routine Description:
  430. This function will give information about a restore database
  431. 1. the way the syskey is stored
  432. 2. the domain that the database came from
  433. 3. where the backup was taken from a GC or not
  434. Arguments:
  435. lpRestorePath - The location of the restored files.
  436. lpDNSDomainName - This parameter will recieve the name of the domain that this backup came
  437. from
  438. State - The return Values that report How the syskey is stored and If the back was likely
  439. taken form a GC or not.
  440. Return Values:
  441. ERROR_SUCCESS - Success
  442. --*/
  443. {
  444. WCHAR regsystemfilepath[MAX_PATH];
  445. WCHAR regsecurityfilepath[MAX_PATH];
  446. DWORD controlset=0;
  447. DWORD BootType=0;
  448. DWORD GCready=0;
  449. DWORD type=REG_DWORD;
  450. DWORD size=sizeof(DWORD);
  451. ULONG cbregsystemfilepath=MAX_PATH*2;
  452. HKEY LsaKey=NULL;
  453. HKEY phkOldlocation=NULL;
  454. HKEY OldSecurityKey=NULL;
  455. DWORD Win32Err=ERROR_SUCCESS;
  456. BOOLEAN fWasEnabled=FALSE;
  457. NTSTATUS Status=STATUS_SUCCESS;
  458. BOOL SystemKeyloaded=FALSE;
  459. BOOL SecurityKeyloaded=FALSE;
  460. Status = RtlAdjustPrivilege( SE_RESTORE_PRIVILEGE,
  461. TRUE, // Enable
  462. FALSE, // not client; process wide
  463. &fWasEnabled );
  464. ASSERT( NT_SUCCESS( Status ) );
  465. if(IsBadWritePtr(lpDNSDomainName,
  466. sizeof(LPWSTR*) )){
  467. Win32Err = ERROR_INVALID_PARAMETER;
  468. goto cleanup;
  469. }
  470. *State=0;
  471. //set up the location of the system registry file
  472. wcscpy(regsystemfilepath,lpRestorePath);
  473. wcscat(regsystemfilepath,L"\\registry\\system");
  474. //
  475. // Get the source path of the database and the log files from the old
  476. // registry
  477. //
  478. Win32Err = DsRolepLoadHive(regsystemfilepath,
  479. IFM_SYSTEM_KEY);
  480. if (ERROR_SUCCESS != Win32Err) {
  481. goto cleanup;
  482. }
  483. SystemKeyloaded = TRUE;
  484. //find the default controlset
  485. Win32Err = RegOpenKeyExW( HKEY_LOCAL_MACHINE,
  486. L"ifmSystem\\Select",
  487. 0,
  488. KEY_READ,
  489. & LsaKey );
  490. if (Win32Err != ERROR_SUCCESS)
  491. {
  492. DsRolepLogPrint(( DEB_ERROR, "Failed to open key: %lu\n",
  493. Win32Err ));
  494. goto cleanup;
  495. }
  496. Win32Err = RegQueryValueExW(
  497. LsaKey,
  498. L"Default",
  499. 0,
  500. &type,
  501. (PUCHAR) &controlset,
  502. &size
  503. );
  504. if (Win32Err != ERROR_SUCCESS)
  505. {
  506. DsRolepLogPrint(( DEB_ERROR, "Couldn't Discover proper controlset: %lu\n",
  507. Win32Err ));
  508. goto cleanup;
  509. }
  510. Win32Err = RegCloseKey(LsaKey);
  511. LsaKey=NULL;
  512. if (Win32Err != ERROR_SUCCESS) {
  513. DsRolepLogPrint(( DEB_ERROR, "RegCloseKey failed with %d\n",
  514. Win32Err ));
  515. goto cleanup;
  516. }
  517. //Find the boot type
  518. if (controlset == 1) {
  519. Win32Err = RegOpenKeyExW( HKEY_LOCAL_MACHINE,
  520. L"ifmSystem\\ControlSet001\\Control\\Lsa",
  521. 0,
  522. KEY_READ,
  523. & LsaKey );
  524. } else {
  525. Win32Err = RegOpenKeyExW( HKEY_LOCAL_MACHINE,
  526. L"ifmSystem\\ControlSet002\\Control\\Lsa",
  527. 0,
  528. KEY_READ,
  529. & LsaKey );
  530. }
  531. if (Win32Err != ERROR_SUCCESS)
  532. {
  533. DsRolepLogPrint(( DEB_ERROR, "Failed to open key: %lu\n",
  534. Win32Err ));
  535. goto cleanup;
  536. }
  537. Win32Err = RegQueryValueExW(
  538. LsaKey,
  539. L"SecureBoot",
  540. 0,
  541. &type,
  542. (PUCHAR) &BootType,
  543. &size
  544. );
  545. if (Win32Err != ERROR_SUCCESS)
  546. {
  547. DsRolepLogPrint(( DEB_ERROR, "Couldn't Discover proper controlset: %lu\n",
  548. Win32Err ));
  549. goto cleanup;
  550. }
  551. Win32Err = RegCloseKey(LsaKey);
  552. LsaKey=NULL;
  553. if (Win32Err != ERROR_SUCCESS) {
  554. DsRolepLogPrint(( DEB_ERROR, "RegCloseKey failed with %d\n",
  555. Win32Err ));
  556. goto cleanup;
  557. }
  558. //find if a GC or not
  559. if (controlset == 1) {
  560. Win32Err = RegOpenKeyExW(
  561. HKEY_LOCAL_MACHINE,
  562. L"ifmSystem\\ControlSet001\\Services\\NTDS\\Parameters",
  563. 0,
  564. KEY_READ,
  565. &phkOldlocation
  566. );
  567. } else {
  568. Win32Err = RegOpenKeyExW(
  569. HKEY_LOCAL_MACHINE,
  570. L"ifmSystem\\ControlSet002\\Services\\NTDS\\Parameters",
  571. 0,
  572. KEY_READ,
  573. &phkOldlocation
  574. );
  575. }
  576. if (Win32Err != ERROR_SUCCESS) {
  577. DsRolepLogPrint(( DEB_ERROR, "RegOpenKeyExW failed to discover the GC state of the database %d\n",
  578. Win32Err ));
  579. goto cleanup;
  580. }
  581. Win32Err = RegQueryValueEx(
  582. phkOldlocation,
  583. TEXT(GC_PROMOTION_COMPLETE),
  584. 0,
  585. &type,
  586. (VOID*)&GCready,
  587. &size
  588. );
  589. if (Win32Err != ERROR_SUCCESS && ERROR_FILE_NOT_FOUND != Win32Err) {
  590. DsRolepLogPrint(( DEB_ERROR, "RegQueryValueEx failed to discover the GC state of the database %d\n",
  591. Win32Err ));
  592. goto cleanup;
  593. }
  594. //
  595. // The System key is no longer needed unload it.
  596. //
  597. {
  598. DWORD tWin32Err = ERROR_SUCCESS;
  599. if ( phkOldlocation ) {
  600. tWin32Err = RegCloseKey(phkOldlocation);
  601. phkOldlocation = NULL;
  602. if ( tWin32Err != ERROR_SUCCESS ) {
  603. DsRolepLogPrint(( DEB_ERROR, "RegCloseKey failed with %d\n",
  604. tWin32Err ));
  605. }
  606. }
  607. if(SystemKeyloaded){
  608. tWin32Err = RegUnLoadKeyW(
  609. HKEY_LOCAL_MACHINE,
  610. IFM_SYSTEM_KEY);
  611. SystemKeyloaded = FALSE;
  612. if ( tWin32Err != ERROR_SUCCESS) {
  613. DsRolepLogPrint(( DEB_ERROR, "RegUnLoadKeyW failed to unload system key with %d\n",
  614. tWin32Err ));
  615. }
  616. }
  617. }
  618. //set up the location of the Security registry file
  619. wcscpy(regsecurityfilepath,lpRestorePath);
  620. wcscat(regsecurityfilepath,L"\\registry\\security");
  621. Win32Err = DsRolepLoadHive(regsecurityfilepath,
  622. IFM_SECURITY_KEY);
  623. if (ERROR_SUCCESS != Win32Err) {
  624. goto cleanup;
  625. }
  626. SecurityKeyloaded = TRUE;
  627. //open the security key to pass to LsapRetrieveDnsDomainNameFromHive()
  628. Win32Err = RegOpenKeyExW( HKEY_LOCAL_MACHINE,
  629. L"ifmSecurity",
  630. 0,
  631. KEY_READ,
  632. & OldSecurityKey );
  633. if (Win32Err != ERROR_SUCCESS)
  634. {
  635. DsRolepLogPrint(( DEB_ERROR, "Failed to open key: %lu\n",
  636. Win32Err ));
  637. goto cleanup;
  638. }
  639. //Allocate memory to be returned to the client
  640. *lpDNSDomainName = MIDL_user_allocate((DNS_MAX_NAME_LENGTH+1)*sizeof(WCHAR));
  641. if(!*lpDNSDomainName){
  642. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  643. goto cleanup;
  644. }
  645. ZeroMemory(*lpDNSDomainName,DNS_MAX_NAME_LENGTH*sizeof(WCHAR));
  646. size = (DNS_MAX_NAME_LENGTH+1)*sizeof(WCHAR);
  647. //looking for the DNS name of the Domain that the replica is part of.
  648. Status = LsapRetrieveDnsDomainNameFromHive(OldSecurityKey,
  649. &size,
  650. *lpDNSDomainName
  651. );
  652. if (!NT_SUCCESS(Status)) {
  653. DsRolepLogPrint(( DEB_ERROR, "Failed to retrieve DNS domain name for hive : %lu\n",
  654. RtlNtStatusToDosError(Status) ));
  655. Win32Err = RtlNtStatusToDosError(Status);
  656. goto cleanup;
  657. }
  658. if (GCready) {
  659. *State |= DSROLE_DC_IS_GC;
  660. }
  661. if (BootType == 1) {
  662. *State |= DSROLE_KEY_STORED;
  663. } else if ( BootType == 2) {
  664. *State |= DSROLE_KEY_PROMPT;
  665. } else if ( BootType == 3) {
  666. *State |= DSROLE_KEY_DISK;
  667. } else {
  668. DsRolepLogPrint(( DEB_ERROR, "Didn't discover Boot type Error Unknown\n"));
  669. MIDL_user_free(*lpDNSDomainName);
  670. *lpDNSDomainName=NULL;
  671. }
  672. cleanup:
  673. {
  674. DWORD tWin32Err = ERROR_SUCCESS;
  675. if ( LsaKey ) {
  676. tWin32Err = RegCloseKey(LsaKey);
  677. LsaKey=NULL;
  678. if ( tWin32Err != ERROR_SUCCESS ) {
  679. DsRolepLogPrint(( DEB_ERROR, "RegCloseKey failed with %d\n",
  680. tWin32Err ));
  681. }
  682. }
  683. if ( OldSecurityKey ) {
  684. tWin32Err = RegCloseKey(OldSecurityKey);
  685. OldSecurityKey=NULL;
  686. if ( tWin32Err != ERROR_SUCCESS ) {
  687. DsRolepLogPrint(( DEB_ERROR, "RegCloseKey failed with %d\n",
  688. tWin32Err ));
  689. }
  690. }
  691. if ( phkOldlocation ) {
  692. tWin32Err = RegCloseKey(phkOldlocation);
  693. phkOldlocation=NULL;
  694. if ( tWin32Err != ERROR_SUCCESS ) {
  695. DsRolepLogPrint(( DEB_ERROR, "RegCloseKey failed with %d\n",
  696. tWin32Err ));
  697. }
  698. }
  699. if(SystemKeyloaded){
  700. tWin32Err = RegUnLoadKeyW(
  701. HKEY_LOCAL_MACHINE,
  702. IFM_SYSTEM_KEY);
  703. if ( tWin32Err != ERROR_SUCCESS) {
  704. DsRolepLogPrint(( DEB_ERROR, "RegUnLoadKeyW failed with %d\n",
  705. tWin32Err ));
  706. }
  707. }
  708. if (SecurityKeyloaded) {
  709. tWin32Err = RegUnLoadKeyW(
  710. HKEY_LOCAL_MACHINE,
  711. IFM_SECURITY_KEY);
  712. if ( tWin32Err != ERROR_SUCCESS) {
  713. DsRolepLogPrint(( DEB_ERROR, "RegUnLoadKeyW failed with %d\n",
  714. tWin32Err ));
  715. }
  716. }
  717. }
  718. Status = RtlAdjustPrivilege( SE_RESTORE_PRIVILEGE,
  719. FALSE, // Disable
  720. FALSE, // not client; process wide
  721. &fWasEnabled );
  722. ASSERT( NT_SUCCESS( Status ) );
  723. if ((ERROR_SUCCESS != Win32Err) && *lpDNSDomainName) {
  724. MIDL_user_free(*lpDNSDomainName);
  725. *lpDNSDomainName=NULL;
  726. }
  727. return Win32Err;
  728. }