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

1404 lines
38 KiB
C

/***********************************************************************
*
* ABP.C
*
*
* The Microsoft At Work Fax Address Book Provider.
* This file contains the routines that handle the ABPJump table.
*
* The following routines are implemented in this file:
*
* ABProviderInit
* ABP_QueryInterface
* ABP_Release
* ABP_Shutdown
* ABP_Logon
*
* ServiceEntry
* HrOpenSingleProvider
*
* RemoveLogonObject
* FindLogonObject
* ScLoadString
*
* Globals defined in this file:
*
* Copyright 1992, 1993 Microsoft Corporation. All Rights Reserved.
*
* Revision History:
*
* When Who What
* -------- ------------------ ---------------------------------------
* 1.1.94 MAPI Original source from MAPI sample AB Provider
* 1.27.94 Yoram Yaacovi Modifications to make it an At Work Fax ABP
* 3.5.94 Yoram Yaacovi Update to MAPI build 154
* 4.1.94 Yoram Yaacovi Update to MAPI and sample AB build 157
* 8.1.94 Yoram Yaacovi Update to MAPI and sample AB build 306
*
***********************************************************************/
#define _FAXAB_ABP
#include "faxab.h"
/*
* Prototypes for the functions in this file, most of which I return
* in the jump table returned from ABProviderInit().
*/
ABPROVIDERINIT ABProviderInit;
MSGSERVICEENTRY FABServiceEntry;
HRESULT HrOpenSingleProvider( LPPROVIDERADMIN lpAdminProviders,
LPPROFSECT FAR *lppProfSect
);
void LoadIniParams(void);
/*
* The jump table returned from ABProviderInit().
*/
ABP_Vtbl vtblABP =
{
ABP_QueryInterface,
(ABP_AddRef_METHOD *) ROOT_AddRef,
ABP_Release,
ABP_Shutdown,
ABP_Logon
};
/*************************************************************************
*
- ABProviderInit
-
* Initializes this provider. Returns a jump table that contains the
* addresses of the rest of the functions.
*
*/
HRESULT STDMAPIINITCALLTYPE
ABProviderInit (
HINSTANCE hLibrary,
LPMALLOC lpMalloc,
LPALLOCATEBUFFER lpAllocBuff,
LPALLOCATEMORE lpAllocMore,
LPFREEBUFFER lpFreeBuff,
ULONG ulFlags,
ULONG ulMAPIVersion,
ULONG FAR * lpulABVersion,
LPABPROVIDER FAR * lppABProvider)
{
HRESULT hResult = hrSuccess;
LPABP lpABP;
SCODE scode;
//DebugBreak();
DebugTrace("AWFXAB32(ABProviderInit): entering\n");
// Get registry settings
LoadIniParams();
#ifdef DEBUG
if (fDebugTrap)
DebugBreak();
#endif
/*
* Check the version
*/
if (ulMAPIVersion < CURRENT_SPI_VERSION)
{
/*
* MAPI's version is too old.
*/
/*
* See if they understand my version
*/
*lpulABVersion = CURRENT_SPI_VERSION;
DebugTraceSc(ABProviderInit, MAPI_E_VERSION);
return ResultFromScode(MAPI_E_VERSION);
}
/*
* Allocate memory for this Init Object
*/
scode = lpAllocBuff (SIZEOF(ABP), &lpABP);
if (FAILED(scode))
{
/*
* Out of memory
*/
DebugTraceSc(ABProviderInit, scode);
return ResultFromScode(scode);
}
/*
* Initialize the idle engine that MAPI supplies. This is most useful
* when browsing the .FAB file. See ABCTBLn.C.
*/
if (MAPIInitIdle( NULL )==-1)
{
hResult = ResultFromScode(E_FAIL);
goto err;
}
/*
* Hold on to the lpMalloc
*/
if (lpMalloc)
lpMalloc->lpVtbl->AddRef(lpMalloc);
lpABP->lpVtbl = &vtblABP;
lpABP->lcInit = 1;
lpABP->hLibrary = hLibrary;
lpABP->lpMalloc = lpMalloc;
lpABP->lpAllocBuff = lpAllocBuff;
lpABP->lpAllocMore = lpAllocMore;
lpABP->lpFreeBuff = lpFreeBuff;
lpABP->lpObjectList= NULL;
InitializeCriticalSection(&lpABP->cs);
*lppABProvider = (LPABPROVIDER)lpABP;
*lpulABVersion = CURRENT_SPI_VERSION;
/*
* Get our Locale Identifier
*/
lcidUser = GetUserDefaultLCID();
out:
DebugTraceResult(ABProviderInit, hResult);
return hResult;
err:
lpFreeBuff(lpABP);
goto out;
}
/*
* The Init Object's methods implementation
*/
/**********************************************************************
- ABP_QueryInterface
-
* Supports QI'ing to IUnknown and IABProvider
*
* Note that for all the methods of IABProvider that parameter validation
* is unnecessary. This is because MAPI is handling all the parameters
* being passed in.
* At best you can assert your parameters.
*/
STDMETHODIMP
ABP_QueryInterface (LPABP lpABP, REFIID lpiid, LPVOID *ppvObj)
{
DebugTrace("AWFXAB32(ABP_QueryInterface): entering\n");
/* See if the requested interface is one of ours */
if ( memcmp (lpiid, &IID_IUnknown, SIZEOF (IID)) &&
memcmp (lpiid, &IID_IABProvider, SIZEOF (IID))
)
{
*ppvObj = NULL; /* OLE requires zeroing [out] parameter on error */
DebugTraceSc(ABP_QueryInterface, E_NOINTERFACE);
return ResultFromScode (E_NOINTERFACE);
}
/* We'll do this one. Bump the usage count and return a new pointer. */
EnterCriticalSection(&lpABP->cs);
++lpABP->lcInit;
LeaveCriticalSection(&lpABP->cs);
*ppvObj = lpABP;
return hrSuccess;
}
/*
* Use ROOTs AddRef
*/
/*************************************************************************
*
- ABP_Release
-
* Releases and cleans up this object
*/
STDMETHODIMP_(ULONG)
ABP_Release (LPABP lpABP)
{
long lcInit;
DebugTrace("AWFXAB32(ABP_Release): entering\n");
EnterCriticalSection(&lpABP->cs);
lcInit = --lpABP->lcInit;
LeaveCriticalSection(&lpABP->cs);
if (lcInit == 0)
{
DeleteCriticalSection(&lpABP->cs);
lpABP->lpVtbl = NULL;
lpABP->lpFreeBuff(lpABP);
return (0);
}
return lcInit;
}
/**********************************************************************
- ABP_Shutdown
-
* Informs this provider that MAPI is done with it.
*
*
*/
STDMETHODIMP
ABP_Shutdown (LPABP lpABP, ULONG FAR *lpulFlags)
{
DebugTrace("AWFXAB32(ABP_Shutdown): entering\n");
MAPIDeinitIdle();
if (lpABP->lpMalloc)
{
lpABP->lpMalloc->lpVtbl->Release(lpABP->lpMalloc);
lpABP->lpMalloc = NULL;
}
return hrSuccess;
}
/*************************************************************************
*
- ABP_Logon
-
* Create a logon object and return it to MAPI.
*
*/
/*
* The PropTagArray used to retrieve logon properties
*/
enum { ivallogonPR_FAB_FILE=0,
ivallogonPR_FAB_UID,
cvallogonMax };
static const SizedSPropTagArray(cvallogonMax, tagaFABLogonProps) =
{
cvallogonMax,
{
PR_FAB_FILE_A,
PR_FAB_UID
}
};
STDMETHODIMP
ABP_Logon( LPABP lpABP,
LPMAPISUP lpMAPISup,
ULONG ulUIParam,
LPTSTR lpszProfileName,
ULONG ulFlags,
ULONG FAR * lpulpcbSecurity,
LPBYTE FAR * lppbSecurity,
LPMAPIERROR FAR * lppMapiError,
LPABLOGON FAR * lppABPLogon
)
{
LPABLOGON lpABLogon = NULL;
HRESULT hResult = hrSuccess;
SCODE scode;
LPPROFSECT lpProfSect = NULL;
LPSPropValue lpsPropVal = NULL;
ULONG cValues = 0;
TCHAR szFileName[MAX_PATH];
LPTSTR lpstrT = NULL;
BOOL fUINeeded;
BOOL fNeedMAPIUID = FALSE;
MAPIUID muidID;
LPOBJECTLIST lpObjectList;
LPTSTR lpszAppName=NULL;
#ifdef UNICODE
CHAR szAnsiFileName[ MAX_PATH ];
#endif
#ifdef EXTENDED_DEBUG
MessageBox((HWND) ulUIParam, TEXT("ABP_Logon: entering"), TEXT("awfxab debug message"), MB_OK);
#endif
DebugTrace("AWFXAB32(ABP_Logon): entering\n");
szFileName[0] = TEXT('\0');
*lppMapiError = NULL;
if ( ulFlags & MAPI_UNICODE )
{
DebugTraceArg( ABP_Logon, "Bad Character width" );
return ResultFromScode( MAPI_E_BAD_CHARWIDTH );
}
/*
* Get the name of my browse file from the profile section
*/
/* Open the section for my provider */
hResult = lpMAPISup->lpVtbl->OpenProfileSection( lpMAPISup,
NULL,
MAPI_MODIFY,
&lpProfSect
);
if (HR_FAILED(hResult))
goto out;
/* Get the property containing the Fax AB file name. */
hResult = lpProfSect->lpVtbl->GetProps( lpProfSect,
(LPSPropTagArray)&tagaFABLogonProps,
0, // ANSI
&cValues,
&lpsPropVal
);
if (HR_FAILED(hResult))
goto out;
#ifdef DEBUG
/* The only expected return code is MAPI_E_NOT_FOUND. */
if (hResult != hrSuccess)
{
if (GetScode (hResult) != MAPI_W_ERRORS_RETURNED)
{
DebugTrace("AWFXAB32(ABP_Logon): got unexpected hResult: ");
DebugTraceResult(ProfileGetProps, hResult);
}
else if (lpsPropVal[0].Value.err != MAPI_E_NOT_FOUND)
{
DebugTrace("AWFXAB32(ABP_Logon): got unexpected scode: ");
DebugTraceSc(ProfileGetProps, lpsPropVal[0].Value.err);
}
}
#endif
/* Ignore warnings from reading the property. */
hResult = hrSuccess;
/* copy the Fax Address Book file name */
if (lpsPropVal[0].ulPropTag==PR_FAB_FILE_A)
{
UINT cch = lstrlenA(lpsPropVal[0].Value.lpszA);
if (cch >= MAX_PATH)
cch = MAX_PATH-1;
if (cch)
#ifdef UNICODE
MultiByteToWideChar( CP_ACP, 0, lpsPropVal[0].Value.lpszA, -1, szFileName, ARRAYSIZE(szFileName) );
#else
memcpy(szFileName, lpsPropVal[0].Value.lpszA, cch);
#endif
szFileName[cch] = TEXT('\0');
}
else
{
DebugTrace("AWFXAB32(ABP_Logon): PR_FAB_FILE not found\n");
}
/* copy the fab uid */
if (lpsPropVal[1].ulPropTag==PR_FAB_UID)
{
memcpy(&muidID,lpsPropVal[1].Value.bin.lpb, SIZEOF(MAPIUID));
}
else
{
DebugTrace("AWFXAB32(ABP_Logon): PR_FAB_UID not found\n");
fNeedMAPIUID = TRUE;
}
/* Discard GetProps() return data, if any. */
lpABP->lpFreeBuff (lpsPropVal);
/*
* (UI needed unless the file name is good and file exists.)
*
* in Fax, the AB is not exposed, so there is never a UI
* If you insist on using a fax AB, you can set the name in the registry
*/
fUINeeded = TRUE;
if (szFileName[0] != 0)
{
/* Verify the file exists. */
HANDLE hFile = CreateFile (
szFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
CloseHandle (hFile);
fUINeeded = FALSE;
}
}
// Am I allowed to bring up UI ?
if (ulFlags & AB_NO_DIALOG)
fUINeeded = FALSE;
// If the registry flag does not allow to expose the fax AB UI, don't allow it, no
// matter what happened earlier
if (!fExposeFaxAB)
fUINeeded = FALSE;
/*
* if the sab file name was not found in the profile or the sab file
* does not exist we have to get the user to pick another one and
* save back into the profile
*/
if (fUINeeded)
{
OPENFILENAME openfilename;
SPropValue sProp[1];
/*
* Can't bring up UI unless the client allows it
*/
if (ulFlags & AB_NO_DIALOG)
{
hResult = ResultFromScode (MAPI_E_LOGON_FAILED);
goto out;
}
/*
* Get the user to select a file
*/
openfilename.lStructSize = SIZEOF(OPENFILENAME);
openfilename.hwndOwner = (HWND) ulUIParam;
openfilename.hInstance = 0; /* Ignored */
openfilename.lpstrFilter = TEXT("Microsoft Fax Address Book files\0*.fab\0\0");
openfilename.lpstrCustomFilter = NULL;
openfilename.nMaxCustFilter = 0;
openfilename.nFilterIndex = 0;
openfilename.lpstrFile = szFileName;
openfilename.nMaxFile = MAX_PATH;
openfilename.lpstrFileTitle = NULL;
openfilename.nMaxFileTitle = 0;
openfilename.lpstrInitialDir = NULL;
openfilename.lpstrTitle = TEXT("Microsoft Fax Address Book");
openfilename.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
openfilename.nFileOffset = 0;
openfilename.nFileExtension = 0;
openfilename.lpstrDefExt = TEXT("fab");
openfilename.lCustData = 0;
openfilename.lpfnHook = NULL;
openfilename.lpTemplateName = NULL;
/*
* Call up the common dialog
*/
if (!GetOpenFileName (&openfilename))
{
#ifdef DEBUG
DWORD dwT;
dwT = CommDlgExtendedError();
#endif /* DEBUG */
// next two lines not needed for fax AB. an empty fax AB is valid.
// hResult = ResultFromScode (MAPI_E_LOGON_FAILED);
// goto out;
}
/*
* Set the fab file name property value
*/
sProp[0].ulPropTag = PR_FAB_FILE_A;
#ifdef UNICODE
WideCharToMultiByte( CP_ACP, 0, szFileName, -1, szAnsiFileName, ARRAYSIZE(szAnsiFileName), NULL, NULL );
sProp[0].Value.lpszA = szAnsiFileName;
#else
sProp[0].Value.lpszA = szFileName;
#endif
/*
* Save the fab file into the profile
*/
if (hResult = lpProfSect->lpVtbl->SetProps(lpProfSect, 1, sProp, NULL))
{
/*
* Do nothing... So I couldn't save it away this time...
*/
DebugTraceResult("ABP_Logon got unexpected result on SetProps\n", hResult);
hResult = hrSuccess;
}
} // if (fUINeeded)
/*
* if the uid was not found we have to generate a new muid for the
* PR_SAB_ID property and save it back into the profile
*/
if (fNeedMAPIUID)
{
SPropValue sProp[1];
/*
* Get a new fab uid
*/
hResult=lpMAPISup->lpVtbl->NewUID(lpMAPISup,&muidID);
if (HR_FAILED(hResult))
{
DebugTraceResult(NewUID, hResult);
goto out;
}
/*
* Set the fab uid property value
*/
sProp[1].ulPropTag = PR_FAB_UID;
sProp[1].Value.bin.cb = SIZEOF(MAPIUID);
sProp[1].Value.bin.lpb = (LPBYTE)&muidID;
/*
* Save the sab uid into the profile
*/
if (hResult = lpProfSect->lpVtbl->SetProps(lpProfSect, 1, sProp, NULL))
{
/*
* Do nothing... So I couldn't save it away this time...
*/
DebugTraceResult("ABP_Logon got unexpected result on SetProps\n", hResult);
hResult = hrSuccess;
}
} // if (fNeedMAPIUID)
/*
* Allocate space for keeping the file name in the ABLogon object
*/
if (scode = lpABP->lpAllocBuff((lstrlen(szFileName)+1)*SIZEOF(TCHAR), &lpstrT))
{
hResult = ResultFromScode (scode);
goto out;
}
lstrcpy (lpstrT, szFileName);
hResult = HrNewABLogon( &lpABLogon,
(LPABPROVIDER) lpABP,
lpMAPISup,
lpstrT,
&muidID,
lpABP->hLibrary,
lpABP->lpAllocBuff,
lpABP->lpAllocMore,
lpABP->lpFreeBuff,
lpABP->lpMalloc
);
if (HR_FAILED(hResult))
{
goto out;
}
/*
* Allocate space for another object list item
*/
if (scode = lpABP->lpAllocBuff( sizeof(OBJECTLIST), &lpObjectList))
{
hResult = ResultFromScode(scode);
goto out;
}
/*
* add logon object to list
*/
/* Get the Critical Section */
EnterCriticalSection(&lpABP->cs);
/* add logon object to begining of providers object list */
lpObjectList->lpObject = (LPVOID) lpABLogon;
lpObjectList->lppNext = lpABP->lpObjectList;
/* insert new logon object into the head of the providers object list */
lpABP->lpObjectList = lpObjectList;
/* leave critical section */
LeaveCriticalSection(&lpABP->cs);
/*
* Register my MAPIUID for this provider,
* but do not allow an error from setting the
* MAPIUID to cause failure to Logon.
*/
(void)lpMAPISup->lpVtbl->SetProviderUID(lpMAPISup,
(LPMAPIUID) &muidABMAWF, 0);
#ifdef DO_WE_REALLY_NEED_TAPI
/*
* TAPI
*
* everything seems OK. get TAPI initialized
*/
scode = ScLoadString( IDS_APP_NAME,
MAX_PATH,
lpABP->lpAllocBuff,
lpABP->hLibrary,
&lpszAppName
);
InitTAPI(lpABP->hLibrary, (HWND) ulUIParam, lpszAppName);
// Make sure we have the required location information handy
// bring up mini-dial helper if not
InitLocationParams((HWND) ulUIParam);
#endif
lpABP->lpFreeBuff(lpszAppName);
// return the object to the caller
*lppABPLogon = lpABLogon;
out:
if (lpProfSect)
lpProfSect->lpVtbl->Release(lpProfSect);
if (hResult)
{
lpABP->lpFreeBuff(lpstrT);
Assert(lpABLogon == NULL);
/* Verify we don't return warnings at this time. */
Assert(HR_FAILED(hResult));
}
DebugTraceResult(ABP_Logon, hResult);
return hResult;
}
/*************************************************************************
-
- RemoveLogonObject
-
* Removes a particular logon object from the list of logon objects
* that's kept track of in the IABProvider object
*/
void
RemoveLogonObject( LPABPROVIDER lpABProvider,
LPVOID lpvABLogon,
LPFREEBUFFER lpFreeBuff
)
{
LPOBJECTLIST *lppObjectList;
LPOBJECTLIST lpObjectListT;
LPABP lpABP = (LPABP) lpABProvider;
#if defined DEBUG
BOOL fFound = FALSE;
#endif
/* Get the Critical Section */
EnterCriticalSection(&lpABP->cs);
/*
* remove this logon object from the provider init objects list
* of logon objects
*/
lppObjectList = &(lpABP->lpObjectList);
while (*lppObjectList)
{
/* is this the logon object? */
if ((*lppObjectList)->lpObject == lpvABLogon)
{
/* save next list item */
lpObjectListT = (*lppObjectList)->lppNext;
/* free the object list item */
lpFreeBuff(*lppObjectList);
/* delete object from the list */
*lppObjectList = lpObjectListT;
#if defined DEBUG
fFound = TRUE;
#endif
break;
}
lppObjectList = &(*lppObjectList)->lppNext;
}
/* leave critical section */
LeaveCriticalSection(&lpABP->cs);
#if defined DEBUG
AssertSz(fFound, "Logon object not found on providers object list");
#endif
return;
}
/*************************************************************************
-
- FindLogonObject
-
* Finds a particular logon object by its muid.
*/
void
FindLogonObject( LPABPROVIDER lpABProvider,
LPMAPIUID lpMuidToFind,
LPABLOGON * lppABLogon
)
{
LPABP lpABP = (LPABP) lpABProvider;
LPABLOGON lpABLogonT = NULL;
LPOBJECTLIST lpObjectList = NULL;
LPMAPIUID lpMuidLogon = NULL;
Assert(!IsBadReadPtr(lpABP, SIZEOF(ABP)));
Assert(!IsBadReadPtr(lpMuidToFind, SIZEOF(MAPIUID)));
Assert(!IsBadReadPtr(lppABLogon, SIZEOF(LPABLOGON)));
/* Get the Critical Section */
EnterCriticalSection(&lpABP->cs);
*lppABLogon = NULL;
for (lpObjectList = lpABP->lpObjectList;
lpObjectList; lpObjectList = lpObjectList->lppNext)
{
lpABLogonT = (LPABLOGON) lpObjectList->lpObject;
lpMuidLogon = LpMuidFromLogon(lpABLogonT);
if (memcmp((LPVOID) lpMuidLogon, (LPVOID) lpMuidToFind, SIZEOF(MAPIUID)) == 0)
{
*lppABLogon = lpABLogonT;
break;
}
}
/* leave critical section */
LeaveCriticalSection(&lpABP->cs);
}
/*************************************************************************
*
- FABServiceEntry
-
* This funtion is used by MAPI to configure the Sample Address Book.
* It's a lot like ABP_Logon, except that it doesn't return a logon object
* and it can be passed in its configuration information (as defined in
* smpab.h) from MAPI so that no UI is required.
*
* lppMapiError a pointer to a MAPI error structure which allows
* the provider to return extended error info to MAPI
*/
STDAPI
FABServiceEntry(
HINSTANCE hInstance,
LPMALLOC lpMalloc,
LPMAPISUP lpMAPISup,
ULONG ulUIParam,
ULONG ulFlags,
ULONG ulContext,
ULONG cValues,
LPSPropValue lpProps,
LPPROVIDERADMIN lpAdminProviders,
LPMAPIERROR FAR *lppMapiError)
{
OPENFILENAME openfilename;
TCHAR szFileName[MAX_PATH];
HRESULT hResult=hrSuccess;
SPropValue sProp[cvallogonMax];
LPSPropValue lpsPropVal = NULL;
ULONG ulCount = 0;
LPALLOCATEBUFFER lpAllocBuff;
LPALLOCATEMORE lpAllocMore;
LPFREEBUFFER lpFreeBuff;
MAPIUID muid;
LPPROFSECT lpProf = NULL;
BOOL fFABFound=FALSE; // No fab file name yet
BOOL fUIDFound=FALSE; // No fab uid yet
BOOL fNeedMAPIUID = FALSE;
ULONG uliProp;
#ifdef UNICODE
CHAR szAnsiFileName[ MAX_PATH ];
#endif
#ifdef EXTENDED_DEBUG
TCHAR szTempBuf[256];
#endif
//DebugBreak();
DebugTrace("AWFXAB32(ServiceEntry): entering\n");
// Get registry settings
LoadIniParams();
#ifdef DEBUG
if (fDebugTrap)
DebugBreak();
#endif
/*
* Parameter validation
*/
// check the support object
if (IsBadReadPtr(lpMAPISup, SIZEOF(LPMAPISUP)))
{
DebugTraceSc(ServiceEntry, E_INVALIDARG);
return ResultFromScode(E_INVALIDARG);
}
if ( ulFlags & MAPI_UNICODE )
{
DebugTraceArg( ServiceEntry, "Bad character width" );
return ResultFromScode( MAPI_E_BAD_CHARWIDTH );
}
#ifdef EXTENDED_DEBUG
switch (ulContext) {
case MSG_SERVICE_DELETE:
MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_DELETE called!"), TEXT("awfxab debug message"), MB_OK);
break;
case MSG_SERVICE_INSTALL:
MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_INSTALL called!"), TEXT("awfxab debug message"), MB_OK);
break;
case MSG_SERVICE_UNINSTALL:
MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_UNINSTALL called!"), TEXT("awfxab debug message"), MB_OK);
break;
case MSG_SERVICE_CREATE:
MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_CREATE called!"), TEXT("awfxab debug message"), MB_OK);
break;
case MSG_SERVICE_CONFIGURE:
MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_CONFIGURE called!"), TEXT("awfxab debug message"), MB_OK);
break;
case MSG_SERVICE_PROVIDER_CREATE:
MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_PROVIDER_CREATE called!"), TEXT("awfxab debug message"), MB_OK);
break;
case MSG_SERVICE_PROVIDER_DELETE:
MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_PROVIDER_DELETE called!"), TEXT("awfxab debug message"), MB_OK);
break;
default:
MessageBox((HWND) ulUIParam, TEXT("ServiceEntry unknown called!"), TEXT("awfxab debug message"), MB_OK);
break;
}
#endif
/*
* Check what to do
*/
if ( ulContext==MSG_SERVICE_DELETE ||
ulContext==MSG_SERVICE_INSTALL ||
ulContext==MSG_SERVICE_UNINSTALL
)
{
return hrSuccess;
}
// Only supporting MSG_SERVICE_CONFIGURE and MSG_SERVICE_CREATE
if ( ulContext!=MSG_SERVICE_CONFIGURE &&
ulContext!=MSG_SERVICE_CREATE
)
{
DebugTrace("ServiceEntry unsupported context\n");
return ResultFromScode(MAPI_E_NO_SUPPORT);
}
/* Get the memory allocation routines we'll be needing. */
hResult = lpMAPISup->lpVtbl->GetMemAllocRoutines( lpMAPISup,
&lpAllocBuff,
&lpAllocMore,
&lpFreeBuff
);
if (hResult)
{
DebugTraceResult (MAPISUP::GetMemAllocRoutines, hResult);
goto out;
}
/* Open the profile section associated with our provider */
hResult = HrOpenSingleProvider(lpAdminProviders, &lpProf);
if (hResult)
{
DebugTrace ("AWFXAB32(ServiceEntry): Unable to open the profile.");
goto out;
}
#ifdef EXTENDED_DEBUG
wsprintf (szTempBuf, TEXT("ServiceEntry: HrOpenSingleProvider succeeded. hResult=0x%08lx\n"), (ULONG) hResult);
MessageBox( (HWND)ulUIParam,
szTempBuf,
TEXT("awfxab Debug Message"),
MB_ICONINFORMATION
);
#endif
// No file name for now
szFileName[0] = TEXT('\0');
/*
* Now looking for the two properties I need:
* PR_FAB_FILE
* PR_FAB_UID
*
* they can either be:
* 1. in the lpProps passed to ServiceEntry
* 2. in my profile section
* 3. be requested from the user through a UI
*/
// see if these properties exist on the profile
hResult = lpProf->lpVtbl->GetProps( lpProf,
(LPSPropTagArray)&tagaFABLogonProps,
ulFlags & MAPI_UNICODE,
&ulCount,
&lpsPropVal
);
// If the GetProps fail, I'm dump some debug messages, but it's OK to continue.
// Can still get the props from the ServiceEntry input parameter or from UI
if (hResult!=hrSuccess)
{
#ifdef DEBUG
/* The only expected return code is MAPI_E_NOT_FOUND. */
if (GetScode (hResult) != MAPI_W_ERRORS_RETURNED)
{
DebugTrace("AWFXAB32(ServiceEntry): got unexpected hResult: ");
DebugTraceResult(ProfileGetProps, hResult);
}
else if (lpsPropVal[0].Value.err != MAPI_E_NOT_FOUND)
{
DebugTrace("AWFXAB32(ServiceEntry): got unexpected scode: ");
DebugTraceSc(ProfileGetProps, lpsPropVal[0].Value.err);
}
#endif
/* Ignore errors/warnings from reading the property. */
hResult = hrSuccess;
// These two should be false anyway at this point
fFABFound = FALSE;
fUIDFound = FALSE;
}
/************************
*** PR_FAB_FILE ******
************************/
/*
* 1. Check the lpProps (cValues) passed to ServiceEntry
*/
// First, look for the fab file property in the config props that were passed to
// ServiceEntry. So I am not really looking at what I got in the above GetProps yet
for (uliProp=0; uliProp < cValues; uliProp++)
{
if (PROP_ID(lpProps[uliProp].ulPropTag)==PROP_ID(PR_FAB_FILE_A))
// This is the fab file property
break;
}
// If the fab file property was found (must be found, isn't it ?) and it has a
// non-error value, get the fab filename from it
if ((uliProp < cValues) && (PROP_TYPE(lpProps[uliProp].ulPropTag)!=PT_ERROR))
{
ULONG cch = lstrlenA(lpProps[uliProp].Value.lpszA);
if (cch >= MAX_PATH)
cch = MAX_PATH-1;
if (cch)
#ifdef UNICODE
MultiByteToWideChar( CP_ACP, 0, lpProps[uliProp].Value.lpszA, -1, szFileName, ARRAYSIZE(szFileName) );
#else
memcpy(szFileName, lpProps[uliProp].Value.LPSZ, (size_t)cch*SIZEOF(TCHAR));
#endif
szFileName[cch] = TEXT('\0');
// got my FAB file. Might be "". No need for UI for that
fFABFound = TRUE;
}
/*
* 2. Now the properties I got from the profile (if any)
*/
// no fab file name in the input properties. Look in the profile properties
else if ( (PROP_ID(lpsPropVal[0].ulPropTag) == PROP_ID(PR_FAB_FILE_A)) &&
(PROP_TYPE(lpsPropVal[0].ulPropTag)!= PT_ERROR)
)
{
ULONG cch = lstrlenA(lpsPropVal[0].Value.lpszA);
if (cch >= MAX_PATH)
cch = MAX_PATH-1;
if (cch)
#ifdef UNICODE
MultiByteToWideChar( CP_ACP, 0, lpProps[0].Value.lpszA, -1, szFileName, ARRAYSIZE(szFileName) );
#else
memcpy(szFileName, lpsPropVal[0].Value.LPSZ, (size_t)cch*SIZEOF(TCHAR));
#endif
szFileName[cch] = TEXT('\0');
fFABFound = TRUE;
}
else
{
fFABFound = FALSE;
}
/*
* 3. Last resort: UI
*/
if (fExposeFaxAB)
{
if (!fFABFound || (ulFlags & UI_SERVICE))
{
openfilename.lStructSize = SIZEOF(OPENFILENAME);
openfilename.hwndOwner = (HWND) ulUIParam;
openfilename.hInstance = 0; /* Ignored */
openfilename.lpstrFilter = TEXT("Microsoft Fax Address Book files\0*.fab\0\0");
openfilename.lpstrCustomFilter = NULL;
openfilename.nMaxCustFilter = 0;
openfilename.nFilterIndex = 0;
openfilename.lpstrFile = szFileName;
openfilename.nMaxFile = MAX_PATH;
openfilename.lpstrFileTitle = NULL;
openfilename.nMaxFileTitle = 0;
openfilename.lpstrInitialDir = NULL;
openfilename.lpstrTitle = TEXT("Pick a Microsoft Fax Address Book file");
openfilename.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_HIDEREADONLY;
openfilename.nFileOffset = 0;
openfilename.nFileExtension = 0;
openfilename.lpstrDefExt = TEXT("fab");
openfilename.lCustData = 0;
openfilename.lpfnHook = NULL;
openfilename.lpTemplateName = NULL;
// This hides the fax address book. define FAXAB_YES to expose it.
// No Fax address book, unless it's hardcoded into the profile
/*
* Call up the common dialog
*/
if (!GetOpenFileName (&openfilename))
{
// user pressed cancel
// CHECK: This means we do not have a fab file. Shouldn't I return
// some kind of an error ? The SAB doesn't.
goto out;
}
}
}
/*
* Set the file name property
*/
sProp[ivallogonPR_FAB_FILE].ulPropTag = PR_FAB_FILE_A;
#ifdef UNICODE
WideCharToMultiByte( CP_ACP, 0, szFileName, -1, szAnsiFileName, ARRAYSIZE(szAnsiFileName), NULL, NULL );
sProp[ivallogonPR_FAB_FILE].Value.lpszA = szAnsiFileName;
#else
sProp[ivallogonPR_FAB_FILE].Value.lpszA = szFileName;
#endif
/* if no properties were found then we're configuring for the
* first time and so we have to generate a new muid for the
* PR_FAB_ID property
*/
/************************
*** PR_FAB_UID ******
************************/
/*
* 1. Check the lpProps (cValues) passed to ServiceEntry
*/
for (uliProp=0; uliProp < cValues; uliProp++)
{
if (PROP_ID(lpProps[uliProp].ulPropTag)==PROP_ID(PR_FAB_UID))
break;
}
if ( (uliProp < cValues) && (PROP_TYPE(lpProps[uliProp].ulPropTag)!=PT_ERROR))
{
memcpy(&muid,lpProps[uliProp].Value.bin.lpb,SIZEOF(MAPIUID));
fUIDFound = TRUE;
}
/*
* 2. Now the properties I got from the profile (if any)
*/
else if ( (PROP_ID(lpsPropVal[1].ulPropTag) == PROP_ID(PR_FAB_UID)) &&
(PROP_TYPE(lpsPropVal[1].ulPropTag) != PT_ERROR)
)
{
memcpy(&muid,lpsPropVal[1].Value.bin.lpb,SIZEOF(MAPIUID));
fUIDFound = TRUE;
}
else
{
/* need to generate a uid */
fUIDFound = FALSE;
}
/* Discard GetProps() return data, if any. */
if (lpsPropVal)
lpFreeBuff (lpsPropVal);
/*
* 3. Last resort: generate a UID
*/
if (!fUIDFound)
{
hResult = lpMAPISup->lpVtbl->NewUID(lpMAPISup,&muid);
if (HR_FAILED(hResult))
{
/*
* Can't get a uid so just leave
*/
goto out;
}
}
/*
* Set the id property
*/
sProp[ivallogonPR_FAB_UID].ulPropTag = PR_FAB_UID;
sProp[ivallogonPR_FAB_UID].Value.bin.cb = SIZEOF(MAPIUID);
sProp[ivallogonPR_FAB_UID].Value.bin.lpb = (LPBYTE) &muid;
/*
* Save the file name and the id back into the profile
*/
hResult=lpProf->lpVtbl->SetProps( lpProf,
cvallogonMax,
sProp,
NULL
);
if (HR_FAILED(hResult))
{
/*
* Do nothing... So I couldn't save it away this time...
*/
DebugTrace("AWFXAB32(ServiceEntry): could not SetProps in profile\n");
hResult = hrSuccess;
}
out:
if (lpProf)
lpProf->lpVtbl->Release(lpProf);
DebugTraceResult(ServiceEntry, hResult);
return hResult;
}
/*************************************************************************
- HrOpenSingleProvider
-
* Opens the profile section associated with this provider.
*
* If the ServiceEntry() function exported from a provider had
* more than 1 section associated with it, this is where you'd get the chance
* to get all of them.
*/
static SizedSPropTagArray(1, tagaProviderTable) =
{
1,
{
PR_PROVIDER_UID
}
};
HRESULT
HrOpenSingleProvider( LPPROVIDERADMIN lpAdminProviders,
LPPROFSECT FAR * lppProfSect
)
{
HRESULT hResult;
LPMAPITABLE lpTable = NULL;
LPSRowSet lpRows = NULL;
LPSPropValue lpProp;
hResult = lpAdminProviders->lpVtbl->GetProviderTable( lpAdminProviders,
0,
&lpTable
);
if (HR_FAILED(hResult))
goto out;
hResult = lpTable->lpVtbl->SetColumns(lpTable, (LPSPropTagArray) &tagaProviderTable, 0);
if (HR_FAILED(hResult))
goto out;
hResult = lpTable->lpVtbl->QueryRows(lpTable, 1, 0, &lpRows);
if (HR_FAILED(hResult))
goto out;
if (lpRows->cRows == 0)
{
hResult = ResultFromScode(MAPI_E_NOT_FOUND);
goto out;
}
lpProp = lpRows->aRow[0].lpProps;
hResult = lpAdminProviders->lpVtbl->OpenProfileSection(
lpAdminProviders,
(LPMAPIUID) lpProp->Value.bin.lpb,
NULL,
MAPI_MODIFY,
lppProfSect);
out:
FreeProws(lpRows);
if (lpTable)
lpTable->lpVtbl->Release(lpTable);
DebugTraceResult(HrOpenSingleProvider, hResult);
return hResult;
}
/*
- ScLoadString
-
* Loads a string from a resource. It will optionally allocate the string if
* a allocation function is passed in. Otherwise it assumes that the *lppsz
* is already allocated.
*/
SCODE ScLoadString( UINT ids,
ULONG ulcch,
LPALLOCATEBUFFER lpAllocBuff,
HINSTANCE hLibrary,
LPTSTR * lppsz
)
{
SCODE sc = S_OK;
int iRet;
/*
* Assert parameters
*/
Assert((lpAllocBuff ? !IsBadCodePtr((FARPROC) lpAllocBuff):TRUE));
Assert(ids!=0);
if (lpAllocBuff)
{
sc = lpAllocBuff(ulcch*SIZEOF(TCHAR), lppsz);
if (FAILED(sc))
{
goto out;
}
}
#ifdef DEBUG
else
{
Assert(!IsBadWritePtr(*lppsz, (UINT) ulcch*SIZEOF(TCHAR)));
}
#endif /* DEBUG */
iRet = LoadString( hLibrary,
ids,
*lppsz,
(UINT)ulcch
);
if (!iRet)
{
DebugTrace("AWFXAB32(ScLoadString): LoadString() failed...\n");
sc = E_FAIL;
goto out;
}
out:
DebugTraceSc(ScLoadString, sc);
return sc;
}
/*************************************************************************
*
- LoadIniParams
-
* Loads any paramters I need from the registry
*
*/
void LoadIniParams(void)
{
//fExposeFaxAB = TRUE;
#if 0
fExposeFaxAB = GetInitializerInt( HKEY_CURRENT_USER,
TEXT("Address Book Provider"),
TEXT("ExposeFaxAB"),
FALSE,
TEXT("Software\\Microsoft\\At Work Fax")
);
fDebugTrap = GetInitializerInt( HKEY_CURRENT_USER,
TEXT("Address Book Provider"),
TEXT("DebugTrap"),
FALSE,
TEXT("Software\\Microsoft\\At Work Fax")
);
#endif
}
#undef _FAXAB_ABP