dahall / Vanara

A set of .NET libraries for Windows implementing PInvoke calls to many native Windows APIs with supporting wrappers.
MIT License
1.81k stars 196 forks source link

Problems using WlanGetNetworkBssList of the WLAN API #470

Closed NilsHoyer closed 4 months ago

NilsHoyer commented 4 months ago

I have the following code, I believe I should be able to execute as well. But my App crashes, without a special error message or exception. So, I believe, it based on a memory violation, maybe based on a wrong struct or function definition in your code.

The problem occurs only, if I use the WlanGetNetworkBssList, if not, everything works like excepted.

Unfortunately, I don't have an idea, how I can offer better information to reproduce or hunt this issue 😥.

The networkInterface is a part of the result from NetworkInterface.GetAllNetworkInterfaces(), checked it's a WLAN interface.

My code:

static void ThrowException(Win32Error win32Error)
{
    if (win32Error != ERROR_SUCCESS)
        throw new Exception(win32Error.ToString());
}

ThrowException(WlanOpenHandle(2, 0, out var _, out var clientHandle));

ThrowException(WlanQueryInterface(
    clientHandle,
    Guid.Parse(networkInterface.Id),
    wlan_intf_opcode_current_connection,
    0,
    out var _,
    out var data,
    out var _));

var connectionAttributes = Marshal.PtrToStructure<WLAN_CONNECTION_ATTRIBUTES>(data);

if (WlanGetNetworkBssList(
    clientHandle,
    Guid.Parse(networkInterface.Id),
    connectionAttributes.wlanAssociationAttributes.dot11Ssid,
    connectionAttributes.wlanAssociationAttributes.dot11BssType,
    connectionAttributes.wlanSecurityAttributes.bSecurityEnabled,
    0,
    out var ppWlanBssList) == ERROR_SUCCESS)
{
    ...

    WlanFreeMemory(ppWlanBssList);
}

WlanFreeMemory(data);

ThrowException(WlanCloseHandle(clientHandle));
dahall commented 4 months ago

Working on this now, fix or resolution shortly.

FYI If you're using Vanara, both HRESULT and Win32Error have a ThrowIfFailed method you can use like

WlanOpenHandle(2, 0, out var _, out var clientHandle).ThrowIfFailed();

Win32Error provides some methods similar to your ThrowException for other return values (HANDLE, int, etc.) when methods use SetLastError to provide error codes.

dahall commented 4 months ago

I was able to get this working with the current code base using the following:

using var hWlan = WlanOpenHandle();
WlanQueryInterface(hWlan, PrimaryInterface, WLAN_INTF_OPCODE.wlan_intf_opcode_current_connection,
   default, out _, out SafeHWLANMEM? data, out _).ThrowIfFailed();
var connectionAttributes = data.DangerousGetHandle().ToStructure<WLAN_CONNECTION_ATTRIBUTES>();
WlanGetNetworkBssList(hWlan, PrimaryInterface, connectionAttributes.wlanAssociationAttributes.dot11Ssid,
   connectionAttributes.wlanAssociationAttributes.dot11BssType, connectionAttributes.wlanSecurityAttributes.bSecurityEnabled,
   default, out var mem).ThrowIfFailed();
var list = mem.DangerousGetHandle().ToStructure<WLAN_BSS_LIST>()!;
Console.Write(string.Join("\n", list.wlanBssEntries.Select(e => $"{e.uPhyId}\t{e.dot11Bssid}\t{e.dot11BssType}\t" +
   "{e.dot11BssPhyType}\tstr={e.lRssi}\tper={e.usBeaconPeriod}\tfrq={e.ulChCenterFrequency}\t{e.ulIeOffset}:{e.ulIeSize}")));

WlanCloseHandle and WlanFreeMemory are automatically called by the Safe handles.

NilsHoyer commented 4 months ago

Thanks a lot for your attention, work and suggestions!