rendered paste bodyFunc _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