Tailor: “Do you dress to the right, sir?”
Danny: “No, I always vote New Labour.”
Tailor: “Ah, swinging to the right it is…”
There’s a subtle issue around handling WM_DESTROY in an ATL window and also overriding OnFinalMessage, if using the ATL windowing classes on Windows CE.
Typically, you would override OnFinalMessage if you wanted to do some final cleanup when the window has been destroyed and no further messages will be received. The canonical example – given in the documentation – is automatically deleting the object that manages the window using delete this.
On the desktop, OnFinalMessage is called by the CWindowImplBaseT::WindowProc function after the WM_NCDESTROY message is received. Since Windows CE top-level windows don’t have a non-client area, the non-client messages were removed from the platform. The Windows CE version of ATL therefore uses WM_DESTROY instead.
The code inside WindowProc only cleans up the window proc thunks (dynamic objects containing code used to patch between Windows’ expectation of a flat API, and a call to a C++ object member function) and calls OnFinalMessage if the message (WM_DESTROY or WM_NCDESTROY as appropriate) is not handled. This means it will work fine if you don’t override WM_DESTROY, but what if you need to do some cleanup here?
The last parameter of a message handling function in ATL is a BOOL reference typically named bHandled. This is set to TRUE by the message map macros (ATL message map macros generate a big if statement, rather than being table-driven like MFC) on calling the message handling function. If the value is still TRUE when the function returns, the message map considers it handled and stops processing; if it’s FALSE the macro code keeps looking for a handler.
If you handle WM_DESTROY on CE using ATL, you must set bHandled to FALSE, otherwise the window will never be cleaned up, and OnFinalMessage will not be called. The same is true if you handle WM_NCDESTROY on the desktop, but since this message is rarely handled, it’s less of an issue.
This issue was responsible for me leaking 96 bytes in a program every time an activity was completed, which doesn’t sound like a lot, but any long-running application needs to be free of leaks as far as possible. This was actually a Compact Framework program for the most part – this window implemented a signature capture control, which is actually pretty hard to do in CF 1.0, and we already had working C++ code (excepting leaks…). For some strange reason, though, a leak of 96 bytes here was causing an overall leak of over 300KB of virtual memory! Removing this leak has got it down to about 160KB but I’m stumped on where the rest of it’s going – the amount of VM allocated increases by 160KB whenever the form containing the control is created, but that isn’t returned when the form is disposed. A C++ program containing the control doesn’t exhibit the same behaviour.
Compact Framework seems to do wacky things to the process default heap, which usually means that you can’t actually view it with Remote Heap Walker – it aborts after several seconds of trying to walk the heap. To find this leak I created a non-default heap, overrode operator new and operator delete to allocate and free from this alternative heap, then viewed that.
If you're subscribed and want to follow me if/when I do move, I've added a feed through FeedBurner which should allow me to automatically switch to whichever new service I go for. In the spirit of full disclosure I should add that it also allows me to track who's reading my feed, which I don't get at the moment from Blogger. I believe it also does content negotiation, so if your aggregator supports RSS you should get RSS while if it supports Atom you should get Atom.
If you're a developer using Windows Mobile or Windows CE devices, you may be a bit fed up with the Partnership Wizard that appears when you connect a device. If you decide to create a partnership every time, your list of partnerships grows huge, you keep having to think of a unique name, and you still have to do it every time after hard resetting the device. Alternatively, if you cancel out or opt to connect as Guest, you have to do this every time you connect. After nearly five years of mobile device development I'm sick at the sight of this wizard.
There is another option: to use an undocumented registry key to stop the wizard appearing. Open Registry Editor (as an administrator) and navigate to HKEY_LOCAL_MACHINE\Software\Microsoft\Windows CE Services. Create a new DWORD value called GuestOnly and set its value to 1. The wizard will no longer appear on connecting a device. If you ever do need to create a partnership, you'll need to set this value back to 0 before connecting.
If you already have a partnership with a device, it will still connect with its partnership, rather than as Guest, even if this option is set.
There still seems to be a bit of confusion over the identity of 64-bit processors for Windows operating systems. Windows runs on two types of 64-bit processor, identified as x64 and IA-64.
Going with the oldest first, IA-64 stands for Intel Architecture, 64-bit and was Intel’s attempt to move to a 64-bit architecture. It remains compatible with 32-bit user-mode code through hardware emulation, but this hardware emulation performs so poorly relative to a genuine x86 that all operating systems shipping for IA-64 now include a software x86 emulation called IA-32 EL. IA-64 is the instruction set; the family of processors which implement it are named Itanium (which you’ll see critics refer to as Itanic, suggesting that it’s sinking) and so you’ll sometimes see code written for them referenced as Itanium Processor Family or IPF. You need a new operating system to run any code on an Itanium – it cannot boot a 32-bit operating system.
x64 is actually a Microsoft term and stands for Extended 64. It is implemented by both AMD and Intel who respectively call it AMD64 and EM-64T (Extended Memory 64 Technology). AMD invented it as extensions to the existing x86 architecture. An x64-capable processor natively implements x86 in hardware – it is an x86 processor, with additional modes. It boots up in the same 16-bit ‘real mode’ that an x86 does. It can run existing 32-bit operating systems. You may well have an x64-capable processor without realising it. All AMD Athlon 64 and Opteron processors, and Intel Pentium 4, Pentium D and Xeon processors built within about the last year, implement x64. To check whether your Intel processor supports x64, use Intel’s Processor Identification Utility.
Itanium had the early lead and for a while held the general performance crown, but the relentless increase in x86 clock speeds eventually had AMD’s Opteron overtake it for integer calculation performance. Itanium still leads for floating point performance but has been stuck at 1.6GHz for about two years, if I recall correctly. It’s liable to be beaten by Intel’s own ‘Woodcrest’ Xeon-replacement later this year, in my opinion, if it remains stuck at this (now relatively low) speed.
Itanium is now pretty-much reserved to big-iron datacentre servers. It’s good for highly computationally-intensive applications. If you just need lots of memory, go with x64. Itanium used to have an advantage in number of supported processors too, but IBM recently started selling the xSeries 460 which supports up to 32 dual-core Xeons. This hits Microsoft’s limit of 64 logical processors which applies to both architectures.
This is kind of a brain-dump. I get asked this a fair bit – which tools do you need to develop for Windows CE and/or Windows Mobile? (See here for the difference.)
For Windows CE 3.0 custom platforms, Pocket PC 2000 and Pocket PC 2002: eMbedded Visual C++ 3.0. You cannot debug on these older devices using eVC 4.0; you can’t debug CE 4.x or later devices using eVC 3.0.
For Windows CE 4.x custom platforms: eMbedded Visual C++ 4.0. At least SP1 is required for CE 4.1, SP2 for CE 4.2, latest is SP4. SP1 and SP2 were mutually exclusive – if you installed SP2 you couldn’t develop for CE 4.1; this was rectified in SP3.
For Pocket PC 2003 (alternatively Windows Mobile 2003 for Pocket PC), Smartphone 2003 (Windows Mobile 2003 for Smartphone) and respective Second Editions: eVC 4.0 SP2 or later, or VS 2005.
For Windows CE 5.x custom platforms: eVC 4.0 SP4, or VS 2005. You will get link errors complaining about corrupt debug information if you use eVC 4.0 because the platforms are actually built using version 13.1 (VS2003–compatible) compilers while eVC 4.0 SP4 can only handle debug information from version 12.0 (VC 6.0–compatible) compilers, hence SP4 only includes 12.0 compilers.
For Windows Mobile 5.0: VS 2005 only. The SDKs do not install into eVC 4.0.
For whatever device you’re building for, you need the correct SDK. However, you will find that programs are binary-compatible across different CE platforms, if the APIs required by the program are present on the platform. Using the correct SDK ensures that you build for the correct processor type and don’t accidentally reference APIs that won’t be available at runtime.
.NET Compact Framework 1.0 is supported for Pocket PC 2002, Windows Mobile 2003 for Pocket PC, Windows Mobile 2003 for Smartphone and Windows Mobile 5.0, and custom CE 4.x platforms. For Pocket PC 2002 you must use VS.NET 2003; for Windows Mobile 5.0 you need VS 2005 (I think). For Windows Mobile 2003 you can use either, and I would strongly recommend using VS 2005 as soon as you can stand to convert your project. This will completely rewrite your resx files. Converting the project does not mean immediately upgrading to .NET Compact Framework 2.0, that’s a separate step.
.NET Compact Framework 2.0 requires VS 2005 and only runs on Windows Mobile 2003 for Pocket PC (not WM2003 Smartphone), and CE 5.0 and Windows Mobile 5.0 devices.
VS2005 requires ActiveSync 4.1, minimum, for deployment and debugging. I was originally annoyed at the loss of network synchronisation capability, but found that, if a wireless connection is present, you can begin a debugging session over USB and continue over wireless if you disconnect from the cradle or cable.
To complete the compatibility matrix, as far as I can see CF1.0’s SqlCeClient only works with SQL Server CE 2.0 while CF2.0’s only works with SQL Mobile 2005 (SQL Server 2005 Mobile Edition). If anyone knows different let me know.