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