3 * Copyright 1994 Eric Youndale & Erik Bos
4 * Copyright 1995 Martin von Löwis
6 * based on Eric Youndale's pe-test and:
8 * ftp.microsoft.com:/pub/developer/MSDN/CD8/PEFILE.ZIP
10 * ftp.microsoft.com:/developr/MSDN/OctCD/PEFILE.ZIP
18 #include <sys/types.h>
32 #include "registers.h"
37 void my_wcstombs(char * result
, u_short
* source
, int len
)
40 /* this used to be isascii, but see isascii implementation in Linux'
42 if(*source
<255) *result
++ = *source
++;
44 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 */
59 #if defined(__svr4__) || defined(_SCO_DS)
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
);
80 void dump_exports(struct PE_Export_Directory
* pe_exports
, unsigned int load_addr
)
86 u_char
** name
, *ename
;
88 Module
= ((char *) load_addr
) + pe_exports
->Name
;
89 dprintf_win32(stddeb
,"\n*******EXPORT DATA*******\nModule name is %s, %ld functions, %ld names\n",
91 pe_exports
->Number_Of_Functions
,
92 pe_exports
->Number_Of_Names
);
94 ordinal
= (u_short
*) (((char *) load_addr
) + (int) pe_exports
->Address_Of_Name_Ordinals
);
95 function
= (u_long
*) (((char *) load_addr
) + (int) pe_exports
->AddressOfFunctions
);
96 name
= (u_char
**) (((char *) load_addr
) + (int) pe_exports
->AddressOfNames
);
98 dprintf_win32(stddeb
,"%-32s Ordinal Virt Addr\n", "Function Name");
99 for(i
=0; i
< pe_exports
->Number_Of_Functions
; i
++)
101 ename
= (char *) (((char *) load_addr
) + (int) *name
++);
102 dprintf_win32(stddeb
,"%-32s %4d %8.8lx\n", ename
, *ordinal
++, *function
++);
106 static DWORD
PE_FindExportedFunction(struct pe_data
*pe
, char* funcName
)
108 struct PE_Export_Directory
* exports
= pe
->pe_export
;
109 unsigned load_addr
= pe
->load_addr
;
112 u_char
** name
, *ename
;
114 if(!exports
)return 0;
115 ordinal
= (u_short
*) (((char *) load_addr
) + (int) exports
->Address_Of_Name_Ordinals
);
116 function
= (u_long
*) (((char *) load_addr
) + (int) exports
->AddressOfFunctions
);
117 name
= (u_char
**) (((char *) load_addr
) + (int) exports
->AddressOfNames
);
118 for(i
=0; i
<exports
->Number_Of_Functions
; i
++)
122 ename
= (char *) (((char *) load_addr
) + (int) *name
);
123 if(strcmp(ename
,funcName
)==0)
124 return load_addr
+*function
;
126 if(funcName
== (int)*ordinal
+ exports
->Base
)
127 return load_addr
+*function
;
136 DWORD
PE_GetProcAddress(HMODULE hModule
, char* function
)
140 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
141 if (!(pModule
->flags
& NE_FFLAGS_WIN32
) || !pModule
->pe_module
) return 0;
142 if (pModule
->flags
& NE_FFLAGS_BUILTIN
)
143 return BUILTIN_GetProcAddress32( pModule
, function
);
144 return PE_FindExportedFunction( pModule
->pe_module
, function
);
147 void fixup_imports(struct pe_data
*pe
, HMODULE hModule
)
149 struct PE_Import_Directory
* pe_imp
;
151 unsigned int load_addr
= pe
->load_addr
;
156 /* OK, now dump the import list */
157 dprintf_win32(stddeb
, "\nDumping imports list\n");
159 /* first, count the number of imported non-internal modules */
160 pe_imp
= pe
->pe_import
;
161 for(i
=0;pe_imp
->ModuleName
;pe_imp
++)
164 /* Now, allocate memory for dlls_to_init */
165 ne_mod
= GlobalLock16(hModule
);
166 ne_mod
->dlls_to_init
= GLOBAL_Alloc(GMEM_ZEROINIT
,(i
+1) * sizeof(HMODULE
),
167 hModule
, FALSE
, FALSE
, FALSE
);
168 mod_ptr
= GlobalLock16(ne_mod
->dlls_to_init
);
169 /* load the modules and put their handles into the list */
170 for(i
=0,pe_imp
= pe
->pe_import
;pe_imp
->ModuleName
;pe_imp
++)
172 char *name
= (char*)load_addr
+pe_imp
->ModuleName
;
173 mod_ptr
[i
] = LoadModule(name
,(LPVOID
)-1);
174 if(mod_ptr
[i
]<=(HMODULE
)32)
176 fprintf(stderr
,"Module %s not found\n",name
);
181 pe_imp
= pe
->pe_import
;
182 while (pe_imp
->ModuleName
)
185 struct pe_import_name
* pe_name
;
186 unsigned int * import_list
, *thunk_list
;
188 Module
= ((char *) load_addr
) + pe_imp
->ModuleName
;
189 dprintf_win32(stddeb
, "%s\n", Module
);
191 if(pe_imp
->Import_List
!= 0) { /* original microsoft style */
192 dprintf_win32(stddeb
, "Microsoft style imports used\n");
193 import_list
= (unsigned int *)
194 (((unsigned int) load_addr
) + pe_imp
->Import_List
);
195 thunk_list
= (unsigned int *)
196 (((unsigned int) load_addr
) + pe_imp
->Thunk_List
);
201 pe_name
= (struct pe_import_name
*) ((int) load_addr
+ ((unsigned)*import_list
& ~0x80000000));
202 if((unsigned)*import_list
& 0x80000000)
204 int ordinal
=*import_list
& (0x80000000-1);
205 dprintf_win32(stddeb
,"--- Ordinal %s,%d\n", Module
, ordinal
);
206 *thunk_list
= WIN32_GetProcAddress(MODULE_FindModule(Module
),
210 fprintf(stderr
,"No implementation for %s.%d\n",Module
,
214 }else{ /* import by name */
215 dprintf_win32(stddeb
, "--- %s %s.%d\n", pe_name
->Name
, Module
, pe_name
->Hint
);
216 #ifndef WINELIB /* FIXME: JBP: Should this happen in libwine.a? */
217 *thunk_list
= WIN32_GetProcAddress(MODULE_FindModule(Module
),
221 fprintf(stderr
,"No implementation for %s.%d(%s)\n",Module
,
222 pe_name
->Hint
, pe_name
->Name
);
227 fprintf(stderr
,"JBP: Call to RELAY32_GetEntryPoint being ignored.\n");
234 } else { /* Borland style */
235 dprintf_win32(stddeb
, "Borland style imports used\n");
236 thunk_list
= (unsigned int *)
237 (((unsigned int) load_addr
) + pe_imp
->Thunk_List
);
239 pe_name
= (struct pe_import_name
*) ((int) load_addr
+ *thunk_list
);
240 if((unsigned)pe_name
& 0x80000000) {
241 fprintf(stderr
,"Import by ordinal not supported\n");
244 dprintf_win32(stddeb
, "--- %s %s.%d\n", pe_name
->Name
, Module
, pe_name
->Hint
);
245 #ifndef WINELIB /* FIXME: JBP: Should this happen in libwine.a? */
246 /* FIXME: Both calls should be unified into GetProcAddress */
247 *thunk_list
= WIN32_GetProcAddress(MODULE_FindModule(Module
),
250 fprintf(stderr
,"JBP: Call to RELAY32_GetEntryPoint being ignored.\n");
253 fprintf(stderr
,"No implementation for %s.%d\n",Module
, pe_name
->Hint
);
261 if(fixup_failed
)exit(1);
264 static void calc_vma_size(struct pe_data
*pe
)
268 dprintf_win32(stddeb
, "Dump of segment table\n");
269 dprintf_win32(stddeb
, " Name VSz Vaddr SzRaw Fileadr *Reloc *Lineum #Reloc #Linum Char\n");
270 for(i
=0; i
< pe
->pe_header
->coff
.NumberOfSections
; i
++)
272 dprintf_win32(stddeb
, "%8s: %4.4lx %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %4.4x %4.4x %8.8lx\n",
274 pe
->pe_seg
[i
].Virtual_Size
,
275 pe
->pe_seg
[i
].Virtual_Address
,
276 pe
->pe_seg
[i
].Size_Of_Raw_Data
,
277 pe
->pe_seg
[i
].PointerToRawData
,
278 pe
->pe_seg
[i
].PointerToRelocations
,
279 pe
->pe_seg
[i
].PointerToLinenumbers
,
280 pe
->pe_seg
[i
].NumberOfRelocations
,
281 pe
->pe_seg
[i
].NumberOfLinenumbers
,
282 pe
->pe_seg
[i
].Characteristics
);
283 pe
->vma_size
= MAX(pe
->vma_size
,
284 pe
->pe_seg
[i
].Virtual_Address
+
285 pe
->pe_seg
[i
].Size_Of_Raw_Data
);
289 static void do_relocations(struct pe_data
*pe
)
291 int delta
= pe
->load_addr
- pe
->base_addr
;
292 struct PE_Reloc_Block
*r
= pe
->pe_reloc
;
293 int hdelta
= (delta
>> 16) & 0xFFFF;
294 int ldelta
= delta
& 0xFFFF;
295 /* int reloc_size = */
301 char *page
= (char*)pe
->load_addr
+ r
->PageRVA
;
302 int count
= (r
->BlockSize
- 8)/2;
304 dprintf_fixup(stddeb
, "%x relocations for page %lx\n",
306 /* patching in reverse order */
309 int offset
= r
->Relocations
[i
] & 0xFFF;
310 int type
= r
->Relocations
[i
] >> 12;
311 dprintf_fixup(stddeb
,"patching %x type %x\n", offset
, type
);
314 case IMAGE_REL_BASED_ABSOLUTE
: break;
315 case IMAGE_REL_BASED_HIGH
:
316 *(short*)(page
+offset
) += hdelta
;
318 case IMAGE_REL_BASED_LOW
:
319 *(short*)(page
+offset
) += ldelta
;
321 case IMAGE_REL_BASED_HIGHLOW
:
323 *(int*)(page
+offset
) += delta
;
325 { int h
=*(unsigned short*)(page
+offset
);
326 int l
=r
->Relocations
[++i
];
327 *(unsigned int*)(page
+ offset
) = (h
<<16) + l
+ delta
;
331 case IMAGE_REL_BASED_HIGHADJ
:
332 fprintf(stderr
, "Don't know what to do with IMAGE_REL_BASED_HIGHADJ\n");
334 case IMAGE_REL_BASED_MIPS_JMPADDR
:
335 fprintf(stderr
, "Is this a MIPS machine ???\n");
338 fprintf(stderr
, "Unknown fixup type\n");
342 r
= (struct PE_Reloc_Block
*)((char*)r
+ r
->BlockSize
);
350 /**********************************************************************
352 * Load one PE format executable into memory
354 static struct pe_data
*PE_LoadImage( int fd
, HMODULE hModule
, WORD offset
)
358 unsigned int load_addr
;
359 struct Directory dir
;
361 pe
= xmalloc(sizeof(struct pe_data
));
362 memset(pe
,0,sizeof(struct pe_data
));
363 pe
->pe_header
= xmalloc(sizeof(struct pe_header_s
));
366 lseek( fd
, offset
, SEEK_SET
);
367 read( fd
, pe
->pe_header
, sizeof(struct pe_header_s
));
370 pe
->pe_seg
= xmalloc(sizeof(struct pe_segment_table
) *
371 pe
->pe_header
->coff
.NumberOfSections
);
372 read( fd
, pe
->pe_seg
, sizeof(struct pe_segment_table
) *
373 pe
->pe_header
->coff
.NumberOfSections
);
375 load_addr
= pe
->pe_header
->opt_coff
.BaseOfImage
;
376 pe
->base_addr
=load_addr
;
378 dprintf_win32(stddeb
, "Load addr is %x\n",load_addr
);
381 /* We use malloc here, while a huge part of that address space does
382 not be supported by actual memory. It has to be contiguous, though.
383 I don't know if mmap("/dev/null"); would do any better.
384 What I'd really like to do is a Win32 style VirtualAlloc/MapViewOfFile
386 load_addr
= pe
->load_addr
= malloc(pe
->vma_size
);
387 dprintf_win32(stddeb
, "Load addr is really %x, range %x\n",
388 pe
->load_addr
, pe
->vma_size
);
391 for(i
=0; i
< pe
->pe_header
->coff
.NumberOfSections
; i
++)
393 /* load only non-BSS segments */
394 if(pe
->pe_seg
[i
].Characteristics
&
395 ~ IMAGE_SCN_TYPE_CNT_UNINITIALIZED_DATA
)
396 if(lseek(fd
,pe
->pe_seg
[i
].PointerToRawData
,SEEK_SET
) == -1
397 || read(fd
,load_addr
+ pe
->pe_seg
[i
].Virtual_Address
,
398 pe
->pe_seg
[i
].Size_Of_Raw_Data
)
399 != pe
->pe_seg
[i
].Size_Of_Raw_Data
)
401 fprintf(stderr
,"Failed to load section %x\n", i
);
404 result
= load_addr
+ pe
->pe_seg
[i
].Virtual_Address
;
408 result
= (int)xmmap((char *)0, pe
->pe_seg
[i
].Virtual_Size
,
409 pe
->pe_seg
[i
].Size_Of_Raw_Data
, 7,
410 MAP_PRIVATE
, fd
, pe
->pe_seg
[i
].PointerToRawData
);
411 load_addr
= (unsigned int) result
- pe
->pe_seg
[i
].Virtual_Address
;
413 result
= (int)xmmap((char *) load_addr
+ pe
->pe_seg
[i
].Virtual_Address
,
414 pe
->pe_seg
[i
].Virtual_Size
,
415 pe
->pe_seg
[i
].Size_Of_Raw_Data
, 7, MAP_PRIVATE
| MAP_FIXED
,
416 fd
, pe
->pe_seg
[i
].PointerToRawData
);
419 fprintf(stderr
,"Could not load section %x to desired address %lx\n",
420 i
, load_addr
+pe
->pe_seg
[i
].Virtual_Address
);
421 fprintf(stderr
,"Need to implement relocations now\n");
426 if(strcmp(pe
->pe_seg
[i
].Name
, ".bss") == 0)
427 memset((void *)result
, 0,
428 pe
->pe_seg
[i
].Virtual_Size
?
429 pe
->pe_seg
[i
].Virtual_Size
:
430 pe
->pe_seg
[i
].Size_Of_Raw_Data
);
432 if(strcmp(pe
->pe_seg
[i
].Name
, ".idata") == 0)
433 pe
->pe_import
= (struct PE_Import_Directory
*) result
;
435 if(strcmp(pe
->pe_seg
[i
].Name
, ".edata") == 0)
436 pe
->pe_export
= (struct PE_Export_Directory
*) result
;
438 if(strcmp(pe
->pe_seg
[i
].Name
, ".rsrc") == 0) {
439 pe
->pe_resource
= (struct PE_Resource_Directory
*) result
;
441 /* FIXME pe->resource_offset should be deleted from structure if this
442 ifdef doesn't break anything */
443 /* save offset for PE_FindResource */
444 pe
->resource_offset
= pe
->pe_seg
[i
].Virtual_Address
-
445 pe
->pe_seg
[i
].PointerToRawData
;
448 if(strcmp(pe
->pe_seg
[i
].Name
, ".reloc") == 0)
449 pe
->pe_reloc
= (struct PE_Reloc_Block
*) result
;
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
->opt_coff
.DataDirectory
[IMAGE_FILE_EXPORT_DIRECTORY
];
459 pe
->pe_export
!=load_addr
+dir
.Virtual_address
)
460 fprintf(stderr
,"wrong export directory??\n");
461 /* always trust the directory */
462 pe
->pe_export
= load_addr
+dir
.Virtual_address
;
465 dir
=pe
->pe_header
->opt_coff
.DataDirectory
[IMAGE_FILE_IMPORT_DIRECTORY
];
469 pe
->pe_import
!=load_addr
+dir
.Virtual_address
)
470 fprintf(stderr
,"wrong import directory??\n");
471 pe
->pe_import
= load_addr
+dir
.Virtual_address
;
474 dir
=pe
->pe_header
->opt_coff
.DataDirectory
[IMAGE_FILE_RESOURCE_DIRECTORY
];
477 if(pe
->pe_resource
&&
478 pe
->pe_resource
!=load_addr
+dir
.Virtual_address
)
479 fprintf(stderr
,"wrong resource directory??\n");
480 pe
->pe_resource
= load_addr
+dir
.Virtual_address
;
483 dir
=pe
->pe_header
->opt_coff
.DataDirectory
[IMAGE_FILE_BASE_RELOCATION_TABLE
];
487 pe
->pe_reloc
!=load_addr
+dir
.Virtual_address
)
488 fprintf(stderr
,"wrong relocation list??\n");
489 pe
->pe_reloc
= load_addr
+dir
.Virtual_address
;
492 if(pe
->pe_header
->opt_coff
.DataDirectory
493 [IMAGE_FILE_EXCEPTION_DIRECTORY
].Size
)
494 dprintf_win32(stdnimp
,"Exception directory ignored\n");
496 if(pe
->pe_header
->opt_coff
.DataDirectory
497 [IMAGE_FILE_SECURITY_DIRECTORY
].Size
)
498 dprintf_win32(stdnimp
,"Security directory ignored\n");
500 if(pe
->pe_header
->opt_coff
.DataDirectory
501 [IMAGE_FILE_DEBUG_DIRECTORY
].Size
)
502 dprintf_win32(stdnimp
,"Debug directory ignored\n");
504 if(pe
->pe_header
->opt_coff
.DataDirectory
505 [IMAGE_FILE_DESCRIPTION_STRING
].Size
)
506 dprintf_win32(stdnimp
,"Description string ignored\n");
508 if(pe
->pe_header
->opt_coff
.DataDirectory
509 [IMAGE_FILE_MACHINE_VALUE
].Size
)
510 dprintf_win32(stdnimp
,"Machine Value ignored\n");
512 if(pe
->pe_header
->opt_coff
.DataDirectory
513 [IMAGE_FILE_THREAD_LOCAL_STORAGE
].Size
)
514 dprintf_win32(stdnimp
,"Thread local storage ignored\n");
516 if(pe
->pe_header
->opt_coff
.DataDirectory
517 [IMAGE_FILE_CALLBACK_DIRECTORY
].Size
)
518 dprintf_win32(stdnimp
,"Callback directory ignored\n");
521 if(pe
->pe_import
) fixup_imports(pe
, hModule
);
522 if(pe
->pe_export
) dump_exports(pe
->pe_export
,load_addr
);
523 if(pe
->pe_reloc
) do_relocations(pe
);
527 HINSTANCE
MODULE_CreateInstance(HMODULE hModule
,LOADPARAMS
*params
);
528 void InitTask(struct sigcontext_struct context
);
530 HINSTANCE
PE_LoadModule( int fd
, OFSTRUCT
*ofs
, LOADPARAMS
* params
)
535 SEGTABLEENTRY
*pSegment
;
540 struct mz_header_s mz_header
;
544 lseek(fd
,0,SEEK_SET
);
545 read( fd
, &mz_header
, sizeof(mz_header
) );
547 of_size
= sizeof(OFSTRUCT
) - sizeof(ofs
->szPathName
)
548 + strlen(ofs
->szPathName
) + 1;
549 size
= sizeof(NE_MODULE
) +
550 /* loaded file info */
552 /* segment table: DS,CS */
553 2 * sizeof(SEGTABLEENTRY
) +
556 /* several empty tables */
559 hModule
= GlobalAlloc16( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
560 if (!hModule
) return (HINSTANCE
)11; /* invalid exe */
562 FarSetOwner( hModule
, hModule
);
564 pModule
= (NE_MODULE
*)GlobalLock16(hModule
);
566 /* Set all used entries */
567 pModule
->magic
=NE_SIGNATURE
;
570 pModule
->flags
=NE_FFLAGS_WIN32
;
574 /* Who wants to LocalAlloc for a PE Module? */
575 pModule
->heap_size
=0x1000;
576 pModule
->stack_size
=0xF000;
577 pModule
->seg_count
=1;
578 pModule
->modref_count
=0;
579 pModule
->nrname_size
=0;
580 pModule
->fileinfo
=sizeof(NE_MODULE
);
581 pModule
->os_flags
=NE_OSFLAGS_WINDOWS
;
582 pModule
->expected_version
=0x30A;
583 pModule
->self
= hModule
;
585 /* Set loaded file information */
586 memcpy( pModule
+ 1, ofs
, of_size
);
587 ((OFSTRUCT
*)(pModule
+1))->cBytes
= of_size
- 1;
589 pSegment
=(SEGTABLEENTRY
*)((char*)(pModule
+ 1) + of_size
);
590 pModule
->seg_table
=pModule
->dgroup_entry
=(int)pSegment
-(int)pModule
;
592 pSegment
->flags
=NE_SEGFLAGS_DATA
;
593 pSegment
->minsize
=0x1000;
596 cts
=(DWORD
)MODULE_GetWndProcEntry16("Win32CallToStart");
598 pSegment
->selector
=(void*)cts
;
601 pSegment
->selector
=cts
>>16;
602 pModule
->ip
=cts
& 0xFFFF;
606 pStr
=(char*)pSegment
;
607 pModule
->name_table
=(int)pStr
-(int)pModule
;
608 strcpy(pStr
,"\x08W32SXXXX");
611 /* All tables zero terminated */
612 pModule
->res_table
=pModule
->import_table
=pModule
->entry_table
=
613 (int)pStr
-(int)pModule
;
615 MODULE_RegisterModule( pModule
);
617 pe
= PE_LoadImage( fd
, hModule
, mz_header
.ne_offset
);
619 pModule
->pe_module
= pe
;
620 pModule
->heap_size
=0x1000;
621 pModule
->stack_size
=0xE000;
623 /* CreateInstance allocates now 64KB */
624 hInstance
=MODULE_CreateInstance(hModule
,NULL
/* FIX: NULL? really? */);
626 /* FIXME: Is this really the correct place to initialise the DLL? */
627 if ((pe
->pe_header
->coff
.Characteristics
& IMAGE_FILE_DLL
)) {
628 /* PE_InitDLL(hModule); */
630 TASK_CreateTask(hModule
,hInstance
,0,
631 params
->hEnvironment
,(LPSTR
)PTR_SEG_TO_LIN(params
->cmdLine
),
632 *((WORD
*)PTR_SEG_TO_LIN(params
->showCmd
)+1));
633 PE_InitializeDLLs(hModule
);
638 int USER_InitApp(HINSTANCE hInstance
);
639 void PE_InitTEB(int hTEB
);
641 void PE_Win32CallToStart(struct sigcontext_struct context
)
647 dprintf_win32(stddeb
,"Going to start Win32 program\n");
649 hModule
= GetExePtr( GetCurrentTask() );
650 pModule
= MODULE_GetPtr( hModule
);
651 USER_InitApp( hModule
);
652 fs
=(int)GlobalAlloc16(GHND
,0x10000);
654 __asm__
__volatile__("movw %w0,%%fs"::"r" (fs
));
655 CallTaskStart32( (FARPROC
)(pModule
->pe_module
->load_addr
+
656 pModule
->pe_module
->pe_header
->opt_coff
.AddressOfEntryPoint
) );
659 int PE_UnloadImage( HMODULE hModule
)
661 printf("PEunloadImage() called!\n");
662 /* free resources, image, unmap */
666 static void PE_InitDLL(HMODULE hModule
)
671 hModule
= GetExePtr(hModule
);
672 if (!(pModule
= MODULE_GetPtr(hModule
))) return;
673 if (!(pModule
->flags
& NE_FFLAGS_WIN32
) || !(pe
= pModule
->pe_module
))
676 /* FIXME: What are the correct values for parameters 2 and 3? */
678 /* Is this a library? */
679 if (pe
->pe_header
->coff
.Characteristics
& IMAGE_FILE_DLL
)
681 printf("InitPEDLL() called!\n");
682 CallDLLEntryProc32( (FARPROC
)(pe
->load_addr
+
683 pe
->pe_header
->opt_coff
.AddressOfEntryPoint
),
689 /* FIXME: This stuff is all on a "well it works" basis. An implementation
690 based on some kind of documentation would be greatly appreciated :-) */
697 struct TEB
*TEBDSAlias
;
702 void PE_InitTEB(int hTEB
)
707 pTask
= (TDB
*)(GlobalLock16(GetCurrentTask() & 0xffff));
708 pTEB
= (TEB
*)(PTR_SEG_OFF_TO_LIN(hTEB
, 0));
709 pTEB
->stack
= (void *)(GlobalLock16(pTask
->hStack32
));
710 pTEB
->Except
= (void *)(-1);
711 pTEB
->TEBDSAlias
= pTEB
;
712 pTEB
->taskid
= getpid();
715 void PE_InitializeDLLs(HMODULE hModule
)
719 pModule
= MODULE_GetPtr( GetExePtr(hModule
) );
720 if (pModule
->dlls_to_init
)
722 HANDLE to_init
= pModule
->dlls_to_init
;
723 pModule
->dlls_to_init
= 0;
724 for (pDLL
= (HMODULE
*)GlobalLock16( to_init
); *pDLL
; pDLL
++)
726 PE_InitializeDLLs( *pDLL
);
729 GlobalFree16( to_init
);
731 PE_InitDLL( hModule
);