Release 950319
[wine/hacks.git] / if1632 / relay.c
blobe717b5af7d325616bb4aa130142c2eb60c714faa
1 /*
2 static char RCSId[] = "$Id: relay.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
3 static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
4 */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include <unistd.h>
13 #include <errno.h>
14 #ifdef linux
15 #include <linux/unistd.h>
16 #include <linux/head.h>
17 #include <linux/ldt.h>
18 #endif
20 #include "ldt.h"
22 #include "neexe.h"
23 #include "prototypes.h"
24 #include "dlls.h"
25 #include "options.h"
26 #include "stackframe.h"
27 #include "stddebug.h"
28 /* #define DEBUG_RELAY */
29 /* #define DEBUG_STACK */
30 #include "debug.h"
32 #if 0
33 /* Make make_debug think these were really used */
34 dprintf_relay
35 dprintf_stack
36 #endif
38 #ifdef WINELIB
39 #define WineLibSkip(x) 0
40 #else
41 #define WineLibSkip(x) x
42 #endif
44 struct dll_name_table_entry_s dll_builtin_table[N_BUILTINS] =
46 { "KERNEL", WineLibSkip(KERNEL_table), 410, 1, 1 },
47 { "USER", WineLibSkip(USER_table), 540, 2, 1 },
48 { "GDI", WineLibSkip(GDI_table), 490, 3, 1 },
49 { "WIN87EM", WineLibSkip(WIN87EM_table), 10, 4, 1 },
50 { "SHELL", WineLibSkip(SHELL_table), 103, 5, 1 },
51 { "SOUND", WineLibSkip(SOUND_table), 20, 6, 1 },
52 { "KEYBOARD",WineLibSkip(KEYBOARD_table),137, 7, 1 },
53 { "WINSOCK", WineLibSkip(WINSOCK_table), 155, 8, 1 },
54 { "STRESS", WineLibSkip(STRESS_table), 15, 9, 1},
55 { "MMSYSTEM",WineLibSkip(MMSYSTEM_table),1226,10, 1},
56 { "SYSTEM", WineLibSkip(SYSTEM_table), 20 ,11, 1},
57 { "TOOLHELP",WineLibSkip(TOOLHELP_table), 83, 12, 1},
58 { "MOUSE", WineLibSkip(MOUSE_table), 8, 13, 1},
59 { "COMMDLG", WineLibSkip(COMMDLG_table), 31, 14, 1},
60 { "OLE2", WineLibSkip(OLE2_table), 31, 15, 1},
61 { "OLE2CONV",WineLibSkip(OLE2CONV_table), 31, 16, 1},
62 { "OLE2DISP",WineLibSkip(OLE2DISP_table), 31, 17, 1},
63 { "OLE2NLS", WineLibSkip(OLE2NLS_table), 31, 18, 1},
64 { "OLE2PROX",WineLibSkip(OLE2PROX_table), 31, 19, 1},
65 { "OLECLI", WineLibSkip(OLECLI_table), 31, 20, 1},
66 { "OLESVR", WineLibSkip(OLESVR_table), 31, 21, 1},
67 { "COMPOBJ", WineLibSkip(COMPOBJ_table), 31, 22, 1},
68 { "STORAGE", WineLibSkip(STORAGE_table), 31, 23, 1}
70 /* don't forget to increase N_BUILTINS in dll.h if you add a dll */
72 /* the argument conversion tables for each dll */
73 struct dll_conversions {
74 unsigned short *dst_args; /* Offsets to arguments on stack */
75 unsigned char *src_types; /* Argument types */
76 } dll_conversion_table[N_BUILTINS]= {
77 { KERNEL_offsets, KERNEL_types }, /* KERNEL */
78 { USER_offsets, USER_types }, /* USER */
79 { GDI_offsets, GDI_types }, /* GDI */
80 { WIN87EM_offsets, WIN87EM_types }, /* WIN87EM */
81 { SHELL_offsets, SHELL_types }, /* SHELL */
82 { SOUND_offsets, SOUND_types }, /* SOUND */
83 { KEYBOARD_offsets, KEYBOARD_types }, /* KEYBOARD */
84 { WINSOCK_offsets, WINSOCK_types }, /* WINSOCK */
85 { STRESS_offsets, STRESS_types }, /* STRESS, */
86 { MMSYSTEM_offsets, MMSYSTEM_types }, /* MMSYSTEM */
87 { SYSTEM_offsets, SYSTEM_types }, /* SYSTEM */
88 { TOOLHELP_offsets, TOOLHELP_types }, /* TOOLHELP */
89 { MOUSE_offsets, MOUSE_types }, /* MOUSE */
90 { COMMDLG_offsets, COMMDLG_types }, /* EMUCOMMDLG */
91 { OLE2_offsets, OLE2_types }, /* OLE2 */
92 { OLE2CONV_offsets, OLE2CONV_types }, /* OLE2CONV */
93 { OLE2DISP_offsets, OLE2DISP_types }, /* OLE2DISP */
94 { OLE2NLS_offsets, OLE2NLS_types }, /* OLE2NLS */
95 { OLE2DISP_offsets, OLE2DISP_types }, /* OLE2PROX */
96 { OLECLI_offsets, OLECLI_types }, /* OLE2CLI */
97 { OLESVR_offsets, OLESVR_types }, /* OLE2CLI */
98 { COMPOBJ_offsets, COMPOBJ_types }, /* COMPOBJ */
99 { STORAGE_offsets, STORAGE_types } /* STORAGE */
103 #ifndef WINELIB
105 extern unsigned short IF1632_Saved16_sp;
106 extern unsigned short IF1632_Saved16_bp;
107 extern unsigned short IF1632_Saved16_ss;
109 void RelayDebug( unsigned int func_num )
111 unsigned int dll_id, ordinal;
113 if (debugging_relay)
115 dll_id = ((func_num >> 16) & 0xffff) - 1;
116 ordinal = func_num & 0xffff;
117 printf( "Calling %s.%d\n",
118 dll_builtin_table[dll_id].dll_table[ordinal].export_name,
119 ordinal );
124 /**********************************************************************
125 * DLLRelay
127 * We get a stack frame pointer to data that looks like this:
129 * Hex Offset Contents
130 * ---------- -------
131 * +00 previous saved_16ss
132 * +02 previous saved_16ebp
133 * +06 previous saved_16esp
134 * +0A 16-bit es
135 * +0C 16-bit ds
136 * +0E 16-bit ebp
137 * +12 length of 16-bit arguments
138 * +14 16-bit ip
139 * +16 16-bit cs
140 * +18 arguments
143 DLLRelay(unsigned int func_num, unsigned int seg_off)
145 struct dll_table_entry_s *dll_p;
146 STACK16FRAME *pStack16Frame;
147 unsigned int offset;
148 unsigned int dll_id;
149 unsigned int ordinal;
150 int arg_table[DLL_MAX_ARGS];
151 void *arg_ptr;
152 int (*func_ptr)();
153 int i;
154 int ret_val;
155 int conv_ref;
156 unsigned char *type_conv;
157 unsigned short *offset_conv;
158 STACK16FRAME stackFrameCopy;
161 * Determine address of arguments.
163 pStack16Frame = (STACK16FRAME *) PTR_SEG_TO_LIN(seg_off);
164 arg_ptr = (void *)pStack16Frame->args;
167 * Extract the DLL number and ordinal number.
169 dll_id = ((func_num >> 16) & 0xffff) - 1;
170 ordinal = func_num & 0xffff;
171 dll_p = &dll_builtin_table[dll_id].dll_table[ordinal];
173 dprintf_relay( stddeb, "Call %s (%s.%d), stack=%04x:%04x ret=%04x:%04x ds=%04x bp=%04x args=%d\n",
174 dll_p->export_name,
175 dll_builtin_table[dll_id].dll_name, ordinal,
176 seg_off >> 16, seg_off & 0xffff,
177 pStack16Frame->cs, pStack16Frame->ip,
178 pStack16Frame->ds, pStack16Frame->bp,
179 pStack16Frame->arg_length );
181 if(debugging_stack)
183 unsigned short *stack_p = (unsigned short *) pStack16Frame;
184 /* FIXME: Is there an end-of-stack-pointer somewhere ? */
185 int n = min(24, (0x10000 - (seg_off & 0xffff)) / sizeof(*stack_p));
186 for (i = 0; i < n; i++, stack_p++)
188 printf("%04x ", *stack_p);
189 if ((i & 7) == 7)
190 printf("\n");
192 printf("\n");
196 * Make sure we have a handler defined for this call.
198 if (dll_p->handler == NULL)
200 char buffer[100];
202 sprintf(buffer, "No handler for routine %s.%d",
203 dll_builtin_table[dll_id].dll_name, ordinal);
204 myerror(buffer);
206 func_ptr = dll_p->handler;
209 * OK, special case. If the handler is define as taking no arguments
210 * then pass the address of the arguments on the 16-bit stack to the
211 * handler. It will just ignore the pointer if it really takes no
212 * arguments. This allows us to write slightly faster library routines
213 * if we choose.
215 if (dll_p->n_args == 0)
217 ret_val = (*func_ptr)(arg_ptr);
218 dprintf_relay( stddeb, "Returning %08x from %s (%s.%d) ds=%04x\n",
219 ret_val, dll_p->export_name,
220 dll_builtin_table[dll_id].dll_name, ordinal,
221 pStack16Frame->ds );
222 return ret_val;
226 * Getting this far means we need to convert the 16-bit argument stack.
228 conv_ref= dll_p->conv_reference;
229 type_conv= dll_conversion_table[dll_id].src_types + conv_ref;
230 offset_conv= dll_conversion_table[dll_id].dst_args + conv_ref;
231 for (i = 0; i < dll_p->n_args; i++,type_conv++,offset_conv++)
233 short *sp;
234 int *ip;
236 offset = *offset_conv;
238 switch (*type_conv)
240 case DLL_ARGTYPE_SIGNEDWORD:
241 sp = (short *) ((char *) arg_ptr + offset);
242 arg_table[i] = *sp;
243 break;
245 case DLL_ARGTYPE_WORD:
246 sp = (short *) ((char *) arg_ptr + offset);
247 arg_table[i] = (int) *sp & 0xffff;
248 break;
250 case DLL_ARGTYPE_LONG:
251 ip = (int *) ((char *) arg_ptr + offset);
252 arg_table[i] = *ip;
253 break;
255 case DLL_ARGTYPE_FARPTR:
256 ip = (int *) ((char *) arg_ptr + offset);
257 arg_table[i] = (unsigned int) PTR_SEG_TO_LIN( *ip );
258 break;
262 if (debugging_relay)
263 memcpy( &stackFrameCopy, pStack16Frame, sizeof(stackFrameCopy) );
266 * Call the handler
268 ret_val = (*func_ptr)(arg_table[0], arg_table[1], arg_table[2],
269 arg_table[3], arg_table[4], arg_table[5],
270 arg_table[6], arg_table[7], arg_table[8],
271 arg_table[9], arg_table[10], arg_table[11],
272 arg_table[12], arg_table[13], arg_table[14],
273 arg_table[15]);
275 if (debugging_relay)
277 if (memcmp( &stackFrameCopy, pStack16Frame, sizeof(stackFrameCopy) ))
279 printf( "**** 16-bit stack corrupted!\n" );
281 printf("Returning %08x from %s (%s.%d) ds=%04x\n",
282 ret_val,
283 dll_p->export_name,
284 dll_builtin_table[dll_id].dll_name, ordinal,
285 pStack16Frame->ds );
288 return ret_val;
290 #endif
292 /**********************************************************************
293 * FindDLLTable
295 struct dll_table_entry_s *
296 FindDLLTable(char *dll_name)
298 int i;
300 for (i = 0; i < N_BUILTINS; i++)
301 if (strcasecmp(dll_builtin_table[i].dll_name, dll_name) == 0
302 && dll_builtin_table[i].dll_is_used)
303 #ifdef WINELIB
304 return dll_builtin_table[i].dll_number;
305 #else
306 return dll_builtin_table[i].dll_table;
307 #endif
308 return NULL;
311 /**********************************************************************
312 * FindOrdinalFromName
315 FindOrdinalFromName(struct dll_table_entry_s *dll_table, char *func_name)
317 int i, limit;
319 for (i = 0; i < N_BUILTINS; i++)
320 if (dll_table == dll_builtin_table[i].dll_table)
321 break;
323 if (i == N_BUILTINS)
324 return 0;
326 limit = dll_builtin_table[i].dll_table_length;
327 for (i = 0; i < limit; i++)
328 if (strcasecmp(dll_table[i].export_name, func_name) == 0)
329 return i;
331 return 0;
333 /**********************************************************************
334 * ReturnArg
337 ReturnArg(int arg)
339 return arg;
342 #ifndef WINELIB
343 #ifdef WINESTAT
344 void winestat(){
345 int i, j;
346 double perc;
347 int used, implemented;
348 int tused, timplemented;
349 struct dll_table_entry_s *table;
351 tused = 0;
352 timplemented = 0;
353 for (i = 0; i < N_BUILTINS; i++) {
354 table = dll_builtin_table[i].dll_table;
355 used = 0;
356 implemented = 0;
357 for(j=0; j < dll_builtin_table[i].dll_table_length; j++) {
358 if(table[j].used){
359 used++;
360 if (table[j].handler) implemented++;
361 else
362 printf("%s.%d not implemented\n",
363 dll_builtin_table[i].dll_name,
367 tused += used;
368 timplemented += implemented;
369 if(used)
370 perc = implemented * 100.00 / used;
371 else
372 perc = 0.0;
373 if (used)
374 printf("%s: %d of %d (%3.1f %%)\n", dll_builtin_table[i].dll_name, implemented, used, perc);
376 perc = timplemented * 100.00 / tused;
377 printf("TOTAL: %d of %d winapi functions implemented (%3.1f %%)\n",timplemented, tused, perc);
379 #endif /* WINESTAT */
380 #endif /* !WINELIB */