Jump to content

This site uses cookies. By continuing to browse the site you are agreeing to our use of cookies. Find out more here. X
X


Photo

CallBack - RegisterCallback function


  • This topic is locked This topic is locked
32 replies to this topic

#1 Zedna

Zedna

    AutoIt rulez!

  • MVPs
  • 8,664 posts

Posted 23 June 2007 - 02:24 PM

I noticed AutoHotkey added RegisterCallback(), which creates a machine-code address that when called, redirects the call to a function in the script.
This could be usefull adition to Autoit.

Look at
http://www.autohotkey.com/changelog/
http://www.autohotkey.com/docs/commands/RegisterCallback.htm

Edited by Zedna, 26 November 2007 - 01:36 AM.








#2 Lazycat

Lazycat

    Coding cat

  • MVPs
  • 1,174 posts

Posted 27 June 2007 - 10:04 AM

I noticed AutoHotkey added RegisterCallback(), which creates a machine-code address that when called, redirects the call to a function in the script.
This could be usefull adition to Autoit.

Look at
http://www.autohotkey.com/changelog/
http://www.autohotkey.com/docs/commands/RegisterCallback.htm


Second here.

On their forum I found tiny dll easily adaptable to use with GUIRegisterMsg (maybe something like was posted here, not found), but native dll-less feature is definitely preferable.
Koda homepage (http://www.autoitscript.com/fileman/users/lookfar/formdesign.html) (Bug Tracker)My Autoit script page (http://www.autoitscript.com/fileman/users/Lazycat/)

#3 Zedna

Zedna

    AutoIt rulez!

  • MVPs
  • 8,664 posts

Posted 27 June 2007 - 02:30 PM

Second here.

On their forum I found tiny dll easily adaptable to use with GUIRegisterMsg (maybe something like was posted here, not found), but native dll-less feature is definitely preferable.

Awesome!!
Here is the link to that post.
Can somebody experienced translate this EnumWindows.ahk example using callback.dll to EnumWindows.au3 please?

Plain Text         
pid:=DllCall("GetCurrentProcessId","Uint") DetectHiddenWindows, On hwnd:=WinExist("ahk_pid " . pid) hHookModule := DllCall("LoadLibrary", "str", "callback\callback.dll") EnumWindowsProcStub:=DllCall("callback\callback.dll\callbackit", "UInt", 2,"UInt", hwnd, "UInt", 0x542, "UInt", 0) OnMessage(0x542, "EnumWindowsProc") GoSub doit OnExit Tidyup AppsKey & F11:: doit:     out:=     DllCall("EnumWindows","UInt",EnumWindowsProcStub,"UInt",0)         EnumWindowsProc(wParam, lParam, msg, hwnd) {         global out         winid:=GetDeRefInteger(lParam)         otherparam:=GetDeRefInteger(lParam+4)         DetectHiddenWindows, On         WinGetTitle, text, ahk_id %winid%         WinGetClass, class, ahk_id %winid%         out.="HWND: ". winid . "`tTitle: " . text . "`tClass: " . class . "`n"         return 1     } ;Sleep 5000     MsgBox %out% return ;Tidyness Tidyup: DllCall("GlobalFree", "UInt", EnumWindowsProcStub) DllCall("FreeLibrary", "Uint", hHookModule) ExitApp GetDeRefInteger(pSource, pIsSigned = false, pSize = 4) ; pSource is an integer pointer to a raw/binary integer ; The caller should pass true for pSigned to interpret the result as signed vs. unsigned. ; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int). {     Loop %pSize% ; Build the integer by adding up its bytes.         result += *(pSource + A_Index-1) << 8*(A_Index-1)     if (!pIsSigned OR pSize > 4 OR result < 0x80000000)         return result ; Signed vs. unsigned doesn't matter in these cases. ; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:     return -(0xFFFFFFFF - result + 1) }


#4 Lazycat

Lazycat

    Coding cat

  • MVPs
  • 1,174 posts

Posted 27 June 2007 - 05:12 PM

Awesome!!
Here is the link to that post.
Can somebody experienced translate this EnumWindows.ahk example using callback.dll to EnumWindows.au3 please?

Here it is (a bit simplified).

Plain Text         
Global $out $hwnd = GUICreate("") $WM_AUTOIT_CALLBACK = DllCall("user32", "int", "RegisterWindowMessage") $WM_AUTOIT_CALLBACK = $WM_AUTOIT_CALLBACK[0] $hHookModule = DllCall("kernel32", "int", "LoadLibrary", "str", "callback.dll") $hHookModule = $hHookModule[0] $EnumWindowsProcStub = DllCall("callback.dll", "int", "callbackit", "uint", 2,"uint", $hwnd, "uint", $WM_AUTOIT_CALLBACK, "uint", 0) $EnumWindowsProcStub = $EnumWindowsProcStub[0] GUIRegisterMsg($WM_AUTOIT_CALLBACK, "EnumWindowsProc") DllCall("user32", "int", "EnumWindows","uint", $EnumWindowsProcStub, "uint", 0)     Func EnumWindowsProc($hWnd, $msg, $wParam, $lParam)     $struct = DllStructCreate("int;int", $lParam)     $out &= "Title: " & WinGetTitle(HWND(DllStructGetData($struct, 1))) & @CRLF     Return 1 EndFunc MsgBox (0, "Windows", $out) Func OnAutoitExit()     DllCall("kernel32", "int", "GlobalFree", "uint", $EnumWindowsProcStub)     DllCall("kernel32", "int", "FreeLibrary", "Uint", $hHookModule) EndFunc

Koda homepage (http://www.autoitscript.com/fileman/users/lookfar/formdesign.html) (Bug Tracker)My Autoit script page (http://www.autoitscript.com/fileman/users/Lazycat/)

#5 PaulIA

PaulIA

    API Extremist

  • MVPs
  • 1,201 posts

Posted 27 June 2007 - 06:32 PM

I had some problem getting the code to run. I swapped out a few of the DllCall functions to use the Auto3Lib versions and that seemed to fix the problem:
AutoIt         
#include <A3LMemory.au3> Global $hGUI, $hHook, $iMessage, $pStub $hGUI = GUICreate("") $iMessage = _API_RegisterWindowMessage("AutoItCallback") $hHook    = _API_LoadLibrary("CallBack.dll") $pStub    = DllCall("CallBack.dll", "int", "callbackit", "uint", 2, "uint", $hGUI, "uint", $iMessage, "uint", 0) $pStub    = $pStub[0] GUIRegisterMsg($iMessage, "EnumWindowsProc") DllCall("User32.dll", "int", "EnumWindows", "uint", $pStub, "uint", 0) Func EnumWindowsProc($hWnd, $msg, $wParam, $lParam)   Local $tStruct, $sText   $tStruct = DllStructCreate("int;int", $lParam)   $sText  = WinGetTitle(HWND(DllStructGetData($tStruct, 1)))   if $sText <> "" then _Lib_ConsoleWrite($sText)   Return 1 EndFunc Func OnAutoitExit()   _Mem_GlobalFree ($pStub)   _API_FreeLibrary($hHook) EndFunc

The Callback.dll needs to be in the script directory.
Auto3Lib: A library of over 1200 functions for AutoIt

#6 Zedna

Zedna

    AutoIt rulez!

  • MVPs
  • 8,664 posts

Posted 27 June 2007 - 07:23 PM

Great! It looks very promising.
Thanks Lazycat and PaulIA. :rolleyes:

#7 arcker

arcker

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 581 posts

Posted 27 June 2007 - 08:13 PM

mmm it could be the solution for the listview sort :rambo:
if anyone can do it :rolleyes:

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

 

Projects :

  • Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here

#8 Zedna

Zedna

    AutoIt rulez!

  • MVPs
  • 8,664 posts

Posted 27 June 2007 - 08:30 PM

mmm it could be the solution for the listview sort :rambo:
if anyone can do it :rolleyes:


For ListView sort is GUICtrlRegisterListViewSort() already in Autoit.

#9 arcker

arcker

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 581 posts

Posted 27 June 2007 - 08:41 PM

!! never noticed this function !!
thx

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

 

Projects :

  • Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here

#10 Zedna

Zedna

    AutoIt rulez!

  • MVPs
  • 8,664 posts

Posted 27 June 2007 - 09:17 PM

What about some improvements:

1) use @AutoItPID to get Hwnd --> for scripts without GUI

2) please make your suggestions here for API calls using CallVack
to make try if it works also on other functions then only EnumWindows,
for example: ReadDirectoryChangesW (as somebody said in AHK forum),...

3) make some include or UDF version --> something like :

CallBack_UDF.au3:
#include <A3LMemory.au3> Global $hHook, $iMessage, $pStub Func _RegisterCallBack($hWnd, $FunctioName     $iMessage = _API_RegisterWindowMessage("AutoItCallback")     $hHook    = _API_LoadLibrary("CallBack.dll")     $pStub    = DllCall("CallBack.dll", "int", "callbackit", "uint", 2, "uint", $hWnd, "uint", $iMessage, "uint", 0)     $pStub    = $pStub[0]     GUIRegisterMsg($iMessage, $FunctioName)         Return $pStub EndFunc Func OnAutoitExit()   _Mem_GlobalFree ($pStub)   _API_FreeLibrary($hHook) EndFunc


#11 piccaso

piccaso

    Rock me, Amadeus!

  • MVPs
  • 893 posts

Posted 28 June 2007 - 01:24 AM

thats nice.
i tried to do such a thing but i failed on adjusting the stack pointer right :rolleyes:

Can anyone enlighten me on why the stub is allocated in global memory?
Im not sure but i think its a bad thing to do since global memory is limited...

Anyway i played with it too and wrote some wrappers that do not rely on Auto3Lib.
No offence paul, i really appreciate your work but since there is only one function needed...

AutoIt         
Global $g_hDll_CallBack = DllOpen("Callback.dll") Func _DllCallBackAlloc($nParameters, $hWnd, $msg, $wParam = 0)     Local $hStub     If $g_hDll_CallBack < 0 Then Return SetError(1, 0, 0)     $hStub = DllCall($g_hDll_CallBack, "ptr", "callbackit", "uint", $nParameters, "hwnd", $hWnd, "uint", $msg, "ptr", $wParam)     If @error Then Return SetError(2, 0, 0)     If $hStub[0] = 0 Then Return SetError(2, 0, 0)     Return $hStub[0] EndFunc   ;==>_DllCallBackAlloc Func _DllCallBackFree(ByRef $hStub)     Local $aTmp     If $hStub > 0 Then         $aTmp = DllCall("kernel32.dll", "ptr", "GlobalFree", "ptr", $hStub)         If @error Then Return SetError(1, 0, False)         If $aTmp[0] = $hStub Then Return SetError(2, 0, False)         If $aTmp[0] = 0 Then             $hStub = 0             Return True         EndIf         Return False     EndIf     Return True EndFunc   ;==>_DllCallBackFree ;--------------------------- Global Const $WM_USER = 0x400 Global $hWnd_dummy = GUICreate(""), $sOut GUIRegisterMsg($WM_USER + 1, "_EnumWindowStationProc") Func _EnumWindowStationProc($hWnd, $msg, $wParam, $lParam)     $Param = DllStructCreate("ptr;ptr", $lParam)     $station = DllStructCreate("char[256]", DllStructGetData($Param, 1))     $sOut &= DllStructGetData($station, 1) & @CRLF     Return 1 EndFunc   ;==>_EnumWindowStationProc $hStub_EnumWindowStationProc = _DllCallBackAlloc(2, $hWnd_dummy, $WM_USER + 1) DllCall("user32.dll", "int", "EnumWindowStations", "ptr", $hStub_EnumWindowStationProc, "long", 0) _DllCallBackFree($hStub_EnumWindowStationProc) ConsoleWrite($sOut & @CRLF)


I was thinking about adding cdecl support, but i'm not really sure what i'm doing here...
so if i patch this (the stub created by the dll)
0015B4B8   E8 00000000    CALL 0015B4BD 0015B4BD   58              POP EAX 0015B4BE   8D90 2B000000    LEA EDX,DWORD PTR DS:[EAX+2B] 0015B4C4   8D4424 04        LEA EAX,DWORD PTR SS:[ESP+4] 0015B4C8   FF32          PUSH DWORD PTR DS:[EDX] 0015B4CA   50              PUSH EAX 0015B4CB   FF72 0C        PUSH DWORD PTR DS:[EDX+C] 0015B4CE   FF72 08        PUSH DWORD PTR DS:[EDX+8] 0015B4D1   FF72 04        PUSH DWORD PTR DS:[EDX+4] 0015B4D4   FF15 85103001    CALL DWORD PTR DS:[1301085]          ; SendMessageA 0015B4DA   5A              POP EDX 0015B4DB   59              POP ECX 0015B4DC   8D2494          LEA ESP,DWORD PTR SS:[ESP+EDX*4] 0015B4DF   FFE1          JMP ECX 0015B4E1   90              NOP
into this
0015B4B8   E8 00000000    CALL 0015B4BD 0015B4BD   58              POP EAX 0015B4BE   8D90 2B000000    LEA EDX,DWORD PTR DS:[EAX+2B] 0015B4C4   8D4424 04        LEA EAX,DWORD PTR SS:[ESP+4] 0015B4C8   FF32          PUSH DWORD PTR DS:[EDX] 0015B4CA   50              PUSH EAX 0015B4CB   FF72 0C        PUSH DWORD PTR DS:[EDX+C] 0015B4CE   FF72 08        PUSH DWORD PTR DS:[EDX+8] 0015B4D1   FF72 04        PUSH DWORD PTR DS:[EDX+4] 0015B4D4   FF15 85103001    CALL DWORD PTR DS:[1301085]          ; SendMessageA 0015B4DA   5A              POP EDX 0015B4DB   59              POP ECX 0015B4DC   FFE1          JMP ECX
stack looks good in the debugger but im still not sure :rambo:

any thoughts on that?
Posted Image CoProc Multi Process Helper libraryTrashBin.nfshost.com store your AutoIt related files here!AutoIt User Map

#12 piccaso

piccaso

    Rock me, Amadeus!

  • MVPs
  • 893 posts

Posted 30 June 2007 - 07:48 PM

Finally i see a light at the end of the (callback) tunnel...

This can be done without a dll too :rolleyes:
here is a proof of concept example:
AutoIt         
#cs    $sStub = "" _    & "E800000000"   _     ;~    $ ==>    > E8 00000000      CALL 0015B4BD                                & "58"           _     ;~    $+5      > 58               POP EAX    & "8D902B000000" _     ;~    $+6      > 8D90 2B000000    LEA EDX,DWORD PTR DS:[EAX+2B]    & "8D442404"     _     ;~    $+C      > 8D4424 04        LEA EAX,DWORD PTR SS:[ESP+4]    & "FF32"         _     ;~    $+10     > FF32             PUSH DWORD PTR DS:[EDX]    & "50"           _     ;~    $+12     > 50               PUSH EAX                                 ; lparam    & "FF720C"       _     ;~    $+13     > FF72 0C          PUSH DWORD PTR DS:[EDX+C]                ; wparam $+3c    & "FF7208"       _     ;~    $+16     > FF72 08          PUSH DWORD PTR DS:[EDX+8]                ; msg $+38    & "FF7204"       _     ;~    $+19     > FF72 04          PUSH DWORD PTR DS:[EDX+4]                ; hwnd $+34    & "E8!!!!!!!!90" _     ;~    $+1C     > FF15 85103001    CALL DWORD PTR DS:[1301085]              ; Call Sendmessage    & "5A"           _     ;~    $+22     > 5A               POP EDX    & "59"           _     ;~    $+23     > 59               POP ECX    & "8D2494"       _     ;~    $+24     > 8D2494           LEA ESP,DWORD PTR SS:[ESP+EDX*4]         ; Adjust stack by $+30 (stdcall only)    & "FFE1"         _     ;~    $+27     > FFE1             JMP ECX    & "90"                 ;~    $+29     > 90               NOP                           ;~    $+2A     > 000000000000                                             ; 6 bytes nothing                           ;~    $+30     > 02000000                                                 ; nParameters                           ;~    $+34     > D6080100                                                 ; hwnd                           ;~    $+38     > 01040000                                                 ; msg                           ;~    $+3C     > 00000000                                                 ; wparam        ; stdcall : E800000000588D902B0000008D442404FF3250FF720CFF7208FF7204E8!!!!!!!!905A598D2494FFE190    ; cdecl   : E800000000588D902B0000008D442404FF3250FF720CFF7208FF7204E8!!!!!!!!905A59909090FFE190    ;           0x1D (29.)                                                0x04    0x09    ;           0x56 (86.) #ce $WM_USER = 0x400 $hWnd_dummy = GUICreate("") $sOut = "" $hGlobal = DllCall("kernel32.dll","ptr","GlobalAlloc","uint",0,"dword",96) $hUser32 = DllCall("kernel32.dll","ptr","LoadLibrary","str","user32.dll") $pSendMessage = DllCall("kernel32.dll","ptr","GetProcAddress","ptr",$hUser32[0],"str","SendMessageA") $pRelSendMessage = $pSendMessage[0] - ($hGlobal[0] + 0x21) $vStub = DllStructCreate("ubyte[29];"       _ ; 1 Stub Part 1                        & "ptr;"             _ ; 2 Address of SendMessage relative to $+21 (pTo - $+21)                        & "ubyte[9];"        _ ; 3 Stub Part 2                        & "byte[6];"         _ ; 4 6 bytes nothing                        & "long;"            _ ; 5 nParams                        & "hwnd;"            _ ; 6 hwnd                        & "uint;"            _ ; 7 msg                        & "uint;",$hGlobal[0]) ; 8 wparam DllStructSetData($vStub,1,Binary("0xE800000000588D902B0000008D442404FF3250FF720CFF7208FF7204E8")) DllStructSetData($vStub,2,$pRelSendMessage) DllStructSetData($vStub,3,Binary("0x905A598D2494FFE190")) DllStructSetData($vStub,4,Binary("0x000000000000")) DllStructSetData($vStub,5,2) DllStructSetData($vStub,6,$hWnd_dummy) DllStructSetData($vStub,7,$WM_USER+1) DllStructSetData($vStub,8,0) GUIRegisterMsg($WM_USER + 1, "_EnumWindowStationProc") Func _EnumWindowStationProc($hWnd, $msg, $wParam, $lParam)     $Param = DllStructCreate("ptr;ptr", $lParam)     $station = DllStructCreate("char[256]", DllStructGetData($Param, 1))     $sOut &= DllStructGetData($station, 1) & @CRLF     Return 1 EndFunc   ;==>_EnumWindowStationProc DllCall("user32.dll", "int", "EnumWindowStations", "ptr", $hGlobal[0], "long", 0) ConsoleWrite($sOut & @CRLF) DllCall("kernel32.dll", "ptr", "GlobalFree", "ptr", $hGlobal[0])
at least it works for me :rambo:
but i have no practice on a level that low and i'm only 90% sure about what i'm doing here so
if someone with asm experience could take a look at it...
I would really appreciate that :x
Posted Image CoProc Multi Process Helper libraryTrashBin.nfshost.com store your AutoIt related files here!AutoIt User Map

#13 Uten

Uten

    stupid is as stupid does..

  • Active Members
  • PipPipPipPipPipPip
  • 1,989 posts

Posted 01 July 2007 - 03:05 AM

You guys ROCK! :rolleyes:
Please make it an official UDF.

To make it a safer UDF I think a discussion should be started on how multiple OnAutoItExit functions could be registered with the script engine. It would be so much simpler if a UDF's file could automatically clean up after it self. The discussion probably deserves it's own topic, but maybe you will keep it in mind and consider possible solutions?

I have wrapped it up a bit for my own understanding and added a simple EnumChildWindows sample.

AutoIt         
#region - Win32EnumsStub ; ============================================================================ ; ; ============================================================================ Global $_CreateCallBackStubCounter = 0 Func _CreateCallBackStub() #cs    $sStub = "" _    & "E800000000"   _     ;~    $ ==>    > E8 00000000      CALL 0015B4BD                                & "58"           _     ;~    $+5      > 58               POP EAX    & "8D902B000000" _     ;~    $+6      > 8D90 2B000000    LEA EDX,DWORD PTR DS:[EAX+2B]    & "8D442404"     _     ;~    $+C      > 8D4424 04        LEA EAX,DWORD PTR SS:[ESP+4]    & "FF32"         _     ;~    $+10     > FF32             PUSH DWORD PTR DS:[EDX]    & "50"           _     ;~    $+12     > 50               PUSH EAX                                 ; lparam    & "FF720C"       _     ;~    $+13     > FF72 0C          PUSH DWORD PTR DS:[EDX+C]                ; wparam $+3c    & "FF7208"       _     ;~    $+16     > FF72 08          PUSH DWORD PTR DS:[EDX+8]                ; msg $+38    & "FF7204"       _     ;~    $+19     > FF72 04          PUSH DWORD PTR DS:[EDX+4]                ; hwnd $+34    & "E8!!!!!!!!90" _     ;~    $+1C     > FF15 85103001    CALL DWORD PTR DS:[1301085]              ; Call Sendmessage    & "5A"           _     ;~    $+22     > 5A               POP EDX    & "59"           _     ;~    $+23     > 59               POP ECX    & "8D2494"       _     ;~    $+24     > 8D2494           LEA ESP,DWORD PTR SS:[ESP+EDX*4]         ; Adjust stack by $+30 (stdcall only)    & "FFE1"         _     ;~    $+27     > FFE1             JMP ECX    & "90"                 ;~    $+29     > 90               NOP                           ;~    $+2A     > 000000000000            ; 6 bytes nothing                           ;~    $+30     > 02000000             ; nParameters                           ;~    $+34     > D6080100             ; hwnd                           ;~    $+38     > 01040000             ; msg                           ;~    $+3C     > 00000000             ; wparam        ; stdcall : E800000000588D902B0000008D442404FF3250FF720CFF7208FF7204E8!!!!!!!!905A598D2494FFE190    ; cdecl   : E800000000588D902B0000008D442404FF3250FF720CFF7208FF7204E8!!!!!!!!905A59909090FFE190    ;           0x1D (29.)                                                0x04    0x09    ;           0x56 (86.) #ce     $_CreateCallBackStubCounter += 1     $WM_USER = 0x400 ; TODO: Can we check that the message $WM_USER + $ID is not used allready?     $hWnd_dummy = GUICreate("") ;TODO: Check if user has a window allready and use that or make sure we switch back to current window when done here?     $hGlobal = DllCall("kernel32.dll","ptr","GlobalAlloc","uint",0,"dword",96)     $hUser32 = DllCall("kernel32.dll","ptr","LoadLibrary","str","user32.dll")     $pSendMessage = DllCall("kernel32.dll","ptr","GetProcAddress","ptr",$hUser32[0],"str","SendMessageA")     $pRelSendMessage = $pSendMessage[0] - ($hGlobal[0] + 0x21)     $vStub = DllStructCreate("ubyte[29];"       _ ; 1 Stub Part 1                            & "ptr;"             _ ; 2 Address of SendMessage relative to $+21 (pTo - $+21)                            & "ubyte[9];"        _ ; 3 Stub Part 2                            & "byte[6];"         _ ; 4 6 bytes nothing                            & "long;"            _ ; 5 nParams                            & "hwnd;"            _ ; 6 hwnd                            & "uint;"            _ ; 7 msg                            & "uint;",$hGlobal[0]) ; 8 wparam     DllStructSetData($vStub,1,Binary("0xE800000000588D902B0000008D442404FF3250FF720CFF7208FF7204E8"))     DllStructSetData($vStub,2,$pRelSendMessage)     DllStructSetData($vStub,3,Binary("0x905A598D2494FFE190"))     DllStructSetData($vStub,4,Binary("0x000000000000"))     DllStructSetData($vStub,5,2)     DllStructSetData($vStub,6,$hWnd_dummy)     DllStructSetData($vStub,7,$WM_USER + $_CreateCallBackStubCounter) ;$WM_USER+$ID)     DllStructSetData($vStub,8,0)     Local $r[2]     $r[0] = $WM_USER + $_CreateCallBackStubCounter     $r[1] = $hGlobal[0]     return $r EndFunc #endregion Global $cb1, $cb2, $cb3 ;Has to be global to be able to free data. ;         Used by *proc samples so placed in the midle of the code #region - Win32EnumProcs Func _EnumWindowStationsProc($hWnd, $msg, $wParam, $lParam)     Local $station, $sOut     $Param = DllStructCreate("ptr;ptr", $lParam)     $station = DllStructCreate("char[256]", DllStructGetData($Param, 1))     $sOut = DllStructGetData($station, 1) & @CRLF     ConsoleWrite("_EnumWindowStationsProc: $sOut:=" & $sOut & @CRLF)     Return 1 EndFunc   ;==>_EnumWindowStationsProc Func _EnumWindowsProc($hWnd, $msg, $wParam, $lParam)     Local $tStruct, $sOut     $tStruct = DllStructCreate("int;int", $lParam)     $sOut  = WinGetTitle(HWND(DllStructGetData($tStruct, 1)))     if $sOut <> "" then         ; NOTE: Calling external global variable         DllCall("user32.dll", "int", "EnumChildWindows", "hwnd", HWND(DllStructGetData($tStruct, 1)), "ptr", $cb3[1], "long", 0 )         ConsoleWrite("_EnumWindowsProc: $hWnd:=" & DllStructGetData($tStruct, 1) & ", $lParam:=" & DllStructGetData($tStruct, 2) & ", $sOut:=" & $sOut & @CRLF)     EndIf   Return 1 EndFunc Func _EnumChildWindowsProc($hWnd, $msg, $wParam, $lParam)     Local $tStruct, $sOut     $tStruct = DllStructCreate("int;int", $lParam)     ConsoleWrite("_EnumChildWindowsProc: $hWnd:=" & HWND(DllStructGetData($tStruct, 1)) & ", $lParm:=" & HWND(DllStructGetData($tStruct, 2)) & @CRLF )     Return 1 EndFunc #endregion - Win32EnumProcs Func Main()     HotKeySet("{ESC}", "Terminate")     ; Create stub, Register message, call the api     $cb1 = _CreateCallBackStub()     GUIRegisterMsg($cb1[0], "_EnumWindowStationsProc")     DllCall("user32.dll", "int", "EnumWindowStations", "ptr", $cb1[1], "long", 0)     ;     ; Create stub, Register message, call the api     ; Used by $cb2 To enumerate childwindows        $cb3 = _CreateCallBackStub()     GUIRegisterMsg($cb3[0], "_EnumChildWindowsProc")        ;       ; Create stub, Register message, call the api     $cb2 = _CreateCallBackStub()     GUIRegisterMsg($cb2[0], "_EnumWindowsProc")     DllCall("user32.dll", "int", "EnumWindows", "ptr", $cb2[1], "long", 0)         ; The normal application loop     While 1         Switch GuiGetMsg()             Case -3                 ExitLoop             Case 0                 Sleep(100)         EndSwitch     WEnd     ;ConsoleWrite($sOut & @CRLF)     Terminate() EndFunc Func Terminate()     ; Make sure we clean up the callback stubs.     ConsoleWrite("TERMINATE: Cleaning up" & @CRLF)     If $cb1[1] <> 0 Then DllCall("kernel32.dll", "ptr", "GlobalFree", "ptr", $cb1[1])     If $cb2[1] <> 0 Then DllCall("kernel32.dll", "ptr", "GlobalFree", "ptr", $cb2[1])     If IsArray($cb3) Then         If ($cb3[1] <> 0) Then DllCall("kernel32.dll", "ptr", "GlobalFree", "ptr", $cb3[1])     EndIf     ConsoleWrite("TERMINATE: Cleaning up done" & @CRLF)     Exit EndFunc ; ======================================== Main()


#14 piccaso

piccaso

    Rock me, Amadeus!

  • MVPs
  • 893 posts

Posted 01 July 2007 - 06:35 AM

i dont know if it ever gets official but here is it in udf form...
AutoIt         
Global $gp_DllCallBack_SendMessage = 0 Global $gh_DllCallBack_hUser32 = 0 Global $gi_DllCallBack_StubCount = 0 ;=============================================================================== ; ; Function Name:    _DllCallBackAlloc ; Description:      Allocates memory on global heap and creates a procedure ;                   which forwards a pointer to its arguments to a Window ; Parameter(s):     $nParameters - number of parameters ;                   $hWnd - handle of receiving window ;                   $msg - Window Message ;                   $wParam, Optional - wParam to pass to the handler procedure ;                   $fCedecl, Optional - use cdecl calling convention (default is stdcall) ; Requirement(s): ; Return Value(s):  Pointer to created stub or NULL on error ; @error Value(s):  1 = Error allocating memory from global heap ;                   2 = Error Loading User32.dll ;                   3 = Failed to get the address of SendMessage ; ; Author(s): ; ;=============================================================================== ; Func _DllCallBackAlloc($nParameters, $hWnd, $msg, $wParam = 0, $fcdecl = False)     Local $hGlobal, $hUser32, $pSendMessage_RelAddr, $vStub     $hGlobal = DllCall("kernel32.dll", "ptr", "GlobalAlloc", "uint", 0, "dword", 86) ; 86 = Size of stub     If @error Then Return SetError(1, 0, 0)     If $hGlobal[0] = 0 Then Return SetError(1, 0, 0)     $hGlobal = $hGlobal[0]     If $gp_DllCallBack_SendMessage = 0 Then         $hUser32 = DllCall("kernel32.dll", "ptr", "LoadLibrary", "str", "user32.dll")         If @error Then Return SetError(2, 0, 0)         If $hUser32[0] = 0 Then SetError(2, 0, 0)         $gh_DllCallBack_hUser32 = $hUser32[0]         $pSendMessage = DllCall("kernel32.dll", "ptr", "GetProcAddress", "ptr", $gh_DllCallBack_hUser32, "str", "SendMessageA")         If @error Then Return SetError(3, 0, 0)         If $pSendMessage = 0 Then Return SetError(3, 0, 0)         $gp_DllCallBack_SendMessage = $pSendMessage[0]     EndIf     $pSendMessage_RelAddr = $gp_DllCallBack_SendMessage - ($hGlobal + 0x21)     $vStub = DllStructCreate("ubyte[29];" _ ; 1 Stub Part 1              & "ptr;" _ ; 2 Address of SendMessage relative to $+21 (pTo - $+21)              & "ubyte[9];" _ ; 3 Stub Part 2              & "byte[6];" _ ; 4 6 bytes nothing              & "long;" _ ; 5 nParams              & "hwnd;" _ ; 6 hwnd              & "uint;" _ ; 7 msg              & "uint;", $hGlobal) ; 8 wparam     #cs Stub Part 1         $ ==>    > E8 00000000      CALL 0015B4BD         $+5      > 58               POP EAX         $+6      > 8D90 2B000000    LEA EDX,DWORD PTR DS:[EAX+2B]         $+C      > 8D4424 04        LEA EAX,DWORD PTR SS:[ESP+4]         $+10     > FF32             PUSH DWORD PTR DS:[EDX]         $+12     > 50               PUSH EAX         $+13     > FF72 0C          PUSH DWORD PTR DS:[EDX+C]         $+16     > FF72 08          PUSH DWORD PTR DS:[EDX+8]         $+19     > FF72 04          PUSH DWORD PTR DS:[EDX+4]         $+1C     > E8 !!!!!!!!      CALL USER32.SendMessageA    ; $pSendMessage_RelAddr     #ce     DllStructSetData($vStub, 1, Binary("0xE800000000588D902B0000008D442404FF3250FF720CFF7208FF7204E8"))     DllStructSetData($vStub, 2, $pSendMessage_RelAddr)     If $fcdecl Then         #cs Stub Part 2 - cdecl             $+21     > 90               NOP             $+22     > 5A               POP EDX             $+23     > 59               POP ECX             $+24     > 90               NOP             $+25     > 90               NOP             $+26     > 90               NOP             $+27     > FFE1             JMP ECX             $+29     > 90               NOP         #ce         DllStructSetData($vStub, 3, Binary("0x905A59909090FFE190"))     Else         #cs Stub Part 2 - stdcall             $+21     > 90               NOP             $+22     > 5A               POP EDX             $+23     > 59               POP ECX             $+24     > 8D2494           LEA ESP,DWORD PTR SS:[ESP+EDX*4]             $+27     > FFE1             JMP ECX             $+29     > 90               NOP         #ce         DllStructSetData($vStub, 3, Binary("0x905A598D2494FFE190"))     EndIf ;~    $+2A     > 000000000000     DllStructSetData($vStub, 4, Binary("0x000000000000")) ;~    $+30     > 00000000     DllStructSetData($vStub, 5, $nParameters) ;~    $+34     > 00000000     DllStructSetData($vStub, 6, $hWnd) ;~    $+38     > 00000000     DllStructSetData($vStub, 7, $msg) ;~    $+3C     > 00000000     DllStructSetData($vStub, 8, $wParam)     $gi_DllCallBack_StubCount += 1     Return $hGlobal EndFunc   ;==>_DllCallBackAlloc ;=============================================================================== ; ; Function Name:    _DllCallBackFree ; Description:      Frees memory from global heap allocated by _DllCallBackAlloc ; Parameter(s):     $hStub - Pointer to stub ; Requirement(s): ; Return Value(s):  On Success: True ;                   On Failure: False ; @error Value(s):  1 - Error freeing memory ;                   2 - Error freeing User32.dll ; Author(s): ; ;=============================================================================== ; Func _DllCallBackFree(ByRef $hStub)     Local $aTmp     If $hStub > 0 Then         $aTmp = DllCall("kernel32.dll", "ptr", "GlobalFree", "ptr", $hStub)         If @error Then Return SetError(1, 0, False)         If $aTmp[0] = $hStub Then Return SetError(1, 0, False)         If $aTmp[0] = 0 Then             $hStub = 0             $gi_DllCallBack_StubCount -= 1             If $gi_DllCallBack_StubCount < 1 Then                 $gi_DllCallBack_StubCount = 0                 $aTmp = DllCall("kernel32.dll", "int", "FreeLibrary", "ptr", $gh_DllCallBack_hUser32)                 If @error Then Return SetError(2, 0, False)                 If $aTmp[0] = 0 Then Return SetError(2, 0, False)                 $gh_DllCallBack_hUser32 = 0             EndIf             Return True         EndIf         Return False     EndIf     Return True EndFunc   ;==>_DllCallBackFree

Posted Image CoProc Multi Process Helper libraryTrashBin.nfshost.com store your AutoIt related files here!AutoIt User Map

#15 Lazycat

Lazycat

    Coding cat

  • MVPs
  • 1,174 posts

Posted 01 July 2007 - 03:05 PM

Impressive, piccaso! Though it still preferable have this ability inbuilt, with this solution looks not utterly need!
Koda homepage (http://www.autoitscript.com/fileman/users/lookfar/formdesign.html) (Bug Tracker)My Autoit script page (http://www.autoitscript.com/fileman/users/Lazycat/)

#16 bhoar

bhoar

    Wayfarer

  • Active Members
  • Pip
  • 81 posts

Posted 01 July 2007 - 10:06 PM

Impressive, piccaso! Though it still preferable have this ability inbuilt, with this solution looks not utterly need!


A plus of having it in-built is that it could be coded to avoid the issue of having UDFs register their own code for OnAutoItExit and/or dealing with multiple OnAutoItExit functions.

-brendan

#17 Uten

Uten

    stupid is as stupid does..

  • Active Members
  • PipPipPipPipPipPip
  • 1,989 posts

Posted 04 July 2007 - 07:21 AM

i dont know if it ever gets official but here is it in udf form...

Revorked my code a bit to make it work with your UDF's as a sample. Nicely done @picaso, even if it newer becomes official..:whistle:
AutoIt         
#region - Win32EnumProcs Global $cb3 ;Has to be global to be able to free data. ;         Used by *proc samples so placed in the midle of the code Func _EnumWindowStationsProc($hWnd, $msg, $wParam, $lParam)     Local $station, $sOut     $Param = DllStructCreate("ptr;ptr", $lParam)     $station = DllStructCreate("char[256]", DllStructGetData($Param, 1))     $sOut = DllStructGetData($station, 1) & @CRLF     ConsoleWrite("_EnumWindowStationsProc: $sOut:=" & $sOut & @CRLF)     Return 1 EndFunc   ;==>_EnumWindowStationsProc Func _EnumWindowsProc($hWnd, $msg, $wParam, $lParam)     Local $tStruct, $sOut     $tStruct = DllStructCreate("int;int", $lParam)     $sOut  = WinGetTitle(HWND(DllStructGetData($tStruct, 1)))     ; NOTE: Calling external global variable     Assert($cb3 <> 0)     Assert(HWND(DllStructGetData($tStruct, 1)) <> 0 )     DllCall("user32.dll", "int", "EnumChildWindows", "hwnd", HWND(DllStructGetData($tStruct, 1)), "ptr", $cb3, "long", 0 )     AssertNoErr()     ConsoleWrite("_EnumWindowsProc: $hWnd:=" & DllStructGetData($tStruct, 1) & ", $lParam:=" & DllStructGetData($tStruct, 2) & ", $sOut:=" & $sOut & @CRLF)   Return 1 EndFunc Func _EnumChildWindowsProc($hWnd, $msg, $wParam, $lParam)     Local $tStruct, $sOut     $tStruct = DllStructCreate("int;int", $lParam)     ConsoleWrite("_EnumChildWindowsProc: $hWnd:=" & HWND(DllStructGetData($tStruct, 1)) & ", $lParm:=" & HWND(DllStructGetData($tStruct, 2)) & @CRLF )     Return 1 EndFunc #endregion - Win32EnumProcs Func Main2()     HotKeySet("{ESC}", "Terminate2")     Local $cb1, $cb2     Local $hWndDumy = GUICreate("")     Local $WM_USER = 0x400     ; Get stub pointer, Register message, call the api     $cb1 = _DllCallBackAlloc( 2, $hWndDumy, $WM_USER +1)     If AssertNoErr() Then         GUIRegisterMsg($WM_USER +1, "_EnumWindowStationsProc")         DllCall("user32.dll", "int", "EnumWindowStations", "ptr", $cb1, "long", 0)              ;             ; Get stub pointer, Register message, call the api             ; Used by $cb2 To enumerate childwindows                $cb3 = _DllCallBackAlloc( 2,$hWndDumy, $WM_USER +3)             dbg("$cb3:=" & $cb3)             AssertNoErr()             GUIRegisterMsg($WM_USER +3, "_EnumChildWindowsProc")                AssertNoErr()             ;               ; Get stub pointer, Register message, call the api             Local $cb2 = _DllCallBackAlloc( 2, $hWndDumy, $WM_USER +2)             AssertNoErr()             GUIRegisterMsg($WM_USER +2, "_EnumWindowsProc")             AssertNoErr()             DllCall("user32.dll", "int", "EnumWindows", "ptr", $cb2, "long", 0)             AssertNoErr()         ; The normal application loop         Do             Switch GuiGetMsg()                 Case -3                     ExitLoop                 Case 0                     Sleep(100)                 Case $WM_User + 1, $WM_User + 2, $WM_User + 3                     ConsoleWrite("Unexpected??: $WM_User + [1-3]" & @CRLF)             EndSwitch         Until $gTerminate2     EndIf     ; Clean up. NOTE: This is on the global heap so it is imperative to clean up!     _DllCallBackFree($cb1)     _DllCallBackFree($cb3)     _DllCallBackFree($cb2) EndFunc Global $gTerminate2 = false Func Terminate2()     $gTerminate2 = True EndFuncFunc Assert($bool, $line=@ScriptLineNumber, $err=@error, $ext=@extended)     If NOT $bool then ConsoleWrite("(" & $line & ") := (" & $err & ")(" & $ext &") Assert failure: " & @CRLF)     return $bool EndFunc Func AssertNoErr($line=@ScriptLineNumber, $err=@error, $ext=@extended)     If $err <> 0 then ConsoleWrite("(" & $line & ") := (" & $err & ")(" & $ext &") AssertNoErr" & @CRLF)     return ($err = 0) EndFunc Global $gTrace = True Func Trace($msg="", $line=@ScriptLineNumber, $err=@error, $ext=@extended)     If $gTrace then ConsoleWrite("(" & $line & ") := (" & $err & ")(" & $ext &") TRACE: " &  $msg & @CRLF) EndFunc Global $gDbg = True Func dbg($msg="", $line=@ScriptLineNumber, $err=@error, $ext=@extended)     If $gDbg then ConsoleWrite("(" & $line & ") := (" & $err & ")(" & $ext &") TRACE: " &  $msg & @CRLF) EndFunc ; ======================================== Main2()


#18 Zedna

Zedna

    AutoIt rulez!

  • MVPs
  • 8,664 posts

Posted 04 July 2007 - 01:15 PM

CallBack can be used in Rich Edit Controls for
EM_STREAMIN Message
EM_STREAMOUT Message

In EDITSTREAM structure is EDITSTREAMCALLBACK

See MSDN IN and MSDN OUT

With this we can save/load RTF file from/to RichEdit control

#19 piccaso

piccaso

    Rock me, Amadeus!

  • MVPs
  • 893 posts

Posted 04 July 2007 - 05:59 PM

i read some articles about the global heap and i think explicit deallocation isnt necessary.

Now you're probably wondering if there is any difference between the local and global functions themselves. Well, the answer is no, they are now the same. In fact, they are interchangeable. Memory allocated via a call to LocalAlloc can be reallocated with GlobalReAlloc and then locked by LocalLock. The following table lists the global and local functions now available in Win32.


Other memory management routines such as GlobalAlloc, GlobalLock, GlobalFree, malloc, free, new, and delete, have all been changed to use VirtualAlloc and VirtualFree at a low level.

... and so on.
so if i get this right GloballAlloc is just short for Allocating executable memory on local heap and the name is just a win16 leftover :whistle:

I would prefer an this as an built-in feature too but just because the detour over windows messaging could be avoided.
But this is probably pretty tricky since the os fires callbacks whenever it wants to and might interrupt autoit in doing something...
and there are only a few situations where the windows message detour variant doesn't work (like crt's atexit)
It has been requested a couple of times and never happened so i guess it will stay that way.
Probably because it isn't essential...

thanks for the sample uten, i'll add it to my collection :lmao:
Posted Image CoProc Multi Process Helper libraryTrashBin.nfshost.com store your AutoIt related files here!AutoIt User Map

#20 piccaso

piccaso

    Rock me, Amadeus!

  • MVPs
  • 893 posts

Posted 08 July 2007 - 12:49 AM

simplified it a bit more, now usage can be as easy as this:
#include "DllCallBack.au3" ; Create Stub $hStub_EnumWindows = _DllCallBack ("_EnumWindowsProc", "hwnd;ptr") ; Call EnumWindows DllCall("user32.dll", "int", "EnumWindows", "ptr", $hStub_EnumWindows, "long", 0) ; Callback Procedure Func _EnumWindowsProc($hWnd, $lParam)     $hWnd = HWnd($hWnd)     ConsoleWrite($hWnd & " -> " & WinGetTitle($hWnd) & @CRLF)     Return 1 EndFunc   ;==>_EnumWindowsProc ; Free Stub _DllCallBack_Free ($hStub_EnumWindows)


more examples in the archive

moved here

Edited by piccaso, 08 August 2007 - 11:45 PM.

Posted Image CoProc Multi Process Helper libraryTrashBin.nfshost.com store your AutoIt related files here!AutoIt User Map




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users