• The Old New Thing

    Welcome Martyn Lovell

    • 0 Comments
    Martyn Lovell from the VC++ team has joined the world of blogging. Martyn is a smart guy, even though he does spell some words funny.
  • The Old New Thing

    Is there any vendor bias in the way the Start menu determines which programs are most frequently used?

    • 39 Comments

    Chrissy wants to know if there is a bias towards Microsoft products in the selection of most frequently used programs on the Start menu.

    The only bias is in the initial default MFU list, the one that appears upon a fresh login. In Windows XP, the default Start menu MFU contains six slots. The first three point to Windows applications, and the second three point to programs chosen by the OEM. (If the OEM chooses not to take advantage of this feature, or if this is a boxed version of the product, then the second three slots also point to Windows applications.) Which specific three (or six) programs get displayed depend on the system configuration, so it's not like there's a single initial Start menu that applies to everyone.

    Once those initial MFU items are selected, the Start menu algorithm proceeds in a vendor-blind manner. (Indeed, it doesn't even know who the vendor is; no part of the algorithm looks at file version information.)

    The precise algorithm that is used for determining which programs go on the MFU over time has been reviewed by government-appointed regulators, who have not raised any concerns over vendor bias.

    So I hate to say it, Chrissy, but I think it's all in your head.

  • The Old New Thing

    The MARGINS parameter to the DwmExtendFrameIntoClientArea function controls how far the frame extends into the client area

    • 8 Comments

    A customer wrote a program that calls Dwm­Extend­Frame­Into­Client­Area to extend the frame over the entire client area, but then discovered that this made programming difficult:

    I have a window which I want to have a glassy border but an opaque body. I made my entire window transparent by calling Dwm­Extend­Frame­Into­Client­Area, and I understand that this means that I am now responsible for managing the alpha channel when drawing so that the body of my window remains opaque while the glassy border is transparent. Since most GDI functions are not alpha-aware, this management is frustrating. Is there a better way? In pictures, I only want the red portion of the diagram below to be on glass; the inside yellow part should be opaque like normal. Is there an API that can do this?

    This customer's excitement about the glass frame is like somebody who buys a pallet of tangerine juice even though he only wanted two glasses. And now he has questions about how to store the rest of the tangerine juice he didn't want.

    This customer, it appears, passed −1 as the MARGINS to Dwm­Extend­Frame­Into­Client­Area which means "Bring it on, baby! Give me all tangerine all the time everywhere!" If you only want the glass to extend into part of your client area, then say so. Set the MARGINS to the thickness of the glass border (the thickness of the red portion of the above diagram).

  • The Old New Thing

    If a process crashes while holding a mutex, why is its ownership magically transferred to another process?

    • 29 Comments

    A customer was observing strange mutex ownership behavior. They had two processes that used a mutex to coordinate access to some shared resource. When the first process crashed while owning the mutex, they found that the second process somehow magically gained ownership of that mutex. Specifically, when the first process crashed, the second process could take the mutex, but when it released the mutex, the mutex was still not released. They discovered that in order to release the mutex, the second process had to call Release­Mutex twice. It's as if the claim on the mutex from the crashed process was secretly transferred to the second process.

    My psychic powers told me that that's not what was happening. I guessed that their code went something like this:

    // code in italics is wrong
    bool TryToTakeTheMutex()
    {
     return WaitForSingleObject(TheMutex, TimeOut) == WAIT_OBJECT_0;
    }
    

    The code failed to understand the consequences of WAIT_ABANDONED.

    In the case where the mutex was held by the first process when it crashed, the second process will attempt to claim the mutex, and it will succeed, and the return code from Wait­For­Single­Object will be WAIT_ABANDONED. Their code treated that value as a failure code rather than a modified success code.

    The second program therefore claimed the mutex without realizing it. That is what led the customer to believe that ownership was being magically transferred to the second program. It wasn't magic. The second program misinterpreted the return code.

    The second program saw that Try­To­Take­The­Mutex "failed", and it went off and did something else for a while. Then the next time it called Try­To­Take­The­Mutex, the function succeeded: It was a successful recursive acquisition, but the program thought it was the initial acquisition.

    The customer didn't reply back, so we never found out whether that was the actual problem, but I suspect it was.

  • The Old New Thing

    Why is my icon being drawn at the wrong size when I call DrawIcon?

    • 6 Comments

    Some time ago I had a problem with icon drawing. When I tried to draw an icon with Draw­Icon it ended up being drawn at the wrong size. A call to Get­Icon­Info confirmed that the icon was 48×48, but it drew at 32×32.

    The answer is documented in a backwards sort of way in the Draw­Icon­Ex function, which says at the bottom,

    To duplicate DrawIcon (hDC, X, Y, hIcon), call DrawIconEx as follows:

    DrawIconEx (hDC, X, Y, hIcon, 0, 0, 0, NULL,
                DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE); 
    

    Aha, if you use Draw­Icon, then the icon size is ignored and it is drawn with DI_DEFAULT­SIZE.

    The fix, therefore, was to switch to the Draw­Icon­Ex function so I could remove the DI_DEFAULT­SIZE flag, thereby permitting the icon to be drawn at its actual size.

    - DrawIcon(hdc, pt.x, pt.y, hico);
    + DrawIconEx(hdc, pt.x, pt.y, hico, 0, 0, 0, NULL, DI_NORMAL | DI_COMPAT);
    

    A bonus quirk of the DI_DEFAULT­SIZE flag (and therefore of the Draw­Icon function) is that the drawing is done at the default icon size, even if you asked it to draw a cursor.

  • The Old New Thing

    Why does the MoveWindow function let you suppress repainting?

    • 8 Comments

    Commenter Phil Quirk asks via the suggestion box why the MoveWindow function lets you suppress repainting. "Shouldn't the OS be able to figure out if the window needs to be repainted?"

    Indeed the window manager does do a very nice job of figuring it out if you pass bRepaint = TRUE, which is the expected value of the parameter. But if you think you're smarter than the window manager, then you can pass bRepaint = FALSE and tell the window manager, "Even though you think the window needs to be repainted, don't repaint it. Trust me on this."

    Why would you try to outwit the window manager? Maybe you have special knowledge about how your application behaves. For example, you might exploit special properties about the source and destination coordinates and decide that certain portions of the window should not be redrawn but rather should be shared between the old and new locations, sort of like the advanced tricks you can play with the WM_NCCALCSIZE message. Or you might know that your program is going to invalidate the entire client rectangle soon anyway, so a repaint immediately after the move would just be a waste of time. The bRepaint parameter provides an escape hatch, a throwback to the days when the window manager let you do strange things because you might be doing them as part of a clever thing.

    Mind you, these are pretty advanced concerns and most of the time you would be best off just passing bRepaint = TRUE and letting the window manager do its job of deciding what needs to be repainted.

  • The Old New Thing

    Raise la lanterne rouge

    • 6 Comments

    Sure, everybody knows that Floyd Landis won this year's Tour de France. But what about the guy who came in last? While the race leader wears the maillot jaune (yellow jersey), the person at the bottom of the pack is saddled with the lanterne rouge (red lantern), after the lamp that hangs on the back of a train. This year's "winner" is Wim Vansevenant, who at least appears to be a good sport about it.

    Lanterne rouge is not a position you go for. It comes for you.

    (It also amuses me that there's even a Tour de France Lanterne Rouge blog which keeps track of who is "pulling up the rear" throughout the race.)

    Now, mind you, at least he finished the race, which is more than can be said for the thirty-some-odd people who dropped out for one reason or another. All of whose water bottles I am not worthy to carry, of course.

  • The Old New Thing

    If you had to deal with preschoolers all day, you'd need a nap too

    • 5 Comments

    Today, I'm turning it around: This is a dream that one of my friends had about me!

    She dreamed that she took her camera to school to take some pictures, possibly for the yearbook. She was somewhat surprised to discover that I was the new preschool teacher. When she popped in to my classroom to get a couple of pictures of me, she wasn't able to take any: Apparently, my new position was so exhausting that I'd had to take a nap on the king-size classroom bed...

  • The Old New Thing

    Private classes, superclassing, and global subclassing

    • 9 Comments

    In the suggestion box, A. Skrobov asks why it's impossible to superclass WC_DIALOG, but the example that follows is not actually superclassing.

    When I register my own class under this atom, and leave NULL in WNDCLASS.hInstance, Windows fills it in for me. Then I have two distinct classes registered: (0,WC_DIALOG) and (hMyInstance,WC_DIALOG), and DialogBox functions all use the first one.

    This question is a bit confused, since it says that the goal is to superclass the dialog class, but registering WC_DIALOG is not superclassing.

    First, I'll refer everyone to this MSDN article which describes the various ways of manipulating a window class: Subclassing, superclassing, and global subclassing.

    To superclass the dialog class, you retrieve information about the class by calling GetClassInfo and then register a new class based on the original class. But you don't need to go to all that effort to superclass the dialog class, because you already know what you need to know: The number of extra bytes is DLGWINDOWEXTRA, and the dialog procedure is DefDlgProc. You can just register your superclass directly, as we saw last time.

    Superclassing is done by registering your custom class under a different name, and using that class name if you want to obtain the new behavior. On the other hand, the question about talks about registering a class under the same name as the original (namely, WC_DIALOG). This isn't subclassing, nor is it superclassing, nor is it even global subclassing.

    Before continuing the discussion, I'll first address the issue of leaving NULL in WNDCLASS.hInstance: The value NULL for the instance handle is not legal when registering a class. Each class is associated with a module instance, and NULL is not a module instance. The window manager autocorrects this mistake by registering the class under the module corresponding to the executable. This is the same special-case behavior you get if you call GetModuleHandle(NULL), so it's not something completely out of the blue. It looks like A. Skrobov is being confused by the window manager's attempt to do what you mean. So much for being helpful.

    Okay, back to the original problem. Recall that the HINSTANCE member of the WNDCLASS structure is used to specify the class namespace. If you register a class against the handle of the current executable, then in order to create a window with that class, you need to create it with that same instance handle.

    Now we can put all the pieces together: Registering the class with WNDCLASS.hInstance = NULL is autocorrected to registering it with WNDCLASS.hInstance = GetModuleHandle(NULL), which places the class in the window class namespace of the current module. This is a separate class from the system dialog class, which is registered against GetModuleHandle(TEXT("USER32")). The two are registered against different modules, so they live independent lives. They just happen to have the same name.

    As we learned a few years ago, the instance handle you pass to the CreateWindow (or related) function is used to look up the window class, and as we also learned, the HINSTANCE you pass to the DialogBox (or related) function is used to look up the template as well as to create the frame window. The class name comes from the template, and if you didn't specify an explicit class in your template, then the dialog manager will use WC_DIALOG.

    You now have all the pieces necessary to understand what is going on. When you register the class against your executable's instance, you need to use that same instance when creating the dialog box so that your private class is found instead of the global one.

    To show how this all fits together, I've written a little program which registers a private class which happens to have the name WC_DIALOG and then uses it to create a dialog box.

    // scratch.rc
    #include <windows.h>
    
    // A pointless dialog box, for illustration only
    1 DIALOG 0,0,150,50
    STYLE DS_MODALFRAME | DS_SHELLFONT | WS_POPUP | WS_VISIBLE |
        WS_CAPTION | WS_SYSMENU
    CAPTION "Pointless"
    FONT 8, "MS Shell Dlg"
    BEGIN
        DEFPUSHBUTTON "Cancel",IDCANCEL,50,18,50,14
    END
    
    // scratch.cpp
    #include <windows.h>
    
    LRESULT CALLBACK
    SuperDlgProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
    {
      switch (uiMsg) {
      case WM_ERASEBKGND:
        return DefWindowProc(hwnd, uiMsg, wParam, lParam);
      }
      return DefDlgProc(hwnd, uiMsg, wParam, lParam);
    }
    
    INT_PTR CALLBACK
    DlgProc(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam)
    {
      switch (wm) {
      case WM_INITDIALOG: return TRUE;
      case WM_CLOSE: EndDialog(hwnd, 0); return TRUE;
      }
      return FALSE;
    }
    
    int CALLBACK
    WinMain(HINSTANCE hinst, HINSTANCE hinstPrev,
            LPSTR pszCmdLine, int nShowCmd)
    {
      WNDCLASS wc;
      wc.style = 0;
      wc.lpfnWndProc = SuperDlgProc;
      wc.cbClsExtra = 0;
      wc.cbWndExtra = DLGWINDOWEXTRA;
      wc.hInstance = hinst;
      wc.hIcon = NULL;
      wc.hCursor = LoadCursor(NULL, IDC_ARROW);
      wc.hbrBackground = (HBRUSH)(COLOR_INFOBK + 1);
      wc.lpszMenuName = NULL;
      wc.lpszClassName = WC_DIALOG;
    
      if (RegisterClass(&wc))
        DialogBox(hinst, MAKEINTRESOURCE(1), NULL, DlgProc);
    
      return 0;
    }
    

    The dialog template is itself entirely unremarkable; it looks like any old dialog template.

    Our superclass takes the regular dialog box class and gives it a custom background color, namely COLOR_INFOBK.

    The program registers this private version of WC_DIALOG and creates a dialog box based on it. Since we passed the same HINSTANCE in the WNDCLASS.hInstance as we did to DialogBox, the lookup of the WC_DIALOG class will find our private version and use it instead of the global version.

  • The Old New Thing

    How to rescue a broken stack trace on x64: Recovering the stack pointer

    • 1 Comments

    Recovering a broken stack on x64 machines on Windows is trickier because the x64 uses unwind codes for stack walking rather than a frame pointer chain. When you dump the stack, all you're going to see is return addresses sprinkled in amongst the stack data.

    Begin digression: According to the x64 ABI, each function must begin with a prologue which sets up the stack frame. It traditionally goes something like this:

        push rbx ;; save registers
        push rsi ;; save registers
        push rdi ;; save registers
        sub rsp, 0x20 ;; allocate space for local variables and outbound calls
    

    Suppose we have functions

    void Top(int a, int b)
    {
     int toplocal = b + 5;
     Middle(a, local);
    }
    
    void Middle(int c, int d)
    {
     Bottom(c+d);
    }
    
    void Bottom(int e)
    {
     int bottomlocal1, bottomlocal2;
     ...
    }
    

    When execution reaches the ... inside function Bottom the stack looks like the following. (I put higher addresses at the top; the stack grows downward. I also assume that the code is compiled with absolutely no optimization.)

          0040F8E8 parameter 4 (unused)
    0040F8E0 parameter 3 (unused)
    0040F8D8 parameter b passed to Top
    0040F8D0 parameter a passed to Top
    Top's stack frame     0040F8C8 return address of Top's caller During execution of Top,
    rsp = 0040F8A0
    0040F8C0 toplocal
        0040F8B8 parameter 4 (unused)
    0040F8B0 parameter 3 (unused)
    0040F8A8 parameter d passed to Middle
    0040F8A0 parameter c passed to Middle
    Middle's stack frame     0040F898 return address of Middle's caller During execution of Middle,
    rsp = 0040F870
    0040F890 padding for alignment
        0040F888 parameter 4 (unused)
    0040F880 parameter 3 (unused)
    0040F878 parameter 2 (unused)
    0040F870 parameter e passed to Bottom
    Bottom's stack frame     0040F868 return address of Bottom's caller During execution of Bottom,
    rsp = 0040F830
    0040F860 padding for alignment
    0040F858 bottomlocal1
    0040F850 bottomlocal2
        0040F848 parameter 4
    0040F840 parameter 3
    0040F838 parameter 2
    0040F830 parameter 1

    Of course, once the optimizer kicks in, there will also be saved registers in the stack frame, the unused space will start getting used as scratch variables, and the parameters will almost certainly not be spilled into their home locations. End digression.

    Consider this crash where we started executing random instructions (data in the code segment) and finally trapped.

    0:000> r
    rax=0000000000000000 rbx=0000000000000005 rcx=0000000000000042
    rdx=0000000000000010 rsi=00000000000615d4 rdi=00000000043f48e0
    rip=0000000000000000 rsp=00000000001ebf68 rbp=00000000043f32d0
     r8=00000000001ebfd0  r9=0000000000000000 r10=000000007fff3cae
    r11=0000000000000000 r12=0000000000000002 r13=0000000000517050
    r14=0000000000000000 r15=00000000043f55c0
    iopl=0         nv up ei pl nz na pe nc
    cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
    ABC!RandomFunction+0x1234:
    00000000`ff6ebaad test    byte ptr [rax+rdx*4],ah ds:00000000`00000040=??
    0:000> k
    Child-SP          RetAddr           Call Site
    00000000`001ebf70 00000000`00000004 ABC!RandomFunction+0x1234
    00000000`001ebf78 00000000`0000000e 0x4
    00000000`001ebf80 00000000`00000000 0xe
    

    Not very helpful. Let's try to reconstruct the call stack. Here's what we have right now:

    001ebf70  00000000`00000004
    001ebf78  00000000`0000000e
    001ebf80  00000000`00000000
    001ebf88  00000000`77ba21bc ntdll!RtlAllocateHeap+0x16c
    001ebf90  00000000`00000000
    001ebf98  00000000`ff6e1fa1 ABC!operator new[]+0x20
    001ebfa0  00000000`00000000
    001ebfa8  00000000`ff6e28ae ABC!DoesUserPreferMetricUnits+0x2a
    001ebfb0  00000000`000615d4
    001ebfb8  00000000`043f48e0
    001ebfc0  00000000`00000002
    001ebfc8  00000000`00517050
    001ebfd0  00000000`00000010
    001ebfd8  00000000`00000000
    001ebfe0  00000000`00000005
    001ebfe8  00000000`ff6e2b9b ABC!CUIController::UpdateTwoLineDisplay+0x156
    001ebff0  00000000`00000002
    001ebff8  00000000`005170f0
    001ec000  00000000`043f55c0
    001ec008  00000000`00510000
    001ec010  00000000`00000000
    001ec018  00000000`00000000
    001ec020  00000000`00000002
    001ec028  00000000`005170f0
    001ec030  00000000`00000000
    001ec038  00000000`00000000
    001ec040  00000000`00000002
    001ec048  00000000`005170f0
    001ec050  00000000`005170f8
    001ec058  00000000`ff6e2a94 ABC!CUIController::displayEvent+0xea
    001ec060  00000000`00750ed0
    001ec070  00000000`00517118
    001ec078  00000000`043f5aa0
    001ec080  00000000`005170f8
    001ec088  00000000`ff6e2f70 ABC!CEventRegistry::fire+0x34
    001ec090  00000000`00518090
    001ec098  00000000`00517118
    001ec0a0  00000000`043f5aa0
    001ec0a8  00000000`0000000e
    001ec0b0  00000000`00000000
    001ec0b8  00000000`00000000
    001ec0c0  00000000`043f2f00
    001ec0c8  00000000`ff6e2eef ABC!CCalculatorState::storeAndFire+0x126
    001ec0d0  00000000`043f5aa0
    001ec0d8  00000000`00000000
    001ec0e0  00000000`001ec180
    001ec0e8  00000000`00000000
    

    (Note that this dump shows addresses increasing downward, whereas the previous diagram had them increasing upward. Being able to read stack dumps comfortably in both directions is one of those skills you develop as you gain experience.)

    There is no frame pointer chain here to help you see if what you found is a call frame. You just have to use your intuition based on the function names. For example, it sounds perfectly reasonable for operator new[] to call Rtl­Allocate­Heap (to allocate memory), but DoesUserPreferMetric­Units is probably not going to call operator new[].

    Some disassembling around of candidate return addresses suggests that the DoesUserPreferMetric­Units is the one likely to have jumped into space, because it is calling through a function pointer variable, whereas the other candidate return addresses used a direct call (or a call to an import table entry, which is unlikely to be invalid).

    How do we reconstruct the stack based on this assumption? You trick the debugger into thinking that execution stopped inside the DoesUserPreferMetric­Units just before or after the fateful jump. It's easier to do "just after", since that's just the return address. We're going to pretend that instead of jumping into space, we jumped to a ret instruction.

    Since we don't know what the junk code did before it finally crashed, the current value of rsp is probably not accurate. We'll have to think backward to a point in time whose stack pointer we can infer, and then replay the code forward.

    From our knowledge of stack frames, we see that the rsp register had the value 001ebfb0 during the execution of DoesUserPreferMetric­Units just before it called the bad function pointer. Let's temporarily set our rsp and rip to simulate the return from the function.

    0:000> r rsp=1ebfb0
    0:000> r rip=ff6e28ae 
    0:000> k
    Child-SP          RetAddr           Call Site
    00000000`001ebfb0 00000000`ff6e2b9b ABC!DoesUserPreferMetricUnits+0x2a
    00000000`001ebff0 00000000`ff6e2a94 ABC!CUIController::UpdateDisplay+0x156
    00000000`001ec060 00000000`ff6e2f70 ABC!CUIController::displayEvent+0xea
    00000000`001ec090 00000000`ff6e2eef ABC!CEventRouter::fire+0x34
    00000000`001ec0d0 00000000`ff6e3469 ABC!CEngineState::storeAndFire+0x126
    00000000`001ec110 00000000`ff6e4149 ABC!CEngine::SetDisplayText+0x39
    00000000`001ec140 00000000`ff6ea48d ABC!CEngine::DisplayResult+0x648
    00000000`001ec3c0 00000000`ff6e49c6 ABC!CEngine::ProcessCommandWorker+0xa1a
    00000000`001ec530 00000000`ff6e4938 ABC!CEngine::ProcessCommand+0x2a
    00000000`001ec560 00000000`ff6e460a ABC!CUIController::ProcessInput+0xaa
    00000000`001ec5a0 00000000`ff6e4744 ABC!CContainer::ProcessInputs+0x7a1
    00000000`001ec700 00000000`77a6c3c1 ABC!CContainer::WndProc+0xa12
    00000000`001ecbe0 00000000`77a6a6d8 USER32!UserCallWinProcCheckWow+0x1ad
    00000000`001ecca0 00000000`77a6a85d USER32!SendMessageWorker+0x682
    00000000`001ecd30 00000000`ff70c5d8 USER32!SendMessageW+0x5c
    00000000`001ecd80 00000000`77a5e53b ABC!CMainDlgFrame::MainDlgProc+0x87
    00000000`001ecdc0 00000000`77a5e2f2 USER32!UserCallDlgProcCheckWow+0x1b6
    00000000`001ece80 00000000`77a5e222 USER32!DefDlgProcWorker+0xf1
    00000000`001ecf00 00000000`77a6c3c1 USER32!DefDlgProcW+0x36
    00000000`001ecf40 00000000`77a6a6d8 USER32!UserCallWinProcCheckWow+0x1ad
    00000000`001ed000 00000000`77a6a85d USER32!SendMessageWorker+0x682
    00000000`001ed090 000007fe`fc890ba3 USER32!SendMessageW+0x5c
    00000000`001ed0e0 000007fe`fc8947e2 COMCTL32!Button_ReleaseCapture+0x157
    00000000`001ed120 00000000`77a6c3c1 COMCTL32!Button_WndProc+0xcde
    00000000`001ed1e0 00000000`77a6c60a USER32!UserCallWinProcCheckWow+0x1ad
    00000000`001ed2a0 00000000`ff6e1a76 USER32!DispatchMessageWorker+0x3b5
    00000000`001ed320 00000000`ff6fa00f ABC!WinMain+0x1db4
    00000000`001efa10 00000000`7794f33d ABC!__mainCRTStartup+0x18e
    00000000`001efad0 00000000`77b82ca1 kernel32!BaseThreadInitThunk+0xd
    00000000`001efb00 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
    0:000> r rsp=001ebf68
    0:000> r rip=ff6ebaad
    

    After getting what we want, we restore the registers to their original values at the time of the crash so that future investigation won't be misled by our editing.

Page 372 of 455 (4,549 items) «370371372373374»