|
|
/***********************************************************************
* * OOUSER.C * * Microsoft At Work Fax AB One Off Mail User object * This file contains the code for implementing the Microsoft At Work Fax AB * One Off Mail user. * * Copyright 1992, 1994 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 * 3.17.94 Yoram Yaacovi Update to MAPI build 154 * 4.8.94 Yoram Yaacovi Update to MAPI build 158. Made edit boxes editable * 4.12.94 Yoram Yaacovi Most props are now set on the OOTID (ootid.c) object * instead of the OOUSER object. * 8.8.94 Yoram Yaacovi Updated to MAPI 304 and new spec * ***********************************************************************/
#define _FAXAB_OOUSER
#include "faxab.h"
/*
* External functions */
/*
* Display table control structures for the OneOff property sheet. */
/*
* Control definitions in abuser.c */
extern DTBLEDIT editUserDisplayName; extern DTBLEDIT editUserAreaCode; extern DTBLEDIT editUserTelNumber; extern DTBLDDLBX ddlbxCountryCodes;
/*
* General Property Page definition * * Should be kept in sync with the one for an AB user in abuser.c * Could not use the same because of some fields that need to be editable * here, and read-only for an AB user */
// extern DTCTL rgdtctlUserGeneral[];
// extern WORD sizeof_rgdtpageUserGeneral;
// extern DTPAGE rgdtpageUser[];
// extern WORD sizeof_rgdtpageUser;
// Description the the Fax AB pane in MAPI dialog description language
static DTCTL rgdtctlOOUserGeneral[] = { /* general property page */ { DTCT_PAGE, 0, NULL, 0, NULL, 0, &dtblpage },
/* cover page name static control and edit control */ { DTCT_LABEL, 0, NULL, 0, NULL, IDC_RECIP_DISPLAY_NAME_LABEL, &dtbllabel }, { DTCT_EDIT, DT_REQUIRED | DT_EDITABLE | DT_ACCEPT_DBCS | DT_SET_IMMEDIATE, NULL, 0, (LPTSTR)szNoFilter, IDC_RECIP_DISPLAY_NAME, &editUserDisplayName },
/* Country codes label and drop down list box */ { DTCT_LABEL, 0, NULL, 0, NULL, IDC_RECIP_COUNTRY_CODE_LABEL, &dtbllabel }, { DTCT_DDLBX, DT_EDITABLE, NULL, 0, NULL, IDC_RECIP_COUNTRY_CODE, &ddlbxCountryCodes },
/* Area code and fax number label */ { DTCT_LABEL, 0, NULL, 0, NULL, IDC_RECIP_FAX_NUMBER_LABEL, &dtbllabel },
/* area code edit control */ { DTCT_EDIT, DT_EDITABLE, NULL, 0, (LPTSTR)szDigitsOnlyFilter, IDC_RECIP_FAX_NUMBER_AREA_CODE, &editUserAreaCode },
/* Fax number static control and edit control */ { DTCT_LABEL, 0, NULL, 0, NULL, IDC_RECIP_FAX_NUMBER_LABEL2, &dtbllabel }, { DTCT_EDIT, DT_REQUIRED | DT_EDITABLE, NULL, 0, (LPTSTR)szDigitsOnlyFilter, IDC_RECIP_FAX_NUMBER, &editUserTelNumber} };
/*
* The OneOff property sheet definition * Currently using exactly the same layout as the AB user dialog * with some fields editable here and read-only for an AB user */ static DTPAGE rgdtpageOOUser[] = { { ARRAYSIZE(rgdtctlOOUserGeneral), (LPTSTR)MAKEINTRESOURCE(MAWFRecipient), TEXT(""), rgdtctlOOUserGeneral }, };
/*
* ABOOUser jump table is defined here... */ ABOOUSER_Vtbl vtblABOOUSER = { (ABOOUSER_QueryInterface_METHOD *) ABU_QueryInterface, (ABOOUSER_AddRef_METHOD *) WRAP_AddRef, ABOOUSER_Release, (ABOOUSER_GetLastError_METHOD *) WRAP_GetLastError, (ABOOUSER_SaveChanges_METHOD *) WRAP_SaveChanges, (ABOOUSER_GetProps_METHOD *) WRAP_GetProps, (ABOOUSER_GetPropList_METHOD *) WRAP_GetPropList, ABOOUSER_OpenProperty, (ABOOUSER_SetProps_METHOD *) WRAP_SetProps, (ABOOUSER_DeleteProps_METHOD *) WRAP_DeleteProps, (ABOOUSER_CopyTo_METHOD *) WRAP_CopyTo, (ABOOUSER_CopyProps_METHOD *) WRAP_CopyProps, (ABOOUSER_GetNamesFromIDs_METHOD *) WRAP_GetNamesFromIDs, (ABOOUSER_GetIDsFromNames_METHOD *) WRAP_GetIDsFromNames, };
enum { ivalusrPR_DISPLAY_TYPE = 0, ivalusrPR_OBJECT_TYPE, ivalusrPR_ADDRTYPE, ivalusrPR_COUNTRY_ID, ivalusrPR_AREA_CODE, #ifdef INIT_TEL_NUMBER
ivalusrPR_TEL_NUMBER, #endif
ivalusrPR_TEMPLATEID, cvalusrMax };
/*************************************************************************
* - HrNewFaxOOUser - * Creates the IMAPIProp associated with a one off mail user. * * */ HRESULT HrNewFaxOOUser( LPMAILUSER * lppMAPIPropEntry, ULONG * lpulObjType, ULONG cbEntryID, LPENTRYID lpEntryID, LPABLOGON lpABPLogon, LPCIID lpInterface, HINSTANCE hLibrary, LPALLOCATEBUFFER lpAllocBuff, LPALLOCATEMORE lpAllocMore, LPFREEBUFFER lpFreeBuff, LPMALLOC lpMalloc ) { LPABOOUSER lpABOOUser = NULL; SCODE sc; HRESULT hr = hrSuccess; LPPROPDATA lpPropData = NULL; SPropValue spv[cvalusrMax]; #ifdef UNICODE
CHAR szAnsiAreaCode[ AREA_CODE_SIZE ]; CHAR szEMT[ MAX_PATH ]; #endif
/* Do I support this interface?? */ if (lpInterface) { if ( memcmp(lpInterface, &IID_IMailUser, SIZEOF(IID)) && memcmp(lpInterface, &IID_IMAPIProp, SIZEOF(IID)) && memcmp(lpInterface, &IID_IUnknown, SIZEOF(IID)) ) { DebugTraceSc(HrNewSampOOUser, MAPI_E_INTERFACE_NOT_SUPPORTED); return ResultFromScode(MAPI_E_INTERFACE_NOT_SUPPORTED); } }
/*
* Allocate space for the ABOOUser structure */ sc = lpAllocBuff(SIZEOF(ABOOUSER), (LPVOID *) & lpABOOUser);
if (FAILED(sc)) { hr = ResultFromScode (sc); DebugTraceResult(NewFaxUser, hr); goto err; }
lpABOOUser->lpVtbl = &vtblABOOUSER; lpABOOUser->lcInit = 1; lpABOOUser->hResult = hrSuccess; lpABOOUser->idsLastError = 0; lpABOOUser->hLibrary = hLibrary; lpABOOUser->lpAllocBuff = lpAllocBuff; lpABOOUser->lpAllocMore = lpAllocMore; lpABOOUser->lpFreeBuff = lpFreeBuff; lpABOOUser->lpMalloc = lpMalloc; lpABOOUser->lpABLogon = lpABPLogon; lpABOOUser->lpTDatDDListBox = NULL;
/*
* Create lpPropData */
sc = CreateIProp( (LPIID) &IID_IMAPIPropData, lpAllocBuff, lpAllocMore, lpFreeBuff, lpMalloc, &lpPropData );
if (FAILED(sc)) { hr = ResultFromScode (sc); goto err; }
/*
* Set up the initial set of properties */
spv[ivalusrPR_DISPLAY_TYPE].ulPropTag = PR_DISPLAY_TYPE; spv[ivalusrPR_DISPLAY_TYPE].Value.l = DT_MAILUSER;
spv[ivalusrPR_OBJECT_TYPE].ulPropTag = PR_OBJECT_TYPE; spv[ivalusrPR_OBJECT_TYPE].Value.l = MAPI_MAILUSER;
spv[ivalusrPR_ADDRTYPE].ulPropTag = PR_ADDRTYPE_A; #ifdef UNICODE
szEMT[0] = 0; WideCharToMultiByte( CP_ACP, 0, lpszEMT, -1, szEMT, ARRAYSIZE(szEMT), NULL, NULL ); spv[ivalusrPR_ADDRTYPE].Value.lpszA = szEMT; #else
spv[ivalusrPR_ADDRTYPE].Value.LPSZ = lpszEMT; #endif
spv[ivalusrPR_TEMPLATEID].ulPropTag = PR_TEMPLATEID; spv[ivalusrPR_TEMPLATEID].Value.bin.cb = SIZEOF(OOUSER_ENTRYID); spv[ivalusrPR_TEMPLATEID].Value.bin.lpb = (LPBYTE) lpEntryID;
spv[ivalusrPR_COUNTRY_ID].ulPropTag = PR_COUNTRY_ID; /*
spv[ivalusrPR_COUNTRY_ID].Value.ul = 1; // U.S.;
*/
spv[ivalusrPR_COUNTRY_ID].Value.ul = GetCurrentLocationCountryID();
// display the area code of the current location
spv[ivalusrPR_AREA_CODE].ulPropTag = PR_AREA_CODE_A; #ifdef UNICODE
szAnsiAreaCode[0] = 0; WideCharToMultiByte( CP_ACP, 0, GetCurrentLocationAreaCode(), -1, szAnsiAreaCode, ARRAYSIZE(szAnsiAreaCode), NULL, NULL ); spv[ivalusrPR_AREA_CODE].Value.lpszA = szAnsiAreaCode; #else
spv[ivalusrPR_AREA_CODE].Value.lpszA = GetCurrentLocationAreaCode(); #endif
#ifdef INIT_TEL_NUMBER
// initialize the fax number, so that it won't be PT_ERROR
spv[ivalusrPR_TEL_NUMBER].ulPropTag = PR_TEL_NUMBER_A; spv[ivalusrPR_TEL_NUMBER].Value.lpszA = (LPSTR) ""; #endif
/*
* Note that we're using our entryID for our templateID. * This is a really simple way to implement templateIDs. * (See TID.C) */
/*
* Set the default properties */ hr = lpPropData->lpVtbl->SetProps( lpPropData, cvalusrMax, spv, NULL );
if (HR_FAILED(hr)) { DebugTraceResult(NewFaxOOUser, hr); goto err; }
(void) lpPropData->lpVtbl->HrSetObjAccess(lpPropData, IPROP_READWRITE);
lpABOOUser->lpPropData = (LPMAPIPROP) lpPropData;
InitializeCriticalSection(&lpABOOUser->cs);
*lppMAPIPropEntry = (LPVOID) lpABOOUser; *lpulObjType = MAPI_MAILUSER;
out: DebugTraceResult(HrNewSampOOUser, hr); return hr;
err: if (lpPropData) lpPropData->lpVtbl->Release(lpPropData);
lpFreeBuff( lpABOOUser );
goto out; }
/***************************************************
* * The actual ABOOUser methods */
/**************************************************
* - ABOOUSER_Release - * Decrement lpInit. * When lcInit == 0, free up the lpABOOUser structure * */ STDMETHODIMP_(ULONG) ABOOUSER_Release (LPABOOUSER lpABOOUser) {
LONG lcInit; /*
* Check to see if it's big enough to hold this object */ if (IsBadReadPtr(lpABOOUser, SIZEOF(ABOOUSER))) { /*
* Not large enough */ return 1; }
/*
* Check to see that it's the correct vtbl */ if (lpABOOUser->lpVtbl != &vtblABOOUSER) { /*
* Not my vtbl */ return 1; }
EnterCriticalSection(&lpABOOUser->cs); lcInit = --lpABOOUser->lcInit; LeaveCriticalSection(&lpABOOUser->cs);
if (lcInit == 0) {
/*
* Get rid of the lpPropData */
lpABOOUser->lpPropData->lpVtbl->Release(lpABOOUser->lpPropData);
/*
* Get rid of the country codes table */
if (lpABOOUser->lpTDatDDListBox) lpABOOUser->lpTDatDDListBox->lpVtbl->Release(lpABOOUser->lpTDatDDListBox);
/*
* Destroy the critical section for this object */
DeleteCriticalSection(&lpABOOUser->cs);
/*
* Set the vtbl to NULL. This way the client will find out * real fast if it's calling a method on a released object. That is, * the client will crash. Hopefully, this will happen during the * development stage of the client. */
lpABOOUser->lpVtbl = NULL;
/*
* Need to free the object */
lpABOOUser->lpFreeBuff( lpABOOUser ); return 0; }
return lcInit;
}
/*************************************************************************
* - ABOOUSER_OpenProperty - * * This is how we get the display table associated with this users * details screen. */ STDMETHODIMP ABOOUSER_OpenProperty( LPABOOUSER lpABOOUser, ULONG ulPropTag, LPCIID lpiid, ULONG ulInterfaceOptions, ULONG ulFlags, LPUNKNOWN * lppUnk) { LPMAPITABLE lpDisplayTable=NULL;
/*
* Since the default is that we do not support opening this * object, we can initialize our hResult here. */ HRESULT hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
/*
* Check to see if it can be pointing to the right structure. */ if (IsBadReadPtr(lpABOOUser, SIZEOF(ABOOUSER))) { /*
* Not big enough to be my object */ hResult = ResultFromScode(E_INVALIDARG); goto out; }
/*
* Check to see that it's got the correct vtbl */ if (lpABOOUser->lpVtbl != &vtblABOOUSER) { /*
* Not my vtbl */ hResult = ResultFromScode(E_INVALIDARG); goto out; }
if (IsBadReadPtr(lpiid, SIZEOF(IID))) { /*
* Interfaces are required on this method. */ hResult = ResultFromScode(E_ACCESSDENIED); goto out; }
if (ulInterfaceOptions & ~MAPI_UNICODE ) { /*
* Only UNICODE flag should be set for any of the objects that might * be returned from this object. */ hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS); goto out; }
if ( ulInterfaceOptions & MAPI_UNICODE ) { hResult = ResultFromScode( MAPI_E_BAD_CHARWIDTH ); goto out; }
if (ulFlags & ~(MAPI_CREATE|MAPI_MODIFY|MAPI_DEFERRED_ERRORS)) { /*
* Don't understand the flags that were passed in */ hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS); goto out; }
if (ulFlags & MAPI_CREATE) { /*
* Don't support creating any sub-objects */ hResult = ResultFromScode(E_ACCESSDENIED); goto out; }
if (IsBadWritePtr(lppUnk, SIZEOF(LPUNKNOWN))) { /*
* Got to be able to return an object */ hResult = ResultFromScode(E_INVALIDARG); goto out; }
// If the caller is trying to open a table property and is not expecting a table interface..
switch (ulPropTag) { case PR_DETAILS_TABLE: case PR_DDLBX_COUNTRIES_TABLE: if (memcmp( lpiid, &IID_IMAPITable, SIZEOF(IID) )) { // ... we will abort right here
hResult = ResultFromScode(E_NOINTERFACE); goto out; } break;
default: break; }
/* Check to see if I need a display table*/
switch (ulPropTag) {
case PR_DETAILS_TABLE:
/* Looking for the display table*/
/* // Going to use the AB user display array, but make all editable
// fields editable
for (i=0; i < (sizeof_rgdtpageUserGeneral / sizeof(DTCTL)); i++) if ((rgdtctlUserGeneral[i].ulCtlType == DTCT_EDIT) || (rgdtctlUserGeneral[i].ulCtlType == DTCT_DDLBX))
*/
/* Create a display table */
hResult = BuildDisplayTable( lpABOOUser->lpAllocBuff, lpABOOUser->lpAllocMore, lpABOOUser->lpFreeBuff, lpABOOUser->lpMalloc, lpABOOUser->hLibrary, ARRAYSIZE(rgdtpageOOUser), rgdtpageOOUser, 0, &lpDisplayTable, NULL );
#ifdef WRAP_TABLE
HrNewTableWrap(&lpDisplayTable); #endif
*lppUnk = (LPUNKNOWN) lpDisplayTable;
if (HR_FAILED(hResult)) { goto out; }
/*
* We're succeeding. Ensure our hResult is set properly */
hResult = hrSuccess; break;
case PR_DDLBX_COUNTRIES_TABLE:
// This table is not changing dynamically. No need to rebuild if already built.
if (!lpABOOUser->lpTDatDDListBox) { hResult = HrBuildDDLBXCountriesTable((LPABUSER) lpABOOUser); if (HR_FAILED(hResult)) goto out; }
Assert(lpABOOUser->lpTDatDDListBox);
/* Get a view from the TAD*/ hResult = lpABOOUser->lpTDatDDListBox->lpVtbl->HrGetView( lpABOOUser->lpTDatDDListBox, NULL, NULL, 0, (LPMAPITABLE *) lppUnk);
break;
default: hResult = ResultFromScode(MAPI_E_NO_SUPPORT); break;
}
out:
DebugTraceResult(ABOOUSER_OpenProperty, hResult); return hResult;
}
/**********************************************************************
* * Private functions */
#undef _FAXAB_OOUSER
|