Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / other-licenses / 7zstub / src / 7zip / Archive / 7z / 7zDecode.cpp
blob7f8f1496578f032aa28339301bd0f8d738dca28d
1 // 7zDecode.cpp
3 #include "StdAfx.h"
5 #include "7zDecode.h"
7 #include "../../IPassword.h"
8 #include "../../Common/LockedStream.h"
9 #include "../../Common/StreamObjects.h"
10 #include "../../Common/ProgressUtils.h"
11 #include "../../Common/LimitedStreams.h"
12 #include "../Common/FilterCoder.h"
14 #include "7zMethods.h"
16 #ifdef COMPRESS_LZMA
17 #include "../../Compress/LZMA/LZMADecoder.h"
18 static NArchive::N7z::CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
19 #endif
21 #ifdef COMPRESS_PPMD
22 #include "../../Compress/PPMD/PPMDDecoder.h"
23 static NArchive::N7z::CMethodID k_PPMD = { { 0x3, 0x4, 0x1 }, 3 };
24 #endif
26 #ifdef COMPRESS_BCJ_X86
27 #include "../../Compress/Branch/x86.h"
28 static NArchive::N7z::CMethodID k_BCJ_X86 = { { 0x3, 0x3, 0x1, 0x3 }, 4 };
29 #endif
31 #ifdef COMPRESS_BCJ2
32 #include "../../Compress/Branch/x86_2.h"
33 static NArchive::N7z::CMethodID k_BCJ2 = { { 0x3, 0x3, 0x1, 0x1B }, 4 };
34 #endif
36 #ifdef COMPRESS_DEFLATE
37 #ifndef COMPRESS_DEFLATE_DECODER
38 #define COMPRESS_DEFLATE_DECODER
39 #endif
40 #endif
42 #ifdef COMPRESS_DEFLATE_DECODER
43 #include "../../Compress/Deflate/DeflateDecoder.h"
44 static NArchive::N7z::CMethodID k_Deflate = { { 0x4, 0x1, 0x8 }, 3 };
45 #endif
47 #ifdef COMPRESS_BZIP2
48 #ifndef COMPRESS_BZIP2_DECODER
49 #define COMPRESS_BZIP2_DECODER
50 #endif
51 #endif
53 #ifdef COMPRESS_BZIP2_DECODER
54 #include "../../Compress/BZip2/BZip2Decoder.h"
55 static NArchive::N7z::CMethodID k_BZip2 = { { 0x4, 0x2, 0x2 }, 3 };
56 #endif
58 #ifdef COMPRESS_COPY
59 #include "../../Compress/Copy/CopyCoder.h"
60 static NArchive::N7z::CMethodID k_Copy = { { 0x0 }, 1 };
61 #endif
63 #ifdef CRYPTO_7ZAES
64 #include "../../Crypto/7zAES/7zAES.h"
65 static NArchive::N7z::CMethodID k_7zAES = { { 0x6, 0xF1, 0x07, 0x01 }, 4 };
66 #endif
68 namespace NArchive {
69 namespace N7z {
71 static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,
72 CBindInfoEx &bindInfo)
74 bindInfo.Clear();
75 int i;
76 for (i = 0; i < folder.BindPairs.Size(); i++)
78 NCoderMixer2::CBindPair bindPair;
79 bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;
80 bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;
81 bindInfo.BindPairs.Add(bindPair);
83 UInt32 outStreamIndex = 0;
84 for (i = 0; i < folder.Coders.Size(); i++)
86 NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
87 const CCoderInfo &coderInfo = folder.Coders[i];
88 coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;
89 coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;
90 bindInfo.Coders.Add(coderStreamsInfo);
91 const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders.Front();
92 bindInfo.CoderMethodIDs.Add(altCoderInfo.MethodID);
93 for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
94 if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
95 bindInfo.OutStreams.Add(outStreamIndex);
97 for (i = 0; i < folder.PackStreams.Size(); i++)
98 bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]);
101 static bool AreCodersEqual(const NCoderMixer2::CCoderStreamsInfo &a1,
102 const NCoderMixer2::CCoderStreamsInfo &a2)
104 return (a1.NumInStreams == a2.NumInStreams) &&
105 (a1.NumOutStreams == a2.NumOutStreams);
108 static bool AreBindPairsEqual(const NCoderMixer2::CBindPair &a1, const NCoderMixer2::CBindPair &a2)
110 return (a1.InIndex == a2.InIndex) &&
111 (a1.OutIndex == a2.OutIndex);
114 static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
116 if (a1.Coders.Size() != a2.Coders.Size())
117 return false;
118 int i;
119 for (i = 0; i < a1.Coders.Size(); i++)
120 if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
121 return false;
122 if (a1.BindPairs.Size() != a2.BindPairs.Size())
123 return false;
124 for (i = 0; i < a1.BindPairs.Size(); i++)
125 if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))
126 return false;
127 for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
128 if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
129 return false;
130 if (a1.InStreams.Size() != a2.InStreams.Size())
131 return false;
132 if (a1.OutStreams.Size() != a2.OutStreams.Size())
133 return false;
134 return true;
137 CDecoder::CDecoder(bool multiThread)
139 #ifndef _ST_MODE
140 multiThread = true;
141 #endif
142 _multiThread = multiThread;
143 _bindInfoExPrevIsDefinded = false;
144 #ifndef EXCLUDE_COM
145 LoadMethodMap();
146 #endif
149 HRESULT CDecoder::Decode(IInStream *inStream,
150 UInt64 startPos,
151 const UInt64 *packSizes,
152 const CFolder &folderInfo,
153 ISequentialOutStream *outStream,
154 ICompressProgressInfo *compressProgress
155 #ifndef _NO_CRYPTO
156 , ICryptoGetTextPassword *getTextPassword
157 #endif
158 #ifdef COMPRESS_MT
159 , bool mtMode, UInt32 numThreads
160 #endif
163 CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
165 CLockedInStream lockedInStream;
166 lockedInStream.Init(inStream);
168 for (int j = 0; j < folderInfo.PackStreams.Size(); j++)
170 CLockedSequentialInStreamImp *lockedStreamImpSpec = new
171 CLockedSequentialInStreamImp;
172 CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
173 lockedStreamImpSpec->Init(&lockedInStream, startPos);
174 startPos += packSizes[j];
176 CLimitedSequentialInStream *streamSpec = new
177 CLimitedSequentialInStream;
178 CMyComPtr<ISequentialInStream> inStream = streamSpec;
179 streamSpec->Init(lockedStreamImp, packSizes[j]);
180 inStreams.Add(inStream);
183 int numCoders = folderInfo.Coders.Size();
185 CBindInfoEx bindInfo;
186 ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
187 bool createNewCoders;
188 if (!_bindInfoExPrevIsDefinded)
189 createNewCoders = true;
190 else
191 createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
192 if (createNewCoders)
194 int i;
195 _decoders.Clear();
196 // _decoders2.Clear();
198 _mixerCoder.Release();
200 if (_multiThread)
202 _mixerCoderMTSpec = new NCoderMixer2::CCoderMixer2MT;
203 _mixerCoder = _mixerCoderMTSpec;
204 _mixerCoderCommon = _mixerCoderMTSpec;
206 else
208 #ifdef _ST_MODE
209 _mixerCoderSTSpec = new NCoderMixer2::CCoderMixer2ST;
210 _mixerCoder = _mixerCoderSTSpec;
211 _mixerCoderCommon = _mixerCoderSTSpec;
212 #endif
214 _mixerCoderCommon->SetBindInfo(bindInfo);
216 for (i = 0; i < numCoders; i++)
218 const CCoderInfo &coderInfo = folderInfo.Coders[i];
219 const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders.Front();
220 #ifndef EXCLUDE_COM
221 CMethodInfo methodInfo;
222 if (!GetMethodInfo(altCoderInfo.MethodID, methodInfo))
223 return E_NOTIMPL;
224 #endif
226 if (coderInfo.IsSimpleCoder())
228 CMyComPtr<ICompressCoder> decoder;
229 CMyComPtr<ICompressFilter> filter;
231 #ifdef COMPRESS_LZMA
232 if (altCoderInfo.MethodID == k_LZMA)
233 decoder = new NCompress::NLZMA::CDecoder;
234 #endif
236 #ifdef COMPRESS_PPMD
237 if (altCoderInfo.MethodID == k_PPMD)
238 decoder = new NCompress::NPPMD::CDecoder;
239 #endif
241 #ifdef COMPRESS_BCJ_X86
242 if (altCoderInfo.MethodID == k_BCJ_X86)
243 filter = new CBCJ_x86_Decoder;
244 #endif
246 #ifdef COMPRESS_DEFLATE_DECODER
247 if (altCoderInfo.MethodID == k_Deflate)
248 decoder = new NCompress::NDeflate::NDecoder::CCOMCoder;
249 #endif
251 #ifdef COMPRESS_BZIP2_DECODER
252 if (altCoderInfo.MethodID == k_BZip2)
253 decoder = new NCompress::NBZip2::CDecoder;
254 #endif
256 #ifdef COMPRESS_COPY
257 if (altCoderInfo.MethodID == k_Copy)
258 decoder = new NCompress::CCopyCoder;
259 #endif
261 #ifdef CRYPTO_7ZAES
262 if (altCoderInfo.MethodID == k_7zAES)
263 filter = new NCrypto::NSevenZ::CDecoder;
264 #endif
266 if (filter)
268 CFilterCoder *coderSpec = new CFilterCoder;
269 decoder = coderSpec;
270 coderSpec->Filter = filter;
272 #ifndef EXCLUDE_COM
273 if (decoder == 0)
275 RINOK(_libraries.CreateCoderSpec(methodInfo.FilePath,
276 methodInfo.Decoder, &decoder));
278 #endif
280 if (decoder == 0)
281 return E_NOTIMPL;
283 _decoders.Add((IUnknown *)decoder);
285 if (_multiThread)
286 _mixerCoderMTSpec->AddCoder(decoder);
287 #ifdef _ST_MODE
288 else
289 _mixerCoderSTSpec->AddCoder(decoder, false);
290 #endif
292 else
294 CMyComPtr<ICompressCoder2> decoder;
296 #ifdef COMPRESS_BCJ2
297 if (altCoderInfo.MethodID == k_BCJ2)
298 decoder = new CBCJ2_x86_Decoder;
299 #endif
301 #ifndef EXCLUDE_COM
302 if (decoder == 0)
304 RINOK(_libraries.CreateCoder2(methodInfo.FilePath,
305 methodInfo.Decoder, &decoder));
307 #endif
309 if (decoder == 0)
310 return E_NOTIMPL;
312 _decoders.Add((IUnknown *)decoder);
313 if (_multiThread)
314 _mixerCoderMTSpec->AddCoder2(decoder);
315 #ifdef _ST_MODE
316 else
317 _mixerCoderSTSpec->AddCoder2(decoder, false);
318 #endif
321 _bindInfoExPrev = bindInfo;
322 _bindInfoExPrevIsDefinded = true;
324 int i;
325 _mixerCoderCommon->ReInit();
327 UInt32 packStreamIndex = 0, unPackStreamIndex = 0;
328 UInt32 coderIndex = 0;
329 // UInt32 coder2Index = 0;
331 for (i = 0; i < numCoders; i++)
333 const CCoderInfo &coderInfo = folderInfo.Coders[i];
334 const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders.Front();
335 CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];
338 CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
339 HRESULT result = decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
340 if (setDecoderProperties)
342 const CByteBuffer &properties = altCoderInfo.Properties;
343 size_t size = properties.GetCapacity();
344 if (size > 0xFFFFFFFF)
345 return E_NOTIMPL;
346 if (size > 0)
348 RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, (UInt32)size));
353 #ifdef COMPRESS_MT
354 if (mtMode)
356 CMyComPtr<ICompressSetCoderMt> setCoderMt;
357 decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
358 if (setCoderMt)
360 RINOK(setCoderMt->SetNumberOfThreads(numThreads));
363 #endif
365 #ifndef _NO_CRYPTO
367 CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
368 HRESULT result = decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
369 if (cryptoSetPassword)
371 if (getTextPassword == 0)
372 return E_FAIL;
373 CMyComBSTR password;
374 RINOK(getTextPassword->CryptoGetTextPassword(&password));
375 CByteBuffer buffer;
376 UString unicodePassword(password);
377 const UInt32 sizeInBytes = unicodePassword.Length() * 2;
378 buffer.SetCapacity(sizeInBytes);
379 for (int i = 0; i < unicodePassword.Length(); i++)
381 wchar_t c = unicodePassword[i];
382 ((Byte *)buffer)[i * 2] = (Byte)c;
383 ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
385 RINOK(cryptoSetPassword->CryptoSetPassword(
386 (const Byte *)buffer, sizeInBytes));
389 #endif
391 coderIndex++;
393 UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;
394 UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;
395 CRecordVector<const UInt64 *> packSizesPointers;
396 CRecordVector<const UInt64 *> unPackSizesPointers;
397 packSizesPointers.Reserve(numInStreams);
398 unPackSizesPointers.Reserve(numOutStreams);
399 UInt32 j;
400 for (j = 0; j < numOutStreams; j++, unPackStreamIndex++)
401 unPackSizesPointers.Add(&folderInfo.UnPackSizes[unPackStreamIndex]);
403 for (j = 0; j < numInStreams; j++, packStreamIndex++)
405 int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
406 if (bindPairIndex >= 0)
407 packSizesPointers.Add(
408 &folderInfo.UnPackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]);
409 else
411 int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
412 if (index < 0)
413 return E_FAIL;
414 packSizesPointers.Add(&packSizes[index]);
418 _mixerCoderCommon->SetCoderInfo(i,
419 &packSizesPointers.Front(),
420 &unPackSizesPointers.Front());
422 UInt32 mainCoder, temp;
423 bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
425 if (_multiThread)
426 _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);
428 else
429 _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
432 if (numCoders == 0)
433 return 0;
434 CRecordVector<ISequentialInStream *> inStreamPointers;
435 inStreamPointers.Reserve(inStreams.Size());
436 for (i = 0; i < inStreams.Size(); i++)
437 inStreamPointers.Add(inStreams[i]);
438 ISequentialOutStream *outStreamPointer = outStream;
439 return _mixerCoder->Code(&inStreamPointers.Front(), NULL,
440 inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress);