Fixed some issues found by winapi_check.
[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 WORD CALLBACK CallTo16Word( FARPROC16 target, INT nArgs )
67 { assert( FALSE ); }
68
69 LONG CALLBACK CallTo16Long( FARPROC16 target, INT nArgs )
70 { assert( FALSE ); }
71
72 void CALLBACK CallTo16RegisterShort( CONTEXT86 *context, INT nArgs )
73 { assert( FALSE ); }
74
75 void CALLBACK CallTo16RegisterLong ( CONTEXT86 *context, INT nArgs )
76 { assert( FALSE ); }
77
78 /***********************************************************************
79  *              __wine_call_from_16_word
80  */
81 WORD __cdecl __wine_call_from_16_word(...)
82 {
83     assert( FALSE );
84 }
85
86 /***********************************************************************
87  *              __wine_call_from_16_long
88  */
89 LONG __cdecl __wine_call_from_16_long(...)
90 {
91     assert( FALSE );
92 }
93
94 /***********************************************************************
95  *              __wine_call_from_16_regs
96  */
97 void __cdecl __wine_call_from_16_regs(...)
98 {
99     assert( FALSE );
100 }
101
102 /***********************************************************************
103  *              __wine_call_from_16_thunk
104  */
105 void __cdecl __wine_call_from_16_thunk(...)
106 {
107     assert( FALSE );
108 }
109
110 DWORD WINAPI CALL32_CBClient( FARPROC proc, LPWORD args, DWORD *esi )
111 { assert( FALSE ); }
112
113 DWORD WINAPI CALL32_CBClientEx( FARPROC proc, LPWORD args, DWORD *esi, INT *nArgs )
114 { assert( FALSE ); }
115 #endif
116
117
118 /* from relay32/relay386.c */
119 extern char **debug_relay_excludelist,**debug_relay_includelist;
120
121 /***********************************************************************
122  *           RELAY_DebugCallFrom16
123  */
124 void RELAY_DebugCallFrom16( CONTEXT86 *context )
125 {
126     STACK16FRAME *frame;
127     WORD ordinal;
128     char *args16, funstr[80];
129     const char *args;
130     int i, usecdecl, reg_func;
131
132     if (!TRACE_ON(relay)) return;
133
134     frame = CURRENT_STACK16;
135     args = BUILTIN_GetEntryPoint16( frame, funstr, &ordinal );
136     if (!args) return; /* happens for the two snoop register relays */
137     if (!RELAY_ShowDebugmsgRelay(funstr)) return;
138     DPRINTF( "Call %s(",funstr);
139     VA_START16( args16 );
140
141     usecdecl = ( *args == 'c' );
142     args += 2;
143     reg_func = (    memcmp( args, "regs_", 5 ) == 0
144                  || memcmp( args, "intr_", 5 ) == 0 );
145     args += 5;
146
147     if (usecdecl)
148     {
149         while (*args)
150         {
151             switch(*args)
152             {
153             case 'w':
154             case 's':
155                 DPRINTF( "0x%04x", *(WORD *)args16 );
156                 args16 += 2;
157                 break;
158             case 'l':
159                 DPRINTF( "0x%08x", *(int *)args16 );
160                 args16 += 4;
161                 break;
162             case 'p':
163                 DPRINTF( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
164                 args16 += 4;
165                 break;
166             case 't':
167             case 'T':
168                 DPRINTF( "%04x:%04x %s", *(WORD *)(args16+2), *(WORD *)args16,
169                          debugres_a( (LPSTR)PTR_SEG_TO_LIN(*(SEGPTR *)args16 )) );
170                 args16 += 4;
171                 break;
172             }
173             args++;
174             if (*args) DPRINTF( "," );
175         }
176     }
177     else  /* not cdecl */
178     {
179         /* Start with the last arg */
180         for (i = 0; args[i]; i++)
181         {
182             switch(args[i])
183             {
184             case 'w':
185             case 's':
186                 args16 += 2;
187                 break;
188             case 'l':
189             case 'p':
190             case 't':
191             case 'T':
192                 args16 += 4;
193                 break;
194             }
195         }
196
197         while (*args)
198         {
199             switch(*args)
200             {
201             case 'w':
202             case 's':
203                 args16 -= 2;
204                 DPRINTF( "0x%04x", *(WORD *)args16 );
205                 break;
206             case 'l':
207                 args16 -= 4;
208                 DPRINTF( "0x%08x", *(int *)args16 );
209                 break;
210             case 't':
211                 args16 -= 4;
212                 DPRINTF( "0x%08x %s", *(int *)args16,
213                          debugres_a( (LPSTR)PTR_SEG_TO_LIN(*(SEGPTR *)args16 )));
214                 break;
215             case 'p':
216                 args16 -= 4;
217                 DPRINTF( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
218                 break;
219             case 'T':
220                 args16 -= 4;
221                 DPRINTF( "%04x:%04x %s", *(WORD *)(args16+2), *(WORD *)args16,
222                          debugres_a( (LPSTR)PTR_SEG_TO_LIN(*(SEGPTR *)args16 )));
223                 break;
224             }
225             args++;
226             if (*args) DPRINTF( "," );
227         }
228     }
229
230     DPRINTF( ") ret=%04x:%04x ds=%04x\n", frame->cs, frame->ip, frame->ds );
231     VA_END16( args16 );
232
233     if (reg_func)
234         DPRINTF("     AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n",
235                 AX_reg(context), BX_reg(context), CX_reg(context),
236                 DX_reg(context), SI_reg(context), DI_reg(context),
237                 (WORD)context->SegEs, context->EFlags );
238
239     SYSLEVEL_CheckNotLevel( 2 );
240 }
241
242
243 /***********************************************************************
244  *           RELAY_DebugCallFrom16Ret
245  */
246 void RELAY_DebugCallFrom16Ret( CONTEXT86 *context, int ret_val )
247 {
248     STACK16FRAME *frame;
249     WORD ordinal;
250     char funstr[80];
251     const char *args;
252
253     if (!TRACE_ON(relay)) return;
254     frame = CURRENT_STACK16;
255     args = BUILTIN_GetEntryPoint16( frame, funstr, &ordinal );
256     if (!args) return;
257     if (!RELAY_ShowDebugmsgRelay(funstr)) return;
258     DPRINTF( "Ret  %s() ",funstr);
259
260     if ( memcmp( args+2, "long_", 5 ) == 0 )
261     {
262         DPRINTF( "retval=0x%08x ret=%04x:%04x ds=%04x\n",
263                  ret_val, frame->cs, frame->ip, frame->ds );
264     }
265     else if ( memcmp( args+2, "word_", 5 ) == 0 )
266     {
267         DPRINTF( "retval=0x%04x ret=%04x:%04x ds=%04x\n",
268                  ret_val & 0xffff, frame->cs, frame->ip, frame->ds );
269     }
270     else if (    memcmp( args+2, "regs_", 5 ) == 0 
271               || memcmp( args+2, "intr_", 5 ) == 0 )
272     {
273         DPRINTF("retval=none ret=%04x:%04x ds=%04x\n",
274                 (WORD)context->SegCs, LOWORD(context->Eip), (WORD)context->SegDs);
275         DPRINTF("     AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n",
276                 AX_reg(context), BX_reg(context), CX_reg(context),
277                 DX_reg(context), SI_reg(context), DI_reg(context),
278                 (WORD)context->SegEs, context->EFlags );
279     }
280
281     SYSLEVEL_CheckNotLevel( 2 );
282 }
283
284
285 /***********************************************************************
286  *           RELAY_DebugCallTo16
287  *
288  * 'target' contains either the function to call (normal CallTo16)
289  * or a pointer to the CONTEXT86 struct (register CallTo16).
290  * 'nb_args' is the number of argument bytes on the 16-bit stack; 
291  * 'reg_func' specifies whether we have a register CallTo16 or not.
292  */
293 void RELAY_DebugCallTo16( LPVOID target, int nb_args, BOOL reg_func )
294 {
295     WORD *stack16;
296     TEB *teb;
297
298     if (!TRACE_ON(relay)) return;
299     teb = NtCurrentTeb();
300     stack16 = (WORD *)THREAD_STACK16(teb);
301
302     nb_args /= sizeof(WORD);
303
304     if ( reg_func )
305     {
306         CONTEXT86 *context = (CONTEXT86 *)target;
307
308         DPRINTF("CallTo16(func=%04lx:%04x,ds=%04lx",
309                 context->SegCs, LOWORD(context->Eip), context->SegDs );
310         while (nb_args--) DPRINTF( ",0x%04x", *--stack16 );
311         DPRINTF(") ss:sp=%04x:%04x\n", SELECTOROF(teb->cur_stack),
312                 OFFSETOF(teb->cur_stack) );
313         DPRINTF("     AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x BP=%04x ES=%04x FS=%04x\n",
314                 AX_reg(context), BX_reg(context), CX_reg(context),
315                 DX_reg(context), SI_reg(context), DI_reg(context),
316                 BP_reg(context), (WORD)context->SegEs, (WORD)context->SegFs );
317     }
318     else
319     {
320         DPRINTF("CallTo16(func=%04x:%04x,ds=%04x",
321                 HIWORD(target), LOWORD(target), SELECTOROF(teb->cur_stack) );
322         while (nb_args--) DPRINTF( ",0x%04x", *--stack16 );
323         DPRINTF(") ss:sp=%04x:%04x\n", SELECTOROF(teb->cur_stack),
324                 OFFSETOF(teb->cur_stack) );
325     }
326
327     SYSLEVEL_CheckNotLevel( 2 );
328 }
329
330
331 /***********************************************************************
332  *           RELAY_DebugCallTo16Ret
333  */
334 void RELAY_DebugCallTo16Ret( BOOL reg_func, int ret_val )
335 {
336     if (!TRACE_ON(relay)) return;
337
338     if (!reg_func)
339     {
340         DPRINTF("CallTo16() ss:sp=%04x:%04x retval=0x%08x\n", 
341                 SELECTOROF(NtCurrentTeb()->cur_stack),
342                 OFFSETOF(NtCurrentTeb()->cur_stack), ret_val);
343     }
344     else
345     {
346         CONTEXT86 *context = (CONTEXT86 *)ret_val;
347
348         DPRINTF("CallTo16() ss:sp=%04x:%04x\n", 
349                 SELECTOROF(NtCurrentTeb()->cur_stack),
350                 OFFSETOF(NtCurrentTeb()->cur_stack));
351         DPRINTF("     AX=%04x BX=%04x CX=%04x DX=%04x BP=%04x SP=%04x\n",
352                 AX_reg(context), BX_reg(context), CX_reg(context),
353                 DX_reg(context), BP_reg(context), LOWORD(context->Esp));
354     }
355
356     SYSLEVEL_CheckNotLevel( 2 );
357 }