Search code examples
c#c++pinvoke

Calling C++ method from C# with pointer parameter (WCT)


I am new to this concept of calling C++ methods from C#.

Assuming that I want to call a C++ function GetThreadWaitChain from C#:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms679364(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/ms681623(v=vs.85).aspx

And I've built a model of other types on which the call depends:

[DllImport("Advapi32.dll")]
public static extern void CloseThreadWaitChainSession(IntPtr WctHandle);

 [DllImport("Advapi32.dll")]
 public static extern HANDLE OpenThreadWaitChainSession(UInt32 Flags, UInt32 callback);

[DllImport("Advapi32.dll")]
        public static extern BOOL GetThreadWaitChain(
            IntPtr WctHandle,
            UInt32 Context,
            UInt32 flags,
            UInt32 ThreadId,
            WAITCHAIN_NODE_INFO NodeInfoArray,
            UInt32 IsCycle
        );

[StructLayout(LayoutKind.Sequential)]
public struct WAITCHAIN_NODE_INFO
{
    public UInt32 ObjectType;
    public UInt32 ObjectStatus;

    public struct LockObject
    {
        string ObjectName;                
        UInt64 Timeout;
        UInt32 Alertable;
    }

    public struct ThreadObject
    {
        UInt32  ProcessId;
        UInt32  ThreadId;
        UInt32  WaitTime;
        UInt32  ContextSwitches;
    }
}

How can I call GetThreadWaitChain function? It accepts a pointer to WAITCHAIN_NODE_INFO struct...

Currently, that's how I figured out to call the function (obviously it doesn't works) :

 void CollectWaitInformation(int threadId)
{
    var wctHandle = OpenThreadWaitChainSession(0, 0);
    WAITCHAIN_NODE_INFO info = new WAITCHAIN_NODE_INFO();
    var result =  GetThreadWaitChain(wctHandle, 0,
        GetThreadWaitChainFlags.WCT_OUT_OF_PROC_COM_FLAG, threadID, info , 0);
}

Are my C++ types mapping to C# types right?


Solution

  • The GetThreadWaitChain function prototype is incorrect. It should be:

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool GetThreadWaitChain(
        IntPtr  WctHandle,
        IntPtr Context,
        UInt32 Flags,
        int ThreadId,
        ref int NodeCount,    
        [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] 
        [In, Out] 
        WAITCHAIN_NODE_INFO[] NodeInfoArray,  
        out int IsCycle
    );
    

    When calling first allocate the WAITCHAIN_NODE_INFO array.

    WAITCHAIN_NODE_INFO[] data = new WAITCHAIN_NODE_INFO[16];