Imported Upstream version 9.20
[platform/upstream/7zip.git] / CPP / 7zip / Archive / Nsis / NsisDecode.cpp
1 // NsisDecode.cpp\r
2 \r
3 #include "StdAfx.h"\r
4 \r
5 #include "NsisDecode.h"\r
6 \r
7 #include "../../Common/StreamUtils.h"\r
8 \r
9 #include "../../Common/MethodId.h"\r
10 \r
11 #include "../../Compress/BZip2Decoder.h"\r
12 #include "../../Compress/DeflateDecoder.h"\r
13 #include "../../Compress/LzmaDecoder.h"\r
14 \r
15 namespace NArchive {\r
16 namespace NNsis {\r
17 \r
18 static const CMethodId k_BCJ_X86 = 0x03030103;\r
19 \r
20 HRESULT CDecoder::Init(\r
21     DECL_EXTERNAL_CODECS_LOC_VARS\r
22     IInStream *inStream, NMethodType::EEnum method, bool thereIsFilterFlag, bool &useFilter)\r
23 {\r
24   useFilter = false;\r
25   CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;\r
26 \r
27   if (_decoderInStream)\r
28     if (method != _method)\r
29       Release();\r
30   _method = method;\r
31   if (!_codecInStream)\r
32   {\r
33     switch (method)\r
34     {\r
35       // case NMethodType::kCopy: return E_NOTIMPL;\r
36       case NMethodType::kDeflate: _codecInStream = new NCompress::NDeflate::NDecoder::CNsisCOMCoder(); break;\r
37       case NMethodType::kBZip2: _codecInStream = new NCompress::NBZip2::CNsisDecoder(); break;\r
38       case NMethodType::kLZMA: _codecInStream = new NCompress::NLzma::CDecoder(); break;\r
39       default: return E_NOTIMPL;\r
40     }\r
41   }\r
42 \r
43   if (thereIsFilterFlag)\r
44   {\r
45     UInt32 processedSize;\r
46     BYTE flag;\r
47     RINOK(inStream->Read(&flag, 1, &processedSize));\r
48     if (processedSize != 1)\r
49       return E_FAIL;\r
50     if (flag > 1)\r
51       return E_NOTIMPL;\r
52     useFilter = (flag != 0);\r
53   }\r
54   \r
55   if (useFilter)\r
56   {\r
57     if (!_filterInStream)\r
58     {\r
59       CMyComPtr<ICompressCoder> coder;\r
60       RINOK(CreateCoder(\r
61           EXTERNAL_CODECS_LOC_VARS\r
62           k_BCJ_X86, coder, false));\r
63       if (!coder)\r
64         return E_NOTIMPL;\r
65       coder.QueryInterface(IID_ISequentialInStream, &_filterInStream);\r
66       if (!_filterInStream)\r
67         return E_NOTIMPL;\r
68     }\r
69     CMyComPtr<ICompressSetInStream> setInStream;\r
70     _filterInStream.QueryInterface(IID_ICompressSetInStream, &setInStream);\r
71     if (!setInStream)\r
72       return E_NOTIMPL;\r
73     RINOK(setInStream->SetInStream(_codecInStream));\r
74     _decoderInStream = _filterInStream;\r
75   }\r
76   else\r
77     _decoderInStream = _codecInStream;\r
78 \r
79   if (method == NMethodType::kLZMA)\r
80   {\r
81     CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;\r
82     _codecInStream.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);\r
83     if (setDecoderProperties)\r
84     {\r
85       static const UInt32 kPropertiesSize = 5;\r
86       BYTE properties[kPropertiesSize];\r
87       UInt32 processedSize;\r
88       RINOK(inStream->Read(properties, kPropertiesSize, &processedSize));\r
89       if (processedSize != kPropertiesSize)\r
90         return E_FAIL;\r
91       RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, kPropertiesSize));\r
92     }\r
93   }\r
94 \r
95   {\r
96     CMyComPtr<ICompressSetInStream> setInStream;\r
97     _codecInStream.QueryInterface(IID_ICompressSetInStream, &setInStream);\r
98     if (!setInStream)\r
99       return E_NOTIMPL;\r
100     RINOK(setInStream->SetInStream(inStream));\r
101   }\r
102 \r
103   {\r
104     CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;\r
105     _codecInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);\r
106     if (!setOutStreamSize)\r
107       return E_NOTIMPL;\r
108     RINOK(setOutStreamSize->SetOutStreamSize(NULL));\r
109   }\r
110 \r
111   if (useFilter)\r
112   {\r
113     /*\r
114     CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;\r
115     _filterInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);\r
116     if (!setOutStreamSize)\r
117       return E_NOTIMPL;\r
118     RINOK(setOutStreamSize->SetOutStreamSize(NULL));\r
119     */\r
120   }\r
121 \r
122   return S_OK;\r
123 }\r
124 \r
125 HRESULT CDecoder::Read(void *data, size_t *processedSize)\r
126 {\r
127   return ReadStream(_decoderInStream, data, processedSize);;\r
128 }\r
129 \r
130 }}\r