MSPINIT.C

/* 
* M S P I N I T . C
*
* Initialize the MAPI Sample Message Store Provider.
*
* Copyright 1992-1995 Microsoft Corporation. All Rights Reserved.
*/

#include "msp.h"

CHAR szFolderTemplate[] = "*.fld";
CHAR szMessageTemplate[] = "*.msg";
CHAR szPropertyFileName[] = "folder.prp";
CHAR szHierarchyFileName[] = "hierarch.tbl";
CHAR szContentsFileName[] = "contents.tbl";
CHAR szOutgoingFileName[] = "outgoing.tbl";

#define MSP_CheckParameters(pobj, intf, method, arglist) \
OBJ_CheckParameters(pobj, intf, method, sizeof(MSP), &vtblMSP, arglist)

MSP_Vtbl vtblMSP =
{
(MSP_QueryInterface_METHOD *) OBJ_QueryInterface,
(MSP_AddRef_METHOD *) OBJ_AddRef,
MSP_Release,
MSP_Shutdown,
MSP_Logon,
MSP_SpoolerLogon,
MSP_CompareStoreIDs
};

/*
* Exported functions
*/

/*
* MSProviderInit
*
* Purpose:
* Message Store Provider initialization and version handshake
* with MAPI. Called once for each MAPI Session that uses this
* store provider DLL on this process. Passes back an init
* object (LPMSPROVIDER) used for further access to this provider.
*
* Arguments:
* ulFlags Reserved for future use. Ignored.
* ulMAPIVersion Version of Message Store SPI used by MAPI.
* lpulMDBVersion [out] Version of SPI supported by the provider.
* ppmsp [out] MS Provider object for further access.
*
* Returns:
* HRESULT
*
* Side effects:
* None.
*
* Errors:
* MAPI_E_VERSION Require a higher version of MAPI
* MAPI_E_NOT_ENOUGH_MEMORY Insufficient memory
* Any errors from ScInitMSInstance()
*/
STDINITMETHODIMP
MSProviderInit(HINSTANCE hInstance, LPMALLOC pmalloc,
LPALLOCATEBUFFER pfnAllocBuf, LPALLOCATEMORE pfnAllocMore,
LPFREEBUFFER pfnFreeBuf, ULONG ulFlags, ULONG ulMAPIVersion,
ULONG * pulMDBVersion, LPMSPROVIDER * ppmsp)
{
SCODE sc = S_OK;
PMSP pmsp = NULL;

AssertSz(pmalloc, "Bad pmalloc");
AssertSz(pfnAllocBuf, "Bad pfnAllocBuf");
AssertSz(pfnAllocMore, "Bad pfnAllocMore");
AssertSz(pfnFreeBuf, "Bad pfnFreeBuf");
NFAssertSz(!ulFlags, "Unknown flags, bug in MAPI DLL");
AssertSz(pulMDBVersion, "Bad pulMDBVersion");
AssertSz(ppmsp, "Bad ppmsp");

/* This provider requires MAPI to be at least the version
* of the SPI defined at the time this provider was compiled.
*/
if (ulMAPIVersion < CURRENT_SPI_VERSION)
{
sc = MAPI_E_VERSION;
goto exit;
}

/* Initialize the per-instance global data */
sc = ScInitMSInstance(pmalloc);
if (sc != S_OK)
goto exit;

/* Allocate and initialize the MSPROVIDER object. */
sc = ScAllocZ(sizeof(MSP), (PPV) &pmsp);
if (sc != S_OK)
{
DeinitMSInstance();
goto exit;
}

OBJ_Initialize(pmsp, &vtblMSP, OT_MSPROVIDER, 0, &pmsp->cs);

pmsp->hInst = hInstance;
pmsp->lmr.lpAllocBuf = pfnAllocBuf;
pmsp->lmr.lpAllocMore = pfnAllocMore;
pmsp->lmr.lpFreeBuf = pfnFreeBuf;

InitializeCriticalSection(&pmsp->cs);

/* Pass back [out] parameters. */
*pulMDBVersion = CURRENT_SPI_VERSION;
*ppmsp = (LPMSPROVIDER) pmsp;

exit:
DebugTraceSc(MSProviderInit, sc);
return ResultFromScode(ScCheckSc(sc, IMSProvider_Init));
}

/*
- MSP_Release
-
*/

STDMETHODIMP_(ULONG) MSP_Release(PMSP pmsp)
{
LONG cRef;

MSP_EnterCriticalSection(pmsp);

cRef = --pmsp->cRef;

AssertSz2(cRef >= 0, "MSP_Release(pmsp=%08lX): Bogus cRef (%08lX)",
pmsp, cRef);

AssertSz(cRef > 0 || pmsp->pobjHead == NULL, "There are still valid logons");

MSP_LeaveCriticalSection(pmsp);

if (cRef == 0)
{
DeleteCriticalSection(&pmsp->cs);
FreeNull(pmsp);
DeinitMSInstance();
}

return (cRef);
}

/*
* MSP_Shutdown
*
* Purpose:
* Allow MAPI to specify flags related to the Release().
*
* Arguments:
* pulFlags Reserved for future use. Ignored.
*
* Returns:
* HRESULT
*
* Side effects:
* None.
*
* Errors:
* None.
*/
STDMETHODIMP
MSP_Shutdown(PMSP pmsp, ULONG * pulFlags)
{
MSP_CheckParameters(
pmsp,
IMSProvider,
Shutdown,
(pmsp,
pulFlags));

MSP_EnterCriticalSection(pmsp);

/* MAPI says it will never call Release with valid logons, */
/* let's make sure. */

AssertSz(pmsp->pobjHead == NULL, "There are still valid logons");

#ifdef DEBUG
pmsp->fInvalid = TRUE;
#endif

MSP_LeaveCriticalSection(pmsp);

return 0;
}

/*
* MSP_CompareStoreIDs
*
* Purpose:
* Compare the EntryIDs of two message stores.
*
* Arguments:
* pmsp MSPROVIDER object returned by MSProviderInit.
* lcbEntryID1 Size of first EntryID.
* lpEntryID1 First EntryID to compare.
* lcbEntryID2 Size of second EntryID.
* lpEntryID2 Second EntryID to compare.
* ulFlags Flags. Reserved for future use.
* pulResult Address in which to place the result of
* the comparison (TRUE or FALSE).
*
* Returns:
* HRESULT
*
* Side effects:
* None.
*
* Errors:
* None.
*/
STDMETHODIMP
MSP_CompareStoreIDs(PMSP pmsp, ULONG lcbEntryID1, LPENTRYID lpEntryID1,
ULONG lcbEntryID2, LPENTRYID lpEntryID2, ULONG ulFlags,
ULONG *pulResult)
{
PEID peid1 = (PEID) lpEntryID1;
PEID peid2 = (PEID) lpEntryID2;

MSP_CheckParameters(
pmsp,
IMSProvider,
CompareStoreIDs,
(pmsp,
lcbEntryID1,
lpEntryID1,
lcbEntryID2,
lpEntryID2,
ulFlags,
pulResult));

AssertSz(!pmsp->fInvalid,
"This MSProvider has already been shutdown");

/* The Sample Store's method of deriving and comparing */
/* store EntryIDs has the quirky behavior that if any */
/* OTHER store's EntryIDs are binary-comparable, this */
/* function will return a successful match, without ever */
/* knowing that the EntryIDs were not Sample Store */
/* EntryIDs. A subsequent logon would, of course, fail. */

/* Case-insensitive string compare on part, binary on rest. */
if ( lcbEntryID1 >= offsetof(EID, szPath) + sizeof(TCHAR)
&& lcbEntryID1 == lcbEntryID2
&& memcmp(peid1, peid2, offsetof(EID, szPath)) == 0
&& peid1->bVersion == SMPMS_VERSION
&& lstrcmpi(peid1->szPath, peid2->szPath) == 0)
{
*pulResult = TRUE;
}
else
{
*pulResult = FALSE;
}

return hrSuccess;
}