示例#1
0
        public UsnJournalReturnCode MonitorUsnJournalEntries(UInt32 reasonMask)
        {
            var state = new Win32.USN_JOURNAL_DATA();

            if (!IsNtfsVolume)
            {
                return UsnJournalReturnCode.VOLUME_NOT_NTFS;
            }

            if (_usnJournalRootHandle.ToInt32() == Win32.INVALID_HANDLE_VALUE)
            {
                return UsnJournalReturnCode.INVALID_HANDLE_VALUE;
            }

            var returnCode = QueryUsnJournal(ref state);

            if (returnCode != UsnJournalReturnCode.USN_JOURNAL_SUCCESS)
            {
                return returnCode;
            }

            const int pbDataSize = sizeof (UInt64)*0x4000;

            IntPtr pbData = Marshal.AllocHGlobal(pbDataSize);

            Win32.ZeroMemory(pbData, pbDataSize);

            var rujd = new Win32.READ_USN_JOURNAL_DATA
            {
                StartUsn = state.NextUsn,
                ReasonMask = reasonMask,
                ReturnOnlyOnClose = 0,
                Timeout = 1,
                bytesToWaitFor = 1,
                UsnJournalId = state.UsnJournalID
            };

            int sizeRujd = Marshal.SizeOf(rujd);

            IntPtr rujdBuffer = Marshal.AllocHGlobal(sizeRujd);

            Win32.ZeroMemory(rujdBuffer, sizeRujd);

            Marshal.StructureToPtr(rujd, rujdBuffer, true);

            _readMore = true;

            // Read USN journal entries
            while (_readMore)
            {
                uint bytesReturned;

                bool returnValue = Win32.DeviceIoControl(
                    _usnJournalRootHandle,
                    Win32.FSCTL_READ_USN_JOURNAL,
                    rujdBuffer,
                    sizeRujd,
                    pbData,
                    pbDataSize,
                    out bytesReturned,
                    IntPtr.Zero);

                if (!returnValue)
                {
                    var lastWin32Error = (Win32.GetLastErrorEnum) Marshal.GetLastWin32Error();

                    Marshal.FreeHGlobal(rujdBuffer);
                    Marshal.FreeHGlobal(pbData);

                    return lastWin32Error == Win32.GetLastErrorEnum.ERROR_HANDLE_EOF
                               ? UsnJournalReturnCode.USN_JOURNAL_SUCCESS
                               : ConvertWin32ErrorToUsnError(lastWin32Error);
                }

                var usnEntryPointer = new IntPtr(pbData.ToInt32() + sizeof (UInt64));

                // While there are at least one entry in the usn journal
                // XXX: Why magic number 60?
                while (bytesReturned > 60)
                {
                    var usnEntry = new Win32.UsnEntry(usnEntryPointer);

                    OnNewUsnRecord(new NewUsnRecordEventArgs(usnEntry));

                    usnEntryPointer = new IntPtr(usnEntryPointer.ToInt32() + usnEntry.RecordLength);

                    bytesReturned -= usnEntry.RecordLength;
                }

                var nextUsn = Marshal.ReadInt64(pbData, 0);

                Marshal.WriteInt64(rujdBuffer, nextUsn);
            }

            Marshal.FreeHGlobal(rujdBuffer);
            Marshal.FreeHGlobal(pbData);

            return returnCode;
        }
示例#2
0
        /// <summary>
        /// Rests 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(Win32.USN_JOURNAL_DATA usnJournalPreviousState)
        {
            bool bRtnCode = false;

            if (IsNtfsVolume)
            {
                if (_usnJournalRootHandle.ToInt32() != Win32.INVALID_HANDLE_VALUE)
                {
                    var usnJournalState = new Win32.USN_JOURNAL_DATA();
                    var usnError = QueryUsnJournal(ref usnJournalState);

                    if (usnError == UsnJournalReturnCode.USN_JOURNAL_SUCCESS)
                    {
                        if (usnJournalPreviousState.UsnJournalID == usnJournalState.UsnJournalID)
                        {
                            if (usnJournalPreviousState.NextUsn >= usnJournalState.NextUsn)
                            {
                                bRtnCode = true;
                            }
                        }
                    }
                }
            }
            return bRtnCode;
        }
示例#3
0
        /// <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()
        {
            bool bRtnCode = false;

            if (IsNtfsVolume)
            {
                if (_usnJournalRootHandle.ToInt32() != Win32.INVALID_HANDLE_VALUE)
                {
                    var usnJournalCurrentState = new Win32.USN_JOURNAL_DATA();
                    var usnError = QueryUsnJournal(ref usnJournalCurrentState);

                    if (usnError == UsnJournalReturnCode.USN_JOURNAL_SUCCESS)
                    {
                        bRtnCode = true;
                    }
                }
            }
            return bRtnCode;
        }
示例#4
0
        /// <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, Win32.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 UsnJournalReturnCode GetUsnJournalEntries(Win32.USN_JOURNAL_DATA previousUsnState,
            UInt32 reasonMask,
            out List<Win32.UsnEntry> usnEntries,
            out Win32.USN_JOURNAL_DATA newUsnState)
        {
            usnEntries = new List<Win32.UsnEntry>();
            newUsnState = new Win32.USN_JOURNAL_DATA();

            UsnJournalReturnCode returnCode = UsnJournalReturnCode.VOLUME_NOT_NTFS;

            if (IsNtfsVolume)
            {
                if (_usnJournalRootHandle.ToInt32() != Win32.INVALID_HANDLE_VALUE)
                {
                    // get current usn journal state
                    returnCode = QueryUsnJournal(ref newUsnState);
                    if (returnCode == UsnJournalReturnCode.USN_JOURNAL_SUCCESS)
                    {
                        bool bReadMore = true;
                        // sequentially process the usn journal looking for image file entries
                        int pbDataSize = sizeof(UInt64) * 0x4000;
                        IntPtr pbData = Marshal.AllocHGlobal(pbDataSize);
                        Win32.ZeroMemory(pbData, pbDataSize);

                        Win32.READ_USN_JOURNAL_DATA rujd = new Win32.READ_USN_JOURNAL_DATA();
                        rujd.StartUsn = previousUsnState.NextUsn;
                        rujd.ReasonMask = reasonMask;
                        rujd.ReturnOnlyOnClose = 0;
                        rujd.Timeout = 0;
                        rujd.bytesToWaitFor = 0;
                        rujd.UsnJournalId = previousUsnState.UsnJournalID;
                        int sizeRujd = Marshal.SizeOf(rujd);

                        IntPtr rujdBuffer = Marshal.AllocHGlobal(sizeRujd);
                        Win32.ZeroMemory(rujdBuffer, sizeRujd);
                        Marshal.StructureToPtr(rujd, rujdBuffer, true);

                        //
                        // read usn journal entries
                        //
                        while (bReadMore)
                        {
                            uint outBytesReturned;

                            bool bRtn = Win32.DeviceIoControl(
                                _usnJournalRootHandle,
                                Win32.FSCTL_READ_USN_JOURNAL,
                                rujdBuffer,
                                sizeRujd,
                                pbData,
                                pbDataSize,
                                out outBytesReturned,
                                IntPtr.Zero);

                            if (bRtn)
                            {
                                var pUsnRecord = new IntPtr(pbData.ToInt32() + sizeof(UInt64));

                                while (outBytesReturned > 60)   // while there are at least one entry in the usn journal
                                {
                                    var usnEntry = new Win32.UsnEntry(pUsnRecord);

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

                                        break;
                                    }

                                    usnEntries.Add(usnEntry);

                                    pUsnRecord = new IntPtr(pUsnRecord.ToInt32() + usnEntry.RecordLength);

                                    outBytesReturned -= usnEntry.RecordLength;
                                }
                            }
                            else
                            {
                                var lastWin32Error = (Win32.GetLastErrorEnum)Marshal.GetLastWin32Error();

                                if (lastWin32Error == Win32.GetLastErrorEnum.ERROR_HANDLE_EOF)
                                {
                                    returnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;
                                }
                                else
                                {
                                    returnCode = ConvertWin32ErrorToUsnError(lastWin32Error);
                                }

                                break;
                            }

                            Int64 nextUsn = Marshal.ReadInt64(pbData, 0);

                            if (nextUsn >= newUsnState.NextUsn)
                            {
                                break;
                            }

                            Marshal.WriteInt64(rujdBuffer, nextUsn);
                        }

                        Marshal.FreeHGlobal(rujdBuffer);
                        Marshal.FreeHGlobal(pbData);
                    }
                }
                else
                {
                    returnCode = UsnJournalReturnCode.INVALID_HANDLE_VALUE;
                }
            }

            return returnCode;
        }
示例#5
0
        /// <summary>
        /// GetNtfsVolumeFolders() reads the Master File Table to find all of the folders on a volume 
        /// and returns them in a SortedList<UInt64, Win32.UsnEntry> folders out parameter.
        /// </summary>
        /// <param name="folders">A SortedList<string, UInt64> list where string is
        /// the filename and UInt64 is the parent folder's file reference number
        /// </param>
        /// <returns>
        /// USN_JOURNAL_SUCCESS                 GetNtfsVolumeFolders() 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 UsnJournalReturnCode GetNtfsVolumeFolders(out List<Win32.UsnEntry> folders)
        {
            folders = new List<Win32.UsnEntry>();

            var returnCode = UsnJournalReturnCode.VOLUME_NOT_NTFS;

            if (IsNtfsVolume)
            {
                if (_usnJournalRootHandle.ToInt32() != Win32.INVALID_HANDLE_VALUE)
                {
                    /*
                        returnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;
                    */

                    var usnState = new Win32.USN_JOURNAL_DATA();

                    returnCode = QueryUsnJournal(ref usnState);

                    if (returnCode == UsnJournalReturnCode.USN_JOURNAL_SUCCESS)
                    {
                        //
                        // set up MFT_ENUM_DATA structure
                        //
                        Win32.MFT_ENUM_DATA med;
                        med.StartFileReferenceNumber = 0;
                        med.LowUsn = 0;
                        med.HighUsn = usnState.NextUsn;
                        Int32 sizeMftEnumData = Marshal.SizeOf(med);
                        IntPtr medBuffer = Marshal.AllocHGlobal(sizeMftEnumData);
                        Win32.ZeroMemory(medBuffer, sizeMftEnumData);
                        Marshal.StructureToPtr(med, medBuffer, true);

                        //
                        // set up the data buffer which receives the USN_RECORD data
                        //
                        const int pDataSize = sizeof(UInt64) + 10000;
                        IntPtr pData = Marshal.AllocHGlobal(pDataSize);
                        Win32.ZeroMemory(pData, pDataSize);
                        uint outBytesReturned;

                        //
                        // Gather up volume's directories
                        //
                        while (Win32.DeviceIoControl(
                            _usnJournalRootHandle,
                            Win32.FSCTL_ENUM_USN_DATA,
                            medBuffer,
                            sizeMftEnumData,
                            pData,
                            pDataSize,
                            out outBytesReturned,
                            IntPtr.Zero))
                        {
                            var pUsnRecord = new IntPtr(pData.ToInt32() + sizeof(Int64));
                            while (outBytesReturned > 60)
                            {
                                var usnEntry = new Win32.UsnEntry(pUsnRecord);

                                // check for directory entries
                                if (usnEntry.IsFolder)
                                {
                                    folders.Add(usnEntry);
                                }

                                pUsnRecord = new IntPtr(pUsnRecord.ToInt32() + usnEntry.RecordLength);

                                outBytesReturned -= usnEntry.RecordLength;
                            }

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

                        Marshal.FreeHGlobal(pData);

                        returnCode = ConvertWin32ErrorToUsnError((Win32.GetLastErrorEnum)Marshal.GetLastWin32Error());

                        if (returnCode == UsnJournalReturnCode.ERROR_HANDLE_EOF)
                        {
                            returnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;
                        }
                    }
                }
                else
                {
                    returnCode = UsnJournalReturnCode.INVALID_HANDLE_VALUE;
                }
            }

            folders.Sort();

            return returnCode;
        }
示例#6
0
        public UsnJournalReturnCode GetFilesMatchingFilter(string filter, out List<Win32.UsnEntry> files)
        {
            filter = filter.ToLower();
            files = new List<Win32.UsnEntry>();

            string[] fileTypes = filter.Split(' ', ',', ';');

            if (!IsNtfsVolume)
            {
                return UsnJournalReturnCode.VOLUME_NOT_NTFS;
            }

            if (_usnJournalRootHandle.ToInt32() == Win32.INVALID_HANDLE_VALUE)
            {
                return UsnJournalReturnCode.INVALID_HANDLE_VALUE;
            }

            var usnState = new Win32.USN_JOURNAL_DATA();

            var returnCode = QueryUsnJournal(ref usnState);

            if (returnCode != UsnJournalReturnCode.USN_JOURNAL_SUCCESS)
            {
                return returnCode;
            }

            // set up MFT_ENUM_DATA structure
            Win32.MFT_ENUM_DATA med;

            med.StartFileReferenceNumber = 0;
            med.LowUsn = 0;
            med.HighUsn = usnState.NextUsn;

            Int32 sizeMftEnumData = Marshal.SizeOf(med);
            IntPtr medBuffer = Marshal.AllocHGlobal(sizeMftEnumData);

            Win32.ZeroMemory(medBuffer, sizeMftEnumData);

            Marshal.StructureToPtr(med, medBuffer, true);

            // set up the data buffer which receives the USN_RECORD data
            const int pDataSize = sizeof (UInt64) + 10000;

            IntPtr pData = Marshal.AllocHGlobal(pDataSize);

            Win32.ZeroMemory(pData, pDataSize);

            uint bytesReturned;

            // Gather up volume's directories
            while (Win32.DeviceIoControl(
                _usnJournalRootHandle,
                Win32.FSCTL_ENUM_USN_DATA,
                medBuffer,
                sizeMftEnumData,
                pData,
                pDataSize,
                out bytesReturned,
                IntPtr.Zero))
            {
                var usnEntryPointer = new IntPtr(pData.ToInt32() + sizeof (Int64));

                while (bytesReturned > 60)
                {
                    var usnEntry = new Win32.UsnEntry(usnEntryPointer);

                    // check for directory entries
                    if (usnEntry.IsFile)
                    {
                        string extension = Path.GetExtension(usnEntry.Name).ToLower();

                        if (0 == string.Compare(filter, "*"))
                        {
                            files.Add(usnEntry);
                        }
                        else if (!string.IsNullOrEmpty(extension))
                        {
                            files.AddRange(from fileType in fileTypes
                                           where extension.Contains(fileType)
                                           select usnEntry);
                        }
                    }

                    usnEntryPointer = new IntPtr(usnEntryPointer.ToInt32() + usnEntry.RecordLength);

                    bytesReturned -= usnEntry.RecordLength;
                }

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

            Marshal.FreeHGlobal(pData);

            returnCode = ConvertWin32ErrorToUsnError((Win32.GetLastErrorEnum) Marshal.GetLastWin32Error());

            if (returnCode == UsnJournalReturnCode.ERROR_HANDLE_EOF)
            {
                returnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;
            }

            files.Sort();

            return returnCode;
        }