Jump to content

Recommended Posts

Posted
#include-once
#include <Memory.au3>
#include <WinAPISys.au3>

Func Thread_Call($opcode , $control_wait = 1 , $timeout = 2000 ,  $thread_wait_show = 0)
Local $pExecutableCode = _MemVirtualAlloc(0, BinaryLen($opcode), $MEM_COMMIT, $PAGE_EXECUTE_READWRITE)
Local $tCodeBuffer = DllStructCreate("byte a["&BinaryLen($opcode)&"]", $pExecutableCode)
DllStructSetData($tCodeBuffer, 1, $opcode)
Local $Check_return = 0
Local $Recvice_retcode = DllStructCreate("int a[1];")
Local $aRet = DllCall("kernel32.dll", "handle", "CreateThread", "ptr", 0, "dword_ptr", 0, "ptr", $pExecutableCode, "ptr", DllStructGetPtr($Recvice_retcode), "dword", 0, "dword*", 0)
    If @error Then
        msgbox(0,1,"CreateThread error:" & @error & @CRLF)
    ElseIf $aRet[0] = 0 Then
        msgbox(0,2,"CreateThread error:" & "Null" & @CRLF)
    Else
        Local $hThread = $aRet[0]
        if $control_wait = 1 Then
            $aRet = DllCall("kernel32.dll", "dword", "WaitForSingleObject", "handle", $hThread, "dword", $timeout)
            If @error Then
                MsgBox(0,3,"WaitForSingleObject error: " & @error & @CRLF)
            Else
                Switch $aRet[0]
                    Case -1, 0xFFFFFFFF
                        $aRet = DllCall("kernel32.dll", "bool", "TerminateThread", "handle", $hThread, "int", -1)
                        if $thread_wait_show = 1 then
                            msgbox(0,4,"WAIT_FAILED")
                        EndIf
                    Case 0x00000102
                        $aRet = DllCall("kernel32.dll", "bool", "TerminateThread", "handle", $hThread, "int", -1)
                        if $thread_wait_show = 1 then
                            msgbox(0,5,"WAIT_TIMEOUT")
                        EndIf
                    Case 0x00000080
                        $aRet = DllCall("kernel32.dll", "bool", "TerminateThread", "handle", $hThread, "int", -1)
                        if $thread_wait_show = 1 then
                            msgbox(0,"a","WAIT_ABANDONED")
                        EndIf
                    Case 0x00000000
                        $Check_return = 1
                        if $thread_wait_show = 1 then
                            MsgBox(0,"s","Wait success")
                        EndIf
                    Case Else
                        if $thread_wait_show = 1 then
                            msgbox(0,"b","Unknow = "& $aRet[0])
                        EndIf
                    EndSwitch
            EndIf
        EndIf
    EndIf
        if $control_wait = 1 Then
            _MemGlobalFree($pExecutableCode)
            $tCodeBuffer = 0
            _WinAPI_CloseHandle($hThread)
        EndIf
                    if $Check_return == 1 and $Check_return <> Null then
                        Return $Recvice_retcode.a
                    EndIf
EndFunc

 

Example_no wait_loop.au3 Example_no wait_no loop.au3 Example_wait_loop_timeout 2 Sec.au3 Example_wait_no loop_no timeout.au3 Thread_call_UDF.au3

Posted

Would you please be so kind and add a short description? So everyone knows what this function/UDF is intended to do and when to use.
This is true for your example scripts as well ;) 

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Posted

Alright after some more testing, I can say that this is pretty cool. Although I would love to see x64 support.

You can see all of the threads contained in the single AutoIt process which is neat:

Spoiler

threads.png

 

Posted (edited)
48 minutes ago, WildByDesign said:

Although I would love to see x64 support.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=y ; or n
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

; ===================== UDF =====================

#include-once
#include <Memory.au3>
#include <WinAPISys.au3>
#include <WinAPIHObj.au3>

Func Thread_Call($opcode, $control_wait = 1, $timeout = 2000, $thread_wait_show = 0)
    Local $pExecutableCode = _MemVirtualAlloc(0, BinaryLen($opcode), $MEM_COMMIT, $PAGE_EXECUTE_READWRITE)
    Local $tCodeBuffer = DllStructCreate("byte a[" & BinaryLen($opcode) & "]", $pExecutableCode)
    DllStructSetData($tCodeBuffer, 1, $opcode)
    Local $Check_return = 0
    Local $Recvice_retcode = DllStructCreate("int a[1];")
    Local $aRet = DllCall("kernel32.dll", "handle", "CreateThread", "ptr", 0, "ulong_ptr", 0, "ptr", $pExecutableCode, "ptr", DllStructGetPtr($Recvice_retcode), "dword", 0, "dword*", 0)
    If @error Then
        MsgBox(0, 1, "CreateThread error:" & @error & @CRLF)
    ElseIf $aRet[0] = 0 Then
        MsgBox(0, 2, "CreateThread error:" & "Null" & @CRLF)
    Else
        Local $hThread = $aRet[0]
        If $control_wait = 1 Then
            $aRet = DllCall("kernel32.dll", "dword", "WaitForSingleObject", "handle", $hThread, "dword", $timeout)
            If @error Then
                MsgBox(0, 3, "WaitForSingleObject error: " & @error & @CRLF)
            Else
                Switch $aRet[0]
                    Case -1, 0xFFFFFFFF
                        $aRet = DllCall("kernel32.dll", "bool", "TerminateThread", "handle", $hThread, "int", -1)
                        If $thread_wait_show = 1 Then
                            MsgBox(0, 4, "WAIT_FAILED")
                        EndIf
                    Case 0x00000102
                        $aRet = DllCall("kernel32.dll", "bool", "TerminateThread", "handle", $hThread, "int", -1)
                        If $thread_wait_show = 1 Then
                            MsgBox(0, 5, "WAIT_TIMEOUT")
                        EndIf
                    Case 0x00000080
                        $aRet = DllCall("kernel32.dll", "bool", "TerminateThread", "handle", $hThread, "int", -1)
                        If $thread_wait_show = 1 Then
                            MsgBox(0, "a", "WAIT_ABANDONED")
                        EndIf
                    Case 0x00000000
                        $Check_return = 1
                        If $thread_wait_show = 1 Then
                            MsgBox(0, "s", "Wait success")
                        EndIf
                    Case Else
                        If $thread_wait_show = 1 Then
                            MsgBox(0, "b", "Unknow = " & $aRet[0])
                        EndIf
                EndSwitch
            EndIf
        EndIf
    EndIf
    If $control_wait = 1 Then
        _MemVirtualFree($pExecutableCode, 0, $MEM_RELEASE)
        $tCodeBuffer = 0
        _WinAPI_CloseHandle($hThread)
    Else
        ; Close thread handle in non-blocking mode to avoid handle leaks
        If $aRet[0] <> 0 Then _WinAPI_CloseHandle($aRet[0])
    EndIf
    If $Check_return == 1 Then
        Return DllStructGetData($Recvice_retcode, 1)
    EndIf
EndFunc   ;==>Thread_Call

; ===================== UDF =====================
; ===================== EXAMPLE =====================

;~ #include <Thread_call_UDF.au3>

Func Msgbox_new($style = 0, $title = "", $message = "", $control_wait = 1, $timeout = 2000, $thread_wait_show = 0)
    Local $MessageAddress = DllCall("Kernel32.dll", "ptr", "GetProcAddress", "ptr", _WinAPI_GetModuleHandle("user32.dll"), "str", "MessageBoxW")
    $MessageAddress = $MessageAddress[0]

    Global $ptr_in_a = DllStructCreate("wchar a[65535];")
    Global $ptr_in_b = DllStructCreate("wchar a[65535];")
    $ptr_in_a.a = $message
    $ptr_in_b.a = $title

    Local $opcode = ""

    If @AutoItX64 Then
        ; --- x64 Machine Code ---
        $opcode = Binary("0x" & _
                "4883EC28" & _                                                       ; sub rsp, 0x28 (allocate 32b shadow space + 8b alignment)
                "31C9" & _                                                           ; xor ecx, ecx (RCX = 0 / hWnd)
                "48BA" & Hex(BinaryMid(Binary(DllStructGetPtr($ptr_in_a)), 1, 8)) & _ ; mov rdx, lpText
                "49B8" & Hex(BinaryMid(Binary(DllStructGetPtr($ptr_in_b)), 1, 8)) & _ ; mov r8, lpCaption
                "41B9" & Hex(BinaryMid(Binary($style), 1, 4)) & _                     ; mov r9d, uType
                "48B8" & Hex(BinaryMid(Binary($MessageAddress), 1, 8)) & _           ; mov rax, MessageBoxW address
                "FFD0" & _                                                           ; call rax
                "4883C428" & _                                                       ; add rsp, 0x28 (restore stack frame)
                "C3")                                                                ; ret
    Else
        ; --- x86 Machine Code (Your Original Snippet) ---
        $opcode = Binary("0x" & _
                "68" & Hex(BinaryMid(Binary($style), 1, 4)) & _                      ; push uType
                "68" & Hex(BinaryMid(Binary(DllStructGetPtr($ptr_in_b)), 1, 4)) & _ ; push lpCaption
                "68" & Hex(BinaryMid(Binary(DllStructGetPtr($ptr_in_a)), 1, 4)) & _ ; push lpText
                "6800000000" & _                                                     ; push 0 (hWnd)
                "B8" & Hex(BinaryMid(Binary($MessageAddress), 1, 4)) & _           ; mov eax, MessageBoxW address
                "FFD0" & _                                                           ; call eax
                "C3")                                                                ; ret
    EndIf

    Local $result = Thread_Call($opcode, $control_wait, $timeout, $thread_wait_show)
    Return $result
EndFunc   ;==>Msgbox_new

; ..your EXAMPLE of any of them 4

For $i = 1 To 10
    Msgbox_new(0, "Title", "Number = " & $i, 0)
    Sleep(1)
Next
Msgbox_new(0, "Title", "Number = 101", 1, -1)

 

Edited by argumentum

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting  image.gif.922e3a93535f431de08b31ee669cc446.gif
autoit_scripter_blue_userbar.png

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
×
×
  • Create New...