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.

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