April, 2007

  • The Old New Thing

    Changes to power management in Windows Vista


    As I noted some time ago, it's hard to get programmers excited about power management. What's worse, programs that do take the effort to care about power management often do it rudely, hijacking your computer and preventing you from going into standby or hibernation, instead preferring to drain your battery until the computer just dies from lack of power.

    The Power Management folks decided that they've had enough with these selfish programs and redesigned the way power management works. In addition to exposing finer control over various aspects of power management to the user, they also decided to "take the ball and go home" when it comes to programs rejecting suspend or hibernation requests. When the user asks for the computer to go into a low power state, programs will get notified of the state change but are not allowed to veto it. Programs get two seconds to clean up, and then that's it. The laptop is going into standby, ready or not.

    If you ordered a copy of the PDC DVDs, you can go back and watch session FUN319 to learn more. (Here are some follow-up remarks to that session.) I'm not the expert in this area; I'm just repeating what I've heard. If you have questions about the future of power management, you probably should ask the power management folks over on the Windows Mobile PC Team Blog.

  • The Old New Thing

    Email tip: People didn't answer your first email for a reason


    It is said that insanity is doing the same thing over and over again and expecting different results. Consider:

    From: X
    To: Group Y

    Question blah blah blah.

    A day or two later:

    From: X
    To: Group Y

    Resending due to no response.

    ------- Original Message -------
    From: X
    To: Group Y

    Question blah blah blah.

    You didn't get a response because your previous message was poorly-phrased, or it was sent to the wrong group, or nobody recognized the question as something they could help with, or any of a number of possible reasons. Re-sending it is not going to fix that. If your question was poorly-phrased, it's still poorly-phrased. The only difference is that now, it's been poorly-phrased twice.

    If you're compelled to re-send your question, add information to make it more likely that somebody will respond to the second one. If you merely repeat the question, you're just going to get the same response. (I.e., none.)

  • The Old New Thing

    What is the default version of the shell common controls?


    It depends on what you mean by default.

    As we saw earlier, the convention for Windows header files is that if you don't specify a particular version, then you get the most recent version. The shell common controls header file follows this convention, so if you include the Windows XP version of commctrl.h, you get functions, messages, and structures designed for use with version 6 of the common controls. (And functions, messages, and structures may not work with version 5 of the shell common controls due to changes in structure sizes, for example.) So from the Windows XP Platform SDK header file's point of view, the default version of the shell common controls is version 6.

    On the other hand, there's the question of what version of the shell common controls you actually get at run time. Prior to Windows XP, the answer was simple: You got the most recent version installed on the machine.

    With Windows XP, however, the rules changed. The visuals team wanted to do something more ambitious with the common controls, but the compatibility constraints also created significant risk. The solution was to use side-by-side assemblies.

    For compatibility, if a program didn't specify what version of the shell common controls it wanted, it got version 5.82, which was carefully designed for extremely high compatibility with the previous version, 5.81, which came with Windows 2000 and Windows Me. Now, version 5.82 is not completely identical to 5.81, because it also needs to interoperate with version 6. More on this later.

    If a program wanted to use version 6 of the common controls, it had to say so explicitly in a manifest. (What we on the shell team informally call a "v6 manifest".) That way, only programs that asked for the new behavior got it. The theory being that if you asked for the new behavior, you presumably tested your program against version 6 of the common controls to verify that it behaves as you expected. This freed up the visuals team to make more substantial changes to the common controls without having to worry about some old program that relied on some strange undocumented behavior of the common controls. That old program would get version 5.82, which was designed for high compatibility.

    Now, on that interoperability thing. There are places where the common controls library creates an object which you can then use with other common controls. For example, you can create an image list with ImageList_Create and then use that image list in a list view or tree view. Care had to be taken so that an image list created by version 5 of the common controls (a "v5 image list") could be used by a list view created by version 6 (a "v6 list view"), or conversely that a v6 image list could be used in a v5 list view. This sort of cross-version image list usage is actually quite common: Any application that calls Shell_GetImageLists (or its old-fashioned equivalent, SHGetFileInfo with the SHGFI_SYSICONINDEX flag) will get a v6 image list. If that application uses version 5 of the common controls (because it doesn't have a v6 manifest), then it will find itself using a v6 image list inside a v5 list view. Since each DLL has its own manifest, you can quickly find yourself in a case where there is a hodgepodge of v5 and v6 components all inside a single process, and they all have to work with each other.

    Another example of this cross-version interoperability is the HPROPSHEETPAGE. Property sheet pages created with CreatePropSheetPage from one version of the shell common controls had to work with the PropertySheet function of the other version. This happens a lot with shell property sheet extensions. The shell namespace will ask the shell extensions to provide their custom property sheets, and all the ones written for Windows 2000 will hand back a v5 HPROPSHEETPAGE. But Explorer is going to display that property sheet with the v6 PropertySheet function. That v5 property sheet page had better work even when hosted inside a v6 property sheet.

    Okay, but back to the original problem. If you don't specify what version of the header file you want, then you get the latest version (version 6 if you got the header file from the Windows XP Platform SDK). On the other hand, if you don't specify what version of the DLL you want, you get version 5.82, the compatible version of the DLL. Yes, this is a mismatch. Be on the lookout. This is what happens when a header file convention is at odds with a compatibility decision.

  • The Old New Thing

    Oh no, I have an obstructed view of Joshua Roman!


    This past weekend, a group of us attended a subscription concert performance of Beethoven's Missa Solemnis at Benaroya Hall. We collectively hold a block of seats, and it's a mix of regulars and rotating guests. Our seats are close to the stage, made even closer by the hall reconfiguration to accommodate the choir and soloists; we were effectively in the first row. (And if you were wondering what those covered holes in the floor are up near the stage, they're where the supports go for the stage extension.)

    As we filed into our seats, one of our guests for this particular concert exclaimed in mock consternation, "Oh no, I have an obstructed view of Joshua Roman!" I switched seats, giving our guest a slightly better potential view of the young cellist. In exchange, I got a much better view of Elisa Barston, the new principal second who probably would have gotten most of the ooh-aah attention if it weren't for the even younger new cellist. (Normally, I only get to see the left-hand side of her body, since the Seattle Symphony splits the violins left and right, more in keeping with 19th-century practice. It was somewhat strange seeing her from the other side when she led a string quartet and therefore sat on the left-hand side.)

    Ultimately, the seat swap didn't help much with the Joshua Roman viewing opportunities, because the conductor and soloists occupied most of the field of view. Afterwards, we jokingly discussed various ways we could express our Joshua Roman groupie-dom, ranging from giant "We Love You Joshua Roman" placards to floppy-haired wigs. At least I hope they were joking.

  • The Old New Thing

    What's the difference between WINVER, _WIN32_WINNT, _WIN32_WINDOWS, and _WIN32_IE?


    Okay, so there are all these different ways you can specify what version of the Windows header files you want.†

    #define WINVER         0x0400
    #define _WIN32_WINNT   0x0400
    #define _WIN32_WINDOWS 0x0400
    #define _WIN32_IE      0x0400

    Let's take them in order.

    The WINVER symbol is the earliest one. That's the symbol that 16-bit Windows used to control the versioning of its header files, and its use carried forward into the 32-bit header files, presumably from the people who did the initial conversion of the header files to 32-bit and who grew up with the WINVER symbol. This symbol is still used a lot in the header files that can trace their origins to 16-bit Windows, such as winuser.h, wingdi.h, and mmsystem.h.

    The _WIN32_WINNT symbol came next. I'm not sure where it came from, but from its name it probably was invented by the Windows NT team in order to allow them to block off sections of the header file that are available only in the Windows NT implementation of Win32. Don't forget that in the early days, there was also Win32s, a subset of Win32 that could run on 16-bit Windows 3.1. The single WINVER symbol wasn't enough to specify exactly what you wanted to be compatible with. For example, a function available only in Windows NT 3.1 would be guarded with #if _WIN32_WINNT >= 0x030A so that programs that wanted to run on Win32s could set _WIN32_WINNT to zero and keep that function off-limits.

    Similarly, both Windows 95 and Windows NT 4 identified themselves as Windows major version 4, so the WINVER symbol was insufficient to distinguish them. Functions that existed in Windows NT 4 but not in Window 95 were therefore guarded with _WIN32_WINNT.

    On the other hand, there were also functions that were first introduced in Windows 95 and did not exist in the original version of Windows NT 4. The _WIN32_WINDOWS symbol let you specify that you wanted access to stuff that was new for Windows 95 and which would also be ported to Windows NT 4 and future versions of Windows NT.

    The next symbol in this progression is _WIN32_IE, which lets you specify what version of Internet Explorer you require to be installed on the system. This was more important back in the days when Internet Explorer included updates to selected operating system components. For example, Internet Explorer 4 came not only with an updated comctl32.dll but also a new shell32.dll that gave you Active Desktop. (Wow, remember Active Desktop? That was when everybody thought that HTML was going to take over the world and people would write entire applications in HTML. People are still trying.)

    And history repeated itself: We saw it before when we tried to puzzle out why some functions return NULL while others return INVALID_HANDLE_VALUE. Each time somebody added a new feature to Windows and had to add an #ifdef guard, it was pretty much a toss-up whether they would use WINVER, _WIN32_WINDOWS, or _WIN32_WINNT. Once Internet Explorer stopped including updates to shell components, _WIN32_IE fell into the "toss-up" bucket as well.

    In an attempt to make some sense out of this disaster, the SDK and DDK teams came up with a new plan for Windows Vista header files: sdkddkver.h. There's now just one symbol you define to specify your minimum target operating system: NTDDI_VERSION. Once you set that, all the other symbols are set automatically to the appropriate values for your target operating system. (And no, I don't know what the letters NTDDI stand for, though there is one obvious candidate.) With any luck, everybody wll standardize on NTDDI_VERSION and this article will become one of those "quaint historical novelties" like all the ones about 16-bit Windows. Just "a little story about what people had to do back in the crazy days of the early 21st century. Boy am I glad we don't have to worry about that any more!"


    I'd appreciate it if people would extend me the courtesy of not stepping on my announced topic. (I wonder if these are the same people who go to a comedy show and shout out the punch lines before the performer gets to say them.) I did say that I would pick up the topic today, after all. If you really want to steal my topic, at least be polite enough to post your essay on your own blog.

    Nitpicker's corner

    †This list is not intended to be comprehensive.

  • The Old New Thing

    Enjoy our Bluetooth devices with a glass of beer or wine (Bluetooth device optional)


    Taiwanese Bluetooth technology company Bluetake has an odd picture on their front page. It's three women drinking alcohol, with plenty more bottles in front of them. Not a single Bluetooth device in sight. Maybe Bluetooth just makes alcohol taste better.

    (Yes, I know it's a stock photo, but what's with the alcohol?)

  • The Old New Thing

    What's the row of numbers on the copyright page of books?


    On the copyright page of a book (typically the back of the title page), you'll find a row of numbers. Something like this:

    Printed in the United States of America
    10   9   8   7   6   5   4   3   2   1

    As Dave Taylor explains, the smallest number tells you which printing of the book you have. For example, if you see "10 9 8 7 6 5 4" then you have a fourth printing. Dave doesn't explain why printers use this convention, however.

    I forget where I learned this; I think I read it in one of Don Knuth's books. It has to do with how books are historically made. Each page of a book is converted to a metal plate which is used to make impressions. If another printing run is necessary, you load the plates back onto the printing machine and off you go. But how do you indicate that this is a second printing? It would be expensive to burn a brand new plate just to change the word "first" to "second" on the copyright page. Instead, you pre-load all the printing numbers onto your master, and each time you start a new printing run, you scratch off the lowest number.

    Even though a lot of book printing nowadays is done with computers rather than metal plates, the old method of indicating a printing is retained out of tradition.

  • The Old New Thing

    What is the default version of a header file?


    The general rule with Windows header files is that if you don't specify which version of the header file you want, you get the latest version. For example, if you have the Windows XP Platform SDK header files and you #include <windows.h>, you're going to get the Windows XP function prototypes, the Windows XP structures, the the Windows XP flags, all that stuff. And unless you're careful, the program you get as a result will most likely run only on Windows XP.

    If you call a function that is new for Windows XP, then your program won't run on earlier versions of Windows because the import can't be resolved.†

    If you use a structure that changed for Windows XP, then your program won't run on earlier versions of Windows because the structure size will be wrong.

    Even if the structure size didn't change, using a flag that was introduced in Windows XP will create difficulties for your program when run on earlier versions of Windows because those earlier versions don't support the flag you're passing. Depending on how the function in question was written, it may ignore the "flag from the future" or it may reject it as invalid.

    If you want your program to run on older versions of Windows, you have a few options. First, you can explicitly "downgrade" your header file by defining an appropriate symbol or symbols before including the windows.h header file.

    #define WINVER         0x0400
    #define _WIN32_WINNT   0x0400
    #define _WIN32_WINDOWS 0x0400
    #define _WIN32_IE      0x0400
    #include <windows.h>
    #include <commctrl.h>
    #include <shlobj.h>

    Oh yuck, now we have the messy world of "So what's the difference between _WIN32_WINNT, _WIN32_WINDOWS, _WIN32_IE, and WINVER?" We'll pick up this topic next time, but you're not going to like the answer.

    Nitpicker's corner

    †That statement is from the operating system's‡ point of view. You can of course use techniques like Visual Studio linker's delay-load feature to avoid creating an import dependency, but that's outside the operating system.‡

    ‡s/operating system/Windows operating system/

  • The Old New Thing

    Why doesn't the taskbar return to its original size when I return my settings to their original values?


    Commenter Gareth asked why, when the system metrics change and the taskbar changes size to match, the taskbar doesn't return to its original size when the metrics return to their previous values.

    Because the taskbar doesn't remember the path of changes that led to its current state. It just knows its current state.

    Let's say the taskbar is 30 pixels tall, consisting of one row of buttons. Now you change the metrics so that a button is now 60 pixels tall. The taskbar says, "Hm, I'm 30 pixels tall, but that's not tall enough to hold even one row of buttons. I'd better increase in height to 60 pixels so that the user doesn't see a row of half-buttons (ugh)."

    Okay, the taskbar is now 60 pixels tall.

    Now you change your metrics so that a button is 30 pixels tall again. The taskbar says, "Hm, I'm 60 pixels tall. That's tall enough for two rows of 30-pixel buttons. Woo-hoo!"

    Result: When you change a setting and then change it back, things do not return to the way they were.

    This shouldn't be surprising. Many parts of the world behave this way. If you take a broom and sweep the dirt into the corner of the room, the dirt doesn't "remember" that "I used to be over there in the middle of the room. As soon as that broom is out of the way, I'll go back to the way I was." No, the dirt says, "Here I am in the corner of the room, la di dah."†

    Nitpicker's corner

    †Dirt can't talk.

  • The Old New Thing

    When very young children try too hard to act nonchalant


    Apropos of nothing (but perhaps filed as an addendum to the "stories from school" category), I was reminded of a story from the aftermath of the Nisqually Earthquake that struck Seattle in 2001. Mind you, this story is fourth-hand by now, but it's still cute.

    A young student, whom I will call "Billy", returned from school the day of the earthquake (which struck in mid-morning).

    Billy: "Hi, Mom. I'm home."

    Mom: "Hi, Billy. Anything interesting happen at school today?"

    Billy: (trying to sound nonchalant) "Nothing much."

    Mom: "What about the earthquake?"

    Billy: (surprised) "Who told you about the earthquake?!"

    Update: Corrected Mom's question. And I deleted all the comments arguing about religion. If you want to debate child rearing, do it somewhere else.

Page 3 of 4 (38 items) 1234