示例#1
0
        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;
        }
示例#2
0
        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;
        }