November, 2007

  • The Old New Thing

    Hidden gotcha: The command processor's AutoRun setting

    • 37 Comments

    If you type cmd /? at a command prompt, the command processor will spit out pages upon pages of strange geeky text. I'm not sure why the command processor folks decided to write documentation this way rather than the more traditional manner of putting it into MSDN or the online help. Maybe because that way they don't have to deal with annoying people like "editors" telling them that their documentation contains grammatical errors or is hard to understand.

    Anyway, buried deep in the text is this little gem:

    If /D was NOT specified on the command line, then when CMD.EXE starts, it
    looks for the following REG_SZ/REG_EXPAND_SZ registry variables, and if
    either or both are present, they are executed first.
    
        HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun
    
            and/or
    
        HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun
    

    I sure hope there is some legitimate use for this setting, because the only time I see anybody mention it is when it caused them massive grief.

    I must be losing my mind, but I can't even write a stupid for command to parse the output of a command.

    C:\test>for /f "usebackq delims=" %i in (`dir /ahd/b`) do @echo %i
    

    When I run this command, I get

    RECYCLER
    System Volume Information
    WUTemp
    

    Yet when I type the command manually, I get completely different output!

    C:\test>dir /ahd/b
    test_hidden
    

    Have I gone completely bonkers?

    The original problem was actually much more bizarro because the command whose output the customer was trying to parse merely printed a strange error message, yet running the command manually generated the expected output.

    After an hour and a half of head-scratching, somebody suggested taking a look at the command processor's AutoRun setting, and lo and behold, it was set!

    C:\test>reg query "HKCU\Software\Microsoft\Command Processor" /v AutoRun
    
    ! REG.EXE VERSION 3.0
    
    HKEY_CURRENT_USER\Software\Microsoft\Command Processor
        AutoRun     REG_SZ  cd\
    

    The customer had no idea how that setting got there, but it explained everything. When the command processor ran the dir /ahd/b command as a child process (in order to parse its output), it first ran the AutoRun command, which changed the current directory to the drive's root. As a result, the dir /ahd/b produced a listing of the hidden subdirectories of the root directory rather than the hidden subdirectories of the C:\test directory.

    In the original formulation of the problem, the command the customer was trying to run looked for its configuration files in the current directory, and the cd\ in the AutoRun meant that the program looked for its configuration files in the root directory instead of the C:\test directory. Thus came the error message ("Configuration file not found") and the plea for help that was titled, "Why can't the XYZ command find a configuration file that's right there in front of it?"

    Like I said, I'm sure there must be some valid reason for the AutoRun setting, but I haven't yet found one. All I've seen is the havoc it plays.

  • The Old New Thing

    Dreyer's Berry Rainbow Sherbet

    • 22 Comments

    Okay, we have Dreyer's Berry Rainbow Sherbet.

    Our Berry Rainbow Sherbet combines the tangy fruit taste of blackberry, raspberry and orange sherbets to create a delicious, refreshing treat.

    Orange is a berry?

  • The Old New Thing

    You even have to watch out for your placeholder bitmaps

    • 19 Comments

    During the betas of Windows Vista, the final set of sample logon pictures had yet to be determined, so a bunch of placeholder bitmaps were created. These placeholders consisted of the letters FPO in a box. FPO is a standard term in desktop publishing; it stands for For Position Only. In order to permit designers to perform page layout before final images are ready, a For Position Only image with the correct size and shape (but dummy contents) is used. I learned it as For Placement Only, but the meaning is the same.

    We received a bug report from a beta tester in Austria who was surprised to see what appeared at first glance to be the name of the FPÖ political party as several of the logon picture options. Was Microsoft taking sides in the political affairs of Austria? No, it was just a coincidence.

    I suspect the designers learned their lesson: Don't use publishing jargon in bitmaps, even if it seems harmless.

  • The Old New Thing

    Darkon: A Larping Documentary

    • 13 Comments

    My friend ::Wendy:: has many circles of friends, and several of them converged at the Elephant and Castle Pub in Seattle last week for her send-off party, resulting in a night-long game of Venn Diagram as you tried to work out which groups intersected how.

    I got to meet in person some of ::Wendy::'s blogger friends, including Jennifer (aka "Piehole") and LaCroix (not her real name), the person who tipped me off to Yaktrax earlier this year. Jennifer in real life is pretty much exactly like her blog persona: boistrous and hilariously outrageous. LaCroix was a surprise: Although her writing appears methodical and subdued, in person, she's intensely energetic and charismatic. Once you start talking with her, you somehow just want to be her friend. It's no wonder that she has her own Cafeteria Boyfriends.

    At some point during the evening, I mentioned the movie Darkon, a documentary on the Darkon Wargaming Club, a band of Live Action Role Playing aficionados, known perhaps pejoratively as larpers. We were all fascinated by the idea of the movie (Grady Hendrix of Slate calls it a "must-see"), but alas it doesn't appear to be showing in the Seattle area. We'll just have to wait for it to show up in the video rental stores.

  • The Old New Thing

    If you want a menu that shows the contents of the My Computer folder, you already know how to do it

    • 22 Comments

    Commenter praful asks what to me is a rather confused question, but I'll try to guess what the real question is.

    If you drag My Computer to the Start button in XP, you get an expanding menu that lets you see all files and folders as submenus.

    Is this menu available to applications via an API, or do you have to build it yourself? For example, can an application have a pop-up menu, with the My Computer menu in it?

    If the My Computer menu is available as an API, is it customisable so that, for example, only folders are displayed and items can be added to the menu?

    First of all, if you drag My Computer to the Start button in Windows XP, the result is that the My Computer icon shows up in the pin list as an icon. There is no expanding menu.

    You do get an expanding menu if you are using the classic (non-XP) Start menu, so let's assume that praful really asked about the classic Start menu rather than the Windows XP Start menu. But what's so special about My Computer? You can just right-click the Start button, select Open, and then start creating folders. And those folders will show up as expanding menus on the classic Start menu.

    That's why I'm confused about this question. It's taking a general feature and focusing on a specific case. There's nothing special about My Computer on the Start menu. It expands like any other folder. It's like asking, "If I create a directory on my floppy drive called stuff, I can use the dir command to look at its contents on the screen. Is this textual format of the contents of the stuff directory available to applications via an API?" What's so special about the stuff directory on your floppy drive? This works for any directory, whether it's on a floppy drive or a hard drive or a network drive.

    Anyway, if you want a menu that shows the contents of your My Computer folder, you already know how to do it. It's just a simple matter of typing. You use the IShellFolder::EnumObjects method to enumerate the contents of the My Computer folder. (The linked article shows how to enumerate the contents of the desktop; enumerating the contents of the My Computer folder is left as an exercise.) Since you're in control of the enumeration, you can decide to filter out folders, or show only folders, or show only items whose names end in a vowel. You can show them in a list view, you can show them in a menu, or you can scramble the letters and create a jumble puzzle. It's up to you.

  • The Old New Thing

    Who would win in a fight between a penguin and a lemur?

    • 13 Comments

    One of the world's greatest long-standing debates has now been settled (or perhaps reopened). Kevan Gilbert does the research and determines who would win in a fight between a penguin and a lemur.

  • The Old New Thing

    In Windows XP, even when DEP is on, it's still sometimes off

    • 19 Comments

    As we saw last time, there are a variety of ways you can control DEP, one of which is to turn it on for all system processes. But even if you turn on DEP, it still sometimes turns itself off temporarily. It goes back to those bad versions of ATL.

    The application compatibility team found that there were so many programs written with application frameworks that were not DEP-compatible (ATL mostly, but a few others) that nobody would actually enable DEP because the odds were close to 100% that there would be some program on the system that was not DEP-ready. Even DEP-fan Leo Davidson runs a couple of programs that don't work with DEP enabled. And it takes only one program to foul an upgrade.

    When the kernel encounters a DEP exception, it checks whether thunk emulation is enabled, and if so (which it usually is), it checks whether the code sequence is one of the "well-known DEP-violating thunks". If so, then it simulates the actions the thunks would have performed and resumes execution instead of raising the exception. For example, if thunk emulation is enabled and you just took a DEP exception on the code sequence

    mov ecx, 12345678
    jmp 43218765
    

    the kernel thunk emulator will perform the moral equivalent of

    pContext->Ecx = 0x12345678;
    pContext->Eip = 0x43218765;
    return EXCEPTION_CONTINUE_EXECUTION;
    

    You can mark your program as "I am so okay with DEP that not only do I want you to enable it, but I don't even want you to do this thunk emulation stuff" by setting the IMAGE_DLLCHARACTERISTICS_NX_COMPAT flag in your PE header. (The Visual Studio linker uses the /NXCOMPAT command line switch to set this flag.)

  • The Old New Thing

    I'm going to keep trying on size fours until I find one that fits

    • 32 Comments

    Everybody has noticed by now the phenomenon of vanity sizing, wherein the size numbers printed on the tag shrink over time even though the clothes have stayed the same size. It's a phenomenon of our own doing. People want to remember themselves as the size they were when they were younger, and fashion designers are eager to please. I remember reading an article about this phenomenon a few years ago that quoted a woman searching for a dress as saying, "I'm going to keep trying on size fours until I find one that fits." She was a size four, gosh darn it.

    I know people who have to shop in the "Young Misses" section because the clothing in the "Women" section is too big. They haven't gotten any smaller, but the clothes have gotten larger. I used to wear a medium; now I have to get a small, and my bathroom scale will assure you that I'm definitely not getting smaller.

    The article suggests that sizes will stabilize thanks to online shopping. In the store, you can try on an article of clothing to see how it really fits; when buying online, you don't have the luxury. The size number had better be accurate or you're going to be returning it. At least that's the theory. I'm just waiting for the madness to end.

  • The Old New Thing

    Is DEP on or off on Windows XP Service Pack 2?

    • 11 Comments

    Last time, we traced an IP_ON_HEAP failure to a shell extension that used an older version of ATL which was not DEP-friendly. But that led to a follow-up question:

    Why aren't we seeing this same crash in the main program as in the shell extension? That program uses the same version of ATL, but it doesn't crash.

    The reason is given in this chart. Notice that the default configuration is OptIn, which means that DEP is off for all processes by default, but is on for all Windows system components. That same part of the page describes how you can change to OptOut so that the default is to turn on DEP for all processes except for the ones you put on the exception list. There's more information on this excerpt from the "Changes to Functionality in Microsoft Windows XP Service Pack 2" document.

    The program that comes with the shell extension is not part of Windows, so DEP is disabled by default. But Explorer is part of Windows, so DEP is enabled for Explorer by default. That's why only Explorer encounters this problem.

    (This little saga does illustrate the double-edged sword of extensibility. If you make your system extensible, you allow other people to add features to it. On the other hand, you also allow other people to add bugs to it.)

    The saga of the DEP exception is not over, however, because it turns out I've been lying to you. More information tomorrow.

  • The Old New Thing

    Psychic debugging: IP on heap

    • 43 Comments

    Somebody asked the shell team to look at this crash in a context menu shell extension.

    IP_ON_HEAP:  003996d0
    
    ChildEBP RetAddr
    00b2e1d8 68f79ca6 0x3996d0
    00b2e1f4 7713a7bd ATL::CWindowImplBaseT<
                               ATL::CWindow,ATL::CWinTraits<2147483648,0> >
                         ::StartWindowProc+0x43
    00b2e220 77134be0 USER32!InternalCallWinProc+0x23
    00b2e298 7713a967 USER32!UserCallWinProcCheckWow+0xe0
    ...
    
    eax=68f79c63 ebx=00000000 ecx=00cade10 edx=7770df14 esi=002796d0 edi=000603cc 
    eip=002796d0 esp=00cade4c ebp=00cade90 iopl=0         nv up ei pl nz na pe nc 
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206 
    002796d0 c744240444bafb68 mov     dword ptr [esp+4],68fbba44
    

    You should be able to determine the cause instantly.

    I replied,

    This shell extension is using a non-DEP-aware version of ATL. They need to upgrade to ATL 8 or disable DEP.

    This was totally obvious to me, but the person who asked the question met it with stunned amazement. I guess the person forgot that older versions of ATL are notorious DEP violators. You see a DEP violation, you see that it's coming from ATL, and bingo, you have your answer. When DEP was first introduced, the base team sent out mail to the entire Windows division saying, "Okay, folks, we're turning it on. You're going to see a lot of application compatibility problems, especially this ATL one."

    Psychic powers sometimes just means having a good memory.

    Even if you forgot that information, it's still totally obvious once you look at the scenario and understand what it's trying to do.

    The fault is IP_ON_HEAP which is precisely what DEP protects against. The next question is why IP ended up on the heap. Was it a mistake or intentional?

    Look at the circumstances surrounding the faulting instruction again. The faulting instruction is the window procedure for a window, and the action is storing a constant into the stack. The symbols of the caller tell us that it's some code in ATL, and you can even go look up the source code yourself:

    template <class TBase, class TWinTraits>
    LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >
      ::StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
        CWindowImplBaseT< TBase, TWinTraits >* pThis =
                  (CWindowImplBaseT< TBase, TWinTraits >*)
                      _AtlWinModule.ExtractCreateWndData();
        pThis->m_hWnd = hWnd; 
        pThis->m_thunk.Init(pThis->GetWindowProc(), pThis); 
        WNDPROC pProc = pThis->m_thunk.GetWNDPROC(); 
        ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
        return pProc(hWnd, uMsg, wParam, lParam);
    } 
    

    Is pProc corrupted and we're jumping to a random address on the heap? Or was this intentional?

    ATL is clearly generating code on the fly (the window procedure thunk), and it is in execution of the thunk that we encounter the DEP exception.

    Now, you didn't need to have the ATL source code to realize that this is what's going on. It is a very common pattern in framework libraries to put a C++ wrapper around window procedures. Since C++ functions have a hidden this parameter, the wrappers need to sneak that parameter in somehow, and one common technique is to generate some code on the fly that sets up the hidden this parameter before calling the C++ function. The value at [esp+4] is the window handle, something that can be recovered from the this pointer, so it's a handly thing to replace with this before jumping to the real C++ function.

    The address being stored as the this parameter is 68fbba44, which is inside the DLL in question. (You can tell this because the return address, which points to the ATL thunk code, is at 68f79ca6 which is in the same neighborhood as the mystery pointer.) Therefore, this is almost certainly an ATL thunk for a static C++ object.

    In other words, this is extremely unlikely be a jump to a random address. The code at the address looks too good. It's probably jumping there intentionally, and the fact that it's coming from a window procedure thunk confirms it.

    But our tale is not over yet. The plot thickens. We'll continue next time.

Page 2 of 3 (29 items) 123