/// <summary> /// This function queries the usn journal on the volume. /// </summary> /// <param name="usnJournalState">the USN_JOURNAL_DATA object that is associated with this volume</param> /// <returns> /// The success state of the <c>WinApi32.DeviceIoControl</c> call. /// </returns> private bool QueryUsnJournal(ref Win32Api.USN_JOURNAL_DATA usnJournalState) { UInt32 cb; return(Win32Api.DeviceIoControl( _usnJournalRootHandle, Win32Api.FSCTL_QUERY_USN_JOURNAL, IntPtr.Zero, 0, out usnJournalState, Marshal.SizeOf(usnJournalState), out cb, IntPtr.Zero )); }
/// <summary> /// GetFileAndDirEntries() reads the Master File Table to find all of the files and /// folders on a volume and returns them individually. /// </summary> /// <param name="dirs">The directories.</param> /// <param name="files">The files.</param> /// <param name="filter">The filter.</param> private void GetFileAndDirEntries(out ConcurrentDictionary <ulong, Win32Api.UsnEntry> dirs, out ConcurrentBag <Win32Api.UsnEntry> files, Regex filter = null) { dirs = new ConcurrentDictionary <ulong, Win32Api.UsnEntry>(); files = new ConcurrentBag <Win32Api.UsnEntry>(); var usnState = new Win32Api.USN_JOURNAL_DATA(); if (!QueryUsnJournal(ref usnState)) { throw new Win32Exception("Failed to query the USN journal on the volume."); } // // set up MFT_ENUM_DATA structure // Win32Api.MFT_ENUM_DATA med; med.StartFileReferenceNumber = 0; med.LowUsn = 0; med.HighUsn = usnState.NextUsn; Int32 sizeMftEnumData = Marshal.SizeOf(med); IntPtr medBuffer = Marshal.AllocHGlobal(sizeMftEnumData); Win32Api.ZeroMemory(medBuffer, sizeMftEnumData); Marshal.StructureToPtr(med, medBuffer, true); // // set up the data buffer which receives the USN_RECORD data // int pDataSize = sizeof(UInt64) + 10000; IntPtr pData = Marshal.AllocHGlobal(pDataSize); Win32Api.ZeroMemory(pData, pDataSize); uint outBytesReturned = 0; // // Gather up volume's directories // while (Win32Api.DeviceIoControl( _usnJournalRootHandle, Win32Api.FSCTL_ENUM_USN_DATA, medBuffer, sizeMftEnumData, pData, pDataSize, out outBytesReturned, IntPtr.Zero)) { IntPtr pUsnRecord = new IntPtr((Utils.Is64Bit ? pData.ToInt64() : pData.ToInt32()) + sizeof(Int64)); while (outBytesReturned > 60) { var usnEntry = new Win32Api.UsnEntry(pUsnRecord); if (usnEntry.IsFile && (filter == null || filter.IsMatch(usnEntry.Name))) { files.Add(usnEntry); } if (usnEntry.IsFolder) { dirs.TryAdd(usnEntry.FileReferenceNumber, usnEntry); } pUsnRecord = new IntPtr((Utils.Is64Bit ? pUsnRecord.ToInt64() : pUsnRecord.ToInt32()) + usnEntry.RecordLength); outBytesReturned -= usnEntry.RecordLength; } Marshal.WriteInt64(medBuffer, Marshal.ReadInt64(pData, 0)); } Marshal.FreeHGlobal(pData); }