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
11static const unsigned int kNumArcsMax = 48;
12static unsigned int g_NumArcs = 0;
13static unsigned int g_DefaultArcIndex = 0;
14static const CArcInfo *g_Arcs[kNumArcsMax];
15void 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
26DEFINE_GUID(CLSID_CArchiveHandler,
270x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
28
29#define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5])
30
31static 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
38static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
39{
40  return SetPropString((const char *)&guid, sizeof(GUID), value);
41}
42
43int 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
56STDAPI 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
86STDAPI 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
126STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
127{
128  return GetHandlerProperty2(g_DefaultArcIndex, propID, value);
129}
130
131STDAPI GetNumberOfFormats(UINT32 *numFormats)
132{
133  *numFormats = g_NumArcs;
134  return S_OK;
135}
136