aboutsummaryrefslogtreecommitdiffstats
path: root/src/native/addrbook/msoutlook
diff options
context:
space:
mode:
authorLyubomir Marinov <lyubomir.marinov@jitsi.org>2011-12-17 18:46:28 +0000
committerLyubomir Marinov <lyubomir.marinov@jitsi.org>2011-12-17 18:46:28 +0000
commit30695f035a910cb8cb1f9a6d71fdf9fb2fe9d75c (patch)
treeb7b8cd7d97c88b48ff1c2e670e500c8effb050f5 /src/native/addrbook/msoutlook
parent7494f7d9df52a4ce36938db5d038cc0d70ee8aa3 (diff)
downloadjitsi-30695f035a910cb8cb1f9a6d71fdf9fb2fe9d75c.zip
jitsi-30695f035a910cb8cb1f9a6d71fdf9fb2fe9d75c.tar.gz
jitsi-30695f035a910cb8cb1f9a6d71fdf9fb2fe9d75c.tar.bz2
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.
Diffstat (limited to 'src/native/addrbook/msoutlook')
-rw-r--r--src/native/addrbook/msoutlook/Makefile4
-rw-r--r--src/native/addrbook/msoutlook/MsOutlookMAPIHResultException.cxx2
-rw-r--r--src/native/addrbook/msoutlook/net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContactQuery.cxx755
-rw-r--r--src/native/addrbook/msoutlook/net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContactSourceService.cxx111
4 files changed, 776 insertions, 96 deletions
diff --git a/src/native/addrbook/msoutlook/Makefile b/src/native/addrbook/msoutlook/Makefile
index 6b85fc2..a594e5a 100644
--- a/src/native/addrbook/msoutlook/Makefile
+++ b/src/native/addrbook/msoutlook/Makefile
@@ -1,8 +1,8 @@
CC = gcc -O2
-OUTLOOK_MAPI_HEADERS ?= C:/Users/lyubomir/Downloads/Outlook2010MAPIHeaders
+OUTLOOK_MAPI_HEADERS ?= C:/Users/lyub0m1r/Downloads/Outlook2010MAPIHeaders
TARGET_BASENAME = jmsoutlookaddrbook
-ARCH = $(shell $(CC) -dumpmachine | sed -e s/x86_64-.*/-64/ -e s/i.86-.*// -e s/mingw32//)
+ARCH ?= $(shell $(CC) -dumpmachine | sed -e s/x86_64-.*/-64/ -e s/i.86-.*// -e s/mingw32//)
ifeq "$(ARCH)" "-64"
JAVA_HOME ?= C:/PROGRA~1/jdk
else
diff --git a/src/native/addrbook/msoutlook/MsOutlookMAPIHResultException.cxx b/src/native/addrbook/msoutlook/MsOutlookMAPIHResultException.cxx
index 4c090a3..8123b2a 100644
--- a/src/native/addrbook/msoutlook/MsOutlookMAPIHResultException.cxx
+++ b/src/native/addrbook/msoutlook/MsOutlookMAPIHResultException.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.
diff --git a/src/native/addrbook/msoutlook/net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContactQuery.cxx b/src/native/addrbook/msoutlook/net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContactQuery.cxx
index d6bc0f0..861d485 100644
--- a/src/native/addrbook/msoutlook/net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContactQuery.cxx
+++ b/src/native/addrbook/msoutlook/net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContactQuery.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.
@@ -11,24 +11,69 @@
#include "MsOutlookMAPI.h"
#include "MsOutlookMAPIHResultException.h"
+#include <stdio.h>
#include <string.h>
-#define WIN32_MEAN_AND_LEAN
-#include <windows.h>
+#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,
+ "<init>", "(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 20f9a3c..3e7aa2c 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;
}