<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-21999378</id><updated>2011-12-13T19:55:05.524-08:00</updated><title type='text'>Windows Mobile Pocket PC Smartphone Programming</title><subtitle type='html'>&lt;p&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2005/08/windows-mobile-pocket-pc-smartphone.html"&gt;==&gt;Click here for the SiteMap&lt;==&lt;/a&gt;. Original contents with decent amount of source codes. &lt;/p&gt;</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>45</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-21999378.post-114810902286282944</id><published>2006-05-11T00:09:00.000-07:00</published><updated>2006-05-20T00:10:22.883-07:00</updated><title type='text'>Pocket PC Power Management Series 11: Play sound (for example, wav file) when a Pocket PC is suspended</title><content type='html'>&lt;p&gt;&lt;b&gt;Pocket PC Power Management Series 11: Play sound (for example, wav file)  when a Pocket PC is suspended&lt;/b&gt;&lt;/p&gt; &lt;p&gt;I am going to write a new series on Pocket PC Power Management topic: How to  play sound when Pocket PC is sleeping or suspended. Let me use a simple API to  achieve this purpose: PlaySound. &lt;/p&gt; &lt;h3&gt;Why care? &lt;/h3&gt; &lt;p&gt;If you read my previous series on the Power Management topic, you may ask why  we care. If the Pocket PC sleeps, no thread can run, so PlaySound won't even be  called. If the PPC is not sleeping, PlaySound is called, so why the hassle? The  answer is: Yes, PlaySound will be called, but you may not hear the sound! So the  title of this blog is sort of misleading. It should be changed to something like  "How to make sure there is a sound when the device is suspended".&lt;/p&gt; &lt;p&gt;Let us say, you write the code to request the PPC to play a wav file, even  when it is suspended. A good example is the Alarm program. It might need to play  a warning or ringtone at 8PM. This piece of code can be executed at 8PM,  guaranteed by Windows CE OS. However, you may be disappointed not hearing any  sound. Below I will explain why and how to solve the problem.&lt;/p&gt; &lt;h3&gt;Why no Sound?&lt;/h3&gt; &lt;p&gt;Ultimately a peripheral device needs to emit the sound. This peripheral must  be powered or put into certain state so as to vibrate to produce sound waves. A  good chance is: When PlaySound() is called, the Pocket PC is in such a  "System Power State" that the sound peripheral is not supposed to  work; or in Microsoft terms, the sound peripheral is in such a "Device  Power State" mapped from the current "System Power State", that  the sound peripheral might have no power, have low power or in standby mode.&lt;/p&gt; &lt;p&gt;For our specific alarm example, the Pocket PC might be in a "System  Power State" called "Unattended". The sound peripheral is called  "wav1:", which is put into a "D4 Device Power State", mapped  from "Unattended" state. "D4" means "No Power", so  you won't be able to hear any sound.&lt;/p&gt; &lt;p&gt;To above explanation might be too abstract. If you really need to understand  those terms, please read Microsoft Platform Builder documentation on "Power  Management".&lt;/p&gt; &lt;h3&gt;A Possible Solution&lt;/h3&gt; &lt;p&gt;A possible solution to the problem is to change the mapping, so as to change  the power state of "wav1:" device. The following code snippet is doing  this job:&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Courier;font-size:85%;"&gt;HRESULT ChangeWav1Mapping()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;LRESULT lr = E_FAIL;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;HKEY hKey = NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwSubKeys = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwMaxSubkeyLen = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;TCHAR szSubkeyName[MAX_PATH];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;lr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("\\System\\CurrentControlSet\\Control\\Power\\State"), 0, 0, &amp;amp;hKey);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (ERROR_SUCCESS != lr) goto FuncExit;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;lr = RegQueryInfoKey(hKey, NULL, 0, 0, &amp;amp;dwSubKeys, &amp;amp;dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (ERROR_SUCCESS != lr) goto FuncExit;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (int i=0; i&amp;lt;dwSubKeys; i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwSubkeyNameLen = MAX_PATH-1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;memset(szSubkeyName, 0, MAX_PATH*sizeof(TCHAR));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lr = RegEnumKeyEx(hKey, i, szSubkeyName, &amp;amp;dwSubkeyNameLen, NULL, NULL, NULL, NULL);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (ERROR_SUCCESS != lr) continue;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//ALERT(szSubkeyName);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;HKEY hSubkey = NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lr = RegOpenKeyEx(hKey, szSubkeyName, 0, 0, &amp;amp;hSubkey);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (ERROR_SUCCESS != lr) continue;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// any wav1: ?&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwValueType = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwValueData = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwValueDataLen = sizeof(DWORD);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lr = RegQueryValueEx(hSubkey, TEXT("wav1:"), NULL, &amp;amp;dwValueType, (LPBYTE)&amp;amp;dwValueData, &amp;amp;dwValueDataLen);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (ERROR_SUCCESS == lr &amp;amp;&amp;amp; 0 != dwValueData) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dwValueData = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RegSetValueEx(hSubkey, TEXT("wav1:"), NULL, REG_DWORD, (LPBYTE)&amp;amp;dwValueData, sizeof(DWORD));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RegCloseKey(hSubkey);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;RegFlushKey(hKey);&lt;br /&gt;&lt;br /&gt;FuncExit:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (hKey) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RegCloseKey(hKey);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;return S_OK;&lt;br /&gt;}&lt;/span&gt;&lt;/p&gt; &lt;p&gt;Notice this is a piece of bad code. It forces the "wav1:" device to  be always powered, no matter what state the Pocket PC is in. Looks like that is  the case for most Pocket PC 2003 devices, but probably not true for Pocket PC  5.0 device. So the above code effectively changes the sound behavior of PPC 5.0  device.&lt;/p&gt; &lt;p&gt;The recommended API to use to &lt;b&gt;SetPowerRequirement&lt;/b&gt; and &lt;b&gt;ReleasePowerRequirement&lt;/b&gt;.  I will talk about them in a later post.&lt;/p&gt; &lt;h3&gt;Wrap Up&lt;/h3&gt; &lt;p&gt;Pocket PC sleeps. Read the following two posts for basis:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;a title="Pocket PC Power Management Series 3: When is My Device Sleeping, and when is it Running?" href="http://windowsmobilepro.blogspot.com/2005/10/pocket-pc-power-management-series-3.html"&gt;Pocket      PC Power Management Series 3: When is My Device Sleeping, and when is it      Running?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="Pocket PC Power Management Series 8: Why Pocket PC's Battery Life so Notorious?" href="http://windowsmobilepro.blogspot.com/2006/01/pocket-pc-power-management-series-8.html"&gt;Pocket      PC Power Management Series 8: Why Pocket PC's Battery Life so Notorious?&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;There are ways to force the device not to sleep, or request it to run a  program at certain time or upon certain event:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;a title="Pocket PC Power Management Series 5: Force the Device not to Sleep: a Brutal Way?" href="http://windowsmobilepro.blogspot.com/2005/12/pocket-pc-power-management-series-5.html"&gt;Pocket      PC Power Management Series 5: Force the Device not to Sleep: a Brutal Way?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="Pocket PC Power Management Series 6: Request the Device to Run: a Gentle Way" href="http://windowsmobilepro.blogspot.com/2005/12/pocket-pc-power-management-series-6.html"&gt;Pocket      PC Power Management Series 6: Request the Device to Run: a Gentle Way&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The above techniques force the CPU to run, but not necessarily other  peripheral devices. In this post we talked about "wav1:" and a  possible hacky way to override the power mapping.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114810902286282944?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114810902286282944/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114810902286282944' title='16 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114810902286282944'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114810902286282944'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/05/pocket-pc-power-management-series-11.html' title='Pocket PC Power Management Series 11: Play sound (for example, wav file) when a Pocket PC is suspended'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114741776923632665</id><published>2006-05-08T00:08:00.000-07:00</published><updated>2006-05-12T00:09:29.253-07:00</updated><title type='text'>XXX.exe is not a valid Pocket PC Application: Troubleshooting guidelines</title><content type='html'>&lt;p&gt;&lt;b&gt;XXX.exe is not a valid Pocket PC Application: Troubleshooting guidelines&lt;/b&gt;&lt;/p&gt; &lt;p&gt;It is not uncommon for a developer to see his/her program cannot run in the  emulator or physical device, after struggling with code development, compilation  error and build issues. Most typical error is like "&lt;b&gt;XXX.exe is not a  valid Pocket PC application&lt;/b&gt;", like the following screen cut. Hereby I  am trying to write simple guidelines for troubleshooting such issue.&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/PPC2003WrongSubsystemcannotrun.jpg" border="0" height="552" width="346" /&gt;&lt;/p&gt; &lt;h3&gt;1. Check the Platform&lt;/h3&gt; &lt;p&gt;The executable might be built for a platform that does not match the target  device. For example, an executable built for x86 emulator cannot run in any  physical device, which supports ARM instruction sets.&lt;/p&gt; &lt;p&gt;In WM5.0, Microsoft introduces a build target called "THUMB", which  is a subset of ARM instruction sets. An executable built for "THUMB"  can only run in WM5.0 device or emulator. You'll get the above error message if  running such executable in Pocket PC 2003 or Smartphone 2003 device.&lt;/p&gt; &lt;p&gt;The way to check the platform is to use "&lt;i&gt;dumpbin /header &lt;exe_file&gt;&lt;/i&gt;",  and take a look at the line exposing the "&lt;i&gt;machine&lt;/i&gt;" information.&lt;/p&gt; &lt;p&gt;The way to fix platform issue is to change project settings in your IDE (EVC4  or Visual Studio 2005). Both IDEs allow you to manually modify the command line  option &lt;i&gt;/MACHINE&lt;/i&gt;.&lt;/p&gt; &lt;h3&gt;2. Check the SubSystem&lt;/h3&gt; &lt;p&gt;An executable built for a lower subsystem (for example, 4.20) can run in a  WM5.0 device, but not vice versa. If you try to start a program built for 5.0,  you will get the warning "&lt;b&gt;XXX is not a valid Pocket PC application&lt;/b&gt;".&lt;/p&gt; &lt;p&gt;The way to check the subsystem is to use "&lt;i&gt;dumpbin /header &lt;exe_file&gt;&lt;/i&gt;",  and take a look at the line exposing the "&lt;i&gt;subsystem&lt;/i&gt;"  information.&lt;/p&gt; &lt;p&gt;The way to fix subsystem issue is to change project settings in your IDE  (EVC4 or Visual Studio 2005). Both IDEs allow you to manually modify the command  line option &lt;i&gt;/SUBSYSTEM&lt;/i&gt;.&lt;/p&gt; &lt;h3&gt;3. DLL HELL&lt;/h3&gt; &lt;p&gt;The previous two issues are easy to identify and fix, but the third one is  very concealing and hard to troubleshoot. In general, if a program needs DLLs  (who does not?), the DLL must either be present in the system, or already loaded  into memory. If a required DLL is not available, the warning is clear and to the  point: "&lt;b&gt;Cannot find 'XXX.exe' (or one of its components). Make sure the  path and file name are correct and all the required libraries are  available."&lt;/b&gt;&lt;/p&gt; &lt;p&gt;However, if the DLL is available or already loaded into memory, but the DLL  does not export the required functions, CE OS could not verify that linker time  dependencies are met. It shows a super-misleading warning "&lt;b&gt;XXX.exe is  not a valid Pocket PC application&lt;/b&gt;".&lt;/p&gt; &lt;p&gt;It is hard to find which DLL causes the issue, and even harder to solve the  issue. On the desktop, you can isolate yourself to certain extent by ensuring  that the DLL you built and tested is the one that is loaded by the OS; one way  putting the DLL in the same directory as your application. On Windows CE,  to save memory, only a single copy of DLL is loaded into physical memory, and  multiple processes share the single copy if all requiring such DLL.&lt;/p&gt; &lt;p&gt;To confirm whether the DLL HELL causes the dreaded message, you can try to  find what other processes are using the same DLL, then terminate those processes  and start your first. If your program works, then definitely your issue is  caused by the DLL loaded by other processes. MFC is a good suspect, since there  is so many versions of MFC DLLs (although Microsoft has taken extra mile to name  the MFC DLLs with version number, debug/retail, ...)&lt;/p&gt; &lt;h3&gt;Wrap Up&lt;/h3&gt; &lt;p&gt;Machine or SubSystem mismatch is easy to detect and fix. Please read "&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/trap-of-copying-project-settings-in.html" title="Trap of Copying Project Settings in Visual Studio 2005 (/Machine: ARM vs. Thumb, /subsystem: windowsce, 4.02 vs 5.01)"&gt;Trap  of Copying Project Settings in Visual Studio 2005 (/Machine: ARM vs. Thumb,  /subsystem: windowsce, 4.02 vs 5.01)&lt;/a&gt;" for more details.&lt;/p&gt; &lt;p&gt;Issue caused by DLL-mismatch is much harder to detect. If you run into the  issue, and you are use MFC, there is a high possibility that multiple versions  of MFC DLLs are the culprit.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114741776923632665?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114741776923632665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114741776923632665' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114741776923632665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114741776923632665'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/05/xxxexe-is-not-valid-pocket-pc.html' title='XXX.exe is not a valid Pocket PC Application: Troubleshooting guidelines'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114698565360268579</id><published>2006-05-05T00:06:00.000-07:00</published><updated>2006-05-07T00:07:33.616-07:00</updated><title type='text'>Emulator Troubleshooting/Tip 03: Quickly Establish ActiveSync Connection</title><content type='html'>&lt;p&gt;&lt;b&gt;Emulator Troubleshooting/Tip 03: Quickly Establish ActiveSync Connection&lt;/b&gt;&lt;/p&gt; &lt;p&gt;As talked in "&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/emulator-troubleshootingtip-01-to.html" title="Emulator Troubleshooting/Tip 01: To Cradle or Not to Cradle?"&gt;Emulator  Troubleshooting/Tip 01: To Cradle or Not to Cradle?&lt;/a&gt;", when an emulator  is cradled, ActiveSync uses DMA to communicate with the emulator, eliminating  the error-prone TCP/TP transport. &lt;/p&gt; &lt;p&gt;DMA is generally very reliable. However, quite a few times, an emulator might  have difficulty to be ActiveSync'ed, after cradled. Typically a dialog like  below is displayed. &lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/EmulatorCannotConnectAfterConnectionChange.jpg" border="0" height="295" width="486" /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;I was not able to generalize under what circumstances ActiveSync did not  work. It might happen if ActiveSync's "Connection Setting" is changed,  or the Device Emulator Manager runs several emulators and one of which is  already cradled.&lt;/p&gt; &lt;p&gt;At first, I did not know any good way to fix the problem. Restart the  emulator does not help at all. Killing ActiveSync or &lt;i&gt;wcescomm.exe&lt;/i&gt; might  worsen the issue. A lot of times I had to restart the machine.&lt;/p&gt; &lt;p&gt;Accidentally I found a very quick and very reliable way to make ActiveSync  connect to the emulator:&lt;/p&gt; &lt;p&gt;1. Go to ActiveSync's "Connect Setting" dialog, and clear the check  box "&lt;b&gt;Allow connections to one of the following&lt;/b&gt;". Click OK to  dismiss the dialog.&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/ActiveSyncDMADisabled.jpg" border="0" height="312" width="454" /&gt;&lt;/p&gt; &lt;p&gt;2. Again, go to ActiveSync's "Connect Setting" dialog, and check  the check box "&lt;b&gt;Allow connections to one of the following&lt;/b&gt;". Make  sure DMA is chosen. Click OK to dismiss the dialog.&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/ActiveSyncDMAEnabled.jpg" border="0" height="312" width="454" /&gt;&lt;/p&gt; &lt;p&gt;In my cases, a cradled-emulator will be successfully ActiveSync'ed,  guaranteed!&lt;/p&gt; &lt;p&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;A little off-topic&lt;/span&gt;: When ActiveSync 4.0 were released, there were so many  issues that Microsoft had to publish a special memo to partners, listing all  possible workarounds and promising a quick release of ActiveSync 4.1. Actually  when I got a PPC6700 device from Sprint before it was released to mass-market, I  had so many troubles making ActiveSync 4 work with the device, that the Sprint  support recommended me to format and install a new machine, without installing  any other software and without enabling any firewall, and dedicate the machine  to ActiveSync 4 and the device. What a nice workaround!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114698565360268579?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114698565360268579/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114698565360268579' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114698565360268579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114698565360268579'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/05/emulator-troubleshootingtip-03-quickly.html' title='Emulator Troubleshooting/Tip 03: Quickly Establish ActiveSync Connection'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114690151874706196</id><published>2006-05-03T00:44:00.000-07:00</published><updated>2006-05-06T00:45:18.763-07:00</updated><title type='text'>Pocket PC Console for standard input and standard output: A convenient tool for lazy debugging and tracing in Pocket PC 2003 devices</title><content type='html'>&lt;p&gt;&lt;b&gt;Pocket PC Console for standard input and standard output: &lt;/b&gt;&lt;b&gt;A convenient tool for lazy debugging and tracing in Pocket PC 2003  devices&lt;br /&gt;&lt;/b&gt;&lt;/p&gt; &lt;p&gt;Debugging and tracing sometimes can be a tricky business, especially for a  multi-threaded program. &lt;/p&gt; &lt;ul&gt;&lt;li&gt;Log file is used most commonly. &lt;/li&gt;&lt;li&gt;&lt;i&gt;OutputDebugString&lt;/i&gt; is also nice, and there is no need to write any      code to deal with a log file. However, you do need to attach the debugger to      receive the debugging message. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Probably the simplest approach, requiring neither a log file nor a debugger,  is the famous &lt;i&gt;printf &lt;/i&gt;(or the C# equivalent &lt;i&gt;Console.Write&lt;/i&gt;, or the  Java equivalent &lt;i&gt;System.out.println&lt;/i&gt;). The simplicity of using &lt;i&gt;printf&lt;/i&gt;,  and the beautify of showing messages on a console in real time, make &lt;i&gt;printf&lt;/i&gt;  a very nice tool for lazy programmers :) &lt;/p&gt; &lt;h3&gt;Pocket PC Shell&lt;/h3&gt; &lt;p&gt;Unfortunately there is no built-in console (therefore no standard input and  standard output) in Windows Mobile devices. Even if your code compiles and  builds correctly, there is no way you can see the messages.&lt;/p&gt; &lt;p&gt;One tool coming for rescue is PPC Command Shell, part of Microsoft &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=74473fd6-1dcc-47aa-ab28-6a2b006edfe9&amp;DisplayLang=en"&gt;Windows  Mobile Developer Power Toys&lt;/a&gt;. See my article "&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/how-to-launch-program-via-command-line.html" title="How to launch  a program via command line in Pocket PC 2003 device and Pocket PC 5.0 device?"&gt;How  to launch a program via command line in Pocket PC 2003 device and Pocket PC 5.0  device?&lt;/a&gt;" for a brief introduction on those nice little tools.&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;b&gt;&lt;i&gt;PPC Command Shell &lt;/i&gt;&lt;/b&gt;- Command shell for the Pocket PC 2003      device.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Once installed, three files can be found in the desktop PC's destination  folder:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;i&gt;console.dll&lt;/i&gt;: copying it to the device's \Windows folder&lt;/li&gt;&lt;li&gt;&lt;i&gt;shell.exe&lt;/i&gt;: copying it to any folder in the device&lt;/li&gt;&lt;li&gt;&lt;i&gt;cmd.exe&lt;/i&gt;: copying it to any folder in the device&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The only files needed for &lt;i&gt;printf &lt;/i&gt;to work are &lt;i&gt;console.dll &lt;/i&gt;and &lt;i&gt;shell.exe&lt;/i&gt;.  These two provide the console, supporting standard input and standard output.  Once invoked, &lt;i&gt;shell.exe &lt;/i&gt;stays in the memory. In fact, upon running, &lt;i&gt;shell.exe  &lt;/i&gt;put an entry under registry &lt;i&gt;HKLM\Init&lt;/i&gt;,&lt;i&gt; &lt;/i&gt;so as to make sure  itself is always up and running (even before the OS kernel components, like &lt;i&gt;device.exe&lt;/i&gt;,  &lt;i&gt;gwes.exe&lt;/i&gt;, and etc.)&lt;/p&gt; &lt;blockquote&gt;   &lt;pre&gt;[HKEY_LOCAL_MACHINE\init]&lt;br /&gt;"Launch10"="shell.exe"&lt;/pre&gt; &lt;/blockquote&gt; &lt;p&gt;The executable &lt;i&gt;cmd.exe &lt;/i&gt;is not needed. It solely provide  implementations of some commonly used DOS prompt commands, for example, dir, cd.&lt;/p&gt; &lt;p&gt;Below is a simple testing program:&lt;/p&gt; &lt;blockquote&gt;   &lt;pre&gt;printf("This is a test");&lt;br /&gt;MessageBox(NULL, TEXT("Console Test!"), TEXT("Demo"),&lt;br /&gt; MB_ICONINFORMATION|MB_OK|MB_SETFOREGROUND|MB_OK);&lt;/pre&gt; &lt;/blockquote&gt; &lt;p&gt;And here is the screen cut when the program runs:&lt;/p&gt; &lt;p&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/ConsoleTestingPPC2003.0.jpg" border="0" height="324" width="239" /&gt;&lt;/p&gt; &lt;p&gt;Warning: This tool does not work in Pocket PC 5.0 device, nor does it work in  any Smartphone device. In fact, the following warning is popped up if running in  Smartphone 2003 device:&lt;/p&gt; &lt;p&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/320/ConsoleNotWorkingSP2003.jpg" border="0" height="224" width="179" /&gt;&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;h3&gt;Wrap Up&lt;/h3&gt; &lt;p&gt;Pocket PC Shell is a simple yet powerful tool for debugging or tracing in  real time. However, the one packaged in Microsoft's Mobile Power Toy can only  work in Pocket PC 2003 device (inclduing 2003 SE).&lt;/p&gt; &lt;p&gt;There is &lt;a href="http://www.symbolictools.de/public/pocketconsole/index.htm"&gt;another  free tool&lt;/a&gt; but I've never tested it. Looks like it has not been updated for  quite a while.&lt;/p&gt; &lt;p&gt;Notice: Never compile &lt;i&gt;printf&lt;/i&gt; into your release build! The &lt;i&gt;printf &lt;/i&gt;and  console processing code are not simple thus sort of eating the CPU!&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114690151874706196?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114690151874706196/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114690151874706196' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114690151874706196'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114690151874706196'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/05/pocket-pc-console-for-standard-input.html' title='Pocket PC Console for standard input and standard output: A convenient tool for lazy debugging and tracing in Pocket PC 2003 devices'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114646869223016024</id><published>2006-04-30T00:30:00.000-07:00</published><updated>2006-05-04T23:27:59.906-07:00</updated><title type='text'>Trap of Copying Project Settings in Visual Studio 2005 (/Machine: ARM vs. Thumb, /subsystem: windowsce, 4.02 vs 5.01)</title><content type='html'>&lt;p&gt;&lt;b&gt;Trap of Copying Project Settings in Visual Studio 2005 (/Machine:ARM vs.  Thumb, /subsystem:windowsce,4.02 vs 5.01)&lt;/b&gt;&lt;/p&gt; &lt;p&gt;Visual Studio 2005 offers developers with a nice option when a new project  platform needs to be created: to copy project settings for one platform to the  new platform.&lt;/p&gt; &lt;h3&gt;How Copying Project Setting works?&lt;/h3&gt; &lt;p&gt;Typical use case is that you already have a project for Pocket PC 2003, and  you want to create a new project targeting Pocket PC 5.0 device. You can bring  up "&lt;b&gt;Project Settings&lt;/b&gt;" dialog, and click "&lt;b&gt;Configuration  Manager&lt;/b&gt;" button to "&lt;b&gt;New&lt;/b&gt;" the project for 5.0 platform,  and opt to copy from the project setting for 2003 platform.&lt;/p&gt; &lt;p&gt;Visual Studio takes care quite a few changes automatically, for example,  output directory, windows CE version, and PPC/Smartphone platform. The mechanism  to cover the changes is using Macros extensively. Below are two typical macros:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;Windows CE version difference:&lt;b&gt; $(CEVer)&lt;/b&gt;. 4.20 for 2003 platform,      and 5.01 for 5.0 plaform.&lt;/li&gt;&lt;li&gt;Platform difference: &lt;b&gt;$(CEPlatform) / $(CePlatform) / $(PLATFORMDEFINES)&lt;/b&gt;.      &lt;b&gt;WIN32_PLATFORM_WFSP&lt;/b&gt; for Smartphone, and &lt;b&gt;WIN32_PLATFORM_PSPC&lt;/b&gt;      for Pocket PC.&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Issue of Blindly Copying Project Settings from Newer Platform to Older  Platform&lt;/h3&gt; &lt;p&gt;It is worthy noting that VS2005 does not adjust two important options for its  linker while copying project settings: &lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;b&gt;/SUBSYSTEM &lt;/b&gt;option, which tells the targeting OS how to run the .exe      file, and affects the entry point symbol (or entry point function) that the      linker will choose. &lt;/li&gt;&lt;li&gt;&lt;b&gt;/MACHINE &lt;/b&gt;option, which specifies the target platform for the      program, for example, X86, X64, IA64, MIPS, SH4, and etc.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;If you create a new Smart Device project, possibly &lt;b&gt;/MACHINE &lt;/b&gt;is not set  explicitly, and &lt;b&gt;/SUBSYSTEM &lt;/b&gt;is hard coded to be the number most suitable  for the project. For example, if you create a project for Pocket PC 5.0  platform, &lt;b&gt;/MACHINE &lt;/b&gt;is not set (so default to &lt;b&gt;THUMB&lt;/b&gt;), and &lt;b&gt;/SUBSYSTEM  &lt;/b&gt;is set to 5.01.&lt;/p&gt; &lt;p&gt;If such settings are blindly copied to another project for older platform (in  this case, Pocket PC 2003), the final binary won't be executed by PPC2003  device.&lt;/p&gt; &lt;h3&gt;Walkthrough of the issue&lt;/h3&gt; &lt;p&gt;1. A new solution is created, and a new Smart Device project targeting Pocket  PC 5.0 platform is created. &lt;/p&gt; &lt;ul&gt;&lt;li&gt;"Project      Setting"=&gt;"Linker"=&gt;"System"=&gt;"SubSystem"      is not set. &lt;/li&gt;&lt;li&gt;"Project      Setting"=&gt;"Linker"=&gt;"Advanced"=&gt;"Target      Machine" is not set either. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Command line option will be like "&lt;b&gt; /subsystem:windowsce,5.01"&lt;/b&gt;&lt;/p&gt; &lt;p&gt;Do a "&lt;b&gt;dumpbin /all&lt;/b&gt;" on the executable generated by VS2005,  you'll see something like this, meaning the binary is for Thumb machine and CE  version should be 5.01 or higher.&lt;/p&gt; &lt;blockquote&gt;   &lt;pre&gt;FILE HEADER VALUES&lt;br /&gt; 1C2 machine (Thumb)&lt;br /&gt;OPTIONAL HEADER VALUES&lt;br /&gt; 5.01 subsystem version&lt;/pre&gt; &lt;/blockquote&gt; &lt;p&gt;2. The executable for Pocket PC 5.0 runs great in a 5.0 device. Now you want  propagate its success to Pocket PC 2003 devices, so a new project targeting  PPC2003 platform is created using Configuration Manager. In its "Active  solution platform" dropdown list, you select "New", and  "Copy settings from" the Pocket PC 5.0 platform.&lt;/p&gt; &lt;p&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/PPC2003CopiedFromPPC5.jpg" border="0" height="234" width="339" /&gt;&lt;/p&gt; &lt;p&gt;3. For the new project to build, &lt;a href="http://windowsmobilepro.blogspot.com/2005/08/manually-migrate-embedded-visual-c.html"&gt;you  may need to add "secchk.lib" to lib dependency list if you have at  least one function call, and add "ccrtrtti.lib" to lib dependency list  if you have at least one C++ source file&lt;/a&gt;. However, if you run the  executable, you'll get the infamous error dialog:&lt;/p&gt; &lt;p&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/PPC2003WrongSubsystemcannotrun.jpg" border="0" height="552" width="346" /&gt;&lt;/p&gt; &lt;p&gt;4. Do a "&lt;b&gt;dumpbin /all&lt;/b&gt;" on the executable for PPC2003  platform, you'll see that the executable is for THUMB machine and CE OS must be  5.01 or higher, exactly the same as the one for PPC5.0 device. To fix it, you  need to change the linker option to something like "&lt;b&gt;  /subsystem:windowsce,4.20 /machine:ARM&lt;/b&gt;".&lt;/p&gt; &lt;p&gt;Rebuild and you'll get a good executable with the following header values:&lt;/p&gt; &lt;blockquote&gt;   &lt;pre&gt;FILE HEADER VALUES&lt;br /&gt; 1C0 machine (ARM)&lt;br /&gt;OPTIONAL HEADER VALUES&lt;br /&gt; 4.20 subsystem version&lt;/pre&gt; &lt;/blockquote&gt; &lt;p&gt;Notice you must change both &lt;b&gt;/subsystem&lt;/b&gt; and &lt;b&gt;/machine&lt;/b&gt;, otherwise  it won't work!&lt;/p&gt; &lt;h3&gt;Wrap Up&lt;/h3&gt; &lt;p&gt;VS2005 seems to copy the project setting literally. It resolves the  fundamental differences (OS, PPC or Smartphone, directories) by expanding  Macros, for example, &lt;b&gt;$(CEVer) &lt;/b&gt;and &lt;b&gt;$(CEPlatform)&lt;/b&gt;. However, &lt;b&gt;/MACHINE&lt;/b&gt;  and &lt;b&gt;/SUBSYSTEM &lt;/b&gt;are either not specified, or hard-code to be a number,  resulting in wrong values to be used in the newly-created project. Such mismatch  probably is not a big issue if the new project is for newer platform (for  example, copying PPC2003 settings to PPC5.0 project), but definitely causes  headache is the new project is for an older platform (for example, copying  PPC5.0 settings to PPC2003 project).&lt;/p&gt; &lt;p&gt;&lt;i&gt;A Side Topic&lt;/i&gt;: The THUMB instruction set consists of 16-bit  instructions that act as a compact shorthand for a subset of the 32-bit  instructions of the standard ARM. The binary built for THUMB is typically with  the size roughly 70-80% that of ARM. Unfortunately binary compiled for THUMB  cannot be executed in Windows Mobile 2003 devices.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114646869223016024?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114646869223016024/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114646869223016024' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114646869223016024'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114646869223016024'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/04/trap-of-copying-project-settings-in.html' title='Trap of Copying Project Settings in Visual Studio 2005 (/Machine: ARM vs. Thumb, /subsystem: windowsce, 4.02 vs 5.01)'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114638115970071501</id><published>2006-04-28T00:11:00.000-07:00</published><updated>2006-04-30T18:07:41.800-07:00</updated><title type='text'>/etc/hosts file equivalent in Windows Mobile device</title><content type='html'>&lt;p&gt;&lt;b&gt;/etc/hosts file equivalent in Windows Mobile device&lt;/b&gt;&lt;/p&gt; &lt;p&gt;As you know, the "hosts" file in Windows and other operating  systems is used to associate host names with IP addresses. When TCP/IP  networking stack tries to resolve a host name to its IP address, it first  consults the local hosts file to see whether such mapping is already available.  If not, domain name (DNS) server is then consulted. For example, all machines'  hosts file might contain the following line:&lt;/p&gt; &lt;blockquote&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;"&gt;127.0.0.1 localhost&lt;/span&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;It maps "localhost" to the loopback address. There is no magic; the  TCP/IP stack won't treat "localhost" differently from "&lt;a href="http://www.mit.edu/"&gt;www.mit.edu&lt;/a&gt;"  when it tries to resolve the string name. (For curious mind, the difference  comes when IP stack realizes that the IP's first number is 127, a special  number.)&lt;/p&gt; &lt;h3&gt;Why hosts-like functionality is needed for Windows Mobile device?&lt;/h3&gt; &lt;p&gt;Windows Mobile devices does not have the concept of HOSTS file. &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcetcpip/html/cmconhostnameresolution.asp"&gt;DNS  or WINS is always used&lt;/a&gt;. However, a hosts-file-like capability might be  useful in certain cases. Below I listed a few possible cases:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;b&gt;Corporate intranet&lt;/b&gt;: In a corporate intranet environment, quite      possibly a large number of Windows Mobile devices are used. Unlike desktop      PCs or Linux/Solaris servers, handheld device does not have a good way for      naming, thus typically give IT department more management overhead.      Distributed a common hosts file to all Windows Mobile devices is one way to      manage.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Some special APIs&lt;/b&gt;: A typical example is &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mobilesdk5/html/mob5oriMessageQueuing.asp"&gt;MSMQ      for Windows Mobile devices&lt;/a&gt;. In MSMQ, a message queue can be referenced      by its path name in the form of "MachineName\QueueName". So able      to resolve machine name is essential for MSMQ application to work.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Home or Home Office&lt;/b&gt;: At your home you may have a wireless router,      several PCs and Windows Mobile devices, all having static-assigned IPs or      DHCP-ed IPs. And, you need to sync a device with a home PC over wireless.      The trouble is that ActiveSync in the device side needs the name of the      desktop PC where ActiveSync is also running, and there is no way for the      device to resolve the desktop PC's name (unless you really want to run a      WINS service in one desktop PC and configure your device to use the WINS      service for name resolution.)&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;How to make "hosts" in Windows Mobile devices for name resolution?&lt;/h3&gt; &lt;p&gt;Although there is no hosts file in Pocket PC or Smartphone's file-system,  registry is the place to put such name-IP mappings. To achieve this, add a  subkey to &lt;b&gt;HKEY_LOCAL_MACHINE\Comm\Tcpip\Hosts&lt;/b&gt; for each machine name that  must be resolved, then add binary values for the IP address (value name "ipaddr")  and expiration time (value name "&lt;b&gt;expiretime&lt;/b&gt;"). The following  shows the export of a key entry that resolves the name "hello" to IP  address 161.163.165.169. &lt;b&gt;Expiretime&lt;/b&gt; is a huge number, indicating no  expiration. For the sole purpose of name resolution, &lt;b&gt;expiretime&lt;/b&gt; is not  strictly needed.&lt;/p&gt; &lt;blockquote&gt;   &lt;pre class="clsCode"&gt;[HKEY_LOCAL_MACHINE\Comm\Tcpip\Hosts\hello]&lt;br /&gt;"ipaddr"=hex:a1,a3,a5,a9&lt;br /&gt;"ExpireTime"=hex:99,99,99,99,99,99,99&lt;/pre&gt; &lt;/blockquote&gt; &lt;p&gt;Below are the screen shots how to manually add the entry using Remote  Registry Editor.&lt;/p&gt; &lt;p align="left"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/HostsRegistrySettings.jpg" border="0" height="238" width="640" /&gt;&lt;/p&gt; &lt;p&gt;Below is the screen cut shows testing name resolution in the device. The  following simple code is used:&lt;/p&gt; &lt;pre&gt;C++:&lt;br /&gt;HOSTENT* pHostent = gethostbyname(pchHostName)&lt;br /&gt;or C#:&lt;br /&gt;System.Net.Dns.Resolve(hostName)&lt;/pre&gt; &lt;div align="left"&gt;   &lt;pre&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/HostsResolved.jpg" border="0" height="475" width="350" /&gt;&lt;/pre&gt; &lt;/div&gt; &lt;h3 align="left"&gt;Wrap Up&lt;/h3&gt; &lt;p align="left"&gt;If you only need to take care of one or two name-IP mappings,  manually adding them to the registry is do-able. For large number of names,  Pocket Hosts is an ideal free utility for such task.&lt;/p&gt; &lt;p align="left"&gt;People with good eyesight might notice a subkey called "&lt;b&gt;ppp_peer&lt;/b&gt;"  in one of screen shots. &lt;/p&gt;  &lt;blockquote&gt;   &lt;pre&gt;[HKEY_LOCAL_MACHINE\Comm\Tcpip\Hosts\ppp_peer]&lt;br /&gt;"aliases"=hex(7):     00&lt;br /&gt;"ipaddr"=hex:     c0,a8,37,64&lt;/pre&gt; &lt;/blockquote&gt; &lt;p align="left"&gt;"&lt;b&gt;ppp_peer&lt;/b&gt;" is the name the device gives to the desktop  PC during ActiveSync. It maps to IP "c0,a8,37,64" ("192.168.55.100").  In the device side itself, the IP is "192.168.55.101". &lt;/p&gt;  &lt;h3 align="left"&gt;Update on the Wrap Up&lt;/h3&gt;  &lt;p align="left"&gt;In Windows Mobile 5.0 devices, ActiveSync in the device gives  desktop PC a new name: "&lt;b&gt;dtpt_peer&lt;/b&gt;", which maps to IP  "A9,FE,02,02" (169.254.2.2). In the device side itself, the IP is  "169.254.2.1". &lt;/p&gt;  &lt;p align="left"&gt;Looks like in Windows Mobile 5.0 emulators (and Windows Mobile  2003 devices), "&lt;b&gt;ppp_peer&lt;/b&gt;" is still used.&lt;/p&gt;  &lt;p align="left"&gt;&lt;i&gt;A little bit on why "&lt;b&gt;ppp_peer&lt;/b&gt;" or "&lt;b&gt;dtpt_peer&lt;/b&gt;"  is needed for ActiveSync&lt;/i&gt;: When a windows mobile device plus in a desktop PC,  a new network interface is created in the desktop PC. This NIC is named like  "Windows Mobile-based Device #n", and its IP is hard coded to be  "169.254.2.2".  New entries are also added to the PC's routing  table, so as to route IP packets destined to 169.254.2.X to only the Window  Mobile device. &lt;/p&gt;  &lt;p align="left"&gt;You may notice when your device is cradled, a small tray icon  like networking icon, with a plus sign turning left and right, trying to acquire  a network address. You can also try typing "ipconfig /all" and  "route print" in a command prompt to play with the this NIC.&lt;/p&gt;  &lt;p align="left"&gt;As far as I know, you cannot explicitly bind to this specific  NIC (disclaimer: Never tried myself.)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114638115970071501?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114638115970071501/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114638115970071501' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114638115970071501'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114638115970071501'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/04/etchosts-file-equivalent-in-windows.html' title='/etc/hosts file equivalent in Windows Mobile device'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114620638350589318</id><published>2006-04-26T23:38:00.000-07:00</published><updated>2006-04-30T11:34:49.623-07:00</updated><title type='text'>Pocket Outlook Woe 02: Domain name is truncated to the same size as password after calling IMailSyncCallBack :: RequestCredentials</title><content type='html'>&lt;p&gt;&lt;b&gt;Pocket Outlook Woe 02: Domain name is truncated to the same size as  password after calling IMailSyncCallBack::RequestCredentials&lt;/b&gt;&lt;/p&gt; &lt;p&gt;In "&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/pocket-outlook-woe-01-incoming-server.html" title="Pocket Outlook Woe 01: incoming server and outgoing server are passed as two NULL pointers from Outlook to Transport"&gt;Pocket  Outlook Woe 01&lt;/a&gt;", I talked about one issue regarding the latest version  of Pocket Outlook (installed with Windows Mobile 5.0 devices, and newer version  of Pocket PC 2003 SE devices), that Pocket Outlook passes two NULL pointers as  incoming mail server and outgoing mail server to a customized Transport. Today I  am focusing on the second woe: domain name is truncated to the same size as that  of password after &lt;b&gt;IMailSyncCallBack::RequestCredentials&lt;/b&gt; is returned.&lt;/p&gt; &lt;h3&gt;IMailSyncCallback: Pocket Outlook itself&lt;/h3&gt; &lt;p&gt;The method involved here is called &lt;b&gt;IMailSyncCallBack::RequestCredentials&lt;/b&gt;.   &lt;b&gt;IMailSyncCallback&lt;/b&gt; can be understood as Outlook itself, which provides  Transport with methods to interact with Outlook. For example, Transport can:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;request memory in tmail.exe's address space&lt;/li&gt;&lt;li&gt;request Outlook to synchronize an account&lt;/li&gt;&lt;li&gt;request Outlook to display a message box&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The method giving headache here is &lt;span style="font-weight: bold;"&gt;RequestCredentials&lt;/span&gt;, which is used by  Transport to request new credentials from the user. &lt;/p&gt; &lt;blockquote&gt;   &lt;b&gt;HRESULT RequestCredentials (&lt;/b&gt; &lt;b&gt;LPCWSTR &lt;/b&gt;&lt;i&gt;pszProfile&lt;/i&gt;&lt;b&gt;,&lt;/b&gt; &lt;b&gt;SYNCCREDENTIALS    * &lt;/b&gt;&lt;i&gt;ppcredsSource&lt;/i&gt;&lt;b&gt;,&lt;/b&gt; &lt;b&gt;SYNCCREDENTIALS ** &lt;/b&gt;&lt;i&gt;ppcreds&lt;/i&gt; &lt;b&gt;);&lt;/b&gt; &lt;/blockquote&gt; &lt;p&gt;This is a blocking call. Once called, Outlook shows a dialog to the user  asking username, password and domain name. Results won't be returned to  Transport until after the user clicks "OK" or "Cancel" in  the dialog.&lt;/p&gt; &lt;h3&gt;Domain name is truncated!&lt;/h3&gt; &lt;p&gt;This simple API works greatly in previous version of Pocket Outlook. However,  in the newer version, domain name is always truncated to the same size as that  of password. Below are some screen cuts with illustrations:&lt;/p&gt; &lt;p&gt;Screen 1: &lt;b&gt;RequestCredentials&lt;/b&gt;() is called. Domain name is "aa.com"  (6 characters), password is "12345"&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/320/TransportDemoPasswd12345.jpg" border="0" height="320" width="240" /&gt;&lt;/p&gt; &lt;p&gt;Screen 2: &lt;b&gt;RequestCredentials&lt;/b&gt;() returns with a new credential (in  parameter &lt;i&gt;ppcreds&lt;/i&gt;). Notice domain name is truncated to "aa.co". &lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/320/TransportDemoDomainTruncated.jpg" border="0" height="320" width="240" /&gt;&lt;/p&gt; &lt;p&gt;Screen 3: &lt;b&gt;RequestCredentials&lt;/b&gt;() is called again. Now parameter &lt;i&gt;ppcreds&lt;/i&gt;  is copied to &lt;i&gt;ppcredsSource.&lt;/i&gt;&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/320/TransportDemoDomainTruncatedReAsk.jpg" border="0" height="320" width="240" /&gt;&lt;/p&gt; &lt;p&gt;Screen 4: Let us revert the domain name back to "aa.com", but type  "123" as the password.&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/TransportDemoPasswd123DomainFull.jpg" border="0" height="320" width="240" /&gt;&lt;/p&gt; &lt;p&gt;Screen 5: &lt;b&gt;RequestCredentials&lt;/b&gt;() returns with another new credential.  Now the domain name is truncated to "aa."&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/TransportDemoDomainTruncatedMore.jpg" border="0" height="320" width="240" /&gt;&lt;/p&gt; &lt;h3&gt;Source code used&lt;/h3&gt; &lt;p&gt;The source code is adapted from TransportDemo, really seemingly simple and  innocent code.&lt;/p&gt; &lt;p&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;HRESULT CTransportSyncHandler::Connect(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwReserved,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;SYNCCREDENTIALS* pCredentials&lt;br /&gt;)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;HRESULT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; =&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;S_OK;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;SYNCCREDENTIALS *&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pCurrentCreds&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;=&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pCredentials;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;ULONG&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cTries&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; =&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;// The transport is no longer shut down&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;ASSERT(m_hEventShutdown != NULL);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_fShutDown = FALSE;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;ResetEvent(m_hEventShutdown);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;//while(TRUE)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;while(cTries &amp;lt;= 4) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Do we need to prompt for account info?&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(cTries || *pCurrentCreds-&amp;gt;pszPassword == L'\0') {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SYNCCREDENTIALS * pNewCreds = NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Make a request to the Inbox for logon credentials.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hr = m_pCallback-&amp;gt;RequestCredentials(m_pszProfile, pCurrentCreds, &amp;pNewCreds);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(FAILED(hr)) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Log an error...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!m_fShutDown) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LogErrorEvent(CEMAPI_E_NO_ACCOUNT_INFO, 0);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// pNewCreds now contains the new info from the user.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ASSERT(pNewCreds != NULL);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Check to see if 'pCurrentCreds' is *not* the ones passed in.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// If they are not, then we need to free them.&amp;nbsp;&amp;nbsp;&amp;nbsp; This will happen&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// if the user has been asked more than once for the password.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(pCurrentCreds != pCredentials) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_pCallback-&amp;gt;FreeMem(pCurrentCreds);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// what is the new credential&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TCHAR szInfo[1024];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; swprintf(szInfo, TEXT("After RequestCredentials&amp;gt;&amp;gt;\nUserName: %s\nPassword: %s\nDomain: %s"), pNewCreds-&amp;gt;pszUsername, pNewCreds-&amp;gt;pszPassword, pNewCreds-&amp;gt;pszDomain);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ALERT(szInfo);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pCurrentCreds = pNewCreds;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Now try to connect to the mail server&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // [ Omitted ]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = E_ACCESSDENIED;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // [ Assumed to return hr ]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(FAILED(hr)) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!m_fShutDown) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LogErrorEvent(hr, 0);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// retry instead&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(m_fShutDown) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hr = E_FAIL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Log in to the mail server&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SetStatusText(0/*IDS_TRANSPORT_CONNECTING*/);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // TODO:&amp;nbsp;&amp;nbsp;&amp;nbsp; Use an appropriate string resource&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // [ Omitted ]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // [ Assumed to return hr ]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // If the logon succeeded, we're done&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(SUCCEEDED(hr)) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // If we failed due to anything but authentication errors,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // log the error and bail out&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(hr != E_ACCESSDENIED) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Log an error back to the application if user didn't himself ask for shutdown&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!m_fShutDown) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LogErrorEvent(hr, 0);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // No success!&amp;nbsp;&amp;nbsp;&amp;nbsp; Need to hang up and ask the user for new&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // credentials.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ++cTries;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Disconnect from the mail server&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // [ Omitted ]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // [ Assumed to return hr ]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// while(TRUE)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(FAILED(hr)) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Disconnect from the mail server&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // [ Omitted ]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // [ Assumed to return hr ]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;return hr;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt; &lt;h3 align="left"&gt;Wrap Up&lt;/h3&gt; &lt;p align="left"&gt;Similar to &lt;a href="http://windowsmobilepro.blogspot.com/2006/04/pocket-outlook-woe-01-incoming-server.html"&gt;Outlook  Woe 1&lt;/a&gt;, I tried to disable the device security, or sign the transport DLL  using a certificate, but the problem persists.&lt;/p&gt; &lt;p align="left"&gt;This seems affecting not only Windows Mobile 5.0 device, but  also newer version of Pocket PC 2003 SE device, where the newer version of  Outlook is shipped. The old version of Pocket Outlook actually does NOT show  domain-name input box in the credential request dialog.&lt;/p&gt; &lt;p align="left"&gt;As a workaround, the user might be required to have a password  with the size not shorter than the domain name. For example,  "microsoft.com" employee must have a password with at least 13  characters. This sounds like a ridiculous requirement. So again the burden lies  on the shoulder of transport developers, who might remember the  "original" domain name in a place, and ignore the one passed by &lt;b&gt;IMailSyncCallback&lt;/b&gt;.  Hereby "original" domain name refers to the one passed by &lt;b&gt;IMailSyncCallback&lt;/b&gt;  the first time &lt;b&gt;RequestCredentials&lt;/b&gt;() is called. Alternatively, registry  can be used to store the domain information, rather than relying on Outlook.  However, this means that the user cannot change the domain settings via Outlook.&lt;/p&gt; &lt;p align="left"&gt;Also similar to &lt;a href="http://windowsmobilepro.blogspot.com/2006/04/pocket-outlook-woe-01-incoming-server.html"&gt;Outlook  Woe 1&lt;/a&gt;, the POP3 transport and IMAP4 transport shipped along with Pocket  Outlook seem immune to the issue. Could it because the TransportDemo code is not  doing the correct thing in its &lt;b&gt;Connect&lt;/b&gt;() method?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114620638350589318?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114620638350589318/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114620638350589318' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114620638350589318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114620638350589318'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/04/pocket-outlook-woe-02-domain-name-is.html' title='Pocket Outlook Woe 02: Domain name is truncated to the same size as password after calling IMailSyncCallBack :: RequestCredentials'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114611519746220617</id><published>2006-04-24T22:18:00.000-07:00</published><updated>2006-04-26T23:55:06.150-07:00</updated><title type='text'>Emulator Troubleshooting/Tip 02: Emulator Connecting to Internet (Internet Pass-through Connectivity) Issue</title><content type='html'>&lt;p&gt;&lt;b&gt;Emulator Troubleshooting/Tip 02: Emulator Connecting to Internet (Internet  Pass-through Connectivity) Issue&lt;/b&gt;&lt;/p&gt; &lt;p&gt;The post "&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/emulator-troubleshootingtip-01-to.html" title="Emulator Troubleshooting/Tip 01: To Cradle or Not to Cradle?"&gt;Emulator  Troubleshooting/Tip 01: To Cradle or Not to Cradle?&lt;/a&gt;" is mainly  regarding basic knowledge of the new Emulators. Essentially DMA channel is used  by Visual Studio and Remote Tools to communicate with the Emulator. It is really  NOT that necessary to always ActiveSync an emulator. &lt;/p&gt; &lt;h3&gt;Internet Pass-through Connectivity&lt;/h3&gt; &lt;p&gt;However, in a lot of cases, the emulator needs to be cradled and  ActiveSync'ed. One common requirement is that the emulator wants to use host  PC's networking capability, as if it were its own. You can use this feature to  perform tasks such as downloading POP3 or IMAP4 email messages, to connect  directly with a remote server, or to browse the Internet. This feature is called  "Internet Pass-Through". &lt;a href="file:///E:/Wireless/Docs/Leisure/windowsmobilepro.blogspot.com/2006/04/emulator-troubleshootingtip-01-to.html"&gt;My  post&lt;/a&gt; briefly talks about how to make it. &lt;a href="http://blogs.msdn.com/akhune/archive/2005/11/16/493329.aspx"&gt;An  excellent post&lt;/a&gt; from a Microsoft employee shows much detailed steps with  screen cuts.&lt;/p&gt; &lt;p&gt;However, the Microsoft post and a lot of other similar articles only mention  what to do in the emulator side. I want to emphasize here that you also need to  take care of the ActiveSync side. &lt;b&gt;ActiveSync needs to be instructed whether  the host computer is connected to "Work Network" or "The  Internet"&lt;/b&gt;. See below for a screen cut and how to do it:&lt;/p&gt; &lt;ol type="1"&gt;&lt;li&gt;Click &lt;b&gt;Connection Settings&lt;/b&gt;.   &lt;/li&gt;&lt;li&gt;Select &lt;b&gt;Open ActiveSync when my device connects&lt;/b&gt;.   &lt;/li&gt;&lt;li&gt;In the &lt;b&gt;This computer is connected to&lt;/b&gt; list, select a connection to      which this computer should connected when passing through ActiveSync.&lt;/li&gt;&lt;/ol&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/ActiveSyncInternetPassthrough.jpg" border="0" height="312" width="454" /&gt; &lt;/p&gt; &lt;p align="left"&gt;If you are not sure what network to use, choose  "Automatic". Hopefully ActiveSync can automatically find out which  network the host PC is connected and adjust emulator's setting accordingly. &lt;/p&gt; &lt;h3&gt;My Use Case&lt;/h3&gt; &lt;p&gt;I am not the lucky one that ActiveSync magically finds out the network to  use. It took me 30 minutes to figure out why all of a sudden the emulator in my home PC could not browse internet. Basically the ActiveSync setting is somewhat  mysteriously changed to either "Work Network" or "The  Internet". Here is my story:&lt;/p&gt; &lt;p&gt;I am using Comcast cable for internet access at home. Occasionally, when I  work from home, I run a VPN software in my home PC to place it into the  company's intranet. Once in the intranet, any external web site can only be  accessed via a proxy server.&lt;/p&gt; &lt;p&gt;Therefore, the emulator in my home PC needs to have internet access in two  distinct cases:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;My home PC is inside the corporate intranet. In the emulator side, a proxy      server must be configured. In ActiveSync side, "Work Network" or      "Automatic" must be used. The emulator cannot browse internet if      "The Internet" is chosen in ActiveSync.&lt;/li&gt;&lt;li&gt;After business hour, my home PC is directly connected to the public      internet. In the emulator side, no special action needs to be taken. In      ActiveSync side, "The Internet" or "Automatic" must be      chosen. Again, the emulator won't connect if "Work Network" is      chosen in ActiveSync.&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Wrap Up&lt;/h3&gt; &lt;p&gt;Next time when you fight with your emulator that cannot browse a public  site, not only check whether the emulator is cradled and ActiveSync'ed  successfully, but also check whether ActiveSync side is setup properly!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114611519746220617?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114611519746220617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114611519746220617' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114611519746220617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114611519746220617'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/04/emulator-troubleshootingtip-02.html' title='Emulator Troubleshooting/Tip 02: Emulator Connecting to Internet (Internet Pass-through Connectivity) Issue'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114603695089224227</id><published>2006-04-23T00:34:00.000-07:00</published><updated>2006-04-26T23:52:54.053-07:00</updated><title type='text'>Pocket Outlook Woe 01: incoming server and outgoing server are passed as two NULL pointers from Outlook to Transport</title><content type='html'>&lt;p&gt;&lt;b&gt;Pocket Outlook Woe 01: incoming server and outgoing server are passed as  two NULL pointers from Outlook to Transport&lt;/b&gt;&lt;/p&gt; &lt;p&gt;I've briefly mentioned how to write a transport plugin for Pocket Outlook in  two of my previous posts:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/02/transportdemo-sample-in-pocket-pc-50.html" title="TransportDemo sample in Pocket PC 5.0 SDK does not work? Check the solution here..."&gt;TransportDemo      sample in Pocket PC 5.0 SDK does not work? Check the solution here...&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/02/how-to-programmatically-query-mail.html" title="How to programmatically query mail account information in Windows Mobile devices, for example, incoming server and username?"&gt;How      to programmatically query mail account information in Windows Mobile      devices, for example, incoming server and username?&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;In Pocket Outlook, each mail account is associated with a MAPI store, and a  transport. A store is a store, for storing email folders and email messages. The  transport is responsible for synchronizing a mail account by talking to the  remote server. The main reference on CEMAPI can be found in MSDN's &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mobilesdk5/html/mob5oriMessagingAPIMAPI.asp"&gt;Windows  Mobile SDK Messaging section&lt;/a&gt;, and the main interface a transport must  implement is called &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mobilesdk5/html/mob5lrfimailsynchandler.asp"&gt;IMailSyncHandler&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;In Windows Mobile 5.0 devices (and some newer version of Pocket PC 2003 SE  devices), a newer version of Pocket Outlook is shipped. This updated version  seems bringing a couple of woes to transport developers. Today I am focusing on  the first one: Incoming server and outgoing server are passed by Outlook as two  NULL pointers to the transport.&lt;/p&gt; &lt;p&gt;The method involved is &lt;b&gt;Install&lt;/b&gt;, which is called by Outlook to install  the transport and then passes the configuration information to the transport.&lt;/p&gt; &lt;blockquote&gt;   &lt;b&gt;HRESULT Install (&lt;/b&gt; &lt;b&gt;LPCWSTR &lt;/b&gt;&lt;i&gt;pszProfileName&lt;/i&gt;&lt;b&gt;,&lt;/b&gt; &lt;b&gt;LPCWSTR    &lt;/b&gt;&lt;i&gt;pszIncomingServer&lt;/i&gt;&lt;b&gt;,&lt;/b&gt; &lt;b&gt;LPCWSTR &lt;/b&gt;&lt;i&gt;pszOutgoingServer&lt;/i&gt;&lt;b&gt;,&lt;/b&gt;    &lt;b&gt;GUID * &lt;/b&gt;&lt;i&gt;pidNetwork&lt;/i&gt; &lt;b&gt;);&lt;/b&gt; &lt;/blockquote&gt; &lt;dl&gt;&lt;dt&gt;&lt;i&gt;pszProfileName&lt;/i&gt;   &lt;/dt&gt;&lt;dd&gt;[in] Profile name of the transport instance, which is also the account      name.   &lt;/dd&gt;&lt;dt&gt;&lt;i&gt;pszIncomingServer&lt;/i&gt;   &lt;/dt&gt;&lt;dd&gt;[in] Incoming server name that the transport should use to synchronize the      e-mail into the device.   &lt;/dd&gt;&lt;dt&gt;&lt;i&gt;pszOutgoingServer&lt;/i&gt;   &lt;/dt&gt;&lt;dd&gt;[in] Outgoing server name that the transport should use to send outgoing      e-mails.&lt;/dd&gt;&lt;/dl&gt; &lt;p&gt;Incoming server and outgoing server can be either specified by the user who  create the account via Outlook's New Account Setup wizard, or created by the  developer using &lt;b&gt;DMProcessConfigXML&lt;/b&gt; and &lt;b&gt;EMAIL2 &lt;/b&gt;CSP. &lt;/p&gt; &lt;p&gt;I tested both cases, and found that two NULL pointers are always passed from  Outlook to the transport. The testing transport is the TransportDemo sample in  Windows Mobile SDK. In its &lt;b&gt;Install &lt;/b&gt;method, a dialog is used to display  two server strings passed by Outlook&lt;/p&gt; &lt;h3&gt;Case 1: TransportDemo1 is created by the user using Outlook's wizard&lt;/h3&gt; &lt;p&gt;In New Account Setup Wizard, typing the incoming mail server name and  outgoing mail server name.&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/TransportDemo1SetupServers.jpg" border="0" height="320" width="240" /&gt;&lt;/p&gt; &lt;p&gt;When the transport (TransportDemo) is loaded, two NULL pointers are passed  from Outlook.&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/TransportDemo1InstallNULL.jpg" border="0" height="320" width="240" /&gt;&lt;/p&gt; &lt;h3&gt;Case 2: TransportDemo2 is programmatically created using DMProcessConfigXML&lt;/h3&gt; &lt;p&gt;The account information can be queried back successfully, showing the two  server names correctly. Refer here for &lt;a href="http://windowsmobilepro.blogspot.com/2006/02/how-to-programmatically-query-mail.html" title="How to programmatically query mail account information in Windows Mobile devices, for example, incoming server and username?"&gt;how  to programmatically query mail account information in Windows Mobile devices,  for example, incoming server and username.&lt;/a&gt;&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/TransportDemo2QueryBack.jpg" border="0" height="320" width="240" /&gt;&lt;/p&gt; &lt;p align="left"&gt;Unfortunately, you'll still get two NULL pointers.&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/TransportDemo2InstallNULL.jpg" border="0" height="320" width="240" /&gt;&lt;/p&gt; &lt;h3 align="left"&gt;Wrap Up&lt;/h3&gt; &lt;p align="left"&gt;I tried to disable the device security, or sign the transport  DLL using a certificate, but the problem persists.&lt;/p&gt; &lt;p align="left"&gt;This seems affecting not only Windows Mobile 5.0 device, but  also newer version of Pocket PC 2003 SE device, where the newer version of  Outlook is shipped.&lt;/p&gt; &lt;p align="left"&gt;As a workaround, the transport developer might use registry to  store the sever information, rather than relying on Outlook. However, this means  that the user cannot change the server settings via Outlook.&lt;/p&gt; &lt;p align="left"&gt;The POP3 transport and IMAP4 transport shipped along with Pocket  Outlook seem immune to the issue. Could it because the TransportDemo code is too  simple and not implement necessary methods??&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114603695089224227?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114603695089224227/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114603695089224227' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114603695089224227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114603695089224227'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/04/pocket-outlook-woe-01-incoming-server.html' title='Pocket Outlook Woe 01: incoming server and outgoing server are passed as two NULL pointers from Outlook to Transport'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114595030413002741</id><published>2006-04-21T00:30:00.000-07:00</published><updated>2006-04-25T00:33:33.510-07:00</updated><title type='text'>Emulator Troubleshooting/Tip 01: To Cradle or Not to Cradle?</title><content type='html'>&lt;p&gt;&lt;b&gt;Emulator Troubleshooting/Tip 01: To Cradle or Not to Cradle?&lt;/b&gt;&lt;/p&gt; &lt;p&gt;Firstly, a quick introduction to the emulators shipped with Visual Studio  2005 (VS2005, and/or Windows Mobile 5.0 SDK). &lt;/p&gt; &lt;h3&gt;What is New in the emulators shipped with VS2005&lt;/h3&gt; &lt;p&gt;The 2005 emulator runs applications compiled for the ARM instruction set  (same as the physical device) and runs as a user-mode process. The emulators  work much faster than the previous generations that deal with X86 instruction  sets. Also the emulator loading and shutdown time reduce significantly.&lt;/p&gt; &lt;p&gt;The other big change is that VS2005 now provides a Direct Memory Access (DMA)  transport to communicate with the emulator. Surpassing the traditional TCP/IP  transport, the DMA transport is faster, does not rely on network connectivity or  other external factors, and provides deterministic connection and disconnection. &lt;/p&gt; &lt;h3&gt;Connect and Cradle Emulator&lt;/h3&gt; &lt;p&gt;The centralized place to interact with the emulators is the Device Emulator  Manager. To launch the Device Emulator using the Device Emulator Manager in  VS2005:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;On the Visual Studio &lt;b&gt;Tools&lt;/b&gt; menu, click &lt;b&gt;Device Emulator Manager&lt;/b&gt;.&lt;/li&gt;&lt;li&gt;In the &lt;b&gt;Device Emulator Manager&lt;/b&gt; window, right-click the emulator you      want to launch.&lt;/li&gt;&lt;li&gt;On the shortcut menu, click &lt;b&gt;Connect&lt;/b&gt;.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The following screen cut show that Pocket PC 2003 SE Emulator is connected.  Now VS2005 is able to deploy your program to the emulator and debug your program  as well. The Remote Tools (like remote registry editor, remote spy, remote file  explorer, and etc) can also work with the emulator. No, in such case, you do not  need to establish an ActiveSync connection to use the remote tools.&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/DEMConnect.jpg" border="0" height="300" width="420" /&gt;&lt;/p&gt; &lt;p&gt;Sometimes you may need to ActiveSync with an emulator, for example, you want  to use the "Mobile Device" shell namespace in your desktop PC's  explorer to access the emulator's file system, or you want to make the emulator  use the host PC's network connection. The way to establish an ActiveSync  connection changed significantly compared to the the previous development  environment (Visual Studio 2003/VS2003, Embedded Visual C++ 4/EVC4, and Pocket  PC 2003 SDK or Smartphone 2003 SDK). &lt;/p&gt; &lt;ul&gt;&lt;li&gt;Right click the already-connected emulator, then click &lt;b&gt;Cradle &lt;/b&gt;in      the popup menu. &lt;/li&gt;&lt;li&gt;Make sure ActiveSync is configured to allow &lt;b&gt;DMA &lt;/b&gt;connections via its      &lt;b&gt;Connection Setting&lt;/b&gt; dialog's "&lt;b&gt;Allow connections to one of the      following&lt;/b&gt;" option.&lt;/li&gt;&lt;li&gt;ActiveSync should then start as the emulator makes a connection to your      desktop computer. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The following screen cut shows that the Pocket PC 2003 SE emulator is  ActiveSync'ed.&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/DEMtoCradle.jpg" border="0" height="300" width="420" /&gt;&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/DEMCradled.jpg" border="0" height="300" width="420" /&gt;&lt;/p&gt; &lt;h3&gt;To Cradle or Not to Cradle &lt;/h3&gt; &lt;p&gt;If an emulator is successfully cradled, VS2005 and Remote Tools can either  treat the emulator as an Emulator, or as a Physical Device. For example, in  above screen cuts, Pocket PC 2003 SE Emulator is ActiveSync'ed. Now in VS2005 or  in Remote Tool's "Select a Windows CE Device" dialog, you can either  choose the Emulator as is, or choose "Pocket PC 2003 Device". Either  way, the emulator will be connected.&lt;/p&gt; &lt;p&gt;However, you'll see certain degree of performance penalty if the emulator is  cradled, compared to a non-cradled emulator. As mentioned above, VS2005 and  Remote Tools do not really need the emulator to be ActiveSync'ed. In case that  the emulator is not cradled, DMA transport is used. As the named implies, VS2005  or Remote Tool is directly accessing the emulator process' memory, much faster  and reliable. Using ActiveSync as the transport adds an unnecessary extra layer.&lt;/p&gt; &lt;p&gt;The other advantage to realize no-need-to-cradle-clarification is that you  can connect a Remote Tool to multiple Emulators simultaneously. ActiveSync  actually does not support connecting to multiple devices or emulators.&lt;/p&gt; &lt;h3&gt;Wrap Up&lt;/h3&gt; &lt;p&gt;"&lt;b&gt;To Cradle or Not to Cradle&lt;/b&gt;" only applies to Emulators. For  a physical device, you do need to cradle and ActiveSync it for VS2005 and Remote  Tools to work. Reason is simple. There is no such thing like "DMA" in  such a scenario, because the desktop PC and the pocket PC are living in two  worlds. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114595030413002741?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114595030413002741/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114595030413002741' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114595030413002741'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114595030413002741'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/04/emulator-troubleshootingtip-01-to.html' title='Emulator Troubleshooting/Tip 01: To Cradle or Not to Cradle?'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114525107883638827</id><published>2006-04-19T22:16:00.000-07:00</published><updated>2006-04-20T23:31:10.453-07:00</updated><title type='text'>Internal Use Spy: A nice hidden debugging tool for Pocket PC 2003 device and Pocket PC 5.0 device</title><content type='html'>&lt;p&gt;&lt;b&gt;Internal Use Spy: A nice hidden debugging tool for Pocket PC 2003 device and Pocket PC 5.0 device&lt;/b&gt;&lt;/p&gt; &lt;p&gt;On Apr. 13, 2006, I talked about &lt;a href="http://windowsmobilepro.blogspot.com/2006/04/remote-ce-spy-shipped-with-visual.html"&gt;the usage of Remote CE Spy and how to overcome the broken Remote CE Spy shipped with Visual Studio 2005&lt;/a&gt;. Specifically, the Remote Spy displays a list of the windows that are open on a target device. In a separate window, the tool displays information about the messages in the message queue for the selected window.&lt;/p&gt; &lt;p&gt;Remote CE Spy is a very powerful tool for any UI-related programming job.  However, the tool requires the target device must be ActiveSync'ed with the  desktop PC. What if you do not have access to a PC? With only the physical  device, can you discover similar information on the fly, like the window handle, class,  style, size, and etc?&lt;/p&gt;  &lt;p&gt;Recently when I was playing with my PPC6601 (2003 SE) device, I found such a  hidden  tool called "Internal Use Spy". The way to bring it up is like this:&lt;/p&gt;  &lt;ul&gt;&lt;li&gt;Press (and Hold) the Action key&lt;/li&gt;&lt;li&gt;Tap the top title bar where nothing is displayed (to the right of      title string, and to the left of notification icon)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;A dialog will popup, listing the current window's handle, style, title,  client area position and size. Further, it shows the handle of the parent  window, and offers a choice to further dump the properties of the parent window.  The following screen cut is for "Microphone AGC" applet in the  Control Panel Settings:&lt;/p&gt;  &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/320/InternalUseSpy.jpg" alt="Internal Use Spy Screen dump" border="0" height="320" width="240" /&gt;&lt;/p&gt; &lt;h3 align="left"&gt;Wrap Up&lt;/h3&gt; &lt;p align="left"&gt;I tested in my PPC6700 device, a Windows Mobile 5.0 device. It  also works. It seems both Pocket PC 2003 device and Pocket PC 5.0 device have  the hidden tool built-in.&lt;/p&gt; &lt;p align="left"&gt;The emulator does not expose the same. In the emulator,  supposedly one can press  and hold the PC's CTRL key to simulate the behavior of pressing and holding  Action key in real devices. However, the Internal Use Spy dialog simply does not  show up.&lt;/p&gt; &lt;p align="left"&gt;For a related post on the hidden trick without connecting the  device to a desktop PC, read "&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/how-to-launch-program-via-command-line.html"&gt;how  to launch a program via command line in Pocket PC 2003 device and Pocket PC 5.0  device&lt;/a&gt;".&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114525107883638827?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114525107883638827/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114525107883638827' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114525107883638827'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114525107883638827'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/04/internal-use-spy-nice-hidden-debugging.html' title='Internal Use Spy: A nice hidden debugging tool for Pocket PC 2003 device and Pocket PC 5.0 device'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114558332917270682</id><published>2006-04-17T18:34:00.000-07:00</published><updated>2006-04-30T10:56:40.243-07:00</updated><title type='text'>Using Camera API with only Embedded Visual C++ 4.0 (evc4): Sample code and EVC4 workspace download</title><content type='html'>&lt;p&gt;&lt;b&gt;Using Camera API with only Embedded Visual C++ 4.0 (evc4): Sample code and EVC4 workspace download&lt;/b&gt;&lt;/p&gt; &lt;p align="left"&gt;In my previous post, I talked about &lt;a href="http://windowsmobilepro.blogspot.com/2006/04/how-to-use-new-camera-api-in-windows.html"&gt;how to use the new Camera API in Windows Mobile 5.0 SDK with only Embedded Visual C++ 4.0 (evc4)&lt;/a&gt;. &lt;/p&gt; &lt;p align="left"&gt;You can &lt;a href="http://windowsmobilepro.home.comcast.net/CameraDemo.zip"&gt;download the EVC4 workspace here&lt;/a&gt;. The source code is written based on the &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mobilesdk5/html/mob5lrfSHCameraCaptureFn.asp"&gt;MSDN documentation on SHCameraCapture&lt;/a&gt;, which states:&lt;/p&gt; &lt;blockquote&gt;   &lt;p align="left"&gt;Application writers should be aware that &lt;b&gt;SHCameraCapture&lt;/b&gt;   function can cause the calling application to stop responding in cases where   the calling application is minimized and then reactivated while the call to &lt;b&gt;SHCameraCapture&lt;/b&gt;   function is still blocking.&lt;/p&gt; &lt;/blockquote&gt; &lt;p align="left"&gt;The sample code is written by copying the snippets in that MSDN documentation, although I do not really find such "stop responding" mischief using the "possible sequence of events". The program shows "Capture" and "Exit" in the bottom menu bar. Clicking the left soft key launches the camera capture dialog.  After clicking the Action key, the program captures videos for 15 seconds then ask for a place to save the video file.&lt;/p&gt; &lt;p align="left"&gt;Two gotchas:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;     &lt;p align="left"&gt;The MSDN documentation says the window class of camera     capture dialog is "Camera View". In my Sprint PPC6700 device, the     class name is actually "WCE_IA_Camera_Main" (read the source code     for a comment).   &lt;/p&gt;&lt;/li&gt;&lt;li&gt;     &lt;p align="left"&gt;The camera capture dialog still shows even after the program     is closed. The function "&lt;i&gt;CloseCameraDialog&lt;/i&gt;" is used to     close it before the program shuts down (read the source code for details) &lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p align="left"&gt;BTW, the tool to find out the window class is Remote CE Spy. The default Remote CE Spy shipped with VS2005 does not work well with Windows Mobile 5.0 device. Read "&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/remote-ce-spy-shipped-with-visual.html"&gt;Remote CE Spy shipped with Visual Studio 2005 fails to intercept windows messages&lt;/a&gt;" for a possible solution.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114558332917270682?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114558332917270682/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114558332917270682' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114558332917270682'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114558332917270682'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/04/using-camera-api-with-only-embedded.html' title='Using Camera API with only Embedded Visual C++ 4.0 (evc4): Sample code and EVC4 workspace download'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114551555713742788</id><published>2006-04-16T23:45:00.000-07:00</published><updated>2006-04-30T10:54:39.833-07:00</updated><title type='text'>How to use the new Camera API in Windows Mobile 5.0 SDK with only Embedded Visual C++ 4.0 (evc4)?</title><content type='html'>&lt;p&gt;&lt;b&gt;How to use the new Camera API in Windows Mobile 5.0 SDK with only Embedded Visual C++ 4.0 (evc4)?&lt;/b&gt;&lt;/p&gt; &lt;p align="left"&gt;Almost all up-to-date phones, PDAs, or handheld gadgets have an embedded camera, allow users to snap pictures or capture videos. Microsoft releases &lt;a href="http://msdn.microsoft.com/mobility/windowsmobile/howto/windowsmobile5/api/default.aspx#native"&gt;new APIs in Windows Mobile 5.0 SDK to help developers controlling the camera&lt;/a&gt;.&lt;/p&gt; &lt;blockquote&gt;   &lt;p align="left"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;b&gt;Camera Capture API&lt;/b&gt;&lt;br /&gt;  Camera enabled devices are extremely popular. With these devices being so   widely available, application developers now have the opportunity to   substantially enhance the user experience by integrating the capture of both   still and video images directly into their applications. To enable application   developers to easily provide this functionality, Windows Mobile 5.0 provides   the camera capture dialog. The unmanaged API is called &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mobilesdk5/html/mob5lrfSHCameraCaptureFn.asp"&gt;SHCameraCapture&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p align="left"&gt;The problem is that the only Visual Studio 2005 can work with Windows Mobile 5.0 SDK. What if you are still using the free Embedded Visual C++ 4 (EVC4), and you do not want to shed a cool $800 to get a copy of VS2005?&lt;/p&gt; &lt;p align="left"&gt;The solution is to use &lt;i&gt;LoadLibrary&lt;/i&gt; to load &lt;i&gt;aygshell.dll&lt;/i&gt;, get the entry point to &lt;i&gt;SHCameraCapture&lt;/i&gt;, then call that function by jumping to the entry point. The API anticipates a structure as the parameter, so you need to instruct EVC4 compiler to generate the parameter correctly by defining it yourself. Luckily all the members in the structure are primitive types or character arrays, so there is really not much hassle.&lt;/p&gt; &lt;p align="left"&gt;Below is the source code that you can copy and paste into your EVC4 source code. It uses &lt;i&gt;#ifdef _WIN32_WCE &lt;/i&gt;to make sure the code gets compiled for Pocket PC 2003 project or Smartphone 2003 project. The final executable can then be copied to a Pocket PC 5.0 device or Smartphone 5.0 device.&lt;/p&gt; &lt;p align="left"&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;#include &amp;lt;aygshell.h&amp;gt;&lt;br /&gt;#if _WIN32_WCE &amp;lt; 0x0500&lt;br /&gt;&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;// Flags for camera capture UI&lt;br /&gt;&lt;br /&gt;typedef enum {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;CAMERACAPTURE_MODE_STILL = 0,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;CAMERACAPTURE_MODE_VIDEOONLY,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;CAMERACAPTURE_MODE_VIDEOWITHAUDIO,&lt;br /&gt;} CAMERACAPTURE_MODE;&lt;br /&gt;&lt;br /&gt;typedef enum {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;CAMERACAPTURE_STILLQUALITY_DEFAULT = 0,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;CAMERACAPTURE_STILLQUALITY_LOW,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;CAMERACAPTURE_STILLQUALITY_NORMAL,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;CAMERACAPTURE_STILLQUALITY_HIGH,&lt;br /&gt;} CAMERACAPTURE_STILLQUALITY;&lt;br /&gt;&lt;br /&gt;typedef enum {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;CAMERACAPTURE_VIDEOTYPE_ALL = 0xFFFF,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;CAMERACAPTURE_VIDEOTYPE_STANDARD = 1,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;CAMERACAPTURE_VIDEOTYPE_MESSAGING = 2,&lt;br /&gt;} CAMERACAPTURE_VIDEOTYPES;&lt;br /&gt;&lt;br /&gt;typedef struct tagSHCAMERACAPTURE&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD&amp;nbsp;&amp;nbsp;&amp;nbsp;cbSize;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;HWND&amp;nbsp;&amp;nbsp;&amp;nbsp;hwndOwner;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;TCHAR&amp;nbsp;&amp;nbsp;&amp;nbsp;szFile[MAX_PATH];&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;LPCTSTR&amp;nbsp;&amp;nbsp;&amp;nbsp;pszInitialDir;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;LPCTSTR&amp;nbsp;&amp;nbsp;&amp;nbsp;pszDefaultFileName;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;LPCTSTR&amp;nbsp;&amp;nbsp;&amp;nbsp;pszTitle;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;CAMERACAPTURE_STILLQUALITY&amp;nbsp;&amp;nbsp;&amp;nbsp;StillQuality;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;CAMERACAPTURE_VIDEOTYPES&amp;nbsp;&amp;nbsp;&amp;nbsp;VideoTypes;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD&amp;nbsp;&amp;nbsp;&amp;nbsp;nResolutionWidth;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD&amp;nbsp;&amp;nbsp;&amp;nbsp;nResolutionHeight;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD&amp;nbsp;&amp;nbsp;&amp;nbsp;nVideoTimeLimit;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;CAMERACAPTURE_MODE&amp;nbsp;&amp;nbsp;&amp;nbsp;Mode;&lt;br /&gt;} SHCAMERACAPTURE, *PSHCAMERACAPTURE;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;HRESULT SHCameraCapture(PSHCAMERACAPTURE pshcc);&lt;br /&gt;&lt;br /&gt;typedef HRESULT (*fnSHCameraCapture)(PSHCAMERACAPTURE pshcc);&lt;br /&gt;&lt;br /&gt;HRESULT SHCameraCapture(PSHCAMERACAPTURE pshcc)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;HRESULT hr = S_OK;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;HINSTANCE hAygShell = LoadLibrary(TEXT("aygshell.dll"));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;fnSHCameraCapture funcSHCameraCapture = NULL;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!hAygShell) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;hr = HRESULT_FROM_WIN32(GetLastError());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;goto FuncExit;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;funcSHCameraCapture = (fnSHCameraCapture)GetProcAddress(hAygShell, TEXT("SHCameraCapture"));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!funcSHCameraCapture) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;hr = HRESULT_FROM_WIN32(GetLastError());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;goto FuncExit;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;// call the API now&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;hr = funcSHCameraCapture(pshcc);&lt;br /&gt;&lt;br /&gt;FuncExit:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (hAygShell) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;FreeLibrary(hAygShell);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;return hr;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;#endif&amp;nbsp;&amp;nbsp;&amp;nbsp;// faked one in 4.20/4.21 platform&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt; &lt;h3 align="left"&gt;Wrap Up&lt;/h3&gt; &lt;p&gt;You may use similar approach to access other new 5.0 APIs from within EVC4. You need to find out which DLL exports the API, and more importantly, you need to let EVC4 compiler correctly generate parameters to feed into those APIs, so inevitably you have to copy some header definitions from Windows Mobile 5.0 SDKs.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114551555713742788?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114551555713742788/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114551555713742788' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114551555713742788'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114551555713742788'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/04/how-to-use-new-camera-api-in-windows.html' title='How to use the new Camera API in Windows Mobile 5.0 SDK with only Embedded Visual C++ 4.0 (evc4)?'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114542948249207959</id><published>2006-04-13T23:42:00.000-07:00</published><updated>2006-04-19T00:06:37.133-07:00</updated><title type='text'>Remote CE Spy shipped with Visual Studio 2005 fails to intercept windows messages: Check the solution here!</title><content type='html'>&lt;p&gt;&lt;b&gt;Remote CE Spy shipped with Visual Studio 2005 fails to intercept windows messages: Check the solution here!&lt;/b&gt;&lt;/p&gt; &lt;p&gt;Remote CE Spy is Windows Mobile programmer's buddy if there is a need to inspect the windows currently opened in a Windows Mobile device, or intercept the messages sent to a particular window in real-time. It might not be useful if you are writing simple UI and know for sure what messages to process. However, if you need to find out what is going on with a program written by other people, need to inject messages into the message queue of a program (or to be technically right, a window), or want to find the ID of a window control, Remote CE Spy is an indispensable tool.&lt;/p&gt; &lt;p&gt;CE Spy shipped with Embedded Visual Tools 4 (along with Pocket PC 2003 SDK and Smartphone 2003 SDK) works perfectly, always able to list all the windows, and reliably capture the messages of any window's message queue. However, the one shipped with Visual Studio 2005 is broken. It might list all the windows, but sometimes it doesn't. Worse, when capturing messages sent to a particular window, it grossly misses messages.&lt;/p&gt; &lt;p&gt;Quite some users reported various issues and Microsoft acknowledged it:&lt;/p&gt;  &lt;ul&gt;&lt;li&gt;&lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=58908&amp;SiteID=1"&gt;http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=58908&amp;amp;SiteID=1&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=17401&amp;SiteID=1"&gt;http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=17401&amp;amp;SiteID=1&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=12630&amp;SiteID=1"&gt;http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=12630&amp;amp;SiteID=1&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=319056&amp;SiteID=1"&gt;http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=319056&amp;amp;SiteID=1&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://groups.google.com/group/microsoft.public.pocketpc.developer/browse_thread/thread/13dc59c942299c34/2c31c0c768f21722"&gt;http://groups.google.com/group/microsoft.public.pocketpc.developer/browse_thread&lt;br /&gt; /thread/13dc59c942299c34/2c31c0c768f21722&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://groups.google.com/group/microsoft.public.pocketpc.developer/browse_thread/thread/2ca5adc86877ca3a/c4e504353719e397"&gt;http://groups.google.com/group/microsoft.public.pocketpc.developer/browse_thread/&lt;br /&gt; thread/2ca5adc86877ca3a/c4e504353719e397&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://groups.google.com/group/microsoft.public.pocketpc.developer/browse_thread/thread/3eabee13724fe80d/0f9e22d7c69e0b16"&gt;http://groups.google.com/group/microsoft.public.pocketpc.developer/browse_thread/&lt;br /&gt; thread/3eabee13724fe80d/0f9e22d7c69e0b16&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://groups.google.com/group/microsoft.public.pocketpc.developer/browse_thread/thread/6705c8793e6f4e51/340654e349c75a6f"&gt;http://groups.google.com/group/microsoft.public.pocketpc.developer/browse_thread/&lt;br /&gt; thread/6705c8793e6f4e51/340654e349c75a6f&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://groups.google.com/group/microsoft.public.dotnet.framework.compactframework/browse_thread/thread/3b51d271fa8c7583/b07ff4a4696d8185"&gt;http://groups.google.com/group/microsoft.public.dotnet.framework.compactframework/&lt;br /&gt; browse_thread/thread/3b51d271fa8c7583/b07ff4a4696d8185&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Basically those posts are saying that CE Spy is broken in Visual Studio Beta  2. I also found it out when I was using Beta 2. The real trouble is that I am  using the RTM version of Visual Studio 2005 (8.0.50727.42, see below). CE Spy  still missed capturing messages.&lt;/p&gt;  &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/VS2005Version.jpg" border="0" height="95" width="288" /&gt;&lt;/p&gt; &lt;p&gt;I did a search on my hard drive, and found three version of cespy under "&lt;i&gt;\Program Files&lt;/i&gt;". Looks like one of them can work with Windows Mobile 5.0 device. &lt;/p&gt; &lt;h3&gt;Version 5.0.1.1400 works!&lt;/h3&gt; &lt;p&gt;The following one works without any issue:&lt;/p&gt; &lt;p&gt;&lt;i&gt;C:\Program Files\Common Files\Microsoft Shared\Windows CE Tools\Platman\bin\wce500\cespy.exe&lt;/i&gt;&lt;/p&gt; &lt;p&gt; The catch is: After 5.0 device is ActiveSync'ed,  this tool won't list Pocket PC 5.0 as a target platform. Just simply choose  Pocket PC 2003, the tool can make the connection, list windows and intercept  messages correctly!&lt;/p&gt;  &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/CESpy5.0.1.jpg" border="0" height="502" width="454" /&gt;&lt;/p&gt; &lt;p align="center"&gt;Version 5.0.1.1400&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/CESpy5.0.1_Connect2003.jpg" border="0" height="424" width="382" /&gt;&lt;/p&gt; &lt;p align="left"&gt;The window below shows the messages capture by ceSpy.exe  5.0.1.1400 when I clicked the "Send/Receive" menu item of Pocket  Outlook. It reports 12 messages. Keep reading on, and you'll be surprised how many  messages the "broken" spy is reporting.&lt;/p&gt;  &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/CESpy5.0.1_AllMessages.jpg" border="0" height="294" width="639" /&gt;&lt;/p&gt; &lt;h3&gt;Version 5.1.1651.0 (shipped with Visual Studio 2005 RTM and appearing under the start menu "&lt;i&gt;Visual Studio Remote Tools =&gt; Remote Spy&lt;/i&gt;" does not work&lt;/h3&gt; &lt;p&gt;Version 5.1.1651.0 seems to be the on shipped with Visual Studio 2005 and is  put under start menu "&lt;i&gt;Visual Studio Remote Tools =&gt; Remote Spy&lt;/i&gt;":&lt;/p&gt; &lt;p&gt;&lt;i&gt;C:\Program Files\CE Remote Tools\5.01\bin\ccspy.exe (Notice the name is  called ccspy.exe, not cespy.exe)&lt;/i&gt;&lt;/p&gt; &lt;p&gt; It has no problem connecting to 5.0 device, but messages are grossly missing. Do  not use it!&lt;/p&gt;  &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/CESpy5.1.1651.0.jpg" border="0" height="502" width="454" /&gt;&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/CESpy5.1.1651.0_Connect5.0.jpg" border="0" height="424" width="382" /&gt;&lt;/p&gt; &lt;p align="left"&gt;The window below shows the messages capture by ccSpy.exe when I clicked the "Send/Receive" menu item of Pocket Outlook. Only two messages are captured. Compared to the messages intercepted by the good version 5.0.1.1400. This guy fails to report 10 messages!&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/CESpy5.1.1651.0_MissingMessages.jpg" border="0" height="142" width="609" /&gt;&lt;/p&gt; &lt;h3&gt;Version 4.10.1.908 (shipped with Embedded Visual Tools) does not work with 5.0 device, but is the ideal choice to work with 2003 device&lt;/h3&gt; &lt;p&gt;The one installed with Embedded Visual Tools does not work against Windows  Mobile 5.0 device:&lt;/p&gt; &lt;p&gt;&lt;i&gt;C:\Program Files\Common Files\Microsoft Shared\Windows CE Tools\Platman\bin&lt;/i&gt;&lt;/p&gt; &lt;p&gt; This is anticipated, as it is supposed to work with Pocket PC  2003 device and Smartphone 2003 device.&lt;/p&gt;  &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/CESpy4.10.1.jpg" border="0" height="502" width="454" /&gt;&lt;/p&gt; &lt;p&gt;If you ActiveSync'ed a device and try connect, you will get the following error message.&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/CESpy4.10.1_CannotConnect.jpg" border="0" height="128" width="358" /&gt;&lt;/p&gt; &lt;p align="center"&gt; &lt;/p&gt; &lt;h3 align="left"&gt;Wrap Up&lt;/h3&gt; &lt;p&gt;When you need to use Remote CE Spy to watch windows or messages in a Pocket PC 5.0 device or Smartphone 5.0 device, do not use the one put into the start menu by Visual Studio 2005. Instead, search your hard drive, and locate the one with version 5.0.1.1400.&lt;/p&gt; &lt;p&gt;Please do not  ask me why if you cannot find the good guy in your hard drive. I  have no idea why I have two different 5.0 versions of them.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114542948249207959?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114542948249207959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114542948249207959' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114542948249207959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114542948249207959'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/04/remote-ce-spy-shipped-with-visual.html' title='Remote CE Spy shipped with Visual Studio 2005 fails to intercept windows messages: Check the solution here!'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114515311559247228</id><published>2006-04-11T18:55:00.000-07:00</published><updated>2006-04-16T12:44:42.523-07:00</updated><title type='text'>How to launch  a program via command line in Pocket PC 2003 device and Pocket PC 5.0 device?</title><content type='html'>&lt;p&gt;&lt;b&gt;How to launch  a program via command line in Pocket PC 2003 device  and Pocket PC 5.0 device?&lt;/b&gt;&lt;/p&gt; &lt;p&gt;As you may have already known, Pocket PC does not have a shell (unless you  want to install one), so there is no easy way to launch a program by typing in  command line. Daily average user may not have such requirement. A developer,  especially a Java developer, may consider it a nice-to-have feature. Java  program is normally launched in the following format:&lt;/p&gt; &lt;blockquote&gt;   &lt;p&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&amp;lt;jvm_executable&amp;gt; [jvm_argument|jvm_argument] &amp;lt;main_class_name&amp;gt; [program_argument|program_argument]&lt;/span&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;The command line is usually long. Worse, for debugging purpose, you may need  to feed different arguments into your program.&lt;/p&gt; &lt;h3&gt;If the device is connected to desktop PC via ActiveSync&lt;/h3&gt; &lt;p&gt;If you have setup your development environment and connect the device to your  desktop via ActiveSync, the IDE will take care the steps to remote launch a  program. &lt;/p&gt; &lt;p&gt;You can also install &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=74473fd6-1dcc-47aa-ab28-6a2b006edfe9&amp;amp;DisplayLang=en"&gt;Windows  Mobile Developer Power Toys&lt;/a&gt;, which packages a few useful tools for  developers:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;b&gt;&lt;i&gt;Emulator ActiveSync Connection Tool &lt;/i&gt;&lt;/b&gt; - Allows Activesync to connect to your Emulator session from Visual Studio .NET 2003.&lt;/li&gt;&lt;li&gt;&lt;b&gt;&lt;i&gt; ActiveSync Remote Display &lt;/i&gt;&lt;/b&gt; - Display Pocket PC applications on your desktop or laptop without needing any device side configuration.&lt;/li&gt;&lt;li&gt;&lt;b&gt;&lt;i&gt; CECopy &lt;/i&gt;&lt;/b&gt; - Command line tool for copying files to the device currently connected to desktop ActiveSync.&lt;/li&gt;&lt;li&gt;&lt;b&gt;&lt;i&gt; Convert PPC DAT to SP XML &lt;/i&gt;&lt;/b&gt; - Command line tool for generating Smartphone CABWizSP XML docs from existing Pocket PC CAB files.&lt;/li&gt;&lt;li&gt;&lt;b&gt;&lt;i&gt; Hopper &lt;/i&gt;&lt;/b&gt; - User input stress simulator.&lt;/li&gt;&lt;li&gt;&lt;b&gt;&lt;i&gt; JShell &lt;/i&gt;&lt;/b&gt; - UI version of the Platform Builder Target Control Window.&lt;/li&gt;&lt;li&gt;&lt;b&gt;&lt;i&gt; PPC Command Shell &lt;/i&gt;&lt;/b&gt; - Command shell for the Pocket PC 2003 device.&lt;/li&gt;&lt;li&gt;&lt;b&gt;&lt;i&gt; RAPI Debug &lt;/i&gt;&lt;/b&gt; - Displays detailed information about currently running processes.&lt;/li&gt;&lt;li&gt;&lt;b&gt;&lt;i&gt; RAPI Start &lt;/i&gt;&lt;/b&gt; - Command line tool to remotely start an application on your Pocket PC from your desktop.&lt;/li&gt;&lt;li&gt;&lt;b&gt;&lt;i&gt; TypeIt &lt;/i&gt;&lt;/b&gt; - Send characters/strings to the Smartphone 2003 Emulator via ActiveSync.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Among them, &lt;b&gt;&lt;i&gt;RAPIStart&lt;/i&gt;&lt;/b&gt; and &lt;b&gt;&lt;i&gt;PPC Command Shell &lt;/i&gt;&lt;/b&gt;can  be used for remotely launching an application via command line.&lt;/p&gt; &lt;h3&gt;What if the device is not connected to desktop PC, for example, I am outside  my office&lt;/h3&gt; &lt;p&gt;The above tools requires the Pocket PC to be connected to a desktop PC via  ActiveSync. What if you do not have access to a PC? You can try the  following: &lt;/p&gt; &lt;ul&gt;&lt;li&gt;Go to Today screen (the home screen)&lt;/li&gt;&lt;li&gt;Press (and Hold) the Action key&lt;/li&gt;&lt;li&gt;Tap the position where the current time is displayed in the title bar&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;A menu pops up with two items: &lt;i&gt;Run &lt;/i&gt;and &lt;i&gt;Clock&lt;/i&gt;. Click &lt;i&gt;Run&lt;/i&gt;,  you will get a dialog asking for the program name and arguments. &lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/RunClock.jpg" border="0" height="320" width="240" /&gt;  &lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/runPIE.jpg" border="0" height="320" width="240" /&gt;&lt;/p&gt; &lt;p align="left"&gt;It is for sure a painful experience to type a long command line  in the Pocket PC. You can first write down the command line in a Word Mobile  file, then do a copy and paste into the &lt;i&gt;Run &lt;/i&gt;dialog. For varying  arguments, just do copy and paste then make minor modifications.&lt;/p&gt; &lt;p align="left"&gt;In the emulator you can achieve the same, but you need to press  and hold your PC's CTRL key to simulate the behvaior of pressing and holding  Action key in real devices. See &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/guide_ppc/html/ppc_intro_to_the_ce_emulator_jfcm.asp"&gt;Emulator  Keyboard Shortcuts&lt;/a&gt; for details.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114515311559247228?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114515311559247228/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114515311559247228' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114515311559247228'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114515311559247228'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/04/how-to-launch-program-via-command-line.html' title='How to launch  a program via command line in Pocket PC 2003 device and Pocket PC 5.0 device?'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114508373440912295</id><published>2006-04-09T23:46:00.000-07:00</published><updated>2006-04-16T22:39:10.663-07:00</updated><title type='text'>Pocket PC Power Management Series 10: A Better Way to Catch when the Device Wakes Up - Multi-Thread Code with Visual Studio 2005 Solution Download</title><content type='html'>&lt;p&gt;&lt;b&gt;Pocket PC Power Management Series 10: A Better Way to Catch when the  Device Wakes Up - Multi-Thread Code with Visual Studio 2005 Solution Download&lt;/b&gt;&lt;/p&gt; &lt;p&gt;In &lt;a href="http://windowsmobilepro.blogspot.com/2005/11/pocket-pc-power-management-series-4.html"&gt;Pocket  PC Power Management Series 4: A Better Way to Catch when the Device Wakes Up&lt;/a&gt;,  I present a nice way to catch when the device wakes up. The sample code use &lt;i&gt;CeSetUserNotificationEx&lt;/i&gt;  to register a named event; when Windows CE OS wakes up, OS fires the event. The  code has only one thread, calling &lt;i&gt;MsgWaitForMultipleObjectsEx&lt;/i&gt; to both  listen to the wakeup event, and process windows message queue. As warned at the  end of that post, the single thread might be busy thus missing wakeup events. &lt;/p&gt; &lt;p&gt;Some readers mailed me wondering whether I can provide a fully-functional  sample code with two threads such that wakeup event can be always reliably  caught. A reader also left a comment asking for the two-thread code. Here I am  :)&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.home.comcast.net/WakeupDemo2.zip"&gt;Visual      Studio 2005 solution download&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.home.comcast.net/wakeupdemo2.exe"&gt;Pocket      PC executable file download&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The VS2005 solution is a Zip file. Extracting it you'll get .sln, .vcproj and  source code. Project settings cover Pocket PC 2003 platform and Pocket PC 5.0  platform. For PPC2003 platform, &lt;a href="http://windowsmobilepro.blogspot.com/2005/08/manually-migrate-embedded-visual-c.html"&gt;secchk.lib  and ccrtrtti.lib&lt;/a&gt; are added.&lt;/p&gt; &lt;p&gt;The executable can be run on both Pocket PC 2003 device and Pocket PC 5.0  device. You can use your Pocket IE to download the executable file directly into  your device, then run it there. &lt;/p&gt; &lt;p&gt;This is a screen cut when the program runs. All windows messages posted to  the main windows (along with the timestamp) are logged to the screen. Besides,  any wakeup event (along with the timestamp when the event is fired) are also  logged to the screen.&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://photos1.blogger.com/blogger/5783/1371/1600/wakeupdemo2.jpg" border="0" height="525" width="340" /&gt;&lt;/p&gt; &lt;p&gt;Below is a quick walkthrough of the source code:&lt;/p&gt; &lt;p&gt;&lt;b&gt;The thread that is dedicated to listening to the wakeup signal. &lt;/b&gt;Notice  it calls &lt;i&gt;WaitForMultipleObjects &lt;/i&gt;to actually listen to two events, the  other one being the shutdown signal. This also demonstrates how to gracefully  shutdown a thread without relying on a global boolean that the thread  periodically polling against.&lt;/p&gt; &lt;p&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;br /&gt;static DWORD WakeupEventListener(LPVOID lpData)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;TCHAR szBuf[256];&lt;br /&gt;&amp;nbsp;&amp;nbsp;PEVENTHANDLES pEventHandles = (PEVENTHANDLES)lpData;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;while (TRUE) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ResetEvent(pEventHandles-&amp;gt;hWakeupEvent);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DWORD dwResult = WaitForMultipleObjects(2, (HANDLE*)pEventHandles, FALSE, INFINITE);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (WAIT_OBJECT_0 == dwResult) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_tcscpy(szBuf, TEXT("Wakeup at "));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FormatCurrentTime(szBuf+_tcslen(szBuf));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_tcscat(szBuf, TEXT("\r\n\r\n"));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;OutputString(szBuf);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else if (WAIT_OBJECT_0+1 == dwResult) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// WAIT_ABANDONED and WAIT_FAILED&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Abondoned is not possible, failed most probably means the Handle is closed&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (WAIT_FAILED == dwResult) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ... do something error processing&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return S_OK;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;b&gt;Start and stop the wakeup event listener thread.&lt;/b&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;br /&gt;static HRESULT StartWakeupEventListener(const PEVENTHANDLES pEventHandles, HANDLE&amp; hThread)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;DWORD dwDummy = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;hThread = CreateThread(NULL, 0, WakeupEventListener, (LPVOID)pEventHandles, 0, &amp;amp;dwDummy);&lt;br /&gt;&amp;nbsp;&amp;nbsp;// need to error handling if thread creation failed&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return S_OK;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static HRESULT StopWakeupEventListener(const PEVENTHANDLES pEventHandles, HANDLE&amp; hThread)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;DWORD dwMilliSec = 2000;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (hThread) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PulseEvent(pEventHandles-&amp;gt;hThreadStop);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DWORD dwResult = WaitForSingleObject(hThread, dwMilliSec);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (WAIT_OBJECT_0 != dwResult) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// error or timeout. terminate the thread anyway&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TerminateThread(hThread, -1);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CloseHandle(hThread);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hThread = NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return S_OK;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;b&gt;Main logic during program starts up:&lt;/b&gt;&lt;/p&gt; &lt;ul&gt;&lt;li&gt;to create the wakeup event&lt;/li&gt;&lt;li&gt;to create shutdown signal&lt;/li&gt;&lt;li&gt;to start the wakeup event listener thread&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;b&gt;and before the program quits:&lt;/b&gt;&lt;/p&gt; &lt;ul&gt;&lt;li&gt;to stop the wakeup event listener thread,&lt;/li&gt;&lt;li&gt;to destroy the wakeup event&lt;/li&gt;&lt;li&gt;to destroy the shutdown signal&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;HRESULT hr = ClearWakeupNotification(g_szEventName);&lt;br /&gt;&amp;nbsp;&amp;nbsp;hr = AddWakeupNotification(g_szEventName);&lt;br /&gt;&amp;nbsp;&amp;nbsp;HANDLE hWakeupEvent = CreateEvent(NULL, TRUE, FALSE, g_szEventName);&lt;br /&gt;&amp;nbsp;&amp;nbsp;HANDLE hThreadStopEvent = CreateEvent(NULL, TRUE, FALSE, TEXT("ThreadStop"));&lt;br /&gt;&amp;nbsp;&amp;nbsp;EVENTHANDLES eventHandles = {hWakeupEvent, hThreadStopEvent};&lt;br /&gt;&amp;nbsp;&amp;nbsp;HANDLE hWakeupEventListenerThread = NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;hr = StartWakeupEventListener(&amp;eventHandles, hWakeupEventListenerThread);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// ..........&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;hr = StopWakeupEventListener(&amp;eventHandles, hWakeupEventListenerThread);&lt;br /&gt;&amp;nbsp;&amp;nbsp;// thread handle already closed&lt;br /&gt;&amp;nbsp;&amp;nbsp;hr = ClearWakeupNotification(g_szEventName);&lt;br /&gt;&amp;nbsp;&amp;nbsp;CloseHandle(hWakeupEvent);&lt;br /&gt;&amp;nbsp;&amp;nbsp;CloseHandle(hThreadStopEvent);&lt;br /&gt;}&lt;/span&gt;&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt; &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BPower%20Management%5D%22"&gt;[Power Management]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114508373440912295?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114508373440912295/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114508373440912295' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114508373440912295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114508373440912295'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/04/pocket-pc-power-management-series-10.html' title='Pocket PC Power Management Series 10: A Better Way to Catch when the Device Wakes Up - Multi-Thread Code with Visual Studio 2005 Solution Download'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114499975765249974</id><published>2006-04-06T00:27:00.000-07:00</published><updated>2006-04-14T00:29:17.666-07:00</updated><title type='text'>Extreme Makeover - How to rescue a Pocket PC with partially-damaged display screen</title><content type='html'>&lt;p&gt;&lt;b&gt;Extreme Makeover - How to rescue a Pocket PC with partially-damaged  display screen&lt;/b&gt;&lt;/p&gt; &lt;p&gt;Pocket PC is a fragile device. Display screen is Achilles' heel, susceptible  to scratches. Worse, if the device is dropped on the floor or ground, the screen  may be partially damaged (or completely broken, if that day is really not your  day). My officemate actually successfully destroyed the screen of an iPAQ 4155  device.&lt;/p&gt; &lt;p&gt;Besides the obvious choice of trashing the device, or sending it for repair,  can we somewhat DIY and still make use of it? I actually do not have the chance  myself, but being able to help an unlucky guy who posted a question in a  newsgroup:&lt;/p&gt; &lt;blockquote&gt;   &lt;p&gt;My touchscreen is a little damaged. After an accidental hard reset it is    not possible to go successfully the adjust routine through. I can't start    windows mobile (2003). Is there a possibility to start windows and avoid the    adjust procedure?&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;His screen was not completely broken, but he could not use the device,  because there was no way he could pass the "screen align" procedure  after a hard-reset. My first thought was like: If he could not pass the  procedure, why not forcibly kill it? The calibration data is stored under a  predefine registry key, then he could manually populate the registry himself. &lt;/p&gt; &lt;h3&gt;What tools?&lt;/h3&gt; &lt;p&gt;The tools are not hard to find, just remote process viewer and remote  regeditor, which are shipped along with Microsoft Embedded Tools (free) or  Visual Studio (common). The catch is ActiveSync must be up and running for the  remote tools to be able to connect to the device. This should not the a problem,  as the ActiveSync components should be more close to OS than the calibration  process.&lt;/p&gt; &lt;h3&gt;What registry key?&lt;/h3&gt; &lt;p&gt;The registry key is not publicly documented, and I do not think either  Microsoft or OEMs have any reason to document it. So the correct way to locate  the registry key is to find another device with the same model, do a search,  then copy the values and names. In my Sprint PPC6601 device, the key is &lt;i&gt;HKLM\HARDWARE\DEVICEMAP\TOUCH&lt;/i&gt;,  and value name is&lt;br /&gt;&lt;i&gt;CalibrationData&lt;/i&gt;, with value data "&lt;i&gt;507,497 150,763 153,230 886,241  871,767&lt;/i&gt;".&lt;/p&gt; &lt;p&gt;The guy followed my suggestion, managed to kill the calibration program and  populated the registry key. He also contributed another interesting value under  that key:&lt;/p&gt; &lt;blockquote&gt;   &lt;p&gt;&lt;i&gt;"MaxCalError"=dword:50&lt;/i&gt; - for less sensibility and it    works.&lt;/p&gt; &lt;/blockquote&gt; &lt;h3&gt;Which process to kill?&lt;/h3&gt; &lt;p&gt;The final question is how to know which process is showing the "screen  align" window. You can guess from the processes listed by remote process  viewer. A more rational approach needs another remote tool: the remote spy,  which shows all windows in the device. You can easily locate the "screen  align" window from the windows captured by remote spy, find which process  ID owns the window, then switch to remote process viwer to locate the process.&lt;/p&gt; &lt;p&gt;&lt;a href="http://http//groups.google.com/group/microsoft.public.pocketpc.developer/browse_thread/thread/d0731581389da268/b4e4fa96504794fd"&gt;Read  the whole story here&lt;/a&gt;.&lt;/p&gt; &lt;h3&gt;Wrap Up&lt;/h3&gt; &lt;p&gt;There must be a way for Shell to decide not to show the touch screen  calibration window upon rebooting. Most probably such information is stored  under a predefined registry key. If so, there is really no need to kill the  "align screen" window. Instead, using remote regeditor to populate  some values is sufficient to rescue your device.&lt;/p&gt; &lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114499975765249974?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114499975765249974/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114499975765249974' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114499975765249974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114499975765249974'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/04/extreme-makeover-how-to-rescue-pocket.html' title='Extreme Makeover - How to rescue a Pocket PC with partially-damaged display screen'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114482729459381904</id><published>2006-04-03T00:33:00.000-07:00</published><updated>2006-04-12T00:36:37.346-07:00</updated><title type='text'>Windows Mobile 5.0 New MAPI Functions Linker Error LNK2019 / LNK2001</title><content type='html'>&lt;p&gt;&lt;b&gt;Windows Mobile 5.0 New MAPI Functions Linker Error LNK2019 / LNK2001&lt;br /&gt;&lt;/b&gt;&lt;/p&gt; &lt;p&gt;In Windows Mobile 5.0, a few new MAPI functions are exposed, namely:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;i&gt;MailComposeMessage&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;MailDisplayMessage&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;MailSwitchToAccount&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;MailSwitchToFolder&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;MailSyncMessages&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;If you have worked on MAPI, you may notice these functions are not really  that much MAPI related. They are more like Outlook oriented, to facilitate  developers to better control Outlooks' UI and built in forms. For example, &lt;i&gt;MailComposeMessage&lt;/i&gt;  brings up the form to compose an outgoing message, and &lt;i&gt;MailDisplayMessage&lt;/i&gt;  brings up the form to view a message. I guess the reason that Microsoft exposes  these APIs is to help developers make use of Outlook in a very high level, not  in the low level of MAPI coding.&lt;/p&gt; &lt;p&gt;I do like the two functions: &lt;i&gt;MailSwitchToAccount&lt;/i&gt; and &lt;i&gt;MailSyncMessages&lt;/i&gt;,  as I need them for my customized transport. However, as soon as I add them to my  code, I get a very puzzling linker error:&lt;/p&gt; &lt;blockquote&gt;   &lt;p&gt;&lt;i&gt;error LNK2019: unresolved external symbol "long __cdecl    MailSwitchToAccount(wchar_t const *,unsigned long)" (?MailSwitchToAccount@@YAJPB_WK@Z)    referenced in function _Sync&lt;/i&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;The lib file "&lt;i&gt;cemapi.lib&lt;/i&gt;" is already added to the project's  Additional Dependencies, otherwise other MAPI-related code won't even link. So  the only reason is because mangled function name generated by the compiler does  not match the one in the lib.&lt;/p&gt; &lt;p&gt;The function is declared as:&lt;/p&gt; &lt;blockquote&gt;   &lt;p&gt;&lt;b&gt;HRESULT MailSwitchToAccount(&lt;/b&gt; &lt;b&gt;LPCTSTR &lt;/b&gt;&lt;i&gt;&lt;a class="synParam" onclick="showTip(this)" href="http://www.blogger.com/post-create.do"&gt;pszAccount&lt;/a&gt;&lt;/i&gt;&lt;b&gt;,    DWORD &lt;/b&gt;&lt;i&gt;&lt;a class="synParam" onclick="showTip(this)" href="http://www.blogger.com/post-create.do"&gt;dwFlags&lt;/a&gt;&lt;/i&gt; &lt;b&gt;);&lt;/b&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;I decided to trace down to the root, so I did a "&lt;i&gt;dumpbin /exports  cemapi.lib&lt;/i&gt;" to see what name and signature should the compiler generate  to appease the linker:&lt;/p&gt; &lt;blockquote&gt;   &lt;p&gt;&lt;i&gt;?MailSwitchToAccount@@YAJPBGK@Z (long __cdecl    MailSwitchToAccount(unsigned short const *,unsigned long))&lt;/i&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Aha! Do you, the reader, find the difference? Yes the mangled function names  do not match, which is why the linker is not happy. But pay closer attention to  the first parameter. In the source code, it is declared as &lt;i&gt;LCPTSTR&lt;/i&gt;. My  compiler compiles it to "&lt;i&gt;wchar_t const *&lt;/i&gt;", but the compiler  building the &lt;i&gt;cemapi.lib&lt;/i&gt; makes it to "&lt;i&gt;unsigned short const *&lt;/i&gt;"!&lt;/p&gt; &lt;p&gt;So here involves a change: &lt;b&gt;Treat wchar_t as built-in type&lt;/b&gt;. VS2005  compiler changed the behavior how wchar_t is handled. The previous versions  treats &lt;i&gt;wchar_t&lt;/i&gt; as &lt;i&gt;unsgined short &lt;/i&gt;(via Macro include), but the new  compiler in VS2005 treats &lt;i&gt;wchar_t&lt;/i&gt; as a built-in type, which is, of  course, just &lt;i&gt;wchar_t &lt;/i&gt;itself. &lt;/p&gt; &lt;p&gt;Apparently the people who built &lt;i&gt;cemapi.lib &lt;/i&gt;turned the option off,  which IMHO, was not a wise thing to do, as these APIs will be shipped as part of  Windows Mobile 5.0 SDK, and will be used only in Visual Studio 2005 environment  anyway.&lt;/p&gt; &lt;p&gt;To fix the issue is easy:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;Open the project's &lt;b&gt;Property Pages &lt;/b&gt;dialog box. &lt;/li&gt;&lt;li&gt;Click the &lt;b&gt;C/C++&lt;/b&gt; folder.&lt;/li&gt;&lt;li&gt;Click the &lt;b&gt;Language &lt;/b&gt;property page.&lt;/li&gt;&lt;li&gt;Modify the &lt;b&gt;Treat wchar_t as Built-in Type &lt;/b&gt;property.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;There is also a very &lt;a href="http://blogs.msdn.com/vsdteam/archive/2005/11/16/linker_error_lnk2019_lnk2001.aspx"&gt;good  blog post&lt;/a&gt; from Microsoft employees on the problem. The author summarized a  few cases you may encounter such linker error:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;You have created a new C++ MFC smart device project and changed the          Project -&gt; Properties -&gt; C/C++ -&gt; Language -&gt;      "Treat wchar_t as built in type" to "No (/Zc:wchar_t-)"&lt;/li&gt;&lt;li&gt;You have migrated an eVC project to visual Studio 2005, which links to      some dependent ATL/MFC DLLs which are compiled using previous versions (like      eVC3.0, eVC 4.0 or Visual Studio 2003).&lt;/li&gt;&lt;li&gt;You have migrated you eVC ATL/MFC project to Visual Studio 2005 that has      no dependent DLLs, but the Project -&gt; Properties -&gt; C/C++ -&gt;      Language -&gt; "Treat wchar_t as built in type" is set to "No      (/Zc:wchar_t-)"&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;My case is exactly the second case, as I've migrated all my projects from  Embedded Visual C++ 4 to Visual Studio 2005. &lt;a href="http://windowsmobilepro.blogspot.com/2005/08/manually-migrate-embedded-visual-c.html"&gt;Read  my migration lessons here...&lt;/a&gt;&lt;/p&gt; &lt;p&gt;And at the end, he said "Microsoft are looking at fixing this  issue". I certainly hope so!&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BOutlook%20Transport%20MAPI%5D%22"&gt;[Outlook  / Transport / MAPI]&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114482729459381904?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114482729459381904/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114482729459381904' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114482729459381904'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114482729459381904'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/04/windows-mobile-50-new-mapi-functions.html' title='Windows Mobile 5.0 New MAPI Functions Linker Error LNK2019 / LNK2001'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114456631084113511</id><published>2006-03-31T00:03:00.000-08:00</published><updated>2006-04-09T00:06:38.580-07:00</updated><title type='text'>Windows Mobile Secure Socket Implementation Series 4: Changes in Windows Mobile 5.0 platform</title><content type='html'>&lt;p&gt;&lt;b&gt;Windows Mobile Secure Socket Implementation Series 4: Changes in Windows  Mobile 5.0 platform&lt;/b&gt;&lt;/p&gt; &lt;p&gt;In previous three posts on Windows Mobile secure socket implementation, I  talked about:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/03/windows-mobile-secure-socket.html"&gt;general      ideas&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/03/windows-mobile-secure-socket_25.html"&gt;source      code to prepare a socket for secure connection, to crack a BLOB into a X.509      Certificate, and the callback to validate a X.509 certificate&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/03/windows-mobile-secure-socket_28.html"&gt;subject      and CN in X.509 Certificate, and the approach to support wildcard      certificate&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;In this post I will list the changes of secure socket implementation from  Windows Mobile 2003 devices (based on Windows CE 4.2 .NET) to Windows Mobile 5.0  devices (based on Windows CE 5.0 device). &lt;/p&gt; &lt;h3&gt;Newly added: remote host name verification&lt;/h3&gt; &lt;p&gt;In 5.0 platform, Microsoft adds a new control code &lt;i&gt;SO_SSL_SET_PEERNAME&lt;/i&gt;.  With such control code, the remote host name is verified by Winsock against the  server certificate after a successful SSL handshake. The verification results  are then indicated in the certificate validation callback function via the &lt;i&gt;dwFlags  &lt;/i&gt;parameter. If the specified host name does not match the one indicated in  the certificate chain of the SSL Handshake, &lt;i&gt;SSL_CERT_FLAG_ISSUER_UNKNOWN&lt;/i&gt;  is set in the &lt;i&gt;dwFlags &lt;/i&gt;parameter.&lt;/p&gt; &lt;p&gt;It is simple to use the control code:&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;char* pchHostName = &amp;quot;www.example.com&amp;quot;;  // passing somewhere&lt;br /&gt;sockerror = WSAIoctl(in_socket, SO_SSL_SET_PEERNAME,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;pchHostName, strlen(pchHostName)+1, NULL, 0, NULL, NULL, NULL);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;Notice you need to use &lt;i&gt;strlen(hostname)+1&lt;/i&gt; as the input buffer length  (to include the NULL terminator).&lt;/p&gt; &lt;p&gt;If you go through all my previous three posts, you will immediately find that  my code actually is doing the same thing in the certificate validation callback  function, but I need &lt;i&gt;SslCrackCertificate&lt;/i&gt; to crack the BLOB into a X.509  structure. I think the reason why Microsoft adds this new control code is  because &lt;i&gt;SslCrackCertificate&lt;/i&gt; and &lt;i&gt;SslFreeCertificate&lt;/i&gt; are not  publicly documented. &lt;/p&gt; &lt;p&gt;My own test reveals that &lt;i&gt;SO_SSL_SET_PEERNAME&lt;/i&gt; does not recognize  wildcard certificate. Microsoft code possibly just did a literal match between  the desired host name and the CN from the subject, like what I did in my &lt;a href="file:///E:/Wireless/Docs/Leisure/windowsmobilepro.blogspot.com/2006/03/windows-mobile-secure-socket_25.html"&gt;sample  code&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&lt;b&gt;&lt;i&gt;Warning: If you need to support wildcard certificate, do not use  SO_SSL_SET_PEERNAME.&lt;/i&gt;&lt;/b&gt;&lt;/p&gt; &lt;h3&gt;More subtle changes during SSL handshake phase&lt;/h3&gt; &lt;p&gt;My experiences dealing with Windows Mobile users tells me: A lot of users  forgot to set up their devices' time after a hard-reset. It is not a big deal  for smartphones, as the phone can synchronize the time via air. For Pocket PCs,  the time is reset to the factory-default one. For example, in my Sprint PPC6600  device (Windows Mobile 2003 SE), the time is reset to some day in 2004.&lt;/p&gt; &lt;p&gt;Why the time matters to secure socket programming? Remember we need to  validate the lifetime of a server certificate. If the certificate is already  expired, there is no reason we should trust the server, but we may present a  dialog to the user, and let the user to decide whether to connect or not.  However, in the case of a hard-reset device, the certificate's starting time  actually is later than the device's current time. Take PPC6600 device as an  example, the current time returned by &lt;i&gt;GetLocalTime()&lt;/i&gt; is year 2004, but  the server certificate is valid from year 2005 to year 2006. What gives? &lt;/p&gt; &lt;p&gt;You may simply ignore the "post-dated" certificate and continue to  establish a secure connection. Better, as a programmer with good sense, you may  present a dialog reminding the user to set up the time correctly. The above  logic is natural to implement in Windows Mobile 2003 platform; in which, the  server certificate is passed into the validation callback function as  "normal" by Winsock, so you have the chance to test the lifetime of  the certificate.&lt;/p&gt; &lt;p&gt;However, the behavior changed in 5.0 plaform. If the current time of the  device is earlier than the starting time of the certificate, &lt;i&gt;dwFlags&lt;/i&gt; now  contains &lt;i&gt;SSL_CERT_FLAG_ISSUER_UNKNOWN&lt;/i&gt;, . IMHO this is a very misleading  flag. Now the programmer has no idea whether the server certificate is really a  bad one, or the certificate is good but the device's time is bad.&lt;/p&gt; &lt;h3&gt;Wrap-Up&lt;/h3&gt; &lt;p align="left"&gt;You do not really need to change source code in 5.0 platforms,  if you do not plan to use the newly added &lt;i&gt;SO_SSL_SET_PEERNAME&lt;/i&gt; feature.  And, you should not use it at all, if wildcard certificate needs to be  supported.&lt;/p&gt; &lt;p align="left"&gt;In 5.0 platforms, you lose the capability to gracefully handle a  device which has a bad time setting.&lt;/p&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;amp;as_q=%22%5BSSL%20Socket%20Networking%20Connection%20Manager%5D%22"&gt;[SSL / Socket / Networking / Connection Manager]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114456631084113511?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114456631084113511/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114456631084113511' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114456631084113511'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114456631084113511'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/03/windows-mobile-secure-socket_31.html' title='Windows Mobile Secure Socket Implementation Series 4: Changes in Windows Mobile 5.0 platform'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114447900709219733</id><published>2006-03-28T23:48:00.000-08:00</published><updated>2006-04-08T00:02:43.250-07:00</updated><title type='text'>Windows Mobile Secure Socket Implementation Series 3: X.509 Certificate and Wildcard Certificate</title><content type='html'>&lt;p&gt;&lt;b&gt;Windows Mobile Secure Socket Implementation Series 3: X.509 Certificate  and Wildcard Certificate&lt;/b&gt;&lt;/p&gt; &lt;p&gt;In previous two posts on Windows Mobile secure socket implementation, I  talked about &lt;a href="http://windowsmobilepro.blogspot.com/2006/03/windows-mobile-secure-socket.html"&gt;general  ideas&lt;/a&gt;, and the &lt;a href="http://windowsmobilepro.blogspot.com/2006/03/windows-mobile-secure-socket_25.html"&gt;source  code to prepare a socket for secure connection, to crack a BLOB into a X.509  Certificate, and the callback to validate a X.509 certificate&lt;/a&gt;. &lt;/p&gt; &lt;h3&gt;More on X.509 Certificate, Subject and CN (Common Name)&lt;/h3&gt; &lt;p&gt;The function parsing a subject name to retrieve the CN, ParseCN(), is  intentionally left out in the source code in &lt;a href="http://windowsmobilepro.blogspot.com/2006/03/windows-mobile-secure-socket_25.html"&gt;previous  post&lt;/a&gt;. What is a subject, what is CN, and why do we care the subject and CN  when we need to validate a certificate?&lt;/p&gt; &lt;p&gt;To answer the above questions, some basic knowledge of X.509 certificate is  required. Below are two good and quick readings:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/X.509"&gt;X.509 from Wikipedia, the      free encyclopedia&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://java.sun.com/j2se/1.5.0/docs/guide/security/cert3.html"&gt;X.509      Certificates and Certificate Revocation Lists (CRLs)&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Subject can be roughly understood as the name of an entity, who can be  identified by the certificate. CN refers to common name, and in the internet,  most probably a host name. Below is Amazon.com's server certificate. Notice the  subject line and CN.&lt;/p&gt; &lt;blockquote&gt;   &lt;p&gt;&lt;i&gt;CN = www.amazon.com, O = Amazon.com Inc., L = Seattle, ST = Washington,    C = US&lt;/i&gt;&lt;/p&gt;  &lt;p align="center"&gt;&lt;img border="0" src="http://photos1.blogger.com/blogger/5783/1371/1600/AmazonCertificate.jpg" width="475" height="468"&gt;&lt;/p&gt;&lt;br /&gt; &lt;/blockquote&gt; &lt;p&gt;Now we can answer the question why we need to care subject and CN, because we  need to compare CN to the remote host name, to see whether they match. Below is  the function to extract CN from the subject line:&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;&lt;br /&gt;char* ParseCN(char* pchSubjLine)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;char* pchCommonName = NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;char* pchEnd = NULL;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!pchSubjLine) return NULL;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;pchSubjLine = _strlwr(pchSubjLine);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;pchCommonName = strstr(pchSubjLine, &amp;quot;cn=&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!pchCommonName) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;pchCommonName += 3;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;pchEnd = pchCommonName;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;// find the next separator: , or \t or space, or apos&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;while ('\0' != *pchEnd &amp;amp;&amp;amp; ',' != *pchEnd &amp;amp;&amp;amp; ' ' != *pchEnd&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;amp;&amp;amp; '\t' != *pchEnd &amp;amp;&amp;amp; '\'' != *pchEnd) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pchEnd++;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ('\0' != pchEnd) pchEnd = '\0';&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;return pchCommonName;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt; &lt;h3&gt;Wildcard Certificate&lt;/h3&gt; &lt;p&gt;If you go back to the source code in my &lt;a href="http://windowsmobilepro.blogspot.com/2006/03/windows-mobile-secure-socket_25.html"&gt;previous  post&lt;/a&gt;, you may notice that I did a literal match between CN and the remote  host name by simply using &lt;i&gt;_stricmp()&lt;/i&gt;. This simple literal match should  work for most sites, but recently there is an industry trend to use a wildcard  certificate, and literal match won't work against such certificate.&lt;/p&gt; &lt;p&gt;What is a wildcard certificate? Let us say a company "&lt;i&gt;example.com&lt;/i&gt;"  wants to expose 10 web servers to the public internet, all supporting HTTPS:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;i&gt;https://www.example.com&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;https://www01.example.com&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;...&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;https://www09.example.com&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The company can buy 10 certificates from CA , each using the fully qualified  host name as the CN. Alternatively, the company can buy ONE certificate from CA,  using "&lt;i&gt;*.example.com&lt;/i&gt;" as the CN. The price of a wildcard  certificate is definitely higher than a "normal" certificate, but if  the company has a lot of web servers, wildcard certificate can save big. A  little bit more information regarding wildcard certificate can be found in  "&lt;a href="http://www.microsoft.com/technet/prodtechnol/isa/2004/maintain/wildcard.mspx"&gt;Publishing  Multiple Web Sites using a Wildcard Certificate in ISA Server 2004&lt;/a&gt;".&lt;/p&gt; &lt;p&gt;Modern browsers like Firefox and IE have no difficulty supporting wildcard  certificate and do not complain. Interestingly enough, I found that Pocket IE in  both Windows Mobile 2003 devices and Windows Mobile 5.0 devices complains that a  wildcard certificate is not a good match to the remote host.&lt;/p&gt; &lt;p&gt;Back to our code. We need to modify the simple literal match to a slightly  more advanced one:&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;if ('*' == *pchCN &amp;amp;&amp;amp; '.' == *(pchCN+1)) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;while ('\0' != *pchRemoteHost &amp;amp;&amp;amp; '.' != *pchRemoteHost) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pchRemoteHost++;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ('.' == *pchRemoteHost) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bMatched = !(_stricmp(pchRemoteHost+1, pchCN+2));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;// if there is no dot, bMatch remains FALSE&lt;br /&gt;} else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;bMatched = !(_stricmp(pchRemoteHost, pchCN));&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;amp;as_q=%22%5BSSL%20Socket%20Networking%20Connection%20Manager%5D%22"&gt;[SSL / Socket / Networking / Connection Manager]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114447900709219733?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114447900709219733/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114447900709219733' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114447900709219733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114447900709219733'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/03/windows-mobile-secure-socket_28.html' title='Windows Mobile Secure Socket Implementation Series 3: X.509 Certificate and Wildcard Certificate'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114445444425931185</id><published>2006-03-25T16:46:00.000-08:00</published><updated>2006-04-07T23:53:17.233-07:00</updated><title type='text'>Windows Mobile Secure Socket Implementation Series 2: Sample Source Code</title><content type='html'>&lt;p style="font-weight: bold;"&gt;Windows Mobile Secure Socket Implementation Series 2: Sample Source Code&lt;/p&gt; &lt;p&gt;In previous post, I talked about &lt;a href="http://windowsmobilepro.blogspot.com/2006/03/windows-mobile-secure-socket.html"&gt;general  ideas to write secure socket applications in Windows Mobile device (or actually  on Windows CE platforms)&lt;/a&gt;. The current post has the source code and simple explanations  on the code.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Function: Establish a secure socket connection to a remote host:port&lt;/h3&gt; &lt;p&gt;Notice the remote host name is passed as certificate validation function's &lt;i&gt;pvArg&lt;/i&gt;,  which will be given back to us by Winsock when the validation function is  called.&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;font face="Courier" size="2"&gt;&lt;br /&gt;int SecureConnect(int in_socket, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;const struct sockaddr * in_pHostInetAddr, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;int in_port )&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;struct sockaddr_in theInetAddr;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;int sockerror = 0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;/* initialize the address structures */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;memset (&amp;amp;theInetAddr, 0, sizeof(theInetAddr));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;theInetAddr.sin_family = AF_INET;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;theInetAddr.sin_addr.s_addr = htonl(INADDR_ANY);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;theInetAddr.sin_port = htons(in_port);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;// make it secure&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwOptVal = SO_SEC_SSL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwBytes = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SSLVALIDATECERTHOOK sslValidateFunc;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sockerror = setsockopt(in_socket, SOL_SOCKET, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SO_SECURE, (LPSTR)&amp;amp;dwOptVal, sizeof(dwOptVal));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (SOCKET_ERROR == sockerror){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// error logging&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// register certificate validation callback &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sslValidateFunc.HookFunc = certificateValidationCallback;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sslValidateFunc.pvArg = &amp;quot;www.sample.com&amp;quot;; // ... passing server name from your context&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sockerror = WSAIoctl(in_socket, SO_SSL_SET_VALIDATE_CERT_HOOK,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;amp;sslValidateFunc, sizeof(sslValidateFunc), NULL, 0, &amp;amp;dwBytes, NULL, NULL);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (SOCKET_ERROR == sockerror){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// error logging&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;// connect&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;sockerror = connect(in_socket, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(struct sockaddr *)in_pHostInetAddr, sizeof (*in_pHostInetAddr));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (sockerror == SOCKET_ERROR) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// error logging&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// show SSLCONNECTIONINFO&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SSLCONNECTIONINFO SSLConnectionInfo;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwBytes = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sockerror = WSAIoctl(in_socket, SO_SSL_GET_CONNECTION_INFO,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NULL, 0, &amp;amp;SSLConnectionInfo, sizeof(SSLConnectionInfo), &amp;amp;dwBytes, NULL,NULL);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (sockerror == SOCKET_ERROR) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// error logging&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ShowConnectionInfo(&amp;amp;SSLConnectionInfo);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;return 1;&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Function: Load the functions from &lt;i&gt;schannel.dll&lt;/i&gt;, to crack a BLOB  into X.509 certificate &lt;/h3&gt; &lt;p&gt;The two functions pointers are defined as global variables so that they do  not need to be dynamically loaded or unloaded during each SSL handshake phase. &lt;/p&gt; &lt;font face="Courier" size="2"&gt;&lt;br /&gt;&lt;br /&gt;#include &amp;lt;wincrypt.h&amp;gt;&lt;br /&gt;#include &amp;lt;schnlsp.h&amp;gt;&lt;br /&gt;&lt;br /&gt;// load SslCrackCertificate and SslFreeCertificate&lt;br /&gt;#define SSL_CRACK_CERTIFICATE_NAME TEXT(&amp;quot;SslCrackCertificate&amp;quot;)&lt;br /&gt;#define SSL_FREE_CERTIFICATE_NAME TEXT(&amp;quot;SslFreeCertificate&amp;quot;)&lt;br /&gt;&lt;br /&gt;HRESULT LoadSSL()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;// already loaded?&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (gSslCrackCertificate &amp;amp;&amp;amp; gSslFreeCertificate) return S_OK;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;hSchannelDLL = LoadLibrary(TEXT(&amp;quot;schannel.dll&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!hSchannelDLL) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// error logging&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return E_FAIL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;gSslCrackCertificate = (SSL_CRACK_CERTIFICATE_FN)GetProcAddress(hSchannelDLL, SSL_CRACK_CERTIFICATE_NAME);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;gSslFreeCertificate = (SSL_FREE_CERTIFICATE_FN)GetProcAddress(hSchannelDLL, SSL_FREE_CERTIFICATE_NAME);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!gSslCrackCertificate || !gSslFreeCertificate) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// error logging&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gSslCrackCertificate = NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gSslFreeCertificate = NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FreeLibrary(hSchannelDLL);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hSchannelDLL = NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return E_FAIL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;} else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return S_OK;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;HRESULT FreeSSL()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (hSchannelDLL) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FreeLibrary(hSchannelDLL);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hSchannelDLL = NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;return S_OK;&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Function: Show SSL connection information for debugging or learning  purpose&lt;/h3&gt; &lt;p&gt; Do not put it into your release build. &lt;/p&gt; &lt;font face="Courier" size="2"&gt;&lt;br /&gt;&lt;br /&gt;void ShowConnectionInfo(SSLCONNECTIONINFO *pConnectionInfo)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;TCHAR szTemp[1028];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;memset(szTemp, 0, 1028*sizeof(TCHAR));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;switch(pConnectionInfo-&amp;gt;dwProtocol)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;case SSL_PROTOCOL_SSL3:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), TEXT(&amp;quot;Protocol: SSL3&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;case SSL_PROTOCOL_PCT1:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), TEXT(&amp;quot;Protocol: PCT&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;case SSL_PROTOCOL_SSL2:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), TEXT(&amp;quot;Protocol: SSL2&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;default:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), TEXT(&amp;quot;Protocol: 0x%08x&amp;quot;), pConnectionInfo-&amp;gt;dwProtocol);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;wcscat(szTemp, TEXT(&amp;quot;\n&amp;quot;));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;switch(pConnectionInfo-&amp;gt;aiCipher)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;case CALG_RC4: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), TEXT(&amp;quot;Cipher: RC4&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;case CALG_3DES: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), TEXT(&amp;quot;Cipher: Triple DES&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;case CALG_RC2: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), TEXT(&amp;quot;Cipher: RC2&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;case CALG_DES: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), TEXT(&amp;quot;Cipher: DES&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;case CALG_SKIPJACK: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), TEXT(&amp;quot;Cipher: Skipjack&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;default: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), szTemp, TEXT(&amp;quot;Cipher: 0x%08x&amp;quot;), pConnectionInfo-&amp;gt;aiCipher);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;wcscat(szTemp, TEXT(&amp;quot;\n&amp;quot;));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), TEXT(&amp;quot;Cipher strength: %d&amp;quot;), pConnectionInfo-&amp;gt;dwCipherStrength);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;wcscat(szTemp, TEXT(&amp;quot;\n&amp;quot;));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;switch(pConnectionInfo-&amp;gt;aiHash)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;case CALG_MD5: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), TEXT(&amp;quot;Hash: MD5&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;case CALG_SHA: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), TEXT(&amp;quot;Hash: SHA&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;default: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), szTemp, TEXT(&amp;quot;Hash: 0x%08x&amp;quot;), pConnectionInfo-&amp;gt;aiHash);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;wcscat(szTemp, TEXT(&amp;quot;\n&amp;quot;));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), TEXT(&amp;quot;Hash strength: %d&amp;quot;), pConnectionInfo-&amp;gt;dwHashStrength);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;wcscat(szTemp, TEXT(&amp;quot;\n&amp;quot;));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;switch(pConnectionInfo-&amp;gt;aiExch)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;case CALG_RSA_KEYX: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;case CALG_RSA_SIGN: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), TEXT(&amp;quot;Key exchange: RSA&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;case CALG_KEA_KEYX: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), TEXT(&amp;quot;Key exchange: KEA&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;default: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), TEXT(&amp;quot;Key exchange: 0x%08x&amp;quot;), pConnectionInfo-&amp;gt;aiExch);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;wcscat(szTemp, TEXT(&amp;quot;\n&amp;quot;));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;swprintf(szTemp+wcslen(szTemp), TEXT(&amp;quot;Key exchange strength: %d&amp;quot;), pConnectionInfo-&amp;gt;dwExchStrength);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;MessageBox(NULL, szTemp, NULL, NULL);&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Function: Certificate validation callback&lt;/h3&gt; &lt;p&gt;Notice the order how it checks the certificate and other parameters.  Sometimes Winsock passes false alarms in &lt;i&gt;dwFlags&lt;/i&gt;. The way how Winsock  internally handles the certificate in Windows Mobile 5.0 devices (Windows CE 5.0  based) is also changed from Windows Mobile 2003 devices (CE 4.2 based). This  will be discussed in my later post.&lt;/p&gt; &lt;br /&gt;&lt;font face="Courier" size="2"&gt;&lt;br /&gt;// the certificate validattion for SSL&lt;br /&gt;int certificateValidationCallback(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwType,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;LPVOID pvArg,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwChainLen,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;LPBLOB pCertChain,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwFlags)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;X509Certificate* pCert = NULL; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;int nRet = SSL_ERR_CERT_UNKNOWN;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;// dwType must be SSL_CERT_X.509&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (dwType != SSL_CERT_X509) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// error logging&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return nRet;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (dwFlags &amp;amp; SSL_CERT_FLAG_ISSUER_UNKNOWN) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// error logging&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return nRet;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (pCertChain == NULL) return nRet;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;ASSERT(dwChainLen == 1);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!gSslCrackCertificate || !gSslFreeCertificate) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// error logging&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return nRet; // unable to crack&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;// crack X.509 Certificate&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!gSslCrackCertificate(pCertChain-&amp;gt;pBlobData, pCertChain-&amp;gt;cbSize, TRUE, &amp;amp;pCert)) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// error logging&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return SSL_ERR_BAD_DATA;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Site check&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char* pchSubject = NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char* pchCN = NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BOOL bMatched = FALSE;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char* pchRemoteHost = (char*)pvArg;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pchSubject = pCert-&amp;gt;pszSubject;&lt;br /&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// here you need to parse the subjec to retrieve the CN name &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pchCN = ParseCN(pchSubject);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!pchCN) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;goto FuncExit;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// CN comparison&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bMatched = !(_stricmp(pchRemoteHost, pchCN));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!bMatched) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// error logging&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;goto FuncExit;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;// validFrom, validUntil check&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SYSTEMTIME stNow;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FILETIME ftNow;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FILETIME ftValidFrom = pCert-&amp;gt;ValidFrom;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FILETIME ftValidUntil = pCert-&amp;gt;ValidUntil;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;GetSystemTime(&amp;amp;stNow);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SystemTimeToFileTime(&amp;amp;stNow, &amp;amp;ftNow);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!(IsEarlierThan(&amp;amp;ftValidFrom, &amp;amp;ftNow) &amp;amp;&amp;amp; IsEarlierThan(&amp;amp;ftNow, &amp;amp;ftValidUntil))) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// give user an option to continue or not&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// a little more lenient than Subject check&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;nRet = SSL_ERR_OKAY;&lt;br /&gt;&lt;br /&gt;FuncExit:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;gSslFreeCertificate(pCert);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;return nRet;&lt;br /&gt;}&lt;br /&gt; &lt;/font&gt; &lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;amp;as_q=%22%5BSSL%20Socket%20Networking%20Connection%20Manager%5D%22"&gt;[SSL / Socket / Networking / Connection Manager]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114445444425931185?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114445444425931185/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114445444425931185' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114445444425931185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114445444425931185'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/03/windows-mobile-secure-socket_25.html' title='Windows Mobile Secure Socket Implementation Series 2: Sample Source Code'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114439482145988219</id><published>2006-03-22T00:24:00.000-08:00</published><updated>2006-04-07T23:47:43.163-07:00</updated><title type='text'>Windows Mobile Secure Socket Implementation Series 1: General Idea</title><content type='html'>&lt;p style="font-weight: bold;"&gt;Windows Mobile Secure Socket Implementation Series 1: General Idea&lt;/p&gt; &lt;p&gt;Whenever you need to write socket-based programs, very possibly you need to  implement a secure socket. For example, if you develop your own mini-http  client, you have to deal with HTTPS; if you write an IMAP4 client, you may need  to support STARTTLS command. Or, you are writing both the server in the desktop  and the client for Windows Mobile device, and need to support a secure  communication channel.&lt;/p&gt; &lt;p&gt;I plan to write four articles on the series of secure socket implementation:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;General idea&lt;/li&gt;&lt;li&gt;Sample source code&lt;/li&gt;&lt;li&gt;X.509 Certificate and how to deal with wildcard certificate&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Changes in Windows Mobile 5.0 platform (vs. 2003 devices on 4.2 platform)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Different from Windows desktop environment, Windows CE platform exposes a  very nice way to write secure socket program. Adding a security infrastructure  requires few code changes to "normal non-secure" socket-based  applications. Once a secure socket is connected, the application may send and  receive data on that socket unaware that the data over the wire is encoded. You  can just write the boilerplate socket code and functions: socket(), connect(),  read(), recv(), closesocket(). &lt;/p&gt; &lt;p&gt;The procedure to establish a secure socket connection is well documented by  Microsoft, ever since 3.0:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcecomm/html/_wcesdk_Implementing_a_Secure_Socket.asp"&gt;Microsoft      Windows CE 3.0/ .NET 4.2 Implementing a Secure Socket&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://http//msdn.microsoft.com/library/default.asp?url=/library/en-us/wcecomm5/html/wce50conimplementingasecuresocket.asp"&gt;Microsoft      Windows CE .NET 5.0 Implementing a Secure Socket&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Below are the two critical steps:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;Set the socket in secure mode with the &lt;a href="http://msdn.microsoft.com/library/en-us/wcecomm5/html/wce50lrfsetsockoptwindowssockets.asp"&gt;setsockopt&lt;/a&gt;      function. Set &lt;i&gt;level&lt;/i&gt; to SOL_SOCKET, &lt;i&gt;optname&lt;/i&gt; to SO_SECURE, and &lt;i&gt;optval&lt;/i&gt;      to a &lt;b&gt;DWORD&lt;/b&gt; set to SO_SEC_SSL.   &lt;/li&gt;&lt;li&gt;Specify the certificate validation callback function by calling &lt;a href="http://msdn.microsoft.com/library/en-us/wcecomm5/html/wce50lrfwsaioctl.asp"&gt;WSAIoctl&lt;/a&gt;      with the SO_SSL_SET_VALIDATE_CERT_HOOK control code.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Notice the certificate validation callback function: &lt;/p&gt; &lt;pre&gt;int SslValidate (&lt;br /&gt;   DWORD  dwType&lt;br /&gt;   LPVOID pvArg&lt;br /&gt;   DWORD  dwChainLen&lt;br /&gt;   LPBLOB pCertChain&lt;br /&gt;   DWORD  dwFlags&lt;br /&gt;);&lt;/pre&gt; &lt;p&gt;Below are explanations of some important parameters: &lt;/p&gt;&lt;ul type="disc"&gt;&lt;li&gt;The &lt;i&gt;dwType&lt;/i&gt; parameter specifies the data type pointed to by &lt;i&gt;pCertChain&lt;/i&gt;.      It must be SSL_CERT_X.509.   &lt;/li&gt;&lt;li&gt;The &lt;i&gt;pvArg&lt;/i&gt; parameter is the application-defined context. It is a      nice place to pass information against which you want to verify, for      example, remote host name.   &lt;/li&gt;&lt;li&gt;The &lt;i&gt;pCertChain&lt;/i&gt; parameter is a pointer to a BLOB struct, which      contains a X.509 certificate (ISO standard). The certificate is the server      certificate. You can parse the certificate to extract the pertinent data      like the subject and life cycle.&lt;/li&gt;&lt;li&gt;&lt;i&gt;dwFlags&lt;/i&gt; parameter will contain SSL_CERT_FLAG_ISSUER_UNKNOWN, if the      root issuer of the certificate could not be found in the client device's CA      database. &lt;b&gt;Notice WinSock sometimes passes false alarms in this parameter.&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;If you simply return SSL_ERR_OKEY in your certificate validation callback,  then any faked or invalid SSL certificate is deemed valid. This obviously  defeats the purpose of establishing a trusted secure communication channel. You  need to do your due diligence by testing at least three things:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;to test the &lt;i&gt;dwFlags&lt;/i&gt; passed to you by WinSock, &lt;/li&gt;&lt;li&gt;to test the server certificate to see whether the certificate subject name      matches the remote host name, &lt;/li&gt;&lt;li&gt;and, to test whether the server certificate is already expired.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Most probably you do not need to test the issuer, since Winsock already did  the job by checking the server certificate against the root CA store in the  device.&lt;/p&gt; &lt;p&gt;One tricky business of how to parse the &lt;i&gt;pCertChain&lt;/i&gt; Blob to get the  following structure:&lt;/p&gt; &lt;pre&gt;typedef struct _X509Certificate {&lt;br /&gt;   DWORD           Version;&lt;br /&gt;   DWORD           SerialNumber[4];&lt;br /&gt;   ALG_ID          SignatureAlgorithm;&lt;br /&gt;   FILETIME        ValidFrom;&lt;br /&gt;   FILETIME        ValidUntil;&lt;br /&gt;   PSTR            pszIssuer;&lt;br /&gt;   PSTR            pszSubject;&lt;br /&gt;   PctPublicKey    *pPublicKey;&lt;br /&gt;} X509Certificate, * PX509Certificate;&lt;/pre&gt; &lt;p&gt;The way to crack the Blob is not documented by Microsoft, but it it not  difficult to find out by searching in major search engines: to use &lt;i&gt;SslCrackCertificate&lt;/i&gt;  and &lt;i&gt;SslFreeCertificate&lt;/i&gt; that are exported from &lt;i&gt;schannel.dll&lt;/i&gt;. Once  you have the X.509 structure, you can easily validate it against the remote host  name (by checking &lt;i&gt;pszSubject&lt;/i&gt;), and life cycle (by checking &lt;i&gt;ValidFrom &lt;/i&gt;and  &lt;i&gt;ValidUtil&lt;/i&gt;).&lt;/p&gt; &lt;p&gt;I'll post ready-to-compile source code in my next post.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;amp;as_q=%22%5BSSL%20Socket%20Networking%20Connection%20Manager%5D%22"&gt;[SSL / Socket / Networking / Connection Manager]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114439482145988219?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114439482145988219/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114439482145988219' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114439482145988219'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114439482145988219'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/03/windows-mobile-secure-socket.html' title='Windows Mobile Secure Socket Implementation Series 1: General Idea'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114396211970035333</id><published>2006-03-18T18:45:00.000-08:00</published><updated>2006-04-05T00:11:15.026-07:00</updated><title type='text'>1.1 .NET Framework is Needed for Smart Device Projects targeting 1.0 NET CF (Compact Framework) in Visual Studio 2005 (VS2005)</title><content type='html'>&lt;p style="font-weight: bold;"&gt;1.1 .NET Framework is Needed for Smart Device Projects targeting 1.0 NET CF  (Compact Framework) in Visual Studio 2005 (VS2005)&lt;/p&gt; &lt;p&gt;Our new team member was opening a SDK sample C# solution in Visual Studio  2005, and could not build it. I took a look at the output window. The output was  huge with 700+ lines, considering how tiny the sample project is. The following  error message was shown there:&lt;/p&gt; &lt;blockquote&gt;   &lt;p&gt;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Microsoft.CSharp.Targets(147,9):    error VSD6000: Projects targeting .NET Compact Framework 1.0 require version    1.1 of the .NET Framework, which is not detected on this machine.&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;This sounds strange and interesting, as I never seen this error message in my  own PC. A quick search results in the following MSDN2 library documentation:&lt;/p&gt; &lt;blockquote&gt;   &lt;p&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/ms184406.aspx"&gt;Version    1.1 of .NET Framework required&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Looks like the team member just installed a fresh PC with VS2005 and Windows  Mobile SDKs, and apparently Visual Studio 2005 installed .NET Framework 2.0, but  not 1.1. To solve the problem is easy, just downloading .NET Framework 1.1 and  installing it in the team member's PC.&lt;/p&gt; &lt;p&gt;I did not see this problem in my own PC, because several versions of .NET  Framework already reside in my PC. Such weird requirement actually puzzled me.  Why cannot .NET 2.0 Framework do the job, if .NET 1.1 can do? I am not familiar  with what happens under the hood, but just wondering how confusing it is. I  myself did a lot of java coding (ever since JDK 1.1), and I've never seen such  a weird requirement that old JDK or JRE has to be present for some stuff to work.  Kudos to Sun Microsystem guys!&lt;/p&gt; &lt;p&gt;Another thing worth mentioning is one statement in that MSDN2 documentation  page:&lt;/p&gt; &lt;blockquote&gt;   &lt;p&gt;Smartphone 2003 projects fall into this category (.NET Compact Framework    version 1.0)&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Sometimes I saw people posted questions to certain forums wondering how to  develop .NET CF 2.0 applications for Smartphone 2003 platforms. Unfortunately  this is not supported. The root reason is that Smartphone 2003 does not persist  "\Windows" folder (the one it persists is  "\Storage\Windows"). Rather funny, huh? It is not because certain APIs  are not available in Smartphone 2003, nor because Smartphone 2003 is "too  small"...&lt;/p&gt; &lt;p&gt;The following .NET CF team blog presents an excellent table on what platforms  can support .NET CF 2.0:&lt;/p&gt; &lt;blockquote&gt;   &lt;p&gt;&lt;a href="http://blogs.msdn.com/netcfteam/archive/2005/10/11/479793.aspx"&gt;.NET    Compact Framework Version 2 .CAB Files Explained&lt;/a&gt; &lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;In short, .NET CF 2.0 is supported on:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;Pocket PC 2003 and 2003 SE&lt;/li&gt;&lt;li&gt;Windows Mobile 5.0 PPC&lt;/li&gt;&lt;li&gt;Windows Mobile 5.0 Smartphone&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;You even cannot find an installation .NETCFv2 CAB package for Smartphone 2003  platform.&lt;/p&gt; &lt;p&gt;Out of curiosity, I checked what .NET CF version are stored out of box for  the following devices:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;Sprint PPC6700: 1.0.4292.00 (Windows Mobile 5.0 Pocket PC, OS Version      5.1.1700, Build 14352.0.1.0)&lt;/li&gt;&lt;li&gt;Sprint PPC6601: 1.0.3316.00 (Windows Mobile 2003 SE Pocket PC, OS Version      4.21.1088, Build 14132)&lt;/li&gt;&lt;li&gt;I-Mate SP3i: 1.0.3316.00 (Windows Mobile 2003 Smartphone)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BDevelopment%20Environment%5D%22"&gt;[Development Environment]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114396211970035333?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114396211970035333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114396211970035333' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114396211970035333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114396211970035333'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/03/11-net-framework-is-needed-for-smart.html' title='1.1 .NET Framework is Needed for Smart Device Projects targeting 1.0 NET CF (Compact Framework) in Visual Studio 2005 (VS2005)'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114396537980050167</id><published>2006-03-15T00:08:00.000-08:00</published><updated>2006-04-03T17:45:21.520-07:00</updated><title type='text'>Source code to find out all the programs that are installed in a Windows Mobile device and that can be un-Installed</title><content type='html'>&lt;p style="font-weight: bold;"&gt;Source code to find out all the programs that are installed in a Windows Mobile device and that can be un-Installed&lt;/p&gt; &lt;p&gt;In the post "&lt;a href="http://windowsmobilepro.blogspot.com/2006/03/programmatically-find-out-all-programs.html"&gt;Programmatically  find out all the programs that can be unInstalled in Windows Mobile devices&lt;/a&gt;",  I showed how to locate a list of programs installed in a Windows Mobile device.  Pocket PC 2003 and other newer platforms (Smartphone 2003, Pocket PC 5.0, and  Smartphone 5.0) have to be handled differently. &lt;/p&gt;  &lt;p&gt; A reader actually sent me an  email for the source code. Oh well this is an easy one so I am posting here:&lt;/p&gt;&lt;font face="Courier" size="2"&gt;&lt;br /&gt;#include &amp;quot;cfgmgrapi.h&amp;quot;&lt;br /&gt;HRESULT QueryAllInstalled_DM()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;LPTSTR szProvXMLOut = NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;TCHAR szProvXMLIn[512];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;memset(szProvXMLIn, 0, 512*sizeof(TCHAR));&lt;br /&gt;&amp;nbsp;&amp;nbsp;wcscat(szProvXMLIn, TEXT(&amp;quot;&amp;lt;wap-provisioningdoc&amp;gt;&amp;lt;characteristic-query type=\&amp;quot;UnInstall\&amp;quot;&amp;gt;&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;wcscat(szProvXMLIn, TEXT(&amp;quot;&amp;lt;/characteristic-query&amp;gt;&amp;lt;/wap-provisioningdoc&amp;gt;&amp;quot;));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;HRESULT hr = DMProcessConfigXML(szProvXMLIn, CFGFLAG_PROCESS, &amp;amp;szProvXMLOut);&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (!FAILED(hr)) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ALERT2(TEXT(&amp;quot;SUCCESS&amp;quot;), TEXT(&amp;quot;DM&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;} else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ALERT2(TEXT(&amp;quot;FAILED&amp;quot;), TEXT(&amp;quot;DM&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;ALERT2(szProvXMLOut, TEXT(&amp;quot;DM&amp;quot;));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;DELETE_STR(szProvXMLOut);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return hr;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;#define APPS_REGHOME TEXT(&amp;quot;\\Software\\Apps&amp;quot;)&lt;br /&gt;static HRESULT QueryAllInstalled_Registry()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;HRESULT hr = E_FAIL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;LRESULT lr = E_FAIL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;HKEY hKey = NULL;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;DWORD dwcSubKeys = 0; // Number of sub keys&lt;br /&gt;&amp;nbsp;&amp;nbsp;DWORD dwcMaxSubKeyName = 0; // Longest sub key name&lt;br /&gt;&amp;nbsp;&amp;nbsp;TCHAR* szSubKeyName = NULL; // subkey names&lt;br /&gt;&amp;nbsp;&amp;nbsp;DWORD j = 0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// Open the predefined registry&lt;br /&gt;&amp;nbsp;&amp;nbsp;lr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, APPS_REGHOME, 0, 0, &amp;amp;hKey);&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (ERROR_SUCCESS != lr) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;goto FuncExit;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// Get Value count.&lt;br /&gt;&amp;nbsp;&amp;nbsp;lr = RegQueryInfoKey(hKey, // Key handle.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NULL, // Buffer for class name.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NULL, // Length of class string.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NULL, // Reserved.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;amp;dwcSubKeys, // Number of sub keys.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;amp;dwcMaxSubKeyName, // Longest sub key size.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NULL, // Longest class string.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NULL, // Number of values for this key.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NULL, // Longest Value name.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NULL, // Longest Value data.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NULL, // Security descriptor.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NULL); // Last write time.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// Enumerate the sub keys&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (!dwcSubKeys || dwcMaxSubKeyName &amp;lt;= 0) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;goto FuncExit;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;szSubKeyName = new TCHAR[dwcMaxSubKeyName+1];&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (NULL == szSubKeyName) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;goto FuncExit;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;for (j = 0, lr = ERROR_SUCCESS; j &amp;lt; dwcSubKeys; j++)&lt;br /&gt;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwcSubKeyName = dwcMaxSubKeyName;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;memset(szSubKeyName, 0, sizeof(TCHAR)*(dwcMaxSubKeyName+1));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;HKEY hSubKey = NULL;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lr = RegEnumKeyEx(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hKey, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;j,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;szSubKeyName, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;amp;dwcSubKeyName,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NULL,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NULL,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NULL,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NULL);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (ERROR_SUCCESS != lr) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;continue;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// now we have the key name. let us open it.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lr = RegOpenKeyEx(hKey, szSubKeyName, 0, 0, &amp;amp;hSubKey);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (ERROR_SUCCESS != lr) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;continue;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwInstl = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwValueType = REG_DWORD;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwValueLen = sizeof(DWORD);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lr = RegQueryValueEx(hSubKey, TEXT(&amp;quot;Instl&amp;quot;), NULL, &amp;amp;dwValueType, (LPBYTE)&amp;amp;dwInstl, &amp;amp;dwValueLen);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (ERROR_SUCCESS == lr) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (dwInstl == 1) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ALERT2(szSubKeyName, TEXT(&amp;quot;From Registry&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RegCloseKey(hSubKey);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;FuncExit:&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (szSubKeyName) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;delete []szSubKeyName;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (hKey) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RegCloseKey(hKey);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return hr;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;y=0&amp;as_q=%22[Setup%20Install%20unInstall%20Upgrade]%22"&gt;[Setup / Install / unInstall / Upgrade]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114396537980050167?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114396537980050167/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114396537980050167' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114396537980050167'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114396537980050167'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/03/source-code-to-find-out-all-programs.html' title='Source code to find out all the programs that are installed in a Windows Mobile device and that can be un-Installed'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114412889577375220</id><published>2006-03-12T22:34:00.000-08:00</published><updated>2006-04-07T00:30:16.486-07:00</updated><title type='text'>Programmatically find out all the programs that can be unInstalled in Windows Mobile devices</title><content type='html'>&lt;p&gt;&lt;b&gt;Programmatically find out all the programs that can be unInstalled in Windows Mobile devices&lt;/b&gt;&lt;/p&gt; &lt;p&gt;In my previous post, I talked about how to &lt;a href="http://windowsmobilepro.blogspot.com/2006/03/programmatically-uninstallremovedelete.html"&gt;programmatically unInstall/remove/delete one program in Windows Mobile devices&lt;/a&gt;. Notice that is only for one program. In this post, I am going to talk about how to find out all the programs that can be un-installed in a Windows Mobile device. With such a list, we can programmatically un-install all those programs. To enterprise customers, such functionality is a very welcome one, who deem the ability to remote-destroying lost or stolen devices a MUST-Have feature.&lt;/p&gt; &lt;p&gt;Like what I did in the previous post on &lt;a href="http://windowsmobilepro.blogspot.com/2006/03/programmatically-uninstallremovedelete.html"&gt;programmatically unInstall/remove/delete one program in Windows Mobile devices&lt;/a&gt;, I have to treat Pocket PC 2003 differently from other newer platforms to locate a list of un-installable programs&lt;/p&gt; &lt;h3&gt;Pocket PC 2003 platform&lt;/h3&gt; &lt;p&gt;Information about what programs are installed in a Pocket PC 2003 device can be found under registry key "\HKLM\SOFTWARE\Apps\". Each program is listed as a sub-key, with program name as the sub-key name. For each program, the value "CabFile" stores what is the original CAB file (the installation package), and value "InstallDir" is where (in which directory) the program is installed to.&lt;/p&gt; &lt;p&gt;Notice not all the programs listed there can be unInstalled, but only the sub-key with value "Instl" = dword:1. So to find a list of programs that can be uninstalled in a Pocket PC 2003 device, you can simply iterate through all sub-keys under registry hive "\HKLM\SOFTWARE\Apps\" with value "Instl" = dword:1. The APIs to use are RegOpenKeyEx, RegQueryInfoKey, RegQueryValueEx, and mainly RegEnumKeyEx. &lt;/p&gt; &lt;h3&gt;Other newer platforms (Smartphone 2003, Pocket PC 5.0, Smartphone 5.0)&lt;/h3&gt; &lt;p&gt;As I put in my previous post, Microsoft wants to move anything regarding mobile device management and configuration to its CSP (&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mobilesdk5/html/wce51conconfigurationserviceproviderreferenceforwindowsmobiledevices.asp"&gt;Configuration Service Provider&lt;/a&gt;) architecture. UnInstallation is one CSP. UnInstall Configuration Service Provider not only uninstalls applications from the device, but also returns information like what programs can be unInstalled. Below is the exact XML to feed into DMProcessConfigXML to get the list of un-installable programs in a Smartphone 2003 device, Pocket PC 5.0 device, or Smartphone 5.0 device:&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Courier;font-size:85%;"&gt;   &amp;lt;wap-provisioningdoc&amp;gt;&lt;br /&gt;      &amp;lt;characteristic-query type="UnInstall"&amp;gt;&lt;br /&gt;   &amp;lt;/characteristic-query&amp;gt; &amp;lt;/wap-provisioningdoc&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;amp;as_q=%22%5BSetup%20Install%20unInstall%20Upgrade%5D%22"&gt;[Setup / Install / unInstall / Upgrade]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114412889577375220?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114412889577375220/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114412889577375220' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114412889577375220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114412889577375220'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/03/programmatically-find-out-all-programs.html' title='Programmatically find out all the programs that can be unInstalled in Windows Mobile devices'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114386133510839575</id><published>2006-03-09T18:49:00.000-08:00</published><updated>2006-03-31T19:19:17.366-08:00</updated><title type='text'>Programmatically unInstall/remove/delete one program in Windows Mobile devices</title><content type='html'>&lt;p&gt;&lt;b&gt;Programmatically unInstall/remove/delete one program in Windows Mobile  devices&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;Sometimes you need to provide functionality to programmatically unInstall/remove/delete  a program from a user's device. Let us think about a use case: Your program is  managing some private or sensitive data. Unfortunately the user lose the device,  or some one stolen the device. Either case, the capability to remotely destroy  the program and data is highly desired. If you are targeting enterprise  customer, this remote-destroy functionality is almost certain listed as one  of  MUST-Have features. &lt;/p&gt;  &lt;p&gt;How to send a signal to or notify a lost device is the other story that I  might talk later in another blog post, here I solely focus on how to  programmatically unInstall a program in Windows Mobile devices.&lt;/p&gt; &lt;h3&gt;Pocket PC 2003 platform &lt;/h3&gt; &lt;p&gt;In Pocket PC 2003 devices, you can simply execute "\Windows\unload.exe"  and pass program name as the parameter. I guess you should know your own  program's name :) &lt;/p&gt;  &lt;ul&gt;&lt;li&gt;The program name is the concatenation of "Provider" and "AppName"      specified in your .INF file (the file for cabwiz to build)&lt;/li&gt;&lt;li&gt;The program name is listed in the list of "Settings" =&gt;      "System" =&gt; "Remove Programs"&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;You can call either &lt;b&gt;CreateProcess&lt;/b&gt; or &lt;b&gt;ShellExecuteEx&lt;/b&gt; to spawn  unload.exe. If you want to be a little more prefessional, call &lt;b&gt;WaitForSingleObject&lt;/b&gt;  on the handle to the new process returned by both calls. Remember to close those  handles!&lt;/p&gt;  &lt;h3&gt;Other newer platforms (Pocket PC 5.0, Smartphone 2003, Smartphone 5.0)&lt;br /&gt;&lt;/h3&gt;  &lt;p&gt;The simple method of running unload.exe does not work in newer Windows Mobile  platforms: Smartphone 2003, Pocket PC 5.0, Smartphone 5.0. Microsoft wants to  move anything regarding mobile device management and configuration to its CSP (&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mobilesdk5/html/wce51conconfigurationserviceproviderreferenceforwindowsmobiledevices.asp"&gt;Configuration  Service Provider&lt;/a&gt;) architecture. UnInstalling program is one CSP. UnInstall  Configuration Service Provider uninstalls applications from the device. A  provisioning document that contains XML to uninstall an application should  contain &lt;i&gt;only&lt;/i&gt; that XML and no other provisioning information. &lt;/p&gt; &lt;p&gt;MSDN documentation states that using UnInstall CSP is "&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mobilesdk5/html/wce51grfuninstallcsp.asp"&gt;the&lt;br /&gt;cleanest way to uninstall an application under the transactioning model for&lt;br /&gt;Windows Mobile Version 5.0 software for Smartphones&lt;/a&gt;". Actually it is also the case for  Smartphone 2003 device. &lt;/p&gt; &lt;p&gt;Below is a code snippet for such purpose:&lt;/p&gt; &lt;font face="Courier" size="2"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;// build an XML for UnInstallation&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;// using stack , sloppy code&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;TCHAR szProvXML[512];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;LPTSTR szPvXMLOut = NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;memset(szProvXML, 0, 512*sizeof(TCHAR));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;wcscat(szProvXML, TEXT(&amp;quot;&amp;lt;wap-provisioningdoc&amp;gt;&amp;lt;characteristic type=\&amp;quot;UnInstall\&amp;quot;&amp;gt;&amp;lt;characteristic type=\&amp;quot;&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;wcscat(szProvXML, TEXT("TestingApp"));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;wcscat(szProvXML, TEXT(&amp;quot;\&amp;quot;&amp;gt;&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;wcscat(szProvXML, TEXT(&amp;quot;&amp;lt;parm name=\&amp;quot;uninstall\&amp;quot; value=\&amp;quot;1\&amp;quot;/&amp;gt;&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;wcscat(szProvXML, TEXT(&amp;quot;&amp;lt;/characteristic&amp;gt;&amp;lt;/characteristic&amp;gt;&amp;lt;/wap-provisioningdoc&amp;gt;&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;HRESULT hr = DMProcessConfigXML(szProvXML, CFGFLAG_PROCESS, &amp;amp;szPvXMLOut);&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;y=0&amp;as_q=%22[Setup%20Install%20unInstall%20Upgrade]%22"&gt;[Setup / Install / unInstall / Upgrade]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114386133510839575?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114386133510839575/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114386133510839575' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114386133510839575'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114386133510839575'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/03/programmatically-uninstallremovedelete.html' title='Programmatically unInstall/remove/delete one program in Windows Mobile devices'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114370582791673465</id><published>2006-03-02T21:01:00.000-08:00</published><updated>2006-03-31T17:50:15.206-08:00</updated><title type='text'>How to retrieve/get TO, CC, BCC recipient address of an email through CEMAPI (C++) in Windows Mobile device?</title><content type='html'>&lt;p style="font-weight: bold;"&gt;How to retrieve/get TO, CC, BCC recipient address of an email through CEMAPI  (C++) in Windows Mobile device?&lt;/p&gt; &lt;p&gt;Whenever you deal with email application through MAPI (or, CEMAPI, the  trimmed version in Windows Mobile devices), quite possibly you need to load TO  addresses, CC addresses from a given email message (or BCC addresses in case the  message is in "&lt;b&gt;draft&lt;/b&gt;" folder or "&lt;b&gt;Sent Item&lt;/b&gt;"  folder) . For example, when developing a mail transport, you not only need to  synchronize the account's inbox with the remote server, but also have to deal  with outgoing messages. Inevitably, you have to know TO/CC/BCC of any outgoing  message.&lt;/p&gt; &lt;p&gt;Intuitive thought is to query them as corresponding properties from the  message object &lt;b&gt;IMessage &lt;/b&gt;using its &lt;b&gt;GetProps&lt;/b&gt; method. Although the  CEMAPI documentation is scarce, one can still find such properties from the  header files:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;PR_DISPLAY_BCC&lt;/li&gt;&lt;li&gt;PR_DISPLAY_CC&lt;/li&gt;&lt;li&gt;PR_DISPLAY_TO&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Unfortunately all of three properties returned me empty strings, at least in  Pocket PC 2003 devices. Time to take a google search to see whether other people ran into the same issue. I did find two fellow clueless guys, who posted  the question but got no useful answers:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;a href="http://groups.google.com/group/microsoft.public.win32.programmer.messaging/browse_thread/thread/8928a2708b3686ec/c0441a61f00d7e04?lnk=st&amp;q=to+cc+bcc+cemapi&amp;amp;rnum=1&amp;hl=en#c0441a61f00d7e04"&gt;How to get TO, CC, BCC address list from IMessage object? &lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://groups.google.com/group/microsoft.public.pocketpc.developer/browse_thread/thread/f0b71c9dcc0e5626/1351fbbecd585f10?lnk=st&amp;amp;amp;amp;amp;q=to+cc+bcc+cemapi&amp;rnum=3&amp;amp;hl=en#1351fbbecd585f10"&gt;how to retrive the cc and bcc recipient of an email through cemapi in evc 4.0&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;So I had to take the more complex approach, using the  recipient table. Every message has a recipient table. Each record in the  recipient table is a recipient, and has a couple of properties/columns. As with  any other MAPI stuff, an email address is a property, a recipient's name is also  a property, and an address type (TO/CC/BCC) is also a property.&lt;/p&gt; &lt;p&gt;So I changed my simple code to a slightly longer one:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;opening the recipient table by calling &lt;b&gt;GetRecipientTable&lt;/b&gt;, &lt;/li&gt;&lt;li&gt;setting the interested properties by calling &lt;b&gt;SetColumns&lt;/b&gt;, &lt;/li&gt;&lt;li&gt;iterating through the table record-by-record by calling &lt;b&gt;QueryRows&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Heck! This seemingly perfect and innocent code still did not work. After a  debug, I soon realized that &lt;b&gt;SetColumns&lt;/b&gt; returns a COM error meaning not  implemented. Not surprisingly, CEMAPI is not the full-fleged MAPI in the desktop  world, and here we tasted a slight bitterness.&lt;/p&gt; &lt;p&gt;So the natural solution is to loop though all the properties for each record,  and figure out the type of each property. The number of the properties for each  recipient is SRow.cValues, and the type of each property is specified in  SPropValue.ulPropTag. Below is a code snippet:&lt;/p&gt;&lt;font face="Courier" size="2"&gt;&amp;nbsp;&amp;nbsp;// the hack is to loop through all rows without limiting the columns&lt;br /&gt;&amp;nbsp;&amp;nbsp;HRESULT hr = pMessage-&amp;gt;GetRecipientTable(0, &amp;amp;pRecipientTable);&lt;br /&gt;&amp;nbsp;&amp;nbsp;EXIT_ON_FAILED(hr);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// iterate all the recipients&lt;br /&gt;&amp;nbsp;&amp;nbsp;while (TRUE) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hr = pRecipientTable-&amp;gt;QueryRows(1, 0, &amp;amp;pRows);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (FAILED(hr) || !pRows || pRows-&amp;gt;cRows != 1) break;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// nProps is the number of columns in the recipient table&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int nProps = pRows-&amp;gt;aRow[0].cValues;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ULONG ulReceipType = 0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// loop through all the properties&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (int ii = 0; ii &amp;lt; nProps; ii++) {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ULONG ulPT = pRows-&amp;gt;aRow[0].lpProps[ii].ulPropTag;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;switch (ulPT) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case PR_EMAIL_ADDRESS:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// This is the email address&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;szReceipEmail = pRows-&amp;gt;aRow[0].lpProps[ii].Value.LPSZ;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case PR_RECIPIENT_TYPE:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// this is the recipient type: TO/CC/BCC&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ulReceipType = pRows-&amp;gt;aRow[0].lpProps[ii].Value.ul;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case PR_DISPLAY_NAME:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// this is the display name&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;szReceipName = pRows-&amp;gt;aRow[0].lpProps[ii].Value.LPSZ;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;default:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;// switch&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BOutlook%20Transport%20MAPI%5D%22"&gt;[Outlook  / Transport / MAPI]&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114370582791673465?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114370582791673465/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114370582791673465' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114370582791673465'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114370582791673465'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/03/how-to-retrieveget-to-cc-bcc-recipient.html' title='How to retrieve/get TO, CC, BCC recipient address of an email through CEMAPI (C++) in Windows Mobile device?'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114361969749628341</id><published>2006-02-21T00:05:00.000-08:00</published><updated>2006-03-31T17:54:06.216-08:00</updated><title type='text'>How to programmatically query mail account information in Windows Mobile devices, for example, incoming server and username?</title><content type='html'>&lt;p&gt;&lt;span style="font-weight: bold;"&gt;How to programmatically query mail account information in Windows Mobile devices, for example, incoming server and username?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Pocket Outlook manages a few mail accounts. Out of box there is an account  called "Outlook E-Mail", which is used to synchronize with Desktop  Outlook. For Pocket PC Phone edition and Smartphones, out of box there is another account called "Text Messages", which is used to store SMS. Besides, a  user can create new accounts using Pocket Outlook's New Account Wizard and  manually typing required information, such as incoming server, outgoing server,  username, mail transport (POP3 or IMAP4, or customized ones), and the etc.&lt;/p&gt; &lt;p&gt;Developers can programmatically create mail accounts using omnipotent &lt;b&gt;DMProcessConfigXML&lt;/b&gt;.  The CSP (Configuration Service Provider) to use is &lt;b&gt;EMAIL2&lt;/b&gt;. &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/guide_ppc/html/ppc_wce51samprovisioningtwoaccountsozup.asp"&gt;Read  the great example in MSDN&lt;/a&gt; on how to achieve this purpose.&lt;br /&gt;&lt;br /&gt;There is not much to talk about how to create a mail account. What I am trying  to tackle here is how to query back the mail account information, for example,  trying to enumerate all the mail accounts that a user has setup in Pocket  Outlook, and get the authentication and server information. Such information is  useful and handy, if you have your own pieces of application that deals with  mail accounts, and you want to prevent users from having to manually type all  the information in twice (once in the mail setup and once in your application). &lt;/p&gt; &lt;p&gt;For 5.0 devices, Microsoft provides a new managed namespace to deal with  Outlook: &lt;b&gt;Microsoft.WindowsMobile.PocketOutlook&lt;/b&gt;. &lt;b&gt;EmailAccountCollection&lt;/b&gt;  class defines the set of all e-mail accounts that are currently configured on  the mobile device. However, the class &lt;b&gt;EmailAccount&lt;/b&gt; only provides account  name and transport name, which is far less than enough for our purpose. Besides,  we also need to target Pocket PC 2003 devices, which does not the managed  environment yet.&lt;/p&gt; &lt;p&gt;&lt;b&gt;DMProcessConfigXML&lt;/b&gt; is the natural way (and seemingly the only way) to  go.  The trouble is, you need to feed this nice API with a GUID, like the  following:&lt;/p&gt;&lt;font face="Courier" size="2"&gt; &amp;lt;wap-provisioningdoc&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;characteristic type=&amp;quot;EMAIL2&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;characteristic-query type=&amp;quot;{D671C70B-8EE3-4881-8045-2AEE6F731B55}&amp;quot;/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/characteristic&amp;gt;&lt;br /&gt;&amp;lt;/wap-provisioningdoc&amp;gt;&lt;br /&gt; &lt;br /&gt;&lt;/font&gt;&lt;p/&gt;&lt;p/&gt;What the heck? Why not simply using the human-readable human-memorable  account name, which is unique anyway? Well, the guys in Redmond apparently  developed a better appetite to consume GUIDs, which can be supplied, indeed,  infinitely. Of course, not infinitely in strict mathematical sense. So in  addition to CSLID, IID, LIBID, ..., we have another GUID, the ID to identify  each mail account.&lt;/p&gt; &lt;p&gt;Now we need to solve the simple problem of digging out the GUID for each  account. How about trying the usual hack to search in registry? No! It does not  work. No such information is stored in registry.&lt;/p&gt; &lt;p&gt;Do not give up yet. So let us resort to our friend MAPI here. Hate it or love  it, the more than 10-year-old MAPI still powers messaging applications in  Windows kingdom, under the hood of CDO or later Outlook PIA. With MAPI being so ancient,  you can easily smell its unusualness from its way of using complex structures to  define properties and make everything a table of records, every record a number  of properties.&lt;/p&gt; &lt;p&gt;And a little bit of knowledge how Pocket Outlook's mail account is linked to  an MAPI store. Each mail account is associated with a MAPI store, and a  transport. A store is a store, for storing email folders and email messages. The  transport is responsible for synchronizing a mail account by talking to the  remote server. Outlook itself manages UI and coordinates the transport and the  store. Enough with the abstract stuff, two concrete samples: "Outlook  E-Mail" is associated with a store called "ActiveSync",  "Text Messages" is associated with a store called "SMS".&lt;/p&gt; &lt;p&gt;Back to the main topic: What we need to do is to using MAPI to achieve two  purposes:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;Enumerate all mail accounts&lt;/li&gt;&lt;li&gt;Find GUID for each account&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The first purpose is easy to achieve. We just need to enumerate all MAPI  stores. The straightforward approach is to open the message store table and  iterate through all records; for each record, we load the MAPI store name.&lt;/p&gt; &lt;p&gt;The second purpose is a little harder to fulfill. Digging in "cemapi.h",  the main header file for CEMAPI (a trimmed version of MAPI for CE device), one  line caught my eye:&lt;/p&gt;&lt;font face="Courier" size="2"&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// This property is to uniquely identify a store. It's a guid.&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#define PR_CE_UNIQUE_STORE_ID       PROP_TAG(PT_CLSID, 0x8113)&lt;br/&gt; &lt;br /&gt;&lt;/font&gt;&lt;p&gt;Aha! Here we are. This must be the GUID we need. See the comment, its name  and the type, exactly a GUID. Since this is a property associated with a store,  we can query it in two ways:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;While iterating through the records in the message store table, we request      a column &lt;b&gt;PR_CE_UNICODE_STORE_ID&lt;/b&gt; when inspecting each record;&lt;/li&gt;&lt;li&gt;Or, we can load the &lt;b&gt;PR_ENTRY_ID&lt;/b&gt; for each MAPI store, and open the      store then query the property by calling &lt;b&gt;GetProps&lt;/b&gt;.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The first approach saves both coding and runtime computation, so below is the code  following first approach.&lt;/p&gt; &lt;p&gt;Notice "ActiveSync" and "SMS" are not inspected by the  code. This is anticipated, as they do not have "username" or  "incoming server" in the normal sense. Also notice EMAIL2 won't give you the password :)&lt;br /&gt;&lt;/p&gt; &lt;font face="Courier" size="2"&gt;#include &amp;quot;cfgmgrapi.h&amp;quot;&lt;br /&gt;// Query a mail account information using DMProcessConfigXML API&lt;br /&gt;// IN: the account GUID&lt;br /&gt;HRESULT QueryAccountInfo(LPCTSTR szAccountGUID)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; LPTSTR szProvXMLOut = NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp; TCHAR szProvXMLIn[512];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; memset(szProvXMLIn, 0, 512*sizeof(TCHAR));&lt;br /&gt;&amp;nbsp;&amp;nbsp; wcscat(szProvXMLIn, TEXT(&amp;quot;&amp;lt;wap-provisioningdoc&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;characteristic type=\&amp;quot;EMAIL2\&amp;quot;&amp;gt;&amp;lt;characteristic-query type=\&amp;quot;&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp; wcscat(szProvXMLIn, szAccountGUID);&lt;br /&gt;&amp;nbsp;&amp;nbsp; wcscat(szProvXMLIn, TEXT(&amp;quot;\&amp;quot;/&amp;gt;&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp; wcscat(szProvXMLIn, TEXT(&amp;quot;&amp;lt;/characteristic&amp;gt;&amp;lt;/wap-provisioningdoc&amp;gt;&amp;quot;));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; HRESULT hr = DMProcessConfigXML(szProvXMLIn, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CFGFLAG_PROCESS, &amp;amp;szProvXMLOut);&lt;br /&gt;&amp;nbsp;&amp;nbsp; if (!FAILED(hr)) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//...&lt;br /&gt;&amp;nbsp;&amp;nbsp; } else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// ... do error handling&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; ALERT(szProvXMLOut);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; DELETE_STR(szProvXMLOut);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; return hr;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// Query all stores&lt;br /&gt;HRESULT QueryMsgStore(IMAPISession* pMAPISession)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; HRESULT hr = S_OK;&lt;br /&gt;&amp;nbsp;&amp;nbsp; IMAPITable* pMsgStoresTable = NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp; LPSRowSet pRows = NULL;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; enum {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ePR_DISPLAY_NAME,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ePR_CE_UNIQUE_STORE_ID, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NUM_COLS&lt;br /&gt;&amp;nbsp;&amp;nbsp; };&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; // These tags represent the attachment prop information &lt;br /&gt;&amp;nbsp;&amp;nbsp; // we would like to pick up&lt;br /&gt;&amp;nbsp;&amp;nbsp; SizedSPropTagArray(NUM_COLS, Columns) = &lt;br /&gt;&amp;nbsp;&amp;nbsp; {&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NUM_COLS,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PR_DISPLAY_NAME,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PR_CE_UNIQUE_STORE_ID, &lt;br /&gt;&amp;nbsp;&amp;nbsp; };&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; // get the message store table&lt;br /&gt;&amp;nbsp;&amp;nbsp; hr = pMAPISession-&amp;gt;GetMsgStoresTable(0, &amp;amp;pMsgStoresTable);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EXIT_ON_FAILED(hr);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; // Get the display name and all store IDs &lt;br /&gt;&amp;nbsp;&amp;nbsp; // for each message store&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hr = pMsgStoresTable-&amp;gt;SetColumns((LPSPropTagArray)&amp;amp;Columns, 0);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EXIT_ON_FAILED(hr);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; // loop through &lt;br /&gt;&amp;nbsp;&amp;nbsp; while (TRUE) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hr = pMsgStoresTable-&amp;gt;QueryRows(1, 0, &amp;amp;pRows);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (FAILED(hr) || pRows-&amp;gt;cRows != 1) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!FAILED(hr)) hr = E_FAIL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EXIT_ON_FAILED(hr);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (PR_DISPLAY_NAME == &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pRows-&amp;gt;aRow[0].lpProps[ePR_DISPLAY_NAME].ulPropTag&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;&amp;amp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PR_CE_UNIQUE_STORE_ID == &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pRows-&amp;gt;aRow[0].lpProps[ePR_CE_UNIQUE_STORE_ID].ulPropTag) {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // this is the display name column&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TCHAR *pszStoreName = pRows-&amp;gt;aRow[0].lpProps[0].Value.LPSZ;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ALERT(pszStoreName);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Now we got the GUID&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LPGUID pGUID = pRows-&amp;gt;aRow[0].&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lpProps[ePR_CE_UNIQUE_STORE_ID].Value.lpguid;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TCHAR szAccountGUID[40] = {0};&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; memset(szAccountGUID, 0, 40*sizeof(TCHAR));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; wsprintf(szAccountGUID, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TEXT(&amp;quot;{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}&amp;quot;), &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pGUID-&amp;gt;Data1, pGUID-&amp;gt;Data2, pGUID-&amp;gt;Data3, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pGUID-&amp;gt;Data4[0], pGUID-&amp;gt;Data4[1], &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pGUID-&amp;gt;Data4[2], pGUID-&amp;gt;Data4[3], &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pGUID-&amp;gt;Data4[4], pGUID-&amp;gt;Data4[5], &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pGUID-&amp;gt;Data4[6], pGUID-&amp;gt;Data4[7]);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; QueryAccountInfo(szAccountGUID);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (pRows) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FreeProws(pRows);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pRows = NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;FuncExit:&lt;br /&gt;&amp;nbsp;&amp;nbsp; if (pRows) FreeProws(pRows);&lt;br /&gt;&amp;nbsp;&amp;nbsp; RELEASE_COMOBJ(pMsgStoresTable);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; return hr;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BOutlook%20Transport%20MAPI%5D%22"&gt;[Outlook / Transport / MAPI]&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114361969749628341?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114361969749628341/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114361969749628341' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114361969749628341'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114361969749628341'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/02/how-to-programmatically-query-mail.html' title='How to programmatically query mail account information in Windows Mobile devices, for example, incoming server and username?'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114353349604091681</id><published>2006-02-12T00:09:00.000-08:00</published><updated>2006-03-29T18:50:51.546-08:00</updated><title type='text'>TransportDemo sample in Pocket PC 5.0 SDK does not work? Check the solution here...</title><content type='html'>&lt;p style="font-weight: bold;"&gt;TransportDemo sample in Pocket PC 5.0 SDK does not  work? Check the solution here...&lt;/p&gt; &lt;p&gt;I am going to start a new category "Outlook and MAPI related". I  have been developing a customized mail transport for Pocket Outlook for quite  some time, and have programmed MAPI extensively.&lt;/p&gt; &lt;p&gt;A good start to learn how to write a customized mail transport is to read the  &lt;b&gt;TransportDemo&lt;/b&gt; sample shipped in both Windows Mobile 2003 SDK and Windows  Mobile 5.0 SDK. It gives the reader good heads-up what important methods to  implement (&lt;b&gt;IMailSyncHandler&lt;/b&gt;), what to export in the transport DLL (&lt;span style="font-weight: bold;"&gt;OneStopFactory&lt;/span&gt;),  and how to register the transport in registry. The sample does not really  synchronize a mail account, nor does it send outgoing emails. And, the sample  does not show how to programmatically provision a new mail account based on the  customized transport (&lt;i&gt;a possible new blog post here?&lt;/i&gt;); rather, it  anticipates the reader to manually create one via Pocket Outlook's New Account  Wizard.&lt;/p&gt; &lt;p&gt;With all the above being said, I found that I could not create a new account  in Pocket PC 5.0 emulator. I tried both manual creation using Outlook's New  Account Wizard, and programmatic way using &lt;b&gt;DMProcessConfigXML&lt;/b&gt;. The  account simply does not show up. Soon I realized the account WAS created, but was NOT  listed in Outlook, based on the following three reasons: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Since I had already worked on a customized transport in Pocket PC 2003 and Smartphone 2003 for quite some time, I was pretty sure that I built the DLL and registered the transport in the registry correctly.&lt;/li&gt;&lt;li&gt;Further, the account must already have been created, as I could not      created a second one with the same name.&lt;/li&gt;&lt;li&gt;Further, I could easily query back the account information using &lt;b&gt;DMProcessConfigXML&lt;/b&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;A quick google group search reveals three  fellow victims:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;a href="http://groups.google.com/group/microsoft.public.smartphone.developer/browse_frm/thread/23ada804872b9662/67a722c412131143?lnk=st&amp;q=transportdemo+5.0&amp;amp;rnum=1#67a722c412131143"&gt;Custom      transports for PPC2005 Inbox.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://groups.google.com/group/microsoft.public.smartphone/browse_frm/thread/2cd7666d00c42b6/8497e7b36dd68db5?lnk=st&amp;q=transportdemo+5.0&amp;amp;rnum=2#8497e7b36dd68db5"&gt;Tansportdemo      sample can's create a account in Inbox&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://groups.google.com/group/microsoft.public.pocketpc.developer/browse_frm/thread/2d61ba044e88150c/150a528f0ff60566?lnk=st&amp;q=transportdemo+5.0&amp;amp;rnum=3#150a528f0ff60566"&gt;Programmatically      create an Inbox Account&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;None of them found the solution. So I was on my own here. Why the account was created but could not be displayed? Could it be caused by  the fact that I did not sign the DLL, as Pocket PC 5.0 is most probably a  "one-tier-prompt" device (&lt;i&gt;security-related, another big category in  my mind&lt;/i&gt;)? Soon I dismissed this possibility. I tried two methods to rule out  the security concern. First method was to sign the DLL using the SDK privileged  certificate ("&lt;b&gt;SDKSamplePrivDeveloper.pfx&lt;/b&gt;"), and load the  certificate to the emulator (&lt;i&gt;how? a possible new blog post&lt;/i&gt;). Second  method was to disable security settings in the emulator (&lt;i&gt;how? a possible new  blog post&lt;/i&gt;). In both cases, the account simply refused to show up.&lt;/p&gt;  &lt;p&gt;In despair, I wrote a small program to load my own DLL and call the function  "&lt;b&gt;OneStopFactory&lt;/b&gt;". Arrrr... &lt;b&gt;LoadLibrary&lt;/b&gt;() failed!! Till  this point, I knew the reason: Certain DLLs must be missing in the emulator.  After running depends.exe (although in my desktop PC, but still emitted some  traces), I found that "&lt;b&gt;msvcr80d.dll&lt;/b&gt;" is required. So I copied  it from my desktop ("&lt;b&gt;C:\Program Files\Microsoft Visual Studio 8\VC\ce\Dll\armv4i&lt;/b&gt;")  to the Pocket PC 5.0 emulator. Upon restarting Pocket Outlook, all  previously-created accounts showed up.&lt;br /&gt;&lt;/p&gt; &lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BOutlook%20Transport%20MAPI%5D%22"&gt;[Outlook / Transport / MAPI]&lt;/a&gt;&lt;/span&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114353349604091681?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114353349604091681/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114353349604091681' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114353349604091681'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114353349604091681'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/02/transportdemo-sample-in-pocket-pc-50.html' title='TransportDemo sample in Pocket PC 5.0 SDK does not work? Check the solution here...'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114334315048271402</id><published>2006-02-03T19:15:00.000-08:00</published><updated>2006-03-31T17:55:43.300-08:00</updated><title type='text'>How to put your own Control Panel Applet to "Personal" Group?</title><content type='html'>&lt;span style="font-weight: bold;"&gt;How to put your own Control Panel Applet to "Personal" Group?&lt;/span&gt;&lt;p&gt;In Pocket PC 2003 and Pocket PC 5.0, there are three groups of Control Panel Applets: "Personal", "System" and "Connection". Looks like if you simply build a CPL file and export "CPlApplet" function, your Applet will be displayed in the "System" group. No exception is mine. However, quite some users and managers along my management chain think that our Control Panel Applet should be put into "Personal" group. I agree. It is used by the user to control his preferred email-reading-and-composing behavior, which apparently, has nothing to do with any system-wide activity. So I was dispatched the task to drop the Applet to "Personal" group.&lt;/p&gt;&lt;p&gt;I failed to find any useful documentation by searching in major searching engines and MSDN documentation, at the time when I was starting to working on it. I do found an unfamiliar CPL_IDNAME message, with the following description in Pocket PC 2003 SDK documentation:&lt;br /&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;i&gt;This message is sent to the Control Panel application to retrieve its unique name string. This string can be used to find its data in the registry.&lt;/i&gt;&lt;br /&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Man, guess no people can understand what the heck is "... to find its data in the registry...". So I decide to take a look at Pocket PC 5.0 SDK documentation, hoping I could find more up-to-date explanation:&lt;br /&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;i&gt;The &lt;b&gt;CPL_IDNAME&lt;/b&gt; message is sent to the &lt;a href="mob5lrfcplapplet.htm"&gt;CPlApplet &lt;/a&gt;function to retrieve a Control Panel application's unique ID name string.&lt;/i&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;Handling of this message is required only if the application icon exists in a Settings application tab other than the default &lt;b&gt;System&lt;/b&gt; tab. When this message is received, the &lt;a href="mob5lrfcplapplet.htm"&gt;CPlApplet &lt;/a&gt;function must copy the ID name of the application (specified by uAppNum) into the pszName parameter. The ID name can be used to retrieve or set information about the application via the registry subkey &lt;code&gt;&lt;b class="cfe"&gt;[HKEY_LOCAL_MACHINE\ControlPanel\&amp;lt;IDname&amp;gt;]&lt;/b&gt;&lt;/code&gt;. The primary data under this  subkey is &lt;code&gt;&lt;b class="cfe"&gt;"Group" = dword:1&lt;/b&gt;&lt;/code&gt;. The possible values for the &lt;b&gt;Group&lt;/b&gt; data indicate the tab of the Settings application where the application icon exists.&lt;/i&gt;&lt;br /&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Yes, there we are. So below are what we need to do to list the CPL in "Personal" Group, whose group number is 0. Assume the IDName is called "TestingApp". By the way, this name does not need to be your real application name.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;Must-Do 1: Register the ID Name in the specified registry hive. You can put the following code in your setup DLL's Install_Exit function.&lt;/b&gt;&lt;br /&gt;&lt;/p&gt;&lt;font face="Courier" size="2"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Set up registry keys&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// [HKEY_LOCAL_MACHINE\ControlPanel\TestingApp\]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Groupe=dword:0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TCHAR szKeyBase[MAX_PATH];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_tcscpy(szKeyBase, TEXT(&amp;quot;\\ControlPanel\\TestingApp&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LRESULT lr = Registry_SetDWordValue(HKEY_LOCAL_MACHINE,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;szKeyBase, TEXT(&amp;quot;Group&amp;quot;), dwGroup);&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Must-Do 2: Respond to CPL_IDNAME in CPlApplet function.&lt;/b&gt;&lt;font face="Courier" size="2"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case CPL_IDNAME:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UINT uApp = lParam1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LPWSTR pszName = (LPTSTR)lParam2;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_tcscpy(pszName, TEXT(&amp;quot;TestingApp&amp;quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;Must-Do 3: Remember to remove the registry hive in your un-Install code. You can put such code in your setup DLL's Uninstall_Exit function.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Alternatively, you do not really need to write code for Must-Do 1 and Must-Do 3. In your .INF file for CabWiz, adding the following sections:&lt;br /&gt;&lt;/p&gt;&lt;font face="Courier" size="2"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[DefaultInstall]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CopyFiles&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;= XXXXX&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AddReg&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = Reg.CPLApplet&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Reg.CPLApplet]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;HKLM,ControlPanel\%AppName%,Group,0x00010001,0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;; assuming you alrady defined AppName=TesinngApp&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;p&gt;That is it! Microsoft Cab installer will take care the steps to add the registry key during installation, and remove the registry key during un-installation.&lt;/p&gt;&lt;p&gt;Below is a screen cut showing "TestingApp" is put into "Personal" group:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://windowsmobilepro.home.comcast.net/CPInPersonal2.jpg" alt="putting demostration Pocket PC Control Panel Applet into Personal Group" border="0" height="564" width="469" /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BControl%20Panel%5D%22"&gt;[Control Panel]&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114334315048271402?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114334315048271402/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114334315048271402' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114334315048271402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114334315048271402'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/02/how-to-put-your-own-control-panel.html' title='How to put your own Control Panel Applet to &quot;Personal&quot; Group?'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114318769238387780</id><published>2006-01-24T00:02:00.000-08:00</published><updated>2006-03-29T14:29:44.163-08:00</updated><title type='text'>Pocket PC Power Management Series 9: Battery Life Matters</title><content type='html'>&lt;p style="font-weight: bold;"&gt;Pocket PC Power Management Series 9: Battery Life Matters&lt;/p&gt;&lt;p&gt;In my previous series, I talked about the reasons why Pocket PC's battery life is not that great in general. Part of the reason is the intrinsic design problems that we developers have to live with. This reminds me of what the VP in my company once talked to me regarding the battery life in Symbian devices.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Symbian OS runs in a much larger number of handheld units worldwide. Very possibly you, as the reader, is using a phone powered by Symbian OS. In general, the Symbian phones have considerably longer battery life than Pocket PCs (and smartphones). My VP once had a conversation with Symbian guys how they achieve the goal to save battery. His wonder is understandable, since Symbian OS is also numerous lines of human-made codes, so there is no magic. The answer from Symbian guys is that they have put battery-life as the top priority when the OS was designed. They make the kernel and shell very efficient in terms of CPU usage.&lt;/p&gt;&lt;p&gt;One can argue that Windows CE is much more powerful than Symbian OS, so a little more power-hungry is acceptable. Well, probably the argument is not to the point. Smartphone is also powered by Windows CE OS, but have better battery life than Pocket PC. Again, one can argue that smartphone does not have a touch screen, and its LCD is much smaller than that of Pocket PC, so smartphone's LCD consumes less power than Pocket PC. Well, probably the point is missed again. How do you explain the mysterious "\Software\Microsoft\Shell\LowMem" registry setting in Smartphone (which controls how the Shell killed user application at will)? Looks like in Pocket PC, Microsoft suspends itself and all user applications to save battery. In smartphones, Microsoft changed the strategy. It kills user applications to save battery!&lt;/p&gt;&lt;p&gt;Enough for the debate. Developers have to live with it anyway, and have to code prudently to not unnecessarily burn precious battery. How? Again I strongly recommend you to read the two excellent articles from Mike Calligaro:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://blogs.msdn.com/windowsmobile/archive/2005/08/03/447404.aspx"&gt;Power to the Developers part 1&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://blogs.msdn.com/windowsmobile/archive/2005/08/11/450591.aspx"&gt;Power to the Developers part 2&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Mike generalizes the following principles:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Don't use the CPU unless you really need to&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Stop using the CPU as soon as you can&lt;br /&gt;  &lt;ul&gt;&lt;li&gt;Stop using the CPU when your app isn't in the foreground.&lt;br /&gt;  &lt;/li&gt;&lt;li&gt;Stop using the CPU if the user hasn't interacted with your app for a little while&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Also Mike presents a great multi-threaded sample to catch any power state change reported by OS's Power Manager.&lt;/p&gt;Still we may have to develop certain applications that need to run continuously (I called it case-1 programs), or applications that need to run periodically (I called it case-2 programs). See my &lt;a href="http://windowsmobilepro.blogspot.com/2005/10/pocket-pc-power-management-series-2.html"&gt;Series&lt;/a&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2005/10/pocket-pc-power-management-series-2.html"&gt; 2&lt;/a&gt; for the problem domain and &lt;a href="http://windowsmobilepro.blogspot.com/2005/12/pocket-pc-power-management-series-5.html"&gt;Series&lt;/a&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2005/12/pocket-pc-power-management-series-5.html"&gt; 5&lt;/a&gt; for details of case-1 and case-2. For such programs, Mike's principles still apply, but I'd like to add the following suggestions specific to our problem domain:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Prefer CeSetUserNotificationEx than SystemIdleTimerReset. The latter one I&lt;br /&gt;called it &lt;a href="http://windowsmobilepro.blogspot.com/2005/12/pocket-pc-power-management-series-5.html"&gt;a brutal way to force the device to run&lt;/a&gt;, and the former one &lt;a href="http://windowsmobilepro.blogspot.com/2005/12/pocket-pc-power-management-series-6.html"&gt;a gentle way to request the device to run&lt;/a&gt;. You may not really need to run the program continuously. "Downgrade" to running periodically if possible.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Offer your user a choice to control the time period and frequency when the program runs. I bet the user will thank you for your extra work in putting a Control Panel Applet there!&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Make sure not to turn on the display unnecessarily even when your program has to run unattended. Some options of CeSetUserNotificationEx might turn on the LCD display, but probably only on some models. You need to diligently test the physical device.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The ancient advice holds true: Make your code efficient. Avoid unnecessary loop. Cache your data if making sense. Do not write too computationally-intensive code. The list goes on and on. In general, if you come from Desktop Windows world and probably forget those algorithms taught in data structure classes, now probably is time to pick up again!&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BPower%20Management%5D%22"&gt;[Power Management]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114318769238387780?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114318769238387780/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114318769238387780' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114318769238387780'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114318769238387780'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/01/pocket-pc-power-management-series-9.html' title='Pocket PC Power Management Series 9: Battery Life Matters'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114301268986904160</id><published>2006-01-12T23:30:00.000-08:00</published><updated>2006-03-25T17:25:27.226-08:00</updated><title type='text'>Pocket PC Power Management Series 8: Why Pocket PC's Battery Life so Notorious?</title><content type='html'>&lt;p style="font-weight: bold;"&gt;Pocket PC Power Management Series 8: Why Pocket PC's Battery Life so  Notorious?&lt;/p&gt; &lt;p&gt;In my two previous Pocket PC Power Management Series (&lt;a href="http://windowsmobilepro.blogspot.com/2005/12/pocket-pc-power-management-series-5.html"&gt;Series  5&lt;/a&gt; and &lt;a href="http://windowsmobilepro.blogspot.com/2005/12/pocket-pc-power-management-series-6.html"&gt;Series  6&lt;/a&gt;), I am trying to tackle the task of writing either continuously-running or  periodically-running programs. I must admit such programs do not fit nicely into  Microsoft's Windows Mobile-powered Pocket PCs, after having working on such  applications myself for more than 1 year. Why? The fundamentally-flawed design  of the Pocket PC devices prevent any good developer from developing really  battery friendly programs.&lt;/p&gt; &lt;p&gt;When Pocket PC device was initially designed, Microsoft made the decision  that the device should never shutdown, probably by following Palm's design.  Unless battery is removed, the device is always "alive".  Unfortunately, Microsoft's OS is a trimmed version of its bigger brother Desktop  Windows. Desktop Windows was never designed to be CPU or power friendly; in  fact, desktop Windows seems to be proudly following the path of being more and  more power hungry. Windows CE, trimmed down in the sense of fewer APIs, does not  have any luxury of touching the underlying OS layer to make it more battery  friendly. So I guess Pocket PC team had to make the decision to force the OS to  sleep frequently to save power. The basic idea is like: Aha, CPU is running and  burning battery. How about I force it not to run?&lt;/p&gt; &lt;p&gt;This idea apparently does not fly, or at least, does not fly well. Why? As  Mike Calligaro from Microsoft points out, "Staying on all the time actually  burns less power than going to sleep." Why? "The issue is that it  takes a 'long' time to go to sleep and a similarly long time to wake back  up." &lt;a href="http://blogs.msdn.com/windowsmobile/archive/2005/08/01/446240.aspx"&gt;Please  read his excellent post for details.&lt;/a&gt;&lt;/p&gt; &lt;p&gt;To make matter worse, Pocket PC 2003 uses RAM as storage. RAM must be powered  constantly to keep its stuff, even if the device is sleeping. This is another  big battery sucker. As &lt;a href="http://blogs.msdn.com/windowsmobile/archive/2005/07/14/438991.aspx"&gt;Mike  Calligaro vividly pointed out in his another post&lt;/a&gt;, when you see the dire  warning saying something to the effect of, "You are running of battery.  Batter save your data now, because you're on the verge of losing it." At  that point, you can't use the device again until you plug it in.  How much  battery charge do you think you have then? Try half. Yes, when you are shut down  because your batteries were "critically low," they were still 1/4 to  1/2 full.  Why?  Because, if the batteries ever fully died, it would  be catastrophic.  You'd lose your data. So Microsoft made a requirement and  held OEMs to it.  The requirement was that, at the point where the  batteries were decided to be "critically low," they had to still have  enough power to keep the RAM charged for 72 hours.  &lt;/p&gt; &lt;p&gt;Realizing the two fundamental flaws of Pocket PC devices: (1) Forcing CPU not  to run to save battery actually consuming more battery; (2) Using RAM as storage  just does not work the way out, Microsoft learnt the lesson and designed the  smartphone platform quite differently. The smartphone does not sleep, and can be  shutdown just like a desktop computer. And, smartphone uses Flash as storage,  which consumes much less power. Both smartphone 2003 and smartphone 5.0 are like  this.&lt;/p&gt; &lt;p&gt;Unfortunately, Pocket PC 5.0 still inherits the sleeping legacy from Pocket  PC 2003, although it uses Flash as storage. That is why all my previous posts  apply to both Pocket PC 2003 and Pocket PC 5.0.&lt;/p&gt; &lt;p&gt;Next I will talk about how to make your program battery friendly. This is  particularly important, since our problem domain are applications that need to  run either continuously or periodically.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BPower%20Management%5D%22"&gt;[Power Management]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114301268986904160?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114301268986904160/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114301268986904160' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114301268986904160'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114301268986904160'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/01/pocket-pc-power-management-series-8.html' title='Pocket PC Power Management Series 8: Why Pocket PC&apos;s Battery Life so Notorious?'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114292730150920748</id><published>2006-01-08T23:46:00.000-08:00</published><updated>2006-03-25T17:25:40.570-08:00</updated><title type='text'>Pocket PC Power Management Series 7: Trap of GetTickCount, and Sleep()</title><content type='html'>&lt;p style="font-weight: bold;"&gt;Pocket PC Power Management Series 7: Trap of GetTickCount, and Sleep()&lt;/p&gt; &lt;p&gt;If you come from desktop Windows world, very possibly you developed a habit  to call &lt;a style="font-weight: bold;" href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/gettickcount.asp"&gt;GetTickCount&lt;/a&gt;&lt;span style="font-weight: bold;"&gt;()&lt;/span&gt;  to keep track how long has elapsed, for example, to wait for a time interval to  pass. Basically the API retrieves the number of milliseconds that have elapsed  since the system was started.  The elapsed time is stored as a DWORD value.  Therefore, the time will wrap around to zero if the system is run continuously  for 49.7 days. Although the warning message is printed everywhere in Microsoft  documentation and in every tutorial, programmers love to use it, thinking they  never need to track a task for as long as 59.7 days :)&lt;/p&gt; &lt;p&gt;What I want to emphasize to the desktop Windows programmers, is that  &lt;span style="font-weight: bold;"&gt;GetTickCount&lt;/span&gt;() might fail miserably in Pocket PC devices. When the Pocket PC  device is suspended, the internal timer is also suspended, thus stop increasing  value. For example, at 10:00AM your program calls &lt;span style="font-weight: bold;"&gt;GetTickCount&lt;/span&gt;() to retrieve a  DWORD value (time1), and the device runs unattended for 3 minutes then falls  asleep; after another 5 minutes, the device wakes up, and your program resumes  execution and calls &lt;span style="font-weight: bold;"&gt;GetTickCount&lt;/span&gt;() again to retrieve another DWORD value  (time2). You may anticipate the difference between time2 and time1 equals to 8  minutes. Nope! The difference is actually 3 minutes, and you just missed 5  minutes that was when the device was sleeping. &lt;/p&gt; &lt;p&gt;One solution is to use &lt;span style="font-weight: bold;"&gt;GetLocalTime&lt;/span&gt;() API to retrieve the local time as  ULONGLONG, then do arithmetic operation on two ULONGLONG values to calculate the  real time elapsed. Notice &lt;span style="font-weight: bold;"&gt;GetLocalTime&lt;/span&gt;() has one headache: You need to take  into account whether the end user changed the local time setting or not. To  avoid such headache, you call use &lt;span style="font-weight: bold;"&gt;QueryPerformanceCounter&lt;/span&gt;() for similar purpose.  Not surprisingly, &lt;span style="font-weight: bold;"&gt;QueryPerformanceCounter&lt;/span&gt;() has its own issue: It cannot sustain  device reboot. So you need to make a trade off between these two choice.&lt;/p&gt; &lt;p&gt;Similar to the trap of &lt;span style="font-weight: bold;"&gt;GetTickCount&lt;/span&gt;(), desktop programmers also need to  notice that &lt;span style="font-weight: bold;"&gt;Sleep&lt;/span&gt;() API cannot really sleep for the specified time period. Most  probably, your thread will sleep longer, sometimes much longer. Please refer to  my &lt;a href="http://windowsmobilepro.blogspot.com/2005/10/pocket-pc-power-management-series-3.html"&gt;Pocket PC Power Management Series 3&lt;/a&gt; for details, where I present a program  making use of such sleep-longer-expected feature to determine whether the device  was suspended or running.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BPower%20Management%5D%22"&gt;[Power Management]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114292730150920748?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114292730150920748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114292730150920748' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114292730150920748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114292730150920748'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2006/01/pocket-pc-power-management-series-7.html' title='Pocket PC Power Management Series 7: Trap of GetTickCount, and Sleep()'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114280268407792865</id><published>2005-12-20T13:06:00.000-08:00</published><updated>2006-04-15T00:00:08.376-07:00</updated><title type='text'>Pocket PC Power Management Series 6: Request the Device to Run: a Gentle Way</title><content type='html'>&lt;p style="font-weight: bold;"&gt;Pocket PC Power Management Series 6: Request the Device to Run: a  Gentle Way&lt;/p&gt; &lt;p&gt;In Pocket PC Power Management &lt;a href="http://windowsmobilepro.blogspot.com/2005/12/pocket-pc-power-management-series-5.html"&gt;Series  5&lt;/a&gt;, I showed how to use API SystemIdleTimerReset to force the device not to sleep. However, this technique  is an overkill and a waste if used for case-2 programs (which need to run periodically, not  continuously). Further, some utilities are known to disrupt SystemIdleTimerReset, for example, Keyguard.&lt;br /&gt;&lt;/p&gt; &lt;p&gt;A more gentle way is to request the device to run at certain time, by using the omnipotent  CeSetUserNotificationEx (see my &lt;a href="http://windowsmobilepro.blogspot.com/2005/11/pocket-pc-power-management-series-4.html"&gt;Pocket  PC Power Management Series 4&lt;/a&gt; for a brief introduction to this API). Hereby I present three ready-to-use functions. &lt;/p&gt; &lt;p style="font-weight: bold;"&gt;1. How to Use?&lt;/p&gt; &lt;p&gt;If you want to run Pocket IE to browse a URL 10 minutes later, simply call:&lt;/p&gt; &lt;p style="font-family: courier new;"&gt;  ScheduleRunApp(TEXT("&lt;a href="file://windows//iexplore.exe"&gt;\\Windows\\iexplore.exe&lt;/a&gt;"),  TEXT("URLXXX""), 600);&lt;/p&gt; &lt;p&gt;And remember to clear it after some time:&lt;/p&gt; &lt;p style="font-family: courier new;"&gt;  ClearRunApp(TEXT("&lt;a href="file://windows//iexplore.exe"&gt;\\Windows\\iexplore.exe&lt;/a&gt;"));&lt;/p&gt; &lt;p&gt;&lt;b&gt;2. Walkthrough of the functions&lt;/b&gt;&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;SecondsAfter&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;:&lt;/span&gt; It takes a pointer to SYSTEMTIME and a number of seconds,;&lt;br /&gt;upon returning, the SYSTEMTIME is modified to be exactly that number of&lt;br /&gt;seconds after the original time. For example, if original time is 10:00AM&lt;br /&gt;now, and you want to a time 10:05AM, just pass 300 as the second parameter.&lt;br /&gt;The function converts SYSTEMTTIME to FILETIME for easy arithmetic operation.&lt;/li&gt;&lt;/ul&gt;&lt;blockquote&gt;&lt;font face="Courier" size="2"&gt;&lt;br /&gt;static HRESULT SecondsAfter(SYSTEMTIME* pst, int numSeconds)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;FILETIME ft;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// convert to FILETIME then ULONGLONG for calculation&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (!SystemTimeToFileTime(pst, &amp;amp;ft)) return E_FAIL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;ULONGLONG ulLongFt = *(ULONGLONG*)&amp;amp;ft;&lt;br /&gt;&amp;nbsp;&amp;nbsp;ulLongFt += (ULONGLONG)numSeconds * 10000000;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// 10000000: how many nano seconds per second, divided by 100&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// convert back to FILETIMEand SYSTEMTIME&lt;br /&gt;&amp;nbsp;&amp;nbsp;ft = *(FILETIME*)&amp;amp;ulLongFt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (!FileTimeToSystemTime(&amp;amp;ft, pst)) return E_FAIL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return S_OK;&lt;br /&gt;}&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/font&gt;&lt;/blockquote&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;ScheduleRunApp&lt;/span&gt;: It takes an Executable name, arguments and a number of&lt;br /&gt;seconds. All parameters are self-explanatory. For example, if you pass 300&lt;br /&gt;as dwAfterSeconds, the program is scheduled to run 5 minutes after the&lt;br /&gt;function is called.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;blockquote&gt;&lt;font face="Courier" size="2"&gt;&lt;br /&gt;static HRESULT ScheduleRunApp(&lt;br /&gt;&amp;nbsp;&amp;nbsp;LPCTSTR szExeName,&lt;br /&gt;&amp;nbsp;&amp;nbsp;LPCTSTR szArgs,&lt;br /&gt;&amp;nbsp;&amp;nbsp;DWORD dwAfterSeconds)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;HRESULT hr = S_OK;&lt;br /&gt;&amp;nbsp;&amp;nbsp;HANDLE hNotify = NULL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// set a CE_NOTIFICATION_TRIGGER&lt;br /&gt;&amp;nbsp;&amp;nbsp;CE_NOTIFICATION_TRIGGER notifTrigger;&lt;br /&gt;&amp;nbsp;&amp;nbsp;memset(&amp;amp;notifTrigger, 0, sizeof(CE_NOTIFICATION_TRIGGER));&lt;br /&gt;&amp;nbsp;&amp;nbsp;notifTrigger.dwSize = sizeof(CE_NOTIFICATION_TRIGGER);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// calculate time&lt;br /&gt;&amp;nbsp;&amp;nbsp;SYSTEMTIME st = {0};&lt;br /&gt;&amp;nbsp;&amp;nbsp;GetLocalTime(&amp;amp;st);&lt;br /&gt;&amp;nbsp;&amp;nbsp;hr = SecondsAfter(&amp;amp;st, dwAfterSeconds);&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (FAILED(hr)) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return hr;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;notifTrigger.dwType = CNT_TIME;&lt;br /&gt;&amp;nbsp;&amp;nbsp;notifTrigger.stStartTime = st;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// timer: execute an exe at specified time&lt;br /&gt;&amp;nbsp;&amp;nbsp;notifTrigger.lpszApplication = (LPTSTR)szExeName;&lt;br /&gt;&amp;nbsp;&amp;nbsp;notifTrigger.lpszArguments = (LPTSTR)szArgs;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;hNotify = CeSetUserNotificationEx(0, &amp;amp;notifTrigger, NULL);&lt;br /&gt;&amp;nbsp;&amp;nbsp;// NULL because we do not care the action&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (!hNotify) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; hr = E_FAIL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;} else {&lt;br /&gt;&amp;nbsp;&amp;nbsp; // close the handle as we do not need to use it further&lt;br /&gt;&amp;nbsp;&amp;nbsp; CloseHandle(hNotify);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return hr;&lt;br /&gt;}&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;/blockquote&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;ClearRunApp&lt;/span&gt;: I want to emphasize and repeat what I said in &lt;a href="http://windowsmobilepro.blogspot.com/2005/11/pocket-pc-power-management-series-4.html"&gt;Pocket&lt;br /&gt;PC Power Management Series 4&lt;/a&gt; regarding CeSetUserNotificationEx. One&lt;br /&gt;notorious side-effect of CeSetUserNotificationEx is that the notification&lt;br /&gt;will be persisted in a central repository, unless the creator remembers to&lt;br /&gt;remove it. I've seen a couple of novice developers forgot to clear the&lt;br /&gt;notifications and subject his/her testing device to some really weird&lt;br /&gt;behaviors. So I also present ClearRunApp, which is used to clear previously&lt;br /&gt;scheduled tasks. Remember: Even if the task already ran, the notification is&lt;br /&gt;still persisted, unless cleared programmatically.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;blockquote&gt;&lt;font face="Courier" size="2"&gt;static HRESULT ClearRunApp(LPCTSTR szExeName)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;HRESULT hr = S_OK;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// hold a notification&lt;br /&gt;&amp;nbsp;&amp;nbsp;PBYTE pBuff = (PBYTE)LocalAlloc(LPTR, 8192);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (!pBuff) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return E_OUTOFMEMORY;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// at most 256 notification handles&lt;br /&gt;&amp;nbsp;&amp;nbsp;HANDLE hNotifHandlers[256];&lt;br /&gt;&amp;nbsp;&amp;nbsp;DWORD nNumHandlers, nNumClearedHandlers = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;DWORD i = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;int rc = CeGetUserNotificationHandles(hNotifHandlers,&lt;br /&gt;&amp;nbsp;&amp;nbsp;dim(hNotifHandlers), &amp;amp;nNumHandlers);&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (!rc) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hr = E_FAIL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;goto FuncExit;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// iterate all notifications&lt;br /&gt;&amp;nbsp;&amp;nbsp;// Notice: We do not care about the status of the notification.&lt;br /&gt;&amp;nbsp;&amp;nbsp;// Just clear it even if it is not filed??&lt;br /&gt;&amp;nbsp;&amp;nbsp;for (; i&amp;lt;nNumHandlers; i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// query info for this specific handler&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BOOL bClearThis = FALSE;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwSize = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rc = CeGetUserNotification(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hNotifHandlers[i], 8192, &amp;amp;dwSize, pBuff);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!rc) continue;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PCE_NOTIFICATION_INFO_HEADER pnih =&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (PCE_NOTIFICATION_INFO_HEADER)pBuff;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PCE_NOTIFICATION_TRIGGER pNotifTrigger = pnih-&amp;gt;pcent;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Notice some events with NULL lpszApplication might be inserted!&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (pNotifTrigger &amp;amp;&amp;amp; pNotifTrigger-&amp;gt;lpszApplication&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;amp;&amp;amp; !_tcsicmp(pNotifTrigger-&amp;gt;lpszApplication, szToCompare)) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CeClearUserNotification(pnih-&amp;gt;hNotification)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;FuncExit:&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (pBuff) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LocalFree(pBuff);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return hr;&lt;br /&gt;}&lt;/font&gt;&lt;/blockquote&gt;&lt;p style="font-weight: bold;"&gt;3. Further thoughts&lt;/p&gt; &lt;p&gt;If you do not need the style of "running a program AFTER some  time", rather, what you want is "running a program AT certain  time", you can simply modify ScheduleRunApp as needed.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BPower%20Management%5D%22"&gt;[Power Management]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114280268407792865?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114280268407792865/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114280268407792865' title='24 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114280268407792865'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114280268407792865'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2005/12/pocket-pc-power-management-series-6.html' title='Pocket PC Power Management Series 6: Request the Device to Run: a Gentle Way'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>24</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114275153260095789</id><published>2005-12-05T22:56:00.000-08:00</published><updated>2006-03-25T17:26:31.446-08:00</updated><title type='text'>Pocket PC Power Management Series 5: Force the Device not to Sleep: a Brutal Way?</title><content type='html'>&lt;p style="font-weight: bold;"&gt;Pocket PC Power Management Series 5: Force the Device not to Sleep: a Brutal Way?&lt;/p&gt; &lt;p&gt;In Pocket PC Power Management &lt;a href="http://windowsmobilepro.blogspot.com/2005/10/pocket-pc-power-management-series-3.html"&gt;Series  3&lt;/a&gt; and &lt;a href="http://windowsmobilepro.blogspot.com/2005/11/pocket-pc-power-management-series-4.html"&gt;Series  4&lt;/a&gt;, I demonstrated two ways to find out when the device is running, and when  it is sleeping. The techniques is not much useful, unless you need to take  certain actions when the device wakes up. Remember, there is NO WAY for you to  take action when the device falls asleep. (You may write a driver, but that is  completely out of my scope here.)&lt;/p&gt;  &lt;p&gt;Now let us move into the more interesting topic, trying to solve the problem defined in &lt;a href="http://windowsmobilepro.blogspot.com/2005/10/pocket-pc-power-management-series-2.html"&gt;Pocket PC Power Management Series 2&lt;/a&gt;. You need to write a media player, able to playing music without being suspended. Or, you need to write a stock alert program, able to monitor a stock symbol from time to time. The first case, case 1, is a continuously-running program, and the second, case 2, a periodically-running program. Apparently you do not want the OS to suspend your nicely running program abruptly, at least for the first case, the media player case.&lt;/p&gt; &lt;p&gt;Microsoft anticipates such need, and &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceui40/html/cerefSystemIdleTimerReset.asp"&gt;exposes  an API&lt;/a&gt;:&lt;/p&gt;  &lt;blockquote&gt; &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;void WINAPI SystemIdleTimerReset(void);&lt;/span&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Basically this function resets a system timer that controls whether or not the device will automatically go into a suspended state. Let us say you set the device to power down in 3 minutes on battery power (via "Settings"=&gt;"System"=&gt;"Power"=&gt;"Advanced"=&gt;"Turn off device if not used for 3 minutes"). Each time this function is called, the device will run for another 3 minutes even if not used. &lt;/p&gt; &lt;p&gt;The frequency in which to call SystemIdleTimerReset in order to keep a device awake can be determined by retrieving the following registry key:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power&lt;/span&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Value "&lt;span style="font-family: courier new;"&gt;BattPowerOff&lt;/span&gt;" determines the seconds the device will be suspended on battery power (180 standing for 3 minutes), and value "&lt;span style="font-family: courier new;"&gt;ExtPowerOff&lt;/span&gt;" determines the seconds if on AC power (0 meaning no sleeping on AC). &lt;/p&gt; &lt;p&gt;Notice this API  should be used cautiously for the following two reasons:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;It should only be used for continuously-running programs (case 1), rather than periodically-running     programs (case 2). It is a waste of battery if used for case-2 programs. For     case-2 application, the omnipotent CeSetUserNotificationEx should be used     (see my &lt;a href="http://windowsmobilepro.blogspot.com/2005/11/pocket-pc-power-management-series-4.html"&gt;Pocket     PC Power Management Series 4&lt;/a&gt; for a brief introduction to this API).&lt;/li&gt;&lt;li&gt;Some utilities are known to disturb SystemIdleTimerReset. Keyguard      is such one. Basically when your device is locked (unresponsive to any keypresses),      Keyguard is placed to prevent you from hitting the device keys accidentally      (while it is in your pocket) and prevent the backlight from coming on and      drain the battery or making unwanted phone calls. If your program starts      from sleep mode and the Keyaguard mode is on, then SystemIdleTimerReset does      not work and the device suspend after specific time. Again the solution is      to use CeSetUserNotificationEx but in a slightly more creative way.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Because of the nature of SystemIdleTimerReset, I call it a brutal way to  force the device not to sleep. In next post, I plan to discuss how to use CeSetUserNotificationEx  to more gently "request the device not to sleep", a good solution to  case-2 programs, and case-1 programs as well.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BPower%20Management%5D%22"&gt;[Power Management]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114275153260095789?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114275153260095789/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114275153260095789' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114275153260095789'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114275153260095789'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2005/12/pocket-pc-power-management-series-5.html' title='Pocket PC Power Management Series 5: Force the Device not to Sleep: a Brutal Way?'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114271474899070592</id><published>2005-11-28T12:42:00.000-08:00</published><updated>2006-03-31T17:43:16.383-08:00</updated><title type='text'>Error: cab file could not be created - No, not again! Nice workaround/solution</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Error: cab file could not be created - No, not again! Ultimate  workaround/solution&lt;/span&gt;&lt;br /&gt;&lt;p&gt;How many times did you see the dreaded message &lt;span id="_ctl0_MainContent_PostFlatView"&gt;"Error:  CAB file 'XXX.CAB' could not be created", after you managed to tackle the  compilation error, managed to build the needed DLLs, EXEs, and managed to write  a good CAB .inf file? Worse, the error file that CabWiz is supposed to dump  error message is empty! This left you cluelessly scratching your head, having no  idea what exactly you did wrong.&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span id="_ctl0_MainContent_PostFlatView"&gt;I have seen so many such errors in my development,  and I do not think I did anything wrong. Why? Here is &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=82522&amp;SiteID=1"&gt;my  story posted to Microsoft MSDN forum&lt;/a&gt;. Sometimes the new CabWiz (shipped with  VS2005) worked, sometimes did not. Sometimes the old CabWiz (shipped with  PPC2003 SDK) worked, sometime did not. Sometimes everything worked in my PC, but  not in my teammate's...&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span id="_ctl0_MainContent_PostFlatView"&gt;With the &lt;a href="http://www.sysinternals.com/Utilities/Filemon.html"&gt;incredible  tool from the wizards in sysinternals&lt;/a&gt;, I monitored the file-system activities  after launching CabWiz. Looks like CabWiz first analyzed the .INF file,  generated an intermediate file based on a template (cabwiz.ddf), then asked  makecab.exe to build the CAB based on the intermediate file. Makecab failed at  the stage when a CAB was being created, for no apparent reason. That explained why CabWiz could not report any meaningful error message, because  makecab.exe did not communicate with CabWiz why it failed. &lt;/span&gt;&lt;/p&gt; &lt;p&gt;Finally I figured out probably the buggy tool is not comfortable with the  long fully-qualified CAB filename. So I did a subst, making sure the current  directory for CabWiz is very short. Viola! It works. So the ultimate solution is  &lt;span style="font-weight: bold;font-size:130%;" &gt;to use Subst to shorten the absolute name of your CAB file, and launch CabWiz from that shorten path.&lt;/span&gt;&lt;/p&gt;&lt;p&gt; Example:&lt;/p&gt; &lt;p&gt;Original path of INF file&lt;/p&gt; &lt;p&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;c:\MyWork\WindowsMobile\superlong1\superlogn2\superlong3    superlogn4\superlogn5\superlogn6\superlogn7    MailClient\src\Shared\MailClient_release.PPC2003_en.inf&lt;/span&gt;&lt;/p&gt; &lt;p&gt;Do a subst:&lt;/p&gt; &lt;p&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;Subst v:  c:\MyWork\WindowsMobile\superlong1\superlogn2\superlong3     superlogn4\superlogn5\superlogn6\superlogn7&lt;/span&gt;&lt;/p&gt; &lt;p&gt;Then file Cabsize in V: rather than in C:&lt;/p&gt;Sometimes even if the original path is not very long (like 120 characters), CabWiz still fails. A subst is still a good solution.&lt;br /&gt;&lt;br /&gt;PS: &lt;a href="http://technet2.microsoft.com/WindowsServer/en/Library/981db8e3-745c-4666-944f-026cff5544291033.mspx"&gt;Microsoft's documentation on Subst.&lt;/a&gt; Or you can type "subst /h" on the command line to see the details how it works.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BCabwiz%20Build%5D%22"&gt;[Cabwiz / Build]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114271474899070592?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114271474899070592/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114271474899070592' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114271474899070592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114271474899070592'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2005/11/error-cab-file-could-not-be-created-no.html' title='Error: cab file could not be created - No, not again! Nice workaround/solution'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114264561310396605</id><published>2005-11-17T17:31:00.000-08:00</published><updated>2006-03-25T17:29:39.216-08:00</updated><title type='text'>How to debug Control Panel Applet in Pocket PC 2003 and Pocket PC 5.0?</title><content type='html'>&lt;p&gt;&lt;span style="font-weight: bold;"&gt;How to debug Control Panel Applet in Pocket PC 2003 and Pocket PC 5.0?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Recently I was enhancing a Control Panel Applet for my Pocket PC application, which was developed in a hurry one year ago, with very rudimentary user interfaces. This time I expanded it to 4 tabs, with more professional UIs.&lt;br /&gt;&lt;br /&gt;All went on well, until I hit a problem today: After making some code changes, the Applet no longer shows up after I click it! Not able to find out any issue from the source code, I decided to do a debug. Unfortunately a Control Panel Applet cannot be directly started, because it is essentially a DLL  which exports a &lt;span style="font-family:courier new;"&gt;CPlApplet &lt;/span&gt;function. So I have to find a host executable for debugging purpose. &lt;/p&gt;  &lt;p&gt;&lt;span style="font-weight: bold;"&gt;1. Basic knowledge about Pocket PC Control Panel Applet&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The way how Control Panel Applet is loaded by the system is well documented. Basically the CPL file must export the following function:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;span style="font-size:85%;"&gt;    LONG CALLBACK CPlApplet (HWND hwndCPL, UINT uMsg, LONG lParam1, LONG lParam2)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;And the CPL must be able to deal with a series of messages sent from Windows, namely:&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;    CPL_GETCOUNT&lt;br /&gt;    CPL_INIT&lt;br /&gt;    CPL_NEWINQUIRE&lt;br /&gt;    CPL_STOP&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt; 2. Write my own host executable? Overkill?&lt;/span&gt;&lt;/p&gt; &lt;p&gt; So I can easily write a program that &lt;/p&gt;  &lt;ul&gt;&lt;li&gt;load the CPL ("LoadLibrary")&lt;/li&gt;&lt;li&gt;get the function address of &lt;span style="font-family:Courier New;"&gt; CPlApplet&lt;/span&gt;("GetProcAddress"), &lt;/li&gt;&lt;li&gt;and send a series of messages: &lt;span style="font-family:Courier New;"&gt;CPL_INIT, &lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;CPL_GETCOUNT,     CPL_NEWINQUIRE, &lt;span style="font-size:85%;"&gt;CPL_DBLCLK (to show the UI!), CPL_STOP, and     CPL_EXIT&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;I actually find &lt;a href="http://www.pocketpcdn.com/articles/enumerate_cp_applets.html"&gt;such one&lt;/a&gt;, although it does not send &lt;span style="font-size:85%;"&gt;&lt;span style="font-family:Courier New;"&gt;CPL_DBLCLK &lt;/span&gt;&lt;/span&gt;to display the UI. &lt;/p&gt; &lt;p&gt;&lt;span style="font-weight: bold;"&gt;3. ctlpnl.exe? Nope it does not work!&lt;/span&gt; &lt;/p&gt;    &lt;p&gt;It looks to me a little overkill to write a program just for the sake of a debugging. So I am  wondering whether any program already resides in the device is a good host. A  good candidate should be &lt;b&gt; ctlpnl.exe&lt;/b&gt; &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mobilesdk5/html/mob5samMyBacklight.asp"&gt;as documented in MSDN  example&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I was soon disappointed. Nope!! ctlpnl.exe does not work! Although I killed ctlpnl.exe  using the remote process viewer, the VS2005 debugger still quickly terminates  the debug session,  because ctlpnl.exe unloads my CPL as soon as it loads  it, then itself immediately dies. &lt;/p&gt;  &lt;p style="font-weight: bold;"&gt;&lt;span style="font-size:130%;"&gt;4. mstli.exe ==&gt; the good guy&lt;/span&gt; &lt;/p&gt;  &lt;p&gt;After some digging, I found &lt;b&gt;mstli.exe&lt;/b&gt; is the good one. It perfectly  loads my CPL, waits for my click on the device, then stops at my breakpoint. I  tested in my Sprint Smartdevice PPC6601 (Windows Mobile 2003SE), Sprint  Smartdevice PPC6700 (Windows Mobile 5.0), Pocket PC 2003 emulator, Pocket PC 5.0 emulator, all work  well. &lt;/p&gt;  &lt;p&gt;One caveat: Looks like mstli.exe is started once the device is up and  running. So it must be killed before the debugger can start it. I use the remote  process viewer to kill it. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BControl%20Panel%5D%22"&gt;[Control Panel]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114264561310396605?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114264561310396605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114264561310396605' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114264561310396605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114264561310396605'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2005/11/how-to-debug-control-panel-applet-in.html' title='How to debug Control Panel Applet in Pocket PC 2003 and Pocket PC 5.0?'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114258354911632534</id><published>2005-11-09T20:09:00.000-08:00</published><updated>2006-04-14T23:58:49.786-07:00</updated><title type='text'>Pocket PC Power Management Series 4: A Better Way to Catch when the Device Wakes Up</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Pocket PC Power Management Series 4: A Better Way to Catch when the Device Wakes Up&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://windowsmobilepro.blogspot.com/2005_10_30_windowsmobilepro_archive.html"&gt;Pocket PC Power Management Series 3&lt;/a&gt;, I presented a simple program that depicts when the device runs and when it sleeps. The program uses a rudimentary and inefficient way to achieve the purpose: It spawns a periodically sleeping thread, which is responsible for recording whether itself sleeps through the predefined time frame. If it sleeps longer than expected, it draws the conclusion that the device must have been suspended.&lt;br /&gt;&lt;br /&gt;The recommended and efficient way is to use the omnipotent CeSetUserNotificationEx API. If you happen to write any serious Windows Mobile programs, you must either have heard about it, or have used it. Basically it allows the developer to either launch a program, or to display a dialog, or to emit a sound, or to vibrate the device, if certain predefined system events occur, or if the predefined time arrives. I believe the Alarm program shipped with any Pocket PC or Smartphone (for example, the devices I have at hand: Sprint SmartDevice 6600, Sprint SmartDevice 6700, Palm Treo 700w, Cingular 8125, I-Mate SP5, Cingular MPx220, Sprint Samsung i600) must be written based on this API.&lt;br /&gt;&lt;br /&gt;Luckily enough, Microsoft includes device wakeup event as one of the system events. The way to make use of the event is a little tweaked, so here is my example and source code, with detailed explanations.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1. Two helper functions to deal with wakeup Notifications: AddWakeupNotification and ClearWakeupNotification&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;AddWakeupNotification anticipates a constant string, which is the event name. Such name is also used later as the name of an event, as described in &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceui40/html/cerefce_notification_trigger.asp"&gt;msdn documentation for CeSetUserNotificationEx and CE_NOTIFICATION_TRIGGER.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;One notorious side-effect of CeSetUserNotificationEx is that the notification will be persisted in a central repository, unless the creator remembers to remove it. I've seen a couple of novice developers forgot to clear the notifications and subject his/her testing device to some really weird behaviors. So I also present ClearWakeupNotification, which also accepts a constan string.&lt;br /&gt;&lt;br /&gt;&lt;font face="Courier" size="2"&gt;static HRESULT AddWakeupNotification(LPCTSTR szEventName)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;HRESULT hr = S_OK;&lt;br /&gt;&amp;nbsp;&amp;nbsp;HANDLE hNotify = NULL;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// set a CE_NOTIFICATION_TRIGGER&lt;br /&gt;&amp;nbsp;&amp;nbsp;CE_NOTIFICATION_TRIGGER notifTrigger;&lt;br /&gt;&amp;nbsp;&amp;nbsp;memset(&amp;amp;notifTrigger, 0, sizeof(CE_NOTIFICATION_TRIGGER));&lt;br /&gt;&amp;nbsp;&amp;nbsp;notifTrigger.dwSize = sizeof(CE_NOTIFICATION_TRIGGER);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;TCHAR szNamedEventName[MAX_PATH];&lt;br /&gt;&amp;nbsp;&amp;nbsp;memset(szNamedEventName, 0, sizeof(TCHAR)*MAX_PATH);&lt;br /&gt;&amp;nbsp;&amp;nbsp;_tcscat(szNamedEventName, NAMED_EVENT_PREFIX_TEXT);&lt;br /&gt;&amp;nbsp;&amp;nbsp;_tcscat(szNamedEventName, szEventName);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;notifTrigger.dwType = CNT_EVENT;&lt;br /&gt;&amp;nbsp;&amp;nbsp;notifTrigger.dwEvent = NOTIFICATION_EVENT_WAKEUP;&lt;br /&gt;&amp;nbsp;&amp;nbsp;notifTrigger.lpszApplication = szNamedEventName;&lt;br /&gt;&amp;nbsp;&amp;nbsp;//notifTrigger.lpszArguments = NULL;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// set the notification&lt;br /&gt;&amp;nbsp;&amp;nbsp;hNotify = CeSetUserNotificationEx(0, &amp;amp;notifTrigger, NULL);&lt;br /&gt;&amp;nbsp;&amp;nbsp;// NULL because we do not care what action to take&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (!hNotify) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; hr = E_FAIL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;} else {&lt;br /&gt;&amp;nbsp;&amp;nbsp; // close the handle as we do not need to use it further&lt;br /&gt;&amp;nbsp;&amp;nbsp; CloseHandle(hNotify);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return hr;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static HRESULT ClearWakeupNotification(LPCTSTR szEventName)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;HRESULT hr = S_OK;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;TCHAR szToCompare[MAX_PATH];&lt;br /&gt;&amp;nbsp;&amp;nbsp;memset(szToCompare, 0, sizeof(TCHAR)*MAX_PATH);&lt;br /&gt;&amp;nbsp;&amp;nbsp;_tcscat(szToCompare, NAMED_EVENT_PREFIX_TEXT);&lt;br /&gt;&amp;nbsp;&amp;nbsp;_tcscat(szToCompare, szEventName);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// hold a notification&lt;br /&gt;&amp;nbsp;&amp;nbsp;PBYTE pBuff = (PBYTE)LocalAlloc(LPTR, 8192);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (!pBuff) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return E_OUTOFMEMORY;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// at most 256 notification handles -&lt;br /&gt;&amp;nbsp;&amp;nbsp;// should be more than enough for a typical device&lt;br /&gt;&amp;nbsp;&amp;nbsp;HANDLE hNotifHandlers[256];&lt;br /&gt;&amp;nbsp;&amp;nbsp;DWORD nNumHandlers = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;DWORD i = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;int rc = CeGetUserNotificationHandles(hNotifHandlers,&lt;br /&gt;&amp;nbsp;&amp;nbsp;dim(hNotifHandlers), &amp;amp;nNumHandlers);&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (!rc) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hr = E_FAIL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;goto FuncExit;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// iterate all notifications&lt;br /&gt;&amp;nbsp;&amp;nbsp;// Notice: We do not care about the status of the notification.&lt;br /&gt;&amp;nbsp;&amp;nbsp;// Just clear it even if it is not filed??&lt;br /&gt;&amp;nbsp;&amp;nbsp;for (; i&amp;lt;nNumHandlers; i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// query info for this specific handler&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BOOL bClearThis = FALSE;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DWORD dwSize = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rc = CeGetUserNotification(hNotifHandlers[i], 8192, &amp;amp;dwSize, pBuff);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!rc) continue;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PCE_NOTIFICATION_INFO_HEADER pnih = (PCE_NOTIFICATION_INFO_HEADER)pBuff;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PCE_NOTIFICATION_TRIGGER pNotifTrigger = pnih-&amp;amp;gt;pcent;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Notice some events with NULL lpszApplication might be inserted!&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (pNotifTrigger &amp;amp;&amp;amp; pNotifTrigger-&amp;gt;lpszApplication&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;amp;&amp;amp; !_tcsicmp(pNotifTrigger-&amp;gt;lpszApplication, szToCompare)) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CeClearUserNotification(pnih-&amp;gt;hNotification);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;FuncExit:&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (pBuff) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;LocalFree(pBuff);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return hr;&lt;br /&gt;}&lt;/font&gt;&lt;br /&gt;&lt;p/&gt;&lt;p/&gt;&lt;span style="font-weight: bold;"&gt;2. Wait for the named event&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In Windows, events are named. What we need to do here is to create such a named event, and request that the notification subsystem set the named event when the notification event occurs. So the code skeleton is like this:&lt;br /&gt;&lt;font face="Courier" size="2"&gt;&lt;br /&gt;HRESULT hr = AddWakeupNotification(g_szEventName);&lt;br /&gt;HANDLE hWakeupEvent = CreateEvent(NULL, TRUE, FALSE, g_szEventName);&lt;br /&gt;&lt;br /&gt;// some code to wait for the named event &lt;br /&gt;// -- meaning the device just wakes up&lt;br /&gt;// ...&lt;br /&gt;&lt;br /&gt;CloseHandle(hWakeupEvent);&lt;br /&gt;hr = ClearWakeupNotification(g_szEventName);&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;p/&gt;&lt;p/&gt;The tricky part is how to wait for the wakeup event. If you really hates multi-threaded programming, I have the following single-thread example for your reference:&lt;br /&gt;&lt;font face="Courier" size="2"&gt;&lt;br /&gt;&lt;br /&gt;HANDLE eventHandles[] = {hWakeupEvent};&lt;br /&gt;DWORD dwEventCount = 1;&lt;br /&gt;&lt;br /&gt;TCHAR szBuf[256];&lt;br /&gt;MSG currentMsg;&lt;br /&gt;&lt;br /&gt;while (true) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; ResetEvent(hWakeupEvent);&lt;br /&gt;&amp;nbsp;&amp;nbsp; DWORD dwRC = MsgWaitForMultipleObjectsEx(dwEventCount,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eventHandles, INFINITE, QS_ALLEVENTS, NULL);&lt;br /&gt;&amp;nbsp;&amp;nbsp; if (WAIT_OBJECT_0 == dwRC) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ALERT(TEXT(&amp;quot;Aha Wakeup just now!));&lt;br /&gt;&amp;nbsp;&amp;nbsp; } else if (WAIT_FAILED == dwRC) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // XXX wait failed?&lt;br /&gt;&amp;nbsp;&amp;nbsp; } else if (WAIT_OBJECT_0+dwEventCount == dwRC) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int nGetMsg = GetMessage(&amp;amp;currentMsg, NULL, 0, 0);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (nGetMsg &amp;gt; 0) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TranslateMessage(&amp;amp;currentMsg);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DispatchMessage(&amp;amp;currentMsg);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else if (nGetMsg &amp;lt; 0) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // XXX GetMsg failed;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;p/&gt;&lt;p/&gt;Read the above code, you'll find the familiae bolier plate code TranslateMessage() and DispathMessage(). Yes it is right! You can use MsgWaitForMultipleObjectsEx to both respond to the current thread message queue and listen to a list of events. In Windows, a window is associated with a thread, the thread that creates the window. So the "thread message queue" actually is your familiar "windows message queue". Use the powerful MsgWaitForMultipleObjectsEx API, you can achieve the purpose using only one thread to deal with UI, and listen to the wakeup event.&lt;/p&gt;However, the above technique might not work well, and you may notice you'll frequently miss a wake-up event. The reason is obvious. The single thread most probably is processing a windows message (remember the two function calls: TranslateMessage and DispathMessage). If this thread is executing a windows procedure (because of a windows message) when the device wakes up, the thread for sure will miss the wakeup signal!&lt;br /&gt;&lt;br /&gt;So a reliable way is to spawn a new thread, and use WaitForSingleObject to listen to the wakeup signal. Of course this thread does not necessary only deal with the wakeup signal. You can make it run other errands by calling WaitForMultipleObjects, but just make sure it should not be a busy thread!&lt;br /&gt;&lt;p&gt;&lt;br/&gt;Update: I uploaded &lt;a href="http://windowsmobilepro.blogspot.com/2006/04/pocket-pc-power-management-series-10.html"&gt;series 10 with the two-thread code. The Visual Studio 2005 solution can be downloaded as well.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BPower%20Management%5D%22"&gt;[Power Management]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114258354911632534?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114258354911632534/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114258354911632534' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114258354911632534'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114258354911632534'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2005/11/pocket-pc-power-management-series-4.html' title='Pocket PC Power Management Series 4: A Better Way to Catch when the Device Wakes Up'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114204683375272959</id><published>2005-10-30T19:12:00.000-08:00</published><updated>2006-03-25T17:26:43.363-08:00</updated><title type='text'>Pocket PC Power Management Series 3: When is My Device Sleeping, and when is it Running?</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Pocket PC Power Management Series 3: When is My Device Sleeping, and when is it Running?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I have seen too many people asking these questions: I want to query the OS to determine how much time before the device goes into sleep. Or, I want to get notified when the device is going to sleep. Well, conceptually it is not possible. Let us say OS generates such an event that it is going to sleep, and you write an event listener to perform some tasks. Guess what? Your event listener even does not get a chance to run, because the device falls asleep!&lt;br /&gt;&lt;br /&gt;To help understand the pattern how the device runs-sleeps-runs-sleeps, I wrote a program that records when the device falls sleep and prints out a simple diagram showing what time the device is running, and what time the device is sleeping. You can &lt;a href="http://home.comcast.net/%7Ewindowsmobilepro/WindowsMobile/RunSleepPattern.exe"&gt;download the program &lt;/a&gt;from your Pocket IE, or from your desktop browser then copy it to your device. The program can only run in Windows Mobile devices, not on desktop.&lt;br /&gt;&lt;br /&gt;Below are three screen cuts taken when the program runs in my device. Each screen cut shows how long the device runs and how long it sleeps, and draw two lines reflecting when it runs and when it sleeps. Take a closer look at the third screen cut, when the device was put onto my table unattended for a night. The device only runs for 6614/63598=10% of the time. That is Microsoft's way to save battery, and ironically, it did not work well for a few programs, for example, the ones I am trying to tackle in my Power Management series...&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/5783/1371/1600/RSP_01.jpg"&gt;&lt;img style="cursor: pointer;" src="http://photos1.blogger.com/blogger/5783/1371/320/RSP_01.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/5783/1371/1600/RSP_02.jpg"&gt;&lt;img style="cursor: pointer;" src="http://photos1.blogger.com/blogger/5783/1371/320/RSP_02.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/5783/1371/1600/RSP_03.0.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://photos1.blogger.com/blogger/5783/1371/320/RSP_03.0.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;br /&gt;How the program works? Basically there are two threads. One thread is responsible for updating the UI based on an internal data structure. The other thread simply sleeps periodically at a predefined interval; each time it wakes up, the thread tests whether it has slept through the predefined interval.  If the device is suspended, the sleeping thread could find that it has slept for a time longer than expected, so it figured out the device must have fall asleep, and update the internal data structure accordingly. Notice this is an inefficient way to test whether a device is slept. I plan to discuss a much better one in my next post.&lt;br /&gt;&lt;br /&gt;APIs and technique used in the program:&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;- Get the current time in seconds, using GetLocalTime and SystemTimeToFileTime&lt;br /&gt;&lt;br /&gt;- Compare two ULONGLONG structures. A ULONGLONG is essentially two DWORDs.&lt;br /&gt;&lt;br /&gt;- Basic threading code: CreateThread, and how to gracefully shutdown a sleeping or running thread&lt;br /&gt;&lt;br /&gt;- Basic thread communication mechanism: CreateEvent, PulseEvent, WaitForSingleObject&lt;br /&gt;&lt;br /&gt;- InterruptibleSleep: a sleep that can be gracefully interrupted at anytime by using WaitForSingleObject, rather than the plain vanilla Sleep() &lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BPower%20Management%5D%22"&gt;[Power Management]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114204683375272959?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114204683375272959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114204683375272959' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114204683375272959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114204683375272959'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2005/10/pocket-pc-power-management-series-3.html' title='Pocket PC Power Management Series 3: When is My Device Sleeping, and when is it Running?'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-113977767928143149</id><published>2005-10-12T12:52:00.000-07:00</published><updated>2006-03-25T17:27:13.156-08:00</updated><title type='text'>Pocket PC Power Management Series 2: Problem Domain</title><content type='html'>&lt;p style="font-weight: bold;" class="MsoNormal"&gt;Pocket PC Power Management Series 2: Problem Domain&lt;/p&gt;&lt;p class="MsoNormal"&gt;Most UI-intensive applications require the user to interact via a screen UI using stylus or keyboard. For such applications, it does not make sense to run it when the device is suspended, or “in sleep mode”. What a developer needs to do is to avoid burning any CPU cycles when the device is sleeping or, to be more exactly, when the user is not interacting with the application (for example, its main window is not the foreground window.) Mike Calligaro from Microsoft Windows Mobile Team has two excellent articles on this topic with good examples. I strongly recommend readers to go over those two posts:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://blogs.msdn.com/windowsmobile/archive/2005/08/03/447404.aspx"&gt;Power to the Developers part 1&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://blogs.msdn.com/windowsmobile/archive/2005/08/11/450591.aspx"&gt;Power to the Developers part 2&lt;/a&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/li&gt;&lt;/ul&gt;  The problem we are trying to solve here belongs to another domain: What if the application needs to run continuously, or at least, needs to run periodically independent of the user’s action? It runs if the user puts the device unattended, it runs if the user sometimes powers the device on and turns it off quickly, and it runs when the device is put into a charger (of course).&lt;o:p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/o:p&gt;A media player or a MP3 player is a great example of applications that needs to run continuously. A stock-alert application is a good example of applications that needs to run periodically.&lt;o:p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/o:p&gt;Thinking about a stock-alert program that needs to constantly (if not continuously) monitor a stock symbol and alerts the user if the price is higher (or lower) than a predefined threshold value. Such program is a piece of cake in desktop windows, where you may simply write a monitoring thread and assume the thread can run all the time and continuously read stock price from a public server. The same piece of cake becomes sour if running in Pocket PC devices, since the monitoring thread might not get a chance to run for a long time, and you may miss an alert!&lt;o:p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/o:p&gt;Keep in mind battery is precious in a handheld device, so you need to strike a balance between two conflicting factors: to make the system run thus consuming batteries vs. to save battery for the device. The general principle is still the same: to consume CPU cycles as less as possible.&lt;ul&gt;&lt;li&gt;If the application needs to run unattended, turn off the screen display by all means.&lt;/li&gt;&lt;li&gt;If the application does not need to run continuously, make it run periodically.&lt;/li&gt;&lt;li&gt;If the application does not need to run periodically, but needs to catch user’s stylus action as quickly as possible once the device is switched on, listen to a Wakeup event.   &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BPower%20Management%5D%22"&gt;[Power Management]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-113977767928143149?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/113977767928143149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=113977767928143149' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/113977767928143149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/113977767928143149'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2005/10/pocket-pc-power-management-series-2.html' title='Pocket PC Power Management Series 2: Problem Domain'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-113973172682781474</id><published>2005-09-26T00:07:00.000-07:00</published><updated>2006-03-25T17:27:24.563-08:00</updated><title type='text'>Pocket PC Power Management Series 1: the Challenge to Developers</title><content type='html'>&lt;p style="font-weight: bold;" class="MsoNormal"&gt;Pocket PC Power Management Series 1: the Challenge to Developers&lt;/p&gt;&lt;p class="MsoNormal"&gt;If you own a Pocket PC, you may notice that its screen frequently turns off, if the device is not used for certain time. The time can be adjusted via “Start =&gt; Settings =&gt; System =&gt; &lt;st1:place&gt;Battery&lt;/st1:place&gt; =&gt; Advanced”. By default it is 3 minutes.&lt;/p&gt;    &lt;p class="MsoNormal"&gt;To turn off the screen is a good thing to the battery life, as the LCD display often turns out to the big battery sucker, especially if backlight is configured to be very bright. However, for some reason, Microsoft deemed that to turn off the CPU might save even more battery. So here comes a unique power model in Pocket PC: The system is also suspended after the device is not used for certain time. Or we say the system is sleeping, in sleep mode.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&lt;/o:p&gt;When the system is “suspended”, or when the device is “sleeping”, &lt;span style=""&gt; &lt;/span&gt;all threads are suspended. Let us say you have a nicely written application that has a great UI (controlled by one thread) and a hard-working background thread that analyzes storage data and also interacts with the UI thread. When the system is suspended, neither of your two threads gets a chance to run.&lt;/p&gt;&lt;span style=""&gt;&lt;/span&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;When the devie is sleeping, THE THREADS SIMPLY DO NOT RUN! Period.&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;&lt;/span&gt;Compared to a desktop machine, if the machine is not used for certain time, a screen saver may be started, or the power management system may kick in and turn off the screen. Whatever, the CPU is still spinning; any of your threads can still run as usual.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Such unique power model in Pocket PC presents unique challenge to developing programs that need to run for a long time uninterrupted (or need to run even if the system is suspended). I’ll come up with a few blog posts soon on how to write such a program, mainly:&lt;/p&gt;    &lt;ol&gt;&lt;li&gt;General principles&lt;/li&gt;&lt;li&gt;Force the device to run?&lt;/li&gt;&lt;li&gt;Request the device to run?&lt;/li&gt;&lt;li&gt;GetTickCount vs GetLocalTime&lt;/li&gt;&lt;li&gt;Older notification functions&lt;/li&gt;&lt;li&gt;Newer notification functions&lt;/li&gt;&lt;/ol&gt;&lt;o:p&gt;&lt;/o:p&gt;Please notice the smartphone series does not have such power model. Smartphone is more like destkop windows. A smartphone either runs all the time, even if the SCREEN is turned off, or does not run at all, when the phone is turned off.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BPower%20Management%5D%22"&gt;[Power Management]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-113973172682781474?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/113973172682781474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=113973172682781474' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/113973172682781474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/113973172682781474'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2005/09/pocket-pc-power-management-series-1.html' title='Pocket PC Power Management Series 1: the Challenge to Developers'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-113917329677118754</id><published>2005-09-09T21:00:00.000-07:00</published><updated>2006-02-11T21:46:17.276-08:00</updated><title type='text'>InterProcess Communications in Windows Mobile</title><content type='html'>Here are the possible methods. Will expand the content later...&lt;br /&gt;&lt;ol&gt;&lt;li&gt;SendMessage&lt;/li&gt;&lt;li&gt;PostThreadMessage&lt;/li&gt;&lt;li&gt;SharedMem file-mapping&lt;/li&gt;&lt;li&gt;registry, filesystem&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-113917329677118754?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/113917329677118754/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=113917329677118754' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/113917329677118754'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/113917329677118754'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2005/09/interprocess-communications-in-windows.html' title='InterProcess Communications in Windows Mobile'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-113916940635153223</id><published>2005-08-25T18:53:00.000-07:00</published><updated>2006-03-26T13:21:57.576-08:00</updated><title type='text'>Manually migrate Embedded Visual C++ workspace to Visual Studio 2005 (Beta 2) without using Migration Assistant (Upgrade Wizard)</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Manually migrate Embedded Visual C++ workspace to Visual Studio 2005 (Beta 2) without using Migration Assistant (Upgrade Wizard)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;My Embedded Visual C++ 4.0 workspace has more than 10 projects. Some projects are built into EXEs, some DLLs, some static linked libs, and one CPL. If working within EVC IDE I use "batch build" to generate all the binaries, then call a .bat to generate a CAB file. Outside the IDE (for example, overnight build), I have an Ant script that calls "evc" command line to generate binaries and the CAB file.&lt;br /&gt;&lt;br /&gt;Recently I obtained a copy of Visual Studio 2005 Beta 2 DVD. So I need to migrate the EVC4 workspace to VS2005.&lt;br /&gt;&lt;br /&gt;Microsoft published &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnppcgen/html/migrating_evc_vs2005.asp"&gt;an article&lt;/a&gt; to help migrate the EVC workspace to VS2005 as a solution. You may have two choices:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Using MS-provided "EVC Upgrade Wizard" (&lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=77ffddbf-b215-4d96-94dd-6ae9b7bb53d2&amp;displaylang=en"&gt;download here&lt;/a&gt;), which is a Visual Studio Addon. I downloaded a copy and read the installation .bat file. I was scared, as the so-called Visual Studio Addon needs to REPLACE a bunch of existing DLLs, rather than adding some ADDITIONAL DLLs. (So Addon looks like is not a good name.)&lt;/li&gt;&lt;li&gt;Manual migration. This turns out to be a rough road, and that article apparently does not help much.&lt;/li&gt;&lt;/ul&gt;Here it is a recoup of what I did for the manual migration. As a starting point, I picked one project which builds a simple DLL and has no dependency on other projects. I first created an empty solution, and then add a project by choosing the following from "Add New Project" dialog:&lt;br /&gt;Visual C++ =&gt; Smart Device =&gt; Win32 Smart Device Project&lt;br /&gt;&lt;br /&gt;This pops up a "Win32 Smart Device Project Wizard" dialog, in which I choose "DLL" and "Empty project". VS2005 created the .vcproj file and then I started to add the source files to this project.&lt;br /&gt;&lt;br /&gt;Before building the solution, of course some common project settings need to be transferred. For example, "Addtional Include Directories", "Additional Dependencies", and "Ignore Specific Library" (OLDNAMES.lib).&lt;br /&gt;&lt;br /&gt;Notice that I did not copy the "Preprocess Definitions" from EVC++ to VS2005. The system-provided definitions are actually a bit different. For example, in VS2005, "_DEBUG" is defined along with "DEBUG", inline with WIN32 desktop project. Also "$(CePlatform)" and "$(CEVersion)" are replaced by "$(PLATFORMDEFINES)" and "$(CEVER)" respectively. (From the command line, you could easily figure out how VS2005 is expanding them: /D "_WIN32_WCE=0x420" /D "WIN32_PLATFORM_PSPC")&lt;br /&gt;&lt;br /&gt;Next I kicked start "Build". I was glad to find that all source files build successfully, but linker seems not happy. It printed out zillions of errors that I'd never seen before in my EVC++ environment. Luckily all errors belong to either of the following two:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;- error LNK2001: unresolved external symbol __security_check_cookie, or error LNK2001: unresolved external symbol __security_cookie&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;- error LNK2001: unresolved external symbol "const type_info::`vftable'" (??_7type_info@@6B@), or error LNK2001: unresolved external symbol "void __cdecl `eh vector destructor iterator'(void *,unsigned int,int,void (__cdecl*)(void *))" (??_M@YAXPAXIHP6AX0@Z@Z)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So linker is not happy as it could not find some libraries or object files. As usual, Microsoft help does not provide good information, so I googled a few links.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;Linker Error 1. __security_check_cookie &amp; __security_cookie&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There is actually an &lt;a href="http://support.microsoft.com/?id=894573"&gt;MS KB&lt;/a&gt; for this issue. Out of good intention, Microsoft compiler injects some code to detect (but not to prevent) buffer overflow attack. Apparently "__security_cookie" is one function call the complier injects. The KB articles suggests adding "BufferOverflowU.lib" to the library list. However, looks like there is simply no such file under the wce420 (Windows Mobile 2003) SDK directory. The other walkaround is to remove "/GS" switch (or define "/GS-") to instruct the compiler not to inject the code. You could achieve this via "Project Settings"=&gt;"Configuration Properties"=&gt;"C/C++"=&gt;"Code Generation"=&gt;"Buffer Security Check" set to "No".&lt;br /&gt;&lt;br /&gt;Thinking that I should give it a try and retain this buffer overflow detection capability, I did a binary-content search under wce420/lib folder, and find "&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;secchk.lib&lt;/span&gt;&lt;/span&gt;" contains those two functions. So I add this lib to the dependencies list.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;Linker Error 2. const type_info::`vftable'" (??_7type_info@@6B@)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This has something to do with exception handling, which needs dynamic cast (RunTime Type Information, dynamic_cast, typeid, and type_info). MS has a &lt;a href="http://support.microsoft.com/default.aspx?scid=kb;%5BLN%5D;830482"&gt;KB article&lt;/a&gt; instructing where to download RTTI library for Windows Mobile 2003 devices. I did a binary-content search again, and found the library "&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;ccrtrtti.lib&lt;/span&gt;&lt;/span&gt;" under Windows Mobile 2003 SDK. So I just simply add this lib to the dependencies list.&lt;br /&gt;&lt;br /&gt;Please notice that the above two libraries are not available from the Windows Mobile 2003 SDK download, but they do apprear in the SDK directory shipped along with VS2005.&lt;br /&gt;&lt;br /&gt;After I manually add "secchk.lib" and "ccrtrtti.lib" to the additional dependency list, linker is happy, and all 20-around projects build successfully.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Category: &lt;/span&gt;&lt;a style="font-weight: bold;" href="http://search.blogger.com/?ie=UTF-8&amp;ui=blg&amp;amp;bl_url=windowsmobilepro.blogspot.com&amp;x=0&amp;amp;y=0&amp;scoring=d&amp;amp;as_q=%22%5BDevelopment%20Environment%5D%22"&gt;[Development Environment]&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-113916940635153223?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/113916940635153223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=113916940635153223' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/113916940635153223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/113916940635153223'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2005/08/manually-migrate-embedded-visual-c.html' title='Manually migrate Embedded Visual C++ workspace to Visual Studio 2005 (Beta 2) without using Migration Assistant (Upgrade Wizard)'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-114473715181955936</id><published>2005-08-10T23:31:00.000-07:00</published><updated>2006-05-20T00:13:19.566-07:00</updated><title type='text'>Windows Mobile Pocket PC Smartphone Programming: SiteMap</title><content type='html'>&lt;p&gt;&lt;b&gt;Windows Mobile Pocket PC Smartphone Programming: SiteMap&lt;/b&gt;&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;a name="PowerManagement"&gt;&lt;b&gt;Power Management&lt;/b&gt;&lt;/a&gt;     &lt;ul&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2005/09/pocket-pc-power-management-series-1.html"&gt;Pocket          PC Power Management Series 1: the Challenge to Developers&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2005/10/pocket-pc-power-management-series-2.html"&gt;Pocket          PC Power Management Series 2: Problem Domain&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="Pocket PC Power Management Series 3: When is My Device Sleeping, and when is it Running?" href="http://windowsmobilepro.blogspot.com/2005/10/pocket-pc-power-management-series-3.html"&gt;Pocket          PC Power Management Series 3: When is My Device Sleeping, and when is it          Running?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="Pocket PC Power Management Series 4: A Better Way to Catch when the Device Wakes Up" href="http://windowsmobilepro.blogspot.com/2005/11/pocket-pc-power-management-series-4.html"&gt;Pocket          PC Power Management Series 4: A Better Way to Catch when the Device          Wakes Up&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="Pocket PC Power Management Series 5: Force the Device not to Sleep: a Brutal Way?" href="http://windowsmobilepro.blogspot.com/2005/12/pocket-pc-power-management-series-5.html"&gt;Pocket          PC Power Management Series 5: Force the Device not to Sleep: a Brutal          Way?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="Pocket PC Power Management Series 6: Request the Device to Run: a Gentle Way" href="http://windowsmobilepro.blogspot.com/2005/12/pocket-pc-power-management-series-6.html"&gt;Pocket          PC Power Management Series 6: Request the Device to Run: a Gentle Way&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/01/pocket-pc-power-management-series-7.html"&gt;Pocket          PC Power Management Series 7: Trap of GetTickCount(), and Sleep()&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="Pocket PC Power Management Series 8: Why Pocket PC's Battery Life so Notorious?" href="http://windowsmobilepro.blogspot.com/2006/01/pocket-pc-power-management-series-8.html"&gt;Pocket          PC Power Management Series 8: Why Pocket PC's Battery Life so Notorious?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/01/pocket-pc-power-management-series-9.html"&gt;Pocket          PC Power Management Series 9: Battery Life Matters&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/pocket-pc-power-management-series-10.html"&gt;Pocket          PC Power Management Series 10: A Better Way to Catch when the Device          Wakes Up - Multi-Thread Code with Visual Studio 2005 Solution Download&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/05/pocket-pc-power-management-series-11.html" title="Pocket PC Power Management Series 11: Play sound (for example, wav file) when a Pocket PC is suspended"&gt;Pocket          PC Power Management Series 11: Play sound (for example, wav file) when a          Pocket PC is suspended&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;   &lt;/li&gt;&lt;li&gt;&lt;a name="CodeSigningCertificateSecurity"&gt;&lt;b&gt;Code Signing / Certificate /      Security&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a name="OutlookTransportMAPI"&gt;&lt;b&gt;Outlook / Transport / MAPI&lt;/b&gt;&lt;/a&gt;     &lt;ul&gt;&lt;li&gt;&lt;a title="TransportDemo sample in Pocket PC 5.0 SDK does not work? Check the solution here..." href="http://windowsmobilepro.blogspot.com/2006/02/transportdemo-sample-in-pocket-pc-50.html"&gt;TransportDemo          sample in Pocket PC 5.0 SDK does not work? Check the solution here...&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="How to retrieve/get TO, CC, BCC recipient address of an email through CEMAPI (C++) in Windows Mobile device?" href="http://windowsmobilepro.blogspot.com/2006/03/how-to-retrieveget-to-cc-bcc-recipient.html"&gt;How          to retrieve/get TO, CC, BCC recipient address of an email through CEMAPI          (C++) in Windows Mobile device?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="How to programmatically query mail account information in Windows Mobile devices, for example, incoming server and username?" href="http://windowsmobilepro.blogspot.com/2006/02/how-to-programmatically-query-mail.html"&gt;How          to programmatically query mail account information in Windows Mobile          devices, for example, incoming server and username?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/windows-mobile-50-new-mapi-functions.html"&gt;Windows          Mobile 5.0 New MAPI Functions Linker Error LNK2019 / LNK2001&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/pocket-outlook-woe-01-incoming-server.html"&gt;Pocket          Outlook Woe 01: incoming server and outgoing server are passed as two          NULL pointers from Outlook to Transport&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/pocket-outlook-woe-02-domain-name-is.html"&gt;Pocket          Outlook Woe 02: Domain name is truncated to the same size as that of          password after calling IMailSyncCallBack::RequestCredentials&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;   &lt;/li&gt;&lt;li&gt;&lt;a name="SSLSocketNetworkingConnectionManager"&gt;&lt;b&gt;SSL / Socket /      Networking / Connection Manager&lt;/b&gt;&lt;/a&gt;     &lt;ul&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/03/windows-mobile-secure-socket.html"&gt;Windows          Mobile Secure Socket Implementation Series 1: General Idea&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="Windows Mobile Secure Socket Implementation Series 2: Sample Source Code" href="http://windowsmobilepro.blogspot.com/2006/03/windows-mobile-secure-socket_25.html"&gt;Windows          Mobile Secure Socket Implementation Series 2: Sample Source Code&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="Windows Mobile Secure Socket Implementation Series 3: X.509 Certificate and Wildcard Certificate" href="http://windowsmobilepro.blogspot.com/2006/03/windows-mobile-secure-socket_28.html"&gt;Windows          Mobile Secure Socket Implementation Series 3: X.509 Certificate and          Wildcard Certificate&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="Windows Mobile Secure Socket Implementation Series 4: Changes in Windows Mobile 5.0 platform" href="http://windowsmobilepro.blogspot.com/2006/03/windows-mobile-secure-socket_31.html"&gt;Windows          Mobile Secure Socket Implementation Series 4: Changes in Windows Mobile          5.0 platform&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/etchosts-file-equivalent-in-windows.html"&gt;/etc/hosts          file equivalent in Windows Mobile device&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;   &lt;/li&gt;&lt;li&gt;&lt;a name="Notification"&gt;&lt;b&gt;Notification&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a name="ControlPanel"&gt;&lt;b&gt;Control Panel&lt;/b&gt;&lt;/a&gt;     &lt;ul&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2005/11/how-to-debug-control-panel-applet-in.html"&gt;How          to debug Control Panel Applet in Pocket PC 2003 and Pocket PC 5.0?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/02/how-to-put-your-own-control-panel.html"&gt;How          to put your own Control Panel Applet to "Personal" Group?&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;   &lt;/li&gt;&lt;li&gt;&lt;a name="SetupInstallUnInstall"&gt;&lt;b&gt;Setup / Install / unInstall / Upgrade&lt;/b&gt;&lt;/a&gt;     &lt;ul&gt;&lt;li&gt;&lt;a title="Programmatically unInstall/remove/delete one program in Windows Mobile devices" href="http://windowsmobilepro.blogspot.com/2006/03/programmatically-uninstallremovedelete.html"&gt;Programmatically          unInstall/remove/delete one program in Windows Mobile devices&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="Programmatically find out all the programs that can be unInstalled in Windows Mobile devices" href="http://windowsmobilepro.blogspot.com/2006/03/programmatically-find-out-all-programs.html"&gt;Programmatically          find out all the programs that can be unInstalled in Windows Mobile          devices&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="Source code to find out all the programs that are installed in a Windows Mobile device and that can be un-Installed" href="http://windowsmobilepro.blogspot.com/2006/03/source-code-to-find-out-all-programs.html"&gt;Source          code to find out all the programs that are installed in a Windows Mobile          device and that can be un-Installed&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;   &lt;/li&gt;&lt;li&gt;&lt;a name="CabwizBuild"&gt;&lt;b&gt;CabWiz / Build&lt;/b&gt;&lt;/a&gt;     &lt;ul&gt;&lt;li&gt;&lt;a title="Error: cab file could not be created - No, not again! Nice workaround/solution" href="http://windowsmobilepro.blogspot.com/2005/11/error-cab-file-could-not-be-created-no.html"&gt;Error:          cab file could not be created - No, not again! Nice workaround/solution&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;   &lt;/li&gt;&lt;li&gt;&lt;a name="Emulator"&gt;&lt;b&gt;Emulator&lt;/b&gt;&lt;/a&gt;     &lt;ul&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/emulator-troubleshootingtip-01-to.html"&gt;Emulator          Troubleshooting/Tip 01: To Cradle or Not to Cradle?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/emulator-troubleshootingtip-02.html"&gt;Emulator          Troubleshooting/Tip 02: Emulator Connecting to Internet (Internet          Pass-through Connectivity) Issue&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/05/emulator-troubleshootingtip-03-quickly.html" title="Emulator Troubleshooting/Tip 03: Quickly Establish ActiveSync Connection"&gt;Emulator          Troubleshooting/Tip 03: Quickly Establish ActiveSync Connection&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;   &lt;/li&gt;&lt;li&gt;&lt;b&gt;&lt;a name="Debug"&gt;Debug&lt;/a&gt;&lt;/b&gt;     &lt;ul&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/internal-use-spy-nice-hidden-debugging.html"&gt;Internal          Use Spy: A nice hidden debugging tool for Pocket PC 2003 device and          Pocket PC 5.0 device&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/05/pocket-pc-console-for-standard-input.html" title="Pocket PC Console for standard input and standard output: A convenient tool for lazy debugging and tracing in Pocket PC 2003 devices"&gt;Pocket          PC Console for standard input and standard output: A convenient tool for          lazy debugging and tracing in Pocket PC 2003 devices&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/05/xxxexe-is-not-valid-pocket-pc.html" title="XXX.exe is not a valid Pocket PC Application: Troubleshooting guidelines"&gt;XXX.exe          is not a valid Pocket PC Application: Troubleshooting guidelines&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;   &lt;/li&gt;&lt;li&gt;&lt;a name="DevelopmentTools"&gt;&lt;b&gt;Development Tools&lt;/b&gt;&lt;/a&gt;     &lt;ul&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/remote-ce-spy-shipped-with-visual.html"&gt;Remote          CE Spy shipped with Visual Studio 2005 fails to intercept windows          messages: Check the solution here!&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;   &lt;/li&gt;&lt;li&gt;&lt;a name="DevelopmentEnvironment"&gt;&lt;b&gt;Development Environment&lt;/b&gt;&lt;/a&gt;     &lt;ul&gt;&lt;li&gt;&lt;a title="Manually migrate Embedded Visual C++ workspace to Visual Studio 2005 (Beta 2) without using Migration Assistant (Upgrade Wizard)" href="http://windowsmobilepro.blogspot.com/2005/08/manually-migrate-embedded-visual-c.html"&gt;Manually          migrate Embedded Visual C++ workspace to Visual Studio 2005 (Beta 2)          without using Migration Assistant (Upgrade Wizard)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="1.1 .NET Framework is Needed for Smart Device Projects targeting 1.0 NET CF (Compact Framework) in Visual Studio 2005 (VS2005)" href="http://windowsmobilepro.blogspot.com/2006/03/11-net-framework-is-needed-for-smart.html"&gt;1.1          .NET Framework is Needed for Smart Device Projects targeting 1.0 NET CF          (Compact Framework) in Visual Studio 2005 (VS2005)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/how-to-use-new-camera-api-in-windows.html"&gt;How          to use the new Camera API in Windows Mobile 5.0 SDK with only Embedded          Visual C++ 4.0 (evc4)?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/using-camera-api-with-only-embedded.html"&gt;Using          Camera API with only Embedded Visual C++ 4.0 (evc4): Sample code and          EVC4 workspace download&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/trap-of-copying-project-settings-in.html"&gt;Trap          of Copying Project Settings in Visual Studio 2005 (/Machine:ARM vs.          Thumb, /subsystem:windowsce,4.02 vs 5.01)&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;   &lt;/li&gt;&lt;li&gt;&lt;a name="CrossPlatformDevelopment"&gt;&lt;b&gt;Cross-Platform Development&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a name="ProgrammersReview"&gt;&lt;b&gt;Programmer's Review&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a name="FixHackTrickTip"&gt;&lt;b&gt;Fixes / Hacks / Tricks / Tips&lt;/b&gt;&lt;/a&gt;     &lt;ul&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/extreme-makeover-how-to-rescue-pocket.html"&gt;Extreme          Makeover - How to rescue a Pocket PC with partially-damaged display          screen&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2006/04/how-to-launch-program-via-command-line.html"&gt;How          to launch a program via command line in Pocket PC 2003 device and Pocket          PC 5.0 device?&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;   &lt;/li&gt;&lt;li&gt;&lt;a name="QuickChecklist"&gt;&lt;b&gt;Quick Checklist&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a name="BloggingSocialNetworkingWeb2.0"&gt;&lt;b&gt;Blogging / Social Networking /      Web 2.0&lt;/b&gt;&lt;/a&gt;     &lt;ul&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2005/08/introduction.html"&gt;Introduction&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;   &lt;/li&gt;&lt;/ul&gt; &lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-114473715181955936?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/114473715181955936/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=114473715181955936' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114473715181955936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/114473715181955936'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2005/08/windows-mobile-pocket-pc-smartphone.html' title='Windows Mobile Pocket PC Smartphone Programming: SiteMap'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21999378.post-113916928239606714</id><published>2005-08-05T19:48:00.000-07:00</published><updated>2006-04-21T19:06:53.173-07:00</updated><title type='text'>Introduction</title><content type='html'>&lt;a href="http://www.blogger.com/profile/11237015"&gt;Here is my short profile&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://windowsmobilepro.blogspot.com/2005/08/windows-mobile-pocket-pc-smartphone.html"&gt;Here  is the SiteMap categorizing all my articles for easy navigation&lt;/a&gt;. Google's  blog is great in the sense that the blog writer has full control over the format  and presentation of the posts. However, lacking category is a huge drawback, and  makes it very difficult to navigate through the articles. A &lt;a href="http://windowsmobilepro.blogspot.com/2005/08/windows-mobile-pocket-pc-smartphone.html"&gt;site  map page&lt;/a&gt; is an valuable tool for readers.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;br /&gt;My daily job involves java design and programming for generic platforms, and C++  coding for Windows and Windows Mobile devices.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Goal of the Blog&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As a C++ and Java coder, I am new in blogging. The niche topic I picked for my  blog is the one with which I am familiar: Windows Mobile Pocket PC Smartphone  Programming. I tried hard to write &lt;span style="font-weight: bold;"&gt;original  contents&lt;/span&gt;, rather than easy re-blogging or quick short articles with a few  links. Most of the posts were based on my daily programming and problem solving  experiences, and may not publicly documented anywhere else. For example, how to &lt;a href="http://windowsmobilepro.blogspot.com/2006/02/how-to-put-your-own-control-panel.html"&gt;put  a Pocket PC Control Panel Applet into the "Personal" group&lt;/a&gt;, how to  &lt;a href="http://windowsmobilepro.blogspot.com/2006/02/how-to-programmatically-query-mail.html"&gt;programmatically  query mail account information (like username and server name)&lt;/a&gt;. &lt;a href="http://www.google.com/search?hl=en&amp;lr=&amp;amp;q=PR_CE_UNICODE_STORE_ID&amp;btnG=Search"&gt;A  google search might land only one result, which is my post here&lt;/a&gt; :) Hope my  hard work can benefit the Windows Mobile developer community. If you find a post  helpful, or have errors/problems/incompleteness, please take a few seconds to  drop a comment, which serves as great stimulus to me.&lt;br /&gt;&lt;br /&gt;One goal of the blog is &lt;span style="font-weight: bold;"&gt;tailor to programmers&lt;/span&gt;.  I tried to put as many lines of source code as possible. Those source codes are  written and tested by me. Whenever possible, a VS2005 solution or EVC4 workspace  is available for download. Some source codes are only snippets, appearing as  part of an article. A decent programmer should have little difficulty writing a  program using my source code, probably by adding header-file-includes and macro  definitions.&lt;br /&gt;&lt;br /&gt;I take pride in my hard work. I hope you can bookmark my site (typing Ctrl-D  now), or add the site feeds to your news reader: &lt;ul&gt;&lt;li&gt;&lt;a href="http://feeds.feedburner.com/WindowsMobilePro"&gt;RSS Feed&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://windowsmobilepro.blogspot.com/atom.xml"&gt;Atom Feed&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; I also hope you appreciate my hard work. If you need to use or refer to any  post, please provide a link to this site (preferred) or to the specific post.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;A little bit on my Personal Life&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Outside the technology world, I am interested in cars, dinosaurs, wild life,  prehistoric life, human evolution, science fiction, adventure movies, and etc. I  am a big fan of star wars series and lord of the rings series. I am also a super  fan of dinosaurs.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/5783/1371/1600/IMG_4591.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://photos1.blogger.com/blogger/5783/1371/320/IMG_4591.jpg" alt="" border="0" height="240" width="320" /&gt;&lt;/a&gt;My  wife and I are living happily in the sunny Bay Area. Our baby girl was born in  June 2005. She is the loveliest angel in the world, oh, make it “in my  world”. I have never had such strong, devoted, unconditional love toward any  other people, except my baby girl. Look at how lovely her smile is...&lt;br /&gt;&lt;br /&gt;Again, I have been trying hard to find time to post articles to my blog, and  trying harder to promote my site. If you like my site and articles, and would  like to swap a link, feel free to &lt;a href="mailto:windowsmobilepro@yahoo.com"&gt;drop  me a line&lt;/a&gt;. Comments or feedbacks on my articles are very welcome. I am  watching my inbox and comments all the time!&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-8510650669347560";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21999378-113916928239606714?l=windowsmobilepro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://windowsmobilepro.blogspot.com/feeds/113916928239606714/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21999378&amp;postID=113916928239606714' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/113916928239606714'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21999378/posts/default/113916928239606714'/><link rel='alternate' type='text/html' href='http://windowsmobilepro.blogspot.com/2005/08/introduction.html' title='Introduction'/><author><name>Lao K</name><uri>http://www.blogger.com/profile/13748590324739892436</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://windowsmobilepro.home.comcast.net/AbbyInBlog_2.jpg'/></author><thr:total>1</thr:total></entry></feed>
