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