Mercurial > mplayer.hg
annotate loader/pe_image.c @ 22153:0cf24df5d97b
Revert part of commit r22170.
FFmpeg lavcodecs version is still
(or according to ffmpeg commit r7868, it's back to)
49.3.0, so global variables are not yet directly accessable (if ever).
author | iive |
---|---|
date | Wed, 07 Feb 2007 12:31:37 +0000 |
parents | a2e02e6b6379 |
children | acfe034e5386 |
rev | line source |
---|---|
1 | 1 /* |
2 * Copyright 1994 Eric Youndale & Erik Bos | |
3 * Copyright 1995 Martin von Löwis | |
4 * Copyright 1996-98 Marcus Meissner | |
5 * | |
6 * based on Eric Youndale's pe-test and: | |
7 * | |
8 * ftp.microsoft.com:/pub/developer/MSDN/CD8/PEFILE.ZIP | |
9 * make that: | |
10 * ftp.microsoft.com:/developr/MSDN/OctCD/PEFILE.ZIP | |
15166
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
13375
diff
changeset
|
11 * |
18783 | 12 * Modified for use with MPlayer, detailed changelog at |
13 * http://svn.mplayerhq.hu/mplayer/trunk/ | |
15166
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
13375
diff
changeset
|
14 * $Id$ |
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
13375
diff
changeset
|
15 * |
1 | 16 */ |
17 /* Notes: | |
18 * Before you start changing something in this file be aware of the following: | |
19 * | |
20 * - There are several functions called recursively. In a very subtle and | |
21 * obscure way. DLLs can reference each other recursively etc. | |
22 * - If you want to enhance, speed up or clean up something in here, think | |
23 * twice WHY it is implemented in that strange way. There is usually a reason. | |
24 * Though sometimes it might just be lazyness ;) | |
25 * - In PE_MapImage, right before fixup_imports() all external and internal | |
26 * state MUST be correct since this function can be called with the SAME image | |
27 * AGAIN. (Thats recursion for you.) That means MODREF.module and | |
28 * NE_MODULE.module32. | |
29 * - Sometimes, we can't use Linux mmap() to mmap() the images directly. | |
30 * | |
31 * The problem is, that there is not direct 1:1 mapping from a diskimage and | |
32 * a memoryimage. The headers at the start are mapped linear, but the sections | |
33 * are not. Older x86 pe binaries are 512 byte aligned in file and 4096 byte | |
34 * aligned in memory. Linux likes them 4096 byte aligned in memory (due to | |
35 * x86 pagesize, this cannot be fixed without a rather large kernel rewrite) | |
36 * and 'blocksize' file-aligned (offsets). Since we have 512/1024/2048 (CDROM) | |
37 * and other byte blocksizes, we can't always do this. We *can* do this for | |
38 * newer pe binaries produced by MSVC 5 and later, since they are also aligned | |
39 * to 4096 byte boundaries on disk. | |
40 */ | |
2069 | 41 #include "config.h" |
21261
a2e02e6b6379
Rename config.h --> debug.h and include config.h explicitly.
diego
parents:
18783
diff
changeset
|
42 #include "debug.h" |
1 | 43 |
44 #include <errno.h> | |
45 #include <assert.h> | |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
128
diff
changeset
|
46 #include <stdio.h> |
1 | 47 #include <stdlib.h> |
48 #include <string.h> | |
49 #include <unistd.h> | |
50 #include <sys/types.h> | |
51 #include <sys/stat.h> | |
52 #include <fcntl.h> | |
53 #ifdef HAVE_SYS_MMAN_H | |
54 #include <sys/mman.h> | |
55 #endif | |
7386 | 56 #include "wine/windef.h" |
57 #include "wine/winbase.h" | |
58 #include "wine/winerror.h" | |
59 #include "wine/heap.h" | |
60 #include "wine/pe_image.h" | |
61 #include "wine/module.h" | |
62 #include "wine/debugtools.h" | |
2069 | 63 #include "ext.h" |
1 | 64 #include "win32.h" |
65 | |
66 #define RVA(x) ((void *)((char *)load_addr+(unsigned int)(x))) | |
67 | |
68 #define AdjustPtr(ptr,delta) ((char *)(ptr) + (delta)) | |
69 | |
70 extern void* LookupExternal(const char* library, int ordinal); | |
71 extern void* LookupExternalByName(const char* library, const char* name); | |
72 | |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
128
diff
changeset
|
73 static void dump_exports( HMODULE hModule ) |
1 | 74 { |
75 char *Module; | |
7386 | 76 unsigned int i, j; |
1 | 77 u_short *ordinal; |
78 u_long *function,*functions; | |
79 u_char **name; | |
80 unsigned int load_addr = hModule; | |
81 | |
82 DWORD rva_start = PE_HEADER(hModule)->OptionalHeader | |
83 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; | |
84 DWORD rva_end = rva_start + PE_HEADER(hModule)->OptionalHeader | |
85 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; | |
86 IMAGE_EXPORT_DIRECTORY *pe_exports = (IMAGE_EXPORT_DIRECTORY*)RVA(rva_start); | |
87 | |
88 Module = (char*)RVA(pe_exports->Name); | |
89 TRACE("*******EXPORT DATA*******\n"); | |
90 TRACE("Module name is %s, %ld functions, %ld names\n", | |
91 Module, pe_exports->NumberOfFunctions, pe_exports->NumberOfNames); | |
92 | |
93 ordinal=(u_short*) RVA(pe_exports->AddressOfNameOrdinals); | |
94 functions=function=(u_long*) RVA(pe_exports->AddressOfFunctions); | |
95 name=(u_char**) RVA(pe_exports->AddressOfNames); | |
96 | |
97 TRACE(" Ord RVA Addr Name\n" ); | |
98 for (i=0;i<pe_exports->NumberOfFunctions;i++, function++) | |
99 { | |
100 if (!*function) continue; | |
101 if (TRACE_ON(win32)) | |
102 { | |
103 DPRINTF( "%4ld %08lx %p", i + pe_exports->Base, *function, RVA(*function) ); | |
104 | |
105 for (j = 0; j < pe_exports->NumberOfNames; j++) | |
106 if (ordinal[j] == i) | |
107 { | |
108 DPRINTF( " %s", (char*)RVA(name[j]) ); | |
109 break; | |
110 } | |
111 if ((*function >= rva_start) && (*function <= rva_end)) | |
112 DPRINTF(" (forwarded -> %s)", (char *)RVA(*function)); | |
113 DPRINTF("\n"); | |
114 } | |
115 } | |
116 } | |
117 | |
118 /* Look up the specified function or ordinal in the exportlist: | |
119 * If it is a string: | |
120 * - look up the name in the Name list. | |
121 * - look up the ordinal with that index. | |
122 * - use the ordinal as offset into the functionlist | |
123 * If it is a ordinal: | |
124 * - use ordinal-pe_export->Base as offset into the functionlist | |
125 */ | |
126 FARPROC PE_FindExportedFunction( | |
127 WINE_MODREF *wm, | |
128 LPCSTR funcName, | |
129 WIN_BOOL snoop ) | |
130 { | |
131 u_short * ordinals; | |
132 u_long * function; | |
7386 | 133 u_char ** name; |
134 const char *ename = NULL; | |
1 | 135 int i, ordinal; |
136 PE_MODREF *pem = &(wm->binfmt.pe); | |
137 IMAGE_EXPORT_DIRECTORY *exports = pem->pe_export; | |
138 unsigned int load_addr = wm->module; | |
139 u_long rva_start, rva_end, addr; | |
140 char * forward; | |
141 | |
142 if (HIWORD(funcName)) | |
143 TRACE("(%s)\n",funcName); | |
144 else | |
145 TRACE("(%d)\n",(int)funcName); | |
146 if (!exports) { | |
147 /* Not a fatal problem, some apps do | |
148 * GetProcAddress(0,"RegisterPenApp") which triggers this | |
149 * case. | |
150 */ | |
151 WARN("Module %08x(%s)/MODREF %p doesn't have a exports table.\n",wm->module,wm->modname,pem); | |
152 return NULL; | |
153 } | |
154 ordinals= (u_short*) RVA(exports->AddressOfNameOrdinals); | |
155 function= (u_long*) RVA(exports->AddressOfFunctions); | |
156 name = (u_char **) RVA(exports->AddressOfNames); | |
157 forward = NULL; | |
158 rva_start = PE_HEADER(wm->module)->OptionalHeader | |
159 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; | |
160 rva_end = rva_start + PE_HEADER(wm->module)->OptionalHeader | |
161 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; | |
162 | |
163 if (HIWORD(funcName)) | |
164 { | |
165 | |
166 int min = 0, max = exports->NumberOfNames - 1; | |
167 while (min <= max) | |
168 { | |
169 int res, pos = (min + max) / 2; | |
7386 | 170 ename = (const char*) RVA(name[pos]); |
171 if (!(res = strcmp( ename, funcName ))) | |
1 | 172 { |
173 ordinal = ordinals[pos]; | |
174 goto found; | |
175 } | |
176 if (res > 0) max = pos - 1; | |
177 else min = pos + 1; | |
178 } | |
179 | |
7386 | 180 for (i = 0; i < exports->NumberOfNames; i++) |
1 | 181 { |
7386 | 182 ename = (const char*) RVA(name[i]); |
1 | 183 if (!strcmp( ename, funcName )) |
184 { | |
2069 | 185 ERR( "%s.%s required a linear search\n", wm->modname, funcName ); |
1 | 186 ordinal = ordinals[i]; |
187 goto found; | |
188 } | |
189 } | |
190 return NULL; | |
191 } | |
192 else | |
193 { | |
194 ordinal = LOWORD(funcName) - exports->Base; | |
195 if (snoop && name) | |
196 { | |
197 for (i = 0; i < exports->NumberOfNames; i++) | |
198 if (ordinals[i] == ordinal) | |
199 { | |
200 ename = RVA(name[i]); | |
201 break; | |
202 } | |
203 } | |
204 } | |
205 | |
206 found: | |
207 if (ordinal >= exports->NumberOfFunctions) | |
208 { | |
209 TRACE(" ordinal %ld out of range!\n", ordinal + exports->Base ); | |
210 return NULL; | |
211 } | |
212 addr = function[ordinal]; | |
213 if (!addr) return NULL; | |
214 if ((addr < rva_start) || (addr >= rva_end)) | |
215 { | |
216 FARPROC proc = RVA(addr); | |
217 if (snoop) | |
218 { | |
219 if (!ename) ename = "@"; | |
220 // proc = SNOOP_GetProcAddress(wm->module,ename,ordinal,proc); | |
221 TRACE("SNOOP_GetProcAddress n/a\n"); | |
222 | |
223 } | |
224 return proc; | |
225 } | |
226 else | |
227 { | |
228 WINE_MODREF *wm; | |
229 char *forward = RVA(addr); | |
230 char module[256]; | |
231 char *end = strchr(forward, '.'); | |
232 | |
233 if (!end) return NULL; | |
234 if (end - forward >= sizeof(module)) return NULL; | |
235 memcpy( module, forward, end - forward ); | |
236 module[end-forward] = 0; | |
237 if (!(wm = MODULE_FindModule( module ))) | |
238 { | |
239 ERR("module not found for forward '%s'\n", forward ); | |
240 return NULL; | |
241 } | |
242 return MODULE_GetProcAddress( wm->module, end + 1, snoop ); | |
243 } | |
244 } | |
245 | |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
128
diff
changeset
|
246 static DWORD fixup_imports( WINE_MODREF *wm ) |
1 | 247 { |
248 IMAGE_IMPORT_DESCRIPTOR *pe_imp; | |
249 PE_MODREF *pem; | |
250 unsigned int load_addr = wm->module; | |
251 int i,characteristics_detection=1; | |
252 char *modname; | |
253 | |
254 assert(wm->type==MODULE32_PE); | |
255 pem = &(wm->binfmt.pe); | |
256 if (pem->pe_export) | |
257 modname = (char*) RVA(pem->pe_export->Name); | |
258 else | |
259 modname = "<unknown>"; | |
260 | |
261 | |
262 TRACE("Dumping imports list\n"); | |
263 | |
264 | |
265 pe_imp = pem->pe_import; | |
266 if (!pe_imp) return 0; | |
267 | |
268 /* We assume that we have at least one import with !0 characteristics and | |
269 * detect broken imports with all characteristsics 0 (notably Borland) and | |
270 * switch the detection off for them. | |
271 */ | |
272 for (i = 0; pe_imp->Name ; pe_imp++) { | |
273 if (!i && !pe_imp->u.Characteristics) | |
274 characteristics_detection = 0; | |
275 if (characteristics_detection && !pe_imp->u.Characteristics) | |
276 break; | |
277 i++; | |
278 } | |
279 if (!i) return 0; | |
280 | |
281 | |
282 wm->nDeps = i; | |
283 wm->deps = HeapAlloc( GetProcessHeap(), 0, i*sizeof(WINE_MODREF *) ); | |
284 | |
285 /* load the imported modules. They are automatically | |
286 * added to the modref list of the process. | |
287 */ | |
288 | |
289 for (i = 0, pe_imp = pem->pe_import; pe_imp->Name ; pe_imp++) { | |
290 WINE_MODREF *wmImp; | |
291 IMAGE_IMPORT_BY_NAME *pe_name; | |
292 PIMAGE_THUNK_DATA import_list,thunk_list; | |
293 char *name = (char *) RVA(pe_imp->Name); | |
294 | |
295 if (characteristics_detection && !pe_imp->u.Characteristics) | |
296 break; | |
297 | |
298 //#warning FIXME: here we should fill imports | |
299 TRACE("Loading imports for %s.dll\n", name); | |
300 | |
301 if (pe_imp->u.OriginalFirstThunk != 0) { | |
302 TRACE("Microsoft style imports used\n"); | |
303 import_list =(PIMAGE_THUNK_DATA) RVA(pe_imp->u.OriginalFirstThunk); | |
304 thunk_list = (PIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk); | |
305 | |
306 while (import_list->u1.Ordinal) { | |
307 if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal)) { | |
308 int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal); | |
309 | |
310 // TRACE("--- Ordinal %s,%d\n", name, ordinal); | |
311 | |
2651
958d10763c34
partially synced with avifile... (TODO: migrate to new registry.c and driver.c)
arpi
parents:
2069
diff
changeset
|
312 thunk_list->u1.Function=LookupExternal(name, ordinal); |
1 | 313 } else { |
314 pe_name = (PIMAGE_IMPORT_BY_NAME)RVA(import_list->u1.AddressOfData); | |
315 // TRACE("--- %s %s.%d\n", pe_name->Name, name, pe_name->Hint); | |
2651
958d10763c34
partially synced with avifile... (TODO: migrate to new registry.c and driver.c)
arpi
parents:
2069
diff
changeset
|
316 thunk_list->u1.Function=LookupExternalByName(name, pe_name->Name); |
1 | 317 } |
318 import_list++; | |
319 thunk_list++; | |
320 } | |
321 } else { | |
322 TRACE("Borland style imports used\n"); | |
323 thunk_list = (PIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk); | |
324 while (thunk_list->u1.Ordinal) { | |
325 if (IMAGE_SNAP_BY_ORDINAL(thunk_list->u1.Ordinal)) { | |
326 | |
327 int ordinal = IMAGE_ORDINAL(thunk_list->u1.Ordinal); | |
328 | |
329 TRACE("--- Ordinal %s.%d\n",name,ordinal); | |
330 thunk_list->u1.Function=LookupExternal( | |
331 name, ordinal); | |
332 } else { | |
333 pe_name=(PIMAGE_IMPORT_BY_NAME) RVA(thunk_list->u1.AddressOfData); | |
334 TRACE("--- %s %s.%d\n", | |
335 pe_name->Name,name,pe_name->Hint); | |
336 thunk_list->u1.Function=LookupExternalByName( | |
337 name, pe_name->Name); | |
338 } | |
339 thunk_list++; | |
340 } | |
341 } | |
342 } | |
343 return 0; | |
344 } | |
345 | |
346 static int calc_vma_size( HMODULE hModule ) | |
347 { | |
348 int i,vma_size = 0; | |
349 IMAGE_SECTION_HEADER *pe_seg = PE_SECTIONS(hModule); | |
350 | |
351 TRACE("Dump of segment table\n"); | |
352 TRACE(" Name VSz Vaddr SzRaw Fileadr *Reloc *Lineum #Reloc #Linum Char\n"); | |
353 for (i = 0; i< PE_HEADER(hModule)->FileHeader.NumberOfSections; i++) | |
354 { | |
355 TRACE("%8s: %4.4lx %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %4.4x %4.4x %8.8lx\n", | |
356 pe_seg->Name, | |
357 pe_seg->Misc.VirtualSize, | |
358 pe_seg->VirtualAddress, | |
359 pe_seg->SizeOfRawData, | |
360 pe_seg->PointerToRawData, | |
361 pe_seg->PointerToRelocations, | |
362 pe_seg->PointerToLinenumbers, | |
363 pe_seg->NumberOfRelocations, | |
364 pe_seg->NumberOfLinenumbers, | |
365 pe_seg->Characteristics); | |
366 vma_size=max(vma_size, pe_seg->VirtualAddress+pe_seg->SizeOfRawData); | |
367 vma_size=max(vma_size, pe_seg->VirtualAddress+pe_seg->Misc.VirtualSize); | |
368 pe_seg++; | |
369 } | |
370 return vma_size; | |
371 } | |
372 | |
373 static void do_relocations( unsigned int load_addr, IMAGE_BASE_RELOCATION *r ) | |
374 { | |
375 int delta = load_addr - PE_HEADER(load_addr)->OptionalHeader.ImageBase; | |
376 int hdelta = (delta >> 16) & 0xFFFF; | |
377 int ldelta = delta & 0xFFFF; | |
378 | |
379 if(delta == 0) | |
380 | |
381 return; | |
382 while(r->VirtualAddress) | |
383 { | |
384 char *page = (char*) RVA(r->VirtualAddress); | |
385 int count = (r->SizeOfBlock - 8)/2; | |
386 int i; | |
387 TRACE_(fixup)("%x relocations for page %lx\n", | |
388 count, r->VirtualAddress); | |
389 | |
390 for(i=0;i<count;i++) | |
391 { | |
392 int offset = r->TypeOffset[i] & 0xFFF; | |
393 int type = r->TypeOffset[i] >> 12; | |
394 // TRACE_(fixup)("patching %x type %x\n", offset, type); | |
395 switch(type) | |
396 { | |
397 case IMAGE_REL_BASED_ABSOLUTE: break; | |
398 case IMAGE_REL_BASED_HIGH: | |
399 *(short*)(page+offset) += hdelta; | |
400 break; | |
401 case IMAGE_REL_BASED_LOW: | |
402 *(short*)(page+offset) += ldelta; | |
403 break; | |
404 case IMAGE_REL_BASED_HIGHLOW: | |
405 *(int*)(page+offset) += delta; | |
406 | |
407 break; | |
408 case IMAGE_REL_BASED_HIGHADJ: | |
409 FIXME("Don't know what to do with IMAGE_REL_BASED_HIGHADJ\n"); | |
410 break; | |
411 case IMAGE_REL_BASED_MIPS_JMPADDR: | |
412 FIXME("Is this a MIPS machine ???\n"); | |
413 break; | |
414 default: | |
415 FIXME("Unknown fixup type\n"); | |
416 break; | |
417 } | |
418 } | |
419 r = (IMAGE_BASE_RELOCATION*)((char*)r + r->SizeOfBlock); | |
420 } | |
421 } | |
422 | |
423 | |
424 | |
425 | |
426 | |
427 /********************************************************************** | |
428 * PE_LoadImage | |
429 * Load one PE format DLL/EXE into memory | |
430 * | |
431 * Unluckily we can't just mmap the sections where we want them, for | |
432 * (at least) Linux does only support offsets which are page-aligned. | |
433 * | |
434 * BUT we have to map the whole image anyway, for Win32 programs sometimes | |
435 * want to access them. (HMODULE32 point to the start of it) | |
436 */ | |
437 HMODULE PE_LoadImage( int handle, LPCSTR filename, WORD *version ) | |
438 { | |
439 HMODULE hModule; | |
440 HANDLE mapping; | |
441 | |
442 IMAGE_NT_HEADERS *nt; | |
443 IMAGE_SECTION_HEADER *pe_sec; | |
444 IMAGE_DATA_DIRECTORY *dir; | |
445 BY_HANDLE_FILE_INFORMATION bhfi; | |
446 int i, rawsize, lowest_va, vma_size, file_size = 0; | |
447 DWORD load_addr = 0, aoep, reloc = 0; | |
448 // struct get_read_fd_request *req = get_req_buffer(); | |
449 int unix_handle = handle; | |
450 int page_size = getpagesize(); | |
451 | |
452 | |
453 // if ( GetFileInformationByHandle( hFile, &bhfi ) ) | |
454 // file_size = bhfi.nFileSizeLow; | |
455 file_size=lseek(handle, 0, SEEK_END); | |
456 lseek(handle, 0, SEEK_SET); | |
457 | |
458 //#warning fix CreateFileMappingA | |
459 mapping = CreateFileMappingA( handle, NULL, PAGE_READONLY | SEC_COMMIT, | |
460 0, 0, NULL ); | |
461 if (!mapping) | |
462 { | |
463 WARN("CreateFileMapping error %ld\n", GetLastError() ); | |
464 return 0; | |
465 } | |
466 // hModule = (HMODULE)MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 ); | |
467 hModule=(HMODULE)mapping; | |
468 // CloseHandle( mapping ); | |
469 if (!hModule) | |
470 { | |
471 WARN("MapViewOfFile error %ld\n", GetLastError() ); | |
472 return 0; | |
473 } | |
474 if ( *(WORD*)hModule !=IMAGE_DOS_SIGNATURE) | |
475 { | |
476 WARN("%s image doesn't have DOS signature, but 0x%04x\n", filename,*(WORD*)hModule); | |
477 goto error; | |
478 } | |
479 | |
480 nt = PE_HEADER( hModule ); | |
481 | |
482 | |
483 if ( nt->Signature != IMAGE_NT_SIGNATURE ) | |
484 { | |
485 WARN("%s image doesn't have PE signature, but 0x%08lx\n", filename, nt->Signature ); | |
486 goto error; | |
487 } | |
488 | |
489 | |
490 if ( nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386 ) | |
491 { | |
492 MESSAGE("Trying to load PE image for unsupported architecture ("); | |
493 switch (nt->FileHeader.Machine) | |
494 { | |
495 case IMAGE_FILE_MACHINE_UNKNOWN: MESSAGE("Unknown"); break; | |
496 case IMAGE_FILE_MACHINE_I860: MESSAGE("I860"); break; | |
497 case IMAGE_FILE_MACHINE_R3000: MESSAGE("R3000"); break; | |
498 case IMAGE_FILE_MACHINE_R4000: MESSAGE("R4000"); break; | |
499 case IMAGE_FILE_MACHINE_R10000: MESSAGE("R10000"); break; | |
500 case IMAGE_FILE_MACHINE_ALPHA: MESSAGE("Alpha"); break; | |
501 case IMAGE_FILE_MACHINE_POWERPC: MESSAGE("PowerPC"); break; | |
502 default: MESSAGE("Unknown-%04x", nt->FileHeader.Machine); break; | |
503 } | |
504 MESSAGE(")\n"); | |
505 goto error; | |
506 } | |
507 | |
508 | |
509 pe_sec = PE_SECTIONS( hModule ); | |
510 rawsize = 0; lowest_va = 0x10000; | |
511 for (i = 0; i < nt->FileHeader.NumberOfSections; i++) | |
512 { | |
513 if (lowest_va > pe_sec[i].VirtualAddress) | |
514 lowest_va = pe_sec[i].VirtualAddress; | |
515 if (pe_sec[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) | |
516 continue; | |
517 if (pe_sec[i].PointerToRawData+pe_sec[i].SizeOfRawData > rawsize) | |
518 rawsize = pe_sec[i].PointerToRawData+pe_sec[i].SizeOfRawData; | |
519 } | |
520 | |
521 | |
522 if ( file_size && file_size < rawsize ) | |
523 { | |
524 ERR("PE module is too small (header: %d, filesize: %d), " | |
525 "probably truncated download?\n", | |
526 rawsize, file_size ); | |
527 goto error; | |
528 } | |
529 | |
530 | |
531 aoep = nt->OptionalHeader.AddressOfEntryPoint; | |
532 if (aoep && (aoep < lowest_va)) | |
533 FIXME("VIRUS WARNING: '%s' has an invalid entrypoint (0x%08lx) " | |
534 "below the first virtual address (0x%08x) " | |
535 "(possibly infected by Tchernobyl/SpaceFiller virus)!\n", | |
536 filename, aoep, lowest_va ); | |
537 | |
538 | |
539 /* FIXME: Hack! While we don't really support shared sections yet, | |
540 * this checks for those special cases where the whole DLL | |
541 * consists only of shared sections and is mapped into the | |
542 * shared address space > 2GB. In this case, we assume that | |
543 * the module got mapped at its base address. Thus we simply | |
544 * check whether the module has actually been mapped there | |
545 * and use it, if so. This is needed to get Win95 USER32.DLL | |
546 * to work (until we support shared sections properly). | |
547 */ | |
548 | |
549 if ( nt->OptionalHeader.ImageBase & 0x80000000 ) | |
550 { | |
551 HMODULE sharedMod = (HMODULE)nt->OptionalHeader.ImageBase; | |
552 IMAGE_NT_HEADERS *sharedNt = (PIMAGE_NT_HEADERS) | |
553 ( (LPBYTE)sharedMod + ((LPBYTE)nt - (LPBYTE)hModule) ); | |
554 | |
555 /* Well, this check is not really comprehensive, | |
556 but should be good enough for now ... */ | |
557 if ( !IsBadReadPtr( (LPBYTE)sharedMod, sizeof(IMAGE_DOS_HEADER) ) | |
558 && memcmp( (LPBYTE)sharedMod, (LPBYTE)hModule, sizeof(IMAGE_DOS_HEADER) ) == 0 | |
559 && !IsBadReadPtr( sharedNt, sizeof(IMAGE_NT_HEADERS) ) | |
560 && memcmp( sharedNt, nt, sizeof(IMAGE_NT_HEADERS) ) == 0 ) | |
561 { | |
562 UnmapViewOfFile( (LPVOID)hModule ); | |
563 return sharedMod; | |
564 } | |
565 } | |
566 | |
2069 | 567 |
1 | 568 |
569 load_addr = nt->OptionalHeader.ImageBase; | |
570 vma_size = calc_vma_size( hModule ); | |
571 | |
572 load_addr = (DWORD)VirtualAlloc( (void*)load_addr, vma_size, | |
573 MEM_RESERVE | MEM_COMMIT, | |
574 PAGE_EXECUTE_READWRITE ); | |
575 if (load_addr == 0) | |
576 { | |
577 | |
578 FIXME("We need to perform base relocations for %s\n", filename); | |
579 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BASERELOC; | |
580 if (dir->Size) | |
581 reloc = dir->VirtualAddress; | |
582 else | |
583 { | |
584 FIXME( "FATAL: Need to relocate %s, but no relocation records present (%s). Try to run that file directly !\n", | |
585 filename, | |
586 (nt->FileHeader.Characteristics&IMAGE_FILE_RELOCS_STRIPPED)? | |
587 "stripped during link" : "unknown reason" ); | |
588 goto error; | |
589 } | |
590 | |
591 /* FIXME: If we need to relocate a system DLL (base > 2GB) we should | |
592 * really make sure that the *new* base address is also > 2GB. | |
593 * Some DLLs really check the MSB of the module handle :-/ | |
594 */ | |
595 if ( nt->OptionalHeader.ImageBase & 0x80000000 ) | |
596 ERR( "Forced to relocate system DLL (base > 2GB). This is not good.\n" ); | |
597 | |
598 load_addr = (DWORD)VirtualAlloc( NULL, vma_size, | |
599 MEM_RESERVE | MEM_COMMIT, | |
600 PAGE_EXECUTE_READWRITE ); | |
601 if (!load_addr) { | |
602 FIXME_(win32)( | |
603 "FATAL: Couldn't load module %s (out of memory, %d needed)!\n", filename, vma_size); | |
604 goto error; | |
605 } | |
606 } | |
607 | |
608 TRACE("Load addr is %lx (base %lx), range %x\n", | |
609 load_addr, nt->OptionalHeader.ImageBase, vma_size ); | |
610 TRACE_(segment)("Loading %s at %lx, range %x\n", | |
611 filename, load_addr, vma_size ); | |
612 | |
613 #if 0 | |
614 | |
615 *(PIMAGE_DOS_HEADER)load_addr = *(PIMAGE_DOS_HEADER)hModule; | |
616 *PE_HEADER( load_addr ) = *nt; | |
617 memcpy( PE_SECTIONS(load_addr), PE_SECTIONS(hModule), | |
618 sizeof(IMAGE_SECTION_HEADER) * nt->FileHeader.NumberOfSections ); | |
619 | |
620 | |
621 memcpy( load_addr, hModule, lowest_fa ); | |
622 #endif | |
623 | |
624 if ((void*)FILE_dommap( handle, (void *)load_addr, 0, nt->OptionalHeader.SizeOfHeaders, | |
625 0, 0, PROT_EXEC | PROT_WRITE | PROT_READ, | |
626 MAP_PRIVATE | MAP_FIXED ) != (void*)load_addr) | |
627 { | |
628 ERR_(win32)( "Critical Error: failed to map PE header to necessary address.\n"); | |
629 goto error; | |
630 } | |
631 | |
632 | |
633 pe_sec = PE_SECTIONS( hModule ); | |
634 for (i = 0; i < nt->FileHeader.NumberOfSections; i++, pe_sec++) | |
635 { | |
636 if (!pe_sec->SizeOfRawData || !pe_sec->PointerToRawData) continue; | |
637 TRACE("%s: mmaping section %s at %p off %lx size %lx/%lx\n", | |
638 filename, pe_sec->Name, (void*)RVA(pe_sec->VirtualAddress), | |
639 pe_sec->PointerToRawData, pe_sec->SizeOfRawData, pe_sec->Misc.VirtualSize ); | |
640 if ((void*)FILE_dommap( unix_handle, (void*)RVA(pe_sec->VirtualAddress), | |
641 0, pe_sec->SizeOfRawData, 0, pe_sec->PointerToRawData, | |
642 PROT_EXEC | PROT_WRITE | PROT_READ, | |
643 MAP_PRIVATE | MAP_FIXED ) != (void*)RVA(pe_sec->VirtualAddress)) | |
644 { | |
645 | |
646 ERR_(win32)( "Critical Error: failed to map PE section to necessary address.\n"); | |
647 goto error; | |
648 } | |
649 if ((pe_sec->SizeOfRawData < pe_sec->Misc.VirtualSize) && | |
650 (pe_sec->SizeOfRawData & (page_size-1))) | |
651 { | |
652 DWORD end = (pe_sec->SizeOfRawData & ~(page_size-1)) + page_size; | |
653 if (end > pe_sec->Misc.VirtualSize) end = pe_sec->Misc.VirtualSize; | |
654 TRACE("clearing %p - %p\n", | |
655 RVA(pe_sec->VirtualAddress) + pe_sec->SizeOfRawData, | |
656 RVA(pe_sec->VirtualAddress) + end ); | |
657 memset( (char*)RVA(pe_sec->VirtualAddress) + pe_sec->SizeOfRawData, 0, | |
658 end - pe_sec->SizeOfRawData ); | |
659 } | |
660 } | |
661 | |
662 | |
663 if ( reloc ) | |
664 do_relocations( load_addr, (IMAGE_BASE_RELOCATION *)RVA(reloc) ); | |
665 | |
666 | |
667 *version = ( (nt->OptionalHeader.MajorSubsystemVersion & 0xff) << 8 ) | |
668 | (nt->OptionalHeader.MinorSubsystemVersion & 0xff); | |
669 | |
670 | |
671 UnmapViewOfFile( (LPVOID)hModule ); | |
672 return (HMODULE)load_addr; | |
673 | |
674 error: | |
675 if (unix_handle != -1) close( unix_handle ); | |
128 | 676 if (load_addr) |
677 VirtualFree( (LPVOID)load_addr, 0, MEM_RELEASE ); | |
1 | 678 UnmapViewOfFile( (LPVOID)hModule ); |
679 return 0; | |
680 } | |
681 | |
682 /********************************************************************** | |
683 * PE_CreateModule | |
684 * | |
685 * Create WINE_MODREF structure for loaded HMODULE32, link it into | |
686 * process modref_list, and fixup all imports. | |
687 * | |
688 * Note: hModule must point to a correctly allocated PE image, | |
689 * with base relocations applied; the 16-bit dummy module | |
690 * associated to hModule must already exist. | |
691 * | |
692 * Note: This routine must always be called in the context of the | |
693 * process that is to own the module to be created. | |
694 */ | |
695 WINE_MODREF *PE_CreateModule( HMODULE hModule, | |
696 LPCSTR filename, DWORD flags, WIN_BOOL builtin ) | |
697 { | |
698 DWORD load_addr = (DWORD)hModule; | |
699 IMAGE_NT_HEADERS *nt = PE_HEADER(hModule); | |
700 IMAGE_DATA_DIRECTORY *dir; | |
701 IMAGE_IMPORT_DESCRIPTOR *pe_import = NULL; | |
702 IMAGE_EXPORT_DIRECTORY *pe_export = NULL; | |
703 IMAGE_RESOURCE_DIRECTORY *pe_resource = NULL; | |
704 WINE_MODREF *wm; | |
705 int result; | |
706 | |
707 | |
708 | |
709 | |
710 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXPORT; | |
711 if (dir->Size) | |
712 pe_export = (PIMAGE_EXPORT_DIRECTORY)RVA(dir->VirtualAddress); | |
713 | |
714 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IMPORT; | |
715 if (dir->Size) | |
716 pe_import = (PIMAGE_IMPORT_DESCRIPTOR)RVA(dir->VirtualAddress); | |
717 | |
718 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_RESOURCE; | |
719 if (dir->Size) | |
720 pe_resource = (PIMAGE_RESOURCE_DIRECTORY)RVA(dir->VirtualAddress); | |
721 | |
722 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXCEPTION; | |
723 if (dir->Size) FIXME("Exception directory ignored\n" ); | |
724 | |
725 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_SECURITY; | |
726 if (dir->Size) FIXME("Security directory ignored\n" ); | |
727 | |
728 | |
729 | |
730 | |
731 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_DEBUG; | |
732 if (dir->Size) TRACE("Debug directory ignored\n" ); | |
733 | |
734 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_COPYRIGHT; | |
735 if (dir->Size) FIXME("Copyright string ignored\n" ); | |
736 | |
737 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_GLOBALPTR; | |
738 if (dir->Size) FIXME("Global Pointer (MIPS) ignored\n" ); | |
739 | |
740 | |
741 | |
742 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG; | |
743 if (dir->Size) FIXME("Load Configuration directory ignored\n" ); | |
744 | |
745 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT; | |
746 if (dir->Size) TRACE("Bound Import directory ignored\n" ); | |
747 | |
748 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IAT; | |
749 if (dir->Size) TRACE("Import Address Table directory ignored\n" ); | |
750 | |
751 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT; | |
752 if (dir->Size) | |
753 { | |
754 TRACE("Delayed import, stub calls LoadLibrary\n" ); | |
755 /* | |
756 * Nothing to do here. | |
757 */ | |
758 | |
759 #ifdef ImgDelayDescr | |
760 /* | |
761 * This code is useful to observe what the heck is going on. | |
762 */ | |
763 { | |
764 ImgDelayDescr *pe_delay = NULL; | |
765 pe_delay = (PImgDelayDescr)RVA(dir->VirtualAddress); | |
766 TRACE_(delayhlp)("pe_delay->grAttrs = %08x\n", pe_delay->grAttrs); | |
767 TRACE_(delayhlp)("pe_delay->szName = %s\n", pe_delay->szName); | |
768 TRACE_(delayhlp)("pe_delay->phmod = %08x\n", pe_delay->phmod); | |
769 TRACE_(delayhlp)("pe_delay->pIAT = %08x\n", pe_delay->pIAT); | |
770 TRACE_(delayhlp)("pe_delay->pINT = %08x\n", pe_delay->pINT); | |
771 TRACE_(delayhlp)("pe_delay->pBoundIAT = %08x\n", pe_delay->pBoundIAT); | |
772 TRACE_(delayhlp)("pe_delay->pUnloadIAT = %08x\n", pe_delay->pUnloadIAT); | |
773 TRACE_(delayhlp)("pe_delay->dwTimeStamp = %08x\n", pe_delay->dwTimeStamp); | |
774 } | |
775 #endif | |
776 } | |
777 | |
778 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR; | |
779 if (dir->Size) FIXME("Unknown directory 14 ignored\n" ); | |
780 | |
781 dir = nt->OptionalHeader.DataDirectory+15; | |
782 if (dir->Size) FIXME("Unknown directory 15 ignored\n" ); | |
783 | |
784 | |
785 | |
786 | |
787 wm = (WINE_MODREF *)HeapAlloc( GetProcessHeap(), | |
788 HEAP_ZERO_MEMORY, sizeof(*wm) ); | |
789 wm->module = hModule; | |
790 | |
791 if ( builtin ) | |
792 wm->flags |= WINE_MODREF_INTERNAL; | |
793 if ( flags & DONT_RESOLVE_DLL_REFERENCES ) | |
794 wm->flags |= WINE_MODREF_DONT_RESOLVE_REFS; | |
795 if ( flags & LOAD_LIBRARY_AS_DATAFILE ) | |
796 wm->flags |= WINE_MODREF_LOAD_AS_DATAFILE; | |
797 | |
798 wm->type = MODULE32_PE; | |
799 wm->binfmt.pe.pe_export = pe_export; | |
800 wm->binfmt.pe.pe_import = pe_import; | |
801 wm->binfmt.pe.pe_resource = pe_resource; | |
802 wm->binfmt.pe.tlsindex = -1; | |
803 | |
804 wm->filename = malloc(strlen(filename)+1); | |
805 strcpy(wm->filename, filename ); | |
806 wm->modname = strrchr( wm->filename, '\\' ); | |
807 if (!wm->modname) wm->modname = wm->filename; | |
808 else wm->modname++; | |
809 | |
810 if ( pe_export ) | |
811 dump_exports( hModule ); | |
812 | |
813 /* Fixup Imports */ | |
814 | |
815 if ( pe_import | |
816 && !( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE ) | |
817 && !( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS ) | |
818 && fixup_imports( wm ) ) | |
819 { | |
820 /* remove entry from modref chain */ | |
821 return NULL; | |
822 } | |
823 | |
824 return wm; | |
825 } | |
826 | |
827 /****************************************************************************** | |
828 * The PE Library Loader frontend. | |
829 * FIXME: handle the flags. | |
830 */ | |
831 WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags) | |
832 { | |
833 HMODULE hModule32; | |
834 WINE_MODREF *wm; | |
835 char filename[256]; | |
836 int hFile; | |
837 WORD version = 0; | |
838 | |
839 | |
840 strncpy(filename, name, sizeof(filename)); | |
841 hFile=open(filename, O_RDONLY); | |
842 if(hFile==-1) | |
843 return NULL; | |
844 | |
845 | |
846 hModule32 = PE_LoadImage( hFile, filename, &version ); | |
847 if (!hModule32) | |
848 { | |
849 SetLastError( ERROR_OUTOFMEMORY ); | |
850 return NULL; | |
851 } | |
852 | |
853 if ( !(wm = PE_CreateModule( hModule32, filename, flags, FALSE )) ) | |
854 { | |
855 ERR( "can't load %s\n", filename ); | |
856 SetLastError( ERROR_OUTOFMEMORY ); | |
857 return NULL; | |
858 } | |
859 close(hFile); | |
2651
958d10763c34
partially synced with avifile... (TODO: migrate to new registry.c and driver.c)
arpi
parents:
2069
diff
changeset
|
860 //printf("^^^^^^^^^^^^^^^^Alloc VM1 %p\n", wm); |
1 | 861 return wm; |
862 } | |
863 | |
864 | |
865 /***************************************************************************** | |
866 * PE_UnloadLibrary | |
867 * | |
868 * Unload the library unmapping the image and freeing the modref structure. | |
869 */ | |
870 void PE_UnloadLibrary(WINE_MODREF *wm) | |
871 { | |
872 TRACE(" unloading %s\n", wm->filename); | |
873 | |
2651
958d10763c34
partially synced with avifile... (TODO: migrate to new registry.c and driver.c)
arpi
parents:
2069
diff
changeset
|
874 if (wm->filename) |
958d10763c34
partially synced with avifile... (TODO: migrate to new registry.c and driver.c)
arpi
parents:
2069
diff
changeset
|
875 free(wm->filename); |
958d10763c34
partially synced with avifile... (TODO: migrate to new registry.c and driver.c)
arpi
parents:
2069
diff
changeset
|
876 if (wm->short_filename) |
958d10763c34
partially synced with avifile... (TODO: migrate to new registry.c and driver.c)
arpi
parents:
2069
diff
changeset
|
877 free(wm->short_filename); |
958d10763c34
partially synced with avifile... (TODO: migrate to new registry.c and driver.c)
arpi
parents:
2069
diff
changeset
|
878 HeapFree( GetProcessHeap(), 0, wm->deps ); |
128 | 879 VirtualFree( (LPVOID)wm->module, 0, MEM_RELEASE ); |
1 | 880 HeapFree( GetProcessHeap(), 0, wm ); |
2651
958d10763c34
partially synced with avifile... (TODO: migrate to new registry.c and driver.c)
arpi
parents:
2069
diff
changeset
|
881 //printf("^^^^^^^^^^^^^^^^Free VM1 %p\n", wm); |
1 | 882 } |
883 | |
884 /***************************************************************************** | |
885 * Load the PE main .EXE. All other loading is done by PE_LoadLibraryExA | |
886 * FIXME: this function should use PE_LoadLibraryExA, but currently can't | |
887 * due to the PROCESS_Create stuff. | |
888 */ | |
889 | |
2069 | 890 |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
128
diff
changeset
|
891 /* |
1411
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
892 * This is a dirty hack. |
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
893 * The win32 DLLs contain an alloca routine, that first probes the soon |
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
894 * to be allocated new memory *below* the current stack pointer in 4KByte |
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
895 * increments. After the mem probing below the current %esp, the stack |
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
896 * pointer is finally decremented to make room for the "alloca"ed memory. |
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
897 * Maybe the probing code is intended to extend the stack on a windows box. |
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
898 * Anyway, the linux kernel does *not* extend the stack by simply accessing |
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
899 * memory below %esp; it segfaults. |
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
900 * The extend_stack_for_dll_alloca() routine just preallocates a big chunk |
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
901 * of memory on the stack, for use by the DLLs alloca routine. |
13375
460281609f28
force compilers not to optimize/inline extend_stack_for_dll_alloca
reimar
parents:
7386
diff
changeset
|
902 * Added the noinline attribute as e.g. gcc 3.2.2 inlines this function |
460281609f28
force compilers not to optimize/inline extend_stack_for_dll_alloca
reimar
parents:
7386
diff
changeset
|
903 * in a way that breaks it. |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
128
diff
changeset
|
904 */ |
13375
460281609f28
force compilers not to optimize/inline extend_stack_for_dll_alloca
reimar
parents:
7386
diff
changeset
|
905 static void __attribute__((noinline)) extend_stack_for_dll_alloca(void) |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
128
diff
changeset
|
906 { |
15566 | 907 #if !defined(__FreeBSD__) && !defined(__DragonFly__) |
13375
460281609f28
force compilers not to optimize/inline extend_stack_for_dll_alloca
reimar
parents:
7386
diff
changeset
|
908 volatile int* mem=alloca(0x20000); |
460281609f28
force compilers not to optimize/inline extend_stack_for_dll_alloca
reimar
parents:
7386
diff
changeset
|
909 *mem=0x1234; |
2069 | 910 #endif |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
128
diff
changeset
|
911 } |
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
128
diff
changeset
|
912 |
1 | 913 /* Called if the library is loaded or freed. |
914 * NOTE: if a thread attaches a DLL, the current thread will only do | |
915 * DLL_PROCESS_ATTACH. Only new created threads do DLL_THREAD_ATTACH | |
916 * (SDK) | |
917 */ | |
918 WIN_BOOL PE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved ) | |
919 { | |
920 WIN_BOOL retv = TRUE; | |
921 assert( wm->type == MODULE32_PE ); | |
922 | |
923 | |
924 if ((PE_HEADER(wm->module)->FileHeader.Characteristics & IMAGE_FILE_DLL) && | |
925 (PE_HEADER(wm->module)->OptionalHeader.AddressOfEntryPoint) | |
926 ) { | |
927 DLLENTRYPROC entry ; | |
928 entry = (void*)PE_FindExportedFunction(wm, "DllMain", 0); | |
929 if(entry==NULL) | |
930 entry = (void*)RVA_PTR( wm->module,OptionalHeader.AddressOfEntryPoint ); | |
931 | |
932 TRACE_(relay)("CallTo32(entryproc=%p,module=%08x,type=%ld,res=%p)\n", | |
933 entry, wm->module, type, lpReserved ); | |
128 | 934 |
935 | |
936 TRACE("Entering DllMain("); | |
1 | 937 switch(type) |
938 { | |
939 case DLL_PROCESS_DETACH: | |
128 | 940 TRACE("DLL_PROCESS_DETACH) "); |
1 | 941 break; |
942 case DLL_PROCESS_ATTACH: | |
128 | 943 TRACE("DLL_PROCESS_ATTACH) "); |
1 | 944 break; |
945 case DLL_THREAD_DETACH: | |
128 | 946 TRACE("DLL_THREAD_DETACH) "); |
1 | 947 break; |
948 case DLL_THREAD_ATTACH: | |
128 | 949 TRACE("DLL_THREAD_ATTACH) "); |
1 | 950 break; |
951 } | |
128 | 952 TRACE("for %s\n", wm->filename); |
1411
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
953 extend_stack_for_dll_alloca(); |
1 | 954 retv = entry( wm->module, type, lpReserved ); |
955 } | |
956 | |
957 return retv; | |
958 } | |
959 | |
960 static LPVOID | |
961 _fixup_address(PIMAGE_OPTIONAL_HEADER opt,int delta,LPVOID addr) { | |
962 if ( ((DWORD)addr>opt->ImageBase) && | |
963 ((DWORD)addr<opt->ImageBase+opt->SizeOfImage) | |
964 ) | |
965 | |
966 return (LPVOID)(((DWORD)addr)+delta); | |
967 else | |
968 | |
969 return addr; | |
970 } |