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