other-licenses/7zstub/src/7zip/Archive/7z/7zHandler.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial