private PInvokeWin32.READ_USN_JOURNAL_DATA SetupInputData4JournalRead(string volume, uint reason)
        {
            IntPtr pMonitorVolume = MFTSearcher.GetVolumeJournalHandle(volume);
            uint   bytesReturned  = 0;

            PInvokeWin32.USN_JOURNAL_DATA ujd = new PInvokeWin32.USN_JOURNAL_DATA();
            MFTSearcher.QueryUSNJournal(pMonitorVolume, out ujd, out bytesReturned);

            // 构建输入参数
            PInvokeWin32.READ_USN_JOURNAL_DATA rujd = new PInvokeWin32.READ_USN_JOURNAL_DATA();
            rujd.StartUsn          = ujd.NextUsn;
            rujd.ReasonMask        = reason;
            rujd.ReturnOnlyOnClose = 1;
            rujd.Timeout           = 0;
            rujd.BytesToWaitFor    = 1;
            rujd.UsnJournalID      = ujd.UsnJournalID;

            return(rujd);
        }
        private void MonitorThread(string volume, MFTSearcherCache db)
        {
            IntPtr pbuffer = Marshal.AllocHGlobal(0x1000);

            PInvokeWin32.READ_USN_JOURNAL_DATA rujd = SetupInputData4JournalRead(volume, 0xFFFFFFFF);
            UInt32 cbRead;
            IntPtr prujd;

            while (true)
            {
                prujd = Marshal.AllocHGlobal(Marshal.SizeOf(rujd));
                PInvokeWin32.ZeroMemory(prujd, Marshal.SizeOf(rujd));
                Marshal.StructureToPtr(rujd, prujd, true);

                IntPtr pVolume = MFTSearcher.GetVolumeJournalHandle(volume);

                bool fok = PInvokeWin32.DeviceIoControl(pVolume,
                                                        PInvokeWin32.FSCTL_READ_USN_JOURNAL,
                                                        prujd, Marshal.SizeOf(typeof(PInvokeWin32.READ_USN_JOURNAL_DATA)),
                                                        pbuffer, 0x1000, out cbRead, IntPtr.Zero);

                IntPtr pRealData = new IntPtr(pbuffer.ToInt32() + Marshal.SizeOf(typeof(Int64)));
                uint   offset    = 0;

                if (fok)
                {
                    while (offset + Marshal.SizeOf(typeof(Int64)) < cbRead)
                    {
                        PInvokeWin32.USN_RECORD usn = new PInvokeWin32.USN_RECORD(new IntPtr(pRealData.ToInt32() + (int)offset));
                        ProcessUSN(usn, volume, db);
                        offset += usn.RecordLength;
                    }
                }

                Marshal.FreeHGlobal(prujd);
                rujd.StartUsn = Marshal.ReadInt64(pbuffer);
            }
        }