CpEpEngine.cpp
author Thomas
Thu, 14 Nov 2019 16:18:44 +0100
branchsync
changeset 373 5b10b2200c91
parent 371 228f5551c75b
child 374 ccc4c88f280e
permissions -rw-r--r--
Adjust HandshakeSignal enum to engine changes
vb@282
     1
// CpEpEngine.cpp : Implementation of CpEpEngine
markus@280
     2
vb@282
     3
#include "stdafx.h"
vb@282
     4
#include "CpEpEngine.h"
vb@282
     5
#include <mutex>
Thomas@285
     6
#include "GateKeeper.h"
vb@295
     7
#include "..\libpEpAdapter\Adapter.hh"
Thomas@347
     8
#include "pEp\status_to_string.h"
vb@282
     9
vb@282
    10
using namespace std;
vb@282
    11
using namespace pEp::utility;
vb@295
    12
using namespace pEp::Adapter;
vb@282
    13
vb@282
    14
// CpEpEngine
vb@282
    15
vb@308
    16
CpEpEngine::callback_container CpEpEngine::sync_callbacks;
vb@298
    17
vb@282
    18
// the init_mutex protects our initialization and destruction
vb@282
    19
// against a running keysync thread, and it ensures that the
vb@282
    20
// keysync thread actually has finished before we're destructed.
vb@295
    21
vb@282
    22
std::mutex CpEpEngine::init_mutex;
vb@296
    23
atomic< int > CpEpEngine::count = 0;
vb@282
    24
vb@282
    25
STDMETHODIMP CpEpEngine::InterfaceSupportsErrorInfo(REFIID riid)
vb@282
    26
{
vb@282
    27
    static const IID* const arr[] =
vb@282
    28
    {
vb@282
    29
        &IID_IpEpEngine,
vb@282
    30
    };
vb@282
    31
vb@282
    32
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
vb@282
    33
    {
vb@282
    34
        if (InlineIsEqualGUID(*arr[i], riid))
vb@282
    35
            return S_OK;
vb@282
    36
    }
vb@282
    37
    return S_FALSE;
vb@282
    38
}
vb@282
    39
vb@282
    40
// The second argument is optional, and currently supports PEP_STATUS.
vb@282
    41
#define FAIL(msg, ...) error(msg, __VA_ARGS__)
vb@282
    42
vb@282
    43
STDMETHODIMP CpEpEngine::VerboseLogging(VARIANT_BOOL enable)
vb@282
    44
{
vb@282
    45
    verbose_mode = enable != VARIANT_FALSE;
vb@282
    46
    return S_OK;
vb@282
    47
}
vb@282
    48
vb@282
    49
STDMETHODIMP CpEpEngine::PassiveMode(VARIANT_BOOL enable)
vb@282
    50
{
vb@295
    51
    ::config_passive_mode(session(), enable != VARIANT_FALSE);
vb@282
    52
    return S_OK;
vb@282
    53
}
vb@282
    54
vb@282
    55
STDMETHODIMP CpEpEngine::UnencryptedSubject(VARIANT_BOOL enable)
vb@282
    56
{
vb@295
    57
    ::config_unencrypted_subject(session(), enable != VARIANT_FALSE);
vb@282
    58
    return S_OK;
vb@282
    59
}
vb@282
    60
vb@363
    61
STDMETHODIMP CpEpEngine::ConfigCipherSuite(pEpCipherSuite cipherSuite)
vb@363
    62
{
Thomas@364
    63
    PEP_STATUS status = ::config_cipher_suite(session(), (PEP_CIPHER_SUITE)cipherSuite);
vb@363
    64
Thomas@364
    65
    if (status)
Thomas@364
    66
        return FAIL(L"config_cipher_suite", status);
Thomas@364
    67
    
Thomas@364
    68
    return S_OK;
Thomas@343
    69
}
Thomas@343
    70
vb@363
    71
STDMETHODIMP CpEpEngine::ImportKey(BSTR keyData, LPSAFEARRAY * privateKeys)
vb@363
    72
{
Thomas@364
    73
    assert(keyData);
vb@363
    74
Thomas@364
    75
    if (!keyData)
Thomas@364
    76
        return E_INVALIDARG;
vb@363
    77
Thomas@364
    78
    string key_data = utf8_string(keyData);
Thomas@364
    79
    size_t size = SysStringLen(keyData);
Thomas@364
    80
    ::identity_list *private_keys = nullptr;
vb@363
    81
Thomas@364
    82
    PEP_STATUS status = ::import_key(session(), key_data.c_str(), size, &private_keys);
Thomas@364
    83
    assert(status != ::PEP_OUT_OF_MEMORY);
Thomas@364
    84
    if (status == ::PEP_OUT_OF_MEMORY)
Thomas@364
    85
        return E_OUTOFMEMORY;
vb@363
    86
Thomas@364
    87
    if ((status != PEP_STATUS_OK) && (status != PEP_KEY_IMPORTED))
Thomas@364
    88
        return FAIL(L"import_key", status);
vb@363
    89
Thomas@364
    90
    SAFEARRAY * _privateKeys = nullptr;
Thomas@364
    91
    try {
Thomas@364
    92
        _privateKeys = array_from_C<pEpIdentity, identity_list>(private_keys);
Thomas@364
    93
    }
Thomas@364
    94
    catch (exception& ex)
Thomas@364
    95
    {
Thomas@364
    96
        ::free_identity_list(private_keys);
Thomas@364
    97
        try {
Thomas@364
    98
            dynamic_cast<bad_alloc&>(ex);
Thomas@364
    99
        }
Thomas@364
   100
        catch (bad_cast&)
Thomas@364
   101
        {
Thomas@364
   102
            return FAIL(ex.what());
Thomas@364
   103
        }
Thomas@364
   104
        return E_OUTOFMEMORY;
Thomas@364
   105
    }
Thomas@364
   106
    free_identity_list(private_keys);
Thomas@342
   107
Thomas@364
   108
    *privateKeys = _privateKeys;
vb@363
   109
Thomas@364
   110
    return status;
vb@363
   111
}
Thomas@342
   112
Thomas@342
   113
vb@282
   114
STDMETHODIMP CpEpEngine::ExportKey(BSTR fpr, BSTR * keyData)
vb@282
   115
{
vb@282
   116
    assert(fpr);
vb@282
   117
    assert(keyData);
vb@282
   118
vb@282
   119
    if (!(fpr && keyData))
vb@282
   120
        return E_INVALIDARG;
vb@282
   121
vb@282
   122
    string _fpr = utf8_string(fpr);
vb@282
   123
    char *_key_data = NULL;
vb@282
   124
    size_t _size = 0;
vb@282
   125
vb@295
   126
    PEP_STATUS status = ::export_key(session(), _fpr.c_str(), &_key_data, &_size);
vb@282
   127
    assert(status != ::PEP_OUT_OF_MEMORY);
vb@282
   128
    if (status == ::PEP_OUT_OF_MEMORY)
vb@282
   129
        return E_OUTOFMEMORY;
vb@282
   130
vb@295
   131
    if (status != PEP_STATUS_OK)
vb@282
   132
        return FAIL(L"export_key", status);
vb@282
   133
vb@282
   134
    _bstr_t b_key_data(utf16_string(_key_data).c_str());
vb@282
   135
    pEp_free(_key_data);
vb@282
   136
    *keyData = b_key_data.Detach();
vb@282
   137
vb@282
   138
    return S_OK;
vb@282
   139
}
vb@282
   140
Thomas@344
   141
STDMETHODIMP CpEpEngine::LeaveDeviceGroup()
Thomas@344
   142
{
Thomas@364
   143
    PEP_STATUS status = ::leave_device_group(session());
Thomas@344
   144
Thomas@364
   145
    if (status == PEP_OUT_OF_MEMORY)
Thomas@364
   146
        return E_OUTOFMEMORY;
Thomas@344
   147
Thomas@364
   148
    if (status != PEP_STATUS_OK)
Thomas@364
   149
        return FAIL(L"cannot leave device group", status);
Thomas@344
   150
Thomas@364
   151
    return S_OK;
Thomas@344
   152
}
Thomas@344
   153
vb@282
   154
STDMETHODIMP CpEpEngine::Log(BSTR title, BSTR entity, BSTR description, BSTR comment)
vb@282
   155
{
vb@282
   156
    string _title;
vb@282
   157
    string _entity;
vb@282
   158
    string _description;
vb@282
   159
    string _comment;
vb@282
   160
    HRESULT result = S_OK;
vb@282
   161
vb@282
   162
    assert(title);
vb@282
   163
    if (title)
vb@282
   164
        _title = utf8_string(title);
vb@282
   165
    else
vb@282
   166
        result = E_INVALIDARG;
vb@282
   167
vb@282
   168
    assert(entity);
vb@282
   169
    if (entity)
vb@282
   170
        _entity = utf8_string(entity);
vb@282
   171
    else
vb@282
   172
        result = E_INVALIDARG;
vb@282
   173
vb@282
   174
    if (description)
vb@282
   175
        _description = utf8_string(description);
vb@282
   176
vb@282
   177
    if (comment)
vb@282
   178
        _comment = utf8_string(comment);
vb@282
   179
vb@282
   180
    if (result != S_OK)
vb@282
   181
        return result;
vb@282
   182
vb@295
   183
    PEP_STATUS _status = ::log_event(session(), _title.c_str(), _entity.c_str(), _description.c_str(), _comment.c_str());
vb@282
   184
    assert(_status == PEP_STATUS_OK);
vb@282
   185
    if (_status != PEP_STATUS_OK)
vb@282
   186
        return FAIL(L"log_event", _status);
vb@282
   187
    else
vb@282
   188
        return S_OK;
vb@282
   189
}
vb@282
   190
vb@282
   191
STDMETHODIMP CpEpEngine::Trustwords(BSTR fpr, BSTR lang, LONG max_words, BSTR * words)
vb@282
   192
{
vb@282
   193
    assert(fpr);
vb@282
   194
    assert(max_words >= 0);
vb@282
   195
    assert(words);
vb@282
   196
vb@282
   197
    HRESULT result = S_OK;
vb@282
   198
vb@282
   199
    string _fpr;
vb@282
   200
    if (fpr)
vb@282
   201
        _fpr = utf8_string(fpr);
vb@282
   202
    else
vb@282
   203
        result = E_INVALIDARG;
vb@282
   204
vb@282
   205
    string _lang;
vb@282
   206
    if (lang) {
vb@282
   207
        _lang = utf8_string(lang);
vb@282
   208
        if (_lang.length()) {
vb@282
   209
            if (_lang.length() != 2)
vb@282
   210
                result = E_INVALIDARG;
vb@282
   211
        }
vb@282
   212
        else
vb@282
   213
            _lang = "en";
vb@282
   214
    }
vb@282
   215
    else
vb@282
   216
        _lang = "en";
vb@282
   217
vb@282
   218
    if (max_words < 0)
vb@282
   219
        result = E_INVALIDARG;
vb@282
   220
vb@282
   221
    if (words == NULL)
vb@282
   222
        result = E_INVALIDARG;
vb@282
   223
vb@282
   224
    if (result != S_OK)
vb@282
   225
        return result;
vb@282
   226
vb@282
   227
    char *_words = NULL;
vb@282
   228
    size_t _wsize = 0;
vb@282
   229
vb@295
   230
    PEP_STATUS status = ::trustwords(session(), _fpr.c_str(), _lang.c_str(), &_words, &_wsize, max_words);
vb@282
   231
    assert(status != PEP_OUT_OF_MEMORY);
vb@282
   232
    if (status == PEP_OUT_OF_MEMORY)
vb@282
   233
        return E_OUTOFMEMORY;
vb@282
   234
vb@282
   235
    if (_words == NULL) {
vb@282
   236
        *words = NULL;
vb@282
   237
        return FAIL(L"Trustwords: _words == NULL", status);
vb@282
   238
    }
vb@282
   239
    else {
vb@282
   240
        *words = utf16_bstr(_words);
vb@282
   241
        pEp_free(_words);
vb@282
   242
        return S_OK;
vb@282
   243
    }
vb@282
   244
}
vb@282
   245
Thomas@348
   246
STDMETHODIMP CpEpEngine::GetTrustwordsForFprs(BSTR fpr1, BSTR fpr2, BSTR lang, VARIANT_BOOL full, BSTR *words)
Thomas@348
   247
{
Thomas@364
   248
    assert(fpr1);
Thomas@364
   249
    assert(fpr2);
Thomas@364
   250
    assert(words);
Thomas@348
   251
Thomas@364
   252
    if (!(fpr1 && fpr2 && words))
Thomas@364
   253
    {
Thomas@364
   254
        return E_INVALIDARG;
Thomas@364
   255
    }
Thomas@348
   256
Thomas@364
   257
    HRESULT result = S_OK;
Thomas@364
   258
    string _fpr1;
Thomas@364
   259
    string _fpr2;
Thomas@364
   260
    string _lang;
Thomas@364
   261
    *words = NULL;
Thomas@348
   262
Thomas@364
   263
    try {
Thomas@348
   264
Thomas@364
   265
        _fpr1 = utf8_string(fpr1);
Thomas@364
   266
        _fpr2 = utf8_string(fpr2);
Thomas@364
   267
        
Thomas@364
   268
        if (lang) {
Thomas@364
   269
            _lang = utf8_string(lang);
Thomas@364
   270
            if (_lang.length() == 0) {
Thomas@364
   271
                _lang = "en";
Thomas@364
   272
            }
Thomas@364
   273
            else if (_lang.length() != 2) {
Thomas@364
   274
                result = E_INVALIDARG;
Thomas@364
   275
            }
Thomas@364
   276
        }
Thomas@364
   277
        else {
Thomas@364
   278
            _lang = "en";
Thomas@364
   279
        }
Thomas@364
   280
    }
Thomas@364
   281
    catch (bad_alloc&) {
Thomas@364
   282
        result = E_OUTOFMEMORY;
Thomas@364
   283
    }
Thomas@364
   284
    catch (exception& ex) {
Thomas@364
   285
        result = FAIL(ex.what());
Thomas@364
   286
    }
Thomas@348
   287
Thomas@364
   288
    char* _words;
Thomas@364
   289
    size_t _size;
Thomas@364
   290
    if (result == S_OK) {
Thomas@364
   291
        auto status = ::get_trustwords_for_fprs(session(), _fpr1.c_str(), _fpr2.c_str(), _lang.c_str(), &_words, &_size, full != 0 /* convert variant bool to C bool */);
Thomas@348
   292
Thomas@364
   293
        if (status == PEP_OUT_OF_MEMORY) {
Thomas@364
   294
            result = E_OUTOFMEMORY;
Thomas@364
   295
        }
Thomas@364
   296
        else if (status == PEP_TRUSTWORD_NOT_FOUND) {
Thomas@364
   297
            result = FAIL(L"GetTrustwords: Trustword not found", status);
Thomas@364
   298
        }
Thomas@364
   299
        else if (!words) {
Thomas@364
   300
            result = FAIL(L"GetTrustwords: _words == NULL", status);
Thomas@364
   301
        }
Thomas@364
   302
        else {
Thomas@364
   303
            *words = utf16_bstr(_words);
Thomas@364
   304
            pEp_free(_words);
Thomas@364
   305
        }
Thomas@364
   306
    }
Thomas@348
   307
Thomas@364
   308
    return result;
Thomas@348
   309
}
Thomas@348
   310
vb@282
   311
STDMETHODIMP CpEpEngine::GetTrustwords(struct pEpIdentity *id1, struct pEpIdentity *id2, BSTR lang, VARIANT_BOOL full, BSTR *words)
vb@282
   312
{
vb@282
   313
    assert(id1);
vb@282
   314
    assert(id2);
vb@282
   315
    assert(words);
vb@282
   316
vb@282
   317
    if (!(id1 && id2 && words))
vb@282
   318
    {
vb@282
   319
        return E_INVALIDARG;
vb@282
   320
    }
vb@282
   321
vb@282
   322
    HRESULT result = S_OK;
vb@282
   323
vb@282
   324
    pEp_identity* _id1 = NULL;
vb@282
   325
    pEp_identity* _id2 = NULL;
vb@282
   326
    string _lang;
vb@282
   327
    *words = NULL;
vb@282
   328
vb@282
   329
    try {
vb@282
   330
        _id1 = new_identity(id1);
vb@282
   331
        _id2 = new_identity(id2);
vb@282
   332
vb@282
   333
        if (lang) {
vb@282
   334
            _lang = utf8_string(lang);
vb@282
   335
            if (_lang.length() == 0) {
vb@282
   336
                _lang = "en";
vb@282
   337
            }
vb@282
   338
            else if (_lang.length() != 2) {
vb@282
   339
                result = E_INVALIDARG;
vb@282
   340
            }
vb@282
   341
        }
vb@282
   342
        else {
vb@282
   343
            _lang = "en";
vb@282
   344
        }
vb@282
   345
    }
vb@282
   346
    catch (bad_alloc&) {
vb@282
   347
        result = E_OUTOFMEMORY;
vb@282
   348
    }
vb@282
   349
    catch (exception& ex) {
vb@282
   350
        result = FAIL(ex.what());
vb@282
   351
    }
vb@282
   352
vb@282
   353
    char* _words;
vb@282
   354
    size_t _size;
vb@282
   355
    if (result == S_OK) {
vb@295
   356
        auto status = ::get_trustwords(session(), _id1, _id2, _lang.c_str(), &_words, &_size, full != 0 /* convert variant bool to C bool */);
vb@282
   357
vb@282
   358
        if (status == PEP_OUT_OF_MEMORY) {
vb@282
   359
            result = E_OUTOFMEMORY;
vb@282
   360
        }
vb@282
   361
        else if (status == PEP_TRUSTWORD_NOT_FOUND) {
vb@282
   362
            result = FAIL(L"GetTrustwords: Trustword not found", status);
vb@282
   363
        }
vb@282
   364
        else if (!words) {
vb@282
   365
            result = FAIL(L"GetTrustwords: _words == NULL", status);
vb@282
   366
        }
vb@282
   367
        else {
vb@282
   368
            *words = utf16_bstr(_words);
vb@282
   369
            pEp_free(_words);
vb@282
   370
        }
vb@282
   371
    }
vb@282
   372
vb@282
   373
    free_identity(_id1);
vb@282
   374
    free_identity(_id2);
vb@282
   375
vb@282
   376
    return result;
vb@282
   377
}
vb@282
   378
vb@282
   379
STDMETHODIMP CpEpEngine::GetMessageTrustwords(
vb@282
   380
    /* [in] */ struct TextMessage *msg,
vb@282
   381
    /* [in] */ struct pEpIdentity *receivedBy,
vb@282
   382
    /* [in] */ SAFEARRAY *keylist,
vb@282
   383
    /* [defaultvalue][in] */ BSTR lang,
vb@282
   384
    /* [defaultvalue][in] */ VARIANT_BOOL full,
vb@282
   385
    /* [retval][out] */ BSTR *words) {
vb@282
   386
    assert(msg);
vb@282
   387
    assert(receivedBy);
vb@282
   388
    assert(words);
vb@282
   389
vb@282
   390
    if (!(msg && receivedBy && words))
vb@282
   391
    {
vb@282
   392
        return E_INVALIDARG;
vb@282
   393
    }
vb@282
   394
vb@282
   395
    HRESULT result = S_OK;
vb@282
   396
vb@282
   397
    pEp_identity * _received_by = NULL;
vb@282
   398
    ::message * _msg = NULL;
vb@282
   399
    ::stringlist_t *_keylist = NULL;
vb@282
   400
    string _lang;
vb@282
   401
    *words = NULL;
vb@282
   402
vb@282
   403
    try {
vb@282
   404
        _received_by = new_identity(receivedBy);
vb@282
   405
        _msg = text_message_to_C(msg);
vb@282
   406
vb@282
   407
        if (keylist) {
vb@282
   408
            _keylist = new_stringlist(keylist);
vb@282
   409
        }
vb@282
   410
vb@282
   411
        if (lang) {
vb@282
   412
            _lang = utf8_string(lang);
vb@282
   413
            if (_lang.length() == 0) {
vb@282
   414
                _lang = "en";
vb@282
   415
            }
vb@282
   416
            else if (_lang.length() != 2) {
vb@282
   417
                result = E_INVALIDARG;
vb@282
   418
            }
vb@282
   419
        }
vb@282
   420
        else {
vb@282
   421
            _lang = "en";
vb@282
   422
        }
vb@282
   423
    }
vb@282
   424
    catch (bad_alloc&) {
vb@282
   425
        result = E_OUTOFMEMORY;
vb@282
   426
    }
vb@282
   427
    catch (exception& ex) {
vb@282
   428
        result = FAIL(ex.what());
vb@282
   429
    }
vb@282
   430
vb@282
   431
    char* _words = NULL;
vb@282
   432
    if (result == S_OK) {
vb@282
   433
        auto status = ::get_message_trustwords(
vb@295
   434
            session(),
vb@282
   435
            _msg,
vb@282
   436
            _keylist,
vb@282
   437
            _received_by,
vb@282
   438
            _lang.c_str(),
vb@282
   439
            &_words,
vb@282
   440
            full != 0 /* convert variant bool to C bool */);
vb@282
   441
vb@282
   442
        if (status == PEP_OUT_OF_MEMORY) {
vb@282
   443
            result = E_OUTOFMEMORY;
vb@282
   444
        }
vb@282
   445
        else if (status == PEP_TRUSTWORD_NOT_FOUND) {
vb@282
   446
            result = FAIL(L"GetTrustwords: Trustword not found", status);
vb@282
   447
        }
vb@282
   448
        else if (!words) {
vb@282
   449
            result = FAIL(L"GetTrustwords: _words == NULL", status);
vb@282
   450
        }
vb@282
   451
        else {
vb@282
   452
            *words = utf16_bstr(_words);
vb@282
   453
        }
vb@282
   454
    }
vb@282
   455
vb@282
   456
    ::pEp_free(_words);
vb@282
   457
    ::free_message(_msg);
vb@282
   458
    ::free_stringlist(_keylist);
vb@282
   459
    ::free_identity(_received_by);
vb@282
   460
vb@282
   461
    return result;
vb@282
   462
}
vb@282
   463
vb@282
   464
STDMETHODIMP CpEpEngine::GetCrashdumpLog(LONG maxlines, BSTR * log)
vb@282
   465
{
vb@282
   466
    // COM-18: Currently, long == int on windows, so the check
vb@282
   467
    // for INT_MAX is not strictly necessary. However, the code
vb@282
   468
    // might get copy-pasted to other adapters in the future,
vb@282
   469
    // so safety first...
vb@282
   470
    assert(maxlines >= 0 && maxlines <= INT_MAX);
vb@282
   471
    assert(log);
vb@282
   472
vb@282
   473
    if (!(maxlines >= 0 && maxlines <= INT_MAX && log))
vb@282
   474
        return E_INVALIDARG;
vb@282
   475
vb@282
   476
    char *_log;
vb@295
   477
    PEP_STATUS status = ::get_crashdump_log(session(), (int)maxlines, &_log);
vb@282
   478
    assert(status == PEP_STATUS_OK);
vb@282
   479
    if (status == PEP_OUT_OF_MEMORY)
vb@282
   480
        return E_OUTOFMEMORY;
vb@282
   481
    if (status != PEP_STATUS_OK)
vb@282
   482
        return FAIL(L"GetCrashdumpLog", status);
vb@282
   483
    if (_log == NULL)
vb@282
   484
        return FAIL(L"GetCrashdumpLog: _log == NULL");
vb@282
   485
vb@282
   486
    *log = utf16_bstr(_log);
vb@282
   487
    pEp_free(_log);
vb@282
   488
    return S_OK;
vb@282
   489
}
vb@282
   490
vb@282
   491
STDMETHODIMP CpEpEngine::GetEngineVersion(BSTR * engine_version)
vb@282
   492
{
vb@282
   493
    assert(engine_version);
vb@282
   494
vb@282
   495
    if (!engine_version)
vb@282
   496
        return E_INVALIDARG;
vb@282
   497
vb@282
   498
    const char *_engine_version = ::get_engine_version();
vb@282
   499
vb@282
   500
    if (_engine_version == NULL)
vb@282
   501
        return FAIL(L"GetEngineVersion: _engine_version == NULL");
vb@282
   502
vb@282
   503
    *engine_version = utf16_bstr(_engine_version);
vb@282
   504
vb@282
   505
    return S_OK;
vb@282
   506
}
vb@282
   507
vb@282
   508
STDMETHODIMP CpEpEngine::GetLanguageList(BSTR * languages)
vb@282
   509
{
vb@282
   510
    assert(languages);
vb@282
   511
vb@282
   512
    if (!languages)
vb@282
   513
        return E_INVALIDARG;
vb@282
   514
vb@282
   515
    char *_languages;
vb@295
   516
    PEP_STATUS status = ::get_languagelist(session(), &_languages);
vb@282
   517
    assert(status == PEP_STATUS_OK);
vb@282
   518
    if (status == PEP_OUT_OF_MEMORY)
vb@282
   519
        return E_OUTOFMEMORY;
vb@282
   520
    if (status != PEP_STATUS_OK)
vb@282
   521
        return FAIL(L"GetLanguageList", status);
vb@282
   522
    if (_languages == NULL)
vb@282
   523
        return FAIL(L"GetLanguageList: _languages == NULL");
vb@282
   524
vb@282
   525
    *languages = utf16_bstr(_languages);
vb@282
   526
    pEp_free(_languages);
vb@282
   527
    return S_OK;
vb@282
   528
}
vb@282
   529
vb@282
   530
STDMETHODIMP CpEpEngine::SetIdentityFlags(struct pEpIdentity *identity, pEpIdentityFlags flags)
vb@282
   531
{
vb@282
   532
    assert(identity);
vb@282
   533
    if (!identity)
vb@282
   534
        return E_INVALIDARG;
vb@282
   535
vb@282
   536
    ::pEp_identity *_ident = nullptr;
vb@282
   537
vb@282
   538
    try {
vb@282
   539
        _ident = new_identity(identity);
vb@282
   540
        assert(_ident);
vb@282
   541
        if (_ident == NULL)
vb@282
   542
            return E_OUTOFMEMORY;
vb@282
   543
    }
vb@282
   544
    catch (bad_alloc&) {
vb@282
   545
        return E_OUTOFMEMORY;
vb@282
   546
    }
vb@282
   547
    catch (exception& ex) {
vb@282
   548
        return FAIL(ex.what());;
vb@282
   549
    }
vb@282
   550
vb@295
   551
    PEP_STATUS status = ::set_identity_flags(session(), _ident, (identity_flags_t)flags);
vb@282
   552
    ::free_identity(_ident);
vb@282
   553
    if (status != PEP_STATUS_OK)
vb@282
   554
        return FAIL(_T("SetIdentityFlags"), status);
vb@282
   555
vb@282
   556
    return S_OK;
vb@282
   557
}
vb@282
   558
vb@282
   559
STDMETHODIMP CpEpEngine::UnsetIdentityFlags(struct pEpIdentity *identity, pEpIdentityFlags flags)
vb@282
   560
{
vb@282
   561
    assert(identity);
vb@282
   562
    if (!identity)
vb@282
   563
        return E_INVALIDARG;
vb@282
   564
vb@282
   565
    ::pEp_identity *_ident = nullptr;
vb@282
   566
vb@282
   567
    try {
vb@282
   568
        _ident = new_identity(identity);
vb@282
   569
        assert(_ident);
vb@282
   570
        if (_ident == NULL)
vb@282
   571
            return E_OUTOFMEMORY;
vb@282
   572
    }
vb@282
   573
    catch (bad_alloc&) {
vb@282
   574
        return E_OUTOFMEMORY;
vb@282
   575
    }
vb@282
   576
    catch (exception& ex) {
vb@282
   577
        return FAIL(ex.what());;
vb@282
   578
    }
vb@282
   579
vb@295
   580
    PEP_STATUS status = ::unset_identity_flags(session(), _ident, (identity_flags_t)flags);
vb@282
   581
    ::free_identity(_ident);
vb@282
   582
    if (status != PEP_STATUS_OK)
vb@282
   583
        return FAIL(_T("UnsetIdentityFlags"), status);
vb@282
   584
vb@282
   585
    return S_OK;
vb@282
   586
}
vb@282
   587
vb@282
   588
STDMETHODIMP CpEpEngine::StartKeyserverLookup()
vb@282
   589
{
vb@282
   590
    if (identity_queue.load())
vb@282
   591
        return S_OK;
vb@282
   592
vb@282
   593
    identity_queue.store(new identity_queue_t());
vb@282
   594
    keymanagement_thread = new thread(::do_keymanagement, retrieve_next_identity, (void *)identity_queue.load());
vb@282
   595
vb@282
   596
    return S_OK;
vb@282
   597
}
vb@282
   598
vb@282
   599
STDMETHODIMP CpEpEngine::StopKeyserverLookup()
vb@282
   600
{
vb@282
   601
    if (identity_queue.load() == NULL)
vb@282
   602
        return S_OK;
vb@282
   603
vb@282
   604
    identity_queue_t *_iq = identity_queue.load();
vb@282
   605
    identity_queue.store(NULL);
vb@282
   606
vb@282
   607
    pEp_identity_cpp shutdown;
vb@282
   608
    _iq->push_front(shutdown);
vb@282
   609
vb@282
   610
    keymanagement_thread->join();
vb@282
   611
    delete keymanagement_thread;
vb@282
   612
    keymanagement_thread = NULL;
vb@282
   613
vb@282
   614
    delete _iq;
vb@282
   615
vb@282
   616
    return S_OK;
vb@282
   617
}
vb@282
   618
vb@282
   619
STDMETHODIMP CpEpEngine::Myself(struct pEpIdentity *ident, struct pEpIdentity *result)
vb@282
   620
{
vb@282
   621
    assert(ident);
vb@282
   622
    assert(result);
vb@282
   623
vb@282
   624
    if (!(ident && result))
vb@282
   625
        return E_INVALIDARG;
vb@282
   626
vb@282
   627
    ::pEp_identity *_ident = 0;
vb@282
   628
vb@282
   629
    try {
vb@282
   630
        _ident = new_identity(ident);
vb@282
   631
        assert(_ident);
vb@282
   632
        if (_ident == NULL)
vb@282
   633
            return E_OUTOFMEMORY;
vb@282
   634
    }
vb@282
   635
    catch (bad_alloc&) {
vb@282
   636
        return E_OUTOFMEMORY;
vb@282
   637
    }
vb@282
   638
    catch (exception& ex) {
vb@282
   639
        return FAIL(ex.what());;
vb@282
   640
    }
vb@282
   641
vb@295
   642
    PEP_STATUS status = ::myself(session(), _ident);
vb@282
   643
vb@282
   644
    if (status == PEP_STATUS_OK) {
vb@282
   645
        assert(_ident->fpr);
vb@282
   646
        copy_identity(result, _ident);
vb@282
   647
        ::free_identity(_ident);
vb@282
   648
        return S_OK;
vb@282
   649
    }
vb@282
   650
    else {
vb@282
   651
        ::free_identity(_ident);
vb@282
   652
        if (status == PEP_OUT_OF_MEMORY)
vb@282
   653
            return E_OUTOFMEMORY;
vb@282
   654
        else
vb@282
   655
            return FAIL(L"myself", status);
vb@282
   656
    }
vb@282
   657
}
vb@282
   658
vb@282
   659
STDMETHODIMP CpEpEngine::UpdateIdentity(struct pEpIdentity *ident, struct pEpIdentity *result)
vb@282
   660
{
vb@282
   661
    assert(ident);
vb@282
   662
    assert(result);
vb@282
   663
vb@282
   664
    if (!(ident && result))
vb@282
   665
        return E_INVALIDARG;
vb@282
   666
vb@282
   667
    ::pEp_identity *_ident;
vb@282
   668
    try {
vb@282
   669
        _ident = new_identity(ident);
vb@282
   670
    }
vb@282
   671
    catch (bad_alloc&) {
vb@282
   672
        return E_OUTOFMEMORY;
vb@282
   673
    }
vb@282
   674
    catch (exception& ex) {
vb@282
   675
        return FAIL(ex.what());
vb@282
   676
    }
vb@282
   677
vb@282
   678
    assert(_ident);
vb@282
   679
    if (_ident == NULL)
vb@282
   680
        return E_OUTOFMEMORY;
vb@282
   681
vb@295
   682
    PEP_STATUS status = ::update_identity(session(), _ident);
vb@282
   683
vb@282
   684
    if (status == PEP_STATUS_OK) {
vb@282
   685
        copy_identity(result, _ident);
vb@282
   686
        ::free_identity(_ident);
vb@282
   687
        return S_OK;
vb@282
   688
    }
vb@282
   689
    else if (status == PEP_GET_KEY_FAILED || status == PEP_KEY_NOT_FOUND) {
vb@282
   690
        if (_ident->fpr) {
vb@282
   691
            pEp_free(_ident->fpr);
vb@282
   692
            _ident->fpr = NULL;
vb@282
   693
        }
vb@282
   694
        copy_identity(result, _ident);
vb@282
   695
        result->Fpr = NULL;
vb@282
   696
        ::free_identity(_ident);
vb@282
   697
        return S_OK;
vb@282
   698
    }
vb@282
   699
    else {
vb@282
   700
        ::free_identity(_ident);
vb@282
   701
        if (status == PEP_OUT_OF_MEMORY)
vb@282
   702
            return E_OUTOFMEMORY;
vb@282
   703
        else
vb@282
   704
            return FAIL(L"UpdateIdentity", status);
vb@282
   705
    }
vb@282
   706
}
vb@282
   707
vb@282
   708
STDMETHODIMP CpEpEngine::KeyMistrusted(struct pEpIdentity *ident)
vb@282
   709
{
vb@282
   710
    ::pEp_identity *_ident;
vb@282
   711
vb@282
   712
    assert(ident);
vb@282
   713
    if (!ident)
vb@282
   714
        return E_INVALIDARG;
vb@282
   715
vb@282
   716
    try {
vb@282
   717
        _ident = new_identity(ident);
vb@282
   718
    }
vb@282
   719
    catch (bad_alloc&) {
vb@282
   720
        return E_OUTOFMEMORY;
vb@282
   721
    }
vb@282
   722
    catch (exception& ex) {
vb@282
   723
        return FAIL(ex.what());;
vb@282
   724
    }
vb@282
   725
vb@295
   726
    PEP_STATUS status = ::key_mistrusted(session(), _ident);
vb@282
   727
    free_identity(_ident);
vb@282
   728
vb@282
   729
    if (status == PEP_OUT_OF_MEMORY)
vb@282
   730
        return E_OUTOFMEMORY;
vb@282
   731
vb@282
   732
    if (status == PEP_KEY_NOT_FOUND)
vb@282
   733
        return FAIL(L"key not found");
vb@282
   734
vb@295
   735
    if (status != PEP_STATUS_OK)
Thomas@346
   736
        return FAIL(L"cannot revoke compromised key", status);
vb@282
   737
vb@282
   738
    return S_OK;
vb@282
   739
}
vb@282
   740
vb@295
   741
STDMETHODIMP CpEpEngine::IspEpUser(/* [in] */ struct pEpIdentity *ident, /* [retval][out] */ VARIANT_BOOL *ispEp) 
vb@282
   742
{
vb@282
   743
    ::pEp_identity *_ident;
vb@282
   744
vb@282
   745
    assert(ident);
vb@282
   746
    if (!ident)
vb@282
   747
        return E_INVALIDARG;
vb@282
   748
vb@282
   749
    try {
vb@282
   750
        _ident = new_identity(ident);
vb@282
   751
    }
vb@282
   752
    catch (bad_alloc&) {
vb@282
   753
        return E_OUTOFMEMORY;
vb@282
   754
    }
vb@282
   755
    catch (exception& ex) {
vb@282
   756
        return FAIL(ex.what());;
vb@282
   757
    }
vb@282
   758
vb@282
   759
    bool is_pep = FALSE;
vb@295
   760
    PEP_STATUS status = ::is_pEp_user(session(), _ident, &is_pep);
vb@282
   761
vb@282
   762
    *ispEp = is_pep;
vb@282
   763
vb@282
   764
    if (status == PEP_CANNOT_FIND_PERSON)
vb@282
   765
        return FAIL(L"Cannot find identity!", status);
vb@282
   766
vb@282
   767
    if (status == PEP_ILLEGAL_VALUE)
vb@282
   768
        return E_INVALIDARG;
vb@282
   769
vb@295
   770
    if (status != PEP_STATUS_OK)
vb@295
   771
        return FAIL(L"Engine is_pEp_user returned error", status);
vb@282
   772
vb@282
   773
    return S_OK;
vb@282
   774
}
vb@282
   775
Thomas@336
   776
STDMETHODIMP CpEpEngine::KeyResetIdentity(struct pEpIdentity ident, BSTR fpr)
Thomas@331
   777
{
Thomas@364
   778
    ::pEp_identity *_ident;
Thomas@331
   779
Thomas@364
   780
    try {
Thomas@364
   781
        _ident = new_identity(&ident);
Thomas@364
   782
    }
Thomas@364
   783
    catch (bad_alloc&) {
Thomas@364
   784
        return E_OUTOFMEMORY;
Thomas@364
   785
    }
Thomas@364
   786
    catch (exception& ex) {
Thomas@364
   787
        return FAIL(ex.what());;
Thomas@364
   788
    }
Thomas@331
   789
Thomas@364
   790
    string _fpr = utf8_string(fpr);
Thomas@331
   791
Thomas@364
   792
    PEP_STATUS status = ::key_reset_identity(session(), _ident, _fpr.c_str());
Thomas@331
   793
Thomas@364
   794
    free_identity(_ident);
Thomas@331
   795
Thomas@364
   796
    if (status == PEP_OUT_OF_MEMORY)
Thomas@364
   797
        return E_OUTOFMEMORY;
Thomas@331
   798
Thomas@364
   799
    if (status == PEP_KEY_NOT_FOUND)
Thomas@364
   800
        return FAIL(L"key not found");
Thomas@331
   801
Thomas@364
   802
    if (status != PEP_STATUS_OK)
Thomas@364
   803
        return FAIL(L"cannot reset identity", status);
Thomas@336
   804
Thomas@364
   805
    return S_OK;
Thomas@336
   806
}
Thomas@336
   807
Thomas@345
   808
STDMETHODIMP CpEpEngine::KeyResetUser(BSTR userId, BSTR fpr)
vb@338
   809
{
Thomas@364
   810
    string _userId = utf8_string(userId);
Thomas@364
   811
    string _fpr = utf8_string(fpr);
Thomas@336
   812
Thomas@364
   813
    PEP_STATUS status = ::key_reset_user(session(), _userId.c_str(), _fpr.c_str());
Thomas@336
   814
Thomas@364
   815
    if (status == PEP_OUT_OF_MEMORY)
Thomas@364
   816
        return E_OUTOFMEMORY;
Thomas@336
   817
Thomas@364
   818
    if (status == PEP_KEY_NOT_FOUND)
Thomas@364
   819
        return FAIL(L"key not found");
Thomas@336
   820
Thomas@364
   821
    if (status != PEP_STATUS_OK)
Thomas@364
   822
        return FAIL(L"cannot reset user", status);
Thomas@336
   823
Thomas@364
   824
    return S_OK;
vb@338
   825
}
vb@338
   826
Thomas@336
   827
STDMETHODIMP CpEpEngine::KeyResetAllOwnKeys()
Thomas@336
   828
{
Thomas@364
   829
    PEP_STATUS status = ::key_reset_all_own_keys(session());
Thomas@336
   830
Thomas@364
   831
    if (status == PEP_OUT_OF_MEMORY)
Thomas@364
   832
        return E_OUTOFMEMORY;
Thomas@336
   833
Thomas@364
   834
    if (status != PEP_STATUS_OK)
Thomas@364
   835
        return FAIL(L"cannot reset all own keys", status);
Thomas@331
   836
Thomas@364
   837
    return S_OK;
Thomas@331
   838
}
Thomas@331
   839
vb@282
   840
STDMETHODIMP CpEpEngine::KeyResetTrust(struct pEpIdentity *ident)
vb@282
   841
{
vb@282
   842
    ::pEp_identity *_ident;
vb@282
   843
vb@282
   844
    assert(ident);
vb@282
   845
vb@282
   846
    if (!ident)
vb@282
   847
        return E_INVALIDARG;
vb@282
   848
vb@282
   849
    try {
vb@282
   850
        _ident = new_identity(ident);
vb@282
   851
    }
vb@282
   852
    catch (bad_alloc&) {
vb@282
   853
        return E_OUTOFMEMORY;
vb@282
   854
    }
vb@282
   855
    catch (exception& ex) {
vb@282
   856
        return FAIL(ex.what());;
vb@282
   857
    }
vb@282
   858
vb@295
   859
    PEP_STATUS status = ::key_reset_trust(session(), _ident);
vb@282
   860
    free_identity(_ident);
vb@282
   861
vb@282
   862
    if (status == PEP_OUT_OF_MEMORY)
vb@282
   863
        return E_OUTOFMEMORY;
vb@282
   864
vb@282
   865
    if (status == PEP_KEY_NOT_FOUND)
vb@282
   866
        return FAIL(L"key not found");
vb@282
   867
vb@295
   868
    if (status != PEP_STATUS_OK)
vb@282
   869
        return FAIL(L"cannot reset trust", status);
vb@282
   870
vb@282
   871
    return S_OK;
vb@282
   872
}
vb@282
   873
vb@282
   874
int CpEpEngine::examine_identity(pEp_identity *ident, void *management)
vb@282
   875
{
vb@282
   876
    assert(ident);
vb@282
   877
    assert(management);
vb@282
   878
    if (!(ident && management))
vb@282
   879
        return -1;
vb@282
   880
vb@282
   881
    CpEpEngine *me = (CpEpEngine *)management;
vb@282
   882
vb@282
   883
    if (me->identity_queue.load() == NULL)
vb@282
   884
        return 0;
vb@282
   885
vb@282
   886
    try {
vb@282
   887
        me->identity_queue.load()->push_back(ident);
vb@282
   888
    }
vb@282
   889
    catch (exception&) {
vb@282
   890
        return -1;
vb@282
   891
    }
vb@282
   892
vb@282
   893
    return 0;
vb@282
   894
}
vb@282
   895
vb@282
   896
::pEp_identity * CpEpEngine::retrieve_next_identity(void *management)
vb@282
   897
{
vb@282
   898
    assert(management);
vb@282
   899
    if (!management)
vb@282
   900
        return NULL;
vb@282
   901
vb@282
   902
    identity_queue_t *iq = (identity_queue_t *)management;
vb@282
   903
vb@282
   904
    do /* poll queue */ {
vb@282
   905
        if (iq->size())
vb@282
   906
            break;
vb@282
   907
        ::Sleep(100);
vb@282
   908
    } while (true);
vb@282
   909
vb@282
   910
    ::pEp_identity *_ident;
vb@282
   911
    pEp_identity_cpp& ident = iq->front();
vb@282
   912
vb@282
   913
    if (ident.address.size() == 0)
vb@282
   914
        return NULL;
vb@282
   915
vb@282
   916
    _ident = ident.to_pEp_identity();
vb@282
   917
    iq->pop_front();
vb@282
   918
vb@282
   919
    return _ident;
vb@282
   920
}
vb@282
   921
vb@312
   922
static IpEpEngineCallbacks * _unmarshaled_consumer(CpEpEngine::callback_container::Container::iterator p)
vb@308
   923
{
vb@310
   924
    if (!p->cdata && p->pdata && p->pdata->marshaled) {
vb@308
   925
        HRESULT r = CoGetInterfaceAndReleaseStream(p->pdata->marshaled, IID_IpEpEngineCallbacks, (LPVOID*) &p->cdata);
vb@308
   926
        if (!SUCCEEDED(r))
vb@308
   927
            throw runtime_error("_unmarshaled_consumer(): CoGetInterfaceAndReleaseStream() failed");
vb@308
   928
        p->pdata->marshaled = nullptr;
vb@308
   929
    }
vb@312
   930
    else if (p->cdata && !p->pdata) {
vb@312
   931
        p->cdata->Release();
vb@312
   932
        p->cdata = nullptr;
vb@312
   933
    }
vb@308
   934
vb@308
   935
    return p->cdata;
vb@308
   936
}
vb@308
   937
vb@307
   938
PEP_STATUS CpEpEngine::messageToSend(message *msg)
vb@282
   939
{
vb@282
   940
    assert(msg);
vb@295
   941
    if (!msg)
vb@282
   942
        return PEP_ILLEGAL_VALUE;
vb@282
   943
vb@307
   944
    bool in_sync = on_sync_thread();
vb@282
   945
vb@297
   946
    for (auto p = sync_callbacks.begin(); p != sync_callbacks.end(); ++p) {
vb@308
   947
        IpEpEngineCallbacks *cb = in_sync ? _unmarshaled_consumer(p) : p->pdata->unmarshaled;
vb@295
   948
vb@297
   949
        if (cb) {
vb@297
   950
            TextMessage _msg;
vb@297
   951
            memset(&_msg, 0, sizeof(TextMessage));
vb@295
   952
vb@297
   953
            text_message_from_C(&_msg, msg);
vb@297
   954
            HRESULT r = cb->MessageToSend(&_msg);
vb@297
   955
            assert(r == S_OK);
vb@297
   956
            clear_text_message(&_msg);
vb@297
   957
            if (r == E_OUTOFMEMORY)
vb@297
   958
                return PEP_OUT_OF_MEMORY;
vb@297
   959
            if (r != S_OK)
vb@297
   960
                return PEP_UNKNOWN_ERROR;
vb@297
   961
        }
vb@297
   962
    }
Thomas@292
   963
vb@313
   964
    sync_callbacks.compact();
vb@313
   965
vb@297
   966
    return PEP_STATUS_OK;
vb@297
   967
}
vb@297
   968
vb@307
   969
PEP_STATUS CpEpEngine::notifyHandshake(::pEp_identity *self, ::pEp_identity *partner, sync_handshake_signal signal)
vb@297
   970
{
vb@297
   971
    assert(self && partner);
vb@297
   972
    if (!(self && partner))
vb@297
   973
        return PEP_ILLEGAL_VALUE;
vb@297
   974
vb@307
   975
    bool in_sync = on_sync_thread();
vb@307
   976
vb@297
   977
    // fire all of them
vb@297
   978
    for (auto p = sync_callbacks.begin(); p != sync_callbacks.end(); ++p) {
vb@309
   979
        IpEpEngineCallbacks *cb = in_sync ? _unmarshaled_consumer(p) : p->pdata->unmarshaled;
vb@297
   980
vb@297
   981
        if (cb) {
vb@297
   982
            pEpIdentity _self;
vb@297
   983
            copy_identity(&_self, self);
vb@297
   984
            pEpIdentity _partner;
vb@297
   985
            copy_identity(&_partner, partner);
vb@297
   986
vb@297
   987
            SyncHandshakeSignal _signal = (SyncHandshakeSignal)signal;
vb@338
   988
            HRESULT r = cb->NotifyHandshake(&_self, &_partner, _signal);
vb@297
   989
            assert(r == S_OK);
vb@297
   990
            clear_identity_s(_self);
vb@297
   991
            clear_identity_s(_partner);
vb@297
   992
            if (r == E_OUTOFMEMORY)
vb@297
   993
                return PEP_OUT_OF_MEMORY;
vb@297
   994
        }
vb@297
   995
    }
Thomas@292
   996
vb@313
   997
    sync_callbacks.compact();
vb@282
   998
vb@282
   999
    return PEP_STATUS_OK;
vb@282
  1000
}
vb@282
  1001
vb@282
  1002
STDMETHODIMP CpEpEngine::BlacklistAdd(BSTR fpr)
vb@282
  1003
{
vb@282
  1004
    assert(fpr);
vb@282
  1005
    if (!fpr)
vb@282
  1006
        return E_INVALIDARG;
vb@282
  1007
vb@282
  1008
    string _fpr = utf8_string(fpr);
vb@295
  1009
    PEP_STATUS status = ::blacklist_add(session(), _fpr.c_str());
vb@282
  1010
    assert(status == PEP_STATUS_OK);
vb@282
  1011
    if (status != PEP_STATUS_OK)
vb@282
  1012
        return FAIL(L"blacklist_add failed in pEp engine", status);
vb@282
  1013
vb@282
  1014
    return S_OK;
vb@282
  1015
}
vb@282
  1016
vb@282
  1017
STDMETHODIMP CpEpEngine::BlacklistDelete(BSTR fpr)
vb@282
  1018
{
vb@282
  1019
    assert(fpr);
vb@282
  1020
    if (!fpr)
vb@282
  1021
        return E_INVALIDARG;
vb@282
  1022
vb@282
  1023
    string _fpr = utf8_string(fpr);
vb@295
  1024
    PEP_STATUS status = ::blacklist_delete(session(), _fpr.c_str());
vb@282
  1025
    assert(status == PEP_STATUS_OK);
vb@282
  1026
    if (status != PEP_STATUS_OK)
vb@282
  1027
        return FAIL(L"blacklist_delete failed in pEp engine", status);
vb@282
  1028
vb@282
  1029
    return S_OK;
vb@282
  1030
}
vb@282
  1031
vb@282
  1032
STDMETHODIMP CpEpEngine::BlacklistIsListed(BSTR fpr, VARIANT_BOOL *listed)
vb@282
  1033
{
vb@282
  1034
    assert(fpr);
vb@282
  1035
    assert(listed);
vb@282
  1036
vb@282
  1037
    if (!(fpr && listed))
vb@282
  1038
        return E_INVALIDARG;
vb@282
  1039
vb@282
  1040
    string _fpr = utf8_string(fpr);
vb@282
  1041
    bool result;
vb@295
  1042
    PEP_STATUS status = ::blacklist_is_listed(session(), _fpr.c_str(), &result);
vb@282
  1043
    assert(status == PEP_STATUS_OK);
vb@282
  1044
    if (status != PEP_STATUS_OK)
vb@282
  1045
        return FAIL(L"blacklist_is_listed failed in pEp engine", status);
vb@282
  1046
vb@282
  1047
    *listed = result ? VARIANT_TRUE : VARIANT_FALSE;
vb@282
  1048
    return S_OK;
vb@282
  1049
}
vb@282
  1050
vb@282
  1051
STDMETHODIMP CpEpEngine::BlacklistRetrieve(SAFEARRAY **blacklist)
vb@282
  1052
{
vb@282
  1053
    assert(blacklist);
vb@282
  1054
vb@282
  1055
    if (!blacklist)
vb@282
  1056
        return E_INVALIDARG;
vb@282
  1057
vb@282
  1058
    ::stringlist_t *_blacklist = NULL;
vb@295
  1059
    PEP_STATUS status = ::blacklist_retrieve(session(), &_blacklist);
vb@282
  1060
    assert(status == PEP_STATUS_OK);
vb@282
  1061
    if (status != PEP_STATUS_OK)
vb@282
  1062
        return FAIL(L"blacklist_retrieve failed in pEp engine", status);
vb@282
  1063
    assert(_blacklist);
vb@282
  1064
vb@282
  1065
    *blacklist = string_array(_blacklist);
vb@282
  1066
    ::free_stringlist(_blacklist);
vb@282
  1067
    return S_OK;
vb@282
  1068
}
vb@282
  1069
vb@282
  1070
HRESULT CpEpEngine::error(_bstr_t msg)
vb@282
  1071
{
vb@282
  1072
    _bstr_t helpFile = L"";
vb@282
  1073
    _bstr_t source = L"pEp COM Adapter";
vb@282
  1074
vb@282
  1075
    ICreateErrorInfo *cei;
vb@282
  1076
    if (SUCCEEDED(CreateErrorInfo(&cei))) {
vb@282
  1077
        cei->SetDescription(msg);
vb@282
  1078
        cei->SetGUID(__uuidof(IpEpEngine));
vb@282
  1079
        cei->SetHelpContext(0);
vb@282
  1080
        cei->SetHelpFile(helpFile);
vb@282
  1081
        cei->SetSource(source);
vb@282
  1082
vb@282
  1083
        IErrorInfo *errinfo;
vb@282
  1084
        if (SUCCEEDED(cei->QueryInterface(IID_IErrorInfo, (LPVOID FAR*) &errinfo))) {
vb@282
  1085
            SetErrorInfo(0, errinfo);
vb@282
  1086
            errinfo->Release();
vb@282
  1087
        }
vb@282
  1088
        cei->Release();
vb@282
  1089
    }
vb@282
  1090
    return E_FAIL;
vb@282
  1091
}
vb@282
  1092
vb@282
  1093
HRESULT CpEpEngine::error(_bstr_t msg, PEP_STATUS status)
vb@282
  1094
{
vb@282
  1095
    std::stringstream stream;
vb@282
  1096
    stream << msg;
vb@282
  1097
    stream << ": ";
Thomas@347
  1098
    stream << pEp_status_to_string(status);
Thomas@347
  1099
    stream << std::hex << " (" << status << ")";
vb@282
  1100
vb@282
  1101
    error(stream.str().c_str());
vb@282
  1102
vb@282
  1103
    if (status == ::PEP_OUT_OF_MEMORY)
vb@282
  1104
        return E_OUTOFMEMORY;
vb@282
  1105
vb@282
  1106
    return MAKE_HRESULT(1, FACILITY_ITF, (0xFFFF & status));
vb@282
  1107
}
vb@282
  1108
vb@282
  1109
STDMETHODIMP CpEpEngine::EncryptMessage(TextMessage * src, TextMessage * dst, SAFEARRAY * extra, pEpEncryptFlags flags, pEpEncFormat encFormat)
vb@282
  1110
{
vb@282
  1111
    assert(src);
vb@282
  1112
    assert(dst);
vb@282
  1113
vb@282
  1114
    if (!(src && dst))
vb@282
  1115
        return E_INVALIDARG;
vb@282
  1116
Thomas@364
  1117
    ::message *_src = NULL;
Thomas@364
  1118
    try {
Thomas@364
  1119
        _src = text_message_to_C(src);
Thomas@364
  1120
    }
Thomas@364
  1121
    catch (bad_alloc&) {
Thomas@364
  1122
        return E_OUTOFMEMORY;
Thomas@364
  1123
    }
Thomas@364
  1124
    catch (exception& ex) {
Thomas@364
  1125
        return FAIL(ex.what());
Thomas@364
  1126
    }
vb@282
  1127
vb@282
  1128
    _PEP_enc_format _encFormat = (_PEP_enc_format)encFormat;
vb@282
  1129
vb@282
  1130
    // COM-19: Initialize msg_dst to NULL, or we end up calling
vb@282
  1131
    // free_message() below with a pointer to random garbage in
vb@282
  1132
    // case of an error in encrypt_message().
vb@282
  1133
    ::message *msg_dst = NULL;
vb@282
  1134
    ::stringlist_t *_extra = new_stringlist(extra); // can cope with NULL
vb@282
  1135
vb@282
  1136
    // _PEP_enc_format used to be intentionally hardcoded to PEP_enc_PEP:
vb@282
  1137
    // Since COM-74, this has been changed to an explicit parameter, to allow the engine to attach
vb@282
  1138
    // the keys and headers to outgoing, unencrypted messages.
vb@282
  1139
    PEP_encrypt_flags_t engineFlags = (PEP_encrypt_flags_t)flags;
vb@295
  1140
    PEP_STATUS status = ::encrypt_message(session(), _src, _extra, &msg_dst, _encFormat, engineFlags);
vb@282
  1141
    ::free_stringlist(_extra);
vb@282
  1142
vb@282
  1143
    if (status == PEP_STATUS_OK)
vb@282
  1144
        text_message_from_C(dst, msg_dst);
vb@282
  1145
    else
vb@282
  1146
        text_message_from_C(dst, _src);
vb@282
  1147
vb@282
  1148
    ::free_message(msg_dst);
vb@282
  1149
    ::free_message(_src);
vb@282
  1150
vb@282
  1151
    if (status == PEP_OUT_OF_MEMORY)
vb@282
  1152
        return E_OUTOFMEMORY;
vb@282
  1153
vb@282
  1154
    // COM-41: Enhanced PEP status handling
vb@282
  1155
    if ((status != PEP_STATUS_OK) && (status < PEP_UNENCRYPTED || status >= PEP_TRUSTWORD_NOT_FOUND))
vb@282
  1156
        return FAIL("Failure to encrypt message", status);
vb@282
  1157
vb@282
  1158
    // Statii like PEP_UNENCRYPTED due to no private key
vb@282
  1159
    // should not be a catastrophic failure here. Using S_FALSE
vb@282
  1160
    // still allows clients to differentiate with S_OK,
vb@282
  1161
    // although this does not work out of the box with
vb@282
  1162
    // the standard .NET mapping of COM.
vb@282
  1163
    if (status != PEP_STATUS_OK)
vb@282
  1164
        return S_FALSE;
vb@282
  1165
vb@282
  1166
    return S_OK;
vb@282
  1167
}
vb@282
  1168
Thomas@285
  1169
STDMETHODIMP CpEpEngine::EncryptMessageAndAddPrivKey(TextMessage * src, TextMessage * dst, BSTR to_fpr, pEpEncryptFlags flags, pEpEncFormat encFormat)
Thomas@285
  1170
{
Thomas@285
  1171
    assert(src);
Thomas@285
  1172
    assert(dst);
Thomas@285
  1173
    assert(to_fpr);
Thomas@285
  1174
Thomas@285
  1175
    if (!(src && dst))
Thomas@285
  1176
        return E_INVALIDARG;
Thomas@285
  1177
Thomas@364
  1178
    ::message *_src = NULL;
Thomas@364
  1179
    try {
Thomas@364
  1180
        _src = text_message_to_C(src);
Thomas@364
  1181
    }
Thomas@364
  1182
    catch (bad_alloc&) {
Thomas@364
  1183
        return E_OUTOFMEMORY;
Thomas@364
  1184
    }
Thomas@364
  1185
    catch (exception& ex) {
Thomas@364
  1186
        return FAIL(ex.what());
Thomas@364
  1187
    }
Thomas@285
  1188
Thomas@285
  1189
    _PEP_enc_format _encFormat = (_PEP_enc_format)encFormat;
Thomas@285
  1190
Thomas@285
  1191
    // COM-19: Initialize msg_dst to NULL, or we end up calling
Thomas@285
  1192
    // free_message() below with a pointer to random garbage in
Thomas@285
  1193
    // case of an error in encrypt_message().
Thomas@285
  1194
    ::message *msg_dst = NULL;
Thomas@285
  1195
Thomas@285
  1196
    string _to_fpr = utf8_string(to_fpr);
Thomas@285
  1197
                                                    // _PEP_enc_format used to be intentionally hardcoded to PEP_enc_PEP:
Thomas@285
  1198
                                                    // Since COM-74, this has been changed to an explicit parameter, to allow the engine to attach
Thomas@285
  1199
                                                    // the keys and headers to outgoing, unencrypted messages.
Thomas@285
  1200
    PEP_encrypt_flags_t engineFlags = (PEP_encrypt_flags_t)flags;
vb@295
  1201
    PEP_STATUS status = ::encrypt_message_and_add_priv_key(session(), _src, &msg_dst, _to_fpr.c_str(), _encFormat, engineFlags);
Thomas@285
  1202
Thomas@285
  1203
    if (status == PEP_STATUS_OK)
Thomas@285
  1204
        text_message_from_C(dst, msg_dst);
Thomas@285
  1205
    else
Thomas@285
  1206
        text_message_from_C(dst, _src);
Thomas@285
  1207
Thomas@285
  1208
    ::free_message(msg_dst);
Thomas@285
  1209
    ::free_message(_src);
Thomas@285
  1210
Thomas@285
  1211
    if (status == PEP_OUT_OF_MEMORY)
Thomas@285
  1212
        return E_OUTOFMEMORY;
Thomas@285
  1213
Thomas@285
  1214
    // COM-41: Enhanced PEP status handling
Thomas@285
  1215
    if ((status != PEP_STATUS_OK) && (status < PEP_UNENCRYPTED || status >= PEP_TRUSTWORD_NOT_FOUND))
Thomas@285
  1216
        return FAIL("Failure to encrypt message", status);
Thomas@285
  1217
Thomas@285
  1218
    // Statii like PEP_UNENCRYPTED due to no private key
Thomas@285
  1219
    // should not be a catastrophic failure here. Using S_FALSE
Thomas@285
  1220
    // still allows clients to differentiate with S_OK,
Thomas@285
  1221
    // although this does not work out of the box with
Thomas@285
  1222
    // the standard .NET mapping of COM.
Thomas@285
  1223
    if (status != PEP_STATUS_OK)
Thomas@285
  1224
        return S_FALSE;
Thomas@285
  1225
Thomas@285
  1226
    return S_OK;
Thomas@285
  1227
}
Thomas@285
  1228
vb@282
  1229
STDMETHODIMP CpEpEngine::EncryptMessageForSelf(pEpIdentity * targetId, TextMessage * src,
vb@282
  1230
    /* [in] */ SAFEARRAY *extra, TextMessage * dst, pEpEncryptFlags flags)
vb@282
  1231
{
vb@282
  1232
    assert(targetId);
vb@282
  1233
    assert(src);
vb@282
  1234
    assert(dst);
vb@282
  1235
vb@282
  1236
    if (!(targetId && src && dst))
vb@282
  1237
        return E_INVALIDARG;
vb@282
  1238
vb@282
  1239
    PEP_encrypt_flags_t engineFlags = (PEP_encrypt_flags_t)flags;
vb@282
  1240
vb@282
  1241
    ::pEp_identity *_target_id = new_identity(targetId);
vb@282
  1242
Thomas@364
  1243
    ::message *_src = NULL;
Thomas@364
  1244
    try {
Thomas@364
  1245
        _src = text_message_to_C(src);
Thomas@364
  1246
    }
Thomas@364
  1247
    catch (bad_alloc&) {
Thomas@364
  1248
        return E_OUTOFMEMORY;
Thomas@364
  1249
    }
Thomas@364
  1250
    catch (exception& ex) {
Thomas@364
  1251
        return FAIL(ex.what());
Thomas@364
  1252
    }
vb@282
  1253
vb@282
  1254
    ::stringlist_t* _extra = NULL;
vb@282
  1255
    HRESULT result = S_OK;
vb@282
  1256
    ::message *msg_dst = NULL;
vb@282
  1257
    PEP_STATUS status = PEP_STATUS_OK;
vb@282
  1258
vb@282
  1259
    try {
vb@282
  1260
        if (extra) {
vb@282
  1261
            _extra = new_stringlist(extra);
vb@282
  1262
        }
vb@282
  1263
vb@282
  1264
        // COM-19: Initialize msg_dst to NULL, or we end up calling
vb@282
  1265
        // free_message() below with a pointer to random garbage in
vb@282
  1266
        // case of an error in encrypt_message_for_self().
vb@295
  1267
        status = ::encrypt_message_for_self(session(), _target_id, _src, _extra, &msg_dst, PEP_enc_PEP, engineFlags);
vb@282
  1268
vb@282
  1269
        if (status == PEP_STATUS_OK)
vb@282
  1270
            text_message_from_C(dst, msg_dst);
vb@282
  1271
        else
vb@282
  1272
            text_message_from_C(dst, _src);
vb@282
  1273
    } catch (bad_alloc&) {
vb@282
  1274
        result = E_OUTOFMEMORY;
vb@282
  1275
    }
vb@282
  1276
    catch (exception& ex) {
vb@282
  1277
        result = FAIL(ex.what());
vb@282
  1278
    }
vb@282
  1279
vb@282
  1280
    ::free_message(msg_dst);
vb@282
  1281
    ::free_message(_src);
vb@282
  1282
    ::free_identity(_target_id);
vb@282
  1283
    ::free_stringlist(_extra);
vb@282
  1284
vb@282
  1285
    if (status == PEP_OUT_OF_MEMORY)
vb@282
  1286
        return E_OUTOFMEMORY;
vb@282
  1287
vb@282
  1288
    // Different to encrypt_message, this should never fail (we ought to always
vb@282
  1289
    // have a private key for ourself).#
vb@282
  1290
    if (status != PEP_STATUS_OK)
vb@282
  1291
        return FAIL("Failure to encrypt message", status);
vb@282
  1292
vb@282
  1293
    return result;
vb@282
  1294
}
vb@282
  1295
vb@282
  1296
STDMETHODIMP CpEpEngine::DecryptMessage(TextMessage * src, TextMessage * dst, SAFEARRAY ** keylist, pEpDecryptFlags *flags, pEpRating *rating)
vb@282
  1297
{
vb@282
  1298
    assert(src);
vb@282
  1299
    assert(dst);
vb@282
  1300
    assert(keylist);
vb@282
  1301
    assert(flags);
vb@282
  1302
    assert(rating);
vb@282
  1303
vb@282
  1304
    if (!(src && dst && keylist && flags && rating))
vb@282
  1305
        return E_INVALIDARG;
vb@282
  1306
vb@282
  1307
    *rating = pEpRatingUndefined;
vb@282
  1308
Thomas@364
  1309
    ::message *_src = NULL;
Thomas@364
  1310
    try {
Thomas@364
  1311
        _src = text_message_to_C(src);
Thomas@364
  1312
    }
Thomas@364
  1313
    catch (bad_alloc&) {
Thomas@364
  1314
        return E_OUTOFMEMORY;
Thomas@364
  1315
    }
Thomas@364
  1316
    catch (exception& ex) {
Thomas@364
  1317
        return FAIL(ex.what());
Thomas@364
  1318
    }
vb@282
  1319
    ::message *msg_dst = NULL;
Thomas@289
  1320
    ::stringlist_t *_keylist = new_stringlist(*keylist);
vb@282
  1321
    ::PEP_rating _rating;
vb@282
  1322
vb@282
  1323
    PEP_decrypt_flags_t engineflags = (PEP_decrypt_flags_t) *flags;
vb@295
  1324
    PEP_STATUS status = ::decrypt_message(session(), _src, &msg_dst, &_keylist, &_rating, &engineflags);
vb@282
  1325
vb@282
  1326
    *flags = (pEpDecryptFlags)engineflags;
vb@282
  1327
Thomas@334
  1328
    if (_src)
vb@282
  1329
        text_message_from_C(src, _src);
vb@282
  1330
vb@282
  1331
    if (msg_dst)
vb@282
  1332
        text_message_from_C(dst, msg_dst);
vb@282
  1333
vb@282
  1334
    ::free_message(_src);
vb@282
  1335
    ::free_message(msg_dst);
vb@282
  1336
vb@282
  1337
    if (_keylist) {
vb@282
  1338
        *keylist = string_array(_keylist);
vb@282
  1339
        free_stringlist(_keylist);
vb@282
  1340
    }
vb@282
  1341
vb@282
  1342
    *rating = (pEpRating)_rating;
vb@282
  1343
vb@282
  1344
    return S_OK;
vb@282
  1345
}
vb@282
  1346
vb@282
  1347
STDMETHODIMP CpEpEngine::ReEvaluateMessageRating(TextMessage * msg, SAFEARRAY * x_KeyList, pEpRating x_EncStatus, pEpRating *rating)
vb@282
  1348
{
vb@282
  1349
    assert(msg);
vb@282
  1350
    assert(x_EncStatus != PEP_rating_undefined);
vb@282
  1351
    assert(rating);
vb@282
  1352
vb@282
  1353
    if (!(msg && x_EncStatus != PEP_rating_undefined && rating))
vb@282
  1354
        return E_INVALIDARG;
vb@282
  1355
vb@282
  1356
    *rating = pEpRatingUndefined;
vb@282
  1357
Thomas@364
  1358
    ::message *_msg = NULL;
Thomas@364
  1359
    try {
Thomas@364
  1360
        _msg = text_message_to_C(msg);
Thomas@364
  1361
    }
Thomas@364
  1362
    catch (bad_alloc&) {
Thomas@364
  1363
        return E_OUTOFMEMORY;
Thomas@364
  1364
    }
Thomas@364
  1365
    catch (exception& ex) {
Thomas@364
  1366
        return FAIL(ex.what());
Thomas@364
  1367
    }
Thomas@364
  1368
vb@282
  1369
    ::stringlist_t *_keylist = new_stringlist(x_KeyList);
vb@282
  1370
    ::PEP_rating _rating = PEP_rating_undefined;
vb@282
  1371
vb@295
  1372
    PEP_STATUS status = ::re_evaluate_message_rating(session(), _msg, _keylist, (PEP_rating)x_EncStatus, &_rating);
vb@282
  1373
vb@282
  1374
    ::free_stringlist(_keylist);
vb@282
  1375
    ::free_message(_msg);
vb@282
  1376
vb@282
  1377
    *rating = (pEpRating)_rating;
vb@282
  1378
vb@282
  1379
    return S_OK;
vb@282
  1380
}
vb@282
  1381
vb@282
  1382
STDMETHODIMP CpEpEngine::OutgoingMessageRating(TextMessage *msg, pEpRating * pVal)
vb@282
  1383
{
vb@282
  1384
    assert(msg);
vb@282
  1385
    assert(pVal);
vb@282
  1386
vb@282
  1387
    if (!(msg  && pVal))
vb@282
  1388
        return E_INVALIDARG;
vb@282
  1389
Thomas@364
  1390
    ::message *_msg = NULL;
Thomas@364
  1391
    try {
Thomas@364
  1392
        _msg = text_message_to_C(msg);
Thomas@364
  1393
    }
Thomas@364
  1394
    catch (bad_alloc&) {
Thomas@364
  1395
        return E_OUTOFMEMORY;
Thomas@364
  1396
    }
Thomas@364
  1397
    catch (exception& ex) {
Thomas@364
  1398
        return FAIL(ex.what());
Thomas@364
  1399
    }
vb@282
  1400
vb@282
  1401
    PEP_rating _rating;
vb@295
  1402
    PEP_STATUS status = ::outgoing_message_rating(session(), _msg, &_rating);
vb@282
  1403
    if (status != PEP_STATUS_OK)
vb@282
  1404
        return FAIL(L"cannot get message rating", status);
vb@282
  1405
vb@282
  1406
    *pVal = (pEpRating)_rating;
vb@282
  1407
    return S_OK;
vb@282
  1408
}
vb@282
  1409
Thomas@292
  1410
STDMETHODIMP CpEpEngine::OutgoingMessageRatingPreview(TextMessage *msg, pEpRating * pVal)
Thomas@292
  1411
{
Thomas@364
  1412
    assert(msg);
Thomas@364
  1413
    assert(pVal);
Thomas@292
  1414
Thomas@364
  1415
    if (!(msg  && pVal))
Thomas@364
  1416
        return E_INVALIDARG;
Thomas@292
  1417
Thomas@364
  1418
    ::message *_msg = NULL;
Thomas@364
  1419
    try {
Thomas@364
  1420
        _msg = text_message_to_C(msg);
Thomas@364
  1421
    }
Thomas@364
  1422
    catch (bad_alloc&) {
Thomas@364
  1423
        return E_OUTOFMEMORY;
Thomas@364
  1424
    }
Thomas@364
  1425
    catch (exception& ex) {
Thomas@364
  1426
        return FAIL(ex.what());
Thomas@364
  1427
    }
Thomas@292
  1428
Thomas@364
  1429
    PEP_rating _rating;
Thomas@364
  1430
    PEP_STATUS status = ::outgoing_message_rating_preview(session(), _msg, &_rating);
Thomas@364
  1431
    if (status != PEP_STATUS_OK)
Thomas@364
  1432
        return FAIL(L"cannot get message rating", status);
Thomas@292
  1433
Thomas@364
  1434
    *pVal = (pEpRating)_rating;
Thomas@364
  1435
    return S_OK;
Thomas@292
  1436
}
Thomas@292
  1437
vb@282
  1438
STDMETHODIMP CpEpEngine::IdentityRating(struct pEpIdentity *ident, pEpRating * pVal)
vb@282
  1439
{
vb@282
  1440
    ::pEp_identity *_ident;
vb@282
  1441
vb@282
  1442
    assert(ident);
vb@282
  1443
    assert(pVal);
vb@282
  1444
vb@282
  1445
    if (!(ident  && pVal))
vb@282
  1446
        return E_INVALIDARG;
vb@282
  1447
vb@282
  1448
    try {
vb@282
  1449
        _ident = new_identity(ident);
vb@282
  1450
    }
vb@282
  1451
    catch (bad_alloc&) {
vb@282
  1452
        return E_OUTOFMEMORY;
vb@282
  1453
    }
vb@282
  1454
    catch (exception& ex) {
vb@282
  1455
        return FAIL(ex.what());;
vb@282
  1456
    }
vb@282
  1457
vb@282
  1458
    PEP_rating _rating;
vb@295
  1459
    PEP_STATUS status = ::identity_rating(session(), _ident, &_rating);
vb@282
  1460
    free_identity(_ident);
vb@282
  1461
vb@282
  1462
    if (status != PEP_STATUS_OK)
vb@282
  1463
        return FAIL(L"cannot get message color", status);
vb@282
  1464
vb@282
  1465
    *pVal = (pEpRating)_rating;
vb@282
  1466
    return S_OK;
vb@282
  1467
}
vb@282
  1468
vb@282
  1469
STDMETHODIMP CpEpEngine::ColorFromRating(pEpRating rating, pEpColor * pVal)
vb@282
  1470
{
vb@282
  1471
    assert(pVal);
vb@282
  1472
vb@282
  1473
    if (!pVal)
vb@282
  1474
        return E_INVALIDARG;
vb@282
  1475
vb@282
  1476
    PEP_rating engineRating = (PEP_rating)rating;
vb@282
  1477
    PEP_color _color = ::color_from_rating(engineRating);
vb@282
  1478
vb@282
  1479
    *pVal = (pEpColor)_color;
Thomas@364
  1480
     
vb@282
  1481
    return S_OK;
vb@282
  1482
}
vb@282
  1483
vb@282
  1484
STDMETHODIMP CpEpEngine::OwnIdentitiesRetrieve(LPSAFEARRAY* ownIdentities)
vb@282
  1485
{
vb@282
  1486
    assert(ownIdentities);
vb@282
  1487
    if (!ownIdentities)
vb@282
  1488
        return E_INVALIDARG;
vb@282
  1489
vb@282
  1490
    *ownIdentities = nullptr;
vb@282
  1491
vb@282
  1492
    ::identity_list *il = nullptr;
vb@295
  1493
    PEP_STATUS status = ::own_identities_retrieve(session(), &il);
vb@282
  1494
    if (status == PEP_OUT_OF_MEMORY) {
vb@282
  1495
        return E_OUTOFMEMORY;
vb@282
  1496
    }
vb@282
  1497
    else if (status != PEP_STATUS_OK)
vb@282
  1498
    {
vb@282
  1499
        return FAIL(_T("OwnIdentitiesRetrieve"), status);
vb@282
  1500
    }
vb@282
  1501
vb@282
  1502
    SAFEARRAY * _own_identities = nullptr;
vb@282
  1503
    try {
vb@282
  1504
        _own_identities = array_from_C<pEpIdentity, identity_list>(il);
vb@282
  1505
    }
vb@282
  1506
    catch (exception& ex)
vb@282
  1507
    {
vb@282
  1508
        ::free_identity_list(il);
vb@282
  1509
        try {
vb@282
  1510
            dynamic_cast<bad_alloc&>(ex);
vb@282
  1511
        }
vb@282
  1512
        catch (bad_cast&)
vb@282
  1513
        {
vb@282
  1514
            return FAIL(ex.what());
vb@282
  1515
        }
vb@282
  1516
        return E_OUTOFMEMORY;
vb@282
  1517
    }
vb@282
  1518
    free_identity_list(il);
vb@282
  1519
vb@282
  1520
    *ownIdentities = _own_identities;
vb@282
  1521
    return S_OK;
vb@282
  1522
}
vb@282
  1523
vb@282
  1524
STDMETHODIMP CpEpEngine::TrustPersonalKey(struct pEpIdentity *ident, struct pEpIdentity *result)
vb@282
  1525
{
vb@282
  1526
    ::pEp_identity *_ident;
vb@282
  1527
vb@282
  1528
    assert(ident);
vb@282
  1529
    assert(result);
vb@282
  1530
vb@282
  1531
    if (!ident || !result)
vb@282
  1532
        return E_INVALIDARG;
vb@282
  1533
vb@282
  1534
    try {
vb@282
  1535
        _ident = new_identity(ident);
vb@282
  1536
    }
vb@282
  1537
    catch (bad_alloc&) {
vb@282
  1538
        return E_OUTOFMEMORY;
vb@282
  1539
    }
vb@282
  1540
    catch (exception& ex) {
vb@282
  1541
        return FAIL(ex.what());;
vb@282
  1542
    }
vb@282
  1543
vb@282
  1544
    if (verbose_mode) {
vb@282
  1545
        stringstream ss;
vb@282
  1546
        ss << "TrustPersonalKey called with ";
vb@282
  1547
        ss << utf8_string(ident->Address);
vb@282
  1548
        ss << L": ";
vb@282
  1549
        ss << ident->CommType;
vb@282
  1550
        verbose(ss.str());
vb@282
  1551
    }
vb@282
  1552
vb@295
  1553
    PEP_STATUS status = ::trust_personal_key(session(), _ident);
vb@282
  1554
vb@282
  1555
    if (verbose_mode) {
vb@282
  1556
        stringstream ss;
vb@282
  1557
        ss << "result ";
vb@282
  1558
        ss << status;
vb@282
  1559
        ss << " for ";
vb@282
  1560
        ss << _ident->address;
vb@282
  1561
        ss << L": ";
vb@282
  1562
        ss << _ident->comm_type;
vb@282
  1563
        verbose(ss.str());
vb@282
  1564
    }
vb@282
  1565
vb@282
  1566
    if (status == PEP_STATUS_OK)
vb@282
  1567
        copy_identity(result, _ident);
vb@282
  1568
vb@282
  1569
    free_identity(_ident);
vb@282
  1570
    if (status == PEP_OUT_OF_MEMORY)
vb@282
  1571
        return E_OUTOFMEMORY;
vb@282
  1572
    else if (status != PEP_STATUS_OK)
vb@282
  1573
        return FAIL(L"failure while executing TrustPersonalKey()", status);
vb@282
  1574
vb@282
  1575
    return S_OK;
vb@282
  1576
}
vb@282
  1577
Thomas@285
  1578
// Force an update check now
Thomas@368
  1579
STDMETHODIMP CpEpEngine::UpdateNow(BSTR productCode, VARIANT_BOOL *didUpdate)
Thomas@285
  1580
{
Thomas@371
  1581
    BOOL result = FALSE;
vb@366
  1582
Thomas@371
  1583
    try
Thomas@285
  1584
    {
Thomas@371
  1585
        _bstr_t pc(productCode);
Thomas@371
  1586
        wstring _pc = pc;
vb@366
  1587
Thomas@371
  1588
        auto products = pEp::GateKeeper::gatekeeper()->registered_products();
Thomas@371
  1589
        for (auto p = products.begin(); p != products.end(); ++p) {
Thomas@371
  1590
            if (_pc == p->first) {
Thomas@371
  1591
                result = pEp::GateKeeper::gatekeeper()->update_product(*p);
Thomas@371
  1592
                break;
Thomas@371
  1593
            }
Thomas@371
  1594
        }
Thomas@371
  1595
    }
Thomas@285
  1596
    catch (bad_alloc&) {
Thomas@371
  1597
        return E_OUTOFMEMORY;
Thomas@285
  1598
    }
Thomas@285
  1599
    catch (exception& ex) {
Thomas@371
  1600
        return FAIL(ex.what());;
Thomas@285
  1601
    }
vb@295
  1602
Thomas@371
  1603
    *didUpdate = result;
Thomas@371
  1604
    return S_OK;
Thomas@285
  1605
}
vb@282
  1606
vb@282
  1607
// Event callbacks
vb@282
  1608
vb@282
  1609
STDMETHODIMP CpEpEngine::RegisterCallbacks(IpEpEngineCallbacks* new_callbacks)
vb@282
  1610
{
vb@282
  1611
    // check for valid parameter
vb@282
  1612
    if (!new_callbacks)
vb@282
  1613
        return E_INVALIDARG;
vb@282
  1614
vb@282
  1615
    // don't allow double registration.
vb@282
  1616
    if (this->client_callbacks)
vb@282
  1617
        return E_ILLEGAL_STATE_CHANGE;
vb@282
  1618
vb@282
  1619
    this->client_callbacks = new_callbacks;
vb@282
  1620
    new_callbacks->AddRef();
vb@282
  1621
vb@297
  1622
    // provide callbacks to sync
vb@319
  1623
    LPSTREAM marshaled_callbacks = nullptr;
vb@297
  1624
    auto result = CoMarshalInterThreadInterfaceInStream(IID_IpEpEngineCallbacks, client_callbacks, &marshaled_callbacks);
vb@297
  1625
    assert(SUCCEEDED(result));
vb@297
  1626
    assert(marshaled_callbacks);
vb@297
  1627
    sync_callbacks.insert(new MarshaledCallbacks({ this->client_callbacks, marshaled_callbacks }));
vb@282
  1628
vb@282
  1629
    return S_OK;
vb@282
  1630
}
vb@282
  1631
vb@282
  1632
STDMETHODIMP CpEpEngine::UnregisterCallbacks()
vb@282
  1633
{
vb@282
  1634
    // don't allow double deregistration.
vb@282
  1635
    // S_FALSE still is no error (as double deregistration is not fatal).
vb@282
  1636
    if (!this->client_callbacks)
vb@282
  1637
        return S_FALSE;
vb@282
  1638
vb@297
  1639
    for (auto p = sync_callbacks.begin(); p != sync_callbacks.end(); ++p) {
vb@317
  1640
        if (p->pdata && p->pdata->unmarshaled == this->client_callbacks) {
vb@315
  1641
            if (p->pdata->marshaled)
vb@315
  1642
                p->pdata->marshaled->Release();
vb@315
  1643
            if (p->pdata->unmarshaled)
vb@315
  1644
                p->pdata->unmarshaled->Release();
vb@297
  1645
            delete p->pdata;
vb@315
  1646
            p->pdata = nullptr;
vb@297
  1647
            break;
vb@295
  1648
        }
vb@295
  1649
    }
vb@282
  1650
vb@282
  1651
    this->client_callbacks->Release();
vb@315
  1652
    this->client_callbacks = nullptr;
vb@282
  1653
vb@282
  1654
    return S_OK;
vb@282
  1655
}
vb@282
  1656
vb@282
  1657
STDMETHODIMP CpEpEngine::OpenPGPListKeyinfo(BSTR search_pattern, LPSAFEARRAY* keyinfo_list) {
vb@282
  1658
    assert(keyinfo_list);
vb@282
  1659
vb@282
  1660
    if (keyinfo_list == NULL)
vb@282
  1661
        return E_INVALIDARG;
vb@282
  1662
vb@282
  1663
    string _pattern = "";
vb@282
  1664
    if (search_pattern)
vb@282
  1665
        _pattern = utf8_string(search_pattern);
vb@282
  1666
    ::stringpair_list_t* _keyinfo_list = NULL;
vb@282
  1667
vb@295
  1668
    PEP_STATUS status = ::OpenPGP_list_keyinfo(session(), _pattern.c_str(), &_keyinfo_list);
vb@282
  1669
    assert(status != PEP_OUT_OF_MEMORY);
vb@282
  1670
    if (status == PEP_OUT_OF_MEMORY)
vb@282
  1671
        return E_OUTOFMEMORY;
vb@282
  1672
vb@295
  1673
    if (status != PEP_STATUS_OK)
vb@282
  1674
        return FAIL(L"OpenPGP_list_keyinfo", status);
vb@282
  1675
vb@282
  1676
    if (_keyinfo_list && _keyinfo_list->value) {
vb@282
  1677
        ::opt_field_array_from_C(_keyinfo_list, keyinfo_list);
vb@282
  1678
    }
vb@282
  1679
    else {
vb@282
  1680
        ::free_stringpair_list(_keyinfo_list);
vb@282
  1681
        return FAIL(L"OpenPGP_list_keyinfo: no keys found");
vb@282
  1682
    }
vb@282
  1683
vb@282
  1684
    ::free_stringpair_list(_keyinfo_list);
vb@282
  1685
    return S_OK;
vb@282
  1686
vb@282
  1687
}
vb@282
  1688
vb@282
  1689
STDMETHODIMP CpEpEngine::SetOwnKey(pEpIdentity * ident, BSTR fpr, struct pEpIdentity *result)
vb@282
  1690
{
Thomas@364
  1691
    assert(ident);
Thomas@364
  1692
    assert(result);
Thomas@364
  1693
    assert(fpr);
vb@282
  1694
Thomas@364
  1695
    if (!(ident && result))
Thomas@364
  1696
        return E_INVALIDARG;
vb@282
  1697
Thomas@364
  1698
    ::pEp_identity *_ident;
Thomas@364
  1699
    try {
Thomas@364
  1700
        _ident = new_identity(ident);
Thomas@364
  1701
    }
Thomas@364
  1702
    catch (bad_alloc&) {
Thomas@364
  1703
        return E_OUTOFMEMORY;
Thomas@364
  1704
    }
Thomas@364
  1705
    catch (exception& ex) {
Thomas@364
  1706
        return FAIL(ex.what());
Thomas@364
  1707
    }
vb@282
  1708
Thomas@364
  1709
    assert(_ident);
Thomas@364
  1710
    if (_ident == NULL)
Thomas@364
  1711
        return E_OUTOFMEMORY;
vb@282
  1712
Thomas@364
  1713
    string _fpr = utf8_string(fpr);
Thomas@364
  1714
    PEP_STATUS status = ::set_own_key(session(), _ident, _fpr.c_str());
vb@282
  1715
Thomas@364
  1716
    if (status == PEP_STATUS_OK) {
Thomas@364
  1717
        copy_identity(result, _ident);
Thomas@364
  1718
        ::free_identity(_ident);
Thomas@364
  1719
        return S_OK;
Thomas@364
  1720
    }
Thomas@364
  1721
    else {
Thomas@364
  1722
        ::free_identity(_ident);
Thomas@364
  1723
        if (status == PEP_OUT_OF_MEMORY)
Thomas@364
  1724
            return E_OUTOFMEMORY;
Thomas@364
  1725
        else
Thomas@364
  1726
            return FAIL(L"SetOwnKey", status);
Thomas@364
  1727
    }
vb@282
  1728
Thomas@364
  1729
    return S_OK;
vb@282
  1730
}
vb@282
  1731
Thomas@327
  1732
STDMETHODIMP CpEpEngine::TrustOwnKey(pEpIdentity * ident)
Thomas@327
  1733
{
Thomas@364
  1734
    assert(ident);
Thomas@327
  1735
Thomas@364
  1736
    if (!ident)
Thomas@364
  1737
        return E_INVALIDARG;
Thomas@327
  1738
Thomas@364
  1739
    ::pEp_identity *_ident;
Thomas@364
  1740
    try {
Thomas@364
  1741
        _ident = new_identity(ident);
Thomas@364
  1742
    }
Thomas@364
  1743
    catch (bad_alloc&) {
Thomas@364
  1744
        return E_OUTOFMEMORY;
Thomas@364
  1745
    }
Thomas@364
  1746
    catch (exception& ex) {
Thomas@364
  1747
        return FAIL(ex.what());
Thomas@364
  1748
    }
Thomas@327
  1749
Thomas@364
  1750
    assert(_ident);
Thomas@364
  1751
    if (_ident == NULL)
Thomas@364
  1752
        return E_OUTOFMEMORY;
Thomas@327
  1753
Thomas@364
  1754
    PEP_STATUS status = ::trust_own_key(session(), _ident);
Thomas@327
  1755
Thomas@364
  1756
    ::free_identity(_ident);
Thomas@327
  1757
Thomas@364
  1758
    if (status == PEP_STATUS_OK)
Thomas@364
  1759
        return S_OK;
Thomas@364
  1760
    else if (status == PEP_OUT_OF_MEMORY)
Thomas@364
  1761
        return E_OUTOFMEMORY;
Thomas@364
  1762
    else
Thomas@364
  1763
        return FAIL(L"TrustOwnKey", status);
Thomas@327
  1764
}
Thomas@327
  1765
Thomas@322
  1766
STDMETHODIMP CpEpEngine::Startup()
vb@282
  1767
{
Thomas@364
  1768
    try
Thomas@364
  1769
    {
Thomas@364
  1770
        startup<CpEpEngine>(messageToSend, notifyHandshake, this, &CpEpEngine::Startup_sync, &CpEpEngine::Shutdown_sync);
Thomas@364
  1771
    }
Thomas@364
  1772
    catch (bad_alloc&) {
Thomas@364
  1773
        return E_OUTOFMEMORY;
Thomas@364
  1774
    }
Thomas@364
  1775
    catch (exception& ex) {
Thomas@364
  1776
        return FAIL(ex.what());
Thomas@364
  1777
    }
vb@282
  1778
Thomas@364
  1779
    return S_OK;
vb@282
  1780
}
vb@282
  1781
Thomas@349
  1782
STDMETHODIMP CpEpEngine::GetKeyRating(BSTR fpr, pEpComType *commType)
Thomas@349
  1783
{
Thomas@364
  1784
    assert(fpr);
Thomas@349
  1785
Thomas@364
  1786
    if (!fpr)
Thomas@364
  1787
        return E_INVALIDARG;
Thomas@349
  1788
Thomas@364
  1789
    string _fpr = utf8_string(fpr);
Thomas@349
  1790
Thomas@364
  1791
    PEP_comm_type _commType;
Thomas@364
  1792
    PEP_STATUS status = ::get_key_rating(session(), _fpr.c_str(), &_commType);
Thomas@364
  1793
    if (status != PEP_STATUS_OK)
Thomas@364
  1794
        return FAIL(L"cannot get key rating", status);
Thomas@349
  1795
Thomas@364
  1796
    *commType = (pEpComType)_commType;
Thomas@349
  1797
Thomas@364
  1798
    return S_OK;
Thomas@349
  1799
}
Thomas@349
  1800
Thomas@330
  1801
STDMETHODIMP CpEpEngine::GetKeyRatingForUser(BSTR userId, BSTR fpr, pEpRating *rating)
vb@282
  1802
{
Thomas@364
  1803
    assert(userId);
Thomas@364
  1804
    assert(fpr);
vb@282
  1805
Thomas@364
  1806
    if (!(userId && fpr))
Thomas@364
  1807
        return E_INVALIDARG;
vb@282
  1808
Thomas@364
  1809
    string user_id = utf8_string(userId);
Thomas@364
  1810
    string _fpr = utf8_string(fpr);
vb@282
  1811
Thomas@364
  1812
    PEP_rating _rating;
Thomas@364
  1813
    PEP_STATUS status = ::get_key_rating_for_user(session(), user_id.c_str(), _fpr.c_str(), &_rating);
Thomas@364
  1814
    if (status != PEP_STATUS_OK)
Thomas@364
  1815
        return FAIL(L"cannot get key rating for user", status);
vb@282
  1816
Thomas@364
  1817
    *rating = (pEpRating)_rating;
vb@282
  1818
Thomas@364
  1819
    return S_OK;
vb@338
  1820
}
vb@338
  1821
vb@363
  1822
STDMETHODIMP CpEpEngine::DeliverHandshakeResult(enum SyncHandshakeResult result, SAFEARRAY *identities_sharing)
vb@363
  1823
{
Thomas@364
  1824
    sync_handshake_result _result = (sync_handshake_result)result;
Thomas@364
  1825
    identity_list *_identities_sharing = NULL;
Thomas@364
  1826
    if (identities_sharing)
Thomas@364
  1827
    {
Thomas@364
  1828
        try {
Thomas@364
  1829
            _identities_sharing = identities(identities_sharing);
Thomas@364
  1830
        }
Thomas@364
  1831
        catch (bad_alloc&) {
Thomas@364
  1832
            return E_OUTOFMEMORY;
Thomas@364
  1833
        }
Thomas@364
  1834
    }
vb@363
  1835
Thomas@364
  1836
    PEP_STATUS status = ::deliverHandshakeResult(session(), _result, _identities_sharing);
Thomas@364
  1837
    free_identity_list(_identities_sharing);
Thomas@364
  1838
    switch (status) {
Thomas@364
  1839
    case PEP_STATUS_OK:
Thomas@364
  1840
        break;
Thomas@364
  1841
    case PEP_OUT_OF_MEMORY:
Thomas@364
  1842
        return E_OUTOFMEMORY;
Thomas@364
  1843
    default:
Thomas@364
  1844
        return FAIL(L"deliverHandshakeResult is reporting an error", status);
Thomas@364
  1845
    }
vb@363
  1846
Thomas@364
  1847
    return S_OK;
vb@363
  1848
}
vb@363
  1849
vb@363
  1850
STDMETHODIMP CpEpEngine::PERToXERSyncMessage(TextMessage *msg, BSTR * xer)
vb@363
  1851
{
Thomas@364
  1852
    assert(msg);
Thomas@352
  1853
Thomas@364
  1854
    if (!msg)
Thomas@364
  1855
        return E_INVALIDARG;
Thomas@352
  1856
Thomas@364
  1857
    ::message *_msg = NULL;
Thomas@364
  1858
    try {
Thomas@364
  1859
        _msg = text_message_to_C(msg);
Thomas@364
  1860
    }
Thomas@364
  1861
    catch (bad_alloc&) {
Thomas@364
  1862
        return E_OUTOFMEMORY;
Thomas@364
  1863
    }
Thomas@364
  1864
    catch (exception& ex) {
Thomas@364
  1865
        return FAIL(ex.what());
Thomas@364
  1866
    }
vb@363
  1867
Thomas@364
  1868
    char* text;
Thomas@364
  1869
    char* val = _msg->attachments->value;
vb@363
  1870
Thomas@364
  1871
    PEP_STATUS status = ::PER_to_XER_Sync_msg(val, strlen(val), &text);
Thomas@364
  1872
    free_message(_msg);
vb@363
  1873
Thomas@364
  1874
    if (status != PEP_STATUS_OK)
Thomas@364
  1875
        return FAIL(L"cannot get XER", status);
vb@363
  1876
Thomas@364
  1877
    *xer = utf16_bstr(text);
Thomas@364
  1878
    pEp_free(text);
Thomas@364
  1879
Thomas@364
  1880
    return S_OK;
vb@363
  1881
}
vb@363
  1882
vb@363
  1883
STDMETHODIMP CpEpEngine::DisableIdentityForSync(struct pEpIdentity * ident)
vb@363
  1884
{
Thomas@364
  1885
    assert(ident);
Thomas@357
  1886
Thomas@364
  1887
    if (!ident)
Thomas@364
  1888
        return E_INVALIDARG;
Thomas@357
  1889
Thomas@364
  1890
    ::pEp_identity *_ident;
Thomas@364
  1891
    try {
Thomas@364
  1892
        _ident = new_identity(ident);
Thomas@364
  1893
    }
Thomas@364
  1894
    catch (bad_alloc&) {
Thomas@364
  1895
        return E_OUTOFMEMORY;
Thomas@364
  1896
    }
Thomas@364
  1897
    catch (exception& ex) {
Thomas@364
  1898
        return FAIL(ex.what());
Thomas@364
  1899
    }
Thomas@357
  1900
Thomas@364
  1901
    assert(_ident);
Thomas@364
  1902
    if (_ident == NULL)
Thomas@364
  1903
        return E_OUTOFMEMORY;
Thomas@357
  1904
Thomas@364
  1905
    PEP_STATUS status = ::disable_identity_for_sync(session(), _ident);
vb@363
  1906
Thomas@364
  1907
    ::free_identity(_ident);
Thomas@357
  1908
Thomas@364
  1909
    if (status == PEP_STATUS_OK)
Thomas@364
  1910
        return S_OK;
Thomas@364
  1911
    else if (status == PEP_OUT_OF_MEMORY)
Thomas@364
  1912
        return E_OUTOFMEMORY;
Thomas@364
  1913
    else
Thomas@364
  1914
        return FAIL(L"DisableIdentityForSync", status);
vb@363
  1915
}
vb@363
  1916
vb@363
  1917
STDMETHODIMP CpEpEngine::EnableIdentityForSync(struct pEpIdentity * ident)
vb@363
  1918
{
Thomas@364
  1919
    assert(ident);
Thomas@357
  1920
Thomas@364
  1921
    if (!ident)
Thomas@364
  1922
        return E_INVALIDARG;
Thomas@357
  1923
Thomas@364
  1924
    ::pEp_identity *_ident;
Thomas@364
  1925
    try {
Thomas@364
  1926
        _ident = new_identity(ident);
Thomas@364
  1927
    }
Thomas@364
  1928
    catch (bad_alloc&) {
Thomas@364
  1929
        return E_OUTOFMEMORY;
Thomas@364
  1930
    }
Thomas@364
  1931
    catch (exception& ex) {
Thomas@364
  1932
        return FAIL(ex.what());
Thomas@364
  1933
    }
Thomas@357
  1934
Thomas@364
  1935
    assert(_ident);
Thomas@364
  1936
    if (_ident == NULL)
Thomas@364
  1937
        return E_OUTOFMEMORY;
Thomas@357
  1938
Thomas@364
  1939
    PEP_STATUS status = ::enable_identity_for_sync(session(), _ident);
vb@363
  1940
Thomas@364
  1941
    ::free_identity(_ident);
Thomas@357
  1942
Thomas@364
  1943
    if (status == PEP_STATUS_OK)
Thomas@364
  1944
        return S_OK;
Thomas@364
  1945
    else if (status == PEP_OUT_OF_MEMORY)
Thomas@364
  1946
        return E_OUTOFMEMORY;
Thomas@364
  1947
    else
Thomas@364
  1948
        return FAIL(L"EnableIdentityForSync", status);
vb@363
  1949
}
vb@363
  1950
vb@363
  1951
STDMETHODIMP CpEpEngine::PerMachineDirectory(BSTR * directory)
vb@363
  1952
{
Thomas@364
  1953
    assert(directory);
Thomas@358
  1954
Thomas@364
  1955
    if (!directory)
Thomas@364
  1956
        return E_INVALIDARG;
Thomas@358
  1957
Thomas@364
  1958
    const char *_directory = ::per_machine_directory();
Thomas@358
  1959
Thomas@364
  1960
    if (_directory == NULL)
Thomas@364
  1961
        return FAIL(L"PerMachineDirectory: _directory is NULL");
Thomas@358
  1962
Thomas@364
  1963
    *directory = utf16_bstr(_directory);
Thomas@358
  1964
Thomas@364
  1965
    return S_OK;
vb@363
  1966
}
vb@363
  1967
vb@363
  1968
STDMETHODIMP CpEpEngine::PerUserDirectory(BSTR * directory)
vb@363
  1969
{
Thomas@364
  1970
    assert(directory);
Thomas@358
  1971
Thomas@364
  1972
    if (!directory)
Thomas@364
  1973
        return E_INVALIDARG;
Thomas@358
  1974
Thomas@364
  1975
    const char *_directory = ::per_user_directory();
Thomas@358
  1976
Thomas@364
  1977
    if (_directory == NULL)
Thomas@364
  1978
        return FAIL(L"PerUserDirectory: _directory is NULL");
Thomas@358
  1979
Thomas@364
  1980
    *directory = utf16_bstr(_directory);
Thomas@358
  1981
Thomas@364
  1982
    return S_OK;
vb@363
  1983
}
Thomas@365
  1984
Thomas@365
  1985
STDMETHODIMP CpEpEngine::RatingFromCommType(pEpComType commType, pEpRating * rating) 
Thomas@365
  1986
{
Thomas@365
  1987
    PEP_comm_type _comm_type = (PEP_comm_type)commType;
Thomas@365
  1988
    PEP_rating _rating = ::rating_from_comm_type(_comm_type);
Thomas@365
  1989
Thomas@365
  1990
    *rating = (pEpRating)_rating;
Thomas@365
  1991
Thomas@365
  1992
    return S_OK;
Thomas@365
  1993
}