コード例 #1
0
 internal unsafe IPartitionClusterData GetData()
 {
     using (Stream input = OpenDataClusterStream()) {
         NonResidentDataStream dataStream = (NonResidentDataStream)input;
         long length = dataStream.Length;
         if (uint.MaxValue < length)
         {
             throw new ApplicationException();
         }
         IPartitionClusterData result = NtfsPartition.Current.GetBuffer((uint)length);
         byte *rawResult = result.Data;
         IPartitionClusterData inputData;
         while (null != (inputData = ((IClusterStream)dataStream).ReadNextCluster()))
         {
             try {
                 uint inputDataLength = inputData.DataSize;
                 if (int.MaxValue < inputDataLength)
                 {
                     throw new ApplicationException();
                 }
                 Helpers.Memcpy(inputData.Data, rawResult, (int)inputDataLength);
                 rawResult += inputDataLength;
             }
             finally {
                 inputData.Dispose();
             }
         }
         return(result);
     }
 }
コード例 #2
0
        private static unsafe void _Dump(NtfsAttributeListAttribute *from, DumpCallbackDelegate callback)
        {
            if (null == from)
            {
                throw new ArgumentNullException();
            }
            if (NtfsAttributeType.AttributeAttributeList != from->Header.AttributeType)
            {
                throw new ArgumentException();
            }
            IPartitionClusterData disposableData = null;
            ListEntry *           listBase       = null;
            uint listLength;

            try {
                if (from->Header.IsResident)
                {
                    NtfsResidentAttribute *listAttribute = (NtfsResidentAttribute *)from;
                    listBase   = (ListEntry *)((byte *)from + listAttribute->ValueOffset);
                    listLength = listAttribute->ValueLength;
                }
                else
                {
                    NtfsNonResidentAttribute *listAttribute = (NtfsNonResidentAttribute *)from;
                    disposableData = listAttribute->GetData();
                    if (null == disposableData)
                    {
                        throw new ApplicationException();
                    }
                    listBase = (ListEntry *)disposableData.Data;
                    ulong candidateLength = listAttribute->DataSize;
                    if (uint.MaxValue < candidateLength)
                    {
                        throw new ApplicationException();
                    }
                    listLength = (uint)candidateLength;
                }
                if (null == listBase)
                {
                    throw new ApplicationException();
                }
                uint offset = 0;
                while (offset < listLength)
                {
                    ListEntry *entry = (ListEntry *)((byte *)listBase + offset);
                    callback(entry);
                    offset += entry->EntryLength;
                }
            }
            finally {
                if (null != disposableData)
                {
                    disposableData.Dispose();
                }
            }
        }
コード例 #3
0
        /// <summary>Discover partitions</summary>
        internal unsafe void Discover()
        {
            VolumePartition fakePartition = new VolumePartition(_rawHandle, 0, 16);

            using (IPartitionClusterData rawData = fakePartition.ReadSectors(0)) {
                uint  minSector        = uint.MaxValue;
                uint  maxSector        = 0;
                byte *masterBootRecord = rawData.Data;
                if (0x55 != masterBootRecord[510])
                {
                    throw new ApplicationException();
                }
                if (0xAA != masterBootRecord[511])
                {
                    throw new ApplicationException();
                }
                // From http://thestarman.pcministry.com/asm/mbr/PartTables.htm
                // TODO : This is suitable for a Master Boot Record. Other types of boot records exist such
                // as the ExtendedBoot Record format.
                for (uint partitionIndex = 0; partitionIndex < 4; partitionIndex++)
                {
                    IntPtr partitionHandle;
                    if (!Natives.DuplicateHandle(new IntPtr(-1), _rawHandle,
                                                 new IntPtr(-1), out partitionHandle, 0 /* ignored because same access */,
                                                 false, 2 /*DUPLICATE_SAME_ACCESS*/))
                    {
                        throw new ApplicationException();
                    }
                    GenericPartition newPartition = GenericPartition.Create(partitionHandle, masterBootRecord, 446 + (16 * partitionIndex));
                    if (null == newPartition)
                    {
                        Natives.CloseHandle(partitionHandle);
                    }
                    else
                    {
                        // TODO : This algorithm doesn't let us witness the extra sectors after the last partition.
                        if (minSector > newPartition.StartSector)
                        {
                            minSector = newPartition.StartSector;
                        }
                        if (maxSector < (newPartition.StartSector + newPartition.SectorCount - 1))
                        {
                            maxSector = newPartition.StartSector + newPartition.SectorCount - 1;
                        }
                        _partitions.Add(newPartition);
                    }
                }
                Console.WriteLine("Found {0} partitions.", _partitions.Count);
                if (maxSector < minSector)
                {
                    throw new ApplicationException();
                }
                _volumePartition = new VolumePartition(_rawHandle, minSector, maxSector - minSector);
                return;
            }
        }
コード例 #4
0
ファイル: Helpers.cs プロジェクト: BlueSkeye/RDReadPOC
        internal static uint GetChainLength(this IPartitionClusterData data)
        {
            uint result = 0;

            for (IPartitionClusterData scannedData = data; null != scannedData; scannedData = scannedData.NextInChain)
            {
                result += scannedData.DataSize;
            }
            return(result);
        }
コード例 #5
0
ファイル: Helpers.cs プロジェクト: BlueSkeye/RDReadPOC
        internal static uint GetChainItemsCount(this IPartitionClusterData data)
        {
            uint result = 0;

            for (IPartitionClusterData scannedData = data; null != scannedData; scannedData = scannedData.NextInChain)
            {
                result++;
            }
            return(result);
        }
コード例 #6
0
 private void HandlePartitionClusterDataDisposal(IPartitionClusterData disposed)
 {
     if (_disposing)
     {
         return;
     }
     if (!_storage.Remove(disposed))
     {
         throw new ArgumentException();
     }
 }
コード例 #7
0
        /// <summary>Read some number of sectors.</summary>
        /// <param name="logicalSectorId">Logical identifier of the first sector to be read.</param>
        /// <param name="sectorsCount">Number of sectors to read.</param>
        /// <returns>Buffer address.</returns>
        internal unsafe IPartitionClusterData ReadSectors(ulong logicalSectorId, uint sectorsCount = 1)
        {
            IPartitionClusterData result = GetClusterBufferChain(sectorsCount * BytesPerSector);

            try {
                return(ReadSectors(result, 0, logicalSectorId, sectorsCount));
            }
            catch {
                if (null != result)
                {
                    result.Dispose();
                }
                throw;
            }
        }
コード例 #8
0
ファイル: NtfsFileRecord.cs プロジェクト: BlueSkeye/RDReadPOC
        internal static unsafe NtfsFileRecord *Create(ulong fileId)
        {
            if ((0xFFFFFFFFFFFF & fileId) != fileId)
            {
                throw new ArgumentException();
            }
            NtfsPartition         partition       = NtfsPartition.Current;
            ulong                 mftEntrySize    = partition.ClusterSize / partition.MFTEntryPerCluster;
            ulong                 clusterId       = fileId / partition.MFTEntryPerCluster;
            ulong                 inClusterOffset = (fileId % partition.MFTEntryPerCluster) * mftEntrySize;
            IPartitionClusterData clusterData     = partition.ReadSectors(clusterId * partition.SectorsPerCluster,
                                                                          partition.SectorsPerCluster);

            return((NtfsFileRecord *)(clusterData.Data + inClusterOffset));
        }
コード例 #9
0
 internal void Register(IPartitionClusterData data)
 {
     if (null == data)
     {
         throw new ArgumentNullException();
     }
     data.Disposed += _dispositionHandler;
     _storage.Add(data, 0);
     if (FeaturesContext.DataPoolChecksEnabled)
     {
         if (StorageCountAlert < _storage.Count)
         {
             throw new ApplicationException();
         }
     }
 }
コード例 #10
0
ファイル: NtfsFileRecord.cs プロジェクト: BlueSkeye/RDReadPOC
 internal unsafe void EnumerateRecordAttributes(NtfsPartition owner, ulong recordLBA,
                                                ref byte *buffer, RecordAttributeEnumeratorCallbackDelegate callback,
                                                NtfsAttributeType searchedType         = NtfsAttributeType.Any,
                                                AttributeNameFilterDelegate nameFilter = null)
 {
     using (IPartitionClusterData data = owner.ReadSectors(recordLBA)) {
         buffer = data.Data;
         NtfsFileRecord *header = (NtfsFileRecord *)buffer;
         header->AssertRecordType();
         if (1024 < header->BytesAllocated)
         {
             throw new NotImplementedException();
         }
         EnumerateRecordAttributes(header, callback, searchedType, nameFilter);
     }
 }
コード例 #11
0
        private unsafe void _Run()
        {
            NtfsPartition         partition   = Partition;
            IPartitionClusterData clusterData = null;

            try {
                NtfsFileRecord *fileRecord = partition.GetFileRecord(
                    NtfsWellKnownMetadataFiles.LogFile, out clusterData);
                fileRecord->AssertRecordType();
                throw new NotImplementedException();
            }
            finally {
                if (null != clusterData)
                {
                    clusterData.Dispose();
                }
            }
        }
コード例 #12
0
            IPartitionClusterData IClusterStream.ReadNextCluster()
            {
                if (!_clusterStreamBehavior)
                {
                    throw new NotSupportedException("Not a cluster stream.");
                }
                bool success = _ReadNextCluster();
                IPartitionClusterData result = _clusterData;

                _clusterData = null;
                if (!success)
                {
                    if (null != result)
                    {
                        result.Dispose();
                    }
                    return(null);
                }
                return(result);
            }
コード例 #13
0
        /// <summary>Read some number of sectors.</summary>
        /// <param name="into">Pre-allocated buffer.</param>
        /// <param name="logicalSectorId">Logical identifier of the first sector to be read.</param>
        /// <param name="sectorsCount">Number of sectors to read.</param>
        /// <returns>Buffer address.</returns>
        internal unsafe IPartitionClusterData ReadSectors(IPartitionClusterData into, long atOffset,
                                                          ulong logicalSectorId, uint sectorsCount = 1)
        {
            uint bytesPerSector = PartitionManager.Singleton.Geometry.BytesPerSector;
            uint expectedCount  = sectorsCount * bytesPerSector;

            if (null == into)
            {
                throw new ArgumentNullException();
            }
            if (0 > atOffset)
            {
                throw new ArgumentException();
            }
            if ((into.DataSize - atOffset) < expectedCount)
            {
                throw new ArgumentException();
            }
            if (FeaturesContext.DataPoolChecksEnabled)
            {
                if (expectedCount > into.DataSize)
                {
                    throw new ApplicationException();
                }
            }
            ulong offset         = (logicalSectorId + StartSector) * bytesPerSector;
            uint  totalBytesRead = 0;

            // Prevent concurrent reads on this partition.
            lock (_ioLock) {
                if (!Natives.SetFilePointerEx(_handle, (long)offset, out offset, Natives.FILE_BEGIN))
                {
                    int error = Marshal.GetLastWin32Error();
                    throw new ApplicationException();
                }
                uint chainItemsCount = into.GetChainItemsCount();
                uint chainLength     = into.GetChainLength();
                if (chainLength < expectedCount)
                {
                    throw new ApplicationException();
                }
                uint remainingExpectation = expectedCount;
                for (IPartitionClusterData currentData = into; null != currentData; currentData = currentData.NextInChain)
                {
                    uint readSize = remainingExpectation;
                    if (readSize > into.DataSize)
                    {
                        readSize = into.DataSize;
                    }
                    uint effectiveReadSize;
                    if (!Natives.ReadFile(_handle, into.Data + atOffset, readSize, out effectiveReadSize, IntPtr.Zero))
                    {
                        int error = Marshal.GetLastWin32Error();
                        throw new ApplicationException();
                    }
                    atOffset             += effectiveReadSize;
                    totalBytesRead       += effectiveReadSize;
                    remainingExpectation -= effectiveReadSize;
                }
            }
            if (totalBytesRead != expectedCount)
            {
                throw new ApplicationException();
            }
            return(into);
        }
コード例 #14
0
ファイル: Program.cs プロジェクト: BlueSkeye/RDReadPOC
        public static unsafe int Main(string[] args)
        {
            InstallExceptionHandlers();
            using (PartitionDataDisposableBatch mainBatch = PartitionDataDisposableBatch.CreateNew()) {
                DisplayVersion();

                IntPtr       handle = IntPtr.Zero;
                int          nativeError;
                DiskGeometry geometry = new DiskGeometry();

                try {
                    handle = Natives.CreateFile2(@"\\.\PhysicalDrive0", 0x80000000 /* GENERIC_READ */,
                                                 0x02 /* FILE_SHARE_WRITE */, 3 /* OPEN_EXISTING */, IntPtr.Zero);
                    nativeError = Marshal.GetLastWin32Error();
                    if ((IntPtr.Zero == handle) || (0 != nativeError))
                    {
                        Console.WriteLine("Physical drive opening failed. Error 0x{0:X8}", nativeError);
                        return(1);
                    }
                    geometry.Acquire(handle);
                    _partitionManager = new PartitionManager(handle, geometry);
                    _partitionManager.Discover();
                    InterpretActivePartitions();
                    if (FeaturesContext.InvariantChecksEnabled)
                    {
                        NtfsMFTFileRecord.AssertMFTRecordCachingInvariance(_partitionManager);
                    }
                    // TODO : Configure TrackedPartitionIndex from command line arguments.
                    foreach (GenericPartition partition in _partitionManager.EnumeratePartitions())
                    {
                        if (!partition.ShouldCapture)
                        {
                            continue;
                        }
                        NtfsPartition ntfsPartition = partition as NtfsPartition;
                        NtfsPartition.Current = ntfsPartition;

                        // Basic functionnality tests. Don't remove.
                        //ntfsPartition.CountFiles();
                        //ntfsPartition.MonitorBadClusters();
                        //ntfsPartition.ReadBitmap();

                        // Dump bad clusters.
                        ntfsPartition.DumpBadClusters();

                        // Dump UsnJournal
                        PrototypeUsnJournal();
                        new NtfsUsnJournalReader(ntfsPartition).Run();

                        // Dump LogFile
                        // new NtfsLogFileReader(ntfsPartition).Run();

                        // Locate file.
                        // string fileName = @"TEMP\AsciiTes.txt";
                        string fileName = @"$Extend\$UsnJrnl";
                        NtfsIndexEntryHeader *fileDescriptor = ntfsPartition.FindFile(fileName);
                        if (null == fileDescriptor)
                        {
                            throw new System.IO.FileNotFoundException(fileName);
                        }
                        IPartitionClusterData fileData             = null;
                        NtfsFileRecord *      usnJournalFileRecord =
                            ntfsPartition.GetFileRecord(fileDescriptor->FileReference, ref fileData);
                        if ((null == usnJournalFileRecord) || (null == fileData))
                        {
                            throw new ApplicationException();
                        }
                        try {
                            usnJournalFileRecord->EnumerateRecordAttributes(
                                delegate(NtfsAttribute * attribute, Stream dataStream) {
                                attribute->Dump();
                                return(true);
                            });
                            // For debugging purpose.
                            // fileRecord->BinaryDumpContent();

                            // TODO : Do something with the file.
                        }
                        finally {
                            if (null != fileData)
                            {
                                fileData.Dispose();
                            }
                        }
                    }
                    return(0);
                }
                finally {
                    if (IntPtr.Zero == handle)
                    {
                        Natives.CloseHandle(handle);
                        handle = IntPtr.Zero;
                    }
                }
            }
        }
コード例 #15
0
ファイル: Program.cs プロジェクト: BlueSkeye/RDReadPOC
        private static unsafe void PrototypeUsnJournal()
        {
            List <Tuple <uint, ulong> > records = new List <Tuple <uint, ulong> >()
            {
                new Tuple <uint, ulong>(0x00000000, 0x10000000417F8),
                new Tuple <uint, ulong>(0x00831030, 0x133000000030345),
                new Tuple <uint, ulong>(0x00835CE0, 0x79200000000288E),
                new Tuple <uint, ulong>(0x00839E60, 0x16C0000000059EB),
                new Tuple <uint, ulong>(0x00842DE0, 0x7340000000057C6),
                new Tuple <uint, ulong>(0x00844160, 0x600000018405F),
                new Tuple <uint, ulong>(0x0084A215, 0x8F000000036956),
                new Tuple <uint, ulong>(0x0084EF80, 0x2B0000000020AD),
                new Tuple <uint, ulong>(0x00852F71, 0x3D00000000024B8),
                new Tuple <uint, ulong>(0x00857E50, 0x50B000000007274),
                new Tuple <uint, ulong>(0x00858DB0, 0x235000000000705),
                new Tuple <uint, ulong>(0x0085CD90, 0xD20000000086D7),
                new Tuple <uint, ulong>(0x00860A90, 0x7900000000840C),
                new Tuple <uint, ulong>(0x00862160, 0x6E500000002FC3E),
                new Tuple <uint, ulong>(0x00868190, 0x7F000000004050),
                new Tuple <uint, ulong>(0x0086C570, 0x49E000000003C3E),
                new Tuple <uint, ulong>(0x0086D8F0, 0x160000000F353D),
                new Tuple <uint, ulong>(0x00871DB0, 0x9D000000004053),
                new Tuple <uint, ulong>(0x00875B90, 0x19F000000001DD5),
                new Tuple <uint, ulong>(0x00877B0C, 0x387000000031EA2),
                new Tuple <uint, ulong>(0x0087BE50, 0x840000000041B7),
                new Tuple <uint, ulong>(0x00883CC0, 0x2C4000000006741),
                new Tuple <uint, ulong>(0x00888210, 0x93000000007190),
                new Tuple <uint, ulong>(0x00889710, 0xF30000000DD118),
                new Tuple <uint, ulong>(0x0089759B, 0xA2B000000006C37),
                new Tuple <uint, ulong>(0x0089F050, 0xD400000002EF59),
                new Tuple <uint, ulong>(0x008A3480, 0x4000000030266),
                new Tuple <uint, ulong>(0x008A4780, 0x3D000000122430),
                new Tuple <uint, ulong>(0x008A8FF0, 0x4A0000000F8276),
                new Tuple <uint, ulong>(0x008ACDF0, 0x7000000030267),
                new Tuple <uint, ulong>(0x008B1FF0, 0xF000000030265),
                new Tuple <uint, ulong>(0x008B32F2, 0x10000001E9963),
                new Tuple <uint, ulong>(0x008B7272, 0x5000000030269),
                new Tuple <uint, ulong>(0x008BB022, 0x6000000030268),
                new Tuple <uint, ulong>(0x008BC2A0, 0xC000000121FED),
                new Tuple <uint, ulong>(0x008C4B70, 0x3700000016AC1D),
                new Tuple <uint, ulong>(0x008CEDF0, 0x5000000184830),
                new Tuple <uint, ulong>(0x008DEAD0, 0x1D0000000004401),
                new Tuple <uint, ulong>(0x008E2D20, 0x3B400000000157B),
                new Tuple <uint, ulong>(0x008E4120, 0x3DC0000000045DC),
                new Tuple <uint, ulong>(0x008E8FC0, 0x2800000000E8AE),
                new Tuple <uint, ulong>(0x008F123D, 0x52F0000000010F0),
                new Tuple <uint, ulong>(0x008F72F0, 0x147000000033E17),
                new Tuple <uint, ulong>(0x008FB610, 0x5A0000000305FD),
                new Tuple <uint, ulong>(0x008FCA00, 0x144000000003871),
                new Tuple <uint, ulong>(0x00901140, 0x1E2000000033E33),
                new Tuple <uint, ulong>(0x009054B0, 0x29000000033E34),
                new Tuple <uint, ulong>(0x00906AB0, 0x3420000000035B2),
                new Tuple <uint, ulong>(0x0090B250, 0xD7000000004C47),
                new Tuple <uint, ulong>(0x0090F710, 0xA9000000005C58),
                new Tuple <uint, ulong>(0x00913660, 0xC9000000002451),
                new Tuple <uint, ulong>(0x0091A1E0, 0xA8000000004E3B),
                new Tuple <uint, ulong>(0x009280D4, 0x2920000000DD0CA),
                new Tuple <uint, ulong>(0x0092C280, 0x276000000031B0A),
                new Tuple <uint, ulong>(0x00934D30, 0x6F0000000F179E),
                new Tuple <uint, ulong>(0x0093B220, 0xB20000000D3A3F),
                new Tuple <uint, ulong>(0x0093F0C4, 0x5400000002BC62),
                new Tuple <uint, ulong>(0x00940380, 0xA7000000004A8C),
                new Tuple <uint, ulong>(0x00945C6F, 0x6F000000008D46),
                new Tuple <uint, ulong>(0x0094C310, 0x3A0000000D9AA7),
                new Tuple <uint, ulong>(0x00954910, 0x4C0000000D9A91)
            };

            NtfsPartition         partition    = NtfsPartition.Current;
            ulong                 mftEntrySize = partition.ClusterSize / partition.MFTEntryPerCluster;
            IPartitionClusterData data         = null;

            try {
                ulong baseFileRecord = 0;
                foreach (Tuple <uint, ulong> record in records)
                {
                    ulong           fileReference = record.Item2;
                    NtfsFileRecord *fileRecord    = partition.GetFileRecord(fileReference, ref data);
                    if (0 == baseFileRecord)
                    {
                        baseFileRecord = fileRecord->BaseFileRecord;
                    }
                    if (fileRecord->BaseFileRecord != baseFileRecord)
                    {
                        fileRecord->BinaryDump();
                        fileRecord->Dump();
                        throw new ApplicationException();
                    }
                    fileRecord->EnumerateRecordAttributes(delegate(NtfsAttribute * value, Stream attributeDataStream) {
                        if (null != attributeDataStream)
                        {
                            throw new NotSupportedException();
                        }
                        if (value->IsResident)
                        {
                            throw new NotSupportedException();
                        }
                        IClusterStream dataStream = (IClusterStream)((NtfsNonResidentAttribute *)value)->OpenDataClusterStream();
                        dataStream.SeekToNextNonEmptyCluster();
                        NtfsUsnJournalReader.UsnRecordV2 *currentUsnRecord = null;
                        while (true)
                        {
                            using (IPartitionClusterData clusterData = dataStream.ReadNextCluster()) {
                                if (null == clusterData)
                                {
                                    // Done with this stream.
                                    return(true);
                                }
                                for (uint offset = 0; offset < clusterData.DataSize; offset += currentUsnRecord->RecordLength)
                                {
                                    currentUsnRecord = (NtfsUsnJournalReader.UsnRecordV2 *)(clusterData.Data + offset);
                                    if (0 == currentUsnRecord->RecordLength)
                                    {
                                        break;
                                    }
                                    if (2 != currentUsnRecord->MajorVersion)
                                    {
                                        Helpers.BinaryDump((byte *)currentUsnRecord,
                                                           (uint)Marshal.SizeOf <NtfsUsnJournalReader.UsnRecordV2>());
                                        throw new NotSupportedException();
                                    }
                                    if (0 != currentUsnRecord->MinorVersion)
                                    {
                                        throw new NotSupportedException();
                                    }
                                    currentUsnRecord->Dump();
                                }
                            }
                        }
                    },
                                                          NtfsAttributeType.AttributeData, null);
                    fileRecord->DumpAttributes();
                }
                return;
            }
            finally {
                if (null != data)
                {
                    data.Dispose();
                }
            }
        }
コード例 #16
0
        /// <summary></summary>
        /// <param name="from">The NtfsAttributeListAttribute to be used for enumeration.</param>
        /// <param name="searchedAttributeType">The type of the searched attribute or
        /// <see cref="NtfsAttributeType.Any"/> if the caller is interested in all kinds of
        /// attributes.</param>
        /// <param name="listEntryHandler">A callback to be invoked on each entry matching
        /// the attribute type selection criteria.</param>
        /// <remarks>WARNING : This might seems counterintuitive to have this method at a class
        /// level instead of making it an instance one. This is because we absolutely don't want
        /// it to be invoked on an object reference that is subject to being moved in memory by
        /// the GC. Forcing the caller to provide a pointer makes her responsible for enforcing
        /// the pinning requirements.</remarks>
        internal static unsafe void EnumerateEntries(NtfsAttribute *from,
                                                     NtfsAttributeType searchedAttributeType, EntryEnumeratorCallbackDelegate listEntryHandler)
        {
            if (null == from)
            {
                throw new ArgumentNullException();
            }
            if (NtfsAttributeType.AttributeAttributeList != from->AttributeType)
            {
                throw new ArgumentException();
            }
            IPartitionClusterData listAttributeData = null;
            // Address of first ListeEntry item for this attribute.
            ListEntry *listBase = null;
            uint       listLength;

            try {
                if (from->IsResident)
                {
                    NtfsResidentAttribute *listAttribute = (NtfsResidentAttribute *)from;
                    listBase   = (ListEntry *)((byte *)from + listAttribute->ValueOffset);
                    listLength = listAttribute->ValueLength;
                }
                else
                {
                    NtfsNonResidentAttribute *listAttribute = (NtfsNonResidentAttribute *)from;
                    listAttributeData = listAttribute->GetData();
                    if (null == listAttributeData)
                    {
                        throw new ApplicationException();
                    }
                    listBase = (ListEntry *)listAttributeData.Data;
                    ulong candidateLength = listAttribute->DataSize;
                    if (uint.MaxValue < candidateLength)
                    {
                        throw new ApplicationException();
                    }
                    listLength = (uint)candidateLength;
                }
                if (null == listBase)
                {
                    throw new ApplicationException();
                }
                NtfsAttributeType currentAttributeType   = NtfsAttributeType.Any;
                ushort            currentAttributeNumber = ushort.MaxValue;
                ListEntry *       scannedEntry;
                for (uint offset = 0; offset < listLength; offset += scannedEntry->EntryLength)
                {
                    scannedEntry = (ListEntry *)((byte *)listBase + offset);
                    if ((currentAttributeNumber == scannedEntry->AttributeNumber) &&
                        (currentAttributeType == scannedEntry->AttributeType))
                    {
                        // The entry is a continuation of the previous one. Ignore it. It should
                        // have been processed by a previous loop if required.
                        continue;
                    }
                    currentAttributeNumber = scannedEntry->AttributeNumber;
                    currentAttributeType   = scannedEntry->AttributeType;
                    if ((NtfsAttributeType.Any != searchedAttributeType) &&
                        (scannedEntry->AttributeType != searchedAttributeType))
                    {
                        // This entry doesn't match the search criteria on attribute type.
                        continue;
                    }
                    EntryListReferencedAttributeHandlerDelegate attributeDataHandler;
                    bool includeData;
                    if (!listEntryHandler(scannedEntry, out attributeDataHandler, out includeData))
                    {
                        // The callback doesn't wish to continue with other list entries.
                        return;
                    }
                    if (null == attributeDataHandler)
                    {
                        // The callback doesn't wish to retrieve the attribute itself for the
                        // currently scanned entry.
                        continue;
                    }
                    // The last callback invocation decided it needs some data from the attribute
                    // itself before deciding what to do.
                    if (!HandleEntryReferencedAttribute(scannedEntry, listLength - offset,
                                                        attributeDataHandler, includeData))
                    {
                        return;
                    }
                }
            }
            finally {
                if (null != listAttributeData)
                {
                    listAttributeData.Dispose();
                }
            }
        }
コード例 #17
0
        /// <summary>The caller enumerating entries might be interested in the content of
        /// the currently scanned entry. This might be either for additional filtering at
        /// attribute level (including attribute name) or for full attribute data processing.
        /// </summary>
        /// <param name="entry">The scanned list entry of interest. Should a single
        /// attribute span several entries, this one is guaranteed to be the first one for the
        /// attribute.</param>
        /// <param name="remainingBytesInList">Number of bytes remaining in list, relatively to the
        /// entry address.</param>
        /// <param name="entryReferencedAttributeHandler">The callback that will be invoked
        /// with the referenced attribute with or without full attribute data depending on
        /// the value of <paramref name="dataIncluded"/></param>
        /// <param name="dataIncluded"></param>
        /// <returns>true if caller should continue process data, false if it should stop.</returns>
        private static unsafe bool HandleEntryReferencedAttribute(ListEntry *entry, uint remainingBytesInList,
                                                                  EntryListReferencedAttributeHandlerDelegate entryReferencedAttributeHandler,
                                                                  bool dataIncluded)
        {
            ushort            currentAttributeNumber = entry->AttributeNumber;
            NtfsAttributeType currentAttributeType   = entry->AttributeType;
            byte *            baseAddress            = (byte *)entry;
            uint relativeOffset = 0;

            // The last callback invocation decided it needs some more data before deciding
            // what to do.
            IPartitionClusterData clusterData      = null;
            NtfsPartition         currentPartition = NtfsPartition.Current;

            using (PartitionDataDisposableBatch batch = PartitionDataDisposableBatch.CreateNew()) {
                while (true)
                {
                    ListEntry *  scannedEntry            = (ListEntry *)baseAddress;
                    ulong        mainFileReferenceNumber = entry->FileReferenceNumber;
                    List <ulong> entries    = new List <ulong>();
                    Stream       dataStream = null;
                    if (dataIncluded)
                    {
                        // Read each record and prepare for data retrieval.
                        while (true)
                        {
                            entries.Add(scannedEntry->FileReferenceNumber);
                            relativeOffset += scannedEntry->EntryLength;
                            if (relativeOffset >= remainingBytesInList)
                            {
                                // Take care not to go further than the end of the list.
                                break;
                            }
                            scannedEntry = (ListEntry *)(baseAddress + relativeOffset);
                            if ((currentAttributeNumber != scannedEntry->AttributeNumber) ||
                                (currentAttributeType != scannedEntry->AttributeType))
                            {
                                break;
                            }
                        }
                        dataStream = new MultiRecordAttributeDataStream(entries);
                    }
                    // Retrieve attribute itself.
                    NtfsFileRecord *mainFileRecord =
                        currentPartition.GetFileRecord(mainFileReferenceNumber, ref clusterData);
                    if (null == mainFileRecord)
                    {
                        throw new ApplicationException();
                    }
                    NtfsAttribute *retrievedAttribute =
                        (NtfsAttribute *)((byte *)mainFileRecord + mainFileRecord->AttributesOffset);

                    // Invoke callback.
                    bool retry;
                    if (!entryReferencedAttributeHandler(retrievedAttribute, dataStream, out retry))
                    {
                        // After attribute has been processed, it has been decided no other list
                        // entry should be performed.
                        return(false);
                    }
                    if (!retry)
                    {
                        // After attribute has been processed, it has been decided that no
                        // additional data from this attribute is required. However the enumeration
                        // of other list entries should continue.
                        return(true);
                    }
                    if (dataIncluded)
                    {
                        throw new InvalidOperationException();
                    }
                    // Attribute has been processed, however not enough data was available for a
                    // final decision. We loop and include all data now.
                    dataIncluded = true;
                }
            }
        }
コード例 #18
0
        private unsafe void _Run()
        {
            NtfsPartition         partition   = Partition;
            IPartitionClusterData clusterData = null;

            try {
                // Note : We could also use the NtfsWellKnownMetadataFiles.Extend entry to
                // locate the directory, then find the $UsnJrnl entry directly from there.
                string fileName = @"$UsnJrnl";
                NtfsIndexEntryHeader *fileDescriptor = partition.FindFile(fileName, NtfsWellKnownMetadataFiles.Extend);
                if (null == fileDescriptor)
                {
                    throw new System.IO.FileNotFoundException(fileName);
                }
                IPartitionClusterData fileData = null;
                try {
                    NtfsFileRecord *fileRecord =
                        partition.GetFileRecord(fileDescriptor->FileReference, ref fileData);
                    fileRecord->AssertRecordType();
                    // We retrieve the first attribute here.
                    Stream         dataStream;
                    NtfsAttribute *jAttribute = fileRecord->GetAttribute(NtfsAttributeType.AttributeData,
                                                                         out dataStream, 1, _isDollarJAttributeNameFilter);
                    if (null == jAttribute)
                    {
                        throw new ApplicationException();
                    }
                    if (jAttribute->IsResident)
                    {
                        // Seems this is never the case.
                        throw new NotSupportedException("CODE REVIEW REQUIRED");
                    }
                    NtfsNonResidentAttribute *jNrAttribute = (NtfsNonResidentAttribute *)jAttribute;
                    jNrAttribute->Dump();
                    byte[]   buffer = new byte[NtfsPartition.Current.ClusterSize];
                    DateTime sparseReadStartTime = DateTime.UtcNow;
                    TimeSpan sparseReadDuration;
                    if (null == dataStream)
                    {
                        dataStream = jNrAttribute->OpenDataStream();
                        throw new ApplicationException("CODE REVIEW REQUIRED");
                    }
                    int  totalReads       = 0;
                    bool nonNullByteFound = false;
                    while (true)
                    {
                        int readCount = dataStream.Read(buffer, 0, buffer.Length);
                        if (-1 == readCount)
                        {
                            sparseReadDuration = DateTime.UtcNow - sparseReadStartTime;
                            break;
                        }
                        if (nonNullByteFound)
                        {
                            for (int index = 0; index < readCount; index++)
                            {
                                if (0 == buffer[index])
                                {
                                    continue;
                                }
                                sparseReadDuration = DateTime.UtcNow - sparseReadStartTime;
                                Console.WriteLine("{0} null leading bytes found after {1} secs.",
                                                  totalReads + index, (int)sparseReadDuration.TotalSeconds);
                                nonNullByteFound = true;
                                break;
                            }
                        }
                        totalReads += readCount;
                        if (nonNullByteFound)
                        {
                            Helpers.BinaryDump(buffer, (uint)readCount);
                        }
                    }
                    if (!nonNullByteFound)
                    {
                        sparseReadDuration = DateTime.UtcNow - sparseReadStartTime;
                        Console.WriteLine("{0} null leading bytes found after {1} secs.",
                                          totalReads, (int)sparseReadDuration.TotalSeconds);
                    }
                    throw new NotImplementedException();
                    NtfsAttribute *rawAttribute =
                        fileRecord->GetAttribute(NtfsAttributeType.AttributeData, out dataStream, 1);
                    if (null == rawAttribute)
                    {
                        throw new ApplicationException();
                    }
                    if ("$Max" != rawAttribute->Name)
                    {
                        throw new ApplicationException();
                    }
                    if (rawAttribute->IsResident)
                    {
                        NtfsResidentAttribute *reMaxAttribute = (NtfsResidentAttribute *)rawAttribute;
                        if (FeaturesContext.InvariantChecksEnabled)
                        {
                            if (0x20 != reMaxAttribute->ValueLength)
                            {
                                throw new ApplicationException();
                            }
                        }
                        MaxAttribute *maxAttribute = (MaxAttribute *)((byte *)reMaxAttribute + reMaxAttribute->ValueOffset);
                    }
                    else
                    {
                        throw new NotSupportedException();
                    }
                    rawAttribute = fileRecord->GetAttribute(NtfsAttributeType.AttributeData, out dataStream, 2);
                    if (null == rawAttribute)
                    {
                        throw new ApplicationException();
                    }
                    if ("$J" != rawAttribute->Name)
                    {
                        throw new ApplicationException();
                    }
                    throw new NotImplementedException();
                }
                finally {
                    if (null != fileData)
                    {
                        fileData.Dispose();
                    }
                }
            }
            finally {
                if (null != clusterData)
                {
                    clusterData.Dispose();
                }
            }
        }