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 = 72;
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 }
27 // else throw 1;
28 }
29
30 Z7_DEFINE_GUID(CLSID_CArchiveHandler,
31 k_7zip_GUID_Data1,
32 k_7zip_GUID_Data2,
33 k_7zip_GUID_Data3_Common,
34 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
35
36 #define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5])
37
SetPropStrFromBin(const char * s,unsigned size,PROPVARIANT * value)38 static inline HRESULT SetPropStrFromBin(const char *s, unsigned size, PROPVARIANT *value)
39 {
40 if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != NULL)
41 value->vt = VT_BSTR;
42 return S_OK;
43 }
44
SetPropGUID(const GUID & guid,PROPVARIANT * value)45 static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
46 {
47 return SetPropStrFromBin((const char *)&guid, sizeof(guid), value);
48 }
49
FindFormatCalssId(const GUID * clsid)50 static int FindFormatCalssId(const GUID *clsid)
51 {
52 GUID cls = *clsid;
53 CLS_ARC_ID_ITEM(cls) = 0;
54 if (cls != CLSID_CArchiveHandler)
55 return -1;
56 const Byte id = CLS_ARC_ID_ITEM(*clsid);
57 for (unsigned i = 0; i < g_NumArcs; i++)
58 if (g_Arcs[i]->Id == id)
59 return (int)i;
60 return -1;
61 }
62
63 STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject);
CreateArchiver(const GUID * clsid,const GUID * iid,void ** outObject)64 STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject)
65 {
66 COM_TRY_BEGIN
67 {
68 const int needIn = (*iid == IID_IInArchive);
69 const int needOut = (*iid == IID_IOutArchive);
70 if (!needIn && !needOut)
71 return E_NOINTERFACE;
72 const int formatIndex = FindFormatCalssId(clsid);
73 if (formatIndex < 0)
74 return CLASS_E_CLASSNOTAVAILABLE;
75
76 const CArcInfo &arc = *g_Arcs[formatIndex];
77 if (needIn)
78 {
79 *outObject = arc.CreateInArchive();
80 ((IInArchive *)*outObject)->AddRef();
81 }
82 else
83 {
84 if (!arc.CreateOutArchive)
85 return CLASS_E_CLASSNOTAVAILABLE;
86 *outObject = arc.CreateOutArchive();
87 ((IOutArchive *)*outObject)->AddRef();
88 }
89 }
90 COM_TRY_END
91 return S_OK;
92 }
93
94 STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value);
GetHandlerProperty2(UInt32 formatIndex,PROPID propID,PROPVARIANT * value)95 STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value)
96 {
97 COM_TRY_BEGIN
98 NWindows::NCOM::PropVariant_Clear(value);
99 if (formatIndex >= g_NumArcs)
100 return E_INVALIDARG;
101 const CArcInfo &arc = *g_Arcs[formatIndex];
102 NWindows::NCOM::CPropVariant prop;
103 switch (propID)
104 {
105 case NArchive::NHandlerPropID::kName: prop = arc.Name; break;
106 case NArchive::NHandlerPropID::kClassID:
107 {
108 GUID clsId = CLSID_CArchiveHandler;
109 CLS_ARC_ID_ITEM(clsId) = arc.Id;
110 return SetPropGUID(clsId, value);
111 }
112 case NArchive::NHandlerPropID::kExtension: if (arc.Ext) prop = arc.Ext; break;
113 case NArchive::NHandlerPropID::kAddExtension: if (arc.AddExt) prop = arc.AddExt; break;
114 case NArchive::NHandlerPropID::kUpdate: prop = (bool)(arc.CreateOutArchive != NULL); break;
115 case NArchive::NHandlerPropID::kKeepName: prop = ((arc.Flags & NArcInfoFlags::kKeepName) != 0); break;
116 case NArchive::NHandlerPropID::kAltStreams: prop = ((arc.Flags & NArcInfoFlags::kAltStreams) != 0); break;
117 case NArchive::NHandlerPropID::kNtSecure: prop = ((arc.Flags & NArcInfoFlags::kNtSecure) != 0); break;
118 case NArchive::NHandlerPropID::kFlags: prop = (UInt32)arc.Flags; break;
119 case NArchive::NHandlerPropID::kTimeFlags: prop = (UInt32)arc.TimeFlags; break;
120 case NArchive::NHandlerPropID::kSignatureOffset: prop = (UInt32)arc.SignatureOffset; break;
121 // case NArchive::NHandlerPropID::kVersion: prop = (UInt32)MY_VER_MIX; break;
122
123 case NArchive::NHandlerPropID::kSignature:
124 if (arc.SignatureSize != 0 && !arc.IsMultiSignature())
125 return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value);
126 break;
127 case NArchive::NHandlerPropID::kMultiSignature:
128 if (arc.SignatureSize != 0 && arc.IsMultiSignature())
129 return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value);
130 break;
131 }
132 prop.Detach(value);
133 return S_OK;
134 COM_TRY_END
135 }
136
137 STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value);
GetHandlerProperty(PROPID propID,PROPVARIANT * value)138 STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
139 {
140 return GetHandlerProperty2(g_DefaultArcIndex, propID, value);
141 }
142
143 STDAPI GetNumberOfFormats(UINT32 *numFormats);
GetNumberOfFormats(UINT32 * numFormats)144 STDAPI GetNumberOfFormats(UINT32 *numFormats)
145 {
146 *numFormats = g_NumArcs;
147 return S_OK;
148 }
149
150 STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc);
GetIsArc(UInt32 formatIndex,Func_IsArc * isArc)151 STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc)
152 {
153 *isArc = NULL;
154 if (formatIndex >= g_NumArcs)
155 return E_INVALIDARG;
156 *isArc = g_Arcs[formatIndex]->IsArc;
157 return S_OK;
158 }
159