1 // 7zIn.cpp |
|
2 |
|
3 #include "StdAfx.h" |
|
4 |
|
5 #include "7zIn.h" |
|
6 #include "7zDecode.h" |
|
7 #include "../../Common/StreamObjects.h" |
|
8 #include "../../Common/StreamUtils.h" |
|
9 extern "C" |
|
10 { |
|
11 #include "../../../../C/7zCrc.h" |
|
12 } |
|
13 |
|
14 // define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader |
|
15 #ifndef _SFX |
|
16 #define FORMAT_7Z_RECOVERY |
|
17 #endif |
|
18 |
|
19 namespace NArchive { |
|
20 namespace N7z { |
|
21 |
|
22 class CInArchiveException {}; |
|
23 |
|
24 static void ThrowException() { throw CInArchiveException(); } |
|
25 static inline void ThrowEndOfData() { ThrowException(); } |
|
26 static inline void ThrowUnsupported() { ThrowException(); } |
|
27 static inline void ThrowIncorrect() { ThrowException(); } |
|
28 static inline void ThrowUnsupportedVersion() { ThrowException(); } |
|
29 |
|
30 /* |
|
31 class CInArchiveException |
|
32 { |
|
33 public: |
|
34 enum CCauseType |
|
35 { |
|
36 kUnsupportedVersion = 0, |
|
37 kUnsupported, |
|
38 kIncorrect, |
|
39 kEndOfData, |
|
40 } Cause; |
|
41 CInArchiveException(CCauseType cause): Cause(cause) {}; |
|
42 }; |
|
43 |
|
44 static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); } |
|
45 static void ThrowEndOfData() { ThrowException(CInArchiveException::kEndOfData); } |
|
46 static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); } |
|
47 static void ThrowIncorrect() { ThrowException(CInArchiveException::kIncorrect); } |
|
48 static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); } |
|
49 */ |
|
50 |
|
51 class CStreamSwitch |
|
52 { |
|
53 CInArchive *_archive; |
|
54 bool _needRemove; |
|
55 public: |
|
56 CStreamSwitch(): _needRemove(false) {} |
|
57 ~CStreamSwitch() { Remove(); } |
|
58 void Remove(); |
|
59 void Set(CInArchive *archive, const Byte *data, size_t size); |
|
60 void Set(CInArchive *archive, const CByteBuffer &byteBuffer); |
|
61 void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector); |
|
62 }; |
|
63 |
|
64 void CStreamSwitch::Remove() |
|
65 { |
|
66 if (_needRemove) |
|
67 { |
|
68 _archive->DeleteByteStream(); |
|
69 _needRemove = false; |
|
70 } |
|
71 } |
|
72 |
|
73 void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size) |
|
74 { |
|
75 Remove(); |
|
76 _archive = archive; |
|
77 _archive->AddByteStream(data, size); |
|
78 _needRemove = true; |
|
79 } |
|
80 |
|
81 void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer) |
|
82 { |
|
83 Set(archive, byteBuffer, byteBuffer.GetCapacity()); |
|
84 } |
|
85 |
|
86 void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector) |
|
87 { |
|
88 Remove(); |
|
89 Byte external = archive->ReadByte(); |
|
90 if (external != 0) |
|
91 { |
|
92 int dataIndex = (int)archive->ReadNum(); |
|
93 if (dataIndex < 0 || dataIndex >= dataVector->Size()) |
|
94 ThrowIncorrect(); |
|
95 Set(archive, (*dataVector)[dataIndex]); |
|
96 } |
|
97 } |
|
98 |
|
99 #if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) |
|
100 #define SZ_LITTLE_ENDIAN_UNALIGN |
|
101 #endif |
|
102 |
|
103 #ifdef SZ_LITTLE_ENDIAN_UNALIGN |
|
104 static inline UInt16 GetUInt16FromMem(const Byte *p) { return *(const UInt16 *)p; } |
|
105 static inline UInt32 GetUInt32FromMem(const Byte *p) { return *(const UInt32 *)p; } |
|
106 static inline UInt64 GetUInt64FromMem(const Byte *p) { return *(const UInt64 *)p; } |
|
107 #else |
|
108 static inline UInt16 GetUInt16FromMem(const Byte *p) { return p[0] | ((UInt16)p[1] << 8); } |
|
109 static inline UInt32 GetUInt32FromMem(const Byte *p) { return p[0] | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16) | ((UInt32)p[3] << 24); } |
|
110 static inline UInt64 GetUInt64FromMem(const Byte *p) { return GetUInt32FromMem(p) | ((UInt64)GetUInt32FromMem(p + 4) << 32); } |
|
111 #endif |
|
112 |
|
113 Byte CInByte2::ReadByte() |
|
114 { |
|
115 if (_pos >= _size) |
|
116 ThrowEndOfData(); |
|
117 return _buffer[_pos++]; |
|
118 } |
|
119 |
|
120 void CInByte2::ReadBytes(Byte *data, size_t size) |
|
121 { |
|
122 if (size > _size - _pos) |
|
123 ThrowEndOfData(); |
|
124 for (size_t i = 0; i < size; i++) |
|
125 data[i] = _buffer[_pos++]; |
|
126 } |
|
127 |
|
128 void CInByte2::SkeepData(UInt64 size) |
|
129 { |
|
130 if (size > _size - _pos) |
|
131 ThrowEndOfData(); |
|
132 } |
|
133 |
|
134 void CInByte2::SkeepData() |
|
135 { |
|
136 SkeepData(ReadNumber()); |
|
137 } |
|
138 |
|
139 UInt64 CInByte2::ReadNumber() |
|
140 { |
|
141 if (_pos >= _size) |
|
142 ThrowEndOfData(); |
|
143 Byte firstByte = _buffer[_pos++]; |
|
144 Byte mask = 0x80; |
|
145 UInt64 value = 0; |
|
146 for (int i = 0; i < 8; i++) |
|
147 { |
|
148 if ((firstByte & mask) == 0) |
|
149 { |
|
150 UInt64 highPart = firstByte & (mask - 1); |
|
151 value += (highPart << (i * 8)); |
|
152 return value; |
|
153 } |
|
154 if (_pos >= _size) |
|
155 ThrowEndOfData(); |
|
156 value |= ((UInt64)_buffer[_pos++] << (8 * i)); |
|
157 mask >>= 1; |
|
158 } |
|
159 return value; |
|
160 } |
|
161 |
|
162 CNum CInByte2::ReadNum() |
|
163 { |
|
164 UInt64 value = ReadNumber(); |
|
165 if (value > kNumMax) |
|
166 ThrowUnsupported(); |
|
167 return (CNum)value; |
|
168 } |
|
169 |
|
170 UInt32 CInByte2::ReadUInt32() |
|
171 { |
|
172 if (_pos + 4 > _size) |
|
173 ThrowEndOfData(); |
|
174 UInt32 res = GetUInt32FromMem(_buffer + _pos); |
|
175 _pos += 4; |
|
176 return res; |
|
177 } |
|
178 |
|
179 UInt64 CInByte2::ReadUInt64() |
|
180 { |
|
181 if (_pos + 8 > _size) |
|
182 ThrowEndOfData(); |
|
183 UInt64 res = GetUInt64FromMem(_buffer + _pos); |
|
184 _pos += 8; |
|
185 return res; |
|
186 } |
|
187 |
|
188 void CInByte2::ReadString(UString &s) |
|
189 { |
|
190 const Byte *buf = _buffer + _pos; |
|
191 size_t rem = (_size - _pos) / 2 * 2; |
|
192 { |
|
193 size_t i; |
|
194 for (i = 0; i < rem; i += 2) |
|
195 if (buf[i] == 0 && buf[i + 1] == 0) |
|
196 break; |
|
197 if (i == rem) |
|
198 ThrowEndOfData(); |
|
199 rem = i; |
|
200 } |
|
201 int len = (int)(rem / 2); |
|
202 if (len < 0 || (size_t)len * 2 != rem) |
|
203 ThrowUnsupported(); |
|
204 wchar_t *p = s.GetBuffer(len); |
|
205 int i; |
|
206 for (i = 0; i < len; i++, buf += 2) |
|
207 p[i] = (wchar_t)GetUInt16FromMem(buf); |
|
208 p[i] = 0; |
|
209 s.ReleaseBuffer(len); |
|
210 _pos += rem + 2; |
|
211 } |
|
212 |
|
213 static inline bool TestSignatureCandidate(const Byte *p) |
|
214 { |
|
215 for (int i = 0; i < kSignatureSize; i++) |
|
216 if (p[i] != kSignature[i]) |
|
217 return false; |
|
218 return (p[0x1A] == 0 && p[0x1B] == 0); |
|
219 } |
|
220 |
|
221 HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit) |
|
222 { |
|
223 UInt32 processedSize; |
|
224 RINOK(ReadStream(stream, _header, kHeaderSize, &processedSize)); |
|
225 if (processedSize != kHeaderSize) |
|
226 return S_FALSE; |
|
227 if (TestSignatureCandidate(_header)) |
|
228 return S_OK; |
|
229 |
|
230 CByteBuffer byteBuffer; |
|
231 const UInt32 kBufferSize = (1 << 16); |
|
232 byteBuffer.SetCapacity(kBufferSize); |
|
233 Byte *buffer = byteBuffer; |
|
234 UInt32 numPrevBytes = kHeaderSize - 1; |
|
235 memcpy(buffer, _header + 1, numPrevBytes); |
|
236 UInt64 curTestPos = _arhiveBeginStreamPosition + 1; |
|
237 for (;;) |
|
238 { |
|
239 if (searchHeaderSizeLimit != NULL) |
|
240 if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit) |
|
241 break; |
|
242 UInt32 numReadBytes = kBufferSize - numPrevBytes; |
|
243 RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); |
|
244 UInt32 numBytesInBuffer = numPrevBytes + processedSize; |
|
245 if (numBytesInBuffer < kHeaderSize) |
|
246 break; |
|
247 UInt32 numTests = numBytesInBuffer - kHeaderSize + 1; |
|
248 for(UInt32 pos = 0; pos < numTests; pos++, curTestPos++) |
|
249 { |
|
250 if (TestSignatureCandidate(buffer + pos)) |
|
251 { |
|
252 memcpy(_header, buffer + pos, kHeaderSize); |
|
253 _arhiveBeginStreamPosition = curTestPos; |
|
254 return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL); |
|
255 } |
|
256 } |
|
257 numPrevBytes = numBytesInBuffer - numTests; |
|
258 memmove(buffer, buffer + numTests, numPrevBytes); |
|
259 } |
|
260 return S_FALSE; |
|
261 } |
|
262 |
|
263 // S_FALSE means that file is not archive |
|
264 HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) |
|
265 { |
|
266 Close(); |
|
267 RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) |
|
268 RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); |
|
269 _stream = stream; |
|
270 return S_OK; |
|
271 } |
|
272 |
|
273 void CInArchive::Close() |
|
274 { |
|
275 _stream.Release(); |
|
276 } |
|
277 |
|
278 void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) |
|
279 { |
|
280 for (;;) |
|
281 { |
|
282 if (ReadID() == NID::kEnd) |
|
283 break; |
|
284 SkeepData(); |
|
285 } |
|
286 } |
|
287 |
|
288 void CInArchive::GetNextFolderItem(CFolder &folder) |
|
289 { |
|
290 CNum numCoders = ReadNum(); |
|
291 |
|
292 folder.Coders.Clear(); |
|
293 folder.Coders.Reserve((int)numCoders); |
|
294 CNum numInStreams = 0; |
|
295 CNum numOutStreams = 0; |
|
296 CNum i; |
|
297 for (i = 0; i < numCoders; i++) |
|
298 { |
|
299 folder.Coders.Add(CCoderInfo()); |
|
300 CCoderInfo &coder = folder.Coders.Back(); |
|
301 |
|
302 { |
|
303 Byte mainByte = ReadByte(); |
|
304 int idSize = (mainByte & 0xF); |
|
305 Byte longID[15]; |
|
306 ReadBytes(longID, idSize); |
|
307 if (idSize > 8) |
|
308 ThrowUnsupported(); |
|
309 UInt64 id = 0; |
|
310 for (int j = 0; j < idSize; j++) |
|
311 id |= (UInt64)longID[idSize - 1 - j] << (8 * j); |
|
312 coder.MethodID = id; |
|
313 |
|
314 if ((mainByte & 0x10) != 0) |
|
315 { |
|
316 coder.NumInStreams = ReadNum(); |
|
317 coder.NumOutStreams = ReadNum(); |
|
318 } |
|
319 else |
|
320 { |
|
321 coder.NumInStreams = 1; |
|
322 coder.NumOutStreams = 1; |
|
323 } |
|
324 if ((mainByte & 0x20) != 0) |
|
325 { |
|
326 CNum propertiesSize = ReadNum(); |
|
327 coder.Properties.SetCapacity((size_t)propertiesSize); |
|
328 ReadBytes((Byte *)coder.Properties, (size_t)propertiesSize); |
|
329 } |
|
330 if ((mainByte & 0x80) != 0) |
|
331 ThrowUnsupported(); |
|
332 } |
|
333 numInStreams += coder.NumInStreams; |
|
334 numOutStreams += coder.NumOutStreams; |
|
335 } |
|
336 |
|
337 CNum numBindPairs; |
|
338 numBindPairs = numOutStreams - 1; |
|
339 folder.BindPairs.Clear(); |
|
340 folder.BindPairs.Reserve(numBindPairs); |
|
341 for (i = 0; i < numBindPairs; i++) |
|
342 { |
|
343 CBindPair bindPair; |
|
344 bindPair.InIndex = ReadNum(); |
|
345 bindPair.OutIndex = ReadNum(); |
|
346 folder.BindPairs.Add(bindPair); |
|
347 } |
|
348 |
|
349 CNum numPackedStreams = numInStreams - numBindPairs; |
|
350 folder.PackStreams.Reserve(numPackedStreams); |
|
351 if (numPackedStreams == 1) |
|
352 { |
|
353 for (CNum j = 0; j < numInStreams; j++) |
|
354 if (folder.FindBindPairForInStream(j) < 0) |
|
355 { |
|
356 folder.PackStreams.Add(j); |
|
357 break; |
|
358 } |
|
359 } |
|
360 else |
|
361 for(i = 0; i < numPackedStreams; i++) |
|
362 folder.PackStreams.Add(ReadNum()); |
|
363 } |
|
364 |
|
365 void CInArchive::WaitAttribute(UInt64 attribute) |
|
366 { |
|
367 for (;;) |
|
368 { |
|
369 UInt64 type = ReadID(); |
|
370 if (type == attribute) |
|
371 return; |
|
372 if (type == NID::kEnd) |
|
373 ThrowIncorrect(); |
|
374 SkeepData(); |
|
375 } |
|
376 } |
|
377 |
|
378 void CInArchive::ReadHashDigests(int numItems, |
|
379 CRecordVector<bool> &digestsDefined, |
|
380 CRecordVector<UInt32> &digests) |
|
381 { |
|
382 ReadBoolVector2(numItems, digestsDefined); |
|
383 digests.Clear(); |
|
384 digests.Reserve(numItems); |
|
385 for(int i = 0; i < numItems; i++) |
|
386 { |
|
387 UInt32 crc = 0; |
|
388 if (digestsDefined[i]) |
|
389 crc = ReadUInt32(); |
|
390 digests.Add(crc); |
|
391 } |
|
392 } |
|
393 |
|
394 void CInArchive::ReadPackInfo( |
|
395 UInt64 &dataOffset, |
|
396 CRecordVector<UInt64> &packSizes, |
|
397 CRecordVector<bool> &packCRCsDefined, |
|
398 CRecordVector<UInt32> &packCRCs) |
|
399 { |
|
400 dataOffset = ReadNumber(); |
|
401 CNum numPackStreams = ReadNum(); |
|
402 |
|
403 WaitAttribute(NID::kSize); |
|
404 packSizes.Clear(); |
|
405 packSizes.Reserve(numPackStreams); |
|
406 for (CNum i = 0; i < numPackStreams; i++) |
|
407 packSizes.Add(ReadNumber()); |
|
408 |
|
409 UInt64 type; |
|
410 for (;;) |
|
411 { |
|
412 type = ReadID(); |
|
413 if (type == NID::kEnd) |
|
414 break; |
|
415 if (type == NID::kCRC) |
|
416 { |
|
417 ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); |
|
418 continue; |
|
419 } |
|
420 SkeepData(); |
|
421 } |
|
422 if (packCRCsDefined.IsEmpty()) |
|
423 { |
|
424 packCRCsDefined.Reserve(numPackStreams); |
|
425 packCRCsDefined.Clear(); |
|
426 packCRCs.Reserve(numPackStreams); |
|
427 packCRCs.Clear(); |
|
428 for(CNum i = 0; i < numPackStreams; i++) |
|
429 { |
|
430 packCRCsDefined.Add(false); |
|
431 packCRCs.Add(0); |
|
432 } |
|
433 } |
|
434 } |
|
435 |
|
436 void CInArchive::ReadUnPackInfo( |
|
437 const CObjectVector<CByteBuffer> *dataVector, |
|
438 CObjectVector<CFolder> &folders) |
|
439 { |
|
440 WaitAttribute(NID::kFolder); |
|
441 CNum numFolders = ReadNum(); |
|
442 |
|
443 { |
|
444 CStreamSwitch streamSwitch; |
|
445 streamSwitch.Set(this, dataVector); |
|
446 folders.Clear(); |
|
447 folders.Reserve(numFolders); |
|
448 for(CNum i = 0; i < numFolders; i++) |
|
449 { |
|
450 folders.Add(CFolder()); |
|
451 GetNextFolderItem(folders.Back()); |
|
452 } |
|
453 } |
|
454 |
|
455 WaitAttribute(NID::kCodersUnPackSize); |
|
456 |
|
457 CNum i; |
|
458 for (i = 0; i < numFolders; i++) |
|
459 { |
|
460 CFolder &folder = folders[i]; |
|
461 CNum numOutStreams = folder.GetNumOutStreams(); |
|
462 folder.UnPackSizes.Reserve(numOutStreams); |
|
463 for (CNum j = 0; j < numOutStreams; j++) |
|
464 folder.UnPackSizes.Add(ReadNumber()); |
|
465 } |
|
466 |
|
467 for (;;) |
|
468 { |
|
469 UInt64 type = ReadID(); |
|
470 if (type == NID::kEnd) |
|
471 return; |
|
472 if (type == NID::kCRC) |
|
473 { |
|
474 CRecordVector<bool> crcsDefined; |
|
475 CRecordVector<UInt32> crcs; |
|
476 ReadHashDigests(numFolders, crcsDefined, crcs); |
|
477 for(i = 0; i < numFolders; i++) |
|
478 { |
|
479 CFolder &folder = folders[i]; |
|
480 folder.UnPackCRCDefined = crcsDefined[i]; |
|
481 folder.UnPackCRC = crcs[i]; |
|
482 } |
|
483 continue; |
|
484 } |
|
485 SkeepData(); |
|
486 } |
|
487 } |
|
488 |
|
489 void CInArchive::ReadSubStreamsInfo( |
|
490 const CObjectVector<CFolder> &folders, |
|
491 CRecordVector<CNum> &numUnPackStreamsInFolders, |
|
492 CRecordVector<UInt64> &unPackSizes, |
|
493 CRecordVector<bool> &digestsDefined, |
|
494 CRecordVector<UInt32> &digests) |
|
495 { |
|
496 numUnPackStreamsInFolders.Clear(); |
|
497 numUnPackStreamsInFolders.Reserve(folders.Size()); |
|
498 UInt64 type; |
|
499 for (;;) |
|
500 { |
|
501 type = ReadID(); |
|
502 if (type == NID::kNumUnPackStream) |
|
503 { |
|
504 for(int i = 0; i < folders.Size(); i++) |
|
505 numUnPackStreamsInFolders.Add(ReadNum()); |
|
506 continue; |
|
507 } |
|
508 if (type == NID::kCRC || type == NID::kSize) |
|
509 break; |
|
510 if (type == NID::kEnd) |
|
511 break; |
|
512 SkeepData(); |
|
513 } |
|
514 |
|
515 if (numUnPackStreamsInFolders.IsEmpty()) |
|
516 for(int i = 0; i < folders.Size(); i++) |
|
517 numUnPackStreamsInFolders.Add(1); |
|
518 |
|
519 int i; |
|
520 for(i = 0; i < numUnPackStreamsInFolders.Size(); i++) |
|
521 { |
|
522 // v3.13 incorrectly worked with empty folders |
|
523 // v4.07: we check that folder is empty |
|
524 CNum numSubstreams = numUnPackStreamsInFolders[i]; |
|
525 if (numSubstreams == 0) |
|
526 continue; |
|
527 UInt64 sum = 0; |
|
528 for (CNum j = 1; j < numSubstreams; j++) |
|
529 if (type == NID::kSize) |
|
530 { |
|
531 UInt64 size = ReadNumber(); |
|
532 unPackSizes.Add(size); |
|
533 sum += size; |
|
534 } |
|
535 unPackSizes.Add(folders[i].GetUnPackSize() - sum); |
|
536 } |
|
537 if (type == NID::kSize) |
|
538 type = ReadID(); |
|
539 |
|
540 int numDigests = 0; |
|
541 int numDigestsTotal = 0; |
|
542 for(i = 0; i < folders.Size(); i++) |
|
543 { |
|
544 CNum numSubstreams = numUnPackStreamsInFolders[i]; |
|
545 if (numSubstreams != 1 || !folders[i].UnPackCRCDefined) |
|
546 numDigests += numSubstreams; |
|
547 numDigestsTotal += numSubstreams; |
|
548 } |
|
549 |
|
550 for (;;) |
|
551 { |
|
552 if (type == NID::kCRC) |
|
553 { |
|
554 CRecordVector<bool> digestsDefined2; |
|
555 CRecordVector<UInt32> digests2; |
|
556 ReadHashDigests(numDigests, digestsDefined2, digests2); |
|
557 int digestIndex = 0; |
|
558 for (i = 0; i < folders.Size(); i++) |
|
559 { |
|
560 CNum numSubstreams = numUnPackStreamsInFolders[i]; |
|
561 const CFolder &folder = folders[i]; |
|
562 if (numSubstreams == 1 && folder.UnPackCRCDefined) |
|
563 { |
|
564 digestsDefined.Add(true); |
|
565 digests.Add(folder.UnPackCRC); |
|
566 } |
|
567 else |
|
568 for (CNum j = 0; j < numSubstreams; j++, digestIndex++) |
|
569 { |
|
570 digestsDefined.Add(digestsDefined2[digestIndex]); |
|
571 digests.Add(digests2[digestIndex]); |
|
572 } |
|
573 } |
|
574 } |
|
575 else if (type == NID::kEnd) |
|
576 { |
|
577 if (digestsDefined.IsEmpty()) |
|
578 { |
|
579 digestsDefined.Clear(); |
|
580 digests.Clear(); |
|
581 for (int i = 0; i < numDigestsTotal; i++) |
|
582 { |
|
583 digestsDefined.Add(false); |
|
584 digests.Add(0); |
|
585 } |
|
586 } |
|
587 return; |
|
588 } |
|
589 else |
|
590 SkeepData(); |
|
591 type = ReadID(); |
|
592 } |
|
593 } |
|
594 |
|
595 void CInArchive::ReadStreamsInfo( |
|
596 const CObjectVector<CByteBuffer> *dataVector, |
|
597 UInt64 &dataOffset, |
|
598 CRecordVector<UInt64> &packSizes, |
|
599 CRecordVector<bool> &packCRCsDefined, |
|
600 CRecordVector<UInt32> &packCRCs, |
|
601 CObjectVector<CFolder> &folders, |
|
602 CRecordVector<CNum> &numUnPackStreamsInFolders, |
|
603 CRecordVector<UInt64> &unPackSizes, |
|
604 CRecordVector<bool> &digestsDefined, |
|
605 CRecordVector<UInt32> &digests) |
|
606 { |
|
607 for (;;) |
|
608 { |
|
609 UInt64 type = ReadID(); |
|
610 if (type > ((UInt32)1 << 30)) |
|
611 ThrowIncorrect(); |
|
612 switch((UInt32)type) |
|
613 { |
|
614 case NID::kEnd: |
|
615 return; |
|
616 case NID::kPackInfo: |
|
617 { |
|
618 ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs); |
|
619 break; |
|
620 } |
|
621 case NID::kUnPackInfo: |
|
622 { |
|
623 ReadUnPackInfo(dataVector, folders); |
|
624 break; |
|
625 } |
|
626 case NID::kSubStreamsInfo: |
|
627 { |
|
628 ReadSubStreamsInfo(folders, numUnPackStreamsInFolders, |
|
629 unPackSizes, digestsDefined, digests); |
|
630 break; |
|
631 } |
|
632 default: |
|
633 ThrowIncorrect(); |
|
634 } |
|
635 } |
|
636 } |
|
637 |
|
638 void CInArchive::ReadBoolVector(int numItems, CBoolVector &v) |
|
639 { |
|
640 v.Clear(); |
|
641 v.Reserve(numItems); |
|
642 Byte b = 0; |
|
643 Byte mask = 0; |
|
644 for(int i = 0; i < numItems; i++) |
|
645 { |
|
646 if (mask == 0) |
|
647 { |
|
648 b = ReadByte(); |
|
649 mask = 0x80; |
|
650 } |
|
651 v.Add((b & mask) != 0); |
|
652 mask >>= 1; |
|
653 } |
|
654 } |
|
655 |
|
656 void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) |
|
657 { |
|
658 Byte allAreDefined = ReadByte(); |
|
659 if (allAreDefined == 0) |
|
660 { |
|
661 ReadBoolVector(numItems, v); |
|
662 return; |
|
663 } |
|
664 v.Clear(); |
|
665 v.Reserve(numItems); |
|
666 for (int i = 0; i < numItems; i++) |
|
667 v.Add(true); |
|
668 } |
|
669 |
|
670 void CInArchive::ReadTime(const CObjectVector<CByteBuffer> &dataVector, |
|
671 CObjectVector<CFileItem> &files, UInt32 type) |
|
672 { |
|
673 CBoolVector boolVector; |
|
674 ReadBoolVector2(files.Size(), boolVector); |
|
675 |
|
676 CStreamSwitch streamSwitch; |
|
677 streamSwitch.Set(this, &dataVector); |
|
678 |
|
679 for(int i = 0; i < files.Size(); i++) |
|
680 { |
|
681 CFileItem &file = files[i]; |
|
682 CArchiveFileTime fileTime; |
|
683 fileTime.dwLowDateTime = 0; |
|
684 fileTime.dwHighDateTime = 0; |
|
685 bool defined = boolVector[i]; |
|
686 if (defined) |
|
687 { |
|
688 fileTime.dwLowDateTime = ReadUInt32(); |
|
689 fileTime.dwHighDateTime = ReadUInt32(); |
|
690 } |
|
691 switch(type) |
|
692 { |
|
693 case NID::kCreationTime: |
|
694 file.IsCreationTimeDefined = defined; |
|
695 if (defined) |
|
696 file.CreationTime = fileTime; |
|
697 break; |
|
698 case NID::kLastWriteTime: |
|
699 file.IsLastWriteTimeDefined = defined; |
|
700 if (defined) |
|
701 file.LastWriteTime = fileTime; |
|
702 break; |
|
703 case NID::kLastAccessTime: |
|
704 file.IsLastAccessTimeDefined = defined; |
|
705 if (defined) |
|
706 file.LastAccessTime = fileTime; |
|
707 break; |
|
708 } |
|
709 } |
|
710 } |
|
711 |
|
712 HRESULT CInArchive::ReadAndDecodePackedStreams( |
|
713 DECL_EXTERNAL_CODECS_LOC_VARS |
|
714 UInt64 baseOffset, |
|
715 UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector |
|
716 #ifndef _NO_CRYPTO |
|
717 , ICryptoGetTextPassword *getTextPassword |
|
718 #endif |
|
719 ) |
|
720 { |
|
721 CRecordVector<UInt64> packSizes; |
|
722 CRecordVector<bool> packCRCsDefined; |
|
723 CRecordVector<UInt32> packCRCs; |
|
724 CObjectVector<CFolder> folders; |
|
725 |
|
726 CRecordVector<CNum> numUnPackStreamsInFolders; |
|
727 CRecordVector<UInt64> unPackSizes; |
|
728 CRecordVector<bool> digestsDefined; |
|
729 CRecordVector<UInt32> digests; |
|
730 |
|
731 ReadStreamsInfo(NULL, |
|
732 dataOffset, |
|
733 packSizes, |
|
734 packCRCsDefined, |
|
735 packCRCs, |
|
736 folders, |
|
737 numUnPackStreamsInFolders, |
|
738 unPackSizes, |
|
739 digestsDefined, |
|
740 digests); |
|
741 |
|
742 // database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader; |
|
743 |
|
744 CNum packIndex = 0; |
|
745 CDecoder decoder( |
|
746 #ifdef _ST_MODE |
|
747 false |
|
748 #else |
|
749 true |
|
750 #endif |
|
751 ); |
|
752 UInt64 dataStartPos = baseOffset + dataOffset; |
|
753 for(int i = 0; i < folders.Size(); i++) |
|
754 { |
|
755 const CFolder &folder = folders[i]; |
|
756 dataVector.Add(CByteBuffer()); |
|
757 CByteBuffer &data = dataVector.Back(); |
|
758 UInt64 unPackSize64 = folder.GetUnPackSize(); |
|
759 size_t unPackSize = (size_t)unPackSize64; |
|
760 if (unPackSize != unPackSize64) |
|
761 ThrowUnsupported(); |
|
762 data.SetCapacity(unPackSize); |
|
763 |
|
764 CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2; |
|
765 CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; |
|
766 outStreamSpec->Init(data, unPackSize); |
|
767 |
|
768 HRESULT result = decoder.Decode( |
|
769 EXTERNAL_CODECS_LOC_VARS |
|
770 _stream, dataStartPos, |
|
771 &packSizes[packIndex], folder, outStream, NULL |
|
772 #ifndef _NO_CRYPTO |
|
773 , getTextPassword |
|
774 #endif |
|
775 #ifdef COMPRESS_MT |
|
776 , false, 1 |
|
777 #endif |
|
778 ); |
|
779 RINOK(result); |
|
780 |
|
781 if (folder.UnPackCRCDefined) |
|
782 if (CrcCalc(data, unPackSize) != folder.UnPackCRC) |
|
783 ThrowIncorrect(); |
|
784 for (int j = 0; j < folder.PackStreams.Size(); j++) |
|
785 dataStartPos += packSizes[packIndex++]; |
|
786 } |
|
787 return S_OK; |
|
788 } |
|
789 |
|
790 HRESULT CInArchive::ReadHeader( |
|
791 DECL_EXTERNAL_CODECS_LOC_VARS |
|
792 CArchiveDatabaseEx &database |
|
793 #ifndef _NO_CRYPTO |
|
794 , ICryptoGetTextPassword *getTextPassword |
|
795 #endif |
|
796 ) |
|
797 { |
|
798 UInt64 type = ReadID(); |
|
799 |
|
800 if (type == NID::kArchiveProperties) |
|
801 { |
|
802 ReadArchiveProperties(database.ArchiveInfo); |
|
803 type = ReadID(); |
|
804 } |
|
805 |
|
806 CObjectVector<CByteBuffer> dataVector; |
|
807 |
|
808 if (type == NID::kAdditionalStreamsInfo) |
|
809 { |
|
810 HRESULT result = ReadAndDecodePackedStreams( |
|
811 EXTERNAL_CODECS_LOC_VARS |
|
812 database.ArchiveInfo.StartPositionAfterHeader, |
|
813 database.ArchiveInfo.DataStartPosition2, |
|
814 dataVector |
|
815 #ifndef _NO_CRYPTO |
|
816 , getTextPassword |
|
817 #endif |
|
818 ); |
|
819 RINOK(result); |
|
820 database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader; |
|
821 type = ReadID(); |
|
822 } |
|
823 |
|
824 CRecordVector<UInt64> unPackSizes; |
|
825 CRecordVector<bool> digestsDefined; |
|
826 CRecordVector<UInt32> digests; |
|
827 |
|
828 if (type == NID::kMainStreamsInfo) |
|
829 { |
|
830 ReadStreamsInfo(&dataVector, |
|
831 database.ArchiveInfo.DataStartPosition, |
|
832 database.PackSizes, |
|
833 database.PackCRCsDefined, |
|
834 database.PackCRCs, |
|
835 database.Folders, |
|
836 database.NumUnPackStreamsVector, |
|
837 unPackSizes, |
|
838 digestsDefined, |
|
839 digests); |
|
840 database.ArchiveInfo.DataStartPosition += database.ArchiveInfo.StartPositionAfterHeader; |
|
841 type = ReadID(); |
|
842 } |
|
843 else |
|
844 { |
|
845 for(int i = 0; i < database.Folders.Size(); i++) |
|
846 { |
|
847 database.NumUnPackStreamsVector.Add(1); |
|
848 CFolder &folder = database.Folders[i]; |
|
849 unPackSizes.Add(folder.GetUnPackSize()); |
|
850 digestsDefined.Add(folder.UnPackCRCDefined); |
|
851 digests.Add(folder.UnPackCRC); |
|
852 } |
|
853 } |
|
854 |
|
855 database.Files.Clear(); |
|
856 |
|
857 if (type == NID::kEnd) |
|
858 return S_OK; |
|
859 if (type != NID::kFilesInfo) |
|
860 ThrowIncorrect(); |
|
861 |
|
862 CNum numFiles = ReadNum(); |
|
863 database.Files.Reserve(numFiles); |
|
864 CNum i; |
|
865 for(i = 0; i < numFiles; i++) |
|
866 database.Files.Add(CFileItem()); |
|
867 |
|
868 database.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize); |
|
869 if (!database.PackSizes.IsEmpty()) |
|
870 database.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo); |
|
871 if (numFiles > 0 && !digests.IsEmpty()) |
|
872 database.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC); |
|
873 |
|
874 CBoolVector emptyStreamVector; |
|
875 emptyStreamVector.Reserve((int)numFiles); |
|
876 for(i = 0; i < numFiles; i++) |
|
877 emptyStreamVector.Add(false); |
|
878 CBoolVector emptyFileVector; |
|
879 CBoolVector antiFileVector; |
|
880 CNum numEmptyStreams = 0; |
|
881 |
|
882 for (;;) |
|
883 { |
|
884 UInt64 type = ReadID(); |
|
885 if (type == NID::kEnd) |
|
886 break; |
|
887 UInt64 size = ReadNumber(); |
|
888 bool isKnownType = true; |
|
889 if (type > ((UInt32)1 << 30)) |
|
890 isKnownType = false; |
|
891 else switch((UInt32)type) |
|
892 { |
|
893 case NID::kName: |
|
894 { |
|
895 CStreamSwitch streamSwitch; |
|
896 streamSwitch.Set(this, &dataVector); |
|
897 for(int i = 0; i < database.Files.Size(); i++) |
|
898 _inByteBack->ReadString(database.Files[i].Name); |
|
899 break; |
|
900 } |
|
901 case NID::kWinAttributes: |
|
902 { |
|
903 CBoolVector boolVector; |
|
904 ReadBoolVector2(database.Files.Size(), boolVector); |
|
905 CStreamSwitch streamSwitch; |
|
906 streamSwitch.Set(this, &dataVector); |
|
907 for(i = 0; i < numFiles; i++) |
|
908 { |
|
909 CFileItem &file = database.Files[i]; |
|
910 file.AreAttributesDefined = boolVector[i]; |
|
911 if (file.AreAttributesDefined) |
|
912 file.Attributes = ReadUInt32(); |
|
913 } |
|
914 break; |
|
915 } |
|
916 case NID::kStartPos: |
|
917 { |
|
918 CBoolVector boolVector; |
|
919 ReadBoolVector2(database.Files.Size(), boolVector); |
|
920 CStreamSwitch streamSwitch; |
|
921 streamSwitch.Set(this, &dataVector); |
|
922 for(i = 0; i < numFiles; i++) |
|
923 { |
|
924 CFileItem &file = database.Files[i]; |
|
925 file.IsStartPosDefined = boolVector[i]; |
|
926 if (file.IsStartPosDefined) |
|
927 file.StartPos = ReadUInt64(); |
|
928 } |
|
929 break; |
|
930 } |
|
931 case NID::kEmptyStream: |
|
932 { |
|
933 ReadBoolVector(numFiles, emptyStreamVector); |
|
934 for (i = 0; i < (CNum)emptyStreamVector.Size(); i++) |
|
935 if (emptyStreamVector[i]) |
|
936 numEmptyStreams++; |
|
937 emptyFileVector.Reserve(numEmptyStreams); |
|
938 antiFileVector.Reserve(numEmptyStreams); |
|
939 for (i = 0; i < numEmptyStreams; i++) |
|
940 { |
|
941 emptyFileVector.Add(false); |
|
942 antiFileVector.Add(false); |
|
943 } |
|
944 break; |
|
945 } |
|
946 case NID::kEmptyFile: |
|
947 { |
|
948 ReadBoolVector(numEmptyStreams, emptyFileVector); |
|
949 break; |
|
950 } |
|
951 case NID::kAnti: |
|
952 { |
|
953 ReadBoolVector(numEmptyStreams, antiFileVector); |
|
954 break; |
|
955 } |
|
956 case NID::kCreationTime: |
|
957 case NID::kLastWriteTime: |
|
958 case NID::kLastAccessTime: |
|
959 { |
|
960 ReadTime(dataVector, database.Files, (UInt32)type); |
|
961 break; |
|
962 } |
|
963 default: |
|
964 isKnownType = false; |
|
965 } |
|
966 if (isKnownType) |
|
967 database.ArchiveInfo.FileInfoPopIDs.Add(type); |
|
968 else |
|
969 SkeepData(size); |
|
970 } |
|
971 |
|
972 CNum emptyFileIndex = 0; |
|
973 CNum sizeIndex = 0; |
|
974 for(i = 0; i < numFiles; i++) |
|
975 { |
|
976 CFileItem &file = database.Files[i]; |
|
977 file.HasStream = !emptyStreamVector[i]; |
|
978 if(file.HasStream) |
|
979 { |
|
980 file.IsDirectory = false; |
|
981 file.IsAnti = false; |
|
982 file.UnPackSize = unPackSizes[sizeIndex]; |
|
983 file.FileCRC = digests[sizeIndex]; |
|
984 file.IsFileCRCDefined = digestsDefined[sizeIndex]; |
|
985 sizeIndex++; |
|
986 } |
|
987 else |
|
988 { |
|
989 file.IsDirectory = !emptyFileVector[emptyFileIndex]; |
|
990 file.IsAnti = antiFileVector[emptyFileIndex]; |
|
991 emptyFileIndex++; |
|
992 file.UnPackSize = 0; |
|
993 file.IsFileCRCDefined = false; |
|
994 } |
|
995 } |
|
996 return S_OK; |
|
997 } |
|
998 |
|
999 |
|
1000 void CArchiveDatabaseEx::FillFolderStartPackStream() |
|
1001 { |
|
1002 FolderStartPackStreamIndex.Clear(); |
|
1003 FolderStartPackStreamIndex.Reserve(Folders.Size()); |
|
1004 CNum startPos = 0; |
|
1005 for(int i = 0; i < Folders.Size(); i++) |
|
1006 { |
|
1007 FolderStartPackStreamIndex.Add(startPos); |
|
1008 startPos += (CNum)Folders[i].PackStreams.Size(); |
|
1009 } |
|
1010 } |
|
1011 |
|
1012 void CArchiveDatabaseEx::FillStartPos() |
|
1013 { |
|
1014 PackStreamStartPositions.Clear(); |
|
1015 PackStreamStartPositions.Reserve(PackSizes.Size()); |
|
1016 UInt64 startPos = 0; |
|
1017 for(int i = 0; i < PackSizes.Size(); i++) |
|
1018 { |
|
1019 PackStreamStartPositions.Add(startPos); |
|
1020 startPos += PackSizes[i]; |
|
1021 } |
|
1022 } |
|
1023 |
|
1024 void CArchiveDatabaseEx::FillFolderStartFileIndex() |
|
1025 { |
|
1026 FolderStartFileIndex.Clear(); |
|
1027 FolderStartFileIndex.Reserve(Folders.Size()); |
|
1028 FileIndexToFolderIndexMap.Clear(); |
|
1029 FileIndexToFolderIndexMap.Reserve(Files.Size()); |
|
1030 |
|
1031 int folderIndex = 0; |
|
1032 CNum indexInFolder = 0; |
|
1033 for (int i = 0; i < Files.Size(); i++) |
|
1034 { |
|
1035 const CFileItem &file = Files[i]; |
|
1036 bool emptyStream = !file.HasStream; |
|
1037 if (emptyStream && indexInFolder == 0) |
|
1038 { |
|
1039 FileIndexToFolderIndexMap.Add(kNumNoIndex); |
|
1040 continue; |
|
1041 } |
|
1042 if (indexInFolder == 0) |
|
1043 { |
|
1044 // v3.13 incorrectly worked with empty folders |
|
1045 // v4.07: Loop for skipping empty folders |
|
1046 for (;;) |
|
1047 { |
|
1048 if (folderIndex >= Folders.Size()) |
|
1049 ThrowIncorrect(); |
|
1050 FolderStartFileIndex.Add(i); // check it |
|
1051 if (NumUnPackStreamsVector[folderIndex] != 0) |
|
1052 break; |
|
1053 folderIndex++; |
|
1054 } |
|
1055 } |
|
1056 FileIndexToFolderIndexMap.Add(folderIndex); |
|
1057 if (emptyStream) |
|
1058 continue; |
|
1059 indexInFolder++; |
|
1060 if (indexInFolder >= NumUnPackStreamsVector[folderIndex]) |
|
1061 { |
|
1062 folderIndex++; |
|
1063 indexInFolder = 0; |
|
1064 } |
|
1065 } |
|
1066 } |
|
1067 |
|
1068 HRESULT CInArchive::ReadDatabase2( |
|
1069 DECL_EXTERNAL_CODECS_LOC_VARS |
|
1070 CArchiveDatabaseEx &database |
|
1071 #ifndef _NO_CRYPTO |
|
1072 , ICryptoGetTextPassword *getTextPassword |
|
1073 #endif |
|
1074 ) |
|
1075 { |
|
1076 database.Clear(); |
|
1077 database.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; |
|
1078 |
|
1079 database.ArchiveInfo.Version.Major = _header[6]; |
|
1080 database.ArchiveInfo.Version.Minor = _header[7]; |
|
1081 |
|
1082 if (database.ArchiveInfo.Version.Major != kMajorVersion) |
|
1083 ThrowUnsupportedVersion(); |
|
1084 |
|
1085 UInt32 crcFromArchive = GetUInt32FromMem(_header + 8); |
|
1086 UInt64 nextHeaderOffset = GetUInt64FromMem(_header + 0xC); |
|
1087 UInt64 nextHeaderSize = GetUInt64FromMem(_header + 0x14); |
|
1088 UInt32 nextHeaderCRC = GetUInt32FromMem(_header + 0x1C); |
|
1089 UInt32 crc = CrcCalc(_header + 0xC, 20); |
|
1090 |
|
1091 #ifdef FORMAT_7Z_RECOVERY |
|
1092 if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) |
|
1093 { |
|
1094 UInt64 cur, cur2; |
|
1095 RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur)); |
|
1096 const int kCheckSize = 500; |
|
1097 Byte buf[kCheckSize]; |
|
1098 RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2)); |
|
1099 int checkSize = kCheckSize; |
|
1100 if (cur2 - cur < kCheckSize) |
|
1101 checkSize = (int)(cur2 - cur); |
|
1102 RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2)); |
|
1103 |
|
1104 UInt32 realProcessedSize; |
|
1105 RINOK(_stream->Read(buf, (UInt32)kCheckSize, &realProcessedSize)); |
|
1106 |
|
1107 int i; |
|
1108 for (i = (int)realProcessedSize - 2; i >= 0; i--) |
|
1109 if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04) |
|
1110 break; |
|
1111 if (i < 0) |
|
1112 return S_FALSE; |
|
1113 nextHeaderSize = realProcessedSize - i; |
|
1114 nextHeaderOffset = cur2 - cur + i; |
|
1115 nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); |
|
1116 RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); |
|
1117 } |
|
1118 #endif |
|
1119 |
|
1120 #ifdef FORMAT_7Z_RECOVERY |
|
1121 crcFromArchive = crc; |
|
1122 #endif |
|
1123 |
|
1124 database.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; |
|
1125 |
|
1126 if (crc != crcFromArchive) |
|
1127 ThrowIncorrect(); |
|
1128 |
|
1129 if (nextHeaderSize == 0) |
|
1130 return S_OK; |
|
1131 |
|
1132 if (nextHeaderSize > (UInt64)0xFFFFFFFF) |
|
1133 return S_FALSE; |
|
1134 |
|
1135 RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); |
|
1136 |
|
1137 CByteBuffer buffer2; |
|
1138 buffer2.SetCapacity((size_t)nextHeaderSize); |
|
1139 |
|
1140 UInt32 realProcessedSize; |
|
1141 RINOK(_stream->Read(buffer2, (UInt32)nextHeaderSize, &realProcessedSize)); |
|
1142 if (realProcessedSize != (UInt32)nextHeaderSize) |
|
1143 return S_FALSE; |
|
1144 if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC) |
|
1145 ThrowIncorrect(); |
|
1146 |
|
1147 CStreamSwitch streamSwitch; |
|
1148 streamSwitch.Set(this, buffer2); |
|
1149 |
|
1150 CObjectVector<CByteBuffer> dataVector; |
|
1151 |
|
1152 for (;;) |
|
1153 { |
|
1154 UInt64 type = ReadID(); |
|
1155 if (type == NID::kHeader) |
|
1156 break; |
|
1157 if (type != NID::kEncodedHeader) |
|
1158 ThrowIncorrect(); |
|
1159 HRESULT result = ReadAndDecodePackedStreams( |
|
1160 EXTERNAL_CODECS_LOC_VARS |
|
1161 database.ArchiveInfo.StartPositionAfterHeader, |
|
1162 database.ArchiveInfo.DataStartPosition2, |
|
1163 dataVector |
|
1164 #ifndef _NO_CRYPTO |
|
1165 , getTextPassword |
|
1166 #endif |
|
1167 ); |
|
1168 RINOK(result); |
|
1169 if (dataVector.Size() == 0) |
|
1170 return S_OK; |
|
1171 if (dataVector.Size() > 1) |
|
1172 ThrowIncorrect(); |
|
1173 streamSwitch.Remove(); |
|
1174 streamSwitch.Set(this, dataVector.Front()); |
|
1175 } |
|
1176 |
|
1177 return ReadHeader( |
|
1178 EXTERNAL_CODECS_LOC_VARS |
|
1179 database |
|
1180 #ifndef _NO_CRYPTO |
|
1181 , getTextPassword |
|
1182 #endif |
|
1183 ); |
|
1184 } |
|
1185 |
|
1186 HRESULT CInArchive::ReadDatabase( |
|
1187 DECL_EXTERNAL_CODECS_LOC_VARS |
|
1188 CArchiveDatabaseEx &database |
|
1189 #ifndef _NO_CRYPTO |
|
1190 , ICryptoGetTextPassword *getTextPassword |
|
1191 #endif |
|
1192 ) |
|
1193 { |
|
1194 try |
|
1195 { |
|
1196 return ReadDatabase2( |
|
1197 EXTERNAL_CODECS_LOC_VARS database |
|
1198 #ifndef _NO_CRYPTO |
|
1199 , getTextPassword |
|
1200 #endif |
|
1201 ); |
|
1202 } |
|
1203 catch(CInArchiveException &) { return S_FALSE; } |
|
1204 } |
|
1205 |
|
1206 }} |
|