
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@7245 212acab6-be3b-0410-9dea-997c60f758d6
1033 lines
25 KiB
ArmAsm
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
|
|
|