Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include-once
- #include <Memory.au3>
- Global $AUTOITTHREAD = False
- ; *
- #OnAutoItStartRegister "__AT_Init"
- ; #INDEX# =======================================================================================================================
- ; Title .........: AutThread - Concept!
- ; AutoIt Version : >=3.3.8.1
- ; Language ......: Russian
- ; Description ...: Псевдо-потоки в AutoIt!
- ; ===============================================================================================================================
- ; #CURRENT# =====================================================================================================================
- ;_AutThread_Create
- ;_AutThread_Kill
- ;_AutThread_IsAlive
- ;_AutThread_ParentThreadPID
- ;_AutThread_SelfIsThread
- ;_AutThread_ErrorCallbackRegister
- ; ===============================================================================================================================
- ; #INTERNAL_USE_ONLY#============================================================================================================
- ;__AT_Init
- ;__AT_Main
- ;__AT_VarType
- ;__AT_ReinterpretCast
- ;__AT_TagSize
- ;__AT_OpenProcess
- ;__AT_ReadProcessMemory
- ;__AT_WriteProcessMemory
- ;__AT_CloseHandle
- ;__AT_OnExit
- ; ===============================================================================================================================
- ; #FUNCTION# =================================================================================================
- ; Name...........: _AutThread_Create
- ; Description ...: Запускает функцию параллельно работе основного скрипта
- ; Syntax.........: _AutThread_Create( $sFunc [, $iRetSize [, $sVarRet [, $aArgs = 0 [, $sCmdLine = "" ]]]] )
- ; Parameters ....: $sFunc - Имя функции
- ; $iRetSize - Сколько выделить памяти под ответ (в байтах) [ Optional ]
- ; $sVarRet - Имя переменной в которую поместится Return (Global only) [ Optional ]
- ; $aArgs - Массив аргументов которые передадутся функции [ Optional ]
- ; $sCmdLine - CMDLINE [ Optional ]
- ; Return values .: ( ThreadIndex ) Or ( False and set @Error )
- ; Author ........: Firex
- ; Remarks .......:
- ; ============================================================================================================
- Func _AutThread_Create( $sFunc, $iRetSize = 0, $sVarRet = "", $aArgs = 0, $sCmdLine = "" )
- Local $iAutThread, $__aArgs, $Idx, $Jix, $hMemory, $tagAutThread, $tAutThread, $iTmp, $iFunc, $iErr = 0, $iArgs = 0
- ; ---
- $iFunc = StringLen( $sFunc )
- If Not $iFunc Then _
- Return SetError( 1, 0, 0 )
- $tagAutThread = $__tagAutThreadInfo & "char[" & $iFunc & "]; "
- ; ---
- If IsArray( $aArgs ) And UBound( $aArgs ) = $aArgs[0] + 1 Then
- Dim $__aArgs[ $aArgs[0] + 1 ][3]
- For $Idx = 1 To $aArgs[0] Step 1
- $tagAutThread &= $__tagAutThreadBody
- $__aArgs[$Idx][0] = __AT_VarType( VarGetType( $aArgs[$Idx] ) )
- If $aArgs[$Idx] == "" Or IsArray( $aArgs[$Idx] ) Then
- $__aArgs[$Idx][2] = Binary( '0x00' )
- $__aArgs[$Idx][1] = 1
- Else
- $__aArgs[$Idx][2] = StringToBinary( String( $aArgs[$Idx] ) )
- $__aArgs[$Idx][1] = BinaryLen( $__aArgs[$Idx][2] )
- If $__aArgs[$Idx][1] > 16581375 Then _
- $__aArgs[$Idx][1] = 16581375 ;~byte iArg[3]; in $__tagAutThreadBody
- $tagAutThread &= "byte[" & $__aArgs[$Idx][1] & "]; "
- EndIf
- Next
- $iArgs = $aArgs[0]
- EndIf
- ; ---
- $iTmp = __AT_TagSize( $tagAutThread )
- If $iTmp - $__tagATI_Size < $iRetSize Then _
- $iTmp = $iRetSize
- $hMemory = _MemGlobalAlloc( $iTmp, 0x0040 ) ;$GPTR
- If $hMemory <> 0 Then
- $tAutThread = DllStructCreate( $tagAutThread, $hMemory )
- If Not @Error Then
- DllStructSetData( $tAutThread, "iRet", False )
- DllStructSetData( $tAutThread, "iArgs", $iArgs )
- DllStructSetData( $tAutThread, "iFunc", $iFunc )
- DllStructSetData( $tAutThread, "iBuf", $iTmp )
- DllStructSetData( $tAutThread, 5, $sFunc )
- For $Idx = 1 To $iArgs Step 1
- $iTmp = 6 + ( ( $Idx - 1 ) * 3 )
- For $Jix = 0 To 2 Step 1
- DllStructSetData( $tAutThread, $iTmp + $Jix, $__aArgs[$Idx][$Jix] )
- Next
- Next
- Else
- $iErr = 2
- EndIf
- Else
- $iErr = 1
- EndIf
- ; ---
- If Not $iErr Then
- $iAutThread = Run( @ScriptFullPath & ' /AutThreadInfo="' & @AutoItPID & ',' & Int( $hMemory ) & '" ' & $sCmdLine, @ScriptDir )
- If Not $iAutThread Then _
- $iErr = 3
- EndIf
- If Not $iErr Then
- $Idx = $__aAutThreads[0][0] + 1
- ReDim $__aAutThreads[ $Idx + 1 ][4]
- $__aAutThreads[0][0] = $Idx
- $__aAutThreads[$Idx][0] = $hMemory
- $__aAutThreads[$Idx][1] = $tAutThread
- $__aAutThreads[$Idx][2] = $iAutThread
- $__aAutThreads[$Idx][3] = $sVarRet
- $iAutThread = $Idx
- Else
- _MemGlobalFree( $hMemory )
- $iAutThread = 0
- EndIf
- ; ---
- Return SetError( $iErr + 1, 0, $iAutThread )
- EndFunc
- ; #FUNCTION# =================================================================================================
- ; Name...........: _AutThread_Kill
- ; Description ...: Прекращает выполнение параллельной скрипту функции
- ; Syntax.........: _AutThread_Kill( $iAutThread )
- ; Parameters ....: $iAutThread - ThreadIndex
- ; Return values .: ( True ) Or ( False And set @Error )
- ; Author ........: Firex
- ; Remarks .......:
- ; ============================================================================================================
- Func _AutThread_Kill( $iAutThread )
- If $__aAutThreads[0][0] < $iAutThread Then _
- Return SetError( 1, 0, False )
- ; ---
- If $__aAutThreads[$iAutThread][0] Then
- ProcessClose( $__aAutThreads[$iAutThread][2] )
- _MemGlobalFree( $__aAutThreads[$iAutThread][0] )
- $__aAutThreads[$iAutThread][0] = 0
- $__aAutThreads[$iAutThread][1] = 0
- $__aAutThreads[$iAutThread][2] = 0
- $__aAutThreads[$iAutThread][3] = 0
- Else
- Return SetError( 2, 0, False )
- EndIf
- ; ---
- Return True
- EndFunc
- ; #FUNCTION# =================================================================================================
- ; Name...........: _AutThread_IsAlive
- ; Description ...: Проверяет существует ли указанный поток
- ; Syntax.........: _AutThread_IsAlive( $iAutThread )
- ; Parameters ....: $iAutThread - ThreadIndex
- ; Return values .: ( True ) Or ( False Or set @Error )
- ; Author ........: Firex
- ; Remarks .......:
- ; ============================================================================================================
- Func _AutThread_IsAlive( $iAutThread )
- If $__aAutThreads[0][0] < $iAutThread Then _
- Return SetError( 1, 0, False )
- Return $__aAutThreads[$iAutThread][0] <> 0
- EndFunc
- ; #FUNCTION# =================================================================================================
- ; Name...........: _AutThread_ParentThreadPID
- ; Description ...: Возвращает PID родительского процесса ( если таковой имеется ).
- ; Syntax.........: _AutThread_ParentThreadPID()
- ; Parameters ....:
- ; Return values .: ( ParentPID ) Or ( False And set @Error )
- ; Author ........: Firex
- ; Remarks .......:
- ; ============================================================================================================
- Func _AutThread_ParentThreadPID()
- Local $iPid = Eval( "__autThread_ParentScriptPID" )
- If Not $iPid Then _
- $iPid = SetError( 1, 0, 0 )
- Return $iPid
- EndFunc
- ; #FUNCTION# =================================================================================================
- ; Name...........: _AutThread_SelfIsThread
- ; Description ...: Проверяет является ли текущее выполнение потоковым
- ; Syntax.........: _AutThread_SelfIsThread()
- ; Parameters ....:
- ; Return values .: ( True ) Or ( False )
- ; Author ........: Firex
- ; Remarks .......:
- ; ============================================================================================================
- Func _AutThread_SelfIsThread()
- Return Not IsDeclared( "AUTOITTHREAD" )
- EndFunc
- ; #FUNCTION# =================================================================================================
- ; Name...........: _AutThread_ErrorCallbackRegister
- ; Description ...: Регистрирует функцию ( будет вызвана при падении потока ).
- ; Syntax.........: _AutThread_ErrorCallbackRegister( [ $sFunc ] )
- ; Parameters ....: $sFunc - Имя функции
- ; Return values .:
- ; Author ........: Firex
- ; Remarks .......: Функция должна содержать один аргумент, он получит ThreadIndex.
- ; ============================================================================================================
- Func _AutThread_ErrorCallbackRegister( $sFunc = "" )
- $__sAutThread_OnErrCallback = $sFunc
- EndFunc
- ; # INTERNAL USE ONLY
- ; =======================================================
- Func __AT_Init()
- Local $Idx, $hProcess, $_aAutThreadInfo, $tBufThread, $pBufThread, $tAutThread
- Local $iArgs, $iLen, $sType, $sFunc, $aCallArg, $tBuf, $pBuf, $iBuf
- Local $vCallResult, $vCallReport[3]
- Global $__aAutThreads[1][4] = [ [ 0 ] ], $__sAutThread_OnErrCallback = ""
- Global Const $__tagAutThreadBody = "byte vType; byte iArg[3]; ", $__tagATB_Size = __AT_TagSize( $__tagAutThreadBody )
- Global Const $__tagAutThreadInfo = "byte iRet; byte iArgs; ushort iFunc; dword iBuf; ", $__tagATI_Size = __AT_TagSize( $__tagAutThreadInfo )
- OnAutoItExitRegister( "__AT_OnExit" )
- AdlibRegister( "__AT_Main", 450 )
- ; ---
- $_aAutThreadInfo = StringRegExp( $CmdLineRaw, '^.*/(?i)AutThreadInfo="(\d+),(\d+)".*$', 3 )
- If UBound( $_aAutThreadInfo ) <> 2 Then _
- Return
- $_aAutThreadInfo[0] = Int( $_aAutThreadInfo[0] )
- $_aAutThreadInfo[1] = Ptr( $_aAutThreadInfo[1] )
- ; ---
- Global Const $__autThread_ParentScriptPID = $_aAutThreadInfo[0]
- ; ---
- $hProcess = __AT_OpenProcess( $_aAutThreadInfo[0] )
- If $hProcess Then
- $tAutThread = DllStructCreate( $__tagAutThreadInfo )
- __AT_ReadProcessMemory( $hProcess, $_aAutThreadInfo[1], $tAutThread )
- If Not @Error Then
- $iArgs = DllStructGetData( $tAutThread, "iArgs" )
- $iLen = DllStructGetData( $tAutThread, "iFunc" )
- $iBuf = DllStructGetData( $tAutThread, "iBuf" )
- If $iBuf - $iLen > 0 And $iArgs Then _
- Dim $aCallArg[ $iArgs + 1 ] = [ "CallArgArray" ]
- $tBufThread = DllStructCreate( "char[" & $iLen & "]; byte[" & $iBuf - $iLen & "]; " )
- $pBufThread = $_aAutThreadInfo[1] + DllStructGetSize( $tAutThread )
- __AT_ReadProcessMemory( $hProcess, $pBufThread, $tBufThread )
- If Not @Error Then
- $sFunc = DllStructGetData( $tBufThread, 1 )
- $pBuf = DllStructGetPtr( $tBufThread ) + $iLen
- ; ~~~
- For $Idx = 1 To $iArgs Step 1
- $tBuf = DllStructCreate( $__tagAutThreadBody, $pBuf )
- $sType = DllStructGetData( $tBuf, "vType" )
- $iLen = Int( DllStructGetData( $tBuf, "iArg" ) )
- ; *
- $pBuf += $__tagATB_Size
- $tBuf = DllStructCreate( "byte[" & $iLen & "]", $pBuf )
- $aCallArg[$Idx] = BinaryToString( DllStructGetData( $tBuf, 1 ) )
- __AT_ReinterpretCast( $sType, $aCallArg[$Idx] )
- $pBuf += $iLen
- Next
- Dim $tBufThread = "", $tBuf = "" ;Free memory
- ; ---
- $vCallResult = Call( $sFunc, $aCallArg )
- $vCallReport[0] = @Error
- $vCallReport[1] = @Extended
- $vCallReport[2] = __AT_VarType( VarGetType( $vCallResult ), 1 )
- DllStructSetData( $tAutThread, 1, $vCallReport[2] )
- DllStructSetData( $tAutThread, 2, $vCallReport[0] )
- DllStructSetData( $tAutThread, 3, $vCallReport[1] )
- ; ---
- $vCallResult = StringToBinary( $vCallResult )
- $iLen = BinaryLen( $vCallResult )
- If $iLen > $iBuf Then _
- $iLen = $iBuf
- DllStructSetData( $tAutThread, 4, $iLen )
- $tBuf = DllStructCreate( "byte[" & $iLen & "]; " )
- DllStructSetData( $tBuf, 1, $vCallResult )
- __AT_WriteProcessMemory( $hProcess, $pBufThread, $tBuf )
- __AT_WriteProcessMemory( $hProcess, $_aAutThreadInfo[1], $tAutThread )
- __AT_CloseHandle( $hProcess )
- ; *
- Exit 148 ;Thread success exit!
- EndIf
- EndIf
- EndIf
- ; ---
- Exit ( 148 - @Error ) ;Error
- EndFunc
- Func __AT_Main()
- Local $Idx, $Jix, $iRetType, $iPid
- ; ---
- For $Idx = 1 To $__aAutThreads[0][0] Step 1
- If $__aAutThreads[$Idx][0] Then
- $iRetType = DllStructGetData( $__aAutThreads[$Idx][1], 1 )
- If $iRetType Then
- Local $tRet, $iErr, $iExt, $iBuf, $vRet
- ; ~
- $iErr = DllStructGetData( $__aAutThreads[$Idx][1], 2 )
- $iExt = DllStructGetData( $__aAutThreads[$Idx][1], 3 )
- $iBuf = DllStructGetData( $__aAutThreads[$Idx][1], 4 )
- If $iBuf Then
- $tRet = DllStructCreate( "byte[" & $iBuf & "]; ", $__aAutThreads[$Idx][0] + $__tagATI_Size )
- $vRet = BinaryToString( DllStructGetData( $tRet, 1 ) )
- __AT_ReinterpretCast( $iRetType, $vRet )
- Else
- $vRet = ""
- EndIf
- ; ---
- If $__aAutThreads[$Idx][3] Then
- Assign( $__aAutThreads[$Idx][3], $vRet, 2 )
- Assign( $__aAutThreads[$Idx][3] & "_err", $iErr, 2 )
- Assign( $__aAutThreads[$Idx][3] & "_ext", $iExt, 2 )
- EndIf
- ElseIf Not ProcessExists( $__aAutThreads[$Idx][2] ) Then
- Call( $__sAutThread_OnErrCallback, $Idx )
- Else
- ContinueLoop
- EndIf
- ; ---
- _AutThread_Kill( $Idx )
- EndIf
- Next
- ; ---
- $iPid = _AutThread_ParentThreadPID()
- If $iPid And Not ProcessExists( $iPid ) Then _
- Exit 149
- EndFunc
- Func __AT_VarType( $vType, $iRet = 1 )
- Local $aTypes[10][2] = [ [ 9, 1 ], [ 10, "Array" ], [ 11, "Int32" ], [ 12, "Int64" ], [ 13, "Binary" ], _
- [ 14, "Bool" ], [ 15, "Ptr" ], [ 16, "Double" ], [ 17, "String" ], [ 18, "Keyword" ] ], $Idx, $Jix, $vRet = 0
- ; ---
- For $Idx = 1 To $aTypes[0][0] Step 1
- For $Jix = 0 To $aTypes[0][1] Step 1
- If $vType = $aTypes[$Idx][$Jix] Then
- $vRet = $aTypes[$Idx][($Jix-1)*-1]
- If $Jix = $iRet - 1 Then _
- $vRet = $vType
- ExitLoop 2
- EndIf
- Next
- Next
- ; ---
- Return $vRet
- EndFunc
- Func __AT_ReinterpretCast( $sType, ByRef $vVar )
- Switch __AT_VarType( $sType, 2 )
- Case "Array"
- $vVar = ""
- Case "Int32", "Int64"
- $vVar = Int( $vVar )
- Case "Binary"
- If StringLeft( $vVar, 2 ) <> "0x" Then _
- $vVar = "0x" & String( $vVar )
- $vVar = Binary( $vVar )
- Case "Bool"
- Switch $vVar
- Case "True"
- $vVar = True
- Case "False"
- $vVar = False
- Case Else
- $vVar = ( Number( $vVar ) >= 1 )
- EndSwitch
- Case "Ptr"
- $vVar = Ptr( Int( $vVar ) )
- Case "Double"
- $vVar = Round( $vVar, 16 )
- Case "String"
- $vVar = String( $vVar )
- Case "Keyword"
- $vVar = Default
- Case Else
- Return SetError( 1 )
- EndSwitch
- EndFunc
- Func __AT_TagSize( $sTagStruct )
- ;Local $tStruct = DllStructCreate( $sTagStruct )
- ; ---
- ;If @Error Then _
- ; Return SetError( @Error, 0, 0 )
- ; ---
- ;Return DllStructGetSize( $tStruct )
- Local $aStruct, $iSize, $iTypeSize, $Idx
- ; ---
- $aStruct = StringRegExp( $sTagStruct, '\040*([\w\*]+)[\s\w]*\[?((?<=\[)\d*|)', 3 )
- For $Idx = 0 To UBound( $aStruct ) - 1 Step 2
- Switch StringLower( $aStruct[$Idx] )
- Case "byte", "char", "boolean"
- $iTypeSize = 1
- Case "wchar", "short", "ushort", "word"
- $iTypeSize = 2
- Case "int", "long", "bool", "uint", "ulong", "dword", "hwnd", "handle", "float"
- $iTypeSize = 4
- Case "int64", "uint64", "double"
- $iTypeSize = 8
- Case "ptr", "int*", "long*", "uint*", "ulong*", "dword*"
- If @AutoItX64 Then
- $iTypeSize = 8
- Else
- $iTypeSize = 4
- EndIf
- Case Else
- $iTypeSize = 0
- EndSwitch
- If $aStruct[$Idx+1] = "" Then _
- $aStruct[$Idx+1] = 1
- $iSize += $iTypeSize * $aStruct[$Idx+1]
- Next
- ; ---
- Return $iSize
- EndFunc
- Func __AT_OpenProcess( $iProcessID )
- Local $aResult = DllCall( "kernel32.dll", "handle", "OpenProcess", "dword", 0x1F0FFF, "bool", 0, "dword", $iProcessID )
- If @error Or Not $aResult[0] Then Return SetError(@error+1, @extended, 0)
- Return $aResult[0]
- EndFunc ;==>_WinAPI_OpenProcess
- Func __AT_ReadProcessMemory( $hProcess, $pBaseAddress, $tBuffer )
- Local $aResult = DllCall("kernel32.dll", "bool", "ReadProcessMemory", "handle", $hProcess, _
- "ptr", $pBaseAddress, "ptr", DllStructGetPtr( $tBuffer ), "ulong_ptr", DllStructGetSize( $tBuffer ), "ulong_ptr*", 0)
- If @error Then Return SetError(@error, @extended, False)
- Return $aResult[0]
- EndFunc ;==>_WinAPI_ReadProcessMemory
- Func __AT_WriteProcessMemory( $hProcess, $pBaseAddress, $tBuffer )
- Local $aResult = DllCall("kernel32.dll", "bool", "WriteProcessMemory", "handle", $hProcess, "ptr", $pBaseAddress, "ptr", _
- DllStructGetPtr( $tBuffer ), "ulong_ptr", DllStructGetSize( $tBuffer ), "ulong_ptr*", 0 )
- If @error Then Return SetError(@error, @extended, False)
- Return $aResult[0]
- EndFunc ;==>_WinAPI_WriteProcessMemory
- Func __AT_CloseHandle( $hObject )
- Local $aResult = DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hObject)
- If @error Then Return SetError(@error, @extended, False)
- Return $aResult[0]
- EndFunc ;==>_WinAPI_CloseHandle
- Func __AT_OnExit()
- For $Idx = 1 To $__aAutThreads[0][0] Step 1
- _AutThread_Kill( $Idx )
- Next
- EndFunc
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement