Esempio n. 1
0
 public static extern bool DeviceIoControl(
     SafeFileHandle hDevice,
     FsCtl IoControlCode,
     [In] READ_USN_JOURNAL_DATA_V0 InBuffer,
     uint nInBufferSize,
     [In] IntPtr OutBuffer,
     uint nOutBufferSize,
     ref uint pBytesReturned,
     [In] IntPtr overlapped //[In] ref System.Threading.NativeOverlapped Overlapped
     );
Esempio n. 2
0
            private bool Read()
            {
                const int CurrentUSNLength = sizeof(long);

                var readData = new READ_USN_JOURNAL_DATA_V0
                {
                    StartUsn          = _currentUSN,
                    ReasonMask        = Options.ReasonFilter,
                    UsnJournalID      = ChangeJournal.Data.ID,
                    ReturnOnlyOnClose = Options.ReturnOnlyOnClose ? (uint)1 : 0,
                    Timeout           = (ulong)Options.Timeout.TotalSeconds,
                };

                var handle    = ChangeJournal.ChangeJournalHandle;
                var entryData = Win32DeviceControl.ControlWithInput(handle, Win32ControlCode.ReadUsnJournal, ref readData, BufferSize);

                if (entryData.Length > CurrentUSNLength) // There are more data than just data currentUSN.
                {
                    var bufferHandle  = GCHandle.Alloc(entryData, GCHandleType.Pinned);
                    var bufferPointer = bufferHandle.AddrOfPinnedObject();

                    _currentUSN = Marshal.ReadInt64(entryData, 0);

                    // Enumerate entries
                    _entries.Clear();
                    var offset = CurrentUSNLength; // Skip currentUSN field
                    while (offset < entryData.Length)
                    {
                        var entry = GetBufferedEntry(bufferPointer, offset);
                        offset += entry.Length;
                        _entries.Add(entry);
                    }

                    bufferHandle.Free();
                    _currentIndex = 0;
                    return(true);
                }
                else
                {
                    _eof = true;
                    return(false);
                }
            }
        /// <summary><see cref="https://msdn.microsoft.com/en-us/library/windows/desktop/aa364586(v=vs.85).aspx"/></summary>
        public IUSN_RECORD[] FileSystemReadUsnJournal(long volumeJournalId, UsnJournalReasonMask reasonMask, USN firstUsn, int bytesToWaitFor = 0, int timeout = 0)
        {
            READ_USN_JOURNAL_DATA_V0 input = new READ_USN_JOURNAL_DATA_V0();

            input.StartUsn       = firstUsn;
            input.UsnJournalId   = volumeJournalId;
            input.ReasonMask     = reasonMask;
            input.BytesToWaitFor = bytesToWaitFor;
            input.Timeout        = timeout;

            int errorCode;

            byte[] data = DeviceIoControlHelper.InvokeIoControl(Handle, IOControlCode.FsctlReadUsnJournal, 1024 * 1024, input, out errorCode);

            List <IUSN_RECORD> res = new List <IUSN_RECORD>();

            using (UnmanagedMemory mem = new UnmanagedMemory(data))
            {
                int dataOffset = 8;

                while (dataOffset < data.Length)
                {
                    int         length;
                    IUSN_RECORD rec = ParseUsnRecord(mem, dataOffset, out length);

                    if (length <= 0)
                    {
                        break;
                    }

                    res.Add(rec);

                    // Move to next record
                    dataOffset += length;
                }
            }

            return(res.ToArray());
        }
Esempio n. 4
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;
                }
            }
        }