Пример #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;
        }        
Пример #3
0
        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);
        }
Пример #4
0
        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;
        }
Пример #5
0
        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;
        }
Пример #6
0
        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);  
        }