I just ran into this fairly old post on Channel 9. mstefan reported that his applications played a “Ding” noise when selecting an item in a listview (or tree) control.
It turns out that I’d had the problem independently reported to me by one of the people here at Microsoft. Here were his reproduction steps:
Complicating matters is that this didn’t occur with many apps, just a couple of Windows Forms applications that the person at Microsoft had. So I dug into it a bit.
I quickly realized that the problem was that the application was calling PlaySound without the “SND_NODEFAULT” flag. I’ve written about this flag before (in fact I wrote that post shortly after investigating this issue, so that post contains part of the story).
Digging in deeper, I realized that the application was using version 5 of the common controls (there are two versions in Windows, v5 and v6). The problem didn’t occur in the version 6 common controls (this is why most applications didn’t reproduce the problem).
So why did the problem occur?
The common controls have a single routine which calls PlaySound and that code attempts to be somewhat clever. Instead of simply calling PlaySound, the code instead read the HKEY_CURRENT_USER\AppEvents\Schemes\.Default\CCSelect registry key. If the key didn’t exist, it skipped calling PlaySound. If the CCSelect registry key existed, it would call PlaySound specifying the CCSelect alias.
I’ve actually run into this pattern a bunch in WIndows – teams decided that calling PlaySound was “too slow”, or had “too much overhead” so they tried to avoid the call to PlaySound if the call to PlaySound wasn’t going to do anything (once upon a time it was important to avoid calling PlaySound because it could sometimes hang your application for several seconds – this isn’t the case any more if you specify SND_ASYNC).
The problem is that when you hit step 2 above (setting the “Select” sound), the control panel created the CCSelect registry key with a default value of the sound file you’re setting. When you set it to “None” the control panel cleared the value of the sound contained under the key. But the key itself wasn’t deleted. So the check above that checked for the registry key’s existence succeeded and it called PlaySound. But because the call didn’t specify SND_NODEFAULT, the PlaySound API decided to play the default sound when it realized that there wasn’t a sound associated with the CCSelect alias.
I wanted to understand how this bug was introduced so I looked back at the source history of the file containing the bug. It turns out that this was actually a bug fix made to Windows XP that wasn’t incorporated into Windows Server 2003. When Windows Vista was created, the team started with the Windows Server 2003 code base and incorporated all the bug fixes made since Windows XP forked into the Win2K3 code base. For whatever reason, this particular fix was missed when the team did the merge. Because the behavior was so subtle (to trigger the change you MUST go through steps 2 through 4 to get the registry key created and your app must use the v5 of the common controls).
Needless to say, it’s fixed in WIndows 7.
You should compliment whoever succeeded in figuring out the reproduction steps. Most users have a lot of difficulty backtracking and remembering the options they tweaked before doing something.
Scott, believe me I did. He gave me TS access to his machine in the repro state which helped.
So was the fix to, in PlaySound, detect the case when you have a blank registry key, or to make the code that clears the select sound not just clear the key but delete it?
My intuition is that the latter is the more robust solution, but my inner paranoid programmer says that there may be other parts of Windows, or third party apps, which rely on that registry key being blank in that case and that a localised fix would be safer.
jMarkP: No, the fix was in the v5 common controls - that's where the bug was.
PlaySound was behaving exactly as designed. The problem was that the v5 common controls thought they should call PlaySound but they shouldn't.
Actually, I had this with XNews (a newsreader written in Delphi).
Mihai: Did it use the v5 common controls?
I've actually experienced this same problem on my Vista machine, and I'm trying (in vain, currently) to remember the application that caused it. As I can recall, it used a checkbox list and clicking anywhere in the list would result in a little ding! sound.
The two things that stand out, however, is that I've never set a sound for the Select event (it has always had it's default empty value) and I don't believe it was a WinForms app (though I could be wrong). If I can remember, maybe I'll reply to myself here.
A followup question if I might: this leads to something I've wondered for a while about Microsoft patching. You said this problem is fixed in Win7, which is good, but since you've identified the problem, why not fix it in Vista as well (some kind of non-critical update)? Is it just a matter of not allocating the testing resources for a non-critical problem?
Nick, feel free to report the problem to Microsoft. Let customer support know that the bug exists in Vista and is fixed in Windows 7 and ask for a hotfix.
In general the bar for taking fixes after we RTM is fairly high - almost as high as bar was at RTM (because there are extremely limited opportunities to test the fix). As such it's highly unlikely that such a cosmetic fix would be included in a hotfix.
Thanks for the reply Larry. It's obviously not a big deal, I was just wondering what the primary reason was for not fixing a bug once you discover cause and solution. I suppose a big part is probably that since Windows (n+1) has just been released, there isn't much reason or incentive to fix minor issues in Windows (n).
For what it's worth, the troublesome application was TrueCrypt. It uses listboxes (SysListView32) which ding! in response to clicks. The most obvious is the list view containing drive letters in the main window. I'll have to try it on Win7 tomorrow and see if it's fixed.
The best part about reading MSDN blogs like yours and Raymond's is the "So THAT'S why that happened six months ago!" factor you get now and then. The TrueCrypt dinging was a really odd behavior that got me wondering as to the cause. And now I know the rest of the story :)
Nick: That's close - in general non-security bugs found in version <n> that are also in version <n-1> aren't marked for back porting to older versions of the OS.
Once we ship a version of Windows, maintenance shifts from the product development team to another team and that other team decides the bar for making fixes. They triage all the bugs that we indicated might require back porting against their internal bug bar. This bug WAS marked for backporting and I don't know what the maintenance team decided to do with it.
Hmm, am I just being paranoid or this bugfix won't be backported?
Me: It will be backported if there is sufficient reason to backport the bug. But the justification has to be very compelling (think security or data corruption). This bug is quite annoying but doesn't come close to that level.
Windows is no different from any other major OS. The OS vendors (including Red Hat and Canonical) don't tend to backport fixes to older versions of their OS. Sure on *nix you can back port the fix yourself but when you do that, you kiss your support goodbye.
My favorite case of missing SND_NODEFAULT flag is the tray volume control in 2000/XP. Being GUI sound hater as I am, I always choose "No Sounds" scheme. Since the default ding (which the volume control is playing when you move it) is missing, it gets redirected to beep.sys, which is pretty amusing and annoying. I'll have to just use an empty WAV file for a default sound.
Larry, I hope this works OK in Vista/Win7 tray volume control. I havent checked that yet.
So they horribly broke backward compatibility with a silly "ding" sound every time someone clicks an item in a listview.
If you are a developer with an app that "dings" WHATS THE FIX????
Doug: Your idea of "horribly" is very different from my idea of "horribly". Remember that this only affects apps which don't use the v6 version of the common controls, that's a relatively small set of apps.
There are two solutions: 1) Use the v6 version of the common controls (you probably want to do that anyway) or 2) mung with the registry to work around the bug (you need to be very careful if you do that to avoid screwing over user choices).