diff options
Diffstat (limited to 'src/native/windows')
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 |