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