Search code examples
javanativejnawifi

Odd return from WlanEnumInterfaces (Windows Native WiFi) in Java


I'm trying to map the Windows Native Wifi API in Java but I'm having problems with the WlanEnumInterfaces function. Basically, this function outputs a WLAN_INTERFACE_INFO_LIST structure containing an array of WLAN_INTERFACE_INFO structures. When I call the WlanEnumInterfaces in my Java program, its return value indicates that the function succeeds, but when I check the number of items in the WLAN_INTERFACE_INFO array, I get inconsistent values like 1367280 or 4000000. This value should be 1 as I have only one wireless interface on my machine. Here it's my mapping of the WlanEnumInterfaces function:

public int WlanEnumInterfaces(
        HANDLE hClientHandle,
        PointerByReference pReserved,
        WLAN_INTERFACE_INFO_LIST.ByReference ppInterfaceList);

Implementation of WLAN_INTERFACE_INFO_LIST:

public static class WLAN_INTERFACE_INFO_LIST extends Structure {
    public static class ByReference extends WLAN_INTERFACE_INFO_LIST implements Structure.ByReference{}
    public int dwNumberOfItems;
    public int dwIndex;
    public WLAN_INTERFACE_INFO[] InterfaceInfo = new WLAN_INTERFACE_INFO[10];


    @Override
    protected List getFieldOrder() {
        return Arrays.asList(new String[] {"dwNumberOfItems","dwIndex","InterfaceInfo"});
    }
}

And part of the code that calls the function:

HANDLE wlanHandle = getWlanHandle();
WLAN_INTERFACE_INFO_LIST.ByReference ppInterfaceList = new WLAN_INTERFACE_INFO_LIST.ByReference();

int ret = Wlanapi.INSTANCE.WlanEnumInterfaces(wlanHandle,null,ppInterfaceList);
System.out.println("Return: " + ret);    
System.out.println("WlanEnumInterfaces->number of items: "+ppInterfaceList.dwNumberOfItems);

Does anyone know what is happening? Thanks!


Solution

  • The WlanEnumInterfaces populates the field you provide it with the address of a struct. You are passing in the address of a struct rather than the address of an address.

    Use PointerByReference to get the address of the struct, e.g.

    PointerByReference pref = new PointerByReference();
    Wlanapi.INSTANCE.WlanEnumInterfaces(handle, null, pref);
    WLAN_INTERFACE_INFO_LIST list = new WLAN_INTERFACE_INFO_LIST(pref.getValue());
    

    Then you need a Pointer-based constructor for WLAN_INTERFACE_INFO_LIST, i.e.

    WLAN_INTERFACE_INFO_LIST(Pointer p) {
        super(p);
        this.dwNumberOfItems = p.readInt(0);
        this.InterfaceInfo = new WLAN_INTERFACE_INFO[this.dwNumberOfItems];
        read();
    }