3 * Copyright 1994 Eric Youndale & Erik Bos
4 * Copyright 1995 Martin von Löwis
5 * Copyright 1996 Marcus Meissner
7 * based on Eric Youndale's pe-test and:
9 * ftp.microsoft.com:/pub/developer/MSDN/CD8/PEFILE.ZIP
11 * ftp.microsoft.com:/developr/MSDN/OctCD/PEFILE.ZIP
19 #include <sys/types.h>
31 #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
)
85 u_long
*function
,*functions
;
91 Module
= ((char*)load_addr
)+pe_exports
->Name
;
92 dprintf_win32(stddeb
,"\n*******EXPORT DATA*******\nModule name is %s, %ld functions, %ld names\n",
94 pe_exports
->Number_Of_Functions
,
95 pe_exports
->Number_Of_Names
);
97 ordinal
=(u_short
*)(((char*)load_addr
)+(int)pe_exports
->Address_Of_Name_Ordinals
);
98 functions
=function
=(u_long
*)(((char*)load_addr
)+(int)pe_exports
->AddressOfFunctions
);
99 name
=(u_char
**)(((char*)load_addr
)+(int)pe_exports
->AddressOfNames
);
101 dprintf_win32(stddeb
,"%-32s Ordinal Virt Addr\n", "Function Name");
102 for (i
=0;i
<pe_exports
->Number_Of_Functions
;i
++) {
103 if (i
<pe_exports
->Number_Of_Names
) {
104 ename
=(char*)(((char*)load_addr
)+(int)*name
++);
105 dprintf_win32(stddeb
,"%-32s %4d %8.8lx (%8.8lx)\n",ename
,*ordinal
,functions
[*ordinal
],*function
);
106 sprintf(buffer
,"%s.%s",Module
,ename
);
107 daddr
.off
=load_addr
+functions
[*ordinal
];
111 /* ordinals/names no longer valid, but we still got functions */
112 dprintf_win32(stddeb
,"%-32s %4s %8s %8.8lx\n","","","",*function
);
113 sprintf(buffer
,"%s.%d",Module
,i
);
114 daddr
.off
=load_addr
+*functions
;
117 DEBUG_AddSymbol(buffer
,&daddr
, NULL
);
121 /* Look up the specified function or ordinal in the exportlist:
123 * - look up the name in the Name list.
124 * - look up the ordinal with that index.
125 * - use the ordinal as offset into the functionlist
126 * If it is a ordinal:
127 * - use ordinal-pe_export->Base as offset into the functionlist
129 FARPROC32
PE_FindExportedFunction(struct pe_data
*pe
, LPCSTR funcName
)
131 struct PE_Export_Directory
* exports
= pe
->pe_export
;
132 unsigned load_addr
= pe
->load_addr
;
135 u_char
** name
, *ename
;
138 if (HIWORD(funcName
))
139 dprintf_win32(stddeb
,"PE_FindExportedFunction(%s)\n",funcName
);
141 dprintf_win32(stddeb
,"PE_FindExportedFunction(%d)\n",(int)funcName
);
144 ordinal
=(u_short
*)(((char*)load_addr
)+(int)exports
->Address_Of_Name_Ordinals
);
145 function
=(u_long
*)(((char*)load_addr
)+(int)exports
->AddressOfFunctions
);
146 name
=(u_char
**)(((char*)load_addr
)+(int)exports
->AddressOfNames
);
147 if (HIWORD(funcName
)) {
148 for(i
=0; i
<exports
->Number_Of_Names
; i
++) {
149 ename
=(char*)(((char*)load_addr
)+(int)*name
);
150 if(!strcmp(ename
,funcName
))
151 return (FARPROC32
)(load_addr
+function
[*ordinal
]);
156 if (LOWORD(funcName
)-exports
->Base
> exports
->Number_Of_Functions
) {
157 dprintf_win32(stddeb
," ordinal %d out of range!\n",
161 return (FARPROC32
)(load_addr
+function
[(int)funcName
-exports
->Base
]);
167 fixup_imports (struct pe_data
*pe
, HMODULE16 hModule
)
169 struct PE_Import_Directory
*pe_imp
;
170 int fixup_failed
= 0;
171 unsigned int load_addr
= pe
->load_addr
;
176 /* OK, now dump the import list */
177 dprintf_win32 (stddeb
, "\nDumping imports list\n");
179 /* first, count the number of imported non-internal modules */
180 pe_imp
= pe
->pe_import
;
181 for (i
= 0; pe_imp
->ModuleName
; pe_imp
++)
184 /* Now, allocate memory for dlls_to_init */
185 ne_mod
= GlobalLock16 (hModule
);
186 ne_mod
->dlls_to_init
= GLOBAL_Alloc(GMEM_ZEROINIT
, (i
+1)*sizeof(HMODULE16
),
187 hModule
, FALSE
, FALSE
, FALSE
);
188 mod_ptr
= GlobalLock16 (ne_mod
->dlls_to_init
);
189 /* load the modules and put their handles into the list */
190 for (i
= 0, pe_imp
= pe
->pe_import
; pe_imp
->ModuleName
; pe_imp
++) {
191 char *name
= (char *) load_addr
+ pe_imp
->ModuleName
;
192 mod_ptr
[i
] = LoadModule (name
, (LPVOID
) - 1);
193 if (mod_ptr
[i
] <= (HMODULE16
) 32) {
194 char *p
, buffer
[256];
196 /* Try with prepending the path of the current module */
197 GetModuleFileName16 (hModule
, buffer
, sizeof (buffer
));
198 if (!(p
= strrchr (buffer
, '\\')))
200 strcpy (p
+ 1, name
);
201 mod_ptr
[i
] = LoadModule (buffer
, (LPVOID
) - 1);
203 if (mod_ptr
[i
] <= (HMODULE16
) 32) {
204 fprintf (stderr
, "Module %s not found\n", name
);
209 pe_imp
= pe
->pe_import
;
210 while (pe_imp
->ModuleName
) {
212 struct pe_import_name
*pe_name
;
213 unsigned int *import_list
, *thunk_list
;
215 Module
= ((char *) load_addr
) + pe_imp
->ModuleName
;
216 dprintf_win32 (stddeb
, "%s\n", Module
);
218 if (pe_imp
->Import_List
!= 0) { /* original microsoft style */
219 dprintf_win32 (stddeb
, "Microsoft style imports used\n");
220 import_list
= (unsigned int *)(((unsigned int)load_addr
)+pe_imp
->Import_List
);
221 thunk_list
= (unsigned int *)(((unsigned int)load_addr
)+pe_imp
->Thunk_List
);
223 while (*import_list
) {
224 pe_name
= (struct pe_import_name
*) ((int) load_addr
+ ((unsigned) *import_list
& ~0x80000000));
225 if ((unsigned) *import_list
& 0x80000000) {
226 int ordinal
= *import_list
& (0x80000000 - 1);
227 dprintf_win32 (stddeb
, "--- Ordinal %s,%d\n", Module
, ordinal
);
228 *thunk_list
= (unsigned)GetProcAddress32(MODULE_FindModule (Module
),
231 fprintf(stderr
,"No implementation for %s.%d, setting to NULL\n",
233 /* fixup_failed=1; */
235 } else { /* import by name */
236 dprintf_win32 (stddeb
, "--- %s %s.%d\n", pe_name
->Name
, Module
, pe_name
->Hint
);
237 *thunk_list
= (unsigned)GetProcAddress32(MODULE_FindModule (Module
),
240 fprintf(stderr
, "No implementation for %s.%d(%s), setting to NULL\n",
241 Module
, pe_name
->Hint
, pe_name
->Name
);
242 /* fixup_failed=1; */
248 } else { /* Borland style */
249 dprintf_win32 (stddeb
, "Borland style imports used\n");
250 thunk_list
= (unsigned int *)(((unsigned int)load_addr
)+pe_imp
->Thunk_List
);
251 while (*thunk_list
) {
252 pe_name
=(struct pe_import_name
*)((int)load_addr
+*thunk_list
);
253 if ((unsigned) pe_name
& 0x80000000) {
254 /* not sure about this branch, but it seems to work */
255 int ordinal
= *thunk_list
& ~0x80000000;
256 dprintf_win32(stddeb
,"--- Ordinal %s.%d\n",Module
,ordinal
);
257 *thunk_list
= (unsigned)GetProcAddress32(MODULE_FindModule (Module
),
260 fprintf(stderr
, "No implementation for %s.%d, setting to NULL\n",
262 /* fixup_failed=1; */
265 dprintf_win32(stddeb
,"--- %s %s.%d\n",
266 pe_name
->Name
, Module
, pe_name
->Hint
);
267 *thunk_list
= (unsigned)GetProcAddress32(MODULE_FindModule(Module
),
270 fprintf(stderr
, "No implementation for %s.%d, setting to NULL\n",
271 Module
, pe_name
->Hint
);
272 /* fixup_failed=1; */
280 if (fixup_failed
) exit(1);
283 static void calc_vma_size(struct pe_data
*pe
)
287 dprintf_win32(stddeb
, "Dump of segment table\n");
288 dprintf_win32(stddeb
, " Name VSz Vaddr SzRaw Fileadr *Reloc *Lineum #Reloc #Linum Char\n");
289 for(i
=0; i
< pe
->pe_header
->coff
.NumberOfSections
; i
++)
291 dprintf_win32(stddeb
, "%8s: %4.4lx %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %4.4x %4.4x %8.8lx\n",
293 pe
->pe_seg
[i
].Virtual_Size
,
294 pe
->pe_seg
[i
].Virtual_Address
,
295 pe
->pe_seg
[i
].Size_Of_Raw_Data
,
296 pe
->pe_seg
[i
].PointerToRawData
,
297 pe
->pe_seg
[i
].PointerToRelocations
,
298 pe
->pe_seg
[i
].PointerToLinenumbers
,
299 pe
->pe_seg
[i
].NumberOfRelocations
,
300 pe
->pe_seg
[i
].NumberOfLinenumbers
,
301 pe
->pe_seg
[i
].Characteristics
);
302 pe
->vma_size
= MAX(pe
->vma_size
,
303 pe
->pe_seg
[i
].Virtual_Address
+
304 pe
->pe_seg
[i
].Size_Of_Raw_Data
);
308 static void do_relocations(struct pe_data
*pe
)
310 int delta
= pe
->load_addr
- pe
->base_addr
;
311 struct PE_Reloc_Block
*r
= pe
->pe_reloc
;
312 int hdelta
= (delta
>> 16) & 0xFFFF;
313 int ldelta
= delta
& 0xFFFF;
314 /* int reloc_size = */
320 char *page
= (char*)pe
->load_addr
+ r
->PageRVA
;
321 int count
= (r
->BlockSize
- 8)/2;
323 dprintf_fixup(stddeb
, "%x relocations for page %lx\n",
325 /* patching in reverse order */
328 int offset
= r
->Relocations
[i
] & 0xFFF;
329 int type
= r
->Relocations
[i
] >> 12;
330 dprintf_fixup(stddeb
,"patching %x type %x\n", offset
, type
);
333 case IMAGE_REL_BASED_ABSOLUTE
: break;
334 case IMAGE_REL_BASED_HIGH
:
335 *(short*)(page
+offset
) += hdelta
;
337 case IMAGE_REL_BASED_LOW
:
338 *(short*)(page
+offset
) += ldelta
;
340 case IMAGE_REL_BASED_HIGHLOW
:
342 *(int*)(page
+offset
) += delta
;
344 { int h
=*(unsigned short*)(page
+offset
);
345 int l
=r
->Relocations
[++i
];
346 *(unsigned int*)(page
+ offset
) = (h
<<16) + l
+ delta
;
350 case IMAGE_REL_BASED_HIGHADJ
:
351 fprintf(stderr
, "Don't know what to do with IMAGE_REL_BASED_HIGHADJ\n");
353 case IMAGE_REL_BASED_MIPS_JMPADDR
:
354 fprintf(stderr
, "Is this a MIPS machine ???\n");
357 fprintf(stderr
, "Unknown fixup type\n");
361 r
= (struct PE_Reloc_Block
*)((char*)r
+ r
->BlockSize
);
369 /**********************************************************************
371 * Load one PE format executable into memory
373 static struct pe_data
*PE_LoadImage( int fd
, HMODULE16 hModule
, WORD offset
)
378 struct Directory dir
;
384 pe
= xmalloc(sizeof(struct pe_data
));
385 memset(pe
,0,sizeof(struct pe_data
));
386 pe
->pe_header
= xmalloc(sizeof(struct pe_header_s
));
389 lseek( fd
, offset
, SEEK_SET
);
390 read( fd
, pe
->pe_header
, sizeof(struct pe_header_s
));
392 /* FIXME: this is a *horrible* hack to make COMDLG32.DLL load OK. The
393 problem needs to be fixed properly at some stage */
395 if (pe
->pe_header
->opt_coff
.NumberOfRvaAndSizes
!= 16) {
396 printf("Short PE Header!!!\n");
397 lseek( fd
, -(16 - pe
->pe_header
->opt_coff
.NumberOfRvaAndSizes
) * sizeof (struct Directory
), SEEK_CUR
);
400 /* horrible hack ends !!! */
403 pe
->pe_seg
= xmalloc(sizeof(struct pe_segment_table
) *
404 pe
->pe_header
->coff
.NumberOfSections
);
405 read( fd
, pe
->pe_seg
, sizeof(struct pe_segment_table
) *
406 pe
->pe_header
->coff
.NumberOfSections
);
408 load_addr
= pe
->pe_header
->opt_coff
.BaseOfImage
;
409 pe
->base_addr
=load_addr
;
411 dprintf_win32(stddeb
, "Load addr is %x\n",load_addr
);
414 /* We use malloc here, while a huge part of that address space does
415 not be supported by actual memory. It has to be contiguous, though.
416 I don't know if mmap("/dev/null"); would do any better.
417 What I'd really like to do is a Win32 style VirtualAlloc/MapViewOfFile
419 load_addr
= pe
->load_addr
= (int)xmalloc(pe
->vma_size
);
420 dprintf_win32(stddeb
, "Load addr is really %x, range %x\n",
421 pe
->load_addr
, pe
->vma_size
);
424 for(i
=0; i
< pe
->pe_header
->coff
.NumberOfSections
; i
++)
426 /* load only non-BSS segments */
427 if(pe
->pe_seg
[i
].Characteristics
&
428 ~ IMAGE_SCN_TYPE_CNT_UNINITIALIZED_DATA
)
429 if(lseek(fd
,pe
->pe_seg
[i
].PointerToRawData
,SEEK_SET
) == -1
430 || read(fd
,(char *)load_addr
+ pe
->pe_seg
[i
].Virtual_Address
,
431 pe
->pe_seg
[i
].Size_Of_Raw_Data
)
432 != pe
->pe_seg
[i
].Size_Of_Raw_Data
)
434 fprintf(stderr
,"Failed to load section %x\n", i
);
437 result
= load_addr
+ pe
->pe_seg
[i
].Virtual_Address
;
441 result
= (int)xmmap((char *)0, pe
->pe_seg
[i
].Virtual_Size
,
442 pe
->pe_seg
[i
].Size_Of_Raw_Data
, 7,
443 MAP_PRIVATE
, fd
, pe
->pe_seg
[i
].PointerToRawData
);
444 load_addr
= (unsigned int) result
- pe
->pe_seg
[i
].Virtual_Address
;
446 result
= (int)xmmap((char *) load_addr
+ pe
->pe_seg
[i
].Virtual_Address
,
447 pe
->pe_seg
[i
].Virtual_Size
,
448 pe
->pe_seg
[i
].Size_Of_Raw_Data
, 7, MAP_PRIVATE
| MAP_FIXED
,
449 fd
, pe
->pe_seg
[i
].PointerToRawData
);
452 fprintf(stderr
,"Could not load section %x to desired address %lx\n",
453 i
, load_addr
+pe
->pe_seg
[i
].Virtual_Address
);
454 fprintf(stderr
,"Need to implement relocations now\n");
459 if(strcmp(pe
->pe_seg
[i
].Name
, ".bss") == 0)
460 memset((void *)result
, 0,
461 pe
->pe_seg
[i
].Virtual_Size
?
462 pe
->pe_seg
[i
].Virtual_Size
:
463 pe
->pe_seg
[i
].Size_Of_Raw_Data
);
465 if(strcmp(pe
->pe_seg
[i
].Name
, ".idata") == 0)
466 pe
->pe_import
= (struct PE_Import_Directory
*) result
;
468 if(strcmp(pe
->pe_seg
[i
].Name
, ".edata") == 0)
469 pe
->pe_export
= (struct PE_Export_Directory
*) result
;
471 if(strcmp(pe
->pe_seg
[i
].Name
, ".rsrc") == 0)
472 pe
->pe_resource
= (struct PE_Resource_Directory
*) result
;
474 if(strcmp(pe
->pe_seg
[i
].Name
, ".reloc") == 0)
475 pe
->pe_reloc
= (struct PE_Reloc_Block
*) result
;
479 /* There is word that the actual loader does not care about the
480 section names, and only goes for the DataDirectory */
481 dir
=pe
->pe_header
->opt_coff
.DataDirectory
[IMAGE_FILE_EXPORT_DIRECTORY
];
485 (int)pe
->pe_export
!=load_addr
+dir
.Virtual_address
)
486 fprintf(stderr
,"wrong export directory??\n");
487 /* always trust the directory */
488 pe
->pe_export
= (void *)(load_addr
+dir
.Virtual_address
);
491 dir
=pe
->pe_header
->opt_coff
.DataDirectory
[IMAGE_FILE_IMPORT_DIRECTORY
];
495 (int)pe
->pe_import
!=load_addr
+dir
.Virtual_address
)
496 fprintf(stderr
,"wrong import directory??\n");
497 pe
->pe_import
= (void *)(load_addr
+dir
.Virtual_address
);
500 dir
=pe
->pe_header
->opt_coff
.DataDirectory
[IMAGE_FILE_RESOURCE_DIRECTORY
];
503 if(pe
->pe_resource
&&
504 (int)pe
->pe_resource
!=load_addr
+dir
.Virtual_address
)
505 fprintf(stderr
,"wrong resource directory??\n");
506 pe
->pe_resource
= (void *)(load_addr
+dir
.Virtual_address
);
509 dir
=pe
->pe_header
->opt_coff
.DataDirectory
[IMAGE_FILE_BASE_RELOCATION_TABLE
];
513 (int)pe
->pe_reloc
!=load_addr
+dir
.Virtual_address
)
514 fprintf(stderr
,"wrong relocation list??\n");
515 pe
->pe_reloc
= (void *)(load_addr
+dir
.Virtual_address
);
518 if(pe
->pe_header
->opt_coff
.DataDirectory
519 [IMAGE_FILE_EXCEPTION_DIRECTORY
].Size
)
520 dprintf_win32(stdnimp
,"Exception directory ignored\n");
522 if(pe
->pe_header
->opt_coff
.DataDirectory
523 [IMAGE_FILE_SECURITY_DIRECTORY
].Size
)
524 dprintf_win32(stdnimp
,"Security directory ignored\n");
526 if(pe
->pe_header
->opt_coff
.DataDirectory
527 [IMAGE_FILE_DEBUG_DIRECTORY
].Size
)
529 DEBUG_RegisterDebugInfo(fd
, pe
, load_addr
,
530 pe
->pe_header
->opt_coff
.DataDirectory
[IMAGE_FILE_DEBUG_DIRECTORY
].Virtual_address
,
531 pe
->pe_header
->opt_coff
.DataDirectory
[IMAGE_FILE_DEBUG_DIRECTORY
].Size
);
534 if(pe
->pe_header
->opt_coff
.DataDirectory
535 [IMAGE_FILE_DESCRIPTION_STRING
].Size
)
536 dprintf_win32(stdnimp
,"Description string ignored\n");
538 if(pe
->pe_header
->opt_coff
.DataDirectory
539 [IMAGE_FILE_MACHINE_VALUE
].Size
)
540 dprintf_win32(stdnimp
,"Machine Value ignored\n");
542 if(pe
->pe_header
->opt_coff
.DataDirectory
543 [IMAGE_FILE_THREAD_LOCAL_STORAGE
].Size
)
544 dprintf_win32(stdnimp
,"Thread local storage ignored\n");
546 if(pe
->pe_header
->opt_coff
.DataDirectory
547 [IMAGE_FILE_CALLBACK_DIRECTORY
].Size
)
548 dprintf_win32(stdnimp
,"Callback directory ignored\n");
551 if(pe
->pe_reloc
) do_relocations(pe
);
552 if(pe
->pe_import
) fixup_imports(pe
, hModule
);
553 if(pe
->pe_export
) dump_exports(pe
->pe_export
,load_addr
);
556 /* add start of sections as debugsymbols */
557 for(i
=0;i
<pe
->pe_header
->coff
.NumberOfSections
;i
++) {
558 sprintf(buffer
,"%s.%s",
559 ((char*)load_addr
)+pe
->pe_export
->Name
,
562 daddr
.off
=load_addr
+pe
->pe_seg
[i
].Virtual_Address
;
563 DEBUG_AddSymbol(buffer
,&daddr
, NULL
);
565 /* add entry point */
566 sprintf(buffer
,"%s.EntryPoint",((char*)load_addr
)+pe
->pe_export
->Name
);
567 daddr
.off
=load_addr
+pe
->pe_header
->opt_coff
.AddressOfEntryPoint
;
568 DEBUG_AddSymbol(buffer
,&daddr
, NULL
);
569 /* add start of DLL */
571 DEBUG_AddSymbol(((char*)load_addr
)+pe
->pe_export
->Name
,&daddr
,
577 HINSTANCE16
MODULE_CreateInstance(HMODULE16 hModule
,LOADPARAMS
*params
);
578 void InitTask( SIGCONTEXT
*context
);
580 HINSTANCE16
PE_LoadModule( int fd
, OFSTRUCT
*ofs
, LOADPARAMS
* params
)
583 HINSTANCE16 hInstance
;
585 struct mz_header_s mz_header
;
587 if ((hModule
= MODULE_CreateDummyModule( ofs
)) < 32) return hModule
;
588 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
589 pModule
->flags
= NE_FFLAGS_WIN32
;
591 lseek( fd
, 0, SEEK_SET
);
592 read( fd
, &mz_header
, sizeof(mz_header
) );
594 pModule
->pe_module
= PE_LoadImage( fd
, hModule
, mz_header
.ne_offset
);
596 hInstance
= MODULE_CreateInstance( hModule
, params
);
598 if (!(pModule
->pe_module
->pe_header
->coff
.Characteristics
& IMAGE_FILE_DLL
))
600 TASK_CreateTask( hModule
, hInstance
, 0,
601 params
->hEnvironment
,
602 (LPSTR
)PTR_SEG_TO_LIN( params
->cmdLine
),
603 *((WORD
*)PTR_SEG_TO_LIN(params
->showCmd
) + 1) );
608 int PE_UnloadImage( HMODULE16 hModule
)
610 printf("PEunloadImage() called!\n");
611 /* free resources, image, unmap */
615 static void PE_InitDLL(HMODULE16 hModule
)
620 hModule
= GetExePtr(hModule
);
621 if (!(pModule
= MODULE_GetPtr(hModule
))) return;
622 if (!(pModule
->flags
& NE_FFLAGS_WIN32
) || !(pe
= pModule
->pe_module
))
625 /* FIXME: What is the correct value for parameter 3?
626 * (the MSDN library JAN96 says 'reserved for future use')
629 /* Is this a library? */
630 if (pe
->pe_header
->coff
.Characteristics
& IMAGE_FILE_DLL
)
632 printf("InitPEDLL() called!\n");
633 CallDLLEntryProc32( (FARPROC32
)(pe
->load_addr
+
634 pe
->pe_header
->opt_coff
.AddressOfEntryPoint
),
635 hModule
, DLL_PROCESS_ATTACH
, -1 );
640 /* FIXME: This stuff is all on a "well it works" basis. An implementation
641 based on some kind of documentation would be greatly appreciated :-) */
645 void *Except
; /* 00 */
646 void *stack
; /* 04 */
647 int dummy1
[4]; /* 08 */
648 struct _TEB
*TEBDSAlias
; /* 18 */
649 int dummy2
[2]; /* 1C */
651 int dummy3
[2]; /* 28 */
652 LPBYTE process
; /* 30 */ /* points to current process struct */
655 /* the current process structure. Only the processheap is of interest (off 0x18) */
658 HANDLE32 procheap
; /* 18: Process Heap */
661 void PE_InitTEB(int hTEB
)
666 pTask
= (TDB
*)(GlobalLock16(GetCurrentTask() & 0xffff));
667 pTEB
= (TEB
*)(GlobalLock16(hTEB
));
668 pTEB
->stack
= (void *)pTask
->esp
;
669 pTEB
->Except
= (void *)(-1);
670 pTEB
->TEBDSAlias
= pTEB
;
671 pTEB
->taskid
= getpid();
673 dummyprocess
.procheap
= GetProcessHeap();
674 pTEB
->process
= &dummyprocess
;
678 NtCurrentTeb(CONTEXT
*context
) {
679 context
->Eax
= GlobalLock16(LOWORD(context
->SegFs
));
682 void PE_InitializeDLLs(HMODULE16 hModule
)
686 pModule
= MODULE_GetPtr( GetExePtr(hModule
) );
687 if (pModule
->dlls_to_init
)
689 HGLOBAL16 to_init
= pModule
->dlls_to_init
;
690 pModule
->dlls_to_init
= 0;
691 for (pDLL
= (HMODULE16
*)GlobalLock16( to_init
); *pDLL
; pDLL
++)
693 PE_InitializeDLLs( *pDLL
);
696 GlobalFree16( to_init
);
698 PE_InitDLL( hModule
);