aboutsummaryrefslogtreecommitdiffstats
path: root/src/native
diff options
context:
space:
mode:
Diffstat (limited to 'src/native')
-rw-r--r--src/native/windows/msofficecomm/ClassFactory.cxx7
-rw-r--r--src/native/windows/msofficecomm/ClassFactory.h52
-rw-r--r--src/native/windows/msofficecomm/ConnectionPoint.h310
-rw-r--r--src/native/windows/msofficecomm/DMessengerEventsConnectionPoint.cxx32
-rw-r--r--src/native/windows/msofficecomm/DMessengerEventsConnectionPoint.h24
-rw-r--r--src/native/windows/msofficecomm/DispatchImpl.h172
-rw-r--r--src/native/windows/msofficecomm/IWeakReference.cxx10
-rw-r--r--src/native/windows/msofficecomm/IWeakReference.h25
-rw-r--r--src/native/windows/msofficecomm/IWeakReferenceSource.cxx10
-rw-r--r--src/native/windows/msofficecomm/IWeakReferenceSource.h25
-rw-r--r--src/native/windows/msofficecomm/Log.cxx140
-rw-r--r--src/native/windows/msofficecomm/Log.h38
-rw-r--r--src/native/windows/msofficecomm/Messenger.cxx876
-rw-r--r--src/native/windows/msofficecomm/Messenger.h126
-rw-r--r--src/native/windows/msofficecomm/MessengerClassFactory.cxx66
-rw-r--r--src/native/windows/msofficecomm/MessengerClassFactory.h39
-rw-r--r--src/native/windows/msofficecomm/MessengerContact.cxx460
-rw-r--r--src/native/windows/msofficecomm/MessengerContact.h70
-rw-r--r--src/native/windows/msofficecomm/MessengerContacts.cxx116
-rw-r--r--src/native/windows/msofficecomm/MessengerContacts.h40
-rw-r--r--src/native/windows/msofficecomm/MessengerService.cxx52
-rw-r--r--src/native/windows/msofficecomm/MessengerService.h35
-rw-r--r--src/native/windows/msofficecomm/MessengerServices.cxx70
-rw-r--r--src/native/windows/msofficecomm/MessengerServices.h33
-rw-r--r--src/native/windows/msofficecomm/OutOfProcessServer.cxx628
-rw-r--r--src/native/windows/msofficecomm/OutOfProcessServer.h64
-rw-r--r--src/native/windows/msofficecomm/Resources.h6
-rw-r--r--src/native/windows/msofficecomm/Resources.rc9
-rw-r--r--src/native/windows/msofficecomm/StringUtils.cxx54
-rw-r--r--src/native/windows/msofficecomm/StringUtils.h20
-rw-r--r--src/native/windows/msofficecomm/UnknownImpl.h129
-rw-r--r--src/native/windows/msofficecomm/WeakReference.cxx47
-rw-r--r--src/native/windows/msofficecomm/WeakReference.h33
-rw-r--r--src/native/windows/msofficecomm/WeakReferenceSource.cxx37
-rw-r--r--src/native/windows/msofficecomm/WeakReferenceSource.h89
-rw-r--r--src/native/windows/msofficecomm/net_java_sip_communicator_plugin_msofficecomm_Messenger.h21
-rw-r--r--src/native/windows/msofficecomm/net_java_sip_communicator_plugin_msofficecomm_OutOfProcessServer.h29
37 files changed, 3994 insertions, 0 deletions
diff --git a/src/native/windows/msofficecomm/ClassFactory.cxx b/src/native/windows/msofficecomm/ClassFactory.cxx
new file mode 100644
index 0000000..98aa171
--- /dev/null
+++ b/src/native/windows/msofficecomm/ClassFactory.cxx
@@ -0,0 +1,7 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#include "ClassFactory.h"
diff --git a/src/native/windows/msofficecomm/ClassFactory.h b/src/native/windows/msofficecomm/ClassFactory.h
new file mode 100644
index 0000000..abe56cd
--- /dev/null
+++ b/src/native/windows/msofficecomm/ClassFactory.h
@@ -0,0 +1,52 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#ifndef _JMSOFFICECOMM_CLASSFACTORY_H_
+#define _JMSOFFICECOMM_CLASSFACTORY_H_
+
+#include "OutOfProcessServer.h"
+#include "UnknownImpl.h"
+
+/**
+ * Represents a base implementation of the <tt>IClassFactory</tt> interface.
+ *
+ * @author Lyubomir Marinov
+ */
+class ClassFactory
+ : public UnknownImpl<IClassFactory, IID_IClassFactory>
+{
+public:
+ // IClassFactory
+ STDMETHOD(LockServer)(BOOL lock)
+ {
+ lock ? OutOfProcessServer::addRef() : OutOfProcessServer::release();
+ return S_OK;
+ };
+
+ HRESULT registerClassObject()
+ {
+ return
+ ::CoRegisterClassObject(
+ _clsid,
+ this,
+ CLSCTX_LOCAL_SERVER,
+ REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED,
+ &_registration);
+ };
+
+ HRESULT revokeClassObject() { return ::CoRevokeClassObject(_registration); };
+
+protected:
+ ClassFactory(REFCLSID clsid) : _clsid(clsid), _registration(0) {};
+ virtual ~ClassFactory() {};
+
+ const CLSID _clsid;
+
+private:
+ DWORD _registration;
+};
+
+#endif /* #ifndef _JMSOFFICECOMM_CLASSFACTORY_H_ */
diff --git a/src/native/windows/msofficecomm/ConnectionPoint.h b/src/native/windows/msofficecomm/ConnectionPoint.h
new file mode 100644
index 0000000..6c62936
--- /dev/null
+++ b/src/native/windows/msofficecomm/ConnectionPoint.h
@@ -0,0 +1,310 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#ifndef _JMSOFFICECOMM_CONNECTIONPOINT_H_
+#define _JMSOFFICECOMM_CONNECTIONPOINT_H_
+
+#include <ocidl.h>
+#include <olectl.h>
+#include <stdint.h>
+#include "UnknownImpl.h"
+
+template <class T, REFIID IID_T>
+class ConnectionPoint
+ : public IConnectionPoint,
+ public T
+{
+public:
+ ConnectionPoint(IConnectionPointContainer *container)
+ : _container(container),
+ _sinkCount(0),
+ _sinks(NULL)
+ {
+ }
+
+ virtual ~ConnectionPoint()
+ {
+ if (_sinks)
+ ::free(_sinks);
+ }
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID iid, PVOID *obj)
+ {
+ HRESULT hr;
+
+ if (!obj)
+ hr = E_POINTER;
+ else if (IID_IUnknown == iid)
+ {
+ AddRef();
+ *obj
+ = static_cast<LPUNKNOWN>(
+ static_cast<IConnectionPoint *>(this));
+ hr = S_OK;
+ }
+ else if (IID_IConnectionPoint == iid)
+ {
+ AddRef();
+ *obj = static_cast<IConnectionPoint *>(this);
+ hr = S_OK;
+ }
+ else
+ {
+ *obj = NULL;
+ hr = E_NOINTERFACE;
+ }
+ return hr;
+ }
+
+ STDMETHODIMP_(ULONG) AddRef() { return _container->AddRef(); }
+ STDMETHODIMP_(ULONG) Release() { return _container->Release(); }
+
+ // IDispatch
+ STDMETHODIMP GetTypeInfoCount(UINT *)
+ STDMETHODIMP_E_NOTIMPL_STUB
+ STDMETHODIMP GetTypeInfo(UINT, LCID, LPTYPEINFO *)
+ STDMETHODIMP_E_NOTIMPL_STUB
+ STDMETHODIMP GetIDsOfNames(REFIID, LPOLESTR *, UINT, LCID, DISPID *)
+ STDMETHODIMP_E_NOTIMPL_STUB
+ STDMETHODIMP Invoke(DISPID, REFIID, LCID, WORD, DISPPARAMS *, VARIANT *, EXCEPINFO *, UINT *)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+ // IConnectionPoint
+ STDMETHODIMP GetConnectionInterface(IID *pIID)
+ {
+ HRESULT hr;
+
+ if (pIID)
+ {
+ *pIID = IID_T;
+ hr = S_OK;
+ }
+ else
+ hr = E_POINTER;
+ return hr;
+ }
+
+ STDMETHODIMP GetConnectionPointContainer(IConnectionPointContainer **ppCPC)
+ {
+ HRESULT hr;
+
+ if (ppCPC)
+ {
+ _container->AddRef();
+ *ppCPC = _container;
+ hr = S_OK;
+ }
+ else
+ hr = E_POINTER;
+ return hr;
+ }
+
+ STDMETHODIMP Advise(IUnknown *pUnkSink, DWORD *pdwCookie)
+ {
+ HRESULT hr;
+
+ if (pdwCookie)
+ {
+ if (pUnkSink)
+ {
+ T *t;
+
+ if (SUCCEEDED(
+ pUnkSink->QueryInterface(IID_T, (PVOID *) &t)))
+ {
+ LPDISPATCH iDispatch;
+
+ if (SUCCEEDED(
+ t->QueryInterface(
+ IID_IDispatch,
+ (PVOID *) &iDispatch)))
+ {
+ if (addSink(iDispatch))
+ {
+ *pdwCookie
+ = (DWORD)
+ (((intptr_t) iDispatch) & 0xffffffff);
+ hr = S_OK;
+ }
+ else
+ {
+ *pdwCookie = 0;
+ hr = CONNECT_E_CANNOTCONNECT;
+ }
+ iDispatch->Release();
+ }
+ else
+ {
+ *pdwCookie = 0;
+ hr = CONNECT_E_CANNOTCONNECT;
+ }
+
+ t->Release();
+ }
+ else
+ {
+ *pdwCookie = 0;
+ hr = CONNECT_E_CANNOTCONNECT;
+ }
+ }
+ else
+ {
+ *pdwCookie = 0;
+ hr = E_POINTER;
+ }
+ }
+ else
+ hr = E_POINTER;
+ return hr;
+ }
+
+ STDMETHODIMP Unadvise(DWORD dwCookie)
+ {
+ size_t i = 0;
+ LPDISPATCH *ptr = _sinks;
+ HRESULT hr = E_POINTER;
+
+ for (; i < _sinkCount; i++, ptr++)
+ {
+ LPDISPATCH iDispatch = *ptr;
+
+ if (iDispatch
+ && (dwCookie
+ == (DWORD)
+ (((intptr_t) iDispatch) & 0xffffffff)))
+ {
+ *ptr = NULL;
+ iDispatch->Release();
+
+ _sinkCount--;
+ /*
+ * Move the emptied slot of the _sinks storage at the end
+ * where it is not accessible given the value of _sinkCount.
+ * Its memory is retained but it will either be used during
+ * a subsequent addSink(LPDISPATCH) or be freed upon
+ * deleting this ConnectionPoint.
+ */
+ for (; i < _sinkCount; i++)
+ {
+ LPDISPATCH *nextPtr = ptr + 1;
+
+ *ptr = *nextPtr;
+ ptr = nextPtr;
+ }
+
+ hr = S_OK;
+ break;
+ }
+ }
+ return hr;
+ }
+
+ STDMETHODIMP EnumConnections(IEnumConnections **ppEnum)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+protected:
+ HRESULT Invoke(DISPID dispIdMember, DISPPARAMS *pDispParams)
+ {
+ LPDISPATCH *sinks = getSinks();
+ HRESULT hr;
+
+ if (sinks)
+ {
+ for (LPDISPATCH sink, *sinkIt = sinks;
+ (sink = *sinkIt);
+ sinkIt++)
+ {
+ hr
+ = sink->Invoke(
+ dispIdMember,
+ IID_NULL,
+ 0,
+ DISPATCH_METHOD,
+ pDispParams,
+ NULL,
+ NULL,
+ NULL);
+ sink->Release();
+ }
+ ::free(sinks);
+
+ hr = S_OK;
+ }
+ else
+ hr = E_OUTOFMEMORY;
+ return hr;
+ }
+
+private:
+ BOOL addSink(LPDISPATCH sink)
+ {
+ BOOL b;
+
+ if (containsSink(sink))
+ b = FALSE;
+ else
+ {
+ size_t newSinkCount = _sinkCount + 1;
+ LPDISPATCH *newSinks
+ = (LPDISPATCH *)
+ ::realloc(_sinks, newSinkCount * sizeof(LPDISPATCH));
+
+ if (newSinks)
+ {
+ sink->AddRef();
+ newSinks[newSinkCount - 1] = sink;
+ _sinkCount = newSinkCount;
+ _sinks = newSinks;
+ b = TRUE;
+ }
+ else
+ b = FALSE;
+ }
+ return b;
+ }
+
+ BOOL containsSink(const LPDISPATCH sink)
+ {
+ size_t i = 0;
+ LPDISPATCH *ptr = _sinks;
+
+ for (; i < _sinkCount; i++, ptr++)
+ if (sink == *ptr)
+ return TRUE;
+ return FALSE;
+ }
+
+ LPDISPATCH *getSinks()
+ {
+ LPDISPATCH *sinks
+ = (LPDISPATCH *)
+ ::malloc((_sinkCount + 1) * sizeof(LPDISPATCH));
+
+ if (sinks)
+ {
+ size_t i = 0;
+ LPDISPATCH *dst = sinks;
+ LPDISPATCH *src = _sinks;
+
+ for (; i < _sinkCount; i++, src++, dst++)
+ {
+ LPDISPATCH sink = *src;
+
+ sink->AddRef();
+ *dst = sink;
+ }
+ *dst = NULL;
+ }
+ return sinks;
+ }
+
+ IConnectionPointContainer *_container;
+ size_t _sinkCount;
+ LPDISPATCH *_sinks;
+};
+
+#endif /* #ifndef _JMSOFFICECOMM_CONNECTIONPOINT_H_ */
diff --git a/src/native/windows/msofficecomm/DMessengerEventsConnectionPoint.cxx b/src/native/windows/msofficecomm/DMessengerEventsConnectionPoint.cxx
new file mode 100644
index 0000000..b20982c
--- /dev/null
+++ b/src/native/windows/msofficecomm/DMessengerEventsConnectionPoint.cxx
@@ -0,0 +1,32 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#include "DMessengerEventsConnectionPoint.h"
+
+#include <msgruaid.h>
+
+STDMETHODIMP
+DMessengerEventsConnectionPoint::OnContactStatusChange
+ (LPDISPATCH pMContact, MISTATUS mStatus)
+{
+ const UINT argc = 2;
+ VARIANTARG argv[argc];
+
+ for (UINT i = 0; i < argc; i++)
+ ::VariantInit(argv + i);
+ argv[1].vt = VT_DISPATCH;
+ argv[1].pdispVal = pMContact;
+ argv[0].vt = VT_I4;
+ argv[0].lVal = (LONG) mStatus;
+
+ DISPPARAMS dispParams;
+
+ ::ZeroMemory(&dispParams, sizeof(DISPPARAMS));
+ dispParams.cArgs = argc;
+ dispParams.rgvarg = argv;
+
+ return Invoke(DISPID_MUAE_ONUSERSTATECHANGE, &dispParams);
+}
diff --git a/src/native/windows/msofficecomm/DMessengerEventsConnectionPoint.h b/src/native/windows/msofficecomm/DMessengerEventsConnectionPoint.h
new file mode 100644
index 0000000..771b3f6
--- /dev/null
+++ b/src/native/windows/msofficecomm/DMessengerEventsConnectionPoint.h
@@ -0,0 +1,24 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#ifndef _JMSOFFICECOMM_DMESSENGEREVENTSCONNECTIONPOINT_H_
+#define _JMSOFFICECOMM_DMESSENGEREVENTSCONNECTIONPOINT_H_
+
+#include "ConnectionPoint.h"
+#include <msgrua.h>
+
+class DMessengerEventsConnectionPoint
+ : public ConnectionPoint<DMessengerEvents, DIID_DMessengerEvents>
+{
+public:
+ DMessengerEventsConnectionPoint(IConnectionPointContainer *container)
+ : ConnectionPoint(container) {}
+ virtual ~DMessengerEventsConnectionPoint() {}
+
+ STDMETHODIMP OnContactStatusChange(LPDISPATCH pMContact, MISTATUS mStatus);
+};
+
+#endif /* #ifndef _JMSOFFICECOMM_DMESSENGEREVENTSCONNECTIONPOINT_H_ */
diff --git a/src/native/windows/msofficecomm/DispatchImpl.h b/src/native/windows/msofficecomm/DispatchImpl.h
new file mode 100644
index 0000000..f7abcbe
--- /dev/null
+++ b/src/native/windows/msofficecomm/DispatchImpl.h
@@ -0,0 +1,172 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#ifndef _JMSOFFICECOMM_DISPATCHIMPL_H_
+#define _JMSOFFICECOMM_DISPATCHIMPL_H_
+
+#include <oaidl.h>
+#include "UnknownImpl.h"
+
+/**
+ * Represents a base implementation of the <tt>IDispatch</tt> interface.
+ *
+ * @author Lyubomir Marinov
+ */
+template <class T, REFIID IID_T>
+class DispatchImpl
+ : public UnknownImpl<T, IID_T>
+{
+public:
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID iid, PVOID *obj)
+ {
+ HRESULT ret;
+
+ if (obj)
+ {
+ if (IID_IDispatch == iid)
+ {
+ static_cast<LPUNKNOWN>(this)->AddRef();
+ *obj = static_cast<LPDISPATCH>(this);
+ ret = S_OK;
+ }
+ else
+ ret = UnknownImpl<T, IID_T>::QueryInterface(iid, obj);
+ }
+ else
+ ret = E_POINTER;
+ return ret;
+ }
+
+ // IDispatch
+ STDMETHODIMP GetTypeInfoCount(UINT *pctinfo)
+#ifdef DISPATCHIMPL_CREATESTDDISPATCH
+ {
+ LPDISPATCH iDispatch = getIDispatch();
+ HRESULT hr;
+
+ if (iDispatch)
+ hr = iDispatch->GetTypeInfoCount(pctinfo);
+ else if (pctinfo)
+ {
+ *pctinfo = 0;
+ hr = S_OK;
+ }
+ else
+ hr = E_INVALIDARG;
+ return hr;
+ }
+#else
+ STDMETHODIMP_E_NOTIMPL_STUB
+#endif /* #ifdef DISPATCHIMPL_CREATESTDDISPATCH */
+
+ STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO *ppTInfo)
+#ifdef DISPATCHIMPL_CREATESTDDISPATCH
+ {
+ LPDISPATCH iDispatch = getIDispatch();
+ HRESULT hr;
+
+ if (iDispatch)
+ hr = iDispatch->GetTypeInfo(iTInfo, lcid, ppTInfo);
+ else if (ppTInfo)
+ {
+ *ppTInfo = NULL;
+ hr = TYPE_E_ELEMENTNOTFOUND;
+ }
+ else
+ hr = E_INVALIDARG;
+ return hr;
+ }
+#else
+ STDMETHODIMP_E_NOTIMPL_STUB
+#endif /* #ifdef DISPATCHIMPL_CREATESTDDISPATCH */
+
+ STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
+#ifdef DISPATCHIMPL_CREATESTDDISPATCH
+ {
+ LPDISPATCH iDispatch = getIDispatch();
+ HRESULT hr;
+
+ if (iDispatch)
+ hr = iDispatch->GetIDsOfNames(riid, rgszNames, cNames, lcid, rgDispId);
+ else
+ hr = TYPE_E_ELEMENTNOTFOUND;
+ return hr;
+ }
+#else
+ STDMETHODIMP_E_NOTIMPL_STUB
+#endif /* #ifdef DISPATCHIMPL_CREATESTDDISPATCH */
+
+ STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+#ifdef DISPATCHIMPL_CREATESTDDISPATCH
+ {
+ LPDISPATCH iDispatch = getIDispatch();
+ HRESULT hr;
+
+ if (iDispatch)
+ hr = iDispatch->Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+ else
+ hr = TYPE_E_ELEMENTNOTFOUND;
+ return hr;
+ }
+#else
+ STDMETHODIMP_E_NOTIMPL_STUB
+#endif /* #ifdef DISPATCHIMPL_CREATESTDDISPATCH */
+
+protected:
+ DispatchImpl() : _iDispatch(NULL) {};
+
+ virtual ~DispatchImpl()
+ {
+ if (_iDispatch)
+ {
+ _iDispatch->Release();
+ _iDispatch = NULL;
+ }
+ }
+
+private:
+#ifdef DISPATCHIMPL_CREATESTDDISPATCH
+ LPDISPATCH getIDispatch()
+ {
+ if (!_iDispatch)
+ {
+ LPTYPEINFO iTypeInfo;
+
+ if (SUCCEEDED(
+ OutOfProcessServer::getTypeInfoOfGuid(
+ IID_T,
+ &iTypeInfo)))
+ {
+ LPUNKNOWN iUnknown;
+
+ if (SUCCEEDED(
+ ::CreateStdDispatch(
+ this,
+ this,
+ iTypeInfo,
+ &iUnknown)))
+ {
+ LPDISPATCH iDispatch;
+
+ if (SUCCEEDED(
+ iUnknown->QueryInterface(
+ IID_IDispatch,
+ (PVOID *) &iDispatch)))
+ _iDispatch = iDispatch;
+ iUnknown->Release();
+ }
+ iTypeInfo->Release();
+ }
+ }
+ return _iDispatch;
+ }
+#endif /* #ifdef DISPATCHIMPL_CREATESTDDISPATCH */
+
+ LPDISPATCH _iDispatch;
+};
+
+#endif /* #ifndef _JMSOFFICECOMM_DISPATCHIMPL_H_ */
diff --git a/src/native/windows/msofficecomm/IWeakReference.cxx b/src/native/windows/msofficecomm/IWeakReference.cxx
new file mode 100644
index 0000000..f9feebb
--- /dev/null
+++ b/src/native/windows/msofficecomm/IWeakReference.cxx
@@ -0,0 +1,10 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#include "IWeakReference.h"
+
+EXTERN_C const GUID DECLSPEC_SELECTANY IID_IWeakReference
+ = { 0xc59ff8e2, 0xf328, 0x4c93, { 0xa6, 0x2d, 0xe5, 0x03, 0x27, 0x20, 0x0a, 0x4a } };
diff --git a/src/native/windows/msofficecomm/IWeakReference.h b/src/native/windows/msofficecomm/IWeakReference.h
new file mode 100644
index 0000000..301ec3d
--- /dev/null
+++ b/src/native/windows/msofficecomm/IWeakReference.h
@@ -0,0 +1,25 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#ifndef _JMSOFFICECOMM_IWEAKREFERENCE_H_
+#define _JMSOFFICECOMM_IWEAKREFERENCE_H_
+
+#include <unknwn.h>
+
+EXTERN_C const IID IID_IWeakReference;
+
+#undef INTERFACE /* Silence a possible redefinition warning. */
+#define INTERFACE IWeakReference
+DECLARE_INTERFACE_(IWeakReference,IUnknown)
+{
+ STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+ STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+ STDMETHOD_(ULONG,Release)(THIS) PURE;
+ STDMETHOD(Resolve)(THIS_ REFIID, PVOID *) PURE;
+};
+#undef INTERFACE
+
+#endif /* #ifndef _JMSOFFICECOMM_IWEAKREFERENCE_H_ */
diff --git a/src/native/windows/msofficecomm/IWeakReferenceSource.cxx b/src/native/windows/msofficecomm/IWeakReferenceSource.cxx
new file mode 100644
index 0000000..5552dd6
--- /dev/null
+++ b/src/native/windows/msofficecomm/IWeakReferenceSource.cxx
@@ -0,0 +1,10 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#include "IWeakReferenceSource.h"
+
+EXTERN_C const GUID DECLSPEC_SELECTANY IID_IWeakReferenceSource
+ = { 0xcb401dba, 0xadbe, 0x4d7a, { 0x82, 0x75, 0xe2, 0xc4, 0xb7, 0xf9, 0x5c, 0xe0 } };
diff --git a/src/native/windows/msofficecomm/IWeakReferenceSource.h b/src/native/windows/msofficecomm/IWeakReferenceSource.h
new file mode 100644
index 0000000..7102925
--- /dev/null
+++ b/src/native/windows/msofficecomm/IWeakReferenceSource.h
@@ -0,0 +1,25 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#ifndef _JMSOFFICECOMM_IWEAKREFERENCESOURCE_H_
+#define _JMSOFFICECOMM_IWEAKREFERENCESOURCE_H_
+
+#include "IWeakReference.h"
+
+EXTERN_C const IID IID_IWeakReferenceSource;
+
+#undef INTERFACE /* Silence a possible redefinition warning. */
+#define INTERFACE IWeakReferenceSource
+DECLARE_INTERFACE_(IWeakReferenceSource,IUnknown)
+{
+ STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+ STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+ STDMETHOD_(ULONG,Release)(THIS) PURE;
+ STDMETHOD(GetWeakReference)(THIS_ IWeakReference **) PURE;
+};
+#undef INTERFACE
+
+#endif /* #ifndef _JMSOFFICECOMM_IWEAKREFERENCESOURCE_H_ */
diff --git a/src/native/windows/msofficecomm/Log.cxx b/src/native/windows/msofficecomm/Log.cxx
new file mode 100644
index 0000000..85419c9
--- /dev/null
+++ b/src/native/windows/msofficecomm/Log.cxx
@@ -0,0 +1,140 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#include "Log.h"
+
+#include <stdarg.h>
+#include "StringUtils.h"
+
+FILE *Log::_stderr = NULL;
+
+#ifdef _UNICODE
+int Log::d(LPCTSTR format, LPCSTR str)
+{
+ LPWSTR wstr = StringUtils::MultiByteToWideChar(str);
+ int ret;
+
+ if (wstr)
+ {
+ ret = Log::d(format, wstr);
+ ::free(wstr);
+ }
+ else
+ ret = 0;
+ return ret;
+}
+#endif /* #ifdef _UNICODE */
+
+int Log::d(LPCTSTR format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+
+ int ret = ::_vftprintf(_stderr, format, args);
+
+ ::fflush(_stderr);
+ return ret;
+}
+
+LPTSTR Log::getModuleFileName()
+{
+ HMODULE module;
+ LPTSTR ret = NULL;
+
+ if (::GetModuleHandleEx(
+ GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
+ | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+ (LPCTSTR) (Log::getModuleFileName),
+ &module))
+ {
+ TCHAR path[MAX_PATH + 1];
+ DWORD pathCapacity = sizeof(path) / sizeof(TCHAR);
+ DWORD pathLength = ::GetModuleFileName(module, path, pathCapacity);
+
+ if (pathLength && (pathLength < pathCapacity))
+ {
+ LPTSTR fileName = NULL;
+
+ for (LPTSTR str = path + (pathLength - 1); str != path; str--)
+ {
+ TCHAR ch = *str;
+
+ if ((ch == '\\') || (ch == '/'))
+ {
+ fileName = str + 1;
+ break;
+ }
+ else if (ch == '.')
+ *str = '\0';
+ }
+ if (fileName && (*fileName != '\0'))
+ ret = ::_tcsdup(fileName);
+ }
+ }
+ return ret;
+}
+
+FILE *Log::open()
+{
+ LPCTSTR envVarName = _T("USERPROFILE");
+ DWORD envVarValueLength1 = ::GetEnvironmentVariable(envVarName, NULL, 0);
+ FILE *_stderr = NULL;
+
+ if (envVarValueLength1)
+ {
+ LPTSTR moduleFileName = getModuleFileName();
+
+ if (moduleFileName)
+ {
+ LPCTSTR tracing = _T("\\Tracing\\");
+ size_t tracingLength = ::_tcslen(tracing);
+ size_t tracingSize = sizeof(TCHAR) * tracingLength;
+ size_t moduleFileNameLength = ::_tcslen(moduleFileName);
+ size_t moduleFileNameSize = sizeof(TCHAR) * moduleFileNameLength;
+ LPCTSTR log = _T(".log");
+ size_t logLength = ::_tcslen(log);
+ size_t logSize = sizeof(TCHAR) * logLength;
+ LPTSTR logPath
+ = (LPTSTR)
+ ::malloc(
+ sizeof(TCHAR) * envVarValueLength1
+ + tracingSize
+ + moduleFileNameSize
+ + logSize);
+
+ if (logPath)
+ {
+ DWORD envVarValueLength
+ = ::GetEnvironmentVariable(
+ envVarName,
+ logPath,
+ envVarValueLength1);
+
+ if (envVarValueLength
+ && (envVarValueLength < envVarValueLength1))
+ {
+ LPTSTR str = logPath + envVarValueLength;
+
+ ::memcpy(str, tracing, tracingSize);
+ str += tracingLength;
+ ::memcpy(str, moduleFileName, moduleFileNameSize);
+ str += moduleFileNameLength;
+ ::memcpy(str, log, logSize);
+ str += logLength;
+ *str = '\0';
+
+ _stderr = ::_tfopen(logPath, _T("w"));
+ }
+ ::free(logPath);
+ }
+ ::free(moduleFileName);
+ }
+ }
+
+ Log::_stderr = _stderr ? _stderr : stderr;
+ return Log::_stderr;
+}
diff --git a/src/native/windows/msofficecomm/Log.h b/src/native/windows/msofficecomm/Log.h
new file mode 100644
index 0000000..aa71ae9
--- /dev/null
+++ b/src/native/windows/msofficecomm/Log.h
@@ -0,0 +1,38 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#ifndef _JMSOFFICECOMM_LOG_H_
+#define _JMSOFFICECOMM_LOG_H_
+
+#include <stdio.h>
+#include <tchar.h>
+#include <windows.h>
+
+class Log
+{
+public:
+ static void close()
+ {
+ if (_stderr && (_stderr != stderr))
+ {
+ ::fclose(_stderr);
+ _stderr = stderr;
+ }
+ }
+
+#ifdef _UNICODE
+ static int d(LPCTSTR format, LPCSTR str);
+#endif /* #ifdef _UNICODE */
+ static int d(LPCTSTR format, ...);
+ static FILE *open();
+
+private:
+ static LPTSTR getModuleFileName();
+
+ static FILE *_stderr;
+};
+
+#endif /* #ifndef _JMSOFFICECOMM_LOG_H_ */
diff --git a/src/native/windows/msofficecomm/Messenger.cxx b/src/native/windows/msofficecomm/Messenger.cxx
new file mode 100644
index 0000000..41f42ba
--- /dev/null
+++ b/src/native/windows/msofficecomm/Messenger.cxx
@@ -0,0 +1,876 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#include "Messenger.h"
+
+#include "ConnectionPoint.h"
+#include "MessengerContact.h"
+#include "MessengerContacts.h"
+#include "MessengerServices.h"
+#include "net_java_sip_communicator_plugin_msofficecomm_Messenger.h"
+#include <olectl.h>
+
+EXTERN_C const GUID DECLSPEC_SELECTANY DIID_DMessengerEvents
+ = { 0xC9A6A6B6, 0x9BC1, 0x43a5, { 0xB0, 0x6B, 0xE5, 0x88, 0x74, 0xEE, 0xBC, 0x96 } };
+
+EXTERN_C const GUID DECLSPEC_SELECTANY IID_ICallFactory
+ = { 0x1c733a30, 0x2a1c, 0x11ce, { 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d } };
+
+EXTERN_C const GUID DECLSPEC_SELECTANY IID_IMessenger
+ = { 0xD50C3186, 0x0F89, 0x48f8, { 0xB2, 0x04, 0x36, 0x04, 0x62, 0x9D, 0xEE, 0x10 } };
+
+EXTERN_C const GUID DECLSPEC_SELECTANY IID_IMessenger2
+ = { 0xD50C3286, 0x0F89, 0x48f8, { 0xB2, 0x04, 0x36, 0x04, 0x62, 0x9D, 0xEE, 0x10 } };
+
+EXTERN_C const GUID DECLSPEC_SELECTANY IID_IMessenger3
+ = { 0xD50C3386, 0x0F89, 0x48f8, { 0xB2, 0x04, 0x36, 0x04, 0x62, 0x9D, 0xEE, 0x10 } };
+
+EXTERN_C const GUID DECLSPEC_SELECTANY IID_IMessengerAdvanced
+ = { 0xDA0635E8, 0x09AF, 0x480c, { 0x88, 0xB2, 0xAA, 0x9F, 0xA1, 0xD9, 0xDB, 0x27 } };
+
+EXTERN_C const GUID DECLSPEC_SELECTANY IID_IMessengerContactResolution
+ = { 0x53A5023D, 0x6872, 0x454a, { 0x9A, 0x4F, 0x82, 0x7F, 0x18, 0xCF, 0xBE, 0x02 } };
+
+class OnContactStatusChangeEvent
+{
+public:
+ OnContactStatusChangeEvent(BSTR signinName, MISTATUS status)
+ : _signinName(signinName), _status(status) {}
+ ~OnContactStatusChangeEvent()
+ { ::SysFreeString(_signinName); }
+
+ BSTR _signinName;
+ MISTATUS _status;
+};
+
+JNIEXPORT void JNICALL
+Java_net_java_sip_communicator_plugin_msofficecomm_Messenger_onContactStatusChange
+ (JNIEnv *env, jclass clazz, jstring signinName, jint status)
+{
+ const jchar *chars = env->GetStringChars(signinName, NULL);
+
+ if (chars)
+ {
+ BSTR bstr = ::SysAllocString((LPOLESTR) chars);
+
+ env->ReleaseStringChars(signinName, chars);
+ if (bstr)
+ {
+ OnContactStatusChangeEvent *event
+ = new OnContactStatusChangeEvent(bstr, (MISTATUS) status);
+
+ Messenger::onContactStatusChange((ULONG_PTR) event);
+ }
+ }
+}
+
+jclass Messenger::_jclass = NULL;
+jmethodID Messenger::_jctorMethodID = NULL;
+jmethodID Messenger::_jstartConversationMethodID = NULL;
+Messenger *Messenger::_singleton = NULL;
+
+Messenger::Messenger()
+ : _dMessengerEventsConnectionPoint(NULL),
+ _jobject(NULL),
+ _messengerContactCount(0),
+ _messengerContacts(NULL),
+ _myContacts(NULL),
+ _services(NULL)
+{
+ if (SUCCEEDED(::StringFromCLSID(CLSID_Messenger, &_myServiceId)))
+ constructJobject();
+ else
+ _myServiceId = NULL;
+
+ _singleton = this;
+}
+
+Messenger::~Messenger()
+{
+ if (_singleton == this)
+ _singleton = NULL;
+
+ if (_dMessengerEventsConnectionPoint)
+ delete _dMessengerEventsConnectionPoint;
+ if (_jobject)
+ destructJobject();
+
+ // _messengerContacts
+ if (_messengerContactCount)
+ {
+ size_t i = 0;
+ IWeakReference **messengerContactIt = _messengerContacts;
+
+ for (; i < _messengerContactCount; i++, messengerContactIt++)
+ (*messengerContactIt)->Release();
+ ::free(_messengerContacts);
+ }
+
+ if (_myContacts)
+ _myContacts->Release();
+ if (_myServiceId)
+ ::CoTaskMemFree(_myServiceId);
+ if (_services)
+ _services->Release();
+}
+
+STDMETHODIMP Messenger::AddContact(long hwndParent, BSTR bstrEMail)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::AutoSignin()
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::CreateGroup(BSTR bstrName, VARIANT vService, IDispatch **ppGroup)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+HRESULT Messenger::constructJobject()
+{
+ JavaVM *vm = OutOfProcessServer::getJavaVM();
+ JNIEnv *env;
+ HRESULT hr;
+
+ if (vm && !(vm->AttachCurrentThreadAsDaemon((void **) &env, NULL)))
+ {
+ jobject o = env->NewObject(_jclass, _jctorMethodID);
+
+ if (o)
+ {
+ o = env->NewGlobalRef(o);
+ if (o)
+ {
+ if (_jobject)
+ env->DeleteGlobalRef(_jobject);
+ _jobject = o;
+ hr = S_OK;
+ }
+ else
+ hr = E_OUTOFMEMORY;
+ }
+ else
+ hr = E_FAIL;
+
+ /*
+ * The constructJobject(LPCOLESTR) method is called as part of the
+ * Messenger constructor which does not return an error code so any Java
+ * exception should be cleared in order to prevent unexpected behavior
+ * on the side of the Java VM.
+ */
+ if (FAILED(hr))
+ env->ExceptionClear();
+ }
+ else
+ hr = E_UNEXPECTED;
+ return hr;
+}
+
+HRESULT
+Messenger::createMessengerContact(BSTR signinName, REFIID iid, PVOID *obj)
+{
+ MessengerContact *messengerContact = new MessengerContact(this, signinName);
+ HRESULT hr;
+
+ if (messengerContact)
+ {
+ hr = messengerContact->QueryInterface(iid, obj);
+
+ /*
+ * We've created a new instance and we've asked it about the requested
+ * interface. What follows is keeping track of the instance for the
+ * specified signin name in order to try to avoid having multiple
+ * instances for one and the same signin name at one and the same time
+ * (because MSDN mentions it) and it is not vital.
+ */
+ if (SUCCEEDED(hr))
+ {
+ IWeakReferenceSource *weakReferenceSource;
+
+ if (SUCCEEDED(
+ messengerContact->QueryInterface(
+ IID_IWeakReferenceSource,
+ (PVOID *) &weakReferenceSource)))
+ {
+ IWeakReference *weakReference;
+
+ if (SUCCEEDED(
+ weakReferenceSource->GetWeakReference(&weakReference)))
+ {
+ size_t newMessengerContactCount = _messengerContactCount + 1;
+ IWeakReference **newMessengerContacts
+ = (IWeakReference **)
+ ::realloc(
+ _messengerContacts,
+ newMessengerContactCount
+ * sizeof(IWeakReference *));
+
+ if (newMessengerContacts)
+ {
+ newMessengerContacts[newMessengerContactCount - 1]
+ = weakReference;
+ _messengerContactCount = newMessengerContactCount;
+ _messengerContacts = newMessengerContacts;
+ }
+ else
+ weakReference->Release();
+ }
+ weakReferenceSource->Release();
+ }
+ }
+
+ messengerContact->Release();
+ }
+ else
+ {
+ *obj = NULL;
+ hr = E_OUTOFMEMORY;
+ }
+ return hr;
+}
+
+HRESULT Messenger::destructJobject()
+{
+ JavaVM *vm = OutOfProcessServer::getJavaVM();
+ JNIEnv *env;
+ HRESULT hr;
+
+ if (vm && !(vm->AttachCurrentThreadAsDaemon((void **) &env, NULL)))
+ {
+ env->DeleteGlobalRef(_jobject);
+ _jobject = NULL;
+ hr = S_OK;
+ }
+ else
+ hr = E_UNEXPECTED;
+ return hr;
+}
+
+STDMETHODIMP Messenger::EnumConnectionPoints(IEnumConnectionPoints **ppEnum)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP)
+{
+ HRESULT hr;
+
+ if (ppCP)
+ {
+ if (DIID_DMessengerEvents == riid)
+ {
+ if (!_dMessengerEventsConnectionPoint)
+ {
+ _dMessengerEventsConnectionPoint
+ = new DMessengerEventsConnectionPoint(this);
+ }
+ _dMessengerEventsConnectionPoint->AddRef();
+ *ppCP = _dMessengerEventsConnectionPoint;
+ hr = S_OK;
+ }
+ else
+ {
+ *ppCP = NULL;
+ hr = CONNECT_E_NOCONNECTION;
+ }
+ }
+ else
+ hr = E_POINTER;
+ return hr;
+}
+
+STDMETHODIMP Messenger::FindContact(long hwndParent, BSTR bstrFirstName, BSTR bstrLastName, VARIANT vbstrCity, VARIANT vbstrState, VARIANT vbstrCountry)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::get_ContactsSortOrder(MUASORT *pSort)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::get_MyContacts(IDispatch **ppMContacts)
+ STDMETHODIMP_RESOLVE_WEAKREFERENCE_OR_NEW(ppMContacts,_myContacts,MessengerContacts,this)
+
+STDMETHODIMP Messenger::get_MyFriendlyName(BSTR *pbstrName)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::get_MyGroups(IDispatch **ppMGroups)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::get_MyPhoneNumber(MPHONE_TYPE PhoneType, BSTR *pbstrNumber)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::get_MyProperty(MCONTACTPROPERTY ePropType, VARIANT *pvPropVal)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::get_MyServiceId(BSTR *pbstrServiceId)
+{
+ HRESULT hr;
+
+ if (pbstrServiceId)
+ {
+ if (_myServiceId)
+ {
+ hr
+ = ((*pbstrServiceId = ::SysAllocString(_myServiceId)))
+ ? S_OK
+ : E_OUTOFMEMORY;
+ }
+ else
+ {
+ *pbstrServiceId = NULL;
+ hr = E_FAIL;
+ }
+ }
+ else
+ hr = E_INVALIDARG;
+ return hr;
+}
+
+STDMETHODIMP Messenger::get_MyServiceName(BSTR *pbstrServiceName)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::get_MySigninName(BSTR *pbstrName)
+{
+ return get_MyServiceId(pbstrName);
+}
+
+STDMETHODIMP Messenger::get_MyStatus(MISTATUS *pmStatus)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::get_Property(MMESSENGERPROPERTY ePropType, VARIANT *pvPropVal)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::get_ReceiveFileDirectory(BSTR *bstrPath)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::get_Services(IDispatch **ppdispServices)
+ STDMETHODIMP_RESOLVE_WEAKREFERENCE_OR_NEW(ppdispServices,_services,MessengerServices,this)
+
+STDMETHODIMP Messenger::get_UnreadEmailCount(MUAFOLDER mFolder, LONG *plCount)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::get_Window(IDispatch **ppMWindow)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::GetAuthenticationInfo(BSTR *pbstrAuthInfo)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP
+Messenger::GetContact(BSTR bstrSigninName, BSTR bstrServiceId, IDispatch **ppMContact)
+{
+ HRESULT hr;
+
+ if (ppMContact)
+ {
+ if (bstrSigninName)
+ {
+ /*
+ * Try to find an existing MessengerContact instance which has not
+ * been released to deletion yet and which has the specified signin
+ * name.
+ */
+ hr
+ = getMessengerContact(
+ bstrSigninName,
+ IID_IDispatch,
+ (PVOID *) ppMContact);
+ if (FAILED(hr))
+ {
+ /*
+ * Try to find a contact with the specified signin name in the
+ * MyContacts collection of this Messenger.
+ */
+ LPDISPATCH iDispatch;
+
+ hr = get_MyContacts(&iDispatch);
+ if (SUCCEEDED(hr))
+ {
+ IMessengerContacts *myContacts;
+
+ hr
+ = iDispatch->QueryInterface(
+ IID_IMessengerContacts,
+ (PVOID *) &myContacts);
+ iDispatch->Release();
+ if (SUCCEEDED(hr))
+ {
+ LONG myContactCount;
+
+ hr = myContacts->get_Count(&myContactCount);
+ if (SUCCEEDED(hr))
+ {
+ for (LONG i = 0; i < myContactCount; i++)
+ {
+ hr = myContacts->Item(i, &iDispatch);
+ if (SUCCEEDED(hr))
+ {
+ if (MessengerContact::signinNameEquals(
+ iDispatch,
+ bstrSigninName))
+ {
+ *ppMContact = iDispatch;
+ break;
+ }
+ else
+ iDispatch->Release();
+ }
+ else
+ break;
+ }
+ }
+ myContacts->Release();
+ }
+ }
+
+ if (FAILED(hr) || !(*ppMContact))
+ {
+ hr
+ = createMessengerContact(
+ bstrSigninName,
+ IID_IDispatch,
+ (PVOID *) ppMContact);
+ }
+ }
+ }
+ else
+ {
+ *ppMContact = NULL;
+ hr = E_FAIL;
+ }
+ }
+ else
+ hr = RPC_X_NULL_REF_POINTER;
+ return hr;
+}
+
+HRESULT Messenger::getMessengerContact(BSTR signinName, REFIID iid, PVOID *obj)
+{
+ *obj = NULL;
+
+ size_t i = 0;
+ IWeakReference **messengerContactIt = _messengerContacts;
+ HRESULT hr = E_FAIL;
+
+ while (i < _messengerContactCount)
+ {
+ IWeakReference *weakReference = *messengerContactIt;
+ LPDISPATCH iDispatch;
+
+ hr = weakReference->Resolve(IID_IDispatch, (PVOID *) &iDispatch);
+ if (SUCCEEDED(hr))
+ {
+ if (MessengerContact::signinNameEquals(iDispatch, signinName))
+ {
+ if (IID_IDispatch == iid)
+ *obj = iDispatch;
+ else
+ {
+ hr = weakReference->Resolve(iid, obj);
+ iDispatch->Release();
+ }
+ break;
+ }
+ else
+ iDispatch->Release();
+
+ i++;
+ messengerContactIt++;
+ }
+ else if (E_NOINTERFACE != hr)
+ {
+ /*
+ * The weakReference appears to have been invalidated. Release the
+ * resources associated with it.
+ */
+ *messengerContactIt = NULL;
+ weakReference->Release();
+
+ _messengerContactCount--;
+
+ /*
+ * Move the emptied slot of the _messengerContacts storage at the
+ * end where it is not accessible given the value of
+ * _messengerContactCount.
+ */
+ size_t j = i;
+ IWeakReference **it = messengerContactIt;
+
+ for (; j < _messengerContactCount; j++)
+ {
+ IWeakReference **nextIt = it + 1;
+
+ *it = *nextIt;
+ it = nextIt;
+ }
+ }
+ }
+
+ if (SUCCEEDED(hr) && !(*obj))
+ hr = E_FAIL;
+ return hr;
+}
+
+STDMETHODIMP Messenger::InstantMessage(VARIANT vContact, IDispatch **ppMWindow)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::InviteApp(VARIANT vContact, BSTR bstrAppID, IDispatch **ppMWindow)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::MediaWizard(long hwndParent)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+void CALLBACK Messenger::onContactStatusChange(ULONG_PTR dwParam)
+{
+ BOOL run;
+
+ OutOfProcessServer::enterCriticalSection();
+
+ HANDLE threadHandle = OutOfProcessServer::getThreadHandle();
+
+ if (threadHandle)
+ {
+ run = (::GetCurrentThreadId() == OutOfProcessServer::getThreadId());
+ if (!run
+ && !::QueueUserAPC(
+ onContactStatusChange,
+ threadHandle,
+ dwParam))
+ {
+ delete (OnContactStatusChangeEvent *) dwParam;
+ }
+ }
+ else
+ {
+ run = FALSE;
+ delete (OnContactStatusChangeEvent *) dwParam;
+ }
+
+ OutOfProcessServer::leaveCriticalSection();
+
+ if (run)
+ {
+ Messenger *thiz = _singleton;
+ OnContactStatusChangeEvent *event
+ = (OnContactStatusChangeEvent *) dwParam;
+
+ if (thiz && thiz->_dMessengerEventsConnectionPoint)
+ {
+ HRESULT hr;
+ LPDISPATCH contact;
+
+ hr = thiz->GetContact(event->_signinName, NULL, &contact);
+ if (SUCCEEDED(hr))
+ {
+ hr
+ = thiz->_dMessengerEventsConnectionPoint
+ ->OnContactStatusChange(contact, event->_status);
+ contact->Release();
+ }
+ }
+
+ delete event;
+ }
+}
+
+STDMETHODIMP Messenger::OpenInbox()
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::OptionsPages(long hwndParent, MOPTIONPAGE mOptionPage)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::Page(VARIANT vContact, IDispatch **ppMWindow)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::Phone(VARIANT vContact, MPHONE_TYPE ePhoneNumber, BSTR bstrNumber, IDispatch **ppMWindow)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::put_ContactsSortOrder(MUASORT Sort)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::put_MyProperty(MCONTACTPROPERTY ePropType, VARIANT vPropVal)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::put_MyStatus(MISTATUS mStatus)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::put_Property(MMESSENGERPROPERTY ePropType, VARIANT vPropVal)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::QueryInterface(REFIID iid, PVOID *obj)
+{
+ HRESULT hr;
+
+ if (!obj)
+ hr = E_POINTER;
+ else if (IID_IMessenger == iid)
+ {
+ AddRef();
+ *obj = static_cast<IMessenger *>(this);
+ hr = S_OK;
+ }
+ else if (IID_IMessenger2 == iid)
+ {
+ AddRef();
+ *obj = static_cast<IMessenger2 *>(this);
+ hr = S_OK;
+ }
+ else if (IID_IMessenger3 == iid)
+ {
+ AddRef();
+ *obj = static_cast<IMessenger3 *>(this);
+ hr = S_OK;
+ }
+ else if (IID_IMessengerAdvanced == iid)
+ {
+ AddRef();
+ *obj = static_cast<IMessengerAdvanced *>(this);
+ hr = S_OK;
+ }
+ else if (IID_IConnectionPointContainer == iid)
+ {
+ AddRef();
+ *obj = static_cast<IConnectionPointContainer *>(this);
+ hr = S_OK;
+ }
+ else if (IID_IMessengerContactResolution == iid)
+ {
+ AddRef();
+ *obj = static_cast<IMessengerContactResolution *>(this);
+ hr = S_OK;
+ }
+ else
+ hr = DispatchImpl::QueryInterface(iid, obj);
+ return hr;
+}
+
+STDMETHODIMP
+Messenger::ResolveContact(ADDRESS_TYPE AddressType, CONTACT_RESOLUTION_TYPE ResolutionType, BSTR bstrAddress, BSTR *pbstrIMAddress)
+{
+ HRESULT hr;
+
+ if (pbstrIMAddress)
+ {
+ if (bstrAddress)
+ {
+ if (ADDRESS_TYPE_SMTP == AddressType)
+ {
+ hr
+ = ((*pbstrIMAddress = ::SysAllocString(bstrAddress)))
+ ? S_OK
+ : E_OUTOFMEMORY;
+ }
+ else
+ {
+ *pbstrIMAddress = NULL;
+ hr = E_NOTIMPL;
+ }
+ }
+ else
+ {
+ *pbstrIMAddress = NULL;
+ hr = E_INVALIDARG;
+ }
+ }
+ else
+ hr = RPC_X_NULL_REF_POINTER;
+ return hr;
+}
+
+STDMETHODIMP Messenger::SendFile(VARIANT vContact, BSTR bstrFileName, IDispatch **ppMWindow)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::SendMail(VARIANT vContact)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::Signin(long hwndParent, BSTR bstrSigninName, BSTR bstrPassword)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::Signout()
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+HRESULT Messenger::start(JNIEnv *env)
+{
+ LPSTR className = OutOfProcessServer::getClassName("Messenger");
+ HRESULT hr;
+
+ if (className)
+ {
+ jclass clazz = env->FindClass(className);
+
+ ::free(className);
+
+ if (clazz)
+ {
+ jmethodID ctorMethodID = env->GetMethodID(clazz, "<init>", "()V");
+
+ if (ctorMethodID)
+ {
+ jmethodID startConversationMethodID
+ = env->GetMethodID(
+ clazz,
+ "startConversation",
+ "(I[Ljava/lang/String;)V");
+
+ if (startConversationMethodID)
+ {
+ clazz = (jclass) env->NewGlobalRef(clazz);
+ if (clazz)
+ {
+ _jclass = clazz;
+ _jctorMethodID = ctorMethodID;
+ _jstartConversationMethodID = startConversationMethodID;
+ hr = S_OK;
+ }
+ else
+ hr = E_OUTOFMEMORY;
+ }
+ else
+ hr = E_FAIL;
+ }
+ else
+ hr = E_FAIL;
+ }
+ else
+ hr = E_FAIL;
+ }
+ else
+ hr = E_OUTOFMEMORY;
+ return hr;
+}
+
+STDMETHODIMP
+Messenger::StartConversation
+ (CONVERSATION_TYPE ConversationType,
+ VARIANT vParticipants,
+ VARIANT vContextualData,
+ VARIANT vSubject,
+ VARIANT vConversationIndex,
+ VARIANT vConversationData,
+ VARIANT *pvWndHnd)
+{
+ HRESULT hr;
+
+ if (VT_ARRAY == (vParticipants.vt & VT_ARRAY))
+ {
+ SAFEARRAY *sa = vParticipants.parray;
+
+ if (sa
+ && (1 == sa->cDims)
+ && (FADF_VARIANT == (sa->fFeatures & FADF_VARIANT)))
+ {
+ jbyte *data;
+
+ hr = ::SafeArrayAccessData(sa, (PVOID *) &data);
+ if (SUCCEEDED(hr))
+ {
+ JavaVM *vm = OutOfProcessServer::getJavaVM();
+ JNIEnv *env;
+
+ if (vm
+ && !(vm->AttachCurrentThreadAsDaemon(
+ (void **) &env,
+ NULL)))
+ {
+ jclass stringClass = env->FindClass("java/lang/String");
+
+ if (stringClass)
+ {
+ SAFEARRAYBOUND *bound = sa->rgsabound;
+ ULONG length = bound->cElements;
+ jobjectArray participants
+ = env->NewObjectArray(length, stringClass, NULL);
+
+ if (participants)
+ {
+ ULONG elemsize = sa->cbElements;
+
+ data += bound->lLbound;
+ for (ULONG i = 0; i < length; i++, data += elemsize)
+ {
+ VARIANT *v = (VARIANT *) data;
+ BSTR bstr;
+
+ if (VT_BSTR == v->vt)
+ bstr = v->bstrVal;
+ else if ((VT_BSTR | VT_BYREF) == v->vt)
+ bstr = *(v->pbstrVal);
+ else
+ {
+ hr = E_INVALIDARG;
+ break;
+ }
+
+ jstring participant
+ = env->NewString(
+ (const jchar *) bstr,
+ ::SysStringLen(bstr));
+
+ if (participant)
+ {
+ env->SetObjectArrayElement(
+ participants,
+ i,
+ participant);
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ break;
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (_jobject)
+ {
+ env->CallVoidMethod(
+ _jobject,
+ _jstartConversationMethodID,
+ (jint) ConversationType,
+ participants);
+ if (env->ExceptionCheck())
+ {
+ env->ExceptionClear();
+ hr = E_FAIL;
+ }
+ }
+ else
+ hr = E_FAIL;
+ }
+ }
+ else
+ hr = E_OUTOFMEMORY;
+ }
+ else
+ hr = E_UNEXPECTED;
+ }
+ else
+ hr = E_UNEXPECTED;
+ ::SafeArrayUnaccessData(sa);
+ }
+ }
+ else
+ hr = E_INVALIDARG;
+ }
+ else
+ hr = E_INVALIDARG;
+ return hr;
+}
+
+STDMETHODIMP Messenger::StartVideo(VARIANT vContact, IDispatch **ppMWindow)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP Messenger::StartVoice(VARIANT vContact, IDispatch **ppMWindow)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+HRESULT Messenger::stop(JNIEnv *env)
+{
+ jclass clazz = _jclass;
+
+ _jclass = NULL;
+ _jctorMethodID = NULL;
+ _jstartConversationMethodID = NULL;
+ if (clazz)
+ env->DeleteGlobalRef(clazz);
+
+ return S_OK;
+}
+
+STDMETHODIMP Messenger::ViewProfile(VARIANT vContact)
+ STDMETHODIMP_E_NOTIMPL_STUB
diff --git a/src/native/windows/msofficecomm/Messenger.h b/src/native/windows/msofficecomm/Messenger.h
new file mode 100644
index 0000000..7a8051c
--- /dev/null
+++ b/src/native/windows/msofficecomm/Messenger.h
@@ -0,0 +1,126 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#ifndef _JMSOFFICECOMM_MESSENGER_H_
+#define _JMSOFFICECOMM_MESSENGER_H_
+
+#include "DispatchImpl.h"
+#include "DMessengerEventsConnectionPoint.h"
+#include <msgrua.h>
+
+/**
+ * Implements the <tt>IMessenger</tt>, <tt>IMessenger2</tt>,
+ * <tt>IMessenger3</tt>, <tt>IMessengerAdvanced</tt> and
+ * <tt>IMessengerContactResolution</tt> interfaces.
+ *
+ * @author Lyubomir Marinov
+ */
+class Messenger
+ : public DispatchImpl<IMessengerAdvanced, IID_IMessengerAdvanced>,
+ public IConnectionPointContainer,
+ public IMessengerContactResolution
+{
+public:
+ static void CALLBACK onContactStatusChange(ULONG_PTR dwParam);
+ static HRESULT start(JNIEnv *env);
+ static HRESULT stop(JNIEnv *env);
+
+ Messenger();
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID, PVOID *);
+ STDMETHODIMP_(ULONG) AddRef(THIS) { return DispatchImpl::AddRef(); };
+ STDMETHODIMP_(ULONG) Release(THIS) { return DispatchImpl::Release(); };
+
+ // IDispatch
+ STDMETHODIMP GetTypeInfoCount(UINT *pctinfo)
+ { return DispatchImpl::GetTypeInfoCount(pctinfo); };
+ STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO *ppTInfo)
+ { return DispatchImpl::GetTypeInfo(iTInfo, lcid, ppTInfo); };
+ STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
+ { return DispatchImpl::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgDispId); };
+ STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+ { return DispatchImpl::Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); };
+
+ // IMessenger
+ STDMETHODIMP get_Window(IDispatch **ppMWindow);
+ STDMETHODIMP ViewProfile(VARIANT vContact);
+ STDMETHODIMP get_ReceiveFileDirectory(BSTR *bstrPath);
+ STDMETHODIMP StartVoice(VARIANT vContact, IDispatch **ppMWindow);
+ STDMETHODIMP InviteApp(VARIANT vContact, BSTR bstrAppID, IDispatch **ppMWindow);
+ STDMETHODIMP SendMail(VARIANT vContact);
+ STDMETHODIMP OpenInbox();
+ STDMETHODIMP SendFile(VARIANT vContact, BSTR bstrFileName, IDispatch **ppMWindow);
+ STDMETHODIMP Signout();
+ STDMETHODIMP Signin(long hwndParent, BSTR bstrSigninName, BSTR bstrPassword);
+ STDMETHODIMP GetContact(BSTR bstrSigninName, BSTR bstrServiceId, IDispatch **ppMContact);
+ STDMETHODIMP OptionsPages(long hwndParent, MOPTIONPAGE mOptionPage);
+ STDMETHODIMP AddContact(long hwndParent, BSTR bstrEMail);
+ STDMETHODIMP FindContact(long hwndParent, BSTR bstrFirstName, BSTR bstrLastName, VARIANT vbstrCity, VARIANT vbstrState, VARIANT vbstrCountry);
+ STDMETHODIMP InstantMessage(VARIANT vContact, IDispatch **ppMWindow);
+ STDMETHODIMP Phone(VARIANT vContact, MPHONE_TYPE ePhoneNumber, BSTR bstrNumber, IDispatch **ppMWindow);
+ STDMETHODIMP MediaWizard(long hwndParent);
+ STDMETHODIMP Page(VARIANT vContact, IDispatch **ppMWindow);
+ STDMETHODIMP AutoSignin();
+ STDMETHODIMP get_MyContacts(IDispatch **ppMContacts);
+ STDMETHODIMP get_MySigninName(BSTR *pbstrName);
+ STDMETHODIMP get_MyFriendlyName(BSTR *pbstrName);
+ STDMETHODIMP put_MyStatus(MISTATUS mStatus);
+ STDMETHODIMP get_MyStatus(MISTATUS *pmStatus);
+ STDMETHODIMP get_UnreadEmailCount(MUAFOLDER mFolder, LONG *plCount);
+ STDMETHODIMP get_MyServiceName(BSTR *pbstrServiceName);
+ STDMETHODIMP get_MyPhoneNumber(MPHONE_TYPE PhoneType, BSTR *pbstrNumber);
+ STDMETHODIMP get_MyProperty(MCONTACTPROPERTY ePropType, VARIANT *pvPropVal);
+ STDMETHODIMP put_MyProperty(MCONTACTPROPERTY ePropType, VARIANT vPropVal);
+ STDMETHODIMP get_MyServiceId(BSTR *pbstrServiceId);
+ STDMETHODIMP get_Services(IDispatch **ppdispServices);
+
+ // IMessenger2
+ STDMETHODIMP get_ContactsSortOrder(MUASORT *pSort);
+ STDMETHODIMP put_ContactsSortOrder(MUASORT Sort);
+ STDMETHODIMP StartVideo(VARIANT vContact, IDispatch **ppMWindow);
+ STDMETHODIMP get_MyGroups(IDispatch **ppMGroups);
+ STDMETHODIMP CreateGroup(BSTR bstrName, VARIANT vService, IDispatch **ppGroup);
+
+ // IMessenger3
+ STDMETHODIMP get_Property(MMESSENGERPROPERTY ePropType, VARIANT *pvPropVal);
+ STDMETHODIMP put_Property(MMESSENGERPROPERTY ePropType, VARIANT vPropVal);
+
+ // IMessengerAdvanced
+ STDMETHODIMP StartConversation(CONVERSATION_TYPE ConversationType, VARIANT vParticipants, VARIANT vContextualData, VARIANT vSubject, VARIANT vConversationIndex, VARIANT vConversationData, VARIANT *pvWndHnd);
+ STDMETHODIMP GetAuthenticationInfo(BSTR *pbstrAuthInfo);
+
+ // IConnectionPointContainer
+ STDMETHODIMP EnumConnectionPoints(IEnumConnectionPoints **ppEnum);
+ STDMETHODIMP FindConnectionPoint(REFIID riid,IConnectionPoint **ppCP);
+
+ // IMessengerContactResolution
+ STDMETHODIMP ResolveContact(ADDRESS_TYPE AddressType, CONTACT_RESOLUTION_TYPE ResolutionType, BSTR bstrAddress, BSTR *pbstrIMAddress);
+
+protected:
+ virtual ~Messenger();
+
+private:
+ static jclass _jclass;
+ static jmethodID _jctorMethodID;
+ static jmethodID _jstartConversationMethodID;
+ static Messenger * _singleton;
+
+ HRESULT constructJobject();
+ HRESULT createMessengerContact(BSTR signinName, REFIID iid, PVOID *obj);
+ HRESULT destructJobject();
+ HRESULT getMessengerContact(BSTR signinName, REFIID iid, PVOID *obj);
+
+ DMessengerEventsConnectionPoint *_dMessengerEventsConnectionPoint;
+ jobject _jobject;
+ size_t _messengerContactCount;
+ IWeakReference ** _messengerContacts;
+ IWeakReference * _myContacts;
+ LPOLESTR _myServiceId;
+ IWeakReference * _services;
+};
+
+#endif /* #ifndef _JMSOFFICECOMM_MESSENGER_H_ */
diff --git a/src/native/windows/msofficecomm/MessengerClassFactory.cxx b/src/native/windows/msofficecomm/MessengerClassFactory.cxx
new file mode 100644
index 0000000..2152df5
--- /dev/null
+++ b/src/native/windows/msofficecomm/MessengerClassFactory.cxx
@@ -0,0 +1,66 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#include "MessengerClassFactory.h"
+
+#include "Messenger.h"
+
+EXTERN_C const GUID DECLSPEC_SELECTANY CLSID_Messenger
+ = { 0x8885370D, 0xB33E, 0x44b7, { 0x87, 0x5D, 0x28, 0xE4, 0x03, 0xCF, 0x92, 0x70 } };
+
+STDMETHODIMP
+MessengerClassFactory::CreateInstance(LPUNKNOWN outer, REFIID iid, PVOID *obj)
+{
+ HRESULT hr;
+
+ if (outer)
+ {
+ *obj = NULL;
+ hr = CLASS_E_NOAGGREGATION;
+ }
+ else
+ {
+ IMessenger *messenger;
+
+ if (_messenger)
+ {
+ hr = _messenger->Resolve(IID_IMessenger, (PVOID *) &messenger);
+ if (FAILED(hr) && (E_NOINTERFACE != hr))
+ {
+ _messenger->Release();
+ _messenger = NULL;
+ }
+ }
+ else
+ messenger = NULL;
+ if (!messenger)
+ {
+ messenger = new Messenger();
+
+ IWeakReferenceSource *weakReferenceSource;
+
+ hr
+ = messenger->QueryInterface(
+ IID_IWeakReferenceSource,
+ (PVOID *) &weakReferenceSource);
+ if (SUCCEEDED(hr))
+ {
+ IWeakReference *weakReference;
+
+ hr = weakReferenceSource->GetWeakReference(&weakReference);
+ if (SUCCEEDED(hr))
+ {
+ if (_messenger)
+ _messenger->Release();
+ _messenger = weakReference;
+ }
+ }
+ }
+ hr = messenger->QueryInterface(iid, obj);
+ messenger->Release();
+ }
+ return hr;
+}
diff --git a/src/native/windows/msofficecomm/MessengerClassFactory.h b/src/native/windows/msofficecomm/MessengerClassFactory.h
new file mode 100644
index 0000000..52c1a2b
--- /dev/null
+++ b/src/native/windows/msofficecomm/MessengerClassFactory.h
@@ -0,0 +1,39 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#ifndef _JMSOFFICECOMM_MESSENGERCLASSFACTORY_H_
+#define _JMSOFFICECOMM_MESSENGERCLASSFACTORY_H_
+
+#include "ClassFactory.h"
+#include <msgrua.h>
+
+/**
+ * Implements the <tt>IClassFactory</tt> interface for the <tt>IMessenger</tt>
+ * interface implementation.
+ *
+ * @author Lyubomir Marinov
+ */
+class MessengerClassFactory
+ : public ClassFactory
+{
+public:
+ MessengerClassFactory()
+ : ClassFactory(CLSID_Messenger), _messenger(NULL) {}
+
+ STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, PVOID *);
+
+protected:
+ virtual ~MessengerClassFactory()
+ {
+ if (_messenger)
+ _messenger->Release();
+ }
+
+private:
+ IWeakReference *_messenger;
+};
+
+#endif /* _JMSOFFICECOMM_MESSENGERCLASSFACTORY_H_ */
diff --git a/src/native/windows/msofficecomm/MessengerContact.cxx b/src/native/windows/msofficecomm/MessengerContact.cxx
new file mode 100644
index 0000000..73e9a2f
--- /dev/null
+++ b/src/native/windows/msofficecomm/MessengerContact.cxx
@@ -0,0 +1,460 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#include "MessengerContact.h"
+
+EXTERN_C const GUID DECLSPEC_SELECTANY IID_IMessengerContact
+ = { 0xE7479A0F, 0xBB19, 0x44a5, { 0x96, 0x8F, 0x6F, 0x41, 0xD9, 0x3E, 0xE0, 0xBC } };
+
+EXTERN_C const GUID DECLSPEC_SELECTANY IID_IMessengerContactAdvanced
+ = { 0x086F69C0, 0x2FBD, 0x46b3, { 0xBE, 0x50, 0xEC, 0x40, 0x1A, 0xB8, 0x60, 0x99 } };
+
+jclass MessengerContact::_jclass = NULL;
+jmethodID MessengerContact::_jctorMethodID = NULL;
+jmethodID MessengerContact::_jgetStatusMethodID = NULL;
+jmethodID MessengerContact::_jisSelfMethodID = NULL;
+
+MessengerContact::MessengerContact(IMessenger *messenger, LPCOLESTR signinName)
+ : _messenger(messenger),
+ _jobject(NULL)
+{
+ _messenger->AddRef();
+ if (signinName)
+ {
+ _signinName = ::_wcsdup(signinName);
+ constructJobject(_signinName);
+ }
+ else
+ _signinName = NULL;
+}
+
+MessengerContact::~MessengerContact()
+{
+ if (_jobject)
+ destructJobject();
+ _messenger->Release();
+ if (_signinName)
+ ::free(_signinName);
+}
+
+HRESULT MessengerContact::constructJobject(LPCOLESTR signinName)
+{
+ HRESULT hr;
+
+ if (signinName)
+ {
+ JavaVM *vm = OutOfProcessServer::getJavaVM();
+ JNIEnv *env;
+
+ if (vm && !(vm->AttachCurrentThreadAsDaemon((void **) &env, NULL)))
+ {
+ jstring jsigninName
+ = env->NewString(
+ (const jchar *) signinName,
+ ::wcslen(signinName));
+
+ if (jsigninName)
+ {
+ jobject o = env->NewObject(_jclass, _jctorMethodID, jsigninName);
+
+ if (o)
+ {
+ o = env->NewGlobalRef(o);
+ if (o)
+ {
+ if (_jobject)
+ env->DeleteGlobalRef(_jobject);
+ _jobject = o;
+ hr = S_OK;
+ }
+ else
+ hr = E_OUTOFMEMORY;
+ }
+ else
+ hr = E_FAIL;
+ }
+ else
+ hr = E_OUTOFMEMORY;
+
+ /*
+ * The constructJobject(LPCOLESTR) method is called as part of the
+ * MessengerContact constructor which does not return an error code
+ * so any Java exception should be cleared in order to prevent
+ * unexpected behavior on the side of the Java VM.
+ */
+ if (FAILED(hr))
+ env->ExceptionClear();
+ }
+ else
+ hr = E_UNEXPECTED;
+ }
+ else
+ hr = E_INVALIDARG;
+ return hr;
+}
+
+HRESULT MessengerContact::destructJobject()
+{
+ JavaVM *vm = OutOfProcessServer::getJavaVM();
+ JNIEnv *env;
+ HRESULT hr;
+
+ if (vm && !(vm->AttachCurrentThreadAsDaemon((void **) &env, NULL)))
+ {
+ env->DeleteGlobalRef(_jobject);
+ _jobject = NULL;
+ hr = S_OK;
+ }
+ else
+ hr = E_UNEXPECTED;
+ return hr;
+}
+
+STDMETHODIMP MessengerContact::get_Blocked(VARIANT_BOOL *pBoolBlock)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP MessengerContact::get_CanPage(VARIANT_BOOL *pBoolPage)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP MessengerContact::get_FriendlyName(BSTR *pbstrFriendlyName)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP MessengerContact::get_IsSelf(VARIANT_BOOL *pBoolSelf)
+{
+ HRESULT hr;
+
+ if (pBoolSelf)
+ {
+ if (_jobject)
+ {
+ JavaVM *vm = OutOfProcessServer::getJavaVM();
+ JNIEnv *env;
+
+ if (vm && !(vm->AttachCurrentThreadAsDaemon((void **) &env, NULL)))
+ {
+ jboolean jself
+ = env->CallBooleanMethod(_jobject, _jisSelfMethodID);
+
+ if (env->ExceptionCheck())
+ {
+ env->ExceptionClear();
+ hr = E_FAIL;
+ }
+ else
+ {
+ *pBoolSelf
+ = (JNI_TRUE == jself) ? VARIANT_TRUE : VARIANT_FALSE;
+ hr = S_OK;
+ }
+ }
+ else
+ hr = E_UNEXPECTED;
+ }
+ else
+ hr = E_FAIL;
+ }
+ else
+ hr = RPC_X_NULL_REF_POINTER;
+ return hr;
+}
+
+STDMETHODIMP MessengerContact::get_IsTagged(VARIANT_BOOL *pBoolIsTagged)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP MessengerContact::get_PhoneNumber(MPHONE_TYPE PhoneType, BSTR *bstrNumber)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP
+MessengerContact::get_PresenceProperties(VARIANT *pvPresenceProperties)
+{
+ HRESULT hr;
+
+ if (pvPresenceProperties)
+ {
+ MISTATUS status;
+
+ hr = get_Status(&status);
+ if (SUCCEEDED(hr))
+ {
+ hr
+ = (VT_EMPTY == pvPresenceProperties->vt)
+ ? S_OK
+ : (::VariantClear(pvPresenceProperties));
+ if (SUCCEEDED(hr))
+ {
+ SAFEARRAY *sa
+ = ::SafeArrayCreateVector(VT_VARIANT, 0, PRESENCE_PROP_MAX);
+
+ if (sa)
+ {
+ LONG i;
+ VARIANT v;
+
+ i = PRESENCE_PROP_MSTATE;
+ ::VariantInit(&v);
+ v.vt = VT_I4;
+ v.lVal = status;
+ hr = ::SafeArrayPutElement(sa, &i, &v);
+ if (SUCCEEDED(hr))
+ {
+ LONG availability;
+
+ switch (status)
+ {
+ case MISTATUS_AWAY:
+ availability = 15000;
+ break;
+ case MISTATUS_BE_RIGHT_BACK:
+ availability = 12000;
+ break;
+ case MISTATUS_BUSY:
+ availability = 6000;
+ break;
+ case MISTATUS_DO_NOT_DISTURB:
+ availability = 9000;
+ break;
+ case MISTATUS_INVISIBLE:
+ availability = 18000;
+ break;
+ case MISTATUS_ONLINE:
+ availability = 3000;
+ break;
+ default:
+ availability = 0;
+ break;
+ }
+ if (availability)
+ {
+ i = PRESENCE_PROP_AVAILABILITY;
+ v.lVal = availability;
+ hr = ::SafeArrayPutElement(sa, &i, &v);
+ }
+ }
+ if (SUCCEEDED(hr))
+ {
+ pvPresenceProperties->vt = VT_ARRAY;
+ pvPresenceProperties->parray = sa;
+ }
+ else
+ ::SafeArrayDestroy(sa);
+ }
+ else
+ hr = E_FAIL;
+ }
+ }
+ }
+ else
+ hr = E_INVALIDARG;
+ return hr;
+}
+
+STDMETHODIMP MessengerContact::get_Property(MCONTACTPROPERTY ePropType, VARIANT *pvPropVal)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP MessengerContact::get_ServiceId(BSTR *pbstrServiceID)
+{
+ return _messenger->get_MyServiceId(pbstrServiceID);
+}
+
+STDMETHODIMP MessengerContact::get_ServiceName(BSTR *pbstrServiceName)
+{
+ return _messenger->get_MyServiceName(pbstrServiceName);
+}
+
+STDMETHODIMP MessengerContact::get_SigninName(BSTR *pbstrSigninName)
+{
+ HRESULT hr;
+
+ if (pbstrSigninName)
+ {
+ if (_signinName)
+ {
+ hr
+ = ((*pbstrSigninName = ::SysAllocString(_signinName)))
+ ? S_OK
+ : E_OUTOFMEMORY;
+ }
+ else
+ {
+ *pbstrSigninName = NULL;
+ hr = E_FAIL;
+ }
+ }
+ else
+ hr = RPC_X_NULL_REF_POINTER;
+ return hr;
+}
+
+STDMETHODIMP MessengerContact::get_Status(MISTATUS *pMstate)
+{
+ HRESULT hr;
+
+ if (pMstate)
+ {
+ if (_jobject)
+ {
+ JavaVM *vm = OutOfProcessServer::getJavaVM();
+ JNIEnv *env;
+
+ if (vm && !(vm->AttachCurrentThreadAsDaemon((void **) &env, NULL)))
+ {
+ jint jstatus
+ = env->CallIntMethod(_jobject, _jgetStatusMethodID);
+
+ if (env->ExceptionCheck())
+ {
+ env->ExceptionClear();
+ hr = E_FAIL;
+ }
+ else
+ {
+ *pMstate = (MISTATUS) jstatus;
+ hr = S_OK;
+ }
+ }
+ else
+ hr = E_UNEXPECTED;
+ }
+ else
+ hr = E_FAIL;
+ }
+ else
+ hr = RPC_X_NULL_REF_POINTER;
+ return hr;
+}
+
+STDMETHODIMP MessengerContact::put_Blocked(VARIANT_BOOL pBoolBlock)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP MessengerContact::put_IsTagged(VARIANT_BOOL pBoolIsTagged)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP MessengerContact::put_PresenceProperties(VARIANT vPresenceProperties)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP MessengerContact::put_Property(MCONTACTPROPERTY ePropType, VARIANT vPropVal)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP MessengerContact::QueryInterface(REFIID iid, PVOID *obj)
+{
+ HRESULT hr;
+
+ if (obj)
+ {
+ if (IID_IMessengerContact == iid)
+ {
+ AddRef();
+ *obj = static_cast<IMessengerContact *>(this);
+ hr = S_OK;
+ }
+ else
+ hr = DispatchImpl::QueryInterface(iid, obj);
+ }
+ else
+ hr = E_POINTER;
+ return hr;
+}
+
+BOOL MessengerContact::signinNameEquals(LPDISPATCH contact, BSTR signinName)
+{
+ IMessengerContact *iMessengerContact;
+ HRESULT hr
+ = contact->QueryInterface(
+ IID_IMessengerContact,
+ (PVOID *) &iMessengerContact);
+ BOOL b;
+
+ if (SUCCEEDED(hr))
+ {
+ BSTR contactSigninName;
+
+ hr = iMessengerContact->get_SigninName(&contactSigninName);
+ iMessengerContact->Release();
+ if (SUCCEEDED(hr))
+ {
+ b
+ = (VARCMP_EQ
+ == ::VarBstrCmp(contactSigninName, signinName, 0, 0));
+ ::SysFreeString(contactSigninName);
+ }
+ else
+ b = FALSE;
+ }
+ else
+ b = FALSE;
+ return b;
+}
+
+HRESULT MessengerContact::start(JNIEnv *env)
+{
+ LPSTR className = OutOfProcessServer::getClassName("MessengerContact");
+ HRESULT hr;
+
+ if (className)
+ {
+ jclass clazz = env->FindClass(className);
+
+ ::free(className);
+
+ if (clazz)
+ {
+ jmethodID ctorMethodID
+ = env->GetMethodID(clazz, "<init>", "(Ljava/lang/String;)V");
+
+ if (ctorMethodID)
+ {
+ jmethodID getStatusMethodID
+ = env->GetMethodID(clazz, "getStatus", "()I");
+
+ if (getStatusMethodID)
+ {
+ jmethodID isSelfMethodID
+ = env->GetMethodID(clazz, "isSelf", "()Z");
+
+ if (isSelfMethodID)
+ {
+ clazz = (jclass) env->NewGlobalRef(clazz);
+ if (clazz)
+ {
+ _jclass = clazz;
+ _jctorMethodID = ctorMethodID;
+ _jgetStatusMethodID = getStatusMethodID;
+ _jisSelfMethodID = isSelfMethodID;
+ hr = S_OK;
+ }
+ else
+ hr = E_OUTOFMEMORY;
+ }
+ else
+ hr = E_FAIL;
+ }
+ else
+ hr = E_FAIL;
+ }
+ else
+ hr = E_FAIL;
+ }
+ else
+ hr = E_FAIL;
+ }
+ else
+ hr = E_OUTOFMEMORY;
+ return hr;
+}
+
+HRESULT MessengerContact::stop(JNIEnv *env)
+{
+ jclass clazz = _jclass;
+
+ _jclass = NULL;
+ _jctorMethodID = NULL;
+ _jgetStatusMethodID = NULL;
+ _jisSelfMethodID = NULL;
+ if (clazz)
+ env->DeleteGlobalRef(clazz);
+
+ return S_OK;
+}
diff --git a/src/native/windows/msofficecomm/MessengerContact.h b/src/native/windows/msofficecomm/MessengerContact.h
new file mode 100644
index 0000000..3415bde
--- /dev/null
+++ b/src/native/windows/msofficecomm/MessengerContact.h
@@ -0,0 +1,70 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#ifndef _JMSOFFICECOMM_MESSENGERCONTACT_H_
+#define _JMSOFFICECOMM_MESSENGERCONTACT_H_
+
+#include "DispatchImpl.h"
+#include <msgrua.h>
+
+/**
+ * Implements the <tt>IMessengerContact</tt> interface.
+ *
+ * @author Lyubomir Marinov
+ */
+class MessengerContact
+ : public DispatchImpl<IMessengerContactAdvanced, IID_IMessengerContactAdvanced>
+{
+public:
+ static HRESULT start(JNIEnv *env);
+ static HRESULT stop(JNIEnv *env);
+
+ MessengerContact(IMessenger *messenger, LPCOLESTR signinName);
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID, PVOID *);
+
+ // IMessengerContact
+ STDMETHODIMP get_FriendlyName(BSTR *pbstrFriendlyName);
+ STDMETHODIMP get_Status(MISTATUS *pMstate);
+ STDMETHODIMP get_SigninName(BSTR *pbstrSigninName);
+ STDMETHODIMP get_ServiceName(BSTR *pbstrServiceName);
+ STDMETHODIMP get_Blocked(VARIANT_BOOL *pBoolBlock);
+ STDMETHODIMP put_Blocked(VARIANT_BOOL pBoolBlock);
+ STDMETHODIMP get_CanPage(VARIANT_BOOL *pBoolPage);
+ STDMETHODIMP get_PhoneNumber(MPHONE_TYPE PhoneType, BSTR *bstrNumber);
+ STDMETHODIMP get_IsSelf(VARIANT_BOOL *pBoolSelf);
+ STDMETHODIMP get_Property(MCONTACTPROPERTY ePropType, VARIANT *pvPropVal);
+ STDMETHODIMP put_Property(MCONTACTPROPERTY ePropType, VARIANT vPropVal);
+ STDMETHODIMP get_ServiceId(BSTR *pbstrServiceID);
+
+ // IMessengerContactAdvanced
+ STDMETHODIMP get_IsTagged(VARIANT_BOOL *pBoolIsTagged);
+ STDMETHODIMP put_IsTagged(VARIANT_BOOL pBoolIsTagged);
+ STDMETHODIMP get_PresenceProperties(VARIANT *pvPresenceProperties);
+ STDMETHODIMP put_PresenceProperties(VARIANT vPresenceProperties);
+
+ static BOOL signinNameEquals(LPDISPATCH contact, BSTR signinName);
+
+protected:
+ virtual ~MessengerContact();
+
+ IMessenger *_messenger;
+
+private:
+ static jclass _jclass;
+ static jmethodID _jctorMethodID;
+ static jmethodID _jgetStatusMethodID;
+ static jmethodID _jisSelfMethodID;
+
+ HRESULT constructJobject(LPCOLESTR signinName);
+ HRESULT destructJobject();
+
+ jobject _jobject;
+ LPOLESTR _signinName;
+};
+
+#endif /* #ifndef _JMSOFFICECOMM_MESSENGERCONTACT_H_ */
diff --git a/src/native/windows/msofficecomm/MessengerContacts.cxx b/src/native/windows/msofficecomm/MessengerContacts.cxx
new file mode 100644
index 0000000..50544c8
--- /dev/null
+++ b/src/native/windows/msofficecomm/MessengerContacts.cxx
@@ -0,0 +1,116 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#include "MessengerContacts.h"
+
+#include "MessengerContact.h"
+
+EXTERN_C const GUID DECLSPEC_SELECTANY IID_IMessengerContacts
+ = { 0xE7479A0D, 0xBB19, 0x44a5, { 0x96, 0x8F, 0x6F, 0x41, 0xD9, 0x3E, 0xE0, 0xBC } };
+
+class SelfMessengerContact
+ : public MessengerContact
+{
+public:
+ SelfMessengerContact(IMessenger *messenger)
+ : MessengerContact(messenger, NULL) {}
+
+ // IMessengerContact
+ STDMETHODIMP get_IsSelf(VARIANT_BOOL *pBoolSelf)
+ {
+ HRESULT hr;
+
+ if (pBoolSelf)
+ {
+ *pBoolSelf = VARIANT_TRUE;
+ hr = S_OK;
+ }
+ else
+ hr = RPC_X_NULL_REF_POINTER;
+ return hr;
+ }
+
+ STDMETHODIMP get_SigninName(BSTR *pbstrSigninName)
+ { return _messenger->get_MySigninName(pbstrSigninName); }
+
+ STDMETHODIMP get_Status(MISTATUS *pMstate)
+ {
+ HRESULT hr;
+
+ if (pMstate)
+ {
+ *pMstate = MISTATUS_ONLINE;
+ hr = S_OK;
+ }
+ else
+ hr = RPC_X_NULL_REF_POINTER;
+ return hr;
+ }
+
+protected:
+ virtual ~SelfMessengerContact() {}
+};
+
+MessengerContacts::MessengerContacts(IMessenger *messenger)
+ : _messenger(messenger),
+ _self(NULL)
+{
+ _messenger->AddRef();
+}
+
+MessengerContacts::~MessengerContacts()
+{
+ _messenger->Release();
+ if (_self)
+ _self->Release();
+}
+
+STDMETHODIMP MessengerContacts::get__NewEnum(IUnknown **ppUnknown)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP MessengerContacts::get_Count(LONG *pcContacts)
+{
+ HRESULT hr;
+
+ if (pcContacts)
+ {
+ *pcContacts = 1;
+ hr = S_OK;
+ }
+ else
+ hr = RPC_X_NULL_REF_POINTER;
+ return hr;
+}
+
+STDMETHODIMP MessengerContacts::getSelf(IDispatch **ppMContact)
+ STDMETHODIMP_RESOLVE_WEAKREFERENCE_OR_NEW(ppMContact,_self,SelfMessengerContact,_messenger)
+
+STDMETHODIMP MessengerContacts::Item(LONG Index, IDispatch **ppMContact)
+{
+ HRESULT hr;
+
+ if (ppMContact)
+ {
+ if (0 > Index)
+ {
+ *ppMContact = NULL;
+ hr = E_INVALIDARG;
+ }
+ else if (0 == Index)
+ hr = getSelf(ppMContact);
+ else
+ {
+ *ppMContact = NULL;
+ hr = E_FAIL;
+ }
+ }
+ else
+ hr = RPC_X_NULL_REF_POINTER;
+ return hr;
+}
+
+STDMETHODIMP MessengerContacts::Remove(IDispatch *pMContact)
+ STDMETHODIMP_E_NOTIMPL_STUB
diff --git a/src/native/windows/msofficecomm/MessengerContacts.h b/src/native/windows/msofficecomm/MessengerContacts.h
new file mode 100644
index 0000000..8e81dc2
--- /dev/null
+++ b/src/native/windows/msofficecomm/MessengerContacts.h
@@ -0,0 +1,40 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#ifndef _JMSOFFICECOMM_MESSENGERCONTACTS_H_
+#define _JMSOFFICECOMM_MESSENGERCONTACTS_H_
+
+#include "DispatchImpl.h"
+#include <msgrua.h>
+
+/**
+ * Implements the <tt>IMessengerContacts</tt> interface.
+ *
+ * @author Lyubomir Marinov
+ */
+class MessengerContacts
+ : public DispatchImpl<IMessengerContacts, IID_IMessengerContacts>
+{
+public:
+ MessengerContacts(IMessenger *messenger);
+
+ // IMessengerContacts
+ STDMETHODIMP get_Count(LONG *pcContacts);
+ STDMETHODIMP Item(LONG Index, IDispatch **ppMContact);
+ STDMETHODIMP Remove(IDispatch *pMContact);
+ STDMETHODIMP get__NewEnum(IUnknown **ppUnknown);
+
+protected:
+ virtual ~MessengerContacts();
+
+private:
+ STDMETHODIMP getSelf(IDispatch **ppMContact);
+
+ IMessenger *_messenger;
+ IWeakReference *_self;
+};
+
+#endif /* #ifndef _JMSOFFICECOMM_MESSENGERCONTACTS_H_ */
diff --git a/src/native/windows/msofficecomm/MessengerService.cxx b/src/native/windows/msofficecomm/MessengerService.cxx
new file mode 100644
index 0000000..b02f62e
--- /dev/null
+++ b/src/native/windows/msofficecomm/MessengerService.cxx
@@ -0,0 +1,52 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#include "MessengerService.h"
+
+EXTERN_C const GUID DECLSPEC_SELECTANY IID_IMessengerService
+ = { 0x2E50547C, 0xA8AA, 0x4f60, { 0xB5, 0x7E, 0x1F, 0x41, 0x47, 0x11, 0x00, 0x7B } };
+
+MessengerService::MessengerService(IMessenger *messenger)
+ : _messenger(messenger)
+{
+ _messenger->AddRef();
+}
+
+MessengerService::~MessengerService()
+{
+ _messenger->Release();
+}
+
+STDMETHODIMP MessengerService::get_MyFriendlyName(BSTR *pbstrName)
+{
+ return _messenger->get_MyFriendlyName(pbstrName);
+}
+
+STDMETHODIMP MessengerService::get_MySigninName(BSTR *pbstrName)
+{
+ return _messenger->get_MySigninName(pbstrName);
+}
+
+STDMETHODIMP MessengerService::get_MyStatus(MISTATUS *pmiStatus)
+{
+ return _messenger->get_MyStatus(pmiStatus);
+}
+
+STDMETHODIMP MessengerService::get_Property(MSERVICEPROPERTY ePropType, VARIANT *pvPropVal)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP MessengerService::get_ServiceID(BSTR *pbstrID)
+{
+ return _messenger->get_MyServiceId(pbstrID);
+}
+
+STDMETHODIMP MessengerService::get_ServiceName(BSTR *pbstrServiceName)
+{
+ return _messenger->get_MyServiceName(pbstrServiceName);
+}
+
+STDMETHODIMP MessengerService::put_Property(MSERVICEPROPERTY ePropType, VARIANT vPropVal)
+ STDMETHODIMP_E_NOTIMPL_STUB
diff --git a/src/native/windows/msofficecomm/MessengerService.h b/src/native/windows/msofficecomm/MessengerService.h
new file mode 100644
index 0000000..4747fca
--- /dev/null
+++ b/src/native/windows/msofficecomm/MessengerService.h
@@ -0,0 +1,35 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#ifndef _JMSOFFICECOMM_MESSENGERSERVICE_H_
+#define _JMSOFFICECOMM_MESSENGERSERVICE_H_
+
+#include "DispatchImpl.h"
+#include <msgrua.h>
+
+class MessengerService
+ : public DispatchImpl<IMessengerService, IID_IMessengerService>
+{
+public:
+ MessengerService(IMessenger *messenger);
+
+ // IMessengerService
+ STDMETHODIMP get_ServiceName(BSTR *pbstrServiceName);
+ STDMETHODIMP get_ServiceID(BSTR *pbstrID);
+ STDMETHODIMP get_MyFriendlyName(BSTR *pbstrName);
+ STDMETHODIMP get_MyStatus(MISTATUS *pmiStatus);
+ STDMETHODIMP get_MySigninName(BSTR *pbstrName);
+ STDMETHODIMP get_Property(MSERVICEPROPERTY ePropType, VARIANT *pvPropVal);
+ STDMETHODIMP put_Property(MSERVICEPROPERTY ePropType, VARIANT vPropVal);
+
+protected:
+ virtual ~MessengerService();
+
+private:
+ IMessenger *_messenger;
+};
+
+#endif /* #ifndef _JMSOFFICECOMM_MESSENGERSERVICE_H_ */
diff --git a/src/native/windows/msofficecomm/MessengerServices.cxx b/src/native/windows/msofficecomm/MessengerServices.cxx
new file mode 100644
index 0000000..ffd879c
--- /dev/null
+++ b/src/native/windows/msofficecomm/MessengerServices.cxx
@@ -0,0 +1,70 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#include "MessengerServices.h"
+
+#include "MessengerService.h"
+
+EXTERN_C const GUID DECLSPEC_SELECTANY IID_IMessengerServices
+ = { 0x2E50547B, 0xA8AA, 0x4f60, { 0xB5, 0x7E, 0x1F, 0x41, 0x47, 0x11, 0x00, 0x7B } };
+
+MessengerServices::MessengerServices(IMessenger *messenger)
+ : _messenger(messenger),
+ _primaryService(NULL)
+{
+ _messenger->AddRef();
+}
+
+MessengerServices::~MessengerServices()
+{
+ _messenger->Release();
+ if (_primaryService)
+ _primaryService->Release();
+}
+
+STDMETHODIMP MessengerServices::get__NewEnum(IUnknown **ppUnknown)
+ STDMETHODIMP_E_NOTIMPL_STUB
+
+STDMETHODIMP MessengerServices::get_Count(long *pcServices)
+{
+ HRESULT hr;
+
+ if (pcServices)
+ {
+ *pcServices = 1;
+ hr = S_OK;
+ }
+ else
+ hr = RPC_X_NULL_REF_POINTER;
+ return hr;
+}
+
+STDMETHODIMP MessengerServices::get_PrimaryService(IDispatch **ppService)
+ STDMETHODIMP_RESOLVE_WEAKREFERENCE_OR_NEW(ppService,_primaryService,MessengerService,_messenger)
+
+STDMETHODIMP MessengerServices::Item(long Index, IDispatch **ppService)
+{
+ HRESULT hr;
+
+ if (ppService)
+ {
+ if (0 > Index)
+ {
+ *ppService = NULL;
+ hr = E_INVALIDARG;
+ }
+ else if (0 == Index)
+ hr = get_PrimaryService(ppService);
+ else
+ {
+ *ppService = NULL;
+ hr = E_FAIL;
+ }
+ }
+ else
+ hr = RPC_X_NULL_REF_POINTER;
+ return hr;
+}
diff --git a/src/native/windows/msofficecomm/MessengerServices.h b/src/native/windows/msofficecomm/MessengerServices.h
new file mode 100644
index 0000000..3422e0e
--- /dev/null
+++ b/src/native/windows/msofficecomm/MessengerServices.h
@@ -0,0 +1,33 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#ifndef _JMSOFFICECOMM_MESSENGERSERVICES_H_
+#define _JMSOFFICECOMM_MESSENGERSERVICES_H_
+
+#include "DispatchImpl.h"
+#include <msgrua.h>
+
+class MessengerServices
+ : public DispatchImpl<IMessengerServices, IID_IMessengerServices>
+{
+public:
+ MessengerServices(IMessenger *messenger);
+
+ // IMessengerServices
+ STDMETHODIMP get_PrimaryService(IDispatch **ppService);
+ STDMETHODIMP get_Count(long *pcServices);
+ STDMETHODIMP Item(long Index, IDispatch **ppService);
+ STDMETHODIMP get__NewEnum(IUnknown **ppUnknown);
+
+protected:
+ virtual ~MessengerServices();
+
+private:
+ IMessenger *_messenger;
+ IWeakReference *_primaryService;
+};
+
+#endif /* _JMSOFFICECOMM_MESSENGERSERVICES_H_ */
diff --git a/src/native/windows/msofficecomm/OutOfProcessServer.cxx b/src/native/windows/msofficecomm/OutOfProcessServer.cxx
new file mode 100644
index 0000000..1ca3974
--- /dev/null
+++ b/src/native/windows/msofficecomm/OutOfProcessServer.cxx
@@ -0,0 +1,628 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#include "OutOfProcessServer.h"
+
+#include "Log.h"
+#include "Messenger.h"
+#include "MessengerClassFactory.h"
+#include "MessengerContact.h"
+#include "net_java_sip_communicator_plugin_msofficecomm_OutOfProcessServer.h"
+#include "process.h"
+
+EXTERN_C const GUID DECLSPEC_SELECTANY LIBID_CommunicatorUA
+ = { 0x2B317E1D, 0x50E5, 0x4f5e, { 0xA3, 0xA4, 0xFB, 0x85, 0x20, 0x6E, 0xDA, 0x48 } };
+
+JNIEXPORT jint JNICALL
+Java_net_java_sip_communicator_plugin_msofficecomm_OutOfProcessServer_start
+ (JNIEnv *env, jclass clazz)
+{
+ LPSTR functionName = ::strdup(__FUNCTION__);
+ LPSTR packageName;
+
+ if (functionName)
+ {
+ packageName = functionName + 5 /* Java_ */;
+
+ size_t packageNameLength
+ = ::strlen(packageName) - 24 /* OutOfProcessServer_start */;
+
+ packageName[packageNameLength] = '\0';
+
+ char ch;
+ LPSTR str = packageName;
+
+ while ((ch = *str))
+ {
+ if ('_' == ch)
+ *str = '/';
+ str++;
+ }
+ }
+ else
+ packageName = NULL;
+
+ jint ret = OutOfProcessServer::start(env, clazz, packageName);
+
+ if (functionName)
+ ::free(functionName);
+
+ return ret;
+}
+
+JNIEXPORT jint JNICALL
+Java_net_java_sip_communicator_plugin_msofficecomm_OutOfProcessServer_stop
+ (JNIEnv *env, jclass clazz)
+{
+ return OutOfProcessServer::stop(env, clazz);
+}
+
+JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
+{
+ return OutOfProcessServer::JNI_OnLoad(vm);
+}
+
+JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
+{
+ OutOfProcessServer::JNI_OnUnload(vm);
+}
+
+CRITICAL_SECTION OutOfProcessServer::_criticalSection;
+ITypeLib * OutOfProcessServer::_iTypeLib;
+ClassFactory * OutOfProcessServer::_messengerClassFactory = NULL;
+LPSTR OutOfProcessServer::_packageName;
+HANDLE OutOfProcessServer::_threadHandle;
+DWORD OutOfProcessServer::_threadId;
+JavaVM * OutOfProcessServer::_vm = NULL;
+
+LPSTR OutOfProcessServer::getClassName(LPCSTR className)
+{
+ size_t packageNameLength = _packageName ? ::strlen(_packageName) : 0;
+ size_t classNameLength = ::strlen(className);
+ LPSTR ret = (LPSTR) ::malloc(packageNameLength + classNameLength + 1);
+
+ if (ret)
+ {
+ LPSTR str = ret;
+
+ if (packageNameLength)
+ {
+ ::memcpy(str, _packageName, packageNameLength);
+ str += packageNameLength;
+ }
+ if (classNameLength)
+ {
+ ::memcpy(str, className, classNameLength);
+ str += classNameLength;
+ }
+ *str = '\0';
+ }
+ return ret;
+}
+
+BOOL OutOfProcessServer::isMicrosoftOfficeOutlookCallIntegrationIMApplication()
+{
+ TCHAR path[MAX_PATH + 1];
+ DWORD pathCapacity = sizeof(path) / sizeof(TCHAR);
+ DWORD pathLength = ::GetModuleFileName(NULL, path, pathCapacity);
+ BOOL b;
+
+ if (pathLength && (pathLength < pathCapacity))
+ {
+ LPTSTR fileName = NULL;
+
+ for (LPTSTR str = path + (pathLength - 1); str != path; str--)
+ {
+ TCHAR ch = *str;
+
+ if (('\\' == ch) || ('/' == ch))
+ {
+ fileName = str + 1;
+ break;
+ }
+ }
+ if (fileName && *fileName)
+ {
+ DWORD dataSize = (pathLength + 2) * sizeof(TCHAR);
+ LPBYTE data = (LPBYTE) ::malloc(dataSize);
+
+ if (data)
+ {
+ SYSTEM_INFO systemInfo;
+ REGSAM alternatives86[] = { 0 };
+ REGSAM alternatives64[] = { KEY_WOW64_32KEY, KEY_WOW64_64KEY };
+ REGSAM *alternatives;
+ size_t alternativeCount;
+
+ ::GetNativeSystemInfo(&systemInfo);
+ if (PROCESSOR_ARCHITECTURE_INTEL
+ == systemInfo.wProcessorArchitecture)
+ {
+ alternatives = alternatives86;
+ alternativeCount = sizeof(alternatives86) / sizeof(REGSAM);
+ }
+ else
+ {
+ alternatives = alternatives64;
+ alternativeCount = sizeof(alternatives64) / sizeof(REGSAM);
+ }
+
+ LPCTSTR key
+ = _T("SOFTWARE\\Microsoft\\Office\\Outlook\\Call Integration");
+ LPCTSTR valueName = _T("IMApplication");
+ size_t fileNameLength = ::_tcslen(fileName);
+
+ b = FALSE;
+ for (size_t i = 0; i < alternativeCount; i++)
+ {
+ HKEY hkey;
+
+ if (::RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ key,
+ 0,
+ KEY_QUERY_VALUE | alternatives[i],
+ &hkey)
+ == ERROR_SUCCESS)
+ {
+ DWORD type;
+
+ dataSize = (pathLength + 1) * sizeof(TCHAR);
+ ::ZeroMemory(data, dataSize + sizeof(TCHAR));
+ if ((::RegQueryValueEx(
+ hkey,
+ valueName,
+ NULL,
+ &type,
+ data,
+ &dataSize)
+ == ERROR_SUCCESS)
+ && (REG_SZ == type))
+ {
+ b
+ = (::_tcsnicmp(
+ fileName,
+ (LPCTSTR) data,
+ fileNameLength)
+ == 0);
+ }
+ ::RegCloseKey(hkey);
+
+ if (b)
+ break;
+ }
+ }
+ ::free(data);
+ }
+ else
+ b = FALSE;
+ }
+ else
+ b = FALSE;
+ }
+ else
+ b = FALSE;
+ return b;
+}
+
+jint OutOfProcessServer::JNI_OnLoad(JavaVM *vm)
+{
+ jint version;
+
+ if (isMicrosoftOfficeOutlookCallIntegrationIMApplication())
+ {
+ ::InitializeCriticalSection(&_criticalSection);
+ _vm = vm;
+ version = JNI_VERSION_1_4;
+ }
+ else
+ version = JNI_ERR;
+ return version;
+}
+
+HRESULT OutOfProcessServer::loadRegTypeLib()
+{
+ ITypeLib *iTypeLib;
+ HRESULT hr = ::LoadRegTypeLib(LIBID_CommunicatorUA, 1, 0, 0, &iTypeLib);
+
+ if (SUCCEEDED(hr))
+ _iTypeLib = iTypeLib;
+ else
+ {
+ HMODULE module;
+
+ if (::GetModuleHandleEx(
+ GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
+ | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+ (LPCTSTR) (OutOfProcessServer::loadRegTypeLib),
+ &module))
+ {
+ WCHAR path[MAX_PATH + 1];
+ DWORD pathCapacity = sizeof(path) / sizeof(WCHAR);
+ DWORD pathLength = ::GetModuleFileNameW(module, path, pathCapacity);
+
+ if (pathLength && (pathLength < pathCapacity))
+ {
+ hr = ::LoadTypeLibEx(path, REGKIND_NONE, &iTypeLib);
+ if (SUCCEEDED(hr))
+ {
+ HMODULE oleaut32 = ::GetModuleHandle(_T("oleaut32.dll"));
+
+ if (oleaut32)
+ {
+ typedef HRESULT (*RTLFU)(LPTYPELIB,LPOLESTR,LPOLESTR);
+ RTLFU registerTypeLibForUser
+ = (RTLFU)
+ ::GetProcAddress(
+ oleaut32,
+ "RegisterTypeLibForUser");
+
+ if (registerTypeLibForUser)
+ {
+ hr = registerTypeLibForUser(iTypeLib, path, NULL);
+ if (SUCCEEDED(hr))
+ _iTypeLib = iTypeLib;
+ }
+ else
+ hr = E_UNEXPECTED;
+ }
+ else
+ hr = E_UNEXPECTED;
+ }
+ }
+ }
+ if (_iTypeLib != iTypeLib)
+ iTypeLib->Release();
+ }
+ return hr;
+}
+
+DWORD
+OutOfProcessServer::regCreateKeyAndSetValue
+ (LPCTSTR key, LPCTSTR valueName, DWORD data)
+{
+ SYSTEM_INFO systemInfo;
+ REGSAM alternatives86[] = { 0 };
+ REGSAM alternatives64[] = { KEY_WOW64_32KEY, KEY_WOW64_64KEY };
+ REGSAM *alternatives;
+ size_t alternativeCount;
+
+ ::GetNativeSystemInfo(&systemInfo);
+ if (PROCESSOR_ARCHITECTURE_INTEL == systemInfo.wProcessorArchitecture)
+ {
+ alternatives = alternatives86;
+ alternativeCount = sizeof(alternatives86) / sizeof(REGSAM);
+ }
+ else
+ {
+ alternatives = alternatives64;
+ alternativeCount = sizeof(alternatives64) / sizeof(REGSAM);
+ }
+
+ DWORD lastError;
+
+ for (size_t i = 0; i < alternativeCount; i++)
+ {
+ HKEY hkey;
+
+ lastError
+ = ::RegCreateKeyEx(
+ HKEY_CURRENT_USER,
+ key,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ KEY_SET_VALUE | alternatives[i],
+ NULL,
+ &hkey,
+ NULL);
+ if (ERROR_SUCCESS == lastError)
+ {
+ lastError
+ = ::RegSetValueEx(
+ hkey,
+ valueName,
+ 0,
+ REG_DWORD,
+ (const BYTE *) &data,
+ sizeof(data));
+ ::RegCloseKey(hkey);
+ }
+ if (ERROR_SUCCESS != lastError)
+ break;
+ }
+ return lastError;
+}
+
+HRESULT OutOfProcessServer::registerClassObjects()
+{
+ ClassFactory *classObject = new MessengerClassFactory();
+ HRESULT hresult = classObject->registerClassObject();
+
+ if (SUCCEEDED(hresult))
+ _messengerClassFactory = classObject;
+ else
+ classObject->Release();
+
+ if (SUCCEEDED(hresult))
+ {
+ hresult = ::CoResumeClassObjects();
+ if (FAILED(hresult))
+ revokeClassObjects();
+ }
+
+ return hresult;
+}
+
+ULONG OutOfProcessServer::releaseTypeLib()
+{
+ // TODO UnRegisterTypeLibForUser
+ return _iTypeLib->Release();
+}
+
+HRESULT OutOfProcessServer::revokeClassObjects()
+{
+ HRESULT ret = ::CoSuspendClassObjects();
+
+ if (SUCCEEDED(ret))
+ {
+ ClassFactory *classObject = _messengerClassFactory;
+
+ if (classObject)
+ {
+ _messengerClassFactory = NULL;
+
+ HRESULT hr = classObject->revokeClassObject();
+
+ classObject->Release();
+ if (FAILED(hr))
+ ret = hr;
+ }
+ }
+ return ret;
+}
+
+unsigned __stdcall OutOfProcessServer::run(void *)
+{
+ Log::open();
+
+ HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+ unsigned ret = 0;
+
+ if (SUCCEEDED(hr))
+ {
+ hr = loadRegTypeLib();
+ if (SUCCEEDED(hr))
+ {
+ if (ERROR_SUCCESS == setIMProvidersCommunicatorUpAndRunning(1))
+ {
+ MSG msg;
+
+ /*
+ * Create the message queue of this thread before any other part
+ * of the code (e.g. the release method) has a chance to invoke
+ * PostThreadMessage.
+ */
+ ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
+
+ hr = registerClassObjects();
+ if (SUCCEEDED(hr))
+ {
+ if (ERROR_SUCCESS
+ == setIMProvidersCommunicatorUpAndRunning(2))
+ {
+ HANDLE threadHandle = _threadHandle;
+ BOOL logMsgWaitForMultipleObjectsExFailed = TRUE;
+ BOOL quit = FALSE;
+
+ do
+ {
+ /*
+ * Enable the use of the QueueUserAPC function by
+ * entering an altertable state.
+ */
+ if ((WAIT_FAILED
+ == ::MsgWaitForMultipleObjectsEx(
+ 1,
+ &threadHandle,
+ INFINITE,
+ QS_ALLINPUT | QS_ALLPOSTMESSAGE,
+ MWMO_ALERTABLE
+ | MWMO_INPUTAVAILABLE))
+ && logMsgWaitForMultipleObjectsExFailed)
+ {
+ /*
+ * Logging the possible failures of the calls to
+ * MsgWaitForMultipleObjectsEx multiple times is
+ * unlikely to be useful. Besides, the call in
+ * question is performed inside the message loop
+ * and the logging will be an unnecessary
+ * performance penalty.
+ */
+ logMsgWaitForMultipleObjectsExFailed = FALSE;
+ Log::d(
+ _T("OutOfProcessServer::run:")
+ _T(" MsgWaitForMultipleObjectsEx=WAIT_FAILED;")
+ _T("\n"));
+ }
+ while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ if (WM_QUIT == msg.message)
+ {
+ quit = TRUE;
+ ret = msg.wParam;
+ break;
+ }
+ else if (msg.hwnd)
+ {
+ ::TranslateMessage(&msg);
+ ::DispatchMessage(&msg);
+ }
+ }
+ }
+ while (!quit);
+ }
+
+ revokeClassObjects();
+ }
+ }
+
+ /*
+ * Even if setIMProvidersCommunicatorUpAndRunning(DWORD) failed, it
+ * may have successfully set some of the multiple related registry
+ * keys.
+ */
+ setIMProvidersCommunicatorUpAndRunning(0);
+
+ releaseTypeLib();
+ }
+
+ ::CoUninitialize();
+ }
+
+ Log::close();
+ return ret;
+}
+
+DWORD OutOfProcessServer::setIMProvidersCommunicatorUpAndRunning(DWORD dw)
+{
+ DWORD lastError;
+
+ if (dw)
+ {
+ lastError
+ = regCreateKeyAndSetValue(
+ _T("Software\\Microsoft\\Office\\12.0\\Common\\PersonaMenu"),
+ _T("RTCApplication"),
+ 3);
+ }
+ else
+ lastError = ERROR_SUCCESS;
+ if (ERROR_SUCCESS == lastError)
+ {
+ lastError
+ = regCreateKeyAndSetValue(
+ _T("Software\\IM Providers\\Communicator"),
+ _T("UpAndRunning"),
+ dw);
+ }
+ return lastError;
+}
+
+HRESULT OutOfProcessServer::start(JNIEnv *env, jclass clazz, LPCSTR packageName)
+{
+ HRESULT hr;
+
+ if (packageName)
+ hr = ((_packageName = ::strdup(packageName))) ? S_OK : E_OUTOFMEMORY;
+ else
+ {
+ _packageName = NULL;
+ hr = S_OK;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = Messenger::start(env);
+ if (SUCCEEDED(hr))
+ {
+ hr = MessengerContact::start(env);
+ if (SUCCEEDED(hr))
+ {
+ unsigned threadId;
+ HANDLE threadHandle
+ = (HANDLE)
+ ::_beginthreadex(
+ NULL,
+ 0,
+ OutOfProcessServer::run,
+ NULL,
+ CREATE_SUSPENDED,
+ &threadId);
+
+ if (threadHandle)
+ {
+ enterCriticalSection();
+
+ _threadHandle = threadHandle;
+ _threadId = (DWORD) threadId;
+ if (((DWORD) -1) == ::ResumeThread(threadHandle))
+ {
+ DWORD lastError = ::GetLastError();
+
+ _threadHandle = NULL;
+
+ ::CloseHandle(threadHandle);
+ hr = HRESULT_FROM_WIN32(lastError);
+ }
+
+ leaveCriticalSection();
+ }
+ else
+ hr = E_UNEXPECTED;
+
+ if (FAILED(hr))
+ MessengerContact::stop(env);
+ }
+
+ if (FAILED(hr))
+ Messenger::stop(env);
+ }
+
+ if (FAILED(hr) && _packageName)
+ {
+ ::free(_packageName);
+ _packageName = NULL;
+ }
+ }
+
+ return hr;
+}
+
+HRESULT OutOfProcessServer::stop(JNIEnv *env, jclass clazz)
+{
+ DWORD lastError;
+
+ if (::PostThreadMessage(_threadId, WM_QUIT, 0, 0))
+ {
+ do
+ {
+ DWORD exitCode;
+
+ if (::GetExitCodeThread(_threadHandle, &exitCode))
+ {
+ if (STILL_ACTIVE == exitCode)
+ {
+ if (WAIT_FAILED
+ == ::WaitForSingleObject(_threadHandle, INFINITE))
+ break;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+ while (1);
+
+ if (::CloseHandle(_threadHandle))
+ lastError = 0;
+ else
+ lastError = ::GetLastError();
+
+ MessengerContact::stop(env);
+ Messenger::stop(env);
+
+ if (_packageName)
+ {
+ ::free(_packageName);
+ _packageName = NULL;
+ }
+ }
+ else
+ lastError = ::GetLastError();
+ return lastError ? HRESULT_FROM_WIN32(lastError) : S_OK;
+}
diff --git a/src/native/windows/msofficecomm/OutOfProcessServer.h b/src/native/windows/msofficecomm/OutOfProcessServer.h
new file mode 100644
index 0000000..b069a72
--- /dev/null
+++ b/src/native/windows/msofficecomm/OutOfProcessServer.h
@@ -0,0 +1,64 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#ifndef _JMSOFFICECOMM_OUTOFPROCESSSERVER_H_
+#define _JMSOFFICECOMM_OUTOFPROCESSSERVER_H_
+
+#include <objbase.h>
+#include <jni.h>
+#include <windows.h>
+
+class ClassFactory;
+
+/**
+ * Implements the jmsoutlookcomm application which is an out-of-process local COM
+ * server.
+ *
+ * @author Lyubomir Marinov
+ */
+class OutOfProcessServer
+{
+public:
+ static ULONG addRef() { /* TODO Auto-generated method stub */ return 0; }
+ static void enterCriticalSection()
+ { ::EnterCriticalSection(&_criticalSection); }
+ static LPSTR getClassName(LPCSTR className);
+ static JavaVM *getJavaVM() { return _vm; }
+ static HANDLE getThreadHandle() { return _threadHandle; }
+ static DWORD getThreadId() { return _threadId; }
+ static HRESULT getTypeInfo(UINT index, ITypeInfo **ppTInfo)
+ { return _iTypeLib->GetTypeInfo(index, ppTInfo); }
+ static UINT getTypeInfoCount() { return _iTypeLib->GetTypeInfoCount(); }
+ static HRESULT getTypeInfoOfGuid(REFGUID guid, ITypeInfo **ppTInfo)
+ { return _iTypeLib->GetTypeInfoOfGuid(guid, ppTInfo); }
+ static jint JNI_OnLoad(JavaVM *vm);
+ static void JNI_OnUnload(JavaVM *vm) { _vm = NULL; }
+ static void leaveCriticalSection()
+ { ::LeaveCriticalSection(&_criticalSection); }
+ static ULONG release() { /* TODO Auto-generated method stub */ return 0; }
+ static HRESULT start(JNIEnv *env, jclass clazz, LPCSTR packageName);
+ static HRESULT stop(JNIEnv *env, jclass clazz);
+
+private:
+ static BOOL isMicrosoftOfficeOutlookCallIntegrationIMApplication();
+ static HRESULT loadRegTypeLib();
+ static DWORD regCreateKeyAndSetValue(LPCTSTR key, LPCTSTR valueName, DWORD data);
+ static HRESULT registerClassObjects();
+ static ULONG releaseTypeLib();
+ static HRESULT revokeClassObjects();
+ static unsigned __stdcall run(void *);
+ static DWORD setIMProvidersCommunicatorUpAndRunning(DWORD dw);
+
+ static CRITICAL_SECTION _criticalSection;
+ static ITypeLib * _iTypeLib;
+ static ClassFactory * _messengerClassFactory;
+ static LPSTR _packageName;
+ static HANDLE _threadHandle;
+ static DWORD _threadId;
+ static JavaVM * _vm;
+};
+
+#endif /* #ifndef _JMSOFFICECOMM_OUTOFPROCESSSERVER_H_ */
diff --git a/src/native/windows/msofficecomm/Resources.h b/src/native/windows/msofficecomm/Resources.h
new file mode 100644
index 0000000..d8f95d8
--- /dev/null
+++ b/src/native/windows/msofficecomm/Resources.h
@@ -0,0 +1,6 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
diff --git a/src/native/windows/msofficecomm/Resources.rc b/src/native/windows/msofficecomm/Resources.rc
new file mode 100644
index 0000000..dbf4b62
--- /dev/null
+++ b/src/native/windows/msofficecomm/Resources.rc
@@ -0,0 +1,9 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#include "Resources.h"
+
+1 TYPELIB msgrua.tlb
diff --git a/src/native/windows/msofficecomm/StringUtils.cxx b/src/native/windows/msofficecomm/StringUtils.cxx
new file mode 100644
index 0000000..71beed0
--- /dev/null
+++ b/src/native/windows/msofficecomm/StringUtils.cxx
@@ -0,0 +1,54 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#include "StringUtils.h"
+
+LPWSTR StringUtils::MultiByteToWideChar(LPCSTR str)
+{
+ int wsize = ::MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
+ LPWSTR wstr;
+
+ if (wsize)
+ {
+ wstr = (LPWSTR) ::malloc(wsize * sizeof(WCHAR));
+ if (str && !::MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, wsize))
+ {
+ ::free(wstr);
+ wstr = NULL;
+ }
+ }
+ else
+ wstr = NULL;
+ return wstr;
+}
+
+LPSTR StringUtils::WideCharToMultiByte(LPCWSTR wstr)
+{
+ int size = ::WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
+ LPSTR str;
+
+ if (size)
+ {
+ str = (LPSTR) ::malloc(size);
+ if (str
+ && !::WideCharToMultiByte(
+ CP_ACP,
+ 0,
+ wstr,
+ -1,
+ str,
+ size,
+ NULL,
+ NULL))
+ {
+ ::free(str);
+ str = NULL;
+ }
+ }
+ else
+ str = NULL;
+ return str;
+}
diff --git a/src/native/windows/msofficecomm/StringUtils.h b/src/native/windows/msofficecomm/StringUtils.h
new file mode 100644
index 0000000..1c0eb18
--- /dev/null
+++ b/src/native/windows/msofficecomm/StringUtils.h
@@ -0,0 +1,20 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#ifndef _JMSOFFICECOMM_STRINGUTILS_H_
+#define _JMSOFFICECOMM_STRINGUTILS_H_
+
+#include <tchar.h>
+#include <windows.h>
+
+class StringUtils
+{
+public:
+ static LPWSTR MultiByteToWideChar(LPCSTR str);
+ static LPSTR WideCharToMultiByte(LPCWSTR wstr);
+};
+
+#endif /* #ifndef _JMSOFFICECOMM_STRINGUTILS_H_ */
diff --git a/src/native/windows/msofficecomm/UnknownImpl.h b/src/native/windows/msofficecomm/UnknownImpl.h
new file mode 100644
index 0000000..dcd6607
--- /dev/null
+++ b/src/native/windows/msofficecomm/UnknownImpl.h
@@ -0,0 +1,129 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#ifndef _JMSOFFICECOMM_UNKNOWNIMPL_H_
+#define _JMSOFFICECOMM_UNKNOWNIMPL_H_
+
+#include "Log.h"
+#include "OutOfProcessServer.h"
+#include "StringUtils.h"
+#include "WeakReferenceSource.h"
+
+#define STDMETHODIMP_E_NOTIMPL_STUB \
+ { \
+ Log::d(_T("%s\n"), __PRETTY_FUNCTION__); \
+ return E_NOTIMPL; \
+ }
+
+/**
+ * Represents a base implementation of the <tt>IUnknown</tt> interface.
+ *
+ * @author Lyubomir Marinov
+ */
+template <class T, REFIID IID_T>
+class UnknownImpl
+ : public T
+{
+public:
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID iid, PVOID *obj)
+ {
+ HRESULT hr;
+
+ if (!obj)
+ hr = E_POINTER;
+ else if (IID_IUnknown == iid)
+ {
+ AddRef();
+ *obj = static_cast<LPUNKNOWN>(this);
+ hr = S_OK;
+ }
+ else if (IID_T == iid)
+ {
+ AddRef();
+ *obj = static_cast<T *>(this);
+ hr = S_OK;
+ }
+ else if (IID_IWeakReferenceSource == iid)
+ {
+ if (!_weakReferenceSource)
+ _weakReferenceSource = new WeakReferenceSource(this);
+ _weakReferenceSource->AddRef();
+ *obj = static_cast<IWeakReferenceSource *>(_weakReferenceSource);
+ hr = S_OK;
+ }
+ else
+ {
+ *obj = NULL;
+ hr = E_NOINTERFACE;
+ }
+
+ if (FAILED(hr))
+ {
+ LPOLESTR olestr;
+
+ if (SUCCEEDED(::StringFromIID(iid, &olestr)))
+ {
+ LPTSTR tstr
+#ifdef _UNICODE
+ = olestr;
+#else
+ = StringUtils::WideCharToMultiByte(olestr);
+#endif /* #ifdef _UNICODE */
+
+ if (tstr)
+ {
+ Log::d(
+ _T("UnknownImpl::QueryInterface: this=%p; iid=%s;\n"),
+ (PVOID) this,
+ tstr);
+ if (tstr != olestr)
+ ::free(tstr);
+ }
+ ::CoTaskMemFree(olestr);
+ }
+ }
+
+ return hr;
+ }
+
+ STDMETHODIMP_(ULONG) AddRef() { return ++_refCount; }
+
+ STDMETHODIMP_(ULONG) Release()
+ {
+ ULONG refCount = --_refCount;
+
+ if (!refCount)
+ delete this;
+ Log::d(
+ _T("UnknownImpl::Release: this=%p; refCount=%lu;\n"),
+ (PVOID) this,
+ refCount);
+ return refCount;
+ }
+
+protected:
+ UnknownImpl()
+ : _refCount(1),
+ _weakReferenceSource(NULL)
+ {
+ OutOfProcessServer::addRef();
+ }
+
+ virtual ~UnknownImpl()
+ {
+ if (_weakReferenceSource)
+ delete _weakReferenceSource;
+
+ OutOfProcessServer::release();
+ }
+
+private:
+ ULONG _refCount;
+ WeakReferenceSource *_weakReferenceSource;
+};
+
+#endif /* #ifndef _JMSOFFICECOMM_UNKNOWNIMPL_H_ */
diff --git a/src/native/windows/msofficecomm/WeakReference.cxx b/src/native/windows/msofficecomm/WeakReference.cxx
new file mode 100644
index 0000000..a858917
--- /dev/null
+++ b/src/native/windows/msofficecomm/WeakReference.cxx
@@ -0,0 +1,47 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#include "WeakReference.h"
+
+STDMETHODIMP WeakReference::QueryInterface(REFIID iid, PVOID *obj)
+{
+ HRESULT hr;
+
+ if (!obj)
+ hr = E_POINTER;
+ else if (IID_IWeakReferenceSource == iid)
+ {
+ /*
+ * While a weak reference to a weak reference should technically be
+ * possible, such functionality does not seem necessary at the time of
+ * this writing.
+ */
+ *obj = NULL;
+ hr = E_NOINTERFACE;
+ }
+ else
+ hr = UnknownImpl::QueryInterface(iid, obj);
+ return hr;
+}
+
+STDMETHODIMP WeakReference::Resolve(REFIID iid, PVOID *obj)
+{
+ HRESULT hr;
+
+ if (obj)
+ {
+ if (_iUnknown)
+ hr = _iUnknown->QueryInterface(iid, obj);
+ else
+ {
+ *obj = NULL;
+ hr = E_FAIL;
+ }
+ }
+ else
+ hr = E_POINTER;
+ return hr;
+}
diff --git a/src/native/windows/msofficecomm/WeakReference.h b/src/native/windows/msofficecomm/WeakReference.h
new file mode 100644
index 0000000..a00c5d7
--- /dev/null
+++ b/src/native/windows/msofficecomm/WeakReference.h
@@ -0,0 +1,33 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#ifndef _JMSOFFICECOMM_WEAKREFERENCE_H_
+#define _JMSOFFICECOMM_WEAKREFERENCE_H_
+
+#include "UnknownImpl.h"
+
+class WeakReference
+ : public UnknownImpl<IWeakReference, IID_IWeakReference>
+{
+public:
+ WeakReference(LPUNKNOWN iUnknown) : _iUnknown(iUnknown) {}
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID, PVOID *);
+
+ // IWeakReference
+ STDMETHODIMP Resolve(REFIID, PVOID *);
+
+ void invalidate() { _iUnknown = NULL; }
+
+protected:
+ virtual ~WeakReference() {}
+
+private:
+ LPUNKNOWN _iUnknown;
+};
+
+#endif /* #ifndef _JMSOFFICECOMM_WEAKREFERENCE_H_ */
diff --git a/src/native/windows/msofficecomm/WeakReferenceSource.cxx b/src/native/windows/msofficecomm/WeakReferenceSource.cxx
new file mode 100644
index 0000000..4bac616
--- /dev/null
+++ b/src/native/windows/msofficecomm/WeakReferenceSource.cxx
@@ -0,0 +1,37 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#include "WeakReferenceSource.h"
+
+#include "WeakReference.h"
+
+WeakReferenceSource::~WeakReferenceSource()
+{
+ if (_weakReference)
+ {
+ _weakReference->invalidate();
+ _weakReference->Release();
+ _weakReference = NULL;
+ }
+}
+
+STDMETHODIMP
+WeakReferenceSource::GetWeakReference(IWeakReference **weakReference)
+{
+ HRESULT hr;
+
+ if (weakReference)
+ {
+ if (!_weakReference)
+ _weakReference = new WeakReference(_iUnknown);
+ _weakReference->AddRef();
+ *weakReference = _weakReference;
+ hr = S_OK;
+ }
+ else
+ hr = E_POINTER;
+ return hr;
+}
diff --git a/src/native/windows/msofficecomm/WeakReferenceSource.h b/src/native/windows/msofficecomm/WeakReferenceSource.h
new file mode 100644
index 0000000..8be3da2
--- /dev/null
+++ b/src/native/windows/msofficecomm/WeakReferenceSource.h
@@ -0,0 +1,89 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+#ifndef _JMSOFFICECOMM_WEAKREFERENCESOURCE_H_
+#define _JMSOFFICECOMM_WEAKREFERENCESOURCE_H_
+
+#include "IWeakReferenceSource.h"
+
+class WeakReference;
+
+class WeakReferenceSource
+ : public IWeakReferenceSource
+{
+public:
+ WeakReferenceSource(LPUNKNOWN iUnknown)
+ : _iUnknown(iUnknown), _weakReference(NULL) {}
+ virtual ~WeakReferenceSource();
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID iid, PVOID *obj)
+ { return _iUnknown->QueryInterface(iid, obj); }
+ STDMETHODIMP_(ULONG) AddRef()
+ { return _iUnknown->AddRef(); }
+ STDMETHODIMP_(ULONG) Release()
+ { return _iUnknown->Release(); }
+
+ // IWeakReferenceSource
+ STDMETHODIMP GetWeakReference(IWeakReference **weakReference);
+
+private:
+ const LPUNKNOWN _iUnknown;
+ WeakReference *_weakReference;
+};
+
+#define STDMETHODIMP_RESOLVE_WEAKREFERENCE_OR_NEW(out,weakReference,clazz,...) \
+ { \
+ HRESULT hr; \
+\
+ if (out) \
+ { \
+ hr = E_FAIL; \
+ if (weakReference) \
+ { \
+ hr = weakReference->Resolve(IID_IDispatch, (PVOID *) out); \
+ if (FAILED(hr) && (E_NOINTERFACE != hr)) \
+ { \
+ weakReference->Release(); \
+ weakReference = NULL; \
+ } \
+ } \
+ if (FAILED(hr) && (E_NOINTERFACE != hr)) \
+ { \
+ clazz *obj = new clazz(__VA_ARGS__); \
+ IWeakReferenceSource *weakReferenceSource; \
+\
+ hr \
+ = obj->QueryInterface( \
+ IID_IWeakReferenceSource, \
+ (PVOID *) &weakReferenceSource); \
+ obj->Release(); \
+ if (SUCCEEDED(hr)) \
+ { \
+ hr \
+ = weakReferenceSource->GetWeakReference( \
+ &weakReference); \
+ if (SUCCEEDED(hr)) \
+ { \
+ hr \
+ = weakReference->Resolve( \
+ IID_IDispatch, \
+ (PVOID *) out); \
+ } \
+ else \
+ *out = NULL; \
+ weakReferenceSource->Release(); \
+ } \
+ else \
+ *out = NULL; \
+ } \
+ } \
+ else \
+ hr = RPC_X_NULL_REF_POINTER; \
+ return hr; \
+ }
+
+#endif /* #ifndef _JMSOFFICECOMM_WEAKREFERENCESOURCE_H_ */
diff --git a/src/native/windows/msofficecomm/net_java_sip_communicator_plugin_msofficecomm_Messenger.h b/src/native/windows/msofficecomm/net_java_sip_communicator_plugin_msofficecomm_Messenger.h
new file mode 100644
index 0000000..b6ab094
--- /dev/null
+++ b/src/native/windows/msofficecomm/net_java_sip_communicator_plugin_msofficecomm_Messenger.h
@@ -0,0 +1,21 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class net_java_sip_communicator_plugin_msofficecomm_Messenger */
+
+#ifndef _Included_net_java_sip_communicator_plugin_msofficecomm_Messenger
+#define _Included_net_java_sip_communicator_plugin_msofficecomm_Messenger
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: net_java_sip_communicator_plugin_msofficecomm_Messenger
+ * Method: onContactStatusChange
+ * Signature: (Ljava/lang/String;I)V
+ */
+JNIEXPORT void JNICALL Java_net_java_sip_communicator_plugin_msofficecomm_Messenger_onContactStatusChange
+ (JNIEnv *, jclass, jstring, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/native/windows/msofficecomm/net_java_sip_communicator_plugin_msofficecomm_OutOfProcessServer.h b/src/native/windows/msofficecomm/net_java_sip_communicator_plugin_msofficecomm_OutOfProcessServer.h
new file mode 100644
index 0000000..c2ab755
--- /dev/null
+++ b/src/native/windows/msofficecomm/net_java_sip_communicator_plugin_msofficecomm_OutOfProcessServer.h
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class net_java_sip_communicator_plugin_msofficecomm_OutOfProcessServer */
+
+#ifndef _Included_net_java_sip_communicator_plugin_msofficecomm_OutOfProcessServer
+#define _Included_net_java_sip_communicator_plugin_msofficecomm_OutOfProcessServer
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: net_java_sip_communicator_plugin_msofficecomm_OutOfProcessServer
+ * Method: start
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_net_java_sip_communicator_plugin_msofficecomm_OutOfProcessServer_start
+ (JNIEnv *, jclass);
+
+/*
+ * Class: net_java_sip_communicator_plugin_msofficecomm_OutOfProcessServer
+ * Method: stop
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_net_java_sip_communicator_plugin_msofficecomm_OutOfProcessServer_stop
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif