3 * Copyright 1994 Eric Youndale & Erik Bos
5 * based on Eric Youndale's pe-test and:
7 * ftp.microsoft.com:/pub/developer/MSDN/CD8/PEFILE.ZIP
9 * ftp.microsoft.com:/developr/MSDN/OctCD/PEFILE.ZIP
17 #include <sys/types.h>
30 #include "registers.h"
31 #include "selectors.h"
36 #define MAP_ANONYMOUS 0x20
38 struct w_files
*wine_files
= NULL
;
40 void my_wcstombs(char * result
, u_short
* source
, int len
)
43 if(isascii(*source
)) *result
++ = *source
++;
45 printf("Unable to handle unicode right now\n");
51 char * xmmap(char * vaddr
, unsigned int v_size
, unsigned int r_size
,
52 int prot
, int flags
, int fd
, unsigned int file_offset
)
55 /* .bss has no associated storage in the PE file */
60 fprintf(stderr
,"xmmap: %s line %d doesn't support MAP_ANON\n",__FILE__
, __LINE__
);
64 result
= mmap(vaddr
, v_size
, prot
, flags
, fd
, file_offset
);
65 if((unsigned int) result
!= 0xffffffff) return result
;
67 /* Sigh. Alignment must be wrong for mmap. Do this the hard way. */
68 if(!(flags
& MAP_FIXED
)) {
69 vaddr
= (char *)0x40000000;
73 mmap(vaddr
, v_size
, prot
, MAP_ANONYMOUS
| flags
, 0, 0);
74 lseek(fd
, file_offset
, SEEK_SET
);
75 read(fd
, vaddr
, v_size
);
79 void dump_exports(struct PE_Export_Directory
* pe_exports
, unsigned int load_addr
)
85 u_char
** name
, *ename
;
87 Module
= ((char *) load_addr
) + pe_exports
->Name
;
88 dprintf_win32(stddeb
,"\n*******EXPORT DATA*******\nModule name is %s, %ld functions, %ld names\n",
90 pe_exports
->Number_Of_Functions
,
91 pe_exports
->Number_Of_Names
);
93 ordinal
= (u_short
*) (((char *) load_addr
) + (int) pe_exports
->Address_Of_Name_Ordinals
);
94 function
= (u_long
*) (((char *) load_addr
) + (int) pe_exports
->AddressOfFunctions
);
95 name
= (u_char
**) (((char *) load_addr
) + (int) pe_exports
->AddressOfNames
);
97 dprintf_win32(stddeb
,"%-32s Ordinal Virt Addr\n", "Function Name");
98 for(i
=0; i
< pe_exports
->Number_Of_Functions
; i
++)
100 ename
= (char *) (((char *) load_addr
) + (int) *name
++);
101 dprintf_win32(stddeb
,"%-32s %4d %8.8lx\n", ename
, *ordinal
++, *function
++);
105 void fixup_imports(struct PE_Import_Directory
*pe_imports
,unsigned int load_addr
)
107 struct PE_Import_Directory
* pe_imp
;
110 /* OK, now dump the import list */
111 dprintf_win32(stddeb
, "\nDumping imports list\n");
113 while (pe_imp
->ModuleName
)
116 struct pe_import_name
* pe_name
;
117 unsigned int * import_list
, *thunk_list
;
122 Module
= ((char *) load_addr
) + pe_imp
->ModuleName
;
123 dprintf_win32(stddeb
, "%s\n", Module
);
125 c
= strchr(Module
, '.');
129 import_list
= (unsigned int *)
130 (((unsigned int) load_addr
) + pe_imp
->Import_List
);
131 thunk_list
= (unsigned int *)
132 (((unsigned int) load_addr
) + pe_imp
->Thunk_List
);
137 pe_name
= (struct pe_import_name
*) ((int) load_addr
+ *import_list
);
138 if((unsigned)pe_name
& 0x80000000)
140 fprintf(stderr
,"Import by ordinal not supported\n");
143 dprintf_win32(stddeb
, "--- %s %s.%d\n", pe_name
->Name
, Module
, pe_name
->Hint
);
144 #ifndef WINELIB /* FIXME: JBP: Should this happen in libwine.a? */
145 *thunk_list
=(unsigned int)RELAY32_GetEntryPoint(Module
,pe_name
->Name
,pe_name
->Hint
);
147 fprintf(stderr
,"JBP: Call to RELAY32_GetEntryPoint being ignored.\n");
151 fprintf(stderr
,"No implementation for %s.%d\n",Module
, pe_name
->Hint
);
160 if(fixup_failed
)exit(1);
163 static void dump_table(struct w_files
*wpnt
)
167 dprintf_win32(stddeb
, "Dump of segment table\n");
168 dprintf_win32(stddeb
, " Name VSz Vaddr SzRaw Fileadr *Reloc *Lineum #Reloc #Linum Char\n");
169 for(i
=0; i
< wpnt
->pe
->pe_header
->coff
.NumberOfSections
; i
++)
171 dprintf_win32(stddeb
, "%8s: %4.4lx %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %4.4x %4.4x %8.8lx\n",
172 wpnt
->pe
->pe_seg
[i
].Name
,
173 wpnt
->pe
->pe_seg
[i
].Virtual_Size
,
174 wpnt
->pe
->pe_seg
[i
].Virtual_Address
,
175 wpnt
->pe
->pe_seg
[i
].Size_Of_Raw_Data
,
176 wpnt
->pe
->pe_seg
[i
].PointerToRawData
,
177 wpnt
->pe
->pe_seg
[i
].PointerToRelocations
,
178 wpnt
->pe
->pe_seg
[i
].PointerToLinenumbers
,
179 wpnt
->pe
->pe_seg
[i
].NumberOfRelocations
,
180 wpnt
->pe
->pe_seg
[i
].NumberOfLinenumbers
,
181 wpnt
->pe
->pe_seg
[i
].Characteristics
);
185 /**********************************************************************
187 * Load one PE format executable into memory
189 HINSTANCE
PE_LoadImage(struct w_files
*wpnt
)
192 unsigned int load_addr
;
194 wpnt
->pe
= xmalloc(sizeof(struct pe_data
));
195 memset(wpnt
->pe
,0,sizeof(struct pe_data
));
196 wpnt
->pe
->pe_header
= xmalloc(sizeof(struct pe_header_s
));
199 lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
, SEEK_SET
);
200 read(wpnt
->fd
, wpnt
->pe
->pe_header
, sizeof(struct pe_header_s
));
203 wpnt
->pe
->pe_seg
= xmalloc(sizeof(struct pe_segment_table
) *
204 wpnt
->pe
->pe_header
->coff
.NumberOfSections
);
205 read(wpnt
->fd
, wpnt
->pe
->pe_seg
, sizeof(struct pe_segment_table
) *
206 wpnt
->pe
->pe_header
->coff
.NumberOfSections
);
208 load_addr
= wpnt
->pe
->pe_header
->opt_coff
.BaseOfImage
;
209 dprintf_win32(stddeb
, "Load addr is %x\n",load_addr
);
212 for(i
=0; i
< wpnt
->pe
->pe_header
->coff
.NumberOfSections
; i
++)
215 result
= (int)xmmap((char *)0, wpnt
->pe
->pe_seg
[i
].Virtual_Size
,
216 wpnt
->pe
->pe_seg
[i
].Size_Of_Raw_Data
, 7,
217 MAP_PRIVATE
, wpnt
->fd
, wpnt
->pe
->pe_seg
[i
].PointerToRawData
);
218 load_addr
= (unsigned int) result
- wpnt
->pe
->pe_seg
[i
].Virtual_Address
;
220 result
= (int)xmmap((char *) load_addr
+ wpnt
->pe
->pe_seg
[i
].Virtual_Address
,
221 wpnt
->pe
->pe_seg
[i
].Virtual_Size
,
222 wpnt
->pe
->pe_seg
[i
].Size_Of_Raw_Data
, 7, MAP_PRIVATE
| MAP_FIXED
,
223 wpnt
->fd
, wpnt
->pe
->pe_seg
[i
].PointerToRawData
);
226 fprintf(stderr
,"Could not load section %x to desired address %lx\n",
227 i
, load_addr
+wpnt
->pe
->pe_seg
[i
].Virtual_Address
);
228 fprintf(stderr
,"Need to implement relocations now\n");
232 if(strcmp(wpnt
->pe
->pe_seg
[i
].Name
, ".idata") == 0)
233 wpnt
->pe
->pe_import
= (struct PE_Import_Directory
*) result
;
235 if(strcmp(wpnt
->pe
->pe_seg
[i
].Name
, ".edata") == 0)
236 wpnt
->pe
->pe_export
= (struct PE_Export_Directory
*) result
;
238 if(strcmp(wpnt
->pe
->pe_seg
[i
].Name
, ".rsrc") == 0) {
239 wpnt
->pe
->pe_resource
= (struct PE_Resource_Directory
*) result
;
241 /* save offset for PE_FindResource */
242 wpnt
->pe
->resource_offset
= wpnt
->pe
->pe_seg
[i
].Virtual_Address
-
243 wpnt
->pe
->pe_seg
[i
].PointerToRawData
;
247 if(wpnt
->pe
->pe_import
) fixup_imports(wpnt
->pe
->pe_import
,load_addr
);
248 if(wpnt
->pe
->pe_export
) dump_exports(wpnt
->pe
->pe_export
,load_addr
);
250 wpnt
->hinstance
= (HINSTANCE
)0x8000;
251 wpnt
->load_addr
= load_addr
;
252 return (wpnt
->hinstance
);
255 HINSTANCE
MODULE_CreateInstance(HMODULE hModule
,LOADPARAMS
*params
);
256 void InitTask(struct sigcontext_struct context
);
258 HINSTANCE
PE_LoadModule(int fd
, OFSTRUCT
*ofs
, LOADPARAMS
* params
)
260 struct w_files
*wpnt
;
263 LOADEDFILEINFO
*pFileInfo
;
264 SEGTABLEENTRY
*pSegment
;
272 wpnt
=xmalloc(sizeof(struct w_files
));
279 lseek(fd
,0,SEEK_SET
);
280 wpnt
->mz_header
=xmalloc(sizeof(struct mz_header_s
));
281 read(fd
,wpnt
->mz_header
,sizeof(struct mz_header_s
));
283 size
=sizeof(NE_MODULE
) +
284 /* loaded file info */
285 sizeof(LOADEDFILEINFO
) + strlen(ofs
->szPathName
) +
286 /* segment table: DS,CS */
287 2 * sizeof(SEGTABLEENTRY
) +
290 /* several empty tables */
293 hModule
= GlobalAlloc( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
294 wpnt
->hModule
=hModule
;
295 if (!hModule
) return (HINSTANCE
)11; /* invalid exe */
297 FarSetOwner( hModule
, hModule
);
299 pModule
= (NE_MODULE
*)GlobalLock(hModule
);
301 /* Set all used entries */
302 pModule
->magic
=PE_SIGNATURE
;
309 /* Who wants to LocalAlloc for a PE Module? */
310 pModule
->heap_size
=0x1000;
311 pModule
->stack_size
=0xF000;
312 pModule
->seg_count
=1;
313 pModule
->modref_count
=0;
314 pModule
->nrname_size
=0;
315 pModule
->seg_table
=sizeof(NE_MODULE
)+
316 sizeof(LOADEDFILEINFO
)+strlen(ofs
->szPathName
);
317 pModule
->fileinfo
=sizeof(NE_MODULE
);
318 pModule
->os_flags
=NE_OSFLAGS_WINDOWS
;
319 pModule
->expected_version
=0x30A;
321 pFileInfo
=(LOADEDFILEINFO
*)(pModule
+ 1);
322 pFileInfo
->length
= sizeof(LOADEDFILEINFO
)+strlen(ofs
->szPathName
)-1;
323 strcpy(pFileInfo
->filename
,ofs
->szPathName
);
325 pSegment
=(SEGTABLEENTRY
*)((char*)pFileInfo
+pFileInfo
->length
+1);
326 pModule
->dgroup_entry
=(int)pSegment
-(int)pModule
;
328 pSegment
->flags
=NE_SEGFLAGS_DATA
;
329 pSegment
->minsize
=0x1000;
332 cts
=(DWORD
)GetWndProcEntry16("Win32CallToStart");
334 pSegment
->selector
=(void*)cts
;
337 pSegment
->selector
=cts
>>16;
338 pModule
->ip
=cts
& 0xFFFF;
342 pStr
=(char*)pSegment
;
343 pModule
->name_table
=(int)pStr
-(int)pModule
;
344 strcpy(pStr
,"\x08W32SXXXX");
347 /* All tables zero terminated */
348 pModule
->res_table
=pModule
->import_table
=pModule
->entry_table
=
349 (int)pStr
-(int)pModule
;
353 pModule
->heap_size
=0x1000;
354 pModule
->stack_size
=0xE000;
356 /* CreateInstance allocates now 64KB */
357 hInstance
=MODULE_CreateInstance(hModule
,NULL
/* FIX: NULL? really? */);
358 wpnt
->hinstance
=hInstance
;
360 if (wpnt
->pe
->pe_export
) {
361 wpnt
->name
= xmalloc(strlen(wpnt
->pe
->pe_export
->ModuleName
)+1);
362 strcpy(wpnt
->name
, wpnt
->pe
->pe_export
->ModuleName
);
364 wpnt
->name
= xmalloc(strlen(ofs
->szPathName
)+1);
365 strcpy(wpnt
->name
, ofs
->szPathName
);
368 wpnt
->next
=wine_files
;
371 if (!(wpnt
->pe
->pe_header
->coff
.Characteristics
& IMAGE_FILE_DLL
))
372 TASK_CreateTask(hModule
,hInstance
,0,
373 params
->hEnvironment
,(LPSTR
)PTR_SEG_TO_LIN(params
->cmdLine
),
374 *((WORD
*)PTR_SEG_TO_LIN(params
->showCmd
)+1));
379 int USER_InitApp(HINSTANCE hInstance
);
381 void PE_Win32CallToStart(struct sigcontext_struct context
)
384 struct w_files
*wpnt
=wine_files
;
385 fs
=(int)GlobalAlloc(GHND
,0x10000);
386 dprintf_win32(stddeb
,"Going to start Win32 program\n");
388 USER_InitApp(wpnt
->hModule
);
389 __asm__
__volatile__("movw %w0,%%fs"::"r" (fs
));
390 ((void(*)())(wpnt
->load_addr
+wpnt
->pe
->pe_header
->opt_coff
.AddressOfEntryPoint
))();
393 int PE_UnloadImage(struct w_files
*wpnt
)
395 printf("PEunloadImage() called!\n");
396 /* free resources, image, unmap */
400 void PE_InitDLL(struct w_files
*wpnt
)
402 /* Is this a library? */
403 if (wpnt
->pe
->pe_header
->coff
.Characteristics
& IMAGE_FILE_DLL
) {
404 printf("InitPEDLL() called!\n");