March, 2009

  • The Old New Thing

    2009 Q1 link clearance: Microsoft blogger edition

    • 10 Comments

    It's that time again: Sending some link love to my colleagues.

    Updates: Fixed name of product Microsoft Expression (no "s"). Also, I think Arvin's blog is still up—it's just being masked by a doppelganger. Will update as information becomes available.

  • The Old New Thing

    Freudian typo? The spinlock

    • 11 Comments

    I was typing up a document and somehow accidentally misspelled spinlock as sinlock.

    I was tempted to leave it.

  • The Old New Thing

    What is the implementation of WM_PRINTCLIENT?

    • 26 Comments

    Via the suggestion box, Martin Filteau asks

    Could you explain the implementation of WM_PRINTCLIENT?

    It seems that even MS got it wrong in the LISTBOX control.

    Try to AnimateWindow a window that as a LISTBOX control as a child. The LISTBOX displays correctly if it is NOT empty. However, if it is empty... nothing is drawn.

    I got a similar problem when embedding an Internet Explorer control.

    Thanks.

    -mf

    As I noted back in 2003, the implementation of WM_PRINTCLIENT is the same as that of WM_PAINT. In particular, the implementation of WM_PRINTCLIENT for an empty window is... to paint nothing. That's why the window is empty.

    In other words, the listbox control is correct to draw nothing when it is empty. To draw the empty set, you draw nothing!

    Let's make some changes to the scratch program to show that animating a window with an empty listbox as a child works just fine.

    BOOL
    OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
    {
        RECT rc;
        GetClientRect(hwnd, &rc);
        g_hwndChild = CreateWindow(
            TEXT("listbox"), NULL, WS_CHILD | WS_VISIBLE | WS_TABSTOP,
            0, 0,
           (rc.right - rc.left)/2, rc.bottom - rc.top,
           hwnd, (HMENU)1, g_hinst, 0);
    
        return TRUE;
    }
    
    BOOL
    InitApp(void)
    {
        ...
        wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
        ...
    }
    
    int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev,
                       LPSTR lpCmdLine, int nShowCmd)
    {
        ...
            // ShowWindow(hwnd, nShowCmd);
            AnimateWindow(hwnd, 2000, AW_VER_POSITIVE);
        ...
    }
    

    Just to emphasize that the white background in the listbox is really being drawn by the listbox's WM_ERASEBKGND handler and isn't just leftover pixels from its parent window, I've positioned the listbox so it covers only half of the parent window and set the parent window's background to the application workspace color. (If your application workspace color is the same as the window color, then set the parent background color to something else. I can't believe I had to write that.)

    With that simple set-up, we ask AnimateWindow to show our window, and specify a custom animation time so it's easier to see that the color is correct throughout the entire animation. The listbox child window does appear correctly: All you get is the window background. Nothing is drawn. just like it's supposed to be.

    (This particular entry falls into another category of frustrating comment: The comment that claims that something doesn't work when it does, and forces me to write a test program to prove it.)

  • The Old New Thing

    I drive a car the way most people use a computer

    • 82 Comments

    It was interesting to me reading the reactions to my adventures driving a manual transmission. People seemed to be spending a lot of time trying to convince me that if only I were to expend a bit more effort in learning the finer points of driving a manual transmission and log enough time behind the wheel, then the activity will become less taxing on my mental brainpower.

    But why should I care?

    To me, driving is not an end in itself. It is just a tool for solving the problem of getting from point A to point B. The less I have to learn about how to accomplish this task the better.

    My goal is not to become a car expert. My goal is to get to my destination conveniently. I don't want to "have greater control over the experience"; I don't want "more power"; heck, depending on where I'm going, I often prefer to take the bus, where I have no control over the experience at all!

    It occurred to me as I read commenter after commenter try to convince me that my own personal priorities were incorrect that I drive a car the same way most people use a computer. They don't want to know about the difference between ROM and RAM or how many floppy disks you can store in a 6 megabit cable modem. They just want to surf the web, send email, and look at pictures of their grandchildren. (Okay, they may want to do other stuff too, but knowing the difference between PIO and DMA is definitely not on the list.)

    There's no point trying to get these people to learn all these details about how computers work because they don't care. They just want to know where they need to click to see that picture of baby Annie. You can even tell them that the way they're doing it is suboptimal and there's a much more powerful way to view those pictures which also gives them the ability to alter the gamma curve and apply the correct color adjustment to the image to match their monitor's color temperature, but they won't care.

    And I don't blame them. Because I don't care either.

  • The Old New Thing

    The inability to lock someone out of the registry is a feature, not a bug

    • 31 Comments

    There is no way to lock the registry. Whereas you can open a file with a deny all sharing mode to prevent anyone else from opening the file, the registry has no such provision. You can't lock a registry key and prevent others from reading from or writing to it. There is an internal lock on the registry, but that's just to ensure that registry operations are atomic; that is, that if one thread writes a value to the registry and another thread reads that same value from the registry, then the value that comes back is either the value before the write took place or the value after the write took place, but not some sort of mixture of the two.

    Some people consider the inability to lock the registry to be a bug but it's actually a feature. It means that nobody can launch a denial of service attack against the registry by opening a key in an exclusive mode and preventing anybody else from reading it. This is important, because many security settings are stored in the registry, and locking somebody out of a registry key means that the part of the operating system whose job it is to enforce the security of a particular feature would no longer be able to check whether the operation is allowed.

    This all means that if you're reading from the registry, you have to accept that the contents can change while you're reading them, in the same way that you have to accept that the file system can change. If you're writing to the registry, you can take advantage of transactional registry support new to Windows Vista.

  • The Old New Thing

    Caption contest: The pinball machine

    • 56 Comments

    I may regret this, but here's something new: A caption contest. One of my colleagues saw this picture on a company's Web site.

    Pinball machine with flipper about to strike ball.

    The original caption for this picture was something like Join our affiliate program or Score big with our affiliate program. Your mission is to come up with something funnier. Here are some ideas to get you started:

    • Do you have balls of steel? Maybe you can become an affiliate.
    • We love to flip off our affiliates.
    • When you become an affiliate, you're going to get whacked around a lot.
    • Sooner or later you'll end up in the hole.
    • We like to play games with you. Become an affiliate today!

    Now it's your turn. Keep it friendly.

  • The Old New Thing

    Double secret auto-arrange probation

    • 35 Comments

    When you view a folder for the first time, Explorer arranges the items in a nice default pattern. And when items are added to the folder, they get added to the end. And when you delete an item from the folder... the other items auto-arrange to close the gap? But wait, if you look at the View options, the Auto-Arrange option is not set.

    So are we auto-arranging or not auto-arranging?

    Well, yes, but only until you touch it.

    As long as you express no interest in the placement of icons in a folder (and the desktop counts as a folder), then Explorer will auto-arrange them. But once you move an icon around, Explorer will turn off its double secret auto-arrangement and leave the icon arrangement to you.

    (Programmatically, this mode is known as LVS_EX_AUTOAUTOARRANGE.)

  • The Old New Thing

    What's the point of the MoveWindow function when we already have SetWindowPos?

    • 36 Comments

    Commenter Phil Quirk notes via the suggestion box, "MoveWindow is just a weird function. I guess it's easier to call than SetWindowPos, but that's the only thing it seems to have going for it."

    Yup, that's about right.

    The MoveWindow function doesn't really do anything you couldn't already do yourself with SetWindowPos. It's just a convenience function. And it you look at it pretty closely, it's really not that big of a convenience either, saving you one parameter (hwndInsertAfter) and replacing the flag SWP_NOREDRAW with a boolean parameter.

    Whoop-dee-doo.

    It shouldn't take too much imagination to figure out how this situation came about. It's the same reason why you have both CreateWindow and CreateWindowEx.

  • The Old New Thing

    How to write like Raymond: Intentional typographical errors

    • 32 Comments

    I'm a pretty good speller. If I want to show impatience, I will type very fast and make no attempt to fix the typographical errors. Here's an example: Somebody asked me what the correct name is for a particular user interface element.

    i don't nkow. call up the online hep and see what the ycall it.

    It may surprise you to know that I am not part of the committee that decides on the names for all user interface elements. If you want to know the correct name for a user interface element (for example, the Start menu), you don't need to ask me. You can look it up yourself: It's in the help.

    The list of agreed-upon names for user interface elements is given to the help authoring team so they can use those correct terms in the help files, and the editors in the help authoring team use that list to ensure that all the terminology is used correctly.

    Therefore, if you want to look up the correct name for a user interface element, you can look for it in the help system, because the help system has editors who check these things.

  • The Old New Thing

    Defense in depth means that you protect against exploits that don't exist yet

    • 27 Comments

    Defense in depth is about protecting against threats that are already being protected against, just in case the existing protection fails. This is why there is not merely a lock on your safety deposit box, but also a lock on the door to the safety deposit box room, and then a lock on the doors of the bank itself. This is why you wear your seat belt even though the car is equipped with air bags. This is why factories have multiple safety systems. It's why, when you put away a gun, you set the safety and remove the ammunition and lock the gun case.

    An insistent anonymous commenter refused to believe in this principle and couldn't distinguish between the absence of a known security vulnerability and the potential for one, believing that security is a boolean value, that you're either secure or you're insecure, and that if two systems are identical except that the second system has an additional safety check, this is proof that the first system must have been insecure.

    As I described in the comments to the article, there is the potential for bad things to happen if a COM data object is allowed into the process. Even though the CSRSS process never calls any of the potentially dangerous functions in a dangerous way, the potential for some other flaw to result in dangerous behavior creates enough risk that the trade-off tipped toward removing the potential for problems, even though the potential is currently (and hopefully will always remain) unrealized.

    Remember that one of the guidelines of security is that the more valuable the target, the more effort you put into securing it. In this case, CSRSS runs with System security privileges, which is even higher than Administrator. You want to erect a lot of barriers for this puppy.

    It's like a hospital that has the rule "No cell phones allowed in hospital rooms because they may interfere with the equipment." The staff instruct you to leave your phone outside, but you insist that your phone does not pose a problem because it's turned off, and besides, it doesn't use the same radio frequency as the monitoring equipment. Tough. Defense in depth. Even if it's turned off, even if uses a different radio frequency, they won't let it into the room.

    The same thing is true with data objects. CSRSS is careful to extract only the information it needs, but that's like walking into a hospital room with a cell phone whose antenna has been switched off. Sure, the antenna is off, but somebody might bump into you and accidentally turn it on, or there may be some software flaw in the phone that causes it to turn on spontaneously. Sure, you might argue that those failures aren't your fault, so you shouldn't be blamed for them, but try telling that to the person whose monitoring equipment failed to notify the hospital staff of an irregular heartbeat.

    People who study security vulnerabilities have quite a wide array of tricks available to them once they find even the tiniest crack. Even something as simple as a null pointer fault (in itself just a denial of service and not a source of pwnage) can be combined with other techniques and become a full-fledged exploit.

    For example, even though your cell phone antenna is off, its Bluetooth transceiver may still be on, and somebody might be able to hack into your Bluetooth headset and convince it to tell the cell phone, "Hey, I'd like to make a call. Please turn on your antenna." Even though this is a security flaw in the Bluetooth headset, it was used as a stepping stone into hacking your cell phone.

    There's also the possibility that you simply forgot that you had set a text message for delayed delivery, causing the phone to turn on its antenna when the delivery time is reached. Oops. You messed up, and now somebody is intensive care.

    As of this writing, there is no known exploit for drag and drop into console windows, but since drag and drop uses highly extensible technology (namely COM and data objects), the possibility that one of those extension points may be used as an attack vector was deemed too great a risk compared to the benefit of the feature. The anonymous commenter concludes,

    Now if this is not a security hole, then either Csrss doesn't execute code in OLE objects it receives, or it doesn't accept any OLE objects received, or isn't able to receive OLE objects at all. Which one is it?

    CSRSS does not execute untrusted code in OLE objects it receives, but the fact that OLE objects are in the CSRSS process at all give the security folks the heebie-jeebies. Although there is no known security hole, there is great potential for a security hole, and that's the reason for removing the potentially dangerous code from CSRSS even though it is (in theory) never executed.

    I bet you'd be nervous if somebody pointed a loaded gun at you even though the safety is engaged.

    Other discussion of defense in depth, including more examples:

Page 1 of 4 (33 items) 1234