Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 1 | /* |
| 2 | * 386-specific Win32 dll<->dll snooping functions |
| 3 | * |
| 4 | * Copyright 1998 Marcus Meissner |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 5 | * |
| 6 | * This library is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU Lesser General Public |
| 8 | * License as published by the Free Software Foundation; either |
| 9 | * version 2.1 of the License, or (at your option) any later version. |
| 10 | * |
| 11 | * This library is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | * Lesser General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU Lesser General Public |
| 17 | * License along with this library; if not, write to the Free Software |
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 19 | */ |
| 20 | |
Patrik Stridvall | 9633632 | 1999-10-24 22:13:47 +0000 | [diff] [blame] | 21 | #include "config.h" |
Alexandre Julliard | 894b188 | 2002-04-25 21:40:56 +0000 | [diff] [blame] | 22 | #include "wine/port.h" |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 23 | |
| 24 | #include <assert.h> |
Alexandre Julliard | 383da68 | 2000-02-10 22:15:21 +0000 | [diff] [blame] | 25 | #include <stdio.h> |
Marcus Meissner | 317af32 | 1999-02-17 13:51:06 +0000 | [diff] [blame] | 26 | #include <string.h> |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 27 | #include "winbase.h" |
| 28 | #include "winnt.h" |
Patrik Stridvall | 9c1de6d | 2002-09-12 22:07:02 +0000 | [diff] [blame] | 29 | #include "winternl.h" |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 30 | #include "snoop.h" |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 31 | #include "stackframe.h" |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 32 | #include "wine/debug.h" |
Uwe Bonnes | 69277bb | 2000-04-23 20:38:49 +0000 | [diff] [blame] | 33 | #include "wine/exception.h" |
Peter Hunnisett | 73ab649 | 2002-02-25 20:10:35 +0000 | [diff] [blame] | 34 | #include "msvcrt/excpt.h" |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 35 | |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 36 | WINE_DEFAULT_DEBUG_CHANNEL(snoop); |
Patrik Stridvall | b4b9fae | 1999-04-19 14:56:29 +0000 | [diff] [blame] | 37 | |
Uwe Bonnes | 69277bb | 2000-04-23 20:38:49 +0000 | [diff] [blame] | 38 | static WINE_EXCEPTION_FILTER(page_fault) |
| 39 | { |
Rein Klazes | 2826f57 | 2000-09-19 02:39:59 +0000 | [diff] [blame] | 40 | if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION || |
| 41 | GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION) |
Uwe Bonnes | 69277bb | 2000-04-23 20:38:49 +0000 | [diff] [blame] | 42 | return EXCEPTION_EXECUTE_HANDLER; |
| 43 | return EXCEPTION_CONTINUE_SEARCH; |
| 44 | } |
| 45 | |
Alexandre Julliard | a061b84 | 2002-06-04 17:48:41 +0000 | [diff] [blame] | 46 | extern const char **debug_snoop_excludelist; |
| 47 | extern const char **debug_snoop_includelist; |
Alexandre Julliard | ebfc0fe | 1998-06-28 18:40:26 +0000 | [diff] [blame] | 48 | |
Ulrich Weigand | 6ca85a5 | 1999-11-14 21:28:57 +0000 | [diff] [blame] | 49 | #ifdef __i386__ |
| 50 | |
Rein Klazes | 43a98a6 | 1999-11-14 19:44:43 +0000 | [diff] [blame] | 51 | extern void WINAPI SNOOP_Entry(); |
| 52 | extern void WINAPI SNOOP_Return(); |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 53 | |
Patrik Stridvall | c7a8dde | 1999-04-25 12:36:53 +0000 | [diff] [blame] | 54 | #include "pshpack1.h" |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 55 | |
| 56 | typedef struct tagSNOOP_FUN { |
| 57 | /* code part */ |
| 58 | BYTE lcall; /* 0xe8 call snoopentry (relative) */ |
| 59 | /* NOTE: If you move snoopentry OR nrofargs fix the relative offset |
| 60 | * calculation! |
| 61 | */ |
| 62 | DWORD snoopentry; /* SNOOP_Entry relative */ |
| 63 | /* unreached */ |
| 64 | int nrofargs; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 65 | FARPROC origfun; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 66 | char *name; |
| 67 | } SNOOP_FUN; |
| 68 | |
| 69 | typedef struct tagSNOOP_DLL { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 70 | HMODULE hmod; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 71 | SNOOP_FUN *funs; |
Andreas Mohr | 9abd553 | 2001-05-24 18:43:16 +0000 | [diff] [blame] | 72 | DWORD ordbase; |
Alexandre Julliard | 908464d | 2000-11-01 03:11:12 +0000 | [diff] [blame] | 73 | DWORD nrofordinals; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 74 | struct tagSNOOP_DLL *next; |
Alexandre Julliard | 5f728ca | 2001-07-24 21:45:22 +0000 | [diff] [blame] | 75 | char name[1]; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 76 | } SNOOP_DLL; |
Alexandre Julliard | 5f728ca | 2001-07-24 21:45:22 +0000 | [diff] [blame] | 77 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 78 | typedef struct tagSNOOP_RETURNENTRY { |
| 79 | /* code part */ |
| 80 | BYTE lcall; /* 0xe8 call snoopret relative*/ |
| 81 | /* NOTE: If you move snoopret OR origreturn fix the relative offset |
| 82 | * calculation! |
| 83 | */ |
| 84 | DWORD snoopret; /* SNOOP_Ret relative */ |
| 85 | /* unreached */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 86 | FARPROC origreturn; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 87 | SNOOP_DLL *dll; |
| 88 | DWORD ordinal; |
| 89 | DWORD origESP; |
| 90 | DWORD *args; /* saved args across a stdcall */ |
| 91 | } SNOOP_RETURNENTRY; |
| 92 | |
| 93 | typedef struct tagSNOOP_RETURNENTRIES { |
| 94 | SNOOP_RETURNENTRY entry[4092/sizeof(SNOOP_RETURNENTRY)]; |
| 95 | struct tagSNOOP_RETURNENTRIES *next; |
| 96 | } SNOOP_RETURNENTRIES; |
| 97 | |
Patrik Stridvall | c7a8dde | 1999-04-25 12:36:53 +0000 | [diff] [blame] | 98 | #include "poppack.h" |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 99 | |
| 100 | static SNOOP_DLL *firstdll = NULL; |
| 101 | static SNOOP_RETURNENTRIES *firstrets = NULL; |
| 102 | |
Alexandre Julliard | ebfc0fe | 1998-06-28 18:40:26 +0000 | [diff] [blame] | 103 | /*********************************************************************** |
| 104 | * SNOOP_ShowDebugmsgSnoop |
| 105 | * |
| 106 | * Simple function to decide if a particular debugging message is |
| 107 | * wanted. |
| 108 | */ |
| 109 | int SNOOP_ShowDebugmsgSnoop(const char *dll, int ord, const char *fname) { |
| 110 | |
| 111 | if(debug_snoop_excludelist || debug_snoop_includelist) { |
Alexandre Julliard | a061b84 | 2002-06-04 17:48:41 +0000 | [diff] [blame] | 112 | const char **listitem; |
Alexandre Julliard | ebfc0fe | 1998-06-28 18:40:26 +0000 | [diff] [blame] | 113 | char buf[80]; |
| 114 | int len, len2, itemlen, show; |
| 115 | |
| 116 | if(debug_snoop_excludelist) { |
| 117 | show = 1; |
| 118 | listitem = debug_snoop_excludelist; |
| 119 | } else { |
| 120 | show = 0; |
| 121 | listitem = debug_snoop_includelist; |
| 122 | } |
| 123 | len = strlen(dll); |
| 124 | assert(len < 64); |
| 125 | sprintf(buf, "%s.%d", dll, ord); |
| 126 | len2 = strlen(buf); |
| 127 | for(; *listitem; listitem++) { |
| 128 | itemlen = strlen(*listitem); |
Lawson Whitney | bae8af2 | 2001-02-12 01:19:04 +0000 | [diff] [blame] | 129 | if((itemlen == len && !strncasecmp(*listitem, buf, len)) || |
| 130 | (itemlen == len2 && !strncasecmp(*listitem, buf, len2)) || |
| 131 | !strcasecmp(*listitem, fname)) { |
Alexandre Julliard | ebfc0fe | 1998-06-28 18:40:26 +0000 | [diff] [blame] | 132 | show = !show; |
| 133 | break; |
| 134 | } |
| 135 | } |
| 136 | return show; |
| 137 | } |
| 138 | return 1; |
| 139 | } |
| 140 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 141 | void |
Andreas Mohr | 9abd553 | 2001-05-24 18:43:16 +0000 | [diff] [blame] | 142 | SNOOP_RegisterDLL(HMODULE hmod,LPCSTR name,DWORD ordbase,DWORD nrofordinals) { |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 143 | SNOOP_DLL **dll = &(firstdll); |
| 144 | char *s; |
| 145 | |
Dmitry Timoshkov | 23d4aab | 2002-04-02 02:49:42 +0000 | [diff] [blame] | 146 | TRACE("hmod=%x, name=%s, ordbase=%ld, nrofordinals=%ld\n", |
| 147 | hmod, name, ordbase, nrofordinals); |
| 148 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 149 | if (!TRACE_ON(snoop)) return; |
| 150 | while (*dll) { |
| 151 | if ((*dll)->hmod == hmod) |
Dmitry Timoshkov | 23d4aab | 2002-04-02 02:49:42 +0000 | [diff] [blame] | 152 | { |
| 153 | /* another dll, loaded at the same address */ |
| 154 | VirtualFree((*dll)->funs, (*dll)->nrofordinals*sizeof(SNOOP_FUN), MEM_RELEASE); |
| 155 | break; |
| 156 | } |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 157 | dll = &((*dll)->next); |
| 158 | } |
Dmitry Timoshkov | 23d4aab | 2002-04-02 02:49:42 +0000 | [diff] [blame] | 159 | *dll = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *dll, sizeof(SNOOP_DLL)+strlen(name)); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 160 | (*dll)->hmod = hmod; |
Andreas Mohr | 9abd553 | 2001-05-24 18:43:16 +0000 | [diff] [blame] | 161 | (*dll)->ordbase = ordbase; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 162 | (*dll)->nrofordinals = nrofordinals; |
Alexandre Julliard | 5f728ca | 2001-07-24 21:45:22 +0000 | [diff] [blame] | 163 | strcpy( (*dll)->name, name ); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 164 | if ((s=strrchr((*dll)->name,'.'))) |
| 165 | *s='\0'; |
| 166 | (*dll)->funs = VirtualAlloc(NULL,nrofordinals*sizeof(SNOOP_FUN),MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE); |
| 167 | memset((*dll)->funs,0,nrofordinals*sizeof(SNOOP_FUN)); |
| 168 | if (!(*dll)->funs) { |
Alexandre Julliard | 90476d6 | 2000-02-16 22:47:24 +0000 | [diff] [blame] | 169 | HeapFree(GetProcessHeap(),0,*dll); |
Alexandre Julliard | 9fe7a25 | 1999-05-14 08:17:14 +0000 | [diff] [blame] | 170 | FIXME("out of memory\n"); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 171 | return; |
| 172 | } |
| 173 | } |
| 174 | |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 175 | FARPROC |
| 176 | SNOOP_GetProcAddress(HMODULE hmod,LPCSTR name,DWORD ordinal,FARPROC origfun) { |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 177 | SNOOP_DLL *dll = firstdll; |
| 178 | SNOOP_FUN *fun; |
Alexandre Julliard | a5dea21 | 2002-08-09 19:57:38 +0000 | [diff] [blame] | 179 | IMAGE_SECTION_HEADER *sec; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 180 | |
| 181 | if (!TRACE_ON(snoop)) return origfun; |
| 182 | if (!*(LPBYTE)origfun) /* 0x00 is an imposs. opcode, poss. dataref. */ |
| 183 | return origfun; |
Alexandre Julliard | a5dea21 | 2002-08-09 19:57:38 +0000 | [diff] [blame] | 184 | |
| 185 | sec = RtlImageRvaToSection( RtlImageNtHeader(hmod), hmod, (char *)origfun - (char *)hmod ); |
| 186 | |
| 187 | if (!sec || !(sec->Characteristics & IMAGE_SCN_CNT_CODE)) |
| 188 | return origfun; /* most likely a data reference */ |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 189 | |
| 190 | while (dll) { |
| 191 | if (hmod == dll->hmod) |
| 192 | break; |
| 193 | dll=dll->next; |
| 194 | } |
| 195 | if (!dll) /* probably internal */ |
| 196 | return origfun; |
Marcus Meissner | 30c112e | 1998-11-14 17:06:55 +0000 | [diff] [blame] | 197 | if (!SNOOP_ShowDebugmsgSnoop(dll->name,ordinal,name)) |
| 198 | return origfun; |
Alexandre Julliard | 908464d | 2000-11-01 03:11:12 +0000 | [diff] [blame] | 199 | assert(ordinal < dll->nrofordinals); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 200 | fun = dll->funs+ordinal; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 201 | if (!fun->name) |
Uwe Bonnes | 574a10e | 2001-07-14 00:43:57 +0000 | [diff] [blame] | 202 | { |
Alexandre Julliard | 5f728ca | 2001-07-24 21:45:22 +0000 | [diff] [blame] | 203 | fun->name = HeapAlloc(GetProcessHeap(),0,strlen(name)+1); |
| 204 | strcpy( fun->name, name ); |
Uwe Bonnes | 574a10e | 2001-07-14 00:43:57 +0000 | [diff] [blame] | 205 | fun->lcall = 0xe8; |
| 206 | /* NOTE: origreturn struct member MUST come directly after snoopentry */ |
| 207 | fun->snoopentry = (char*)SNOOP_Entry-((char*)(&fun->nrofargs)); |
| 208 | fun->origfun = origfun; |
| 209 | fun->nrofargs = -1; |
| 210 | } |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 211 | return (FARPROC)&(fun->lcall); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 212 | } |
| 213 | |
Alexandre Julliard | 0aa28b5 | 2002-05-17 02:55:48 +0000 | [diff] [blame] | 214 | static void SNOOP_PrintArg(DWORD x) |
| 215 | { |
| 216 | int i,nostring; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 217 | |
Alexandre Julliard | 0aa28b5 | 2002-05-17 02:55:48 +0000 | [diff] [blame] | 218 | DPRINTF("%08lx",x); |
| 219 | if ( !HIWORD(x) ) return; /* trivial reject to avoid faults */ |
| 220 | __TRY |
| 221 | { |
| 222 | LPBYTE s=(LPBYTE)x; |
| 223 | i=0;nostring=0; |
| 224 | while (i<80) { |
| 225 | if (s[i]==0) break; |
| 226 | if (s[i]<0x20) {nostring=1;break;} |
| 227 | if (s[i]>=0x80) {nostring=1;break;} |
| 228 | i++; |
| 229 | } |
| 230 | if (!nostring && i > 5) |
| 231 | DPRINTF(" %s",debugstr_an((LPSTR)x,i)); |
| 232 | else /* try unicode */ |
| 233 | { |
| 234 | LPWSTR s=(LPWSTR)x; |
| 235 | i=0;nostring=0; |
| 236 | while (i<80) { |
| 237 | if (s[i]==0) break; |
| 238 | if (s[i]<0x20) {nostring=1;break;} |
| 239 | if (s[i]>0x100) {nostring=1;break;} |
| 240 | i++; |
| 241 | } |
| 242 | if (!nostring && i > 5) DPRINTF(" %s",debugstr_wn((LPWSTR)x,i)); |
| 243 | } |
| 244 | } |
| 245 | __EXCEPT(page_fault) |
| 246 | { |
| 247 | } |
| 248 | __ENDTRY |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 249 | } |
| 250 | |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 251 | #define CALLER1REF (*(DWORD*)context->Esp) |
Ulrich Weigand | 6ca85a5 | 1999-11-14 21:28:57 +0000 | [diff] [blame] | 252 | |
Ulrich Weigand | 6ca85a5 | 1999-11-14 21:28:57 +0000 | [diff] [blame] | 253 | void WINAPI SNOOP_DoEntry( CONTEXT86 *context ) |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 254 | { |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 255 | DWORD ordinal=0,entry = context->Eip - 5; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 256 | SNOOP_DLL *dll = firstdll; |
| 257 | SNOOP_FUN *fun = NULL; |
| 258 | SNOOP_RETURNENTRIES **rets = &firstrets; |
| 259 | SNOOP_RETURNENTRY *ret; |
Dimitrie O. Paun | 334a42f | 2000-10-29 18:07:04 +0000 | [diff] [blame] | 260 | int i=0, max; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 261 | |
| 262 | while (dll) { |
| 263 | if ( ((char*)entry>=(char*)dll->funs) && |
| 264 | ((char*)entry<=(char*)(dll->funs+dll->nrofordinals)) |
| 265 | ) { |
| 266 | fun = (SNOOP_FUN*)entry; |
| 267 | ordinal = fun-dll->funs; |
| 268 | break; |
| 269 | } |
| 270 | dll=dll->next; |
| 271 | } |
| 272 | if (!dll) { |
Alexandre Julliard | 9fe7a25 | 1999-05-14 08:17:14 +0000 | [diff] [blame] | 273 | FIXME("entrypoint 0x%08lx not found\n",entry); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 274 | return; /* oops */ |
| 275 | } |
| 276 | /* guess cdecl ... */ |
| 277 | if (fun->nrofargs<0) { |
| 278 | /* Typical cdecl return frame is: |
Alexandre Julliard | ebfc0fe | 1998-06-28 18:40:26 +0000 | [diff] [blame] | 279 | * add esp, xxxxxxxx |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 280 | * which has (for xxxxxxxx up to 255 the opcode "83 C4 xx". |
Marcus Meissner | 4178629 | 1998-10-11 10:47:02 +0000 | [diff] [blame] | 281 | * (after that 81 C2 xx xx xx xx) |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 282 | */ |
| 283 | LPBYTE reteip = (LPBYTE)CALLER1REF; |
| 284 | |
Alexandre Julliard | 829fe32 | 1998-07-26 14:27:39 +0000 | [diff] [blame] | 285 | if (reteip) { |
| 286 | if ((reteip[0]==0x83)&&(reteip[1]==0xc4)) |
| 287 | fun->nrofargs=reteip[2]/4; |
| 288 | } |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 289 | } |
| 290 | |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 291 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 292 | while (*rets) { |
| 293 | for (i=0;i<sizeof((*rets)->entry)/sizeof((*rets)->entry[0]);i++) |
| 294 | if (!(*rets)->entry[i].origreturn) |
| 295 | break; |
| 296 | if (i!=sizeof((*rets)->entry)/sizeof((*rets)->entry[0])) |
| 297 | break; |
| 298 | rets = &((*rets)->next); |
| 299 | } |
| 300 | if (!*rets) { |
| 301 | *rets = VirtualAlloc(NULL,4096,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE); |
| 302 | memset(*rets,0,4096); |
| 303 | i = 0; /* entry 0 is free */ |
| 304 | } |
| 305 | ret = &((*rets)->entry[i]); |
| 306 | ret->lcall = 0xe8; |
| 307 | /* NOTE: origreturn struct member MUST come directly after snoopret */ |
| 308 | ret->snoopret = ((char*)SNOOP_Return)-(char*)(&ret->origreturn); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 309 | ret->origreturn = (FARPROC)CALLER1REF; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 310 | CALLER1REF = (DWORD)&ret->lcall; |
| 311 | ret->dll = dll; |
| 312 | ret->args = NULL; |
| 313 | ret->ordinal = ordinal; |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 314 | ret->origESP = context->Esp; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 315 | |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 316 | context->Eip = (DWORD)fun->origfun; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 317 | |
Andreas Mohr | 9abd553 | 2001-05-24 18:43:16 +0000 | [diff] [blame] | 318 | DPRINTF("%08lx:CALL %s.%ld: %s(",GetCurrentThreadId(),dll->name,dll->ordbase+ordinal,fun->name); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 319 | if (fun->nrofargs>0) { |
| 320 | max = fun->nrofargs; if (max>16) max=16; |
| 321 | for (i=0;i<max;i++) |
Alexandre Julliard | 0aa28b5 | 2002-05-17 02:55:48 +0000 | [diff] [blame] | 322 | { |
| 323 | SNOOP_PrintArg(*(DWORD*)(context->Esp + 4 + sizeof(DWORD)*i)); |
| 324 | if (i<fun->nrofargs-1) DPRINTF(","); |
| 325 | } |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 326 | if (max!=fun->nrofargs) |
| 327 | DPRINTF(" ..."); |
| 328 | } else if (fun->nrofargs<0) { |
| 329 | DPRINTF("<unknown, check return>"); |
Alexandre Julliard | 90476d6 | 2000-02-16 22:47:24 +0000 | [diff] [blame] | 330 | ret->args = HeapAlloc(GetProcessHeap(),0,16*sizeof(DWORD)); |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 331 | memcpy(ret->args,(LPBYTE)(context->Esp + 4),sizeof(DWORD)*16); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 332 | } |
Francois Gouget | e17d1a3 | 2001-05-08 00:13:38 +0000 | [diff] [blame] | 333 | DPRINTF(") ret=%08lx\n",(DWORD)ret->origreturn); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 334 | } |
| 335 | |
Alexandre Julliard | 85d666a | 2000-12-12 00:49:45 +0000 | [diff] [blame] | 336 | |
Ulrich Weigand | 6ca85a5 | 1999-11-14 21:28:57 +0000 | [diff] [blame] | 337 | void WINAPI SNOOP_DoReturn( CONTEXT86 *context ) |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 338 | { |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 339 | SNOOP_RETURNENTRY *ret = (SNOOP_RETURNENTRY*)(context->Eip - 5); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 340 | |
| 341 | /* We haven't found out the nrofargs yet. If we called a cdecl |
Alexandre Julliard | ebfc0fe | 1998-06-28 18:40:26 +0000 | [diff] [blame] | 342 | * function it is too late anyway and we can just set '0' (which |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 343 | * will be the difference between orig and current ESP |
| 344 | * If stdcall -> everything ok. |
| 345 | */ |
| 346 | if (ret->dll->funs[ret->ordinal].nrofargs<0) |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 347 | ret->dll->funs[ret->ordinal].nrofargs=(context->Esp - ret->origESP-4)/4; |
| 348 | context->Eip = (DWORD)ret->origreturn; |
Marcus Meissner | 4178629 | 1998-10-11 10:47:02 +0000 | [diff] [blame] | 349 | if (ret->args) { |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 350 | int i,max; |
| 351 | |
Francois Gouget | e17d1a3 | 2001-05-08 00:13:38 +0000 | [diff] [blame] | 352 | DPRINTF("%08lx:RET %s.%ld: %s(", |
| 353 | GetCurrentThreadId(), |
Andreas Mohr | 9abd553 | 2001-05-24 18:43:16 +0000 | [diff] [blame] | 354 | ret->dll->name,ret->dll->ordbase+ret->ordinal,ret->dll->funs[ret->ordinal].name); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 355 | max = ret->dll->funs[ret->ordinal].nrofargs; |
| 356 | if (max>16) max=16; |
| 357 | |
| 358 | for (i=0;i<max;i++) |
Alexandre Julliard | 0aa28b5 | 2002-05-17 02:55:48 +0000 | [diff] [blame] | 359 | { |
| 360 | SNOOP_PrintArg(ret->args[i]); |
| 361 | if (i<max-1) DPRINTF(","); |
| 362 | } |
Francois Gouget | e17d1a3 | 2001-05-08 00:13:38 +0000 | [diff] [blame] | 363 | DPRINTF(") retval = %08lx ret=%08lx\n", |
| 364 | context->Eax,(DWORD)ret->origreturn ); |
Alexandre Julliard | 90476d6 | 2000-02-16 22:47:24 +0000 | [diff] [blame] | 365 | HeapFree(GetProcessHeap(),0,ret->args); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 366 | ret->args = NULL; |
| 367 | } else |
Uwe Bonnes | 0249fcd | 2001-07-18 20:00:06 +0000 | [diff] [blame] | 368 | DPRINTF("%08lx:RET %s.%ld: %s() retval = %08lx ret=%08lx\n", |
Francois Gouget | e17d1a3 | 2001-05-08 00:13:38 +0000 | [diff] [blame] | 369 | GetCurrentThreadId(), |
Andreas Mohr | 9abd553 | 2001-05-24 18:43:16 +0000 | [diff] [blame] | 370 | ret->dll->name,ret->dll->ordbase+ret->ordinal,ret->dll->funs[ret->ordinal].name, |
Uwe Bonnes | 0249fcd | 2001-07-18 20:00:06 +0000 | [diff] [blame] | 371 | context->Eax, (DWORD)ret->origreturn); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 372 | ret->origreturn = NULL; /* mark as empty */ |
| 373 | } |
Alexandre Julliard | 85d666a | 2000-12-12 00:49:45 +0000 | [diff] [blame] | 374 | |
| 375 | /* assembly wrappers that save the context */ |
| 376 | __ASM_GLOBAL_FUNC( SNOOP_Entry, |
Alexandre Julliard | eb9a863 | 2001-12-11 00:50:33 +0000 | [diff] [blame] | 377 | "call " __ASM_NAME("__wine_call_from_32_regs") "\n\t" |
Alexandre Julliard | 85d666a | 2000-12-12 00:49:45 +0000 | [diff] [blame] | 378 | ".long " __ASM_NAME("SNOOP_DoEntry") ",0" ); |
| 379 | __ASM_GLOBAL_FUNC( SNOOP_Return, |
Alexandre Julliard | eb9a863 | 2001-12-11 00:50:33 +0000 | [diff] [blame] | 380 | "call " __ASM_NAME("__wine_call_from_32_regs") "\n\t" |
Alexandre Julliard | 85d666a | 2000-12-12 00:49:45 +0000 | [diff] [blame] | 381 | ".long " __ASM_NAME("SNOOP_DoReturn") ",0" ); |
| 382 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 383 | #else /* !__i386__ */ |
Warren Baird | c43b5c8 | 2002-05-16 23:08:01 +0000 | [diff] [blame] | 384 | void SNOOP_RegisterDLL(HMODULE hmod,LPCSTR name,DWORD nrofordinals, DWORD dw) { |
Ulrich Weigand | 9a07b16 | 2000-12-27 18:37:37 +0000 | [diff] [blame] | 385 | if (!TRACE_ON(snoop)) return; |
Alexandre Julliard | 9fe7a25 | 1999-05-14 08:17:14 +0000 | [diff] [blame] | 386 | FIXME("snooping works only on i386 for now.\n"); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 387 | } |
| 388 | |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 389 | FARPROC SNOOP_GetProcAddress(HMODULE hmod,LPCSTR name,DWORD ordinal,FARPROC origfun) { |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 390 | return origfun; |
| 391 | } |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 392 | #endif /* !__i386__ */ |