5 #include "../../../../C/CpuArch.h"
\r
7 #include "../../../Common/ComTry.h"
\r
8 #include "../../../Common/IntToString.h"
\r
10 #ifndef __7Z_SET_PROPERTIES
\r
11 #include "../../../Windows/System.h"
\r
14 #include "../Common/ItemNameUtils.h"
\r
16 #include "7zHandler.h"
\r
17 #include "7zProperties.h"
\r
19 #ifdef __7Z_SET_PROPERTIES
\r
21 #include "../Common/ParseProperties.h"
\r
25 using namespace NWindows;
\r
27 extern UString ConvertMethodIdToString(UInt64 id);
\r
29 namespace NArchive {
\r
32 CHandler::CHandler()
\r
37 _passwordIsDefined = false;
\r
41 #ifdef __7Z_SET_PROPERTIES
\r
42 _numThreads = NSystem::GetNumberOfProcessors();
\r
49 STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
\r
51 *numItems = _db.Files.Size();
\r
57 IMP_IInArchive_ArcProps_NO
\r
59 STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */)
\r
64 STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,
\r
65 BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
\r
73 STATPROPSTG kArcProps[] =
\r
75 { NULL, kpidMethod, VT_BSTR},
\r
76 { NULL, kpidSolid, VT_BOOL},
\r
77 { NULL, kpidNumBlocks, VT_UI4},
\r
78 { NULL, kpidPhySize, VT_UI8},
\r
79 { NULL, kpidHeadersSize, VT_UI8},
\r
80 { NULL, kpidOffset, VT_UI8}
\r
83 STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
\r
86 NCOM::CPropVariant prop;
\r
92 CRecordVector<UInt64> ids;
\r
94 for (i = 0; i < _db.Folders.Size(); i++)
\r
96 const CFolder &f = _db.Folders[i];
\r
97 for (int j = f.Coders.Size() - 1; j >= 0; j--)
\r
98 ids.AddToUniqueSorted(f.Coders[j].MethodID);
\r
101 for (i = 0; i < ids.Size(); i++)
\r
103 UInt64 id = ids[i];
\r
104 UString methodName;
\r
105 /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName);
\r
106 if (methodName.IsEmpty())
\r
107 methodName = ConvertMethodIdToString(id);
\r
108 if (!resString.IsEmpty())
\r
110 resString += methodName;
\r
115 case kpidSolid: prop = _db.IsSolid(); break;
\r
116 case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break;
\r
117 case kpidHeadersSize: prop = _db.HeadersSize; break;
\r
118 case kpidPhySize: prop = _db.PhySize; break;
\r
119 case kpidOffset: if (_db.ArchiveInfo.StartPosition != 0) prop = _db.ArchiveInfo.StartPosition; break;
\r
121 prop.Detach(value);
\r
126 IMP_IInArchive_ArcProps
\r
130 static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop)
\r
133 if (v.GetItem(index, value))
\r
136 ft.dwLowDateTime = (DWORD)value;
\r
137 ft.dwHighDateTime = (DWORD)(value >> 32);
\r
144 static UString ConvertUInt32ToString(UInt32 value)
\r
146 wchar_t buffer[32];
\r
147 ConvertUInt64ToString(value, buffer);
\r
151 static UString GetStringForSizeValue(UInt32 value)
\r
153 for (int i = 31; i >= 0; i--)
\r
154 if ((UInt32(1) << i) == value)
\r
155 return ConvertUInt32ToString(i);
\r
157 if (value % (1 << 20) == 0)
\r
159 result += ConvertUInt32ToString(value >> 20);
\r
162 else if (value % (1 << 10) == 0)
\r
164 result += ConvertUInt32ToString(value >> 10);
\r
169 result += ConvertUInt32ToString(value);
\r
175 static const UInt64 k_Copy = 0x0;
\r
176 static const UInt64 k_Delta = 3;
\r
177 static const UInt64 k_LZMA2 = 0x21;
\r
178 static const UInt64 k_LZMA = 0x030101;
\r
179 static const UInt64 k_PPMD = 0x030401;
\r
181 static wchar_t GetHex(Byte value)
\r
183 return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));
\r
185 static inline void AddHexToString(UString &res, Byte value)
\r
187 res += GetHex((Byte)(value >> 4));
\r
188 res += GetHex((Byte)(value & 0xF));
\r
193 bool CHandler::IsEncrypted(UInt32 index2) const
\r
195 CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
\r
196 if (folderIndex != kNumNoIndex)
\r
197 return _db.Folders[folderIndex].IsEncrypted();
\r
201 STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
\r
204 NCOM::CPropVariant prop;
\r
207 const CRef2 &ref2 = _refs[index];
\r
208 if (ref2.Refs.IsEmpty())
\r
210 const CRef &ref = ref2.Refs.Front();
\r
213 const CFileItem &item = _db.Files[index];
\r
214 UInt32 index2 = index;
\r
219 if (!item.Name.IsEmpty())
\r
220 prop = NItemName::GetOSName(item.Name);
\r
222 case kpidIsDir: prop = item.IsDir; break;
\r
226 // prop = ref2.Size;
\r
231 // prop = ref2.PackSize;
\r
233 CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
\r
234 if (folderIndex != kNumNoIndex)
\r
236 if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2)
\r
237 prop = _db.GetFolderFullPackSize(folderIndex);
\r
248 case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) prop = v; break; }
\r
249 case kpidCTime: SetPropFromUInt64Def(_db.CTime, index2, prop); break;
\r
250 case kpidATime: SetPropFromUInt64Def(_db.ATime, index2, prop); break;
\r
251 case kpidMTime: SetPropFromUInt64Def(_db.MTime, index2, prop); break;
\r
252 case kpidAttrib: if (item.AttribDefined) prop = item.Attrib; break;
\r
253 case kpidCRC: if (item.CrcDefined) prop = item.Crc; break;
\r
254 case kpidEncrypted: prop = IsEncrypted(index2); break;
\r
255 case kpidIsAnti: prop = _db.IsItemAnti(index2); break;
\r
259 CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
\r
260 if (folderIndex != kNumNoIndex)
\r
262 const CFolder &folderInfo = _db.Folders[folderIndex];
\r
263 UString methodsString;
\r
264 for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
\r
266 const CCoderInfo &coder = folderInfo.Coders[i];
\r
267 if (!methodsString.IsEmpty())
\r
268 methodsString += L' ';
\r
270 UString methodName, propsString;
\r
271 bool methodIsKnown = FindMethod(
\r
272 EXTERNAL_CODECS_VARS
\r
273 coder.MethodID, methodName);
\r
275 if (!methodIsKnown)
\r
276 methodsString += ConvertMethodIdToString(coder.MethodID);
\r
279 methodsString += methodName;
\r
280 if (coder.MethodID == k_Delta && coder.Props.GetCapacity() == 1)
\r
281 propsString = ConvertUInt32ToString((UInt32)coder.Props[0] + 1);
\r
282 else if (coder.MethodID == k_LZMA && coder.Props.GetCapacity() == 5)
\r
284 UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);
\r
285 propsString = GetStringForSizeValue(dicSize);
\r
287 else if (coder.MethodID == k_LZMA2 && coder.Props.GetCapacity() == 1)
\r
289 Byte p = coder.Props[0];
\r
290 UInt32 dicSize = (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11));
\r
291 propsString = GetStringForSizeValue(dicSize);
\r
293 else if (coder.MethodID == k_PPMD && coder.Props.GetCapacity() == 5)
\r
295 Byte order = *(const Byte *)coder.Props;
\r
296 propsString = L'o';
\r
297 propsString += ConvertUInt32ToString(order);
\r
298 propsString += L":mem";
\r
299 UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);
\r
300 propsString += GetStringForSizeValue(dicSize);
\r
302 else if (coder.MethodID == k_AES && coder.Props.GetCapacity() >= 1)
\r
304 const Byte *data = (const Byte *)coder.Props;
\r
305 Byte firstByte = *data++;
\r
306 UInt32 numCyclesPower = firstByte & 0x3F;
\r
307 propsString = ConvertUInt32ToString(numCyclesPower);
\r
309 if ((firstByte & 0xC0) != 0)
\r
311 UInt32 saltSize = (firstByte >> 7) & 1;
\r
312 UInt32 ivSize = (firstByte >> 6) & 1;
\r
313 if (coder.Props.GetCapacity() >= 2)
\r
315 Byte secondByte = *data++;
\r
316 saltSize += (secondByte >> 4);
\r
317 ivSize += (secondByte & 0x0F);
\r
323 if (!propsString.IsEmpty())
\r
325 methodsString += L':';
\r
326 methodsString += propsString;
\r
328 else if (coder.Props.GetCapacity() > 0)
\r
330 methodsString += L":[";
\r
331 for (size_t bi = 0; bi < coder.Props.GetCapacity(); bi++)
\r
333 if (bi > 5 && bi + 1 < coder.Props.GetCapacity())
\r
335 methodsString += L"..";
\r
339 AddHexToString(methodsString, coder.Props[bi]);
\r
341 methodsString += L']';
\r
344 prop = methodsString;
\r
350 CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
\r
351 if (folderIndex != kNumNoIndex)
\r
352 prop = (UInt32)folderIndex;
\r
355 case kpidPackedSize0:
\r
356 case kpidPackedSize1:
\r
357 case kpidPackedSize2:
\r
358 case kpidPackedSize3:
\r
359 case kpidPackedSize4:
\r
361 CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
\r
362 if (folderIndex != kNumNoIndex)
\r
364 const CFolder &folderInfo = _db.Folders[folderIndex];
\r
365 if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
\r
366 folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0))
\r
368 prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);
\r
379 prop.Detach(value);
\r
384 STDMETHODIMP CHandler::Open(IInStream *stream,
\r
385 const UInt64 *maxCheckStartPosition,
\r
386 IArchiveOpenCallback *openArchiveCallback)
\r
391 _fileInfoPopIDs.Clear();
\r
395 CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
\r
398 CMyComPtr<ICryptoGetTextPassword> getTextPassword;
\r
399 if (openArchiveCallback)
\r
401 openArchiveCallbackTemp.QueryInterface(
\r
402 IID_ICryptoGetTextPassword, &getTextPassword);
\r
405 CInArchive archive;
\r
406 RINOK(archive.Open(stream, maxCheckStartPosition));
\r
408 _passwordIsDefined = false;
\r
411 HRESULT result = archive.ReadDatabase(
\r
412 EXTERNAL_CODECS_VARS
\r
415 , getTextPassword, _passwordIsDefined
\r
420 _inStream = stream;
\r
427 // _inStream = stream;
\r
435 STDMETHODIMP CHandler::Close()
\r
438 _inStream.Release();
\r
444 #ifdef __7Z_SET_PROPERTIES
\r
445 #ifdef EXTRACT_ONLY
\r
447 STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
\r
450 const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
\r
451 _numThreads = numProcessors;
\r
453 for (int i = 0; i < numProperties; i++)
\r
455 UString name = names[i];
\r
457 if (name.IsEmpty())
\r
458 return E_INVALIDARG;
\r
459 const PROPVARIANT &value = values[i];
\r
461 int index = ParseStringToUInt32(name, number);
\r
464 if(name.Left(2).CompareNoCase(L"MT") == 0)
\r
466 RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));
\r
470 return E_INVALIDARG;
\r
480 IMPL_ISetCompressCodecsInfo
\r