unsafe private void EnumerateFiles(IntPtr medBuffer , ref Dictionary <ulong, FileEntry> files , HashSet <string> fileExtensions , Dictionary <ulong, FileEntry> directories , IntPtr changeJournalRootHandle ) { IntPtr pData = Marshal.AllocHGlobal(sizeof(ulong) + 0x10000); WinApi.ZeroMemory(pData, sizeof(ulong) + 0x10000); uint outBytesReturned = 0; while (false != WinApi.DeviceIoControl(changeJournalRootHandle, WinApi.FSCTL_ENUM_USN_DATA, medBuffer, sizeof(WinApi.MFT_ENUM_DATA), pData, sizeof(ulong) + 0x10000, out outBytesReturned, IntPtr.Zero)) { IntPtr pUsnRecord = new IntPtr(pData.ToInt32() + sizeof(Int64)); while (outBytesReturned > 60) { WinApi.USN_RECORD usn = new WinApi.USN_RECORD(pUsnRecord); if (0 != (usn.FileAttributes & WinApi.FILE_ATTRIBUTE_DIRECTORY)) { // // handle directories // if (!directories.ContainsKey(usn.FileReferenceNumber)) { directories.Add(usn.FileReferenceNumber, new FileEntry(usn.FileName, usn.ParentFileReferenceNumber)); } else { // this is debug code and should be removed when we are certain that // duplicate frn's don't exist on a given drive. To date, this exception has // never been thrown. Removing this code improves performance.... throw new Exception(string.Format("Duplicate FRN: {0} for {1}", usn.FileReferenceNumber, usn.FileName) ); } } else { // // handle files // bool add = true; if (fileExtensions != null) { string s = Path.GetExtension(usn.FileName); add = fileExtensions.Contains(s); } if (add) { if (!files.ContainsKey(usn.FileReferenceNumber)) { files.Add(usn.FileReferenceNumber, new FileEntry(usn.FileName, usn.ParentFileReferenceNumber)); } else { FileEntry frn = files [usn.FileReferenceNumber]; if (0 != string.Compare(usn.FileName, frn.Name, true)) { Console.WriteLine( "Attempt to add duplicate file reference number: {0} for file {1}, file from index {2}", usn.FileReferenceNumber, usn.FileName, frn.Name); throw new Exception(string.Format("Duplicate FRN: {0} for {1}", usn.FileReferenceNumber, usn.FileName) ); } } } } pUsnRecord = new IntPtr(pUsnRecord.ToInt32() + usn.RecordLength); outBytesReturned -= usn.RecordLength; } Marshal.WriteInt64(medBuffer, Marshal.ReadInt64(pData, 0)); } Marshal.FreeHGlobal(pData); }
private unsafe void EnumerateFiles(IntPtr medBuffer , ref Dictionary<ulong, FileEntry> files , HashSet<string> fileExtensions , Dictionary<ulong,FileEntry> directories , IntPtr changeJournalRootHandle ) { IntPtr pData = Marshal.AllocHGlobal (sizeof(ulong) + 0x10000); WinApi.ZeroMemory (pData, sizeof(ulong) + 0x10000); uint outBytesReturned = 0; while (false != WinApi.DeviceIoControl(changeJournalRootHandle, WinApi.FSCTL_ENUM_USN_DATA, medBuffer, sizeof(WinApi.MFT_ENUM_DATA), pData, sizeof(ulong) + 0x10000, out outBytesReturned, IntPtr.Zero)) { IntPtr pUsnRecord = new IntPtr (pData.ToInt32 () + sizeof(Int64)); while (outBytesReturned > 60) { WinApi.USN_RECORD usn = new WinApi.USN_RECORD (pUsnRecord); if (0 != (usn.FileAttributes & WinApi.FILE_ATTRIBUTE_DIRECTORY)) { // // handle directories // if (!directories.ContainsKey (usn.FileReferenceNumber)) { directories.Add (usn.FileReferenceNumber, new FileEntry (usn.FileName, usn.ParentFileReferenceNumber)); } else { // this is debug code and should be removed when we are certain that // duplicate frn's don't exist on a given drive. To date, this exception has // never been thrown. Removing this code improves performance.... throw new Exception (string.Format ("Duplicate FRN: {0} for {1}", usn.FileReferenceNumber, usn.FileName) ); } } else { // // handle files // bool add = true; if (fileExtensions != null) { string s = Path.GetExtension (usn.FileName); add = fileExtensions.Contains(s); } if (add) { if (!files.ContainsKey (usn.FileReferenceNumber)) { files.Add (usn.FileReferenceNumber, new FileEntry (usn.FileName, usn.ParentFileReferenceNumber)); } else { FileEntry frn = files [usn.FileReferenceNumber]; if (0 != string.Compare (usn.FileName, frn.Name, true)) { Console.WriteLine( "Attempt to add duplicate file reference number: {0} for file {1}, file from index {2}", usn.FileReferenceNumber, usn.FileName, frn.Name); throw new Exception (string.Format ("Duplicate FRN: {0} for {1}", usn.FileReferenceNumber, usn.FileName) ); } } } } pUsnRecord = new IntPtr (pUsnRecord.ToInt32 () + usn.RecordLength); outBytesReturned -= usn.RecordLength; } Marshal.WriteInt64 (medBuffer, Marshal.ReadInt64 (pData, 0)); } Marshal.FreeHGlobal (pData); }