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

    The Notepad file encoding problem, redux


    About every ten months, somebody new discovers the Notepad file encoding problem. Let's see what else there is to say about it.

    First of all, can we change Notepad's detection algorithm? The problem is that there are a lot of different text files out there. Let's look just at the ones that Notepad supports.

    • 8-bit ANSI (of which 7-bit ASCII is a subset). These have no BOM; they just dive right in with bytes of text. They are also probably the most common type of text file.
    • UTF-8. These usually begin with a BOM but not always.
    • Unicode big-endian (UTF-16BE). These usually begin with a BOM but not always.
    • Unicode little-endian (UTF-16LE). These usually begin with a BOM but not always.

    If a BOM is found, then life is easy, since the BOM tells you what encoding the file uses. The problem is when there is no BOM. Now you have to guess, and when you guess, you can guess wrong. For example, consider this file:

    D0 AE

    Depending on which encoding you assume, you get very different results.

    • If you assume 8-bit ANSI (with code page 1252), then the file consists of the two characters U+00D0 U+00AE, or "Ю". Sure this looks strange, but maybe it's part of the word VATNIЮ which might be the name of an Icelandic hotel.
    • If you assume UTF-8, then the file consists of the single Cyrillic character U+042E, or "Ю".
    • If you assume Unicode big-endian, then the file consists of the Korean Hangul syllable U+D0AE, or "킮".
    • If you assume Unicode little-endian, then the file consists of the Korean Hangul syllable U+AED0, or "껐".

    Okay, so this file can be interpreted in four different ways. Are you going to use the "try to guess" algorithm from IsTextUnicode? (Michael Kaplan has some thoughts on this subject.) If so, then you are right where Notepad is today. Notice that all four interpretations are linguistically plausible.

    Some people might say that the rule should be "All files without a BOM are 8-bit ANSI." In that case, you're going to misinterpret all the files that use UTF-8 or UTF-16 and don't have a BOM. Note that the Unicode standard even advises against using a BOM for UTF-8, so you're already throwing out everybody who follows the recommendation.

    Okay, given that the Unicode folks recommend against using a BOM for UTF-8, maybe your rule is "All files without a BOM are UTF-8." Well, that messes up all 8-bit ANSI files that use characters above 127.

    Maybe you're willing to accept that ambiguity, and use the rule, "If the file looks like valid UTF-8, then use UTF-8; otherwise use 8-bit ANSI, but under no circumstances should you treat the file as UTF-16LE or UTF-16BE." In other words, "never auto-detect UTF-16". First, you still have ambiguous cases, like the file above, which could be either 8-bit ANSI or UTF-8. And second, you are going to be flat-out wrong when you run into a Unicode file that lacks a BOM, since you're going to misinterpret it as either UTF-8 or (more likely) 8-bit ANSI. You might decide that programs that generate UTF-16 files without a BOM are broken, but that doesn't mean that they don't exist. For example,

    cmd /u /c dir >results.txt

    This generates a UTF-16LE file without a BOM. If you poke around your Windows directory, you'll probably find other Unicode files without a BOM. (For example, I found COM+.log.) These files still "worked" under the old IsTextUnicode algorithm, but now they are unreadable. Maybe you consider that an acceptable loss.

    The point is that no matter how you decide to resolve the ambiguity, somebody will win and somebody else will lose. And then people can start experimenting with the "losers" to find one that makes your algorithm look stupid for choosing "incorrectly".

  • 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

    Code is read much more often than it is written, so plan accordingly


    Design for readability.

    Even if you don't intend anybody else to read your code, there's still a very good chance that somebody will have to stare at your code and figure out what it does: That person is probably going to be you, twelve months from now.

    When I advised against the use of BOOL function parameters, one commenter pointed out that Intellisense shows you what the parameters are. Sure, that's a great help when you're writing the code, but you write the code only once. You read it a lot.

    An anonymous commenter pointed out that hovering over the offending function in the IDE shows the function declaration. While that may be true, it's still not a great solution. First, it means that you have to read code with your hand on the mouse. Second, it means that you can't skim code because you're going to hit a CreateEvent and then have to wait a little while for the tooltip to appear and then read and parse the tooltip and match the parameters up to what you have on the screen. This throws off your rhythm.

    Imagine if you had to read code that had gone through a ROT-13 filter. Sure, the IDE might help you by decoding the text under the cursor if you hover over it, but even instant help isn't fast enough.

    And finally, another commenter pointed out that this doesn't help you if you're reading code anywhere outside your IDE. It might be in a magazine, in a printout, in a bug report, on an overhead projector, on a web page, in a Usenet message, or in an email message. Good luck getting Intellisense to help you out there.

  • The Old New Thing

    Why do operating system files still adhere to the old 8.3 naming convention?


    Commenter Brian Reiter asks a duplicate of a question that was already submitted to the Suggestion Box: Darren asks why operating system† files still (for the most part) adhere to the old 8.3 naming convention.

    There are a few reasons I can think of. I'm not saying that these are the reasons; I'm just brainstorming.

    First, of course, the name of a DLL cannot change once it has been chosen, because that would break programs which linked to that DLL by its old name. Windows 95 did not require the system volume and user profile volume to support long file names, although that was certainly the case by default. Companies which used roaming profiles or redirected folders may have had a heavy investment in servers which did not support long file names. Therefore, all system files on Windows 95 had to conform to the 8.3 naming convention.

    I believe that Windows NT permitted the system volume to be a short-file-names-only FAT partition as late as Windows 2000. Therefore, any DLL that existed in the Windows 2000 era had to conform to the 8.3 naming convention.

    Starting in Windows XP, long file names became mandatory, and a few system files such as shellstyle.dll waded tentatively into the long file name world. (The .NET Framework folks jumped in with both feet with their managed DLLs, but notice that their unmanaged DLLs like mscoree.dll still conform to 8.3.) But the waters in this world can be treacherous for operating system components.

    First of all, you have to worry about the automatically-generated short name. Suppose the operating system setup program is copying the shellstyle.dll file, but there is already a file called shellstuff.dll. The short name for shellstuff.dll will probably be SHELLS~1.DLL, and therefore the short name for shellstyle.dll will likely be SHELLS~2.DLL. Now, this may not be a big deal, except that some programs like to hard-code a file's short name. (There are a lot of programs that assume that the Program Files directory is C:\PROGRA~1, for example.)

    Furthermore, you can create confusion if the same DLL is loaded by both its short and long names, since the loader treats them as distinct:

    #include <stdio.h>
    #include <windows.h>
    int __cdecl main(int argc, char **argv)
     printf("%p\n", LoadLibrary("SHELLS~1.DLL"));
     printf("%p\n", LoadLibrary("SHELLSTYLE.DLL"));
     return 0;

    If you run this program, you will get something like this:


    Even though the two paths refer to the same DLL, the loader treats them as different, and you end up with two copies of the same DLL loaded into memory. Now things get confusing, since you now have two sets of global variables, and if two components both use SHELLSTYLE.DLL but one used the short name and the other the long name, things get exciting when those two components try to talk about what they think is the same thing.

    It's like that time when I was a child and our family took a trip to Disneyland. Our parents put my brother and me on the gondola ride, and upon arrival at the other end, we were to go to the Autopia ride which was right next door. The plan was that our parents would meet us at the exit to Autopia. When my brother and I exited Autopia, we expected our parents to be waiting there for us, but they were nowhere to be seen. Sticking to the plan, we waited patiently for our parents to arrive. We sat there for what seemed like two hours (but which was probably much less), until eventually we decided that my brother would stay put and I would go looking around, at which point it didn't take long for me to find my father, who was walking around looking for us.

    What went wrong? Well, the problem was that the map of Disneyland showed Autopia, but what the map didn't say was that there were two Autopia rides (and therefore two Autopia exits) right next to each other. My brother and I were waiting by one exit, and our parents were waiting by the other. Each of us thought the other party was simply late.

    Similarly, if a DLL goes by multiple names, you can end up with two copies of it loaded into the process, with different components talking about different copies, unaware that they are talking about different things.

    And one final reason I can think of for sticking with 8.3 file names for operating system DLLs is simply, "Well, that's the way we've always done it. All the problems with 8.3 names are well-understood and under control. If we switched to long file names, we'd end up discovering a whole new set of problems. Why mess with something that works if it isn't broken?"

    Better the devil you know.

    Exercise: Why is it okay for the .NET Framework to use long file names for their managed DLLs?

    Nitpicker's Corner

    †s/operating system/Windows operating system/. Apparently nothing is obvious from context any more.

  • The Old New Thing

    His lips are moving: In order to serve you better


    Q: How do you know when a lawyer is lying?

    A: His lips are moving.

    This is of course a completely unfair and discriminatory joke.

    Many lawyers are women.

    Anyway, today I'm going to rant about the phrase "In order to serve you better." Whenever you hear this phrase, you are pretty much guaranteed that whatever follows will in fact not serve you better at all.

    When I bought tickets to see Real Madrid play against some Americans, the online ticket service gave me multiple options for receiving my tickets. I could have them mailed to me, or I could have the tickets sent to me electronically. And for some reason, there was a "convenience fee" for receiving electronic tickets, even though sending me electronic tickets costs them approximately one gazillionth of a penny†, whereas paper tickets cost them paper, handling, and postage. They are inviting me to pay more so they can save money. To maximize their revenues, they also put "(Recommended)" next to the electronic ticketing option and selected it by default.

    I can't believe they get away with this.

    It used to be that when you looked up somebody's office number in the address book at Microsoft, you got something like "9S/1044", which means "Room 1044 in the South wing of Building 9." These buildings are big, and knowing which half to start in can save you a lot of walking, especially in some buildings where the two wings are not always connected! For example, in Building 26 the north and south wings are connected only on the first two floors. If you want to get from the north wing of the third floor to the south wing, you have to go down a flight of stairs, then across, then up.

    But several years ago, they removed the wing designation from the address book. That same office is now listed as simply "9/1044". When I asked why they removed the wing designations, I was told, "We did this in order to serve you better. Many people were confused by it."

    I have yet to find any of those people who are being served better. Every single person I asked wanted the wing designations restored, too.

    Nitpicker's corner

    †A gazillion is not an actual number.

  • The Old New Thing

    The wisdom of seventh graders: Designing an elective course


    Last month, I spent a few hours reading essays written by seventh graders (ages 12 and 13) on the following subject:

    Electives are often fun and different from our normal core classes. Imagine you have been chosen to create one new elective for our school. In a multi-paragraph essay, explain what the new elective would be like and what students would learn.

    (Students were given two hours, plus one additional hour upon request.)

    Before I present you some of the responses, I'd like to take some time to address the students on the subject of writing. I know they won't read this, but I have to tell someone.

    • Stay on prompt; in other words, make sure you address the assigned topic in its entirety. Don't get so carried away describing the class itself that you forget to explain what students would learn. Going off prompt is an automatic disqualification.
    • Stay on mode; in other words, write the type of essay requested. This example demands an expository essay, not a persuasive one. You aren't trying to convince other students to take your elective. As with going off prompt, going off mode is an automatic disqualification.
    • Do not introduce new material in your conclusion. Your conclusion is for tying your argument together; it's not a place for "oh, wait, I forgot something."
    • Take it easy with the exclamation points! It's really distracting!
    • Inside these questions there is often hidden another question, usually a Why. Here, the hidden question is "Why is it important that students learn that which this elective teaches?" Addressing the hidden question takes your essay to the next level. This tip is only for advanced writers; don't even consider addressing the hidden question until you can handle the explicit one!
    • Mind your frame of reference. Don't start with students and then switch to you. Example of error (exaggerated): "Students who complete this class can show off to your friends." I'd say that over half of the essays made mistakes like this, though none so blatant.
    • Mind your antecedents. When you use a pronoun, make sure the noun to which it refers is unambiguous. Example of error: "If teachers or anyone else hears insults, they will be thrown out of class."
    • I'm sure there are adjectives other than cool and fun. Try using them once in a while. It's cool and fun.
    • Many rules of writing can be broken, but don't break a rule until you've first mastered it. Richard Wagner can write an orchestral prelude that consists of a single chord for over four minutes, but that's because he's Richard Wagner, and he knows what he's doing.

    What electives would seventh-graders design for themselves? Here are the ones from the essays that I read (plus some that other readers shared with me, marked with asterisks), broken down roughly into categories, and illustrated with selected sentences from those essays or closely-related essays.

    • Sports and exercise
      • Skateboarding.
      • Fencing.
      • Cricket.
      • Soccer. The student explains that the problem with standard gym classes is that you don't get to spend much time focusing on any one sport. "This class will have more variety than any other class."
      • *Basketball. "Shooting is a exceedingly important part of basketball because if you didn't score you would have no points. Shooting well helps your team's chances of winning the game."
      • *Swimming. This essay had an excellent introductory paragraph that ended with "We need more electives. We need variety. We need swimming." It's a joy to read from students who have such control of writing that they can explore rhetorical devices.
      • Paintballing [sic]. "There is not another elective where the goal is to shoot another student to win." (How about photography?)
      • A single sport (chosen by the student).
      • Exercise for students who are overweight or have physical disabilities.
      • Weight training. It "strenthens strength."
      • *Skydiving.
    • Arts
      • Glass blowing.
      • Metal shop. (The school already offers woodworking.)
      • Drawing. "There is, quite literally, a fine line between a sketch of a drawing and the actual drawing."
      • Cartooning.
      • Architecture.
      • Creative writing (2×).
      • *Rock music performance. "Would you rather be shreding (on the guitar) or playing Betovon."
    • Sciences
      • Electronics.
      • Material science.
      • *Writing video games. "Each kid would pay a fee of $20 to pay some real progromers to teach the class for a year."
    • Personal development
      • Make-up and beauty.
      • Style and fashion. Specifically, shopping for clothes.
      • Self-image improvement. Specifically, by improving one's hairstyle ("Braids, twists, and buns, OH MY!"), make-up, and fashion sense. "From color choices to what fashion style best suits them, it can get very confussing."
      • Information. A combination of writing and public speaking. The student's recommendations for presentations? The second slide should contain ten bullet points. "The third slide would be a five paragraph essay about the topic."
    • Languages and cultures
      • Foreign travel. "The students might have to take quizzes." The class concludes with trips to seven countries, each lasting one week. "It would be worth it to say, 'I have been to all seven countries just in Middle school.'" The student acknowledged that this class would be expensive. "It will cost you 1000 dollars to get your seven tickets to fly to all those countries."
      • Foreign language (unspecified). (Most schools in the United States do not introduce foreign languages until high school, typically age 14.)
      • Mandarin Chinese (2×).
    • Life skills
      • Introduction to automobile driving and safety. Students are too young to drive cars, so they will train on go-karts. "Go-karting would allow you to practice those basics so much that driving a car would be a walk in the park."
      • Wilderness survival. The final exam is a practical.
    • Careers
      • How to get a job. Focusing on the mechanics, like filling out an application.
      • Choosing a career. Students research various careers to learn more about them.
      • Veterinarian. "This elective would teach students all that they need to know to become a vet such as the basics of being a veterinarian and how to treat animals." The basics are all you need to know!
      • Doctor. Students will attend class in surgical scrubs and perform dissections and autopsies. Field trips include going to a local hospital and assisting an actual doctor. (You are responsible for your own malpractice insurance.) "In conclusion, having a class about what a doctor does is what we should have at our school because it is informative yet amusing."
    • Wildcard
      • *"I sugjest reshersh and repor class."
      • *Adobe Photoshop. This essay was a one-page advertisement for Photoshop, going into the product's features in fantastic detail.
      • Fire.
      • Inventing. Students will create an invention over the course of the term.
      • Television appreciation. "Our current electives require thought and work. ... This class is a much needed easy A+. ... This class will prepare our students for the real world. You can learn more life lessons in an episode of Spong Bob than the average person can learn in his life. ... Watching mindless television for a whole period for credit will be a great elective."
      • *Being lazy. This student cut to the chase. Not like that "television appreciation" student who tried to disguise it as something remotely educational.
      • "Social hall." This class is limited to fifteen students and consists only of students you choose to take it with. One of the school buildings will be converted to "social hall," with one classroom for doing homework, another classroom converted to a movie theater, and others available just for hanging out with your friends. Food and beverages will be provided, of course. There is no examination. "I think Social hall would be an excellent elective. Students will inhance social skills, physical skills and eating ideas."
      • "Anything you want." Students are free to roam the campus for this double-length period. "It would be the greatest elective yet to be invented. There will be no teachers, no rules, no fighting."

    Other sentences, taken completely out of context for maximum amusement.

    • *"Sure fit people are in good shape but they nee exersise too."
    • "Students would prefer it for its ingenuous content."
    • "There is only so long a 7th grader can sit in a cluttered room and write." (A comment on the assignment, perhaps?)
    • *"In this class, students will learn how to vacation."
    • *"We would be able to go to the lake three times a week, Tuesdays and Thursdays."
    • *"It would most likely shock the students that when you have a job you have to do just about everything by yourself."
    • *"Art is hard and easy but not both."

    Spelling corner: See if you can guess the word before reading the answer.

    soddering hazardist conclonstion
    gragwwhts Joner of Achievement
    tords enchurens

    Best new word: "confussing"

    Note: Hover over dotted words for explanations/answers.

  • 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

    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

    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.

Page 1 of 4 (38 items) 1234