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