private void QueryUsnJournal_Click(object sender, RoutedEventArgs e) { e.Handled = true; _usnEntryDetail.Visibility = Visibility.Hidden; resultsLb.ItemsSource = null; resultsLb.Items.Clear(); var journalState = new Win32Api.USN_JOURNAL_DATA_V0(); var rtn = Journal.GetUsnJournalState(ref journalState); FunctionElapsedTime.Content = string.Format(CultureInfo.InvariantCulture, "Query->{0} duration: {1} (ms)", "GetUsnJournalState", NtfsUsnJournal.ElapsedTime.TotalMilliseconds); if (rtn == (int)NtfsUsnJournal.UsnJournalReturnCode.USN_JOURNAL_SUCCESS) { var lbItem = new ListBoxItem { Foreground = Brushes.Black, Content = FormatUsnJournalState(journalState) }; resultsLb.Items.Add(lbItem); } else { var lbItem = new ListBoxItem { Content = string.Format(CultureInfo.InvariantCulture, "Query->{0} returned error code: {1}", "GetUsnJournalState", rtn), Foreground = Brushes.Red }; resultsLb.Items.Add(lbItem); } }
/// <summary>Tests to see if the USN journal is active on the volume.</summary> /// <returns>true if USN journal is active, false if no USN journal on volume</returns> public bool IsUsnJournalActive() { var success = false; var sw = new Stopwatch(); sw.Start(); if (bNtfsVolume) { if (_usnJournalRootHandle.ToInt64() != Win32Api.INVALID_HANDLE_VALUE) { var usnJournalCurrentState = new Win32Api.USN_JOURNAL_DATA_V0(); var lastError = QueryUsnJournal(ref usnJournalCurrentState); if (lastError == (int)UsnJournalReturnCode.USN_JOURNAL_SUCCESS) { success = true; } } } ElapsedTime = TimeSpan.FromMilliseconds(sw.ElapsedMilliseconds); return(success); }
/// <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> private int QueryUsnJournal(ref Win32Api.USN_JOURNAL_DATA_V0 usnJournalState) { uint cb; Win32Api.DeviceIoControl(_usnJournalRootHandle, Win32Api.FSCTL_QUERY_USN_JOURNAL, IntPtr.Zero, 0, out usnJournalState, Marshal.SizeOf(usnJournalState), out cb, IntPtr.Zero); return(Marshal.GetLastWin32Error()); }
private static string FormatUsnJournalState(Win32Api.USN_JOURNAL_DATA_V0 _usnCurrentJournalState) { var sb = new StringBuilder(); sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "Journal ID: {0}", _usnCurrentJournalState.UsnJournalID.ToString("X", CultureInfo.InvariantCulture))); sb.AppendLine(string.Format(CultureInfo.InvariantCulture, " First USN: {0}", _usnCurrentJournalState.FirstUsn.ToString("X", CultureInfo.InvariantCulture))); sb.AppendLine(string.Format(CultureInfo.InvariantCulture, " Next USN: {0}", _usnCurrentJournalState.NextUsn.ToString("X", CultureInfo.InvariantCulture))); sb.AppendLine(); sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "Lowest Valid USN: {0}", _usnCurrentJournalState.LowestValidUsn.ToString("X", CultureInfo.InvariantCulture))); sb.AppendLine(string.Format(CultureInfo.InvariantCulture, " Max USN: {0}", _usnCurrentJournalState.MaxUsn.ToString("X", CultureInfo.InvariantCulture))); sb.AppendLine(string.Format(CultureInfo.InvariantCulture, " Max Size: {0}", _usnCurrentJournalState.MaximumSize.ToString("X", CultureInfo.InvariantCulture))); sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "Allocation Delta: {0}", _usnCurrentJournalState.AllocationDelta.ToString("X", CultureInfo.InvariantCulture))); return(sb.ToString()); }
private void FillListBoxWithUsnEntries(NtfsUsnJournal.UsnJournalReturnCode rtnCode, List <Win32Api.UsnEntry> usnEntries, Win32Api.USN_JOURNAL_DATA_V0 newUsnState) { FunctionElapsedTime.Content = string.Format(CultureInfo.InvariantCulture, "'View Changes'->{0} duration: {1} (ms)", "GetUsnJournalEntries", NtfsUsnJournal.ElapsedTime.TotalMilliseconds); if (rtnCode == NtfsUsnJournal.UsnJournalReturnCode.USN_JOURNAL_SUCCESS) { if (usnEntries.Count > 0) { _entryDetail = UsnEntryDetail.EntryDetail.UsnEntry; resultsLb.ItemsSource = usnEntries; var updateUsnStateDlg = new UpdateUsnStateDialog(this) { Owner = this }; var bRtn = updateUsnStateDlg.ShowDialog(); if (bRtn != null && bRtn.Value) { _usnCurrentJournalState = newUsnState; } } else { var lbItem = new ListBoxItem { Content = "\'View Changes\'-> No Journal entries found", Foreground = Brushes.Red }; resultsLb.Items.Add(lbItem); } } else { var lbItem = new ListBoxItem { Content = string.Format(CultureInfo.InvariantCulture, "'View Changes'->{0} returned error code: {1}", "GetUsnJournalEntries", rtnCode), Foreground = Brushes.Red }; resultsLb.Items.Add(lbItem); } Cursor = Cursors.Arrow; }
/// <summary>Tests to see if there is a USN journal on this volume and if there is determines whether any journal entries have been lost.</summary> /// <returns>true if the USN journal is active and if the JournalId's are the same /// and if all the USN journal entries expected by the previous state are available /// from the current state. false if not. /// </returns> public bool IsUsnJournalValid(Win32Api.USN_JOURNAL_DATA_V0 usnJournalPreviousState) { var usnJournalState = new Win32Api.USN_JOURNAL_DATA_V0(); var sw = new Stopwatch(); sw.Start(); var success = bNtfsVolume && _usnJournalRootHandle.ToInt64() != Win32Api.INVALID_HANDLE_VALUE && QueryUsnJournal(ref usnJournalState) == (int)UsnJournalReturnCode.USN_JOURNAL_SUCCESS && usnJournalPreviousState.UsnJournalID == usnJournalState.UsnJournalID && usnJournalPreviousState.NextUsn >= usnJournalState.NextUsn; ElapsedTime = TimeSpan.FromMilliseconds(sw.ElapsedMilliseconds); return(success); }
/// <summary>GetUsnJournalState() gets the current state of the USN journal if it is active.</summary> /// <param name="usnJournalState"> /// Reference to USN journal data object filled with the current USN journal state. /// </param> /// <param name="elapsedTime">The elapsed time for the GetUsnJournalState() function call.</param> /// <returns> /// USN_JOURNAL_SUCCESS GetUsnJournalState() function succeeded. /// VOLUME_NOT_NTFS volume is not an NTFS volume. /// INVALID_HANDLE_VALUE NtfsUsnJournal object failed initialization. /// USN_JOURNAL_NOT_ACTIVE USN journal is not active on volume. /// ERROR_ACCESS_DENIED accessing the USN journal requires admin rights, see remarks. /// ERROR_INVALID_FUNCTION error generated by DeviceIoControl() call. /// ERROR_FILE_NOT_FOUND error generated by DeviceIoControl() call. /// ERROR_PATH_NOT_FOUND error generated by DeviceIoControl() call. /// ERROR_TOO_MANY_OPEN_FILES error generated by DeviceIoControl() call. /// ERROR_INVALID_HANDLE error generated by DeviceIoControl() call. /// ERROR_INVALID_DATA error generated by DeviceIoControl() call. /// ERROR_NOT_SUPPORTED error generated by DeviceIoControl() call. /// ERROR_INVALID_PARAMETER error generated by DeviceIoControl() call. /// ERROR_JOURNAL_DELETE_IN_PROGRESS USN journal delete is in progress. /// ERROR_INVALID_USER_BUFFER error generated by DeviceIoControl() call. /// USN_JOURNAL_ERROR unspecified USN journal error. /// </returns> /// <remarks> /// If function returns ERROR_ACCESS_DENIED you need to run application as an Administrator. /// </remarks> public int GetUsnJournalState(ref Win32Api.USN_JOURNAL_DATA_V0 usnJournalState) { var lastError = (int)UsnJournalReturnCode.VOLUME_NOT_NTFS; var sw = new Stopwatch(); sw.Start(); if (bNtfsVolume) { lastError = _usnJournalRootHandle.ToInt64() == Win32Api.INVALID_HANDLE_VALUE ? (int)UsnJournalReturnCode.INVALID_HANDLE_VALUE : QueryUsnJournal(ref usnJournalState); } ElapsedTime = TimeSpan.FromMilliseconds(sw.ElapsedMilliseconds); return(lastError); }
/// <summary> /// DeleteUsnJournal() deletes a USN journal on the volume. If no USN journal exists, this /// function simply returns success. /// </summary> /// <param name="journalState">USN_JOURNAL_DATA object for this volume</param> /// <returns>a UsnJournalReturnCode /// USN_JOURNAL_SUCCESS DeleteUsnJournal() function succeeded. /// VOLUME_NOT_NTFS volume is not an NTFS volume. /// INVALID_HANDLE_VALUE NtfsUsnJournal object failed initialization. /// USN_JOURNAL_NOT_ACTIVE USN journal is not active on volume. /// ERROR_ACCESS_DENIED accessing the USN journal requires admin rights, see remarks. /// ERROR_INVALID_FUNCTION error generated by DeviceIoControl() call. /// ERROR_FILE_NOT_FOUND error generated by DeviceIoControl() call. /// ERROR_PATH_NOT_FOUND error generated by DeviceIoControl() call. /// ERROR_TOO_MANY_OPEN_FILES error generated by DeviceIoControl() call. /// ERROR_INVALID_HANDLE error generated by DeviceIoControl() call. /// ERROR_INVALID_DATA error generated by DeviceIoControl() call. /// ERROR_NOT_SUPPORTED error generated by DeviceIoControl() call. /// ERROR_INVALID_PARAMETER error generated by DeviceIoControl() call. /// ERROR_JOURNAL_DELETE_IN_PROGRESS USN journal delete is in progress. /// ERROR_INVALID_USER_BUFFER error generated by DeviceIoControl() call. /// USN_JOURNAL_ERROR unspecified USN journal error. /// </returns> /// <remarks> /// If function returns ERROR_ACCESS_DENIED you need to run application as an Administrator. /// </remarks> public int DeleteUsnJournal(Win32Api.USN_JOURNAL_DATA_V0 journalState) { var lastError = (int)UsnJournalReturnCode.VOLUME_NOT_NTFS; var sw = new Stopwatch(); sw.Start(); if (bNtfsVolume) { if (_usnJournalRootHandle.ToInt64() != Win32Api.INVALID_HANDLE_VALUE) { uint cb; var dujd = new Win32Api.DELETE_USN_JOURNAL_DATA { UsnJournalID = journalState.UsnJournalID, DeleteFlags = (uint)Win32Api.UsnJournalDeleteFlags.USN_DELETE_FLAG_DELETE }; var sizeDujd = Marshal.SizeOf(dujd); var dujdBuffer = Marshal.AllocHGlobal(sizeDujd); Win32Api.ZeroMemory(dujdBuffer, sizeDujd); Marshal.StructureToPtr(dujd, dujdBuffer, true); Win32Api.DeviceIoControl(_usnJournalRootHandle, Win32Api.FSCTL_DELETE_USN_JOURNAL, dujdBuffer, sizeDujd, IntPtr.Zero, 0, out cb, IntPtr.Zero); lastError = Marshal.GetLastWin32Error(); Marshal.FreeHGlobal(dujdBuffer); } else { lastError = (int)UsnJournalReturnCode.INVALID_HANDLE_VALUE; } } ElapsedTime = TimeSpan.FromMilliseconds(sw.ElapsedMilliseconds); return(lastError); }
/// <summary>Given a previous state, GetUsnJournalEntries() determines if the USN journal is active and /// no USN journal entries have been lost (i.e. USN journal is valid), then /// it loads a SortedList<UInt64, Win32Api.UsnEntry> list and returns it as the out parameter 'usnEntries'. /// If GetUsnJournalChanges returns anything but USN_JOURNAL_SUCCESS, the usnEntries list will /// be empty. /// </summary> /// <param name="previousUsnState">The USN journal state the last time volume changes were requested.</param> /// <param name="reasonMask"></param> /// <param name="usnEntries"></param> /// <param name="newUsnState"></param> /// <returns> /// USN_JOURNAL_SUCCESS GetUsnJournalChanges() function succeeded. /// VOLUME_NOT_NTFS volume is not an NTFS volume. /// INVALID_HANDLE_VALUE NtfsUsnJournal object failed initialization. /// USN_JOURNAL_NOT_ACTIVE USN journal is not active on volume. /// ERROR_ACCESS_DENIED accessing the USN journal requires admin rights, see remarks. /// ERROR_INVALID_FUNCTION error generated by DeviceIoControl() call. /// ERROR_FILE_NOT_FOUND error generated by DeviceIoControl() call. /// ERROR_PATH_NOT_FOUND error generated by DeviceIoControl() call. /// ERROR_TOO_MANY_OPEN_FILES error generated by DeviceIoControl() call. /// ERROR_INVALID_HANDLE error generated by DeviceIoControl() call. /// ERROR_INVALID_DATA error generated by DeviceIoControl() call. /// ERROR_NOT_SUPPORTED error generated by DeviceIoControl() call. /// ERROR_INVALID_PARAMETER error generated by DeviceIoControl() call. /// ERROR_JOURNAL_DELETE_IN_PROGRESS USN journal delete is in progress. /// ERROR_INVALID_USER_BUFFER error generated by DeviceIoControl() call. /// USN_JOURNAL_ERROR unspecified USN journal error. /// </returns> /// <remarks> /// If function returns ERROR_ACCESS_DENIED you need to run application as an Administrator. /// </remarks> public int GetUsnJournalEntries(Win32Api.USN_JOURNAL_DATA_V0 previousUsnState, uint reasonMask, out List <Win32Api.UsnEntry> usnEntries, out Win32Api.USN_JOURNAL_DATA_V0 newUsnState) { usnEntries = new List <Win32Api.UsnEntry>(); newUsnState = new Win32Api.USN_JOURNAL_DATA_V0(); var lastError = (int)UsnJournalReturnCode.VOLUME_NOT_NTFS; var sw = new Stopwatch(); sw.Start(); if (bNtfsVolume) { if (_usnJournalRootHandle.ToInt64() != Win32Api.INVALID_HANDLE_VALUE) { // Get current USN journal state. lastError = QueryUsnJournal(ref newUsnState); if (lastError == (int)UsnJournalReturnCode.USN_JOURNAL_SUCCESS) { var bReadMore = true; // Sequentially process the USN journal looking for image file entries. const int pbDataSize = sizeof(ulong) * 16384; var pbData = Marshal.AllocHGlobal(pbDataSize); Win32Api.ZeroMemory(pbData, pbDataSize); var rujd = new Win32Api.READ_USN_JOURNAL_DATA_V0 { StartUsn = (ulong)previousUsnState.NextUsn, ReasonMask = reasonMask, ReturnOnlyOnClose = 0, Timeout = 0, BytesToWaitFor = 0, UsnJournalId = previousUsnState.UsnJournalID }; var sizeRujd = Marshal.SizeOf(rujd); var rujdBuffer = Marshal.AllocHGlobal(sizeRujd); Win32Api.ZeroMemory(rujdBuffer, sizeRujd); Marshal.StructureToPtr(rujd, rujdBuffer, true); // Read USN journal entries. while (bReadMore) { uint outBytesReturned; var bRtn = Win32Api.DeviceIoControl(_usnJournalRootHandle, Win32Api.FSCTL_READ_USN_JOURNAL, rujdBuffer, sizeRujd, pbData, pbDataSize, out outBytesReturned, IntPtr.Zero); if (bRtn) { var pUsnRecord = new IntPtr(pbData.ToInt64() + sizeof(ulong)); // While there is at least one entry in the USN journal. while (outBytesReturned > 60) { var usnEntry = new Win32Api.UsnEntry(pUsnRecord); // Only read until the current usn points beyond the current state's USN. if (usnEntry.USN >= newUsnState.NextUsn) { bReadMore = false; break; } usnEntries.Add(usnEntry); pUsnRecord = new IntPtr(pUsnRecord.ToInt64() + usnEntry.RecordLength); outBytesReturned -= usnEntry.RecordLength; } } else { var lastWin32Error = Marshal.GetLastWin32Error(); if (lastWin32Error == (int)Win32Api.GetLastErrorEnum.ERROR_HANDLE_EOF) { lastError = (int)UsnJournalReturnCode.USN_JOURNAL_SUCCESS; } break; } var nextUsn = Marshal.ReadInt64(pbData, 0); if (nextUsn >= newUsnState.NextUsn) { break; } Marshal.WriteInt64(rujdBuffer, nextUsn); } Marshal.FreeHGlobal(rujdBuffer); Marshal.FreeHGlobal(pbData); } } else { lastError = (int)UsnJournalReturnCode.INVALID_HANDLE_VALUE; } } ElapsedTime = TimeSpan.FromMilliseconds(sw.ElapsedMilliseconds); return(lastError); }
/// <summary>Returns an enumerable collection of <see cref="Win32Api.UsnEntry"/> entries that meet specified criteria.</summary> /// <param name="onlyFolders"></param> /// <param name="filter">The filter.</param> private IEnumerable <Win32Api.UsnEntry> EnumerateUsnEntries(bool?onlyFolders, string filter = null) { var usnState = new Win32Api.USN_JOURNAL_DATA_V0(); if (QueryUsnJournal(ref usnState) != (int)UsnJournalReturnCode.USN_JOURNAL_SUCCESS) { throw new Win32Exception("Failed to query the USN journal on the volume."); } if (string.IsNullOrWhiteSpace(filter) || filter.Equals("*", StringComparison.Ordinal)) { filter = null; } var fileTypes = null != filter?filter.Split(' ', ',', ';') : null; // Set up MFT_ENUM_DATA_V0 structure. var mftData = new Win32Api.MFT_ENUM_DATA_V0 { StartFileReferenceNumber = 0, LowUsn = 0, HighUsn = usnState.NextUsn }; var mftDataSize = Marshal.SizeOf(mftData); var mftDataBuffer = Marshal.AllocHGlobal(mftDataSize); Win32Api.ZeroMemory(mftDataBuffer, mftDataSize); Marshal.StructureToPtr(mftData, mftDataBuffer, true); // Set up the data buffer which receives the USN_RECORD data. const int pDataSize = sizeof(ulong) + 10000; var pData = Marshal.AllocHGlobal(pDataSize); Win32Api.ZeroMemory(pData, pDataSize); uint outBytesReturned; // Gather up volume's directories. while (Win32Api.DeviceIoControl(_usnJournalRootHandle, Win32Api.FSCTL_ENUM_USN_DATA, mftDataBuffer, mftDataSize, pData, pDataSize, out outBytesReturned, IntPtr.Zero)) { var pUsnRecord = new IntPtr(pData.ToInt64() + sizeof(long)); // While there is at least one entry in the USN journal. while (outBytesReturned > 60) { var usnEntry = new Win32Api.UsnEntry(pUsnRecord); if (null == onlyFolders) { yield return(usnEntry); } else if (usnEntry.IsFolder) { if ((bool)onlyFolders) { yield return(usnEntry); } } else if (!(bool)onlyFolders) { if (null == filter) { yield return(usnEntry); } else { var extension = Path.GetExtension(usnEntry.Name); if (!string.IsNullOrEmpty(extension)) { foreach (var fileType in fileTypes) { if (fileType.Contains("*")) { if (extension.IndexOf(fileType.Trim('*'), StringComparison.OrdinalIgnoreCase) >= 0) { yield return(usnEntry); } } else if (extension.Equals("." + fileType.TrimStart('.'), StringComparison.OrdinalIgnoreCase)) { yield return(usnEntry); } } } } } pUsnRecord = new IntPtr(pUsnRecord.ToInt64() + usnEntry.RecordLength); outBytesReturned -= usnEntry.RecordLength; } Marshal.WriteInt64(mftDataBuffer, Marshal.ReadInt64(pData, 0)); } Marshal.FreeHGlobal(pData); }
public MainWindow() { InitializeComponent(); _usnCurrentJournalState = new Win32Api.USN_JOURNAL_DATA_V0(); }