December, 2012

  • The Old New Thing

    Why do I sometimes get classic buttons and sometimes themed buttons depending on the host process?

    • 20 Comments

    A customer reported that their printer configuration property sheet page looked different depending on the host process. In some processes, the printer configuration dialog had the classic look of Windows 2000, but in other processes it has the themed look of Windows XP and later versions.

    The printer driver calls the Create­Property­Sheet­PageW to create the property sheet page that contains the push-button, radio-button, and other controls. We've confirmed that we call the function with the same parameters each time, but the results are different depending on which program is doing the printing. We've confirmed that both applications are using version 6.0 of the common controls library. Can you provide pointers for investigating why we are getting the old-school look sometimes?

    It's clear that the problem is that the property sheet page is being created with a different activation context depending on the host process. If the activation context is a v6 context, then you get the themed buttons; if the activation context is a v5 context, then you get the classic buttons. The fact that version 6.0 of the common controls library is loaded by the process is not relevant; what's relevant is which version is active at the time the dialog is created, since that's the time the class names are resolved.

    If the problem were with a regular dialog box, then you can explicitly activate the v6 context before calling Dialog­Box, or you can use isolation awareness to have the activation code generated for you.

    However, the case here is a property sheet page. Since property sheet pages are created on demand (when the user selects the page), you don't have direct control over the code that calls Dialog­Box in order to activate your v6 manifest. Instead, use the hAct­Ctx member of the PROP­SHEET­PAGE structure and set the PSP_USE­FUSION­CONTEXT flag in the dwFlags.

    Trivia: Fusion was the code name for the feature which includes things like isolated applications, application manifests and redirection files. And because they were apparently a bunch of nerds (quelle surprise!) they named the initial version Hydrogen.

  • The Old New Thing

    Why doesn't SHGetKnownFolderPath return the customized path?

    • 23 Comments

    A customer reported that the SHGet­Known­Folder­Path function was not working correctly. They moved their Videos folder to a new location, but when they called SHGet­Known­Folder­Path, they got the old path rather than the new one.

    A quick check of the code they provided showed why:

     ...
     SHGetKnownFolderPath(FOLDERID_Videos,
                          KF_FLAG_DONT_VERIFY |
                          KF_FLAG_DEFAULT_PATH,
                          NULL,
                          &pszPath);
    

    Um, you're passing the KF_FLAG_DEFAULT_PATH flag. That flag means "Tell me where this folder would have been if its location had never been customized." Therefore, if you pass this flag, you have no right to complain that it's returning a path different from the customized path. Because passing that flag means "I don't want the customized path."

  • The Old New Thing

    Why was Pinball removed from Windows Vista?

    • 115 Comments

    Windows XP was the last client version of Windows to include the Pinball game that had been part of Windows since Windows 95. There is apparently speculation that this was done for legal reasons.

    No, that's not why.

    One of the things I did in Windows XP was port several millions of lines of code from 32-bit to 64-bit Windows so that we could ship Windows XP 64-bit Edition. But one of the programs that ran into trouble was Pinball. The 64-bit version of Pinball had a pretty nasty bug where the ball would simply pass through other objects like a ghost. In particular, when you started the game, the ball would be delivered to the launcher, and then it would slowly fall towards the bottom of the screen, through the plunger, and out the bottom of the table.

    Games tended to be really short.

    Two of us tried to debug the program to figure out what was going on, but given that this was code written several years earlier by an outside company, and that nobody at Microsoft ever understood how the code worked (much less still understood it), and that most of the code was completely uncommented, we simply couldn't figure out why the collision detector was not working. Heck, we couldn't even find the collision detector!

    We had several million lines of code still to port, so we couldn't afford to spend days studying the code trying to figure out what obscure floating point rounding error was causing collision detection to fail. We just made the executive decision right there to drop Pinball from the product.

    If it makes you feel better, I am saddened by this as much as you are. I really enjoyed playing that game. It was the location of the one Windows XP feature I am most proud of.

    Update: Hey everybody asking that the source code be released: The source code was licensed from another company. If you want the source code, you have to go ask them.

  • The Old New Thing

    2012 års Gävlebock gick upp i brand. Igen.

    • 15 Comments

    The town of Gävle in Sweden erects a large straw goat every year. The Yule Goat is a Scandinavian tradition, but the Gävle goat (Gävlebocken in Swedish) is by far the most famous, or perhaps the most notorious, because it has been the center of conflict from its very beginning, and over the years since its first appearance in 1966, it has only gained more notoriety. (For something that is supposed to bring people together, it sure does a good job of dividing them.)

    The first conflict is between those who want the goat to last the entire season and those who want it to be lit on fire. (And anecdotal evidence suggests that a large number of Swedes are in the second category.) It is such a big deal that you can place bets on whether the goat will survive or what day it will succumb to flames.

    The second conflict is between the Southern Merchants organization, who built the Yule Goat in its initial years but gave up out of frustration over the repeated arson, and the Natural Science Club (Natur­veten­skap­liga För­ening­en) of the School of Vasa, who took up the tradition, even though their goats didn't fare much better. The Southern Merchants resumed constructing a Yule Goat, leading to a bitter rivalry between the two groups.

    Wikipedia has a rundown of the goat's fate every year since its inception, including its burning in 2001 by a tourist from the United States who claims that he intended only to burn one piece of straw but was unable to stop the spread of the flames. (The article in Afton­bladet is far more insightful than any of the other reports I've seen, despite the fact that Afton­bladet is a tabloid. Unfortunately, as far as I can tell, the article is available only in Swedish.)

    The Gävle goat blogs and tweets in both Swedish and English.

    And for those keeping score: On the evening of December 12, the 2012 Yule Goat of Gävle went up in flames.

    Ursprunglig titel: "Den 2012 Gävlebocken gick upp i brand. Igen." Korrigerad efter kommentar från BOFH. Jag var så orolig om jag skulle använda "upp i brand" eller "upp i eld" att jag förbisåg andra fel... Tack.

  • The Old New Thing

    Like the cake, WS_EX_TRANSPARENT is a lie, or at least not the entire truth

    • 4 Comments

    There is an extended window style known as WS_EX_TRANSPARENT. Explaining what this style does is kind of difficult, but it's been on the list of future topics since 2003. Better late than never, I guess.

    First of all, there are two unrelated senses of transparent in play. One is visual transparency: Pixels beneath the window can show through. The other is hit-test transparency: Do clicks on this window go to the window, or do they pass through to the window beneath?

    And each of those senses of transparent is itself complicated.

    Let's look a hit-test transparency first. We saw some time ago that It's Complicated. Different hit-testing functions use different methods of determining whether a click should be given to a window or pass through it. And the WS_EX_TRANSPARENT extended window style plays into some of those rules. I'll let you read the linked article to learn the details.

    Okay, now to visual transparency. The WS_EX_TRANSPARENT extended window style alters the painting algorithm as follows: If a WS_EX_TRANSPARENT window needs to be painted, and it has any non-WS_EX_TRANSPARENT windows siblings (which belong to the same process) which also need to be painted, then the window manager will paint the non-WS_EX_TRANSPARENT windows first.

    That "lets the other windows paint first" behavior is what gave the style its name, because if you let the other windows paint first, and then you paint on top of it, then the parts you don't actually paint will appear to be transparent because the other windows' pixels will show through.

    Calling this painting style transparent is kind of overselling the feature. It's really a very specific behavior which makes transparent rendering sort of possible; it's not a just turn this on and you get transparent rendering feature.

    It's like taking a lump of coal and labeling it diamond. Or like those advertisements which say things like "Can create up to five million cups of coffee per day!"

    In order to turn the flour into a cake, the window with the WS_EX_TRANSPARENT window style needs to know not to draw opaquely. Because if it draws opaquely, then all the work the window manager did to get the other window to draw first (so you can draw on top of it) is for naught.

    And sometimes the WS_EX_TRANSPARENT window style doesn't even work. For example, observe that if the windows are not siblings of each other, then the style has no effect. If the windows belong to different processes, then the style has no effect. If both windows are not invalid simultaneously, then the style has no effect. (I don't know how you could get into that last state, but maybe you're more creative than I am.)

    Go ahead and use the WS_EX_TRANSPARENT window style if that's what you want. Just understand that it doesn't get you what the name might promise. (Depending on your situation, a layered window may work better.)

  • The Old New Thing

    Why is it possible to create a toolbar with the wrong HINSTANCE? And what's the right HINSTANCE anyway?

    • 5 Comments

    A customer observed that all of the following code fragments are successful in creating a toolbar common control:

    // Fragment 1: Use the process instance
        // Create the toolbar.
        HWND hWndToolbar = CreateWindowEx(
            0, TOOLBARCLASSNAME, NULL,
            WS_CHILD | TBSTYLE_WRAPABLE, 0, 0, 0, 0,
            hWndParent, NULL, g_hInst, NULL);
    
    // Fragment 2: Use the comctl32 instance
        // Create the toolbar.
        HWND hWndToolbar = CreateWindowEx(
            0, TOOLBARCLASSNAME, L"Toolbar", 
            WS_CHILD | WS_VISIBLE | WS_BORDER,
            0, 0, 0, 0,
            hWndParent, NULL, HINST_COMMCTRL, NULL);
    
    // Fragment 3: Use NULL!
        // Create the toolbar.
        HWND hWndToolbar = CreateWindowEx(
            0, TOOLBARCLASSNAME, NULL,
            WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
            hWndParent, NULL, NULL, NULL);
    

    Furthermore, the customer observed that Get­Class­Info(hinst, TOOLBAR­CLASS­NAME, &wc) works regardless of whether you pass the process instance or NULL for the hinst parameter.

    First of all, what's going on? And second of all, which of the three methods above is most correct?

    We can dispatch Fragment­3 easily, because passing NULL as the instance handle is equivalent to passing the process instance handle. Therefore, whatever happens in Fragment­3 is explained by whatever happens in Fragment 1. (Treating a NULL instance as a synonym for the process instance is a leftover behavior from 16-bit Windows, so I'm going to declare it a workaround for sloppy programming rather than a recommended practice. If you are doing this from the process module itself, then you already have your instance handle, so you should just use it. And if you are doing this from a DLL, then stop doing it, because you're messing with with somebody else's namespace.)

    The behavior of Fragment 2 is easy to explain: The class is registered against the comctl32 library, so naturally, if you create it from that library, you'll get the class.

    The last case is Fragment 1: Even though we passed the wrong instance handle, we still got the control from comctl32. We saw the explanation for this some time ago: In order to allow the common controls classes to be used in dialog templates, they are registered as CS_GLOBAL­CLASS. One could argue that this is the recommended way of creating the window, since it allows your application to superclass a common control by registering a private class with the same name in its own namespace. Only if a custom version is not found in the provided instance is the list of global classes consulted. (I'm not saying that I'm arguing that position, just that it is a valid position.)

    Okay, so the mystery of the instance handle has been solved. But why does Get­Class­Info return the class even when it's registered against some other instance?

    Because it found the class! Get­Class­Info uses the same search algorithm that Create­Window does, and it tells you the class it ultimately found. However, for compatibility reasons, the WNDCLASS.hInstance member is (usually) a copy of the HINSTANCE you passed to Get­Class­Info, regardless of where the class was ultimately found.

    The reason for this is that some applications pull tricks like this:

    WNDCLASS wc;
    GetClassInfo(hinstApp, "something", &wc);
    ... edit the WNDCLASS structure ...
    UnregisterClass("something", hinstApp);
    RegisterClass(&wc);
    

    Suppose that something is a global class and suppose that the WNDCLASS.hInstance were set to the instance of the module that registered the global class. The application then unregisters its private class and registers what it thinks is a replacement private class. But instead, it overwrites the global class.

    Oops.

    The compatibility fix for this is to return hinstApp in the WNDCLASS.hInstance member. That way, these programs are tricked into registering a private class rather than overwriting a global class.

  • The Old New Thing

    Why is it so hard to write a program that requires UI Access privilege?

    • 23 Comments

    If you want your program to have the UI Access privilege, you have to jump through a few hoops. The program needs to be digitally signed, and it needs to go into the system32 directory. Why is it so hard to get UI Access?

    Because UI Access bypasses User Interface Privilege Isolation (UIPI) security measures. The more valuable the target, the more substantial the security measures.

    UI Access allows low-integrity programs to access and interact with the user interface of high-integrity programs. This has historically been the source of security vulnerabilities. UIPI was created in part to prevent this type of security attack. If a low-integrity program could programmatically manipulate the user interface of a high-integrity program, then all an attacker needs to do is sit and wait for the user to elevate a command prompt, and then start programmatically driving the command prompt to do whatever it wanted.

    If all you had to do to obtain UI Access was simply ask for it (by setting uiaccess="true" in your manifest), then every piece of malware would just do that, and boom, the value of UIPI has effectively vanished. (This is the sort of trap that leads to eventually, nothing is special any more.)

    Okay, so the digital signature requirement is there to create a barrier to entry for malware authors. It also creates some degree of accountability (since you have to identify yourself to a certificate authority, though as we've seen in the past, this relies on certificate authorities remaining trustworthy), And it allows your application's ability to obtain UI Access to be revoked by revoking the certificate.

    But why does the file have to be in the system32 directory?

    As we saw some time ago, the directory is the application bundle. If programs with UI Access could be installed anywhere, then an attacker could exploit an insecure application directory to plant a rogue copy of a system DLL in that directory, allowing itself to be injected into the process with UI Access and thereby compromise it.

    The thinking here is "If the application cannot create its install directory, then the application cannot create its install directory wrong."

    Requiring progams with UI Access to be installed into the system32 directory is an additional secure by default measure. In order to compromise the application bundle, the attacker must already have compromised the system32 directory, at which point he's already on the other side of the airtight hatchway.

  • The Old New Thing

    How am I supposed to free the information returned by the GetSecurityInfo function?

    • 25 Comments

    The Get­Security­Info function returns a copy of the security descriptor for a kernel object, along with pointers to specific portions you request. More than once, a customer has been confused by the guidelines for how to manage the memory returned by the function.

    Let's look at what the function says:

    ppsidOwner [out, optional]
    A pointer to a variable that receives a pointer to the owner SID in the security descriptor returned in ppSecurity­Descriptor. The returned pointer is valid only if you set the OWNER_SECURITY_INFORMATION flag. This parameter can be NULL if you do not need the owner SID.

    Similar verbiage can be found for the other subcomponent parameters. The final parameter is described as

    ppSecurity­Descriptor [out, optional]
    A pointer to a variable that receives a pointer to the security descriptor of the object. When you have finished using the pointer, free the returned buffer by calling the Local­Free function.

    Okay, so it's clear that you need to free the security descriptor with Local­Free. But how do you free the owner, group, DACL, and SACL?

    Read the documentation again. I've underlined the important part.

    ppsidOwner [out, optional]
    A pointer to a variable that receives a pointer to the owner SID in the security descriptor returned in ppSecurity­Descriptor. The returned pointer is valid only if you set the OWNER_SECURITY_INFORMATION flag. This parameter can be NULL if you do not need the owner SID.

    In case that wasn't clear, the point is reiterated in the remarks.

    If the ppsidOwner, ppsidGroup, ppDacl, and ppSacl parameters are non-NULL, and the Security­Info parameter specifies that they be retrieved from the object, those parameters will point to the corresponding parameters in the security descriptor returned in ppSecurity­Descriptor.

    In other words, you are getting a pointer into the security descriptor. No separate memory allocation is made. The memory for the owner SID is freed when you free the security descriptor. It's like the last parameter to Get­Full­Path­Name, which receives a pointer to the file part of the full path. There is no separate memory allocation for that pointer; it's just a pointer back into the main buffer.

    You can think of the ppsidOwner parameter as a convenience parameter. The Get­Security­Info function offers to do the work of calling Get­Security­Descriptor­Owner for you. You can think of the function as operating like this:

    DWORD WINAPI GetSecurityInfo(...)
    {
        ... blah blah get the security info ...
    
        // Just out of courtesy:
        // Fetch the owner if the caller requested it
        if (ppsidOwner != NULL &&
            (SecurityInfo & OWNER_SECURITY_INFO)) {
            BOOL fDefaulted;
            GetSecurityDescriptorOwner(pSecurityDescriptor,
                                       ppsidOwner,
                                       &fDefaulted);
        }
    
        ...
    }
    

    That's why the documentation says that you need to pass a non-null ppSecurity­Descriptor if you request any of the pieces of the security descriptor: If you don't, then you won't be able to free the memory for it.

    Bonus chatter: If the ppSecurity­Descriptor is so important, why is it marked "optional"?

    It really should be a mandatory parameter, but older versions of Windows didn't enforce the rule, so the parameter is grandfathered in as optional, even though no self-respecting program should ever pass in NULL. If you pass NULL for the ppSecurity­Descriptor, the function happily allocates the security descriptor and then, "Oh wait, the caller didn't give me a way to receive the pointer to the security descriptor, so I guess I won't give it to him."

    DWORD WINAPI GetSecurityInfo(...)
    {
        ... blah blah get the security info ...
    
        if (ppSecurityDescriptor != NULL) {
            *ppSecurityDescriptor = pSecurityDescriptor;
        }
        ...
    }
    

    Result: Memory leak.

    You might say that the last parameter was designed by somebody wearing kernel-colored glasses.

  • The Old New Thing

    Microspeak: v-team

    • 15 Comments

    People who don't work at Microsoft but who are aware of its jargon might encounter the term v-team and guess that it's a team consisting of vendors, because the Microspeak term v-dash is used to refer to vendors (whose email addresses begin with v-).

    It's a good guess, but in this case, it's wrong.

    Tasks at Microsoft typically map to organizational boundaries. (Organizational boundaries having been chosen so that tasks fall nicely within them.) A memory management feature will be handled by the memory management team. A user interface feature will be handled by the user interface team. But there are some tasks that span teams, and for those cases, Microsoft managers like to create a virtual team, usually abbreviated v-team and pronounced vee team. (Not to be confused with the Virtualization Team.)

    The defining characteristic of a v-team is that the members of the v-team come from different parts of the organization. For example, you might have Alice from the Power Management team, Bob from the User Interface team, and Charlie from the Networking team working together to design cloud-based notifications. These people do not share the same immediate manager, but for the purpose of this feature, they've been plucked out of the tree and formed into a self-organizing team to solve a particular problem.

    Loren Ipsum
    Alice
    Bob
    Charlie
       
       
    ...
    ...
    ...
               
           
    ...
     
    ...
     
    Alice
     
    ...
    ...
     
    ...
    Charlie
     
                   
                         
    ...
    ...
    Bob
    ...
     
    ...

    These virtual teams are formed as needed and conversely are disbanded when no longer needed. Some may be short-lived, like a virtual team to review all the sample apps for the //build conference, which disbands once review is complete. Others may last for the duration of the project, like a virtual team to debug performance issues.

  • The Old New Thing

    I'll tell you what I think of the new University of California logo once it finishes loading

    • 20 Comments
    The new University of California logo
Page 2 of 3 (26 items) 123