August, 2007

  • The Old New Thing

    The Great Muffin Heist of '07

    • 15 Comments

    Earlier this month, there were no muffins to be found anywhere on Microsoft campus. Somebody stole the Muffin Truck!

  • The Old New Thing

    The Internet Explorer pop-up blocker follows guidelines, not rules

    • 52 Comments

    Here's a question that came in from a customer (paraphrased):

    Hello, we are developing an ASP.NET application and are running into problems with the pop-up blocker introduced in Windows XP Service Pack 2. Where can we get a full description of the rules that control whether a pop-up will be blocked so we can make sure our pop-ups are let through?

    There is no full description because that would make the pop-up blocker useless. Suppose a formal description were available. Somebody studies the formal description and finds a loophole in the pop-up blocker and exploits it. (Indeed that is precisely what this customer is trying to do!) The browser team finds the same loophole and tries to plug it. The exploiter says, "Uh uh, according to your formal description, the XYZ technique avoids all the checks and therefore must not be blocked." A bug has become a feature.

    What you do have is a guiding principle: "Pop-ups are allowed if they were triggered by an explicit user input." For example, if the user clicks a button or link, you can display a pop-up in response to that click. React to the click when it is clicked. The click isn't a coupon you can save and then spend later. You have to do it when the click happens.

    Consequences of this guiding principle:

    • Don't "forward" the click through redirects. Again, the browser won't necessarily make the connection between the redirect and the click.
    • Don't set a timer and then display the pop-up later, because the browser won't necessarily make the connection between the call to window.open from your timer and the user click action from long ago. (Arguably, the user won't make the connection either!)

    The point is, you get your chance when the click happens. If you blow it, then it's gone.

    If you are implementing an ActiveX control, you need to make sure to forward QueryService calls through your site chain so that when your control decides to perform a navigation, the navigation object can connect back to the web browser's pop-up blocker to determine whether the navigation should be allowed or blocked.

    In the future, new rules may be invented to plug additional holes in the current implementation, but the guiding principle will still govern. Stick to the principles and you'll be fine.

    Notes

    I reiterate that the reason for not disclosing the "official rules" is not for security reasons. (Indeed the word "security" never appears in the article.) The reason is that making the rules official means that you can never change them. And the IE team wants to reserve the right to change the rules. Notice that the customer was looking for a guarantee that their pop-up algorithm will always be permitted in current and future versions of IE. In other words, they wanted a promise that the rules would never change.

    Some people have mentioned that Firefox has disclosed their rules for pop-up blockers. Has Firefox also promised never to change their rules? What happens if Firefox makes a change, and a site that used to be allowed is now blocked? Can the site sue Firefox for violating its own rules?

    You can find loopholes in even the simplest rules. "If the user physically clicks the mouse button over a link element that is enabled, visible, and all that good stuff, and the link is marked to open in a new window, then it will open in a new window." Sounds like a pretty fair rule, but are you willing to guarantee that this behavior will always be permitted in all future versions of the Web browser?

    I'm glad you think so, because there's a loophole in that rule. But since you made the guarantee, you can't close the loophole.

  • The Old New Thing

    Somebody actually took the time to translate my book into Japanese, it appears

    • 29 Comments

    I have no idea who they are (since I can't read Japanese), but hatena appears to be some sort of Japanese social bookmarking site, and I'll often find hits from them in my referrer logs. One of the members found a newly-issued Japanese translation of my book, which opens up a whole new audience to my obnoxious personality.

    Stumbling across the Japanese edition was a bit of a surprise. I mean, yeah, the book contract has some paragraphs about translations, but seriously, who actually expects their book to be translated? That's just standard book contract boilerplate stuff.

    What next, a movie deal?

  • The Old New Thing

    Microspeak: FMLA

    • 78 Comments

    If you leave your computer unattended and logged in, especially if you work on the security team, you may come back to your office to find that somebody used your computer to sent email out to the entire team with the subject line FMLA.

    FMLA stands for "Fire my lame anterior" (except with another word for anterior).

    The implication is that somebody who left their computer unattended and logged in has left themselves open to an identity theft attack, for the person who sent the email could very well have just sent the email to Bill Gates demanding to be fired. (The victim of this prank is typically somebody new to the team.)

  • The Old New Thing

    Follow-up: Mysterious Dietrich identified from that bizarre Ferarri crash

    • 7 Comments

    Last year, a spectacular crash of a $1 million Ferrari left a lot of questions unanswered. Who were those mysterious men who picked up Eriksson? How did a fully loaded automatic pistol get under the seat of a person who stopped to help? Why exactly does the San Gabriel Valley Transit Authority have an anti-terrorism unit? And who is this mysterious Dietrich who was allegedly driving the car when it crashed?

    Well, the authorities think they have an answer to that last question. Trevor Karney is in custody on charges of drunken driving, among others. He gave a false address to the police, and while they were trying to track him down, he slipped out of the country, then slipped back in. His story was (get this) that he was a passenger in a Mercedes that was behind the Ferrari, and when it crashed, the driver of the Mercedes stopped, Karney got out, and the Mercedes drove off without him.

    Authorities believe that Karney is the mysterious Dietrich, and that he was a passenger in the crashed Ferrari.

    (Eriksson was sentenced to 3½ years in prison for embezzlement and drunken-driving.)

  • The Old New Thing

    Kernel handles are not reference-counted

    • 16 Comments

    Here's a question that floated past some time ago:

    In my code, I have multiple objects that want to talk to the same handle (via DeviceIoControl). Each time I create an object, I use DuplicateHandle to increment the reference count on the handle. That way, when each object calls CloseHandle, only the last one actually closes the handle. However, when I run the code, I find as soon as the first object calls CloseHandle, the handle is no longer valid and nobody else can use it. What flags do I need to pass to CreateFile to get this to work?

    In other words, the code went something like this:

    // h is the handle that we want to share with a new CFred object
    
    CFred *MakeFred(HANDLE h)
    {
     // "Duplicate the handle to bump the reference count"
     // This code is wrong - see discussion
     // All error checking removed for expository purposes
     HANDLE hDup;
     DuplicateHandle(GetCurrentProcess(), h,
                     GetCurrentProcess(), &hDup,
                     0, FALSE, DUPLICATE_SAME_ACCESS);
     return new CFred(h);
    }
    

    Kernel handles aren't reference-counted. When you call CloseHandle, that closes the handle, end of story.

    From the original problem statement, we know that the CFred object closes the handle when it is destroyed. Just for argument's sake, let's say that the caller goes something like this:

    CFred *pfred1 = MakeFred(h);
    CFred *pfred2 = MakeFred(h);
    delete pfred1;
    delete pfred2;
    

    What actually happens when you run this fragment?

    The first time we call MakeFred we take the original handle h and duplicate it, but we give the original handle to the CFred constructor and leak the hDup! The original poster assumed that duplicating a handle merely incremented the handle's imaginary reference count, so that h == hDup. (Which would also have made the original poster wonder why we even bother having a lpTargetHandle parameter in the first place.)

    When pfred1 is deleted, it closes its handle, which is h. This closes the h handle and renders it invalid and available to be recycled for another CreateFile or other operation that creates a handle.

    When pfred2 is deleted, it also closes its handle, which is still h. This is now closing an already-close handle, which is an error. If we had bothered calling a method on pfred2 that used the handle, it would have gotten failures from those operations as well, since the handle is no longer valid. (Well, if we're lucky, we would have gotten a failure. If we were unlucky, the handle would have been recycled and we ended up performing a DeviceIoControl on somebody else's handle!)

    Meanwhile, the calling code's copy of h is also bad, since pfred1 closed it when it was deleted.

    What we really want to do here is duplicate the handle and pass the duplicate to each object. The DuplicateHandle function creates a new handle that refers to the same object as the original handle. That new handle can be closed without affecting the original handle.

    // h is the handle that we want to share with a new CFred object
    
    CFred *MakeFred(HANDLE h)
    {
     // Create another handle that refers to the same object as "h"
     // All error checking removed for expository purposes
     HANDLE hDup;
     DuplicateHandle(GetCurrentProcess(), h,
                     GetCurrentProcess(), &hDup,
                     0, FALSE, DUPLICATE_SAME_ACCESS);
     return new CFred(hDup);
    }
    

    The fix is one word, highlighted in blue. We give the duplicated handle to the CFred object. That way, it gets its own handle which it is free to close any time it wants, and it won't affect anybody else's handle.

    You can think of DuplicateHandle as a sort of AddRef for kernel objects. Each time you duplicate a handle, the reference count on the kernel object goes up by one, and you gain a new reference (the new handle). Each time you close a handle, the reference count on the kernel object drops by one.

    In summary, a handle is not a reference-counted object. When you close a handle, it's gone. When you duplicate a handle, you gain a new obligation to close the duplicate, in addition to the existing obligation to close the original handle. The duplicate handle refers to the same object as the original handle, and it is the underlying object that is reference-counted. (Note that kernel objects can have reference from things that aren't handles. For example, an executing thread maintains a reference to the underlying thread object. Closing the last handle to a thread will not destroy the thread object because the thread keeps a reference to itself as long as it's running.)

  • The Old New Thing

    Airport travel tip: LAX Terminal 6 (United)

    • 15 Comments

    When you enter Terminal 6 and turn right to enter the security queue, there are two sets of security equipment. If you are directed to the far set of equipment, you will find three lines for screening. At the point at which you have to choose which line to take, you can't see how your decision is going to play out. The arrangement is effectively the same as at Newark: You want to take the rightmost line, number three in the diagram below.

    1 >>>------------------------+
    2 >>>------------------+     |
    3 >>>------------+     |     |
                     |     |     |
                     v     v     v
    
  • The Old New Thing

    With a new Start menu come new keyboard shortcuts

    • 54 Comments

    With the new Windows Vista Start menu, the keyboard shortcuts have once again been reorganized. You used to be able to hit the Windows key and then type L to call up the Log off menu, and then L again to trigger the logoff. Or you can hit the Windows key and then type I to launch Internet Explorer if you've been so careful to ensure that Internet Explorer is the only program that you run frequently which begins with the letter I. With Windows Vista, the keyboard focus is on the Search box when you open the Start menu, so these one-letter shortcuts are treated as the start of a search.

    The designers of the Windows Vista Start menu realized that the loss of these one-letter shortcuts was a drawback of the new design. Their rationale for the change was that they were providing quick two- or three-letter shortcuts to hundreds of programs and documents that users frequently use, at a cost of one-letter shortcuts to a very small number of programs.

    But all is not lost. The Search box still knows about what you do most often. If you really log off that frequently, then when you type L, the option to Log off will be at the top of the search hits, and you can just hit Enter to confirm.

    Windows, L, L is now Windows, L, Enter. Same number of keystrokes, but now more flexible and adaptive.

  • The Old New Thing

    Is this the normal way of comparing toilets?

    • 21 Comments

    My colleague Erin Dallin remarked, "I just installed a new toilet as part of my bathroom remodel. I was told that it is capable of flushing 20 golf balls using only 1.6 gallons of water. I'd love to know how this standard was developed."

    Visit the product Web site and click on Flushing system in action to watch the video. Or read Wired's coverage of flush technology.

    "I also suspect that someday I'll finally break down and verify just how many golf balls I can flush."

  • The Old New Thing

    Yes indeed, all Microsoft files are (or should be) digitally signed

    • 52 Comments

    Yes indeed, all Microsoft files are (or should be) digitally signed (as far as I'm aware). So I'm not quite sure what commenter Dave is getting at:

    The Microsoft file should have embedded vendor/product information saying it's from Microsoft and will be cryptographically signed by Microsoft. Similarly-named malware won't be signed by Microsoft, unless Verisign slipped up *again* and issued another bogus certificate.

    Wow, this is such a great idea, that it's been true for many years now. All Microsoft files are digitally signed. They have to be; otherwise, Windows File Protection wouldn't be able to tell whether this new version of shell32.dll is a security update or just some malware trying to replace a system file. As I noted quite some time ago, you can run the sigverif program to validate the digital signatures of all system files.

    Long descriptive names are just as much an opportunity to malware makers as they are to legit software developers. Gee, why would you want to stop a file named "Critical Security Update Service.exe" for example?

    And that's why Windows XP Service Pack 2 added the ability to mark a file as "I got this from the Internet." (Internet Explorer applies this marking when you download a file from the Internet.) Before you run such a file, Explorer will prompt you with a warning and show you the digital signature information so that you can confirm that the download is what it purports to be and has not been tampered with.

    This is just one example of a commenter who suggests that Windows do things that it already does: Drop down lists do let you type multiple characters. Here's another example. Windows has been multilingual since Windows 2000.

    For now, I'm going to keep ignoring them. Just because you say something in my presence and I don't raise an objection doesn't mean that I agree. Or that what you said is even true.

Page 1 of 5 (46 items) 12345