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