misc/libphysfs/lzma/CPP/7zip/Compress/CodecExports.cpp
changeset 12213 bb5522e88ab2
equal deleted inserted replaced
12212:ea891871f481 12213:bb5522e88ab2
       
     1 // CodecExports.cpp
       
     2 
       
     3 #include "StdAfx.h"
       
     4 
       
     5 #include "../../Common/ComTry.h"
       
     6 #include "../../Windows/PropVariant.h"
       
     7 #include "../Common/RegisterCodec.h"
       
     8 #include "../ICoder.h"
       
     9 
       
    10 extern unsigned int g_NumCodecs;
       
    11 extern const CCodecInfo *g_Codecs[]; 
       
    12 
       
    13 static const UInt16 kDecodeId = 0x2790;
       
    14 
       
    15 DEFINE_GUID(CLSID_CCodec, 
       
    16 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
       
    17 
       
    18 static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value)
       
    19 {
       
    20   if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)
       
    21     value->vt = VT_BSTR;
       
    22   return S_OK;
       
    23 }
       
    24 
       
    25 static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
       
    26 {
       
    27   return SetPropString((const char *)&guid, sizeof(GUID), value);
       
    28 }
       
    29 
       
    30 static HRESULT SetClassID(CMethodId id, bool encode, PROPVARIANT *value)
       
    31 {
       
    32   GUID clsId = CLSID_CCodec;
       
    33   for (int i = 0; i < sizeof(id); i++, id >>= 8)
       
    34     clsId.Data4[i] = (Byte)(id & 0xFF);
       
    35   if (encode)
       
    36     clsId.Data3++;
       
    37   return SetPropGUID(clsId, value);
       
    38 }
       
    39 
       
    40 static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index)
       
    41 {
       
    42   index = -1;
       
    43   if (clsID->Data1 != CLSID_CCodec.Data1 || 
       
    44       clsID->Data2 != CLSID_CCodec.Data2 ||
       
    45       (clsID->Data3 & ~1) != kDecodeId)
       
    46     return S_OK;
       
    47   encode = (clsID->Data3 != kDecodeId);
       
    48   UInt64 id = 0;
       
    49   for (int j = 0; j < 8; j++)
       
    50     id |= ((UInt64)clsID->Data4[j]) << (8 * j);
       
    51   for (UInt32 i = 0; i < g_NumCodecs; i++)
       
    52   {
       
    53     const CCodecInfo &codec = *g_Codecs[i];
       
    54     if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder)
       
    55       continue;
       
    56     if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter ||
       
    57         codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2)
       
    58       return E_NOINTERFACE;
       
    59     index = i;
       
    60     return S_OK;
       
    61   }
       
    62   return S_OK;
       
    63 }
       
    64 
       
    65 STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject)
       
    66 {
       
    67   COM_TRY_BEGIN
       
    68   *outObject = 0;
       
    69   bool isCoder = (*iid == IID_ICompressCoder) != 0;
       
    70   bool isCoder2 = (*iid == IID_ICompressCoder2) != 0;
       
    71   bool isFilter = (*iid == IID_ICompressFilter) != 0;
       
    72   const CCodecInfo &codec = *g_Codecs[index];
       
    73   if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter ||
       
    74       codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2)
       
    75     return E_NOINTERFACE;
       
    76   if (encode)
       
    77   {
       
    78     if (!codec.CreateEncoder)
       
    79       return CLASS_E_CLASSNOTAVAILABLE;
       
    80     *outObject = codec.CreateEncoder();
       
    81   }
       
    82   else
       
    83   {
       
    84     if (!codec.CreateDecoder)
       
    85       return CLASS_E_CLASSNOTAVAILABLE;
       
    86     *outObject = codec.CreateDecoder();
       
    87   }
       
    88   if (isCoder)
       
    89     ((ICompressCoder *)*outObject)->AddRef();
       
    90   else if (isCoder2)
       
    91     ((ICompressCoder2 *)*outObject)->AddRef();
       
    92   else
       
    93     ((ICompressFilter *)*outObject)->AddRef();
       
    94   return S_OK;
       
    95   COM_TRY_END
       
    96 }
       
    97 
       
    98 STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject)
       
    99 {
       
   100   *outObject = 0;
       
   101   bool isCoder = (*iid == IID_ICompressCoder) != 0;
       
   102   bool isCoder2 = (*iid == IID_ICompressCoder2) != 0;
       
   103   bool isFilter = (*iid == IID_ICompressFilter) != 0;
       
   104   if (!isCoder && !isCoder2 && !isFilter)
       
   105     return E_NOINTERFACE;
       
   106   bool encode;
       
   107   int codecIndex;
       
   108   HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex);
       
   109   if (res != S_OK)
       
   110     return res;
       
   111   if (codecIndex < 0)
       
   112     return CLASS_E_CLASSNOTAVAILABLE;
       
   113   return CreateCoder2(encode, codecIndex, iid, outObject);
       
   114 }
       
   115 
       
   116 STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)
       
   117 {
       
   118   ::VariantClear((VARIANTARG *)value);
       
   119   const CCodecInfo &codec = *g_Codecs[codecIndex];
       
   120   switch(propID)
       
   121   {
       
   122     case NMethodPropID::kID:
       
   123     {
       
   124       value->uhVal.QuadPart = (UInt64)codec.Id;
       
   125       value->vt = VT_UI8;
       
   126       break;
       
   127     }
       
   128     case NMethodPropID::kName:
       
   129       if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0)
       
   130         value->vt = VT_BSTR;
       
   131       break;
       
   132     case NMethodPropID::kDecoder:
       
   133       if (codec.CreateDecoder)
       
   134         return SetClassID(codec.Id, false, value);
       
   135       break;
       
   136     case NMethodPropID::kEncoder:
       
   137       if (codec.CreateEncoder)
       
   138         return SetClassID(codec.Id, true, value);
       
   139       break;
       
   140     case NMethodPropID::kInStreams:
       
   141     {
       
   142       if (codec.NumInStreams != 1)
       
   143       {
       
   144         value->vt = VT_UI4;
       
   145         value->ulVal = codec.NumInStreams;
       
   146       }
       
   147       break;
       
   148     }
       
   149   }
       
   150   return S_OK;
       
   151 }
       
   152 
       
   153 STDAPI GetNumberOfMethods(UINT32 *numCodecs)
       
   154 {
       
   155   *numCodecs = g_NumCodecs;
       
   156   return S_OK;
       
   157 }