NSIS/Contrib/System/Source/Call.S
anders_k f69251d87e (C) 2021
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@7245 212acab6-be3b-0410-9dea-997c60f758d6
2021-01-01 20:27:52 +00:00

1033 lines
25 KiB
ArmAsm

;# Copyright (c) 2008 Thomas Gaugler <thomas@dadie.net>
;# Copyright (c) 2008-2021 NSIS Contributors
;#
;# Permission is hereby granted, free of charge, to any person
;# obtaining a copy of this software and associated documentation
;# files (the "Software"), to deal in the Software without
;# restriction, including without limitation the rights to use,
;# copy, modify, merge, publish, distribute, sublicense, and/or sell
;# copies of the Software, and to permit persons to whom the
;# Software is furnished to do so, subject to the following
;# conditions:
;#
;# The above copyright notice and this permission notice shall be
;# included in all copies or substantial portions of the Software.
;#
;# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
;# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
;# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
;# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
;# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
;# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
;# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
;# OTHER DEALINGS IN THE SOFTWARE.
;#
;#
;# Implementation of the functions CallProc, RealCallBack and
;# CallBack of the System plugin in pure x86 assembly.
;#
;# This is a hybrid assembly source file supporting both the
;# MASM as well as the GNU assembler in one file.
;#
;#
;# MASM:
;# ml.exe /c /nologo /Fo"call.obj" /W3 /Zi /errorReport:prompt /Ta"call.S"
;#
;# For enabling debug support use:
;# ml.exe /c /nologo /D"SYSTEM_LOG_DEBUG" /Fo"call.obj" /W3 /Zi /errorReport:prompt /Ta"call.S"
;#
;# GNU toolchain:
;# gcc -x assembler-with-cpp -s call.S -c
;#
;# For enabling debug support use:
;# gcc -x assembler-with-cpp -DSYSTEM_LOG_DEBUG -s call.S -c
;#
;#
; .if 0
;# MASM specific block
.386
.model flat
OPTION casemap:none
;# SYSCALL is identical to the C calling convention,
;# but does not add an underscore prefix to symbols.
OPTION language:syscall
SECTION_DATA equ .data
SECTION_CODE equ .code
DATA_SUFFIX equ
ASCII equ DB
TEMP_LABEL equ @@
TEMP_LABEL_AHEAD equ @f
TEMP_LABEL_BACK equ @b
MACRO_DECL equ
FUNC_DECL MACRO name
name PROC
ENDM
FUNC_END MACRO name
name ENDP
ENDM
;# end of MASM specific block
IF 0
; .else
;# GNU toolchain specific block
.intel_syntax noprefix
.set __GNU__,1
#ifdef SYSTEM_LOG_DEBUG
;# Disable further proprocessing of SYSTEM_LOG_DEBUG
;# and hand it over to the GNU assembler
#undef SYSTEM_LOG_DEBUG
.set SYSTEM_LOG_DEBUG,1
#endif
#ifdef _UNICODE
#undef _UNICODE
.set _UNICODE,1
#endif
#define IFDEF .ifdef
#define ELSE .else
#define ENDIF .endif
#define EXTERN .extern
#define SECTION_DATA .data
#define SECTION_CODE .text
#define DATA_SUFFIX :
#define BYTE .byte
#define DWORD .int
#define WORD .word
#define ASCII .ascii
#define MACRO_DECL .macro
#define MACRO
#define ENDM .endm
#define TEMP_LABEL 1
#define TEMP_LABEL_AHEAD 1f
#define TEMP_LABEL_BACK 1b
.macro FUNC_DECL name
.global \name
.func \name
\name:
.endm
.macro FUNC_END name
.endfunc
.endm
;# /*
;# http://gcc.gnu.org/ml/gcc/2006-11/msg00081.html
;# _alloca_probe <=> _chkstk <=> _alloca (in libgcc)
;# */
#define __alloca_probe __alloca
#define END .end
;# end of GNU toolchain specific block
ENDIF
IFDEF SYSTEM_LOG_DEBUG
EXTERN _WriteToLog : PROC
EXTERN _syslogbuf : DWORD
ENDIF
EXTERN __alloca_probe : PROC
EXTERN __imp__GlobalFree@4 : PROC
IFDEF _UNICODE
EXTERN __imp__wsprintfW : PROC
ELSE
EXTERN __imp__wsprintfA : PROC
ENDIF
EXTERN _GlobalCopy : PROC
EXTERN _LastStackPlace : DWORD
EXTERN _LastStackReal : DWORD
EXTERN _LastProc : DWORD
EXTERN _CallbackIndex : DWORD
EXTERN _retexpr : DWORD
EXTERN _retaddr : PTR
EXTERN _GetNewStackSize : PROC
EXTERN _GetGenStackOption : PROC
EXTERN _GetCDeclOption : PROC
EXTERN _GetProcOffset : PROC
EXTERN _GetCloneOffset : PROC
EXTERN _GetProcNameOffset : PROC
EXTERN _GetArgsSizeOffset : PROC
EXTERN _GetParamCount : PROC
EXTERN _GetParamsOffset : PROC
EXTERN _GetSizeOfProcParam : PROC
EXTERN _GetSizeOffsetParam : PROC
EXTERN _GetValueOffsetParam : PROC
EXTERN _Get_valueOffsetParam : PROC
EXTERN _SetCloneOption : PROC
EXTERN _SetCallProcResultValues@12 : PROC
EXTERN _SetProcResultCallback : PROC
SECTION_DATA
;# Low double word of result
_z1 DATA_SUFFIX DWORD 0
;# High double word of result
_z2 DATA_SUFFIX DWORD 0
IFDEF SYSTEM_LOG_DEBUG
IFDEF _UNICODE
LogStack DATA_SUFFIX
BYTE '%', 0, 's', 0, ' ', 0, ' ', 0, 'E', 0, 'S', 0, 'P', 0, ' ', 0
BYTE ' ', 0, '0', 0, 'x', 0, '%', 0, '0', 0, '8', 0, 'X', 0, ' ', 0
BYTE 'S', 0, 't', 0, 'a', 0, 'c', 0, 'k', 0, ' ', 0, '=', 0, ' ', 0
BYTE 'x', 0, '%', 0, '0', 0, '8', 0, 'X', 0, ' ', 0, ' ', 0, 'R', 0
BYTE 'a', 0, 'l', 0, ' ', 0, '=', 0, ' ', 0, '0', 0, 'x', 0, '%', 0
BYTE '8', 0, 'X', 0
WORD 0
LogCall DATA_SUFFIX WORD 9,9
BYTE 'C', 0, 'a', 0, 'l', 0, 'l', 0, ':', 0
WORD 10,0
LogBeforeCall DATA_SUFFIX WORD 9,9,9
BYTE 'B', 0, 'e', 0, 'f', 0, 'o', 0, 'r', 0, 'e', 0, ' ', 0, 'c', 0
BYTE 'l', 0, 'l', 0, ' ', 0, ' ', 0, ' ', 0, ' ', 0, ' ', 0, ' ', 0
BYTE ' ', 0
WORD 0
LogNearCall DATA_SUFFIX WORD 10,9,9,9
BYTE 'N', 0, 'e', 0, 'a', 0, 'r', 0, ' ', 0, 'c', 0, 'a', 0, 'l', 0
BYTE ' ', 0, ' ', 0, ' ', 0, ' ', 0, ' ', 0, ' ', 0, ' ', 0, ' ', 0
BYTE ' ', 0
WORD 0
LogBackFrom DATA_SUFFIX WORD 9
BYTE 'B', 0, 'a', 0, 'c', 0, 'k', 0, ' ', 0, 'f', 0, 'r', 0, 'o', 0
BYTE ' ', 0
WORD 0
LogAfterCall DATA_SUFFIX WORD 10,9,9,9
BYTE 'A', 0, 'f', 0, 't', 0, 'e', 0, 'r', 0, ' ', 0, 'c', 0, 'a', 0
BYTE 'l', 0, ' ', 0, ' ', 0, ' ', 0, ' ', 0, ' ', 0, ' ', 0, ' ', 0
BYTE ' ', 0
WORD 0
LogReturnAfter DATA_SUFFIX WORD 10,9,9,9
BYTE 'R', 0, 'e', 0, 't', 0, 'u', 0, 'r', 0, 'n', 0, ' ', 0, ' ', 0
BYTE ' ', 0, ' ', 0, ' ', 0, ' ', 0, ' ', 0, ' ', 0, ' ', 0, ' ', 0
BYTE ' ', 0, ' ', 0, ' ', 0, '0', 0, 'x', 0, '%', 0, '0', 0, '8', 0
BYTE ' ', 0, ' ', 0, ' ', 0, ' ', 0, '0', 0, 'x', 0, '%', 0, '0', 0
BYTE 'X', 0
WORD 0
LogCalled DATA_SUFFIX
BYTE 'C', 0, 'a', 0, 'l', 0, 'l', 0, 'e', 0, 'd', 0, ' ', 0, 'c', 0
BYTE 'l', 0, 'l', 0, 'b', 0, 'a', 0, 'c', 0, 'k', 0, ' ', 0, 'f', 0
BYTE 'o', 0, 'm', 0, ' ', 0
WORD 0
LogShortAfter DATA_SUFFIX WORD 10,9,9,9
BYTE 'S', 0, 'h', 0, 'o', 0, 'r', 0, 't', 0, '-', 0, 'A', 0, 'f', 0
BYTE 'e', 0, 'r', 0, ' ', 0, 'c', 0, 'a', 0, 'l', 0, 'l', 0, ' ', 0
BYTE ' ', 0
WORD 0
LogReturn DATA_SUFFIX WORD 9,9
BYTE 'R', 0, 'e', 0, 't', 0, 'u', 0, 'r', 0, 'n', 0, ' ', 0, 'f', 0
BYTE 'o', 0, 'm', 0, ' ', 0, 'c', 0, 'a', 0, 'l', 0, 'l', 0, 'b', 0
BYTE 'c', 0, 'k', 0, ':', 0
WORD 10,0
LogBefore DATA_SUFFIX WORD 9,9,9
BYTE 'B', 0, 'e', 0, 'f', 0, 'o', 0, 'r', 0, 'e', 0, ' ', 0, 'c', 0
BYTE 'l', 0, 'l', 0, '-', 0, 'b', 0, 'a', 0, 'c', 0, 'k', 0, ' ', 0
BYTE ' ', 0
WORD 0
LogShortBefore DATA_SUFFIX WORD 10,9,9,9
BYTE 'S', 0, 'h', 0, '-', 0, 'B', 0, 'e', 0, 'f', 0, 'o', 0, 'r', 0
BYTE ' ', 0, 'c', 0, 'a', 0, 'l', 0, 'l', 0, '-', 0, 'b', 0, 'a', 0
BYTE 'k', 0
WORD 0
LogLF DATA_SUFFIX WORD 10,0
ELSE
LogStack DATA_SUFFIX ASCII "%s ESP = 0x%08X Stack = 0x%08X Real = 0x%08X"
BYTE 0
LogCall DATA_SUFFIX BYTE 9,9
ASCII "Call:"
BYTE 10,0
LogBeforeCall DATA_SUFFIX BYTE 9,9,9
ASCII "Before call "
BYTE 0
LogNearCall DATA_SUFFIX BYTE 10,9,9,9
ASCII "Near call "
BYTE 0
LogBackFrom DATA_SUFFIX BYTE 9
ASCII "Back from "
BYTE 0
LogAfterCall DATA_SUFFIX BYTE 10,9,9,9
ASCII "After call "
BYTE 0
LogReturnAfter DATA_SUFFIX BYTE 10,9,9,9
ASCII "Return 0x%08X 0x%08X"
BYTE 0
LogCalled DATA_SUFFIX ASCII "Called callback from "
BYTE 0
LogShortAfter DATA_SUFFIX BYTE 10,9,9,9
ASCII "Short-After call "
BYTE 0
LogReturn DATA_SUFFIX BYTE 9,9
ASCII "Return from callback:"
BYTE 10,0
LogBefore DATA_SUFFIX BYTE 9,9,9
ASCII "Before call-back "
BYTE 0
LogShortBefore DATA_SUFFIX BYTE 10,9,9,9
ASCII "Sh-Before call-back"
BYTE 0
LogLF DATA_SUFFIX BYTE 10,0
ENDIF
ENDIF
SECTION_CODE
IFDEF SYSTEM_LOG_DEBUG
;# Sets edi to address of the end of the syslog buffer (terminating zero)
MACRO_DECL SYSTEM_LOG_INIT MACRO
mov edi,offset _syslogbuf
TEMP_LABEL:
;# End loop if terminating zero of buffer was found otherwise move
;# to next character and check again
cmp byte ptr [edi],0
je TEMP_LABEL_AHEAD
inc edi
jmp TEMP_LABEL_BACK
TEMP_LABEL:
ENDM
;# Appends log information and advances edi accordingly.
;#
;# edi must point to the address of the log buffer where
;# the log information should be appended.
;#
;# eax returns number of bytes appended to log buffer
MACRO_DECL SYSTEM_LOG_ADD MACRO arg1,arg2
;# Format string
IFDEF __GNU__
push \arg1 \arg2
ELSE
push arg1 arg2
ENDIF
;# Log buffer
push edi
IFDEF _UNICODE
call dword ptr [__imp__wsprintfW]
ELSE
call dword ptr [__imp__wsprintfA]
ENDIF
;# If wsprintf succeeds then advance edi by number of bytes
;# written to buffer
cmp eax,0
jl TEMP_LABEL_AHEAD
add edi,eax
TEMP_LABEL:
add esp,8
ENDM
;# Writes stackpointer and additional information to log
;# and advances edi accordingly (terminating zero of buffer).
;#
;# edi must point to the address of the log buffer where
;# the log information should be appended.
;#
;# eax returns number of bytes appended to log buffer
MACRO_DECL SYSTEM_EVENT MACRO arg1,arg2
;# Save current stack pointer in eax
mov eax,esp
;# Stackpointer information
push dword ptr [_LastStackReal]
push dword ptr [_LastStackPlace]
push eax
;# Event information
IFDEF __GNU__
push \arg1 \arg2
ELSE
push arg1 arg2
ENDIF
SYSTEM_LOG_ADD offset LogStack
add esp,16
ENDM
;# Flush log information and reset log buffer.
;#
;# edi must point to the address of the log buffer where
;# the log information should be appended.
;#
;# eax returns number of bytes appended to log buffer
MACRO_DECL SYSTEM_LOG_POST MACRO
;# Append line feed to log information
SYSTEM_LOG_ADD offset LogLF
;# Flush log information
push offset _syslogbuf
call _WriteToLog
add esp,4
;# Reset log buffer
mov byte ptr [_syslogbuf],0
ENDM
ENDIF
FUNC_DECL _CallProc
;# Save stack
push ebp
mov ebp,esp
;# Stack space for local variables
;# ebp-4 = Size of ProcParameter structure
sub esp,4
;# Save all usable registers to free our hands
push ebx
push edi
push esi
IFDEF SYSTEM_LOG_DEBUG
SYSTEM_LOG_INIT
SYSTEM_LOG_ADD offset LogCall
SYSTEM_EVENT offset LogBeforeCall
ENDIF
;# CallbackIndex != 0
cmp dword ptr [_CallbackIndex],0
je stack_expand_done
;# proc->Options without POPT_GENSTACK
push dword ptr [ebp+8]
call _GetGenStackOption
cmp eax,0
pop eax
jne stack_expand_done
;# Save previous stack location
push ebp
mov dword ptr [_LastStackReal],esp
cmp dword ptr [_LastStackPlace],0
jne stack_adjust
;# Create new stack
call _GetNewStackSize
call __alloca_probe
mov dword ptr [_LastStackPlace],esp
jmp stack_expand_done
stack_adjust:
;# Move stack pointer
mov esp,dword ptr [_LastStackPlace]
stack_expand_done:
;# Push arguments to stack
;#
;# Get number of parameters
push dword ptr [ebp+8]
call _GetParamCount
add esp,4
;# Skip if there are no parameters
cmp eax,0
jle params_loop_done
;# Save number of parameters on stack
push eax
;# Get offset for element Params of SystemProc structure
call _GetParamsOffset
add eax,dword ptr [ebp+8]
push eax
call _GetSizeOfProcParam
mov dword ptr [ebp-4],eax
;# Calculate offset for the last Parameter
pop ebx
pop ecx
mul ecx
add ebx,eax
;# Save offset of last parameter on stack
push ebx
;# Save number of parameters on stack
push ecx
;# Size offset of parameter
call _GetSizeOffsetParam
push eax
;# Value offset of parameter
call _GetValueOffsetParam
push eax
;# _value offset of parameter
call _Get_valueOffsetParam
push eax
;# ebx = _value offset
pop ebx
;# edx = Value offset
pop edx
;# esi = Size offset
pop esi
;# ecx = n-th parameter
pop ecx
;# eax = offset of current worked on parameter
pop eax
params_loop:
;# Check Size of param
cmp dword ptr [eax+esi],2
jne params_default
;# Long type 'L'/'l' (64-bit)
push dword ptr [eax+ebx]
params_default:
;# Default for all types
push dword ptr [eax+edx]
;# Continue with next parameter
sub eax,dword ptr[ebp-4]
loop params_loop
params_loop_done:
;# Save proc
;# proc->Clone
call _GetCloneOffset
mov ecx,dword ptr [ebp+8]
add eax,ecx
;# proc->Clone = LastProc
mov edx,dword ptr [_LastProc]
mov dword ptr [eax],edx
;# LastProc = proc
mov dword ptr [_LastProc],ecx
IFDEF SYSTEM_LOG_DEBUG
SYSTEM_EVENT offset LogNearCall
SYSTEM_LOG_POST
ENDIF
;# Get address of procedure
call _GetProcOffset
mov ecx,dword ptr [ebp+8]
mov ecx,dword ptr [eax+ecx]
;# /*
;# workaround for bug #1535007
;# http://sf.net/tracker/index.php?func=detail&aid=1535007&group_id=22049&atid=373085
;#
;# If a function returns short and doesn't clear eax in the process,
;# it will only set 2 bytes of eax, and the other 2 bytes remain
;# "random". In this case, they'll be part of the proc pointer.
;#
;# To avoid this, eax is cleared before the function is called. This
;# makes sure the value eax will contain is only what the function
;# actually sets.
;# */
xor eax,eax
;# Call
call ecx
;# Save return
mov dword ptr [_z1],eax
mov dword ptr [_z2],edx
IFDEF SYSTEM_LOG_DEBUG
SYSTEM_LOG_INIT
SYSTEM_LOG_ADD offset LogBackFrom
;# LastProc->ProcName
call _GetProcNameOffset
mov ecx,dword ptr [_LastProc]
add eax,ecx
SYSTEM_LOG_ADD eax
SYSTEM_EVENT offset LogShortAfter
ENDIF
cmp dword ptr [_CallbackIndex],0
je stack_restore_done
mov eax,dword ptr [_LastProc]
push eax
call _GetGenStackOption
cmp eax,0
pop eax
jne stack_restore_done
;# Restore real stack location
mov dword ptr [_LastStackPlace],esp
mov esp,dword ptr [_LastStackReal]
pop ebp
stack_restore_done:
;# Restore proc
mov edx,dword ptr [_LastProc]
mov dword ptr [ebp+8],edx
;# proc->Clone
call _GetCloneOffset
add eax,edx
;# LastProc = proc->Clone
mov eax,dword ptr [eax]
mov dword ptr [_LastProc],eax
;# In case of cdecl convention we should clear stack
;# if ((proc->Options & POPT_CDECL) != 0)
push edx
call _GetCDeclOption
cmp eax,0
pop edx
je stack_clear_done
;# Get number of parameters
push edx
call _GetParamCount
add esp,4
;# Skip if there are no parameters
cmp eax,0
jle stack_clear_done
;# Save number of parameters on stack
push eax
;# Get offset for element Params of SystemProc structure
call _GetParamsOffset
add eax,dword ptr [ebp+8]
;# Calculate offset for the Parameter 1
add eax,dword ptr [ebp-4]
;# Save offset for the Parameter 1 on stack
push eax
;# Size offset of parameter
call _GetSizeOffsetParam
push eax
;# if ((CallbackIndex > 0) && ((proc->Options & POPT_GENSTACK) == 0))
cmp dword ptr [_CallbackIndex],0
jle real_stack_cleanup
push dword ptr [ebp+8]
call _GetGenStackOption
cmp eax,0
pop eax
jne real_stack_cleanup
;# In case of temporary stack
;#
;# esi = Size offset
pop esi
;# eax = offset of current worked on parameter
pop eax
;# ecx = n-th parameter
pop ecx
temp_stack_loop:
;# LastStackPlace += 4* Size of current parameter;
mov edx,dword ptr [eax+esi]
mov ebx,dword ptr [_LastStackPlace]
lea edx,[ebx+edx*4]
mov dword ptr [_LastStackPlace],edx
;# Go to next
add eax,dword ptr [ebp-4]
loop temp_stack_loop
;# End of stack cleanup
jmp stack_clear_done
real_stack_cleanup:
;# In case of real stack
;#
;# esi = Size offset
pop esi
;# eax = offset of current worked on parameter
pop eax
;# ecx = Number of parameters
pop ecx
real_stack_loop:
;# Size of current parameter == 2
cmp dword ptr [eax+esi],2
jne real_stack_default
;# Long type
pop edx
real_stack_default:
;# Default
pop edx
add eax,dword ptr [ebp-4]
loop real_stack_loop
stack_clear_done:
;# In case of cleared call-proc-queue -> clear allocated stack place (more flexible)
cmp dword ptr [_LastProc],0
jne stack_cleanup_done
mov dword ptr [_LastStackPlace],0
stack_cleanup_done:
;# Save return
push dword ptr [_z2]
push dword ptr [_z1]
push dword ptr [ebp+8]
call _SetCallProcResultValues@12
IFDEF SYSTEM_LOG_DEBUG
SYSTEM_EVENT offset LogAfterCall
push dword ptr [_z2]
push dword ptr [_z1]
SYSTEM_LOG_ADD offset LogReturnAfter
add esp,8
SYSTEM_LOG_POST
ENDIF
;# Return
mov eax,dword ptr [ebp+8]
;# Restore registers
pop esi
pop edi
pop ebx
;# Restore stack pointer
mov esp,ebp
pop ebp
ret
FUNC_END _CallProc
FUNC_DECL _RealCallBack
;# Save stack
push ebp
mov ebp,esp
;# Stack space for local variables
;# ebp-16 = Size of ProcParameter structure
;# ebp-12 = ArgsSize
;# ebp-8 = Arguments pointer
;# ebp-4 = proc
sub esp,16
;# Save all usable registers to free our hands
push ebx
push edi
push esi
;# Arguments pointer
;# 1-st arg (4 bytes), return (4 bytes) => add 8 bytes
mov dword ptr [ebp-8],ebp
add dword ptr [ebp-8],8
;# Our callback proc is in eax (set by the thunk created in CreateCallback)
mov dword ptr [ebp-4],eax
IFDEF SYSTEM_LOG_DEBUG
SYSTEM_LOG_INIT
SYSTEM_LOG_ADD offset LogCalled
;# LastProc->ProcName
call _GetProcNameOffset
mov ecx,dword ptr [_LastProc]
add eax,ecx
SYSTEM_LOG_ADD eax
SYSTEM_EVENT offset LogShortAfter
SYSTEM_LOG_POST
ENDIF
call _GetCloneOffset
mov edx,eax
mov ecx,dword ptr [ebp-4]
;# 1. Find last unused clone
jmp clone_load
clone_next:
mov ecx,dword ptr [eax]
mov dword ptr [ebp-4],ecx
clone_load:
lea eax,[ecx+edx]
cmp dword ptr [eax],0
jne clone_next
;# 2. Create new clone
push edx
push ecx
call _GlobalCopy
pop ecx
pop edx
;# proc->Clone = Result of GlobalCopy
mov ecx,dword ptr [ebp-4]
mov dword ptr [ecx+edx],eax
;# proc = proc->Clone
mov dword ptr [ebp-4],eax
;# 3. Set clone option
push eax
call _SetCloneOption
pop eax
;# proc->ArgsSize = 0
mov dword ptr [ebp-12],0
;# Read Arguments
;# Get number of parameters
push dword ptr [ebp-4]
call _GetParamCount
add esp,4
;# Skip if there are no parameters
cmp eax,0
jle cb_params_loop_done
;# Save number of parameters on stack
push eax
;# Get size of ProcParameter structure
call _GetSizeOfProcParam
mov dword ptr [ebp-16],eax
;# Get offset for element Params of SystemProc structure
call _GetParamsOffset
add eax,dword ptr [ebp-4]
;# Calculate offset for the Parameter 1
add eax,dword ptr [ebp-16]
;# Save offset for the Parameter 1 on stack
push eax
;# Size offset of parameter
call _GetSizeOffsetParam
push eax
;# Value offset of parameter
call _GetValueOffsetParam
push eax
;# _value offset of parameter
call _Get_valueOffsetParam
push eax
;# ebx = _value offset
pop ebx
;# edx = Value offset
pop edx
;# esi = Size offset
pop esi
;# eax = offset of current worked on parameter
pop eax
;# ecx = n-th parameter
pop ecx
cb_params_loop:
push ecx
;# Default
mov ecx,dword ptr [ebp-8]
mov ecx,dword ptr [ecx]
mov dword ptr [eax+edx],ecx
;# (Arguments pointer)++
add dword ptr [ebp-8],4
;# ArgsSize += 4
add dword ptr [ebp-12],4
;# Size of current parameter == 2
cmp dword ptr [eax+esi],2
jne cb_params_next
;# Long type
mov ecx,dword ptr [ebp-8]
mov ecx,dword ptr [ecx]
mov dword ptr [eax+ebx],ecx
;# (Arguments pointer)++
add dword ptr [ebp-8],4
;# ArgsSize += 4
add dword ptr [ebp-12],4
cb_params_next:
;# Next parameter
add eax,dword ptr [ebp-16]
pop ecx
loop cb_params_loop
cb_params_loop_done:
;# proc->ArgsSize = ArgsSize
call _GetArgsSizeOffset
add eax,dword ptr [ebp-4]
mov ecx,dword ptr [ebp-12]
mov dword ptr [eax],ecx
push dword ptr [ebp-4]
call _SetProcResultCallback
pop eax
;# Return
;# eax = proc
;# Save temporary stack info
push ebp
;# Push LastStackPlace
mov dword ptr [_LastStackPlace],esp
;# Restore real stack
mov esp,dword ptr [_LastStackReal]
;# Pop LastStackReal
pop ebp
;# Fake return from System::Call
;# Restore registers
pop esi
pop edi
pop ebx
;# Restore stack pointer
mov esp,ebp
pop ebp
;# Return
ret
FUNC_END _RealCallBack
FUNC_DECL _CallBack
;# Save stack
push ebp
mov ebp,esp
;# Save all usable registers to free our hands
push ebx
push edi
push esi
IFDEF SYSTEM_LOG_DEBUG
SYSTEM_LOG_INIT
SYSTEM_LOG_ADD offset LogReturn
SYSTEM_EVENT offset LogBefore
SYSTEM_LOG_POST
ENDIF
;# Get offset for element Params of SystemProc structure
call _GetParamsOffset
add eax,dword ptr [ebp+8]
push eax
;# Value offset
call _GetValueOffsetParam
push eax
;# _value offset
call _Get_valueOffsetParam
mov edx,eax
;# offset of Value element within SystemProc structure
pop ecx
;# offset of Params element within SystemProc structure
pop eax
;# Callback proc result
push dword ptr [eax+ecx]
push dword ptr [eax+edx]
;# Adjust return statement
;# if ((proc->Options & POPT_CDECL) != 0)
push dword ptr [ebp+8]
call _GetCDeclOption
cmp eax,0
pop edx
jne _retexpr_stdcall
;# retexpr[1] = proc->ArgsSize
call _GetArgsSizeOffset
mov ecx,dword ptr [ebp+8]
mov al,byte ptr [ecx+eax]
mov byte ptr [_retexpr+1],al
jmp set_return_addr
_retexpr_stdcall:
;# retexpr[1] = 0
mov byte ptr [_retexpr+1],0
set_return_addr:
;# Right return statement address
mov dword ptr [_retaddr],offset _retexpr
;# Remove unneeded callback proc
push dword ptr [ebp+8]
call dword ptr [__imp__GlobalFree@4]
;# Prepare return
;# Callback proc result
pop edx
pop eax
;# Restore temporary stack and return
;# Save real stack info
;# Save previous stack location
;# Push _LastStackReal
push ebp
mov dword ptr [_LastStackReal],esp
;# Move stack pointer
mov esp,dword ptr [_LastStackPlace]
;# Pop _LastStackPlace
pop ebp
IFDEF SYSTEM_LOG_DEBUG
push eax
push edx
SYSTEM_EVENT offset LogShortBefore
SYSTEM_LOG_POST
;# Callback proc result
pop edx
pop eax
ENDIF
;# Fake return from Callback
;# Restore registers
pop esi
pop edi
pop ebx
;# Restore stack pointer
mov esp,ebp
pop ebp
;# Return
jmp dword ptr [_retaddr]
FUNC_END _CallBack
END