Release 940518
[wine] / if1632 / relay.c
1 static char RCSId[] = "$Id: relay.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
2 static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
3
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11 #ifdef linux
12 #include <linux/unistd.h>
13 #include <linux/head.h>
14 #include <linux/ldt.h>
15 #include <linux/segment.h>
16 #endif
17 #include <errno.h>
18
19 #include "neexe.h"
20 #include "segmem.h"
21 #include "prototypes.h"
22 #include "dlls.h"
23 #include "options.h"
24
25 #define DEBUG_RELAY /* */
26
27 #define N_BUILTINS      11
28
29 struct dll_name_table_entry_s dll_builtin_table[N_BUILTINS] =
30 {
31     { "KERNEL",  KERNEL_table,  410, 1 },
32     { "USER",    USER_table,    540, 2 },
33     { "GDI",     GDI_table,     490, 3 },
34     { "UNIXLIB", UNIXLIB_table,  10, 4 },
35     { "WIN87EM", WIN87EM_table,  10, 5 },
36     { "SHELL",   SHELL_table,   256, 6 },
37     { "SOUND",   SOUND_table,    20, 7 },
38     { "KEYBOARD",KEYBOARD_table,137, 8 },
39     { "WINSOCK", WINSOCK_table, 155, 9 },
40     { "STRESS",  STRESS_table,   15, 10},
41     { "MMSYSTEM",MMSYSTEM_table,1023,11},
42 };
43
44 unsigned short *Stack16Frame;
45
46 extern unsigned long  IF1632_Saved16_esp;
47 extern unsigned long  IF1632_Saved16_ebp;
48 extern unsigned short IF1632_Saved16_ss;
49
50 /**********************************************************************
51  *                                      DLLRelay
52  *
53  * We get a stack frame pointer to data that looks like this:
54  *
55  *   Hex Offset Contents
56  *   ---------- -------
57  *      +00     previous saved_16ss
58  *      +02     previous saved_16ebp
59  *      +06     previous saved_16esp
60  *      +0A     16-bit es
61  *      +0C     16-bit ds
62  *      +0E     16-bit ebp
63  *      +12     length of 16-bit arguments
64  *      +14     16-bit ip
65  *      +16     16-bit cs
66  *      +18     arguments
67  */
68 int
69 DLLRelay(unsigned int func_num, unsigned int seg_off)
70 {
71     struct dll_table_entry_s *dll_p;
72     unsigned short *saved_Stack16Frame;
73     unsigned int segment;
74     unsigned int offset;
75     unsigned int dll_id;
76     unsigned int ordinal;
77     int arg_table[DLL_MAX_ARGS];
78     void *arg_ptr;
79     int (*func_ptr)();
80     int i;
81     int ret_val;
82     
83     /*
84      * Determine address of arguments.
85      */
86     saved_Stack16Frame = Stack16Frame;
87     Stack16Frame = (unsigned short *) seg_off;
88     arg_ptr = (void *) (seg_off + 0x18);
89
90     /*
91      * Extract the DLL number and ordinal number.
92      */
93     dll_id  = ((func_num >> 16) & 0xffff) - 1;
94     ordinal = func_num & 0xffff;
95     dll_p   = &dll_builtin_table[dll_id].dll_table[ordinal];
96
97 #ifdef DEBUG_RELAY
98     if (Options.relay_debug)
99     {
100         unsigned int *ret_addr;
101         unsigned short *stack_p;
102         
103         ret_addr = (unsigned int *) ((char *) seg_off + 0x14);
104         printf("Calling %s (%s.%d), 16-bit stack at %04x:%04x, ",
105                dll_p->export_name,
106                dll_builtin_table[dll_id].dll_name, ordinal,
107                seg_off >> 16, seg_off & 0xffff);
108         printf("return to %08x\n", *ret_addr);
109         printf("  ESP %08x, EBP %08x, SS %04x\n", 
110                IF1632_Saved16_esp, IF1632_Saved16_ebp,
111                IF1632_Saved16_ss);
112
113 #ifdef DEBUG_STACK
114         stack_p = (unsigned short *) seg_off;
115         for (i = 0; i < 24; i++, stack_p++)
116         {
117             printf("%04x ", *stack_p);
118             if ((i & 7) == 7)
119                 printf("\n");
120         }
121         printf("\n");
122 #endif /* DEBUG_STACK */
123     }
124 #endif /* DEBUG_RELAY */
125
126     /*
127      * Make sure we have a handler defined for this call.
128      */
129     if (dll_p->handler == NULL)
130     {
131         char buffer[100];
132         
133         sprintf(buffer, "No handler for routine %s.%d", 
134                 dll_builtin_table[dll_id].dll_name, ordinal);
135         myerror(buffer);
136     }
137     func_ptr = dll_p->handler;
138
139     /*
140      * OK, special case.  If the handler is define as taking no arguments
141      * then pass the address of the arguments on the 16-bit stack to the
142      * handler.  It will just ignore the pointer if it really takes no
143      * arguments.  This allows us to write slightly faster library routines
144      * if we choose.
145      */
146     if (dll_p->n_args == 0)
147     {
148         ret_val = (*func_ptr)(arg_ptr);
149         Stack16Frame = saved_Stack16Frame;
150         return ret_val;
151     }
152
153     /*
154      * Getting this far means we need to convert the 16-bit argument stack.
155      */
156     for (i = 0; i < dll_p->n_args; i++)
157     {
158         short *sp;
159         int *ip;
160         
161         offset = dll_p->args[i].dst_arg;
162
163         switch (dll_p->args[i].src_type)
164         {
165           case DLL_ARGTYPE_SIGNEDWORD:
166             sp = (short *) ((char *) arg_ptr + offset);
167             arg_table[i] = *sp;
168             break;
169             
170           case DLL_ARGTYPE_WORD:
171             sp = (short *) ((char *) arg_ptr + offset);
172             arg_table[i] = (int) *sp & 0xffff;
173             break;
174             
175           case DLL_ARGTYPE_LONG:
176             ip = (int *) ((char *) arg_ptr + offset);
177             arg_table[i] = *ip;
178             break;
179
180           case DLL_ARGTYPE_FARPTR:
181             ip = (int *) ((char *) arg_ptr + offset);
182             if (*ip & 0xffff0000)
183                 arg_table[i] = FIXPTR(*ip);
184             else
185                 arg_table[i] = *ip;
186             break;
187         }
188     }
189
190     /*
191      * Call the handler
192      */
193     ret_val = (*func_ptr)(arg_table[0], arg_table[1], arg_table[2], 
194                           arg_table[3], arg_table[4], arg_table[5], 
195                           arg_table[6], arg_table[7], arg_table[8], 
196                           arg_table[9], arg_table[10], arg_table[11],
197                           arg_table[12], arg_table[13], arg_table[14], 
198                           arg_table[15]);
199
200 #ifdef DEBUG_RELAY
201     if (Options.relay_debug)
202     {
203         printf("Returning %08.8x from %s (%s.%d)\n",
204                ret_val,
205                dll_p->export_name,
206                dll_builtin_table[dll_id].dll_name, ordinal);
207     }
208 #endif
209
210     Stack16Frame = saved_Stack16Frame;
211     return ret_val;
212 }
213
214 /**********************************************************************
215  *                                      FindDLLTable
216  */
217 struct  dll_table_entry_s *
218 FindDLLTable(char *dll_name)
219 {
220     int i;
221
222     for (i = 0; i < N_BUILTINS; i++)
223         if (strcmp(dll_builtin_table[i].dll_name, dll_name) == 0)
224             return dll_builtin_table[i].dll_table;
225     
226     return NULL;
227 }
228
229 /**********************************************************************
230  *                                      FindOrdinalFromName
231  */
232 int
233 FindOrdinalFromName(struct dll_table_entry_s *dll_table, char *func_name)
234 {
235     int i, limit;
236
237     for (i = 0; i < N_BUILTINS; i++)
238         if (dll_table == dll_builtin_table[i].dll_table)
239             break;
240     
241     if (i == N_BUILTINS)
242         return 0;
243
244     limit = dll_builtin_table[i].dll_table_length;
245     for (i = 0; i < limit; i++)
246         if (strcasecmp(dll_table[i].export_name, func_name) == 0)
247             return i;
248     
249     return 0;
250 }
251 /**********************************************************************
252  *                                      ReturnArg
253  */
254 int
255 ReturnArg(int arg)
256 {
257     return arg;
258 }
259
260 #ifdef WINESTAT
261 void winestat(){
262         int i, j;
263         double perc;
264         int used, implemented;
265         int tused, timplemented;
266         struct dll_table_entry_s *table;
267
268         tused = 0;
269         timplemented = 0;
270     for (i = 0; i < N_BUILTINS; i++) {
271             table = dll_builtin_table[i].dll_table;
272             used = 0;
273             implemented = 0;
274             for(j=0; j < dll_builtin_table[i].dll_table_length; j++) {
275                     if(table[j].used){
276                             used++;
277                             if (table[j].handler) implemented++;
278                             else 
279                                     printf("%s.%d\n",
280                                            dll_builtin_table[i].dll_name,
281                                            j);
282                     };
283             };
284             tused += used;
285             timplemented += implemented;
286             if(used)
287                     perc = implemented * 100.00 / used;
288             else
289                     perc = 0.0;
290             printf("%s: %d %d %3.1f\n", dll_builtin_table[i].dll_name, implemented, used, perc);
291     };
292         perc = timplemented * 100.00 / tused;
293         printf("TOTAL: %d %d %3.1f\n",timplemented, tused, perc);
294 }
295 #endif /* WINESTAT */