Loading the color schema for registry.
[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                    "FATAL: Need to relocate %s, but no relocation records present (%s). Try to run that file directly !\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     if ( builtin ) 
744         wm->flags |= WINE_MODREF_INTERNAL;
745     if ( flags & DONT_RESOLVE_DLL_REFERENCES )
746         wm->flags |= WINE_MODREF_DONT_RESOLVE_REFS;
747     if ( flags & LOAD_LIBRARY_AS_DATAFILE )
748         wm->flags |= WINE_MODREF_LOAD_AS_DATAFILE;
749
750     wm->type = MODULE32_PE;
751     wm->binfmt.pe.pe_export = pe_export;
752     wm->binfmt.pe.pe_import = pe_import;
753     wm->binfmt.pe.pe_resource = pe_resource;
754     wm->binfmt.pe.tlsindex = -1;
755
756     if ( pe_export ) 
757         modname = (char *)RVA( pe_export->Name );
758     else 
759     {
760         /* try to find out the name from the OFSTRUCT */
761         char *s;
762         modname = ofs->szPathName;
763         if ((s=strrchr(modname,'\\'))) modname = s+1;
764     }
765     wm->modname = HEAP_strdupA( GetProcessHeap(), 0, modname );
766
767     result = GetLongPathNameA( ofs->szPathName, NULL, 0 );
768     wm->longname = (char *)HeapAlloc( GetProcessHeap(), 0, result+1 );
769     GetLongPathNameA( ofs->szPathName, wm->longname, result+1 );
770
771     wm->shortname = HEAP_strdupA( GetProcessHeap(), 0, ofs->szPathName );
772
773     /* Link MODREF into process list */
774
775     EnterCriticalSection( &PROCESS_Current()->crit_section );
776
777     wm->next = PROCESS_Current()->modref_list;
778     PROCESS_Current()->modref_list = wm;
779     if ( wm->next ) wm->next->prev = wm;
780
781     if ( !(nt->FileHeader.Characteristics & IMAGE_FILE_DLL) )
782     {
783         if ( PROCESS_Current()->exe_modref )
784             FIXME( win32, "overwriting old exe_modref... arrgh\n" );
785         PROCESS_Current()->exe_modref = wm;
786     }
787
788     LeaveCriticalSection( &PROCESS_Current()->crit_section );
789
790
791     /* Dump Exports */
792
793     if ( pe_export )
794         dump_exports( hModule );
795
796     /* Fixup Imports */
797
798     if (    pe_import && fixup_imports( wm ) 
799          && !( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE )
800          && !( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS ) ) 
801     {
802         /* remove entry from modref chain */
803         EnterCriticalSection( &PROCESS_Current()->crit_section );
804
805         if ( !wm->prev )
806             PROCESS_Current()->modref_list = wm->next;
807         else
808             wm->prev->next = wm->next;
809
810         if ( wm->next ) wm->next->prev = wm->prev;
811         wm->next = wm->prev = NULL;
812
813         LeaveCriticalSection( &PROCESS_Current()->crit_section );
814
815         /* FIXME: there are several more dangling references
816          * left. Including dlls loaded by this dll before the
817          * failed one. Unrolling is rather difficult with the
818          * current structure and we can leave it them lying
819          * around with no problems, so we don't care.
820          * As these might reference our wm, we don't free it.
821          */
822          return NULL;
823     }
824
825     return wm;
826 }
827
828 /******************************************************************************
829  * The PE Library Loader frontend. 
830  * FIXME: handle the flags.
831  */
832 HMODULE PE_LoadLibraryExA (LPCSTR name, 
833                                HFILE hFile, DWORD flags)
834 {
835     LPCSTR      modName = NULL;
836     OFSTRUCT    ofs;
837     HMODULE     hModule32;
838     HMODULE16   hModule16;
839     NE_MODULE   *pModule;
840     WINE_MODREF *wm;
841     BOOL        builtin = TRUE;
842     char        dllname[256], *p;
843
844     /* Check for already loaded module */
845     if ((hModule32 = MODULE_FindModule( name ))) 
846         return hModule32;
847
848     /* Append .DLL to name if no extension present */
849     strcpy( dllname, name );
850     if (!(p = strrchr( dllname, '.')) || strchr( p, '/' ) || strchr( p, '\\'))
851         strcat( dllname, ".DLL" );
852
853     /* Try to load builtin enabled modules first */
854     if ( !(hModule32 = BUILTIN32_LoadImage( name, &ofs, FALSE )) )
855     {
856         /* Load PE module */
857
858         hFile = OpenFile( dllname, &ofs, OF_READ | OF_SHARE_DENY_WRITE );
859         if ( hFile != HFILE_ERROR )
860             if ( (hModule32 = PE_LoadImage( hFile, &ofs, &modName )) >= 32 )
861                 builtin = FALSE;
862
863         CloseHandle( hFile );
864     }
865
866     /* Now try the built-in even if disabled */
867     if ( builtin ) {
868         if ( (hModule32 = BUILTIN32_LoadImage( name, &ofs, TRUE )) )
869             WARN( module, "Could not load external DLL '%s', using built-in module.\n", name );
870         else
871             return 0;
872     }
873
874
875     /* Create 16-bit dummy module */
876     if ((hModule16 = MODULE_CreateDummyModule( &ofs, modName )) < 32) return hModule16;
877     pModule = (NE_MODULE *)GlobalLock16( hModule16 );
878     pModule->flags    = NE_FFLAGS_LIBMODULE | NE_FFLAGS_SINGLEDATA |
879                         NE_FFLAGS_WIN32 | (builtin? NE_FFLAGS_BUILTIN : 0);
880     pModule->module32 = hModule32;
881
882     /* Create 32-bit MODREF */
883     if ( !(wm = PE_CreateModule( hModule32, &ofs, flags, builtin )) )
884     {
885         ERR(win32,"can't load %s\n",ofs.szPathName);
886         FreeLibrary16( hModule16 );
887         return 0;
888     }
889
890     if (wm->binfmt.pe.pe_export)
891         SNOOP_RegisterDLL(wm->module,wm->modname,wm->binfmt.pe.pe_export->NumberOfFunctions);
892
893     return wm->module;
894 }
895
896 /*****************************************************************************
897  * Load the PE main .EXE. All other loading is done by PE_LoadLibraryExA
898  * FIXME: this function should use PE_LoadLibraryExA, but currently can't
899  * due to the PROCESS_Create stuff.
900  */
901 BOOL PE_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmd_line, LPCSTR env, 
902                        LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
903                        BOOL inherit, LPSTARTUPINFOA startup,
904                        LPPROCESS_INFORMATION info )
905 {
906     LPCSTR modName = NULL;
907     HMODULE16 hModule16;
908     HMODULE hModule32;
909     NE_MODULE *pModule;
910
911     /* Load file */
912     if ( (hModule32 = PE_LoadImage( hFile, ofs, &modName )) < 32 )
913     {
914         SetLastError( hModule32 );
915         return FALSE;
916     }
917 #if 0
918     if (PE_HEADER(hModule32)->FileHeader.Characteristics & IMAGE_FILE_DLL)
919     {
920         SetLastError( 20 );  /* FIXME: not the right error code */
921         return FALSE;
922     }
923 #endif
924
925     /* Create 16-bit dummy module */
926     if ( (hModule16 = MODULE_CreateDummyModule( ofs, modName )) < 32 ) 
927     {
928         SetLastError( hModule16 );
929         return FALSE;
930     }
931     pModule = (NE_MODULE *)GlobalLock16( hModule16 );
932     pModule->flags    = NE_FFLAGS_WIN32;
933     pModule->module32 = hModule32;
934
935     /* Create new process */
936     if ( !PROCESS_Create( pModule, cmd_line, env,
937                           0, 0, psa, tsa, inherit, startup, info ) )
938         return FALSE;
939
940     /* Note: PE_CreateModule and the remaining process initialization will
941              be done in the context of the new process, in TASK_CallToStart */
942
943     return TRUE;
944 }
945
946 /*********************************************************************
947  * PE_UnloadImage [internal]
948  */
949 int PE_UnloadImage( HMODULE hModule )
950 {
951         FIXME(win32,"stub.\n");
952         /* free resources, image, unmap */
953         return 1;
954 }
955
956 /* Called if the library is loaded or freed.
957  * NOTE: if a thread attaches a DLL, the current thread will only do
958  * DLL_PROCESS_ATTACH. Only new created threads do DLL_THREAD_ATTACH
959  * (SDK)
960  */
961 void PE_InitDLL(WINE_MODREF *wm, DWORD type, LPVOID lpReserved)
962 {
963     if (wm->type!=MODULE32_PE)
964         return;
965
966     /*  DLL_ATTACH_PROCESS:
967      *          lpreserved is NULL for dynamic loads, not-NULL for static loads
968      *  DLL_DETACH_PROCESS:
969      *          lpreserved is NULL if called by FreeLibrary, not-NULL otherwise
970      *  the SDK doesn't mention anything for DLL_THREAD_*
971      */
972         
973     /* Is this a library? And has it got an entrypoint? */
974     if ((PE_HEADER(wm->module)->FileHeader.Characteristics & IMAGE_FILE_DLL) &&
975         (PE_HEADER(wm->module)->OptionalHeader.AddressOfEntryPoint)
976     ) {
977         DLLENTRYPROC entry = (void*)RVA_PTR( wm->module,OptionalHeader.AddressOfEntryPoint );
978         TRACE(relay, "CallTo32(entryproc=%p,module=%08x,type=%ld,res=%p)\n",
979                        entry, wm->module, type, lpReserved );
980
981         entry( wm->module, type, lpReserved );
982     }
983 }
984
985 /************************************************************************
986  *      PE_InitTls                      (internal)
987  *
988  * If included, initialises the thread local storages of modules.
989  * Pointers in those structs are not RVAs but real pointers which have been
990  * relocated by do_relocations() already.
991  */
992 void PE_InitTls( void )
993 {
994         WINE_MODREF             *wm;
995         PE_MODREF               *pem;
996         IMAGE_NT_HEADERS        *peh;
997         DWORD                   size,datasize;
998         LPVOID                  mem;
999         PIMAGE_TLS_DIRECTORY    pdir;
1000         int delta;
1001         
1002         for (wm = PROCESS_Current()->modref_list;wm;wm=wm->next) {
1003                 if (wm->type!=MODULE32_PE)
1004                         continue;
1005                 pem = &(wm->binfmt.pe);
1006                 peh = PE_HEADER(wm->module);
1007                 delta = wm->module - peh->OptionalHeader.ImageBase;
1008                 if (!peh->OptionalHeader.DataDirectory[IMAGE_FILE_THREAD_LOCAL_STORAGE].VirtualAddress)
1009                         continue;
1010                 pdir = (LPVOID)(wm->module + peh->OptionalHeader.
1011                         DataDirectory[IMAGE_FILE_THREAD_LOCAL_STORAGE].VirtualAddress);
1012                 
1013                 
1014                 if ( pem->tlsindex == -1 ) {
1015                         pem->tlsindex = TlsAlloc();
1016                         *pdir->AddressOfIndex=pem->tlsindex;   
1017                 }
1018                 datasize= pdir->EndAddressOfRawData-pdir->StartAddressOfRawData;
1019                 size    = datasize + pdir->SizeOfZeroFill;
1020                 mem=VirtualAlloc(0,size,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE);
1021                 memcpy(mem,(LPVOID)pdir->StartAddressOfRawData,datasize);
1022                 if (pdir->AddressOfCallBacks) {
1023                      PIMAGE_TLS_CALLBACK *cbs = 
1024                        (PIMAGE_TLS_CALLBACK *)pdir->AddressOfCallBacks;
1025
1026                      if (*cbs)
1027                        FIXME(win32, "TLS Callbacks aren't going to be called\n");
1028                 }
1029
1030                 TlsSetValue( pem->tlsindex, mem );
1031         }
1032 }
1033