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