The Old New Thing
Practical development throughout the evolution of Windows.
Latest posts
Paul Cézanne and Camille Saint-Saëns may have similar-sounding last names, but they are not the same person
Next week, the Seattle Symphony Orchestra performs the Saint-Saëns Organ Symphony, but the people responsible for the symphony's radio advertisements don't realize that. As the strains of the symphony resound in the background, the announcer proudly announces that tickets are still available for "Cézanne's Organ Symphony." The names Cézanne and Saint-Saëns may sound similar, but I can assure you that they are not the same person. Here's a handy chart: This is not the first time the Seattle Symphony's radio announcer has made this substitution. I don't know whether somebody is giving h...
How do I monitor, or even control, the lifetime of an Explorer window?
A customer wanted help with monitoring the lifetime of an Explorer window. We want to launch a copy of Explorer to open a specific folder, then wait until the user closes the folder before continuing. We tried launching a copy of Explorer with the folder on the command line, then doing a on the process handle, but the wait sometimes completes immediately without waiting. How do we wait until the user closes the Explorer window? This is another case of solving a problem halfway and then having trouble with the other half. The reason that returns immediately is that Explorer is a single-instance program (w...
How can I generate a consistent but unique value that can coexist with GUIDs?
A customer needed to generate a GUID for each instance of a hardware device they encounter: The serial number for each device is 20 bits long (four and a half bytes). We need to generate a GUID based on each device, subject to the constraints that when a device is reinserted, we generate the same GUID for it, that no two devices generate the same GUID, and that the GUIDs we generate not collide with GUIDs generated by other means. One of our engineers suggested just running and substituting the serial number for the final nine hex digits. Is this a viable technique? This is similar to the trap of thinking tha...
Function requirements are cumulative: If you fail to meet any of them, then all bets are off
A customer was having problems with the function: We are looking for a clarification of the behavior of . We have a thread that waits on two handles (call them and ) with , . Under certain conditions, we signal and close from another thread while the wait is in progress. This results in being returned from the wait call. MSDN is not clear on what the expected behavior is here. On the one hand, it says This description implies that the wait should never fail, because the function should have noticed that is signaled before it got around to noticing that was invalid. On the other hand, the documenta...
Why is there the message '!Do not use this registry key' in the registry?
Under , there is a message to registry snoopers: The first value is called "!Do not use this registry key" and the associated data is the message "Use the SHGetFolderPath or SHGetKnownFolderPath function instead." I added that message. The long and sad story of the Shell Folders key explains that the registry key exists only to retain backward compatibility with four programs written in 1994. There's also a TechNet version of the article which is just as sad but not as long. One customer saw this message and complained, "That registry key and that TechNet article explain ho...
How does the C runtime know whether to use the static-linking or dynamic-linking version of the header file?
In response to a description of what happens when you get wrong, nksingh asks, "This seems like a problem for the CRT. As far as I know, VC gives you the option of statically or dynamically linking the CRT. But it seems like the headers will have to make a choice to support one thing better than the other. Conditional compilation would work, but then people would have to remember to include a #define somewhere. Is this dllimport vs. static linking thing something the compiler could figure out on its own if you're doing Link-time codegen?" Let's start from the beginning. Yes, this would be a problem for the...
You can extend the PROPSHEETPAGE structure with your own bonus data
... for when regular strength lParam just isn't enough. A little-known and even less-used feature of the shell property sheet is that you can hang custom data off the end of the structure, and the shell will carry it around for you. Mind you, the shell carries it around by means of and destroys it by just freeing the underlying memory, so whatever you stick on the end needs to be plain old data. (Though you do get an opportunity to "construct" and "destruct" if you register a callback, during which you are permitted to modify your bonus data and the field of the .) Here's a program that illustrates this...
What does the "l" in lstrcmp stand for?
If you ask Michael Kaplan, he'd probably say that it stands for lame. In his article, Michael presents a nice chart of the various L-functions and their sort-of counterparts. There are other L-functions not on his list, not because he missed them, but because they don't have anything to do with characters or encodings. On the other hand, those other functions help shed light on the history of the L-functions. Those other functions are lopen, lcreat, lread, lwrite, lclose, and llseek. There are all L-version sort-of counterparts to open, creat, and read, write, close, and lseek. Note that we've already uncovere...
What’s up with the mysterious inc bp in function prologues of 16-bit code?
A little while ago, we learned about the EBP chain. The EBP chain in 32-bit code is pretty straightforward because there is only one type of function call. But in 16-bit code there are two types of function calls, the near call and the far call. A near call pushes a 16-bit return address on the stack before branching to the function entry point, which must reside in the same code segment as the caller. The function then uses a instruction (a near return) when it wants to return to the caller, indicating that the CPU should resume execution at the specified address within the same code segment. By comparison, ...