Why do I have to return this goofy value for WM_DEVICECHANGE?

To deny a device removal query, you must return the special value BROADCAST_QUERY_DENY, which has the curious value 0x424D5144. What's the story behind that?

Well, we first tried following the pattern set by WM_QUERYENDSESSION, where returning TRUE allows the operation to proceed and returning FALSE causes the operation to fail. But when we did this, we found that lots of programs were denying all Plug and Play removal requests - programs that were written for Windows 3.1 which didn't have Plug and Play! How could this be?

These programs decided, "Well, I have the Windows 3.1 SDK right here in front of me and I looked at all the messages. The ones I care about, I handled, and for all the others, I will just return zero instead of calling DefWindowProc." And they managed to get this to work in Windows 3.1 because they read the SDK carefully and found the five or six messages that require a nonzero return value and made sure to return that nonzero value. The rest got zero.

And then when we added a new message that required a nonzero return value (which DefWindowProc provided), these programs continued to return zero and caused all device removal queries to fail.

So we had to change the "cancel" return value to something that wasn't zero. To play it extra safe, we also made the "cancel" return value something other than 1, since we suspected that there would be lots of programs who were just returning TRUE to all messages and we didn't want to have to rewrite the specification twice.

Comments (12)
  1. Curt Hagenlocher says:

    Yes, but what does "DQMB" mean? Device Query Message Broadcast? Or should the 0x51 have been a 0x55 instead?

  2. Mike Dimmick says:

    Normally, MS ’embedded ASCII’ codes should be read from least- to most-significant byte, so in this case it’s BMQD, which I assume is Broadcast Message Query Deny.

    Other ones I can recall are the special structured exception codes used by Visual C++’s C++ exception handling (0xE06D7363, or E0 followed by "msc") and the equivalent in the CLR: 0xE0434F4D = 0xE0 + "COM".

    There’s another magic number in the C++ exception handling tables that appears to be the date that the programmer worked on it: 1993mmdd (I can’t find the reference at the moment).

  3. evariste says:

    Raymond, why is it that when you hover over a folder to get its size in a tooltip, the routine doing the calculating doesn’t seem to give up and say "larger than n gb" in a consistent manner? Sometimes it gives up after only 4 gb, sometimes it counts 11 gb then gives up…

  4. Jordan Russell says:

    evariste: I would guess that it stops after a certain number of seconds have passed.

  5. You’re right, Jordan. Explorer only scans the folder for a maximum of 2-3 seconds and gives up with an incomplete result if it runs out of time. However, since the directory structure is cached, you can get incremental results by bringing up the tooltip again and again until everything is counted. A lazy man’s Properties box, I guess :)

  6. C# fan says:

    Raymond, if you have a little time, see this issue with the PostQuitMessage/WM_DESTROY here: http://discuss.fogcreek.com/joelonsoftware/default.asp?cmd=show&ixPost=92812

  7. Raymond Chen says:

    Yes it would have been nice to forward drops, but the problem is that there is no way to forward a drop to another window. To forward the drop, you’d have to get the IDropTarget of the window you want to forward to, but there is no way to get it. (You can attach an IDropTarget to a window via RegisterDragDrop but you can’t query the drop target from a window.)

  8. Mike Dimmick says:

    Well, surely some piece of Windows knows, otherwise how would OLE know to call the IDropTarget methods when something is dragged over the window?

    Kraig Brockschmidt in Inside OLE (available in the Jan 2001 MSDN I have on my hard disk) says that RegisterDragDrop sets a window property with SetWindowProp – I think he means SetProp. I suspect, however, that this will only make sense in the context of the window’s process – it’s probably a local object pointer rather than a marshalled interface, and OLE is making an internal cross-process call to perform the appropriate work.

    I don’t see a reason why a feature couldn’t have been added to OLE to proxy the drop, though. I suppose everyone would have started proxying everyone else’s drops, given the general tendency of developers to try to steal other programs’ events…

  9. Moi says:

    Rymond, what question was your 12/07/2003 6:58 PM post answering? Am I not seeing all the comments, here, or what?

  10. Raymond Chen says:

    Hm, I was answering a question about why you can’t drop on a taskbar button, but I don’t see the source comment either. Odd.

  11. If you don’t, all sorts of bad things happen.

Comments are closed.