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