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