List available wireless networks (using WMI) - Help pls
Hi all,
I have written a simple prog (button, listbox), to list available wireless networks.
When you click scan it will show 1. the SSID and 2. signalstrength of discovered networks.
Problem 1: the characters of the SSID are unreadable (the raw SSID is a 32section array and characters are in ASCII, so each portion of the array must be chr'd). However this does not return the correct results.
Problem 2: signalstrength is not displayed properly. But that will be solved with correct SSID.
I have read somewhere that this is a bug in XP SP2. I have seen apps written in C# that perform this function properly, so I don't believe its a bug in XP SP2.
Any help would be greatly appreciated (attached is my prog).
Re: List available wireless networks (using WMI) - Help pls
i tested your code, the fault is not your code as one of my networks returned the ssid correctly, the other returned the name with garbage before and after
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
Re: List available wireless networks (using WMI) - Help pls
Hi Pete,
Thanks for the reply.
I noticed the same.
At first I thought it had something to do with the networks encryption. I thought that WEP networks showed up correct and WPA networks would show garbage because the SSID is encrypted too, but then it shows one network name correctly (eg a WEP one) and nn 15 minutes it might show another network name correctly (eg a WPA one).
My inclination is the way C# handles converting to char. I'm not sure though.
I've updated my app to show the same as before, but this time I include the rawssid (ascii).
Re: List available wireless networks (using WMI) - Help pls
same thing one ssid is correct, some other network come online, nothing to recognise that ssid at all
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
The data structures mentioned above are actually outdated ones, and WRAPI uses these. The
newer structures have _EX postfix appended to the names, as in
NDIS_802_11_BSSID_LIST_EX and NDIS_WLAN_BSSID_EX. The newer structures
have some minor changes and additions. However, these are significant because WRAPI
code uses array indexing to select the next AP, as can be seen in the following pseudo-code:
pBssid_List: type PNDIS_802_11_BSSID_LIST
buffer: type char[]
rssi: type long
have pBssid_List point to buffer
for(i=0; i<pBssid_List->NumberOfItems; i++)
rssi for AP index 'i' is (pBssid_List->Bssid[i]).Rssi
Listing X.
One might think that simply by changing PNDIS_802_11_BSSID_LIST to
PNDIS_802_11_BSSID_LIST_EX, WRAPI would be fixed. However, this approach won’t
work, because NDIS_WLAN_BSSID_EX contains following two new fields:
ULONG IELength;
UCHAR IEs[1];
The size of IEs is not 1, but depends on IELength, which can vary, so accessing the next AP
using array indexing won't work. The solution is to use the length attribute of
NDIS_WLAN_BSSID_EX to determine the starting address of the next AP data
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
Mars base one Username: Jim Davis Password: yCrm33
Posts
1,284
Re: List available wireless networks (using WMI) - Help pls
Here, im using an Atheros MiniPCI Card attached to a MiniPCI-PCI adaptor. I also got a DLINK DWL520 card, so i can do some tests for you.
Here is the Atheros gives. (Something terribly wrong)
As long as this atheros card cant give the proper values, i dont wanna play to assemble my pc to replace to the dlink But im happy to helping you testing your app!
Oh, also my Atheros card (just like my dlink) uses its OWN APP, not window's internal AP proggie for connecting to aps.
Mars base one Username: Jim Davis Password: yCrm33
Posts
1,284
Re: List available wireless networks (using WMI) - Help pls
I've just found, that the first entry is seems to be correct. But the second and those come after, will be shifted by 3 (or more) bytes, that is the reason it drops bad results.
Mars base one Username: Jim Davis Password: yCrm33
Posts
1,284
Re: List available wireless networks (using WMI) - Help pls
OK, here is an alternate way to get the same results.
Code:
strServer = "."
Set objWMI = GetObject("winmgmts://" & strServer & "/root\WMI")
Set objInstances = objWMI.InstancesOf("MSNdis_80211_BSSIList", 48)
For Each objInstance In objInstances
Debug.Print objInstance.getObjectText_
Next
The results are the same, i found that this is a common bug, that not solved in Vista either!
Re: List available wireless networks (using WMI) - Help pls
i downloaded wmi tools from microsoft
it just don't work
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
Re: List available wireless networks (using WMI) - Help pls
Interesting....
Thanks for all the tips. I am going to work on this and post my results.
I've been thinking about this now, and if the AP ssid is in an array, and there is byte shifting and as Petes above post regarding WRAPI, then by getting the SSID length, then it should return the correct results.
This somehow makes me think that my ap is overlapping SSID's.
This is extremely wierd for me (btw, I am also using an Atheros card).
Re: List available wireless networks (using WMI) - Help pls
the information say that the value returned can now be of variable length, so it would be quite hard to figure how to make a structure that can accomodate, unknown data lengths
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
Re: List available wireless networks (using WMI) - Help pls
As per 5th post (Petes).
I've done further research and DAMN, SSID in the new structs IS variable length.... now what
From the net somewhere (this relates to XP SP2 and up)
"This is because there are two structures for SSID name:
the old one (NDIS_WLAN_BSSID) has fixed size, it
is what WMI uses on WinXP.
The new struct, NDIS_WLAN_BSSID_EX, has variable size
(so you can't simply make array of these) and it breaks
the older WMI classes.
All modern wi-fi drivers return only new structs"
Re: List available wireless networks (using WMI) - Help pls
only suggestion i have is to return one connection at a time (not that i know how to do that), as the first connection seems to display correctly
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
Mars base one Username: Jim Davis Password: yCrm33
Posts
1,284
Re: List available wireless networks (using WMI) - Help pls
Every (vary length) fields should have a length property, that describes the field length. A basic parser could be a working solution. But i just dont know how to get the whole results in a simple binary array.
Re: List available wireless networks (using WMI) - Help pls
Hi,
Well, after more research and finally realising that straight WMI calls aren't going to do the job, and the reason is the variable length SSID, plain WMI does not include an SSID_Length object, so I am now investigating working straight with NDIS or Native Wifi API.
I downloaded Ndis Tools from www.pcausa.com there is an app called OIDScope. From there I check the properties of my wireless card and then run an NDis Query on OID_802_11_BSSID_LIST and I get information on all the access points (the correct info), interesting is that its in Hex.
I have a program called "inSSIDer" installed on my PC (its like NetStumbler), only difference is its open source and I have the code. Its a VC# app. I don't know C# but from what I can decipher from the code, the app uses the (wlanapi.dll). So off to MSDN I go, print out the entire lot about Native Wifi API (works on XP SP2 with KB 918997 installed, works on XP SP3, and Vista).
So if I can get working on that it will solve all my problems, I'll be able to creative a cross platform app (XP, Vista) without using WMI for one and Native Wifi for the other.
Yet again, I'll report back.
Thanks for all the input so far, it really helps steering in the right direction.
BTW: I am posting all the work I have done so far on VB6 and wireless.
Re: List available wireless networks (using WMI) - Help pls
Hi,
I've been playing with the Wlan APIs. This was developed, and appears to work, under Vista and also appears to work on XP.
Code:
Option Explicit
Private Const DOT11_SSID_MAX_LENGTH As Long = 32
Private Const WLAN_MAX_PHY_TYPE_NUMBER As Long = 8
Private Type GUID
data1 As Long
data2 As Integer
data3 As Integer
data4(7) As Byte
End Type
Private Type WLAN_INTERFACE_INFO
ifGuid As GUID
InterfaceDescription(255) As Byte
IsState As Long
End Type
Private Type DOT11_SSID
uSSIDLength As Long
ucSSID(DOT11_SSID_MAX_LENGTH - 1) As Byte
End Type
Private Type WLAN_AVAILABLE_NETWORK
strProfileName(511) As Byte
dot11Ssid As DOT11_SSID
dot11BssType As Long
uNumberOfBssids As Long
bNetworkConnectable As Long
wlanNotConnectableReason As Long
uNumberOfPhyTypes As Long
dot11PhyTypes(WLAN_MAX_PHY_TYPE_NUMBER - 1) As Long
bMorePhyTypes As Long
wlanSignalQuality As Long
bSEcurityEnabled As Long
dot11DefaultAuthAlgorithm As Long
dot11DefaultCipherAlgorithm As Long
dwflags As Long
dwreserved As Long
End Type
Private Type WLAN_INTERFACE_INFO_LIST
dwNumberOfItems As Long
dwIndex As Long
InterfaceInfo As WLAN_INTERFACE_INFO
End Type
Private Type WLAN_AVAILABLE_NETWORK_LIST
dwNumberOfItems As Long
dwIndex As Long
Network As WLAN_AVAILABLE_NETWORK
End Type
Private Declare Function WlanOpenHandle Lib "wlanapi.dll" (ByVal dwClientVersion As Long, _
ByVal pdwReserved As Long, _
ByRef pdwNegotiaitedVersion As Long, _
ByRef phClientHandle As Long) As Long
Private Declare Function WlanEnumInterfaces Lib "wlanapi.dll" (ByVal hClientHandle As Long, _
ByVal pReserved As Long, _
ppInterfaceList As Long) As Long
Private Declare Function WlanGetAvailableNetworkList Lib "wlanapi.dll" (ByVal hClientHandle As Long, _
pInterfaceGuid As GUID, _
ByVal dwflags As Long, _
ByVal pReserved As Long, _
ppAvailableNetworkList As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, _
Source As Any, _
ByVal Length As Long)
Private Declare Sub WlanFreeMemory Lib "wlanapi.dll" (ByVal pMemory As Long)
Private Sub Command1_Click()
Dim lngReturn As Long
Dim lngHandle As Long
Dim lngVersion As Long
Dim lngList As Long
Dim lngAvailable As Long
Dim lngStart As Long
Dim intCount As Integer
Dim intI As Integer
Dim strSSID As String
Dim strProfile As String
Dim udtList As WLAN_INTERFACE_INFO_LIST
Dim udtInfo As WLAN_INTERFACE_INFO
Dim udtAvailableList As WLAN_AVAILABLE_NETWORK_LIST
Dim udtNetwork As WLAN_AVAILABLE_NETWORK
'
' Get a Handle
'
lngReturn = WlanOpenHandle(2&, 0&, lngVersion, lngHandle)
If lngReturn = 0 Then
'
' Enumerate the Interfaces
' (Note: this code only looks at the first interface)
'
lngReturn = WlanEnumInterfaces(ByVal lngHandle, 0&, lngList)
CopyMemory udtList, ByVal lngList, Len(udtList)
'
' Get the list of available Networks
'
lngReturn = WlanGetAvailableNetworkList(lngHandle, udtList.InterfaceInfo.ifGuid, 2&, 0&, lngAvailable)
CopyMemory udtAvailableList, ByVal lngAvailable, LenB(udtAvailableList)
intCount = 0
lngStart = lngAvailable + 8
Do
'
' Populate the Available network structure
'
CopyMemory udtNetwork, ByVal lngStart, Len(udtNetwork)
'
' Display the Data for this Network
'
strProfile = ByteToString(udtNetwork.strProfileName)
strProfile = Left$(strProfile, InStr(strProfile, Chr(0)) - 1)
strSSID = ByteToString(udtNetwork.dot11Ssid.ucSSID, udtNetwork.dot11Ssid.uSSIDLength, False)
strSSID = Left(strSSID, InStr(strSSID, Chr(0)) - 1)
Debug.Print "Profile "; strProfile, "SSID "; strSSID, "Signal "; udtNetwork.wlanSignalQuality; " Connected "; udtNetwork.dwflags
Debug.Print "BSS Type "; udtNetwork.dot11BssType
Debug.Print "Number of BSSids "; udtNetwork.uNumberOfBssids
Debug.Print "Network Connectable "; udtNetwork.bNetworkConnectable
Debug.Print "Not Connectable Reason "; udtNetwork.wlanNotConnectableReason
Debug.Print "Number of PHY Types "; udtNetwork.uNumberOfPhyTypes
Debug.Print "PHY Types "
For intI = 0 To UBound(udtNetwork.dot11PhyTypes)
Debug.Print udtNetwork.dot11PhyTypes(intI); " ";
Next intI
Debug.Print
Debug.Print "More PHY Types "; udtNetwork.bMorePhyTypes
Debug.Print "Signal Quality "; udtNetwork.wlanSignalQuality
Debug.Print "Security Enabled "; udtNetwork.bSEcurityEnabled
Debug.Print "Default Auth Algorithm "; udtNetwork.dot11DefaultAuthAlgorithm
Debug.Print "Default Cypher Algorithm "; udtNetwork.dot11DefaultCipherAlgorithm
Debug.Print "Connected "; udtNetwork.dwflags
intCount = intCount + 1
lngStart = lngStart + Len(udtNetwork)
'
' Process all available networks
'
Loop Until intCount = udtAvailableList.dwNumberOfItems
WlanFreeMemory lngAvailable
WlanFreeMemory lngList
End If
End Sub
Private Function ByteToString(bytArray() As Byte, Optional lngLen As Long = 0, Optional boConvert As Boolean = True) As String
Dim strTemp As String
Dim intI As Integer
Dim intEnd As Integer
If lngLen = 0 Then
intEnd = UBound(bytArray)
Else
intEnd = lngLen
End If
For intI = 0 To intEnd
strTemp = strTemp & Chr(bytArray(intI))
Next intI
If boConvert = True Then strTemp = StrConv(strTemp, vbFromUnicode)
ByteToString = strTemp
End Function
EDIT: Removed the ReDim byt() statement - it was there for debugging purposes only, I'd removed all other references but forgot that one !
Re: List available wireless networks (using WMI) - Help pls
maybe needs sp3 to work in XP
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
Re: List available wireless networks (using WMI) - Help pls
My intention is, when I get some time, to use the WlanScan API and the Callback before looking at the available networks.
The reason I started playing was because I couldn't find the WMI Class you were using, in my Vista machine. I suspect it's buried within a different namespace under Vista. Anyway, like you I turned to the MSDN site and found the Wlan APIs.......
Re: List available wireless networks (using WMI) - Help pls
Quote"Hi,
I've been playing with the Wlan APIs. This was developed, and appears to work, under Vista and also appears to work on XP.
Code:
Code:
Option Explicit
Private Const DOT11_SSID_MAX_LENGTH As Long = 32
Private Const WLAN_MAX_PHY_TYPE_NUMBER As Long = 8
Private Type GUID
data1 As Long
data2 As Integer
data3 As Integer
data4(7) As Byte
End Type
Private Type WLAN_INTERFACE_INFO
ifGuid As GUID
InterfaceDescription(255) As Byte
IsState As Long
End Type
Private Type DOT11_SSID
uSSIDLength As Long
ucSSID(DOT11_SSID_MAX_LENGTH - 1) As Byte
End Type
Private Type WLAN_AVAILABLE_NETWORK
strProfileName(511) As Byte
dot11Ssid As DOT11_SSID
dot11BssType As Long
uNumberOfBssids As Long
bNetworkConnectable As Long
wlanNotConnectableReason As Long
uNumberOfPhyTypes As Long
dot11PhyTypes(WLAN_MAX_PHY_TYPE_NUMBER - 1) As Long
bMorePhyTypes As Long
wlanSignalQuality As Long
bSEcurityEnabled As Long
dot11DefaultAuthAlgorithm As Long
dot11DefaultCipherAlgorithm As Long
dwflags As Long
dwreserved As Long
End Type
Private Type WLAN_INTERFACE_INFO_LIST
dwNumberOfItems As Long
dwIndex As Long
InterfaceInfo As WLAN_INTERFACE_INFO
End Type
Private Type WLAN_AVAILABLE_NETWORK_LIST
dwNumberOfItems As Long
dwIndex As Long
Network As WLAN_AVAILABLE_NETWORK
End Type
Private Declare Function WlanOpenHandle Lib "wlanapi.dll" (ByVal dwClientVersion As Long, _
ByVal pdwReserved As Long, _
ByRef pdwNegotiaitedVersion As Long, _
ByRef phClientHandle As Long) As Long
Private Declare Function WlanEnumInterfaces Lib "wlanapi.dll" (ByVal hClientHandle As Long, _
ByVal pReserved As Long, _
ppInterfaceList As Long) As Long
Private Declare Function WlanGetAvailableNetworkList Lib "wlanapi.dll" (ByVal hClientHandle As Long, _
pInterfaceGuid As GUID, _
ByVal dwflags As Long, _
ByVal pReserved As Long, _
ppAvailableNetworkList As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, _
Source As Any, _
ByVal Length As Long)
Private Declare Sub WlanFreeMemory Lib "wlanapi.dll" (ByVal pMemory As Long)
Private Sub Command1_Click()
Dim lngReturn As Long
Dim lngHandle As Long
Dim lngVersion As Long
Dim lngList As Long
Dim lngAvailable As Long
Dim lngStart As Long
Dim intCount As Integer
Dim intI As Integer
Dim strSSID As String
Dim strProfile As String
Dim udtList As WLAN_INTERFACE_INFO_LIST
Dim udtInfo As WLAN_INTERFACE_INFO
Dim udtAvailableList As WLAN_AVAILABLE_NETWORK_LIST
Dim udtNetwork As WLAN_AVAILABLE_NETWORK
'
' Get a Handle
'
lngReturn = WlanOpenHandle(2&, 0&, lngVersion, lngHandle)
If lngReturn = 0 Then
'
' Enumerate the Interfaces
' (Note: this code only looks at the first interface)
'
lngReturn = WlanEnumInterfaces(ByVal lngHandle, 0&, lngList)
CopyMemory udtList, ByVal lngList, Len(udtList)
'
' Get the list of available Networks
'
lngReturn = WlanGetAvailableNetworkList(lngHandle, udtList.InterfaceInfo.ifGuid, 2&, 0&, lngAvailable)
CopyMemory udtAvailableList, ByVal lngAvailable, LenB(udtAvailableList)
intCount = 0
lngStart = lngAvailable + 8
Do
'
' Populate the Available network structure
'
CopyMemory udtNetwork, ByVal lngStart, Len(udtNetwork)
'
' Display the Data for this Network
'
strProfile = ByteToString(udtNetwork.strProfileName)
strProfile = Left$(strProfile, InStr(strProfile, Chr(0)) - 1)
strSSID = ByteToString(udtNetwork.dot11Ssid.ucSSID, udtNetwork.dot11Ssid.uSSIDLength, False)
strSSID = Left(strSSID, InStr(strSSID, Chr(0)) - 1)
Debug.Print "Profile "; strProfile, "SSID "; strSSID, "Signal "; udtNetwork.wlanSignalQuality; " Connected "; udtNetwork.dwflags
Debug.Print "BSS Type "; udtNetwork.dot11BssType
Debug.Print "Number of BSSids "; udtNetwork.uNumberOfBssids
Debug.Print "Network Connectable "; udtNetwork.bNetworkConnectable
Debug.Print "Not Connectable Reason "; udtNetwork.wlanNotConnectableReason
Debug.Print "Number of PHY Types "; udtNetwork.uNumberOfPhyTypes
Debug.Print "PHY Types "
For intI = 0 To UBound(udtNetwork.dot11PhyTypes)
Debug.Print udtNetwork.dot11PhyTypes(intI); " ";
Next intI
Debug.Print
Debug.Print "More PHY Types "; udtNetwork.bMorePhyTypes
Debug.Print "Signal Quality "; udtNetwork.wlanSignalQuality
Debug.Print "Security Enabled "; udtNetwork.bSEcurityEnabled
Debug.Print "Default Auth Algorithm "; udtNetwork.dot11DefaultAuthAlgorithm
Debug.Print "Default Cypher Algorithm "; udtNetwork.dot11DefaultCipherAlgorithm
Debug.Print "Connected "; udtNetwork.dwflags
intCount = intCount + 1
lngStart = lngStart + Len(udtNetwork)
'
' Process all available networks
'
Loop Until intCount = udtAvailableList.dwNumberOfItems
WlanFreeMemory lngAvailable
WlanFreeMemory lngList
End If
End Sub
Private Function ByteToString(bytArray() As Byte, Optional lngLen As Long = 0, Optional boConvert As Boolean = True) As String
Dim strTemp As String
Dim intI As Integer
Dim intEnd As Integer
If lngLen = 0 Then
intEnd = UBound(bytArray)
Else
intEnd = lngLen
End If
For intI = 0 To intEnd
strTemp = strTemp & Chr(bytArray(intI))
Next intI
If boConvert = True Then strTemp = StrConv(strTemp, vbFromUnicode)
ByteToString = strTemp
End Function
I am trying to make this work. I thought I would need to Reference the Wlanapi.dll but it won't let me. Is there something else I am missing?
Thanks
Last edited by si_the_geek; Apr 19th, 2009 at 10:29 AM.
Reason: added Code tags