CpEpEngine.cpp
author Thomas
Thu, 21 Nov 2019 17:27:18 +0100
branchsync
changeset 376 c29ae3e408a8
parent 375 fe31c63ea77d
child 377 f3db78b86204
permissions -rw-r--r--
Shut down sync before key reset and start up again afterwards
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@376
   829
    // We have to stop sync before resetting all own keys and enable it again afterwards
Thomas@376
   830
    ShutDownSync();
Thomas@376
   831
Thomas@364
   832
    PEP_STATUS status = ::key_reset_all_own_keys(session());
Thomas@336
   833
Thomas@376
   834
    Startup();
Thomas@376
   835
Thomas@364
   836
    if (status == PEP_OUT_OF_MEMORY)
Thomas@364
   837
        return E_OUTOFMEMORY;
Thomas@336
   838
Thomas@364
   839
    if (status != PEP_STATUS_OK)
Thomas@364
   840
        return FAIL(L"cannot reset all own keys", status);
Thomas@331
   841
Thomas@364
   842
    return S_OK;
Thomas@331
   843
}
Thomas@331
   844
vb@282
   845
STDMETHODIMP CpEpEngine::KeyResetTrust(struct pEpIdentity *ident)
vb@282
   846
{
vb@282
   847
    ::pEp_identity *_ident;
vb@282
   848
vb@282
   849
    assert(ident);
vb@282
   850
vb@282
   851
    if (!ident)
vb@282
   852
        return E_INVALIDARG;
vb@282
   853
vb@282
   854
    try {
vb@282
   855
        _ident = new_identity(ident);
vb@282
   856
    }
vb@282
   857
    catch (bad_alloc&) {
vb@282
   858
        return E_OUTOFMEMORY;
vb@282
   859
    }
vb@282
   860
    catch (exception& ex) {
vb@282
   861
        return FAIL(ex.what());;
vb@282
   862
    }
vb@282
   863
vb@295
   864
    PEP_STATUS status = ::key_reset_trust(session(), _ident);
vb@282
   865
    free_identity(_ident);
vb@282
   866
vb@282
   867
    if (status == PEP_OUT_OF_MEMORY)
vb@282
   868
        return E_OUTOFMEMORY;
vb@282
   869
vb@282
   870
    if (status == PEP_KEY_NOT_FOUND)
vb@282
   871
        return FAIL(L"key not found");
vb@282
   872
vb@295
   873
    if (status != PEP_STATUS_OK)
vb@282
   874
        return FAIL(L"cannot reset trust", status);
vb@282
   875
vb@282
   876
    return S_OK;
vb@282
   877
}
vb@282
   878
vb@282
   879
int CpEpEngine::examine_identity(pEp_identity *ident, void *management)
vb@282
   880
{
vb@282
   881
    assert(ident);
vb@282
   882
    assert(management);
vb@282
   883
    if (!(ident && management))
vb@282
   884
        return -1;
vb@282
   885
vb@282
   886
    CpEpEngine *me = (CpEpEngine *)management;
vb@282
   887
vb@282
   888
    if (me->identity_queue.load() == NULL)
vb@282
   889
        return 0;
vb@282
   890
vb@282
   891
    try {
vb@282
   892
        me->identity_queue.load()->push_back(ident);
vb@282
   893
    }
vb@282
   894
    catch (exception&) {
vb@282
   895
        return -1;
vb@282
   896
    }
vb@282
   897
vb@282
   898
    return 0;
vb@282
   899
}
vb@282
   900
vb@282
   901
::pEp_identity * CpEpEngine::retrieve_next_identity(void *management)
vb@282
   902
{
vb@282
   903
    assert(management);
vb@282
   904
    if (!management)
vb@282
   905
        return NULL;
vb@282
   906
vb@282
   907
    identity_queue_t *iq = (identity_queue_t *)management;
vb@282
   908
vb@282
   909
    do /* poll queue */ {
vb@282
   910
        if (iq->size())
vb@282
   911
            break;
vb@282
   912
        ::Sleep(100);
vb@282
   913
    } while (true);
vb@282
   914
vb@282
   915
    ::pEp_identity *_ident;
vb@282
   916
    pEp_identity_cpp& ident = iq->front();
vb@282
   917
vb@282
   918
    if (ident.address.size() == 0)
vb@282
   919
        return NULL;
vb@282
   920
vb@282
   921
    _ident = ident.to_pEp_identity();
vb@282
   922
    iq->pop_front();
vb@282
   923
vb@282
   924
    return _ident;
vb@282
   925
}
vb@282
   926
vb@312
   927
static IpEpEngineCallbacks * _unmarshaled_consumer(CpEpEngine::callback_container::Container::iterator p)
vb@308
   928
{
vb@310
   929
    if (!p->cdata && p->pdata && p->pdata->marshaled) {
vb@308
   930
        HRESULT r = CoGetInterfaceAndReleaseStream(p->pdata->marshaled, IID_IpEpEngineCallbacks, (LPVOID*) &p->cdata);
vb@308
   931
        if (!SUCCEEDED(r))
vb@308
   932
            throw runtime_error("_unmarshaled_consumer(): CoGetInterfaceAndReleaseStream() failed");
vb@308
   933
        p->pdata->marshaled = nullptr;
vb@308
   934
    }
vb@312
   935
    else if (p->cdata && !p->pdata) {
vb@312
   936
        p->cdata->Release();
vb@312
   937
        p->cdata = nullptr;
vb@312
   938
    }
vb@308
   939
vb@308
   940
    return p->cdata;
vb@308
   941
}
vb@308
   942
vb@307
   943
PEP_STATUS CpEpEngine::messageToSend(message *msg)
vb@282
   944
{
vb@282
   945
    assert(msg);
vb@295
   946
    if (!msg)
vb@282
   947
        return PEP_ILLEGAL_VALUE;
vb@282
   948
vb@307
   949
    bool in_sync = on_sync_thread();
vb@282
   950
vb@297
   951
    for (auto p = sync_callbacks.begin(); p != sync_callbacks.end(); ++p) {
vb@308
   952
        IpEpEngineCallbacks *cb = in_sync ? _unmarshaled_consumer(p) : p->pdata->unmarshaled;
vb@295
   953
vb@297
   954
        if (cb) {
vb@297
   955
            TextMessage _msg;
vb@297
   956
            memset(&_msg, 0, sizeof(TextMessage));
vb@295
   957
vb@297
   958
            text_message_from_C(&_msg, msg);
vb@297
   959
            HRESULT r = cb->MessageToSend(&_msg);
vb@297
   960
            assert(r == S_OK);
vb@297
   961
            clear_text_message(&_msg);
vb@297
   962
            if (r == E_OUTOFMEMORY)
vb@297
   963
                return PEP_OUT_OF_MEMORY;
vb@297
   964
            if (r != S_OK)
vb@297
   965
                return PEP_UNKNOWN_ERROR;
vb@297
   966
        }
vb@297
   967
    }
Thomas@292
   968
vb@313
   969
    sync_callbacks.compact();
vb@313
   970
vb@297
   971
    return PEP_STATUS_OK;
vb@297
   972
}
vb@297
   973
vb@307
   974
PEP_STATUS CpEpEngine::notifyHandshake(::pEp_identity *self, ::pEp_identity *partner, sync_handshake_signal signal)
vb@297
   975
{
vb@297
   976
    assert(self && partner);
vb@297
   977
    if (!(self && partner))
vb@297
   978
        return PEP_ILLEGAL_VALUE;
vb@297
   979
vb@307
   980
    bool in_sync = on_sync_thread();
vb@307
   981
vb@297
   982
    // fire all of them
vb@297
   983
    for (auto p = sync_callbacks.begin(); p != sync_callbacks.end(); ++p) {
vb@309
   984
        IpEpEngineCallbacks *cb = in_sync ? _unmarshaled_consumer(p) : p->pdata->unmarshaled;
vb@297
   985
vb@297
   986
        if (cb) {
vb@297
   987
            pEpIdentity _self;
vb@297
   988
            copy_identity(&_self, self);
vb@297
   989
            pEpIdentity _partner;
vb@297
   990
            copy_identity(&_partner, partner);
vb@297
   991
vb@297
   992
            SyncHandshakeSignal _signal = (SyncHandshakeSignal)signal;
vb@338
   993
            HRESULT r = cb->NotifyHandshake(&_self, &_partner, _signal);
vb@297
   994
            assert(r == S_OK);
vb@297
   995
            clear_identity_s(_self);
vb@297
   996
            clear_identity_s(_partner);
vb@297
   997
            if (r == E_OUTOFMEMORY)
vb@297
   998
                return PEP_OUT_OF_MEMORY;
vb@297
   999
        }
vb@297
  1000
    }
Thomas@292
  1001
vb@313
  1002
    sync_callbacks.compact();
vb@282
  1003
vb@282
  1004
    return PEP_STATUS_OK;
vb@282
  1005
}
vb@282
  1006
vb@282
  1007
STDMETHODIMP CpEpEngine::BlacklistAdd(BSTR fpr)
vb@282
  1008
{
vb@282
  1009
    assert(fpr);
vb@282
  1010
    if (!fpr)
vb@282
  1011
        return E_INVALIDARG;
vb@282
  1012
vb@282
  1013
    string _fpr = utf8_string(fpr);
vb@295
  1014
    PEP_STATUS status = ::blacklist_add(session(), _fpr.c_str());
vb@282
  1015
    assert(status == PEP_STATUS_OK);
vb@282
  1016
    if (status != PEP_STATUS_OK)
vb@282
  1017
        return FAIL(L"blacklist_add failed in pEp engine", status);
vb@282
  1018
vb@282
  1019
    return S_OK;
vb@282
  1020
}
vb@282
  1021
vb@282
  1022
STDMETHODIMP CpEpEngine::BlacklistDelete(BSTR fpr)
vb@282
  1023
{
vb@282
  1024
    assert(fpr);
vb@282
  1025
    if (!fpr)
vb@282
  1026
        return E_INVALIDARG;
vb@282
  1027
vb@282
  1028
    string _fpr = utf8_string(fpr);
vb@295
  1029
    PEP_STATUS status = ::blacklist_delete(session(), _fpr.c_str());
vb@282
  1030
    assert(status == PEP_STATUS_OK);
vb@282
  1031
    if (status != PEP_STATUS_OK)
vb@282
  1032
        return FAIL(L"blacklist_delete failed in pEp engine", status);
vb@282
  1033
vb@282
  1034
    return S_OK;
vb@282
  1035
}
vb@282
  1036
vb@282
  1037
STDMETHODIMP CpEpEngine::BlacklistIsListed(BSTR fpr, VARIANT_BOOL *listed)
vb@282
  1038
{
vb@282
  1039
    assert(fpr);
vb@282
  1040
    assert(listed);
vb@282
  1041
vb@282
  1042
    if (!(fpr && listed))
vb@282
  1043
        return E_INVALIDARG;
vb@282
  1044
vb@282
  1045
    string _fpr = utf8_string(fpr);
vb@282
  1046
    bool result;
vb@295
  1047
    PEP_STATUS status = ::blacklist_is_listed(session(), _fpr.c_str(), &result);
vb@282
  1048
    assert(status == PEP_STATUS_OK);
vb@282
  1049
    if (status != PEP_STATUS_OK)
vb@282
  1050
        return FAIL(L"blacklist_is_listed failed in pEp engine", status);
vb@282
  1051
vb@282
  1052
    *listed = result ? VARIANT_TRUE : VARIANT_FALSE;
vb@282
  1053
    return S_OK;
vb@282
  1054
}
vb@282
  1055
vb@282
  1056
STDMETHODIMP CpEpEngine::BlacklistRetrieve(SAFEARRAY **blacklist)
vb@282
  1057
{
vb@282
  1058
    assert(blacklist);
vb@282
  1059
vb@282
  1060
    if (!blacklist)
vb@282
  1061
        return E_INVALIDARG;
vb@282
  1062
vb@282
  1063
    ::stringlist_t *_blacklist = NULL;
vb@295
  1064
    PEP_STATUS status = ::blacklist_retrieve(session(), &_blacklist);
vb@282
  1065
    assert(status == PEP_STATUS_OK);
vb@282
  1066
    if (status != PEP_STATUS_OK)
vb@282
  1067
        return FAIL(L"blacklist_retrieve failed in pEp engine", status);
vb@282
  1068
    assert(_blacklist);
vb@282
  1069
vb@282
  1070
    *blacklist = string_array(_blacklist);
vb@282
  1071
    ::free_stringlist(_blacklist);
vb@282
  1072
    return S_OK;
vb@282
  1073
}
vb@282
  1074
vb@282
  1075
HRESULT CpEpEngine::error(_bstr_t msg)
vb@282
  1076
{
vb@282
  1077
    _bstr_t helpFile = L"";
vb@282
  1078
    _bstr_t source = L"pEp COM Adapter";
vb@282
  1079
vb@282
  1080
    ICreateErrorInfo *cei;
vb@282
  1081
    if (SUCCEEDED(CreateErrorInfo(&cei))) {
vb@282
  1082
        cei->SetDescription(msg);
vb@282
  1083
        cei->SetGUID(__uuidof(IpEpEngine));
vb@282
  1084
        cei->SetHelpContext(0);
vb@282
  1085
        cei->SetHelpFile(helpFile);
vb@282
  1086
        cei->SetSource(source);
vb@282
  1087
vb@282
  1088
        IErrorInfo *errinfo;
vb@282
  1089
        if (SUCCEEDED(cei->QueryInterface(IID_IErrorInfo, (LPVOID FAR*) &errinfo))) {
vb@282
  1090
            SetErrorInfo(0, errinfo);
vb@282
  1091
            errinfo->Release();
vb@282
  1092
        }
vb@282
  1093
        cei->Release();
vb@282
  1094
    }
vb@282
  1095
    return E_FAIL;
vb@282
  1096
}
vb@282
  1097
vb@282
  1098
HRESULT CpEpEngine::error(_bstr_t msg, PEP_STATUS status)
vb@282
  1099
{
vb@282
  1100
    std::stringstream stream;
vb@282
  1101
    stream << msg;
vb@282
  1102
    stream << ": ";
Thomas@347
  1103
    stream << pEp_status_to_string(status);
Thomas@347
  1104
    stream << std::hex << " (" << status << ")";
vb@282
  1105
vb@282
  1106
    error(stream.str().c_str());
vb@282
  1107
vb@282
  1108
    if (status == ::PEP_OUT_OF_MEMORY)
vb@282
  1109
        return E_OUTOFMEMORY;
vb@282
  1110
vb@282
  1111
    return MAKE_HRESULT(1, FACILITY_ITF, (0xFFFF & status));
vb@282
  1112
}
vb@282
  1113
vb@282
  1114
STDMETHODIMP CpEpEngine::EncryptMessage(TextMessage * src, TextMessage * dst, SAFEARRAY * extra, pEpEncryptFlags flags, pEpEncFormat encFormat)
vb@282
  1115
{
vb@282
  1116
    assert(src);
vb@282
  1117
    assert(dst);
vb@282
  1118
vb@282
  1119
    if (!(src && dst))
vb@282
  1120
        return E_INVALIDARG;
vb@282
  1121
Thomas@364
  1122
    ::message *_src = NULL;
Thomas@364
  1123
    try {
Thomas@364
  1124
        _src = text_message_to_C(src);
Thomas@364
  1125
    }
Thomas@364
  1126
    catch (bad_alloc&) {
Thomas@364
  1127
        return E_OUTOFMEMORY;
Thomas@364
  1128
    }
Thomas@364
  1129
    catch (exception& ex) {
Thomas@364
  1130
        return FAIL(ex.what());
Thomas@364
  1131
    }
vb@282
  1132
vb@282
  1133
    _PEP_enc_format _encFormat = (_PEP_enc_format)encFormat;
vb@282
  1134
vb@282
  1135
    // COM-19: Initialize msg_dst to NULL, or we end up calling
vb@282
  1136
    // free_message() below with a pointer to random garbage in
vb@282
  1137
    // case of an error in encrypt_message().
vb@282
  1138
    ::message *msg_dst = NULL;
vb@282
  1139
    ::stringlist_t *_extra = new_stringlist(extra); // can cope with NULL
vb@282
  1140
vb@282
  1141
    // _PEP_enc_format used to be intentionally hardcoded to PEP_enc_PEP:
vb@282
  1142
    // Since COM-74, this has been changed to an explicit parameter, to allow the engine to attach
vb@282
  1143
    // the keys and headers to outgoing, unencrypted messages.
vb@282
  1144
    PEP_encrypt_flags_t engineFlags = (PEP_encrypt_flags_t)flags;
vb@295
  1145
    PEP_STATUS status = ::encrypt_message(session(), _src, _extra, &msg_dst, _encFormat, engineFlags);
vb@282
  1146
    ::free_stringlist(_extra);
vb@282
  1147
vb@282
  1148
    if (status == PEP_STATUS_OK)
vb@282
  1149
        text_message_from_C(dst, msg_dst);
vb@282
  1150
    else
vb@282
  1151
        text_message_from_C(dst, _src);
vb@282
  1152
vb@282
  1153
    ::free_message(msg_dst);
vb@282
  1154
    ::free_message(_src);
vb@282
  1155
vb@282
  1156
    if (status == PEP_OUT_OF_MEMORY)
vb@282
  1157
        return E_OUTOFMEMORY;
vb@282
  1158
vb@282
  1159
    // COM-41: Enhanced PEP status handling
vb@282
  1160
    if ((status != PEP_STATUS_OK) && (status < PEP_UNENCRYPTED || status >= PEP_TRUSTWORD_NOT_FOUND))
vb@282
  1161
        return FAIL("Failure to encrypt message", status);
vb@282
  1162
vb@282
  1163
    // Statii like PEP_UNENCRYPTED due to no private key
vb@282
  1164
    // should not be a catastrophic failure here. Using S_FALSE
vb@282
  1165
    // still allows clients to differentiate with S_OK,
vb@282
  1166
    // although this does not work out of the box with
vb@282
  1167
    // the standard .NET mapping of COM.
vb@282
  1168
    if (status != PEP_STATUS_OK)
vb@282
  1169
        return S_FALSE;
vb@282
  1170
vb@282
  1171
    return S_OK;
vb@282
  1172
}
vb@282
  1173
Thomas@285
  1174
STDMETHODIMP CpEpEngine::EncryptMessageAndAddPrivKey(TextMessage * src, TextMessage * dst, BSTR to_fpr, pEpEncryptFlags flags, pEpEncFormat encFormat)
Thomas@285
  1175
{
Thomas@285
  1176
    assert(src);
Thomas@285
  1177
    assert(dst);
Thomas@285
  1178
    assert(to_fpr);
Thomas@285
  1179
Thomas@285
  1180
    if (!(src && dst))
Thomas@285
  1181
        return E_INVALIDARG;
Thomas@285
  1182
Thomas@364
  1183
    ::message *_src = NULL;
Thomas@364
  1184
    try {
Thomas@364
  1185
        _src = text_message_to_C(src);
Thomas@364
  1186
    }
Thomas@364
  1187
    catch (bad_alloc&) {
Thomas@364
  1188
        return E_OUTOFMEMORY;
Thomas@364
  1189
    }
Thomas@364
  1190
    catch (exception& ex) {
Thomas@364
  1191
        return FAIL(ex.what());
Thomas@364
  1192
    }
Thomas@285
  1193
Thomas@285
  1194
    _PEP_enc_format _encFormat = (_PEP_enc_format)encFormat;
Thomas@285
  1195
Thomas@285
  1196
    // COM-19: Initialize msg_dst to NULL, or we end up calling
Thomas@285
  1197
    // free_message() below with a pointer to random garbage in
Thomas@285
  1198
    // case of an error in encrypt_message().
Thomas@285
  1199
    ::message *msg_dst = NULL;
Thomas@285
  1200
Thomas@285
  1201
    string _to_fpr = utf8_string(to_fpr);
Thomas@285
  1202
                                                    // _PEP_enc_format used to be intentionally hardcoded to PEP_enc_PEP:
Thomas@285
  1203
                                                    // Since COM-74, this has been changed to an explicit parameter, to allow the engine to attach
Thomas@285
  1204
                                                    // the keys and headers to outgoing, unencrypted messages.
Thomas@285
  1205
    PEP_encrypt_flags_t engineFlags = (PEP_encrypt_flags_t)flags;
vb@295
  1206
    PEP_STATUS status = ::encrypt_message_and_add_priv_key(session(), _src, &msg_dst, _to_fpr.c_str(), _encFormat, engineFlags);
Thomas@285
  1207
Thomas@285
  1208
    if (status == PEP_STATUS_OK)
Thomas@285
  1209
        text_message_from_C(dst, msg_dst);
Thomas@285
  1210
    else
Thomas@285
  1211
        text_message_from_C(dst, _src);
Thomas@285
  1212
Thomas@285
  1213
    ::free_message(msg_dst);
Thomas@285
  1214
    ::free_message(_src);
Thomas@285
  1215
Thomas@285
  1216
    if (status == PEP_OUT_OF_MEMORY)
Thomas@285
  1217
        return E_OUTOFMEMORY;
Thomas@285
  1218
Thomas@285
  1219
    // COM-41: Enhanced PEP status handling
Thomas@285
  1220
    if ((status != PEP_STATUS_OK) && (status < PEP_UNENCRYPTED || status >= PEP_TRUSTWORD_NOT_FOUND))
Thomas@285
  1221
        return FAIL("Failure to encrypt message", status);
Thomas@285
  1222
Thomas@285
  1223
    // Statii like PEP_UNENCRYPTED due to no private key
Thomas@285
  1224
    // should not be a catastrophic failure here. Using S_FALSE
Thomas@285
  1225
    // still allows clients to differentiate with S_OK,
Thomas@285
  1226
    // although this does not work out of the box with
Thomas@285
  1227
    // the standard .NET mapping of COM.
Thomas@285
  1228
    if (status != PEP_STATUS_OK)
Thomas@285
  1229
        return S_FALSE;
Thomas@285
  1230
Thomas@285
  1231
    return S_OK;
Thomas@285
  1232
}
Thomas@285
  1233
vb@282
  1234
STDMETHODIMP CpEpEngine::EncryptMessageForSelf(pEpIdentity * targetId, TextMessage * src,
vb@282
  1235
    /* [in] */ SAFEARRAY *extra, TextMessage * dst, pEpEncryptFlags flags)
vb@282
  1236
{
vb@282
  1237
    assert(targetId);
vb@282
  1238
    assert(src);
vb@282
  1239
    assert(dst);
vb@282
  1240
vb@282
  1241
    if (!(targetId && src && dst))
vb@282
  1242
        return E_INVALIDARG;
vb@282
  1243
vb@282
  1244
    PEP_encrypt_flags_t engineFlags = (PEP_encrypt_flags_t)flags;
vb@282
  1245
vb@282
  1246
    ::pEp_identity *_target_id = new_identity(targetId);
vb@282
  1247
Thomas@364
  1248
    ::message *_src = NULL;
Thomas@364
  1249
    try {
Thomas@364
  1250
        _src = text_message_to_C(src);
Thomas@364
  1251
    }
Thomas@364
  1252
    catch (bad_alloc&) {
Thomas@364
  1253
        return E_OUTOFMEMORY;
Thomas@364
  1254
    }
Thomas@364
  1255
    catch (exception& ex) {
Thomas@364
  1256
        return FAIL(ex.what());
Thomas@364
  1257
    }
vb@282
  1258
vb@282
  1259
    ::stringlist_t* _extra = NULL;
vb@282
  1260
    HRESULT result = S_OK;
vb@282
  1261
    ::message *msg_dst = NULL;
vb@282
  1262
    PEP_STATUS status = PEP_STATUS_OK;
vb@282
  1263
vb@282
  1264
    try {
vb@282
  1265
        if (extra) {
vb@282
  1266
            _extra = new_stringlist(extra);
vb@282
  1267
        }
vb@282
  1268
vb@282
  1269
        // COM-19: Initialize msg_dst to NULL, or we end up calling
vb@282
  1270
        // free_message() below with a pointer to random garbage in
vb@282
  1271
        // case of an error in encrypt_message_for_self().
vb@295
  1272
        status = ::encrypt_message_for_self(session(), _target_id, _src, _extra, &msg_dst, PEP_enc_PEP, engineFlags);
vb@282
  1273
vb@282
  1274
        if (status == PEP_STATUS_OK)
vb@282
  1275
            text_message_from_C(dst, msg_dst);
vb@282
  1276
        else
vb@282
  1277
            text_message_from_C(dst, _src);
vb@282
  1278
    } catch (bad_alloc&) {
vb@282
  1279
        result = E_OUTOFMEMORY;
vb@282
  1280
    }
vb@282
  1281
    catch (exception& ex) {
vb@282
  1282
        result = FAIL(ex.what());
vb@282
  1283
    }
vb@282
  1284
vb@282
  1285
    ::free_message(msg_dst);
vb@282
  1286
    ::free_message(_src);
vb@282
  1287
    ::free_identity(_target_id);
vb@282
  1288
    ::free_stringlist(_extra);
vb@282
  1289
vb@282
  1290
    if (status == PEP_OUT_OF_MEMORY)
vb@282
  1291
        return E_OUTOFMEMORY;
vb@282
  1292
vb@282
  1293
    // Different to encrypt_message, this should never fail (we ought to always
vb@282
  1294
    // have a private key for ourself).#
vb@282
  1295
    if (status != PEP_STATUS_OK)
vb@282
  1296
        return FAIL("Failure to encrypt message", status);
vb@282
  1297
vb@282
  1298
    return result;
vb@282
  1299
}
vb@282
  1300
vb@282
  1301
STDMETHODIMP CpEpEngine::DecryptMessage(TextMessage * src, TextMessage * dst, SAFEARRAY ** keylist, pEpDecryptFlags *flags, pEpRating *rating)
vb@282
  1302
{
vb@282
  1303
    assert(src);
vb@282
  1304
    assert(dst);
vb@282
  1305
    assert(keylist);
vb@282
  1306
    assert(flags);
vb@282
  1307
    assert(rating);
vb@282
  1308
vb@282
  1309
    if (!(src && dst && keylist && flags && rating))
vb@282
  1310
        return E_INVALIDARG;
vb@282
  1311
vb@282
  1312
    *rating = pEpRatingUndefined;
vb@282
  1313
Thomas@364
  1314
    ::message *_src = NULL;
Thomas@364
  1315
    try {
Thomas@364
  1316
        _src = text_message_to_C(src);
Thomas@364
  1317
    }
Thomas@364
  1318
    catch (bad_alloc&) {
Thomas@364
  1319
        return E_OUTOFMEMORY;
Thomas@364
  1320
    }
Thomas@364
  1321
    catch (exception& ex) {
Thomas@364
  1322
        return FAIL(ex.what());
Thomas@364
  1323
    }
vb@282
  1324
    ::message *msg_dst = NULL;
Thomas@289
  1325
    ::stringlist_t *_keylist = new_stringlist(*keylist);
vb@282
  1326
    ::PEP_rating _rating;
vb@282
  1327
vb@282
  1328
    PEP_decrypt_flags_t engineflags = (PEP_decrypt_flags_t) *flags;
vb@295
  1329
    PEP_STATUS status = ::decrypt_message(session(), _src, &msg_dst, &_keylist, &_rating, &engineflags);
vb@282
  1330
vb@282
  1331
    *flags = (pEpDecryptFlags)engineflags;
vb@282
  1332
Thomas@334
  1333
    if (_src)
vb@282
  1334
        text_message_from_C(src, _src);
vb@282
  1335
vb@282
  1336
    if (msg_dst)
vb@282
  1337
        text_message_from_C(dst, msg_dst);
vb@282
  1338
vb@282
  1339
    ::free_message(_src);
vb@282
  1340
    ::free_message(msg_dst);
vb@282
  1341
vb@282
  1342
    if (_keylist) {
vb@282
  1343
        *keylist = string_array(_keylist);
vb@282
  1344
        free_stringlist(_keylist);
vb@282
  1345
    }
vb@282
  1346
vb@282
  1347
    *rating = (pEpRating)_rating;
vb@282
  1348
vb@282
  1349
    return S_OK;
vb@282
  1350
}
vb@282
  1351
vb@282
  1352
STDMETHODIMP CpEpEngine::ReEvaluateMessageRating(TextMessage * msg, SAFEARRAY * x_KeyList, pEpRating x_EncStatus, pEpRating *rating)
vb@282
  1353
{
vb@282
  1354
    assert(msg);
vb@282
  1355
    assert(x_EncStatus != PEP_rating_undefined);
vb@282
  1356
    assert(rating);
vb@282
  1357
vb@282
  1358
    if (!(msg && x_EncStatus != PEP_rating_undefined && rating))
vb@282
  1359
        return E_INVALIDARG;
vb@282
  1360
vb@282
  1361
    *rating = pEpRatingUndefined;
vb@282
  1362
Thomas@364
  1363
    ::message *_msg = NULL;
Thomas@364
  1364
    try {
Thomas@364
  1365
        _msg = text_message_to_C(msg);
Thomas@364
  1366
    }
Thomas@364
  1367
    catch (bad_alloc&) {
Thomas@364
  1368
        return E_OUTOFMEMORY;
Thomas@364
  1369
    }
Thomas@364
  1370
    catch (exception& ex) {
Thomas@364
  1371
        return FAIL(ex.what());
Thomas@364
  1372
    }
Thomas@364
  1373
vb@282
  1374
    ::stringlist_t *_keylist = new_stringlist(x_KeyList);
vb@282
  1375
    ::PEP_rating _rating = PEP_rating_undefined;
vb@282
  1376
vb@295
  1377
    PEP_STATUS status = ::re_evaluate_message_rating(session(), _msg, _keylist, (PEP_rating)x_EncStatus, &_rating);
vb@282
  1378
vb@282
  1379
    ::free_stringlist(_keylist);
vb@282
  1380
    ::free_message(_msg);
vb@282
  1381
vb@282
  1382
    *rating = (pEpRating)_rating;
vb@282
  1383
vb@282
  1384
    return S_OK;
vb@282
  1385
}
vb@282
  1386
vb@282
  1387
STDMETHODIMP CpEpEngine::OutgoingMessageRating(TextMessage *msg, pEpRating * pVal)
vb@282
  1388
{
vb@282
  1389
    assert(msg);
vb@282
  1390
    assert(pVal);
vb@282
  1391
vb@282
  1392
    if (!(msg  && pVal))
vb@282
  1393
        return E_INVALIDARG;
vb@282
  1394
Thomas@364
  1395
    ::message *_msg = NULL;
Thomas@364
  1396
    try {
Thomas@364
  1397
        _msg = text_message_to_C(msg);
Thomas@364
  1398
    }
Thomas@364
  1399
    catch (bad_alloc&) {
Thomas@364
  1400
        return E_OUTOFMEMORY;
Thomas@364
  1401
    }
Thomas@364
  1402
    catch (exception& ex) {
Thomas@364
  1403
        return FAIL(ex.what());
Thomas@364
  1404
    }
vb@282
  1405
vb@282
  1406
    PEP_rating _rating;
vb@295
  1407
    PEP_STATUS status = ::outgoing_message_rating(session(), _msg, &_rating);
vb@282
  1408
    if (status != PEP_STATUS_OK)
vb@282
  1409
        return FAIL(L"cannot get message rating", status);
vb@282
  1410
vb@282
  1411
    *pVal = (pEpRating)_rating;
vb@282
  1412
    return S_OK;
vb@282
  1413
}
vb@282
  1414
Thomas@292
  1415
STDMETHODIMP CpEpEngine::OutgoingMessageRatingPreview(TextMessage *msg, pEpRating * pVal)
Thomas@292
  1416
{
Thomas@364
  1417
    assert(msg);
Thomas@364
  1418
    assert(pVal);
Thomas@292
  1419
Thomas@364
  1420
    if (!(msg  && pVal))
Thomas@364
  1421
        return E_INVALIDARG;
Thomas@292
  1422
Thomas@364
  1423
    ::message *_msg = NULL;
Thomas@364
  1424
    try {
Thomas@364
  1425
        _msg = text_message_to_C(msg);
Thomas@364
  1426
    }
Thomas@364
  1427
    catch (bad_alloc&) {
Thomas@364
  1428
        return E_OUTOFMEMORY;
Thomas@364
  1429
    }
Thomas@364
  1430
    catch (exception& ex) {
Thomas@364
  1431
        return FAIL(ex.what());
Thomas@364
  1432
    }
Thomas@292
  1433
Thomas@364
  1434
    PEP_rating _rating;
Thomas@364
  1435
    PEP_STATUS status = ::outgoing_message_rating_preview(session(), _msg, &_rating);
Thomas@364
  1436
    if (status != PEP_STATUS_OK)
Thomas@364
  1437
        return FAIL(L"cannot get message rating", status);
Thomas@292
  1438
Thomas@364
  1439
    *pVal = (pEpRating)_rating;
Thomas@364
  1440
    return S_OK;
Thomas@292
  1441
}
Thomas@292
  1442
vb@282
  1443
STDMETHODIMP CpEpEngine::IdentityRating(struct pEpIdentity *ident, pEpRating * pVal)
vb@282
  1444
{
vb@282
  1445
    ::pEp_identity *_ident;
vb@282
  1446
vb@282
  1447
    assert(ident);
vb@282
  1448
    assert(pVal);
vb@282
  1449
vb@282
  1450
    if (!(ident  && pVal))
vb@282
  1451
        return E_INVALIDARG;
vb@282
  1452
vb@282
  1453
    try {
vb@282
  1454
        _ident = new_identity(ident);
vb@282
  1455
    }
vb@282
  1456
    catch (bad_alloc&) {
vb@282
  1457
        return E_OUTOFMEMORY;
vb@282
  1458
    }
vb@282
  1459
    catch (exception& ex) {
vb@282
  1460
        return FAIL(ex.what());;
vb@282
  1461
    }
vb@282
  1462
vb@282
  1463
    PEP_rating _rating;
vb@295
  1464
    PEP_STATUS status = ::identity_rating(session(), _ident, &_rating);
vb@282
  1465
    free_identity(_ident);
vb@282
  1466
vb@282
  1467
    if (status != PEP_STATUS_OK)
vb@282
  1468
        return FAIL(L"cannot get message color", status);
vb@282
  1469
vb@282
  1470
    *pVal = (pEpRating)_rating;
vb@282
  1471
    return S_OK;
vb@282
  1472
}
vb@282
  1473
vb@282
  1474
STDMETHODIMP CpEpEngine::ColorFromRating(pEpRating rating, pEpColor * pVal)
vb@282
  1475
{
vb@282
  1476
    assert(pVal);
vb@282
  1477
vb@282
  1478
    if (!pVal)
vb@282
  1479
        return E_INVALIDARG;
vb@282
  1480
vb@282
  1481
    PEP_rating engineRating = (PEP_rating)rating;
vb@282
  1482
    PEP_color _color = ::color_from_rating(engineRating);
vb@282
  1483
vb@282
  1484
    *pVal = (pEpColor)_color;
Thomas@364
  1485
     
vb@282
  1486
    return S_OK;
vb@282
  1487
}
vb@282
  1488
vb@282
  1489
STDMETHODIMP CpEpEngine::OwnIdentitiesRetrieve(LPSAFEARRAY* ownIdentities)
vb@282
  1490
{
vb@282
  1491
    assert(ownIdentities);
vb@282
  1492
    if (!ownIdentities)
vb@282
  1493
        return E_INVALIDARG;
vb@282
  1494
vb@282
  1495
    *ownIdentities = nullptr;
vb@282
  1496
vb@282
  1497
    ::identity_list *il = nullptr;
vb@295
  1498
    PEP_STATUS status = ::own_identities_retrieve(session(), &il);
vb@282
  1499
    if (status == PEP_OUT_OF_MEMORY) {
vb@282
  1500
        return E_OUTOFMEMORY;
vb@282
  1501
    }
vb@282
  1502
    else if (status != PEP_STATUS_OK)
vb@282
  1503
    {
vb@282
  1504
        return FAIL(_T("OwnIdentitiesRetrieve"), status);
vb@282
  1505
    }
vb@282
  1506
vb@282
  1507
    SAFEARRAY * _own_identities = nullptr;
vb@282
  1508
    try {
vb@282
  1509
        _own_identities = array_from_C<pEpIdentity, identity_list>(il);
vb@282
  1510
    }
vb@282
  1511
    catch (exception& ex)
vb@282
  1512
    {
vb@282
  1513
        ::free_identity_list(il);
vb@282
  1514
        try {
vb@282
  1515
            dynamic_cast<bad_alloc&>(ex);
vb@282
  1516
        }
vb@282
  1517
        catch (bad_cast&)
vb@282
  1518
        {
vb@282
  1519
            return FAIL(ex.what());
vb@282
  1520
        }
vb@282
  1521
        return E_OUTOFMEMORY;
vb@282
  1522
    }
vb@282
  1523
    free_identity_list(il);
vb@282
  1524
vb@282
  1525
    *ownIdentities = _own_identities;
vb@282
  1526
    return S_OK;
vb@282
  1527
}
vb@282
  1528
vb@282
  1529
STDMETHODIMP CpEpEngine::TrustPersonalKey(struct pEpIdentity *ident, struct pEpIdentity *result)
vb@282
  1530
{
vb@282
  1531
    ::pEp_identity *_ident;
vb@282
  1532
vb@282
  1533
    assert(ident);
vb@282
  1534
    assert(result);
vb@282
  1535
vb@282
  1536
    if (!ident || !result)
vb@282
  1537
        return E_INVALIDARG;
vb@282
  1538
vb@282
  1539
    try {
vb@282
  1540
        _ident = new_identity(ident);
vb@282
  1541
    }
vb@282
  1542
    catch (bad_alloc&) {
vb@282
  1543
        return E_OUTOFMEMORY;
vb@282
  1544
    }
vb@282
  1545
    catch (exception& ex) {
vb@282
  1546
        return FAIL(ex.what());;
vb@282
  1547
    }
vb@282
  1548
vb@282
  1549
    if (verbose_mode) {
vb@282
  1550
        stringstream ss;
vb@282
  1551
        ss << "TrustPersonalKey called with ";
vb@282
  1552
        ss << utf8_string(ident->Address);
vb@282
  1553
        ss << L": ";
vb@282
  1554
        ss << ident->CommType;
vb@282
  1555
        verbose(ss.str());
vb@282
  1556
    }
vb@282
  1557
vb@295
  1558
    PEP_STATUS status = ::trust_personal_key(session(), _ident);
vb@282
  1559
vb@282
  1560
    if (verbose_mode) {
vb@282
  1561
        stringstream ss;
vb@282
  1562
        ss << "result ";
vb@282
  1563
        ss << status;
vb@282
  1564
        ss << " for ";
vb@282
  1565
        ss << _ident->address;
vb@282
  1566
        ss << L": ";
vb@282
  1567
        ss << _ident->comm_type;
vb@282
  1568
        verbose(ss.str());
vb@282
  1569
    }
vb@282
  1570
vb@282
  1571
    if (status == PEP_STATUS_OK)
vb@282
  1572
        copy_identity(result, _ident);
vb@282
  1573
vb@282
  1574
    free_identity(_ident);
vb@282
  1575
    if (status == PEP_OUT_OF_MEMORY)
vb@282
  1576
        return E_OUTOFMEMORY;
vb@282
  1577
    else if (status != PEP_STATUS_OK)
vb@282
  1578
        return FAIL(L"failure while executing TrustPersonalKey()", status);
vb@282
  1579
vb@282
  1580
    return S_OK;
vb@282
  1581
}
vb@282
  1582
Thomas@285
  1583
// Force an update check now
Thomas@368
  1584
STDMETHODIMP CpEpEngine::UpdateNow(BSTR productCode, VARIANT_BOOL *didUpdate)
Thomas@285
  1585
{
Thomas@371
  1586
    BOOL result = FALSE;
vb@366
  1587
Thomas@371
  1588
    try
Thomas@285
  1589
    {
Thomas@371
  1590
        _bstr_t pc(productCode);
Thomas@371
  1591
        wstring _pc = pc;
vb@366
  1592
Thomas@371
  1593
        auto products = pEp::GateKeeper::gatekeeper()->registered_products();
Thomas@371
  1594
        for (auto p = products.begin(); p != products.end(); ++p) {
Thomas@371
  1595
            if (_pc == p->first) {
Thomas@371
  1596
                result = pEp::GateKeeper::gatekeeper()->update_product(*p);
Thomas@371
  1597
                break;
Thomas@371
  1598
            }
Thomas@371
  1599
        }
Thomas@371
  1600
    }
Thomas@285
  1601
    catch (bad_alloc&) {
Thomas@371
  1602
        return E_OUTOFMEMORY;
Thomas@285
  1603
    }
Thomas@285
  1604
    catch (exception& ex) {
Thomas@371
  1605
        return FAIL(ex.what());;
Thomas@285
  1606
    }
vb@295
  1607
Thomas@371
  1608
    *didUpdate = result;
Thomas@371
  1609
    return S_OK;
Thomas@285
  1610
}
vb@282
  1611
vb@282
  1612
// Event callbacks
vb@282
  1613
vb@282
  1614
STDMETHODIMP CpEpEngine::RegisterCallbacks(IpEpEngineCallbacks* new_callbacks)
vb@282
  1615
{
vb@282
  1616
    // check for valid parameter
vb@282
  1617
    if (!new_callbacks)
vb@282
  1618
        return E_INVALIDARG;
vb@282
  1619
vb@282
  1620
    // don't allow double registration.
vb@282
  1621
    if (this->client_callbacks)
vb@282
  1622
        return E_ILLEGAL_STATE_CHANGE;
vb@282
  1623
vb@282
  1624
    this->client_callbacks = new_callbacks;
vb@282
  1625
    new_callbacks->AddRef();
vb@282
  1626
vb@297
  1627
    // provide callbacks to sync
vb@319
  1628
    LPSTREAM marshaled_callbacks = nullptr;
vb@297
  1629
    auto result = CoMarshalInterThreadInterfaceInStream(IID_IpEpEngineCallbacks, client_callbacks, &marshaled_callbacks);
vb@297
  1630
    assert(SUCCEEDED(result));
vb@297
  1631
    assert(marshaled_callbacks);
vb@297
  1632
    sync_callbacks.insert(new MarshaledCallbacks({ this->client_callbacks, marshaled_callbacks }));
vb@282
  1633
vb@282
  1634
    return S_OK;
vb@282
  1635
}
vb@282
  1636
vb@282
  1637
STDMETHODIMP CpEpEngine::UnregisterCallbacks()
vb@282
  1638
{
vb@282
  1639
    // don't allow double deregistration.
vb@282
  1640
    // S_FALSE still is no error (as double deregistration is not fatal).
vb@282
  1641
    if (!this->client_callbacks)
vb@282
  1642
        return S_FALSE;
vb@282
  1643
vb@297
  1644
    for (auto p = sync_callbacks.begin(); p != sync_callbacks.end(); ++p) {
vb@317
  1645
        if (p->pdata && p->pdata->unmarshaled == this->client_callbacks) {
vb@315
  1646
            if (p->pdata->marshaled)
vb@315
  1647
                p->pdata->marshaled->Release();
vb@315
  1648
            if (p->pdata->unmarshaled)
vb@315
  1649
                p->pdata->unmarshaled->Release();
vb@297
  1650
            delete p->pdata;
vb@315
  1651
            p->pdata = nullptr;
vb@297
  1652
            break;
vb@295
  1653
        }
vb@295
  1654
    }
vb@282
  1655
vb@282
  1656
    this->client_callbacks->Release();
vb@315
  1657
    this->client_callbacks = nullptr;
vb@282
  1658
vb@282
  1659
    return S_OK;
vb@282
  1660
}
vb@282
  1661
vb@282
  1662
STDMETHODIMP CpEpEngine::OpenPGPListKeyinfo(BSTR search_pattern, LPSAFEARRAY* keyinfo_list) {
vb@282
  1663
    assert(keyinfo_list);
vb@282
  1664
vb@282
  1665
    if (keyinfo_list == NULL)
vb@282
  1666
        return E_INVALIDARG;
vb@282
  1667
vb@282
  1668
    string _pattern = "";
vb@282
  1669
    if (search_pattern)
vb@282
  1670
        _pattern = utf8_string(search_pattern);
vb@282
  1671
    ::stringpair_list_t* _keyinfo_list = NULL;
vb@282
  1672
vb@295
  1673
    PEP_STATUS status = ::OpenPGP_list_keyinfo(session(), _pattern.c_str(), &_keyinfo_list);
vb@282
  1674
    assert(status != PEP_OUT_OF_MEMORY);
vb@282
  1675
    if (status == PEP_OUT_OF_MEMORY)
vb@282
  1676
        return E_OUTOFMEMORY;
vb@282
  1677
vb@295
  1678
    if (status != PEP_STATUS_OK)
vb@282
  1679
        return FAIL(L"OpenPGP_list_keyinfo", status);
vb@282
  1680
vb@282
  1681
    if (_keyinfo_list && _keyinfo_list->value) {
vb@282
  1682
        ::opt_field_array_from_C(_keyinfo_list, keyinfo_list);
vb@282
  1683
    }
vb@282
  1684
    else {
vb@282
  1685
        ::free_stringpair_list(_keyinfo_list);
vb@282
  1686
        return FAIL(L"OpenPGP_list_keyinfo: no keys found");
vb@282
  1687
    }
vb@282
  1688
vb@282
  1689
    ::free_stringpair_list(_keyinfo_list);
vb@282
  1690
    return S_OK;
vb@282
  1691
vb@282
  1692
}
vb@282
  1693
vb@282
  1694
STDMETHODIMP CpEpEngine::SetOwnKey(pEpIdentity * ident, BSTR fpr, struct pEpIdentity *result)
vb@282
  1695
{
Thomas@364
  1696
    assert(ident);
Thomas@364
  1697
    assert(result);
Thomas@364
  1698
    assert(fpr);
vb@282
  1699
Thomas@364
  1700
    if (!(ident && result))
Thomas@364
  1701
        return E_INVALIDARG;
vb@282
  1702
Thomas@364
  1703
    ::pEp_identity *_ident;
Thomas@364
  1704
    try {
Thomas@364
  1705
        _ident = new_identity(ident);
Thomas@364
  1706
    }
Thomas@364
  1707
    catch (bad_alloc&) {
Thomas@364
  1708
        return E_OUTOFMEMORY;
Thomas@364
  1709
    }
Thomas@364
  1710
    catch (exception& ex) {
Thomas@364
  1711
        return FAIL(ex.what());
Thomas@364
  1712
    }
vb@282
  1713
Thomas@364
  1714
    assert(_ident);
Thomas@364
  1715
    if (_ident == NULL)
Thomas@364
  1716
        return E_OUTOFMEMORY;
vb@282
  1717
Thomas@364
  1718
    string _fpr = utf8_string(fpr);
Thomas@364
  1719
    PEP_STATUS status = ::set_own_key(session(), _ident, _fpr.c_str());
vb@282
  1720
Thomas@364
  1721
    if (status == PEP_STATUS_OK) {
Thomas@364
  1722
        copy_identity(result, _ident);
Thomas@364
  1723
        ::free_identity(_ident);
Thomas@364
  1724
        return S_OK;
Thomas@364
  1725
    }
Thomas@364
  1726
    else {
Thomas@364
  1727
        ::free_identity(_ident);
Thomas@364
  1728
        if (status == PEP_OUT_OF_MEMORY)
Thomas@364
  1729
            return E_OUTOFMEMORY;
Thomas@364
  1730
        else
Thomas@364
  1731
            return FAIL(L"SetOwnKey", status);
Thomas@364
  1732
    }
vb@282
  1733
Thomas@364
  1734
    return S_OK;
vb@282
  1735
}
vb@282
  1736
Thomas@327
  1737
STDMETHODIMP CpEpEngine::TrustOwnKey(pEpIdentity * ident)
Thomas@327
  1738
{
Thomas@364
  1739
    assert(ident);
Thomas@327
  1740
Thomas@364
  1741
    if (!ident)
Thomas@364
  1742
        return E_INVALIDARG;
Thomas@327
  1743
Thomas@364
  1744
    ::pEp_identity *_ident;
Thomas@364
  1745
    try {
Thomas@364
  1746
        _ident = new_identity(ident);
Thomas@364
  1747
    }
Thomas@364
  1748
    catch (bad_alloc&) {
Thomas@364
  1749
        return E_OUTOFMEMORY;
Thomas@364
  1750
    }
Thomas@364
  1751
    catch (exception& ex) {
Thomas@364
  1752
        return FAIL(ex.what());
Thomas@364
  1753
    }
Thomas@327
  1754
Thomas@364
  1755
    assert(_ident);
Thomas@364
  1756
    if (_ident == NULL)
Thomas@364
  1757
        return E_OUTOFMEMORY;
Thomas@327
  1758
Thomas@364
  1759
    PEP_STATUS status = ::trust_own_key(session(), _ident);
Thomas@327
  1760
Thomas@364
  1761
    ::free_identity(_ident);
Thomas@327
  1762
Thomas@364
  1763
    if (status == PEP_STATUS_OK)
Thomas@364
  1764
        return S_OK;
Thomas@364
  1765
    else if (status == PEP_OUT_OF_MEMORY)
Thomas@364
  1766
        return E_OUTOFMEMORY;
Thomas@364
  1767
    else
Thomas@364
  1768
        return FAIL(L"TrustOwnKey", status);
Thomas@327
  1769
}
Thomas@327
  1770
Thomas@322
  1771
STDMETHODIMP CpEpEngine::Startup()
vb@282
  1772
{
Thomas@364
  1773
    try
Thomas@364
  1774
    {
Thomas@364
  1775
        startup<CpEpEngine>(messageToSend, notifyHandshake, this, &CpEpEngine::Startup_sync, &CpEpEngine::Shutdown_sync);
Thomas@364
  1776
    }
Thomas@364
  1777
    catch (bad_alloc&) {
Thomas@364
  1778
        return E_OUTOFMEMORY;
Thomas@364
  1779
    }
Thomas@364
  1780
    catch (exception& ex) {
Thomas@364
  1781
        return FAIL(ex.what());
Thomas@364
  1782
    }
vb@282
  1783
Thomas@364
  1784
    return S_OK;
vb@282
  1785
}
vb@282
  1786
Thomas@349
  1787
STDMETHODIMP CpEpEngine::GetKeyRating(BSTR fpr, pEpComType *commType)
Thomas@349
  1788
{
Thomas@364
  1789
    assert(fpr);
Thomas@349
  1790
Thomas@364
  1791
    if (!fpr)
Thomas@364
  1792
        return E_INVALIDARG;
Thomas@349
  1793
Thomas@364
  1794
    string _fpr = utf8_string(fpr);
Thomas@349
  1795
Thomas@364
  1796
    PEP_comm_type _commType;
Thomas@364
  1797
    PEP_STATUS status = ::get_key_rating(session(), _fpr.c_str(), &_commType);
Thomas@364
  1798
    if (status != PEP_STATUS_OK)
Thomas@364
  1799
        return FAIL(L"cannot get key rating", status);
Thomas@349
  1800
Thomas@364
  1801
    *commType = (pEpComType)_commType;
Thomas@349
  1802
Thomas@364
  1803
    return S_OK;
Thomas@349
  1804
}
Thomas@349
  1805
Thomas@330
  1806
STDMETHODIMP CpEpEngine::GetKeyRatingForUser(BSTR userId, BSTR fpr, pEpRating *rating)
vb@282
  1807
{
Thomas@364
  1808
    assert(userId);
Thomas@364
  1809
    assert(fpr);
vb@282
  1810
Thomas@364
  1811
    if (!(userId && fpr))
Thomas@364
  1812
        return E_INVALIDARG;
vb@282
  1813
Thomas@364
  1814
    string user_id = utf8_string(userId);
Thomas@364
  1815
    string _fpr = utf8_string(fpr);
vb@282
  1816
Thomas@364
  1817
    PEP_rating _rating;
Thomas@364
  1818
    PEP_STATUS status = ::get_key_rating_for_user(session(), user_id.c_str(), _fpr.c_str(), &_rating);
Thomas@364
  1819
    if (status != PEP_STATUS_OK)
Thomas@364
  1820
        return FAIL(L"cannot get key rating for user", status);
vb@282
  1821
Thomas@364
  1822
    *rating = (pEpRating)_rating;
vb@282
  1823
Thomas@364
  1824
    return S_OK;
vb@338
  1825
}
vb@338
  1826
vb@363
  1827
STDMETHODIMP CpEpEngine::DeliverHandshakeResult(enum SyncHandshakeResult result, SAFEARRAY *identities_sharing)
vb@363
  1828
{
Thomas@364
  1829
    sync_handshake_result _result = (sync_handshake_result)result;
Thomas@364
  1830
    identity_list *_identities_sharing = NULL;
Thomas@364
  1831
    if (identities_sharing)
Thomas@364
  1832
    {
Thomas@364
  1833
        try {
Thomas@364
  1834
            _identities_sharing = identities(identities_sharing);
Thomas@364
  1835
        }
Thomas@364
  1836
        catch (bad_alloc&) {
Thomas@364
  1837
            return E_OUTOFMEMORY;
Thomas@364
  1838
        }
Thomas@364
  1839
    }
vb@363
  1840
Thomas@364
  1841
    PEP_STATUS status = ::deliverHandshakeResult(session(), _result, _identities_sharing);
Thomas@364
  1842
    free_identity_list(_identities_sharing);
Thomas@364
  1843
    switch (status) {
Thomas@364
  1844
    case PEP_STATUS_OK:
Thomas@364
  1845
        break;
Thomas@364
  1846
    case PEP_OUT_OF_MEMORY:
Thomas@364
  1847
        return E_OUTOFMEMORY;
Thomas@364
  1848
    default:
Thomas@364
  1849
        return FAIL(L"deliverHandshakeResult is reporting an error", status);
Thomas@364
  1850
    }
vb@363
  1851
Thomas@364
  1852
    return S_OK;
vb@363
  1853
}
vb@363
  1854
vb@363
  1855
STDMETHODIMP CpEpEngine::PERToXERSyncMessage(TextMessage *msg, BSTR * xer)
vb@363
  1856
{
Thomas@364
  1857
    assert(msg);
Thomas@352
  1858
Thomas@364
  1859
    if (!msg)
Thomas@364
  1860
        return E_INVALIDARG;
Thomas@352
  1861
Thomas@364
  1862
    ::message *_msg = NULL;
Thomas@364
  1863
    try {
Thomas@364
  1864
        _msg = text_message_to_C(msg);
Thomas@364
  1865
    }
Thomas@364
  1866
    catch (bad_alloc&) {
Thomas@364
  1867
        return E_OUTOFMEMORY;
Thomas@364
  1868
    }
Thomas@364
  1869
    catch (exception& ex) {
Thomas@364
  1870
        return FAIL(ex.what());
Thomas@364
  1871
    }
vb@363
  1872
Thomas@364
  1873
    char* text;
Thomas@364
  1874
    char* val = _msg->attachments->value;
vb@363
  1875
Thomas@364
  1876
    PEP_STATUS status = ::PER_to_XER_Sync_msg(val, strlen(val), &text);
Thomas@364
  1877
    free_message(_msg);
vb@363
  1878
Thomas@364
  1879
    if (status != PEP_STATUS_OK)
Thomas@364
  1880
        return FAIL(L"cannot get XER", status);
vb@363
  1881
Thomas@364
  1882
    *xer = utf16_bstr(text);
Thomas@364
  1883
    pEp_free(text);
Thomas@364
  1884
Thomas@364
  1885
    return S_OK;
vb@363
  1886
}
vb@363
  1887
vb@363
  1888
STDMETHODIMP CpEpEngine::DisableIdentityForSync(struct pEpIdentity * ident)
vb@363
  1889
{
Thomas@364
  1890
    assert(ident);
Thomas@357
  1891
Thomas@364
  1892
    if (!ident)
Thomas@364
  1893
        return E_INVALIDARG;
Thomas@357
  1894
Thomas@364
  1895
    ::pEp_identity *_ident;
Thomas@364
  1896
    try {
Thomas@364
  1897
        _ident = new_identity(ident);
Thomas@364
  1898
    }
Thomas@364
  1899
    catch (bad_alloc&) {
Thomas@364
  1900
        return E_OUTOFMEMORY;
Thomas@364
  1901
    }
Thomas@364
  1902
    catch (exception& ex) {
Thomas@364
  1903
        return FAIL(ex.what());
Thomas@364
  1904
    }
Thomas@357
  1905
Thomas@364
  1906
    assert(_ident);
Thomas@364
  1907
    if (_ident == NULL)
Thomas@364
  1908
        return E_OUTOFMEMORY;
Thomas@357
  1909
Thomas@364
  1910
    PEP_STATUS status = ::disable_identity_for_sync(session(), _ident);
vb@363
  1911
Thomas@364
  1912
    ::free_identity(_ident);
Thomas@357
  1913
Thomas@364
  1914
    if (status == PEP_STATUS_OK)
Thomas@364
  1915
        return S_OK;
Thomas@364
  1916
    else if (status == PEP_OUT_OF_MEMORY)
Thomas@364
  1917
        return E_OUTOFMEMORY;
Thomas@364
  1918
    else
Thomas@364
  1919
        return FAIL(L"DisableIdentityForSync", status);
vb@363
  1920
}
vb@363
  1921
vb@363
  1922
STDMETHODIMP CpEpEngine::EnableIdentityForSync(struct pEpIdentity * ident)
vb@363
  1923
{
Thomas@364
  1924
    assert(ident);
Thomas@357
  1925
Thomas@364
  1926
    if (!ident)
Thomas@364
  1927
        return E_INVALIDARG;
Thomas@357
  1928
Thomas@364
  1929
    ::pEp_identity *_ident;
Thomas@364
  1930
    try {
Thomas@364
  1931
        _ident = new_identity(ident);
Thomas@364
  1932
    }
Thomas@364
  1933
    catch (bad_alloc&) {
Thomas@364
  1934
        return E_OUTOFMEMORY;
Thomas@364
  1935
    }
Thomas@364
  1936
    catch (exception& ex) {
Thomas@364
  1937
        return FAIL(ex.what());
Thomas@364
  1938
    }
Thomas@357
  1939
Thomas@364
  1940
    assert(_ident);
Thomas@364
  1941
    if (_ident == NULL)
Thomas@364
  1942
        return E_OUTOFMEMORY;
Thomas@357
  1943
Thomas@364
  1944
    PEP_STATUS status = ::enable_identity_for_sync(session(), _ident);
vb@363
  1945
Thomas@364
  1946
    ::free_identity(_ident);
Thomas@357
  1947
Thomas@364
  1948
    if (status == PEP_STATUS_OK)
Thomas@364
  1949
        return S_OK;
Thomas@364
  1950
    else if (status == PEP_OUT_OF_MEMORY)
Thomas@364
  1951
        return E_OUTOFMEMORY;
Thomas@364
  1952
    else
Thomas@364
  1953
        return FAIL(L"EnableIdentityForSync", status);
vb@363
  1954
}
vb@363
  1955
vb@363
  1956
STDMETHODIMP CpEpEngine::PerMachineDirectory(BSTR * directory)
vb@363
  1957
{
Thomas@364
  1958
    assert(directory);
Thomas@358
  1959
Thomas@364
  1960
    if (!directory)
Thomas@364
  1961
        return E_INVALIDARG;
Thomas@358
  1962
Thomas@364
  1963
    const char *_directory = ::per_machine_directory();
Thomas@358
  1964
Thomas@364
  1965
    if (_directory == NULL)
Thomas@364
  1966
        return FAIL(L"PerMachineDirectory: _directory is NULL");
Thomas@358
  1967
Thomas@364
  1968
    *directory = utf16_bstr(_directory);
Thomas@358
  1969
Thomas@364
  1970
    return S_OK;
vb@363
  1971
}
vb@363
  1972
vb@363
  1973
STDMETHODIMP CpEpEngine::PerUserDirectory(BSTR * directory)
vb@363
  1974
{
Thomas@364
  1975
    assert(directory);
Thomas@358
  1976
Thomas@364
  1977
    if (!directory)
Thomas@364
  1978
        return E_INVALIDARG;
Thomas@358
  1979
Thomas@364
  1980
    const char *_directory = ::per_user_directory();
Thomas@358
  1981
Thomas@364
  1982
    if (_directory == NULL)
Thomas@364
  1983
        return FAIL(L"PerUserDirectory: _directory is NULL");
Thomas@358
  1984
Thomas@364
  1985
    *directory = utf16_bstr(_directory);
Thomas@358
  1986
Thomas@364
  1987
    return S_OK;
vb@363
  1988
}
Thomas@365
  1989
Thomas@365
  1990
STDMETHODIMP CpEpEngine::RatingFromCommType(pEpComType commType, pEpRating * rating) 
Thomas@365
  1991
{
Thomas@365
  1992
    PEP_comm_type _comm_type = (PEP_comm_type)commType;
Thomas@365
  1993
    PEP_rating _rating = ::rating_from_comm_type(_comm_type);
Thomas@365
  1994
Thomas@365
  1995
    *rating = (pEpRating)_rating;
Thomas@365
  1996
Thomas@365
  1997
    return S_OK;
Thomas@365
  1998
}
Thomas@374
  1999
Thomas@374
  2000
STDMETHODIMP CpEpEngine::GetIsSyncRunning(VARIANT_BOOL *running)
Thomas@374
  2001
{
Thomas@375
  2002
    *running = pEp::Adapter::is_sync_running();
Thomas@374
  2003
Thomas@374
  2004
    return S_OK;
Thomas@374
  2005
}
Thomas@375
  2006
Thomas@375
  2007
STDMETHODIMP CpEpEngine::ShutDownSync()
Thomas@375
  2008
{
Thomas@375
  2009
    pEp::Adapter::shutdown();
Thomas@375
  2010
Thomas@375
  2011
    return S_OK;
Thomas@375
  2012
}