applied patch #2193442 - port System::Call and related functions to GCC
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@5775 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
ef3c40bbfd
commit
4c87ec9e83
8 changed files with 1152 additions and 416 deletions
|
@ -2,6 +2,7 @@ target = 'System'
|
|||
|
||||
files = Split("""
|
||||
Source/Buffers.c
|
||||
Source/Call.S
|
||||
Source/Plugin.c
|
||||
Source/System.c
|
||||
""")
|
||||
|
@ -32,7 +33,6 @@ BuildPlugin(
|
|||
libs,
|
||||
examples,
|
||||
docs,
|
||||
entry = '_DllMainCRTStartup',
|
||||
nodeflib = False,
|
||||
defines = ['SYSTEM_EXPORTS']
|
||||
)
|
||||
|
|
|
@ -1,2 +1,8 @@
|
|||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef BUFFERS_H
|
||||
#define BUFFERS_H
|
||||
|
||||
#endif /* BUFFERS_H */
|
||||
|
|
968
Contrib/System/Source/Call.S
Normal file
968
Contrib/System/Source/Call.S
Normal file
|
@ -0,0 +1,968 @@
|
|||
;# Copyright (c) 2008 Thomas Gaugler <thomas@dadie.net>
|
||||
;#
|
||||
;# 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
|
||||
|
||||
#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 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
|
||||
EXTERN __imp__GetLastError@0 : PROC
|
||||
EXTERN __imp__wsprintfA : PROC
|
||||
|
||||
EXTERN _GlobalCopy : PROC
|
||||
|
||||
EXTERN _LastStackPlace : DWORD
|
||||
EXTERN _LastStackReal : DWORD
|
||||
EXTERN _LastError : DWORD
|
||||
EXTERN _LastProc : DWORD
|
||||
EXTERN _CallbackIndex : DWORD
|
||||
|
||||
EXTERN _retexpr : DWORD
|
||||
EXTERN _retaddr : PTR
|
||||
|
||||
EXTERN _GetNewStackSize : PROC
|
||||
EXTERN _GetGenStackOption : PROC
|
||||
EXTERN _GetCDeclOption : PROC
|
||||
EXTERN _GetErrorOption : 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 _SetProcResultOk : 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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
call dword ptr [__imp__wsprintfA]
|
||||
;# 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
|
||||
push ebp
|
||||
|
||||
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
|
||||
;# Remove ebp from stack, no need to generate stack
|
||||
pop eax
|
||||
jne stack_expand_done
|
||||
|
||||
;# Save previous stack location
|
||||
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 paramters 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 paramter on stack
|
||||
push ebx
|
||||
;# Save number of paramters 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
|
||||
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
|
||||
|
||||
;# 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 paramter
|
||||
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 paramters
|
||||
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
|
||||
|
||||
;# Get offset for element Params of SystemProc structure
|
||||
call _GetParamsOffset
|
||||
mov edx,dword ptr [ebp+8]
|
||||
add edx,eax
|
||||
|
||||
;# proc->Params[0].Value = Low double word of result
|
||||
call _GetValueOffsetParam
|
||||
mov ecx,dword ptr [_z1]
|
||||
mov dword ptr [edx+eax],ecx
|
||||
|
||||
;# proc->Params[0]._value = High double word of result
|
||||
call _Get_valueOffsetParam
|
||||
mov ecx,dword ptr [_z2]
|
||||
mov dword ptr [edx+eax],ecx
|
||||
|
||||
;# Proc result: OK
|
||||
push dword ptr [ebp+8]
|
||||
call _SetProcResultOk
|
||||
;# In case of POPT_ERROR -> Get_LastError
|
||||
call _GetErrorOption
|
||||
cmp eax,0
|
||||
pop eax
|
||||
je handling_error_option_done
|
||||
call dword ptr [__imp__GetLastError@0]
|
||||
mov dword ptr [_LastError],eax
|
||||
|
||||
handling_error_option_done:
|
||||
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
|
||||
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
|
||||
|
|
@ -6,10 +6,18 @@
|
|||
#include "Buffers.h"
|
||||
#include "System.h"
|
||||
#ifndef __GNUC__
|
||||
#define _DECL_DLLMAIN /* enable prototypes for DllMain and _CRT_INIT */
|
||||
#include <process.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#define _RPT0(type, msg)
|
||||
#define _CRT_WARN 0
|
||||
#endif /* __GNUC__ */
|
||||
#include <objbase.h>
|
||||
|
||||
// Type conversion macro
|
||||
#define INT_TO_POINTER(i) ((void *) (int) (i))
|
||||
|
||||
// Parse Section Type
|
||||
#define PST_PROC 0
|
||||
#define PST_PARAMS 1
|
||||
|
@ -29,7 +37,6 @@ const int ParamSizeByType[7] = {0, // PAT_VOID (Size will be equal to 1)
|
|||
1, // PAT_GUID
|
||||
0}; // PAT_CALLBACK (Size will be equal to 1)
|
||||
|
||||
int z1, z2; // I've made them static for easier use at callback procs
|
||||
int LastStackPlace;
|
||||
int LastStackReal;
|
||||
DWORD LastError;
|
||||
|
@ -41,15 +48,6 @@ HINSTANCE g_hInstance;
|
|||
char retexpr[4];
|
||||
HANDLE retaddr;
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
/*
|
||||
FIXME:
|
||||
GCC cannot compile the inline assembly used by System::Call and
|
||||
System::Get, so those functions and their supporting functions
|
||||
are disabled when using GCC.
|
||||
*/
|
||||
|
||||
char *GetResultStr(SystemProc *proc)
|
||||
{
|
||||
char *buf = AllocString();
|
||||
|
@ -61,14 +59,13 @@ char *GetResultStr(SystemProc *proc)
|
|||
|
||||
#ifdef SYSTEM_LOG_DEBUG
|
||||
|
||||
// System log debuggin turned on
|
||||
#define SYSTEM_EVENT(a) { _asm { mov logespsave, esp }; LogEvent(a); }
|
||||
#define SYSTEM_LOG_ADD(a) { lstrcat(syslogbuf, a); }
|
||||
#define SYSTEM_LOG_POST { lstrcat(syslogbuf, "\n"); WriteToLog(syslogbuf); *syslogbuf = 0; }
|
||||
// System log debugging turned on
|
||||
#define SYSTEM_LOG_ADD(a) { register int _len = lstrlen(syslogbuf); lstrcpyn(syslogbuf + _len, a, sizeof(syslogbuf) - _len); }
|
||||
#define SYSTEM_LOG_POST { SYSTEM_LOG_ADD("\n"); WriteToLog(syslogbuf); *syslogbuf = 0; }
|
||||
|
||||
HANDLE logfile = NULL;
|
||||
char syslogbuf[4096] = "";
|
||||
int logop = 0, logespsave;
|
||||
int logop = 0;
|
||||
|
||||
void WriteToLog(char *buffer)
|
||||
{
|
||||
|
@ -92,14 +89,6 @@ void WriteToLog(char *buffer)
|
|||
// FlushFileBuffers(logfile);
|
||||
}
|
||||
|
||||
void LogEvent(char *a)
|
||||
{
|
||||
char buffer[1024];
|
||||
wsprintf(buffer, "%s ESP = 0x%08X Stack = 0x%08X Real = 0x%08X", a,
|
||||
logespsave, LastStackPlace, LastStackReal);
|
||||
SYSTEM_LOG_ADD(buffer);
|
||||
}
|
||||
|
||||
PLUGINFUNCTION(Debug)
|
||||
{
|
||||
char *o1;
|
||||
|
@ -261,8 +250,6 @@ PLUGINFUNCTION(Call)
|
|||
GlobalFree((HANDLE) proc); // No, free it
|
||||
} PLUGINFUNCTIONEND
|
||||
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
PLUGINFUNCTIONSHORT(Int64Op)
|
||||
{
|
||||
__int64 i1, i2 = 0, i3, i4;
|
||||
|
@ -320,8 +307,6 @@ __int64 GetIntFromString(char **p)
|
|||
return myatoi(buffer);
|
||||
}
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
SystemProc *PrepareProc(BOOL NeedForCall)
|
||||
{
|
||||
int SectionType = PST_PROC, // First section is always proc spec
|
||||
|
@ -402,7 +387,7 @@ SystemProc *PrepareProc(BOOL NeedForCall)
|
|||
|
||||
if (proc != NULL) GlobalFree(proc);
|
||||
// Get already defined proc
|
||||
proc = (SystemProc *) myatoi(cbuf);
|
||||
proc = (SystemProc *) INT_TO_POINTER(myatoi(cbuf));
|
||||
if (!proc) break;
|
||||
|
||||
// Find the last clone at proc queue
|
||||
|
@ -683,7 +668,7 @@ SystemProc *PrepareProc(BOOL NeedForCall)
|
|||
// Use direct system proc address
|
||||
int addr;
|
||||
|
||||
proc->Dll = (HANDLE) myatoi(proc->DllName);
|
||||
proc->Dll = (HANDLE) INT_TO_POINTER(myatoi(proc->DllName));
|
||||
|
||||
if (proc->Dll == 0)
|
||||
{
|
||||
|
@ -712,7 +697,7 @@ SystemProc *PrepareProc(BOOL NeedForCall)
|
|||
if (*proc->DllName == 0)
|
||||
{
|
||||
// Use direct system proc address
|
||||
if ((proc->Proc = (HANDLE) myatoi(proc->ProcName)) == 0)
|
||||
if ((proc->Proc = (HANDLE) INT_TO_POINTER(myatoi(proc->ProcName))) == 0)
|
||||
proc->ProcResult = PR_ERROR;
|
||||
} else
|
||||
{
|
||||
|
@ -735,7 +720,7 @@ SystemProc *PrepareProc(BOOL NeedForCall)
|
|||
}
|
||||
break;
|
||||
case PT_STRUCT:
|
||||
if (*(proc->ProcName) != 0) proc->Proc = (HANDLE) myatoi(proc->ProcName);
|
||||
if (*(proc->ProcName) != 0) proc->Proc = (HANDLE) INT_TO_POINTER(myatoi(proc->ProcName));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -817,7 +802,7 @@ void ParamsIn(SystemProc *proc)
|
|||
case PAT_CALLBACK:
|
||||
// Generate new or use old callback
|
||||
if (lstrlen(realbuf) > 0)
|
||||
par->Value = (int) CreateCallback((SystemProc*) myatoi(realbuf));
|
||||
par->Value = (int) CreateCallback((SystemProc*) INT_TO_POINTER(myatoi(realbuf)));
|
||||
break;
|
||||
}
|
||||
GlobalFree(realbuf);
|
||||
|
@ -916,368 +901,6 @@ void ParamsOut(SystemProc *proc)
|
|||
while (i >= 0);
|
||||
}
|
||||
|
||||
void _alloca_probe();
|
||||
|
||||
SystemProc __declspec(naked) *CallProc(SystemProc *proc)
|
||||
{
|
||||
int z3;
|
||||
|
||||
_asm
|
||||
{
|
||||
// Save stack
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
// Stack space for local variables
|
||||
sub esp, __LOCAL_SIZE
|
||||
// Save all usable registers to free our hands
|
||||
push ebx
|
||||
push edi
|
||||
push esi
|
||||
}
|
||||
|
||||
SYSTEM_LOG_ADD("\t\tCall:\n");
|
||||
SYSTEM_EVENT("\t\t\tBefore call ")
|
||||
|
||||
if (CallbackIndex && (!(proc->Options & POPT_GENSTACK)))
|
||||
{
|
||||
_asm
|
||||
{
|
||||
push ebp
|
||||
// Save previous stack location
|
||||
mov LastStackReal, esp
|
||||
}
|
||||
|
||||
if (LastStackPlace == 0)
|
||||
{
|
||||
_asm
|
||||
{
|
||||
// Create new stack
|
||||
mov eax, NEW_STACK_SIZE
|
||||
call _alloca_probe
|
||||
mov LastStackPlace, esp
|
||||
}
|
||||
} else
|
||||
_asm
|
||||
{
|
||||
// Move stack pointer
|
||||
mov esp, LastStackPlace
|
||||
}
|
||||
}
|
||||
|
||||
// Push arguments to stack
|
||||
for (z1 = proc->ParamCount; z1 > 0; z1--)
|
||||
{
|
||||
// Long types
|
||||
if (proc->Params[z1].Size == 2)
|
||||
{
|
||||
z2 = proc->Params[z1]._value;
|
||||
_asm push z2;
|
||||
}
|
||||
// Default
|
||||
z2 = proc->Params[z1].Value;
|
||||
_asm push z2;
|
||||
}
|
||||
|
||||
// Call the proc and save return
|
||||
z1 = (int) proc->Proc;
|
||||
|
||||
// Save proc
|
||||
proc->Clone = (SystemProc *) LastProc;
|
||||
_asm
|
||||
{
|
||||
mov eax, proc
|
||||
mov LastProc, eax
|
||||
}
|
||||
//LastProc = proc;
|
||||
|
||||
SYSTEM_EVENT("\n\t\t\tNear call ")
|
||||
SYSTEM_LOG_POST;
|
||||
|
||||
// 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.
|
||||
_asm xor eax, eax
|
||||
|
||||
_asm
|
||||
{
|
||||
// Call
|
||||
call z1
|
||||
// Return
|
||||
mov z1, eax
|
||||
mov z2, edx
|
||||
}
|
||||
|
||||
SYSTEM_LOG_ADD("Back from ");
|
||||
SYSTEM_LOG_ADD(LastProc->ProcName);
|
||||
SYSTEM_EVENT("\n\t\t\tShort-After call ")
|
||||
|
||||
if ((CallbackIndex) && (!(LastProc->Options & POPT_GENSTACK)))
|
||||
{
|
||||
_asm
|
||||
{
|
||||
// Restore real stack location
|
||||
mov LastStackPlace, esp
|
||||
mov esp, LastStackReal
|
||||
pop ebp
|
||||
}
|
||||
}
|
||||
|
||||
// Restore proc
|
||||
_asm
|
||||
{
|
||||
mov eax, LastProc
|
||||
mov proc, eax
|
||||
}
|
||||
// proc = LastProc;
|
||||
LastProc = proc->Clone;
|
||||
|
||||
// In case of cdecl convention we should clear stack
|
||||
if ((proc->Options & POPT_CDECL) != 0)
|
||||
{
|
||||
if ((CallbackIndex > 0) && ((proc->Options & POPT_GENSTACK) == 0))
|
||||
{
|
||||
// In case of temporary stack
|
||||
for (z3 = 1; z3 <= proc->ParamCount; z3++)
|
||||
LastStackPlace += 4*proc->Params[z3].Size;
|
||||
} else
|
||||
{
|
||||
// in case of real stack
|
||||
for (z3 = 1; z3 <= proc->ParamCount; z3++)
|
||||
{
|
||||
if (proc->Params[z3].Size == 2)
|
||||
_asm pop edx;
|
||||
_asm pop edx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In case of cleared call-proc-queue -> clear allocated stack place (more flexible)
|
||||
if (LastProc == NULL) LastStackPlace = (int) NULL;
|
||||
|
||||
// Save return
|
||||
proc->Params[0].Value = z1;
|
||||
// if (proc->Params[0].Size == 2)
|
||||
proc->Params[0]._value = z2;
|
||||
// Proc result: OK
|
||||
proc->ProcResult = PR_OK;
|
||||
|
||||
// In case of POPT_ERROR -> GetLastError
|
||||
if ((proc->Options & POPT_ERROR) != 0)
|
||||
{
|
||||
LastError = GetLastError();
|
||||
}
|
||||
|
||||
SYSTEM_EVENT("\n\t\t\tAfter call ")
|
||||
#ifdef SYSTEM_LOG_DEBUG
|
||||
{
|
||||
char buf[1024];
|
||||
wsprintf(buf, "\n\t\t\tReturn 0x%08X 0x%08X", z1, z2);
|
||||
SYSTEM_LOG_ADD(buf);
|
||||
}
|
||||
#endif
|
||||
SYSTEM_LOG_POST;
|
||||
|
||||
_asm
|
||||
{
|
||||
// Return
|
||||
mov eax, proc
|
||||
// Restore registers
|
||||
pop esi
|
||||
pop edi
|
||||
pop ebx
|
||||
// Restore stack pointer
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
// Return
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
SystemProc __declspec(naked) *RealCallBack()
|
||||
{
|
||||
SystemProc *proc;
|
||||
|
||||
_asm
|
||||
{
|
||||
// Save stack
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
// Stack space for local variables
|
||||
sub esp, __LOCAL_SIZE
|
||||
// Save all usable registers to free our hands
|
||||
push ebx
|
||||
push edi
|
||||
push esi
|
||||
|
||||
// Arguments pointer
|
||||
mov z2, esp // 1-st arg - 4*4 (pushes) - 4 (return) - __LOCAL_SIZE
|
||||
add z2, __LOCAL_SIZE
|
||||
add z2, 5*4
|
||||
// Our callback proc
|
||||
mov proc, eax
|
||||
}
|
||||
|
||||
SYSTEM_LOG_ADD("Called callback from ");
|
||||
SYSTEM_LOG_ADD(LastProc->ProcName);
|
||||
SYSTEM_EVENT("\n\t\t\tShort-After call ")
|
||||
SYSTEM_LOG_POST;
|
||||
|
||||
// Find last unused clone
|
||||
while ((proc->Clone != NULL)) proc = proc->Clone;
|
||||
// 2. Create new clone
|
||||
proc = (proc->Clone = GlobalCopy(proc));
|
||||
// 3. Set clone option
|
||||
proc->Options |= POPT_CLONE;
|
||||
|
||||
// Read arguments
|
||||
proc->ArgsSize = 0;
|
||||
for (z1 = 1; z1 <= proc->ParamCount; z1++)
|
||||
{
|
||||
// Default
|
||||
proc->Params[z1].Value = *(((int*)z2)++);
|
||||
proc->ArgsSize += 4;
|
||||
// Long only
|
||||
if (proc->Params[z1].Size == 2)
|
||||
{
|
||||
proc->Params[z1]._value = *(((int*)z2)++);
|
||||
proc->ArgsSize += 4;
|
||||
}
|
||||
}
|
||||
proc->ProcResult = PR_CALLBACK;
|
||||
|
||||
_asm
|
||||
{
|
||||
// Return
|
||||
mov eax, proc
|
||||
|
||||
// Save temporary stack info
|
||||
push ebp
|
||||
// push LastStackPlace
|
||||
mov LastStackPlace, esp
|
||||
// Restore real stack
|
||||
mov esp, LastStackReal
|
||||
pop ebp
|
||||
// pop LastStackReal
|
||||
}
|
||||
|
||||
_asm
|
||||
{
|
||||
// Fake return from System::Call
|
||||
|
||||
// Restore registers
|
||||
pop esi
|
||||
pop edi
|
||||
pop ebx
|
||||
// Restore stack pointer
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
// Return
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SystemProc __declspec(naked) *CallBack(SystemProc *proc)
|
||||
{
|
||||
_asm
|
||||
{
|
||||
// Save stack
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
// Stack space for local variables
|
||||
sub esp, __LOCAL_SIZE
|
||||
// Save all usable registers to free our hands
|
||||
push ebx
|
||||
push edi
|
||||
push esi
|
||||
}
|
||||
|
||||
// MessageBox(NULL, "cool1", "Cool", MB_OK);
|
||||
|
||||
SYSTEM_LOG_ADD("\t\tReturn from callback:\n");
|
||||
SYSTEM_EVENT("\t\t\tBefore call-back ");
|
||||
SYSTEM_LOG_POST;
|
||||
|
||||
//z1 = proc->Params[0].Value;
|
||||
//z2 = proc->Params[0]._value;
|
||||
//z1 = &(proc->Params[0].Value);
|
||||
_asm
|
||||
{
|
||||
mov eax, proc
|
||||
add eax, SYSTEM_ZERO_PARAM_VALUE_OFFSET
|
||||
push [eax]
|
||||
push [eax+4]
|
||||
}
|
||||
|
||||
// Adjust return statement
|
||||
if ((proc->Options & POPT_CDECL) == 0) retexpr[1] = proc->ArgsSize;
|
||||
else retexpr[1] = 0x0;
|
||||
|
||||
// Right return statement address
|
||||
retaddr = (HANDLE) retexpr;
|
||||
|
||||
// Remove unneeded callback proc
|
||||
GlobalFree((HANDLE) proc);
|
||||
|
||||
// MessageBox(NULL, "cool2", "Cool", MB_OK);
|
||||
|
||||
_asm
|
||||
{
|
||||
// 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 LastStackReal, esp
|
||||
// Move stack pointer
|
||||
mov esp, LastStackPlace
|
||||
// pop LastStackPlace
|
||||
pop ebp
|
||||
}
|
||||
|
||||
#ifdef SYSTEM_LOG_DEBUG
|
||||
_asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
}
|
||||
SYSTEM_EVENT("\n\t\t\tSh-Before call-back");
|
||||
SYSTEM_LOG_POST;
|
||||
_asm
|
||||
{
|
||||
// callback proc result
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#endif
|
||||
|
||||
// Fake return from Callback
|
||||
_asm {
|
||||
// Restore registers
|
||||
pop esi
|
||||
pop edi
|
||||
pop ebx
|
||||
// Restore stack pointer
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
// Return
|
||||
jmp retaddr
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE CreateCallback(SystemProc *cbproc)
|
||||
{
|
||||
char *mem;
|
||||
|
@ -1290,7 +913,8 @@ HANDLE CreateCallback(SystemProc *cbproc)
|
|||
|
||||
mem = (char *) (cbproc->Proc = VirtualAlloc(NULL, 10, MEM_COMMIT, PAGE_EXECUTE_READWRITE));
|
||||
*(mem++) = (char) 0xB8; // Mov eax, const
|
||||
*(((int *)mem)++) = (int) cbproc;
|
||||
*((int *)mem) = (int) cbproc;
|
||||
mem += sizeof(int);
|
||||
*(mem++) = (char) 0xe9; // Jmp relative
|
||||
*((int *)mem) = (int) RealCallBack;
|
||||
*((int *)mem) -= ((int) mem) + 4;
|
||||
|
@ -1387,16 +1011,25 @@ void CallStruct(SystemProc *proc)
|
|||
proc->Params[0].Value = (int) proc->Proc;
|
||||
}
|
||||
|
||||
#endif /* __GNUC__ */
|
||||
/*
|
||||
Use of system _DllMainCRTStartup to avoid endless recursion for the debug
|
||||
report macro _RPT0.
|
||||
|
||||
BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
|
||||
The system _DllMainCRTStartup initializes the C runtime environment.
|
||||
In particular the value for _osplatform is initialized. In the function
|
||||
_get_winmajor called in the execution of the _RPT0 macro an assertion
|
||||
failure is raised if _osplatform is not set. The assertion is reported by
|
||||
the same means as used for the _RPT0 macro. This leads to an endless recursion.
|
||||
*/
|
||||
|
||||
BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
|
||||
{
|
||||
g_hInstance=hInst;
|
||||
|
||||
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
// change the protection of return command
|
||||
VirtualProtect(&retexpr, sizeof(retexpr), PAGE_EXECUTE_READWRITE, &LastStackPlace);
|
||||
VirtualProtect(&retexpr, sizeof(retexpr), PAGE_EXECUTE_READWRITE, (PDWORD)&LastStackPlace);
|
||||
|
||||
// initialize some variables
|
||||
LastStackPlace = 0;
|
||||
|
@ -1411,3 +1044,139 @@ BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lp
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns size by which the stack should be expanded
|
||||
*/
|
||||
unsigned int GetNewStackSize(void)
|
||||
{
|
||||
return NEW_STACK_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns non-zero value if GENSTACK option is set
|
||||
*/
|
||||
unsigned int GetGenStackOption(SystemProc *proc)
|
||||
{
|
||||
return (proc->Options & POPT_GENSTACK);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns non-zero value if CDECL option is set
|
||||
*/
|
||||
unsigned int GetCDeclOption(SystemProc *proc)
|
||||
{
|
||||
return (proc->Options & POPT_CDECL);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns non-zero value if Error option is set
|
||||
*/
|
||||
unsigned int GetErrorOption(SystemProc *proc)
|
||||
{
|
||||
return (proc->Options & POPT_ERROR);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns offset for element Proc of SystemProc structure
|
||||
*/
|
||||
unsigned int GetProcOffset(void)
|
||||
{
|
||||
return (unsigned int)(&(((SystemProc *)0)->Proc));
|
||||
}
|
||||
|
||||
/*
|
||||
Returns offset for element Clone of SystemProc structure
|
||||
*/
|
||||
unsigned int GetCloneOffset(void)
|
||||
{
|
||||
return (unsigned int)(&(((SystemProc *)0)->Clone));
|
||||
}
|
||||
|
||||
/*
|
||||
Returns offset for element ProcName of SystemProc structure
|
||||
*/
|
||||
unsigned int GetProcNameOffset(void)
|
||||
{
|
||||
return (unsigned int)(&(((SystemProc *)0)->ProcName));
|
||||
}
|
||||
|
||||
/*
|
||||
Returns offset for element ArgsSize of SystemProc structure
|
||||
*/
|
||||
unsigned int GetArgsSizeOffset(void)
|
||||
{
|
||||
return (unsigned int)(&(((SystemProc *)0)->ArgsSize));
|
||||
}
|
||||
|
||||
/*
|
||||
Returns number of parameters
|
||||
*/
|
||||
unsigned int GetParamCount(SystemProc *proc)
|
||||
{
|
||||
return proc->ParamCount;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns offset for element Params of SystemProc structure
|
||||
*/
|
||||
unsigned int GetParamsOffset(void)
|
||||
{
|
||||
return (unsigned int)(&(((SystemProc *)0)->Params));
|
||||
}
|
||||
|
||||
/*
|
||||
Returns size of ProcParameter structure
|
||||
*/
|
||||
unsigned int GetSizeOfProcParam(void)
|
||||
{
|
||||
return (sizeof(ProcParameter));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Returns offset for element Size of ProcParameter structure
|
||||
*/
|
||||
unsigned int GetSizeOffsetParam(void)
|
||||
{
|
||||
return (unsigned int)(&(((ProcParameter *)0)->Size));
|
||||
}
|
||||
|
||||
/*
|
||||
Returns offset for element Value of ProcParameter structure
|
||||
*/
|
||||
unsigned int GetValueOffsetParam(void)
|
||||
{
|
||||
return (unsigned int)(&(((ProcParameter *)0)->Value));
|
||||
}
|
||||
|
||||
/*
|
||||
Returns offset for element _value of ProcParameter structure
|
||||
*/
|
||||
unsigned int Get_valueOffsetParam(void)
|
||||
{
|
||||
return (unsigned int)(&(((ProcParameter *)0)->_value));
|
||||
}
|
||||
|
||||
/*
|
||||
Sets "CLONE" option
|
||||
*/
|
||||
void SetCloneOption(SystemProc *proc)
|
||||
{
|
||||
proc->Options |= POPT_CLONE;
|
||||
}
|
||||
|
||||
/*
|
||||
Sets Result of procedure call to be "OK"
|
||||
*/
|
||||
void SetProcResultOk(SystemProc *proc)
|
||||
{
|
||||
proc->ProcResult = PR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
Sets Result of procedure call to be "CALLBACK"
|
||||
*/
|
||||
void SetProcResultCallback(SystemProc *proc)
|
||||
{
|
||||
proc->ProcResult = PR_CALLBACK;
|
||||
}
|
||||
|
|
|
@ -58,10 +58,6 @@ typedef struct
|
|||
{
|
||||
int Type;
|
||||
int Option; // -1 -> Pointer, 1-... -> Special+1
|
||||
|
||||
// if you'll change ProcParameter or SystemProc structure - update this value
|
||||
#define SYSTEM_ZERO_PARAM_VALUE_OFFSET 0x820
|
||||
|
||||
int Value; // it can hold any 4 byte value
|
||||
int _value; // value buffer for structures > 4 bytes (I hope 8 bytes will be enough)
|
||||
int Size; // Value real size (should be either 1 or 2 (the number of pushes))
|
||||
|
|
|
@ -3,7 +3,12 @@
|
|||
// are changed infrequently
|
||||
//
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef STDAFX_H
|
||||
#define STDAFX_H
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
// Windows Header Files:
|
||||
|
@ -11,3 +16,5 @@
|
|||
|
||||
// TODO: reference additional headers your program requires here
|
||||
//#define SYSTEM_LOG_DEBUG
|
||||
|
||||
#endif /* STDAFX_H */
|
||||
|
|
|
@ -20,6 +20,8 @@ if float(defenv['MSVS_VERSION'].replace('Exp','')) >= 8.0:
|
|||
else:
|
||||
defenv['EXCEPTION_FLAG'] = '/GX'
|
||||
|
||||
defenv.Append(ASFLAGS = ['/coff'])
|
||||
|
||||
### debug
|
||||
|
||||
if defenv['DEBUG']:
|
||||
|
|
14
SConstruct
14
SConstruct
|
@ -127,20 +127,8 @@ if 'msvc' in defenv['TOOLS'] or 'mstoolkit' in defenv['TOOLS']:
|
|||
ignore_tests = 'none'
|
||||
else:
|
||||
ignore_tests = ','.join(Split("""
|
||||
Examples/LogicLib.nsi
|
||||
Examples/StrFunc.nsi
|
||||
Examples/TextFunc.nsi
|
||||
Examples/TextFuncTest.nsi
|
||||
Examples/FileFunc.nsi
|
||||
Examples/FileFuncTest.nsi
|
||||
Examples/Library.nsi
|
||||
Examples/makensis.nsi
|
||||
Examples/gfx.nsi
|
||||
Examples/System/System.nsi
|
||||
Examples/nsDialogs/example.nsi
|
||||
Examples/nsDialogs/InstallOptions.nsi
|
||||
Examples/nsDialogs/welcome.nsi""")
|
||||
+ ['Examples/Modern UI/WelcomeFinish.nsi'])
|
||||
Examples/gfx.nsi"""))
|
||||
|
||||
# version
|
||||
opts.Add(('VERSION', 'Version of NSIS', cvs_version))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue