October, 2009

  • The Old New Thing

    Still working out the finer details of how this Hallowe'en thing works

    • 31 Comments

    Here's an excerpt from a conversation on the subject of Hallowe'en which I had with my niece some time ago. Let's call her "Cathy". (This is a different Cathy from last time.)

    "Cathy, what do you do on Hallowe'en?"

    "You get all dressed up and people give you candy."

    "What do you say when people come to the door?"

    "Chuck-E-Cheese!"

  • The Old New Thing

    What is the format for FirstInstallDateTime on Windows 95?

    • 19 Comments

    Public Service Announcement: Daylight Saving Time ends in most parts of the United States this weekend.

    Windows 98/98/Me recorded the date and time at which Setup was run in the registry under HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion as a binary value named FirstInstallDateTime. What is the format of this data?

    Take the binary value and treat it as a 32-bit little-endian value. The format of the value is basically DOS date/time format, except that the seconds are always 0 or 1 (usually 1), due to a programming error.

    Exercise: What error would result in the seconds always being 0 or 1 (usually 1)?

    [Update: Falcon is the first to post the correct answer.]

  • The Old New Thing

    What this batch file needs is more escape characters

    • 16 Comments

    (Employing the snowclone "What this X needs is more Y.")

    Each time you add a parsing pass to the batch processor, you have to add another layer of escaping. This is just a special case of the more general rule of thumb: any problem in quoting can be solved by adding another layer of escaping.

    (Okay, it's not actually true, nor is it a rule of thumb, but it's still something to keep in mind.)

    When you enable delayed variable expansion, you add another parsing pass to the batch processor. It used to expand % variables at the time the line is ready, but now you told it that, oh wait, just before executing the command, expand it a second time (this time looking for ! variables.)

    Which means that if you want to echo an exclamation point, you have to protect the exclamation point so the parser won't treat it as a delayed expansion.

    echo Error^^!
    

    The ^^ collapses to a ^ during the first parsing pass. On the second parsing pass, the ^! turns into a !

    Remember, the batch language was not designed; it evolved. I admire the approach taken by commenter Nick, in a tip of the hat to Douglas Adams:

    Much like the universe, if anyone ever does fully come to understand Batch then the language will instantly be replaced by an infinitely weirder and more complex version of itself. This has obviously happened at least once before ;)
  • The Old New Thing

    Warning: Not much useful content inside

    • 20 Comments

    Remember, this Web site is for entertainment purposes only. Sometimes it takes people a little while before they realize this:

    I apologize for posting the link to the "Old New Thing" blog. [...] I have read a few articles in the "Old New Thing" blog and so far I have not seen much that is useful there.
  • The Old New Thing

    Why does the Photo Gallery show all my photos with a colored tinge?

    • 31 Comments

    When you view your pictures with the Photo Gallery program which comes with Windows Vista, and which is also available for download from live.com, you might see a colored tinge. Where is the tinge coming from, and how do you get rid of it?

    Ironically, what you're actually seeing is the absence of a tinge, but you got so used to seeing the tinge, your eyes established the tinge as the new baseline.

    Not all display devices show exactly the same color when you ask them to display a particular RGB. The Windows Color System takes into account the color characteristics of output devices so that these variations can be taken into account when rendering to those devices. (Not that you could have figured this out from reading the official description, which just rambles for two paragraphs of marketing nonsense without actually saying what it does.) The goal is to make the color you see on the screen match the color that comes out on the printer, and have both match the color the person who created the image intended you to see.

    If you don't want Windows to perform this color correction, open your Start menu and run the Color Management tool by typing its name into the Search box, or by hunting for it inside your Control Panel. Once you manage to launch it (by whatever means), go to your display device, check Use my settings for this device and then remove the color profile.

    That was the tip. Now come da history.

    The feature now known as the Windows Color System was introduced in Windows 95 under the name Independent Color Management. This explains why the color profile files have the *.icm extension.

    But Independent Color Management was not the original name for the feature. The original name was Device-Independent Color, but the name was changed because the original name resulted in an unfortunate acronym that was lost on nobody. When Device-Independent Color was being written, one of the programmers in the user interface group reviewed the work in progress and sent an update to the rest of the team. She wrote, "I just looked at David's DIC, and (since I know you're all going to ask)... it looks good."

  • The Old New Thing

    If aluminum pull tab redemption is a rumor, what happens to all the tabs?

    • 25 Comments

    Everybody should know by now that it is not true that pull tabs from aluminum cans can be redeemed for time on a dialysis machine. Of course, not everybody actually knows this, and then the next question is, well, what happens to all those pull tabs collected by misinformed people?

    The Snopes article explains that it depends on where you turn in the tabs. They might get recycled at the going scrap rate and the proceeds donated to the National Kidney Foundation or the Ronald McDonald House. But I was most fascinated by this resourceful researcher who played the game of "follow the tabs" from a State Police office to a high school to a hospital to the Shriners to a library to a community college, where the trail finally runs cold.

    I related this story to a friend of mine, who did a double-take. "Wait a second. That guy where the trail runs cold? I know that guy. I used to work for him!"

    That the trail runs cold was hardly surprising to my friend. Apparently, my friend's former boss was the sort of person who would never admit that he made a mistake, no matter how obvious the error. My friend speculated that when his boss discovered that nobody would take the aluminum pull tabs, he certainly wasn't going to admit, "Oops, sorry everybody." In order to keep up appearances, he had to keep collecting them, even though he had nowhere to dispose of them. And of course, all the independent pull-tab collectors who couldn't find anybody to give them to gradually learned about this guy who will take them, which meant that more and more of them kept coming in. My friend figured, "He probably has an enormous pile of aluminum pull tabs just sitting in his garage."

  • The Old New Thing

    Freudian typo: The accidental emoticon

    • 5 Comments

    Some time ago, I ran across the following Freudian typo in a mail thread discussing plans for the project after Milestone 3, commonly abbreviated M3.

    I'd like to talk with you about your plans for this area after <3.

    On the US-English keyboard layout, the M and comma keys are adjacent, and a shifted comma is a less-than sign. A simple off-by-one-key typo resulted in M3 turning into an emoticon.

  • The Old New Thing

    Why won't my computer go to sleep? Where is the energy going?

    • 20 Comments

    The powercfg utility has been around for a while, but in Windows 7, it gained a little bit more awesome.

    powercfg /energy will analyze your computer's power consumption and report on things like devices that prevent the computer from sleeping, devices which won't suspend, and processes which are increasing your battery drain.

    Another neat flag is powercfg /requests which will report on why your computer can't go to sleep, for example, because it has open files on the network, or because the clown will eat it.

  • The Old New Thing

    Yes, there's a new desktop window manager, but no, I don't know any more about it than you do

    • 7 Comments

    Sean W. requests, via the suggestion box, "an in-depth discussion of the use of the shell's new Desktop Window Manager (Dwm*) functions in Win32."

    The desktop window manager is not actually part of the shell. It operates at the window manager level. (Notice that DWM is active even when Explorer isn't running.) You probably should have posted your suggestion to Greg Schechter's request for DWM topics which was not too old at the time you posted your topic suggestion. But then again, "Best practices for applications under the DWM" was on his list of future topics, so it looks like what you wanted was already on his to-do list. I don't know whether he followed up on his own to-do list, though. If not, you can always consult the Performance Considerations and Best Practices (for using DWM) topic in MSDN.

  • The Old New Thing

    If you have to cast, you can't afford it

    • 41 Comments

    A customer reported a crash inside a function we'll call XyzConnect:

    DWORD XyzConnect(
        __in DWORD ConnectionType,
        __in PCWSTR Server,
        __in PCWSTR Target,
        __out void **Handle);
    ...
    // HACK - Create a dummy structure to pass to the XyzConnect
    // function to avoid AV within the function.
    int dummy = 0;    
    if ( NO_ERROR != ( XyzConnect( 0, L"", L"", (PVOID*)&dummy ) )
    {
        TRACE( L"XyzConnect failed." );
        return FALSE;
    }
    ...
    

    The title of today's entry gives the answer away. (The title is also an exaggeration, but it's a pun on the saying If you have to ask, you can't afford it.)

    The last parameter to the XyzConnect function is declared as a void**: A pointer to a generic pointer. Note that it is not itself a generic pointer, however. A generic pointer can point to anything, possibly unaligned. But this is an aligned pointer to a generic pointer. Therefore, the memory for the generic pointer must be aligned in a manner appropriate to its type.

    But this caller didn't pass a pointer to a pointer; the caller passed a pointer to an int, and an int has different alignment requirements from a pointer on 64-bit systems. (You might conclude that this decision was the stupidest decision on the face of the planet, but that's a different argument for a different time. For example, I can think of decisions far stupider.)

    When the XyzConnect function tries to dereference this purported void ** pointer, it encounters an alignment fault, because it does not in fact point to a void * as the type claims, but rather points to a DWORD. A DWORD requires only 32-bit alignment, so you have a 50% chance that the DWORD* is not suitably aligned to be a void*.

    Mind you, you also have a 100% chance of a buffer overflow, because a DWORD is only four bytes, whereas a void* is eight bytes. The function is going to write eight bytes into your four-byte buffer.

    When this question was posed, one person suggested changing the DWORD to a __int64, since the __int64 is an 8-byte value, which is big enough to hold a pointer on both 32-bit and 64-bit Windows. Then again, it's overkill on 32-bit systems, since you allocated eight bytes when you only needed four. Another suggestion was to use DWORD_PTR, since that type changes in size to match the size of a void*.

    Well, yeah, but here's another type that matches the size of a void*: It's called void*.

    Just declare void *dummy and get rid of the cast. And get rid of the comment while you're at it. If you do it right, you don't need the cast or the hack.

    void *handle = 0;    
    if ( NO_ERROR != ( XyzConnect( 0, L"", L"", &handle ) )
    {
        TRACE( L"XyzConnect failed." );
        return FALSE;
    }
    

    A large number of porting problems can be traced to incorrect casts. The original author probably inserted the cast to "shut up the compiler" but the compiler was trying to tell you something.

    Any time you see a function cast or see a cast to/from something other than void* or BYTE*, then you should be suspicious, because there's a chance somebody is simply trying to shut up the compiler.

Page 1 of 4 (35 items) 1234