diff options
author | Lyubomir Marinov <lyubomir.marinov@jitsi.org> | 2012-06-01 08:41:50 +0000 |
---|---|---|
committer | Lyubomir Marinov <lyubomir.marinov@jitsi.org> | 2012-06-01 08:41:50 +0000 |
commit | 97f00d4a432a0688f1446c5bf10d92e5a60c0cf8 (patch) | |
tree | 942362de0c3646e2e3f92a3c0240486d1888b507 /src/native/windows/msofficecomm/Messenger.cxx | |
parent | 4b00ebbb7e12aa763e9528c6ea145ba17c937469 (diff) | |
download | jitsi-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.cxx | 876 |
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 |