Home | History | Annotate | Download | only in Archive
      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 
     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 
     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 
     42 static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
     43 {
     44   return SetPropString((const char *)&guid, sizeof(GUID), value);
     45 }
     46 
     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 
     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 
     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 
    131 STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
    132 {
    133   return GetHandlerProperty2(g_DefaultArcIndex, propID, value);
    134 }
    135 
    136 STDAPI GetNumberOfFormats(UINT32 *numFormats)
    137 {
    138   *numFormats = g_NumArcs;
    139   return S_OK;
    140 }
    141 
    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