January, 2008

  • The Old New Thing

    The dead home desktop problem returns


    The computer I bought not a year and a half ago decided to keel over last week. When I push the power button, the power light goes on, the drives spin up, but there is nothing out the video card and not even a reassuring beep from the power-on self test. I've disconnected all the external peripherals as well as all the IDE devices, and no change. The problem might be a fried motherboard connection or something. I'm not a hardware person, so I'm not sure how to diagnose it.

    This is easily the shortest life for a computer I've owned (not counting the ones that were dead on arrival). I feel kind of bad buying a replacement for a computer that's barely fifteen months old, but I also can't think of what else I can do. All the stuff I can easily swap out I think I've already swapped out. And I don't know if I can find a new power supply or motherboard that fits the custom case.

    So it's back down to Fry's to buy some random bottom-feeder computer just so I can whack my hard drives into it and get back in business. But man, is that machine going to inherit a lot of memory!

    (Then again, maybe my problem is that I keep buying bottom-feeder computers?)

  • The Old New Thing

    Shell policy is not the same as security


    Mark Russinovich pointed out that if you let users run arbitrary programs, they can circumvent policies. This is actually not surprising, because policy is not the same as security.

    Shell policies control how Explorer and other shell components behave, but that's just blocking the front door. For example, there is a shell policy to prevent the user from changing the wallpaper from the Desktop control panel. This disables the controls on the Desktop control panel for changing the wallpaper, but there are ways to change the wallpaper other than that. If users can run an arbitrary program, then they can run a program that calls SystemParametersInfo(SPI_SETDESKWALLPAPER) to change the wallpaper directly, bypassing the shell. The purpose of the shell policies is merely to make it more difficult for users to perform various categories of operations by removing them from the shell interface. But, of course, if the users are allowed to write their own program with its own user interface, then they can still access the underlying functionality.

    Setting a policy to remove the user interface for a feature is like removing the staircase that leads to the second floor to keep people out. If you let them bring a ladder, then they can still get up there.

    Mark Russinovich points out that policies are enforced at the application level, and since applications run as the user, the user can run a program that commandeers the application and patches out the code that checks the policy setting.

    Shell policies are just for modifying the user interface. If you want to block an operation even from users who bypass the normal user interface, you have to block it at a level below the user interface. For example, you might revoke write permission to the relevant registry key; that way, even if the user manages to run their own code on the machine, they still can't change the underlying setting.

    Every so often, somebody who doesn't understand the difference between shell policy and security submits a security vulnerability report to MSRC saying, "Check this out, I can set the policy to prevent the user from changing the desktop wallpaper via the shell, but through this clever technique of injecting code into Explorer and patching the binary in memory, I can change the desktop anyway!" Well yeah, but why go to all that effort? Just write a program that changes the desktop wallpaper already.

  • The Old New Thing

    Even without a nitpicker's corner, I have to worry about nitpickers


    Even without a nitpicker's corner, I have to worry about nitpickers. I just have to do it in a more subtle way.

    Here are some examples of changes I've made to upcoming entries in order to forestall nitpicking:

    Original text Revised text Reason
    ... entries in our list... ... entries in our table... The entries are kept in an array, but writing "list" may cause some people to nitpick that an array is not a list.
    ... this function returns X... ... this function can be asked to return X... The function returns different things based on what the caller requests, but the only case we're interested in right now is the case of X.
    ... X affects only Y. ... X typically affects only Y. Again, I have to add the qualifier to protect against the case where a program intentionally broadens the scope of X.
    ... X isn't a problem because... ... X isn't usually a problem because... There can be cases where X is a problem because the program explicitly created the problem for itself, so I have to put in a qualifier. Indeed, later in the article I give an example of how a program can cause this problem, so I'd better leave myself some wiggle room at the expense of rhetorical power.
    ... a holiday.... ... a holiday in the United States... Otherwise somebody would make some smart-alec remark like "It's not a holiday where I live." [Typo fixed: 10am]
    ... the kernel .... ... the exception dispatch code... To avoid confusion between "the kernel" and "kernel mode".
    ... 64KB ... ... about 64KB... Because the limit is actually 65280 bytes.

    What's scary is that I've noticed that I begun pre-emptively nitpicking my own entries while I'm writing them. In the balance between writing something that reads more naturally and something that is more resiliant to nitpicking, I've unfortunately started preferring the latter.

    Observant readers may have noticed that I've slowly introduced a section called "Pre-emptive snarky comment" wherein I try to anticipate drive-by "Hey wouldn't it be hilarious if I ridiculed Microsoft on a Microsoft employee's blog?" comments. It seems to be largely successful, although sometimes people will post the identical snarky comment that I pre-empted. These are probably the people who talk just to enjoy the sound of their own voice.

    An extension of this is the "Now that you brought up something that sucks, I'm going to tell you that it sucks" phenomenon. This is pretty much guaranteed whenever I bring up anything that is related to UAC and security, since it appears that everybody agrees that UAC sucks, so any blog entry that talks about elevation invariably leads to comments about how UAC sucks. There are also popular tangents, such as any article that mentions installing software turning into a "post your complaints about setup here" thread.

    Some people are more indiscriminate and merely bash Vista whenever they get a chance, such as using a story about the psychology of how people fail to process information that they see to rant about how it's hard to copy text out of the event viewer.

    (That article about how people fail to process information that they see was indeed an unmitigated disaster. Everybody got into arguing over how the message should have been presented so the user would be more likely to see it, but that completely misses the point. The user positively confirmed, "I see the yellow warning." The problem wasn't that the user didn't see the message; the response confirmed that the user saw the message just fine. What the user didn't do was process the information. It's my fault for choosing a bad title. Instead of "People can't see things that are right in front of them," I should have titled it "People see things but don't pay attention to them," opting for precision even though it meant I couldn't use the idiomatic phrase can't see what's right in front of you. What made it worse is that I fell for the trap. I responded to the details instead of saying, "Whether your suggestion would have helped the user see the message or not is totally irrelevant to the point of the article.")

    I also hadn't predicted that my discussion of how reasonable people can disagree about how a setting should be exposed would turn into a discussion of how to shut down your computer, turning a footnote into the primary topic of discussion. But that's a fairly common occurrence: People focus on a side detail (which I added for color) and ignore the point of the story. Sometimes I think I'd be better off if I didn't give examples. That way nobody could be distracted by them.

  • The Old New Thing

    Microspeak: Housing


    The real estate department at Microsoft has their own weird jargon. In the real estate world, you don't "work" in a building; you are "housed" there. Here are a few citations.

    The new buildings will be able to house N workers.
    Employees housed at Facility X will be able to use temporary parking spaces being constructed at Location Y.
  • The Old New Thing

    The history of the Windows XP common controls


    In the beginning, there was one control library, namely USER, the window manager itself, which provided buttons, static controls, edit controls, scroll bars, list boxes, and combo boxes. These controls were under the purview of the window manager team.

    In Windows 3.1 a second control library known as the shell common controls was added, but the library really didn't come into it own until Windows 95, where it consisted of the list view, header, tree view, tooltip, toolbar, status bar, track bar, tab, updown, progress, hotkey, and animation controls. These controls were originally custom controls written by the shell team for use in Explorer, but since they seemed to be generally useful, time was budged to do the extra work to make the controls more suitable for general use, testing the controls in combinations and scenarios that Explorer itself didn't use, and putting together formal documentation.

    The shell common controls library underwent many changes over the years, whereas the core intrinsic controls in the window manager changed much more conservatively.

    With Windows XP, the visual design team wanted to give the look of Windows a new life. Changing the non-client area (such as the window frame) was comparatively straightforward, since programs didn't have much control over that part of the window anyway. As a result, they get the Windows XP look "for free".

    The client area is another story. Programs are in control of their client area, where they can place controls that come with Windows, their own custom controls, or controls obtained from a third party library. Making major changes to the core controls or the common controls would be a high-risk endeavor since there are thousands upon thousands of Windows program that not only use them, but use them in all sorts of crazy ways.

    The initial stab at resolving these two conflicting goals (making major changes to these controls to increase visual appeal and functionality while simultaneously not changing them to maintain compatibility) was to create a new DLL that would contain the "fancy new version" of the core controls as well as the shell common controls. The old DLLs USER32 and COMCTL32 stayed where they were, so that old programs continued to get the behavior they were expecting, and the new XP-style controls were placed in a DLL named UXCTRL.DLL. UX stands for user experience, which was the hot new buzzword at the time. To avoid name collision with the old style controls, the new controls got new names beginning with Ux. For example, the UXCTRL version of the button control was called UxButton.

    New features could be added to these new Ux controls with wild abandon without heed for backward compatibility since they were brand new controls. There was nothing they had to be compatible with. Explorer was changed to use these new controls instead of the old stodgy controls, and everything worked great.

    Or so it seemed.

    We thought we had cleverly sidestepped the backward compatibility problem by creating entirely new controls, but doing that created a whole new category of compatibility bugs. Even though it's completely undocumented and unsupported, programs like to grovel into the internal data structures of other programs or otherwise manipulate those programs' windows. In Explorer's case, it turns out that a lot of programs like to go spelunking around Explorer's window hierarchy and use functions like FindWindow and EnumChildWindows to find the object of their affections. For example, a program might use EnumChildWindows to enumerate all the child windows of an Explorer browser, and then use GetClassName and lstrcmpi(szClassName, TEXT("button")) to look for a specific control. In this example, the target was a button, but it could have been a list view or a tool bar. Since all the new XP-style controls were named things like UxButton and UxListView, these programs which looked for a button by comparing against the string "button" stopped working.

    Of course, there was no guarantee that Explorer would even use buttons at all; Explorer was completely within its rights to revamp its user interface. But that's not much consolation to the customers who paid good money for these programs, especially since magazine columnists are the types of people most likely to be running (or indeed even writing!) strange off-the-wall programs that pull these sorts of nasty stunts in the first place.

    Okay, so it is now a compatibility requirement that all the new window classes have the same names as their old counterparts. This created an impasse, since these controls needed to be created by dialog boxes, and therefore they had to be globally-registered window classes. But you can't have two global window classes with the same name, because that would create ambiguity over which one the caller was asking for.

    More brainstorming ensued, and a Plan C emerged. The common controls library would take advantage of side-by-side assemblies and use the application manifest to control which DLL a given window class name would resolve to. Thus was born a new DLL also called COMCTL32, but with a new version number—version 6. Old programs would get version 5.82 just like they did in Windows 2000. New programs would have to use a manifest to specify that they wanted version 6.

    Once again, the solution came with a new problem. Since the entire COMCTL32 library got split into two versions, this meant that there were two versions of the image list code. Whole new scenarios emerged, such as putting a version 5 image list in a version 6 tree view, or vice versa. (As the linked thread notes illustrates, not all of the problems with cross-version scenarios were caught in the initial release and had to wait for a service pack for the fix to become available.)

  • The Old New Thing

    Crackpots in computer security: Don't plug it in, man!


    Some time a few years ago, some folks on the security team were swapping crackpots stories, and this one somehow lodged in my mind. The story below is paraphrased, but the essense remains intact.

    "We had a crazy guy call into the security support line many years ago. He was going through a messy divorce and was convinced that his wife's lawyers were hacking into his computer in order to frame him, thereby gaining the upper hand during divorce proceedings. He wanted to know how to protect his computer against them. We played along and told him to keep the computer unplugged from the Internet, and he laughed a triumphant laugh and said condescendingly, 'They're coming in through the power lines, man! Don't you know anything?' Now, yeah, today we do have Internet access over the power lines, but still, that guy was crazy!"

  • The Old New Thing

    PLAY! A Video Game Symphony comes to Seattle


    Competing with the Miss America pageant for your Saturday evening attention is the Seattle performance of PLAY! A Video Game Symphony, featuring music from a large number of video games. Presumably, the music will have something to do with the accompanying video being projected on large screens.

    The description of the concert omits any mention of whether this is a cosplay event. Just saying.

  • The Old New Thing

    What counts as a talent nowadays?


    The annual Miss America Pageant struggles for survival tomorrow. And what makes it different from Donald Trump's Miss USA and Miss Universe is the talent competition. (Yes, Miss World also has a talent competition, but nobody in the United States pays any attention to Miss World, probably because of the aforementioned Donald Trump.)

    It's not that I go out of my way to watch these pageants, but if it's convenient, a bunch of us will get together to enjoy the festivities. During the opening parade of the Miss Universe pageant, we scream in horror at the hideous national costumes or the unflattering evening gowns. During the swimsuit Lifestyle and Fitness competition (Whom do they think they're kidding?) the women play the game "Real or Fake?" (I recuse myself from that game citing lack of expertise.) But my favorite part is always the talent competition.

    The talents are mostly musical, primarily singing, with a decent amount of instrumental performance—I enjoy these, particularly the instrumental ones, since I actually know something about the subject. The ones that aren't musical are dancing—I'm not particularly knowledgeable about dance and usually don't know what to make of the performance. Extremely rarely you'll encounter a dramatic reading (which to me feels like a cheat). As accomplished as the contestants are, these talents all feel kind of "squishy". (Indeed, back in the Regency era, the term accomplished was used to refer to proficiency at these sorts of talents, and it was an open secret that the reason for developing these skills was simply to secure a husband.) But where are the real talents?

    If only we had contestants demonstrating other talents like consensus building, project management, electronics repair, chicken plucking, or suitcase packing.

    Then again, maybe those things are really skills rather than talents.

  • The Old New Thing

    The classic start menu is even more classic than it looks


    In Windows 95, the Find option took its place on the Start menu between Settings and Help. In Windows 2000, the option was still there, but its name changed to Search, a name which persist today if you use the classic Start menu.

    When the menu option changed its name, the keyboard accelerator changed accordingly. Whereas Find used F as its accelerator, Search uses C. Here's a secret: The classic Start menu still responds to F as the keyboard accelerator for Search. The work to make this happen was undertaken as a concession to people who imprinted on the old Start menu and whose "muscle memory" still wants to press F to open what used to be the Find menu.

    The totally redesigned Start menu for Windows XP changed the keyboard model radically, but if you're still attached to your muscle memory, you can switch to the classic Start menu and keep using all the old keyboard shortcuts from Windows versions past.

  • The Old New Thing

    It's one thing to say "somebody should do this", but doing it is another matter


    A common response when I describe a programming error is, ""Programs should have to pass a test that includes testing for this case." The case could be a program mishandling a message, a program responding incorrectly to IUnknown::QueryInterface, whatever. But these suggestions fall into the same trap that I see when grading student essays: They're good with the what but very weak on the how.

    Saying "Somebody should do X" is easy, but without some sort of suggestion as to how that could be accomplished, the suggestion rarely gets off the drawing board. It's like saying "Somebody should solve world hunger."

    Let's look at that first example again. The topic at hand was window procedures which fail to pass unhandled messages to the DefWindowProc function. How would one "test for this"? Would the test walk through every code path in the program that creates a window, and then send each of those windows a fake WM_QUERYENDSESSION or a fake WM_APPCOMMAND message to see what happens? First of all, it's unclear how a test could exercise all the window-creation code paths of a program without insider knowledge of that program. Therefore, this test would have to be written by the authors of the program.

    Next, even if you sent the message and saw that the message was passed to the DefWindowProc function, that wouldn't actually prove that the message was handled properly. Maybe the window procedure for a window goes something like this:

     if (GetTickCount() / 1000 % 2) return 0;
     return DefWindowProc(hwnd, uMsg, wParam, lParam);

    Even if you managed to get this window created, if you send it a fake WM_QUERYENDSESSION, you'll catch the issue only half the time. It's not enough just to exercise every window procedure; you also have to exercise every code path.

    But wait, there's more. What if the program really wanted to prevent the user from logging off?

     if (FileHasBeenEditedSinceLastSave()) {
      switch (MessageBox(hwnd,
                 TEXT("Save changes before exiting?"),
                 TEXT("Title"), MB_YESNOCANCEL)) {
      case IDYES: Save(); break;
      case IDCANCEL: return 0; // user cancelled logoff
     return DefWindowProc(hwnd, uMsg, wParam, lParam);

    In this case, there is a code path that cancels the logoff, and it is legitimate, since it was done as the result of a user decision. Your test would somehow have to know this and consider that case to be a pass and not a failure. This sort of reasoning is hardly something that a generic test suite can do; it has to be tailored for each program.

    It's one thing to say that something should be tested, but without an idea as to how it should be tested, the suggestion is much less valuable. I may as well say, "Programs should have to pass a test that verifies that there are no bugs."

Page 1 of 4 (35 items) 1234