Renamed CallTo16* functions to wine_call_to_16* and export them from
[wine] / if1632 / relay.c
1 /*
2  * Copyright 1993 Robert J. Amstadt
3  * Copyright 1995 Alexandre Julliard
4  */
5
6 #include <assert.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include "wine/winbase16.h"
10 #include "winnt.h"
11 #include "heap.h"
12 #include "module.h"
13 #include "stackframe.h"
14 #include "selectors.h"
15 #include "builtin16.h"
16 #include "task.h"
17 #include "syslevel.h"
18 #include "debugtools.h"
19 #include "main.h"
20 #include "callback.h"
21
22 DEFAULT_DEBUG_CHANNEL(relay);
23
24 /***********************************************************************
25  *           RELAY_Init
26  */
27 BOOL RELAY_Init(void)
28 {
29 #ifdef __i386__
30     WORD codesel;
31
32       /* Allocate the code selector for CallTo16 routines */
33
34     extern void Call16_Ret_Start(), Call16_Ret_End();
35     extern void CallTo16_Ret();
36     extern void CALL32_CBClient_Ret();
37     extern void CALL32_CBClientEx_Ret();
38     extern SEGPTR CallTo16_RetAddr;
39     extern DWORD CallTo16_DataSelector;
40     extern SEGPTR CALL32_CBClient_RetAddr;
41     extern SEGPTR CALL32_CBClientEx_RetAddr;
42
43     codesel = SELECTOR_AllocBlock( (void *)Call16_Ret_Start,
44                                    (char *)Call16_Ret_End - (char *)Call16_Ret_Start,
45                                    WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT );
46     if (!codesel) return FALSE;
47
48       /* Patch the return addresses for CallTo16 routines */
49
50     CallTo16_DataSelector = __get_ds();
51     CallTo16_RetAddr = 
52         PTR_SEG_OFF_TO_SEGPTR( codesel, (char*)CallTo16_Ret - (char*)Call16_Ret_Start );
53     CALL32_CBClient_RetAddr = 
54         PTR_SEG_OFF_TO_SEGPTR( codesel, (char*)CALL32_CBClient_Ret - (char*)Call16_Ret_Start );
55     CALL32_CBClientEx_RetAddr = 
56         PTR_SEG_OFF_TO_SEGPTR( codesel, (char*)CALL32_CBClientEx_Ret - (char*)Call16_Ret_Start );
57 #endif
58     return TRUE;
59 }
60
61 /*
62  * Stubs for the CallTo16/CallFrom16 routines on non-Intel architectures
63  * (these will never be called but need to be present to satisfy the linker ...)
64  */
65 #ifndef __i386__
66 /***********************************************************************
67  *              wine_call_to_16_word
68  */
69 WORD WINAPI wine_call_to_16_word( FARPROC16 target, INT nArgs )
70 {
71     assert( FALSE );
72 }
73
74 /***********************************************************************
75  *              wine_call_to_16_long
76  */
77 LONG WINAPI wine_call_to_16_long( FARPROC16 target, INT nArgs )
78 {
79     assert( FALSE );
80 }
81
82 /***********************************************************************
83  *              wine_call_to_16_regs_short
84  */
85 void WINAPI wine_call_to_16_regs_short( CONTEXT86 *context, INT nArgs )
86 {
87     assert( FALSE );
88 }
89
90 /***********************************************************************
91  *              wine_call_to_16_regs_long
92  */
93 void WINAPI wine_call_to_16_regs_long ( CONTEXT86 *context, INT nArgs )
94 {
95     assert( FALSE );
96 }
97
98 /***********************************************************************
99  *              __wine_call_from_16_word
100  */
101 WORD __cdecl __wine_call_from_16_word(...)
102 {
103     assert( FALSE );
104 }
105
106 /***********************************************************************
107  *              __wine_call_from_16_long
108  */
109 LONG __cdecl __wine_call_from_16_long(...)
110 {
111     assert( FALSE );
112 }
113
114 /***********************************************************************
115  *              __wine_call_from_16_regs
116  */
117 void __cdecl __wine_call_from_16_regs(...)
118 {
119     assert( FALSE );
120 }
121
122 /***********************************************************************
123  *              __wine_call_from_16_thunk
124  */
125 void __cdecl __wine_call_from_16_thunk(...)
126 {
127     assert( FALSE );
128 }
129
130 DWORD WINAPI CALL32_CBClient( FARPROC proc, LPWORD args, DWORD *esi )
131 { assert( FALSE ); }
132
133 DWORD WINAPI CALL32_CBClientEx( FARPROC proc, LPWORD args, DWORD *esi, INT *nArgs )
134 { assert( FALSE ); }
135 #endif
136
137
138 /* from relay32/relay386.c */
139 extern char **debug_relay_excludelist,**debug_relay_includelist;
140
141 /***********************************************************************
142  *           RELAY_DebugCallFrom16
143  */
144 void RELAY_DebugCallFrom16( CONTEXT86 *context )
145 {
146     STACK16FRAME *frame;
147     WORD ordinal;
148     char *args16, funstr[80];
149     const char *args;
150     int i, usecdecl, reg_func;
151
152     if (!TRACE_ON(relay)) return;
153
154     frame = CURRENT_STACK16;
155     args = BUILTIN_GetEntryPoint16( frame, funstr, &ordinal );
156     if (!args) return; /* happens for the two snoop register relays */
157     if (!RELAY_ShowDebugmsgRelay(funstr)) return;
158     DPRINTF( "Call %s(",funstr);
159     VA_START16( args16 );
160
161     usecdecl = ( *args == 'c' );
162     args += 2;
163     reg_func = (    memcmp( args, "regs_", 5 ) == 0
164                  || memcmp( args, "intr_", 5 ) == 0 );
165     args += 5;
166
167     if (usecdecl)
168     {
169         while (*args)
170         {
171             switch(*args)
172             {
173             case 'w':
174             case 's':
175                 DPRINTF( "0x%04x", *(WORD *)args16 );
176                 args16 += 2;
177                 break;
178             case 'l':
179                 DPRINTF( "0x%08x", *(int *)args16 );
180                 args16 += 4;
181                 break;
182             case 'p':
183                 DPRINTF( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
184                 args16 += 4;
185                 break;
186             case 't':
187             case 'T':
188                 DPRINTF( "%04x:%04x %s", *(WORD *)(args16+2), *(WORD *)args16,
189                          debugres_a( (LPSTR)PTR_SEG_TO_LIN(*(SEGPTR *)args16 )) );
190                 args16 += 4;
191                 break;
192             }
193             args++;
194             if (*args) DPRINTF( "," );
195         }
196     }
197     else  /* not cdecl */
198     {
199         /* Start with the last arg */
200         for (i = 0; args[i]; i++)
201         {
202             switch(args[i])
203             {
204             case 'w':
205             case 's':
206                 args16 += 2;
207                 break;
208             case 'l':
209             case 'p':
210             case 't':
211             case 'T':
212                 args16 += 4;
213                 break;
214             }
215         }
216
217         while (*args)
218         {
219             switch(*args)
220             {
221             case 'w':
222             case 's':
223                 args16 -= 2;
224                 DPRINTF( "0x%04x", *(WORD *)args16 );
225                 break;
226             case 'l':
227                 args16 -= 4;
228                 DPRINTF( "0x%08x", *(int *)args16 );
229                 break;
230             case 't':
231                 args16 -= 4;
232                 DPRINTF( "0x%08x %s", *(int *)args16,
233                          debugres_a( (LPSTR)PTR_SEG_TO_LIN(*(SEGPTR *)args16 )));
234                 break;
235             case 'p':
236                 args16 -= 4;
237                 DPRINTF( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
238                 break;
239             case 'T':
240                 args16 -= 4;
241                 DPRINTF( "%04x:%04x %s", *(WORD *)(args16+2), *(WORD *)args16,
242                          debugres_a( (LPSTR)PTR_SEG_TO_LIN(*(SEGPTR *)args16 )));
243                 break;
244             }
245             args++;
246             if (*args) DPRINTF( "," );
247         }
248     }
249
250     DPRINTF( ") ret=%04x:%04x ds=%04x\n", frame->cs, frame->ip, frame->ds );
251     VA_END16( args16 );
252
253     if (reg_func)
254         DPRINTF("     AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n",
255                 AX_reg(context), BX_reg(context), CX_reg(context),
256                 DX_reg(context), SI_reg(context), DI_reg(context),
257                 (WORD)context->SegEs, context->EFlags );
258
259     SYSLEVEL_CheckNotLevel( 2 );
260 }
261
262
263 /***********************************************************************
264  *           RELAY_DebugCallFrom16Ret
265  */
266 void RELAY_DebugCallFrom16Ret( CONTEXT86 *context, int ret_val )
267 {
268     STACK16FRAME *frame;
269     WORD ordinal;
270     char funstr[80];
271     const char *args;
272
273     if (!TRACE_ON(relay)) return;
274     frame = CURRENT_STACK16;
275     args = BUILTIN_GetEntryPoint16( frame, funstr, &ordinal );
276     if (!args) return;
277     if (!RELAY_ShowDebugmsgRelay(funstr)) return;
278     DPRINTF( "Ret  %s() ",funstr);
279
280     if ( memcmp( args+2, "long_", 5 ) == 0 )
281     {
282         DPRINTF( "retval=0x%08x ret=%04x:%04x ds=%04x\n",
283                  ret_val, frame->cs, frame->ip, frame->ds );
284     }
285     else if ( memcmp( args+2, "word_", 5 ) == 0 )
286     {
287         DPRINTF( "retval=0x%04x ret=%04x:%04x ds=%04x\n",
288                  ret_val & 0xffff, frame->cs, frame->ip, frame->ds );
289     }
290     else if (    memcmp( args+2, "regs_", 5 ) == 0 
291               || memcmp( args+2, "intr_", 5 ) == 0 )
292     {
293         DPRINTF("retval=none ret=%04x:%04x ds=%04x\n",
294                 (WORD)context->SegCs, LOWORD(context->Eip), (WORD)context->SegDs);
295         DPRINTF("     AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n",
296                 AX_reg(context), BX_reg(context), CX_reg(context),
297                 DX_reg(context), SI_reg(context), DI_reg(context),
298                 (WORD)context->SegEs, context->EFlags );
299     }
300
301     SYSLEVEL_CheckNotLevel( 2 );
302 }
303
304
305 /***********************************************************************
306  *           RELAY_DebugCallTo16
307  *
308  * 'target' contains either the function to call (normal CallTo16)
309  * or a pointer to the CONTEXT86 struct (register CallTo16).
310  * 'nb_args' is the number of argument bytes on the 16-bit stack; 
311  * 'reg_func' specifies whether we have a register CallTo16 or not.
312  */
313 void RELAY_DebugCallTo16( LPVOID target, int nb_args, BOOL reg_func )
314 {
315     WORD *stack16;
316     TEB *teb;
317
318     if (!TRACE_ON(relay)) return;
319     teb = NtCurrentTeb();
320     stack16 = (WORD *)THREAD_STACK16(teb);
321
322     nb_args /= sizeof(WORD);
323
324     if ( reg_func )
325     {
326         CONTEXT86 *context = (CONTEXT86 *)target;
327
328         DPRINTF("CallTo16(func=%04lx:%04x,ds=%04lx",
329                 context->SegCs, LOWORD(context->Eip), context->SegDs );
330         while (nb_args--) DPRINTF( ",0x%04x", *--stack16 );
331         DPRINTF(") ss:sp=%04x:%04x\n", SELECTOROF(teb->cur_stack),
332                 OFFSETOF(teb->cur_stack) );
333         DPRINTF("     AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x BP=%04x ES=%04x FS=%04x\n",
334                 AX_reg(context), BX_reg(context), CX_reg(context),
335                 DX_reg(context), SI_reg(context), DI_reg(context),
336                 BP_reg(context), (WORD)context->SegEs, (WORD)context->SegFs );
337     }
338     else
339     {
340         DPRINTF("CallTo16(func=%04x:%04x,ds=%04x",
341                 HIWORD(target), LOWORD(target), SELECTOROF(teb->cur_stack) );
342         while (nb_args--) DPRINTF( ",0x%04x", *--stack16 );
343         DPRINTF(") ss:sp=%04x:%04x\n", SELECTOROF(teb->cur_stack),
344                 OFFSETOF(teb->cur_stack) );
345     }
346
347     SYSLEVEL_CheckNotLevel( 2 );
348 }
349
350
351 /***********************************************************************
352  *           RELAY_DebugCallTo16Ret
353  */
354 void RELAY_DebugCallTo16Ret( BOOL reg_func, int ret_val )
355 {
356     if (!TRACE_ON(relay)) return;
357
358     if (!reg_func)
359     {
360         DPRINTF("CallTo16() ss:sp=%04x:%04x retval=0x%08x\n", 
361                 SELECTOROF(NtCurrentTeb()->cur_stack),
362                 OFFSETOF(NtCurrentTeb()->cur_stack), ret_val);
363     }
364     else
365     {
366         CONTEXT86 *context = (CONTEXT86 *)ret_val;
367
368         DPRINTF("CallTo16() ss:sp=%04x:%04x\n", 
369                 SELECTOROF(NtCurrentTeb()->cur_stack),
370                 OFFSETOF(NtCurrentTeb()->cur_stack));
371         DPRINTF("     AX=%04x BX=%04x CX=%04x DX=%04x BP=%04x SP=%04x\n",
372                 AX_reg(context), BX_reg(context), CX_reg(context),
373                 DX_reg(context), BP_reg(context), LOWORD(context->Esp));
374     }
375
376     SYSLEVEL_CheckNotLevel( 2 );
377 }