private static void ExampleBitmap() { const string drive = @"\\.\C:"; Console.WriteLine(@"## Exmaple on {0} ##", drive); SafeFileHandle volumeHandle = CreateFile(drive, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero); if (volumeHandle.IsInvalid) { int lastError = Marshal.GetLastWin32Error(); Console.WriteLine(@"!! Invalid {0}; Error ({1}): {2}", drive, lastError, new Win32Exception(lastError).Message); Console.WriteLine(); return; } using (FilesystemDeviceWrapper fsIo = new FilesystemDeviceWrapper(volumeHandle, true)) { // Bitmap VOLUME_BITMAP_BUFFER bitmap = fsIo.FileSystemGetVolumeBitmap(); Console.WriteLine("Bitmap: {0:N0} clusters", bitmap.Buffer.Length); int width = 10000; int height = (int)Math.Ceiling(bitmap.BitmapSize / (double)width); Console.WriteLine("W/H: {0:N0} / {1:N0}", width, height); using (Bitmap bmp = new Bitmap(width, height)) { using (Graphics g = Graphics.FromImage(bmp)) g.Clear(Color.Green); for (int i = 0; i < bitmap.Buffer.Length; i++) { int x = i % width; int y = i / width; if (bitmap.Buffer[i]) { bmp.SetPixel(x, y, Color.Black); } else { bmp.SetPixel(x, y, Color.White); } if (y % 100 == 0 && x == 0) { Console.WriteLine("{0:N0} / {1:N0}", y, height); } } bmp.Save("test.png", ImageFormat.Png); } } Console.WriteLine(); }
private static void ExampleBitmap() { const string drive = @"\\.\C:"; Console.WriteLine(@"## Exmaple on {0} ##", drive); SafeFileHandle volumeHandle = CreateFile(drive, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero); if (volumeHandle.IsInvalid) { int lastError = Marshal.GetLastWin32Error(); Console.WriteLine(@"!! Invalid {0}; Error ({1}): {2}", drive, lastError, new Win32Exception(lastError).Message); Console.WriteLine(); return; } using (FilesystemDeviceWrapper fsIo = new FilesystemDeviceWrapper(volumeHandle, true)) { // Bitmap VOLUME_BITMAP_BUFFER bitmap = fsIo.FileSystemGetVolumeBitmap(); Console.WriteLine("Bitmap: {0:N0} clusters", bitmap.Buffer.Length); int width = 10000; int height = (int)Math.Ceiling(bitmap.BitmapSize / (double)width); Console.WriteLine("W/H: {0:N0} / {1:N0}", width, height); using (Bitmap bmp = new Bitmap(width, height)) { using (Graphics g = Graphics.FromImage(bmp)) g.Clear(Color.Green); for (int i = 0; i < bitmap.Buffer.Length; i++) { int x = i % width; int y = i / width; if (bitmap.Buffer[i]) bmp.SetPixel(x, y, Color.Black); else bmp.SetPixel(x, y, Color.White); if (y % 100 == 0 && x == 0) Console.WriteLine("{0:N0} / {1:N0}", y, height); } bmp.Save("test.png", ImageFormat.Png); } } Console.WriteLine(); }
public void SparseFile() { byte[] randomData = new byte[35 * 4096]; _random.NextBytes(randomData); // Clear the 16 * 4096 -> 32 * 4096 range Array.Clear(randomData, 16 * 4096, 16 * 4096); using (TempFile tmpFile = new TempFile()) { // Create a file File.WriteAllBytes(tmpFile.File.FullName, randomData); using (FilesystemDeviceWrapper wrapper = Win32.GetFileWrapper(tmpFile.File.FullName)) { wrapper.FileSystemSetSparseFile(true); wrapper.FileSystemSetZeroData(16 * 4096, 16 * 4096); FILE_ALLOCATED_RANGE_BUFFER[] rangesData = wrapper.FileSystemQueryAllocatedRanges(0, randomData.Length); // We should have 2 ranges on non-zero data Assert.AreEqual(2, rangesData.Length); } // Discover it via the NTFS lib char driveLetter = tmpFile.File.FullName[0]; RawDisk disk = new RawDisk(driveLetter); NTFSDiskProvider provider = new NTFSDiskProvider(disk); NTFSWrapper ntfsWrapper = new NTFSWrapper(provider, 0); NtfsDirectory ntfsDir = NTFSHelpers.OpenDir(ntfsWrapper, tmpFile.File.DirectoryName); NtfsFile ntfsFile = NTFSHelpers.OpenFile(ntfsDir, tmpFile.File.Name); Assert.IsNotNull(ntfsFile); Assert.IsTrue(tmpFile.File.Attributes.HasFlag(FileAttributes.SparseFile)); AttributeData attributeData = ntfsFile.MFTRecord.Attributes.OfType <AttributeData>().Single(); Assert.IsTrue(attributeData.DataFragments.Length > 1); Assert.IsTrue(attributeData.DataFragments.Any(s => s.IsSparseFragment)); // Read it using (Stream actualStream = File.OpenRead(tmpFile.File.FullName)) using (Stream ntfsStream = ntfsFile.OpenRead()) { bool equal = StreamUtils.CompareStreams(actualStream, ntfsStream); Assert.IsTrue(equal); } } }
private static void ExampleCompression() { string file = Path.GetTempFileName(); try { // Write file data using (FileStream fs = File.OpenWrite(file)) { byte[] data = Encoding.ASCII.GetBytes("The white bunny jumps over the brown dog in a carparking lot"); for (int i = 0; i < 20000; i++) { fs.Write(data, 0, data.Length); } } Console.WriteLine(@"## Exmaple with {0} ##", file); SafeFileHandle fileHandle = CreateFile(file, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero); if (fileHandle.IsInvalid) { int lastError = Marshal.GetLastWin32Error(); Console.WriteLine(@"!! Invalid {0}; Error ({1}): {2}", file, lastError, new Win32Exception(lastError).Message); Console.WriteLine(); return; } using (FilesystemDeviceWrapper fileIo = new FilesystemDeviceWrapper(fileHandle, true)) { FileInfo fileInfo = new FileInfo(file); Console.WriteLine("File size: {0:N0} (compressed: {1:N0})", fileInfo.Length, GetCompressedSize(file)); Console.WriteLine("Compression: {0} ({1})", fileInfo.Attributes.HasFlag(FileAttributes.Compressed), fileIo.FileSystemGetCompression()); Console.WriteLine(" Enabling compression (LZNT1)"); fileIo.FileSystemSetCompression(COMPRESSION_FORMAT.LZNT1); fileInfo.Refresh(); Console.WriteLine("File size: {0:N0} (compressed: {1:N0})", fileInfo.Length, GetCompressedSize(file)); Console.WriteLine("Compression: {0} ({1})", fileInfo.Attributes.HasFlag(FileAttributes.Compressed), fileIo.FileSystemGetCompression()); } } finally { if (File.Exists(file)) { File.Delete(file); } } }
public void CompressedFile() { using (TempFile tmpFile = new TempFile()) { // Create a file // Write file data using (FileStream fs = File.OpenWrite(tmpFile.File.FullName)) { byte[] data = Encoding.ASCII.GetBytes("The white bunny jumps over the brown dog in a carparking lot"); for (int i = 0; i < 20000; i++) { fs.Write(data, 0, data.Length); } } using (FilesystemDeviceWrapper wrapper = Win32.GetFileWrapper(tmpFile.File.FullName)) { wrapper.FileSystemSetCompression(COMPRESSION_FORMAT.LZNT1); } // Discover it via the NTFS lib char driveLetter = tmpFile.File.FullName[0]; RawDisk disk = new RawDisk(driveLetter); NTFSDiskProvider provider = new NTFSDiskProvider(disk); NTFSWrapper ntfsWrapper = new NTFSWrapper(provider, 0); NtfsDirectory ntfsDir = NTFSHelpers.OpenDir(ntfsWrapper, tmpFile.File.DirectoryName); NtfsFile ntfsFile = NTFSHelpers.OpenFile(ntfsDir, tmpFile.File.Name); Assert.IsNotNull(ntfsFile); Assert.IsTrue(tmpFile.File.Attributes.HasFlag(FileAttributes.Compressed)); AttributeData attributeData = ntfsFile.MFTRecord.Attributes.OfType <AttributeData>().Single(); Assert.IsTrue(attributeData.DataFragments.Any(s => s.IsCompressed)); // Read it using (Stream actualStream = File.OpenRead(tmpFile.File.FullName)) using (Stream ntfsStream = ntfsFile.OpenRead()) { bool equal = StreamUtils.CompareStreams(actualStream, ntfsStream); Assert.IsTrue(equal); } } }
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 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); }
private static void ExampleSparseFile() { string file = Path.GetTempFileName(); try { // Write file data const int length = 1 * 1024 * 1024; // 1 MB const int sparseLength = 512 * 1024; // 0.5 MB using (FileStream fs = File.OpenWrite(file)) { byte[] data = new byte[length]; for (int i = 0; i < data.Length; i++) data[i] = 1; // Set the data to non-zero fs.Write(data, 0, data.Length); } Console.WriteLine(@"## Exmaple with {0} ##", file); SafeFileHandle fileHandle = CreateFile(file, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero); if (fileHandle.IsInvalid) { int lastError = Marshal.GetLastWin32Error(); Console.WriteLine(@"!! Invalid {0}; Error ({1}): {2}", file, lastError, new Win32Exception(lastError).Message); Console.WriteLine(); return; } using (FilesystemDeviceWrapper fileIo = new FilesystemDeviceWrapper(fileHandle, true)) { FileInfo fileInfo = new FileInfo(file); Console.WriteLine("File size: " + fileInfo.Length); Console.WriteLine("Sparse: " + fileInfo.Attributes.HasFlag(FileAttributes.SparseFile)); // Enable sparse ranges Console.WriteLine("Enabling Sparse file"); fileIo.FileSystemSetSparseFile(true); fileInfo.Refresh(); Console.WriteLine("Sparse: " + fileInfo.Attributes.HasFlag(FileAttributes.SparseFile)); // Set sparse range Console.WriteLine(" Setting sparse range: " + sparseLength + " (length: " + ((fileInfo.Length - sparseLength) / 2) + ")"); fileIo.FileSystemSetZeroData(sparseLength, (fileInfo.Length - sparseLength) / 2); // Query sparse range fileInfo.Refresh(); FILE_ALLOCATED_RANGE_BUFFER[] ranges = fileIo.FileSystemQueryAllocatedRanges(0, length); Console.WriteLine("File size: " + fileInfo.Length); Console.WriteLine("Sparse ranges (" + ranges.Length + "):"); foreach (FILE_ALLOCATED_RANGE_BUFFER range in ranges) { Console.WriteLine(" Non-sparse range: " + range.FileOffset + " (length: " + range.Length + ")"); } } } finally { if (File.Exists(file)) File.Delete(file); } }
private static void ExampleFileSystemIO() { const string drive = @"\\.\C:"; Console.WriteLine(@"## Exmaple on {0} ##", drive); SafeFileHandle volumeHandle = CreateFile(drive, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero); if (volumeHandle.IsInvalid) { int lastError = Marshal.GetLastWin32Error(); Console.WriteLine(@"!! Invalid {0}; Error ({1}): {2}", drive, lastError, new Win32Exception(lastError).Message); Console.WriteLine(); return; } using (volumeHandle) { // Extract a complete file list from the target drive IUSN_RECORD[] usnData; using (UsnDeviceWrapper usnIo = new UsnDeviceWrapper(volumeHandle)) usnData = usnIo.FileSystemEnumUsnData(); Console.WriteLine("Found {0:N0} file/folder records", usnData.Length); // Count the unique file names int usnNameUniques = new HashSet<string>(usnData.Select(s => s.FileName)).Count; Console.WriteLine("Found {0:N0} unique names on records", usnNameUniques); // Prepare a dictionary to resolve parents Dictionary<ulong, USN_RECORD_V2> usnDic = usnData.OfType<USN_RECORD_V2>().ToDictionary(s => s.FileReferenceNumber); const string root = drive + "\\"; List<string> files = new List<string>(); List<string> parents = new List<string>(); foreach (USN_RECORD_V2 usnRecord in usnData.OfType<USN_RECORD_V2>()) { parents.Clear(); USN_RECORD_V2 current = usnRecord; while (usnDic.ContainsKey(current.ParentFileReferenceNumber)) { current = usnDic[current.ParentFileReferenceNumber]; parents.Add(current.FileName); } parents.Reverse(); string path = Path.Combine(root, Path.Combine(parents.ToArray()), usnRecord.FileName); files.Add(path); } // Sort all files in lexicographical order files.Sort(); // FS Stats FileSystemStats[] fsStats; using (FilesystemDeviceWrapper fsIo = new FilesystemDeviceWrapper(volumeHandle)) fsStats = fsIo.FileSystemGetStatistics(); for (int i = 0; i < fsStats.Length; i++) { switch (fsStats[i].Stats.FileSystemType) { case FILESYSTEM_STATISTICS_TYPE.FILESYSTEM_STATISTICS_TYPE_NTFS: NTFS_STATISTICS ntfsStats = (NTFS_STATISTICS)fsStats[i].FSStats; Console.WriteLine("Processor {0}: (NTFS) MFT Reads/Writes: {1,7:N0} / {2,7:N0}", i, ntfsStats.MftReads, ntfsStats.MftWrites); break; case FILESYSTEM_STATISTICS_TYPE.FILESYSTEM_STATISTICS_TYPE_FAT: FAT_STATISTICS fatStats = (FAT_STATISTICS)fsStats[i].FSStats; Console.WriteLine("Processor {0}: (FAT) Noncached Disk Reads/Writes: {1,7:N0} / {2,7:N0}", i, fatStats.NonCachedDiskReads, fatStats.NonCachedDiskWrites); break; case FILESYSTEM_STATISTICS_TYPE.FILESYSTEM_STATISTICS_TYPE_EXFAT: EXFAT_STATISTICS exfatStats = (EXFAT_STATISTICS)fsStats[i].FSStats; Console.WriteLine("Processor {0}: (EXFAT) Noncached Disk Reads/Writes: {1,7:N0} / {2,7:N0}", i, exfatStats.NonCachedDiskReads, exfatStats.NonCachedDiskWrites); break; default: throw new ArgumentOutOfRangeException(); } } // Bitmap VOLUME_BITMAP_BUFFER bitmap; using (FilesystemDeviceWrapper fsIo = new FilesystemDeviceWrapper(volumeHandle)) bitmap = fsIo.FileSystemGetVolumeBitmap(0); Console.WriteLine("Bitmap: {0:N0} clusters", bitmap.Buffer.Length); int trues = 0, falses = 0; for (int i = 0; i < bitmap.Buffer.Length; i++) if (bitmap.Buffer[i]) trues++; else falses++; Console.WriteLine("Allocated clusters: {0:N0}", trues); Console.WriteLine("Unallocated clusters: {0:N0}", falses); // NTFS Base LCN (always 0) RETRIEVAL_POINTER_BASE basePointer; using (FilesystemDeviceWrapper fsIo = new FilesystemDeviceWrapper(volumeHandle)) basePointer = fsIo.FileSystemGetRetrievalPointerBase(); Console.WriteLine("Base LCN: {0:N0}", basePointer.FileAreaOffset); } Console.WriteLine(); }
private static void ExampleDefragmentFile() { const string file = @"C:\Windows\system32\cmd.exe"; string drive = @"\\.\" + Directory.GetDirectoryRoot(file).Substring(0, 2); Console.WriteLine(@"## Exmaple on {0} on drive {1} ##", file, drive); // Open file to defragment SafeFileHandle fileHandle = CreateFile(file, FileAccess.Read, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero); if (fileHandle.IsInvalid) { int lastError = Marshal.GetLastWin32Error(); Console.WriteLine(@"!! Invalid {0}; Error ({1}): {2}", file, lastError, new Win32Exception(lastError).Message); Console.WriteLine(); return; } // Open volume to defragment on SafeFileHandle driveHandle = CreateFile(drive, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero); if (driveHandle.IsInvalid) { int lastError = Marshal.GetLastWin32Error(); Console.WriteLine(@"!! Invalid {0}; Error ({1}): {2}", drive, lastError, new Win32Exception(lastError).Message); Console.WriteLine(); return; } using (FilesystemDeviceWrapper fileIo = new FilesystemDeviceWrapper(fileHandle, true)) using (FilesystemDeviceWrapper fsIo = new FilesystemDeviceWrapper(driveHandle, true)) { // Find all fragments of the file FileExtentInfo[] extents = fileIo.FileSystemGetRetrievalPointers(); Console.WriteLine("File has {0} fragments", extents.Length); if (extents.Length == 1) { Console.WriteLine("File is already defragmented"); Console.WriteLine(); return; } // Calculate number of clusters we need to find int clustersNeeded = (int)extents.Sum(s => (decimal)s.Size); Console.WriteLine("We need to find {0:N0} free clusters, for this file.", clustersNeeded); // Get the drive bitmap VOLUME_BITMAP_BUFFER bitmap = fsIo.FileSystemGetVolumeBitmap(); Console.WriteLine("Got the drive bitmap, it contains {0:N0} clusters and starts at LCN: {1:N0}", bitmap.BitmapSize, bitmap.StartingLcn); // Find a sequential area of [clustersNeeded] free clusters ulong foundFreeLCN = 0; // The result of the search uint maxStart = (uint)(bitmap.Buffer.Length - (decimal)clustersNeeded); // There's no point searching beyond this LCN // Enumerate clusters for (uint i = 0; i < maxStart; i++) { // Check bitmap, find location with [clustersNeeded] free clusters bool found = true; for (uint x = i; x < i + clustersNeeded; x++) { if (bitmap.Buffer[(int)x]) { // Found an occupied cluster found = false; // Advance the pointer, so that we don't have to re-search the same clusters again. i = x; break; } } if (found) { // We found a free block! foundFreeLCN = i + bitmap.StartingLcn; break; } } // Did we find a free area? if (foundFreeLCN > 0) { Console.WriteLine("Found {0:N0} free clusters starting at LCN: {1:N0}", clustersNeeded, foundFreeLCN); fsIo.FileSystemMoveFile(fileHandle.DangerousGetHandle(), 0, foundFreeLCN, (uint)clustersNeeded); } else { Console.WriteLine("Unable to find {0:N0} contigous free clusters", clustersNeeded); } extents = fileIo.FileSystemGetRetrievalPointers(); Console.WriteLine("File now has {0} fragment(s)", extents.Length); } Console.ReadLine(); Console.WriteLine(); }
private static void ExampleCompression() { string file = Path.GetTempFileName(); try { // Write file data using (FileStream fs = File.OpenWrite(file)) { byte[] data = Encoding.ASCII.GetBytes("The white bunny jumps over the brown dog in a carparking lot"); for (int i = 0; i < 20000; i++) { fs.Write(data, 0, data.Length); } } Console.WriteLine(@"## Exmaple with {0} ##", file); SafeFileHandle fileHandle = CreateFile(file, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero); if (fileHandle.IsInvalid) { int lastError = Marshal.GetLastWin32Error(); Console.WriteLine(@"!! Invalid {0}; Error ({1}): {2}", file, lastError, new Win32Exception(lastError).Message); Console.WriteLine(); return; } using (FilesystemDeviceWrapper fileIo = new FilesystemDeviceWrapper(fileHandle, true)) { FileInfo fileInfo = new FileInfo(file); Console.WriteLine("File size: {0:N0} (compressed: {1:N0})", fileInfo.Length, GetCompressedSize(file)); Console.WriteLine("Compression: {0} ({1})", fileInfo.Attributes.HasFlag(FileAttributes.Compressed), fileIo.FileSystemGetCompression()); Console.WriteLine(" Enabling compression (LZNT1)"); fileIo.FileSystemSetCompression(COMPRESSION_FORMAT.LZNT1); fileInfo.Refresh(); Console.WriteLine("File size: {0:N0} (compressed: {1:N0})", fileInfo.Length, GetCompressedSize(file)); Console.WriteLine("Compression: {0} ({1})", fileInfo.Attributes.HasFlag(FileAttributes.Compressed), fileIo.FileSystemGetCompression()); } } finally { if (File.Exists(file)) File.Delete(file); } }
private static void ExampleSparseFile() { string file = Path.GetTempFileName(); try { // Write file data const int length = 1 * 1024 * 1024; // 1 MB const int sparseLength = 512 * 1024; // 0.5 MB using (FileStream fs = File.OpenWrite(file)) { byte[] data = new byte[length]; for (int i = 0; i < data.Length; i++) { data[i] = 1; // Set the data to non-zero } fs.Write(data, 0, data.Length); } Console.WriteLine(@"## Exmaple with {0} ##", file); SafeFileHandle fileHandle = CreateFile(file, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero); if (fileHandle.IsInvalid) { int lastError = Marshal.GetLastWin32Error(); Console.WriteLine(@"!! Invalid {0}; Error ({1}): {2}", file, lastError, new Win32Exception(lastError).Message); Console.WriteLine(); return; } using (FilesystemDeviceWrapper fileIo = new FilesystemDeviceWrapper(fileHandle, true)) { FileInfo fileInfo = new FileInfo(file); Console.WriteLine("File size: " + fileInfo.Length); Console.WriteLine("Sparse: " + fileInfo.Attributes.HasFlag(FileAttributes.SparseFile)); // Enable sparse ranges Console.WriteLine("Enabling Sparse file"); fileIo.FileSystemSetSparseFile(true); fileInfo.Refresh(); Console.WriteLine("Sparse: " + fileInfo.Attributes.HasFlag(FileAttributes.SparseFile)); // Set sparse range Console.WriteLine(" Setting sparse range: " + sparseLength + " (length: " + ((fileInfo.Length - sparseLength) / 2) + ")"); fileIo.FileSystemSetZeroData(sparseLength, (fileInfo.Length - sparseLength) / 2); // Query sparse range fileInfo.Refresh(); FILE_ALLOCATED_RANGE_BUFFER[] ranges = fileIo.FileSystemQueryAllocatedRanges(0, length); Console.WriteLine("File size: " + fileInfo.Length); Console.WriteLine("Sparse ranges (" + ranges.Length + "):"); foreach (FILE_ALLOCATED_RANGE_BUFFER range in ranges) { Console.WriteLine(" Non-sparse range: " + range.FileOffset + " (length: " + range.Length + ")"); } } } finally { if (File.Exists(file)) { File.Delete(file); } } }
private static void ExampleDefragmentDir() { const string dir = @"C:\Windows"; string drive = @"\\.\" + Directory.GetDirectoryRoot(dir).Substring(0, 2); Console.WriteLine(@"## Exmaple on {0} on drive {1} ##", dir, drive); // Open volume to defragment on SafeFileHandle driveHandle = CreateFile(drive, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero); if (driveHandle.IsInvalid) { int lastError = Marshal.GetLastWin32Error(); Console.WriteLine(@"!! Invalid {0}; Error ({1}): {2}", drive, lastError, new Win32Exception(lastError).Message); Console.WriteLine(); return; } using (FilesystemDeviceWrapper fsIo = new FilesystemDeviceWrapper(driveHandle, true)) { // Get the drive bitmap VOLUME_BITMAP_BUFFER bitmap = fsIo.FileSystemGetVolumeBitmap(); Console.WriteLine("Got the drive bitmap, it contains {0:N0} clusters and starts at LCN: {1:N0}", bitmap.BitmapSize, bitmap.StartingLcn); string[] files = Directory.GetFiles(dir, "*", SearchOption.TopDirectoryOnly); Console.WriteLine("Beginning work on {0} files", files.Length); foreach (string file in files) { Console.WriteLine("Beginning work on {0}", file); // Open file to defragment SafeFileHandle fileHandle = CreateFile(file, FileAccess.Read, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero); if (fileHandle.IsInvalid) { int lastError = Marshal.GetLastWin32Error(); Console.WriteLine(@"!! Invalid {0}; Error ({1}): {2}", file, lastError, new Win32Exception(lastError).Message); continue; } using (FilesystemDeviceWrapper fileIo = new FilesystemDeviceWrapper(fileHandle, true)) { // Find all fragments of the file FileExtentInfo[] extents; try { extents = fileIo.FileSystemGetRetrievalPointers(); } catch (Win32Exception ex) { Console.WriteLine("Couldn't get file extents: " + ex.Message); continue; } if (extents.Length == 1) { Console.WriteLine("File is already defragmented"); continue; } Console.WriteLine("File has {0} fragments", extents.Length); // Calculate number of clusters we need to find int clustersNeeded = (int)extents.Sum(s => (decimal)s.Size); Console.WriteLine("We need to find {0:N0} free clusters, for this file.", clustersNeeded); // Find a sequential area of [clustersNeeded] free clusters ulong foundFreeLCN = 0; // The result of the search uint maxStart = (uint)(bitmap.Buffer.Length - (decimal)clustersNeeded); // There's no point searching beyond this LCN // Enumerate clusters for (uint i = 0; i < maxStart; i++) { // Check bitmap, find location with [clustersNeeded] free clusters bool found = true; for (uint x = i; x < i + clustersNeeded; x++) { if (bitmap.Buffer[(int)x]) { // Found an occupied cluster found = false; // Advance the pointer, so that we don't have to re-search the same clusters again. i = x; break; } } if (found) { // We found a free block! foundFreeLCN = i + bitmap.StartingLcn; break; } } // Did we find a free area? if (foundFreeLCN > 0) { Console.WriteLine("Found {0:N0} free clusters starting at LCN: {1:N0}", clustersNeeded, foundFreeLCN); try { fsIo.FileSystemMoveFile(fileHandle.DangerousGetHandle(), 0, foundFreeLCN, (uint)clustersNeeded); // Mark newly used areas as used ulong upperFreeLCN = foundFreeLCN + (ulong)clustersNeeded; for (ulong i = foundFreeLCN; i < upperFreeLCN; i++) { bitmap.Buffer[(int)i] = true; } // Mark newly freed areas as free foreach (FileExtentInfo extent in extents) { for (ulong i = extent.Lcn; i < extent.Lcn + extent.Size; i++) { bitmap.Buffer[(int)i] = false; } } } catch (Win32Exception ex) { Console.WriteLine("Unable to move file: " + ex.Message); } } else { Console.WriteLine("Unable to find {0:N0} contigous free clusters", clustersNeeded); } extents = fileIo.FileSystemGetRetrievalPointers(); Console.WriteLine("File now has {0} fragment(s)", extents.Length); } } } Console.WriteLine("Done... "); Console.ReadLine(); Console.WriteLine(); }
private static void ExampleFileSystemIO() { const string drive = @"\\.\C:"; Console.WriteLine(@"## Exmaple on {0} ##", drive); SafeFileHandle volumeHandle = CreateFile(drive, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero); if (volumeHandle.IsInvalid) { int lastError = Marshal.GetLastWin32Error(); Console.WriteLine(@"!! Invalid {0}; Error ({1}): {2}", drive, lastError, new Win32Exception(lastError).Message); Console.WriteLine(); return; } using (volumeHandle) { // Extract a complete file list from the target drive IUSN_RECORD[] usnData; using (UsnDeviceWrapper usnIo = new UsnDeviceWrapper(volumeHandle)) usnData = usnIo.FileSystemEnumUsnData(); Console.WriteLine("Found {0:N0} file/folder records", usnData.Length); // Count the unique file names int usnNameUniques = new HashSet <string>(usnData.Select(s => s.FileName)).Count; Console.WriteLine("Found {0:N0} unique names on records", usnNameUniques); // Prepare a dictionary to resolve parents Dictionary <ulong, USN_RECORD_V2> usnDic = usnData.OfType <USN_RECORD_V2>().ToDictionary(s => s.FileReferenceNumber); const string root = drive + "\\"; List <string> files = new List <string>(); List <string> parents = new List <string>(); foreach (USN_RECORD_V2 usnRecord in usnData.OfType <USN_RECORD_V2>()) { parents.Clear(); USN_RECORD_V2 current = usnRecord; while (usnDic.ContainsKey(current.ParentFileReferenceNumber)) { current = usnDic[current.ParentFileReferenceNumber]; parents.Add(current.FileName); } parents.Reverse(); string path = Path.Combine(root, Path.Combine(parents.ToArray()), usnRecord.FileName); files.Add(path); } // Sort all files in lexicographical order files.Sort(); // FS Stats FileSystemStats[] fsStats; using (FilesystemDeviceWrapper fsIo = new FilesystemDeviceWrapper(volumeHandle)) fsStats = fsIo.FileSystemGetStatistics(); for (int i = 0; i < fsStats.Length; i++) { switch (fsStats[i].Stats.FileSystemType) { case FILESYSTEM_STATISTICS_TYPE.FILESYSTEM_STATISTICS_TYPE_NTFS: NTFS_STATISTICS ntfsStats = (NTFS_STATISTICS)fsStats[i].FSStats; Console.WriteLine("Processor {0}: (NTFS) MFT Reads/Writes: {1,7:N0} / {2,7:N0}", i, ntfsStats.MftReads, ntfsStats.MftWrites); break; case FILESYSTEM_STATISTICS_TYPE.FILESYSTEM_STATISTICS_TYPE_FAT: FAT_STATISTICS fatStats = (FAT_STATISTICS)fsStats[i].FSStats; Console.WriteLine("Processor {0}: (FAT) Noncached Disk Reads/Writes: {1,7:N0} / {2,7:N0}", i, fatStats.NonCachedDiskReads, fatStats.NonCachedDiskWrites); break; case FILESYSTEM_STATISTICS_TYPE.FILESYSTEM_STATISTICS_TYPE_EXFAT: EXFAT_STATISTICS exfatStats = (EXFAT_STATISTICS)fsStats[i].FSStats; Console.WriteLine("Processor {0}: (EXFAT) Noncached Disk Reads/Writes: {1,7:N0} / {2,7:N0}", i, exfatStats.NonCachedDiskReads, exfatStats.NonCachedDiskWrites); break; default: throw new ArgumentOutOfRangeException(); } } // Bitmap VOLUME_BITMAP_BUFFER bitmap; using (FilesystemDeviceWrapper fsIo = new FilesystemDeviceWrapper(volumeHandle)) bitmap = fsIo.FileSystemGetVolumeBitmap(0); Console.WriteLine("Bitmap: {0:N0} clusters", bitmap.Buffer.Length); int trues = 0, falses = 0; for (int i = 0; i < bitmap.Buffer.Length; i++) { if (bitmap.Buffer[i]) { trues++; } else { falses++; } } Console.WriteLine("Allocated clusters: {0:N0}", trues); Console.WriteLine("Unallocated clusters: {0:N0}", falses); // NTFS Base LCN (always 0) RETRIEVAL_POINTER_BASE basePointer; using (FilesystemDeviceWrapper fsIo = new FilesystemDeviceWrapper(volumeHandle)) basePointer = fsIo.FileSystemGetRetrievalPointerBase(); Console.WriteLine("Base LCN: {0:N0}", basePointer.FileAreaOffset); } Console.WriteLine(); }