From a37e7608c75d6b339781675f05bb07e1b312b43f Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 19 Sep 2003 04:32:39 +0000 Subject: [PATCH] Moved 32-bit relay and snoop support to dlls/ntdll. --- dlls/kernel/ne_module.c | 3 +- dlls/kernel/snoop16.c | 4 +- dlls/ntdll/Makefile.in | 4 +- dlls/ntdll/ntdll_misc.h | 2 +- relay32/relay386.c => dlls/ntdll/relay.c | 466 +++++++++++++++++++++-- include/snoop.h | 29 -- loader/ne/module.c | 1 - relay32/snoop.c | 450 ---------------------- 8 files changed, 449 insertions(+), 510 deletions(-) rename relay32/relay386.c => dlls/ntdll/relay.c (63%) delete mode 100644 include/snoop.h delete mode 100644 relay32/snoop.c diff --git a/dlls/kernel/ne_module.c b/dlls/kernel/ne_module.c index 74b53dfac5c..6b5ff076863 100644 --- a/dlls/kernel/ne_module.c +++ b/dlls/kernel/ne_module.c @@ -44,7 +44,6 @@ #include "global.h" #include "file.h" #include "task.h" -#include "snoop.h" #include "builtin16.h" #include "stackframe.h" #include "excpt.h" @@ -93,6 +92,8 @@ typedef struct static const BUILTIN16_DESCRIPTOR *builtin_dlls[MAX_DLLS]; +extern void SNOOP16_RegisterDLL(NE_MODULE*,LPCSTR); +extern FARPROC16 SNOOP16_GetProcAddress16(HMODULE16,DWORD,FARPROC16); static HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL lib_only ); static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL call_wep ); diff --git a/dlls/kernel/snoop16.c b/dlls/kernel/snoop16.c index adcdc5b3a74..e2e800acb27 100644 --- a/dlls/kernel/snoop16.c +++ b/dlls/kernel/snoop16.c @@ -31,10 +31,10 @@ #include "wine/winbase16.h" #include "wine/library.h" #include "global.h" +#include "module.h" #include "stackframe.h" #include "builtin16.h" #include "toolhelp.h" -#include "snoop.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(snoop); @@ -43,6 +43,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(snoop); #include "pshpack1.h" +extern int SNOOP_ShowDebugmsgSnoop(const char *dll,int ord,const char *fname); /* FIXME */ + void WINAPI SNOOP16_Entry(FARPROC proc, LPBYTE args, CONTEXT86 *context); void WINAPI SNOOP16_Return(FARPROC proc, LPBYTE args, CONTEXT86 *context); diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index 2c0b5def009..25f4277bf38 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -27,8 +27,6 @@ C_SRCS = \ $(TOPOBJDIR)/misc/registry.c \ $(TOPOBJDIR)/misc/version.c \ $(TOPOBJDIR)/msdos/dpmi.c \ - $(TOPOBJDIR)/relay32/relay386.c \ - $(TOPOBJDIR)/relay32/snoop.c \ $(TOPOBJDIR)/scheduler/handle.c \ $(TOPOBJDIR)/scheduler/process.c \ $(TOPOBJDIR)/scheduler/pthread.c \ @@ -51,6 +49,7 @@ C_SRCS = \ path.c \ process.c \ reg.c \ + relay.c \ resource.c \ rtl.c \ rtlbitmap.c \ @@ -81,7 +80,6 @@ EXTRASUBDIRS = \ $(TOPOBJDIR)/memory \ $(TOPOBJDIR)/misc \ $(TOPOBJDIR)/msdos \ - $(TOPOBJDIR)/relay32 \ $(TOPOBJDIR)/scheduler \ $(TOPOBJDIR)/win32 diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 37c63e9a25d..aad260b545e 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -44,7 +44,7 @@ extern FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exp DWORD exp_size, FARPROC proc, const char *user ); extern FARPROC SNOOP_GetProcAddress( HMODULE hmod, IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size, FARPROC origfun, DWORD ordinal ); -extern void RELAY_SetupDLL( const char *module ); +extern void RELAY_SetupDLL( HMODULE hmod ); extern void SNOOP_SetupDLL( HMODULE hmod ); static inline HANDLE ntdll_get_process_heap(void) diff --git a/relay32/relay386.c b/dlls/ntdll/relay.c similarity index 63% rename from relay32/relay386.c rename to dlls/ntdll/relay.c index f2a396d651f..631fdb64e0c 100644 --- a/relay32/relay386.c +++ b/dlls/ntdll/relay.c @@ -1,7 +1,8 @@ /* - * 386-specific Win32 relay functions + * Win32 relay and snoop functions * * Copyright 1997 Alexandre Julliard + * Copyright 1998 Marcus Meissner * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -30,12 +31,15 @@ #include "winbase.h" #include "winreg.h" #include "winternl.h" +#include "excpt.h" +#include "wine/exception.h" +#include "ntdll_misc.h" #include "wine/unicode.h" #include "wine/debug.h" -#include "ntdll_misc.h" WINE_DEFAULT_DEBUG_CHANNEL(relay); WINE_DECLARE_DEBUG_CHANNEL(snoop); +WINE_DECLARE_DEBUG_CHANNEL(seh); const char **debug_relay_excludelist = NULL; const char **debug_relay_includelist = NULL; @@ -170,16 +174,77 @@ void RELAY_InitDebugLists(void) #ifdef __i386__ +#include "pshpack1.h" + typedef struct { - BYTE call; /* 0xe8 call callfrom32 (relative) */ - DWORD callfrom32 WINE_PACKED; /* RELAY_CallFrom32 relative addr */ - BYTE ret; /* 0xc2 ret $n or 0xc3 ret */ - WORD args; /* nb of args to remove from the stack */ - void *orig; /* original entry point */ - DWORD argtypes; /* argument types */ + BYTE call; /* 0xe8 call callfrom32 (relative) */ + DWORD callfrom32; /* RELAY_CallFrom32 relative addr */ + BYTE ret; /* 0xc2 ret $n or 0xc3 ret */ + WORD args; /* nb of args to remove from the stack */ + void *orig; /* original entry point */ + DWORD argtypes; /* argument types */ } DEBUG_ENTRY_POINT; +typedef struct +{ + /* code part */ + BYTE lcall; /* 0xe8 call snoopentry (relative) */ + /* NOTE: If you move snoopentry OR nrofargs fix the relative offset + * calculation! + */ + DWORD snoopentry; /* SNOOP_Entry relative */ + /* unreached */ + int nrofargs; + FARPROC origfun; + const char *name; +} SNOOP_FUN; + +typedef struct tagSNOOP_DLL { + HMODULE hmod; + SNOOP_FUN *funs; + DWORD ordbase; + DWORD nrofordinals; + struct tagSNOOP_DLL *next; + char name[1]; +} SNOOP_DLL; + +typedef struct +{ + /* code part */ + BYTE lcall; /* 0xe8 call snoopret relative*/ + /* NOTE: If you move snoopret OR origreturn fix the relative offset + * calculation! + */ + DWORD snoopret; /* SNOOP_Ret relative */ + /* unreached */ + FARPROC origreturn; + SNOOP_DLL *dll; + DWORD ordinal; + DWORD origESP; + DWORD *args; /* saved args across a stdcall */ +} SNOOP_RETURNENTRY; + +typedef struct tagSNOOP_RETURNENTRIES { + SNOOP_RETURNENTRY entry[4092/sizeof(SNOOP_RETURNENTRY)]; + struct tagSNOOP_RETURNENTRIES *next; +} SNOOP_RETURNENTRIES; + +#include "poppack.h" + +extern void WINAPI SNOOP_Entry(); +extern void WINAPI SNOOP_Return(); + +static SNOOP_DLL *firstdll; +static SNOOP_RETURNENTRIES *firstrets; + +static WINE_EXCEPTION_FILTER(page_fault) +{ + if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION || + GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION) + return EXCEPTION_EXECUTE_HANDLER; + return EXCEPTION_CONTINUE_SEARCH; +} /*********************************************************************** * check_relay_include @@ -259,17 +324,17 @@ static BOOL check_relay_from_module( const char *module ) * * Find the name of an exported function. */ -static const char *find_exported_name( const char *module, +static const char *find_exported_name( HMODULE module, IMAGE_EXPORT_DIRECTORY *exp, int ordinal ) { int i; const char *ret = NULL; - WORD *ordptr = (WORD *)(module + exp->AddressOfNameOrdinals); + WORD *ordptr = (WORD *)((char *)module + exp->AddressOfNameOrdinals); for (i = 0; i < exp->NumberOfNames; i++, ordptr++) if (*ordptr + exp->Base == ordinal) break; if (i < exp->NumberOfNames) - ret = module + ((DWORD*)(module + exp->AddressOfNames))[i]; + ret = (char *)module + ((DWORD*)((char *)module + exp->AddressOfNames))[i]; return ret; } @@ -283,7 +348,7 @@ static void get_entry_point( char *buffer, DEBUG_ENTRY_POINT *relay ) { IMAGE_EXPORT_DIRECTORY *exp = NULL; DEBUG_ENTRY_POINT *debug; - char *p, *base = NULL; + char *p; const char *name; int ordinal = 0; PLIST_ENTRY mark, entry; @@ -309,12 +374,11 @@ static void get_entry_point( char *buffer, DEBUG_ENTRY_POINT *relay ) /* Now find the function */ - base = (char *)mod->BaseAddress; - strcpy( buffer, base + exp->Name ); + strcpy( buffer, (char *)mod->BaseAddress + exp->Name ); p = buffer + strlen(buffer); if (p > buffer + 4 && !strcasecmp( p - 4, ".dll" )) p -= 4; - if ((name = find_exported_name( base, exp, ordinal + exp->Base ))) + if ((name = find_exported_name( mod->BaseAddress, exp, ordinal + exp->Base ))) sprintf( p, ".%s", name ); else sprintf( p, ".%ld", ordinal + exp->Base ); @@ -331,9 +395,9 @@ static inline void RELAY_PrintArgs( int *args, int nb_args, unsigned int typemas if ((typemask & 3) && HIWORD(*args)) { if (typemask & 2) - DPRINTF( "%08x %s", *args, debugstr_w((LPWSTR)*args) ); + DPRINTF( "%08x %s", *args, debugstr_w((LPWSTR)*args) ); else - DPRINTF( "%08x %s", *args, debugstr_a((LPCSTR)*args) ); + DPRINTF( "%08x %s", *args, debugstr_a((LPCSTR)*args) ); } else DPRINTF( "%08x", *args ); if (nb_args) DPRINTF( "," ); @@ -631,7 +695,7 @@ FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports, * * Setup relay debugging for a built-in dll. */ -void RELAY_SetupDLL( const char *module ) +void RELAY_SetupDLL( HMODULE module ) { IMAGE_EXPORT_DIRECTORY *exports; DEBUG_ENTRY_POINT *debug; @@ -641,12 +705,11 @@ void RELAY_SetupDLL( const char *module ) char *p, dllname[80]; DWORD size; - exports = RtlImageDirectoryEntryToData( (HMODULE)module, TRUE, - IMAGE_DIRECTORY_ENTRY_EXPORT, &size ); + exports = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size ); if (!exports) return; debug = (DEBUG_ENTRY_POINT *)((char *)exports + size); - funcs = (DWORD *)(module + exports->AddressOfFunctions); - strcpy( dllname, module + exports->Name ); + funcs = (DWORD *)((char *)module + exports->AddressOfFunctions); + strcpy( dllname, (char *)module + exports->Name ); p = dllname + strlen(dllname) - 4; if (p > dllname && !strcasecmp( p, ".dll" )) *p = 0; @@ -674,11 +737,355 @@ void RELAY_SetupDLL( const char *module ) debug->callfrom32 = (char *)debug->orig - (char *)&debug->ret; } - debug->orig = (FARPROC)(module + (DWORD)*funcs); - *funcs = (char *)debug - module; + debug->orig = (FARPROC)((char *)module + (DWORD)*funcs); + *funcs = (char *)debug - (char *)module; } } + +/*********************************************************************** + * SNOOP_ShowDebugmsgSnoop + * + * Simple function to decide if a particular debugging message is + * wanted. + */ +int SNOOP_ShowDebugmsgSnoop(const char *dll, int ord, const char *fname) { + + if(debug_snoop_excludelist || debug_snoop_includelist) { + const char **listitem; + char buf[80]; + int len, len2, itemlen, show; + + if(debug_snoop_excludelist) { + show = 1; + listitem = debug_snoop_excludelist; + } else { + show = 0; + listitem = debug_snoop_includelist; + } + len = strlen(dll); + assert(len < 64); + sprintf(buf, "%s.%d", dll, ord); + len2 = strlen(buf); + for(; *listitem; listitem++) { + itemlen = strlen(*listitem); + if((itemlen == len && !strncasecmp(*listitem, buf, len)) || + (itemlen == len2 && !strncasecmp(*listitem, buf, len2)) || + !strcasecmp(*listitem, fname)) { + show = !show; + break; + } + } + return show; + } + return 1; +} + + +/*********************************************************************** + * SNOOP_SetupDLL + * + * Setup snoop debugging for a native dll. + */ +void SNOOP_SetupDLL(HMODULE hmod) +{ + SNOOP_DLL **dll = &firstdll; + char *p, *name; + void *addr; + SIZE_T size; + IMAGE_EXPORT_DIRECTORY *exports; + + exports = RtlImageDirectoryEntryToData( hmod, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size ); + if (!exports) return; + name = (char *)hmod + exports->Name; + + TRACE("hmod=%p, name=%s\n", hmod, name); + + while (*dll) { + if ((*dll)->hmod == hmod) + { + /* another dll, loaded at the same address */ + addr = (*dll)->funs; + size = (*dll)->nrofordinals * sizeof(SNOOP_FUN); + NtFreeVirtualMemory(GetCurrentProcess(), &addr, &size, MEM_RELEASE); + break; + } + dll = &((*dll)->next); + } + *dll = RtlReAllocateHeap(ntdll_get_process_heap(), + HEAP_ZERO_MEMORY, *dll, + sizeof(SNOOP_DLL) + strlen(name)); + (*dll)->hmod = hmod; + (*dll)->ordbase = exports->Base; + (*dll)->nrofordinals = exports->NumberOfFunctions; + strcpy( (*dll)->name, name ); + p = (*dll)->name + strlen((*dll)->name) - 4; + if (p > (*dll)->name && !strcasecmp( p, ".dll" )) *p = 0; + + size = exports->NumberOfFunctions * sizeof(SNOOP_FUN); + NtAllocateVirtualMemory(GetCurrentProcess(), &addr, NULL, &size, + MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (!addr) { + RtlFreeHeap(ntdll_get_process_heap(),0,*dll); + FIXME("out of memory\n"); + return; + } + (*dll)->funs = addr; + memset((*dll)->funs,0,size); +} + + +/*********************************************************************** + * SNOOP_GetProcAddress + * + * Return the proc address to use for a given function. + */ +FARPROC SNOOP_GetProcAddress( HMODULE hmod, IMAGE_EXPORT_DIRECTORY *exports, + DWORD exp_size, FARPROC origfun, DWORD ordinal ) +{ + int i; + const char *ename; + WORD *ordinals; + DWORD *names; + SNOOP_DLL *dll = firstdll; + SNOOP_FUN *fun; + IMAGE_SECTION_HEADER *sec; + + if (!TRACE_ON(snoop)) return origfun; + if (!*(LPBYTE)origfun) /* 0x00 is an imposs. opcode, poss. dataref. */ + return origfun; + + sec = RtlImageRvaToSection( RtlImageNtHeader(hmod), hmod, (char *)origfun - (char *)hmod ); + + if (!sec || !(sec->Characteristics & IMAGE_SCN_CNT_CODE)) + return origfun; /* most likely a data reference */ + + while (dll) { + if (hmod == dll->hmod) + break; + dll=dll->next; + } + if (!dll) /* probably internal */ + return origfun; + + /* try to find a name for it */ + ename = NULL; + names = (DWORD *)((char *)hmod + exports->AddressOfNames); + ordinals = (WORD *)((char *)hmod + exports->AddressOfNameOrdinals); + if (names) for (i = 0; i < exports->NumberOfNames; i++) + { + if (ordinals[i] == ordinal) + { + ename = (char *)hmod + names[i]; + break; + } + } + if (!SNOOP_ShowDebugmsgSnoop(dll->name,ordinal,ename)) + return origfun; + assert(ordinal < dll->nrofordinals); + fun = dll->funs+ordinal; + if (!fun->name) + { + fun->name = ename; + fun->lcall = 0xe8; + /* NOTE: origreturn struct member MUST come directly after snoopentry */ + fun->snoopentry = (char*)SNOOP_Entry-((char*)(&fun->nrofargs)); + fun->origfun = origfun; + fun->nrofargs = -1; + } + return (FARPROC)&(fun->lcall); +} + +static void SNOOP_PrintArg(DWORD x) +{ + int i,nostring; + + DPRINTF("%08lx",x); + if (!HIWORD(x) || TRACE_ON(seh)) return; /* trivial reject to avoid faults */ + __TRY + { + LPBYTE s=(LPBYTE)x; + i=0;nostring=0; + while (i<80) { + if (s[i]==0) break; + if (s[i]<0x20) {nostring=1;break;} + if (s[i]>=0x80) {nostring=1;break;} + i++; + } + if (!nostring && i > 5) + DPRINTF(" %s",debugstr_an((LPSTR)x,i)); + else /* try unicode */ + { + LPWSTR s=(LPWSTR)x; + i=0;nostring=0; + while (i<80) { + if (s[i]==0) break; + if (s[i]<0x20) {nostring=1;break;} + if (s[i]>0x100) {nostring=1;break;} + i++; + } + if (!nostring && i > 5) DPRINTF(" %s",debugstr_wn((LPWSTR)x,i)); + } + } + __EXCEPT(page_fault) + { + } + __ENDTRY +} + +#define CALLER1REF (*(DWORD*)context->Esp) + +void WINAPI SNOOP_DoEntry( CONTEXT86 *context ) +{ + DWORD ordinal=0,entry = context->Eip - 5; + SNOOP_DLL *dll = firstdll; + SNOOP_FUN *fun = NULL; + SNOOP_RETURNENTRIES **rets = &firstrets; + SNOOP_RETURNENTRY *ret; + int i=0, max; + + while (dll) { + if ( ((char*)entry>=(char*)dll->funs) && + ((char*)entry<=(char*)(dll->funs+dll->nrofordinals)) + ) { + fun = (SNOOP_FUN*)entry; + ordinal = fun-dll->funs; + break; + } + dll=dll->next; + } + if (!dll) { + FIXME("entrypoint 0x%08lx not found\n",entry); + return; /* oops */ + } + /* guess cdecl ... */ + if (fun->nrofargs<0) { + /* Typical cdecl return frame is: + * add esp, xxxxxxxx + * which has (for xxxxxxxx up to 255 the opcode "83 C4 xx". + * (after that 81 C2 xx xx xx xx) + */ + LPBYTE reteip = (LPBYTE)CALLER1REF; + + if (reteip) { + if ((reteip[0]==0x83)&&(reteip[1]==0xc4)) + fun->nrofargs=reteip[2]/4; + } + } + + + while (*rets) { + for (i=0;ientry)/sizeof((*rets)->entry[0]);i++) + if (!(*rets)->entry[i].origreturn) + break; + if (i!=sizeof((*rets)->entry)/sizeof((*rets)->entry[0])) + break; + rets = &((*rets)->next); + } + if (!*rets) { + SIZE_T size = 4096; + VOID* addr; + + NtAllocateVirtualMemory(GetCurrentProcess(), &addr, NULL, &size, + MEM_COMMIT | MEM_RESERVE, + PAGE_EXECUTE_READWRITE); + if (!addr) return; + *rets = addr; + memset(*rets,0,4096); + i = 0; /* entry 0 is free */ + } + ret = &((*rets)->entry[i]); + ret->lcall = 0xe8; + /* NOTE: origreturn struct member MUST come directly after snoopret */ + ret->snoopret = ((char*)SNOOP_Return)-(char*)(&ret->origreturn); + ret->origreturn = (FARPROC)CALLER1REF; + CALLER1REF = (DWORD)&ret->lcall; + ret->dll = dll; + ret->args = NULL; + ret->ordinal = ordinal; + ret->origESP = context->Esp; + + context->Eip = (DWORD)fun->origfun; + + if (fun->name) DPRINTF("%04lx:CALL %s.%s(",GetCurrentThreadId(),dll->name,fun->name); + else DPRINTF("%04lx:CALL %s.%ld(",GetCurrentThreadId(),dll->name,dll->ordbase+ordinal); + if (fun->nrofargs>0) { + max = fun->nrofargs; if (max>16) max=16; + for (i=0;iEsp + 4 + sizeof(DWORD)*i)); + if (inrofargs-1) DPRINTF(","); + } + if (max!=fun->nrofargs) + DPRINTF(" ..."); + } else if (fun->nrofargs<0) { + DPRINTF(""); + ret->args = RtlAllocateHeap(ntdll_get_process_heap(), + 0,16*sizeof(DWORD)); + memcpy(ret->args,(LPBYTE)(context->Esp + 4),sizeof(DWORD)*16); + } + DPRINTF(") ret=%08lx\n",(DWORD)ret->origreturn); +} + + +void WINAPI SNOOP_DoReturn( CONTEXT86 *context ) +{ + SNOOP_RETURNENTRY *ret = (SNOOP_RETURNENTRY*)(context->Eip - 5); + SNOOP_FUN *fun = &ret->dll->funs[ret->ordinal]; + + /* We haven't found out the nrofargs yet. If we called a cdecl + * function it is too late anyway and we can just set '0' (which + * will be the difference between orig and current ESP + * If stdcall -> everything ok. + */ + if (ret->dll->funs[ret->ordinal].nrofargs<0) + ret->dll->funs[ret->ordinal].nrofargs=(context->Esp - ret->origESP-4)/4; + context->Eip = (DWORD)ret->origreturn; + if (ret->args) { + int i,max; + + if (fun->name) + DPRINTF("%04lx:RET %s.%s(", GetCurrentThreadId(), ret->dll->name, fun->name); + else + DPRINTF("%04lx:RET %s.%ld(", GetCurrentThreadId(), + ret->dll->name,ret->dll->ordbase+ret->ordinal); + + max = fun->nrofargs; + if (max>16) max=16; + + for (i=0;iargs[i]); + if (iEax,(DWORD)ret->origreturn ); + RtlFreeHeap(ntdll_get_process_heap(),0,ret->args); + ret->args = NULL; + } + else + { + if (fun->name) + DPRINTF("%04lx:RET %s.%s() retval=%08lx ret=%08lx\n", + GetCurrentThreadId(), + ret->dll->name, fun->name, context->Eax, (DWORD)ret->origreturn); + else + DPRINTF("%04lx:RET %s.%ld() retval=%08lx ret=%08lx\n", + GetCurrentThreadId(), + ret->dll->name,ret->dll->ordbase+ret->ordinal, + context->Eax, (DWORD)ret->origreturn); + } + ret->origreturn = NULL; /* mark as empty */ +} + +/* assembly wrappers that save the context */ +__ASM_GLOBAL_FUNC( SNOOP_Entry, + "call " __ASM_NAME("__wine_call_from_32_regs") "\n\t" + ".long " __ASM_NAME("SNOOP_DoEntry") ",0" ); +__ASM_GLOBAL_FUNC( SNOOP_Return, + "call " __ASM_NAME("__wine_call_from_32_regs") "\n\t" + ".long " __ASM_NAME("SNOOP_DoReturn") ",0" ); + #else /* __i386__ */ FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports, @@ -687,8 +1094,19 @@ FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports, return proc; } +FARPROC SNOOP_GetProcAddress( HMODULE hmod, IMAGE_EXPORT_DIRECTORY *exports, + DWORD exp_size, FARPROC origfun, DWORD ordinal ) +{ + return origfun; +} + void RELAY_SetupDLL( const char *module ) { } +void SNOOP_SetupDLL( HMODULE hmod ) +{ + FIXME("snooping works only on i386 for now.\n"); +} + #endif /* __i386__ */ diff --git a/include/snoop.h b/include/snoop.h deleted file mode 100644 index 5e7a8809d8e..00000000000 --- a/include/snoop.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Definitions for inter-dll snooping - * - * Copyright 1998 Marcus Meissner - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __WINE_SNOOP_H -#define __WINE_SNOOP_H - -#include - -extern void SNOOP16_RegisterDLL(NE_MODULE*,LPCSTR); -extern FARPROC16 SNOOP16_GetProcAddress16(HMODULE16,DWORD,FARPROC16); -extern int SNOOP_ShowDebugmsgSnoop(const char *dll,int ord,const char *fname); -#endif diff --git a/loader/ne/module.c b/loader/ne/module.c index 1e479b1931c..2b7556e0496 100644 --- a/loader/ne/module.c +++ b/loader/ne/module.c @@ -41,7 +41,6 @@ #include "toolhelp.h" #include "file.h" #include "task.h" -#include "snoop.h" #include "builtin16.h" #include "stackframe.h" #include "excpt.h" diff --git a/relay32/snoop.c b/relay32/snoop.c deleted file mode 100644 index 2ad07de95b4..00000000000 --- a/relay32/snoop.c +++ /dev/null @@ -1,450 +0,0 @@ -/* - * 386-specific Win32 dll<->dll snooping functions - * - * Copyright 1998 Marcus Meissner - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include -#include "ntstatus.h" -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "winternl.h" -#include "snoop.h" -#include "wine/debug.h" -#include "wine/exception.h" -#include "excpt.h" -#include "ntdll_misc.h" - -WINE_DEFAULT_DEBUG_CHANNEL(snoop); -WINE_DECLARE_DEBUG_CHANNEL(seh); - -static WINE_EXCEPTION_FILTER(page_fault) -{ - if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION || - GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION) - return EXCEPTION_EXECUTE_HANDLER; - return EXCEPTION_CONTINUE_SEARCH; -} - -extern const char **debug_snoop_excludelist; -extern const char **debug_snoop_includelist; - -#ifdef __i386__ - -extern void WINAPI SNOOP_Entry(); -extern void WINAPI SNOOP_Return(); - -#include "pshpack1.h" - -typedef struct tagSNOOP_FUN { - /* code part */ - BYTE lcall; /* 0xe8 call snoopentry (relative) */ - /* NOTE: If you move snoopentry OR nrofargs fix the relative offset - * calculation! - */ - DWORD snoopentry; /* SNOOP_Entry relative */ - /* unreached */ - int nrofargs; - FARPROC origfun; - const char *name; -} SNOOP_FUN; - -typedef struct tagSNOOP_DLL { - HMODULE hmod; - SNOOP_FUN *funs; - DWORD ordbase; - DWORD nrofordinals; - struct tagSNOOP_DLL *next; - char name[1]; -} SNOOP_DLL; - -typedef struct tagSNOOP_RETURNENTRY { - /* code part */ - BYTE lcall; /* 0xe8 call snoopret relative*/ - /* NOTE: If you move snoopret OR origreturn fix the relative offset - * calculation! - */ - DWORD snoopret; /* SNOOP_Ret relative */ - /* unreached */ - FARPROC origreturn; - SNOOP_DLL *dll; - DWORD ordinal; - DWORD origESP; - DWORD *args; /* saved args across a stdcall */ -} SNOOP_RETURNENTRY; - -typedef struct tagSNOOP_RETURNENTRIES { - SNOOP_RETURNENTRY entry[4092/sizeof(SNOOP_RETURNENTRY)]; - struct tagSNOOP_RETURNENTRIES *next; -} SNOOP_RETURNENTRIES; - -#include "poppack.h" - -static SNOOP_DLL *firstdll = NULL; -static SNOOP_RETURNENTRIES *firstrets = NULL; - -/*********************************************************************** - * SNOOP_ShowDebugmsgSnoop - * - * Simple function to decide if a particular debugging message is - * wanted. - */ -int SNOOP_ShowDebugmsgSnoop(const char *dll, int ord, const char *fname) { - - if(debug_snoop_excludelist || debug_snoop_includelist) { - const char **listitem; - char buf[80]; - int len, len2, itemlen, show; - - if(debug_snoop_excludelist) { - show = 1; - listitem = debug_snoop_excludelist; - } else { - show = 0; - listitem = debug_snoop_includelist; - } - len = strlen(dll); - assert(len < 64); - sprintf(buf, "%s.%d", dll, ord); - len2 = strlen(buf); - for(; *listitem; listitem++) { - itemlen = strlen(*listitem); - if((itemlen == len && !strncasecmp(*listitem, buf, len)) || - (itemlen == len2 && !strncasecmp(*listitem, buf, len2)) || - !strcasecmp(*listitem, fname)) { - show = !show; - break; - } - } - return show; - } - return 1; -} - -void SNOOP_SetupDLL(HMODULE hmod) -{ - SNOOP_DLL **dll = &firstdll; - char *p, *name; - void *addr; - SIZE_T size; - IMAGE_EXPORT_DIRECTORY *exports; - - exports = RtlImageDirectoryEntryToData( hmod, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size ); - if (!exports) return; - name = (char *)hmod + exports->Name; - - TRACE("hmod=%p, name=%s\n", hmod, name); - - while (*dll) { - if ((*dll)->hmod == hmod) - { - /* another dll, loaded at the same address */ - addr = (*dll)->funs; - size = (*dll)->nrofordinals * sizeof(SNOOP_FUN); - NtFreeVirtualMemory(GetCurrentProcess(), &addr, &size, MEM_RELEASE); - break; - } - dll = &((*dll)->next); - } - *dll = RtlReAllocateHeap(ntdll_get_process_heap(), - HEAP_ZERO_MEMORY, *dll, - sizeof(SNOOP_DLL) + strlen(name)); - (*dll)->hmod = hmod; - (*dll)->ordbase = exports->Base; - (*dll)->nrofordinals = exports->NumberOfFunctions; - strcpy( (*dll)->name, name ); - p = (*dll)->name + strlen((*dll)->name) - 4; - if (p > (*dll)->name && !strcasecmp( p, ".dll" )) *p = 0; - - size = exports->NumberOfFunctions * sizeof(SNOOP_FUN); - NtAllocateVirtualMemory(GetCurrentProcess(), &addr, NULL, &size, - MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); - if (!addr) { - RtlFreeHeap(ntdll_get_process_heap(),0,*dll); - FIXME("out of memory\n"); - return; - } - (*dll)->funs = addr; - memset((*dll)->funs,0,size); -} - -FARPROC SNOOP_GetProcAddress( HMODULE hmod, IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size, - FARPROC origfun, DWORD ordinal ) -{ - int i; - const char *ename; - WORD *ordinals; - DWORD *names; - SNOOP_DLL *dll = firstdll; - SNOOP_FUN *fun; - IMAGE_SECTION_HEADER *sec; - - if (!TRACE_ON(snoop)) return origfun; - if (!*(LPBYTE)origfun) /* 0x00 is an imposs. opcode, poss. dataref. */ - return origfun; - - sec = RtlImageRvaToSection( RtlImageNtHeader(hmod), hmod, (char *)origfun - (char *)hmod ); - - if (!sec || !(sec->Characteristics & IMAGE_SCN_CNT_CODE)) - return origfun; /* most likely a data reference */ - - while (dll) { - if (hmod == dll->hmod) - break; - dll=dll->next; - } - if (!dll) /* probably internal */ - return origfun; - - /* try to find a name for it */ - ename = NULL; - names = (DWORD *)((char *)hmod + exports->AddressOfNames); - ordinals = (WORD *)((char *)hmod + exports->AddressOfNameOrdinals); - if (names) for (i = 0; i < exports->NumberOfNames; i++) - { - if (ordinals[i] == ordinal) - { - ename = (char *)hmod + names[i]; - break; - } - } - if (!SNOOP_ShowDebugmsgSnoop(dll->name,ordinal,ename)) - return origfun; - assert(ordinal < dll->nrofordinals); - fun = dll->funs+ordinal; - if (!fun->name) - { - fun->name = ename; - fun->lcall = 0xe8; - /* NOTE: origreturn struct member MUST come directly after snoopentry */ - fun->snoopentry = (char*)SNOOP_Entry-((char*)(&fun->nrofargs)); - fun->origfun = origfun; - fun->nrofargs = -1; - } - return (FARPROC)&(fun->lcall); -} - -static void SNOOP_PrintArg(DWORD x) -{ - int i,nostring; - - DPRINTF("%08lx",x); - if (!HIWORD(x) || TRACE_ON(seh)) return; /* trivial reject to avoid faults */ - __TRY - { - LPBYTE s=(LPBYTE)x; - i=0;nostring=0; - while (i<80) { - if (s[i]==0) break; - if (s[i]<0x20) {nostring=1;break;} - if (s[i]>=0x80) {nostring=1;break;} - i++; - } - if (!nostring && i > 5) - DPRINTF(" %s",debugstr_an((LPSTR)x,i)); - else /* try unicode */ - { - LPWSTR s=(LPWSTR)x; - i=0;nostring=0; - while (i<80) { - if (s[i]==0) break; - if (s[i]<0x20) {nostring=1;break;} - if (s[i]>0x100) {nostring=1;break;} - i++; - } - if (!nostring && i > 5) DPRINTF(" %s",debugstr_wn((LPWSTR)x,i)); - } - } - __EXCEPT(page_fault) - { - } - __ENDTRY -} - -#define CALLER1REF (*(DWORD*)context->Esp) - -void WINAPI SNOOP_DoEntry( CONTEXT86 *context ) -{ - DWORD ordinal=0,entry = context->Eip - 5; - SNOOP_DLL *dll = firstdll; - SNOOP_FUN *fun = NULL; - SNOOP_RETURNENTRIES **rets = &firstrets; - SNOOP_RETURNENTRY *ret; - int i=0, max; - - while (dll) { - if ( ((char*)entry>=(char*)dll->funs) && - ((char*)entry<=(char*)(dll->funs+dll->nrofordinals)) - ) { - fun = (SNOOP_FUN*)entry; - ordinal = fun-dll->funs; - break; - } - dll=dll->next; - } - if (!dll) { - FIXME("entrypoint 0x%08lx not found\n",entry); - return; /* oops */ - } - /* guess cdecl ... */ - if (fun->nrofargs<0) { - /* Typical cdecl return frame is: - * add esp, xxxxxxxx - * which has (for xxxxxxxx up to 255 the opcode "83 C4 xx". - * (after that 81 C2 xx xx xx xx) - */ - LPBYTE reteip = (LPBYTE)CALLER1REF; - - if (reteip) { - if ((reteip[0]==0x83)&&(reteip[1]==0xc4)) - fun->nrofargs=reteip[2]/4; - } - } - - - while (*rets) { - for (i=0;ientry)/sizeof((*rets)->entry[0]);i++) - if (!(*rets)->entry[i].origreturn) - break; - if (i!=sizeof((*rets)->entry)/sizeof((*rets)->entry[0])) - break; - rets = &((*rets)->next); - } - if (!*rets) { - SIZE_T size = 4096; - VOID* addr; - - NtAllocateVirtualMemory(GetCurrentProcess(), &addr, NULL, &size, - MEM_COMMIT | MEM_RESERVE, - PAGE_EXECUTE_READWRITE); - if (!addr) return; - *rets = addr; - memset(*rets,0,4096); - i = 0; /* entry 0 is free */ - } - ret = &((*rets)->entry[i]); - ret->lcall = 0xe8; - /* NOTE: origreturn struct member MUST come directly after snoopret */ - ret->snoopret = ((char*)SNOOP_Return)-(char*)(&ret->origreturn); - ret->origreturn = (FARPROC)CALLER1REF; - CALLER1REF = (DWORD)&ret->lcall; - ret->dll = dll; - ret->args = NULL; - ret->ordinal = ordinal; - ret->origESP = context->Esp; - - context->Eip = (DWORD)fun->origfun; - - if (fun->name) DPRINTF("%04lx:CALL %s.%s(",GetCurrentThreadId(),dll->name,fun->name); - else DPRINTF("%04lx:CALL %s.%ld(",GetCurrentThreadId(),dll->name,dll->ordbase+ordinal); - if (fun->nrofargs>0) { - max = fun->nrofargs; if (max>16) max=16; - for (i=0;iEsp + 4 + sizeof(DWORD)*i)); - if (inrofargs-1) DPRINTF(","); - } - if (max!=fun->nrofargs) - DPRINTF(" ..."); - } else if (fun->nrofargs<0) { - DPRINTF(""); - ret->args = RtlAllocateHeap(ntdll_get_process_heap(), - 0,16*sizeof(DWORD)); - memcpy(ret->args,(LPBYTE)(context->Esp + 4),sizeof(DWORD)*16); - } - DPRINTF(") ret=%08lx\n",(DWORD)ret->origreturn); -} - - -void WINAPI SNOOP_DoReturn( CONTEXT86 *context ) -{ - SNOOP_RETURNENTRY *ret = (SNOOP_RETURNENTRY*)(context->Eip - 5); - SNOOP_FUN *fun = &ret->dll->funs[ret->ordinal]; - - /* We haven't found out the nrofargs yet. If we called a cdecl - * function it is too late anyway and we can just set '0' (which - * will be the difference between orig and current ESP - * If stdcall -> everything ok. - */ - if (ret->dll->funs[ret->ordinal].nrofargs<0) - ret->dll->funs[ret->ordinal].nrofargs=(context->Esp - ret->origESP-4)/4; - context->Eip = (DWORD)ret->origreturn; - if (ret->args) { - int i,max; - - if (fun->name) - DPRINTF("%04lx:RET %s.%s(", GetCurrentThreadId(), ret->dll->name, fun->name); - else - DPRINTF("%04lx:RET %s.%ld(", GetCurrentThreadId(), - ret->dll->name,ret->dll->ordbase+ret->ordinal); - - max = fun->nrofargs; - if (max>16) max=16; - - for (i=0;iargs[i]); - if (iEax,(DWORD)ret->origreturn ); - RtlFreeHeap(ntdll_get_process_heap(),0,ret->args); - ret->args = NULL; - } - else - { - if (fun->name) - DPRINTF("%04lx:RET %s.%s() retval=%08lx ret=%08lx\n", - GetCurrentThreadId(), - ret->dll->name, fun->name, context->Eax, (DWORD)ret->origreturn); - else - DPRINTF("%04lx:RET %s.%ld() retval=%08lx ret=%08lx\n", - GetCurrentThreadId(), - ret->dll->name,ret->dll->ordbase+ret->ordinal, - context->Eax, (DWORD)ret->origreturn); - } - ret->origreturn = NULL; /* mark as empty */ -} - -/* assembly wrappers that save the context */ -__ASM_GLOBAL_FUNC( SNOOP_Entry, - "call " __ASM_NAME("__wine_call_from_32_regs") "\n\t" - ".long " __ASM_NAME("SNOOP_DoEntry") ",0" ); -__ASM_GLOBAL_FUNC( SNOOP_Return, - "call " __ASM_NAME("__wine_call_from_32_regs") "\n\t" - ".long " __ASM_NAME("SNOOP_DoReturn") ",0" ); - -#else /* !__i386__ */ - -void SNOOP_SetupDLL(HMODULE hmod) -{ - FIXME("snooping works only on i386 for now.\n"); -} - -FARPROC SNOOP_GetProcAddress( HMODULE hmod, IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size, - FARPROC origfun, DWORD ordinal ) -{ - return origfun; -} -#endif /* !__i386__ */