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.

1583 lines
46 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 <wxlpc.h>
  39. #include "secure.h"
  40. #include "dsconfig.h"
  41. #define STRSAFE_NO_DEPRECATE 1
  42. #include "strsafe.h"
  43. // Few forward delcarations
  44. DWORD DsRolepGetRegString(HKEY hKey, WCHAR * wszValueName, WCHAR ** pwszOutValue);
  45. DWORD NtdspRemoveROAttrib(WCHAR * DstPath);
  46. DWORD NtdspClearDirectory(WCHAR * DirectoryName, BOOL fRemoveRO);
  47. DWORD DsRolepMakeAltRegistry(WCHAR * wszOldRegPath, WCHAR * wszNewRegPath, ULONG cbNewRegPath);
  48. DWORD
  49. DsRolepInstallDs(
  50. IN LPWSTR DnsDomainName,
  51. IN LPWSTR FlatDomainName,
  52. IN LPWSTR DnsTreeRoot,
  53. IN LPWSTR SiteName,
  54. IN LPWSTR DsDatabasePath,
  55. IN LPWSTR DsLogPath,
  56. IN IFM_SYSTEM_INFO * pIfmSystemInfo,
  57. IN LPWSTR SysVolRootPath,
  58. IN PUNICODE_STRING Bootkey,
  59. IN LPWSTR AdminAccountPassword,
  60. IN LPWSTR ParentDnsName,
  61. IN LPWSTR Server OPTIONAL,
  62. IN LPWSTR Account OPTIONAL,
  63. IN LPWSTR Password OPTIONAL,
  64. IN LPWSTR SafeModePassword OPTIONAL,
  65. IN LPWSTR SourceDomain OPTIONAL,
  66. IN ULONG Options,
  67. IN BOOLEAN Replica,
  68. IN HANDLE ImpersonateToken,
  69. OUT LPWSTR *InstalledSite,
  70. IN OUT GUID *DomainGuid,
  71. OUT PSID *NewDomainSid
  72. )
  73. /*++
  74. Routine Description:
  75. Wrapper for the routine that does the actual install.
  76. Arguments:
  77. DnsDomainName - Dns domain name of the domain to install
  78. FlatDomainName - NetBIOS domain name of the domain to install
  79. SiteName - Name of the site this DC should belong to
  80. DsDatabasePath - Absolute path on the local machine where the Ds DIT should go
  81. DsLogPath - Absolute path on the local machine where the Ds log files should go
  82. pIfmSystemInfo - Information about the IFM system and restore media used to
  83. dcpromo off. If NULL, not an IFM promotion.
  84. EnterpriseSysVolPath -- Absolute path on the local machine for the enterprise wide
  85. system volume
  86. DomainSysVolPath -- Absolute path on the local machine for the domain wide system volume
  87. AdminAccountPassword -- Administrator password to set for the domain
  88. ParentDnsName - Optional. Parent domain name
  89. Server -- Optional. Replica partner or name of Dc in parent domain
  90. Account - User account to use when setting up as a child domain
  91. Password - Password to use with the above account
  92. Replica - If TRUE, treat this as a replica install
  93. ImpersonateToken - the token of caller of the role change API
  94. InstalledSite - Name of the site the Dc was installed into
  95. DomainGuid - Where the new domain guid is returned
  96. NewDomainSid - Where the new domain sid is returned.
  97. Returns:
  98. ERROR_SUCCESS - Success
  99. --*/
  100. {
  101. DWORD Win32Err = ERROR_SUCCESS;
  102. NTDS_INSTALL_INFO DsInstallInfo;
  103. PSEC_WINNT_AUTH_IDENTITY AuthIdent = NULL;
  104. BOOL fRewindServer = FALSE;
  105. RtlZeroMemory( &DsInstallInfo, sizeof( DsInstallInfo ) );
  106. if ( !Replica ) {
  107. if ( ParentDnsName == NULL ) {
  108. DsInstallInfo.Flags = NTDS_INSTALL_ENTERPRISE;
  109. } else {
  110. DsInstallInfo.Flags = NTDS_INSTALL_DOMAIN;
  111. }
  112. } else {
  113. DsInstallInfo.Flags = NTDS_INSTALL_REPLICA;
  114. }
  115. if ( FLAG_ON( Options, DSROLE_DC_ALLOW_DC_REINSTALL ) ) {
  116. DsInstallInfo.Flags |= NTDS_INSTALL_DC_REINSTALL;
  117. }
  118. if ( FLAG_ON( Options, DSROLE_DC_ALLOW_DOMAIN_REINSTALL ) ) {
  119. DsInstallInfo.Flags |= NTDS_INSTALL_DOMAIN_REINSTALL;
  120. }
  121. if ( FLAG_ON( Options, DSROLE_DC_DOWNLEVEL_UPGRADE ) ) {
  122. DsInstallInfo.Flags |= NTDS_INSTALL_UPGRADE;
  123. }
  124. if ( FLAG_ON( Options, DSROLE_DC_TRUST_AS_ROOT ) ) {
  125. DsInstallInfo.Flags |= NTDS_INSTALL_NEW_TREE;
  126. }
  127. if ( FLAG_ON( Options, DSROLE_DC_ALLOW_ANONYMOUS_ACCESS ) ) {
  128. DsInstallInfo.Flags |= NTDS_INSTALL_ALLOW_ANONYMOUS;
  129. }
  130. if ( FLAG_ON( Options, DSROLE_DC_DEFAULT_REPAIR_PWD ) ) {
  131. DsInstallInfo.Flags |= NTDS_INSTALL_DFLT_REPAIR_PWD;
  132. }
  133. if ( FLAG_ON( Options, DSROLE_DC_SET_FOREST_CURRENT ) ) {
  134. DsInstallInfo.Flags |= NTDS_INSTALL_SET_FOREST_CURRENT;
  135. }
  136. if ( Server
  137. && Server[0] == L'\\' ) {
  138. //
  139. // Don't pass in \\
  140. //
  141. Server += 2;
  142. fRewindServer = TRUE;
  143. }
  144. DsInstallInfo.DitPath = ( PWSTR )DsDatabasePath;
  145. DsInstallInfo.LogPath = ( PWSTR )DsLogPath;
  146. DsInstallInfo.SysVolPath = (PWSTR)SysVolRootPath;
  147. DsInstallInfo.pIfmSystemInfo = pIfmSystemInfo;
  148. DsInstallInfo.BootKey = Bootkey->Buffer;
  149. DsInstallInfo.cbBootKey = Bootkey->Length;
  150. DsInstallInfo.SiteName = ( PWSTR )SiteName;
  151. DsInstallInfo.DnsDomainName = ( PWSTR )DnsDomainName;
  152. DsInstallInfo.FlatDomainName = ( PWSTR )FlatDomainName;
  153. DsInstallInfo.DnsTreeRoot = ( PWSTR )DnsTreeRoot;
  154. DsInstallInfo.ReplServerName = ( PWSTR )Server;
  155. DsInstallInfo.pfnUpdateStatus = DsRolepStringUpdateCallback;
  156. DsInstallInfo.pfnOperationResultFlags = DsRolepOperationResultFlagsCallBack;
  157. DsInstallInfo.AdminPassword = AdminAccountPassword;
  158. DsInstallInfo.pfnErrorStatus = DsRolepStringErrorUpdateCallback;
  159. DsInstallInfo.ClientToken = ImpersonateToken;
  160. DsInstallInfo.SafeModePassword = SafeModePassword;
  161. DsInstallInfo.SourceDomainName = SourceDomain;
  162. DsInstallInfo.Options = Options;
  163. if (pIfmSystemInfo) {
  164. ASSERT(pIfmSystemInfo->dwSchemaVersion);
  165. ASSERT(pIfmSystemInfo->wszDnsDomainName);
  166. DsInstallInfo.RestoredSystemSchemaVersion = pIfmSystemInfo->dwSchemaVersion;
  167. if(FALSE == DnsNameCompare_W(pIfmSystemInfo->wszDnsDomainName,
  168. DsInstallInfo.DnsDomainName)) {
  169. DSROLEP_FAIL2( ERROR_CURRENT_DOMAIN_NOT_ALLOWED,
  170. DSROLERES_WRONG_DOMAIN,
  171. DsInstallInfo.DnsDomainName,
  172. pIfmSystemInfo->wszDnsDomainName );
  173. return ERROR_CURRENT_DOMAIN_NOT_ALLOWED;
  174. }
  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.pIfmSystemInfo == NULL) {
  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. IN ULONG cRemoveNCs,
  281. IN LPWSTR * pszRemoveNCs,
  282. IN ULONG Flags
  283. )
  284. /*++
  285. Routine Description:
  286. Wrapper for the routine that does the actual demotion.
  287. Arguments:
  288. DnsDomainName - Dns domain name of the domain to demote
  289. Account - Account to use for the demotion
  290. Password - Password to use with the above account
  291. AdminPassword -- Administrator password to set for the domain
  292. SupportDc - Optional. Name of a Dc in a domain (current or parent) to
  293. clean up Ds information
  294. SupportDomain - Optional. Name of the domain (current or parent) to
  295. clean up Ds information
  296. ImpersonateToken - the token of caller of the role change API
  297. LastDcInDomain - If TRUE, this is the last Dc in the domain
  298. Returns:
  299. ERROR_SUCCESS - Success
  300. --*/
  301. {
  302. DWORD Win32Err = ERROR_SUCCESS;
  303. PSEC_WINNT_AUTH_IDENTITY AuthIdent = NULL;
  304. NTSTATUS Status;
  305. DSROLEP_CURRENT_OP0( DSROLEEVT_UNINSTALL_DS );
  306. DsRoleDebugOut(( DEB_TRACE_DS, "Calling NtdsDemote for %ws\n", DnsDomainName ));
  307. DSROLE_GET_SETUP_FUNC( Win32Err, DsrNtdsDemote );
  308. if ( Win32Err == ERROR_SUCCESS ) {
  309. DsRolepSetAndClearLog();
  310. //
  311. // Build the cred structure
  312. //
  313. Win32Err = DsRolepCreateAuthIdentForCreds( Account, Password, &AuthIdent );
  314. if ( Win32Err == ERROR_SUCCESS ) {
  315. Status = LsapDsUnitializeDsStateInfo();
  316. if ( !NT_SUCCESS( Status ) ) {
  317. Win32Err = RtlNtStatusToDosError( Status );
  318. }
  319. }
  320. if ( Win32Err == ERROR_SUCCESS ) {
  321. DsRolepLogPrint(( DEB_TRACE_DS, "Invoking NtdsDemote\n" ));
  322. Win32Err = ( *DsrNtdsDemote )( AuthIdent,
  323. AdminPassword,
  324. (LastDcInDomain ? NTDS_LAST_DC_IN_DOMAIN : 0)|DsRolepDemoteFlagsToNtdsFlags(Flags),
  325. SupportDc,
  326. ImpersonateToken,
  327. DsRolepStringUpdateCallback,
  328. DsRolepStringErrorUpdateCallback,
  329. cRemoveNCs,
  330. pszRemoveNCs );
  331. if ( Win32Err != ERROR_SUCCESS ) {
  332. //
  333. // Switch the LSA back to using the DS
  334. //
  335. LsapDsInitializeDsStateInfo( LsapDsDs );
  336. }
  337. //
  338. // Free the allocated creditials structure
  339. //
  340. DsRolepFreeAuthIdentForCreds( AuthIdent );
  341. }
  342. DsRolepSetAndClearLog();
  343. DsRolepLogPrint(( DEB_TRACE_DS, "NtdsDemote returned %lu\n",
  344. Win32Err ));
  345. }
  346. DsRolepLogPrint(( DEB_TRACE,
  347. "DsRolepDemoteDs returned %lu\n",
  348. Win32Err ));
  349. DSROLEP_FAIL0( Win32Err, DSROLERES_DEMOTE_DS );
  350. return( Win32Err );
  351. }
  352. DWORD
  353. DsRolepUninstallDs(
  354. VOID
  355. )
  356. /*++
  357. Routine Description:
  358. Uninstalls the Ds.
  359. Arguments:
  360. VOID
  361. Returns:
  362. ERROR_SUCCESS - Success
  363. --*/
  364. {
  365. DWORD Win32Err = ERROR_SUCCESS;
  366. DSROLE_GET_SETUP_FUNC( Win32Err, DsrNtdsInstallUndo );
  367. if ( Win32Err == ERROR_SUCCESS ) {
  368. Win32Err = ( *DsrNtdsInstallUndo )( );
  369. }
  370. DsRoleDebugOut(( DEB_TRACE_DS, "NtdsUnInstall returned %lu\n", Win32Err ));
  371. return( Win32Err );
  372. }
  373. DWORD
  374. DsRolepDemoteFlagsToNtdsFlags(
  375. DWORD Flags
  376. )
  377. {
  378. DWORD fl = 0;
  379. fl |= ( FLAG_ON( Flags, DSROLE_DC_DONT_DELETE_DOMAIN ) ? NTDS_DONT_DELETE_DOMAIN : 0 );
  380. fl |= ( FLAG_ON( Flags, DSROLE_DC_FORCE_DEMOTE ) ? NTDS_FORCE_DEMOTE : 0 );
  381. return fl;
  382. }
  383. DWORD
  384. DsRolepLoadHive(
  385. IN LPWSTR Hive,
  386. IN LPWSTR KeyName
  387. )
  388. /*++
  389. Routine Description:
  390. This function will load a hive into the registry
  391. Arguments:
  392. lpRestorePath - The location of the restored files.
  393. lpDNSDomainName - This parameter will recieve the name of the domain that this backup came
  394. from
  395. State - The return Values that report How the syskey is stored and If the back was likely
  396. taken form a GC or not.
  397. Return Values:
  398. ERROR_SUCCESS - Success
  399. --*/
  400. {
  401. DWORD Win32Err = ERROR_SUCCESS;
  402. Win32Err = RegLoadKeyW(
  403. HKEY_LOCAL_MACHINE,
  404. KeyName,
  405. Hive);
  406. if (Win32Err != ERROR_SUCCESS) {
  407. DsRolepLogPrint(( DEB_WARN, "Failed to load key %ws: %lu retrying\n",
  408. Hive,
  409. Win32Err ));
  410. RegUnLoadKeyW(
  411. HKEY_LOCAL_MACHINE,
  412. KeyName);
  413. Win32Err = RegLoadKeyW(
  414. HKEY_LOCAL_MACHINE,
  415. KeyName,
  416. Hive);
  417. if (Win32Err != ERROR_SUCCESS) {
  418. DsRolepLogPrint(( DEB_ERROR, "Failed to load key %ws: %lu\n",
  419. Hive,
  420. Win32Err ));
  421. goto cleanup;
  422. }
  423. }
  424. cleanup:
  425. return Win32Err;
  426. }
  427. DWORD
  428. WINAPI
  429. DsRolepClearIfmParams(
  430. void
  431. )
  432. /*++
  433. Routine Description:
  434. Deallocate the IFM params.
  435. Return Values:
  436. ERROR_SUCCESS
  437. --*/
  438. {
  439. IFM_SYSTEM_INFO * pIfm = &DsRolepCurrentIfmOperationHandle.IfmSystemInfo;
  440. ASSERT(DsRolepCurrentIfmOperationHandle.fIfmOpHandleLock);
  441. //
  442. // Deallocate and clear the IFM_SYSTEM_INFO blob
  443. //
  444. if (pIfm->wszRestorePath) {
  445. LocalFree(pIfm->wszRestorePath);
  446. }
  447. if (pIfm->wszDnsDomainName) {
  448. LocalFree(pIfm->wszDnsDomainName);
  449. }
  450. if (pIfm->wszOriginalDitPath) {
  451. LocalFree(pIfm->wszOriginalDitPath);
  452. }
  453. if (pIfm->pvSysKey) {
  454. // We need to scrub the syskey from memory, before freeing it.
  455. memset(pIfm->pvSysKey, 0, pIfm->cbSysKey);
  456. LocalFree(pIfm->pvSysKey);
  457. }
  458. // Clear everything out...
  459. memset(pIfm, 0, sizeof(IFM_SYSTEM_INFO));
  460. return(ERROR_SUCCESS);
  461. }
  462. DWORD
  463. WINAPI
  464. DsRolepGetDatabaseFacts(
  465. IN LPWSTR lpRestorePath
  466. )
  467. /*++
  468. Routine Description:
  469. This function will collect all the information from the IFM system's
  470. "restored" registry that is required for this IFM Dcpromo.
  471. This function will collect this information about the IFM system:
  472. 1. the way the syskey is stored
  473. a. and the syskey itself if it was stored in the registry
  474. 2. the domain that the database came from
  475. 3. where the backup was taken from a GC or not
  476. 4. the schema version
  477. 5. the original IFM system's DIT/DB path.
  478. Arguments:
  479. lpRestorePath - The location of the restored files.
  480. This function primarily sets up this global:
  481. DsRolepCurrentIfmOperationHandle.IfmSystemInfo
  482. Return Values:
  483. Win32 Error
  484. --*/
  485. {
  486. #define IFM_SYSTEM_KEY L"ifmSystem"
  487. #define IFM_SECURITY_KEY L"ifmSecurity"
  488. WCHAR wszAltRegLoc[MAX_PATH+1] = L"\0";
  489. WCHAR regsystemfilepath[MAX_PATH+1];
  490. WCHAR regsecurityfilepath[MAX_PATH+1];
  491. DWORD controlset=0;
  492. DWORD BootType=0;
  493. DWORD GCready=0;
  494. DWORD type=REG_DWORD;
  495. DWORD size=sizeof(DWORD);
  496. HKEY LsaKey=NULL;
  497. HKEY hSystemKey=NULL;
  498. HKEY phkOldlocation=NULL;
  499. HKEY OldSecurityKey=NULL;
  500. DWORD Win32Err=ERROR_SUCCESS;
  501. BOOLEAN fWasEnabled=FALSE;
  502. NTSTATUS Status=STATUS_SUCCESS;
  503. BOOL SystemKeyloaded=FALSE;
  504. BOOL SecurityKeyloaded=FALSE;
  505. WCHAR *pStr = NULL;
  506. BOOL bRetryInWriteableLoc = FALSE;
  507. // This is the structure this function initializes
  508. IFM_SYSTEM_INFO * pIfmSystemInfo = &(DsRolepCurrentIfmOperationHandle.IfmSystemInfo);
  509. // Some validation.
  510. ASSERT(DsRolepCurrentIfmOperationHandle.fIfmOpHandleLock);
  511. ASSERT(!DsRolepCurrentIfmOperationHandle.fIfmSystemInfoSet);
  512. ASSERT( wcslen(lpRestorePath) <= MAX_PATH );
  513. //
  514. // Null out info ...
  515. //
  516. ZeroMemory(pIfmSystemInfo, sizeof(IFM_SYSTEM_INFO));
  517. Status = RtlAdjustPrivilege( SE_RESTORE_PRIVILEGE,
  518. TRUE, // Enable
  519. FALSE, // not client; process wide
  520. &fWasEnabled );
  521. ASSERT( NT_SUCCESS( Status ) );
  522. //set up the location of the system registry file
  523. //
  524. // Set restore path
  525. //
  526. pIfmSystemInfo->wszRestorePath = LocalAlloc(LMEM_FIXED, (wcslen(lpRestorePath)+1)*sizeof(WCHAR));
  527. if (pIfmSystemInfo->wszRestorePath == NULL) {
  528. Win32Err = GetLastError();
  529. goto cleanup;
  530. }
  531. wcscpy(pIfmSystemInfo->wszRestorePath, lpRestorePath);
  532. //
  533. // On first try setup the system and security registry paths
  534. //
  535. regsystemfilepath[MAX_PATH] = L'\0';
  536. wcscpy(regsystemfilepath,lpRestorePath);
  537. wcsncat(regsystemfilepath,L"\\registry\\system",(MAX_PATH)-wcslen(regsystemfilepath));
  538. regsecurityfilepath[MAX_PATH] = L'\0';
  539. wcscpy(regsecurityfilepath,lpRestorePath);
  540. wcsncat(regsecurityfilepath,L"\\registry\\security",MAX_PATH-wcslen(regsecurityfilepath));
  541. //
  542. // First - Load the old IFM system's hive
  543. //
  544. //
  545. // Get the source path of the database and the log files from the old
  546. // registry
  547. //
  548. Win32Err = DsRolepLoadHive(regsystemfilepath,
  549. IFM_SYSTEM_KEY);
  550. if (ERROR_SUCCESS != Win32Err) {
  551. if (Win32Err != ERROR_ACCESS_DENIED) {
  552. goto cleanup;
  553. }
  554. //
  555. // This can happen if the IFM Systems hive is on any
  556. // non-writeable directory, so in this case, we'll try
  557. // making a copy and retrying.
  558. //
  559. //
  560. // On a retry, copy off the hives, and then re-setup the
  561. // system and security registry paths
  562. //
  563. DsRolepLogPrint(( DEB_TRACE, "No access to IFM registry, copying off and retrying ...\n"));
  564. // Setup current registry location.
  565. wcscpy(regsystemfilepath,lpRestorePath);
  566. wcsncat(regsystemfilepath,L"\\registry",(MAX_PATH)-wcslen(regsystemfilepath));
  567. Win32Err = DsRolepMakeAltRegistry(regsystemfilepath,
  568. wszAltRegLoc,
  569. sizeof(wszAltRegLoc)/sizeof(wszAltRegLoc[0]));
  570. if (Win32Err) {
  571. // logged error already ...
  572. goto cleanup;
  573. }
  574. bRetryInWriteableLoc = TRUE;
  575. ASSERT(wszAltRegLoc[0] != L'\0');
  576. wcscpy(regsystemfilepath, wszAltRegLoc);
  577. wcscpy(regsecurityfilepath, wszAltRegLoc);
  578. wcsncat(regsystemfilepath, L"\\system", (MAX_PATH)-wcslen(regsystemfilepath));
  579. wcsncat(regsecurityfilepath, L"\\security", (MAX_PATH)-wcslen(regsecurityfilepath));
  580. // retry load IFM system's hives
  581. //
  582. Win32Err = DsRolepLoadHive(regsystemfilepath,
  583. IFM_SYSTEM_KEY);
  584. if (ERROR_SUCCESS != Win32Err) {
  585. goto cleanup;
  586. }
  587. }
  588. SystemKeyloaded = TRUE;
  589. //find the default controlset
  590. Win32Err = RegOpenKeyExW( HKEY_LOCAL_MACHINE,
  591. L"ifmSystem\\Select",
  592. 0,
  593. KEY_READ,
  594. & LsaKey );
  595. if (Win32Err != ERROR_SUCCESS)
  596. {
  597. DsRolepLogPrint(( DEB_ERROR, "Failed to open key: %lu\n",
  598. Win32Err ));
  599. goto cleanup;
  600. }
  601. Win32Err = RegQueryValueExW(
  602. LsaKey,
  603. L"Default",
  604. 0,
  605. &type,
  606. (PUCHAR) &controlset,
  607. &size
  608. );
  609. if (Win32Err != ERROR_SUCCESS)
  610. {
  611. DsRolepLogPrint(( DEB_ERROR, "Couldn't Discover proper controlset: %lu\n",
  612. Win32Err ));
  613. goto cleanup;
  614. }
  615. Win32Err = RegCloseKey(LsaKey);
  616. LsaKey=NULL;
  617. if (Win32Err != ERROR_SUCCESS) {
  618. DsRolepLogPrint(( DEB_ERROR, "RegCloseKey failed with %d\n",
  619. Win32Err ));
  620. goto cleanup;
  621. }
  622. //Find the boot type
  623. if (controlset == 1) {
  624. Win32Err = RegOpenKeyExW( HKEY_LOCAL_MACHINE,
  625. L"ifmSystem\\ControlSet001\\Control\\Lsa",
  626. 0,
  627. KEY_READ,
  628. & LsaKey );
  629. } else {
  630. Win32Err = RegOpenKeyExW( HKEY_LOCAL_MACHINE,
  631. L"ifmSystem\\ControlSet002\\Control\\Lsa",
  632. 0,
  633. KEY_READ,
  634. & LsaKey );
  635. }
  636. if (Win32Err != ERROR_SUCCESS)
  637. {
  638. DsRolepLogPrint(( DEB_ERROR, "Failed to open key: %lu\n",
  639. Win32Err ));
  640. goto cleanup;
  641. }
  642. Win32Err = RegQueryValueExW(
  643. LsaKey,
  644. L"SecureBoot",
  645. 0,
  646. &type,
  647. (PUCHAR) &BootType,
  648. &size
  649. );
  650. if (Win32Err != ERROR_SUCCESS)
  651. {
  652. DsRolepLogPrint(( DEB_ERROR, "Couldn't Discover proper controlset: %lu\n",
  653. Win32Err ));
  654. goto cleanup;
  655. }
  656. Win32Err = RegCloseKey(LsaKey);
  657. LsaKey=NULL;
  658. if (Win32Err != ERROR_SUCCESS) {
  659. DsRolepLogPrint(( DEB_ERROR, "RegCloseKey failed with %d\n",
  660. Win32Err ));
  661. goto cleanup;
  662. }
  663. //find if a GC or not
  664. if (controlset == 1) {
  665. Win32Err = RegOpenKeyExW(
  666. HKEY_LOCAL_MACHINE,
  667. L"ifmSystem\\ControlSet001\\Services\\NTDS\\Parameters",
  668. 0,
  669. KEY_READ,
  670. &phkOldlocation
  671. );
  672. } else {
  673. Win32Err = RegOpenKeyExW(
  674. HKEY_LOCAL_MACHINE,
  675. L"ifmSystem\\ControlSet002\\Services\\NTDS\\Parameters",
  676. 0,
  677. KEY_READ,
  678. &phkOldlocation
  679. );
  680. }
  681. if (Win32Err != ERROR_SUCCESS) {
  682. DsRolepLogPrint(( DEB_ERROR, "RegOpenKeyExW failed to discover the GC state of the database %d\n",
  683. Win32Err ));
  684. goto cleanup;
  685. }
  686. Win32Err = RegQueryValueEx(
  687. phkOldlocation,
  688. TEXT(GC_PROMOTION_COMPLETE),
  689. 0,
  690. &type,
  691. (VOID*)&GCready,
  692. &size
  693. );
  694. if (Win32Err != ERROR_SUCCESS && ERROR_FILE_NOT_FOUND != Win32Err) {
  695. DsRolepLogPrint(( DEB_ERROR, "RegQueryValueEx failed to discover the GC state of the database %d\n",
  696. Win32Err ));
  697. goto cleanup;
  698. }
  699. Win32Err = RegQueryValueEx(
  700. phkOldlocation,
  701. TEXT(SYSTEM_SCHEMA_VERSION),
  702. 0,
  703. &type,
  704. (VOID*)&(pIfmSystemInfo->dwSchemaVersion),
  705. &size
  706. );
  707. if (Win32Err != ERROR_SUCCESS && ERROR_FILE_NOT_FOUND != Win32Err) {
  708. DsRolepLogPrint(( DEB_ERROR, "RegQueryValueEx failed to discover the GC state of the database %d\n",
  709. Win32Err ));
  710. goto cleanup;
  711. }
  712. //
  713. // Fill in the wszDitPath for later use.
  714. //
  715. Win32Err = DsRolepGetRegString(phkOldlocation,
  716. TEXT(FILEPATH_KEY),
  717. &(pIfmSystemInfo->wszOriginalDitPath));
  718. if (Win32Err != ERROR_SUCCESS) {
  719. DsRolepLogPrint(( DEB_ERROR, "DsRolepGetRegString() failed to discover the old databae location %d\n",
  720. Win32Err ));
  721. goto cleanup;
  722. }
  723. //
  724. // This code loads the system key from the old registry if
  725. // it's supposed (BootType is right). We ignore errors,
  726. // as install will print and do the right thing later on.
  727. //
  728. ASSERT(BootType);
  729. ASSERT(pIfmSystemInfo->dwSysKeyStatus == ERROR_SUCCESS);
  730. if (BootType == 1) {
  731. //
  732. // Fill in the system key if we're supposed.
  733. //
  734. Win32Err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, // handle to open key
  735. IFM_SYSTEM_KEY, // subkey name
  736. 0, // reserved
  737. KEY_READ, // security access mask
  738. &hSystemKey // handle to open key
  739. );
  740. if (Win32Err) {
  741. pIfmSystemInfo->dwSysKeyStatus = Win32Err;
  742. DsRolepLogPrint(( DEB_ERROR, "Failed to open key: %lu\n",
  743. Win32Err ));
  744. Win32Err = ERROR_SUCCESS;
  745. } else {
  746. pIfmSystemInfo->cbSysKey = SYSKEY_SIZE;
  747. pIfmSystemInfo->pvSysKey = LocalAlloc(LMEM_FIXED, pIfmSystemInfo->cbSysKey);
  748. if (pIfmSystemInfo->pvSysKey == NULL) {
  749. pIfmSystemInfo->dwSysKeyStatus = GetLastError();
  750. // go on.
  751. } else {
  752. Win32Err = WxReadSysKeyEx(hSystemKey,
  753. &pIfmSystemInfo->cbSysKey,
  754. (PVOID)pIfmSystemInfo->pvSysKey);
  755. if (Win32Err) {
  756. pIfmSystemInfo->dwSysKeyStatus = Win32Err;
  757. DsRolepLogPrint(( DEB_ERROR, "WxReadSysKeyEx failed to get the syskey %d\n",
  758. Win32Err ));
  759. Win32Err = ERROR_SUCCESS;
  760. }
  761. Win32Err = RegCloseKey(hSystemKey);
  762. if (Win32Err!=ERROR_SUCCESS) {
  763. DsRolepLogPrint(( DEB_ERROR, "RegCloseKey failed %d\n",
  764. Win32Err ));
  765. Win32Err = ERROR_SUCCESS;
  766. }
  767. }
  768. }
  769. } else {
  770. // SysKey not set
  771. pIfmSystemInfo->dwSysKeyStatus = ERROR_FILE_NOT_FOUND;
  772. pIfmSystemInfo->cbSysKey = 0;
  773. }
  774. //
  775. // The System key is no longer needed unload it.
  776. //
  777. {
  778. DWORD tWin32Err = ERROR_SUCCESS;
  779. if ( phkOldlocation ) {
  780. tWin32Err = RegCloseKey(phkOldlocation);
  781. phkOldlocation = NULL;
  782. if ( tWin32Err != ERROR_SUCCESS ) {
  783. DsRolepLogPrint(( DEB_ERROR, "RegCloseKey failed with %d\n",
  784. tWin32Err ));
  785. }
  786. }
  787. if(SystemKeyloaded){
  788. tWin32Err = RegUnLoadKeyW(
  789. HKEY_LOCAL_MACHINE,
  790. IFM_SYSTEM_KEY);
  791. SystemKeyloaded = FALSE;
  792. if ( tWin32Err != ERROR_SUCCESS) {
  793. DsRolepLogPrint(( DEB_ERROR, "RegUnLoadKeyW failed to unload system key with %d\n",
  794. tWin32Err ));
  795. }
  796. }
  797. }
  798. Win32Err = DsRolepLoadHive(regsecurityfilepath,
  799. IFM_SECURITY_KEY);
  800. if (ERROR_SUCCESS != Win32Err) {
  801. goto cleanup;
  802. }
  803. SecurityKeyloaded = TRUE;
  804. //open the security key to pass to LsapRetrieveDnsDomainNameFromHive()
  805. Win32Err = RegOpenKeyExW( HKEY_LOCAL_MACHINE,
  806. L"ifmSecurity",
  807. 0,
  808. KEY_READ,
  809. & OldSecurityKey );
  810. if (Win32Err != ERROR_SUCCESS)
  811. {
  812. DsRolepLogPrint(( DEB_ERROR, "Failed to open key: %lu\n",
  813. Win32Err ));
  814. goto cleanup;
  815. }
  816. pIfmSystemInfo->wszDnsDomainName = LocalAlloc(0, ((DNS_MAX_NAME_LENGTH+1)*sizeof(WCHAR)));
  817. if(pIfmSystemInfo->wszDnsDomainName == NULL){
  818. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  819. goto cleanup;
  820. }
  821. ZeroMemory(pIfmSystemInfo->wszDnsDomainName,DNS_MAX_NAME_LENGTH*sizeof(WCHAR));
  822. size = (DNS_MAX_NAME_LENGTH+1)*sizeof(WCHAR);
  823. //looking for the DNS name of the Domain that the replica is part of.
  824. Status = LsapRetrieveDnsDomainNameFromHive(OldSecurityKey,
  825. &size,
  826. pIfmSystemInfo->wszDnsDomainName
  827. );
  828. if (!NT_SUCCESS(Status)) {
  829. DsRolepLogPrint(( DEB_ERROR, "Failed to retrieve DNS domain name for hive : %lu\n",
  830. RtlNtStatusToDosError(Status) ));
  831. Win32Err = RtlNtStatusToDosError(Status);
  832. goto cleanup;
  833. }
  834. if (GCready) {
  835. pIfmSystemInfo->dwState |= DSROLE_DC_IS_GC;
  836. }
  837. if (BootType == 1) {
  838. pIfmSystemInfo->dwState |= DSROLE_KEY_STORED;
  839. } else if ( BootType == 2) {
  840. pIfmSystemInfo->dwState |= DSROLE_KEY_PROMPT;
  841. } else if ( BootType == 3) {
  842. pIfmSystemInfo->dwState |= DSROLE_KEY_DISK;
  843. } else {
  844. DsRolepLogPrint(( DEB_ERROR, "Didn't discover Boot type Error Unknown\n"));
  845. MIDL_user_free(pIfmSystemInfo->wszDnsDomainName);
  846. pIfmSystemInfo->wszDnsDomainName = NULL;
  847. }
  848. cleanup:
  849. {
  850. DWORD tWin32Err = ERROR_SUCCESS;
  851. if ( LsaKey ) {
  852. tWin32Err = RegCloseKey(LsaKey);
  853. LsaKey=NULL;
  854. if ( tWin32Err != ERROR_SUCCESS ) {
  855. DsRolepLogPrint(( DEB_ERROR, "RegCloseKey failed with %d\n",
  856. tWin32Err ));
  857. }
  858. }
  859. if ( OldSecurityKey ) {
  860. tWin32Err = RegCloseKey(OldSecurityKey);
  861. OldSecurityKey=NULL;
  862. if ( tWin32Err != ERROR_SUCCESS ) {
  863. DsRolepLogPrint(( DEB_ERROR, "RegCloseKey failed with %d\n",
  864. tWin32Err ));
  865. }
  866. }
  867. if ( phkOldlocation ) {
  868. tWin32Err = RegCloseKey(phkOldlocation);
  869. phkOldlocation=NULL;
  870. if ( tWin32Err != ERROR_SUCCESS ) {
  871. DsRolepLogPrint(( DEB_ERROR, "RegCloseKey failed with %d\n",
  872. tWin32Err ));
  873. }
  874. }
  875. if(SystemKeyloaded){
  876. tWin32Err = RegUnLoadKeyW(
  877. HKEY_LOCAL_MACHINE,
  878. IFM_SYSTEM_KEY);
  879. if ( tWin32Err != ERROR_SUCCESS) {
  880. DsRolepLogPrint(( DEB_ERROR, "RegUnLoadKeyW failed with %d\n",
  881. tWin32Err ));
  882. }
  883. }
  884. if (SecurityKeyloaded) {
  885. tWin32Err = RegUnLoadKeyW(
  886. HKEY_LOCAL_MACHINE,
  887. IFM_SECURITY_KEY);
  888. if ( tWin32Err != ERROR_SUCCESS) {
  889. DsRolepLogPrint(( DEB_ERROR, "RegUnLoadKeyW failed with %d\n",
  890. tWin32Err ));
  891. }
  892. }
  893. if (bRetryInWriteableLoc && wszAltRegLoc[0] != L'\0') {
  894. // This also deletes the directory ...
  895. tWin32Err = NtdspClearDirectory( wszAltRegLoc , TRUE );
  896. if ( tWin32Err != ERROR_SUCCESS) {
  897. DsRolepLogPrint(( DEB_ERROR, "Failed (%d) to clear temporary registry from %ws\n",
  898. tWin32Err, wszAltRegLoc ));
  899. }
  900. }
  901. }
  902. Status = RtlAdjustPrivilege( SE_RESTORE_PRIVILEGE,
  903. FALSE, // Disable
  904. FALSE, // not client; process wide
  905. &fWasEnabled );
  906. ASSERT( NT_SUCCESS( Status ) );
  907. //
  908. // Validate and return
  909. //
  910. if (ERROR_SUCCESS == Win32Err){
  911. if (pIfmSystemInfo->wszRestorePath == NULL ||
  912. pIfmSystemInfo->wszDnsDomainName == NULL ||
  913. pIfmSystemInfo->wszOriginalDitPath == NULL) {
  914. ASSERT(!"prgrammer logic error");
  915. Win32Err = ERROR_DS_CODE_INCONSISTENCY;
  916. } else {
  917. DsRolepLogPrint(( DEB_TRACE,
  918. "IFM System Info: \n"
  919. "\t Restore Path: %ws\n"
  920. "\t Domain: %ws\n"
  921. "\t Schema Version: %d\n"
  922. "\t Original Dit Path: %ws\n"
  923. "\t State: 0x%x\n"
  924. "\t SysKey Loaded: %ws (%d)\n",
  925. pIfmSystemInfo->wszRestorePath,
  926. pIfmSystemInfo->wszDnsDomainName,
  927. pIfmSystemInfo->dwSchemaVersion,
  928. pIfmSystemInfo->wszOriginalDitPath,
  929. pIfmSystemInfo->dwState,
  930. pIfmSystemInfo->pvSysKey ? L"yes" : L"no", pIfmSystemInfo->dwSysKeyStatus
  931. ));
  932. }
  933. } else {
  934. // This safe to call, as it safely checks before de-allocating.
  935. DsRolepClearIfmParams();
  936. }
  937. return Win32Err;
  938. }
  939. DWORD
  940. DsRolepGetRegString(
  941. HKEY hKey,
  942. WCHAR * wszValueName,
  943. WCHAR ** pwszOutValue
  944. )
  945. /*++
  946. Routine Description:
  947. This gets and allocates (LocalAlloc) a string from the registry
  948. with the value name in the key provided.
  949. Arguments:
  950. hKey - Opened key handle
  951. wszValueName - Name of the value label for the registry value desired.
  952. pwszOutValue - LocalAlloc()'d results of this string.
  953. Return Values:
  954. Win32 Error
  955. --*/
  956. {
  957. DWORD Win32Err;
  958. DWORD type=REG_SZ;
  959. WCHAR * szOutTemp = NULL;
  960. DWORD cbOutTemp = 0;
  961. ASSERT(pwszOutValue);
  962. *pwszOutValue = NULL;
  963. Win32Err = RegQueryValueEx(hKey,
  964. wszValueName,
  965. 0,
  966. &type,
  967. (VOID*)szOutTemp,
  968. &cbOutTemp);
  969. if (Win32Err != ERROR_SUCCESS && Win32Err != ERROR_MORE_DATA) {
  970. DsRolepLogPrint(( DEB_ERROR, "RegQueryValueEx failed with %d\n",
  971. Win32Err ));
  972. goto cleanup;
  973. }
  974. ASSERT(cbOutTemp);
  975. szOutTemp = LocalAlloc(0, cbOutTemp);
  976. if (szOutTemp == NULL) {
  977. Win32Err = GetLastError();
  978. DsRolepLogPrint(( DEB_ERROR, "LocalAlloc() failed with %d\n",
  979. Win32Err ));
  980. goto cleanup;
  981. }
  982. Win32Err = RegQueryValueEx(hKey,
  983. wszValueName,
  984. 0,
  985. &type,
  986. (VOID*)szOutTemp,
  987. &cbOutTemp);
  988. if (Win32Err != ERROR_SUCCESS) {
  989. DsRolepLogPrint(( DEB_ERROR, "RegQueryValueEx failed with %d\n",
  990. Win32Err ));
  991. goto cleanup;
  992. }
  993. cleanup:
  994. if (Win32Err == ERROR_SUCCESS) {
  995. *pwszOutValue = szOutTemp;
  996. }
  997. return(Win32Err);
  998. }
  999. DWORD
  1000. NtdspRemoveROAttrib(
  1001. WCHAR * DstPath
  1002. )
  1003. {
  1004. DWORD dwFileAttrs = 0;
  1005. dwFileAttrs = GetFileAttributes(DstPath);
  1006. if (dwFileAttrs == INVALID_FILE_ATTRIBUTES) {
  1007. return(GetLastError());
  1008. }
  1009. if(dwFileAttrs & FILE_ATTRIBUTE_READONLY){
  1010. // Hmmm, we've got a read only file for our DIT or LOG files ... that's no good...
  1011. dwFileAttrs &= ~FILE_ATTRIBUTE_READONLY;
  1012. dwFileAttrs ? dwFileAttrs : FILE_ATTRIBUTE_NORMAL;
  1013. if(SetFileAttributes(DstPath, dwFileAttrs)){
  1014. //
  1015. // success - yeah, fall through ...
  1016. //
  1017. } else {
  1018. // failure
  1019. // There is not much we can do here, we'll probably fail later on, but
  1020. // we'll give it a shot. A failure here would likely indicate dcpromo
  1021. // was broken in some other way though, such as bad permissions on the
  1022. // db or logs directory.
  1023. return(GetLastError());
  1024. }
  1025. } // else it's writeable, nothing to do :)
  1026. return(ERROR_SUCCESS);
  1027. }
  1028. DWORD
  1029. NtdspClearDirectory(
  1030. IN WCHAR * DirectoryName,
  1031. IN BOOL fRemoveRO
  1032. )
  1033. /*++
  1034. Routine Description:
  1035. This routine deletes all the files in Directory and, then
  1036. if the directory is empty, removes the directory.
  1037. NOTE: This was stolen from ntdsetup.dll
  1038. Parameters:
  1039. DirectoryName: a null terminated string
  1040. Return Values:
  1041. A value from winerror.h
  1042. ERROR_SUCCESS - The check was done successfully.
  1043. --*/
  1044. {
  1045. DWORD WinError = ERROR_SUCCESS;
  1046. HANDLE FindHandle = INVALID_HANDLE_VALUE;
  1047. WIN32_FIND_DATA FindData;
  1048. WCHAR Path[ MAX_PATH+1 ];
  1049. WCHAR FilePath[ MAX_PATH+1 ];
  1050. BOOL fStatus;
  1051. if ( !DirectoryName || DirectoryName[0] == L'\0' )
  1052. {
  1053. ASSERT(!"Programmer error");
  1054. return ERROR_SUCCESS;
  1055. }
  1056. if ( wcslen(DirectoryName) > MAX_PATH - 4 )
  1057. {
  1058. return ERROR_INVALID_PARAMETER;
  1059. }
  1060. RtlZeroMemory( Path, sizeof(Path) );
  1061. wcscpy( Path, DirectoryName );
  1062. wcscat( Path, L"\\*.*" );
  1063. RtlZeroMemory( &FindData, sizeof( FindData ) );
  1064. FindHandle = FindFirstFile( Path, &FindData );
  1065. if ( INVALID_HANDLE_VALUE == FindHandle )
  1066. {
  1067. WinError = GetLastError();
  1068. goto ClearDirectoryExit;
  1069. }
  1070. do
  1071. {
  1072. if ( !FLAG_ON( FindData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY ) )
  1073. {
  1074. RtlZeroMemory( FilePath, sizeof(FilePath) );
  1075. wcscpy( FilePath, DirectoryName );
  1076. wcscat( FilePath, L"\\" );
  1077. wcscat( FilePath, FindData.cFileName );
  1078. fStatus = DeleteFile( FilePath );
  1079. if (fRemoveRO && fStatus) {
  1080. // perhaps it's RO ...
  1081. NtdspRemoveROAttrib( FilePath );
  1082. // now give it another go ...
  1083. fStatus = DeleteFile( FilePath );
  1084. }
  1085. //
  1086. // Even if error, continue on
  1087. //
  1088. }
  1089. RtlZeroMemory( &FindData, sizeof( FindData ) );
  1090. } while ( FindNextFile( FindHandle, &FindData ) );
  1091. WinError = GetLastError();
  1092. if ( ERROR_NO_MORE_FILES != WinError
  1093. && ERROR_SUCCESS != WinError )
  1094. {
  1095. goto ClearDirectoryExit;
  1096. }
  1097. WinError = ERROR_SUCCESS;
  1098. //
  1099. // Fall through to the exit
  1100. //
  1101. ClearDirectoryExit:
  1102. if ( ERROR_NO_MORE_FILES == WinError )
  1103. {
  1104. WinError = ERROR_SUCCESS;
  1105. }
  1106. if ( INVALID_HANDLE_VALUE != FindHandle )
  1107. {
  1108. FindClose( FindHandle );
  1109. }
  1110. if ( ERROR_SUCCESS == WinError )
  1111. {
  1112. //
  1113. // Try to remove the directory
  1114. //
  1115. fStatus = RemoveDirectory( DirectoryName );
  1116. //
  1117. // Ignore the error and continue on
  1118. //
  1119. }
  1120. return WinError;
  1121. }
  1122. DWORD
  1123. WINAPI
  1124. DsRolepMakeAltRegistry(
  1125. IN WCHAR * wszOldRegPath,
  1126. OUT WCHAR * wszNewRegPath,
  1127. IN ULONG cbNewRegPath
  1128. )
  1129. /*++
  1130. Routine Description:
  1131. This routine will create an alternate location for the system
  1132. and security hives/registries. We create a directory which
  1133. is returned in wszNewRegPath.
  1134. Arguments:
  1135. wszOldRegPath [IN] - The path to copy the system and security hives from.
  1136. wszNewRegPath [OUT] - The buffer to hold the location of the alternate hives.
  1137. cbNewRegPath [IN] - The size of the wszNewRegPath buffer.
  1138. Return Values:
  1139. Win32 Error
  1140. --*/
  1141. {
  1142. DWORD Win32Err = ERROR_SUCCESS;
  1143. WCHAR wszTempPath[MAX_PATH+1];
  1144. WCHAR wszDest[MAX_PATH+1];
  1145. SYSTEMTIME sTime;
  1146. if (wszOldRegPath == NULL || wszOldRegPath[0] == L'\0' || cbNewRegPath < sizeof(WCHAR)) {
  1147. ASSERT(!"Seems unlikely");
  1148. return(ERROR_INVALID_PARAMETER);
  1149. }
  1150. wszNewRegPath[0] = L'\0';
  1151. //
  1152. // 1) Create temp registry directory.
  1153. //
  1154. // Determine the system root
  1155. if (!GetEnvironmentVariable(L"temp", wszTempPath, sizeof(wszTempPath)/sizeof(wszTempPath[0]) )){
  1156. Win32Err = GetLastError();
  1157. DsRolepLogPrint(( DEB_ERROR, "Failed to retrieve environmental variable \"temp\" - 0x%x\n", Win32Err));
  1158. goto cleanup;
  1159. }
  1160. //dwTime = GetSecondsSince1601();
  1161. GetSystemTime( &sTime );
  1162. Win32Err = StringCbPrintf(wszNewRegPath, cbNewRegPath,
  1163. L"%ws\\ifm-reg-%d-%d-%d-%d-%d",
  1164. wszTempPath, sTime.wYear, sTime.wMonth,
  1165. sTime.wDay, sTime.wMinute, sTime.wSecond);
  1166. Win32Err = HRESULT_CODE(Win32Err);
  1167. if (Win32Err) {
  1168. wszNewRegPath[0] = L'\0'; // don't clean up directory
  1169. DsRolepLogPrint(( DEB_ERROR, "Failed to format temp registry path 0x%x\n", Win32Err));
  1170. goto cleanup;
  1171. }
  1172. if ( CreateDirectory( wszNewRegPath, NULL ) == FALSE ) {
  1173. Win32Err = GetLastError() ? GetLastError() : ERROR_INVALID_PARAMETER;
  1174. wszNewRegPath[0] = L'\0'; // don't clean up directory
  1175. DsRolepLogPrint(( DEB_ERROR, "Failed to create temp directory for temp registry files 0x%x, %ws\n", wszNewRegPath, Win32Err));
  1176. goto cleanup;
  1177. }
  1178. //
  1179. // 2) Copy over registries of interest
  1180. //
  1181. DsRolepLogPrint(( DEB_TRACE, "Making copy of IFM registry to temp directry: %ws\n", wszNewRegPath));
  1182. // First copy the system registry
  1183. wcscpy(wszTempPath, wszOldRegPath);
  1184. wcsncat(wszTempPath, L"\\system", (MAX_PATH)-wcslen(wszTempPath));
  1185. wcscpy(wszDest, wszNewRegPath);
  1186. wcsncat(wszDest, L"\\system", (MAX_PATH)-wcslen(wszDest));
  1187. if ( CopyFile( wszTempPath, wszDest, TRUE ) == FALSE ) {
  1188. Win32Err = GetLastError();
  1189. DsRolepLogPrint(( DEB_ERROR, "Failed to copy file from %ws to %ws with 0x%x\n", wszTempPath, wszDest, Win32Err));
  1190. goto cleanup;
  1191. }
  1192. // Then copy the security registry
  1193. wcscpy(wszTempPath, wszOldRegPath);
  1194. wcsncat(wszTempPath, L"\\security", (MAX_PATH)-wcslen(wszTempPath));
  1195. wcscpy(wszDest, wszNewRegPath);
  1196. wcsncat(wszDest, L"\\security", (MAX_PATH)-wcslen(wszDest));
  1197. if ( CopyFile( wszTempPath, wszDest, TRUE ) == FALSE ) {
  1198. Win32Err = GetLastError();
  1199. DsRolepLogPrint(( DEB_ERROR, "Failed to copy file from %ws to %ws with 0x%x\n", wszTempPath, wszDest, Win32Err));
  1200. goto cleanup;
  1201. }
  1202. cleanup:
  1203. if (Win32Err && wszNewRegPath[0] != L'\0') {
  1204. // Need to see if we can clean up what we did.
  1205. NtdspClearDirectory( wszNewRegPath , TRUE );
  1206. wszNewRegPath[0] = L'\0';
  1207. }
  1208. return(Win32Err);
  1209. }