Release 971130
[wine/hacks.git] / loader / pe_image.c
blob1485cb6818552e0f5e6bb28bbfdecbe443678ab4
1 /*
2 * Copyright 1994 Eric Youndale & Erik Bos
3 * Copyright 1995 Martin von Löwis
4 * Copyright 1996 Marcus Meissner
6 * based on Eric Youndale's pe-test and:
8 * ftp.microsoft.com:/pub/developer/MSDN/CD8/PEFILE.ZIP
9 * make that:
10 * ftp.microsoft.com:/developr/MSDN/OctCD/PEFILE.ZIP
13 #include <ctype.h>
14 #include <errno.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/mman.h>
22 #include "windows.h"
23 #include "winbase.h"
24 #include "callback.h"
25 #include "file.h"
26 #include "neexe.h"
27 #include "peexe.h"
28 #include "process.h"
29 #include "pe_image.h"
30 #include "module.h"
31 #include "global.h"
32 #include "task.h"
33 #include "ldt.h"
34 #include "stddebug.h"
35 #include "debug.h"
36 #include "xmalloc.h"
38 static void PE_InitDLL(PE_MODREF* modref, DWORD type, LPVOID lpReserved);
40 /* convert PE image VirtualAddress to Real Address */
41 #define RVA(x) ((unsigned int)load_addr+(unsigned int)(x))
43 void dump_exports( HMODULE32 hModule )
45 char *Module;
46 int i, j;
47 u_short *ordinal;
48 u_long *function,*functions;
49 u_char **name;
50 unsigned int load_addr = hModule;
52 DWORD rva_start = PE_HEADER(hModule)->OptionalHeader
53 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
54 DWORD rva_end = rva_start + PE_HEADER(hModule)->OptionalHeader
55 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
56 IMAGE_EXPORT_DIRECTORY *pe_exports = (IMAGE_EXPORT_DIRECTORY*)RVA(rva_start);
58 Module = (char*)RVA(pe_exports->Name);
59 dprintf_win32(stddeb,"\n*******EXPORT DATA*******\nModule name is %s, %ld functions, %ld names\n",
60 Module,
61 pe_exports->NumberOfFunctions,
62 pe_exports->NumberOfNames);
64 ordinal=(u_short*) RVA(pe_exports->AddressOfNameOrdinals);
65 functions=function=(u_long*) RVA(pe_exports->AddressOfFunctions);
66 name=(u_char**) RVA(pe_exports->AddressOfNames);
68 dprintf_win32(stddeb," Ord RVA Addr Name\n" );
69 for (i=0;i<pe_exports->NumberOfFunctions;i++, function++)
71 if (!*function) continue; /* No such function */
72 dprintf_win32( stddeb,"%4ld %08lx %08x",
73 i + pe_exports->Base, *function, RVA(*function) );
74 /* Check if we have a name for it */
75 for (j = 0; j < pe_exports->NumberOfNames; j++)
76 if (ordinal[j] == i)
77 dprintf_win32( stddeb, " %s", (char*)RVA(name[j]) );
78 if ((*function >= rva_start) && (*function <= rva_end))
79 dprintf_win32(stddeb, " (forwarded -> %s)", (char *)RVA(*function));
80 dprintf_win32( stddeb,"\n" );
84 /* Look up the specified function or ordinal in the exportlist:
85 * If it is a string:
86 * - look up the name in the Name list.
87 * - look up the ordinal with that index.
88 * - use the ordinal as offset into the functionlist
89 * If it is a ordinal:
90 * - use ordinal-pe_export->Base as offset into the functionlist
92 FARPROC32 PE_FindExportedFunction( HMODULE32 hModule, LPCSTR funcName)
94 IMAGE_EXPORT_DIRECTORY *exports;
95 unsigned load_addr;
96 u_short * ordinal;
97 u_long * function;
98 u_char ** name, *ename;
99 int i;
100 PDB32 *process=(PDB32*)GetCurrentProcessId();
101 PE_MODREF *pem;
102 u_long rva_start, rva_end, addr;
103 char * forward;
105 pem = process->modref_list;
106 while (pem && (pem->module != hModule))
107 pem=pem->next;
108 if (!pem) {
109 fprintf(stderr,"No MODREF found for PE_MODULE %08x in process %p\n",hModule,process);
110 return NULL;
112 load_addr = hModule;
113 exports = pem->pe_export;
115 if (HIWORD(funcName))
116 dprintf_win32(stddeb,"PE_FindExportedFunction(%s)\n",funcName);
117 else
118 dprintf_win32(stddeb,"PE_FindExportedFunction(%d)\n",(int)funcName);
119 if (!exports) {
120 fprintf(stderr,"Module %08x/MODREF %p doesn't have a exports table.\n",hModule,pem);
121 return NULL;
123 ordinal = (u_short*) RVA(exports->AddressOfNameOrdinals);
124 function= (u_long*) RVA(exports->AddressOfFunctions);
125 name = (u_char **) RVA(exports->AddressOfNames);
126 forward = NULL;
127 rva_start = PE_HEADER(hModule)->OptionalHeader
128 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
129 rva_end = rva_start + PE_HEADER(hModule)->OptionalHeader
130 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
132 if (HIWORD(funcName)) {
133 for(i=0; i<exports->NumberOfNames; i++) {
134 ename=(char*)RVA(*name);
135 if(!strcmp(ename,funcName))
137 addr = function[*ordinal];
138 if ((addr < rva_start) || (addr >= rva_end))
139 return (FARPROC32)RVA(addr);
140 forward = (char *)RVA(addr);
141 break;
143 ordinal++;
144 name++;
146 } else {
147 if (LOWORD(funcName)-exports->Base > exports->NumberOfFunctions) {
148 dprintf_win32(stddeb," ordinal %d out of range!\n",
149 LOWORD(funcName));
150 return NULL;
152 addr = function[(int)funcName-exports->Base];
153 if ((addr < rva_start) || (addr >= rva_end))
154 return (FARPROC32)RVA(addr);
155 forward = (char *)RVA(addr);
157 if (forward)
159 char module[256];
160 char *end = strchr(forward, '.');
161 if (!end) return NULL;
162 strncpy(module, forward, (end - forward));
163 module[end-forward] = 0;
164 return GetProcAddress32(MODULE_FindModule(module), end + 1);
166 return NULL;
169 void
170 fixup_imports (PDB32 *process,PE_MODREF *pem)
172 IMAGE_IMPORT_DESCRIPTOR *pe_imp;
173 int fixup_failed = 0;
174 unsigned int load_addr = pem->module;
175 int i;
176 char *modname;
178 if (pem->pe_export)
179 modname = (char*) RVA(pem->pe_export->Name);
180 else
181 modname = "<unknown>";
183 /* OK, now dump the import list */
184 dprintf_win32 (stddeb, "\nDumping imports list\n");
186 /* first, count the number of imported non-internal modules */
187 pe_imp = pem->pe_import;
188 if (!pe_imp)
189 fprintf(stderr,"no import directory????\n");
191 /* FIXME: should terminate on 0 Characteristics */
192 for (i = 0; pe_imp->Name; pe_imp++)
193 i++;
195 /* load the imported modules. They are automatically
196 * added to the modref list of the process.
199 /* FIXME: should terminate on 0 Characteristics */
200 for (i = 0, pe_imp = pem->pe_import; pe_imp->Name; pe_imp++) {
201 HMODULE32 res;
202 PE_MODREF *xpem,**ypem;
205 char *name = (char *) RVA(pe_imp->Name);
207 /* don't use MODULE_Load, Win32 creates new task differently */
208 res = PE_LoadLibraryEx32A( name, 0, 0 );
209 if (res <= (HMODULE32) 32) {
210 char *p, buffer[256];
212 /* Try with prepending the path of the current module */
213 GetModuleFileName32A( pem->module, buffer, sizeof (buffer));
214 if (!(p = strrchr (buffer, '\\')))
215 p = buffer;
216 strcpy (p + 1, name);
217 res = PE_LoadLibraryEx32A( buffer, 0, 0 );
219 if (res <= (HMODULE32) 32) {
220 fprintf (stderr, "Module %s not found\n", name);
221 exit (0);
223 res = MODULE_HANDLEtoHMODULE32(res);
224 xpem = pem->next;
225 while (xpem) {
226 if (xpem->module == res)
227 break;
228 xpem = xpem->next;
230 if (xpem) {
231 /* it has been loaded *BEFORE* us, so we have to init
232 * it before us. we just swap the two modules which should
233 * work.
235 /* unlink xpem from chain */
236 ypem = &(process->modref_list);
237 while (*ypem) {
238 if ((*ypem)==xpem)
239 break;
240 ypem = &((*ypem)->next);
242 *ypem = xpem->next;
244 /* link it directly before pem */
245 ypem = &(process->modref_list);
246 while (*ypem) {
247 if ((*ypem)==pem)
248 break;
249 ypem = &((*ypem)->next);
251 *ypem = xpem;
252 xpem->next = pem;
255 i++;
257 pe_imp = pem->pe_import;
258 while (pe_imp->Name) {
259 char *Module;
260 IMAGE_IMPORT_BY_NAME *pe_name;
261 LPIMAGE_THUNK_DATA import_list,thunk_list;
263 Module = (char *) RVA(pe_imp->Name);
264 dprintf_win32 (stddeb, "%s\n", Module);
266 /* FIXME: forwarder entries ... */
268 if (pe_imp->u.OriginalFirstThunk != 0) { /* original MS style */
269 dprintf_win32 (stddeb, "Microsoft style imports used\n");
270 import_list =(LPIMAGE_THUNK_DATA) RVA(pe_imp->u.OriginalFirstThunk);
271 thunk_list = (LPIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk);
273 while (import_list->u1.Ordinal) {
274 if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal)) {
275 int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);
277 dprintf_win32 (stddeb, "--- Ordinal %s,%d\n", Module, ordinal);
278 thunk_list->u1.Function=(LPDWORD)GetProcAddress32(MODULE_FindModule(Module),(LPCSTR)ordinal);
279 if (!thunk_list->u1.Function) {
280 fprintf(stderr,"No implementation for %s.%d, setting to NULL\n",
281 Module, ordinal);
282 /* fixup_failed=1; */
284 } else { /* import by name */
285 pe_name = (LPIMAGE_IMPORT_BY_NAME)RVA(import_list->u1.AddressOfData);
286 dprintf_win32 (stddeb, "--- %s %s.%d\n", pe_name->Name, Module, pe_name->Hint);
287 thunk_list->u1.Function=(LPDWORD)GetProcAddress32(
288 MODULE_FindModule (Module),
289 pe_name->Name);
290 if (!thunk_list->u1.Function) {
291 fprintf(stderr,"No implementation for %s.%d(%s), setting to NULL\n",
292 Module,pe_name->Hint,pe_name->Name);
293 /* fixup_failed=1; */
296 import_list++;
297 thunk_list++;
299 } else { /* Borland style */
300 dprintf_win32 (stddeb, "Borland style imports used\n");
301 thunk_list = (LPIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk);
302 while (thunk_list->u1.Ordinal) {
303 if (IMAGE_SNAP_BY_ORDINAL(thunk_list->u1.Ordinal)) {
304 /* not sure about this branch, but it seems to work */
305 int ordinal = IMAGE_ORDINAL(thunk_list->u1.Ordinal);
307 dprintf_win32(stddeb,"--- Ordinal %s.%d\n",Module,ordinal);
308 thunk_list->u1.Function=(LPDWORD)GetProcAddress32(MODULE_FindModule(Module),
309 (LPCSTR) ordinal);
310 if (!thunk_list->u1.Function) {
311 fprintf(stderr, "No implementation for %s.%d, setting to NULL\n",
312 Module,ordinal);
313 /* fixup_failed=1; */
315 } else {
316 pe_name=(LPIMAGE_IMPORT_BY_NAME) RVA(thunk_list->u1.AddressOfData);
317 dprintf_win32(stddeb,"--- %s %s.%d\n",
318 pe_name->Name,Module,pe_name->Hint);
319 thunk_list->u1.Function=(LPDWORD)GetProcAddress32(MODULE_FindModule(Module),pe_name->Name);
320 if (!thunk_list->u1.Function) {
321 fprintf(stderr, "No implementation for %s.%d, setting to NULL\n",
322 Module, pe_name->Hint);
323 /* fixup_failed=1; */
326 thunk_list++;
329 pe_imp++;
331 if (fixup_failed) exit(1);
334 static int calc_vma_size( HMODULE32 hModule )
336 int i,vma_size = 0;
337 IMAGE_SECTION_HEADER *pe_seg = PE_SECTIONS(hModule);
339 dprintf_win32(stddeb, "Dump of segment table\n");
340 dprintf_win32(stddeb, " Name VSz Vaddr SzRaw Fileadr *Reloc *Lineum #Reloc #Linum Char\n");
341 for (i = 0; i< PE_HEADER(hModule)->FileHeader.NumberOfSections; i++)
343 dprintf_win32(stddeb, "%8s: %4.4lx %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %4.4x %4.4x %8.8lx\n",
344 pe_seg->Name,
345 pe_seg->Misc.VirtualSize,
346 pe_seg->VirtualAddress,
347 pe_seg->SizeOfRawData,
348 pe_seg->PointerToRawData,
349 pe_seg->PointerToRelocations,
350 pe_seg->PointerToLinenumbers,
351 pe_seg->NumberOfRelocations,
352 pe_seg->NumberOfLinenumbers,
353 pe_seg->Characteristics);
354 vma_size = MAX(vma_size, pe_seg->VirtualAddress+pe_seg->SizeOfRawData);
355 pe_seg++;
357 return vma_size;
360 static void do_relocations(PE_MODREF *pem)
362 int delta = pem->module - PE_HEADER(pem->module)->OptionalHeader.ImageBase;
363 unsigned int load_addr= pem->module;
364 IMAGE_BASE_RELOCATION *r = pem->pe_reloc;
365 int hdelta = (delta >> 16) & 0xFFFF;
366 int ldelta = delta & 0xFFFF;
368 /* int reloc_size = */
370 if(delta == 0)
371 /* Nothing to do */
372 return;
373 while(r->VirtualAddress)
375 char *page = (char*) RVA(r->VirtualAddress);
376 int count = (r->SizeOfBlock - 8)/2;
377 int i;
378 dprintf_fixup(stddeb, "%x relocations for page %lx\n",
379 count, r->VirtualAddress);
380 /* patching in reverse order */
381 for(i=0;i<count;i++)
383 int offset = r->TypeOffset[i] & 0xFFF;
384 int type = r->TypeOffset[i] >> 12;
385 dprintf_fixup(stddeb,"patching %x type %x\n", offset, type);
386 switch(type)
388 case IMAGE_REL_BASED_ABSOLUTE: break;
389 case IMAGE_REL_BASED_HIGH:
390 *(short*)(page+offset) += hdelta;
391 break;
392 case IMAGE_REL_BASED_LOW:
393 *(short*)(page+offset) += ldelta;
394 break;
395 case IMAGE_REL_BASED_HIGHLOW:
396 #if 1
397 *(int*)(page+offset) += delta;
398 #else
399 { int h=*(unsigned short*)(page+offset);
400 int l=r->TypeOffset[++i];
401 *(unsigned int*)(page + offset) = (h<<16) + l + delta;
403 #endif
404 break;
405 case IMAGE_REL_BASED_HIGHADJ:
406 fprintf(stderr, "Don't know what to do with IMAGE_REL_BASED_HIGHADJ\n");
407 break;
408 case IMAGE_REL_BASED_MIPS_JMPADDR:
409 fprintf(stderr, "Is this a MIPS machine ???\n");
410 break;
411 default:
412 fprintf(stderr, "Unknown fixup type\n");
413 break;
416 r = (IMAGE_BASE_RELOCATION*)((char*)r + r->SizeOfBlock);
424 /**********************************************************************
425 * PE_LoadImage
426 * Load one PE format DLL/EXE into memory
428 * Unluckily we can't just mmap the sections where we want them, for
429 * (at least) Linux does only support offsets which are page-aligned.
431 * BUT we have to map the whole image anyway, for Win32 programs sometimes
432 * want to access them. (HMODULE32 point to the start of it)
434 static HMODULE32 PE_LoadImage( HFILE32 hFile )
436 HMODULE32 hModule;
437 HANDLE32 mapping;
439 /* map the PE file somewhere */
440 mapping = CreateFileMapping32A( hFile, NULL, PAGE_READONLY | SEC_COMMIT,
441 0, 0, NULL );
442 if (!mapping)
444 fprintf( stderr, "PE_LoadImage: CreateFileMapping error %ld\n",
445 GetLastError() );
446 return 0;
448 hModule = (HMODULE32)MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
449 CloseHandle( mapping );
450 if (!hModule)
452 fprintf( stderr, "PE_LoadImage: MapViewOfFile error %ld\n",
453 GetLastError() );
454 return 0;
457 if (PE_HEADER(hModule)->Signature != IMAGE_NT_SIGNATURE)
459 fprintf(stderr,"image doesn't have PE signature, but 0x%08lx\n",
460 PE_HEADER(hModule)->Signature );
461 goto error;
464 if (PE_HEADER(hModule)->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
466 fprintf(stderr,"trying to load PE image for unsupported architecture (");
467 switch (PE_HEADER(hModule)->FileHeader.Machine)
469 case IMAGE_FILE_MACHINE_UNKNOWN: fprintf(stderr,"Unknown"); break;
470 case IMAGE_FILE_MACHINE_I860: fprintf(stderr,"I860"); break;
471 case IMAGE_FILE_MACHINE_R3000: fprintf(stderr,"R3000"); break;
472 case IMAGE_FILE_MACHINE_R4000: fprintf(stderr,"R4000"); break;
473 case IMAGE_FILE_MACHINE_R10000: fprintf(stderr,"R10000"); break;
474 case IMAGE_FILE_MACHINE_ALPHA: fprintf(stderr,"Alpha"); break;
475 case IMAGE_FILE_MACHINE_POWERPC: fprintf(stderr,"PowerPC"); break;
476 default: fprintf(stderr,"Unknown-%04x",
477 PE_HEADER(hModule)->FileHeader.Machine); break;
479 fprintf(stderr,")\n");
480 goto error;
482 return hModule;
484 error:
485 UnmapViewOfFile( (LPVOID)hModule );
486 return 0;
489 /**********************************************************************
490 * This maps a loaded PE dll into the address space of the specified process.
492 static HMODULE32 PE_MapImage( HMODULE32 hModule, PDB32 *process,
493 OFSTRUCT *ofs, DWORD flags )
495 PE_MODREF *pem;
496 int i, result;
497 DWORD load_addr;
498 IMAGE_DATA_DIRECTORY dir;
499 char *modname;
500 int vma_size;
502 IMAGE_SECTION_HEADER *pe_seg;
503 IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *)hModule;
504 IMAGE_NT_HEADERS *nt_header = PE_HEADER(hModule);
506 pem = (PE_MODREF*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
507 sizeof(*pem));
508 /* NOTE: fixup_imports takes care of the correct order */
509 pem->next = process->modref_list;
510 process->modref_list = pem;
512 if (!(nt_header->FileHeader.Characteristics & IMAGE_FILE_DLL))
514 if (process->exe_modref)
515 fprintf(stderr,"overwriting old exe_modref... arrgh\n");
516 process->exe_modref = pem;
519 load_addr = nt_header->OptionalHeader.ImageBase;
520 vma_size = calc_vma_size( hModule );
521 dprintf_win32(stddeb, "Load addr is %lx\n",load_addr);
522 load_addr = (DWORD)VirtualAlloc( (void*)load_addr, vma_size,
523 MEM_RESERVE | MEM_COMMIT,
524 PAGE_EXECUTE_READWRITE );
525 pem->module = (HMODULE32)load_addr;
527 dprintf_win32(stddeb, "Load addr is really %lx, range %x\n",
528 load_addr, vma_size);
530 /* Store the NT header at the load addr
531 * (FIXME: should really use mmap)
533 *(IMAGE_DOS_HEADER *)load_addr = *dos_header;
534 *(IMAGE_NT_HEADERS *)(load_addr + dos_header->e_lfanew) = *nt_header;
536 pe_seg = PE_SECTIONS(hModule);
537 for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++, pe_seg++)
539 /* memcpy only non-BSS segments */
540 /* FIXME: this should be done by mmap(..MAP_PRIVATE|MAP_FIXED..)
541 * but it is not possible for (at least) Linux needs
542 * a page-aligned offset.
544 if(!(pe_seg->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA))
545 memcpy((char*)RVA(pe_seg->VirtualAddress),
546 (char*)(hModule + pe_seg->PointerToRawData),
547 pe_seg->SizeOfRawData
550 result = RVA (pe_seg->VirtualAddress);
551 #if 1
552 /* not needed, memory is zero */
553 if(strcmp(pe_seg->Name, ".bss") == 0)
554 memset((void *)result, 0,
555 pe_seg->Misc.VirtualSize ?
556 pe_seg->Misc.VirtualSize :
557 pe_seg->SizeOfRawData);
558 #endif
560 if(strcmp(pe_seg->Name, ".idata") == 0)
561 pem->pe_import = (LPIMAGE_IMPORT_DESCRIPTOR) result;
563 if(strcmp(pe_seg->Name, ".edata") == 0)
564 pem->pe_export = (LPIMAGE_EXPORT_DIRECTORY) result;
566 if(strcmp(pe_seg->Name, ".rsrc") == 0)
567 pem->pe_resource = (LPIMAGE_RESOURCE_DIRECTORY) result;
569 if(strcmp(pe_seg->Name, ".reloc") == 0)
570 pem->pe_reloc = (LPIMAGE_BASE_RELOCATION) result;
573 /* There is word that the actual loader does not care about the
574 section names, and only goes for the DataDirectory */
575 dir=nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
576 if(dir.Size)
578 if(pem->pe_export && (int)pem->pe_export!=RVA(dir.VirtualAddress))
579 fprintf(stderr,"wrong export directory??\n");
580 /* always trust the directory */
581 pem->pe_export = (LPIMAGE_EXPORT_DIRECTORY) RVA(dir.VirtualAddress);
584 dir=nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
585 if(dir.Size)
588 if(pem->pe_import && (int)pem->pe_import!=RVA(dir.VirtualAddress))
589 fprintf(stderr,"wrong import directory??\n");
591 pem->pe_import = (LPIMAGE_IMPORT_DESCRIPTOR) RVA(dir.VirtualAddress);
594 dir=nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
595 if(dir.Size)
597 if(pem->pe_resource && (int)pem->pe_resource!=RVA(dir.VirtualAddress))
598 fprintf(stderr,"wrong resource directory??\n");
599 pem->pe_resource = (LPIMAGE_RESOURCE_DIRECTORY) RVA(dir.VirtualAddress);
602 if(nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size)
603 dprintf_win32(stdnimp,"Exception directory ignored\n");
605 if(nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size)
606 dprintf_win32(stdnimp,"Security directory ignored\n");
610 dir=nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
611 if(dir.Size)
613 if(pem->pe_reloc && (int)pem->pe_reloc!= RVA(dir.VirtualAddress))
614 fprintf(stderr,"wrong relocation list??\n");
615 pem->pe_reloc = (void *) RVA(dir.VirtualAddress);
618 if(nt_header->OptionalHeader.DataDirectory
619 [IMAGE_DIRECTORY_ENTRY_COPYRIGHT].Size)
620 dprintf_win32(stdnimp,"Copyright string ignored\n");
622 if(nt_header->OptionalHeader.DataDirectory
623 [IMAGE_DIRECTORY_ENTRY_GLOBALPTR].Size)
624 dprintf_win32(stdnimp,"Global Pointer (MIPS) ignored\n");
626 if(nt_header->OptionalHeader.DataDirectory
627 [IMAGE_DIRECTORY_ENTRY_TLS].Size)
628 fprintf(stdnimp,"Thread local storage ignored\n");
630 if(nt_header->OptionalHeader.DataDirectory
631 [IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size)
632 dprintf_win32(stdnimp,"Load Configuration directory ignored\n");
634 if(nt_header->OptionalHeader.DataDirectory
635 [IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size)
636 dprintf_win32(stdnimp,"Bound Import directory ignored\n");
638 if(nt_header->OptionalHeader.DataDirectory
639 [IMAGE_DIRECTORY_ENTRY_IAT].Size)
640 dprintf_win32(stdnimp,"Import Address Table directory ignored\n");
641 if(nt_header->OptionalHeader.DataDirectory[13].Size)
642 dprintf_win32(stdnimp,"Unknown directory 13 ignored\n");
643 if(nt_header->OptionalHeader.DataDirectory[14].Size)
644 dprintf_win32(stdnimp,"Unknown directory 14 ignored\n");
645 if(nt_header->OptionalHeader.DataDirectory[15].Size)
646 dprintf_win32(stdnimp,"Unknown directory 15 ignored\n");
648 if(pem->pe_reloc) do_relocations(pem);
649 if(pem->pe_export) dump_exports(pem->module);
650 if(pem->pe_import) fixup_imports(process,pem);
652 if (pem->pe_export)
653 modname = (char*)RVA(pem->pe_export->Name);
654 else {
655 char *s;
656 modname = s = ofs->szPathName;
657 while ((s=strchr(modname,'\\')))
658 modname = s+1;
659 if ((s=strchr(modname,'.')))
660 *s='\0';
663 /* Now that we got everything at the right address,
664 * we can unmap the previous module */
665 UnmapViewOfFile( (LPVOID)hModule );
666 return (HMODULE32)load_addr;
669 HINSTANCE16 MODULE_CreateInstance(HMODULE16 hModule,LOADPARAMS *params);
671 /******************************************************************************
672 * The PE Library Loader frontend.
673 * FIXME: handle the flags.
675 HMODULE32 PE_LoadLibraryEx32A (LPCSTR name, HFILE32 hFile, DWORD flags) {
676 OFSTRUCT ofs;
677 HMODULE32 hModule;
678 NE_MODULE *pModule;
679 PE_MODREF *pem;
681 if ((hModule = MODULE_FindModule( name ))) {
682 /* the .DLL is either loaded or internal */
683 hModule = MODULE_HANDLEtoHMODULE32(hModule);
684 if (!HIWORD(hModule)) /* internal (or bad) */
685 return hModule;
686 /* check if this module is already mapped */
687 pem = ((PDB32*)GetCurrentProcessId())->modref_list;
688 while (pem) {
689 if (pem->module == hModule) return hModule;
690 pem = pem->next;
692 pModule = MODULE_GetPtr(hModule);
693 } else {
695 /* try to load builtin, enabled modules first */
696 if ((hModule = BUILTIN_LoadModule( name, FALSE )))
697 return MODULE_HANDLEtoHMODULE32( hModule );
699 /* try to open the specified file */
700 if (HFILE_ERROR32==(hFile=OpenFile32(name,&ofs,OF_READ))) {
701 /* Now try the built-in even if disabled */
702 if ((hModule = BUILTIN_LoadModule( name, TRUE ))) {
703 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
704 return MODULE_HANDLEtoHMODULE32( hModule );
706 return 1;
708 if ((hModule = MODULE_CreateDummyModule( &ofs )) < 32) {
709 _lclose32(hFile);
710 return hModule;
712 pModule = (NE_MODULE *)GlobalLock16( hModule );
713 pModule->flags = NE_FFLAGS_WIN32;
714 pModule->module32 = PE_LoadImage( hFile );
715 CloseHandle( hFile );
716 if (pModule->module32 < 32) return 21;
718 /* recurse */
719 pModule->module32 = PE_MapImage( pModule->module32,
720 (PDB32*)GetCurrentProcessId(),
721 &ofs,flags);
722 return pModule->module32;
725 /*****************************************************************************
726 * Load the PE main .EXE. All other loading is done by PE_LoadLibraryEx32A
727 * FIXME: this function should use PE_LoadLibraryEx32A, but currently can't
728 * due to the TASK_CreateTask stuff.
730 HINSTANCE16 PE_LoadModule( HFILE32 hFile, OFSTRUCT *ofs, LOADPARAMS* params )
732 HMODULE16 hModule16;
733 HMODULE32 hModule32;
734 HINSTANCE16 hInstance;
735 NE_MODULE *pModule;
737 if ((hModule16 = MODULE_CreateDummyModule( ofs )) < 32) return hModule16;
738 pModule = (NE_MODULE *)GlobalLock16( hModule16 );
739 pModule->flags = NE_FFLAGS_WIN32;
741 pModule->module32 = hModule32 = PE_LoadImage( hFile );
742 CloseHandle( hFile );
743 if (hModule32 < 32) return 21;
745 hInstance = MODULE_CreateInstance( hModule16, params );
746 if (!(PE_HEADER(hModule32)->FileHeader.Characteristics & IMAGE_FILE_DLL))
748 TASK_CreateTask( hModule16, hInstance, 0,
749 params->hEnvironment,
750 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
751 *((WORD*)PTR_SEG_TO_LIN(params->showCmd) + 1) );
753 pModule->module32 = PE_MapImage( hModule32, (PDB32*)GetCurrentProcessId(),
754 ofs, 0 );
755 return hInstance;
758 int PE_UnloadImage( HMODULE32 hModule )
760 printf("PEunloadImage() called!\n");
761 /* free resources, image, unmap */
762 return 1;
765 /* Called if the library is loaded or freed.
766 * NOTE: if a thread attaches a DLL, the current thread will only do
767 * DLL_PROCESS_ATTACH. Only new created threads do DLL_THREAD_ATTACH
768 * (SDK)
770 static void PE_InitDLL(PE_MODREF *pem, DWORD type,LPVOID lpReserved)
772 if (type==DLL_PROCESS_ATTACH)
773 pem->flags |= PE_MODREF_PROCESS_ATTACHED;
775 /* DLL_ATTACH_PROCESS:
776 * lpreserved is NULL for dynamic loads, not-NULL for static loads
777 * DLL_DETACH_PROCESS:
778 * lpreserved is NULL if called by FreeLibrary, not-NULL otherwise
779 * the SDK doesn't mention anything for DLL_THREAD_*
782 /* Is this a library? And has it got an entrypoint? */
783 if ((PE_HEADER(pem->module)->FileHeader.Characteristics & IMAGE_FILE_DLL) &&
784 (PE_HEADER(pem->module)->OptionalHeader.AddressOfEntryPoint)
786 FARPROC32 entry = (FARPROC32)RVA_PTR( pem->module,
787 OptionalHeader.AddressOfEntryPoint );
788 dprintf_relay( stddeb, "CallTo32(entryproc=%p,module=%d,type=%ld,res=%p)\n",
789 entry, pem->module, type, lpReserved );
790 entry( pem->module, type, lpReserved );
794 /* Call the DLLentry function of all dlls used by that process.
795 * (NOTE: this may recursively call this function (if a library calls
796 * LoadLibrary) ... but it won't matter)
798 void PE_InitializeDLLs(PDB32 *process,DWORD type,LPVOID lpReserved) {
799 PE_MODREF *pem;
801 pem = process->modref_list;
802 while (pem) {
803 if (pem->flags & PE_MODREF_NO_DLL_CALLS) {
804 pem = pem->next;
805 continue;
807 if (type==DLL_PROCESS_ATTACH) {
808 if (pem->flags & PE_MODREF_PROCESS_ATTACHED) {
809 pem = pem->next;
810 continue;
813 PE_InitDLL( pem, type, lpReserved );
814 pem = pem->next;
818 void PE_InitTls(PDB32 *pdb)
820 /* FIXME: tls callbacks ??? */
821 PE_MODREF *pem;
822 IMAGE_NT_HEADERS *peh;
823 DWORD size,datasize,index;
824 LPVOID mem;
825 LPIMAGE_TLS_DIRECTORY pdir;
827 pem = pdb->modref_list;
828 while (pem) {
829 peh = PE_HEADER(pem->module);
830 if (!peh->OptionalHeader.DataDirectory[IMAGE_FILE_THREAD_LOCAL_STORAGE].VirtualAddress) {
831 pem = pem->next;
832 continue;
834 pdir = (LPVOID)(pem->module + peh->OptionalHeader.
835 DataDirectory[IMAGE_FILE_THREAD_LOCAL_STORAGE].VirtualAddress);
836 index = TlsAlloc();
837 datasize= pdir->EndAddressOfRawData-pdir->StartAddressOfRawData;
838 size = datasize + pdir->SizeOfZeroFill;
839 mem=VirtualAlloc(0,size,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE);
840 memcpy(mem,(LPVOID) pdir->StartAddressOfRawData, datasize);
841 TlsSetValue(index,mem);
842 *(pdir->AddressOfIndex)=index;
843 pem=pem->next;
847 /****************************************************************************
848 * DisableThreadLibraryCalls (KERNEL32.74)
849 * Don't call DllEntryPoint for DLL_THREAD_{ATTACH,DETACH} if set.
851 BOOL32 WINAPI DisableThreadLibraryCalls(HMODULE32 hModule)
853 PDB32 *process = (PDB32*)GetCurrentProcessId();
854 PE_MODREF *pem = process->modref_list;
856 while (pem) {
857 if (pem->module == hModule)
858 pem->flags|=PE_MODREF_NO_DLL_CALLS;
859 pem = pem->next;
861 return TRUE;