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