Going Places

Provisioning Mobile Devices

Mike Calligaro

Contents

Why Provision?
Configuration Service Providers
Getting Your XML to the Device
Who Wants to Type XML?
All Provisioned and Ready to Go

Welcome to Going Places—a new column devoted to mobile device development. The main focus will be on Windows Mobile® phones and Tablet PCs, although any topic related to mobility is fair game.

My name is Mike Calligaro, and I've been a developer at Microsoft for 14 years. Aside from a two week stint in the Windows® desktop group, I've spent my entire career in what is now the Windows Mobile division. I've worked on a wide range of products, including an early version of interactive TV, the Sega Dreamcast, and the Windows CE operating system. I've spent the past eight years working on various parts of Windows Mobile.

Today I'm going to talk about programmatically configuring Windows Mobile devices (or "provisioning" to people who like to use fancy words). If you're an IT manager or support technician, and are manually configuring Windows Mobile devices for your users, stop. This article is for you. If you're a mobile app developer and wish you had an easy way to add your Web page to the browser's favorites, this will help you too.

Putting on a polyester suit for a moment, what if I told you that, with a few lines of code and some XML, you can set up a VPN, set the device's date and time, configure an e-mail account, add a file to the device, set a ring tone, change a registry key, and much, much more? Now how much would you pay? A million dollars? Two million dollars? Well, in this special MSDN® Magazine offer, we're making these capabilities available to you for the low, low price of free. That's right, free. So call now while I throw this digital fish into a blender.

Hopefully I'm a better developer than I am a salesman. In all seriousness, the provisioning APIs are part of the standard Windows Mobile SDK, which is a free download available from the Windows Mobile Developer Center at msdn.microsoft.com/windowsmobile.

Why Provision?

Although the name Windows Mobile came later, Microsoft released its first platform for cellular phones in 2002. Getting into the phone space meant implementing a lot of things that mobile operators wanted but weren't accustomed to doing, such as the ability to configure devices remotely. Now, there wasn't a whole lot to configure on the typical 2002-era phone, but we needed to support that basic level of configuration to be competitive. Once we had the infrastructure in place, we found it convenient to do a lot of remote configuration.

For instance, due to the requirements of my job, I end up using a number of different phones and many different OS versions. During the more unstable times in the development lifecycle, I've occasionally had to set up various phones multiple times a day. And even when things are running smoothly, it's not uncommon for me to configure at least one phone a week. So rather than manually type in my Exchange Server address and set my ring tone, I put together an XML blob that does most of my setup. I keep the XML file and a little program to process it on a storage card. That way I'm always ready when someone hands me a new phone to try.

I'm sure that being able to set Penny Arcade as a browser favorite was never a mobile operator requirement, but I'm glad that we used the "I have a hammer, so everything looks like a nail" mentality in this case.

To work this configuration magic, all you need is a single API (DMProcessConfigXML) and some XML. For example, say you want to set Live Search as a browser favorite. Start with the following XML:

// WAP provisioning XML to add a new browser favorite.
LPCWSTR g_wszFavoriteXml = 
    L"<wap-provisioningdoc> "
    L"   <characteristic type=\"BrowserFavorite\"> "
    L"      <characteristic type=\"Live Search\"> "
    L"         <parm name=\"URL\" value=\"https://m.live.com/\"/> "
    L"      </characteristic> "
    L"   </characteristic>"
    L"</wap-provisioningdoc>";

Given that, here's all the code you need in order to set the favorite using the XML:

HRESULT AddFavorite() {
   HRESULT hr         = E_FAIL;
   LPWSTR wszOutput   = NULL;
   
   // Process the XML.
   hr = DMProcessConfigXML(g_wszFavoriteXml, 
     CFGFLAG_PROCESS, &amp;wszOutput);
 
   // The caller must delete the XML returned from DMProcessConfigXML.
   delete [] wszOutput;
   return hr;
 }

I'm simplifying things a bit here for the sake of space. In your own code you should do security and error checking. And you're more likely to be reading XML from a file rather than having it compiled into your code. But, in a nutshell, this is what you need to do.

There's also a managed wrapper for DMProcessConfigXML. In C#, you can use ConfigurationManager.ProcessConfiguration instead. Here's the same code in C#:

XmlDocument configDoc = new XmlDocument();
configDoc.LoadXml(
    "<wap-provisioningdoc>"+
    "<characteristic type=\"BrowserFavorite\">"+
    "<characteristic type=\"Live Search\">"+
    "<parm name=\"URL\" value=\"https://m.live.com/\"/>"+
    "</characteristic>"+
    "</characteristic>"+
    "</wap-provisioningdoc>"
    );
ConfigurationManager.ProcessConfiguration(configDoc, false);

Configuration Service Providers

DMProcessConfigXML sends the XML it receives to various Configuration Service Providers (CSPs). These providers read the XML and act on it. If there's some sort of configuration you want to change that isn't supported, the likelihood is that we haven't written a CSP for it yet. We're interested in hearing feedback on new CSPs you'd find useful for us to add.

The definitive list of CSPs is available from msdn2.microsoft.com/bb737536.aspx. Also, there are a number of XML examples available from msdn2.microsoft.com/bb737572.aspx.

Unfortunately, with regard to the availability of CSPs, there is still a difference between Windows Mobile Professional (Pocket PC) phones and Windows Mobile Standard (Smartphone) phones. You will find that some of the CSPs are available on Standard but not Professional. (No, the irony isn't lost on us.) We're working to unify the platforms in the future. Also, OEMs and mobile operators have the ability to selectively disable CSPs to lock down functionality they don't want changed. To be safe, you should always test any configuration you plan to deploy on the phones you're thinking about supporting.

How about a few examples? First, here's a blob of XML that sets the time zone, turns on the alarm, and sets it:

<wap-provisioningdoc>
   <characteristic type="clock">
      <parm name="TimeZone" value="4"/>
      <parm name="AlarmOn" value="1"/>
      <parm name="AlarmTime" value="06:30:00Z"/>  
   </characteristic>
</wap-provisioningdoc>

The characteristic type tells you that it uses the Clock CSP. Each CSP has an MSDN page that describes the parameters you can change as well as the possible values you can change each parameter to. For instance, the documentation for the Clock CSP is available at msdn2.microsoft.com/bb737261.aspx, and it describes the possible values for TimeZone, AlarmOn, and AlarmTime as well as two parameters not in this example (date and time).

Be sure to look at the docs for the correct values to assign to the parameters. I'm sure they make sense to someone, but often not to mere mortals like me. For instance, the TimeZone value for GMT -8 is 4, but the value for GMT -5 is 35. Go figure.

Figure 1 shows an example of some of the things you can do with the Sync CSP. (Note that the documentation for the Sync provider is at msdn2.microsoft.com/bb737700.aspx.) As you see, you can choose what data to sync, where to sync it from, how often to sync, and so on. There are something like 50 parameters related to syncing that you can configure with this provider.

Figure 1 Using the Sync CSP

<wap-provisioningdoc>
   <characteristic type="Sync">
      <characteristic type="Connection">
         <parm name="Server" value="testserver"/>
         <parm name="User" value="testuser"/>
         <parm name="Domain" value="thephone-company"/>
         <parm name="AllowSSLOption" value="1"/>
      </characteristic>
      <characteristic type="Settings">
         <parm name="PeakStartTime" value="0800"/>
         <parm name="PeakEndTime" value="1800"/>
         <parm name="PeakFrequency" value="0"/>
         <parm name="BodyTruncation" value="5120"/>
      </characteristic>
      <characteristic type="Calendar">
         <parm name="Enabled" value="1"/>
      </characteristic>
      <characteristic type="Contacts">
         <parm name="Enabled" value="1"/>
      </characteristic>
      <characteristic type="Mail">
         <parm name="Enabled" value="1"/>
      </characteristic>
   </characteristic>
</wap-provisioningdoc>

While these examples only scratch the surface, hopefully they give you an idea of how the CSPs work.

Getting Your XML to the Device

So you've put together some great XML, and you've written a little app that opens an XML file and sends the data to DMProcessConfigXML. But you won't be doing any provisioning until you can get the XML and the app onto the device.

You have a few options here. The simplest is to put the file and the application on a storage card, pop the card into a device, and then run the application using File Explorer. This is what I do to configure my devices.

But what if you're an IT manager with hundreds of devices to configure? The extra steps of launching File Explorer and navigating to the app would take too much time. In that case, you could make the configuration app run automatically when you insert the storage card.

Create a folder called 2577 (don't ask) at the root of the storage card and put your configuration app into that folder. Name the app autorun.exe. If the app automatically opens a standard XML file name (for example, config.xml), then all you'll need to do to configure the device is insert the card. The AutoRun trick also works when the device boots, so it will work even if you have a phone that requires you to remove the battery to insert the storage card.

Of course, there are more options. If, after the initial setup, you plan to do further configuration with your devices, you could put the configuration app on the device and associate an extension with it. Then you could e-mail configuration files with the associated extension to your users. They would only need to open the attached configuration file to configure their devices. Alternately, your users could browse to a Web site that downloads the configuration file for them.

It's also possible to use PushRouter to send Wireless Application Protocol (WAP) configuration files over SMS to devices. PushRouter is beyond the scope of this article, but this is how mobile operators send configuration files to phones on their networks.

If you're an independent software vendor (ISV), you can use the CSPs from within your setup program to do any necessary device configuration, from adding files to changing registry keys to adding browser favorites to changing the home screen. The simplicity of the configuration format also makes it easy to have a matched XML file for your uninstaller that undoes what your installer did.

If you have a connection to the device through ActiveSync® or the Windows Mobile Device Center, you can configure the device without putting any files on it. The desktop tool rapiconfig.exe is located in the tools directory of the Windows Mobile SDK. This tool will read an XML file and use RAPI to configure the device currently connected to ActiveSync. After you've docked the device, go into the tools directory in the SDK and (assuming your XML file is called config.xml) type this:

rapiconfig config.xml

For more information on RapiConfig, see msdn2.microsoft.com/bb737541.aspx.

Finally, you can create either a CAB or a CAB Provisioning Format (CPF) file. Both CABs and CPFs can be copied to a device and executed directly without the need for a program. The desktop tool makecab.exe is used to create both file types and is also available in the Windows Mobile SDK.

The main difference between a CAB and a CPF file is that the CPF won't open any dialog boxes when it is executed (it runs silently). This turns out to be the CPF's main drawback as well. Depending on the security settings on the device and whether or not the file is signed, CABs and CPFs might need to show a dialog box asking the user if it's OK to provision the device. Because the CPF is required to run silently, it can't show this dialog box. So it fails. In the end, if you're planning to sign the configuration file, use a CPF. If not, use a CAB.

Making either is very simple. You just pass a normal XML file to makecab and give it the name of the output file you want. The one trick is that the XML file must be named _setup.xml. If you call it something else, makecab will succeed, the CAB or CPF file will be generated fine, and then it will fail with a cryptic error when you try to use it. Beware, the documentation doesn't make this very clear.

The syntax for making a CAB file is:

makecab _setup.xml config.cab

Unlike the XML file, there are no such restrictions on the name of the generated CAB file. For instance, instead of config.cab, you can choose whatever name you want for the generated CAB file. The syntax for making a CPF file is, likewise:

makecab _setup.xml config.cpf

Again, replace config.cpf with whatever you want the CPF file to be called. Yes, that's correct, the only difference in the two is whether you name the output file .cab or .cpf. And, again, in both cases the XML file must be called _setup.xml.

Go to msdn2.microsoft.com/bb737689.aspx for more information on CPF files and to msdn2.microsoft.com/bb416436.aspx for more information on signing CPF files.

Who Wants to Type XML?

Hand-typing XML is fine for savvy IT professionals, but what if you want to allow your users to choose their own configuration from a set of options? Wouldn't it be cool to have a Web site with a bunch of checkboxes and such? The users would browse to the site, choose what they want, and it would generate the XML file.

For this scenario, the Microsoft® .NET Framework provides the XmlDocument class, making it easy to programmatically generate XML. For example, remember the clock XML above? The code in Figure 2 creates it on the fly.

Figure 2 Creating the Clock Configuration

void CreateXML()
{
    XmlDocument xmlDoc = new XmlDocument();
    XmlElement root = CreateRoot(xmlDoc);

    XmlElement type = CreateCharacteristic(xmlDoc, "clock", root);
    CreateParm(xmlDoc, "TimeZone", "4", type);
    CreateParm(xmlDoc, "AlarmOn", "1", type);
    CreateParm(xmlDoc, "AlarmTime", "06:30:00Z", type);

    xmlDoc.Save("config.xml");           
}

XmlElement CreateRoot(XmlDocument xmlDoc)
{
    XmlElement root = xmlDoc.CreateElement("wap-provisioningdoc");
    xmlDoc.AppendChild(root);
    return root;
}

XmlElement CreateCharacteristic(XmlDocument xmlDoc, string type, XmlElement parent)
{
    XmlElement element = xmlDoc.CreateElement("characteristic");
    element.SetAttribute("type", type);
    parent.AppendChild(element);
    return element;
}

XmlElement CreateParm(XmlDocument xmlDoc, string name, string value, XmlElement parent)
{
    XmlElement element = xmlDoc.CreateElement("parm");
    element.SetAttribute("name", name);
    element.SetAttribute("value", value);
    parent.AppendChild(element);
    return element;
}

CreateRoot, CreateCharacteristic, and CreateParm are helper functions that you can lift wholesale. Then just make your own CreateXML that calls into them. This example hardcodes the parameter information, but in your Web page the values would come from the user's UI choices. After generating the XML, the Web site downloads it to the device for the user to execute.

Conceivably, you could also write a configuration app that runs on the device. After the user selects the appropriate configuration, code like that in Figure 2 would generate the XML and send it directly to ConfigurationManager.ProcessConfiguration. So you wouldn't need to go through the steps of sending the XML to a file and then reading it back in.

All Provisioned and Ready to Go

If you've ever had to enter an Exchange Server address using the numeric keypad on your phone, you owe it to yourself to move to the comfort of your desktop keyboard and compose some XML. No one should have to go through that pain. I hope you've found this article to be ... liberating. Happy provisioning.

Send your questions and comments to goplaces@microsoft.com.

Mike Calligaro is a Senior Development Lead with the Windows Mobile team at Microsoft and a contributor to the Windows Mobile team blog at blogs.msdn.com/windowsmobile.