Monday, November 16, 2009

HTTP Error 401.1 - Unauthorized: Access is denied due to invalid credentials.

We just experienced a problem with web services authentication. Two of our production servers suddenly failed to authenticate users. We kept getting the 401.1 error. We are using "digest authentication". We had this issue before when we setup a new server. Rebooting the server fixed it. However, this time the trick didn't work. Finally, our administrator decided to remove the server from the domain and re-join it. That fixed the issue.

Friday, November 6, 2009

Provisioning Windows Mobile Devices

Recently I worked on a project in which I need to create a configuration tool for windows mobile device, so it can setup the device ID, date/time, Network connection, Wi-Fi, etc. I used the windows mobile provisioning tool. There are more information on MSDN web site on how to use it. I am not going to repeat that. However, I want to document the issues I ran into while implementing it. Hope this will help others.

Note: The devices I was configuring are Intermec CN50 and Symbol MC75 with windows mobile 6 professional.

To use the provisioning tool, you will create a XML file with the following format. It contains the things you want to configure.

<wap-provisioningdoc>
<characteristic type="Registry">
<characteristic type="HKCU\ControlPanel\Owner">
<parm name="Name" value="[DeviceID]"/>
<parm name="Owner" value="[DeviceIDBinary]" datatype="binary"/>
</characteristic>
</characteristic>
</wap-provisioningdoc>



 


Then in your code you will load the XML into a XmlDocument variable and call ProcessConfiguration()



XmlDocument xd = new XmlDocument();
xd.LoadXml(XMLContent);
XmlDocument xdResult = ConfigurationManager.ProcessConfiguration(xd, false);



Setup Device ID



There is a DeviceInformation Configuration Service Provider, but surprisingly I couldn't find how you would setup the device ID. So I used Registry configuration service provider to update the registry.




<wap-provisioningdoc>
<characteristic type="Registry">
<characteristic type="HKCU\ControlPanel\Owner">
<parm name="Name" value="[DeviceID]"/>
<parm name="Owner" value="[DeviceIDBinary]" datatype="binary"/>
</characteristic>
<characteristic type="HKCU\Software\Microsoft\Bluetooth\Settings">
<parm name="LocalName" value="[DeviceID]" datatype="string"/>
</characteristic>
<characteristic type="HKLM\Ident">
<parm name="Name" value="[DeviceID]" datatype="string"/>
</characteristic>
</wap-provisioningdoc>



Notice the [DeviceIDBinary] field? I didn't have that in there at first. But after changing the DeviceID, it didn't change the owner info displayed on the Today screen, even after a reboot. After researching the registry, I found out that I have to change the Owner field and that is a binary field.



Also most of the time, you will need to specify the datatype. Otherwise you may get an error code 2147500037, or something like that.





Set VPN connection



Using CM_VPNEntries Configuration Service Provider to set VPN connection is very straight forward. Here is the sample XML. If you have more than one, you can set Enabled to 1 to make it default.




<characteristic type="CM_VPNEntries">
<characteristic type="MyVPN">
<parm name="SrcId" value="{436EF144-B4FB-4863-A041-8F905A62C572}"/>
<parm name="DestId" value="{A1182988-0D73-439e-87AD-2A5B369F808B}"/>
<parm name="Phone" value="[MyIP]"/>
<parm name="UserName" value="[UserName]"/>
<parm name="Password" value="[Password]"/>
<parm name="Domain" value="[MyDomain]"/>
<!--Determins the type of authentication e.g. IPSec = 1 vs PPTP = 0-->
<parm name="Type" value="0"/>
<!--Determins the type IPSec encryption, either pre shared key or cert based-->
<parm name="IPSecAuth" value="1"/>
<!--pre shared key can be 256 chars long, but must be ASCII-->
<parm name="PresharedKey" value="[NetworkKey]"/>
<parm name="Enabled" value="0" />
</characteristic>
</characteristic>



Wi-Fi configuration



The XML to configure Wi-Fi is simple, just follow Wi-Fi Configuration Service Provider. However, there are a couple of things worth mention. First, we need to turn on Wi-Fi before apply the XML file, otherwise it will throw a error code. Second, this only worked for Intermec device. The Symbol device has its own way configuring Wi-Fi. I have to export their setting and use Registry configuration service provider to configure it.




<characteristic type="Wi-Fi">
<characteristic type="access-point">
<characteristic type="[MyAccessPointName]">
<parm name="DestId" value="{436EF144-B4FB-4863-A041-8F905A62C572}"/>
<parm name="Encryption" value="0"/>
<parm name="Authentication" value="0"/>
<parm name="Hidden" value="0"/>
<parm name="KeyProvided" value="0"/>
<parm name="NetworkKey" value="[NetworkKey]"/>
<parm name="KeyIndex" value="1"/>
<parm name="Use8021x" value="0"/>
</characteristic>
</characteristic>
</characteristic>



Add URL Exceptions



To add URL Exceptions in the screen showed here, use the following XML.



image




<characteristic type="CM_Mappings">
<characteristic type="16842751">
<parm name="Pattern" value="http://*/*" />
<parm name="Network" value="{A1182988-0D73-439E-87AD-2A5B369F808B}" />
</characteristic>
</characteristic>



GPRS configuration



I used CM_GPRSEntries Configuration Service Provider to configure GPRS. Nothing is special there.





<characteristic type="CM_GPRSEntries">
<characteristic type="GPRS Connection">
<parm name="DestId" value="{436EF144-B4FB-4863-A041-8F905A62C572}" />
<parm name="UserName" value="[DeviceID]" />
<parm name="Password" value="[Password]" />
<parm name="Domain" value="[Domain]" />
<parm name="AlwaysOn" value="1" />
<characteristic type="DevSpecificCellular">
<parm name="GPRSInfoValid" value="1" />
<parm name="GPRSInfoAccessPointName" value="[AcceessPointName]" />
<parm name="BearerInfoValid" value="1" />
<parm name="GPRSInfoProtocolType" value="2" />
<parm name="GPRSInfoL2ProtocolType" value="2" />
<parm name="GPRSInfoAddress" value="" />
<parm name="GPRSInfoDataCompression" value="1" />
<parm name="GPRSInfoHeaderCompression" value="1" />
</characteristic>
</characteristic>
</characteristic>




Set Date/Time and Time Zone



In this application, we also need to set the date/time and time zone information. I tried to use the Clock Configuration Service Provider, but it doesn't work. I don't know what is wrong. I followed the sample xml, but I couldn't get it to work. Finally, since we only use 4 of the time zones, I queried the TimeZoneInformation for each time zone and exported the values. Then put those values in the application's configuration file. I load them in when the user choose a time zone and pass it to the following xml to set the time zone. To set the date/time, I used OpenNETCF.WinAPI.Core.SetLocalDateTime(). This is not pretty, but it worked.




<wap-provisioningdoc>
<characteristic type="Registry">
<characteristic type="HKLM\Time">
<parm name="TimeZoneInformation" value="[TimeZoneInformation]" datatype="binary"/>
</characteristic>
<characteristic type="HKLM\Software\Microsoft\Clock">
<parm name="GMT_OFFSET" value="[GMT_OFFSET]" datatype="integer"/>
</characteristic>
</characteristic>
</wap-provisioningdoc>



If you are changing the time zone and you need to display current date/time on your configuration screen like we did, you need to get the local time using native function call instead of using DateTime.Now. Otherwise, it will mess up.