November, 2012

  • The Old New Thing

    How do I use group policy to improve security of USB thumb drives in my organization?

    • 15 Comments

    A customer wanted to know how they could improve the security of USB thumb drives in their organization. Specifically, they wanted to block access to removable media devices (primarily USB thumb drives), but provide a list of exceptions for specific thumb drives. Fortunately, there's a whitepaper that covers exactly this topic and explains how to set up your policies to accomplish this.

    Step-By-Step Guide to Controlling Device Installation Using Group Policy

  • The Old New Thing

    Microspeak: touch base

    • 5 Comments

    The verb phrase touch base is in general business jargon use, but it's quite popular at Microsoft.

    To touch base with someone is to contact someone in a lightweight and mostly-informal sort of way. In other words, it takes the form of a piece of email or a brief office visit rather than a formal meeting with an agenda.

    Bob, can you touch base with the Nosebleed team to verify that this design change won't affect them?

    Bob is expected to contact a representative from the Nosebleed team, either by sending email, or by telephone, or by stopping by their office for a quick chat. If Bob sets up a one-hour meeting with a dozen engineers from both sides, then he's blowing the issue out of proportion.

  • The Old New Thing

    Raymond's podcast list (for 2011, at least)

    • 12 Comments

    Ry Jones wants to know what other podcasts I subscribe to.

    Remember, I wrote this back in 2011.

    Here's what I listen to. Note that I am not averse to fast-forwarding over parts that don't interest me, such as when they discuss a movie that I simply don't care about.

    • Pop culture: I don't really follow pop culture, but these podcasts are just plain fun to listen to.
      • Pop Culture Happy Hour. Imagine a group of four really close friends, all intelligent, witty, and who love to tease each other. That's what this is. Favorite part: The Regrettable Television Pop Quiz, an occasional segment in which participants are challenged to identify excerpts from television programs you are embarrassed to admit that you watch.
      • Extra Hot Great. Similarly enjoyable round-table discussion of This Week in Pop Culture. Most of the attention goes to The Canon, a segment in which episodes of television are nominated for inclusion in the pantheon of great television. But my favorite part is Game Time. (Alas, by the time this article reached the head of the queue, Extra Hot Great is no longer in production.)
      • Slate's Culture Gabfest. The most highbrow of the three, and the most likely to suffer the fast-forward button. Sorry, guys.
    • Sports: I am more of a meta-sports person rather than a sports person. I'm interested in things like rule changes and the business of sports, not so much the "Who's going to win this year?"
      • Hang Up and Listen. I find Mike Pesca's voice a bit too brash for NPR news reporting, but when opining about sports, it's the perfect pitch. Stefan Fatsis's sporteaucrat impression is always welcomed. It's hosted by Josh Levin, who opens each week's show with "This is Josh Levin, and this is Slate's Hang Up and Listen." That opening bothers me because of the shifting antecedent of the word this. ("This voice is Josh Levin, and this show is Slate's Hang Up and Listen.") I would prefer that he open with "I'm Josh Levin, and this is Slate's Hang Up and Listen."
      • Only a Game. The week in sports. I usually fast-forward over the "Who's going to win this year?", but I never miss Charlie Pierce.
    • Economics: The dismal science.
      • Planet Money. Economics in layman's terms. I'm a particular fan of their latest series, Ask a Banker, mostly because Matt Levine writing style is hilarious.
      • Freakonomics Radio. This is the most recent addition to my blogroll. Still in the trial period. We'll see if it's still on my list next year.
    • Other
      • Slate's Political Gabfest. The first podcast I ever subscribed to. I tend to fast-forward this one a lot of late, though.
      • Wait, Wait, Don't Tell Me, the NPR News Quiz. I was one of the very first listener-contestants on this show, back when it was really awful. (They actually called me to ask me if I wanted to be on.) Fortunately, the show is no longer awful.
  • The Old New Thing

    How do I forward an exported function to an ordinal in another DLL?

    • 16 Comments

    The syntax for specifying that requests to import a function from your DLL should be forwarded to another DLL is

    ; A.DEF
    EXPORTS
     Dial = B.Call
    

    This says that if somebody tries to call Dial() from A.DLL, they are really calling Call() in B.DLL. This forwarding is done in the loader. Normally, when a client links to the function A!Dial, the loader says, "Okay, let me get the address of the Dial function in A.DLL and store it into the __imp__Dial variable." It's the logical equivalent of

    client::__imp__Dial = GetProcAddress(hinstA, "Dial");
    

    When you use a forwarder, the loader sees the forwarder entry and says, "Whoa, I'm not actually supposed to get the function from A.DLL at all! I'm supposed to get the function Call from B.DLL!" So it loads B.DLL and gets the function Call from it.

    hinstB = LoadLibrary("B.DLL");
    client::__imp__Dial = GetProcAddress(B, "Call");
    

    (Of course, the loader doesn't actually do it this way, but this is a good way of thinking about it.)

    But what if the function Call was exported by ordinal? How do you tell the linker, "Please create a forwarder entry for Dial that forwards to function 42 in B.DLL?"

    I didn't know, but I was able to guess.

    Back in the days of 16-bit Windows, there were two ways to obtain the address of a function exported by ordinal. The first way is the way most people are familiar with:

    FARPROC fp = GetProcAddress(hinst, MAKEINTRESOURCE(42));
    

    The second way uses an alternate formulation, passing the desired ordinal as a string prefixed with the number-sign:

    FARPROC fp = GetProcAddress(hinst, "#42");
    

    You can hide a number inside a string by using MAKEINTRESOURCE, and you can hide a string inside a number by using the '#' character.

    Given that the number sign has been used in the past to hide a number inside a string, I figured it was worth a shot to see if the loader carried this convention forward. (No pun intended.)

    ; A.DEF
    EXPORTS
     Dial = B.#1
    

    Hey, check it out. It works.

    Sometimes a little knowledge of history actually helps you solve problems in the present day.

  • The Old New Thing

    If you're going to write your own allocator, you need to respect the MEMORY_ALLOCATION_ALIGNMENT

    • 22 Comments

    This time, I'm not going to set up a story. I'm just going to go straight to the punch line.

    A customer overrode the new operator in order to add additional instrumentation. Something like this:

    struct EXTRASTUFF
    {
        DWORD Awesome1;
        DWORD Awesome2;
    };
    
    // error checking elided for expository purposes
    void *operator new(size_t n)
    {
      EXTRASTUFF *extra = (EXTRASTUFF)malloc(sizeof(EXTRASTUFF) + n);
      extra->Awesome1 = get_awesome_1();
      extra->Awesome2 = get_awesome_2();
      return ((BYTE *)extra) + sizeof(EXTRASTUFF);
    }
    
    // use your imagination to implement
    // operators new[], delete, and delete[]
    

    This worked out okay on 32-bit systems because in 32-bit Windows, MEMORY_ALLOCATION_ALIGNMENT is 8, and sizeof(EXTRASTUFF) is also 8. If you start with a value that is a multiple of 8, then add 8 to it, the result is still a multiple of 8, so the pointer returned by the custom operator new remains properly aligned.

    But on 64-bit systems, things went awry. On 64-bit systems, MEMORY_ALLOCATION_ALIGNMENT is 16, As a result, the custom operator new handed out guaranteed-misaligned memory.

    The misalignment went undetected for a long time, but the sleeping bug finally woke up when somebody allocated a structure that contained an SLIST_ENTRY. As we saw earlier, the SLIST_ENTRY really does need to be aligned according to the MEMORY_ALLOCATION_ALIGNMENT, especially on 64-bit systems, because 64-bit Windows takes advantage of the extra "guaranteed to be zero" bits that 16-byte alignment gives you. If your SLIST_ENTRY is not 16-byte aligned, then those "guaranteed to be zero" bits are not actually zero, and then the algorithm breaks down.

    Result: Memory corruption and eventually a crash.

  • The Old New Thing

    Break it up, you two!: The zero width non-joiner

    • 14 Comments

    Keytips are those little pop-up keyboard accelerator thingies that appear on the Ribbon when you tap the Alt key:

    A tester discovered that when a test tried to read the accessibility name for a Ribbon keytip, "an extra character appears after every keytip character." In the above example, the keytip for "Tab 1" was being read back as

    46 00 0C 20 46 00 0C 20
    ----- ----- ----- -----
      F   ?????   F   ?????
    

    The question marks are U+200C, formally known as ZERO WIDTH NON-JOINER. Michael Kaplan discussed the character (and its evil twin the ZERO WIDTH JOINER) some time ago.

    The ZERO WIDTH NON-JOINER (or ZWNJ to his friends) is a hint to the font engine that the characters on opposite sides of the ZWNJ should not be combined into a ligature. In English, the ZWNJ would prevent two consecutive lowercase "f"s from being converted into a "ff" ligature. Ligatures are fading from use in contemporary printing, probably due to the rise of computers. Back in the old days, you saw all sorts of neat ligatures, like "st".

    Breaking up the ligature is important when presenting keyboard accelerators. Imagine if the keyboard accelerator for a key sequence was "A" followed by "E". If this were displayed as "Æ", users would waste their time looking for an "Æ" key on their keyboard. Although English doesn't have many ligatures any more, many other languages still employ them heavily. (You may have noticed that the keytip was a bit overzealous with the ZWNJ, putting one at the end of the string even though there was nothing for the second F to be unjoined from!)

    So if you encounter one of these ZWNJ characters, don't be afraid. He's just there to break things up. And as Michael notes, ZWNJ and ZWJ "are supposed to be ignored in things like the Unicode Collation Algortihm."

  • The Old New Thing

    Microsoft Money crashes during import of account transactions or when changing a payee of a downloaded transaction

    • 49 Comments
    Update: An official fix for this issue has been released to Windows Update, although I must say that I think my patch has more style than the official one. You do not need to patch your binary. Just keep your copy of Windows 8 up to date and you'll be fine.

    For the five remaining Microsoft Money holdouts (meekly raises hand), here's a patch for a crashing bug during import of account transactions or when changing a payee of a downloaded transaction in Microsoft Money Sunset Deluxe. Patch the mnyob99.dll file as follows:

    • File offset 003FACE8: Change 85 to 8D
    • File offset 003FACED: Change 50 to 51
    • File offset 003FACF0: Change FF to 85
    • File offset 003FACF6: Change E8 to B9

    Note that this patch is completely unsupported. If it makes your computer explode or transfers all your money to an account in the Cayman Islands, well, too bad for you.

    If you are not one of the five remaining customers of Microsoft Money, this is a little exercise in application compatibility debugging. Why application compatibility debugging? Because the problem seems to be more prevalent on Windows 8 machines.

    Note that I used no special knowledge about Microsoft Money. All this debugging was performed with information you also have access to. It's not like I have access to the Microsoft Money source code. And I did this debugging entirely on my own. It was not part of any official customer support case or anything like that. I was just debugging a crash that I kept hitting.

    The crash occurs in the function utlsrf08!DwStringLengthA:

    utlsrf08!DwStringLengthA:
            push    ebp
            mov     ebp,esp
            mov     eax,dword ptr [ebp+8]
            lea     edx,[eax+1]
    again:
            mov     cl,byte ptr [eax]
            inc     eax
            test    cl,cl
            jne     again
            sub     eax,edx
            pop     ebp
            ret     4
    

    The proximate cause is that the string pointer in eax is garbage. If you unwind the stack one step, you'll see that the pointer came from here:

            lea     eax,[ebp-20Ch]
            push    eax
            call    dword ptr [__imp__GetCurrentProcessId]
            push    eax
            push    offset "Global\TRIE@%d!%s"
            lea     eax,[ebp-108h]
            push    104h
            push    eax
            call    mnyob99!DwStringFormatA
            add     esp,14h
            lea     eax,[ebp-2E4h]
            push    eax
            push    5Ch
            push    dword ptr [ebp-2E4h] ; invalid pointer
            call    mnyob99!DwStringLengthA
            sub     eax,7
            push    eax
            lea     eax,[ebp-101h]
            push    eax
            jmp     l2
    l1:
            mov     eax,dword ptr [ebp-2E4h]
            mov     byte ptr [eax],5Fh
            lea     eax,[ebp-2E4h]
            push    eax
            push    5Ch
            push    dword ptr [ebp-2E4h]
            call    mnyob99!DwStringLengthA
            push    eax
            push    dword ptr [ebp-2E4h]
    l2:
            call    mnyob99!FStringFindCharacterA
            cmp     dword ptr [ebp-2E4h],edi
            jne     l1
    

    I was lucky in that all the function calls here were to imported functions, so I could extract the names from the imported function table. For example, the call to DwStringFormatA was originally

            call    mnyob99!CBillContextMenu::SetHwndNotifyOnGoto+0x1e56a (243fc3cc)
    

    But the target address is an import stub:

            jmp     dword ptr [mnyob99+0x1ec0 (24001ec0)]
    

    And then I can walk the import table to see that this was the import table entry for utlsrf08!DwStringFormatA. From the function name, it's evident that this is some sort of sprintf-like function. (If you disassemble it, you'll see that it's basically a wrapper around vsnprintf.)

    Reverse-compiling this code, we get

    char name[...];
    char buffer[MAX_PATH];
    char *backslash;
    ...
    DwStringFormatA(buffer, MAX_PATH, "Global\\TRIE@%d!%s",
                    GetCurrentProcessId(), name);
    
    // Change all backslashes (except for the first one) to underscores
    if (FStringFindCharacterA(buffer + 7, DwStringLengthA(backslash) - 7,
                              '\\',&backslash))
    {
      do {
        *backslash = '_'; // Change backslash to underscore
      } while (FStringFindCharacterA(backslash, DwStringLengthA(backslash),
                                     '\\',&backslash));
    }
    

    (Remember, all variable names are made-up since I don't have source code access. I'm just working from the disassembly.)

    At this point, you can see the bug: It's an uninitialized variable at the first call to String­Find­CharacterA. Whether we crash or survive is a matter of luck. If the uninitialized variable happens to be a pointer to readable data, then the Dw­String­LengthA will eventually find the null terminator, and since in practice the string does not contain any extra backslashes, the call to FString­Find­CharacterA fails, and nobody gets hurt.

    But it looks like their luck ran out, and now the uninitialized variable contains something that is not a valid pointer.

    The if test should have been

    if (FStringFindCharacterA(buffer + 7, DwStringLengthA(buffer) - 7,
                              '\\',&backslash))
    

    This means changing the

            push    dword ptr [ebp-2E4h]
    

    to

            lea     eax,[ebp-101h]
            push    eax
    

    Unfortunately, the patch is one byte larger than the existing code, so we will need to get a little clever in order to get it to fit.

    One trick is to rewrite the test as

    if (FStringFindCharacterA(buffer + 7, DwStringLengthA(buffer + 7),
                              '\\',&backslash))
    

    That lets us rewrite the assembly code as

            lea     eax,[ebp-2E4h]
            push    eax
            push    5Ch
            lea     eax,[ebp-101h]          ; \ was "push dword ptr [ebp-2E4h]"
            push    eax                     ; /
            call    mnyob99!DwStringLengthA ; unchanged but code moved down one byte
            nop                             ; \ was "sub eax,7" (3-byte instruction)
            nop                             ; /
            push    eax
            lea     eax,[ebp-101h]
            push    eax
    

    The new instructions (lea and push) are one byte larger than the original push, but we got rid of the three-byte sub eax, 7, so it's a net savings of two bytes, which therefore fits.

    However, I'm going to crank the nerd level up another notch and try to come up with a patch that involves modifying as few bytes as possible. In other words, I'm going for style points.

    To do this, I'm going to take advantage of the fact that the string length is the return value of Dw­String­FormatA, so that lets me eliminate the call to Dw­String­LengthA altogether. However, this means that I have to be careful not to damage the value in eax before I get there.

            lea     ecx,[ebp-2E4h] ; was "lea eax,[ebp-2E4h]"
            push    ecx            ; was "push eax"
            push    5Ch
            nop                    ; \
            nop                    ; |
            nop                    ; |
            nop                    ; | was "push dword ptr [ebp-2E4h]"
            nop                    ; |
            nop                    ; /
            nop                    ; \
            nop                    ; |
            nop                    ; | was "call mnyob99!DwStringLengthA"
            nop                    ; |
            nop                    ; /
            sub     eax,7
            push    eax
            lea     eax,[ebp-101h]
            push    eax
    

    Patching the lea eax, ... to be lea ecx, ... can be done with a single byte, and the push eax is a single-byte instruction as well, so the first two patches can be done with one byte each. That leaves me with 11 bytes that need to be nop'd out.

    The naïve way of nopping out eleven bytes is simply to patch in 11 nop instructions, but you can do better by taking advantage of the bytes that are already there.

    ffb51cfdffff    push    dword ptr [ebp-2E4h]
    85b51cfdffff    test    dword ptr [ebp-2E4h],esi
    
    e8770a0000      call    mnyob99!DwStringLengthA
    b9770a0000      mov     ecx,0A77h
    

    By patching a single byte in each of the two instructions, I can turn them into effective nops by making them do nothing interesting. The first one tests the uninitialized variable against some garbage bits, and the second one loads a unused register with a constant. (Since the ecx register is going to be trashed by the call to FString­Find­CharacterA, we are free to modify it all we want prior to the call. No code could have relied on it anyway.)

    That second patch is a variation of one I called out some time ago, except that instead of patching out the call with a mov eax, immed32, we're using a mov ecx, immed32, because the value in the eax register is still important.

    Here's the final result:

            lea     ecx,[ebp-2E4h]           ; was "lea eax,[ebp-2E4h]"
            push    ecx                      ; was "push eax"
            push    5Ch
            test    dword ptr [ebp-2E4h],esi ; was "push dword ptr [ebp-2E4h]"
            mov     ecx,0a77h                ; was "call mnyob99!DwStringLengthA"
            sub     eax,7
            push    eax
            lea     eax,[ebp-101h]
            push    eax
    

    Bonus chatter: When I shared this patch with my friends, I mentioned that this patch made me feel like my retired colleague Jeff, who had a reputation for accomplishing astonishing programming tasks in his spare time. You would pop into his office asking for some help, and he'd fire up some program you'd never seen before.

    "What's that?" you'd ask.

    "Oh, it's a debugger I wrote," he'd calmly reply.

    Or you'd point him to a program and apologize, "Sorry, I only compiled it for x86. There isn't an Alpha version."

    "That's okay, I'll run it in my emulator," he'd say, matter-of-factly.

    (And retiring from Microsoft hasn't slowed him down. Here's an IBM PC Model 5150 emulator written in JavaScript.)

    Specifically, I said, "I feel like Jeff, who does this sort of thing before his morning coffee."

    Jeff corrected me. "If this was something I used to do before coffee, that probably meant I was up all night. Persistence >= talent."

  • The Old New Thing

    Frequentists vs Bayesians

    • 20 Comments

    But, I mean, c'mon. Frequentists vs Bayesians? Worst. Action. Movie. Ever.

  • The Old New Thing

    Why are taskbar live previews lost when you use Fast User Switching?

    • 25 Comments

    Anonymous asks a metric buttload of questions, which means that I feel compelled to answer all or none. And given the choice, I decided to answer none.

    Okay, I will answer one and ignore the rest.

    Why are taskbar live previews lost when you use Fast User Switching?

    When you switch away from a user via Fast User Switching, the Desktop Window Manager for that session is turned off. After all, since that session no longer has access to the screen, there's no point running all this code and consuming all this memory for something nobody can see.

    When the Desktop Window Manager restarts upon reactivation of a session, it can recovery nearly all of the information it needs: It can enumerate all the windows and obtain their positions and styles. For each visible window, it can send a WM_PAINT message to ask it to paint its contents afresh. But if the window is minimized, the Desktop Window Manager has no way to get at the application's non-minimized pixels, because the application will respond to the WM_PAINT message by saying, "My client area is 0×0. I will therefore paint nothing!"

    This is one of those tradeoffs that you have to make when engineering software. The benefit of shutting down the Desktop Window Manager when it is not being used exceeds the cost of losing thumbnails for minimized applications. Until the application is restored (and can therefore be sent a WM_PAINT message to get it to paint its client area at its restored size), the Desktop Window Manager merely shows a placeholder bitmap.

  • The Old New Thing

    Thread affinity of user interface objects: Addendum

    • 14 Comments
    Some time ago, I discussed the thread affinity of device contexts, noting that the Get­DC and Release­DC functions must be called from the same thread.

    The same restriction also applies to printer DCs. Printer DCs must be created and destroyed on the same thread. The printing team imposed this additional rule in order to make it easier for printer driver vendors to author their drivers. (Printer driver developers have a habit of calling CoInitialize in their implementation of CreateDC and CoUninitialize in their implementation of DeleteDC.)

    Given that printer drivers are a third-party extension point, it's probably in your best interest to treat printer DCs as having hard thread affinity, since who knows what the printer driver is going to do if you try to access it from multiple threads. In other words, the thread that creates the printer DC should be the only thread which prints to it, and should also be the thread which destroys the printer DC when printing is complete.

    That's not saying that all your printing has to be done from one thread. If you want, you can create multiple printer DCs, each on different threads. Just make sure to use each printer DC only on the thread that created it. Your printer driver will thank you.

Page 2 of 3 (26 items) 123