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 #ifdef _WIN32
267 Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
268 #endif
269
270 #define MY_GET_FUNC(dest, type, lib, func) \
271 dest = Z7_GET_PROC_ADDRESS(type, lib.Get_HMODULE(), func);
272 // #define MY_GET_FUNC(dest, type, func) dest = (type)(func);
273
274 #define MY_GET_FUNC_LOC(dest, type, lib, func) \
275 type dest; MY_GET_FUNC(dest, type, lib, func)
276
LoadCodecs()277 HRESULT CCodecs::LoadCodecs()
278 {
279 CCodecLib &lib = Libs.Back();
280
281 MY_GET_FUNC (lib.CreateDecoder, Func_CreateDecoder, lib.Lib, "CreateDecoder")
282 MY_GET_FUNC (lib.CreateEncoder, Func_CreateEncoder, lib.Lib, "CreateEncoder")
283 MY_GET_FUNC (lib.GetMethodProperty, Func_GetMethodProperty, lib.Lib, "GetMethodProperty")
284
285 if (lib.GetMethodProperty)
286 {
287 UInt32 numMethods = 1;
288 MY_GET_FUNC_LOC (getNumberOfMethods, Func_GetNumberOfMethods, lib.Lib, "GetNumberOfMethods")
289 if (getNumberOfMethods)
290 {
291 RINOK(getNumberOfMethods(&numMethods))
292 }
293 for (UInt32 i = 0; i < numMethods; i++)
294 {
295 CDllCodecInfo info;
296 info.LibIndex = Libs.Size() - 1;
297 info.CodecIndex = i;
298 RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned))
299 RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned))
300 RINOK(GetMethodBoolProp(lib.GetMethodProperty, i, NMethodPropID::kIsFilter, info.IsFilter, info.IsFilter_Assigned))
301 Codecs.Add(info);
302 }
303 }
304
305 MY_GET_FUNC_LOC (getHashers, Func_GetHashers, lib.Lib, "GetHashers")
306 if (getHashers)
307 {
308 RINOK(getHashers(&lib.ComHashers))
309 if (lib.ComHashers)
310 {
311 UInt32 numMethods = lib.ComHashers->GetNumHashers();
312 for (UInt32 i = 0; i < numMethods; i++)
313 {
314 CDllHasherInfo info;
315 info.LibIndex = Libs.Size() - 1;
316 info.HasherIndex = i;
317 Hashers.Add(info);
318 }
319 }
320 }
321
322 return S_OK;
323 }
324
GetProp(Func_GetHandlerProperty getProp,Func_GetHandlerProperty2 getProp2,UInt32 index,PROPID propID,NCOM::CPropVariant & prop)325 static HRESULT GetProp(
326 Func_GetHandlerProperty getProp,
327 Func_GetHandlerProperty2 getProp2,
328 UInt32 index, PROPID propID, NCOM::CPropVariant &prop)
329 {
330 if (getProp2)
331 return getProp2(index, propID, &prop);
332 return getProp(propID, &prop);
333 }
334
GetProp_Bool(Func_GetHandlerProperty getProp,Func_GetHandlerProperty2 getProp2,UInt32 index,PROPID propID,bool & res)335 static HRESULT GetProp_Bool(
336 Func_GetHandlerProperty getProp,
337 Func_GetHandlerProperty2 getProp2,
338 UInt32 index, PROPID propID, bool &res)
339 {
340 res = false;
341 NCOM::CPropVariant prop;
342 RINOK(GetProp(getProp, getProp2, index, propID, prop))
343 if (prop.vt == VT_BOOL)
344 res = VARIANT_BOOLToBool(prop.boolVal);
345 else if (prop.vt != VT_EMPTY)
346 return E_FAIL;
347 return S_OK;
348 }
349
GetProp_UInt32(Func_GetHandlerProperty getProp,Func_GetHandlerProperty2 getProp2,UInt32 index,PROPID propID,UInt32 & res,bool & defined)350 static HRESULT GetProp_UInt32(
351 Func_GetHandlerProperty getProp,
352 Func_GetHandlerProperty2 getProp2,
353 UInt32 index, PROPID propID, UInt32 &res, bool &defined)
354 {
355 res = 0;
356 defined = false;
357 NCOM::CPropVariant prop;
358 RINOK(GetProp(getProp, getProp2, index, propID, prop))
359 if (prop.vt == VT_UI4)
360 {
361 res = prop.ulVal;
362 defined = true;
363 }
364 else if (prop.vt != VT_EMPTY)
365 return E_FAIL;
366 return S_OK;
367 }
368
GetProp_String(Func_GetHandlerProperty getProp,Func_GetHandlerProperty2 getProp2,UInt32 index,PROPID propID,UString & res)369 static HRESULT GetProp_String(
370 Func_GetHandlerProperty getProp,
371 Func_GetHandlerProperty2 getProp2,
372 UInt32 index, PROPID propID, UString &res)
373 {
374 res.Empty();
375 NCOM::CPropVariant prop;
376 RINOK(GetProp(getProp, getProp2, index, propID, prop))
377 if (prop.vt == VT_BSTR)
378 res.SetFromBstr(prop.bstrVal);
379 else if (prop.vt != VT_EMPTY)
380 return E_FAIL;
381 return S_OK;
382 }
383
GetProp_RawData(Func_GetHandlerProperty getProp,Func_GetHandlerProperty2 getProp2,UInt32 index,PROPID propID,CByteBuffer & bb)384 static HRESULT GetProp_RawData(
385 Func_GetHandlerProperty getProp,
386 Func_GetHandlerProperty2 getProp2,
387 UInt32 index, PROPID propID, CByteBuffer &bb)
388 {
389 bb.Free();
390 NCOM::CPropVariant prop;
391 RINOK(GetProp(getProp, getProp2, index, propID, prop))
392 if (prop.vt == VT_BSTR)
393 {
394 UINT len = ::SysStringByteLen(prop.bstrVal);
395 bb.CopyFrom((const Byte *)prop.bstrVal, len);
396 }
397 else if (prop.vt != VT_EMPTY)
398 return E_FAIL;
399 return S_OK;
400 }
401
402 static const UInt32 kArcFlagsPars[] =
403 {
404 NArchive::NHandlerPropID::kKeepName, NArcInfoFlags::kKeepName,
405 NArchive::NHandlerPropID::kAltStreams, NArcInfoFlags::kAltStreams,
406 NArchive::NHandlerPropID::kNtSecure, NArcInfoFlags::kNtSecure
407 };
408
LoadFormats()409 HRESULT CCodecs::LoadFormats()
410 {
411 const NDLL::CLibrary &lib = Libs.Back().Lib;
412
413 Func_GetHandlerProperty getProp = NULL;
414 MY_GET_FUNC_LOC (getProp2, Func_GetHandlerProperty2, lib, "GetHandlerProperty2")
415 MY_GET_FUNC_LOC (getIsArc, Func_GetIsArc, lib, "GetIsArc")
416
417 UInt32 numFormats = 1;
418
419 if (getProp2)
420 {
421 MY_GET_FUNC_LOC (getNumberOfFormats, Func_GetNumberOfFormats, lib, "GetNumberOfFormats")
422 if (getNumberOfFormats)
423 {
424 RINOK(getNumberOfFormats(&numFormats))
425 }
426 }
427 else
428 {
429 MY_GET_FUNC (getProp, Func_GetHandlerProperty, lib, "GetHandlerProperty")
430 if (!getProp)
431 return S_OK;
432 }
433
434 for (UInt32 i = 0; i < numFormats; i++)
435 {
436 CArcInfoEx item;
437 item.LibIndex = (int)(Libs.Size() - 1);
438 item.FormatIndex = i;
439
440 RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kName, item.Name))
441
442 {
443 NCOM::CPropVariant prop;
444 if (GetProp(getProp, getProp2, i, NArchive::NHandlerPropID::kClassID, prop) != S_OK)
445 continue;
446 if (prop.vt != VT_BSTR)
447 continue;
448 if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID))
449 return E_FAIL;
450 item.ClassID = *(const GUID *)(const void *)prop.bstrVal;
451 prop.Clear();
452 }
453
454 UString ext, addExt;
455 RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kExtension, ext))
456 RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kAddExtension, addExt))
457 item.AddExts(ext, addExt);
458
459 GetProp_Bool(getProp, getProp2, i, NArchive::NHandlerPropID::kUpdate, item.UpdateEnabled);
460 bool flags_Defined = false;
461 RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kFlags, item.Flags, flags_Defined))
462 item.NewInterface = flags_Defined;
463 if (!flags_Defined) // && item.UpdateEnabled
464 {
465 // support for DLL version before 9.31:
466 for (unsigned j = 0; j < Z7_ARRAY_SIZE(kArcFlagsPars); j += 2)
467 {
468 bool val = false;
469 GetProp_Bool(getProp, getProp2, i, kArcFlagsPars[j], val);
470 if (val)
471 item.Flags |= kArcFlagsPars[j + 1];
472 }
473 }
474
475 {
476 bool defined = false;
477 RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kTimeFlags, item.TimeFlags, defined))
478 }
479
480 CByteBuffer sig;
481 RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kSignature, sig))
482 if (sig.Size() != 0)
483 item.Signatures.Add(sig);
484 else
485 {
486 RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kMultiSignature, sig))
487 ParseSignatures(sig, (unsigned)sig.Size(), item.Signatures);
488 }
489
490 bool signatureOffset_Defined;
491 RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kSignatureOffset, item.SignatureOffset, signatureOffset_Defined))
492
493 // bool version_Defined;
494 // RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kVersion, item.Version, version_Defined));
495
496 if (getIsArc)
497 getIsArc(i, &item.IsArcFunc);
498
499 Formats.Add(item);
500 }
501 return S_OK;
502 }
503
504 #ifdef Z7_LARGE_PAGES
505 extern "C"
506 {
507 extern SIZE_T g_LargePageSize;
508 }
509 #endif
510
511
AddLastError(const FString & path)512 void CCodecs::AddLastError(const FString &path)
513 {
514 const HRESULT res = GetLastError_noZero_HRESULT();
515 CCodecError &error = Errors.AddNew();
516 error.Path = path;
517 error.ErrorCode = res;
518 }
519
520
IsSupportedDll(CCodecLib & lib)521 static bool IsSupportedDll(CCodecLib &lib)
522 {
523 MY_GET_FUNC_LOC (
524 f_GetModuleProp,
525 Func_GetModuleProp, lib.Lib,
526 "GetModuleProp")
527 /* p7zip and 7-Zip before v23 used virtual destructor in IUnknown,
528 if _WIN32 is not defined */
529 UInt32 flags =
530 #ifdef _WIN32
531 NModuleInterfaceType::k_IUnknown_VirtDestructor_No;
532 #else
533 NModuleInterfaceType::k_IUnknown_VirtDestructor_Yes;
534 #endif
535 if (f_GetModuleProp)
536 {
537 {
538 NCOM::CPropVariant prop;
539 if (f_GetModuleProp(NModulePropID::kInterfaceType, &prop) == S_OK)
540 {
541 if (prop.vt == VT_UI4)
542 flags = prop.ulVal;
543 else if (prop.vt != VT_EMPTY)
544 return false;
545 }
546 }
547 {
548 NCOM::CPropVariant prop;
549 if (f_GetModuleProp(NModulePropID::kVersion, &prop) == S_OK)
550 {
551 if (prop.vt == VT_UI4)
552 lib.Version = prop.ulVal;
553 }
554 }
555 }
556 if (
557 flags
558 // (flags & NModuleFlags::kMask)
559 != NModuleInterfaceType::k_IUnknown_VirtDestructor_ThisModule)
560 return false;
561 return true;
562 }
563
564
LoadDll(const FString & dllPath,bool needCheckDll,bool * loadedOK)565 HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loadedOK)
566 {
567 if (loadedOK)
568 *loadedOK = false;
569
570 // needCheckDll = 1;
571
572 #ifdef _WIN32
573 if (needCheckDll)
574 {
575 NDLL::CLibrary lib;
576 if (!lib.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE))
577 {
578 /* if is not win32
579 // %1 is not a valid Win32 application.
580 // #define ERROR_BAD_EXE_FORMAT 193L
581 */
582 // return GetLastError_noZero_HRESULT();
583 const DWORD lastError = GetLastError();
584 if (lastError != ERROR_BAD_EXE_FORMAT)
585 {
586 CCodecError &error = Errors.AddNew();
587 error.Path = dllPath;
588 error.Message = "cannot load file as datafile library";
589 error.ErrorCode = HRESULT_FROM_WIN32(lastError);
590 }
591 return S_OK;
592 }
593 }
594 #else
595 UNUSED_VAR(needCheckDll)
596 #endif
597
598 Libs.AddNew();
599 CCodecLib &lib = Libs.Back();
600 lib.Path = dllPath;
601 bool used = false;
602 // HRESULT res = S_OK;
603
604 if (lib.Lib.Load(dllPath))
605 {
606 if (!IsSupportedDll(lib))
607 {
608 CCodecError &error = Errors.AddNew();
609 error.Path = dllPath;
610 error.Message = "the module is not compatible with program";
611 }
612 else
613 {
614 if (loadedOK)
615 *loadedOK = true;
616 /*
617 #ifdef NEW_FOLDER_INTERFACE
618 lib.LoadIcons();
619 #endif
620 */
621
622 /*
623 {
624 MY_GET_FUNC_LOC (_libStartup, Func_libStartup, lib.Lib, "LibStartup")
625 if (_libStartup)
626 {
627 HRESULT res = _libStartup();
628 if (res != 0)
629 {
630 CCodecError &error = Errors.AddNew();
631 error.Path = dllPath;
632 error.ErrorCode = res;
633 }
634 }
635 }
636 */
637
638 #ifdef Z7_LARGE_PAGES
639 if (g_LargePageSize != 0)
640 {
641 MY_GET_FUNC_LOC (setLargePageMode, Func_SetLargePageMode, lib.Lib, "SetLargePageMode")
642 if (setLargePageMode)
643 setLargePageMode();
644 }
645 #endif
646
647 if (CaseSensitive_Change)
648 {
649 MY_GET_FUNC_LOC (setCaseSensitive, Func_SetCaseSensitive, lib.Lib, "SetCaseSensitive")
650 if (setCaseSensitive)
651 setCaseSensitive(CaseSensitive ? 1 : 0);
652 }
653
654 /*
655 {
656 MY_GET_FUNC_LOC (setClientVersion, Func_SetClientVersion, lib.Lib, "SetClientVersion")
657 if (setClientVersion)
658 {
659 // const UInt32 kVersion = (MY_VER_MAJOR << 16) | MY_VER_MINOR;
660 setClientVersion(g_ClientVersion);
661 }
662 }
663 */
664
665
666 MY_GET_FUNC (lib.CreateObject, Func_CreateObject, lib.Lib, "CreateObject")
667 {
668 unsigned startSize = Codecs.Size() + Hashers.Size();
669 HRESULT res = LoadCodecs();
670 if (startSize != Codecs.Size() + Hashers.Size())
671 used = true;
672 if (res == S_OK && lib.CreateObject)
673 {
674 startSize = Formats.Size();
675 res = LoadFormats();
676 if (startSize != Formats.Size())
677 used = true;
678 }
679 if (res != S_OK)
680 {
681 CCodecError &error = Errors.AddNew();
682 error.Path = dllPath;
683 error.ErrorCode = res;
684 }
685 }
686 // plugins can use non-7-zip dlls, so we silently ignore non7zip DLLs
687 /*
688 if (!used)
689 {
690 CCodecError &error = Errors.AddNew();
691 error.Path = dllPath;
692 error.Message = "no 7-Zip code";
693 }
694 */
695 }
696 }
697 else
698 {
699 AddLastError(dllPath);
700 }
701
702 if (!used)
703 Libs.DeleteBack();
704
705 return S_OK;
706 }
707
LoadDllsFromFolder(const FString & folderPath)708 HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPath)
709 {
710 if (!NFile::NFind::DoesDirExist_FollowLink(folderPath))
711 // if (!NFile::NFind::DoesDirExist(folderPath))
712 {
713 // AddLastError(folderPath);
714 return S_OK;
715 }
716
717 FString folderPrefix = folderPath;
718 folderPrefix.Add_PathSepar();
719
720 NFile::NFind::CEnumerator enumerator;
721 enumerator.SetDirPrefix(folderPrefix);
722 NFile::NFind::CDirEntry fi;
723 for (;;)
724 {
725 bool found;
726 if (!enumerator.Next(fi, found))
727 {
728 // it can be wrong Symbolic link to folder here
729 AddLastError(folderPath);
730 break;
731 // return GetLastError_noZero_HRESULT();
732 }
733 if (!found)
734 break;
735 #ifdef _WIN32
736 if (fi.IsDir())
737 continue;
738 #else
739 if (enumerator.DirEntry_IsDir(fi, true)) // followLink
740 continue;
741 #endif
742
743 RINOK(LoadDll(folderPrefix + fi.Name, true))
744 }
745 return S_OK;
746 }
747
CloseLibs()748 void CCodecs::CloseLibs()
749 {
750 // OutputDebugStringA("~CloseLibs start");
751 /*
752 WIN32: FreeLibrary() (CLibrary::Free()) function doesn't work as expected,
753 if it's called from another FreeLibrary() call.
754 So we need to call FreeLibrary() before global destructors.
755
756 Also we free global links from DLLs to object of this module before CLibrary::Free() call.
757 */
758
759 FOR_VECTOR(i, Libs)
760 {
761 const CCodecLib &lib = Libs[i];
762 if (lib.SetCodecs)
763 lib.SetCodecs(NULL);
764 }
765
766 // OutputDebugStringA("~CloseLibs after SetCodecs");
767 Libs.Clear();
768 // OutputDebugStringA("~CloseLibs end");
769 }
770
771 #endif // Z7_EXTERNAL_CODECS
772
773
Load()774 HRESULT CCodecs::Load()
775 {
776 /*
777 #ifdef NEW_FOLDER_INTERFACE
778 InternalIcons.LoadIcons(g_hInstance);
779 #endif
780 */
781
782 Formats.Clear();
783
784 #ifdef Z7_EXTERNAL_CODECS
785 Errors.Clear();
786 MainDll_ErrorPath.Empty();
787 Codecs.Clear();
788 Hashers.Clear();
789 #endif
790
791 for (UInt32 i = 0; i < g_NumArcs; i++)
792 {
793 const CArcInfo &arc = *g_Arcs[i];
794 CArcInfoEx item;
795
796 item.Name = arc.Name;
797 item.CreateInArchive = arc.CreateInArchive;
798 item.IsArcFunc = arc.IsArc;
799 item.Flags = arc.Flags;
800
801 {
802 UString e, ae;
803 if (arc.Ext)
804 e = arc.Ext;
805 if (arc.AddExt)
806 ae = arc.AddExt;
807 item.AddExts(e, ae);
808 }
809
810 #ifndef Z7_SFX
811
812 item.CreateOutArchive = arc.CreateOutArchive;
813 item.UpdateEnabled = (arc.CreateOutArchive != NULL);
814 item.SignatureOffset = arc.SignatureOffset;
815 // item.Version = MY_VER_MIX;
816 item.NewInterface = true;
817
818 if (arc.IsMultiSignature())
819 ParseSignatures(arc.Signature, arc.SignatureSize, item.Signatures);
820 else
821 {
822 if (arc.SignatureSize != 0) // 21.04
823 item.Signatures.AddNew().CopyFrom(arc.Signature, arc.SignatureSize);
824 }
825
826 #endif
827
828 Formats.Add(item);
829 }
830
831 // printf("\nLoad codecs \n");
832
833 #ifdef Z7_EXTERNAL_CODECS
834 const FString baseFolder = GetBaseFolderPrefixFromRegistry();
835 {
836 bool loadedOK;
837 RINOK(LoadDll(baseFolder + kMainDll, false, &loadedOK))
838 if (!loadedOK)
839 MainDll_ErrorPath = kMainDll;
840 }
841 RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName))
842 RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName))
843
844 NeedSetLibCodecs = true;
845
846 if (Libs.Size() == 0)
847 NeedSetLibCodecs = false;
848 else if (Libs.Size() == 1)
849 {
850 // we don't need to set ISetCompressCodecsInfo, if all arcs and codecs are in one external module.
851 #ifndef EXPORT_CODECS
852 if (g_NumArcs == 0)
853 NeedSetLibCodecs = false;
854 #endif
855 }
856
857 if (NeedSetLibCodecs)
858 {
859 /* 15.00: now we call global function in DLL: SetCompressCodecsInfo(c)
860 old versions called only ISetCompressCodecsInfo::SetCompressCodecsInfo(c) for each archive handler */
861
862 FOR_VECTOR(i, Libs)
863 {
864 CCodecLib &lib = Libs[i];
865 MY_GET_FUNC (lib.SetCodecs, Func_SetCodecs, lib.Lib, "SetCodecs")
866 if (lib.SetCodecs)
867 {
868 RINOK(lib.SetCodecs(this))
869 }
870 }
871 }
872
873 #endif
874
875 // we sort Formats to get fixed order of Formats after compilation.
876 Formats.Sort();
877 return S_OK;
878 }
879
880 #ifndef Z7_SFX
881
FindFormatForArchiveName(const UString & arcPath) const882 int CCodecs::FindFormatForArchiveName(const UString &arcPath) const
883 {
884 int dotPos = arcPath.ReverseFind_Dot();
885 if (dotPos <= arcPath.ReverseFind_PathSepar())
886 return -1;
887 const UString ext = arcPath.Ptr((unsigned)(dotPos + 1));
888 if (ext.IsEmpty())
889 return -1;
890 if (ext.IsEqualTo_Ascii_NoCase("exe"))
891 return -1;
892 FOR_VECTOR (i, Formats)
893 {
894 const CArcInfoEx &arc = Formats[i];
895 /*
896 if (!arc.UpdateEnabled)
897 continue;
898 */
899 if (arc.FindExtension(ext) >= 0)
900 return (int)i;
901 }
902 return -1;
903 }
904
FindFormatForExtension(const UString & ext) const905 int CCodecs::FindFormatForExtension(const UString &ext) const
906 {
907 if (ext.IsEmpty())
908 return -1;
909 FOR_VECTOR (i, Formats)
910 if (Formats[i].FindExtension(ext) >= 0)
911 return (int)i;
912 return -1;
913 }
914
FindFormatForArchiveType(const UString & arcType) const915 int CCodecs::FindFormatForArchiveType(const UString &arcType) const
916 {
917 FOR_VECTOR (i, Formats)
918 if (Formats[i].Name.IsEqualTo_NoCase(arcType))
919 return (int)i;
920 return -1;
921 }
922
FindFormatForArchiveType(const UString & arcType,CIntVector & formatIndices) const923 bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const
924 {
925 formatIndices.Clear();
926 for (unsigned pos = 0; pos < arcType.Len();)
927 {
928 int pos2 = arcType.Find(L'.', pos);
929 if (pos2 < 0)
930 pos2 = (int)arcType.Len();
931 const UString name = arcType.Mid(pos, (unsigned)pos2 - pos);
932 if (name.IsEmpty())
933 return false;
934 int index = FindFormatForArchiveType(name);
935 if (index < 0 && name != L"*")
936 {
937 formatIndices.Clear();
938 return false;
939 }
940 formatIndices.Add(index);
941 pos = (unsigned)pos2 + 1;
942 }
943 return true;
944 }
945
946 #endif // Z7_SFX
947
948
949 #ifdef Z7_EXTERNAL_CODECS
950
951 // #define EXPORT_CODECS
952
953 #ifdef EXPORT_CODECS
954
955 extern unsigned g_NumCodecs;
956 STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject);
957 STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject);
958 STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);
959 #define NUM_EXPORT_CODECS g_NumCodecs
960
961 extern unsigned g_NumHashers;
962 STDAPI CreateHasher(UInt32 index, IHasher **hasher);
963 STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);
964 #define NUM_EXPORT_HASHERS g_NumHashers
965
966 #else // EXPORT_CODECS
967
968 #define NUM_EXPORT_CODECS 0
969 #define NUM_EXPORT_HASHERS 0
970
971 #endif // EXPORT_CODECS
972
Z7_COM7F_IMF(CCodecs::GetNumMethods (UInt32 * numMethods))973 Z7_COM7F_IMF(CCodecs::GetNumMethods(UInt32 *numMethods))
974 {
975 *numMethods = NUM_EXPORT_CODECS
976 #ifdef Z7_EXTERNAL_CODECS
977 + Codecs.Size()
978 #endif
979 ;
980 return S_OK;
981 }
982
Z7_COM7F_IMF(CCodecs::GetProperty (UInt32 index,PROPID propID,PROPVARIANT * value))983 Z7_COM7F_IMF(CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
984 {
985 #ifdef EXPORT_CODECS
986 if (index < g_NumCodecs)
987 return GetMethodProperty(index, propID, value);
988 #endif
989
990 #ifdef Z7_EXTERNAL_CODECS
991 const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
992
993 if (propID == NMethodPropID::kDecoderIsAssigned ||
994 propID == NMethodPropID::kEncoderIsAssigned)
995 {
996 NCOM::CPropVariant prop;
997 prop = (bool)((propID == NMethodPropID::kDecoderIsAssigned) ?
998 ci.DecoderIsAssigned :
999 ci.EncoderIsAssigned);
1000 prop.Detach(value);
1001 return S_OK;
1002 }
1003
1004 if (propID == NMethodPropID::kIsFilter && ci.IsFilter_Assigned)
1005 {
1006 NCOM::CPropVariant prop;
1007 prop = (bool)ci.IsFilter;
1008 prop.Detach(value);
1009 return S_OK;
1010 }
1011
1012 const CCodecLib &lib = Libs[ci.LibIndex];
1013 return lib.GetMethodProperty(ci.CodecIndex, propID, value);
1014 #else
1015 return E_FAIL;
1016 #endif
1017 }
1018
Z7_COM7F_IMF(CCodecs::CreateDecoder (UInt32 index,const GUID * iid,void ** coder))1019 Z7_COM7F_IMF(CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder))
1020 {
1021 #ifdef EXPORT_CODECS
1022 if (index < g_NumCodecs)
1023 return CreateDecoder(index, iid, coder);
1024 #endif
1025
1026 #ifdef Z7_EXTERNAL_CODECS
1027 const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
1028 if (ci.DecoderIsAssigned)
1029 {
1030 const CCodecLib &lib = Libs[ci.LibIndex];
1031 if (lib.CreateDecoder)
1032 return lib.CreateDecoder(ci.CodecIndex, iid, (void **)coder);
1033 if (lib.CreateObject)
1034 return lib.CreateObject(&ci.Decoder, iid, (void **)coder);
1035 }
1036 return S_OK;
1037 #else
1038 return E_FAIL;
1039 #endif
1040 }
1041
Z7_COM7F_IMF(CCodecs::CreateEncoder (UInt32 index,const GUID * iid,void ** coder))1042 Z7_COM7F_IMF(CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder))
1043 {
1044 #ifdef EXPORT_CODECS
1045 if (index < g_NumCodecs)
1046 return CreateEncoder(index, iid, coder);
1047 #endif
1048
1049 #ifdef Z7_EXTERNAL_CODECS
1050 const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
1051 if (ci.EncoderIsAssigned)
1052 {
1053 const CCodecLib &lib = Libs[ci.LibIndex];
1054 if (lib.CreateEncoder)
1055 return lib.CreateEncoder(ci.CodecIndex, iid, (void **)coder);
1056 if (lib.CreateObject)
1057 return lib.CreateObject(&ci.Encoder, iid, (void **)coder);
1058 }
1059 return S_OK;
1060 #else
1061 return E_FAIL;
1062 #endif
1063 }
1064
1065
Z7_COM7F_IMF2(UInt32,CCodecs::GetNumHashers ())1066 Z7_COM7F_IMF2(UInt32, CCodecs::GetNumHashers())
1067 {
1068 return NUM_EXPORT_HASHERS
1069 #ifdef Z7_EXTERNAL_CODECS
1070 + Hashers.Size()
1071 #endif
1072 ;
1073 }
1074
Z7_COM7F_IMF(CCodecs::GetHasherProp (UInt32 index,PROPID propID,PROPVARIANT * value))1075 Z7_COM7F_IMF(CCodecs::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value))
1076 {
1077 #ifdef EXPORT_CODECS
1078 if (index < g_NumHashers)
1079 return ::GetHasherProp(index, propID, value);
1080 #endif
1081
1082 #ifdef Z7_EXTERNAL_CODECS
1083 const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
1084 return Libs[ci.LibIndex].ComHashers->GetHasherProp(ci.HasherIndex, propID, value);
1085 #else
1086 return E_FAIL;
1087 #endif
1088 }
1089
Z7_COM7F_IMF(CCodecs::CreateHasher (UInt32 index,IHasher ** hasher))1090 Z7_COM7F_IMF(CCodecs::CreateHasher(UInt32 index, IHasher **hasher))
1091 {
1092 #ifdef EXPORT_CODECS
1093 if (index < g_NumHashers)
1094 return CreateHasher(index, hasher);
1095 #endif
1096 #ifdef Z7_EXTERNAL_CODECS
1097 const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
1098 return Libs[ci.LibIndex].ComHashers->CreateHasher(ci.HasherIndex, hasher);
1099 #else
1100 return E_FAIL;
1101 #endif
1102 }
1103
GetCodec_LibIndex(UInt32 index) const1104 int CCodecs::GetCodec_LibIndex(UInt32 index) const
1105 {
1106 #ifdef EXPORT_CODECS
1107 if (index < g_NumCodecs)
1108 return -1;
1109 #endif
1110
1111 #ifdef Z7_EXTERNAL_CODECS
1112 const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
1113 return (int)ci.LibIndex;
1114 #else
1115 return -1;
1116 #endif
1117 }
1118
GetHasherLibIndex(UInt32 index)1119 int CCodecs::GetHasherLibIndex(UInt32 index)
1120 {
1121 #ifdef EXPORT_CODECS
1122 if (index < g_NumHashers)
1123 return -1;
1124 #endif
1125
1126 #ifdef Z7_EXTERNAL_CODECS
1127 const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
1128 return (int)ci.LibIndex;
1129 #else
1130 return -1;
1131 #endif
1132 }
1133
GetCodec_DecoderIsAssigned(UInt32 index) const1134 bool CCodecs::GetCodec_DecoderIsAssigned(UInt32 index) const
1135 {
1136 #ifdef EXPORT_CODECS
1137 if (index < g_NumCodecs)
1138 {
1139 NCOM::CPropVariant prop;
1140 if (GetProperty(index, NMethodPropID::kDecoderIsAssigned, &prop) == S_OK)
1141 {
1142 if (prop.vt == VT_BOOL)
1143 return VARIANT_BOOLToBool(prop.boolVal);
1144 }
1145 return false;
1146 }
1147 #endif
1148
1149 #ifdef Z7_EXTERNAL_CODECS
1150 return Codecs[index - NUM_EXPORT_CODECS].DecoderIsAssigned;
1151 #else
1152 return false;
1153 #endif
1154 }
1155
1156
GetCodec_EncoderIsAssigned(UInt32 index) const1157 bool CCodecs::GetCodec_EncoderIsAssigned(UInt32 index) const
1158 {
1159 #ifdef EXPORT_CODECS
1160 if (index < g_NumCodecs)
1161 {
1162 NCOM::CPropVariant prop;
1163 if (GetProperty(index, NMethodPropID::kEncoderIsAssigned, &prop) == S_OK)
1164 {
1165 if (prop.vt == VT_BOOL)
1166 return VARIANT_BOOLToBool(prop.boolVal);
1167 }
1168 return false;
1169 }
1170 #endif
1171
1172 #ifdef Z7_EXTERNAL_CODECS
1173 return Codecs[index - NUM_EXPORT_CODECS].EncoderIsAssigned;
1174 #else
1175 return false;
1176 #endif
1177 }
1178
1179
GetCodec_IsFilter(UInt32 index,bool & isAssigned) const1180 bool CCodecs::GetCodec_IsFilter(UInt32 index, bool &isAssigned) const
1181 {
1182 isAssigned = false;
1183 #ifdef EXPORT_CODECS
1184 if (index < g_NumCodecs)
1185 {
1186 NCOM::CPropVariant prop;
1187 if (GetProperty(index, NMethodPropID::kIsFilter, &prop) == S_OK)
1188 {
1189 if (prop.vt == VT_BOOL)
1190 {
1191 isAssigned = true;
1192 return VARIANT_BOOLToBool(prop.boolVal);
1193 }
1194 }
1195 return false;
1196 }
1197 #endif
1198
1199 #ifdef Z7_EXTERNAL_CODECS
1200 {
1201 const CDllCodecInfo &c = Codecs[index - NUM_EXPORT_CODECS];
1202 isAssigned = c.IsFilter_Assigned;
1203 return c.IsFilter;
1204 }
1205 #else
1206 return false;
1207 #endif
1208 }
1209
1210
GetCodec_NumStreams(UInt32 index)1211 UInt32 CCodecs::GetCodec_NumStreams(UInt32 index)
1212 {
1213 NCOM::CPropVariant prop;
1214 if (GetProperty(index, NMethodPropID::kPackStreams, &prop) != S_OK)
1215 return 0;
1216 if (prop.vt == VT_UI4)
1217 return (UInt32)prop.ulVal;
1218 if (prop.vt == VT_EMPTY)
1219 return 1;
1220 return 0;
1221 }
1222
GetCodec_Id(UInt32 index,UInt64 & id)1223 HRESULT CCodecs::GetCodec_Id(UInt32 index, UInt64 &id)
1224 {
1225 NCOM::CPropVariant prop;
1226 RINOK(GetProperty(index, NMethodPropID::kID, &prop))
1227 if (prop.vt != VT_UI8)
1228 return E_INVALIDARG;
1229 id = prop.uhVal.QuadPart;
1230 return S_OK;
1231 }
1232
GetCodec_Name(UInt32 index)1233 AString CCodecs::GetCodec_Name(UInt32 index)
1234 {
1235 AString s;
1236 NCOM::CPropVariant prop;
1237 if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK)
1238 if (prop.vt == VT_BSTR)
1239 s.SetFromWStr_if_Ascii(prop.bstrVal);
1240 return s;
1241 }
1242
GetHasherId(UInt32 index)1243 UInt64 CCodecs::GetHasherId(UInt32 index)
1244 {
1245 NCOM::CPropVariant prop;
1246 if (GetHasherProp(index, NMethodPropID::kID, &prop) != S_OK)
1247 return 0;
1248 if (prop.vt != VT_UI8)
1249 return 0;
1250 return prop.uhVal.QuadPart;
1251 }
1252
GetHasherName(UInt32 index)1253 AString CCodecs::GetHasherName(UInt32 index)
1254 {
1255 AString s;
1256 NCOM::CPropVariant prop;
1257 if (GetHasherProp(index, NMethodPropID::kName, &prop) == S_OK)
1258 if (prop.vt == VT_BSTR)
1259 s.SetFromWStr_if_Ascii(prop.bstrVal);
1260 return s;
1261 }
1262
GetHasherDigestSize(UInt32 index)1263 UInt32 CCodecs::GetHasherDigestSize(UInt32 index)
1264 {
1265 NCOM::CPropVariant prop;
1266 if (GetHasherProp(index, NMethodPropID::kDigestSize, &prop) != S_OK)
1267 return 0;
1268 if (prop.vt != VT_UI4)
1269 return 0;
1270 return prop.ulVal;
1271 }
1272
GetCodecsErrorMessage(UString & s)1273 void CCodecs::GetCodecsErrorMessage(UString &s)
1274 {
1275 s.Empty();
1276 FOR_VECTOR (i, Errors)
1277 {
1278 const CCodecError &ce = Errors[i];
1279 s += "Codec Load Error: ";
1280 s += fs2us(ce.Path);
1281 if (ce.ErrorCode != 0)
1282 {
1283 s += " : ";
1284 s += NWindows::NError::MyFormatMessage(ce.ErrorCode);
1285 }
1286 if (!ce.Message.IsEmpty())
1287 {
1288 s += " : ";
1289 s += ce.Message;
1290 }
1291 s.Add_LF();
1292 }
1293 }
1294
1295 #endif // Z7_EXTERNAL_CODECS
1296
1297 #ifndef Z7_SFX
1298
1299 extern unsigned g_NumCodecs;
1300 extern const CCodecInfo *g_Codecs[];
1301
Get_CodecsInfoUser_Vector(CObjectVector<CCodecInfoUser> & v)1302 void CCodecs::Get_CodecsInfoUser_Vector(CObjectVector<CCodecInfoUser> &v)
1303 {
1304 v.Clear();
1305 {
1306 for (unsigned i = 0; i < g_NumCodecs; i++)
1307 {
1308 const CCodecInfo &cod = *g_Codecs[i];
1309 CCodecInfoUser &u = v.AddNew();
1310 u.EncoderIsAssigned = (cod.CreateEncoder != NULL);
1311 u.DecoderIsAssigned = (cod.CreateDecoder != NULL);
1312 u.IsFilter_Assigned = true;
1313 u.IsFilter = cod.IsFilter;
1314 u.NumStreams = cod.NumStreams;
1315 u.Name = cod.Name;
1316 }
1317 }
1318
1319
1320 #ifdef Z7_EXTERNAL_CODECS
1321 {
1322 UInt32 numMethods;
1323 if (GetNumMethods(&numMethods) == S_OK)
1324 for (UInt32 j = 0; j < numMethods; j++)
1325 {
1326 CCodecInfoUser &u = v.AddNew();
1327 u.EncoderIsAssigned = GetCodec_EncoderIsAssigned(j);
1328 u.DecoderIsAssigned = GetCodec_DecoderIsAssigned(j);
1329 u.IsFilter = GetCodec_IsFilter(j, u.IsFilter_Assigned);
1330 u.NumStreams = GetCodec_NumStreams(j);
1331 u.Name = GetCodec_Name(j);
1332 }
1333 }
1334 #endif
1335 }
1336
1337 #endif
1338