The Old New Thing
Practical development throughout the evolution of Windows.
Latest posts
The extern “C” specifier disables C++ mangling, but that doesn’t mean it disables mangling
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 ...
How do I prevent unchecked checkboxes in my listview control from disappearing?
A customer asked, "I have a listview control in report view with the 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 ap...
GUIDs are designed to be unique, not random
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 l...
Why is the Close button in the upper right corner?
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...
What was the registry like in 16-bit Windows?
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 . All it was used for was COM objects and file associations. The registry was stored in the 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 t...
How to view the stack of threads that were terminated as part of process teardown from user mode
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 , , and .) A direct translation of the kernel-mode technique from last time would involve using the command and picking through for the memory blocks with candidate size and attributes. But there's an easier way. Now would be ...
Charles Petzold is back with another edition of Programming Windows
Back in the day (and perhaps still true today), Charles Petzold's Programming Windows was the definitive source for learning to program Windows. The book is so old that even I used it to learn Windows programming, back when everything was 16-bit and uphill both ways. The most recent edition is Programming Windows, 5th Edition, which was published way back in 1998. What has he been doing since then? My guess would have been "sitting on a beach in Hawaiʻi," but apparently he's been writing books on C# and Windows Forms and WPF and Silverlight. Hey, I could still be right: Maybe he writes the books while s...
How to view the stack of threads that were terminated as part of process teardown from the kernel debugger
As we saw some time ago, process shutdown is a multi-phase affair. After you call , all the threads are forcibly terminated. After that's done, each DLL is sent a notification. You may be debugging a problem with handling that suggests that some of those threads were not cleaned up properly. For example, you might assert that a reference count is zero, and you find during process shutdown that this assertion sometimes fires. Maybe you terminated a thread before it got a chance to release its reference? How can you test this theory if the thread is already gone? It so happens that when all the threads are te...
Sure, we do that: Context menu edition
A customer reported a problem that occurred only when they installed a particular application. If they uninstalled it, then the problem went away. After installing the application, the "Run As" context menu option stopped working. The customer didn't provide any other details, but we were able to make an educated guess as to what was going on. A common programming error in context menu extensions occurs in extensions which add only one menu item. These extensions ignore the parameters to the and simply assume that the only reason the method can be called is if the user selected their menu item. After all, if y...