Thu Feb 16 18:57:31 1995 Alexandre Julliard (julliard@sunsite.unc.edu) * [if1632/call.S] Only save the lower 16-bits of SP and BP. * [if1632/callback.c] When calling to 16-bit code, restore DS from its previous value on entry to the 32-bit code, instead of from the code segment owner. * [if1632/relay.c] [include/stackframe.h] Use a structure to represent the 16-bit stack frame layout instead of hard-coded offsets. * [rc/Imakefile] Use y.tab.c for bison output file for compatibility with yacc. * [tools/build.c] Small optimization for calls to 32-bit code. Sun Feb 12 03:19:47 1995 Michael Veksler (s1678223@t2.technion.ac.il) * [tools/build.c] Fixed bug (inflicted by previous change) - SEGV on ZMAGIC file format. Sun Feb 11 20:00:00 1995 Göran Thyni (goran@norrsken.bildbasen.se) * [debugger/dbg.y] Remove unnecessary sym-table loading when stopped in 16-bit mode. * [include/segmem.h] [loader/selector.c] Added dynamic alloction of selectors. Fixed some problems with large programs SIGSEGV-ing while running out of selectors. * [include/segmem.h] [loader/selector.c] [if1632/callback.c] [memory/global.c] [memory/heap.c] [memory/linear.c] Use __AHSHIFT and __AHINCR instead of 3 and 8. Mon Feb 6 18:07:38 1995 Cameron Heide (heide@ee.ualberta.ca) * [misc/dos_fs.c] Better relative path handling when converting filenames between dos and unix, allowing '.' to be used in the Windows path. Startup working dir is now based on current working dir. Sat Feb 4 21:21:13 1995 Michael Veksler (s1678223@t2.technion.ac.il) * [if1632/relay.c] [include/dlls.h] [tools/build.c] Squeezed data structure that references internal dll's (mostly "struct dll_table_entry_s"). Caused 20% reduction in executable code size. Fri Feb 3 18:53:15 1995 Martin v. Loewis (loewis@marie) * [Imakefile] make wine.sym only when making emulator * [misc/file.c] OpenFile(): report as not implemented for WINELIB * [misc/winsock.c] Fix CONVERT_HOSTENT and friends for use with WINELIB * [rc/Imakefile][rc/rc.y][rc/parser.c] Rename rc.y to parser.y Use flex and bison on Sun * [toolkit/sup.c] CallWindowProc: fix parameter type * [windows/event.c] Commented #ifdef sparc
348 lines
9.2 KiB
C
348 lines
9.2 KiB
C
/*
|
|
static char RCSId[] = "$Id: relay.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
|
|
static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#ifdef linux
|
|
#include <linux/unistd.h>
|
|
#include <linux/head.h>
|
|
#include <linux/ldt.h>
|
|
#endif
|
|
|
|
#include "neexe.h"
|
|
#include "segmem.h"
|
|
#include "prototypes.h"
|
|
#include "dlls.h"
|
|
#include "options.h"
|
|
#include "stackframe.h"
|
|
#include "stddebug.h"
|
|
/* #define DEBUG_RELAY */
|
|
/* #define DEBUG_STACK */
|
|
#include "debug.h"
|
|
|
|
#if 0
|
|
/* Make make_debug think these were really used */
|
|
dprintf_relay
|
|
dprintf_stack
|
|
#endif
|
|
|
|
#ifdef WINELIB
|
|
#define WineLibSkip(x) 0
|
|
#else
|
|
#define WineLibSkip(x) x
|
|
#endif
|
|
|
|
struct dll_name_table_entry_s dll_builtin_table[N_BUILTINS] =
|
|
{
|
|
{ "KERNEL", WineLibSkip(KERNEL_table), 410, 1 },
|
|
{ "USER", WineLibSkip(USER_table), 540, 2 },
|
|
{ "GDI", WineLibSkip(GDI_table), 490, 3 },
|
|
{ "UNIXLIB", WineLibSkip(UNIXLIB_table), 10, 4 },
|
|
{ "WIN87EM", WineLibSkip(WIN87EM_table), 10, 5 },
|
|
{ "SHELL", WineLibSkip(SHELL_table), 103, 6 },
|
|
{ "SOUND", WineLibSkip(SOUND_table), 20, 7 },
|
|
{ "KEYBOARD",WineLibSkip(KEYBOARD_table),137, 8 },
|
|
{ "WINSOCK", WineLibSkip(WINSOCK_table), 155, 9 },
|
|
{ "STRESS", WineLibSkip(STRESS_table), 15, 10},
|
|
{ "MMSYSTEM",WineLibSkip(MMSYSTEM_table),1226,11},
|
|
{ "SYSTEM", WineLibSkip(SYSTEM_table), 20 ,12},
|
|
{ "TOOLHELP",WineLibSkip(TOOLHELP_table), 83, 13},
|
|
{ "MOUSE", WineLibSkip(MOUSE_table), 8, 14},
|
|
{ "EMUCOMMDLG", WineLibSkip(COMMDLG_table), 31, 15},
|
|
};
|
|
/* don't forget to increase N_BUILTINS in dll.h if you add a dll */
|
|
|
|
/* the argument conversion tables for each dll */
|
|
struct dll_conversions {
|
|
unsigned short *dst_args; /* Offsets to arguments on stack */
|
|
unsigned char *src_types; /* Argument types */
|
|
} dll_conversion_table[N_BUILTINS]= {
|
|
KERNEL_offsets, KERNEL_types, /* KERNEL */
|
|
USER_offsets, USER_types, /* USER */
|
|
GDI_offsets, GDI_types, /* GDI */
|
|
UNIXLIB_offsets, UNIXLIB_types, /* UNIXLIB */
|
|
WIN87EM_offsets, WIN87EM_types, /* WIN87EM */
|
|
SHELL_offsets, SHELL_types, /* SHELL */
|
|
SOUND_offsets, SOUND_types, /* SOUND */
|
|
KEYBOARD_offsets, KEYBOARD_types, /* KEYBOARD */
|
|
WINSOCK_offsets, WINSOCK_types, /* WINSOCK */
|
|
STRESS_offsets, STRESS_types, /* STRESS, */
|
|
MMSYSTEM_offsets, MMSYSTEM_types, /* MMSYSTEM */
|
|
SYSTEM_offsets, SYSTEM_types, /* SYSTEM */
|
|
TOOLHELP_offsets, TOOLHELP_types, /* TOOLHELP */
|
|
MOUSE_offsets, MOUSE_types, /* MOUSE */
|
|
COMMDLG_offsets, COMMDLG_types /* EMUCOMMDLG */
|
|
};
|
|
|
|
|
|
#ifndef WINELIB
|
|
STACK16FRAME *pStack16Frame;
|
|
|
|
extern unsigned short IF1632_Saved16_sp;
|
|
extern unsigned short IF1632_Saved16_bp;
|
|
extern unsigned short IF1632_Saved16_ss;
|
|
|
|
/**********************************************************************
|
|
* DLLRelay
|
|
*
|
|
* We get a stack frame pointer to data that looks like this:
|
|
*
|
|
* Hex Offset Contents
|
|
* ---------- -------
|
|
* +00 previous saved_16ss
|
|
* +02 previous saved_16ebp
|
|
* +06 previous saved_16esp
|
|
* +0A 16-bit es
|
|
* +0C 16-bit ds
|
|
* +0E 16-bit ebp
|
|
* +12 length of 16-bit arguments
|
|
* +14 16-bit ip
|
|
* +16 16-bit cs
|
|
* +18 arguments
|
|
*/
|
|
int
|
|
DLLRelay(unsigned int func_num, unsigned int seg_off)
|
|
{
|
|
struct dll_table_entry_s *dll_p;
|
|
STACK16FRAME *pOldStack16Frame;
|
|
unsigned int offset;
|
|
unsigned int dll_id;
|
|
unsigned int ordinal;
|
|
int arg_table[DLL_MAX_ARGS];
|
|
void *arg_ptr;
|
|
int (*func_ptr)();
|
|
int i;
|
|
int ret_val;
|
|
int conv_ref;
|
|
unsigned char *type_conv;
|
|
unsigned short *offset_conv;
|
|
|
|
/*
|
|
* Determine address of arguments.
|
|
*/
|
|
pOldStack16Frame = pStack16Frame;
|
|
pStack16Frame = (STACK16FRAME *) seg_off;
|
|
arg_ptr = (void *)pStack16Frame->args;
|
|
|
|
/*
|
|
* Extract the DLL number and ordinal number.
|
|
*/
|
|
dll_id = ((func_num >> 16) & 0xffff) - 1;
|
|
ordinal = func_num & 0xffff;
|
|
dll_p = &dll_builtin_table[dll_id].dll_table[ordinal];
|
|
|
|
if (debugging_relay)
|
|
{
|
|
unsigned int *ret_addr;
|
|
|
|
ret_addr = (unsigned int *) ((char *) seg_off + 0x14);
|
|
printf("Call %s (%s.%d), stack=%04x:%04x, ",
|
|
dll_p->export_name,
|
|
dll_builtin_table[dll_id].dll_name, ordinal,
|
|
seg_off >> 16, seg_off & 0xffff);
|
|
printf("ret=%08x", *ret_addr);
|
|
printf(" ESP=%04x, EBP=%04x, SS=%04x\n",
|
|
IF1632_Saved16_sp, IF1632_Saved16_bp,
|
|
IF1632_Saved16_ss);
|
|
|
|
if(debugging_stack)
|
|
{
|
|
unsigned short *stack_p = (unsigned short *) seg_off;
|
|
/* FIXME: Is there an end-of-stack-pointer somewhere ? */
|
|
int n = min(24, (0x10000 - (seg_off & 0xffff)) / sizeof(*stack_p));
|
|
for (i = 0; i < n; i++, stack_p++)
|
|
{
|
|
printf("%04x ", *stack_p);
|
|
if ((i & 7) == 7)
|
|
printf("\n");
|
|
}
|
|
printf("\n");
|
|
}
|
|
} /* DEBUG_RELAY */
|
|
|
|
/*
|
|
* Make sure we have a handler defined for this call.
|
|
*/
|
|
if (dll_p->handler == NULL)
|
|
{
|
|
char buffer[100];
|
|
|
|
sprintf(buffer, "No handler for routine %s.%d",
|
|
dll_builtin_table[dll_id].dll_name, ordinal);
|
|
myerror(buffer);
|
|
}
|
|
func_ptr = dll_p->handler;
|
|
|
|
/*
|
|
* OK, special case. If the handler is define as taking no arguments
|
|
* then pass the address of the arguments on the 16-bit stack to the
|
|
* handler. It will just ignore the pointer if it really takes no
|
|
* arguments. This allows us to write slightly faster library routines
|
|
* if we choose.
|
|
*/
|
|
if (dll_p->n_args == 0)
|
|
{
|
|
ret_val = (*func_ptr)(arg_ptr);
|
|
pStack16Frame = pOldStack16Frame;
|
|
return ret_val;
|
|
}
|
|
|
|
/*
|
|
* Getting this far means we need to convert the 16-bit argument stack.
|
|
*/
|
|
conv_ref= dll_p->conv_reference;
|
|
type_conv= dll_conversion_table[dll_id].src_types + conv_ref;
|
|
offset_conv= dll_conversion_table[dll_id].dst_args + conv_ref;
|
|
for (i = 0; i < dll_p->n_args; i++,type_conv++,offset_conv++)
|
|
{
|
|
short *sp;
|
|
int *ip;
|
|
|
|
offset = *offset_conv;
|
|
|
|
switch (*type_conv)
|
|
{
|
|
case DLL_ARGTYPE_SIGNEDWORD:
|
|
sp = (short *) ((char *) arg_ptr + offset);
|
|
arg_table[i] = *sp;
|
|
break;
|
|
|
|
case DLL_ARGTYPE_WORD:
|
|
sp = (short *) ((char *) arg_ptr + offset);
|
|
arg_table[i] = (int) *sp & 0xffff;
|
|
break;
|
|
|
|
case DLL_ARGTYPE_LONG:
|
|
ip = (int *) ((char *) arg_ptr + offset);
|
|
arg_table[i] = *ip;
|
|
break;
|
|
|
|
case DLL_ARGTYPE_FARPTR:
|
|
ip = (int *) ((char *) arg_ptr + offset);
|
|
if (*ip & 0xffff0000)
|
|
arg_table[i] = FIXPTR(*ip);
|
|
else
|
|
arg_table[i] = *ip;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Call the handler
|
|
*/
|
|
ret_val = (*func_ptr)(arg_table[0], arg_table[1], arg_table[2],
|
|
arg_table[3], arg_table[4], arg_table[5],
|
|
arg_table[6], arg_table[7], arg_table[8],
|
|
arg_table[9], arg_table[10], arg_table[11],
|
|
arg_table[12], arg_table[13], arg_table[14],
|
|
arg_table[15]);
|
|
|
|
if (debugging_relay)
|
|
{
|
|
printf("Returning %08x from %s (%s.%d)\n",
|
|
ret_val,
|
|
dll_p->export_name,
|
|
dll_builtin_table[dll_id].dll_name, ordinal);
|
|
}
|
|
|
|
pStack16Frame = pOldStack16Frame;
|
|
return ret_val;
|
|
}
|
|
#endif
|
|
|
|
/**********************************************************************
|
|
* FindDLLTable
|
|
*/
|
|
struct dll_table_entry_s *
|
|
FindDLLTable(char *dll_name)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < N_BUILTINS; i++)
|
|
if (strcasecmp(dll_builtin_table[i].dll_name, dll_name) == 0)
|
|
#ifdef WINELIB
|
|
return dll_builtin_table[i].dll_number;
|
|
#else
|
|
return dll_builtin_table[i].dll_table;
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* FindOrdinalFromName
|
|
*/
|
|
int
|
|
FindOrdinalFromName(struct dll_table_entry_s *dll_table, char *func_name)
|
|
{
|
|
int i, limit;
|
|
|
|
for (i = 0; i < N_BUILTINS; i++)
|
|
if (dll_table == dll_builtin_table[i].dll_table)
|
|
break;
|
|
|
|
if (i == N_BUILTINS)
|
|
return 0;
|
|
|
|
limit = dll_builtin_table[i].dll_table_length;
|
|
for (i = 0; i < limit; i++)
|
|
if (strcasecmp(dll_table[i].export_name, func_name) == 0)
|
|
return i;
|
|
|
|
return 0;
|
|
}
|
|
/**********************************************************************
|
|
* ReturnArg
|
|
*/
|
|
int
|
|
ReturnArg(int arg)
|
|
{
|
|
return arg;
|
|
}
|
|
|
|
#ifndef WINELIB
|
|
#ifdef WINESTAT
|
|
void winestat(){
|
|
int i, j;
|
|
double perc;
|
|
int used, implemented;
|
|
int tused, timplemented;
|
|
struct dll_table_entry_s *table;
|
|
|
|
tused = 0;
|
|
timplemented = 0;
|
|
for (i = 0; i < N_BUILTINS; i++) {
|
|
table = dll_builtin_table[i].dll_table;
|
|
used = 0;
|
|
implemented = 0;
|
|
for(j=0; j < dll_builtin_table[i].dll_table_length; j++) {
|
|
if(table[j].used){
|
|
used++;
|
|
if (table[j].handler) implemented++;
|
|
else
|
|
printf("%s.%d not implemented\n",
|
|
dll_builtin_table[i].dll_name,
|
|
j);
|
|
};
|
|
};
|
|
tused += used;
|
|
timplemented += implemented;
|
|
if(used)
|
|
perc = implemented * 100.00 / used;
|
|
else
|
|
perc = 0.0;
|
|
if (used)
|
|
printf("%s: %d of %d (%3.1f %%)\n", dll_builtin_table[i].dll_name, implemented, used, perc);
|
|
};
|
|
perc = timplemented * 100.00 / tused;
|
|
printf("TOTAL: %d of %d winapi functions implemented (%3.1f %%)\n",timplemented, tused, perc);
|
|
}
|
|
#endif /* WINESTAT */
|
|
#endif /* !WINELIB */
|