Monitoring Connection State Changes Using an Offline State Add-in
Applies to: Office 2010 | Outlook 2010 | Visual Studio
In this article
Open Offline Object Routine
HrOpenOfflineObj Example
Initialize Monitor Routine
InitMonitor() Example
Get Current State Routine
GetCurrentState() Example
Set Current State Routine
SetCurrentState() Example
Notification Routine
CMyOfflineNotify::Notify() Example
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
Concepts
Installing the Sample Offline State Add-in
About the Sample Offline State Add-in