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