Fixed definitions of TTTOOLINFOA/W_V1_SIZE and
[wine] / dlls / kernel / relay16.c
1 /*
2  * Copyright 1993 Robert J. Amstadt
3  * Copyright 1995 Alexandre Julliard
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include "config.h"
21 #include "wine/port.h"
22
23 #include <assert.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wine/winbase16.h"
32 #include "module.h"
33 #include "stackframe.h"
34 #include "selectors.h"
35 #include "builtin16.h"
36 #include "syslevel.h"
37 #include "wine/library.h"
38 #include "wine/debug.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(relay);
41
42 /*
43  * Stubs for the CallTo16/CallFrom16 routines on non-Intel architectures
44  * (these will never be called but need to be present to satisfy the linker ...)
45  */
46 #ifndef __i386__
47 /***********************************************************************
48  *              __wine_call_from_16_word (KERNEL32.@)
49  */
50 WORD __wine_call_from_16_word()
51 {
52     assert( FALSE );
53 }
54
55 /***********************************************************************
56  *              __wine_call_from_16_long (KERNEL32.@)
57  */
58 LONG __wine_call_from_16_long()
59 {
60     assert( FALSE );
61 }
62
63 /***********************************************************************
64  *              __wine_call_from_16_regs (KERNEL32.@)
65  */
66 void __wine_call_from_16_regs()
67 {
68     assert( FALSE );
69 }
70
71 DWORD WINAPI CALL32_CBClient( FARPROC proc, LPWORD args, DWORD *esi )
72 { assert( FALSE ); }
73
74 DWORD WINAPI CALL32_CBClientEx( FARPROC proc, LPWORD args, DWORD *esi, INT *nArgs )
75 { assert( FALSE ); }
76 #endif
77
78
79 /***********************************************************************
80  *           RELAY_ShowDebugmsgRelay
81  *
82  * Simple function to decide if a particular debugging message is
83  * wanted.
84  */
85 static int RELAY_ShowDebugmsgRelay(const char *func)
86 {
87   /* from relay32/relay386.c */
88   extern const char **debug_relay_excludelist,**debug_relay_includelist;
89
90   if(debug_relay_excludelist || debug_relay_includelist) {
91     const char *term = strchr(func, ':');
92     const char **listitem;
93     int len, len2, itemlen, show;
94
95     if(debug_relay_excludelist) {
96       show = 1;
97       listitem = debug_relay_excludelist;
98     } else {
99       show = 0;
100       listitem = debug_relay_includelist;
101     }
102     assert(term);
103     assert(strlen(term) > 2);
104     len = term - func;
105     len2 = strchr(func, '.') - func;
106     assert(len2 && len2 > 0 && len2 < 64);
107     term += 2;
108     for(; *listitem; listitem++) {
109       itemlen = strlen(*listitem);
110       if((itemlen == len && !strncasecmp(*listitem, func, len)) ||
111          (itemlen == len2 && !strncasecmp(*listitem, func, len2)) ||
112          !strcasecmp(*listitem, term)) {
113         show = !show;
114        break;
115       }
116     }
117     return show;
118   }
119   return 1;
120 }
121
122
123 /***********************************************************************
124  *           get_entry_point
125  *
126  * Return the ordinal, name, and type info corresponding to a CS:IP address.
127  */
128 static const CALLFROM16 *get_entry_point( STACK16FRAME *frame, LPSTR name, WORD *pOrd )
129 {
130     WORD i, max_offset;
131     register BYTE *p;
132     NE_MODULE *pModule;
133     ET_BUNDLE *bundle;
134     ET_ENTRY *entry;
135
136     if (!(pModule = NE_GetPtr( FarGetOwner16( GlobalHandle16( frame->module_cs ) ))))
137         return NULL;
138
139     max_offset = 0;
140     *pOrd = 0;
141     bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
142     do
143     {
144         entry = (ET_ENTRY *)((BYTE *)bundle+6);
145         for (i = bundle->first + 1; i <= bundle->last; i++)
146         {
147             if ((entry->offs < frame->entry_ip)
148             && (entry->segnum == 1) /* code segment ? */
149             && (entry->offs >= max_offset))
150             {
151                 max_offset = entry->offs;
152                 *pOrd = i;
153             }
154             entry++;
155         }
156     } while ( (bundle->next)
157            && (bundle = (ET_BUNDLE *)((BYTE *)pModule+bundle->next)));
158
159     /* Search for the name in the resident names table */
160     /* (built-in modules have no non-resident table)   */
161
162     p = (BYTE *)pModule + pModule->name_table;
163     while (*p)
164     {
165         p += *p + 1 + sizeof(WORD);
166         if (*(WORD *)(p + *p + 1) == *pOrd) break;
167     }
168
169     sprintf( name, "%.*s.%d: %.*s",
170              *((BYTE *)pModule + pModule->name_table),
171              (char *)pModule + pModule->name_table + 1,
172              *pOrd, *p, (char *)(p + 1) );
173
174     /* Retrieve entry point call structure */
175     p = MapSL( MAKESEGPTR( frame->module_cs, frame->callfrom_ip ) );
176     /* p now points to lret, get the start of CALLFROM16 structure */
177     return (CALLFROM16 *)(p - (BYTE *)&((CALLFROM16 *)0)->lret);
178 }
179
180
181 /***********************************************************************
182  *           RELAY_DebugCallFrom16
183  */
184 void RELAY_DebugCallFrom16( CONTEXT86 *context )
185 {
186     STACK16FRAME *frame;
187     WORD ordinal;
188     char *args16, funstr[80];
189     const CALLFROM16 *call;
190     int i;
191
192     if (!TRACE_ON(relay)) return;
193
194     frame = CURRENT_STACK16;
195     call = get_entry_point( frame, funstr, &ordinal );
196     if (!call) return; /* happens for the two snoop register relays */
197     if (!RELAY_ShowDebugmsgRelay(funstr)) return;
198     DPRINTF( "%04lx:Call %s(",GetCurrentThreadId(),funstr);
199     args16 = (char *)(frame + 1);
200
201     if (call->lret == 0xcb66)  /* cdecl */
202     {
203         for (i = 0; i < 20; i++)
204         {
205             int type = (call->arg_types[i / 10] >> (3 * (i % 10))) & 7;
206
207             if (type == ARG_NONE) break;
208             if (i) DPRINTF( "," );
209             switch(type)
210             {
211             case ARG_WORD:
212             case ARG_SWORD:
213                 DPRINTF( "%04x", *(WORD *)args16 );
214                 args16 += sizeof(WORD);
215                 break;
216             case ARG_LONG:
217                 DPRINTF( "%08x", *(int *)args16 );
218                 args16 += sizeof(int);
219                 break;
220             case ARG_PTR:
221                 DPRINTF( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
222                 args16 += sizeof(SEGPTR);
223                 break;
224             case ARG_STR:
225                 DPRINTF( "%08x %s", *(int *)args16,
226                          debugstr_a( MapSL(*(SEGPTR *)args16 )));
227                 args16 += sizeof(int);
228                 break;
229             case ARG_SEGSTR:
230                 DPRINTF( "%04x:%04x %s", *(WORD *)(args16+2), *(WORD *)args16,
231                          debugstr_a( MapSL(*(SEGPTR *)args16 )) );
232                 args16 += sizeof(SEGPTR);
233                 break;
234             default:
235                 break;
236             }
237         }
238     }
239     else  /* not cdecl */
240     {
241         /* Start with the last arg */
242         args16 += call->nArgs;
243         for (i = 0; i < 20; i++)
244         {
245             int type = (call->arg_types[i / 10] >> (3 * (i % 10))) & 7;
246
247             if (type == ARG_NONE) break;
248             if (i) DPRINTF( "," );
249             switch(type)
250             {
251             case ARG_WORD:
252             case ARG_SWORD:
253                 args16 -= sizeof(WORD);
254                 DPRINTF( "%04x", *(WORD *)args16 );
255                 break;
256             case ARG_LONG:
257                 args16 -= sizeof(int);
258                 DPRINTF( "%08x", *(int *)args16 );
259                 break;
260             case ARG_PTR:
261                 args16 -= sizeof(SEGPTR);
262                 DPRINTF( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
263                 break;
264             case ARG_STR:
265                 args16 -= sizeof(int);
266                 DPRINTF( "%08x %s", *(int *)args16,
267                          debugstr_a( MapSL(*(SEGPTR *)args16 )));
268                 break;
269             case ARG_SEGSTR:
270                 args16 -= sizeof(SEGPTR);
271                 DPRINTF( "%04x:%04x %s", *(WORD *)(args16+2), *(WORD *)args16,
272                          debugstr_a( MapSL(*(SEGPTR *)args16 )) );
273                 break;
274             default:
275                 break;
276             }
277         }
278     }
279
280     DPRINTF( ") ret=%04x:%04x ds=%04x\n", frame->cs, frame->ip, frame->ds );
281
282     if (call->arg_types[0] & ARG_REGISTER)
283         DPRINTF("     AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n",
284                 (WORD)context->Eax, (WORD)context->Ebx, (WORD)context->Ecx,
285                 (WORD)context->Edx, (WORD)context->Esi, (WORD)context->Edi,
286                 (WORD)context->SegEs, context->EFlags );
287
288     SYSLEVEL_CheckNotLevel( 2 );
289 }
290
291
292 /***********************************************************************
293  *           RELAY_DebugCallFrom16Ret
294  */
295 void RELAY_DebugCallFrom16Ret( CONTEXT86 *context, int ret_val )
296 {
297     STACK16FRAME *frame;
298     WORD ordinal;
299     char funstr[80];
300     const CALLFROM16 *call;
301
302     if (!TRACE_ON(relay)) return;
303     frame = CURRENT_STACK16;
304     call = get_entry_point( frame, funstr, &ordinal );
305     if (!call) return;
306     if (!RELAY_ShowDebugmsgRelay(funstr)) return;
307     DPRINTF( "%04lx:Ret  %s() ",GetCurrentThreadId(),funstr);
308
309     if (call->arg_types[0] & ARG_REGISTER)
310     {
311         DPRINTF("retval=none ret=%04x:%04x ds=%04x\n",
312                 (WORD)context->SegCs, LOWORD(context->Eip), (WORD)context->SegDs);
313         DPRINTF("     AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n",
314                 (WORD)context->Eax, (WORD)context->Ebx, (WORD)context->Ecx,
315                 (WORD)context->Edx, (WORD)context->Esi, (WORD)context->Edi,
316                 (WORD)context->SegEs, context->EFlags );
317     }
318     else if (call->arg_types[0] & ARG_RET16)
319     {
320         DPRINTF( "retval=%04x ret=%04x:%04x ds=%04x\n",
321                  ret_val & 0xffff, frame->cs, frame->ip, frame->ds );
322     }
323     else
324     {
325         DPRINTF( "retval=%08x ret=%04x:%04x ds=%04x\n",
326                  ret_val, frame->cs, frame->ip, frame->ds );
327     }
328     SYSLEVEL_CheckNotLevel( 2 );
329 }