Infrastructure
Here we will review initial infrastructure to create handlers for sz
and sze
sample archives. If you need additional info see 7z-assembly.h
1. Define archive handlers
C++
struct ArchiveHandler {
const wchar_t* name;
GUID guid;
const wchar_t* extension;
const wchar_t* add_extension;
UInt32 flags;
char signature[2];
bool enable_update;
void* (*in_factory)();
};
const ArchiveHandler handlers[] = {
{L"SZ",
SzHandlerGuid,
L"sz",
L"",
NArcInfoFlags::kByExtOnlyOpen,
{0x53, 0x5A},
false,
[]() -> void* {
return new archive::SzInArchive();
}},
{L"SZE",
SzeHandlerGuid,
L"sze",
L"",
NArcInfoFlags::kByExtOnlyOpen,
{0x53, 0x45},
true,
[]() -> void* {
return new archive::SzeInArchive();
}},
};
struct ArchiveHandler {
const wchar_t* name;
GUID guid;
const wchar_t* extension;
const wchar_t* add_extension;
UInt32 flags;
char signature[2];
bool enable_update;
void* (*in_factory)();
};
const ArchiveHandler handlers[] = {
{L"SZ",
SzHandlerGuid,
L"sz",
L"",
NArcInfoFlags::kByExtOnlyOpen,
{0x53, 0x5A},
false,
[]() -> void* {
return new archive::SzInArchive();
}},
{L"SZE",
SzeHandlerGuid,
L"sze",
L"",
NArcInfoFlags::kByExtOnlyOpen,
{0x53, 0x45},
true,
[]() -> void* {
return new archive::SzeInArchive();
}},
};
Later on we define SZ and SZE handlers with corresponding GUIDs, extensions, etc.
INFO
It worth to mention that NArcInfoFlags::kByExtOnlyOpen
to avoid cases when 7zip will recognize archive inside of the archive because of weak signatures.
2. Create Object
CreateObject method is used to create Archive Handlers:
C++
STDAPI_LIB CreateObject(const GUID* clsid, const GUID* iid, void** outObject) {
for (int i = 0; i < std::size(handlers) && *outObject == nullptr; i++) {
if (handlers[i].guid == *clsid && *iid == IID_IInArchive) {
*outObject = handlers[i].in_factory();
}
}
static_cast<IUnknown*>(*outObject)->AddRef();
return S_OK;
}
STDAPI_LIB CreateObject(const GUID* clsid, const GUID* iid, void** outObject) {
for (int i = 0; i < std::size(handlers) && *outObject == nullptr; i++) {
if (handlers[i].guid == *clsid && *iid == IID_IInArchive) {
*outObject = handlers[i].in_factory();
}
}
static_cast<IUnknown*>(*outObject)->AddRef();
return S_OK;
}
3. GetHandlerProperty2
Simply query for the properties. All of the handlers are defined in handlers
array.
C++
STDAPI_LIB GetHandlerProperty2(UInt32 formatIndex, PROPID propID,
PROPVARIANT* value) {
switch (propID) {
case NArchive::NHandlerPropID::kName:
return utils::SetVariant(handlers[formatIndex].name, value);
case NArchive::NHandlerPropID::kClassID:
return utils::SetPropGUID(handlers[formatIndex].guid, value);
case NArchive::NHandlerPropID::kExtension:
return utils::SetVariant(handlers[formatIndex].extension, value);
case NArchive::NHandlerPropID::kAddExtension:
return utils::SetVariant(handlers[formatIndex].add_extension, value);
case NArchive::NHandlerPropID::kFlags:
return utils::SetVariant(handlers[formatIndex].flags, value);
case NArchive::NHandlerPropID::kUpdate:
return utils::SetVariant(handlers[formatIndex].enable_update, value);
case NArchive::NHandlerPropID::kTimeFlags:
return S_OK;
case NArchive::NHandlerPropID::kSignature:
return utils::SetVariant(handlers[formatIndex].signature, 2, value);
case NArchive::NHandlerPropID::kMultiSignature:
return S_OK;
case NArchive::NHandlerPropID::kSignatureOffset:
return utils::SetVariant(0u, value);
default:
return E_FAIL;
}
}
STDAPI_LIB GetHandlerProperty2(UInt32 formatIndex, PROPID propID,
PROPVARIANT* value) {
switch (propID) {
case NArchive::NHandlerPropID::kName:
return utils::SetVariant(handlers[formatIndex].name, value);
case NArchive::NHandlerPropID::kClassID:
return utils::SetPropGUID(handlers[formatIndex].guid, value);
case NArchive::NHandlerPropID::kExtension:
return utils::SetVariant(handlers[formatIndex].extension, value);
case NArchive::NHandlerPropID::kAddExtension:
return utils::SetVariant(handlers[formatIndex].add_extension, value);
case NArchive::NHandlerPropID::kFlags:
return utils::SetVariant(handlers[formatIndex].flags, value);
case NArchive::NHandlerPropID::kUpdate:
return utils::SetVariant(handlers[formatIndex].enable_update, value);
case NArchive::NHandlerPropID::kTimeFlags:
return S_OK;
case NArchive::NHandlerPropID::kSignature:
return utils::SetVariant(handlers[formatIndex].signature, 2, value);
case NArchive::NHandlerPropID::kMultiSignature:
return S_OK;
case NArchive::NHandlerPropID::kSignatureOffset:
return utils::SetVariant(0u, value);
default:
return E_FAIL;
}
}
4. GetHandlerProperty and GetNumberOfFormats
We have 2 formats: sz
and sze
. And redirecting calls from GetHandlerProperty
to GetHandlerProperty2
C++
STDAPI_LIB GetHandlerProperty(PROPID propID, PROPVARIANT* value) {
return GetHandlerProperty2(0, propID, value);
}
STDAPI_LIB GetNumberOfFormats(UINT32* numFormats) {
*numFormats = static_cast<UInt32>(std::size(handlers));
return S_OK;
}
STDAPI_LIB GetHandlerProperty(PROPID propID, PROPVARIANT* value) {
return GetHandlerProperty2(0, propID, value);
}
STDAPI_LIB GetNumberOfFormats(UINT32* numFormats) {
*numFormats = static_cast<UInt32>(std::size(handlers));
return S_OK;
}
All set. Now we can start implementation of the SZ and SZE handlers.