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