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 struct w_files
*wine_files
= NULL
;
38 void my_wcstombs(char * result
, u_short
* source
, int len
)
41 /* this used to be isascii, but see isascii implementation in Linux'
43 if(*source
<255) *result
++ = *source
++;
45 printf("Unable to handle unicode right now\n");
52 char * xmmap(char * vaddr
, unsigned int v_size
, unsigned int r_size
,
53 int prot
, int flags
, int fd
, unsigned int file_offset
)
56 /* .bss has no associated storage in the PE file */
61 fprintf(stderr
,"xmmap: %s line %d doesn't support MAP_ANON\n",__FILE__
, __LINE__
);
65 result
= mmap(vaddr
, v_size
, prot
, flags
, fd
, file_offset
);
66 if((unsigned int) result
!= 0xffffffff) return result
;
68 /* Sigh. Alignment must be wrong for mmap. Do this the hard way. */
69 if(!(flags
& MAP_FIXED
)) {
70 vaddr
= (char *)0x40000000;
74 mmap(vaddr
, v_size
, prot
, MAP_ANONYMOUS
| flags
, 0, 0);
75 lseek(fd
, file_offset
, SEEK_SET
);
76 read(fd
, vaddr
, v_size
);
81 void dump_exports(struct PE_Export_Directory
* pe_exports
, unsigned int load_addr
)
87 u_char
** name
, *ename
;
89 Module
= ((char *) load_addr
) + pe_exports
->Name
;
90 dprintf_win32(stddeb
,"\n*******EXPORT DATA*******\nModule name is %s, %ld functions, %ld names\n",
92 pe_exports
->Number_Of_Functions
,
93 pe_exports
->Number_Of_Names
);
95 ordinal
= (u_short
*) (((char *) load_addr
) + (int) pe_exports
->Address_Of_Name_Ordinals
);
96 function
= (u_long
*) (((char *) load_addr
) + (int) pe_exports
->AddressOfFunctions
);
97 name
= (u_char
**) (((char *) load_addr
) + (int) pe_exports
->AddressOfNames
);
99 dprintf_win32(stddeb
,"%-32s Ordinal Virt Addr\n", "Function Name");
100 for(i
=0; i
< pe_exports
->Number_Of_Functions
; i
++)
102 ename
= (char *) (((char *) load_addr
) + (int) *name
++);
103 dprintf_win32(stddeb
,"%-32s %4d %8.8lx\n", ename
, *ordinal
++, *function
++);
107 DWORD
PE_FindExportedFunction(struct w_files
* wpnt
, char* funcName
)
109 struct PE_Export_Directory
* exports
= wpnt
->pe
->pe_export
;
110 unsigned load_addr
= wpnt
->pe
->load_addr
;
113 u_char
** name
, *ename
;
115 if(!exports
)return 0;
116 ordinal
= (u_short
*) (((char *) load_addr
) + (int) exports
->Address_Of_Name_Ordinals
);
117 function
= (u_long
*) (((char *) load_addr
) + (int) exports
->AddressOfFunctions
);
118 name
= (u_char
**) (((char *) load_addr
) + (int) exports
->AddressOfNames
);
119 for(i
=0; i
<exports
->Number_Of_Functions
; i
++)
121 ename
= (char *) (((char *) load_addr
) + (int) *name
);
122 if(strcmp(ename
,funcName
)==0)
123 return load_addr
+*function
;
131 DWORD
PE_GetProcAddress(HMODULE hModule
, char* function
)
133 struct w_files
*wpnt
;
134 for(wpnt
=wine_files
;wpnt
;wpnt
=wpnt
->next
)
135 if(wpnt
->hModule
==hModule
) break;
137 return PE_FindExportedFunction(wpnt
,function
);
140 void fixup_imports(struct w_files
* wpnt
)
142 struct PE_Import_Directory
* pe_imp
;
144 unsigned int load_addr
= wpnt
->pe
->load_addr
;
149 /* OK, now dump the import list */
150 dprintf_win32(stddeb
, "\nDumping imports list\n");
152 /* first, count the number of imported non-internal modules */
153 pe_imp
= wpnt
->pe
->pe_import
;
154 for(i
=0;pe_imp
->ModuleName
;pe_imp
++)
157 /* Now, allocate memory for dlls_to_init */
158 ne_mod
= GlobalLock(wpnt
->hModule
);
159 ne_mod
->dlls_to_init
= GLOBAL_Alloc(GMEM_ZEROINIT
,(i
+1) * sizeof(HMODULE
),
160 wpnt
->hModule
, FALSE
, FALSE
, FALSE
);
161 mod_ptr
= GlobalLock(ne_mod
->dlls_to_init
);
162 /* load the modules and put their handles into the list */
163 for(i
=0,pe_imp
= wpnt
->pe
->pe_import
;pe_imp
->ModuleName
;pe_imp
++)
165 char *name
= (char*)load_addr
+pe_imp
->ModuleName
;
166 if(RELAY32_GetBuiltinDLL(name
))
168 mod_ptr
[i
] = LoadModule(name
,(LPVOID
)-1);
169 if(mod_ptr
[i
]<=(HMODULE
)32)
171 fprintf(stderr
,"Module %s not found\n",name
);
176 pe_imp
= wpnt
->pe
->pe_import
;
177 while (pe_imp
->ModuleName
)
180 struct pe_import_name
* pe_name
;
181 unsigned int * import_list
, *thunk_list
;
186 Module
= ((char *) load_addr
) + pe_imp
->ModuleName
;
187 dprintf_win32(stddeb
, "%s\n", Module
);
189 c
= strchr(Module
, '.');
193 if(pe_imp
->Import_List
!= 0) { /* original microsoft style */
194 dprintf_win32(stddeb
, "Microsoft style imports used\n");
195 import_list
= (unsigned int *)
196 (((unsigned int) load_addr
) + pe_imp
->Import_List
);
197 thunk_list
= (unsigned int *)
198 (((unsigned int) load_addr
) + pe_imp
->Thunk_List
);
203 pe_name
= (struct pe_import_name
*) ((int) load_addr
+ *import_list
);
204 if((unsigned)pe_name
& 0x80000000)
206 fprintf(stderr
,"Import by ordinal not supported\n");
209 dprintf_win32(stddeb
, "--- %s %s.%d\n", pe_name
->Name
, Module
, pe_name
->Hint
);
210 #ifndef WINELIB /* FIXME: JBP: Should this happen in libwine.a? */
211 /* FIXME: Both calls should be unified into GetProcAddress */
212 *thunk_list
=(unsigned int)RELAY32_GetEntryPoint(Module
,pe_name
->Name
,pe_name
->Hint
);
214 *thunk_list
= WIN32_GetProcAddress(MODULE_FindModule(Module
),
218 fprintf(stderr
,"JBP: Call to RELAY32_GetEntryPoint being ignored.\n");
222 fprintf(stderr
,"No implementation for %s.%d\n",Module
, pe_name
->Hint
);
229 } else { /* Borland style */
230 dprintf_win32(stddeb
, "Borland style imports used\n");
231 thunk_list
= (unsigned int *)
232 (((unsigned int) load_addr
) + pe_imp
->Thunk_List
);
234 pe_name
= (struct pe_import_name
*) ((int) load_addr
+ *thunk_list
);
235 if((unsigned)pe_name
& 0x80000000) {
236 fprintf(stderr
,"Import by ordinal not supported\n");
239 dprintf_win32(stddeb
, "--- %s %s.%d\n", pe_name
->Name
, Module
, pe_name
->Hint
);
240 #ifndef WINELIB /* FIXME: JBP: Should this happen in libwine.a? */
241 /* FIXME: Both calls should be unified into GetProcAddress */
242 *thunk_list
=(unsigned int)RELAY32_GetEntryPoint(Module
,pe_name
->Name
,pe_name
->Hint
);
244 *thunk_list
= WIN32_GetProcAddress(MODULE_FindModule(Module
),
247 fprintf(stderr
,"JBP: Call to RELAY32_GetEntryPoint being ignored.\n");
250 fprintf(stderr
,"No implementation for %s.%d\n",Module
, pe_name
->Hint
);
258 if(fixup_failed
)exit(1);
261 static void calc_vma_size(struct w_files
*wpnt
)
265 dprintf_win32(stddeb
, "Dump of segment table\n");
266 dprintf_win32(stddeb
, " Name VSz Vaddr SzRaw Fileadr *Reloc *Lineum #Reloc #Linum Char\n");
267 for(i
=0; i
< wpnt
->pe
->pe_header
->coff
.NumberOfSections
; i
++)
269 dprintf_win32(stddeb
, "%8s: %4.4lx %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %4.4x %4.4x %8.8lx\n",
270 wpnt
->pe
->pe_seg
[i
].Name
,
271 wpnt
->pe
->pe_seg
[i
].Virtual_Size
,
272 wpnt
->pe
->pe_seg
[i
].Virtual_Address
,
273 wpnt
->pe
->pe_seg
[i
].Size_Of_Raw_Data
,
274 wpnt
->pe
->pe_seg
[i
].PointerToRawData
,
275 wpnt
->pe
->pe_seg
[i
].PointerToRelocations
,
276 wpnt
->pe
->pe_seg
[i
].PointerToLinenumbers
,
277 wpnt
->pe
->pe_seg
[i
].NumberOfRelocations
,
278 wpnt
->pe
->pe_seg
[i
].NumberOfLinenumbers
,
279 wpnt
->pe
->pe_seg
[i
].Characteristics
);
280 wpnt
->pe
->vma_size
= max(wpnt
->pe
->vma_size
,
281 wpnt
->pe
->pe_seg
[i
].Virtual_Address
+
282 wpnt
->pe
->pe_seg
[i
].Size_Of_Raw_Data
);
286 static void do_relocations(struct w_files
*wpnt
)
288 int delta
= wpnt
->pe
->load_addr
- wpnt
->pe
->base_addr
;
289 struct PE_Reloc_Block
*r
= wpnt
->pe
->pe_reloc
;
290 int hdelta
= (delta
>> 16) & 0xFFFF;
291 int ldelta
= delta
& 0xFFFF;
292 /* int reloc_size = */
298 char *page
= (char*)wpnt
->pe
->load_addr
+ r
->PageRVA
;
299 int count
= (r
->BlockSize
- 8)/2;
301 dprintf_fixup(stddeb
, "%x relocations for page %lx\n",
303 /* patching in reverse order */
306 int offset
= r
->Relocations
[i
] & 0xFFF;
307 int type
= r
->Relocations
[i
] >> 12;
308 dprintf_fixup(stddeb
,"patching %x type %x\n", offset
, type
);
311 case IMAGE_REL_BASED_ABSOLUTE
: break;
312 case IMAGE_REL_BASED_HIGH
:
313 *(short*)(page
+offset
) += hdelta
;
315 case IMAGE_REL_BASED_LOW
:
316 *(short*)(page
+offset
) += ldelta
;
318 case IMAGE_REL_BASED_HIGHLOW
:
320 *(int*)(page
+offset
) += delta
;
322 { int h
=*(unsigned short*)(page
+offset
);
323 int l
=r
->Relocations
[++i
];
324 *(unsigned int*)(page
+ offset
) = (h
<<16) + l
+ delta
;
328 case IMAGE_REL_BASED_HIGHADJ
:
329 fprintf(stderr
, "Don't know what to do with IMAGE_REL_BASED_HIGHADJ\n");
331 case IMAGE_REL_BASED_MIPS_JMPADDR
:
332 fprintf(stderr
, "Is this a MIPS machine ???\n");
335 fprintf(stderr
, "Unknown fixup type\n");
339 r
= (struct PE_Reloc_Block
*)((char*)r
+ r
->BlockSize
);
347 /**********************************************************************
349 * Load one PE format executable into memory
351 static HINSTANCE
PE_LoadImage( int fd
, struct w_files
*wpnt
)
354 unsigned int load_addr
;
355 struct Directory dir
;
357 wpnt
->pe
= xmalloc(sizeof(struct pe_data
));
358 memset(wpnt
->pe
,0,sizeof(struct pe_data
));
359 wpnt
->pe
->pe_header
= xmalloc(sizeof(struct pe_header_s
));
362 lseek( fd
, wpnt
->mz_header
->ne_offset
, SEEK_SET
);
363 read( fd
, wpnt
->pe
->pe_header
, sizeof(struct pe_header_s
));
366 wpnt
->pe
->pe_seg
= xmalloc(sizeof(struct pe_segment_table
) *
367 wpnt
->pe
->pe_header
->coff
.NumberOfSections
);
368 read( fd
, wpnt
->pe
->pe_seg
, sizeof(struct pe_segment_table
) *
369 wpnt
->pe
->pe_header
->coff
.NumberOfSections
);
371 load_addr
= wpnt
->pe
->pe_header
->opt_coff
.BaseOfImage
;
372 wpnt
->pe
->base_addr
=load_addr
;
373 wpnt
->pe
->vma_size
=0;
374 dprintf_win32(stddeb
, "Load addr is %x\n",load_addr
);
377 /* We use malloc here, while a huge part of that address space does
378 not be supported by actual memory. It has to be contiguous, though.
379 I don't know if mmap("/dev/null"); would do any better.
380 What I'd really like to do is a Win32 style VirtualAlloc/MapViewOfFile
382 load_addr
= wpnt
->pe
->load_addr
= malloc(wpnt
->pe
->vma_size
);
383 dprintf_win32(stddeb
, "Load addr is really %x, range %x\n",
384 wpnt
->pe
->load_addr
, wpnt
->pe
->vma_size
);
387 for(i
=0; i
< wpnt
->pe
->pe_header
->coff
.NumberOfSections
; i
++)
389 /* load only non-BSS segments */
390 if(wpnt
->pe
->pe_seg
[i
].Characteristics
&
391 ~ IMAGE_SCN_TYPE_CNT_UNINITIALIZED_DATA
)
392 if(lseek(fd
,wpnt
->pe
->pe_seg
[i
].PointerToRawData
,SEEK_SET
) == -1
393 || read(fd
,load_addr
+ wpnt
->pe
->pe_seg
[i
].Virtual_Address
,
394 wpnt
->pe
->pe_seg
[i
].Size_Of_Raw_Data
)
395 != wpnt
->pe
->pe_seg
[i
].Size_Of_Raw_Data
)
397 fprintf(stderr
,"Failed to load section %x\n", i
);
400 result
= load_addr
+ wpnt
->pe
->pe_seg
[i
].Virtual_Address
;
404 result
= (int)xmmap((char *)0, wpnt
->pe
->pe_seg
[i
].Virtual_Size
,
405 wpnt
->pe
->pe_seg
[i
].Size_Of_Raw_Data
, 7,
406 MAP_PRIVATE
, fd
, wpnt
->pe
->pe_seg
[i
].PointerToRawData
);
407 load_addr
= (unsigned int) result
- wpnt
->pe
->pe_seg
[i
].Virtual_Address
;
409 result
= (int)xmmap((char *) load_addr
+ wpnt
->pe
->pe_seg
[i
].Virtual_Address
,
410 wpnt
->pe
->pe_seg
[i
].Virtual_Size
,
411 wpnt
->pe
->pe_seg
[i
].Size_Of_Raw_Data
, 7, MAP_PRIVATE
| MAP_FIXED
,
412 fd
, wpnt
->pe
->pe_seg
[i
].PointerToRawData
);
415 fprintf(stderr
,"Could not load section %x to desired address %lx\n",
416 i
, load_addr
+wpnt
->pe
->pe_seg
[i
].Virtual_Address
);
417 fprintf(stderr
,"Need to implement relocations now\n");
422 if(strcmp(wpnt
->pe
->pe_seg
[i
].Name
, ".bss") == 0)
423 memset((void *)result
, 0,
424 wpnt
->pe
->pe_seg
[i
].Virtual_Size
?
425 wpnt
->pe
->pe_seg
[i
].Virtual_Size
:
426 wpnt
->pe
->pe_seg
[i
].Size_Of_Raw_Data
);
428 if(strcmp(wpnt
->pe
->pe_seg
[i
].Name
, ".idata") == 0)
429 wpnt
->pe
->pe_import
= (struct PE_Import_Directory
*) result
;
431 if(strcmp(wpnt
->pe
->pe_seg
[i
].Name
, ".edata") == 0)
432 wpnt
->pe
->pe_export
= (struct PE_Export_Directory
*) result
;
434 if(strcmp(wpnt
->pe
->pe_seg
[i
].Name
, ".rsrc") == 0) {
435 wpnt
->pe
->pe_resource
= (struct PE_Resource_Directory
*) result
;
437 /* FIXME pe->resource_offset should be deleted from structure if this
438 ifdef doesn't break anything */
439 /* save offset for PE_FindResource */
440 wpnt
->pe
->resource_offset
= wpnt
->pe
->pe_seg
[i
].Virtual_Address
-
441 wpnt
->pe
->pe_seg
[i
].PointerToRawData
;
444 if(strcmp(wpnt
->pe
->pe_seg
[i
].Name
, ".reloc") == 0)
445 wpnt
->pe
->pe_reloc
= (struct PE_Reloc_Block
*) result
;
449 /* There is word that the actual loader does not care about the
450 section names, and only goes for the DataDirectory */
451 dir
=wpnt
->pe
->pe_header
->opt_coff
.DataDirectory
[IMAGE_FILE_EXPORT_DIRECTORY
];
454 if(wpnt
->pe
->pe_export
&&
455 wpnt
->pe
->pe_export
!=load_addr
+dir
.Virtual_address
)
456 fprintf(stderr
,"wrong export directory??\n");
458 wpnt
->pe
->pe_export
= load_addr
+dir
.Virtual_address
;
461 dir
=wpnt
->pe
->pe_header
->opt_coff
.DataDirectory
[IMAGE_FILE_IMPORT_DIRECTORY
];
464 if(wpnt
->pe
->pe_import
&&
465 wpnt
->pe
->pe_import
!=load_addr
+dir
.Virtual_address
)
466 fprintf(stderr
,"wrong export directory??\n");
468 wpnt
->pe
->pe_import
= load_addr
+dir
.Virtual_address
;
471 dir
=wpnt
->pe
->pe_header
->opt_coff
.DataDirectory
[IMAGE_FILE_RESOURCE_DIRECTORY
];
474 if(wpnt
->pe
->pe_resource
&&
475 wpnt
->pe
->pe_resource
!=load_addr
+dir
.Virtual_address
)
476 fprintf(stderr
,"wrong resource directory??\n");
478 wpnt
->pe
->pe_resource
= load_addr
+dir
.Virtual_address
;
481 dir
=wpnt
->pe
->pe_header
->opt_coff
.DataDirectory
[IMAGE_FILE_BASE_RELOCATION_TABLE
];
484 if(wpnt
->pe
->pe_reloc
&&
485 wpnt
->pe
->pe_reloc
!=load_addr
+dir
.Virtual_address
)
486 fprintf(stderr
,"wrong export directory??\n");
488 wpnt
->pe
->pe_reloc
= load_addr
+dir
.Virtual_address
;
491 if(wpnt
->pe
->pe_header
->opt_coff
.DataDirectory
492 [IMAGE_FILE_EXCEPTION_DIRECTORY
].Size
)
493 dprintf_win32(stdnimp
,"Exception directory ignored\n");
495 if(wpnt
->pe
->pe_header
->opt_coff
.DataDirectory
496 [IMAGE_FILE_SECURITY_DIRECTORY
].Size
)
497 dprintf_win32(stdnimp
,"Security directory ignored\n");
499 if(wpnt
->pe
->pe_header
->opt_coff
.DataDirectory
500 [IMAGE_FILE_DEBUG_DIRECTORY
].Size
)
501 dprintf_win32(stdnimp
,"Debug directory ignored\n");
503 if(wpnt
->pe
->pe_header
->opt_coff
.DataDirectory
504 [IMAGE_FILE_DESCRIPTION_STRING
].Size
)
505 dprintf_win32(stdnimp
,"Description string ignored\n");
507 if(wpnt
->pe
->pe_header
->opt_coff
.DataDirectory
508 [IMAGE_FILE_MACHINE_VALUE
].Size
)
509 dprintf_win32(stdnimp
,"Machine Value ignored\n");
511 if(wpnt
->pe
->pe_header
->opt_coff
.DataDirectory
512 [IMAGE_FILE_THREAD_LOCAL_STORAGE
].Size
)
513 dprintf_win32(stdnimp
,"Thread local storage ignored\n");
515 if(wpnt
->pe
->pe_header
->opt_coff
.DataDirectory
516 [IMAGE_FILE_CALLBACK_DIRECTORY
].Size
)
517 dprintf_win32(stdnimp
,"Callback directory ignored\n");
520 if(wpnt
->pe
->pe_import
) fixup_imports(wpnt
);
521 if(wpnt
->pe
->pe_export
) dump_exports(wpnt
->pe
->pe_export
,load_addr
);
522 if(wpnt
->pe
->pe_reloc
) do_relocations(wpnt
);
524 wpnt
->hinstance
= (HINSTANCE
)0x8000;
525 wpnt
->load_addr
= load_addr
;
526 return (wpnt
->hinstance
);
529 HINSTANCE
MODULE_CreateInstance(HMODULE hModule
,LOADPARAMS
*params
);
530 void InitTask(struct sigcontext_struct context
);
532 HINSTANCE
PE_LoadModule(int fd
, OFSTRUCT
*ofs
, LOADPARAMS
* params
)
534 struct w_files
*wpnt
;
537 LOADEDFILEINFO
*pFileInfo
;
538 SEGTABLEENTRY
*pSegment
;
546 wpnt
=xmalloc(sizeof(struct w_files
));
552 lseek(fd
,0,SEEK_SET
);
553 wpnt
->mz_header
=xmalloc(sizeof(struct mz_header_s
));
554 read(fd
,wpnt
->mz_header
,sizeof(struct mz_header_s
));
556 size
=sizeof(NE_MODULE
) +
557 /* loaded file info */
558 sizeof(LOADEDFILEINFO
) + strlen(ofs
->szPathName
) +
559 /* segment table: DS,CS */
560 2 * sizeof(SEGTABLEENTRY
) +
563 /* several empty tables */
566 hModule
= GlobalAlloc( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
567 wpnt
->hModule
=hModule
;
568 if (!hModule
) return (HINSTANCE
)11; /* invalid exe */
570 FarSetOwner( hModule
, hModule
);
572 pModule
= (NE_MODULE
*)GlobalLock(hModule
);
574 /* Set all used entries */
575 pModule
->magic
=PE_SIGNATURE
;
582 /* Who wants to LocalAlloc for a PE Module? */
583 pModule
->heap_size
=0x1000;
584 pModule
->stack_size
=0xF000;
585 pModule
->seg_count
=1;
586 pModule
->modref_count
=0;
587 pModule
->nrname_size
=0;
588 pModule
->seg_table
=sizeof(NE_MODULE
)+
589 sizeof(LOADEDFILEINFO
)+strlen(ofs
->szPathName
);
590 pModule
->fileinfo
=sizeof(NE_MODULE
);
591 pModule
->os_flags
=NE_OSFLAGS_WINDOWS
;
592 pModule
->expected_version
=0x30A;
594 pFileInfo
=(LOADEDFILEINFO
*)(pModule
+ 1);
595 pFileInfo
->length
= sizeof(LOADEDFILEINFO
)+strlen(ofs
->szPathName
)-1;
596 strcpy(pFileInfo
->filename
,ofs
->szPathName
);
598 pSegment
=(SEGTABLEENTRY
*)((char*)pFileInfo
+pFileInfo
->length
+1);
599 pModule
->dgroup_entry
=(int)pSegment
-(int)pModule
;
601 pSegment
->flags
=NE_SEGFLAGS_DATA
;
602 pSegment
->minsize
=0x1000;
605 cts
=(DWORD
)GetWndProcEntry16("Win32CallToStart");
607 pSegment
->selector
=(void*)cts
;
610 pSegment
->selector
=cts
>>16;
611 pModule
->ip
=cts
& 0xFFFF;
615 pStr
=(char*)pSegment
;
616 pModule
->name_table
=(int)pStr
-(int)pModule
;
617 strcpy(pStr
,"\x08W32SXXXX");
620 /* All tables zero terminated */
621 pModule
->res_table
=pModule
->import_table
=pModule
->entry_table
=
622 (int)pStr
-(int)pModule
;
624 MODULE_RegisterModule(hModule
);
626 PE_LoadImage( fd
, wpnt
);
628 pModule
->heap_size
=0x1000;
629 pModule
->stack_size
=0xE000;
631 /* CreateInstance allocates now 64KB */
632 hInstance
=MODULE_CreateInstance(hModule
,NULL
/* FIX: NULL? really? */);
633 wpnt
->hinstance
=hInstance
;
635 if (wpnt
->pe
->pe_export
) {
636 pStr
= ((unsigned char *)(wpnt
->load_addr
))+wpnt
->pe
->pe_export
->Name
;
637 wpnt
->name
= xstrdup(pStr
);
639 wpnt
->name
= xstrdup( ofs
->szPathName
);
642 wpnt
->next
=wine_files
;
645 /* FIXME: Is this really the correct place to initialise the DLL? */
646 if ((wpnt
->pe
->pe_header
->coff
.Characteristics
& IMAGE_FILE_DLL
)) {
649 TASK_CreateTask(hModule
,hInstance
,0,
650 params
->hEnvironment
,(LPSTR
)PTR_SEG_TO_LIN(params
->cmdLine
),
651 *((WORD
*)PTR_SEG_TO_LIN(params
->showCmd
)+1));
656 int USER_InitApp(HINSTANCE hInstance
);
657 void PE_InitTEB(int hTEB
);
659 void PE_Win32CallToStart(struct sigcontext_struct context
)
662 struct w_files
*wpnt
=wine_files
;
663 dprintf_win32(stddeb
,"Going to start Win32 program\n");
665 USER_InitApp(wpnt
->hModule
);
666 fs
=(int)GlobalAlloc(GHND
,0x10000);
668 __asm__
__volatile__("movw %w0,%%fs"::"r" (fs
));
669 ((void(*)())(wpnt
->load_addr
+wpnt
->pe
->pe_header
->opt_coff
.AddressOfEntryPoint
))();
672 int PE_UnloadImage(struct w_files
*wpnt
)
674 printf("PEunloadImage() called!\n");
675 /* free resources, image, unmap */
679 void PE_InitDLL(HMODULE hModule
)
681 struct w_files
*wpnt
;
682 hModule
= GetExePtr(hModule
);
683 for(wpnt
= wine_files
;wpnt
&& wpnt
->hModule
!= hModule
;
684 wpnt
= wpnt
->next
) /*nothing*/;
685 if(!wpnt
|| wpnt
->initialised
)
687 /* FIXME: What are the correct values for parameters 2 and 3? */
689 /* Is this a library? */
690 if (wpnt
->pe
->pe_header
->coff
.Characteristics
& IMAGE_FILE_DLL
) {
691 /* Should call DLLEntryPoint here */
692 printf("InitPEDLL() called!\n");
693 wpnt
->initialised
= 1;
694 ((void(*)())(wpnt
->load_addr
+wpnt
->pe
->pe_header
->opt_coff
.AddressOfEntryPoint
))(wpnt
->hModule
, 0, 0);
699 /* FIXME: This stuff is all on a "well it works" basis. An implementation
700 based on some kind of documentation would be greatly appreciated :-) */
707 struct TEB
*TEBDSAlias
;
712 void PE_InitTEB(int hTEB
)
717 pTask
= (TDB
*)(GlobalLock(GetCurrentTask() & 0xffff));
718 pTEB
= (TEB
*)(PTR_SEG_OFF_TO_LIN(hTEB
, 0));
719 pTEB
->stack
= (void *)(GlobalLock(pTask
->hStack32
));
720 pTEB
->Except
= (void *)(-1);
721 pTEB
->TEBDSAlias
= pTEB
;
722 pTEB
->taskid
= getpid();
725 void PE_InitializeDLLs(HMODULE hModule
)
729 pModule
= (NE_MODULE
*)GlobalLock( GetExePtr(hModule
) );
730 if (pModule
->dlls_to_init
)
732 HANDLE to_init
= pModule
->dlls_to_init
;
733 pModule
->dlls_to_init
= 0;
734 for (pDLL
= (HMODULE
*)GlobalLock( to_init
); *pDLL
; pDLL
++)
736 PE_InitializeDLLs( *pDLL
);
739 GlobalFree( to_init
);
741 PE_InitDLL( hModule
);