Fixed typo.
[wine] / loader / pe_image.c
1 /* 
2  *  Copyright   1994    Eric Youndale & Erik Bos
3  *  Copyright   1995    Martin von Löwis
4  *  Copyright   1996-98 Marcus Meissner
5  *
6  *      based on Eric Youndale's pe-test and:
7  *
8  *      ftp.microsoft.com:/pub/developer/MSDN/CD8/PEFILE.ZIP
9  * make that:
10  *      ftp.microsoft.com:/developr/MSDN/OctCD/PEFILE.ZIP
11  */
12 /* Notes:
13  * Before you start changing something in this file be aware of the following:
14  *
15  * - There are several functions called recursively. In a very subtle and 
16  *   obscure way. DLLs can reference each other recursively etc.
17  * - If you want to enhance, speed up or clean up something in here, think
18  *   twice WHY it is implemented in that strange way. There is usually a reason.
19  *   Though sometimes it might just be lazyness ;)
20  * - In PE_MapImage, right before fixup_imports() all external and internal 
21  *   state MUST be correct since this function can be called with the SAME image
22  *   AGAIN. (Thats recursion for you.) That means MODREF.module and
23  *   NE_MODULE.module32.
24  * - No, you (usually) cannot use Linux mmap() to mmap() the images directly.
25  *
26  *   The problem is, that there is not direct 1:1 mapping from a diskimage and
27  *   a memoryimage. The headers at the start are mapped linear, but the sections
28  *   are not. For x86 the sections are 512 byte aligned in file and 4096 byte
29  *   aligned in memory. Linux likes them 4096 byte aligned in memory (due to
30  *   x86 pagesize, this cannot be fixed without a rather large kernel rewrite)
31  *   and 'blocksize' file-aligned (offsets). Since we have 512/1024/2048 (CDROM)
32  *   and other byte blocksizes, we can't do this. However, this could be less
33  *   difficult to support... (See mm/filemap.c).
34  */
35
36 #include <errno.h>
37 #include <assert.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <sys/mman.h>
44 #include "windef.h"
45 #include "winbase.h"
46 #include "winerror.h"
47 #include "callback.h"
48 #include "file.h"
49 #include "heap.h"
50 #include "neexe.h"
51 #include "peexe.h"
52 #include "process.h"
53 #include "thread.h"
54 #include "pe_image.h"
55 #include "module.h"
56 #include "global.h"
57 #include "task.h"
58 #include "snoop.h"
59 #include "debug.h"
60
61
62 /* convert PE image VirtualAddress to Real Address */
63 #define RVA(x) ((unsigned int)load_addr+(unsigned int)(x))
64
65 #define AdjustPtr(ptr,delta) ((char *)(ptr) + (delta))
66
67 void dump_exports( HMODULE hModule )
68
69   char          *Module;
70   int           i, j;
71   u_short       *ordinal;
72   u_long        *function,*functions;
73   u_char        **name;
74   unsigned int load_addr = hModule;
75
76   DWORD rva_start = PE_HEADER(hModule)->OptionalHeader
77                    .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
78   DWORD rva_end = rva_start + PE_HEADER(hModule)->OptionalHeader
79                    .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
80   IMAGE_EXPORT_DIRECTORY *pe_exports = (IMAGE_EXPORT_DIRECTORY*)RVA(rva_start);
81
82   Module = (char*)RVA(pe_exports->Name);
83   TRACE(win32,"*******EXPORT DATA*******\n");
84   TRACE(win32,"Module name is %s, %ld functions, %ld names\n", 
85                Module, pe_exports->NumberOfFunctions, pe_exports->NumberOfNames);
86
87   ordinal=(u_short*) RVA(pe_exports->AddressOfNameOrdinals);
88   functions=function=(u_long*) RVA(pe_exports->AddressOfFunctions);
89   name=(u_char**) RVA(pe_exports->AddressOfNames);
90
91   TRACE(win32," Ord    RVA     Addr   Name\n" );
92   for (i=0;i<pe_exports->NumberOfFunctions;i++, function++)
93   {
94       if (!*function) continue;  /* No such function */
95       if (TRACE_ON(win32)){
96         dbg_decl_str(win32, 1024);
97
98         dsprintf(win32,"%4ld %08lx %08x",
99                  i + pe_exports->Base, *function, RVA(*function) );
100         /* Check if we have a name for it */
101         for (j = 0; j < pe_exports->NumberOfNames; j++)
102           if (ordinal[j] == i)
103             dsprintf(win32, "  %s", (char*)RVA(name[j]) );
104         if ((*function >= rva_start) && (*function <= rva_end))
105           dsprintf(win32, " (forwarded -> %s)", (char *)RVA(*function));
106         TRACE(win32,"%s\n", dbg_str(win32));
107       }
108   }
109 }
110
111 /* Look up the specified function or ordinal in the exportlist:
112  * If it is a string:
113  *      - look up the name in the Name list. 
114  *      - look up the ordinal with that index.
115  *      - use the ordinal as offset into the functionlist
116  * If it is a ordinal:
117  *      - use ordinal-pe_export->Base as offset into the functionlist
118  */
119 FARPROC PE_FindExportedFunction( 
120         WINE_MODREF *wm,        /* [in] WINE modreference */
121         LPCSTR funcName,        /* [in] function name */
122         BOOL snoop )
123 {
124         u_short                         * ordinal;
125         u_long                          * function;
126         u_char                          ** name, *ename;
127         int                             i;
128         PE_MODREF                       *pem = &(wm->binfmt.pe);
129         IMAGE_EXPORT_DIRECTORY          *exports = pem->pe_export;
130         unsigned int                    load_addr = wm->module;
131         u_long                          rva_start, rva_end, addr;
132         char                            * forward;
133
134         if (HIWORD(funcName))
135                 TRACE(win32,"(%s)\n",funcName);
136         else
137                 TRACE(win32,"(%d)\n",(int)funcName);
138         if (!exports) {
139                 /* Not a fatal problem, some apps do
140                  * GetProcAddress(0,"RegisterPenApp") which triggers this
141                  * case.
142                  */
143                 WARN(win32,"Module %08x(%s)/MODREF %p doesn't have a exports table.\n",wm->module,wm->modname,pem);
144                 return NULL;
145         }
146         ordinal = (u_short*)  RVA(exports->AddressOfNameOrdinals);
147         function= (u_long*)   RVA(exports->AddressOfFunctions);
148         name    = (u_char **) RVA(exports->AddressOfNames);
149         forward = NULL;
150         rva_start = PE_HEADER(wm->module)->OptionalHeader
151                 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
152         rva_end = rva_start + PE_HEADER(wm->module)->OptionalHeader
153                 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
154
155         if (HIWORD(funcName)) {
156                 for(i=0; i<exports->NumberOfNames; i++) {
157                         ename=(char*)RVA(*name);
158                         if(!strcmp(ename,funcName))
159                         {
160                             addr = function[*ordinal];
161                             if (!addr) return NULL;
162                             if ((addr < rva_start) || (addr >= rva_end))
163                                 return snoop? SNOOP_GetProcAddress(wm->module,ename,*ordinal,(FARPROC)RVA(addr))
164                                             : (FARPROC)RVA(addr);
165                             forward = (char *)RVA(addr);
166                             break;
167                         }
168                         ordinal++;
169                         name++;
170                 }
171         } else  {
172                 int i;
173                 if (LOWORD(funcName)-exports->Base > exports->NumberOfFunctions) {
174                         TRACE(win32,"   ordinal %d out of range!\n",
175                                       LOWORD(funcName));
176                         return NULL;
177                 }
178                 addr = function[(int)funcName-exports->Base];
179                 if (!addr) return NULL;
180                 ename = "";
181                 if (name) {
182                     for (i=0;i<exports->NumberOfNames;i++) {
183                             ename = (char*)RVA(*name);
184                             if (*ordinal == LOWORD(funcName)-exports->Base)
185                                 break;
186                             ordinal++;
187                             name++;
188                     }
189                     if (i==exports->NumberOfNames)
190                         ename = "";
191                 }
192                 if ((addr < rva_start) || (addr >= rva_end))
193                         return snoop? SNOOP_GetProcAddress(wm->module,ename,(DWORD)funcName-exports->Base,(FARPROC)RVA(addr))
194                                     : (FARPROC)RVA(addr);
195                 forward = (char *)RVA(addr);
196         }
197         if (forward)
198         {
199                 HMODULE hMod;
200                 char module[256];
201                 char *end = strchr(forward, '.');
202
203                 if (!end) return NULL;
204                 assert(end-forward<256);
205                 strncpy(module, forward, (end - forward));
206                 module[end-forward] = 0;
207                 hMod = MODULE_FindModule( module );
208                 assert(hMod);
209                 return MODULE_GetProcAddress( hMod, end + 1, snoop );
210         }
211         return NULL;
212 }
213
214 DWORD fixup_imports( WINE_MODREF *wm )
215 {
216     IMAGE_IMPORT_DESCRIPTOR     *pe_imp;
217     WINE_MODREF                 *xwm;
218     PE_MODREF                   *pem;
219     unsigned int load_addr      = wm->module;
220     int                         i,characteristics_detection=1;
221     char                        *modname;
222     
223     assert(wm->type==MODULE32_PE);
224     pem = &(wm->binfmt.pe);
225     if (pem->pe_export)
226         modname = (char*) RVA(pem->pe_export->Name);
227     else
228         modname = "<unknown>";
229
230     /* OK, now dump the import list */
231     TRACE(win32, "Dumping imports list\n");
232
233     /* first, count the number of imported non-internal modules */
234     pe_imp = pem->pe_import;
235     if (!pe_imp) 
236         ERR(win32, "no import directory????\n");
237
238     /* We assume that we have at least one import with !0 characteristics and
239      * detect broken imports with all characteristsics 0 (notably Borland) and
240      * switch the detection off for them.
241      */
242     for (i = 0; pe_imp->Name ; pe_imp++) {
243         if (!i && !pe_imp->u.Characteristics)
244                 characteristics_detection = 0;
245         if (characteristics_detection && !pe_imp->u.Characteristics)
246                 break;
247         i++;
248     }
249
250     /* Allocate module dependency list */
251     wm->nDeps = i;
252     wm->deps  = HeapAlloc( GetProcessHeap(), 0, i*sizeof(WINE_MODREF *) );
253
254     /* load the imported modules. They are automatically 
255      * added to the modref list of the process.
256      */
257  
258     for (i = 0, pe_imp = pem->pe_import; pe_imp->Name ; pe_imp++) {
259         HMODULE         hImpModule;
260         IMAGE_IMPORT_BY_NAME    *pe_name;
261         PIMAGE_THUNK_DATA       import_list,thunk_list;
262         char                    *name = (char *) RVA(pe_imp->Name);
263
264         if (characteristics_detection && !pe_imp->u.Characteristics)
265                 break;
266
267         /* don't use MODULE_Load, Win32 creates new task differently */
268         hImpModule = MODULE_LoadLibraryExA( name, 0, 0 );
269         if (!hImpModule) {
270             char *p,buffer[2000];
271             
272             /* GetModuleFileName would use the wrong process, so don't use it */
273             strcpy(buffer,wm->shortname);
274             if (!(p = strrchr (buffer, '\\')))
275                 p = buffer;
276             strcpy (p + 1, name);
277             hImpModule = MODULE_LoadLibraryExA( buffer, 0, 0 );
278         }
279         if (!hImpModule) {
280             ERR (module, "Module %s not found\n", name);
281             return 1;
282         }
283         xwm = MODULE32_LookupHMODULE( hImpModule );
284         assert( xwm );
285         wm->deps[i++] = xwm;
286
287         /* FIXME: forwarder entries ... */
288
289         if (pe_imp->u.OriginalFirstThunk != 0) { /* original MS style */
290             TRACE(win32, "Microsoft style imports used\n");
291             import_list =(PIMAGE_THUNK_DATA) RVA(pe_imp->u.OriginalFirstThunk);
292             thunk_list = (PIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk);
293
294             while (import_list->u1.Ordinal) {
295                 if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal)) {
296                     int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);
297
298                     TRACE(win32, "--- Ordinal %s,%d\n", name, ordinal);
299                     thunk_list->u1.Function=MODULE_GetProcAddress(
300                         hImpModule, (LPCSTR)ordinal, TRUE
301                     );
302                     if (!thunk_list->u1.Function) {
303                         ERR(win32,"No implementation for %s.%d, setting to 0xdeadbeef\n",
304                                 name, ordinal);
305                         thunk_list->u1.Function = (FARPROC)0xdeadbeef;
306                     }
307                 } else {                /* import by name */
308                     pe_name = (PIMAGE_IMPORT_BY_NAME)RVA(import_list->u1.AddressOfData);
309                     TRACE(win32, "--- %s %s.%d\n", pe_name->Name, name, pe_name->Hint);
310                     thunk_list->u1.Function=MODULE_GetProcAddress(
311                         hImpModule, pe_name->Name, TRUE
312                     );
313                     if (!thunk_list->u1.Function) {
314                         ERR(win32,"No implementation for %s.%d(%s), setting to 0xdeadbeef\n",
315                                 name,pe_name->Hint,pe_name->Name);
316                         thunk_list->u1.Function = (FARPROC)0xdeadbeef;
317                     }
318                 }
319                 import_list++;
320                 thunk_list++;
321             }
322         } else {        /* Borland style */
323             TRACE(win32, "Borland style imports used\n");
324             thunk_list = (PIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk);
325             while (thunk_list->u1.Ordinal) {
326                 if (IMAGE_SNAP_BY_ORDINAL(thunk_list->u1.Ordinal)) {
327                     /* not sure about this branch, but it seems to work */
328                     int ordinal = IMAGE_ORDINAL(thunk_list->u1.Ordinal);
329
330                     TRACE(win32,"--- Ordinal %s.%d\n",name,ordinal);
331                     thunk_list->u1.Function=MODULE_GetProcAddress(
332                         hImpModule, (LPCSTR) ordinal, TRUE
333                     );
334                     if (!thunk_list->u1.Function) {
335                         ERR(win32, "No implementation for %s.%d, setting to 0xdeadbeef\n",
336                                 name,ordinal);
337                         thunk_list->u1.Function = (FARPROC)0xdeadbeef;
338                     }
339                 } else {
340                     pe_name=(PIMAGE_IMPORT_BY_NAME) RVA(thunk_list->u1.AddressOfData);
341                     TRACE(win32,"--- %s %s.%d\n",
342                                   pe_name->Name,name,pe_name->Hint);
343                     thunk_list->u1.Function=MODULE_GetProcAddress(
344                         hImpModule, pe_name->Name, TRUE
345                     );
346                     if (!thunk_list->u1.Function) {
347                         ERR(win32, "No implementation for %s.%d, setting to 0xdeadbeef\n",
348                                 name, pe_name->Hint);
349                         thunk_list->u1.Function = (FARPROC)0xdeadbeef;
350                     }
351                 }
352                 thunk_list++;
353             }
354         }
355     }
356     return 0;
357 }
358
359 static int calc_vma_size( HMODULE hModule )
360 {
361     int i,vma_size = 0;
362     IMAGE_SECTION_HEADER *pe_seg = PE_SECTIONS(hModule);
363
364     TRACE(win32, "Dump of segment table\n");
365     TRACE(win32, "   Name    VSz  Vaddr     SzRaw   Fileadr  *Reloc *Lineum #Reloc #Linum Char\n");
366     for (i = 0; i< PE_HEADER(hModule)->FileHeader.NumberOfSections; i++)
367     {
368         TRACE(win32, "%8s: %4.4lx %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %4.4x %4.4x %8.8lx\n", 
369                       pe_seg->Name, 
370                       pe_seg->Misc.VirtualSize,
371                       pe_seg->VirtualAddress,
372                       pe_seg->SizeOfRawData,
373                       pe_seg->PointerToRawData,
374                       pe_seg->PointerToRelocations,
375                       pe_seg->PointerToLinenumbers,
376                       pe_seg->NumberOfRelocations,
377                       pe_seg->NumberOfLinenumbers,
378                       pe_seg->Characteristics);
379         vma_size=MAX(vma_size, pe_seg->VirtualAddress+pe_seg->SizeOfRawData);
380         vma_size=MAX(vma_size, pe_seg->VirtualAddress+pe_seg->Misc.VirtualSize);
381         pe_seg++;
382     }
383     return vma_size;
384 }
385
386 static void do_relocations( unsigned int load_addr, IMAGE_BASE_RELOCATION *r )
387 {
388     int delta = load_addr - PE_HEADER(load_addr)->OptionalHeader.ImageBase;
389     int hdelta = (delta >> 16) & 0xFFFF;
390     int ldelta = delta & 0xFFFF;
391
392         if(delta == 0)
393                 /* Nothing to do */
394                 return;
395         while(r->VirtualAddress)
396         {
397                 char *page = (char*) RVA(r->VirtualAddress);
398                 int count = (r->SizeOfBlock - 8)/2;
399                 int i;
400                 TRACE(fixup, "%x relocations for page %lx\n",
401                         count, r->VirtualAddress);
402                 /* patching in reverse order */
403                 for(i=0;i<count;i++)
404                 {
405                         int offset = r->TypeOffset[i] & 0xFFF;
406                         int type = r->TypeOffset[i] >> 12;
407                         TRACE(fixup,"patching %x type %x\n", offset, type);
408                         switch(type)
409                         {
410                         case IMAGE_REL_BASED_ABSOLUTE: break;
411                         case IMAGE_REL_BASED_HIGH:
412                                 *(short*)(page+offset) += hdelta;
413                                 break;
414                         case IMAGE_REL_BASED_LOW:
415                                 *(short*)(page+offset) += ldelta;
416                                 break;
417                         case IMAGE_REL_BASED_HIGHLOW:
418 #if 1
419                                 *(int*)(page+offset) += delta;
420 #else
421                                 { int h=*(unsigned short*)(page+offset);
422                                   int l=r->TypeOffset[++i];
423                                   *(unsigned int*)(page + offset) = (h<<16) + l + delta;
424                                 }
425 #endif
426                                 break;
427                         case IMAGE_REL_BASED_HIGHADJ:
428                                 FIXME(win32, "Don't know what to do with IMAGE_REL_BASED_HIGHADJ\n");
429                                 break;
430                         case IMAGE_REL_BASED_MIPS_JMPADDR:
431                                 FIXME(win32, "Is this a MIPS machine ???\n");
432                                 break;
433                         default:
434                                 FIXME(win32, "Unknown fixup type\n");
435                                 break;
436                         }
437                 }
438                 r = (IMAGE_BASE_RELOCATION*)((char*)r + r->SizeOfBlock);
439         }
440 }
441                 
442
443         
444         
445
446 /**********************************************************************
447  *                      PE_LoadImage
448  * Load one PE format DLL/EXE into memory
449  * 
450  * Unluckily we can't just mmap the sections where we want them, for 
451  * (at least) Linux does only support offsets which are page-aligned.
452  *
453  * BUT we have to map the whole image anyway, for Win32 programs sometimes
454  * want to access them. (HMODULE32 point to the start of it)
455  */
456 HMODULE PE_LoadImage( HFILE hFile, OFSTRUCT *ofs, LPCSTR *modName )
457 {
458     HMODULE     hModule;
459     HANDLE      mapping;
460
461     IMAGE_NT_HEADERS *nt;
462     IMAGE_SECTION_HEADER *pe_sec;
463     IMAGE_DATA_DIRECTORY *dir;
464     BY_HANDLE_FILE_INFORMATION bhfi;
465     int i, rawsize, lowest_va, lowest_fa, vma_size, file_size = 0;
466     DWORD load_addr, aoep, reloc = 0;
467
468     /* Retrieve file size */
469     if ( GetFileInformationByHandle( hFile, &bhfi ) ) 
470         file_size = bhfi.nFileSizeLow; /* FIXME: 64 bit */
471
472     /* Map the PE file somewhere */
473     mapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT,
474                                     0, 0, NULL );
475     if (!mapping)
476     {
477         WARN( win32, "CreateFileMapping error %ld\n", GetLastError() );
478         return 0;
479     }
480     hModule = (HMODULE)MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
481     CloseHandle( mapping );
482     if (!hModule)
483     {
484         WARN( win32, "MapViewOfFile error %ld\n", GetLastError() );
485         return 0;
486     }
487     nt = PE_HEADER( hModule );
488
489     /* Check signature */
490     if ( nt->Signature != IMAGE_NT_SIGNATURE )
491     {
492         WARN(win32, "image doesn't have PE signature, but 0x%08lx\n",
493                     nt->Signature );
494         goto error;
495     }
496
497     /* Check architecture */
498     if ( nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386 )
499     {
500         MSG("Trying to load PE image for unsupported architecture (");
501         switch (nt->FileHeader.Machine)
502         {
503         case IMAGE_FILE_MACHINE_UNKNOWN: MSG("Unknown"); break;
504         case IMAGE_FILE_MACHINE_I860:    MSG("I860"); break;
505         case IMAGE_FILE_MACHINE_R3000:   MSG("R3000"); break;
506         case IMAGE_FILE_MACHINE_R4000:   MSG("R4000"); break;
507         case IMAGE_FILE_MACHINE_R10000:  MSG("R10000"); break;
508         case IMAGE_FILE_MACHINE_ALPHA:   MSG("Alpha"); break;
509         case IMAGE_FILE_MACHINE_POWERPC: MSG("PowerPC"); break;
510         default: MSG("Unknown-%04x", nt->FileHeader.Machine); break;
511         }
512         MSG(")\n");
513         goto error;
514     }
515
516     /* Find out how large this executeable should be */
517     pe_sec = PE_SECTIONS( hModule );
518     rawsize = 0; lowest_va = 0x10000; lowest_fa = 0x10000;
519     for (i = 0; i < nt->FileHeader.NumberOfSections; i++) 
520     {
521         if (lowest_va > pe_sec[i].VirtualAddress)
522            lowest_va = pe_sec[i].VirtualAddress;
523         if (pe_sec[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
524             continue;
525         if (pe_sec[i].PointerToRawData < lowest_fa)
526             lowest_fa = pe_sec[i].PointerToRawData;
527         if (pe_sec[i].PointerToRawData+pe_sec[i].SizeOfRawData > rawsize)
528             rawsize = pe_sec[i].PointerToRawData+pe_sec[i].SizeOfRawData;
529     }
530  
531     /* Check file size */
532     if ( file_size && file_size < rawsize )
533     {
534         ERR( win32, "PE module is too small (header: %d, filesize: %d), "
535                     "probably truncated download?\n", 
536                     rawsize, file_size );
537         goto error;
538     }
539
540     /* Check entrypoint address */
541     aoep = nt->OptionalHeader.AddressOfEntryPoint;
542     if (aoep && (aoep < lowest_va))
543         FIXME( win32, "WARNING: '%s' has an invalid entrypoint (0x%08lx) "
544                       "below the first virtual address (0x%08x) "
545                       "(possible Virus Infection or broken binary)!\n",
546                        ofs->szPathName, aoep, lowest_va );
547
548
549     /* Allocate memory for module */
550     load_addr = nt->OptionalHeader.ImageBase;
551     vma_size = calc_vma_size( hModule );
552
553     load_addr = (DWORD)VirtualAlloc( (void*)load_addr, vma_size,
554                                      MEM_RESERVE | MEM_COMMIT,
555                                      PAGE_EXECUTE_READWRITE );
556     if (load_addr == 0) 
557     {
558         /* We need to perform base relocations */
559         dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BASERELOC;
560         if (dir->Size)
561             reloc = dir->VirtualAddress;
562         else 
563         {
564             FIXME( win32,
565                    "Need to relocate %s, but no relocation records present (%s).\n",
566                    ofs->szPathName,
567                    (nt->FileHeader.Characteristics&IMAGE_FILE_RELOCS_STRIPPED)?
568                    "stripped during link" : "unknown reason" );
569             goto error;
570         }
571
572         load_addr = (DWORD)VirtualAlloc( NULL, vma_size,
573                                          MEM_RESERVE | MEM_COMMIT,
574                                          PAGE_EXECUTE_READWRITE );
575     }
576
577     TRACE( win32, "Load addr is %lx (base %lx), range %x\n",
578                   load_addr, nt->OptionalHeader.ImageBase, vma_size );
579     TRACE( segment, "Loading %s at %lx, range %x\n",
580                     ofs->szPathName, load_addr, vma_size );
581
582     /* Store the NT header at the load addr */
583     *(PIMAGE_DOS_HEADER)load_addr = *(PIMAGE_DOS_HEADER)hModule;
584     *PE_HEADER( load_addr ) = *nt;
585     memcpy( PE_SECTIONS(load_addr), PE_SECTIONS(hModule),
586             sizeof(IMAGE_SECTION_HEADER) * nt->FileHeader.NumberOfSections );
587 #if 0
588     /* Copies all stuff up to the first section. Including win32 viruses. */
589     memcpy( load_addr, hModule, lowest_fa );
590 #endif
591
592     /* Copy sections into module image */
593     pe_sec = PE_SECTIONS( hModule );
594     for (i = 0; i < nt->FileHeader.NumberOfSections; i++, pe_sec++)
595     {
596         /* memcpy only non-BSS segments */
597         /* FIXME: this should be done by mmap(..MAP_PRIVATE|MAP_FIXED..)
598          * but it is not possible for (at least) Linux needs
599          * a page-aligned offset.
600          */
601         if(!(pe_sec->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA))
602             memcpy((char*)RVA(pe_sec->VirtualAddress),
603                    (char*)(hModule + pe_sec->PointerToRawData),
604                    pe_sec->SizeOfRawData);
605 #if 0
606         /* not needed, memory is zero */
607         if(strcmp(pe_sec->Name, ".bss") == 0)
608             memset((void *)RVA(pe_sec->VirtualAddress), 0, 
609                    pe_sec->Misc.VirtualSize ?
610                    pe_sec->Misc.VirtualSize :
611                    pe_sec->SizeOfRawData);
612 #endif
613     }
614
615     /* Perform base relocation, if necessary */
616     if ( reloc )
617         do_relocations( load_addr, (IMAGE_BASE_RELOCATION *)RVA(reloc) );
618
619     /* Get module name */
620     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXPORT;
621     if (dir->Size)
622         *modName = (LPCSTR)RVA(((PIMAGE_EXPORT_DIRECTORY)RVA(dir->VirtualAddress))->Name);
623
624     /* We don't need the orignal mapping any more */
625     UnmapViewOfFile( (LPVOID)hModule );
626     return (HMODULE)load_addr;
627
628 error:
629     UnmapViewOfFile( (LPVOID)hModule );
630     return 0;
631 }
632
633 /**********************************************************************
634  *                 PE_CreateModule
635  *
636  * Create WINE_MODREF structure for loaded HMODULE32, link it into
637  * process modref_list, and fixup all imports.
638  *
639  * Note: hModule must point to a correctly allocated PE image,
640  *       with base relocations applied; the 16-bit dummy module
641  *       associated to hModule must already exist.
642  *
643  * Note: This routine must always be called in the context of the
644  *       process that is to own the module to be created.
645  */
646 WINE_MODREF *PE_CreateModule( HMODULE hModule, 
647                               OFSTRUCT *ofs, DWORD flags, BOOL builtin )
648 {
649     DWORD load_addr = (DWORD)hModule;  /* for RVA */
650     IMAGE_NT_HEADERS *nt = PE_HEADER(hModule);
651     IMAGE_DATA_DIRECTORY *dir;
652     IMAGE_IMPORT_DESCRIPTOR *pe_import = NULL;
653     IMAGE_EXPORT_DIRECTORY *pe_export = NULL;
654     IMAGE_RESOURCE_DIRECTORY *pe_resource = NULL;
655     WINE_MODREF *wm;
656     int result;
657     char *modname;
658
659
660     /* Retrieve DataDirectory entries */
661
662     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXPORT;
663     if (dir->Size)
664         pe_export = (PIMAGE_EXPORT_DIRECTORY)RVA(dir->VirtualAddress);
665
666     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IMPORT;
667     if (dir->Size)
668         pe_import = (PIMAGE_IMPORT_DESCRIPTOR)RVA(dir->VirtualAddress);
669
670     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_RESOURCE;
671     if (dir->Size)
672         pe_resource = (PIMAGE_RESOURCE_DIRECTORY)RVA(dir->VirtualAddress);
673
674     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXCEPTION;
675     if (dir->Size) FIXME( win32, "Exception directory ignored\n" );
676
677     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_SECURITY;
678     if (dir->Size) FIXME( win32, "Security directory ignored\n" );
679
680     /* IMAGE_DIRECTORY_ENTRY_BASERELOC handled in PE_LoadImage */
681     /* IMAGE_DIRECTORY_ENTRY_DEBUG handled by debugger */
682
683     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_DEBUG;
684     if (dir->Size) TRACE( win32, "Debug directory ignored\n" );
685
686     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_COPYRIGHT;
687     if (dir->Size) FIXME( win32, "Copyright string ignored\n" );
688
689     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_GLOBALPTR;
690     if (dir->Size) FIXME( win32, "Global Pointer (MIPS) ignored\n" );
691
692     /* IMAGE_DIRECTORY_ENTRY_TLS handled in PE_TlsInit */
693
694     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG;
695     if (dir->Size) FIXME (win32, "Load Configuration directory ignored\n" );
696
697     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT;
698     if (dir->Size) TRACE( win32, "Bound Import directory ignored\n" );
699
700     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IAT;
701     if (dir->Size) TRACE( win32, "Import Address Table directory ignored\n" );
702
703     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT;
704     if (dir->Size)
705     {
706                 TRACE( win32, "Delayed import, stub calls LoadLibrary\n" );
707                 /*
708                  * Nothing to do here.
709                  */
710
711 #ifdef ImgDelayDescr
712                 /*
713                  * This code is useful to observe what the heck is going on.
714                  */
715                 {
716                 ImgDelayDescr *pe_delay = NULL;
717         pe_delay = (PImgDelayDescr)RVA(dir->VirtualAddress);
718         TRACE(delayhlp,"pe_delay->grAttrs = %08x\n", pe_delay->grAttrs);
719         TRACE(delayhlp,"pe_delay->szName = %s\n", pe_delay->szName);
720         TRACE(delayhlp,"pe_delay->phmod = %08x\n", pe_delay->phmod);
721         TRACE(delayhlp,"pe_delay->pIAT = %08x\n", pe_delay->pIAT);
722         TRACE(delayhlp,"pe_delay->pINT = %08x\n", pe_delay->pINT);
723         TRACE(delayhlp,"pe_delay->pBoundIAT = %08x\n", pe_delay->pBoundIAT);
724         TRACE(delayhlp,"pe_delay->pUnloadIAT = %08x\n", pe_delay->pUnloadIAT);
725         TRACE(delayhlp,"pe_delay->dwTimeStamp = %08x\n", pe_delay->dwTimeStamp);
726         }
727 #endif /* ImgDelayDescr */
728         }
729
730     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR;
731     if (dir->Size) FIXME( win32, "Unknown directory 14 ignored\n" );
732
733     dir = nt->OptionalHeader.DataDirectory+15;
734     if (dir->Size) FIXME( win32, "Unknown directory 15 ignored\n" );
735
736
737     /* Allocate and fill WINE_MODREF */
738
739     wm = (WINE_MODREF *)HeapAlloc( GetProcessHeap(), 
740                                    HEAP_ZERO_MEMORY, sizeof(*wm) );
741     wm->module = hModule;
742
743     wm->type = MODULE32_PE;
744     wm->binfmt.pe.flags = builtin? PE_MODREF_INTERNAL : 0;
745     wm->binfmt.pe.pe_export = pe_export;
746     wm->binfmt.pe.pe_import = pe_import;
747     wm->binfmt.pe.pe_resource = pe_resource;
748
749     if ( pe_export ) 
750         modname = (char *)RVA( pe_export->Name );
751     else 
752     {
753         /* try to find out the name from the OFSTRUCT */
754         char *s;
755         modname = ofs->szPathName;
756         while ((s=strchr(modname,'\\')))
757             modname = s+1;
758     }
759     wm->modname = HEAP_strdupA( GetProcessHeap(), 0, modname );
760
761     result = GetLongPathNameA( ofs->szPathName, NULL, 0 );
762     wm->longname = (char *)HeapAlloc( GetProcessHeap(), 0, result+1 );
763     GetLongPathNameA( ofs->szPathName, wm->longname, result+1 );
764
765     wm->shortname = HEAP_strdupA( GetProcessHeap(), 0, ofs->szPathName );
766
767     /* Link MODREF into process list */
768
769     wm->next = PROCESS_Current()->modref_list;
770     PROCESS_Current()->modref_list = wm;
771
772     if ( !(nt->FileHeader.Characteristics & IMAGE_FILE_DLL) )
773     {
774         if ( PROCESS_Current()->exe_modref )
775             FIXME( win32, "overwriting old exe_modref... arrgh\n" );
776         PROCESS_Current()->exe_modref = wm;
777     }
778
779     /* Dump Exports */
780
781     if ( pe_export )
782         dump_exports( hModule );
783
784     /* Fixup Imports */
785
786     if ( pe_import && fixup_imports( wm ) ) 
787     {
788         /* remove entry from modref chain */
789         WINE_MODREF **xwm;
790         for ( xwm = &PROCESS_Current()->modref_list; *xwm; xwm = &(*xwm)->next )
791             if ( *xwm == wm )
792             {
793                 *xwm = wm->next;
794                 break;
795             }
796         /* FIXME: there are several more dangling references
797          * left. Including dlls loaded by this dll before the
798          * failed one. Unrolling is rather difficult with the
799          * current structure and we can leave it them lying
800          * around with no problems, so we don't care.
801          * As these might reference our wm, we don't free it.
802          */
803          return NULL;
804     }
805
806     return wm;
807 }
808
809 /******************************************************************************
810  * The PE Library Loader frontend. 
811  * FIXME: handle the flags.
812  */
813 HMODULE PE_LoadLibraryExA (LPCSTR name, 
814                                HFILE hFile, DWORD flags)
815 {
816     LPCSTR      modName = NULL;
817     OFSTRUCT    ofs;
818     HMODULE     hModule32;
819     HMODULE16   hModule16;
820     NE_MODULE   *pModule;
821     WINE_MODREF *wm;
822     BOOL        builtin = TRUE;
823     char        dllname[256], *p;
824
825     /* Check for already loaded module */
826     if ((hModule32 = MODULE_FindModule( name ))) 
827         return hModule32;
828
829     /* Append .DLL to name if no extension present */
830     strcpy( dllname, name );
831     if (!(p = strrchr( dllname, '.')) || strchr( p, '/' ) || strchr( p, '\\'))
832         strcat( dllname, ".DLL" );
833
834     /* Try to load builtin enabled modules first */
835     if ( !(hModule32 = BUILTIN32_LoadImage( name, &ofs, FALSE )) )
836     {
837         /* Load PE module */
838
839         hFile = OpenFile( dllname, &ofs, OF_READ | OF_SHARE_DENY_WRITE );
840         if ( hFile != HFILE_ERROR )
841             if ( (hModule32 = PE_LoadImage( hFile, &ofs, &modName )) >= 32 )
842                 builtin = FALSE;
843
844         CloseHandle( hFile );
845     }
846
847     /* Now try the built-in even if disabled */
848     if ( builtin ) {
849         if ( (hModule32 = BUILTIN32_LoadImage( name, &ofs, TRUE )) )
850             WARN( module, "Could not load external DLL '%s', using built-in module.\n", name );
851         else
852             return 0;
853     }
854
855
856     /* Create 16-bit dummy module */
857     if ((hModule16 = MODULE_CreateDummyModule( &ofs, modName )) < 32) return hModule16;
858     pModule = (NE_MODULE *)GlobalLock16( hModule16 );
859     pModule->flags    = NE_FFLAGS_LIBMODULE | NE_FFLAGS_SINGLEDATA |
860                         NE_FFLAGS_WIN32 | (builtin? NE_FFLAGS_BUILTIN : 0);
861     pModule->module32 = hModule32;
862
863     /* Create 32-bit MODREF */
864     if ( !(wm = PE_CreateModule( hModule32, &ofs, flags, builtin )) )
865     {
866         ERR(win32,"can't load %s\n",ofs.szPathName);
867         FreeLibrary16( hModule16 );
868         return 0;
869     }
870
871     if (wm->binfmt.pe.pe_export)
872         SNOOP_RegisterDLL(wm->module,wm->modname,wm->binfmt.pe.pe_export->NumberOfFunctions);
873
874     return wm->module;
875 }
876
877 /*****************************************************************************
878  * Load the PE main .EXE. All other loading is done by PE_LoadLibraryExA
879  * FIXME: this function should use PE_LoadLibraryExA, but currently can't
880  * due to the PROCESS_Create stuff.
881  */
882 BOOL PE_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmd_line, LPCSTR env, 
883                        LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
884                        BOOL inherit, LPSTARTUPINFOA startup,
885                        LPPROCESS_INFORMATION info )
886 {
887     LPCSTR modName = NULL;
888     HMODULE16 hModule16;
889     HMODULE hModule32;
890     NE_MODULE *pModule;
891
892     /* Load file */
893     if ( (hModule32 = PE_LoadImage( hFile, ofs, &modName )) < 32 )
894     {
895         SetLastError( hModule32 );
896         return FALSE;
897     }
898 #if 0
899     if (PE_HEADER(hModule32)->FileHeader.Characteristics & IMAGE_FILE_DLL)
900     {
901         SetLastError( 20 );  /* FIXME: not the right error code */
902         return FALSE;
903     }
904 #endif
905
906     /* Create 16-bit dummy module */
907     if ( (hModule16 = MODULE_CreateDummyModule( ofs, modName )) < 32 ) 
908     {
909         SetLastError( hModule16 );
910         return FALSE;
911     }
912     pModule = (NE_MODULE *)GlobalLock16( hModule16 );
913     pModule->flags    = NE_FFLAGS_WIN32;
914     pModule->module32 = hModule32;
915
916     /* Create new process */
917     if ( !PROCESS_Create( pModule, cmd_line, env,
918                           0, 0, psa, tsa, inherit, startup, info ) )
919         return FALSE;
920
921     /* Note: PE_CreateModule and the remaining process initialization will
922              be done in the context of the new process, in TASK_CallToStart */
923
924     return TRUE;
925 }
926
927 /*********************************************************************
928  * PE_UnloadImage [internal]
929  */
930 int PE_UnloadImage( HMODULE hModule )
931 {
932         FIXME(win32,"stub.\n");
933         /* free resources, image, unmap */
934         return 1;
935 }
936
937 /* Called if the library is loaded or freed.
938  * NOTE: if a thread attaches a DLL, the current thread will only do
939  * DLL_PROCESS_ATTACH. Only new created threads do DLL_THREAD_ATTACH
940  * (SDK)
941  */
942 void PE_InitDLL(WINE_MODREF *wm, DWORD type, LPVOID lpReserved)
943 {
944     if (wm->type!=MODULE32_PE)
945         return;
946     if (wm->binfmt.pe.flags & PE_MODREF_NO_DLL_CALLS)
947         return;
948     if (type==DLL_PROCESS_ATTACH)
949     {
950         if (wm->binfmt.pe.flags & PE_MODREF_PROCESS_ATTACHED)
951             return;
952
953         wm->binfmt.pe.flags |= PE_MODREF_PROCESS_ATTACHED;
954     }
955
956     /*  DLL_ATTACH_PROCESS:
957      *          lpreserved is NULL for dynamic loads, not-NULL for static loads
958      *  DLL_DETACH_PROCESS:
959      *          lpreserved is NULL if called by FreeLibrary, not-NULL otherwise
960      *  the SDK doesn't mention anything for DLL_THREAD_*
961      */
962         
963     /* Is this a library? And has it got an entrypoint? */
964     if ((PE_HEADER(wm->module)->FileHeader.Characteristics & IMAGE_FILE_DLL) &&
965         (PE_HEADER(wm->module)->OptionalHeader.AddressOfEntryPoint)
966     ) {
967         DLLENTRYPROC entry = (void*)RVA_PTR( wm->module,OptionalHeader.AddressOfEntryPoint );
968         TRACE(relay, "CallTo32(entryproc=%p,module=%08x,type=%ld,res=%p)\n",
969                        entry, wm->module, type, lpReserved );
970
971         entry( wm->module, type, lpReserved );
972     }
973 }
974
975 /************************************************************************
976  *      PE_InitTls                      (internal)
977  *
978  * If included, initialises the thread local storages of modules.
979  * Pointers in those structs are not RVAs but real pointers which have been
980  * relocated by do_relocations() already.
981  */
982 void PE_InitTls(THDB *thdb)
983 {
984         WINE_MODREF             *wm;
985         PE_MODREF               *pem;
986         IMAGE_NT_HEADERS        *peh;
987         DWORD                   size,datasize;
988         LPVOID                  mem;
989         PIMAGE_TLS_DIRECTORY    pdir;
990         PDB                     *pdb = thdb->process;
991         int delta;
992         
993         for (wm = pdb->modref_list;wm;wm=wm->next) {
994                 if (wm->type!=MODULE32_PE)
995                         continue;
996                 pem = &(wm->binfmt.pe);
997                 peh = PE_HEADER(wm->module);
998                 delta = wm->module - peh->OptionalHeader.ImageBase;
999                 if (!peh->OptionalHeader.DataDirectory[IMAGE_FILE_THREAD_LOCAL_STORAGE].VirtualAddress)
1000                         continue;
1001                 pdir = (LPVOID)(wm->module + peh->OptionalHeader.
1002                         DataDirectory[IMAGE_FILE_THREAD_LOCAL_STORAGE].VirtualAddress);
1003                 
1004                 
1005                 if (!(pem->flags & PE_MODREF_TLS_ALLOCED)) {
1006                         pem->tlsindex = THREAD_TlsAlloc(thdb);
1007                         *pdir->AddressOfIndex=pem->tlsindex;   
1008                 }
1009                 pem->flags |= PE_MODREF_TLS_ALLOCED;
1010                 datasize= pdir->EndAddressOfRawData-pdir->StartAddressOfRawData;
1011                 size    = datasize + pdir->SizeOfZeroFill;
1012                 mem=VirtualAlloc(0,size,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE);
1013                 memcpy(mem,(LPVOID)pdir->StartAddressOfRawData,datasize);
1014                 if (pdir->AddressOfCallBacks) {
1015                      PIMAGE_TLS_CALLBACK *cbs = 
1016                        (PIMAGE_TLS_CALLBACK *)pdir->AddressOfCallBacks;
1017
1018                      if (*cbs)
1019                        FIXME(win32, "TLS Callbacks aren't going to be called\n");
1020                 }
1021                 /* Don't use TlsSetValue, we are in the wrong thread */
1022                 thdb->tls_array[pem->tlsindex] = mem;
1023         }
1024 }
1025
1026 /****************************************************************************
1027  *              DisableThreadLibraryCalls (KERNEL32.74)
1028  * Don't call DllEntryPoint for DLL_THREAD_{ATTACH,DETACH} if set.
1029  */
1030 BOOL WINAPI DisableThreadLibraryCalls(HMODULE hModule)
1031 {
1032         WINE_MODREF     *wm;
1033
1034         for (wm=PROCESS_Current()->modref_list;wm;wm=wm->next)
1035                 if ((wm->module == hModule) && (wm->type==MODULE32_PE))
1036                         wm->binfmt.pe.flags|=PE_MODREF_NO_DLL_CALLS;
1037         return TRUE;
1038 }