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.

967 lines
27 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. copy.c
  5. Abstract:
  6. This is for supporting copying files, creating new files, and copying the registries to
  7. the remote server.
  8. Author:
  9. Sean Selitrennikoff - 4/5/98
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. WCHAR pConfigPath[MAX_PATH];
  15. WCHAR pSystemPath[MAX_PATH];
  16. WCHAR pCSDVersion[128];
  17. WCHAR pProcessorArchitecture[64];
  18. WCHAR pCurrentType[128];
  19. WCHAR pHalName[128];
  20. #if 0
  21. IMIRROR_MODIFY_DS_INFO ModifyInfo;
  22. #endif
  23. NTSTATUS
  24. AddCopyToDoItems(
  25. VOID
  26. )
  27. /*++
  28. Routine Description:
  29. This routine adds all the to do items necessary for copying files and registries to
  30. a server installation point, as well as creating new files necessary for remote boot.
  31. Arguments:
  32. None
  33. Return Value:
  34. STATUS_SUCCESS if it completes adding all the to do items properly.
  35. --*/
  36. {
  37. NTSTATUS Status;
  38. Status = AddToDoItem(CheckPartitions, NULL, 0);
  39. if (!NT_SUCCESS(Status)) {
  40. IMirrorHandleError(Status, IMirrorInitialize);
  41. return Status;
  42. }
  43. Status = AddToDoItem(CopyPartitions, NULL, 0);
  44. if (!NT_SUCCESS(Status)) {
  45. IMirrorHandleError(Status, IMirrorInitialize);
  46. return Status;
  47. }
  48. #if 0
  49. Status = AddToDoItem(PatchDSEntries, &ModifyInfo, sizeof(ModifyInfo)); // NOTE: This MUST come before MungeRegistry
  50. if (!NT_SUCCESS(Status)) {
  51. IMirrorHandleError(Status, IMirrorInitialize);
  52. return Status;
  53. }
  54. #endif
  55. return STATUS_SUCCESS;
  56. }
  57. //
  58. // Functions for processing each TO DO item
  59. //
  60. NTSTATUS
  61. CopyCopyPartitions(
  62. IN PVOID pBuffer,
  63. IN ULONG Length
  64. )
  65. /*++
  66. Routine Description:
  67. This routine verifies that any partition on the same disk as in the parameter pBuffer, has
  68. enough free space to hold all the files in the partition that is also in pBuffer.
  69. Arguments:
  70. pBuffer - Pointer to any arguments passed in the to do item.
  71. Length - Length, in bytes of the arguments.
  72. Return Value:
  73. STATUS_SUCCESS if it completes adding all the to do items properly.
  74. --*/
  75. {
  76. NTSTATUS Status;
  77. PLIST_ENTRY listEntry;
  78. PMIRROR_VOLUME_INFO mirrorVolInfo;
  79. ULONG numberPartitions;
  80. BOOLEAN copyRegistry = FALSE;
  81. ULONG NameLength;
  82. ULONG TmpUlong;
  83. ULONG baseLength;
  84. BOOLEAN gotUncPath = FALSE;
  85. IMirrorNowDoing(CopyPartitions, NULL);
  86. if (GlobalMirrorCfgInfo == NULL) {
  87. Status = CheckForPartitions( pBuffer, Length );
  88. if (!NT_SUCCESS(Status)) {
  89. IMirrorHandleError(Status, CopyPartitions);
  90. return Status;
  91. }
  92. }
  93. listEntry = GlobalMirrorCfgInfo->MirrorVolumeList.Flink;
  94. numberPartitions = 0;
  95. Status = STATUS_SUCCESS;
  96. while (listEntry != &GlobalMirrorCfgInfo->MirrorVolumeList) {
  97. mirrorVolInfo = (PMIRROR_VOLUME_INFO) CONTAINING_RECORD(
  98. listEntry,
  99. MIRROR_VOLUME_INFO,
  100. ListEntry
  101. );
  102. listEntry = listEntry->Flink;
  103. if (mirrorVolInfo->MirrorUncPath == NULL) {
  104. if (! gotUncPath) {
  105. gotUncPath = TRUE;
  106. NameLength = TMP_BUFFER_SIZE;
  107. Status = IMirrorGetMirrorDir( (PWCHAR)TmpBuffer,
  108. &NameLength);
  109. if (!NT_SUCCESS(Status)) {
  110. IMirrorHandleError(Status, CopyPartitions);
  111. return Status;
  112. }
  113. baseLength = lstrlenW( (PWCHAR) TmpBuffer );
  114. }
  115. swprintf( (PWCHAR)TmpBuffer2,
  116. L"\\Mirror%d",
  117. mirrorVolInfo->MirrorTableIndex );
  118. *((PWCHAR)(TmpBuffer)+baseLength) = L'\0';
  119. lstrcatW( (PWCHAR)TmpBuffer, (PWCHAR)TmpBuffer2 );
  120. NameLength = (lstrlenW( (PWCHAR)TmpBuffer ) + 1) * sizeof(WCHAR);
  121. mirrorVolInfo->MirrorUncPath = IMirrorAllocMem(NameLength);
  122. if (mirrorVolInfo->MirrorUncPath == NULL) {
  123. Status = STATUS_NO_MEMORY;
  124. IMirrorHandleError(Status, CopyPartitions);
  125. return Status;
  126. }
  127. RtlMoveMemory( mirrorVolInfo->MirrorUncPath,
  128. TmpBuffer,
  129. NameLength );
  130. }
  131. IMirrorNowDoing(CopyPartitions, mirrorVolInfo->MirrorUncPath);
  132. if (mirrorVolInfo->IsBootDisk) {
  133. copyRegistry = TRUE;
  134. }
  135. Status = AddToDoItem(CopyFiles, &mirrorVolInfo->DriveLetter, sizeof(WCHAR));
  136. if (!NT_SUCCESS(Status)) {
  137. IMirrorHandleError(Status, CheckPartitions);
  138. return Status;
  139. }
  140. numberPartitions++;
  141. }
  142. if (copyRegistry) {
  143. Status = AddToDoItem(CopyRegistry, pBuffer, Length);
  144. if (!NT_SUCCESS(Status)) {
  145. IMirrorHandleError(Status, CopyPartitions);
  146. return Status;
  147. }
  148. }
  149. //
  150. // write out the mirror config file locally so that if we restart, we
  151. // can retrieve the same config again.
  152. //
  153. if (numberPartitions && ! GlobalMirrorCfgInfo->SysPrepImage) {
  154. //
  155. // Write it out to \\SystemRoot\System32\IMirror.dat
  156. //
  157. Status = GetBaseDeviceName(L"\\SystemRoot", (PWCHAR)TmpBuffer2, sizeof(TmpBuffer2));
  158. wcscat((PWCHAR)TmpBuffer2, L"\\System32\\");
  159. wcscat((PWCHAR)TmpBuffer2, IMIRROR_DAT_FILE_NAME );
  160. Status = NtPathToDosPath((PWCHAR)TmpBuffer2, (PWCHAR)TmpBuffer, FALSE, FALSE);
  161. if (NT_SUCCESS(Status)) {
  162. Status = WriteMirrorConfigFile((PWCHAR) TmpBuffer);
  163. if (!NT_SUCCESS(Status)) {
  164. IMirrorHandleError(Status, CopyPartitions);
  165. }
  166. }
  167. }
  168. return Status;
  169. }
  170. NTSTATUS
  171. CopyCopyFiles(
  172. IN PVOID pBuffer,
  173. IN ULONG Length
  174. )
  175. /*++
  176. Routine Description:
  177. This routine copies all the files on the given drive to the remote server.
  178. Arguments:
  179. pBuffer - Pointer to any arguments passed in the to do item.
  180. The argument must be the drive letter
  181. Length - Length, in bytes of the arguments. Should be sizeof(WCHAR)
  182. Return Value:
  183. STATUS_SUCCESS if it completes the to do item properly.
  184. --*/
  185. {
  186. PLIST_ENTRY listEntry;
  187. PMIRROR_VOLUME_INFO mirrorVolInfo;
  188. NTSTATUS Status;
  189. WCHAR LocalBuffer[TMP_BUFFER_SIZE];
  190. WCHAR SourcePath[8];
  191. PCOPY_TREE_CONTEXT copyContext = NULL;
  192. BOOLEAN BackupPriviledged = FALSE;
  193. Status = IMirrorNowDoing(CopyFiles, NULL);
  194. if ( Status != NO_ERROR ) {
  195. return Status;
  196. }
  197. if (GlobalMirrorCfgInfo == NULL) {
  198. Status = CheckForPartitions( pBuffer, Length );
  199. if (!NT_SUCCESS(Status)) {
  200. IMirrorHandleError(Status, CopyFiles);
  201. return Status;
  202. }
  203. }
  204. if (Length != sizeof(WCHAR) || pBuffer == NULL) {
  205. IMirrorHandleError(ERROR_INVALID_DRIVE, CopyFiles);
  206. return ERROR_INVALID_DRIVE;
  207. }
  208. listEntry = GlobalMirrorCfgInfo->MirrorVolumeList.Flink;
  209. while (listEntry != &GlobalMirrorCfgInfo->MirrorVolumeList) {
  210. mirrorVolInfo = (PMIRROR_VOLUME_INFO) CONTAINING_RECORD(
  211. listEntry,
  212. MIRROR_VOLUME_INFO,
  213. ListEntry
  214. );
  215. listEntry = listEntry->Flink;
  216. if (mirrorVolInfo->DriveLetter == *(PWCHAR)pBuffer) {
  217. break;
  218. }
  219. mirrorVolInfo = NULL;
  220. }
  221. if (mirrorVolInfo == NULL) {
  222. IMirrorHandleError(ERROR_INVALID_DRIVE, CopyFiles);
  223. return ERROR_INVALID_DRIVE;
  224. }
  225. //
  226. // Create root directory, don't fail if it already exists
  227. //
  228. if (!CreateDirectory(mirrorVolInfo->MirrorUncPath, NULL)) {
  229. Status = GetLastError();
  230. if (Status != ERROR_ALREADY_EXISTS) {
  231. IMirrorHandleError(Status, CopyFiles);
  232. return Status;
  233. }
  234. }
  235. //
  236. // create the config file in this mirror root
  237. //
  238. lstrcpyW( LocalBuffer, mirrorVolInfo->MirrorUncPath );
  239. wcscat( LocalBuffer, L"\\");
  240. wcscat( LocalBuffer, IMIRROR_DAT_FILE_NAME );
  241. Status = WriteMirrorConfigFile(LocalBuffer);
  242. if (!NT_SUCCESS(Status)) {
  243. IMirrorHandleError(Status, CopyFiles);
  244. return Status;
  245. }
  246. if (!GlobalMirrorCfgInfo->SysPrepImage) {
  247. //
  248. // create staging directory if one is required
  249. //
  250. lstrcpyW( LocalBuffer, mirrorVolInfo->MirrorUncPath );
  251. wcscat( LocalBuffer, L"\\Staging");
  252. if (!CreateDirectory( LocalBuffer, NULL)) {
  253. Status = GetLastError();
  254. if (Status != ERROR_ALREADY_EXISTS) {
  255. IMirrorHandleError(Status, CopyFiles);
  256. return Status;
  257. }
  258. }
  259. }
  260. if (mirrorVolInfo->PartitionActive) {
  261. //
  262. // copy the boot code to the server
  263. //
  264. lstrcpyW( LocalBuffer, mirrorVolInfo->MirrorUncPath );
  265. wcscat( LocalBuffer, L"\\BootCode.dat");
  266. Status = SaveBootSector( mirrorVolInfo->DiskNumber,
  267. mirrorVolInfo->PartitionNumber,
  268. mirrorVolInfo->BlockSize,
  269. LocalBuffer );
  270. if (Status != STATUS_SUCCESS) {
  271. IMirrorHandleError(Status, CopyFiles);
  272. return Status;
  273. }
  274. }
  275. //
  276. // Create UserData directory, don't fail if it already exists
  277. //
  278. lstrcpyW( LocalBuffer, mirrorVolInfo->MirrorUncPath );
  279. wcscat( LocalBuffer, L"\\UserData");
  280. if (!CreateDirectory( LocalBuffer, NULL)) {
  281. Status = GetLastError();
  282. if (Status != ERROR_ALREADY_EXISTS) {
  283. IMirrorHandleError(Status, CopyFiles);
  284. return Status;
  285. }
  286. }
  287. //
  288. // set up the dest path ready for really long file names.
  289. //
  290. if (*(mirrorVolInfo->MirrorUncPath) == L'\\' &&
  291. *(mirrorVolInfo->MirrorUncPath+1) == L'\\') {
  292. if (*(mirrorVolInfo->MirrorUncPath+2) == L'?') {
  293. // dest is \\?\..., it's of the correct format
  294. lstrcpyW( LocalBuffer, mirrorVolInfo->MirrorUncPath );
  295. } else {
  296. // dest is \\billg1\imirror
  297. // format should be \\?\UNC\billg1\imirror
  298. lstrcpyW( LocalBuffer, L"\\\\?\\UNC" );
  299. lstrcatW( LocalBuffer, mirrorVolInfo->MirrorUncPath + 1 );
  300. }
  301. } else {
  302. // dest is something like X:
  303. // format should be \\?\X:
  304. lstrcpyW( LocalBuffer, L"\\\\?\\" );
  305. lstrcatW( LocalBuffer, mirrorVolInfo->MirrorUncPath );
  306. }
  307. wcscat( LocalBuffer, L"\\UserData");
  308. SourcePath[0] = L'\\'; // format is L"\\\\?\\E:"
  309. SourcePath[1] = L'\\';
  310. SourcePath[2] = L'?';
  311. SourcePath[3] = L'\\';
  312. SourcePath[4] = mirrorVolInfo->DriveLetter;
  313. SourcePath[5] = L':';
  314. SourcePath[6] = L'\\';
  315. SourcePath[7] = L'\0';
  316. //
  317. // Copy all the files
  318. //
  319. Status = AllocateCopyTreeContext( &copyContext, TRUE );
  320. if (Status != ERROR_SUCCESS) {
  321. IMirrorHandleError(Status, CopyFiles);
  322. return Status;
  323. }
  324. if (RTEnableBackupRestorePrivilege()) {
  325. BackupPriviledged = TRUE;
  326. }
  327. Status = CopyTree( copyContext,
  328. (BOOLEAN) (mirrorVolInfo->PartitionType == PARTITION_IFS),
  329. &SourcePath[0],
  330. LocalBuffer );
  331. if (BackupPriviledged) {
  332. RTDisableBackupRestorePrivilege();
  333. }
  334. if (copyContext->Cancelled) {
  335. //
  336. // since the copy was cancelled, let's bail on the rest of the processing.
  337. //
  338. ClearAllToDoItems(TRUE);
  339. }
  340. FreeCopyTreeContext( copyContext );
  341. if (!NT_SUCCESS(Status)) {
  342. IMirrorHandleError(Status, CopyFiles);
  343. return(Status);
  344. }
  345. return Status;
  346. }
  347. NTSTATUS
  348. CopyCopyRegistry(
  349. IN PVOID pBuffer,
  350. IN ULONG Length
  351. )
  352. /*++
  353. Routine Description:
  354. This routine copies the currently running registries to the server.
  355. Arguments:
  356. pBuffer - Pointer to any arguments passed in the to do item.
  357. Length - Length, in bytes of the arguments.
  358. Return Value:
  359. STATUS_SUCCESS if it completes the to do item properly.
  360. --*/
  361. {
  362. NTSTATUS Status;
  363. PLIST_ENTRY listEntry;
  364. ULONG Error;
  365. PMIRROR_VOLUME_INFO mirrorVolInfo;
  366. IMirrorNowDoing(CopyRegistry, NULL);
  367. if (GlobalMirrorCfgInfo == NULL) {
  368. Status = CheckForPartitions( pBuffer, Length );
  369. if (!NT_SUCCESS(Status)) {
  370. IMirrorHandleError(Status, CopyRegistry);
  371. return Status;
  372. }
  373. }
  374. listEntry = GlobalMirrorCfgInfo->MirrorVolumeList.Flink;
  375. while (listEntry != &GlobalMirrorCfgInfo->MirrorVolumeList) {
  376. mirrorVolInfo = (PMIRROR_VOLUME_INFO) CONTAINING_RECORD(
  377. listEntry,
  378. MIRROR_VOLUME_INFO,
  379. ListEntry
  380. );
  381. listEntry = listEntry->Flink;
  382. if (mirrorVolInfo->IsBootDisk) {
  383. break;
  384. }
  385. mirrorVolInfo = NULL;
  386. }
  387. if (mirrorVolInfo == NULL) {
  388. IMirrorHandleError(ERROR_INVALID_DRIVE, CopyRegistry);
  389. return ERROR_INVALID_DRIVE;
  390. }
  391. //
  392. // Now do registry backup
  393. //
  394. Error = DoFullRegBackup( mirrorVolInfo->MirrorUncPath );
  395. if (Error != NO_ERROR) {
  396. IMirrorHandleError(Error, CopyRegistry);
  397. return STATUS_UNSUCCESSFUL;
  398. }
  399. return STATUS_SUCCESS;
  400. }
  401. NTSTATUS
  402. WriteMirrorConfigFile(
  403. PWCHAR DestFile
  404. )
  405. {
  406. ULONG bufferSize;
  407. PCHAR buffer;
  408. PLIST_ENTRY listEntry;
  409. PMIRROR_VOLUME_INFO mirrorVolInfo;
  410. PMIRROR_VOLUME_INFO_FILE mirrorVolInfoFile;
  411. PMIRROR_CFG_INFO_FILE mirrorInfoFile;
  412. ULONG pathLength;
  413. ULONG systemPathLength;
  414. ULONG csdVersionLength;
  415. ULONG processorArchitectureLength;
  416. ULONG currentTypeLength;
  417. ULONG halNameLength;
  418. PWCHAR nextString;
  419. NTSTATUS Status;
  420. HANDLE fileHandle;
  421. retryWriteConfig:
  422. mirrorInfoFile = NULL;
  423. Status = STATUS_SUCCESS;
  424. fileHandle = INVALID_HANDLE_VALUE;
  425. ASSERT(GlobalMirrorCfgInfo != NULL);
  426. systemPathLength = (lstrlenW( GlobalMirrorCfgInfo->SystemPath ) + 1) * sizeof(WCHAR);
  427. csdVersionLength = (lstrlenW( GlobalMirrorCfgInfo->CSDVersion ) + 1) * sizeof(WCHAR);
  428. processorArchitectureLength = (lstrlenW( GlobalMirrorCfgInfo->ProcessorArchitecture ) + 1) * sizeof(WCHAR);
  429. currentTypeLength = (lstrlenW( GlobalMirrorCfgInfo->CurrentType ) + 1) * sizeof(WCHAR);
  430. halNameLength = (lstrlenW( GlobalMirrorCfgInfo->HalName ) + 1) * sizeof(WCHAR);
  431. bufferSize = sizeof( MIRROR_CFG_INFO_FILE ) +
  432. (sizeof( MIRROR_VOLUME_INFO_FILE ) *
  433. (GlobalMirrorCfgInfo->NumberVolumes - 1)) +
  434. systemPathLength +
  435. csdVersionLength +
  436. processorArchitectureLength +
  437. currentTypeLength +
  438. halNameLength;
  439. listEntry = GlobalMirrorCfgInfo->MirrorVolumeList.Flink;
  440. while (listEntry != &GlobalMirrorCfgInfo->MirrorVolumeList) {
  441. mirrorVolInfo = (PMIRROR_VOLUME_INFO) CONTAINING_RECORD(
  442. listEntry,
  443. MIRROR_VOLUME_INFO,
  444. ListEntry
  445. );
  446. listEntry = listEntry->Flink;
  447. bufferSize += ((lstrlenW( mirrorVolInfo->MirrorUncPath ) + 1) * sizeof(WCHAR)) +
  448. ((lstrlenW( mirrorVolInfo->VolumeLabel ) + 1) * sizeof(WCHAR)) +
  449. ((lstrlenW( mirrorVolInfo->NtName ) + 1) * sizeof(WCHAR)) +
  450. ((lstrlenW( mirrorVolInfo->ArcName ) + 1) * sizeof(WCHAR));
  451. }
  452. mirrorInfoFile = (PMIRROR_CFG_INFO_FILE) IMirrorAllocMem( bufferSize );
  453. if (mirrorInfoFile == NULL) {
  454. Status = STATUS_NO_MEMORY;
  455. goto exitWriteFile;
  456. }
  457. mirrorInfoFile->MirrorVersion = IMIRROR_CURRENT_VERSION;
  458. mirrorInfoFile->FileLength = bufferSize;
  459. mirrorInfoFile->NumberVolumes = GlobalMirrorCfgInfo->NumberVolumes;
  460. mirrorInfoFile->SystemPathLength = systemPathLength;
  461. mirrorInfoFile->CSDVersionLength = csdVersionLength;
  462. mirrorInfoFile->ProcessorArchitectureLength = processorArchitectureLength;
  463. mirrorInfoFile->CurrentTypeLength = currentTypeLength;
  464. mirrorInfoFile->HalNameLength = halNameLength;
  465. mirrorInfoFile->SysPrepImage = GlobalMirrorCfgInfo->SysPrepImage;
  466. mirrorInfoFile->Debug = GlobalMirrorCfgInfo->Debug;
  467. mirrorInfoFile->MajorVersion = GlobalMirrorCfgInfo->MajorVersion;
  468. mirrorInfoFile->MinorVersion = GlobalMirrorCfgInfo->MinorVersion;
  469. mirrorInfoFile->BuildNumber = GlobalMirrorCfgInfo->BuildNumber;
  470. mirrorInfoFile->KernelFileVersionMS = GlobalMirrorCfgInfo->KernelFileVersionMS;
  471. mirrorInfoFile->KernelFileVersionLS = GlobalMirrorCfgInfo->KernelFileVersionLS;
  472. mirrorInfoFile->KernelFileFlags = GlobalMirrorCfgInfo->KernelFileFlags;
  473. mirrorVolInfoFile = &mirrorInfoFile->Volumes[mirrorInfoFile->NumberVolumes];
  474. nextString = (PWCHAR) mirrorVolInfoFile;
  475. mirrorInfoFile->SystemPathOffset = (ULONG)((PCHAR) nextString - (PCHAR) mirrorInfoFile);
  476. lstrcpyW( nextString, GlobalMirrorCfgInfo->SystemPath );
  477. nextString += systemPathLength / sizeof(WCHAR);
  478. mirrorInfoFile->CSDVersionOffset = (ULONG)((PCHAR) nextString - (PCHAR) mirrorInfoFile);
  479. lstrcpyW( nextString, GlobalMirrorCfgInfo->CSDVersion );
  480. nextString += csdVersionLength / sizeof(WCHAR);
  481. mirrorInfoFile->ProcessorArchitectureOffset = (ULONG)((PCHAR) nextString - (PCHAR) mirrorInfoFile);
  482. lstrcpyW( nextString, GlobalMirrorCfgInfo->ProcessorArchitecture );
  483. nextString += processorArchitectureLength / sizeof(WCHAR);
  484. mirrorInfoFile->CurrentTypeOffset = (ULONG)((PCHAR) nextString - (PCHAR) mirrorInfoFile);
  485. lstrcpyW( nextString, GlobalMirrorCfgInfo->CurrentType );
  486. nextString += currentTypeLength / sizeof(WCHAR);
  487. mirrorInfoFile->HalNameOffset = (ULONG)((PCHAR) nextString - (PCHAR) mirrorInfoFile);
  488. lstrcpyW( nextString, GlobalMirrorCfgInfo->HalName );
  489. nextString += halNameLength / sizeof(WCHAR);
  490. listEntry = GlobalMirrorCfgInfo->MirrorVolumeList.Flink;
  491. mirrorVolInfoFile = &mirrorInfoFile->Volumes[0];
  492. while (listEntry != &GlobalMirrorCfgInfo->MirrorVolumeList) {
  493. mirrorVolInfo = (PMIRROR_VOLUME_INFO) CONTAINING_RECORD(
  494. listEntry,
  495. MIRROR_VOLUME_INFO,
  496. ListEntry
  497. );
  498. listEntry = listEntry->Flink;
  499. mirrorVolInfoFile->MirrorTableIndex = mirrorVolInfo->MirrorTableIndex;
  500. mirrorVolInfoFile->DriveLetter = mirrorVolInfo->DriveLetter;
  501. mirrorVolInfoFile->PartitionType = mirrorVolInfo->PartitionType;
  502. mirrorVolInfoFile->PartitionActive = mirrorVolInfo->PartitionActive;
  503. mirrorVolInfoFile->IsBootDisk = mirrorVolInfo->IsBootDisk;
  504. mirrorVolInfoFile->CompressedVolume = mirrorVolInfo->CompressedVolume;
  505. mirrorVolInfoFile->DiskSignature = mirrorVolInfo->DiskSignature;
  506. mirrorVolInfoFile->BlockSize = mirrorVolInfo->BlockSize;
  507. mirrorVolInfoFile->LastUSNMirrored = mirrorVolInfo->LastUSNMirrored;
  508. mirrorVolInfoFile->FileSystemFlags = mirrorVolInfo->FileSystemFlags;
  509. wcscpy(mirrorVolInfoFile->FileSystemName, mirrorVolInfo->FileSystemName);
  510. mirrorVolInfoFile->DiskSpaceUsed = mirrorVolInfo->DiskSpaceUsed;
  511. mirrorVolInfoFile->StartingOffset = mirrorVolInfo->StartingOffset;
  512. mirrorVolInfoFile->PartitionSize = mirrorVolInfo->PartitionSize;
  513. mirrorVolInfoFile->DiskNumber = mirrorVolInfo->DiskNumber;
  514. mirrorVolInfoFile->PartitionNumber = mirrorVolInfo->PartitionNumber;
  515. // set the path in the config file relative to the root of this
  516. // image. As example, set it to L"\Mirror1\UserData"
  517. swprintf( (PWCHAR)TmpBuffer2,
  518. L"\\Mirror%d\\UserData",
  519. mirrorVolInfo->MirrorTableIndex );
  520. pathLength = (lstrlenW( (PWCHAR)TmpBuffer2 ) + 1) * sizeof(WCHAR);
  521. mirrorVolInfoFile->MirrorUncLength = pathLength;
  522. mirrorVolInfoFile->MirrorUncPathOffset = (ULONG)((PCHAR) nextString - (PCHAR) mirrorInfoFile);
  523. lstrcpyW( nextString, (PWCHAR)TmpBuffer2 );
  524. nextString += pathLength / sizeof(WCHAR);
  525. pathLength = (lstrlenW( mirrorVolInfo->VolumeLabel ) + 1) * sizeof(WCHAR);
  526. mirrorVolInfoFile->VolumeLabelLength = pathLength;
  527. mirrorVolInfoFile->VolumeLabelOffset = (ULONG)((PCHAR) nextString - (PCHAR) mirrorInfoFile);
  528. lstrcpyW( nextString, mirrorVolInfo->VolumeLabel );
  529. nextString += pathLength / sizeof(WCHAR);
  530. pathLength = (lstrlenW( mirrorVolInfo->NtName ) + 1) * sizeof(WCHAR);
  531. mirrorVolInfoFile->NtNameLength = pathLength;
  532. mirrorVolInfoFile->NtNameOffset = (ULONG)((PCHAR) nextString - (PCHAR) mirrorInfoFile);
  533. lstrcpyW( nextString, mirrorVolInfo->NtName );
  534. nextString += pathLength / sizeof(WCHAR);
  535. pathLength = (lstrlenW( mirrorVolInfo->ArcName ) + 1) * sizeof(WCHAR);
  536. mirrorVolInfoFile->ArcNameLength = pathLength;
  537. mirrorVolInfoFile->ArcNameOffset = (ULONG)((PCHAR) nextString - (PCHAR) mirrorInfoFile);
  538. lstrcpyW( nextString, mirrorVolInfo->ArcName );
  539. nextString += pathLength / sizeof(WCHAR);
  540. mirrorVolInfoFile++;
  541. //
  542. // call off to the wizard to tell him what the system directory
  543. // is if we have a valid one.
  544. //
  545. if (mirrorVolInfo->IsBootDisk && (systemPathLength > 3 * sizeof(WCHAR))) {
  546. //
  547. // pass it in the form of "MirrorX\UserData\WinNT"
  548. // so we have to skip the C: in the systempath
  549. //
  550. swprintf( (PWCHAR)TmpBuffer2,
  551. L"Mirror%d\\UserData",
  552. mirrorVolInfo->MirrorTableIndex );
  553. lstrcatW( (PWCHAR)TmpBuffer2, GlobalMirrorCfgInfo->SystemPath + 2 );
  554. IMirrorSetSystemPath( (PWCHAR) TmpBuffer2,
  555. (lstrlenW( (PWCHAR) TmpBuffer2)) );
  556. }
  557. }
  558. fileHandle = CreateFile( DestFile,
  559. GENERIC_WRITE,
  560. 0,
  561. NULL,
  562. CREATE_ALWAYS,
  563. FILE_ATTRIBUTE_ARCHIVE,
  564. NULL );
  565. if (fileHandle == INVALID_HANDLE_VALUE) {
  566. Status = GetLastError();
  567. goto exitWriteFile;
  568. }
  569. if (!WriteFile( fileHandle,
  570. mirrorInfoFile,
  571. bufferSize,
  572. &bufferSize,
  573. NULL)) {
  574. Status = GetLastError();
  575. goto exitWriteFile;
  576. }
  577. exitWriteFile:
  578. if (fileHandle != INVALID_HANDLE_VALUE) {
  579. CloseHandle( fileHandle );
  580. fileHandle = INVALID_HANDLE_VALUE;
  581. }
  582. if (mirrorInfoFile) {
  583. IMirrorFreeMem( mirrorInfoFile );
  584. mirrorInfoFile = NULL;
  585. }
  586. if (Status != ERROR_SUCCESS) {
  587. DWORD errorCase;
  588. errorCase = ReportCopyError( NULL,
  589. DestFile,
  590. COPY_ERROR_ACTION_CREATE_FILE,
  591. Status );
  592. if (errorCase == STATUS_RETRY) {
  593. goto retryWriteConfig;
  594. }
  595. if ( errorCase == ERROR_SUCCESS ) {
  596. Status = ERROR_SUCCESS;
  597. }
  598. }
  599. return Status;
  600. }
  601. #define MIN_BOOT_SECTOR_BLOCK_SIZE 512
  602. NTSTATUS
  603. SaveBootSector(
  604. DWORD DiskNumber,
  605. DWORD PartitionNumber,
  606. DWORD BlockSize,
  607. PWCHAR DestFile
  608. )
  609. {
  610. NTSTATUS Status;
  611. UNICODE_STRING UnicodeString;
  612. IO_STATUS_BLOCK IoStatusBlock;
  613. DWORD bufferSize;
  614. OBJECT_ATTRIBUTES ObjectAttributes;
  615. HANDLE bootSectorHandle = INVALID_HANDLE_VALUE;
  616. HANDLE fileHandle = INVALID_HANDLE_VALUE;
  617. PUCHAR AlignedBuffer;
  618. PUCHAR allocatedBuffer = NULL;
  619. swprintf((PWCHAR)TmpBuffer, L"\\Device\\Harddisk%d\\Partition%d", DiskNumber, PartitionNumber );
  620. RtlInitUnicodeString(&UnicodeString, (PWCHAR)TmpBuffer);
  621. InitializeObjectAttributes(&ObjectAttributes,
  622. &UnicodeString,
  623. OBJ_CASE_INSENSITIVE,
  624. NULL,
  625. NULL
  626. );
  627. Status = NtCreateFile(&bootSectorHandle,
  628. (ACCESS_MASK)FILE_GENERIC_READ,
  629. &ObjectAttributes,
  630. &IoStatusBlock,
  631. NULL,
  632. FILE_ATTRIBUTE_NORMAL,
  633. FILE_SHARE_READ | FILE_SHARE_WRITE,
  634. FILE_OPEN,
  635. FILE_SYNCHRONOUS_IO_NONALERT,
  636. NULL,
  637. 0
  638. );
  639. if (!NT_SUCCESS(Status)) {
  640. IMirrorHandleError(Status, CopyPartitions);
  641. goto exitSaveBootSector;
  642. }
  643. if (BlockSize < MIN_BOOT_SECTOR_BLOCK_SIZE) {
  644. BlockSize = MIN_BOOT_SECTOR_BLOCK_SIZE;
  645. }
  646. if (BlockSize + MIN_BOOT_SECTOR_BLOCK_SIZE > TMP_BUFFER_SIZE) {
  647. allocatedBuffer = IMirrorAllocMem( BlockSize + MIN_BOOT_SECTOR_BLOCK_SIZE );
  648. if (allocatedBuffer == NULL) {
  649. Status = STATUS_NO_MEMORY;
  650. goto exitSaveBootSector;
  651. }
  652. AlignedBuffer = ALIGN(allocatedBuffer, MIN_BOOT_SECTOR_BLOCK_SIZE);
  653. } else {
  654. AlignedBuffer = ALIGN(TmpBuffer, MIN_BOOT_SECTOR_BLOCK_SIZE);
  655. }
  656. Status = NtReadFile(bootSectorHandle,
  657. NULL,
  658. NULL,
  659. NULL,
  660. &IoStatusBlock,
  661. AlignedBuffer,
  662. BlockSize,
  663. NULL,
  664. NULL
  665. );
  666. if (!NT_SUCCESS(Status)) {
  667. IMirrorHandleError(Status, CopyPartitions);
  668. goto exitSaveBootSector;
  669. }
  670. fileHandle = CreateFile( DestFile,
  671. GENERIC_WRITE,
  672. 0,
  673. NULL,
  674. CREATE_ALWAYS,
  675. FILE_ATTRIBUTE_ARCHIVE,
  676. NULL );
  677. if (fileHandle == INVALID_HANDLE_VALUE) {
  678. Status = GetLastError();
  679. goto exitSaveBootSector;
  680. }
  681. if (!WriteFile( fileHandle,
  682. AlignedBuffer,
  683. BlockSize,
  684. &bufferSize,
  685. NULL)) {
  686. Status = GetLastError();
  687. } else {
  688. Status = STATUS_SUCCESS;
  689. }
  690. exitSaveBootSector:
  691. if (bootSectorHandle != INVALID_HANDLE_VALUE) {
  692. NtClose(bootSectorHandle);
  693. }
  694. if (fileHandle != INVALID_HANDLE_VALUE) {
  695. NtClose(fileHandle);
  696. }
  697. if (allocatedBuffer) {
  698. IMirrorFreeMem( allocatedBuffer );
  699. }
  700. if (!NT_SUCCESS(Status)) {
  701. IMirrorHandleError(Status, CopyPartitions);
  702. }
  703. return STATUS_SUCCESS;
  704. }