private PInvokeWin32.READ_USN_JOURNAL_DATA SetupInputData4JournalRead(string volume, uint reason) { IntPtr pMonitorVolume = MyEverything.GetVolumeJournalHandle(volume); uint bytesReturned = 0; PInvokeWin32.USN_JOURNAL_DATA ujd = new PInvokeWin32.USN_JOURNAL_DATA(); MyEverything.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(object param) { MyEverythingDB db = (param as Dictionary <string, object>)["MyEverythingDB"] as MyEverythingDB; string volume = (param as Dictionary <string, object>)["Volume"] as string; IntPtr pbuffer = Marshal.AllocHGlobal(0x1000); // 构建输出参数 PInvokeWin32.READ_USN_JOURNAL_DATA rujd = SetupInputData4JournalRead(volume, 0xFFFFFFFF); // 对所有类型的reason都监听 UInt32 cbRead; // 用来存储实际输出的字节数 IntPtr prujd; // 指向输入参数结构体的指针 while (true) { // 构建输入参数的指针 prujd = Marshal.AllocHGlobal(Marshal.SizeOf(rujd)); PInvokeWin32.ZeroMemory(prujd, Marshal.SizeOf(rujd)); Marshal.StructureToPtr(rujd, prujd, true); Debug.WriteLine(string.Format("\nMoniting on {0}......", volume)); IntPtr pVolume = MyEverything.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))); // 返回的内存块头上的8个字节是一个usn_id, 从第9个字节开始才是record. uint offset = 0; if (fok) { while (offset + Marshal.SizeOf(typeof(Int64)) < cbRead) // record可能有多个! { 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); // 返回的内存块头上的8个字节就是用来在进行下一次查询的 } }