Пример #1
0
        public static void PrintUsnEntry(IConsole console, UsnJournal usnJournal, UsnEntry usnEntry)
        {
            console.WriteLine();
            console.WriteLine($"{"USN:",-20}{usnEntry.USN:X}");
            console.WriteLine(usnEntry.IsFolder
                ? $"{"Directory:",-20}{usnEntry.Name}"
                : $"{"File:",-20}{usnEntry.Name}");
            if (usnJournal.TryGetPathFromFileId(usnEntry.ParentFileReferenceNumber, out var path))
            {
                path = $"{usnJournal.VolumeName.TrimEnd('\\')}{path}";
                console.WriteLine($"{"Parent:",-20}{path}");
            }

            if (usnEntry.TimeStamp > 0)
            {
                console.WriteLine($"{"Timestamp:",-20}{DateTime.FromFileTimeUtc(usnEntry.TimeStamp).ToLocalTime()}");
            }

            console.WriteLine($"{"File ID:",-20}{usnEntry.FileReferenceNumber:X}");
            console.WriteLine($"{"Parent File ID:",-20}{usnEntry.ParentFileReferenceNumber:X}");

            var reason = ((UsnReason)usnEntry.Reason).ToString().Replace(',', '|');

            console.WriteLine($"{"Reason:",-20}{reason}");

            var sourceInfo = ((UsnSource)usnEntry.SourceInfo).ToString().Replace(',', '|');

            console.WriteLine($"{"Source Info:",-20}{sourceInfo}");
        }
 public FileAndDirectoryEntry(UsnEntry usnEntry, string path)
 {
     this.fileReferenceNumber       = usnEntry.FileReferenceNumber;
     this.parentFileReferenceNumber = usnEntry.ParentFileReferenceNumber;
     this.fileName = usnEntry.FileName;
     this.isFolder = usnEntry.IsFolder;
     this.path     = path;
 }
 public FileAndDirectoryEntry(UsnEntry usnEntry, string path)
 {
     this.fileReferenceNumber       = usnEntry.FileReferenceNumber;
     this.parentFileReferenceNumber = usnEntry.ParentFileReferenceNumber;
     this.fileName = usnEntry.FileName;
     this.isFolder = usnEntry.IsFolder;
     this.isHidden = usnEntry.IsHidden;
     this.isNormal = usnEntry.IsNormal;
     this.isSys    = usnEntry.IsSys;
     this.path     = path;
 }
Пример #4
0
 public static void PrintEntryPath(IConsole console, UsnJournal usnJournal, UsnEntry usnEntry)
 {
     console.WriteLine();
     console.WriteLine($"{"Name:",-20}{usnEntry.Name}");
     console.WriteLine($"{"IsFolder:",-20}{usnEntry.IsFolder}");
     if (usnJournal.TryGetPathFromFileId(usnEntry.ParentFileReferenceNumber, out var path))
     {
         path = $"{usnJournal.VolumeName.TrimEnd('\\')}{path}";
         console.WriteLine($"{"Parent:",-20}{path}");
     }
 }
Пример #5
0
        public IEnumerable <UsnEntry> ReadUsnEntries(USN_JOURNAL_DATA_V0 previousUsnState, uint reasonMask, string filter, bool?onlyFiles)
        {
            var newUsnState = new USN_JOURNAL_DATA_V0();
            var lastError   = (int)UsnJournalReturnCode.VOLUME_NOT_NTFS;

            if (_isNtfsVolume)
            {
                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 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)
                        {
                            var bRtn = Win32Api.DeviceIoControl(_usnJournalRootHandle, Win32Api.FSCTL_READ_USN_JOURNAL, rujdBuffer, sizeRujd, pbData, pbDataSize, out var 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 UsnEntry(pUsnRecord);

                                    // Only read until the current usn points beyond the current state's USN.
                                    if (usnEntry.USN >= newUsnState.NextUsn)
                                    {
                                        bReadMore = false;
                                        break;
                                    }

                                    switch (onlyFiles)
                                    {
                                    case true when usnEntry.IsFolder:
                                    case false when !usnEntry.IsFolder:
                                    {
                                        pUsnRecord        = new IntPtr(pUsnRecord.ToInt64() + usnEntry.RecordLength);
                                        outBytesReturned -= usnEntry.RecordLength;
                                        continue;
                                    }
                                    }

                                    if (string.IsNullOrWhiteSpace(filter))
                                    {
                                        yield return(usnEntry);
                                    }
                                    else
                                    {
                                        var options = new GlobOptions {
                                            Evaluation = { CaseInsensitive = true }
                                        };
                                        var glob = Glob.Parse(filter, options);
                                        if (glob.IsMatch(usnEntry.Name.AsSpan()))
                                        {
                                            yield return(usnEntry);
                                        }
                                    }

                                    pUsnRecord        = new IntPtr(pUsnRecord.ToInt64() + usnEntry.RecordLength);
                                    outBytesReturned -= usnEntry.RecordLength;
                                }
                            }

                            else
                            {
                                var lastWin32Error = Marshal.GetLastWin32Error();
                                if (lastWin32Error == (int)Win32Errors.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;
                }
            }
        }
Пример #6
0
        /// <summary>Returns an enumerable collection of <see cref="UsnEntry"/> entries that meet specified criteria.</summary>
        /// <param name="filter">The filter.</param>
        /// <param name="onlyFiles">If gets only the file entries.</param>
        public IEnumerable <UsnEntry> EnumerateUsnEntries(string filter, bool?onlyFiles)
        {
            var usnState = new 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.");
            }

            // Set up MFT_ENUM_DATA_V0 structure.
            var mftData = new 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);


            // Gather up volume's directories.
            while (Win32Api.DeviceIoControl(
                       _usnJournalRootHandle,
                       Win32Api.FSCTL_ENUM_USN_DATA,
                       mftDataBuffer,
                       mftDataSize,
                       pData,
                       pDataSize,
                       out var 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 UsnEntry(pUsnRecord);

                    switch (onlyFiles)
                    {
                    case true when usnEntry.IsFolder:
                    case false when !usnEntry.IsFolder:
                    {
                        pUsnRecord        = new IntPtr(pUsnRecord.ToInt64() + usnEntry.RecordLength);
                        outBytesReturned -= usnEntry.RecordLength;
                        continue;
                    }
                    }

                    if (string.IsNullOrWhiteSpace(filter))
                    {
                        yield return(usnEntry);
                    }
                    else
                    {
                        var options = new GlobOptions {
                            Evaluation = { CaseInsensitive = true }
                        };
                        var glob = Glob.Parse(filter, options);
                        if (glob.IsMatch(usnEntry.Name.AsSpan()))
                        {
                            yield return(usnEntry);
                        }
                    }

                    pUsnRecord        = new IntPtr(pUsnRecord.ToInt64() + usnEntry.RecordLength);
                    outBytesReturned -= usnEntry.RecordLength;
                }

                Marshal.WriteInt64(mftDataBuffer, Marshal.ReadInt64(pData, 0));
            }

            Marshal.FreeHGlobal(pData);
        }