Что нового

Выполнение API без приостановки скрипта

firex

AutoIT Гуру
Сообщения
943
Репутация
208
Очередная вариация на тему потоков. Простая концепция, все возможности не раскрыты. Присутствует возможность получения результата.

Код:
#Include <WinAPI.au3>
#Include <Memory.au3>

$tData = DllStructCreate( "wchar Title[50]; wchar Text[50]" )
$tData.Title = "Title"
$tData.Text = "Text"

$tThread = _AsmThread( 'user32.dll', 'int', 'MessageBoxW', 65, DllStructGetPtr( $tData, 'Title' ), DllStructGetPtr( $tData, 'Text' ), 0 )
If IsDllStruct( $tThread ) Then
	While Sleep( 1000 )
		If $tThread.Return Then
			ConsoleWrite( $tThread.Return & @CRLF)
			ExitLoop
		EndIf
		ConsoleWrite( "Main thread..." & @CRLF)
	WEnd
EndIf

;sModule - Module name
;sRetType - Return type( 4 BYTE, like dword, ptr32, int ... )
;sFunc - Function name
;ArgN - Argument( 4 BYTE )
; -----
;Return:
;$tRet.Id - InternalThreadId ( ___THREADi )
;$tRet.Thread - hThread
;$tRet.Mem - pAllocatedVirtualMemory
;$tRet.Ptr - Ptr to tRet
;$tRet.Return - Return value
Func _AsmThread( $sModule, $sRetType, $sFunc, $Arg1 = 0, $Arg2 = 0, $Arg3 = 0, $Arg4 = 0, $Arg5 = 0, $Arg6 = 0 )
	Local $Idx, $hModule, $pFunc, $tRet, $pMem, $aRes, _
		$tOpCode, $iOpCode_sz, $vOpCode = "0x", _
		$aArgs[6] = [ $Arg1, $Arg2, $Arg3, $Arg4, $Arg5, $Arg6 ]
	; *
	ReDim $aArgs[@NumParams-2]
	; ---
	$tRet = DllStructCreate( $sRetType & " Return; ptr Ptr; ptr Mem; handle Thread; ulong Id" )
		$tRet.Ptr = DllStructGetPtr( $tRet )

	For $Idx = 0 To @NumParams - 4 Step 1
		$vOpCode &= "68" & _AsmSwap( $aArgs[$Idx] ) ;PUSH Arg
	Next
	Do
		$hModule = _WinAPI_GetModuleHandle( $sModule )
		If Not $hModule Then ExitLoop

		$pFunc =  _WinAPI_GetProcAddress( $hModule, $sFunc )
		If Not $pFunc Then ExitLoop
		; -
		$vOpCode &= _
			"B8" & _AsmSwap( $pFunc ) & _ 		;MOV EAX,pFunc
			"FFD0" & _ 							;CALL EAX
			"A3" & _AsmSwap( $tRet.Ptr ) & _ 	;MOV DWORD PTR[pRet],EAX
			"C3"								;RET

		$vOpCode = Binary( $vOpCode )
		$iOpCode_sz = BinaryLen( $vOpCode )
		; -
		$pMem = _MemVirtualAlloc( 0, $iOpCode_sz, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE )
		If Not $pMem Then ExitLoop

		$tOpCode = DllStructCreate( "byte OpCode[" & $iOpCode_sz & "]", $pMem )
		$tOpCode.OpCode = $vOpCode

		$aRes = DllCall( 'kernel32.dll', 'ptr', 'CreateThread', 'ptr', 0, 'dword_ptr', 0, 'ptr', $pMem, 'ptr', 0, 'dword', 0, 'dword*', 0)
		If @Error Or Not $aRes[0] Then ExitLoop

		; - < Anti-crash region ( save allocated memory for struct's )
		$Idx = 0
		While IsDeclared( "___THREAD" & $Idx )
			$Idx += 1
		WEnd
		Assign( "___THREAD" & $Idx, $tRet, 2 )

		$tRet.Mem = $pMem
		$tRet.Thread = $aRes[0]
		$tRet.Id = $Idx

		Sleep( 10 )
		Return $tRet
	Until True
	; ---
	Return 0
EndFunc

Func _AsmSwap( $vData )
	Return Hex( Binary( $vData ) )
EndFunc
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
А какой интерес запускать самодостаточную MessageBox(), и зачем здесь нужен opcode? Кстати, давно я уже что-то похожее писал.
 
Автор
firex

firex

AutoIT Гуру
Сообщения
943
Репутация
208
Yashied
1. MessageBox я привел в кач-ве примера, а цели у меня были иные, как и в целом их реализация.
2. С опкодом я облегчаю получение результата, хотя перспективы все же иные.
 

Prog

Продвинутый
Сообщения
537
Репутация
65
1. Формат ThreadProc. https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms686736(v=vs.85).aspx
Асм. вставка не чистит стек от аргумента.

2. Не освобождается память выделенная MemVirtualAlloc.

3. Проще и безопаснее написать dll в которой реализовать многопоточность.
 
Автор
firex

firex

AutoIT Гуру
Сообщения
943
Репутация
208
Prog
Если вы присмотритесь, то увидите следующее:
Код:
;Return:
;$tRet.Id - InternalThreadId ( ___THREADi )
;$tRet.Thread - hThread
;$tRet.Mem - pAllocatedVirtualMemory
;$tRet.Ptr - Ptr to tRet
;$tRet.Return - Return value


Асм. вставка не чистит стек от аргумента.
В данном опкоде в этом нет необходимости.

2. Не освобождается память выделенная MemVirtualAlloc
Это концепция, а следовательно если это будет интересно, то подобные операции должен будет производить интересующийся.
1. Отслеживать ( GetThreadExitCode )
2. Чистить ( VirtualFree )

3. Проще и безопаснее написать dll в которой реализовать многопоточность.
Ну вы разогнались... Речь идет о частных вызовах DLL функций в потоке, а не полноценной реализации потоков.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Prog сказал(а):
Проще и безопаснее написать dll в которой реализовать многопоточность.

Я, собственно, так и делаю. В данном контексте больше представляет интерес запуск AutoIt - DllCallback() - процедуры, а не функции из DLL. ASM, VirtualAlloc() и все прочие плюшки в этом примере нафиг не нужны. Достаточно просто создать глобальную или static AutoIt структуру для передачи параметров и отпустить MessageBox() в свободное плавание.
 
Верх