/* static char RCSId[] = "$Id: relay.c,v 1.2 1993/07/04 04:04:21 root Exp root $"; static char Copyright[] = "Copyright Robert J. Amstadt, 1993"; */ #include #include #include #include #include #include #include #include #ifdef linux #include #include #include #endif #include "neexe.h" #include "segmem.h" #include "prototypes.h" #include "dlls.h" #include "options.h" #include "stackframe.h" #include "stddebug.h" /* #define DEBUG_RELAY */ /* #define DEBUG_STACK */ #include "debug.h" #if 0 /* Make make_debug think these were really used */ dprintf_relay dprintf_stack #endif #ifdef WINELIB #define WineLibSkip(x) 0 #else #define WineLibSkip(x) x #endif struct dll_name_table_entry_s dll_builtin_table[N_BUILTINS] = { { "KERNEL", WineLibSkip(KERNEL_table), 410, 1, 1 }, { "USER", WineLibSkip(USER_table), 540, 2, 1 }, { "GDI", WineLibSkip(GDI_table), 490, 3, 1 }, { "UNIXLIB", WineLibSkip(UNIXLIB_table), 10, 4, 1 }, { "WIN87EM", WineLibSkip(WIN87EM_table), 10, 5, 1 }, { "SHELL", WineLibSkip(SHELL_table), 103, 6, 1 }, { "SOUND", WineLibSkip(SOUND_table), 20, 7, 1 }, { "KEYBOARD",WineLibSkip(KEYBOARD_table),137, 8, 1 }, { "WINSOCK", WineLibSkip(WINSOCK_table), 155, 9, 1 }, { "STRESS", WineLibSkip(STRESS_table), 15, 10, 1}, { "MMSYSTEM",WineLibSkip(MMSYSTEM_table),1226,11, 1}, { "SYSTEM", WineLibSkip(SYSTEM_table), 20 ,12, 1}, { "TOOLHELP",WineLibSkip(TOOLHELP_table), 83, 13, 1}, { "MOUSE", WineLibSkip(MOUSE_table), 8, 14, 1}, { "COMMDLG", WineLibSkip(COMMDLG_table), 31, 15, 1}, { "OLE2", WineLibSkip(OLE2_table), 31, 16, 1}, { "OLE2CONV",WineLibSkip(OLE2CONV_table), 31, 17, 1}, { "OLE2DISP",WineLibSkip(OLE2DISP_table), 31, 18, 1}, { "OLE2NLS", WineLibSkip(OLE2NLS_table), 31, 19, 1}, { "OLE2PROX",WineLibSkip(OLE2PROX_table), 31, 20, 1}, { "OLECLI", WineLibSkip(OLECLI_table), 31, 21, 1}, { "OLESVR", WineLibSkip(OLESVR_table), 31, 22, 1}, }; /* don't forget to increase N_BUILTINS in dll.h if you add a dll */ /* the argument conversion tables for each dll */ struct dll_conversions { unsigned short *dst_args; /* Offsets to arguments on stack */ unsigned char *src_types; /* Argument types */ } dll_conversion_table[N_BUILTINS]= { KERNEL_offsets, KERNEL_types, /* KERNEL */ USER_offsets, USER_types, /* USER */ GDI_offsets, GDI_types, /* GDI */ UNIXLIB_offsets, UNIXLIB_types, /* UNIXLIB */ WIN87EM_offsets, WIN87EM_types, /* WIN87EM */ SHELL_offsets, SHELL_types, /* SHELL */ SOUND_offsets, SOUND_types, /* SOUND */ KEYBOARD_offsets, KEYBOARD_types, /* KEYBOARD */ WINSOCK_offsets, WINSOCK_types, /* WINSOCK */ STRESS_offsets, STRESS_types, /* STRESS, */ MMSYSTEM_offsets, MMSYSTEM_types, /* MMSYSTEM */ SYSTEM_offsets, SYSTEM_types, /* SYSTEM */ TOOLHELP_offsets, TOOLHELP_types, /* TOOLHELP */ MOUSE_offsets, MOUSE_types, /* MOUSE */ COMMDLG_offsets, COMMDLG_types, /* EMUCOMMDLG */ OLE2_offsets, OLE2_types, /* OLE2 */ OLE2CONV_offsets, OLE2CONV_types, /* OLE2CONV */ OLE2DISP_offsets, OLE2DISP_types, /* OLE2DISP */ OLE2NLS_offsets, OLE2NLS_types, /* OLE2NLS */ OLE2DISP_offsets, OLE2DISP_types, /* OLE2PROX */ OLECLI_offsets, OLECLI_types, /* OLE2CLI */ OLESVR_offsets, OLESVR_types /* OLE2CLI */ }; #ifndef WINELIB STACK16FRAME *pStack16Frame; extern unsigned short IF1632_Saved16_sp; extern unsigned short IF1632_Saved16_bp; extern unsigned short IF1632_Saved16_ss; /********************************************************************** * DLLRelay * * We get a stack frame pointer to data that looks like this: * * Hex Offset Contents * ---------- ------- * +00 previous saved_16ss * +02 previous saved_16ebp * +06 previous saved_16esp * +0A 16-bit es * +0C 16-bit ds * +0E 16-bit ebp * +12 length of 16-bit arguments * +14 16-bit ip * +16 16-bit cs * +18 arguments */ int DLLRelay(unsigned int func_num, unsigned int seg_off) { struct dll_table_entry_s *dll_p; STACK16FRAME *pOldStack16Frame; unsigned int offset; unsigned int dll_id; unsigned int ordinal; int arg_table[DLL_MAX_ARGS]; void *arg_ptr; int (*func_ptr)(); int i; int ret_val; int conv_ref; unsigned char *type_conv; unsigned short *offset_conv; /* * Determine address of arguments. */ pOldStack16Frame = pStack16Frame; pStack16Frame = (STACK16FRAME *) seg_off; arg_ptr = (void *)pStack16Frame->args; /* * Extract the DLL number and ordinal number. */ dll_id = ((func_num >> 16) & 0xffff) - 1; ordinal = func_num & 0xffff; dll_p = &dll_builtin_table[dll_id].dll_table[ordinal]; if (debugging_relay) { printf( "Call %s (%s.%d), stack=%04x:%04x, ret=%04x:%04x", dll_p->export_name, dll_builtin_table[dll_id].dll_name, ordinal, seg_off >> 16, seg_off & 0xffff, pStack16Frame->cs, pStack16Frame->ip ); printf(" bp=%04x ds=%04x args=%d\n", pStack16Frame->bp, pStack16Frame->ds, pStack16Frame->arg_length ); if(debugging_stack) { unsigned short *stack_p = (unsigned short *) seg_off; /* FIXME: Is there an end-of-stack-pointer somewhere ? */ int n = min(24, (0x10000 - (seg_off & 0xffff)) / sizeof(*stack_p)); for (i = 0; i < n; i++, stack_p++) { printf("%04x ", *stack_p); if ((i & 7) == 7) printf("\n"); } printf("\n"); } } /* DEBUG_RELAY */ /* * Make sure we have a handler defined for this call. */ if (dll_p->handler == NULL) { char buffer[100]; sprintf(buffer, "No handler for routine %s.%d", dll_builtin_table[dll_id].dll_name, ordinal); myerror(buffer); } func_ptr = dll_p->handler; /* * OK, special case. If the handler is define as taking no arguments * then pass the address of the arguments on the 16-bit stack to the * handler. It will just ignore the pointer if it really takes no * arguments. This allows us to write slightly faster library routines * if we choose. */ if (dll_p->n_args == 0) { ret_val = (*func_ptr)(arg_ptr); pStack16Frame = pOldStack16Frame; return ret_val; } /* * Getting this far means we need to convert the 16-bit argument stack. */ conv_ref= dll_p->conv_reference; type_conv= dll_conversion_table[dll_id].src_types + conv_ref; offset_conv= dll_conversion_table[dll_id].dst_args + conv_ref; for (i = 0; i < dll_p->n_args; i++,type_conv++,offset_conv++) { short *sp; int *ip; offset = *offset_conv; switch (*type_conv) { case DLL_ARGTYPE_SIGNEDWORD: sp = (short *) ((char *) arg_ptr + offset); arg_table[i] = *sp; break; case DLL_ARGTYPE_WORD: sp = (short *) ((char *) arg_ptr + offset); arg_table[i] = (int) *sp & 0xffff; break; case DLL_ARGTYPE_LONG: ip = (int *) ((char *) arg_ptr + offset); arg_table[i] = *ip; break; case DLL_ARGTYPE_FARPTR: ip = (int *) ((char *) arg_ptr + offset); if (*ip & 0xffff0000) arg_table[i] = FIXPTR(*ip); else arg_table[i] = *ip; break; } } /* * Call the handler */ ret_val = (*func_ptr)(arg_table[0], arg_table[1], arg_table[2], arg_table[3], arg_table[4], arg_table[5], arg_table[6], arg_table[7], arg_table[8], arg_table[9], arg_table[10], arg_table[11], arg_table[12], arg_table[13], arg_table[14], arg_table[15]); pStack16Frame = pOldStack16Frame; if (debugging_relay) { printf("Returning %08x from %s (%s.%d) ds=%04x\n", ret_val, dll_p->export_name, dll_builtin_table[dll_id].dll_name, ordinal, pStack16Frame->ds ); } return ret_val; } #endif /********************************************************************** * FindDLLTable */ struct dll_table_entry_s * FindDLLTable(char *dll_name) { int i; for (i = 0; i < N_BUILTINS; i++) if (strcasecmp(dll_builtin_table[i].dll_name, dll_name) == 0 && dll_builtin_table[i].dll_is_used) #ifdef WINELIB return dll_builtin_table[i].dll_number; #else return dll_builtin_table[i].dll_table; #endif return NULL; } /********************************************************************** * FindOrdinalFromName */ int FindOrdinalFromName(struct dll_table_entry_s *dll_table, char *func_name) { int i, limit; for (i = 0; i < N_BUILTINS; i++) if (dll_table == dll_builtin_table[i].dll_table) break; if (i == N_BUILTINS) return 0; limit = dll_builtin_table[i].dll_table_length; for (i = 0; i < limit; i++) if (strcasecmp(dll_table[i].export_name, func_name) == 0) return i; return 0; } /********************************************************************** * ReturnArg */ int ReturnArg(int arg) { return arg; } #ifndef WINELIB #ifdef WINESTAT void winestat(){ int i, j; double perc; int used, implemented; int tused, timplemented; struct dll_table_entry_s *table; tused = 0; timplemented = 0; for (i = 0; i < N_BUILTINS; i++) { table = dll_builtin_table[i].dll_table; used = 0; implemented = 0; for(j=0; j < dll_builtin_table[i].dll_table_length; j++) { if(table[j].used){ used++; if (table[j].handler) implemented++; else printf("%s.%d not implemented\n", dll_builtin_table[i].dll_name, j); }; }; tused += used; timplemented += implemented; if(used) perc = implemented * 100.00 / used; else perc = 0.0; if (used) printf("%s: %d of %d (%3.1f %%)\n", dll_builtin_table[i].dll_name, implemented, used, perc); }; perc = timplemented * 100.00 / tused; printf("TOTAL: %d of %d winapi functions implemented (%3.1f %%)\n",timplemented, tused, perc); } #endif /* WINESTAT */ #endif /* !WINELIB */