December, 2012

  • 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

    You too can use your psychic powers: Spaces in paths

    • 29 Comments

    I'm going to be lazy today and make you solve the problem.

    Did a recent security hotfix change change the way we handle UNC paths with spaces? Normally, if we open the Run dialog and type \\server\share\Support Library\, the Support Library folder opens. But recently it stopped working. Instead of opening the Support Library folder, we get the Open With dialog:

    Open with

    Choose the program you want to use to open this file:

    File: Support

      Contoso Chess Challenger 5.0
      Contoso Music Studio
      Fabrikam Chart 2.0
      Litware 2010
    $   Woodgrove Bank Online
     
     
     
     
     
     
     
      Happy Holidays!
     
     
     
     
     
      Always use the selected program to open this kind of file

     

    Can you figure out what happened recently that introduced this problem? You have all the information you need.

  • 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
  • The Old New Thing

    Why do some shortcuts not support editing the command line and other properties?

    • 27 Comments

    Ben L observed that some shortcuts do not permit the command line and other options to be edited. "Where is this feature controlled? Is there a way to override this mode?" This question is echoed by "Anonymous (Mosquito buzzing around)" (and don't think we don't know who you are), who in a huge laundry list of questions adds, "Why does the Game Explorer limit customizing command line, target, etc?"

    These questions are looking at the situation backwards. The issue is not "Why do these shortcuts block editing the command line?" The issue is "Why do some shortcuts allow editing the command line?"

    Recall that shortcuts are references to objects in the shell namespace. Shell namespace objects are abstract. Some of them refer to files, but others refer to non-file objects, like control panels, printers, and dial-up networking connectoids. And in the abstract, these objects support verbs like Open and Rename. But there is no requirement that a shell namespace object support "Run with command line argument".

    If you have a shortcut to an executable, then the LNK file handler says, "Okay, this is a special case. Executables support command line arguments, so I will run the executable with the command line arguments set by the IShell­Link::Set­Arguments method.

    Note that the shortcut target and arguments are separate properties. The LNK file property sheet hides this from you by calling IShell­Link::Get­Path and IShell­Link::Get­Arguments, then taking the two strings and combining them into a single Target field for display. When you save the changes, the LNK file property sheet takes the Target, figures out which part is the executable and which part is the arguments, and calls IShell­Link::Set­Path and IShell­Link::Set­Arguments on the two parts.

    In other words, the command line is all a ruse.

    This special action is performed only for executable targets, because those are the only things that accept arguments. If you create a shortcut to a control panel, you'll find that the Target is not editable. If you create a shortcut to a printer, you'll find that the Target is not editable. If you create a shortcut to a dial-up networking connectoid, you'll find that the Target is not editable. Having a non-editable command line is the normal case. The file system is the weirdo.

    Shortcuts to advertise applications and shortcuts to items in the Games folder are not shortcuts to executables. They are shortcuts into the shell namespace for various types of virtual data. An advertised application is a shell namespace object that represents "an installed application". It is not a pointer directly to the executable, but rather a reference to an entry in the MSI database, which in turn contains information about how to install the program, repair it, update it, and run it. The shell doesn't even know what the command line is. To launch an advertised shortcut, the shell asks the MSI database for the command line, and it then executes that command line that MSI returns. The value set by IShell­Link::Set­Arguments never enters the picture. Similarly, the entries in the Games Folder are not executables; they are entries in the games database.

    I can see how this can be confusing, because when you click on these shortcuts, a program runs, but these shortcuts are not shortcuts directly to programs. As a result, the code that takes a Target and Arguments and combines them into a command line does not get a chance to run.

  • 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

    Have you found any TheDailyWTF-worthy code during the development of Windows 95?

    • 25 Comments

    Mott555 is interested in some sloppy/ugly code or strange workarounds or code comments during the development of Windows 95, like "anything TheDailyWTF-worthy."

    I discovered that opening a particular program churned the hard drive a lot when you opened it. I decided to hook up the debugger to see what the problem was. What I discovered was code that went roughly like this, in pseudo-code:

    int TryToCallFunctionX(a, b, c)
    {
      for each file in (SystemDirectory,
                        WindowsDirectory,
                        ProgramFilesDirectory(RecursiveSearch),
                        KitchenSink,
                        Uncle.GetKitchenSink)
      {
        hInstance = LoadLibrary(file);
        fn = GetProcAddress(hInstance, "FunctionX");
        if (fn != nullptr) {
            int result = fn(a,b,c);
            FreeLibrary(hInstance);
            return result;
        }
        fn = GetProcAddress(hInstance, "__imp__FunctionX");
        if (fn != nullptr) {
            int result = fn(a,b,c);
            FreeLibrary(hInstance);
            return result;
        }
        fn = GetProcAddress(hInstance, "FunctionX@12");
        if (fn != nullptr) {
            int result = fn(a,b,c);
            FreeLibrary(hInstance);
            return result;
        }
        fn = GetProcAddress(hInstance, "__imp__FunctionX@12");
        if (fn != nullptr) {
            int result = fn(a,b,c);
            FreeLibrary(hInstance);
            return result;
        }
        FreeLibrary(hInstance);
      }
      return 0;
    }
    

    The code enumerated every file in the system directory, Windows directory, Program Files directory, and possibly also the kitchen sink and their uncle's kitchen sink. It tries to load each one as a library, and sees if it has an export called FunctionX. For good measure, it also tries __imp__­FunctionX, FunctionX@12, and __imp__­FunctionX@12. If it finds any match, it calls the function.

    As it happens, every single call to Get­Proc­Address failed. The function they were trying to call was an internal function in the window manager that wasn't exported. I guess they figured, "Hm, I can't find it in user32. Maybe it moved to some other DLL," and went through every DLL they could think of.

    I called out this rather dubious programming technique, and word got back to the development team for that program. They came back and admitted, "Yeah, we were hoping to call that function, but couldn't find it, and the code you found is stuff we added during debugging. We have no intention of actually shipping that code."

    Well, yeah, but still, what possesses you to try such a crazy technique, even if only for debugging?

  • The Old New Thing

    What is so special about the instance handle 0x10000000?

    • 12 Comments
    A customer wanted to know what it means when the Load­Library function returns the special value 0x10000000.

    Um, it means that the library was loaded at 0x10000000?

    Okay, here's some more information: "We're trying to debug an application which loads DLLs and attempts to hook their registry accesses when they call Dll­Register­Server. It looks like when the special handle is returned from Load­Library, the registry writes go through and bypass the hook. On the other hand, when a normal value is returned by Load­Library, the hook works."

    There is nothing special about the value 0x10000000. It's an address like any other address.

    At this point, your psychic powers might start tingling. Everybody who does Win32 programming should recognize that 0x10000000 is the default DLL base address assigned by the linker. If you don't specify a custom base address, the linker will base you at 0x10000000.

    Now things are starting to make sense. The DLL being monitored was probably built with the default base address. The value 0x10000000 is special not because of its numeric value, but because it matches the DLL's preferred address, which means that no rebasing has occurred. And this in turn suggests that there's a bug in the registry hooks if the DLL is loaded at its preferred address.

    The code in question was copied from a book, so now they get to debug code copied from a book.

    Wait, we're not finished yet.

    You may have answered the customer's question, but you haven't solved their problem.

    Hooking and patching DLLs like this is not supported. But what is supported is the Reg­Override­Predef­Key function. In fact, the Reg­Override­Predef­Key was designed specifically to solve this very problem:

    The Reg­Override­Predef­Key function is intended for software installation programs. It allows them to remap a predefined key, load a DLL component that will be installed on the system, call an entry point in the DLL, and examine the changes to the registry that the component attempted to make.

    The documentation continues, explaining how such an installation program might use the Reg­Override­Predef­Key function to accomplish the desired task.

  • 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

    2012 year-end link clearance

    • 12 Comments

    Another round of the semi-annual link clearance.

    Snark

    Tech

    Culture (or what passes for it)

    Other Stuff

    And, as always, the obligatory plug for my column in TechNet Magazine:

Page 1 of 3 (26 items) 123