• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/Registry.h"
26 #endif
27 
28 using namespace NWindows;
29 using namespace NFile;
30 
31 #ifdef _WIN32
32 extern HINSTANCE g_hInstance;
33 #endif
34 
GetLibraryFolderPrefix()35 static CSysString GetLibraryFolderPrefix()
36 {
37   #ifdef _WIN32
38   TCHAR fullPath[MAX_PATH + 1];
39   ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH);
40   CSysString path = fullPath;
41   int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
42   return path.Left(pos + 1);
43   #else
44   return CSysString(); // FIX IT
45   #endif
46 }
47 
48 #define kCodecsFolderName TEXT("Codecs")
49 #define kFormatsFolderName TEXT("Formats")
50 static const TCHAR *kMainDll = TEXT("7z.dll");
51 
52 #ifdef _WIN32
53 static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip");
54 static LPCTSTR kProgramPathValue = TEXT("Path");
ReadPathFromRegistry(HKEY baseKey,CSysString & path)55 static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path)
56 {
57   NRegistry::CKey key;
58   if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS)
59     if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS)
60     {
61       NName::NormalizeDirPathPrefix(path);
62       return true;
63     }
64   return false;
65 }
66 
67 #endif
68 
GetBaseFolderPrefixFromRegistry()69 CSysString GetBaseFolderPrefixFromRegistry()
70 {
71   CSysString moduleFolderPrefix = GetLibraryFolderPrefix();
72   #ifdef _WIN32
73   if (!NFind::DoesFileExist(moduleFolderPrefix + kMainDll) &&
74       !NFind::DoesDirExist(moduleFolderPrefix + kCodecsFolderName) &&
75       !NFind::DoesDirExist(moduleFolderPrefix + kFormatsFolderName))
76   {
77     CSysString path;
78     if (ReadPathFromRegistry(HKEY_CURRENT_USER, path))
79       return path;
80     if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path))
81       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 
AddExts(const wchar_t * ext,const wchar_t * addExt)213 void CArcInfoEx::AddExts(const wchar_t *ext, const wchar_t *addExt)
214 {
215   UStringVector exts, addExts;
216   if (ext != 0)
217     SplitString(ext, exts);
218   if (addExt != 0)
219     SplitString(addExt, addExts);
220   for (int i = 0; i < exts.Size(); i++)
221   {
222     CArcExtInfo extInfo;
223     extInfo.Ext = exts[i];
224     if (i < addExts.Size())
225     {
226       extInfo.AddExt = addExts[i];
227       if (extInfo.AddExt == L"*")
228         extInfo.AddExt.Empty();
229     }
230     Exts.Add(extInfo);
231   }
232 }
233 
234 #ifdef EXTERNAL_CODECS
235 
LoadFormats()236 HRESULT CCodecs::LoadFormats()
237 {
238   const NDLL::CLibrary &lib = Libs.Back().Lib;
239   GetHandlerPropertyFunc getProp = 0;
240   GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2)lib.GetProc("GetHandlerProperty2");
241   if (getProp2 == NULL)
242   {
243     getProp = (GetHandlerPropertyFunc)lib.GetProc("GetHandlerProperty");
244     if (getProp == NULL)
245       return S_OK;
246   }
247 
248   UInt32 numFormats = 1;
249   GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc)lib.GetProc("GetNumberOfFormats");
250   if (getNumberOfFormats != NULL)
251   {
252     RINOK(getNumberOfFormats(&numFormats));
253   }
254   if (getProp2 == NULL)
255     numFormats = 1;
256 
257   for(UInt32 i = 0; i < numFormats; i++)
258   {
259     CArcInfoEx item;
260     item.LibIndex = Libs.Size() - 1;
261     item.FormatIndex = i;
262 
263     RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kName, item.Name));
264 
265     NCOM::CPropVariant prop;
266     if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK)
267       continue;
268     if (prop.vt != VT_BSTR)
269       continue;
270     item.ClassID = *(const GUID *)prop.bstrVal;
271     prop.Clear();
272 
273     UString ext, addExt;
274     RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext));
275     RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt));
276     item.AddExts(ext, addExt);
277 
278     ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, item.UpdateEnabled);
279     if (item.UpdateEnabled)
280       ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, item.KeepName);
281 
282     if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK)
283       if (prop.vt == VT_BSTR)
284       {
285         UINT len = ::SysStringByteLen(prop.bstrVal);
286         item.StartSignature.SetCapacity(len);
287         memmove(item.StartSignature, prop.bstrVal, len);
288       }
289     Formats.Add(item);
290   }
291   return S_OK;
292 }
293 
294 #ifdef NEW_FOLDER_INTERFACE
LoadIcons(HMODULE m)295 void CCodecIcons::LoadIcons(HMODULE m)
296 {
297   UString iconTypes = MyLoadStringW(m, kIconTypesResId);
298   UStringVector pairs;
299   SplitString(iconTypes, pairs);
300   for (int i = 0; i < pairs.Size(); i++)
301   {
302     const UString &s = pairs[i];
303     int pos = s.Find(L':');
304     CIconPair iconPair;
305     iconPair.IconIndex = -1;
306     if (pos < 0)
307       pos = s.Length();
308     else
309     {
310       UString num = s.Mid(pos + 1);
311       if (!num.IsEmpty())
312       {
313         const wchar_t *end;
314         iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end);
315         if (*end != L'\0')
316           continue;
317       }
318     }
319     iconPair.Ext = s.Left(pos);
320     IconPairs.Add(iconPair);
321   }
322 }
323 
FindIconIndex(const UString & ext,int & iconIndex) const324 bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const
325 {
326   iconIndex = -1;
327   for (int i = 0; i < IconPairs.Size(); i++)
328   {
329     const CIconPair &pair = IconPairs[i];
330     if (ext.CompareNoCase(pair.Ext) == 0)
331     {
332       iconIndex = pair.IconIndex;
333       return true;
334     }
335   }
336   return false;
337 }
338 #endif
339 
340 #ifdef _7ZIP_LARGE_PAGES
341 extern "C"
342 {
343   extern SIZE_T g_LargePageSize;
344 }
345 #endif
346 
LoadDll(const CSysString & dllPath,bool needCheckDll)347 HRESULT CCodecs::LoadDll(const CSysString &dllPath, bool needCheckDll)
348 {
349   if (needCheckDll)
350   {
351     NDLL::CLibrary library;
352     if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE))
353       return S_OK;
354   }
355   Libs.Add(CCodecLib());
356   CCodecLib &lib = Libs.Back();
357   #ifdef NEW_FOLDER_INTERFACE
358   lib.Path = dllPath;
359   #endif
360   bool used = false;
361   HRESULT res = S_OK;
362   if (lib.Lib.Load(dllPath))
363   {
364     #ifdef NEW_FOLDER_INTERFACE
365     lib.LoadIcons();
366     #endif
367 
368     #ifdef _7ZIP_LARGE_PAGES
369     if (g_LargePageSize != 0)
370     {
371       SetLargePageModeFunc setLargePageMode = (SetLargePageModeFunc)lib.Lib.GetProc("SetLargePageMode");
372       if (setLargePageMode != 0)
373         setLargePageMode();
374     }
375     #endif
376 
377     lib.CreateObject = (CreateObjectFunc)lib.Lib.GetProc("CreateObject");
378     if (lib.CreateObject != 0)
379     {
380       int startSize = Codecs.Size();
381       res = LoadCodecs();
382       used = (Codecs.Size() != startSize);
383       if (res == S_OK)
384       {
385         startSize = Formats.Size();
386         res = LoadFormats();
387         used = used || (Formats.Size() != startSize);
388       }
389     }
390   }
391   if (!used)
392     Libs.DeleteBack();
393   return res;
394 }
395 
LoadDllsFromFolder(const CSysString & folderPrefix)396 HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix)
397 {
398   NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*")));
399   NFile::NFind::CFileInfo fi;
400   while (enumerator.Next(fi))
401   {
402     if (fi.IsDir())
403       continue;
404     RINOK(LoadDll(folderPrefix + fi.Name, true));
405   }
406   return S_OK;
407 }
408 
409 #endif
410 
411 #ifndef _SFX
SetBuffer(CByteBuffer & bb,const Byte * data,int size)412 static inline void SetBuffer(CByteBuffer &bb, const Byte *data, int size)
413 {
414   bb.SetCapacity(size);
415   memmove((Byte *)bb, data, size);
416 }
417 #endif
418 
Load()419 HRESULT CCodecs::Load()
420 {
421   #ifdef NEW_FOLDER_INTERFACE
422   InternalIcons.LoadIcons(g_hInstance);
423   #endif
424 
425   Formats.Clear();
426   #ifdef EXTERNAL_CODECS
427   Codecs.Clear();
428   #endif
429   for (UInt32 i = 0; i < g_NumArcs; i++)
430   {
431     const CArcInfo &arc = *g_Arcs[i];
432     CArcInfoEx item;
433     item.Name = arc.Name;
434     item.CreateInArchive = arc.CreateInArchive;
435     item.CreateOutArchive = arc.CreateOutArchive;
436     item.AddExts(arc.Ext, arc.AddExt);
437     item.UpdateEnabled = (arc.CreateOutArchive != 0);
438     item.KeepName = arc.KeepName;
439 
440     #ifndef _SFX
441     SetBuffer(item.StartSignature, arc.Signature, arc.SignatureSize);
442     #endif
443     Formats.Add(item);
444   }
445   #ifdef EXTERNAL_CODECS
446   const CSysString baseFolder = GetBaseFolderPrefixFromRegistry();
447   RINOK(LoadDll(baseFolder + kMainDll, false));
448   RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName TEXT(STRING_PATH_SEPARATOR)));
449   RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName TEXT(STRING_PATH_SEPARATOR)));
450   #endif
451   return S_OK;
452 }
453 
454 #ifndef _SFX
455 
FindFormatForArchiveName(const UString & arcPath) const456 int CCodecs::FindFormatForArchiveName(const UString &arcPath) const
457 {
458   int slashPos1 = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR);
459   int slashPos2 = arcPath.ReverseFind(L'.');
460   int dotPos = arcPath.ReverseFind(L'.');
461   if (dotPos < 0 || dotPos < slashPos1 || dotPos < slashPos2)
462     return -1;
463   UString ext = arcPath.Mid(dotPos + 1);
464   for (int i = 0; i < Formats.Size(); i++)
465   {
466     const CArcInfoEx &arc = Formats[i];
467     if (!arc.UpdateEnabled)
468       continue;
469     if (arc.FindExtension(ext) >= 0)
470       return i;
471   }
472   return -1;
473 }
474 
FindFormatForExtension(const UString & ext) const475 int CCodecs::FindFormatForExtension(const UString &ext) const
476 {
477   if (ext.IsEmpty())
478     return -1;
479   for (int i = 0; i < Formats.Size(); i++)
480     if (Formats[i].FindExtension(ext) >= 0)
481       return i;
482   return -1;
483 }
484 
FindFormatForArchiveType(const UString & arcType) const485 int CCodecs::FindFormatForArchiveType(const UString &arcType) const
486 {
487   for (int i = 0; i < Formats.Size(); i++)
488     if (Formats[i].Name.CompareNoCase(arcType) == 0)
489       return i;
490   return -1;
491 }
492 
FindFormatForArchiveType(const UString & arcType,CIntVector & formatIndices) const493 bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const
494 {
495   formatIndices.Clear();
496   for (int pos = 0; pos < arcType.Length();)
497   {
498     int pos2 = arcType.Find('.', pos);
499     if (pos2 < 0)
500       pos2 = arcType.Length();
501     const UString name = arcType.Mid(pos, pos2 - pos);
502     int index = FindFormatForArchiveType(name);
503     if (index < 0 && name != L"*")
504     {
505       formatIndices.Clear();
506       return false;
507     }
508     formatIndices.Add(index);
509     pos = pos2 + 1;
510   }
511   return true;
512 }
513 
514 #endif
515 
516 #ifdef EXTERNAL_CODECS
517 
518 #ifdef EXPORT_CODECS
519 extern unsigned int g_NumCodecs;
520 STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject);
521 STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);
522 // STDAPI GetNumberOfMethods(UInt32 *numCodecs);
523 #endif
524 
GetNumberOfMethods(UInt32 * numMethods)525 STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods)
526 {
527   *numMethods =
528       #ifdef EXPORT_CODECS
529       g_NumCodecs +
530       #endif
531       Codecs.Size();
532   return S_OK;
533 }
534 
GetProperty(UInt32 index,PROPID propID,PROPVARIANT * value)535 STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
536 {
537   #ifdef EXPORT_CODECS
538   if (index < g_NumCodecs)
539     return GetMethodProperty(index, propID, value);
540   #endif
541 
542   const CDllCodecInfo &ci = Codecs[index
543       #ifdef EXPORT_CODECS
544       - g_NumCodecs
545       #endif
546       ];
547 
548   if (propID == NMethodPropID::kDecoderIsAssigned)
549   {
550     NWindows::NCOM::CPropVariant propVariant;
551     propVariant = ci.DecoderIsAssigned;
552     propVariant.Detach(value);
553     return S_OK;
554   }
555   if (propID == NMethodPropID::kEncoderIsAssigned)
556   {
557     NWindows::NCOM::CPropVariant propVariant;
558     propVariant = ci.EncoderIsAssigned;
559     propVariant.Detach(value);
560     return S_OK;
561   }
562   return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value);
563 }
564 
CreateDecoder(UInt32 index,const GUID * iid,void ** coder)565 STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder)
566 {
567   #ifdef EXPORT_CODECS
568   if (index < g_NumCodecs)
569     return CreateCoder2(false, index, iid, coder);
570   #endif
571   const CDllCodecInfo &ci = Codecs[index
572       #ifdef EXPORT_CODECS
573       - g_NumCodecs
574       #endif
575       ];
576   if (ci.DecoderIsAssigned)
577     return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder);
578   return S_OK;
579 }
580 
CreateEncoder(UInt32 index,const GUID * iid,void ** coder)581 STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder)
582 {
583   #ifdef EXPORT_CODECS
584   if (index < g_NumCodecs)
585     return CreateCoder2(true, index, iid, coder);
586   #endif
587   const CDllCodecInfo &ci = Codecs[index
588       #ifdef EXPORT_CODECS
589       - g_NumCodecs
590       #endif
591       ];
592   if (ci.EncoderIsAssigned)
593     return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder);
594   return S_OK;
595 }
596 
CreateCoder(const UString & name,bool encode,CMyComPtr<ICompressCoder> & coder) const597 HRESULT CCodecs::CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const
598 {
599   for (int i = 0; i < Codecs.Size(); i++)
600   {
601     const CDllCodecInfo &codec = Codecs[i];
602     if (encode && !codec.EncoderIsAssigned || !encode && !codec.DecoderIsAssigned)
603       continue;
604     const CCodecLib &lib = Libs[codec.LibIndex];
605     UString res;
606     NWindows::NCOM::CPropVariant prop;
607     RINOK(lib.GetMethodProperty(codec.CodecIndex, NMethodPropID::kName, &prop));
608     if (prop.vt == VT_BSTR)
609       res = prop.bstrVal;
610     else if (prop.vt != VT_EMPTY)
611       continue;
612     if (name.CompareNoCase(res) == 0)
613       return lib.CreateObject(encode ? &codec.Encoder : &codec.Decoder, &IID_ICompressCoder, (void **)&coder);
614   }
615   return CLASS_E_CLASSNOTAVAILABLE;
616 }
617 
GetCodecLibIndex(UInt32 index)618 int CCodecs::GetCodecLibIndex(UInt32 index)
619 {
620   #ifdef EXPORT_CODECS
621   if (index < g_NumCodecs)
622     return -1;
623   #endif
624   #ifdef EXTERNAL_CODECS
625   const CDllCodecInfo &ci = Codecs[index
626       #ifdef EXPORT_CODECS
627       - g_NumCodecs
628       #endif
629       ];
630   return ci.LibIndex;
631   #else
632   return -1;
633   #endif
634 }
635 
GetCodecEncoderIsAssigned(UInt32 index)636 bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index)
637 {
638   #ifdef EXPORT_CODECS
639   if (index < g_NumCodecs)
640   {
641     NWindows::NCOM::CPropVariant prop;
642     if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK)
643       if (prop.vt != VT_EMPTY)
644         return true;
645     return false;
646   }
647   #endif
648   #ifdef EXTERNAL_CODECS
649   const CDllCodecInfo &ci = Codecs[index
650       #ifdef EXPORT_CODECS
651       - g_NumCodecs
652       #endif
653       ];
654   return ci.EncoderIsAssigned;
655   #else
656   return false;
657   #endif
658 }
659 
GetCodecId(UInt32 index,UInt64 & id)660 HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id)
661 {
662   UString s;
663   NWindows::NCOM::CPropVariant prop;
664   RINOK(GetProperty(index, NMethodPropID::kID, &prop));
665   if (prop.vt != VT_UI8)
666     return E_INVALIDARG;
667   id = prop.uhVal.QuadPart;
668   return S_OK;
669 }
670 
GetCodecName(UInt32 index)671 UString CCodecs::GetCodecName(UInt32 index)
672 {
673   UString s;
674   NWindows::NCOM::CPropVariant prop;
675   if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK)
676     if (prop.vt == VT_BSTR)
677       s = prop.bstrVal;
678   return s;
679 }
680 
681 #endif
682