July, 2008

  • The Old New Thing

    Wikipedia has created its own reactionary subculture

    • 20 Comments

    Now that Wikipedia has catapulted the wiki into the general consciousness, where there's a wiki, a spoof of a wiki can't be far behind.

  • The Old New Thing

    The evolution of menu templates: Introduction

    • 2 Comments

    As with dialog templates, menu templates have also gone through a four-stage evolutionary process. People don't often generate menu templates in code, although the LoadMenuIndirect function is there waiting for you once you get the urge. As a result, there aren't many questions from people trying to generate menu templates dynamically, but I'm going to go into the history of menu templates anyway, just out of a sense of completeness.

    If you're having problems with your dynamically-generated menu templates, you can ask the resource compiler to tell you what you're doing wrong by createing a *.rc file for it and compiling it into a scratch program. Dump the resource as bytes, and there's your answer. Same trick we used for dialog templates.

  • The Old New Thing

    Why is the LOADPARMS32 structure so messed up?

    • 26 Comments

    If you look at the LOADPARMS32 structure, you'll find a horrific mishmash. Double-null-terminated strings, a null-terminated string, some WORDs, and even a Pascal-style string. What's going on here?

    Each of those members comes from a different era in time. The oldest member is the Pascal-style command line, which dates back to CP/M. On CP/M, command lines were stored at a fixed location, namely 0080h through 00FFh, in the form of a Pascal string. The byte at 0080h specified the length of the command line, and the bytes at 0081h through 00FFh contained the command line itself.

    MS-DOS based much of its initial interface on CP/M in order to make porting to the new operating system easier, and part of what got carried over was the way command lines were passed from one program to another. The MS-DOS function to load a program took two parameters, a pointer to a null-terminated string (specifying the module to load) and a pointer to a parameter block which took the following form:

    LOADPARMS       struc
    loadp_environ   dw      ?       ; environment of new process
    loadp_cmdline   dd      ?       ; command line of new process
    loadp_fcb1      dd      ?       ; first FCB
    loadp_fcb2      dd      ?       ; second FCB
    LOADPARMS       ends
    

    To ease the transition, Windows 1.0 used the same MS-DOS interface for launching programs: You loaded up the registers and issued an int 21h instruction. All the parameters had the same meaning. Generally speaking, 16-bit Windows used the old MS-DOS interface for a lot of functionality, especially disk access. Want to write to a file? Put the file handle in the BX register, the number of bytes in the CX register, a pointer to the buffer in the DS:DX registers, function code 40h in the AH register, and issue an int 21h, just like in MS-DOS.

    Why do this? Well, it saved the Windows team from having to invent a whole boatload of functions that duplicated what MS-DOS already did, and it meant that existing MS-DOS programs didn't need to change a thing in their file I/O code. If they used a runtime library designed for MS-DOS (C or otherwise), that library would still write to files by setting registers and issuing an int 21h. If you want people to switch to your new platform, you need to make it easy, and "you don't have to change anything; it all just works" is pretty easy. (One minor change was that the first FCB was repurposed to contain the nCmdShow; the magic value of "2" in the first word of the FCB signals that it's not really an FCB.)

    As a minor convenience, the LoadModule function provided a C-callable version of the low-level int 21h, but you still had to provide the parameters in the form of the MS-DOS exec structure. It wasn't until later versions of Windows that the WinExec function was added, thereby providing a much more convenient interface to starting a new program. No longer did you have to mess with the crazy MS-DOS exec structure and its strange way of passing the command line and nCmdShow.

    The people who were designing Win32 created their own function CreateProcess to launch a new process, but for backward compatiblity, they retained the old WinExec and even older LoadModule mechanisms. The pointers in the crazy 16-bit exec block got converted to 32-bit, but the craziness of what they pointed to was retained to make porting old code easier. The int 21h interface no longer exists, of course. The craziness is just a leftover from the old MS-DOS days. The WinExec and LoadModule functions are now just stub functions that convert their parameters and call the CreateProcess function to do the real work.

  • The Old New Thing

    Double the usual number of fire alarms today

    • 14 Comments

    Firefighters hate the Fourth of July, the holiday dedicated to blowing up stuff, because when amateurs try to blow up stuff, they often blow up stuff they didn't intend to blow up. One of my friends has a particular unfortunate knack of drawing disasters to his neighborhood. One July 4th, a house in his neighborhood burnt down due to a stray firecracker landing on a wooden roof. A few years later, he moved to another neighborhood, and the next July 4th, a house in his neighborhood burnt down due to a stray firecracker landing on a wooden roof.

    The Seattle Fire Department lets you view all the incidents to which they responded, and the year I checked (the year of the second house-burning-down), the Seattle Fire Department responded to twice as many reports on the fourth as they did on the third.

  • The Old New Thing

    When anybody can look up your name in the company directory and pay a visit

    • 20 Comments

    In late 2004, I was working in my office, minding my own business. I normally keep my door open, as do most other people.

    «Knock-knock»

    I turn around. There's somebody at the door.

    "Oh, nothing," the person said. "I just wanted to look at you."

    I closed the door and drew my blinds.

    What would you have done?

    (In retrospect, I obviously should have installed a webcam and charged a membership fee.)

  • The Old New Thing

    How did the invalid floating point operand exception get raised when I disabled it?

    • 23 Comments

    Last time, we learned about the dangers of uninitialized floating point variables but left with a puzzle: Why wasn't this caught during internal testing?

    I dropped a hint when I described how SNaNs work: You have to ask the processor to raise an exception when it encounters a signaling NaN, and the program disabled that exception. Why was an exception being raised when it had been disabled?

    The clue to the cause was that the customer that was encountering the crash reported that it tended to happen after they printed a report. It turns out that the customer's printer driver was re-enabling the invalid operand exception in its DLL_PROCESS_ATTACH handler. Since the exception was enabled, the SNaN exception, which was previously masked, was now live, and it crashed the program.

    I've also seen DLLs change the floating point rounding state in their DLL_PROCESS_ATTACH handler. This behavior can be traced back to old versions of the C runtime library which reset the floating point state as part of their DLL_PROCESS_ATTACH; this behavior was corrected as long ago as 2002 (possibly even earlier; I don't know for sure). Obviously that printer driver was even older. Good luck convincing the vendor to fix a bug in a driver for a printer they most likely don't even manufacture any more. If anything, they'll probably just treat it as incentive for you to buy a new printer.

    When you load external code into your process, you implicitly trust that the code won't screw you up. This is just another example of how a DLL can inadvertently screw you up.

    Sidebar

    One might argue that the LoadLibrary function should save the floating point state before loading a library and restore it afterwards. This is an easy suggestion to make in retrospect. Writing software would be so much easier if people would just extend the courtesy of coming up with a comprehensive list of "bugs applications will have that you should protect against" before you design the platform. That way, when a new class of application bugs is found, and they say "You should've protected against this!", you can point to the list and say, "Nuh, uh, you didn't put it on the list. You had your chance."

    As a mental exercise for yourself: Come up with a list of "all the bugs that the LoadLibrary function should protect against" and how the LoadLibrary function would go about doing it.

  • The Old New Thing

    Raymond misreads newspaper head... no wait, I didn't!

    • 26 Comments

    I have a habit of misreading newspaper headlines, so I simply assumed that this was just another one: Phelps sets word record in 400 IM. (And no, I don't normally read the Rocky Mountain News. The actual headline was printed across the top of the June 30 Seattle Times Sports section, but I couldn't find the headline in the online archives, so I found another newspaper with the same headline.)

    Wow, how fast did he IM 400 words?

    Duh, I must've misread it. Obviously the headline said world record.

    No wait, it really was word record!

  • The Old New Thing

    Uninitialized floating point variables can be deadly

    • 49 Comments

    A colleague of mine related to me this story about uninitialized floating point variables. He had a function that went something like this, simplified for expository purposes. The infoType parameter specified which piece of information you're requesting, and depending on what you're asking for, one or the other of the output parameters may not contain a meaningful result.

    BOOL GetInfo(int infoType, int *intResult, double *dblResult)
    {
     int intValue;
     double dblValue;
    
     switch (infoType) {
     case NUMBER_OF_GLOBS:
      intValue = ...;
      break;
    
     case AVERAGE_GLOB_SIZE:
      dblValue = ...;
      break;
     ...
     }
     *intResult = intValue;
     *dblResult = dblValue;
     ...
    }
    

    After the product shipped, they started geting crash reports. This was in the days before Windows Error Reporting, so all they had to work from was the faulting address, which implicated the line *dblResult = dblValue.

    My colleague initially suspected that dblResult was an invalid pointer, but a search of the entire code base ruled out that possibility.

    The problem was the use of an uninitialized floating point variable. Unlike integers, not all bit patterns are valid for use as floating point values. There is a category of values known as signaling NaNs, or SNaN for short, which are special "not a number" values. If you ask the processor to, it will keep an eye out for these signaling NaNs and raise an "invalid operand" exception when one is encountered. (This, after all, is the whole reason why it's called a signaling NaN.)

    The problem was that, if you are sufficiently unlucky, the leftover values in the memory assigned to the dblValue will happen to have a bit pattern corresponding to a SNaN. And then when the processor tries to copy it to dblResult, then exception is raised.

    There's another puzzle lurking behind this one: Why wasn't this problem caught in internal testing? We'll learn about that next time.

  • The Old New Thing

    András Schiff 2006 lectures on the Beethoven piano sonatas

    • 9 Comments

    In 2006, pianist András Schiff gave a series of eight lecture-recitals covering the complete cycle of Beethoven piano sonatas. Here are all the lectures on one page. (Beware: The metadata on these mp3 files is all over the map.)

    As an incompetent student of the Beethoven sonatas, I find these lectures absolutely riveting.

    Note: Schiff assumes you are familiar with basic musical terminology, terms like exposition, subdominant, Neapolitan, enharmonic and quaver.

  • The Old New Thing

    Windows Vista changed the Alt+Tab order slightly

    • 38 Comments

    For decades, the Alt+Tab order was the same as the Z-order, but that changes in Windows Vista if you use the enhanced Alt+Tab feature known as Flip, which is on by default on most systems. There are three types of interactive task switching in Windows Vista:

    • Classic Alt+Tab: This is the same one that's been around since Windows 95. It shows a grid of icons.
    • Flip (new for Windows Vista): This shows a grid of thumbnails.
    • Flip3D (also new for Windows Vista): This shows a stack of windows in 3D.

    Classic Alt+Tab continues to show the icons in Z-order order, but the developer who wrote Flip told me that Flip changed it up a bit based on feedback from the design team. The first several icons are still shown in Z-order order, but if you have a lot of windows open, the rest of them are shown in alphabetical order to make it easier to pick the one you want from the list.

    I think it's a good sign that nobody seems to have noticed. A lot of user interface work tries to be invisible.

Page 4 of 4 (40 items) 1234