private void SaveUsnState_Click(object sender, RoutedEventArgs e) { _usnEntryDetail.Visibility = Visibility.Hidden; resultsLb.ItemsSource = null; resultsLb.Items.Clear(); Win32Api.USN_JOURNAL_DATA journalState = new Win32Api.USN_JOURNAL_DATA(); NtfsUsnJournal.UsnJournalReturnCode rtn = _usnJournal.GetUsnJournalState(ref journalState); FunctionElapsedTime.Content = string.Format("Save State->{0} elapsed time {1}(ms)", "GetUsnJournalState()", NtfsUsnJournal.ElapsedTime.Milliseconds.ToString()); if (rtn == NtfsUsnJournal.UsnJournalReturnCode.USN_JOURNAL_SUCCESS) { _usnCurrentJournalState = journalState; ListBoxItem lbItem = new ListBoxItem(); lbItem.Foreground = Brushes.Black; lbItem.Content = FormatUsnJournalState(journalState); resultsLb.Items.Add(lbItem); } else { ListBoxItem lbItem = new ListBoxItem(); lbItem.Content = string.Format("Save State->{0} returned error code: {1}", "GetUsnJournalState()", rtn.ToString()); lbItem.Foreground = Brushes.Red; resultsLb.Items.Add(lbItem); } }
public void Do_Backup() { Init_Volume(); _LastJournal = Vol.Refresh(); Vol.Map_Volume(); Vol.Update(_LastJournal); var r = Vol.GetDirectory(SourcePath); if (r != null) { var dst = DestnationPath + "\\test_" + Increment.ToString(); var src = ""; if (Increment == 0) { src = dst; } else { src = DestnationPath + "\\test_" + (Increment - 1).ToString(); } r.CopyTo(dst, src); } Increment += 1; }
public static bool Build_Volume_Mapping(SafeFileHandle roothandle, Win32Api.USN_JOURNAL_DATA currentUsnState, Action <Win32Api.UsnEntry> func) { Debug.WriteLine("Starting Build_Volume_Mapping"); DateTime startTime = DateTime.Now; Win32Api.MFT_ENUM_DATA med; med.StartFileReferenceNumber = 0; med.LowUsn = 0; med.HighUsn = currentUsnState.NextUsn; using (var med_struct = new StructWrapper(med)) using (var rawdata = new Raw_Array_Wrapper(BUF_LEN)) { uint outBytesReturned = 0; while (Win32Api.DeviceIoControl( roothandle.DangerousGetHandle(), Win32Api.FSCTL_ENUM_USN_DATA, med_struct.Ptr, med_struct.Size, rawdata.Ptr, rawdata.Size, out outBytesReturned, IntPtr.Zero)) { outBytesReturned = outBytesReturned - sizeof(Int64); IntPtr pUsnRecord = System.IntPtr.Add(rawdata.Ptr, sizeof(Int64));//need to skip 8 bytes because the first 8 bytes are to a usn number, which isnt in the structure while (outBytesReturned > 60) { var usnEntry = new Win32Api.UsnEntry(pUsnRecord); pUsnRecord = System.IntPtr.Add(pUsnRecord, (int)usnEntry.RecordLength); func(usnEntry); if (usnEntry.RecordLength > outBytesReturned) { outBytesReturned = 0;// prevent overflow } else { outBytesReturned -= usnEntry.RecordLength; } } Marshal.WriteInt64(med_struct.Ptr, Marshal.ReadInt64(rawdata.Ptr, 0));//read the usn that we skipped and place it into the nextusn } var possiblerror = Marshal.GetLastWin32Error(); if (possiblerror < 0) { throw new Win32Exception(possiblerror); } } Debug.WriteLine("Time took: " + (DateTime.Now - startTime).TotalMilliseconds + "ms"); return(true); }
public void SignalBackup() // to be called when full is performed //Console.WriteLine ("brd snapshot type="+brd.Snapshot.); { using (usnJ = new NtfsUsnJournal(brd /*.Snapshot.MountPoint*/)){ Win32Api.USN_JOURNAL_DATA journal = new Win32Api.USN_JOURNAL_DATA(); usnJ.GetUsnJournalState(ref journal); Logger.Append(Severity.DEBUG, "Current USN journal for '" + brd.Snapshot.MountPoint + "' " + journal.UsnJournalID + ", USN no: " + journal.NextUsn + ", maxSize=" + journal.MaximumSize / 1024 + "k, FirstEntry=" + journal.FirstUsn); journalId = (ulong)journal.UsnJournalID; transactionId = journal.NextUsn; journalMinUsn = journal.FirstUsn; } }
public void Position(string Path) { NtfsUsnJournal journal = new NtfsUsnJournal(Path); Win32Api.USN_JOURNAL_DATA journalData = new Win32Api.USN_JOURNAL_DATA(); var usnJournalReturnCode = journal.GetUsnJournalState(ref journalData); if (usnJournalReturnCode == NtfsUsnJournal.UsnJournalReturnCode.USN_JOURNAL_SUCCESS) { Console.WriteLine("Next USN: " + journalData.NextUsn); } }
public static void GetUsnJournalEntries(SafeFileHandle roothandle, Win32Api.USN_JOURNAL_DATA previousUsnState, UInt32 reasonMask, out List <Win32Api.UsnEntry> usnEntries, out Win32Api.USN_JOURNAL_DATA newUsnState) { usnEntries = new List <Win32Api.UsnEntry>(); newUsnState = new Win32Api.USN_JOURNAL_DATA(); QueryUsnJournal(roothandle, ref newUsnState); Win32Api.READ_USN_JOURNAL_DATA rujd = new Win32Api.READ_USN_JOURNAL_DATA(); rujd.StartUsn = previousUsnState.NextUsn; rujd.ReasonMask = reasonMask; rujd.ReturnOnlyOnClose = 0; rujd.Timeout = 0; rujd.bytesToWaitFor = 0; rujd.UsnJournalId = previousUsnState.UsnJournalID; using (var med_struct = new StructWrapper(rujd)) using (var rawdata = new Raw_Array_Wrapper(BUF_LEN)) { uint outBytesReturned = 0; var nextusn = previousUsnState.NextUsn; while (nextusn < newUsnState.NextUsn && Win32Api.DeviceIoControl( roothandle.DangerousGetHandle(), Win32Api.FSCTL_READ_USN_JOURNAL, med_struct.Ptr, med_struct.Size, rawdata.Ptr, rawdata.Size, out outBytesReturned, IntPtr.Zero)) { outBytesReturned = outBytesReturned - sizeof(Int64); IntPtr pUsnRecord = System.IntPtr.Add(rawdata.Ptr, sizeof(Int64)); //point safe arithmetic!~!! while (outBytesReturned > 60) // while there are at least one entry in the usn journal { var usnEntry = new Win32Api.UsnEntry(pUsnRecord); if (usnEntry.USN > newUsnState.NextUsn) { break; } usnEntries.Add(usnEntry); pUsnRecord = System.IntPtr.Add(pUsnRecord, (int)usnEntry.RecordLength);//point safe arithmetic!~!! outBytesReturned -= usnEntry.RecordLength; } nextusn = Marshal.ReadInt64(rawdata.Ptr, 0); Marshal.WriteInt64(med_struct.Ptr, nextusn);//read the usn that we skipped and place it into the nextusn } } }
private string FormatUsnJournalState(Win32Api.USN_JOURNAL_DATA _usnCurrentJournalState) { StringBuilder sb = new StringBuilder(); sb.AppendLine(string.Format("Journal ID: {0}", _usnCurrentJournalState.UsnJournalID.ToString("X"))); sb.AppendLine(string.Format(" First USN: {0}", _usnCurrentJournalState.FirstUsn.ToString("X"))); sb.AppendLine(string.Format(" Next USN: {0}", _usnCurrentJournalState.NextUsn.ToString("X"))); sb.AppendLine(); sb.AppendLine(string.Format("Lowest Valid USN: {0}", _usnCurrentJournalState.LowestValidUsn.ToString("X"))); sb.AppendLine(string.Format(" Max USN: {0}", _usnCurrentJournalState.MaxUsn.ToString("X"))); sb.AppendLine(string.Format(" Max Size: {0}", _usnCurrentJournalState.MaximumSize.ToString("X"))); sb.AppendLine(string.Format("Allocation Delta: {0}", _usnCurrentJournalState.AllocationDelta.ToString("X"))); return(sb.ToString()); }
public static Win32Api.USN_JOURNAL_DATA GetCurrentUSNJournalData(string DriveLetter) { NtfsUsnJournal journal = new NtfsUsnJournal(DriveLetter); Win32Api.USN_JOURNAL_DATA journalState = new Win32Api.USN_JOURNAL_DATA(); NtfsUsnJournal.UsnJournalReturnCode rtn = journal.GetUsnJournalState(ref journalState); if (rtn == NtfsUsnJournal.UsnJournalReturnCode.USN_JOURNAL_SUCCESS) { return(journalState); } else { throw new UsnJournalException(rtn); } }
private static readonly int BUF_LEN = 8192 + 8;//8 bytes for the leading USN public static void QueryUsnJournal(SafeFileHandle roothandle, ref Win32Api.USN_JOURNAL_DATA usnJournalState) { int sizeUsnJournalState = Marshal.SizeOf(usnJournalState); UInt32 cb; if (!Win32Api.DeviceIoControl( roothandle.DangerousGetHandle(), Win32Api.FSCTL_QUERY_USN_JOURNAL, IntPtr.Zero, 0, out usnJournalState, sizeUsnJournalState, out cb, IntPtr.Zero)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } }
public static Win32Api.USN_JOURNAL_DATA GetCurrentUSNJournalData(string DriveLetter) { NtfsUsnJournal journal = new NtfsUsnJournal(DriveLetter); Win32Api.USN_JOURNAL_DATA journalState = new Win32Api.USN_JOURNAL_DATA(); NtfsUsnJournal.UsnJournalReturnCode rtn = journal.GetUsnJournalState(ref journalState); if (rtn == NtfsUsnJournal.UsnJournalReturnCode.USN_JOURNAL_SUCCESS) { return journalState; } else { throw new UsnJournalException(rtn); } }
public void GetUSNDetails(string Mountpoint) { using (var journal = new NtfsUsnJournal(Mountpoint)) { Win32Api.USN_JOURNAL_DATA data = new Win32Api.USN_JOURNAL_DATA(); var usnJournalReturnCode = journal.GetUsnJournalState(ref data); if (usnJournalReturnCode == NtfsUsnJournal.UsnJournalReturnCode.USN_JOURNAL_SUCCESS) { Console.WriteLine("Journal ID: " + data.UsnJournalID); Console.WriteLine("Allocation Delta: " + data.AllocationDelta); Console.WriteLine("First USN: " + data.FirstUsn); Console.WriteLine("Lowest Valid USN: " + data.LowestValidUsn); Console.WriteLine("Max USN: " + data.MaxUsn); Console.WriteLine("Maximum Size: " + data.MaximumSize); Console.WriteLine("Next Usn: " + data.NextUsn); } else { Console.WriteLine("ERROR: " + usnJournalReturnCode.ToString()); } } }
private void FillListBoxWithUsnEntries(NtfsUsnJournal.UsnJournalReturnCode rtnCode, List <Win32Api.UsnEntry> usnEntries, Win32Api.USN_JOURNAL_DATA newUsnState) { FunctionElapsedTime.Content = string.Format("'View Changes'->{0} elapsed time {1}(ms)", "GetUsnJournalEntries()", NtfsUsnJournal.ElapsedTime.Milliseconds.ToString()); if (rtnCode == NtfsUsnJournal.UsnJournalReturnCode.USN_JOURNAL_SUCCESS) { if (usnEntries.Count > 0) { _entryDetail = UsnEntryDetail.EntryDetail.UsnEntry; resultsLb.ItemsSource = usnEntries; UpdateUsnStateDialog updateUsnStateDlg = new UpdateUsnStateDialog(this); updateUsnStateDlg.Owner = this; bool?bRtn = updateUsnStateDlg.ShowDialog(); if (bRtn != null && bRtn.Value) { _usnCurrentJournalState = newUsnState; } } else { ListBoxItem lbItem = new ListBoxItem(); lbItem.Content = string.Format("'View Changes'-> No Journal entries found"); lbItem.Foreground = Brushes.Red; resultsLb.Items.Add(lbItem); } } else { ListBoxItem lbItem = new ListBoxItem(); lbItem.Content = string.Format("'View Changes'->{0} returned error code: {1}", "GetUsnJournalEntries()", rtnCode.ToString()); lbItem.Foreground = Brushes.Red; resultsLb.Items.Add(lbItem); } Cursor = Cursors.Arrow; }
public void BeginScan() { //clear parentFileReferenceIdentifiers.Clear(); USNEntries.Clear(); USNDirectories.Clear(); usnCurrentJournalState = new Win32Api.USN_JOURNAL_DATA(); //1 phase; handle try { usnJournal = new NtfsUsnJournal(selectedVolume); OnEntryAmountUpdate(true); } catch (Exception) { OnEntryAmountUpdate(false); return; } //2 phase; current state Win32Api.USN_JOURNAL_DATA journalState = new Win32Api.USN_JOURNAL_DATA(); NtfsUsnJournal.UsnJournalReturnCode rtn = usnJournal.GetUsnJournalState(ref journalState); if (rtn == NtfsUsnJournal.UsnJournalReturnCode.USN_JOURNAL_SUCCESS) { usnCurrentJournalState = journalState; OnEntryAmountUpdate(true); } else { OnEntryAmountUpdate(false); return; } //3 phase; query uint reasonMask = Win32Api.USN_REASON_DATA_OVERWRITE | Win32Api.USN_REASON_DATA_EXTEND | Win32Api.USN_REASON_NAMED_DATA_OVERWRITE | Win32Api.USN_REASON_NAMED_DATA_TRUNCATION | Win32Api.USN_REASON_FILE_CREATE | Win32Api.USN_REASON_FILE_DELETE | Win32Api.USN_REASON_EA_CHANGE | Win32Api.USN_REASON_SECURITY_CHANGE | Win32Api.USN_REASON_RENAME_OLD_NAME | Win32Api.USN_REASON_RENAME_NEW_NAME | Win32Api.USN_REASON_INDEXABLE_CHANGE | Win32Api.USN_REASON_BASIC_INFO_CHANGE | Win32Api.USN_REASON_HARD_LINK_CHANGE | Win32Api.USN_REASON_COMPRESSION_CHANGE | Win32Api.USN_REASON_ENCRYPTION_CHANGE | Win32Api.USN_REASON_OBJECT_ID_CHANGE | Win32Api.USN_REASON_REPARSE_POINT_CHANGE | Win32Api.USN_REASON_STREAM_CHANGE | Win32Api.USN_REASON_CLOSE; OldestUSN = usnCurrentJournalState.FirstUsn; NtfsUsnJournal.UsnJournalReturnCode rtnCode = usnJournal.GetUsnJournalEntries(usnCurrentJournalState, reasonMask, out List <Win32Api.UsnEntry> usnEntries, out usnCurrentJournalState); if (rtnCode == NtfsUsnJournal.UsnJournalReturnCode.USN_JOURNAL_SUCCESS) { OnEntryAmountUpdate(true); //4 phase ResolveIdentifiers(usnEntries); OnEntryAmountUpdate(true); //5 phase AddEntries(usnEntries); OnEntryAmountUpdate(true); OnWorkEnded(); } else { OnEntryAmountUpdate(false); return; } }
public MainWindow() { InitializeComponent(); _usnCurrentJournalState = new Win32Api.USN_JOURNAL_DATA(); }
private Dictionary <int, Win32Api.UsnEntry> GetUsnRecordsDictionary() { PrivilegesManager pm = new PrivilegesManager(); pm.Grant(); Dictionary <int, Win32Api.UsnEntry> uEntries = new Dictionary <int, Win32Api.UsnEntry>(); using (usnJ = new NtfsUsnJournal(/*brd.SystemDrive.MountPoint*/ brd /*.Snapshot.MountPoint*/)){ Logger.Append(Severity.DEBUG, "Reading USN journal " + journalId + " for '" + brd.SystemDrive.MountPoint + "' from seq " + prevTransactionId + " to seq " + transactionId + " (changed entries from " + Utilities.Utils.GetLocalDateTimeFromUnixTime(refTimeStamp).ToString() + " to " + Utilities.Utils.GetLocalDateTimeFromUnixTime(brd.Snapshot.TimeStamp).ToLocalTime().ToString() + ")"); Win32Api.USN_JOURNAL_DATA stateJd = new Win32Api.USN_JOURNAL_DATA(); stateJd.UsnJournalID = journalId; stateJd.NextUsn = prevTransactionId; Win32Api.USN_JOURNAL_DATA newState = new Win32Api.USN_JOURNAL_DATA(); // unused, as we maintain our own state List <Win32Api.UsnEntry> changedUsnEntries = new List <Win32Api.UsnEntry>(); usnJ.GetUsnJournalState(ref newState); NtfsUsnJournal.UsnJournalReturnCode retCode = usnJ.GetUsnJournalEntries(stateJd, refTimeStamp, 0xFFFFFFFF, out changedUsnEntries, out newState); if (retCode != NtfsUsnJournal.UsnJournalReturnCode.USN_JOURNAL_SUCCESS) { throw new Exception(retCode.ToString()); } int entryId = 0; foreach (Win32Api.UsnEntry ue in changedUsnEntries) { if (ue != null && ue.Reason > 0) { entryId = (int)(ue.FileReferenceNumber); //if(ue.Name.StartsWith("grut")) //Console.WriteLine ("|--------| USN seq="+ue.USN+", item "+entryId+" ("+ue.Name+") "+((NtfsUsnJournal.UsnReasonCode)ue.Reason).ToString()); if (!uEntries.ContainsKey(entryId)) { uEntries[entryId] = ue; } else // cumulate reason flags // ignore created+deleted (temporary or short-lived (between 2 backups) items { if ( ((Win32Api.UsnReasonCode)ue.Reason).HasFlag(Win32Api.UsnReasonCode.USN_REASON_FILE_DELETE) && ((Win32Api.UsnReasonCode)uEntries[entryId].Reason).HasFlag(Win32Api.UsnReasonCode.USN_REASON_FILE_CREATE) ) { Console.WriteLine("*** item " + ue.Name + " CREATED+DELETED"); continue; } // file ID reused (file delete + new create) : totally replace previous entry else if ( ((Win32Api.UsnReasonCode)ue.Reason).HasFlag(Win32Api.UsnReasonCode.USN_REASON_FILE_CREATE) && ((Win32Api.UsnReasonCode)uEntries[entryId].Reason).HasFlag(Win32Api.UsnReasonCode.USN_REASON_FILE_DELETE) ) { uEntries[entryId] = ue; } // cumulate flags else if (!((Win32Api.UsnReasonCode)uEntries[entryId].Reason).HasFlag(((Win32Api.UsnReasonCode)ue.Reason))) { Win32Api.UsnReasonCode newReason = ((Win32Api.UsnReasonCode)uEntries[entryId].Reason) | ((Win32Api.UsnReasonCode)ue.Reason); uEntries[entryId] = ue; uEntries[entryId].Reason = (uint)newReason; } // only keep the last rename operation /*if(((NtfsUsnJournal.UsnReasonCode)ue.Reason).HasFlag(NtfsUsnJournal.UsnReasonCode.USN_REASON_RENAME_NEW_NAME) ){ * Console.WriteLine ("*** item "+ue.Name+" RENAMED (reasons="+((NtfsUsnJournal.UsnReasonCode)ue.Reason).ToString()); * NtfsUsnJournal.UsnReasonCode newReason = ((NtfsUsnJournal.UsnReasonCode)entries[entryId].Reason) ; * if(!((NtfsUsnJournal.UsnReasonCode)entries[entryId].Reason).HasFlag(NtfsUsnJournal.UsnReasonCode.USN_REASON_RENAME_NEW_NAME) ) * newReason |= NtfsUsnJournal.UsnReasonCode.USN_REASON_RENAME_NEW_NAME; * entries[entryId] = ue; * entries[entryId].Reason = (uint)newReason; * }*/ } } } Logger.Append(Severity.TRIVIA, "Done reading USN journal " + journalId + " for '" + brd.SystemDrive.MountPoint); } //end using return(uEntries); }
/// <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(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(pUsnRecord.ToInt32() + usnEntry.RecordLength); outBytesReturned -= usnEntry.RecordLength; } Marshal.WriteInt64(medBuffer, Marshal.ReadInt64(pData, 0)); } Marshal.FreeHGlobal(pData); }
public static List <Win32Api.UsnEntry> Get_Changes(SafeFileHandle roothandle, Win32Api.USN_JOURNAL_DATA startUsnState) { uint reasonMask = Win32Api.USN_REASON_DATA_OVERWRITE | Win32Api.USN_REASON_DATA_EXTEND | Win32Api.USN_REASON_NAMED_DATA_OVERWRITE | Win32Api.USN_REASON_NAMED_DATA_TRUNCATION | Win32Api.USN_REASON_FILE_CREATE | Win32Api.USN_REASON_FILE_DELETE | Win32Api.USN_REASON_EA_CHANGE | Win32Api.USN_REASON_SECURITY_CHANGE | Win32Api.USN_REASON_RENAME_OLD_NAME | Win32Api.USN_REASON_RENAME_NEW_NAME | Win32Api.USN_REASON_INDEXABLE_CHANGE | Win32Api.USN_REASON_BASIC_INFO_CHANGE | Win32Api.USN_REASON_HARD_LINK_CHANGE | Win32Api.USN_REASON_COMPRESSION_CHANGE | Win32Api.USN_REASON_ENCRYPTION_CHANGE | Win32Api.USN_REASON_OBJECT_ID_CHANGE | Win32Api.USN_REASON_REPARSE_POINT_CHANGE | Win32Api.USN_REASON_STREAM_CHANGE | Win32Api.USN_REASON_CLOSE; var changes = new List <Win32Api.UsnEntry>(); Win32Api.USN_JOURNAL_DATA newUsnState; GetUsnJournalEntries(roothandle, startUsnState, reasonMask, out changes, out newUsnState); return(changes); }
public static void GetUsnJournalEntries(SafeFileHandle roothandle, Win32Api.USN_JOURNAL_DATA previousUsnState, UInt32 reasonMask, out List<Win32Api.UsnEntry> usnEntries, out Win32Api.USN_JOURNAL_DATA newUsnState) { usnEntries = new List<Win32Api.UsnEntry>(); newUsnState = new Win32Api.USN_JOURNAL_DATA(); QueryUsnJournal(roothandle, ref newUsnState); Win32Api.READ_USN_JOURNAL_DATA rujd = new Win32Api.READ_USN_JOURNAL_DATA(); rujd.StartUsn = previousUsnState.NextUsn; rujd.ReasonMask = reasonMask; rujd.ReturnOnlyOnClose = 0; rujd.Timeout = 0; rujd.bytesToWaitFor = 0; rujd.UsnJournalId = previousUsnState.UsnJournalID; using(var med_struct = new StructWrapper(rujd)) using(var rawdata = new Raw_Array_Wrapper(BUF_LEN)) { uint outBytesReturned = 0; var nextusn = previousUsnState.NextUsn; while(nextusn < newUsnState.NextUsn && Win32Api.DeviceIoControl( roothandle.DangerousGetHandle(), Win32Api.FSCTL_READ_USN_JOURNAL, med_struct.Ptr, med_struct.Size, rawdata.Ptr, rawdata.Size, out outBytesReturned, IntPtr.Zero)) { outBytesReturned = outBytesReturned - sizeof(Int64); IntPtr pUsnRecord = System.IntPtr.Add(rawdata.Ptr, sizeof(Int64));//point safe arithmetic!~!! while(outBytesReturned > 60) // while there are at least one entry in the usn journal { var usnEntry = new Win32Api.UsnEntry(pUsnRecord); if(usnEntry.USN > newUsnState.NextUsn) break; usnEntries.Add(usnEntry); pUsnRecord = System.IntPtr.Add(pUsnRecord, (int)usnEntry.RecordLength);//point safe arithmetic!~!! outBytesReturned -= usnEntry.RecordLength; } nextusn = Marshal.ReadInt64(rawdata.Ptr, 0); Marshal.WriteInt64(med_struct.Ptr, nextusn);//read the usn that we skipped and place it into the nextusn } } }