public void GetEntries(long usn, ulong fileNumber, GetEntriesHandler handler, int count) { List <UsnEntry> result = new List <UsnEntry>(); UsnErrorCode usnErrorCode = this.QueryUSNJournal(); if (usnErrorCode == UsnErrorCode.SUCCESS) { MFT_ENUM_DATA mftEnumData = new MFT_ENUM_DATA(); mftEnumData.StartFileReferenceNumber = fileNumber; mftEnumData.LowUsn = 0; mftEnumData.HighUsn = this.ntfsUsnJournalData.NextUsn; int sizeMftEnumData = Marshal.SizeOf(mftEnumData); IntPtr ptrMftEnumData = GetHeapGlobalPtr(sizeMftEnumData); Marshal.StructureToPtr(mftEnumData, ptrMftEnumData, true); int ptrDataSize = sizeof(UInt64) + 10000; IntPtr ptrData = GetHeapGlobalPtr(ptrDataSize); uint outBytesCount; while (false != Win32Api.DeviceIoControl( this.DriveRootHandle, UsnControlCode.FSCTL_ENUM_USN_DATA, ptrMftEnumData, sizeMftEnumData, ptrData, ptrDataSize, out outBytesCount, IntPtr.Zero)) { long purvalue = ptrData.ToInt64() + sizeof(long); IntPtr ptrUsnRecord = new IntPtr(purvalue); while (outBytesCount > 60) { var usnRecord = new USN_RECORD_V2(ptrUsnRecord); UsnEntry rec = new UsnEntry(usnRecord); if (rec.FileReferenceNumber > fileNumber || rec.Usn > usn) { result.Add(rec); } ptrUsnRecord = new IntPtr(ptrUsnRecord.ToInt64() + usnRecord.RecordLength); outBytesCount -= usnRecord.RecordLength; if (result.Count >= count) { handler?.Invoke(Drive, result); result = new List <UsnEntry>(); } } Marshal.WriteInt64(ptrMftEnumData, Marshal.ReadInt64(ptrData, 0)); } Marshal.FreeHGlobal(ptrData); Marshal.FreeHGlobal(ptrMftEnumData); } handler?.Invoke(Drive, result); }
public List <UsnEntry> GetEntries() { var result = new List <UsnEntry>(); UsnErrorCode usnErrorCode = this.QueryUSNJournal(); if (usnErrorCode == UsnErrorCode.SUCCESS) { MFT_ENUM_DATA mftEnumData = new MFT_ENUM_DATA(); mftEnumData.StartFileReferenceNumber = 0; mftEnumData.LowUsn = 0; mftEnumData.HighUsn = this.ntfsUsnJournalData.NextUsn; int sizeMftEnumData = Marshal.SizeOf(mftEnumData); IntPtr ptrMftEnumData = GetHeapGlobalPtr(sizeMftEnumData); Marshal.StructureToPtr(mftEnumData, ptrMftEnumData, true); int ptrDataSize = sizeof(UInt64) + 10000; IntPtr ptrData = GetHeapGlobalPtr(ptrDataSize); uint outBytesCount; while (false != Win32Api.DeviceIoControl( this.DriveRootHandle, UsnControlCode.FSCTL_ENUM_USN_DATA, ptrMftEnumData, sizeMftEnumData, ptrData, ptrDataSize, out outBytesCount, IntPtr.Zero)) { // ptrData includes following struct: //typedef struct //{ // USN LastFileReferenceNumber; // USN_RECORD_V2 Record[1]; //} *PENUM_USN_DATA; long purvalue = ptrData.ToInt64() + sizeof(long); IntPtr ptrUsnRecord = new IntPtr(purvalue); while (outBytesCount > 60) { var usnRecord = new USN_RECORD_V2(ptrUsnRecord); result.Add(new UsnEntry(usnRecord)); ptrUsnRecord = new IntPtr(ptrUsnRecord.ToInt64() + usnRecord.RecordLength); outBytesCount -= usnRecord.RecordLength; } Marshal.WriteInt64(ptrMftEnumData, Marshal.ReadInt64(ptrData, 0)); } Marshal.FreeHGlobal(ptrData); Marshal.FreeHGlobal(ptrMftEnumData); } return(result); }
public UsnEntry(USN_RECORD_V2 usnRecord) { this.RecordLength = usnRecord.RecordLength; this.FileReferenceNumber = usnRecord.FileReferenceNumber; this.ParentFileReferenceNumber = usnRecord.ParentFileReferenceNumber; this.Usn = usnRecord.Usn; this.Reason = usnRecord.Reason; this.FileAttributes = usnRecord.FileAttributes; this.FileNameLength = usnRecord.FileNameLength; this.FileNameOffset = usnRecord.FileNameOffset; this.FileName = usnRecord.FileName; }
/// <summary> /// Copy constructor. /// </summary> /// <param name="nativeEntry"></param> /// <param name="name"></param> internal JournalEntry(USN_RECORD_V2 nativeEntry, string name) { Name = name ?? throw new ArgumentNullException(nameof(name)); Length = (int)nativeEntry.RecordLength; Version = new Version(nativeEntry.MajorVersion, nativeEntry.MinorVersion); ReferenceNumber = nativeEntry.FileReferenceNumber; ParentReferenceNumber = nativeEntry.ParentFileReferenceNumber; UniqueSequenceNumber = nativeEntry.USN; TimeStamp = DateTime.FromFileTimeUtc(nativeEntry.TimeStamp); Reason = (ChangeReason)nativeEntry.Reason; Source = (SourceInformation)nativeEntry.SourceInfo; SecurityID = (int)nativeEntry.SecurityId; Attributes = (FileAttributes)nativeEntry.FileAttributes; }
public bool UsnIsExist(long usn) { bool rs = false; UsnErrorCode usnErrorCode = QueryUSNJournal(); if (ntfsUsnJournalData.NextUsn < usn) { return(rs); } if (usnErrorCode == UsnErrorCode.SUCCESS) { MFT_ENUM_DATA mftEnumData = new MFT_ENUM_DATA(); mftEnumData.StartFileReferenceNumber = 0; mftEnumData.LowUsn = usn; mftEnumData.HighUsn = usn; int sizeMftEnumData = Marshal.SizeOf(mftEnumData); IntPtr ptrMftEnumData = GetHeapGlobalPtr(sizeMftEnumData); Marshal.StructureToPtr(mftEnumData, ptrMftEnumData, true); int ptrDataSize = sizeof(UInt64) + 10000; IntPtr ptrData = GetHeapGlobalPtr(ptrDataSize); uint outBytesCount; while (false != Win32Api.DeviceIoControl( this.DriveRootHandle, UsnControlCode.FSCTL_ENUM_USN_DATA, ptrMftEnumData, sizeMftEnumData, ptrData, ptrDataSize, out outBytesCount, IntPtr.Zero)) { IntPtr ptrUsnRecord = new IntPtr(ptrData.ToInt32() + sizeof(Int64)); while (outBytesCount > 60) { var usnRecord = new USN_RECORD_V2(ptrUsnRecord); ptrUsnRecord = new IntPtr(ptrUsnRecord.ToInt32() + usnRecord.RecordLength); outBytesCount -= usnRecord.RecordLength; rs = true; } Marshal.WriteInt64(ptrMftEnumData, Marshal.ReadInt64(ptrData, 0)); } Marshal.FreeHGlobal(ptrData); Marshal.FreeHGlobal(ptrMftEnumData); } return(rs); }
private static IUSN_RECORD ParseUsnRecord(UnmanagedMemory mem, int dataOffset, out int length) { // Get record length length = Marshal.ReadInt32(mem, dataOffset); int majorVersion = Marshal.ReadByte(mem, dataOffset + sizeof(int)) + (Marshal.ReadByte(mem, dataOffset + sizeof(int) + 1) << 8); if (length <= 0) { // No more records return(null); } // Copy out record subset switch (majorVersion) { case 2: USN_RECORD_V2 recordv2 = (USN_RECORD_V2)Marshal.PtrToStructure(mem.Handle + dataOffset, typeof(USN_RECORD_V2)); // Parse string manually, as we cannot rely on the string to be null-terminated. recordv2.FileName = Marshal.PtrToStringUni(mem.Handle + dataOffset + recordv2.FileNameOffset, recordv2.FileNameLength / 2); return(recordv2); case 3: USN_RECORD_V3 recordv3 = (USN_RECORD_V3)Marshal.PtrToStructure(mem.Handle + dataOffset, typeof(USN_RECORD_V3)); // Parse string manually, as we cannot rely on the string to be null-terminated. recordv3.FileName = Marshal.PtrToStringUni(mem.Handle + dataOffset + recordv3.FileNameOffset, recordv3.FileNameLength / 2); return(recordv3); default: // Ignore Debugger.Break(); break; } return(null); }
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(); }