Monitoring Connection State Changes Using an Offline State Add-in

Monitoring Connection State Changes Using an Offline State Add-in

Before you can use an offline state add-in to monitor connection state changes, you must implement functions to set up and initialize the add-in. For more information, see Setting Up an Offline State Add-in.

After you set up the offline state add-in, you must use the HrOpenOfflineObj function to obtain an offline object. Using this offline object, you can initialize your state monitor, and then get and set the current state.

In this topic, these state monitoring functions are demonstrated by using code examples from the Sample Offline State Add-in. The Sample Offline State Add-in is a COM add-in that adds an Offline State menu to Outlook and utilizes the Offline State API. Through the Offline State menu, you can enable or disable state monitoring, check the current state, and change the current state. For more information about downloading and installing the Sample Offline State Add-in, see Installing the Sample Offline State Add-in. For more information about the Offline State API, see About the Offline State API.

When the offline state add-in is disconnected, you must implement functions to properly terminate and clean up the add-in. For more information, see Disconnecting an Offline State Add-in.

Open Offline Object Routine

For the client to be notified when a connection state change occurs, you must call the HrOpenOfflineObj function. This function opens an offline object that supports IMAPIOfflineMgr. The HrOpenOfflineObj function is defined in the ConnectionState.h header file.

Note

The HrOpenOfflineObj function is declared in the ImportProcs.h header file as follows: extern HROPENOFFLINEOBJ* pfnHrOpenOfflineObj;.

HrOpenOfflineObj Example

  typedef HRESULT (STDMETHODCALLTYPE HROPENOFFLINEOBJ)(
    ULONG ulFlags,			
    LPCWSTR pwszProfileName,	
    const GUID* pGUID,				
    const GUID* pInstance,			
    IMAPIOfflineMgr** ppOffline
);

Initialize Monitor Routine

The InitMonitor function calls the HrOpenOfflineObj function. The InitMonitor function calls CMyOfflineNotify so that Outlook can send callback notifications to the client, and registers the callback through the MAPIOFFLINE_ADVISEINFO variable AdviseInfo.

InitMonitor() Example

  void InitMonitor(LPCWSTR szProfile)
{
    if (!szProfile) return;
    Log(true,_T("Initializing Outlook Offline State Monitor\n"));
    HRESULT hRes = S_OK;
if (g_lpOfflineMgr)
{
    Log(true,_T("Already initialized\n"));
    return;
}

if (pfnHrOpenOfflineObj)
{
    if (g_lpOfflineMgr) DeInitMonitor();
    Log(true,_T("Calling HrOpenOfflineObj for \"%ws\"\n"),szProfile);
    hRes = pfnHrOpenOfflineObj(
        NULL,
        szProfile,
        &GUID_GlobalState,
        NULL,
        &g_lpOfflineMgr);
    if (FAILED(hRes)) 
    {
        Log(true,_T("HrOpenOfflineObj failed: 0x%08X\n"),hRes);
    }
    if (g_lpOfflineMgr)
    {
        IMAPIOffline* lpOffline = NULL;
        hRes = g_lpOfflineMgr->QueryInterface(IID_IMAPIOffline,(LPVOID*)&lpOffline);
        
        if (lpOffline)
        {
            ULONG ulCap = NULL;
            hRes = lpOffline->GetCapabilities(&ulCap);
            
            if (ulCap & MAPIOFFLINE_CAPABILITY_OFFLINE) Log(true,_T("MAPIOFFLINE_CAPABILITY_OFFLINE supported\n"));
            if (ulCap & MAPIOFFLINE_CAPABILITY_ONLINE) Log(true,_T("MAPIOFFLINE_CAPABILITY_ONLINE supported\n"));
            
            if (ulCap & (MAPIOFFLINE_CAPABILITY_OFFLINE | MAPIOFFLINE_CAPABILITY_ONLINE))
            {
                CMyOfflineNotify* lpImplNotify = new CMyOfflineNotify();
                
                if (lpImplNotify)
                {
                    MAPIOFFLINE_ADVISEINFO AdviseInfo = {0};
                    AdviseInfo.ulSize = sizeof(MAPIOFFLINE_ADVISEINFO);
                    AdviseInfo.ulClientToken = 0;// something you want to get handed back when you get the notification
                    AdviseInfo.CallbackType = MAPIOFFLINE_CALLBACK_TYPE_NOTIFY;
                    AdviseInfo.pCallback = lpImplNotify;
                    AdviseInfo.ulAdviseTypes = MAPIOFFLINE_ADVISE_TYPE_STATECHANGE;
                    AdviseInfo.ulStateMask = MAPIOFFLINE_STATE_ALL;
                    
                    hRes = g_lpOfflineMgr->Advise(MAPIOFFLINE_ADVISE_DEFAULT, &AdviseInfo, &g_ulAdviseToken);
                    Log(true,"ulAdviseToken = 0x%08X\n",g_ulAdviseToken);
                }
            }
            lpOffline->Release();
        }                
    }
}

}

Get Current State Routine

The GetCurrentState function calls the HrOpenOfflineObj function, and then uses the offline object to get the current connection state. The current state is returned in the ulCurState variable, which is used in the CButtonEventHandler::Click function to display the current state to the user.

GetCurrentState() Example

  ULONG (LPCWSTR szProfile)
{
    if (!szProfile) return 0;
    Log(true,_T("Getting Current Offline State\n"));
    HRESULT hRes = S_OK;
    ULONG ulCurState = NULL;
if (pfnHrOpenOfflineObj)
{
    if (g_lpOfflineMgr) DeInitMonitor();
    Log(true,_T("Calling HrOpenOfflineObj for \"%ws\"\n"),szProfile);
    hRes = pfnHrOpenOfflineObj(
        NULL,
        szProfile,
        &GUID_GlobalState,
        NULL,
        &g_lpOfflineMgr);
    if (FAILED(hRes)) 
    {
        Log(true,_T("HrOpenOfflineObj failed: 0x%08X\n"),hRes);
    }
    if (g_lpOfflineMgr)
    {
        IMAPIOffline* lpOffline = NULL;
        hRes = g_lpOfflineMgr->QueryInterface(IID_IMAPIOffline,(LPVOID*)&lpOffline);
        
        if (lpOffline)
        {
            hRes = lpOffline->GetCurrentState(&ulCurState);
            Log(true,_T("GetCurrentState returned 0x%08X\n"),hRes);

            switch(ulCurState)
            {
            case MAPIOFFLINE_STATE_ONLINE:
                Log(true,_T("Current state is MAPIOFFLINE_STATE_ONLINE\n"));
                break;
            case MAPIOFFLINE_STATE_OFFLINE:
                Log(true,_T("Current state is MAPIOFFLINE_STATE_OFFLINE\n"));
                break;
            default:
                Log(true,_T("Current state is 0x%0X\n"),ulCurState);
            }
            lpOffline->Release();
        }
    }
}
return ulCurState;

}

Set Current State Routine

The SetCurrentState function calls the HrOpenOfflineObj function, and then uses the offline object to set the current connection state. The CButtonEventHandler::Click function calls the SetCurrentState function and the new state is passed in through the ulState variable.

SetCurrentState() Example

  HRESULT SetCurrentState(LPCWSTR szProfile, ULONG ulFlags, ULONG ulState)
{
    if (!szProfile) return 0;
    Log(true,_T("Setting Current Offline State\n"));
    HRESULT hRes = S_OK;
if (pfnHrOpenOfflineObj)
{
    if (g_lpOfflineMgr) DeInitMonitor();
    Log(true,_T("Calling HrOpenOfflineObj for \"%ws\"\n"),szProfile);
    hRes = pfnHrOpenOfflineObj(
        NULL,
        szProfile,
        &GUID_GlobalState,
        NULL,
        &g_lpOfflineMgr);
    if (FAILED(hRes)) 
    {
        Log(true,_T("HrOpenOfflineObj failed: 0x%08X\n"),hRes);
    }
    if (g_lpOfflineMgr)
    {
        IMAPIOffline* lpOffline = NULL;
        hRes = g_lpOfflineMgr->QueryInterface(IID_IMAPIOffline,(LPVOID*)&lpOffline);
        
        if (lpOffline)
        {
            switch(ulFlags)
            {
            case MAPIOFFLINE_FLAG_BLOCK:
                Log(true,_T("Flag used: MAPIOFFLINE_FLAG_BLOCK\n"));
                break;
            case MAPIOFFLINE_FLAG_DEFAULT:
                Log(true,_T("Flag used: MAPIOFFLINE_FLAG_DEFAULT\n"));
                break;
            default:
                Log(true,_T("Flag used: 0x%0X\n"),ulFlags);
            }
            switch(ulState)
            {
            case MAPIOFFLINE_STATE_ONLINE:
                Log(true,_T("New state will be MAPIOFFLINE_STATE_ONLINE\n"));
                break;
            case MAPIOFFLINE_STATE_OFFLINE:
                Log(true,_T("New state will be MAPIOFFLINE_STATE_OFFLINE\n"));
                break;
            default:
                Log(true,_T("New state will be 0x%0X\n"),ulState);
            }
            hRes = lpOffline->SetCurrentState(ulFlags, MAPIOFFLINE_STATE_OFFLINE_MASK,ulState,NULL);
            Log(true,_T("SetCurrentState returned 0x%08X\n"),hRes);
            
            lpOffline->Release();
        }
    }
}
return hRes;

}

Notification Routine

The IMAPIOfflineNotify::Notify function is used by Outlook to send notifications to a client when there are changes in the connection state.

CMyOfflineNotify::Notify() Example

  void CMyOfflineNotify::Notify(const MAPIOFFLINE_NOTIFY *pNotifyInfo)
{
    Log(true,_T("CMyOfflineNotify::Notify\n"));
    if    (pNotifyInfo == NULL)
    {    
        Log(true,_T("pNotifyInfo is NULL\n"));
    }
    else
    {
        Log(true,_T("pNotifyInfo->ulSize == 0x%0X\n"),pNotifyInfo->ulSize);
        switch(pNotifyInfo->NotifyType)
        {
            case    MAPIOFFLINE_NOTIFY_TYPE_STATECHANGE:
                Log(true,_T("pNotifyInfo->NotifyType == MAPIOFFLINE_NOTIFY_TYPE_STATECHANGE\n"));
                break;
            case    MAPIOFFLINE_NOTIFY_TYPE_STATECHANGE_START:
                Log(true,_T("pNotifyInfo->NotifyType == MAPIOFFLINE_NOTIFY_TYPE_STATECHANGE_START\n"));
                break;
            case    MAPIOFFLINE_NOTIFY_TYPE_STATECHANGE_DONE:
                Log(true,_T("pNotifyInfo->NotifyType == MAPIOFFLINE_NOTIFY_TYPE_STATECHANGE_DONE\n"));
                break;
            default:
                Log(true,_T("pNotifyInfo->NotifyType == 0x%08X\n"),pNotifyInfo->NotifyType);
        }
        Log(true,_T("pNotifyInfo->ulClientToken == 0x%0X\n"),pNotifyInfo->ulClientToken);
        switch(pNotifyInfo->Info.StateChange.ulMask)
        {
            case    MAPIOFFLINE_STATE_OFFLINE_MASK:
                Log(true,_T("pNotifyInfo->Info.StateChange.ulMask == MAPIOFFLINE_STATE_OFFLINE_MASK\n"));
                break;
            default:
                Log(true,_T("pNotifyInfo->Info.StateChange.ulMask == 0x%0X\n"),pNotifyInfo->Info.StateChange.ulMask);
        }
        switch(pNotifyInfo->Info.StateChange.ulStateOld)
        {
            case    MAPIOFFLINE_STATE_ONLINE:
                Log(true,_T("pNotifyInfo->Info.StateChange.ulStateOld == MAPIOFFLINE_STATE_ONLINE\n"));
                break;
            case    MAPIOFFLINE_STATE_OFFLINE:
                Log(true,_T("pNotifyInfo->Info.StateChange.ulStateOld == MAPIOFFLINE_STATE_OFFLINE\n"));
                break;
            default:
                Log(true,_T("pNotifyInfo->Info.StateChange.ulStateOld == 0x%0X\n"),pNotifyInfo->Info.StateChange.ulStateOld);
        }
        switch(pNotifyInfo->Info.StateChange.ulStateNew)
        {
            case    MAPIOFFLINE_STATE_ONLINE:
                Log(true,_T("pNotifyInfo->Info.StateChange.ulStateNew == MAPIOFFLINE_STATE_ONLINE\n"));
                break;
            case    MAPIOFFLINE_STATE_OFFLINE:
                Log(true,_T("pNotifyInfo->Info.StateChange.ulStateNew == MAPIOFFLINE_STATE_OFFLINE\n"));
                break;
            default:
                Log(true,_T("pNotifyInfo->Info.StateChange.ulStateNew == 0x%0X\n"),pNotifyInfo->Info.StateChange.ulStateNew);
        }
    }
    return;
}

See Also

About the Offline State API

About the Sample Offline State Add-in

Installing the Sample Offline State Add-in

Setting Up an Offline State Add-in

Disconnecting an Offline State Add-in