Commit 3dff7bb8 authored by Ulrich Weigand's avatar Ulrich Weigand Committed by Alexandre Julliard

Modularized CallFrom/To16 routines. Adapted dependent routines,

16-bit snoop/relay debugging, and make rules.
parent 03c13bbd
......@@ -9,6 +9,8 @@
# ASM_SRCS : assembly sources (optional)
# GEN_ASM_SRCS : generated assembly sources (optional)
# RC_SRCS : resource source files (optional)
# SPEC_SRCS : interface definition files (optional)
# GLUE : C sources for which glue code needs to be generated (optional)
# EXTRA_SRCS : extra source files for make depend (optional)
# EXTRA_OBJS : extra object files (optional)
# WRCEXTRA : extra wrc flags (e.g. '-p _SysRes') (optional)
......@@ -69,12 +71,12 @@ mandir = @mandir@/man1
manext = .1
includedir = @includedir@/wine
OBJS = $(C_SRCS:.c=.o) $(GEN_ASM_SRCS:.s=.o) $(ASM_SRCS:.S=.o) \
$(RC_SRCS:.rc=.o) $(EXTRA_OBJS)
OBJS = $(C_SRCS:.c=.o) $(GEN_ASM_SRCS:.s=.o) $(ASM_SRCS:.S=.o) $(RC_SRCS:.rc=.o) \
$(SPEC_SRCS:.spec=.spec.o) $(GLUE:.c=.glue.o) $(EXTRA_OBJS)
# Implicit rules
.SUFFIXES: .rc .res
.SUFFIXES: .rc .res .spec .spec.c .glue.s
.c.o:
$(CC) -c $(ALLCFLAGS) -o $*.o $<
......@@ -100,6 +102,11 @@ OBJS = $(C_SRCS:.c=.o) $(GEN_ASM_SRCS:.s=.o) $(ASM_SRCS:.S=.o) \
.res.h:
$(WRC) $(WRCFLAGS) $(WRCEXTRA) -bnh $<
.spec.spec.c:
$(BUILD) -o $@ -spec $<
.c.glue.s:
$(BUILD) -o $@ -glue $<
# Rule to rebuild the resource compiler
......@@ -147,11 +154,15 @@ lint:
# Misc. rules
$(SPEC_SRCS:.spec=.spec.c): $(BUILD) $(TOPSRCDIR)/include/builtin16.h $(TOPSRCDIR)/include/builtin32.h
$(GLUE:.c=.glue.s): $(BUILD)
depend:: $(MAKEDEP) $(C_SRCS) $(RC_SRCS) $(EXTRA_SRCS)
$(MAKEDEP) $(DIVINCL) -C$(SRCDIR) $(C_SRCS) $(RC_SRCS) $(EXTRA_SRCS)
clean::
$(RM) *.o \#*\# *~ *% .#* *.bak *.orig *.rej *.flc y.tab.c y.tab.h lex.yy.c core $(GEN_ASM_SRCS) $(RC_SRCS:.rc=.s) $(RC_SRCS:.rc=.h) $(PROGRAMS)
$(RM) *.o \#*\# *~ *% .#* *.bak *.orig *.rej *.flc y.tab.c y.tab.h lex.yy.c core $(GEN_ASM_SRCS) $(RC_SRCS:.rc=.s) $(RC_SRCS:.rc=.h) $(SPEC_SRCS:.spec=.spec.c) $(GLUE:.c=.glue.s) $(PROGRAMS)
dummy:
......
Makefile
avifile.s
callfrom16.s
callto16.s
comm.s
commdlg.s
compobj.s
ddeml.s
dispdib.s
display.s
gdi.s
kernel.s
keyboard.s
lzexpand.s
mmsystem.s
mouse.s
msacm.s
msvideo.s
ole2.s
ole2conv.s
ole2disp.s
ole2nls.s
ole2prox.s
ole2thk.s
olecli.s
olesvr.s
rasapi16.s
shell.s
sound.s
storage.s
stress.s
system.s
toolhelp.s
typelib.s
user.s
ver.s
w32sys.s
win32s16.s
win87em.s
winaspi.s
windebug.s
wineps.s
wing.s
winsock.s
wprocs.s
avifile.spec.c
avifile.spec.glue.s
call16.s
callfrom16.spec.c
callfrom16.spec.glue.s
callto16.spec.c
callto16.spec.glue.s
comm.spec.c
comm.spec.glue.s
commdlg.spec.c
commdlg.spec.glue.s
compobj.spec.c
compobj.spec.glue.s
ddeml.spec.c
ddeml.spec.glue.s
dispdib.spec.c
dispdib.spec.glue.s
display.spec.c
display.spec.glue.s
gdi.spec.c
gdi.spec.glue.s
kernel.spec.c
kernel.spec.glue.s
keyboard.spec.c
keyboard.spec.glue.s
lzexpand.spec.c
lzexpand.spec.glue.s
mmsystem.spec.c
mmsystem.spec.glue.s
mouse.spec.c
mouse.spec.glue.s
msacm.spec.c
msacm.spec.glue.s
msvideo.spec.c
msvideo.spec.glue.s
ole2.spec.c
ole2.spec.glue.s
ole2conv.spec.c
ole2conv.spec.glue.s
ole2disp.spec.c
ole2disp.spec.glue.s
ole2nls.spec.c
ole2nls.spec.glue.s
ole2prox.spec.c
ole2prox.spec.glue.s
ole2thk.spec.c
ole2thk.spec.glue.s
olecli.spec.c
olecli.spec.glue.s
olesvr.spec.c
olesvr.spec.glue.s
rasapi16.spec.c
rasapi16.spec.glue.s
shell.spec.c
shell.spec.glue.s
sound.spec.c
sound.spec.glue.s
storage.spec.c
storage.spec.glue.s
stress.spec.c
stress.spec.glue.s
system.spec.c
system.spec.glue.s
thunk.glue.s
toolhelp.spec.c
toolhelp.spec.glue.s
typelib.spec.c
typelib.spec.glue.s
user.spec.c
user.spec.glue.s
ver.spec.c
ver.spec.glue.s
w32sys.spec.c
w32sys.spec.glue.s
win32s16.spec.c
win32s16.spec.glue.s
win87em.spec.c
win87em.spec.glue.s
winaspi.spec.c
winaspi.spec.glue.s
windebug.spec.c
windebug.spec.glue.s
wineps.spec.c
wineps.spec.glue.s
wing.spec.c
wing.spec.glue.s
winsock.spec.c
winsock.spec.glue.s
wprocs.spec.c
wprocs.spec.glue.s
......@@ -5,7 +5,7 @@ SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = if1632
DLLS = \
SPEC_SRCS = \
avifile.spec \
comm.spec \
commdlg.spec \
......@@ -49,8 +49,6 @@ DLLS = \
winsock.spec \
wprocs.spec
SPEC_FILES = $(DLLS:.spec=.s)
C_SRCS = \
builtin.c \
dummy.c \
......@@ -59,25 +57,16 @@ C_SRCS = \
thunk.c
GEN_ASM_SRCS = \
$(SPEC_FILES) \
callfrom16.s \
callto16.s
.SUFFIXES: .spec
call16.s
.spec.s:
$(BUILD) -o $@ -spec $<
GLUE = $(SPEC_SRCS:.spec=.spec.c) \
thunk.c
all: checkbuild $(MODULE).o
all: $(MODULE).o
@MAKE_RULES@
$(SPEC_FILES): $(BUILD)
callfrom16.s: $(SPEC_FILES)
$(BUILD) -o $@ -callfrom16 `cat $(SPEC_FILES) | grep CallFrom16_ | sed 's/.*CallFrom16_\(.*\)/\1/' | sort | uniq`
callto16.s: $(SRCDIR)/thunk.c $(BUILD)
$(BUILD) -o $@ -callto16 $(SRCDIR)/thunk.c
call16.s: $(BUILD)
$(BUILD) -o $@ -call16
### Dependencies:
......@@ -263,12 +263,11 @@ HMODULE16 BUILTIN_LoadModule( LPCSTR name, BOOL force )
/***********************************************************************
* BUILTIN_GetEntryPoint16
*
* Return the ordinal and name corresponding to a CS:IP address.
* Return the ordinal, name, and type info corresponding to a CS:IP address.
* This is used only by relay debugging.
*/
LPCSTR BUILTIN_GetEntryPoint16( WORD cs, WORD ip, WORD *pOrd )
LPCSTR BUILTIN_GetEntryPoint16( WORD cs, WORD ip, LPSTR name, WORD *pOrd )
{
static char buffer[80];
WORD i, max_offset;
register BYTE *p;
NE_MODULE *pModule;
......@@ -286,7 +285,7 @@ LPCSTR BUILTIN_GetEntryPoint16( WORD cs, WORD ip, WORD *pOrd )
entry = (ET_ENTRY *)((BYTE *)bundle+6);
for (i = bundle->first + 1; i <= bundle->last; i++)
{
if ((entry->offs <= ip)
if ((entry->offs < ip)
&& (entry->segnum == 1) /* code segment ? */
&& (entry->offs >= max_offset))
{
......@@ -308,11 +307,13 @@ LPCSTR BUILTIN_GetEntryPoint16( WORD cs, WORD ip, WORD *pOrd )
if (*(WORD *)(p + *p + 1) == *pOrd) break;
}
sprintf( buffer, "%.*s.%d: %.*s",
sprintf( name, "%.*s.%d: %.*s",
*((BYTE *)pModule + pModule->name_table),
(char *)pModule + pModule->name_table + 1,
*pOrd, *p, (char *)(p + 1) );
return buffer;
/* Retrieve type info string */
return *(LPCSTR *)((LPBYTE)PTR_SEG_OFF_TO_LIN( cs, ip ) - 6) + 10;
}
......@@ -324,8 +325,9 @@ LPCSTR BUILTIN_GetEntryPoint16( WORD cs, WORD ip, WORD *pOrd )
void BUILTIN_DefaultIntHandler( CONTEXT86 *context )
{
WORD ordinal;
char name[80];
STACK16FRAME *frame = CURRENT_STACK16;
BUILTIN_GetEntryPoint16( frame->entry_cs, frame->entry_ip, &ordinal );
BUILTIN_GetEntryPoint16( frame->entry_cs, frame->entry_ip, name, &ordinal );
INT_BARF( context, ordinal - FIRST_INTERRUPT_ORDINAL );
}
......@@ -30,34 +30,27 @@ BOOL RELAY_Init(void)
/* Allocate the code selector for CallTo16 routines */
extern void CALLTO16_Start(), CALLTO16_End();
extern void CALLTO16_Ret_word(), CALLTO16_Ret_long();
extern void CALLTO16_Ret_eax();
extern void Call16_Ret_Start(), Call16_Ret_End();
extern void CallTo16_Ret();
extern void CALL32_CBClient_Ret();
extern void CALL32_CBClientEx_Ret();
extern DWORD CALLTO16_RetAddr_word;
extern DWORD CALLTO16_RetAddr_long;
extern DWORD CALLTO16_RetAddr_eax;
extern DWORD CallTo16_RetAddr;
extern DWORD CALL32_CBClient_RetAddr;
extern DWORD CALL32_CBClientEx_RetAddr;
codesel = GLOBAL_CreateBlock( GMEM_FIXED, (void *)CALLTO16_Start,
(int)CALLTO16_End - (int)CALLTO16_Start,
codesel = GLOBAL_CreateBlock( GMEM_FIXED, (void *)Call16_Ret_Start,
(int)Call16_Ret_End - (int)Call16_Ret_Start,
0, TRUE, TRUE, FALSE, NULL );
if (!codesel) return FALSE;
/* Patch the return addresses for CallTo16 routines */
CALLTO16_RetAddr_word=MAKELONG( (int)CALLTO16_Ret_word-(int)CALLTO16_Start,
codesel );
CALLTO16_RetAddr_long=MAKELONG( (int)CALLTO16_Ret_long-(int)CALLTO16_Start,
codesel );
CALLTO16_RetAddr_eax =MAKELONG( (int)CALLTO16_Ret_eax -(int)CALLTO16_Start,
codesel );
CallTo16_RetAddr =
MAKELONG( (int)CallTo16_Ret -(int)Call16_Ret_Start, codesel );
CALL32_CBClient_RetAddr =
MAKELONG( (int)CALL32_CBClient_Ret -(int)CALLTO16_Start, codesel );
MAKELONG( (int)CALL32_CBClient_Ret -(int)Call16_Ret_Start, codesel );
CALL32_CBClientEx_RetAddr =
MAKELONG( (int)CALL32_CBClientEx_Ret -(int)CALLTO16_Start, codesel );
MAKELONG( (int)CALL32_CBClientEx_Ret -(int)Call16_Ret_Start, codesel );
/* Create built-in modules */
if (!BUILTIN_Init()) return FALSE;
......@@ -73,25 +66,29 @@ extern char **debug_relay_excludelist,**debug_relay_includelist;
/***********************************************************************
* RELAY_DebugCallFrom16
*/
void RELAY_DebugCallFrom16( int func_type, char *args,
void *entry_point, CONTEXT86 *context )
void RELAY_DebugCallFrom16( CONTEXT86 *context )
{
STACK16FRAME *frame;
WORD ordinal;
char *args16;
const char *funstr;
int i;
char *args16, funstr[80];
const char *args;
int i, usecdecl, reg_func;
if (!TRACE_ON(relay)) return;
frame = CURRENT_STACK16;
funstr = BUILTIN_GetEntryPoint16(frame->entry_cs,frame->entry_ip,&ordinal);
if (!funstr) return; /* happens for the two snoop register relays */
args = BUILTIN_GetEntryPoint16(frame->entry_cs,frame->entry_ip,funstr,&ordinal);
if (!args) return; /* happens for the two snoop register relays */
if (!RELAY_ShowDebugmsgRelay(funstr)) return;
DPRINTF( "Call %s(",funstr);
VA_START16( args16 );
if (func_type & 4) /* cdecl */
usecdecl = ( *args == 'c' );
args += 2;
reg_func = ( memcmp( args, "regs_", 5 ) == 0 );
args += 5;
if (usecdecl)
{
while (*args)
{
......@@ -185,11 +182,11 @@ void RELAY_DebugCallFrom16( int func_type, char *args,
DPRINTF( ") ret=%04x:%04x ds=%04x\n", frame->cs, frame->ip, frame->ds );
VA_END16( args16 );
if (func_type & 2) /* register function */
DPRINTF( " AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n",
AX_reg(context), BX_reg(context), CX_reg(context),
DX_reg(context), SI_reg(context), DI_reg(context),
(WORD)ES_reg(context), EFL_reg(context) );
if (reg_func)
DPRINTF(" AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n",
AX_reg(context), BX_reg(context), CX_reg(context),
DX_reg(context), SI_reg(context), DI_reg(context),
(WORD)ES_reg(context), EFL_reg(context) );
SYSLEVEL_CheckNotLevel( 2 );
}
......@@ -198,36 +195,38 @@ void RELAY_DebugCallFrom16( int func_type, char *args,
/***********************************************************************
* RELAY_DebugCallFrom16Ret
*/
void RELAY_DebugCallFrom16Ret( int func_type, int ret_val, CONTEXT86 *context)
void RELAY_DebugCallFrom16Ret( CONTEXT86 *context, int ret_val )
{
STACK16FRAME *frame;
WORD ordinal;
const char *funstr;
char funstr[80];
const char *args;
if (!TRACE_ON(relay)) return;
frame = CURRENT_STACK16;
funstr = BUILTIN_GetEntryPoint16(frame->entry_cs,frame->entry_ip,&ordinal);
if (!funstr) return;
args = BUILTIN_GetEntryPoint16(frame->entry_cs,frame->entry_ip,funstr,&ordinal);
if (!args) return;
if (!RELAY_ShowDebugmsgRelay(funstr)) return;
DPRINTF( "Ret %s() ",funstr);
switch(func_type)
if ( memcmp( args+2, "long_", 5 ) == 0 )
{
case 0: /* long */
DPRINTF( "retval=0x%08x ret=%04x:%04x ds=%04x\n",
ret_val, frame->cs, frame->ip, frame->ds );
break;
case 1: /* word */
}
else if ( memcmp( args+2, "word_", 5 ) == 0 )
{
DPRINTF( "retval=0x%04x ret=%04x:%04x ds=%04x\n",
ret_val & 0xffff, frame->cs, frame->ip, frame->ds );
break;
case 2: /* regs */
}
else if ( memcmp( args+2, "regs_", 5 ) == 0 )
{
DPRINTF("retval=none ret=%04x:%04x ds=%04x\n",
(WORD)CS_reg(context), IP_reg(context), (WORD)DS_reg(context));
DPRINTF(" AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n",
AX_reg(context), BX_reg(context), CX_reg(context),
DX_reg(context), SI_reg(context), DI_reg(context),
(WORD)ES_reg(context), EFL_reg(context) );
break;
}
SYSLEVEL_CheckNotLevel( 2 );
......@@ -243,10 +242,11 @@ void RELAY_DebugCallFrom16Ret( int func_type, int ret_val, CONTEXT86 *context)
void RELAY_Unimplemented16(void)
{
WORD ordinal;
char name[80];
STACK16FRAME *frame = CURRENT_STACK16;
BUILTIN_GetEntryPoint16(frame->entry_cs,frame->entry_ip,name,&ordinal);
MESSAGE("No handler for Win16 routine %s (called from %04x:%04x)\n",
BUILTIN_GetEntryPoint16(frame->entry_cs,frame->entry_ip,&ordinal),
frame->cs, frame->ip );
name, frame->cs, frame->ip );
ExitProcess(1);
}
......
......@@ -24,7 +24,7 @@ DEFAULT_DEBUG_CHANNEL(snoop)
void WINAPI SNOOP16_Entry(CONTEXT86 *context);
void WINAPI SNOOP16_Return(CONTEXT86 *context);
extern void CallFrom16_p_regs_();
extern void KERNEL_CallFrom16_p_regs_();
/* Generic callfrom16_p_regs function entry.
* pushw %bp 0x55
......@@ -103,14 +103,14 @@ SNOOP16_RegisterDLL(NE_MODULE *pModule,LPCSTR name) {
snr[0].pushl = 0x68;
snr[0].realfun = (DWORD)SNOOP16_Entry;
snr[0].lcall = 0x9a;
snr[0].callfromregs = (DWORD)CallFrom16_p_regs_;
snr[0].callfromregs = (DWORD)KERNEL_CallFrom16_p_regs_;
GET_CS(snr[0].seg);
snr[1].prefix = 0x66;
snr[1].pushbp = 0x55;
snr[1].pushl = 0x68;
snr[1].realfun = (DWORD)SNOOP16_Return;
snr[1].lcall = 0x9a;
snr[1].callfromregs = (DWORD)CallFrom16_p_regs_;
snr[1].callfromregs = (DWORD)KERNEL_CallFrom16_p_regs_;
GET_CS(snr[1].seg);
}
while (*dll) {
......
......@@ -26,85 +26,84 @@ DECLARE_DEBUG_CHANNEL(system)
DECLARE_DEBUG_CHANNEL(thunk)
extern LONG CallTo16RegisterShort(const CONTEXT86 *context, INT offset);
extern LONG CallTo16RegisterLong(const CONTEXT86 *context, INT offset);
/* List of the 16-bit callback functions. This list is used */
/* by the build program to generate the file if1632/callto16.S */
/* ### start build ### */
extern LONG CALLBACK CallTo16_sreg_(const CONTEXT86 *context, INT offset);
extern LONG CALLBACK CallTo16_lreg_(const CONTEXT86 *context, INT offset);
extern WORD CALLBACK CallTo16_word_ (FARPROC16);
extern LONG CALLBACK CallTo16_long_ (FARPROC16);
extern WORD CALLBACK CallTo16_word_w (FARPROC16,WORD);
extern WORD CALLBACK CallTo16_word_l (FARPROC16,LONG);
extern LONG CALLBACK CallTo16_long_l (FARPROC16,LONG);
extern WORD CALLBACK CallTo16_word_ww (FARPROC16,WORD,WORD);
extern WORD CALLBACK CallTo16_word_wl (FARPROC16,WORD,LONG);
extern WORD CALLBACK CallTo16_word_ll (FARPROC16,LONG,LONG);
extern LONG CALLBACK CallTo16_long_ll (FARPROC16,LONG,LONG);
extern WORD CALLBACK CallTo16_word_www (FARPROC16,WORD,WORD,WORD);
extern WORD CALLBACK CallTo16_word_wwl (FARPROC16,WORD,WORD,LONG);
extern WORD CALLBACK CallTo16_word_wlw (FARPROC16,WORD,LONG,WORD);
extern LONG CALLBACK CallTo16_long_wwl (FARPROC16,WORD,WORD,LONG);
extern LONG CALLBACK CallTo16_long_lll (FARPROC16,LONG,LONG,LONG);
extern WORD CALLBACK CallTo16_word_llwl (FARPROC16,LONG,LONG,WORD,LONG);
extern WORD CALLBACK CallTo16_word_lwll (FARPROC16,LONG,WORD,LONG,LONG);
extern WORD CALLBACK CallTo16_word_lwww (FARPROC16,LONG,WORD,WORD,WORD);
extern WORD CALLBACK CallTo16_word_wlww (FARPROC16,WORD,LONG,WORD,WORD);
extern WORD CALLBACK CallTo16_word_wwll (FARPROC16,WORD,WORD,LONG,LONG);
extern WORD CALLBACK CallTo16_word_wwwl (FARPROC16,WORD,WORD,WORD,LONG);
extern LONG CALLBACK CallTo16_long_wwwl (FARPROC16,WORD,WORD,WORD,LONG);
extern WORD CALLBACK CallTo16_word_llll (FARPROC16,LONG,LONG,LONG,LONG);
extern LONG CALLBACK CallTo16_long_llll (FARPROC16,LONG,LONG,LONG,LONG);
extern WORD CALLBACK CallTo16_word_wllwl(FARPROC16,WORD,LONG,LONG,WORD,LONG);
extern WORD CALLBACK CallTo16_word_lwwww(FARPROC16,LONG,WORD,WORD,WORD,WORD);
extern LONG CALLBACK CallTo16_long_lwwll(FARPROC16,LONG,WORD,WORD,LONG,LONG);
extern WORD CALLBACK CallTo16_word_wwlll(FARPROC16,WORD,WORD,LONG,LONG,LONG);
extern WORD CALLBACK CallTo16_word_wwwww(FARPROC16,WORD,WORD,WORD,WORD,WORD);
extern WORD CALLBACK CallTo16_word_lwlll(FARPROC16,LONG,WORD,LONG,LONG,LONG);
extern LONG CALLBACK CallTo16_long_lwlll(FARPROC16,LONG,WORD,LONG,LONG,LONG);
extern LONG CALLBACK CallTo16_long_lllll(FARPROC16,LONG,LONG,LONG,LONG,LONG);
extern LONG CALLBACK CallTo16_long_llllll(FARPROC16,LONG,LONG,LONG,LONG,LONG,
LONG);
extern LONG CALLBACK CallTo16_long_lllllll(FARPROC16,LONG,LONG,LONG,LONG,LONG,
LONG,LONG);
extern WORD CALLBACK CallTo16_word_llwwlll(FARPROC16,LONG,LONG,WORD,WORD,LONG,
LONG,LONG);
extern LONG CALLBACK CallTo16_word_lwwlllll(FARPROC16,LONG,WORD,WORD,LONG,LONG,
extern WORD THUNK_CallTo16_word_ (FARPROC16);
extern LONG THUNK_CallTo16_long_ (FARPROC16);
extern WORD THUNK_CallTo16_word_w (FARPROC16,WORD);
extern WORD THUNK_CallTo16_word_l (FARPROC16,LONG);
extern LONG THUNK_CallTo16_long_l (FARPROC16,LONG);
extern WORD THUNK_CallTo16_word_ww (FARPROC16,WORD,WORD);
extern WORD THUNK_CallTo16_word_wl (FARPROC16,WORD,LONG);
extern WORD THUNK_CallTo16_word_ll (FARPROC16,LONG,LONG);
extern LONG THUNK_CallTo16_long_ll (FARPROC16,LONG,LONG);
extern WORD THUNK_CallTo16_word_www (FARPROC16,WORD,WORD,WORD);
extern WORD THUNK_CallTo16_word_wwl (FARPROC16,WORD,WORD,LONG);
extern WORD THUNK_CallTo16_word_wlw (FARPROC16,WORD,LONG,WORD);
extern LONG THUNK_CallTo16_long_wwl (FARPROC16,WORD,WORD,LONG);
extern LONG THUNK_CallTo16_long_lll (FARPROC16,LONG,LONG,LONG);
extern WORD THUNK_CallTo16_word_llwl (FARPROC16,LONG,LONG,WORD,LONG);
extern WORD THUNK_CallTo16_word_lwll (FARPROC16,LONG,WORD,LONG,LONG);
extern WORD THUNK_CallTo16_word_lwww (FARPROC16,LONG,WORD,WORD,WORD);
extern WORD THUNK_CallTo16_word_wlww (FARPROC16,WORD,LONG,WORD,WORD);
extern WORD THUNK_CallTo16_word_wwll (FARPROC16,WORD,WORD,LONG,LONG);
extern WORD THUNK_CallTo16_word_wwwl (FARPROC16,WORD,WORD,WORD,LONG);
extern LONG THUNK_CallTo16_long_wwwl (FARPROC16,WORD,WORD,WORD,LONG);
extern WORD THUNK_CallTo16_word_llll (FARPROC16,LONG,LONG,LONG,LONG);
extern LONG THUNK_CallTo16_long_llll (FARPROC16,LONG,LONG,LONG,LONG);
extern WORD THUNK_CallTo16_word_wllwl(FARPROC16,WORD,LONG,LONG,WORD,LONG);
extern WORD THUNK_CallTo16_word_lwwww(FARPROC16,LONG,WORD,WORD,WORD,WORD);
extern LONG THUNK_CallTo16_long_lwwll(FARPROC16,LONG,WORD,WORD,LONG,LONG);
extern WORD THUNK_CallTo16_word_wwlll(FARPROC16,WORD,WORD,LONG,LONG,LONG);
extern WORD THUNK_CallTo16_word_wwwww(FARPROC16,WORD,WORD,WORD,WORD,WORD);
extern WORD THUNK_CallTo16_word_lwlll(FARPROC16,LONG,WORD,LONG,LONG,LONG);
extern LONG THUNK_CallTo16_long_lwlll(FARPROC16,LONG,WORD,LONG,LONG,LONG);
extern LONG THUNK_CallTo16_long_lllll(FARPROC16,LONG,LONG,LONG,LONG,LONG);
extern LONG THUNK_CallTo16_long_llllll(FARPROC16,LONG,LONG,LONG,LONG,LONG,LONG);
extern LONG THUNK_CallTo16_long_lllllll(FARPROC16,LONG,LONG,LONG,LONG,LONG,LONG,LONG);
extern WORD THUNK_CallTo16_word_llwwlll(FARPROC16,LONG,LONG,WORD,WORD,LONG,LONG,LONG);
extern LONG THUNK_CallTo16_word_lwwlllll(FARPROC16,LONG,WORD,WORD,LONG,LONG,
LONG,LONG,LONG);
extern LONG CALLBACK CallTo16_long_llllllll(FARPROC16,LONG,LONG,LONG,LONG,LONG,
extern LONG THUNK_CallTo16_long_llllllll(FARPROC16,LONG,LONG,LONG,LONG,LONG,
LONG,LONG,LONG);
extern LONG CALLBACK CallTo16_long_lllllllll(FARPROC16,LONG,LONG,LONG,LONG,
extern LONG THUNK_CallTo16_long_lllllllll(FARPROC16,LONG,LONG,LONG,LONG,
LONG,LONG,LONG,LONG,LONG);
extern LONG CALLBACK CallTo16_long_llllllllll(FARPROC16,LONG,LONG,LONG,LONG,
extern LONG THUNK_CallTo16_long_llllllllll(FARPROC16,LONG,LONG,LONG,LONG,
LONG,LONG,LONG,LONG,LONG,LONG);
extern LONG CALLBACK CallTo16_long_lllllllllll(FARPROC16,LONG,LONG,LONG,LONG,
extern LONG THUNK_CallTo16_long_lllllllllll(FARPROC16,LONG,LONG,LONG,LONG,
LONG,LONG,LONG,LONG,LONG,LONG,
LONG);
extern LONG CALLBACK CallTo16_long_llllllllllll(FARPROC16,LONG,LONG,LONG,LONG,
extern LONG THUNK_CallTo16_long_llllllllllll(FARPROC16,LONG,LONG,LONG,LONG,
LONG,LONG,LONG,LONG,LONG,LONG,
LONG,LONG);
extern LONG CALLBACK CallTo16_long_lwwllwlllllw(FARPROC16,LONG,WORD,WORD,LONG,
extern LONG THUNK_CallTo16_long_lwwllwlllllw(FARPROC16,LONG,WORD,WORD,LONG,
LONG,WORD,LONG,LONG,LONG,LONG,
LONG,WORD);
extern LONG CALLBACK CallTo16_long_lllllllllllll(FARPROC16,LONG,LONG,LONG,LONG,
extern LONG THUNK_CallTo16_long_lllllllllllll(FARPROC16,LONG,LONG,LONG,LONG,
LONG,LONG,LONG,LONG,LONG,LONG,
LONG,LONG,LONG);
extern LONG CALLBACK CallTo16_long_llllllllllllll(FARPROC16,LONG,LONG,LONG,
extern LONG THUNK_CallTo16_long_llllllllllllll(FARPROC16,LONG,LONG,LONG,
LONG,LONG,LONG,LONG,LONG,
LONG,LONG,LONG,LONG,LONG,
LONG);
extern LONG CALLBACK CallTo16_word_lwwwwlwwwwllll(FARPROC16,LONG,WORD,WORD,
extern LONG THUNK_CallTo16_word_lwwwwlwwwwllll(FARPROC16,LONG,WORD,WORD,
WORD,WORD,LONG,WORD,WORD,
WORD,WORD,LONG,LONG,LONG,
LONG);
extern LONG CALLBACK CallTo16_long_lllllllllllllll(FARPROC16,LONG,LONG,LONG,
extern LONG THUNK_CallTo16_long_lllllllllllllll(FARPROC16,LONG,LONG,LONG,
LONG,LONG,LONG,LONG,LONG,
LONG,LONG,LONG,LONG,LONG,
LONG,LONG);
extern LONG CALLBACK CallTo16_long_llllllllllllllll(FARPROC16,LONG,LONG,LONG,
extern LONG THUNK_CallTo16_long_llllllllllllllll(FARPROC16,LONG,LONG,LONG,
LONG,LONG,LONG,LONG,LONG,
LONG,LONG,LONG,LONG,LONG,
LONG,LONG,LONG);
extern void THUNK_CallFrom16_p_long_wwwll();
/* ### stop build ### */
......@@ -144,38 +143,36 @@ static BOOL WINAPI THUNK_WOWCallback16Ex( FARPROC16,DWORD,DWORD,
LPVOID,LPDWORD );
static BOOL THUNK_ThunkletInit( void );
extern void CallFrom16_p_long_wwwll(void);
/* Callbacks function table for the emulator */
static const CALLBACKS_TABLE CALLBACK_EmulatorTable =
{
(void *)CallTo16_sreg_, /* CallRegisterShortProc */
(void *)CallTo16_lreg_, /* CallRegisterLongProc */
(void*)CallFrom16_p_long_wwwll, /* CallFrom16WndProc */
THUNK_CallWndProc16, /* CallWndProc */
(void *)CallTo16_long_lwwll, /* CallDriverProc */
(void *)CallTo16_word_wwlll, /* CallDriverCallback */
(void *)CallTo16_word_wwlll, /* CallTimeFuncProc */
(void *)CallTo16_word_w, /* CallWindowsExitProc */
(void *)CallTo16_word_lwww, /* CallWordBreakProc */
(void *)CallTo16_word_ww, /* CallBootAppProc */
(void *)CallTo16_word_www, /* CallLoadAppSegProc */
(void *)CallTo16_word_www, /* CallLocalNotifyFunc */
(void *)CallTo16_word_www, /* CallResourceHandlerProc */
(void *)CallTo16_long_l, /* CallWOWCallbackProc */
THUNK_WOWCallback16Ex, /* CallWOWCallback16Ex */
(void *)CallTo16_long_ll, /* CallUTProc */
(void *)CallTo16_long_l, /* CallASPIPostProc */
(void *)CallTo16_word_lwll, /* CallDrvControlProc */
(void *)CallTo16_word_lwlll, /* CallDrvEnableProc */
(void *)CallTo16_word_llll, /* CallDrvEnumDFontsProc */
(void *)CallTo16_word_lwll, /* CallDrvEnumObjProc */
(void *)CallTo16_word_lwwlllll, /* CallDrvOutputProc */
(void *)CallTo16_long_lwlll, /* CallDrvRealizeProc */
(void *)CallTo16_word_lwwwwlwwwwllll, /* CallDrvStretchBltProc */
(void *)CallTo16_long_lwwllwlllllw, /* CallDrvExtTextOutProc */
(void *)CallTo16_word_llwwlll, /* CallDrvGetCharWidth */
(void *)CallTo16_word_ww /* CallDrvAbortProc */
(void *)CallTo16RegisterShort, /* CallRegisterShortProc */
(void *)CallTo16RegisterLong, /* CallRegisterLongProc */
(void*)THUNK_CallFrom16_p_long_wwwll, /* CallFrom16WndProc */
THUNK_CallWndProc16, /* CallWndProc */
(void *)THUNK_CallTo16_long_lwwll, /* CallDriverProc */
(void *)THUNK_CallTo16_word_wwlll, /* CallDriverCallback */
(void *)THUNK_CallTo16_word_wwlll, /* CallTimeFuncProc */
(void *)THUNK_CallTo16_word_w, /* CallWindowsExitProc */
(void *)THUNK_CallTo16_word_lwww, /* CallWordBreakProc */
(void *)THUNK_CallTo16_word_ww, /* CallBootAppProc */
(void *)THUNK_CallTo16_word_www, /* CallLoadAppSegProc */
(void *)THUNK_CallTo16_word_www, /* CallLocalNotifyFunc */
(void *)THUNK_CallTo16_word_www, /* CallResourceHandlerProc */
(void *)THUNK_CallTo16_long_l, /* CallWOWCallbackProc */
THUNK_WOWCallback16Ex, /* CallWOWCallback16Ex */
(void *)THUNK_CallTo16_long_ll, /* CallUTProc */
(void *)THUNK_CallTo16_long_l, /* CallASPIPostProc */
(void *)THUNK_CallTo16_word_lwll, /* CallDrvControlProc */
(void *)THUNK_CallTo16_word_lwlll, /* CallDrvEnableProc */
(void *)THUNK_CallTo16_word_llll, /* CallDrvEnumDFontsProc */
(void *)THUNK_CallTo16_word_lwll, /* CallDrvEnumObjProc */
(void *)THUNK_CallTo16_word_lwwlllll, /* CallDrvOutputProc */
(void *)THUNK_CallTo16_long_lwlll, /* CallDrvRealizeProc */
(void *)THUNK_CallTo16_word_lwwwwlwwwwllll, /* CallDrvStretchBltProc */
(void *)THUNK_CallTo16_long_lwwllwlllllw, /* CallDrvExtTextOutProc */
(void *)THUNK_CallTo16_word_llwwlll, /* CallDrvGetCharWidth */
(void *)THUNK_CallTo16_word_ww /* CallDrvAbortProc */
};
......@@ -307,7 +304,7 @@ static LRESULT WINAPI THUNK_CallWndProc16( WNDPROC16 proc, HWND16 hwnd,
args[3] = msg;
args[4] = hwnd;
ret = CallTo16_sreg_( &context, 5 * sizeof(WORD) );
ret = CallTo16RegisterShort( &context, 5 * sizeof(WORD) );
if (offset) STACK16_POP( teb, offset );
WIN_RestoreWndsLock(iWndsLocks);
......@@ -322,7 +319,7 @@ static LRESULT WINAPI THUNK_CallWndProc16( WNDPROC16 proc, HWND16 hwnd,
INT16 WINAPI THUNK_EnumObjects16( HDC16 hdc, INT16 nObjType,
GOBJENUMPROC16 func, LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo16_word_ll );
DECL_THUNK( thunk, func, THUNK_CallTo16_word_ll );
return EnumObjects16( hdc, nObjType, (GOBJENUMPROC16)&thunk, lParam );
}
......@@ -333,7 +330,7 @@ INT16 WINAPI THUNK_EnumObjects16( HDC16 hdc, INT16 nObjType,
INT16 WINAPI THUNK_EnumFonts16( HDC16 hdc, LPCSTR lpFaceName,
FONTENUMPROC16 func, LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo16_word_llwl );
DECL_THUNK( thunk, func, THUNK_CallTo16_word_llwl );
return EnumFonts16( hdc, lpFaceName, (FONTENUMPROC16)&thunk, lParam );
}
......@@ -343,7 +340,7 @@ INT16 WINAPI THUNK_EnumFonts16( HDC16 hdc, LPCSTR lpFaceName,
BOOL16 WINAPI THUNK_EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
MFENUMPROC16 func, LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo16_word_wllwl );
DECL_THUNK( thunk, func, THUNK_CallTo16_word_wllwl );
return EnumMetaFile16( hdc, hmf, (MFENUMPROC16)&thunk, lParam );
}
......@@ -354,7 +351,7 @@ BOOL16 WINAPI THUNK_EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
INT16 WINAPI THUNK_EnumFontFamilies16( HDC16 hdc, LPCSTR lpszFamily,
FONTENUMPROC16 func, LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo16_word_llwl );
DECL_THUNK( thunk, func, THUNK_CallTo16_word_llwl );
return EnumFontFamilies16(hdc, lpszFamily, (FONTENUMPROC16)&thunk, lParam);
}
......@@ -366,7 +363,7 @@ INT16 WINAPI THUNK_EnumFontFamiliesEx16( HDC16 hdc, LPLOGFONT16 lpLF,
FONTENUMPROCEX16 func, LPARAM lParam,
DWORD reserved )
{
DECL_THUNK( thunk, func, CallTo16_word_llwl );
DECL_THUNK( thunk, func, THUNK_CallTo16_word_llwl );
return EnumFontFamiliesEx16( hdc, lpLF, (FONTENUMPROCEX16)&thunk,
lParam, reserved );
}
......@@ -378,7 +375,7 @@ INT16 WINAPI THUNK_EnumFontFamiliesEx16( HDC16 hdc, LPLOGFONT16 lpLF,
void WINAPI THUNK_LineDDA16( INT16 nXStart, INT16 nYStart, INT16 nXEnd,
INT16 nYEnd, LINEDDAPROC16 func, LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo16_word_wwl );
DECL_THUNK( thunk, func, THUNK_CallTo16_word_wwl );
LineDDA16( nXStart, nYStart, nXEnd, nYEnd, (LINEDDAPROC16)&thunk, lParam );
}
......@@ -388,7 +385,7 @@ void WINAPI THUNK_LineDDA16( INT16 nXStart, INT16 nYStart, INT16 nXEnd,
*/
BOOL16 WINAPI THUNK_EnumWindows16( WNDENUMPROC16 func, LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo16_word_wl );
DECL_THUNK( thunk, func, THUNK_CallTo16_word_wl );
return EnumWindows16( (WNDENUMPROC16)&thunk, lParam );
}
......@@ -399,7 +396,7 @@ BOOL16 WINAPI THUNK_EnumWindows16( WNDENUMPROC16 func, LPARAM lParam )
BOOL16 WINAPI THUNK_EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo16_word_wl );
DECL_THUNK( thunk, func, THUNK_CallTo16_word_wl );
return EnumChildWindows16( parent, (WNDENUMPROC16)&thunk, lParam );
}
......@@ -410,7 +407,7 @@ BOOL16 WINAPI THUNK_EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
BOOL16 WINAPI THUNK_EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo16_word_wl );
DECL_THUNK( thunk, func, THUNK_CallTo16_word_wl );
return EnumTaskWindows16( hTask, (WNDENUMPROC16)&thunk, lParam );
}
......@@ -420,7 +417,7 @@ BOOL16 WINAPI THUNK_EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
*/
INT16 WINAPI THUNK_EnumProps16( HWND16 hwnd, PROPENUMPROC16 func )
{
DECL_THUNK( thunk, func, CallTo16_word_wlw );
DECL_THUNK( thunk, func, THUNK_CallTo16_word_wlw );
return EnumProps16( hwnd, (PROPENUMPROC16)&thunk );
}
......@@ -433,7 +430,7 @@ BOOL16 WINAPI THUNK_GrayString16( HDC16 hdc, HBRUSH16 hbr,
INT16 cch, INT16 x, INT16 y,
INT16 cx, INT16 cy )
{
DECL_THUNK( thunk, func, CallTo16_word_wlw );
DECL_THUNK( thunk, func, THUNK_CallTo16_word_wlw );
if (!func)
return GrayString16( hdc, hbr, NULL, lParam, cch, x, y, cx, cy );
else
......@@ -449,7 +446,7 @@ FARPROC16 WINAPI THUNK_SetWindowsHook16( INT16 id, HOOKPROC16 proc )
{
HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) );
HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
THUNK *thunk = THUNK_Alloc( (FARPROC16)proc, (RELAY)CallTo16_long_wwl );
THUNK *thunk = THUNK_Alloc( (FARPROC16)proc, (RELAY)THUNK_CallTo16_long_wwl );
if (!thunk) return 0;
return (FARPROC16)SetWindowsHookEx16( id, (HOOKPROC16)thunk, hInst, hTask);
}
......@@ -475,7 +472,7 @@ BOOL16 WINAPI THUNK_UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
HHOOK WINAPI THUNK_SetWindowsHookEx16( INT16 id, HOOKPROC16 proc,
HINSTANCE16 hInst, HTASK16 hTask )
{
THUNK *thunk = THUNK_Alloc( (FARPROC16)proc, (RELAY)CallTo16_long_wwl );
THUNK *thunk = THUNK_Alloc( (FARPROC16)proc, (RELAY)THUNK_CallTo16_long_wwl );
if (!thunk) return 0;
return SetWindowsHookEx16( id, (HOOKPROC16)thunk, hInst, hTask );
}
......@@ -518,7 +515,7 @@ BOOL16 WINAPI THUNK_SetDCHook( HDC16 hdc, FARPROC16 proc, DWORD dwHookData )
thunk = NULL;
else if (proc != defDCHookProc)
{
thunk = THUNK_Alloc( proc, (RELAY)CallTo16_word_wwll );
thunk = THUNK_Alloc( proc, (RELAY)THUNK_CallTo16_word_wwll );
if (!thunk) return FALSE;
}
else thunk = (THUNK *)DCHook16;
......@@ -560,7 +557,7 @@ DWORD WINAPI THUNK_GetDCHook( HDC16 hdc, FARPROC16 *phookProc )
*/
FARPROC16 WINAPI THUNK_SetTaskSignalProc( HTASK16 hTask, FARPROC16 proc )
{
THUNK *thunk = THUNK_Alloc( proc, (RELAY)CallTo16_word_wwwww );
THUNK *thunk = THUNK_Alloc( proc, (RELAY)THUNK_CallTo16_word_wwwww );
if ( !thunk ) return NULL;
thunk = (THUNK*)SetTaskSignalProc( hTask, (FARPROC16)thunk );
......@@ -580,7 +577,7 @@ static DWORD CALLBACK THUNK_StartThread16( LPVOID threadArgs )
DWORD param = ((DWORD *)threadArgs)[1];
HeapFree( GetProcessHeap(), 0, threadArgs );
return CallTo16_long_l( start, param );
return THUNK_CallTo16_long_l( start, param );
}
HANDLE WINAPI THUNK_CreateThread16( SECURITY_ATTRIBUTES *sa, DWORD stack,
FARPROC16 start, SEGPTR param,
......@@ -621,61 +618,61 @@ static BOOL WINAPI THUNK_WOWCallback16Ex(
args[i] = ((DWORD*)xargs)[cbArgs-i-1];
}
switch (cbArgs) {
case 0: ret = CallTo16_long_(proc);break;
case 1: ret = CallTo16_long_l(proc,args[0]);break;
case 2: ret = CallTo16_long_ll(proc,args[0],args[1]);break;
case 3: ret = CallTo16_long_lll(proc,args[0],args[1],args[2]);break;
case 4: ret = CallTo16_long_llll(proc,args[0],args[1],args[2],args[3]);
case 0: ret = THUNK_CallTo16_long_(proc);break;
case 1: ret = THUNK_CallTo16_long_l(proc,args[0]);break;
case 2: ret = THUNK_CallTo16_long_ll(proc,args[0],args[1]);break;
case 3: ret = THUNK_CallTo16_long_lll(proc,args[0],args[1],args[2]);break;
case 4: ret = THUNK_CallTo16_long_llll(proc,args[0],args[1],args[2],args[3]);
break;
case 5: ret = CallTo16_long_lllll(proc,args[0],args[1],args[2],args[3],
case 5: ret = THUNK_CallTo16_long_lllll(proc,args[0],args[1],args[2],args[3],
args[4]
);
break;
case 6: ret = CallTo16_long_llllll(proc,args[0],args[1],args[2],args[3],
case 6: ret = THUNK_CallTo16_long_llllll(proc,args[0],args[1],args[2],args[3],
args[4],args[5]
);
break;
case 7: ret = CallTo16_long_lllllll(proc,args[0],args[1],args[2],args[3],
case 7: ret = THUNK_CallTo16_long_lllllll(proc,args[0],args[1],args[2],args[3],
args[4],args[5],args[6]
);
break;
case 8: ret = CallTo16_long_llllllll(proc,args[0],args[1],args[2],args[3],
case 8: ret = THUNK_CallTo16_long_llllllll(proc,args[0],args[1],args[2],args[3],
args[4],args[5],args[6],args[7]
);
break;
case 9: ret = CallTo16_long_lllllllll(proc,args[0],args[1],args[2],args[3],
case 9: ret = THUNK_CallTo16_long_lllllllll(proc,args[0],args[1],args[2],args[3],
args[4],args[5],args[6],args[7],args[8]
);
break;
case 10:ret = CallTo16_long_llllllllll(proc,args[0],args[1],args[2],args[3],
case 10:ret = THUNK_CallTo16_long_llllllllll(proc,args[0],args[1],args[2],args[3],
args[4],args[5],args[6],args[7],args[8],args[9]
);
break;
case 11:ret = CallTo16_long_lllllllllll(proc,args[0],args[1],args[2],
case 11:ret = THUNK_CallTo16_long_lllllllllll(proc,args[0],args[1],args[2],
args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]
);
break;
case 12:ret = CallTo16_long_llllllllllll(proc,args[0],args[1],args[2],
case 12:ret = THUNK_CallTo16_long_llllllllllll(proc,args[0],args[1],args[2],
args[3],args[4],args[5],args[6],args[7],args[8],args[9],
args[10],args[11]
);
break;
case 13:ret = CallTo16_long_lllllllllllll(proc,args[0],args[1],args[2],
case 13:ret = THUNK_CallTo16_long_lllllllllllll(proc,args[0],args[1],args[2],
args[3],args[4],args[5],args[6],args[7],args[8],args[9],
args[10],args[11],args[12]
);
break;
case 14:ret = CallTo16_long_llllllllllllll(proc,args[0],args[1],args[2],
case 14:ret = THUNK_CallTo16_long_llllllllllllll(proc,args[0],args[1],args[2],
args[3],args[4],args[5],args[6],args[7],args[8],args[9],
args[10],args[11],args[12],args[13]
);
break;
case 15:ret = CallTo16_long_lllllllllllllll(proc,args[0],args[1],args[2],
case 15:ret = THUNK_CallTo16_long_lllllllllllllll(proc,args[0],args[1],args[2],
args[3],args[4],args[5],args[6],args[7],args[8],args[9],
args[10],args[11],args[12],args[13],args[14]
);
break;
case 16:ret = CallTo16_long_llllllllllllllll(proc,args[0],args[1],args[2],
case 16:ret = THUNK_CallTo16_long_llllllllllllllll(proc,args[0],args[1],args[2],
args[3],args[4],args[5],args[6],args[7],args[8],args[9],
args[10],args[11],args[12],args[13],args[14],args[15]
);
......@@ -712,7 +709,7 @@ static VOID WINAPI THUNK_CallMouseEventProc( FARPROC16 proc,
SI_reg(&context) = LOWORD( dwExtraInfo );
DI_reg(&context) = HIWORD( dwExtraInfo );
CallTo16_sreg_( &context, 0 );
CallTo16RegisterShort( &context, 0 );
}
VOID WINAPI THUNK_MOUSE_Enable( FARPROC16 proc )
{
......@@ -774,7 +771,7 @@ static VOID WINAPI THUNK_CallKeybdEventProc( FARPROC16 proc,
SI_reg(&context) = LOWORD( dwExtraInfo );
DI_reg(&context) = HIWORD( dwExtraInfo );
CallTo16_sreg_( &context, 0 );
CallTo16RegisterShort( &context, 0 );
}
VOID WINAPI THUNK_KEYBOARD_Enable( FARPROC16 proc, LPBYTE lpKeyState )
{
......@@ -834,7 +831,7 @@ static void THUNK_CallSystemTimerProc( FARPROC16 proc, WORD timer )
return;
}
CallTo16_sreg_( &context, 0 );
CallTo16RegisterShort( &context, 0 );
/* FIXME: This does not work if the signal occurs while this thread
is currently in 16-bit code. With the current structure
......@@ -890,7 +887,7 @@ void THUNK_InitCallout(void)
#define GETADDR( var, name, thk ) \
*(FARPROC *)&Callout.##var = (FARPROC) \
THUNK_Alloc( WIN32_GetProcAddress16( hModule, name ), \
(RELAY)CallTo16_##thk )
(RELAY)THUNK_CallTo16_##thk )
GETADDR( PeekMessage16, "PeekMessage", word_lwwww );
GETADDR( GetMessage16, "GetMessage", word_lwww );
......@@ -1006,7 +1003,7 @@ UINT WINAPI ThunkConnect16(
void WINAPI C16ThkSL(CONTEXT86 *context)
{
extern void CallFrom16_t_long_(void);
extern void CallFrom16Thunk(void);
LPBYTE stub = PTR_SEG_TO_LIN(EAX_reg(context)), x = stub;
WORD cs, ds;
GET_CS(cs);
......@@ -1031,7 +1028,7 @@ void WINAPI C16ThkSL(CONTEXT86 *context)
*x++ = 0x55;
*x++ = 0x66; *x++ = 0x52;
*x++ = 0x66; *x++ = 0x9A; *((DWORD *)x)++ = (DWORD)CallFrom16_t_long_;
*x++ = 0x66; *x++ = 0x9A; *((DWORD *)x)++ = (DWORD)CallFrom16Thunk;
*((WORD *)x)++ = cs;
/* Jump to the stub code just created */
......@@ -1056,7 +1053,7 @@ void WINAPI C16ThkSL01(CONTEXT86 *context)
struct ThunkDataSL16 *SL16 = PTR_SEG_TO_LIN(EDX_reg(context));
struct ThunkDataSL *td = SL16->fpData;
extern void CallFrom16_t_long_(void);
extern void CallFrom16Thunk(void);
DWORD procAddress = (DWORD)GetProcAddress16(GetModuleHandle16("KERNEL"), 631);
WORD cs;
GET_CS(cs);
......@@ -1086,7 +1083,7 @@ void WINAPI C16ThkSL01(CONTEXT86 *context)
*x++ = 0x55;
*x++ = 0x66; *x++ = 0x52;
*x++ = 0x66; *x++ = 0x9A; *((DWORD *)x)++ = (DWORD)CallFrom16_t_long_;
*x++ = 0x66; *x++ = 0x9A; *((DWORD *)x)++ = (DWORD)CallFrom16Thunk;
*((WORD *)x)++ = cs;
/* Jump to the stub code just created */
......
/*
* Win16 built-in DLLs definitions
*
* Copyright 1999 Ulrich Weigand
*/
#ifndef __WINE_BUILTIN16_H
#define __WINE_BUILTIN16_H
#include "windef.h"
#include "pshpack1.h"
typedef struct
{
WORD pushw_bp; /* pushw %bp */
BYTE pushl; /* pushl $target */
DWORD target;
BYTE lcall; /* lcall __FLATCS__:relay */
DWORD relay;
WORD flatcs;
} STD_ENTRYPOINT16;
typedef struct
{
WORD movw_ax; /* movw $<ax>, %ax */
WORD ax;
WORD movw_dx; /* movw $<dx>, %dx */
WORD dx;
WORD lret; /* lret $<args> */
WORD args;
WORD nopnop; /* nop; nop */
} RET_ENTRYPOINT16;
typedef union
{
STD_ENTRYPOINT16 std;
RET_ENTRYPOINT16 ret;
} ENTRYPOINT16;
#define EP_STD( target, relay ) \
{ std: { 0x5566, 0x68, (DWORD)(target), 0x9a, (DWORD)(relay), __FLATCS__ } }
#define EP_RET( retval, nargs ) \
{ ret: { 0xb866, LOWORD(retval), 0xba66, HIWORD(retval), \
(nargs)? 0xca66 : 0xcb66, (nargs)? (nargs) : 0x9090, 0x9090 } }
#include "poppack.h"
typedef struct
{
const char *name; /* DLL name */
void *module_start; /* 32-bit address of the module data */
int module_size; /* Size of the module data */
const BYTE *code_start; /* 32-bit address of DLL code */
const BYTE *data_start; /* 32-bit address of DLL data */
} WIN16_DESCRIPTOR;
extern void RELAY_Unimplemented16(void);
#endif /* __WINE_BUILTIN16_H */
......@@ -20,53 +20,53 @@ extern int (*IF1632_CallLargeStack)( int (*func)(void), void *arg );
typedef struct
{
LONG (CALLBACK *CallRegisterShortProc)( CONTEXT86 *, INT );
LONG (CALLBACK *CallRegisterLongProc)( CONTEXT86 *, INT );
VOID (CALLBACK *CallFrom16WndProc)(void);
LRESULT (CALLBACK *CallWndProc)( WNDPROC16, HWND16, UINT16,
LONG (*CallRegisterShortProc)( CONTEXT86 *, INT );
LONG (*CallRegisterLongProc)( CONTEXT86 *, INT );
VOID (*CallFrom16WndProc)(void);
LRESULT (*CallWndProc)( WNDPROC16, HWND16, UINT16,
WPARAM16, LPARAM );
LRESULT (CALLBACK *CallDriverProc)( DRIVERPROC16, DWORD, HDRVR16,
LRESULT (*CallDriverProc)( DRIVERPROC16, DWORD, HDRVR16,
UINT16, LPARAM, LPARAM );
LRESULT (CALLBACK *CallDriverCallback)( FARPROC16, HANDLE16, UINT16,
LRESULT (*CallDriverCallback)( FARPROC16, HANDLE16, UINT16,
DWORD, LPARAM, LPARAM );
LRESULT (CALLBACK *CallTimeFuncProc)( FARPROC16, WORD, UINT16,
LRESULT (*CallTimeFuncProc)( FARPROC16, WORD, UINT16,
DWORD, LPARAM, LPARAM );
INT16 (CALLBACK *CallWindowsExitProc)( FARPROC16, INT16 );
INT16 (CALLBACK *CallWordBreakProc)( EDITWORDBREAKPROC16, SEGPTR, INT16,
INT16 (*CallWindowsExitProc)( FARPROC16, INT16 );
INT16 (*CallWordBreakProc)( EDITWORDBREAKPROC16, SEGPTR, INT16,
INT16, INT16 );
VOID (CALLBACK *CallBootAppProc)( FARPROC16, HANDLE16, HFILE16 );
WORD (CALLBACK *CallLoadAppSegProc)( FARPROC16, HANDLE16, HFILE16, WORD );
WORD (CALLBACK *CallLocalNotifyFunc)( FARPROC16, WORD, HLOCAL16, WORD );
HGLOBAL16 (CALLBACK *CallResourceHandlerProc)( FARPROC16, HGLOBAL16, HMODULE16, HRSRC16 );
DWORD (CALLBACK *CallWOWCallbackProc)( FARPROC16, DWORD );
BOOL (CALLBACK *CallWOWCallback16Ex)( FARPROC16, DWORD, DWORD, LPVOID,
VOID (*CallBootAppProc)( FARPROC16, HANDLE16, HFILE16 );
WORD (*CallLoadAppSegProc)( FARPROC16, HANDLE16, HFILE16, WORD );
WORD (*CallLocalNotifyFunc)( FARPROC16, WORD, HLOCAL16, WORD );
HGLOBAL16 (*CallResourceHandlerProc)( FARPROC16, HGLOBAL16, HMODULE16, HRSRC16 );
DWORD (*CallWOWCallbackProc)( FARPROC16, DWORD );
BOOL (*CallWOWCallback16Ex)( FARPROC16, DWORD, DWORD, LPVOID,
LPDWORD );
DWORD (CALLBACK *CallUTProc)( FARPROC16, DWORD, DWORD );
LRESULT (CALLBACK *CallASPIPostProc)( FARPROC16, SEGPTR );
DWORD (*CallUTProc)( FARPROC16, DWORD, DWORD );
LRESULT (*CallASPIPostProc)( FARPROC16, SEGPTR );
/* Following are the graphics driver callbacks */
WORD (CALLBACK *CallDrvControlProc)( FARPROC16, SEGPTR, WORD,
WORD (*CallDrvControlProc)( FARPROC16, SEGPTR, WORD,
SEGPTR, SEGPTR );
WORD (CALLBACK *CallDrvEnableProc)( FARPROC16, SEGPTR, WORD, SEGPTR,
WORD (*CallDrvEnableProc)( FARPROC16, SEGPTR, WORD, SEGPTR,
SEGPTR, SEGPTR );
WORD (CALLBACK *CallDrvEnumDFontsProc)( FARPROC16, SEGPTR, SEGPTR,
WORD (*CallDrvEnumDFontsProc)( FARPROC16, SEGPTR, SEGPTR,
FARPROC16, SEGPTR );
WORD (CALLBACK *CallDrvEnumObjProc)( FARPROC16, SEGPTR, WORD, FARPROC16,
WORD (*CallDrvEnumObjProc)( FARPROC16, SEGPTR, WORD, FARPROC16,
SEGPTR );
WORD (CALLBACK *CallDrvOutputProc)( FARPROC16, SEGPTR, WORD, WORD, SEGPTR,
WORD (*CallDrvOutputProc)( FARPROC16, SEGPTR, WORD, WORD, SEGPTR,
SEGPTR, SEGPTR, SEGPTR, SEGPTR );
DWORD (CALLBACK *CallDrvRealizeProc)( FARPROC16, SEGPTR, WORD, SEGPTR,
DWORD (*CallDrvRealizeProc)( FARPROC16, SEGPTR, WORD, SEGPTR,
SEGPTR, SEGPTR );
WORD (CALLBACK *CallDrvStretchBltProc)( FARPROC16, SEGPTR, WORD, WORD,
WORD (*CallDrvStretchBltProc)( FARPROC16, SEGPTR, WORD, WORD,
WORD, WORD, SEGPTR, WORD, WORD,
WORD, WORD, DWORD, SEGPTR, SEGPTR,
SEGPTR );
DWORD (CALLBACK *CallDrvExtTextOutProc)( FARPROC16, SEGPTR, WORD, WORD,
DWORD (*CallDrvExtTextOutProc)( FARPROC16, SEGPTR, WORD, WORD,
SEGPTR, SEGPTR, INT16, SEGPTR,
SEGPTR, SEGPTR, SEGPTR, SEGPTR,
WORD );
WORD (CALLBACK *CallDrvGetCharWidthProc)( FARPROC16, SEGPTR, SEGPTR, WORD,
WORD (*CallDrvGetCharWidthProc)( FARPROC16, SEGPTR, SEGPTR, WORD,
WORD, SEGPTR, SEGPTR, SEGPTR );
BOOL16 (CALLBACK *CallDrvAbortProc)( FARPROC16, HDC16, INT16 );
BOOL16 (*CallDrvAbortProc)( FARPROC16, HDC16, INT16 );
} CALLBACKS_TABLE;
extern const CALLBACKS_TABLE *Callbacks;
......
......@@ -235,7 +235,7 @@ HGLOBAL16 NE_LoadPEResource( NE_MODULE *pModule, WORD type, LPVOID bits, DWORD s
/* if1632/builtin.c */
extern BOOL BUILTIN_Init(void);
extern HMODULE16 BUILTIN_LoadModule( LPCSTR name, BOOL force );
extern LPCSTR BUILTIN_GetEntryPoint16( WORD cs, WORD ip, WORD *pOrd );
extern LPCSTR BUILTIN_GetEntryPoint16( WORD cs, WORD ip, LPSTR name, WORD *pOrd );
/* relay32/builtin.c */
extern HMODULE BUILTIN32_LoadImage(LPCSTR name, OFSTRUCT *ofs);
......
......@@ -32,17 +32,20 @@ typedef struct _STACK32FRAME
typedef struct
{
STACK32FRAME *frame32; /* 00 32-bit frame from last CallTo16() */
DWORD ebp; /* 04 full 32-bit content of ebp */
WORD mutex_count; /* 08 Win16Mutex recursion count */
WORD fs; /* 0a fs */
WORD entry_ip; /* 0c ip of entry point */
WORD ds; /* 0e ds */
WORD entry_cs; /* 10 cs of entry point */
WORD es; /* 12 es */
DWORD entry_point; /* 14 32-bit entry point to call */
WORD bp; /* 18 16-bit bp */
WORD ip; /* 1a return address */
WORD cs; /* 1c */
DWORD edx; /* 04 saved registers */
DWORD ecx; /* 08 */
DWORD ebp; /* 0c */
WORD ds; /* 10 */
WORD es; /* 12 */
WORD fs; /* 14 */
WORD gs; /* 16 */
DWORD relay; /* 18 address of argument relay stub */
DWORD entry_ip; /* 1c ip of entry point */
DWORD entry_cs; /* 20 cs of entry point */
DWORD entry_point; /* 24 API entry point to call, reused as mutex count */
WORD bp; /* 28 16-bit stack frame chain */
WORD ip; /* 2a return address */
WORD cs; /* 2c */
} STACK16FRAME;
#include "poppack.h"
......
......@@ -21,7 +21,7 @@ DEFAULT_DEBUG_CHANNEL(relay)
/**********************************************************************
* CALLBACK_CallWndProc
*/
static LRESULT WINAPI CALLBACK_CallWndProc( WNDPROC16 proc, HWND16 hwnd,
static LRESULT CALLBACK_CallWndProc( WNDPROC16 proc, HWND16 hwnd,
UINT16 msg, WPARAM16 wParam,
LPARAM lParam )
{
......@@ -36,225 +36,149 @@ static LRESULT WINAPI CALLBACK_CallWndProc( WNDPROC16 proc, HWND16 hwnd,
return retvalue;
}
/**********************************************************************
* CALLBACK_CallRegisterProc
*/
static LONG WINAPI CALLBACK_CallRegisterProc( CONTEXT86 *context, INT offset)
static LONG CALLBACK_CallRegisterProc( CONTEXT86 *context, INT offset)
{
ERR("Cannot call a register proc in Winelib\n" );
assert( FALSE );
return 0;
}
/**********************************************************************
* CALLBACK_CallDriverProc
*/
static LRESULT WINAPI CALLBACK_CallDriverProc( DRIVERPROC16 proc, DWORD dwId,
HDRVR16 hdrvr, UINT16 msg,
LPARAM lp1, LPARAM lp2 )
static LRESULT CALLBACK_CallDriverProc( DRIVERPROC16 proc, DWORD dwId,
HDRVR16 hdrvr, UINT16 msg,
LPARAM lp1, LPARAM lp2 )
{
return proc( dwId, hdrvr, msg, lp1, lp2 );
ERR("Cannot call a 16-bit driver proc in Winelib\n" );
assert( FALSE );
return 0;
}
/**********************************************************************
* CALLBACK_CallDriverCallback
*/
static LRESULT WINAPI CALLBACK_CallDriverCallback( FARPROC16 proc,
HANDLE16 hDev, UINT16 msg,
DWORD dwUser, LPARAM lp1,
LPARAM lp2 )
static LRESULT CALLBACK_CallDriverCallback( FARPROC16 proc,
HANDLE16 hDev, UINT16 msg,
DWORD dwUser, LPARAM lp1,
LPARAM lp2 )
{
return proc( hDev, msg, dwUser, lp1, lp2 );
ERR("Cannot call a 16-bit driver proc in Winelib\n" );
assert( FALSE );
return 0;
}
/**********************************************************************
* CALLBACK_CallTimeFuncProc
*/
static LRESULT WINAPI CALLBACK_CallTimeFuncProc( FARPROC16 proc, WORD id,
static LRESULT CALLBACK_CallTimeFuncProc( FARPROC16 proc, WORD id,
UINT16 msg, DWORD dwUser,
LPARAM lp1, LPARAM lp2 )
{
return proc( id, msg, dwUser, lp1, lp2 );
}
/**********************************************************************
* CALLBACK_CallWindowsExitProc
*/
static INT16 WINAPI CALLBACK_CallWindowsExitProc( FARPROC16 proc, INT16 type)
static INT16 CALLBACK_CallWindowsExitProc( FARPROC16 proc, INT16 type)
{
return proc( type );
}
/**********************************************************************
* CALLBACK_CallWordBreakProc
*/
static INT16 WINAPI CALLBACK_CallWordBreakProc( EDITWORDBREAKPROC16 proc,
static INT16 CALLBACK_CallWordBreakProc( EDITWORDBREAKPROC16 proc,
SEGPTR text, INT16 word,
INT16 len, INT16 action )
{
return proc( (LPSTR)text, word, len, action );
}
/**********************************************************************
* CALLBACK_CallBootAppProc
*/
static void WINAPI CALLBACK_CallBootAppProc( FARPROC16 proc, HANDLE16 module,
static void CALLBACK_CallBootAppProc( FARPROC16 proc, HANDLE16 module,
HFILE16 file )
{
proc( module, file );
ERR("Cannot call a 16-bit self-load handler in Winelib\n" );
assert( FALSE );
return;
}
/**********************************************************************
* CALLBACK_CallLoadAppSegProc
*/
static WORD WINAPI CALLBACK_CallLoadAppSegProc( FARPROC16 proc,
static WORD CALLBACK_CallLoadAppSegProc( FARPROC16 proc,
HANDLE16 module, HFILE16 file,
WORD seg )
{
return proc( module, file, seg );
ERR("Cannot call a 16-bit self-load handler in Winelib\n" );
assert( FALSE );
return 0;
}
/**********************************************************************
* CALLBACK_CallLocalNotifyFunc
*/
static WORD WINAPI CALLBACK_CallLocalNotifyFunc( FARPROC16 proc,
WORD wMsg, HLOCAL16 hMem,
WORD wArg )
static WORD CALLBACK_CallLocalNotifyFunc( FARPROC16 proc,
WORD wMsg, HLOCAL16 hMem, WORD wArg )
{
return proc( wMsg, hMem, wArg );
ERR("Cannot call a 16-bit notification handler in Winelib\n" );
assert( FALSE );
return 0;
}
/**********************************************************************
* CALLBACK_CallResourceHandlerProc
*/
static HGLOBAL16 WINAPI CALLBACK_CallResourceHandlerProc( FARPROC16 proc,
HGLOBAL16 hMemObj,
HMODULE16 hModule,
HRSRC16 hRsrc )
static HGLOBAL16 CALLBACK_CallResourceHandlerProc( FARPROC16 proc,
HGLOBAL16 hMemObj,
HMODULE16 hModule,
HRSRC16 hRsrc )
{
ERR("Cannot call a 16-bit resource handler in Winelib\n" );
assert( FALSE );
return 0;
}
/**********************************************************************
* CALLBACK_CallASPIPostProc
*/
static LRESULT WINAPI CALLBACK_CallASPIPostProc( FARPROC16 proc, SEGPTR ptr )
static LRESULT CALLBACK_CallASPIPostProc( FARPROC16 proc, SEGPTR ptr )
{
return proc( ptr );
}
/**********************************************************************
* CALLBACK_CallWOWCallbackProc
*/
static DWORD WINAPI CALLBACK_CallWOWCallbackProc( FARPROC16 proc, DWORD dw )
static DWORD CALLBACK_CallWOWCallbackProc( FARPROC16 proc, DWORD dw )
{
return proc( dw );
ERR("Cannot call a WOW thunk proc in Winelib\n" );
assert( FALSE );
return 0;
}
/**********************************************************************
* CALLBACK_CallWOWCallback16Ex
*
* WCB16_MAX_CBARGS (16) is the maximum number of args.
*
* Can call functions using CDECL or PASCAL calling conventions. The CDECL
* ones are reversed (not 100% sure about that).
*/
static BOOL WINAPI CALLBACK_CallWOWCallback16Ex(
FARPROC16 proc, DWORD dwFlags, DWORD cbArgs, LPVOID xargs,LPDWORD pdwret
) {
LPDWORD args = (LPDWORD)xargs;
DWORD ret,i;
if (dwFlags == WCB16_CDECL) {
/* swap the arguments */
args = HeapAlloc(GetProcessHeap(),0,cbArgs*sizeof(DWORD));
for (i=0;i<cbArgs;i++)
args[i] = ((DWORD*)xargs)[cbArgs-i-1];
}
switch (cbArgs) {
case 0: ret = proc();break;
case 1: ret = proc(args[0]);break;
case 2: ret = proc(args[0],args[1]);break;
case 3: ret = proc(args[0],args[1],args[2]);break;
case 4: ret = proc(args[0],args[1],args[2],args[3]);break;
case 5: ret = proc(args[0],args[1],args[2],args[3],args[4]);break;
case 6: ret = proc(args[0],args[1],args[2],args[3],args[4],args[5]);
break;
case 7: ret = proc(args[0],args[1],args[2],args[3],args[4],args[5],
args[6]
);
break;
case 8: ret = proc(args[0],args[1],args[2],args[3],args[4],args[5],
args[6],args[7]
);
break;
case 9: ret = proc(args[0],args[1],args[2],args[3],args[4],args[5],
args[6],args[7],args[8]
);
break;
case 10:ret = proc(args[0],args[1],args[2],args[3],args[4],args[5],
args[6],args[7],args[8],args[9]
);
break;
case 11:ret = proc(args[0],args[1],args[2],args[3],args[4],args[5],
args[6],args[7],args[8],args[9],args[10]
);
break;
case 12:ret = proc(args[0],args[1],args[2],args[3],args[4],args[5],
args[6],args[7],args[8],args[9],args[10],args[11]
);
break;
case 13:ret = proc(args[0],args[1],args[2],args[3],args[4],args[5],
args[6],args[7],args[8],args[9],args[10],args[11],
args[12]
);
break;
case 14:ret = proc(args[0],args[1],args[2],args[3],args[4],args[5],
args[6],args[7],args[8],args[9],args[10],args[11],
args[12],args[13]
);
break;
case 15:ret = proc(args[0],args[1],args[2],args[3],args[4],args[5],
args[6],args[7],args[8],args[9],args[10],args[11],
args[12],args[13],args[14]
);
break;
case 16:ret = proc(args[0],args[1],args[2],args[3],args[4],args[5],
args[6],args[7],args[8],args[9],args[10],args[11],
args[12],args[13],args[14],args[15]
);
break;
default:
WARN("(%ld) arguments not supported.\n",cbArgs);
if (dwFlags == WCB16_CDECL)
HeapFree(GetProcessHeap(),0,args);
return FALSE;
}
if (dwFlags == WCB16_CDECL)
HeapFree(GetProcessHeap(),0,args);
if (pdwret)
*pdwret = ret;
return TRUE;
static BOOL CALLBACK_CallWOWCallback16Ex( FARPROC16 proc, DWORD dwFlags,
DWORD cbArgs, LPVOID xargs, LPDWORD pdwret )
{
ERR("Cannot call a WOW thunk proc in Winelib\n" );
assert( FALSE );
return 0;
}
/**********************************************************************
* CALLBACK_CallUTProc
*/
static DWORD WINAPI CALLBACK_CallUTProc( FARPROC16 proc, DWORD w1, DWORD w2 )
static DWORD CALLBACK_CallUTProc( FARPROC16 proc, DWORD w1, DWORD w2 )
{
ERR("Cannot call a UT thunk proc in Winelib\n" );
assert( FALSE );
......
......@@ -27,12 +27,8 @@ extern int (*INSTR_IsRelay)( const void *addr );
static int is_relay_addr( const void *addr )
{
extern char CallFrom16_Start, CallFrom16_End, CALLTO16_Start, CALLTO16_End;
return ((((char *)addr >= &CallFrom16_Start) &&
((char *)addr < &CallFrom16_End)) ||
(((char *)addr >= &CALLTO16_Start) &&
((char *)addr < &CALLTO16_End)));
extern char Call16_Start, Call16_End;
return ((char *)addr >= &Call16_Start) && ((char *)addr < &Call16_End);
}
/***********************************************************************
......
Makefile
advapi32.c
avifil32.c
advapi32.spec.c
avifil32.spec.c
call32.s
comctl32.c
comdlg32.c
crtdll.c
dciman32.c
ddraw.c
dinput.c
dplay.c
dplayx.c
dsound.c
gdi32.c
imagehlp.c
imm32.c
kernel32.c
lz32.c
mcianim.c
mciavi.c
mcicda.c
mciseq.c
mciwave.c
mpr.c
msacm32.c
msnet32.c
msvfw32.c
ntdll.c
ole32.c
oleaut32.c
olecli32.c
oledlg.c
olesvr32.c
psapi.c
rasapi32.c
shell32.c
tapi32.c
user32.c
version.c
w32skrnl.c
winmm.c
winspool.c
wnaspi32.c
wow32.c
wsock32.c
comctl32.spec.c
comdlg32.spec.c
crtdll.spec.c
dciman32.spec.c
ddraw.spec.c
dinput.spec.c
dplay.spec.c
dplayx.spec.c
dsound.spec.c
gdi32.spec.c
imagehlp.spec.c
imm32.spec.c
kernel32.spec.c
lz32.spec.c
mcianim.spec.c
mciavi.spec.c
mcicda.spec.c
mciseq.spec.c
mciwave.spec.c
mpr.spec.c
msacm32.spec.c
msnet32.spec.c
msvfw32.spec.c
ntdll.spec.c
ole32.spec.c
oleaut32.spec.c
olecli32.spec.c
oledlg.spec.c
olesvr32.spec.c
psapi.spec.c
rasapi32.spec.c
shell32.spec.c
tapi32.spec.c
user32.spec.c
version.spec.c
w32skrnl.spec.c
winmm.spec.c
winspool.spec.c
wnaspi32.spec.c
wow32.spec.c
wsock32.spec.c
......@@ -5,7 +5,7 @@ SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = relay32
DLLS = \
SPEC_SRCS = \
advapi32.spec \
avifil32.spec \
comctl32.spec \
......@@ -56,30 +56,14 @@ C_SRCS = \
snoop.c \
utthunk.c
SPEC_FILES = $(DLLS:.spec=.c)
EXTRA_OBJS = $(DLLS:.spec=.o)
GEN_ASM_SRCS = \
call32.s
.SUFFIXES: .spec
.spec.c:
$(BUILD) -o $@ -spec $<
all: checkbuild $(MODULE).o
all: $(MODULE).o
@MAKE_RULES@
$(SPEC_FILES): $(BUILD)
$(EXTRA_OBJS): $(TOPSRCDIR)/include/builtin32.h
call32.s: $(BUILD)
$(BUILD) -o $@ -call32
clean::
$(RM) $(SPEC_FILES)
### Dependencies:
......@@ -204,14 +204,10 @@ VOID WINAPI RestoreThunkLock(DWORD mutex_count)
*/
VOID SYSLEVEL_ReleaseWin16Lock(VOID)
{
DWORD count;
/* entry_point is never used again once the entry point has
been called. Thus we re-use it to hold the Win16Lock count */
ReleaseThunkLock(&count);
if (count > 0xffff)
ERR("Win16Mutex recursion count too large!\n");
CURRENT_STACK16->mutex_count = (WORD)count;
ReleaseThunkLock(&CURRENT_STACK16->entry_point);
}
/************************************************************************
......@@ -219,12 +215,7 @@ VOID SYSLEVEL_ReleaseWin16Lock(VOID)
*/
VOID SYSLEVEL_RestoreWin16Lock(VOID)
{
DWORD count = CURRENT_STACK16->mutex_count;
if (!count)
ERR("Win16Mutex recursion count is zero!\n");
RestoreThunkLock(count);
RestoreThunkLock(CURRENT_STACK16->entry_point);
}
/************************************************************************
......
......@@ -3,6 +3,7 @@
* Copyright 1995 Martin von Loewis
* Copyright 1995, 1996, 1997 Alexandre Julliard
* Copyright 1997 Eric Youngdale
* Copyright 1999 Ulrich Weigand
*/
#include <assert.h>
......@@ -18,6 +19,7 @@
#include "neexe.h"
#include "selectors.h"
#include "stackframe.h"
#include "builtin16.h"
#include "thread.h"
#ifdef NEED_UNDERSCORE_PREFIX
......@@ -176,6 +178,12 @@ static int debugging = 1;
/* Offset of register relative to the start of the CONTEXT struct */
#define CONTEXTOFFSET(reg) STRUCTOFFSET(CONTEXT86,reg)
/* Offset of register relative to the start of the STACK16FRAME struct */
#define STACK16OFFSET(reg) STRUCTOFFSET(STACK16FRAME,reg)
/* Offset of register relative to the start of the STACK32FRAME struct */
#define STACK32OFFSET(reg) STRUCTOFFSET(STACK32FRAME,reg)
/* Offset of the stack pointer relative to %fs:(0) */
#define STACKOFFSET (STRUCTOFFSET(TEB,cur_stack))
......@@ -815,19 +823,19 @@ static int StoreVariableCode( unsigned char *buffer, int size, ORDDEF *odp )
* Dump a byte stream into the assembly code.
*/
static void DumpBytes( FILE *outfile, const unsigned char *data, int len,
const char *section, const char *label_start )
const char *label )
{
int i;
if (section) fprintf( outfile, "\t%s\n", section );
if (label_start) fprintf( outfile, "%s:\n", label_start );
fprintf( outfile, "\nstatic BYTE %s[] = \n{", label );
for (i = 0; i < len; i++)
{
if (!(i & 0x0f)) fprintf( outfile, "\t.byte " );
if (!(i & 0x0f)) fprintf( outfile, "\n " );
fprintf( outfile, "%d", *data++ );
if (i < len - 1)
fprintf( outfile, "%c", ((i & 0x0f) != 0x0f) ? ',' : '\n' );
if (i < len - 1) fprintf( outfile, ", " );
}
fprintf( outfile, "\n" );
fprintf( outfile, "\n};\n" );
}
......@@ -865,6 +873,7 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
buffer = xmalloc( 0x10000 );
pModule = (NE_MODULE *)buffer;
memset( pModule, 0, sizeof(*pModule) );
pModule->magic = IMAGE_OS2_SIGNATURE;
pModule->count = 1;
pModule->next = 0;
......@@ -1024,7 +1033,7 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
/* Dump the module content */
DumpBytes( outfile, (char *)pModule, (int)pstr - (int)pModule,
".data", "Module_Start" );
"Module" );
return (int)pstr - (int)pModule;
}
......@@ -1258,6 +1267,28 @@ static int BuildSpec32File( char * specfile, FILE *outfile )
return 0;
}
/*******************************************************************
* Spec16TypeCompare
*/
static int Spec16TypeCompare( const void *e1, const void *e2 )
{
const ORDDEF *odp1 = *(const ORDDEF **)e1;
const ORDDEF *odp2 = *(const ORDDEF **)e2;
int type1 = (odp1->type == TYPE_CDECL) ? 0
: (odp1->type == TYPE_REGISTER) ? 3
: (odp1->type == TYPE_PASCAL_16) ? 1 : 2;
int type2 = (odp2->type == TYPE_CDECL) ? 0
: (odp2->type == TYPE_REGISTER) ? 3
: (odp2->type == TYPE_PASCAL_16) ? 1 : 2;
int retval = type1 - type2;
if ( !retval )
retval = strcmp( odp1->u.func.arg_types, odp2->u.func.arg_types );
return retval;
}
/*******************************************************************
* BuildSpec16File
......@@ -1266,18 +1297,89 @@ static int BuildSpec32File( char * specfile, FILE *outfile )
*/
static int BuildSpec16File( char * specfile, FILE *outfile )
{
ORDDEF *odp;
int i;
ORDDEF *odp, **typelist;
int i, j, k;
int code_offset, data_offset, module_size;
unsigned char *data;
/* File header */
fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n\n",
specfile );
fprintf( outfile, "#define __FLATCS__ 0x%04x\n", Code_Selector );
fprintf( outfile, "#include \"builtin16.h\"\n\n" );
data = (unsigned char *)xmalloc( 0x10000 );
memset( data, 0, 16 );
data_offset = 16;
fprintf( outfile, "/* File generated automatically; do not edit! */\n" );
fprintf( outfile, "\t.text\n" );
fprintf( outfile, "Code_Start:\n" );
/* Build sorted list of all argument types, without duplicates */
typelist = (ORDDEF **)calloc( Limit+1, sizeof(ORDDEF *) );
odp = OrdinalDefinitions;
for (i = j = 0; i <= Limit; i++, odp++)
{
switch (odp->type)
{
case TYPE_REGISTER:
case TYPE_CDECL:
case TYPE_PASCAL:
case TYPE_PASCAL_16:
case TYPE_STUB:
typelist[j++] = odp;
default:
break;
}
}
qsort( typelist, j, sizeof(ORDDEF *), Spec16TypeCompare );
i = k = 0;
while ( i < j )
{
typelist[k++] = typelist[i++];
while ( i < j && Spec16TypeCompare( typelist + i, typelist + k-1 ) == 0 )
i++;
}
/* Output CallFrom16 profiles needed by this .spec file */
fprintf( outfile, "\n/* ### start build ### */\n" );
for ( i = 0; i < k; i++ )
fprintf( outfile, "extern void %s_CallFrom16_%s_%s_%s();\n",
DLLName,
(typelist[i]->type == TYPE_CDECL) ? "c" : "p",
(typelist[i]->type == TYPE_REGISTER) ? "regs" :
(typelist[i]->type == TYPE_PASCAL_16) ? "word" : "long",
typelist[i]->u.func.arg_types );
fprintf( outfile, "/* ### stop build ### */\n\n" );
/* Output the DLL functions prototypes */
odp = OrdinalDefinitions;
for (i = 0; i <= Limit; i++, odp++)
{
switch(odp->type)
{
case TYPE_REGISTER:
case TYPE_CDECL:
case TYPE_PASCAL:
case TYPE_PASCAL_16:
fprintf( outfile, "extern void %s();\n", odp->u.func.link_name );
break;
default:
break;
}
}
/* Output code segment */
fprintf( outfile, "\nstatic ENTRYPOINT16 Code_Segment[] = \n{\n" );
code_offset = 0;
odp = OrdinalDefinitions;
......@@ -1309,20 +1411,12 @@ static int BuildSpec16File( char * specfile, FILE *outfile )
break;
case TYPE_RETURN:
fprintf( outfile,"/* %s.%d */\n", DLLName, i);
fprintf( outfile,"\tmovw $%d,%%ax\n",LOWORD(odp->u.ret.ret_value));
fprintf( outfile,"\tmovw $%d,%%dx\n",HIWORD(odp->u.ret.ret_value));
fprintf( outfile,"\t.byte 0x66\n");
if (odp->u.ret.arg_size != 0)
fprintf( outfile, "\tlret $%d\n\n", odp->u.ret.arg_size);
else
{
fprintf( outfile, "\tlret\n");
fprintf( outfile, "\tnop\n");
fprintf( outfile, "\tnop\n\n");
}
fprintf( outfile, " /* %s.%d */ ", DLLName, i );
fprintf( outfile, "EP_RET( %d, %d ),\n",
odp->u.ret.ret_value, odp->u.ret.arg_size );
odp->offset = code_offset;
code_offset += 12; /* Assembly code is 12 bytes long */
code_offset += sizeof(ENTRYPOINT16);
break;
case TYPE_REGISTER:
......@@ -1330,20 +1424,17 @@ static int BuildSpec16File( char * specfile, FILE *outfile )
case TYPE_PASCAL:
case TYPE_PASCAL_16:
case TYPE_STUB:
fprintf( outfile, "/* %s.%d */\n", DLLName, i);
fprintf( outfile, "\tpushw %%bp\n" );
fprintf( outfile, "\tpushl $" PREFIX "%s\n",odp->u.func.link_name);
/* FreeBSD does not understand lcall, so do it the hard way */
fprintf( outfile, "\t.byte 0x9a\n" );
fprintf( outfile, "\t.long " PREFIX "CallFrom16_%s_%s_%s\n",
(odp->type == TYPE_CDECL) ? "c" : "p",
(odp->type == TYPE_REGISTER) ? "regs" :
(odp->type == TYPE_PASCAL_16) ? "word" : "long",
odp->u.func.arg_types );
fprintf( outfile, "\t.long 0x%08lx\n",
MAKELONG( Code_Selector, 0x9090 /* nop ; nop */ ) );
fprintf( outfile, " /* %s.%d */ ", DLLName, i );
fprintf( outfile, "EP_STD( %s, %s_CallFrom16_%s_%s_%s ),\n",
odp->u.func.link_name,
DLLName,
(odp->type == TYPE_CDECL) ? "c" : "p",
(odp->type == TYPE_REGISTER) ? "regs" :
(odp->type == TYPE_PASCAL_16) ? "word" : "long",
odp->u.func.arg_types );
odp->offset = code_offset;
code_offset += 16; /* Assembly code is 16 bytes long */
code_offset += sizeof(ENTRYPOINT16);
break;
default:
......@@ -1355,13 +1446,15 @@ static int BuildSpec16File( char * specfile, FILE *outfile )
if (!code_offset) /* Make sure the code segment is not empty */
{
fprintf( outfile, "\t.byte 0\n" );
code_offset++;
fprintf( outfile, " { },\n" );
code_offset += sizeof(ENTRYPOINT16);
}
fprintf( outfile, "};\n" );
/* Output data segment */
DumpBytes( outfile, data, data_offset, NULL, "Data_Start" );
DumpBytes( outfile, data, data_offset, "Data_Segment" );
/* Build the module */
......@@ -1369,16 +1462,14 @@ static int BuildSpec16File( char * specfile, FILE *outfile )
/* Output the DLL descriptor */
fprintf( outfile, "\t.text\n" );
fprintf( outfile, "DLLName:\t" STRING " \"%s\\0\"\n", DLLName );
fprintf( outfile, "\t.align 4\n" );
fprintf( outfile, "\t.globl " PREFIX "%s_Descriptor\n", DLLName );
fprintf( outfile, PREFIX "%s_Descriptor:\n", DLLName );
fprintf( outfile, "\t.long DLLName\n" ); /* Name */
fprintf( outfile, "\t.long Module_Start\n" ); /* Module start */
fprintf( outfile, "\t.long %d\n", module_size ); /* Module size */
fprintf( outfile, "\t.long Code_Start\n" ); /* Code start */
fprintf( outfile, "\t.long Data_Start\n" ); /* Data start */
fprintf( outfile, "\nWIN16_DESCRIPTOR %s_Descriptor = \n{\n", DLLName );
fprintf( outfile, " \"%s\",\n", DLLName );
fprintf( outfile, " Module,\n" );
fprintf( outfile, " sizeof(Module),\n" );
fprintf( outfile, " (BYTE *)Code_Segment,\n" );
fprintf( outfile, " (BYTE *)Data_Segment\n" );
fprintf( outfile, "};\n" );
return 0;
}
......@@ -1414,216 +1505,352 @@ static int BuildSpecFile( FILE *outfile, char *specname )
/*******************************************************************
* TransferArgs16To32
* BuildCallFrom16Func
*
* Get the arguments from the 16-bit stack and push them on the 32-bit stack.
* The 16-bit stack layout is:
* ... ...
* (bp+8) arg2
* (bp+6) arg1
* (bp+4) cs
* (bp+2) ip
* (bp) bp
* Build a 16-bit-to-Wine callback glue function. The syntax of the function
* profile is: call_type_xxxxx, where 'call' is the letter 'c' or 'p' for C or
* Pascal calling convention, 'type' is one of 'regs', 'word' or
* 'long' and each 'x' is an argument ('w'=word, 's'=signed word,
* 'l'=long, 'p'=linear pointer, 't'=linear pointer to null-terminated string,
* 'T'=segmented pointer to null-terminated string).
* For register functions, the arguments are ignored, but they are still
* removed from the stack upon return. !! FIXME !!
*
* This glue function contains only that part of the 16->32 thunk that is
* variable (depending on the type and number of arguments); the glue routine
* is part of a particular DLL and uses a routine provided by the core to
* perform those actions that do not depend on the argument type.
*
* The 16->32 glue routine consists of a main entry point (which must be part
* of the ELF .data section) and two auxillary routines (in the .text section).
* The main entry point pushes address of the 'Thunk' auxillary routine onto
* the stack and then jumps to the appropriate core CallFrom16... routine.
* Furthermore, at a fixed position relative to the main entry point, the
* function profile string is stored if relay debugging is active; this string
* will be consulted by the debugging routines in the core to correctly
* display the arguments.
*
* The core will perform the switch to 32-bit, and then call back to the
* 'Thunk' auxillary routine. This routine is expected to perform the
* following tasks:
* - modify the auxillary routine address in the STACK16FRAME to now
* point to the 'ThunkRet' routine
* - convert arguemnts and push them onto the 32-bit stack
* - call the 32-bit target routine
*
* After the target routine (and then the 'Thunk' routine) have returned,
* the core part will switch back to 16-bit, and finally jump to the
* 'ThunkRet' auxillary routine. This routine is expected to convert the
* return value if necessary (%eax -> %dx:%ax), and perform the appropriate
* return to the 16-bit caller (lret or lret $argsize).
*
* For 'cdecl' argn up to arg1 are reversed.
* In the case of a 'register' routine, there is no 'ThunkRet' auxillary
* routine, as the reloading of all registers and return to 16-bit code
* is done by the core routine. The number of arguments to be popped off
* the caller's stack must be returned (in %eax) by the 'Thunk' routine.
*
* NOTE: The generated routines contain only proper position-independent
* code and may thus be used within shared objects (e.g. libwine.so
* or elfdlls). The exception is the main entry point, which must
* contain absolute relocations but cannot yet use the GOT; thus
* this entry point is made part of the ELF .data section.
*/
static int TransferArgs16To32( FILE *outfile, char *args, int usecdecl )
static void BuildCallFrom16Func( FILE *outfile, char *profile, char *prefix )
{
int i, pos16, pos32;
char *xargs;
int i, pos, argsize = 0;
int short_ret = 0;
int reg_func = 0;
int usecdecl = 0;
char *args = profile + 7;
/* Copy the arguments */
/* Parse function type */
pos16 = 6; /* skip bp and return address */
pos32 = usecdecl ? -(strlen(args) * 4) : 0;
xargs = usecdecl ? args:args+strlen(args);
if (!strncmp( "c_", profile, 2 )) usecdecl = 1;
else if (strncmp( "p_", profile, 2 ))
{
fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
return;
}
for (i = strlen(args); i > 0; i--)
if (!strncmp( "word_", profile + 2, 5 )) short_ret = 1;
else if (!strncmp( "regs_", profile + 2, 5 )) reg_func = 1;
else if (strncmp( "long_", profile + 2, 5 ))
{
if (!usecdecl) {
pos32 -= 4;
xargs--;
fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
return;
}
for ( i = 0; args[i]; i++ )
switch ( args[i] )
{
case 'w': /* word */
case 's': /* s_word */
argsize += 2;
break;
case 'l': /* long or segmented pointer */
case 'T': /* segmented pointer to null-terminated string */
case 'p': /* linear pointer */
case 't': /* linear pointer to null-terminated string */
argsize += 4;
break;
}
switch(*xargs)
/*
* Build main entry point (in .data section)
*
* NOTE: If you change this, you must also change the retrieval of
* the profile string relative to the main entry point address
* (see BUILTIN_GetEntryPoint16 in if1632/builtin.c).
*/
fprintf( outfile, "\t.data\n" );
fprintf( outfile, "\t.globl " PREFIX "%s_CallFrom16_%s\n", prefix, profile );
fprintf( outfile, PREFIX "%s_CallFrom16_%s:\n", prefix, profile );
fprintf( outfile, "\tpushl $.L%s_Thunk_%s\n", prefix, profile );
fprintf( outfile, "\tjmp " PREFIX "%s\n",
!reg_func? "CallFrom16" : "CallFrom16Register" );
if ( debugging )
fprintf( outfile, "\t" STRING " \"%s\\0\"\n", profile );
/*
* Build *Thunk* routine
*
* This routine gets called by the main CallFrom16 routine with
* registers set up as follows:
*
* STACK16FRAME is completely set up on the 16-bit stack
* DS, ES, SS: flat data segment
* FS: current TEB
* ESP: points to 32-bit stack
* EBP: points to ebp member of last STACK32FRAME
* EDX: points to current STACK16FRAME
* ECX: points to ldt_copy
*/
fprintf( outfile, "\t.text\n" );
fprintf( outfile, ".L%s_Thunk_%s:\n", prefix, profile );
if ( reg_func )
fprintf( outfile, "\tleal 4(%%esp), %%eax\n"
"\tpushl %%eax\n" );
else
fprintf( outfile, "\taddl $[.L%s_ThunkRet_%s - .L%s_Thunk_%s], %d(%%edx)\n",
prefix, profile, prefix, profile,
STACK16OFFSET(relay));
if ( !reg_func ) /* FIXME */
{
/* Copy the arguments */
pos = (usecdecl? argsize : 0) + sizeof( STACK16FRAME );
args = profile + 7;
for ( i = strlen(args)-1; i >= 0; i-- )
switch (args[i])
{
case 'w': /* word */
fprintf( outfile, "\tmovzwl %d(%%ebp),%%eax\n", pos16 );
fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n", pos32 );
pos16 += 2;
if ( usecdecl ) pos -= 2;
fprintf( outfile, "\tmovzwl %d(%%edx),%%eax\n", pos );
fprintf( outfile, "\tpushl %%eax\n" );
if ( !usecdecl ) pos += 2;
break;
case 's': /* s_word */
fprintf( outfile, "\tmovswl %d(%%ebp),%%eax\n", pos16 );
fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n", pos32 );
pos16 += 2;
if ( usecdecl ) pos -= 2;
fprintf( outfile, "\tmovswl %d(%%edx),%%eax\n", pos );
fprintf( outfile, "\tpushl %%eax\n" );
if ( !usecdecl ) pos += 2;
break;
case 'l': /* long or segmented pointer */
case 'T': /* segmented pointer to null-terminated string */
fprintf( outfile, "\tmovl %d(%%ebp),%%eax\n", pos16 );
fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n", pos32 );
pos16 += 4;
if ( usecdecl ) pos -= 4;
fprintf( outfile, "\tpushl %d(%%edx)\n", pos );
if ( !usecdecl ) pos += 4;
break;
case 'p': /* linear pointer */
case 't': /* linear pointer to null-terminated string */
if ( usecdecl ) pos -= 4;
/* Get the selector */
fprintf( outfile, "\tmovw %d(%%ebp),%%ax\n", pos16 + 2 );
fprintf( outfile, "\tmovzwl %d(%%edx),%%eax\n", pos + 2 );
/* Get the selector base */
fprintf( outfile, "\tandl $0xfff8,%%eax\n" );
fprintf( outfile, "\tmovl " PREFIX "ldt_copy(%%eax),%%eax\n" );
fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n", pos32 );
fprintf( outfile, "\tpushl (%%ecx,%%eax)\n" );
/* Add the offset */
fprintf( outfile, "\tmovzwl %d(%%ebp),%%eax\n", pos16 );
fprintf( outfile, "\taddl %%eax,%d(%%ebx)\n", pos32 );
pos16 += 4;
fprintf( outfile, "\tmovzwl %d(%%edx),%%eax\n", pos );
fprintf( outfile, "\taddl %%eax,(%%esp)\n" );
if ( !usecdecl ) pos += 4;
break;
default:
fprintf( stderr, "Unknown arg type '%c'\n", *xargs );
fprintf( stderr, "Unknown arg type '%c'\n", args[i] );
}
}
/* Call entry point */
fprintf( outfile, "\tcall *%d(%%edx)\n", STACK16OFFSET(entry_point) );
if ( reg_func )
fprintf( outfile, "\tmovl $%d, %%eax\n", argsize );
fprintf( outfile, "\tret\n" );
/*
* Build *ThunkRet* routine
*
* At this point, all registers are set up for return to 16-bit code.
* EAX contains the function return value.
* SS:SP point to the return address to the caller (on 16-bit stack).
*/
if ( !reg_func )
{
fprintf( outfile, ".L%s_ThunkRet_%s:\n", prefix, profile );
if ( !short_ret )
fprintf( outfile, "\tshldl $16, %%eax, %%edx\n" );
if ( !usecdecl && argsize )
{
fprintf( outfile, "\t.byte 0x66\n" );
fprintf( outfile, "\tlret $%d\n", argsize );
}
if (usecdecl) {
pos32 += 4;
xargs++;
else
{
fprintf( outfile, "\t.byte 0x66\n" );
fprintf( outfile, "\tlret\n" );
}
}
return pos16 - 6; /* Return the size of the 16-bit args */
fprintf( outfile, "\n" );
}
/*******************************************************************
* BuildContext16
* BuildCallTo16Func
*
* Build a Wine-to-16-bit callback glue function. As above, this glue
* routine will only contain the argument-type dependent part of the
* thunk; the rest will be done by a routine provided by the core.
*
* Prototypes for the CallTo16 functions:
* extern WORD PREFIX_CallTo16_word_xxx( FARPROC16 func, args... );
* extern LONG PREFIX_CallTo16_long_xxx( FARPROC16 func, args... );
*
* The main entry point of the glue routine simply performs a call to
* the proper core routine depending on the return type (WORD/LONG).
* Note that the core will never perform a return from this call; however,
* it will use the return address on the stack to access the other
* argument-type dependent parts of the thunk. (If relay debugging is
* active, the core routine will access the number of arguments stored
* in the code section immediately precending the main entry point).
*
* After the core routine has performed the switch to 16-bit code, it
* will call the argument-transfer routine provided by the glue code
* immediately after the main entry point. This routine is expected
* to transfer the arguments to the 16-bit stack, finish loading the
* register for 16-bit code (%ds and %es must be loaded from %ss),
* and call the 16-bit target.
*
* The target will return to a 16:16 return address provided by the core.
* The core will finalize the switch back to 32-bit and the return to
* the caller without additional support by the glue code. Note that
* the 32-bit arguments will not be popped off the stack (hence the
* CallTo... routine must *not* be declared WINAPI/CALLBACK).
*
* Build the context structure on the 32-bit stack.
*/
static void BuildContext16( FILE *outfile )
static void BuildCallTo16Func( FILE *outfile, char *profile, char *prefix )
{
/* Store the registers */
fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
CONTEXTOFFSET(Eax) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovl %%ecx,%d(%%ebx)\n",
CONTEXTOFFSET(Ecx) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovl %%edx,%d(%%ebx)\n",
CONTEXTOFFSET(Edx) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovl %%esi,%d(%%ebx)\n",
CONTEXTOFFSET(Esi) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovl %%edi,%d(%%ebx)\n",
CONTEXTOFFSET(Edi) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovl -24(%%ebp),%%eax\n" ); /* Get %ebx from stack*/
fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
CONTEXTOFFSET(Ebx) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovzwl -10(%%ebp),%%eax\n" ); /* Get %ds from stack*/
fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
CONTEXTOFFSET(SegDs) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovzwl -6(%%ebp),%%eax\n" ); /* Get %es from stack*/
fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
CONTEXTOFFSET(SegEs) - sizeof(CONTEXT86) );
fprintf( outfile, "\tpushfl\n" );
fprintf( outfile, "\tpopl %d(%%ebx)\n",
CONTEXTOFFSET(EFlags) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovl -20(%%ebp),%%eax\n" ); /* Get %ebp from stack */
fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
CONTEXTOFFSET(Ebp) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovzwl 2(%%ebp),%%eax\n" ); /* Get %ip from stack */
fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
CONTEXTOFFSET(Eip) - sizeof(CONTEXT86) );
fprintf( outfile, "\tleal 2(%%ebp),%%eax\n" ); /* Get initial %sp */
fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
CONTEXTOFFSET(Esp) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovzwl 4(%%ebp),%%eax\n" ); /* Get %cs from stack */
fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
CONTEXTOFFSET(SegCs) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovzwl -14(%%ebp),%%eax\n" ); /* Get %fs from stack */
fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
CONTEXTOFFSET(SegFs) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovw %%gs,%%ax\n" );
fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
CONTEXTOFFSET(SegGs) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovw %%ss,%%ax\n" );
fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
CONTEXTOFFSET(SegSs) - sizeof(CONTEXT86) );
#if 0
fprintf( outfile, "\tfsave %d(%%ebx)\n",
CONTEXTOFFSET(FloatSave) - sizeof(CONTEXT86) );
char *args = profile + 5;
int pos, short_ret = 0;
if (!strncmp( "word_", profile, 5 )) short_ret = 1;
else if (strncmp( "long_", profile, 5 ))
{
fprintf( stderr, "Invalid function name '%s'.\n", profile );
exit(1);
}
if ( debugging )
{
/* Number of arguments (for relay debugging) */
fprintf( outfile, "\n\t.align 4\n" );
fprintf( outfile, "\t.long %d\n", strlen(args) );
}
/* Main entry point */
#ifdef USE_STABS
fprintf( outfile, ".stabs \"%s_CallTo16_%s:F1\",36,0,0," PREFIX "%s_CallTo16_%s\n",
prefix, profile, prefix, profile);
#endif
}
fprintf( outfile, "\t.globl " PREFIX "%s_CallTo16_%s\n", prefix, profile );
fprintf( outfile, PREFIX "%s_CallTo16_%s:\n", prefix, profile );
if ( short_ret )
fprintf( outfile, "\tcall " PREFIX "CallTo16Word\n" );
else
fprintf( outfile, "\tcall " PREFIX "CallTo16Long\n" );
/*
* The core routine will call here with registers set up as follows:
*
* SS:SP points to the 16-bit stack
* SS:BP points to the bp member of last STACK16FRAME
* EDX points to the current STACK32FRAME
* ECX contains the 16:16 return address
* FS contains the last 16-bit %fs value
*/
/*******************************************************************
* RestoreContext16
*
* Restore the registers from the context structure.
*/
static void RestoreContext16( FILE *outfile )
{
/* Get the 32-bit stack pointer */
fprintf( outfile, "\tleal -%d(%%ebp),%%ebx\n",
STRUCTOFFSET(STACK32FRAME,ebp) );
/* Remove everything up to (including) the return address
* from the 16-bit stack */
fprintf( outfile, "\tmovl %d(%%ebx),%%eax\n",
CONTEXTOFFSET(SegSs) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovw %%ax,%%ss\n" );
fprintf( outfile, "\tmovl %d(%%ebx),%%esp\n",
CONTEXTOFFSET(Esp) - sizeof(CONTEXT86) );
fprintf( outfile, "\taddl $4,%%esp\n" ); /* Remove return address */
/* Restore the registers */
fprintf( outfile, "\tmovl %d(%%ebx),%%ecx\n",
CONTEXTOFFSET(Ecx) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovl %d(%%ebx),%%edx\n",
CONTEXTOFFSET(Edx) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovl %d(%%ebx),%%esi\n",
CONTEXTOFFSET(Esi) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovl %d(%%ebx),%%edi\n",
CONTEXTOFFSET(Edi) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovl %d(%%ebx),%%ebp\n",
CONTEXTOFFSET(Ebp) - sizeof(CONTEXT86) );
fprintf( outfile, "\tpushw %d(%%ebx)\n", /* Push new cs */
CONTEXTOFFSET(SegCs) - sizeof(CONTEXT86) );
fprintf( outfile, "\tpushw %d(%%ebx)\n", /* Push new ip */
CONTEXTOFFSET(Eip) - sizeof(CONTEXT86) );
fprintf( outfile, "\tpushl %d(%%ebx)\n", /* Push new ds */
CONTEXTOFFSET(SegDs) - sizeof(CONTEXT86) );
fprintf( outfile, "\tpushl %d(%%ebx)\n", /* Push new es */
CONTEXTOFFSET(SegEs) - sizeof(CONTEXT86) );
fprintf( outfile, "\tpushl %d(%%ebx)\n", /* Push new fs */
CONTEXTOFFSET(SegFs) - sizeof(CONTEXT86) );
fprintf( outfile, "\tpushl %d(%%ebx)\n",
CONTEXTOFFSET(EFlags) - sizeof(CONTEXT86) );
fprintf( outfile, "\tpopfl\n" );
fprintf( outfile, "\tmovl %d(%%ebx),%%eax\n",
CONTEXTOFFSET(Eax) - sizeof(CONTEXT86) );
fprintf( outfile, "\tmovl %d(%%ebx),%%ebx\n",
CONTEXTOFFSET(Ebx) - sizeof(CONTEXT86) );
fprintf( outfile, "\tpopl %%fs\n" ); /* Set fs */
fprintf( outfile, "\tpopl %%es\n" ); /* Set es */
fprintf( outfile, "\tpopl %%ds\n" ); /* Set ds */
/* Transfer the arguments */
pos = STACK32OFFSET(args) + 4; /* first arg is target address */
while (*args)
{
switch (*args++)
{
case 'w': /* word */
fprintf( outfile, "\tpushw %d(%%edx)\n", pos );
break;
case 'l': /* long */
fprintf( outfile, "\tpushl %d(%%edx)\n", pos );
break;
default:
fprintf( stderr, "Unexpected case '%c' in BuildCallTo16Func\n",
args[-1] );
}
pos += 4;
}
/* Push the return address */
fprintf( outfile, "\tpushl %%ecx\n" );
/* Push the called routine address */
fprintf( outfile, "\tpushl %d(%%edx)\n", STACK32OFFSET(args) );
/* Set %ds and %es (and %ax just in case) equal to %ss */
fprintf( outfile, "\tmovw %%ss,%%ax\n" );
fprintf( outfile, "\tmovw %%ax,%%ds\n" );
fprintf( outfile, "\tmovw %%ax,%%es\n" );
/* Jump to the called routine */
fprintf( outfile, "\t.byte 0x66\n" );
fprintf( outfile, "\tlret\n" );
}
/*******************************************************************
* BuildCallFrom16Func
* BuildCallFrom16Core
*
* Build a 16-bit-to-Wine callback function. The syntax of the function
* profile is: call_type_xxxxx, where 'call' is the letter 'c' or 'p' for C or
* Pascal calling convention, 'type' is one of 'regs', 'word' or
* 'long' and each 'x' is an argument ('w'=word, 's'=signed word,
* 'l'=long, 'p'=linear pointer, 't'=linear pointer to null-terminated string,
* 'T'=segmented pointer to null-terminated string).
* For register functions, the arguments are ignored, but they are still
* removed from the stack upon return.
* This routine builds the core routines used in 16->32 thunks:
* CallFrom16, CallFrom16Register, and CallFrom16Thunk.
*
* A special variant of the callback function is generated by the function
* profile "t_long_". This is used by the Win95 16->32 thunk
* functions C16ThkSL and C16ThkSL01 and is implemented as follows:
* CallFrom16 and CallFrom16Register are used by the 16->32 glue code
* as described above. CallFrom16Thunk is a special variant used by
* the implementation of the Win95 16->32 thunk functions C16ThkSL and
* C16ThkSL01 and is implemented as follows:
* On entry, the EBX register is set up to contain a flat pointer to the
* 16-bit stack such that EBX+22 points to the first argument.
* Then, the entry point is called, while EBP is set up to point
......@@ -1631,536 +1858,521 @@ static void RestoreContext16( FILE *outfile )
* The called function returns with CX set to the number of bytes
* to be popped of the caller's stack.
*
* Stack layout upon entry to the callback function:
* Stack layout upon entry to the core routine (STACK16FRAME):
* ... ...
* (sp+18) word first 16-bit arg
* (sp+16) word cs
* (sp+14) word ip
* (sp+12) word bp
* (sp+8) long 32-bit entry point (used to store edx)
* (sp+6) word high word of cs (always 0, used to store es)
* (sp+4) word low word of cs of 16-bit entry point
* (sp+2) word high word of ip (always 0, used to store ds)
* (sp) word low word of ip of 16-bit entry point
* (sp+22) word first 16-bit arg
* (sp+20) word cs
* (sp+18) word ip
* (sp+16) word bp
* (sp+12) long 32-bit entry point (reused for Win16 mutex recursion count)
* (sp+8) long cs of 16-bit entry point
* (sp+4) long ip of 16-bit entry point
* (sp) long auxillary relay function address
*
* Added on the stack:
* (sp-2) word saved fs
* (sp-4) word buffer for Win16Mutex recursion count
* (sp-8) long ebp
* (sp-12) long saved previous stack
* (sp-2) word saved gs
* (sp-4) word saved fs
* (sp-6) word saved es
* (sp-8) word saved ds
* (sp-12) long saved ebp
* (sp-16) long saved ecx
* (sp-20) long saved edx
* (sp-24) long saved previous stack
*/
static void BuildCallFrom16Func( FILE *outfile, char *profile )
static void BuildCallFrom16Core( FILE *outfile, int reg_func, int thunk )
{
int argsize = 0;
int short_ret = 0;
int reg_func = 0;
int Cdecl = 0;
int thunk = 0;
char *args = profile + 7;
/* Parse function type */
if (!strncmp( "c_", profile, 2 )) Cdecl = 1;
else if (!strncmp( "t_", profile, 2 )) thunk = 1;
else if (strncmp( "p_", profile, 2 ))
{
fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
return;
}
if (!strncmp( "word_", profile + 2, 5 )) short_ret = 1;
else if (!strncmp( "regs_", profile + 2, 5 )) reg_func = 1;
else if (strncmp( "long_", profile + 2, 5 ))
{
fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
return;
}
char *name = thunk? "Thunk" : reg_func? "Register" : "";
/* Function header */
fprintf( outfile, "\n\t.align 4\n" );
#ifdef USE_STABS
fprintf( outfile, ".stabs \"CallFrom16_%s:F1\",36,0,0," PREFIX "CallFrom16_%s\n",
profile, profile);
fprintf( outfile, ".stabs \"CallFrom16%s:F1\",36,0,0," PREFIX "CallFrom16%s\n",
name, name);
#endif
fprintf( outfile, "\t.globl " PREFIX "CallFrom16_%s\n", profile );
fprintf( outfile, PREFIX "CallFrom16_%s:\n", profile );
/* Save 16-bit fs and leave room for Win16Mutex recursion count */
fprintf( outfile, "\t.byte 0x66\n\tpushl %%fs\n" );
fprintf( outfile, "\tpushw $0\n" );
/* Setup bp to point to its copy on the stack */
fprintf( outfile, "\tpushl %%ebp\n" ); /* Save the full 32-bit ebp */
fprintf( outfile, "\tmovzwl %%sp,%%ebp\n" );
fprintf( outfile, "\taddw $20,%%bp\n" );
/* Save 16-bit ds and es */
/* Stupid FreeBSD assembler doesn't know these either */
/* fprintf( outfile, "\tmovw %%ds,-10(%%ebp)\n" ); */
fprintf( outfile, "\t.byte 0x66,0x8c,0x5d,0xf6\n" );
/* fprintf( outfile, "\tmovw %%es,-6(%%ebp)\n" ); */
fprintf( outfile, "\t.byte 0x66,0x8c,0x45,0xfa\n" );
/* Save %ebx */
fprintf( outfile, "\tpushl %%ebx\n" );
fprintf( outfile, "\t.globl " PREFIX "CallFrom16%s\n", name );
fprintf( outfile, PREFIX "CallFrom16%s:\n", name );
/* No relay function for 'thunk' */
if ( thunk )
fprintf( outfile, "\tpushl $0\n" );
/* Create STACK16FRAME (except STACK32FRAME link) */
fprintf( outfile, "\tpushw %%gs\n" );
fprintf( outfile, "\tpushw %%fs\n" );
fprintf( outfile, "\tpushw %%es\n" );
fprintf( outfile, "\tpushw %%ds\n" );
fprintf( outfile, "\tpushl %%ebp\n" );
fprintf( outfile, "\tpushl %%ecx\n" );
fprintf( outfile, "\tpushl %%edx\n" );
/* Restore 32-bit segment registers */
#ifdef USE__PIC__
/* Get Global Offset Table into %ecx */
fprintf( outfile, "\tcall .LCallFrom16%s.getgot\n", name );
fprintf( outfile, ".LCallFrom16%s.getgot:\n", name );
fprintf( outfile, "\tpopl %%ecx\n" );
fprintf( outfile, "\taddl $_GLOBAL_OFFSET_TABLE+[.-.LCallFrom16%s.getgot], %%ecx\n" );
#endif
fprintf( outfile, "\tmovw $0x%04x,%%bx\n", Data_Selector );
/* Load 32-bit segment registers */
fprintf( outfile, "\tmovw $0x%04x, %%dx\n", Data_Selector );
#ifdef __svr4__
fprintf( outfile, "\tdata16\n");
#endif
fprintf( outfile, "\tmovw %%bx,%%ds\n" );
fprintf( outfile, "\tmovw %%dx, %%ds\n" );
#ifdef __svr4__
fprintf( outfile, "\tdata16\n");
#endif
fprintf( outfile, "\tmovw %%bx,%%es\n" );
fprintf( outfile, "\tmovw " PREFIX "SYSLEVEL_Win16CurrentTeb,%%fs\n" );
fprintf( outfile, "\tmovw %%dx, %%es\n" );
#ifdef USE__PIC__
fprintf( outfile, "\tmovl " PREFIX "SYSLEVEL_Win16CurrentTeb@GOT(%%ecx), %%edx\n" );
fprintf( outfile, "\tmovw (%%edx), %%fs\n" );
#else
fprintf( outfile, "\tmovw " PREFIX "SYSLEVEL_Win16CurrentTeb, %%fs\n" );
#endif
/* Get the 32-bit stack pointer from the TEB */
/* Get address of ldt_copy array into %ecx */
#ifdef USE__PIC__
fprintf( outfile, "\tmovl " PREFIX "ldt_copy@GOT(%%ecx), %%ecx\n" );
#else
fprintf( outfile, "\tmovl $" PREFIX "ldt_copy, %%ecx\n" );
#endif
fprintf( outfile, "\t.byte 0x64\n\tmovl (%d),%%ebx\n", STACKOFFSET );
/* Translate STACK16FRAME base to flat offset in %edx */
fprintf( outfile, "\tmovw %%ss, %%dx\n" );
fprintf( outfile, "\tandl $0xfff8, %%edx\n" );
fprintf( outfile, "\tmovl (%%ecx,%%edx), %%edx\n" );
fprintf( outfile, "\tmovzwl %%sp, %%ebp\n" );
fprintf( outfile, "\tleal -4(%%ebp,%%edx), %%edx\n" );
/* -4 since STACK16FRAME not yet complete! */
/* Save the 16-bit stack */
/* Get the 32-bit stack pointer from the TEB and complete STACK16FRAME */
fprintf( outfile, "\t.byte 0x64\n\tmovl (%d), %%ebp\n", STACKOFFSET );
fprintf( outfile, "\tpushl %%ebp\n" );
/* Switch stacks */
#ifdef __svr4__
fprintf( outfile,"\tdata16\n");
#endif
fprintf( outfile, "\t.byte 0x64\n\tmovw %%ss,(%d)\n", STACKOFFSET + 2 );
fprintf( outfile, "\t.byte 0x64\n\tmovw %%sp,(%d)\n", STACKOFFSET );
fprintf( outfile, "\t.byte 0x64\n\tmovw %%ss, (%d)\n", STACKOFFSET + 2 );
fprintf( outfile, "\t.byte 0x64\n\tmovw %%sp, (%d)\n", STACKOFFSET );
fprintf( outfile, "\tpushl %%ds\n" );
fprintf( outfile, "\tpopl %%ss\n" );
fprintf( outfile, "\tmovl %%ebp, %%esp\n" );
fprintf( outfile, "\taddl $%d, %%ebp\n", STRUCTOFFSET(STACK32FRAME, ebp) );
/* Transfer the arguments */
if (reg_func) BuildContext16( outfile );
else if (*args) argsize = TransferArgs16To32( outfile, args, Cdecl );
else if (thunk)
/* At this point:
STACK16FRAME is completely set up
DS, ES, SS: flat data segment
FS: current TEB
ESP: points to last STACK32FRAME
EBP: points to ebp member of last STACK32FRAME
EDX: points to current STACK16FRAME
ECX: points to ldt_copy
all other registers: unchanged */
/* Special case: C16ThkSL stub */
if ( thunk )
{
/* Get the stack selector base */
fprintf( outfile, "\tmovw %%ss,%%ax\n" );
fprintf( outfile, "\tandl $0xfff8,%%eax\n" );
fprintf( outfile, "\tmovl " PREFIX "ldt_copy(%%eax),%%eax\n" );
fprintf( outfile, "\tmovl %%eax,-24(%%ebp)\n" );
/* Add the offset */
fprintf( outfile, "\tleal -16(%%ebp),%%eax\n" );
fprintf( outfile, "\taddl %%eax,-24(%%ebp)\n" );
}
/* Set up registers as expected and call thunk */
fprintf( outfile, "\tleal %d(%%edx), %%ebx\n", sizeof(STACK16FRAME)-22 );
fprintf( outfile, "\tleal -4(%%esp), %%ebp\n" );
/* Get the address of the API function */
fprintf( outfile, "\tcall *%d(%%edx)\n", STACK16OFFSET(entry_point) );
fprintf( outfile, "\tmovl -4(%%ebp),%%eax\n" );
/* Switch stack back */
/* fprintf( outfile, "\t.byte 0x64\n\tlssw (%d), %%sp\n", STACKOFFSET ); */
fprintf( outfile, "\t.byte 0x64,0x66,0x0f,0xb2,0x25\n\t.long %d\n", STACKOFFSET );
fprintf( outfile, "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET );
/* If necessary, save %edx over the API function address */
/* Restore registers and return directly to caller */
fprintf( outfile, "\taddl $8, %%esp\n" );
fprintf( outfile, "\tpopl %%ebp\n" );
fprintf( outfile, "\tpopw %%ds\n" );
fprintf( outfile, "\tpopw %%es\n" );
fprintf( outfile, "\tpopw %%fs\n" );
fprintf( outfile, "\tpopw %%gs\n" );
fprintf( outfile, "\taddl $18, %%esp\n" );
if (!reg_func && short_ret)
fprintf( outfile, "\tmovl %%edx,-4(%%ebp)\n" );
fprintf( outfile, "\txorb %%ch, %%ch\n" );
fprintf( outfile, "\tpopl %%ebx\n" );
fprintf( outfile, "\taddw %%cx, %%sp\n" );
fprintf( outfile, "\tpush %%ebx\n" );
/* Restore %ebx and store the 32-bit stack pointer instead */
fprintf( outfile, "\t.byte 0x66\n" );
fprintf( outfile, "\tlret\n" );
fprintf( outfile, "\tmovl %%ebx,%%ebp\n" );
fprintf( outfile, "\tpopl %%ebx\n" );
fprintf( outfile, "\tpushl %%ebp\n" );
return;
}
/* Switch to the 32-bit stack */
fprintf( outfile, "\tpushl %%ds\n" );
fprintf( outfile, "\tpopl %%ss\n" );
fprintf( outfile, "\tleal -%d(%%ebp),%%esp\n",
reg_func ? sizeof(CONTEXT86) : 4 * strlen(args) );
if (reg_func) /* Push the address of the context struct */
fprintf( outfile, "\tpushl %%esp\n" );
/* Build register CONTEXT */
if ( reg_func )
{
fprintf( outfile, "\tsubl $%d, %%esp\n", sizeof(CONTEXT) );
/* Setup %ebp to point to the previous stack frame (built by CallTo16) */
fprintf( outfile, "\tpushfl\n" );
fprintf( outfile, "\tpopl %d(%%esp)\n", CONTEXTOFFSET(EFlags) );
fprintf( outfile, "\taddl $%d,%%ebp\n", STRUCTOFFSET(STACK32FRAME,ebp) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Eax) );
fprintf( outfile, "\tmovl %%ebx, %d(%%esp)\n", CONTEXTOFFSET(Ebx) );
fprintf( outfile, "\tmovl %%esi, %d(%%esp)\n", CONTEXTOFFSET(Esi) );
fprintf( outfile, "\tmovl %%edi, %d(%%esp)\n", CONTEXTOFFSET(Edi) );
/* Print the debug information before the call */
fprintf( outfile, "\tmovl %d(%%edx), %%eax\n", STACK16OFFSET(ebp) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Ebp) );
fprintf( outfile, "\tmovl %d(%%edx), %%eax\n", STACK16OFFSET(ecx) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Ecx) );
fprintf( outfile, "\tmovl %d(%%edx), %%eax\n", STACK16OFFSET(edx) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Edx) );
if (debugging && !thunk)
{
int ftype = 0;
fprintf( outfile, "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(ds) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegDs) );
fprintf( outfile, "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(es) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegEs) );
fprintf( outfile, "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(fs) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegFs) );
fprintf( outfile, "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(gs) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegGs) );
if (Cdecl) ftype |= 4;
if (reg_func) ftype |= 2;
if (short_ret) ftype |= 1;
fprintf( outfile, "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(cs) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegCs) );
fprintf( outfile, "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(ip) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Eip) );
fprintf( outfile, "\tpushl %%eax\n" );
fprintf( outfile, "\tpushl $Profile_%s\n", profile );
fprintf( outfile, "\tpushl $%d\n", ftype );
fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallFrom16\n" );
fprintf( outfile, "\tpopl %%eax\n" );
fprintf( outfile, "\tpopl %%eax\n" );
fprintf( outfile, "\tpopl %%eax\n" );
fprintf( outfile, "\t.byte 0x64\n\tmovzwl (%d), %%eax\n", STACKOFFSET+2 );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegSs) );
fprintf( outfile, "\t.byte 0x64\n\tmovzwl (%d), %%eax\n", STACKOFFSET );
fprintf( outfile, "\taddl $%d, %%eax\n", STACK16OFFSET(ip) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Esp) );
#if 0
fprintf( outfile, "\tfsave %d(%%esp)\n", CONTEXTOFFSET(FloatSave) );
#endif
}
/* Call the entry point */
if (thunk)
/* Print debug info before call */
if ( debugging )
{
fprintf( outfile, "\tpushl %%ebp\n" );
fprintf( outfile, "\tleal -4(%%esp), %%ebp\n" );
fprintf( outfile, "\tcall *%%eax\n" );
fprintf( outfile, "\tpopl %%ebp\n" );
fprintf( outfile, "\tpushl %%ecx\n" );
fprintf( outfile, "\tpushl %%edx\n" );
if ( reg_func )
fprintf( outfile, "\tleal -%d(%%ebp), %%eax\n\tpushl %%eax\n",
sizeof(CONTEXT) + STRUCTOFFSET(STACK32FRAME, ebp) );
else
fprintf( outfile, "\tpushl $0\n" );
#if USE__PIC__
fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallFrom16@PLT\n ");
#else
fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallFrom16\n ");
#endif
fprintf( outfile, "\tpopl %%edx\n" );
fprintf( outfile, "\tpopl %%edx\n" );
fprintf( outfile, "\tpopl %%ecx\n" );
}
else
fprintf( outfile, "\tcall *%%eax\n" );
/* Print the debug information after the call */
/* Call *Thunk* relay routine (which will call the API entry point) */
fprintf( outfile, "\tcall *%d(%%edx)\n", STACK16OFFSET(relay) );
if (debugging && !thunk)
/* Print debug info after call */
if ( debugging )
{
if (reg_func)
{
/* Push again the address of the context struct in case */
/* it has been removed by an stdcall function */
fprintf( outfile, "\tleal -%d(%%ebp),%%esp\n",
sizeof(CONTEXT86) + STRUCTOFFSET(STACK32FRAME,ebp) );
fprintf( outfile, "\tpushl %%esp\n" );
}
fprintf( outfile, "\tpushl %%eax\n" );
fprintf( outfile, "\tpushl $%d\n", reg_func ? 2 : (short_ret ? 1 : 0));
fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallFrom16Ret\n" );
if ( reg_func )
fprintf( outfile, "\tleal -%d(%%ebp), %%eax\n\tpushl %%eax\n",
sizeof(CONTEXT) + STRUCTOFFSET(STACK32FRAME, ebp) );
else
fprintf( outfile, "\tpushl $0\n" );
#if USE__PIC__
fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallFrom16Ret@PLT\n ");
#else
fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallFrom16Ret\n ");
#endif
fprintf( outfile, "\tpopl %%eax\n" );
fprintf( outfile, "\tpopl %%eax\n" );
}
/* Restore the 16-bit stack */
#ifdef __svr4__
fprintf( outfile, "\tdata16\n");
#endif
fprintf( outfile, "\t.byte 0x64\n\tmovw (%d),%%ss\n", STACKOFFSET + 2 );
fprintf( outfile, "\t.byte 0x64\n\tmovzwl (%d),%%esp\n", STACKOFFSET );
fprintf( outfile, "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET );
if (reg_func)
{
/* Calc the arguments size */
while (*args)
{
switch(*args)
{
case 'w':
case 's':
argsize += 2;
break;
case 'p':
case 't':
case 'l':
case 'T':
argsize += 4;
break;
default:
fprintf( stderr, "Unknown arg type '%c'\n", *args );
}
args++;
}
/* Restore registers from the context structure */
RestoreContext16( outfile );
}
else
if ( reg_func )
{
/* Restore high 16 bits of ebp */
fprintf( outfile, "\tpopl %%ebp\n" );
fprintf( outfile, "\tmovl %%esp, %%ebx\n" );
/* Restore ds and es */
fprintf( outfile, "\tincl %%esp\n" ); /* Remove mutex count */
fprintf( outfile, "\tincl %%esp\n" );
fprintf( outfile, "\tpopl %%edx\n" ); /* Remove ip and fs */
fprintf( outfile, "\tmovw %%dx,%%fs\n" ); /* and restore fs */
fprintf( outfile, "\tpopl %%edx\n" ); /* Remove cs and ds */
fprintf( outfile, "\tmovw %%dx,%%ds\n" ); /* and restore ds */
fprintf( outfile, "\t.byte 0x66\n\tpopl %%es\n" ); /* Restore es */
/* Switch stack back */
/* fprintf( outfile, "\t.byte 0x64\n\tlssw (%d), %%sp\n", STACKOFFSET ); */
fprintf( outfile, "\t.byte 0x64,0x66,0x0f,0xb2,0x25\n\t.long %d\n", STACKOFFSET );
fprintf( outfile, "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET );
if (short_ret) fprintf( outfile, "\tpopl %%edx\n" ); /* Restore edx */
else
{
/* Get the return value into dx:ax */
fprintf( outfile, "\tmovl %%eax,%%edx\n" );
fprintf( outfile, "\tshrl $16,%%edx\n" );
/* Remove API entry point */
fprintf( outfile, "\taddl $4,%%esp\n" );
}
/* Restore all registers from CONTEXT */
fprintf( outfile, "\tmovw %d(%%ebx), %%ss\n", CONTEXTOFFSET(SegSs) );
fprintf( outfile, "\tmovl %d(%%ebx), %%esp\n", CONTEXTOFFSET(Esp) );
fprintf( outfile, "\tleal 4(%%esp, %%eax), %%esp\n" );
/* Restore low 16 bits of ebp */
fprintf( outfile, "\tpopw %%bp\n" );
}
fprintf( outfile, "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(SegCs) );
fprintf( outfile, "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(Eip) );
fprintf( outfile, "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(EFlags) );
fprintf( outfile, "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegDs) );
/* Remove the arguments and return */
if (thunk)
{
fprintf( outfile, "\tpopl %%ebx\n" );
fprintf( outfile, "\txorb %%ch,%%ch\n" );
fprintf( outfile, "\taddw %%cx, %%sp\n" );
fprintf( outfile, "\tpushl %%ebx\n" );
fprintf( outfile, "\tmovw %d(%%ebx), %%es\n", CONTEXTOFFSET(SegEs) );
fprintf( outfile, "\tmovw %d(%%ebx), %%fs\n", CONTEXTOFFSET(SegFs) );
fprintf( outfile, "\tmovw %d(%%ebx), %%gs\n", CONTEXTOFFSET(SegGs) );
fprintf( outfile, "\tmovl %d(%%ebx), %%ebp\n", CONTEXTOFFSET(Ebp) );
fprintf( outfile, "\tmovl %d(%%ebx), %%esi\n", CONTEXTOFFSET(Esi) );
fprintf( outfile, "\tmovl %d(%%ebx), %%edi\n", CONTEXTOFFSET(Edi) );
fprintf( outfile, "\tmovl %d(%%ebx), %%eax\n", CONTEXTOFFSET(Eax) );
fprintf( outfile, "\tmovl %d(%%ebx), %%edx\n", CONTEXTOFFSET(Edx) );
fprintf( outfile, "\tmovl %d(%%ebx), %%ecx\n", CONTEXTOFFSET(Ecx) );
fprintf( outfile, "\tmovl %d(%%ebx), %%ebx\n", CONTEXTOFFSET(Ebx) );
fprintf( outfile, "\tpopl %%ds\n" );
fprintf( outfile, "\tpopfl\n" );
fprintf( outfile, "\t.byte 0x66\n" );
fprintf( outfile, "\tlret\n" );
}
else if (argsize && !Cdecl)
{
fprintf( outfile, "\t.byte 0x66\n" );
fprintf( outfile, "\tlret $%d\n", argsize );
}
else
{
fprintf( outfile, "\t.byte 0x66\n" );
fprintf( outfile, "\tlret\n" );
/* Switch stack back */
/* fprintf( outfile, "\t.byte 0x64\n\tlssw (%d), %%sp\n", STACKOFFSET ); */
fprintf( outfile, "\t.byte 0x64,0x66,0x0f,0xb2,0x25\n\t.long %d\n", STACKOFFSET );
fprintf( outfile, "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET );
/* Restore registers and return to *ThunkRet* routine */
fprintf( outfile, "\tpopl %%edx\n" );
fprintf( outfile, "\tpopl %%ecx\n" );
fprintf( outfile, "\tpopl %%ebp\n" );
fprintf( outfile, "\tpopw %%ds\n" );
fprintf( outfile, "\tpopw %%es\n" );
fprintf( outfile, "\tpopw %%fs\n" );
fprintf( outfile, "\tpopw %%gs\n" );
fprintf( outfile, "\tret $14\n" );
}
}
/*******************************************************************
* BuildCallTo16Func
* BuildCallTo16Core
*
* Build a Wine-to-16-bit callback function.
* This routine builds the core routines used in 32->16 thunks:
* CallTo16Word, CallTo16Long, CallTo16RegisterShort, and
* CallTo16RegisterLong.
*
* Stack frame of the callback function:
* ... ...
* (ebp+16) arg2
* (ebp+12) arg1
* (ebp+8) func to call
* (ebp+4) return address
* (ebp) previous ebp
* CallTo16Word and CallTo16Long are used by the 32->16 glue code
* as described above. The register functions can be called directly:
*
* Prototypes for the CallTo16 functions:
* extern WINAPI WORD CallTo16_word_xxx( FARPROC16 func, args... );
* extern WINAPI LONG CallTo16_long_xxx( FARPROC16 func, args... );
* extern WINAPI void CallTo16_sreg_( const CONTEXT86 *context, int nb_args );
* extern WINAPI void CallTo16_lreg_( const CONTEXT86 *context, int nb_args );
* extern void CallTo16RegisterShort( const CONTEXT86 *context, int nb_args );
* extern void CallTo16RegisterLong ( const CONTEXT86 *context, int nb_args );
*
* They call to 16-bit code with all registers except SS:SP set up as specified
* by the 'context' structure, and SS:SP set to point to the current 16-bit
* stack, decremented by the value specified in the 'nb_args' argument.
*/
static void BuildCallTo16Func( FILE *outfile, char *profile )
{
int short_ret = 0;
int reg_func = 0;
char *args = profile + 5;
if (!strncmp( "word_", profile, 5 )) short_ret = 1;
else if (!strncmp( "sreg_", profile, 5 )) reg_func = 1;
else if (!strncmp( "lreg_", profile, 5 )) reg_func = 2;
else if (strncmp( "long_", profile, 5 ))
{
fprintf( stderr, "Invalid function name '%s'.\n", profile );
exit(1);
}
static void BuildCallTo16Core( FILE *outfile, int short_ret, int reg_func )
{
char *name = reg_func == 2 ? "RegisterLong" :
reg_func == 1 ? "RegisterShort" :
short_ret? "Word" : "Long";
/* Function header */
fprintf( outfile, "\n\t.align 4\n" );
#ifdef USE_STABS
fprintf( outfile, ".stabs \"CallTo16_%s:F1\",36,0,0," PREFIX "CallTo16_%s\n",
profile, profile);
fprintf( outfile, ".stabs \"CallTo16%s:F1\",36,0,0," PREFIX "CallTo16%s\n",
name, name);
#endif
fprintf( outfile, "\t.globl " PREFIX "CallTo16_%s\n", profile );
fprintf( outfile, PREFIX "CallTo16_%s:\n", profile );
fprintf( outfile, "\t.globl " PREFIX "CallTo16%s\n", name );
fprintf( outfile, PREFIX "CallTo16%s:\n", name );
/* Entry code */
/* Retrieve relay target address */
if ( !reg_func )
fprintf( outfile, "\tpopl %%eax\n" );
/* Function entry sequence */
fprintf( outfile, "\tpushl %%ebp\n" );
fprintf( outfile, "\tmovl %%esp,%%ebp\n" );
fprintf( outfile, "\tmovl %%esp, %%ebp\n" );
/* Save the 32-bit registers */
fprintf( outfile, "\tpushl %%ebx\n" );
fprintf( outfile, "\tpushl %%ecx\n" );
fprintf( outfile, "\tpushl %%edx\n" );
fprintf( outfile, "\tpushl %%esi\n" );
fprintf( outfile, "\tpushl %%edi\n" );
/* Enter Win16 Mutex */
#ifdef USE__PIC__
/* Get Global Offset Table into %ebx */
fprintf( outfile, "\tcall .LCallTo16%s.getgot\n", name );
fprintf( outfile, ".LCallFrom16%s.getgot:\n", name );
fprintf( outfile, "\tpopl %%ebx\n" );
fprintf( outfile, "\taddl $_GLOBAL_OFFSET_TABLE+[.-.LCallFrom16%s.getgot], %%ebx\n" );
#endif
/* Move relay target address to %edi */
if ( !reg_func )
fprintf( outfile, "\tmovl %%eax, %%edi\n" );
/* Enter Win16 Mutex */
#ifdef USE__PIC__
fprintf( outfile, "\tcall " PREFIX "SYSLEVEL_EnterWin16Lock@PLT\n" );
#else
fprintf( outfile, "\tcall " PREFIX "SYSLEVEL_EnterWin16Lock\n" );
#endif
/* Print debugging info */
if (debugging)
{
/* Push number of arguments (from relay stub) */
if ( reg_func )
fprintf( outfile, "\tpushl $-1\n" );
else
fprintf( outfile, "\tpushl -9(%%edi)\n" );
/* Push the address of the first argument */
fprintf( outfile, "\tleal 8(%%ebp),%%eax\n" );
fprintf( outfile, "\tpushl $%d\n", reg_func ? -1 : strlen(args) );
fprintf( outfile, "\tpushl %%eax\n" );
#ifdef USE__PIC__
fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallTo16@PLT\n" );
#else
fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallTo16\n" );
#endif
fprintf( outfile, "\tpopl %%eax\n" );
fprintf( outfile, "\tpopl %%eax\n" );
}
/* Call the actual CallTo16 routine (simulate a lcall) */
/* Get return address */
#ifdef USE__PIC__
fprintf( outfile, "\tmovl " PREFIX "CallTo16_RetAddr@GOTOFF(%%ebx), %%ecx\n" );
#else
fprintf( outfile, "\tmovl " PREFIX "CallTo16_RetAddr, %%ecx\n" );
#endif
/* Call the actual CallTo16 routine (simulate a lcall) */
fprintf( outfile, "\tpushl %%cs\n" );
fprintf( outfile, "\tcall do_callto16_%s\n", profile );
fprintf( outfile, "\tcall .LCallTo16%s\n", name );
fprintf( outfile, "\tpushl %%eax\n" );
/* Convert and push return value */
if ( short_ret )
{
fprintf( outfile, "\tmovzwl %%ax, %%eax\n" );
fprintf( outfile, "\tpushl %%eax\n" );
}
else if ( reg_func != 2 )
{
fprintf( outfile, "\tshll $16,%%edx\n" );
fprintf( outfile, "\tmovw %%ax,%%dx\n" );
fprintf( outfile, "\tpushl %%edx\n" );
}
else
fprintf( outfile, "\tpushl %%eax\n" );
/* Print debugging info */
if (debugging)
{
fprintf( outfile, "\tpushl %%eax\n" );
#ifdef USE__PIC__
fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallTo16Ret@PLT\n" );
#else
fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallTo16Ret\n" );
fprintf( outfile, "\tpopl %%eax\n" );
#endif
}
/* Leave Win16 Mutex */
#ifdef USE__PIC__
fprintf( outfile, "\tcall " PREFIX "SYSLEVEL_LeaveWin16Lock@PLT\n" );
#else
fprintf( outfile, "\tcall " PREFIX "SYSLEVEL_LeaveWin16Lock\n" );
#endif
/* Restore the 32-bit registers */
/* Get return value */
fprintf( outfile, "\tpopl %%eax\n" );
/* Restore the 32-bit registers */
fprintf( outfile, "\tpopl %%edi\n" );
fprintf( outfile, "\tpopl %%esi\n" );
fprintf( outfile, "\tpopl %%edx\n" );
fprintf( outfile, "\tpopl %%ecx\n" );
fprintf( outfile, "\tpopl %%ebx\n" );
/* Exit code */
#if 0
/* FIXME: this is a hack because of task.c */
if (!strcmp( profile, "word_" ))
{
fprintf( outfile, ".globl " PREFIX "CALLTO16_Restore\n" );
fprintf( outfile, PREFIX "CALLTO16_Restore:\n" );
}
#endif
/* Function exit sequence */
fprintf( outfile, "\tpopl %%ebp\n" );
fprintf( outfile, "\tret $%d\n", 4 * strlen(args) + 4 );
fprintf( outfile, "\tret\n" );
/* Start of the actual CallTo16 routine */
fprintf( outfile, "do_callto16_%s:\n", profile );
/* Save the 32-bit stack */
fprintf( outfile, ".LCallTo16%s:\n", name );
/* Complete STACK32FRAME */
fprintf( outfile, "\t.byte 0x64\n\tpushl (%d)\n", STACKOFFSET );
fprintf( outfile, "\tmovl %%ebp,%%ebx\n" );
fprintf( outfile, "\tmovl %%esp,%%edx\n" );
if (reg_func)
{
/* Switch to the 16-bit stack, saving the current %%esp, */
/* and adding the specified offset to the new sp */
fprintf( outfile, "\t.byte 0x64\n\tmovzwl (%d),%%eax\n", STACKOFFSET );
fprintf( outfile, "\tsubl 12(%%ebx),%%eax\n" ); /* Get the offset */
/* Switch to the 16-bit stack */
#ifdef __svr4__
fprintf( outfile,"\tdata16\n");
fprintf( outfile,"\tdata16\n");
#endif
fprintf( outfile, "\t.byte 0x64\n\tmovw (%d),%%ss\n", STACKOFFSET + 2);
fprintf( outfile, "\tmovl %%eax,%%esp\n" );
fprintf( outfile, "\t.byte 0x64\n\tmovl %%edx,(%d)\n", STACKOFFSET );
fprintf( outfile, "\t.byte 0x64\n\tmovw (%d),%%ss\n", STACKOFFSET + 2);
fprintf( outfile, "\t.byte 0x64\n\tmovw (%d),%%sp\n", STACKOFFSET );
fprintf( outfile, "\t.byte 0x64\n\tmovl %%edx,(%d)\n", STACKOFFSET );
/* Get the registers. ebx is handled later on. */
fprintf( outfile, "\tmovl 8(%%ebx),%%ebx\n" );
fprintf( outfile, "\tmovl %d(%%ebx),%%eax\n", CONTEXTOFFSET(SegEs) );
fprintf( outfile, "\tmovw %%ax,%%es\n" );
fprintf( outfile, "\tmovl %d(%%ebx),%%eax\n", CONTEXTOFFSET(SegFs) );
fprintf( outfile, "\tmovw %%ax,%%fs\n" );
fprintf( outfile, "\tmovl %d(%%ebx),%%ebp\n", CONTEXTOFFSET(Ebp) );
fprintf( outfile, "\tmovl %d(%%ebx),%%eax\n", CONTEXTOFFSET(Eax) );
fprintf( outfile, "\tmovl %d(%%ebx),%%ecx\n", CONTEXTOFFSET(Ecx) );
fprintf( outfile, "\tmovl %d(%%ebx),%%edx\n", CONTEXTOFFSET(Edx) );
fprintf( outfile, "\tmovl %d(%%ebx),%%esi\n", CONTEXTOFFSET(Esi) );
fprintf( outfile, "\tmovl %d(%%ebx),%%edi\n", CONTEXTOFFSET(Edi) );
if (reg_func)
{
/* Add the specified offset to the new sp */
fprintf( outfile, "\tsubw %d(%%edx), %%sp\n", STACK32OFFSET(args)+4 );
/* Push the return address
* With sreg suffix, we push 16:16 address (normal lret)
* With lreg suffix, we push 16:32 address (0x66 lret, for KERNEL32_45)
*/
if (reg_func == 1)
fprintf( outfile, "\tpushl " PREFIX "CALLTO16_RetAddr_long\n" );
fprintf( outfile, "\tpushl %%ecx\n" );
else
{
fprintf( outfile, "\tshldl $16, %%ecx, %%eax\n" );
fprintf( outfile, "\tpushw $0\n" );
fprintf( outfile, "\tpushw " PREFIX "CALLTO16_RetAddr_eax+2\n" );
fprintf( outfile, "\tpushw %%ax\n" );
fprintf( outfile, "\tpushw $0\n" );
fprintf( outfile, "\tpushw " PREFIX "CALLTO16_RetAddr_eax\n" );
fprintf( outfile, "\tpushw %%cx\n" );
}
/* Push the called routine address */
fprintf( outfile, "\tmovl %d(%%edx),%%edx\n", STACK32OFFSET(args) );
fprintf( outfile, "\tpushw %d(%%edx)\n", CONTEXTOFFSET(SegCs) );
fprintf( outfile, "\tpushw %d(%%edx)\n", CONTEXTOFFSET(Eip) );
fprintf( outfile, "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(SegCs) );
fprintf( outfile, "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(Eip) );
/* Get the registers */
fprintf( outfile, "\tpushw %d(%%edx)\n", CONTEXTOFFSET(SegDs) );
fprintf( outfile, "\tmovl %d(%%edx),%%eax\n", CONTEXTOFFSET(SegEs) );
fprintf( outfile, "\tmovw %%ax,%%es\n" );
fprintf( outfile, "\tmovl %d(%%edx),%%eax\n", CONTEXTOFFSET(SegFs) );
fprintf( outfile, "\tmovw %%ax,%%fs\n" );
fprintf( outfile, "\tmovl %d(%%edx),%%ebp\n", CONTEXTOFFSET(Ebp) );
fprintf( outfile, "\tmovl %d(%%edx),%%esi\n", CONTEXTOFFSET(Esi) );
fprintf( outfile, "\tmovl %d(%%edx),%%edi\n", CONTEXTOFFSET(Edi) );
fprintf( outfile, "\tmovl %d(%%edx),%%eax\n", CONTEXTOFFSET(Eax) );
fprintf( outfile, "\tmovl %d(%%edx),%%ebx\n", CONTEXTOFFSET(Ebx) );
fprintf( outfile, "\tmovl %d(%%edx),%%ecx\n", CONTEXTOFFSET(Ecx) );
fprintf( outfile, "\tmovl %d(%%edx),%%edx\n", CONTEXTOFFSET(Edx) );
/* Get the 16-bit ds */
fprintf( outfile, "\tpopw %%ds\n" );
fprintf( outfile, "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegDs) );
/* Get ebx from the 32-bit stack */
fprintf( outfile, "\tmovl %d(%%ebx),%%ebx\n", CONTEXTOFFSET(Ebx) );
fprintf( outfile, "\tpopl %%ds\n" );
/* Jump to the called routine */
fprintf( outfile, "\t.byte 0x66\n" );
fprintf( outfile, "\tlret\n" );
}
else /* not a register function */
{
int pos = 12; /* first argument position */
/* Switch to the 16-bit stack */
#ifdef __svr4__
fprintf( outfile,"\tdata16\n");
#endif
fprintf( outfile, "\t.byte 0x64\n\tmovw (%d),%%ss\n", STACKOFFSET + 2);
fprintf( outfile, "\t.byte 0x64\n\tmovw (%d),%%sp\n", STACKOFFSET );
fprintf( outfile, "\t.byte 0x64\n\tmovl %%edx,(%d)\n", STACKOFFSET );
/* Make %bp point to the previous stackframe (built by CallFrom16) */
fprintf( outfile, "\tmovzwl %%sp,%%ebp\n" );
fprintf( outfile, "\tleal %d(%%ebp),%%ebp\n",
STRUCTOFFSET(STACK16FRAME,bp) );
/* Transfer the arguments */
while (*args)
{
switch(*args++)
{
case 'w': /* word */
fprintf( outfile, "\tpushw %d(%%ebx)\n", pos );
break;
case 'l': /* long */
fprintf( outfile, "\tpushl %d(%%ebx)\n", pos );
break;
default:
fprintf( stderr, "Unexpected case '%c' in BuildCallTo16Func\n",
args[-1] );
}
pos += 4;
}
/* Push the return address */
fprintf( outfile, "\tpushl " PREFIX "CALLTO16_RetAddr_%s\n",
short_ret ? "word" : "long" );
/* Push the called routine address */
fprintf( outfile, "\tpushl 8(%%ebx)\n" );
fprintf( outfile, "\tleal %d(%%ebp),%%ebp\n", STACK16OFFSET(bp) );
/* Set %fs to the value saved by the last CallFrom16 */
fprintf( outfile, "\tmovw -14(%%ebp),%%ax\n" );
fprintf( outfile, "\tmovw %d(%%ebp),%%ax\n", STACK16OFFSET(fs)-STACK16OFFSET(bp) );
fprintf( outfile, "\tmovw %%ax,%%fs\n" );
/* Set %ds and %es (and %ax just in case) equal to %ss */
fprintf( outfile, "\tmovw %%ss,%%ax\n" );
fprintf( outfile, "\tmovw %%ax,%%ds\n" );
fprintf( outfile, "\tmovw %%ax,%%es\n" );
/* Jump to the relay code */
fprintf( outfile, "\tjmp *%%edi\n" );
}
/* Jump to the called routine */
fprintf( outfile, "\t.byte 0x66\n" );
fprintf( outfile, "\tlret\n" );
}
/*******************************************************************
* BuildRet16Func
*
......@@ -2168,20 +2380,13 @@ static void BuildCallTo16Func( FILE *outfile, char *profile )
*/
static void BuildRet16Func( FILE *outfile )
{
fprintf( outfile, "\t.globl " PREFIX "CALLTO16_Ret_word\n" );
fprintf( outfile, "\t.globl " PREFIX "CALLTO16_Ret_long\n" );
fprintf( outfile, "\t.globl " PREFIX "CALLTO16_Ret_eax\n" );
fprintf( outfile, PREFIX "CALLTO16_Ret_word:\n" );
fprintf( outfile, "\txorl %%edx,%%edx\n" );
/* Put return value into %eax */
/*
* Note: This must reside in the .data section to allow
* run-time relocation of the SYSLEVEL_Win16CurrentTeb symbol
*/
fprintf( outfile, PREFIX "CALLTO16_Ret_long:\n" );
fprintf( outfile, "\tshll $16,%%edx\n" );
fprintf( outfile, "\tmovw %%ax,%%dx\n" );
fprintf( outfile, "\tmovl %%edx,%%eax\n" );
fprintf( outfile, PREFIX "CALLTO16_Ret_eax:\n" );
fprintf( outfile, "\n\t.globl " PREFIX "CallTo16_Ret\n" );
fprintf( outfile, PREFIX "CallTo16_Ret:\n" );
/* Restore 32-bit segment registers */
......@@ -2210,16 +2415,10 @@ static void BuildRet16Func( FILE *outfile )
fprintf( outfile, "\tlret\n" );
/* Declare the return address variables */
/* Declare the return address variable */
fprintf( outfile, "\t.data\n" );
fprintf( outfile, "\t.globl " PREFIX "CALLTO16_RetAddr_word\n" );
fprintf( outfile, "\t.globl " PREFIX "CALLTO16_RetAddr_long\n" );
fprintf( outfile, "\t.globl " PREFIX "CALLTO16_RetAddr_eax\n" );
fprintf( outfile, PREFIX "CALLTO16_RetAddr_word:\t.long 0\n" );
fprintf( outfile, PREFIX "CALLTO16_RetAddr_long:\t.long 0\n" );
fprintf( outfile, PREFIX "CALLTO16_RetAddr_eax:\t.long 0\n" );
fprintf( outfile, "\t.text\n" );
fprintf( outfile, "\n\t.globl " PREFIX "CallTo16_RetAddr\n" );
fprintf( outfile, PREFIX "CallTo16_RetAddr:\t.long 0\n" );
}
/*******************************************************************
......@@ -2446,10 +2645,15 @@ static void BuildCallTo32CBClient( FILE *outfile, BOOL isEx )
fprintf( outfile, "\tpopl %%edi\n" );
fprintf( outfile, "\tpopl %%ebp\n" );
fprintf( outfile, "\tret\n" );
}
static void BuildCallTo32CBClientRet( FILE *outfile, BOOL isEx )
{
char *name = isEx? "CBClientEx" : "CBClient";
/* '16-bit' return stub */
fprintf( outfile, "\t.globl " PREFIX "CALL32_%s_Ret\n", name );
fprintf( outfile, "\n\t.globl " PREFIX "CALL32_%s_Ret\n", name );
fprintf( outfile, PREFIX "CALL32_%s_Ret:\n", name );
if ( !isEx )
......@@ -2468,14 +2672,11 @@ static void BuildCallTo32CBClient( FILE *outfile, BOOL isEx )
/* Declare the return address variable */
fprintf( outfile, "\t.data\n" );
fprintf( outfile, "\t.globl " PREFIX "CALL32_%s_RetAddr\n", name );
fprintf( outfile, "\n\t.globl " PREFIX "CALL32_%s_RetAddr\n", name );
fprintf( outfile, PREFIX "CALL32_%s_RetAddr:\t.long 0\n", name );
fprintf( outfile, "\t.text\n" );
}
/*******************************************************************
* BuildCallTo32LargeStack
*
......@@ -2721,18 +2922,26 @@ static int BuildSpec( FILE *outfile, int argc, char *argv[] )
return 0;
}
/*******************************************************************
* BuildCallFrom16
* BuildGlue
*
* Build the 16-bit-to-Wine callbacks
* Build the 16-bit-to-Wine/Wine-to-16-bit callback glue code
*/
static int BuildCallFrom16( FILE *outfile, char * outname, int argc, char *argv[] )
static int BuildGlue( FILE *outfile, char * outname, int argc, char *argv[] )
{
int i;
#ifdef USE_STABS
char buffer[1024];
#endif
FILE *infile;
if (argc > 2)
{
infile = fopen( argv[2], "r" );
if (!infile)
{
perror( argv[2] );
exit( 1 );
}
}
else infile = stdin;
/* File header */
......@@ -2753,30 +2962,41 @@ static int BuildCallFrom16( FILE *outfile, char * outname, int argc, char *argv[
fprintf( outfile, "\t.align 4\n" );
fprintf( outfile, "Code_Start:\n\n" );
#endif
fprintf( outfile, PREFIX"CallFrom16_Start:\n" );
fprintf( outfile, "\t.globl "PREFIX"CallFrom16_Start\n" );
/* Build the callback functions */
/* Build the callback glue functions */
for (i = 2; i < argc; i++) BuildCallFrom16Func( outfile, argv[i] );
/* Build the thunk callback function */
BuildCallFrom16Func( outfile, "t_long_" );
/* Output the argument debugging strings */
if (debugging)
while (fgets( buffer, sizeof(buffer), infile ))
{
if (strstr( buffer, "### start build ###" )) break;
}
while (fgets( buffer, sizeof(buffer), infile ))
{
fprintf( outfile, "/* Argument strings */\n" );
for (i = 2; i < argc; i++)
char *p;
if ( (p = strstr( buffer, "CallFrom16_" )) != NULL )
{
char *q, *profile = p + strlen( "CallFrom16_" );
for (q = profile; (*q == '_') || isalpha(*q); q++ )
;
*q = '\0';
for (q = p-1; q > buffer && ((*q == '_') || isalnum(*q)); q-- )
;
if ( ++q < p ) p[-1] = '\0'; else q = "";
BuildCallFrom16Func( outfile, profile, q );
}
if ( (p = strstr( buffer, "CallTo16_" )) != NULL )
{
fprintf( outfile, "Profile_%s:\t", argv[i] );
fprintf( outfile, STRING " \"%s\\0\"\n", argv[i] + 7 );
char *q, *profile = p + strlen( "CallTo16_" );
for (q = profile; (*q == '_') || isalpha(*q); q++ )
;
*q = '\0';
for (q = p-1; q > buffer && ((*q == '_') || isalnum(*q)); q-- )
;
if ( ++q < p ) p[-1] = '\0'; else q = "";
BuildCallTo16Func( outfile, profile, q );
}
if (strstr( buffer, "### stop build ###" )) break;
}
fprintf( outfile, PREFIX"CallFrom16_End:\n" );
fprintf( outfile, "\t.globl "PREFIX"CallFrom16_End\n" );
#ifdef USE_STABS
fprintf( outfile, "\t.text\n");
......@@ -2784,30 +3004,20 @@ static int BuildCallFrom16( FILE *outfile, char * outname, int argc, char *argv[
fprintf( outfile, ".Letext:\n");
#endif
fclose( infile );
return 0;
}
/*******************************************************************
* BuildCallTo16
* BuildCall16
*
* Build the Wine-to-16-bit callbacks
* Build the 16-bit callbacks
*/
static int BuildCallTo16( FILE *outfile, char * outname, int argc, char *argv[] )
static int BuildCall16( FILE *outfile, char * outname )
{
#ifdef USE_STABS
char buffer[1024];
FILE *infile;
if (argc > 2)
{
infile = fopen( argv[2], "r" );
if (!infile)
{
perror( argv[2] );
exit( 1 );
}
}
else infile = stdin;
#endif
/* File header */
......@@ -2828,57 +3038,67 @@ static int BuildCallTo16( FILE *outfile, char * outname, int argc, char *argv[]
fprintf( outfile, "\t.align 4\n" );
fprintf( outfile, "Code_Start:\n\n" );
#endif
fprintf( outfile, PREFIX"Call16_Start:\n" );
fprintf( outfile, "\t.globl "PREFIX"Call16_Start\n" );
fprintf( outfile, "\t.byte 0\n\n" );
fprintf( outfile, "\t.globl " PREFIX "CALLTO16_Start\n" );
fprintf( outfile, PREFIX "CALLTO16_Start:\n" );
/* Build the callback functions */
/* Standard CallFrom16 routine */
BuildCallFrom16Core( outfile, FALSE, FALSE );
while (fgets( buffer, sizeof(buffer), infile ))
{
if (strstr( buffer, "### start build ###" )) break;
}
while (fgets( buffer, sizeof(buffer), infile ))
{
char *p = strstr( buffer, "CallTo16_" );
if (p)
{
char *profile = p + strlen( "CallTo16_" );
p = profile;
while ((*p == '_') || isalpha(*p)) p++;
*p = '\0';
BuildCallTo16Func( outfile, profile );
}
if (strstr( buffer, "### stop build ###" )) break;
}
/* Register CallFrom16 routine */
BuildCallFrom16Core( outfile, TRUE, FALSE );
/* Output the 16-bit return code */
/* C16ThkSL CallFrom16 routine */
BuildCallFrom16Core( outfile, FALSE, TRUE );
BuildRet16Func( outfile );
/* Standard CallTo16 routine (WORD return) */
BuildCallTo16Core( outfile, TRUE, FALSE );
/* Output the CBClient callback functions
* (while this does not really 'call to 16-bit' code, it is placed
* here so that its 16-bit return stub is defined within the CALLTO16
* 16-bit segment)
*/
/* Standard CallTo16 routine (DWORD return) */
BuildCallTo16Core( outfile, FALSE, FALSE );
/* Register CallTo16 routine (16:16 retf) */
BuildCallTo16Core( outfile, FALSE, 1 );
/* Register CallTo16 routine (16:32 retf) */
BuildCallTo16Core( outfile, FALSE, 2 );
/* CBClientThunkSL routine */
BuildCallTo32CBClient( outfile, FALSE );
BuildCallTo32CBClient( outfile, TRUE );
/* CBClientThunkSLEx routine */
BuildCallTo32CBClient( outfile, TRUE );
fprintf( outfile, "\t.globl " PREFIX "CALLTO16_End\n" );
fprintf( outfile, PREFIX "CALLTO16_End:\n" );
fprintf( outfile, PREFIX"Call16_End:\n" );
fprintf( outfile, "\t.globl "PREFIX"Call16_End\n" );
#ifdef USE_STABS
fprintf( outfile, "\t.text\n");
fprintf( outfile, "\t.stabs \"\",100,0,0,.Letext\n");
fprintf( outfile, ".Letext:\n");
#endif
fclose( infile );
/* The whole Call16_Ret segment must lie within the .data section */
fprintf( outfile, "\n\t.data\n" );
fprintf( outfile, "\t.globl " PREFIX "Call16_Ret_Start\n" );
fprintf( outfile, PREFIX "Call16_Ret_Start:\n" );
/* Standard CallTo16 return stub */
BuildRet16Func( outfile );
/* CBClientThunkSL return stub */
BuildCallTo32CBClientRet( outfile, FALSE );
/* CBClientThunkSLEx return stub */
BuildCallTo32CBClientRet( outfile, TRUE );
/* End of Call16_Ret segment */
fprintf( outfile, "\n\t.globl " PREFIX "Call16_Ret_End\n" );
fprintf( outfile, PREFIX "Call16_Ret_End:\n" );
return 0;
}
/*******************************************************************
* BuildCall32
*
......@@ -2943,8 +3163,8 @@ static void usage(void)
{
fprintf( stderr,
"usage: build [-o outfile] -spec SPECNAMES\n"
" build [-o outfile] -callfrom16 FUNCTION_PROFILES\n"
" build [-o outfile] -callto16 FUNCTION_PROFILES\n"
" build [-o outfile] -glue SOURCE_FILE\n"
" build [-o outfile] -call16\n"
" build [-o outfile] -call32\n" );
exit(1);
}
......@@ -2983,10 +3203,10 @@ int main(int argc, char **argv)
if (!strcmp( argv[1], "-spec" ))
res = BuildSpec( outfile, argc, argv );
else if (!strcmp( argv[1], "-callfrom16" ))
res = BuildCallFrom16( outfile, outname, argc, argv );
else if (!strcmp( argv[1], "-callto16" ))
res = BuildCallTo16( outfile, outname, argc, argv );
else if (!strcmp( argv[1], "-glue" ))
res = BuildGlue( outfile, outname, argc, argv );
else if (!strcmp( argv[1], "-call16" ))
res = BuildCall16( outfile, outname );
else if (!strcmp( argv[1], "-call32" ))
res = BuildCall32( outfile, outname );
else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment