May, 2011

  • The Old New Thing

    Your program loads libraries by their short name and you don't even realize it


    In the discussion of the problems that occur if you load the same DLL by both its short and long names, Xepol asserted that any program which loads a DLL by its short name "would have ONLY itself to blame for making stupid, unpredictable, asinine assumptions" and that Windows should "change the loader to NOT load any dll with a short name where the short name and long name do not match."

    The problem with this rule, well, okay, one problem is that you're changing the rules after the game has started. Programs have been allowed to load DLLs by their short name in the past; making it no longer possible creates an application compatibility hurdle.

    Second, it may not be possible to obtain the long name for a DLL. If the user has access to the DLL but not to one of the directories in the path to the DLL, then the attempt to get its long name will fail. The "directory you can access hidden inside a directory you cannot access" directory structure is commonly used as a less expensive alternative to Access Based Enumeration. Maybe your answer to this is to say that this is not allowed; people who set up their systems this way deserve to lose.

    Third, the application often does not control the path being passed to Load­Library, so it doesn't even know that it's making a stupid, unpredictable, asinine assumption. For example, the program may call Get­Module­File­Name to obtain the directory the application was installed to, then attempt to load satellite DLLs from that same directory. If the current directory was set by passing a short name to Set­Current­Directory (try it: cd C:\Progra~1) then the program will unwittingly be making a stupid, unpredictable, asinine decision. (But since the decision is being made consistently, there was no problem up until now.)

    When you call Co­Create­Instance, there is nearly always a Load­Library happening behind the scenes, because the object you are trying to create is coming from a DLL that somebody else registered. If they registered it with a short name, then any application that wanted to use that object runs afoul of the new rule, even though the application did nothing wrong.

    Now, you might argue that this just means that the component provider is the one who made a stupid, unpredicable, asinine assumption. But that may not have been a stupid assumption at the time: 16-bit applications see only short names, so it might have been that that's the only thing they can do. Or the component may have made a conscious decision to register under short names; this was common in the Windows 95 era because file names often passed through components that didn't understand long file names. (Examples: 16-bit applications, backup applications.)

    Even if you decide that what was once a reasonable decision is now asinine, you have to get there from here. Do you declare all 16-bit applications asinine (because they can only use those asinine short file name)? Even for the 32-bit components, how do you convince them to switch over? Can you even get them to switch over? Until they do, their component will not be accessible: The shell extension won't be loaded until they fix their registration. A program which anticipated this problem and always loaded DLLs by their short names is now broken. (After all, you had to make an arbitrary decision to use long names exclusively or short names exclusively, and someone may have chosen the other branch of the decision tree.)

    And long name/short name is really just a special case of a single file having multiple names. Other ways of creating multiple names include hard links, symbolic links, and junction points. If a file has two names due to hard links, which one is the "preferred" name and which is the "asinine" name? (And what if the "preferred" name is not available to the user? Suppose you decide that the preferred name is the one that comes first alphabetically. Can I launch a denial-of-service attack by creating a hard link to C:\Windows\system32\shell32.dll called C:\A\A.DLL? All attempts to link to C:\Windows\system32\shell32.dll will fail because it is now the "asinine" name.) Does this rule against loading DLLs by "asinine" names negate part of the functionality of the compatibility paths introduced in Windows Vista (since, under this new rule, you can't use them to load DLLs or execute programs because they entail traversing a symbolic link).

    Perhaps these concerns could be addressed in a manner that didn't have all these problems, but it's an awful lot of complexity. In general, simple rules are preferred to complex rules. Especially if the complexity is to address an issue that was not a serious problem to begin with.

  • The Old New Thing

    Why don't the file timestamps on an extracted file match the ones stored in the ZIP file?


    A customer liaison had the following question:

    My customer has ZIP files stored on a remote server being accessed from a machine running Windows Server 2003 and Internet Explorer Enhanced Security Configuration. When we extract files from the ZIP file, the last-modified time is set to the current time rather than the time specified in the ZIP file. The problem goes away if we disable Enhanced Security Configuration or if we add the remote server to our Trusted Sites list. We think the reason is that if the file is in a non-trusted zone, the ZIP file is copied to a temporary location and is extracted from there, and somehow the date information is lost.

    The customer is reluctant to turn off Enhanced Security Configuration (which is understandable) and doesn't want to add the server as a trusted site (somewhat less understandable). Their questions are

    • Why is the time stamp changed during the extract? If we copy the ZIP file locally and extract from there, the time stamp is preserved.
    • Why does being in an untrusted zone affect the behavior?
    • How can we avoid this behavior without having to disable Enhanced Security Configuration or adding the server as a trusted site?

    The customer has an interesting theory (that the ZIP file is copied locally) but it's the wrong theory. After all, copying the ZIP file locally doesn't modify the timestamps stored inside it.

    Since the ZIP file is on an untrusted source, a zone identifier is being applied to the extracted file to indicate that the resulting file is not trustworthy. This permits Explorer to display a dialog box that says "Do you want to run this file? It was downloaded from the Internet, and bad guys hang out there, bad guys who try to give you candy."

    And that's why the last-modified time is the current date: Applying the zone identifier to the extracted file modifies its last-modified time, since the file on disk is not identical to the one in the ZIP file. (The one on disk has the "Oh no, this file came from a stranger with candy!" label on it.)

    The recommended solution is to add the server containing trusted ZIP files to your trusted sites list. Since the customer is reluctant to do this (for unspecified reasons), there are some other alternatives, though they are considerably riskier. (These alternatives are spelled out in KB article 883260: Description of how the Attachment Manager works.)

    You can disable the saving of zone information from the Group Policy Editor, under Administrative Templates, Windows Components, Attachment Manager, Do not preserve zone information in file attachments. This does mean that users will not be warned when they attempt to use a file downloaded from an untrusted source, so you have to trust your users not to execute that random executable they downloaded from some untrusted corner of the Internet.

    You can use the Inclusion list for low, moderate, and high risk file types policy to add ZIP as a low-risk file type. This is not quite as drastic as suppressing zone information for all files, but it means that users who fall for the "Please unpack the attached ZIP file and open the XYZ icon" trick will not receive a "Do you want to eat this candy that a stranger gave to you?" warning prompt before they get pwned.

    But like I said, it's probably best to add just the server containing the trusted ZIP files to your trusted sites list. If the server contains both trusted and untrusted data (maybe that's why the customer doesn't want to put it on the trusted sites list), then you need to separate the trusted data from the untrusted data and put only the trusted server's name in your trusted sites list.

  • The Old New Thing

    Like a chicken talking to a duck


    Many years ago, I called the home of my Chinese-speaking nieces. This was before they started learning English and before I started learning their dialect of Chinese. After the call was over, the eldest niece asked, "Who was that on the phone?"

    "That was Uncle Raymond."

    "Oh, I want to talk to Uncle Raymond!"

    Her mother replied, "That'd be like a chicken talking to a duck."

    A chicken talking to a duck is a Chinese idiom referring to two people who cannot communicate due to a language barrier.

    It seems that ducks are somehow central to the concept of language unintelligibility. Is there a duck-related language idiom in your language?

  • The Old New Thing

    That's not a duck


    One of the audio features added to Windows 7 goes by the formal name stream attenuation, but it is more commonly known to people in the audio world as ducking. Ducking is the process of lowering the volume of background sounds in order to draw more attention to the foreground sound. For example, when you're watching a big battle scene in a summer action movie, your ears are assaulted with the sounds of weapons fire, objects exploding left and right, but when the hero turns to his girlfriend-of-the-moment, the sound level of all the death and destruction drops a bit so you can hear him say something tender, or maybe inspiring, or maybe inspiringly tender. Something like that. And then when the moment is over, the sound level returns to normal and once again the sound of things blowing up overwhelms your eardrums.

    Sorry, I got a bit carried away. Where was I? Oh right, ducking.

    Ducking is the process of temporarily reducing the volume of background sounds in order to make foreground sounds easier to hear. Here's a presentation from the 2008 PDC by Larry Osterman which covers the technical part of ducking.

    When the feature was added to Windows 7, the icon on the Communications tab of the Sound control panel was a yellow rubber duck. Those audio folks think they're so cute.

    Sadly (or perhaps fortunately), the icon was changed to a telephone handset.

    The subject line of this article is an inside joke: When visiting one of my friends, I would sometimes speak to his three-year-old daughter in German, because they say that exposure to multiple languages is a good thing. At one time, I asked her a question, I forget what it was, and she responded, in English, "That's not a duck!"

    None of us could figure out what she was talking about, but it has been a catch phrase among us for over a decade.

  • The Old New Thing

    The Importance of Being Snooki


    What if Jersey Shore were actually a play written by Oscar Wilde? Algernon Moncrieff and Jack Worthing from Broadway's current production of The Importance of Being Earnest explore that premise in a five-part series titled "Jersey Shore" Gone Wilde, drawing its dialogue from things actually said on "Jersey Shore".

    The dialogue and delivery are funny enough. But what really sells it is the acting: The eye rolls, the nervous glances, the blank stares...

    Warning: NSFW for crude language, so I didn't embed the videos. You'll have to click through.

  • The Old New Thing

    Hidden compatibility constraints of redirecting program execution via a stub


    One of the "obvious" solutions to the issue of how much work you're willing to do to save 68KB of disk space was to replace one of the copies with a stub that launches the other copy.

    If you try this obvious solution, you may run into some compatibility issues.

    First of all, there are programs which launch Notepad and then wait on the process handle so they can wait until the user closes Notepad. Your stub program cannot just do a Create­Process on the target, because programs which perform a wait will find the wait satisfied when your stub program exits.

    Okay, so your stub program has to wait for the real copy of Notepad to exit before it can exit itself.

    Once you fix that, you'll find another problem: Programs call Get­Exit­Code­Process to see how Notepad exited. Your stub program therefore cannot just perform an Exit­Process; it has to do a Get­Exit­Code­Process on the real Notepad and pass that exit code to your own Exit­Process.

    Once you fix that, you'll find another problem: There are programs which execute a process and then look for windows owned by that process. (Yes, there can be more than one, but Notepad is a simple program that creates only one top-level unowned window.) Those programs will get the process ID of your stub program and be unable to find the Notepad window (since it belongs to the real Notepad program, which has a different process ID). I'm not sure how to fix that one.

    Yes, you can write a stub that launches another program, but that solves the "save disk space" problem by introducing other problems.

    Remember, even though people are supposed to stick to documented behavior (since that is all that is contractual), in practice any implementation detail becomes a compatibility constraint.

Page 3 of 3 (26 items) 123