tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CodecExports.cpp (8503B)


      1 // CodecExports.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "../../../C/CpuArch.h"
      6 
      7 #include "../../Common/ComTry.h"
      8 #include "../../Common/MyCom.h"
      9 
     10 #include "../../Windows/Defs.h"
     11 
     12 #include "../ICoder.h"
     13 
     14 #include "../Common/RegisterCodec.h"
     15 
     16 extern unsigned g_NumCodecs;
     17 extern const CCodecInfo *g_Codecs[];
     18 
     19 extern unsigned g_NumHashers;
     20 extern const CHasherInfo *g_Hashers[];
     21 
     22 static void SetPropFromAscii(const char *s, PROPVARIANT *prop) throw()
     23 {
     24  UINT len = (UINT)strlen(s);
     25  BSTR dest = ::SysAllocStringLen(NULL, len);
     26  if (dest)
     27  {
     28    for (UINT i = 0; i <= len; i++)
     29      dest[i] = (Byte)s[i];
     30    prop->bstrVal = dest;
     31    prop->vt = VT_BSTR;
     32  }
     33 }
     34 
     35 static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) throw()
     36 {
     37  if ((value->bstrVal = ::SysAllocStringByteLen((const char *)&guid, sizeof(guid))) != NULL)
     38    value->vt = VT_BSTR;
     39  return S_OK;
     40 }
     41 
     42 static HRESULT MethodToClassID(UInt16 typeId, CMethodId id, PROPVARIANT *value) throw()
     43 {
     44  GUID clsId;
     45  clsId.Data1 = k_7zip_GUID_Data1;
     46  clsId.Data2 = k_7zip_GUID_Data2;
     47  clsId.Data3 = typeId;
     48  SetUi64(clsId.Data4, id);
     49  return SetPropGUID(clsId, value);
     50 }
     51 
     52 static HRESULT FindCodecClassId(const GUID *clsid, bool isCoder2, bool isFilter, bool &encode, int &index) throw()
     53 {
     54  index = -1;
     55  if (clsid->Data1 != k_7zip_GUID_Data1 ||
     56      clsid->Data2 != k_7zip_GUID_Data2)
     57    return S_OK;
     58  
     59  encode = true;
     60  
     61       if (clsid->Data3 == k_7zip_GUID_Data3_Decoder) encode = false;
     62  else if (clsid->Data3 != k_7zip_GUID_Data3_Encoder) return S_OK;
     63  
     64  UInt64 id = GetUi64(clsid->Data4);
     65  
     66  for (unsigned i = 0; i < g_NumCodecs; i++)
     67  {
     68    const CCodecInfo &codec = *g_Codecs[i];
     69    
     70    if (id != codec.Id
     71        || (encode ? !codec.CreateEncoder : !codec.CreateDecoder)
     72        || (isFilter ? !codec.IsFilter : codec.IsFilter))
     73      continue;
     74 
     75    if (codec.NumStreams == 1 ? isCoder2 : !isCoder2)
     76      return E_NOINTERFACE;
     77    
     78    index = i;
     79    return S_OK;
     80  }
     81  
     82  return S_OK;
     83 }
     84 
     85 static HRESULT CreateCoderMain(unsigned index, bool encode, void **coder)
     86 {
     87  COM_TRY_BEGIN
     88  
     89  const CCodecInfo &codec = *g_Codecs[index];
     90  
     91  void *c;
     92  if (encode)
     93    c = codec.CreateEncoder();
     94  else
     95    c = codec.CreateDecoder();
     96  
     97  if (c)
     98  {
     99    IUnknown *unk;
    100    if (codec.IsFilter)
    101      unk = (IUnknown *)(ICompressFilter *)c;
    102    else if (codec.NumStreams != 1)
    103      unk = (IUnknown *)(ICompressCoder2 *)c;
    104    else
    105      unk = (IUnknown *)(ICompressCoder *)c;
    106    unk->AddRef();
    107    *coder = c;
    108  }
    109  return S_OK;
    110  
    111  COM_TRY_END
    112 }
    113 
    114 static HRESULT CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject)
    115 {
    116  *outObject = NULL;
    117 
    118  const CCodecInfo &codec = *g_Codecs[index];
    119 
    120  if (encode ? !codec.CreateEncoder : !codec.CreateDecoder)
    121    return CLASS_E_CLASSNOTAVAILABLE;
    122 
    123  if (codec.IsFilter)
    124  {
    125    if (*iid != IID_ICompressFilter) return E_NOINTERFACE;
    126  }
    127  else if (codec.NumStreams != 1)
    128  {
    129    if (*iid != IID_ICompressCoder2) return E_NOINTERFACE;
    130  }
    131  else
    132  {
    133    if (*iid != IID_ICompressCoder) return E_NOINTERFACE;
    134  }
    135  
    136  return CreateCoderMain(index, encode, outObject);
    137 }
    138 
    139 STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject)
    140 {
    141  return CreateCoder2(false, index, iid, outObject);
    142 }
    143 
    144 STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject)
    145 {
    146  return CreateCoder2(true, index, iid, outObject);
    147 }
    148 
    149 STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject)
    150 {
    151  *outObject = NULL;
    152 
    153  bool isFilter = false;
    154  bool isCoder2 = false;
    155  bool isCoder = (*iid == IID_ICompressCoder) != 0;
    156  if (!isCoder)
    157  {
    158    isFilter = (*iid == IID_ICompressFilter) != 0;
    159    if (!isFilter)
    160    {
    161      isCoder2 = (*iid == IID_ICompressCoder2) != 0;
    162      if (!isCoder2)
    163        return E_NOINTERFACE;
    164    }
    165  }
    166  
    167  bool encode;
    168  int codecIndex;
    169  HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex);
    170  if (res != S_OK)
    171    return res;
    172  if (codecIndex < 0)
    173    return CLASS_E_CLASSNOTAVAILABLE;
    174 
    175  return CreateCoderMain(codecIndex, encode, outObject);
    176 }
    177 
    178 STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)
    179 {
    180  ::VariantClear((VARIANTARG *)value);
    181  const CCodecInfo &codec = *g_Codecs[codecIndex];
    182  switch (propID)
    183  {
    184    case NMethodPropID::kID:
    185      value->uhVal.QuadPart = (UInt64)codec.Id;
    186      value->vt = VT_UI8;
    187      break;
    188    case NMethodPropID::kName:
    189      SetPropFromAscii(codec.Name, value);
    190      break;
    191    case NMethodPropID::kDecoder:
    192      if (codec.CreateDecoder)
    193        return MethodToClassID(k_7zip_GUID_Data3_Decoder, codec.Id, value);
    194      break;
    195    case NMethodPropID::kEncoder:
    196      if (codec.CreateEncoder)
    197        return MethodToClassID(k_7zip_GUID_Data3_Encoder, codec.Id, value);
    198      break;
    199    case NMethodPropID::kDecoderIsAssigned:
    200        value->vt = VT_BOOL;
    201        value->boolVal = BoolToVARIANT_BOOL(codec.CreateDecoder != NULL);
    202      break;
    203    case NMethodPropID::kEncoderIsAssigned:
    204        value->vt = VT_BOOL;
    205        value->boolVal = BoolToVARIANT_BOOL(codec.CreateEncoder != NULL);
    206      break;
    207    case NMethodPropID::kPackStreams:
    208      if (codec.NumStreams != 1)
    209      {
    210        value->vt = VT_UI4;
    211        value->ulVal = (ULONG)codec.NumStreams;
    212      }
    213      break;
    214    /*
    215    case NMethodPropID::kIsFilter:
    216      // if (codec.IsFilter)
    217      {
    218        value->vt = VT_BOOL;
    219        value->boolVal = BoolToVARIANT_BOOL(codec.IsFilter);
    220      }
    221      break;
    222    */
    223    /*
    224    case NMethodPropID::kDecoderFlags:
    225      {
    226        value->vt = VT_UI4;
    227        value->ulVal = (ULONG)codec.DecoderFlags;
    228      }
    229      break;
    230    case NMethodPropID::kEncoderFlags:
    231      {
    232        value->vt = VT_UI4;
    233        value->ulVal = (ULONG)codec.EncoderFlags;
    234      }
    235      break;
    236    */
    237  }
    238  return S_OK;
    239 }
    240 
    241 STDAPI GetNumberOfMethods(UINT32 *numCodecs)
    242 {
    243  *numCodecs = g_NumCodecs;
    244  return S_OK;
    245 }
    246 
    247 
    248 // ---------- Hashers ----------
    249 
    250 static int FindHasherClassId(const GUID *clsid) throw()
    251 {
    252  if (clsid->Data1 != k_7zip_GUID_Data1 ||
    253      clsid->Data2 != k_7zip_GUID_Data2 ||
    254      clsid->Data3 != k_7zip_GUID_Data3_Hasher)
    255    return -1;
    256  UInt64 id = GetUi64(clsid->Data4);
    257  for (unsigned i = 0; i < g_NumCodecs; i++)
    258    if (id == g_Hashers[i]->Id)
    259      return i;
    260  return -1;
    261 }
    262 
    263 static HRESULT CreateHasher2(UInt32 index, IHasher **hasher)
    264 {
    265  COM_TRY_BEGIN
    266  *hasher = g_Hashers[index]->CreateHasher();
    267  if (*hasher)
    268    (*hasher)->AddRef();
    269  return S_OK;
    270  COM_TRY_END
    271 }
    272 
    273 STDAPI CreateHasher(const GUID *clsid, IHasher **outObject)
    274 {
    275  COM_TRY_BEGIN
    276  *outObject = 0;
    277  int index = FindHasherClassId(clsid);
    278  if (index < 0)
    279    return CLASS_E_CLASSNOTAVAILABLE;
    280  return CreateHasher2(index, outObject);
    281  COM_TRY_END
    282 }
    283 
    284 STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)
    285 {
    286  ::VariantClear((VARIANTARG *)value);
    287  const CHasherInfo &codec = *g_Hashers[codecIndex];
    288  switch (propID)
    289  {
    290    case NMethodPropID::kID:
    291      value->uhVal.QuadPart = (UInt64)codec.Id;
    292      value->vt = VT_UI8;
    293      break;
    294    case NMethodPropID::kName:
    295      SetPropFromAscii(codec.Name, value);
    296      break;
    297    case NMethodPropID::kEncoder:
    298      if (codec.CreateHasher)
    299        return MethodToClassID(k_7zip_GUID_Data3_Hasher, codec.Id, value);
    300      break;
    301    case NMethodPropID::kDigestSize:
    302      value->ulVal = (ULONG)codec.DigestSize;
    303      value->vt = VT_UI4;
    304      break;
    305  }
    306  return S_OK;
    307 }
    308 
    309 class CHashers:
    310  public IHashers,
    311  public CMyUnknownImp
    312 {
    313 public:
    314  MY_UNKNOWN_IMP1(IHashers)
    315 
    316  STDMETHOD_(UInt32, GetNumHashers)();
    317  STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value);
    318  STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher);
    319 };
    320 
    321 STDAPI GetHashers(IHashers **hashers)
    322 {
    323  COM_TRY_BEGIN
    324  *hashers = new CHashers;
    325  if (*hashers)
    326    (*hashers)->AddRef();
    327  return S_OK;
    328  COM_TRY_END
    329 }
    330 
    331 STDMETHODIMP_(UInt32) CHashers::GetNumHashers()
    332 {
    333  return g_NumHashers;
    334 }
    335 
    336 STDMETHODIMP CHashers::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value)
    337 {
    338  return ::GetHasherProp(index, propID, value);
    339 }
    340 
    341 STDMETHODIMP CHashers::CreateHasher(UInt32 index, IHasher **hasher)
    342 {
    343  return ::CreateHasher2(index, hasher);
    344 }