7zHandler.cpp 20 KB

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