- don't initialize with pFirstLDD if pFirstLDD isn't initialized yet either
[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 "callback.h"
20
21 DEFAULT_DEBUG_CHANNEL(relay);
22
23 /***********************************************************************
24  *           RELAY_Init
25  */
26 BOOL RELAY_Init(void)
27 {
28 #ifdef __i386__
29     WORD codesel;
30
31       /* Allocate the code selector for CallTo16 routines */
32
33     extern void Call16_Ret_Start(), Call16_Ret_End();
34     extern void CallTo16_Ret();
35     extern void CALL32_CBClient_Ret();
36     extern void CALL32_CBClientEx_Ret();
37     extern SEGPTR CallTo16_RetAddr;
38     extern DWORD CallTo16_DataSelector;
39     extern SEGPTR CALL32_CBClient_RetAddr;
40     extern SEGPTR CALL32_CBClientEx_RetAddr;
41
42     codesel = SELECTOR_AllocBlock( (void *)Call16_Ret_Start,
43                                    (char *)Call16_Ret_End - (char *)Call16_Ret_Start,
44                                    WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT );
45     if (!codesel) return FALSE;
46
47       /* Patch the return addresses for CallTo16 routines */
48
49     CallTo16_DataSelector = __get_ds();
50     CallTo16_RetAddr = 
51         MAKESEGPTR( codesel, (char*)CallTo16_Ret - (char*)Call16_Ret_Start );
52     CALL32_CBClient_RetAddr = 
53         MAKESEGPTR( codesel, (char*)CALL32_CBClient_Ret - (char*)Call16_Ret_Start );
54     CALL32_CBClientEx_RetAddr = 
55         MAKESEGPTR( codesel, (char*)CALL32_CBClientEx_Ret - (char*)Call16_Ret_Start );
56 #endif
57     return TRUE;
58 }
59
60 /*
61  * Stubs for the CallTo16/CallFrom16 routines on non-Intel architectures
62  * (these will never be called but need to be present to satisfy the linker ...)
63  */
64 #ifndef __i386__
65 /***********************************************************************
66  *              wine_call_to_16_word
67  */
68 WORD WINAPI wine_call_to_16_word( FARPROC16 target, INT nArgs )
69 {
70     assert( FALSE );
71 }
72
73 /***********************************************************************
74  *              wine_call_to_16_long
75  */
76 LONG WINAPI wine_call_to_16_long( FARPROC16 target, INT nArgs )
77 {
78     assert( FALSE );
79 }
80
81 /***********************************************************************
82  *              wine_call_to_16_regs_short
83  */
84 void WINAPI wine_call_to_16_regs_short( CONTEXT86 *context, INT nArgs )
85 {
86     assert( FALSE );
87 }
88
89 /***********************************************************************
90  *              wine_call_to_16_regs_long
91  */
92 void WINAPI wine_call_to_16_regs_long ( CONTEXT86 *context, INT nArgs )
93 {
94     assert( FALSE );
95 }
96
97 /***********************************************************************
98  *              __wine_call_from_16_word
99  */
100 WORD __cdecl __wine_call_from_16_word(...)
101 {
102     assert( FALSE );
103 }
104
105 /***********************************************************************
106  *              __wine_call_from_16_long
107  */
108 LONG __cdecl __wine_call_from_16_long(...)
109 {
110     assert( FALSE );
111 }
112
113 /***********************************************************************
114  *              __wine_call_from_16_regs
115  */
116 void __cdecl __wine_call_from_16_regs(...)
117 {
118     assert( FALSE );
119 }
120
121 /***********************************************************************
122  *              __wine_call_from_16_thunk
123  */
124 void __cdecl __wine_call_from_16_thunk(...)
125 {
126     assert( FALSE );
127 }
128
129 DWORD WINAPI CALL32_CBClient( FARPROC proc, LPWORD args, DWORD *esi )
130 { assert( FALSE ); }
131
132 DWORD WINAPI CALL32_CBClientEx( FARPROC proc, LPWORD args, DWORD *esi, INT *nArgs )
133 { assert( FALSE ); }
134 #endif
135
136
137 /* from relay32/relay386.c */
138 extern char **debug_relay_excludelist,**debug_relay_includelist;
139 extern int RELAY_ShowDebugmsgRelay(const char *func);
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( MapSL(*(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( MapSL(*(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( MapSL(*(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 }