Search code examples
c#-4.0pinvokecomctl32

PinvokeStackImbalance calling comctl32 With CallingConvention.Cdecl


We've just upgraded our projects from .NET 3.5SP1 to .NET 4.5 and now we're getting the PInvokeStackImbalance MDA on a call to DllGetVersion from comctl32. I've read around and understand that the Framework is no longer resilient to incorrect calling conventions by default. What is strange is that we are already specifying CallingConvention.Cdecl which I believe is the correct one. If I remove the CallingConvention attribute altogether and let it default (CallingConvention.WinAPI), we don't get the PInvokeStackImbalance. Can anyone shed any light on this? OS is Win 7 64 bit and it's a 32 bit app if that makes any difference. I've tried looking at the header file for the DllGetVersion function but I can't figure out what the calling convention should be .

    [DllImport("Comctl32.dll", EntryPoint = "DllGetVersion", CallingConvention = CallingConvention.Cdecl)]
    private static extern int NativeDllGetVersion(ref DLLVERSIONINFO pdvi);

Solution

  • In general, any Windows API call should use CallingConvention.StdCall.

    In this case, if you look at the declaration of DllGetVersion, you'll see it's defined as:

    HRESULT CALLBACK DllGetVersion(DLLVERSIONINFO *pdvi);
    

    CALLBACK is defined as:

    #define CALLBACK __stdcall
    

    With the notes:

    CALLBACK, WINAPI, and APIENTRY are all used to define functions with the __stdcall calling convention. Most functions in the Windows API are declared using WINAPI. You may wish to use CALLBACK for the callback functions that you implement to help identify the function as a callback function.

    In your case, this means switching to StdCall is required.