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 |
|