Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get IntPtr to a boolean value

For a function marshalled like that:

/*************************************************
*  DWORD WINAPI WlanHostedNetworkSetProperty(
*      _In_        HANDLE hClientHandle,
*      _In_        _WLAN_HOSTED_NETWORK_OPCODE OpCode,
*      _In_        DWORD dwDataSize,
*      _In_        PVOID pvData,
*      _Out_opt_   P_WLAN_HOSTED_NETWORK_REASON pFailReason,
*      _Reserved_  PVOID pvReserved
*  );
*************************************************/
[DllImport("Wlanapi.dll", SetLastError = true)]
public static extern UInt32 WlanHostedNetworkSetProperty(
    [In] IntPtr hClientHandle,
    [In] _WLAN_HOSTED_NETWORK_OPCODE OpCode,
    [In] UInt32 dwDataSize,
    [In] IntPtr pvData,
    [Out] out _WLAN_HOSTED_NETWORK_REASON pFailReason,
    [In, Out] IntPtr pvReserved
);

Microsoft documentation says that when I pass

_WLAN_HOSTED_NETWORK_OPCODE._WLAN_HOSTED_NETWORK_OPCODE_enable

as a parameter of OpCode, the value of pvData should be a pointer to a Boolean value.
Hereis the documentation for that function
I have no idea though how to get an IntPtr to point to a Boolean?
Should it be done in a similar way to when I pass a pointer to a struct as pvData :

int size = Marshal.SizeOf(settings); //*settings* is a struct with some data
IntPtr pSettings = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(settings, pSettings, true);

/* use the IntPtr */

Marshal.FreeHGlobal(pSettings);

But instead I marshal the Boolean? Or is there an easier way?

Thanks for your help all lovely people.

like image 328
Daniel Gruszczyk Avatar asked Dec 19 '12 14:12

Daniel Gruszczyk


2 Answers

Win32 BOOL is DWORD. You can define pvData as ref UInt32 or ref Int32 for this case. Or leave pvData as IntPtr, allocate unmanaged memory with Marshal.AllocHGLobal(Marshal.SizeOf(Int32)), and fill this memory with Marshal.WriteInt32.

int size = Marshal.SizeOf(Int32);
IntPtr pBool = Marshal.AllocHGlobal(size);
Marshal.WriteInt32(pBool, 0, 1);  // last parameter 0 (FALSE), 1 (TRUE)

/* use the IntPtr */

Marshal.FreeHGlobal(pBool);
like image 176
Alex F Avatar answered Sep 23 '22 15:09

Alex F


Oh, yes, there's a much easier way. This can be very elegantly done in C# because it supports method overloading. A feature that doesn't exist in C and thus requires the PVOID argument type. You can simply declare the argument as ref bool. The marshaller will create the storage for the BOOL before calling the native function and pass a pointer to it. Converting and copying the result back into the bool variable you pass after the call.

If you have additional calls for this function that require a different data type then just repeat the declaration. This time specifying, say, ref uint if you are supposed to pass a pointer to a DWORD. Etcetera. The C# compiler's method overload resolution feature ensures that the correct pinvoke declaration is used.

like image 38
Hans Passant Avatar answered Sep 21 '22 15:09

Hans Passant