1370b324cSopenharmony_ci// LoadCodecs.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci/*
4370b324cSopenharmony_ciZ7_EXTERNAL_CODECS
5370b324cSopenharmony_ci---------------
6370b324cSopenharmony_ci  CCodecs::Load() tries to detect the directory with plugins.
7370b324cSopenharmony_ci  It stops the checking, if it can find any of the following items:
8370b324cSopenharmony_ci    - 7z.dll file
9370b324cSopenharmony_ci    - "Formats" subdir
10370b324cSopenharmony_ci    - "Codecs"  subdir
11370b324cSopenharmony_ci  The order of check:
12370b324cSopenharmony_ci    1) directory of client executable
13370b324cSopenharmony_ci    2) WIN32: directory for REGISTRY item [HKEY_*\Software\7-Zip\Path**]
14370b324cSopenharmony_ci       The order for HKEY_* : Path** :
15370b324cSopenharmony_ci         - HKEY_CURRENT_USER  : PathXX
16370b324cSopenharmony_ci         - HKEY_LOCAL_MACHINE : PathXX
17370b324cSopenharmony_ci         - HKEY_CURRENT_USER  : Path
18370b324cSopenharmony_ci         - HKEY_LOCAL_MACHINE : Path
19370b324cSopenharmony_ci       PathXX is Path32 in 32-bit code
20370b324cSopenharmony_ci       PathXX is Path64 in 64-bit code
21370b324cSopenharmony_ci
22370b324cSopenharmony_ci
23370b324cSopenharmony_ciEXPORT_CODECS
24370b324cSopenharmony_ci-------------
25370b324cSopenharmony_ci  if (Z7_EXTERNAL_CODECS) is defined, then the code exports internal
26370b324cSopenharmony_ci  codecs of client from CCodecs object to external plugins.
27370b324cSopenharmony_ci  7-Zip doesn't use that feature. 7-Zip uses the scheme:
28370b324cSopenharmony_ci    - client application without internal plugins.
29370b324cSopenharmony_ci    - 7z.dll module contains all (or almost all) plugins.
30370b324cSopenharmony_ci      7z.dll can use codecs from another plugins, if required.
31370b324cSopenharmony_ci*/
32370b324cSopenharmony_ci
33370b324cSopenharmony_ci
34370b324cSopenharmony_ci#include "StdAfx.h"
35370b324cSopenharmony_ci
36370b324cSopenharmony_ci#include "../../../Common/MyCom.h"
37370b324cSopenharmony_ci#include "../../../Common/StringToInt.h"
38370b324cSopenharmony_ci#include "../../../Common/StringConvert.h"
39370b324cSopenharmony_ci
40370b324cSopenharmony_ci#include "../../../Windows/ErrorMsg.h"
41370b324cSopenharmony_ci#include "../../../Windows/FileIO.h"
42370b324cSopenharmony_ci#include "../../../Windows/PropVariant.h"
43370b324cSopenharmony_ci
44370b324cSopenharmony_ci#include "LoadCodecs.h"
45370b324cSopenharmony_ci
46370b324cSopenharmony_ci#include "../../ICoder.h"
47370b324cSopenharmony_ci#include "../../Common/RegisterArc.h"
48370b324cSopenharmony_ci#include "../../Common/RegisterCodec.h"
49370b324cSopenharmony_ci
50370b324cSopenharmony_ci#ifdef Z7_EXTERNAL_CODECS
51370b324cSopenharmony_ci// #define EXPORT_CODECS
52370b324cSopenharmony_ci#endif
53370b324cSopenharmony_ci
54370b324cSopenharmony_ci#ifdef Z7_EXTERNAL_CODECS
55370b324cSopenharmony_ci
56370b324cSopenharmony_ci#include "../../../Windows/FileFind.h"
57370b324cSopenharmony_ci#include "../../../Windows/DLL.h"
58370b324cSopenharmony_ci
59370b324cSopenharmony_ci#ifdef _WIN32
60370b324cSopenharmony_ci#include "../../../Windows/FileName.h"
61370b324cSopenharmony_ci#include "../../../Windows/Registry.h"
62370b324cSopenharmony_ci#endif
63370b324cSopenharmony_ci
64370b324cSopenharmony_ciusing namespace NWindows;
65370b324cSopenharmony_ciusing namespace NFile;
66370b324cSopenharmony_ci
67370b324cSopenharmony_ci
68370b324cSopenharmony_ci#define kCodecsFolderName FTEXT("Codecs")
69370b324cSopenharmony_ci#define kFormatsFolderName FTEXT("Formats")
70370b324cSopenharmony_ci
71370b324cSopenharmony_ci
72370b324cSopenharmony_cistatic CFSTR const kMainDll =
73370b324cSopenharmony_ci  #ifdef _WIN32
74370b324cSopenharmony_ci    FTEXT("7z.dll");
75370b324cSopenharmony_ci  #else
76370b324cSopenharmony_ci    FTEXT("7z.so");
77370b324cSopenharmony_ci  #endif
78370b324cSopenharmony_ci
79370b324cSopenharmony_ci
80370b324cSopenharmony_ci#ifdef _WIN32
81370b324cSopenharmony_ci
82370b324cSopenharmony_cistatic LPCTSTR const kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip");
83370b324cSopenharmony_cistatic LPCWSTR const kProgramPathValue = L"Path";
84370b324cSopenharmony_cistatic LPCWSTR const kProgramPath2Value = L"Path"
85370b324cSopenharmony_ci  #ifdef _WIN64
86370b324cSopenharmony_ci  L"64";
87370b324cSopenharmony_ci  #else
88370b324cSopenharmony_ci  L"32";
89370b324cSopenharmony_ci  #endif
90370b324cSopenharmony_ci
91370b324cSopenharmony_cistatic bool ReadPathFromRegistry(HKEY baseKey, LPCWSTR value, FString &path)
92370b324cSopenharmony_ci{
93370b324cSopenharmony_ci  NRegistry::CKey key;
94370b324cSopenharmony_ci  if (key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS)
95370b324cSopenharmony_ci  {
96370b324cSopenharmony_ci    UString pathU;
97370b324cSopenharmony_ci    if (key.QueryValue(value, pathU) == ERROR_SUCCESS)
98370b324cSopenharmony_ci    {
99370b324cSopenharmony_ci      path = us2fs(pathU);
100370b324cSopenharmony_ci      NName::NormalizeDirPathPrefix(path);
101370b324cSopenharmony_ci      return NFind::DoesFileExist_Raw(path + kMainDll);
102370b324cSopenharmony_ci    }
103370b324cSopenharmony_ci  }
104370b324cSopenharmony_ci  return false;
105370b324cSopenharmony_ci}
106370b324cSopenharmony_ci
107370b324cSopenharmony_ci#endif // _WIN32
108370b324cSopenharmony_ci
109370b324cSopenharmony_ci#endif // Z7_EXTERNAL_CODECS
110370b324cSopenharmony_ci
111370b324cSopenharmony_ci
112370b324cSopenharmony_cistatic const unsigned kNumArcsMax = 72;
113370b324cSopenharmony_cistatic unsigned g_NumArcs = 0;
114370b324cSopenharmony_cistatic const CArcInfo *g_Arcs[kNumArcsMax];
115370b324cSopenharmony_ci
116370b324cSopenharmony_civoid RegisterArc(const CArcInfo *arcInfo) throw()
117370b324cSopenharmony_ci{
118370b324cSopenharmony_ci  if (g_NumArcs < kNumArcsMax)
119370b324cSopenharmony_ci  {
120370b324cSopenharmony_ci    g_Arcs[g_NumArcs] = arcInfo;
121370b324cSopenharmony_ci    g_NumArcs++;
122370b324cSopenharmony_ci  }
123370b324cSopenharmony_ci  // else throw 1;
124370b324cSopenharmony_ci}
125370b324cSopenharmony_ci
126370b324cSopenharmony_ci/*
127370b324cSopenharmony_cistatic void SplitString(const UString &srcString, UStringVector &destStrings)
128370b324cSopenharmony_ci{
129370b324cSopenharmony_ci  destStrings.Clear();
130370b324cSopenharmony_ci  UString s;
131370b324cSopenharmony_ci  unsigned len = srcString.Len();
132370b324cSopenharmony_ci  if (len == 0)
133370b324cSopenharmony_ci    return;
134370b324cSopenharmony_ci  for (unsigned i = 0; i < len; i++)
135370b324cSopenharmony_ci  {
136370b324cSopenharmony_ci    wchar_t c = srcString[i];
137370b324cSopenharmony_ci    if (c == L' ')
138370b324cSopenharmony_ci    {
139370b324cSopenharmony_ci      if (!s.IsEmpty())
140370b324cSopenharmony_ci      {
141370b324cSopenharmony_ci        destStrings.Add(s);
142370b324cSopenharmony_ci        s.Empty();
143370b324cSopenharmony_ci      }
144370b324cSopenharmony_ci    }
145370b324cSopenharmony_ci    else
146370b324cSopenharmony_ci      s += c;
147370b324cSopenharmony_ci  }
148370b324cSopenharmony_ci  if (!s.IsEmpty())
149370b324cSopenharmony_ci    destStrings.Add(s);
150370b324cSopenharmony_ci}
151370b324cSopenharmony_ci*/
152370b324cSopenharmony_ci
153370b324cSopenharmony_ciint CArcInfoEx::FindExtension(const UString &ext) const
154370b324cSopenharmony_ci{
155370b324cSopenharmony_ci  FOR_VECTOR (i, Exts)
156370b324cSopenharmony_ci    if (ext.IsEqualTo_NoCase(Exts[i].Ext))
157370b324cSopenharmony_ci      return (int)i;
158370b324cSopenharmony_ci  return -1;
159370b324cSopenharmony_ci}
160370b324cSopenharmony_ci
161370b324cSopenharmony_civoid CArcInfoEx::AddExts(const UString &ext, const UString &addExt)
162370b324cSopenharmony_ci{
163370b324cSopenharmony_ci  UStringVector exts, addExts;
164370b324cSopenharmony_ci  SplitString(ext, exts);
165370b324cSopenharmony_ci  SplitString(addExt, addExts);
166370b324cSopenharmony_ci  FOR_VECTOR (i, exts)
167370b324cSopenharmony_ci  {
168370b324cSopenharmony_ci    CArcExtInfo extInfo;
169370b324cSopenharmony_ci    extInfo.Ext = exts[i];
170370b324cSopenharmony_ci    if (i < addExts.Size())
171370b324cSopenharmony_ci    {
172370b324cSopenharmony_ci      extInfo.AddExt = addExts[i];
173370b324cSopenharmony_ci      if (extInfo.AddExt == L"*")
174370b324cSopenharmony_ci        extInfo.AddExt.Empty();
175370b324cSopenharmony_ci    }
176370b324cSopenharmony_ci    Exts.Add(extInfo);
177370b324cSopenharmony_ci  }
178370b324cSopenharmony_ci}
179370b324cSopenharmony_ci
180370b324cSopenharmony_ci#ifndef Z7_SFX
181370b324cSopenharmony_ci
182370b324cSopenharmony_cistatic bool ParseSignatures(const Byte *data, unsigned size, CObjectVector<CByteBuffer> &signatures)
183370b324cSopenharmony_ci{
184370b324cSopenharmony_ci  signatures.Clear();
185370b324cSopenharmony_ci  while (size != 0)
186370b324cSopenharmony_ci  {
187370b324cSopenharmony_ci    const unsigned len = *data++;
188370b324cSopenharmony_ci    size--;
189370b324cSopenharmony_ci    if (len > size)
190370b324cSopenharmony_ci      return false;
191370b324cSopenharmony_ci    signatures.AddNew().CopyFrom(data, len);
192370b324cSopenharmony_ci    data += len;
193370b324cSopenharmony_ci    size -= len;
194370b324cSopenharmony_ci  }
195370b324cSopenharmony_ci  return true;
196370b324cSopenharmony_ci}
197370b324cSopenharmony_ci
198370b324cSopenharmony_ci#endif // Z7_SFX
199370b324cSopenharmony_ci
200370b324cSopenharmony_ci// #include <stdio.h>
201370b324cSopenharmony_ci
202370b324cSopenharmony_ci#ifdef Z7_EXTERNAL_CODECS
203370b324cSopenharmony_ci
204370b324cSopenharmony_cistatic FString GetBaseFolderPrefixFromRegistry()
205370b324cSopenharmony_ci{
206370b324cSopenharmony_ci  FString moduleFolderPrefix = NDLL::GetModuleDirPrefix();
207370b324cSopenharmony_ci
208370b324cSopenharmony_ci  #ifdef _WIN32
209370b324cSopenharmony_ci  if (   !NFind::DoesFileOrDirExist(moduleFolderPrefix + kMainDll)
210370b324cSopenharmony_ci      && !NFind::DoesFileOrDirExist(moduleFolderPrefix + kCodecsFolderName)
211370b324cSopenharmony_ci      && !NFind::DoesFileOrDirExist(moduleFolderPrefix + kFormatsFolderName))
212370b324cSopenharmony_ci  {
213370b324cSopenharmony_ci    FString path;
214370b324cSopenharmony_ci    if (ReadPathFromRegistry(HKEY_CURRENT_USER,  kProgramPath2Value, path)) return path;
215370b324cSopenharmony_ci    if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPath2Value, path)) return path;
216370b324cSopenharmony_ci    if (ReadPathFromRegistry(HKEY_CURRENT_USER,  kProgramPathValue,  path)) return path;
217370b324cSopenharmony_ci    if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPathValue,  path)) return path;
218370b324cSopenharmony_ci  }
219370b324cSopenharmony_ci  #endif
220370b324cSopenharmony_ci
221370b324cSopenharmony_ci  // printf("\nmoduleFolderPrefix = %s\n", (const char *)GetAnsiString(moduleFolderPrefix));
222370b324cSopenharmony_ci  return moduleFolderPrefix;
223370b324cSopenharmony_ci}
224370b324cSopenharmony_ci
225370b324cSopenharmony_ci
226370b324cSopenharmony_cistatic HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 index,
227370b324cSopenharmony_ci    PROPID propId, CLSID &clsId, bool &isAssigned)
228370b324cSopenharmony_ci{
229370b324cSopenharmony_ci  NCOM::CPropVariant prop;
230370b324cSopenharmony_ci  isAssigned = false;
231370b324cSopenharmony_ci  RINOK(getMethodProperty(index, propId, &prop))
232370b324cSopenharmony_ci  if (prop.vt == VT_BSTR)
233370b324cSopenharmony_ci  {
234370b324cSopenharmony_ci    if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID))
235370b324cSopenharmony_ci      return E_FAIL;
236370b324cSopenharmony_ci    isAssigned = true;
237370b324cSopenharmony_ci    clsId = *(const GUID *)(const void *)prop.bstrVal;
238370b324cSopenharmony_ci  }
239370b324cSopenharmony_ci  else if (prop.vt != VT_EMPTY)
240370b324cSopenharmony_ci    return E_FAIL;
241370b324cSopenharmony_ci  return S_OK;
242370b324cSopenharmony_ci}
243370b324cSopenharmony_ci
244370b324cSopenharmony_ci
245370b324cSopenharmony_cistatic HRESULT GetMethodBoolProp(Func_GetMethodProperty getMethodProperty, UInt32 index,
246370b324cSopenharmony_ci    PROPID propId, bool &resVal, bool &isAssigned)
247370b324cSopenharmony_ci{
248370b324cSopenharmony_ci  NCOM::CPropVariant prop;
249370b324cSopenharmony_ci  resVal = false;
250370b324cSopenharmony_ci  isAssigned = false;
251370b324cSopenharmony_ci  RINOK(getMethodProperty(index, propId, &prop))
252370b324cSopenharmony_ci  if (prop.vt == VT_BOOL)
253370b324cSopenharmony_ci  {
254370b324cSopenharmony_ci    isAssigned = true;
255370b324cSopenharmony_ci    resVal = VARIANT_BOOLToBool(prop.boolVal);
256370b324cSopenharmony_ci  }
257370b324cSopenharmony_ci  else if (prop.vt != VT_EMPTY)
258370b324cSopenharmony_ci    return E_FAIL;
259370b324cSopenharmony_ci  return S_OK;
260370b324cSopenharmony_ci}
261370b324cSopenharmony_ci
262370b324cSopenharmony_ci#if defined(__clang__)
263370b324cSopenharmony_ci#pragma GCC diagnostic ignored "-Wc++98-compat-pedantic"
264370b324cSopenharmony_ci#endif
265370b324cSopenharmony_ci
266370b324cSopenharmony_ci#define MY_GET_FUNC(dest, type, lib, func)  \
267370b324cSopenharmony_ci  dest = Z7_GET_PROC_ADDRESS(type, lib.Get_HMODULE(), func);
268370b324cSopenharmony_ci// #define MY_GET_FUNC(dest, type, func)  dest = (type)(func);
269370b324cSopenharmony_ci
270370b324cSopenharmony_ci#define MY_GET_FUNC_LOC(dest, type, lib, func) \
271370b324cSopenharmony_ci  type dest;  MY_GET_FUNC(dest, type, lib, func)
272370b324cSopenharmony_ci
273370b324cSopenharmony_ciHRESULT CCodecs::LoadCodecs()
274370b324cSopenharmony_ci{
275370b324cSopenharmony_ci  CCodecLib &lib = Libs.Back();
276370b324cSopenharmony_ci
277370b324cSopenharmony_ci  MY_GET_FUNC (lib.CreateDecoder,     Func_CreateDecoder,     lib.Lib, "CreateDecoder")
278370b324cSopenharmony_ci  MY_GET_FUNC (lib.CreateEncoder,     Func_CreateEncoder,     lib.Lib, "CreateEncoder")
279370b324cSopenharmony_ci  MY_GET_FUNC (lib.GetMethodProperty, Func_GetMethodProperty, lib.Lib, "GetMethodProperty")
280370b324cSopenharmony_ci
281370b324cSopenharmony_ci  if (lib.GetMethodProperty)
282370b324cSopenharmony_ci  {
283370b324cSopenharmony_ci    UInt32 numMethods = 1;
284370b324cSopenharmony_ci    MY_GET_FUNC_LOC (getNumberOfMethods, Func_GetNumberOfMethods, lib.Lib, "GetNumberOfMethods")
285370b324cSopenharmony_ci    if (getNumberOfMethods)
286370b324cSopenharmony_ci    {
287370b324cSopenharmony_ci      RINOK(getNumberOfMethods(&numMethods))
288370b324cSopenharmony_ci    }
289370b324cSopenharmony_ci    for (UInt32 i = 0; i < numMethods; i++)
290370b324cSopenharmony_ci    {
291370b324cSopenharmony_ci      CDllCodecInfo info;
292370b324cSopenharmony_ci      info.LibIndex = Libs.Size() - 1;
293370b324cSopenharmony_ci      info.CodecIndex = i;
294370b324cSopenharmony_ci      RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned))
295370b324cSopenharmony_ci      RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned))
296370b324cSopenharmony_ci      RINOK(GetMethodBoolProp(lib.GetMethodProperty, i, NMethodPropID::kIsFilter, info.IsFilter, info.IsFilter_Assigned))
297370b324cSopenharmony_ci      Codecs.Add(info);
298370b324cSopenharmony_ci    }
299370b324cSopenharmony_ci  }
300370b324cSopenharmony_ci
301370b324cSopenharmony_ci  MY_GET_FUNC_LOC (getHashers, Func_GetHashers, lib.Lib, "GetHashers")
302370b324cSopenharmony_ci  if (getHashers)
303370b324cSopenharmony_ci  {
304370b324cSopenharmony_ci    RINOK(getHashers(&lib.ComHashers))
305370b324cSopenharmony_ci    if (lib.ComHashers)
306370b324cSopenharmony_ci    {
307370b324cSopenharmony_ci      UInt32 numMethods = lib.ComHashers->GetNumHashers();
308370b324cSopenharmony_ci      for (UInt32 i = 0; i < numMethods; i++)
309370b324cSopenharmony_ci      {
310370b324cSopenharmony_ci        CDllHasherInfo info;
311370b324cSopenharmony_ci        info.LibIndex = Libs.Size() - 1;
312370b324cSopenharmony_ci        info.HasherIndex = i;
313370b324cSopenharmony_ci        Hashers.Add(info);
314370b324cSopenharmony_ci      }
315370b324cSopenharmony_ci    }
316370b324cSopenharmony_ci  }
317370b324cSopenharmony_ci
318370b324cSopenharmony_ci  return S_OK;
319370b324cSopenharmony_ci}
320370b324cSopenharmony_ci
321370b324cSopenharmony_cistatic HRESULT GetProp(
322370b324cSopenharmony_ci    Func_GetHandlerProperty getProp,
323370b324cSopenharmony_ci    Func_GetHandlerProperty2 getProp2,
324370b324cSopenharmony_ci    UInt32 index, PROPID propID, NCOM::CPropVariant &prop)
325370b324cSopenharmony_ci{
326370b324cSopenharmony_ci  if (getProp2)
327370b324cSopenharmony_ci    return getProp2(index, propID, &prop);
328370b324cSopenharmony_ci  return getProp(propID, &prop);
329370b324cSopenharmony_ci}
330370b324cSopenharmony_ci
331370b324cSopenharmony_cistatic HRESULT GetProp_Bool(
332370b324cSopenharmony_ci    Func_GetHandlerProperty getProp,
333370b324cSopenharmony_ci    Func_GetHandlerProperty2 getProp2,
334370b324cSopenharmony_ci    UInt32 index, PROPID propID, bool &res)
335370b324cSopenharmony_ci{
336370b324cSopenharmony_ci  res = false;
337370b324cSopenharmony_ci  NCOM::CPropVariant prop;
338370b324cSopenharmony_ci  RINOK(GetProp(getProp, getProp2, index, propID, prop))
339370b324cSopenharmony_ci  if (prop.vt == VT_BOOL)
340370b324cSopenharmony_ci    res = VARIANT_BOOLToBool(prop.boolVal);
341370b324cSopenharmony_ci  else if (prop.vt != VT_EMPTY)
342370b324cSopenharmony_ci    return E_FAIL;
343370b324cSopenharmony_ci  return S_OK;
344370b324cSopenharmony_ci}
345370b324cSopenharmony_ci
346370b324cSopenharmony_cistatic HRESULT GetProp_UInt32(
347370b324cSopenharmony_ci    Func_GetHandlerProperty getProp,
348370b324cSopenharmony_ci    Func_GetHandlerProperty2 getProp2,
349370b324cSopenharmony_ci    UInt32 index, PROPID propID, UInt32 &res, bool &defined)
350370b324cSopenharmony_ci{
351370b324cSopenharmony_ci  res = 0;
352370b324cSopenharmony_ci  defined = false;
353370b324cSopenharmony_ci  NCOM::CPropVariant prop;
354370b324cSopenharmony_ci  RINOK(GetProp(getProp, getProp2, index, propID, prop))
355370b324cSopenharmony_ci  if (prop.vt == VT_UI4)
356370b324cSopenharmony_ci  {
357370b324cSopenharmony_ci    res = prop.ulVal;
358370b324cSopenharmony_ci    defined = true;
359370b324cSopenharmony_ci  }
360370b324cSopenharmony_ci  else if (prop.vt != VT_EMPTY)
361370b324cSopenharmony_ci    return E_FAIL;
362370b324cSopenharmony_ci  return S_OK;
363370b324cSopenharmony_ci}
364370b324cSopenharmony_ci
365370b324cSopenharmony_cistatic HRESULT GetProp_String(
366370b324cSopenharmony_ci    Func_GetHandlerProperty getProp,
367370b324cSopenharmony_ci    Func_GetHandlerProperty2 getProp2,
368370b324cSopenharmony_ci    UInt32 index, PROPID propID, UString &res)
369370b324cSopenharmony_ci{
370370b324cSopenharmony_ci  res.Empty();
371370b324cSopenharmony_ci  NCOM::CPropVariant prop;
372370b324cSopenharmony_ci  RINOK(GetProp(getProp, getProp2, index, propID, prop))
373370b324cSopenharmony_ci  if (prop.vt == VT_BSTR)
374370b324cSopenharmony_ci    res.SetFromBstr(prop.bstrVal);
375370b324cSopenharmony_ci  else if (prop.vt != VT_EMPTY)
376370b324cSopenharmony_ci    return E_FAIL;
377370b324cSopenharmony_ci  return S_OK;
378370b324cSopenharmony_ci}
379370b324cSopenharmony_ci
380370b324cSopenharmony_cistatic HRESULT GetProp_RawData(
381370b324cSopenharmony_ci    Func_GetHandlerProperty getProp,
382370b324cSopenharmony_ci    Func_GetHandlerProperty2 getProp2,
383370b324cSopenharmony_ci    UInt32 index, PROPID propID, CByteBuffer &bb)
384370b324cSopenharmony_ci{
385370b324cSopenharmony_ci  bb.Free();
386370b324cSopenharmony_ci  NCOM::CPropVariant prop;
387370b324cSopenharmony_ci  RINOK(GetProp(getProp, getProp2, index, propID, prop))
388370b324cSopenharmony_ci  if (prop.vt == VT_BSTR)
389370b324cSopenharmony_ci  {
390370b324cSopenharmony_ci    UINT len = ::SysStringByteLen(prop.bstrVal);
391370b324cSopenharmony_ci    bb.CopyFrom((const Byte *)prop.bstrVal, len);
392370b324cSopenharmony_ci  }
393370b324cSopenharmony_ci  else if (prop.vt != VT_EMPTY)
394370b324cSopenharmony_ci    return E_FAIL;
395370b324cSopenharmony_ci  return S_OK;
396370b324cSopenharmony_ci}
397370b324cSopenharmony_ci
398370b324cSopenharmony_cistatic const UInt32 kArcFlagsPars[] =
399370b324cSopenharmony_ci{
400370b324cSopenharmony_ci  NArchive::NHandlerPropID::kKeepName, NArcInfoFlags::kKeepName,
401370b324cSopenharmony_ci  NArchive::NHandlerPropID::kAltStreams, NArcInfoFlags::kAltStreams,
402370b324cSopenharmony_ci  NArchive::NHandlerPropID::kNtSecure, NArcInfoFlags::kNtSecure
403370b324cSopenharmony_ci};
404370b324cSopenharmony_ci
405370b324cSopenharmony_ciHRESULT CCodecs::LoadFormats()
406370b324cSopenharmony_ci{
407370b324cSopenharmony_ci  const NDLL::CLibrary &lib = Libs.Back().Lib;
408370b324cSopenharmony_ci
409370b324cSopenharmony_ci  Func_GetHandlerProperty getProp = NULL;
410370b324cSopenharmony_ci  MY_GET_FUNC_LOC (getProp2, Func_GetHandlerProperty2, lib, "GetHandlerProperty2")
411370b324cSopenharmony_ci  MY_GET_FUNC_LOC (getIsArc, Func_GetIsArc, lib, "GetIsArc")
412370b324cSopenharmony_ci
413370b324cSopenharmony_ci  UInt32 numFormats = 1;
414370b324cSopenharmony_ci
415370b324cSopenharmony_ci  if (getProp2)
416370b324cSopenharmony_ci  {
417370b324cSopenharmony_ci    MY_GET_FUNC_LOC (getNumberOfFormats, Func_GetNumberOfFormats, lib, "GetNumberOfFormats")
418370b324cSopenharmony_ci    if (getNumberOfFormats)
419370b324cSopenharmony_ci    {
420370b324cSopenharmony_ci      RINOK(getNumberOfFormats(&numFormats))
421370b324cSopenharmony_ci    }
422370b324cSopenharmony_ci  }
423370b324cSopenharmony_ci  else
424370b324cSopenharmony_ci  {
425370b324cSopenharmony_ci    MY_GET_FUNC (getProp, Func_GetHandlerProperty, lib, "GetHandlerProperty")
426370b324cSopenharmony_ci    if (!getProp)
427370b324cSopenharmony_ci      return S_OK;
428370b324cSopenharmony_ci  }
429370b324cSopenharmony_ci
430370b324cSopenharmony_ci  for (UInt32 i = 0; i < numFormats; i++)
431370b324cSopenharmony_ci  {
432370b324cSopenharmony_ci    CArcInfoEx item;
433370b324cSopenharmony_ci    item.LibIndex = (int)(Libs.Size() - 1);
434370b324cSopenharmony_ci    item.FormatIndex = i;
435370b324cSopenharmony_ci
436370b324cSopenharmony_ci    RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kName, item.Name))
437370b324cSopenharmony_ci
438370b324cSopenharmony_ci    {
439370b324cSopenharmony_ci      NCOM::CPropVariant prop;
440370b324cSopenharmony_ci      if (GetProp(getProp, getProp2, i, NArchive::NHandlerPropID::kClassID, prop) != S_OK)
441370b324cSopenharmony_ci        continue;
442370b324cSopenharmony_ci      if (prop.vt != VT_BSTR)
443370b324cSopenharmony_ci        continue;
444370b324cSopenharmony_ci      if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID))
445370b324cSopenharmony_ci        return E_FAIL;
446370b324cSopenharmony_ci      item.ClassID = *(const GUID *)(const void *)prop.bstrVal;
447370b324cSopenharmony_ci      prop.Clear();
448370b324cSopenharmony_ci    }
449370b324cSopenharmony_ci
450370b324cSopenharmony_ci    UString ext, addExt;
451370b324cSopenharmony_ci    RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kExtension, ext))
452370b324cSopenharmony_ci    RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kAddExtension, addExt))
453370b324cSopenharmony_ci    item.AddExts(ext, addExt);
454370b324cSopenharmony_ci
455370b324cSopenharmony_ci    GetProp_Bool(getProp, getProp2, i, NArchive::NHandlerPropID::kUpdate, item.UpdateEnabled);
456370b324cSopenharmony_ci    bool flags_Defined = false;
457370b324cSopenharmony_ci    RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kFlags, item.Flags, flags_Defined))
458370b324cSopenharmony_ci    item.NewInterface = flags_Defined;
459370b324cSopenharmony_ci    if (!flags_Defined) // && item.UpdateEnabled
460370b324cSopenharmony_ci    {
461370b324cSopenharmony_ci      // support for DLL version before 9.31:
462370b324cSopenharmony_ci      for (unsigned j = 0; j < Z7_ARRAY_SIZE(kArcFlagsPars); j += 2)
463370b324cSopenharmony_ci      {
464370b324cSopenharmony_ci        bool val = false;
465370b324cSopenharmony_ci        GetProp_Bool(getProp, getProp2, i, kArcFlagsPars[j], val);
466370b324cSopenharmony_ci        if (val)
467370b324cSopenharmony_ci          item.Flags |= kArcFlagsPars[j + 1];
468370b324cSopenharmony_ci      }
469370b324cSopenharmony_ci    }
470370b324cSopenharmony_ci
471370b324cSopenharmony_ci    {
472370b324cSopenharmony_ci      bool defined = false;
473370b324cSopenharmony_ci      RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kTimeFlags, item.TimeFlags, defined))
474370b324cSopenharmony_ci    }
475370b324cSopenharmony_ci
476370b324cSopenharmony_ci    CByteBuffer sig;
477370b324cSopenharmony_ci    RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kSignature, sig))
478370b324cSopenharmony_ci    if (sig.Size() != 0)
479370b324cSopenharmony_ci      item.Signatures.Add(sig);
480370b324cSopenharmony_ci    else
481370b324cSopenharmony_ci    {
482370b324cSopenharmony_ci      RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kMultiSignature, sig))
483370b324cSopenharmony_ci      ParseSignatures(sig, (unsigned)sig.Size(), item.Signatures);
484370b324cSopenharmony_ci    }
485370b324cSopenharmony_ci
486370b324cSopenharmony_ci    bool signatureOffset_Defined;
487370b324cSopenharmony_ci    RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kSignatureOffset, item.SignatureOffset, signatureOffset_Defined))
488370b324cSopenharmony_ci
489370b324cSopenharmony_ci    // bool version_Defined;
490370b324cSopenharmony_ci    // RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kVersion, item.Version, version_Defined));
491370b324cSopenharmony_ci
492370b324cSopenharmony_ci    if (getIsArc)
493370b324cSopenharmony_ci      getIsArc(i, &item.IsArcFunc);
494370b324cSopenharmony_ci
495370b324cSopenharmony_ci    Formats.Add(item);
496370b324cSopenharmony_ci  }
497370b324cSopenharmony_ci  return S_OK;
498370b324cSopenharmony_ci}
499370b324cSopenharmony_ci
500370b324cSopenharmony_ci#ifdef Z7_LARGE_PAGES
501370b324cSopenharmony_ciextern "C"
502370b324cSopenharmony_ci{
503370b324cSopenharmony_ci  extern SIZE_T g_LargePageSize;
504370b324cSopenharmony_ci}
505370b324cSopenharmony_ci#endif
506370b324cSopenharmony_ci
507370b324cSopenharmony_ci
508370b324cSopenharmony_civoid CCodecs::AddLastError(const FString &path)
509370b324cSopenharmony_ci{
510370b324cSopenharmony_ci  const HRESULT res = GetLastError_noZero_HRESULT();
511370b324cSopenharmony_ci  CCodecError &error = Errors.AddNew();
512370b324cSopenharmony_ci  error.Path = path;
513370b324cSopenharmony_ci  error.ErrorCode = res;
514370b324cSopenharmony_ci}
515370b324cSopenharmony_ci
516370b324cSopenharmony_ci
517370b324cSopenharmony_cistatic bool IsSupportedDll(CCodecLib &lib)
518370b324cSopenharmony_ci{
519370b324cSopenharmony_ci  MY_GET_FUNC_LOC (
520370b324cSopenharmony_ci     f_GetModuleProp,
521370b324cSopenharmony_ci  Func_GetModuleProp, lib.Lib,
522370b324cSopenharmony_ci      "GetModuleProp")
523370b324cSopenharmony_ci  /* p7zip and 7-Zip before v23 used virtual destructor in IUnknown,
524370b324cSopenharmony_ci     if _WIN32 is not defined */
525370b324cSopenharmony_ci  UInt32 flags =
526370b324cSopenharmony_ci    #ifdef _WIN32
527370b324cSopenharmony_ci      NModuleInterfaceType::k_IUnknown_VirtDestructor_No;
528370b324cSopenharmony_ci    #else
529370b324cSopenharmony_ci      NModuleInterfaceType::k_IUnknown_VirtDestructor_Yes;
530370b324cSopenharmony_ci    #endif
531370b324cSopenharmony_ci  if (f_GetModuleProp)
532370b324cSopenharmony_ci  {
533370b324cSopenharmony_ci    {
534370b324cSopenharmony_ci      NCOM::CPropVariant prop;
535370b324cSopenharmony_ci      if (f_GetModuleProp(NModulePropID::kInterfaceType, &prop) == S_OK)
536370b324cSopenharmony_ci      {
537370b324cSopenharmony_ci        if (prop.vt == VT_UI4)
538370b324cSopenharmony_ci          flags = prop.ulVal;
539370b324cSopenharmony_ci        else if (prop.vt != VT_EMPTY)
540370b324cSopenharmony_ci          return false;
541370b324cSopenharmony_ci      }
542370b324cSopenharmony_ci    }
543370b324cSopenharmony_ci    {
544370b324cSopenharmony_ci      NCOM::CPropVariant prop;
545370b324cSopenharmony_ci      if (f_GetModuleProp(NModulePropID::kVersion, &prop) == S_OK)
546370b324cSopenharmony_ci      {
547370b324cSopenharmony_ci        if (prop.vt == VT_UI4)
548370b324cSopenharmony_ci          lib.Version = prop.ulVal;
549370b324cSopenharmony_ci      }
550370b324cSopenharmony_ci    }
551370b324cSopenharmony_ci  }
552370b324cSopenharmony_ci  if (
553370b324cSopenharmony_ci      flags
554370b324cSopenharmony_ci      // (flags & NModuleFlags::kMask)
555370b324cSopenharmony_ci      != NModuleInterfaceType::k_IUnknown_VirtDestructor_ThisModule)
556370b324cSopenharmony_ci    return false;
557370b324cSopenharmony_ci  return true;
558370b324cSopenharmony_ci}
559370b324cSopenharmony_ci
560370b324cSopenharmony_ci
561370b324cSopenharmony_ciHRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loadedOK)
562370b324cSopenharmony_ci{
563370b324cSopenharmony_ci  if (loadedOK)
564370b324cSopenharmony_ci    *loadedOK = false;
565370b324cSopenharmony_ci
566370b324cSopenharmony_ci  // needCheckDll = 1;
567370b324cSopenharmony_ci
568370b324cSopenharmony_ci  #ifdef _WIN32
569370b324cSopenharmony_ci  if (needCheckDll)
570370b324cSopenharmony_ci  {
571370b324cSopenharmony_ci    NDLL::CLibrary lib;
572370b324cSopenharmony_ci    if (!lib.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE))
573370b324cSopenharmony_ci    {
574370b324cSopenharmony_ci      /* if is not win32
575370b324cSopenharmony_ci      //  %1 is not a valid Win32 application.
576370b324cSopenharmony_ci      //  #define ERROR_BAD_EXE_FORMAT             193L
577370b324cSopenharmony_ci      */
578370b324cSopenharmony_ci      // return GetLastError_noZero_HRESULT();
579370b324cSopenharmony_ci      const DWORD lastError = GetLastError();
580370b324cSopenharmony_ci      if (lastError != ERROR_BAD_EXE_FORMAT)
581370b324cSopenharmony_ci      {
582370b324cSopenharmony_ci        CCodecError &error = Errors.AddNew();
583370b324cSopenharmony_ci        error.Path = dllPath;
584370b324cSopenharmony_ci        error.Message = "cannot load file as datafile library";
585370b324cSopenharmony_ci        error.ErrorCode = HRESULT_FROM_WIN32(lastError);
586370b324cSopenharmony_ci      }
587370b324cSopenharmony_ci      return S_OK;
588370b324cSopenharmony_ci    }
589370b324cSopenharmony_ci  }
590370b324cSopenharmony_ci  #else
591370b324cSopenharmony_ci  UNUSED_VAR(needCheckDll)
592370b324cSopenharmony_ci  #endif
593370b324cSopenharmony_ci
594370b324cSopenharmony_ci  Libs.AddNew();
595370b324cSopenharmony_ci  CCodecLib &lib = Libs.Back();
596370b324cSopenharmony_ci  lib.Path = dllPath;
597370b324cSopenharmony_ci  bool used = false;
598370b324cSopenharmony_ci  // HRESULT res = S_OK;
599370b324cSopenharmony_ci
600370b324cSopenharmony_ci if (lib.Lib.Load(dllPath))
601370b324cSopenharmony_ci {
602370b324cSopenharmony_ci  if (!IsSupportedDll(lib))
603370b324cSopenharmony_ci  {
604370b324cSopenharmony_ci    CCodecError &error = Errors.AddNew();
605370b324cSopenharmony_ci    error.Path = dllPath;
606370b324cSopenharmony_ci    error.Message = "the module is not compatible with program";
607370b324cSopenharmony_ci  }
608370b324cSopenharmony_ci  else
609370b324cSopenharmony_ci  {
610370b324cSopenharmony_ci    if (loadedOK)
611370b324cSopenharmony_ci      *loadedOK = true;
612370b324cSopenharmony_ci    /*
613370b324cSopenharmony_ci    #ifdef NEW_FOLDER_INTERFACE
614370b324cSopenharmony_ci    lib.LoadIcons();
615370b324cSopenharmony_ci    #endif
616370b324cSopenharmony_ci    */
617370b324cSopenharmony_ci
618370b324cSopenharmony_ci    /*
619370b324cSopenharmony_ci    {
620370b324cSopenharmony_ci      MY_GET_FUNC_LOC (_libStartup, Func_libStartup, lib.Lib, "LibStartup")
621370b324cSopenharmony_ci      if (_libStartup)
622370b324cSopenharmony_ci      {
623370b324cSopenharmony_ci        HRESULT res = _libStartup();
624370b324cSopenharmony_ci        if (res != 0)
625370b324cSopenharmony_ci        {
626370b324cSopenharmony_ci          CCodecError &error = Errors.AddNew();
627370b324cSopenharmony_ci          error.Path = dllPath;
628370b324cSopenharmony_ci          error.ErrorCode = res;
629370b324cSopenharmony_ci        }
630370b324cSopenharmony_ci      }
631370b324cSopenharmony_ci    }
632370b324cSopenharmony_ci    */
633370b324cSopenharmony_ci
634370b324cSopenharmony_ci    #ifdef Z7_LARGE_PAGES
635370b324cSopenharmony_ci    if (g_LargePageSize != 0)
636370b324cSopenharmony_ci    {
637370b324cSopenharmony_ci      MY_GET_FUNC_LOC (setLargePageMode, Func_SetLargePageMode, lib.Lib, "SetLargePageMode")
638370b324cSopenharmony_ci      if (setLargePageMode)
639370b324cSopenharmony_ci        setLargePageMode();
640370b324cSopenharmony_ci    }
641370b324cSopenharmony_ci    #endif
642370b324cSopenharmony_ci
643370b324cSopenharmony_ci    if (CaseSensitive_Change)
644370b324cSopenharmony_ci    {
645370b324cSopenharmony_ci      MY_GET_FUNC_LOC (setCaseSensitive, Func_SetCaseSensitive, lib.Lib, "SetCaseSensitive")
646370b324cSopenharmony_ci      if (setCaseSensitive)
647370b324cSopenharmony_ci        setCaseSensitive(CaseSensitive ? 1 : 0);
648370b324cSopenharmony_ci    }
649370b324cSopenharmony_ci
650370b324cSopenharmony_ci    /*
651370b324cSopenharmony_ci    {
652370b324cSopenharmony_ci      MY_GET_FUNC_LOC (setClientVersion, Func_SetClientVersion, lib.Lib, "SetClientVersion")
653370b324cSopenharmony_ci      if (setClientVersion)
654370b324cSopenharmony_ci      {
655370b324cSopenharmony_ci        // const UInt32 kVersion = (MY_VER_MAJOR << 16) | MY_VER_MINOR;
656370b324cSopenharmony_ci        setClientVersion(g_ClientVersion);
657370b324cSopenharmony_ci      }
658370b324cSopenharmony_ci    }
659370b324cSopenharmony_ci    */
660370b324cSopenharmony_ci
661370b324cSopenharmony_ci
662370b324cSopenharmony_ci    MY_GET_FUNC (lib.CreateObject, Func_CreateObject, lib.Lib, "CreateObject")
663370b324cSopenharmony_ci    {
664370b324cSopenharmony_ci      unsigned startSize = Codecs.Size() + Hashers.Size();
665370b324cSopenharmony_ci      HRESULT res = LoadCodecs();
666370b324cSopenharmony_ci      if (startSize != Codecs.Size() + Hashers.Size())
667370b324cSopenharmony_ci        used = true;
668370b324cSopenharmony_ci      if (res == S_OK && lib.CreateObject)
669370b324cSopenharmony_ci      {
670370b324cSopenharmony_ci        startSize = Formats.Size();
671370b324cSopenharmony_ci        res = LoadFormats();
672370b324cSopenharmony_ci        if (startSize != Formats.Size())
673370b324cSopenharmony_ci          used = true;
674370b324cSopenharmony_ci      }
675370b324cSopenharmony_ci      if (res != S_OK)
676370b324cSopenharmony_ci      {
677370b324cSopenharmony_ci        CCodecError &error = Errors.AddNew();
678370b324cSopenharmony_ci        error.Path = dllPath;
679370b324cSopenharmony_ci        error.ErrorCode = res;
680370b324cSopenharmony_ci      }
681370b324cSopenharmony_ci    }
682370b324cSopenharmony_ci    // plugins can use non-7-zip dlls, so we silently ignore non7zip DLLs
683370b324cSopenharmony_ci    /*
684370b324cSopenharmony_ci    if (!used)
685370b324cSopenharmony_ci    {
686370b324cSopenharmony_ci      CCodecError &error = Errors.AddNew();
687370b324cSopenharmony_ci      error.Path = dllPath;
688370b324cSopenharmony_ci      error.Message = "no 7-Zip code";
689370b324cSopenharmony_ci    }
690370b324cSopenharmony_ci    */
691370b324cSopenharmony_ci  }
692370b324cSopenharmony_ci }
693370b324cSopenharmony_ci else
694370b324cSopenharmony_ci  {
695370b324cSopenharmony_ci    AddLastError(dllPath);
696370b324cSopenharmony_ci  }
697370b324cSopenharmony_ci
698370b324cSopenharmony_ci  if (!used)
699370b324cSopenharmony_ci    Libs.DeleteBack();
700370b324cSopenharmony_ci
701370b324cSopenharmony_ci  return S_OK;
702370b324cSopenharmony_ci}
703370b324cSopenharmony_ci
704370b324cSopenharmony_ciHRESULT CCodecs::LoadDllsFromFolder(const FString &folderPath)
705370b324cSopenharmony_ci{
706370b324cSopenharmony_ci  if (!NFile::NFind::DoesDirExist_FollowLink(folderPath))
707370b324cSopenharmony_ci  // if (!NFile::NFind::DoesDirExist(folderPath))
708370b324cSopenharmony_ci  {
709370b324cSopenharmony_ci    // AddLastError(folderPath);
710370b324cSopenharmony_ci    return S_OK;
711370b324cSopenharmony_ci  }
712370b324cSopenharmony_ci
713370b324cSopenharmony_ci  FString folderPrefix = folderPath;
714370b324cSopenharmony_ci  folderPrefix.Add_PathSepar();
715370b324cSopenharmony_ci
716370b324cSopenharmony_ci  NFile::NFind::CEnumerator enumerator;
717370b324cSopenharmony_ci  enumerator.SetDirPrefix(folderPrefix);
718370b324cSopenharmony_ci  NFile::NFind::CDirEntry fi;
719370b324cSopenharmony_ci  for (;;)
720370b324cSopenharmony_ci  {
721370b324cSopenharmony_ci    bool found;
722370b324cSopenharmony_ci    if (!enumerator.Next(fi, found))
723370b324cSopenharmony_ci    {
724370b324cSopenharmony_ci      // it can be wrong Symbolic link to folder here
725370b324cSopenharmony_ci      AddLastError(folderPath);
726370b324cSopenharmony_ci      break;
727370b324cSopenharmony_ci      // return GetLastError_noZero_HRESULT();
728370b324cSopenharmony_ci    }
729370b324cSopenharmony_ci    if (!found)
730370b324cSopenharmony_ci      break;
731370b324cSopenharmony_ci    #ifdef _WIN32
732370b324cSopenharmony_ci    if (fi.IsDir())
733370b324cSopenharmony_ci      continue;
734370b324cSopenharmony_ci    #else
735370b324cSopenharmony_ci    if (enumerator.DirEntry_IsDir(fi, true)) // followLink
736370b324cSopenharmony_ci      continue;
737370b324cSopenharmony_ci    #endif
738370b324cSopenharmony_ci
739370b324cSopenharmony_ci    RINOK(LoadDll(folderPrefix + fi.Name, true))
740370b324cSopenharmony_ci  }
741370b324cSopenharmony_ci  return S_OK;
742370b324cSopenharmony_ci}
743370b324cSopenharmony_ci
744370b324cSopenharmony_civoid CCodecs::CloseLibs()
745370b324cSopenharmony_ci{
746370b324cSopenharmony_ci  // OutputDebugStringA("~CloseLibs start");
747370b324cSopenharmony_ci  /*
748370b324cSopenharmony_ci  WIN32: FreeLibrary() (CLibrary::Free()) function doesn't work as expected,
749370b324cSopenharmony_ci  if it's called from another FreeLibrary() call.
750370b324cSopenharmony_ci  So we need to call FreeLibrary() before global destructors.
751370b324cSopenharmony_ci
752370b324cSopenharmony_ci  Also we free global links from DLLs to object of this module before CLibrary::Free() call.
753370b324cSopenharmony_ci  */
754370b324cSopenharmony_ci
755370b324cSopenharmony_ci  FOR_VECTOR(i, Libs)
756370b324cSopenharmony_ci  {
757370b324cSopenharmony_ci    const CCodecLib &lib = Libs[i];
758370b324cSopenharmony_ci    if (lib.SetCodecs)
759370b324cSopenharmony_ci      lib.SetCodecs(NULL);
760370b324cSopenharmony_ci  }
761370b324cSopenharmony_ci
762370b324cSopenharmony_ci  // OutputDebugStringA("~CloseLibs after SetCodecs");
763370b324cSopenharmony_ci  Libs.Clear();
764370b324cSopenharmony_ci  // OutputDebugStringA("~CloseLibs end");
765370b324cSopenharmony_ci}
766370b324cSopenharmony_ci
767370b324cSopenharmony_ci#endif // Z7_EXTERNAL_CODECS
768370b324cSopenharmony_ci
769370b324cSopenharmony_ci
770370b324cSopenharmony_ciHRESULT CCodecs::Load()
771370b324cSopenharmony_ci{
772370b324cSopenharmony_ci  /*
773370b324cSopenharmony_ci  #ifdef NEW_FOLDER_INTERFACE
774370b324cSopenharmony_ci  InternalIcons.LoadIcons(g_hInstance);
775370b324cSopenharmony_ci  #endif
776370b324cSopenharmony_ci  */
777370b324cSopenharmony_ci
778370b324cSopenharmony_ci  Formats.Clear();
779370b324cSopenharmony_ci
780370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
781370b324cSopenharmony_ci    Errors.Clear();
782370b324cSopenharmony_ci    MainDll_ErrorPath.Empty();
783370b324cSopenharmony_ci    Codecs.Clear();
784370b324cSopenharmony_ci    Hashers.Clear();
785370b324cSopenharmony_ci  #endif
786370b324cSopenharmony_ci
787370b324cSopenharmony_ci  for (UInt32 i = 0; i < g_NumArcs; i++)
788370b324cSopenharmony_ci  {
789370b324cSopenharmony_ci    const CArcInfo &arc = *g_Arcs[i];
790370b324cSopenharmony_ci    CArcInfoEx item;
791370b324cSopenharmony_ci
792370b324cSopenharmony_ci    item.Name = arc.Name;
793370b324cSopenharmony_ci    item.CreateInArchive = arc.CreateInArchive;
794370b324cSopenharmony_ci    item.IsArcFunc = arc.IsArc;
795370b324cSopenharmony_ci    item.Flags = arc.Flags;
796370b324cSopenharmony_ci
797370b324cSopenharmony_ci    {
798370b324cSopenharmony_ci      UString e, ae;
799370b324cSopenharmony_ci      if (arc.Ext)
800370b324cSopenharmony_ci        e = arc.Ext;
801370b324cSopenharmony_ci      if (arc.AddExt)
802370b324cSopenharmony_ci        ae = arc.AddExt;
803370b324cSopenharmony_ci      item.AddExts(e, ae);
804370b324cSopenharmony_ci    }
805370b324cSopenharmony_ci
806370b324cSopenharmony_ci    #ifndef Z7_SFX
807370b324cSopenharmony_ci
808370b324cSopenharmony_ci    item.CreateOutArchive = arc.CreateOutArchive;
809370b324cSopenharmony_ci    item.UpdateEnabled = (arc.CreateOutArchive != NULL);
810370b324cSopenharmony_ci    item.SignatureOffset = arc.SignatureOffset;
811370b324cSopenharmony_ci    // item.Version = MY_VER_MIX;
812370b324cSopenharmony_ci    item.NewInterface = true;
813370b324cSopenharmony_ci
814370b324cSopenharmony_ci    if (arc.IsMultiSignature())
815370b324cSopenharmony_ci      ParseSignatures(arc.Signature, arc.SignatureSize, item.Signatures);
816370b324cSopenharmony_ci    else
817370b324cSopenharmony_ci    {
818370b324cSopenharmony_ci      if (arc.SignatureSize != 0) // 21.04
819370b324cSopenharmony_ci        item.Signatures.AddNew().CopyFrom(arc.Signature, arc.SignatureSize);
820370b324cSopenharmony_ci    }
821370b324cSopenharmony_ci
822370b324cSopenharmony_ci    #endif
823370b324cSopenharmony_ci
824370b324cSopenharmony_ci    Formats.Add(item);
825370b324cSopenharmony_ci  }
826370b324cSopenharmony_ci
827370b324cSopenharmony_ci  // printf("\nLoad codecs \n");
828370b324cSopenharmony_ci
829370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
830370b324cSopenharmony_ci    const FString baseFolder = GetBaseFolderPrefixFromRegistry();
831370b324cSopenharmony_ci    {
832370b324cSopenharmony_ci      bool loadedOK;
833370b324cSopenharmony_ci      RINOK(LoadDll(baseFolder + kMainDll, false, &loadedOK))
834370b324cSopenharmony_ci      if (!loadedOK)
835370b324cSopenharmony_ci        MainDll_ErrorPath = kMainDll;
836370b324cSopenharmony_ci    }
837370b324cSopenharmony_ci    RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName))
838370b324cSopenharmony_ci    RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName))
839370b324cSopenharmony_ci
840370b324cSopenharmony_ci  NeedSetLibCodecs = true;
841370b324cSopenharmony_ci
842370b324cSopenharmony_ci  if (Libs.Size() == 0)
843370b324cSopenharmony_ci    NeedSetLibCodecs = false;
844370b324cSopenharmony_ci  else if (Libs.Size() == 1)
845370b324cSopenharmony_ci  {
846370b324cSopenharmony_ci    // we don't need to set ISetCompressCodecsInfo, if all arcs and codecs are in one external module.
847370b324cSopenharmony_ci    #ifndef EXPORT_CODECS
848370b324cSopenharmony_ci    if (g_NumArcs == 0)
849370b324cSopenharmony_ci      NeedSetLibCodecs = false;
850370b324cSopenharmony_ci    #endif
851370b324cSopenharmony_ci  }
852370b324cSopenharmony_ci
853370b324cSopenharmony_ci  if (NeedSetLibCodecs)
854370b324cSopenharmony_ci  {
855370b324cSopenharmony_ci    /* 15.00: now we call global function in DLL: SetCompressCodecsInfo(c)
856370b324cSopenharmony_ci       old versions called only ISetCompressCodecsInfo::SetCompressCodecsInfo(c) for each archive handler */
857370b324cSopenharmony_ci
858370b324cSopenharmony_ci    FOR_VECTOR(i, Libs)
859370b324cSopenharmony_ci    {
860370b324cSopenharmony_ci      CCodecLib &lib = Libs[i];
861370b324cSopenharmony_ci      MY_GET_FUNC (lib.SetCodecs, Func_SetCodecs, lib.Lib, "SetCodecs")
862370b324cSopenharmony_ci      if (lib.SetCodecs)
863370b324cSopenharmony_ci      {
864370b324cSopenharmony_ci        RINOK(lib.SetCodecs(this))
865370b324cSopenharmony_ci      }
866370b324cSopenharmony_ci    }
867370b324cSopenharmony_ci  }
868370b324cSopenharmony_ci
869370b324cSopenharmony_ci  #endif
870370b324cSopenharmony_ci
871370b324cSopenharmony_ci  // we sort Formats to get fixed order of Formats after compilation.
872370b324cSopenharmony_ci  Formats.Sort();
873370b324cSopenharmony_ci  return S_OK;
874370b324cSopenharmony_ci}
875370b324cSopenharmony_ci
876370b324cSopenharmony_ci#ifndef Z7_SFX
877370b324cSopenharmony_ci
878370b324cSopenharmony_ciint CCodecs::FindFormatForArchiveName(const UString &arcPath) const
879370b324cSopenharmony_ci{
880370b324cSopenharmony_ci  int dotPos = arcPath.ReverseFind_Dot();
881370b324cSopenharmony_ci  if (dotPos <= arcPath.ReverseFind_PathSepar())
882370b324cSopenharmony_ci    return -1;
883370b324cSopenharmony_ci  const UString ext = arcPath.Ptr((unsigned)(dotPos + 1));
884370b324cSopenharmony_ci  if (ext.IsEmpty())
885370b324cSopenharmony_ci    return -1;
886370b324cSopenharmony_ci  if (ext.IsEqualTo_Ascii_NoCase("exe"))
887370b324cSopenharmony_ci    return -1;
888370b324cSopenharmony_ci  FOR_VECTOR (i, Formats)
889370b324cSopenharmony_ci  {
890370b324cSopenharmony_ci    const CArcInfoEx &arc = Formats[i];
891370b324cSopenharmony_ci    /*
892370b324cSopenharmony_ci    if (!arc.UpdateEnabled)
893370b324cSopenharmony_ci      continue;
894370b324cSopenharmony_ci    */
895370b324cSopenharmony_ci    if (arc.FindExtension(ext) >= 0)
896370b324cSopenharmony_ci      return (int)i;
897370b324cSopenharmony_ci  }
898370b324cSopenharmony_ci  return -1;
899370b324cSopenharmony_ci}
900370b324cSopenharmony_ci
901370b324cSopenharmony_ciint CCodecs::FindFormatForExtension(const UString &ext) const
902370b324cSopenharmony_ci{
903370b324cSopenharmony_ci  if (ext.IsEmpty())
904370b324cSopenharmony_ci    return -1;
905370b324cSopenharmony_ci  FOR_VECTOR (i, Formats)
906370b324cSopenharmony_ci    if (Formats[i].FindExtension(ext) >= 0)
907370b324cSopenharmony_ci      return (int)i;
908370b324cSopenharmony_ci  return -1;
909370b324cSopenharmony_ci}
910370b324cSopenharmony_ci
911370b324cSopenharmony_ciint CCodecs::FindFormatForArchiveType(const UString &arcType) const
912370b324cSopenharmony_ci{
913370b324cSopenharmony_ci  FOR_VECTOR (i, Formats)
914370b324cSopenharmony_ci    if (Formats[i].Name.IsEqualTo_NoCase(arcType))
915370b324cSopenharmony_ci      return (int)i;
916370b324cSopenharmony_ci  return -1;
917370b324cSopenharmony_ci}
918370b324cSopenharmony_ci
919370b324cSopenharmony_cibool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const
920370b324cSopenharmony_ci{
921370b324cSopenharmony_ci  formatIndices.Clear();
922370b324cSopenharmony_ci  for (unsigned pos = 0; pos < arcType.Len();)
923370b324cSopenharmony_ci  {
924370b324cSopenharmony_ci    int pos2 = arcType.Find(L'.', pos);
925370b324cSopenharmony_ci    if (pos2 < 0)
926370b324cSopenharmony_ci      pos2 = (int)arcType.Len();
927370b324cSopenharmony_ci    const UString name = arcType.Mid(pos, (unsigned)pos2 - pos);
928370b324cSopenharmony_ci    if (name.IsEmpty())
929370b324cSopenharmony_ci      return false;
930370b324cSopenharmony_ci    int index = FindFormatForArchiveType(name);
931370b324cSopenharmony_ci    if (index < 0 && name != L"*")
932370b324cSopenharmony_ci    {
933370b324cSopenharmony_ci      formatIndices.Clear();
934370b324cSopenharmony_ci      return false;
935370b324cSopenharmony_ci    }
936370b324cSopenharmony_ci    formatIndices.Add(index);
937370b324cSopenharmony_ci    pos = (unsigned)pos2 + 1;
938370b324cSopenharmony_ci  }
939370b324cSopenharmony_ci  return true;
940370b324cSopenharmony_ci}
941370b324cSopenharmony_ci
942370b324cSopenharmony_ci#endif // Z7_SFX
943370b324cSopenharmony_ci
944370b324cSopenharmony_ci
945370b324cSopenharmony_ci#ifdef Z7_EXTERNAL_CODECS
946370b324cSopenharmony_ci
947370b324cSopenharmony_ci// #define EXPORT_CODECS
948370b324cSopenharmony_ci
949370b324cSopenharmony_ci#ifdef EXPORT_CODECS
950370b324cSopenharmony_ci
951370b324cSopenharmony_ciextern unsigned g_NumCodecs;
952370b324cSopenharmony_ciSTDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject);
953370b324cSopenharmony_ciSTDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject);
954370b324cSopenharmony_ciSTDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);
955370b324cSopenharmony_ci#define NUM_EXPORT_CODECS g_NumCodecs
956370b324cSopenharmony_ci
957370b324cSopenharmony_ciextern unsigned g_NumHashers;
958370b324cSopenharmony_ciSTDAPI CreateHasher(UInt32 index, IHasher **hasher);
959370b324cSopenharmony_ciSTDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);
960370b324cSopenharmony_ci#define NUM_EXPORT_HASHERS g_NumHashers
961370b324cSopenharmony_ci
962370b324cSopenharmony_ci#else // EXPORT_CODECS
963370b324cSopenharmony_ci
964370b324cSopenharmony_ci#define NUM_EXPORT_CODECS 0
965370b324cSopenharmony_ci#define NUM_EXPORT_HASHERS 0
966370b324cSopenharmony_ci
967370b324cSopenharmony_ci#endif // EXPORT_CODECS
968370b324cSopenharmony_ci
969370b324cSopenharmony_ciZ7_COM7F_IMF(CCodecs::GetNumMethods(UInt32 *numMethods))
970370b324cSopenharmony_ci{
971370b324cSopenharmony_ci  *numMethods = NUM_EXPORT_CODECS
972370b324cSopenharmony_ci    #ifdef Z7_EXTERNAL_CODECS
973370b324cSopenharmony_ci    + Codecs.Size()
974370b324cSopenharmony_ci    #endif
975370b324cSopenharmony_ci    ;
976370b324cSopenharmony_ci  return S_OK;
977370b324cSopenharmony_ci}
978370b324cSopenharmony_ci
979370b324cSopenharmony_ciZ7_COM7F_IMF(CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
980370b324cSopenharmony_ci{
981370b324cSopenharmony_ci  #ifdef EXPORT_CODECS
982370b324cSopenharmony_ci  if (index < g_NumCodecs)
983370b324cSopenharmony_ci    return GetMethodProperty(index, propID, value);
984370b324cSopenharmony_ci  #endif
985370b324cSopenharmony_ci
986370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
987370b324cSopenharmony_ci  const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
988370b324cSopenharmony_ci
989370b324cSopenharmony_ci  if (propID == NMethodPropID::kDecoderIsAssigned ||
990370b324cSopenharmony_ci      propID == NMethodPropID::kEncoderIsAssigned)
991370b324cSopenharmony_ci  {
992370b324cSopenharmony_ci    NCOM::CPropVariant prop;
993370b324cSopenharmony_ci    prop = (bool)((propID == NMethodPropID::kDecoderIsAssigned) ?
994370b324cSopenharmony_ci        ci.DecoderIsAssigned :
995370b324cSopenharmony_ci        ci.EncoderIsAssigned);
996370b324cSopenharmony_ci    prop.Detach(value);
997370b324cSopenharmony_ci    return S_OK;
998370b324cSopenharmony_ci  }
999370b324cSopenharmony_ci
1000370b324cSopenharmony_ci  if (propID == NMethodPropID::kIsFilter && ci.IsFilter_Assigned)
1001370b324cSopenharmony_ci  {
1002370b324cSopenharmony_ci    NCOM::CPropVariant prop;
1003370b324cSopenharmony_ci    prop = (bool)ci.IsFilter;
1004370b324cSopenharmony_ci    prop.Detach(value);
1005370b324cSopenharmony_ci    return S_OK;
1006370b324cSopenharmony_ci  }
1007370b324cSopenharmony_ci
1008370b324cSopenharmony_ci  const CCodecLib &lib = Libs[ci.LibIndex];
1009370b324cSopenharmony_ci  return lib.GetMethodProperty(ci.CodecIndex, propID, value);
1010370b324cSopenharmony_ci  #else
1011370b324cSopenharmony_ci  return E_FAIL;
1012370b324cSopenharmony_ci  #endif
1013370b324cSopenharmony_ci}
1014370b324cSopenharmony_ci
1015370b324cSopenharmony_ciZ7_COM7F_IMF(CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder))
1016370b324cSopenharmony_ci{
1017370b324cSopenharmony_ci  #ifdef EXPORT_CODECS
1018370b324cSopenharmony_ci  if (index < g_NumCodecs)
1019370b324cSopenharmony_ci    return CreateDecoder(index, iid, coder);
1020370b324cSopenharmony_ci  #endif
1021370b324cSopenharmony_ci
1022370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
1023370b324cSopenharmony_ci  const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
1024370b324cSopenharmony_ci  if (ci.DecoderIsAssigned)
1025370b324cSopenharmony_ci  {
1026370b324cSopenharmony_ci    const CCodecLib &lib = Libs[ci.LibIndex];
1027370b324cSopenharmony_ci    if (lib.CreateDecoder)
1028370b324cSopenharmony_ci      return lib.CreateDecoder(ci.CodecIndex, iid, (void **)coder);
1029370b324cSopenharmony_ci    if (lib.CreateObject)
1030370b324cSopenharmony_ci      return lib.CreateObject(&ci.Decoder, iid, (void **)coder);
1031370b324cSopenharmony_ci  }
1032370b324cSopenharmony_ci  return S_OK;
1033370b324cSopenharmony_ci  #else
1034370b324cSopenharmony_ci  return E_FAIL;
1035370b324cSopenharmony_ci  #endif
1036370b324cSopenharmony_ci}
1037370b324cSopenharmony_ci
1038370b324cSopenharmony_ciZ7_COM7F_IMF(CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder))
1039370b324cSopenharmony_ci{
1040370b324cSopenharmony_ci  #ifdef EXPORT_CODECS
1041370b324cSopenharmony_ci  if (index < g_NumCodecs)
1042370b324cSopenharmony_ci    return CreateEncoder(index, iid, coder);
1043370b324cSopenharmony_ci  #endif
1044370b324cSopenharmony_ci
1045370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
1046370b324cSopenharmony_ci  const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
1047370b324cSopenharmony_ci  if (ci.EncoderIsAssigned)
1048370b324cSopenharmony_ci  {
1049370b324cSopenharmony_ci    const CCodecLib &lib = Libs[ci.LibIndex];
1050370b324cSopenharmony_ci    if (lib.CreateEncoder)
1051370b324cSopenharmony_ci      return lib.CreateEncoder(ci.CodecIndex, iid, (void **)coder);
1052370b324cSopenharmony_ci    if (lib.CreateObject)
1053370b324cSopenharmony_ci      return lib.CreateObject(&ci.Encoder, iid, (void **)coder);
1054370b324cSopenharmony_ci  }
1055370b324cSopenharmony_ci  return S_OK;
1056370b324cSopenharmony_ci  #else
1057370b324cSopenharmony_ci  return E_FAIL;
1058370b324cSopenharmony_ci  #endif
1059370b324cSopenharmony_ci}
1060370b324cSopenharmony_ci
1061370b324cSopenharmony_ci
1062370b324cSopenharmony_ciZ7_COM7F_IMF2(UInt32, CCodecs::GetNumHashers())
1063370b324cSopenharmony_ci{
1064370b324cSopenharmony_ci  return NUM_EXPORT_HASHERS
1065370b324cSopenharmony_ci    #ifdef Z7_EXTERNAL_CODECS
1066370b324cSopenharmony_ci    + Hashers.Size()
1067370b324cSopenharmony_ci    #endif
1068370b324cSopenharmony_ci    ;
1069370b324cSopenharmony_ci}
1070370b324cSopenharmony_ci
1071370b324cSopenharmony_ciZ7_COM7F_IMF(CCodecs::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value))
1072370b324cSopenharmony_ci{
1073370b324cSopenharmony_ci  #ifdef EXPORT_CODECS
1074370b324cSopenharmony_ci  if (index < g_NumHashers)
1075370b324cSopenharmony_ci    return ::GetHasherProp(index, propID, value);
1076370b324cSopenharmony_ci  #endif
1077370b324cSopenharmony_ci
1078370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
1079370b324cSopenharmony_ci  const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
1080370b324cSopenharmony_ci  return Libs[ci.LibIndex].ComHashers->GetHasherProp(ci.HasherIndex, propID, value);
1081370b324cSopenharmony_ci  #else
1082370b324cSopenharmony_ci  return E_FAIL;
1083370b324cSopenharmony_ci  #endif
1084370b324cSopenharmony_ci}
1085370b324cSopenharmony_ci
1086370b324cSopenharmony_ciZ7_COM7F_IMF(CCodecs::CreateHasher(UInt32 index, IHasher **hasher))
1087370b324cSopenharmony_ci{
1088370b324cSopenharmony_ci  #ifdef EXPORT_CODECS
1089370b324cSopenharmony_ci  if (index < g_NumHashers)
1090370b324cSopenharmony_ci    return CreateHasher(index, hasher);
1091370b324cSopenharmony_ci  #endif
1092370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
1093370b324cSopenharmony_ci  const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
1094370b324cSopenharmony_ci  return Libs[ci.LibIndex].ComHashers->CreateHasher(ci.HasherIndex, hasher);
1095370b324cSopenharmony_ci  #else
1096370b324cSopenharmony_ci  return E_FAIL;
1097370b324cSopenharmony_ci  #endif
1098370b324cSopenharmony_ci}
1099370b324cSopenharmony_ci
1100370b324cSopenharmony_ciint CCodecs::GetCodec_LibIndex(UInt32 index) const
1101370b324cSopenharmony_ci{
1102370b324cSopenharmony_ci  #ifdef EXPORT_CODECS
1103370b324cSopenharmony_ci  if (index < g_NumCodecs)
1104370b324cSopenharmony_ci    return -1;
1105370b324cSopenharmony_ci  #endif
1106370b324cSopenharmony_ci
1107370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
1108370b324cSopenharmony_ci  const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
1109370b324cSopenharmony_ci  return (int)ci.LibIndex;
1110370b324cSopenharmony_ci  #else
1111370b324cSopenharmony_ci  return -1;
1112370b324cSopenharmony_ci  #endif
1113370b324cSopenharmony_ci}
1114370b324cSopenharmony_ci
1115370b324cSopenharmony_ciint CCodecs::GetHasherLibIndex(UInt32 index)
1116370b324cSopenharmony_ci{
1117370b324cSopenharmony_ci  #ifdef EXPORT_CODECS
1118370b324cSopenharmony_ci  if (index < g_NumHashers)
1119370b324cSopenharmony_ci    return -1;
1120370b324cSopenharmony_ci  #endif
1121370b324cSopenharmony_ci
1122370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
1123370b324cSopenharmony_ci  const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
1124370b324cSopenharmony_ci  return (int)ci.LibIndex;
1125370b324cSopenharmony_ci  #else
1126370b324cSopenharmony_ci  return -1;
1127370b324cSopenharmony_ci  #endif
1128370b324cSopenharmony_ci}
1129370b324cSopenharmony_ci
1130370b324cSopenharmony_cibool CCodecs::GetCodec_DecoderIsAssigned(UInt32 index) const
1131370b324cSopenharmony_ci{
1132370b324cSopenharmony_ci  #ifdef EXPORT_CODECS
1133370b324cSopenharmony_ci  if (index < g_NumCodecs)
1134370b324cSopenharmony_ci  {
1135370b324cSopenharmony_ci    NCOM::CPropVariant prop;
1136370b324cSopenharmony_ci    if (GetProperty(index, NMethodPropID::kDecoderIsAssigned, &prop) == S_OK)
1137370b324cSopenharmony_ci    {
1138370b324cSopenharmony_ci      if (prop.vt == VT_BOOL)
1139370b324cSopenharmony_ci        return VARIANT_BOOLToBool(prop.boolVal);
1140370b324cSopenharmony_ci    }
1141370b324cSopenharmony_ci    return false;
1142370b324cSopenharmony_ci  }
1143370b324cSopenharmony_ci  #endif
1144370b324cSopenharmony_ci
1145370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
1146370b324cSopenharmony_ci  return Codecs[index - NUM_EXPORT_CODECS].DecoderIsAssigned;
1147370b324cSopenharmony_ci  #else
1148370b324cSopenharmony_ci  return false;
1149370b324cSopenharmony_ci  #endif
1150370b324cSopenharmony_ci}
1151370b324cSopenharmony_ci
1152370b324cSopenharmony_ci
1153370b324cSopenharmony_cibool CCodecs::GetCodec_EncoderIsAssigned(UInt32 index) const
1154370b324cSopenharmony_ci{
1155370b324cSopenharmony_ci  #ifdef EXPORT_CODECS
1156370b324cSopenharmony_ci  if (index < g_NumCodecs)
1157370b324cSopenharmony_ci  {
1158370b324cSopenharmony_ci    NCOM::CPropVariant prop;
1159370b324cSopenharmony_ci    if (GetProperty(index, NMethodPropID::kEncoderIsAssigned, &prop) == S_OK)
1160370b324cSopenharmony_ci    {
1161370b324cSopenharmony_ci      if (prop.vt == VT_BOOL)
1162370b324cSopenharmony_ci        return VARIANT_BOOLToBool(prop.boolVal);
1163370b324cSopenharmony_ci    }
1164370b324cSopenharmony_ci    return false;
1165370b324cSopenharmony_ci  }
1166370b324cSopenharmony_ci  #endif
1167370b324cSopenharmony_ci
1168370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
1169370b324cSopenharmony_ci  return Codecs[index - NUM_EXPORT_CODECS].EncoderIsAssigned;
1170370b324cSopenharmony_ci  #else
1171370b324cSopenharmony_ci  return false;
1172370b324cSopenharmony_ci  #endif
1173370b324cSopenharmony_ci}
1174370b324cSopenharmony_ci
1175370b324cSopenharmony_ci
1176370b324cSopenharmony_cibool CCodecs::GetCodec_IsFilter(UInt32 index, bool &isAssigned) const
1177370b324cSopenharmony_ci{
1178370b324cSopenharmony_ci  isAssigned = false;
1179370b324cSopenharmony_ci  #ifdef EXPORT_CODECS
1180370b324cSopenharmony_ci  if (index < g_NumCodecs)
1181370b324cSopenharmony_ci  {
1182370b324cSopenharmony_ci    NCOM::CPropVariant prop;
1183370b324cSopenharmony_ci    if (GetProperty(index, NMethodPropID::kIsFilter, &prop) == S_OK)
1184370b324cSopenharmony_ci    {
1185370b324cSopenharmony_ci      if (prop.vt == VT_BOOL)
1186370b324cSopenharmony_ci      {
1187370b324cSopenharmony_ci        isAssigned = true;
1188370b324cSopenharmony_ci        return VARIANT_BOOLToBool(prop.boolVal);
1189370b324cSopenharmony_ci      }
1190370b324cSopenharmony_ci    }
1191370b324cSopenharmony_ci    return false;
1192370b324cSopenharmony_ci  }
1193370b324cSopenharmony_ci  #endif
1194370b324cSopenharmony_ci
1195370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
1196370b324cSopenharmony_ci  {
1197370b324cSopenharmony_ci    const CDllCodecInfo &c = Codecs[index - NUM_EXPORT_CODECS];
1198370b324cSopenharmony_ci    isAssigned = c.IsFilter_Assigned;
1199370b324cSopenharmony_ci    return c.IsFilter;
1200370b324cSopenharmony_ci  }
1201370b324cSopenharmony_ci  #else
1202370b324cSopenharmony_ci  return false;
1203370b324cSopenharmony_ci  #endif
1204370b324cSopenharmony_ci}
1205370b324cSopenharmony_ci
1206370b324cSopenharmony_ci
1207370b324cSopenharmony_ciUInt32 CCodecs::GetCodec_NumStreams(UInt32 index)
1208370b324cSopenharmony_ci{
1209370b324cSopenharmony_ci  NCOM::CPropVariant prop;
1210370b324cSopenharmony_ci  if (GetProperty(index, NMethodPropID::kPackStreams, &prop) != S_OK)
1211370b324cSopenharmony_ci    return 0;
1212370b324cSopenharmony_ci  if (prop.vt == VT_UI4)
1213370b324cSopenharmony_ci    return (UInt32)prop.ulVal;
1214370b324cSopenharmony_ci  if (prop.vt == VT_EMPTY)
1215370b324cSopenharmony_ci    return 1;
1216370b324cSopenharmony_ci  return 0;
1217370b324cSopenharmony_ci}
1218370b324cSopenharmony_ci
1219370b324cSopenharmony_ciHRESULT CCodecs::GetCodec_Id(UInt32 index, UInt64 &id)
1220370b324cSopenharmony_ci{
1221370b324cSopenharmony_ci  NCOM::CPropVariant prop;
1222370b324cSopenharmony_ci  RINOK(GetProperty(index, NMethodPropID::kID, &prop))
1223370b324cSopenharmony_ci  if (prop.vt != VT_UI8)
1224370b324cSopenharmony_ci    return E_INVALIDARG;
1225370b324cSopenharmony_ci  id = prop.uhVal.QuadPart;
1226370b324cSopenharmony_ci  return S_OK;
1227370b324cSopenharmony_ci}
1228370b324cSopenharmony_ci
1229370b324cSopenharmony_ciAString CCodecs::GetCodec_Name(UInt32 index)
1230370b324cSopenharmony_ci{
1231370b324cSopenharmony_ci  AString s;
1232370b324cSopenharmony_ci  NCOM::CPropVariant prop;
1233370b324cSopenharmony_ci  if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK)
1234370b324cSopenharmony_ci    if (prop.vt == VT_BSTR)
1235370b324cSopenharmony_ci      s.SetFromWStr_if_Ascii(prop.bstrVal);
1236370b324cSopenharmony_ci  return s;
1237370b324cSopenharmony_ci}
1238370b324cSopenharmony_ci
1239370b324cSopenharmony_ciUInt64 CCodecs::GetHasherId(UInt32 index)
1240370b324cSopenharmony_ci{
1241370b324cSopenharmony_ci  NCOM::CPropVariant prop;
1242370b324cSopenharmony_ci  if (GetHasherProp(index, NMethodPropID::kID, &prop) != S_OK)
1243370b324cSopenharmony_ci    return 0;
1244370b324cSopenharmony_ci  if (prop.vt != VT_UI8)
1245370b324cSopenharmony_ci    return 0;
1246370b324cSopenharmony_ci  return prop.uhVal.QuadPart;
1247370b324cSopenharmony_ci}
1248370b324cSopenharmony_ci
1249370b324cSopenharmony_ciAString CCodecs::GetHasherName(UInt32 index)
1250370b324cSopenharmony_ci{
1251370b324cSopenharmony_ci  AString s;
1252370b324cSopenharmony_ci  NCOM::CPropVariant prop;
1253370b324cSopenharmony_ci  if (GetHasherProp(index, NMethodPropID::kName, &prop) == S_OK)
1254370b324cSopenharmony_ci    if (prop.vt == VT_BSTR)
1255370b324cSopenharmony_ci      s.SetFromWStr_if_Ascii(prop.bstrVal);
1256370b324cSopenharmony_ci  return s;
1257370b324cSopenharmony_ci}
1258370b324cSopenharmony_ci
1259370b324cSopenharmony_ciUInt32 CCodecs::GetHasherDigestSize(UInt32 index)
1260370b324cSopenharmony_ci{
1261370b324cSopenharmony_ci  NCOM::CPropVariant prop;
1262370b324cSopenharmony_ci  if (GetHasherProp(index, NMethodPropID::kDigestSize, &prop) != S_OK)
1263370b324cSopenharmony_ci    return 0;
1264370b324cSopenharmony_ci  if (prop.vt != VT_UI4)
1265370b324cSopenharmony_ci    return 0;
1266370b324cSopenharmony_ci  return prop.ulVal;
1267370b324cSopenharmony_ci}
1268370b324cSopenharmony_ci
1269370b324cSopenharmony_civoid CCodecs::GetCodecsErrorMessage(UString &s)
1270370b324cSopenharmony_ci{
1271370b324cSopenharmony_ci  s.Empty();
1272370b324cSopenharmony_ci  FOR_VECTOR (i, Errors)
1273370b324cSopenharmony_ci  {
1274370b324cSopenharmony_ci    const CCodecError &ce = Errors[i];
1275370b324cSopenharmony_ci    s += "Codec Load Error: ";
1276370b324cSopenharmony_ci    s += fs2us(ce.Path);
1277370b324cSopenharmony_ci    if (ce.ErrorCode != 0)
1278370b324cSopenharmony_ci    {
1279370b324cSopenharmony_ci      s += " : ";
1280370b324cSopenharmony_ci      s += NWindows::NError::MyFormatMessage(ce.ErrorCode);
1281370b324cSopenharmony_ci    }
1282370b324cSopenharmony_ci    if (!ce.Message.IsEmpty())
1283370b324cSopenharmony_ci    {
1284370b324cSopenharmony_ci      s += " : ";
1285370b324cSopenharmony_ci      s += ce.Message;
1286370b324cSopenharmony_ci    }
1287370b324cSopenharmony_ci    s.Add_LF();
1288370b324cSopenharmony_ci  }
1289370b324cSopenharmony_ci}
1290370b324cSopenharmony_ci
1291370b324cSopenharmony_ci#endif // Z7_EXTERNAL_CODECS
1292370b324cSopenharmony_ci
1293370b324cSopenharmony_ci#ifndef Z7_SFX
1294370b324cSopenharmony_ci
1295370b324cSopenharmony_ciextern unsigned g_NumCodecs;
1296370b324cSopenharmony_ciextern const CCodecInfo *g_Codecs[];
1297370b324cSopenharmony_ci
1298370b324cSopenharmony_civoid CCodecs::Get_CodecsInfoUser_Vector(CObjectVector<CCodecInfoUser> &v)
1299370b324cSopenharmony_ci{
1300370b324cSopenharmony_ci  v.Clear();
1301370b324cSopenharmony_ci  {
1302370b324cSopenharmony_ci    for (unsigned i = 0; i < g_NumCodecs; i++)
1303370b324cSopenharmony_ci    {
1304370b324cSopenharmony_ci      const CCodecInfo &cod = *g_Codecs[i];
1305370b324cSopenharmony_ci      CCodecInfoUser &u = v.AddNew();
1306370b324cSopenharmony_ci      u.EncoderIsAssigned = (cod.CreateEncoder != NULL);
1307370b324cSopenharmony_ci      u.DecoderIsAssigned = (cod.CreateDecoder != NULL);
1308370b324cSopenharmony_ci      u.IsFilter_Assigned = true;
1309370b324cSopenharmony_ci      u.IsFilter = cod.IsFilter;
1310370b324cSopenharmony_ci      u.NumStreams = cod.NumStreams;
1311370b324cSopenharmony_ci      u.Name = cod.Name;
1312370b324cSopenharmony_ci    }
1313370b324cSopenharmony_ci  }
1314370b324cSopenharmony_ci
1315370b324cSopenharmony_ci
1316370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
1317370b324cSopenharmony_ci  {
1318370b324cSopenharmony_ci    UInt32 numMethods;
1319370b324cSopenharmony_ci    if (GetNumMethods(&numMethods) == S_OK)
1320370b324cSopenharmony_ci    for (UInt32 j = 0; j < numMethods; j++)
1321370b324cSopenharmony_ci    {
1322370b324cSopenharmony_ci      CCodecInfoUser &u = v.AddNew();
1323370b324cSopenharmony_ci      u.EncoderIsAssigned = GetCodec_EncoderIsAssigned(j);
1324370b324cSopenharmony_ci      u.DecoderIsAssigned = GetCodec_DecoderIsAssigned(j);
1325370b324cSopenharmony_ci      u.IsFilter = GetCodec_IsFilter(j, u.IsFilter_Assigned);
1326370b324cSopenharmony_ci      u.NumStreams = GetCodec_NumStreams(j);
1327370b324cSopenharmony_ci      u.Name = GetCodec_Name(j);
1328370b324cSopenharmony_ci    }
1329370b324cSopenharmony_ci  }
1330370b324cSopenharmony_ci  #endif
1331370b324cSopenharmony_ci}
1332370b324cSopenharmony_ci
1333370b324cSopenharmony_ci#endif
1334