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