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.

cusax-fix
Lyubomir Marinov 14 years ago
parent 7494f7d9df
commit 30695f035a

@ -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

@ -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.

@ -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;
}

@ -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;
}

@ -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

@ -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 <tt>ContactQuery</tt> for the Address Book of Microsoft Outlook.
@ -21,6 +22,13 @@
public class MsOutlookAddrBookContactQuery
extends AsyncContactQuery<MsOutlookAddrBookContactSourceService>
{
/**
* The <tt>Logger</tt> used by the <tt>MsOutlookAddrBookContactQuery</tt>
* 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 <tt>PR_DISPLAY_NAME</tt> 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;
}
}
}
});
});
}
}
/**

Loading…
Cancel
Save