Jump to content

DllCreateStruct with sub-structure array


Recommended Posts

Hopefully someone can help.

How would I go about making a call to GetIpAddrTable (MSDN).

The call requires a ptr to a structure to be sent as the first argument. That structure contains a ptr to another a structure in array form. Briefly: -

typedef struct _MIB_IPADDRTABLE {
  DWORD dwNumEntries;
  MIB_IPADDRROW table[ANY_SIZE];
} MIB_IPADDRTABLE, 
 *PMIB_IPADDRTABLE;

typedef struct _MIB_IPADDRROW {
  DWORD dwAddr;
  DWORD dwIndex;
  DWORD dwMask;
  DWORD dwBCastAddr;
  DWORD dwReasmSize;
  unsigned short unused1;
  unsigned short wType;
} MIB_IPADDRROW, 
 *PMIB_IPADDRROW;

How would this be defined in AutoIt thereby allowing me to make a call to the dll and retrieve the necessary information?

Any help is appreciated.

Link to comment
Share on other sites

I don't have a lot of experience with API calls such as this, but the following example should point you in the right direction. I doubt it will work as is, it will need some adjustment:

$_MIB_IPADDRROW_STRUCT = DllStructCreate('dword;dword;dword;dword;dword;ushort;ushort')

$Pointer = DllStructGetPtr($_MIB_IPADDRROW_STRUCT)

$_MIB_IPADDRTABLE_STRUCT = DllStructCreate('dword', $Pointer)

$bOrder = 1 ;1 = TRUE, 0 = FALSE

;this next function should be 1 line, it will probably split in 2 (needs re-combined)
DllCall("IPHLPAPI.DLL", "int", "GetIpAddrTable", "int", $_MIB_IPADDRTABLE_STRUCT, "ptr", DllStructGetSize($_MIB_IPADDRTABLE_STRUCT), "uint", $bOrder, "int")

$dwAddr = DllStructGetData($_MIB_IPADDRROW_STRUCT, 1)
$dwIndex = DllStructGetData($_MIB_IPADDRROW_STRUCT, 2)
$dwMask = DllStructGetData($_MIB_IPADDRROW_STRUCT, 3)
$dwBCastAddr = DllStructGetData($_MIB_IPADDRROW_STRUCT, 4)
$dwReasmSize = DllStructGetData($_MIB_IPADDRROW_STRUCT, 5)
$sunused1 = DllStructGetData($_MIB_IPADDRROW_STRUCT, 6)
$swType = DllStructGetData($_MIB_IPADDRROW_STRUCT, 7)

Nomad :D

Link to comment
Share on other sites

@Nomad

Thanks (i had started along this line but was starting to get stuck retrieving the information.

This is the code so far

$_MIB_IPADDRROW_STRUCT = DllStructCreate("dword;dword;dword;dword;dword;ushort;ushort")

$Pointer = DllStructGetPtr($_MIB_IPADDRROW_STRUCT)

$_MIB_IPADDRTABLE_STRUCT = DllStructCreate("dword", $Pointer)

$dwSize = DllStructCreate("dword")

;this next function should be 1 line, it will probably split in 2 (needs re-combined)
$ret = DllCall("IPHLPAPI.DLL", "int", "GetIpAddrTable", "ptr", 0, "ptr", DllStructGetPtr($dwSize), "int", 0)
if $ret[0] = 122 then $ret = DllCall("IPHLPAPI.DLL", "long", "GetIpAddrTable", "ptr", DllStructGetPtr($_MIB_IPADDRTABLE_STRUCT), "ptr", DllStructGetPtr($dwSize), "int", 0)
if $ret[0] = 0 then
   $dwAddr = DllStructGetData($_MIB_IPADDRROW_STRUCT, 1)
   $dwIndex = DllStructGetData($_MIB_IPADDRROW_STRUCT, 2)
   $dwMask = DllStructGetData($_MIB_IPADDRROW_STRUCT, 3)
   $dwBCastAddr = DllStructGetData($_MIB_IPADDRROW_STRUCT, 4)
   $dwReasmSize = DllStructGetData($_MIB_IPADDRROW_STRUCT, 5)
   $sunused1 = DllStructGetData($_MIB_IPADDRROW_STRUCT, 6)
   $swType = DllStructGetData($_MIB_IPADDRROW_STRUCT, 7)
   msgbox(0, "IP Address", $dwAddr & @crlf & $dwIndex & @crlf & $dwMask & @crlf & $dwBCastAddr & @crlf & $dwReasmSize & @crlf & $sunused1 & @crlf & $swType)
else
   msgbox(0, "Error",  $ret[0])
endif
$ret = 0
$dwSize = 0
$Pointer = 0
$_MIB_IPADDRROW_STRUCT = 0
$_MIB_IPADDRTABLE_STRUCT = 0

The problem I have now is that the data in _MIB_IPADDRROW_STRUCT does not seem to be in the same order as detailed by the structure definition.

Also I have multiple NICs in my laptop and therefore get 2 entries returned but I ponly have access to 1 of them. How would I turn $Pointer into an array or how would I access the items if it were already an array?

Link to comment
Share on other sites

@Nomad

Thanks (i had started along this line but was starting to get stuck retrieving the information.

This is the code so far

The problem I have now is that the data in _MIB_IPADDRROW_STRUCT does not seem to be in the same order as detailed by the structure definition.

Also I have multiple NICs in my laptop and therefore get 2 entries returned but I ponly have access to 1 of them. How would I turn $Pointer into an array or how would I access the items if it were already an array?

$Pointer should only be a pointer to the DllStructure array $_MIB_IPADDRROW_STRUCT. It may not be coded correctly for use like that, I'm not familiar with this API function. In any case, to get the data from a DllStructure, whether it is an array or not, you need to use DllStructGetData (Struct, Element, Index).

Struct is the DllStructure

Element is a number which cooresponds to the "Type" location in the structure. ('dword;int;dword;int') 1 would point to the first element 'dword', 2 would point to the second element 'int', 3 would point to the third element 'dword', etc..

Index is a number which cooresponds to the array index of the Element pointed to. ('char[5];char[6]') Element 1 has 5 indices, Element 2 has 6 indices. To read Index 3 of Element 2 you would do DllStructGetData (Struct, 2, 3).

I hope that helps a little. As far as trying to store information as you have asked, I'm not sure. You could try this:

$_MIB_IPADDRROW_STRUCT = DllStructCreate("dword[2];dword[2];dword[2];dword[2];dword[2];ushort[2];ushort[2]")
But I'm not sure if the API call would know to store the information in an array like this or not. I'd need to reproduce your situation to try this out, and I can't. Do some trial and error, that's what I'd be doing. :wacko:

At least it partially works for you, I wasn't sure if it would work at all, hehe. The rest is just trial and error, and once you get it working correctly, you'll have a nice new UDF. :D

Nomad :D

Link to comment
Share on other sites

Ejoc discussed structs within structs on this post (3rd page). I'm not sure if it can be done with current beta. I think we would need to add DllStructCreateSubStruct. I am interested in achieving this functionality also.

-Livewire

Link to comment
Share on other sites

Ejoc discussed structs within structs on this post (3rd page). I'm not sure if it can be done with current beta. I think we would need to add DllStructCreateSubStruct. I am interested in achieving this functionality also.

-Livewire

Yeah, that's a good link. I recommend thoroughly looking over page 3 cojms1 (post # 40+). If there's an answer, it's likely to hit you there. I don't really have the time to dive too deep into it right now. But if you haven't figured it out soon, I might give it a try. If for no other reason than a learning experience. :wacko:

Nomad :D

Link to comment
Share on other sites

This code is kind of confusing, but creates a struct which contains a float and an array of 5 sub-structs. This will only work with a fixed number of sub structs. This code does work with a dll call (not yours though, cojms1, b/c you need varying length of array)

-Livewire

Dim $num_of_sub_structs = 5
Dim $i
Dim $sub_struct[$num_of_sub_structs]
Dim $sub_struct_representation = "int;int"

$struct = DllStructCreate("float;" & OneToMultiple($sub_struct_representation,$num_of_sub_structs))
If @error Then
    MsgBox(0,"","Error in DllStructCreate " & @error);
    Exit
EndIf

For $i = 1 To $num_of_sub_structs
    $sub_struct[$i - 1] = DllStructCreate($sub_struct_representation,DllStructGetPtr($struct,DetermineLocation($sub_struct_representation,$i,2)))
Next

DllStructSetData($struct,1,10.123)
DllStructSetData($sub_struct[4],1,20)
dllstructsetData($sub_struct[4],2,100)

MsgBox(0,"Struct Data",DllStructGetData($struct,1) & @CRLF & _
                        DllStructGetData($struct,DetermineLocation($sub_struct_representation,5,2)) & @CRLF & _
                        DllStructGetData($struct,DetermineLocation($sub_struct_representation,5,2) + 1))

Func OneToMultiple($rep,$num)
    Local $local_rep = $rep
    While $num - 1 > 0
        $local_rep &= ";" & $rep
        $num -= 1
    WEnd
    Return $local_rep
EndFunc

Func DetermineLocation($rep,$offset,$initial_loc = 1)
    Local $split_string
    $split_string = StringSplit($rep,";")
    Return 1 + ($offset - 1) * $split_string[0] + $initial_loc - 1
EndFunc
Link to comment
Share on other sites

Thanks for all the help guys.

Working code is: -

$numElements = 7
$strStruct = "dword;dword;dword;dword;dword;ushort;ushort"
$_MIB_IPADDRTABLE_STRUCT = DllStructCreate("dword;" & $strStruct)
$dwSize = DllStructCreate("dword")

$ret = DllCall("IPHLPAPI.DLL", "int", "GetIpAddrTable", "ptr", DllStructGetPtr($_MIB_IPADDRTABLE_STRUCT), "ptr", DllStructGetPtr($dwSize), "int", 0);get the size
$ret = DllCall("IPHLPAPI.DLL", "int", "GetIpAddrTable", "ptr", DllStructGetPtr($_MIB_IPADDRTABLE_STRUCT), "ptr", DllStructGetPtr($dwSize), "int", 0);get the number of entries
$numEntries = DllStructGetData($_MIB_IPADDRTABLE_STRUCT, 1)

;create the structure string
$strTemp = ""
for $i = 1 to $numEntries
   $strTemp &= $strStruct & ";"
next
$strTemp = StringTrimRight($strTemp, 1)
$_MIB_IPADDRTABLE_STRUCT = 0
$_MIB_IPADDRTABLE_STRUCT = DllStructCreate("dword;" & $strTemp)

$ret = DllCall("IPHLPAPI.DLL", "int", "GetIpAddrTable", "ptr", DllStructGetPtr($_MIB_IPADDRTABLE_STRUCT), "ptr", DllStructGetPtr($dwSize), "int", 0);get the results
if $ret[0] = 0 then
   for $i = 1 to $numEntries
      $strMsg = ""
      $offset = (($i -1) * $numElements)
      $strAddress = DllStructGetData($_MIB_IPADDRTABLE_STRUCT, $offset + 2)
      $ret = DllCall("wsock32.dll", "str", "inet_ntoa", "int", $strAddress)
      $strAddress = $ret[0]
      $dwindex = DllStructGetData($_MIB_IPADDRTABLE_STRUCT, $offset + 3)
      $strMask = DllStructGetData($_MIB_IPADDRTABLE_STRUCT, $offset + 4)
      $ret = DllCall("wsock32.dll", "str", "inet_ntoa", "int", $strMask)
      $strMask = $ret[0]
      $strBAddr = DllStructGetData($_MIB_IPADDRTABLE_STRUCT, $offset + 5)
      $ret = DllCall("wsock32.dll", "str", "inet_ntoa", "int", $strBAddr)
      $strBAddr = $ret[0]     
      $dwReasmSize = DllStructGetData($_MIB_IPADDRTABLE_STRUCT, $offset + 6)
      $unused1 = DllStructGetData($_MIB_IPADDRTABLE_STRUCT, $offset + 7)
      $wType = DllStructGetData($_MIB_IPADDRTABLE_STRUCT, $offset + 8)
      $strMsg = $strAddress & @crlf & $dwIndex & @crlf & $strMask & @crlf & $strBAddr & @crlf & $dwReasmSize & @crlf & $unused1 & @crlf & $wType 
      msgbox(0, "", $strMsg)
   next
endif

$_MIB_IPADDRRABLE_STRUCT = 0
Link to comment
Share on other sites

Lol.

It was quite easy after it had been pointed out that the arrays could be used as repeated types in the structure. Should have seen this earlier really.

Right. Now on to getting the rest of the app working.

Thanks again for all your help.

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