1018 lines
21 KiB
C
1018 lines
21 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1996 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
mapiutil.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Utility functions for working with MAPI
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Windows NT fax driver user interface
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
09/18/96 -davidx-
|
|||
|
Created it.
|
|||
|
|
|||
|
mm/dd/yy -author-
|
|||
|
description
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "faxui.h"
|
|||
|
|
|||
|
#define INITGUID
|
|||
|
#define USES_IID_IMAPISession
|
|||
|
#define USES_IID_IDistList
|
|||
|
|
|||
|
#include "mapiwrap.h"
|
|||
|
|
|||
|
//
|
|||
|
// Global variables used for accessing MAPI services
|
|||
|
//
|
|||
|
|
|||
|
static HINSTANCE hInstMapi = NULL;
|
|||
|
static INT mapiRefCount = 0;
|
|||
|
|
|||
|
ULONG lhMapiSession = 0;
|
|||
|
LPMAPISESSION lpMapiSession = NULL;
|
|||
|
LPMAPILOGON lpfnMAPILogon = NULL;
|
|||
|
LPMAPILOGOFF lpfnMAPILogoff = NULL;
|
|||
|
LPMAPIADDRESS lpfnMAPIAddress = NULL;
|
|||
|
LPMAPIFREEBUFFER lpfnMAPIFreeBuffer = NULL;
|
|||
|
LPSCMAPIXFROMSMAPI lpfnScMAPIXFromSMAPI = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Function to insert a recipient into the recipient list view
|
|||
|
//
|
|||
|
|
|||
|
BOOL
|
|||
|
InsertRecipientListItem(
|
|||
|
HWND hwndLV,
|
|||
|
PRECIPIENT pRecipient
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
IsMapiAvailable(
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Determine whether MAPI is available
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if MAPI is installed on the system, FALSE otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return GetProfileInt(TEXT("MAIL"), TEXT("MAPI"), 0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
DoMapiLogon(
|
|||
|
HWND hDlg
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Logon MAPI to in order to access address book
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hDlg - Handle to the send fax wizard window
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if successful, FALSE if there is an error
|
|||
|
|
|||
|
!!!BUGBUG:
|
|||
|
|
|||
|
MAPI is not Unicoded enabled on NT.
|
|||
|
Must revisit this code once that's fixed.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#define MAX_PROFILE_NAME 256
|
|||
|
|
|||
|
{
|
|||
|
LPTSTR profileName;
|
|||
|
CHAR ansiProfileName[MAX_PROFILE_NAME];
|
|||
|
HKEY hRegKey;
|
|||
|
ULONG status;
|
|||
|
|
|||
|
//
|
|||
|
// Retrieve the fax profile name stored in registry
|
|||
|
//
|
|||
|
|
|||
|
profileName[0] = NUL;
|
|||
|
|
|||
|
if (hRegKey = GetUserInfoRegKey(REGKEY_FAX_SETUP, REG_READONLY)) {
|
|||
|
|
|||
|
profileName = GetRegistryString(hRegKey, REGVAL_FAX_PROFILE, TEXT(""));
|
|||
|
|
|||
|
RegCloseKey(hRegKey);
|
|||
|
|
|||
|
if (!profileName || !*profileName) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
} else {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
Verbose(("Fax profile name: %ws\n", profileName));
|
|||
|
|
|||
|
//
|
|||
|
// Attempt to logon to MAPI - We need to convert MAPI profile name to ANSI
|
|||
|
// here because MAPI is not Unicode enabled.
|
|||
|
//
|
|||
|
|
|||
|
if (! WideCharToMultiByte(CP_ACP,
|
|||
|
0,
|
|||
|
profileName,
|
|||
|
-1,
|
|||
|
ansiProfileName,
|
|||
|
MAX_PROFILE_NAME,
|
|||
|
NULL,
|
|||
|
NULL))
|
|||
|
{
|
|||
|
Error(("WideCharToMultiByte failed: %d\n", GetLastError()));
|
|||
|
MemFree(profileName);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
MemFree(profileName);
|
|||
|
|
|||
|
status = lpfnMAPILogon((ULONG) hDlg,
|
|||
|
ansiProfileName,
|
|||
|
NULL,
|
|||
|
MAPI_LOGON_UI,
|
|||
|
0,
|
|||
|
&lhMapiSession);
|
|||
|
|
|||
|
//
|
|||
|
// If a profile name is specified and logon failed,
|
|||
|
// then try again without a profile.
|
|||
|
//
|
|||
|
|
|||
|
if (status != SUCCESS_SUCCESS && !IsEmptyString(ansiProfileName)) {
|
|||
|
|
|||
|
ansiProfileName[0] = NUL;
|
|||
|
|
|||
|
status = lpfnMAPILogon((ULONG) hDlg,
|
|||
|
ansiProfileName,
|
|||
|
NULL,
|
|||
|
MAPI_LOGON_UI,
|
|||
|
0,
|
|||
|
&lhMapiSession);
|
|||
|
}
|
|||
|
|
|||
|
if (status != SUCCESS_SUCCESS) {
|
|||
|
|
|||
|
Error(("MAPILogon failed: %d\n", status));
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Convert simple MAPI session handle to extended MAPI session pointer
|
|||
|
//
|
|||
|
|
|||
|
if (FAILED(lpfnScMAPIXFromSMAPI(lhMapiSession, 0, &IID_IMAPISession, &lpMapiSession))) {
|
|||
|
|
|||
|
Error(("ScMAPIXFromSMAPI failed: %d\n", GetLastError()));
|
|||
|
lpfnMAPILogoff(lhMapiSession, 0, 0, 0);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
InitMapiService(
|
|||
|
HWND hDlg
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Initialize Simple MAPI services if necessary
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hDlg - Handle to the send fax wizard window
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if successful, FALSE otherwise
|
|||
|
|
|||
|
NOTE:
|
|||
|
|
|||
|
Every successful call to this function must be balanced
|
|||
|
by a call to DeinitMapiService.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BOOL result;
|
|||
|
|
|||
|
EnterDrvSem();
|
|||
|
|
|||
|
//
|
|||
|
// Load MAPI32.DLL into memory if necessary
|
|||
|
//
|
|||
|
|
|||
|
if ((hInstMapi == NULL) &&
|
|||
|
(hInstMapi = LoadLibrary(TEXT("MAPI32.DLL"))))
|
|||
|
{
|
|||
|
//
|
|||
|
// Get pointers to various Simple MAPI functions
|
|||
|
//
|
|||
|
|
|||
|
lpfnMAPILogon = (LPMAPILOGON) GetProcAddress(hInstMapi, "MAPILogon");
|
|||
|
lpfnMAPILogoff = (LPMAPILOGOFF) GetProcAddress(hInstMapi, "MAPILogoff");
|
|||
|
lpfnMAPIAddress = (LPMAPIADDRESS) GetProcAddress(hInstMapi, "MAPIAddress");
|
|||
|
lpfnMAPIFreeBuffer = (LPMAPIFREEBUFFER) GetProcAddress(hInstMapi, "MAPIFreeBuffer");
|
|||
|
lpfnScMAPIXFromSMAPI = (LPSCMAPIXFROMSMAPI) GetProcAddress(hInstMapi, "ScMAPIXFromSMAPI");
|
|||
|
|
|||
|
//
|
|||
|
// Begins a simple MAPI session and obtain session handle and pointer
|
|||
|
//
|
|||
|
|
|||
|
if (lpfnMAPILogon == NULL ||
|
|||
|
lpfnMAPILogoff == NULL ||
|
|||
|
lpfnMAPIAddress == NULL ||
|
|||
|
lpfnMAPIFreeBuffer == NULL ||
|
|||
|
lpfnScMAPIXFromSMAPI == NULL ||
|
|||
|
!DoMapiLogon(hDlg))
|
|||
|
{
|
|||
|
//
|
|||
|
// Clean up properly in case of error
|
|||
|
//
|
|||
|
|
|||
|
lhMapiSession = 0;
|
|||
|
lpMapiSession = NULL;
|
|||
|
FreeLibrary(hInstMapi);
|
|||
|
hInstMapi = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (result = (hInstMapi != NULL))
|
|||
|
mapiRefCount++;
|
|||
|
else
|
|||
|
Error(("InitMapiService failed: %d", GetLastError()));
|
|||
|
|
|||
|
LeaveDrvSem();
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
DeinitMapiService(
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Deinitialize Simple MAPI services if necessary
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
EnterDrvSem();
|
|||
|
|
|||
|
Assert(hInstMapi != NULL);
|
|||
|
|
|||
|
if (mapiRefCount > 0 && --mapiRefCount == 0 && hInstMapi != NULL) {
|
|||
|
|
|||
|
if (lpMapiSession)
|
|||
|
MAPICALL(lpMapiSession)->Release(lpMapiSession);
|
|||
|
|
|||
|
if (lhMapiSession)
|
|||
|
lpfnMAPILogoff(lhMapiSession, 0, 0, 0);
|
|||
|
|
|||
|
lhMapiSession = 0;
|
|||
|
lpMapiSession = NULL;
|
|||
|
FreeLibrary(hInstMapi);
|
|||
|
hInstMapi = NULL;
|
|||
|
}
|
|||
|
|
|||
|
LeaveDrvSem();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
LPSTR
|
|||
|
DupStringUnicodeToAnsi(
|
|||
|
LPWSTR pUnicodeStr
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Convert a Unicode string to a multi-byte string
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pUnicodeStr - Pointer to the Unicode string to be duplicated
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Pointer to the duplicated multi-byte string
|
|||
|
|
|||
|
NOTE:
|
|||
|
|
|||
|
This is only need because MAPI is not Unicode enabled on NT.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
INT nChar;
|
|||
|
LPSTR pAnsiStr;
|
|||
|
|
|||
|
//
|
|||
|
// Figure out how much memory to allocate for the multi-byte string
|
|||
|
//
|
|||
|
|
|||
|
if (! (nChar = WideCharToMultiByte(CP_ACP, 0, pUnicodeStr, -1, NULL, 0, NULL, NULL)) ||
|
|||
|
! (pAnsiStr = MemAlloc(nChar)))
|
|||
|
{
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Convert Unicode string to multi-byte string
|
|||
|
//
|
|||
|
|
|||
|
WideCharToMultiByte(CP_ACP, 0, pUnicodeStr, -1, pAnsiStr, nChar, NULL, NULL);
|
|||
|
return pAnsiStr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
CallMapiAddress(
|
|||
|
HWND hDlg,
|
|||
|
PUSERMEM pUserMem,
|
|||
|
PULONG pnRecips,
|
|||
|
lpMapiRecipDesc *ppRecips
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Call MAPIAddress to display the address dialog
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hDlg - Handle to the send fax wizard window
|
|||
|
pUserMem - Points to user mode memory structure
|
|||
|
pnRecips - Returns number of selected recipients
|
|||
|
ppRecips - Returns information about selected recipients
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if successful, FALSE if there is an error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
lpMapiRecipDesc pRecips;
|
|||
|
PRECIPIENT pRecipient;
|
|||
|
ULONG nRecips, index;
|
|||
|
LONG status;
|
|||
|
|
|||
|
//
|
|||
|
// Convert the recipient list to an array of MapiRecipDesc
|
|||
|
//
|
|||
|
|
|||
|
nRecips = 0;
|
|||
|
pRecipient = pUserMem->pRecipients;
|
|||
|
|
|||
|
while (pRecipient) {
|
|||
|
|
|||
|
nRecips++;
|
|||
|
pRecipient = pRecipient->pNext;
|
|||
|
}
|
|||
|
|
|||
|
if (nRecips == 0)
|
|||
|
pRecips = NULL;
|
|||
|
else if (! (pRecips = MemAllocZ(nRecips * sizeof(MapiRecipDesc))))
|
|||
|
return FALSE;
|
|||
|
|
|||
|
status = SUCCESS_SUCCESS;
|
|||
|
index = nRecips;
|
|||
|
pRecipient = pUserMem->pRecipients;
|
|||
|
|
|||
|
Verbose(("Recipients passed to MAPIAddress:\n"));
|
|||
|
|
|||
|
while (index-- > 0) {
|
|||
|
|
|||
|
Assert(pRecipient != NULL);
|
|||
|
|
|||
|
pRecips[index].ulRecipClass = MAPI_TO;
|
|||
|
pRecips[index].lpszName = DupStringUnicodeToAnsi(pRecipient->pName);
|
|||
|
pRecips[index].lpszAddress = DupStringUnicodeToAnsi(pRecipient->pAddress);
|
|||
|
|
|||
|
if (!pRecips[index].lpszName || !pRecips[index].lpszAddress) {
|
|||
|
|
|||
|
status = MAPI_E_INSUFFICIENT_MEMORY;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
Verbose((" %s, %s\n", pRecips[index].lpszName, pRecips[index].lpszAddress));
|
|||
|
|
|||
|
pRecipient = pRecipient->pNext;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Call MAPI to display the address book dialog
|
|||
|
//
|
|||
|
|
|||
|
if (status == SUCCESS_SUCCESS) {
|
|||
|
|
|||
|
status = lpfnMAPIAddress(lhMapiSession,
|
|||
|
(ULONG) hDlg,
|
|||
|
NULL,
|
|||
|
1,
|
|||
|
NULL,
|
|||
|
nRecips,
|
|||
|
pRecips,
|
|||
|
MAPI_LOGON_UI,
|
|||
|
0,
|
|||
|
pnRecips,
|
|||
|
ppRecips);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Free the input recipient list after coming back from MAPI
|
|||
|
//
|
|||
|
|
|||
|
for (index=0; index < nRecips; index++) {
|
|||
|
|
|||
|
MemFree(pRecips[index].lpszName);
|
|||
|
MemFree(pRecips[index].lpszAddress);
|
|||
|
}
|
|||
|
|
|||
|
MemFree(pRecips);
|
|||
|
|
|||
|
if (status != SUCCESS_SUCCESS) {
|
|||
|
|
|||
|
Error(("MAPIAddress failed: %d\n", status));
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
INT
|
|||
|
InterpretSimpleAddress(
|
|||
|
PUSERMEM pUserMem,
|
|||
|
HWND hwndLV,
|
|||
|
LPSTR pRecipName,
|
|||
|
LPSTR pRecipAddress
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Process a simple address entry and insert it into the recipient list view
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pUserMem - Points to user mode memory structure
|
|||
|
hwndLV - Handle to the recipient list view window
|
|||
|
pRecipName - Specifies the name of the recipient
|
|||
|
pRecipName - Specifies the recipient's address
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
-1 : if there is an error
|
|||
|
0 : if the address entry is ignored
|
|||
|
1 : if successful
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LPTSTR pName, pAddress;
|
|||
|
INT nameLen, addrLen;
|
|||
|
PRECIPIENT pRecipient;
|
|||
|
|
|||
|
//
|
|||
|
// Allocate memory to hold recipient information
|
|||
|
//
|
|||
|
|
|||
|
if (pRecipName == NULL) {
|
|||
|
|
|||
|
Error(("Recipient name is NULL!\n"));
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
nameLen = strlen(pRecipName) + 1;
|
|||
|
addrLen = strlen(pRecipAddress) + 1;
|
|||
|
|
|||
|
pRecipient = MemAllocZ(sizeof(RECIPIENT));
|
|||
|
pName = MemAllocZ(nameLen * sizeof(TCHAR));
|
|||
|
pAddress = MemAllocZ(addrLen * sizeof(TCHAR));
|
|||
|
|
|||
|
if (!pRecipient || !pName || !pAddress) {
|
|||
|
|
|||
|
Error(("Memory allocation failed\n"));
|
|||
|
MemFree(pRecipient);
|
|||
|
MemFree(pName);
|
|||
|
MemFree(pAddress);
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
pRecipient->pName = pName;
|
|||
|
pRecipient->pAddress = pAddress;
|
|||
|
|
|||
|
//
|
|||
|
// Convert name and address from Ansi string to Unicode string
|
|||
|
//
|
|||
|
|
|||
|
MultiByteToWideChar(CP_ACP, 0, pRecipName, -1, pName, nameLen);
|
|||
|
MultiByteToWideChar(CP_ACP, 0, pRecipAddress, -1, pAddress, addrLen);
|
|||
|
|
|||
|
//
|
|||
|
// Add this recipient to the recipient list
|
|||
|
//
|
|||
|
|
|||
|
if (InsertRecipientListItem(hwndLV, pRecipient)) {
|
|||
|
|
|||
|
pRecipient->pNext = pUserMem->pRecipients;
|
|||
|
pUserMem->pRecipients = pRecipient;
|
|||
|
return 1;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
FreeRecipient(pRecipient);
|
|||
|
return -1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
INT
|
|||
|
DetermineAddressType(
|
|||
|
LPSTR pAddress
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Determine the type of an address
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pAddress - Points to an address or address type string
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
One of the ADDRTYPE_* constants below
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#define ADDRTYPE_NULL 0
|
|||
|
#define ADDRTYPE_FAX 1
|
|||
|
#define ADDRTYPE_MAPIPDL 2
|
|||
|
#define ADDRTYPE_UNKNOWN 3
|
|||
|
|
|||
|
#define ADDRTYPESTR_FAX "FAX"
|
|||
|
#define ADDRTYPESTR_MAPIPDL "MAPIPDL"
|
|||
|
|
|||
|
{
|
|||
|
INT n;
|
|||
|
LPSTR p;
|
|||
|
|
|||
|
//
|
|||
|
// Check if the input string is NULL
|
|||
|
//
|
|||
|
|
|||
|
if (pAddress == NULL)
|
|||
|
return ADDRTYPE_NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Check if the address type is FAX
|
|||
|
//
|
|||
|
|
|||
|
p = ADDRTYPESTR_FAX;
|
|||
|
n = strlen(p);
|
|||
|
|
|||
|
if ((_strnicmp(pAddress, p, n) == EQUAL_STRING) &&
|
|||
|
(pAddress[n] == NUL || pAddress[n] == ':'))
|
|||
|
{
|
|||
|
return ADDRTYPE_FAX;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check if the address type is MAPIPDL
|
|||
|
//
|
|||
|
|
|||
|
p = ADDRTYPESTR_MAPIPDL;
|
|||
|
n = strlen(p);
|
|||
|
|
|||
|
if ((_strnicmp(pAddress, p, n) == EQUAL_STRING) &&
|
|||
|
(pAddress[n] == NUL || pAddress[n] == ':'))
|
|||
|
{
|
|||
|
return ADDRTYPE_MAPIPDL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Address type is something that we don't understand
|
|||
|
//
|
|||
|
|
|||
|
return ADDRTYPE_UNKNOWN;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
LPSTR
|
|||
|
ConcatTypeWithAddress(
|
|||
|
LPSTR pType,
|
|||
|
LPSTR pAddress
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Helper function to concatenate address type in front of the address
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pType - Points to address type string
|
|||
|
pAddress - Points to address string
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Pointer to concatenated address, NULL if there is an error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
INT length;
|
|||
|
LPSTR p;
|
|||
|
|
|||
|
//
|
|||
|
// Sanity check
|
|||
|
//
|
|||
|
|
|||
|
if (pType == NULL || pAddress == NULL)
|
|||
|
return NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Calculate the length of the concatenated string
|
|||
|
//
|
|||
|
|
|||
|
length = strlen(pType) + 1 + strlen(pAddress) + 1;
|
|||
|
|
|||
|
//
|
|||
|
// Concatenate type with address, separated by a colon
|
|||
|
//
|
|||
|
|
|||
|
if (p = MemAllocZ(length))
|
|||
|
sprintf(p, "%s:%s", pType, pAddress);
|
|||
|
|
|||
|
return p;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
INT
|
|||
|
InterpretDistList(
|
|||
|
PUSERMEM pUserMem,
|
|||
|
HWND hwndLV,
|
|||
|
ULONG ulEIDSize,
|
|||
|
PVOID pEntryID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Expand a distribution list entry and insert the individual
|
|||
|
addresses into the recipient list view.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pUserMem - Points to user mode memory structure
|
|||
|
hwndLV - Handle to the recipient list view window
|
|||
|
ulEIDSize - Specifies the size of entry ID
|
|||
|
pEntryID - Points to entry ID data
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
> 0 : total number of useful address entries
|
|||
|
= 0 : no useful address entry found
|
|||
|
< 0 : if there is an error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#define EXIT_IF_FAILED(hr) { if (FAILED(hr)) goto ExitDistList; }
|
|||
|
|
|||
|
{
|
|||
|
LPDISTLIST pDistList = NULL;
|
|||
|
LPMAPITABLE pMapiTable = NULL;
|
|||
|
LPSRowSet pRows = NULL;
|
|||
|
ULONG ulObjType, cRows;
|
|||
|
HRESULT hr;
|
|||
|
INT entriesUsed = 0;
|
|||
|
|
|||
|
static SizedSPropTagArray(4, sPropTags) =
|
|||
|
{
|
|||
|
4,
|
|||
|
{
|
|||
|
PR_ENTRYID,
|
|||
|
PR_ADDRTYPE_A,
|
|||
|
PR_DISPLAY_NAME_A,
|
|||
|
PR_EMAIL_ADDRESS_A
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
//
|
|||
|
// Deal with distribution lists
|
|||
|
//
|
|||
|
|
|||
|
if (ulEIDSize == 0 || pEntryID == NULL) {
|
|||
|
|
|||
|
Error(("Unusable address entry\n"));
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Open the recipient entry
|
|||
|
//
|
|||
|
|
|||
|
hr = MAPICALL(lpMapiSession)->OpenEntry(lpMapiSession,
|
|||
|
ulEIDSize,
|
|||
|
pEntryID,
|
|||
|
&IID_IDistList,
|
|||
|
MAPI_DEFERRED_ERRORS,
|
|||
|
&ulObjType,
|
|||
|
(LPUNKNOWN *) &pDistList);
|
|||
|
|
|||
|
EXIT_IF_FAILED(hr);
|
|||
|
|
|||
|
//
|
|||
|
// Get the contents table of the address entry
|
|||
|
//
|
|||
|
|
|||
|
hr = MAPICALL(pDistList)->GetContentsTable(pDistList,
|
|||
|
MAPI_DEFERRED_ERRORS,
|
|||
|
&pMapiTable);
|
|||
|
|
|||
|
EXIT_IF_FAILED(hr);
|
|||
|
|
|||
|
//
|
|||
|
// Limit the query to only the properties we're interested in
|
|||
|
//
|
|||
|
|
|||
|
hr = MAPICALL(pMapiTable)->SetColumns(pMapiTable, (LPSPropTagArray) &sPropTags, 0);
|
|||
|
|
|||
|
EXIT_IF_FAILED(hr);
|
|||
|
|
|||
|
//
|
|||
|
// Get the total number of rows
|
|||
|
//
|
|||
|
|
|||
|
hr = MAPICALL(pMapiTable)->GetRowCount(pMapiTable, 0, &cRows);
|
|||
|
|
|||
|
EXIT_IF_FAILED(hr);
|
|||
|
|
|||
|
//
|
|||
|
// Get the individual entries of the distribution list
|
|||
|
//
|
|||
|
|
|||
|
hr = MAPICALL(pMapiTable)->SeekRow(pMapiTable, BOOKMARK_BEGINNING, 0, NULL);
|
|||
|
|
|||
|
EXIT_IF_FAILED(hr);
|
|||
|
|
|||
|
hr = MAPICALL(pMapiTable)->QueryRows(pMapiTable, cRows, 0, &pRows);
|
|||
|
|
|||
|
EXIT_IF_FAILED(hr);
|
|||
|
|
|||
|
hr = S_OK;
|
|||
|
entriesUsed = 0;
|
|||
|
|
|||
|
if (pRows && pRows->cRows) {
|
|||
|
|
|||
|
//
|
|||
|
// Handle each entry of the distribution list in turn:
|
|||
|
// for simple entries, call InterpretSimpleAddress
|
|||
|
// for embedded distribution list, call this function recursively
|
|||
|
//
|
|||
|
|
|||
|
for (cRows = 0; cRows < pRows->cRows; cRows++) {
|
|||
|
|
|||
|
LPSPropValue lpProps = pRows->aRow[cRows].lpProps;
|
|||
|
LPSTR pType, pName, pAddress;
|
|||
|
INT result;
|
|||
|
|
|||
|
pType = lpProps[1].Value.lpszA;
|
|||
|
pName = lpProps[2].Value.lpszA;
|
|||
|
pAddress = lpProps[3].Value.lpszA;
|
|||
|
|
|||
|
Verbose((" %s: %s", pType, pName));
|
|||
|
|
|||
|
switch (DetermineAddressType(pType)) {
|
|||
|
|
|||
|
case ADDRTYPE_FAX:
|
|||
|
|
|||
|
if ((pAddress != NULL) &&
|
|||
|
(lpProps[3].ulPropTag == PR_EMAIL_ADDRESS_A) &&
|
|||
|
(pAddress = ConcatTypeWithAddress(pType, pAddress)))
|
|||
|
{
|
|||
|
Verbose((", %s\n", pAddress));
|
|||
|
|
|||
|
result = InterpretSimpleAddress(pUserMem, hwndLV, pName, pAddress);
|
|||
|
MemFree(pAddress);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
Verbose(("\nBad address.\n"));
|
|||
|
result = -1;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case ADDRTYPE_MAPIPDL:
|
|||
|
case ADDRTYPE_NULL:
|
|||
|
|
|||
|
Verbose(("\n"));
|
|||
|
|
|||
|
result = InterpretDistList(pUserMem,
|
|||
|
hwndLV,
|
|||
|
lpProps[0].Value.bin.cb,
|
|||
|
lpProps[0].Value.bin.lpb);
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
Verbose(("\nUnknown address type.\n"));
|
|||
|
result = 0;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (result < 0)
|
|||
|
hr = -1;
|
|||
|
else
|
|||
|
entriesUsed += result;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
ExitDistList:
|
|||
|
|
|||
|
//
|
|||
|
// Perform necessary clean up before returning to caller
|
|||
|
//
|
|||
|
|
|||
|
if (pRows) {
|
|||
|
|
|||
|
for (cRows = 0; cRows < pRows->cRows; cRows++)
|
|||
|
lpfnMAPIFreeBuffer(pRows->aRow[cRows].lpProps);
|
|||
|
|
|||
|
lpfnMAPIFreeBuffer(pRows);
|
|||
|
}
|
|||
|
|
|||
|
if (pMapiTable)
|
|||
|
MAPICALL(pMapiTable)->Release(pMapiTable);
|
|||
|
|
|||
|
if (pDistList)
|
|||
|
MAPICALL(pDistList)->Release(pDistList);
|
|||
|
|
|||
|
if (FAILED(hr)) {
|
|||
|
|
|||
|
Error(("InterpretDistList failed: 0x%x\n", hr));
|
|||
|
return -1;
|
|||
|
|
|||
|
} else
|
|||
|
return entriesUsed;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
InterpretSelectedAddresses(
|
|||
|
HWND hDlg,
|
|||
|
PUSERMEM pUserMem,
|
|||
|
HWND hwndLV,
|
|||
|
ULONG nRecips,
|
|||
|
lpMapiRecipDesc pRecips
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Expand the selected addresses and insert them into the recipient list view
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hDlg - Handle to the send fax wizard window
|
|||
|
pUserMem - Points to user mode memory structure
|
|||
|
hwndLV - Handle to the recipient list view window
|
|||
|
nRecips - Number of selected recipients
|
|||
|
pRecips - Information about selected recipients
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if successful, FALSE if there is an error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
INT discarded = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Remove all existing entries in the recipient list view
|
|||
|
//
|
|||
|
|
|||
|
if (! ListView_DeleteAllItems(hwndLV))
|
|||
|
return FALSE;
|
|||
|
|
|||
|
FreeRecipientList(pUserMem);
|
|||
|
|
|||
|
Verbose(("Recipients returned from MAPIAddress:\n"));
|
|||
|
|
|||
|
for ( ; nRecips--; pRecips++) {
|
|||
|
|
|||
|
INT result;
|
|||
|
|
|||
|
Verbose((" %s, %s\n", pRecips->lpszName, pRecips->lpszAddress));
|
|||
|
|
|||
|
switch (DetermineAddressType(pRecips->lpszAddress)) {
|
|||
|
|
|||
|
case ADDRTYPE_FAX:
|
|||
|
|
|||
|
result = InterpretSimpleAddress(pUserMem,
|
|||
|
hwndLV,
|
|||
|
pRecips->lpszName,
|
|||
|
pRecips->lpszAddress);
|
|||
|
break;
|
|||
|
|
|||
|
case ADDRTYPE_MAPIPDL:
|
|||
|
case ADDRTYPE_NULL:
|
|||
|
|
|||
|
result = InterpretDistList(pUserMem,
|
|||
|
hwndLV,
|
|||
|
pRecips->ulEIDSize,
|
|||
|
pRecips->lpEntryID);
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
Verbose(("Unknown address type.\n"));
|
|||
|
result = 0;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (result <= 0)
|
|||
|
discarded++;
|
|||
|
}
|
|||
|
|
|||
|
if (discarded)
|
|||
|
DisplayMessageDialog(hDlg, 0, 0, IDS_BAD_ADDRESS_TYPE);
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|