From 3dff7bb84258475b0bab2e50ceb2db057f196d9c Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Sun, 11 Jul 1999 13:58:31 +0000 Subject: [PATCH] Modularized CallFrom/To16 routines. Adapted dependent routines, 16-bit snoop/relay debugging, and make rules. --- Make.rules.in | 19 +- if1632/.cvsignore | 136 +++-- if1632/Makefile.in | 25 +- if1632/builtin.c | 16 +- if1632/relay.c | 84 +-- if1632/snoop.c | 6 +- if1632/thunk.c | 241 ++++---- include/builtin16.h | 63 ++ include/callback.h | 54 +- include/module.h | 2 +- include/stackframe.h | 25 +- misc/callback.c | 170 ++---- miscemu/main.c | 8 +- relay32/.cvsignore | 90 +-- relay32/Makefile.in | 20 +- scheduler/syslevel.c | 17 +- tools/build.c | 1592 ++++++++++++++++++++++++++++---------------------- 17 files changed, 1397 insertions(+), 1171 deletions(-) rewrite if1632/.cvsignore (97%) create mode 100644 include/builtin16.h rewrite relay32/.cvsignore (95%) diff --git a/Make.rules.in b/Make.rules.in index d49c32164e4..20b74bb150e 100644 --- a/Make.rules.in +++ b/Make.rules.in @@ -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: diff --git a/if1632/.cvsignore b/if1632/.cvsignore dissimilarity index 97% index 42b069c164b..f22507ffaa4 100644 --- a/if1632/.cvsignore +++ b/if1632/.cvsignore @@ -1,45 +1,91 @@ -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 +Makefile +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 diff --git a/if1632/Makefile.in b/if1632/Makefile.in index 4ffa622928f..16227585b67 100644 --- a/if1632/Makefile.in +++ b/if1632/Makefile.in @@ -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: diff --git a/if1632/builtin.c b/if1632/builtin.c index 4818aaf274a..30191417a01 100644 --- a/if1632/builtin.c +++ b/if1632/builtin.c @@ -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 ); } diff --git a/if1632/relay.c b/if1632/relay.c index ec8d32bc9fb..1c0d8264f36 100644 --- a/if1632/relay.c +++ b/if1632/relay.c @@ -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); } diff --git a/if1632/snoop.c b/if1632/snoop.c index 52e3bce1274..127c4b28056 100644 --- a/if1632/snoop.c +++ b/if1632/snoop.c @@ -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) { diff --git a/if1632/thunk.c b/if1632/thunk.c index 032e4de2424..2fcbd8866f4 100644 --- a/if1632/thunk.c +++ b/if1632/thunk.c @@ -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 */ diff --git a/include/builtin16.h b/include/builtin16.h new file mode 100644 index 00000000000..f905beae021 --- /dev/null +++ b/include/builtin16.h @@ -0,0 +1,63 @@ +/* + * 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 */ + WORD ax; + WORD movw_dx; /* movw $, %dx */ + WORD dx; + WORD lret; /* lret $ */ + 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 */ diff --git a/include/callback.h b/include/callback.h index bb3dae378ab..34e03b8f5c8 100644 --- a/include/callback.h +++ b/include/callback.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; diff --git a/include/module.h b/include/module.h index 10e302eed7f..fdd1c556a1b 100644 --- a/include/module.h +++ b/include/module.h @@ -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); diff --git a/include/stackframe.h b/include/stackframe.h index 1a08630a4fc..a7b9f0b1b74 100644 --- a/include/stackframe.h +++ b/include/stackframe.h @@ -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" diff --git a/misc/callback.c b/misc/callback.c index dd46fb047f7..bdccaafb078 100644 --- a/misc/callback.c +++ b/misc/callback.c @@ -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= &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); } /*********************************************************************** diff --git a/relay32/.cvsignore b/relay32/.cvsignore dissimilarity index 95% index b2ad281e93c..fda6ca49711 100644 --- a/relay32/.cvsignore +++ b/relay32/.cvsignore @@ -1,45 +1,45 @@ -Makefile -advapi32.c -avifil32.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 +Makefile +advapi32.spec.c +avifil32.spec.c +call32.s +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 diff --git a/relay32/Makefile.in b/relay32/Makefile.in index e84e3a686c0..c10e5dd192c 100644 --- a/relay32/Makefile.in +++ b/relay32/Makefile.in @@ -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: diff --git a/scheduler/syslevel.c b/scheduler/syslevel.c index 37c33258a98..aeb3692c734 100644 --- a/scheduler/syslevel.c +++ b/scheduler/syslevel.c @@ -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); } /************************************************************************ diff --git a/tools/build.c b/tools/build.c index 20f6ff041bf..add3b18563c 100644 --- a/tools/build.c +++ b/tools/build.c @@ -3,6 +3,7 @@ * Copyright 1995 Martin von Loewis * Copyright 1995, 1996, 1997 Alexandre Julliard * Copyright 1997 Eric Youngdale + * Copyright 1999 Ulrich Weigand */ #include @@ -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 -- 2.11.4.GIT