public IEnumerable<PInvokeWin32.USN_RECORD> ReadUSN(ulong USNJournalID, Int64 lowUsn, uint ReasonMask, ulong TimeOut, ulong ByteToWait) { int buffersize = sizeof(UInt64) + 65535; // Set READ_USN_JOURNAL_DATA PInvokeWin32.READ_USN_JOURNAL_DATA Rujd; /// Document: /// http://www.microsoft.com/msj/0999/journal/journal.aspx /// http://www.microsoft.com/msj/1099/journal2/journal2.aspx /// /// Timeout: /// Timeout is a value for use with the BytesToWaitFor member. /// It does not guarantee that DeviceIoControl will return after /// the specified timeout, but rather it specifies how often the /// system should check whether requested data is available. /// This member is not like other conventional Win32¨ timeout /// parameters that use milliseconds. Instead, this member uses /// the same resolution as the Win32 FILETIME structure /// (100-nanosecond intervals—one second has ten million intervals). /// A value of zero specifies no timeout (or infinite). /// A fixed timeout is specified using negative values /// (even though this is an unsigned variable). /// For example, a timeout of 25 seconds can be expressed as /// (DWORDLONG)(-2500000000). /// The Timeout member is ignored if DeviceIoControl is /// called with an asynchronous request. /// BytesToWaitFor: /// Don't confuse the BytesToWaitFor member with the output buffer /// size or the count of bytes returned by DeviceIoControl. /// If this member is set to zero, the function will return immediately, /// even if it found no matching records in the journal. If this member /// is nonzero, the system will not return until it has found at least /// one record to return. BytesToWaitFor specifies how often the system /// will recheck the journal to see whether any matching records have been /// created. For example, if you specify 16384, the system will only examine /// the journal for new records after a new 16KB block of raw data has been /// added. This prevents a process from using too many resources when many /// records are being added. If the Timeout and BytesToWaitFor members are /// both nonzero, the system also checks records if the timeout period expires /// before the journal has grown by the specified number of bytes. /// If BytesToWaitFor is nonzero, but records are found that match the user's /// request, the DeviceIoControl function will return immediately; that is, the /// BytesToWaitFor and TimeOut members only have an effect when there are not any /// existing records that fulfill the ReasonMask/ReturnOnlyOnClose requirements. Rujd.StartUSN = lowUsn; Rujd.ReasonMask = ReasonMask; Rujd.UsnJournalID = USNJournalID; Rujd.BytesToWaitFor = ByteToWait; /// Set to 0 for no waiting, otherwise it will notice new record Rujd.Timeout = TimeOut; /// When BytesToWaitfor is 0, the timeout is ignore Rujd.ReturnOnlyOnClose = 0; IntPtr UsnBuffer = IntPtr.Zero; IntPtr pData = IntPtr.Zero; try { // Set User Buffer UsnBuffer = Marshal.AllocHGlobal(PInvokeWin32.SizeOf_READ_USN_JOURNAL_DATA); PInvokeWin32.ZeroMemory(UsnBuffer, PInvokeWin32.SizeOf_READ_USN_JOURNAL_DATA); Marshal.StructureToPtr(Rujd, UsnBuffer, true); // Set Output Buffer pData = Marshal.AllocHGlobal(buffersize); PInvokeWin32.ZeroMemory(pData, buffersize); uint outBytesReturned = 0; Int64 startUsn = lowUsn; while (true) { Rujd.StartUSN = startUsn; Rujd.ReasonMask = ReasonMask; Rujd.UsnJournalID = USNJournalID; Marshal.StructureToPtr(Rujd, UsnBuffer, true); var retOK = PInvokeWin32.DeviceIoControl(ChangeJournalRootHandle, PInvokeWin32.FSCTL_READ_USN_JOURNAL, UsnBuffer, PInvokeWin32.SizeOf_READ_USN_JOURNAL_DATA, pData, buffersize, out outBytesReturned, IntPtr.Zero); if (retOK == false) { throw new Win32Exception(Marshal.GetLastWin32Error()); } /// the first returned USN record /// The first Int64 are next usn number!! /// If there are no more record, it is the next usn startUsn = Marshal.ReadInt64(pData); CurUsn = startUsn; IntPtr pUsnRecord = new IntPtr(pData.ToInt32() + sizeof(Int64)); PInvokeWin32.USN_RECORD p = null; while (outBytesReturned > 60) { p = new PInvokeWin32.USN_RECORD(pUsnRecord); pUsnRecord = new IntPtr(pUsnRecord.ToInt32() + p.RecordLength); outBytesReturned -= p.RecordLength; yield return p; } if (p == null || startUsn == p.Usn) break; } } finally { if (pData != IntPtr.Zero) Marshal.FreeHGlobal(pData); if (UsnBuffer != IntPtr.Zero) Marshal.FreeHGlobal(UsnBuffer); } yield break; }
public IEnumerable<PInvokeWin32.USN_RECORD> EnumVolume(Int64 lowUsn, Int64 highUsn) { PInvokeWin32.MFT_ENUM_DATA med; med.StartFileReferenceNumber = 0; med.LowUsn = lowUsn; med.HighUsn = highUsn; IntPtr medBuffer = IntPtr.Zero; IntPtr pData = IntPtr.Zero; try { medBuffer = Marshal.AllocHGlobal(PInvokeWin32.SizeOf_MFT_ENUM_DATA); PInvokeWin32.ZeroMemory(medBuffer, PInvokeWin32.SizeOf_MFT_ENUM_DATA); Marshal.StructureToPtr(med, medBuffer, true); int buffersize = sizeof(UInt64) + 0x10000; pData = Marshal.AllocHGlobal(buffersize); PInvokeWin32.ZeroMemory(pData, buffersize); uint outBytesReturned = 0; while (true) { bool stOK = PInvokeWin32.DeviceIoControl( ChangeJournalRootHandle, // VolumHandler PInvokeWin32.FSCTL_ENUM_USN_DATA, // Command medBuffer, // Command Block, inputer buffer PInvokeWin32.SizeOf_MFT_ENUM_DATA, // Command Block Size pData, // Output buffer buffersize, // size of output buffer out outBytesReturned, // Return Value (Error Message) IntPtr.Zero); if (stOK == false) break; IntPtr pUsnRecord = new IntPtr(pData.ToInt32() + sizeof(Int64)); while (outBytesReturned > PInvokeWin32.SizeOf_USN_RECORD) { PInvokeWin32.USN_RECORD usn = new PInvokeWin32.USN_RECORD(pUsnRecord); yield return usn; pUsnRecord = new IntPtr(pUsnRecord.ToInt32() + usn.RecordLength); outBytesReturned -= usn.RecordLength; } /// Write the new StartFileReferenceNumber Marshal.WriteInt64(medBuffer, Marshal.ReadInt64(pData, 0)); } } finally { if (medBuffer != IntPtr.Zero) Marshal.FreeHGlobal(medBuffer); if (pData != IntPtr.Zero) Marshal.FreeHGlobal(pData); } yield break; }
public unsafe void EnumFiles() { /// MFT ENUM DATA PInvokeWin32.MFT_ENUM_DATA MedData = new PInvokeWin32.MFT_ENUM_DATA(); MedData.StartFileReferenceNumber = 0; MedData.LowUsn = mUSN.FirstUsn; MedData.HighUsn = mUSN.NextUsn; IntPtr MedBuffer = Marshal.AllocHGlobal(sizeof(PInvokeWin32.MFT_ENUM_DATA)); Marshal.StructureToPtr(MedData, MedBuffer, true); // Open Buffer int OutBufferSize = sizeof(UInt64) + 0x10000; IntPtr OutBuffer = Marshal.AllocHGlobal(OutBufferSize); uint BytesReturned = 0; while (PInvokeWin32.DeviceIoControl(mDriveHandle, PInvokeWin32.FSCTL_ENUM_USN_DATA, MedBuffer, sizeof(PInvokeWin32.MFT_ENUM_DATA), OutBuffer, OutBufferSize, out BytesReturned, IntPtr.Zero)) { IntPtr pUsnRecord = new IntPtr(OutBuffer.ToInt32() + sizeof(Int64)); while (BytesReturned > 60) { PInvokeWin32.USN_RECORD usn = new PInvokeWin32.USN_RECORD(pUsnRecord); if (0 != (usn.FileAttributes & PInvokeWin32.FILE_ATTRIBUTE_DIRECTORY)) { /// /// Handle Directories /// mDictionarys[usn.FileReferenceNumber] = usn; } else { /// /// Handle Files /// mFiles[usn.FileReferenceNumber] = usn; } pUsnRecord = new IntPtr(pUsnRecord.ToInt32() + usn.RecordLength); BytesReturned -= usn.RecordLength; } Marshal.WriteInt64(MedBuffer, Marshal.ReadInt64(OutBuffer, 0)); } Marshal.FreeHGlobal(MedBuffer); Marshal.FreeHGlobal(OutBuffer); }
public unsafe PInvokeWin32.USN_RECORD ReadFileUSN(String Path) { String DevicePath = @"\\.\" + Path; IntPtr handle = PInvokeWin32.CreateFile(DevicePath, PInvokeWin32.GENERIC_READ, PInvokeWin32.FILE_SHARE_READ, IntPtr.Zero, PInvokeWin32.OPEN_EXISTING, 0, IntPtr.Zero); if (mDriveHandle.ToInt32() == PInvokeWin32.INVALID_HANDLE_VALUE) { throw new IOException(); } int BufferSize = 200; IntPtr UsnBuffer = Marshal.AllocHGlobal(BufferSize); uint outBytesReturned = 0; bool retOK = PInvokeWin32.DeviceIoControl(handle, PInvokeWin32.FSCTL_READ_FILE_USN_DATA, IntPtr.Zero, 0, UsnBuffer, BufferSize, out outBytesReturned, IntPtr.Zero); if (!retOK) { throw new Exception(); } PInvokeWin32.USN_RECORD p = new PInvokeWin32.USN_RECORD(UsnBuffer); Marshal.FreeHGlobal(UsnBuffer); return p; }
public unsafe List<PInvokeWin32.USN_RECORD> ReadUSN(UInt64 startUsn) { int buffersize = sizeof(UInt64) + 65535; // Set READ_USN_JOURNAL_DATA PInvokeWin32.READ_USN_JOURNAL_DATA Rujd = new PInvokeWin32.READ_USN_JOURNAL_DATA(); Rujd.StartUSN = startUsn; Rujd.ReasonMask = uint.MaxValue; Rujd.UsnJournalID = mUSN.UsnJournalID; Rujd.BytesToWaitFor = (ulong)buffersize; int SizeOfUsnJournalData = Marshal.SizeOf(Rujd); IntPtr UsnBuffer = Marshal.AllocHGlobal(SizeOfUsnJournalData); PInvokeWin32.ZeroMemory(UsnBuffer, SizeOfUsnJournalData); Marshal.StructureToPtr(Rujd, UsnBuffer, true); // Set Output Buffer IntPtr pData = Marshal.AllocHGlobal(buffersize); PInvokeWin32.ZeroMemory(pData, buffersize); uint outBytesReturned = 0; List<PInvokeWin32.USN_RECORD> USNRecords = new List<PInvokeWin32.USN_RECORD>(); while (true) { Rujd.StartUSN = startUsn; Rujd.ReasonMask = uint.MaxValue; Rujd.UsnJournalID = mUSN.UsnJournalID; Rujd.BytesToWaitFor = (ulong)buffersize; Marshal.StructureToPtr(Rujd, UsnBuffer, true); bool retOK = PInvokeWin32.DeviceIoControl(mDriveHandle, PInvokeWin32.FSCTL_READ_USN_JOURNAL, UsnBuffer, sizeof(PInvokeWin32.READ_USN_JOURNAL_DATA), pData, buffersize, out outBytesReturned, IntPtr.Zero); if (!retOK) { throw new IOException(); } /// the first returned USN record IntPtr pUsnRecord = new IntPtr(pData.ToInt32() + sizeof(Int64)); // skip first gap while (outBytesReturned > 60) { PInvokeWin32.USN_RECORD p = new PInvokeWin32.USN_RECORD(pUsnRecord); pUsnRecord = new IntPtr(pUsnRecord.ToInt32() + p.RecordLength); outBytesReturned -= p.RecordLength; USNRecords.Add(p); } if (startUsn == USNRecords[USNRecords.Count - 1].Usn) break; startUsn = USNRecords[USNRecords.Count - 1].Usn; } return USNRecords; }
unsafe private void EnumerateFiles(IntPtr medBuffer, ref Dictionary<ulong, FileNameAndFrn> files, string[] fileExtensions) { IntPtr pData = Marshal.AllocHGlobal(sizeof(UInt64) + 0x10000); PInvokeWin32.ZeroMemory(pData, sizeof(UInt64) + 0x10000); uint outBytesReturned = 0; while (false != PInvokeWin32.DeviceIoControl(_changeJournalRootHandle, PInvokeWin32.FSCTL_ENUM_USN_DATA, medBuffer, sizeof(PInvokeWin32.MFT_ENUM_DATA), pData, sizeof(UInt64) + 0x10000, out outBytesReturned, IntPtr.Zero)) { IntPtr pUsnRecord = new IntPtr(pData.ToInt32() + sizeof(Int64)); while (outBytesReturned > 60) { PInvokeWin32.USN_RECORD usn = new PInvokeWin32.USN_RECORD(pUsnRecord); if (0 != (usn.FileAttributes & PInvokeWin32.FILE_ATTRIBUTE_DIRECTORY)) { // // handle directories // if (!_directories.ContainsKey(usn.FileReferenceNumber)) { _directories.Add(usn.FileReferenceNumber, new FileNameAndFrn(usn.FileName, usn.ParentFileReferenceNumber)); } else { // this is debug code and should be removed when we are certain that // duplicate frn's don't exist on a given drive. To date, this exception has // never been thrown. Removing this code improves performance.... throw new Exception(string.Format("Duplicate FRN: {0} for {1}", usn.FileReferenceNumber, usn.FileName)); } } else { // // handle files // bool add = true; if (fileExtensions != null && fileExtensions.Length != 0) { add = false; string s = Path.GetExtension(usn.FileName); foreach (string extension in fileExtensions) { if (0 == string.Compare(s, extension, true)) { add = true; break; } } } if (add) { if (!files.ContainsKey(usn.FileReferenceNumber)) { files.Add(usn.FileReferenceNumber, new FileNameAndFrn(usn.FileName, usn.ParentFileReferenceNumber)); } else { FileNameAndFrn frn = files[usn.FileReferenceNumber]; if (0 != string.Compare(usn.FileName, frn.Name, true)) { //Log.InfoFormat( // "Attempt to add duplicate file reference number: {0} for file {1}, file from index {2}", // usn.FileReferenceNumber, usn.FileName, frn.Name); throw new Exception(string.Format("Duplicate FRN: {0} for {1}", usn.FileReferenceNumber, usn.FileName)); } } } } pUsnRecord = new IntPtr(pUsnRecord.ToInt32() + usn.RecordLength); outBytesReturned -= usn.RecordLength; } Marshal.WriteInt64(medBuffer, Marshal.ReadInt64(pData, 0)); } Marshal.FreeHGlobal(pData); }