windows-nt/Source/XPSP1/NT/printscan/fax/exchange/ab/oouser.c
2020-09-26 16:20:57 +08:00

610 lines
17 KiB
C

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