xref: /aosp_15_r20/external/lzma/CPP/7zip/Compress/CodecExports.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // CodecExports.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../../../C/CpuArch.h"
6 #include "../../../C/7zVersion.h"
7 
8 #include "../../Common/ComTry.h"
9 #include "../../Common/MyCom.h"
10 
11 #include "../../Windows/Defs.h"
12 #include "../../Windows/PropVariant.h"
13 
14 #include "../ICoder.h"
15 
16 #include "../Common/RegisterCodec.h"
17 
18 extern unsigned g_NumCodecs;
19 extern const CCodecInfo *g_Codecs[];
20 
21 extern unsigned g_NumHashers;
22 extern const CHasherInfo *g_Hashers[];
23 
SetPropFromAscii(const char * s,PROPVARIANT * prop)24 static void SetPropFromAscii(const char *s, PROPVARIANT *prop) throw()
25 {
26   const UINT len = (UINT)strlen(s);
27   BSTR dest = ::SysAllocStringLen(NULL, len);
28   if (dest)
29   {
30     for (UINT i = 0; i <= len; i++)
31       dest[i] = (Byte)s[i];
32     prop->bstrVal = dest;
33     prop->vt = VT_BSTR;
34   }
35 }
36 
SetPropGUID(const GUID & guid,PROPVARIANT * value)37 static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) throw()
38 {
39   if ((value->bstrVal = ::SysAllocStringByteLen((const char *)&guid, sizeof(guid))) != NULL)
40     value->vt = VT_BSTR;
41   return S_OK;
42 }
43 
MethodToClassID(UInt16 typeId,CMethodId id,PROPVARIANT * value)44 static HRESULT MethodToClassID(UInt16 typeId, CMethodId id, PROPVARIANT *value) throw()
45 {
46   GUID clsId;
47   clsId.Data1 = k_7zip_GUID_Data1;
48   clsId.Data2 = k_7zip_GUID_Data2;
49   clsId.Data3 = typeId;
50   SetUi64(clsId.Data4, id)
51   return SetPropGUID(clsId, value);
52 }
53 
FindCodecClassId(const GUID * clsid,bool isCoder2,bool isFilter,bool & encode,int & index)54 static HRESULT FindCodecClassId(const GUID *clsid, bool isCoder2, bool isFilter, bool &encode, int &index) throw()
55 {
56   index = -1;
57   if (clsid->Data1 != k_7zip_GUID_Data1 ||
58       clsid->Data2 != k_7zip_GUID_Data2)
59     return S_OK;
60 
61   encode = true;
62 
63        if (clsid->Data3 == k_7zip_GUID_Data3_Decoder) encode = false;
64   else if (clsid->Data3 != k_7zip_GUID_Data3_Encoder) return S_OK;
65 
66   const UInt64 id = GetUi64(clsid->Data4);
67 
68   for (unsigned i = 0; i < g_NumCodecs; i++)
69   {
70     const CCodecInfo &codec = *g_Codecs[i];
71 
72     if (id != codec.Id
73         || (encode ? !codec.CreateEncoder : !codec.CreateDecoder)
74         || (isFilter ? !codec.IsFilter : codec.IsFilter))
75       continue;
76 
77     if (codec.NumStreams == 1 ? isCoder2 : !isCoder2)
78       return E_NOINTERFACE;
79 
80     index = (int)i;
81     return S_OK;
82   }
83 
84   return S_OK;
85 }
86 
87 /*
88 #ifdef __GNUC__
89 #ifndef __clang__
90 #pragma GCC diagnostic ignored "-Wduplicated-branches"
91 #endif
92 #endif
93 */
94 
CreateCoderMain(unsigned index,bool encode,void ** coder)95 static HRESULT CreateCoderMain(unsigned index, bool encode, void **coder)
96 {
97   COM_TRY_BEGIN
98 
99   const CCodecInfo &codec = *g_Codecs[index];
100 
101   void *c;
102   if (encode)
103     c = codec.CreateEncoder();
104   else
105     c = codec.CreateDecoder();
106 
107   if (c)
108   {
109     IUnknown *unk;
110     unk = (IUnknown *)c;
111     /*
112     if (codec.IsFilter)
113       unk = (IUnknown *)(ICompressFilter *)c;
114     else if (codec.NumStreams != 1)
115       unk = (IUnknown *)(ICompressCoder2 *)c;
116     else
117       unk = (IUnknown *)(ICompressCoder *)c;
118     */
119     unk->AddRef();
120     *coder = c;
121   }
122   return S_OK;
123 
124   COM_TRY_END
125 }
126 
CreateCoder2(bool encode,UInt32 index,const GUID * iid,void ** outObject)127 static HRESULT CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject)
128 {
129   *outObject = NULL;
130 
131   const CCodecInfo &codec = *g_Codecs[index];
132 
133   if (encode ? !codec.CreateEncoder : !codec.CreateDecoder)
134     return CLASS_E_CLASSNOTAVAILABLE;
135 
136   if (codec.IsFilter)
137   {
138     if (*iid != IID_ICompressFilter) return E_NOINTERFACE;
139   }
140   else if (codec.NumStreams != 1)
141   {
142     if (*iid != IID_ICompressCoder2) return E_NOINTERFACE;
143   }
144   else
145   {
146     if (*iid != IID_ICompressCoder) return E_NOINTERFACE;
147   }
148 
149   return CreateCoderMain(index, encode, outObject);
150 }
151 
152 
153 STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject);
CreateDecoder(UInt32 index,const GUID * iid,void ** outObject)154 STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject)
155 {
156   return CreateCoder2(false, index, iid, outObject);
157 }
158 
159 
160 STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject);
CreateEncoder(UInt32 index,const GUID * iid,void ** outObject)161 STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject)
162 {
163   return CreateCoder2(true, index, iid, outObject);
164 }
165 
166 
167 STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject);
CreateCoder(const GUID * clsid,const GUID * iid,void ** outObject)168 STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject)
169 {
170   *outObject = NULL;
171 
172   bool isFilter = false;
173   bool isCoder2 = false;
174   const bool isCoder = (*iid == IID_ICompressCoder) != 0;
175   if (!isCoder)
176   {
177     isFilter = (*iid == IID_ICompressFilter) != 0;
178     if (!isFilter)
179     {
180       isCoder2 = (*iid == IID_ICompressCoder2) != 0;
181       if (!isCoder2)
182         return E_NOINTERFACE;
183     }
184   }
185 
186   bool encode;
187   int codecIndex;
188   const HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex);
189   if (res != S_OK)
190     return res;
191   if (codecIndex < 0)
192     return CLASS_E_CLASSNOTAVAILABLE;
193 
194   return CreateCoderMain((unsigned)codecIndex, encode, outObject);
195 }
196 
197 
198 STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);
GetMethodProperty(UInt32 codecIndex,PROPID propID,PROPVARIANT * value)199 STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)
200 {
201   ::VariantClear((VARIANTARG *)value);
202   const CCodecInfo &codec = *g_Codecs[codecIndex];
203   switch (propID)
204   {
205     case NMethodPropID::kID:
206       value->uhVal.QuadPart = (UInt64)codec.Id;
207       value->vt = VT_UI8;
208       break;
209     case NMethodPropID::kName:
210       SetPropFromAscii(codec.Name, value);
211       break;
212     case NMethodPropID::kDecoder:
213       if (codec.CreateDecoder)
214         return MethodToClassID(k_7zip_GUID_Data3_Decoder, codec.Id, value);
215       break;
216     case NMethodPropID::kEncoder:
217       if (codec.CreateEncoder)
218         return MethodToClassID(k_7zip_GUID_Data3_Encoder, codec.Id, value);
219       break;
220     case NMethodPropID::kDecoderIsAssigned:
221         value->vt = VT_BOOL;
222         value->boolVal = BoolToVARIANT_BOOL(codec.CreateDecoder != NULL);
223       break;
224     case NMethodPropID::kEncoderIsAssigned:
225         value->vt = VT_BOOL;
226         value->boolVal = BoolToVARIANT_BOOL(codec.CreateEncoder != NULL);
227       break;
228     case NMethodPropID::kPackStreams:
229       if (codec.NumStreams != 1)
230       {
231         value->vt = VT_UI4;
232         value->ulVal = (ULONG)codec.NumStreams;
233       }
234       break;
235     case NMethodPropID::kIsFilter:
236       {
237         value->vt = VT_BOOL;
238         value->boolVal = BoolToVARIANT_BOOL(codec.IsFilter);
239       }
240       break;
241     /*
242     case NMethodPropID::kDecoderFlags:
243       {
244         value->vt = VT_UI4;
245         value->ulVal = (ULONG)codec.DecoderFlags;
246       }
247       break;
248     case NMethodPropID::kEncoderFlags:
249       {
250         value->vt = VT_UI4;
251         value->ulVal = (ULONG)codec.EncoderFlags;
252       }
253       break;
254     */
255   }
256   return S_OK;
257 }
258 
259 
260 STDAPI GetNumberOfMethods(UInt32 *numCodecs);
GetNumberOfMethods(UInt32 * numCodecs)261 STDAPI GetNumberOfMethods(UInt32 *numCodecs)
262 {
263   *numCodecs = g_NumCodecs;
264   return S_OK;
265 }
266 
267 
268 // ---------- Hashers ----------
269 
FindHasherClassId(const GUID * clsid)270 static int FindHasherClassId(const GUID *clsid) throw()
271 {
272   if (clsid->Data1 != k_7zip_GUID_Data1 ||
273       clsid->Data2 != k_7zip_GUID_Data2 ||
274       clsid->Data3 != k_7zip_GUID_Data3_Hasher)
275     return -1;
276   const UInt64 id = GetUi64(clsid->Data4);
277   for (unsigned i = 0; i < g_NumCodecs; i++)
278     if (id == g_Hashers[i]->Id)
279       return (int)i;
280   return -1;
281 }
282 
CreateHasher2(UInt32 index,IHasher ** hasher)283 static HRESULT CreateHasher2(UInt32 index, IHasher **hasher)
284 {
285   COM_TRY_BEGIN
286   *hasher = g_Hashers[index]->CreateHasher();
287   if (*hasher)
288     (*hasher)->AddRef();
289   return S_OK;
290   COM_TRY_END
291 }
292 
293 STDAPI CreateHasher(const GUID *clsid, IHasher **outObject);
CreateHasher(const GUID * clsid,IHasher ** outObject)294 STDAPI CreateHasher(const GUID *clsid, IHasher **outObject)
295 {
296   COM_TRY_BEGIN
297   *outObject = NULL;
298   const int index = FindHasherClassId(clsid);
299   if (index < 0)
300     return CLASS_E_CLASSNOTAVAILABLE;
301   return CreateHasher2((UInt32)(unsigned)index, outObject);
302   COM_TRY_END
303 }
304 
305 STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);
GetHasherProp(UInt32 codecIndex,PROPID propID,PROPVARIANT * value)306 STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)
307 {
308   ::VariantClear((VARIANTARG *)value);
309   const CHasherInfo &codec = *g_Hashers[codecIndex];
310   switch (propID)
311   {
312     case NMethodPropID::kID:
313       value->uhVal.QuadPart = (UInt64)codec.Id;
314       value->vt = VT_UI8;
315       break;
316     case NMethodPropID::kName:
317       SetPropFromAscii(codec.Name, value);
318       break;
319     case NMethodPropID::kEncoder:
320       if (codec.CreateHasher)
321         return MethodToClassID(k_7zip_GUID_Data3_Hasher, codec.Id, value);
322       break;
323     case NMethodPropID::kDigestSize:
324       value->ulVal = (ULONG)codec.DigestSize;
325       value->vt = VT_UI4;
326       break;
327   }
328   return S_OK;
329 }
330 
331 Z7_CLASS_IMP_COM_1(CHashers, IHashers) };
332 
333 STDAPI GetHashers(IHashers **hashers);
334 STDAPI GetHashers(IHashers **hashers)
335 {
336   COM_TRY_BEGIN
337   *hashers = new CHashers;
338   if (*hashers)
339     (*hashers)->AddRef();
340   return S_OK;
341   COM_TRY_END
342 }
343 
344 Z7_COM7F_IMF2(UInt32, CHashers::GetNumHashers())
345 {
346   return g_NumHashers;
347 }
348 
349 Z7_COM7F_IMF(CHashers::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value))
350 {
351   return ::GetHasherProp(index, propID, value);
352 }
353 
354 Z7_COM7F_IMF(CHashers::CreateHasher(UInt32 index, IHasher **hasher))
355 {
356   return ::CreateHasher2(index, hasher);
357 }
358 
359 
360 STDAPI GetModuleProp(PROPID propID, PROPVARIANT *value);
361 STDAPI GetModuleProp(PROPID propID, PROPVARIANT *value)
362 {
363   ::VariantClear((VARIANTARG *)value);
364   switch (propID)
365   {
366     case NModulePropID::kInterfaceType:
367     {
368       NWindows::NCOM::PropVarEm_Set_UInt32(value, NModuleInterfaceType::k_IUnknown_VirtDestructor_ThisModule);
369       break;
370     }
371     case NModulePropID::kVersion:
372     {
373       NWindows::NCOM::PropVarEm_Set_UInt32(value, (MY_VER_MAJOR << 16) | MY_VER_MINOR);
374       break;
375     }
376   }
377   return S_OK;
378 }
379