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