// ArchiveExports.cpp #include "StdAfx.h" #include "../../../C/7zVersion.h" #include "../../Common/ComTry.h" #include "../../Windows/PropVariant.h" #include "../Common/RegisterArc.h" static const unsigned kNumArcsMax = 64; static unsigned g_NumArcs = 0; static unsigned g_DefaultArcIndex = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) throw() { if (g_NumArcs < kNumArcsMax) { const char *p = arcInfo->Name; if (p[0] == '7' && p[1] == 'z' && p[2] == 0) g_DefaultArcIndex = g_NumArcs; g_Arcs[g_NumArcs] = arcInfo; g_NumArcs++; } } DEFINE_GUID(CLSID_CArchiveHandler, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); #define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5]) static inline HRESULT SetPropString(const char *s, unsigned size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; return S_OK; } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { return SetPropString((const char *)&guid, sizeof(GUID), value); } int FindFormatCalssId(const GUID *clsID) { GUID cls = *clsID; CLS_ARC_ID_ITEM(cls) = 0; if (cls != CLSID_CArchiveHandler) return -1; Byte id = CLS_ARC_ID_ITEM(*clsID); for (unsigned i = 0; i < g_NumArcs; i++) if (g_Arcs[i]->ClassId == id) return (int)i; return -1; } STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject) { COM_TRY_BEGIN { int needIn = (*iid == IID_IInArchive); int needOut = (*iid == IID_IOutArchive); if (!needIn && !needOut) return E_NOINTERFACE; int formatIndex = FindFormatCalssId(clsid); if (formatIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; const CArcInfo &arc = *g_Arcs[formatIndex]; if (needIn) { *outObject = arc.CreateInArchive(); ((IInArchive *)*outObject)->AddRef(); } else { if (!arc.CreateOutArchive) return CLASS_E_CLASSNOTAVAILABLE; *outObject = arc.CreateOutArchive(); ((IOutArchive *)*outObject)->AddRef(); } } COM_TRY_END return S_OK; } STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NWindows::NCOM::PropVariant_Clear(value); if (formatIndex >= g_NumArcs) return E_INVALIDARG; const CArcInfo &arc = *g_Arcs[formatIndex]; NWindows::NCOM::CPropVariant prop; switch (propID) { case NArchive::NHandlerPropID::kName: prop = arc.Name; break; case NArchive::NHandlerPropID::kClassID: { GUID clsId = CLSID_CArchiveHandler; CLS_ARC_ID_ITEM(clsId) = arc.ClassId; return SetPropGUID(clsId, value); } case NArchive::NHandlerPropID::kExtension: if (arc.Ext) prop = arc.Ext; break; case NArchive::NHandlerPropID::kAddExtension: if (arc.AddExt) prop = arc.AddExt; break; case NArchive::NHandlerPropID::kUpdate: prop = (bool)(arc.CreateOutArchive != NULL); break; case NArchive::NHandlerPropID::kKeepName: prop = ((arc.Flags & NArcInfoFlags::kKeepName) != 0); break; case NArchive::NHandlerPropID::kAltStreams: prop = ((arc.Flags & NArcInfoFlags::kAltStreams) != 0); break; case NArchive::NHandlerPropID::kNtSecure: prop = ((arc.Flags & NArcInfoFlags::kNtSecure) != 0); break; case NArchive::NHandlerPropID::kFlags: prop = (UInt32)arc.Flags; break; case NArchive::NHandlerPropID::kSignatureOffset: prop = (UInt32)arc.SignatureOffset; break; // case NArchive::NHandlerPropID::kVersion: prop = (UInt32)MY_VER_MIX; break; case NArchive::NHandlerPropID::kSignature: if (!arc.IsMultiSignature()) return SetPropString((const char *)arc.Signature, arc.SignatureSize, value); break; case NArchive::NHandlerPropID::kMultiSignature: if (arc.IsMultiSignature()) return SetPropString((const char *)arc.Signature, arc.SignatureSize, value); break; } prop.Detach(value); return S_OK; COM_TRY_END } STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) { return GetHandlerProperty2(g_DefaultArcIndex, propID, value); } STDAPI GetNumberOfFormats(UINT32 *numFormats) { *numFormats = g_NumArcs; return S_OK; } STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc) { *isArc = NULL; if (formatIndex >= g_NumArcs) return E_INVALIDARG; *isArc = g_Arcs[formatIndex]->IsArc; return S_OK; }