CpEpEngine.cpp
author Markus Schaber <markus@pep-security.net>
Sat, 05 Nov 2016 10:22:14 +0100
changeset 193 896f1ea47f31
parent 192 da7caa87f709
child 194 2ed82f56ffcf
permissions -rw-r--r--
COM-20: Memory leak in CpEpEngine::blacklist_retrieve
vb@0
     1
// CpEpEngine.cpp : Implementation of CpEpEngine
vb@0
     2
vb@0
     3
#include "stdafx.h"
vb@0
     4
#include "CpEpEngine.h"
vb@0
     5
vb@10
     6
using namespace std;
vb@10
     7
using namespace pEp::utility;
vb@0
     8
vb@0
     9
// CpEpEngine
vb@0
    10
vb@0
    11
STDMETHODIMP CpEpEngine::InterfaceSupportsErrorInfo(REFIID riid)
vb@0
    12
{
markus@165
    13
	static const IID* const arr[] =
vb@0
    14
	{
vb@0
    15
		&IID_IpEpEngine
vb@0
    16
	};
vb@0
    17
markus@165
    18
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
vb@0
    19
	{
markus@165
    20
		if (InlineIsEqualGUID(*arr[i], riid))
vb@0
    21
			return S_OK;
vb@0
    22
	}
vb@0
    23
	return S_FALSE;
vb@0
    24
}
vb@0
    25
markus@189
    26
// The second argument is optional, and currently supports PEP_STATUS.
markus@189
    27
#define FAIL(msg, ...) error(msg, __VA_ARGS__)
vb@0
    28
markus@172
    29
STDMETHODIMP CpEpEngine::VerboseLogging(VARIANT_BOOL enable)
vb@51
    30
{
markus@165
    31
	verbose_mode = enable != VARIANT_FALSE;
markus@165
    32
	return S_OK;
vb@60
    33
}
vb@60
    34
markus@172
    35
STDMETHODIMP CpEpEngine::PassiveMode(VARIANT_BOOL enable)
vb@60
    36
{
markus@165
    37
	::config_passive_mode(get_session(), enable != VARIANT_FALSE);
markus@165
    38
	return S_OK;
vb@60
    39
}
vb@60
    40
markus@172
    41
STDMETHODIMP CpEpEngine::UnencryptedSubject(VARIANT_BOOL enable)
vb@60
    42
{
markus@165
    43
	::config_unencrypted_subject(get_session(), enable != VARIANT_FALSE);
markus@165
    44
	return S_OK;
vb@51
    45
}
vb@0
    46
Dean@184
    47
STDMETHODIMP CpEpEngine::ExportKey(BSTR fpr, BSTR * keyData)
Dean@183
    48
{
Dean@183
    49
    assert(fpr);
Dean@185
    50
    assert(keyData);
Dean@183
    51
markus@192
    52
    if (!(fpr && keyData))
Dean@183
    53
        return E_INVALIDARG;
Dean@183
    54
Dean@183
    55
    string _fpr = utf8_string(fpr);
Dean@183
    56
    char *_key_data = NULL;
Dean@183
    57
    size_t _size = 0;
Dean@183
    58
Dean@183
    59
    ::PEP_STATUS status = ::export_key(get_session(), _fpr.c_str(), &_key_data, &_size);
Dean@183
    60
    assert(status != ::PEP_OUT_OF_MEMORY);
Dean@183
    61
    if (status == ::PEP_OUT_OF_MEMORY)
Dean@183
    62
        return E_OUTOFMEMORY;
Dean@183
    63
Dean@183
    64
    if (status != ::PEP_STATUS_OK)
markus@189
    65
        return FAIL(L"export_key", status);
Dean@183
    66
Dean@183
    67
    _bstr_t b_key_data(utf16_string(_key_data).c_str());
Dean@183
    68
    pEp_free(_key_data);
Dean@184
    69
    * keyData = b_key_data.Detach();
Dean@183
    70
Dean@183
    71
    return S_OK;
Dean@183
    72
}
Dean@183
    73
markus@177
    74
STDMETHODIMP CpEpEngine::Log(BSTR title, BSTR entity, BSTR description, BSTR comment)
vb@0
    75
{
markus@165
    76
	string _title;
markus@165
    77
	string _entity;
markus@165
    78
	string _description;
markus@165
    79
	string _comment;
markus@165
    80
	HRESULT result = S_OK;
vb@0
    81
markus@165
    82
	assert(title);
markus@165
    83
	if (title)
markus@165
    84
		_title = utf8_string(title);
markus@165
    85
	else
markus@165
    86
		result = E_INVALIDARG;
vb@0
    87
markus@165
    88
	assert(entity);
markus@165
    89
	if (entity)
markus@165
    90
		_entity = utf8_string(entity);
markus@165
    91
	else
markus@165
    92
		result = E_INVALIDARG;
vb@0
    93
markus@165
    94
	if (description)
markus@165
    95
		_description = utf8_string(description);
vb@0
    96
markus@165
    97
	if (comment)
markus@165
    98
		_comment = utf8_string(comment);
vb@0
    99
markus@165
   100
	if (result != S_OK)
markus@165
   101
		return result;
vb@0
   102
markus@165
   103
	PEP_STATUS _status = ::log_event(get_session(), _title.c_str(), _entity.c_str(), _description.c_str(), _comment.c_str());
markus@165
   104
	assert(_status == PEP_STATUS_OK);
markus@165
   105
	if (_status != PEP_STATUS_OK)
markus@189
   106
		return FAIL(L"log_event", _status);
markus@165
   107
	else
markus@165
   108
		return S_OK;
vb@0
   109
}
vb@0
   110
markus@172
   111
STDMETHODIMP CpEpEngine::TrustWords(BSTR fpr, BSTR lang, LONG max_words, BSTR * words)
vb@0
   112
{
markus@165
   113
	assert(fpr);
markus@165
   114
	assert(max_words >= 0);
markus@165
   115
	assert(words);
vb@0
   116
markus@165
   117
	HRESULT result = S_OK;
vb@0
   118
markus@165
   119
	string _fpr;
markus@165
   120
	if (fpr)
markus@165
   121
		_fpr = utf8_string(fpr);
markus@165
   122
	else
markus@165
   123
		result = E_INVALIDARG;
vb@0
   124
markus@165
   125
	string _lang;
markus@165
   126
	if (lang) {
markus@165
   127
		_lang = utf8_string(lang);
markus@165
   128
		if (_lang.length()) {
markus@165
   129
			if (_lang.length() != 2)
markus@165
   130
				result = E_INVALIDARG;
markus@165
   131
		}
markus@165
   132
		else
markus@165
   133
			_lang = "en";
markus@165
   134
	}
markus@165
   135
	else
markus@165
   136
		_lang = "en";
vb@0
   137
markus@165
   138
	if (max_words < 0)
markus@165
   139
		result = E_INVALIDARG;
vb@0
   140
markus@165
   141
	if (words == NULL)
markus@165
   142
		result = E_INVALIDARG;
vb@0
   143
markus@165
   144
	if (result != S_OK)
markus@165
   145
		return result;
vb@0
   146
markus@165
   147
	char *_words = NULL;
markus@165
   148
	size_t _wsize = 0;
vb@0
   149
markus@165
   150
	PEP_STATUS status = ::trustwords(get_session(), _fpr.c_str(), _lang.c_str(), &_words, &_wsize, max_words);
markus@165
   151
	assert(status != PEP_OUT_OF_MEMORY);
markus@165
   152
	if (status == PEP_OUT_OF_MEMORY)
markus@165
   153
		return E_OUTOFMEMORY;
vb@0
   154
markus@165
   155
	if (_words == NULL) {
markus@165
   156
		*words = NULL;
markus@189
   157
		return FAIL(L"TrustWords: _words == NULL", status);
markus@165
   158
	}
markus@165
   159
	else {
markus@165
   160
		*words = utf16_bstr(_words);
markus@165
   161
		pEp_free(_words);
markus@165
   162
		return S_OK;
markus@165
   163
	}
vb@0
   164
}
vb@0
   165
markus@190
   166
STDMETHODIMP CpEpEngine::GetTrustWords(struct pEpIdentity *id1, struct pEpIdentity *id2, BSTR lang, VARIANT_BOOL full, BSTR *words)
markus@190
   167
{
markus@190
   168
    assert(id1);
markus@190
   169
    assert(id2);
markus@190
   170
    assert(words);
markus@190
   171
markus@192
   172
    if (!(id1 && id2 && words))
markus@190
   173
    {
markus@190
   174
        return E_INVALIDARG;
markus@190
   175
    }
markus@190
   176
markus@190
   177
    HRESULT result = S_OK;
markus@190
   178
markus@190
   179
    pEp_identity* _id1 = NULL;
markus@190
   180
    pEp_identity* _id2 = NULL;
markus@190
   181
    string _lang;
markus@190
   182
    *words = NULL;
markus@190
   183
markus@190
   184
    try {
markus@190
   185
        _id1 = new_identity(id1);
markus@190
   186
        _id2 = new_identity(id2);
markus@190
   187
markus@190
   188
        if (!lang) {
markus@190
   189
            _lang = utf8_string(lang);
markus@190
   190
            if (_lang.length() == 0) {
markus@190
   191
                _lang = "en";
markus@190
   192
            } else if (_lang.length() != 2) {
markus@190
   193
                result = E_INVALIDARG;
markus@190
   194
            }
markus@190
   195
        } else {
markus@190
   196
            _lang = "en";
markus@190
   197
        }
markus@190
   198
    } catch (bad_alloc&) {
markus@190
   199
        result = E_OUTOFMEMORY;
markus@190
   200
    } catch (exception& ex) {
markus@190
   201
        result = FAIL(ex.what());
markus@190
   202
    }
markus@190
   203
markus@190
   204
    char* _words;
markus@190
   205
    size_t _size;
markus@190
   206
    if (result = S_OK) {
markus@190
   207
        auto status = ::get_trustwords(get_session(), _id1, _id2, _lang.c_str(), &_words, &_size, full != 0 /* convert variant bool to C bool */);
markus@190
   208
markus@190
   209
        if (status == PEP_OUT_OF_MEMORY) {
markus@190
   210
            result = E_OUTOFMEMORY;
markus@190
   211
        }
markus@190
   212
        else if (status == PEP_TRUSTWORD_NOT_FOUND) {
markus@190
   213
            result = FAIL(L"GetTrustWords: Trustword not found", status);
markus@190
   214
        }
markus@190
   215
        else if (!words) {
markus@190
   216
            result = FAIL(L"GetTrustWords: _words == NULL", status);
markus@190
   217
        }
markus@190
   218
        else {
markus@190
   219
            *words = utf16_bstr(_words);
markus@190
   220
            pEp_free(_words);
markus@190
   221
        }
markus@190
   222
    }
markus@190
   223
markus@190
   224
    free_identity(_id1);
markus@190
   225
    free_identity(_id2);
markus@190
   226
markus@190
   227
    return result;
markus@190
   228
}
markus@190
   229
markus@190
   230
markus@172
   231
STDMETHODIMP CpEpEngine::GetCrashdumpLog(LONG maxlines, BSTR * log)
vb@57
   232
{
markus@165
   233
	assert(maxlines >= 0);
markus@165
   234
	assert(log);
vb@57
   235
markus@165
   236
	if (!(maxlines >= 0 && log))
markus@165
   237
		return E_INVALIDARG;
vb@57
   238
markus@165
   239
	char *_log;
markus@165
   240
	PEP_STATUS status = ::get_crashdump_log(get_session(), (int)maxlines, &_log);
markus@165
   241
	assert(status == PEP_STATUS_OK);
markus@165
   242
	if (status == PEP_OUT_OF_MEMORY)
markus@165
   243
		return E_OUTOFMEMORY;
markus@189
   244
	if (status != PEP_STATUS_OK)
markus@189
   245
		return FAIL(L"GetCrashdumpLog", status);
markus@189
   246
    if (_log == NULL)
markus@189
   247
        return FAIL(L"GetCrashdumpLog: _log == NULL");
vb@57
   248
markus@165
   249
	*log = utf16_bstr(_log);
markus@165
   250
	pEp_free(_log);
markus@165
   251
	return S_OK;
vb@57
   252
}
vb@57
   253
markus@172
   254
STDMETHODIMP CpEpEngine::GetEngineVersion(BSTR * engine_version)
Dean@151
   255
{
markus@165
   256
	assert(engine_version);
Dean@151
   257
markus@165
   258
	if (!engine_version)
markus@165
   259
		return E_INVALIDARG;
Dean@151
   260
Dean@174
   261
	const char *_engine_version = ::get_engine_version();
Dean@151
   262
Dean@174
   263
	if (_engine_version == NULL)
markus@189
   264
		return FAIL(L"GetEngineVersion: _engine_version == NULL");
Dean@151
   265
Dean@174
   266
	*engine_version = utf16_bstr(_engine_version);
Dean@151
   267
markus@165
   268
	return S_OK;
Dean@151
   269
}
Dean@151
   270
markus@177
   271
STDMETHODIMP CpEpEngine::GetLanguageList(BSTR * languages)
vb@59
   272
{
markus@165
   273
	assert(languages);
vb@59
   274
markus@165
   275
	if (!languages)
markus@165
   276
		return E_INVALIDARG;
vb@59
   277
markus@165
   278
	char *_languages;
markus@165
   279
	PEP_STATUS status = ::get_languagelist(get_session(), &_languages);
markus@165
   280
	assert(status == PEP_STATUS_OK);
markus@165
   281
	if (status == PEP_OUT_OF_MEMORY)
markus@165
   282
		return E_OUTOFMEMORY;
markus@189
   283
    if (status != PEP_STATUS_OK)
markus@189
   284
        return FAIL(L"GetLanguageList", status);
markus@189
   285
	if (_languages == NULL)
markus@189
   286
		return FAIL(L"GetLanguageList: _languages == NULL");
vb@59
   287
markus@165
   288
	*languages = utf16_bstr(_languages);
markus@165
   289
	pEp_free(_languages);
markus@165
   290
	return S_OK;
vb@59
   291
}
vb@59
   292
markus@172
   293
STDMETHODIMP CpEpEngine::StartKeyserverLookup()
vb@24
   294
{
markus@165
   295
	if (identity_queue.load())
markus@165
   296
		return S_OK;
vb@24
   297
markus@165
   298
	identity_queue.store(new identity_queue_t());
markus@165
   299
	keymanagement_thread = new thread(::do_keymanagement, retrieve_next_identity, (void *)identity_queue.load());
markus@165
   300
markus@165
   301
	return S_OK;
vb@24
   302
}
vb@24
   303
markus@172
   304
STDMETHODIMP CpEpEngine::StopKeyserverLookup()
vb@24
   305
{
markus@165
   306
	if (identity_queue.load() == NULL)
markus@165
   307
		return S_OK;
vb@24
   308
markus@165
   309
	identity_queue_t *_iq = identity_queue.load();
markus@165
   310
	identity_queue.store(NULL);
vb@25
   311
markus@165
   312
	pEp_identity_cpp shutdown;
markus@165
   313
	_iq->push_front(shutdown);
vb@24
   314
markus@165
   315
	keymanagement_thread->join();
markus@165
   316
	delete keymanagement_thread;
markus@165
   317
	keymanagement_thread = NULL;
vb@24
   318
markus@165
   319
	delete _iq;
vb@24
   320
markus@165
   321
	return S_OK;
vb@24
   322
}
vb@24
   323
markus@172
   324
STDMETHODIMP CpEpEngine::Myself(struct pEpIdentity *ident, struct pEpIdentity *result)
vb@0
   325
{
markus@165
   326
	assert(ident);
markus@165
   327
	assert(result);
vb@0
   328
markus@192
   329
	if (!(ident && result))
markus@165
   330
		return E_INVALIDARG;
vb@0
   331
markus@165
   332
	::pEp_identity *_ident = new_identity(ident);
markus@165
   333
	assert(_ident);
markus@165
   334
	if (_ident == NULL)
markus@165
   335
		return E_OUTOFMEMORY;
vb@0
   336
markus@84
   337
	// DEBUG CODE - REMOVE BEFORE RELEASE!
markus@172
   338
	// SyncHandshakeResult handshakeResult;
markus@84
   339
	//
markus@85
   340
	// HRESULT res = Fire_ShowHandshake(ident, result, &handshakeResult);
markus@85
   341
	// 
markus@85
   342
	// HRESULT res2 = Fire_TestEvent(15, _bstr_t( "hallo"));
markus@84
   343
markus@165
   344
	PEP_STATUS status = ::myself(get_session(), _ident);
vb@0
   345
markus@165
   346
	if (status == PEP_STATUS_OK) {
markus@165
   347
		assert(_ident->fpr);
markus@165
   348
		copy_identity(result, _ident);
markus@165
   349
		::free_identity(_ident);
markus@165
   350
		return S_OK;
markus@165
   351
	}
markus@165
   352
	else {
markus@165
   353
		::free_identity(_ident);
markus@165
   354
		if (status == PEP_OUT_OF_MEMORY)
markus@165
   355
			return E_OUTOFMEMORY;
markus@165
   356
		else
markus@189
   357
			return FAIL(L"myself", status);
markus@165
   358
	}
vb@0
   359
}
vb@0
   360
markus@172
   361
STDMETHODIMP CpEpEngine::UpdateIdentity(struct pEpIdentity *ident, struct pEpIdentity *result)
vb@0
   362
{
markus@165
   363
	assert(ident);
markus@165
   364
	assert(result);
vb@0
   365
markus@192
   366
	if (!(ident && result))
markus@165
   367
		return E_INVALIDARG;
vb@0
   368
markus@165
   369
	::pEp_identity *_ident = new_identity(ident);
markus@165
   370
	assert(_ident);
markus@165
   371
	if (_ident == NULL)
markus@165
   372
		return E_OUTOFMEMORY;
vb@0
   373
markus@165
   374
	PEP_STATUS status = ::update_identity(get_session(), _ident);
vb@0
   375
markus@165
   376
	if (status == PEP_STATUS_OK) {
markus@165
   377
		assert(_ident->fpr);
markus@165
   378
		copy_identity(result, _ident);
markus@165
   379
		::free_identity(_ident);
markus@165
   380
		return S_OK;
markus@165
   381
	}
markus@165
   382
	else {
markus@165
   383
		::free_identity(_ident);
markus@165
   384
		if (status == PEP_OUT_OF_MEMORY)
markus@165
   385
			return E_OUTOFMEMORY;
markus@165
   386
		else
markus@189
   387
			return FAIL(L"UpdateIdentity", status);
markus@165
   388
	}
vb@0
   389
}
vb@0
   390
markus@172
   391
STDMETHODIMP CpEpEngine::KeyMistrusted(struct pEpIdentity *ident)
vb@4
   392
{
markus@165
   393
	::pEp_identity *_ident;
vb@4
   394
markus@165
   395
	assert(ident);
markus@192
   396
	if (!ident)
markus@192
   397
		return E_INVALIDARG;
vb@4
   398
markus@165
   399
	try {
markus@165
   400
		_ident = new_identity(ident);
markus@165
   401
	}
markus@165
   402
	catch (bad_alloc&) {
markus@165
   403
		return E_OUTOFMEMORY;
markus@165
   404
	}
markus@165
   405
	catch (exception&) {
markus@165
   406
		return E_FAIL;
markus@165
   407
	}
vb@4
   408
markus@165
   409
	PEP_STATUS status = ::key_mistrusted(get_session(), _ident);
markus@165
   410
	free_identity(_ident);
vb@49
   411
markus@165
   412
	if (status == PEP_OUT_OF_MEMORY)
markus@165
   413
		return E_OUTOFMEMORY;
vb@4
   414
markus@165
   415
	if (status == PEP_KEY_NOT_FOUND)
markus@165
   416
		return FAIL(L"key not found");
vb@4
   417
markus@165
   418
	if (status != ::PEP_STATUS_OK)
markus@189
   419
		return FAIL(L"cannot revoke compromized key", status);
vb@4
   420
markus@165
   421
	return S_OK;
vb@4
   422
}
vb@4
   423
markus@172
   424
STDMETHODIMP CpEpEngine::KeyResetTrust(struct pEpIdentity *ident)
Edouard@53
   425
{
markus@165
   426
	::pEp_identity *_ident;
Edouard@53
   427
markus@192
   428
	assert(ident); 
markus@192
   429
	
markus@192
   430
	if (!ident)
markus@192
   431
		return E_INVALIDARG;
Edouard@53
   432
markus@165
   433
	try {
markus@165
   434
		_ident = new_identity(ident);
markus@165
   435
	}
markus@165
   436
	catch (bad_alloc&) {
markus@165
   437
		return E_OUTOFMEMORY;
markus@165
   438
	}
markus@165
   439
	catch (exception&) {
markus@165
   440
		return E_FAIL;
markus@165
   441
	}
Edouard@53
   442
markus@165
   443
	PEP_STATUS status = ::key_reset_trust(get_session(), _ident);
markus@165
   444
	free_identity(_ident);
Edouard@53
   445
markus@165
   446
	if (status == PEP_OUT_OF_MEMORY)
markus@165
   447
		return E_OUTOFMEMORY;
Edouard@53
   448
markus@165
   449
	if (status == PEP_KEY_NOT_FOUND)
markus@165
   450
		return FAIL(L"key not found");
Edouard@53
   451
markus@165
   452
	if (status != ::PEP_STATUS_OK)
markus@189
   453
		return FAIL(L"cannot reset trust", status);
Edouard@53
   454
markus@165
   455
	return S_OK;
Edouard@53
   456
}
Edouard@53
   457
vb@28
   458
int CpEpEngine::examine_identity(pEp_identity *ident, void *management)
vb@28
   459
{
markus@165
   460
	assert(ident);
markus@165
   461
	assert(management);
markus@165
   462
	if (!(ident && management))
markus@165
   463
		return -1;
vb@28
   464
markus@165
   465
	CpEpEngine *me = (CpEpEngine *)management;
vb@28
   466
markus@165
   467
	if (me->identity_queue.load() == NULL)
markus@165
   468
		return 0;
vb@28
   469
markus@165
   470
	try {
markus@165
   471
		me->identity_queue.load()->push_back(ident);
markus@165
   472
	}
markus@165
   473
	catch (exception&) {
markus@165
   474
		return -1;
markus@165
   475
	}
vb@28
   476
markus@165
   477
	return 0;
vb@28
   478
}
vb@28
   479
vb@0
   480
::pEp_identity * CpEpEngine::retrieve_next_identity(void *management)
vb@0
   481
{
markus@165
   482
	assert(management);
markus@192
   483
	if (!management)
markus@192
   484
		return NULL;
markus@192
   485
markus@165
   486
	identity_queue_t *iq = (identity_queue_t *)management;
vb@0
   487
markus@165
   488
	do /* poll queue */ {
markus@165
   489
		if (iq->size())
markus@165
   490
			break;
markus@165
   491
		::Sleep(100);
markus@165
   492
	} while (true);
vb@0
   493
markus@165
   494
	::pEp_identity *_ident;
markus@165
   495
	pEp_identity_cpp& ident = iq->front();
vb@0
   496
markus@165
   497
	if (ident.address.size() == 0)
markus@165
   498
		return NULL;
vb@0
   499
markus@165
   500
	_ident = ident.to_pEp_identity();
markus@165
   501
	iq->pop_front();
vb@0
   502
markus@165
   503
	return _ident;
vb@0
   504
}
vb@0
   505
markus@164
   506
PEP_STATUS CpEpEngine::messageToSend(void * obj, message *msg)
vb@74
   507
{
markus@165
   508
	assert(msg);
markus@192
   509
	assert(obj);
markus@192
   510
	if (!(msg && obj))
markus@165
   511
		return PEP_ILLEGAL_VALUE;
vb@75
   512
markus@172
   513
	TextMessage _msg;
markus@172
   514
	memset(&_msg, 0, sizeof(TextMessage));
vb@82
   515
markus@165
   516
	text_message_from_C(&_msg, msg);
markus@165
   517
	CpEpEngine *me = (CpEpEngine *)obj;
markus@165
   518
	HRESULT r = me->Fire_MessageToSend(&_msg);
markus@165
   519
	assert(r == S_OK);
markus@165
   520
	clear_text_message(&_msg);
markus@165
   521
	if (r == E_OUTOFMEMORY)
markus@165
   522
		return PEP_OUT_OF_MEMORY;
markus@165
   523
	if (r != S_OK)
markus@165
   524
		return PEP_UNKNOWN_ERROR;
vb@75
   525
markus@165
   526
	return PEP_STATUS_OK;
vb@74
   527
}
vb@74
   528
markus@164
   529
PEP_STATUS CpEpEngine::showHandshake(void * obj, pEp_identity *self, pEp_identity *partner)
vb@74
   530
{
markus@165
   531
	assert(self && partner);
markus@165
   532
	if (!(self && partner))
markus@165
   533
		return PEP_ILLEGAL_VALUE;
vb@80
   534
markus@172
   535
	pEpIdentity _self;
markus@165
   536
	copy_identity(&_self, self);
markus@172
   537
	pEpIdentity _partner;
markus@165
   538
	copy_identity(&_partner, partner);
markus@165
   539
	CpEpEngine *me = (CpEpEngine *)obj;
markus@172
   540
	SyncHandshakeResult _result;
markus@165
   541
	HRESULT r = me->Fire_ShowHandshake(&_self, &_partner, &_result);
markus@165
   542
	assert(r == S_OK);
markus@165
   543
	clear_identity_s(_self);
markus@165
   544
	clear_identity_s(_partner);
markus@165
   545
	if (r == E_OUTOFMEMORY)
markus@165
   546
		return PEP_OUT_OF_MEMORY;
markus@165
   547
	if (r != S_OK)
markus@165
   548
		return PEP_UNKNOWN_ERROR;
vb@75
   549
markus@165
   550
	PEP_STATUS status = deliverHandshakeResult(me->get_session(), partner, (sync_handshake_result)(int)_result);
markus@165
   551
	return status;
vb@74
   552
}
vb@74
   553
markus@172
   554
STDMETHODIMP CpEpEngine::BlacklistAdd(BSTR fpr)
vb@65
   555
{
markus@165
   556
	assert(fpr);
markus@192
   557
	if (!fpr)
markus@192
   558
		return E_INVALIDARG;
vb@65
   559
markus@165
   560
	string _fpr = utf8_string(fpr);
markus@165
   561
	PEP_STATUS status = ::blacklist_add(get_session(), _fpr.c_str());
markus@165
   562
	assert(status == PEP_STATUS_OK);
markus@165
   563
	if (status != PEP_STATUS_OK)
markus@189
   564
		return FAIL(L"blacklist_add failed in pEp engine", status);
vb@65
   565
markus@165
   566
	return S_OK;
vb@65
   567
}
vb@65
   568
markus@172
   569
STDMETHODIMP CpEpEngine::BlacklistDelete(BSTR fpr)
vb@65
   570
{
markus@165
   571
	assert(fpr);
markus@192
   572
	if (!fpr)
markus@192
   573
		return E_INVALIDARG;
vb@65
   574
markus@165
   575
	string _fpr = utf8_string(fpr);
markus@165
   576
	PEP_STATUS status = ::blacklist_delete(get_session(), _fpr.c_str());
markus@165
   577
	assert(status == PEP_STATUS_OK);
markus@165
   578
	if (status != PEP_STATUS_OK)
markus@189
   579
		return FAIL(L"blacklist_delete failed in pEp engine", status);
vb@65
   580
markus@165
   581
	return S_OK;
vb@65
   582
}
vb@65
   583
markus@172
   584
STDMETHODIMP CpEpEngine::BlacklistIsListed(BSTR fpr, VARIANT_BOOL *listed)
vb@65
   585
{
markus@165
   586
	assert(fpr);
markus@165
   587
	assert(listed);
vb@65
   588
markus@192
   589
	if (!(fpr && listed))
markus@192
   590
		return E_INVALIDARG;
markus@192
   591
markus@165
   592
	string _fpr = utf8_string(fpr);
markus@165
   593
	bool result;
markus@165
   594
	PEP_STATUS status = ::blacklist_is_listed(get_session(), _fpr.c_str(), &result);
markus@165
   595
	assert(status == PEP_STATUS_OK);
markus@165
   596
	if (status != PEP_STATUS_OK)
markus@189
   597
		return FAIL(L"blacklist_is_listed failed in pEp engine", status);
vb@65
   598
markus@165
   599
	*listed = result ? VARIANT_TRUE : VARIANT_FALSE;
markus@165
   600
	return S_OK;
vb@65
   601
}
vb@65
   602
Dean@187
   603
STDMETHODIMP CpEpEngine::BlacklistRetrieve(SAFEARRAY **blacklist)
vb@65
   604
{
markus@165
   605
	assert(blacklist);
vb@65
   606
markus@192
   607
	if (!blacklist)
markus@192
   608
		return E_INVALIDARG;
markus@192
   609
markus@165
   610
	::stringlist_t *_blacklist = NULL;
markus@165
   611
	PEP_STATUS status = ::blacklist_retrieve(get_session(), &_blacklist);
markus@165
   612
	assert(status == PEP_STATUS_OK);
markus@165
   613
	if (status != PEP_STATUS_OK)
markus@189
   614
		return FAIL(L"blacklist_retrieve failed in pEp engine", status);
markus@165
   615
	assert(_blacklist);
vb@65
   616
markus@165
   617
	*blacklist = string_array(_blacklist);
markus@193
   618
	::free_stringlist(_blacklist);
markus@165
   619
	return S_OK;
vb@65
   620
}
vb@65
   621
vb@0
   622
HRESULT CpEpEngine::error(_bstr_t msg)
vb@0
   623
{
markus@165
   624
	_bstr_t helpFile = L"";
markus@165
   625
	_bstr_t source = L"pEp COM Adapter";
vb@0
   626
markus@165
   627
	ICreateErrorInfo *cei;
markus@165
   628
	if (SUCCEEDED(CreateErrorInfo(&cei))) {
markus@165
   629
		cei->SetDescription(msg);
markus@165
   630
		cei->SetGUID(__uuidof(IpEpEngine));
markus@165
   631
		cei->SetHelpContext(0);
markus@165
   632
		cei->SetHelpFile(helpFile);
markus@165
   633
		cei->SetSource(source);
vb@0
   634
markus@165
   635
		IErrorInfo *errinfo;
markus@165
   636
		if (SUCCEEDED(cei->QueryInterface(IID_IErrorInfo, (LPVOID FAR*) &errinfo))) {
markus@165
   637
			SetErrorInfo(0, errinfo);
markus@165
   638
			errinfo->Release();
markus@165
   639
		}
markus@165
   640
		cei->Release();
markus@165
   641
	}
markus@165
   642
	return E_FAIL;
vb@0
   643
}
vb@15
   644
markus@189
   645
HRESULT CpEpEngine::error(_bstr_t msg, PEP_STATUS status)
markus@189
   646
{
markus@189
   647
    std::stringstream stream;
markus@189
   648
    stream << msg;
markus@189
   649
    stream << ": ";
markus@189
   650
    stream << std::hex << status;
markus@189
   651
    
markus@189
   652
    error(stream.str().c_str());
markus@189
   653
markus@189
   654
    if (status == ::PEP_OUT_OF_MEMORY)
markus@189
   655
        return E_OUTOFMEMORY;
markus@189
   656
markus@189
   657
    return E_FAIL;
markus@189
   658
}
markus@189
   659
markus@172
   660
STDMETHODIMP CpEpEngine::EncryptMessage(TextMessage * src, TextMessage * dst, SAFEARRAY * extra, pEpEncryptFlags flags)
vb@15
   661
{
markus@165
   662
	assert(src);
markus@165
   663
	assert(dst);
vb@15
   664
markus@192
   665
	if (!(src && dst))
markus@192
   666
		return E_INVALIDARG;
markus@192
   667
markus@165
   668
	::message *_src = text_message_to_C(src);
markus@191
   669
markus@191
   670
	// COM-19: Initialize msg_dst to NULL, or we end up calling
markus@191
   671
	// free_message() below with a pointer to random garbage in
markus@191
   672
	// case of an error in encrypt_message().
markus@191
   673
	::message *msg_dst = NULL;
markus@192
   674
	::stringlist_t *_extra = new_stringlist(extra); // can cope with NULL
vb@16
   675
markus@167
   676
	// _PEP_enc_format is intentionally hardcoded to PEP_enc_PEP:
markus@167
   677
	// 2016-10-02 14:10 < fdik> schabi: actually, all adapters now must use PEP_enc_PEP
markus@167
   678
	PEP_encrypt_flags_t engineFlags = (PEP_encrypt_flags_t) flags;
markus@167
   679
	PEP_STATUS status = ::encrypt_message(get_session(), _src, _extra, &msg_dst, PEP_enc_PEP, engineFlags);
markus@165
   680
	::free_stringlist(_extra);
vb@16
   681
markus@165
   682
	if (status == PEP_STATUS_OK)
markus@165
   683
		text_message_from_C(dst, msg_dst);
markus@165
   684
	else
markus@165
   685
		text_message_from_C(dst, _src);
vb@38
   686
markus@165
   687
	::free_message(msg_dst);
markus@165
   688
	::free_message(_src);
vb@16
   689
markus@165
   690
	if (status == PEP_OUT_OF_MEMORY)
markus@165
   691
		return E_OUTOFMEMORY;
vb@46
   692
markus@165
   693
	return S_OK;
vb@15
   694
}
vb@15
   695
markus@172
   696
STDMETHODIMP CpEpEngine::DecryptMessage(TextMessage * src, TextMessage * dst, SAFEARRAY ** keylist, pEpDecryptFlags *flags, pEpRating *rating)
vb@15
   697
{
markus@165
   698
	assert(src);
markus@165
   699
	assert(dst);
markus@165
   700
	assert(keylist);
markus@192
   701
	assert(flags);
markus@165
   702
	assert(rating);
vb@15
   703
markus@192
   704
	if (!(src && dst && keylist && flags && rating))
markus@192
   705
		return E_INVALIDARG;
markus@192
   706
markus@165
   707
	*keylist = NULL;
markus@172
   708
	*rating = pEpRatingUndefined;
vb@40
   709
markus@165
   710
	::message *_src = text_message_to_C(src);
markus@165
   711
	::message *msg_dst = NULL;
markus@165
   712
	::stringlist_t *_keylist;
markus@165
   713
	::PEP_rating _rating;
vb@16
   714
markus@167
   715
	PEP_decrypt_flags_t engineflags = 0;
markus@167
   716
	PEP_STATUS status = ::decrypt_message(get_session(), _src, &msg_dst, &_keylist, &_rating, &engineflags);
markus@167
   717
markus@167
   718
	*flags = (pEpDecryptFlags)engineflags;
vb@42
   719
markus@165
   720
	if (msg_dst)
markus@165
   721
		text_message_from_C(dst, msg_dst);
vb@42
   722
markus@165
   723
	::free_message(_src);
markus@165
   724
	::free_message(msg_dst);
vb@16
   725
markus@165
   726
	if (_keylist) {
markus@165
   727
		*keylist = string_array(_keylist);
markus@165
   728
		free_stringlist(_keylist);
markus@165
   729
	}
vb@18
   730
markus@172
   731
	*rating = (pEpRating)_rating;
vb@18
   732
markus@165
   733
	return S_OK;
vb@15
   734
}
vb@15
   735
markus@172
   736
STDMETHODIMP CpEpEngine::OutgoingMessageRating(TextMessage *msg, pEpRating * pVal)
vb@15
   737
{
markus@165
   738
	assert(msg);
markus@165
   739
	assert(pVal);
vb@15
   740
markus@192
   741
	if (!(msg  && pVal))
markus@192
   742
		return E_INVALIDARG;
markus@192
   743
markus@165
   744
	::message *_msg = text_message_to_C(msg);
vb@19
   745
markus@165
   746
	PEP_rating _rating;
markus@165
   747
	PEP_STATUS status = ::outgoing_message_rating(get_session(), _msg, &_rating);
markus@165
   748
	if (status != PEP_STATUS_OK)
markus@189
   749
		return FAIL(L"cannot get message rating", status);
vb@16
   750
markus@172
   751
	*pVal = (pEpRating)_rating;
markus@165
   752
	return S_OK;
vb@15
   753
}
vb@18
   754
markus@172
   755
STDMETHODIMP CpEpEngine::IdentityRating(struct pEpIdentity *ident, pEpRating * pVal)
vb@18
   756
{
markus@165
   757
	::pEp_identity *_ident;
vb@18
   758
markus@165
   759
	assert(ident);
markus@165
   760
	assert(pVal);
vb@18
   761
markus@192
   762
	if (!(ident  && pVal))
markus@192
   763
		return E_INVALIDARG;
markus@192
   764
markus@165
   765
	try {
markus@165
   766
		_ident = new_identity(ident);
markus@165
   767
	}
markus@165
   768
	catch (bad_alloc&) {
markus@165
   769
		return E_OUTOFMEMORY;
markus@165
   770
	}
markus@165
   771
	catch (exception&) {
markus@165
   772
		return E_FAIL;
markus@165
   773
	}
vb@18
   774
markus@165
   775
	PEP_rating _rating;
markus@165
   776
	PEP_STATUS status = ::identity_rating(get_session(), _ident, &_rating);
markus@165
   777
	free_identity(_ident);
markus@192
   778
markus@165
   779
	if (status != PEP_STATUS_OK)
markus@189
   780
		return FAIL(L"cannot get message color", status);
vb@18
   781
markus@172
   782
	*pVal = (pEpRating)_rating;
markus@165
   783
	return S_OK;
vb@18
   784
}
vb@48
   785
markus@172
   786
STDMETHODIMP CpEpEngine::ColorFromRating(pEpRating rating, pEpColor * pVal)
markus@164
   787
{
markus@164
   788
	assert(pVal);
markus@164
   789
markus@192
   790
	if (!pVal)
markus@192
   791
		return E_INVALIDARG;
markus@192
   792
markus@164
   793
	PEP_rating engineRating = (PEP_rating)rating;
markus@164
   794
	PEP_color _color = ::color_from_rating(engineRating);
markus@164
   795
markus@172
   796
	*pVal = (pEpColor)_color;
markus@164
   797
markus@164
   798
	return S_OK;
markus@164
   799
}
markus@164
   800
markus@172
   801
STDMETHODIMP CpEpEngine::TrustPersonalKey(struct pEpIdentity *ident, struct pEpIdentity *result)
vb@48
   802
{
markus@165
   803
	::pEp_identity *_ident;
vb@48
   804
markus@165
   805
	assert(ident);
markus@165
   806
	assert(result);
vb@48
   807
markus@192
   808
	if (!ident || !result)
markus@192
   809
		return E_INVALIDARG;
markus@192
   810
markus@165
   811
	try {
markus@165
   812
		_ident = new_identity(ident);
markus@165
   813
	}
markus@165
   814
	catch (bad_alloc&) {
markus@165
   815
		return E_OUTOFMEMORY;
markus@165
   816
	}
markus@165
   817
	catch (exception&) {
markus@165
   818
		return E_FAIL;
markus@165
   819
	}
vb@48
   820
markus@165
   821
	if (verbose_mode) {
markus@165
   822
		stringstream ss;
markus@172
   823
		ss << "TrustPersonalKey called with ";
markus@180
   824
		ss << utf8_string(ident->Address);
markus@165
   825
		ss << L": ";
markus@180
   826
		ss << ident->CommType;
markus@165
   827
		verbose(ss.str());
markus@165
   828
	}
vb@52
   829
markus@165
   830
	PEP_STATUS status = ::trust_personal_key(get_session(), _ident);
vb@52
   831
markus@165
   832
	if (verbose_mode) {
markus@165
   833
		stringstream ss;
markus@165
   834
		ss << "result ";
markus@165
   835
		ss << status;
markus@165
   836
		ss << " for ";
markus@165
   837
		ss << _ident->address;
markus@165
   838
		ss << L": ";
markus@165
   839
		ss << _ident->comm_type;
markus@165
   840
		verbose(ss.str());
markus@165
   841
	}
vb@52
   842
markus@165
   843
	if (status == PEP_STATUS_OK)
markus@165
   844
		copy_identity(result, _ident);
vb@50
   845
markus@165
   846
	free_identity(_ident);
markus@165
   847
	if (status == PEP_OUT_OF_MEMORY)
markus@165
   848
		return E_OUTOFMEMORY;
markus@165
   849
	else if (status != PEP_STATUS_OK)
markus@189
   850
		return FAIL(L"failure while executing TrustPersonalKey()", status);
vb@48
   851
markus@165
   852
	return S_OK;
markus@165
   853
}
markus@165
   854
markus@165
   855
// keysync api
markus@165
   856
markus@169
   857
void CpEpEngine::start_keysync()
markus@165
   858
{
markus@165
   859
	// acquire the lock
markus@165
   860
	std::unique_lock<std::mutex> lock(keysync_mutex);
markus@165
   861
markus@188
   862
	// Assert if we're not already running.
markus@188
   863
    assert(!this->keysync_thread);
markus@165
   864
markus@169
   865
	// Ensure we are not aborting the new thread due to a
markus@169
   866
	// left over flag.
markus@169
   867
	keysync_abort_requested = false;
markus@165
   868
markus@169
   869
	// Init our keysync session
markus@165
   870
	PEP_STATUS status = ::init(&keysync_session);
Dean@187
   871
	::register_sync_callbacks(keysync_session, (void*)this, messageToSend, showHandshake, inject_sync_msg, retrieve_next_sync_msg);
markus@176
   872
	assert(status == PEP_STATUS_OK);
markus@175
   873
markus@175
   874
    attach_sync_session(get_session(), keysync_session);
markus@165
   875
markus@188
   876
    // We need to marshal the callbacks to the keysync thread
markus@188
   877
    LPSTREAM marshaled_callbacks;
markus@188
   878
markus@188
   879
    auto result = CoMarshalInterThreadInterfaceInStream(IID_IpEpEngineCallbacks, client_callbacks, &marshaled_callbacks);
markus@188
   880
    assert(result == S_OK);
markus@188
   881
markus@169
   882
	// Star the keysync thread
markus@188
   883
	keysync_thread = new thread(do_keysync_in_thread, this, marshaled_callbacks);
markus@188
   884
}
markus@165
   885
markus@188
   886
void CpEpEngine::do_keysync_in_thread(CpEpEngine* self, LPSTREAM marshaled_callbacks) 
markus@188
   887
{
markus@188
   888
    assert(self);
markus@192
   889
	assert(marshaled_callbacks);
markus@192
   890
markus@188
   891
    // We need to initialize COM here for successfull delivery of the callbacks.
markus@188
   892
    // As we don't create any COM instances in our thread, the COMINIT value is
markus@188
   893
    // currently irrelevant, so we go with the safest value.
markus@188
   894
    auto res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
markus@188
   895
    assert(res == S_OK);
markus@188
   896
markus@188
   897
    LPVOID vp;
markus@188
   898
markus@188
   899
    res = CoGetInterfaceAndReleaseStream(marshaled_callbacks, IID_IpEpEngineCallbacks, &vp);
markus@188
   900
    assert(SUCCEEDED(res));
markus@188
   901
markus@188
   902
    self->client_callbacks_on_sync_thread = static_cast<IpEpEngineCallbacks*>(vp);
markus@188
   903
markus@188
   904
    ::do_sync_protocol(self->keysync_session, self);
markus@188
   905
markus@188
   906
    self->client_callbacks_on_sync_thread->Release();
markus@188
   907
markus@188
   908
    self->client_callbacks_on_sync_thread = NULL;
markus@188
   909
markus@188
   910
    CoUninitialize();
markus@165
   911
}
markus@165
   912
markus@169
   913
void CpEpEngine::stop_keysync()
markus@165
   914
{
markus@165
   915
	// acquire the lock
markus@165
   916
	std::unique_lock<std::mutex> lock(keysync_mutex);
markus@165
   917
markus@188
   918
    // Do nothing if keysync is not running.
markus@188
   919
    if (!keysync_thread)
markus@188
   920
        return;
markus@165
   921
markus@188
   922
    assert(!keysync_abort_requested);
markus@165
   923
	// signal that we're gonna abort
markus@165
   924
	keysync_abort_requested = true;
markus@165
   925
markus@165
   926
	// Notify the keysync thread
markus@165
   927
	keysync_condition.notify_all();
markus@165
   928
markus@165
   929
	// Wait for the other thread to finish and clean up
markus@188
   930
	while (keysync_abort_requested)
markus@165
   931
		keysync_condition.wait(lock);
markus@165
   932
markus@188
   933
	// collect the child thread for the thread to end
markus@165
   934
	keysync_thread->join();
markus@165
   935
markus@165
   936
	// clean up
markus@165
   937
	delete keysync_thread;
markus@165
   938
	keysync_thread = NULL;
markus@188
   939
markus@188
   940
    ::detach_sync_session(get_session());
markus@169
   941
	::unregister_sync_callbacks(keysync_session);
markus@165
   942
	release(keysync_session);
markus@180
   943
    keysync_session = NULL;
markus@165
   944
}
markus@165
   945
markus@165
   946
int CpEpEngine::inject_sync_msg(void * msg, void * management)
markus@165
   947
{
markus@192
   948
	assert(msg);
markus@192
   949
	assert(management);
markus@165
   950
	// check argument
markus@165
   951
	if (!msg)
markus@165
   952
		return E_INVALIDARG;
markus@169
   953
	if (!management)
markus@165
   954
		return ERROR_INVALID_HANDLE;
markus@165
   955
markus@169
   956
	CpEpEngine* me = (CpEpEngine*)management;
markus@169
   957
markus@165
   958
	// acquire the lock
markus@169
   959
	std::unique_lock<std::mutex> lock(me->keysync_mutex);
markus@165
   960
markus@188
   961
	// check whether we're in a valid state running:
markus@188
   962
	if (!me->keysync_thread)
markus@165
   963
		return E_ASYNC_OPERATION_NOT_STARTED;
markus@165
   964
markus@165
   965
	// queue the message
markus@169
   966
	me->keysync_queue.push(msg);
markus@165
   967
markus@165
   968
	// notify the receivers
markus@169
   969
	me->keysync_condition.notify_all();
markus@170
   970
markus@170
   971
    return S_OK;
markus@165
   972
}
markus@165
   973
Dean@187
   974
void * CpEpEngine::retrieve_next_sync_msg(void * management)
markus@165
   975
{
markus@165
   976
	// sanity check
markus@169
   977
	assert(management);
markus@192
   978
	if (!management)
markus@192
   979
		return NULL;
markus@169
   980
markus@169
   981
	CpEpEngine* me = (CpEpEngine*)management;
markus@165
   982
markus@165
   983
	// acquire the lock
markus@169
   984
	std::unique_lock<std::mutex> lock(me->keysync_mutex);
markus@165
   985
markus@165
   986
	// as long as we're supposed to be active 
markus@165
   987
	// (we won't wait for the queue to empty currently...)
markus@169
   988
	while (!me->keysync_abort_requested)
markus@165
   989
	{
markus@165
   990
		// If the queue is empty, wait for a signal, and try again.
markus@169
   991
		if (me->keysync_queue.empty())
markus@165
   992
		{
markus@169
   993
			me->keysync_condition.wait(lock);
markus@165
   994
			continue;
markus@165
   995
		}
markus@165
   996
markus@165
   997
		// Pop the message and return it.
markus@169
   998
		void* msg = me->keysync_queue.front();
markus@165
   999
		assert(msg);
markus@165
  1000
markus@169
  1001
		me->keysync_queue.pop();
markus@169
  1002
markus@165
  1003
		return msg;
markus@165
  1004
	}
markus@165
  1005
markus@165
  1006
	// we acknowledge that we're quitting...
markus@188
  1007
	me->keysync_abort_requested = false;
markus@165
  1008
markus@165
  1009
	// We signal the main thread that we got his signal
markus@165
  1010
	// so it can gain the mutex again and call join() on us.
markus@169
  1011
	me->keysync_condition.notify_all();
markus@165
  1012
markus@165
  1013
	// and tell the pep engine we're done.
markus@165
  1014
	return NULL;
vb@48
  1015
}
markus@84
  1016
markus@84
  1017
markus@84
  1018
// Event callbacks
markus@84
  1019
markus@172
  1020
STDMETHODIMP CpEpEngine::RegisterCallbacks(IpEpEngineCallbacks* new_callbacks)
markus@84
  1021
{
markus@188
  1022
    // check for valid parameter
markus@188
  1023
    if (!new_callbacks)
markus@188
  1024
        return E_INVALIDARG;
markus@84
  1025
markus@188
  1026
    // don't allow double registration.
markus@188
  1027
    if (this->client_callbacks)
markus@188
  1028
        return E_ILLEGAL_STATE_CHANGE;
markus@188
  1029
markus@188
  1030
    this->client_callbacks = new_callbacks;
markus@188
  1031
    new_callbacks->AddRef();
markus@188
  1032
markus@169
  1033
	start_keysync();
markus@84
  1034
markus@84
  1035
	return S_OK;
markus@84
  1036
}
markus@84
  1037
markus@188
  1038
STDMETHODIMP CpEpEngine::UnregisterCallbacks()
markus@84
  1039
{
markus@188
  1040
    // don't allow double deregistration.
markus@188
  1041
    // S_FALSE still is no error (as double deregistration is not fatal).
markus@188
  1042
    if (!this->client_callbacks)
markus@188
  1043
        return S_FALSE;
markus@84
  1044
markus@188
  1045
    stop_keysync();
markus@169
  1046
markus@188
  1047
    this->client_callbacks->Release();
markus@84
  1048
markus@188
  1049
    this->client_callbacks = NULL;
markus@188
  1050
markus@188
  1051
    return S_OK;
markus@84
  1052
}
markus@84
  1053
markus@177
  1054
STDMETHODIMP CpEpEngine::OpenPGPListKeyinfo(BSTR search_pattern, LPSAFEARRAY* keyinfo_list) {
markus@165
  1055
	assert(keyinfo_list);
krista@154
  1056
markus@165
  1057
	if (keyinfo_list == NULL)
markus@165
  1058
		return E_INVALIDARG;
krista@154
  1059
markus@165
  1060
	string _pattern = "";
markus@165
  1061
	if (search_pattern)
markus@165
  1062
		_pattern = utf8_string(search_pattern);
markus@165
  1063
	::stringpair_list_t* _keyinfo_list = NULL;
krista@154
  1064
markus@165
  1065
	PEP_STATUS status = ::OpenPGP_list_keyinfo(get_session(), _pattern.c_str(), &_keyinfo_list);
markus@165
  1066
	assert(status != PEP_OUT_OF_MEMORY);
markus@165
  1067
	if (status == PEP_OUT_OF_MEMORY)
markus@165
  1068
		return E_OUTOFMEMORY;
krista@154
  1069
markus@165
  1070
	if (status != ::PEP_STATUS_OK)
markus@189
  1071
		return FAIL(L"OpenPGP_list_keyinfo", status);
krista@154
  1072
markus@165
  1073
	if (_keyinfo_list && _keyinfo_list->value) {
markus@165
  1074
		::opt_field_array_from_C(_keyinfo_list, keyinfo_list);
markus@165
  1075
	}
markus@165
  1076
	else {
markus@165
  1077
		::free_stringpair_list(_keyinfo_list);
markus@165
  1078
		return FAIL(L"OpenPGP_list_keyinfo: no keys found");
markus@165
  1079
	}
markus@165
  1080
markus@165
  1081
	::free_stringpair_list(_keyinfo_list);
markus@165
  1082
	return S_OK;
markus@165
  1083
krista@154
  1084
}
krista@154
  1085
markus@172
  1086
HRESULT CpEpEngine::Fire_MessageToSend(TextMessage * msg)
markus@84
  1087
{
markus@188
  1088
	assert(msg);
markus@188
  1089
    assert(this->client_callbacks_on_sync_thread);
markus@84
  1090
markus@192
  1091
	if (!msg)
markus@192
  1092
		return E_INVALIDARG;
markus@192
  1093
markus@192
  1094
	if (!this->client_callbacks_on_sync_thread)
markus@192
  1095
		return E_ILLEGAL_METHOD_CALL;
markus@192
  1096
markus@188
  1097
    auto result = this->client_callbacks_on_sync_thread->MessageToSend(msg);
markus@84
  1098
markus@188
  1099
	return result;
markus@84
  1100
}
markus@84
  1101
markus@172
  1102
HRESULT CpEpEngine::Fire_ShowHandshake(pEpIdentity * self, pEpIdentity * partner, SyncHandshakeResult * result)
markus@84
  1103
{
markus@84
  1104
	assert(self);
markus@84
  1105
	assert(partner);
markus@84
  1106
	assert(result);
markus@188
  1107
    assert(this->client_callbacks_on_sync_thread);
markus@192
  1108
markus@192
  1109
	if (!(self && partner && result))
markus@192
  1110
		return E_INVALIDARG;
markus@192
  1111
	if (!this->client_callbacks_on_sync_thread)
markus@192
  1112
		return E_ILLEGAL_METHOD_CALL;
markus@188
  1113
    	
markus@188
  1114
	auto res = this->client_callbacks_on_sync_thread->ShowHandshake(self, partner, result);
markus@188
  1115
		
markus@188
  1116
	return res;	
markus@84
  1117
}