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
13static const unsigned kNumArcsMax = 72;
14static unsigned g_NumArcs = 0;
15static unsigned g_DefaultArcIndex = 0;
16static const CArcInfo *g_Arcs[kNumArcsMax];
17
18void 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
30Z7_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
38static 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
45static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
46{
47  return SetPropStrFromBin((const char *)&guid, sizeof(guid), value);
48}
49
50static 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
63STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject);
64STDAPI 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
94STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value);
95STDAPI 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
137STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value);
138STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
139{
140  return GetHandlerProperty2(g_DefaultArcIndex, propID, value);
141}
142
143STDAPI GetNumberOfFormats(UINT32 *numFormats);
144STDAPI GetNumberOfFormats(UINT32 *numFormats)
145{
146  *numFormats = g_NumArcs;
147  return S_OK;
148}
149
150STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc);
151STDAPI 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