Using Windows Mobile State and Notification Broker

Download [download id=”5″]

Windows Mobile State and Notification Broker is a mechanism which provides storing system and application information in registry and send notifications whenever these values changes. An application registers for a particular event and the State and Notification Broker notifies the client application whenever the event occurs. For example an application wants to get notified when the Windows Media Player start playing a media or when the cellular signal level changes.

The State and Notification Broker mechanism works by monitoring any registry key and whenever the key changes send notification to all the registered clients. The Windows Mobile system provides many notifications. The header file SNAPI.H provides the definitions of the registry keys, its path and bitmask for all the notifications the system provides. The general categories of notifications are:

    System state information
    Message information
    Tasks and appointment information
    Windows Media Player information
    Phone information
    Connection information

Besides these notifications, an application can create its own notification. In this case the application is a provider which provides state notifications. To do this the application creates a registry key and changes this key whenever the state is changes. The State and Notification Broker will notify all the client applications that registered for this event.

A client application does the following steps to get notified about an event:

    A client Register for the notification using RegistryNotifyApp, RegistryNotifyWindow, RegistryNotifyCallback or RegistryNotifyMsgQueue API.
    When the notification arrives, the client application reads the specified registry key to get the necessary information
    When the client application no longer needs the notification, close the notification using RegistryCloseNotification.

A provider application does these steps to provide notification of the state change:

    A provider application creates a registry key and stores the state information
    When a change occurs, the provider application changes this information
    The State and Notification Broker notifies all the clients when the change occurs

The State and Notification Broker supports the following notification types:

Transient: In this, the notifications are only valid when the application is running. The request is closed when the application exits or the device is reset.

Persistent: In persistent type, the notification is remains valid even after the application exits or the device is reset.

There are four modes of notifications in State and Notification Broker, they are;

Application Activation: In this mode, the State and Notification Broker starts the application if it is not running already. This mode applies to the persistent notification type.

Window Message: In this mode, the State and Notification Broker sends the specified window message to the application window. This mode applies to the transient notification type.

Message Queue: In this mode, the Broker sends the message to the specified Message Queue. This mode applies to the transient notification type.

Callback Function: In this mode, the Broker calls the specified callback function when the state change occurs. This mode applies to the transient notification type.

Besides these the State and Notification Broker also support Conditional Notification and Batch Notification. In Conditional Notification, an application can specify to send notification only when the state property is changed to a particular value. This way an application can reduce the number of notification sends to the application. In this the system checks the state property value and send the notification only if the property value matches the specified value.

In Batch Notification, an application can tell the system how frequently the notification has to send. Here you can specify maximum idle time before sending the notification. Whenever the change occurs, the system waits the specified idle time before sending the notification. If the value changes during this time, the system resets the idle time and waits another idle time. But this may leads to infinite wait, to prevent this you can specify maximum wait time. The system either waits for the maximum wait time or waits for the value to get settled.

As I stated before there are many notifications provides by the system by default. For a detailed explanation either refer to the SNAPI.H header file or follow this link:

In Native Mode, the header file REGEXT.H contains the function to register and close the notifications. In Managed Mode, it is exposed via the Microsoft.WindowsMobile.Status namespace (Microsoft.WindowsMobile.Status.dll assembly).

In Native Mode, an application uses any of the following function to register for the notification.

HRESULT WINAPI RegistryNotifyApp(HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValueName, LPCTSTR pszName, LPCTSTR pszApp, LPCTSTR pszClass, LPCTSTR pszWindow, UINT msg, DWORD dwFlags, NOTIFICATIONCONDITION* pCondition);

HRESULT WINAPI RegistryNotifyWindow(  HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValueName, HWND hWnd, UINT msg, DWORD dwUserData, NOTIFICATIONCONDITION* pCondition, HREGNOTIFY* phNotify);

HRESULT WINAPI RegistryNotifyWindow(HKEY hKey,LPCTSTR pszSubKey, LPCTSTR pszValueName, HWND hWnd, UINT msg, DWORD dwUserData, NOTIFICATIONCONDITION* pCondition, HREGNOTIFY* phNotify);

HRESULT WINAPI RegistryNotifyMsgQueue(HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValueName, LPCTSTR pszMsgQueue, DWORD dwUserData, NOTIFICATIONCONDITION* pCondition, HREGNOTIFY* phNotify);

The RegistryNotifyApp API is used to register for persistent notification mode. The parameters are:

hKey Handle to the opened key or the root key
pszSubKey Name of the sub key, this can be null
pszValueName Name of the value in which state is stored
pszName A unique user defined string that represents the
notification. Note that it should be unique, you can try something like ApplicationName.
pszApp Complete path of the executable to be start when the event occurs
pszClass Class name of the window that receives the notification message,this can be NULL
pszWindow Name of the window that receives the notification message, this can be NULL
msg Message to be send to the window. If both pszClass and pszWindow are null, the system will just start the application and will not send the
dwFlags Notification flags, this should be 0 or RNAF_NONAMEONCMDLINE. If 0 then system will send the pszName as a command
pCondition A pointer to the NOTIFICATIONCONDITION structure. Using
this structure you can specify the conditions to be checked before sending
the notification. See Conditional Notification

The first three parameters are common for all the APIs. The other parameters change according the API.

When the notification receives, client the application can use RegistryGetString or RegistryGetDWORD to read values from the key. Whenever the application finished using the notification, application should close the notification by using the API RegistryCloseNotification or RegistryStopNotification.

To create a notification provider, an application has to create a registry key and change the value of the registry key whenever the state is changed. The system will notify all the client applications about the change.

There are two samples provided, one is uses transient mode and other uses persistent mode. These are very simple ones to get started with the State and Notification Broker mechanism. Hope this will help you to get started.

Getting Signal Strength using TAPI and RIL

Download [download id=”2″]
Download [download id=”3″]

In Windows Mobile, we can retrieve signal strength in two ways, one using TAPI and other using RIL. The TAPI function lineGetLineDevStatus is used to retrieve the signal strength of the current line. This function returns the details in LINEDEVSTATUS variable length structure. The dwSignalLevel member contains the signal strength in the range 0x00000000 to 0x0000FFFF.

The other method is to use the RIL function RIL_GetSignalQuality. This functon returns the signal strength in RILSIGNALQUALITY structure. The member nSignalStrength contains the signal strength. This link explains how to calculate the signal strength from the RILSIGNALQUALITY structure members.

Programmatically start touch screen calibration

The following link explains the Touch Screen Driver functions. Since we cannot directly call these function using Windows Mobile SDK, we have to load the CoreDll.dll file and call these function dynamically. The following code snippet start the Touch Screen calibration programmatically.

typedef BOOL (WINAPI* pfnTouchCalibrate)(void)
int _tmain(int argc, _TCHAR* argv[])
	HMODULE hCoreDLL = LoadLibrary(_T("coredll.dll"));
	pfnTouchCalibrate pTouchCalibrate = (pfnTouchCalibrate)GetProcAddress(hCoreDLL, _T("TouchCalibrate"));
	if (pTouchCalibrate)

Reading IMSI, TMSI, ICCID, MNC, MCC and LAC using SimReadRecord API

Download the source code

While searching I found this useful link explaining how to retrieve ICC-ID using Sim Manager APIs. I extended this sample to read IMSI, TMSI, MNC, MCC and LAC. The SimReadRecord API is used to read the records stored in the SIM. The second parameter specifies the address to read and the sixth parameter specifies the size of the data to read. To get more details of the SIM records refer to the GSM 11.11 specification. Below are some of the record address and its length:

ICCID address 0x2FE2, length 10 bytes
IMSI address 0x6F07, length 10 bytes
TMSI, MCC, MNC, LAC address 0x6F7E, length 11 bytes

Programatically forwarding calls using TAPI

Download the source code

Recently one of my friend asked me how to forward calls using the USSD commands. This link describes how to forward calls using USSD codes. I tried a lot using my previous article code but ended up with no success. The USSD command are sending successfully but always the result is “UNKNOWN APPLICATION”. Then I decided to work on a sample using the TAPI API lineForward.

The lineForward API is used to programatically forward calls. The syntax of the API is defined as:

LONG WINAPI lineForward(HLINE hLine,DWORD bAllAddresses,
        DWORD dwAddressID,LPLINEFORWARDLIST const lpForwardList,
        DWORD dwNumRingsNoAnswer,LPHCALL lphConsultCall,LPLINECALLPARAMS const lpCallParams);

The first parameter is the handle to the line (Cellular Line), second a boolean value indicating all originating addresses of the line or a single address of the line. Third is the address id of the line. Fourth is a pointer to variably sized structure that describes the forwarding instructions. Fifth is number of rings that has to be considered as no answer. Sixth is a pointer to handle to a call which will be filled with handle to a consultation call (only used in some telephony environments). Seventh is pointer to LINECALLPARAMS, if NULL specified default call parameter will be used.

Following steps are needed to forward calls:

1. Initialize TAPI
2. Open the Cellular Line
3. Allocate and initialize the LINEFORWARDLIST variable sized structure
4. Call lineForward API

Allocating and initializing the LINEFORWARDLIST structure is little bit complex. This is a pointer to a variable sized structure and is defined as:

typedef struct lineforwardlist_tag {
  DWORD dwTotalSize;
  DWORD dwNumEntries;
  LINEFORWARD ForwardList[1];

The dwTotalSize member is the total size of the structure, dwNumEntries member is the number of ForwardList array. The LINEFORWARD structure is defined as:

typedef struct lineforward_tag {  
DWORD dwForwardMode;  
DWORD dwCallerAddressSize;  
DWORD dwCallerAddressOffset;  
DWORD dwDestCountryCode;  
DWORD dwDestAddressSize;  
DWORD dwDestAddressOffset;  
DWORD dwCallerAddressType;  
DWORD dwDestAddressType;

The dwDestAddressOffset specifies the offset of the destination address from the starting of the structure. The dwDestAddressSize specifies the size of the destination address in bytes. Same in the case of dwCallerAddressOffset and dwCallerAddressSize and specifies the caller address and size. To allocate memory for the forward list, first we have to find out the total number of bytes needed. This will be:

sizeof(LINEFORWARDLIST) + (sizeof(LINEFORWARD) * number of entries - 1) + size of all phone numbers

After allocating the memory we need to initialize the members of the structure and append the phone numbers. The API lineForward returns a positive integer if successful otherwise a negative value indicating the error. To get the current status of the call forward, lineGetAddressStatus API is used. This returns the result in a variable sized array. The sample application presented here retrieves the call forward status and display it is dialog. Users can change the settings and upon exit the application sets new call forward information. Hope this gives you an introduction on how to programatically forward calls.