CpEpEngine.cpp
author Markus Schaber <markus@pep-security.net>
Tue, 03 May 2016 20:15:26 +0200
changeset 71 8d19e1c194f0
parent 70 000c4f33e0f8
child 74 f2531096699e
permissions -rw-r--r--
Fix com server registration via /Regserver
     1 // CpEpEngine.cpp : Implementation of CpEpEngine
     2 
     3 #include "stdafx.h"
     4 #include "CpEpEngine.h"
     5 
     6 using namespace std;
     7 using namespace pEp::utility;
     8 
     9 // CpEpEngine
    10 
    11 STDMETHODIMP CpEpEngine::InterfaceSupportsErrorInfo(REFIID riid)
    12 {
    13 	static const IID* const arr[] = 
    14 	{
    15 		&IID_IpEpEngine
    16 	};
    17 
    18 	for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
    19 	{
    20 		if (InlineIsEqualGUID(*arr[i],riid))
    21 			return S_OK;
    22 	}
    23 	return S_FALSE;
    24 }
    25 
    26 #define FAIL(msg) error(msg)
    27 
    28 STDMETHODIMP CpEpEngine::verbose_logging(VARIANT_BOOL enable)
    29 {
    30     verbose_mode = enable != VARIANT_FALSE;
    31     return S_OK;
    32 }
    33 
    34 STDMETHODIMP CpEpEngine::passive_mode(VARIANT_BOOL enable)
    35 {
    36     ::config_passive_mode(get_session(), enable != VARIANT_FALSE);
    37     return S_OK;
    38 }
    39 
    40 STDMETHODIMP CpEpEngine::unencrypted_subject(VARIANT_BOOL enable)
    41 {
    42     ::config_unencrypted_subject(get_session(), enable != VARIANT_FALSE);
    43     return S_OK;
    44 }
    45 
    46 STDMETHODIMP CpEpEngine::log(BSTR title, BSTR entity, BSTR description, BSTR comment)
    47 {
    48     string _title;
    49     string _entity;
    50     string _description;
    51     string _comment;
    52     HRESULT result = S_OK;
    53 
    54     assert(title);
    55     if (title)
    56         _title = utf8_string(title);
    57     else
    58         result = E_INVALIDARG;
    59 
    60     assert(entity);
    61     if (entity)
    62         _entity = utf8_string(entity);
    63     else
    64         result = E_INVALIDARG;
    65 
    66     if (description)
    67         _description = utf8_string(description);
    68 
    69     if (comment)
    70         _comment = utf8_string(comment);
    71 
    72     if (result != S_OK)
    73         return result;
    74 
    75     PEP_STATUS _status = ::log_event(get_session(), _title.c_str(), _entity.c_str(), _description.c_str(), _comment.c_str());
    76     assert(_status == PEP_STATUS_OK);
    77     if (_status != PEP_STATUS_OK)
    78         return FAIL(L"log_event");
    79     else
    80         return S_OK;
    81 }
    82 
    83 
    84 STDMETHODIMP CpEpEngine::decrypt(BSTR ctext, BSTR * ptext, LPSAFEARRAY * key_list, pEp_STATUS * status)
    85 {
    86     assert(ctext);
    87     assert(ptext);
    88     assert(key_list);
    89     assert(status);
    90 
    91     if (ctext == NULL || ptext == NULL || key_list == NULL || status == NULL) {
    92         if (ptext)
    93             *ptext = NULL;
    94         if (key_list)
    95             *key_list = NULL;
    96         if (status)
    97             *status = pEp_UNENCRYPTED;
    98         return E_INVALIDARG;
    99     }
   100 
   101     string _ctext = utf8_string(ctext);
   102 
   103     char *_ptext = NULL;
   104     size_t _psize = 0;
   105     ::stringlist_t *_keylist = NULL;
   106     PEP_STATUS _status;
   107 
   108     _status = ::decrypt_and_verify(get_session(), _ctext.c_str(), _ctext.size(), &_ptext, &_psize, &_keylist);
   109     assert(_status != PEP_OUT_OF_MEMORY);
   110     if (_status == PEP_OUT_OF_MEMORY)
   111         return E_OUTOFMEMORY;
   112 
   113     *status = (pEp_STATUS) _status;
   114     if (_ptext == NULL) {
   115         if (_keylist) {
   116             string msg;
   117             if (_keylist->value[0] != 0) {
   118                 msg = _keylist->value;
   119             }
   120             else {
   121                 for (::stringlist_t *s = _keylist->next; s != NULL; s = s->next) {
   122                     if (s->value) {
   123                         msg += s->value;
   124                         msg += ";";
   125                     }
   126                 }
   127             }
   128             ::free_stringlist(_keylist);
   129 
   130             return FAIL(utf16_bstr(msg));
   131         }
   132         else
   133             return FAIL(L"cannot decrypt");
   134     }
   135 
   136     *ptext = utf16_bstr(_ptext);
   137     pEp_free(_ptext);
   138 
   139     if (_keylist && _keylist->value)
   140         *key_list = string_array(_keylist);
   141     else
   142         *key_list = NULL;
   143     ::free_stringlist(_keylist);
   144 
   145     return S_OK;
   146 }
   147 
   148 STDMETHODIMP CpEpEngine::decrypt_b(BSTR ctext, LPSAFEARRAY * ptext, LPSAFEARRAY * key_list, pEp_STATUS * status)
   149 {
   150     assert(ctext);
   151     assert(ptext);
   152     assert(key_list);
   153     assert(status);
   154 
   155     if (ctext == NULL || ptext == NULL || key_list == NULL || status == NULL) {
   156         if (ptext)
   157             *ptext = NULL;
   158         if (key_list)
   159             *key_list = NULL;
   160         if (status)
   161             *status = pEp_UNENCRYPTED;
   162         return E_INVALIDARG;
   163     }
   164 
   165     // Welcome to Windoze string hell!
   166 
   167     char *_ctext = NULL;
   168     _bstr_t bstr_ctext(ctext, true);
   169     int w_csize = bstr_ctext.length() + 1;
   170     int _csize = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, (wchar_t *) bstr_ctext, w_csize, NULL, 0, NULL, NULL);
   171     if (_csize) {
   172         _ctext = new char[_csize];
   173         WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, (wchar_t *) bstr_ctext, w_csize, _ctext, _csize, NULL, NULL);
   174     }
   175 
   176     char *_ptext = NULL;
   177     size_t _psize = 0;
   178     ::stringlist_t *_keylist = NULL;
   179     PEP_STATUS _status;
   180 
   181     _status = ::decrypt_and_verify(get_session(), _ctext, _csize, &_ptext, &_psize, &_keylist);
   182     assert(_status != PEP_OUT_OF_MEMORY);
   183     delete[] _ctext;
   184     if (_status == PEP_OUT_OF_MEMORY) {
   185         ::free_stringlist(_keylist);
   186         return E_OUTOFMEMORY;
   187     }
   188     *status = (pEp_STATUS) _status;
   189 
   190     if (_ptext == NULL) {
   191         ::free_stringlist(_keylist);
   192         return FAIL(L"decrypt_and_verify");
   193     }
   194 
   195     CComSafeArray<BYTE> sa_ptext;
   196 
   197     HRESULT _result = sa_ptext.Create(_psize, 0);
   198     assert(_result == S_OK);
   199     if (_result == E_OUTOFMEMORY) {
   200         pEp_free(_ptext);
   201         ::free_stringlist(_keylist);
   202         return E_OUTOFMEMORY;
   203     }
   204     else if (_result != S_OK) {
   205         pEp_free(_ptext);
   206         ::free_stringlist(_keylist);
   207         return FAIL(L"CComSafeArray<BYTE>::Create");
   208     }
   209 
   210     memcpy(sa_ptext.m_psa->pvData, _ptext, _psize);
   211     *ptext = sa_ptext.Detach();
   212     ::pEp_free(_ptext);
   213 
   214     if (_keylist && _keylist->value)
   215         *key_list = string_array(_keylist);
   216     else
   217         *key_list = NULL;
   218     ::free_stringlist(_keylist);
   219 
   220     return S_OK;
   221 }
   222 
   223 STDMETHODIMP CpEpEngine::verify(BSTR text, BSTR signature, LPSAFEARRAY * key_list, pEp_STATUS * verify_status)
   224 {
   225     assert(text);
   226     assert(signature);
   227     assert(key_list);
   228 
   229     if (text == NULL || signature == NULL || key_list == NULL)
   230         return E_INVALIDARG;
   231 
   232     string _text = utf8_string(text);
   233     string _signature = utf8_string(signature);
   234 
   235     ::stringlist_t *_keylist = NULL;
   236     PEP_STATUS _status;
   237     _status = ::verify_text(get_session(), _text.c_str(), _text.size(), _signature.c_str(), _signature.size(), &_keylist);
   238     assert(_status != PEP_OUT_OF_MEMORY);
   239     if (_status == PEP_OUT_OF_MEMORY)
   240         return E_OUTOFMEMORY;
   241     if (_status == PEP_DECRYPT_WRONG_FORMAT || _status == PEP_UNKNOWN_ERROR)
   242         return FAIL(L"verify_text");
   243 
   244     *verify_status = (pEp_STATUS) _status;
   245 
   246     if (_keylist && _keylist->value)
   247         *key_list = string_array(_keylist);
   248     else
   249         *key_list = NULL;
   250     ::free_stringlist(_keylist);
   251 
   252     return S_OK;
   253 }
   254 
   255 STDMETHODIMP CpEpEngine::encrypt(SAFEARRAY * key_list, BSTR ptext, BSTR * ctext, pEp_STATUS * status)
   256 {
   257     assert(key_list);
   258     assert(ptext);
   259     assert(ctext);
   260     assert(status);
   261 
   262     if (ctext == NULL || ptext == NULL || key_list == NULL || status == NULL) {
   263         if (ctext)
   264             *ctext = NULL;
   265         if (status)
   266             *status = pEp_UNKNOWN_ERROR;
   267         return E_INVALIDARG;
   268     }
   269 
   270     HRESULT result = S_OK;
   271 
   272     ::stringlist_t *_keylist = new_stringlist(key_list);
   273     string _ptext = utf8_string(ptext);
   274 
   275     char *_ctext = NULL;
   276     size_t _csize = 0;
   277     PEP_STATUS _status;
   278 
   279     _status = ::encrypt_and_sign(get_session(), _keylist, _ptext.c_str(), _ptext.size(), &_ctext, &_csize);
   280 
   281     assert(_status != PEP_OUT_OF_MEMORY);
   282     ::free_stringlist(_keylist);
   283     if (_status == PEP_OUT_OF_MEMORY)
   284         return E_OUTOFMEMORY;
   285     *status = (pEp_STATUS) _status;
   286 
   287     if (_ctext == NULL)
   288         return FAIL(L"encrypt_and_sign");
   289 
   290     *ctext = utf16_bstr(_ctext);
   291     pEp_free(_ctext);
   292 
   293     return S_OK;
   294 }
   295 
   296 STDMETHODIMP CpEpEngine::encrypt_b(SAFEARRAY * key_list, SAFEARRAY * ptext, BSTR * ctext, pEp_STATUS * status)
   297 {
   298     assert(key_list);
   299     assert(ptext);
   300     assert(ctext);
   301     assert(status);
   302 
   303     if (ctext == NULL || ptext == NULL || key_list == NULL || status == NULL) {
   304         if (ctext)
   305             *ctext = NULL;
   306         if (status)
   307             *status = pEp_UNKNOWN_ERROR;
   308         return E_INVALIDARG;
   309     }
   310 
   311     HRESULT result = S_OK;
   312 
   313     ::stringlist_t *_keylist = new_stringlist(key_list);
   314 
   315     char *_ctext = NULL;
   316     size_t _csize = 0;
   317     ::PEP_STATUS _status;
   318 
   319     _status = ::encrypt_and_sign(get_session(), _keylist, (const char *) ptext->pvData, ptext->rgsabound[0].cElements, &_ctext, &_csize);
   320     assert(_status != PEP_OUT_OF_MEMORY);
   321     ::free_stringlist(_keylist);
   322     if (_status == PEP_OUT_OF_MEMORY)
   323         return E_OUTOFMEMORY;
   324     *status = (pEp_STATUS) _status;
   325 
   326     if (_ctext == NULL)
   327         return FAIL(L"encrypt_and_sign");
   328 
   329     *status = (pEp_STATUS) _status;
   330     wchar_t *w_ctext = NULL;
   331     int w_csize = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, _ctext, _csize, NULL, 0);
   332     if (w_csize) {
   333         w_ctext = new wchar_t[w_csize + 1];
   334         MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, _ctext, _csize, w_ctext, w_csize);
   335         w_ctext[w_csize] = 0; // this is for debugging; Visual Studio will crash without that if you're unlucky
   336     }
   337     *ctext = ::SysAllocStringLen(w_ctext, w_csize);
   338     assert(ctext);
   339     delete[] w_ctext;
   340     pEp_free(_ctext);
   341     if (ctext == NULL)
   342         return E_OUTOFMEMORY;
   343 
   344     return S_OK;
   345 }
   346 
   347 STDMETHODIMP CpEpEngine::trustword(LONG value, BSTR lang, BSTR * word)
   348 {
   349     assert(value >= 0 && value <= 65535);
   350     assert(word);
   351 
   352     HRESULT result = S_OK;
   353 
   354     uint16_t _value = 0;
   355     if (value < 0 || value > 65535)
   356         result = E_INVALIDARG;
   357     else
   358         _value = (uint16_t) value;
   359 
   360     string _lang = "en";
   361     if (lang) {
   362         _lang = utf8_string(lang);
   363         if (_lang.length() != 2)
   364             result = E_INVALIDARG;
   365     }
   366 
   367     if (word == NULL)
   368         result = E_INVALIDARG;
   369 
   370     if (result != S_OK)
   371         return result;
   372 
   373     char *_word = NULL;
   374     size_t _wsize = 0;
   375 
   376     PEP_STATUS status = ::trustword(get_session(), _value, _lang.c_str(), &_word, &_wsize);
   377     assert(status != PEP_OUT_OF_MEMORY);
   378     if (status == PEP_OUT_OF_MEMORY)
   379         return E_OUTOFMEMORY;
   380 
   381     if (_word == NULL) {
   382         *word = NULL;
   383         return FAIL(L"trustword");
   384     }
   385     else {
   386         *word = utf16_bstr(_word);
   387         pEp_free(_word);
   388         return S_OK;
   389     }
   390 }
   391 
   392 STDMETHODIMP CpEpEngine::trustwords(BSTR fpr, BSTR lang, LONG max_words, BSTR * words)
   393 {
   394     assert(fpr);
   395     assert(max_words >= 0);
   396     assert(words);
   397 
   398     HRESULT result = S_OK;
   399 
   400     string _fpr;
   401     if (fpr)
   402         _fpr = utf8_string(fpr);
   403     else
   404         result = E_INVALIDARG;
   405 
   406     string _lang;
   407     if (lang) {
   408         _lang = utf8_string(lang);
   409         if (_lang.length()) {
   410             if (_lang.length() != 2)
   411                 result = E_INVALIDARG;
   412         }
   413         else
   414             _lang = "en";
   415     }
   416     else
   417         _lang = "en";
   418 
   419     if (max_words < 0)
   420         result = E_INVALIDARG;
   421 
   422     if (words == NULL)
   423         result = E_INVALIDARG;
   424 
   425     if (result != S_OK)
   426         return result;
   427 
   428     char *_words = NULL;
   429     size_t _wsize = 0;
   430 
   431     PEP_STATUS status = ::trustwords(get_session(), _fpr.c_str(), _lang.c_str(), &_words, &_wsize, max_words);
   432     assert(status != PEP_OUT_OF_MEMORY);
   433     if (status == PEP_OUT_OF_MEMORY)
   434         return E_OUTOFMEMORY;
   435 
   436     if (_words == NULL) {
   437         *words = NULL;
   438         return FAIL(L"trustwords");
   439     }
   440     else {
   441         *words = utf16_bstr(_words);
   442         pEp_free(_words);
   443         return S_OK;
   444     }
   445 }
   446 
   447 STDMETHODIMP CpEpEngine::get_crashdump_log(LONG maxlines, BSTR * log)
   448 {
   449     assert(maxlines >= 0);
   450     assert(log);
   451 
   452     if (!(maxlines >= 0 && log))
   453         return E_INVALIDARG;
   454 
   455     char *_log;
   456     PEP_STATUS status = ::get_crashdump_log(get_session(), (int) maxlines, &_log);
   457     assert(status == PEP_STATUS_OK);
   458     if (status == PEP_OUT_OF_MEMORY)
   459         return E_OUTOFMEMORY;
   460     if (status != PEP_STATUS_OK || _log == NULL)
   461         return FAIL(L"get_crashdump_log");
   462 
   463     *log = utf16_bstr(_log);
   464     pEp_free(_log);
   465     return S_OK;
   466 }
   467 
   468 STDMETHODIMP CpEpEngine::get_languagelist(BSTR * languages)
   469 {
   470     assert(languages);
   471 
   472     if (!languages)
   473         return E_INVALIDARG;
   474 
   475     char *_languages;
   476     PEP_STATUS status = ::get_languagelist(get_session(), &_languages);
   477     assert(status == PEP_STATUS_OK);
   478     if (status == PEP_OUT_OF_MEMORY)
   479         return E_OUTOFMEMORY;
   480     if (status != PEP_STATUS_OK || _languages == NULL)
   481         return FAIL(L"get_languagelist");
   482 
   483     *languages = utf16_bstr(_languages);
   484     pEp_free(_languages);
   485     return S_OK;
   486 }
   487 
   488 STDMETHODIMP CpEpEngine::get_phrase(BSTR lang, LONG phrase_id, BSTR * phrase)
   489 {
   490     assert(lang && phrase_id >= 0 && phrase);
   491 
   492     if (!(lang && phrase_id >= 0 && phrase))
   493         return E_INVALIDARG;
   494 
   495     string _lang = utf8_string(lang);
   496     assert(_lang.length() == 2);
   497     if (_lang.length() != 2)
   498         return E_INVALIDARG;
   499 
   500     char *_phrase;
   501     PEP_STATUS status = ::get_phrase(get_session(), _lang.c_str(), (int) phrase_id, &_phrase);
   502     assert(status == PEP_STATUS_OK);
   503     if (status == PEP_OUT_OF_MEMORY)
   504         return E_OUTOFMEMORY;
   505     if (status != PEP_STATUS_OK || _phrase == NULL)
   506         return FAIL(L"get_phrase");
   507 
   508     *phrase = utf16_bstr(_phrase);
   509     pEp_free(_phrase);
   510     return S_OK;
   511 }
   512 
   513 STDMETHODIMP CpEpEngine::get_identity(BSTR address, BSTR user_id, pEp_identity_s * ident)
   514 {
   515     assert(address);
   516     assert(user_id);
   517     assert(ident);
   518 
   519     if (address == NULL)
   520         return E_INVALIDARG;
   521     if (user_id == NULL)
   522         return E_INVALIDARG;
   523     if (ident == NULL)
   524         return E_INVALIDARG;
   525 
   526     string _address = utf8_string(address);
   527     string _user_id = utf8_string(user_id);
   528 
   529     ::pEp_identity *_ident = NULL;
   530     PEP_STATUS status = ::get_identity(get_session(), _address.c_str(), _user_id.c_str(), &_ident);
   531     assert(status != PEP_OUT_OF_MEMORY);
   532     if (status == PEP_OUT_OF_MEMORY)
   533         return E_OUTOFMEMORY;
   534 
   535     if (_ident == NULL) {
   536         return FAIL(L"get_identity");
   537     }
   538 
   539     copy_identity(ident, _ident);
   540     ::free_identity(_ident);
   541 
   542     return S_OK;
   543 }
   544 
   545 STDMETHODIMP CpEpEngine::set_identity(pEp_identity_s * ident)
   546 {
   547     assert(ident);
   548     assert(ident->address);
   549     assert(ident->fpr);
   550     assert(ident->username);
   551     assert(ident->user_id);
   552 
   553     if (ident == NULL || ident->address == NULL || ident->fpr == NULL
   554         || ident->username == NULL || ident->user_id == NULL)
   555         return E_INVALIDARG;
   556 
   557     ::pEp_identity *_ident = new_identity(ident);
   558     ::PEP_STATUS status = ::set_identity(get_session(), _ident);
   559     ::free_identity(_ident);
   560 
   561     if (status != ::PEP_STATUS_OK)
   562         return FAIL(L"set_identity");
   563     else
   564         return S_OK;
   565 }
   566 
   567 STDMETHODIMP CpEpEngine::generate_keypair(pEp_identity_s * ident, BSTR * fpr)
   568 {
   569     assert(ident);
   570     assert(ident->address);
   571     assert(ident->username);
   572     assert(fpr);
   573 
   574     if (ident == NULL || ident->address == NULL || ident->username == NULL || fpr == NULL)
   575         return E_INVALIDARG;
   576 
   577     ::pEp_identity *_ident = new_identity(ident);
   578     ::pEp_free(_ident->fpr);
   579     _ident->fpr = NULL;
   580 
   581     ::PEP_STATUS status = ::generate_keypair(get_session(), _ident);
   582     assert(status != ::PEP_OUT_OF_MEMORY);
   583     if (status == ::PEP_OUT_OF_MEMORY) {
   584         ::free_identity(_ident);
   585         return E_OUTOFMEMORY;
   586     }
   587 
   588     if (_ident->fpr)
   589         *fpr = utf16_bstr(_ident->fpr);
   590 
   591     ::free_identity(_ident);
   592 
   593     if (status != ::PEP_STATUS_OK)
   594         return FAIL(L"generate_keypair");
   595 
   596     return S_OK;
   597 }
   598 
   599 STDMETHODIMP CpEpEngine::delete_keypair(BSTR fpr)
   600 {
   601     assert(fpr);
   602 
   603     if (fpr == NULL)
   604         return E_INVALIDARG;
   605 
   606     string _fpr = utf8_string(fpr);
   607 
   608     ::PEP_STATUS status = ::delete_keypair(get_session(), _fpr.c_str());
   609     assert(status != PEP_OUT_OF_MEMORY);
   610     if (status == PEP_OUT_OF_MEMORY)
   611         return E_OUTOFMEMORY;
   612 
   613     if (status != ::PEP_STATUS_OK)
   614         return FAIL(L"delete_keypair");
   615     else
   616         return S_OK;
   617 }
   618 
   619 STDMETHODIMP CpEpEngine::import_key(BSTR key_data)
   620 {
   621     assert(key_data);
   622 
   623     if (key_data == NULL)
   624         return E_INVALIDARG;
   625 
   626     string _key_data = utf8_string(key_data);
   627 
   628     PEP_STATUS status = ::import_key(get_session(), _key_data.c_str(), _key_data.length());
   629     assert(status != PEP_OUT_OF_MEMORY);
   630     if (status == PEP_OUT_OF_MEMORY)
   631         return E_OUTOFMEMORY;
   632 
   633     if (status != pEp_STATUS_OK)
   634         return FAIL(L"import_key");
   635     else
   636         return S_OK;
   637 }
   638 
   639 STDMETHODIMP CpEpEngine::import_key_b(SAFEARRAY * key_data)
   640 {
   641     assert(key_data);
   642 
   643     if (key_data == NULL)
   644         return E_INVALIDARG;
   645 
   646     ::PEP_STATUS status = ::import_key(get_session(), (const char *) key_data->pvData, key_data->rgsabound[0].cElements);
   647     assert(status != ::PEP_OUT_OF_MEMORY);
   648     if (status == ::PEP_OUT_OF_MEMORY)
   649         return E_OUTOFMEMORY;
   650 
   651     if (status != ::PEP_STATUS_OK)
   652         return FAIL(L"import_key");
   653     else
   654         return S_OK;
   655 }
   656 
   657 STDMETHODIMP CpEpEngine::export_key(BSTR fpr, BSTR * key_data)
   658 {
   659     assert(fpr);
   660     assert(key_data);
   661 
   662     if (fpr == NULL || key_data == NULL)
   663         return E_INVALIDARG;
   664 
   665     string _fpr = utf8_string(fpr);
   666     char *_key_data = NULL;
   667     size_t _size = 0;
   668 
   669     ::PEP_STATUS status = ::export_key(get_session(), _fpr.c_str(), &_key_data, &_size);
   670     assert(status != ::PEP_OUT_OF_MEMORY);
   671     if (status == ::PEP_OUT_OF_MEMORY)
   672         return E_OUTOFMEMORY;
   673 
   674     if (status != ::PEP_STATUS_OK)
   675         return FAIL(L"export_key");
   676 
   677     _bstr_t b_key_data(utf16_string(_key_data).c_str());
   678     pEp_free(_key_data);
   679     *key_data = b_key_data.Detach();
   680 
   681     return S_OK;
   682 }
   683 
   684 STDMETHODIMP CpEpEngine::recv_key(BSTR pattern)
   685 {
   686     assert(pattern);
   687 
   688     if (pattern == NULL)
   689         return E_INVALIDARG;
   690 
   691     string _pattern = utf8_string(pattern);
   692 
   693     PEP_STATUS status = ::recv_key(get_session(), _pattern.c_str());
   694     assert(status != PEP_OUT_OF_MEMORY);
   695     if (status == PEP_OUT_OF_MEMORY)
   696         return E_OUTOFMEMORY;
   697 
   698     if (status != ::PEP_STATUS_OK)
   699         return FAIL(L"recv_key");
   700     else
   701         return S_OK;
   702 }
   703 
   704 STDMETHODIMP CpEpEngine::find_keys(BSTR pattern, LPSAFEARRAY * key_list)
   705 {
   706     assert(pattern);
   707     assert(key_list);
   708 
   709     if (pattern == NULL || key_list == NULL)
   710         return E_INVALIDARG;
   711 
   712     string _pattern = utf8_string(pattern);
   713     ::stringlist_t *_keylist = NULL;
   714 
   715     PEP_STATUS status = ::find_keys(get_session(), _pattern.c_str(), &_keylist);
   716     assert(status != PEP_OUT_OF_MEMORY);
   717     if (status == PEP_OUT_OF_MEMORY)
   718         return E_OUTOFMEMORY;
   719 
   720     if (status != ::PEP_STATUS_OK)
   721         return FAIL(L"find_keys");
   722 
   723     if (_keylist && _keylist->value) {
   724         *key_list = string_array(_keylist);
   725     }
   726     else {
   727         ::free_stringlist(_keylist);
   728         return FAIL(L"find_keys: no keys found");
   729     }
   730 
   731     ::free_stringlist(_keylist);
   732     return S_OK;
   733 }
   734 
   735 STDMETHODIMP CpEpEngine::send_key(BSTR pattern)
   736 {
   737     assert(pattern);
   738 
   739     if (pattern == NULL)
   740         return E_INVALIDARG;
   741 
   742     string _pattern = utf8_string(pattern);
   743 
   744     ::PEP_STATUS status = ::send_key(get_session(), _pattern.c_str());
   745 
   746     if (status != ::PEP_STATUS_OK)
   747         return FAIL(L"send_key");
   748     else
   749         return S_OK;
   750 }
   751 
   752 STDMETHODIMP CpEpEngine::start_keyserver_lookup()
   753 {
   754     if (identity_queue.load())
   755         return S_OK;
   756 
   757     identity_queue.store(new identity_queue_t());
   758     keymanagement_thread = new thread(::do_keymanagement, retrieve_next_identity, (void *) identity_queue.load());
   759     
   760     return S_OK;
   761 }
   762 
   763 STDMETHODIMP CpEpEngine::stop_keyserver_lookup()
   764 {
   765     if (identity_queue.load() == NULL)
   766         return S_OK;
   767 
   768     identity_queue_t *_iq = identity_queue.load();
   769     identity_queue.store(NULL);
   770 
   771     pEp_identity_cpp shutdown;
   772     _iq->push_front(shutdown);
   773 
   774     keymanagement_thread->join();
   775     delete keymanagement_thread;
   776     keymanagement_thread = NULL;
   777 
   778     delete _iq;
   779 
   780     return S_OK;
   781 }
   782 
   783 STDMETHODIMP CpEpEngine::examine_identity(pEp_identity_s * ident)
   784 {
   785     assert(ident);
   786     if (ident == NULL)
   787         return E_INVALIDARG;
   788 
   789     if (identity_queue.load() == NULL) {
   790         try {
   791             identity_queue.load()->push_back(ident);
   792         }
   793         catch (bad_alloc) {
   794             return E_OUTOFMEMORY;
   795         }
   796     }
   797 
   798     return S_OK;
   799 }
   800 
   801 STDMETHODIMP CpEpEngine::myself(struct pEp_identity_s *ident, struct pEp_identity_s *result)
   802 {
   803     assert(ident);
   804     assert(result);
   805 
   806     if (ident == NULL || result == NULL)
   807         return E_INVALIDARG;
   808 
   809     ::pEp_identity *_ident = new_identity(ident);
   810     assert(_ident);
   811     if (_ident == NULL)
   812         return E_OUTOFMEMORY;
   813 
   814     PEP_STATUS status = ::myself(get_session(), _ident);
   815 
   816     if (status == PEP_STATUS_OK) {
   817         assert(_ident->fpr);
   818         copy_identity(result, _ident);
   819         ::free_identity(_ident);
   820         return S_OK;
   821     }
   822     else {
   823         ::free_identity(_ident);
   824         if (status == PEP_OUT_OF_MEMORY)
   825             return E_OUTOFMEMORY;
   826         else
   827             return FAIL(L"myself");
   828     }
   829 }
   830 
   831 STDMETHODIMP CpEpEngine::update_identity(struct pEp_identity_s *ident, struct pEp_identity_s *result)
   832 {
   833     assert(ident);
   834     assert(result);
   835 
   836     if (ident == NULL || result == NULL)
   837         return E_INVALIDARG;
   838 
   839     ::pEp_identity *_ident = new_identity(ident);
   840     assert(_ident);
   841     if (_ident == NULL)
   842         return E_OUTOFMEMORY;
   843 
   844     PEP_STATUS status = ::update_identity(get_session(), _ident);
   845 
   846     if (status == PEP_STATUS_OK) {
   847         assert(_ident->fpr);
   848         copy_identity(result, _ident);
   849         ::free_identity(_ident);
   850         return S_OK;
   851     }
   852     else {
   853         ::free_identity(_ident);
   854         if (status == PEP_OUT_OF_MEMORY)
   855             return E_OUTOFMEMORY;
   856         else
   857             return FAIL(L"update_identity");
   858     }
   859 }
   860 
   861 STDMETHODIMP CpEpEngine::key_compromized(struct pEp_identity_s *ident)
   862 {
   863     ::pEp_identity *_ident;
   864 
   865     assert(ident);
   866 
   867     try {
   868         _ident = new_identity(ident);
   869     }
   870     catch (bad_alloc&) {
   871         return E_OUTOFMEMORY;
   872     }
   873     catch (exception&) {
   874         return E_FAIL;
   875     }
   876 
   877     PEP_STATUS status = ::key_compromized(get_session(), _ident);
   878     free_identity(_ident);
   879 
   880     if (status == PEP_OUT_OF_MEMORY)
   881         return E_OUTOFMEMORY;
   882 
   883     if (status == PEP_KEY_NOT_FOUND)
   884         return FAIL(L"key not found");
   885 
   886     if (status != ::PEP_STATUS_OK)
   887         return FAIL(L"cannot revoke compromized key");
   888 
   889     return S_OK;
   890 }
   891 
   892 STDMETHODIMP CpEpEngine::key_reset_trust(struct pEp_identity_s *ident)
   893 {
   894     ::pEp_identity *_ident;
   895 
   896     assert(ident);
   897 
   898     try {
   899         _ident = new_identity(ident);
   900     }
   901     catch (bad_alloc&) {
   902         return E_OUTOFMEMORY;
   903     }
   904     catch (exception&) {
   905         return E_FAIL;
   906     }
   907 
   908     PEP_STATUS status = ::key_reset_trust(get_session(), _ident);
   909     free_identity(_ident);
   910 
   911     if (status == PEP_OUT_OF_MEMORY)
   912         return E_OUTOFMEMORY;
   913 
   914     if (status == PEP_KEY_NOT_FOUND)
   915         return FAIL(L"key not found");
   916 
   917     if (status != ::PEP_STATUS_OK)
   918         return FAIL(L"cannot reset trust");
   919 
   920     return S_OK;
   921 }
   922 
   923 int CpEpEngine::examine_identity(pEp_identity *ident, void *management)
   924 {
   925     assert(ident);
   926     assert(management);
   927     if (!(ident && management))
   928         return -1;
   929 
   930     CpEpEngine *me = (CpEpEngine *) management;
   931 
   932     if (me->identity_queue.load() == NULL)
   933         return 0;
   934 
   935     try {
   936         me->identity_queue.load()->push_back(ident);
   937     }
   938     catch (exception&) {
   939         return -1;
   940     }
   941 
   942     return 0;
   943 }
   944 
   945 ::pEp_identity * CpEpEngine::retrieve_next_identity(void *management)
   946 {
   947     assert(management);
   948     identity_queue_t *iq = (identity_queue_t *) management;
   949 
   950     do /* poll queue */ {
   951         if (iq->size())
   952             break;
   953         ::Sleep(100);
   954     } while (true);
   955 
   956     ::pEp_identity *_ident;
   957     pEp_identity_cpp& ident = iq->front();
   958 
   959     if (ident.address.size() == 0)
   960         return NULL;
   961 
   962     _ident = ident.to_pEp_identity();
   963     iq->pop_front();
   964 
   965     return _ident;
   966 }
   967 
   968 STDMETHODIMP CpEpEngine::blacklist_add(BSTR fpr)
   969 {
   970     assert(fpr);
   971 
   972     string _fpr = utf8_string(fpr);
   973     PEP_STATUS status = ::blacklist_add(get_session(), _fpr.c_str());
   974     assert(status == PEP_STATUS_OK);
   975     if (status != PEP_STATUS_OK)
   976         return FAIL(L"blacklist_add failed in pEp engine");
   977 
   978     return S_OK;
   979 }
   980 
   981 STDMETHODIMP CpEpEngine::blacklist_delete(BSTR fpr)
   982 {
   983     assert(fpr);
   984 
   985     string _fpr = utf8_string(fpr);
   986     PEP_STATUS status = ::blacklist_delete(get_session(), _fpr.c_str());
   987     assert(status == PEP_STATUS_OK);
   988     if (status != PEP_STATUS_OK)
   989         return FAIL(L"blacklist_delete failed in pEp engine");
   990 
   991     return S_OK;
   992 }
   993 
   994 STDMETHODIMP CpEpEngine::blacklist_is_listed(BSTR fpr, VARIANT_BOOL *listed)
   995 {
   996     assert(fpr);
   997     assert(listed);
   998 
   999     string _fpr = utf8_string(fpr);
  1000     bool result;
  1001     PEP_STATUS status = ::blacklist_is_listed(get_session(), _fpr.c_str(), &result);
  1002     assert(status == PEP_STATUS_OK);
  1003     if (status != PEP_STATUS_OK)
  1004         return FAIL(L"blacklist_is_listed failed in pEp engine");
  1005 
  1006     *listed = result ? VARIANT_TRUE : VARIANT_FALSE;
  1007     return S_OK;
  1008 }
  1009 
  1010 STDMETHODIMP CpEpEngine::blacklist_retrieve(SAFEARRAY **blacklist)
  1011 {
  1012     assert(blacklist);
  1013 
  1014     ::stringlist_t *_blacklist = NULL;
  1015     PEP_STATUS status = ::blacklist_retrieve(get_session(), &_blacklist);
  1016     assert(status == PEP_STATUS_OK);
  1017     if (status != PEP_STATUS_OK)
  1018         return FAIL(L"blacklist_retrieve failed in pEp engine");
  1019     assert(_blacklist);
  1020 
  1021     *blacklist = string_array(_blacklist);
  1022     return S_OK;
  1023 }
  1024 
  1025 HRESULT CpEpEngine::error(_bstr_t msg)
  1026 {
  1027     _bstr_t helpFile = L"";
  1028     _bstr_t source = L"pEp COM Adapter";
  1029 
  1030     ICreateErrorInfo *cei;
  1031     if (SUCCEEDED(CreateErrorInfo(&cei))) {
  1032         cei->SetDescription(msg);
  1033         cei->SetGUID(__uuidof(IpEpEngine));
  1034         cei->SetHelpContext(0);
  1035         cei->SetHelpFile(helpFile);
  1036         cei->SetSource(source);
  1037 
  1038         IErrorInfo *errinfo;
  1039         if (SUCCEEDED(cei->QueryInterface(IID_IErrorInfo, (LPVOID FAR*) &errinfo))) {
  1040             SetErrorInfo(0, errinfo);
  1041             errinfo->Release();
  1042         }
  1043         cei->Release();
  1044     }
  1045     return E_FAIL;
  1046 }
  1047 
  1048 STDMETHODIMP CpEpEngine::encrypt_message(text_message * src, text_message * dst, SAFEARRAY * extra)
  1049 {
  1050     assert(src);
  1051     assert(dst);
  1052 
  1053     ::message *_src = text_message_to_C(src);
  1054     ::message *msg_dst;
  1055     ::stringlist_t *_extra = new_stringlist(extra);
  1056 
  1057     PEP_STATUS status = ::encrypt_message(get_session(), _src, _extra, &msg_dst, PEP_enc_pieces);
  1058     ::free_stringlist(_extra);
  1059 
  1060     if (status == PEP_STATUS_OK)
  1061         text_message_from_C(dst, msg_dst);
  1062     else
  1063         text_message_from_C(dst, _src);
  1064 
  1065     ::free_message(msg_dst);
  1066     ::free_message(_src);
  1067 
  1068     if (status == PEP_OUT_OF_MEMORY)
  1069         return E_OUTOFMEMORY;
  1070 
  1071     return S_OK;
  1072 }
  1073 
  1074 STDMETHODIMP CpEpEngine::decrypt_message(text_message * src, text_message * dst, SAFEARRAY ** keylist, pEp_color *rating)
  1075 {
  1076     assert(src);
  1077     assert(dst);
  1078     assert(keylist);
  1079     assert(rating);
  1080 
  1081     *keylist = NULL;
  1082     *rating = pEp_rating_undefined;
  1083 
  1084     ::message *_src = text_message_to_C(src);
  1085     ::message *msg_dst = NULL;
  1086     ::stringlist_t *_keylist;
  1087     ::PEP_color _rating;
  1088 
  1089     PEP_STATUS status = ::decrypt_message(get_session(), _src, &msg_dst, &_keylist, &_rating);
  1090 
  1091     if (msg_dst)
  1092         text_message_from_C(dst, msg_dst);
  1093 
  1094     ::free_message(_src);
  1095     ::free_message(msg_dst);
  1096 
  1097     if (_keylist) {
  1098         *keylist = string_array(_keylist);
  1099         free_stringlist(_keylist);
  1100     }
  1101 
  1102     *rating = (pEp_color) _rating;
  1103 
  1104     return S_OK;
  1105 }
  1106 
  1107 STDMETHODIMP CpEpEngine::outgoing_message_color(text_message *msg, pEp_color * pVal)
  1108 {
  1109     assert(msg);
  1110     assert(pVal);
  1111 
  1112     ::message *_msg = text_message_to_C(msg);
  1113 
  1114     PEP_color _color;
  1115     PEP_STATUS status = ::outgoing_message_color(get_session(), _msg, &_color);
  1116     if (status != PEP_STATUS_OK)
  1117         return FAIL(L"cannot get message color");
  1118 
  1119     *pVal = (pEp_color) _color;
  1120     return S_OK;
  1121 }
  1122 
  1123 STDMETHODIMP CpEpEngine::identity_color(struct pEp_identity_s *ident, pEp_color * pVal)
  1124 {
  1125     ::pEp_identity *_ident;
  1126 
  1127     assert(ident);
  1128     assert(pVal);
  1129 
  1130     try {
  1131         _ident = new_identity(ident);
  1132     }
  1133     catch (bad_alloc&) {
  1134         return E_OUTOFMEMORY;
  1135     }
  1136     catch (exception&) {
  1137         return E_FAIL;
  1138     }
  1139 
  1140     PEP_color _color;
  1141     PEP_STATUS status = ::identity_color(get_session(), _ident, &_color);
  1142     free_identity(_ident);
  1143     if (status != PEP_STATUS_OK)
  1144         return FAIL(L"cannot get message color");
  1145 
  1146     *pVal = (pEp_color) _color;
  1147     return S_OK;
  1148 }
  1149 
  1150 STDMETHODIMP CpEpEngine::trust_personal_key(struct pEp_identity_s *ident, struct pEp_identity_s *result)
  1151 {
  1152     ::pEp_identity *_ident;
  1153 
  1154     assert(ident);
  1155     assert(result);
  1156 
  1157     try {
  1158         _ident = new_identity(ident);
  1159     }
  1160     catch (bad_alloc&) {
  1161         return E_OUTOFMEMORY;
  1162     }
  1163     catch (exception&) {
  1164         return E_FAIL;
  1165     }
  1166 
  1167     if (verbose_mode) {
  1168         stringstream ss;
  1169         ss << "trust_personal_key called with ";
  1170         ss << utf8_string(ident->address);
  1171         ss << L": ";
  1172         ss << ident->comm_type;
  1173         verbose(ss.str());
  1174     }
  1175 
  1176     PEP_STATUS status = ::trust_personal_key(get_session(), _ident);
  1177 
  1178     if (verbose_mode) {
  1179         stringstream ss;
  1180         ss << "result ";
  1181         ss << status;
  1182         ss << " for ";
  1183         ss << _ident->address;
  1184         ss << L": ";
  1185         ss << _ident->comm_type;
  1186         verbose(ss.str());
  1187     }
  1188 
  1189     if (status == PEP_STATUS_OK)
  1190         copy_identity(result, _ident);
  1191 
  1192     free_identity(_ident);
  1193     if (status == PEP_OUT_OF_MEMORY)
  1194         return E_OUTOFMEMORY;
  1195     else if (status != PEP_STATUS_OK)
  1196         return FAIL(L"failure while executing trust_personal_key()");
  1197 
  1198     return S_OK;
  1199 }