August, 2007

  • The Old New Thing

    At last you can turn off the USB 2.0 balloon

    • 84 Comments

    One of the more annoying messages in Windows XP¹ is the "This USB device can perform faster" balloon that appears whenever you plug in a USB 2.0-capable device into a USB 1.0 port. When I click on that balooon, I get a message that says, "Sorry, you don't have any USB 2.0 ports. You'll have to install one to be able to take full advantage of this device."²

    Yeah, that's really nice, but one of my machines is a laptop, so its USB ports can't be upgraded. And my desktop computer at the time had an older motherboard that predated USB 2.0. The really annoying part was that there was no way to turn off the balloon. "Yes, I know I inserted the device into a USB 1.0 port, but this computer doesn't have any USB 2.0 ports, so stop bugging me already."

    It actually got the point that I went out and bought a USB 2.0 adapter card just to shut up the stupid balloon.³

    Thank goodness that in Windows Vista, the USB folks realized how annoying it is to show a balloon that yells at you for something you can't do anything about, and they added a way to disable the pop-up.

    Nitpicker's Corner

    ¹Although this statement takes the grammatical form of a statement of fact, it is actually a statement of opinion. Other people may legitimately disagree with this opinion. Whether the message is in fact "one of the more annoying messages in Windows XP" is irrelevant to the story; the employment of this statement of opinion is rhetorical and serves a useful storytelling purpose, namely to serve as an interesting introduction and to establish a context for elaboration. It does not establish the official position of Microsoft Corporation regarding how annoying that message is.

    ²That is not literally what the message says, but the underlying meaning is comparable. The message text has been paraphrased for rhetorical purposes (to create a more informal tone) and for time-saving purposes (to save me the trouble of having to re-create the message and carefully transcribe the message word-for-word).

    ³Again, the use of the word "stupid" here is rhetorical, indicating my level of frustration and not attempting to establish the official Microsoft position on the intelligence of the balloon or the people responsible for it.

  • 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

    Nested fly-out menus are a usability nightmare

    • 74 Comments

    The Windows Vista Start menu abandoned the flyout model for the "All Programs" menu because nested fly-out menus are a usability nightmare, and not just for novices.

    Research has shown that once you have menus more than one level deep, you have the problem that the slightly wiggle of the mouse can take the big, complicated menu hierarchy that the user spent enormous attention to build and make it all disappear in a flash. I run into this a lot. "File, Open Multiple, By Searching..." oops I moved my mouse too far upwards and tickled the View menu and boom my menu vanishes and I have to start all over again. Menu navigation has turned into one of those mouse dexterity games where you have to guide your character through a maze without hitting any of the walls or you die and have to start over.

    The All Programs menu has turned into a unwieldy mess thanks to all the programs that shove themselves into every nook and cranny. As a result, navigating it as a hierarchical menu has turned into a common source of frustration due to the "collapsing menu" problem. The solution? Reframe it as a tree view which acts only when you click. The hierarchy is still there, but it's much easier to navigate.

    This ease of use comes at a cost: If you're one of those people who can guide a mouse with pixel-perfect precision, then you're going to find mouse-based menu navigation a bit slower due to the extra clicking. But if it's speed you're after, then put down the mouse and stick to the keyboard: Type the name of what you want into the Start menu search box, and you'll be taken straight to it.

    (No nitpicker's corner today. We'll see what happens.)

  • The Old New Thing

    What is the order of evaluation in C#?

    • 68 Comments

    The C and C++ languages leave the order of evaluation generally unspecified aside from specific locations called sequence points. Side effects of operations performed prior to the sequence point are guaranteed visible to operations performed after it.¹ For example, the C comma operator introduces a sequence point. When you write f(), g(), the language guarantees that any changes to program state made by the function f can be seen by the function g; f executes before g. On the other hand, the multiplication operator does not introduce a sequence point. If you write f() * g() there is no guarantee which side will be evaluated first.

    (Note that order of evaluation is not the same as associativity and operator precedence. Given the expression f() + g() * h(), operator precedence says that it should be evaluated as if it were written f() + (g() * h()), but that doesn't say what order the three functions will be evaluated. It merely describes how the results of the three functions will be combined.)

    In the C# language, the order of evaluation is spelled out more explicitly. The order of evaluation for operators is left to right. if you write f() + g() in C#, the language guarantees that f() will be evaluated first. The example in the linked-to page is even clearer. The expression F(i) + G(i++) * H(i) is evaluated as if it were written like this:

    temp1 = F(i);
    temp2 = i++;
    temp3 = G(temp2);
    temp4 = H(i);
    return temp1 + temp3 * temp4;
    

    The side effects of each part of the expression take effect in left-to-right order. Even the order of evaluation of function arguments is strictly left-to-right.

    Note that the compiler has permission to evaluate the operands in a different order if it can prove that the alternate order of evaluation has the same effect as the original one (in the absence of asynchronous exceptions).

    Why does C# take a much more restrictive view of the order of evaluation? I don't know, but I can guess.²

    My guess is that the language designers wanted to reduce the frequency of a category of subtle bugs (in this case, order-of-evaluation dependency). There are many other examples of this in the language design. Consider:

    class A {
     void f()
     {
      int i = 1;
      if (true) {
       int i = 2; // error - redeclaration
      }
     }
    
     int x;
     void g()
     {
      x = 3; // error - using variable before declared
      int x = 2;
     }
    }
    

    The language designers specified that the scope of a local variable in C# extends to the entire block in which it is declared. As a first consequence of this, the second declaration of i in the function f() is illegal since its scope overlaps with the scope of the first declaration. This removes a class of bugs that can be traced to one local variable masking another with the same name.

    In the function g() the assignment x = 3; is illegal because the x refers not to the member variable but to the local variable declared below it. Notice that the scope of the local variable begins with the entire block, and not with the point of declaration as it would have been in C++.

    Nitpicker's Corner

    ¹This is a simplified definition of sequence point. For more precise definitions, consult the relevant standards documents.

    ²I have not historically included the sentence "I don't know but I can guess" because this is a blog, not formal documentation. Everything is my opinion, recollection, or interpretation. But it seems that people take what I say to establish the official Microsoft position on things, so now I have to go back and add explicit disclaimers.

  • The Old New Thing

    Things I've written that have amused other people, Episode 4

    • 66 Comments

    One of my colleagues pointed out that my web site is listed in the references section of this whitepaper. It scares me that I'm being used as formal documentation because that is explicitly what this web site isn't. I wrote back,

    I really need to put a disclaimer on my web site.
    FOR ENTERTAINMENT PURPOSES ONLY

    Remember, this is a blog. The opinions (and even some facts) expressed here are those of the author and do not necessarily reflect those of Microsoft Corporation. Nothing I write here creates an obligation on Microsoft or establishes the company's official position on anything. I am not a spokesperson. I'm just this guy who strings people along in the hopes that they might hear a funny story once in a while.

    You'd think this was obvious, but apparently there are people who think that somehow what I write has the weight of official Microsoft policy and take my sentences apart as if they were legal documents or who take my articles and declare them to be official statements from Microsoft Corporation.

  • The Old New Thing

    Windows Vista has more extended options on the context menu

    • 63 Comments

    As we saw when we discussed context menus, holding down the shift key when opening a context menu adds so-called extended verbs to the menu. These are verbs that are less frequently used whose presence would clutter up the menu or pose an attractive nuisance.

    For example, the "Command Prompt Here" command is an extended command since your typical non-technical user has no use for it,¹ and selecting it creates a baffling command prompt that screams "You are not smart enough to use this computer! Return it to the store and get a Mac instead!"

    In reaction to this, one person wrote, "I've not seen anyone even attempt to justify why this should be hidden like this. Shift+RightClick is not a standard move so no one is going to find this by accident."

    And indeed, that's precisely why it's hidden²—so that nobody finds it by accident! The only³ people that find it are the people who are smart enough to go looking for it.

    Nitpicker's Corner

    ¹Although this statement is written as if it were a fact, all facts presented here are really just my personal interpretation of the world. That interpretation is not the official position of Microsoft Corporation, and it may ultimately prove incorrect.

    ²The use of the word "precisely" here is rhetorical, emphasizing that the argument against hiding them works equally well as an argument for hiding them. The statement is not an establishment of the official Microsoft position on why the menu items are on the extended menu. It is merely my interpretation of the situation.

    ³The use of the term "only" here is not meant in an absolute sense, as if there were some physical barrier preventing people from using it inadvertently. It is possible that somebody might hold the shift key by mistake when calling up the context menu, in which case my statement that "The only people that find it are the people who are smart enough to go looking for it" becomes incorrect.

  • The Old New Thing

    Math is hard, let's go shopp—oops

    • 60 Comments

    (The title is another variation on Math is hard, let's go shopping!", which appears to be a popular catchphrase over in Michael Kaplan's neck of the woods. The history of the phrase was researched on Language Log.)

    Last spring, I was at a local crafts store and paid for a $2.15 item with a $5 bill and two dimes. The teenage salesclerk rang up the sale and began to give me $17.90 in change.

    "Um, I gave you $5.20." You'd think the salesclerk would notice something strange when the amount of change exceeded the amount of cash tendered!

    "Oh, right." The salesclerk had entered $20.05 instead of $5.20. But now came the hard part: Computing the correct amount of change.

    Apparently kids these days aren't taught how to make change. They just punch the number into the register and trust what comes out. "In my day," we learned to make change by rewriting the formula "change = tendered - cost" as "cost + change = tendered". In other words, you start with the cost of the item, then add money to bring the total to the amount of money you received. For example, if somebody paid for a $3.45 item with a $20 bill, you'd make change as follows:

    You give the customer... You say...
    three forty-five
    a nickel ($0.05)three fifty
    a quarter ($0.25)three seventy-five
    a quarter ($0.25)four
    a $1 billfive
    a $5 billten
    a $10 billtwenty

    Adding up the change you created yields $0.05 + $0.25 + $0.25 + $1 + $5 + $10 = $16.55, which is the correct amount of change for $20 - $3.45.

    Even if kids aren't taught this technique nowadays, at least they should be able to do subtraction the traditional way. $5.20 - $2.15 is not a particularly difficult computation, seeing as I specifically added the extra twenty cents to avoid the borrow from the units position.

    But the salesclerk sat there and stared at the numbers for several seconds, unsure what to do next. I had to say, "$5.20 minus $2.15 is $3.05."

    Going shopping won't let you escape math.

  • The Old New Thing

    C# static constructors are called on demand, not at startup

    • 55 Comments

    One of the differences between C++ and C# is when static constructors run. In C++, static constructors are the first thing run in a module, even before the DllMain function runs.¹ In C#, however, static constructors don't run until you use the class for the first time. If your static constructor has side effects, you may find yourself experiencing those side effects in strange ways.

    Consider the following program. It's rather contrived and artificial, but it's based on an actual program that encountered the same problem.

    using System;
    using System.Runtime.InteropServices;
    
    class Program {
     [DllImport("kernel32.dll", SetLastError=true)]
     public static extern bool SetEvent(IntPtr hEvent);
    
     public static void Main()
     {
      if (!SetEvent(IntPtr.Zero)) {
       System.Console.WriteLine("Error: {0}", Trace.GetLastErrorFriendlyName());
      }
     }
    }
    

    This program tries to set an invalid event, so the call to SetEvent is expected to fail with an invalid handle error. We print the last error code using a function in this helper class: The details of this method aren't important. In fact, for illustrative purposes, I'm going to skip the call to FormatMessage and just return an ugly name.²

    class Trace {
     public static string GetLastErrorFriendlyName()
     {
      return Marshal.GetLastWin32Error().ToString();
     }
    }
    

    Run this program, and you should get this output:

    Error: 6
    

    Six is the expected error code, since that is the numeric value of ERROR_INVALID_HANDLE.

    You don't think much of this program until one day you run it and instead of getting error 6, you get something like this:

    Error: 126
    

    What happened?

    While you weren't paying attention, somebody decided to do some enhancements to the Trace class, maybe added some new methods and stuff, and in particular, a static constructor got added:

    class Trace {
     public static string GetLastErrorFriendlyName()
     {
      return Marshal.GetLastWin32Error().ToString();
     }
    
     [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)]
     public static extern IntPtr LoadLibrary(string dll);
     static Trace() { LoadLibrary("enhanced_logging.dll"); }
    }
    

    It's not important what the static constructor does; the point is that we have a static constructor now. In this case, the static constructor tries to load a helper DLL which presumably does something fancy so we can get better trace logging, something like that, the details aren't important.

    The important thing is that the constructor has a side effect. Since it uses a p/invoke, the value of Marshal.GetLastWin32Error() is overwritten by the error code returned by the LoadLibrary, which in our case is error 126, ERROR_MOD_NOT_FOUND.

    Now let's look at what happens in our program.

    First, we call SetEvent, which fails and sets the Win32 error code to 6. Next, we call Trace.GetLastErrorFriendlyName, but wait! This is the first call to a method in the Trace class, so we have to run the static constructor first.

    The static constructor tries to load the enhanced_logging.dll module, and it fails, setting the last error code to 126. This overwrites the previous value.

    After the static constructor returns, we return to our program already in progress and call Trace.GetLastErrorFriendlyName, but it's too late. The damage has been done. The last error code has been corrupted.

    And that's why we get 126 instead of 6.

    What's really scary is that problems with static constructors running at inopportune times are often extremely hard to identify. For one thing, there is no explicit indication in the source code that there's any static constructor funny business going on. Indeed, somebody could just recompile the assembly containing the Trace class without modifying your program, and the problem will rear its head. "But I didn't change anything. The timestamp on program.exe is the same as the one that still works!"

    A side effect you might not consider is synchronization. If the static constructor takes any locks, you have to keep an eye on your lock hierarchy, or one of those locks might trigger a deadlock. This is insidious, because you can stare at the code all you want; you won't see anything. You'll have a method like

    class Trace {
     ...
     public static string GetFavoriteColor() { return "blue"; }
    }
    

    and yet when you try to step over a call to Trace.GetFavoriteColor, your program hangs! "This makes no sense. How can Trace.GetFavoriteColor hang? It just returns a constant!"

    Another factor that makes this problem baffling is that the problem occurs only the first time you call a method in the Trace class. We saw it here only because the very first thing we did with Trace was display an error. If you happened to call, say, Trace.GetFavoriteColor() before calling Trace.GetLastErrorFriendlyName(), then you wouldn't have seen this problem. In fact, that's how the program that inspired today's entry stumbled across this problem. They deleted a call into the Trace class from some unrelated part of the program, which meant that the static constructor ran at a different time than it used to, and unfortunately, the new time was less hospitable to static construction.

    "I'm sorry, did I call you at a bad time?"

    Footnotes³

    ¹This is not strictly true. In reality, it's a bit of sleight-of-hand performed by the C runtime library.⁴

    ²For a less ugly name, you can use this class instead:

    class Trace {
     [DllImport("kernel32.dll", SetLastError=true)]
     public static extern IntPtr LocalFree(IntPtr hlocal);
    
     [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)]
     public static extern int FormatMessage(int flags, IntPtr unused1,
        int error, int unused2, ref IntPtr result, int size, IntPtr unused3);
     static int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
     static int FORMAT_MESSAGE_IGNORE_INSERTS  = 0x00000200;
     static int FORMAT_MESSAGE_FROM_SYSTEM     = 0x00001000;
    
     public static string GetLastErrorFriendlyName()
     {
      string result = null;
      IntPtr str = IntPtr.Zero;
      if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                        FORMAT_MESSAGE_IGNORE_INSERTS  |
                        FORMAT_MESSAGE_FROM_SYSTEM, IntPtr.Zero,
                        Marshal.GetLastWin32Error(), 0,
                        ref str, 0, IntPtr.Zero) > 0) {
       try {
        result = Marshal.PtrToStringAuto(str);
       } finally {
        LocalFree(str);
       }
      }
      return result;
     }
    }
    

    Note that there may be better ways of accomplishing this. I'm not the expert here.

    ³Boring footnote symbols from now on. You guys sure know how to take the fun out of blogging. (I didn't realize that blogs were held to academic writing standards. Silly me.) Now you can go spend your time telling Scoble that he wrote a run-on sentence or something.

    ⁴Although this statement is written as if it were a fact, it is actually my interpretation of how the C runtime works and is not an official position of the Visual Studio team nor Microsoft Corporation, and that interpretation may ultimately prove incorrect. Similar remarks apply to other statements of fact in this article.

    Postscript: Before you start pointing fingers and saying, "Hah hah, we don't have this problem in Win32!"—it turns out that you do! As we noted in the introduction, static constructors run when the DLL is loaded. The granularity in Win32 is not as fine, being at the module level rather than the class level, but the problem is still there. If you use delay-loading, then the first call to a function in a delay-loaded DLL will load the target DLL, and its static constructors will run, possibly when your program wasn't expecting it.

  • 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

    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