Release 970202
[wine] / loader / pe_image.c
1 #ifndef WINELIB
2 /* 
3  *  Copyright   1994    Eric Youndale & Erik Bos
4  *  Copyright   1995    Martin von Löwis
5  *  Copyright   1996    Marcus Meissner
6  *
7  *      based on Eric Youndale's pe-test and:
8  *
9  *      ftp.microsoft.com:/pub/developer/MSDN/CD8/PEFILE.ZIP
10  * make that:
11  *      ftp.microsoft.com:/developr/MSDN/OctCD/PEFILE.ZIP
12  */
13
14 #include <ctype.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <sys/types.h>
20 #include "windows.h"
21 #include "winbase.h"
22 #include "callback.h"
23 #include "neexe.h"
24 #include "peexe.h"
25 #include "pe_image.h"
26 #include "module.h"
27 #include "global.h"
28 #include "task.h"
29 #include "ldt.h"
30 #include "stddebug.h"
31 #include "debug.h"
32 #include "debugger.h"
33 #include "xmalloc.h"
34
35 /* convert PE image VirtualAddress to Real Address */
36 #define RVA(x) ((unsigned int)load_addr+(unsigned int)(x))
37
38 void dump_exports(IMAGE_EXPORT_DIRECTORY * pe_exports, unsigned int load_addr)
39
40   char          *Module;
41   int           i;
42   u_short       *ordinal;
43   u_long        *function,*functions;
44   u_char        **name,*ename;
45   char          buffer[1000];
46   DBG_ADDR      daddr;
47
48   daddr.seg = 0;
49   daddr.type = NULL;
50   Module = (char*)RVA(pe_exports->Name);
51   dprintf_win32(stddeb,"\n*******EXPORT DATA*******\nModule name is %s, %ld functions, %ld names\n", 
52          Module,
53          pe_exports->NumberOfFunctions,
54          pe_exports->NumberOfNames);
55
56   ordinal=(u_short*) RVA(pe_exports->AddressOfNameOrdinals);
57   functions=function=(u_long*) RVA(pe_exports->AddressOfFunctions);
58   name=(u_char**) RVA(pe_exports->AddressOfNames);
59
60   dprintf_win32(stddeb,"%-32s Ordinal Virt Addr\n", "Function Name");
61   for (i=0;i<pe_exports->NumberOfFunctions;i++) {
62       if (i<pe_exports->NumberOfNames) {
63           ename=(char*)RVA(*name++);
64           dprintf_win32(stddeb,"%-32s %4d    %8.8lx (%8.8lx)\n",ename,*ordinal,functions[*ordinal],*function);
65           sprintf(buffer,"%s_%s",Module,ename);
66           daddr.off=RVA(functions[*ordinal]);
67           ordinal++;
68           function++;
69       } else {
70           /* ordinals/names no longer valid, but we still got functions */
71           dprintf_win32(stddeb,"%-32s %4s    %8s %8.8lx\n","","","",*function);
72           sprintf(buffer,"%s_%d",Module,i);
73           daddr.off=RVA(*functions);
74           function++;
75       }
76       DEBUG_AddSymbol(buffer,&daddr, NULL, SYM_WIN32 | SYM_FUNC);
77   }
78 }
79
80 /* Look up the specified function or ordinal in the exportlist:
81  * If it is a string:
82  *      - look up the name in the Name list. 
83  *      - look up the ordinal with that index.
84  *      - use the ordinal as offset into the functionlist
85  * If it is a ordinal:
86  *      - use ordinal-pe_export->Base as offset into the functionlist
87  */
88 FARPROC32 PE_FindExportedFunction(struct pe_data *pe, LPCSTR funcName)
89 {
90         IMAGE_EXPORT_DIRECTORY * exports = pe->pe_export;
91         unsigned load_addr = pe->load_addr;
92         u_short * ordinal;
93         u_long * function;
94         u_char ** name, *ename;
95         int i;
96
97         if (HIWORD(funcName))
98                 dprintf_win32(stddeb,"PE_FindExportedFunction(%s)\n",funcName);
99         else
100                 dprintf_win32(stddeb,"PE_FindExportedFunction(%d)\n",(int)funcName);
101         if (!exports)
102                 return NULL;
103         ordinal=(u_short*) RVA(exports->AddressOfNameOrdinals);
104         function=(u_long*) RVA(exports->AddressOfFunctions);
105         name=(u_char **) RVA(exports->AddressOfNames);
106         if (HIWORD(funcName)) {
107                 for(i=0; i<exports->NumberOfNames; i++) {
108                         ename=(char*) RVA(*name);
109                         if(!strcmp(ename,funcName))
110                                 return (FARPROC32) RVA(function[*ordinal]);
111                         ordinal++;
112                         name++;
113                 }
114         } else {
115                 if (LOWORD(funcName)-exports->Base > exports->NumberOfFunctions) {
116                         dprintf_win32(stddeb,"  ordinal %d out of range!\n",
117                                       LOWORD(funcName));
118                         return NULL;
119                 }
120                 return (FARPROC32) RVA(function[(int)funcName-exports->Base]);
121         }
122         return NULL;
123 }
124
125 void 
126 fixup_imports (struct pe_data *pe, HMODULE16 hModule)
127 {
128     IMAGE_IMPORT_DESCRIPTOR *pe_imp;
129     int fixup_failed = 0;
130     unsigned int load_addr = pe->load_addr;
131     int i;
132     NE_MODULE *ne_mod;
133     HMODULE16 *mod_ptr;
134     char *modname;
135     
136     if (pe->pe_export)
137         modname = (char*) RVA(pe->pe_export->Name);
138     else
139         modname = "<unknown>";
140
141     /* OK, now dump the import list */
142     dprintf_win32 (stddeb, "\nDumping imports list\n");
143
144     /* first, count the number of imported non-internal modules */
145     pe_imp = pe->pe_import;
146
147     /* FIXME: should terminate on 0 Characteristics */
148     for (i = 0; pe_imp->Name; pe_imp++)
149         i++;
150
151     /* Now, allocate memory for dlls_to_init */
152     ne_mod = GlobalLock16 (hModule);
153     ne_mod->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT, (i+1)*sizeof(HMODULE16),
154                                         hModule, FALSE, FALSE, FALSE);
155     mod_ptr = GlobalLock16 (ne_mod->dlls_to_init);
156     /* load the modules and put their handles into the list */
157  
158      /* FIXME: should terminate on 0 Characteristics */
159      for (i = 0, pe_imp = pe->pe_import; pe_imp->Name; pe_imp++) {
160         char *name = (char *) RVA(pe_imp->Name);
161         mod_ptr[i] = MODULE_Load( name, (LPVOID)-1, FALSE );
162         if (mod_ptr[i] <= (HMODULE16) 32) {
163             char *p, buffer[256];
164
165             /* Try with prepending the path of the current module */
166             GetModuleFileName16 (hModule, buffer, sizeof (buffer));
167             if (!(p = strrchr (buffer, '\\')))
168                 p = buffer;
169             strcpy (p + 1, name);
170             mod_ptr[i] = MODULE_Load( buffer, (LPVOID)-1, FALSE );
171         }
172         if (mod_ptr[i] <= (HMODULE16) 32) {
173             fprintf (stderr, "Module %s not found\n", name);
174             exit (0);
175         }
176         i++;
177     }
178     pe_imp = pe->pe_import;
179     while (pe_imp->Name) {
180         char                    *Module;
181         IMAGE_IMPORT_BY_NAME    *pe_name;
182         LPIMAGE_THUNK_DATA      import_list,thunk_list;
183         int                     ordimportwarned;
184
185         ordimportwarned = 0;
186         Module = (char *) RVA(pe_imp->Name);
187         dprintf_win32 (stddeb, "%s\n", Module);
188
189         if (pe_imp->u.OriginalFirstThunk != 0) { /* original MS style */
190             dprintf_win32 (stddeb, "Microsoft style imports used\n");
191             import_list =(LPIMAGE_THUNK_DATA) RVA(pe_imp->u.OriginalFirstThunk);
192             thunk_list = (LPIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk);
193
194             while (import_list->u1.Ordinal) {
195                 if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal)) {
196                     int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);
197
198                     if(!lstrncmpi32A(Module,"kernel32",8) && !ordimportwarned){
199                        fprintf(stderr,"%s imports kernel32.dll by ordinal. May crash.\n",modname);
200                        ordimportwarned = 1;
201                     }
202                     dprintf_win32 (stddeb, "--- Ordinal %s,%d\n", Module, ordinal);
203                     thunk_list->u1.Function=(LPDWORD)GetProcAddress32(MODULE_FindModule(Module),(LPCSTR)ordinal);
204                     if (!thunk_list->u1.Function) {
205                         fprintf(stderr,"No implementation for %s.%d, setting to NULL\n",
206                                 Module, ordinal);
207                         /* fixup_failed=1; */
208                     }
209                 } else {                /* import by name */
210                     pe_name = (LPIMAGE_IMPORT_BY_NAME)RVA(import_list->u1.AddressOfData);
211                     dprintf_win32 (stddeb, "--- %s %s.%d\n", pe_name->Name, Module, pe_name->Hint);
212                     thunk_list->u1.Function=(LPDWORD)GetProcAddress32(
213                                                 MODULE_FindModule (Module),
214                                                 pe_name->Name);
215                     if (!thunk_list->u1.Function) {
216                         fprintf(stderr,"No implementation for %s.%d(%s), setting to NULL\n",
217                                 Module,pe_name->Hint,pe_name->Name);
218                         /* fixup_failed=1; */
219                     }
220                 }
221                 import_list++;
222                 thunk_list++;
223             }
224         } else {        /* Borland style */
225             dprintf_win32 (stddeb, "Borland style imports used\n");
226             thunk_list = (LPIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk);
227             while (thunk_list->u1.Ordinal) {
228                 if (IMAGE_SNAP_BY_ORDINAL(thunk_list->u1.Ordinal)) {
229                     /* not sure about this branch, but it seems to work */
230                     int ordinal = IMAGE_ORDINAL(thunk_list->u1.Ordinal);
231
232
233                     if (!lstrncmpi32A(Module,"kernel32",8) && 
234                         !ordimportwarned
235                     ) {
236                        fprintf(stderr,"%s imports kernel32.dll by ordinal. May crash.\n",modname);
237                        ordimportwarned = 1;
238                     }
239                     dprintf_win32(stddeb,"--- Ordinal %s.%d\n",Module,ordinal);
240                     thunk_list->u1.Function=(LPDWORD)GetProcAddress32(MODULE_FindModule(Module),
241                                                      (LPCSTR) ordinal);
242                     if (!thunk_list->u1.Function) {
243                         fprintf(stderr, "No implementation for %s.%d, setting to NULL\n",
244                                 Module,ordinal);
245                         /* fixup_failed=1; */
246                     }
247                 } else {
248                     pe_name=(LPIMAGE_IMPORT_BY_NAME) RVA(thunk_list->u1.AddressOfData);
249                     dprintf_win32(stddeb,"--- %s %s.%d\n",
250                                   pe_name->Name,Module,pe_name->Hint);
251                     thunk_list->u1.Function=(LPDWORD)GetProcAddress32(MODULE_FindModule(Module),pe_name->Name);
252                     if (!thunk_list->u1.Function) {
253                         fprintf(stderr, "No implementation for %s.%d, setting to NULL\n",
254                                 Module, pe_name->Hint);
255                         /* fixup_failed=1; */
256                     }
257                 }
258                 thunk_list++;
259             }
260         }
261         pe_imp++;
262     }
263     if (fixup_failed) exit(1);
264 }
265
266 static void calc_vma_size(struct pe_data *pe)
267 {
268   int i;
269
270   dprintf_win32(stddeb, "Dump of segment table\n");
271   dprintf_win32(stddeb, "   Name    VSz  Vaddr     SzRaw   Fileadr  *Reloc *Lineum #Reloc #Linum Char\n");
272   for(i=0; i< pe->pe_header->FileHeader.NumberOfSections; i++)
273     {
274       dprintf_win32(stddeb, "%8s: %4.4lx %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %4.4x %4.4x %8.8lx\n", 
275              pe->pe_seg[i].Name, 
276              pe->pe_seg[i].Misc.VirtualSize,
277              pe->pe_seg[i].VirtualAddress,
278              pe->pe_seg[i].SizeOfRawData,
279              pe->pe_seg[i].PointerToRawData,
280              pe->pe_seg[i].PointerToRelocations,
281              pe->pe_seg[i].PointerToLinenumbers,
282              pe->pe_seg[i].NumberOfRelocations,
283              pe->pe_seg[i].NumberOfLinenumbers,
284              pe->pe_seg[i].Characteristics);
285           pe->vma_size = MAX(pe->vma_size,
286                         pe->pe_seg[i].VirtualAddress + 
287                         pe->pe_seg[i].SizeOfRawData);
288     }
289 }
290
291 static void do_relocations(struct pe_data *pe)
292 {
293         int delta = pe->load_addr - pe->base_addr;
294         unsigned int load_addr = pe->load_addr;
295         IMAGE_BASE_RELOCATION   *r = pe->pe_reloc;
296         int hdelta = (delta >> 16) & 0xFFFF;
297         int ldelta = delta & 0xFFFF;
298
299         /* int reloc_size = */
300
301         if(delta == 0)
302                 /* Nothing to do */
303                 return;
304         while(r->VirtualAddress)
305         {
306                 char *page = (char*) RVA(r->VirtualAddress);
307                 int count = (r->SizeOfBlock - 8)/2;
308                 int i;
309                 dprintf_fixup(stddeb, "%x relocations for page %lx\n",
310                         count, r->VirtualAddress);
311                 /* patching in reverse order */
312                 for(i=0;i<count;i++)
313                 {
314                         int offset = r->TypeOffset[i] & 0xFFF;
315                         int type = r->TypeOffset[i] >> 12;
316                         dprintf_fixup(stddeb,"patching %x type %x\n", offset, type);
317                         switch(type)
318                         {
319                         case IMAGE_REL_BASED_ABSOLUTE: break;
320                         case IMAGE_REL_BASED_HIGH:
321                                 *(short*)(page+offset) += hdelta;
322                                 break;
323                         case IMAGE_REL_BASED_LOW:
324                                 *(short*)(page+offset) += ldelta;
325                                 break;
326                         case IMAGE_REL_BASED_HIGHLOW:
327 #if 1
328                                 *(int*)(page+offset) += delta;
329 #else
330                                 { int h=*(unsigned short*)(page+offset);
331                                   int l=r->TypeOffset[++i];
332                                   *(unsigned int*)(page + offset) = (h<<16) + l + delta;
333                                 }
334 #endif
335                                 break;
336                         case IMAGE_REL_BASED_HIGHADJ:
337                                 fprintf(stderr, "Don't know what to do with IMAGE_REL_BASED_HIGHADJ\n");
338                                 break;
339                         case IMAGE_REL_BASED_MIPS_JMPADDR:
340                                 fprintf(stderr, "Is this a MIPS machine ???\n");
341                                 break;
342                         default:
343                                 fprintf(stderr, "Unknown fixup type\n");
344                                 break;
345                         }
346                 }
347                 r = (IMAGE_BASE_RELOCATION*)((char*)r + r->SizeOfBlock);
348         }
349 }
350                 
351
352         
353         
354
355 /**********************************************************************
356  *                      PE_LoadImage
357  * Load one PE format executable into memory
358  */
359 static struct pe_data *PE_LoadImage( int fd, HMODULE16 hModule, WORD offset )
360 {
361         struct pe_data          *pe;
362         int                     i, result;
363         int                     load_addr;
364         IMAGE_DATA_DIRECTORY    dir;
365         char                    buffer[200];
366         DBG_ADDR                daddr;
367
368         daddr.seg=0;
369         daddr.type = NULL;
370         pe = xmalloc(sizeof(struct pe_data));
371         memset(pe,0,sizeof(struct pe_data));
372         pe->pe_header = xmalloc(sizeof(IMAGE_NT_HEADERS));
373
374         /* read PE header */
375         lseek( fd, offset, SEEK_SET);
376         read( fd, pe->pe_header, sizeof(IMAGE_NT_HEADERS));
377
378 /* FIXME: this is a *horrible* hack to make COMDLG32.DLL load OK. The
379 problem needs to be fixed properly at some stage */
380
381         if (pe->pe_header->OptionalHeader.NumberOfRvaAndSizes != 16) {
382                 printf("Short PE Header!!!\n");
383                 lseek( fd, -(16 - pe->pe_header->OptionalHeader.NumberOfRvaAndSizes) * sizeof(IMAGE_DATA_DIRECTORY), SEEK_CUR);
384         }
385
386 /* horrible hack ends !!! */
387         /* read sections */
388         pe->pe_seg = xmalloc(sizeof(IMAGE_SECTION_HEADER) * 
389                                    pe->pe_header->FileHeader.NumberOfSections);
390         read( fd, pe->pe_seg, sizeof(IMAGE_SECTION_HEADER) * 
391                         pe->pe_header->FileHeader.NumberOfSections);
392
393         load_addr = pe->pe_header->OptionalHeader.ImageBase;
394         pe->base_addr=load_addr;
395         pe->vma_size=0;
396         dprintf_win32(stddeb, "Load addr is %x\n",load_addr);
397         calc_vma_size(pe);
398
399 #if 0
400         /* We use malloc here, while a huge part of that address space does
401            not be supported by actual memory. It has to be contiguous, though.
402            I don't know if mmap("/dev/null"); would do any better.
403            What I'd really like to do is a Win32 style VirtualAlloc/MapViewOfFile
404            sequence */
405         load_addr = pe->load_addr = (int)xmalloc(pe->vma_size);
406         memset( load_addr, 0, pe->vma_size);
407 #else
408         load_addr =  pe->load_addr = VirtualAlloc( NULL, pe->vma_size,
409                                                    MEM_COMMIT,
410                                                    PAGE_EXECUTE_READWRITE );
411 #endif
412
413         dprintf_win32(stddeb, "Load addr is really %x, range %x\n",
414                 pe->load_addr, pe->vma_size);
415         
416
417         for(i=0; i < pe->pe_header->FileHeader.NumberOfSections; i++)
418         {
419                 /* load only non-BSS segments */
420                 if(pe->pe_seg[i].Characteristics & 
421                         ~ IMAGE_SCN_CNT_UNINITIALIZED_DATA)
422                 if(lseek(fd,pe->pe_seg[i].PointerToRawData,SEEK_SET) == -1
423                 || read(fd,(char*)RVA(pe->pe_seg[i].VirtualAddress),
424                            pe->pe_seg[i].SizeOfRawData) != pe->pe_seg[i].SizeOfRawData)
425                 {
426                         fprintf(stderr,"Failed to load section %x\n", i);
427                         exit(0);
428                 }
429                 result = RVA (pe->pe_seg[i].VirtualAddress);
430 #if 1
431                 /* not needed, memory is zero */
432                 if(strcmp(pe->pe_seg[i].Name, ".bss") == 0)
433                     memset((void *)result, 0, 
434                            pe->pe_seg[i].Misc.VirtualSize ?
435                            pe->pe_seg[i].Misc.VirtualSize :
436                            pe->pe_seg[i].SizeOfRawData);
437 #endif
438
439                 if(strcmp(pe->pe_seg[i].Name, ".idata") == 0)
440                         pe->pe_import = (LPIMAGE_IMPORT_DESCRIPTOR) result;
441
442                 if(strcmp(pe->pe_seg[i].Name, ".edata") == 0)
443                         pe->pe_export = (LPIMAGE_EXPORT_DIRECTORY) result;
444
445                 if(strcmp(pe->pe_seg[i].Name, ".rsrc") == 0)
446                         pe->pe_resource = (LPIMAGE_RESOURCE_DIRECTORY) result;
447
448                 if(strcmp(pe->pe_seg[i].Name, ".reloc") == 0)
449                         pe->pe_reloc = (LPIMAGE_BASE_RELOCATION) result;
450
451         }
452
453         /* There is word that the actual loader does not care about the
454            section names, and only goes for the DataDirectory */
455         dir=pe->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
456         if(dir.Size)
457         {
458                 if(pe->pe_export && (int)pe->pe_export!=RVA(dir.VirtualAddress))
459                         fprintf(stderr,"wrong export directory??\n");
460                 /* always trust the directory */
461                 pe->pe_export = (LPIMAGE_EXPORT_DIRECTORY) RVA(dir.VirtualAddress);
462         }
463
464         dir=pe->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
465         if(dir.Size)
466         {
467                 if(pe->pe_import && (int)pe->pe_import!=RVA(dir.VirtualAddress))
468                         fprintf(stderr,"wrong import directory??\n");
469                 pe->pe_import = (LPIMAGE_IMPORT_DESCRIPTOR) RVA(dir.VirtualAddress);
470         }
471
472         dir=pe->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
473         if(dir.Size)
474         {
475                 if(pe->pe_resource && (int)pe->pe_resource!=RVA(dir.VirtualAddress))
476                         fprintf(stderr,"wrong resource directory??\n");
477                 pe->pe_resource = (LPIMAGE_RESOURCE_DIRECTORY) RVA(dir.VirtualAddress);
478         }
479
480         if(pe->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size)
481                 dprintf_win32(stdnimp,"Exception directory ignored\n");
482
483         if(pe->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size)
484                 dprintf_win32(stdnimp,"Security directory ignored\n");
485
486
487
488         dir=pe->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
489         if(dir.Size)
490         {
491                 if(pe->pe_reloc && (int)pe->pe_reloc!= RVA(dir.VirtualAddress))
492                         fprintf(stderr,"wrong relocation list??\n");
493                 pe->pe_reloc = (void *) RVA(dir.VirtualAddress);
494         }
495
496         if(pe->pe_header->OptionalHeader.DataDirectory
497                 [IMAGE_DIRECTORY_ENTRY_DEBUG].Size)
498           {
499             DEBUG_RegisterDebugInfo(fd, pe, load_addr, 
500                         pe->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress,
501                         pe->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size);
502           }
503
504         if(pe->pe_header->OptionalHeader.DataDirectory
505                 [IMAGE_DIRECTORY_ENTRY_COPYRIGHT].Size)
506                 dprintf_win32(stdnimp,"Copyright string ignored\n");
507
508         if(pe->pe_header->OptionalHeader.DataDirectory
509                 [IMAGE_DIRECTORY_ENTRY_GLOBALPTR].Size)
510                 dprintf_win32(stdnimp,"Global Pointer (MIPS) ignored\n");
511
512         if(pe->pe_header->OptionalHeader.DataDirectory
513                 [IMAGE_DIRECTORY_ENTRY_TLS].Size)
514                  dprintf_win32(stdnimp,"Thread local storage ignored\n");
515
516         if(pe->pe_header->OptionalHeader.DataDirectory
517                 [IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size)
518                 dprintf_win32(stdnimp,"Load Configuration directory ignored\n");
519
520         if(pe->pe_header->OptionalHeader.DataDirectory
521                 [IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size)
522                 dprintf_win32(stdnimp,"Bound Import directory ignored\n");
523
524         if(pe->pe_header->OptionalHeader.DataDirectory
525                 [IMAGE_DIRECTORY_ENTRY_IAT].Size)
526                 dprintf_win32(stdnimp,"Import Address Table directory ignored\n");
527         if(pe->pe_header->OptionalHeader.DataDirectory[13].Size)
528                 dprintf_win32(stdnimp,"Unknown directory 13 ignored\n");
529         if(pe->pe_header->OptionalHeader.DataDirectory[14].Size)
530                 dprintf_win32(stdnimp,"Unknown directory 14 ignored\n");
531         if(pe->pe_header->OptionalHeader.DataDirectory[15].Size)
532                 dprintf_win32(stdnimp,"Unknown directory 15 ignored\n");
533
534         if(pe->pe_reloc) do_relocations(pe);
535         if(pe->pe_import) fixup_imports(pe, hModule);
536         if(pe->pe_export) dump_exports(pe->pe_export,load_addr);
537                 
538         if (pe->pe_export) {
539                 /* add start of sections as debugsymbols */
540                 for(i=0;i<pe->pe_header->FileHeader.NumberOfSections;i++) {
541                         sprintf(buffer,"%s_%s",
542                                 (char*)RVA(pe->pe_export->Name),
543                                 pe->pe_seg[i].Name
544                         );
545                         daddr.off= RVA(pe->pe_seg[i].VirtualAddress);
546                         DEBUG_AddSymbol(buffer,&daddr, NULL, SYM_WIN32 | SYM_FUNC);
547                 }
548                 /* add entry point */
549                 sprintf(buffer,"%s_EntryPoint",(char*)RVA(pe->pe_export->Name));
550                 daddr.off=RVA(pe->pe_header->OptionalHeader.AddressOfEntryPoint);
551                 DEBUG_AddSymbol(buffer,&daddr, NULL, SYM_WIN32 | SYM_FUNC);
552                 /* add start of DLL */
553                 daddr.off=load_addr;
554                 DEBUG_AddSymbol((char*) RVA(pe->pe_export->Name),&daddr,
555                                 NULL, SYM_WIN32 | SYM_FUNC);
556         }
557         return pe;
558 }
559
560 HINSTANCE16 MODULE_CreateInstance(HMODULE16 hModule,LOADPARAMS *params);
561
562 HINSTANCE16 PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params )
563 {
564     HMODULE16 hModule;
565     HINSTANCE16 hInstance;
566     NE_MODULE *pModule;
567     struct mz_header_s mz_header;
568
569     if ((hModule = MODULE_CreateDummyModule( ofs )) < 32) return hModule;
570     pModule = (NE_MODULE *)GlobalLock16( hModule );
571     pModule->flags = NE_FFLAGS_WIN32;
572
573     lseek( fd, 0, SEEK_SET );
574     read( fd, &mz_header, sizeof(mz_header) );
575
576     pModule->pe_module = PE_LoadImage( fd, hModule, mz_header.ne_offset );
577
578     hInstance = MODULE_CreateInstance( hModule, params );
579
580     if (!(pModule->pe_module->pe_header->FileHeader.Characteristics & IMAGE_FILE_DLL))
581     {
582         TASK_CreateTask( hModule, hInstance, 0,
583                          params->hEnvironment,
584                          (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
585                          *((WORD*)PTR_SEG_TO_LIN(params->showCmd) + 1) );
586     }
587     return hInstance;
588 }
589
590 int PE_UnloadImage( HMODULE16 hModule )
591 {
592         printf("PEunloadImage() called!\n");
593         /* free resources, image, unmap */
594         return 1;
595 }
596
597 static void PE_InitDLL(HMODULE16 hModule)
598 {
599     NE_MODULE *pModule;
600     PE_MODULE *pe;
601     unsigned int load_addr;
602
603     hModule = GetExePtr(hModule);
604     if (!(pModule = MODULE_GetPtr(hModule))) return;
605     if (!(pModule->flags & NE_FFLAGS_WIN32) || !(pe = pModule->pe_module))
606         return;
607
608     /* FIXME: What is the correct value for parameter 3? 
609      *        (the MSDN library JAN96 says 'reserved for future use')
610      */
611         
612     /* Is this a library? And has it got an entrypoint? */
613     if (        (pe->pe_header->FileHeader.Characteristics & IMAGE_FILE_DLL) &&
614                 (pe->pe_header->OptionalHeader.AddressOfEntryPoint)
615     ) {
616         load_addr = pe->load_addr;
617         printf("InitPEDLL() called!\n");
618         CallDLLEntryProc32( 
619             (FARPROC32)RVA(pe->pe_header->OptionalHeader.AddressOfEntryPoint),
620             hModule,
621             DLL_PROCESS_ATTACH,
622             -1
623         );
624     }
625 }
626
627 void PE_InitializeDLLs(HMODULE16 hModule)
628 {
629         NE_MODULE *pModule;
630         HMODULE16 *pDLL;
631         pModule = MODULE_GetPtr( GetExePtr(hModule) );
632         if (pModule->dlls_to_init)
633         {
634                 HGLOBAL16 to_init = pModule->dlls_to_init;
635                 pModule->dlls_to_init = 0;
636                 for (pDLL = (HMODULE16 *)GlobalLock16( to_init ); *pDLL; pDLL++)
637                 {
638                         PE_InitializeDLLs( *pDLL );
639                         PE_InitDLL( *pDLL );
640                 }
641                 GlobalFree16( to_init );
642         }
643         PE_InitDLL( hModule );
644 }
645 #endif /* WINELIB */