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