initial commit
authorVolker Birk <vb@pep-project.org>
Thu, 16 Apr 2015 20:43:31 +0200
changeset 00aa9866d751c
child 1 ba35633c2f5c
initial commit
CpEpEngine.cpp
CpEpEngine.h
ReadMe.txt
_IpEpEngineEvents_CP.h
dlldata.c
locked_queue.hh
pEpCOMServerAdapter.cpp
pEpCOMServerAdapter.idl
pEpCOMServerAdapter.rc
pEpCOMServerAdapter.vcxproj
pEpComAdapter.idl
pEpEngine.rgs
resource.h
stdafx.cpp
stdafx.h
targetver.h
utf8_helper.cpp
utf8_helper.h
xdlldata.c
xdlldata.h
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/CpEpEngine.cpp	Thu Apr 16 20:43:31 2015 +0200
     1.3 @@ -0,0 +1,945 @@
     1.4 +// CpEpEngine.cpp : Implementation of CpEpEngine
     1.5 +
     1.6 +#include "stdafx.h"
     1.7 +#include "CpEpEngine.h"
     1.8 +
     1.9 +
    1.10 +// CpEpEngine
    1.11 +
    1.12 +STDMETHODIMP CpEpEngine::InterfaceSupportsErrorInfo(REFIID riid)
    1.13 +{
    1.14 +	static const IID* const arr[] = 
    1.15 +	{
    1.16 +		&IID_IpEpEngine
    1.17 +	};
    1.18 +
    1.19 +	for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
    1.20 +	{
    1.21 +		if (InlineIsEqualGUID(*arr[i],riid))
    1.22 +			return S_OK;
    1.23 +	}
    1.24 +	return S_FALSE;
    1.25 +}
    1.26 +
    1.27 +#define FAIL(msg) error(msg)
    1.28 +
    1.29 +using namespace std;
    1.30 +
    1.31 +static CComSafeArray<BSTR> string_array(const ::stringlist_t *stringlist)
    1.32 +{
    1.33 +    CComSafeArray<BSTR> sa_string_list;
    1.34 +    int n = 0;
    1.35 +    for (const ::stringlist_t *k = stringlist; k != NULL; k = k->next) {
    1.36 +        if (k->value) {
    1.37 +            HRESULT _result = sa_string_list.Add(utf16_bstr(k->value).Detach(), false);
    1.38 +            assert(_result == S_OK);
    1.39 +            if (_result == E_OUTOFMEMORY)
    1.40 +                throw std::bad_alloc();
    1.41 +            ++n;
    1.42 +        }
    1.43 +    }
    1.44 +
    1.45 +    return sa_string_list;
    1.46 +}
    1.47 +
    1.48 +static ::stringlist_t * new_stringlist(const SAFEARRAY * safearray)
    1.49 +{
    1.50 +    CComSafeArray<BSTR> sa(safearray);
    1.51 +    int n_strings = 0;
    1.52 +    ::stringlist_t *_stringlist = ::new_stringlist((const char *) NULL);
    1.53 +    assert(_stringlist);
    1.54 +    if (_stringlist == NULL)
    1.55 +        throw std::bad_alloc();
    1.56 +
    1.57 +    n_strings = sa.GetUpperBound() - sa.GetLowerBound() + 1;
    1.58 +    ::stringlist_t *k = _stringlist;
    1.59 +    for (int i = 0, j = sa.GetLowerBound(); i<n_strings; ++i, ++j) {
    1.60 +        k = ::stringlist_add(k, utf8_string(sa.GetAt(j)).c_str());
    1.61 +        assert(k);
    1.62 +        if (k == NULL) {
    1.63 +            ::free_stringlist(_stringlist);
    1.64 +            throw std::bad_alloc();
    1.65 +        }
    1.66 +    }
    1.67 +
    1.68 +    return _stringlist;
    1.69 +}
    1.70 +
    1.71 +static ::pEp_identity *new_identity(const pEp_identity_s * ident)
    1.72 +{
    1.73 +    ::pEp_identity *_ident;
    1.74 +
    1.75 +    string _address;
    1.76 +    string _fpr;
    1.77 +    string _user_id;
    1.78 +    string _username;
    1.79 +
    1.80 +    if (ident->address)
    1.81 +        _address = utf8_string(ident->address);
    1.82 +    if (ident->fpr) {
    1.83 +        _fpr = utf8_string(ident->fpr);
    1.84 +        for (auto p = _fpr.begin(); p != _fpr.end(); ++p) {
    1.85 +            if (*p >= 'A' && *p <= 'Z')
    1.86 +                continue;
    1.87 +            if (*p >= '0' && *p <= '9')
    1.88 +                continue;
    1.89 +            throw invalid_argument("invalid hex digits in fingerprint");
    1.90 +        }
    1.91 +    }
    1.92 +    if (ident->user_id)
    1.93 +        _user_id = utf8_string(ident->user_id);
    1.94 +    if (ident->username)
    1.95 +        _username = utf8_string(ident->username);
    1.96 +
    1.97 +    _ident = ::new_identity(_address.c_str(), _fpr.c_str(), _user_id.c_str(), _username.c_str());
    1.98 +    assert(_ident);
    1.99 +    if (_ident == NULL)
   1.100 +        throw bad_alloc();
   1.101 +
   1.102 +    _ident->comm_type = (PEP_comm_type) ident->comm_type;
   1.103 +
   1.104 +    if (ident->lang) {
   1.105 +        string _lang = utf8_string(ident->lang);
   1.106 +        if (_lang.length() != 0) {
   1.107 +            if (_lang.length() != 2) {
   1.108 +                ::free_identity(_ident);
   1.109 +                throw invalid_argument("invalid language code");
   1.110 +            }
   1.111 +            if (_lang[0] < 'a' || _lang[0] > 'z') {
   1.112 +                ::free_identity(_ident);
   1.113 +                throw invalid_argument("invalid language code");
   1.114 +            }
   1.115 +            if (_lang[1] < 'a' || _lang[1] > 'z') {
   1.116 +                ::free_identity(_ident);
   1.117 +                throw invalid_argument("invalid language code");
   1.118 +            }
   1.119 +            _ident->lang[0] = _lang[0];
   1.120 +            _ident->lang[1] = _lang[1];
   1.121 +        }
   1.122 +    }
   1.123 +
   1.124 +    return _ident;
   1.125 +}
   1.126 +
   1.127 +static void copy_identity(pEp_identity_s * ident_s, const pEp_identity * ident)
   1.128 +{
   1.129 +    ::memset(ident_s, 0, sizeof(pEp_identity_s));
   1.130 +
   1.131 +    if (ident->address)
   1.132 +        ident_s->address = utf16_bstr(ident->address).Detach();
   1.133 +    if (ident->fpr)
   1.134 +        ident_s->fpr = utf16_bstr(ident->fpr).Detach();
   1.135 +    if (ident->user_id)
   1.136 +        ident_s->user_id = utf16_bstr(ident->user_id).Detach();
   1.137 +    if (ident->username)
   1.138 +        ident_s->username = utf16_bstr(ident->username).Detach();
   1.139 +    ident_s->comm_type = (pEp_comm_type) ident->comm_type;
   1.140 +    if (ident->lang)
   1.141 +        ident_s->lang = utf16_bstr(ident->lang).Detach();
   1.142 +}
   1.143 +
   1.144 +// CpEpEngine
   1.145 +
   1.146 +::pEp_identity *CpEpEngine::new_identity(const CpEpEngine::pEp_identity_cpp& ident)
   1.147 +{
   1.148 +    ::pEp_identity *_ident = ::new_identity(ident.address.c_str(), ident.fpr.c_str(), ident.user_id.c_str(), ident.username.c_str());
   1.149 +    assert(_ident);
   1.150 +    if (_ident == NULL)
   1.151 +        throw bad_alloc();
   1.152 +
   1.153 +    _ident->comm_type = (::PEP_comm_type) ident.comm_type;
   1.154 +    _ident->me = ident.me;
   1.155 +
   1.156 +    assert(ident.lang.size() == 0 || ident.lang.size() == 2);
   1.157 +
   1.158 +    if (ident.lang.size()) {
   1.159 +        _ident->lang[0] = ident.lang[0];
   1.160 +        _ident->lang[1] = ident.lang[1];
   1.161 +    }
   1.162 +
   1.163 +    return _ident;
   1.164 +}
   1.165 +
   1.166 +STDMETHODIMP CpEpEngine::log(BSTR title, BSTR entity, BSTR description, BSTR comment)
   1.167 +{
   1.168 +    string _title;
   1.169 +    string _entity;
   1.170 +    string _description;
   1.171 +    string _comment;
   1.172 +    HRESULT result = S_OK;
   1.173 +
   1.174 +    assert(title);
   1.175 +    if (title)
   1.176 +        _title = utf8_string(title);
   1.177 +    else
   1.178 +        result = E_INVALIDARG;
   1.179 +
   1.180 +    assert(entity);
   1.181 +    if (entity)
   1.182 +        _entity = utf8_string(entity);
   1.183 +    else
   1.184 +        result = E_INVALIDARG;
   1.185 +
   1.186 +    if (description)
   1.187 +        _description = utf8_string(description);
   1.188 +
   1.189 +    if (comment)
   1.190 +        _comment = utf8_string(comment);
   1.191 +
   1.192 +    if (result != S_OK)
   1.193 +        return result;
   1.194 +
   1.195 +    PEP_STATUS _status = ::log_event(get_session(), _title.c_str(), _entity.c_str(), _description.c_str(), _comment.c_str());
   1.196 +    assert(_status == PEP_STATUS_OK);
   1.197 +    if (_status != PEP_STATUS_OK)
   1.198 +        return FAIL(L"log_event");
   1.199 +    else
   1.200 +        return S_OK;
   1.201 +}
   1.202 +
   1.203 +
   1.204 +STDMETHODIMP CpEpEngine::decrypt(BSTR ctext, BSTR * ptext, LPSAFEARRAY * key_list, pEp_STATUS * status)
   1.205 +{
   1.206 +    assert(ctext);
   1.207 +    assert(ptext);
   1.208 +    assert(key_list);
   1.209 +    assert(status);
   1.210 +
   1.211 +    if (ctext == NULL || ptext == NULL || key_list == NULL || status == NULL) {
   1.212 +        if (ptext)
   1.213 +            *ptext = NULL;
   1.214 +        if (key_list)
   1.215 +            *key_list = NULL;
   1.216 +        if (status)
   1.217 +            *status = pEp_UNENCRYPTED;
   1.218 +        return E_INVALIDARG;
   1.219 +    }
   1.220 +
   1.221 +    string _ctext = utf8_string(ctext);
   1.222 +
   1.223 +    char *_ptext = NULL;
   1.224 +    size_t _psize = 0;
   1.225 +    ::stringlist_t *_keylist = NULL;
   1.226 +    PEP_STATUS _status;
   1.227 +
   1.228 +    _status = ::decrypt_and_verify(get_session(), _ctext.c_str(), _ctext.size(), &_ptext, &_psize, &_keylist);
   1.229 +    assert(_status != PEP_OUT_OF_MEMORY);
   1.230 +    if (_status == PEP_OUT_OF_MEMORY)
   1.231 +        return E_OUTOFMEMORY;
   1.232 +
   1.233 +    *status = (pEp_STATUS) _status;
   1.234 +    if (_ptext == NULL) {
   1.235 +        if (_keylist) {
   1.236 +            string msg;
   1.237 +            if (_keylist->value[0] != 0) {
   1.238 +                msg = _keylist->value;
   1.239 +            }
   1.240 +            else {
   1.241 +                for (::stringlist_t *s = _keylist->next; s != NULL; s = s->next) {
   1.242 +                    if (s->value) {
   1.243 +                        msg += s->value;
   1.244 +                        msg += ";";
   1.245 +                    }
   1.246 +                }
   1.247 +            }
   1.248 +            ::free_stringlist(_keylist);
   1.249 +
   1.250 +            return FAIL(utf16_bstr(msg));
   1.251 +        }
   1.252 +        else
   1.253 +            return FAIL(L"cannot decrypt");
   1.254 +    }
   1.255 +
   1.256 +    *ptext = utf16_bstr(_ptext).Detach();
   1.257 +    pEp_free(_ptext);
   1.258 +
   1.259 +    if (_keylist && _keylist->value)
   1.260 +        *key_list = string_array(_keylist).Detach();
   1.261 +    else
   1.262 +        *key_list = NULL;
   1.263 +    ::free_stringlist(_keylist);
   1.264 +
   1.265 +    return S_OK;
   1.266 +}
   1.267 +
   1.268 +STDMETHODIMP CpEpEngine::decrypt_b(BSTR ctext, LPSAFEARRAY * ptext, LPSAFEARRAY * key_list, pEp_STATUS * status)
   1.269 +{
   1.270 +    assert(ctext);
   1.271 +    assert(ptext);
   1.272 +    assert(key_list);
   1.273 +    assert(status);
   1.274 +
   1.275 +    if (ctext == NULL || ptext == NULL || key_list == NULL || status == NULL) {
   1.276 +        if (ptext)
   1.277 +            *ptext = NULL;
   1.278 +        if (key_list)
   1.279 +            *key_list = NULL;
   1.280 +        if (status)
   1.281 +            *status = pEp_UNENCRYPTED;
   1.282 +        return E_INVALIDARG;
   1.283 +    }
   1.284 +
   1.285 +    // Welcome to Windoze string hell!
   1.286 +
   1.287 +    char *_ctext = NULL;
   1.288 +    _bstr_t bstr_ctext(ctext, true);
   1.289 +    int w_csize = bstr_ctext.length() + 1;
   1.290 +    int _csize = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, (wchar_t *) bstr_ctext, w_csize, NULL, 0, NULL, NULL);
   1.291 +    if (_csize) {
   1.292 +        _ctext = new char[_csize];
   1.293 +        WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, (wchar_t *) bstr_ctext, w_csize, _ctext, _csize, NULL, NULL);
   1.294 +    }
   1.295 +
   1.296 +    char *_ptext = NULL;
   1.297 +    size_t _psize = 0;
   1.298 +    ::stringlist_t *_keylist = NULL;
   1.299 +    PEP_STATUS _status;
   1.300 +
   1.301 +    _status = ::decrypt_and_verify(get_session(), _ctext, _csize, &_ptext, &_psize, &_keylist);
   1.302 +    assert(_status != PEP_OUT_OF_MEMORY);
   1.303 +    delete[] _ctext;
   1.304 +    if (_status == PEP_OUT_OF_MEMORY) {
   1.305 +        ::free_stringlist(_keylist);
   1.306 +        return E_OUTOFMEMORY;
   1.307 +    }
   1.308 +    *status = (pEp_STATUS) _status;
   1.309 +
   1.310 +    if (_ptext == NULL) {
   1.311 +        ::free_stringlist(_keylist);
   1.312 +        return FAIL(L"decrypt_and_verify");
   1.313 +    }
   1.314 +
   1.315 +    CComSafeArray<BYTE> sa_ptext;
   1.316 +
   1.317 +    HRESULT _result = sa_ptext.Create(_psize, 0);
   1.318 +    assert(_result == S_OK);
   1.319 +    if (_result == E_OUTOFMEMORY) {
   1.320 +        pEp_free(_ptext);
   1.321 +        ::free_stringlist(_keylist);
   1.322 +        return E_OUTOFMEMORY;
   1.323 +    }
   1.324 +    else if (_result != S_OK) {
   1.325 +        pEp_free(_ptext);
   1.326 +        ::free_stringlist(_keylist);
   1.327 +        return FAIL(L"CComSafeArray<BYTE>::Create");
   1.328 +    }
   1.329 +
   1.330 +    memcpy(sa_ptext.m_psa->pvData, _ptext, _psize);
   1.331 +    *ptext = sa_ptext.Detach();
   1.332 +    ::pEp_free(_ptext);
   1.333 +
   1.334 +    if (_keylist && _keylist->value)
   1.335 +        *key_list = string_array(_keylist).Detach();
   1.336 +    else
   1.337 +        *key_list = NULL;
   1.338 +    ::free_stringlist(_keylist);
   1.339 +
   1.340 +    return S_OK;
   1.341 +}
   1.342 +
   1.343 +STDMETHODIMP CpEpEngine::verify(BSTR text, BSTR signature, LPSAFEARRAY * key_list, pEp_STATUS * verify_status)
   1.344 +{
   1.345 +    assert(text);
   1.346 +    assert(signature);
   1.347 +    assert(key_list);
   1.348 +
   1.349 +    if (text == NULL || signature == NULL || key_list == NULL)
   1.350 +        return E_INVALIDARG;
   1.351 +
   1.352 +    string _text = utf8_string(text);
   1.353 +    string _signature = utf8_string(signature);
   1.354 +
   1.355 +    ::stringlist_t *_keylist = NULL;
   1.356 +    PEP_STATUS _status;
   1.357 +    _status = ::verify_text(get_session(), _text.c_str(), _text.size(), _signature.c_str(), _signature.size(), &_keylist);
   1.358 +    assert(_status != PEP_OUT_OF_MEMORY);
   1.359 +    if (_status == PEP_OUT_OF_MEMORY)
   1.360 +        return E_OUTOFMEMORY;
   1.361 +    if (_status == PEP_DECRYPT_WRONG_FORMAT || _status == PEP_UNKNOWN_ERROR)
   1.362 +        return FAIL(L"verify_text");
   1.363 +
   1.364 +    *verify_status = (pEp_STATUS) _status;
   1.365 +
   1.366 +    if (_keylist && _keylist->value)
   1.367 +        *key_list = string_array(_keylist).Detach();
   1.368 +    else
   1.369 +        *key_list = NULL;
   1.370 +    ::free_stringlist(_keylist);
   1.371 +
   1.372 +    return S_OK;
   1.373 +}
   1.374 +
   1.375 +STDMETHODIMP CpEpEngine::encrypt(SAFEARRAY * key_list, BSTR ptext, BSTR * ctext, pEp_STATUS * status)
   1.376 +{
   1.377 +    assert(key_list);
   1.378 +    assert(ptext);
   1.379 +    assert(ctext);
   1.380 +    assert(status);
   1.381 +
   1.382 +    if (ctext == NULL || ptext == NULL || key_list == NULL || status == NULL) {
   1.383 +        if (ctext)
   1.384 +            *ctext = NULL;
   1.385 +        if (status)
   1.386 +            *status = pEp_UNKNOWN_ERROR;
   1.387 +        return E_INVALIDARG;
   1.388 +    }
   1.389 +
   1.390 +    HRESULT result = S_OK;
   1.391 +
   1.392 +    ::stringlist_t *_keylist = new_stringlist(key_list);
   1.393 +    string _ptext = utf8_string(ptext);
   1.394 +
   1.395 +    char *_ctext = NULL;
   1.396 +    size_t _csize = 0;
   1.397 +    PEP_STATUS _status;
   1.398 +
   1.399 +    _status = ::encrypt_and_sign(get_session(), _keylist, _ptext.c_str(), _ptext.size(), &_ctext, &_csize);
   1.400 +
   1.401 +    assert(_status != PEP_OUT_OF_MEMORY);
   1.402 +    ::free_stringlist(_keylist);
   1.403 +    if (_status == PEP_OUT_OF_MEMORY)
   1.404 +        return E_OUTOFMEMORY;
   1.405 +    *status = (pEp_STATUS) _status;
   1.406 +
   1.407 +    if (_ctext == NULL)
   1.408 +        return FAIL(L"encrypt_and_sign");
   1.409 +
   1.410 +    *ctext = utf16_bstr(_ctext).Detach();
   1.411 +    pEp_free(_ctext);
   1.412 +
   1.413 +    return S_OK;
   1.414 +}
   1.415 +
   1.416 +STDMETHODIMP CpEpEngine::encrypt_b(SAFEARRAY * key_list, SAFEARRAY * ptext, BSTR * ctext, pEp_STATUS * status)
   1.417 +{
   1.418 +    assert(key_list);
   1.419 +    assert(ptext);
   1.420 +    assert(ctext);
   1.421 +    assert(status);
   1.422 +
   1.423 +    if (ctext == NULL || ptext == NULL || key_list == NULL || status == NULL) {
   1.424 +        if (ctext)
   1.425 +            *ctext = NULL;
   1.426 +        if (status)
   1.427 +            *status = pEp_UNKNOWN_ERROR;
   1.428 +        return E_INVALIDARG;
   1.429 +    }
   1.430 +
   1.431 +    HRESULT result = S_OK;
   1.432 +
   1.433 +    ::stringlist_t *_keylist = new_stringlist(key_list);
   1.434 +
   1.435 +    char *_ctext = NULL;
   1.436 +    size_t _csize = 0;
   1.437 +    ::PEP_STATUS _status;
   1.438 +
   1.439 +    _status = ::encrypt_and_sign(get_session(), _keylist, (const char *) ptext->pvData, ptext->rgsabound[0].cElements, &_ctext, &_csize);
   1.440 +    assert(_status != PEP_OUT_OF_MEMORY);
   1.441 +    ::free_stringlist(_keylist);
   1.442 +    if (_status == PEP_OUT_OF_MEMORY)
   1.443 +        return E_OUTOFMEMORY;
   1.444 +    *status = (pEp_STATUS) _status;
   1.445 +
   1.446 +    if (_ctext == NULL)
   1.447 +        return FAIL(L"encrypt_and_sign");
   1.448 +
   1.449 +    *status = (pEp_STATUS) _status;
   1.450 +    wchar_t *w_ctext = NULL;
   1.451 +    int w_csize = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, _ctext, _csize, NULL, 0);
   1.452 +    if (w_csize) {
   1.453 +        w_ctext = new wchar_t[w_csize + 1];
   1.454 +        MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, _ctext, _csize, w_ctext, w_csize);
   1.455 +        w_ctext[w_csize] = 0; // this is for debugging; Visual Studio will crash without that if you're unlucky
   1.456 +    }
   1.457 +    *ctext = ::SysAllocStringLen(w_ctext, w_csize);
   1.458 +    assert(ctext);
   1.459 +    delete[] w_ctext;
   1.460 +    pEp_free(_ctext);
   1.461 +    if (ctext == NULL)
   1.462 +        return E_OUTOFMEMORY;
   1.463 +
   1.464 +    return S_OK;
   1.465 +}
   1.466 +
   1.467 +STDMETHODIMP CpEpEngine::safeword(LONG value, BSTR lang, BSTR * word)
   1.468 +{
   1.469 +    assert(value >= 0 && value <= 65535);
   1.470 +    assert(word);
   1.471 +
   1.472 +    HRESULT result = S_OK;
   1.473 +
   1.474 +    uint16_t _value = 0;
   1.475 +    if (value < 0 || value > 65535)
   1.476 +        result = E_INVALIDARG;
   1.477 +    else
   1.478 +        _value = (uint16_t) value;
   1.479 +
   1.480 +    string _lang = "en";
   1.481 +    if (lang) {
   1.482 +        _lang = utf8_string(lang);
   1.483 +        if (_lang.length() != 2)
   1.484 +            result = E_INVALIDARG;
   1.485 +    }
   1.486 +
   1.487 +    if (word == NULL)
   1.488 +        result = E_INVALIDARG;
   1.489 +
   1.490 +    if (result != S_OK)
   1.491 +        return result;
   1.492 +
   1.493 +    char *_word = NULL;
   1.494 +    size_t _wsize = 0;
   1.495 +
   1.496 +    PEP_STATUS status = ::safeword(get_session(), _value, _lang.c_str(), &_word, &_wsize);
   1.497 +    assert(status != PEP_OUT_OF_MEMORY);
   1.498 +    if (status == PEP_OUT_OF_MEMORY)
   1.499 +        return E_OUTOFMEMORY;
   1.500 +
   1.501 +    if (_word == NULL) {
   1.502 +        *word = NULL;
   1.503 +        return FAIL(L"safeword");
   1.504 +    }
   1.505 +    else {
   1.506 +        *word = utf16_bstr(_word).Detach();
   1.507 +        pEp_free(_word);
   1.508 +        return S_OK;
   1.509 +    }
   1.510 +}
   1.511 +
   1.512 +STDMETHODIMP CpEpEngine::safewords(BSTR fpr, BSTR lang, LONG max_words, BSTR * words)
   1.513 +{
   1.514 +    assert(fpr);
   1.515 +    assert(max_words >= 0);
   1.516 +    assert(words);
   1.517 +
   1.518 +    HRESULT result = S_OK;
   1.519 +
   1.520 +    string _fpr;
   1.521 +    if (fpr)
   1.522 +        _fpr = utf8_string(fpr);
   1.523 +    else
   1.524 +        result = E_INVALIDARG;
   1.525 +
   1.526 +    string _lang;
   1.527 +    if (lang) {
   1.528 +        _lang = utf8_string(lang);
   1.529 +        if (_lang.length()) {
   1.530 +            if (_lang.length() != 2)
   1.531 +                result = E_INVALIDARG;
   1.532 +        }
   1.533 +        else
   1.534 +            _lang = "en";
   1.535 +    }
   1.536 +    else
   1.537 +        _lang = "en";
   1.538 +
   1.539 +    if (max_words < 0)
   1.540 +        result = E_INVALIDARG;
   1.541 +
   1.542 +    if (words == NULL)
   1.543 +        result = E_INVALIDARG;
   1.544 +
   1.545 +    if (result != S_OK)
   1.546 +        return result;
   1.547 +
   1.548 +    char *_words = NULL;
   1.549 +    size_t _wsize = 0;
   1.550 +
   1.551 +    PEP_STATUS status = ::safewords(get_session(), _fpr.c_str(), _lang.c_str(), &_words, &_wsize, max_words);
   1.552 +    assert(status != PEP_OUT_OF_MEMORY);
   1.553 +    if (status == PEP_OUT_OF_MEMORY)
   1.554 +        return E_OUTOFMEMORY;
   1.555 +
   1.556 +    if (_words == NULL) {
   1.557 +        *words = NULL;
   1.558 +        return FAIL(L"safewords");
   1.559 +    }
   1.560 +    else {
   1.561 +        *words = utf16_bstr(_words).Detach();
   1.562 +        pEp_free(_words);
   1.563 +        return S_OK;
   1.564 +    }
   1.565 +}
   1.566 +
   1.567 +STDMETHODIMP CpEpEngine::get_identity(BSTR address, pEp_identity_s * ident)
   1.568 +{
   1.569 +    assert(address);
   1.570 +    assert(ident);
   1.571 +
   1.572 +    if (address == NULL)
   1.573 +        return E_INVALIDARG;
   1.574 +
   1.575 +    if (ident == NULL)
   1.576 +        return E_INVALIDARG;
   1.577 +
   1.578 +    string _address = utf8_string(address);
   1.579 +    ::pEp_identity *_ident = NULL;
   1.580 +    PEP_STATUS status = ::get_identity(get_session(), _address.c_str(), &_ident);
   1.581 +    assert(status != PEP_OUT_OF_MEMORY);
   1.582 +    if (status == PEP_OUT_OF_MEMORY)
   1.583 +        return E_OUTOFMEMORY;
   1.584 +
   1.585 +    if (_ident == NULL) {
   1.586 +        return FAIL(L"get_identity");
   1.587 +    }
   1.588 +
   1.589 +    copy_identity(ident, _ident);
   1.590 +    ::free_identity(_ident);
   1.591 +
   1.592 +    return S_OK;
   1.593 +}
   1.594 +
   1.595 +STDMETHODIMP CpEpEngine::set_identity(pEp_identity_s * ident)
   1.596 +{
   1.597 +    assert(ident);
   1.598 +    assert(ident->address);
   1.599 +    assert(ident->fpr);
   1.600 +    assert(ident->username);
   1.601 +    assert(ident->user_id);
   1.602 +
   1.603 +    if (ident == NULL || ident->address == NULL || ident->fpr == NULL
   1.604 +        || ident->username == NULL || ident->user_id == NULL)
   1.605 +        return E_INVALIDARG;
   1.606 +
   1.607 +    ::pEp_identity *_ident = new_identity(ident);
   1.608 +    ::PEP_STATUS status = ::set_identity(get_session(), _ident);
   1.609 +    ::free_identity(_ident);
   1.610 +
   1.611 +    if (status != ::PEP_STATUS_OK)
   1.612 +        return FAIL(L"set_identity");
   1.613 +    else
   1.614 +        return S_OK;
   1.615 +}
   1.616 +
   1.617 +STDMETHODIMP CpEpEngine::generate_keypair(pEp_identity_s * ident, BSTR * fpr)
   1.618 +{
   1.619 +    assert(ident);
   1.620 +    assert(ident->address);
   1.621 +    assert(ident->username);
   1.622 +    assert(fpr);
   1.623 +
   1.624 +    if (ident == NULL || ident->address == NULL || ident->username == NULL || fpr == NULL)
   1.625 +        return E_INVALIDARG;
   1.626 +
   1.627 +    ::pEp_identity *_ident = new_identity(ident);
   1.628 +    ::pEp_free(_ident->fpr);
   1.629 +    _ident->fpr = NULL;
   1.630 +
   1.631 +    ::PEP_STATUS status = ::generate_keypair(get_session(), _ident);
   1.632 +    assert(status != ::PEP_OUT_OF_MEMORY);
   1.633 +    if (status == ::PEP_OUT_OF_MEMORY) {
   1.634 +        ::free_identity(_ident);
   1.635 +        return E_OUTOFMEMORY;
   1.636 +    }
   1.637 +
   1.638 +    if (_ident->fpr)
   1.639 +        *fpr = utf16_bstr(_ident->fpr).Detach();
   1.640 +
   1.641 +    ::free_identity(_ident);
   1.642 +
   1.643 +    if (status != ::PEP_STATUS_OK)
   1.644 +        return FAIL(L"generate_keypair");
   1.645 +
   1.646 +    return S_OK;
   1.647 +}
   1.648 +
   1.649 +STDMETHODIMP CpEpEngine::delete_keypair(BSTR fpr)
   1.650 +{
   1.651 +    assert(fpr);
   1.652 +
   1.653 +    if (fpr == NULL)
   1.654 +        return E_INVALIDARG;
   1.655 +
   1.656 +    string _fpr = utf8_string(fpr);
   1.657 +
   1.658 +    ::PEP_STATUS status = ::delete_keypair(get_session(), _fpr.c_str());
   1.659 +    assert(status != PEP_OUT_OF_MEMORY);
   1.660 +    if (status == PEP_OUT_OF_MEMORY)
   1.661 +        return E_OUTOFMEMORY;
   1.662 +
   1.663 +    if (status != ::PEP_STATUS_OK)
   1.664 +        return FAIL(L"delete_keypair");
   1.665 +    else
   1.666 +        return S_OK;
   1.667 +}
   1.668 +
   1.669 +STDMETHODIMP CpEpEngine::import_key(BSTR key_data)
   1.670 +{
   1.671 +    assert(key_data);
   1.672 +
   1.673 +    if (key_data == NULL)
   1.674 +        return E_INVALIDARG;
   1.675 +
   1.676 +    string _key_data = utf8_string(key_data);
   1.677 +
   1.678 +    PEP_STATUS status = ::import_key(get_session(), _key_data.c_str(), _key_data.length());
   1.679 +    assert(status != PEP_OUT_OF_MEMORY);
   1.680 +    if (status == PEP_OUT_OF_MEMORY)
   1.681 +        return E_OUTOFMEMORY;
   1.682 +
   1.683 +    if (status != pEp_STATUS_OK)
   1.684 +        return FAIL(L"import_key");
   1.685 +    else
   1.686 +        return S_OK;
   1.687 +}
   1.688 +
   1.689 +STDMETHODIMP CpEpEngine::import_key_b(SAFEARRAY * key_data)
   1.690 +{
   1.691 +    assert(key_data);
   1.692 +
   1.693 +    if (key_data == NULL)
   1.694 +        return E_INVALIDARG;
   1.695 +
   1.696 +    ::PEP_STATUS status = ::import_key(get_session(), (const char *) key_data->pvData, key_data->rgsabound[0].cElements);
   1.697 +    assert(status != ::PEP_OUT_OF_MEMORY);
   1.698 +    if (status == ::PEP_OUT_OF_MEMORY)
   1.699 +        return E_OUTOFMEMORY;
   1.700 +
   1.701 +    if (status != ::PEP_STATUS_OK)
   1.702 +        return FAIL(L"import_key");
   1.703 +    else
   1.704 +        return S_OK;
   1.705 +}
   1.706 +
   1.707 +STDMETHODIMP CpEpEngine::export_key(BSTR fpr, BSTR * key_data)
   1.708 +{
   1.709 +    assert(fpr);
   1.710 +    assert(key_data);
   1.711 +
   1.712 +    if (fpr == NULL || key_data == NULL)
   1.713 +        return E_INVALIDARG;
   1.714 +
   1.715 +    string _fpr = utf8_string(fpr);
   1.716 +    char *_key_data = NULL;
   1.717 +    size_t _size = 0;
   1.718 +
   1.719 +    ::PEP_STATUS status = ::export_key(get_session(), _fpr.c_str(), &_key_data, &_size);
   1.720 +    assert(status != ::PEP_OUT_OF_MEMORY);
   1.721 +    if (status == ::PEP_OUT_OF_MEMORY)
   1.722 +        return E_OUTOFMEMORY;
   1.723 +
   1.724 +    if (status != ::PEP_STATUS_OK)
   1.725 +        return FAIL(L"export_key");
   1.726 +
   1.727 +    _bstr_t b_key_data(utf16_string(_key_data).c_str());
   1.728 +    pEp_free(_key_data);
   1.729 +    *key_data = b_key_data.Detach();
   1.730 +
   1.731 +    return S_OK;
   1.732 +}
   1.733 +
   1.734 +STDMETHODIMP CpEpEngine::recv_key(BSTR pattern)
   1.735 +{
   1.736 +    assert(pattern);
   1.737 +
   1.738 +    if (pattern == NULL)
   1.739 +        return E_INVALIDARG;
   1.740 +
   1.741 +    string _pattern = utf8_string(pattern);
   1.742 +
   1.743 +    PEP_STATUS status = ::recv_key(get_session(), _pattern.c_str());
   1.744 +    assert(status != PEP_OUT_OF_MEMORY);
   1.745 +    if (status == PEP_OUT_OF_MEMORY)
   1.746 +        return E_OUTOFMEMORY;
   1.747 +
   1.748 +    if (status != ::PEP_STATUS_OK)
   1.749 +        return FAIL(L"recv_key");
   1.750 +    else
   1.751 +        return S_OK;
   1.752 +}
   1.753 +
   1.754 +STDMETHODIMP CpEpEngine::find_keys(BSTR pattern, LPSAFEARRAY * key_list)
   1.755 +{
   1.756 +    assert(pattern);
   1.757 +    assert(key_list);
   1.758 +
   1.759 +    if (pattern == NULL || key_list == NULL)
   1.760 +        return E_INVALIDARG;
   1.761 +
   1.762 +    string _pattern = utf8_string(pattern);
   1.763 +    ::stringlist_t *_keylist = NULL;
   1.764 +
   1.765 +    PEP_STATUS status = ::find_keys(get_session(), _pattern.c_str(), &_keylist);
   1.766 +    assert(status != PEP_OUT_OF_MEMORY);
   1.767 +    if (status == PEP_OUT_OF_MEMORY)
   1.768 +        return E_OUTOFMEMORY;
   1.769 +
   1.770 +    if (status != ::PEP_STATUS_OK)
   1.771 +        return FAIL(L"find_keys");
   1.772 +
   1.773 +    if (_keylist && _keylist->value) {
   1.774 +        *key_list = string_array(_keylist).Detach();
   1.775 +    }
   1.776 +    else {
   1.777 +        ::free_stringlist(_keylist);
   1.778 +        return FAIL(L"find_keys: no keys found");
   1.779 +    }
   1.780 +
   1.781 +    ::free_stringlist(_keylist);
   1.782 +    return S_OK;
   1.783 +}
   1.784 +
   1.785 +STDMETHODIMP CpEpEngine::send_key(BSTR pattern)
   1.786 +{
   1.787 +    assert(pattern);
   1.788 +
   1.789 +    if (pattern == NULL)
   1.790 +        return E_INVALIDARG;
   1.791 +
   1.792 +    string _pattern = utf8_string(pattern);
   1.793 +
   1.794 +    ::PEP_STATUS status = ::send_key(get_session(), _pattern.c_str());
   1.795 +
   1.796 +    if (status != ::PEP_STATUS_OK)
   1.797 +        return FAIL(L"send_key");
   1.798 +    else
   1.799 +        return S_OK;
   1.800 +}
   1.801 +
   1.802 +STDMETHODIMP CpEpEngine::examine_identity(pEp_identity_s * ident)
   1.803 +{
   1.804 +    assert(ident);
   1.805 +    if (ident == NULL)
   1.806 +        return E_INVALIDARG;
   1.807 +
   1.808 +    try {
   1.809 +        identity_queue->push_back(ident);
   1.810 +    }
   1.811 +    catch (bad_alloc) {
   1.812 +        return E_OUTOFMEMORY;
   1.813 +    }
   1.814 +
   1.815 +    return S_OK;
   1.816 +}
   1.817 +
   1.818 +STDMETHODIMP CpEpEngine::examine_myself(pEp_identity_s * myself)
   1.819 +{
   1.820 +    assert(myself);
   1.821 +    if (myself == NULL)
   1.822 +        return E_INVALIDARG;
   1.823 +
   1.824 +    pEp_identity_cpp _ident(myself);
   1.825 +    _ident.me = true;
   1.826 +
   1.827 +    ::log_event(get_session(), "examine_myself", "debug", _ident.address.c_str(), NULL);
   1.828 +    try {
   1.829 +        identity_queue->push_front(_ident);
   1.830 +    }
   1.831 +    catch (bad_alloc) {
   1.832 +        return E_OUTOFMEMORY;
   1.833 +    }
   1.834 +
   1.835 +    return S_OK;
   1.836 +}
   1.837 +
   1.838 +STDMETHODIMP CpEpEngine::myself(struct pEp_identity_s *ident, struct pEp_identity_s *result)
   1.839 +{
   1.840 +    assert(ident);
   1.841 +    assert(result);
   1.842 +
   1.843 +    if (ident == NULL || result == NULL)
   1.844 +        return E_INVALIDARG;
   1.845 +
   1.846 +    ::pEp_identity *_ident = new_identity(ident);
   1.847 +    assert(_ident);
   1.848 +    if (_ident == NULL)
   1.849 +        return E_OUTOFMEMORY;
   1.850 +
   1.851 +    PEP_STATUS status = ::myself(get_session(), _ident);
   1.852 +
   1.853 +    if (status == PEP_STATUS_OK) {
   1.854 +        assert(_ident->fpr);
   1.855 +        copy_identity(result, _ident);
   1.856 +        ::free_identity(_ident);
   1.857 +        return S_OK;
   1.858 +    }
   1.859 +    else {
   1.860 +        ::free_identity(_ident);
   1.861 +        if (status == PEP_OUT_OF_MEMORY)
   1.862 +            return E_OUTOFMEMORY;
   1.863 +        else
   1.864 +            return FAIL(L"myself");
   1.865 +    }
   1.866 +}
   1.867 +
   1.868 +STDMETHODIMP CpEpEngine::update_identity(struct pEp_identity_s *ident, struct pEp_identity_s *result)
   1.869 +{
   1.870 +    assert(ident);
   1.871 +    assert(result);
   1.872 +
   1.873 +    if (ident == NULL || result == NULL)
   1.874 +        return E_INVALIDARG;
   1.875 +
   1.876 +    ::pEp_identity *_ident = new_identity(ident);
   1.877 +    assert(_ident);
   1.878 +    if (_ident == NULL)
   1.879 +        return E_OUTOFMEMORY;
   1.880 +
   1.881 +    PEP_STATUS status = ::update_identity(get_session(), _ident);
   1.882 +
   1.883 +    if (status == PEP_STATUS_OK) {
   1.884 +        assert(_ident->fpr);
   1.885 +        copy_identity(result, _ident);
   1.886 +        if (_ident->comm_type == PEP_ct_unknown || _ident->comm_type == PEP_ct_key_expired) {
   1.887 +            pEp_identity_cpp _ident_cpp(_ident);
   1.888 +            identity_queue->push_back(_ident_cpp);
   1.889 +        }
   1.890 +        ::free_identity(_ident);
   1.891 +        return S_OK;
   1.892 +    }
   1.893 +    else {
   1.894 +        ::free_identity(_ident);
   1.895 +        if (status == PEP_OUT_OF_MEMORY)
   1.896 +            return E_OUTOFMEMORY;
   1.897 +        else
   1.898 +            return FAIL(L"update_identity");
   1.899 +    }
   1.900 +}
   1.901 +
   1.902 +::pEp_identity * CpEpEngine::retrieve_next_identity(void *management)
   1.903 +{
   1.904 +    assert(management);
   1.905 +    identity_queue_t *iq = (identity_queue_t *) management;
   1.906 +
   1.907 +    do /* poll queue */ {
   1.908 +        if (iq->size())
   1.909 +            break;
   1.910 +        ::Sleep(100);
   1.911 +    } while (true);
   1.912 +
   1.913 +    ::pEp_identity *_ident;
   1.914 +    pEp_identity_cpp& ident = iq->front();
   1.915 +
   1.916 +    if (ident.address.size() == 0) {
   1.917 +        delete iq;
   1.918 +        return NULL;
   1.919 +    }
   1.920 +
   1.921 +    _ident = new_identity(ident);
   1.922 +    iq->pop_front();
   1.923 +
   1.924 +    return _ident;
   1.925 +}
   1.926 +
   1.927 +HRESULT CpEpEngine::error(_bstr_t msg)
   1.928 +{
   1.929 +    _bstr_t helpFile = L"";
   1.930 +    _bstr_t source = L"pEp COM Adapter";
   1.931 +
   1.932 +    ICreateErrorInfo *cei;
   1.933 +    if (SUCCEEDED(CreateErrorInfo(&cei))) {
   1.934 +        cei->SetDescription(msg);
   1.935 +        cei->SetGUID(__uuidof(IpEpEngine));
   1.936 +        cei->SetHelpContext(0);
   1.937 +        cei->SetHelpFile(helpFile);
   1.938 +        cei->SetSource(source);
   1.939 +
   1.940 +        IErrorInfo *errinfo;
   1.941 +        if (SUCCEEDED(cei->QueryInterface(IID_IErrorInfo, (LPVOID FAR*) &errinfo))) {
   1.942 +            SetErrorInfo(0, errinfo);
   1.943 +            errinfo->Release();
   1.944 +        }
   1.945 +        cei->Release();
   1.946 +    }
   1.947 +    return E_FAIL;
   1.948 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/CpEpEngine.h	Thu Apr 16 20:43:31 2015 +0200
     2.3 @@ -0,0 +1,197 @@
     2.4 +// CpEpEngine.h : Declaration of the CpEpEngine
     2.5 +
     2.6 +#pragma once
     2.7 +#include "resource.h"       // main symbols
     2.8 +
     2.9 +
    2.10 +
    2.11 +#include "pEpComServerAdapter_i.h"
    2.12 +#include "_IpEpEngineEvents_CP.h"
    2.13 +#include "locked_queue.hh"
    2.14 +#include "utf8_helper.h"
    2.15 +
    2.16 +
    2.17 +
    2.18 +#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
    2.19 +#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
    2.20 +#endif
    2.21 +
    2.22 +using namespace ATL;
    2.23 +using namespace utility;
    2.24 +
    2.25 +
    2.26 +// CpEpEngine
    2.27 +
    2.28 +class ATL_NO_VTABLE CpEpEngine :
    2.29 +	public CComObjectRootEx<CComSingleThreadModel>,
    2.30 +	public CComCoClass<CpEpEngine, &CLSID_pEpEngine>,
    2.31 +	public ISupportErrorInfo,
    2.32 +	public IConnectionPointContainerImpl<CpEpEngine>,
    2.33 +	public CProxy_IpEpEngineEvents<CpEpEngine>,
    2.34 +	public IpEpEngine
    2.35 +{
    2.36 +public:
    2.37 +	CpEpEngine()
    2.38 +	{
    2.39 +        PEP_STATUS status = ::init(&m_session);
    2.40 +        assert(status == PEP_STATUS_OK);
    2.41 +        ::log_event(m_session, "Startup", "pEp COM Adapter", NULL, NULL);
    2.42 +        identity_queue = new identity_queue_t();
    2.43 +        keymanagement_thread = new thread(::do_keymanagement, retrieve_next_identity, (void *) identity_queue);
    2.44 +        keymanagement_thread->detach();
    2.45 +    }
    2.46 +    ~CpEpEngine()
    2.47 +    {
    2.48 +        pEp_identity_cpp shutdown;
    2.49 +        identity_queue->push_front(shutdown);
    2.50 +        ::log_event(m_session, "Shutdown", "pEp COM Adapter", NULL, NULL);
    2.51 +        ::release(m_session);
    2.52 +    }
    2.53 +
    2.54 +DECLARE_REGISTRY_RESOURCEID(IDR_PEPENGINE)
    2.55 +
    2.56 +DECLARE_NOT_AGGREGATABLE(CpEpEngine)
    2.57 +
    2.58 +BEGIN_COM_MAP(CpEpEngine)
    2.59 +	COM_INTERFACE_ENTRY(IpEpEngine)
    2.60 +	COM_INTERFACE_ENTRY(ISupportErrorInfo)
    2.61 +	COM_INTERFACE_ENTRY(IConnectionPointContainer)
    2.62 +END_COM_MAP()
    2.63 +
    2.64 +BEGIN_CONNECTION_POINT_MAP(CpEpEngine)
    2.65 +	CONNECTION_POINT_ENTRY(__uuidof(_IpEpEngineEvents))
    2.66 +END_CONNECTION_POINT_MAP()
    2.67 +// ISupportsErrorInfo
    2.68 +	STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
    2.69 +
    2.70 +
    2.71 +	DECLARE_PROTECT_FINAL_CONSTRUCT()
    2.72 +
    2.73 +	HRESULT FinalConstruct()
    2.74 +	{
    2.75 +		return S_OK;
    2.76 +	}
    2.77 +
    2.78 +	void FinalRelease()
    2.79 +	{
    2.80 +	}
    2.81 +
    2.82 +
    2.83 +protected:
    2.84 +    struct pEp_identity_cpp {
    2.85 +        std::string address;
    2.86 +        std::string fpr;
    2.87 +        std::string user_id;
    2.88 +        std::string username;
    2.89 +        pEp_comm_type comm_type;
    2.90 +        std::string lang;
    2.91 +        bool me;
    2.92 +
    2.93 +        pEp_identity_cpp(
    2.94 +            std::string _address = std::string(),
    2.95 +            std::string _fpr = std::string(),
    2.96 +            std::string _user_id = std::string(),
    2.97 +            std::string _username = std::string(),
    2.98 +            pEp_comm_type _comm_type = pEp_ct_unknown,
    2.99 +            std::string _lang = std::string()
   2.100 +            ) : address(_address), fpr(_fpr), user_id(_user_id), username(_username), comm_type(_comm_type), lang(_lang), me(false)
   2.101 +        { }
   2.102 +
   2.103 +        pEp_identity_cpp(const ::pEp_identity *_ident)
   2.104 +            : me(false)
   2.105 +        {
   2.106 +            if (_ident->address)
   2.107 +                address = _ident->address;
   2.108 +            if (_ident->fpr)
   2.109 +                fpr = _ident->fpr;
   2.110 +            if (_ident->user_id)
   2.111 +                user_id = _ident->user_id;
   2.112 +            if (_ident->username)
   2.113 +                username = _ident->username;
   2.114 +            comm_type = (pEp_comm_type) _ident->comm_type;
   2.115 +            lang = _ident->lang;
   2.116 +        }
   2.117 +
   2.118 +        pEp_identity_cpp(const pEp_identity_s *_ident)
   2.119 +            : me(false)
   2.120 +        {
   2.121 +            if (_ident->address)
   2.122 +                address = utf8_string(_ident->address);
   2.123 +            if (_ident->fpr)
   2.124 +                fpr = utf8_string(_ident->fpr);
   2.125 +            if (_ident->user_id)
   2.126 +                user_id = utf8_string(_ident->user_id);
   2.127 +            if (_ident->username)
   2.128 +                username = utf8_string(_ident->username);
   2.129 +            comm_type = _ident->comm_type;
   2.130 +            if (_ident->lang)
   2.131 +                lang = utf8_string(_ident->lang);
   2.132 +        }
   2.133 +    };
   2.134 +
   2.135 +    class session
   2.136 +    {
   2.137 +    private:
   2.138 +        CpEpEngine *me;
   2.139 +
   2.140 +    public:
   2.141 +        session(CpEpEngine *myself)
   2.142 +        {
   2.143 +            me = myself;
   2.144 +            me->session_mutex.lock();
   2.145 +        }
   2.146 +
   2.147 +        ~session()
   2.148 +        {
   2.149 +            me->session_mutex.unlock();
   2.150 +        }
   2.151 +
   2.152 +        operator PEP_SESSION const () 
   2.153 +        {
   2.154 +            return me->m_session;
   2.155 +        }
   2.156 +    };
   2.157 +
   2.158 +    session get_session()
   2.159 +    {
   2.160 +        return session(this);
   2.161 +    }
   2.162 +
   2.163 +    static ::pEp_identity *new_identity(const pEp_identity_cpp&);
   2.164 +
   2.165 +    typedef locked_queue<pEp_identity_cpp> identity_queue_t;
   2.166 +    static ::pEp_identity * retrieve_next_identity(void *management);
   2.167 +    HRESULT error(_bstr_t msg);
   2.168 +
   2.169 +private:
   2.170 +    PEP_SESSION m_session;
   2.171 +    mutex session_mutex;
   2.172 +    identity_queue_t *identity_queue;
   2.173 +    thread *keymanagement_thread;
   2.174 +
   2.175 +public:
   2.176 +    STDMETHOD(log)(BSTR title, BSTR entity, BSTR description, BSTR comment);
   2.177 +    STDMETHOD(decrypt)(BSTR ctext, BSTR * ptext, LPSAFEARRAY * key_list, pEp_STATUS * decrypt_status);
   2.178 +    STDMETHOD(decrypt_b)(BSTR ctext, LPSAFEARRAY * ptext, LPSAFEARRAY * key_list, pEp_STATUS * decrypt_status);
   2.179 +    STDMETHOD(encrypt)(SAFEARRAY * key_list, BSTR ptext, BSTR * ctext, pEp_STATUS * status);
   2.180 +    STDMETHOD(encrypt_b)(SAFEARRAY * key_list, SAFEARRAY * ptext, BSTR * ctext, pEp_STATUS * status);
   2.181 +    STDMETHOD(safeword)(LONG value, BSTR lang, BSTR * word);
   2.182 +    STDMETHOD(safewords)(BSTR fpr, BSTR lang, LONG max_words, BSTR * words);
   2.183 +    STDMETHOD(get_identity)(BSTR address, pEp_identity_s * ident);
   2.184 +    STDMETHOD(set_identity)(pEp_identity_s * ident);
   2.185 +    STDMETHOD(generate_keypair)(pEp_identity_s * ident, BSTR * fpr);
   2.186 +    STDMETHOD(delete_keypair)(BSTR fpr);
   2.187 +    STDMETHOD(import_key)(BSTR key_data);
   2.188 +    STDMETHOD(import_key_b)(SAFEARRAY * key_data);
   2.189 +    STDMETHOD(export_key)(BSTR fpr, BSTR * key_data);
   2.190 +    STDMETHOD(recv_key)(BSTR pattern);
   2.191 +    STDMETHOD(find_keys)(BSTR pattern, LPSAFEARRAY * key_list);
   2.192 +    STDMETHOD(send_key)(BSTR pattern);
   2.193 +    STDMETHOD(examine_identity)(pEp_identity_s * ident);
   2.194 +    STDMETHOD(examine_myself)(pEp_identity_s * myself);
   2.195 +    STDMETHOD(verify)(BSTR text, BSTR signature, LPSAFEARRAY * key_list, pEp_STATUS * verify_status);
   2.196 +    STDMETHOD(myself)(struct pEp_identity_s *ident, struct pEp_identity_s *result);
   2.197 +    STDMETHOD(update_identity)(struct pEp_identity_s *ident, struct pEp_identity_s *result);
   2.198 +};
   2.199 +
   2.200 +OBJECT_ENTRY_AUTO(__uuidof(pEpEngine), CpEpEngine)
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/ReadMe.txt	Thu Apr 16 20:43:31 2015 +0200
     3.3 @@ -0,0 +1,56 @@
     3.4 +========================================================================
     3.5 +    ACTIVE TEMPLATE LIBRARY : pEpCOMServerAdapter Project Overview
     3.6 +========================================================================
     3.7 +
     3.8 +AppWizard has created this pEpCOMServerAdapter project for you to use as the starting point for
     3.9 +writing your Executable (EXE).
    3.10 +
    3.11 +This file contains a summary of what you will find in each of the files that
    3.12 +make up your project.
    3.13 +
    3.14 +pEpCOMServerAdapter.vcxproj
    3.15 +    This is the main project file for VC++ projects generated using an Application Wizard.
    3.16 +    It contains information about the version of Visual C++ that generated the file, and
    3.17 +    information about the platforms, configurations, and project features selected with the
    3.18 +    Application Wizard.
    3.19 +
    3.20 +pEpCOMServerAdapter.vcxproj.filters
    3.21 +    This is the filters file for VC++ projects generated using an Application Wizard. 
    3.22 +    It contains information about the association between the files in your project 
    3.23 +    and the filters. This association is used in the IDE to show grouping of files with
    3.24 +    similar extensions under a specific node (for e.g. ".cpp" files are associated with the
    3.25 +    "Source Files" filter).
    3.26 +
    3.27 +pEpCOMServerAdapter.idl
    3.28 +    This file contains the IDL definitions of the type library, the interfaces
    3.29 +    and co-classes defined in your project.
    3.30 +    This file will be processed by the MIDL compiler to generate:
    3.31 +        C++ interface definitions and GUID declarations (pEpCOMServerAdapter.h)
    3.32 +        GUID definitions                                (pEpCOMServerAdapter_i.c)
    3.33 +        A type library                                  (pEpCOMServerAdapter.tlb)
    3.34 +        Marshaling code                                 (pEpCOMServerAdapter_p.c and dlldata.c)
    3.35 +
    3.36 +pEpCOMServerAdapter.h
    3.37 +    This file contains the C++ interface definitions and GUID declarations of the
    3.38 +    items defined in pEpCOMServerAdapter.idl. It will be regenerated by MIDL during compilation.
    3.39 +
    3.40 +pEpCOMServerAdapter.cpp
    3.41 +    This file contains the object map and the implementation of WinMain.
    3.42 +
    3.43 +pEpCOMServerAdapter.rc
    3.44 +    This is a listing of all of the Microsoft Windows resources that the
    3.45 +    program uses.
    3.46 +
    3.47 +
    3.48 +/////////////////////////////////////////////////////////////////////////////
    3.49 +Other standard files:
    3.50 +
    3.51 +StdAfx.h, StdAfx.cpp
    3.52 +    These files are used to build a precompiled header (PCH) file
    3.53 +    named pEpCOMServerAdapter.pch and a precompiled types file named StdAfx.obj.
    3.54 +
    3.55 +Resource.h
    3.56 +    This is the standard header file that defines resource IDs.
    3.57 +
    3.58 +
    3.59 +/////////////////////////////////////////////////////////////////////////////
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/_IpEpEngineEvents_CP.h	Thu Apr 16 20:43:31 2015 +0200
     4.3 @@ -0,0 +1,10 @@
     4.4 +#pragma once
     4.5 +
     4.6 +using namespace ATL;
     4.7 +
     4.8 +template <class T>
     4.9 +class CProxy_IpEpEngineEvents : public IConnectionPointImpl<T, &__uuidof( _IpEpEngineEvents ), CComDynamicUnkArray>
    4.10 +{
    4.11 +	// WARNING: This class may be regenerated by the wizard
    4.12 +public:
    4.13 +};
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/dlldata.c	Thu Apr 16 20:43:31 2015 +0200
     5.3 @@ -0,0 +1,37 @@
     5.4 +/*********************************************************
     5.5 +   DllData file -- generated by MIDL compiler 
     5.6 +
     5.7 +        DO NOT ALTER THIS FILE
     5.8 +
     5.9 +   This file is regenerated by MIDL on every IDL file compile.
    5.10 +
    5.11 +   To completely reconstruct this file, delete it and rerun MIDL
    5.12 +   on all the IDL files in this DLL, specifying this file for the
    5.13 +   /dlldata command line option
    5.14 +
    5.15 +*********************************************************/
    5.16 +
    5.17 +
    5.18 +#include <rpcproxy.h>
    5.19 +
    5.20 +#ifdef __cplusplus
    5.21 +extern "C"   {
    5.22 +#endif
    5.23 +
    5.24 +EXTERN_PROXY_FILE( pEpCOMServerAdapter )
    5.25 +
    5.26 +
    5.27 +PROXYFILE_LIST_START
    5.28 +/* Start of list */
    5.29 +  REFERENCE_PROXY_FILE( pEpCOMServerAdapter ),
    5.30 +/* End of list */
    5.31 +PROXYFILE_LIST_END
    5.32 +
    5.33 +
    5.34 +DLLDATA_ROUTINES( aProxyFileList, GET_DLL_CLSID )
    5.35 +
    5.36 +#ifdef __cplusplus
    5.37 +}  /*extern "C" */
    5.38 +#endif
    5.39 +
    5.40 +/* end of generated dlldata file */
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/locked_queue.hh	Thu Apr 16 20:43:31 2015 +0200
     6.3 @@ -0,0 +1,52 @@
     6.4 +#pragma once
     6.5 +
     6.6 +#include <list>
     6.7 +#include <mutex>
     6.8 +
     6.9 +namespace utility
    6.10 +{
    6.11 +	using namespace std;
    6.12 +
    6.13 +	template<class T> class locked_queue
    6.14 +	{
    6.15 +		mutex _mtx;
    6.16 +		list<T> _q;
    6.17 +
    6.18 +	public:
    6.19 +		T& back()
    6.20 +		{
    6.21 +			lock_guard<mutex> lg(_mtx);
    6.22 +			return _q.back();
    6.23 +		}
    6.24 +		T& front()
    6.25 +		{
    6.26 +			lock_guard<mutex> lg(_mtx);
    6.27 +			return _q.front();
    6.28 +		}
    6.29 +		void pop_back()
    6.30 +		{
    6.31 +			lock_guard<mutex> lg(_mtx);
    6.32 +			_q.pop_back();
    6.33 +		}
    6.34 +		void pop_front()
    6.35 +		{
    6.36 +			lock_guard<mutex> lg(_mtx);
    6.37 +			_q.pop_front();
    6.38 +		}
    6.39 +		void push_back(const T& data)
    6.40 +		{
    6.41 +			lock_guard<mutex> lg(_mtx);
    6.42 +			_q.push_back(data);
    6.43 +		}
    6.44 +		void push_front(const T& data)
    6.45 +		{
    6.46 +			lock_guard<mutex> lg(_mtx);
    6.47 +			_q.push_front(data);
    6.48 +		}
    6.49 +		size_t size()
    6.50 +		{
    6.51 +			lock_guard<mutex> lg(_mtx);
    6.52 +			return _q.size();
    6.53 +		}
    6.54 +	};
    6.55 +};
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/pEpCOMServerAdapter.cpp	Thu Apr 16 20:43:31 2015 +0200
     7.3 @@ -0,0 +1,30 @@
     7.4 +// pEpCOMServerAdapter.cpp : Implementation of WinMain
     7.5 +
     7.6 +
     7.7 +#include "stdafx.h"
     7.8 +#include "resource.h"
     7.9 +#include "pEpCOMServerAdapter_i.h"
    7.10 +#include "xdlldata.h"
    7.11 +
    7.12 +
    7.13 +using namespace ATL;
    7.14 +
    7.15 +
    7.16 +class CpEpCOMServerAdapterModule : public ATL::CAtlExeModuleT< CpEpCOMServerAdapterModule >
    7.17 +{
    7.18 +public :
    7.19 +	DECLARE_LIBID(LIBID_pEpCOMServerAdapterLib)
    7.20 +	DECLARE_REGISTRY_APPID_RESOURCEID(IDR_PEPCOMSERVERADAPTER, "{B3480081-82C0-4EE4-9AA1-3F513C9D78DD}")
    7.21 +};
    7.22 +
    7.23 +CpEpCOMServerAdapterModule _AtlModule;
    7.24 +
    7.25 +
    7.26 +
    7.27 +//
    7.28 +extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, 
    7.29 +								LPTSTR /*lpCmdLine*/, int nShowCmd)
    7.30 +{
    7.31 +    return _AtlModule.WinMain(nShowCmd);
    7.32 +}
    7.33 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/pEpCOMServerAdapter.idl	Thu Apr 16 20:43:31 2015 +0200
     8.3 @@ -0,0 +1,145 @@
     8.4 +// pEpCOMServerAdapter.idl : IDL source for pEpCOMServerAdapter
     8.5 +//
     8.6 +
     8.7 +// This file will be processed by the MIDL tool to
     8.8 +// produce the type library (pEpCOMServerAdapter.tlb) and marshalling code.
     8.9 +
    8.10 +import "oaidl.idl";
    8.11 +import "ocidl.idl";
    8.12 +
    8.13 +
    8.14 +[
    8.15 +    object,
    8.16 +    uuid(9A9F4422-CF0A-45D7-90CD-1D1B7B2A4540),
    8.17 +    oleautomation,
    8.18 +    nonextensible,
    8.19 +    pointer_default(unique)
    8.20 +]
    8.21 +interface IpEpEngine : IUnknown {
    8.22 +    typedef enum _pEp_STATUS {
    8.23 +        pEp_STATUS_OK = 0,
    8.24 +
    8.25 +        pEp_KEY_NOT_FOUND = 0x0201,
    8.26 +        pEp_KEY_HAS_AMBIG_NAME = 0x0202,
    8.27 +        pEp_GET_KEY_FAILED = 0x0203,
    8.28 +
    8.29 +        pEp_UNENCRYPTED = 0x0400,
    8.30 +        pEp_VERIFIED = 0x0401,
    8.31 +        pEp_DECRYPTED = 0x0402,
    8.32 +        pEp_DECRYPTED_AND_VERIFIED = 0x0403,
    8.33 +        pEp_DECRYPT_WRONG_FORMAT = 0x0404,
    8.34 +        pEp_DECRYPT_NO_KEY = 0x0405,
    8.35 +        pEp_DECRYPT_SIGNATURE_DOES_NOT_MATCH = 0x0406,
    8.36 +        pEp_VERIFY_NO_KEY = 0x0407,
    8.37 +        pEp_VERIFIED_AND_TRUSTED = 0x0408,
    8.38 +
    8.39 +        pEp_ILLEGAL_VALUE = -4,
    8.40 +        pEp_BUFFER_TOO_SMALL = -3,
    8.41 +        pEp_OUT_OF_MEMORY = -2,
    8.42 +        pEp_UNKNOWN_ERROR = -1
    8.43 +    } pEp_STATUS;
    8.44 +
    8.45 +    [id(1)] HRESULT log([in] BSTR title, [in] BSTR entity, [in, defaultvalue("")] BSTR description, [in, defaultvalue("")] BSTR comment);
    8.46 +    [id(2)] HRESULT decrypt([in] BSTR ctext, [out] BSTR * ptext, [out] SAFEARRAY(BSTR) * key_list, [out, retval] pEp_STATUS * decrypt_status);
    8.47 +    [id(3)] HRESULT decrypt_b([in] BSTR ctext, [out] SAFEARRAY(BYTE) * ptext, [out] SAFEARRAY(BSTR) * key_list, [out, retval] pEp_STATUS * decrypt_status);
    8.48 +    [id(4)] HRESULT encrypt([in] SAFEARRAY(BSTR) key_list, [in] BSTR ptext, [out] BSTR * ctext, [out, retval] pEp_STATUS * status);
    8.49 +    [id(5)] HRESULT encrypt_b([in] SAFEARRAY(BSTR) key_list, [in] SAFEARRAY(BYTE) ptext, [out] BSTR * ctext, [out, retval] pEp_STATUS * status);
    8.50 +    [id(21)] HRESULT verify([in] BSTR text, [in] BSTR signature, [out] SAFEARRAY(BSTR) * key_list, [out, retval] pEp_STATUS * verify_status);
    8.51 +    [id(6)] HRESULT safeword([in] LONG value, [in, defaultvalue("en")] BSTR lang, [out, retval] BSTR * word);
    8.52 +    [id(7)] HRESULT safewords([in] BSTR fpr, [in, defaultvalue("en")] BSTR lang, [in, defaultvalue(0)] LONG max_words, [out, retval] BSTR * words);
    8.53 +
    8.54 +    typedef enum _pEp_comm_type {
    8.55 +        pEp_ct_unknown = 0,
    8.56 +
    8.57 +        // range 0x01 to 0x09: no encryption, 0x0a to 0x0e: nothing reasonable
    8.58 +
    8.59 +        pEp_ct_no_encryption = 0x01,                // generic
    8.60 +        pEp_ct_no_encrypted_channel = 0x02,
    8.61 +        pEp_ct_key_not_found = 0x03,
    8.62 +        pEp_ct_key_expired = 0x04,
    8.63 +        pEp_ct_key_revoked = 0x05,
    8.64 +        pEp_ct_key_b0rken = 0x06,
    8.65 +        pEp_ct_my_key_not_included = 0x09,
    8.66 +
    8.67 +        pEp_ct_security_by_obscurity = 0x0a,
    8.68 +        pEp_ct_b0rken_crypto = 0x0b,
    8.69 +        pEp_ct_key_too_short = 0x0e,
    8.70 +
    8.71 +        pEp_ct_compromized = 0x0f,                  // known compromized connection
    8.72 +
    8.73 +        // range 0x10 to 0x3f: unconfirmed encryption
    8.74 +
    8.75 +        pEp_ct_unconfirmed_encryption = 0x10,       // generic
    8.76 +        pEp_ct_OpenPGP_1024_RSA_unconfirmed = 0x11,	// RSA 1024 is weak
    8.77 +        pEp_ct_OpenPGP_unconfirmed = 0x3f,          // key at least 2048 bit RSA
    8.78 +        // or 1024 bit DSA
    8.79 +
    8.80 +        // range 0x40 to 0x7f: unconfirmed encryption and anonymization
    8.81 +
    8.82 +        pEp_ct_unconfirmed_enc_anon = 0x40,         // generic
    8.83 +        pEp_ct_pEp_unconfirmed = 0x7f,
    8.84 +
    8.85 +        pEp_ct_confirmed = 0x80,                    // this bit decides if trust is confirmed
    8.86 +
    8.87 +        // range 0x81 to 0x8f: reserved
    8.88 +        // range 0x90 to 0xbf: confirmed encryption
    8.89 +
    8.90 +        pEp_ct_confirmed_encryption = 0x90,         // generic
    8.91 +        pEp_ct_OpenPGP_1024_RSA = 0x91, // RSA 1024 is weak
    8.92 +        pEp_ct_OpenPGP = 0xbf, // key at least 2048 bit RSA or 1024 bit DSA
    8.93 +
    8.94 +        // range 0xc0 to 0xff: confirmed encryption and anonymization
    8.95 +
    8.96 +        pEp_ct_confirmed_enc_anon = 0xc0,           // generic
    8.97 +        pEp_ct_pEp = 0xff
    8.98 +    } pEp_comm_type;
    8.99 +
   8.100 +    struct pEp_identity_s {
   8.101 +        BSTR address;
   8.102 +        BSTR fpr;
   8.103 +        BSTR user_id;
   8.104 +        BSTR username;
   8.105 +        pEp_comm_type comm_type;
   8.106 +        BSTR lang;
   8.107 +    };
   8.108 +
   8.109 +    [id(8)] HRESULT get_identity([in] BSTR address, [out, retval] struct pEp_identity_s * ident);
   8.110 +    [id(9)] HRESULT set_identity([in] struct pEp_identity_s * ident);
   8.111 +    [id(10)] HRESULT generate_keypair([in] struct pEp_identity_s * ident, [out, retval] BSTR * fpr);
   8.112 +    [id(11)] HRESULT delete_keypair([in] BSTR fpr);
   8.113 +    [id(12)] HRESULT import_key([in] BSTR key_data);
   8.114 +    [id(13)] HRESULT import_key_b([in] SAFEARRAY(BYTE) key_data);
   8.115 +    [id(14)] HRESULT export_key([in] BSTR fpr, [out, retval] BSTR * key_data);
   8.116 +    [id(15)] HRESULT recv_key([in] BSTR pattern);
   8.117 +    [id(16)] HRESULT find_keys([in] BSTR pattern, [out, retval] SAFEARRAY(BSTR) * key_list);
   8.118 +    [id(17)] HRESULT send_key([in] BSTR pattern);
   8.119 +
   8.120 +    [id(19)] HRESULT examine_identity([in] struct pEp_identity_s * ident);
   8.121 +    [id(20)] HRESULT examine_myself([in] struct pEp_identity_s * myself);
   8.122 +    [id(22)] HRESULT myself([in] struct pEp_identity_s *ident, [out, retval] struct pEp_identity_s *result);
   8.123 +    [id(23)] HRESULT update_identity([in] struct pEp_identity_s *ident, [out, retval] struct pEp_identity_s *result);
   8.124 +};
   8.125 +[
   8.126 +    uuid(3EC2E1A4-40E8-48E4-A7B0-1876D34F9462),
   8.127 +    version(1.0),
   8.128 +]
   8.129 +library pEpCOMServerAdapterLib
   8.130 +{
   8.131 +    importlib("stdole2.tlb");
   8.132 +    [
   8.133 +        uuid(B6BC9B8E-D9E2-4419-A3A4-7B4B58175549)
   8.134 +    ]
   8.135 +    dispinterface _IpEpEngineEvents
   8.136 +    {
   8.137 +    properties:
   8.138 +    methods:
   8.139 +    };
   8.140 +    [
   8.141 +        uuid(EF1B073D-5058-4E0E-829E-B4D22CA21EA2)
   8.142 +    ]
   8.143 +    coclass pEpEngine {
   8.144 +        [default] interface IpEpEngine;
   8.145 +        [default, source] dispinterface _IpEpEngineEvents;
   8.146 +    };
   8.147 +};
   8.148 +
     9.1 Binary file pEpCOMServerAdapter.rc has changed
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/pEpCOMServerAdapter.vcxproj	Thu Apr 16 20:43:31 2015 +0200
    10.3 @@ -0,0 +1,172 @@
    10.4 +<?xml version="1.0" encoding="utf-8"?>
    10.5 +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    10.6 +  <ItemGroup Label="ProjectConfigurations">
    10.7 +    <ProjectConfiguration Include="Debug|Win32">
    10.8 +      <Configuration>Debug</Configuration>
    10.9 +      <Platform>Win32</Platform>
   10.10 +    </ProjectConfiguration>
   10.11 +    <ProjectConfiguration Include="Release|Win32">
   10.12 +      <Configuration>Release</Configuration>
   10.13 +      <Platform>Win32</Platform>
   10.14 +    </ProjectConfiguration>
   10.15 +  </ItemGroup>
   10.16 +  <PropertyGroup Label="Globals">
   10.17 +    <ProjectGuid>{A27BD6BF-63BC-473D-B8BD-84ACB085F39C}</ProjectGuid>
   10.18 +    <Keyword>AtlProj</Keyword>
   10.19 +  </PropertyGroup>
   10.20 +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   10.21 +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
   10.22 +    <ConfigurationType>Application</ConfigurationType>
   10.23 +    <UseDebugLibraries>true</UseDebugLibraries>
   10.24 +    <PlatformToolset>v120</PlatformToolset>
   10.25 +    <CharacterSet>Unicode</CharacterSet>
   10.26 +  </PropertyGroup>
   10.27 +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
   10.28 +    <ConfigurationType>Application</ConfigurationType>
   10.29 +    <UseDebugLibraries>false</UseDebugLibraries>
   10.30 +    <PlatformToolset>v120</PlatformToolset>
   10.31 +    <CharacterSet>Unicode</CharacterSet>
   10.32 +  </PropertyGroup>
   10.33 +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   10.34 +  <ImportGroup Label="ExtensionSettings">
   10.35 +  </ImportGroup>
   10.36 +  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
   10.37 +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
   10.38 +  </ImportGroup>
   10.39 +  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
   10.40 +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
   10.41 +  </ImportGroup>
   10.42 +  <PropertyGroup Label="UserMacros" />
   10.43 +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
   10.44 +    <IgnoreImportLibrary>true</IgnoreImportLibrary>
   10.45 +    <LinkIncremental>true</LinkIncremental>
   10.46 +  </PropertyGroup>
   10.47 +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
   10.48 +    <IgnoreImportLibrary>true</IgnoreImportLibrary>
   10.49 +    <LinkIncremental>false</LinkIncremental>
   10.50 +  </PropertyGroup>
   10.51 +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
   10.52 +    <ClCompile>
   10.53 +      <PrecompiledHeader>Use</PrecompiledHeader>
   10.54 +      <WarningLevel>Level3</WarningLevel>
   10.55 +      <Optimization>Disabled</Optimization>
   10.56 +      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   10.57 +      <SDLCheck>true</SDLCheck>
   10.58 +    </ClCompile>
   10.59 +    <Midl>
   10.60 +      <MkTypLibCompatible>false</MkTypLibCompatible>
   10.61 +      <TargetEnvironment>Win32</TargetEnvironment>
   10.62 +      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   10.63 +      <HeaderFileName>pEpCOMServerAdapter_i.h</HeaderFileName>
   10.64 +      <InterfaceIdentifierFileName>pEpCOMServerAdapter_i.c</InterfaceIdentifierFileName>
   10.65 +      <ProxyFileName>pEpCOMServerAdapter_p.c</ProxyFileName>
   10.66 +      <GenerateStublessProxies>true</GenerateStublessProxies>
   10.67 +      <TypeLibraryName>$(IntDir)pEpCOMServerAdapter.tlb</TypeLibraryName>
   10.68 +      <DllDataFileName />
   10.69 +      <ValidateAllParameters>true</ValidateAllParameters>
   10.70 +    </Midl>
   10.71 +    <ResourceCompile>
   10.72 +      <Culture>0x0409</Culture>
   10.73 +      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
   10.74 +      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   10.75 +    </ResourceCompile>
   10.76 +    <Link>
   10.77 +      <SubSystem>Windows</SubSystem>
   10.78 +      <GenerateDebugInformation>true</GenerateDebugInformation>
   10.79 +      <RegisterOutput>true</RegisterOutput>
   10.80 +      <AdditionalDependencies>comsuppwd.lib;%(AdditionalDependencies)</AdditionalDependencies>
   10.81 +      <PerUserRedirection>true</PerUserRedirection>
   10.82 +    </Link>
   10.83 +  </ItemDefinitionGroup>
   10.84 +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
   10.85 +    <ClCompile>
   10.86 +      <PrecompiledHeader>Use</PrecompiledHeader>
   10.87 +      <WarningLevel>Level3</WarningLevel>
   10.88 +      <Optimization>MaxSpeed</Optimization>
   10.89 +      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   10.90 +      <SDLCheck>true</SDLCheck>
   10.91 +    </ClCompile>
   10.92 +    <Midl>
   10.93 +      <MkTypLibCompatible>false</MkTypLibCompatible>
   10.94 +      <TargetEnvironment>Win32</TargetEnvironment>
   10.95 +      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   10.96 +      <HeaderFileName>pEpCOMServerAdapter_i.h</HeaderFileName>
   10.97 +      <InterfaceIdentifierFileName>pEpCOMServerAdapter_i.c</InterfaceIdentifierFileName>
   10.98 +      <ProxyFileName>pEpCOMServerAdapter_p.c</ProxyFileName>
   10.99 +      <GenerateStublessProxies>true</GenerateStublessProxies>
  10.100 +      <TypeLibraryName>$(IntDir)pEpCOMServerAdapter.tlb</TypeLibraryName>
  10.101 +      <DllDataFileName />
  10.102 +      <ValidateAllParameters>true</ValidateAllParameters>
  10.103 +    </Midl>
  10.104 +    <ResourceCompile>
  10.105 +      <Culture>0x0409</Culture>
  10.106 +      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
  10.107 +      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
  10.108 +    </ResourceCompile>
  10.109 +    <Link>
  10.110 +      <SubSystem>Windows</SubSystem>
  10.111 +      <GenerateDebugInformation>true</GenerateDebugInformation>
  10.112 +      <EnableCOMDATFolding>true</EnableCOMDATFolding>
  10.113 +      <OptimizeReferences>true</OptimizeReferences>
  10.114 +      <RegisterOutput>true</RegisterOutput>
  10.115 +      <AdditionalDependencies>comsuppw.lib;%(AdditionalDependencies)</AdditionalDependencies>
  10.116 +    </Link>
  10.117 +  </ItemDefinitionGroup>
  10.118 +  <ItemGroup>
  10.119 +    <ClCompile Include="CpEpEngine.cpp" />
  10.120 +    <ClCompile Include="pEpCOMServerAdapter.cpp" />
  10.121 +    <ClCompile Include="pEpCOMServerAdapter_i.c">
  10.122 +      <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
  10.123 +      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
  10.124 +      </PrecompiledHeader>
  10.125 +      <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
  10.126 +      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
  10.127 +      </PrecompiledHeader>
  10.128 +    </ClCompile>
  10.129 +    <ClCompile Include="stdafx.cpp">
  10.130 +      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
  10.131 +      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
  10.132 +    </ClCompile>
  10.133 +    <ClCompile Include="utf8_helper.cpp" />
  10.134 +    <ClCompile Include="xdlldata.c">
  10.135 +      <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
  10.136 +      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
  10.137 +      </PrecompiledHeader>
  10.138 +      <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
  10.139 +      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
  10.140 +      </PrecompiledHeader>
  10.141 +    </ClCompile>
  10.142 +  </ItemGroup>
  10.143 +  <ItemGroup>
  10.144 +    <ClInclude Include="CpEpEngine.h" />
  10.145 +    <ClInclude Include="locked_queue.hh" />
  10.146 +    <ClInclude Include="pEpCOMServerAdapter_i.h" />
  10.147 +    <ClInclude Include="Resource.h" />
  10.148 +    <ClInclude Include="stdafx.h" />
  10.149 +    <ClInclude Include="targetver.h" />
  10.150 +    <ClInclude Include="utf8_helper.h" />
  10.151 +    <ClInclude Include="xdlldata.h" />
  10.152 +    <ClInclude Include="_IpEpEngineEvents_CP.h" />
  10.153 +  </ItemGroup>
  10.154 +  <ItemGroup>
  10.155 +    <ResourceCompile Include="pEpCOMServerAdapter.rc" />
  10.156 +  </ItemGroup>
  10.157 +  <ItemGroup>
  10.158 +    <Text Include="ReadMe.txt" />
  10.159 +  </ItemGroup>
  10.160 +  <ItemGroup>
  10.161 +    <None Include="pEpCOMServerAdapter.rgs" />
  10.162 +    <None Include="pEpEngine.rgs" />
  10.163 +  </ItemGroup>
  10.164 +  <ItemGroup>
  10.165 +    <Midl Include="pEpCOMServerAdapter.idl" />
  10.166 +  </ItemGroup>
  10.167 +  <ItemGroup>
  10.168 +    <ProjectReference Include="..\..\pEpEngine\pEpEngine.vcxproj">
  10.169 +      <Project>{146e69f8-e1da-456a-b048-6dd29d9acf6b}</Project>
  10.170 +    </ProjectReference>
  10.171 +  </ItemGroup>
  10.172 +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  10.173 +  <ImportGroup Label="ExtensionTargets">
  10.174 +  </ImportGroup>
  10.175 +</Project>
  10.176 \ No newline at end of file
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/pEpComAdapter.idl	Thu Apr 16 20:43:31 2015 +0200
    11.3 @@ -0,0 +1,145 @@
    11.4 +// pEpComAdapter.idl : IDL source for pEpComAdapter
    11.5 +//
    11.6 +
    11.7 +// This file will be processed by the MIDL tool to
    11.8 +// produce the type library (pEpComAdapter.tlb) and marshalling code.
    11.9 +
   11.10 +import "oaidl.idl";
   11.11 +import "ocidl.idl";
   11.12 +
   11.13 +[
   11.14 +	object,
   11.15 +	uuid(9A9F4422-CF0A-45D7-90CD-1D1B7B2A4540),
   11.16 +	oleautomation,
   11.17 +	nonextensible,
   11.18 +	pointer_default(unique)
   11.19 +]
   11.20 +interface IpEpEngine : IUnknown{
   11.21 +    typedef enum _pEp_STATUS {
   11.22 +        pEp_STATUS_OK = 0,
   11.23 +
   11.24 +        pEp_KEY_NOT_FOUND = 0x0201,
   11.25 +        pEp_KEY_HAS_AMBIG_NAME = 0x0202,
   11.26 +        pEp_GET_KEY_FAILED = 0x0203,
   11.27 +
   11.28 +        pEp_UNENCRYPTED = 0x0400,
   11.29 +        pEp_VERIFIED = 0x0401,
   11.30 +        pEp_DECRYPTED = 0x0402,
   11.31 +        pEp_DECRYPTED_AND_VERIFIED = 0x0403,
   11.32 +        pEp_DECRYPT_WRONG_FORMAT = 0x0404,
   11.33 +        pEp_DECRYPT_NO_KEY = 0x0405,
   11.34 +        pEp_DECRYPT_SIGNATURE_DOES_NOT_MATCH = 0x0406,
   11.35 +        pEp_VERIFY_NO_KEY = 0x0407,
   11.36 +        pEp_VERIFIED_AND_TRUSTED = 0x0408,
   11.37 +
   11.38 +        pEp_ILLEGAL_VALUE = -4,
   11.39 +        pEp_BUFFER_TOO_SMALL = -3,
   11.40 +        pEp_OUT_OF_MEMORY = -2,
   11.41 +        pEp_UNKNOWN_ERROR = -1
   11.42 +    } pEp_STATUS;
   11.43 +
   11.44 +    [id(1)] HRESULT log([in] BSTR title, [in] BSTR entity, [in, defaultvalue("")] BSTR description, [in, defaultvalue("")] BSTR comment);
   11.45 +    [id(2)] HRESULT decrypt([in] BSTR ctext, [out] BSTR * ptext, [out] SAFEARRAY(BSTR) * key_list, [out, retval] pEp_STATUS * decrypt_status);
   11.46 +    [id(3)] HRESULT decrypt_b([in] BSTR ctext, [out] SAFEARRAY(BYTE) * ptext, [out] SAFEARRAY(BSTR) * key_list, [out, retval] pEp_STATUS * decrypt_status);
   11.47 +    [id(4)] HRESULT encrypt([in] SAFEARRAY(BSTR) key_list, [in] BSTR ptext, [out] BSTR * ctext, [out, retval] pEp_STATUS * status);
   11.48 +    [id(5)] HRESULT encrypt_b([in] SAFEARRAY(BSTR) key_list, [in] SAFEARRAY(BYTE) ptext, [out] BSTR * ctext, [out, retval] pEp_STATUS * status);
   11.49 +    [id(21)] HRESULT verify([in] BSTR text, [in] BSTR signature, [out] SAFEARRAY(BSTR) * key_list, [out, retval] pEp_STATUS * verify_status);
   11.50 +    [id(6)] HRESULT safeword([in] LONG value, [in, defaultvalue("en")] BSTR lang, [out, retval] BSTR * word);
   11.51 +    [id(7)] HRESULT safewords([in] BSTR fpr, [in, defaultvalue("en")] BSTR lang, [in, defaultvalue(0)] LONG max_words, [out, retval] BSTR * words);
   11.52 +
   11.53 +    typedef enum _pEp_comm_type {
   11.54 +        pEp_ct_unknown = 0,
   11.55 +
   11.56 +        // range 0x01 to 0x09: no encryption, 0x0a to 0x0e: nothing reasonable
   11.57 +
   11.58 +        pEp_ct_no_encryption = 0x01,                // generic
   11.59 +        pEp_ct_no_encrypted_channel = 0x02,
   11.60 +        pEp_ct_key_not_found = 0x03,
   11.61 +        pEp_ct_key_expired = 0x04,
   11.62 +        pEp_ct_key_revoked = 0x05,
   11.63 +        pEp_ct_key_b0rken = 0x06,
   11.64 +        pEp_ct_my_key_not_included = 0x09,
   11.65 +
   11.66 +        pEp_ct_security_by_obscurity = 0x0a,
   11.67 +        pEp_ct_b0rken_crypto = 0x0b,
   11.68 +        pEp_ct_key_too_short = 0x0e,
   11.69 +
   11.70 +        pEp_ct_compromized = 0x0f,                  // known compromized connection
   11.71 +
   11.72 +        // range 0x10 to 0x3f: unconfirmed encryption
   11.73 +
   11.74 +        pEp_ct_unconfirmed_encryption = 0x10,       // generic
   11.75 +        pEp_ct_OpenPGP_1024_RSA_unconfirmed = 0x11,	// RSA 1024 is weak
   11.76 +        pEp_ct_OpenPGP_unconfirmed = 0x3f,          // key at least 2048 bit RSA
   11.77 +        // or 1024 bit DSA
   11.78 +
   11.79 +        // range 0x40 to 0x7f: unconfirmed encryption and anonymization
   11.80 +
   11.81 +        pEp_ct_unconfirmed_enc_anon = 0x40,         // generic
   11.82 +        pEp_ct_pEp_unconfirmed = 0x7f,
   11.83 +
   11.84 +        pEp_ct_confirmed = 0x80,                    // this bit decides if trust is confirmed
   11.85 +
   11.86 +        // range 0x81 to 0x8f: reserved
   11.87 +        // range 0x90 to 0xbf: confirmed encryption
   11.88 +
   11.89 +        pEp_ct_confirmed_encryption = 0x90,         // generic
   11.90 +        pEp_ct_OpenPGP_1024_RSA = 0x91, // RSA 1024 is weak
   11.91 +        pEp_ct_OpenPGP = 0xbf, // key at least 2048 bit RSA or 1024 bit DSA
   11.92 +
   11.93 +        // range 0xc0 to 0xff: confirmed encryption and anonymization
   11.94 +
   11.95 +        pEp_ct_confirmed_enc_anon = 0xc0,           // generic
   11.96 +        pEp_ct_pEp = 0xff
   11.97 +    } pEp_comm_type;
   11.98 +
   11.99 +    struct pEp_identity_s {
  11.100 +        BSTR address;
  11.101 +        BSTR fpr;
  11.102 +        BSTR user_id;
  11.103 +        BSTR username;
  11.104 +        pEp_comm_type comm_type;
  11.105 +        BSTR lang;
  11.106 +    };
  11.107 +
  11.108 +    [id(8)] HRESULT get_identity([in] BSTR address, [out, retval] struct pEp_identity_s * ident);
  11.109 +    [id(9)] HRESULT set_identity([in] struct pEp_identity_s * ident);
  11.110 +    [id(10)] HRESULT generate_keypair([in] struct pEp_identity_s * ident, [out, retval] BSTR * fpr);
  11.111 +    [id(11)] HRESULT delete_keypair([in] BSTR fpr);
  11.112 +    [id(12)] HRESULT import_key([in] BSTR key_data);
  11.113 +    [id(13)] HRESULT import_key_b([in] SAFEARRAY(BYTE) key_data);
  11.114 +    [id(14)] HRESULT export_key([in] BSTR fpr, [out, retval] BSTR * key_data);
  11.115 +    [id(15)] HRESULT recv_key([in] BSTR pattern);
  11.116 +    [id(16)] HRESULT find_keys([in] BSTR pattern, [out, retval] SAFEARRAY(BSTR) * key_list);
  11.117 +    [id(17)] HRESULT send_key([in] BSTR pattern);
  11.118 +
  11.119 +    [id(19)] HRESULT examine_identity([in] struct pEp_identity_s * ident);
  11.120 +    [id(20)] HRESULT examine_myself([in] struct pEp_identity_s * myself);
  11.121 +    [id(22)] HRESULT myself([in] struct pEp_identity_s *ident, [out, retval] struct pEp_identity_s *result);
  11.122 +    [id(23)] HRESULT update_identity([in] struct pEp_identity_s *ident, [out, retval] struct pEp_identity_s *result);
  11.123 +};
  11.124 +[
  11.125 +	uuid(3EC2E1A4-40E8-48E4-A7B0-1876D34F9462),
  11.126 +	version(1.0),
  11.127 +]
  11.128 +library pEpComAdapterLib
  11.129 +{
  11.130 +	importlib("stdole2.tlb");
  11.131 +	[
  11.132 +		uuid(B6BC9B8E-D9E2-4419-A3A4-7B4B58175549)		
  11.133 +	]
  11.134 +	dispinterface _IpEpEngineEvents
  11.135 +	{
  11.136 +		properties:
  11.137 +		methods:
  11.138 +	};
  11.139 +	[
  11.140 +		uuid(EF1B073D-5058-4E0E-829E-B4D22CA21EA2)		
  11.141 +	]
  11.142 +	coclass pEpEngine
  11.143 +	{
  11.144 +		[default] interface IpEpEngine;
  11.145 +		[default, source] dispinterface _IpEpEngineEvents;
  11.146 +	};
  11.147 +};
  11.148 +
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/pEpEngine.rgs	Thu Apr 16 20:43:31 2015 +0200
    12.3 @@ -0,0 +1,15 @@
    12.4 +HKCR
    12.5 +{
    12.6 +	NoRemove CLSID
    12.7 +	{
    12.8 +		ForceRemove {EF1B073D-5058-4E0E-829E-B4D22CA21EA2} = s 'pEpEngine Class'
    12.9 +		{
   12.10 +			LocalServer32 = s '%MODULE%'
   12.11 +			{
   12.12 +				val ServerExecutable = s '%MODULE%'
   12.13 +			}
   12.14 +			TypeLib = s '{3EC2E1A4-40E8-48E4-A7B0-1876D34F9462}'
   12.15 +			Version = s '1.0'
   12.16 +		}
   12.17 +	}
   12.18 +}
    13.1 Binary file resource.h has changed
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/stdafx.cpp	Thu Apr 16 20:43:31 2015 +0200
    14.3 @@ -0,0 +1,5 @@
    14.4 +// stdafx.cpp : source file that includes just the standard includes
    14.5 +// pEpCOMServerAdapter.pch will be the pre-compiled header
    14.6 +// stdafx.obj will contain the pre-compiled type information
    14.7 +
    14.8 +#include "stdafx.h"
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/stdafx.h	Thu Apr 16 20:43:31 2015 +0200
    15.3 @@ -0,0 +1,41 @@
    15.4 +// stdafx.h : include file for standard system include files,
    15.5 +// or project specific include files that are used frequently,
    15.6 +// but are changed infrequently
    15.7 +
    15.8 +#pragma once
    15.9 +
   15.10 +#ifndef STRICT
   15.11 +#define STRICT
   15.12 +#endif
   15.13 +
   15.14 +#include "targetver.h"
   15.15 +
   15.16 +#define _ATL_APARTMENT_THREADED
   15.17 +
   15.18 +#define _ATL_NO_AUTOMATIC_NAMESPACE
   15.19 +
   15.20 +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS	// some CString constructors will be explicit
   15.21 +
   15.22 +
   15.23 +#define ATL_NO_ASSERT_ON_DESTROY_NONEXISTENT_WINDOW
   15.24 +
   15.25 +#include "resource.h"
   15.26 +#include <atlbase.h>
   15.27 +#include <atlcom.h>
   15.28 +#include <atlctl.h>
   15.29 +#include <atlsafe.h>
   15.30 +
   15.31 +#include <comutil.h>
   15.32 +
   15.33 +#include <vector>
   15.34 +#include <sstream>
   15.35 +#include <string>
   15.36 +#include <stdexcept>
   15.37 +#include <list>
   15.38 +#include <thread>
   15.39 +#include <mutex>
   15.40 +
   15.41 +#include <assert.h>
   15.42 +
   15.43 +#include "../../pEpEngine/src/pEpEngine.h"
   15.44 +#include "../../pEpEngine/src/keymanagement.h"
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/targetver.h	Thu Apr 16 20:43:31 2015 +0200
    16.3 @@ -0,0 +1,11 @@
    16.4 +#pragma once
    16.5 +
    16.6 +// Including SDKDDKVer.h defines the highest available Windows platform.
    16.7 +
    16.8 +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
    16.9 +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
   16.10 +
   16.11 +#include <WinSDKVer.h>
   16.12 +
   16.13 +#define WINVER 0x0601
   16.14 +#define _WIN32_WINNT 0x0601 // build for Windows 7
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/utf8_helper.cpp	Thu Apr 16 20:43:31 2015 +0200
    17.3 @@ -0,0 +1,68 @@
    17.4 +#include "stdafx.h"
    17.5 +#include "utf8_helper.h"
    17.6 +
    17.7 +using namespace std;
    17.8 +
    17.9 +string utf8_string(wstring wstr, NORM_FORM norm) {
   17.10 +	if (wstr.size() == 0)
   17.11 +		return string();
   17.12 +
   17.13 +	wstring _wstr_normalized;
   17.14 +
   17.15 +	if (norm == NormalizationOther)
   17.16 +		_wstr_normalized = wstr;
   17.17 +	else {
   17.18 +		int size = NormalizeString(norm, wstr.c_str(), -1, NULL, 0);
   17.19 +		assert(size > 0);
   17.20 +		if (size > 0) {
   17.21 +			wchar_t *buf = new wchar_t[size];
   17.22 +			NormalizeString(norm, wstr.c_str(), -1, buf, size);
   17.23 +			_wstr_normalized = buf;
   17.24 +			delete[] buf;
   17.25 +		}
   17.26 +		else
   17.27 +			throw out_of_range("input wstring is not valid while normalizing.");
   17.28 +	}
   17.29 +	string result;
   17.30 +
   17.31 +	int size = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, _wstr_normalized.c_str(), -1, NULL, 0, NULL, NULL);
   17.32 +	assert(size);
   17.33 +	if (size) {
   17.34 +		char *buf = new char[size];
   17.35 +		WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, _wstr_normalized.c_str(), -1, buf, size, NULL, NULL);
   17.36 +		result = buf;
   17.37 +		delete[] buf;
   17.38 +	}
   17.39 +	else
   17.40 +		throw out_of_range("input wstring is not valid while converting UTF-16 to UTF-8.");
   17.41 +
   17.42 +	return result;
   17.43 +}
   17.44 +
   17.45 +string utf8_string(BSTR bstr, NORM_FORM norm) {
   17.46 +	return utf8_string((wstring)(wchar_t *)_bstr_t(bstr, true), norm);
   17.47 +}
   17.48 +
   17.49 +wstring utf16_string(string str) {
   17.50 +	if (str.size() == 0)
   17.51 +		return wstring();
   17.52 +
   17.53 +	wstring result;
   17.54 +
   17.55 +	int size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str.c_str(), -1, NULL, 0);
   17.56 +	assert(size);
   17.57 +	if (size) {
   17.58 +		wchar_t * buf = new wchar_t[size];
   17.59 +		MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str.c_str(), -1, buf, size);
   17.60 +		result = buf;
   17.61 +		delete[] buf;
   17.62 +	}
   17.63 +	else
   17.64 +		throw out_of_range("input string is not valid while converting UTF-8 to UTF-16.");
   17.65 +
   17.66 +	return result;
   17.67 +}
   17.68 +
   17.69 +_bstr_t utf16_bstr(string str) {
   17.70 +	return _bstr_t(utf16_string(str).c_str());
   17.71 +}
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/utf8_helper.h	Thu Apr 16 20:43:31 2015 +0200
    18.3 @@ -0,0 +1,6 @@
    18.4 +#pragma once
    18.5 +
    18.6 +std::string utf8_string(std::wstring wstr, NORM_FORM norm = NormalizationC);
    18.7 +std::string utf8_string(BSTR bstr, NORM_FORM norm = NormalizationC);
    18.8 +std::wstring utf16_string(std::string str);
    18.9 +_bstr_t utf16_bstr(std::string str);
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/xdlldata.c	Thu Apr 16 20:43:31 2015 +0200
    19.3 @@ -0,0 +1,18 @@
    19.4 +// wrapper for dlldata.c
    19.5 +
    19.6 +#ifdef _MERGE_PROXYSTUB // merge proxy stub DLL
    19.7 +
    19.8 +#define REGISTER_PROXY_DLL //DllRegisterServer, etc.
    19.9 +
   19.10 +#define _WIN32_WINNT 0x0500	//for WinNT 4.0 or Win95 with DCOM
   19.11 +#define USE_STUBLESS_PROXY	//defined only with MIDL switch /Oicf
   19.12 +
   19.13 +#pragma comment(lib, "rpcns4.lib")
   19.14 +#pragma comment(lib, "rpcrt4.lib")
   19.15 +
   19.16 +#define ENTRY_PREFIX	Prx
   19.17 +
   19.18 +#include "dlldata.c"
   19.19 +#include "pEpCOMServerAdapter_p.c"
   19.20 +
   19.21 +#endif //_MERGE_PROXYSTUB
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/xdlldata.h	Thu Apr 16 20:43:31 2015 +0200
    20.3 @@ -0,0 +1,15 @@
    20.4 +#pragma once
    20.5 +
    20.6 +#ifdef _MERGE_PROXYSTUB
    20.7 +
    20.8 +extern "C" 
    20.9 +{
   20.10 +BOOL WINAPI PrxDllMain(HINSTANCE hInstance, DWORD dwReason, 
   20.11 +	LPVOID lpReserved);
   20.12 +STDAPI PrxDllCanUnloadNow(void);
   20.13 +STDAPI PrxDllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv);
   20.14 +STDAPI PrxDllRegisterServer(void);
   20.15 +STDAPI PrxDllUnregisterServer(void);
   20.16 +}
   20.17 +
   20.18 +#endif