internal MultiRecordAttributeDataStream(List <ulong> fileReferenceNumbers)
 {
     if (null == fileReferenceNumbers)
     {
         throw new ArgumentNullException();
     }
     if (1 > fileReferenceNumbers.Count)
     {
         throw new ArgumentException();
     }
     _fileReferenceNumbers = new List <ulong>(fileReferenceNumbers);
     _currentEntryIndex    = 0;
     _currentEntry         = _fileReferenceNumbers[_currentEntryIndex];
     _thisBatch            = PartitionDataDisposableBatch.CreateNew(true);
 }
        /// <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;
                }
            }
        }