Sign in to follow this  
Followers 0
ramadash

passing dll struct ptr to another au3 script

8 posts in this topic

#1 ·  Posted (edited)

ok it works now!

both scripts needs to be compiled, and in the same directory, you need an include located at http://www.autoitscript.com/forum/index.ph...1&hl=Diablo

I did not do any intensive testing, ima test it more and then post a skeleton class in the scripts and scraps.

plugin.au3

global $StructTypeString = "int;char[128];int;int";set the structure types here
global $STRUCT = DllStructCreate( $StructTypeString )
DllStructSetData( $STRUCT, 1, 555 );set the structure values here
DllStructSetData( $STRUCT, 2, "this is a string" )
DllStructSetData( $STRUCT, 3, 777 )
DllStructSetData( $STRUCT, 4, 888 )

;No editing needed below this point
RemoteFunc( WinGetHandle("myTest"), 10000, DllStructGetPtr( $STRUCT ), $StructTypeString )

Func RemoteFunc($window, $functionID, $wparam = 0, $lparam = 0)
    $dll = DllOpen("user32.dll")
    RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\autoit3", "StructTypeString01", "REG_SZ", $StructTypeString);dont worry this gets deleted after the call
    DllCall($dll, "none", "SendMessage","hwnd", $window, _
        "int", $functionID, "ptr",  $wparam, "str", $lparam)
    DllClose( $dll )
    $STRUCT = 0
    exit 
EndFunc

main.au3

#include <GUIConstants.au3>
#include <memory.au3>
;Editing of this file is not needed ( well except if you want to add features )
global $memHANDLE, $StructTypeString 

$CMD_Test = 10000
$mygui = GuiCreate("myTest",1,1)
GUIRegisterMsg($CMD_Test, "Rebuild_Struct")

func Rebuild_Struct($hWndGUI, $MsgID, $ptr, $useless )
    $StructTypeString = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\autoit3", "StructTypeString01")
    dim $v_buffer
    $memHANDLE = OpenMem( "Plugin.exe" )
     _MemoryGetStruct( $ptr , $memHandle, $v_buffer, $StructTypeString  ) 
    $fooError = @error 
    if $fooError > 0 then
        MsgBox( 0, "", "Error reading memory, @error= " & $fooError & " " & $StructTypeString )
        exit 
    EndIf
    $MaxIndex = StringSplit( $StructTypeString, ";" )
    dim $debugString
    for $i = 1 to $MaxIndex [0]
        $debugString &= " " & DllStructGetData( $v_buffer, $i )
    Next
    MsgBox( 0, "", $debugString )
    $v_buffer = 0;free mem used by struct
    _MemoryClose( $memHANDLE )
    if @error then MsgBox( 0, "", "Error closing memory" )
    Regdelete("HKEY_LOCAL_MACHINE\SOFTWARE\autoit3", "StructTypeString01" )
    exit 
EndFunc


While 1
    Sleep(100)
WEnd

;return a memory handle
func OpenMem( $process )
    $pid = ProcessExists ( $process )
    if not $pid then 
        MsgBox( 0, "", "ERROR: " & $process & " process does not exist" )
        exit 
    EndIf

;open main memory handle
    $mem = _memoryOpen( $pid )
    $fooError = @error
    if $fooError > 0 then 
        MsgBox( 0, "", "error opening " & $process & " , @error=" & $fooError )
        Exit
    Else
        MsgBox( 0, "", $process & " memory open sucessfully" )
    EndIf
    return $mem
EndFunc

;based off Nomad _MemoryRead() functions, credits to him :D 
;using byref is the only way I was able to keep the struct valid outside the function
;error values are the same as _MemoryRead()
;return value, 1=sucess 0=failed
func _MemoryGetStruct( $iv_Address, $ah_Handle, byref $v_buffer, $sv_Type = 'dword' )
    If Not IsArray($ah_Handle) Then
        SetError(1)
        Return 0
    EndIf
    
    $v_Buffer = DllStructCreate($sv_Type)
    
    If @Error Then
        SetError(@Error + 1)
        Return 0
    EndIf
    
    DllCall($ah_Handle[0], 'int', 'ReadProcessMemory', 'int', $ah_Handle[1], 'int', $iv_Address, 'ptr', DllStructGetPtr($v_Buffer), 'int', DllStructGetSize($v_Buffer), 'int', '')
    
    If Not @Error Then
        return 1
    Else
        SetError(6)
        Return 0
    EndIf
    
EndFunc
Edited by ramadash

Share this post


Link to post
Share on other sites



is this possible? I tryed but im having all kind of problems, So basically i just want to create a struct in 1 script, pass the poiter in script 2 and re-create the dllstruct from the pointer.

As I understand it, (I could be wrong!) an AutoIt script destroys its objects in memory when it closes (to free up memory), so any pointers from a closed script are useless. You may want to consider persisting the data some other way, like through the file system, registry or clipboard.

Alternatively, if script 2 is launched by script 1, you may only need to ensure the dllstruct is recreated before script 1 closes - but once it closes, the data is gone, like an unclosed file, dll or gui object handle. The best practice is to close them yourself, but of course not everyone does that.

Someone please correct me if I am wrong on this!

Share this post


Link to post
Share on other sites

well both scripts are running.

what I do is:

1. Generate a dllstruct in the form of a "CallArg" array (elem 1 = func name, elem 2 = @NumParams == 2 ? param name : param name array with "CallArg" string added to element 0 ) from the calling script

2. register MsgEvent from the Called script with 2 params: a "ptr" and a "int" (well 2 more params for function whnd and something else but its unimportant)

3. dllcall user32.dll sendmsg: Pass DllStructGetPtr( $Struct ) as the "ptr" value and @NumParams to the "int" value from calling script

4. the function registered to the event in the calling script DOES get called. Then I recreate the dllstruct with the passed pointer to the function and its there that it fuck up. the pointer point to something else (First element in the array did not return always the same thing, and most other values were 0 most of the time).

5. I am 100% sure that the DllStruct {set} and DllStruct {Get;FromPointer} functions works because they work when inside the same script using the pointer from DllStruct{set} passed to DllStruct{get}

I am really new with pointer stuff so im kinda lost, and I don't even know if what I am gonna say will make any sense, but I suspect that the pointer get's declared in the current program memory space (no clue how its called but I think each programs have memory adresses assigned to them, im not even sure on this one) so the pointer point's to the right adress but not in the right memory space...

pheww maby someone good in c++ could help :P

Share this post


Link to post
Share on other sites

well both scripts are running.

what I do is:

1. Generate a dllstruct in the form of a "CallArg" array (elem 1 = func name, elem 2 = @NumParams == 2 ? param name : param name array with "CallArg" string added to element 0 ) from the calling script

2. register MsgEvent from the Called script with 2 params: a "ptr" and a "int" (well 2 more params for function whnd and something else but its unimportant)

3. dllcall user32.dll sendmsg: Pass DllStructGetPtr( $Struct ) as the "ptr" value and @NumParams to the "int" value from calling script

4. the function registered to the event in the calling script DOES get called. Then I recreate the dllstruct with the passed pointer to the function and its there that it fuck up. the pointer point to something else (First element in the array did not return always the same thing, and most other values were 0 most of the time).

5. I am 100% sure that the DllStruct {set} and DllStruct {Get;FromPointer} functions works because they work when inside the same script using the pointer from DllStruct{set} passed to DllStruct{get}

I've had to pass complex information between concurrent scripts. I ended up using RegRead functions in While loops on both ends, and it really works quite well. If nobody comes up with a way for you to use DllStructs directly for this, you might consider that. (I hope someone has a way - that would be awesome and probably a lot cleaner!)

Share this post


Link to post
Share on other sites

Can you tell us what it is you are trying to achieve? Give us the bigger picture.

I may be wrong, but I seem to see in http://www.autoitscript.com/forum/index.php?showtopic=32073 and http://www.autoitscript.com/forum/index.php?showtopic=30969 and http://www.autoitscript.com/forum/index.php?showtopic=31563 and http://www.autoitscript.com/forum/index.php?showtopic=31551 you appear to be asking the same thing over and over again.

Have you read the help file on creating and using functions and scoping of variables? Have you had a look at the tutorial in these forums?

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

Can you tell us what it is you are trying to achieve? Give us the bigger picture.

I may be wrong, but I seem to see in http://www.autoitscript.com/forum/index.php?showtopic=32073 and http://www.autoitscript.com/forum/index.php?showtopic=30969 and http://www.autoitscript.com/forum/index.php?showtopic=31563 and http://www.autoitscript.com/forum/index.php?showtopic=31551 you appear to be asking the same thing over and over again.

Have you read the help file on creating and using functions and scoping of variables? Have you had a look at the tutorial in these forums?

yes man I mean im not that newb at using autoit (even if I dont have much post)..

im not asking the same things, all those topics are for different stuff... now I got my way to pass data but the pointer I am trying to pass seem's to turn invalid after it's passed. Ok if you want ill get u some code sample when i get home. But eh it's not because I cant declare a function that my pointer is screwing up..

@Sohfeyr: After thinking I think you might be right, when I first read the "SendMessage" documentation in the win32 api I think there is something Ive got wrong:

The SendMessage function sends the specified message to a window or windows. The function calls the window procedure for the specified window and does not return until the window procedure has processed the message. The PostMessage function, in contrast, posts a message to a thread’s message queue and returns immediately.
When I saw The function calls the window procedure for the specified window and does not return until the window procedure has processed the message. I assumed that it would wait for the remotly called function to return, but I think it only wait for the function to be called, and since my other script was calling 2 functions then returning it is very possible that the main script did not had the time to handle the request befor the other script exited with it's pointer.

Ok ima go try something now thanks alot!

edit: well im not sure I tryied looping the functions so they have to be manually closed, I also tryied not to kill the struct at any times, the pointer have the same value in script 1 than script 2.

ok here I have sample code, its pretty ugly but I was just testing stuff so.. eh..

Script 1 run's first and register the msg, script 2 is runned after, create a struct, pass it's pointer to script 2. Well try it, the values are hella weird (looks like the pointer dosent point to the same stuff in each scripts) or maby I am just doing it completly wrong, or maby it cant be done at all.

script 1

#include <GUIConstants.au3>

$CMD_Test = 10000

$mygui = GuiCreate("myTest",1,1)

GUIRegisterMsg($CMD_Test, "Rebuild_Struct")

While 1
    Sleep(100)
WEnd

func Rebuild_Struct($hWndGUI, $MsgID, $ptr)
    MsgBox( 0, "", $ptr )
    $newSTRUCT = DllStructCreate( "char[128];char[128]", $ptr )
    MsgBox( 0, "", "Structure values, index 1 = " & DllStructGetData( $newSTRUCT, 1 ) & ", index 2 = " & DllStructGetData( $newSTRUCT, 2 ) )
    kill_Struct( $newSTRUCT )
EndFunc

func kill_Struct($handle)
   $handle = 0
EndFunc

script 2

global $STRUCT = DllStructCreate( "char[128];char[128]" )
DllStructSetData( $STRUCT, 1, "Str01" )
DllStructSetData( $STRUCT, 2, "Str02" )
MsgBox( 0, "", "Structure values, index 1 = " & DllStructGetData( $STRUCT, 1 ) & ", index 2 = " _ 
        & DllStructGetData( $STRUCT, 2 ) & ", Pointer = 0x" & Hex( DllStructGetPtr( $STRUCT ) ) )

RemoteFunc( WinGetHandle("myTest"), 10000, DllStructGetPtr( $STRUCT ))
while 1
    Sleep(100)
WEnd

kill_struct($STRUCT)

Func RemoteFunc($window, $functionID, $wparam = 0, $lparam = 0)
    $dll = DllOpen("user32.dll")
    DllCall($dll, "none", "SendMessage","hwnd", $window, _
        "int", $functionID, "ptr",  $wparam, "long", $lparam)
EndFunc

func kill_Struct($handle)
   $handle = 0
EndFunc

my original function was more complicated than that but im not home now so I just created those to test

Edited by ramadash

Share this post


Link to post
Share on other sites

yep there is something that need's to be done to the pointer to be valid in another program adress space (exactly what i was suspecting) quote from some objective-c tutorial:

The way the pointer is used makes a difference in how the remote message is carried out. In neither case can the pointer simply be passed to the remote object unchanged; it points to a memory location in the senders address space and would not be meaningful in the address space of the remote receiver. The runtime system for remote messaging must make some adjustments behind the scenes.

now onto finding how to change it and if au3 supports that.

Share this post


Link to post
Share on other sites

yep there is something that need's to be done to the pointer to be valid in another program adress space (exactly what i was suspecting) quote from some objective-c tutorial:

now onto finding how to change it and if au3 supports that.

Did you ever find out how to do that? I'd be interested to know how, too...

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  
Followers 0