tor-browser

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

CreateCoder.cpp (13042B)


      1 // CreateCoder.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "../../Windows/Defs.h"
      6 #include "../../Windows/PropVariant.h"
      7 
      8 #include "CreateCoder.h"
      9 
     10 #include "FilterCoder.h"
     11 #include "RegisterCodec.h"
     12 
     13 static const unsigned kNumCodecsMax = 64;
     14 unsigned g_NumCodecs = 0;
     15 const CCodecInfo *g_Codecs[kNumCodecsMax];
     16 
     17 // We use g_ExternalCodecs in other stages.
     18 /*
     19 #ifdef EXTERNAL_CODECS
     20 extern CExternalCodecs g_ExternalCodecs;
     21 #define CHECK_GLOBAL_CODECS \
     22    if (!__externalCodecs || !__externalCodecs->IsSet()) __externalCodecs = &g_ExternalCodecs;
     23 #endif
     24 */
     25 
     26 #define CHECK_GLOBAL_CODECS
     27 
     28 void RegisterCodec(const CCodecInfo *codecInfo) throw()
     29 {
     30  if (g_NumCodecs < kNumCodecsMax)
     31    g_Codecs[g_NumCodecs++] = codecInfo;
     32 }
     33 
     34 static const unsigned kNumHashersMax = 16;
     35 unsigned g_NumHashers = 0;
     36 const CHasherInfo *g_Hashers[kNumHashersMax];
     37 
     38 void RegisterHasher(const CHasherInfo *hashInfo) throw()
     39 {
     40  if (g_NumHashers < kNumHashersMax)
     41    g_Hashers[g_NumHashers++] = hashInfo;
     42 }
     43 
     44 
     45 #ifdef EXTERNAL_CODECS
     46 
     47 static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res)
     48 {
     49  NWindows::NCOM::CPropVariant prop;
     50  RINOK(codecsInfo->GetProperty(index, propID, &prop));
     51  if (prop.vt == VT_EMPTY)
     52    res = 1;
     53  else if (prop.vt == VT_UI4)
     54    res = prop.ulVal;
     55  else
     56    return E_INVALIDARG;
     57  return S_OK;
     58 }
     59 
     60 static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res)
     61 {
     62  NWindows::NCOM::CPropVariant prop;
     63  RINOK(codecsInfo->GetProperty(index, propID, &prop));
     64  if (prop.vt == VT_EMPTY)
     65    res = true;
     66  else if (prop.vt == VT_BOOL)
     67    res = VARIANT_BOOLToBool(prop.boolVal);
     68  else
     69    return E_INVALIDARG;
     70  return S_OK;
     71 }
     72 
     73 HRESULT CExternalCodecs::Load()
     74 {
     75  Codecs.Clear();
     76  Hashers.Clear();
     77 
     78  if (GetCodecs)
     79  {
     80    CCodecInfoEx info;
     81    
     82    UString s;
     83    UInt32 num;
     84    RINOK(GetCodecs->GetNumMethods(&num));
     85    
     86    for (UInt32 i = 0; i < num; i++)
     87    {
     88      NWindows::NCOM::CPropVariant prop;
     89      
     90      RINOK(GetCodecs->GetProperty(i, NMethodPropID::kID, &prop));
     91      if (prop.vt != VT_UI8)
     92        continue; // old Interface
     93      info.Id = prop.uhVal.QuadPart;
     94      
     95      prop.Clear();
     96      
     97      info.Name.Empty();
     98      RINOK(GetCodecs->GetProperty(i, NMethodPropID::kName, &prop));
     99      if (prop.vt == VT_BSTR)
    100        info.Name.SetFromWStr_if_Ascii(prop.bstrVal);
    101      else if (prop.vt != VT_EMPTY)
    102        continue;
    103      
    104      RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kPackStreams, info.NumStreams));
    105      {
    106        UInt32 numUnpackStreams = 1;
    107        RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kUnpackStreams, numUnpackStreams));
    108        if (numUnpackStreams != 1)
    109          continue;
    110      }
    111      RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned));
    112      RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned));
    113      
    114      Codecs.Add(info);
    115    }
    116  }
    117  
    118  if (GetHashers)
    119  {
    120    UInt32 num = GetHashers->GetNumHashers();
    121    CHasherInfoEx info;
    122    
    123    for (UInt32 i = 0; i < num; i++)
    124    {
    125      NWindows::NCOM::CPropVariant prop;
    126 
    127      RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kID, &prop));
    128      if (prop.vt != VT_UI8)
    129        continue;
    130      info.Id = prop.uhVal.QuadPart;
    131      
    132      prop.Clear();
    133      
    134      info.Name.Empty();
    135      RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kName, &prop));
    136      if (prop.vt == VT_BSTR)
    137        info.Name.SetFromWStr_if_Ascii(prop.bstrVal);
    138      else if (prop.vt != VT_EMPTY)
    139        continue;
    140      
    141      Hashers.Add(info);
    142    }
    143  }
    144  
    145  return S_OK;
    146 }
    147 
    148 #endif
    149 
    150 
    151 int FindMethod_Index(
    152    DECL_EXTERNAL_CODECS_LOC_VARS
    153    const AString &name,
    154    bool encode,
    155    CMethodId &methodId,
    156    UInt32 &numStreams)
    157 {
    158  unsigned i;
    159  for (i = 0; i < g_NumCodecs; i++)
    160  {
    161    const CCodecInfo &codec = *g_Codecs[i];
    162    if ((encode ? codec.CreateEncoder : codec.CreateDecoder)
    163        && StringsAreEqualNoCase_Ascii(name, codec.Name))
    164    {
    165      methodId = codec.Id;
    166      numStreams = codec.NumStreams;
    167      return i;
    168    }
    169  }
    170  
    171  #ifdef EXTERNAL_CODECS
    172  
    173  CHECK_GLOBAL_CODECS
    174 
    175  if (__externalCodecs)
    176    for (i = 0; i < __externalCodecs->Codecs.Size(); i++)
    177    {
    178      const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
    179      if ((encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned)
    180          && StringsAreEqualNoCase_Ascii(name, codec.Name))
    181      {
    182        methodId = codec.Id;
    183        numStreams = codec.NumStreams;
    184        return g_NumCodecs + i;
    185      }
    186    }
    187  
    188  #endif
    189  
    190  return -1;
    191 }
    192 
    193 
    194 static int FindMethod_Index(
    195    DECL_EXTERNAL_CODECS_LOC_VARS
    196    CMethodId methodId, bool encode)
    197 {
    198  unsigned i;
    199  for (i = 0; i < g_NumCodecs; i++)
    200  {
    201    const CCodecInfo &codec = *g_Codecs[i];
    202    if (codec.Id == methodId && (encode ? codec.CreateEncoder : codec.CreateDecoder))
    203      return i;
    204  }
    205  
    206  #ifdef EXTERNAL_CODECS
    207  
    208  CHECK_GLOBAL_CODECS
    209 
    210  if (__externalCodecs)
    211    for (i = 0; i < __externalCodecs->Codecs.Size(); i++)
    212    {
    213      const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
    214      if (codec.Id == methodId && (encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned))
    215        return g_NumCodecs + i;
    216    }
    217  
    218  #endif
    219  
    220  return -1;
    221 }
    222 
    223 
    224 bool FindMethod(
    225    DECL_EXTERNAL_CODECS_LOC_VARS
    226    CMethodId methodId,
    227    AString &name)
    228 {
    229  name.Empty();
    230 
    231  unsigned i;
    232  for (i = 0; i < g_NumCodecs; i++)
    233  {
    234    const CCodecInfo &codec = *g_Codecs[i];
    235    if (methodId == codec.Id)
    236    {
    237      name = codec.Name;
    238      return true;
    239    }
    240  }
    241  
    242  #ifdef EXTERNAL_CODECS
    243 
    244  CHECK_GLOBAL_CODECS
    245 
    246  if (__externalCodecs)
    247    for (i = 0; i < __externalCodecs->Codecs.Size(); i++)
    248    {
    249      const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
    250      if (methodId == codec.Id)
    251      {
    252        name = codec.Name;
    253        return true;
    254      }
    255    }
    256  
    257  #endif
    258  
    259  return false;
    260 }
    261 
    262 bool FindHashMethod(
    263    DECL_EXTERNAL_CODECS_LOC_VARS
    264    const AString &name,
    265    CMethodId &methodId)
    266 {
    267  unsigned i;
    268  for (i = 0; i < g_NumHashers; i++)
    269  {
    270    const CHasherInfo &codec = *g_Hashers[i];
    271    if (StringsAreEqualNoCase_Ascii(name, codec.Name))
    272    {
    273      methodId = codec.Id;
    274      return true;
    275    }
    276  }
    277  
    278  #ifdef EXTERNAL_CODECS
    279 
    280  CHECK_GLOBAL_CODECS
    281 
    282  if (__externalCodecs)
    283    for (i = 0; i < __externalCodecs->Hashers.Size(); i++)
    284    {
    285      const CHasherInfoEx &codec = __externalCodecs->Hashers[i];
    286      if (StringsAreEqualNoCase_Ascii(name, codec.Name))
    287      {
    288        methodId = codec.Id;
    289        return true;
    290      }
    291    }
    292  
    293  #endif
    294  
    295  return false;
    296 }
    297 
    298 void GetHashMethods(
    299    DECL_EXTERNAL_CODECS_LOC_VARS
    300    CRecordVector<CMethodId> &methods)
    301 {
    302  methods.ClearAndSetSize(g_NumHashers);
    303  unsigned i;
    304  for (i = 0; i < g_NumHashers; i++)
    305    methods[i] = (*g_Hashers[i]).Id;
    306  
    307  #ifdef EXTERNAL_CODECS
    308  
    309  CHECK_GLOBAL_CODECS
    310 
    311  if (__externalCodecs)
    312    for (i = 0; i < __externalCodecs->Hashers.Size(); i++)
    313      methods.Add(__externalCodecs->Hashers[i].Id);
    314  
    315  #endif
    316 }
    317 
    318 
    319 
    320 HRESULT CreateCoder_Index(
    321    DECL_EXTERNAL_CODECS_LOC_VARS
    322    unsigned i, bool encode,
    323    CMyComPtr<ICompressFilter> &filter,
    324    CCreatedCoder &cod)
    325 {
    326  cod.IsExternal = false;
    327  cod.IsFilter = false;
    328  cod.NumStreams = 1;
    329 
    330  if (i < g_NumCodecs)
    331  {
    332    const CCodecInfo &codec = *g_Codecs[i];
    333    // if (codec.Id == methodId)
    334    {
    335      if (encode)
    336      {
    337        if (codec.CreateEncoder)
    338        {
    339          void *p = codec.CreateEncoder();
    340          if (codec.IsFilter) filter = (ICompressFilter *)p;
    341          else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p;
    342          else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; }
    343          return S_OK;
    344        }
    345      }
    346      else
    347        if (codec.CreateDecoder)
    348        {
    349          void *p = codec.CreateDecoder();
    350          if (codec.IsFilter) filter = (ICompressFilter *)p;
    351          else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p;
    352          else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; }
    353          return S_OK;
    354        }
    355    }
    356  }
    357 
    358  #ifdef EXTERNAL_CODECS
    359 
    360  CHECK_GLOBAL_CODECS
    361  
    362  if (__externalCodecs)
    363  {
    364    i -= g_NumCodecs;
    365    cod.IsExternal = true;
    366    if (i < __externalCodecs->Codecs.Size())
    367    {
    368      const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
    369      // if (codec.Id == methodId)
    370      {
    371        if (encode)
    372        {
    373          if (codec.EncoderIsAssigned)
    374          {
    375            if (codec.NumStreams == 1)
    376            {
    377              HRESULT res = __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder, (void **)&cod.Coder);
    378              if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE)
    379                return res;
    380              if (cod.Coder)
    381                return res;
    382              return __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter);
    383            }
    384            cod.NumStreams = codec.NumStreams;
    385            return __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2);
    386          }
    387        }
    388        else
    389          if (codec.DecoderIsAssigned)
    390          {
    391            if (codec.NumStreams == 1)
    392            {
    393              HRESULT res = __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder, (void **)&cod.Coder);
    394              if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE)
    395                return res;
    396              if (cod.Coder)
    397                return res;
    398              return __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter);
    399            }
    400            cod.NumStreams = codec.NumStreams;
    401            return __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2);
    402          }
    403      }
    404    }
    405  }
    406  #endif
    407 
    408  return S_OK;
    409 }
    410 
    411 
    412 HRESULT CreateCoder_Index(
    413    DECL_EXTERNAL_CODECS_LOC_VARS
    414    unsigned index, bool encode,
    415    CCreatedCoder &cod)
    416 {
    417  CMyComPtr<ICompressFilter> filter;
    418  HRESULT res = CreateCoder_Index(
    419      EXTERNAL_CODECS_LOC_VARS
    420      index, encode,
    421      filter, cod);
    422  
    423  if (filter)
    424  {
    425    cod.IsFilter = true;
    426    CFilterCoder *coderSpec = new CFilterCoder(encode);
    427    cod.Coder = coderSpec;
    428    coderSpec->Filter = filter;
    429  }
    430  
    431  return res;
    432 }
    433 
    434 
    435 HRESULT CreateCoder_Id(
    436    DECL_EXTERNAL_CODECS_LOC_VARS
    437    CMethodId methodId, bool encode,
    438    CMyComPtr<ICompressFilter> &filter,
    439    CCreatedCoder &cod)
    440 {
    441  int index = FindMethod_Index(EXTERNAL_CODECS_LOC_VARS methodId, encode);
    442  if (index < 0)
    443    return S_OK;
    444  return CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS index, encode, filter, cod);
    445 }
    446 
    447 
    448 HRESULT CreateCoder_Id(
    449    DECL_EXTERNAL_CODECS_LOC_VARS
    450    CMethodId methodId, bool encode,
    451    CCreatedCoder &cod)
    452 {
    453  CMyComPtr<ICompressFilter> filter;
    454  HRESULT res = CreateCoder_Id(
    455      EXTERNAL_CODECS_LOC_VARS
    456      methodId, encode,
    457      filter, cod);
    458  
    459  if (filter)
    460  {
    461    cod.IsFilter = true;
    462    CFilterCoder *coderSpec = new CFilterCoder(encode);
    463    cod.Coder = coderSpec;
    464    coderSpec->Filter = filter;
    465  }
    466  
    467  return res;
    468 }
    469 
    470 
    471 HRESULT CreateCoder_Id(
    472    DECL_EXTERNAL_CODECS_LOC_VARS
    473    CMethodId methodId, bool encode,
    474    CMyComPtr<ICompressCoder> &coder)
    475 {
    476  CCreatedCoder cod;
    477  HRESULT res = CreateCoder_Id(
    478      EXTERNAL_CODECS_LOC_VARS
    479      methodId, encode,
    480      cod);
    481  coder = cod.Coder;
    482  return res;
    483 }
    484 
    485 HRESULT CreateFilter(
    486    DECL_EXTERNAL_CODECS_LOC_VARS
    487    CMethodId methodId, bool encode,
    488    CMyComPtr<ICompressFilter> &filter)
    489 {
    490  CCreatedCoder cod;
    491  return CreateCoder_Id(
    492      EXTERNAL_CODECS_LOC_VARS
    493      methodId, encode,
    494      filter, cod);
    495 }
    496 
    497 
    498 HRESULT CreateHasher(
    499    DECL_EXTERNAL_CODECS_LOC_VARS
    500    CMethodId methodId,
    501    AString &name,
    502    CMyComPtr<IHasher> &hasher)
    503 {
    504  name.Empty();
    505 
    506  unsigned i;
    507  for (i = 0; i < g_NumHashers; i++)
    508  {
    509    const CHasherInfo &codec = *g_Hashers[i];
    510    if (codec.Id == methodId)
    511    {
    512      hasher = codec.CreateHasher();
    513      name = codec.Name;
    514      break;
    515    }
    516  }
    517 
    518  #ifdef EXTERNAL_CODECS
    519 
    520  CHECK_GLOBAL_CODECS
    521 
    522  if (!hasher && __externalCodecs)
    523    for (i = 0; i < __externalCodecs->Hashers.Size(); i++)
    524    {
    525      const CHasherInfoEx &codec = __externalCodecs->Hashers[i];
    526      if (codec.Id == methodId)
    527      {
    528        name = codec.Name;
    529        return __externalCodecs->GetHashers->CreateHasher((UInt32)i, &hasher);
    530      }
    531    }
    532 
    533  #endif
    534 
    535  return S_OK;
    536 }