Skip to content

Commit

Permalink
OrcLib: Enable multi-files extension dlls
Browse files Browse the repository at this point in the history
  • Loading branch information
jgautier-anssi authored and fabienfl-orc committed Nov 9, 2020
1 parent 3993a13 commit e94897e
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 100 deletions.
15 changes: 15 additions & 0 deletions src/OrcLib/EmbeddedResource.h
Expand Up @@ -364,6 +364,21 @@ class ORCLIB_API EmbeddedResource
const std::wstring& strTempDir,
std::wstring& outputFile);

static HRESULT ExtractToDirectory(
const std::wstring& szImageFileRessourceID,
const std::wstring& Keyword,
LPCWSTR szSDDL,
const std::wstring& strTempDir,
std::vector<std::pair<std::wstring, std::wstring>>& outputFiles);

static HRESULT ExtractToDirectory(
const std::wstring& szImageFileRessourceID,
const std::wstring& Keyword,
LPCWSTR szSDDLFormat,
LPCWSTR szSID,
const std::wstring& strTempDir,
std::vector<std::pair<std::wstring, std::wstring>>& outputFiles);

static HRESULT ExtractToBuffer(const std::wstring& szImageFileRessourceID, CBinaryBuffer& Buffer);

template <typename _T, size_t _DeclElts>
Expand Down
199 changes: 125 additions & 74 deletions src/OrcLib/EmbeddedResource_Extract.cpp
Expand Up @@ -59,7 +59,7 @@ EmbeddedResource::EmbeddedResource(void) {}
wregex& Orc::EmbeddedResource::ArchRessourceRegEx()
{
static wregex g_ArchRessourceRegEx(
L"((7z|zip):([a-zA-Z0-9_\\-\\.]*))#([a-zA-Z0-9_\\-\\.]+)\\|([a-zA-Z0-9\\-_\\.\\\\/]+)");
L"((7z|zip):([a-zA-Z0-9_\\-\\.]*))#([a-zA-Z0-9_\\-\\.]+)\\|([a-zA-Z0-9\\-_\\*\\.\\\\/]+)");
return g_ArchRessourceRegEx;
}

Expand Down Expand Up @@ -427,8 +427,47 @@ HRESULT EmbeddedResource::ExtractToFile(
const std::wstring& strOutputDir,
std::wstring& outputFile)
{
HRESULT hr = E_FAIL;
std::vector<std::pair<std::wstring, std::wstring>> outputFiles;
if (auto hr = ExtractToDirectory(szImageFileRessourceID, Keyword, szSDDL, strOutputDir, outputFiles); FAILED(hr))
return hr;
if (outputFiles.size() == 1)
{
std::swap(outputFile, outputFiles[0].second);
return S_OK;
}

if (outputFiles.size() > 1)
{
Log::Error(L"More than one file were extracted from {}", szImageFileRessourceID);
return E_INVALIDARG;
}

Log::Error(L"No file extracted from {}", szImageFileRessourceID);
return E_INVALIDARG;
}

HRESULT Orc::EmbeddedResource::ExtractToDirectory(
const std::wstring& szImageFileRessourceID,
const std::wstring& Keyword,
LPCWSTR szSDDLFormat,
LPCWSTR szSID,
const std::wstring& strTempDir,
std::vector<std::pair<std::wstring, std::wstring>>& outputFiles)
{
WCHAR szSDDL[MAX_PATH] = {0};

swprintf_s(szSDDL, MAX_PATH, szSDDLFormat, szSID);

return ExtractToDirectory(szImageFileRessourceID, Keyword, szSDDL, strTempDir, outputFiles);
}

HRESULT EmbeddedResource::ExtractToDirectory(
const std::wstring& szImageFileRessourceID,
const std::wstring& Keyword,
LPCWSTR szSDDL,
const std::wstring& strOutputDir,
std::vector<std::pair<std::wstring, std::wstring>>& outputFiles)
{
WCHAR szTempDir[MAX_PATH];

if (!strOutputDir.empty())
Expand All @@ -437,120 +476,132 @@ HRESULT EmbeddedResource::ExtractToFile(
}
else
{
if (FAILED(hr = UtilGetTempDirPath(szTempDir, MAX_PATH)))
if (auto hr = UtilGetTempDirPath(szTempDir, MAX_PATH); FAILED(hr))
return hr;
}

if (IsSelf(szImageFileRessourceID))
{
if (FAILED(GetSelf(outputFile)))
std::wstring myself;

if (auto hr = GetSelf(myself); FAILED(hr))
return hr;
outputFiles.emplace_back(std::make_pair(myself, myself));
return S_OK;
}

wstring MotherShip, ResName, NameInArchive, FormatName;

if (SUCCEEDED(hr = SplitResourceReference(szImageFileRessourceID, MotherShip, ResName, NameInArchive, FormatName)))
if (auto hr = SplitResourceReference(szImageFileRessourceID, MotherShip, ResName, NameInArchive, FormatName);
FAILED(hr))
{
if (NameInArchive.empty())
if (hr == HRESULT_FROM_WIN32(ERROR_NO_MATCH))
{
// Resource is directly embedded in resource
Log::Error(
L"'{}' does not match a typical embedded ressource pattern (code: {:#x})", szImageFileRessourceID, hr);
return E_INVALIDARG;
}
else
{
Log::Error(L"'{}' failed to match a supported ressource pattern (code: {:#x})", szImageFileRessourceID, hr);
return E_INVALIDARG;
}
}

shared_ptr<ResourceStream> res = make_shared<ResourceStream>();
if (NameInArchive.empty())
{
// Resource is directly embedded in resource

HRSRC hRes = NULL;
HMODULE hModule = NULL;
std::wstring strBinaryPath;
if (FAILED(hr = LocateResource(MotherShip, ResName, BINARY(), hModule, hRes, strBinaryPath)))
{
Log::Warn(L"Could not locate resource '{}' (code: {:#x})", szImageFileRessourceID, hr);
return hr;
}
shared_ptr<ResourceStream> res = make_shared<ResourceStream>();

if (FAILED(res->OpenForReadOnly(hModule, hRes)))
return hr;
HRSRC hRes = NULL;
HMODULE hModule = NULL;
std::wstring strBinaryPath;
if (auto hr = LocateResource(MotherShip, ResName, BINARY(), hModule, hRes, strBinaryPath); FAILED(hr))
{
Log::Warn(L"Could not locate resource '{}' (code: {:#x})", szImageFileRessourceID, hr);
return hr;
}

wstring fileName;
HANDLE hFile = INVALID_HANDLE_VALUE;
if (auto hr = res->OpenForReadOnly(hModule, hRes); FAILED(hr))
return hr;

if (FAILED(
hr = UtilGetUniquePath(
wstring fileName;
HANDLE hFile = INVALID_HANDLE_VALUE;

if (auto hr = UtilGetUniquePath(
szTempDir,
Keyword.c_str(),
fileName,
hFile,
FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
szSDDL);
FAILED(hr))
{
if (hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS))
{
if (auto hr = UtilGetUniquePath(
szTempDir,
Keyword.c_str(),
fileName,
hFile,
FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
szSDDL)))
{
if (hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS))
{
if (FAILED(
hr = UtilGetUniquePath(
szTempDir,
Keyword.c_str(),
fileName,
hFile,
FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
szSDDL)))
{
Log::Error(L"Failed to create extracted file '{}' (code: {:#x})", fileName, hr);
return hr;
}
}
else
szSDDL);
FAILED(hr))
{
Log::Error(L"Failed to create extracted file '{}' (code: {:#x})", fileName, hr);
return hr;
}
}

shared_ptr<FileStream> fs = make_shared<FileStream>();
if (FAILED(hr = fs->OpenHandle(hFile)))
{
Log::Error(L"Failed to create extracted '{}' (code: {:#x})", fileName, hr);
return hr;
}
ULONGLONG nbBytes = 0;
if (FAILED(hr = res->CopyTo(fs, &nbBytes)))
else
{
Log::Error(L"Failed to copy resource to '{} (code: {:#x})'", fileName, hr);
Log::Error(L"Failed to create extracted file '{}' (code: {:#x})", fileName, hr);
return hr;
}
fs->Close();
res->Close();
}

outputFile.swap(fileName);
shared_ptr<FileStream> fs = make_shared<FileStream>();
if (auto hr = fs->OpenHandle(hFile); FAILED(hr))
{
Log::Error(L"Failed to create extracted '{}' (code: {:#x})", fileName, hr);
return hr;
}
else
ULONGLONG nbBytes = 0;
if (auto hr = res->CopyTo(fs, &nbBytes); FAILED(hr))
{
// Resource is based in an archive... extracting file
auto fmt = ArchiveExtract::GetArchiveFormat(FormatName);
if (fmt == ArchiveFormat::Unknown)
fmt = ArchiveFormat::SevenZip;
Log::Error(L"Failed to copy resource to '{} (code: {:#x})'", fileName, hr);
return hr;
}
fs->Close();
res->Close();

auto extract = ArchiveExtract::MakeExtractor(fmt);
outputFiles.emplace_back(std::make_pair(fileName, fileName));
}
else
{
// Resource is based in an archive... extracting file
auto fmt = ArchiveExtract::GetArchiveFormat(FormatName);
if (fmt == ArchiveFormat::Unknown)
fmt = ArchiveFormat::SevenZip;

vector<wstring> ToExtract;
auto extract = ArchiveExtract::MakeExtractor(fmt);

ToExtract.push_back(NameInArchive);
if (FAILED(hr = extract->Extract(szImageFileRessourceID.c_str(), szTempDir, szSDDL, ToExtract)))
return hr;
vector<wstring> ToExtract;

if (!extract->Items().empty())
ToExtract.push_back(NameInArchive);
if (auto hr = extract->Extract(szImageFileRessourceID.c_str(), szTempDir, szSDDL, ToExtract); FAILED(hr))
return hr;

if (!extract->Items().empty())
{
for (auto&& item : extract->Items())
{
outputFile = begin(extract->Items())->Path;
outputFiles.emplace_back(std::make_pair(std::move(item.NameInArchive), std::move(item.Path)));
}
else
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
}
else
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
}
else if (hr == HRESULT_FROM_WIN32(ERROR_NO_MATCH))
{
Log::Error(
L"'{}' does not match a typical embedded ressource pattern (code: {:#x})", szImageFileRessourceID, hr);
return E_INVALIDARG;
}

return S_OK;
}

Expand Down

0 comments on commit e94897e

Please sign in to comment.