CpEpEngine.h
author Thomas
Wed, 20 Nov 2019 17:14:38 +0100
branchsync
changeset 374 ccc4c88f280e
parent 368 407097584d25
child 375 fe31c63ea77d
permissions -rw-r--r--
Wrap is_sync_running()
vb@0
     1
// CpEpEngine.h : Declaration of the CpEpEngine
vb@0
     2
vb@0
     3
#pragma once
vb@0
     4
#include "resource.h"       // main symbols
vb@0
     5
vb@0
     6
#include "pEpComServerAdapter_i.h"
vb@295
     7
#include "..\libpEpAdapter\locked_queue.hh"
vb@0
     8
#include "utf8_helper.h"
vb@33
     9
#include "pEp_utility.h"
vb@295
    10
#include "..\libpEpAdapter\Adapter.hh"
markus@165
    11
#include <queue>
krista@261
    12
#include <mutex>
vb@295
    13
#include <vector>
vb@297
    14
#include "..\libpEpAdapter\pc_container.hh"
Thomas@352
    15
#include "..\pEp\sync_codec.h"
vb@0
    16
vb@0
    17
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
vb@0
    18
#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."
vb@0
    19
#endif
vb@0
    20
vb@0
    21
using namespace ATL;
vb@0
    22
using namespace utility;
vb@10
    23
using namespace pEp::utility;
vb@295
    24
using namespace pEp::Adapter;
vb@0
    25
vb@0
    26
// CpEpEngine
vb@0
    27
vb@0
    28
class ATL_NO_VTABLE CpEpEngine :
vb@3
    29
    public CComObjectRootEx<CComObjectThreadModel>,
markus@267
    30
    public CComCoClass<CpEpEngine, &CLSID_pEpEngine>,
markus@267
    31
    public ISupportErrorInfo,
markus@271
    32
    public IpEpEngine
vb@0
    33
{
krista@261
    34
vb@28
    35
protected:
vb@28
    36
    static int examine_identity(pEp_identity *ident, void *management);
vb@28
    37
vb@0
    38
public:
vb@51
    39
    CpEpEngine() : keymanagement_thread(NULL), identity_queue(NULL), verbose_mode(false)
markus@267
    40
    {
markus@269
    41
        // See FinalConstruct() below for most initialization work, and an
markus@269
    42
        // explanation why it had to be moved there...
vb@296
    43
        ++count;
vb@0
    44
    }
vb@24
    45
vb@0
    46
    ~CpEpEngine()
vb@0
    47
    {
vb@296
    48
        --count;
vb@296
    49
        if (!count) {
vb@296
    50
            StopKeyserverLookup();
vb@296
    51
            ::log_event(session(), "Shutdown", "pEp COM Adapter", NULL, NULL);
vb@296
    52
            session(pEp::Adapter::release);
vb@296
    53
            shutdown();
vb@316
    54
vb@316
    55
            sync_callbacks.clear([](CpEpEngine::MarshaledCallbacks *p) {
vb@316
    56
                if (p) {
vb@318
    57
                    if (p->marshaled)
vb@318
    58
                        p->marshaled->Release();
vb@318
    59
                    if (p->unmarshaled)
vb@316
    60
                        p->unmarshaled->Release();
vb@316
    61
                    delete p;
vb@316
    62
                }
vb@316
    63
            });
markus@269
    64
        }
vb@0
    65
    }
vb@0
    66
markus@269
    67
    DECLARE_REGISTRY_RESOURCEID(IDR_PEPENGINE)
vb@0
    68
markus@269
    69
    DECLARE_NOT_AGGREGATABLE(CpEpEngine)
vb@0
    70
markus@269
    71
    BEGIN_COM_MAP(CpEpEngine)
markus@269
    72
        COM_INTERFACE_ENTRY(IpEpEngine)
markus@269
    73
        COM_INTERFACE_ENTRY(ISupportErrorInfo)
markus@269
    74
    END_COM_MAP()
vb@0
    75
markus@269
    76
    // ISupportsErrorInfo
markus@267
    77
    STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
vb@0
    78
markus@267
    79
    DECLARE_PROTECT_FINAL_CONSTRUCT()
vb@0
    80
markus@269
    81
    // Unfortunately, neither FAIL nor error() work in the constructor, as 
markus@269
    82
    // CreateErrorInfo/SetErrorInfo cannot work when the instance is not constructed.
markus@269
    83
    // AtlThrow works, but the exception is caught in CComCreator.CreateInstance, and
markus@269
    84
    // unconditionally turned into E_OUTOFMEMORY. Thus, we need to do most constructor
markus@269
    85
    // work in FinalConstruct. CreateErrorInfo/SetErrorInfo still won't work, but at least,
markus@269
    86
    // we can return a meaningful HRESULT. Thus, we pack our PEP_STATUS into a custom HRESULT.	
markus@267
    87
    HRESULT FinalConstruct()
markus@267
    88
    {
markus@269
    89
        std::lock_guard<std::mutex> lock(init_mutex);
vb@295
    90
        try {
Thomas@353
    91
            if (!_messageToSend) {
Thomas@353
    92
                _messageToSend = messageToSend;
Thomas@353
    93
            }
vb@295
    94
            session();
vb@295
    95
        }
vb@295
    96
        catch (pEp::RuntimeError& e) {
vb@295
    97
            HRESULT res = MAKE_HRESULT(1, FACILITY_ITF, (0xFFFF & e.status));
markus@269
    98
            return res;
Thomas@322
    99
        }       
markus@268
   100
vb@295
   101
        ::register_examine_function(session(), CpEpEngine::examine_identity, (void *)this);
Thomas@322
   102
        ::log_event(session(), "FinalConstruct", "pEp COM Adapter", NULL, NULL);
vb@297
   103
markus@267
   104
        return S_OK;
markus@267
   105
    }
vb@0
   106
markus@267
   107
    void FinalRelease()
markus@267
   108
    {
markus@267
   109
    }
vb@0
   110
vb@308
   111
    struct MarshaledCallbacks {
vb@308
   112
        IpEpEngineCallbacks *unmarshaled;
vb@308
   113
        LPSTREAM marshaled;
vb@308
   114
    };
vb@308
   115
vb@308
   116
    typedef pEp::pc_container< MarshaledCallbacks, IpEpEngineCallbacks > callback_container;
vb@0
   117
vb@0
   118
protected:
vb@0
   119
    typedef locked_queue<pEp_identity_cpp> identity_queue_t;
vb@0
   120
    static ::pEp_identity * retrieve_next_identity(void *management);
vb@74
   121
vb@295
   122
    static PEP_STATUS messageToSend(message *msg);
vb@295
   123
    static PEP_STATUS notifyHandshake(pEp_identity *self, pEp_identity *partner, sync_handshake_signal signal);
markus@165
   124
vb@0
   125
    HRESULT error(_bstr_t msg);
markus@189
   126
    HRESULT error(_bstr_t msg, PEP_STATUS errorcode);
vb@0
   127
vb@51
   128
    void verbose(string text)
vb@51
   129
    {
vb@51
   130
        if (verbose_mode) {
vb@51
   131
            stringstream ss;
vb@51
   132
            ss << __FILE__ << ":" << __LINE__ << " " << text;
vb@295
   133
            ::log_event(session(), "verbose", "pEp COM Server Adapter", ss.str().c_str(), NULL);
vb@51
   134
        }
vb@51
   135
    }
vb@51
   136
vb@0
   137
private:
vb@297
   138
    // callbacks for sync
vb@297
   139
vb@308
   140
    static callback_container sync_callbacks;
vb@297
   141
vb@304
   142
    void Startup_sync()
vb@304
   143
    {
vb@304
   144
        HRESULT r = CoInitializeEx(NULL, COINIT_MULTITHREADED);
vb@304
   145
        if (!SUCCEEDED(r))
vb@304
   146
            throw runtime_error("CoInitializeEx() failed on sync thread");
vb@304
   147
    }
vb@304
   148
vb@311
   149
    void Shutdown_sync()
vb@311
   150
    {
vb@314
   151
        for (auto p = sync_callbacks.begin(); p != sync_callbacks.end(); ++p) {
vb@314
   152
            if (p->cdata) {
Thomas@354
   153
                // p->cdata->Release(); FIXME: This occasionally raises an access violation. To be investigated, why => COM-99
vb@314
   154
                p->cdata = nullptr;
vb@314
   155
            }
vb@314
   156
        }
vb@314
   157
vb@311
   158
        CoUninitialize();
vb@311
   159
    }
vb@311
   160
vb@25
   161
    atomic< identity_queue_t * > identity_queue;
vb@0
   162
    thread *keymanagement_thread;
vb@51
   163
    bool verbose_mode;
vb@0
   164
markus@267
   165
    IpEpEngineCallbacks* client_callbacks = NULL;
markus@232
   166
    bool client_last_signalled_polling_state = true;
markus@84
   167
markus@267
   168
    static std::mutex init_mutex;
vb@296
   169
    static atomic< int > count;
markus@234
   170
vb@0
   171
public:
vb@60
   172
    // runtime config of the adapter
vb@60
   173
markus@172
   174
    STDMETHOD(VerboseLogging)(VARIANT_BOOL enable);
markus@169
   175
vb@60
   176
    // runtime config of the engine
vb@60
   177
markus@172
   178
    STDMETHOD(PassiveMode)(VARIANT_BOOL enable);
markus@172
   179
    STDMETHOD(UnencryptedSubject)(VARIANT_BOOL enable);
vb@60
   180
vb@60
   181
    // basic API
vb@51
   182
Dean@184
   183
    STDMETHOD(ExportKey)(BSTR fpr, BSTR * keyData);
markus@177
   184
    STDMETHOD(Log)(BSTR title, BSTR entity, BSTR description, BSTR comment);
Dean@202
   185
    STDMETHOD(Trustwords)(BSTR fpr, BSTR lang, LONG max_words, BSTR * words);
Dean@202
   186
    STDMETHOD(GetTrustwords)(struct pEpIdentity *id1, struct pEpIdentity *id2, BSTR lang, VARIANT_BOOL full, BSTR *words);
Thomas@348
   187
    STDMETHOD(GetTrustwordsForFprs)(BSTR fpr1, BSTR fpr2, BSTR lang, VARIANT_BOOL full, BSTR *words);
markus@232
   188
    STDMETHOD(GetMessageTrustwords)(
markus@232
   189
        /* [in] */ struct TextMessage *msg,
markus@232
   190
        /* [in] */ struct pEpIdentity *receivedBy,
markus@232
   191
        /* [in] */ SAFEARRAY *keylist,
markus@232
   192
        /* [defaultvalue][in] */ BSTR lang,
markus@232
   193
        /* [defaultvalue][in] */ VARIANT_BOOL full,
markus@232
   194
        /* [retval][out] */ BSTR *words);
markus@172
   195
    STDMETHOD(GetCrashdumpLog)(LONG maxlines, BSTR * log);
markus@177
   196
    STDMETHOD(GetEngineVersion)(BSTR * engineVersion);
markus@177
   197
    STDMETHOD(GetLanguageList)(BSTR * languages);
markus@267
   198
    STDMETHOD(SetIdentityFlags)(struct pEpIdentity *identity, pEpIdentityFlags flags);
markus@267
   199
    STDMETHOD(UnsetIdentityFlags)(struct pEpIdentity *identity, pEpIdentityFlags flags);
Thomas@374
   200
    STDMETHOD(ImportKey)(BSTR keyData, LPSAFEARRAY *privateKeys);
vb@11
   201
vb@11
   202
    // keymanagement API
vb@11
   203
markus@172
   204
    STDMETHOD(StartKeyserverLookup)();
markus@172
   205
    STDMETHOD(StopKeyserverLookup)();
vb@24
   206
markus@172
   207
    STDMETHOD(Myself)(struct pEpIdentity *ident, struct pEpIdentity *result);
markus@172
   208
    STDMETHOD(UpdateIdentity)(struct pEpIdentity *ident, struct pEpIdentity *result);
markus@172
   209
    STDMETHOD(KeyMistrusted)(struct pEpIdentity *ident);
Thomas@374
   210
    STDMETHOD(KeyResetIdentity)(pEpIdentity ident, BSTR fpr);
Thomas@374
   211
    STDMETHOD(KeyResetUser)(BSTR userId, BSTR fpr);
Thomas@374
   212
    STDMETHOD(KeyResetAllOwnKeys)();
markus@172
   213
    STDMETHOD(KeyResetTrust)(struct pEpIdentity *ident);
markus@172
   214
    STDMETHOD(TrustPersonalKey)(struct pEpIdentity *ident, struct pEpIdentity *result);
markus@267
   215
    STDMETHOD(OwnIdentitiesRetrieve)(LPSAFEARRAY* ownIdentities);
Thomas@374
   216
    STDMETHOD(ConfigCipherSuite)(pEpCipherSuite cipherSuite);
markus@165
   217
vb@295
   218
    // STDMETHOD(UndoLastMistrust)(); 
markus@274
   219
    
vb@295
   220
    STDMETHOD(IspEpUser)(
markus@274
   221
        /* [in] */ struct pEpIdentity *ident,
markus@274
   222
        /* [retval][out] */ VARIANT_BOOL *ispEp);
markus@274
   223
Thomas@331
   224
vb@65
   225
    // Blacklist API
vb@65
   226
markus@172
   227
    STDMETHOD(BlacklistAdd)(BSTR fpr);
markus@172
   228
    STDMETHOD(BlacklistDelete)(BSTR fpr);
markus@172
   229
    STDMETHOD(BlacklistIsListed)(BSTR fpr, VARIANT_BOOL *listed);
Dean@187
   230
    STDMETHOD(BlacklistRetrieve)(SAFEARRAY **blacklist);
vb@65
   231
vb@12
   232
    // Message API
vb@12
   233
markus@271
   234
    STDMETHOD(EncryptMessage)(
markus@271
   235
        /* [in] */ struct TextMessage *src,
markus@271
   236
        /* [out] */ struct TextMessage *dst,
markus@271
   237
        /* [in] */ SAFEARRAY * extra,
markus@271
   238
        /* [defaultvalue][in] */ pEpEncryptFlags flags = pEpEncryptFlagDefault,
markus@271
   239
        /* [defaultvalue][in] */ pEpEncFormat encFormat = pEpEncPep);
markus@271
   240
markus@283
   241
    STDMETHOD(EncryptMessageAndAddPrivKey)(
markus@283
   242
        /* [in] */ struct TextMessage *src,
markus@283
   243
        /* [out] */ struct TextMessage *dst,
markus@283
   244
        /* [in] */ BSTR to_fpr,
markus@283
   245
        /* [defaultvalue][in] */ pEpEncryptFlags flags = pEpEncryptFlagDefault,
markus@283
   246
        /* [defaultvalue][in] */ pEpEncFormat encFormat = pEpEncPep);
markus@283
   247
markus@172
   248
    STDMETHOD(DecryptMessage)(TextMessage * src, TextMessage * dst, SAFEARRAY ** keylist, pEpDecryptFlags* flags, pEpRating *rating);
markus@254
   249
    STDMETHOD(ReEvaluateMessageRating)(TextMessage * msg, SAFEARRAY * x_KeyList, pEpRating x_EncStatus, pEpRating *rating);
Thomas@374
   250
    STDMETHOD(OutgoingMessageRating)(TextMessage *msg, pEpRating * pVal);
Thomas@374
   251
    STDMETHOD(OutgoingMessageRatingPreview)(TextMessage *msg, pEpRating * pVal);
markus@172
   252
    STDMETHOD(IdentityRating)(pEpIdentity * ident, pEpRating * pVal);
markus@267
   253
    STDMETHOD(ColorFromRating)(pEpRating rating, pEpColor * pVal);
Thomas@365
   254
    STDMETHOD(RatingFromCommType)(pEpComType commType, pEpRating * rating);
vb@18
   255
markus@240
   256
    STDMETHOD(EncryptMessageForSelf)(
markus@269
   257
        pEpIdentity * targetId,
markus@240
   258
        TextMessage* src,
markus@280
   259
        /* [in] */ SAFEARRAY *extra,
markus@240
   260
        TextMessage *dst,
markus@240
   261
        pEpEncryptFlags flags
markus@240
   262
        );
markus@238
   263
markus@267
   264
    // Event callbacks
markus@267
   265
markus@267
   266
    STDMETHOD(RegisterCallbacks)(IpEpEngineCallbacks *new_callback);
markus@267
   267
    STDMETHOD(UnregisterCallbacks)();
markus@169
   268
krista@154
   269
    // PGP compatibility functions
markus@177
   270
    STDMETHOD(OpenPGPListKeyinfo)(BSTR search_pattern, LPSAFEARRAY* keyinfo_list);
Thomas@374
   271
    STDMETHOD(SetOwnKey)(pEpIdentity * ident, BSTR fpr, struct pEpIdentity *result);
Thomas@374
   272
    STDMETHOD(TrustOwnKey)(pEpIdentity * ident);
markus@84
   273
markus@284
   274
    // Trigger an immediate update
Thomas@368
   275
    STDMETHOD(UpdateNow)(BSTR productCode, VARIANT_BOOL *didUpdate);
Thomas@322
   276
Thomas@374
   277
    STDMETHOD(Startup)();
Thomas@330
   278
Thomas@374
   279
    STDMETHOD(GetKeyRatingForUser)(BSTR userId, BSTR fpr, pEpRating *rating);
Thomas@374
   280
    STDMETHOD(GetKeyRating)(BSTR fpr, pEpComType *commType);
vb@338
   281
Thomas@374
   282
    // sync API
Thomas@374
   283
    STDMETHOD(DeliverHandshakeResult)(enum SyncHandshakeResult result, SAFEARRAY *identities_sharing);
Thomas@374
   284
    STDMETHOD(LeaveDeviceGroup)();
Thomas@374
   285
    STDMETHOD(DisableIdentityForSync)(struct pEpIdentity * ident);
Thomas@374
   286
    STDMETHOD(EnableIdentityForSync)(struct pEpIdentity * ident);
Thomas@374
   287
    STDMETHOD(GetIsSyncRunning)(VARIANT_BOOL *running);
Thomas@352
   288
Thomas@374
   289
    STDMETHOD(PERToXERSyncMessage)(TextMessage *msg, BSTR * xer);
Thomas@358
   290
Thomas@374
   291
    STDMETHOD(PerMachineDirectory)(BSTR * directory);
Thomas@374
   292
    STDMETHOD(PerUserDirectory)(BSTR * directory);
vb@0
   293
};
vb@0
   294
vb@0
   295
OBJECT_ENTRY_AUTO(__uuidof(pEpEngine), CpEpEngine)