Initializing a Transport Provider

Initializing a Transport Provider

To implement a transport provider, you must initialize the transport provider by using the XPProviderInit function as an entry point. Once the transport provider's DLL is initialized, the IXPProvider::TransportLogon function allows MAPI to log on to the transport provider.

In this topic, these functions are demonstrated by using code examples from the MRXP Sample Transport Provider. The MRXP Sample Transport Provider implements a shared network file system transport provider by using a UNC share or a local folder. For more information about downloading and installing the MRXP Sample Transport Provider, see Installing the Sample Transport Provider.

After you have initialized a transport provider, the next step is to set up the types of addresses the transport provider will accept and notify MAPI that the transport provider is ready for processing. For more information, see Setting Up a Transport Provider.

Initialization Routine

All transport providers must implement XPProviderInit as an entry point to initialize the provider's DLL. XPProviderInit checks to see if the version number of the service provider interface, ulMAPIVer, is compatible with the current version number, CURRENT_SPI_VERSION. The function creates a new instance of the CXPProvider class and returns it in the lppXPProvider parameter.

XPProviderInit() Example

  STDINITMETHODIMP XPProviderInit(
    HINSTANCE hInstance,
    LPMALLOC /*lpMalloc*/,
    LPALLOCATEBUFFER lpAllocateBuffer,
    LPALLOCATEMORE lpAllocateMore,
    LPFREEBUFFER lpFreeBuffer,
    ULONG /*ulFlags*/,
    ULONG ulMAPIVer,
    ULONG FAR * lpulProviderVer,
    LPXPPROVIDER FAR * lppXPProvider)
    
{
    Log(true, _T("XPProviderInit function called\n"));
if (!hInstance || !lpAllocateBuffer || !lpAllocateMore || !lpFreeBuffer 
    || !lpulProviderVer || !lppXPProvider)
    return MAPI_E_INVALID_PARAMETER;

if (ulMAPIVer < CURRENT_SPI_VERSION)
{
    Log(true, _T("XPProviderInit: Invalid version passed in ulMAPIVer: %d\n"), 
        ulMAPIVer);
    return MAPI_E_VERSION;
}

CXPProvider* pProvider =NULL;
pProvider = new CXPProvider(hInstance);
if (!pProvider)
{
    Log(true, _T("XPProviderInit: failed to create new CXPProvider\n"));
    return MAPI_E_NOT_ENOUGH_MEMORY;
}

*lpulProviderVer = CURRENT_SPI_VERSION;
*lppXPProvider = (LPXPPROVIDER)pProvider;

return S_OK;

}

Logon Routine

The last step in initializing the transport provider is to call IXPProvider::TransportLogon so that MAPI can log on to the transport provider. The function calls the OpenProfileSection method to get the profile properties for the user. Then the TransportLogon function evaluates the input flags from the lpulFlags parameter to set the status for the logon session, and sets the appropriate output flags. The new logon object is returned in the lppXPLogon parameter.

CXPProvider::TransportLogon Example()

  STDMETHODIMP CXPProvider::TransportLogon(
    LPMAPISUP			lpMAPISup,
    ULONG /*ulUIParam*/,
    LPTSTR /*lpszProfileName*/,
    ULONG FAR* lpulFlags,
    LPMAPIERROR FAR* /*lppMAPIError*/,
    LPXPLOGON FAR* lppXPLogon)
{
    Log(true, _T("CXPProvider::TransportLogon function called\n"));
if (!lpMAPISup || !lppXPLogon)
    return MAPI_E_INVALID_PARAMETER;

*lppXPLogon = NULL;
HRESULT hRes = S_OK;
LPALLOCATEBUFFER lpAllocBuffer = NULL;
LPALLOCATEMORE lpAllocMore = NULL;
LPFREEBUFFER lpFreeBuffer = NULL;

// Get the MAPI memory routines
hRes = lpMAPISup->
    GetMemAllocRoutines(&lpAllocBuffer, &lpAllocMore, &lpFreeBuffer);
if (SUCCEEDED(hRes) && lpAllocBuffer && lpAllocMore && lpFreeBuffer)
{
    // Get the profile properties
    LPPROFSECT lpProfSect = NULL;
    hRes = lpMAPISup->OpenProfileSection(NULL, MAPI_MODIFY, &lpProfSect);

    if (SUCCEEDED(hRes) && lpProfSect)
    {
        ULONG ulProfProps = 0;
        LPSPropValue pProfProps = NULL;
        hRes = lpProfSect->GetProps((LPSPropTagArray)&sptClientProps, 0,
            &ulProfProps, &pProfProps);
        if (SUCCEEDED(hRes) && ulProfProps && pProfProps)
        {
            // Validate the properties
            hRes = ValidateConfigProps(ulProfProps, pProfProps);
            if (SUCCEEDED(hRes))
            {
                CXPLogon* pXPLogon = NULL;
                pXPLogon = new CXPLogon(this, lpMAPISup, lpAllocBuffer, lpAllocMore, 
                    lpFreeBuffer, ulProfProps, pProfProps, *lpulFlags);
                if (!pXPLogon)
                {
                    Log(true, _T("CXPProvider::TransportLogon: Failed to create new "
                        + "CXPLogon\n"));
                    lpFreeBuffer(pProfProps);
                    hRes = MAPI_E_NOT_ENOUGH_MEMORY;
                }
                if(SUCCEEDED(hRes))
                {
                    if (*lpulFlags & LOGON_NO_CONNECT)
                    {
                        pXPLogon->AddStatusBits(STATUS_OFFLINE);
                    }
                    else
                    {
                        if (!(*lpulFlags & LOGON_NO_INBOUND))
                            pXPLogon->AddStatusBits(STATUS_INBOUND_ENABLED);
                        if (!(*lpulFlags & LOGON_NO_OUTBOUND))
                            pXPLogon->AddStatusBits(STATUS_OUTBOUND_ENABLED);
                    }
                    hRes = lpMAPISup->RegisterPreprocessor(NULL, 
                        (LPTSTR)MRXP_ADDRTYPE_A, (LPTSTR)MRXP_FULLDLLNAME_A,
                        "PreprocessMessage", "RemovePreprocessInfo", 0);
                    if (SUCCEEDED(hRes))
                    {
                        EnterCriticalSection(&m_csObj);
                        hRes = pXPLogon->CreateStatusRow();
                        if (SUCCEEDED(hRes))
                        {
                            pXPLogon->SetNextLogon(m_pLogonList);
                            m_pLogonList = pXPLogon;
                            *lppXPLogon = (LPXPLOGON)pXPLogon;
                            if (*lpulFlags & LOGON_NO_CONNECT)
                            {
                                *lpulFlags = 0;
                            }
                            else
                            {
                                *lpulFlags = LOGON_SP_IDLE | LOGON_SP_RESOLVE | 
                                     LOGON_SP_POLL;
                            }
                        }
                        else
                        {
                            Log(true, _T("CXPProvider::TransportLogon: CreateStatusRow "
                                + "returned an error: 0x%08X\n"), hRes);
                            delete pXPLogon;
                        }
                        LeaveCriticalSection(&m_csObj);
                    }
                    else
                    {
                        Log(true, _T("CXPProvider::TransportLogon: RegisterPreprocessor "
                            + "returned an error: 0x%08X\n"), hRes);
                        delete pXPLogon;
                    }
                }
            }
            else
            {
                Log(true, _T("CXPProvider::TransportLogon: ValidateConfigProps "
                    + "returned an error: 0x%08X\n"), hRes);
            }
        }
        else
        {
            Log(true, _T("CXPProvider::TransportLogon: GetProps on lpProfSect "
                + "returned an error: 0x%08X\n"), hRes);
        }
    }
    else
    {
        Log(true, _T("CXPProvider::TransportLogon: OpenProfileSection "
            + "returned an error: 0x%08X\n"), hRes);
    }

    if (lpProfSect)
        lpProfSect->Release();
}
else
{
    Log(true, _T("CXPProvider::TransportLogon: GetMemAllocRoutines "
        + "returned an error: 0x%08X\n"), hRes);
}	

return hRes;

}

See Also

About the Sample Transport Provider

Installing the Sample Transport Provider

Setting Up a Transport Provider

Sending Messages by Using a Transport Provider

Receiving Messages by Using a Transport Provider

Shutting Down a Transport Provider