MSMQ on Windows Mobile: Troubleshooting Guide

I've handled in the past many requests about installation and configuration issues around MSMQ on Windows Mobile, therefore here it is the "status of the art" of my personal troubleshooting guide...

Above all, check if you’re installing the right CAB. MSMQ for WM5 is different from the one contained in the WM2003 SDK, and it’s not contained in the WM5 SDK. It’s now part of the Redistributable Server Components for Windows Mobile 5.0.

Then, you need to either (a) install the SdkCerts.cab on the test device or (b) sign the msmq.arm.cab with a certificate you know is installed on the device. For SOME smartphones (depending on OEM’s choice about security), contrarily to Pocket PCs, you might have to sign internal executables (EXE, DLL) as well, for example through the utility cabsigntool.exe. This is required on Windows Mobile 5.0- and 6-based devices since MSMQ needs to start as a priviledged service, therefore it must be signed with a certificate stored in the Priviledge Certificate Store, due to the Security-related features of the OS. For testing purposes only, you can use the SDK Test Certificates (SdkCerts.cab), considering that the MSMQ’s CAB coming with the download above (msmq.arm.CAB) is actually signed with that certificate: then, if you’ll need to sign the CAB with another certificate, you can simply add a new certificate to the chain of the CAB, because Windows Mobile will look only at the last certificate signing a file.

In any case if you're running in troubles with MSMQ installation\configuration I usually suggest starting with the SDK certificates just to understand if the problem you’re experiencing is related to security (see “note about security” below).

The steps for correctly installing MSMQ on WM5 include a soft-reset. On some devices, it happened that because of a problem of the OEM’s customized WM5-based image, modifications to the registry were not persisted during a soft-reset. A temporary solution for this (waiting for the next ROM Upgrade from OEMs) was to invoke the RegFlushKey() API from an application:

 RegFlushKey(0x80000002) //“0x80000002" simply means HKEY_LOCAL_MACHINE

Sincerely it's about time that I don't encounter a device that doesn't flush registry modifications when soft-resetting... and in any case before doing this you could simply use a Registry viewer to see if after a soft-reset the modifications are persisted on your specific device.

Finally, as you may know an application that needs to use MSMQ has to activate this service before calling it, through the call

 ActivateDevice(@"Drivers\BuiltIn\MSMQD", 0);

– this has been documented since WM2003 days through this blog from the NETCF Dev Team, which explained how to develop NETCF applications using MSMQ (at that point in time only WM2003 was available, so it was using the CAB for WM2003).

Keep in mind that you may need to change AllowCmdLine registry to 1 as described by Services.exe Registry Settings.

If you’re interested on using MSMQ within a NETCF application, you can use the same code sample of the blog as a template for MSMQ on WM5, paying attention on modifying the constant strings. Or, you could consider the suggestions above and modify the following code, provided “AS IS”:

 

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace MSMQ_patch
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                long reg = RegFlushKey(0x80000002);
                if (reg == 0)
                    MessageBox.Show("Registry saved");
                else
                    MessageBox.Show("Error: " + System.Runtime.InteropServices.Marshal.GetLastWin32Error().ToString());
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error: " + ex.Message);
            }
        }
        private void button2_Click(object sender, EventArgs e)
        {
            try
            {
                IntPtr handle = ActivateDevice(MSMQ_DRIVER_REG, 0);
                if (handle != null)
                {
                    MessageBox.Show("Activated");
                    CloseHandle(handle);
                }
                else
                    MessageBox.Show("Error: " + System.Runtime.InteropServices.Marshal.GetLastWin32Error().ToString());
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error: " + ex.Message);
            }
        }
        [System.Runtime.InteropServices.DllImport("CoreDll.dll", EntryPoint = "RegFlushKey", SetLastError = true)]
        private static extern uint RegFlushKey(uint hKey);
        private const String MSMQ_DRIVER_REG = @"Drivers\BuiltIn\MSMQD";
        [System.Runtime.InteropServices.DllImport("CoreDll.dll", SetLastError = true)]
        private static extern IntPtr ActivateDevice(string lpszDevKey, Int32 dwClientInfo);
        [System.Runtime.InteropServices.DllImport("CoreDll.dll", SetLastError = true)]
        private extern static Int32 CloseHandle(IntPtr hProcess);
    }
}

After checking that registry is flushed correctly after a soft-reset, you might also convert the application into a Console Application that invokes ActivateDevice() and then launch visadm.exe – I’m talking about something similar to:

 static void Main(string[] args)
{
    try
    {
        IntPtr handle = ActivateDevice(MSMQ_DRIVER_REG, 0);
        //if (handle != null)
        //{
        //    MessageBox.Show("Activated");
        //    CloseHandle(handle);
        //    return;
        //}
        //else
        //{
        //    MessageBox.Show("Error: " +
        //        System.Runtime.InteropServices.Marshal.GetLastWin32Error().ToString());
        //}
        
        Process.Start(@"\Windows\visadm.exe","");
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error: " + ex.Message);
    }
}
    
private const String MSMQ_DRIVER_REG = @"Drivers\BuiltIn\MSMQD";
[System.Runtime.InteropServices.DllImport("CoreDll.dll", SetLastError = true)]
private static extern IntPtr ActivateDevice(string lpszDevKey, Int32 dwClientInfo);
[System.Runtime.InteropServices.DllImport("CoreDll.dll", SetLastError = true)]
private extern static Int32 CloseHandle(IntPtr hProcess);

You can also use that application as it is, purely to perform the following TEST:

(0. hard-reset the test device)

1. install SdkCerts.cab on the device

2. install msmq.arm.cab on the device

3. run \Windows\visadm.exe

4. tap on Shortcuts, then “Install” and finally “Register”

5. launch the app above and click on button1 (to invoke RegFlushKey)

6. soft-reset the device

7. launch again the app above and now click on button2 (to invoke ActivateDevice)

8. run \Windows\visadm.exe

9. tap on Shortcuts, then “Verify”: it should that MSMQ and NETREG daemons are installed

10. now tap on Shortcuts, then “Status”: it should return “DISCONNECTED”, which is the expected result at this point

NOTE ABOUT SECURITY:

The download “Windows Mobile 5.0 Server Components” is meant to be used by ISV Application Developers and therefore during the developing\testing phase of the application it simply needs the SDK Certificates on the test target devices. However, when deploying the application, since the SDK Certificates cannot be “redistributed” along with an application, an ISV Developer needs to sign the CAB *AND* its binaries inside (for example by using cabsigntool.exe) with a certificate that he\she knows will be registered in the Priviledge Certificate Store (this is for the binaries) and the SPC Store (this is for the CAB) of the target device. This is because the MSMQ service is registered during system boot. This heavily depends on the Security Configuration chosen by the device’s OEM.

You can use your own certificate, however you must be sure that the target device allows you to install that new certificate you’ll use (OEMs can also choose if end-users can install new certificates). Usually, ISV Developers ask to device OEMs or Mobile Operator which certificates they can use to sign their application: this is valid for the MSMQ cab and its binaries inside as well. As an ISV Application Developer, possibly you already own a Mobile2Market certificate you use to sign your applications: you might use the same M2M certificate for the MSMQ CAB and its files. Some other info about how ISV Application Developers should approach to Windows Mobile 5.0 Security are available at Windows Mobile 5.0 Application Security .