1 // LoadCodecs.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../../C/7zVersion.h"
6
7 #include "../../../Common/MyCom.h"
8 #include "../../../Common/StringToInt.h"
9 #include "../../../Common/StringConvert.h"
10
11 #include "../../../Windows/PropVariant.h"
12
13 #include "LoadCodecs.h"
14
15 using namespace NWindows;
16
17 #ifdef NEW_FOLDER_INTERFACE
18 #include "../../../Common/StringToInt.h"
19 #endif
20
21 #include "../../ICoder.h"
22 #include "../../Common/RegisterArc.h"
23
24 #ifdef EXTERNAL_CODECS
25
26 #include "../../../Windows/FileFind.h"
27 #include "../../../Windows/DLL.h"
28 #ifdef NEW_FOLDER_INTERFACE
29 #include "../../../Windows/ResourceString.h"
30 static const UINT kIconTypesResId = 100;
31 #endif
32
33 #ifdef _WIN32
34 #include "../../../Windows/FileName.h"
35 #include "../../../Windows/Registry.h"
36 #endif
37
38 using namespace NFile;
39
40 #ifdef _WIN32
41 extern HINSTANCE g_hInstance;
42 #endif
43
44 #define kCodecsFolderName FTEXT("Codecs")
45 #define kFormatsFolderName FTEXT("Formats")
46 static CFSTR kMainDll = FTEXT("7z.dll");
47
48 #ifdef _WIN32
49
50 static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip");
51 static LPCWSTR kProgramPathValue = L"Path";
52 static LPCWSTR kProgramPath2Value = L"Path"
53 #ifdef _WIN64
54 L"64";
55 #else
56 L"32";
57 #endif
58
ReadPathFromRegistry(HKEY baseKey,LPCWSTR value,FString & path)59 static bool ReadPathFromRegistry(HKEY baseKey, LPCWSTR value, FString &path)
60 {
61 NRegistry::CKey key;
62 if (key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS)
63 {
64 UString pathU;
65 if (key.QueryValue(value, pathU) == ERROR_SUCCESS)
66 {
67 path = us2fs(pathU);
68 NName::NormalizeDirPathPrefix(path);
69 return NFind::DoesFileExist(path + kMainDll);
70 }
71 }
72 return false;
73 }
74
75 #endif // _WIN32
76
77 #endif // EXTERNAL_CODECS
78
79
80 static const unsigned kNumArcsMax = 48;
81 static unsigned g_NumArcs = 0;
82 static const CArcInfo *g_Arcs[kNumArcsMax];
83
RegisterArc(const CArcInfo * arcInfo)84 void RegisterArc(const CArcInfo *arcInfo) throw()
85 {
86 if (g_NumArcs < kNumArcsMax)
87 {
88 g_Arcs[g_NumArcs] = arcInfo;
89 g_NumArcs++;
90 }
91 }
92
SplitString(const UString & srcString,UStringVector & destStrings)93 static void SplitString(const UString &srcString, UStringVector &destStrings)
94 {
95 destStrings.Clear();
96 UString s;
97 unsigned len = srcString.Len();
98 if (len == 0)
99 return;
100 for (unsigned i = 0; i < len; i++)
101 {
102 wchar_t c = srcString[i];
103 if (c == L' ')
104 {
105 if (!s.IsEmpty())
106 {
107 destStrings.Add(s);
108 s.Empty();
109 }
110 }
111 else
112 s += c;
113 }
114 if (!s.IsEmpty())
115 destStrings.Add(s);
116 }
117
FindExtension(const UString & ext) const118 int CArcInfoEx::FindExtension(const UString &ext) const
119 {
120 FOR_VECTOR (i, Exts)
121 if (ext.IsEqualToNoCase(Exts[i].Ext))
122 return i;
123 return -1;
124 }
125
AddExts(const UString & ext,const UString & addExt)126 void CArcInfoEx::AddExts(const UString &ext, const UString &addExt)
127 {
128 UStringVector exts, addExts;
129 SplitString(ext, exts);
130 SplitString(addExt, addExts);
131 FOR_VECTOR (i, exts)
132 {
133 CArcExtInfo extInfo;
134 extInfo.Ext = exts[i];
135 if (i < addExts.Size())
136 {
137 extInfo.AddExt = addExts[i];
138 if (extInfo.AddExt == L"*")
139 extInfo.AddExt.Empty();
140 }
141 Exts.Add(extInfo);
142 }
143 }
144
145 #ifndef _SFX
146
ParseSignatures(const Byte * data,unsigned size,CObjectVector<CByteBuffer> & signatures)147 static bool ParseSignatures(const Byte *data, unsigned size, CObjectVector<CByteBuffer> &signatures)
148 {
149 signatures.Clear();
150 while (size > 0)
151 {
152 unsigned len = *data++;
153 size--;
154 if (len > size)
155 return false;
156 signatures.AddNew().CopyFrom(data, len);
157 data += len;
158 size -= len;
159 }
160 return true;
161 }
162
163 #endif // _SFX
164
165 #ifdef EXTERNAL_CODECS
166
GetBaseFolderPrefixFromRegistry()167 static FString GetBaseFolderPrefixFromRegistry()
168 {
169 FString moduleFolderPrefix = NDLL::GetModuleDirPrefix();
170 #ifdef _WIN32
171 if (!NFind::DoesFileExist(moduleFolderPrefix + kMainDll) &&
172 !NFind::DoesDirExist(moduleFolderPrefix + kCodecsFolderName) &&
173 !NFind::DoesDirExist(moduleFolderPrefix + kFormatsFolderName))
174 {
175 FString path;
176 if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPath2Value, path)) return path;
177 if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPath2Value, path)) return path;
178 if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPathValue, path)) return path;
179 if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPathValue, path)) return path;
180 }
181 #endif
182 return moduleFolderPrefix;
183 }
184
GetCoderClass(Func_GetMethodProperty getMethodProperty,UInt32 index,PROPID propId,CLSID & clsId,bool & isAssigned)185 static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 index,
186 PROPID propId, CLSID &clsId, bool &isAssigned)
187 {
188 NCOM::CPropVariant prop;
189 isAssigned = false;
190 RINOK(getMethodProperty(index, propId, &prop));
191 if (prop.vt == VT_BSTR)
192 {
193 if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID))
194 return E_FAIL;
195 isAssigned = true;
196 clsId = *(const GUID *)prop.bstrVal;
197 }
198 else if (prop.vt != VT_EMPTY)
199 return E_FAIL;
200 return S_OK;
201 }
202
LoadCodecs()203 HRESULT CCodecs::LoadCodecs()
204 {
205 CCodecLib &lib = Libs.Back();
206 lib.GetMethodProperty = (Func_GetMethodProperty)lib.Lib.GetProc("GetMethodProperty");
207 if (lib.GetMethodProperty)
208 {
209 UInt32 numMethods = 1;
210 Func_GetNumberOfMethods getNumberOfMethodsFunc = (Func_GetNumberOfMethods)lib.Lib.GetProc("GetNumberOfMethods");
211 if (getNumberOfMethodsFunc)
212 {
213 RINOK(getNumberOfMethodsFunc(&numMethods));
214 }
215 for (UInt32 i = 0; i < numMethods; i++)
216 {
217 CDllCodecInfo info;
218 info.LibIndex = Libs.Size() - 1;
219 info.CodecIndex = i;
220 RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned));
221 RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned));
222 Codecs.Add(info);
223 }
224 }
225
226 Func_GetHashers getHashers = (Func_GetHashers)lib.Lib.GetProc("GetHashers");
227 if (getHashers)
228 {
229 RINOK(getHashers(&lib.Hashers));
230 if (lib.Hashers)
231 {
232 UInt32 numMethods = lib.Hashers->GetNumHashers();
233 for (UInt32 i = 0; i < numMethods; i++)
234 {
235 CDllHasherInfo info;
236 info.LibIndex = Libs.Size() - 1;
237 info.HasherIndex = i;
238 Hashers.Add(info);
239 }
240 }
241 }
242 return S_OK;
243 }
244
GetProp(Func_GetHandlerProperty getProp,Func_GetHandlerProperty2 getProp2,UInt32 index,PROPID propID,NCOM::CPropVariant & prop)245 static HRESULT GetProp(
246 Func_GetHandlerProperty getProp,
247 Func_GetHandlerProperty2 getProp2,
248 UInt32 index, PROPID propID, NCOM::CPropVariant &prop)
249 {
250 if (getProp2)
251 return getProp2(index, propID, &prop);;
252 return getProp(propID, &prop);
253 }
254
GetProp_Bool(Func_GetHandlerProperty getProp,Func_GetHandlerProperty2 getProp2,UInt32 index,PROPID propID,bool & res)255 static HRESULT GetProp_Bool(
256 Func_GetHandlerProperty getProp,
257 Func_GetHandlerProperty2 getProp2,
258 UInt32 index, PROPID propID, bool &res)
259 {
260 res = false;
261 NCOM::CPropVariant prop;
262 RINOK(GetProp(getProp, getProp2, index, propID, prop));
263 if (prop.vt == VT_BOOL)
264 res = VARIANT_BOOLToBool(prop.boolVal);
265 else if (prop.vt != VT_EMPTY)
266 return E_FAIL;
267 return S_OK;
268 }
269
GetProp_UInt32(Func_GetHandlerProperty getProp,Func_GetHandlerProperty2 getProp2,UInt32 index,PROPID propID,UInt32 & res,bool & defined)270 static HRESULT GetProp_UInt32(
271 Func_GetHandlerProperty getProp,
272 Func_GetHandlerProperty2 getProp2,
273 UInt32 index, PROPID propID, UInt32 &res, bool &defined)
274 {
275 res = 0;
276 defined = false;
277 NCOM::CPropVariant prop;
278 RINOK(GetProp(getProp, getProp2, index, propID, prop));
279 if (prop.vt == VT_UI4)
280 {
281 res = prop.ulVal;
282 defined = true;
283 }
284 else if (prop.vt != VT_EMPTY)
285 return E_FAIL;
286 return S_OK;
287 }
288
GetProp_String(Func_GetHandlerProperty getProp,Func_GetHandlerProperty2 getProp2,UInt32 index,PROPID propID,UString & res)289 static HRESULT GetProp_String(
290 Func_GetHandlerProperty getProp,
291 Func_GetHandlerProperty2 getProp2,
292 UInt32 index, PROPID propID, UString &res)
293 {
294 res.Empty();
295 NCOM::CPropVariant prop;
296 RINOK(GetProp(getProp, getProp2, index, propID, prop));
297 if (prop.vt == VT_BSTR)
298 res = prop.bstrVal;
299 else if (prop.vt != VT_EMPTY)
300 return E_FAIL;
301 return S_OK;
302 }
303
GetProp_RawData(Func_GetHandlerProperty getProp,Func_GetHandlerProperty2 getProp2,UInt32 index,PROPID propID,CByteBuffer & bb)304 static HRESULT GetProp_RawData(
305 Func_GetHandlerProperty getProp,
306 Func_GetHandlerProperty2 getProp2,
307 UInt32 index, PROPID propID, CByteBuffer &bb)
308 {
309 bb.Free();
310 NCOM::CPropVariant prop;
311 RINOK(GetProp(getProp, getProp2, index, propID, prop));
312 if (prop.vt == VT_BSTR)
313 {
314 UINT len = ::SysStringByteLen(prop.bstrVal);
315 bb.CopyFrom((const Byte *)prop.bstrVal, len);
316 }
317 else if (prop.vt != VT_EMPTY)
318 return E_FAIL;
319 return S_OK;
320 }
321
322 static const UInt32 kArcFlagsPars[] =
323 {
324 NArchive::NHandlerPropID::kKeepName, NArcInfoFlags::kKeepName,
325 NArchive::NHandlerPropID::kAltStreams, NArcInfoFlags::kAltStreams,
326 NArchive::NHandlerPropID::kNtSecure, NArcInfoFlags::kNtSecure
327 };
328
LoadFormats()329 HRESULT CCodecs::LoadFormats()
330 {
331 const NDLL::CLibrary &lib = Libs.Back().Lib;
332
333 Func_GetHandlerProperty getProp = NULL;
334 Func_GetHandlerProperty2 getProp2 = (Func_GetHandlerProperty2)lib.GetProc("GetHandlerProperty2");
335 Func_GetIsArc getIsArc = (Func_GetIsArc)lib.GetProc("GetIsArc");
336
337 UInt32 numFormats = 1;
338
339 if (getProp2)
340 {
341 Func_GetNumberOfFormats getNumberOfFormats = (Func_GetNumberOfFormats)lib.GetProc("GetNumberOfFormats");
342 if (getNumberOfFormats)
343 {
344 RINOK(getNumberOfFormats(&numFormats));
345 }
346 }
347 else
348 {
349 getProp = (Func_GetHandlerProperty)lib.GetProc("GetHandlerProperty");
350 if (!getProp)
351 return S_OK;
352 }
353
354 for (UInt32 i = 0; i < numFormats; i++)
355 {
356 CArcInfoEx item;
357 item.LibIndex = Libs.Size() - 1;
358 item.FormatIndex = i;
359
360 RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kName, item.Name));
361
362 {
363 NCOM::CPropVariant prop;
364 if (GetProp(getProp, getProp2, i, NArchive::NHandlerPropID::kClassID, prop) != S_OK)
365 continue;
366 if (prop.vt != VT_BSTR)
367 continue;
368 if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID))
369 return E_FAIL;
370 item.ClassID = *(const GUID *)prop.bstrVal;
371 prop.Clear();
372 }
373
374 UString ext, addExt;
375 RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kExtension, ext));
376 RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kAddExtension, addExt));
377 item.AddExts(ext, addExt);
378
379 GetProp_Bool(getProp, getProp2, i, NArchive::NHandlerPropID::kUpdate, item.UpdateEnabled);
380 bool flags_Defined = false;
381 RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kFlags, item.Flags, flags_Defined));
382 item.NewInterface = flags_Defined;
383 if (!flags_Defined) // && item.UpdateEnabled
384 {
385 // support for DLL version before 9.31:
386 for (unsigned j = 0; j < ARRAY_SIZE(kArcFlagsPars); j += 2)
387 {
388 bool val = false;
389 GetProp_Bool(getProp, getProp2, i, kArcFlagsPars[j], val);
390 if (val)
391 item.Flags |= kArcFlagsPars[j + 1];
392 }
393 }
394
395 CByteBuffer sig;
396 RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kSignature, sig));
397 if (sig.Size() != 0)
398 item.Signatures.Add(sig);
399 else
400 {
401 RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kMultiSignature, sig));
402 ParseSignatures(sig, (unsigned)sig.Size(), item.Signatures);
403 }
404
405 bool signatureOffset_Defined;
406 RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kSignatureOffset, item.SignatureOffset, signatureOffset_Defined));
407
408 // bool version_Defined;
409 // RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kVersion, item.Version, version_Defined));
410
411 if (getIsArc)
412 getIsArc(i, &item.IsArcFunc);
413
414 Formats.Add(item);
415 }
416 return S_OK;
417 }
418
419 #ifdef NEW_FOLDER_INTERFACE
LoadIcons(HMODULE m)420 void CCodecIcons::LoadIcons(HMODULE m)
421 {
422 UString iconTypes;
423 MyLoadString(m, kIconTypesResId, iconTypes);
424 UStringVector pairs;
425 SplitString(iconTypes, pairs);
426 FOR_VECTOR (i, pairs)
427 {
428 const UString &s = pairs[i];
429 int pos = s.Find(L':');
430 CIconPair iconPair;
431 iconPair.IconIndex = -1;
432 if (pos < 0)
433 pos = s.Len();
434 else
435 {
436 UString num = s.Ptr(pos + 1);
437 if (!num.IsEmpty())
438 {
439 const wchar_t *end;
440 iconPair.IconIndex = ConvertStringToUInt32(num, &end);
441 if (*end != 0)
442 continue;
443 }
444 }
445 iconPair.Ext = s.Left(pos);
446 IconPairs.Add(iconPair);
447 }
448 }
449
FindIconIndex(const UString & ext,int & iconIndex) const450 bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const
451 {
452 iconIndex = -1;
453 FOR_VECTOR (i, IconPairs)
454 {
455 const CIconPair &pair = IconPairs[i];
456 if (ext.IsEqualToNoCase(pair.Ext))
457 {
458 iconIndex = pair.IconIndex;
459 return true;
460 }
461 }
462 return false;
463 }
464
465 #endif // EXTERNAL_CODECS
466
467 #ifdef _7ZIP_LARGE_PAGES
468 extern "C"
469 {
470 extern SIZE_T g_LargePageSize;
471 }
472 #endif
473
LoadDll(const FString & dllPath,bool needCheckDll)474 HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll)
475 {
476 if (needCheckDll)
477 {
478 NDLL::CLibrary library;
479 if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE))
480 return S_OK;
481 }
482 Libs.Add(CCodecLib());
483 CCodecLib &lib = Libs.Back();
484 lib.Path = dllPath;
485 bool used = false;
486 HRESULT res = S_OK;
487 if (lib.Lib.Load(dllPath))
488 {
489 #ifdef NEW_FOLDER_INTERFACE
490 lib.LoadIcons();
491 #endif
492
493 #ifdef _7ZIP_LARGE_PAGES
494 if (g_LargePageSize != 0)
495 {
496 Func_SetLargePageMode setLargePageMode = (Func_SetLargePageMode)lib.Lib.GetProc("SetLargePageMode");
497 if (setLargePageMode)
498 setLargePageMode();
499 }
500 #endif
501
502 if (CaseSensitiveChange)
503 {
504 Func_SetCaseSensitive setCaseSensitive = (Func_SetCaseSensitive)lib.Lib.GetProc("SetCaseSensitive");
505 if (setCaseSensitive)
506 setCaseSensitive(CaseSensitive ? 1 : 0);
507 }
508
509 lib.CreateObject = (Func_CreateObject)lib.Lib.GetProc("CreateObject");
510 if (lib.CreateObject)
511 {
512 unsigned startSize = Codecs.Size() + Hashers.Size();
513 res = LoadCodecs();
514 used = (startSize != Codecs.Size() + Hashers.Size());
515 if (res == S_OK)
516 {
517 startSize = Formats.Size();
518 res = LoadFormats();
519 if (startSize != Formats.Size())
520 used = true;
521 }
522 }
523 }
524 if (!used)
525 Libs.DeleteBack();
526 return res;
527 }
528
LoadDllsFromFolder(const FString & folderPrefix)529 HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPrefix)
530 {
531 NFile::NFind::CEnumerator enumerator(folderPrefix + FCHAR_ANY_MASK);
532 NFile::NFind::CFileInfo fi;
533 while (enumerator.Next(fi))
534 {
535 if (fi.IsDir())
536 continue;
537 RINOK(LoadDll(folderPrefix + fi.Name, true));
538 }
539 return S_OK;
540 }
541
542 #endif
543
Load()544 HRESULT CCodecs::Load()
545 {
546 #ifdef NEW_FOLDER_INTERFACE
547 InternalIcons.LoadIcons(g_hInstance);
548 #endif
549
550 Formats.Clear();
551
552 #ifdef EXTERNAL_CODECS
553 Codecs.Clear();
554 Hashers.Clear();
555 #endif
556
557 for (UInt32 i = 0; i < g_NumArcs; i++)
558 {
559 const CArcInfo &arc = *g_Arcs[i];
560 CArcInfoEx item;
561
562 item.Name.SetFromAscii(arc.Name);
563 item.CreateInArchive = arc.CreateInArchive;
564 item.IsArcFunc = arc.IsArc;
565 item.Flags = arc.Flags;
566
567 {
568 UString e, ae;
569 if (arc.Ext)
570 e.SetFromAscii(arc.Ext);
571 if (arc.AddExt)
572 ae.SetFromAscii(arc.AddExt);
573 item.AddExts(e, ae);
574 }
575
576 #ifndef _SFX
577
578 item.CreateOutArchive = arc.CreateOutArchive;
579 item.UpdateEnabled = (arc.CreateOutArchive != NULL);
580 item.SignatureOffset = arc.SignatureOffset;
581 // item.Version = MY_VER_MIX;
582 item.NewInterface = true;
583
584 if (arc.IsMultiSignature())
585 ParseSignatures(arc.Signature, arc.SignatureSize, item.Signatures);
586 else
587 item.Signatures.AddNew().CopyFrom(arc.Signature, arc.SignatureSize);
588
589 #endif
590
591 Formats.Add(item);
592 }
593
594 #ifdef EXTERNAL_CODECS
595 const FString baseFolder = GetBaseFolderPrefixFromRegistry();
596 RINOK(LoadDll(baseFolder + kMainDll, false));
597 RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName FSTRING_PATH_SEPARATOR));
598 RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName FSTRING_PATH_SEPARATOR));
599 #endif
600
601 return S_OK;
602 }
603
604 #ifndef _SFX
605
FindFormatForArchiveName(const UString & arcPath) const606 int CCodecs::FindFormatForArchiveName(const UString &arcPath) const
607 {
608 int slashPos = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR);
609 int dotPos = arcPath.ReverseFind(L'.');
610 if (dotPos < 0 || dotPos < slashPos)
611 return -1;
612 const UString ext = arcPath.Ptr(dotPos + 1);
613 if (ext.IsEmpty())
614 return -1;
615 if (ext.IsEqualToNoCase(L"exe"))
616 return -1;
617 FOR_VECTOR (i, Formats)
618 {
619 const CArcInfoEx &arc = Formats[i];
620 /*
621 if (!arc.UpdateEnabled)
622 continue;
623 */
624 if (arc.FindExtension(ext) >= 0)
625 return i;
626 }
627 return -1;
628 }
629
FindFormatForExtension(const UString & ext) const630 int CCodecs::FindFormatForExtension(const UString &ext) const
631 {
632 if (ext.IsEmpty())
633 return -1;
634 FOR_VECTOR (i, Formats)
635 if (Formats[i].FindExtension(ext) >= 0)
636 return i;
637 return -1;
638 }
639
FindFormatForArchiveType(const UString & arcType) const640 int CCodecs::FindFormatForArchiveType(const UString &arcType) const
641 {
642 FOR_VECTOR (i, Formats)
643 if (Formats[i].Name.IsEqualToNoCase(arcType))
644 return i;
645 return -1;
646 }
647
FindFormatForArchiveType(const UString & arcType,CIntVector & formatIndices) const648 bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const
649 {
650 formatIndices.Clear();
651 for (unsigned pos = 0; pos < arcType.Len();)
652 {
653 int pos2 = arcType.Find('.', pos);
654 if (pos2 < 0)
655 pos2 = arcType.Len();
656 const UString name = arcType.Mid(pos, pos2 - pos);
657 if (name.IsEmpty())
658 return false;
659 int index = FindFormatForArchiveType(name);
660 if (index < 0 && name != L"*")
661 {
662 formatIndices.Clear();
663 return false;
664 }
665 formatIndices.Add(index);
666 pos = pos2 + 1;
667 }
668 return true;
669 }
670
671 #endif // _SFX
672
673
674 #ifdef EXTERNAL_CODECS
675
676 // #define EXPORT_CODECS
677
678 #ifdef EXPORT_CODECS
679
680 extern unsigned g_NumCodecs;
681 STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject);
682 STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);
683 #define NUM_EXPORT_CODECS g_NumCodecs
684
685 extern unsigned g_NumHashers;
686 STDAPI CreateHasher(UInt32 index, IHasher **hasher);
687 STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);
688 #define NUM_EXPORT_HASHERS g_NumHashers
689
690 #else // EXPORT_CODECS
691
692 #define NUM_EXPORT_CODECS 0
693 #define NUM_EXPORT_HASHERS 0
694
695 #endif // EXPORT_CODECS
696
GetNumberOfMethods(UInt32 * numMethods)697 STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods)
698 {
699 *numMethods = NUM_EXPORT_CODECS
700 #ifdef EXTERNAL_CODECS
701 + Codecs.Size()
702 #endif
703 ;
704 return S_OK;
705 }
706
GetProperty(UInt32 index,PROPID propID,PROPVARIANT * value)707 STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
708 {
709 #ifdef EXPORT_CODECS
710 if (index < g_NumCodecs)
711 return GetMethodProperty(index, propID, value);
712 #endif
713
714 #ifdef EXTERNAL_CODECS
715 const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
716
717 if (propID == NMethodPropID::kDecoderIsAssigned ||
718 propID == NMethodPropID::kEncoderIsAssigned)
719 {
720 NCOM::CPropVariant prop;
721 prop = (propID == NMethodPropID::kDecoderIsAssigned) ?
722 ci.DecoderIsAssigned :
723 ci.EncoderIsAssigned;
724 prop.Detach(value);
725 return S_OK;
726 }
727 return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value);
728 #else
729 return E_FAIL;
730 #endif
731 }
732
CreateDecoder(UInt32 index,const GUID * iid,void ** coder)733 STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder)
734 {
735 #ifdef EXPORT_CODECS
736 if (index < g_NumCodecs)
737 return CreateCoder2(false, index, iid, coder);
738 #endif
739 #ifdef EXTERNAL_CODECS
740 const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
741 if (ci.DecoderIsAssigned)
742 return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder);
743 return S_OK;
744 #else
745 return E_FAIL;
746 #endif
747 }
748
CreateEncoder(UInt32 index,const GUID * iid,void ** coder)749 STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder)
750 {
751 #ifdef EXPORT_CODECS
752 if (index < g_NumCodecs)
753 return CreateCoder2(true, index, iid, coder);
754 #endif
755 #ifdef EXTERNAL_CODECS
756 const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
757 if (ci.EncoderIsAssigned)
758 return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder);
759 return S_OK;
760 #else
761 return E_FAIL;
762 #endif
763 }
764
765
STDMETHODIMP_(UInt32)766 STDMETHODIMP_(UInt32) CCodecs::GetNumHashers()
767 {
768 return NUM_EXPORT_HASHERS
769 #ifdef EXTERNAL_CODECS
770 + Hashers.Size()
771 #endif
772 ;
773 }
774
GetHasherProp(UInt32 index,PROPID propID,PROPVARIANT * value)775 STDMETHODIMP CCodecs::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value)
776 {
777 #ifdef EXPORT_CODECS
778 if (index < g_NumHashers)
779 return ::GetHasherProp(index, propID, value);
780 #endif
781
782 #ifdef EXTERNAL_CODECS
783 const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
784 return Libs[ci.LibIndex].Hashers->GetHasherProp(ci.HasherIndex, propID, value);
785 #else
786 return E_FAIL;
787 #endif
788 }
789
CreateHasher(UInt32 index,IHasher ** hasher)790 STDMETHODIMP CCodecs::CreateHasher(UInt32 index, IHasher **hasher)
791 {
792 #ifdef EXPORT_CODECS
793 if (index < g_NumHashers)
794 return CreateHasher(index, hasher);
795 #endif
796 #ifdef EXTERNAL_CODECS
797 const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
798 return Libs[ci.LibIndex].Hashers->CreateHasher(ci.HasherIndex, hasher);
799 #else
800 return E_FAIL;
801 #endif
802 }
803
GetCodecLibIndex(UInt32 index)804 int CCodecs::GetCodecLibIndex(UInt32 index)
805 {
806 #ifdef EXPORT_CODECS
807 if (index < g_NumCodecs)
808 return -1;
809 #endif
810 #ifdef EXTERNAL_CODECS
811 const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
812 return ci.LibIndex;
813 #else
814 return -1;
815 #endif
816 }
817
GetHasherLibIndex(UInt32 index)818 int CCodecs::GetHasherLibIndex(UInt32 index)
819 {
820 #ifdef EXPORT_CODECS
821 if (index < g_NumHashers)
822 return -1;
823 #endif
824 #ifdef EXTERNAL_CODECS
825 const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
826 return ci.LibIndex;
827 #else
828 return -1;
829 #endif
830 }
831
GetCodecEncoderIsAssigned(UInt32 index)832 bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index)
833 {
834 #ifdef EXPORT_CODECS
835 if (index < g_NumCodecs)
836 {
837 NCOM::CPropVariant prop;
838 if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK)
839 if (prop.vt != VT_EMPTY)
840 return true;
841 return false;
842 }
843 #endif
844 #ifdef EXTERNAL_CODECS
845 const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
846 return ci.EncoderIsAssigned;
847 #else
848 return false;
849 #endif
850 }
851
GetCodecId(UInt32 index,UInt64 & id)852 HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id)
853 {
854 NCOM::CPropVariant prop;
855 RINOK(GetProperty(index, NMethodPropID::kID, &prop));
856 if (prop.vt != VT_UI8)
857 return E_INVALIDARG;
858 id = prop.uhVal.QuadPart;
859 return S_OK;
860 }
861
GetCodecName(UInt32 index)862 UString CCodecs::GetCodecName(UInt32 index)
863 {
864 UString s;
865 NCOM::CPropVariant prop;
866 if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK)
867 if (prop.vt == VT_BSTR)
868 s = prop.bstrVal;
869 return s;
870 }
871
GetHasherId(UInt32 index)872 UInt64 CCodecs::GetHasherId(UInt32 index)
873 {
874 NCOM::CPropVariant prop;
875 RINOK(GetHasherProp(index, NMethodPropID::kID, &prop));
876 if (prop.vt != VT_UI8)
877 return 0;
878 return prop.uhVal.QuadPart;
879 }
880
GetHasherName(UInt32 index)881 UString CCodecs::GetHasherName(UInt32 index)
882 {
883 UString s;
884 NCOM::CPropVariant prop;
885 if (GetHasherProp(index, NMethodPropID::kName, &prop) == S_OK)
886 if (prop.vt == VT_BSTR)
887 s = prop.bstrVal;
888 return s;
889 }
890
GetHasherDigestSize(UInt32 index)891 UInt32 CCodecs::GetHasherDigestSize(UInt32 index)
892 {
893 NCOM::CPropVariant prop;
894 RINOK(GetHasherProp(index, NMethodPropID::kDigestSize, &prop));
895 if (prop.vt != VT_UI4)
896 return 0;
897 return prop.ulVal;
898 }
899
900 #endif // EXTERNAL_CODECS
901