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