853 lines
25 KiB
C
853 lines
25 KiB
C
/*
|
|
* WMCSERVE.C - Main entry to WMCSERVE import/exporter
|
|
*
|
|
*/
|
|
|
|
|
|
#include <windows.h>
|
|
#include <wab.h>
|
|
#include <wabmig.h>
|
|
#include <wabdbg.h>
|
|
#include "dbgutil.h"
|
|
#include "resource.h"
|
|
|
|
#define MAX_UI_STR 256
|
|
#define MAX_BUF_STR 4 * MAX_UI_STR
|
|
|
|
// Per-process Globals
|
|
HINSTANCE hinst;
|
|
const LPTSTR szCompuserveFilter = "*.dat";
|
|
const LPTSTR szAtCompuserve = "@compuserve.com";
|
|
#define SIZEOF_AT_COMPUSERVE 15
|
|
|
|
const LPTSTR szSMTP = "SMTP";
|
|
|
|
|
|
// Global WAB Allocator access functions
|
|
//
|
|
typedef struct _WAB_ALLOCATORS {
|
|
LPWABOBJECT lpWABObject;
|
|
LPWABALLOCATEBUFFER lpAllocateBuffer;
|
|
LPWABALLOCATEMORE lpAllocateMore;
|
|
LPWABFREEBUFFER lpFreeBuffer;
|
|
} WAB_ALLOCATORS, *LPWAB_ALLOCATORS;
|
|
|
|
WAB_ALLOCATORS WABAllocators = {0};
|
|
|
|
enum {
|
|
iconPR_DEF_CREATE_MAILUSER = 0,
|
|
iconPR_DEF_CREATE_DL,
|
|
iconMax
|
|
};
|
|
static const SizedSPropTagArray(iconMax, ptaCon)=
|
|
{
|
|
iconMax,
|
|
{
|
|
PR_DEF_CREATE_MAILUSER,
|
|
PR_DEF_CREATE_DL,
|
|
}
|
|
};
|
|
|
|
typedef enum {
|
|
CONFIRM_YES,
|
|
CONFIRM_NO,
|
|
CONFIRM_YES_TO_ALL,
|
|
CONFIRM_NO_TO_ALL,
|
|
CONFIRM_ERROR
|
|
} CONFIRM_RESULT, *LPCONFIRM_RESULT;
|
|
|
|
typedef struct _ReplaceInfo {
|
|
LPTSTR lpszDisplayName; // Conflicting display name
|
|
CONFIRM_RESULT ConfirmResult; // Results from dialog
|
|
LPWAB_IMPORT_OPTIONS lpImportOptions;
|
|
} REPLACE_INFO, * LPREPLACE_INFO;
|
|
|
|
/***************************************************************************
|
|
|
|
Name : SetGlobalBufferFunctions
|
|
|
|
Purpose : Set the global buffer functions based on methods from
|
|
the WAB object.
|
|
|
|
Parameters: lpWABObject = the open wab object
|
|
|
|
Returns : none
|
|
|
|
Comment :
|
|
|
|
***************************************************************************/
|
|
void SetGlobalBufferFunctions(LPWABOBJECT lpWABObject) {
|
|
if (lpWABObject && ! WABAllocators.lpWABObject) {
|
|
WABAllocators.lpAllocateBuffer = lpWABObject->lpVtbl->AllocateBuffer;
|
|
WABAllocators.lpAllocateMore = lpWABObject->lpVtbl->AllocateMore;
|
|
WABAllocators.lpFreeBuffer = lpWABObject->lpVtbl->FreeBuffer;
|
|
WABAllocators.lpWABObject = lpWABObject;
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
Name : WABAllocateBuffer
|
|
|
|
Purpose : Use the WAB Allocator
|
|
|
|
Parameters: cbSize = size to allocate
|
|
lppBuffer = returned buffer
|
|
|
|
Returns : SCODE
|
|
|
|
Comment :
|
|
|
|
***************************************************************************/
|
|
SCODE WABAllocateBuffer(ULONG cbSize, LPVOID FAR * lppBuffer) {
|
|
if (WABAllocators.lpWABObject && WABAllocators.lpAllocateBuffer) {
|
|
return(WABAllocators.lpAllocateBuffer(WABAllocators.lpWABObject, cbSize, lppBuffer));
|
|
} else {
|
|
return(MAPI_E_INVALID_OBJECT);
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
Name : WABAllocateMore
|
|
|
|
Purpose : Use the WAB Allocator
|
|
|
|
Parameters: cbSize = size to allocate
|
|
lpObject = existing allocation
|
|
lppBuffer = returned buffer
|
|
|
|
Returns : SCODE
|
|
|
|
Comment :
|
|
|
|
***************************************************************************/
|
|
SCODE WABAllocateMore(ULONG cbSize, LPVOID lpObject, LPVOID FAR * lppBuffer) {
|
|
if (WABAllocators.lpWABObject && WABAllocators.lpAllocateMore) {
|
|
return(WABAllocators.lpAllocateMore(WABAllocators.lpWABObject, cbSize, lpObject, lppBuffer));
|
|
} else {
|
|
return(MAPI_E_INVALID_OBJECT);
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
Name : WABFreeBuffer
|
|
|
|
Purpose : Use the WAB Allocator
|
|
|
|
Parameters: lpBuffer = buffer to free
|
|
|
|
Returns : SCODE
|
|
|
|
Comment :
|
|
|
|
***************************************************************************/
|
|
SCODE WABFreeBuffer(LPVOID lpBuffer) {
|
|
if (WABAllocators.lpWABObject && WABAllocators.lpFreeBuffer) {
|
|
return(WABAllocators.lpFreeBuffer(WABAllocators.lpWABObject, lpBuffer));
|
|
} else {
|
|
return(MAPI_E_INVALID_OBJECT);
|
|
}
|
|
}
|
|
|
|
|
|
//$$//////////////////////////////////////////////////////////////////////
|
|
//
|
|
// LoadAllocString - Loads a string resource and allocates enough
|
|
// memory to hold it.
|
|
//
|
|
// StringID - String identifier to load
|
|
//
|
|
// returns the LocalAlloc'd, null terminated string. Caller is responsible
|
|
// for LocalFree'ing this buffer. If the string can't be loaded or memory
|
|
// can't be allocated, returns NULL.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
LPTSTR LoadAllocString(int StringID) {
|
|
ULONG ulSize = 0;
|
|
LPTSTR lpBuffer = NULL;
|
|
TCHAR szBuffer[261]; // Big enough? Strings better be smaller than 260!
|
|
|
|
ulSize = LoadString(hinst, StringID, szBuffer, sizeof(szBuffer));
|
|
|
|
if (ulSize && (lpBuffer = LocalAlloc(LPTR, ulSize + 1))) {
|
|
lstrcpy(lpBuffer, szBuffer);
|
|
}
|
|
|
|
return(lpBuffer);
|
|
}
|
|
|
|
|
|
//$$//////////////////////////////////////////////////////////////////////
|
|
//
|
|
// FormatAllocFilter - Loads a file filter name string resource and
|
|
// formats it with the file extension filter
|
|
//
|
|
// StringID - String identifier to load
|
|
// szFilter - file name filter, ie, "*.vcf"
|
|
//
|
|
// returns the LocalAlloc'd, null terminated string. Caller is responsible
|
|
// for LocalFree'ing this buffer. If the string can't be loaded or memory
|
|
// can't be allocated, returns NULL.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
LPTSTR FormatAllocFilter(int StringID, const LPTSTR lpFilter) {
|
|
LPTSTR lpFileType;
|
|
LPTSTR lpTemp;
|
|
LPTSTR lpBuffer = NULL;
|
|
ULONG cbFileType, cbFilter;
|
|
|
|
cbFilter = lstrlen(lpFilter);
|
|
if (lpFileType = LoadAllocString(StringID)) {
|
|
if (lpBuffer = LocalAlloc(LPTR, (cbFileType = lstrlen(lpFileType)) + 1 + lstrlen(lpFilter) + 2)) {
|
|
lpTemp = lpBuffer;
|
|
lstrcpy(lpTemp, lpFileType);
|
|
lpTemp += cbFileType;
|
|
lpTemp++; // leave null there
|
|
lstrcpy(lpTemp, lpFilter);
|
|
lpTemp += cbFilter;
|
|
lpTemp++; // leave null there
|
|
*lpTemp = '\0';
|
|
}
|
|
|
|
LocalFree(lpFileType);
|
|
}
|
|
|
|
return(lpBuffer);
|
|
}
|
|
|
|
|
|
//$$/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ShowMessageBoxParam - Generic MessageBox displayer .. saves space all over
|
|
//
|
|
// hWndParent - Handle of Message Box Parent
|
|
// MsgID - resource id of message string
|
|
// ulFlags - MessageBox flags
|
|
// ... - format parameters
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
int __cdecl ShowMessageBoxParam(HWND hWndParent, int MsgId, int ulFlags, ...)
|
|
{
|
|
TCHAR szBuf[MAX_BUF_STR] = "";
|
|
TCHAR szCaption[MAX_PATH] = "";
|
|
LPTSTR lpszBuffer = NULL;
|
|
int iRet = 0;
|
|
va_list vl;
|
|
|
|
va_start(vl, ulFlags);
|
|
|
|
LoadString(hinst, MsgId, szBuf, sizeof(szBuf));
|
|
if (FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
|
szBuf,
|
|
0,0, //ignored
|
|
(LPTSTR)&lpszBuffer,
|
|
MAX_BUF_STR, //MAX_UI_STR
|
|
&vl)) {
|
|
TCHAR szCaption[MAX_PATH];
|
|
GetWindowText(hWndParent, szCaption, sizeof(szCaption));
|
|
if(!lstrlen(szCaption)) // if no caption get the parents caption - this is necessary for property sheets
|
|
{
|
|
GetWindowText(GetParent(hWndParent), szCaption, sizeof(szCaption));
|
|
if(!lstrlen(szCaption)) //if still not caption, get the generic title
|
|
LoadString(hinst, IDS_CSERVE_IMPORT_TITLE, szCaption, sizeof(szCaption));
|
|
}
|
|
iRet = MessageBox(hWndParent, lpszBuffer, szCaption, ulFlags);
|
|
if(lpszBuffer) {
|
|
LocalFree(lpszBuffer);
|
|
}
|
|
}
|
|
va_end(vl);
|
|
return(iRet);
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK ReplaceDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
|
LPREPLACE_INFO lpRI = (LPREPLACE_INFO)GetWindowLongPtr(hwnd, DWLP_USER);
|
|
|
|
switch (message) {
|
|
case WM_INITDIALOG:
|
|
{
|
|
TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
|
|
LPTSTR lpszMessage;
|
|
|
|
SetWindowLongPtr(hwnd, DWLP_USER, lParam); //Save this for future reference
|
|
lpRI = (LPREPLACE_INFO)lParam;
|
|
|
|
if (LoadString(hinst, IDS_REPLACE_MESSAGE, szBuffer, sizeof(szBuffer))) {
|
|
|
|
if (lpszMessage = LocalAlloc(LMEM_FIXED, lstrlen(szBuffer) + 1 + lstrlen(lpRI->lpszDisplayName))) {
|
|
|
|
wsprintf(lpszMessage, szBuffer, lpRI->lpszDisplayName);
|
|
|
|
DebugTrace("Status Message: %s\n", lpszMessage);
|
|
if (! SetDlgItemText(hwnd, IDC_Replace_Message, lpszMessage)) {
|
|
DebugTrace("SetDlgItemText -> %u\n", GetLastError());
|
|
}
|
|
LocalFree(lpszMessage);
|
|
}
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
case WM_COMMAND :
|
|
switch (wParam) {
|
|
case IDCLOSE:
|
|
case IDNO:
|
|
case IDCANCEL:
|
|
lpRI->ConfirmResult = CONFIRM_NO;
|
|
SendMessage(hwnd, WM_CLOSE, 0, 0L);
|
|
return(0);
|
|
|
|
case IDOK:
|
|
case IDYES:
|
|
// Set the state of the parameter
|
|
lpRI->ConfirmResult = CONFIRM_YES;
|
|
SendMessage(hwnd, WM_CLOSE, 0, 0);
|
|
return(0);
|
|
|
|
|
|
case IDC_NoToAll:
|
|
lpRI->ConfirmResult = CONFIRM_NO_TO_ALL;
|
|
lpRI->lpImportOptions->ReplaceOption = WAB_REPLACE_NEVER;
|
|
SendMessage(hwnd, WM_CLOSE, 0, 0);
|
|
return(0);
|
|
|
|
case IDC_YesToAll:
|
|
lpRI->ConfirmResult = CONFIRM_YES_TO_ALL;
|
|
lpRI->lpImportOptions->ReplaceOption = WAB_REPLACE_ALWAYS;
|
|
SendMessage(hwnd, WM_CLOSE, 0, 0);
|
|
return(0);
|
|
|
|
case IDM_EXIT:
|
|
SendMessage(hwnd, WM_DESTROY, 0, 0L);
|
|
return(0);
|
|
|
|
#ifdef OLD_STUFF
|
|
case IDHELP:
|
|
MessageBox(hwnd, "Help not yet implemented!",
|
|
szAppName, MB_ICONEXCLAMATION | MB_OK);
|
|
return(0);
|
|
#endif // OLD_STUFF
|
|
}
|
|
break ;
|
|
|
|
case IDCANCEL:
|
|
SendMessage(hwnd, WM_CLOSE, 0, 0);
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
EndDialog(hwnd, FALSE);
|
|
return(0);
|
|
|
|
default:
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
Name : MigrateContact
|
|
|
|
Purpose : Migrates the user entry from CSERVE address book to the WAB
|
|
|
|
Parameters: hwnd = main dialog window
|
|
lpContainerWAB -> WAB PAB container
|
|
lpCreateEIDsWAB -> SPropValue of default object creation EIDs
|
|
lpName = display name
|
|
lpAddress = email address
|
|
lpOptions -> import options
|
|
|
|
Returns : HRESULT
|
|
|
|
Comment :
|
|
|
|
***************************************************************************/
|
|
HRESULT MigrateContact(HWND hwnd,
|
|
LPABCONT lpContainerWAB,
|
|
LPSPropValue lpCreateEIDsWAB,
|
|
LPTSTR lpName,
|
|
LPTSTR lpAddress,
|
|
LPWAB_IMPORT_OPTIONS lpOptions) {
|
|
|
|
HRESULT hResult = hrSuccess;
|
|
BOOL fDistList = FALSE;
|
|
BOOL fDuplicate = FALSE;
|
|
LPMAPIPROP lpMailUserWAB = NULL;
|
|
SPropValue rgProps[3];
|
|
LPSRowSet lpRow = NULL;
|
|
LPMAPIPROP lpEntryWAB = NULL;
|
|
ULONG ulCreateFlags = CREATE_CHECK_DUP_STRICT;
|
|
REPLACE_INFO RI;
|
|
static TCHAR szBufferDLMessage[MAX_RESOURCE_STRING + 1] = "";
|
|
LONG lListIndex = -1;
|
|
ULONG iCreateTemplate = iconPR_DEF_CREATE_MAILUSER;
|
|
LPTSTR lpTempAddress;
|
|
LPTSTR lpAddressOrg = lpAddress;
|
|
|
|
|
|
|
|
if (lpOptions->ReplaceOption == WAB_REPLACE_ALWAYS) {
|
|
ulCreateFlags |= CREATE_REPLACE;
|
|
}
|
|
|
|
// Set up some object type specific variables
|
|
iCreateTemplate = iconPR_DEF_CREATE_MAILUSER;
|
|
fDistList = FALSE;
|
|
|
|
|
|
retry:
|
|
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;
|
|
}
|
|
|
|
// Munge the address to SMTP format
|
|
// nuke the "INTERNET:"
|
|
lpTempAddress = lpAddress;
|
|
while (*lpTempAddress) {
|
|
if (*lpTempAddress == ':') {
|
|
lpAddress = lpTempAddress + 1;
|
|
break;
|
|
}
|
|
lpTempAddress++;
|
|
}
|
|
if (lpAddress == lpAddressOrg) {
|
|
// Must be a compuserve address, fix it
|
|
lpTempAddress = lpAddress;
|
|
while (*lpTempAddress) {
|
|
if (*lpTempAddress == ',') { // compuserve uses comma internally
|
|
*lpTempAddress = '.'; // map to a period
|
|
}
|
|
lpTempAddress++;
|
|
}
|
|
|
|
lstrcat(lpAddress, szAtCompuserve);
|
|
}
|
|
|
|
|
|
rgProps[0].ulPropTag = PR_DISPLAY_NAME;
|
|
rgProps[0].Value.LPSZ = lpName;
|
|
|
|
rgProps[1].ulPropTag = PR_EMAIL_ADDRESS;
|
|
rgProps[1].Value.LPSZ = lpAddress;
|
|
|
|
rgProps[2].ulPropTag = PR_ADDRTYPE;
|
|
rgProps[2].Value.LPSZ = szSMTP;
|
|
|
|
|
|
// Set the properties on the WAB entry
|
|
if (HR_FAILED(hResult = lpMailUserWAB->lpVtbl->SetProps(lpMailUserWAB,
|
|
3, // cValues
|
|
rgProps, // property array
|
|
NULL))) { // problems array
|
|
DebugTrace("MigrateEntry: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
|
|
|
|
|
|
// Do we need to prompt?
|
|
if (lpOptions->ReplaceOption == WAB_REPLACE_PROMPT) {
|
|
// Prompt user with dialog. If they say YES, we should
|
|
// recurse with the FORCE flag set.
|
|
|
|
RI.lpszDisplayName = lpName;
|
|
RI.ConfirmResult = CONFIRM_ERROR;
|
|
RI.lpImportOptions = lpOptions;
|
|
|
|
DialogBoxParam(hinst,
|
|
MAKEINTRESOURCE(IDD_Replace),
|
|
hwnd,
|
|
ReplaceDialogProc,
|
|
(LPARAM)&RI);
|
|
|
|
switch (RI.ConfirmResult) {
|
|
case CONFIRM_YES:
|
|
case CONFIRM_YES_TO_ALL:
|
|
// YES
|
|
// Do it again!
|
|
|
|
lpMailUserWAB->lpVtbl->Release(lpMailUserWAB);
|
|
ulCreateFlags |= CREATE_REPLACE;
|
|
goto retry;
|
|
break;
|
|
|
|
default:
|
|
// NO
|
|
break;
|
|
}
|
|
}
|
|
hResult = hrSuccess;
|
|
|
|
} else {
|
|
DebugTrace("SaveChanges(WAB MailUser) -> %x\n", GetScode(hResult));
|
|
}
|
|
}
|
|
exit:
|
|
if (lpMailUserWAB) {
|
|
lpMailUserWAB->lpVtbl->Release(lpMailUserWAB);
|
|
}
|
|
|
|
if (! HR_FAILED(hResult)) {
|
|
hResult = hrSuccess;
|
|
}
|
|
|
|
return(hResult);
|
|
}
|
|
|
|
|
|
/*
|
|
- CServeImport
|
|
-
|
|
* Purpose:
|
|
* Import a compuserve address book to the WAB
|
|
*
|
|
* Arguments:
|
|
* hwnd window handle
|
|
* lpAdrBook Returned IAdrBook object
|
|
* lpWABOBJECT Returned WABObject
|
|
* lpProgressCB Progress callback
|
|
* lpOptions Import options structure
|
|
*
|
|
* Returns:
|
|
* HRESULT
|
|
*
|
|
*/
|
|
STDMETHODIMP CServeImport(HWND hwnd, LPADRBOOK lpAdrBook, LPWABOBJECT lpWABObject,
|
|
LPWAB_PROGRESS_CALLBACK lpProgressCB, LPWAB_IMPORT_OPTIONS lpOptions) {
|
|
SCODE sc = SUCCESS_SUCCESS;
|
|
HRESULT hResult = hrSuccess;
|
|
HANDLE hFile = NULL;
|
|
OPENFILENAME ofn;
|
|
LPTSTR lpFilter = FormatAllocFilter(IDS_CSERVE_FILE_SPEC, szCompuserveFilter);
|
|
TCHAR szFileName[MAX_PATH + 1] = "addrbook.dat";
|
|
BOOL fDone = FALSE;
|
|
WORD wEntries = 0;
|
|
DWORD i, j;
|
|
ULONG ulBytesRead;
|
|
BOOL fDL;
|
|
TCHAR szPad[2];
|
|
ULONG cbWABEID;
|
|
LPENTRYID lpWABEID = NULL;
|
|
LPABCONT lpContainerWAB = NULL;
|
|
LPSPropValue lpCreateEIDsWAB = NULL;
|
|
ULONG ulObjType;
|
|
ULONG cProps;
|
|
WAB_PROGRESS Progress;
|
|
|
|
|
|
SetGlobalBufferFunctions(lpWABObject);
|
|
|
|
|
|
ofn.lStructSize = sizeof(ofn);
|
|
ofn.hwndOwner = hwnd;
|
|
ofn.hInstance = hinst;
|
|
ofn.lpstrFilter = lpFilter;
|
|
ofn.lpstrCustomFilter = NULL;
|
|
ofn.nMaxCustFilter = 0;
|
|
ofn.nFilterIndex = 0;
|
|
ofn.lpstrFile = szFileName;
|
|
ofn.nMaxFile = sizeof(szFileName);
|
|
ofn.lpstrFileTitle = NULL;
|
|
ofn.nMaxFileTitle = 0;
|
|
ofn.lpstrInitialDir = NULL;
|
|
ofn.lpstrTitle = LoadAllocString(IDS_CSERVE_IMPORT_TITLE);
|
|
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
|
|
ofn.nFileOffset = 0;
|
|
ofn.nFileExtension = 0;
|
|
ofn.lpstrDefExt = NULL;
|
|
ofn.lCustData = 0;
|
|
ofn.lpfnHook = NULL;
|
|
ofn.lpTemplateName = NULL;
|
|
|
|
// Find and Open the file
|
|
if (GetOpenFileName(&ofn)) {
|
|
if (INVALID_HANDLE_VALUE == (hFile = CreateFile(szFileName,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_FLAG_SEQUENTIAL_SCAN,
|
|
NULL))) {
|
|
// couldn't open file.
|
|
ShowMessageBoxParam(hwnd, IDE_CSERVE_IMPORT_FILE_ERROR, MB_ICONEXCLAMATION, szFileName);
|
|
hResult = ResultFromScode(MAPI_E_NOT_FOUND);
|
|
goto exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Open the WAB's PAB container
|
|
//
|
|
if (hResult = lpAdrBook->lpVtbl->GetPAB(lpAdrBook,
|
|
&cbWABEID,
|
|
&lpWABEID)) {
|
|
DebugTrace("WAB GetPAB -> %x\n", GetScode(hResult));
|
|
goto exit;
|
|
} else {
|
|
if (hResult = lpAdrBook->lpVtbl->OpenEntry(lpAdrBook,
|
|
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 WAB's creation entryids
|
|
if ((hResult = lpContainerWAB->lpVtbl->GetProps(lpContainerWAB,
|
|
(LPSPropTagArray)&ptaCon,
|
|
0,
|
|
&cProps,
|
|
&lpCreateEIDsWAB))) {
|
|
DebugTrace("Can't get container properties for WAB\n");
|
|
// Bad stuff here!
|
|
goto exit;
|
|
}
|
|
|
|
// Validate the properites
|
|
if (lpCreateEIDsWAB[iconPR_DEF_CREATE_MAILUSER].ulPropTag != PR_DEF_CREATE_MAILUSER ||
|
|
lpCreateEIDsWAB[iconPR_DEF_CREATE_DL].ulPropTag != PR_DEF_CREATE_DL) {
|
|
DebugTrace("WAB: Container property errors\n");
|
|
goto exit;
|
|
}
|
|
|
|
|
|
if (! ReadFile(hFile,
|
|
szPad,
|
|
sizeof(BYTE),
|
|
&ulBytesRead,
|
|
NULL)) {
|
|
hResult = ResultFromScode(MAPI_E_CORRUPT_DATA);
|
|
goto exit;
|
|
} // toss this byte, don't know what it does
|
|
|
|
// How many entries?
|
|
if (! ReadFile(hFile,
|
|
&wEntries,
|
|
sizeof(wEntries),
|
|
&ulBytesRead,
|
|
NULL)) {
|
|
hResult = ResultFromScode(MAPI_E_CORRUPT_DATA);
|
|
goto exit;
|
|
}
|
|
|
|
Progress.denominator = (ULONG)wEntries;
|
|
Progress.numerator = 0;
|
|
Progress.lpText = NULL;
|
|
|
|
for (i = 0; i < (DWORD)wEntries; i++) {
|
|
WORD wEntry;
|
|
BYTE bNameSize, bAddressSize;
|
|
TCHAR szName[256]; // max is 2^8
|
|
TCHAR szAddress[256 + SIZEOF_AT_COMPUSERVE]; // max is 2^8
|
|
|
|
// Update progress bar
|
|
Progress.numerator = i;
|
|
lpProgressCB(hwnd, &Progress);
|
|
|
|
// Read the entry number (should be == i + 1)
|
|
if (! ReadFile(hFile,
|
|
&wEntry,
|
|
sizeof(wEntry),
|
|
&ulBytesRead,
|
|
NULL)) {
|
|
hResult = ResultFromScode(MAPI_E_CORRUPT_DATA);
|
|
goto exit;
|
|
}
|
|
|
|
if ((DWORD)(wEntry & 0x7F) != i + 1) {
|
|
hResult = ResultFromScode(MAPI_E_CORRUPT_DATA);
|
|
goto exit;
|
|
}
|
|
|
|
// Is this a DL?
|
|
fDL = (wEntry & 0x80);
|
|
|
|
// Read size of Name
|
|
if (! ReadFile(hFile,
|
|
&bNameSize,
|
|
sizeof(bNameSize),
|
|
&ulBytesRead,
|
|
NULL)) {
|
|
hResult = ResultFromScode(MAPI_E_CORRUPT_DATA);
|
|
goto exit;
|
|
}
|
|
|
|
// Read name
|
|
if (! ReadFile(hFile,
|
|
&szName,
|
|
(DWORD)bNameSize,
|
|
&ulBytesRead,
|
|
NULL)) {
|
|
hResult = ResultFromScode(MAPI_E_CORRUPT_DATA);
|
|
goto exit;
|
|
}
|
|
szName[bNameSize] = '\0'; // null terminate it.
|
|
DebugTrace("%s:", szName);
|
|
|
|
if (fDL) {
|
|
BYTE bDLEntries;
|
|
WORD wDLEntry;
|
|
|
|
// Read the number of entries in this DL
|
|
if (! ReadFile(hFile,
|
|
&bDLEntries,
|
|
sizeof(bDLEntries),
|
|
&ulBytesRead,
|
|
NULL)) {
|
|
hResult = ResultFromScode(MAPI_E_CORRUPT_DATA);
|
|
goto exit;
|
|
}
|
|
|
|
// Read in each DL entry identifier
|
|
for (j = 0; j < (DWORD)bDLEntries; j++) {
|
|
if (! ReadFile(hFile,
|
|
&wDLEntry,
|
|
sizeof(wDLEntry),
|
|
&ulBytesRead,
|
|
NULL)) {
|
|
hResult = ResultFromScode(MAPI_E_CORRUPT_DATA);
|
|
goto exit;
|
|
}
|
|
|
|
DebugTrace(" %u", (DWORD)wDLEntry);
|
|
// BUGBUG: Need to implement DL entries
|
|
}
|
|
DebugTrace("\n");
|
|
} else {
|
|
// Read size of address
|
|
if (! ReadFile(hFile,
|
|
&bAddressSize,
|
|
sizeof(bAddressSize),
|
|
&ulBytesRead,
|
|
NULL)) {
|
|
hResult = ResultFromScode(MAPI_E_CORRUPT_DATA);
|
|
goto exit;
|
|
}
|
|
|
|
// Read address
|
|
if (! ReadFile(hFile,
|
|
&szAddress,
|
|
(DWORD)bAddressSize,
|
|
&ulBytesRead,
|
|
NULL)) {
|
|
hResult = ResultFromScode(MAPI_E_CORRUPT_DATA);
|
|
goto exit;
|
|
}
|
|
szAddress[bAddressSize] = '\0'; // null terminate it.
|
|
DebugTrace("%s\n", szAddress);
|
|
|
|
|
|
if (hResult = MigrateContact(hwnd,
|
|
lpContainerWAB,
|
|
lpCreateEIDsWAB,
|
|
szName,
|
|
szAddress,
|
|
lpOptions)) {
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
// Read in terminator byte
|
|
if (! ReadFile(hFile,
|
|
szPad,
|
|
sizeof(BYTE),
|
|
&ulBytesRead,
|
|
NULL)) {
|
|
hResult = ResultFromScode(MAPI_E_CORRUPT_DATA);
|
|
goto exit;
|
|
} // toss this byte, don't know what it does
|
|
}
|
|
} else {
|
|
hResult = ResultFromScode(MAPI_E_USER_CANCEL);
|
|
}
|
|
|
|
|
|
exit:
|
|
// Free up memory and objects
|
|
if (lpWABEID) {
|
|
WABFreeBuffer(lpWABEID);
|
|
}
|
|
|
|
if (lpCreateEIDsWAB) {
|
|
WABFreeBuffer(lpCreateEIDsWAB);
|
|
}
|
|
|
|
if (lpContainerWAB) {
|
|
lpContainerWAB->lpVtbl->Release(lpContainerWAB);
|
|
}
|
|
|
|
|
|
if (hFile) {
|
|
CloseHandle(hFile);
|
|
}
|
|
|
|
return(hResult);
|
|
}
|
|
|
|
|
|
/*
|
|
- CServeExport
|
|
-
|
|
* Purpose:
|
|
* Export to a compuserve address book from the WAB
|
|
*
|
|
* Arguments:
|
|
* hwnd window handle
|
|
* lpAdrBook Returned IAdrBook object
|
|
* lpWABOBJECT Returned WABObject
|
|
* lpProgressCB Progress callback
|
|
* lpOptions Export options structure
|
|
*
|
|
* Returns:
|
|
* HRESULT
|
|
*
|
|
*/
|
|
STDMETHODIMP CServeExport(HWND hwnd, LPADRBOOK lpAdrBook, LPWABOBJECT lpWABObject,
|
|
LPWAB_PROGRESS_CALLBACK lpProgressCB, LPWAB_IMPORT_OPTIONS lpOptions) {
|
|
SCODE sc = SUCCESS_SUCCESS;
|
|
HRESULT hResult = hrSuccess;
|
|
|
|
SetGlobalBufferFunctions(lpWABObject);
|
|
|
|
return(hResult);
|
|
}
|
|
|
|
|
|
/*
|
|
* DLL entry point for Win32
|
|
*/
|
|
|
|
BOOL WINAPI _DllMainCRTStartup(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpvReserved) {
|
|
switch (dwReason) {
|
|
case DLL_PROCESS_ATTACH:
|
|
hinst = hinstDll; // set global hinst
|
|
break;
|
|
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|