예제 #1
0
        protected override void DoRun()
        {
            if (DiskSize <= 0)
            {
                DisplayHelp();
                return;
            }

            using (VirtualDisk sourceDisk = VirtualDisk.OpenDisk(_sourceFile.Value, FileAccess.Read, UserName, Password))
                using (VirtualDisk destDisk = VirtualDisk.CreateDisk(OutputDiskType, OutputDiskVariant, _destFile.Value, DiskParameters, UserName, Password))
                {
                    if (destDisk is DiscUtils.Vhd.Disk)
                    {
                        ((DiscUtils.Vhd.Disk)destDisk).AutoCommitFooter = false;
                    }

                    // Copy the MBR from the source disk, and invent a new signature for this new disk
                    destDisk.SetMasterBootRecord(sourceDisk.GetMasterBootRecord());
                    destDisk.Signature = new Random().Next();

                    SparseStream   sourcePartStream = SparseStream.FromStream(sourceDisk.Partitions[0].Open(), Ownership.None);
                    NtfsFileSystem sourceNtfs       = new NtfsFileSystem(sourcePartStream);

                    // Copy the OS boot code into memory, so we can apply it when formatting the new disk
                    byte[] bootCode;
                    using (Stream bootStream = sourceNtfs.OpenFile("$Boot", FileMode.Open, FileAccess.Read))
                    {
                        bootCode = new byte[bootStream.Length];
                        int totalRead = 0;
                        while (totalRead < bootCode.Length)
                        {
                            totalRead += bootStream.Read(bootCode, totalRead, bootCode.Length - totalRead);
                        }
                    }

                    // Partition the new disk with a single NTFS partition
                    BiosPartitionTable.Initialize(destDisk, WellKnownPartitionType.WindowsNtfs);
                    VolumeManager volMgr = new VolumeManager(destDisk);

                    string label = _labelSwitch.IsPresent ? _labelSwitch.Value : sourceNtfs.VolumeLabel;
                    using (NtfsFileSystem destNtfs = NtfsFileSystem.Format(volMgr.GetLogicalVolumes()[0], label, bootCode))
                    {
                        destNtfs.SetSecurity(@"\", sourceNtfs.GetSecurity(@"\"));
                        destNtfs.NtfsOptions.ShortNameCreation = ShortFileNameOption.Disabled;

                        sourceNtfs.NtfsOptions.HideHiddenFiles = false;
                        sourceNtfs.NtfsOptions.HideSystemFiles = false;
                        CopyFiles(sourceNtfs, destNtfs, @"\", true);

                        if (destNtfs.FileExists(@"\boot\BCD"))
                        {
                            // Force all boot entries in the BCD to point to the newly created NTFS partition - does _not_ cope with
                            // complex multi-volume / multi-boot scenarios at all.
                            using (Stream bcdStream = destNtfs.OpenFile(@"\boot\BCD", FileMode.Open, FileAccess.ReadWrite))
                            {
                                using (RegistryHive hive = new RegistryHive(bcdStream))
                                {
                                    Store store = new Store(hive.Root);
                                    foreach (var obj in store.Objects)
                                    {
                                        foreach (var elem in obj.Elements)
                                        {
                                            if (elem.Format == DiscUtils.BootConfig.ElementFormat.Device)
                                            {
                                                elem.Value = DiscUtils.BootConfig.ElementValue.ForDevice(elem.Value.ParentObject, volMgr.GetPhysicalVolumes()[0]);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
        }