Home | History | Annotate | Download | only in Common
      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 
     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");
     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 
     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 
     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 
    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 
    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 
    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 
    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];
    182 void RegisterArc(const CArcInfo *arcInfo)
    183 {
    184   if (g_NumArcs < kNumArcsMax)
    185     g_Arcs[g_NumArcs++] = arcInfo;
    186 }
    187 
    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 
    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 
    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
    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 
    324 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 
    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 
    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
    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 
    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 
    456 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 
    475 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 
    485 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 
    493 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 
    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 
    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 
    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 
    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 
    597 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 
    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 
    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 
    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 
    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