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