Jump to content
Sign in to follow this  
Ejoc

Structres for DLLs

Recommended Posts

*Closed*

Version 0.7a:

added some data types, that's all

Version 0.7:

Added _DllMemSetString() - write a string

Added _DllMemGetString() - returns the string in the struct

Version 0.6d:

Fixed opt("mustdeclarevars",1) from complaining about dllmem.au3

Version 0.6b:

Removed a bug I introduced in 0.6

Version 0.6:

Fixed a "bug" in _DllMemFree() - wasnt decreasing the stack size

Removed a MsgBox debug

Version 0.5:

Fixed a bug in _DllMemSizeOf()

Version 0.4:

Reworked _DllMemSet() - added array element indexing

Reworked _DllMemGet() - added array element indexing

Added _DllMemSetDataType() - so you can add / redfine data types

Version 0.3:

Removed the need to call _DllMemFree()

Removed the need to call _DllMemEnd()

Sets OnExitFunc to _DllMemEnd()

Version 0.2:

Added comments, fixed reading ints from a struct.

New DllMem.dll

DllMem.au3 Header:

#cs
vi:ts=4 sw=4:
DllMem.au3
There is a supplied dll (DllMem.dll) that will create memory you can use
to pass to dll's that require structures.

Version 0.7
Ejoc

Functions you will be using:
_DllMemCreate($szStruct)                            - Creates a structure
_DllMemGet($lpStruct,$szStruct,$iElement,$iSub=0)- Get data from the struct
_DllMemSet($lpStruct,$szStruct,$iElement,$iData,$iSub=0)- Set data in the struct
_DllMemSetDataType($szDataType,$iSize)      - add a data type ie ("int",4)
_DllMemFree($lpStruct)                  - Free's the structure
_DllMemGetString($lpStruct,$szStruct,$iElement)     - Write a string
_DllMemSetString($lpStruct,$szStruct,$iElement,$szData) - Read a string

Functions you probably dont need to call:
_DllMemElementOffset($szStruct,$iIndex) - Calcs the offset of an element
_DllMemSizeOf($szDataType,$szStruct="",$iElement=0)- Calcs the sizeof the data type
_DllMemStructSize($szStruct)            - Calcs the size of a struct

Functions you should not need call:
_DllMemStart()                          - Called Automaticly
_DllMemEnd()                            - Call on Script Exit

There quite a few ways to call _DllMemCreate:
_DllMemCreate("int,int"); Allocate 8 bytes
_DllMemCreate("int;int"); Allocate 8 bytes
_DllMemCreate("int|int"); Allocate 8 bytes
_DllMemCreate("int(2)")  ; Allocate 8 bytes
_DllMemCreate(8)      ; Allocate 8 bytes
_DllMemCreate("byte(8)"); Allocate 8 bytes

Current Data Types Supported:
int,long,byte,char,ptr

Example Structures:
Struct {
    int x,y;
    long z;
    int *ptr;
}
Would be: "int;int;long;ptr"

Struct {
    int data[256];
    char string[128];
}
Would be: "int(256);char(128)"

Notes:
* When #include <DllMem.au3> is called OnExitFunc is set to _DllMemEnd(),
  if you set OnExitFunc to another function, have your function call
  _DllMemEnd()
* There is no checking if you are trying to access memory outside
  the memory allocated for the struct, ie you could cause overflows and
  bad things if you aren't careful

@Error states:
1   DllOpen Failed
2   DllCall Failed
3   Called FreeMem when DllMem.dll isnt open
4   Bad Struct String Format
#ce

This is a working version of code by Smed posted in this thread: http://www.autoitscript.com/forum/index.php?showtopic=10605

#include <DllMem.au3>

$MAC = _GetMACFromIP ("192.168.1.103")
MsgBox (0, "MAC Value", $MAC)

Func _GetMACFromIP ($sIP)
    Local $MAC,$MACSize,$mac_struct = "byte;byte;byte;byte;byte;byte"
    Local $i,$s,$r,$iIP
    
    $MAC        = _DllMemCreate($mac_struct)
    $MACSize    = _DllMemCreate("int")

    _DllMemSet($MACSize,"int",0,6)

    $r = DllCall ("Ws2_32.dll", "int", "inet_addr", "str", $sIP)
    $iIP = $r[0]
    $r = DllCall ("iphlpapi.dll", "int", "SendARP",_
                    "int", $iIP,_
                    "int", 0,_
                    "ptr", $MAC,_
                    "ptr", $MACSize)

    $s  = ""
    For $i = 0 To 5
        If $i Then $s = $s & ":"
        $s = $s & Hex(_DllMemGet($MAC,$mac_struct,$i),2)
    Next

    Return $s
EndFunc

And a Dll version of MouseGetPos:

#include <DllMem.au3>
#include <GUIConstants.au3>

$point_struct   = "int;int"
$test           = _DllMemCreate($point_struct)

GUICreate("MouseGetPos Test",300,300)
$h= GuiCtrlCreatelabel("",10,10,290,290)
GUISetState()

while 1
    $msg    = GUIGetMSG()
    $coor   = MouseGetPos()
    $s      = "MouseGetPos(" & $coor[0] & "," & $coor[1] & ")" & @CRLF
    $coor   = _MyMouseGetPos()
    $s      = $s & "_MyMouseGetPos(" & $coor[0] & "," & $coor[1] & ")" & @CRLF
    GUICtrlSetData($h,$s,1)
    sleep(10)
    if $msg = $GUI_EVENT_CLOSE Then Exitloop
WEnd

exit


Func _MyMouseGetPos()
    Local $r,$coor

    Dim $coor[2]
    $r          = DllCall ("user32.dll", "int", "GetCursorPos", "ptr", $test)
    $coor[0]    = _DllMemGet($test,$point_struct,0)
    $coor[1]    = _DllMemGet($test,$point_struct,1)

    return $coor
EndFunc

DllMem.zip

Edited by Ejoc

Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs

Share this post


Link to post
Share on other sites

Ok have some working code, needs comments, they are soon to come.

There is a bug when reading anything larger then a byte...

Edited by Ejoc

Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs

Share this post


Link to post
Share on other sites

Ok have some working code, needs comments, they are soon to come.

There is a bug when reading anything larger then a byte...

<{POST_SNAPBACK}>

Looks like something we can use for more than just the DllCall once you get it debuged, would be able to use it for sendmessage that needs pointer to buffer.

:)


SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Share this post


Link to post
Share on other sites

Excellent work! :)

I figured it was going to require some jumping through hoops to get working. Any chance of getting the DLL source too?


601DisengageEnd Program

Share this post


Link to post
Share on other sites

Sets OnExitFunc to _DllMemEnd()

What if I want to do an OnExitFunc also?

"I thoroughly disapprove of duels. If a man should challenge me, I would take him kindly and forgivingly by the hand and lead him to a quiet place and kill him." - Mark TwainPatient: "It hurts when I do $var_"Doctor: "Don't do $var_" - Lar.

Share this post


Link to post
Share on other sites

Notes:

* When #include <DllMem.au3> is called OnExitFunc is set to _DllMemEnd(),

  if you set OnExitFunc to another function, have your function call

  _DllMemEnd()


Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs

Share this post


Link to post
Share on other sites

Notes:

* When #include <DllMem.au3> is called OnExitFunc is set to _DllMemEnd(),

  if you set OnExitFunc to another function, have your function call

  _DllMemEnd()

<{POST_SNAPBACK}>

Didn't notice that :) Edited by Insolence

"I thoroughly disapprove of duels. If a man should challenge me, I would take him kindly and forgivingly by the hand and lead him to a quiet place and kill him." - Mark TwainPatient: "It hurts when I do $var_"Doctor: "Don't do $var_" - Lar.

Share this post


Link to post
Share on other sites

I haven't tested it, but you should post the source in the developer forum and try to get something as such added to the AutoIt3 source...  would be nice to have structs in AutoIt3... especially RECT, POINT, and other simple common structs...

Lar.

<{POST_SNAPBACK}>

If it makes you happy any, Larry, I just started messing around trying to come up with a good framework for doing something completely awesome in this regard. If I can figure out how the architecture should be, the actual implementation will be cake to do.

Share this post


Link to post
Share on other sites

Just woke up and glad to see people taking interest in it. Honestly this is so "simple" in my mind I was surprised no one did it :) I already know what 3 things I'll be adding today:

1) User defined data types, so if it isn't there you can just add it

2) Thought of a way to do "some" easy memory access checking, ie are you accessing memory that wasn't allocated

3) Currently if you call _DllMemGet($struct,"char(128);int",1) you get the int, which is what I want, but you currently cant access data in the char(128). So I will add an optional variable on the end to access elements in the array, ie: _DllMemGet($struct,"char(128);int",0,10) would return the 10'th char

I guess I can post the dll source, but its sooo simple :D basicly all it does is malloc(), free() and return *ptr;

Edited by Ejoc

Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs

Share this post


Link to post
Share on other sites

Added userdefined data types and added array element indexing.

Fixed a bug in _DllMemSizeOf() Was failing on arrays when I added user defined datatypes, but its all good now :)

Edited by Ejoc

Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs

Share this post


Link to post
Share on other sites

Wow! very cool!

any plans to incorporate the script functions into the dll itself. so we can just use dllcall alone?

<{POST_SNAPBACK}>

Probably not, the reason being... I like dealing w/ string in AutoIt better then C :D And actually the development path I was aiming for was to incorperate my dll function calls into AutoIt. :)

Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs

Share this post


Link to post
Share on other sites

ok, this is looking good, now able to access what i was trying to access, can now get the text from an index of the combo box

#include <GuiConstants.au3>
#include <DllMem.au3>

Opt('MustDeclareVars',1)
If(Not IsDeclared('CB_GETCOUNT')) Then Global Const $CB_GETCOUNT = 0x146
If(Not IsDeclared('CB_GETLBTEXT')) Then Global Const $CB_GETLBTEXT = 0x148
If(Not IsDeclared('CB_GETLBTEXTLEN')) Then Global Const $CB_GETLBTEXTLEN = 0x149
    
If(Not IsDeclared('CB_GETDROPPEDCONTROLRECT')) Then Global Const $CB_GETDROPPEDCONTROLRECT = 0x152 

Dim $Combo,$Btn_Exit,$Status,$msg,$Btn_Get,$Input_item, $label_rect, $s_rect, $Btn_GETRECT

GuiCreate("ComboBox Get Item Data", 392, 254)

$Combo = GuiCtrlCreateCombo("", 70, 10, 270, 100)
GUICtrlSetData($Combo,"AutoIt|v3|is|freeware|BASIC-like|scripting|language|designed|for|automating|the Windows GUI.")
GUICtrlCreateLabel("Enter index number of item:",65,112,130,20,$SS_RIGHT)
$Input_item = GUICtrlCreateInput("0",200,110,50,20,$ES_NUMBER)
GUICtrlSetLimit($Input_item,2)
$Btn_Get = GuiCtrlCreateButton("Get Item", 150, 140, 90, 30)
$Btn_Exit = GuiCtrlCreateButton("Exit", 150, 180, 90, 30)
$s_rect = "Left:" & @LF & "Top:" & @LF & "Right:" & @LF & "Bottom:"
$label_rect = GUICtrlCreateLabel($s_rect,270,100,100,55,$SS_SUNKEN)
$Btn_GETRECT = GUICtrlCreateButton("Get Dropped Control Rect",270,180,90,40,$BS_MULTILINE)
$Status = GUICtrlCreateLabel("",0,234,392,20,BitOR($SS_SUNKEN,$SS_CENTER))
GUICtrlSetData($Status,"Items: " & _GUICtrlComboBoxGetCount($Combo))
GuiSetState()
While 1
    $msg = GuiGetMsg()
    Select
        Case $msg = $GUI_EVENT_CLOSE Or $msg = $Btn_Exit
            ExitLoop
        Case $msg = $Btn_Get
                Local $v_data
                Local $i_count = _GUICtrlComboBoxGetLBText($Combo, Int(GUICtrlRead($Input_item)), $v_data)
            GUICtrlSetData($Status,"Len: " & $i_count & " Item: " & $v_data)
        Case $msg = $Btn_GETRECT
                Local $rect_array = _GUICtrlComboBoxGetDroppedControlRect($Combo)
                If(IsArray($rect_array)) Then
                    $s_rect = "Left:" & $rect_array[1] & @LF & "Top:" & $rect_array[2] & @LF & "Right:" & $rect_array[3] & @LF & "Bottom:" & $rect_array[4]
                    GUICtrlSetData($label_rect,$s_rect)
                EndIf
    EndSelect
WEnd
Exit

Func _GUICtrlComboBoxGetCount($h_combobox)
   Return GUICtrlSendMsg ( $h_combobox, $CB_GETCOUNT , 0, 0 )
EndFunc

Func _GUICtrlComboBoxGetLBText($h_combobox, $i_index, ByRef $v_data)
    Local $len = _GUICtrlComboBoxGetLBTextLen($h_combobox, $i_index)
    Local $i,$ret
    Local $struct=""

    $v_data = ""
    $struct = "char(" & $len & ")"
    Local $p
    _DllMemSetDataType("char",$len)
    $p    = _DllMemCreate($struct)
    _DllMemSet($p,$struct,0, _DllMemStructSize($struct))
    $ret = GUICtrlSendMsg( $h_combobox, $CB_GETLBTEXT, $i_index, $p)
    $v_data = _DllMemGetString($p,$struct,0)
    _DllMemFree($p)
    Return $ret
EndFunc

Func _GUICtrlComboBoxGetLBTextLen($h_combobox, $i_index)
   Return GUICtrlSendMsg ( $h_combobox, $CB_GETLBTEXTLEN , $i_index, 0 )
EndFunc

Func _GUICtrlComboBoxGetDroppedControlRect($h_combobox)
;~     typedef struct _RECT { 
;~       LONG left; 
;~       LONG top; 
;~       LONG right; 
;~       LONG bottom; 
;~     } RECT, *PRECT;
    Local $RECT = "long;long;long;long"
    Local $left = 0
    Local $top = 1
    local $right = 2
    Local $bottom = 3
    Local $p, $ret
    _DllMemSetDataType("long",4)
    $p    = _DllMemCreate($RECT)
    _DllMemSet($p,$RECT,0, _DllMemStructSize($RECT))
    $ret = GUICtrlSendMsg($h_combobox, $CB_GETDROPPEDCONTROLRECT, 0, $p)
    If(Not $ret) Then 
        _DllMemFree($p)
        Return -1
    EndIf
    Local $array = StringSplit(_DllMemGet($p,$RECT,$left) & "," & _DllMemGet($p,$RECT,$top) & "," & _DllMemGet($p,$RECT,$right) & "," & _DllMemGet($p,$RECT,$bottom),",")
    _DllMemFree($p)
    Return $array
EndFunc

Hope this does get implimented, think it could solve alot of small problems.

Edited by gafrost

SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Share this post


Link to post
Share on other sites

Cool, 1 thing I should mention, each time you call _DllMemCreate() it will allocate memory and it is freed when you exit or by calling _DllMemFree(), if you create a struct in a function and dont free it, at some point it wont be able to allocate any more memory. I'd recommend either createing the struct outside the function OR call _DllMemFree($p) before you exit the Func.


Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs

Share this post


Link to post
Share on other sites

Just woke up and glad to see people taking interest in it.  Honestly this is so "simple" in my mind I was surprised no one did it :D

I don't think many people realize how simple objects are laid out in memory, particularly C-style structures. I've been wanting to work on something like this for awhile, but I'm lazy. At the moment, though, I have been working on some design ideas. My goal is a bit more ambitious than yours, so its pretty complicated. The actual coding for my idea shouldn't be too hard, but coming up with a good design that fits together and that I'm satisfied with is. This is a lot more fun than what I worked on previously (And put to the side for awhile), which was PE Header stuff... :)

Share this post


Link to post
Share on other sites

Here's another example I thru together:

#include <DllMem.au3>

#cs
From MSDN:
typedef struct _OSVERSIONINFO
{ 
  DWORD dwOSVersionInfoSize; 
  DWORD dwMajorVersion; 
  DWORD dwMinorVersion; 
  DWORD dwBuildNumber; 
  DWORD dwPlatformId; 
  TCHAR szCSDVersion[ 128 ]; 
} OSVERSIONINFO; 
#ce

$OSVersionInfo_struct   = "dword;dword;dword;dword;dword;char(128)"
$dwOSVersionInfoSize    = 0
$dwMajorVersion         = 1
$dwMinorVersion         = 2
$dwBuildNumber          = 3
$dwPlatformId           = 4
$szCSDVersion           = 5

_DllMemSetDataType("dword",4)
$p  = _DllMemCreate($OSVersionInfo_struct)

;think of this as p->dwOSVersionInfoSize = sizeof(OSVERSIONINFO)
_DllMemSet($p,$OSVersionInfo_struct,_
            $dwOSVersionInfoSize, _DllMemStructSize($OSVersionInfo_struct))

$ret = DllCall("kernel32.dll","int","GetVersionEx","ptr",$p)

if Not $ret[0] Then
    MsgBox(0,"DllCall Error","DllCall Failed")
    exit
EndIf

$major      = _DllMemGet($p,$OSVersionInfo_struct,$dwMajorVersion)
$minor      = _DllMemGet($p,$OSVersionInfo_struct,$dwMinorVersion)
$build      = _DllMemGet($p,$OSVersionInfo_struct,$dwBuildNumber)
$platform   = _DllMemGet($p,$OSVersionInfo_struct,$dwPlatformId)

$i          = 0
$version    = ""
While _DllMemGet($p,$OSVersionInfo_struct,$szCSDVersion,$i)
    $version    = $version & Chr(_DllMemGet($p,$OSVersionInfo_struct,$szCSDVersion,$i))
    $i          = $i + 1
WEnd

msgbox(0,"","Major: " & $major & @CRLF & _
            "Minor: " & $minor & @CRLF & _
            "Build: " & $build & @CRLF & _
            "Platform ID: " & $platform & @CRLF & _
            "Version: " & $version)
Edited by Ejoc

Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs

Share this post


Link to post
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
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...