aboutsummaryrefslogtreecommitdiffstats
path: root/src/native/windows/msofficecomm/Messenger.cxx
diff options
context:
space:
mode:
authorLyubomir Marinov <lyubomir.marinov@jitsi.org>2012-06-01 08:41:50 +0000
committerLyubomir Marinov <lyubomir.marinov@jitsi.org>2012-06-01 08:41:50 +0000
commit97f00d4a432a0688f1446c5bf10d92e5a60c0cf8 (patch)
tree942362de0c3646e2e3f92a3c0240486d1888b507 /src/native/windows/msofficecomm/Messenger.cxx
parent4b00ebbb7e12aa763e9528c6ea145ba17c937469 (diff)
downloadjitsi-97f00d4a432a0688f1446c5bf10d92e5a60c0cf8.zip
jitsi-97f00d4a432a0688f1446c5bf10d92e5a60c0cf8.tar.gz
jitsi-97f00d4a432a0688f1446c5bf10d92e5a60c0cf8.tar.bz2
Integrates Jitsi presence, IM and VoIP with MS Outlook.
Diffstat (limited to 'src/native/windows/msofficecomm/Messenger.cxx')
-rw-r--r--src/native/windows/msofficecomm/Messenger.cxx876
1 files changed, 876 insertions, 0 deletions
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