Introduction
In my previous two articles, I have shown you how to access an NDIS miniport driver using the DeviceIOControl and the Windows Management Instrumentation (WMI) mechanisms. This article focuses more on the Native Wifi API. Native Wifi API is basically designed for C/C++ programmers. This API contains a lot of functions for wireless network connectivity and profile management.
Earlier, programmers would query OIDs using DeviceIOControl or WMI for accessing the various parameters of a wireless network. Microsoft makes this easy by introducing the native Wifi API. Now, we don't have to query miniport drivers directly. We can use Wifi APIs from our applications just like using Win32 APIs.
Background
Microsoft has come up with the Native Wifi API; a new API for managing wireless network connectivity and profiles. Client applications running Windows Vista or Windows XP SP2 can use this API. Microsoft has incorporated this API into Vista, by default.
Windows XP SP2 also supports a subset of the native Wifi API. But the user has to install an additional package/hotfix for getting this API support in a Windows XP ASP2 environment. You can check more about the wireless LAN API for Windows XP SP2 from the Microsoft website.
Using the code
In the example given below, we will see how to enumerate wireless adapters using the Wifi API. The Wifi API provides a lot of functions for querying various parameters of wireless networks.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
PlatformInvoke.wifi wifiAPI = new PlatformInvoke.wifi();
wifiAPI.EnumerateNICs();
}
}
}
namespace PlatformInvoke
{
class wifi
{
#region declarations
private const int WLAN_API_VERSION_2_0 = 2;
private const int ERROR_SUCCESS = 0;
[DllImport("wlanapi.dll", SetLastError = true)]
private static extern UInt32 WlanOpenHandle(UInt32 dwClientVersion,
IntPtr pReserved, out UInt32 pdwNegotiatedVersion,
out IntPtr phClientHandle);
[DllImport("wlanapi.dll", SetLastError = true)]
private static extern UInt32 WlanCloseHandle(IntPtr hClientHandle,
IntPtr pReserved);
[DllImport("wlanapi.dll", SetLastError = true)]
private static extern UInt32 WlanEnumInterfaces(IntPtr hClientHandle,
IntPtr pReserved, out IntPtr ppInterfaceList);
[DllImport("wlanapi.dll", SetLastError = true)]
private static extern void WlanFreeMemory(IntPtr pmemory);
public enum WLAN_INTERFACE_STATE : int
{
wlan_interface_state_not_ready = 0,
wlan_interface_state_connected,
wlan_interface_state_ad_hoc_network_formed,
wlan_interface_state_disconnecting,
wlan_interface_state_disconnected,
wlan_interface_state_associating,
wlan_interface_state_discovering,
wlan_interface_state_authenticating
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct WLAN_INTERFACE_INFO
{
public Guid InterfaceGuid;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string strInterfaceDescription;
public WLAN_INTERFACE_STATE isState;
}
[StructLayout(LayoutKind.Sequential)]
public struct WLAN_INTERFACE_INFO_LIST
{
public Int32 dwNumberofItems;
public Int32 dwIndex;
public WLAN_INTERFACE_INFO[] InterfaceInfo;
public WLAN_INTERFACE_INFO_LIST(IntPtr pList)
{
dwNumberofItems = Marshal.ReadInt32(pList, 0);
dwIndex = Marshal.ReadInt32(pList, 4);
InterfaceInfo = new WLAN_INTERFACE_INFO[dwNumberofItems];
for (int i = 0; i < dwNumberofItems; i++)
{
IntPtr pItemList = new IntPtr(pList.ToInt32() + (i * 532) + 8);
WLAN_INTERFACE_INFO wii = new WLAN_INTERFACE_INFO();
wii = (WLAN_INTERFACE_INFO)Marshal.PtrToStructure(pItemList,
typeof(WLAN_INTERFACE_INFO));
InterfaceInfo[i] = wii;
}
}
}
#endregion
#region Private Functions
private string getStateDescription(WLAN_INTERFACE_STATE state)
{
string stateDescription=string.Empty;
switch (state)
{
case WLAN_INTERFACE_STATE.wlan_interface_state_not_ready:
stateDescription = "not ready to operate";
break;
case WLAN_INTERFACE_STATE.wlan_interface_state_connected:
stateDescription = "connected";
break;
case WLAN_INTERFACE_STATE.wlan_interface_state_ad_hoc_network_formed:
stateDescription = "first node in an adhoc network";
break;
case WLAN_INTERFACE_STATE.wlan_interface_state_disconnecting:
stateDescription = "disconnecting";
break;
case WLAN_INTERFACE_STATE.wlan_interface_state_disconnected:
stateDescription = "disconnected";
break;
case WLAN_INTERFACE_STATE.wlan_interface_state_associating:
stateDescription = "associating";
break;
case WLAN_INTERFACE_STATE.wlan_interface_state_discovering:
stateDescription = "discovering";
break;
case WLAN_INTERFACE_STATE.wlan_interface_state_authenticating:
stateDescription = "authenticating";
break;
}
return stateDescription;
}
#endregion
#region Public Functions
public void EnumerateNICs()
{
uint serviceVersion = 0;
IntPtr handle = IntPtr.Zero;
if(WlanOpenHandle(WLAN_API_VERSION_2_0, IntPtr.Zero,
out serviceVersion, out handle) == ERROR_SUCCESS)
{
IntPtr ppInterfaceList = IntPtr.Zero;
WLAN_INTERFACE_INFO_LIST interfaceList;
if (WlanEnumInterfaces(handle, IntPtr.Zero,
out ppInterfaceList) == ERROR_SUCCESS)
{
interfaceList = new WLAN_INTERFACE_INFO_LIST(ppInterfaceList);
Console.WriteLine("Enumerating Wireless Network Adapters...");
for (int i = 0; i < interfaceList.dwNumberofItems; i++)
Console.WriteLine("{0}-->{1}",
interfaceList.InterfaceInfo[i].strInterfaceDescription,
getStateDescription(interfaceList.InterfaceInfo[i].isState));
if (ppInterfaceList != IntPtr.Zero)
WlanFreeMemory(ppInterfaceList);
}
WlanCloseHandle(handle, IntPtr.Zero);
}
}
#endregion
}
}
The above code is written in C# using the Platform Invoke mechanism, and it shows each wirless adapter name and its state.
Conclusion
This article demonstrates how to access the Wifi API from a C# .NET application. The Wifi API exposes a lot of functionality and you can explore each one of them.
References
- http://www.codeproject.com/KB/system/DeviceIOControl1.aspx
- http://www.codeproject.com/KB/system/WMIInterface.aspx