1 // LoadCodecs.cpp
2
3 #include "StdAfx.h"
4
5 #include "LoadCodecs.h"
6
7 #include "../../../Common/MyCom.h"
8 #ifdef NEW_FOLDER_INTERFACE
9 #include "../../../Common/StringToInt.h"
10 #endif
11 #include "../../../Windows/PropVariant.h"
12
13 #include "../../ICoder.h"
14 #include "../../Common/RegisterArc.h"
15
16 #ifdef EXTERNAL_CODECS
17 #include "../../../Windows/FileFind.h"
18 #include "../../../Windows/DLL.h"
19 #ifdef NEW_FOLDER_INTERFACE
20 #include "../../../Windows/ResourceString.h"
21 static const UINT kIconTypesResId = 100;
22 #endif
23
24 #ifdef _WIN32
25 #include "Windows/FileName.h"
26 #include "Windows/Registry.h"
27 #endif
28
29 using namespace NWindows;
30 using namespace NFile;
31
32 #ifdef _WIN32
33 extern HINSTANCE g_hInstance;
34 #endif
35
36 #define kCodecsFolderName FTEXT("Codecs")
37 #define kFormatsFolderName FTEXT("Formats")
38 static CFSTR kMainDll = FTEXT("7z.dll");
39
40 #ifdef _WIN32
41
42 static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip");
43 static LPCWSTR kProgramPathValue = L"Path";
44 static LPCWSTR kProgramPath2Value = L"Path"
45 #ifdef _WIN64
46 L"64";
47 #else
48 L"32";
49 #endif
50
ReadPathFromRegistry(HKEY baseKey,LPCWSTR value,FString & path)51 static bool ReadPathFromRegistry(HKEY baseKey, LPCWSTR value, FString &path)
52 {
53 NRegistry::CKey key;
54 if (key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS)
55 {
56 UString pathU;
57 if (key.QueryValue(value, pathU) == ERROR_SUCCESS)
58 {
59 path = us2fs(pathU);
60 NName::NormalizeDirPathPrefix(path);
61 return NFind::DoesFileExist(path + kMainDll);
62 }
63 }
64 return false;
65 }
66
67 #endif
68
GetBaseFolderPrefixFromRegistry()69 static FString GetBaseFolderPrefixFromRegistry()
70 {
71 FString moduleFolderPrefix = NDLL::GetModuleDirPrefix();
72 #ifdef _WIN32
73 if (!NFind::DoesFileExist(moduleFolderPrefix + kMainDll) &&
74 !NFind::DoesDirExist(moduleFolderPrefix + kCodecsFolderName) &&
75 !NFind::DoesDirExist(moduleFolderPrefix + kFormatsFolderName))
76 {
77 FString path;
78 if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPath2Value, path)) return path;
79 if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPath2Value, path)) return path;
80 if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPathValue, path)) return path;
81 if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPathValue, path)) return path;
82 }
83 #endif
84 return moduleFolderPrefix;
85 }
86
87 typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods);
88 typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats);
89 typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value);
90 typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value);
91 typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *iid, void **outObject);
92 typedef UInt32 (WINAPI *SetLargePageModeFunc)();
93
94
GetCoderClass(GetMethodPropertyFunc getMethodProperty,UInt32 index,PROPID propId,CLSID & clsId,bool & isAssigned)95 static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index,
96 PROPID propId, CLSID &clsId, bool &isAssigned)
97 {
98 NWindows::NCOM::CPropVariant prop;
99 isAssigned = false;
100 RINOK(getMethodProperty(index, propId, &prop));
101 if (prop.vt == VT_BSTR)
102 {
103 isAssigned = true;
104 clsId = *(const GUID *)prop.bstrVal;
105 }
106 else if (prop.vt != VT_EMPTY)
107 return E_FAIL;
108 return S_OK;
109 }
110
LoadCodecs()111 HRESULT CCodecs::LoadCodecs()
112 {
113 CCodecLib &lib = Libs.Back();
114 lib.GetMethodProperty = (GetMethodPropertyFunc)lib.Lib.GetProc("GetMethodProperty");
115 if (lib.GetMethodProperty == NULL)
116 return S_OK;
117
118 UInt32 numMethods = 1;
119 GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)lib.Lib.GetProc("GetNumberOfMethods");
120 if (getNumberOfMethodsFunc != NULL)
121 {
122 RINOK(getNumberOfMethodsFunc(&numMethods));
123 }
124
125 for(UInt32 i = 0; i < numMethods; i++)
126 {
127 CDllCodecInfo info;
128 info.LibIndex = Libs.Size() - 1;
129 info.CodecIndex = i;
130
131 RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned));
132 RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned));
133
134 Codecs.Add(info);
135 }
136 return S_OK;
137 }
138
ReadProp(GetHandlerPropertyFunc getProp,GetHandlerPropertyFunc2 getProp2,UInt32 index,PROPID propID,NCOM::CPropVariant & prop)139 static HRESULT ReadProp(
140 GetHandlerPropertyFunc getProp,
141 GetHandlerPropertyFunc2 getProp2,
142 UInt32 index, PROPID propID, NCOM::CPropVariant &prop)
143 {
144 if (getProp2)
145 return getProp2(index, propID, &prop);;
146 return getProp(propID, &prop);
147 }
148
ReadBoolProp(GetHandlerPropertyFunc getProp,GetHandlerPropertyFunc2 getProp2,UInt32 index,PROPID propID,bool & res)149 static HRESULT ReadBoolProp(
150 GetHandlerPropertyFunc getProp,
151 GetHandlerPropertyFunc2 getProp2,
152 UInt32 index, PROPID propID, bool &res)
153 {
154 NCOM::CPropVariant prop;
155 RINOK(ReadProp(getProp, getProp2, index, propID, prop));
156 if (prop.vt == VT_BOOL)
157 res = VARIANT_BOOLToBool(prop.boolVal);
158 else if (prop.vt != VT_EMPTY)
159 return E_FAIL;
160 return S_OK;
161 }
162
ReadStringProp(GetHandlerPropertyFunc getProp,GetHandlerPropertyFunc2 getProp2,UInt32 index,PROPID propID,UString & res)163 static HRESULT ReadStringProp(
164 GetHandlerPropertyFunc getProp,
165 GetHandlerPropertyFunc2 getProp2,
166 UInt32 index, PROPID propID, UString &res)
167 {
168 NCOM::CPropVariant prop;
169 RINOK(ReadProp(getProp, getProp2, index, propID, prop));
170 if (prop.vt == VT_BSTR)
171 res = prop.bstrVal;
172 else if (prop.vt != VT_EMPTY)
173 return E_FAIL;
174 return S_OK;
175 }
176
177 #endif
178
179 static const unsigned int kNumArcsMax = 48;
180 static unsigned int g_NumArcs = 0;
181 static const CArcInfo *g_Arcs[kNumArcsMax];
RegisterArc(const CArcInfo * arcInfo)182 void RegisterArc(const CArcInfo *arcInfo)
183 {
184 if (g_NumArcs < kNumArcsMax)
185 g_Arcs[g_NumArcs++] = arcInfo;
186 }
187
SplitString(const UString & srcString,UStringVector & destStrings)188 static void SplitString(const UString &srcString, UStringVector &destStrings)
189 {
190 destStrings.Clear();
191 UString s;
192 int len = srcString.Length();
193 if (len == 0)
194 return;
195 for (int i = 0; i < len; i++)
196 {
197 wchar_t c = srcString[i];
198 if (c == L' ')
199 {
200 if (!s.IsEmpty())
201 {
202 destStrings.Add(s);
203 s.Empty();
204 }
205 }
206 else
207 s += c;
208 }
209 if (!s.IsEmpty())
210 destStrings.Add(s);
211 }
212
FindExtension(const UString & ext) const213 int CArcInfoEx::FindExtension(const UString &ext) const
214 {
215 for (int i = 0; i < Exts.Size(); i++)
216 if (ext.CompareNoCase(Exts[i].Ext) == 0)
217 return i;
218 return -1;
219 }
220
AddExts(const wchar_t * ext,const wchar_t * addExt)221 void CArcInfoEx::AddExts(const wchar_t *ext, const wchar_t *addExt)
222 {
223 UStringVector exts, addExts;
224 if (ext != 0)
225 SplitString(ext, exts);
226 if (addExt != 0)
227 SplitString(addExt, addExts);
228 for (int i = 0; i < exts.Size(); i++)
229 {
230 CArcExtInfo extInfo;
231 extInfo.Ext = exts[i];
232 if (i < addExts.Size())
233 {
234 extInfo.AddExt = addExts[i];
235 if (extInfo.AddExt == L"*")
236 extInfo.AddExt.Empty();
237 }
238 Exts.Add(extInfo);
239 }
240 }
241
242 #ifdef EXTERNAL_CODECS
243
LoadFormats()244 HRESULT CCodecs::LoadFormats()
245 {
246 const NDLL::CLibrary &lib = Libs.Back().Lib;
247 GetHandlerPropertyFunc getProp = 0;
248 GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2)lib.GetProc("GetHandlerProperty2");
249 if (getProp2 == NULL)
250 {
251 getProp = (GetHandlerPropertyFunc)lib.GetProc("GetHandlerProperty");
252 if (getProp == NULL)
253 return S_OK;
254 }
255
256 UInt32 numFormats = 1;
257 GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc)lib.GetProc("GetNumberOfFormats");
258 if (getNumberOfFormats != NULL)
259 {
260 RINOK(getNumberOfFormats(&numFormats));
261 }
262 if (getProp2 == NULL)
263 numFormats = 1;
264
265 for(UInt32 i = 0; i < numFormats; i++)
266 {
267 CArcInfoEx item;
268 item.LibIndex = Libs.Size() - 1;
269 item.FormatIndex = i;
270
271 RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kName, item.Name));
272
273 NCOM::CPropVariant prop;
274 if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK)
275 continue;
276 if (prop.vt != VT_BSTR)
277 continue;
278 item.ClassID = *(const GUID *)prop.bstrVal;
279 prop.Clear();
280
281 UString ext, addExt;
282 RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext));
283 RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt));
284 item.AddExts(ext, addExt);
285
286 ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, item.UpdateEnabled);
287 if (item.UpdateEnabled)
288 ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, item.KeepName);
289
290 if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK)
291 if (prop.vt == VT_BSTR)
292 {
293 UINT len = ::SysStringByteLen(prop.bstrVal);
294 item.StartSignature.SetCapacity(len);
295 memmove(item.StartSignature, prop.bstrVal, len);
296 }
297 Formats.Add(item);
298 }
299 return S_OK;
300 }
301
302 #ifdef NEW_FOLDER_INTERFACE
LoadIcons(HMODULE m)303 void CCodecIcons::LoadIcons(HMODULE m)
304 {
305 UString iconTypes = MyLoadStringW(m, kIconTypesResId);
306 UStringVector pairs;
307 SplitString(iconTypes, pairs);
308 for (int i = 0; i < pairs.Size(); i++)
309 {
310 const UString &s = pairs[i];
311 int pos = s.Find(L':');
312 CIconPair iconPair;
313 iconPair.IconIndex = -1;
314 if (pos < 0)
315 pos = s.Length();
316 else
317 {
318 UString num = s.Mid(pos + 1);
319 if (!num.IsEmpty())
320 {
321 const wchar_t *end;
322 iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end);
323 if (*end != L'\0')
324 continue;
325 }
326 }
327 iconPair.Ext = s.Left(pos);
328 IconPairs.Add(iconPair);
329 }
330 }
331
FindIconIndex(const UString & ext,int & iconIndex) const332 bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const
333 {
334 iconIndex = -1;
335 for (int i = 0; i < IconPairs.Size(); i++)
336 {
337 const CIconPair &pair = IconPairs[i];
338 if (ext.CompareNoCase(pair.Ext) == 0)
339 {
340 iconIndex = pair.IconIndex;
341 return true;
342 }
343 }
344 return false;
345 }
346 #endif
347
348 #ifdef _7ZIP_LARGE_PAGES
349 extern "C"
350 {
351 extern SIZE_T g_LargePageSize;
352 }
353 #endif
354
LoadDll(const FString & dllPath,bool needCheckDll)355 HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll)
356 {
357 if (needCheckDll)
358 {
359 NDLL::CLibrary library;
360 if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE))
361 return S_OK;
362 }
363 Libs.Add(CCodecLib());
364 CCodecLib &lib = Libs.Back();
365 #ifdef NEW_FOLDER_INTERFACE
366 lib.Path = dllPath;
367 #endif
368 bool used = false;
369 HRESULT res = S_OK;
370 if (lib.Lib.Load(dllPath))
371 {
372 #ifdef NEW_FOLDER_INTERFACE
373 lib.LoadIcons();
374 #endif
375
376 #ifdef _7ZIP_LARGE_PAGES
377 if (g_LargePageSize != 0)
378 {
379 SetLargePageModeFunc setLargePageMode = (SetLargePageModeFunc)lib.Lib.GetProc("SetLargePageMode");
380 if (setLargePageMode != 0)
381 setLargePageMode();
382 }
383 #endif
384
385 lib.CreateObject = (CreateObjectFunc)lib.Lib.GetProc("CreateObject");
386 if (lib.CreateObject != 0)
387 {
388 int startSize = Codecs.Size();
389 res = LoadCodecs();
390 used = (Codecs.Size() != startSize);
391 if (res == S_OK)
392 {
393 startSize = Formats.Size();
394 res = LoadFormats();
395 used = used || (Formats.Size() != startSize);
396 }
397 }
398 }
399 if (!used)
400 Libs.DeleteBack();
401 return res;
402 }
403
LoadDllsFromFolder(const FString & folderPrefix)404 HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPrefix)
405 {
406 NFile::NFind::CEnumerator enumerator(folderPrefix + FCHAR_ANY_MASK);
407 NFile::NFind::CFileInfo fi;
408 while (enumerator.Next(fi))
409 {
410 if (fi.IsDir())
411 continue;
412 RINOK(LoadDll(folderPrefix + fi.Name, true));
413 }
414 return S_OK;
415 }
416
417 #endif
418
419 #ifndef _SFX
SetBuffer(CByteBuffer & bb,const Byte * data,int size)420 static inline void SetBuffer(CByteBuffer &bb, const Byte *data, int size)
421 {
422 bb.SetCapacity(size);
423 memmove((Byte *)bb, data, size);
424 }
425 #endif
426
Load()427 HRESULT CCodecs::Load()
428 {
429 #ifdef NEW_FOLDER_INTERFACE
430 InternalIcons.LoadIcons(g_hInstance);
431 #endif
432
433 Formats.Clear();
434 #ifdef EXTERNAL_CODECS
435 Codecs.Clear();
436 #endif
437 for (UInt32 i = 0; i < g_NumArcs; i++)
438 {
439 const CArcInfo &arc = *g_Arcs[i];
440 CArcInfoEx item;
441 item.Name = arc.Name;
442 item.CreateInArchive = arc.CreateInArchive;
443 item.CreateOutArchive = arc.CreateOutArchive;
444 item.AddExts(arc.Ext, arc.AddExt);
445 item.UpdateEnabled = (arc.CreateOutArchive != 0);
446 item.KeepName = arc.KeepName;
447
448 #ifndef _SFX
449 SetBuffer(item.StartSignature, arc.Signature, arc.SignatureSize);
450 #endif
451 Formats.Add(item);
452 }
453 #ifdef EXTERNAL_CODECS
454 const FString baseFolder = GetBaseFolderPrefixFromRegistry();
455 RINOK(LoadDll(baseFolder + kMainDll, false));
456 RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName FSTRING_PATH_SEPARATOR));
457 RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName FSTRING_PATH_SEPARATOR));
458 #endif
459 return S_OK;
460 }
461
462 #ifndef _SFX
463
FindFormatForArchiveName(const UString & arcPath) const464 int CCodecs::FindFormatForArchiveName(const UString &arcPath) const
465 {
466 int slashPos = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR);
467 int dotPos = arcPath.ReverseFind(L'.');
468 if (dotPos < 0 || dotPos < slashPos)
469 return -1;
470 const UString ext = arcPath.Mid(dotPos + 1);
471 for (int i = 0; i < Formats.Size(); i++)
472 {
473 const CArcInfoEx &arc = Formats[i];
474 if (!arc.UpdateEnabled)
475 continue;
476 if (arc.FindExtension(ext) >= 0)
477 return i;
478 }
479 return -1;
480 }
481
FindFormatForExtension(const UString & ext) const482 int CCodecs::FindFormatForExtension(const UString &ext) const
483 {
484 if (ext.IsEmpty())
485 return -1;
486 for (int i = 0; i < Formats.Size(); i++)
487 if (Formats[i].FindExtension(ext) >= 0)
488 return i;
489 return -1;
490 }
491
FindFormatForArchiveType(const UString & arcType) const492 int CCodecs::FindFormatForArchiveType(const UString &arcType) const
493 {
494 for (int i = 0; i < Formats.Size(); i++)
495 if (Formats[i].Name.CompareNoCase(arcType) == 0)
496 return i;
497 return -1;
498 }
499
FindFormatForArchiveType(const UString & arcType,CIntVector & formatIndices) const500 bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const
501 {
502 formatIndices.Clear();
503 for (int pos = 0; pos < arcType.Length();)
504 {
505 int pos2 = arcType.Find('.', pos);
506 if (pos2 < 0)
507 pos2 = arcType.Length();
508 const UString name = arcType.Mid(pos, pos2 - pos);
509 int index = FindFormatForArchiveType(name);
510 if (index < 0 && name != L"*")
511 {
512 formatIndices.Clear();
513 return false;
514 }
515 formatIndices.Add(index);
516 pos = pos2 + 1;
517 }
518 return true;
519 }
520
521 #endif
522
523 #ifdef EXTERNAL_CODECS
524
525 #ifdef EXPORT_CODECS
526 extern unsigned int g_NumCodecs;
527 STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject);
528 STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);
529 // STDAPI GetNumberOfMethods(UInt32 *numCodecs);
530 #endif
531
GetNumberOfMethods(UInt32 * numMethods)532 STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods)
533 {
534 *numMethods =
535 #ifdef EXPORT_CODECS
536 g_NumCodecs +
537 #endif
538 Codecs.Size();
539 return S_OK;
540 }
541
GetProperty(UInt32 index,PROPID propID,PROPVARIANT * value)542 STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
543 {
544 #ifdef EXPORT_CODECS
545 if (index < g_NumCodecs)
546 return GetMethodProperty(index, propID, value);
547 #endif
548
549 const CDllCodecInfo &ci = Codecs[index
550 #ifdef EXPORT_CODECS
551 - g_NumCodecs
552 #endif
553 ];
554
555 if (propID == NMethodPropID::kDecoderIsAssigned)
556 {
557 NWindows::NCOM::CPropVariant propVariant;
558 propVariant = ci.DecoderIsAssigned;
559 propVariant.Detach(value);
560 return S_OK;
561 }
562 if (propID == NMethodPropID::kEncoderIsAssigned)
563 {
564 NWindows::NCOM::CPropVariant propVariant;
565 propVariant = ci.EncoderIsAssigned;
566 propVariant.Detach(value);
567 return S_OK;
568 }
569 return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value);
570 }
571
CreateDecoder(UInt32 index,const GUID * iid,void ** coder)572 STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder)
573 {
574 #ifdef EXPORT_CODECS
575 if (index < g_NumCodecs)
576 return CreateCoder2(false, index, iid, coder);
577 #endif
578 const CDllCodecInfo &ci = Codecs[index
579 #ifdef EXPORT_CODECS
580 - g_NumCodecs
581 #endif
582 ];
583 if (ci.DecoderIsAssigned)
584 return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder);
585 return S_OK;
586 }
587
CreateEncoder(UInt32 index,const GUID * iid,void ** coder)588 STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder)
589 {
590 #ifdef EXPORT_CODECS
591 if (index < g_NumCodecs)
592 return CreateCoder2(true, index, iid, coder);
593 #endif
594 const CDllCodecInfo &ci = Codecs[index
595 #ifdef EXPORT_CODECS
596 - g_NumCodecs
597 #endif
598 ];
599 if (ci.EncoderIsAssigned)
600 return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder);
601 return S_OK;
602 }
603
CreateCoder(const UString & name,bool encode,CMyComPtr<ICompressCoder> & coder) const604 HRESULT CCodecs::CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const
605 {
606 for (int i = 0; i < Codecs.Size(); i++)
607 {
608 const CDllCodecInfo &codec = Codecs[i];
609 if (encode && !codec.EncoderIsAssigned || !encode && !codec.DecoderIsAssigned)
610 continue;
611 const CCodecLib &lib = Libs[codec.LibIndex];
612 UString res;
613 NWindows::NCOM::CPropVariant prop;
614 RINOK(lib.GetMethodProperty(codec.CodecIndex, NMethodPropID::kName, &prop));
615 if (prop.vt == VT_BSTR)
616 res = prop.bstrVal;
617 else if (prop.vt != VT_EMPTY)
618 continue;
619 if (name.CompareNoCase(res) == 0)
620 return lib.CreateObject(encode ? &codec.Encoder : &codec.Decoder, &IID_ICompressCoder, (void **)&coder);
621 }
622 return CLASS_E_CLASSNOTAVAILABLE;
623 }
624
GetCodecLibIndex(UInt32 index)625 int CCodecs::GetCodecLibIndex(UInt32 index)
626 {
627 #ifdef EXPORT_CODECS
628 if (index < g_NumCodecs)
629 return -1;
630 #endif
631 #ifdef EXTERNAL_CODECS
632 const CDllCodecInfo &ci = Codecs[index
633 #ifdef EXPORT_CODECS
634 - g_NumCodecs
635 #endif
636 ];
637 return ci.LibIndex;
638 #else
639 return -1;
640 #endif
641 }
642
GetCodecEncoderIsAssigned(UInt32 index)643 bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index)
644 {
645 #ifdef EXPORT_CODECS
646 if (index < g_NumCodecs)
647 {
648 NWindows::NCOM::CPropVariant prop;
649 if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK)
650 if (prop.vt != VT_EMPTY)
651 return true;
652 return false;
653 }
654 #endif
655 #ifdef EXTERNAL_CODECS
656 const CDllCodecInfo &ci = Codecs[index
657 #ifdef EXPORT_CODECS
658 - g_NumCodecs
659 #endif
660 ];
661 return ci.EncoderIsAssigned;
662 #else
663 return false;
664 #endif
665 }
666
GetCodecId(UInt32 index,UInt64 & id)667 HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id)
668 {
669 UString s;
670 NWindows::NCOM::CPropVariant prop;
671 RINOK(GetProperty(index, NMethodPropID::kID, &prop));
672 if (prop.vt != VT_UI8)
673 return E_INVALIDARG;
674 id = prop.uhVal.QuadPart;
675 return S_OK;
676 }
677
GetCodecName(UInt32 index)678 UString CCodecs::GetCodecName(UInt32 index)
679 {
680 UString s;
681 NWindows::NCOM::CPropVariant prop;
682 if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK)
683 if (prop.vt == VT_BSTR)
684 s = prop.bstrVal;
685 return s;
686 }
687
688 #endif
689