コード例 #1
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();
                }
            }
        }
コード例 #2
0
        public static void InsertHeadList(
            ListEntry *ListHead,
            ListEntry *Entry
            )
        {
            ListEntry *flink;

            flink           = ListHead->Flink;
            Entry->Flink    = flink;
            Entry->Blink    = ListHead;
            flink->Blink    = Entry;
            ListHead->Flink = Entry;
        }
コード例 #3
0
        public static void InsertTailList(
            ListEntry *ListHead,
            ListEntry *Entry
            )
        {
            ListEntry *blink;

            blink           = ListHead->Blink;
            Entry->Flink    = ListHead;
            Entry->Blink    = blink;
            blink->Flink    = Entry;
            ListHead->Blink = Entry;
        }
コード例 #4
0
        public static ListEntry *RemoveTailList(
            ListEntry *ListHead
            )
        {
            ListEntry *blink;
            ListEntry *entry;

            entry           = ListHead->Blink;
            blink           = entry->Blink;
            ListHead->Blink = blink;
            blink->Flink    = ListHead;

            return(entry);
        }
コード例 #5
0
        public static ListEntry *RemoveHeadList(
            ListEntry *ListHead
            )
        {
            ListEntry *flink;
            ListEntry *entry;

            entry           = ListHead->Flink;
            flink           = entry->Flink;
            ListHead->Flink = flink;
            flink->Blink    = ListHead;

            return(entry);
        }
コード例 #6
0
        public static bool RemoveEntryList(
            ListEntry *Entry
            )
        {
            ListEntry *blink;
            ListEntry *flink;

            flink        = Entry->Flink;
            blink        = Entry->Blink;
            blink->Flink = flink;
            flink->Blink = blink;

            return(flink == blink);
        }
コード例 #7
0
 public static bool IsListEmpty(
     ListEntry *ListHead
     )
 {
     return(ListHead->Flink == ListHead->Blink);
 }
コード例 #8
0
 public static void InitializeListHead(
     ListEntry *ListHead
     )
 {
     ListHead->Flink = ListHead->Blink = ListHead;
 }
コード例 #9
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;
                }
            }
        }
コード例 #10
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();
                }
            }
        }