Release 0.0.2
[wine] / relay.c
1 /* $Id$
2  */
3 /*
4  * Copyright  Robert J. Amstadt, 1993
5  */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include <unistd.h>
13 #include <linux/unistd.h>
14 #include <linux/head.h>
15 #include <linux/ldt.h>
16 #include <linux/segment.h>
17 #include <errno.h>
18 #include "neexe.h"
19 #include "segmem.h"
20 #include "prototypes.h"
21 #include "dlls.h"
22
23 struct dll_name_table_entry_s dll_builtin_table[4] =
24 {
25     { "KERNEL",  KERNEL_table,  256, 1 },
26     { "USER",    USER_table,    256, 2 },
27     { "GDI",     GDI_table,     256, 3 },
28     { "UNIXLIB", UNIXLIB_table, 256, 4 },
29 };
30
31 unsigned short *Stack16Frame;
32
33 /**********************************************************************
34  *                                      DLLRelay
35  *
36  * We get a stack frame pointer to data that looks like this:
37  *
38  *   Hex Offset Contents
39  *   ---------- -------
40  *      +00     previous saved_16ss
41  *      +02     previous saved_16ebp
42  *      +06     previous saved_16esp
43  *      +0A     16-bit es
44  *      +0C     16-bit ds
45  *      +0E     16-bit ebp
46  *      +12     length of 16-bit arguments
47  *      +14     16-bit ip
48  *      +16     16-bit cs
49  *      +18     arguments
50  */
51 int
52 DLLRelay(unsigned int func_num, unsigned int seg_off)
53 {
54     struct dll_table_entry_s *dll_p;
55     unsigned int segment;
56     unsigned int offset;
57     unsigned int dll_id;
58     unsigned int ordinal;
59     int arg_table[DLL_MAX_ARGS];
60     void *arg_ptr;
61     int (*func_ptr)();
62     int i;
63     
64     /*
65      * Determine address of arguments.
66      */
67     Stack16Frame = (unsigned short *) seg_off;
68     arg_ptr = (void *) (seg_off + 0x18);
69
70     /*
71      * Extract the DLL number and ordinal number.
72      */
73     dll_id  = ((func_num >> 16) & 0xffff) - 1;
74     ordinal = func_num & 0xffff;
75     dll_p   = &dll_builtin_table[dll_id].dll_table[ordinal];
76
77 #ifdef RELAY_DEBUG
78     {
79         unsigned int *ret_addr;
80         unsigned short *stack_p;
81         
82         ret_addr = (unsigned int *) ((char *) seg_off + 0x14);
83         printf("RELAY: Calling %s.%d, 16-bit stack at %04x:%04x, ",
84                dll_builtin_table[dll_id].dll_name, ordinal,
85                seg_off >> 16, seg_off & 0xffff);
86         printf("return to %08x\n", *ret_addr);
87
88 #ifdef STACK_DEBUG
89         stack_p = (unsigned short *) seg_off;
90         for (i = 0; i < 24; i++, stack_p++)
91         {
92             printf("%04x ", *stack_p);
93             if ((i & 7) == 7)
94                 printf("\n");
95         }
96         printf("\n");
97 #endif /* STACK_DEBUG */
98     }
99 #endif /* RELAY_DEBUG */
100
101     /*
102      * Make sure we have a handler defined for this call.
103      */
104     if (dll_p->handler == NULL)
105     {
106         char buffer[100];
107         
108         sprintf(buffer, "No handler for routine %s.%d", 
109                 dll_builtin_table[dll_id].dll_name, ordinal);
110         myerror(buffer);
111     }
112     func_ptr = dll_p->handler;
113
114     /*
115      * OK, special case.  If the handler is define as taking no arguments
116      * then pass the address of the arguments on the 16-bit stack to the
117      * handler.  It will just ignore the pointer if it really takes no
118      * arguments.  This allows us to write slightly faster library routines
119      * if we choose.
120      */
121     if (dll_p->n_args == 0)
122         return (*func_ptr)(arg_ptr);
123
124     /*
125      * Getting this far means we need to convert the 16-bit argument stack.
126      */
127     for (i = 0; i < dll_p->n_args; i++)
128     {
129         short *sp;
130         int *ip;
131         
132         offset = dll_p->args[i].dst_arg;
133
134         switch (dll_p->args[i].src_type)
135         {
136           case DLL_ARGTYPE_SIGNEDWORD:
137             sp = (short *) ((char *) arg_ptr + offset);
138             arg_table[i] = *sp;
139             break;
140             
141           case DLL_ARGTYPE_WORD:
142             sp = (short *) ((char *) arg_ptr + offset);
143             arg_table[i] = (int) *sp & 0xffff;
144             break;
145             
146           case DLL_ARGTYPE_LONG:
147           case DLL_ARGTYPE_FARPTR:
148             ip = (int *) ((char *) arg_ptr + offset);
149             arg_table[i] = *ip;
150             break;
151         }
152     }
153
154     /*
155      * Call the handler
156      */
157     return (*func_ptr)(arg_table[0], arg_table[1], arg_table[2], 
158                        arg_table[3], arg_table[4], arg_table[5], 
159                        arg_table[6], arg_table[7], arg_table[8], 
160                        arg_table[9], arg_table[10], arg_table[11],
161                        arg_table[12], arg_table[13], arg_table[14], 
162                        arg_table[15]);
163 }
164
165 /**********************************************************************
166  *                                      FindDLLTable
167  */
168 struct  dll_table_entry_s *
169 FindDLLTable(char *dll_name)
170 {
171     int i;
172
173     for (i = 0; i < 4; i++)
174         if (strcmp(dll_builtin_table[i].dll_name, dll_name) == 0)
175             return dll_builtin_table[i].dll_table;
176     
177     return NULL;
178 }
179
180 /**********************************************************************
181  *                                      FindOrdinalFromName
182  */
183 int
184 FindOrdinalFromName(struct dll_table_entry_s *dll_table, char *func_name)
185 {
186     int i, limit;
187
188     for (i = 0; i < 4; i++)
189         if (dll_table == dll_builtin_table[i].dll_table)
190             break;
191     
192     if (i == 4)
193         return 0;
194
195     limit = dll_builtin_table[i].dll_table_length;
196     for (i = 0; i < limit; i++)
197         if (strcasecmp(dll_table[i].export_name, func_name) == 0)
198             return i;
199     
200     return 0;
201 }