Mercurial > vba-linux
diff src/win32/7zip/7z/CPP/7zip/Archive/Rar/RarIn.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Archive/Rar/RarIn.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,513 @@ 1.4 +// Archive/RarIn.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +#include "Common/StringConvert.h" 1.9 +#include "Common/UTFConvert.h" 1.10 + 1.11 +#include "RarIn.h" 1.12 +#include "../../Common/LimitedStreams.h" 1.13 +#include "../../Common/StreamUtils.h" 1.14 + 1.15 +#include "../Common/FindSignature.h" 1.16 + 1.17 +extern "C" 1.18 +{ 1.19 + #include "../../../../C/7zCrc.h" 1.20 +} 1.21 + 1.22 +namespace NArchive { 1.23 +namespace NRar { 1.24 + 1.25 +void CInArchive::ThrowExceptionWithCode( 1.26 + CInArchiveException::CCauseType cause) 1.27 +{ 1.28 + throw CInArchiveException(cause); 1.29 +} 1.30 + 1.31 +HRESULT CInArchive::Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit) 1.32 +{ 1.33 + try 1.34 + { 1.35 + Close(); 1.36 + HRESULT res = Open2(inStream, searchHeaderSizeLimit); 1.37 + if (res == S_OK) 1.38 + return res; 1.39 + Close(); 1.40 + return res; 1.41 + } 1.42 + catch(...) { Close(); throw; } 1.43 +} 1.44 + 1.45 +void CInArchive::Close() 1.46 +{ 1.47 + m_Stream.Release(); 1.48 +} 1.49 + 1.50 + 1.51 +static inline bool TestMarkerCandidate(const void *aTestBytes) 1.52 +{ 1.53 + for (UInt32 i = 0; i < NHeader::kMarkerSize; i++) 1.54 + if (((const Byte *)aTestBytes)[i] != NHeader::kMarker[i]) 1.55 + return false; 1.56 + return true; 1.57 +} 1.58 + 1.59 +HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit) 1.60 +{ 1.61 + RINOK(FindSignatureInStream(stream, 1.62 + NHeader::kMarker, NHeader::kMarkerSize, 1.63 + searchHeaderSizeLimit, m_ArchiveStartPosition)); 1.64 + m_Stream = stream; 1.65 + m_Position = m_ArchiveStartPosition + NHeader::kMarkerSize; 1.66 + return m_Stream->Seek(m_Position, STREAM_SEEK_SET, NULL); 1.67 +} 1.68 + 1.69 +void CInArchive::ThrowUnexpectedEndOfArchiveException() 1.70 +{ 1.71 + ThrowExceptionWithCode(CInArchiveException::kUnexpectedEndOfArchive); 1.72 +} 1.73 + 1.74 +bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size) 1.75 +{ 1.76 + if (m_CryptoMode) 1.77 + { 1.78 + const Byte *bufData = (const Byte *)m_DecryptedData; 1.79 + UInt32 bufSize = m_DecryptedDataSize; 1.80 + UInt32 i; 1.81 + for (i = 0; i < size && m_CryptoPos < bufSize; i++) 1.82 + ((Byte *)data)[i] = bufData[m_CryptoPos++]; 1.83 + return (i == size); 1.84 + } 1.85 + return (ReadStream_FALSE(m_Stream, data, size) == S_OK); 1.86 +} 1.87 + 1.88 +void CInArchive::ReadBytesAndTestResult(void *data, UInt32 size) 1.89 +{ 1.90 + if(!ReadBytesAndTestSize(data,size)) 1.91 + ThrowUnexpectedEndOfArchiveException(); 1.92 +} 1.93 + 1.94 +HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize) 1.95 +{ 1.96 + size_t realProcessedSize = size; 1.97 + HRESULT result = ReadStream(m_Stream, data, &realProcessedSize); 1.98 + if (processedSize != NULL) 1.99 + *processedSize = (UInt32)realProcessedSize; 1.100 + AddToSeekValue(realProcessedSize); 1.101 + return result; 1.102 +} 1.103 + 1.104 +static UInt32 CrcUpdateUInt16(UInt32 crc, UInt16 v) 1.105 +{ 1.106 + crc = CRC_UPDATE_BYTE(crc, (Byte)(v & 0xFF)); 1.107 + crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 8) & 0xFF)); 1.108 + return crc; 1.109 +} 1.110 + 1.111 +static UInt32 CrcUpdateUInt32(UInt32 crc, UInt32 v) 1.112 +{ 1.113 + crc = CRC_UPDATE_BYTE(crc, (Byte)(v & 0xFF)); 1.114 + crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 8) & 0xFF)); 1.115 + crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 16) & 0xFF)); 1.116 + crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 24) & 0xFF)); 1.117 + return crc; 1.118 +} 1.119 + 1.120 + 1.121 +HRESULT CInArchive::Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit) 1.122 +{ 1.123 + m_CryptoMode = false; 1.124 + RINOK(stream->Seek(0, STREAM_SEEK_SET, &m_StreamStartPosition)); 1.125 + m_Position = m_StreamStartPosition; 1.126 + 1.127 + RINOK(FindAndReadMarker(stream, searchHeaderSizeLimit)); 1.128 + 1.129 + Byte buf[NHeader::NArchive::kArchiveHeaderSize]; 1.130 + UInt32 processedSize; 1.131 + ReadBytes(buf, sizeof(buf), &processedSize); 1.132 + if (processedSize != sizeof(buf)) 1.133 + return S_FALSE; 1.134 + m_CurData = buf; 1.135 + m_CurPos = 0; 1.136 + m_PosLimit = sizeof(buf); 1.137 + 1.138 + m_ArchiveHeader.CRC = ReadUInt16(); 1.139 + m_ArchiveHeader.Type = ReadByte(); 1.140 + m_ArchiveHeader.Flags = ReadUInt16(); 1.141 + m_ArchiveHeader.Size = ReadUInt16(); 1.142 + m_ArchiveHeader.Reserved1 = ReadUInt16(); 1.143 + m_ArchiveHeader.Reserved2 = ReadUInt32(); 1.144 + m_ArchiveHeader.EncryptVersion = 0; 1.145 + 1.146 + UInt32 crc = CRC_INIT_VAL; 1.147 + crc = CRC_UPDATE_BYTE(crc, m_ArchiveHeader.Type); 1.148 + crc = CrcUpdateUInt16(crc, m_ArchiveHeader.Flags); 1.149 + crc = CrcUpdateUInt16(crc, m_ArchiveHeader.Size); 1.150 + crc = CrcUpdateUInt16(crc, m_ArchiveHeader.Reserved1); 1.151 + crc = CrcUpdateUInt32(crc, m_ArchiveHeader.Reserved2); 1.152 + 1.153 + if (m_ArchiveHeader.IsThereEncryptVer() && m_ArchiveHeader.Size > NHeader::NArchive::kArchiveHeaderSize) 1.154 + { 1.155 + ReadBytes(&m_ArchiveHeader.EncryptVersion, 1, &processedSize); 1.156 + if (processedSize != 1) 1.157 + return S_FALSE; 1.158 + crc = CRC_UPDATE_BYTE(crc, m_ArchiveHeader.EncryptVersion); 1.159 + } 1.160 + 1.161 + if(m_ArchiveHeader.CRC != (CRC_GET_DIGEST(crc) & 0xFFFF)) 1.162 + ThrowExceptionWithCode(CInArchiveException::kArchiveHeaderCRCError); 1.163 + if (m_ArchiveHeader.Type != NHeader::NBlockType::kArchiveHeader) 1.164 + return S_FALSE; 1.165 + m_ArchiveCommentPosition = m_Position; 1.166 + m_SeekOnArchiveComment = true; 1.167 + return S_OK; 1.168 +} 1.169 + 1.170 +void CInArchive::SkipArchiveComment() 1.171 +{ 1.172 + if (!m_SeekOnArchiveComment) 1.173 + return; 1.174 + AddToSeekValue(m_ArchiveHeader.Size - m_ArchiveHeader.GetBaseSize()); 1.175 + m_SeekOnArchiveComment = false; 1.176 +} 1.177 + 1.178 +void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const 1.179 +{ 1.180 + archiveInfo.StartPosition = m_ArchiveStartPosition; 1.181 + archiveInfo.Flags = m_ArchiveHeader.Flags; 1.182 + archiveInfo.CommentPosition = m_ArchiveCommentPosition; 1.183 + archiveInfo.CommentSize = (UInt16)(m_ArchiveHeader.Size - NHeader::NArchive::kArchiveHeaderSize); 1.184 +} 1.185 + 1.186 +static void DecodeUnicodeFileName(const char *name, const Byte *encName, 1.187 + int encSize, wchar_t *unicodeName, int maxDecSize) 1.188 +{ 1.189 + int encPos = 0; 1.190 + int decPos = 0; 1.191 + int flagBits = 0; 1.192 + Byte flags = 0; 1.193 + Byte highByte = encName[encPos++]; 1.194 + while (encPos < encSize && decPos < maxDecSize) 1.195 + { 1.196 + if (flagBits == 0) 1.197 + { 1.198 + flags = encName[encPos++]; 1.199 + flagBits = 8; 1.200 + } 1.201 + switch(flags >> 6) 1.202 + { 1.203 + case 0: 1.204 + unicodeName[decPos++] = encName[encPos++]; 1.205 + break; 1.206 + case 1: 1.207 + unicodeName[decPos++] = (wchar_t)(encName[encPos++] + (highByte << 8)); 1.208 + break; 1.209 + case 2: 1.210 + unicodeName[decPos++] = (wchar_t)(encName[encPos] + (encName[encPos + 1] << 8)); 1.211 + encPos += 2; 1.212 + break; 1.213 + case 3: 1.214 + { 1.215 + int length = encName[encPos++]; 1.216 + if (length & 0x80) 1.217 + { 1.218 + Byte correction = encName[encPos++]; 1.219 + for (length = (length & 0x7f) + 2; 1.220 + length > 0 && decPos < maxDecSize; length--, decPos++) 1.221 + unicodeName[decPos] = (wchar_t)(((name[decPos] + correction) & 0xff) + (highByte << 8)); 1.222 + } 1.223 + else 1.224 + for (length += 2; length > 0 && decPos < maxDecSize; length--, decPos++) 1.225 + unicodeName[decPos] = name[decPos]; 1.226 + } 1.227 + break; 1.228 + } 1.229 + flags <<= 2; 1.230 + flagBits -= 2; 1.231 + } 1.232 + unicodeName[decPos < maxDecSize ? decPos : maxDecSize - 1] = 0; 1.233 +} 1.234 + 1.235 +void CInArchive::ReadName(CItemEx &item, int nameSize) 1.236 +{ 1.237 + item.UnicodeName.Empty(); 1.238 + if (nameSize > 0) 1.239 + { 1.240 + m_NameBuffer.EnsureCapacity(nameSize + 1); 1.241 + char *buffer = (char *)m_NameBuffer; 1.242 + 1.243 + for (int i = 0; i < nameSize; i++) 1.244 + buffer[i] = ReadByte(); 1.245 + 1.246 + int mainLen; 1.247 + for (mainLen = 0; mainLen < nameSize; mainLen++) 1.248 + if (buffer[mainLen] == '\0') 1.249 + break; 1.250 + buffer[mainLen] = '\0'; 1.251 + item.Name = buffer; 1.252 + 1.253 + if(item.HasUnicodeName()) 1.254 + { 1.255 + if(mainLen < nameSize) 1.256 + { 1.257 + int unicodeNameSizeMax = MyMin(nameSize, (0x400)); 1.258 + _unicodeNameBuffer.EnsureCapacity(unicodeNameSizeMax + 1); 1.259 + DecodeUnicodeFileName(buffer, (const Byte *)buffer + mainLen + 1, 1.260 + nameSize - (mainLen + 1), _unicodeNameBuffer, unicodeNameSizeMax); 1.261 + item.UnicodeName = _unicodeNameBuffer; 1.262 + } 1.263 + else if (!ConvertUTF8ToUnicode(item.Name, item.UnicodeName)) 1.264 + item.UnicodeName.Empty(); 1.265 + } 1.266 + } 1.267 + else 1.268 + item.Name.Empty(); 1.269 +} 1.270 + 1.271 +Byte CInArchive::ReadByte() 1.272 +{ 1.273 + if (m_CurPos >= m_PosLimit) 1.274 + throw CInArchiveException(CInArchiveException::kIncorrectArchive); 1.275 + return m_CurData[m_CurPos++]; 1.276 +} 1.277 + 1.278 +UInt16 CInArchive::ReadUInt16() 1.279 +{ 1.280 + UInt16 value = 0; 1.281 + for (int i = 0; i < 2; i++) 1.282 + { 1.283 + Byte b = ReadByte(); 1.284 + value |= (UInt16(b) << (8 * i)); 1.285 + } 1.286 + return value; 1.287 +} 1.288 + 1.289 +UInt32 CInArchive::ReadUInt32() 1.290 +{ 1.291 + UInt32 value = 0; 1.292 + for (int i = 0; i < 4; i++) 1.293 + { 1.294 + Byte b = ReadByte(); 1.295 + value |= (UInt32(b) << (8 * i)); 1.296 + } 1.297 + return value; 1.298 +} 1.299 + 1.300 +void CInArchive::ReadTime(Byte mask, CRarTime &rarTime) 1.301 +{ 1.302 + rarTime.LowSecond = (Byte)(((mask & 4) != 0) ? 1 : 0); 1.303 + int numDigits = (mask & 3); 1.304 + rarTime.SubTime[0] = rarTime.SubTime[1] = rarTime.SubTime[2] = 0; 1.305 + for (int i = 0; i < numDigits; i++) 1.306 + rarTime.SubTime[3 - numDigits + i] = ReadByte(); 1.307 +} 1.308 + 1.309 +void CInArchive::ReadHeaderReal(CItemEx &item) 1.310 +{ 1.311 + item.Flags = m_BlockHeader.Flags; 1.312 + item.PackSize = ReadUInt32(); 1.313 + item.Size = ReadUInt32(); 1.314 + item.HostOS = ReadByte(); 1.315 + item.FileCRC = ReadUInt32(); 1.316 + item.MTime.DosTime = ReadUInt32(); 1.317 + item.UnPackVersion = ReadByte(); 1.318 + item.Method = ReadByte(); 1.319 + int nameSize = ReadUInt16(); 1.320 + item.Attrib = ReadUInt32(); 1.321 + 1.322 + item.MTime.LowSecond = 0; 1.323 + item.MTime.SubTime[0] = 1.324 + item.MTime.SubTime[1] = 1.325 + item.MTime.SubTime[2] = 0; 1.326 + 1.327 + if((item.Flags & NHeader::NFile::kSize64Bits) != 0) 1.328 + { 1.329 + item.PackSize |= ((UInt64)ReadUInt32() << 32); 1.330 + item.Size |= ((UInt64)ReadUInt32() << 32); 1.331 + } 1.332 + 1.333 + ReadName(item, nameSize); 1.334 + 1.335 + if (item.HasSalt()) 1.336 + for (int i = 0; i < sizeof(item.Salt); i++) 1.337 + item.Salt[i] = ReadByte(); 1.338 + 1.339 + // some rar archives have HasExtTime flag without field. 1.340 + if (m_CurPos < m_PosLimit && item.HasExtTime()) 1.341 + { 1.342 + Byte accessMask = (Byte)(ReadByte() >> 4); 1.343 + Byte b = ReadByte(); 1.344 + Byte modifMask = (Byte)(b >> 4); 1.345 + Byte createMask = (Byte)(b & 0xF); 1.346 + if ((modifMask & 8) != 0) 1.347 + ReadTime(modifMask, item.MTime); 1.348 + item.CTimeDefined = ((createMask & 8) != 0); 1.349 + if (item.CTimeDefined) 1.350 + { 1.351 + item.CTime.DosTime = ReadUInt32(); 1.352 + ReadTime(createMask, item.CTime); 1.353 + } 1.354 + item.ATimeDefined = ((accessMask & 8) != 0); 1.355 + if (item.ATimeDefined) 1.356 + { 1.357 + item.ATime.DosTime = ReadUInt32(); 1.358 + ReadTime(accessMask, item.ATime); 1.359 + } 1.360 + } 1.361 + 1.362 + UInt16 fileHeaderWithNameSize = (UInt16)m_CurPos; 1.363 + 1.364 + item.Position = m_Position; 1.365 + item.MainPartSize = fileHeaderWithNameSize; 1.366 + item.CommentSize = (UInt16)(m_BlockHeader.HeadSize - fileHeaderWithNameSize); 1.367 + 1.368 + if (m_CryptoMode) 1.369 + item.AlignSize = (UInt16)((16 - ((m_BlockHeader.HeadSize) & 0xF)) & 0xF); 1.370 + else 1.371 + item.AlignSize = 0; 1.372 + AddToSeekValue(m_BlockHeader.HeadSize); 1.373 +} 1.374 + 1.375 +void CInArchive::AddToSeekValue(UInt64 addValue) 1.376 +{ 1.377 + m_Position += addValue; 1.378 +} 1.379 + 1.380 +HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword) 1.381 +{ 1.382 + if (m_SeekOnArchiveComment) 1.383 + SkipArchiveComment(); 1.384 + for (;;) 1.385 + { 1.386 + if(!SeekInArchive(m_Position)) 1.387 + return S_FALSE; 1.388 + if (!m_CryptoMode && (m_ArchiveHeader.Flags & 1.389 + NHeader::NArchive::kBlockHeadersAreEncrypted) != 0) 1.390 + { 1.391 + m_CryptoMode = false; 1.392 + if (getTextPassword == 0) 1.393 + return S_FALSE; 1.394 + if(!SeekInArchive(m_Position)) 1.395 + return S_FALSE; 1.396 + if (!m_RarAES) 1.397 + { 1.398 + m_RarAESSpec = new NCrypto::NRar29::CDecoder; 1.399 + m_RarAES = m_RarAESSpec; 1.400 + } 1.401 + m_RarAESSpec->SetRar350Mode(m_ArchiveHeader.IsEncryptOld()); 1.402 + 1.403 + // Salt 1.404 + const UInt32 kSaltSize = 8; 1.405 + Byte salt[kSaltSize]; 1.406 + if(!ReadBytesAndTestSize(salt, kSaltSize)) 1.407 + return S_FALSE; 1.408 + m_Position += kSaltSize; 1.409 + RINOK(m_RarAESSpec->SetDecoderProperties2(salt, kSaltSize)) 1.410 + // Password 1.411 + CMyComBSTR password; 1.412 + RINOK(getTextPassword->CryptoGetTextPassword(&password)) 1.413 + UString unicodePassword(password); 1.414 + 1.415 + CByteBuffer buffer; 1.416 + const UInt32 sizeInBytes = unicodePassword.Length() * 2; 1.417 + buffer.SetCapacity(sizeInBytes); 1.418 + for (int i = 0; i < unicodePassword.Length(); i++) 1.419 + { 1.420 + wchar_t c = unicodePassword[i]; 1.421 + ((Byte *)buffer)[i * 2] = (Byte)c; 1.422 + ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); 1.423 + } 1.424 + 1.425 + RINOK(m_RarAESSpec->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); 1.426 + 1.427 + const UInt32 kDecryptedBufferSize = (1 << 12); 1.428 + if (m_DecryptedData.GetCapacity() == 0) 1.429 + { 1.430 + m_DecryptedData.SetCapacity(kDecryptedBufferSize); 1.431 + } 1.432 + RINOK(m_RarAES->Init()); 1.433 + size_t decryptedDataSizeT = kDecryptedBufferSize; 1.434 + RINOK(ReadStream(m_Stream, (Byte *)m_DecryptedData, &decryptedDataSizeT)); 1.435 + m_DecryptedDataSize = (UInt32)decryptedDataSizeT; 1.436 + m_DecryptedDataSize = m_RarAES->Filter((Byte *)m_DecryptedData, m_DecryptedDataSize); 1.437 + 1.438 + m_CryptoMode = true; 1.439 + m_CryptoPos = 0; 1.440 + } 1.441 + 1.442 + m_FileHeaderData.EnsureCapacity(7); 1.443 + if(!ReadBytesAndTestSize((Byte *)m_FileHeaderData, 7)) 1.444 + return S_FALSE; 1.445 + 1.446 + m_CurData = (Byte *)m_FileHeaderData; 1.447 + m_CurPos = 0; 1.448 + m_PosLimit = 7; 1.449 + m_BlockHeader.CRC = ReadUInt16(); 1.450 + m_BlockHeader.Type = ReadByte(); 1.451 + m_BlockHeader.Flags = ReadUInt16(); 1.452 + m_BlockHeader.HeadSize = ReadUInt16(); 1.453 + 1.454 + if (m_BlockHeader.HeadSize < 7) 1.455 + ThrowExceptionWithCode(CInArchiveException::kIncorrectArchive); 1.456 + 1.457 + if (m_BlockHeader.Type == NHeader::NBlockType::kEndOfArchive) 1.458 + return S_FALSE; 1.459 + 1.460 + if (m_BlockHeader.Type == NHeader::NBlockType::kFileHeader) 1.461 + { 1.462 + m_FileHeaderData.EnsureCapacity(m_BlockHeader.HeadSize); 1.463 + m_CurData = (Byte *)m_FileHeaderData; 1.464 + m_PosLimit = m_BlockHeader.HeadSize; 1.465 + ReadBytesAndTestResult(m_CurData + m_CurPos, m_BlockHeader.HeadSize - 7); 1.466 + ReadHeaderReal(item); 1.467 + if ((CrcCalc(m_CurData + 2, 1.468 + m_BlockHeader.HeadSize - item.CommentSize - 2) & 0xFFFF) != m_BlockHeader.CRC) 1.469 + ThrowExceptionWithCode(CInArchiveException::kFileHeaderCRCError); 1.470 + 1.471 + FinishCryptoBlock(); 1.472 + m_CryptoMode = false; 1.473 + SeekInArchive(m_Position); // Move Position to compressed Data; 1.474 + AddToSeekValue(item.PackSize); // m_Position points to next header; 1.475 + return S_OK; 1.476 + } 1.477 + if (m_CryptoMode && m_BlockHeader.HeadSize > (1 << 12)) 1.478 + return E_FAIL; // it's for bad passwords 1.479 + if ((m_BlockHeader.Flags & NHeader::NBlock::kLongBlock) != 0) 1.480 + { 1.481 + m_FileHeaderData.EnsureCapacity(7 + 4); 1.482 + m_CurData = (Byte *)m_FileHeaderData; 1.483 + ReadBytesAndTestResult(m_CurData + m_CurPos, 4); // test it 1.484 + m_PosLimit = 7 + 4; 1.485 + UInt32 dataSize = ReadUInt32(); 1.486 + AddToSeekValue(dataSize); 1.487 + if (m_CryptoMode && dataSize > (1 << 27)) 1.488 + return E_FAIL; // it's for bad passwords 1.489 + m_CryptoPos = m_BlockHeader.HeadSize; 1.490 + } 1.491 + else 1.492 + m_CryptoPos = 0; 1.493 + AddToSeekValue(m_BlockHeader.HeadSize); 1.494 + FinishCryptoBlock(); 1.495 + m_CryptoMode = false; 1.496 + } 1.497 +} 1.498 + 1.499 +bool CInArchive::SeekInArchive(UInt64 position) 1.500 +{ 1.501 + UInt64 newPosition; 1.502 + m_Stream->Seek(position, STREAM_SEEK_SET, &newPosition); 1.503 + return newPosition == position; 1.504 +} 1.505 + 1.506 +ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size) 1.507 +{ 1.508 + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; 1.509 + CMyComPtr<ISequentialInStream> inStream(streamSpec); 1.510 + SeekInArchive(position); 1.511 + streamSpec->SetStream(m_Stream); 1.512 + streamSpec->Init(size); 1.513 + return inStream.Detach(); 1.514 +} 1.515 + 1.516 +}}