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