May, 2012

  • The Old New Thing

    What happens if I call KillTimer with a NULL hwnd?

    • 16 Comments

    A customer discovered a bug in their code and wanted some information on how serious it was, so they could assess how urgently they need to issue a fix.

    We have code that calls Set­Timer with a valid window handle, but then we destroy the window before we get around to calling Kill­Timer. When we finally do call Kill­Timer, we do so with a NULL window handle. The Kill­Timer calls are probably harmless, but are we leaking the timers?

    The customer's real concern was actually in the part of the problem they thought was a point of little concern. The window manager cleans up orphaned timers when the associated window is destroyed, so there is no timer leak in this case. Of course, it's still good practice to clean up those timers. (Note however that a similar situation does lead to leaked timers.)

    The real danger is in the Kill­Timer call. By passing a null window handle, you are killing a thread timer. Maybe you're lucky and there is no thread timer whose ID is the value you passed as the second parameter, but someday your luck will run out and you will accidentally kill somebody else's timer.

    The customer was pleased with this explanation.

    That's exactly the information we were looking for. Thanks.
  • The Old New Thing

    What does a STATUS_OBJECT_TYPE_MISMATCH exception in LeaveCriticalSection mean?

    • 10 Comments

    It means the same thing as a STATUS_INVALID_HANDLE exception.

  • The Old New Thing

    Hazards of spelling autocorrection: defiance

    • 44 Comments

    On an internal mailing list, a colleague asked for some recommendations on a webcam.

    I was wondering if there are any models I should avoid or defiantly get.

    I got this mental image of my colleague giving the salesperson the finger as he handed over his credit card.

    My colleague explained, "That's an error I frequently make because Outlook by default autocorrects 'definatly' to 'defiantly' instead of 'definitely'. You should see the reaction from my manager when he asks me to do something and I write back, 'I'll defiantly do that.' I'm a terrible speller. That's why I went into math: Only single letters."

    But the kicker was the end of his original message.

    We'll be using Windows Live Massager.
  • The Old New Thing

    If my window hosts multiple windowless ActiveX controls, which one do I call IOleInPlaceActiveObject::TranslateAccelerator and IOleInPlaceObjectWindowless::OnWindowMessage on?

    • 15 Comments

    Commenter Farproc asks how one goes about hosting two windowless ActiveX controls in a single window. In particular, "none of the documentation explains how to choose which control to send IOle­In­Place­Active­Object::Translate­Accelerator and IOle­In­Place­Object­Windowless::On­Window­Message on?"

    Actually, the documentation does say.

    The documentation for IOle­In­Place­Active­Object::Translate­Accelerator says, "Active in-place objects must always be given the first chance at translating accelerator keystrokes." So you pass the message to the active in-place object. Your window may host multiple windowless ActiveX controls, but at most one of them is the active object at a time. And most of the time, none of them will be active. For example, in Word, most of the time the insertion point is in the text part of the document. Only occasionally do you activate an in-place object by, say, double-clicking on an embedded Excel spreadsheet, at which point Excel adds its menu items to your menu bar and basically takes over your application window for a while.

    Here's an example of Windows 95's Wordpad hosting Paint as an in-place active object.

    Source: 2.1.6 OLE/COM example: using compound documents

    If you have an in-place active object, then it's the one that gets the IOle­In­Place­Active­Object::Translate­Accelerator If, as is usually the case, you don't have an in-place active object, then nobody's IOle­In­Place­Active­Object::Translate­Accelerator gets called because they aren't the in-place active object. (It's right there in the interface name.)

    For IOle­In­Place­Object­Windowless::On­Window­Message, the documentation is even more explicit. It contains pretty much a checklist of what you need to do.

    For the following messages, the container should first dispatch the message to the windowless object that has captured the mouse, if any. Otherwise, the container should dispatch the message to the windowless object under the mouse cursor. If there is no such object, the container is free to process the message itself:

    • WM_MOUSEMOVE
    • WM_SETCURSOR
    • WM_XBUTTONDOWN
    • WM_XBUTTONUP
    • WM_XBUTTONDBLCLK

    The container should dispatch the message to the windowless object with the keyboard focus for the following messages:

    • WM_CANCELMODE
    • WM_CHAR
    • WM_DEADCHAR
    • WM_HELP
    • WM_IMExxx
    • WM_KEYDOWN
    • WM_KEYUP
    • WM_SYSDEADCHAR
    • WM_SYSKEYDOWN
    • WM_SYSKEYUP

    For all other messages, the container should process the message on its own.

    There it is, plain as day.

    Farproc's last question was "how to track or set 'focus' if there is at least one windowless control."

    Um, in a variable?

    I was kind of confused by this question because it's part of the deal that when you use windowless controls, you don't have the window manager to take care of keeping track of which sub-object has focus. That now becomes your job.

    The user clicked on an object. I guess that's the focus object now. Oh wait, now the user hit the left arrow. I guess the object to the left of that object has focus now. It's just like any other control with windowless sub-components, like list boxes. You have to keep track yourself of the currently-selected item and other properties which the window manager normally does for you. If you don't have any windows, then there is nothing for the window manager to manage. From the window manager's point of view, focus is on your container. You then have to manage focus within your window yourself by keeping track of which of your sub-objects is the focus object.

  • The Old New Thing

    The extern "C" specifier disables C++ mangling, but that doesn't mean it disables mangling

    • 18 Comments

    The MSDN documentation on dllexport contains the following enigmatic paragraph, or at least did at the time I wrote this article:

    dllexport of a C++ function will expose the function with C++ name mangling. If C++ name mangling is not desired, either use a .def file (EXPORTS keyword) or declare the function as extern "C".

    I've seen this sentence misinterpreted as follows:

    dllexport of a C++ function will expose the function with C++ name mangling. To disable name mangling either use a .def file (EXPORTS keyword) or declare the function as extern "C".

    This is an understandable misinterpretation, but it is still a misinterpretation.

    The root cause of the misinterpretation is that the author of this documentation was wearing C++-colored glasses. In the author's mind, there are only two interesting cases:

    1. C++ name mangling, where all the cool people are, and
    2. everything else, for all the lamers.

    Here is a precise formulation of the paragraph:

    dllexport of a C++ function will expose the function with C++ name mangling. If C++ name mangling is not desired, either use a .def file (EXPORTS keyword), which will expose the name without mangling, or declare the function as extern "C", which will expose the name with C mangling.

    Here's a version of the paragraph that tries to take away the C++-colored glasses.

    dllexport exposes the function as it is decorated by the compiler. For example, if the function is a C++ function, it will be exposed with C++ name mangling. If the function is a C function, or has been declared as extern "C", it will be exposed with C name mangling. To expose the function under its unmangled name (or to expose it via an alternate name), use use a .def file (EXPORTS keyword).

    Behind the scenes: To forestall nitpickers, I had to go back to my copy of the C++ standard to make sure I filled in the blank in "The extern "C" _________" correctly. Officially, extern "C" is a storage class specifier.

  • The Old New Thing

    How do I prevent unchecked checkboxes in my listview control from disappearing?

    • 22 Comments

    A customer asked, "I have a listview control in report view with the LVS_EX_CHECK­BOXES extended style. I noticed that unchecked checkboxes are not visible until I hover over the corresponding item. Is it possible to get the checkboxes to be visible all the time?"

    I was kind of puzzled by this question because the default behavior of the list view control is to show the checkboxes all the time. I could have sat down and written a test program to prove it, but that would have taken too much time, and it wouldn't have advanced the story any. (The customer would merely have written back, "Well, that's not what I'm seeing.")

    This appeared to be a case of a customer providing incomplete information, forcing me to invoke my psychic powers to fill them in.

    "My psychic powers tell me that you have also set the LVS_EX_AUTO­CHECK­SELECT extended style. When LVS_EX_AUTO­CHECK­SELECT is set, then unchecked checkboxes are hidden."

    Remember, when you ask a question about a component and you have done any customization to that component, please remember to mention that when you ask your question. Otherwise nobody will be able to reproduce your problem, because they will assume you left everything at the defaults.

    It's like calling the Ikea customer service line, saying "My Ikea Frusträt rolling cabinet doesn't roll properly on my hardwood floor when I put more than about 25 pounds of stuff on it." The person on the phone looks up the specifications for the rolling cabinet and sees that that is well within the design limits. "I paid for you guys to assemble and install it, so it can't be an assembly or installation error." The person on the other end scratches their head for a while. And then you mention, "Oh, but I didn't like the color of the wheels, so I replaced them with some other wheels I bought at Home Depot."

    Oh, yeah, thanks for not mentioning that.

  • The Old New Thing

    GUIDs are designed to be unique, not random

    • 47 Comments

    A customer liaison asked, "My customer is looking for information on the GUID generation algorithm. They need to select N items randomly from a pool of M (jury selection), and their proposed algorithm is to assign each item a GUID, then sort the items by GUID and take the first N." (I've seen similar questions regarding using GUIDs for things like passwords or other situations where the programmer is looking for a way to generate a value that cannot be predicted.)

    The GUID generation algorithm was designed for uniqueness. It was not designed for randomness or for unpredictability. Indeed, if you look at an earlier discussion, you can see that so-called Algorithm 1 is non-random and totally predictable. If you use an Algorithm 1 GUID generator to assign GUIDs to candidates, you'll find that the GUIDs are assigned in numerically ascending order (because the timestamp increases). The customer's proposed algorithm would most likely end up choosing for jury duty the first N people entered into the system after a 32-bit timer rollover. Definitely not random.

    Similarly, the person who wanted to use a GUID for password generation would find that the passwords are totally predictable if you know what time the GUID was generated and which computer generated the GUID (which you can get by looking at the final six bytes from some other password-GUID). Totally-predictable passwords are probably not a good idea.

    Even the Version 4 GUID algorithm (which basically says "set the version to 4 and fill everything else with random or pseudo-random numbers") is not guaranteed to be unpredictable, because the algorithm does not specify the quality of the random number generator. The Wikipedia article for GUID contains primary research which suggests that future and previous GUIDs can be predicted based on knowledge of the random number generator state, since the generator is not cryptographically strong.

    If you want a random number generator, then use a random number generator.

    Bonus reading: Eric Lippert's GUID Guide, part 1, part 2, and part 3.

  • The Old New Thing

    Why is the Close button in the upper right corner?

    • 47 Comments
    Chris wants to know how the close button ended up to the right of the minimize and maximize/restore buttons. "In OS/2, it is on the left, which left the two other buttons in place."

    I don't know why the Close button went to the upper right instead of going to the left of the other buttons, but I'm going to guess. (That's what I do around here most of the time anyway; I just don't usually call it out.)

    Two words: Fitts's Law.

    The corners of the screen are very valuable, because users can target them with very little effort. You just slam the mouse in the direction you want, and the cursor goes into the corner. And since closing a window is a much more common operation than minimizing, maximizing, and restoring it, it seems a natural choice to give the close button the preferred location.

    Besides, maximizing and restoring a window already have very large targets, namely the entire caption. You can double-click the caption to maximize, and double-click again to restore. The restore even gets you a little bit of Fitt's Law action because the top of the screen makes the height of the caption bar effectively infinite.

  • The Old New Thing

    What was the registry like in 16-bit Windows?

    • 22 Comments

    Commenter Niels wonders when and how the registry was introduced to 16-bit Windows and how much of it carried over to Windows 95.

    The 16-bit registry was extremely simple. There were just keys, no values. The only hive was HKEY_CLASSES_ROOT. All it was used for was COM objects and file associations. The registry was stored in the REG.DAT file, and its maximum size was 64KB.

    It is my recollection that the registry was introduced in Windows 3.1, but Niels says it's not in a plain vanilla install, so I guess my memory is faulty.

    None of the 16-bit registry code was carried over to Windows 95. Windows 95 extended the registry into kernel mode, added support for values and non-string data types, increased the maximum registry size (though if some people are to be believed, not by enough), and added a bunch of other hives, like added the HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, and the HKEY_DYN_DATA, The old 16-bit registry code was woefully inadequate for all these new requirements (especially the kernel mode part), so it was all thrown out and a brand new registry written.

    In the early days of the Windows 95 registry, the in-memory signature value to identify the data structures which represent an open registry key were four bytes which corresponded to the ASCII values for the initials of the two programmers who wrote it.

  • The Old New Thing

    How to view the stack of threads that were terminated as part of process teardown from user mode

    • 25 Comments

    Last time we saw how to view the stack of threads that were terminated as part of process teardown from the kernel debugger. You can do the same thing from a user-mode debugger, and it's actually a bit easier there. (The user-mode debugger I'm using is the one that comes with the Debugging Tools for Windows, the debugging engine that goes by a number of different front-ends, such as ntsd, cdb, and windbg.)

    A direct translation of the kernel-mode technique from last time would involve using the !vadump command and picking through for the memory blocks with candidate size and attributes. But there's an easier way.

    Now would be a good point for me to remind you that this information is for debugging purposes only. The structures and offsets are all implementation details which can change from release to release.

    Recall that the TEB begins with some pointers which bound the stack, and the seventh pointer is a self-pointer. What's even more useful is the thirteenth pointer (offset 0x30 for 32-bit TEBs, offset 0x60 for 64-bit TEBs), because that is where the PEB is stored.

    Each process has a single global PEB, so all the TEBs will have the same PEB value at offset 0x30/0x60. And you can figure out the address of the current process's PEB either by using the !peb command or by simply looking at the TEB you already have.

    0:000> dd fs:30 l1
    0053:00000030  7efde000
    

    Now you can search through memory looking for that value. If you see any hits at offset 0x30/0x60, then that's a candidate TEB.

    The debugger normally limits memory scans to 256MB.

    0:001> s 00000000 L 80000000 00 e0 fd 7e
                               ^ Range error in 's 00000000 l 80000000 00 e0 fd 7e'
    

    Therefore, you have to issue the search eight times (for 32-bit processes) to cover the 2GB user-mode address space.

    0:001> s 00000000 L 10000000 00 e0 fd 7e
    0009e01c  00 e0 fd 7e 00 d0 fd 7e-44 e0 09 00 7b ef 17 77  ...~...~D...{..w
    0009fdc0  00 e0 fd 7e 44 00 00 00-f0 ee 3a 00 10 ef 3a 00  ...~D.....:...:.
    0009fe34  00 e0 fd 7e 78 fe 09 00-02 9f 18 77 00 e0 fd 7e  ...~x......w...~
    0:001> s 10000000 L 10000000 00 e0 fd 7e
    0:001> s 20000000 L 10000000 00 e0 fd 7e
    0:001> s 30000000 L 10000000 00 e0 fd 7e
    0:001> s 40000000 L 10000000 00 e0 fd 7e
    0:001> s 50000000 L 10000000 00 e0 fd 7e
    0:001> s 60000000 L 10000000 00 e0 fd 7e
    0:001> s 70000000 L 10000000 00 e0 fd 7e
    7486af70  00 e0 fd 7e 00 00 00 00-b8 00 16 77 28 00 16 77  ...~.......w(..w
    7efda030  00 e0 fd 7e 00 00 00 00-00 00 00 00 00 00 00 00  ...~............
    7efdd030  00 e0 fd 7e 00 00 00 00-00 00 00 00 00 00 00 00  ...~............
    

    Alternatively, you can use the "length sanity check override" by inserting a question mark after the L:

    0:001> s 00000000 L?80000000 00 e0 fd 7e
    0009e01c  00 e0 fd 7e 00 d0 fd 7e-44 e0 09 00 7b ef 17 77  ...~...~D...{..w
    0009fdc0  00 e0 fd 7e 44 00 00 00-f0 ee 3a 00 10 ef 3a 00  ...~D.....:...:.
    0009fe34  00 e0 fd 7e 78 fe 09 00-02 9f 18 77 00 e0 fd 7e  ...~x......w...~
    7486af70  00 e0 fd 7e 00 00 00 00-b8 00 16 77 28 00 16 77  ...~.......w(..w
    7efda030  00 e0 fd 7e 00 00 00 00-00 00 00 00 00 00 00 00  ...~............
    7efdd030  00 e0 fd 7e 00 00 00 00-00 00 00 00 00 00 00 00  ...~............
    

    From the above output, we see that we can quickly reject all but the last two entries because the offset within the page is not the magic value 0x30. (This is a 32-bit process.) Hooray, two debugger commands reduce the search space to just two pages!

    At this point, you can continue with the debugging technique from last time, looking at each candidate TEB to see if there's a valid stack in there.

Page 1 of 3 (25 items) 123