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