Don't Change System Settings to Perform a Computation

A post from Raymond Chen today reminds me of the first application compatibility issue I debugged (and fixed). At the time I was working on the MSN client and our team was on loan to load balance compatibility bugs for the release of Windows XP.

This application (which will remain nameless) had an alarm clock feature and the problem was that when you set the alarm on XP it would hang. After of slogging through retail assembly code for a while I finally found that whenever you set an alarm they would use SetTimeZoneInformation to temporarily change the system's time zone as part of an internal calculation, and then call it again to change it back. From the user's point of view it was fast enough that you never noticed.

That by itself wouldn't cause a hang. What caused the hang is that they also handled the WM_TIMECHANGE message, ostensibly to update the alarm if there was a system time or time zone change. While handling this message they called SetTimeZoneInformation to do their computation, which on XP caused the WM_TIMECHANGE notification to be sent again, leading to an asynchronous infinite loop.

The fix was to add a shim as part of the application compatibility functionality in Windows (from XP on, I believe), which provides a way to implement per-application compatibility workarounds without polluting the core Windows code base. The shim simply detected that a WM_TIMECHANGE was triggered by a call to SetTimeZoneInformation for this application and blocked the subsequent WM_TIMECHANGE notification.