📄 loadcodecs.cpp
字号:
// LoadCodecs.cpp
#include "StdAfx.h"
#include "LoadCodecs.h"
#include "../../../Common/MyCom.h"
#ifdef NEW_FOLDER_INTERFACE
#include "../../../Common/StringToInt.h"
#endif
#include "../../../Windows/PropVariant.h"
#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/Registry.h"
#endif
using namespace NWindows;
using namespace NFile;
#ifdef _WIN32
extern HINSTANCE g_hInstance;
#endif
static CSysString GetLibraryFolderPrefix()
{
#ifdef _WIN32
TCHAR fullPath[MAX_PATH + 1];
::GetModuleFileName(g_hInstance, fullPath, MAX_PATH);
CSysString path = fullPath;
int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
return path.Left(pos + 1);
#else
return CSysString(); // FIX IT
#endif
}
#define kCodecsFolderName TEXT("Codecs")
#define kFormatsFolderName TEXT("Formats")
static TCHAR *kMainDll = TEXT("7z.dll");
#ifdef _WIN32
static LPCTSTR kRegistryPath = TEXT("Software\\7-zip");
static LPCTSTR kProgramPathValue = TEXT("Path");
static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path)
{
NRegistry::CKey key;
if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS)
if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS)
{
NName::NormalizeDirPathPrefix(path);
return true;
}
return false;
}
#endif
CSysString GetBaseFolderPrefixFromRegistry()
{
CSysString moduleFolderPrefix = GetLibraryFolderPrefix();
NFind::CFileInfo fileInfo;
if (NFind::FindFile(moduleFolderPrefix + kMainDll, fileInfo))
if (!fileInfo.IsDirectory())
return moduleFolderPrefix;
if (NFind::FindFile(moduleFolderPrefix + kCodecsFolderName, fileInfo))
if (fileInfo.IsDirectory())
return moduleFolderPrefix;
if (NFind::FindFile(moduleFolderPrefix + kFormatsFolderName, fileInfo))
if (fileInfo.IsDirectory())
return moduleFolderPrefix;
#ifdef _WIN32
CSysString path;
if (ReadPathFromRegistry(HKEY_CURRENT_USER, path))
return path;
if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path))
return path;
#endif
return moduleFolderPrefix;
}
typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods);
typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats);
typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value);
typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value);
typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *iid, void **outObject);
typedef UInt32 (WINAPI *SetLargePageModeFunc)();
static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index,
PROPID propId, CLSID &clsId, bool &isAssigned)
{
NWindows::NCOM::CPropVariant prop;
isAssigned = false;
RINOK(getMethodProperty(index, propId, &prop));
if (prop.vt == VT_BSTR)
{
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 = (GetMethodPropertyFunc)lib.Lib.GetProcAddress("GetMethodProperty");
if (lib.GetMethodProperty == NULL)
return S_OK;
UInt32 numMethods = 1;
GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)lib.Lib.GetProcAddress("GetNumberOfMethods");
if (getNumberOfMethodsFunc != NULL)
{
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);
}
return S_OK;
}
static HRESULT ReadProp(
GetHandlerPropertyFunc getProp,
GetHandlerPropertyFunc2 getProp2,
UInt32 index, PROPID propID, NCOM::CPropVariant &prop)
{
if (getProp2)
return getProp2(index, propID, &prop);;
return getProp(propID, &prop);
}
static HRESULT ReadBoolProp(
GetHandlerPropertyFunc getProp,
GetHandlerPropertyFunc2 getProp2,
UInt32 index, PROPID propID, bool &res)
{
NCOM::CPropVariant prop;
RINOK(ReadProp(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 ReadStringProp(
GetHandlerPropertyFunc getProp,
GetHandlerPropertyFunc2 getProp2,
UInt32 index, PROPID propID, UString &res)
{
NCOM::CPropVariant prop;
RINOK(ReadProp(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;
}
#endif
static const unsigned int kNumArcsMax = 32;
static unsigned int g_NumArcs = 0;
static const CArcInfo *g_Arcs[kNumArcsMax];
void RegisterArc(const CArcInfo *arcInfo)
{
if (g_NumArcs < kNumArcsMax)
g_Arcs[g_NumArcs++] = arcInfo;
}
static void SplitString(const UString &srcString, UStringVector &destStrings)
{
destStrings.Clear();
UString s;
int len = srcString.Length();
if (len == 0)
return;
for (int 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);
}
void CArcInfoEx::AddExts(const wchar_t* ext, const wchar_t* addExt)
{
UStringVector exts, addExts;
SplitString(ext, exts);
if (addExt != 0)
SplitString(addExt, addExts);
for (int i = 0; i < exts.Size(); i++)
{
CArcExtInfo extInfo;
extInfo.Ext = exts[i];
if (i < addExts.Size())
{
extInfo.AddExt = addExts[i];
if (extInfo.AddExt == L"*")
extInfo.AddExt.Empty();
}
Exts.Add(extInfo);
}
}
#ifdef EXTERNAL_CODECS
HRESULT CCodecs::LoadFormats()
{
const NDLL::CLibrary &lib = Libs.Back().Lib;
GetHandlerPropertyFunc getProp = 0;
GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2)
lib.GetProcAddress("GetHandlerProperty2");
if (getProp2 == NULL)
{
getProp = (GetHandlerPropertyFunc)
lib.GetProcAddress("GetHandlerProperty");
if (getProp == NULL)
return S_OK;
}
UInt32 numFormats = 1;
GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc)
lib.GetProcAddress("GetNumberOfFormats");
if (getNumberOfFormats != NULL)
{
RINOK(getNumberOfFormats(&numFormats));
}
if (getProp2 == NULL)
numFormats = 1;
for(UInt32 i = 0; i < numFormats; i++)
{
CArcInfoEx item;
item.LibIndex = Libs.Size() - 1;
item.FormatIndex = i;
RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kName, item.Name));
NCOM::CPropVariant prop;
if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK)
continue;
if (prop.vt != VT_BSTR)
continue;
item.ClassID = *(const GUID *)prop.bstrVal;
prop.Clear();
UString ext, addExt;
RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext));
RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt));
item.AddExts(ext, addExt);
ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, item.UpdateEnabled);
if (item.UpdateEnabled)
ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, item.KeepName);
if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK)
if (prop.vt == VT_BSTR)
{
UINT len = ::SysStringByteLen(prop.bstrVal);
item.StartSignature.SetCapacity(len);
memmove(item.StartSignature, prop.bstrVal, len);
}
Formats.Add(item);
}
return S_OK;
}
#ifdef NEW_FOLDER_INTERFACE
void CCodecLib::LoadIcons()
{
UString iconTypes = MyLoadStringW((HMODULE)Lib, kIconTypesResId);
UStringVector pairs;
SplitString(iconTypes, pairs);
for (int i = 0; i < pairs.Size(); i++)
{
const UString &s = pairs[i];
int pos = s.Find(L':');
if (pos < 0)
continue;
CIconPair iconPair;
const wchar_t *end;
UString num = s.Mid(pos + 1);
iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end);
if (*end != L'\0')
continue;
iconPair.Ext = s.Left(pos);
IconPairs.Add(iconPair);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -