Click here to Skip to main content
Click here to Skip to main content

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

, 10 Apr 2009 CDDL
Rate this:
Please Sign up or sign in to vote.
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.

/// <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.

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.

//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.

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.

//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)

Share

About the Author

Maju. M
Software Developer (Senior)
India India
No Biography provided

Comments and Discussions

 
Questioncan we use C or Java to do the same? PinmemberqtelSparrow29-Oct-11 6:40 
QuestionHow to do this on Wince. there is no GUID on wince for wireless network adapter Pinmemberfollowthesun27-Oct-10 8:23 
GeneralCommunication between two WLAN devices Pinmembervarunatbenz14-Apr-10 18:52 
QuestionHow to get SSID and RSSI in Windows 7 Pinmemberailhaddin1-Mar-10 17:53 
QuestionOID_802_11_RSSI value? PinmemberAlon Ronen24-Dec-09 17:55 
GeneralWindows Mobile for Smartphones PinmemberVS newbie26-Nov-09 6:16 
GeneralRuning on Windows 7 Pinmembersharkius23-Nov-09 5:18 
GeneralRe: Runing on Windows 7 PinmemberKeith Mann4-Jan-10 9:01 
Questiondriver handle open error PinmemberAnnBran18-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 PinmemberMaju. M23-Nov-09 17:23 
Questionhow to use the DeviceIOControl function from a C# application PinmemberVS newbie1-Nov-09 19:43 
AnswerRe: how to use the DeviceIOControl function from a C# application PinmemberMaju. M12-Nov-09 17:32 
GeneralRe: how to use the DeviceIOControl function from a C# application PinmemberVS newbie26-Nov-09 5:49 
Questiontest wireless network card? Pinmemberelvis_pan12-Jul-09 21:23 
AnswerRe: test wireless network card? PinmemberMaju. M14-Jul-09 16:51 
Generalexcellent article!!! Pinmembervalenci9-Jul-09 1:34 
QuestionHow to get the wireless device info. Pinmembermeramkumar8-Jun-09 0:33 
Questionit's only show the associated ssid rssi? Pinmemberliaommx15-Apr-09 19:55 
AnswerRe: it's only show the associated ssid rssi? PinmemberMaju. M19-Apr-09 19:32 
GeneralRe: it's only show the associated ssid rssi? Pinmemberliaommx21-Apr-09 18:18 
GeneralRe: it's only show the associated ssid rssi? PinmemberMaju. M23-Apr-09 16:17 
QuestionUsing on Linux Pinmemberyasserbn31-Dec-08 11:21 
AnswerRe: Using on Linux Pinmemberyasserbn3-Jan-09 16:18 
Questionhow to use the SET operation(like IOCTL_NDISUIO_SET_OID_VALUE)? Pinmemberanders ling23-Jun-08 14:25 
AnswerRe: how to use the SET operation(like IOCTL_NDISUIO_SET_OID_VALUE)? PinmemberMaju. M23-Jun-08 18:34 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.141029.1 | Last Updated 10 Apr 2009
Article Copyright 2008 by Maju. M
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid