• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // LoadCodecs.cpp
2 
3 /*
4 Z7_EXTERNAL_CODECS
5 ---------------
6   CCodecs::Load() tries to detect the directory with plugins.
7   It stops the checking, if it can find any of the following items:
8     - 7z.dll file
9     - "Formats" subdir
10     - "Codecs"  subdir
11   The order of check:
12     1) directory of client executable
13     2) WIN32: directory for REGISTRY item [HKEY_*\Software\7-Zip\Path**]
14        The order for HKEY_* : Path** :
15          - HKEY_CURRENT_USER  : PathXX
16          - HKEY_LOCAL_MACHINE : PathXX
17          - HKEY_CURRENT_USER  : Path
18          - HKEY_LOCAL_MACHINE : Path
19        PathXX is Path32 in 32-bit code
20        PathXX is Path64 in 64-bit code
21 
22 
23 EXPORT_CODECS
24 -------------
25   if (Z7_EXTERNAL_CODECS) is defined, then the code exports internal
26   codecs of client from CCodecs object to external plugins.
27   7-Zip doesn't use that feature. 7-Zip uses the scheme:
28     - client application without internal plugins.
29     - 7z.dll module contains all (or almost all) plugins.
30       7z.dll can use codecs from another plugins, if required.
31 */
32 
33 
34 #include "StdAfx.h"
35 
36 #include "../../../Common/MyCom.h"
37 #include "../../../Common/StringToInt.h"
38 #include "../../../Common/StringConvert.h"
39 
40 #include "../../../Windows/ErrorMsg.h"
41 #include "../../../Windows/FileIO.h"
42 #include "../../../Windows/PropVariant.h"
43 
44 #include "LoadCodecs.h"
45 
46 #include "../../ICoder.h"
47 #include "../../Common/RegisterArc.h"
48 #include "../../Common/RegisterCodec.h"
49 
50 #ifdef Z7_EXTERNAL_CODECS
51 // #define EXPORT_CODECS
52 #endif
53 
54 #ifdef Z7_EXTERNAL_CODECS
55 
56 #include "../../../Windows/FileFind.h"
57 #include "../../../Windows/DLL.h"
58 
59 #ifdef _WIN32
60 #include "../../../Windows/FileName.h"
61 #include "../../../Windows/Registry.h"
62 #endif
63 
64 using namespace NWindows;
65 using namespace NFile;
66 
67 
68 #define kCodecsFolderName FTEXT("Codecs")
69 #define kFormatsFolderName FTEXT("Formats")
70 
71 
72 static CFSTR const kMainDll =
73   #ifdef _WIN32
74     FTEXT("7z.dll");
75   #else
76     FTEXT("7z.so");
77   #endif
78 
79 
80 #ifdef _WIN32
81 
82 static LPCTSTR const kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip");
83 static LPCWSTR const kProgramPathValue = L"Path";
84 static LPCWSTR const kProgramPath2Value = L"Path"
85   #ifdef _WIN64
86   L"64";
87   #else
88   L"32";
89   #endif
90 
ReadPathFromRegistry(HKEY baseKey,LPCWSTR value,FString & path)91 static bool ReadPathFromRegistry(HKEY baseKey, LPCWSTR value, FString &path)
92 {
93   NRegistry::CKey key;
94   if (key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS)
95   {
96     UString pathU;
97     if (key.QueryValue(value, pathU) == ERROR_SUCCESS)
98     {
99       path = us2fs(pathU);
100       NName::NormalizeDirPathPrefix(path);
101       return NFind::DoesFileExist_Raw(path + kMainDll);
102     }
103   }
104   return false;
105 }
106 
107 #endif // _WIN32
108 
109 #endif // Z7_EXTERNAL_CODECS
110 
111 
112 static const unsigned kNumArcsMax = 72;
113 static unsigned g_NumArcs = 0;
114 static const CArcInfo *g_Arcs[kNumArcsMax];
115 
RegisterArc(const CArcInfo * arcInfo)116 void RegisterArc(const CArcInfo *arcInfo) throw()
117 {
118   if (g_NumArcs < kNumArcsMax)
119   {
120     g_Arcs[g_NumArcs] = arcInfo;
121     g_NumArcs++;
122   }
123   // else throw 1;
124 }
125 
126 /*
127 static void SplitString(const UString &srcString, UStringVector &destStrings)
128 {
129   destStrings.Clear();
130   UString s;
131   unsigned len = srcString.Len();
132   if (len == 0)
133     return;
134   for (unsigned i = 0; i < len; i++)
135   {
136     wchar_t c = srcString[i];
137     if (c == L' ')
138     {
139       if (!s.IsEmpty())
140       {
141         destStrings.Add(s);
142         s.Empty();
143       }
144     }
145     else
146       s += c;
147   }
148   if (!s.IsEmpty())
149     destStrings.Add(s);
150 }
151 */
152 
FindExtension(const UString & ext) const153 int CArcInfoEx::FindExtension(const UString &ext) const
154 {
155   FOR_VECTOR (i, Exts)
156     if (ext.IsEqualTo_NoCase(Exts[i].Ext))
157       return (int)i;
158   return -1;
159 }
160 
AddExts(const UString & ext,const UString & addExt)161 void CArcInfoEx::AddExts(const UString &ext, const UString &addExt)
162 {
163   UStringVector exts, addExts;
164   SplitString(ext, exts);
165   SplitString(addExt, addExts);
166   FOR_VECTOR (i, exts)
167   {
168     CArcExtInfo extInfo;
169     extInfo.Ext = exts[i];
170     if (i < addExts.Size())
171     {
172       extInfo.AddExt = addExts[i];
173       if (extInfo.AddExt == L"*")
174         extInfo.AddExt.Empty();
175     }
176     Exts.Add(extInfo);
177   }
178 }
179 
180 #ifndef Z7_SFX
181 
ParseSignatures(const Byte * data,unsigned size,CObjectVector<CByteBuffer> & signatures)182 static bool ParseSignatures(const Byte *data, unsigned size, CObjectVector<CByteBuffer> &signatures)
183 {
184   signatures.Clear();
185   while (size != 0)
186   {
187     const unsigned len = *data++;
188     size--;
189     if (len > size)
190       return false;
191     signatures.AddNew().CopyFrom(data, len);
192     data += len;
193     size -= len;
194   }
195   return true;
196 }
197 
198 #endif // Z7_SFX
199 
200 // #include <stdio.h>
201 
202 #ifdef Z7_EXTERNAL_CODECS
203 
GetBaseFolderPrefixFromRegistry()204 static FString GetBaseFolderPrefixFromRegistry()
205 {
206   FString moduleFolderPrefix = NDLL::GetModuleDirPrefix();
207 
208   #ifdef _WIN32
209   if (   !NFind::DoesFileOrDirExist(moduleFolderPrefix + kMainDll)
210       && !NFind::DoesFileOrDirExist(moduleFolderPrefix + kCodecsFolderName)
211       && !NFind::DoesFileOrDirExist(moduleFolderPrefix + kFormatsFolderName))
212   {
213     FString path;
214     if (ReadPathFromRegistry(HKEY_CURRENT_USER,  kProgramPath2Value, path)) return path;
215     if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPath2Value, path)) return path;
216     if (ReadPathFromRegistry(HKEY_CURRENT_USER,  kProgramPathValue,  path)) return path;
217     if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPathValue,  path)) return path;
218   }
219   #endif
220 
221   // printf("\nmoduleFolderPrefix = %s\n", (const char *)GetAnsiString(moduleFolderPrefix));
222   return moduleFolderPrefix;
223 }
224 
225 
GetCoderClass(Func_GetMethodProperty getMethodProperty,UInt32 index,PROPID propId,CLSID & clsId,bool & isAssigned)226 static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 index,
227     PROPID propId, CLSID &clsId, bool &isAssigned)
228 {
229   NCOM::CPropVariant prop;
230   isAssigned = false;
231   RINOK(getMethodProperty(index, propId, &prop))
232   if (prop.vt == VT_BSTR)
233   {
234     if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID))
235       return E_FAIL;
236     isAssigned = true;
237     clsId = *(const GUID *)(const void *)prop.bstrVal;
238   }
239   else if (prop.vt != VT_EMPTY)
240     return E_FAIL;
241   return S_OK;
242 }
243 
244 
GetMethodBoolProp(Func_GetMethodProperty getMethodProperty,UInt32 index,PROPID propId,bool & resVal,bool & isAssigned)245 static HRESULT GetMethodBoolProp(Func_GetMethodProperty getMethodProperty, UInt32 index,
246     PROPID propId, bool &resVal, bool &isAssigned)
247 {
248   NCOM::CPropVariant prop;
249   resVal = false;
250   isAssigned = false;
251   RINOK(getMethodProperty(index, propId, &prop))
252   if (prop.vt == VT_BOOL)
253   {
254     isAssigned = true;
255     resVal = VARIANT_BOOLToBool(prop.boolVal);
256   }
257   else if (prop.vt != VT_EMPTY)
258     return E_FAIL;
259   return S_OK;
260 }
261 
262 #if defined(__clang__)
263 #pragma GCC diagnostic ignored "-Wc++98-compat-pedantic"
264 #endif
265 
266 #define MY_GET_FUNC(dest, type, lib, func)  \
267   dest = Z7_GET_PROC_ADDRESS(type, lib.Get_HMODULE(), func);
268 // #define MY_GET_FUNC(dest, type, func)  dest = (type)(func);
269 
270 #define MY_GET_FUNC_LOC(dest, type, lib, func) \
271   type dest;  MY_GET_FUNC(dest, type, lib, func)
272 
LoadCodecs()273 HRESULT CCodecs::LoadCodecs()
274 {
275   CCodecLib &lib = Libs.Back();
276 
277   MY_GET_FUNC (lib.CreateDecoder,     Func_CreateDecoder,     lib.Lib, "CreateDecoder")
278   MY_GET_FUNC (lib.CreateEncoder,     Func_CreateEncoder,     lib.Lib, "CreateEncoder")
279   MY_GET_FUNC (lib.GetMethodProperty, Func_GetMethodProperty, lib.Lib, "GetMethodProperty")
280 
281   if (lib.GetMethodProperty)
282   {
283     UInt32 numMethods = 1;
284     MY_GET_FUNC_LOC (getNumberOfMethods, Func_GetNumberOfMethods, lib.Lib, "GetNumberOfMethods")
285     if (getNumberOfMethods)
286     {
287       RINOK(getNumberOfMethods(&numMethods))
288     }
289     for (UInt32 i = 0; i < numMethods; i++)
290     {
291       CDllCodecInfo info;
292       info.LibIndex = Libs.Size() - 1;
293       info.CodecIndex = i;
294       RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned))
295       RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned))
296       RINOK(GetMethodBoolProp(lib.GetMethodProperty, i, NMethodPropID::kIsFilter, info.IsFilter, info.IsFilter_Assigned))
297       Codecs.Add(info);
298     }
299   }
300 
301   MY_GET_FUNC_LOC (getHashers, Func_GetHashers, lib.Lib, "GetHashers")
302   if (getHashers)
303   {
304     RINOK(getHashers(&lib.ComHashers))
305     if (lib.ComHashers)
306     {
307       UInt32 numMethods = lib.ComHashers->GetNumHashers();
308       for (UInt32 i = 0; i < numMethods; i++)
309       {
310         CDllHasherInfo info;
311         info.LibIndex = Libs.Size() - 1;
312         info.HasherIndex = i;
313         Hashers.Add(info);
314       }
315     }
316   }
317 
318   return S_OK;
319 }
320 
GetProp(Func_GetHandlerProperty getProp,Func_GetHandlerProperty2 getProp2,UInt32 index,PROPID propID,NCOM::CPropVariant & prop)321 static HRESULT GetProp(
322     Func_GetHandlerProperty getProp,
323     Func_GetHandlerProperty2 getProp2,
324     UInt32 index, PROPID propID, NCOM::CPropVariant &prop)
325 {
326   if (getProp2)
327     return getProp2(index, propID, &prop);
328   return getProp(propID, &prop);
329 }
330 
GetProp_Bool(Func_GetHandlerProperty getProp,Func_GetHandlerProperty2 getProp2,UInt32 index,PROPID propID,bool & res)331 static HRESULT GetProp_Bool(
332     Func_GetHandlerProperty getProp,
333     Func_GetHandlerProperty2 getProp2,
334     UInt32 index, PROPID propID, bool &res)
335 {
336   res = false;
337   NCOM::CPropVariant prop;
338   RINOK(GetProp(getProp, getProp2, index, propID, prop))
339   if (prop.vt == VT_BOOL)
340     res = VARIANT_BOOLToBool(prop.boolVal);
341   else if (prop.vt != VT_EMPTY)
342     return E_FAIL;
343   return S_OK;
344 }
345 
GetProp_UInt32(Func_GetHandlerProperty getProp,Func_GetHandlerProperty2 getProp2,UInt32 index,PROPID propID,UInt32 & res,bool & defined)346 static HRESULT GetProp_UInt32(
347     Func_GetHandlerProperty getProp,
348     Func_GetHandlerProperty2 getProp2,
349     UInt32 index, PROPID propID, UInt32 &res, bool &defined)
350 {
351   res = 0;
352   defined = false;
353   NCOM::CPropVariant prop;
354   RINOK(GetProp(getProp, getProp2, index, propID, prop))
355   if (prop.vt == VT_UI4)
356   {
357     res = prop.ulVal;
358     defined = true;
359   }
360   else if (prop.vt != VT_EMPTY)
361     return E_FAIL;
362   return S_OK;
363 }
364 
GetProp_String(Func_GetHandlerProperty getProp,Func_GetHandlerProperty2 getProp2,UInt32 index,PROPID propID,UString & res)365 static HRESULT GetProp_String(
366     Func_GetHandlerProperty getProp,
367     Func_GetHandlerProperty2 getProp2,
368     UInt32 index, PROPID propID, UString &res)
369 {
370   res.Empty();
371   NCOM::CPropVariant prop;
372   RINOK(GetProp(getProp, getProp2, index, propID, prop))
373   if (prop.vt == VT_BSTR)
374     res.SetFromBstr(prop.bstrVal);
375   else if (prop.vt != VT_EMPTY)
376     return E_FAIL;
377   return S_OK;
378 }
379 
GetProp_RawData(Func_GetHandlerProperty getProp,Func_GetHandlerProperty2 getProp2,UInt32 index,PROPID propID,CByteBuffer & bb)380 static HRESULT GetProp_RawData(
381     Func_GetHandlerProperty getProp,
382     Func_GetHandlerProperty2 getProp2,
383     UInt32 index, PROPID propID, CByteBuffer &bb)
384 {
385   bb.Free();
386   NCOM::CPropVariant prop;
387   RINOK(GetProp(getProp, getProp2, index, propID, prop))
388   if (prop.vt == VT_BSTR)
389   {
390     UINT len = ::SysStringByteLen(prop.bstrVal);
391     bb.CopyFrom((const Byte *)prop.bstrVal, len);
392   }
393   else if (prop.vt != VT_EMPTY)
394     return E_FAIL;
395   return S_OK;
396 }
397 
398 static const UInt32 kArcFlagsPars[] =
399 {
400   NArchive::NHandlerPropID::kKeepName, NArcInfoFlags::kKeepName,
401   NArchive::NHandlerPropID::kAltStreams, NArcInfoFlags::kAltStreams,
402   NArchive::NHandlerPropID::kNtSecure, NArcInfoFlags::kNtSecure
403 };
404 
LoadFormats()405 HRESULT CCodecs::LoadFormats()
406 {
407   const NDLL::CLibrary &lib = Libs.Back().Lib;
408 
409   Func_GetHandlerProperty getProp = NULL;
410   MY_GET_FUNC_LOC (getProp2, Func_GetHandlerProperty2, lib, "GetHandlerProperty2")
411   MY_GET_FUNC_LOC (getIsArc, Func_GetIsArc, lib, "GetIsArc")
412 
413   UInt32 numFormats = 1;
414 
415   if (getProp2)
416   {
417     MY_GET_FUNC_LOC (getNumberOfFormats, Func_GetNumberOfFormats, lib, "GetNumberOfFormats")
418     if (getNumberOfFormats)
419     {
420       RINOK(getNumberOfFormats(&numFormats))
421     }
422   }
423   else
424   {
425     MY_GET_FUNC (getProp, Func_GetHandlerProperty, lib, "GetHandlerProperty")
426     if (!getProp)
427       return S_OK;
428   }
429 
430   for (UInt32 i = 0; i < numFormats; i++)
431   {
432     CArcInfoEx item;
433     item.LibIndex = (int)(Libs.Size() - 1);
434     item.FormatIndex = i;
435 
436     RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kName, item.Name))
437 
438     {
439       NCOM::CPropVariant prop;
440       if (GetProp(getProp, getProp2, i, NArchive::NHandlerPropID::kClassID, prop) != S_OK)
441         continue;
442       if (prop.vt != VT_BSTR)
443         continue;
444       if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID))
445         return E_FAIL;
446       item.ClassID = *(const GUID *)(const void *)prop.bstrVal;
447       prop.Clear();
448     }
449 
450     UString ext, addExt;
451     RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kExtension, ext))
452     RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kAddExtension, addExt))
453     item.AddExts(ext, addExt);
454 
455     GetProp_Bool(getProp, getProp2, i, NArchive::NHandlerPropID::kUpdate, item.UpdateEnabled);
456     bool flags_Defined = false;
457     RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kFlags, item.Flags, flags_Defined))
458     item.NewInterface = flags_Defined;
459     if (!flags_Defined) // && item.UpdateEnabled
460     {
461       // support for DLL version before 9.31:
462       for (unsigned j = 0; j < Z7_ARRAY_SIZE(kArcFlagsPars); j += 2)
463       {
464         bool val = false;
465         GetProp_Bool(getProp, getProp2, i, kArcFlagsPars[j], val);
466         if (val)
467           item.Flags |= kArcFlagsPars[j + 1];
468       }
469     }
470 
471     {
472       bool defined = false;
473       RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kTimeFlags, item.TimeFlags, defined))
474     }
475 
476     CByteBuffer sig;
477     RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kSignature, sig))
478     if (sig.Size() != 0)
479       item.Signatures.Add(sig);
480     else
481     {
482       RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kMultiSignature, sig))
483       ParseSignatures(sig, (unsigned)sig.Size(), item.Signatures);
484     }
485 
486     bool signatureOffset_Defined;
487     RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kSignatureOffset, item.SignatureOffset, signatureOffset_Defined))
488 
489     // bool version_Defined;
490     // RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kVersion, item.Version, version_Defined));
491 
492     if (getIsArc)
493       getIsArc(i, &item.IsArcFunc);
494 
495     Formats.Add(item);
496   }
497   return S_OK;
498 }
499 
500 #ifdef Z7_LARGE_PAGES
501 extern "C"
502 {
503   extern SIZE_T g_LargePageSize;
504 }
505 #endif
506 
507 
AddLastError(const FString & path)508 void CCodecs::AddLastError(const FString &path)
509 {
510   const HRESULT res = GetLastError_noZero_HRESULT();
511   CCodecError &error = Errors.AddNew();
512   error.Path = path;
513   error.ErrorCode = res;
514 }
515 
516 
IsSupportedDll(CCodecLib & lib)517 static bool IsSupportedDll(CCodecLib &lib)
518 {
519   MY_GET_FUNC_LOC (
520      f_GetModuleProp,
521   Func_GetModuleProp, lib.Lib,
522       "GetModuleProp")
523   /* p7zip and 7-Zip before v23 used virtual destructor in IUnknown,
524      if _WIN32 is not defined */
525   UInt32 flags =
526     #ifdef _WIN32
527       NModuleInterfaceType::k_IUnknown_VirtDestructor_No;
528     #else
529       NModuleInterfaceType::k_IUnknown_VirtDestructor_Yes;
530     #endif
531   if (f_GetModuleProp)
532   {
533     {
534       NCOM::CPropVariant prop;
535       if (f_GetModuleProp(NModulePropID::kInterfaceType, &prop) == S_OK)
536       {
537         if (prop.vt == VT_UI4)
538           flags = prop.ulVal;
539         else if (prop.vt != VT_EMPTY)
540           return false;
541       }
542     }
543     {
544       NCOM::CPropVariant prop;
545       if (f_GetModuleProp(NModulePropID::kVersion, &prop) == S_OK)
546       {
547         if (prop.vt == VT_UI4)
548           lib.Version = prop.ulVal;
549       }
550     }
551   }
552   if (
553       flags
554       // (flags & NModuleFlags::kMask)
555       != NModuleInterfaceType::k_IUnknown_VirtDestructor_ThisModule)
556     return false;
557   return true;
558 }
559 
560 
LoadDll(const FString & dllPath,bool needCheckDll,bool * loadedOK)561 HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loadedOK)
562 {
563   if (loadedOK)
564     *loadedOK = false;
565 
566   // needCheckDll = 1;
567 
568   #ifdef _WIN32
569   if (needCheckDll)
570   {
571     NDLL::CLibrary lib;
572     if (!lib.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE))
573     {
574       /* if is not win32
575       //  %1 is not a valid Win32 application.
576       //  #define ERROR_BAD_EXE_FORMAT             193L
577       */
578       // return GetLastError_noZero_HRESULT();
579       const DWORD lastError = GetLastError();
580       if (lastError != ERROR_BAD_EXE_FORMAT)
581       {
582         CCodecError &error = Errors.AddNew();
583         error.Path = dllPath;
584         error.Message = "cannot load file as datafile library";
585         error.ErrorCode = HRESULT_FROM_WIN32(lastError);
586       }
587       return S_OK;
588     }
589   }
590   #else
591   UNUSED_VAR(needCheckDll)
592   #endif
593 
594   Libs.AddNew();
595   CCodecLib &lib = Libs.Back();
596   lib.Path = dllPath;
597   bool used = false;
598   // HRESULT res = S_OK;
599 
600  if (lib.Lib.Load(dllPath))
601  {
602   if (!IsSupportedDll(lib))
603   {
604     CCodecError &error = Errors.AddNew();
605     error.Path = dllPath;
606     error.Message = "the module is not compatible with program";
607   }
608   else
609   {
610     if (loadedOK)
611       *loadedOK = true;
612     /*
613     #ifdef NEW_FOLDER_INTERFACE
614     lib.LoadIcons();
615     #endif
616     */
617 
618     /*
619     {
620       MY_GET_FUNC_LOC (_libStartup, Func_libStartup, lib.Lib, "LibStartup")
621       if (_libStartup)
622       {
623         HRESULT res = _libStartup();
624         if (res != 0)
625         {
626           CCodecError &error = Errors.AddNew();
627           error.Path = dllPath;
628           error.ErrorCode = res;
629         }
630       }
631     }
632     */
633 
634     #ifdef Z7_LARGE_PAGES
635     if (g_LargePageSize != 0)
636     {
637       MY_GET_FUNC_LOC (setLargePageMode, Func_SetLargePageMode, lib.Lib, "SetLargePageMode")
638       if (setLargePageMode)
639         setLargePageMode();
640     }
641     #endif
642 
643     if (CaseSensitive_Change)
644     {
645       MY_GET_FUNC_LOC (setCaseSensitive, Func_SetCaseSensitive, lib.Lib, "SetCaseSensitive")
646       if (setCaseSensitive)
647         setCaseSensitive(CaseSensitive ? 1 : 0);
648     }
649 
650     /*
651     {
652       MY_GET_FUNC_LOC (setClientVersion, Func_SetClientVersion, lib.Lib, "SetClientVersion")
653       if (setClientVersion)
654       {
655         // const UInt32 kVersion = (MY_VER_MAJOR << 16) | MY_VER_MINOR;
656         setClientVersion(g_ClientVersion);
657       }
658     }
659     */
660 
661 
662     MY_GET_FUNC (lib.CreateObject, Func_CreateObject, lib.Lib, "CreateObject")
663     {
664       unsigned startSize = Codecs.Size() + Hashers.Size();
665       HRESULT res = LoadCodecs();
666       if (startSize != Codecs.Size() + Hashers.Size())
667         used = true;
668       if (res == S_OK && lib.CreateObject)
669       {
670         startSize = Formats.Size();
671         res = LoadFormats();
672         if (startSize != Formats.Size())
673           used = true;
674       }
675       if (res != S_OK)
676       {
677         CCodecError &error = Errors.AddNew();
678         error.Path = dllPath;
679         error.ErrorCode = res;
680       }
681     }
682     // plugins can use non-7-zip dlls, so we silently ignore non7zip DLLs
683     /*
684     if (!used)
685     {
686       CCodecError &error = Errors.AddNew();
687       error.Path = dllPath;
688       error.Message = "no 7-Zip code";
689     }
690     */
691   }
692  }
693  else
694   {
695     AddLastError(dllPath);
696   }
697 
698   if (!used)
699     Libs.DeleteBack();
700 
701   return S_OK;
702 }
703 
LoadDllsFromFolder(const FString & folderPath)704 HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPath)
705 {
706   if (!NFile::NFind::DoesDirExist_FollowLink(folderPath))
707   // if (!NFile::NFind::DoesDirExist(folderPath))
708   {
709     // AddLastError(folderPath);
710     return S_OK;
711   }
712 
713   FString folderPrefix = folderPath;
714   folderPrefix.Add_PathSepar();
715 
716   NFile::NFind::CEnumerator enumerator;
717   enumerator.SetDirPrefix(folderPrefix);
718   NFile::NFind::CDirEntry fi;
719   for (;;)
720   {
721     bool found;
722     if (!enumerator.Next(fi, found))
723     {
724       // it can be wrong Symbolic link to folder here
725       AddLastError(folderPath);
726       break;
727       // return GetLastError_noZero_HRESULT();
728     }
729     if (!found)
730       break;
731     #ifdef _WIN32
732     if (fi.IsDir())
733       continue;
734     #else
735     if (enumerator.DirEntry_IsDir(fi, true)) // followLink
736       continue;
737     #endif
738 
739     RINOK(LoadDll(folderPrefix + fi.Name, true))
740   }
741   return S_OK;
742 }
743 
CloseLibs()744 void CCodecs::CloseLibs()
745 {
746   // OutputDebugStringA("~CloseLibs start");
747   /*
748   WIN32: FreeLibrary() (CLibrary::Free()) function doesn't work as expected,
749   if it's called from another FreeLibrary() call.
750   So we need to call FreeLibrary() before global destructors.
751 
752   Also we free global links from DLLs to object of this module before CLibrary::Free() call.
753   */
754 
755   FOR_VECTOR(i, Libs)
756   {
757     const CCodecLib &lib = Libs[i];
758     if (lib.SetCodecs)
759       lib.SetCodecs(NULL);
760   }
761 
762   // OutputDebugStringA("~CloseLibs after SetCodecs");
763   Libs.Clear();
764   // OutputDebugStringA("~CloseLibs end");
765 }
766 
767 #endif // Z7_EXTERNAL_CODECS
768 
769 
Load()770 HRESULT CCodecs::Load()
771 {
772   /*
773   #ifdef NEW_FOLDER_INTERFACE
774   InternalIcons.LoadIcons(g_hInstance);
775   #endif
776   */
777 
778   Formats.Clear();
779 
780   #ifdef Z7_EXTERNAL_CODECS
781     Errors.Clear();
782     MainDll_ErrorPath.Empty();
783     Codecs.Clear();
784     Hashers.Clear();
785   #endif
786 
787   for (UInt32 i = 0; i < g_NumArcs; i++)
788   {
789     const CArcInfo &arc = *g_Arcs[i];
790     CArcInfoEx item;
791 
792     item.Name = arc.Name;
793     item.CreateInArchive = arc.CreateInArchive;
794     item.IsArcFunc = arc.IsArc;
795     item.Flags = arc.Flags;
796 
797     {
798       UString e, ae;
799       if (arc.Ext)
800         e = arc.Ext;
801       if (arc.AddExt)
802         ae = arc.AddExt;
803       item.AddExts(e, ae);
804     }
805 
806     #ifndef Z7_SFX
807 
808     item.CreateOutArchive = arc.CreateOutArchive;
809     item.UpdateEnabled = (arc.CreateOutArchive != NULL);
810     item.SignatureOffset = arc.SignatureOffset;
811     // item.Version = MY_VER_MIX;
812     item.NewInterface = true;
813 
814     if (arc.IsMultiSignature())
815       ParseSignatures(arc.Signature, arc.SignatureSize, item.Signatures);
816     else
817     {
818       if (arc.SignatureSize != 0) // 21.04
819         item.Signatures.AddNew().CopyFrom(arc.Signature, arc.SignatureSize);
820     }
821 
822     #endif
823 
824     Formats.Add(item);
825   }
826 
827   // printf("\nLoad codecs \n");
828 
829   #ifdef Z7_EXTERNAL_CODECS
830     const FString baseFolder = GetBaseFolderPrefixFromRegistry();
831     {
832       bool loadedOK;
833       RINOK(LoadDll(baseFolder + kMainDll, false, &loadedOK))
834       if (!loadedOK)
835         MainDll_ErrorPath = kMainDll;
836     }
837     RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName))
838     RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName))
839 
840   NeedSetLibCodecs = true;
841 
842   if (Libs.Size() == 0)
843     NeedSetLibCodecs = false;
844   else if (Libs.Size() == 1)
845   {
846     // we don't need to set ISetCompressCodecsInfo, if all arcs and codecs are in one external module.
847     #ifndef EXPORT_CODECS
848     if (g_NumArcs == 0)
849       NeedSetLibCodecs = false;
850     #endif
851   }
852 
853   if (NeedSetLibCodecs)
854   {
855     /* 15.00: now we call global function in DLL: SetCompressCodecsInfo(c)
856        old versions called only ISetCompressCodecsInfo::SetCompressCodecsInfo(c) for each archive handler */
857 
858     FOR_VECTOR(i, Libs)
859     {
860       CCodecLib &lib = Libs[i];
861       MY_GET_FUNC (lib.SetCodecs, Func_SetCodecs, lib.Lib, "SetCodecs")
862       if (lib.SetCodecs)
863       {
864         RINOK(lib.SetCodecs(this))
865       }
866     }
867   }
868 
869   #endif
870 
871   // we sort Formats to get fixed order of Formats after compilation.
872   Formats.Sort();
873   return S_OK;
874 }
875 
876 #ifndef Z7_SFX
877 
FindFormatForArchiveName(const UString & arcPath) const878 int CCodecs::FindFormatForArchiveName(const UString &arcPath) const
879 {
880   int dotPos = arcPath.ReverseFind_Dot();
881   if (dotPos <= arcPath.ReverseFind_PathSepar())
882     return -1;
883   const UString ext = arcPath.Ptr((unsigned)(dotPos + 1));
884   if (ext.IsEmpty())
885     return -1;
886   if (ext.IsEqualTo_Ascii_NoCase("exe"))
887     return -1;
888   FOR_VECTOR (i, Formats)
889   {
890     const CArcInfoEx &arc = Formats[i];
891     /*
892     if (!arc.UpdateEnabled)
893       continue;
894     */
895     if (arc.FindExtension(ext) >= 0)
896       return (int)i;
897   }
898   return -1;
899 }
900 
FindFormatForExtension(const UString & ext) const901 int CCodecs::FindFormatForExtension(const UString &ext) const
902 {
903   if (ext.IsEmpty())
904     return -1;
905   FOR_VECTOR (i, Formats)
906     if (Formats[i].FindExtension(ext) >= 0)
907       return (int)i;
908   return -1;
909 }
910 
FindFormatForArchiveType(const UString & arcType) const911 int CCodecs::FindFormatForArchiveType(const UString &arcType) const
912 {
913   FOR_VECTOR (i, Formats)
914     if (Formats[i].Name.IsEqualTo_NoCase(arcType))
915       return (int)i;
916   return -1;
917 }
918 
FindFormatForArchiveType(const UString & arcType,CIntVector & formatIndices) const919 bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const
920 {
921   formatIndices.Clear();
922   for (unsigned pos = 0; pos < arcType.Len();)
923   {
924     int pos2 = arcType.Find(L'.', pos);
925     if (pos2 < 0)
926       pos2 = (int)arcType.Len();
927     const UString name = arcType.Mid(pos, (unsigned)pos2 - pos);
928     if (name.IsEmpty())
929       return false;
930     int index = FindFormatForArchiveType(name);
931     if (index < 0 && name != L"*")
932     {
933       formatIndices.Clear();
934       return false;
935     }
936     formatIndices.Add(index);
937     pos = (unsigned)pos2 + 1;
938   }
939   return true;
940 }
941 
942 #endif // Z7_SFX
943 
944 
945 #ifdef Z7_EXTERNAL_CODECS
946 
947 // #define EXPORT_CODECS
948 
949 #ifdef EXPORT_CODECS
950 
951 extern unsigned g_NumCodecs;
952 STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject);
953 STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject);
954 STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);
955 #define NUM_EXPORT_CODECS g_NumCodecs
956 
957 extern unsigned g_NumHashers;
958 STDAPI CreateHasher(UInt32 index, IHasher **hasher);
959 STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);
960 #define NUM_EXPORT_HASHERS g_NumHashers
961 
962 #else // EXPORT_CODECS
963 
964 #define NUM_EXPORT_CODECS 0
965 #define NUM_EXPORT_HASHERS 0
966 
967 #endif // EXPORT_CODECS
968 
Z7_COM7F_IMF(CCodecs::GetNumMethods (UInt32 * numMethods))969 Z7_COM7F_IMF(CCodecs::GetNumMethods(UInt32 *numMethods))
970 {
971   *numMethods = NUM_EXPORT_CODECS
972     #ifdef Z7_EXTERNAL_CODECS
973     + Codecs.Size()
974     #endif
975     ;
976   return S_OK;
977 }
978 
Z7_COM7F_IMF(CCodecs::GetProperty (UInt32 index,PROPID propID,PROPVARIANT * value))979 Z7_COM7F_IMF(CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
980 {
981   #ifdef EXPORT_CODECS
982   if (index < g_NumCodecs)
983     return GetMethodProperty(index, propID, value);
984   #endif
985 
986   #ifdef Z7_EXTERNAL_CODECS
987   const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
988 
989   if (propID == NMethodPropID::kDecoderIsAssigned ||
990       propID == NMethodPropID::kEncoderIsAssigned)
991   {
992     NCOM::CPropVariant prop;
993     prop = (bool)((propID == NMethodPropID::kDecoderIsAssigned) ?
994         ci.DecoderIsAssigned :
995         ci.EncoderIsAssigned);
996     prop.Detach(value);
997     return S_OK;
998   }
999 
1000   if (propID == NMethodPropID::kIsFilter && ci.IsFilter_Assigned)
1001   {
1002     NCOM::CPropVariant prop;
1003     prop = (bool)ci.IsFilter;
1004     prop.Detach(value);
1005     return S_OK;
1006   }
1007 
1008   const CCodecLib &lib = Libs[ci.LibIndex];
1009   return lib.GetMethodProperty(ci.CodecIndex, propID, value);
1010   #else
1011   return E_FAIL;
1012   #endif
1013 }
1014 
Z7_COM7F_IMF(CCodecs::CreateDecoder (UInt32 index,const GUID * iid,void ** coder))1015 Z7_COM7F_IMF(CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder))
1016 {
1017   #ifdef EXPORT_CODECS
1018   if (index < g_NumCodecs)
1019     return CreateDecoder(index, iid, coder);
1020   #endif
1021 
1022   #ifdef Z7_EXTERNAL_CODECS
1023   const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
1024   if (ci.DecoderIsAssigned)
1025   {
1026     const CCodecLib &lib = Libs[ci.LibIndex];
1027     if (lib.CreateDecoder)
1028       return lib.CreateDecoder(ci.CodecIndex, iid, (void **)coder);
1029     if (lib.CreateObject)
1030       return lib.CreateObject(&ci.Decoder, iid, (void **)coder);
1031   }
1032   return S_OK;
1033   #else
1034   return E_FAIL;
1035   #endif
1036 }
1037 
Z7_COM7F_IMF(CCodecs::CreateEncoder (UInt32 index,const GUID * iid,void ** coder))1038 Z7_COM7F_IMF(CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder))
1039 {
1040   #ifdef EXPORT_CODECS
1041   if (index < g_NumCodecs)
1042     return CreateEncoder(index, iid, coder);
1043   #endif
1044 
1045   #ifdef Z7_EXTERNAL_CODECS
1046   const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
1047   if (ci.EncoderIsAssigned)
1048   {
1049     const CCodecLib &lib = Libs[ci.LibIndex];
1050     if (lib.CreateEncoder)
1051       return lib.CreateEncoder(ci.CodecIndex, iid, (void **)coder);
1052     if (lib.CreateObject)
1053       return lib.CreateObject(&ci.Encoder, iid, (void **)coder);
1054   }
1055   return S_OK;
1056   #else
1057   return E_FAIL;
1058   #endif
1059 }
1060 
1061 
Z7_COM7F_IMF2(UInt32,CCodecs::GetNumHashers ())1062 Z7_COM7F_IMF2(UInt32, CCodecs::GetNumHashers())
1063 {
1064   return NUM_EXPORT_HASHERS
1065     #ifdef Z7_EXTERNAL_CODECS
1066     + Hashers.Size()
1067     #endif
1068     ;
1069 }
1070 
Z7_COM7F_IMF(CCodecs::GetHasherProp (UInt32 index,PROPID propID,PROPVARIANT * value))1071 Z7_COM7F_IMF(CCodecs::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value))
1072 {
1073   #ifdef EXPORT_CODECS
1074   if (index < g_NumHashers)
1075     return ::GetHasherProp(index, propID, value);
1076   #endif
1077 
1078   #ifdef Z7_EXTERNAL_CODECS
1079   const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
1080   return Libs[ci.LibIndex].ComHashers->GetHasherProp(ci.HasherIndex, propID, value);
1081   #else
1082   return E_FAIL;
1083   #endif
1084 }
1085 
Z7_COM7F_IMF(CCodecs::CreateHasher (UInt32 index,IHasher ** hasher))1086 Z7_COM7F_IMF(CCodecs::CreateHasher(UInt32 index, IHasher **hasher))
1087 {
1088   #ifdef EXPORT_CODECS
1089   if (index < g_NumHashers)
1090     return CreateHasher(index, hasher);
1091   #endif
1092   #ifdef Z7_EXTERNAL_CODECS
1093   const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
1094   return Libs[ci.LibIndex].ComHashers->CreateHasher(ci.HasherIndex, hasher);
1095   #else
1096   return E_FAIL;
1097   #endif
1098 }
1099 
GetCodec_LibIndex(UInt32 index) const1100 int CCodecs::GetCodec_LibIndex(UInt32 index) const
1101 {
1102   #ifdef EXPORT_CODECS
1103   if (index < g_NumCodecs)
1104     return -1;
1105   #endif
1106 
1107   #ifdef Z7_EXTERNAL_CODECS
1108   const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
1109   return (int)ci.LibIndex;
1110   #else
1111   return -1;
1112   #endif
1113 }
1114 
GetHasherLibIndex(UInt32 index)1115 int CCodecs::GetHasherLibIndex(UInt32 index)
1116 {
1117   #ifdef EXPORT_CODECS
1118   if (index < g_NumHashers)
1119     return -1;
1120   #endif
1121 
1122   #ifdef Z7_EXTERNAL_CODECS
1123   const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
1124   return (int)ci.LibIndex;
1125   #else
1126   return -1;
1127   #endif
1128 }
1129 
GetCodec_DecoderIsAssigned(UInt32 index) const1130 bool CCodecs::GetCodec_DecoderIsAssigned(UInt32 index) const
1131 {
1132   #ifdef EXPORT_CODECS
1133   if (index < g_NumCodecs)
1134   {
1135     NCOM::CPropVariant prop;
1136     if (GetProperty(index, NMethodPropID::kDecoderIsAssigned, &prop) == S_OK)
1137     {
1138       if (prop.vt == VT_BOOL)
1139         return VARIANT_BOOLToBool(prop.boolVal);
1140     }
1141     return false;
1142   }
1143   #endif
1144 
1145   #ifdef Z7_EXTERNAL_CODECS
1146   return Codecs[index - NUM_EXPORT_CODECS].DecoderIsAssigned;
1147   #else
1148   return false;
1149   #endif
1150 }
1151 
1152 
GetCodec_EncoderIsAssigned(UInt32 index) const1153 bool CCodecs::GetCodec_EncoderIsAssigned(UInt32 index) const
1154 {
1155   #ifdef EXPORT_CODECS
1156   if (index < g_NumCodecs)
1157   {
1158     NCOM::CPropVariant prop;
1159     if (GetProperty(index, NMethodPropID::kEncoderIsAssigned, &prop) == S_OK)
1160     {
1161       if (prop.vt == VT_BOOL)
1162         return VARIANT_BOOLToBool(prop.boolVal);
1163     }
1164     return false;
1165   }
1166   #endif
1167 
1168   #ifdef Z7_EXTERNAL_CODECS
1169   return Codecs[index - NUM_EXPORT_CODECS].EncoderIsAssigned;
1170   #else
1171   return false;
1172   #endif
1173 }
1174 
1175 
GetCodec_IsFilter(UInt32 index,bool & isAssigned) const1176 bool CCodecs::GetCodec_IsFilter(UInt32 index, bool &isAssigned) const
1177 {
1178   isAssigned = false;
1179   #ifdef EXPORT_CODECS
1180   if (index < g_NumCodecs)
1181   {
1182     NCOM::CPropVariant prop;
1183     if (GetProperty(index, NMethodPropID::kIsFilter, &prop) == S_OK)
1184     {
1185       if (prop.vt == VT_BOOL)
1186       {
1187         isAssigned = true;
1188         return VARIANT_BOOLToBool(prop.boolVal);
1189       }
1190     }
1191     return false;
1192   }
1193   #endif
1194 
1195   #ifdef Z7_EXTERNAL_CODECS
1196   {
1197     const CDllCodecInfo &c = Codecs[index - NUM_EXPORT_CODECS];
1198     isAssigned = c.IsFilter_Assigned;
1199     return c.IsFilter;
1200   }
1201   #else
1202   return false;
1203   #endif
1204 }
1205 
1206 
GetCodec_NumStreams(UInt32 index)1207 UInt32 CCodecs::GetCodec_NumStreams(UInt32 index)
1208 {
1209   NCOM::CPropVariant prop;
1210   if (GetProperty(index, NMethodPropID::kPackStreams, &prop) != S_OK)
1211     return 0;
1212   if (prop.vt == VT_UI4)
1213     return (UInt32)prop.ulVal;
1214   if (prop.vt == VT_EMPTY)
1215     return 1;
1216   return 0;
1217 }
1218 
GetCodec_Id(UInt32 index,UInt64 & id)1219 HRESULT CCodecs::GetCodec_Id(UInt32 index, UInt64 &id)
1220 {
1221   NCOM::CPropVariant prop;
1222   RINOK(GetProperty(index, NMethodPropID::kID, &prop))
1223   if (prop.vt != VT_UI8)
1224     return E_INVALIDARG;
1225   id = prop.uhVal.QuadPart;
1226   return S_OK;
1227 }
1228 
GetCodec_Name(UInt32 index)1229 AString CCodecs::GetCodec_Name(UInt32 index)
1230 {
1231   AString s;
1232   NCOM::CPropVariant prop;
1233   if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK)
1234     if (prop.vt == VT_BSTR)
1235       s.SetFromWStr_if_Ascii(prop.bstrVal);
1236   return s;
1237 }
1238 
GetHasherId(UInt32 index)1239 UInt64 CCodecs::GetHasherId(UInt32 index)
1240 {
1241   NCOM::CPropVariant prop;
1242   if (GetHasherProp(index, NMethodPropID::kID, &prop) != S_OK)
1243     return 0;
1244   if (prop.vt != VT_UI8)
1245     return 0;
1246   return prop.uhVal.QuadPart;
1247 }
1248 
GetHasherName(UInt32 index)1249 AString CCodecs::GetHasherName(UInt32 index)
1250 {
1251   AString s;
1252   NCOM::CPropVariant prop;
1253   if (GetHasherProp(index, NMethodPropID::kName, &prop) == S_OK)
1254     if (prop.vt == VT_BSTR)
1255       s.SetFromWStr_if_Ascii(prop.bstrVal);
1256   return s;
1257 }
1258 
GetHasherDigestSize(UInt32 index)1259 UInt32 CCodecs::GetHasherDigestSize(UInt32 index)
1260 {
1261   NCOM::CPropVariant prop;
1262   if (GetHasherProp(index, NMethodPropID::kDigestSize, &prop) != S_OK)
1263     return 0;
1264   if (prop.vt != VT_UI4)
1265     return 0;
1266   return prop.ulVal;
1267 }
1268 
GetCodecsErrorMessage(UString & s)1269 void CCodecs::GetCodecsErrorMessage(UString &s)
1270 {
1271   s.Empty();
1272   FOR_VECTOR (i, Errors)
1273   {
1274     const CCodecError &ce = Errors[i];
1275     s += "Codec Load Error: ";
1276     s += fs2us(ce.Path);
1277     if (ce.ErrorCode != 0)
1278     {
1279       s += " : ";
1280       s += NWindows::NError::MyFormatMessage(ce.ErrorCode);
1281     }
1282     if (!ce.Message.IsEmpty())
1283     {
1284       s += " : ";
1285       s += ce.Message;
1286     }
1287     s.Add_LF();
1288   }
1289 }
1290 
1291 #endif // Z7_EXTERNAL_CODECS
1292 
1293 #ifndef Z7_SFX
1294 
1295 extern unsigned g_NumCodecs;
1296 extern const CCodecInfo *g_Codecs[];
1297 
Get_CodecsInfoUser_Vector(CObjectVector<CCodecInfoUser> & v)1298 void CCodecs::Get_CodecsInfoUser_Vector(CObjectVector<CCodecInfoUser> &v)
1299 {
1300   v.Clear();
1301   {
1302     for (unsigned i = 0; i < g_NumCodecs; i++)
1303     {
1304       const CCodecInfo &cod = *g_Codecs[i];
1305       CCodecInfoUser &u = v.AddNew();
1306       u.EncoderIsAssigned = (cod.CreateEncoder != NULL);
1307       u.DecoderIsAssigned = (cod.CreateDecoder != NULL);
1308       u.IsFilter_Assigned = true;
1309       u.IsFilter = cod.IsFilter;
1310       u.NumStreams = cod.NumStreams;
1311       u.Name = cod.Name;
1312     }
1313   }
1314 
1315 
1316   #ifdef Z7_EXTERNAL_CODECS
1317   {
1318     UInt32 numMethods;
1319     if (GetNumMethods(&numMethods) == S_OK)
1320     for (UInt32 j = 0; j < numMethods; j++)
1321     {
1322       CCodecInfoUser &u = v.AddNew();
1323       u.EncoderIsAssigned = GetCodec_EncoderIsAssigned(j);
1324       u.DecoderIsAssigned = GetCodec_DecoderIsAssigned(j);
1325       u.IsFilter = GetCodec_IsFilter(j, u.IsFilter_Assigned);
1326       u.NumStreams = GetCodec_NumStreams(j);
1327       u.Name = GetCodec_Name(j);
1328     }
1329   }
1330   #endif
1331 }
1332 
1333 #endif
1334