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

By , 10 Apr 2009
 

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)

About the Author

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

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questioncan we use C or Java to do the same?memberqtelSparrow29 Oct '11 - 6:40 
I need to write a program that would be able to access wifi adapter properties. Do you know what would be the best way to do it using c or Java or maybe you know some websites that i can check? if you know how to do it for Linux it would be perfect but windows will do as well. thank you
QuestionHow to do this on Wince. there is no GUID on wince for wireless network adaptermemberfollowthesun27 Oct '10 - 8:23 
Hi, How to do this on Wince and there is no GUID on wince for wireless network adapter. I tried put in UIO1: and NDSO: and all I can get is Adapter name. I really want to get the signal strength of the Wince wireless network. Thanks
GeneralCommunication between two WLAN devicesmembervarunatbenz14 Apr '10 - 18:52 
hi all,   First i would like to thank Maju.M for his valuable post on WLAN 802.11OID.   i have one requirement in which i have to establish communication between   two WLAN systems can any one of you please answer my questions given below?   and i am using...
QuestionHow to get SSID and RSSI in Windows 7memberailhaddin1 Mar '10 - 17:53 
Hi,   I am very new to Win7 and Wifi programming. Please advice me in how to get ssid/rssi using C#.   Actually, I tried the sample code but still no luck. I'm using Visual Studio 2010 and Windows 7 for my development eviroment.   FYI, I have used:   1)...
QuestionOID_802_11_RSSI value?memberAlon Ronen24 Dec '09 - 17:55 
Hi,   I'm trying to replicate your work to start the Bluetooth service in a WinCE device. I'm missing the value of OID_802_11_RSSI... what is it and if you know, what should I use for the Bluetooth?   (In the CreateFile I'm using "BTD0:")   Thanks,   Alon   Alon
GeneralWindows Mobile for SmartphonesmemberVS newbie26 Nov '09 - 6:16 
Can you use GetWifiReading method in the WindowsCEWifiReader class to get a list of network adapters and also RSSI reading?   I would like to get the RSSI reading just like using DeviceIOControl() function but using a smartphone.   Thanks!
GeneralRuning on Windows 7membersharkius23 Nov '09 - 5:18 
Has anyone gotten this working on Windows 7 (or Vista, should be close enough)? DeviceIOControl returns a invalid parameter error, but doesn't doesn't specify what parameter is invalid.
GeneralRe: Runing on Windows 7memberKeith Mann4 Jan '10 - 9:01 
I'm pretty sure that the invalid parameter is OID_802_11_RSSI. I've tried using OIDs for other stuff instead, like the MAC address and the media connect status, and they've both worked (this is using Windows 7, 64-bit).   So, for example, here's the relevant bit of Maju's code:  ...
Questiondriver handle open errormemberAnnBran18 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!...
AnswerRe: driver handle open errormemberMaju. M23 Nov '09 - 17:23 
You don't need to change anything with registry. Just identify the correct service name for your wireless card from registry and specify it in 'printSignalStrength' function. This opens a handle to that device and queries signal strength.   You can also add Marshal.GetLastWin32Error()...
Questionhow to use the DeviceIOControl function from a C# applicationmemberVS newbie1 Nov '09 - 19:43 
I'm a newbie in C# I would appreciate any help on how to use DeviceIOControl funtion in querying for the signal strength of a wireless network using Visual Studio 2008 Prof edition. I'm interested in querying using C# in VS 2008 prof edition   Thanks!
AnswerRe: how to use the DeviceIOControl function from a C# applicationmemberMaju. M12 Nov '09 - 17:32 
check the attached sample application.
GeneralRe: how to use the DeviceIOControl function from a C# applicationmemberVS newbie26 Nov '09 - 5:49 
Thank you...managed to get it to work...great article.
Questiontest wireless network card?memberelvis_pan12 Jul '09 - 21:23 
hi, My network card is not a wireless, and i use the code,the "DeviceIoControl" return "false". and GetLastError() return "0".   so i think wether it could be used to test the network card is working in wirless status? my thought is right?hoping for reply.   Thanks
AnswerRe: test wireless network card?memberMaju. M14 Jul '09 - 16:51 
No.   Check OID_GEN_PHYSICAL_MEDIUM and determine the type.   http://msdn.microsoft.com/en-us/library/bb648526.aspx[^]
Generalexcellent article!!!membervalenci9 Jul '09 - 1:34 
Thanks for this excellent info. I think it would be nice if you could first use a more generic (common) OID which is not wireless specific (like links peed or state) and then go specific. This way this example could fit a broader audience and work for other NICs in case the wrong GUID was...
QuestionHow to get the wireless device info.membermeramkumar8 Jun '09 - 0:33 
Hi Maju,   How to get the wireless device which is connected to the machine and how can i disable it. i have confusion weather each type of Wireless device will have sperate deivice info if yes how can i find it and disable the device power using C#.   kindly help me asap.
Questionit's only show the associated ssid rssi?memberliaommx15 Apr '09 - 19:55 
i don't have idea about querying the exist ssid's signal strength(RSSI) i want to get every ssid signal strength. i try some method, like query wmi and OIDs, i could only get the rssi about associating ssid.   but from WMI, i could query the SSID, if i want to get every SSIDs RSSI,...
AnswerRe: it's only show the associated ssid rssi?memberMaju. M19 Apr '09 - 19:32 
This program queries RSSI value of active connection. You can query RSSI values of all networks using OID_802_11_BSSID_LIST oid.   Similarly WMI also provides classes which returns all wireless networks with MSNdis_80211_BSSIList. Since WMI is buggy,i don't recommend it.
GeneralRe: it's only show the associated ssid rssi?memberliaommx21 Apr '09 - 18:18 
i could query the value at OIDscope program. but i don't know how to program it in c#.   this is the OIDscope tool screenshot http://img16.imageshack.us/my.php?image=43600890.png   how could i display the value at OID_802_11_BSSID_LIST in c# ?   my coding stopped for...
GeneralRe: it's only show the associated ssid rssi?memberMaju. M23 Apr '09 - 16:17 
You have to use platform invoke mechanism and query the above OID.
QuestionUsing on Linuxmemberyasserbn31 Dec '08 - 11:21 
Can DeviceIOControl() function be used in Linux?
AnswerRe: Using on Linuxmemberyasserbn3 Jan '09 - 16:18 
No, It can not be used
GeneralDeviceIoControl returns false :((memberserkan19777 Aug '08 - 19:51 
I really like your article thanks alot.   I did and replace my guid as you said. but "DeviceIoControl" function returns false and I got "DeviceIoControl Failed" message. What could be the reason for it??   Thanks,
GeneralRe: DeviceIoControl returns false :((memberMaju. M19 Aug '08 - 16:41 
I can't say the exact reason without checking your laptop. You can verify the following things:   (1) Go to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\Current Version\NetworkCards windows registry and check GUIDs of wireless network cards. You should check the description of each...

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

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