Click here to Skip to main content
15,880,796 members
Articles / Programming Languages / C#

How to query miniport driver information (802.11 OIDs) using the DeviceIOControl() function

Rate me:
Please Sign up or sign in to vote.
4.72/5 (15 votes)
10 Apr 2009CDDL3 min read 126.8K   2.4K   36   32
Query 802.11 OIDs using DeviceIOControl from a C# application.

Introduction

With this article, I would like to demonstrate how to query 802.11 OIDs from a C# .NET application. Noramlly, we use the DeviceIOControl API for querying an NDIS miniport driver. The DeviceIOControl API sends a control code directly to a specified device driver and the device performs the corresponding operation.

How to use the DeviceIOControl function from a C# application is ambiguous. Because the developer has to implement the platform invoke mechanism and need to take care of the marshaling of data between managed and unmanaged code.

I have seen a lot of queries in discussion forums about accessing a miniport driver from a C# application. This article demonstrates how to use the DeviceIOControl function from a C# application. As an example, we will see how to query for the signal strength of a wireless network.

Background

Device Driver programmers are familiar with the NDIS miniport driver. An NDIS miniport driver has two main functions: managing the network card and interfacing with other drivers like a protocol driver. Miniport drivers that support 802.11 interfaces for network interface cards must support all mandatory native IEEE 802.11 OIDs.

Using the code

In this article, I will show you a C# console application which queries the signal strength of the currently connected wireless network. This application uses the platform invoke mechanism and calls the DeviceIOControl function with control code OID_802_11_RSSI.

A OID_802_11_RSSI OID requests the miniport driver to return the signal strength of the wireless network.

C#
/// <summary>
/// Print Signal Strength value of currently connected wireless network
/// </summary>
public void printSignalStrength(string wlanInterfaceGuid)
{
    int hFileHandle = new int();
    IntPtr ptrOutput = IntPtr.Zero;
    IntPtr ptrInput = IntPtr.Zero;

    try
    {
        hFileHandle = INVALID_HANDLE_VALUE;
        string devName = string.Format("\\\\.\\{0}", wlanInterfaceGuid);

        //open handle
        hFileHandle = CreateFile(devName, GENERIC_READ | GENERIC_WRITE,
                    0,
                    (IntPtr)0,
                    OPEN_EXISTING,
                    0,
                    NULL);

        if (hFileHandle == INVALID_HANDLE_VALUE)
        {
            Console.WriteLine("Cannot open driver handle");
            return;
        }
        else
        {
            //OID - IOCTL_NDIS_QUERY_GLOBAL_STATS
            int IOCTL_NDIS_QUERY = new int();
            IOCTL_NDIS_QUERY = IOCTL_NDIS_QUERY_GLOBAL_STATS();

            //OID length
            uint oidCodeLength = 4; //bytes
            //size of output buffer
            uint OutputBufferSize = 1000;

            //bytes returned
            int bytesReturned = new int();
            //passing NDIS driver OID into DeviceIOControl
            GCHandle handle = GCHandle.Alloc(OID_802_11_RSSI,  GCHandleType.Pinned);

            ptrInput = handle.AddrOfPinnedObject();
          
            //Output buffer
            ptrOutput = Marshal.AllocHGlobal((int)OutputBufferSize);
            ZeroMemory(ptrOutput, (int)OutputBufferSize);

            //calling DeviceIOControl
            if (DeviceIoControl(hFileHandle, IOCTL_NDIS_QUERY, ptrInput, 
                oidCodeLength, ptrOutput, OutputBufferSize, out bytesReturned, 0))
            {
                Console.WriteLine("DeviceIOControl success");
     
                //Marshing data back into .net data type
                Int32 rssi = (Int32)Marshal.PtrToStructure(ptrOutput, typeof(Int32));
                //recived signal strength 
                Console.WriteLine("Received Signal Strength: {0}", rssi);
 
               if (ptrOutput != IntPtr.Zero)
               {
                   Marshal.FreeHGlobal(ptrOutput);
                   ptrOutput = IntPtr.Zero;
               }

               handle.Free();

            }
            else
            {
                Console.WriteLine("DeviceIOControl failed");
            }
        }
    }
    catch (Exception e)
    {
        Console.WriteLine("Exception: {0}", e.Message);
    }
    finally
    {
        //free allocated
        if (ptrOutput != IntPtr.Zero)
        Marshal.FreeHGlobal(ptrOutput);
        //close device handle
        CloseHandle(hFileHandle);
    }
}

The above code snippet shows how to query a 802.11 OID using the DeviceIOControl function. Let me explain the details here.

C#
string devName = string.Format("\\\\.\\{0}", wlanInterfaceGuid);
//open handle
hFileHandle = CreateFile(devName, GENERIC_READ | GENERIC_WRITE,
            0,
            (IntPtr)0,
            OPEN_EXISTING,
            0,
            NULL);

if (hFileHandle == INVALID_HANDLE_VALUE)
{
    Console.WriteLine("Cannot open driver handle");
} 
else
{
    //DeviceIOControl query
}

The CreateFile() function opens a handle to the device. In this case, the device is a wireless network adapter. The first argument accepts the device name in the format “\\\\.\\{A5128180-8811-451C-BBBD-2BE2F69F65C9}”. “{A5128180-8811-451C-BBBD-2BE2F69F65C9}” specifies the GUID for the wireless card. I have hardcoded this card GUID for my wireless card. You can check the system Registry for the list of available cards in your machine. This is available under the following Registry key:

  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\Current Version\NetworkCards

This key lists down all the available network adapters in the system. The ‘ServiceName’ Registry sub-key specifies the GUID value for that card. Network adapters can be enumerated using IPHelper functions also. For more reference about enumerating network cards, please go through this MSDN link: http://msdn2.microsoft.com/en-us/library/aa365798(VS.85).aspx.

Next, we will see the DeviceIOControl() calling section.

C#
//calling DeviceIOControl
if (DeviceIoControl(hFileHandle, IOCTL_NDIS_QUERY, ptrInput, oidCodeLength, 
    ptrOutput, OutputBufferSize, out bytesReturned, 0))
{
      Console.WriteLine("DeviceIOControl success");
}

DeviceIOControl() accepts the following arguments:

  • Handle to the network adapter
  • IO control code; in our case, it’s IOCTL_NDIS_QUERY_GLOBAL_STATS
  • Pointer to an input buffer that contains 802.11 OID
  • Specifies the size of the input buffer used to query 802.11 OID
  • Pointer to the output buffer that receives the result
  • Specifies the output buffer size
  • Pointer to the buffer that contains the actual size of the result
  • Specifies ‘0’ for a synchronous query

I am not going to explain more about the GCHandle and Marshal classes as that is beyond the scope of this article.

If DeviceIOControl returns a non-zero value, it indicates that the query is success, and the result can be received in the output buffer.

C#
if (DeviceIoControl(hFileHandle, IOCTL_NDIS_QUERY, ptrInput, 
    oidCodeLength, ptrOutput, OutputBufferSize, out bytesReturned, 0))
{
    Console.WriteLine("DeviceIOControl success");

    //Marshing data back into .net data type
    Int32 rssi = (Int32)Marshal.PtrToStructure(ptrOutput, typeof(Int32));
                        
    //recived signal strength 
    Console.WriteLine("Received Signal Strength: {0}", rssi);

    if (ptrOutput != IntPtr.Zero)
    {
        Marshal.FreeHGlobal(ptrOutput);
        ptrOutput = IntPtr.Zero;
    }

    handle.Free();
}

Now, the result is available in the output buffer and we have to marshal that data and transfer it into a .NET data type.

C#
//Marshing data back into .net data type
Int32 rssi = (Int32)Marshal.PtrToStructure(ptrOutput, typeof(Int32));

Marshal.PtrToStructure() will do the marshaling of the unmanaged data to managed data, and the user can see the received signal strength value in the console window.

Conclusion

This article demonstrates how to query 802.11 OIDs using the DeviceIOControl() function from a C# application. As a sample, we have seen querying the signal strength of the currently connected wireless network. In my next article, I will show you how to access the same 802.11 OID using the Windows Management Instrumentation (WMI) mechanism.

References

  1. How to query miniport driver information (802.11 OIDs) using Windows Management Instrumentation (WMI) mechanism
  2. How to access wireless network parameters using native WiFi API

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)


Written By
Software Developer (Senior)
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionError 87 Pin
Member 92447721-Dec-19 20:08
Member 92447721-Dec-19 20:08 
QuestionHelp for Wifi API use Pin
Member 101945843-Aug-15 20:58
Member 101945843-Aug-15 20:58 
Questioncan we use C or Java to do the same? Pin
qtelSparrow29-Oct-11 6:40
qtelSparrow29-Oct-11 6:40 
QuestionHow to do this on Wince. there is no GUID on wince for wireless network adapter Pin
followthesun27-Oct-10 8:23
followthesun27-Oct-10 8:23 
GeneralCommunication between two WLAN devices Pin
varunatbenz14-Apr-10 18:52
varunatbenz14-Apr-10 18:52 
QuestionHow to get SSID and RSSI in Windows 7 Pin
ailhaddin1-Mar-10 17:53
ailhaddin1-Mar-10 17:53 
QuestionOID_802_11_RSSI value? Pin
Alon Ronen24-Dec-09 17:55
Alon Ronen24-Dec-09 17:55 
GeneralWindows Mobile for Smartphones Pin
VS newbie 26-Nov-09 6:16
VS newbie 26-Nov-09 6:16 
GeneralRuning on Windows 7 Pin
sharkius23-Nov-09 5:18
sharkius23-Nov-09 5:18 
GeneralRe: Runing on Windows 7 Pin
Keith Mann4-Jan-10 9:01
Keith Mann4-Jan-10 9:01 
Questiondriver handle open error Pin
AnnBran18-Nov-09 6:54
AnnBran18-Nov-09 6:54 
Hi,

I'm getting a driver handle open error on the CreateFile line.. I have changed the Driver ID to what matches with mine..

I ran it on 2 pcs, vista and xp, and same error..

Do I need to do a registry change or something to make this work?

Please help!

Anita
AnswerRe: driver handle open error Pin
Maju M23-Nov-09 17:23
Maju M23-Nov-09 17:23 
Questionhow to use the DeviceIOControl function from a C# application Pin
VS newbie 1-Nov-09 19:43
VS newbie 1-Nov-09 19:43 
AnswerRe: how to use the DeviceIOControl function from a C# application Pin
Maju M12-Nov-09 17:32
Maju M12-Nov-09 17:32 
GeneralRe: how to use the DeviceIOControl function from a C# application Pin
VS newbie 26-Nov-09 5:49
VS newbie 26-Nov-09 5:49 
Questiontest wireless network card? Pin
elvis_pan12-Jul-09 21:23
elvis_pan12-Jul-09 21:23 
AnswerRe: test wireless network card? Pin
Maju M14-Jul-09 16:51
Maju M14-Jul-09 16:51 
Generalexcellent article!!! Pin
valenci9-Jul-09 1:34
valenci9-Jul-09 1:34 
QuestionHow to get the wireless device info. Pin
meramkumar8-Jun-09 0:33
meramkumar8-Jun-09 0:33 
Questionit's only show the associated ssid rssi? Pin
liaommx15-Apr-09 19:55
liaommx15-Apr-09 19:55 
AnswerRe: it's only show the associated ssid rssi? Pin
Maju M19-Apr-09 19:32
Maju M19-Apr-09 19:32 
GeneralRe: it's only show the associated ssid rssi? Pin
liaommx21-Apr-09 18:18
liaommx21-Apr-09 18:18 
GeneralRe: it's only show the associated ssid rssi? Pin
Maju M23-Apr-09 16:17
Maju M23-Apr-09 16:17 
QuestionUsing on Linux Pin
yasserbn31-Dec-08 11:21
yasserbn31-Dec-08 11:21 
AnswerRe: Using on Linux Pin
yasserbn3-Jan-09 16:18
yasserbn3-Jan-09 16:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.