// LoadCodecs.cpp | |
#include "StdAfx.h" | |
#include "../../../../C/7zVersion.h" | |
#include "../../../Common/MyCom.h" | |
#include "../../../Common/StringToInt.h" | |
#include "../../../Common/StringConvert.h" | |
#include "../../../Windows/PropVariant.h" | |
#include "LoadCodecs.h" | |
using namespace NWindows; | |
#ifdef NEW_FOLDER_INTERFACE | |
#include "../../../Common/StringToInt.h" | |
#endif | |
#include "../../ICoder.h" | |
#include "../../Common/RegisterArc.h" | |
#ifdef EXTERNAL_CODECS | |
#include "../../../Windows/FileFind.h" | |
#include "../../../Windows/DLL.h" | |
#ifdef NEW_FOLDER_INTERFACE | |
#include "../../../Windows/ResourceString.h" | |
static const UINT kIconTypesResId = 100; | |
#endif | |
#ifdef _WIN32 | |
#include "../../../Windows/FileName.h" | |
#include "../../../Windows/Registry.h" | |
#endif | |
using namespace NFile; | |
#ifdef _WIN32 | |
extern HINSTANCE g_hInstance; | |
#endif | |
#define kCodecsFolderName FTEXT("Codecs") | |
#define kFormatsFolderName FTEXT("Formats") | |
static CFSTR kMainDll = FTEXT("7z.dll"); | |
#ifdef _WIN32 | |
static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip"); | |
static LPCWSTR kProgramPathValue = L"Path"; | |
static LPCWSTR kProgramPath2Value = L"Path" | |
#ifdef _WIN64 | |
L"64"; | |
#else | |
L"32"; | |
#endif | |
static bool ReadPathFromRegistry(HKEY baseKey, LPCWSTR value, FString &path) | |
{ | |
NRegistry::CKey key; | |
if (key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS) | |
{ | |
UString pathU; | |
if (key.QueryValue(value, pathU) == ERROR_SUCCESS) | |
{ | |
path = us2fs(pathU); | |
NName::NormalizeDirPathPrefix(path); | |
return NFind::DoesFileExist(path + kMainDll); | |
} | |
} | |
return false; | |
} | |
#endif // _WIN32 | |
#endif // EXTERNAL_CODECS | |
static const unsigned kNumArcsMax = 48; | |
static unsigned g_NumArcs = 0; | |
static const CArcInfo *g_Arcs[kNumArcsMax]; | |
void RegisterArc(const CArcInfo *arcInfo) throw() | |
{ | |
if (g_NumArcs < kNumArcsMax) | |
{ | |
g_Arcs[g_NumArcs] = arcInfo; | |
g_NumArcs++; | |
} | |
} | |
static void SplitString(const UString &srcString, UStringVector &destStrings) | |
{ | |
destStrings.Clear(); | |
UString s; | |
unsigned len = srcString.Len(); | |
if (len == 0) | |
return; | |
for (unsigned i = 0; i < len; i++) | |
{ | |
wchar_t c = srcString[i]; | |
if (c == L' ') | |
{ | |
if (!s.IsEmpty()) | |
{ | |
destStrings.Add(s); | |
s.Empty(); | |
} | |
} | |
else | |
s += c; | |
} | |
if (!s.IsEmpty()) | |
destStrings.Add(s); | |
} | |
int CArcInfoEx::FindExtension(const UString &ext) const | |
{ | |
FOR_VECTOR (i, Exts) | |
if (ext.IsEqualToNoCase(Exts[i].Ext)) | |
return i; | |
return -1; | |
} | |
void CArcInfoEx::AddExts(const UString &ext, const UString &addExt) | |
{ | |
UStringVector exts, addExts; | |
SplitString(ext, exts); | |
SplitString(addExt, addExts); | |
FOR_VECTOR (i, exts) | |
{ | |
CArcExtInfo extInfo; | |
extInfo.Ext = exts[i]; | |
if (i < addExts.Size()) | |
{ | |
extInfo.AddExt = addExts[i]; | |
if (extInfo.AddExt == L"*") | |
extInfo.AddExt.Empty(); | |
} | |
Exts.Add(extInfo); | |
} | |
} | |
#ifndef _SFX | |
static bool ParseSignatures(const Byte *data, unsigned size, CObjectVector<CByteBuffer> &signatures) | |
{ | |
signatures.Clear(); | |
while (size > 0) | |
{ | |
unsigned len = *data++; | |
size--; | |
if (len > size) | |
return false; | |
signatures.AddNew().CopyFrom(data, len); | |
data += len; | |
size -= len; | |
} | |
return true; | |
} | |
#endif // _SFX | |
#ifdef EXTERNAL_CODECS | |
static FString GetBaseFolderPrefixFromRegistry() | |
{ | |
FString moduleFolderPrefix = NDLL::GetModuleDirPrefix(); | |
#ifdef _WIN32 | |
if (!NFind::DoesFileExist(moduleFolderPrefix + kMainDll) && | |
!NFind::DoesDirExist(moduleFolderPrefix + kCodecsFolderName) && | |
!NFind::DoesDirExist(moduleFolderPrefix + kFormatsFolderName)) | |
{ | |
FString path; | |
if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPath2Value, path)) return path; | |
if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPath2Value, path)) return path; | |
if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPathValue, path)) return path; | |
if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPathValue, path)) return path; | |
} | |
#endif | |
return moduleFolderPrefix; | |
} | |
static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 index, | |
PROPID propId, CLSID &clsId, bool &isAssigned) | |
{ | |
NCOM::CPropVariant prop; | |
isAssigned = false; | |
RINOK(getMethodProperty(index, propId, &prop)); | |
if (prop.vt == VT_BSTR) | |
{ | |
if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID)) | |
return E_FAIL; | |
isAssigned = true; | |
clsId = *(const GUID *)prop.bstrVal; | |
} | |
else if (prop.vt != VT_EMPTY) | |
return E_FAIL; | |
return S_OK; | |
} | |
HRESULT CCodecs::LoadCodecs() | |
{ | |
CCodecLib &lib = Libs.Back(); | |
lib.GetMethodProperty = (Func_GetMethodProperty)lib.Lib.GetProc("GetMethodProperty"); | |
if (lib.GetMethodProperty) | |
{ | |
UInt32 numMethods = 1; | |
Func_GetNumberOfMethods getNumberOfMethodsFunc = (Func_GetNumberOfMethods)lib.Lib.GetProc("GetNumberOfMethods"); | |
if (getNumberOfMethodsFunc) | |
{ | |
RINOK(getNumberOfMethodsFunc(&numMethods)); | |
} | |
for (UInt32 i = 0; i < numMethods; i++) | |
{ | |
CDllCodecInfo info; | |
info.LibIndex = Libs.Size() - 1; | |
info.CodecIndex = i; | |
RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned)); | |
RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned)); | |
Codecs.Add(info); | |
} | |
} | |
Func_GetHashers getHashers = (Func_GetHashers)lib.Lib.GetProc("GetHashers"); | |
if (getHashers) | |
{ | |
RINOK(getHashers(&lib.Hashers)); | |
if (lib.Hashers) | |
{ | |
UInt32 numMethods = lib.Hashers->GetNumHashers(); | |
for (UInt32 i = 0; i < numMethods; i++) | |
{ | |
CDllHasherInfo info; | |
info.LibIndex = Libs.Size() - 1; | |
info.HasherIndex = i; | |
Hashers.Add(info); | |
} | |
} | |
} | |
return S_OK; | |
} | |
static HRESULT GetProp( | |
Func_GetHandlerProperty getProp, | |
Func_GetHandlerProperty2 getProp2, | |
UInt32 index, PROPID propID, NCOM::CPropVariant &prop) | |
{ | |
if (getProp2) | |
return getProp2(index, propID, &prop);; | |
return getProp(propID, &prop); | |
} | |
static HRESULT GetProp_Bool( | |
Func_GetHandlerProperty getProp, | |
Func_GetHandlerProperty2 getProp2, | |
UInt32 index, PROPID propID, bool &res) | |
{ | |
res = false; | |
NCOM::CPropVariant prop; | |
RINOK(GetProp(getProp, getProp2, index, propID, prop)); | |
if (prop.vt == VT_BOOL) | |
res = VARIANT_BOOLToBool(prop.boolVal); | |
else if (prop.vt != VT_EMPTY) | |
return E_FAIL; | |
return S_OK; | |
} | |
static HRESULT GetProp_UInt32( | |
Func_GetHandlerProperty getProp, | |
Func_GetHandlerProperty2 getProp2, | |
UInt32 index, PROPID propID, UInt32 &res, bool &defined) | |
{ | |
res = 0; | |
defined = false; | |
NCOM::CPropVariant prop; | |
RINOK(GetProp(getProp, getProp2, index, propID, prop)); | |
if (prop.vt == VT_UI4) | |
{ | |
res = prop.ulVal; | |
defined = true; | |
} | |
else if (prop.vt != VT_EMPTY) | |
return E_FAIL; | |
return S_OK; | |
} | |
static HRESULT GetProp_String( | |
Func_GetHandlerProperty getProp, | |
Func_GetHandlerProperty2 getProp2, | |
UInt32 index, PROPID propID, UString &res) | |
{ | |
res.Empty(); | |
NCOM::CPropVariant prop; | |
RINOK(GetProp(getProp, getProp2, index, propID, prop)); | |
if (prop.vt == VT_BSTR) | |
res = prop.bstrVal; | |
else if (prop.vt != VT_EMPTY) | |
return E_FAIL; | |
return S_OK; | |
} | |
static HRESULT GetProp_RawData( | |
Func_GetHandlerProperty getProp, | |
Func_GetHandlerProperty2 getProp2, | |
UInt32 index, PROPID propID, CByteBuffer &bb) | |
{ | |
bb.Free(); | |
NCOM::CPropVariant prop; | |
RINOK(GetProp(getProp, getProp2, index, propID, prop)); | |
if (prop.vt == VT_BSTR) | |
{ | |
UINT len = ::SysStringByteLen(prop.bstrVal); | |
bb.CopyFrom((const Byte *)prop.bstrVal, len); | |
} | |
else if (prop.vt != VT_EMPTY) | |
return E_FAIL; | |
return S_OK; | |
} | |
static const UInt32 kArcFlagsPars[] = | |
{ | |
NArchive::NHandlerPropID::kKeepName, NArcInfoFlags::kKeepName, | |
NArchive::NHandlerPropID::kAltStreams, NArcInfoFlags::kAltStreams, | |
NArchive::NHandlerPropID::kNtSecure, NArcInfoFlags::kNtSecure | |
}; | |
HRESULT CCodecs::LoadFormats() | |
{ | |
const NDLL::CLibrary &lib = Libs.Back().Lib; | |
Func_GetHandlerProperty getProp = NULL; | |
Func_GetHandlerProperty2 getProp2 = (Func_GetHandlerProperty2)lib.GetProc("GetHandlerProperty2"); | |
Func_GetIsArc getIsArc = (Func_GetIsArc)lib.GetProc("GetIsArc"); | |
UInt32 numFormats = 1; | |
if (getProp2) | |
{ | |
Func_GetNumberOfFormats getNumberOfFormats = (Func_GetNumberOfFormats)lib.GetProc("GetNumberOfFormats"); | |
if (getNumberOfFormats) | |
{ | |
RINOK(getNumberOfFormats(&numFormats)); | |
} | |
} | |
else | |
{ | |
getProp = (Func_GetHandlerProperty)lib.GetProc("GetHandlerProperty"); | |
if (!getProp) | |
return S_OK; | |
} | |
for (UInt32 i = 0; i < numFormats; i++) | |
{ | |
CArcInfoEx item; | |
item.LibIndex = Libs.Size() - 1; | |
item.FormatIndex = i; | |
RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kName, item.Name)); | |
{ | |
NCOM::CPropVariant prop; | |
if (GetProp(getProp, getProp2, i, NArchive::NHandlerPropID::kClassID, prop) != S_OK) | |
continue; | |
if (prop.vt != VT_BSTR) | |
continue; | |
if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID)) | |
return E_FAIL; | |
item.ClassID = *(const GUID *)prop.bstrVal; | |
prop.Clear(); | |
} | |
UString ext, addExt; | |
RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kExtension, ext)); | |
RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kAddExtension, addExt)); | |
item.AddExts(ext, addExt); | |
GetProp_Bool(getProp, getProp2, i, NArchive::NHandlerPropID::kUpdate, item.UpdateEnabled); | |
bool flags_Defined = false; | |
RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kFlags, item.Flags, flags_Defined)); | |
item.NewInterface = flags_Defined; | |
if (!flags_Defined) // && item.UpdateEnabled | |
{ | |
// support for DLL version before 9.31: | |
for (unsigned j = 0; j < ARRAY_SIZE(kArcFlagsPars); j += 2) | |
{ | |
bool val = false; | |
GetProp_Bool(getProp, getProp2, i, kArcFlagsPars[j], val); | |
if (val) | |
item.Flags |= kArcFlagsPars[j + 1]; | |
} | |
} | |
CByteBuffer sig; | |
RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kSignature, sig)); | |
if (sig.Size() != 0) | |
item.Signatures.Add(sig); | |
else | |
{ | |
RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kMultiSignature, sig)); | |
ParseSignatures(sig, (unsigned)sig.Size(), item.Signatures); | |
} | |
bool signatureOffset_Defined; | |
RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kSignatureOffset, item.SignatureOffset, signatureOffset_Defined)); | |
// bool version_Defined; | |
// RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kVersion, item.Version, version_Defined)); | |
if (getIsArc) | |
getIsArc(i, &item.IsArcFunc); | |
Formats.Add(item); | |
} | |
return S_OK; | |
} | |
#ifdef NEW_FOLDER_INTERFACE | |
void CCodecIcons::LoadIcons(HMODULE m) | |
{ | |
UString iconTypes; | |
MyLoadString(m, kIconTypesResId, iconTypes); | |
UStringVector pairs; | |
SplitString(iconTypes, pairs); | |
FOR_VECTOR (i, pairs) | |
{ | |
const UString &s = pairs[i]; | |
int pos = s.Find(L':'); | |
CIconPair iconPair; | |
iconPair.IconIndex = -1; | |
if (pos < 0) | |
pos = s.Len(); | |
else | |
{ | |
UString num = s.Ptr(pos + 1); | |
if (!num.IsEmpty()) | |
{ | |
const wchar_t *end; | |
iconPair.IconIndex = ConvertStringToUInt32(num, &end); | |
if (*end != 0) | |
continue; | |
} | |
} | |
iconPair.Ext = s.Left(pos); | |
IconPairs.Add(iconPair); | |
} | |
} | |
bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const | |
{ | |
iconIndex = -1; | |
FOR_VECTOR (i, IconPairs) | |
{ | |
const CIconPair &pair = IconPairs[i]; | |
if (ext.IsEqualToNoCase(pair.Ext)) | |
{ | |
iconIndex = pair.IconIndex; | |
return true; | |
} | |
} | |
return false; | |
} | |
#endif // EXTERNAL_CODECS | |
#ifdef _7ZIP_LARGE_PAGES | |
extern "C" | |
{ | |
extern SIZE_T g_LargePageSize; | |
} | |
#endif | |
HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll) | |
{ | |
if (needCheckDll) | |
{ | |
NDLL::CLibrary library; | |
if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE)) | |
return S_OK; | |
} | |
Libs.Add(CCodecLib()); | |
CCodecLib &lib = Libs.Back(); | |
lib.Path = dllPath; | |
bool used = false; | |
HRESULT res = S_OK; | |
if (lib.Lib.Load(dllPath)) | |
{ | |
#ifdef NEW_FOLDER_INTERFACE | |
lib.LoadIcons(); | |
#endif | |
#ifdef _7ZIP_LARGE_PAGES | |
if (g_LargePageSize != 0) | |
{ | |
Func_SetLargePageMode setLargePageMode = (Func_SetLargePageMode)lib.Lib.GetProc("SetLargePageMode"); | |
if (setLargePageMode) | |
setLargePageMode(); | |
} | |
#endif | |
if (CaseSensitiveChange) | |
{ | |
Func_SetCaseSensitive setCaseSensitive = (Func_SetCaseSensitive)lib.Lib.GetProc("SetCaseSensitive"); | |
if (setCaseSensitive) | |
setCaseSensitive(CaseSensitive ? 1 : 0); | |
} | |
lib.CreateObject = (Func_CreateObject)lib.Lib.GetProc("CreateObject"); | |
if (lib.CreateObject) | |
{ | |
unsigned startSize = Codecs.Size() + Hashers.Size(); | |
res = LoadCodecs(); | |
used = (startSize != Codecs.Size() + Hashers.Size()); | |
if (res == S_OK) | |
{ | |
startSize = Formats.Size(); | |
res = LoadFormats(); | |
if (startSize != Formats.Size()) | |
used = true; | |
} | |
} | |
} | |
if (!used) | |
Libs.DeleteBack(); | |
return res; | |
} | |
HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPrefix) | |
{ | |
NFile::NFind::CEnumerator enumerator(folderPrefix + FCHAR_ANY_MASK); | |
NFile::NFind::CFileInfo fi; | |
while (enumerator.Next(fi)) | |
{ | |
if (fi.IsDir()) | |
continue; | |
RINOK(LoadDll(folderPrefix + fi.Name, true)); | |
} | |
return S_OK; | |
} | |
#endif | |
HRESULT CCodecs::Load() | |
{ | |
#ifdef NEW_FOLDER_INTERFACE | |
InternalIcons.LoadIcons(g_hInstance); | |
#endif | |
Formats.Clear(); | |
#ifdef EXTERNAL_CODECS | |
Codecs.Clear(); | |
Hashers.Clear(); | |
#endif | |
for (UInt32 i = 0; i < g_NumArcs; i++) | |
{ | |
const CArcInfo &arc = *g_Arcs[i]; | |
CArcInfoEx item; | |
item.Name.SetFromAscii(arc.Name); | |
item.CreateInArchive = arc.CreateInArchive; | |
item.IsArcFunc = arc.IsArc; | |
item.Flags = arc.Flags; | |
{ | |
UString e, ae; | |
if (arc.Ext) | |
e.SetFromAscii(arc.Ext); | |
if (arc.AddExt) | |
ae.SetFromAscii(arc.AddExt); | |
item.AddExts(e, ae); | |
} | |
#ifndef _SFX | |
item.CreateOutArchive = arc.CreateOutArchive; | |
item.UpdateEnabled = (arc.CreateOutArchive != NULL); | |
item.SignatureOffset = arc.SignatureOffset; | |
// item.Version = MY_VER_MIX; | |
item.NewInterface = true; | |
if (arc.IsMultiSignature()) | |
ParseSignatures(arc.Signature, arc.SignatureSize, item.Signatures); | |
else | |
item.Signatures.AddNew().CopyFrom(arc.Signature, arc.SignatureSize); | |
#endif | |
Formats.Add(item); | |
} | |
#ifdef EXTERNAL_CODECS | |
const FString baseFolder = GetBaseFolderPrefixFromRegistry(); | |
RINOK(LoadDll(baseFolder + kMainDll, false)); | |
RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName FSTRING_PATH_SEPARATOR)); | |
RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName FSTRING_PATH_SEPARATOR)); | |
#endif | |
return S_OK; | |
} | |
#ifndef _SFX | |
int CCodecs::FindFormatForArchiveName(const UString &arcPath) const | |
{ | |
int slashPos = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR); | |
int dotPos = arcPath.ReverseFind(L'.'); | |
if (dotPos < 0 || dotPos < slashPos) | |
return -1; | |
const UString ext = arcPath.Ptr(dotPos + 1); | |
if (ext.IsEmpty()) | |
return -1; | |
if (ext.IsEqualToNoCase(L"exe")) | |
return -1; | |
FOR_VECTOR (i, Formats) | |
{ | |
const CArcInfoEx &arc = Formats[i]; | |
/* | |
if (!arc.UpdateEnabled) | |
continue; | |
*/ | |
if (arc.FindExtension(ext) >= 0) | |
return i; | |
} | |
return -1; | |
} | |
int CCodecs::FindFormatForExtension(const UString &ext) const | |
{ | |
if (ext.IsEmpty()) | |
return -1; | |
FOR_VECTOR (i, Formats) | |
if (Formats[i].FindExtension(ext) >= 0) | |
return i; | |
return -1; | |
} | |
int CCodecs::FindFormatForArchiveType(const UString &arcType) const | |
{ | |
FOR_VECTOR (i, Formats) | |
if (Formats[i].Name.IsEqualToNoCase(arcType)) | |
return i; | |
return -1; | |
} | |
bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const | |
{ | |
formatIndices.Clear(); | |
for (unsigned pos = 0; pos < arcType.Len();) | |
{ | |
int pos2 = arcType.Find('.', pos); | |
if (pos2 < 0) | |
pos2 = arcType.Len(); | |
const UString name = arcType.Mid(pos, pos2 - pos); | |
if (name.IsEmpty()) | |
return false; | |
int index = FindFormatForArchiveType(name); | |
if (index < 0 && name != L"*") | |
{ | |
formatIndices.Clear(); | |
return false; | |
} | |
formatIndices.Add(index); | |
pos = pos2 + 1; | |
} | |
return true; | |
} | |
#endif // _SFX | |
#ifdef EXTERNAL_CODECS | |
// #define EXPORT_CODECS | |
#ifdef EXPORT_CODECS | |
extern unsigned g_NumCodecs; | |
STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject); | |
STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); | |
#define NUM_EXPORT_CODECS g_NumCodecs | |
extern unsigned g_NumHashers; | |
STDAPI CreateHasher(UInt32 index, IHasher **hasher); | |
STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); | |
#define NUM_EXPORT_HASHERS g_NumHashers | |
#else // EXPORT_CODECS | |
#define NUM_EXPORT_CODECS 0 | |
#define NUM_EXPORT_HASHERS 0 | |
#endif // EXPORT_CODECS | |
STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods) | |
{ | |
*numMethods = NUM_EXPORT_CODECS | |
#ifdef EXTERNAL_CODECS | |
+ Codecs.Size() | |
#endif | |
; | |
return S_OK; | |
} | |
STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) | |
{ | |
#ifdef EXPORT_CODECS | |
if (index < g_NumCodecs) | |
return GetMethodProperty(index, propID, value); | |
#endif | |
#ifdef EXTERNAL_CODECS | |
const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; | |
if (propID == NMethodPropID::kDecoderIsAssigned || | |
propID == NMethodPropID::kEncoderIsAssigned) | |
{ | |
NCOM::CPropVariant prop; | |
prop = (propID == NMethodPropID::kDecoderIsAssigned) ? | |
ci.DecoderIsAssigned : | |
ci.EncoderIsAssigned; | |
prop.Detach(value); | |
return S_OK; | |
} | |
return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value); | |
#else | |
return E_FAIL; | |
#endif | |
} | |
STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder) | |
{ | |
#ifdef EXPORT_CODECS | |
if (index < g_NumCodecs) | |
return CreateCoder2(false, index, iid, coder); | |
#endif | |
#ifdef EXTERNAL_CODECS | |
const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; | |
if (ci.DecoderIsAssigned) | |
return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder); | |
return S_OK; | |
#else | |
return E_FAIL; | |
#endif | |
} | |
STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder) | |
{ | |
#ifdef EXPORT_CODECS | |
if (index < g_NumCodecs) | |
return CreateCoder2(true, index, iid, coder); | |
#endif | |
#ifdef EXTERNAL_CODECS | |
const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; | |
if (ci.EncoderIsAssigned) | |
return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder); | |
return S_OK; | |
#else | |
return E_FAIL; | |
#endif | |
} | |
STDMETHODIMP_(UInt32) CCodecs::GetNumHashers() | |
{ | |
return NUM_EXPORT_HASHERS | |
#ifdef EXTERNAL_CODECS | |
+ Hashers.Size() | |
#endif | |
; | |
} | |
STDMETHODIMP CCodecs::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value) | |
{ | |
#ifdef EXPORT_CODECS | |
if (index < g_NumHashers) | |
return ::GetHasherProp(index, propID, value); | |
#endif | |
#ifdef EXTERNAL_CODECS | |
const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; | |
return Libs[ci.LibIndex].Hashers->GetHasherProp(ci.HasherIndex, propID, value); | |
#else | |
return E_FAIL; | |
#endif | |
} | |
STDMETHODIMP CCodecs::CreateHasher(UInt32 index, IHasher **hasher) | |
{ | |
#ifdef EXPORT_CODECS | |
if (index < g_NumHashers) | |
return CreateHasher(index, hasher); | |
#endif | |
#ifdef EXTERNAL_CODECS | |
const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; | |
return Libs[ci.LibIndex].Hashers->CreateHasher(ci.HasherIndex, hasher); | |
#else | |
return E_FAIL; | |
#endif | |
} | |
int CCodecs::GetCodecLibIndex(UInt32 index) | |
{ | |
#ifdef EXPORT_CODECS | |
if (index < g_NumCodecs) | |
return -1; | |
#endif | |
#ifdef EXTERNAL_CODECS | |
const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; | |
return ci.LibIndex; | |
#else | |
return -1; | |
#endif | |
} | |
int CCodecs::GetHasherLibIndex(UInt32 index) | |
{ | |
#ifdef EXPORT_CODECS | |
if (index < g_NumHashers) | |
return -1; | |
#endif | |
#ifdef EXTERNAL_CODECS | |
const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; | |
return ci.LibIndex; | |
#else | |
return -1; | |
#endif | |
} | |
bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index) | |
{ | |
#ifdef EXPORT_CODECS | |
if (index < g_NumCodecs) | |
{ | |
NCOM::CPropVariant prop; | |
if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK) | |
if (prop.vt != VT_EMPTY) | |
return true; | |
return false; | |
} | |
#endif | |
#ifdef EXTERNAL_CODECS | |
const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; | |
return ci.EncoderIsAssigned; | |
#else | |
return false; | |
#endif | |
} | |
HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id) | |
{ | |
NCOM::CPropVariant prop; | |
RINOK(GetProperty(index, NMethodPropID::kID, &prop)); | |
if (prop.vt != VT_UI8) | |
return E_INVALIDARG; | |
id = prop.uhVal.QuadPart; | |
return S_OK; | |
} | |
UString CCodecs::GetCodecName(UInt32 index) | |
{ | |
UString s; | |
NCOM::CPropVariant prop; | |
if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK) | |
if (prop.vt == VT_BSTR) | |
s = prop.bstrVal; | |
return s; | |
} | |
UInt64 CCodecs::GetHasherId(UInt32 index) | |
{ | |
NCOM::CPropVariant prop; | |
RINOK(GetHasherProp(index, NMethodPropID::kID, &prop)); | |
if (prop.vt != VT_UI8) | |
return 0; | |
return prop.uhVal.QuadPart; | |
} | |
UString CCodecs::GetHasherName(UInt32 index) | |
{ | |
UString s; | |
NCOM::CPropVariant prop; | |
if (GetHasherProp(index, NMethodPropID::kName, &prop) == S_OK) | |
if (prop.vt == VT_BSTR) | |
s = prop.bstrVal; | |
return s; | |
} | |
UInt32 CCodecs::GetHasherDigestSize(UInt32 index) | |
{ | |
NCOM::CPropVariant prop; | |
RINOK(GetHasherProp(index, NMethodPropID::kDigestSize, &prop)); | |
if (prop.vt != VT_UI4) | |
return 0; | |
return prop.ulVal; | |
} | |
#endif // EXTERNAL_CODECS |