• The Old New Thing

    I saw a pinvoke signature that passed a UInt64 instead of a FILETIME, what's up with that?


    A customer had a question about a pinvoke signature that used a UInt64 to hold a FILETIME structure.

    [DllImport("kernel32.dll", SetLastError = true)
    static external bool GetProcessTimes(
        IntPtr hProcess,
        out UInt64 creationTime,
        out UInt64 exitTime,
        out UInt64 kernelTime,
        out UInt64 userTime);

    Is this legal? The documentation for FILETIME says

    Do not cast a pointer to a FILETIME structure to either a ULARGE_INTEGER* or __int64* value because it can cause alignment faults on 64-bit Windows.

    Are we guilty of this cast in the above code? After all you can't treat a FILETIME as an __int64.

    There are two types of casts possible in this scenario.

    • Casting from FILETIME* to __int64*.
    • Casting from __int64* to FILETIME*.

    The FILETIME structure requires 4-byte alignment, and the __int64 data type requires 8-byte alignment. Therefore the first cast is unsafe, because you are casting from a pointer with lax alignment requirements to one with stricter requirements. The second cast is safe because you are casting from a pointer with strict alignment requirements to one with laxer requirements.

    4-byte aligned 8-byte aligned

    Everything in the blue box is also in the pink box, but not vice versa.

    Which cast is the one occurring in the above pinvoke signature?

    In the above signature, the UInt64 is being allocated by the interop code, and therefore it is naturally aligned for UInt64, which means that it is 8-byte aligned. The Get­Process­Times function then treats those eight bytes as a FILETIME. So we are in the second case, where we cast from __int64* to FILETIME*.

    Mind you, you can avoid all this worrying by simply declaring your pinvoke more accurately. The correct solution is to declare the last four parameters as ComTypes.FILETIME. Now there are no sneaky games. Everything is exactly what it says it is.

    Bonus reading: The article Use PowerShell to access registry last-modified time stamp shows how to use the ComTypes.FILETIME technique from PowerShell.

  • The Old New Thing

    If you are going to call Marshal.GetLastWin32Error, the function whose error you're retrieving had better be the one called most recently


    Even if you remember to set Set­Last­Error=true in your p/invoke signature, you still have to be careful with Marshal.Get­Last­Win32­Error because there is only one last-error code, and it gets overwritten each time.

    So let's try this program:

    using System;
    using System.Runtime.InteropServices;
    class Program
      [DllImport("user32.dll", SetLastError=true)]
      public static extern bool OpenIcon(IntPtr hwnd);
      public static void Main()
        // Intentionally pass an invalid parameter.
        var result = OpenIcon(IntPtr.Zero);
        Console.WriteLine("result: {0}", result);
        Console.WriteLine("last error = {0}",

    The expectation is that the call to Open­Icon will fail, and the error code will be some form of invalid parameter.

    But when you run the program, it prints this:

    result: False
    last error = 0


    Zero means "No error". But the function failed. Where's our error code? We printed the result immediately after calling Open­Icon. We didn't call any other p/invoke functions. The last-error code should still be there.

    Oh wait, printing the result to the screen involves a function call.

    That function call might itself do a p/invoke!

    We have to call Marshal.Get­Last­Win32­Error immediately after calling Open­Icon. Nothing else can sneak in between.

    using System;
    using System.Runtime.InteropServices;
    class Program
      [DllImport("user32.dll", SetLastError=true)]
      public static extern bool OpenIcon(IntPtr hwnd);
      public static void Main()
        // Intentionally pass an invalid parameter.
        var result = OpenIcon(IntPtr.Zero);
        var lastError = Marshal.GetLastWin32Error();
        Console.WriteLine("result: {0}", result);
        Console.WriteLine("last error = {0}",

    Okay, now the program reports the error code as 1400: "Invalid window handle."

    This one was pretty straightforward, because the function call that modified the last-error code was right there in front of us. But there are other ways that code can run which are more subtle.

    • If you retrieve a property, the property retrieval may involve a p/invoke.
    • If you access a class that has a static constructor, the static constructor will secretly run if this is the first time the class is used.
  • The Old New Thing

    If you are going to call Marshal.GetLastWin32Error, the function whose error you're retrieving had better have SetLastError=true


    A customer reported that their p/invoke to a custom DLL was failing, and the error code made no sense.

    // C#
    using System;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    class Program
      [DllImport("contoso.dll", CallingConvention=CallingConvention.Cdecl)]
      public static extern int Fribble();
      public static void Main()
        Console.WriteLine("About to call Fribble");
        var result = Fribble();
        if (result >= 0) {
          Console.WriteLine("succeeded {0}", result);
        } else {
          Console.WriteLine("failed {0}, last error = {1}",
                            result, Marshal.GetLastWin32Error());
    // C++
    int __cdecl Fribble()
     if (hEvent == nullptr)
      return -1;
     if (!SetEvent(hEvent)) {
      return -2;
     return 1;

    The customer reported that their Fribble function was returning −1, indicating a failure to open the event, but the error code returned by Marshal.Get­Last­Win32­Error is 87, "The parameter is incorrect." But all of the parameters to Open­Event look correct. Why are we getting this strange error code?

    My psychic powers tell me that if the customer had taken the time to troubleshoot their problem by writing a C++ program that calls the Fribble function, Get­Last­Error would have returned the more reasonable error 2, meaning that the event does not exist.

    That's because Get­Last­Error is working fine. The last error code is 2.

    The problem is with the p/invoke declaration.

    The documentation for the Marshal.Get­Last­Win32­Error function says as its very first line

    Returns the error code returned by the last unmanaged function that was called using platform invoke that has the DllImportAttribute.SetLastError flag set.

    (Emphasis mine.)

    This reminder about Dll­Import­Attribute.Set­Last­Error is repeated in the Remarks.

    You can use this method to obtain error codes only if you apply the System.Runtime.Interop­Services.Dll­Import­Attribute to the method signature and set the Set­Last­Error field to true.

    Observe that the Set­Last­Error field was not set in the p/invoke declaration. Therefore, what you are actually getting when you call Marshal.Get­Last­Win32­Error is whatever error was lying around after the previous call to a p/invoke function that did specify Set­Last­Error = true.

    Changing the p/invoke to

    [DllImport("contoso.dll", SetLastError=true,
    public static extern int Fribble();

    fixed the problem.

  • The Old New Thing

    p/invoke gotcha: C++ bool is not Win32 BOOLEAN is not UnmanagedType.Bool


    Welcome to CLR Week. I hope you enjoy your stay.

    A customer reported that their p/invoke was not working.

    We aren't getting the proper return codes from the Audit­Set­System­Policy. When the call succeeds, the return code is 1, as expected. But in our tests, when we force the call to fail (insufficient access), the return code is not zero. Instead, the return code is some value of the form 0xFFxxxxxx, where the x's vary, but the high byte is always 0xFF.

    For reference, the DllImport declaration we are using is

    [DllImport("advapi32.dll", SetLastError=true)]
    public static extern UInt32 AuditSetSystemPolicy(
        IntPtr pAuditPolicy,
        UInt32 policyCount);

    The corresponding Win32 declaration is

    BOOLEAN WINAPI AuditSetSystemPolicy(
      _In_  ULONG PolicyCount

    Alas, the customer fell into one of the common gotchas when writing p/invoke: They confused BOOLEAN and BOOL.

    BOOL is a 32-bit integer, whereas BOOLEAN is an 8-bit integer.

    Since they were marshaling the return code as a UInt32, they were getting the byte returned by the function, plus three bonus uninitialized garbage bytes. If they studied more closely, they would have found that the erroneous return codes were all of the form 0xFFxxxx00 where the bottom 8 bits are all zero. That's because the bottom 8 bits are the actual value; the rest are garbage.

    The correct declaration is to use Unmanaged­Type.U1 aka byte rather than Unmanaged­Type.U4 aka UInt32.

    [DllImport("advapi32.dll", SetLastError=true)]
    public static extern byte AuditSetSystemPolicy(
        IntPtr pAuditPolicy,
        UInt32 policyCount);

    The customer confirmed that switching to Unmanaged­Type.U1 fixed the problem.

  • The Old New Thing

    Windows started picking up the really big pieces of TerminateThread garbage on the sidewalk, but it's still garbage on the sidewalk


    Ah, Terminate­Thread. There are still people who think that there are valid scenarios for calling Terminate­Thread.

    Can you explain how Exit­Thread works?

    We are interested because we have a class called Thread­Class. We call the Start() method , and then the Stop() method, and then the Wait­Until­Stopped() method, and then the process hangs with this call stack:


    Can you help us figure out what's going on?

    From the stack trace, it is clear that the thread is shutting down, and the loader (Ldr) is waiting on a critical section. The critical section the loader is most famous for needing is the so-called loader lock which is used for various things, most notably to make sure that all DLL thread notification are serialized.

    I guessed that the call to Wait­Until­Stopped() was happening inside Dll­Main, which created a deadlock because the thread cannot exit until it delivers its Dll­Main notifications, but it can't do that until the calling thread exits Dll­Main.

    The customer did some more debugging:

    The debugger reports the critical section as

    CritSec ntdll!LdrpLoaderLock+0 at 77724300
    WaiterWoken        No
    LockCount          3
    RecursionCount     1
    OwningThread       a80
    EntryCount         0
    ContentionCount    3
    *** Locked

    The critical section claims that it is owned by thread 0xa80, but there is no such active thread in the process. In the kernel debugger, a search for that thread says

    Looking for thread Cid = a80 ...
    THREAD 8579e1c0  Cid 0b58.0a80  Teb: 00000000 Win32Thread: 00000000 TERMINATED
    Not impersonating
    DeviceMap                 862f8a98
    Owning Process            0       Image:         <Unknown>
    Attached Process          84386d90       Image:         Contoso.exe
    Wait Start TickCount      12938474       Ticks: 114780 (0:00:29:50.579)
    Context Switch Count      8             
    UserTime                  00:00:00.000
    KernelTime                00:00:00.000
    Win32 Start Address 0x011167c0
    Stack Init 0 Current bae35be0 Base bae36000 Limit bae33000 Call 0
    Priority 10 BasePriority 8 PriorityDecrement 2 IoPriority 2 PagePriority 5

    Contoso.exe is our process.

    Okay, we're getting somewhere now. The thread 0xa80 terminated while it held the loader lock. When you run the program under a debugger, do you see any exceptions that might suggest that the thread terminated abnormally?

    We found the cause of the problem. We use Terminate­Thread in the other place. That causes the thread to continue to hold the loader lock after it has terminated.

    It's not clear what the customer meant by "the other place", but no matter. The cause of the problem was found: They were using Terminate­Thread.

    At this point, Larry Osterman was inspired to write a poem.

    How many times does
    it have to be said: Never
    call TerminateThread.

    In the ensuing discussion, somebody suggested,

    One case where it is okay to use Terminate­Thread is if the thread was created suspended and has never been resumed. I believe it is perfectly legal to terminate it, at least in Windows Vista and later.

    No, it is not "perfectly legal," for certain values of "perfectly legal."

    What happened is that Windows Vista added some code to try to limit the impact of a bad idea. Specifically, it added code to free the thread's stack when the thread was terminated, so that each terminated thread didn't leak a megabyte of memory. In the parlance of earlier discussion, I referred to this as stop throwing garbage on the sidewalk.

    In this case, it's like saying, "It's okay to run this red light because the city added a delayed green to the cross traffic." The city added a delayed green to the cross traffic because people were running the light and the city didn't want people to die. That doesn't mean that it's okay to run the light now.

    Unfortunately, the guidance that says "Sometimes it's okay to call Terminate­Thread" has seeped into our own Best Practices documents. The Dynamic-Link Library Best Practices under Best Practices for Synchronization describes a synchronization model which actually involves calling Terminate­Thread.

    Do not do this.

    It's particularly sad because the downloadable version of the document references both Larry and me telling people to stop doing crazy things in Dll­Main, and terminating threads is definitely a crazy thing.

    (The solution to the problem described in the whitepaper is not to use Terminate­Thread. It's to use the Free­Library­And­Exit­Thread pattern.)

    Now the history.

    Originally, there was no Terminate­Thread function. The original designers felt strongly that no such function should exist because there was no safe way to terminate a thread, and there's no point having a function that cannot be called safely. But people screamed that they needed the Terminate­Thread function, even though it wasn't safe, so the operating system designers caved and added the function because people demanded it. Of course, those people who insisted that they needed Terminate­Thread now regret having been given it.

    It's one of those "Be careful what you wish for" things.

  • The Old New Thing

    Crashes in the I/O stack tend to occur in programs which do the most I/O


    A customer was diagnosing repeated blue screen errors on their system. They shared a few crash dumps, and they all had a similar profile: The crash occurred in the file system filter stack as the I/O request passed through the anti-virus software.

    Some of the crashes reported PROCESS_NAME: ngen.exe. "Could ngen.exe be the problem?"

    As a general rule, user-mode code cannot be responsible for blue-screen failures. It's the job of the kernel to be resistant to misbehavior in user-mode. Failures of the form IRQL_NOT_LESS_THAN_OR_EQUAL and PAGE_FAULT_IN_NON_PAGED_AREA are typically driver bugs or faulty hardware (for example, due to overheating or overclocking).

    The application that happened to be active at the time of the failure is not typically interesting in and of itself, although it can give a clue as to what part of the kernel is misbehaving. The fact that ngen appears is more an indication that ngen performs a lot of disk I/O, so if there's a problem in the I/O stack, there's a good chance that ngen was involved, simply because ngen is involved in a lot of I/O requests.

    • Bob goes to the beach very frequently.
    • Every time there is a shark attack, Bob is at the beach.
    • Conclusion: Bob causes shark attacks.

    Blaming ngen for the kernel crash is like blaming Bob for the shark attacks.

    Bonus chatter: Some of my colleagues came to different conclusions:

    • Conclusion: Bob should stop going to the beach.
    • Conclusion: Bob must be the shark.

  • The Old New Thing

    Why does the taskbar icon for grouped windows change to something weird?


    This question came in from two customers. I'm pretty sure it was two customers rather than one customer going on a fishing expedition because the questions came six months apart, and the scenarios were different.

    Suppose you remove all shortcuts to Explorer from the taskbar and the Start menu. Then you create a shortcut to Explorer and put it on the desktop. Wait, you're not done yet. Now view the Properties of that shortcut, use the Change Icon button, and give it some random icon. The uglier the better.

    Last step: Go to the Taskbar properties and set Taskbar buttons to Always combine, hide labels.

    All right, now open an Explorer window. Observe that it has the ugly icon in the taskbar rather than an icon that matches the Explorer window that you opened.

    What's going on here?

    Last step first: Since you configured the taskbar as Always combine, the icon for the Explorer does not come from the window itself, but is rather the group icon.

    Okay, so where does the taskbar get the group icon from? The taskbar looks in the following places to get the group icon:

    1. A shortcut on the Start menu.
    2. A shortcut on the desktop.
    3. The executable itself.

    Normally, a shortcut is found on the Start menu, but in this case, the user explicitly removed all shortcuts to explorer.exe from the Start menu. That means that the winner was the shortcut on the desktop. That shortcut has a really ugly icon, so the taskbar shows the really ugly icon.

    In other words, the reason you're getting an ugly icon is that when Windows tries to figure out the icon to show for Explorer groups, you deleted all the good icons and left only the ugly icon.

    Okay, so why does the taskbar even bother looking at shortcuts on the Start menu and on the desktop? Why doesn't it just show the icon for the executable itself?

    A lot of applications don't bother giving their executable a nice icon. The theory being, "Well, we give our Start menu shortcut a nice icon. And when the program runs, it registers a nice icon when it calls Register­Class. The executable itself is buried off in the Program Files directory, which nobody should be messing with anyway, so who cares if it has an ugly icon there?" And then when the taskbar first added the "group icons" feature, a lot of programs showed the wrong icon when collapsed to a group.

    MFC logo 3 Contoso Designer

    So that's where the first rule comes from: See if there is a shortcut to the program on the Start menu. If so, then use that icon, because that's the icon the program wants to show to the user to say "Hey, run my program!"

    But even with that, there were still some incorrect icons. Those were from programs who installed their shortcut on the desktop rather than the Start menu. That's why there is rule number two.

    Only if there is no shortcut on the Start menu or the desktop does the taskbar look to the executable itself.

    It so happens that Explorer already has to keep track of every shortcut on the Start menu and on the desktop, because it needs to keep track of any hotkeys registered by those shortcuts. Having it keep track of yet another piece of information for every shortcut wasn't too much of an extra burden.

    Bonus chatter: Why not just create a compatibility shim for these ugly applications?

    In general, when you find these sorts of compatibility issues, you can choose to fix them either by accommodating the issue in the core operating system, or by creating a compatibility shim that applies only to the applications affected by the issue. If the problem is widespread, then you just have to suck it up and put the compatibility behavior in the core operating system. Otherwise, the compatibility database would be bloated with thousands of entries. What's more, it's clear that there will be a very long tail of affected applications, seeing as the default icon for MFC applications is the generic MFC icon, and there are probably a whole lot of vertical-market and line-of-business applications that are just using the default icon without realizing it. These applications are not big-market mainstream applications, so they will likely never come to the attention of the application compatibility team.

  • The Old New Thing

    The ARM processor architecture: Somebody else's introduction


    While you wait for me to write the Alpha AXP processor architecture overview,¹ I'd like to direct your attention to the ARM processor architecture overview written up by Marion Cole over at the NT Debugging blog. I hope that'll keep you busy for a little while longer.

    ¹ Spoiler alert: Don't hold your breath.

  • The Old New Thing

    The changing fortunes of being the last program on the Start menu


    One of the thing I didn't mention during my discussion lo many years ago on how Windows XP chooses what goes on the front page of the Start menu is that the the last-place position is actually kind of special.

    In Windows Vista, the last-place position was used to hold the program you ran most recently, regardless of how often you ran it. In a sense, the last slot is a one-entry MRU. (This was the general idea, although it could be overridden by other principles. For example, if the program you last ran is pinned, then it shows up in its natural pinned location rather than being shoved to the bottom of the Start menu.)

    In Windows 7, the magical last-place position goes to the application you just installed, if one exists, to save you the trouble of hunting for it. (As we saw some time ago, you can set the System.App­User­Model.Exclude­From­Show­In­New­Install property to remove your shortcut from consideration as a newly-installed program.)

  • The Old New Thing

    What if I have two programs that are logically a single application, and I want them to be treated as a single group on the taskbar?


    Suppose you have two programs that are logically one application, and you want them to be treated as a single group on the taskbar, share jump lists, and all that stuff. Basically, even though they are physically separate executables, they should be logically be treated as two facets of the same application.

    This the opposite of What if my application is really two applications bundled into a single file, and I want them collected into two groups on the taskbar in Windows 7?. But the solution is the same.

    As noted in the linked article, the central concept is the Application User Model ID. The shell uses the Application User Model ID to identify applications. If you give two processes the same Application User Model ID, then they will be treated as two instances of the same application. If you give them different Application User Model IDs, then they will be treated as instances of separate applications.

    In the linked article, we had two processes running from the same executable, but we wanted them to be treated as separate applications, so we gave them different Application User Model IDs. Today, we have two processes running from separate executables, but we want them to be treated as the same application. Solution: Give them the same Application User Model ID.

    Start with our scratch program and make these changes:


    Tricked you! We're not changing anything. Just compile and run it. Then copy scratch.exe to scratch2.exe and run that. Observe that the two windows are not grouped together in the taskbar.

    Okay, now let's make these changes:

    #include <shlobj.h>
    int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev,
                       LPSTR lpCmdLine, int nShowCmd)

    Compile and run this program, then copy scratch.exe to scratch2.exe and run the second copy. This time, the two windows are grouped together because they have the same Application User Model ID.

    Bonus chatter: If you create a shortcut to the application, you should also assign the custom Application User Model ID to the shortcut. That way, if the user calls up the jump list for the shortcut, they get the jump list for the correct Application User Model ID.

Page 5 of 461 (4,602 items) «34567»