Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

4439 lines
152 KiB

/*
* PAB.C
*
* Migrate PAB <-> WAB
*
* Copyright 1996-1997 Microsoft Corporation. All Rights Reserved.
*/
#include "_comctl.h"
#include <windows.h>
#include <commctrl.h>
#include <mapix.h>
#include <wab.h>
#include <wabguid.h>
#include <wabdbg.h>
#include <wabmig.h>
#include <emsabtag.h>
#include "..\..\wab32res\resrc2.h"
#include "dbgutil.h"
#include "wabimp.h"
#include <shlwapi.h>
void StateImportNextMU(HWND hwnd);
void StateImportDL(HWND hwnd);
void StateImportNextDL(HWND hwnd);
void StateImportFinish(HWND hwnd);
//void StateImportMU(HWND hwnd);
void StateImportMU(HWND hwnd);
void StateImportError(HWND hwnd);
void StateImportCancel(HWND hwnd);
BOOL HandleImportError(HWND hwnd, ULONG ids, HRESULT hResult, LPTSTR lpDisplayName,
LPTSTR lpEmailAddress, LPWAB_IMPORT_OPTIONS lpImportOptions);
HRESULT ImportEntry(HWND hwnd,
LPADRBOOK lpAdrBookMAPI,
LPABCONT lpContainerWAB,
LPSPropValue lpCreateEIDsWAB,
ULONG ulObjectType,
LPENTRYID lpEID,
ULONG cbEID,
LPENTRYID * lppEIDWAB,
LPULONG lpcbEIDWAB,
BOOL fInDL,
BOOL fForceReplace);
const UCHAR szQuote[] = "\"";
LPPROP_NAME lpImportMapping = NULL;
BOOL fError = FALSE;
LPWABOBJECT lpWABObject = NULL;
LPMAPISESSION lpMAPISession = NULL;
LPADRBOOK lpAdrBookWAB = NULL, lpAdrBookMAPI = NULL;
LPSPropValue lpCreateEIDsWAB = NULL, lpCreateEIDsMAPI = NULL;
LPABCONT lpContainerWAB = NULL, lpContainerMAPI = NULL;
LPMAPITABLE lpContentsTableWAB = NULL, lpContentsTableMAPI = NULL;
ULONG ulcEntries = 0, ulcDone = 0;
PAB_STATE State = STATE_IMPORT_FINISH;
LPTSTR lpszWABFileName = NULL;
LPWAB_PROGRESS_CALLBACK lpfnProgressCB = NULL;
LPWAB_IMPORT_OPTIONS lpImportOptions = NULL;
LPWAB_EXPORT_OPTIONS lpExportOptions = NULL;
/*
- The following IDs and tags are for the conferencing named properties
-
- The GUID for these props is PS_Conferencing
*/
DEFINE_OLEGUID(PS_Conferencing, 0x00062004, 0, 0);
#define CONF_SERVERS 0x8056
#define OLK_NAMEDPROPS_START CONF_SERVERS
ULONG PR_SERVERS;
enum _ConferencingTags
{
prWABConfServers = 0,
prWABConfMax
};
SizedSPropTagArray(prWABConfMax, ptaUIDetlsPropsConferencing);
HRESULT HrLoadPrivateWABPropsForCSV(LPADRBOOK );
// end conferencing duplication
/***************************************************************************
Name : NewState
Purpose :
Parameters: hwnd = window handle of Dialog (currently unused)
NewState = new state to set
Returns : none
Comment :
***************************************************************************/
__inline void NewState(HWND hwnd, PAB_STATE NewState) {
// Old version
// PostMessage(hwnd, WM_COMMAND, NewState, 0);
State = NewState;
UNREFERENCED_PARAMETER(hwnd);
}
/***************************************************************************
Name : SetDialogMessage
Purpose : Sets the message text for the dialog box item IDC_Message
Parameters: hwnd = window handle of dialog
ids = stringid of message resource
Returns : none
***************************************************************************/
void SetDialogMessage(HWND hwnd, int ids) {
TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
WAB_PROGRESS Progress = {0};
Assert(lpfnProgressCB);
if (lpfnProgressCB && LoadString(hInst, ids, szBuffer, ARRAYSIZE(szBuffer))) {
DebugTrace("Status Message: %s\n", szBuffer);
Progress.lpText = szBuffer;
lpfnProgressCB(hwnd, &Progress);
} else {
DebugTrace("Cannot load resource string %u\n", ids);
Assert(FALSE);
}
}
/***************************************************************************
Name : SetDialogProgress
Purpose : Sets progress bar
Parameters: hwnd = window handle of dialog
ulTotal = total entries
ulDone = finished entries
Returns : none
***************************************************************************/
void SetDialogProgress(HWND hwnd, ULONG ulTotal, ULONG ulDone) {
WAB_PROGRESS Progress = {0};
Assert(lpfnProgressCB);
if (lpfnProgressCB) {
Progress.denominator = ulTotal;
Progress.numerator = ulDone;
lpfnProgressCB(hwnd, &Progress);
}
}
/***************************************************************************
Name : AddEntryToImportList
Purpose : Checks this entry against our "seen" list and adds it.
Parameters: cbEID = size of lpEID
lpEID -> EntryID of entry
lplIndex -> returned list index (or -1 on error)
Returns : TRUE if entry already exists
Comment : Caller must mark the WAB entry!
***************************************************************************/
#define GROW_SIZE 10
BOOL AddEntryToImportList(ULONG cbEID, LPENTRYID lpEID, LPLONG lplIndex) {
ULONG i;
LPENTRY_SEEN lpEntrySeen;
if (cbEID && lpEID) {
for (i = 0; i < ulEntriesSeen; i++) {
if (cbEID == lpEntriesSeen[i].sbinPAB.cb && (! memcmp(lpEID, lpEntriesSeen[i].sbinPAB.lpb, cbEID))) {
// This one's in the list
*lplIndex = i;
// If cb 0, we must have recursed and are replacing, so this one is not a dup.
return(lpEntriesSeen[i].sbinWAB.cb != 0);
}
}
// Add to the end of the list
if (++ulEntriesSeen > ulMaxEntries) {
// Grow the array.
ulMaxEntries += GROW_SIZE;
if (lpEntriesSeen) {
if (! (lpEntrySeen = LocalReAlloc(lpEntriesSeen, ulMaxEntries * sizeof(ENTRY_SEEN), LMEM_MOVEABLE | LMEM_ZEROINIT))) {
DebugTrace("LocalReAlloc(%u) -> %u\n", ulMaxEntries * sizeof(ENTRY_SEEN), GetLastError());
goto error;
}
lpEntriesSeen = lpEntrySeen;
} else {
if (! (lpEntriesSeen = LocalAlloc(LPTR, ulMaxEntries * sizeof(ENTRY_SEEN)))) {
DebugTrace("LocalAlloc(%u) -> %u\n", ulMaxEntries * sizeof(ENTRY_SEEN), GetLastError());
goto error;
}
}
}
lpEntrySeen = &lpEntriesSeen[ulEntriesSeen - 1];
// Allocate space for data
lpEntrySeen->sbinPAB.cb = cbEID;
if (! (lpEntrySeen->sbinPAB.lpb = LocalAlloc(LPTR, cbEID))) {
DebugTrace("LocalAlloc(%u) -> %u\n", cbEID, GetLastError());
goto error;
}
// Mark as unknown WAB entry
lpEntrySeen->sbinWAB.cb = 0;
lpEntrySeen->sbinWAB.lpb = 0;
// Copy in the data
CopyMemory(lpEntrySeen->sbinPAB.lpb, lpEID, cbEID);
*lplIndex = i;
}
return(FALSE);
error:
// undo the damage...
--ulEntriesSeen;
ulMaxEntries -= GROW_SIZE;
*lplIndex = -1; // error
if (! lpEntriesSeen) {
ulEntriesSeen = 0; // pointer is null now, back to square one.
ulMaxEntries = 0;
}
return(FALSE);
}
/***************************************************************************
Name : MarkWABEntryInList
Purpose : Marks the WAB entry fields in the list node
Parameters: cbEID = size of lpEID
lpEID -> EntryID of entry
lIndex = list index (or -1 on error)
Returns : none
Comment :
***************************************************************************/
void MarkWABEntryInList(ULONG cbEID, LPENTRYID lpEID, LONG lIndex) {
if (lIndex != -1 && cbEID) {
if (! (lpEntriesSeen[lIndex].sbinWAB.lpb = LocalAlloc(LPTR, cbEID))) {
DebugTrace("LocalAlloc(%u) -> %u\n", cbEID, GetLastError());
// leave it null
} else {
lpEntriesSeen[lIndex].sbinWAB.cb = cbEID;
// Copy in the data
CopyMemory(lpEntriesSeen[lIndex].sbinWAB.lpb, lpEID, cbEID);
}
}
}
/***************************************************************************
Name : StateImportMU
Purpose : Start the migration of MailUsers
Parameters: hwnd = window handle of Import Dialog
lpszFileName - FileName of WAB File to open
Returns : none
Comment : Login to MAPI
Open the WAB
Open the MAPI AB
Open the WAB container
Get the MAPI PAB contents table
Restrict it to PR_OBJECTTYPE == MAPI_MAILUSER
Post new state(STATE_NEXT_MU)
***************************************************************************/
void StateImportMU(HWND hwnd) {
HRESULT hResult;
ULONG ulFlags;
ULONG cbPABEID, cbWABEID;
LPENTRYID lpPABEID = NULL;
ULONG ulObjType;
ULONG_PTR ulUIParam = (ULONG_PTR)(void *)hwnd;
SRestriction restrictObjectType;
SPropValue spvObjectType;
ULONG cProps;
TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
WAB_PARAM wp = {0};
LPWAB_PARAM lpwp = NULL;
//
// Logon to MAPI and open the MAPI Address book, if one exists
//
DebugTrace(">>> STATE_IMPORT_MU\n");
SetDialogMessage(hwnd, IDS_STATE_LOGGING_IN);
if (FAILED(hResult = MAPIInitialize(NULL))) {
DebugTrace("MAPIInitialize -> %x\n", GetScode(hResult));
switch (GetScode(hResult)) {
case MAPI_E_NOT_ENOUGH_MEMORY:
SetDialogMessage(hwnd, IDS_ERROR_NOT_ENOUGH_MEMORY);
break;
case MAPI_E_NOT_ENOUGH_DISK:
SetDialogMessage(hwnd, IDS_ERROR_NOT_ENOUGH_DISK);
break;
default:
case MAPI_E_NOT_FOUND:
case MAPI_E_NOT_INITIALIZED:
SetDialogMessage(hwnd, IDS_ERROR_MAPI_DLL_NOT_FOUND);
break;
}
#ifdef OLD_STUFF
ShowWindow(GetDlgItem(hwnd, IDC_Progress), SW_HIDE); // hide progress bar
#endif // OLD_STUFF
fError = TRUE;
hResult = hrSuccess;
goto exit;
}
ulFlags = MAPI_LOGON_UI | MAPI_NO_MAIL | MAPI_EXTENDED;
if (FAILED(hResult = MAPILogonEx(ulUIParam,
NULL,
NULL,
ulFlags,
(LPMAPISESSION FAR *)&lpMAPISession))) {
DebugTrace("MAPILogonEx -> %x\n", GetScode(hResult));
switch (GetScode(hResult)) {
case MAPI_E_USER_CANCEL:
SetDialogMessage(hwnd, IDS_STATE_IMPORT_IDLE);
break;
case MAPI_E_NOT_INITIALIZED:
SetDialogMessage(hwnd, IDS_ERROR_MAPI_DLL_NOT_FOUND);
break;
default:
SetDialogMessage(hwnd, IDS_ERROR_MAPI_LOGON);
break;
}
#ifdef OLD_STUFF
ShowWindow(GetDlgItem(hwnd, IDC_Progress), SW_HIDE); // hide progress bar
#endif // OLD_STUFF
fError = TRUE;
hResult = hrSuccess;
goto exit;
}
if (hResult = lpMAPISession->lpVtbl->OpenAddressBook(lpMAPISession, (ULONG_PTR)(void *)hwnd,
NULL,
0,
&lpAdrBookMAPI)) {
DebugTrace("OpenAddressBook(MAPI) -> %x", GetScode(hResult));
if(FAILED(hResult)) {
goto exit;
}
}
if (! lpAdrBookMAPI) {
DebugTrace("MAPILogonEx didn't return a valid AdrBook object\n");
goto exit;
}
//
// Open the MAPI PAB container
//
// [PaulHi] Raid #63578 1/7/98
// Correctly check return code and provide user error message if
// Exchange PAB cannot be opened.
//
hResult = lpAdrBookMAPI->lpVtbl->GetPAB(lpAdrBookMAPI,
&cbPABEID,
&lpPABEID);
if (HR_FAILED(hResult))
{
DebugTrace("MAPI GetPAB -> %x\n", GetScode(hResult));
goto exit;
}
hResult = lpAdrBookMAPI->lpVtbl->OpenEntry(lpAdrBookMAPI,
cbPABEID, // size of EntryID to open
lpPABEID, // EntryID to open
NULL, // interface
0, // flags
&ulObjType,
(LPUNKNOWN *)&lpContainerMAPI);
if (HR_FAILED(hResult))
{
DebugTrace("MAPI OpenEntry(PAB) -> %x\n", GetScode(hResult));
goto exit;
}
Assert(lpAdrBookWAB);
//
// Open the WAB's PAB container: fills global lpCreateEIDsWAB
//
if (hResult = LoadWABEIDs(lpAdrBookWAB, &lpContainerWAB)) {
goto exit;
}
HrLoadPrivateWABPropsForCSV(lpAdrBookWAB);
//
// All set... now loop through the PAB's entries, copying them to WAB
//
if (HR_FAILED(hResult = lpContainerMAPI->lpVtbl->GetContentsTable(lpContainerMAPI,
0, // ulFlags
&lpContentsTableMAPI))) {
DebugTrace("MAPI GetContentsTable(PAB Table) -> %x\n", GetScode(hResult));
goto exit;
}
// Set the columns to those we're interested in
if (hResult = lpContentsTableMAPI->lpVtbl->SetColumns(lpContentsTableMAPI,
(LPSPropTagArray)&ptaColumns,
0)) {
DebugTrace("MAPI SetColumns(PAB Table) -> %x\n", GetScode(hResult));
goto exit;
}
// Restrict the table to MAPI_MAILUSERs
// If the convenient depth flag was not specified we restrict on
// PR_DEPTH == 1.
spvObjectType.ulPropTag = PR_OBJECT_TYPE;
spvObjectType.Value.l = MAPI_MAILUSER;
restrictObjectType.rt = RES_PROPERTY;
restrictObjectType.res.resProperty.relop = RELOP_EQ;
restrictObjectType.res.resProperty.ulPropTag = PR_OBJECT_TYPE;
restrictObjectType.res.resProperty.lpProp = &spvObjectType;
if (HR_FAILED(hResult = lpContentsTableMAPI->lpVtbl->Restrict(lpContentsTableMAPI,
&restrictObjectType,
0))) {
DebugTrace("MAPI Restrict (MAPI_MAILUSER) -> %x\n", GetScode(hResult));
goto exit;
}
SetDialogMessage(hwnd, IDS_STATE_IMPORT_MU);
// Initialize the Progress Bar
// How many MailUser entries are there?
ulcEntries = CountRows(lpContentsTableMAPI, TRUE);
ulcDone = 0;
DebugTrace("PAB contains %u MailUser entries\n", ulcEntries);
SetDialogProgress(hwnd, ulcEntries, 0);
exit:
if (lpPABEID) {
MAPIFreeBuffer(lpPABEID);
}
// On error, set the state to STATE_ERROR
if (HR_FAILED(hResult))
{
if (GetScode(hResult) == MAPI_E_USER_CANCEL)
{
NewState(hwnd, STATE_IMPORT_CANCEL);
}
else
{
// [PaulHi] 1/7/98 Error reporting is hosed
// Display error message here to the user to ensure they
// get it.
{
TCHAR tszBuffer[MAX_RESOURCE_STRING];
TCHAR tszBufferTitle[MAX_RESOURCE_STRING];
if ( !LoadString(hInst, IDS_STATE_IMPORT_ERROR_NOPAB, tszBuffer, MAX_RESOURCE_STRING-1) )
{
Assert(0);
tszBuffer[0] = '\0';
}
if ( !LoadString(hInst, IDS_APP_TITLE, tszBufferTitle, MAX_RESOURCE_STRING-1) )
{
Assert(0);
tszBufferTitle[0] = '\0';
}
MessageBox(hwnd, tszBuffer, tszBufferTitle, MB_ICONEXCLAMATION | MB_OK);
}
NewState(hwnd, STATE_IMPORT_ERROR);
}
}
else if (fError)
{
NewState(hwnd, STATE_IMPORT_FINISH); // must be logon error
}
else
{
NewState(hwnd, STATE_IMPORT_NEXT_MU);
}
}
/***************************************************************************
Name : StateImportNextMU
Purpose : Migrate the next MailUser object
Parameters: hwnd = window handle of Import Dialog
Returns : none
Comment : QueryRows on the global MAPI contents table
if there was a row
Migrate the entry to the WAB
Re-post STATE_NEXT_MU
else
Post STATE_IMPORT_DL
***************************************************************************/
void StateImportNextMU(HWND hwnd) {
ULONG cRows = 0;
HRESULT hResult;
LPSRowSet lpRow = NULL;
DebugTrace(">>> STATE_NEXT_MU\n");
// Get the next PAB entry
if (hResult = lpContentsTableMAPI->lpVtbl->QueryRows(lpContentsTableMAPI,
1, // one row at a time
0, // ulFlags
&lpRow)) {
DebugTrace("QueryRows -> %x\n", GetScode(hResult));
goto exit;
}
if (lpRow) {
if (cRows = lpRow->cRows) { // Yes, single '='
Assert(lpRow->cRows == 1);
Assert(lpRow->aRow[0].cValues == iptaColumnsMax);
Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].ulPropTag == PR_ENTRYID);
Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].ulPropTag == PR_OBJECT_TYPE);
if (cRows = lpRow->cRows) { // yes, single '='
hResult = ImportEntry(hwnd,
lpAdrBookMAPI,
lpContainerWAB,
lpCreateEIDsWAB,
lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].Value.l,
(LPENTRYID)lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.lpb,
lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.cb,
NULL,
NULL,
FALSE,
FALSE);
// Update Progress Bar
// ignore errors!
SetDialogProgress(hwnd, ulcEntries, ++ulcDone);
if (hResult) {
if (HandleImportError(hwnd,
0,
hResult,
lpRow->aRow[0].lpProps[iptaColumnsPR_DISPLAY_NAME].Value.LPSZ,
PropStringOrNULL(&lpRow->aRow[0].lpProps[iptaColumnsPR_EMAIL_ADDRESS]),
lpImportOptions)) {
hResult = ResultFromScode(MAPI_E_USER_CANCEL);
} else {
hResult = hrSuccess;
}
}
} // else, drop out of loop, we're done.
}
FreeProws(lpRow);
}
exit:
// On error, set the state to STATE_ERROR
if (HR_FAILED(hResult)) {
if (GetScode(hResult) == MAPI_E_USER_CANCEL) {
NewState(hwnd, STATE_IMPORT_CANCEL);
} else {
NewState(hwnd, STATE_IMPORT_ERROR);
}
} else {
if (cRows) {
NewState(hwnd, STATE_IMPORT_NEXT_MU);
} else {
NewState(hwnd, STATE_IMPORT_DL);
}
}
}
/***************************************************************************
Name : StateImportDL
Purpose : Start migration of DISTLIST objects
Parameters: hwnd = window handle of Import Dialog
Returns : none
Comment : Set a new restriction on the contents table, selecting
DISTLIST objects only.
Post STATE_NEXT_DL
***************************************************************************/
void StateImportDL(HWND hwnd) {
HRESULT hResult;
SRestriction restrictObjectType;
SPropValue spvObjectType;
TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
DebugTrace(">>> STATE_IMPORT_DL\n");
// Restrict the table to MAPI_MAILUSERs
// If the convenient depth flag was not specified we restrict on
// PR_DEPTH == 1.
spvObjectType.ulPropTag = PR_OBJECT_TYPE;
spvObjectType.Value.l = MAPI_DISTLIST;
restrictObjectType.rt = RES_PROPERTY;
restrictObjectType.res.resProperty.relop = RELOP_EQ;
restrictObjectType.res.resProperty.ulPropTag = PR_OBJECT_TYPE;
restrictObjectType.res.resProperty.lpProp = &spvObjectType;
if (HR_FAILED(hResult = lpContentsTableMAPI->lpVtbl->Restrict(lpContentsTableMAPI,
&restrictObjectType,
0))) {
DebugTrace("MAPI Restrict (MAPI_DISTLIST) -> %x\n", GetScode(hResult));
goto exit;
}
// Restrict resets the current position to the beginning of the table, by definition.
SetDialogMessage(hwnd, IDS_STATE_IMPORT_DL);
// Initialize the Progress Bar
// How many entries are there?
ulcEntries = CountRows(lpContentsTableMAPI, TRUE);
ulcDone = 0;
DebugTrace("PAB contains %u Distribution List entries\n", ulcEntries);
if (ulcEntries) {
SetDialogProgress(hwnd, ulcEntries, 0);
}
exit:
// On error, set the state to STATE_ERROR
if (HR_FAILED(hResult)) {
if (GetScode(hResult) == MAPI_E_USER_CANCEL) {
NewState(hwnd, STATE_IMPORT_CANCEL);
} else {
NewState(hwnd, STATE_IMPORT_ERROR);
}
} else {
NewState(hwnd, STATE_IMPORT_NEXT_DL);
}
}
/***************************************************************************
Name : StateImportNextDL
Purpose : Migrate the next DISTLIST object
Parameters: hwnd = window handle of Import Dialog
Returns : none
Comment : QueryRows on the global MAPI contents table
if there was a row
Migrate the DistList to the WAB
Re-post STATE_NEXT_DL
else
Post STATE_FINISH
***************************************************************************/
void StateImportNextDL(HWND hwnd) {
ULONG cRows = 0;
HRESULT hResult;
LPSRowSet lpRow = NULL;
DebugTrace(">>> STATE_NEXT_DL\n");
// Get the next PAB entry
if (hResult = lpContentsTableMAPI->lpVtbl->QueryRows(lpContentsTableMAPI,
1, // one row at a time
0, // ulFlags
&lpRow)) {
DebugTrace("QueryRows -> %x\n", GetScode(hResult));
goto exit;
}
if (lpRow) {
if (cRows = lpRow->cRows) { // Yes, single '='
Assert(lpRow->cRows == 1);
Assert(lpRow->aRow[0].cValues == iptaColumnsMax);
Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].ulPropTag == PR_ENTRYID);
Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].ulPropTag == PR_OBJECT_TYPE);
if (cRows = lpRow->cRows) { // yes, single '='
hResult = ImportEntry(hwnd,
lpAdrBookMAPI,
lpContainerWAB,
lpCreateEIDsWAB,
lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].Value.l,
(LPENTRYID)lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.lpb,
lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.cb,
NULL,
NULL,
FALSE,
FALSE);
// Update Progress Bar
SetDialogProgress(hwnd, ulcEntries, ++ulcDone);
if (hResult) {
if (HandleImportError(hwnd,
0,
hResult,
lpRow->aRow[0].lpProps[iptaColumnsPR_DISPLAY_NAME].Value.LPSZ,
PropStringOrNULL(&lpRow->aRow[0].lpProps[iptaColumnsPR_EMAIL_ADDRESS]),
lpImportOptions)) {
hResult = ResultFromScode(MAPI_E_USER_CANCEL);
} else {
hResult = hrSuccess;
}
}
} // else, drop out of loop, we're done.
}
FreeProws(lpRow);
}
exit:
// On error, set the state to STATE_ERROR
if (HR_FAILED(hResult)) {
if (GetScode(hResult) == MAPI_E_USER_CANCEL) {
NewState(hwnd, STATE_IMPORT_CANCEL);
} else {
NewState(hwnd, STATE_IMPORT_ERROR);
}
} else {
if (cRows) {
NewState(hwnd, STATE_IMPORT_NEXT_DL);
} else {
// Update Progress Bar to indicate completion
SetDialogProgress(hwnd, ulcEntries, ulcEntries);
NewState(hwnd, STATE_IMPORT_FINISH);
}
}
}
/***************************************************************************
Name : StateImportFinish
Purpose : Clean up after the migration process
Parameters: hwnd = window handle of Import Dialog
Returns : none
Comment : Clean up the global MAPI objects and buffers
Clean up the global WAB objects and buffers.
Re-enable the Import button on the UI.
***************************************************************************/
void StateImportFinish(HWND hwnd) {
TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
TCHAR szBufferTitle[MAX_RESOURCE_STRING + 1];
DebugTrace(">>> STATE_FINISH\n");
//
// Cleanup MAPI
//
if (lpContentsTableMAPI) {
lpContentsTableMAPI->lpVtbl->Release(lpContentsTableMAPI);
lpContentsTableMAPI = NULL;
}
if (lpContainerMAPI) {
lpContainerMAPI->lpVtbl->Release(lpContainerMAPI);
lpContainerMAPI = NULL;
}
if (lpAdrBookMAPI) {
lpAdrBookMAPI->lpVtbl->Release(lpAdrBookMAPI);
lpAdrBookMAPI = NULL;
}
if(lpMAPISession){
lpMAPISession->lpVtbl->Logoff(lpMAPISession, (ULONG_PTR)(void *)hwnd,
MAPI_LOGOFF_UI,
0);
lpMAPISession->lpVtbl->Release(lpMAPISession);
lpMAPISession = NULL;
}
//
// Cleanup the WAB
//
if (lpCreateEIDsWAB) {
WABFreeBuffer(lpCreateEIDsWAB);
lpCreateEIDsWAB = NULL;
}
if (lpContainerWAB) {
lpContainerWAB->lpVtbl->Release(lpContainerWAB);
lpContainerWAB = NULL;
}
#ifdef OLD_STUFF // Don't release the WABObject or AdrBook object. They
// were passed in.
if (lpAdrBookWAB) {
lpAdrBookWAB->lpVtbl->Release(lpAdrBookWAB);
lpAdrBookWAB = NULL;
}
if (lpWABObject) {
lpWABObject->lpVtbl->Release(lpWABObject);
lpWABObject = NULL;
}
#endif // OLD_STUFF
// Cleanup the cache
FreeSeenList();
if (! fError) { // Leave error state displayed
if (LoadString(hInst, IDS_STATE_IMPORT_COMPLETE, szBuffer, ARRAYSIZE(szBuffer))) {
DebugTrace("Status Message: %s\n", szBuffer);
SetDlgItemText(hwnd, IDC_Message, szBuffer);
if (! LoadString(hInst, IDS_APP_TITLE, szBufferTitle, ARRAYSIZE(szBufferTitle))) {
StrCpyN(szBufferTitle, "", ARRAYSIZE(szBufferTitle));
}
#ifdef OLD_STUFF
// Display a dialog telling user it's over
MessageBox(hwnd, szBuffer,
szBufferTitle, MB_ICONINFORMATION | MB_OK);
#endif // OLD_STUFF
}
#ifdef OLD_STUFF
ShowWindow(GetDlgItem(hwnd, IDC_Progress), SW_HIDE);
#endif // OLD_STUFF
}
fError = FALSE;
// Re-enable the Import button here.
EnableWindow(GetDlgItem(hwnd, IDC_Import), TRUE);
// Change the Cancel button to Close
if (LoadString(hInst, IDS_BUTTON_CLOSE, szBuffer, ARRAYSIZE(szBuffer))) {
SetDlgItemText(hwnd, IDCANCEL, szBuffer);
}
}
/***************************************************************************
Name : StateImportError
Purpose : Report fatal error and cleanup.
Parameters: hwnd = window handle of Import Dialog
Returns : none
Comment : Report error and post STATE_FINISH.
***************************************************************************/
void StateImportError(HWND hwnd) {
TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
// Set some global flag and set state to finish
DebugTrace(">>> STATE_ERROR\n");
fError = TRUE;
SetDialogMessage(hwnd, IDS_STATE_IMPORT_ERROR);
NewState(hwnd, STATE_IMPORT_FINISH);
}
/***************************************************************************
Name : StateImportCancel
Purpose : Report cancel error and cleanup.
Parameters: hwnd = window handle of Import Dialog
Returns : none
Comment : Report error and post STATE_FINISH.
***************************************************************************/
void StateImportCancel(HWND hwnd) {
TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
// Set some global flag and set state to finish
DebugTrace(">>> STATE_CANCEL\n");
fError = TRUE;
SetDialogMessage(hwnd, IDS_STATE_IMPORT_CANCEL);
NewState(hwnd, STATE_IMPORT_FINISH);
}
/***************************************************************************
Name : HrFilterImportMailUserProps
Purpose : Filters out undesirable properties from the property array.
Converts known email address types to SMTP.
Moves FAX address to PR_BUSINESS_FAX_NUMBER.
Parameters: lpcProps -> IN: Input number of properties
OUT: Output number of properties
lppProps -> IN: Input property array (MAPI allocation)
OUT: Output property array (WAB allocation)
lpObjectMAPI -> MAPI object (used to get extra props)
lpfDL -> flag to set FALSE if we change a DL to a MAILUSER
(ie, for an EXchange DL)
Returns : HRESULT
Comment : Setting the property tag in the array to PR_NULL effectively
nulls this property out. We can re-use these in the second
pass.
Caller should use WABFreeBuffer to free *lppProps.
This routine will free the input value of *lppProps.
***************************************************************************/
HRESULT HrFilterImportMailUserProps(LPULONG lpcProps, LPSPropValue * lppProps,
LPMAPIPROP lpObjectMAPI, LPBOOL lpfDL) {
HRESULT hResult = hrSuccess;
ULONG i;
LPSPropValue lpPropsMAPI = *lppProps, lpPropsWAB = NULL;
ULONG cbProps;
SCODE sc;
ULONG cProps = *lpcProps;
ULONG iPR_ADDRTYPE = NOT_FOUND;
ULONG iPR_EMAIL_ADDRESS = NOT_FOUND;
ULONG iPR_PRIMARY_FAX_NUMBER = NOT_FOUND;
ULONG iPR_BUSINESS_FAX_NUMBER = NOT_FOUND;
ULONG iPR_MSNINET_DOMAIN = NOT_FOUND;
ULONG iPR_MSNINET_ADDRESS = NOT_FOUND;
ULONG iPR_DISPLAY_NAME = NOT_FOUND;
ULONG iPR_OBJECT_TYPE = NOT_FOUND;
LPSBinary lpEntryID = NULL;
LPTSTR lpTemp;
BOOL fBadAddress = FALSE;
ULONG cbDisplayName;
LPTSTR lpDisplayName = NULL;
// MAPIDebugProperties(lpPropsMAPI, *lpcProps, "MailUser BEFORE");
// First pass: Remove the junk
for (i = 0; i < cProps; i++) {
// Error value
if (PROP_ERROR(lpPropsMAPI[i])) {
lpPropsMAPI[i].ulPropTag = PR_NULL;
continue;
}
// Named property
if (PROP_ID(lpPropsMAPI[i].ulPropTag) >= MIN_NAMED_PROPID) {
lpPropsMAPI[i].ulPropTag = PR_NULL;
continue;
}
// Object property
if (PROP_TYPE(lpPropsMAPI[i].ulPropTag) == PT_OBJECT) {
lpPropsMAPI[i].ulPropTag = PR_NULL;
continue;
}
switch (lpPropsMAPI[i].ulPropTag) {
case PR_ENTRYID:
lpEntryID = &lpPropsMAPI[i].Value.bin;
// fall through
case PR_PRIMARY_CAPABILITY:
case PR_TEMPLATEID:
case PR_SEARCH_KEY:
case PR_INITIAL_DETAILS_PANE:
case PR_RECORD_KEY:
case PR_MAPPING_SIGNATURE:
lpPropsMAPI[i].ulPropTag = PR_NULL;
break;
case PR_COMMENT:
// Don't save PR_COMMENT if it is empty
if (lstrlen(lpPropsMAPI[i].Value.LPSZ) == 0) {
lpPropsMAPI[i].ulPropTag = PR_NULL;
}
break;
// Keep track of the position of these for later
case PR_ADDRTYPE:
iPR_ADDRTYPE = i;
break;
case PR_OBJECT_TYPE:
iPR_OBJECT_TYPE = i;
break;
case PR_EMAIL_ADDRESS:
iPR_EMAIL_ADDRESS = i;
break;
case PR_PRIMARY_FAX_NUMBER:
iPR_PRIMARY_FAX_NUMBER = i;
break;
case PR_BUSINESS_FAX_NUMBER:
iPR_BUSINESS_FAX_NUMBER = i;
break;
case PR_MSNINET_ADDRESS:
iPR_MSNINET_ADDRESS = i;
break;
case PR_MSNINET_DOMAIN:
iPR_MSNINET_DOMAIN = i;
break;
case PR_DISPLAY_NAME:
iPR_DISPLAY_NAME = i;
// Make sure it isn't quoted.
lpDisplayName = lpPropsMAPI[i].Value.LPSZ;
if (lpDisplayName[0] == '\'') {
cbDisplayName = lstrlen(lpDisplayName);
if ((cbDisplayName > 1) && lpDisplayName[cbDisplayName - 1] == '\'') {
// String is surrounded by apostrophes. Strip them.
lpDisplayName[cbDisplayName - 1] = '\0';
lpDisplayName++;
lpPropsMAPI[i].Value.LPSZ = lpDisplayName;
}
} else {
if (lpDisplayName[0] == '"') {
cbDisplayName = lstrlen(lpDisplayName);
if ((cbDisplayName > 1) && lpDisplayName[cbDisplayName - 1] == '"') {
// String is surrounded by quotes. Strip them.
lpDisplayName[cbDisplayName - 1] = '\0';
lpDisplayName++;
lpPropsMAPI[i].Value.LPSZ = lpDisplayName;
}
}
}
break;
}
// Put this after the switch since we do want to track a few props which fall in
// the 0x6000 range but don't want to transfer them to the wab.
if (PROP_ID(lpPropsMAPI[i].ulPropTag) >= MAX_SCHEMA_PROPID) {
lpPropsMAPI[i].ulPropTag = PR_NULL;
continue;
}
}
// Second pass: Fix up the addresses
if (iPR_ADDRTYPE != NOT_FOUND) {
if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szFAX)) {
DebugTrace("FAX address for %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
//
// Handle MS-FAX Address conversion
//
if (iPR_EMAIL_ADDRESS != NOT_FOUND) {
// Rename the PR_EMAIL_ADDRESS to PR_BUSINESS_FAX_NUMBER
lpPropsMAPI[iPR_EMAIL_ADDRESS].ulPropTag = PR_BUSINESS_FAX_NUMBER;
// Get rid of any existing PR_BUSINESS_FAX_NUMBER
if (iPR_BUSINESS_FAX_NUMBER != NOT_FOUND) {
lpPropsMAPI[iPR_BUSINESS_FAX_NUMBER].ulPropTag = PR_NULL;
iPR_BUSINESS_FAX_NUMBER = NOT_FOUND;
}
}
// Nuke ADDRTYPE
lpPropsMAPI[iPR_ADDRTYPE].ulPropTag = PR_NULL;
} else if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szMSN)) {
ULONG cchSize = lstrlen(lpPropsMAPI[iPR_EMAIL_ADDRESS].Value.LPSZ) + 1 + cbMSNpostfix ;
DebugTrace("MSN address for %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
//
// Handle MSN Address conversion
//
if (iPR_EMAIL_ADDRESS != NOT_FOUND) {
// Allocate a new, longer string
if (FAILED(sc = MAPIAllocateMore(
sizeof(TCHAR) * cchSize,
lpPropsMAPI,
&lpTemp))) {
DebugTrace("HrFilterImportMailUserProps:MAPIAllocateMore -> %x\n", sc);
hResult = ResultFromScode(sc);
goto exit;
}
// append the msn site
StrCpyN(lpTemp, lpPropsMAPI[iPR_EMAIL_ADDRESS].Value.LPSZ, cchSize);
StrCatBuff(lpTemp, szMSNpostfix, cchSize);
lpPropsMAPI[iPR_EMAIL_ADDRESS].Value.LPSZ = lpTemp;
// Convert MSN addrtype to SMTP
lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ = (LPTSTR)szSMTP;
} else {
// No address, nuke ADDRTYPE
lpPropsMAPI[iPR_ADDRTYPE].ulPropTag = PR_NULL;
}
} else if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szCOMPUSERVE)) {
ULONG cchSize = lstrlen(lpPropsMAPI[iPR_EMAIL_ADDRESS].Value.LPSZ) + 1 + cbCOMPUSERVEpostfix;
DebugTrace("COMPUSERVE address for %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
//
// Handle COMPUSERVE Address conversion
//
if (iPR_EMAIL_ADDRESS != NOT_FOUND) {
// Allocate a new, longer string
if (FAILED(sc = MAPIAllocateMore(
sizeof(TCHAR)*cchSize,
lpPropsMAPI,
&lpTemp))) {
DebugTrace("HrFilterImportMailUserProps:MAPIAllocateMore -> %x\n", sc);
hResult = ResultFromScode(sc);
goto exit;
}
// append the Compuserve site
StrCpyN(lpTemp, lpPropsMAPI[iPR_EMAIL_ADDRESS].Value.LPSZ, cchSize);
StrCatBuff(lpTemp, szCOMPUSERVEpostfix, cchSize);
lpPropsMAPI[iPR_EMAIL_ADDRESS].Value.LPSZ = lpTemp;
// I need to convert the ',' to a '.'
while (*lpTemp) {
if (*lpTemp == ',') {
*lpTemp = '.';
break; // should only be one comma
}
lpTemp = CharNext(lpTemp);
}
// Convert COMPUSERVE addrtype to SMTP
lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ = (LPTSTR)szSMTP;
} else {
// No address, nuke ADDRTYPE
lpPropsMAPI[iPR_ADDRTYPE].ulPropTag = PR_NULL;
}
} else if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szMSNINET)) {
ULONG cchSize =
lstrlen(lpPropsMAPI[iPR_MSNINET_ADDRESS].Value.LPSZ) + cbAtSign +
lstrlen(lpPropsMAPI[iPR_MSNINET_DOMAIN].Value.LPSZ) + 1;
DebugTrace("MSINET address for %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
//
// Handle MSN Internet address conversion. These are weird.
// They often don't fill in the PR_EMAIL_ADDRESS at all, but do fill
// in some private properties: 6001 and 6002 with the name and domain,
// respectively. We should take these and append them with the '@' to
// get our PR_EMAIL_ADDRESS. We will toss out any existing
// PR_EMAIL_ADDRESS in favor of these values.
//
// Allocate a new string
//
if ((iPR_MSNINET_ADDRESS != NOT_FOUND) && (iPR_MSNINET_DOMAIN != NOT_FOUND)) {
if (FAILED(sc = MAPIAllocateMore(sizeof(TCHAR)*cchSize,
lpPropsMAPI,
&lpTemp))) {
DebugTrace("HrFilterImportMailUserProps:MAPIAllocateMore -> %x\n", sc);
hResult = ResultFromScode(sc);
goto exit;
}
// Build the address
StrCpyN(lpTemp, lpPropsMAPI[iPR_MSNINET_ADDRESS].Value.LPSZ, cchSize);
StrCatBuff(lpTemp, szAtSign, cchSize);
StrCatBuff(lpTemp, lpPropsMAPI[iPR_MSNINET_DOMAIN].Value.LPSZ, cchSize);
lpPropsMAPI[iPR_EMAIL_ADDRESS].Value.LPSZ = lpTemp;
// Convert addrtype to SMTP
lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ = (LPTSTR)szSMTP;
} else if (iPR_EMAIL_ADDRESS && lstrlen(lpPropsMAPI[iPR_EMAIL_ADDRESS].Value.LPSZ)) {
// keep existing PR_EMAIL_ADDRES and assume it's ok
lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ = (LPTSTR)szSMTP;
} else {
// No address, nuke ADDRTYPE
lpPropsMAPI[iPR_ADDRTYPE].ulPropTag = PR_NULL;
}
} else if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szMS)) {
DebugTrace("MS address for %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
// No SMTP form of a MSMail address. destroy it.
if (iPR_EMAIL_ADDRESS != NOT_FOUND) {
lpPropsMAPI[iPR_EMAIL_ADDRESS].ulPropTag = PR_NULL;
fBadAddress = TRUE;
}
lpPropsMAPI[iPR_ADDRTYPE].ulPropTag = PR_NULL;
} else if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szX400)) {
DebugTrace("X400 address for %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
// No SMTP form of a X400 address. destroy it.
if (iPR_EMAIL_ADDRESS != NOT_FOUND) {
lpPropsMAPI[iPR_EMAIL_ADDRESS].ulPropTag = PR_NULL;
fBadAddress = TRUE;
}
lpPropsMAPI[iPR_ADDRTYPE].ulPropTag = PR_NULL;
} else if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szMSA)) {
DebugTrace("MacMail address for %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
// No SMTP form of a MacMail address. destroy it.
if (iPR_EMAIL_ADDRESS != NOT_FOUND) {
lpPropsMAPI[iPR_EMAIL_ADDRESS].ulPropTag = PR_NULL;
fBadAddress = TRUE;
}
lpPropsMAPI[iPR_ADDRTYPE].ulPropTag = PR_NULL;
} else if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szEX)) {
DebugTrace("EX address for %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
if (lpTemp = GetEMSSMTPAddress(lpObjectMAPI, lpPropsMAPI)) {
lpPropsMAPI[iPR_EMAIL_ADDRESS].Value.LPSZ = lpTemp;
// Convert addrtype to SMTP
lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ = (LPTSTR)szSMTP;
// Make sure that caller doesn't think this is a Personal DL.
*lpfDL = FALSE;
if (iPR_EMAIL_ADDRESS != NOT_FOUND) {
lpPropsMAPI[iPR_OBJECT_TYPE].ulPropTag = PR_OBJECT_TYPE;
lpPropsMAPI[iPR_OBJECT_TYPE].Value.l = MAPI_MAILUSER;
}
} else {
if (iPR_EMAIL_ADDRESS != NOT_FOUND) {
lpPropsMAPI[iPR_EMAIL_ADDRESS].ulPropTag = PR_NULL;
fBadAddress = TRUE;
}
lpPropsMAPI[iPR_ADDRTYPE].ulPropTag = PR_NULL;
}
} else if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szSMTP)) {
DebugTrace("SMTP address for %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
} else if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szMAPIPDL)) {
DebugTrace("MAPIPDL %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
// Distribution list, ignore it.
} else {
MAPIDebugProperties(lpPropsMAPI, cProps, "Unknown address type");
DebugTrace("Found unknown PR_ADDRTYPE: %s\n", lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ);
Assert(FALSE);
}
}
// PR_BUSINESS_FAX_NUMBER?
// The PAB puts the Fax number in PR_PRIMARY_FAX_NUMBER, but the WAB UI splits it
// into PR_BUSINESS_FAX_NUMBER and PR_HOME_FAX_NUMBER. We always assume that the
// Primary fax number is business.
if ((iPR_PRIMARY_FAX_NUMBER != NOT_FOUND) && (iPR_BUSINESS_FAX_NUMBER == NOT_FOUND)) {
// We need to also have a PR_BUSINESS_FAX_NUMBER
// Find the next PR_NULL spot.
iPR_BUSINESS_FAX_NUMBER = iPR_PRIMARY_FAX_NUMBER; // overwrite this one if there isn't
// an available slot in the prop array.
for (i = 0; i < cProps; i++) {
if (lpPropsMAPI[i].ulPropTag == PR_NULL) {
iPR_BUSINESS_FAX_NUMBER = i;
lpPropsMAPI[iPR_BUSINESS_FAX_NUMBER].Value.LPSZ =
lpPropsMAPI[iPR_PRIMARY_FAX_NUMBER].Value.LPSZ;
break;
}
}
lpPropsMAPI[iPR_BUSINESS_FAX_NUMBER].ulPropTag = PR_BUSINESS_FAX_NUMBER;
}
// Get rid of PR_NULL props
for (i = 0; i < cProps; i++) {
if (lpPropsMAPI[i].ulPropTag == PR_NULL) {
// Slide the props down.
if (i + 1 < cProps) { // Are there any higher props to copy?
CopyMemory(&lpPropsMAPI[i], &lpPropsMAPI[i + 1], ((cProps - i) - 1) * sizeof(lpPropsMAPI[i]));
}
// decrement count
cProps--;
i--; // You overwrote the current propval. Look at it again.
}
}
// Reallocate as WAB memory.
if (sc = ScCountProps(cProps, lpPropsMAPI, &cbProps)) {
hResult = ResultFromScode(sc);
DebugTrace("ScCountProps -> %x\n", sc);
goto exit;
}
if (sc = WABAllocateBuffer(cbProps, &lpPropsWAB)) {
hResult = ResultFromScode(sc);
DebugTrace("WABAllocateBuffer -> %x\n", sc);
goto exit;
}
if (sc = ScCopyProps(cProps,
lpPropsMAPI,
lpPropsWAB,
NULL)) {
hResult = ResultFromScode(sc);
DebugTrace("ScCopyProps -> %x\n", sc);
goto exit;
}
exit:
if (lpPropsMAPI) {
MAPIFreeBuffer(lpPropsMAPI);
}
if (HR_FAILED(hResult)) {
if (lpPropsWAB) {
WABFreeBuffer(lpPropsWAB);
lpPropsWAB = NULL;
}
cProps = 0;
} else if (fBadAddress) {
hResult = ResultFromScode(WAB_W_BAD_EMAIL);
}
*lppProps = lpPropsWAB;
*lpcProps = cProps;
return(hResult);
}
/***************************************************************************
Name : HandleImportError
Purpose : Decides if a dialog needs to be displayed to
indicate the failure and does so.
Parameters: hwnd = main dialog window
ids = String ID (optional: calculated from hResult if 0)
hResult = Result of action
lpDisplayName = display name of object that failed
lpEmailAddress = email address of object that failed or NULL
lpImportOptions -> import options structure
Returns : TRUE if user requests ABORT.
Comment : Abort is not yet implemented in the dialog, but if you
ever want to, just make this routine return TRUE;
***************************************************************************/
BOOL HandleImportError(HWND hwnd, ULONG ids, HRESULT hResult, LPTSTR lpDisplayName,
LPTSTR lpEmailAddress, LPWAB_IMPORT_OPTIONS lpImportOptions) {
BOOL fAbort = FALSE;
ERROR_INFO EI;
if ((ids || hResult) && ! lpImportOptions->fNoErrors) {
if (ids == 0) {
switch (GetScode(hResult)) {
case WAB_W_BAD_EMAIL:
ids = lpEmailAddress ? IDS_ERROR_EMAIL_ADDRESS_2 : IDS_ERROR_EMAIL_ADDRESS_1;
break;
case MAPI_E_NO_SUPPORT:
// Propbably failed to open contents on a distribution list
ids = IDS_ERROR_NO_SUPPORT;
break;
case MAPI_E_USER_CANCEL:
return(TRUE);
default:
if (HR_FAILED(hResult)) {
DebugTrace("Error Box for Hresult: 0x%08x\n", GetScode(hResult));
Assert(FALSE); // want to know about it.
ids = IDS_ERROR_GENERAL;
}
break;
}
}
EI.lpszDisplayName = lpDisplayName;
EI.lpszEmailAddress = lpEmailAddress;
EI.ErrorResult = ERROR_OK;
EI.ids = ids;
EI.fExport = FALSE;
EI.lpImportOptions = lpImportOptions;
DialogBoxParam(hInst,
MAKEINTRESOURCE(IDD_ErrorImport),
hwnd,
ErrorDialogProc,
(LPARAM)&EI);
fAbort = EI.ErrorResult == ERROR_ABORT;
}
return(fAbort);
}
/***************************************************************************
Name : FindExistingWABEntry
Purpose : Finds an existing entry in the WAB
Parameters: lpProps -> PropArray of MAPI entry
cProps = number of props in lpProps
lpContainerWAB -> WAB Container object
lppEIDWAB -> returned EntryID (caller must WABFreeBuffer)
lpcbEIDWAB -> returned size of lppEID
Returns : HRESULT
Comment : At this point, we expect to find a match since
SaveChanges said we had a duplicate.
***************************************************************************/
HRESULT FindExistingWABEntry(LPSPropValue lpProps,
ULONG cProps,
LPABCONT lpContainerWAB,
LPENTRYID * lppEIDWAB,
LPULONG lpcbEIDWAB) {
ULONG rgFlagList[2];
LPFlagList lpFlagList = (LPFlagList)rgFlagList;
LPADRLIST lpAdrListWAB = NULL;
SCODE sc;
HRESULT hResult = hrSuccess;
LPSBinary lpsbEntryID = NULL;
ULONG cbEID = 0;
*lpcbEIDWAB = 0;
*lppEIDWAB = NULL;
// find the existing WAB entry.
// Setup for ResolveNames on the WAB container.
if (sc = WABAllocateBuffer(sizeof(ADRLIST) + sizeof(ADRENTRY), &lpAdrListWAB)) {
DebugTrace("WAB Allocation(ADRLIST) failed -> %x\n", sc);
hResult = ResultFromScode(sc);
goto exit;
}
lpAdrListWAB->cEntries = 1;
lpAdrListWAB->aEntries[0].ulReserved1 = 0;
lpAdrListWAB->aEntries[0].cValues = 1;
if (sc = WABAllocateBuffer(sizeof(SPropValue), &lpAdrListWAB->aEntries[0].rgPropVals)) {
DebugTrace("WAB Allocation(ADRENTRY propval) failed -> %x\n", sc);
hResult = ResultFromScode(sc);
goto exit;
}
lpAdrListWAB->aEntries[0].rgPropVals[0].ulPropTag = PR_DISPLAY_NAME;
if (! (lpAdrListWAB->aEntries[0].rgPropVals[0].Value.LPSZ =
FindStringInProps(lpProps, cProps, PR_DISPLAY_NAME))) {
DebugTrace("Can't find PR_DISPLAY_NAME in entry\n");
// pretty weird if this caused a collision...
goto exit;
}
lpFlagList->cFlags = 1;
lpFlagList->ulFlag[0] = MAPI_UNRESOLVED;
if (HR_FAILED(hResult = lpContainerWAB->lpVtbl->ResolveNames(lpContainerWAB,
NULL, // tag set
0, // ulFlags
lpAdrListWAB,
lpFlagList))) {
DebugTrace("WAB ResolveNames -> %x\n", GetScode(hResult));
goto exit;
}
switch (lpFlagList->ulFlag[0]) {
case MAPI_UNRESOLVED:
DebugTrace("WAB ResolveNames didn't find the entry\n");
hResult = ResultFromScode(MAPI_E_NOT_FOUND);
goto exit;
case MAPI_AMBIGUOUS:
#ifdef NEW_STUFF
// Do it the hard way. Open a table, restrict, take the first match.
lpContainerWAB->lpVtbl->GetContentsTable(lpContainerWAB,
if (HR_FAILED(hResult = lpContainerWAB->lpVtbl->GetContentsTable(lpContainerWAB,
0, // ulFlags
&lpTableWAB))) {
DebugTrace("ImportEntry:GetContentsTable(WAB) -> %x\n", GetScode(hResult));
goto exit;
}
lpTableWAB->lpVtbl->Restrict....... // just the ones that match our entry...
cRows = 1;
while (cRows) {
// Get the next DL entry
if (hResult = lpTableWAB->lpVtbl->QueryRows(lpTableWAB,
1, // one row at a time
0, // ulFlags
&lpRow)) {
DebugTrace("DL: QueryRows -> %x\n", GetScode(hResult));
goto exit;
}
if (lpRow && lpRow->cRows) {
Assert(lpRow->cRows == 1);
Assert(lpRow->aRow[0].cValues == iptaColumnsMax);
Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].ulPropTag == PR_ENTRYID);
Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].ulPropTag == PR_OBJECT_TYPE);
} else {
break; // done
}
}
#endif // NEW_STUFF
break;
}
// Find the PR_ENTRYID
if (! (lpsbEntryID = FindAdrEntryID(lpAdrListWAB, 0))) {
DebugTrace("WAB ResolveNames didn't give us an EntryID\n");
hResult = ResultFromScode(MAPI_E_NOT_FOUND);
goto exit;
}
*lpcbEIDWAB = lpsbEntryID->cb;
if (FAILED(sc = WABAllocateBuffer(*lpcbEIDWAB, lppEIDWAB))) {
DebugTrace("ImportEntry: WABAllocateBuffer(WAB ENTRYID) -> %x\n", sc);
hResult = ResultFromScode(sc);
*lpcbEIDWAB = 0;
goto exit;
}
// Copy the new EntryID into the buffer
CopyMemory(*lppEIDWAB, lpsbEntryID->lpb, *lpcbEIDWAB);
exit:
if (lpAdrListWAB) {
WABFreePadrlist(lpAdrListWAB);
}
return(hResult);
}
/****************************************************************************
*
* CheckReversedDisplayName(lpDisplayName);
*
* PAB and outlook display names are "LastName, FirstName"
* We need to reverse this for the WAB to handle it correctly ...
*
*
*****************************************************************************/
void CheckReversedDisplayName(LPTSTR lpDisplayName)
{
TCHAR szTemp[MAX_PATH * 3];
LPTSTR lp1=NULL, lp2=NULL;
ULONG cchSize = lstrlen(lpDisplayName);
if(!lpDisplayName)
return;
lp1 = lp2 = lpDisplayName;
while(lp1 && *lp1)
{
if(*lp1 == ',')
{
// A comma means this is Last, First
// We will make an assumption here that "L, F" or "L,F" is longer than or equal to "F L" and so
// we can reverse the name in place without any problems
//
lp2 = CharNext(lp1);
//skip spaces
while (IsSpace(lp2)) {
lp2 = CharNext(lp2);
}
*lp1 = '\0';
StrCpyN(szTemp, lpDisplayName, ARRAYSIZE(szTemp));
StrCpyN(lpDisplayName, lp2, cchSize);
StrCatBuff(lpDisplayName, TEXT(" "), cchSize);
StrCatBuff(lpDisplayName, szTemp, cchSize);
break;
}
lp1 = CharNext(lp1);
}
return;
}
/***************************************************************************
Name : ImportEntry
Purpose : Migrates the entry from the PAB to the WAB
Parameters: hwnd = main dialog window
lpAdrBookMAPI -> MAPI AdrBook object
lpContainerWAB -> WAB PAB container
lpCreateEIDsWAB -> SPropValue of default object creation EIDs
ulObjectType = {MAPI_MAILUSER, MAPI_DISTLIST}
lpEID -> ENTYRID of the PAB entry
cbEID = sizeof lpEID
lppEIDWAB -> returned WAB ENTRYID: Caller must WABFreeBuffer.
May be NULL.
lpcbEIDWAB -> returned size of lppEIDWAB (ignored if lppEIDWAB
is NULL.
fInDL = TRUE if this entry is for creation in a Distribution List
fForceReplace = TRUE if this entry should replace any duplicate.
Returns : HRESULT
Comment : This routine is a MESS! Should break it up when we get time.
***************************************************************************/
HRESULT ImportEntry(HWND hwnd,
LPADRBOOK lpAdrBookMAPI,
LPABCONT lpContainerWAB,
LPSPropValue lpCreateEIDsWAB,
ULONG ulObjectType,
LPENTRYID lpEID,
ULONG cbEID,
LPENTRYID * lppEIDWAB,
LPULONG lpcbEIDWAB,
BOOL fInDL,
BOOL fForceReplace) {
HRESULT hResult = hrSuccess;
SCODE sc;
BOOL fDistList = FALSE;
BOOL fDuplicate = FALSE;
BOOL fDuplicateEID;
BOOL fReturnEID = FALSE;
ULONG ulObjectTypeOpen;
LPDISTLIST lpDistListMAPI = NULL, lpDistListWAB = NULL;
LPMAPIPROP lpMailUserMAPI = NULL, lpMailUserWAB = NULL;
LPSPropValue lpProps = NULL;
ULONG cProps, cEIDPropWAB;
LPMAPITABLE lpDLTableMAPI = NULL;
ULONG cRows;
LPSRowSet lpRow = NULL;
LPENTRYID lpeidDLWAB = NULL;
ULONG cbeidDLWAB;
LPSPropValue lpEIDPropWAB = NULL;
LPMAPIPROP lpEntryWAB = NULL;
ULONG ulCreateFlags = CREATE_CHECK_DUP_STRICT;
REPLACE_INFO RI;
LPTSTR lpDisplayName = NULL, lpEmailAddress = NULL;
static TCHAR szBufferDLMessage[MAX_RESOURCE_STRING + 1] = "";
LPTSTR lpszMessage;
LONG lListIndex = -1;
LPENTRYID lpEIDNew = NULL;
DWORD cbEIDNew = 0;
LPIID lpIIDOpen;
ULONG iCreateTemplate = iconPR_DEF_CREATE_MAILUSER;
// Check the entry against our "seen" list
fDuplicateEID = AddEntryToImportList(cbEID, lpEID, &lListIndex);
if (! fDuplicateEID) {
if ((fForceReplace || (lpImportOptions->ReplaceOption == WAB_REPLACE_ALWAYS)) && ! fInDL) {
ulCreateFlags |= CREATE_REPLACE;
}
// Set up some object type specific variables
switch (ulObjectType) {
default:
DebugTrace("ImportEntry got unknown object type %u, assuming MailUser\n", ulObjectType);
Assert(FALSE);
case MAPI_MAILUSER:
iCreateTemplate = iconPR_DEF_CREATE_MAILUSER;
lpIIDOpen = NULL;
fDistList = FALSE;
break;
case MAPI_DISTLIST:
iCreateTemplate = iconPR_DEF_CREATE_DL;
lpIIDOpen = (LPIID)&IID_IDistList;
fDistList = TRUE;
break;
}
// Open the entry
if (HR_FAILED(hResult = lpAdrBookMAPI->lpVtbl->OpenEntry(lpAdrBookMAPI,
cbEID,
lpEID,
lpIIDOpen,
0,
&ulObjectTypeOpen,
(LPUNKNOWN *)&lpMailUserMAPI))) {
DebugTrace("OpenEntry(MAPI MailUser) -> %x\n", GetScode(hResult));
goto exit;
}
// If DISTLIST, assume we got lpMailUser until we need lpDistList.
Assert(lpMailUserMAPI);
Assert(ulObjectType == ulObjectTypeOpen);
// Get the properties from this entry
if (HR_FAILED(hResult = lpMailUserMAPI->lpVtbl->GetProps(lpMailUserMAPI,
NULL,
0,
&cProps,
&lpProps))) {
DebugTrace("ImportEntry:GetProps(MAPI) -> %x\n", GetScode(hResult));
goto exit;
}
//
// NOTE: Must not fail between here and HrFilterImportMailUserProps because
// we will end up freeing lpProps with WABFreeBuffer.
//
// Filter the property array here
if (hResult = HrFilterImportMailUserProps(&cProps, &lpProps, lpMailUserMAPI, &fDistList)) {
lpDisplayName = FindStringInProps(lpProps, cProps, PR_DISPLAY_NAME);
lpEmailAddress = FindStringInProps(lpProps, cProps, PR_EMAIL_ADDRESS);
if (HandleImportError(hwnd,
0,
hResult,
lpDisplayName,
lpEmailAddress,
lpImportOptions)) {
hResult = ResultFromScode(MAPI_E_USER_CANCEL);
goto exit;
}
}
lpDisplayName = FindStringInProps(lpProps, cProps, PR_DISPLAY_NAME);
lpEmailAddress = FindStringInProps(lpProps, cProps, PR_EMAIL_ADDRESS);
CheckReversedDisplayName(lpDisplayName);
if (ulObjectType == MAPI_DISTLIST && ! fDistList) {
// Filter must have changed this to a mailuser.
ulObjectType = MAPI_MAILUSER;
iCreateTemplate = iconPR_DEF_CREATE_MAILUSER;
lpIIDOpen = NULL;
}
//
// NOTE: lpProps after this point is WAB Allocated rather than MAPI allocated.
//
if (HR_FAILED(hResult = lpContainerWAB->lpVtbl->CreateEntry(lpContainerWAB,
lpCreateEIDsWAB[iCreateTemplate].Value.bin.cb,
(LPENTRYID)lpCreateEIDsWAB[iCreateTemplate].Value.bin.lpb,
ulCreateFlags,
&lpMailUserWAB))) {
DebugTrace("CreateEntry(WAB MailUser) -> %x\n", GetScode(hResult));
goto exit;
}
if (fDistList) {
// Update status message
if (*szBufferDLMessage == '\0') { // only load once, then keep it.
LoadString(hInst, IDS_MESSAGE_IMPORTING_DL, szBufferDLMessage, ARRAYSIZE(szBufferDLMessage));
}
if (lpDisplayName) {
ULONG cchSize = lstrlen(szBufferDLMessage) + 1 + lstrlen(lpDisplayName);
if (lpszMessage = LocalAlloc(LMEM_FIXED, sizeof(TCHAR)*cchSize)) {
wnsprintf(lpszMessage, cchSize, szBufferDLMessage, lpDisplayName);
DebugTrace("Status Message: %s\n", lpszMessage);
if (! SetDlgItemText(hwnd, IDC_Message, lpszMessage)) {
DebugTrace("SetDlgItemText -> %u\n", GetLastError());
}
LocalFree(lpszMessage);
}
}
}
// Set the properties on the WAB entry
if (HR_FAILED(hResult = lpMailUserWAB->lpVtbl->SetProps(lpMailUserWAB,
cProps, // cValues
lpProps, // property array
NULL))) { // problems array
DebugTrace("ImportEntry:SetProps(WAB) -> %x\n", GetScode(hResult));
goto exit;
}
// Save the new wab mailuser or distlist
if (HR_FAILED(hResult = lpMailUserWAB->lpVtbl->SaveChanges(lpMailUserWAB,
KEEP_OPEN_READONLY | FORCE_SAVE))) {
if (GetScode(hResult) == MAPI_E_COLLISION) {
// Find the display name
if (! lpDisplayName) {
DebugTrace("Collision, but can't find PR_DISPLAY_NAME in entry\n");
goto exit;
}
// Do we need to prompt?
// if (! fInDL && lpImportOptions->ReplaceOption == WAB_REPLACE_PROMPT) {
if (lpImportOptions->ReplaceOption == WAB_REPLACE_PROMPT) {
// Prompt user with dialog. If they say YES, we should
// recurse with the FORCE flag set.
RI.lpszDisplayName = lpDisplayName;
RI.lpszEmailAddress = lpEmailAddress;
RI.ConfirmResult = CONFIRM_ERROR;
RI.fExport = FALSE;
RI.lpImportOptions = lpImportOptions;
DialogBoxParam(hInst,
MAKEINTRESOURCE(IDD_ImportReplace),
hwnd,
ReplaceDialogProc,
(LPARAM)&RI);
switch(RI.ConfirmResult) {
case CONFIRM_YES:
case CONFIRM_YES_TO_ALL:
// YES
// NOTE: recursive Migrate will fill in the SeenList entry
hResult = ImportEntry(hwnd,
lpAdrBookMAPI,
lpContainerWAB,
lpCreateEIDsWAB,
ulObjectType,
lpEID,
cbEID,
&lpEIDNew, // Need this for later
&cbEIDNew,
FALSE,
TRUE);
if (hResult) {
if (HandleImportError(hwnd,
0,
hResult,
lpDisplayName,
lpEmailAddress,
lpImportOptions)) {
hResult = ResultFromScode(MAPI_E_USER_CANCEL);
} else {
hResult = hrSuccess;
}
}
break;
case CONFIRM_ABORT:
hResult = ResultFromScode(MAPI_E_USER_CANCEL);
goto exit;
default:
// NO
fDuplicate = TRUE;
break;
}
} else {
fDuplicate = TRUE;
}
hResult = hrSuccess;
} else {
DebugTrace("SaveChanges(WAB MailUser) -> %x\n", GetScode(hResult));
}
} else {
// What is the ENTRYID of our new entry?
if ((hResult = lpMailUserWAB->lpVtbl->GetProps(lpMailUserWAB,
(LPSPropTagArray)&ptaEid,
0,
&cEIDPropWAB,
&lpEIDPropWAB))) {
DebugTrace("ImportEntry: GetProps(WAB ENTRYID) -> %x\n", GetScode(hResult));
goto exit;
}
Assert(cEIDPropWAB);
Assert(lpEIDPropWAB[ieidPR_ENTRYID].ulPropTag == PR_ENTRYID);
cbEIDNew = lpEIDPropWAB[0].Value.bin.cb;
if (FAILED(sc = WABAllocateBuffer(cbEIDNew, &lpEIDNew))) {
DebugTrace("ImportEntry: WABAllocateBuffer(WAB ENTRYID) -> %x\n", sc);
hResult = ResultFromScode(sc);
goto exit;
}
// Copy the new EntryID into the buffer
CopyMemory(lpEIDNew, lpEIDPropWAB[0].Value.bin.lpb, cbEIDNew);
}
//
// If this is a DISTLIST, fill it in.
//
if (fDistList && ! fDuplicate && cbEIDNew) {
lpDistListMAPI = (LPDISTLIST)lpMailUserMAPI; // This is REALLY a DISTLIST object
// DO NOT Release this!
// Open the new WAB DL as a DISTLIST object
if (HR_FAILED(hResult = lpContainerWAB->lpVtbl->OpenEntry(lpContainerWAB,
cbEIDNew,
lpEIDNew,
(LPIID)&IID_IDistList,
MAPI_MODIFY,
&ulObjectTypeOpen,
(LPUNKNOWN*)&lpDistListWAB))) {
DebugTrace("ImportEntry: WAB OpenEntry(IID_DistList) -> %x\n", GetScode(hResult));
goto exit;
}
Assert(lpDistListWAB);
// For each entry in the DL:
// Migrate the entry (MailUser or DL) recursively
// Add new entryid to DL contents
if (HR_FAILED(hResult = lpDistListMAPI->lpVtbl->GetContentsTable(lpDistListMAPI,
0, // ulFlags
&lpDLTableMAPI ))) {
DebugTrace("ImportEntry:GetContentsTable(MAPI) -> %x\n", GetScode(hResult));
goto exit;
}
// Set the columns to those we're interested in
if (hResult = lpDLTableMAPI->lpVtbl->SetColumns(lpDLTableMAPI,
(LPSPropTagArray)&ptaColumns,
0)) {
DebugTrace("MAPI SetColumns(DL Table) -> %x\n", GetScode(hResult));
goto exit;
}
cRows = 1;
while (cRows) {
// Get the next DL entry
if (hResult = lpDLTableMAPI->lpVtbl->QueryRows(lpDLTableMAPI,
1, // one row at a time
0, // ulFlags
&lpRow)) {
DebugTrace("DL: QueryRows -> %x\n", GetScode(hResult));
goto exit;
}
if (lpRow && lpRow->cRows) {
Assert(lpRow->cRows == 1);
Assert(lpRow->aRow[0].cValues == iptaColumnsMax);
Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].ulPropTag == PR_ENTRYID);
Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].ulPropTag == PR_OBJECT_TYPE);
if (lpRow) {
if (cRows = lpRow->cRows) { // yes, single '='
hResult = ImportEntry(hwnd,
lpAdrBookMAPI,
lpContainerWAB,
lpCreateEIDsWAB,
lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].Value.l,
(LPENTRYID)lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.lpb,
lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.cb,
&lpeidDLWAB, // returned new or existing entry
&cbeidDLWAB,
TRUE,
FALSE);
if (hResult) {
if (HandleImportError(hwnd,
0,
hResult,
lpRow->aRow[0].lpProps[iptaColumnsPR_DISPLAY_NAME].Value.LPSZ,
PropStringOrNULL(&lpRow->aRow[0].lpProps[iptaColumnsPR_EMAIL_ADDRESS]),
lpImportOptions)) {
hResult = ResultFromScode(MAPI_E_USER_CANCEL);
break; // out of loop
} else {
hResult = hrSuccess;
}
}
} // else, drop out of loop, we're done.
FreeProws(lpRow);
lpRow = NULL;
if (HR_FAILED(hResult)) {
// This entry couldn't be created. Ignore it.
DebugTrace("Coudln't create DL entry -> %x\n", GetScode(hResult));
hResult = hrSuccess;
continue;
}
// Add the Entry to the DL using the new entry's EntryID
if (cbeidDLWAB && lpeidDLWAB) {
// BUGBUG: Don't bother with this one if this is a duplicate entry.
if (HR_FAILED(hResult = lpDistListWAB->lpVtbl->CreateEntry(lpDistListWAB,
cbeidDLWAB,
lpeidDLWAB,
0, // allow duplicates here
&lpEntryWAB))) {
DebugTrace("Couldn't create new entry in DL -> %x\n", GetScode(hResult));
break;
}
hResult = lpEntryWAB->lpVtbl->SaveChanges(lpEntryWAB, FORCE_SAVE);
if (lpEntryWAB) {
lpEntryWAB->lpVtbl->Release(lpEntryWAB);
lpEntryWAB = NULL;
}
}
if (lpeidDLWAB) {
WABFreeBuffer(lpeidDLWAB);
lpeidDLWAB = NULL;
}
}
} else {
break; // done
}
}
}
} else {
DebugTrace("Found a duplicate EntryID\n");
}
//
// Save the entryid to the list and return a buffer with it
//
if (cbEIDNew && lpEIDNew) { // We created one?
// created one
} else if (fDuplicateEID && lListIndex != -1) { // Was it in the list?
cbEIDNew = lpEntriesSeen[lListIndex].sbinWAB.cb;
if (FAILED(sc = WABAllocateBuffer(cbEIDNew, &lpEIDNew))) {
DebugTrace("ImportEntry: WABAllocateBuffer(WAB ENTRYID) -> %x\n", sc);
// ignore
cbEIDNew = 0;
} else {
// Copy the EntryID from the list into the buffer
CopyMemory(lpEIDNew, lpEntriesSeen[lListIndex].sbinWAB.lpb, cbEIDNew);
}
} else if (fDuplicate) { // Was it a duplicate
FindExistingWABEntry(lpProps, cProps, lpContainerWAB, &lpEIDNew, &cbEIDNew);
// ignore errors since the lpEIDNew and cbEIDNew will be nulled out
}
// Update the seen list
if (! fDuplicateEID) {
MarkWABEntryInList(cbEIDNew, lpEIDNew, lListIndex);
}
// If caller requested the entryid's, return them
if (lpcbEIDWAB && lppEIDWAB) {
*lpcbEIDWAB = cbEIDNew;
*lppEIDWAB = lpEIDNew;
fReturnEID = TRUE; // don't free it
}
exit:
//
// Cleanup WAB stuff
//
if (lpProps) {
WABFreeBuffer(lpProps);
}
if (lpEIDPropWAB) {
WABFreeBuffer(lpEIDPropWAB);
}
if (lpEIDNew && ! fReturnEID) {
WABFreeBuffer(lpEIDNew);
}
if (lpeidDLWAB) {
WABFreeBuffer(lpeidDLWAB);
}
if (lpMailUserWAB) {
lpMailUserWAB->lpVtbl->Release(lpMailUserWAB);
}
if (lpDistListWAB) {
lpDistListWAB->lpVtbl->Release(lpDistListWAB);
}
//
// Cleanup MAPI stuff
//
if (lpRow) {
FreeProws(lpRow);
}
if (lpDLTableMAPI) {
lpDLTableMAPI->lpVtbl->Release(lpDLTableMAPI);
}
if (lpMailUserMAPI) {
lpMailUserMAPI->lpVtbl->Release(lpMailUserMAPI);
}
// Do not release this... It is the same object as lpMailUserMAPI!
// if (lpDistListMAPI) {
// lpDistListMAPI->lpVtbl->Release(lpDistListMAPI);
// }
if (! HR_FAILED(hResult)) {
hResult = hrSuccess;
}
return(hResult);
}
/*
* PAB EXPORT
*
* Migrate WAB to PAB
*/
BOOL HandleExportError(HWND hwnd, ULONG ids, HRESULT hResult, LPTSTR lpDisplayName,
LPTSTR lpEmailAddress, LPWAB_EXPORT_OPTIONS lpExportOptions);
void StateExportNextMU(HWND hwnd);
void StateExportDL(HWND hwnd);
void StateExportNextDL(HWND hwnd);
void StateExportFinish(HWND hwnd);
void StateExportMU(HWND hwnd);
void StateExportError(HWND hwnd);
void StateExportCancel(HWND hwnd);
HRESULT ExportEntry(HWND hwnd,
LPADRBOOK lpAdrBookMAPI,
LPABCONT lpContainerWAB,
LPSPropValue lpCreateEIDsWAB,
ULONG ulObjectType,
LPENTRYID lpEID,
ULONG cbEID,
LPENTRYID * lppEIDWAB,
LPULONG lpcbEIDWAB,
BOOL fInDL,
BOOL fForceReplace);
LPSPropTagArray lpspta = NULL; // List of tags to export
LPTSTR * lppNames = NULL; // List of names of tags
//
// Map property tags to strings
//
PROP_NAME rgPropNames[NUM_MORE_EXPORT_PROPS] = {
// ulPropTag, fChosen, ids, lpszName lpszName
// Personal Pane
PR_GIVEN_NAME, FALSE, ids_ExportGivenName, NULL, NULL,
PR_SURNAME, FALSE, ids_ExportSurname, NULL, NULL,
PR_MIDDLE_NAME, FALSE, ids_ExportMiddleName, NULL, NULL,
PR_DISPLAY_NAME, TRUE, ids_ExportDisplayName, NULL, NULL,
PR_NICKNAME, FALSE, ids_ExportNickname, NULL, NULL,
PR_EMAIL_ADDRESS, TRUE, ids_ExportEmailAddress, NULL, NULL,
// Home Pane
PR_HOME_ADDRESS_STREET, TRUE, ids_ExportHomeAddressStreet, NULL, NULL,
PR_HOME_ADDRESS_CITY, TRUE, ids_ExportHomeAddressCity, NULL, NULL,
PR_HOME_ADDRESS_POSTAL_CODE, TRUE, ids_ExportHomeAddressPostalCode, NULL, NULL,
PR_HOME_ADDRESS_STATE_OR_PROVINCE, TRUE, ids_ExportHomeAddressState, NULL, NULL,
PR_HOME_ADDRESS_COUNTRY, TRUE, ids_ExportHomeAddressCountry, NULL, NULL,
PR_HOME_TELEPHONE_NUMBER, TRUE, ids_ExportHomeTelephoneNumber, NULL, NULL,
PR_HOME_FAX_NUMBER, FALSE, ids_ExportHomeFaxNumber, NULL, NULL,
PR_CELLULAR_TELEPHONE_NUMBER, FALSE, ids_ExportCellularTelephoneNumber, NULL, NULL,
PR_PERSONAL_HOME_PAGE, FALSE, ids_ExportPersonalHomePage, NULL, NULL,
// Business Pane
PR_BUSINESS_ADDRESS_STREET, TRUE, ids_ExportBusinessAddressStreet, NULL, NULL,
PR_BUSINESS_ADDRESS_CITY, TRUE, ids_ExportBusinessAddressCity, NULL, NULL,
PR_BUSINESS_ADDRESS_POSTAL_CODE, TRUE, ids_ExportBusinessAddressPostalCode, NULL, NULL,
PR_BUSINESS_ADDRESS_STATE_OR_PROVINCE, TRUE, ids_ExportBusinessAddressStateOrProvince, NULL, NULL,
PR_BUSINESS_ADDRESS_COUNTRY, TRUE, ids_ExportBusinessAddressCountry, NULL, NULL,
PR_BUSINESS_HOME_PAGE, FALSE, ids_ExportBusinessHomePage, NULL, NULL,
PR_BUSINESS_TELEPHONE_NUMBER, TRUE, ids_ExportBusinessTelephoneNumber, NULL, NULL,
PR_BUSINESS_FAX_NUMBER, FALSE, ids_ExportBusinessFaxNumber, NULL, NULL,
PR_PAGER_TELEPHONE_NUMBER, FALSE, ids_ExportPagerTelephoneNumber, NULL, NULL,
PR_COMPANY_NAME, TRUE, ids_ExportCompanyName, NULL, NULL,
PR_TITLE, TRUE, ids_ExportTitle, NULL, NULL,
PR_DEPARTMENT_NAME, FALSE, ids_ExportDepartmentName, NULL, NULL,
PR_OFFICE_LOCATION, FALSE, ids_ExportOfficeLocation, NULL, NULL,
// Notes Pane
PR_COMMENT, FALSE, ids_ExportComment, NULL, NULL,
};
/***************************************************************************
Name : StateExportMU
Purpose : Start the migration of MailUsers
Parameters: hwnd = window handle of Export Dialog
Returns : none
Comment : Login to MAPI
Open the WAB
Open the MAPI AB
Open the WAB container
Get the WAB contents table
Restrict it to PR_OBJECTTYPE == MAPI_MAILUSER
Post new state(STATE_NEXT_MU)
***************************************************************************/
void StateExportMU(HWND hwnd) {
HRESULT hResult;
ULONG ulFlags;
ULONG cbPABEID, cbWABEID;
LPENTRYID lpPABEID = NULL, lpWABEID = NULL;
ULONG ulObjType;
ULONG_PTR ulUIParam = (ULONG_PTR)(void *)hwnd;
SRestriction restrictObjectType;
SPropValue spvObjectType;
ULONG cProps;
TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
WAB_PARAM wp = {0};
LPWAB_PARAM lpwp = NULL;
//
// Logon to MAPI and open the MAPI Address book, if one exists
//
DebugTrace(">>> STATE_EXPORT_MU\n");
SetDialogMessage(hwnd, IDS_STATE_LOGGING_IN);
if (FAILED(hResult = MAPIInitialize(NULL))) {
DebugTrace("MAPIInitialize -> %x\n", GetScode(hResult));
switch (GetScode(hResult)) {
case MAPI_E_NOT_ENOUGH_MEMORY:
SetDialogMessage(hwnd, IDS_ERROR_NOT_ENOUGH_MEMORY);
break;
case MAPI_E_NOT_ENOUGH_DISK:
SetDialogMessage(hwnd, IDS_ERROR_NOT_ENOUGH_DISK);
break;
default:
case MAPI_E_NOT_FOUND:
case MAPI_E_NOT_INITIALIZED:
SetDialogMessage(hwnd, IDS_ERROR_MAPI_DLL_NOT_FOUND);
break;
}
#ifdef OLD_STUFF
ShowWindow(GetDlgItem(hwnd, IDC_Progress), SW_HIDE); // hide progress bar
#endif // OLD_STUFF
fError = TRUE;
hResult = hrSuccess;
goto exit;
}
ulFlags = MAPI_LOGON_UI | MAPI_NO_MAIL | MAPI_EXTENDED;
if (FAILED(hResult = MAPILogonEx(ulUIParam,
NULL,
NULL,
ulFlags,
(LPMAPISESSION FAR *)&lpMAPISession))) {
DebugTrace("MAPILogonEx -> %x\n", GetScode(hResult));
switch (GetScode(hResult)) {
case MAPI_E_USER_CANCEL:
SetDialogMessage(hwnd, IDS_STATE_EXPORT_IDLE);
break;
case MAPI_E_NOT_INITIALIZED:
SetDialogMessage(hwnd, IDS_ERROR_MAPI_DLL_NOT_FOUND);
break;
default:
SetDialogMessage(hwnd, IDS_ERROR_MAPI_LOGON);
break;
}
#ifdef OLD_STUFF
ShowWindow(GetDlgItem(hwnd, IDC_Progress), SW_HIDE); // hide progress bar
#endif // OLD_STUFF
fError = TRUE;
hResult = hrSuccess;
goto exit;
}
if (hResult = lpMAPISession->lpVtbl->OpenAddressBook(lpMAPISession, (ULONG_PTR)(void *)hwnd,
NULL,
0,
&lpAdrBookMAPI)) {
DebugTrace("OpenAddressBook(MAPI) -> %x", GetScode(hResult));
if(FAILED(hResult)) {
goto exit;
}
}
if (! lpAdrBookMAPI) {
DebugTrace("MAPILogonEx didn't return a valid AdrBook object\n");
goto exit;
}
//
// Open the MAPI PAB container
//
// [PaulHi] Raid #63578 1/7/98
// Correctly check return code and provide user error message if
// Exchange PAB cannot be opened.
//
hResult = lpAdrBookMAPI->lpVtbl->GetPAB(lpAdrBookMAPI,
&cbPABEID,
&lpPABEID);
if (HR_FAILED(hResult))
{
DebugTrace("MAPI GetPAB -> %x\n", GetScode(hResult));
goto exit;
}
else
{
hResult = lpAdrBookMAPI->lpVtbl->OpenEntry(lpAdrBookMAPI,
cbPABEID, // size of EntryID to open
lpPABEID, // EntryID to open
NULL, // interface
MAPI_MODIFY, // flags
&ulObjType,
(LPUNKNOWN *)&lpContainerMAPI);
if (HR_FAILED(hResult))
{
DebugTrace("MAPI OpenEntry(PAB) -> %x\n", GetScode(hResult));
goto exit;
}
}
Assert(lpAdrBookWAB);
//
// Open the WAB's PAB container
//
if (hResult = lpAdrBookWAB->lpVtbl->GetPAB(lpAdrBookWAB,
&cbWABEID,
&lpWABEID)) {
DebugTrace("WAB GetPAB -> %x\n", GetScode(hResult));
goto exit;
} else {
if (hResult = lpAdrBookWAB->lpVtbl->OpenEntry(lpAdrBookWAB,
cbWABEID, // size of EntryID to open
lpWABEID, // EntryID to open
NULL, // interface
0, // flags
&ulObjType,
(LPUNKNOWN *)&lpContainerWAB)) {
DebugTrace("WAB OpenEntry(PAB) -> %x\n", GetScode(hResult));
goto exit;
}
}
// Get the PAB's creation entryids
hResult = lpContainerMAPI->lpVtbl->GetProps(lpContainerMAPI,
(LPSPropTagArray)&ptaCon,
0,
&cProps,
&lpCreateEIDsMAPI);
if (HR_FAILED(hResult))
{
DebugTrace("Can't get container properties for PAB\n");
// Bad stuff here!
hResult = ResultFromScode(MAPI_E_NOT_FOUND);
goto exit;
}
// Validate the properites
if (lpCreateEIDsMAPI[iconPR_DEF_CREATE_MAILUSER].ulPropTag != PR_DEF_CREATE_MAILUSER ||
lpCreateEIDsMAPI[iconPR_DEF_CREATE_DL].ulPropTag != PR_DEF_CREATE_DL)
{
DebugTrace("MAPI: Container property errors\n");
hResult = ResultFromScode(MAPI_E_NOT_FOUND);
goto exit;
}
//
// All set... now loop through the WAB's entries, copying them to PAB
//
if (HR_FAILED(hResult = lpContainerWAB->lpVtbl->GetContentsTable(lpContainerWAB,
0, // ulFlags
&lpContentsTableWAB))) {
DebugTrace("WAB GetContentsTable(PAB Table) -> %x\n", GetScode(hResult));
goto exit;
}
// Set the columns to those we're interested in
if (hResult = lpContentsTableWAB->lpVtbl->SetColumns(lpContentsTableWAB,
(LPSPropTagArray)&ptaColumns,
0)) {
DebugTrace("WAB SetColumns(PAB Table) -> %x\n", GetScode(hResult));
goto exit;
}
// Restrict the table to MAPI_MAILUSERs
// If the convenient depth flag was not specified we restrict on
// PR_DEPTH == 1.
spvObjectType.ulPropTag = PR_OBJECT_TYPE;
spvObjectType.Value.l = MAPI_MAILUSER;
restrictObjectType.rt = RES_PROPERTY;
restrictObjectType.res.resProperty.relop = RELOP_EQ;
restrictObjectType.res.resProperty.ulPropTag = PR_OBJECT_TYPE;
restrictObjectType.res.resProperty.lpProp = &spvObjectType;
if (HR_FAILED(hResult = lpContentsTableWAB->lpVtbl->Restrict(lpContentsTableWAB,
&restrictObjectType,
0))) {
DebugTrace("WAB Restrict (MAPI_MAILUSER) -> %x\n", GetScode(hResult));
goto exit;
}
SetDialogMessage(hwnd, IDS_STATE_EXPORT_MU);
// Initialize the Progress Bar
// How many MailUser entries are there?
ulcEntries = CountRows(lpContentsTableWAB, FALSE);
DebugTrace("WAB contains %u MailUser entries\n", ulcEntries);
SetDialogProgress(hwnd, ulcEntries, 0);
exit:
if (lpWABEID) {
WABFreeBuffer(lpWABEID);
}
if (lpPABEID) {
MAPIFreeBuffer(lpPABEID);
}
// On error, set the state to STATE_ERROR
if (HR_FAILED(hResult))
{
if (GetScode(hResult) == MAPI_E_USER_CANCEL)
{
NewState(hwnd, STATE_EXPORT_CANCEL);
}
else
{
// [PaulHi] 1/7/98 Error reporting is hosed
// Display error message here to the user to ensure they
// get it.
{
TCHAR tszBuffer[MAX_RESOURCE_STRING];
TCHAR tszBufferTitle[MAX_RESOURCE_STRING];
if ( !LoadString(hInst, IDS_STATE_EXPORT_ERROR_NOPAB, tszBuffer, MAX_RESOURCE_STRING-1) )
{
Assert(0);
tszBuffer[0] = '\0';
}
if ( !LoadString(hInst, IDS_APP_TITLE, tszBufferTitle, MAX_RESOURCE_STRING-1) )
{
Assert(0);
tszBufferTitle[0] = '\0';
}
MessageBox(hwnd, tszBuffer, tszBufferTitle, MB_ICONEXCLAMATION | MB_OK);
}
NewState(hwnd, STATE_EXPORT_ERROR);
}
}
else if (fError)
{
NewState(hwnd, STATE_EXPORT_FINISH); // must be logon error
}
else
{
NewState(hwnd, STATE_EXPORT_NEXT_MU);
}
}
/***************************************************************************
Name : StateExportNextMU
Purpose : Migrate the next MailUser object
Parameters: hwnd = window handle of Export Dialog
Returns : none
Comment : QueryRows on the global WAB contents table
if there was a row
Migrate the entry to the PAB
Re-post STATE_EXPORT_NEXT_MU
else
Post STATE_EXPORT_DL
***************************************************************************/
void StateExportNextMU(HWND hwnd) {
ULONG cRows = 0;
HRESULT hResult;
LPSRowSet lpRow = NULL;
DebugTrace(">>> STATE_EXPORT_NEXT_MU\n");
Assert(lpContentsTableWAB);
// Get the next WAB entry
if (hResult = lpContentsTableWAB->lpVtbl->QueryRows(lpContentsTableWAB,
1, // one row at a time
0, // ulFlags
&lpRow)) {
DebugTrace("QueryRows -> %x\n", GetScode(hResult));
goto exit;
}
if (lpRow) {
if (cRows = lpRow->cRows) { // Yes, single '='
Assert(lpRow->cRows == 1);
Assert(lpRow->aRow[0].cValues == iptaColumnsMax);
Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].ulPropTag == PR_ENTRYID);
Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].ulPropTag == PR_OBJECT_TYPE);
if (cRows = lpRow->cRows) { // yes, single '='
hResult = ExportEntry(hwnd,
lpAdrBookWAB,
lpContainerMAPI,
lpCreateEIDsMAPI,
lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].Value.l,
(LPENTRYID)lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.lpb,
lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.cb,
NULL,
NULL,
FALSE,
FALSE);
// Update Progress Bar
// ignore errors!
SetDialogProgress(hwnd, ulcEntries, ++ulcDone);
if (hResult) {
if (HandleExportError(hwnd,
0,
hResult,
lpRow->aRow[0].lpProps[iptaColumnsPR_DISPLAY_NAME].Value.LPSZ,
PropStringOrNULL(&lpRow->aRow[0].lpProps[iptaColumnsPR_EMAIL_ADDRESS]),
lpExportOptions)) {
hResult = ResultFromScode(MAPI_E_USER_CANCEL);
} else {
hResult = hrSuccess;
}
}
} // else, drop out of loop, we're done.
}
WABFreeProws(lpRow);
}
exit:
// On error, set the state to STATE_ERROR
if (HR_FAILED(hResult)) {
if (GetScode(hResult) == MAPI_E_USER_CANCEL) {
NewState(hwnd, STATE_EXPORT_CANCEL);
} else {
NewState(hwnd, STATE_EXPORT_ERROR);
}
} else {
if (cRows) {
NewState(hwnd, STATE_EXPORT_NEXT_MU);
} else {
NewState(hwnd, STATE_EXPORT_DL);
}
}
}
/***************************************************************************
Name : StateExportDL
Purpose : Start migration of DISTLIST objects
Parameters: hwnd = window handle of Export Dialog
Returns : none
Comment : Set a new restriction on the contents table, selecting
DISTLIST objects only.
Post STATE_EXPORT_NEXT_DL
***************************************************************************/
void StateExportDL(HWND hwnd) {
HRESULT hResult;
SRestriction restrictObjectType;
SPropValue spvObjectType;
TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
DebugTrace(">>> STATE_EXPORT_DL\n");
// Restrict the table to MAPI_MAILUSERs
// If the convenient depth flag was not specified we restrict on
// PR_DEPTH == 1.
spvObjectType.ulPropTag = PR_OBJECT_TYPE;
spvObjectType.Value.l = MAPI_DISTLIST;
restrictObjectType.rt = RES_PROPERTY;
restrictObjectType.res.resProperty.relop = RELOP_EQ;
restrictObjectType.res.resProperty.ulPropTag = PR_OBJECT_TYPE;
restrictObjectType.res.resProperty.lpProp = &spvObjectType;
if (HR_FAILED(hResult = lpContentsTableWAB->lpVtbl->Restrict(lpContentsTableWAB,
&restrictObjectType,
0))) {
DebugTrace("WAB Restrict (MAPI_DISTLIST) -> %x\n", GetScode(hResult));
goto exit;
}
// Restrict resets the current position to the beginning of the table, by definition.
SetDialogMessage(hwnd, IDS_STATE_EXPORT_DL);
// Initialize the Progress Bar
// How many entries are there?
ulcEntries = CountRows(lpContentsTableWAB, FALSE);
DebugTrace("WAB contains %u Distribution List entries\n", ulcEntries);
if (ulcEntries) {
SetDialogProgress(hwnd, ulcEntries, 0);
}
exit:
// On error, set the state to STATE_ERROR
if (HR_FAILED(hResult)) {
if (GetScode(hResult) == MAPI_E_USER_CANCEL) {
NewState(hwnd, STATE_EXPORT_CANCEL);
} else {
NewState(hwnd, STATE_EXPORT_ERROR);
}
} else {
NewState(hwnd, STATE_EXPORT_NEXT_DL);
}
}
/***************************************************************************
Name : StateExportNextDL
Purpose : Migrate the next DISTLIST object
Parameters: hwnd = window handle of Export Dialog
Returns : none
Comment : QueryRows on the global WAB contents table
if there was a row
Migrate the DistList to the PAB
Re-post STATE_EXPORT_NEXT_DL
else
Post STATE_EXPORT_FINISH
***************************************************************************/
void StateExportNextDL(HWND hwnd) {
ULONG cRows = 0;
HRESULT hResult;
LPSRowSet lpRow = NULL;
DebugTrace(">>> STATE_EXPORT_NEXT_DL\n");
// Get the next WAB entry
if (hResult = lpContentsTableWAB->lpVtbl->QueryRows(lpContentsTableWAB,
1, // one row at a time
0, // ulFlags
&lpRow)) {
DebugTrace("QueryRows -> %x\n", GetScode(hResult));
goto exit;
}
if (lpRow) {
if (cRows = lpRow->cRows) { // Yes, single '='
Assert(lpRow->cRows == 1);
Assert(lpRow->aRow[0].cValues == iptaColumnsMax);
Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].ulPropTag == PR_ENTRYID);
Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].ulPropTag == PR_OBJECT_TYPE);
if (cRows = lpRow->cRows) { // yes, single '='
hResult = ExportEntry(hwnd,
lpAdrBookWAB,
lpContainerMAPI,
lpCreateEIDsMAPI,
lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].Value.l,
(LPENTRYID)lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.lpb,
lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.cb,
NULL,
NULL,
FALSE,
FALSE);
// Update Progress Bar
SetDialogProgress(hwnd, ulcEntries, ++ulcDone);
if (hResult) {
if (HandleExportError(hwnd,
0,
hResult,
lpRow->aRow[0].lpProps[iptaColumnsPR_DISPLAY_NAME].Value.LPSZ,
PropStringOrNULL(&lpRow->aRow[0].lpProps[iptaColumnsPR_EMAIL_ADDRESS]),
lpExportOptions)) {
hResult = ResultFromScode(MAPI_E_USER_CANCEL);
} else {
hResult = hrSuccess;
}
}
} // else, drop out of loop, we're done.
}
WABFreeProws(lpRow);
}
exit:
// On error, set the state to STATE_ERROR
if (HR_FAILED(hResult)) {
if (GetScode(hResult) == MAPI_E_USER_CANCEL) {
NewState(hwnd, STATE_EXPORT_CANCEL);
} else {
NewState(hwnd, STATE_EXPORT_ERROR);
}
} else {
if (cRows) {
NewState(hwnd, STATE_EXPORT_NEXT_DL);
} else {
// Update Progress Bar to indicate completion
SetDialogProgress(hwnd, ulcEntries, ulcEntries);
NewState(hwnd, STATE_EXPORT_FINISH);
}
}
}
/***************************************************************************
Name : StateExportFinish
Purpose : Clean up after the migration process
Parameters: hwnd = window handle of Export Dialog
Returns : none
Comment : Clean up the global MAPI objects and buffers
Clean up the global WAB objects and buffers.
Re-enable the Export button on the UI.
***************************************************************************/
void StateExportFinish(HWND hwnd) {
TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
TCHAR szBufferTitle[MAX_RESOURCE_STRING + 1];
DebugTrace(">>> STATE_EXPORT_FINISH\n");
//
// Cleanup MAPI
//
if (lpContainerMAPI) {
lpContainerMAPI->lpVtbl->Release(lpContainerMAPI);
lpContainerMAPI = NULL;
}
if (lpAdrBookMAPI) {
lpAdrBookMAPI->lpVtbl->Release(lpAdrBookMAPI);
lpAdrBookMAPI = NULL;
}
if(lpMAPISession){
lpMAPISession->lpVtbl->Logoff(lpMAPISession, (ULONG_PTR)(void *)hwnd,
MAPI_LOGOFF_UI,
0);
lpMAPISession->lpVtbl->Release(lpMAPISession);
lpMAPISession = NULL;
}
//
// Cleanup the WAB
//
if (lpContentsTableWAB) {
lpContentsTableWAB->lpVtbl->Release(lpContentsTableWAB);
lpContentsTableWAB = NULL;
}
if (lpCreateEIDsWAB) {
WABFreeBuffer(lpCreateEIDsWAB);
lpCreateEIDsWAB = NULL;
}
if (lpContainerWAB) {
lpContainerWAB->lpVtbl->Release(lpContainerWAB);
lpContainerWAB = NULL;
}
#ifdef OLD_STUFF // Don't release AdrBookWAB or WABObject
if (lpAdrBookWAB) {
lpAdrBookWAB->lpVtbl->Release(lpAdrBookWAB);
lpAdrBookWAB = NULL;
}
if (lpWABObject) {
lpWABObject->lpVtbl->Release(lpWABObject);
lpWABObject = NULL;
}
#endif // OLD_STUFF
// Cleanup the cache
FreeSeenList();
if (! fError) { // Leave error state displayed
if (LoadString(hInst, IDS_STATE_EXPORT_COMPLETE, szBuffer, ARRAYSIZE(szBuffer))) {
DebugTrace("Status Message: %s\n", szBuffer);
SetDlgItemText(hwnd, IDC_Message, szBuffer);
if (! LoadString(hInst, IDS_APP_TITLE, szBufferTitle, ARRAYSIZE(szBufferTitle))) {
StrCpyN(szBufferTitle, "", ARRAYSIZE(szBufferTitle));
}
#ifdef OLD_STUFF
// Display a dialog telling user it's over
MessageBox(hwnd, szBuffer,
szBufferTitle, MB_ICONINFORMATION | MB_OK);
#endif // OLD_STUFF
}
#ifdef OLD_STUFF
ShowWindow(GetDlgItem(hwnd, IDC_Progress), SW_HIDE);
#endif // OLD_STUFF
}
fError = FALSE;
// Re-enable the Export button here.
EnableWindow(GetDlgItem(hwnd, IDC_Export), TRUE);
// Change the Cancel button to Close
if (LoadString(hInst, IDS_BUTTON_CLOSE, szBuffer, ARRAYSIZE(szBuffer))) {
SetDlgItemText(hwnd, IDCANCEL, szBuffer);
}
}
/***************************************************************************
Name : StateExportError
Purpose : Report fatal error and cleanup.
Parameters: hwnd = window handle of Export Dialog
Returns : none
Comment : Report error and post STATE_EXPORT_FINISH.
***************************************************************************/
void StateExportError(HWND hwnd) {
TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
// Set some global flag and set state to finish
DebugTrace(">>> STATE_EXPORT_ERROR\n");
fError = TRUE;
SetDialogMessage(hwnd, IDS_STATE_EXPORT_ERROR);
NewState(hwnd, STATE_EXPORT_FINISH);
}
/***************************************************************************
Name : StateExportCancel
Purpose : Report cancel error and cleanup.
Parameters: hwnd = window handle of Export Dialog
Returns : none
Comment : Report error and post STATE_EXPORT_FINISH.
***************************************************************************/
void StateExportCancel(HWND hwnd) {
TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
// Set some global flag and set state to finish
DebugTrace(">>> STATE_EXPORT_CANCEL\n");
fError = TRUE;
SetDialogMessage(hwnd, IDS_STATE_EXPORT_CANCEL);
NewState(hwnd, STATE_EXPORT_FINISH);
}
/***************************************************************************
Name : HrFilterExportMailUserProps
Purpose : Filters out undesirable properties from the property array.
Converts known email address types to SMTP.
Moves FAX address to PR_BUSINESS_FAX_NUMBER.
Parameters: lpcProps -> IN: Input number of properties
OUT: Output number of properties
lppProps -> IN: Input property array (MAPI allocation)
OUT: Output property array (WAB allocation)
lpObjectWAB -> WAB object (used to get extra props)
lpfDL -> flag to set FALSE if we change a DL to a MAILUSER
(ie, for an EXchange DL)
Returns : HRESULT
Comment : Setting the property tag in the array to PR_NULL effectively
nulls this property out. We can re-use these in the second
pass.
Caller should use MAPIFreeBuffer to free *lppProps.
This routine will free the input value of *lppProps.
WARNING: This routine will add dummy properties to the
input WAB object, so don't go doing SaveChanges on it!
***************************************************************************/
#define MAX_ADD_PROPS 2
#define PR_DUMMY_1 PROP_TAG(PT_LONG, 0xF000)
#define PR_DUMMY_2 PROP_TAG(PT_LONG, 0xF001)
HRESULT HrFilterExportMailUserProps(LPULONG lpcProps, LPSPropValue * lppProps,
LPMAPIPROP lpObjectWAB, LPBOOL lpfDL) {
HRESULT hResult = hrSuccess;
ULONG i;
LPSPropValue lpPropsWAB, lpPropsMAPI = NULL;
ULONG cbProps;
SCODE sc;
ULONG cProps;
ULONG iPR_ADDRTYPE = NOT_FOUND;
ULONG iPR_EMAIL_ADDRESS = NOT_FOUND;
ULONG iPR_PRIMARY_FAX_NUMBER = NOT_FOUND;
ULONG iPR_BUSINESS_FAX_NUMBER = NOT_FOUND;
ULONG iPR_MSNINET_DOMAIN = NOT_FOUND;
ULONG iPR_MSNINET_ADDRESS = NOT_FOUND;
ULONG iPR_DISPLAY_NAME = NOT_FOUND;
ULONG iPR_OBJECT_TYPE = NOT_FOUND;
ULONG iPR_SEND_RICH_INFO = NOT_FOUND;
LPSBinary lpEntryID = NULL;
LPTSTR lpTemp;
BOOL fBadAddress = FALSE;
SPropValue rgPropsDummy[MAX_ADD_PROPS] = {
PR_DUMMY_1, 0, 1,
PR_DUMMY_2, 0, 2,
};
// Set extra bogus props on the object in case we need to add more props
// to the array later. These will be PR_NULL'ed out by the first pass.
if (HR_FAILED(hResult = lpObjectWAB->lpVtbl->SetProps(lpObjectWAB,
MAX_ADD_PROPS,
rgPropsDummy,
NULL))) {
DebugTrace("HrFilterExportMailUserProps:SetProps dummy props -> %x\n", GetScode(hResult));
// ignore the error
}
// Get the properties from this entry
if (HR_FAILED(hResult = lpObjectWAB->lpVtbl->GetProps(lpObjectWAB,
NULL,
0,
&cProps,
&lpPropsWAB))) {
DebugTrace("HrFilterExportMailUserProps:GetProps(WAB) -> %x\n", GetScode(hResult));
return(hResult);
}
// WABDebugProperties(lpPropsWAB, *lpcProps, "MailUser BEFORE");
// First pass: Remove the junk
for (i = 0; i < cProps; i++) {
// Error value
if (PROP_ERROR(lpPropsWAB[i])) {
lpPropsWAB[i].ulPropTag = PR_NULL;
continue;
}
// Named property
if (PROP_ID(lpPropsWAB[i].ulPropTag) >= MIN_NAMED_PROPID) {
lpPropsWAB[i].ulPropTag = PR_NULL;
continue;
}
// Object property
if (PROP_TYPE(lpPropsWAB[i].ulPropTag) == PT_OBJECT) {
lpPropsWAB[i].ulPropTag = PR_NULL;
continue;
}
switch (lpPropsWAB[i].ulPropTag) {
case PR_ENTRYID:
lpEntryID = &lpPropsWAB[i].Value.bin;
// fall through
case PR_PRIMARY_CAPABILITY:
case PR_TEMPLATEID:
case PR_SEARCH_KEY:
case PR_INITIAL_DETAILS_PANE:
case PR_RECORD_KEY:
case PR_MAPPING_SIGNATURE:
lpPropsWAB[i].ulPropTag = PR_NULL;
break;
case PR_COMMENT:
// Don't save PR_COMMENT if it is empty
if (lstrlen(lpPropsWAB[i].Value.LPSZ) == 0) {
lpPropsWAB[i].ulPropTag = PR_NULL;
}
break;
// Keep track of the position of these for later
case PR_ADDRTYPE:
iPR_ADDRTYPE = i;
break;
case PR_OBJECT_TYPE:
iPR_OBJECT_TYPE = i;
break;
case PR_EMAIL_ADDRESS:
iPR_EMAIL_ADDRESS = i;
break;
case PR_PRIMARY_FAX_NUMBER:
iPR_PRIMARY_FAX_NUMBER = i;
break;
case PR_BUSINESS_FAX_NUMBER:
iPR_BUSINESS_FAX_NUMBER = i;
break;
case PR_MSNINET_ADDRESS:
iPR_MSNINET_ADDRESS = i;
break;
case PR_MSNINET_DOMAIN:
iPR_MSNINET_DOMAIN = i;
break;
case PR_DISPLAY_NAME:
iPR_DISPLAY_NAME = i;
break;
case PR_SEND_RICH_INFO:
iPR_SEND_RICH_INFO = i;
break;
}
// Put this after the switch since we do want to track a few props which fall in
// the 0x6000 range but don't want to transfer them to the wab.
if (PROP_ID(lpPropsWAB[i].ulPropTag) >= MAX_SCHEMA_PROPID) {
lpPropsWAB[i].ulPropTag = PR_NULL;
continue;
}
}
// Second pass: Fix up the addresses
if (iPR_ADDRTYPE != NOT_FOUND) {
if (! lstrcmpi(lpPropsWAB[iPR_ADDRTYPE].Value.LPSZ, szSMTP)) {
DebugTrace("SMTP address for %s\n", lpPropsWAB[iPR_DISPLAY_NAME].Value.LPSZ);
} else if (! lstrcmpi(lpPropsWAB[iPR_ADDRTYPE].Value.LPSZ, szMAPIPDL)) {
DebugTrace("MAPIPDL %s\n", lpPropsWAB[iPR_DISPLAY_NAME].Value.LPSZ);
// Distribution list, ignore it.
} else {
WABDebugProperties(lpPropsWAB, cProps, "Unknown address type");
DebugTrace("Found unknown PR_ADDRTYPE: %s\n", lpPropsWAB[iPR_ADDRTYPE].Value.LPSZ);
Assert(FALSE);
}
}
// PR_BUSINESS_FAX_NUMBER?
// The PAB puts the Fax number in PR_PRIMARY_FAX_NUMBER, but the WAB UI splits it
// into PR_BUSINESS_FAX_NUMBER and PR_HOME_FAX_NUMBER. We always map business to
// Primary fax number and ignore home fax number.
if ((iPR_BUSINESS_FAX_NUMBER != NOT_FOUND) && (iPR_PRIMARY_FAX_NUMBER == NOT_FOUND)) {
// We need to also have a PR_PRIMARY_FAX_NUMBER
// Find the next PR_NULL spot.
iPR_PRIMARY_FAX_NUMBER = iPR_BUSINESS_FAX_NUMBER; // overwrite this one if there isn't
// an available slot in the prop array.
for (i = 0; i < cProps; i++) {
if (lpPropsWAB[i].ulPropTag == PR_NULL) {
iPR_PRIMARY_FAX_NUMBER = i;
lpPropsWAB[iPR_PRIMARY_FAX_NUMBER].Value.LPSZ =
lpPropsWAB[iPR_BUSINESS_FAX_NUMBER].Value.LPSZ;
break;
}
}
lpPropsWAB[iPR_PRIMARY_FAX_NUMBER].ulPropTag = PR_PRIMARY_FAX_NUMBER;
}
// If there is no PR_SEND_RICH_INFO, make one and set it FALSE
if (iPR_SEND_RICH_INFO == NOT_FOUND) {
// Find the next PR_NULL and put it there.
for (i = 0; i < cProps; i++) {
if (lpPropsWAB[i].ulPropTag == PR_NULL) {
iPR_SEND_RICH_INFO = i;
lpPropsWAB[iPR_SEND_RICH_INFO].Value.b = FALSE;
lpPropsWAB[iPR_SEND_RICH_INFO].ulPropTag = PR_SEND_RICH_INFO;
break;
}
}
Assert(iPR_SEND_RICH_INFO != NOT_FOUND);
}
// Get rid of PR_NULL props
for (i = 0; i < cProps; i++) {
if (lpPropsWAB[i].ulPropTag == PR_NULL) {
// Slide the props down.
if (i + 1 < cProps) { // Are there any higher props to copy?
CopyMemory(&lpPropsWAB[i], &lpPropsWAB[i + 1], ((cProps - i) - 1) * sizeof(lpPropsWAB[i]));
}
// decrement count
cProps--;
i--; // You overwrote the current propval. Look at it again.
}
}
// Reallocate as MAPI memory.
if (sc = ScCountProps(cProps, lpPropsWAB, &cbProps)) {
hResult = ResultFromScode(sc);
DebugTrace("ScCountProps -> %x\n", sc);
goto exit;
}
if (sc = MAPIAllocateBuffer(cbProps, &lpPropsMAPI)) {
hResult = ResultFromScode(sc);
DebugTrace("WABAllocateBuffer -> %x\n", sc);
goto exit;
}
if (sc = ScCopyProps(cProps,
lpPropsWAB,
lpPropsMAPI,
NULL)) {
hResult = ResultFromScode(sc);
DebugTrace("ScCopyProps -> %x\n", sc);
goto exit;
}
exit:
if (lpPropsWAB) {
WABFreeBuffer(lpPropsWAB);
}
if (HR_FAILED(hResult)) {
if (lpPropsMAPI) {
MAPIFreeBuffer(lpPropsMAPI);
lpPropsMAPI = NULL;
}
cProps = 0;
} else if (fBadAddress) {
hResult = ResultFromScode(WAB_W_BAD_EMAIL);
}
*lppProps = lpPropsMAPI;
*lpcProps = cProps;
return(hResult);
}
/***************************************************************************
Name : HandleExportError
Purpose : Decides if a dialog needs to be displayed to
indicate the failure and does so.
Parameters: hwnd = main dialog window
ids = String ID (optional: calculated from hResult if 0)
hResult = Result of action
lpDisplayName = display name of object that failed
lpEmailAddress = email address of object that failed (or NULL)
Returns : TRUE if user requests ABORT.
Comment : Abort is not yet implemented in the dialog, but if you
ever want to, just make this routine return TRUE;
***************************************************************************/
BOOL HandleExportError(HWND hwnd, ULONG ids, HRESULT hResult, LPTSTR lpDisplayName,
LPTSTR lpEmailAddress, LPWAB_EXPORT_OPTIONS lpExportOptions) {
BOOL fAbort = FALSE;
ERROR_INFO EI;
if ((ids || hResult) && ! lpExportOptions->fNoErrors) {
if (ids == 0) {
switch (GetScode(hResult)) {
case WAB_W_BAD_EMAIL:
ids = lpEmailAddress ? IDS_ERROR_EMAIL_ADDRESS_2 : IDS_ERROR_EMAIL_ADDRESS_1;
break;
case MAPI_E_NO_SUPPORT:
// Propbably failed to open contents on a distribution list
ids = IDS_ERROR_NO_SUPPORT;
break;
case MAPI_E_USER_CANCEL:
return(TRUE);
default:
if (HR_FAILED(hResult)) {
DebugTrace("Error Box for Hresult: 0x%08x\n", GetScode(hResult));
Assert(FALSE); // want to know about it.
ids = IDS_ERROR_GENERAL;
}
break;
}
}
EI.lpszDisplayName = lpDisplayName;
EI.lpszEmailAddress = lpEmailAddress;
EI.ErrorResult = ERROR_OK;
EI.ids = ids;
EI.fExport = TRUE;
EI.lpImportOptions = lpExportOptions;
DialogBoxParam(hInst,
MAKEINTRESOURCE(IDD_ErrorExport),
hwnd,
ErrorDialogProc,
(LPARAM)&EI);
fAbort = EI.ErrorResult == ERROR_ABORT;
}
return(fAbort);
}
/***************************************************************************
Name : AddEntryToExportList
Purpose : Checks this entry against our "seen" list and adds it.
Parameters: cbEID = size of lpEID
lpEID -> EntryID of entry
lplIndex -> returned list index (or -1 on error)
Returns : TRUE if entry already exists
Comment : Caller must mark the WAB entry!
***************************************************************************/
#define GROW_SIZE 10
BOOL AddEntryToExportList(ULONG cbEID, LPENTRYID lpEID, LPLONG lplIndex) {
ULONG i;
LPENTRY_SEEN lpEntrySeen;
if (cbEID && lpEID) {
for (i = 0; i < ulEntriesSeen; i++) {
if (cbEID == lpEntriesSeen[i].sbinPAB.cb && (! memcmp(lpEID, lpEntriesSeen[i].sbinPAB.lpb, cbEID))) {
// This one's in the list
*lplIndex = i;
// If cb 0, we must have recursed and are replacing, so this one is not a dup.
return(lpEntriesSeen[i].sbinWAB.cb != 0);
}
}
// Add to the end of the list
if (++ulEntriesSeen > ulMaxEntries) {
// Grow the array.
ulMaxEntries += GROW_SIZE;
if (lpEntriesSeen) {
if (! (lpEntrySeen = LocalReAlloc(lpEntriesSeen, ulMaxEntries * sizeof(ENTRY_SEEN), LMEM_MOVEABLE | LMEM_ZEROINIT))) {
DebugTrace("LocalReAlloc(%u) -> %u\n", ulMaxEntries * sizeof(ENTRY_SEEN), GetLastError());
goto error;
}
lpEntriesSeen = lpEntrySeen;
} else {
if (! (lpEntriesSeen = LocalAlloc(LPTR, ulMaxEntries * sizeof(ENTRY_SEEN)))) {
DebugTrace("LocalAlloc(%u) -> %u\n", ulMaxEntries * sizeof(ENTRY_SEEN), GetLastError());
goto error;
}
}
}
lpEntrySeen = &lpEntriesSeen[ulEntriesSeen - 1];
// Allocate space for data
lpEntrySeen->sbinPAB.cb = cbEID;
if (! (lpEntrySeen->sbinPAB.lpb = LocalAlloc(LPTR, cbEID))) {
DebugTrace("LocalAlloc(%u) -> %u\n", cbEID, GetLastError());
goto error;
}
// Mark as unknown WAB entry
lpEntrySeen->sbinWAB.cb = 0;
lpEntrySeen->sbinWAB.lpb = 0;
// Copy in the data
CopyMemory(lpEntrySeen->sbinPAB.lpb, lpEID, cbEID);
*lplIndex = i;
}
return(FALSE);
error:
// undo the damage...
--ulEntriesSeen;
ulMaxEntries -= GROW_SIZE;
*lplIndex = -1; // error
if (! lpEntriesSeen) {
ulEntriesSeen = 0; // pointer is null now, back to square one.
ulMaxEntries = 0;
}
return(FALSE);
}
/***************************************************************************
Name : MarkPABEntryInList
Purpose : Marks the PAB entry fields in the list node
Parameters: cbEID = size of lpEID
lpEID -> EntryID of entry
lIndex = list index (or -1 on error)
Returns : none
Comment :
***************************************************************************/
void MarkPABEntryInList(ULONG cbEID, LPENTRYID lpEID, LONG lIndex) {
if (lIndex != -1 && cbEID) {
if (! (lpEntriesSeen[lIndex].sbinWAB.lpb = LocalAlloc(LPTR, cbEID))) {
DebugTrace("LocalAlloc(%u) -> %u\n", cbEID, GetLastError());
// leave it null
} else {
lpEntriesSeen[lIndex].sbinWAB.cb = cbEID;
// Copy in the data
CopyMemory(lpEntriesSeen[lIndex].sbinWAB.lpb, lpEID, cbEID);
}
}
}
//
// Properties to get from the PAB Entry
//
enum {
ifePR_OBJECT_TYPE = 0,
ifePR_ENTRYID,
ifePR_DISPLAY_NAME,
ifePR_EMAIL_ADDRESS,
ifeMax
};
static const SizedSPropTagArray(ifeMax, ptaFind) =
{
ifeMax,
{
PR_OBJECT_TYPE,
PR_ENTRYID,
PR_DISPLAY_NAME,
PR_EMAIL_ADDRESS
}
};
/***************************************************************************
Name : FindPABEntry
Purpose : Finds the named entry in the PAB
Parameters: lpContainerPAB -> MAPI PAB container
ulObjectType = {MAPI_MAILUSER, MAPI_DISTLIST}
lpDisplayName = name of entry
lpEmailAddress = email address or NULL if none
lppEIDMAPI -> returned MAPI ENTRYID: Caller must MAPIFreeBuffer.
lpcbEIDMAPI -> returned size of lppEIDMAPI
Returns : HRESULT
Comment : At this point, we expect to find a match since
SaveChanges said we had a duplicate.
***************************************************************************/
HRESULT FindPABEntry(LPABCONT lpContainerPAB,
ULONG ulObjectType,
LPTSTR lpDisplayName,
LPTSTR lpEmailAddress,
LPULONG lpcbEIDDup,
LPENTRYID * lppEIDDup) {
HRESULT hResult = hrSuccess;
SCODE sc;
SRestriction resAnd[3]; // 0 = object type, 1 = displayname, 2 = emailaddress
SRestriction resFind;
SPropValue spvObjectType, spvDisplayName, spvEmailAddress;
LPSRowSet lpRow = NULL;
LPMAPITABLE lpTable = NULL;
ULONG rgFlagList[2];
LPFlagList lpFlagList = (LPFlagList)rgFlagList;
LPADRLIST lpAdrListMAPI = NULL;
LPSBinary lpsbEntryID;
ULONG i;
// init return values
*lppEIDDup = NULL;
*lpcbEIDDup = 0;
// find the existing PAB entry.
// Setup for ResolveNames on the PAB container.
if (sc = MAPIAllocateBuffer(sizeof(ADRLIST) + sizeof(ADRENTRY), &lpAdrListMAPI)) {
DebugTrace("MAPI Allocation(ADRLIST) failed -> %x\n", sc);
hResult = ResultFromScode(sc);
goto restrict;
}
lpAdrListMAPI->cEntries = 1;
lpAdrListMAPI->aEntries[0].ulReserved1 = 0;
lpAdrListMAPI->aEntries[0].cValues = 1;
if (sc = MAPIAllocateBuffer(sizeof(SPropValue), &lpAdrListMAPI->aEntries[0].rgPropVals)) {
DebugTrace("MAPI Allocation(ADRENTRY propval) failed -> %x\n", sc);
hResult = ResultFromScode(sc);
goto restrict;
}
lpFlagList->cFlags = 1;
for (i = 0; i <= 1; i++) {
switch (i) {
case 0: // pass 0
lpAdrListMAPI->aEntries[0].rgPropVals[0].ulPropTag = PR_DISPLAY_NAME;
lpAdrListMAPI->aEntries[0].rgPropVals[0].Value.LPSZ = lpDisplayName;
break;
case 1:
if (lpEmailAddress) {
lpAdrListMAPI->aEntries[0].rgPropVals[0].ulPropTag = PR_EMAIL_ADDRESS;
lpAdrListMAPI->aEntries[0].rgPropVals[0].Value.LPSZ = lpEmailAddress;
} else {
continue; // no email address, don't bother with second pass
}
break;
default:
Assert(FALSE);
}
lpFlagList->ulFlag[0] = MAPI_UNRESOLVED;
if (HR_FAILED(hResult = lpContainerPAB->lpVtbl->ResolveNames(lpContainerPAB,
NULL, // tag set
0, // ulFlags
lpAdrListMAPI,
lpFlagList))) {
DebugTrace("MAPI ResolveNames -> %x\n", GetScode(hResult));
continue;
}
switch (lpFlagList->ulFlag[0]) {
case MAPI_UNRESOLVED:
DebugTrace("WAB ResolveNames didn't find the entry %s\n", lpDisplayName);
continue;
case MAPI_AMBIGUOUS:
DebugTrace("WAB ResolveNames find ambiguous entry %s\n", lpDisplayName);
continue;
case MAPI_RESOLVED:
i = 2; // Found it, exit the loop
}
}
if (lpFlagList->ulFlag[0] == MAPI_RESOLVED) {
// Found one, find its PR_ENTRYID
if (! (lpsbEntryID = FindAdrEntryID(lpAdrListMAPI, 0))) {
DebugTrace("MAPI ResolveNames didn't give us an EntryID\n");
Assert(lpsbEntryID);
goto restrict;
}
*lpcbEIDDup = lpsbEntryID->cb;
if (FAILED(sc = MAPIAllocateBuffer(*lpcbEIDDup, lppEIDDup))) {
hResult = ResultFromScode(sc);
DebugTrace("FindPABEntry couldn't allocate duplicate entryid %x\n", sc);
goto exit;
}
memcpy(*lppEIDDup, lpsbEntryID->lpb, *lpcbEIDDup);
}
restrict:
if (! *lppEIDDup) {
//
// Last ditch effort... use a table restriction to try to find this entry.
//
// Get the contents table
if (HR_FAILED(hResult = lpContainerPAB->lpVtbl->GetContentsTable(lpContainerPAB,
0, // ulFlags
&lpTable))) {
DebugTrace("PAB GetContentsTable -> %x\n", GetScode(hResult));
goto exit;
}
// Set the columns
if (HR_FAILED(hResult = lpTable->lpVtbl->SetColumns(lpTable,
(LPSPropTagArray)&ptaFind,
0))) {
DebugTrace("PAB SetColumns-> %x\n", GetScode(hResult));
goto exit;
}
// Restrict to the object we care about
resAnd[0].rt = RES_PROPERTY; // Restriction type Property
resAnd[0].res.resProperty.relop = RELOP_EQ;
resAnd[0].res.resProperty.ulPropTag = PR_OBJECT_TYPE;
resAnd[0].res.resProperty.lpProp = &spvObjectType;
spvObjectType.ulPropTag = PR_OBJECT_TYPE;
spvObjectType.Value.ul = ulObjectType;
// Restrict to get correct display name
resAnd[1].rt = RES_PROPERTY; // Restriction type Property
resAnd[1].res.resProperty.relop = RELOP_EQ;
resAnd[1].res.resProperty.ulPropTag = PR_DISPLAY_NAME;
resAnd[1].res.resProperty.lpProp = &spvDisplayName;
spvDisplayName.ulPropTag = PR_DISPLAY_NAME;
spvDisplayName.Value.LPSZ = lpDisplayName;
if (lpEmailAddress) {
// Restrict to get correct email address
resAnd[2].rt = RES_PROPERTY; // Restriction type Property
resAnd[2].res.resProperty.relop = RELOP_EQ;
resAnd[2].res.resProperty.ulPropTag = PR_EMAIL_ADDRESS;
resAnd[2].res.resProperty.lpProp = &spvEmailAddress;
spvEmailAddress.ulPropTag = PR_EMAIL_ADDRESS;
spvEmailAddress.Value.LPSZ = lpEmailAddress;
}
resFind.rt = RES_AND;
resFind.res.resAnd.cRes = lpEmailAddress ? 3 : 2;
resFind.res.resAnd.lpRes = resAnd;
if (HR_FAILED(hResult = lpTable->lpVtbl->Restrict(lpTable,
&resFind,
0))) {
DebugTrace("FindPABEntry: Restrict -> %x", hResult);
goto exit;
}
if (hResult = lpTable->lpVtbl->QueryRows(lpTable,
1, // First row only
0, // ulFlags
&lpRow)) {
DebugTrace("FindPABEntry: QueryRows -> %x\n", GetScode(hResult));
} else {
// Found it, copy entryid to new allocation
if (lpRow->cRows) {
*lpcbEIDDup = lpRow->aRow[0].lpProps[ifePR_ENTRYID].Value.bin.cb;
if (FAILED(sc = MAPIAllocateBuffer(*lpcbEIDDup, lppEIDDup))) {
hResult = ResultFromScode(sc);
DebugTrace("FindPABEntry couldn't allocate duplicate entryid %x\n", sc);
goto exit;
}
memcpy(*lppEIDDup, lpRow->aRow[0].lpProps[ifePR_ENTRYID].Value.bin.lpb, *lpcbEIDDup);
} else {
hResult = ResultFromScode(MAPI_E_NOT_FOUND);
}
}
// Still not found?!! Maybe the PAB has a different idea of what the Display name is.
// Search just by email address.
if (hResult && lpEmailAddress) {
resAnd[1] = resAnd[2]; // copy the email address res over the display name res.
resFind.res.resAnd.cRes = 2;
if (HR_FAILED(hResult = lpTable->lpVtbl->Restrict(lpTable,
&resFind,
0))) {
DebugTrace("FindPABEntry: Restrict -> %x", hResult);
goto exit;
}
if (hResult = lpTable->lpVtbl->QueryRows(lpTable,
1, // First row only
0, // ulFlags
&lpRow)) {
DebugTrace("FindPABEntry: QueryRows -> %x\n", GetScode(hResult));
} else {
// Found it, copy entryid to new allocation
if (lpRow->cRows) {
*lpcbEIDDup = lpRow->aRow[0].lpProps[ifePR_ENTRYID].Value.bin.cb;
if (FAILED(sc = MAPIAllocateBuffer(*lpcbEIDDup, lppEIDDup))) {
hResult = ResultFromScode(sc);
DebugTrace("FindPABEntry couldn't allocate duplicate entryid %x\n", sc);
goto exit;
}
memcpy(*lppEIDDup, lpRow->aRow[0].lpProps[ifePR_ENTRYID].Value.bin.lpb, *lpcbEIDDup);
} else {
hResult = ResultFromScode(MAPI_E_NOT_FOUND);
DebugTrace("FindPABEntry coudln't find %s %s <%s>\n",
ulObjectType == MAPI_MAILUSER ? "Mail User" : "Distribution List",
lpDisplayName,
lpEmailAddress ? lpEmailAddress : "");
}
}
}
}
exit:
if (lpAdrListMAPI) {
FreePadrlist(lpAdrListMAPI);
}
if (lpRow) {
FreeProws(lpRow);
}
if (lpTable) {
lpTable->lpVtbl->Release(lpTable);
}
if (HR_FAILED(hResult) && *lppEIDDup) {
MAPIFreeBuffer(*lppEIDDup);
*lpcbEIDDup = 0;
*lppEIDDup = NULL;
}
if (hResult) {
DebugTrace("FindPABEntry coudln't find %s %s <%s>\n",
ulObjectType == MAPI_MAILUSER ? "Mail User" : "Distribution List",
lpDisplayName,
lpEmailAddress ? lpEmailAddress : "");
}
return(hResult);
}
// enum for setting the created properties
enum {
irnPR_DISPLAY_NAME = 0,
irnPR_RECIPIENT_TYPE,
irnPR_ENTRYID,
irnPR_EMAIL_ADDRESS,
irnMax
};
/***************************************************************************
Name : ExportEntry
Purpose : Migrates the entry from the WAB to the PAB
Parameters: hwnd = main dialog window
lpAdrBookWAB -> WAB AdrBook object
lpContainerMAPI -> MAPI PAB container
lpCreateEIDsMAPI -> SPropValue of default object creation EIDs
ulObjectType = {MAPI_MAILUSER, MAPI_DISTLIST}
lpEID -> ENTYRID of the WAB entry
cbEID = sizeof lpEID
lppEIDMAPI -> returned MAPI ENTRYID: Caller must MAPIFreeBuffer.
May be NULL.
lpcbEIDMAPI -> returned size of lppEIDMAPI (ignored if lppEIDMAPI
is NULL.
fInDL = TRUE if this entry is for creation in a Distribution List
fForceReplace = TRUE if this entry should replace any duplicate.
Returns : HRESULT
Comment : This routine is a MESS! Should break it up when we get time.
***************************************************************************/
HRESULT ExportEntry(HWND hwnd,
LPADRBOOK lpAdrBookWAB,
LPABCONT lpContainerMAPI,
LPSPropValue lpCreateEIDsMAPI,
ULONG ulObjectType,
LPENTRYID lpEID,
ULONG cbEID,
LPENTRYID * lppEIDMAPI,
LPULONG lpcbEIDMAPI,
BOOL fInDL,
BOOL fForceReplace) {
HRESULT hResult = hrSuccess;
SCODE sc;
BOOL fDistList = FALSE;
BOOL fDuplicate = FALSE;
BOOL fDuplicateEID;
BOOL fReturnEID = FALSE;
ULONG ulObjectTypeOpen;
LPDISTLIST lpDistListMAPI = NULL, lpDistListWAB = NULL;
LPMAPIPROP lpMailUserMAPI = NULL, lpMailUserWAB = NULL;
LPSPropValue lpProps = NULL;
ULONG cProps, cEIDPropMAPI;
LPMAPITABLE lpDLTableWAB = NULL;
ULONG cRows;
LPSRowSet lpRow = NULL;
LPENTRYID lpeidDLMAPI = NULL;
ULONG cbeidDLMAPI;
LPSPropValue lpEIDPropMAPI = NULL;
LPMAPIPROP lpEntryMAPI = NULL;
ULONG ulCreateFlags;
REPLACE_INFO RI;
LPTSTR lpDisplayName = NULL, lpEmailAddress = NULL;
static TCHAR szBufferDLMessage[MAX_RESOURCE_STRING + 1] = "";
LPTSTR lpszMessage;
LONG lListIndex = -1;
LPENTRYID lpEIDNew = NULL;
DWORD cbEIDNew = 0;
LPIID lpIIDOpen;
ULONG iCreateTemplate = iconPR_DEF_CREATE_MAILUSER;
BOOL fCreatedNew = FALSE;
LPENTRYID lpEIDDup = NULL;
ULONG cbEIDDup;
// Check the entry against our "seen" list
fDuplicateEID = AddEntryToExportList(cbEID, lpEID, &lListIndex);
if (! fDuplicateEID) {
// Set up some object type specific variables
switch (ulObjectType) {
default:
DebugTrace("ExportEntry got unknown object type %u, assuming MailUser\n", ulObjectType);
Assert(FALSE);
case MAPI_MAILUSER:
iCreateTemplate = iconPR_DEF_CREATE_MAILUSER;
lpIIDOpen = NULL;
fDistList = FALSE;
break;
case MAPI_DISTLIST:
iCreateTemplate = iconPR_DEF_CREATE_DL;
lpIIDOpen = (LPIID)&IID_IDistList;
fDistList = TRUE;
break;
}
// Open the entry
if (HR_FAILED(hResult = lpAdrBookWAB->lpVtbl->OpenEntry(lpAdrBookWAB,
cbEID,
lpEID,
lpIIDOpen,
MAPI_MODIFY, // need to do SetProps inside Filter routine, but won't save them.
&ulObjectTypeOpen,
(LPUNKNOWN *)&lpMailUserWAB))) {
DebugTrace("OpenEntry(WAB MailUser) -> %x\n", GetScode(hResult));
goto exit;
}
// If DISTLIST, assume we got lpMailUser until we need lpDistList.
Assert(lpMailUserWAB);
Assert(ulObjectType == ulObjectTypeOpen);
//
// NOTE: Must not fail between here and HrFilterExportMailUserProps because
// we will end up freeing lpProps with MAPIFreeBuffer.
//
// Get and filter the property array here
if (hResult = HrFilterExportMailUserProps(&cProps, &lpProps, lpMailUserWAB, &fDistList)) {
lpDisplayName = FindStringInProps(lpProps, cProps, PR_DISPLAY_NAME);
lpEmailAddress = FindStringInProps(lpProps, cProps, PR_EMAIL_ADDRESS);
if (HandleExportError(hwnd,
0,
hResult,
lpDisplayName,
lpEmailAddress,
lpExportOptions)) {
hResult = ResultFromScode(MAPI_E_USER_CANCEL);
goto exit;
}
}
// Find some interesting property values here
lpDisplayName = FindStringInProps(lpProps, cProps, PR_DISPLAY_NAME);
lpEmailAddress = FindStringInProps(lpProps, cProps, PR_EMAIL_ADDRESS);
if (ulObjectType == MAPI_DISTLIST && ! fDistList) {
// Filter must have changed this to a mailuser.
ulObjectType = MAPI_MAILUSER;
iCreateTemplate = iconPR_DEF_CREATE_MAILUSER;
lpIIDOpen = NULL;
}
if (fDistList) {
ulCreateFlags = CREATE_CHECK_DUP_LOOSE;
// PAB can't detect collisions on DL SaveChanges.
// See if this is a duplicate:
if (! HR_FAILED(hResult = FindPABEntry(lpContainerMAPI,
MAPI_DISTLIST,
lpDisplayName,
NULL,
&cbEIDDup,
&lpEIDDup))) {
// Found a duplicate. Keep track of it!
}
} else {
ulCreateFlags = CREATE_CHECK_DUP_STRICT;
}
//
// NOTE: lpProps after this point is MAPI Allocated rather than WAB allocated.
//
if (HR_FAILED(hResult = lpContainerMAPI->lpVtbl->CreateEntry(lpContainerMAPI,
lpCreateEIDsMAPI[iCreateTemplate].Value.bin.cb,
(LPENTRYID)lpCreateEIDsMAPI[iCreateTemplate].Value.bin.lpb,
ulCreateFlags,
&lpMailUserMAPI))) {
DebugTrace("CreateEntry(MAPI MailUser) -> %x\n", GetScode(hResult));
goto exit;
}
if (fDistList) {
// Update status message
if (*szBufferDLMessage == '\0') { // only load once, then keep it.
LoadString(hInst, IDS_MESSAGE_EXPORTING_DL, szBufferDLMessage, ARRAYSIZE(szBufferDLMessage));
}
if (lpDisplayName) {
ULONG cchSize =lstrlen(szBufferDLMessage) + 1 + lstrlen(lpDisplayName);
if (lpszMessage = LocalAlloc(LMEM_FIXED, sizeof(TCHAR)*cchSize)) {
wnsprintf(lpszMessage, cchSize, szBufferDLMessage, lpDisplayName);
DebugTrace("Status Message: %s\n", lpszMessage);
if (! SetDlgItemText(hwnd, IDC_Message, lpszMessage)) {
DebugTrace("SetDlgItemText -> %u\n", GetLastError());
}
LocalFree(lpszMessage);
}
}
}
if (! lpEIDDup) {
// If this was a DL which we know already exists, don't even bother writing it,
// just fall through to the collision pass. Otherwise, try to set the props
// and save it... if it fails, we'll get an hResult=MAPI_E_COLLISION.
// Set the properties on the PAB entry
if (HR_FAILED(hResult = lpMailUserMAPI->lpVtbl->SetProps(lpMailUserMAPI,
cProps, // cValues
lpProps, // property array
NULL))) { // problems array
DebugTrace("ExportEntry:SetProps(MAPI) -> %x\n", GetScode(hResult));
goto exit;
}
// Save the new wab mailuser or distlist
if (HR_FAILED(hResult = lpMailUserMAPI->lpVtbl->SaveChanges(lpMailUserMAPI,
KEEP_OPEN_READONLY | FORCE_SAVE))) {
DebugTrace("SaveChanges -> %x\n", GetScode(hResult));
} else {
fCreatedNew = TRUE;
}
}
//
// Handle Collisions
//
if (lpEIDDup || GetScode(hResult) == MAPI_E_COLLISION) {
// Find the display name
if (! lpDisplayName) {
DebugTrace("Collision, but can't find PR_DISPLAY_NAME in entry\n");
goto exit;
}
// Do we need to prompt?
switch (lpExportOptions->ReplaceOption) {
case WAB_REPLACE_PROMPT:
// Prompt user with dialog. If they say YES, we should
// recurse with the FORCE flag set.
RI.lpszDisplayName = lpDisplayName;
RI.lpszEmailAddress = lpEmailAddress;
RI.ConfirmResult = CONFIRM_ERROR;
RI.fExport = TRUE;
RI.lpImportOptions = lpExportOptions;
DialogBoxParam(hInst,
MAKEINTRESOURCE(IDD_ExportReplace),
hwnd,
ReplaceDialogProc,
(LPARAM)&RI);
switch (RI.ConfirmResult) {
case CONFIRM_YES:
case CONFIRM_YES_TO_ALL:
fForceReplace = TRUE;
break;
case CONFIRM_ABORT:
hResult = ResultFromScode(MAPI_E_USER_CANCEL);
goto exit;
default:
// NO
break;
}
break;
case WAB_REPLACE_ALWAYS:
fForceReplace = TRUE;
break;
}
if (fForceReplace) {
SBinary sbEntry;
ENTRYLIST EntryList = {1, &sbEntry};
// Find the existing PAB entry and delete it.
if (! lpDisplayName) {
lpDisplayName = (LPTSTR)szEmpty;
}
if (! lpEIDDup) {
if (HR_FAILED(hResult = FindPABEntry(lpContainerMAPI,
ulObjectType,
lpDisplayName,
lpEmailAddress,
&cbEIDDup,
&lpEIDDup))) {
// Hey, couldn't find it. Just pretend it isn't there,
// go on and create the new one anyway.
}
}
if (lpEIDDup) {
// Delete this entry.
sbEntry.cb = cbEIDDup;
sbEntry.lpb = (LPBYTE)lpEIDDup;
if (HR_FAILED(hResult = lpContainerMAPI->lpVtbl->DeleteEntries(lpContainerMAPI,
&EntryList,
0))) {
DebugTrace("PAB DeleteEntries(%s) -> %x\n", lpDisplayName);
}
if (lpEIDDup) {
MAPIFreeBuffer(lpEIDDup);
}
}
lpMailUserMAPI->lpVtbl->Release(lpMailUserMAPI);
lpMailUserMAPI = NULL;
// Create a new entry without the collision flags
if (HR_FAILED(hResult = lpContainerMAPI->lpVtbl->CreateEntry(lpContainerMAPI,
lpCreateEIDsMAPI[iCreateTemplate].Value.bin.cb,
(LPENTRYID)lpCreateEIDsMAPI[iCreateTemplate].Value.bin.lpb,
0,
&lpMailUserMAPI))) {
DebugTrace("CreateEntry(MAPI MailUser) -> %x\n", GetScode(hResult));
goto exit;
}
// Set the properties on the PAB entry
if (HR_FAILED(hResult = lpMailUserMAPI->lpVtbl->SetProps(lpMailUserMAPI,
cProps, // cValues
lpProps, // property array
NULL))) { // problems array
DebugTrace("ExportEntry:SetProps(MAPI) -> %x\n", GetScode(hResult));
goto exit;
}
// Save the new wab mailuser or distlist
if (HR_FAILED(hResult = lpMailUserMAPI->lpVtbl->SaveChanges(lpMailUserMAPI,
KEEP_OPEN_READONLY | FORCE_SAVE))) {
DebugTrace("SaveChanges(WAB MailUser) -> %x\n", GetScode(hResult));
} else {
fCreatedNew = TRUE;
}
} else {
fDuplicate = TRUE;
}
hResult = hrSuccess;
}
if (fCreatedNew) {
// What is the ENTRYID of our new entry?
if ((hResult = lpMailUserMAPI->lpVtbl->GetProps(lpMailUserMAPI,
(LPSPropTagArray)&ptaEid,
0,
&cEIDPropMAPI,
&lpEIDPropMAPI))) {
DebugTrace("ExportEntry: GetProps(MAPI ENTRYID) -> %x\n", GetScode(hResult));
goto exit;
}
Assert(cEIDPropMAPI);
Assert(lpEIDPropMAPI[ieidPR_ENTRYID].ulPropTag == PR_ENTRYID);
cbEIDNew = lpEIDPropMAPI[0].Value.bin.cb;
if (FAILED(sc = MAPIAllocateBuffer(cbEIDNew, &lpEIDNew))) {
DebugTrace("ExportEntry: MAPIAllocateBuffer(MAPI ENTRYID) -> %x\n", sc);
hResult = ResultFromScode(sc);
goto exit;
}
// Copy the new EntryID into the buffer
CopyMemory(lpEIDNew, lpEIDPropMAPI[0].Value.bin.lpb, cbEIDNew);
}
//
// If this is a DISTLIST, fill it in.
//
if (fDistList && ! fDuplicate && cbEIDNew) {
lpDistListWAB = (LPDISTLIST)lpMailUserWAB; // This is REALLY a DISTLIST object
// DO NOT Release this!
// Open the new WAB DL as a DISTLIST object
if (HR_FAILED(hResult = lpContainerMAPI->lpVtbl->OpenEntry(lpContainerMAPI,
cbEIDNew,
lpEIDNew,
(LPIID)&IID_IDistList,
MAPI_MODIFY,
&ulObjectTypeOpen,
(LPUNKNOWN*)&lpDistListMAPI))) {
DebugTrace("ExportEntry: MAPI OpenEntry(IID_DistList) -> %x\n", GetScode(hResult));
goto exit;
}
Assert(lpDistListMAPI);
// For each entry in the DL:
// Migrate the entry (MailUser or DL) recursively
// Add new entryid to DL contents
if (HR_FAILED(hResult = lpDistListWAB->lpVtbl->GetContentsTable(lpDistListWAB,
0, // ulFlags
&lpDLTableWAB))) {
DebugTrace("ExportEntry:GetContentsTable(WAB) -> %x\n", GetScode(hResult));
goto exit;
}
// Set the columns to those we're interested in
if (hResult = lpDLTableWAB->lpVtbl->SetColumns(lpDLTableWAB,
(LPSPropTagArray)&ptaColumns,
0)) {
DebugTrace("WAB SetColumns(DL Table) -> %x\n", GetScode(hResult));
goto exit;
}
cRows = 1;
while (cRows) {
// Get the next DL entry
if (hResult = lpDLTableWAB->lpVtbl->QueryRows(lpDLTableWAB,
1, // one row at a time
0, // ulFlags
&lpRow)) {
DebugTrace("DL: QueryRows -> %x\n", GetScode(hResult));
goto exit;
}
if (lpRow && lpRow->cRows) {
Assert(lpRow->cRows == 1);
Assert(lpRow->aRow[0].cValues == iptaColumnsMax);
Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].ulPropTag == PR_ENTRYID);
Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].ulPropTag == PR_OBJECT_TYPE);
if (lpRow) {
if (cRows = lpRow->cRows) { // yes, single '='
hResult = ExportEntry(hwnd,
lpAdrBookWAB,
lpContainerMAPI,
lpCreateEIDsMAPI,
lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].Value.l,
(LPENTRYID)lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.lpb,
lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.cb,
&lpeidDLMAPI, // returned new or existing entry
&cbeidDLMAPI,
TRUE,
FALSE);
if (hResult) {
if (HandleExportError(hwnd,
0,
hResult,
lpRow->aRow[0].lpProps[iptaColumnsPR_DISPLAY_NAME].Value.LPSZ,
PropStringOrNULL(&lpRow->aRow[0].lpProps[iptaColumnsPR_EMAIL_ADDRESS]),
lpExportOptions)) {
hResult = ResultFromScode(MAPI_E_USER_CANCEL);
break; // out of loop
} else {
hResult = hrSuccess;
}
}
} // else, drop out of loop, we're done.
WABFreeProws(lpRow);
lpRow = NULL;
if (HR_FAILED(hResult)) {
// This entry couldn't be created. Ignore it.
DebugTrace("Coudln't create DL entry -> %x\n", GetScode(hResult));
hResult = hrSuccess;
continue;
}
// Add the Entry to the DL using the new entry's EntryID
if (cbeidDLMAPI && lpeidDLMAPI) {
// BUGBUG: Don't bother with this one if this is a duplicate entry.
if (HR_FAILED(hResult = lpDistListMAPI->lpVtbl->CreateEntry(lpDistListMAPI,
cbeidDLMAPI,
lpeidDLMAPI,
0, // allow duplicates here
&lpEntryMAPI))) {
DebugTrace("Couldn't create new entry in DL -> %x\n", GetScode(hResult));
break;
}
hResult = lpEntryMAPI->lpVtbl->SaveChanges(lpEntryMAPI, FORCE_SAVE);
if (lpEntryMAPI) {
lpEntryMAPI->lpVtbl->Release(lpEntryMAPI);
lpEntryMAPI = NULL;
}
}
if (lpeidDLMAPI) {
MAPIFreeBuffer(lpeidDLMAPI);
lpeidDLMAPI = NULL;
}
}
} else {
break; // done
}
}
}
} else {
DebugTrace("Found a duplicate EntryID\n");
}
//
// Save the entryid to the list and return a buffer with it
//
if (cbEIDNew && lpEIDNew) { // We created one?
// created one
} else if (fDuplicateEID && lListIndex != -1) { // Was it in the list?
cbEIDNew = lpEntriesSeen[lListIndex].sbinWAB.cb;
if (FAILED(sc = MAPIAllocateBuffer(cbEIDNew, &lpEIDNew))) {
DebugTrace("ExportEntry: WABAllocateBuffer(WAB ENTRYID) -> %x\n", sc);
// ignore
cbEIDNew = 0;
} else {
// Copy the EntryID from the list into the buffer
CopyMemory(lpEIDNew, lpEntriesSeen[lListIndex].sbinWAB.lpb, cbEIDNew);
}
} else if (fDuplicate) { // Was it a duplicate
FindPABEntry(lpContainerMAPI,
ulObjectType,
lpDisplayName,
lpEmailAddress,
&cbEIDNew,
&lpEIDNew);
#ifdef OLD_STUFF
FindExistingPABEntry(lpProps, cProps, lpContainerMAPI, &lpEIDNew, &cbEIDNew);
#endif // OLD_STUFF
// ignore errors since the lpEIDNew and cbEIDNew will be nulled out
}
// Update the seen list
if (! fDuplicateEID) {
MarkPABEntryInList(cbEIDNew, lpEIDNew, lListIndex);
}
// If caller requested the entryid's, return them
if (lpcbEIDMAPI && lppEIDMAPI) {
*lpcbEIDMAPI = cbEIDNew;
*lppEIDMAPI = lpEIDNew;
fReturnEID = TRUE; // don't free it
}
exit:
//
// Cleanup MAPI stuff
//
if (lpProps) {
MAPIFreeBuffer(lpProps);
}
if (lpEIDPropMAPI) {
MAPIFreeBuffer(lpEIDPropMAPI);
}
if (lpEIDNew && ! fReturnEID) {
MAPIFreeBuffer(lpEIDNew);
}
if (lpeidDLMAPI) {
MAPIFreeBuffer(lpeidDLMAPI);
}
if (lpMailUserMAPI) {
lpMailUserMAPI->lpVtbl->Release(lpMailUserMAPI);
}
if (lpDistListMAPI) {
lpDistListMAPI->lpVtbl->Release(lpDistListMAPI);
}
//
// Cleanup WAB stuff
//
if (lpRow) {
WABFreeProws(lpRow);
}
if (lpDLTableWAB) {
lpDLTableWAB->lpVtbl->Release(lpDLTableWAB);
}
if (lpMailUserWAB) {
lpMailUserWAB->lpVtbl->Release(lpMailUserWAB);
}
// Do not release this... It is the same object as lpMailUserWAB!
// if (lpDistListWAB) {
// lpDistListWAB->lpVtbl->Release(lpDistListWAB);
// }
if (! HR_FAILED(hResult)) {
hResult = hrSuccess;
}
return(hResult);
}
HRESULT PABExport(HWND hWnd,
LPADRBOOK lpAdrBook,
LPWABOBJECT lpWABObject,
LPWAB_PROGRESS_CALLBACK lpProgressCB,
LPWAB_EXPORT_OPTIONS lpOptions) {
BOOL fDone = FALSE;
HRESULT hResult = hrSuccess;
lpAdrBookWAB = lpAdrBook;
lpfnProgressCB = lpProgressCB;
lpExportOptions = lpOptions;
// Setup memory allocators
SetGlobalBufferFunctions(lpWABObject);
// Prime the state machine
State = STATE_EXPORT_MU;
while (! fDone) {
switch (State) {
case STATE_EXPORT_MU:
StateExportMU(hWnd);
break;
case STATE_EXPORT_NEXT_MU:
StateExportNextMU(hWnd);
break;
case STATE_EXPORT_DL:
StateExportDL(hWnd);
break;
case STATE_EXPORT_NEXT_DL:
StateExportNextDL(hWnd);
break;
case STATE_EXPORT_FINISH:
StateExportFinish(hWnd);
fDone = TRUE;
break;
case STATE_EXPORT_ERROR:
StateExportError(hWnd);
// BUGBUG: Should set hResult to something
break;
case STATE_EXPORT_CANCEL:
StateExportCancel(hWnd);
break;
default:
DebugTrace("Unknown state %u in PABExport\n", State);
Assert(FALSE);
break;
}
}
return(hResult);
}
HRESULT PABImport(HWND hWnd,
LPADRBOOK lpAdrBook,
LPWABOBJECT lpWABObject,
LPWAB_PROGRESS_CALLBACK lpProgressCB,
LPWAB_IMPORT_OPTIONS lpOptions) {
BOOL fDone = FALSE;
HRESULT hResult = hrSuccess;
lpAdrBookWAB = lpAdrBook;
lpfnProgressCB = lpProgressCB;
lpImportOptions = lpOptions;
// Setup memory allocators
SetGlobalBufferFunctions(lpWABObject);
// Prime the state machine
State = STATE_IMPORT_MU;
while (! fDone) {
switch (State) {
case STATE_IMPORT_MU:
StateImportMU(hWnd);
break;
case STATE_IMPORT_NEXT_MU:
StateImportNextMU(hWnd);
break;
case STATE_IMPORT_DL:
StateImportDL(hWnd);
break;
case STATE_IMPORT_NEXT_DL:
StateImportNextDL(hWnd);
break;
case STATE_IMPORT_FINISH:
StateImportFinish(hWnd);
fDone = TRUE;
break;
case STATE_IMPORT_ERROR:
StateImportError(hWnd);
// BUGBUG: Should set hResult to something
break;
case STATE_IMPORT_CANCEL:
StateImportCancel(hWnd);
break;
default:
DebugTrace("Unknown state %u in PABImport\n", State);
Assert(FALSE);
break;
}
}
return(hResult);
}
/*
- HrLoadPrivateWABProps
-
* Private function to load Conferencing Named properties
* as globals up front
*
*
*/
HRESULT HrLoadPrivateWABPropsForCSV(LPADRBOOK lpIAB)
{
HRESULT hr = E_FAIL;
LPSPropTagArray lpta = NULL;
SCODE sc = 0;
ULONG i, uMax = prWABConfMax, nStartIndex = OLK_NAMEDPROPS_START;
LPMAPINAMEID *lppConfPropNames = NULL;
sc = WABAllocateBuffer(sizeof(LPMAPINAMEID) * uMax, (LPVOID *) &lppConfPropNames);
//sc = WABAllocateBuffer(sizeof(LPMAPINAMEID) * uMax, (LPVOID *) &lppConfPropNames);
if( (HR_FAILED(hr = ResultFromScode(sc))) )
goto err;
for(i=0;i< uMax;i++)
{
//sc = WABAllocateMore(sizeof(MAPINAMEID), lppConfPropNames, &(lppConfPropNames[i]));
sc = WABAllocateMore( sizeof(MAPINAMEID), lppConfPropNames, &(lppConfPropNames[i]));
if(sc)
{
hr = ResultFromScode(sc);
goto err;
}
lppConfPropNames[i]->lpguid = (LPGUID) &PS_Conferencing;
lppConfPropNames[i]->ulKind = MNID_ID;
lppConfPropNames[i]->Kind.lID = nStartIndex + i;
}
// Load the set of conferencing named props
//
if( HR_FAILED(hr = (lpIAB)->lpVtbl->GetIDsFromNames(lpIAB, uMax, lppConfPropNames,
MAPI_CREATE, &lpta) ))
goto err;
if(lpta)
{
// Set the property types on the returned props
PR_SERVERS = CHANGE_PROP_TYPE(lpta->aulPropTag[prWABConfServers], PT_MV_TSTRING);
}
rgPropNames[NUM_MORE_EXPORT_PROPS-1].ulPropTag = PR_SERVERS;
rgPropNames[NUM_MORE_EXPORT_PROPS-1].fChosen = FALSE;
rgPropNames[NUM_MORE_EXPORT_PROPS-1].ids = ids_ExportConfServer;
rgPropNames[NUM_MORE_EXPORT_PROPS-1].lpszName = NULL;
rgPropNames[NUM_MORE_EXPORT_PROPS-1].lpszCSVName = NULL;
err:
if(lpta)
WABFreeBuffer( lpta );
if( lppConfPropNames )
WABFreeBuffer( lppConfPropNames );
//WABFreeBuffer(lpta);
return hr;
}