/// <summary> /// Returns a list of all files and folders changed since the USN /// </summary> /// <param name="startUsn">The USN number to start the list from, set to zero to get all</param> /// <returns>A list of files and folders changed since the USN</returns> private List <KeyValuePair <string, Win32USN.USN_RECORD> > BuildUSNTable(long startUsn) { const int ALLOCATED_MEMORY = 64 * 1024; IntPtr allocatedMemory = IntPtr.Zero; List <KeyValuePair <string, Win32USN.USN_RECORD> > records = new List <KeyValuePair <string, Win32USN.USN_RECORD> >(); try { uint bytesRead = 0; bool more = true; allocatedMemory = Marshal.AllocHGlobal(ALLOCATED_MEMORY); Win32USN.MFT_ENUM_DATA startParams = new Win32USN.MFT_ENUM_DATA(); startParams.StartFileReferenceNumber = 0; startParams.LowUsn = Math.Max(startUsn, m_journal.LowestValidUsn); startParams.HighUsn = m_journal.NextUsn; while (more) { if (!Win32USN.DeviceIoControl(m_volumeHandle, Win32USN.EIOControlCode.FsctlEnumUsnData, ref startParams, (uint)Marshal.SizeOf(typeof(Win32USN.MFT_ENUM_DATA)), allocatedMemory, ALLOCATED_MEMORY, ref bytesRead, IntPtr.Zero)) { int errorCode = Marshal.GetLastWin32Error(); //If we get no error or EOF the enumeration is completed if (errorCode == Win32USN.ERROR_HANDLE_EOF || errorCode == Win32USN.ERROR_SUCCESS) { break; } else { throw new Win32Exception(errorCode); } } startParams.StartFileReferenceNumber = (ulong)ExtractUsnEntries(bytesRead, allocatedMemory, records, out more); } return(ParseRecordList(records)); } finally { if (allocatedMemory != IntPtr.Zero) { Marshal.FreeHGlobal(allocatedMemory); allocatedMemory = IntPtr.Zero; } } }
/// <summary> /// Retrieves a USN_RECORD_V2 by file reference number (FRN, not USN!) /// </summary> /// <param name="frn">File reference number</param> /// <returns>Returned entry if successful; null otherwise</returns> private Record GetRecordByFileRef(ulong frn) { var enumData = new Win32USN.MFT_ENUM_DATA { StartFileReferenceNumber = frn, LowUsn = 0, HighUsn = m_journal.NextUsn }; var bufferSize = 512; byte[] entryData; while (!Win32USN.ControlWithInput(m_volumeHandle, Win32USN.FsCtl.EnumUSNData, ref enumData, bufferSize, out entryData)) { var e = Marshal.GetLastWin32Error(); if (e != Win32USN.ERROR_INSUFFICIENT_BUFFER) { return(null); } // retry, increasing buffer size bufferSize *= 2; } // not really a foreach: we only check the first record foreach (var rec in EnumerateRecords(entryData)) { if (rec.UsnRecord.FileReferenceNumber == frn) { return(rec); } break; } return(null); }
/// <summary> /// Returns a list of all files and folders changed since the USN /// </summary> /// <param name="startUsn">The USN number to start the list from, set to zero to get all</param> /// <returns>A list of files and folders changed since the USN</returns> private List<KeyValuePair<string, Win32USN.USN_RECORD>> BuildUSNTable(long startUsn) { const int ALLOCATED_MEMORY = 64 * 1024; IntPtr allocatedMemory = IntPtr.Zero; List<KeyValuePair<string, Win32USN.USN_RECORD>> records = new List<KeyValuePair<string, Win32USN.USN_RECORD>>(); try { uint bytesRead = 0; bool more = true; allocatedMemory = Marshal.AllocHGlobal(ALLOCATED_MEMORY); Win32USN.MFT_ENUM_DATA startParams = new Win32USN.MFT_ENUM_DATA(); startParams.StartFileReferenceNumber = 0; startParams.LowUsn = Math.Max(startUsn, m_journal.LowestValidUsn); startParams.HighUsn = m_journal.NextUsn; while (more) { if (!Win32USN.DeviceIoControl(m_volumeHandle, Win32USN.EIOControlCode.FsctlEnumUsnData, ref startParams, (uint)Marshal.SizeOf(typeof(Win32USN.MFT_ENUM_DATA)), allocatedMemory, ALLOCATED_MEMORY, ref bytesRead, IntPtr.Zero)) { int errorCode = Marshal.GetLastWin32Error(); //If we get no error or EOF the enumeration is completed if (errorCode == Win32USN.ERROR_HANDLE_EOF || errorCode == Win32USN.ERROR_SUCCESS) break; else throw new Win32Exception(errorCode); } startParams.StartFileReferenceNumber = (ulong)ExtractUsnEntries(bytesRead, allocatedMemory, records, out more); } return ParseRecordList(records); } finally { if (allocatedMemory != IntPtr.Zero) { Marshal.FreeHGlobal(allocatedMemory); allocatedMemory = IntPtr.Zero; } } }