• The Old New Thing

    Where do those customized web site icons come from?


    In a comment to yesterday's entry, someone asked about the customized icon that appears in the address bar... sometimes.

    There's actually method to the madness. I was going to write about it later, but the comment (and misinformed answers) prompted me to move it up the schedule a bit. (The originally-scheduled topic for today - the history of Ctrl+Z - will have to wait.)

    Each web site can put a customized icon called favicon.ico into the root of the site, or the page can use a custom LINK tag in the HTML to specify a nondefault location for the favicon, handy if the page author do not have write permission into the root directory of the server.

    In order for the favicon.ico to show up in the address bar, (1) the site needs to offer a customized icon, (2) you have to have added the site to your favorites, and (3) the site icon must still be in your IE cache.

    IE does not go and hit every site you visit for a favicon.ico file; that would put too much strain on the server. (Heck, some people got hopping mad that IE was probing for favicon.ico files at all. Imagine the apoplectic fits people would have had if IE probed for the file at every hit!) Only when you add the site to your favorites does IE go looking for the favicon and stash it in the cache for future use.

  • The Old New Thing

    Sorry, my kitchen is on fire


    The other night my phone rang just as I discovered that I overheated my pan and the oil was starting to burn. I rushed to the phone, thinking it's the people I had invited to dinner, but no, it was some telemarketer.

    "Hello, is this Mr. Chen?"

    "Sorry, can't talk now, my kitchen is on fire."

    "Oh my God, sorry!" <click>

    I'll have to remember to use that again in the future.

    (P.S., there were no actual flames and I managed to open enough windows so my smoke detector didn't go off.)

  • The Old New Thing

    Blow the dust out of the connector

    Okay, I'm about to reveal one of the tricks of Product Support.

    Sometimes you're on the phone with somebody and you suspect that the problem is something as simple as forgetting to plug it in, or that the cable was plugged into the wrong port. This is easy to do with those PS/2 connectors that fit both a keyboard and a mouse plug, or with network cables that can fit both into the upstream and downstream ports on a router.

    Here's the trick: Don't ask "Are you sure it's plugged in correctly?"

    If you do this, they will get all insulted and say indignantly, "Of course it is! Do I look like an idiot?" without actually checking.

    Instead, say "Okay, sometimes the connection gets a little dusty and the connection gets weak. Could you unplug the connector, blow into it to get the dust out, then plug it back in?"

    They will then crawl under the desk, find that they forgot to plug it in (or plugged it into the wrong port), blow out the dust, plug it in, and reply, "Um, yeah, that fixed it, thanks."

    (Or if the problem was that it was plugged into the wrong port, then the act of unplugging it and blowing into the connector takes their eyes off the port. Then when they go to plug it in, they will look carefully and get it right the second time because they're paying attention.)

    Customer saves face, you close a support case, everybody wins.

    Corollary: Instead of asking "Are you sure it's turned on?", ask them to turn it off and back on.

  • The Old New Thing

    Calling the irony patrol


    I don't speak Dutch, so I went of course to a Dutch search engine, www.vinden.nl. And upon my arrival I was greeted with a pop-up ad offering me a pop-up blocker.

    There's something wrong about that.

  • The Old New Thing

    Went to a Seattle Thunderbirds game this weekend


    This past weekend I fell into tickets to a Seattle Thunderbirds game. (The Seattle Thunderbirds belong to the "U.S. Division" of the otherwise-Canadian Western Hockey League, one of the three Major Junior Leagues.)

    I hadn't been to a hockey game since my college days. It was quite enjoyable and I may very well do it again.

    On the message board, the various groups in attendance were recognized. In addition to the usual things like "Fred's 9th Birthday" and "Company X", there was the curious juxtaposition of "David's Bachelor Party" and "XYZ Church". I hope they weren't seated next to each other.

    I was there with a bunch of seventh graders and their parents because the middle school choir performed the Canadian and U.S. national anthems. I had forgotten that to seventh graders, the world is one giant social event, just with different background noise. In this case, it was a big social event with hockey noise in the background. They were chatting away, waving to their friends, changing seats, calling each other on their cell phones, writing notes to each other...

    To give you an idea of the tenor of play, I refer you to the game report: Under "Seattle Penalties", observe that in the second period, player number 28 was assessed a two-minute roughing penalty which expired at 3:13. Now look down a little bit more: At 3:23, the same player was assessed a Checking from Behind penalty. I watched this happen. When his penalty expired, the player dashed out of the penalty box straight for an opposing player and walloped him. And then was promptly sent back off the ice.

    Ah, minor league hockey. "We may not play very well, but we make up for it with really aggressive tactics."

    And yes multiple fights broke out, to my disappointment (but to the delight of the crowd, it appears). As we left, I overheard one seventh grader say to her friend, "It was fun, but there wasn't enough fighting."

  • The Old New Thing

    Why are HANDLE return values so inconsistent?


    If you look at the various functions that return HANDLEs, you'll see that some of them return NULL (like CreateThread) and some of them return INVALID_HANDLE_VALUE (like CreateFile). You have to check the documentation to see what each particular function returns on failure.

    Why are the return values so inconsistent?

    The reasons, as you may suspect, are historical.

    The values were chosen to be compatible with 16-bit Windows. The 16-bit functions OpenFile, _lopen and _lcreat return -1 on failure, so the 32-bit CreateFile function returns INVALID_HANDLE_VALUE in order to facilitate porting code from Win16.

    (Armed with this, you can now answer the following trivia question: Why do I call CreateFile when I'm not actually creating a file? Shouldn't it be called OpenFile? Answer: Yes, OpenFile would have been a better name, but that name was already taken.)

    On the other hand, there are no Win16 equivalents for CreateThread or CreateMutex, so they return NULL.

    Since the precedent had now been set for inconsistent return values, whenever a new function got added, it was a bit of a toss-up whether the new function returned NULL or INVALID_HANDLE_VALUE.

    This inconsistency has multiple consequences.

    First, of course, you have to be careful to check the return values properly.

    Second, it means that if you write a generic handle-wrapping class, you have to be mindful of two possible "not a handle" values.

    Third, if you want to pre-initialize a HANDLE variable, you have to initialize it in a manner compatible with the function you intend to use. For example, the following code is wrong:

    HANDLE h = NULL;
    if (UseLogFile()) {
        h = CreateFile(...);
    if (h) {
    if (h) {
    This code has two bugs. First, the return value from CreateFile is checked incorrectly. The code above checks for NULL instead of INVALID_HANDLE_VALUE. Second, the code initializes the h variable incorrectly. Here's the corrected version:
    if (UseLogFile()) {
        h = CreateFile(...);
    if (h != INVALID_HANDLE_VALUE) {
    if (h != INVALID_HANDLE_VALUE) {

    Fourth, you have to be particularly careful with the INVALID_HANDLE_VALUE value: By coincidence, the value INVALID_HANDLE_VALUE happens to be numerically equal to the pseudohandle returned by GetCurrentProcess(). Many kernel functions accept pseudohandles, so if if you mess up and accidentally call, say, WaitForSingleObject on a failed INVALID_HANDLE_VALUE handle, you will actually end up waiting on your own process. This wait will, of course, never complete, because a process is signalled when it exits, so you ended up waiting for yourself.

  • The Old New Thing

    Why 16-bit DOS and Windows are still with us

    Many people are calling for the abandonment of 16-bit DOS and 16-bit Windows compatibility subsystems. And trust me, when it comes time to pull the plug, I'll be fighting to be the one to throw the lever. (How's that for a mixed metaphor.)

    But that time is not yet here.

    You see, folks over in the Setup and Deployment group have gone and visited companies around the world, learned how they use Windows in their businesses, and one thing keeps showing up, as it relates to these compatibility subsystems:

    Companies still rely on them. Heavily.

    Every company has its own collection of Line of Business (LOB) applications. These are programs that the company uses for its day-to-day business, programs the company simply cannot live without. For example, at Microsoft two of our critical LOB applications are our defect tracking system and our source control system.

    And like Microsoft's defect tracking system and source control system, many of the LOB applications at major corporations are not commercial-available software; they are internally-developed software, tailored to the way that company works, and treated as trade secrets. At a financial services company, the trend analysis and prediction software is what makes the company different from all its competitors.

    The LOB application is the deal-breaker. If a Windows upgrade breaks a LOB application, it's game over. No upgrade. No company is going to lose a program that is critical to their business.

    And it happens that a lot of these LOB applications are 16-bit programs. Some are DOS. Some are 16-bit Windows programs written in some ancient version of Visual Basic.

    "Well, tell them to port the programs to Win32."

    Easier said than done.

    • Why would a company go to all the effort of porting a program when the current version still works fine. If it ain't broke, don't fix it.
    • The port would have to be debugged and field-tested in parallel with the existing system. The existing system is probably ten years old. All its quirks are well-understood. It survived that time in 1998 when there was a supply chain breakdown and when production finally got back online, they had to run at triple capacity for a month to catch up. The new system hasn't been stress-tested. Who knows whether it will handle these emergencies as well as the last system.
    • Converting it from a DOS program to a Windows program would incur massive retraining costs for its employees ("I have always used F4 to submit a purchase order. Now I have this toolbar with a bunch of strange pictures, and I have to learn what they all mean." Imagine if somebody took away your current editor and gave you a new one with different keybindings. "But the new one is better.")
    • Often the companies don't have the source code to the programs any more, so they couldn't port it if they wanted to. It may use a third-party VB control from a company that has since gone out of business. It may use a custom piece of hardware that they have only 16-bit drivers for. And even if they did have the source code, the author of the program may no longer work at the company. In the case of a missing driver, there may be nobody at the company qualified to write a 32-bit Windows driver. (I know one company that used foot-pedals to control their software.)

    Perhaps with a big enough carrot, these companies could be convinced to undertake the effort (and risk!) of porting (or in the case of lost source code and/or expertise, rewriting from scratch) their LOB applications.

    But it'll have to be a really big carrot.

    Real example: Just this past weekend I was visiting a friend who lived in a very nice, professionally-managed apartment complex. We had occasion to go to the office, and I caught a glimpse of their computer screen. The operating system was Windows XP. And the program they were running to do their apartment management? It was running in a DOS box.

  • The Old New Thing

    The correct order for disabling and enabling windows

    If you want to display modal UI, you need to disable the owner and enable the modal child, and then reverse the procedure when the modal child is finished.

    And if you do it wrong, focus will get all messed up.

    If you are finished with a modal dialog, your temptation would be to clean up in the following order:

    • Destroy the modal dialog.
    • Re-enable the owner.

    But if you do that, you'll find that foreground activation doesn't go back to your owner. Instead, it goes to some random other window. Explicitly setting activation to the intended owner "fixes" the problem, but you still have all the flicker, and the Z-order of the interloper window gets all messed up.

    What's going on?

    When you destroy the modal dialog, you are destroying the window with foreground activation. The window manager now needs to find somebody else to give activation to. It tries to give it to the dialog's owner, but the owner is still disabled, so the window manager skips it and looks for some other window, somebody who is not disabled.

    That's why you get the weird interloper window.

    The correct order for destroying a modal dialog is

    • Re-enable the owner.
    • Destroy the modal dialog.

    This time, when the modal dialog is destroyed, the window manager looks to the owner and hey this time it's enabled, so it inherits activation.

    No flicker. No interloper.
  • The Old New Thing

    Why do timestamps change when I copy files to a floppy?

    Floppy disks use the FAT filesystem, as do DOS-based and Windows 95-based operating systems. On the other hand, Windows NT-based systems (Windows 2000, XP, 2003, ...) tend to use the NTFS filesystem. (Although you can format a drive as FAT on Windows NT-based systems, it is not the default option.)

    The NTFS and FAT filesystems store times and dates differently. Note, for example, that FAT records last-write time only to two-second accuracy. So if you copy a file from NTFS to FAT, the last-write time can change by as much as two seconds.

    Why is FAT so much lamer than NTFS? Because FAT was invented in 1977, back before people were worried about such piddling things like time zones, much less Unicode. And it was still a major improvement over CP/M, which didn't have timestamps at all.

    It is also valuable to read and understand the consequences of FAT storing filetimes in local time, compared to NTFS storing filetimes in UTC. In addition to the Daylight Savings time problems, you also will notice that the timestamp will appear to change if you take a floppy across timezones. Create a file at, say, 9am Pacific time, on a floppy disk. Now move the floppy disk to Mountain time. The file was created at 10am Mountain time, but if you look at the disk it will still say 9am, which corresponds to 8am Pacific time. The file travelled backwards in time one hour. (In other words, the timestamp failed to change when it should.)

  • The Old New Thing

    Why can't I put hotlinks in notification icon balloon tips?

    The short answer: "Because there is no NIF_PARSELINKS flag."

    The long answer:

    When balloon tips were first developed, there was no ability to embed links. Consequently, programs were free to put insecure text in balloon tips, since there was no risk that they would become "live". So, for example, a virus scanner might say "The document 'XYZ' has been scanned and found to be free of viruses."

    Now suppose hotlinks were supported in balloon tips. Look at how this can be exploited: I can write a web page that goes

    <TITLE>&lt;A HREF="file:C:\Windows\system32\format.com?C:"&gt;
    Party plans&lt;/A&gt;</TITLE>
    I then rename the file to "Party plans.html", attach it to some email, and send it to you.

    You download the message and since you are a cautious person, you ask your virus scanner to check it out. The balloon appears:

    Virus scan complete ×
    The document 'Party plans' has been scanned
    and found to be free of known viruses.

    "Oh, how convenient," you say to yourself. "The virus scanner even included a hotlink to the document so I can read it."

    And then you click on it and your hard drive gets reformatted.

    "So why don't you add a NIF_PARSELINKS flag, so people who want to enable hotlinks in their balloon tips can do so, and still remain compatible with people who wrote to the old API?"

    (I've heard of one person trying to pass a TTF_PARSELINKS flag in the NOTIFYICONDATA.uFlags member and wondering why it wasn't working. I hope it's obvious to everybody why this had no chance of working.)

    Because that would just be passing the buck. Anybody who used this proposed flag would then have to be extra-careful not to put untrusted links in their balloon tips. Most people would just say, "Wow! A new flag! That's awesome!" and start using it without considering the serious security implications. Then somebody can trick the program into putting untrusted text into a balloon tip and thereby exploit the security hole.

    "Aw, come on, who would be so stupid as to write code without considering all the security implications?"

    I hope that was a joke question.

    The best way to make sure things are secure is to make it impossible to be insecure.

Page 417 of 444 (4,431 items) «415416417418419»