XPPROV.CPP
/////////////////////////////////////////////////////////////////////////////// 
// 
//  File Name  
//      XPPROV.CPP 
// 
//  Description 
//      This file implements the IXPProvider interface with the methods  
//      specified in the MAPI SPI 1.0 specifications. Also some helper 
//      functions are implemented in this file. 
// 
//  Author 
//      Irving De la Cruz 
// 
//  Revision: 1.7 
// 
// Written for Microsoft Windows Developer Support 
// Copyright (c) 1995-1996 Microsoft Corporation. All rights reserved. 
// 
#define INITGUID 
#define USES_IID_IXPProvider 
#define USES_IID_IXPLogon 
#define USES_IID_IMAPIStatus 
#define USES_IID_IMAPIProp 
#define USES_IID_IMAPIPropData 
#define USES_IID_IMAPIControl 
#define USES_IID_IMAPIContainer 
#define USES_IID_IMAPIFolder 
#define USES_IID_IMAPITableData 
 
#include "XPWDSR.H" 
 
// Remark this line to turn verbose tracing OFF 
#define DO_INFO_TRACES 
#ifdef DO_INFO_TRACES 
#define InfoTrace(a)   TraceInfoMessage(a) 
#else 
#define InfoTrace(a)    
#endif // DO_INFO_TRACES 
 
/////////////////////////////////////////////////////////////////////////////// 
//    CXPProvider::CXPProvider() 
// 
//    Parameters 
//      hInst                   Handle to instance of this XP DLL 
// 
//    Purpose 
//      Constructor of the object. Parameters are passed to initialize the 
//      data members with the appropiate values. 
// 
//    Return Value 
//      None 
// 
CXPProvider::CXPProvider (HINSTANCE hInst) 
{ 
    InfoTrace ("CXPProvider: Constructor called"); 
    m_hInstance    = hInst; 
    m_cRef         = 1; 
    // Initialize critical sections for this transport 
    InitializeCriticalSection (&m_csTransport); 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    CXPProvider::~CXPProvider() 
// 
//    Parameters 
//      None 
// 
//    Purpose 
//      Close down and release resources and libraries 
// 
//    Return Value 
//      None 
// 
CXPProvider::~CXPProvider() 
{ 
    InfoTrace ("CXPProvider: Destructor called"); 
    m_hInstance = NULL; 
 
    // This is the last method called on a transport, close down the traces 
    UnInitTraces(); 
    DeleteCriticalSection (&m_csTransport); 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    CXPProvider::QueryInterface() 
// 
//    Parameters 
//      { Refer to OLE Documentation on this method } 
// 
//    Purpose 
//      Returns a pointer to a interface requested if the interface is  
//      supported and implemented by this object. If it is not supported, it  
//      returns NULL 
// 
//    Return Value 
//      An HRESULT 
// 
STDMETHODIMP CXPProvider::QueryInterface (REFIID riid, LPVOID * ppvObj) 
{ 
    // OLE requires NULLing parameter 
    *ppvObj = NULL; 
    // If this is one of the two IID return an interface pointer to it 
    if (riid == IID_IXPProvider || riid == IID_IUnknown) 
    { 
        *ppvObj = (LPVOID)this; 
        // Increase usage count of this object 
        AddRef(); 
        return S_OK; 
    } 
    // This object does not support the interface requested 
    return E_NOINTERFACE; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
// IXPProvider virtual member functions implementation 
// 
 
/////////////////////////////////////////////////////////////////////////////// 
//    CXPProvider::Shutdown() 
// 
//    Parameters 
//      { Refer to MAPI Documentation on this method } 
// 
//    Purpose 
//      Stub method. 
// 
//    Return Value 
//      An HRESULT 
// 
STDMETHODIMP CXPProvider::Shutdown (ULONG * pulFlags) 
{ 
    InfoTrace ("CXPProvider::Shutdown method called"); 
    CheckParameters_IXPProvider_Shutdown (this, pulFlags); 
    return S_OK; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    CXPProvider::TransportLogon() 
// 
//    Parameters 
//      { Refer to MAPI Documentation on this method } 
// 
//    Purpose 
//      Display the logon dialog to show the options saved in the profile for 
//      this provider and allow changes to it. Save new configuration settings 
//      back in the profile. 
//      Create a new CXPLogon object and return it to the spooler. Also,  
//      initialize the properties array for each address type handled 
//      by this transport. Check all the flags and return them to the spooler 
// 
//    Return Value 
//      An HRESULT 
// 
STDMETHODIMP CXPProvider::TransportLogon (LPMAPISUP     pSupObj, 
                                          ULONG         ulUIParam, 
                                          LPTSTR        pszProfileName, 
                                          ULONG *       pulFlags, 
                                          LPMAPIERROR * ppMAPIError, 
                                          LPXPLOGON *   ppXPLogon) 
{ 
    InfoTrace ("CXPProvider::TransportLogon method called"); 
    CheckParameters_IXPProvider_TransportLogon (this, 
                                                pSupObj, 
                                                ulUIParam, 
                                                pszProfileName, 
                                                pulFlags, 
                                                ppMAPIError, 
                                                ppXPLogon); 
    CXPLogon * pXPLogon = NULL; 
    ULONG ulPropCount; 
    LPSPropValue pProps = NULL; 
    MAILBOX_INFO UserMBInfo = { 0 }; 
    CFGDLG CfgDialog = { 0 }; 
    LPPROFSECT pProfileObj; 
    HRESULT hResult = OpenServiceProfileSection (pSupObj, &pProfileObj, gpfnFreeBuffer); 
    if (hResult) 
    { 
        TraceResult ("CXPProvider::TransportLogon: Failed to open the service profile section", hResult); 
        return hResult; 
    } 
 
    HANDLE hUIMutex = CreateMutex (NULL, FALSE, CONFIG_UI_MUTEX); 
    if (NULL == hUIMutex) 
    { 
        HRESULT hResult = HRESULT_FROM_WIN32 (GetLastError()); 
        TraceResult ("CXPProvider::TransportLogon: Failed to create UI mutext", hResult); 
    } 
     
    hResult = pProfileObj->GetProps ((LPSPropTagArray)&sptLogonProps, 
                                     fMapiUnicode, 
                                     &ulPropCount, 
                                     &pProps); 
    if (FAILED(hResult)) 
    { 
        TraceResult ("CXPProvider::TransportLogon: Failed to get the logon props", hResult); 
        goto ErrorExit; 
    } 
 
    // Fill in the logon UI structure 
    CfgDialog.hInst    = m_hInstance; 
    CfgDialog.hWnd     = (HWND)ulUIParam; 
    CfgDialog.ppProps  = &pProps; 
    CfgDialog.pSupObj  = pSupObj; 
    CfgDialog.hUIMutex = hUIMutex; 
 
    // In case we get MAPI_W_ERRORS_RETURNED, ignore it and reset  
    // to S_OK. Now display the logon configuration dialog 
    if (MAPI_W_ERRORS_RETURNED == hResult) 
    { 
        if (PR_SMP_MAILBOX_ID       != pProps[MAILBOX_ID].ulPropTag  || 
            PR_SMP_CONNECTION_TYPE  != pProps[NET_CON].ulPropTag     || 
            PR_SMP_UPLOAD_TIME      != pProps[UPLOAD_TIME].ulPropTag || 
            PR_SMP_HEADERS_FILENAME != pProps[HEADER_FILE].ulPropTag || 
            PR_SMP_GET_HEADERS      != pProps[GET_HEADERS].ulPropTag) 
        { 
            TraceMessage ("CXPProvider::TransportLogon: Where are the provider properties?"); 
            hResult = MAPI_E_UNCONFIGURED; 
            if (!(LOGON_NO_DIALOG & *pulFlags)) 
            { 
                PrivInitialize3DCtl (m_hInstance); 
                PrivateMessageBox (IDS_MSG_SERVICE_NOT_PROPERLY_CFG, (HWND)ulUIParam); 
                PrivUninitialize3DCtl (m_hInstance); 
            } 
            goto ErrorExit; 
        } 
 
        if (PR_SMP_REMOTE_SERVER != pProps[SERVER_NAME].ulPropTag || 
            PR_SMP_MAILBOX_NAME != pProps[MAILBOX_NAME].ulPropTag || 
            PR_SMP_USER_NAME != pProps[USER_NAME].ulPropTag || 
            PR_SMP_MAILBOX_PASSWORD != pProps[PASSWORD].ulPropTag) 
        { 
            if (LOGON_NO_DIALOG & *pulFlags) 
            { 
                TraceMessage ("CXPProvider::TransportLogon: UI not allowed but it is needed"); 
                hResult = MAPI_E_UNCONFIGURED; 
                goto ErrorExit; 
            } 
            PrivInitialize3DCtl (m_hInstance); 
ReStartLogonDlg : 
            if ((hResult = DoLogonDlg (&CfgDialog))) 
            { 
                goto ErrorExit; 
            } 
            hResult = pProfileObj->SetProps (4, pProps, NULL); 
            if (hResult) 
            { 
                TraceResult ("CXPProvider::TransportLogon: Failed to set the properties", hResult); 
                goto ErrorExit; 
            } 
        } 
    } 
    // Connect to the server with the stored information. If necessary (and allowed) display UI. 
    hResult = DoServerLogon (&UserMBInfo, 
                             pProps, 
                             pProfileObj, 
                             !(LOGON_NO_DIALOG & *pulFlags), 
                             (HWND)ulUIParam, 
                             FALSE, 
                             0, 
                             NULL, 
                             TRUE); 
    if (S_FALSE == hResult) 
    { 
        goto ReStartLogonDlg; 
    } 
    if (hResult) 
    { 
        goto ErrorExit; 
    } 
 
    // Once we have validated the remote credentials, terminate all connections 
    TerminateRemoteConnections(); 
 
    try 
    { 
        // Allocate the IXPLogon-derived object. Initialize its data members with the necessary values 
        pXPLogon = new CXPLogon (m_hInstance, 
                                 pSupObj, 
                                 pProps[HEADER_FILE].Value.LPSZ, 
                                 pProps[GET_HEADERS].Value.b, 
                                 &UserMBInfo, 
                                 pProps[MAILBOX_ID].Value.l, 
                                 pProps[SERVER_NAME].Value.LPSZ, 
                                 hUIMutex); 
        if (!pXPLogon) 
        { 
            // New failed, propably due to memory shortage 
            TraceMessage ("CXPProvider::TransportLogon: Failed to allocate new CXPLogon object"); 
            hResult = E_OUTOFMEMORY; 
        } 
    } 
    catch (CException & Exception) 
    { 
        hResult = Exception.GetError(); 
    } 
    if (hResult) 
    { 
        goto ErrorExit; 
    } 
    hUIMutex = NULL; 
 
    pXPLogon->CheckForUnfinishedDownloads(); 
 
    // Lock other threads because we are going to work on data that is  
    // global to all threads (sessions) using this transport 
    EnterCriticalSection (&m_csTransport); 
    // Check the mode in which MAPI is logging into our transport and set 
    // the appropiate internal (this CXPLogon object) transport session flags 
    pXPLogon->InitializeTransportStatusFlags (*pulFlags); 
    // Initialize the transport ID prop array for this session 
    hResult = pXPLogon->SetIdentityProps(); 
    if (!hResult) 
    { 
        // Build the transport status row for this session 
        hResult = pXPLogon->InitializeStatusRow(); 
        if (!hResult) 
        { 
            // Set the session flags returned to MAPI by the transport 
            pXPLogon->SetSessionFlags (pulFlags); 
            // Set the upload delivery time to the current day, mo, yr and the hour and 
            // minute from the config dialog saved in the profile. The profile info 
            // is only valid for the hour and minute of day, the date can be old 
            pXPLogon->SetUploadTime (pProps[UPLOAD_TIME].Value.ft); 
            // Copy our allocated object back to the returned MAPI object pointer 
            *ppXPLogon = (LPXPLOGON)pXPLogon; 
        } 
    } 
    // Release the critical section 
    LeaveCriticalSection (&m_csTransport); 
 
 
ErrorExit: 
    // Release pProfileObj. This object was AddRef() by MAPI before it  
    // came to us. The transport is in charge of cleaning it up (Release()ing it). 
    if (pProfileObj) 
    { 
        pProfileObj->Release(); 
    } 
    PrivUninitialize3DCtl (m_hInstance); 
 
    if (hUIMutex) 
    { 
        CloseHandle (hUIMutex); 
    } 
    gpfnFreeBuffer (pProps); 
    if (hResult) 
    {    
        // Something failed, so clean the session if it has been allocated. 
        // The Release() method of CXPLogon does the memory deallocation  
        // of this object. The destructor of CXPLogon does the rest of  
        // the clean up 
        if (pXPLogon) 
        { 
            pXPLogon->Release(); 
        } 
    } 
    return hResult; 
}                                         
 
// End of File for XPPROV.CPP