How to map Win32 types to C# types when using P/Invoke?

What is LPCTSTR, and to what data type
does it map in C#?

LPCTSTR is a typedef for const TCHAR*.

TCHAR is an attempt to abstract away the fact that the Windows API exists in both “ANSI” (char strings in a locale-specific encoding) and “Unicode” (UTF-16) versions. There is no actual PdhOpenQuery function; there is a PdhOpenQueryA function that takes an ANSI string and a PdhOpenQueryW function that takes a UTF-16 string.

C# uses UTF-16 strings, so you’ll want to prefer the “W” version of these functions. Use PdhOpenQueryW. Then the first parameter has C++ type const wchar_t*. The C# type is [MarshalAs(UnmanagedType.LPWStr)] string.

How to map a pointer type DWORD_PTR?
The pinvoke article says DWORD maps to
UInt32, but how about pointers?

DWORD_PTR isn’t a pointer. It’s an unsigned integer big enough to hold a pointer. The equivalent C# type is System.UIntPtr.

I think PDH_STATUS and PDH_HQUERY are
specific struct to the library (I’m
not sure yet). how do I map these?

PDH_STATUS appears to be just an int.

PDH_HQUERY is a pointer to a handle (another pointer), but you can just pretend it’s an integer and use IntPtr.

Putting it all together, your declaration should be:

[DllImport("Pdh.dll")]
static extern int PdhOpenQueryW(
    [MarshalAs(UnmanagedType.LPWStr)] string szDataSource, 
    UIntPtr dwUserData,
    out IntPtr phQuery);

Leave a Comment