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