1 // ArchiveExports.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../C/7zVersion.h"
6
7 #include "../../Common/ComTry.h"
8
9 #include "../../Windows/PropVariant.h"
10
11 #include "../Common/RegisterArc.h"
12
13 static const unsigned kNumArcsMax = 64;
14 static unsigned g_NumArcs = 0;
15 static unsigned g_DefaultArcIndex = 0;
16 static const CArcInfo *g_Arcs[kNumArcsMax];
17
RegisterArc(const CArcInfo * arcInfo)18 void RegisterArc(const CArcInfo *arcInfo) throw()
19 {
20 if (g_NumArcs < kNumArcsMax)
21 {
22 const char *p = arcInfo->Name;
23 if (p[0] == '7' && p[1] == 'z' && p[2] == 0)
24 g_DefaultArcIndex = g_NumArcs;
25 g_Arcs[g_NumArcs] = arcInfo;
26 g_NumArcs++;
27 }
28 }
29
30 DEFINE_GUID(CLSID_CArchiveHandler,
31 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
32
33 #define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5])
34
SetPropString(const char * s,unsigned size,PROPVARIANT * value)35 static inline HRESULT SetPropString(const char *s, unsigned size, PROPVARIANT *value)
36 {
37 if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)
38 value->vt = VT_BSTR;
39 return S_OK;
40 }
41
SetPropGUID(const GUID & guid,PROPVARIANT * value)42 static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
43 {
44 return SetPropString((const char *)&guid, sizeof(GUID), value);
45 }
46
FindFormatCalssId(const GUID * clsID)47 int FindFormatCalssId(const GUID *clsID)
48 {
49 GUID cls = *clsID;
50 CLS_ARC_ID_ITEM(cls) = 0;
51 if (cls != CLSID_CArchiveHandler)
52 return -1;
53 Byte id = CLS_ARC_ID_ITEM(*clsID);
54 for (unsigned i = 0; i < g_NumArcs; i++)
55 if (g_Arcs[i]->ClassId == id)
56 return (int)i;
57 return -1;
58 }
59
CreateArchiver(const GUID * clsid,const GUID * iid,void ** outObject)60 STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject)
61 {
62 COM_TRY_BEGIN
63 {
64 int needIn = (*iid == IID_IInArchive);
65 int needOut = (*iid == IID_IOutArchive);
66 if (!needIn && !needOut)
67 return E_NOINTERFACE;
68 int formatIndex = FindFormatCalssId(clsid);
69 if (formatIndex < 0)
70 return CLASS_E_CLASSNOTAVAILABLE;
71
72 const CArcInfo &arc = *g_Arcs[formatIndex];
73 if (needIn)
74 {
75 *outObject = arc.CreateInArchive();
76 ((IInArchive *)*outObject)->AddRef();
77 }
78 else
79 {
80 if (!arc.CreateOutArchive)
81 return CLASS_E_CLASSNOTAVAILABLE;
82 *outObject = arc.CreateOutArchive();
83 ((IOutArchive *)*outObject)->AddRef();
84 }
85 }
86 COM_TRY_END
87 return S_OK;
88 }
89
GetHandlerProperty2(UInt32 formatIndex,PROPID propID,PROPVARIANT * value)90 STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value)
91 {
92 COM_TRY_BEGIN
93 NWindows::NCOM::PropVariant_Clear(value);
94 if (formatIndex >= g_NumArcs)
95 return E_INVALIDARG;
96 const CArcInfo &arc = *g_Arcs[formatIndex];
97 NWindows::NCOM::CPropVariant prop;
98 switch (propID)
99 {
100 case NArchive::NHandlerPropID::kName: prop = arc.Name; break;
101 case NArchive::NHandlerPropID::kClassID:
102 {
103 GUID clsId = CLSID_CArchiveHandler;
104 CLS_ARC_ID_ITEM(clsId) = arc.ClassId;
105 return SetPropGUID(clsId, value);
106 }
107 case NArchive::NHandlerPropID::kExtension: if (arc.Ext) prop = arc.Ext; break;
108 case NArchive::NHandlerPropID::kAddExtension: if (arc.AddExt) prop = arc.AddExt; break;
109 case NArchive::NHandlerPropID::kUpdate: prop = (bool)(arc.CreateOutArchive != NULL); break;
110 case NArchive::NHandlerPropID::kKeepName: prop = ((arc.Flags & NArcInfoFlags::kKeepName) != 0); break;
111 case NArchive::NHandlerPropID::kAltStreams: prop = ((arc.Flags & NArcInfoFlags::kAltStreams) != 0); break;
112 case NArchive::NHandlerPropID::kNtSecure: prop = ((arc.Flags & NArcInfoFlags::kNtSecure) != 0); break;
113 case NArchive::NHandlerPropID::kFlags: prop = (UInt32)arc.Flags; break;
114 case NArchive::NHandlerPropID::kSignatureOffset: prop = (UInt32)arc.SignatureOffset; break;
115 // case NArchive::NHandlerPropID::kVersion: prop = (UInt32)MY_VER_MIX; break;
116
117 case NArchive::NHandlerPropID::kSignature:
118 if (!arc.IsMultiSignature())
119 return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);
120 break;
121 case NArchive::NHandlerPropID::kMultiSignature:
122 if (arc.IsMultiSignature())
123 return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);
124 break;
125 }
126 prop.Detach(value);
127 return S_OK;
128 COM_TRY_END
129 }
130
GetHandlerProperty(PROPID propID,PROPVARIANT * value)131 STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
132 {
133 return GetHandlerProperty2(g_DefaultArcIndex, propID, value);
134 }
135
GetNumberOfFormats(UINT32 * numFormats)136 STDAPI GetNumberOfFormats(UINT32 *numFormats)
137 {
138 *numFormats = g_NumArcs;
139 return S_OK;
140 }
141
GetIsArc(UInt32 formatIndex,Func_IsArc * isArc)142 STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc)
143 {
144 *isArc = NULL;
145 if (formatIndex >= g_NumArcs)
146 return E_INVALIDARG;
147 *isArc = g_Arcs[formatIndex]->IsArc;
148 return S_OK;
149 }
150