900 lines
29 KiB
C
900 lines
29 KiB
C
/***********************************************************************
|
|
*
|
|
* OOTID.C
|
|
*
|
|
* Microsoft At Work Fax Address Book OneOff Template ID object
|
|
* This file contains the code for implementing the Microsoft At Work Fax AB
|
|
* TID object.
|
|
*
|
|
* Copyright 1992, 1993 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* Revision History:
|
|
*
|
|
* When Who What
|
|
* -------- ------------------ ---------------------------------------
|
|
* MAPI Original source from MAPI(154) sample AB Provider
|
|
* 3.7.94 Yoram Yaacovi Modifications to make it an At Work Fax ABP
|
|
* 4.2.94 Yoram Yaacovi Update to MAPI and sample AB 157
|
|
* 8.7.94 Yoram Yaacovi Update to MAPI and sample AB 304
|
|
* 8.24.94 Yoram Yaacovi Added OpenProperty and Release to support ddlbx and buttons in the one-off template
|
|
*
|
|
***********************************************************************/
|
|
|
|
#include "faxab.h"
|
|
|
|
/*
|
|
* External functions
|
|
*/
|
|
|
|
HRESULT
|
|
NewABUserButton(LPROOT, ULONG, ULONG, ULONG, LPMAPICONTROL FAR *);
|
|
void LoadIniParams(void);
|
|
|
|
/*
|
|
* OOTID jump table is defined here...
|
|
*/
|
|
|
|
static const OOTID_Vtbl vtblOOTID =
|
|
{
|
|
(OOTID_QueryInterface_METHOD *) ABU_QueryInterface,
|
|
(OOTID_AddRef_METHOD *) WRAP_AddRef,
|
|
OOTID_Release,
|
|
(OOTID_GetLastError_METHOD *) WRAP_GetLastError,
|
|
OOTID_SaveChanges,
|
|
(OOTID_GetProps_METHOD *) WRAP_GetProps,
|
|
(OOTID_GetPropList_METHOD *) WRAP_GetPropList,
|
|
OOTID_OpenProperty,
|
|
OOTID_SetProps,
|
|
(OOTID_DeleteProps_METHOD *) WRAP_DeleteProps,
|
|
(OOTID_CopyTo_METHOD *) WRAP_CopyTo,
|
|
(OOTID_CopyProps_METHOD *) WRAP_CopyProps,
|
|
(OOTID_GetNamesFromIDs_METHOD *) WRAP_GetNamesFromIDs,
|
|
(OOTID_GetIDsFromNames_METHOD *) WRAP_GetIDsFromNames,
|
|
};
|
|
|
|
// enum and property tag array for getting the properties
|
|
enum { ivalootidPR_COUNTRY_ID,
|
|
ivalootidPR_AREA_CODE,
|
|
ivalootidPR_TEL_NUMBER,
|
|
ivalootidPR_EMAIL_ADDRESS,
|
|
ivalootidPR_FAX_CP_NAME,
|
|
ivalootidMax };
|
|
|
|
static const SizedSPropTagArray(ivalootidMax,pta)=
|
|
{
|
|
ivalootidMax,
|
|
{
|
|
PR_COUNTRY_ID,
|
|
PR_AREA_CODE_A,
|
|
PR_TEL_NUMBER_A,
|
|
PR_EMAIL_ADDRESS_A,
|
|
PR_FAX_CP_NAME_A,
|
|
}
|
|
};
|
|
|
|
|
|
/*************************************************************************
|
|
*
|
|
- HrNewOOTID
|
|
-
|
|
* Creates the OOTID object associated with a mail user.
|
|
*
|
|
*
|
|
*/
|
|
HRESULT
|
|
HrNewOOTID( LPMAPIPROP * lppMAPIPropNew,
|
|
ULONG cbTemplateId,
|
|
LPENTRYID lpTemplateId,
|
|
ULONG ulTemplateFlags,
|
|
LPMAPIPROP lpPropData,
|
|
LPABLOGON lpABPLogon,
|
|
LPCIID lpInterface,
|
|
HINSTANCE hLibrary,
|
|
LPALLOCATEBUFFER lpAllocBuff,
|
|
LPALLOCATEMORE lpAllocMore,
|
|
LPFREEBUFFER lpFreeBuff,
|
|
LPMALLOC lpMalloc
|
|
)
|
|
{
|
|
LPOOTID lpOOTID;
|
|
SCODE sc;
|
|
HRESULT hResult = hrSuccess;
|
|
LPMAILUSER lpABOOUser = NULL;
|
|
ULONG ulObjType;
|
|
LPSPropValue lpspv=NULL;
|
|
ULONG ulcValues;
|
|
PARSEDTELNUMBER sParsedFaxAddr={{TEXT("")},{TEXT("")},{TEXT("")},{TEXT("")}};
|
|
|
|
/*
|
|
* Create the one-off object corresponding to the template id
|
|
*/
|
|
hResult = HrNewFaxOOUser( &lpABOOUser,
|
|
&ulObjType,
|
|
cbTemplateId,
|
|
lpTemplateId,
|
|
lpABPLogon,
|
|
lpInterface,
|
|
hLibrary,
|
|
lpAllocBuff,
|
|
lpAllocMore,
|
|
lpFreeBuff,
|
|
lpMalloc
|
|
);
|
|
if (HR_FAILED(hResult))
|
|
{
|
|
goto err;
|
|
}
|
|
|
|
/*
|
|
* Allocate space for the OOTID structure
|
|
*/
|
|
sc = lpAllocBuff(SIZEOF(OOTID), (LPVOID *) & lpOOTID);
|
|
if (FAILED(sc))
|
|
{
|
|
DebugTrace("NewOOTID() - AllocBuffer failed %s\n",SzDecodeScode(sc));
|
|
hResult = ResultFromScode (sc);
|
|
goto err;
|
|
}
|
|
|
|
/*
|
|
* Initialize the OOTID structure
|
|
*/
|
|
|
|
lpOOTID->lpVtbl = &vtblOOTID;
|
|
lpOOTID->lcInit = 1;
|
|
lpOOTID->hResult = hrSuccess;
|
|
lpOOTID->idsLastError = 0;
|
|
lpOOTID->hLibrary = hLibrary;
|
|
lpOOTID->lpAllocBuff = lpAllocBuff;
|
|
lpOOTID->lpAllocMore = lpAllocMore;
|
|
lpOOTID->lpFreeBuff = lpFreeBuff;
|
|
lpOOTID->lpMalloc = lpMalloc;
|
|
lpOOTID->lpABLogon = lpABPLogon;
|
|
lpOOTID->lpPropData = lpPropData;
|
|
lpOOTID->lpABUser = lpABOOUser;
|
|
lstrcpy(lpOOTID->szPreviousCPName, TEXT(""));
|
|
/*
|
|
* First time creation - must set the address type and template id.
|
|
*/
|
|
if (ulTemplateFlags==FILL_ENTRY)
|
|
{
|
|
ULONG ulCount;
|
|
LPSPropValue lpspv = NULL;
|
|
/*
|
|
* Copy all the properties from my object to the propdata
|
|
* These properties were set on the oouser object when it was created
|
|
* (by HrNewFaxOOUser calling into oouser.c)
|
|
*/
|
|
hResult = lpABOOUser->lpVtbl->GetProps( lpABOOUser,
|
|
NULL,
|
|
0, /* ansi */
|
|
&ulCount,
|
|
&lpspv
|
|
);
|
|
|
|
if (FAILED(hResult))
|
|
goto err;
|
|
|
|
hResult = lpPropData->lpVtbl->SetProps( lpPropData,
|
|
ulCount,
|
|
lpspv,
|
|
NULL
|
|
);
|
|
|
|
lpFreeBuff(lpspv);
|
|
|
|
if (FAILED(hResult))
|
|
goto err;
|
|
}
|
|
|
|
// entry already exists in the PAB
|
|
else
|
|
{
|
|
LPTSTR lpszCanonical=NULL;
|
|
|
|
/*
|
|
* Get the properties that make up the email address from the
|
|
* mapiprop object
|
|
*/
|
|
hResult = lpOOTID->lpPropData->lpVtbl->GetProps( lpOOTID->lpPropData,
|
|
(LPSPropTagArray) &pta,
|
|
0, /* ansi */
|
|
&ulcValues,
|
|
&lpspv
|
|
);
|
|
|
|
// see if the tel number component of the email address exists on the object
|
|
// if it doesn't, and there is a PR_EMAIL_ADDRESS,
|
|
// create the address components from the email address
|
|
if ( (PROP_TYPE(lpspv[ivalootidPR_TEL_NUMBER].ulPropTag) == PT_ERROR) &&
|
|
(PROP_TYPE(lpspv[ivalootidPR_EMAIL_ADDRESS].ulPropTag) != PT_ERROR)
|
|
)
|
|
{
|
|
#ifdef UNICODE
|
|
WCHAR szTmp[ MAX_PATH ];
|
|
CHAR szAnsiTelNumber[ 100 ];
|
|
CHAR szAnsiAreaCode[ 5 ];
|
|
|
|
szTmp[0] = 0;
|
|
MultiByteToWideChar( CP_ACP, 0, lpspv[ivalootidPR_EMAIL_ADDRESS].Value.lpszA, -1, szTmp, ARRAYSIZE(szTmp) );
|
|
DecodeFaxAddress(szTmp, &sParsedFaxAddr);
|
|
#else
|
|
DecodeFaxAddress(lpspv[ivalootidPR_EMAIL_ADDRESS].Value.LPSZ, &sParsedFaxAddr);
|
|
#endif
|
|
|
|
lpspv[ivalootidPR_TEL_NUMBER].ulPropTag = PR_TEL_NUMBER_A;
|
|
#ifdef UNICODE
|
|
szAnsiTelNumber[0] = 0;
|
|
WideCharToMultiByte( CP_ACP, 0, sParsedFaxAddr.szTelNumber, -1, szAnsiTelNumber, ARRAYSIZE(szAnsiTelNumber), NULL, NULL );
|
|
lpspv[ivalootidPR_TEL_NUMBER].Value.lpszA = szAnsiTelNumber;
|
|
#else
|
|
lpspv[ivalootidPR_TEL_NUMBER].Value.LPSZ = sParsedFaxAddr.szTelNumber;
|
|
#endif
|
|
|
|
lpspv[ivalootidPR_AREA_CODE].ulPropTag = PR_AREA_CODE_A;
|
|
#ifdef UNICODE
|
|
szAnsiAreaCode[0] = 0;
|
|
WideCharToMultiByte( CP_ACP, 0, sParsedFaxAddr.szAreaCode, -1, szAnsiAreaCode, ARRAYSIZE(szAnsiAreaCode), NULL, NULL );
|
|
lpspv[ivalootidPR_AREA_CODE].Value.lpszA = szAnsiAreaCode;
|
|
#else
|
|
lpspv[ivalootidPR_AREA_CODE].Value.LPSZ = sParsedFaxAddr.szAreaCode;
|
|
#endif
|
|
|
|
// CHECK: may need to get country id from country code
|
|
lpspv[ivalootidPR_COUNTRY_ID].ulPropTag = PR_COUNTRY_ID;
|
|
#ifdef UNICODE
|
|
lpspv[ivalootidPR_COUNTRY_ID].Value.l = (DWORD) wcstol(sParsedFaxAddr.szCountryCode,NULL,0);
|
|
#else
|
|
lpspv[ivalootidPR_COUNTRY_ID].Value.l = (DWORD) atol(sParsedFaxAddr.szCountryCode);
|
|
#endif
|
|
|
|
}
|
|
|
|
// save the starting (previous) cover page name, so that at SaveChanges time,
|
|
// I can see if the user changed it
|
|
if (PROP_TYPE(lpspv[ivalootidPR_FAX_CP_NAME].ulPropTag) != PT_ERROR)
|
|
{
|
|
#ifdef UNICODE
|
|
lpOOTID->szPreviousCPName[0] = 0;
|
|
MultiByteToWideChar( CP_ACP, 0, lpspv[ivalootidPR_FAX_CP_NAME].Value.lpszA, -1, lpOOTID->szPreviousCPName, ARRAYSIZE(lpOOTID->szPreviousCPName) );
|
|
#else
|
|
lstrcpy(lpOOTID->szPreviousCPName, lpspv[ivalootidPR_FAX_CP_NAME].Value.LPSZ);
|
|
#endif
|
|
}
|
|
|
|
|
|
/* free the buffer */
|
|
lpOOTID->lpFreeBuff(lpspv);
|
|
|
|
if (HR_FAILED(hResult))
|
|
{
|
|
DebugTrace("HrNewOOTID: SetProps failed %s\n",SzDecodeScode(GetScode(hResult)));
|
|
goto err;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* AddRef lpPropData so we can use it after we return
|
|
*/
|
|
|
|
(void)lpPropData->lpVtbl->AddRef(lpPropData);
|
|
|
|
InitializeCriticalSection(&lpOOTID->cs);
|
|
|
|
*lppMAPIPropNew = (LPVOID) lpOOTID;
|
|
|
|
out:
|
|
|
|
DebugTraceResult(HrNewOOTID, hResult);
|
|
return hResult;
|
|
|
|
err:
|
|
|
|
if (lpABOOUser)
|
|
lpABOOUser->lpVtbl->Release(lpABOOUser);
|
|
|
|
lpFreeBuff(lpOOTID);
|
|
goto out;
|
|
|
|
}
|
|
|
|
/*********************************************************************
|
|
*********************************************************************
|
|
*
|
|
* The OOTID IMAPIProp methods
|
|
*
|
|
*/
|
|
|
|
STDMETHODIMP_(ULONG) OOTID_Release(LPOOTID lpOOTID)
|
|
{
|
|
LONG lcInit;
|
|
|
|
/*
|
|
* Check to see if it's large enough to hold this object
|
|
*/
|
|
if (IsBadReadPtr(lpOOTID, sizeof(OOTID)))
|
|
{
|
|
/*
|
|
* I'm not looking at an object that I expect to be.
|
|
*/
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Check to see that it's TIDs vtbl
|
|
*/
|
|
if (lpOOTID->lpVtbl != &vtblOOTID)
|
|
{
|
|
/*
|
|
* It's big enough but it's got the wrong vtbl.
|
|
*/
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Release the mapi property object
|
|
*/
|
|
lpOOTID->lpPropData->lpVtbl->Release( lpOOTID->lpPropData );
|
|
|
|
EnterCriticalSection(&lpOOTID->cs);
|
|
lcInit = --lpOOTID->lcInit;
|
|
LeaveCriticalSection(&lpOOTID->cs);
|
|
|
|
if (lcInit == 0)
|
|
{
|
|
/*
|
|
* Release the ABUser object
|
|
*/
|
|
lpOOTID->lpABUser->lpVtbl->Release( lpOOTID->lpABUser );
|
|
|
|
/*
|
|
* Clean up the critical section
|
|
*/
|
|
DeleteCriticalSection(&lpOOTID->cs);
|
|
|
|
/*
|
|
* Need to free the object
|
|
*/
|
|
lpOOTID->lpFreeBuff(lpOOTID);
|
|
return 0;
|
|
}
|
|
|
|
return lcInit;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
SetProps
|
|
*****************************************************************************/
|
|
STDMETHODIMP
|
|
OOTID_SetProps( LPOOTID lpOOTID,
|
|
ULONG cValues,
|
|
LPSPropValue lpPropArray,
|
|
LPSPropProblemArray * lppProblems
|
|
)
|
|
{
|
|
enum { ivalspPR_DISPLAY_NAME = 0,
|
|
ivalspMax };
|
|
ULONG i;
|
|
SPropValue spv[ivalspMax];
|
|
HRESULT hResult=hrSuccess;
|
|
|
|
/* Validate the object */
|
|
|
|
if ( FBadUnknown(lpOOTID) ||
|
|
IsBadWritePtr(lpOOTID, SIZEOF(lpOOTID)) ||
|
|
IsBadReadPtr(lpOOTID->lpVtbl, offsetof(OOTID_Vtbl, SetProps)) ||
|
|
OOTID_SetProps != lpOOTID->lpVtbl->SetProps
|
|
)
|
|
{
|
|
DebugTrace("OOTID_SetProps -> E_INVALIDARG\n");
|
|
return ResultFromScode(E_INVALIDARG);
|
|
}
|
|
|
|
for (i=0; i < cValues; i++)
|
|
{
|
|
// see if one of the set properties is PR_FAX_CP_NAME_A
|
|
if (lpPropArray[i].ulPropTag == PR_FAX_CP_NAME_A)
|
|
{
|
|
// The cover page name is copied into the display name
|
|
spv[ivalspPR_DISPLAY_NAME].ulPropTag = PR_DISPLAY_NAME_A;
|
|
spv[ivalspPR_DISPLAY_NAME].Value.lpszA = lpPropArray[i].Value.lpszA;
|
|
// set PR_DISPLAY_NAME
|
|
hResult = lpOOTID->lpPropData->lpVtbl->SetProps( lpOOTID->lpPropData,
|
|
ivalspMax,
|
|
spv,
|
|
NULL
|
|
);
|
|
|
|
if (HR_FAILED(hResult))
|
|
{
|
|
DebugTrace("OOTID_SetProps: SetProps on PR_DISPLAY_NAME failed %s\n",
|
|
SzDecodeScode(GetScode(hResult)));
|
|
goto out;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
out:
|
|
// now set the properties I was asked to save
|
|
return hResult=lpOOTID->lpPropData->lpVtbl->SetProps( lpOOTID->lpPropData,
|
|
cValues,
|
|
lpPropArray,
|
|
lppProblems
|
|
);
|
|
}
|
|
/*
|
|
* These properties are used and set by the one off dialog.
|
|
* These properties combined make up a valid email address and display name
|
|
*/
|
|
|
|
// enum and property tag array for getting the properties
|
|
enum { ivalootidgPR_DISPLAY_NAME = 0,
|
|
ivalootidgPR_FAX_CP_NAME,
|
|
ivalootidgPR_COUNTRY_ID,
|
|
ivalootidgPR_AREA_CODE,
|
|
ivalootidgPR_TEL_NUMBER,
|
|
ivalootidgPR_GIVEN_NAME,
|
|
ivalootidgPR_SURNAME,
|
|
ivalootidgPR_EMAIL_ADDRESS,
|
|
ivalootidgMax };
|
|
|
|
static const SizedSPropTagArray(ivalootidgMax,ptag)=
|
|
{
|
|
ivalootidgMax,
|
|
{
|
|
PR_DISPLAY_NAME_A,
|
|
PR_FAX_CP_NAME_A,
|
|
PR_COUNTRY_ID,
|
|
PR_AREA_CODE_A,
|
|
PR_TEL_NUMBER_A,
|
|
PR_GIVEN_NAME_A,
|
|
PR_SURNAME_A,
|
|
PR_EMAIL_ADDRESS_A,
|
|
}
|
|
};
|
|
|
|
// enum for setting the created properties
|
|
enum { /*ivalootidsPR_DISPLAY_NAME = 0,
|
|
ivalootidsPR_FAX_CP_NAME,*/
|
|
ivalootidsPR_EMAIL_ADDRESS = 0,
|
|
ivalootidsPR_PRIMARY_FAX_NUMBER,
|
|
ivalootidsMax };
|
|
|
|
|
|
/*****************************************************************************
|
|
SaveChanges
|
|
*****************************************************************************/
|
|
STDMETHODIMP
|
|
OOTID_SaveChanges( LPOOTID lpOOTID,
|
|
ULONG ulFlags
|
|
)
|
|
{
|
|
HRESULT hResult;
|
|
LPSPropValue lpspv=NULL;
|
|
SPropValue spv[ivalootidsMax];
|
|
ULONG ulcValues;
|
|
BOOL bDispName=FALSE;
|
|
BOOL bFirstName=FALSE;
|
|
BOOL bSurName=FALSE;
|
|
BOOL bCPName=FALSE;
|
|
PARSEDTELNUMBER sParsedFaxAddr={{TEXT("")},{TEXT("")},{TEXT("")},{TEXT("")}};
|
|
ULONG dwCountryCode=0;
|
|
TCHAR szEncodedFaxAddress[CANONICAL_NUMBER_SIZE];
|
|
LPSTR lpszCanonical=NULL;
|
|
#ifdef UNICODE
|
|
CHAR szAnsiFaxAddr[CANONICAL_NUMBER_SIZE];
|
|
#endif
|
|
|
|
/*
|
|
* Check to see if it is big enough to be my object
|
|
*/
|
|
if (IsBadReadPtr(lpOOTID, SIZEOF(OOTID)))
|
|
{
|
|
/*
|
|
* Not big enough
|
|
*/
|
|
return MakeResult(E_INVALIDARG);
|
|
}
|
|
|
|
/*
|
|
* Check to see that it's OOTIDs vtbl
|
|
*/
|
|
if (lpOOTID->lpVtbl != &vtblOOTID)
|
|
{
|
|
/*
|
|
* vtbl not ours
|
|
*/
|
|
return MakeResult(E_INVALIDARG);
|
|
}
|
|
|
|
|
|
/*
|
|
* Get the properties that make up the email address from the
|
|
* mapiprop object
|
|
*/
|
|
hResult = lpOOTID->lpPropData->lpVtbl->GetProps( lpOOTID->lpPropData,
|
|
(LPSPropTagArray) &ptag,
|
|
0, /* ansi */
|
|
&ulcValues,
|
|
&lpspv
|
|
);
|
|
|
|
/*
|
|
* Abort in failure. Nothing to do without an email address
|
|
*/
|
|
if (FAILED(hResult))
|
|
{
|
|
DebugTrace("OOTID_SaveChanges: GetProps failed %s\n",SzDecodeScode(GetScode(hResult)));
|
|
goto err;
|
|
}
|
|
|
|
/***************************/
|
|
/****** display name *******/
|
|
/***************************/
|
|
|
|
/*
|
|
* Need to make the display name
|
|
* I believe there must be either a PR_DISPLAY_NAME or a PR_FAX_CP_NAME. If there isn't,
|
|
* I'll make one out of the first and last name
|
|
*/
|
|
|
|
#ifdef OLD_CODE
|
|
// Set the tags
|
|
spv[ivalootidsPR_DISPLAY_NAME].ulPropTag = PR_DISPLAY_NAME_A;
|
|
spv[ivalootidsPR_FAX_CP_NAME].ulPropTag = PR_FAX_CP_NAME_A;
|
|
|
|
// Set the props to the exact value I got from GetProps
|
|
spv[ivalootidsPR_DISPLAY_NAME_A].Value.lpszA = lpspv[ivalootidgPR_DISPLAY_NAME].Value.lpszA;
|
|
spv[ivalootidsPR_FAX_CP_NAME_A].Value.lpszA = lpspv[ivalootidgPR_FAX_CP_NAME].Value.lpszA;
|
|
|
|
if ( (PROP_TYPE(lpspv[ivalootidgPR_DISPLAY_NAME_A].ulPropTag) != PT_ERROR) &&
|
|
lstrlenA(lpspv[ivalootidgPR_DISPLAY_NAME].Value.lpszA)
|
|
)
|
|
{
|
|
bDispName = TRUE;
|
|
}
|
|
|
|
if ( (PROP_TYPE(lpspv[ivalootidgPR_FAX_CP_NAME].ulPropTag) != PT_ERROR) &&
|
|
lstrlenA(lpspv[ivalootidgPR_FAX_CP_NAME].Value.lpszA))
|
|
{
|
|
bCPName = TRUE;
|
|
}
|
|
|
|
// Can't find PR_GIVEN_NAME anywhere in the MAPI or Mail world for now
|
|
if ( (PROP_TYPE(lpspv[ivalootidgPR_GIVEN_NAME].ulPropTag) != PT_ERROR) &&
|
|
lstrlenA(lpspv[ivalootidgPR_GIVEN_NAME].Value.lpszA))
|
|
{
|
|
bFirstName = TRUE;
|
|
}
|
|
|
|
if ( (PROP_TYPE(lpspv[ivalootidgPR_SURNAME].ulPropTag) != PT_ERROR) &&
|
|
lstrlenA(lpspv[ivalootidgPR_SURNAME].Value.lpszA))
|
|
{
|
|
bSurName = TRUE;
|
|
}
|
|
|
|
#ifdef EXTENDED_DEBUG
|
|
{
|
|
TCHAR msg[256];
|
|
|
|
wsprintf(msg, TEXT("Display name: %s\nCover page name: %s\nGiven name: %s\nSurname: %s\n"),
|
|
(bDispName ? lpspv[ivalootidgPR_DISPLAY_NAME].Value.LPSZ : TEXT("")),
|
|
(bCPName ? lpspv[ivalootidgPR_FAX_CP_NAME].Value.LPSZ : TEXT("")),
|
|
(bFirstName ? lpspv[ivalootidgPR_GIVEN_NAME].Value.LPSZ : TEXT("")),
|
|
(bSurName ? lpspv[ivalootidgPR_SURNAME].Value.LPSZ : TEXT("")));
|
|
|
|
MessageBox(HWND_DESKTOP, msg, TEXT("Debug Message"), MB_OK);
|
|
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
The cases:
|
|
|
|
(1) No PR_DISPLAY_NAME, but there is PR_GIVEN_NAME or PR_SURNAME: this is the
|
|
creation of the entry, and the user entered first/last name in addition
|
|
to cover page name. Don't override PR_DISPLAY_NAME with PR_FAX_CP_NAME. Exchange
|
|
will use PR_GIVEN_NAME and PR_SURNAME to create PR_DISPLAY_NAME
|
|
(2) No PR_DISPLAY_NAME, and also PR_GIVEN_NAME or PR_SURNAME: this is the
|
|
creation of the entry, and the user did not enter first/last name.
|
|
Override PR_DISPLAY_NAME with PR_FAX_CP_NAME.
|
|
(3) There is a PR_DISPLAY_NAME, and the user has changed the PR_FAX_CP_NAME: this
|
|
is not a first time entry. The user selected to edit the template, and changed
|
|
the cover page name. We are assuming he wants to reflect these changes into
|
|
the display name. There were some CompuServe complaints on not doing this.
|
|
(4) There is a PR_DISPLAY_NAME, and the user did not change the PR_FAX_CP_NAME: this
|
|
is not a first time entry. The user selected to edit the template, but did not
|
|
change the cover page name. We are not overriding the display name in this
|
|
case, thus providing a way for the user to have a display name different from
|
|
the cover page name
|
|
*/
|
|
|
|
if (!bDispName)
|
|
{
|
|
if (bFirstName || bSurName)
|
|
// (1)
|
|
{
|
|
}
|
|
else
|
|
// (2)
|
|
{
|
|
// The cover page name is copied into the display name
|
|
spv[ivalootidsPR_DISPLAY_NAME].Value.lpszA =
|
|
lpspv[ivalootidgPR_FAX_CP_NAME].Value.lpszA;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
#ifdef UNICODE
|
|
CHAR szAnsiPrevName[ MAX_PATH ];
|
|
|
|
szAnsiPrevName[0] = 0;
|
|
WideCharToMultiByte( CP_ACP, 0, lpOOTID->szPreviousName, -1, szAnsiPrevName, ARRAYSIZE(szAnsiPrevName), NULL, NULL );
|
|
if (lstrcmpA(lpspv[ivalootidgPR_FAX_CP_NAME_A].Value.lpszA, szAnsiPrevName))
|
|
#else
|
|
if (lstrcmp(lpspv[ivalootidgPR_FAX_CP_NAME_A].Value.lpszA, lpOOTID->szPreviousCPName))
|
|
#endif
|
|
// (3)
|
|
{
|
|
// The cover page name is copied into the display name
|
|
spv[ivalootidsPR_DISPLAY_NAME].Value.lpszA =
|
|
lpspv[ivalootidgPR_FAX_CP_NAME].Value.lpszA;
|
|
}
|
|
else
|
|
// (4)
|
|
{
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/***************************/
|
|
/****** email address ******/
|
|
/***************************/
|
|
|
|
// Now do the email address
|
|
// initialize the email address prop value
|
|
spv[ivalootidsPR_EMAIL_ADDRESS].ulPropTag = PR_EMAIL_ADDRESS_A;
|
|
|
|
// if there is already an email address, and no fax number, this entry
|
|
// is not created from the UI (which requires a fax number)
|
|
// Generate the address components from the email address
|
|
if ( (PROP_TYPE(lpspv[ivalootidgPR_EMAIL_ADDRESS].ulPropTag) != PT_ERROR) &&
|
|
(lpspv[ivalootidgPR_EMAIL_ADDRESS].Value.lpszA) &&
|
|
(lstrlenA(lpspv[ivalootidgPR_EMAIL_ADDRESS].Value.lpszA)) &&
|
|
(PROP_TYPE(lpspv[ivalootidgPR_TEL_NUMBER].ulPropTag) == PT_ERROR)
|
|
)
|
|
{
|
|
spv[ivalootidsPR_EMAIL_ADDRESS].Value.lpszA =
|
|
lpspv[ivalootidgPR_EMAIL_ADDRESS].Value.lpszA;
|
|
}
|
|
// no email address. must compute from properties.
|
|
else
|
|
{
|
|
// Is there a fax number ?
|
|
if ( (PROP_TYPE(lpspv[ivalootidgPR_TEL_NUMBER].ulPropTag) != PT_ERROR) &&
|
|
(lpspv[ivalootidgPR_TEL_NUMBER].Value.lpszA) &&
|
|
(lstrlenA(lpspv[ivalootidgPR_TEL_NUMBER].Value.lpszA))
|
|
)
|
|
{
|
|
// truncate if necessary. note that the MAPI dialog should limit the user
|
|
// to this number of characters anyway
|
|
#ifdef UNICODE
|
|
sParsedFaxAddr.szTelNumber[0] = 0;
|
|
MultiByteToWideChar( CP_ACP, 0,
|
|
lpspv[ivalootidgPR_TEL_NUMBER].Value.lpszA, -1,
|
|
sParsedFaxAddr.szTelNumber,
|
|
ARRAYSIZE(sParsedFaxAddr.szTelNumber)
|
|
);
|
|
#else
|
|
lstrcpyn( sParsedFaxAddr.szTelNumber,
|
|
lpspv[ivalootidgPR_TEL_NUMBER].Value.lpszA,
|
|
ARRAYSIZE(sParsedFaxAddr.szTelNumber)
|
|
);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// must have at least a fax number
|
|
// this field is required in my MAPI dialog, so I should never get here
|
|
DebugTrace("OOTID_SaveChanges: No PR_FAX_NUMBER (or invalid) on the object\n");
|
|
goto err;
|
|
}
|
|
|
|
// Country Code
|
|
if (PROP_TYPE(lpspv[ivalootidgPR_COUNTRY_ID].ulPropTag) != PT_ERROR)
|
|
{
|
|
if (!GetCountryCode(lpspv[ivalootidgPR_COUNTRY_ID].Value.ul, &dwCountryCode))
|
|
{
|
|
// Use none
|
|
dwCountryCode = 0;
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
{
|
|
CHAR szTemp[ARRAYSIZE(sParsedFaxAddr.szCountryCode)];
|
|
|
|
itoa(dwCountryCode, szTemp, COUNTRY_CODE_SIZE);
|
|
MultiByteToWideChar( CP_ACP, 0,
|
|
szTemp, -1,
|
|
sParsedFaxAddr.szCountryCode,
|
|
ARRAYSIZE(sParsedFaxAddr.szCountryCode)
|
|
);
|
|
}
|
|
#else
|
|
itoa(dwCountryCode, sParsedFaxAddr.szCountryCode, COUNTRY_CODE_SIZE);
|
|
#endif
|
|
|
|
}
|
|
|
|
// Area Code
|
|
if ( (PROP_TYPE(lpspv[ivalootidgPR_AREA_CODE].ulPropTag) != PT_ERROR) &&
|
|
(lpspv[ivalootidgPR_AREA_CODE].Value.lpszA)
|
|
)
|
|
{
|
|
// if we ended up with a 0 as the area code (error or internal extension,
|
|
// this won't be a canonical number and I don't need the area code.
|
|
// truncate if necessary
|
|
if (dwCountryCode != 0)
|
|
{
|
|
#ifdef UNICODE
|
|
sParsedFaxAddr.szAreaCode[0] = 0;
|
|
MultiByteToWideChar( CP_ACP, 0,
|
|
lpspv[ivalootidgPR_AREA_CODE].Value.lpszA,
|
|
-1,
|
|
sParsedFaxAddr.szAreaCode,
|
|
ARRAYSIZE(sParsedFaxAddr.szAreaCode)
|
|
);
|
|
#else
|
|
lstrcpyn( sParsedFaxAddr.szAreaCode,
|
|
lpspv[ivalootidgPR_AREA_CODE].Value.LPSZ,
|
|
ARRAYSIZE(sParsedFaxAddr.szAreaCode)
|
|
);
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
// Construct the canonical number from the components
|
|
EncodeFaxAddress(szEncodedFaxAddress, &sParsedFaxAddr);
|
|
|
|
#ifdef UNICODE
|
|
szAnsiFaxAddr[0] = 0;
|
|
WideCharToMultiByte( CP_ACP, 0, szEncodedFaxAddress, -1, szAnsiFaxAddr, ARRAYSIZE(szAnsiFaxAddr), NULL, NULL );
|
|
spv[ivalootidsPR_EMAIL_ADDRESS].Value.lpszA = szAnsiFaxAddr;
|
|
#else
|
|
spv[ivalootidsPR_EMAIL_ADDRESS].Value.LPSZ = szEncodedFaxAddress;
|
|
#endif
|
|
|
|
}
|
|
|
|
// now use the same fax number, but w/o the mailbox, to set the
|
|
// primary fax property on the telephone pane
|
|
spv[ivalootidsPR_PRIMARY_FAX_NUMBER].ulPropTag = PR_PRIMARY_FAX_NUMBER_A;
|
|
|
|
// don't want the mailbox for this
|
|
lpszCanonical = _mbsrchr(spv[ivalootidsPR_EMAIL_ADDRESS].Value.lpszA, '+');
|
|
if (lpszCanonical)
|
|
spv[ivalootidsPR_PRIMARY_FAX_NUMBER].Value.lpszA = lpszCanonical;
|
|
else
|
|
spv[ivalootidsPR_PRIMARY_FAX_NUMBER].Value.lpszA = "";
|
|
|
|
/***************************/
|
|
/****** toll list ******/
|
|
/***************************/
|
|
|
|
/* set the email address property value */
|
|
hResult= lpOOTID->lpPropData->lpVtbl->SetProps( lpOOTID->lpPropData,
|
|
ivalootidsMax,
|
|
spv,
|
|
NULL
|
|
);
|
|
|
|
if (HR_FAILED(hResult))
|
|
{
|
|
DebugTrace("OOTID_SaveChanges: SetProps failed %s\n",SzDecodeScode(GetScode(hResult)));
|
|
goto err;
|
|
}
|
|
|
|
hResult = lpOOTID->lpPropData->lpVtbl->SaveChanges( lpOOTID->lpPropData,
|
|
ulFlags
|
|
);
|
|
|
|
err:
|
|
/* free the buffer */
|
|
lpOOTID->lpFreeBuff(lpspv);
|
|
|
|
DebugTraceResult(OOTID_SaveChanges,hResult);
|
|
return hResult;
|
|
}
|
|
|
|
/*
|
|
- OOTID_OpenProperty
|
|
-
|
|
* This is needed to support the countries table and dial helper button on the one-off
|
|
* template. If the one-off template would only have edit controls nad checkboxes, I
|
|
* could call the wrapper object OpenProperty.
|
|
*
|
|
*/
|
|
|
|
STDMETHODIMP
|
|
OOTID_OpenProperty( LPOOTID lpOOTID,
|
|
ULONG ulPropTag,
|
|
LPCIID lpiid,
|
|
ULONG ulInterfaceOptions,
|
|
ULONG ulFlags,
|
|
LPUNKNOWN * lppUnk
|
|
)
|
|
{
|
|
|
|
HRESULT hResult;
|
|
|
|
/*
|
|
* Check to see if it's large enough to hold this object
|
|
*/
|
|
if (IsBadReadPtr(lpOOTID, SIZEOF(OOTID)))
|
|
{
|
|
/*
|
|
* No vtbl found
|
|
*/
|
|
return ResultFromScode(E_INVALIDARG);
|
|
}
|
|
|
|
/*
|
|
* Check to see that it's TIDs vtbl
|
|
*/
|
|
if (lpOOTID->lpVtbl != &vtblOOTID)
|
|
{
|
|
/*
|
|
* It's big enough but it's got the wrong vtbl.
|
|
*/
|
|
return ResultFromScode(E_INVALIDARG);
|
|
}
|
|
|
|
/*
|
|
* Don't want to check any other parameters here.
|
|
* Calls down to wrapped objects will do this for
|
|
* me.
|
|
*/
|
|
|
|
switch (ulPropTag)
|
|
{
|
|
// For now, I just call the underlying (my) user object method to handle, which
|
|
// means the template ID does not do anything.
|
|
|
|
case PR_DETAILS_TABLE:
|
|
case PR_DDLBX_COUNTRIES_TABLE:
|
|
case PR_DIAL_HELPER_BUTTON:
|
|
{
|
|
hResult = lpOOTID->lpABUser->lpVtbl->OpenProperty(
|
|
lpOOTID->lpABUser,
|
|
ulPropTag,
|
|
lpiid,
|
|
ulInterfaceOptions,
|
|
ulFlags,
|
|
lppUnk);
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
{
|
|
hResult = lpOOTID->lpPropData->lpVtbl->OpenProperty(
|
|
lpOOTID->lpPropData,
|
|
ulPropTag,
|
|
lpiid,
|
|
ulInterfaceOptions,
|
|
ulFlags,
|
|
lppUnk);
|
|
break;
|
|
}
|
|
}
|
|
|
|
DebugTraceResult(OOTID_OpenProperty, hResult);
|
|
return hResult;
|
|
|
|
}
|
|
|