/* * Copyright 1993 Robert J. Amstadt * Copyright 1995 Alexandre Julliard */ #include #include "dlls.h" #include "global.h" #include "module.h" #include "registers.h" #include "stackframe.h" #include "stddebug.h" /* #define DEBUG_RELAY */ #include "debug.h" #if 0 /* Make make_debug think these were really used */ dprintf_relay #endif #define DLL_ENTRY(name,flags) \ { #name, name##_Code_Start, name##_Data_Start, \ name##_Module_Start, name##_Module_End, (flags) } BUILTIN_DLL dll_builtin_table[] = { /* Win16 DLLs */ DLL_ENTRY( KERNEL, DLL_FLAG_ALWAYS_USED), DLL_ENTRY( USER, DLL_FLAG_ALWAYS_USED), DLL_ENTRY( GDI, DLL_FLAG_ALWAYS_USED), DLL_ENTRY( WIN87EM, DLL_FLAG_NOT_USED), DLL_ENTRY( SHELL, 0), DLL_ENTRY( SOUND, 0), DLL_ENTRY( KEYBOARD, 0), DLL_ENTRY( WINSOCK, 0), DLL_ENTRY( STRESS, 0), DLL_ENTRY( MMSYSTEM, 0), DLL_ENTRY( SYSTEM, 0), DLL_ENTRY( TOOLHELP, 0), DLL_ENTRY( MOUSE, 0), DLL_ENTRY( COMMDLG, DLL_FLAG_NOT_USED), DLL_ENTRY( OLE2, DLL_FLAG_NOT_USED), DLL_ENTRY( OLE2CONV, DLL_FLAG_NOT_USED), DLL_ENTRY( OLE2DISP, DLL_FLAG_NOT_USED), DLL_ENTRY( OLE2NLS, DLL_FLAG_NOT_USED), DLL_ENTRY( OLE2PROX, DLL_FLAG_NOT_USED), DLL_ENTRY( OLECLI, DLL_FLAG_NOT_USED), DLL_ENTRY( OLESVR, DLL_FLAG_NOT_USED), DLL_ENTRY( COMPOBJ, DLL_FLAG_NOT_USED), DLL_ENTRY( STORAGE, DLL_FLAG_NOT_USED), DLL_ENTRY( WINPROCS, DLL_FLAG_ALWAYS_USED), DLL_ENTRY( DDEML, DLL_FLAG_NOT_USED), DLL_ENTRY( LZEXPAND, 0), DLL_ENTRY( W32SYS, 0), /* Win32 DLLs */ DLL_ENTRY( ADVAPI32, 0), DLL_ENTRY( COMCTL32, 0), DLL_ENTRY( COMDLG32, 0), DLL_ENTRY( OLE32, 0), DLL_ENTRY( GDI32, 0), DLL_ENTRY( KERNEL32, DLL_FLAG_ALWAYS_USED), DLL_ENTRY( SHELL32, 0), DLL_ENTRY( USER32, 0), DLL_ENTRY( WINPROCS32, DLL_FLAG_ALWAYS_USED), DLL_ENTRY( WINSPOOL, 0), /* Last entry */ { NULL, } }; /* Saved 16-bit stack for current process (Win16 only) */ WORD IF1632_Saved16_ss = 0; WORD IF1632_Saved16_sp = 0; /* Saved 32-bit stack for current process (Win16 only) */ DWORD IF1632_Saved32_esp = 0; SEGPTR IF1632_Stack32_base = 0; /* Original Unix stack */ DWORD IF1632_Original32_esp; /*********************************************************************** * RELAY_Init */ BOOL RELAY_Init(void) { WORD codesel; /* Allocate the code selector for CallTo16 routines */ extern void CALLTO16_Start(), CALLTO16_End(); extern void CALLTO16_Ret_word(), CALLTO16_Ret_long(); extern DWORD CALLTO16_RetAddr_word, CALLTO16_RetAddr_long; codesel = GLOBAL_CreateBlock( GMEM_FIXED, (void *)CALLTO16_Start, (int)CALLTO16_End - (int)CALLTO16_Start, 0, TRUE, TRUE, FALSE, NULL ); if (!codesel) return FALSE; /* Patch the return addresses for CallTo16 routines */ CALLTO16_RetAddr_word=MAKELONG( (int)CALLTO16_Ret_word-(int)CALLTO16_Start, codesel ); CALLTO16_RetAddr_long=MAKELONG( (int)CALLTO16_Ret_long-(int)CALLTO16_Start, codesel ); return TRUE; } /*********************************************************************** * RELAY_DebugCallFrom16 */ void RELAY_DebugCallFrom16( int func_type, char *args, void *entry_point, int args32 ) { STACK16FRAME *frame; struct dll_table_s *table; char *args16, *name; int i; if (!debugging_relay) return; frame = CURRENT_STACK16; table = &dll_builtin_table[frame->dll_id-1]; name = MODULE_GetEntryPointName( table->hModule, frame->ordinal_number ); printf( "Call %s.%d: %.*s(", table->name, frame->ordinal_number, *name, name + 1 ); args16 = (char *)frame->args; for (i = 0; i < strlen(args); i++) { switch(args[i]) { case 'w': case 's': args16 += 2; break; case 'l': case 'p': args16 += 4; break; } } while (*args) { switch(*args) { case 'w': case 's': args16 -= 2; printf( "0x%04x", *(WORD *)args16 ); break; case 'l': args16 -= 4; printf( "0x%08x", *(int *)args16 ); break; case 'p': args16 -= 4; printf( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 ); break; } args++; if (*args) printf( "," ); } printf( ") ret=%04x:%04x ds=%04x\n", frame->cs, frame->ip, frame->ds ); if (func_type == 2) /* register function */ { struct sigcontext_struct *context = (struct sigcontext_struct *)&args32; printf( " AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n", AX_reg(context), BX_reg(context), CX_reg(context), DX_reg(context), SI_reg(context), DI_reg(context), ES_reg(context), EFL_reg(context) ); } } /*********************************************************************** * RELAY_DebugCallFrom16Ret */ void RELAY_DebugCallFrom16Ret( int func_type, int ret_val, int args32 ) { STACK16FRAME *frame; struct dll_table_s *table; char *name; if (*(DWORD *)PTR_SEG_TO_LIN(IF1632_Stack32_base) != 0xDEADBEEF) { fprintf(stderr, "Wine wrote past the end of the 32 bit stack. Please report this.\n"); exit(1); /* There's probably no point in going on */ } if (!debugging_relay) return; frame = CURRENT_STACK16; table = &dll_builtin_table[frame->dll_id-1]; name = MODULE_GetEntryPointName( table->hModule, frame->ordinal_number ); printf( "Ret %s.%d: %.*s() ", table->name, frame->ordinal_number, *name, name + 1 ); switch(func_type) { case 0: /* long */ printf( "retval=0x%08x ret=%04x:%04x ds=%04x\n", ret_val, frame->cs, frame->ip, frame->ds ); break; case 1: /* word */ printf( "retval=0x%04x ret=%04x:%04x ds=%04x\n", ret_val & 0xffff, frame->cs, frame->ip, frame->ds ); break; case 2: /* regs */ printf( "retval=none ret=%04x:%04x ds=%04x\n", frame->cs, frame->ip, frame->ds ); { struct sigcontext_struct *context = (struct sigcontext_struct *)&args32; printf( " AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n", AX_reg(context), BX_reg(context), CX_reg(context), DX_reg(context), SI_reg(context), DI_reg(context), ES_reg(context), EFL_reg(context) ); } break; } } /*********************************************************************** * RELAY_Unimplemented16 * * This function is called for unimplemented 16-bit entry points (declared * as 'stub' in the spec file). */ void RELAY_Unimplemented16(void) { STACK16FRAME *frame = CURRENT_STACK16; struct dll_table_s *table = &dll_builtin_table[frame->dll_id-1]; char *name = MODULE_GetEntryPointName( table->hModule, frame->ordinal_number ); fprintf( stderr, "No handler for routine %s.%d (%.*s)\n", table->name, frame->ordinal_number, *name, name + 1 ); exit(1); } /*********************************************************************** * RELAY_Unimplemented32 * * This function is called for unimplemented 32-bit entry points (declared * as 'stub' in the spec file). * (The args are the same than for RELAY_DebugCallFrom32). */ void RELAY_Unimplemented32( int nb_args, void *entry_point, const char *func_name ) { fprintf( stderr, "No handler for Win32 routine %s\n", func_name ); exit(1); } /*********************************************************************** * RELAY_DebugCallTo16 * * 'stack' points to the called function address on the 32-bit stack. * Stack layout: * ... ... * (stack+12) arg2 * (stack+8) arg1 * (stack+4) 16-bit ds * (stack) func to call */ void RELAY_DebugCallTo16( int* stack, int nbargs ) { if (!debugging_relay) return; printf( "CallTo16(func=%04x:%04x,ds=%04x", HIWORD(stack[0]), LOWORD(stack[0]), LOWORD(stack[1]) ); stack += 2; while (nbargs--) printf( ",0x%04x", *stack++ ); printf( ")\n" ); } /*********************************************************************** * RELAY_DebugCallFrom32 */ void RELAY_DebugCallFrom32( int nb_args, void *entry_point, const char *func_name, int ebp, int ret_addr, int arg1 ) { int *parg; if (!debugging_relay) return; printf( "Call %s(", func_name ); for (parg = &arg1; nb_args; parg++, nb_args--) { printf( "%08x", *parg ); if (nb_args > 1) printf( "," ); } printf( ") ret=%08x\n", ret_addr ); } /*********************************************************************** * RELAY_DebugCallFrom32Ret */ void RELAY_DebugCallFrom32Ret( int ret_val, void *entry_point, const char *func_name, int ebp, int ret_addr ) { if (!debugging_relay) return; printf( "Ret %s() retval=0x%08x ret=%08x\n", func_name, ret_val, ret_addr ); } /*********************************************************************** * RELAY_DebugCallTo32 */ void RELAY_DebugCallTo32( unsigned int func, int nbargs, unsigned int arg1 ) { unsigned int *argptr; if (!debugging_relay) return; printf( "CallTo32(func=%08x", func ); for (argptr = &arg1; nbargs; nbargs--, argptr++) printf( ",%08x", *argptr ); printf( ")\n" ); }