public FileRecord(byte[] recordBytes, string volume, bool fast)
        {
            VolumePath = volume;

            Signature = Encoding.ASCII.GetString(recordBytes, 0x00, 0x04);

            if (Signature == "FILE")
            {
                // Parse File Record Header
                OffsetOfUS = BitConverter.ToUInt16(recordBytes, 0x04);
                SizeOfUS   = BitConverter.ToUInt16(recordBytes, 0x06);

                #region UpdateSequenceNumber
                byte[] usnBytes = new byte[2];
                Array.Copy(recordBytes, OffsetOfUS, usnBytes, 0, usnBytes.Length);
                UpdateSequenceNumber = BitConverter.ToUInt16(usnBytes, 0);
                #endregion UpdateSequenceNumber

                #region UpdateSequenceArray
                UpdateSequenceArray = new byte[(2 * SizeOfUS) - 2];
                Array.Copy(recordBytes, (OffsetOfUS + 2), UpdateSequenceArray, 0, UpdateSequenceArray.Length);
                #endregion UpdateSequenceArray

                LogFileSequenceNumber = BitConverter.ToUInt64(recordBytes, 0x08);
                SequenceNumber        = BitConverter.ToUInt16(recordBytes, 0x10);
                Hardlinks             = BitConverter.ToUInt16(recordBytes, 18);
                OffsetOfAttribute     = BitConverter.ToUInt16(recordBytes, 20);
                Flags = BitConverter.ToUInt16(recordBytes, 22);

                #region Deleted
                if ((Flags & (ushort)FILE_RECORD_FLAG.INUSE) == (ushort)FILE_RECORD_FLAG.INUSE)
                {
                    Deleted = false;
                }
                else
                {
                    Deleted = true;
                }
                #endregion Deleted

                #region Directory
                if ((Flags & (ushort)FILE_RECORD_FLAG.DIR) == (ushort)FILE_RECORD_FLAG.DIR)
                {
                    Directory = true;
                }
                else
                {
                    Directory = false;
                }
                #endregion Directory

                RealSize        = BitConverter.ToUInt32(recordBytes, 24);
                AllocatedSize   = BitConverter.ToUInt32(recordBytes, 28);
                ReferenceToBase = BitConverter.ToUInt64(recordBytes, 32);
                NextAttrId      = BitConverter.ToUInt16(recordBytes, 40);
                RecordNumber    = BitConverter.ToUInt32(recordBytes, 44);

                #region Attribute
                // Create a byte array representing the attribute array
                byte[] attrArrayBytes = new byte[RealSize - OffsetOfAttribute];
                Array.Copy(recordBytes, OffsetOfAttribute, attrArrayBytes, 0, attrArrayBytes.Length);

                // Instantiate an empty list of Attr Objects (We don't know how many attributes the record contains)
                List <Attr> AttributeList = new List <Attr>();

                // Initialize the offset value to 0
                int currentOffset = 0;

                do
                {
                    // Get attribute size
                    int attrSizeOffset = currentOffset + 4;
                    int attrSize       = BitConverter.ToInt32(attrArrayBytes, attrSizeOffset);

                    // Create new byte array with just current attribute's bytes
                    byte[] currentAttrBytes = new byte[attrSize];
                    Array.Copy(attrArrayBytes, currentOffset, currentAttrBytes, 0, currentAttrBytes.Length);

                    // Increment currentOffset
                    currentOffset += attrSize;

                    Attr attr = AttributeFactory.Get(currentAttrBytes, volume);

                    if (attr != null)
                    {
                        if (attr.Name == Attr.ATTR_TYPE.STANDARD_INFORMATION)
                        {
                            StandardInformation stdInfo = attr as StandardInformation;
                            ModifiedTime = stdInfo.ModifiedTime;
                            AccessedTime = stdInfo.AccessedTime;
                            ChangedTime  = stdInfo.ChangedTime;
                            BornTime     = stdInfo.BornTime;
                            Permission   = stdInfo.Permission;
                        }
                        else if (attr.Name == Attr.ATTR_TYPE.FILE_NAME)
                        {
                            FileName fN = attr as FileName;
                            if (!(fN.Namespace == 2))
                            {
                                Name = fN.Filename;
                                ParentSequenceNumber = fN.ParentSequenceNumber;
                                ParentRecordNumber   = fN.ParentRecordNumber;
                                FNModifiedTime       = fN.ModifiedTime;
                                FNAccessedTime       = fN.AccessedTime;
                                FNChangedTime        = fN.ChangedTime;
                                FNBornTime           = fN.BornTime;
                            }
                        }

                        AttributeList.Add(attr);
                    }
                } while (currentOffset < (attrArrayBytes.Length - 8));

                Attribute = AttributeList.ToArray();
                #endregion Attribute

                FullName = Name;
            }
            else
            {
                throw new Exception("Invalid Master File Table Entry");
            }
        }
        public FileRecord(ref FileRecord[] array, byte[] recordBytes, string volume)
        {
            VolumePath = volume;

            Signature = Encoding.ASCII.GetString(recordBytes, 0x00, 0x04);

            if (Signature == "FILE")
            {
                // Parse File Record Header
                OffsetOfUS = BitConverter.ToUInt16(recordBytes, 4);
                SizeOfUS   = BitConverter.ToUInt16(recordBytes, 6);

                #region UpdateSequenceNumber

                byte[] usnBytes = new byte[2];
                Array.Copy(recordBytes, OffsetOfUS, usnBytes, 0, usnBytes.Length);
                UpdateSequenceNumber = BitConverter.ToUInt16(usnBytes, 0);

                #endregion UpdateSequenceNumber

                #region UpdateSequenceArray

                UpdateSequenceArray = new byte[(2 * SizeOfUS) - 2];
                Array.Copy(recordBytes, (OffsetOfUS + 2), UpdateSequenceArray, 0, UpdateSequenceArray.Length);

                #endregion UpdateSequenceArray

                LogFileSequenceNumber = BitConverter.ToUInt64(recordBytes, 8);
                SequenceNumber        = BitConverter.ToUInt16(recordBytes, 16);
                Hardlinks             = BitConverter.ToUInt16(recordBytes, 18);
                OffsetOfAttribute     = BitConverter.ToUInt16(recordBytes, 20);
                Flags = BitConverter.ToUInt16(recordBytes, 22);

                #region Deleted
                if ((Flags & (ushort)FILE_RECORD_FLAG.INUSE) == (ushort)FILE_RECORD_FLAG.INUSE)
                {
                    Deleted = false;
                }
                else
                {
                    Deleted = true;
                }
                #endregion Deleted

                #region Directory
                if ((Flags & (ushort)FILE_RECORD_FLAG.DIR) == (ushort)FILE_RECORD_FLAG.DIR)
                {
                    Directory = true;
                }
                else
                {
                    Directory = false;
                }
                #endregion Directory

                RealSize        = BitConverter.ToUInt32(recordBytes, 24);
                AllocatedSize   = BitConverter.ToUInt32(recordBytes, 28);
                ReferenceToBase = BitConverter.ToUInt64(recordBytes, 32);
                NextAttrId      = BitConverter.ToUInt16(recordBytes, 40);
                RecordNumber    = BitConverter.ToUInt32(recordBytes, 44);

                #region Attribute
                // Create a byte array representing the attribute array
                byte[] attrArrayBytes = new byte[RealSize - OffsetOfAttribute];
                Array.Copy(recordBytes, OffsetOfAttribute, attrArrayBytes, 0, attrArrayBytes.Length);

                // Instantiate an empty list of Attr Objects (We don't know how many attributes the record contains)
                List <Attr> AttributeList = new List <Attr>();

                // Initialize the offset value to 0
                int currentOffset = 0;

                if (currentOffset < (attrArrayBytes.Length - 8))
                {
                    do
                    {
                        // Get attribute size
                        int attrSizeOffset = currentOffset + 4;
                        int attrSize       = BitConverter.ToInt32(attrArrayBytes, attrSizeOffset);

                        // Create new byte array with just current attribute's bytes
                        byte[] currentAttrBytes = new byte[attrSize];
                        Array.Copy(attrArrayBytes, currentOffset, currentAttrBytes, 0, currentAttrBytes.Length);

                        // Increment currentOffset
                        currentOffset += attrSize;

                        Attr attr = AttributeFactory.Get(currentAttrBytes, volume);

                        if (attr != null)
                        {
                            if (attr.Name == Attr.ATTR_TYPE.STANDARD_INFORMATION)
                            {
                                StandardInformation stdInfo = attr as StandardInformation;
                                ModifiedTime = stdInfo.ModifiedTime;
                                AccessedTime = stdInfo.AccessedTime;
                                ChangedTime  = stdInfo.ChangedTime;
                                BornTime     = stdInfo.BornTime;
                                Permission   = stdInfo.Permission;
                            }
                            else if (attr.Name == Attr.ATTR_TYPE.FILE_NAME)
                            {
                                FileName fN = attr as FileName;
                                if (!(fN.Namespace == 2))
                                {
                                    Name = fN.Filename;
                                    ParentSequenceNumber = fN.ParentSequenceNumber;
                                    ParentRecordNumber   = fN.ParentRecordNumber;
                                    FNModifiedTime       = fN.ModifiedTime;
                                    FNAccessedTime       = fN.AccessedTime;
                                    FNChangedTime        = fN.ChangedTime;
                                    FNBornTime           = fN.BornTime;
                                }
                            }

                            AttributeList.Add(attr);
                        }
                    } while (currentOffset < (attrArrayBytes.Length - 8));
                }

                Attribute = AttributeList.ToArray();
                #endregion Attribute

                #region FullName

                StringBuilder sb = new StringBuilder();

                // Record 5 is the root of the drive
                if (RecordNumber == 5)
                {
                    sb.Append(volume.Split('\\')[3]);
                }
                else
                {
                    // Derive Path by looking at ParentRecord's FullName
                    if (array[(int)ParentRecordNumber] != null)
                    {
                        sb.Append(array[(int)ParentRecordNumber].FullName);
                    }
                    // If record for Parent does not already exist then instantiate it and add it to the array
                    else
                    {
                        //Console.WriteLine("RecordIndex: {0}, ParentIndex: {1}", RecordNumber, ParentRecordNumber);
                        // This is where the recursive call should live...
                        //array[(int)ParentRecordNumber] = new FileRecord(ref array, FileRecord.GetRecordBytes(volume, (int)ParentRecordNumber), volume);
                        //sb.Append(array[(int)ParentRecordNumber].FullName);
                    }
                    // Add file name to end of path
                    sb.Append(Name);
                }

                // Add trailing \ to any file that is a directory
                if (Directory)
                {
                    sb.Append('\\');
                }

                // Figure out a way to have record 15 not have a name of $MFT...

                FullName = sb.ToString();

                #endregion FullName
            }
        }