Jump to content

DllCall question


FreeFry
 Share

Recommended Posts

Ok, basically what I'm wondering if it's even possible to use this function with AutoIt: http://msdn2.microsoft.com/en-us/library/a...947(VS.85).aspx

I've got this code so far:

Global Const $ERROR_INSUFFICIENT_BUFFER = 122
Global Const $ERROR_INVALID_PARAMETER = 87
Global Const $NO_ERROR = 0


$dwOutBufLen = DllStructCreate("dword dwOutBufLen")

$a = DllCall("Iphlpapi.dll", "int", "GetInterfaceInfo", "ptr", 0, "ptr", DllStructGetPtr($dwOutBufLen))
If Not $a[0] = $ERROR_INSUFFICIENT_BUFFER Then Exit

$_IP_INTERFACE_INFO = DllStructCreate("byte[" & DllStructGetData($dwOutBufLen, "dwOutBufLen") & "]")

$a = DllCall("Iphlpapi.dll", "int", "GetInterfaceInfo", "ptr", DllStructGetPtr($_IP_INTERFACE_INFO), "ptr", DllStructGetPtr($dwOutBufLen, "dwOutBufLen"))
If $a[0] Then _Exit("Error " &  $a[0])

MsgBox(0, "", DllStructGetData($_IP_INTERFACE_INFO, 1))

The problem is, how do I get the info from that structure? Normal DllStructGetData won't work(?) as autoit doesn't "see" any difference in the bytes in the structure itself(?).

The C# example goes(partially) like this:

printf("Number of Adapters: %ld\n\n", pInfo->NumAdapters);
        for (i = 0; i < (int) pInfo->NumAdapters; i++) {
            printf("Adapter Index[%d]: %ld\n", i,
                   pInfo->Adapter[0].Index);
            printf("Adapter Name[%d]: %ws\n\n", i,
                   pInfo->Adapter[0].Name);

pInfo is the structure that contains the info I need(or some kind of pointer or something to it).

But what does the "->" expression translate to in AutoIt? :S

And how would autoit know that it's an object ("Adapter[0].Name")?

I'm really confused about this, please someone enlighten me on this subject. :)

Edited by FreeFry
Link to comment
Share on other sites

That's not hard, except for some M$ confusion in definitions I googled - length of wchar member in IP_ADAPTER_INDEX_MAP structure is defined as MAX_ADAPTER_NAME, which supposed to be 128, but for me the length is actually 256.

#include <Array.au3>

Global Const $ERROR_INSUFFICIENT_BUFFER = 122
Global Const $ERROR_INVALID_PARAMETER = 87
Global Const $NO_ERROR = 0

Global Const $MAX_ADAPTER_NAME = 128
Global Const $MAX_INTERFACE_NAME_LEN = 256
Global Const $SIZEOFLONG = 4

$a = DllCall("Iphlpapi.dll", "int", "GetInterfaceInfo", "ptr", 0, "int*", 0)
If Not $a[0] = $ERROR_INSUFFICIENT_BUFFER Then Exit

$_IP_INTERFACE_INFO = DllStructCreate("byte[" & $a[2] & "]")

$a = DllCall("Iphlpapi.dll", "int", "GetInterfaceInfo", "ptr", DllStructGetPtr($_IP_INTERFACE_INFO), "int*", $a[2])
If $a[0] Then ConsoleWrite("Error " &  $a[0] & @CRLF)

$iCount = DllStructGetData(DllStructCreate('long', DllStructGetPtr($_IP_INTERFACE_INFO)), 1)

Global $Adapters[$iCount][2]

For $i = 0 To $iCount-1
    $_IP_ADAPTER_INDEX_MAP = DllStructCreate("long Index;wchar Name[" & $MAX_INTERFACE_NAME_LEN & "]", DllStructGetPtr($_IP_INTERFACE_INFO)+$SIZEOFLONG+$i*($SIZEOFLONG+$MAX_INTERFACE_NAME_LEN))
    $Adapters[$i][0] = DllStructGetData($_IP_ADAPTER_INDEX_MAP, "Index")
    $Adapters[$i][1] = DllStructGetData($_IP_ADAPTER_INDEX_MAP, "Name")
Next

_ArrayDisplay($Adapters)

Also it seems you could calculate the size from the dwOutBufLen of the 2nd GetInterfaceInfo call (it returns actual total size, without the extra bytes like the 1st call does)...

"be smart, drink your wine"

Link to comment
Share on other sites

Oh my that looked really advanced! :|

Thanks for the response though Siao! I wonder how/or where you got such extensive knowledge about DllCall and how it translates to C structures. :)

Just a quick question though:

So, if a API parameter is specified as "inout", it's basically like the ByRef keyword when declaring a function in autoit, which means they need the * suffix in the DllCall type parameter right?

Man o man, I really want to learn how this works, but hell that looked super tricky to figure out. :)

Link to comment
Share on other sites

So, if a API parameter is specified as "inout", it's basically like the ByRef keyword when declaring a function in autoit, which means they need the * suffix in the DllCall type parameter right?

Yes. Although what you did - creating a struct for that purpose and passing the pointer to it - works fine too. The '*' thing was introduced in v3.2.10.0. And it makes the otherwise very annoying feature of DllCall (that it always returns an array) somewhat useful and therefore slightly more bearable.

Anyway, the "trick" is that you can specify a pointer when creating a DllStruct, which allows you to layer struct upon struct.

Edited by Siao

"be smart, drink your wine"

Link to comment
Share on other sites

Thank you again for the supreme explanations! :)

On a side note: I knew that you could create struct with data from another struct, but I was not sure how to 'read' the data in the first struct to begin with. Thanks for really shining some light on this for me. :)

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