All pastes #717707 Raw Edit

Something

public text v1 · immutable
#717707 ·published 2007-09-27 20:20 UTC
rendered paste body
Func _DllCallBack($sFunction, $sParameters = "", Const $nOptions = 0)
	Local $pSendMessage, $hGlobal, $hUser32, $vStub, $i, $vCriticalSection, $pCallWindowProc
	Local $nParameters, $vParameters, $wParam = -1, $nParameters_struct = -1, $hKernel32
	Local $sStub, $dwStubSize
	If BitAND($_DllCallBack_Debug, $nOptions) Then $sStub = "90909090CC" ; INT3
	If Not $gf_DllCallBack_fMsgRegistred Then Return SetError(5, 0, 0)
	If $sParameters = "" Or $sParameters = Default Then
		$nParameters = 0
	Else
		$vParameters = DllStructCreate($sParameters)
		If @error Then Return SetError(6, 0, 0)
		$nParameters = DllStructGetSize($vParameters) / 4
		If $nParameters <> Int($nParameters) Or @error Then Return SetError(6, 0, 0)
		For $i = 1 To 256
			DllStructGetData($vParameters, $i)
			If @error Then
				$nParameters_struct = $i - 1
				ExitLoop
			EndIf
		Next
		If $nParameters_struct < 0 Then SetError(6, 0, 0)
	EndIf
	For $i = 0 To $gi_DllCallBack_MaxStubs
		If Not $ga_DllCallBack_hGlobals[$i] Then
			$wParam = $i
			ExitLoop
		EndIf
	Next
	If $wParam = -1 Then Return SetError(4, 0, 0)
	If $gh_DllCallBack_hUser32 = 0 Then
		$hUser32 = DllCall("kernel32.dll", "ptr", "LoadLibrary", "str", "user32.dll")
		If @error Then Return SetError(2, 0, 0)
		If $hUser32[0] = 0 Then Return SetError(2, 0, 0)
		$gh_DllCallBack_hUser32 = $hUser32[0]
		$pSendMessage = DllCall("kernel32.dll", "ptr", "GetProcAddress", "ptr", $gh_DllCallBack_hUser32, "str", "SendMessage")
		If @error Then Return SetError(3, 0, 0)
		If $pSendMessage[0] = 0 Then
			If @Unicode Then
				$pSendMessage = DllCall("kernel32.dll", "ptr", "GetProcAddress", "ptr", $gh_DllCallBack_hUser32, "str", "SendMessageW")
				If @error Then Return SetError(3, 0, 0)
			Else
				$pSendMessage = DllCall("kernel32.dll", "ptr", "GetProcAddress", "ptr", $gh_DllCallBack_hUser32, "str", "SendMessageA")
				If @error Then Return SetError(3, 0, 0)
			EndIf
		EndIf
		If $pSendMessage[0] = 0 Then Return SetError(3, 0, 0)
		$gp_DllCallBack_SendMessage = $pSendMessage[0]
		$pCallWindowProc = DllCall("kernel32.dll", "ptr", "GetProcAddress", "ptr", $gh_DllCallBack_hUser32, "str", "CallWindowProc")
		If @error Then Return SetError(3, 0, 0)
		If $pCallWindowProc[0] = 0 Then
			If @Unicode Then
				$pCallWindowProc = DllCall("kernel32.dll", "ptr", "GetProcAddress", "ptr", $gh_DllCallBack_hUser32, "str", "CallWindowProcW")
				If @error Then Return SetError(3, 0, 0)
			Else
				$pCallWindowProc = DllCall("kernel32.dll", "ptr", "GetProcAddress", "ptr", $gh_DllCallBack_hUser32, "str", "CallWindowProcA")
				If @error Then Return SetError(3, 0, 0)
			EndIf
		EndIf
		If $pCallWindowProc[0] = 0 Then Return SetError(3, 0, 0)
		$gp_DllCallBack_CallWindowProc = $pCallWindowProc[0]
	EndIf
	If Not BitAND($_DllCallBack_Sync, $nOptions) Then ; Critical section disabled
		$vCriticalSection = -1
	Else ; Critical section enabled
		If $gp_DllCallBack_EnterCriticalSection = 0 Or $gp_DllCallBack_LeaveCriticalSection = 0 Then
			; we assume kernel32.dll is allways loaded
			$hKernel32 = DllCall("kernel32.dll", "ptr", "GetModuleHandle", "str", "kernel32.dll")
			If @error Then Return SetError(2, 0, 0)
			If $hKernel32[0] = 0 Then Return SetError(2, 0, 0)
			$gp_DllCallBack_EnterCriticalSection = DllCall("kernel32.dll", "ptr", "GetProcAddress", "ptr", $hKernel32[0], "str", "EnterCriticalSection")
			If @error Then Return SetError(3, 0, 0)
			$gp_DllCallBack_EnterCriticalSection = $gp_DllCallBack_EnterCriticalSection[0]
			If $gp_DllCallBack_EnterCriticalSection = 0 Then Return SetError(3, 0, 0)
			$gp_DllCallBack_LeaveCriticalSection = DllCall("kernel32.dll", "ptr", "GetProcAddress", "ptr", $hKernel32[0], "str", "LeaveCriticalSection")
			If @error Then Return SetError(3, 0, 0)
			$gp_DllCallBack_LeaveCriticalSection = $gp_DllCallBack_LeaveCriticalSection[0]
			If $gp_DllCallBack_LeaveCriticalSection = 0 Then Return SetError(3, 0, 0)
		EndIf
		$vCriticalSection = DllStructCreate($gs_DllCallBack_typedef_CriticalSection)
		DllCall("kernel32.dll", "none", "InitializeCriticalSection", "ptr", DllStructGetPtr($vCriticalSection))
		If @error Then Return SetError(7, 0, 0)
	EndIf

	If @error Then Return SetError(7, 0, 0)
	#cs
		Options: Critical section, Breakpoint, stdcall - 2 parameters
		
		$ ==>    > CC               INT3                                     ; Breakpoint (for debugging only)
		$+1      > 68 30859B00      PUSH 9B8530                              ; Push LPCRITICAL_SECTION
		$+6      > B8 0510917C      MOV EAX,ntdll.RtlEnterCriticalSection    ; Set address for EnterCriticalSection
		$+B      > FFD0             CALL EAX                                 ; Call EnterCriticalSection
		$+D      > 8D4424 04        LEA EAX,DWORD PTR SS:[ESP+4]             ; Load Pointer to parameters on stack to EAX
		$+11     > 50               PUSH EAX                                 ; Push lParam - Stack Pointer
		$+12     > 68 00000000      PUSH 0                                   ; Push wParam - internal reference to au3 function
		$+17     > 68 FF7F0000      PUSH 7FFF                                ; Push uiMsg - internal identifier for callback
		$+1C     > 68 26063000      PUSH 300626                              ; Push hWnd - Autoit's Callback window
		$+21     > B8 AEE2D177      MOV EAX,USER32.SendMessageA              ; Set address for SendMessage
		$+26     > FFD0             CALL EAX                                 ; Call Sendmessage
		$+28     > 50               PUSH EAX                                 ; Preserve Return value of Callback Function
		$+29     > 68 30859B00      PUSH 9B8530                              ; Push LPCRITICAL_SECTION
		$+2E     > B8 ED10917C      MOV EAX,ntdll.RtlLeaveCriticalSection    ; Set address for LeaveCriticalSection
		$+33     > FFD0             CALL EAX                                 ; Call LeaveCriticalSection
		$+35     > 58               POP EAX                                  ; Restore Return value of Callback Function
		$+36     > C2 0800          RETN 8                                   ; Adjust stack for stdcall and return
		
		
		Options: Default, stdcall - 2 parameters
		
		$ ==>    > 8D4424 04        LEA EAX,DWORD PTR SS:[ESP+4]             ; Load Pointer to parameters on stack to EAX
		$+4      > 50               PUSH EAX                                 ; Push lParam - Stack Pointer
		$+5      > 68 00000000      PUSH 0                                   ; Push wParam - internal reference to au3 function
		$+A      > 68 FF7F0000      PUSH 7FFF                                ; Push uiMsg - internal identifier for callback
		$+F      > 68 C6041700      PUSH 1704C6                              ; Push hWnd - Autoit's Callback window
		$+14     > B8 AEE2D177      MOV EAX,USER32.SendMessageA              ; Set address for SendMessage
		$+19     > FFD0             CALL EAX                                 ; Call Sendmessage
		$+1B     > C2 0800          RETN 8                                   ; Adjust stack for stdcall and return
		
		
		nOptions: Subclassing, stdcall - 4 parameters
		
		$ ==>    > 8D4424 04        LEA EAX,DWORD PTR SS:[ESP+4]             ; Load Pointer to parameters on stack to EAX
		$+4      > 50               PUSH EAX                                 ; Push lParam - Stack Pointer
		$+5      > 68 00000000      PUSH 0                                   ; Push wParam - internal reference to au3 function
		$+A      > 68 FF7F0000      PUSH 7FFF                                ; Push uiMsg - internal identifier for callback
		$+F      > 68 34063100      PUSH 310634                              ; Push hWnd - Autoit's Callback window
		$+14     > B8 62B7D177      MOV EAX,USER32.SendMessageW              ; Set address for SendMessage
		$+19     > FFD0             CALL EAX                                 ; Call Sendmessage
		$+1B     > 83F8 00          CMP EAX,0                                ; Compare EAX and NULL
		$+1E     > 74 1C            JE SHORT <$+3C>                          ; If equal (EAX == NULL) jump down to $+3C (return)
		$+20     > 8B5424 10        MOV EDX,DWORD PTR SS:[ESP+10]            ; Copy lParam from stack to EDX
		$+24     > 52               PUSH EDX                                 ; Push lParam
		$+25     > 8B5424 10        MOV EDX,DWORD PTR SS:[ESP+10]            ; Copy wParam from stack to EDX
		$+29     > 52               PUSH EDX                                 ; Push wParam
		$+2A     > 8B5424 10        MOV EDX,DWORD PTR SS:[ESP+10]            ; Copy uiMsg from stack to EDX
		$+2E     > 52               PUSH EDX                                 ; Push uiMsg
		$+2F     > 8B5424 10        MOV EDX,DWORD PTR SS:[ESP+10]            ; Copy hWnd from stack to EDX
		$+33     > 52               PUSH EDX                                 ; Push hWnd - Subclassed Window
		$+34     > 50               PUSH EAX                                 ; Push lpPrevWndFunc (Returned by SendMessage/Callback Func)
		$+35     > B8 19C0D177      MOV EAX,USER32.CallWindowProcW           ; Set address for CallWindowProc
		$+3A     > FFD0             CALL EAX                                 ; Call CallWindowProc
		$+3C     > C2 1000          RETN 10                                  ; Adjust stack and return
	#ce
	; Note: EAX ECX EDX can be freely modified
	If BitAND($_DllCallBack_Sync, $nOptions) Then ; Critical section
		$sStub &= "68" & __DllCallBack_Endian(DllStructGetPtr($vCriticalSection))
		$sStub &= "B8" & __DllCallBack_Endian($gp_DllCallBack_EnterCriticalSection)
		$sStub &= "FFD0" ; call EnterCriticalSection
	EndIf
	$sStub &= "8D442404" ; load stack poiner into eax
	$sStub &= "50" ; push eax - lparam
	$sStub &= "68" & __DllCallBack_Endian($wParam, "uint")
	$sStub &= "68" & __DllCallBack_Endian($gi_DllCallBack_uiMsg, "uint")
	$sStub &= "68" & __DllCallBack_Endian($gh_DllCallBack_hWnd, "hwnd")
	$sStub &= "B8" & __DllCallBack_Endian($gp_DllCallBack_SendMessage)
	$sStub &= "FFD0" ; call SendMessage
	If BitAND($_DllCallBack_Sync, $nOptions) Then ; Critical section
		$sStub &= "50" ; push eax - to preserve return value of callback function
		$sStub &= "68" & __DllCallBack_Endian(DllStructGetPtr($vCriticalSection))
		$sStub &= "B8" & __DllCallBack_Endian($gp_DllCallBack_LeaveCriticalSection)
		$sStub &= "FFD0" ; call LeaveCriticalSection
		$sStub &= "58" ; pop eax - Retstore return value
	EndIf
	If BitAND($_DllCallBack_Subclass, $nOptions) Then ; Subclassing
		$sStub &= "83F800"; cmp eax,0
		$sStub &= "74" & "1C"; je 0x1c - if eax == 0 jump down 0x1c opcodes (to return)
		$sStub &= "8B5424" & "10" & "52"; mov edx,dword ptr ss:esp+10; push edx - lparam
		$sStub &= "8B5424" & "10" & "52"; mov edx,dword ptr ss:esp+10; push edx - wparam
		$sStub &= "8B5424" & "10" & "52"; mov edx,dword ptr ss:esp+10; push edx - msg
		$sStub &= "8B5424" & "10" & "52"; mov edx,dword ptr ss:esp+10; push edx - hwnd
		$sStub &= "50"; push eax - lpPrevWndFunc
		$sStub &= "B8" & __DllCallBack_Endian($gp_DllCallBack_CallWindowProc) ; Set eax to CallWindowProc
		$sStub &= "FFD0"; call eax
	EndIf
	If BitAND($_DllCallBack_Cdecl, $nOptions) Then
		$sStub &= "C3" ; return near 'cdecl'
	Else
		$sStub &= "C2" & __DllCallBack_Endian($nParameters * 4, "ushort", 2) ; Return near 'stdcall'
	EndIf
	$dwStubSize = StringLen($sStub) / 2
	$hGlobal = DllCall("kernel32.dll", "ptr", "GlobalAlloc", "uint", 0, "dword", $dwStubSize)
	If @error Then Return SetError(1, 0, 0)
	If $hGlobal[0] = 0 Then Return SetError(1, 0, 0)
	$hGlobal = $hGlobal[0]
	$vStub = DllStructCreate("ubyte[" & $dwStubSize & "]", $hGlobal)
	DllStructSetData($vStub, 1, Binary("0x" & $sStub))
	$gi_DllCallBack_StubCount += 1
	$ga_DllCallBack_hGlobals[$wParam] = $hGlobal
	$ga_DllCallBack_sFunctions[$wParam] = $sFunction
	$ga_DllCallBack_sParameters[$wParam] = $sParameters
	$ga_DllCallBack_nParameters[$wParam] = $nParameters_struct
	$ga_DllCallBack_vCriticalSections[$wParam] = $vCriticalSection
	$ga_DllCallBack_nOptions[$wParam] = $nOptions
	Return $hGlobal
EndFunc   ;==>_DllCallBack