610 lines
17 KiB
C
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
|
|
|