Jump to content

DLL calls


Recommended Posts

Thanks for that reponse but it's my first time using DLL. Never used them before.

I understand the 1st link but not the second and the 3rd one. They are structures. How do i get their returns?

DllStructCreate? If yes would it be like that? Never used it before and i have 0 knowledge of dlls.

As i understood from a bit search on help files

$var = "wchar WLAN_INTERFACE_INFO_LIST;dword dwNumberOfItems;dword dwIndex;"
DllStructCreate($var)

Here is an example of how to get InterfaceGUID (binary & string format):

$tInterfaceList = DllStructCreate("ptr InterfaceList")

$hDll = DllOpen("wlanapi.dll")
$aHandle = DllCall($hDll, "dword", "WlanOpenHandle", "dword", 2, "ptr", 0, "dword*", 0, "handle*", 0)
DllCall($hDll, "dword", "WlanEnumInterfaces", "handle", $aHandle[4], "ptr", 0, "ptr", DllStructGetPtr($tInterfaceList))
$bGUID = DllStructGetData(DllStructCreate("byte GUID[16]",DllStructGetData($tInterfaceList,"InterfaceList")+8),"GUID")
DllCall($hDll, "dword", "WlanCloseHandle", "handle", $aHandle[4], "ptr", 0)
DllClose($hDll)

MsgBox(0,"GUID","Binary format: " & $bGUID & @CRLF & "String format: " & GUID_String($bGUID))

Func GUID_String($bGUID)
    Local $First, $Second, $Third, $Fourth
    For $Index = 1 To 4
        $First = StringTrimLeft(BinaryMid($bGUID,$Index,1),2) & $First
    Next
    For $Index = 5 To 6
        $Second = StringTrimLeft(BinaryMid($bGUID,$Index,1),2) & $Second
    Next
    For $Index = 7 To 8
        $Third = StringTrimLeft(BinaryMid($bGUID,$Index,1),2) & $Third
    Next
    For $Index = 9 To 16
        $Fourth = StringTrimLeft(BinaryMid($bGUID,$Index,1),2) & $Fourth
    Next
    Return "{" & $First & "-" & $Second & "-" & $Third & "-" & $Fourth & "}"
EndFunc

When the words fail... music speaks.

Link to comment
Share on other sites

Well done Andreik!

I hope this clarifys things a bit. Ilendros, If you can follow this code WlanGetAvailableNetworkList should be a doddle.

Cheers,

Matt

local $hDLL = DllOpen("wlanapi.dll"), $aResult, $hClientHandle, $pInterfaceList, _
$tInterfaceList, $iInterfaceCount, $tInterface, $pInterface, $tGUID, $pGUID

$aResult = DllCall($hDLL, "dword", "WlanOpenHandle", "dword", 2, "ptr", 0, "dword*", 0, "hwnd*", 0)
If @error Or $aResult[0] Then
ConsoleWrite("WlanOpenHandle Failed" & @CRLF)
Exit
EndIf

$hClientHandle = $aResult[4]

$aResult = DllCall($hDLL, "dword", "WlanEnumInterfaces", "hwnd", $hClientHandle, "ptr", 0, "ptr*", 0)
If @error Or $aResult[0] Then
ConsoleWrite("WlanEnumInterfaces Failed" & @CRLF)
Exit
EndIf

$pInterfaceList = $aResult[3] ;pointer to WLAN_INTERFACE_INFO_LIST. This is where the struct is in memory.

;The WLAN_INTERFACE_INFO_LIST structure contains two dwords followed by an array of WLAN_INTERFACE_INFO structures.
;~ DWORD dwNumberOfItems;
;~ DWORD dwIndex;
;~ WLAN_INTERFACE_INFO InterfaceInfo[];

;The first dword defines how many interfaces are in the list - this is all we are interested in for the minute.
$tInterfaceList = DllStructCreate("dword", $pInterfaceList)
$iInterfaceCount = DllStructGetData($tInterfaceList, 1)
If Not $iInterfaceCount Then
ConsoleWrite("no interfaces were found" & @CRLF)
Exit
EndIf
Local $abGUIDs[$iInterfaceCount]

;The next thing we need to do is find out more about a WLAN_INTERFACE_INFO structure.
;~ GUID InterfaceGuid;
;~ WCHAR strInterfaceDescription[256];
;~ WLAN_INTERFACE_STATE isState;
;we know what a WCHAR is, but what about GUID and WLAN_INTERFACE_STATE types?.

;from MSDN we can see the GUID data type is actually a structure in itself.
;~ DWORD Data1;
;~ WORD Data2;
;~ WORD Data3;
;~ BYTE Data4[8];
;We dont really care what each element contains - however we do need the size of a GUID struct. 4 + 2 + 2 + (8 x 1) = 16 bytes

;WLAN_INTERFACE_STATE is an enumeration. In other words it is just an integer.

;So now we know a WLAN_INTERFACE_INFO struct is 532 bytes in size. 16 + (256 * 2) + 4.
;This means we can pinpoint the location of every WLAN_INTERFACE_INFO struct in WLAN_INTERFACE_INFO_LIST
;the first will be offset 8 bytes to $pInterfaceList (dwNumberOfItems + dwIndex)
;the second (if there is one) will be offset 540 bytes to $pInterfaceList (dwNumberOfItems + dwIndex + WLAN_INTERFACE_INFO) and so on.

For $i = 0 To $iInterfaceCount - 1
$pInterface = Ptr(Number($pInterfaceList) + ($i * 532 + 8)) ;Find pointer to WLAN_INTERFACE_INFO struct.
$tInterface = DllStructCreate("byte GUID[16]; wchar descr[256]; int State", $pInterface)
$abGUIDs[$i] = DllStructGetData($tInterface, "GUID")
ConsoleWrite("Found: " & DllStructGetData($tInterface, "descr") & @CRLF)
Next

;We dont need the WLAN_INTERFACE_INFO_LIST struct anymore. we should free the memory that our program has gobbled up.
DllCall($hDLL, "dword", "WlanFreeMemory", "ptr", $pInterfaceList)

;So now we have an array of all the GUIDs the WlanEnumInterfaces has found.
;We need to choose the interface we want to work with and throw it back into memory (because other funtions need a pointer to a GUID - not a GUID).
;I will choose the first interface.
$tGUID = DllStructCreate("byte[16]")
DllStructSetData($tGUID, 1, $abGUIDs[0])
$pGUID = DllStructGetPtr($tGUID) ;We now have our GUID pointer!

;Finish things off properly.
DllCall($hDLL, "dword", "WlanCloseHandle", "ptr", $hClientHandle, "ptr", 0); second param is reserved
DllClose($hDLL)
Edited by MattyD
Link to comment
Share on other sites

  • 2 weeks later...

Lets put this one to bed shall we.

Global $hDLL = DllOpen("wlanapi.dll"), $tGUID = DllStructCreate("byte[16]")
Local $hClientHandle, $abGUIDs, $pGUID, $avNetworks

$hClientHandle = _GetClientHandle()
$abGUIDs = _GetInterfaces($hClientHandle)
$pGUID = _SelectInterface($abGUIDs[0])
$avNetworks = _GetNetworkList($hClientHandle, $pGUID, 0)
_End()

Func _GetClientHandle()
    Local $aResult = DllCall($hDLL, "dword", "WlanOpenHandle", "dword", 2, "ptr", 0, "dword*", 0, "hwnd*", 0)
    If @error Or $aResult[0] Then
        ConsoleWrite("WlanOpenHandle Failed" & @CRLF)
        Exit
    EndIf

    Return $aResult[4]
EndFunc

Func _GetInterfaces($hClientHandle)
    Local $aResult, $pInterfaceList, $tInterfaceList, $iInterfaceCount, $pInterface, $tInterface
    
    ;Find pointer to interface List
    $aResult = DllCall($hDLL, "dword", "WlanEnumInterfaces", "hwnd", $hClientHandle, "ptr", 0, "ptr*", 0)
    If @error Or $aResult[0] Then
        ConsoleWrite("WlanEnumInterfaces Failed" & @CRLF)
        Exit
    EndIf

    $pInterfaceList = $aResult[3]
    
    ;Find number of items in the list
    $tInterfaceList = DllStructCreate("dword", $pInterfaceList)
    $iInterfaceCount = DllStructGetData($tInterfaceList, 1)

    If Not $iInterfaceCount Then
        ConsoleWrite("no interfaces were found" & @CRLF)
        Exit
    EndIf
    
    ;Calculate the size of an item in the list (532 bytes)
    
    ;create an array to store data
    Local $abGUIDs[$iInterfaceCount]

    
    For $i = 0 To $iInterfaceCount - 1
        $pInterface = Ptr(Number($pInterfaceList) + ($i * 532 + 8)) ;calculate the pointer to each item using infromation we found out earlier
        $tInterface = DllStructCreate("byte GUID[16]; wchar descr[256]; int State", $pInterface) ;define how memory should be broken up at these pointers
        $abGUIDs[$i] = DllStructGetData($tInterface, "GUID") ;extract relevent data from every item in the list
        ConsoleWrite("Found Interface: " & DllStructGetData($tInterface, "descr") & @CRLF)
    Next

    DllCall($hDLL, "dword", "WlanFreeMemory", "ptr", $pInterfaceList) ;free memory

    Return $abGUIDs
EndFunc

Func _SelectInterface($bGUID)
    DllStructSetData($tGUID, 1, $bGUID)
    Return DllStructGetPtr($tGUID)
EndFunc

Func _GetNetworkList($hClientHandle, $pGUID, $iFlags)
    Local $aResult, $pNetworkList, $tNetworkList, $iNetworkCount, $pNetworkItem, $tNetworkItem
    
    ;~     DWORD WINAPI WlanGetAvailableNetworkList(
    ;~   _In_       HANDLE hClientHandle,
    ;~   _In_       const GUID *pInterfaceGuid,
    ;~   _In_       DWORD dwFlags,
    ;~   _Reserved_  PVOID pReserved,
    ;~   _Out_     PWLAN_AVAILABLE_NETWORK_LIST *ppAvailableNetworkList
    ;~ );
    
    ;Find a pointer to the list...
    $aResult = DllCall($hDLL, "dword", "WlanGetAvailableNetworkList", "hwnd", $hClientHandle, "ptr", $pGUID, "int", $iFlags, "ptr", 0, "ptr*", 0)
    If @error Or $aResult[0] Then
        ConsoleWrite("WlanGetAvailableNetworkList Failed" & @CRLF)
        Exit
    EndIf

    $pNetworkList = $aResult[5]

    ;~     typedef struct _WLAN_AVAILABLE_NETWORK_LIST {
    ;~       DWORD                dwNumberOfItems;
    ;~       DWORD                dwIndex;
    ;~       WLAN_AVAILABLE_NETWORK Network[1];
    ;~     } WLAN_AVAILABLE_NETWORK_LIST, *PWLAN_AVAILABLE_NETWORK_LIST;

    ;Find number of networks in the list...
    $tNetworkList = DllStructCreate("dword", $pNetworkList)
    $iNetworkCount = DllStructGetData($tNetworkList, 1)
    If Not $iNetworkCount Then
        ConsoleWrite("no networks were found" & @CRLF)
        Exit
    EndIf

    Local $avNetworks[$iNetworkCount][20] ;declare array to store information.

    ;Find the size of a WLAN_AVAILABLE_NETWORK structure...

    ;~     typedef struct _WLAN_AVAILABLE_NETWORK {
    ;~       WCHAR                strProfileName[256];
    ;~       DOT11_SSID          dot11Ssid;
    ;~       DOT11_BSS_TYPE      dot11BssType;
    ;~       ULONG                uNumberOfBssids;
    ;~       BOOL                  bNetworkConnectable;
    ;~       WLAN_REASON_CODE      wlanNotConnectableReason;
    ;~       ULONG                uNumberOfPhyTypes;
    ;~       DOT11_PHY_TYPE      dot11PhyTypes[WLAN_MAX_PHY_TYPE_NUMBER];
    ;~       BOOL                  bMorePhyTypes;
    ;~       WLAN_SIGNAL_QUALITY    wlanSignalQuality;
    ;~       BOOL                  bSecurityEnabled;
    ;~       DOT11_AUTH_ALGORITHM   dot11DefaultAuthAlgorithm;
    ;~       DOT11_CIPHER_ALGORITHM dot11DefaultCipherAlgorithm;
    ;~       DWORD                dwFlags;
    ;~       DWORD                dwReserved;
    ;~     } WLAN_AVAILABLE_NETWORK, *PWLAN_AVAILABLE_NETWORK;

    ;WCHAR[256]                                    2 * 256         = 512
    ;DOT11_SSID
    ;    ULONG + UCHAR[DOT11_SSID_MAX_LENGTH]    4 + (1 * 32)     = 36
    ;DOT11_BSS_TYPE                                4                = 4
    ;ULONG                                        4                = 4
    ;BOOL                                        4                = 4
    ;WLAN_REASON_CODE                            4                = 4
    ;ULONG                                        4                = 4
    ;DOT11_PHY_TYPE[WLAN_MAX_PHY_TYPE_NUMBER]    4 * 8            = 32
    ;BOOL                                        4                = 4
    ;WLAN_SIGNAL_QUALITY                        4                = 4
    ;BOOL                                        4                = 4
    ;DOT11_AUTH_ALGORITHM                        4                = 4
    ;DOT11_CIPHER_ALGORITHM                        4                = 4
    ;DWORD                                        4                = 4
    ;DWORD                                        4                = 4
    ;                                                             = 628 bytes total

    For $i = 0 To $iNetworkCount - 1 ;For each network found:
        ;Calculate pointer to WLAN_INTERFACE_INFO struct
        $pNetworkItem = Ptr(Number($pNetworkList) + ($i * 628 + 8))
        ;Tell AutoIt how to break memory up from that pointer
        $tNetworkItem = DllStructCreate("wchar ProfName[256]; dword SSIDLen; char SSID[32]; dword BSSType; dword NoBSSIDs; dword Connectable; dword RsnCode; dword NoPhyTypes; " & _
            "dword PhyTypes[8]; dword MorePhyTypes; dword Signal; dword SecEnabled; dword Auth; dword Ciph; dword Flags", $pNetworkItem)
        ;Extract relevant data
        $avNetworks[$i][0] = DllStructGetData($tNetworkItem, "ProfName")
        $avNetworks[$i][1] = DllStructGetData($tNetworkItem, "SSID")
        $avNetworks[$i][2] = DllStructGetData($tNetworkItem, "Signal")
        ;interpret data where needed
        If DllStructGetData($tNetworkItem, "SecEnabled") Then
            $avNetworks[$i][3] = "Secure"
        Else
            $avNetworks[$i][3] = "Not Secure"
        EndIf
        ;etc...

        ConsoleWrite("Found Network: " & $avNetworks[$i][1] & " [" & $avNetworks[$i][2] & "%]" & @CRLF)
    Next

    DllCall($hDLL, "dword", "WlanFreeMemory", "ptr", $pNetworkList) ;Free memory

    Return $avNetworks
EndFunc

Func _End()
    DllCall($hDLL, "dword", "WlanCloseHandle", "ptr", $hClientHandle, "ptr", 0)
    DllClose($hDLL)
EndFunc
Edited by MattyD
Link to comment
Share on other sites

  • 4 years later...
On ‎3‎-‎11‎-‎2012 at 1:24 AM, MattyD said:

Well done Andreik!

 

I hope this clarifys things a bit. Ilendros, If you can follow this code WlanGetAvailableNetworkList should be a doddle.

 

Cheers,

Matt

 

 

local $hDLL = DllOpen("wlanapi.dll"), $aResult, $hClientHandle, $pInterfaceList, _
$tInterfaceList, $iInterfaceCount, $tInterface, $pInterface, $tGUID, $pGUID

$aResult = DllCall($hDLL, "dword", "WlanOpenHandle", "dword", 2, "ptr", 0, "dword*", 0, "hwnd*", 0)
If @error Or $aResult[0] Then
ConsoleWrite("WlanOpenHandle Failed" & @CRLF)
Exit
EndIf

$hClientHandle = $aResult[4]

$aResult = DllCall($hDLL, "dword", "WlanEnumInterfaces", "hwnd", $hClientHandle, "ptr", 0, "ptr*", 0)
If @error Or $aResult[0] Then
ConsoleWrite("WlanEnumInterfaces Failed" & @CRLF)
Exit
EndIf

$pInterfaceList = $aResult[3] ;pointer to WLAN_INTERFACE_INFO_LIST. This is where the struct is in memory.

;The WLAN_INTERFACE_INFO_LIST structure contains two dwords followed by an array of WLAN_INTERFACE_INFO structures.
;~ DWORD dwNumberOfItems;
;~ DWORD dwIndex;
;~ WLAN_INTERFACE_INFO InterfaceInfo[];

;The first dword defines how many interfaces are in the list - this is all we are interested in for the minute.
$tInterfaceList = DllStructCreate("dword", $pInterfaceList)
$iInterfaceCount = DllStructGetData($tInterfaceList, 1)
If Not $iInterfaceCount Then
ConsoleWrite("no interfaces were found" & @CRLF)
Exit
EndIf
Local $abGUIDs[$iInterfaceCount]

;The next thing we need to do is find out more about a WLAN_INTERFACE_INFO structure.
;~ GUID InterfaceGuid;
;~ WCHAR strInterfaceDescription[256];
;~ WLAN_INTERFACE_STATE isState;
;we know what a WCHAR is, but what about GUID and WLAN_INTERFACE_STATE types?.

;from MSDN we can see the GUID data type is actually a structure in itself.
;~ DWORD Data1;
;~ WORD Data2;
;~ WORD Data3;
;~ BYTE Data4[8];
;We dont really care what each element contains - however we do need the size of a GUID struct. 4 + 2 + 2 + (8 x 1) = 16 bytes

;WLAN_INTERFACE_STATE is an enumeration. In other words it is just an integer.

;So now we know a WLAN_INTERFACE_INFO struct is 532 bytes in size. 16 + (256 * 2) + 4.
;This means we can pinpoint the location of every WLAN_INTERFACE_INFO struct in WLAN_INTERFACE_INFO_LIST
;the first will be offset 8 bytes to $pInterfaceList (dwNumberOfItems + dwIndex)
;the second (if there is one) will be offset 540 bytes to $pInterfaceList (dwNumberOfItems + dwIndex + WLAN_INTERFACE_INFO) and so on.

For $i = 0 To $iInterfaceCount - 1
$pInterface = Ptr(Number($pInterfaceList) + ($i * 532 + 8)) ;Find pointer to WLAN_INTERFACE_INFO struct.
$tInterface = DllStructCreate("byte GUID[16]; wchar descr[256]; int State", $pInterface)
$abGUIDs[$i] = DllStructGetData($tInterface, "GUID")
ConsoleWrite("Found: " & DllStructGetData($tInterface, "descr") & @CRLF)
Next

;We dont need the WLAN_INTERFACE_INFO_LIST struct anymore. we should free the memory that our program has gobbled up.
DllCall($hDLL, "dword", "WlanFreeMemory", "ptr", $pInterfaceList)

;So now we have an array of all the GUIDs the WlanEnumInterfaces has found.
;We need to choose the interface we want to work with and throw it back into memory (because other funtions need a pointer to a GUID - not a GUID).
;I will choose the first interface.
$tGUID = DllStructCreate("byte[16]")
DllStructSetData($tGUID, 1, $abGUIDs[0])
$pGUID = DllStructGetPtr($tGUID) ;We now have our GUID pointer!

;Finish things off properly.
DllCall($hDLL, "dword", "WlanCloseHandle", "ptr", $hClientHandle, "ptr", 0); second param is reserved
DllClose($hDLL)

I understand that wchar[256] takes 256 bytes but why do we multiplt it by 2?

$pInterface = Ptr(Number($pInterfaceList) + ($i * 532 + 8)) ;Find pointer to WLAN_INTERFACE_INFO struct.

;So now we know a WLAN_INTERFACE_INFO struct is 532 bytes in size. 16 + (256 * 2) + 4.
 

I would be very happy if anyone can clarify this for me.

Link to comment
Share on other sites

58 minutes ago, crackdonalds said:

I understand that wchar[256] takes 256 bytes but why do we multiplt it by 2?

Because a wchar isn't a char. A wchar represents an encoding unit of the UTF16-LE encoding, hence 16-bit. Note that for Windows this doesn't reflect reality since a Unicode codepoint in UTF16 may need two 16-bit encoding units (using a surrogate). This is necessary to represent characters in higher Unicode planes than the BMP (Basic multilingual Plane).

But since AutoIt is essentially using a slightly restricted character set (UCS2) than the full Unicode range, you can approximate that a wchar represents a single Unicode character, coded as a 16-bit unit.

Also realize that in any Unicode encoding a "character" (in the sense of "the composed glyph that a user can see displayed on the screen") may be represented by an unbounded number of codepoints.

Edited by jchd
added detail on decomposed characters

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...