byte[] ReadDynamic(int count) { int positionInBuffer = 0; int bytesRemaining = count; byte[] destBuffer = new byte[count]; while (positionInBuffer < count) { byte[] data = new byte[0]; if (Position < StaticDataLength) { // Read a chunk from non-dynamic area, next iteration will read dynamic data int maxReadLength = (int)(StaticDataLength - Position); int length = bytesRemaining > maxReadLength ? maxReadLength : bytesRemaining; data = InternalRead(length); } else { // Lookup block allocation table for real data offset var targetVirtualOffset = (ulong)(Position - StaticDataLength); ulong blockNumber = XvdMath.OffsetToBlockNumber(targetVirtualOffset); long inBlockOffset = (long)XvdMath.InBlockOffset(targetVirtualOffset); int maxReadLength = (int)(XvdFile.BLOCK_SIZE - inBlockOffset); int length = bytesRemaining > maxReadLength ? maxReadLength : bytesRemaining; var targetPage = _xvdFile.ReadBat(blockNumber); if (targetPage == XvdFile.INVALID_SECTOR) { data = new byte[length]; // Advance stream position cause we are not actually reading data Position += length; } else { long targetPhysicalOffset = DynamicBaseOffset + (long)XvdMath.PageNumberToOffset(targetPage) + inBlockOffset; data = InternalReadAbsolute(targetPhysicalOffset, length); } } Array.Copy(data, 0, destBuffer, positionInBuffer, data.Length); positionInBuffer += data.Length; bytesRemaining -= data.Length; } return(destBuffer); }