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