Exemple #1
0
        private void ReadMft(SafeHandle volume)
        {
            // ~1MB
            const int outputBufferSize = 1024 * 1024;

            var input = SetupMFTEnumData(volume);

            using (var outBuffer = SafeHGlobalHandle.Alloc(outputBufferSize))
            {
                PInvoke.ZeroMemory(outBuffer, outputBufferSize);
                using (var inBuffer = SafeHGlobalHandle.Alloc(sizeof(ulong)))
                {
                    bool hasData;

                    do
                    {
                        Marshal.StructureToPtr(input.StartFileReferenceNumber, inBuffer, true);

                        uint outBytesReturned;

                        hasData = PInvoke.DeviceIoControl(
                            volume.DangerousGetHandle(),
                            DeviceIoControlCode.FsctlEnumUsnData,
                            inBuffer,
                            Marshal.SizeOf <MFT_ENUM_DATA_V0>(),
                            outBuffer,
                            outputBufferSize,
                            out outBytesReturned,
                            IntPtr.Zero
                            );


                        var pUsnRecord = new IntPtr(outBuffer.DangerousGetHandle().ToInt64() + sizeof(Int64));

                        //61 is the minimum record length. Less than that is left-over space on the buffer
                        while (outBytesReturned > 60)
                        {
                            var usn = new USN_RECORD(pUsnRecord);

                            if (0 != (usn.FileAttributes & FileAttributeDirectory))
                            {
                                //Directory
                                _directories.Add(usn.FileReferenceNumber, new UsnRefsAndFileName
                                {
                                    FileName = usn.FileName,
                                    ParentFileReferenceNumber = usn.ParentFileReferenceNumber,
                                    FileReferenceNumber       = usn.FileReferenceNumber
                                });
                            }
                            else
                            {
                                //Files
                                _files.Add(usn.FileReferenceNumber, new UsnRefsAndFileName
                                {
                                    FileName = usn.FileName,
                                    ParentFileReferenceNumber = usn.ParentFileReferenceNumber,
                                    FileReferenceNumber       = usn.FileReferenceNumber
                                });
                            }

                            pUsnRecord        = new IntPtr(pUsnRecord.ToInt64() + usn.RecordLength);
                            outBytesReturned -= usn.RecordLength;
                        }

                        input.StartFileReferenceNumber = (ulong)Marshal.ReadInt64(outBuffer, 0);
                    } while (hasData);
                }
                ParseFullPath();
            }
        }
Exemple #2
0
        unsafe public void EnumerateFiles(IntPtr medBuffer, ref Dictionary <ulong, FileNameAndParentFrn> files, string[] fileExtensions)
        {
            IntPtr pData = Marshal.AllocHGlobal(sizeof(UInt64) + 0x10000);

            try
            {
                NativeWrapper.ZeroMemory(pData, sizeof(UInt64) + 0x10000);
                uint outBytesReturned = 0;

                while (false != NativeWrapper.DeviceIoControl(_changeJournalRootHandle,
                                                              NativeWrapper.FSCTL_ENUM_USN_DATA,
                                                              medBuffer,
                                                              sizeof(MFT_ENUM_DATA),
                                                              pData,
                                                              sizeof(UInt64) + 0x10000,
                                                              out outBytesReturned,
                                                              IntPtr.Zero))
                {
                    IntPtr pUsnRecord = new IntPtr(pData.ToInt32() + sizeof(Int64));
                    while (outBytesReturned > 60)
                    {
                        USN_RECORD usn = new USN_RECORD(pUsnRecord);
                        if (0 != (usn.FileAttributes & NativeWrapper.FILE_ATTRIBUTE_DIRECTORY))
                        {
                            //
                            // handle directories
                            //
                            if (!_directories.ContainsKey(usn.FileReferenceNumber))
                            {
                                _directories.Add(usn.FileReferenceNumber,
                                                 new FileNameAndParentFrn(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
                            //

                            // at this point we could get the * for the extension
                            bool add      = true;
                            bool fullpath = false;
                            if (fileExtensions != null && fileExtensions.Length != 0)
                            {
                                if (fileExtensions[0].ToString() == "*")
                                {
                                    add      = true;
                                    fullpath = true;
                                }
                                else
                                {
                                    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 (fullpath)
                                {
                                    if (!files.ContainsKey(usn.FileReferenceNumber))
                                    {
                                        files.Add(usn.FileReferenceNumber,
                                                  new FileNameAndParentFrn(usn.FileName, usn.ParentFileReferenceNumber));
                                    }
                                    else
                                    {
                                        FileNameAndParentFrn 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));
                                        }
                                    }
                                }
                                else
                                {
                                    if (!files.ContainsKey(usn.FileReferenceNumber))
                                    {
                                        files.Add(usn.FileReferenceNumber,
                                                  new FileNameAndParentFrn(usn.FileName, usn.ParentFileReferenceNumber));
                                    }
                                    else
                                    {
                                        FileNameAndParentFrn 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));
                }
            }
            catch (Exception e)
            {
                Console.Error.WriteLine(e.Message);
                Console.Error.WriteLine(e.StackTrace);
                throw new ApplicationException("Error in EnumerateFiles()", e);
            }
            finally
            {
                Marshal.FreeHGlobal(pData);
            }
        }
Exemple #3
0
        internal USNJrnl(byte[] bytes)
        {
            USN_RECORD structUSN = new USN_RECORD(bytes);

            #region UnmaskReason

            string reason = null;

            if ((structUSN.Reason & (uint)USN_REASON_BASIC_INFO_CHANGE) == (uint)USN_REASON_BASIC_INFO_CHANGE)
            {
                reason = "Basic Info Change";
            }
            if ((structUSN.Reason & (uint)USN_REASON_CLOSE) == (uint)USN_REASON_CLOSE)
            {
                reason = "Close";
            }
            if ((structUSN.Reason & (uint)USN_REASON_COMPRESSION_CHANGE) == (uint)USN_REASON_COMPRESSION_CHANGE)
            {
                reason = "Compression Change";
            }
            if ((structUSN.Reason & (uint)USN_REASON_DATA_EXTEND) == (uint)USN_REASON_DATA_EXTEND)
            {
                reason = "Data Extended";
            }
            if ((structUSN.Reason & (uint)USN_REASON_DATA_OVERWRITE) == (uint)USN_REASON_DATA_OVERWRITE)
            {
                reason = "Data Overwrite";
            }
            if ((structUSN.Reason & (uint)USN_REASON_DATA_TRUNCATION) == (uint)USN_REASON_DATA_TRUNCATION)
            {
                reason = "Data Truncation";
            }
            if ((structUSN.Reason & (uint)USN_REASON_EA_CHANGE) == (uint)USN_REASON_EA_CHANGE)
            {
                reason = "EA Change";
            }
            if ((structUSN.Reason & (uint)USN_REASON_ENCRYPTION_CHANGE) == (uint)USN_REASON_ENCRYPTION_CHANGE)
            {
                reason = "Encryption Change";
            }
            if ((structUSN.Reason & (uint)USN_REASON_FILE_CREATE) == (uint)USN_REASON_FILE_CREATE)
            {
                reason = "File Create";
            }
            if ((structUSN.Reason & (uint)USN_REASON_FILE_DELETE) == (uint)USN_REASON_FILE_DELETE)
            {
                reason = "File Delete";
            }
            if ((structUSN.Reason & (uint)USN_REASON_HARD_LINK_CHANGE) == (uint)USN_REASON_HARD_LINK_CHANGE)
            {
                reason = "Hard Link Change";
            }
            if ((structUSN.Reason & (uint)USN_REASON_INDEXABLE_CHANGE) == (uint)USN_REASON_INDEXABLE_CHANGE)
            {
                reason = "Indexable Change";
            }
            if ((structUSN.Reason & (uint)USN_REASON_NAMED_DATA_EXTEND) == (uint)USN_REASON_NAMED_DATA_EXTEND)
            {
                reason = "Named Data Extend";
            }
            if ((structUSN.Reason & (uint)USN_REASON_NAMED_DATA_OVERWRITE) == (uint)USN_REASON_NAMED_DATA_OVERWRITE)
            {
                reason = "Named Data Overwrite";
            }
            if ((structUSN.Reason & (uint)USN_REASON_NAMED_DATA_TRUNCATION) == (uint)USN_REASON_NAMED_DATA_TRUNCATION)
            {
                reason = "Named Data Truncation";
            }
            if ((structUSN.Reason & (uint)USN_REASON_OBJECT_ID_CHANGE) == (uint)USN_REASON_OBJECT_ID_CHANGE)
            {
                reason = "Object ID Change";
            }
            if ((structUSN.Reason & (uint)USN_REASON_RENAME_NEW_NAME) == (uint)USN_REASON_RENAME_NEW_NAME)
            {
                reason = "Rename: New Name";
            }
            if ((structUSN.Reason & (uint)USN_REASON_RENAME_OLD_NAME) == (uint)USN_REASON_RENAME_OLD_NAME)
            {
                reason = "Rename: Old Name";
            }
            if ((structUSN.Reason & (uint)USN_REASON_REPARSE_POINT_CHANGE) == (uint)USN_REASON_REPARSE_POINT_CHANGE)
            {
                reason = "Reparse Point Change";
            }
            if ((structUSN.Reason & (uint)USN_REASON_SECURITY_CHANGE) == (uint)USN_REASON_SECURITY_CHANGE)
            {
                reason = "Security Change";
            }
            if ((structUSN.Reason & (uint)USN_REASON_STREAM_CHANGE) == (uint)USN_REASON_STREAM_CHANGE)
            {
                reason = "Stream Change";
            }

            #endregion UnmaskReason

            #region UnmaskSourceInfo

            string sourceInfo = null;

            if ((structUSN.SourceInfo & (uint)USN_SOURCE.AUXILIARY_DATA) == (uint)USN_SOURCE.AUXILIARY_DATA)
            {
                sourceInfo = "Auxiliary Data";
            }
            if ((structUSN.SourceInfo & (uint)USN_SOURCE.DATA_MANAGEMENT) == (uint)USN_SOURCE.DATA_MANAGEMENT)
            {
                sourceInfo = "Data Management";
            }
            if ((structUSN.SourceInfo & (uint)USN_SOURCE.REPLICATION_MANAGEMENT) == (uint)USN_SOURCE.REPLICATION_MANAGEMENT)
            {
                sourceInfo = "Replication Management";
            }

            #endregion UnmaskSourceInfo

            FileReferenceNumber       = structUSN.FileReferenceNumber;
            ParentFileReferenceNumber = structUSN.ParentFileReferenceNumber;
            Usn            = structUSN.Usn;
            TimeStamp      = DateTime.FromFileTime(structUSN.TimeStamp);
            Reason         = reason;
            SourceInfo     = sourceInfo;
            SecurityId     = structUSN.SecurityId;
            FileAttributes = structUSN.FileAttributes;
            FileName       = Encoding.Unicode.GetString(structUSN.FileName);
        }