Release 941107
[wine/multimedia.git] / if1632 / relay.c
blobd9d9994bdadef71618c959be99c132086a28bd3e
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";
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>
19 #include "neexe.h"
20 #include "segmem.h"
21 #include "prototypes.h"
22 #include "dlls.h"
23 #include "options.h"
25 #define DEBUG_RELAY /* */
27 #ifdef WINELIB
28 #define WineLibSkip(x) 0
29 #else
30 #define WineLibSkip(x) x
31 #endif
33 struct dll_name_table_entry_s dll_builtin_table[N_BUILTINS] =
35 { "KERNEL", WineLibSkip(KERNEL_table), 410, 1 },
36 { "USER", WineLibSkip(USER_table), 540, 2 },
37 { "GDI", WineLibSkip(GDI_table), 490, 3 },
38 { "UNIXLIB", WineLibSkip(UNIXLIB_table), 10, 4 },
39 { "WIN87EM", WineLibSkip(WIN87EM_table), 10, 5 },
40 { "SHELL", WineLibSkip(SHELL_table), 103, 6 },
41 { "SOUND", WineLibSkip(SOUND_table), 20, 7 },
42 { "KEYBOARD",WineLibSkip(KEYBOARD_table),137, 8 },
43 { "WINSOCK", WineLibSkip(WINSOCK_table), 155, 9 },
44 { "STRESS", WineLibSkip(STRESS_table), 15, 10},
45 { "MMSYSTEM",WineLibSkip(MMSYSTEM_table),1226,11},
46 { "SYSTEM", WineLibSkip(SYSTEM_table), 20 ,12},
47 { "TOOLHELP",WineLibSkip(TOOLHELP_table), 83, 13},
48 { "MOUSE", WineLibSkip(MOUSE_table), 8, 14},
49 { "EMUCOMMDLG", WineLibSkip(COMMDLG_table), 31, 15},
51 /* don't forget to increase N_BUILTINS in dll.h if you add a dll */
53 #ifndef WINELIB
54 unsigned short *Stack16Frame;
56 extern unsigned long IF1632_Saved16_esp;
57 extern unsigned long IF1632_Saved16_ebp;
58 extern unsigned short IF1632_Saved16_ss;
60 /**********************************************************************
61 * DLLRelay
63 * We get a stack frame pointer to data that looks like this:
65 * Hex Offset Contents
66 * ---------- -------
67 * +00 previous saved_16ss
68 * +02 previous saved_16ebp
69 * +06 previous saved_16esp
70 * +0A 16-bit es
71 * +0C 16-bit ds
72 * +0E 16-bit ebp
73 * +12 length of 16-bit arguments
74 * +14 16-bit ip
75 * +16 16-bit cs
76 * +18 arguments
78 int
79 DLLRelay(unsigned int func_num, unsigned int seg_off)
81 struct dll_table_entry_s *dll_p;
82 unsigned short *saved_Stack16Frame;
83 unsigned int segment;
84 unsigned int offset;
85 unsigned int dll_id;
86 unsigned int ordinal;
87 int arg_table[DLL_MAX_ARGS];
88 void *arg_ptr;
89 int (*func_ptr)();
90 int i;
91 int ret_val;
94 * Determine address of arguments.
96 saved_Stack16Frame = Stack16Frame;
97 Stack16Frame = (unsigned short *) seg_off;
98 arg_ptr = (void *) (seg_off + 0x18);
101 * Extract the DLL number and ordinal number.
103 dll_id = ((func_num >> 16) & 0xffff) - 1;
104 ordinal = func_num & 0xffff;
105 dll_p = &dll_builtin_table[dll_id].dll_table[ordinal];
107 #ifdef DEBUG_RELAY
108 if (Options.relay_debug)
110 unsigned int *ret_addr;
111 unsigned short *stack_p;
113 ret_addr = (unsigned int *) ((char *) seg_off + 0x14);
114 printf("Call %s (%s.%d), stack=%04x:%04x, ",
115 dll_p->export_name,
116 dll_builtin_table[dll_id].dll_name, ordinal,
117 seg_off >> 16, seg_off & 0xffff);
118 printf("ret=%08x", *ret_addr);
119 printf(" ESP=%08x, EBP=%08x, SS=%04x\n",
120 IF1632_Saved16_esp, IF1632_Saved16_ebp,
121 IF1632_Saved16_ss);
123 #ifdef DEBUG_STACK
124 stack_p = (unsigned short *) seg_off;
125 for (i = 0; i < 24; i++, stack_p++)
127 printf("%04x ", *stack_p);
128 if ((i & 7) == 7)
129 printf("\n");
131 printf("\n");
132 #endif /* DEBUG_STACK */
134 #endif /* DEBUG_RELAY */
137 * Make sure we have a handler defined for this call.
139 if (dll_p->handler == NULL)
141 char buffer[100];
143 sprintf(buffer, "No handler for routine %s.%d",
144 dll_builtin_table[dll_id].dll_name, ordinal);
145 myerror(buffer);
147 func_ptr = dll_p->handler;
150 * OK, special case. If the handler is define as taking no arguments
151 * then pass the address of the arguments on the 16-bit stack to the
152 * handler. It will just ignore the pointer if it really takes no
153 * arguments. This allows us to write slightly faster library routines
154 * if we choose.
156 if (dll_p->n_args == 0)
158 ret_val = (*func_ptr)(arg_ptr);
159 Stack16Frame = saved_Stack16Frame;
160 return ret_val;
164 * Getting this far means we need to convert the 16-bit argument stack.
166 for (i = 0; i < dll_p->n_args; i++)
168 short *sp;
169 int *ip;
171 offset = dll_p->args[i].dst_arg;
173 switch (dll_p->args[i].src_type)
175 case DLL_ARGTYPE_SIGNEDWORD:
176 sp = (short *) ((char *) arg_ptr + offset);
177 arg_table[i] = *sp;
178 break;
180 case DLL_ARGTYPE_WORD:
181 sp = (short *) ((char *) arg_ptr + offset);
182 arg_table[i] = (int) *sp & 0xffff;
183 break;
185 case DLL_ARGTYPE_LONG:
186 ip = (int *) ((char *) arg_ptr + offset);
187 arg_table[i] = *ip;
188 break;
190 case DLL_ARGTYPE_FARPTR:
191 ip = (int *) ((char *) arg_ptr + offset);
192 if (*ip & 0xffff0000)
193 arg_table[i] = FIXPTR(*ip);
194 else
195 arg_table[i] = *ip;
196 break;
201 * Call the handler
203 ret_val = (*func_ptr)(arg_table[0], arg_table[1], arg_table[2],
204 arg_table[3], arg_table[4], arg_table[5],
205 arg_table[6], arg_table[7], arg_table[8],
206 arg_table[9], arg_table[10], arg_table[11],
207 arg_table[12], arg_table[13], arg_table[14],
208 arg_table[15]);
210 #ifdef DEBUG_RELAY
211 if (Options.relay_debug)
213 printf("Returning %08.8x from %s (%s.%d)\n",
214 ret_val,
215 dll_p->export_name,
216 dll_builtin_table[dll_id].dll_name, ordinal);
218 #endif
220 Stack16Frame = saved_Stack16Frame;
221 return ret_val;
223 #endif
225 /**********************************************************************
226 * FindDLLTable
228 struct dll_table_entry_s *
229 FindDLLTable(char *dll_name)
231 int i;
233 for (i = 0; i < N_BUILTINS; i++)
234 if (strcasecmp(dll_builtin_table[i].dll_name, dll_name) == 0)
235 #ifdef WINELIB
236 return dll_builtin_table[i].dll_number;
237 #else
238 return dll_builtin_table[i].dll_table;
239 #endif
240 return NULL;
243 /**********************************************************************
244 * FindOrdinalFromName
247 FindOrdinalFromName(struct dll_table_entry_s *dll_table, char *func_name)
249 int i, limit;
251 for (i = 0; i < N_BUILTINS; i++)
252 if (dll_table == dll_builtin_table[i].dll_table)
253 break;
255 if (i == N_BUILTINS)
256 return 0;
258 limit = dll_builtin_table[i].dll_table_length;
259 for (i = 0; i < limit; i++)
260 if (strcasecmp(dll_table[i].export_name, func_name) == 0)
261 return i;
263 return 0;
265 /**********************************************************************
266 * ReturnArg
269 ReturnArg(int arg)
271 return arg;
274 #ifndef WINELIB
275 #ifdef WINESTAT
276 void winestat(){
277 int i, j;
278 double perc;
279 int used, implemented;
280 int tused, timplemented;
281 struct dll_table_entry_s *table;
283 tused = 0;
284 timplemented = 0;
285 for (i = 0; i < N_BUILTINS; i++) {
286 table = dll_builtin_table[i].dll_table;
287 used = 0;
288 implemented = 0;
289 for(j=0; j < dll_builtin_table[i].dll_table_length; j++) {
290 if(table[j].used){
291 used++;
292 if (table[j].handler) implemented++;
293 else
294 printf("%s.%d not implemented\n",
295 dll_builtin_table[i].dll_name,
299 tused += used;
300 timplemented += implemented;
301 if(used)
302 perc = implemented * 100.00 / used;
303 else
304 perc = 0.0;
305 if (used)
306 printf("%s: %d of %d (%3.1f %%)\n", dll_builtin_table[i].dll_name, implemented, used, perc);
308 perc = timplemented * 100.00 / tused;
309 printf("TOTAL: %d of %d winapi functions implemented (%3.1f %%)\n",timplemented, tused, perc);
311 #endif /* WINESTAT */
312 #endif /* !WINELIB */