1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/other-licenses/7zstub/src/7zip/Archive/7z/7zHandler.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,757 @@ 1.4 +// 7zHandler.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +#include "7zHandler.h" 1.9 +#include "7zProperties.h" 1.10 + 1.11 +#include "../../../Common/IntToString.h" 1.12 +#include "../../../Common/ComTry.h" 1.13 +#include "../../../Windows/Defs.h" 1.14 + 1.15 +#include "../Common/ItemNameUtils.h" 1.16 +#ifdef _7Z_VOL 1.17 +#include "../Common/MultiStream.h" 1.18 +#endif 1.19 + 1.20 +#ifdef __7Z_SET_PROPERTIES 1.21 +#ifdef EXTRACT_ONLY 1.22 +#include "../Common/ParseProperties.h" 1.23 +#endif 1.24 +#endif 1.25 + 1.26 +using namespace NWindows; 1.27 + 1.28 +namespace NArchive { 1.29 +namespace N7z { 1.30 + 1.31 +CHandler::CHandler() 1.32 +{ 1.33 + #ifdef COMPRESS_MT 1.34 + _numThreads = NWindows::NSystem::GetNumberOfProcessors(); 1.35 + #endif 1.36 + #ifndef EXTRACT_ONLY 1.37 + Init(); 1.38 + #endif 1.39 + #ifndef EXCLUDE_COM 1.40 + LoadMethodMap(); 1.41 + #endif 1.42 +} 1.43 + 1.44 +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) 1.45 +{ 1.46 + COM_TRY_BEGIN 1.47 + *numItems = 1.48 + #ifdef _7Z_VOL 1.49 + _refs.Size(); 1.50 + #else 1.51 + *numItems = _database.Files.Size(); 1.52 + #endif 1.53 + return S_OK; 1.54 + COM_TRY_END 1.55 +} 1.56 + 1.57 +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) 1.58 +{ 1.59 + value->vt = VT_EMPTY; 1.60 + return S_OK; 1.61 +} 1.62 + 1.63 +#ifdef _SFX 1.64 + 1.65 +STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) 1.66 +{ 1.67 + return E_NOTIMPL; 1.68 +} 1.69 + 1.70 +STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, 1.71 + BSTR *name, PROPID *propID, VARTYPE *varType) 1.72 +{ 1.73 + return E_NOTIMPL; 1.74 +} 1.75 + 1.76 +#endif 1.77 + 1.78 + 1.79 +STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) 1.80 +{ 1.81 + *numProperties = 0; 1.82 + return S_OK; 1.83 +} 1.84 + 1.85 +STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index, 1.86 + BSTR *name, PROPID *propID, VARTYPE *varType) 1.87 +{ 1.88 + return E_NOTIMPL; 1.89 +} 1.90 + 1.91 + 1.92 +static void MySetFileTime(bool timeDefined, FILETIME unixTime, 1.93 + NWindows::NCOM::CPropVariant &propVariant) 1.94 +{ 1.95 + if (timeDefined) 1.96 + propVariant = unixTime; 1.97 +} 1.98 + 1.99 +/* 1.100 +inline static wchar_t GetHex(Byte value) 1.101 +{ 1.102 + return (value < 10) ? ('0' + value) : ('A' + (value - 10)); 1.103 +} 1.104 + 1.105 +static UString ConvertBytesToHexString(const Byte *data, UInt32 size) 1.106 +{ 1.107 + UString result; 1.108 + for (UInt32 i = 0; i < size; i++) 1.109 + { 1.110 + Byte b = data[i]; 1.111 + result += GetHex(b >> 4); 1.112 + result += GetHex(b & 0xF); 1.113 + } 1.114 + return result; 1.115 +} 1.116 +*/ 1.117 + 1.118 + 1.119 +#ifndef _SFX 1.120 + 1.121 +static UString ConvertUInt32ToString(UInt32 value) 1.122 +{ 1.123 + wchar_t buffer[32]; 1.124 + ConvertUInt64ToString(value, buffer); 1.125 + return buffer; 1.126 +} 1.127 + 1.128 +static UString GetStringForSizeValue(UInt32 value) 1.129 +{ 1.130 + for (int i = 31; i >= 0; i--) 1.131 + if ((UInt32(1) << i) == value) 1.132 + return ConvertUInt32ToString(i); 1.133 + UString result; 1.134 + if (value % (1 << 20) == 0) 1.135 + { 1.136 + result += ConvertUInt32ToString(value >> 20); 1.137 + result += L"m"; 1.138 + } 1.139 + else if (value % (1 << 10) == 0) 1.140 + { 1.141 + result += ConvertUInt32ToString(value >> 10); 1.142 + result += L"k"; 1.143 + } 1.144 + else 1.145 + { 1.146 + result += ConvertUInt32ToString(value); 1.147 + result += L"b"; 1.148 + } 1.149 + return result; 1.150 +} 1.151 + 1.152 +static CMethodID k_Copy = { { 0x0 }, 1 }; 1.153 +static CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 }; 1.154 +static CMethodID k_BCJ = { { 0x3, 0x3, 0x1, 0x3 }, 4 }; 1.155 +static CMethodID k_BCJ2 = { { 0x3, 0x3, 0x1, 0x1B }, 4 }; 1.156 +static CMethodID k_PPMD = { { 0x3, 0x4, 0x1 }, 3 }; 1.157 +static CMethodID k_Deflate = { { 0x4, 0x1, 0x8 }, 3 }; 1.158 +static CMethodID k_BZip2 = { { 0x4, 0x2, 0x2 }, 3 }; 1.159 + 1.160 +static inline char GetHex(Byte value) 1.161 +{ 1.162 + return (value < 10) ? ('0' + value) : ('A' + (value - 10)); 1.163 +} 1.164 +static inline UString GetHex2(Byte value) 1.165 +{ 1.166 + UString result; 1.167 + result += GetHex(value >> 4); 1.168 + result += GetHex(value & 0xF); 1.169 + return result; 1.170 +} 1.171 + 1.172 +#endif 1.173 + 1.174 +static inline UInt32 GetUInt32FromMemLE(const Byte *p) 1.175 +{ 1.176 + return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24); 1.177 +} 1.178 + 1.179 +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) 1.180 +{ 1.181 + COM_TRY_BEGIN 1.182 + NWindows::NCOM::CPropVariant propVariant; 1.183 + 1.184 + /* 1.185 + const CRef2 &ref2 = _refs[index]; 1.186 + if (ref2.Refs.IsEmpty()) 1.187 + return E_FAIL; 1.188 + const CRef &ref = ref2.Refs.Front(); 1.189 + */ 1.190 + 1.191 + #ifdef _7Z_VOL 1.192 + const CRef &ref = _refs[index]; 1.193 + const CVolume &volume = _volumes[ref.VolumeIndex]; 1.194 + const CArchiveDatabaseEx &_database = volume.Database; 1.195 + UInt32 index2 = ref.ItemIndex; 1.196 + const CFileItem &item = _database.Files[index2]; 1.197 + #else 1.198 + const CFileItem &item = _database.Files[index]; 1.199 + UInt32 index2 = index; 1.200 + #endif 1.201 + 1.202 + switch(propID) 1.203 + { 1.204 + case kpidPath: 1.205 + { 1.206 + if (!item.Name.IsEmpty()) 1.207 + propVariant = NItemName::GetOSName(item.Name); 1.208 + break; 1.209 + } 1.210 + case kpidIsFolder: 1.211 + propVariant = item.IsDirectory; 1.212 + break; 1.213 + case kpidSize: 1.214 + { 1.215 + propVariant = item.UnPackSize; 1.216 + // propVariant = ref2.UnPackSize; 1.217 + break; 1.218 + } 1.219 + case kpidPosition: 1.220 + { 1.221 + /* 1.222 + if (ref2.Refs.Size() > 1) 1.223 + propVariant = ref2.StartPos; 1.224 + else 1.225 + */ 1.226 + if (item.IsStartPosDefined) 1.227 + propVariant = item.StartPos; 1.228 + break; 1.229 + } 1.230 + case kpidPackedSize: 1.231 + { 1.232 + // propVariant = ref2.PackSize; 1.233 + { 1.234 + CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; 1.235 + if (folderIndex != kNumNoIndex) 1.236 + { 1.237 + if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2) 1.238 + propVariant = _database.GetFolderFullPackSize(folderIndex); 1.239 + /* 1.240 + else 1.241 + propVariant = UInt64(0); 1.242 + */ 1.243 + } 1.244 + else 1.245 + propVariant = UInt64(0); 1.246 + } 1.247 + break; 1.248 + } 1.249 + case kpidLastAccessTime: 1.250 + MySetFileTime(item.IsLastAccessTimeDefined, item.LastAccessTime, propVariant); 1.251 + break; 1.252 + case kpidCreationTime: 1.253 + MySetFileTime(item.IsCreationTimeDefined, item.CreationTime, propVariant); 1.254 + break; 1.255 + case kpidLastWriteTime: 1.256 + MySetFileTime(item.IsLastWriteTimeDefined, item.LastWriteTime, propVariant); 1.257 + break; 1.258 + case kpidAttributes: 1.259 + if (item.AreAttributesDefined) 1.260 + propVariant = item.Attributes; 1.261 + break; 1.262 + case kpidCRC: 1.263 + if (item.IsFileCRCDefined) 1.264 + propVariant = item.FileCRC; 1.265 + break; 1.266 + #ifndef _SFX 1.267 + case kpidMethod: 1.268 + { 1.269 + CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; 1.270 + if (folderIndex != kNumNoIndex) 1.271 + { 1.272 + const CFolder &folderInfo = _database.Folders[folderIndex]; 1.273 + UString methodsString; 1.274 + for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) 1.275 + { 1.276 + const CCoderInfo &coderInfo = folderInfo.Coders[i]; 1.277 + if (!methodsString.IsEmpty()) 1.278 + methodsString += L' '; 1.279 + CMethodInfo methodInfo; 1.280 + 1.281 + bool methodIsKnown; 1.282 + 1.283 + for (int j = 0; j < coderInfo.AltCoders.Size(); j++) 1.284 + { 1.285 + if (j > 0) 1.286 + methodsString += L"|"; 1.287 + const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders[j]; 1.288 + 1.289 + UString methodName; 1.290 + #ifdef NO_REGISTRY 1.291 + 1.292 + methodIsKnown = true; 1.293 + if (altCoderInfo.MethodID == k_Copy) 1.294 + methodName = L"Copy"; 1.295 + else if (altCoderInfo.MethodID == k_LZMA) 1.296 + methodName = L"LZMA"; 1.297 + else if (altCoderInfo.MethodID == k_BCJ) 1.298 + methodName = L"BCJ"; 1.299 + else if (altCoderInfo.MethodID == k_BCJ2) 1.300 + methodName = L"BCJ2"; 1.301 + else if (altCoderInfo.MethodID == k_PPMD) 1.302 + methodName = L"PPMD"; 1.303 + else if (altCoderInfo.MethodID == k_Deflate) 1.304 + methodName = L"Deflate"; 1.305 + else if (altCoderInfo.MethodID == k_BZip2) 1.306 + methodName = L"BZip2"; 1.307 + else 1.308 + methodIsKnown = false; 1.309 + 1.310 + #else 1.311 + 1.312 + methodIsKnown = GetMethodInfo( 1.313 + altCoderInfo.MethodID, methodInfo); 1.314 + methodName = methodInfo.Name; 1.315 + 1.316 + #endif 1.317 + 1.318 + if (methodIsKnown) 1.319 + { 1.320 + methodsString += methodName; 1.321 + if (altCoderInfo.MethodID == k_LZMA) 1.322 + { 1.323 + if (altCoderInfo.Properties.GetCapacity() >= 5) 1.324 + { 1.325 + methodsString += L":"; 1.326 + UInt32 dicSize = GetUInt32FromMemLE( 1.327 + ((const Byte *)altCoderInfo.Properties + 1)); 1.328 + methodsString += GetStringForSizeValue(dicSize); 1.329 + } 1.330 + } 1.331 + else if (altCoderInfo.MethodID == k_PPMD) 1.332 + { 1.333 + if (altCoderInfo.Properties.GetCapacity() >= 5) 1.334 + { 1.335 + Byte order = *(const Byte *)altCoderInfo.Properties; 1.336 + methodsString += L":o"; 1.337 + methodsString += ConvertUInt32ToString(order); 1.338 + methodsString += L":mem"; 1.339 + UInt32 dicSize = GetUInt32FromMemLE( 1.340 + ((const Byte *)altCoderInfo.Properties + 1)); 1.341 + methodsString += GetStringForSizeValue(dicSize); 1.342 + } 1.343 + } 1.344 + else 1.345 + { 1.346 + if (altCoderInfo.Properties.GetCapacity() > 0) 1.347 + { 1.348 + methodsString += L":["; 1.349 + for (size_t bi = 0; bi < altCoderInfo.Properties.GetCapacity(); bi++) 1.350 + { 1.351 + if (bi > 2 && bi + 1 < altCoderInfo.Properties.GetCapacity()) 1.352 + { 1.353 + methodsString += L".."; 1.354 + break; 1.355 + } 1.356 + else 1.357 + methodsString += GetHex2(altCoderInfo.Properties[bi]); 1.358 + } 1.359 + methodsString += L"]"; 1.360 + } 1.361 + } 1.362 + } 1.363 + else 1.364 + { 1.365 + methodsString += altCoderInfo.MethodID.ConvertToString(); 1.366 + } 1.367 + } 1.368 + } 1.369 + propVariant = methodsString; 1.370 + } 1.371 + } 1.372 + break; 1.373 + case kpidBlock: 1.374 + { 1.375 + CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; 1.376 + if (folderIndex != kNumNoIndex) 1.377 + propVariant = (UInt32)folderIndex; 1.378 + } 1.379 + break; 1.380 + case kpidPackedSize0: 1.381 + case kpidPackedSize1: 1.382 + case kpidPackedSize2: 1.383 + case kpidPackedSize3: 1.384 + case kpidPackedSize4: 1.385 + { 1.386 + CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; 1.387 + if (folderIndex != kNumNoIndex) 1.388 + { 1.389 + const CFolder &folderInfo = _database.Folders[folderIndex]; 1.390 + if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2 && 1.391 + folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0)) 1.392 + { 1.393 + propVariant = _database.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0); 1.394 + } 1.395 + else 1.396 + propVariant = UInt64(0); 1.397 + } 1.398 + else 1.399 + propVariant = UInt64(0); 1.400 + } 1.401 + break; 1.402 + #endif 1.403 + case kpidIsAnti: 1.404 + propVariant = item.IsAnti; 1.405 + break; 1.406 + } 1.407 + propVariant.Detach(value); 1.408 + return S_OK; 1.409 + COM_TRY_END 1.410 +} 1.411 + 1.412 +static const wchar_t *kExt = L"7z"; 1.413 +static const wchar_t *kAfterPart = L".7z"; 1.414 + 1.415 +#ifdef _7Z_VOL 1.416 + 1.417 +class CVolumeName 1.418 +{ 1.419 + bool _first; 1.420 + UString _unchangedPart; 1.421 + UString _changedPart; 1.422 + UString _afterPart; 1.423 +public: 1.424 + bool InitName(const UString &name) 1.425 + { 1.426 + _first = true; 1.427 + int dotPos = name.ReverseFind('.'); 1.428 + UString basePart = name; 1.429 + if (dotPos >= 0) 1.430 + { 1.431 + UString ext = name.Mid(dotPos + 1); 1.432 + if (ext.CompareNoCase(kExt)==0 || 1.433 + ext.CompareNoCase(L"EXE") == 0) 1.434 + { 1.435 + _afterPart = kAfterPart; 1.436 + basePart = name.Left(dotPos); 1.437 + } 1.438 + } 1.439 + 1.440 + int numLetters = 1; 1.441 + bool splitStyle = false; 1.442 + if (basePart.Right(numLetters) == L"1") 1.443 + { 1.444 + while (numLetters < basePart.Length()) 1.445 + { 1.446 + if (basePart[basePart.Length() - numLetters - 1] != '0') 1.447 + break; 1.448 + numLetters++; 1.449 + } 1.450 + } 1.451 + else 1.452 + return false; 1.453 + _unchangedPart = basePart.Left(basePart.Length() - numLetters); 1.454 + _changedPart = basePart.Right(numLetters); 1.455 + return true; 1.456 + } 1.457 + 1.458 + UString GetNextName() 1.459 + { 1.460 + UString newName; 1.461 + // if (_newStyle || !_first) 1.462 + { 1.463 + int i; 1.464 + int numLetters = _changedPart.Length(); 1.465 + for (i = numLetters - 1; i >= 0; i--) 1.466 + { 1.467 + wchar_t c = _changedPart[i]; 1.468 + if (c == L'9') 1.469 + { 1.470 + c = L'0'; 1.471 + newName = c + newName; 1.472 + if (i == 0) 1.473 + newName = UString(L'1') + newName; 1.474 + continue; 1.475 + } 1.476 + c++; 1.477 + newName = UString(c) + newName; 1.478 + i--; 1.479 + for (; i >= 0; i--) 1.480 + newName = _changedPart[i] + newName; 1.481 + break; 1.482 + } 1.483 + _changedPart = newName; 1.484 + } 1.485 + _first = false; 1.486 + return _unchangedPart + _changedPart + _afterPart; 1.487 + } 1.488 +}; 1.489 + 1.490 +#endif 1.491 + 1.492 +STDMETHODIMP CHandler::Open(IInStream *stream, 1.493 + const UInt64 *maxCheckStartPosition, 1.494 + IArchiveOpenCallback *openArchiveCallback) 1.495 +{ 1.496 + COM_TRY_BEGIN 1.497 + Close(); 1.498 + #ifndef _SFX 1.499 + _fileInfoPopIDs.Clear(); 1.500 + #endif 1.501 + try 1.502 + { 1.503 + CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback; 1.504 + #ifdef _7Z_VOL 1.505 + CVolumeName seqName; 1.506 + 1.507 + CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; 1.508 + #endif 1.509 + 1.510 + #ifndef _NO_CRYPTO 1.511 + CMyComPtr<ICryptoGetTextPassword> getTextPassword; 1.512 + if (openArchiveCallback) 1.513 + { 1.514 + openArchiveCallbackTemp.QueryInterface( 1.515 + IID_ICryptoGetTextPassword, &getTextPassword); 1.516 + } 1.517 + #endif 1.518 + #ifdef _7Z_VOL 1.519 + if (openArchiveCallback) 1.520 + { 1.521 + openArchiveCallbackTemp.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback); 1.522 + } 1.523 + while(true) 1.524 + { 1.525 + CMyComPtr<IInStream> inStream; 1.526 + if (!_volumes.IsEmpty()) 1.527 + { 1.528 + if (!openVolumeCallback) 1.529 + break; 1.530 + if(_volumes.Size() == 1) 1.531 + { 1.532 + UString baseName; 1.533 + { 1.534 + NCOM::CPropVariant propVariant; 1.535 + RINOK(openVolumeCallback->GetProperty(kpidName, &propVariant)); 1.536 + if (propVariant.vt != VT_BSTR) 1.537 + break; 1.538 + baseName = propVariant.bstrVal; 1.539 + } 1.540 + seqName.InitName(baseName); 1.541 + } 1.542 + 1.543 + UString fullName = seqName.GetNextName(); 1.544 + HRESULT result = openVolumeCallback->GetStream(fullName, &inStream); 1.545 + if (result == S_FALSE) 1.546 + break; 1.547 + if (result != S_OK) 1.548 + return result; 1.549 + if (!stream) 1.550 + break; 1.551 + } 1.552 + else 1.553 + inStream = stream; 1.554 + 1.555 + CInArchive archive; 1.556 + RINOK(archive.Open(inStream, maxCheckStartPosition)); 1.557 + 1.558 + _volumes.Add(CVolume()); 1.559 + CVolume &volume = _volumes.Back(); 1.560 + CArchiveDatabaseEx &database = volume.Database; 1.561 + volume.Stream = inStream; 1.562 + volume.StartRef2Index = _refs.Size(); 1.563 + 1.564 + HRESULT result = archive.ReadDatabase(database 1.565 + #ifndef _NO_CRYPTO 1.566 + , getTextPassword 1.567 + #endif 1.568 + ); 1.569 + if (result != S_OK) 1.570 + { 1.571 + _volumes.Clear(); 1.572 + return result; 1.573 + } 1.574 + database.Fill(); 1.575 + for(int i = 0; i < database.Files.Size(); i++) 1.576 + { 1.577 + CRef refNew; 1.578 + refNew.VolumeIndex = _volumes.Size() - 1; 1.579 + refNew.ItemIndex = i; 1.580 + _refs.Add(refNew); 1.581 + /* 1.582 + const CFileItem &file = database.Files[i]; 1.583 + int j; 1.584 + */ 1.585 + /* 1.586 + for (j = _refs.Size() - 1; j >= 0; j--) 1.587 + { 1.588 + CRef2 &ref2 = _refs[j]; 1.589 + const CRef &ref = ref2.Refs.Back(); 1.590 + const CVolume &volume2 = _volumes[ref.VolumeIndex]; 1.591 + const CArchiveDatabaseEx &database2 = volume2.Database; 1.592 + const CFileItem &file2 = database2.Files[ref.ItemIndex]; 1.593 + if (file2.Name.CompareNoCase(file.Name) == 0) 1.594 + { 1.595 + if (!file.IsStartPosDefined) 1.596 + continue; 1.597 + if (file.StartPos != ref2.StartPos + ref2.UnPackSize) 1.598 + continue; 1.599 + ref2.Refs.Add(refNew); 1.600 + break; 1.601 + } 1.602 + } 1.603 + */ 1.604 + /* 1.605 + j = -1; 1.606 + if (j < 0) 1.607 + { 1.608 + CRef2 ref2New; 1.609 + ref2New.Refs.Add(refNew); 1.610 + j = _refs.Add(ref2New); 1.611 + } 1.612 + CRef2 &ref2 = _refs[j]; 1.613 + ref2.UnPackSize += file.UnPackSize; 1.614 + ref2.PackSize += database.GetFilePackSize(i); 1.615 + if (ref2.Refs.Size() == 1 && file.IsStartPosDefined) 1.616 + ref2.StartPos = file.StartPos; 1.617 + */ 1.618 + } 1.619 + if (database.Files.Size() != 1) 1.620 + break; 1.621 + const CFileItem &file = database.Files.Front(); 1.622 + if (!file.IsStartPosDefined) 1.623 + break; 1.624 + } 1.625 + #else 1.626 + CInArchive archive; 1.627 + RINOK(archive.Open(stream, maxCheckStartPosition)); 1.628 + HRESULT result = archive.ReadDatabase(_database 1.629 + #ifndef _NO_CRYPTO 1.630 + , getTextPassword 1.631 + #endif 1.632 + ); 1.633 + RINOK(result); 1.634 + _database.Fill(); 1.635 + _inStream = stream; 1.636 + #endif 1.637 + } 1.638 + catch(...) 1.639 + { 1.640 + Close(); 1.641 + return S_FALSE; 1.642 + } 1.643 + // _inStream = stream; 1.644 + #ifndef _SFX 1.645 + FillPopIDs(); 1.646 + #endif 1.647 + return S_OK; 1.648 + COM_TRY_END 1.649 +} 1.650 + 1.651 +STDMETHODIMP CHandler::Close() 1.652 +{ 1.653 + COM_TRY_BEGIN 1.654 + #ifdef _7Z_VOL 1.655 + _volumes.Clear(); 1.656 + _refs.Clear(); 1.657 + #else 1.658 + _inStream.Release(); 1.659 + _database.Clear(); 1.660 + #endif 1.661 + return S_OK; 1.662 + COM_TRY_END 1.663 +} 1.664 + 1.665 +#ifdef _7Z_VOL 1.666 +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) 1.667 +{ 1.668 + if (index != 0) 1.669 + return E_INVALIDARG; 1.670 + *stream = 0; 1.671 + CMultiStream *streamSpec = new CMultiStream; 1.672 + CMyComPtr<ISequentialInStream> streamTemp = streamSpec; 1.673 + 1.674 + UInt64 pos = 0; 1.675 + const UString *fileName; 1.676 + for (int i = 0; i < _refs.Size(); i++) 1.677 + { 1.678 + const CRef &ref = _refs[i]; 1.679 + const CVolume &volume = _volumes[ref.VolumeIndex]; 1.680 + const CArchiveDatabaseEx &database = volume.Database; 1.681 + const CFileItem &file = database.Files[ref.ItemIndex]; 1.682 + if (i == 0) 1.683 + fileName = &file.Name; 1.684 + else 1.685 + if (fileName->Compare(file.Name) != 0) 1.686 + return S_FALSE; 1.687 + if (!file.IsStartPosDefined) 1.688 + return S_FALSE; 1.689 + if (file.StartPos != pos) 1.690 + return S_FALSE; 1.691 + CNum folderIndex = database.FileIndexToFolderIndexMap[ref.ItemIndex]; 1.692 + if (folderIndex == kNumNoIndex) 1.693 + { 1.694 + if (file.UnPackSize != 0) 1.695 + return E_FAIL; 1.696 + continue; 1.697 + } 1.698 + if (database.NumUnPackStreamsVector[folderIndex] != 1) 1.699 + return S_FALSE; 1.700 + const CFolder &folder = database.Folders[folderIndex]; 1.701 + if (folder.Coders.Size() != 1) 1.702 + return S_FALSE; 1.703 + const CCoderInfo &coder = folder.Coders.Front(); 1.704 + if (coder.NumInStreams != 1 || coder.NumOutStreams != 1) 1.705 + return S_FALSE; 1.706 + const CAltCoderInfo &altCoder = coder.AltCoders.Front(); 1.707 + if (altCoder.MethodID.IDSize != 1 || altCoder.MethodID.ID[0] != 0) 1.708 + return S_FALSE; 1.709 + 1.710 + pos += file.UnPackSize; 1.711 + CMultiStream::CSubStreamInfo subStreamInfo; 1.712 + subStreamInfo.Stream = volume.Stream; 1.713 + subStreamInfo.Pos = database.GetFolderStreamPos(folderIndex, 0); 1.714 + subStreamInfo.Size = file.UnPackSize; 1.715 + streamSpec->Streams.Add(subStreamInfo); 1.716 + } 1.717 + streamSpec->Init(); 1.718 + *stream = streamTemp.Detach(); 1.719 + return S_OK; 1.720 +} 1.721 +#endif 1.722 + 1.723 + 1.724 +#ifdef __7Z_SET_PROPERTIES 1.725 +#ifdef EXTRACT_ONLY 1.726 + 1.727 +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) 1.728 +{ 1.729 + COM_TRY_BEGIN 1.730 + const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); 1.731 + _numThreads = numProcessors; 1.732 + 1.733 + for (int i = 0; i < numProperties; i++) 1.734 + { 1.735 + UString name = names[i]; 1.736 + name.MakeUpper(); 1.737 + if (name.IsEmpty()) 1.738 + return E_INVALIDARG; 1.739 + const PROPVARIANT &value = values[i]; 1.740 + UInt32 number; 1.741 + int index = ParseStringToUInt32(name, number); 1.742 + if (index == 0) 1.743 + { 1.744 + if(name.Left(2).CompareNoCase(L"MT") == 0) 1.745 + { 1.746 + RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); 1.747 + continue; 1.748 + } 1.749 + else 1.750 + return E_INVALIDARG; 1.751 + } 1.752 + } 1.753 + return S_OK; 1.754 + COM_TRY_END 1.755 +} 1.756 + 1.757 +#endif 1.758 +#endif 1.759 + 1.760 +}}