1 // 7zHandler.cpp |
|
2 |
|
3 #include "StdAfx.h" |
|
4 |
|
5 #include "7zHandler.h" |
|
6 #include "7zProperties.h" |
|
7 |
|
8 #include "../../../Common/IntToString.h" |
|
9 #include "../../../Common/ComTry.h" |
|
10 #include "../../../Windows/Defs.h" |
|
11 |
|
12 #include "../Common/ItemNameUtils.h" |
|
13 #ifdef _7Z_VOL |
|
14 #include "../Common/MultiStream.h" |
|
15 #endif |
|
16 |
|
17 #ifdef __7Z_SET_PROPERTIES |
|
18 #ifdef EXTRACT_ONLY |
|
19 #include "../Common/ParseProperties.h" |
|
20 #endif |
|
21 #endif |
|
22 |
|
23 #ifdef COMPRESS_MT |
|
24 #include "../../../Windows/System.h" |
|
25 #endif |
|
26 |
|
27 using namespace NWindows; |
|
28 |
|
29 extern UString ConvertMethodIdToString(UInt64 id); |
|
30 |
|
31 namespace NArchive { |
|
32 namespace N7z { |
|
33 |
|
34 CHandler::CHandler() |
|
35 { |
|
36 _crcSize = 4; |
|
37 |
|
38 #ifdef EXTRACT_ONLY |
|
39 #ifdef COMPRESS_MT |
|
40 _numThreads = NWindows::NSystem::GetNumberOfProcessors(); |
|
41 #endif |
|
42 #else |
|
43 Init(); |
|
44 #endif |
|
45 } |
|
46 |
|
47 STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) |
|
48 { |
|
49 *numItems = |
|
50 #ifdef _7Z_VOL |
|
51 _refs.Size(); |
|
52 #else |
|
53 *numItems = _database.Files.Size(); |
|
54 #endif |
|
55 return S_OK; |
|
56 } |
|
57 |
|
58 #ifdef _SFX |
|
59 |
|
60 IMP_IInArchive_ArcProps_NO |
|
61 |
|
62 STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */) |
|
63 { |
|
64 return E_NOTIMPL; |
|
65 } |
|
66 |
|
67 STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, |
|
68 BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */) |
|
69 { |
|
70 return E_NOTIMPL; |
|
71 } |
|
72 |
|
73 |
|
74 #else |
|
75 |
|
76 STATPROPSTG kArcProps[] = |
|
77 { |
|
78 { NULL, kpidMethod, VT_BSTR}, |
|
79 { NULL, kpidSolid, VT_BOOL}, |
|
80 { NULL, kpidNumBlocks, VT_UI4} |
|
81 }; |
|
82 |
|
83 STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) |
|
84 { |
|
85 COM_TRY_BEGIN |
|
86 NWindows::NCOM::CPropVariant prop; |
|
87 switch(propID) |
|
88 { |
|
89 case kpidMethod: |
|
90 { |
|
91 UString resString; |
|
92 CRecordVector<UInt64> ids; |
|
93 int i; |
|
94 for (i = 0; i < _database.Folders.Size(); i++) |
|
95 { |
|
96 const CFolder &f = _database.Folders[i]; |
|
97 for (int j = f.Coders.Size() - 1; j >= 0; j--) |
|
98 ids.AddToUniqueSorted(f.Coders[j].MethodID); |
|
99 } |
|
100 |
|
101 for (i = 0; i < ids.Size(); i++) |
|
102 { |
|
103 UInt64 id = ids[i]; |
|
104 UString methodName; |
|
105 /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName); |
|
106 if (methodName.IsEmpty()) |
|
107 methodName = ConvertMethodIdToString(id); |
|
108 if (!resString.IsEmpty()) |
|
109 resString += L' '; |
|
110 resString += methodName; |
|
111 } |
|
112 prop = resString; |
|
113 break; |
|
114 } |
|
115 case kpidSolid: prop = _database.IsSolid(); break; |
|
116 case kpidNumBlocks: prop = (UInt32)_database.Folders.Size(); break; |
|
117 } |
|
118 prop.Detach(value); |
|
119 return S_OK; |
|
120 COM_TRY_END |
|
121 } |
|
122 |
|
123 IMP_IInArchive_ArcProps |
|
124 |
|
125 #endif |
|
126 |
|
127 static void MySetFileTime(bool timeDefined, FILETIME unixTime, NWindows::NCOM::CPropVariant &prop) |
|
128 { |
|
129 if (timeDefined) |
|
130 prop = unixTime; |
|
131 } |
|
132 |
|
133 #ifndef _SFX |
|
134 |
|
135 static UString ConvertUInt32ToString(UInt32 value) |
|
136 { |
|
137 wchar_t buffer[32]; |
|
138 ConvertUInt64ToString(value, buffer); |
|
139 return buffer; |
|
140 } |
|
141 |
|
142 static UString GetStringForSizeValue(UInt32 value) |
|
143 { |
|
144 for (int i = 31; i >= 0; i--) |
|
145 if ((UInt32(1) << i) == value) |
|
146 return ConvertUInt32ToString(i); |
|
147 UString result; |
|
148 if (value % (1 << 20) == 0) |
|
149 { |
|
150 result += ConvertUInt32ToString(value >> 20); |
|
151 result += L"m"; |
|
152 } |
|
153 else if (value % (1 << 10) == 0) |
|
154 { |
|
155 result += ConvertUInt32ToString(value >> 10); |
|
156 result += L"k"; |
|
157 } |
|
158 else |
|
159 { |
|
160 result += ConvertUInt32ToString(value); |
|
161 result += L"b"; |
|
162 } |
|
163 return result; |
|
164 } |
|
165 |
|
166 static const UInt64 k_Copy = 0x0; |
|
167 static const UInt64 k_LZMA = 0x030101; |
|
168 static const UInt64 k_PPMD = 0x030401; |
|
169 |
|
170 static wchar_t GetHex(Byte value) |
|
171 { |
|
172 return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10))); |
|
173 } |
|
174 static inline UString GetHex2(Byte value) |
|
175 { |
|
176 UString result; |
|
177 result += GetHex((Byte)(value >> 4)); |
|
178 result += GetHex((Byte)(value & 0xF)); |
|
179 return result; |
|
180 } |
|
181 |
|
182 #endif |
|
183 |
|
184 static const UInt64 k_AES = 0x06F10701; |
|
185 |
|
186 #ifndef _SFX |
|
187 static inline UInt32 GetUInt32FromMemLE(const Byte *p) |
|
188 { |
|
189 return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24); |
|
190 } |
|
191 #endif |
|
192 |
|
193 bool CHandler::IsEncrypted(UInt32 index2) const |
|
194 { |
|
195 CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; |
|
196 if (folderIndex != kNumNoIndex) |
|
197 { |
|
198 const CFolder &folderInfo = _database.Folders[folderIndex]; |
|
199 for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) |
|
200 if (folderInfo.Coders[i].MethodID == k_AES) |
|
201 return true; |
|
202 } |
|
203 return false; |
|
204 } |
|
205 |
|
206 STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) |
|
207 { |
|
208 COM_TRY_BEGIN |
|
209 NWindows::NCOM::CPropVariant prop; |
|
210 |
|
211 /* |
|
212 const CRef2 &ref2 = _refs[index]; |
|
213 if (ref2.Refs.IsEmpty()) |
|
214 return E_FAIL; |
|
215 const CRef &ref = ref2.Refs.Front(); |
|
216 */ |
|
217 |
|
218 #ifdef _7Z_VOL |
|
219 const CRef &ref = _refs[index]; |
|
220 const CVolume &volume = _volumes[ref.VolumeIndex]; |
|
221 const CArchiveDatabaseEx &_database = volume.Database; |
|
222 UInt32 index2 = ref.ItemIndex; |
|
223 const CFileItem &item = _database.Files[index2]; |
|
224 #else |
|
225 const CFileItem &item = _database.Files[index]; |
|
226 UInt32 index2 = index; |
|
227 #endif |
|
228 |
|
229 switch(propID) |
|
230 { |
|
231 case kpidPath: |
|
232 { |
|
233 if (!item.Name.IsEmpty()) |
|
234 prop = NItemName::GetOSName(item.Name); |
|
235 break; |
|
236 } |
|
237 case kpidIsFolder: |
|
238 prop = item.IsDirectory; |
|
239 break; |
|
240 case kpidSize: |
|
241 { |
|
242 prop = item.UnPackSize; |
|
243 // prop = ref2.UnPackSize; |
|
244 break; |
|
245 } |
|
246 case kpidPosition: |
|
247 { |
|
248 /* |
|
249 if (ref2.Refs.Size() > 1) |
|
250 prop = ref2.StartPos; |
|
251 else |
|
252 */ |
|
253 if (item.IsStartPosDefined) |
|
254 prop = item.StartPos; |
|
255 break; |
|
256 } |
|
257 case kpidPackedSize: |
|
258 { |
|
259 // prop = ref2.PackSize; |
|
260 { |
|
261 CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; |
|
262 if (folderIndex != kNumNoIndex) |
|
263 { |
|
264 if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2) |
|
265 prop = _database.GetFolderFullPackSize(folderIndex); |
|
266 /* |
|
267 else |
|
268 prop = (UInt64)0; |
|
269 */ |
|
270 } |
|
271 else |
|
272 prop = (UInt64)0; |
|
273 } |
|
274 break; |
|
275 } |
|
276 case kpidLastAccessTime: |
|
277 MySetFileTime(item.IsLastAccessTimeDefined, item.LastAccessTime, prop); |
|
278 break; |
|
279 case kpidCreationTime: |
|
280 MySetFileTime(item.IsCreationTimeDefined, item.CreationTime, prop); |
|
281 break; |
|
282 case kpidLastWriteTime: |
|
283 MySetFileTime(item.IsLastWriteTimeDefined, item.LastWriteTime, prop); |
|
284 break; |
|
285 case kpidAttributes: |
|
286 if (item.AreAttributesDefined) |
|
287 prop = item.Attributes; |
|
288 break; |
|
289 case kpidCRC: |
|
290 if (item.IsFileCRCDefined) |
|
291 prop = item.FileCRC; |
|
292 break; |
|
293 case kpidEncrypted: |
|
294 { |
|
295 prop = IsEncrypted(index2); |
|
296 break; |
|
297 } |
|
298 #ifndef _SFX |
|
299 case kpidMethod: |
|
300 { |
|
301 CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; |
|
302 if (folderIndex != kNumNoIndex) |
|
303 { |
|
304 const CFolder &folderInfo = _database.Folders[folderIndex]; |
|
305 UString methodsString; |
|
306 for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) |
|
307 { |
|
308 const CCoderInfo &coderInfo = folderInfo.Coders[i]; |
|
309 if (!methodsString.IsEmpty()) |
|
310 methodsString += L' '; |
|
311 |
|
312 { |
|
313 UString methodName; |
|
314 bool methodIsKnown = FindMethod( |
|
315 EXTERNAL_CODECS_VARS |
|
316 coderInfo.MethodID, methodName); |
|
317 |
|
318 if (methodIsKnown) |
|
319 { |
|
320 methodsString += methodName; |
|
321 if (coderInfo.MethodID == k_LZMA) |
|
322 { |
|
323 if (coderInfo.Properties.GetCapacity() >= 5) |
|
324 { |
|
325 methodsString += L":"; |
|
326 UInt32 dicSize = GetUInt32FromMemLE( |
|
327 ((const Byte *)coderInfo.Properties + 1)); |
|
328 methodsString += GetStringForSizeValue(dicSize); |
|
329 } |
|
330 } |
|
331 else if (coderInfo.MethodID == k_PPMD) |
|
332 { |
|
333 if (coderInfo.Properties.GetCapacity() >= 5) |
|
334 { |
|
335 Byte order = *(const Byte *)coderInfo.Properties; |
|
336 methodsString += L":o"; |
|
337 methodsString += ConvertUInt32ToString(order); |
|
338 methodsString += L":mem"; |
|
339 UInt32 dicSize = GetUInt32FromMemLE( |
|
340 ((const Byte *)coderInfo.Properties + 1)); |
|
341 methodsString += GetStringForSizeValue(dicSize); |
|
342 } |
|
343 } |
|
344 else if (coderInfo.MethodID == k_AES) |
|
345 { |
|
346 if (coderInfo.Properties.GetCapacity() >= 1) |
|
347 { |
|
348 methodsString += L":"; |
|
349 const Byte *data = (const Byte *)coderInfo.Properties; |
|
350 Byte firstByte = *data++; |
|
351 UInt32 numCyclesPower = firstByte & 0x3F; |
|
352 methodsString += ConvertUInt32ToString(numCyclesPower); |
|
353 /* |
|
354 if ((firstByte & 0xC0) != 0) |
|
355 { |
|
356 methodsString += L":"; |
|
357 return S_OK; |
|
358 UInt32 saltSize = (firstByte >> 7) & 1; |
|
359 UInt32 ivSize = (firstByte >> 6) & 1; |
|
360 if (coderInfo.Properties.GetCapacity() >= 2) |
|
361 { |
|
362 Byte secondByte = *data++; |
|
363 saltSize += (secondByte >> 4); |
|
364 ivSize += (secondByte & 0x0F); |
|
365 } |
|
366 } |
|
367 */ |
|
368 } |
|
369 } |
|
370 else |
|
371 { |
|
372 if (coderInfo.Properties.GetCapacity() > 0) |
|
373 { |
|
374 methodsString += L":["; |
|
375 for (size_t bi = 0; bi < coderInfo.Properties.GetCapacity(); bi++) |
|
376 { |
|
377 if (bi > 5 && bi + 1 < coderInfo.Properties.GetCapacity()) |
|
378 { |
|
379 methodsString += L".."; |
|
380 break; |
|
381 } |
|
382 else |
|
383 methodsString += GetHex2(coderInfo.Properties[bi]); |
|
384 } |
|
385 methodsString += L"]"; |
|
386 } |
|
387 } |
|
388 } |
|
389 else |
|
390 { |
|
391 methodsString += ConvertMethodIdToString(coderInfo.MethodID); |
|
392 } |
|
393 } |
|
394 } |
|
395 prop = methodsString; |
|
396 } |
|
397 } |
|
398 break; |
|
399 case kpidBlock: |
|
400 { |
|
401 CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; |
|
402 if (folderIndex != kNumNoIndex) |
|
403 prop = (UInt32)folderIndex; |
|
404 } |
|
405 break; |
|
406 case kpidPackedSize0: |
|
407 case kpidPackedSize1: |
|
408 case kpidPackedSize2: |
|
409 case kpidPackedSize3: |
|
410 case kpidPackedSize4: |
|
411 { |
|
412 CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; |
|
413 if (folderIndex != kNumNoIndex) |
|
414 { |
|
415 const CFolder &folderInfo = _database.Folders[folderIndex]; |
|
416 if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2 && |
|
417 folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0)) |
|
418 { |
|
419 prop = _database.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0); |
|
420 } |
|
421 else |
|
422 prop = (UInt64)0; |
|
423 } |
|
424 else |
|
425 prop = (UInt64)0; |
|
426 } |
|
427 break; |
|
428 #endif |
|
429 case kpidIsAnti: |
|
430 prop = item.IsAnti; |
|
431 break; |
|
432 } |
|
433 prop.Detach(value); |
|
434 return S_OK; |
|
435 COM_TRY_END |
|
436 } |
|
437 |
|
438 #ifdef _7Z_VOL |
|
439 |
|
440 static const wchar_t *kExt = L"7z"; |
|
441 static const wchar_t *kAfterPart = L".7z"; |
|
442 |
|
443 class CVolumeName |
|
444 { |
|
445 bool _first; |
|
446 UString _unchangedPart; |
|
447 UString _changedPart; |
|
448 UString _afterPart; |
|
449 public: |
|
450 bool InitName(const UString &name) |
|
451 { |
|
452 _first = true; |
|
453 int dotPos = name.ReverseFind('.'); |
|
454 UString basePart = name; |
|
455 if (dotPos >= 0) |
|
456 { |
|
457 UString ext = name.Mid(dotPos + 1); |
|
458 if (ext.CompareNoCase(kExt)==0 || |
|
459 ext.CompareNoCase(L"EXE") == 0) |
|
460 { |
|
461 _afterPart = kAfterPart; |
|
462 basePart = name.Left(dotPos); |
|
463 } |
|
464 } |
|
465 |
|
466 int numLetters = 1; |
|
467 bool splitStyle = false; |
|
468 if (basePart.Right(numLetters) == L"1") |
|
469 { |
|
470 while (numLetters < basePart.Length()) |
|
471 { |
|
472 if (basePart[basePart.Length() - numLetters - 1] != '0') |
|
473 break; |
|
474 numLetters++; |
|
475 } |
|
476 } |
|
477 else |
|
478 return false; |
|
479 _unchangedPart = basePart.Left(basePart.Length() - numLetters); |
|
480 _changedPart = basePart.Right(numLetters); |
|
481 return true; |
|
482 } |
|
483 |
|
484 UString GetNextName() |
|
485 { |
|
486 UString newName; |
|
487 // if (_newStyle || !_first) |
|
488 { |
|
489 int i; |
|
490 int numLetters = _changedPart.Length(); |
|
491 for (i = numLetters - 1; i >= 0; i--) |
|
492 { |
|
493 wchar_t c = _changedPart[i]; |
|
494 if (c == L'9') |
|
495 { |
|
496 c = L'0'; |
|
497 newName = c + newName; |
|
498 if (i == 0) |
|
499 newName = UString(L'1') + newName; |
|
500 continue; |
|
501 } |
|
502 c++; |
|
503 newName = UString(c) + newName; |
|
504 i--; |
|
505 for (; i >= 0; i--) |
|
506 newName = _changedPart[i] + newName; |
|
507 break; |
|
508 } |
|
509 _changedPart = newName; |
|
510 } |
|
511 _first = false; |
|
512 return _unchangedPart + _changedPart + _afterPart; |
|
513 } |
|
514 }; |
|
515 |
|
516 #endif |
|
517 |
|
518 STDMETHODIMP CHandler::Open(IInStream *stream, |
|
519 const UInt64 *maxCheckStartPosition, |
|
520 IArchiveOpenCallback *openArchiveCallback) |
|
521 { |
|
522 COM_TRY_BEGIN |
|
523 Close(); |
|
524 #ifndef _SFX |
|
525 _fileInfoPopIDs.Clear(); |
|
526 #endif |
|
527 try |
|
528 { |
|
529 CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback; |
|
530 #ifdef _7Z_VOL |
|
531 CVolumeName seqName; |
|
532 |
|
533 CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; |
|
534 #endif |
|
535 |
|
536 #ifndef _NO_CRYPTO |
|
537 CMyComPtr<ICryptoGetTextPassword> getTextPassword; |
|
538 if (openArchiveCallback) |
|
539 { |
|
540 openArchiveCallbackTemp.QueryInterface( |
|
541 IID_ICryptoGetTextPassword, &getTextPassword); |
|
542 } |
|
543 #endif |
|
544 #ifdef _7Z_VOL |
|
545 if (openArchiveCallback) |
|
546 { |
|
547 openArchiveCallbackTemp.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback); |
|
548 } |
|
549 for (;;) |
|
550 { |
|
551 CMyComPtr<IInStream> inStream; |
|
552 if (!_volumes.IsEmpty()) |
|
553 { |
|
554 if (!openVolumeCallback) |
|
555 break; |
|
556 if(_volumes.Size() == 1) |
|
557 { |
|
558 UString baseName; |
|
559 { |
|
560 NCOM::CPropVariant prop; |
|
561 RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); |
|
562 if (prop.vt != VT_BSTR) |
|
563 break; |
|
564 baseName = prop.bstrVal; |
|
565 } |
|
566 seqName.InitName(baseName); |
|
567 } |
|
568 |
|
569 UString fullName = seqName.GetNextName(); |
|
570 HRESULT result = openVolumeCallback->GetStream(fullName, &inStream); |
|
571 if (result == S_FALSE) |
|
572 break; |
|
573 if (result != S_OK) |
|
574 return result; |
|
575 if (!stream) |
|
576 break; |
|
577 } |
|
578 else |
|
579 inStream = stream; |
|
580 |
|
581 CInArchive archive; |
|
582 RINOK(archive.Open(inStream, maxCheckStartPosition)); |
|
583 |
|
584 _volumes.Add(CVolume()); |
|
585 CVolume &volume = _volumes.Back(); |
|
586 CArchiveDatabaseEx &database = volume.Database; |
|
587 volume.Stream = inStream; |
|
588 volume.StartRef2Index = _refs.Size(); |
|
589 |
|
590 HRESULT result = archive.ReadDatabase(database |
|
591 #ifndef _NO_CRYPTO |
|
592 , getTextPassword |
|
593 #endif |
|
594 ); |
|
595 if (result != S_OK) |
|
596 { |
|
597 _volumes.Clear(); |
|
598 return result; |
|
599 } |
|
600 database.Fill(); |
|
601 for(int i = 0; i < database.Files.Size(); i++) |
|
602 { |
|
603 CRef refNew; |
|
604 refNew.VolumeIndex = _volumes.Size() - 1; |
|
605 refNew.ItemIndex = i; |
|
606 _refs.Add(refNew); |
|
607 /* |
|
608 const CFileItem &file = database.Files[i]; |
|
609 int j; |
|
610 */ |
|
611 /* |
|
612 for (j = _refs.Size() - 1; j >= 0; j--) |
|
613 { |
|
614 CRef2 &ref2 = _refs[j]; |
|
615 const CRef &ref = ref2.Refs.Back(); |
|
616 const CVolume &volume2 = _volumes[ref.VolumeIndex]; |
|
617 const CArchiveDatabaseEx &database2 = volume2.Database; |
|
618 const CFileItem &file2 = database2.Files[ref.ItemIndex]; |
|
619 if (file2.Name.CompareNoCase(file.Name) == 0) |
|
620 { |
|
621 if (!file.IsStartPosDefined) |
|
622 continue; |
|
623 if (file.StartPos != ref2.StartPos + ref2.UnPackSize) |
|
624 continue; |
|
625 ref2.Refs.Add(refNew); |
|
626 break; |
|
627 } |
|
628 } |
|
629 */ |
|
630 /* |
|
631 j = -1; |
|
632 if (j < 0) |
|
633 { |
|
634 CRef2 ref2New; |
|
635 ref2New.Refs.Add(refNew); |
|
636 j = _refs.Add(ref2New); |
|
637 } |
|
638 CRef2 &ref2 = _refs[j]; |
|
639 ref2.UnPackSize += file.UnPackSize; |
|
640 ref2.PackSize += database.GetFilePackSize(i); |
|
641 if (ref2.Refs.Size() == 1 && file.IsStartPosDefined) |
|
642 ref2.StartPos = file.StartPos; |
|
643 */ |
|
644 } |
|
645 if (database.Files.Size() != 1) |
|
646 break; |
|
647 const CFileItem &file = database.Files.Front(); |
|
648 if (!file.IsStartPosDefined) |
|
649 break; |
|
650 } |
|
651 #else |
|
652 CInArchive archive; |
|
653 RINOK(archive.Open(stream, maxCheckStartPosition)); |
|
654 HRESULT result = archive.ReadDatabase( |
|
655 EXTERNAL_CODECS_VARS |
|
656 _database |
|
657 #ifndef _NO_CRYPTO |
|
658 , getTextPassword |
|
659 #endif |
|
660 ); |
|
661 RINOK(result); |
|
662 _database.Fill(); |
|
663 _inStream = stream; |
|
664 #endif |
|
665 } |
|
666 catch(...) |
|
667 { |
|
668 Close(); |
|
669 return S_FALSE; |
|
670 } |
|
671 // _inStream = stream; |
|
672 #ifndef _SFX |
|
673 FillPopIDs(); |
|
674 #endif |
|
675 return S_OK; |
|
676 COM_TRY_END |
|
677 } |
|
678 |
|
679 STDMETHODIMP CHandler::Close() |
|
680 { |
|
681 COM_TRY_BEGIN |
|
682 #ifdef _7Z_VOL |
|
683 _volumes.Clear(); |
|
684 _refs.Clear(); |
|
685 #else |
|
686 _inStream.Release(); |
|
687 _database.Clear(); |
|
688 #endif |
|
689 return S_OK; |
|
690 COM_TRY_END |
|
691 } |
|
692 |
|
693 #ifdef _7Z_VOL |
|
694 STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) |
|
695 { |
|
696 if (index != 0) |
|
697 return E_INVALIDARG; |
|
698 *stream = 0; |
|
699 CMultiStream *streamSpec = new CMultiStream; |
|
700 CMyComPtr<ISequentialInStream> streamTemp = streamSpec; |
|
701 |
|
702 UInt64 pos = 0; |
|
703 const UString *fileName; |
|
704 for (int i = 0; i < _refs.Size(); i++) |
|
705 { |
|
706 const CRef &ref = _refs[i]; |
|
707 const CVolume &volume = _volumes[ref.VolumeIndex]; |
|
708 const CArchiveDatabaseEx &database = volume.Database; |
|
709 const CFileItem &file = database.Files[ref.ItemIndex]; |
|
710 if (i == 0) |
|
711 fileName = &file.Name; |
|
712 else |
|
713 if (fileName->Compare(file.Name) != 0) |
|
714 return S_FALSE; |
|
715 if (!file.IsStartPosDefined) |
|
716 return S_FALSE; |
|
717 if (file.StartPos != pos) |
|
718 return S_FALSE; |
|
719 CNum folderIndex = database.FileIndexToFolderIndexMap[ref.ItemIndex]; |
|
720 if (folderIndex == kNumNoIndex) |
|
721 { |
|
722 if (file.UnPackSize != 0) |
|
723 return E_FAIL; |
|
724 continue; |
|
725 } |
|
726 if (database.NumUnPackStreamsVector[folderIndex] != 1) |
|
727 return S_FALSE; |
|
728 const CFolder &folder = database.Folders[folderIndex]; |
|
729 if (folder.Coders.Size() != 1) |
|
730 return S_FALSE; |
|
731 const CCoderInfo &coder = folder.Coders.Front(); |
|
732 if (coder.NumInStreams != 1 || coder.NumOutStreams != 1) |
|
733 return S_FALSE; |
|
734 if (coder.MethodID != k_Copy) |
|
735 return S_FALSE; |
|
736 |
|
737 pos += file.UnPackSize; |
|
738 CMultiStream::CSubStreamInfo subStreamInfo; |
|
739 subStreamInfo.Stream = volume.Stream; |
|
740 subStreamInfo.Pos = database.GetFolderStreamPos(folderIndex, 0); |
|
741 subStreamInfo.Size = file.UnPackSize; |
|
742 streamSpec->Streams.Add(subStreamInfo); |
|
743 } |
|
744 streamSpec->Init(); |
|
745 *stream = streamTemp.Detach(); |
|
746 return S_OK; |
|
747 } |
|
748 #endif |
|
749 |
|
750 |
|
751 #ifdef __7Z_SET_PROPERTIES |
|
752 #ifdef EXTRACT_ONLY |
|
753 |
|
754 STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) |
|
755 { |
|
756 COM_TRY_BEGIN |
|
757 #ifdef COMPRESS_MT |
|
758 const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); |
|
759 _numThreads = numProcessors; |
|
760 #endif |
|
761 |
|
762 for (int i = 0; i < numProperties; i++) |
|
763 { |
|
764 UString name = names[i]; |
|
765 name.MakeUpper(); |
|
766 if (name.IsEmpty()) |
|
767 return E_INVALIDARG; |
|
768 const PROPVARIANT &value = values[i]; |
|
769 UInt32 number; |
|
770 int index = ParseStringToUInt32(name, number); |
|
771 if (index == 0) |
|
772 { |
|
773 if(name.Left(2).CompareNoCase(L"MT") == 0) |
|
774 { |
|
775 #ifdef COMPRESS_MT |
|
776 RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); |
|
777 #endif |
|
778 continue; |
|
779 } |
|
780 else |
|
781 return E_INVALIDARG; |
|
782 } |
|
783 } |
|
784 return S_OK; |
|
785 COM_TRY_END |
|
786 } |
|
787 |
|
788 #endif |
|
789 #endif |
|
790 |
|
791 IMPL_ISetCompressCodecsInfo |
|
792 |
|
793 }} |
|