From 30695f035a910cb8cb1f9a6d71fdf9fb2fe9d75c Mon Sep 17 00:00:00 2001 From: Lyubomir Marinov Date: Sat, 17 Dec 2011 18:46:28 +0000 Subject: [PATCH] Fixes a crash in the Microsoft Outlook Contacts and Address Book integration. Does not display contacts and contact groups without contact details. Displays the company name for contacts without a display name akin to Microsoft Outlook. --- lib/native/windows-64/jmsoutlookaddrbook.dll | Bin 26624 -> 31232 bytes lib/native/windows/jmsoutlookaddrbook.dll | Bin 17408 -> 17408 bytes src/native/addrbook/msoutlook/Makefile | 4 +- .../MsOutlookMAPIHResultException.cxx | 2 +- ...soutlook_MsOutlookAddrBookContactQuery.cxx | 755 ++++++++++++++++-- ..._MsOutlookAddrBookContactSourceService.cxx | 111 ++- .../plugin/addrbook/addrbook.manifest.mf | 14 +- .../MsOutlookAddrBookContactQuery.java | 113 ++- 8 files changed, 857 insertions(+), 142 deletions(-) diff --git a/lib/native/windows-64/jmsoutlookaddrbook.dll b/lib/native/windows-64/jmsoutlookaddrbook.dll index 19507f9d8c726905d7c14d6331c6045d882e8674..b4c4218621e9dcaad589c6f60cb12aed579b9630 100644 GIT binary patch literal 31232 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

OByU^@*ydE8*cQ$cn9~+Q8IlN<{J> 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 diff --git a/lib/native/windows/jmsoutlookaddrbook.dll b/lib/native/windows/jmsoutlookaddrbook.dll index d84d372cfa20e0fe561b9b0580b9c83233761037..ced51886849074a2e9d4b88e08250cb50eb08912 100644 GIT binary patch literal 17408 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 #include -#define WIN32_MEAN_AND_LEAN -#include +#define PR_ATTACHMENT_CONTACTPHOTO PROP_TAG(PT_BOOLEAN, 0x7FFF) +typedef + jboolean (*MsOutlookAddrBookContactQuery_ForeachRowInTableCallback) + (LPUNKNOWN iUnknown, + ULONG entryIDByteCount, LPENTRYID entryID, ULONG objType, + JNIEnv *jniEnv, + jstring query, + jobject callback, jmethodID callbackMethodID); + +static HRESULT HrGetOneProp + (LPMAPIPROP mapiProp, ULONG propTag, LPSPropValue *prop); + +static jboolean MsOutlookAddrBookContactQuery_foreachContactInMsgStoresTable + (LPMAPISESSION mapiSession, + JNIEnv *jniEnv, + jstring query, + jobject callback, jmethodID callbackMethodID); static jboolean MsOutlookAddrBookContactQuery_foreachMailUser (ULONG objType, LPUNKNOWN iUnknown, JNIEnv *jniEnv, jstring query, jobject callback, jmethodID callbackMethodID); +static jboolean MsOutlookAddrBookContactQuery_foreachMailUserInAddressBook + (LPMAPISESSION mapiSession, + JNIEnv *jniEnv, + jstring query, + jobject callback, jmethodID callbackMethodID); static jboolean MsOutlookAddrBookContactQuery_foreachMailUserInContainerTable (LPMAPICONTAINER mapiContainer, LPMAPITABLE mapiTable, JNIEnv *jniEnv, jstring query, jobject callback, jmethodID callbackMethodID); +static jboolean MsOutlookAddrBookContactQuery_foreachRowInTable + (LPMAPITABLE mapiTable, + MsOutlookAddrBookContactQuery_ForeachRowInTableCallback rowCallback, + LPUNKNOWN iUnknown, + JNIEnv *jniEnv, jstring query, jobject callback, jmethodID callbackMethodID); static void MsOutlookAddrBookContactQuery_freeSRowSet(LPSRowSet rows); +static jbyteArray MsOutlookAddrBookContactQuery_getAttachmentContactPhoto + (LPMESSAGE message, + JNIEnv *jniEnv); +static HRESULT MsOutlookAddrBookContactQuery_getContactsFolderEntryID + (LPMDB msgStore, + ULONG folderEntryIDByteCount, LPENTRYID folderEntryID, + ULONG *contactsFolderEntryIDByteCount, LPENTRYID *contactsFolderEntryID); +static ULONG MsOutlookAddrBookContactQuery_getPropTagFromLid + (LPMAPIPROP mapiProp, LONG lid); static jboolean MsOutlookAddrBookContactQuery_mailUserMatches (LPMAPIPROP mailUser, JNIEnv *jniEnv, jstring query); +static jboolean MsOutlookAddrBookContactQuery_onForeachContactInMsgStoresTableRow + (LPUNKNOWN mapiSession, + ULONG entryIDByteCount, LPENTRYID entryID, ULONG objType, + JNIEnv *jniEnv, jstring query, jobject callback, jmethodID callbackMethodID); +static jboolean MsOutlookAddrBookContactQuery_onForeachMailUserInContainerTableRow + (LPUNKNOWN mapiContainer, + ULONG entryIDByteCount, LPENTRYID entryID, ULONG objType, + JNIEnv *jniEnv, jstring query, jobject callback, jmethodID callbackMethodID); +static jbyteArray MsOutlookAddrBookContactQuery_readAttachment + (LPMESSAGE message, LONG method, ULONG num, JNIEnv *jniEnv, ULONG cond); JNIEXPORT void JNICALL Java_net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContactQuery_foreachMailUser @@ -37,11 +82,11 @@ Java_net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContac jmethodID callbackMethodID; HRESULT hResult; - LPMAPISESSION mapiSession; + LPMAPISESSION mapiSession = NULL; callbackMethodID = AddrBookContactQuery_getPtrCallbackMethodID(jniEnv, callback); - if (!callbackMethodID || (JNI_TRUE == jniEnv->ExceptionCheck())) + if (!callbackMethodID || jniEnv->ExceptionCheck()) return; hResult @@ -50,45 +95,32 @@ Java_net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContac NULL, NULL, MAPI_EXTENDED | MAPI_NO_MAIL | MAPI_USE_DEFAULT, &mapiSession); - if (HR_SUCCEEDED(hResult)) + if (HR_SUCCEEDED(hResult) && mapiSession) { - LPADRBOOK adrBook; - - hResult = mapiSession->OpenAddressBook(0, NULL, AB_NO_DIALOG, &adrBook); - if (HR_SUCCEEDED(hResult)) - { - ULONG objType; - LPUNKNOWN iUnknown; - - hResult = adrBook->OpenEntry(0, NULL, NULL, 0, &objType, &iUnknown); - if (HR_SUCCEEDED(hResult)) - { - MsOutlookAddrBookContactQuery_foreachMailUser( - objType, iUnknown, - jniEnv, query, callback, callbackMethodID); - - iUnknown->Release(); - } - else - { - MsOutlookMAPIHResultException_throwNew( - jniEnv, - hResult, - __FILE__, __LINE__); - } + jboolean proceed + = MsOutlookAddrBookContactQuery_foreachContactInMsgStoresTable( + mapiSession, + jniEnv, + query, + callback, callbackMethodID); - adrBook->Release(); - } - else + if (proceed && !(jniEnv->ExceptionCheck())) { - MsOutlookMAPIHResultException_throwNew( + MsOutlookAddrBookContactQuery_foreachMailUserInAddressBook( + mapiSession, jniEnv, - hResult, - __FILE__, __LINE__); + query, + callback, callbackMethodID); } - mapiSession->Logoff(0, 0, 0); - mapiSession->Release(); + /* + * XXX MAPILogonEx has been redefined to return a shared mapiSession + * which is logged off and released upon uninitializing MAPI. The reason + * for the redefinition is that logging on, off and releasing multiple + * times leads to a crash eventually. + */ +// mapiSession->Logoff(0, 0, 0); +// mapiSession->Release(); } else { @@ -122,7 +154,7 @@ Java_net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContac jlong propId; jniEnv->GetLongArrayRegion(propIds, i, 1, &propId); - if (JNI_TRUE == jniEnv->ExceptionCheck()) + if (jniEnv->ExceptionCheck()) { MAPIFreeBuffer(propTagArray); propTagArray = NULL; @@ -130,8 +162,23 @@ Java_net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContac } else { - *(propTagArray->aulPropTag + i) - = PROP_TAG(PT_UNSPECIFIED, propId); + ULONG propTag; + + if (propId < 0x8000) + { + if (propId == PROP_ID(PR_ATTACHMENT_CONTACTPHOTO)) + propTag = PR_HASATTACH; + else + propTag = PROP_TAG(PT_UNSPECIFIED, propId); + } + else + { + propTag + = MsOutlookAddrBookContactQuery_getPropTagFromLid( + (LPMAPIPROP) mapiProp, + propId); + } + *(propTagArray->aulPropTag + i) = propTag; } } if (propTagArray) @@ -167,6 +214,61 @@ Java_net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContac { switch (PROP_TYPE(prop->ulPropTag)) { + case PT_BOOLEAN: + { + if ((PR_HASATTACH == prop->ulPropTag) + && prop->Value.b) + { + jbyteArray value + = MsOutlookAddrBookContactQuery_getAttachmentContactPhoto( + (LPMESSAGE) mapiProp, + jniEnv); + + if (value) + { + jniEnv->SetObjectArrayElement( + props, j, + value); + if (jniEnv->ExceptionCheck()) + props = NULL; + } + } + break; + } + + case PT_LONG: + { + jclass longClass + = jniEnv->FindClass("java/lang/Long"); + + if (longClass) + { + jmethodID longMethodID + = jniEnv->GetMethodID( + longClass, + "", "(J)V"); + + if (longMethodID) + { + jlong l = prop->Value.l; + jobject value + = jniEnv->NewObject( + longClass, longMethodID, + l); + + if (value) + { + jniEnv->SetObjectArrayElement( + props, j, + value); + if (jniEnv->ExceptionCheck()) + props = NULL; + } + } + } + break; + } + case PT_STRING8: { if (prop->Value.lpszA) @@ -209,8 +311,8 @@ Java_net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContac } } } - MAPIFreeBuffer(prop); propArray++; + MAPIFreeBuffer(prop); } } else @@ -233,26 +335,90 @@ Java_net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContac return props; } +static HRESULT +HrGetOneProp(LPMAPIPROP mapiProp, ULONG propTag, LPSPropValue *prop) +{ + SPropTagArray propTagArray; + HRESULT hResult; + ULONG valueCount; + LPSPropValue values; + + propTagArray.cValues = 1; + propTagArray.aulPropTag[0] = propTag; + + hResult = mapiProp->GetProps(&propTagArray, 0, &valueCount, &values); + if (HR_SUCCEEDED(hResult)) + { + ULONG i; + jboolean propHasBeenAssignedTo = JNI_FALSE; + + for (i = 0; i < valueCount; i++) + { + LPSPropValue value = values; + + values++; + if (value->ulPropTag == propTag) + { + *prop = value; + propHasBeenAssignedTo = JNI_TRUE; + } + else + MAPIFreeBuffer(value); + } + if (!propHasBeenAssignedTo) + hResult = MAPI_E_NOT_FOUND; + } + return hResult; +} + +static jboolean +MsOutlookAddrBookContactQuery_foreachContactInMsgStoresTable + (LPMAPISESSION mapiSession, + JNIEnv *jniEnv, jstring query, jobject callback, jmethodID callbackMethodID) +{ + HRESULT hResult; + LPMAPITABLE msgStoresTable = NULL; + jboolean proceed; + + hResult = mapiSession->GetMsgStoresTable(0, &msgStoresTable); + if (HR_SUCCEEDED(hResult) && msgStoresTable) + { + proceed + = MsOutlookAddrBookContactQuery_foreachRowInTable( + msgStoresTable, + MsOutlookAddrBookContactQuery_onForeachContactInMsgStoresTableRow, + (LPUNKNOWN) mapiSession, + jniEnv, query, callback, callbackMethodID); + msgStoresTable->Release(); + } + else + { + MsOutlookMAPIHResultException_throwNew( + jniEnv, + hResult, + __FILE__, __LINE__); + proceed = JNI_TRUE; + } + return proceed; +} + static jboolean MsOutlookAddrBookContactQuery_foreachMailUser (ULONG objType, LPUNKNOWN iUnknown, - JNIEnv *jniEnv, - jstring query, - jobject callback, jmethodID callbackMethodID) + JNIEnv *jniEnv, jstring query, jobject callback, jmethodID callbackMethodID) { - jboolean proceed; + jboolean proceed = JNI_TRUE; switch (objType) { case MAPI_ABCONT: + case MAPI_FOLDER: { LPMAPICONTAINER mapiContainer = (LPMAPICONTAINER) iUnknown; HRESULT hResult; LPMAPITABLE mapiTable; - proceed = JNI_TRUE; - /* Look for MAPI_MAILUSER through the contents. */ mapiTable = NULL; hResult = mapiContainer->GetContentsTable(0, &mapiTable); @@ -266,7 +432,7 @@ MsOutlookAddrBookContactQuery_foreachMailUser } /* Drill down the hierarchy. */ - if (JNI_TRUE == proceed) + if (proceed) { mapiTable = NULL; hResult = mapiContainer->GetHierarchyTable(0, &mapiTable); @@ -284,28 +450,74 @@ MsOutlookAddrBookContactQuery_foreachMailUser } case MAPI_MAILUSER: + case MAPI_MESSAGE: { - if (JNI_TRUE - == MsOutlookAddrBookContactQuery_mailUserMatches( - (LPMAPIPROP) iUnknown, - jniEnv, query)) + if (MsOutlookAddrBookContactQuery_mailUserMatches( + (LPMAPIPROP) iUnknown, + jniEnv, query)) { /* Report the MAPI_MAILUSER to the callback. */ proceed = jniEnv->CallBooleanMethod( callback, callbackMethodID, iUnknown); + /* * XXX When an exception is thrown in the callback, does proceed get * assigned JNI_FALSE? */ - if ((JNI_TRUE == proceed) && (JNI_TRUE == jniEnv->ExceptionCheck())) + if (proceed && jniEnv->ExceptionCheck()) proceed = JNI_FALSE; } + break; + } + } + return proceed; +} + +static jboolean +MsOutlookAddrBookContactQuery_foreachMailUserInAddressBook + (LPMAPISESSION mapiSession, + JNIEnv *jniEnv, jstring query, jobject callback, jmethodID callbackMethodID) +{ + HRESULT hResult; + LPADRBOOK adrBook; + jboolean proceed; + + hResult = mapiSession->OpenAddressBook(0, NULL, AB_NO_DIALOG, &adrBook); + if (HR_SUCCEEDED(hResult)) + { + ULONG objType; + LPUNKNOWN iUnknown; + + hResult = adrBook->OpenEntry(0, NULL, NULL, 0, &objType, &iUnknown); + if (HR_SUCCEEDED(hResult)) + { + proceed + = MsOutlookAddrBookContactQuery_foreachMailUser( + objType, iUnknown, + jniEnv, query, callback, callbackMethodID); + + iUnknown->Release(); + } else + { + MsOutlookMAPIHResultException_throwNew( + jniEnv, + hResult, + __FILE__, __LINE__); proceed = JNI_TRUE; - break; + } + + adrBook->Release(); } + else + { + MsOutlookMAPIHResultException_throwNew( + jniEnv, + hResult, + __FILE__, __LINE__); + proceed = JNI_TRUE; } return proceed; } @@ -313,9 +525,22 @@ MsOutlookAddrBookContactQuery_foreachMailUser static jboolean MsOutlookAddrBookContactQuery_foreachMailUserInContainerTable (LPMAPICONTAINER mapiContainer, LPMAPITABLE mapiTable, - JNIEnv *jniEnv, - jstring query, - jobject callback, jmethodID callbackMethodID) + JNIEnv *jniEnv, jstring query, jobject callback, jmethodID callbackMethodID) +{ + return + MsOutlookAddrBookContactQuery_foreachRowInTable( + mapiTable, + MsOutlookAddrBookContactQuery_onForeachMailUserInContainerTableRow, + (LPUNKNOWN) mapiContainer, + jniEnv, query, callback, callbackMethodID); +} + +static jboolean +MsOutlookAddrBookContactQuery_foreachRowInTable + (LPMAPITABLE mapiTable, + MsOutlookAddrBookContactQuery_ForeachRowInTableCallback rowCallback, + LPUNKNOWN iUnknown, + JNIEnv *jniEnv, jstring query, jobject callback, jmethodID callbackMethodID) { HRESULT hResult; jboolean proceed; @@ -323,18 +548,21 @@ MsOutlookAddrBookContactQuery_foreachMailUserInContainerTable hResult = mapiTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL); if (HR_SUCCEEDED(hResult)) { - LPSRowSet rows; - proceed = JNI_TRUE; - while ((JNI_TRUE == proceed) - && HR_SUCCEEDED(hResult = mapiTable->QueryRows(1, 0, &rows))) + while (proceed) { + LPSRowSet rows; + + hResult = mapiTable->QueryRows(1, 0, &rows); + if (HR_FAILED(hResult)) + break; + if (rows->cRows == 1) { ULONG i; LPSRow row = rows->aRow; ULONG objType = 0; - SBinary entryIDBinary = {0, NULL}; + SBinary entryIDBinary = { 0, NULL }; for (i = 0; i < row->cValues; i++) { @@ -360,8 +588,6 @@ MsOutlookAddrBookContactQuery_foreachMailUserInContainerTable entryIDBinary.cb, (void **) &entryID)) { - LPUNKNOWN iUnknown; - CopyMemory( entryID, entryIDBinary.lpb, @@ -373,22 +599,16 @@ MsOutlookAddrBookContactQuery_foreachMailUserInContainerTable */ MsOutlookAddrBookContactQuery_freeSRowSet(rows); - hResult - = mapiContainer->OpenEntry( - entryIDBinary.cb, entryID, - NULL, - 0, - &objType, &iUnknown); - if (HR_SUCCEEDED(hResult)) - { - proceed - = MsOutlookAddrBookContactQuery_foreachMailUser( - objType, iUnknown, - jniEnv, query, callback, callbackMethodID); - iUnknown->Release(); - } + proceed + = rowCallback( + iUnknown, + entryIDBinary.cb, entryID, objType, + jniEnv, query, callback, callbackMethodID); MAPIFreeBuffer(entryID); + + if (proceed && jniEnv->ExceptionCheck()) + proceed = JNI_FALSE; } else MsOutlookAddrBookContactQuery_freeSRowSet(rows); @@ -431,6 +651,177 @@ MsOutlookAddrBookContactQuery_freeSRowSet(LPSRowSet rows) MAPIFreeBuffer(rows); } +static jbyteArray +MsOutlookAddrBookContactQuery_getAttachmentContactPhoto + (LPMESSAGE message, JNIEnv *jniEnv) +{ + HRESULT hResult; + LPMAPITABLE attachmentTable; + jbyteArray attachmentContactPhoto = NULL; + + hResult = message->GetAttachmentTable(0, &attachmentTable); + if (HR_SUCCEEDED(hResult)) + { + hResult = attachmentTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL); + if (HR_SUCCEEDED(hResult)) + { + while (1) + { + LPSRowSet rows; + + hResult = attachmentTable->QueryRows(1, 0, &rows); + if (HR_FAILED(hResult)) + break; + + if (rows->cRows == 1) + { + ULONG i; + LPSRow row = rows->aRow; + jboolean isAttachmentContactPhotoRow = JNI_FALSE; + jboolean hasAttachmentContactPhoto = JNI_FALSE; + ULONG attachNum = 0; + LONG attachMethod = NO_ATTACHMENT; + + for (i = 0; i < row->cValues; i++) + { + LPSPropValue prop = (row->lpProps) + i; + + switch (prop->ulPropTag) + { + case PR_ATTACHMENT_CONTACTPHOTO: + isAttachmentContactPhotoRow = JNI_TRUE; + hasAttachmentContactPhoto + = prop->Value.b ? JNI_TRUE : JNI_FALSE; + break; + case PR_ATTACH_METHOD: + attachMethod = prop->Value.l; + break; + case PR_ATTACH_NUM: + attachNum = prop->Value.l; + break; + } + } + + MsOutlookAddrBookContactQuery_freeSRowSet(rows); + + /* + * As the reference says and as discovered in practice, + * PR_ATTACHMENT_CONTACTPHOTO is sometimes in IAttach. + */ + if ((isAttachmentContactPhotoRow + && hasAttachmentContactPhoto) + || !isAttachmentContactPhotoRow) + { + attachmentContactPhoto + = MsOutlookAddrBookContactQuery_readAttachment( + message, + attachMethod, attachNum, + jniEnv, + (!isAttachmentContactPhotoRow) + ? PR_ATTACHMENT_CONTACTPHOTO + : PROP_TAG(PT_UNSPECIFIED, 0)); + } + if (isAttachmentContactPhotoRow + || attachmentContactPhoto) + { + /* + * The reference says there can be only 1 + * PR_ATTACHMENT_CONTACTPHOTO. + */ + break; + } + } + else + { + MAPIFreeBuffer(rows); + break; + } + } + } + + attachmentTable->Release(); + } + return attachmentContactPhoto; +} + +static HRESULT +MsOutlookAddrBookContactQuery_getContactsFolderEntryID + (LPMDB msgStore, + ULONG folderEntryIDByteCount, LPENTRYID folderEntryID, + ULONG *contactsFolderEntryIDByteCount, LPENTRYID *contactsFolderEntryID) +{ + HRESULT hResult; + ULONG objType; + LPUNKNOWN folder; + + hResult + = msgStore->OpenEntry( + folderEntryIDByteCount, folderEntryID, + NULL, + 0, + &objType, &folder); + if (HR_SUCCEEDED(hResult)) + { + LPSPropValue prop; + + hResult + = HrGetOneProp( + (LPMAPIPROP) folder, + 0x36D10102 /* PR_IPM_CONTACT_ENTRYID */, + &prop); + if (HR_SUCCEEDED(hResult)) + { + LPSBinary bin = &(prop->Value.bin); + if (S_OK + == MAPIAllocateBuffer( + bin->cb, + (void **) contactsFolderEntryID)) + { + hResult = S_OK; + *contactsFolderEntryIDByteCount = bin->cb; + CopyMemory(*contactsFolderEntryID, bin->lpb, bin->cb); + } + else + hResult = MAPI_E_NOT_ENOUGH_MEMORY; + MAPIFreeBuffer(prop); + } + folder->Release(); + } + return hResult; +} + +static ULONG +MsOutlookAddrBookContactQuery_getPropTagFromLid(LPMAPIPROP mapiProp, LONG lid) +{ + GUID PSETID_Address + = {0x00062004, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}; + MAPINAMEID propName; + LPMAPINAMEID propNamePtr; + HRESULT hResult; + LPSPropTagArray propTagArray; + + propName.lpguid = (LPGUID) &PSETID_Address; + propName.ulKind = MNID_ID; + propName.Kind.lID = lid; + propNamePtr = &propName; + hResult + = mapiProp->GetIDsFromNames( + 1, &propNamePtr, + 0, + &propTagArray); + if (HR_SUCCEEDED(hResult) && (1 == propTagArray->cValues)) + { + ULONG propTag = propTagArray->aulPropTag[0]; + + if (PT_ERROR == PROP_TYPE(propTag)) + propTag = PROP_TAG(PT_UNSPECIFIED, lid); + MAPIFreeBuffer(propTagArray); + return propTag; + } + else + return PROP_TAG(PT_UNSPECIFIED, lid); +} + static jboolean MsOutlookAddrBookContactQuery_mailUserMatches (LPMAPIPROP mailUser, JNIEnv *jniEnv, jstring query) @@ -438,3 +829,209 @@ MsOutlookAddrBookContactQuery_mailUserMatches // TODO Auto-generated method stub return JNI_TRUE; } + +static jboolean +MsOutlookAddrBookContactQuery_onForeachContactInMsgStoresTableRow + (LPUNKNOWN mapiSession, + ULONG entryIDByteCount, LPENTRYID entryID, ULONG objType, + JNIEnv *jniEnv, jstring query, jobject callback, jmethodID callbackMethodID) +{ + HRESULT hResult; + LPMDB msgStore; + jboolean proceed; + + hResult + = ((LPMAPISESSION) mapiSession)->OpenMsgStore( + 0, + entryIDByteCount, entryID, + NULL, + MDB_NO_MAIL, + &msgStore); + if (HR_SUCCEEDED(hResult)) + { + LPENTRYID receiveFolderEntryID; + ULONG contactsFolderEntryIDByteCount; + LPENTRYID contactsFolderEntryID; + + hResult + = msgStore->GetReceiveFolder( + NULL, + 0, + &entryIDByteCount, &receiveFolderEntryID, + NULL); + if (HR_SUCCEEDED(hResult)) + { + hResult + = MsOutlookAddrBookContactQuery_getContactsFolderEntryID( + msgStore, + entryIDByteCount, receiveFolderEntryID, + &contactsFolderEntryIDByteCount, &contactsFolderEntryID); + MAPIFreeBuffer(receiveFolderEntryID); + } + if (HR_FAILED(hResult)) + { + hResult + = MsOutlookAddrBookContactQuery_getContactsFolderEntryID( + msgStore, + 0, NULL, + &contactsFolderEntryIDByteCount, &contactsFolderEntryID); + } + if (HR_SUCCEEDED(hResult)) + { + ULONG contactsFolderObjType; + LPUNKNOWN contactsFolder; + + hResult + = msgStore->OpenEntry( + contactsFolderEntryIDByteCount, contactsFolderEntryID, + NULL, + 0, + &contactsFolderObjType, &contactsFolder); + if (HR_SUCCEEDED(hResult)) + { + proceed + = MsOutlookAddrBookContactQuery_foreachMailUser( + contactsFolderObjType, contactsFolder, + jniEnv, query, callback, callbackMethodID); + contactsFolder->Release(); + } + else + { + /* + * We've failed but other parts of the hierarchy may still + * succeed. + */ + proceed = JNI_TRUE; + } + MAPIFreeBuffer(contactsFolderEntryID); + } + else + { + /* + * We've failed but other parts of the hierarchy may still succeed. + */ + proceed = JNI_TRUE; + } + msgStore->Release(); + } + else + { + /* We've failed but other parts of the hierarchy may still succeed. */ + proceed = JNI_TRUE; + } + return proceed; +} + +static jboolean +MsOutlookAddrBookContactQuery_onForeachMailUserInContainerTableRow + (LPUNKNOWN mapiContainer, + ULONG entryIDByteCount, LPENTRYID entryID, ULONG objType, + JNIEnv *jniEnv, jstring query, jobject callback, jmethodID callbackMethodID) +{ + HRESULT hResult; + LPUNKNOWN iUnknown; + jboolean proceed; + + hResult + = ((LPMAPICONTAINER) mapiContainer)->OpenEntry( + entryIDByteCount, entryID, + NULL, + 0, + &objType, &iUnknown); + if (HR_SUCCEEDED(hResult)) + { + proceed + = MsOutlookAddrBookContactQuery_foreachMailUser( + objType, iUnknown, + jniEnv, query, callback, callbackMethodID); + iUnknown->Release(); + } + else + { + /* We've failed but other parts of the hierarchy may still succeed. */ + proceed = JNI_TRUE; + } + return proceed; +} + +static jbyteArray +MsOutlookAddrBookContactQuery_readAttachment + (LPMESSAGE message, LONG method, ULONG num, JNIEnv *jniEnv, ULONG cond) +{ + jbyteArray attachment = NULL; + + if (ATTACH_BY_VALUE == method) + { + HRESULT hResult; + LPATTACH attach; + + hResult = message->OpenAttach(num, NULL, 0, &attach); + if (HR_SUCCEEDED(hResult)) + { + IStream *stream; + + if (PT_BOOLEAN == PROP_TYPE(cond)) + { + LPSPropValue condValue; + + hResult = HrGetOneProp((LPMAPIPROP) attach, cond, &condValue); + if (HR_SUCCEEDED(hResult)) + { + if ((PT_BOOLEAN != PROP_TYPE(condValue->ulPropTag)) + || !(condValue->Value.b)) + hResult = MAPI_E_NOT_FOUND; + MAPIFreeBuffer(condValue); + } + } + + if (HR_SUCCEEDED(hResult)) + { + hResult + = ((LPMAPIPROP) attach)->OpenProperty( + PR_ATTACH_DATA_BIN, + &IID_IStream, 0, + 0, + (LPUNKNOWN *) &stream); + } + if (HR_SUCCEEDED(hResult)) + { + STATSTG statstg; + ULONGLONG length; + + hResult = stream->Stat(&statstg, STATFLAG_NONAME); + if ((S_OK == hResult) && ((length = statstg.cbSize.QuadPart))) + { + attachment = jniEnv->NewByteArray((jsize) length); + if (attachment) + { + jbyte *bytes + = jniEnv->GetByteArrayElements(attachment, NULL); + + if (bytes) + { + ULONG read; + jint mode; + + hResult + = stream->Read(bytes, (ULONG) length, &read); + mode + = ((S_OK == hResult) || (S_FALSE == hResult)) + ? 0 + : JNI_ABORT; + jniEnv->ReleaseByteArrayElements( + attachment, bytes, + mode); + if (0 != mode) + attachment = NULL; + } + } + } + + stream->Release(); + } + + attach->Release(); + } + } + return attachment; +} diff --git a/src/native/addrbook/msoutlook/net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContactSourceService.cxx b/src/native/addrbook/msoutlook/net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContactSourceService.cxx index 20f9a3c6c..3e7aa2c38 100644 --- a/src/native/addrbook/msoutlook/net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContactSourceService.cxx +++ b/src/native/addrbook/msoutlook/net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContactSourceService.cxx @@ -1,5 +1,5 @@ /* - * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Distributable under LGPL license. * See terms of license at gnu.org. @@ -22,6 +22,13 @@ static LPMAPILOGONEX MsOutlookAddrBookContactSourceService_mapiLogonEx; static LPMAPIUNINITIALIZE MsOutlookAddrBookContactSourceService_mapiUninitialize; +static LPMAPISESSION MsOutlookAddrBookContactSourceService_mapiSession = NULL; +static CRITICAL_SECTION MsOutlookAddrBookContactSourceService_mapiSessionCriticalSection; + +static jboolean +MsOutlookAddrBookContactSourceService_isValidDefaultMailClient + (LPCTSTR name, DWORD nameLength); + JNIEXPORT void JNICALL Java_net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContactSourceService_MAPIInitialize (JNIEnv *jniEnv, jclass clazz, jlong version, jlong flags) @@ -193,9 +200,10 @@ Java_net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContac DWORD defaultValueLength = defaultValueSize / sizeof(TCHAR); - if ((0 == defaultValueLength) || (0 == defaultValue[0])) - checkHKeyLocalMachine = JNI_TRUE; - else + if (JNI_TRUE + == MsOutlookAddrBookContactSourceService_isValidDefaultMailClient( + defaultValue, + defaultValueLength)) { checkHKeyLocalMachine = JNI_FALSE; if (_tcsnicmp( @@ -204,6 +212,8 @@ Java_net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContac == 0) hResult = S_OK; } + else + checkHKeyLocalMachine = JNI_TRUE; } else checkHKeyLocalMachine = JNI_FALSE; @@ -246,10 +256,12 @@ Java_net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContac { DWORD defaultValueLength = defaultValueSize / sizeof(TCHAR); - if (_tcsnicmp( - _T("Microsoft Outlook"), defaultValue, - defaultValueLength) - == 0) + if ((_tcsnicmp( + _T("Microsoft Outlook"), defaultValue, + defaultValueLength) + == 0) + && (JNI_TRUE + == MsOutlookAddrBookContactSourceService_isValidDefaultMailClient(_T("Microsoft Outlook"), 17))) hResult = S_OK; } RegCloseKey(regKey); @@ -288,6 +300,10 @@ Java_net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContac GetProcAddress(lib, "MAPIFreeBuffer"); MsOutlookAddrBookContactSourceService_mapiLogonEx = (LPMAPILOGONEX) GetProcAddress(lib, "MAPILogonEx"); + + InitializeCriticalSection( + &MsOutlookAddrBookContactSourceService_mapiSessionCriticalSection); + if (MsOutlookAddrBookContactSourceService_mapiAllocateBuffer && MsOutlookAddrBookContactSourceService_mapiFreeBuffer && MsOutlookAddrBookContactSourceService_mapiLogonEx) @@ -315,7 +331,21 @@ JNIEXPORT void JNICALL Java_net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContactSourceService_MAPIUninitialize (JNIEnv *jniEnv, jclass clazz) { + EnterCriticalSection( + &MsOutlookAddrBookContactSourceService_mapiSessionCriticalSection); + if (MsOutlookAddrBookContactSourceService_mapiSession) + { + MsOutlookAddrBookContactSourceService_mapiSession->Logoff(0, 0, 0); + MsOutlookAddrBookContactSourceService_mapiSession->Release(); + MsOutlookAddrBookContactSourceService_mapiSession = NULL; + } + LeaveCriticalSection( + &MsOutlookAddrBookContactSourceService_mapiSessionCriticalSection); + MsOutlookAddrBookContactSourceService_mapiUninitialize(); + + DeleteCriticalSection( + &MsOutlookAddrBookContactSourceService_mapiSessionCriticalSection); } SCODE @@ -338,10 +368,63 @@ MsOutlookAddrBook_mapiLogonEx FLAGS flags, LPMAPISESSION FAR *mapiSession) { - return - MsOutlookAddrBookContactSourceService_mapiLogonEx( - uiParam, - profileName, password, - flags, - mapiSession); + HRESULT hResult; + + EnterCriticalSection( + &MsOutlookAddrBookContactSourceService_mapiSessionCriticalSection); + if (MsOutlookAddrBookContactSourceService_mapiSession) + hResult = S_OK; + else + { + hResult + = MsOutlookAddrBookContactSourceService_mapiLogonEx( + uiParam, + profileName, password, + flags, + &MsOutlookAddrBookContactSourceService_mapiSession); + } + if (HR_SUCCEEDED(hResult)) + *mapiSession = MsOutlookAddrBookContactSourceService_mapiSession; + LeaveCriticalSection( + &MsOutlookAddrBookContactSourceService_mapiSessionCriticalSection); + + return hResult; +} + +static jboolean +MsOutlookAddrBookContactSourceService_isValidDefaultMailClient + (LPCTSTR name, DWORD nameLength) +{ + jboolean validDefaultMailClient = JNI_FALSE; + + if ((0 != nameLength) && (0 != name[0])) + { + LPTSTR str; + TCHAR keyName[ + 22 /* Software\Clients\Mail\ */ + + 255 + + 1 /* The terminating null character */]; + HKEY key; + + str = keyName; + _tcsncpy(str, _T("Software\\Clients\\Mail\\"), 22); + str += 22; + if (nameLength > 255) + nameLength = 255; + _tcsncpy(str, name, nameLength); + *(str + nameLength) = 0; + + if (ERROR_SUCCESS + == RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + keyName, + 0, + KEY_QUERY_VALUE, + &key)) + { + validDefaultMailClient = JNI_TRUE; + RegCloseKey(key); + } + } + return validDefaultMailClient; } diff --git a/src/net/java/sip/communicator/plugin/addrbook/addrbook.manifest.mf b/src/net/java/sip/communicator/plugin/addrbook/addrbook.manifest.mf index fbafa493c..b42344a33 100644 --- a/src/net/java/sip/communicator/plugin/addrbook/addrbook.manifest.mf +++ b/src/net/java/sip/communicator/plugin/addrbook/addrbook.manifest.mf @@ -3,13 +3,13 @@ Bundle-Description: OS-specific Address Book support Bundle-Name: OS-specific Address Book support Bundle-Vendor: sip-communicator.org Bundle-Version: 0.0.1 -Import-Package: net.java.sip.communicator.service.contactsource, +Import-Package: javax.swing, + net.java.sip.communicator.service.configuration, + net.java.sip.communicator.service.contactsource, + net.java.sip.communicator.service.gui, net.java.sip.communicator.service.protocol, + net.java.sip.communicator.service.resources, net.java.sip.communicator.util, - net.java.sip.communicator.service.gui, - net.java.sip.communicator.util.swing, - net.java.sip.communicator.service.resources, - net.java.sip.communicator.service.configuration, - org.osgi.framework, - javax.swing + net.java.sip.communicator.util.swing, + org.osgi.framework System-Bundle: yes diff --git a/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookAddrBookContactQuery.java b/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookAddrBookContactQuery.java index 063c78ee3..229137822 100644 --- a/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookAddrBookContactQuery.java +++ b/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookAddrBookContactQuery.java @@ -12,6 +12,7 @@ import net.java.sip.communicator.plugin.addrbook.*; import net.java.sip.communicator.service.contactsource.*; import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; /** * Implements ContactQuery for the Address Book of Microsoft Outlook. @@ -21,6 +22,13 @@ public class MsOutlookAddrBookContactQuery extends AsyncContactQuery { + /** + * The Logger used by the MsOutlookAddrBookContactQuery + * class and its instances for logging output. + */ + private static final Logger logger + = Logger.getLogger(MsOutlookAddrBookContactQuery.class); + private static final int dispidEmail1EmailAddress = 11; private static final int dispidEmail2EmailAddress = 12; @@ -53,7 +61,8 @@ public class MsOutlookAddrBookContactQuery 0x0FFE /* PR_OBJECT_TYPE */, 0x00008083 /* dispidEmail1EmailAddress */, 0x00008093 /* dispidEmail2EmailAddress */, - 0x000080A3 /* dispidEmail3EmailAddress */ + 0x000080A3 /* dispidEmail3EmailAddress */, + 0x3A16 /* PR_COMPANY_NAME */ }; /** @@ -85,6 +94,8 @@ public class MsOutlookAddrBookContactQuery */ private static final int PR_BUSINESS2_TELEPHONE_NUMBER = 6; + private static final int PR_COMPANY_NAME = 14; + /** * The index of the id of the PR_DISPLAY_NAME property in * {@link #MAPI_MAILUSER_PROP_IDS}. @@ -376,35 +387,49 @@ private boolean onMailUser(long iUnknown) } } - GenericSourceContact sourceContact - = new GenericSourceContact( - getContactSource(), - (String) props[PR_DISPLAY_NAME], - contactDetails); - - if (MAPI_MESSAGE == objType) + /* + * What's the point of showing a contact who has no contact details? + */ + if (!contactDetails.isEmpty()) { - ++mapiMessageCount; + String displayName = (String) props[PR_DISPLAY_NAME]; - try - { - Object[] images - = IMAPIProp_GetProps( - iUnknown, - new long[] { PR_ATTACHMENT_CONTACTPHOTO }, - 0); - Object image = images[0]; - - if (image instanceof byte[]) - sourceContact.setImage((byte[]) image); - } - catch (MsOutlookMAPIHResultException ex) + if ((displayName == null) || (displayName.length() == 0)) + displayName = (String) props[PR_COMPANY_NAME]; + + GenericSourceContact sourceContact + = new GenericSourceContact( + getContactSource(), + displayName, + contactDetails); + + if (MAPI_MESSAGE == objType) { - // Ignore it, the image isn't as vital as the SourceContact. + ++mapiMessageCount; + + try + { + Object[] images + = IMAPIProp_GetProps( + iUnknown, + new long[] { PR_ATTACHMENT_CONTACTPHOTO }, + 0); + Object image = images[0]; + + if (image instanceof byte[]) + sourceContact.setImage((byte[]) image); + } + catch (MsOutlookMAPIHResultException ex) + { + /* + * Ignore it, the image isn't as vital as the + * SourceContact. + */ + } } - } - addQueryResult(sourceContact); + addQueryResult(sourceContact); + } } return (getStatus() == QUERY_IN_PROGRESS); } @@ -416,23 +441,33 @@ private boolean onMailUser(long iUnknown) */ protected void run() { - foreachMailUser( - query.toString(), - new PtrCallback() - { - public boolean callback(long iUnknown) + synchronized (MsOutlookAddrBookContactQuery.class) + { + foreachMailUser( + query.toString(), + new PtrCallback() { - try + public boolean callback(long iUnknown) { - return onMailUser(iUnknown); - } - catch (MsOutlookMAPIHResultException ex) - { - ex.printStackTrace(System.err); - return false; + try + { + return onMailUser(iUnknown); + } + catch (MsOutlookMAPIHResultException e) + { + if (logger.isDebugEnabled()) + { + logger.debug( + MsOutlookAddrBookContactQuery.class + .getSimpleName() + + "#onMailUser(long)", + e); + } + return false; + } } - } - }); + }); + } } /**