public static void PresentResult(RawDisk disk) { byte[] data = disk.ReadClusters(0, (int)Math.Min(disk.ClusterCount, ClustersToRead)); string fatType = Encoding.ASCII.GetString(data, 82, 8); // Extended FAT parameters have a display name here. bool isFat = fatType.StartsWith("FAT"); bool isNTFS = Encoding.ASCII.GetString(data, 3, 4) == "NTFS"; // Optimization, if it's a known FS, we know it's not all zeroes. bool allZero = (!isNTFS || !isFat) && data.All(s => s == 0); Console.WriteLine("Size in bytes : {0:N0}", disk.SizeBytes); Console.WriteLine("Sectors : {0:N0}", disk.ClusterCount); Console.WriteLine("SectorSize : {0:N0}", disk.SectorSize); Console.WriteLine("ClusterCount : {0:N0}", disk.ClusterCount); Console.WriteLine("ClusterSize : {0:N0}", disk.ClusterSize); if (!isFat && !isNTFS) { Console.ForegroundColor = ConsoleColor.Red; } if (isNTFS) { Console.ForegroundColor = ConsoleColor.Green; } Console.WriteLine("Is NTFS : {0}", isNTFS); Console.ForegroundColor = DefaultColor; if (!isFat && !isNTFS) { Console.ForegroundColor = ConsoleColor.Red; } if (isFat) { Console.ForegroundColor = ConsoleColor.Green; } Console.WriteLine("Is FAT : {0}", isFat ? fatType : "False"); Console.ForegroundColor = DefaultColor; if (!allZero) { Console.ForegroundColor = ConsoleColor.Green; } else { Console.ForegroundColor = ConsoleColor.Red; } Console.WriteLine("All bytes zero: {0}", allZero); Console.ForegroundColor = DefaultColor; }
private static MftDetails GetMftDetails(RawDisk disk, BootSector boot) { byte[] mftFirst = disk.ReadClusters((long)boot.MFTCluster, 1); FileRecord rec = FileRecord.Parse(mftFirst, 0, (ushort)disk.SectorSize, (uint)(boot.MFTRecordSizeBytes / disk.SectorSize)); // Get DATA attrib // TODO: Handle multiple DATA attributes AttributeGeneric dataAttrib = null; foreach (Attribute attribute in rec.Attributes) { if (attribute.Type == AttributeType.DATA && attribute.AttributeName.Length == 0) { // Got it! dataAttrib = attribute as AttributeGeneric; break; } } Debug.Assert(dataAttrib != null); MftDetails res = new MftDetails(); // Get attribute data // Parse out extents if (dataAttrib.NonResidentFlag == ResidentFlag.Resident) { byte[] dataAttribData = dataAttrib.Data; res.MftSize = dataAttrib.ResidentHeader.ContentLength; res.MftExtents = DataFragment.ParseFragments(dataAttribData, dataAttribData.Length, 0, 0, 0); } else { res.MftSize = dataAttrib.NonResidentHeader.ContentSize; res.MftExtents = dataAttrib.NonResidentHeader.Fragments; } Debug.Assert(res.MftExtents != null); return(res); }
public static void CopyFile(string sourceFile, string dstFile) { // FileAttributes 0x20000000L = FILE_FLAG_NO_BUFFERING SafeFileHandle fileHandle = Win32Helper.CreateFile(sourceFile, (FileAccess)Program.FILE_READ_ATTRIBUTES, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal | (FileAttributes)0x20000000L, IntPtr.Zero); if (fileHandle.IsInvalid) { throw new ArgumentException("Invalid file: " + sourceFile); } //var driveWrapper = new DeviceIOControlWrapper(driveHandle); FilesystemDeviceWrapper fileWrapper = new FilesystemDeviceWrapper(fileHandle); FileExtentInfo[] extents = fileWrapper.FileSystemGetRetrievalPointers(); decimal totalSize = extents.Sum(s => (decimal)s.Size); decimal copiedBytes = 0; using (RawDisk disk = new RawDisk(char.ToUpper(sourceFile[0]))) { // Write to the source file using (FileStream fs = new FileStream(dstFile, FileMode.Create)) { // Copy all extents foreach (FileExtentInfo fileExtentInfo in extents) { // Copy chunks of data for (ulong offset = 0; offset < fileExtentInfo.Size; offset += 10000) { int currentSizeBytes = (int)Math.Min(10000, fileExtentInfo.Size - offset); byte[] data = disk.ReadClusters((long)(fileExtentInfo.Lcn + offset), currentSizeBytes); fs.Write(data, 0, data.Length); copiedBytes += currentSizeBytes; } } } } Debug.Assert(copiedBytes == totalSize); }
public override void Execute() { IEnumerable <char> volumeDrives = Utils.GetAllAvailableVolumes(); IEnumerable <int> harddiskVolumes = Utils.GetAllAvailableDrives(DiskNumberType.Volume); Console.WriteLine("You need to enter a volume on which to write and read. Note that this volume will be useless afterwards - do not chose anything by test volumes!"); Console.WriteLine("Select volume:"); List <int> options = new List <int>(); foreach (int harddiskVolume in harddiskVolumes) { try { using (RawDisk disk = new RawDisk(DiskNumberType.Volume, harddiskVolume)) { char[] driveLetters = DiskHelper.GetDriveLetters(disk.DosDeviceName.Remove(0, @"\\.\GLOBALROOT".Length)).Where(volumeDrives.Contains).ToArray(); Console.WriteLine(" {0:N0}: {1:N0} Bytes, Drive Letters: {2}", harddiskVolume, disk.SizeBytes, string.Join(", ", driveLetters)); options.Add(harddiskVolume); } } catch (Exception) { // Don't write it } } string vol; int selectedVol; do { Console.WriteLine("Enter #:"); vol = Console.ReadLine(); } while (!(int.TryParse(vol, out selectedVol) && options.Contains(selectedVol))); Console.WriteLine("Selected " + selectedVol + "."); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Are you sure? Type YES."); Console.ForegroundColor = ExampleUtilities.DefaultColor; bool allSuccess = false; string confirm = Console.ReadLine(); if (confirm == "YES") { Console.WriteLine("Confirmed - starting"); using (RawDisk disk = new RawDisk(DiskNumberType.Volume, selectedVol, FileAccess.ReadWrite)) { long chunks = disk.ClusterCount / ExampleUtilities.ClustersToRead; Console.WriteLine("Disk {0} is {1:N0} Bytes large.", disk.DosDeviceName, disk.SizeBytes); Console.WriteLine("Beginning random write in {0:N0} cluster chunks of {1:N0} Bytes each", ExampleUtilities.ClustersToRead, disk.ClusterSize); Console.WriteLine(" # of chunks: {0:N0}", chunks); byte[] chunkData = new byte[disk.ClusterSize * ExampleUtilities.ClustersToRead]; byte[] readData = new byte[disk.ClusterSize * ExampleUtilities.ClustersToRead]; Random rand = new Random(); StringBuilder blankLineBuilder = new StringBuilder(Console.BufferWidth); for (int i = 0; i < Console.BufferWidth; i++) { blankLineBuilder.Append(' '); } string blankLine = blankLineBuilder.ToString(); allSuccess = true; for (int chunk = 0; chunk < chunks; chunk++) { rand.NextBytes(chunkData); Console.Write("Chunk #{0}: ", chunk); try { // Write Console.Write("Writing ... "); disk.WriteClusters(chunkData, chunk * ExampleUtilities.ClustersToRead); // Read Console.Write("Reading ... "); disk.ReadClusters(readData, 0, chunk * ExampleUtilities.ClustersToRead, (int)ExampleUtilities.ClustersToRead); // Check if (chunkData.SequenceEqual(readData)) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Confirmed!"); Console.ForegroundColor = ExampleUtilities.DefaultColor; } else { allSuccess = false; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Failed!"); Console.ForegroundColor = ExampleUtilities.DefaultColor; Console.WriteLine("Presse enter to proceed."); Console.ReadLine(); } } catch (Exception ex) { allSuccess = false; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Error: " + ex.Message); Console.ForegroundColor = ExampleUtilities.DefaultColor; Console.WriteLine("Presse enter to proceed."); Console.ReadLine(); Console.CursorTop--; } Console.CursorTop--; Console.CursorLeft = 0; Console.Write(blankLine); Console.CursorTop--; Console.CursorLeft = 0; } } } else { Console.WriteLine("Aborted"); } if (allSuccess) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("All chunks were able to write and read successfully."); Console.ForegroundColor = ExampleUtilities.DefaultColor; } else { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Some chunks were unable to be read correctly."); Console.ForegroundColor = ExampleUtilities.DefaultColor; } }