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>
38 /* convert PE image VirtualAddress to Real Address */
39 #define RVA(x) ((unsigned int)load_addr+(unsigned int)(x))
41 void dump_exports(IMAGE_EXPORT_DIRECTORY
* pe_exports
, unsigned int load_addr
)
46 u_long
*function
,*functions
;
53 Module
= (char*)RVA(pe_exports
->Name
);
54 dprintf_win32(stddeb
,"\n*******EXPORT DATA*******\nModule name is %s, %ld functions, %ld names\n",
56 pe_exports
->NumberOfFunctions
,
57 pe_exports
->NumberOfNames
);
59 ordinal
=(u_short
*) RVA(pe_exports
->AddressOfNameOrdinals
);
60 functions
=function
=(u_long
*) RVA(pe_exports
->AddressOfFunctions
);
61 name
=(u_char
**) RVA(pe_exports
->AddressOfNames
);
63 dprintf_win32(stddeb
,"%-32s Ordinal Virt Addr\n", "Function Name");
64 for (i
=0;i
<pe_exports
->NumberOfFunctions
;i
++) {
65 if (i
<pe_exports
->NumberOfNames
) {
66 ename
=(char*)RVA(*name
++);
67 dprintf_win32(stddeb
,"%-32s %4d %8.8lx (%8.8lx)\n",ename
,*ordinal
,functions
[*ordinal
],*function
);
68 sprintf(buffer
,"%s.%s",Module
,ename
);
69 daddr
.off
=RVA(functions
[*ordinal
]);
73 /* ordinals/names no longer valid, but we still got functions */
74 dprintf_win32(stddeb
,"%-32s %4s %8s %8.8lx\n","","","",*function
);
75 sprintf(buffer
,"%s.%d",Module
,i
);
76 daddr
.off
=RVA(*functions
);
79 DEBUG_AddSymbol(buffer
,&daddr
, NULL
, SYM_WIN32
| SYM_FUNC
);
83 /* Look up the specified function or ordinal in the exportlist:
85 * - look up the name in the Name list.
86 * - look up the ordinal with that index.
87 * - use the ordinal as offset into the functionlist
89 * - use ordinal-pe_export->Base as offset into the functionlist
91 FARPROC32
PE_FindExportedFunction(struct pe_data
*pe
, LPCSTR funcName
)
93 IMAGE_EXPORT_DIRECTORY
* exports
= pe
->pe_export
;
94 unsigned load_addr
= pe
->load_addr
;
97 u_char
** name
, *ename
;
100 if (HIWORD(funcName
))
101 dprintf_win32(stddeb
,"PE_FindExportedFunction(%s)\n",funcName
);
103 dprintf_win32(stddeb
,"PE_FindExportedFunction(%d)\n",(int)funcName
);
106 ordinal
=(u_short
*) RVA(exports
->AddressOfNameOrdinals
);
107 function
=(u_long
*) RVA(exports
->AddressOfFunctions
);
108 name
=(u_char
**) RVA(exports
->AddressOfNames
);
109 if (HIWORD(funcName
)) {
110 for(i
=0; i
<exports
->NumberOfNames
; i
++) {
111 ename
=(char*) RVA(*name
);
112 if(!strcmp(ename
,funcName
))
113 return (FARPROC32
) RVA(function
[*ordinal
]);
118 if (LOWORD(funcName
)-exports
->Base
> exports
->NumberOfFunctions
) {
119 dprintf_win32(stddeb
," ordinal %d out of range!\n",
123 return (FARPROC32
) RVA(function
[(int)funcName
-exports
->Base
]);
129 fixup_imports (struct pe_data
*pe
, HMODULE16 hModule
)
131 IMAGE_IMPORT_DESCRIPTOR
*pe_imp
;
132 int fixup_failed
= 0;
133 unsigned int load_addr
= pe
->load_addr
;
140 modname
= (char*) RVA(pe
->pe_export
->Name
);
142 modname
= "<unknown>";
144 /* OK, now dump the import list */
145 dprintf_win32 (stddeb
, "\nDumping imports list\n");
147 /* first, count the number of imported non-internal modules */
148 pe_imp
= pe
->pe_import
;
150 /* FIXME: should terminate on 0 Characteristics */
151 for (i
= 0; pe_imp
->Name
; pe_imp
++)
154 /* Now, allocate memory for dlls_to_init */
155 ne_mod
= GlobalLock16 (hModule
);
156 ne_mod
->dlls_to_init
= GLOBAL_Alloc(GMEM_ZEROINIT
, (i
+1)*sizeof(HMODULE16
),
157 hModule
, FALSE
, FALSE
, FALSE
);
158 mod_ptr
= GlobalLock16 (ne_mod
->dlls_to_init
);
159 /* load the modules and put their handles into the list */
161 /* FIXME: should terminate on 0 Characteristics */
162 for (i
= 0, pe_imp
= pe
->pe_import
; pe_imp
->Name
; pe_imp
++) {
163 char *name
= (char *) RVA(pe_imp
->Name
);
164 mod_ptr
[i
] = MODULE_Load( name
, (LPVOID
)-1, FALSE
);
165 if (mod_ptr
[i
] <= (HMODULE16
) 32) {
166 char *p
, buffer
[256];
168 /* Try with prepending the path of the current module */
169 GetModuleFileName16 (hModule
, buffer
, sizeof (buffer
));
170 if (!(p
= strrchr (buffer
, '\\')))
172 strcpy (p
+ 1, name
);
173 mod_ptr
[i
] = MODULE_Load( buffer
, (LPVOID
)-1, FALSE
);
175 if (mod_ptr
[i
] <= (HMODULE16
) 32) {
176 fprintf (stderr
, "Module %s not found\n", name
);
181 pe_imp
= pe
->pe_import
;
182 while (pe_imp
->Name
) {
184 IMAGE_IMPORT_BY_NAME
*pe_name
;
185 LPIMAGE_THUNK_DATA import_list
,thunk_list
;
189 Module
= (char *) RVA(pe_imp
->Name
);
190 dprintf_win32 (stddeb
, "%s\n", Module
);
192 if (pe_imp
->u
.OriginalFirstThunk
!= 0) { /* original MS style */
193 dprintf_win32 (stddeb
, "Microsoft style imports used\n");
194 import_list
=(LPIMAGE_THUNK_DATA
) RVA(pe_imp
->u
.OriginalFirstThunk
);
195 thunk_list
= (LPIMAGE_THUNK_DATA
) RVA(pe_imp
->FirstThunk
);
197 while (import_list
->u1
.Ordinal
) {
198 if (IMAGE_SNAP_BY_ORDINAL(import_list
->u1
.Ordinal
)) {
199 int ordinal
= IMAGE_ORDINAL(import_list
->u1
.Ordinal
);
201 if(!lstrncmpi32A(Module
,"kernel32",8) && !ordimportwarned
){
202 fprintf(stderr
,"%s imports kernel32.dll by ordinal. May crash.\n",modname
);
205 dprintf_win32 (stddeb
, "--- Ordinal %s,%d\n", Module
, ordinal
);
206 thunk_list
->u1
.Function
=(LPDWORD
)GetProcAddress32(MODULE_FindModule(Module
),(LPCSTR
)ordinal
);
207 if (!thunk_list
->u1
.Function
) {
208 fprintf(stderr
,"No implementation for %s.%d, setting to NULL\n",
210 /* fixup_failed=1; */
212 } else { /* import by name */
213 pe_name
= (LPIMAGE_IMPORT_BY_NAME
)RVA(import_list
->u1
.AddressOfData
);
214 dprintf_win32 (stddeb
, "--- %s %s.%d\n", pe_name
->Name
, Module
, pe_name
->Hint
);
215 thunk_list
->u1
.Function
=(LPDWORD
)GetProcAddress32(
216 MODULE_FindModule (Module
),
218 if (!thunk_list
->u1
.Function
) {
219 fprintf(stderr
,"No implementation for %s.%d(%s), setting to NULL\n",
220 Module
,pe_name
->Hint
,pe_name
->Name
);
221 /* fixup_failed=1; */
227 } else { /* Borland style */
228 dprintf_win32 (stddeb
, "Borland style imports used\n");
229 thunk_list
= (LPIMAGE_THUNK_DATA
) RVA(pe_imp
->FirstThunk
);
230 while (thunk_list
->u1
.Ordinal
) {
231 if (IMAGE_SNAP_BY_ORDINAL(thunk_list
->u1
.Ordinal
)) {
232 /* not sure about this branch, but it seems to work */
233 int ordinal
= IMAGE_ORDINAL(thunk_list
->u1
.Ordinal
);
236 if (!lstrncmpi32A(Module
,"kernel32",8) &&
239 fprintf(stderr
,"%s imports kernel32.dll by ordinal. May crash.\n",modname
);
242 dprintf_win32(stddeb
,"--- Ordinal %s.%d\n",Module
,ordinal
);
243 thunk_list
->u1
.Function
=(LPDWORD
)GetProcAddress32(MODULE_FindModule(Module
),
245 if (!thunk_list
->u1
.Function
) {
246 fprintf(stderr
, "No implementation for %s.%d, setting to NULL\n",
248 /* fixup_failed=1; */
251 pe_name
=(LPIMAGE_IMPORT_BY_NAME
) RVA(thunk_list
->u1
.AddressOfData
);
252 dprintf_win32(stddeb
,"--- %s %s.%d\n",
253 pe_name
->Name
,Module
,pe_name
->Hint
);
254 thunk_list
->u1
.Function
=(LPDWORD
)GetProcAddress32(MODULE_FindModule(Module
),pe_name
->Name
);
255 if (!thunk_list
->u1
.Function
) {
256 fprintf(stderr
, "No implementation for %s.%d, setting to NULL\n",
257 Module
, pe_name
->Hint
);
258 /* fixup_failed=1; */
266 if (fixup_failed
) exit(1);
269 static void calc_vma_size(struct pe_data
*pe
)
273 dprintf_win32(stddeb
, "Dump of segment table\n");
274 dprintf_win32(stddeb
, " Name VSz Vaddr SzRaw Fileadr *Reloc *Lineum #Reloc #Linum Char\n");
275 for(i
=0; i
< pe
->pe_header
->FileHeader
.NumberOfSections
; i
++)
277 dprintf_win32(stddeb
, "%8s: %4.4lx %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %4.4x %4.4x %8.8lx\n",
279 pe
->pe_seg
[i
].Misc
.VirtualSize
,
280 pe
->pe_seg
[i
].VirtualAddress
,
281 pe
->pe_seg
[i
].SizeOfRawData
,
282 pe
->pe_seg
[i
].PointerToRawData
,
283 pe
->pe_seg
[i
].PointerToRelocations
,
284 pe
->pe_seg
[i
].PointerToLinenumbers
,
285 pe
->pe_seg
[i
].NumberOfRelocations
,
286 pe
->pe_seg
[i
].NumberOfLinenumbers
,
287 pe
->pe_seg
[i
].Characteristics
);
288 pe
->vma_size
= MAX(pe
->vma_size
,
289 pe
->pe_seg
[i
].VirtualAddress
+
290 pe
->pe_seg
[i
].SizeOfRawData
);
294 static void do_relocations(struct pe_data
*pe
)
296 int delta
= pe
->load_addr
- pe
->base_addr
;
297 unsigned int load_addr
= pe
->load_addr
;
298 IMAGE_BASE_RELOCATION
*r
= pe
->pe_reloc
;
299 int hdelta
= (delta
>> 16) & 0xFFFF;
300 int ldelta
= delta
& 0xFFFF;
302 /* int reloc_size = */
307 while(r
->VirtualAddress
)
309 char *page
= (char*) RVA(r
->VirtualAddress
);
310 int count
= (r
->SizeOfBlock
- 8)/2;
312 dprintf_fixup(stddeb
, "%x relocations for page %lx\n",
313 count
, r
->VirtualAddress
);
314 /* patching in reverse order */
317 int offset
= r
->TypeOffset
[i
] & 0xFFF;
318 int type
= r
->TypeOffset
[i
] >> 12;
319 dprintf_fixup(stddeb
,"patching %x type %x\n", offset
, type
);
322 case IMAGE_REL_BASED_ABSOLUTE
: break;
323 case IMAGE_REL_BASED_HIGH
:
324 *(short*)(page
+offset
) += hdelta
;
326 case IMAGE_REL_BASED_LOW
:
327 *(short*)(page
+offset
) += ldelta
;
329 case IMAGE_REL_BASED_HIGHLOW
:
331 *(int*)(page
+offset
) += delta
;
333 { int h
=*(unsigned short*)(page
+offset
);
334 int l
=r
->TypeOffset
[++i
];
335 *(unsigned int*)(page
+ offset
) = (h
<<16) + l
+ delta
;
339 case IMAGE_REL_BASED_HIGHADJ
:
340 fprintf(stderr
, "Don't know what to do with IMAGE_REL_BASED_HIGHADJ\n");
342 case IMAGE_REL_BASED_MIPS_JMPADDR
:
343 fprintf(stderr
, "Is this a MIPS machine ???\n");
346 fprintf(stderr
, "Unknown fixup type\n");
350 r
= (IMAGE_BASE_RELOCATION
*)((char*)r
+ r
->SizeOfBlock
);
358 /**********************************************************************
360 * Load one PE format executable into memory
362 static struct pe_data
*PE_LoadImage( int fd
, HMODULE16 hModule
, WORD offset
)
367 IMAGE_DATA_DIRECTORY dir
;
373 pe
= xmalloc(sizeof(struct pe_data
));
374 memset(pe
,0,sizeof(struct pe_data
));
375 pe
->pe_header
= xmalloc(sizeof(IMAGE_NT_HEADERS
));
378 lseek( fd
, offset
, SEEK_SET
);
379 read( fd
, pe
->pe_header
, sizeof(IMAGE_NT_HEADERS
));
381 /* FIXME: this is a *horrible* hack to make COMDLG32.DLL load OK. The
382 problem needs to be fixed properly at some stage */
384 if (pe
->pe_header
->OptionalHeader
.NumberOfRvaAndSizes
!= 16) {
385 printf("Short PE Header!!!\n");
386 lseek( fd
, -(16 - pe
->pe_header
->OptionalHeader
.NumberOfRvaAndSizes
) * sizeof(IMAGE_DATA_DIRECTORY
), SEEK_CUR
);
389 /* horrible hack ends !!! */
391 pe
->pe_seg
= xmalloc(sizeof(IMAGE_SECTION_HEADER
) *
392 pe
->pe_header
->FileHeader
.NumberOfSections
);
393 read( fd
, pe
->pe_seg
, sizeof(IMAGE_SECTION_HEADER
) *
394 pe
->pe_header
->FileHeader
.NumberOfSections
);
396 load_addr
= pe
->pe_header
->OptionalHeader
.ImageBase
;
397 pe
->base_addr
=load_addr
;
399 dprintf_win32(stddeb
, "Load addr is %x\n",load_addr
);
403 /* We use malloc here, while a huge part of that address space does
404 not be supported by actual memory. It has to be contiguous, though.
405 I don't know if mmap("/dev/null"); would do any better.
406 What I'd really like to do is a Win32 style VirtualAlloc/MapViewOfFile
408 load_addr
= pe
->load_addr
= (int)xmalloc(pe
->vma_size
);
409 memset( load_addr
, 0, pe
->vma_size
);
411 load_addr
= pe
->load_addr
= VirtualAlloc( NULL
, pe
->vma_size
,
413 PAGE_EXECUTE_READWRITE
);
416 dprintf_win32(stddeb
, "Load addr is really %x, range %x\n",
417 pe
->load_addr
, pe
->vma_size
);
420 for(i
=0; i
< pe
->pe_header
->FileHeader
.NumberOfSections
; i
++)
422 /* load only non-BSS segments */
423 if(pe
->pe_seg
[i
].Characteristics
&
424 ~ IMAGE_SCN_CNT_UNINITIALIZED_DATA
)
425 if(lseek(fd
,pe
->pe_seg
[i
].PointerToRawData
,SEEK_SET
) == -1
426 || read(fd
,(char*)RVA(pe
->pe_seg
[i
].VirtualAddress
),
427 pe
->pe_seg
[i
].SizeOfRawData
) != pe
->pe_seg
[i
].SizeOfRawData
)
429 fprintf(stderr
,"Failed to load section %x\n", i
);
432 result
= RVA (pe
->pe_seg
[i
].VirtualAddress
);
434 /* not needed, memory is zero */
435 if(strcmp(pe
->pe_seg
[i
].Name
, ".bss") == 0)
436 memset((void *)result
, 0,
437 pe
->pe_seg
[i
].Misc
.VirtualSize
?
438 pe
->pe_seg
[i
].Misc
.VirtualSize
:
439 pe
->pe_seg
[i
].SizeOfRawData
);
442 if(strcmp(pe
->pe_seg
[i
].Name
, ".idata") == 0)
443 pe
->pe_import
= (LPIMAGE_IMPORT_DESCRIPTOR
) result
;
445 if(strcmp(pe
->pe_seg
[i
].Name
, ".edata") == 0)
446 pe
->pe_export
= (LPIMAGE_EXPORT_DIRECTORY
) result
;
448 if(strcmp(pe
->pe_seg
[i
].Name
, ".rsrc") == 0)
449 pe
->pe_resource
= (LPIMAGE_RESOURCE_DIRECTORY
) result
;
451 if(strcmp(pe
->pe_seg
[i
].Name
, ".reloc") == 0)
452 pe
->pe_reloc
= (LPIMAGE_BASE_RELOCATION
) result
;
456 /* There is word that the actual loader does not care about the
457 section names, and only goes for the DataDirectory */
458 dir
=pe
->pe_header
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
];
461 if(pe
->pe_export
&& (int)pe
->pe_export
!=RVA(dir
.VirtualAddress
))
462 fprintf(stderr
,"wrong export directory??\n");
463 /* always trust the directory */
464 pe
->pe_export
= (LPIMAGE_EXPORT_DIRECTORY
) RVA(dir
.VirtualAddress
);
467 dir
=pe
->pe_header
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
];
470 if(pe
->pe_import
&& (int)pe
->pe_import
!=RVA(dir
.VirtualAddress
))
471 fprintf(stderr
,"wrong import directory??\n");
472 pe
->pe_import
= (LPIMAGE_IMPORT_DESCRIPTOR
) RVA(dir
.VirtualAddress
);
475 dir
=pe
->pe_header
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
];
478 if(pe
->pe_resource
&& (int)pe
->pe_resource
!=RVA(dir
.VirtualAddress
))
479 fprintf(stderr
,"wrong resource directory??\n");
480 pe
->pe_resource
= (LPIMAGE_RESOURCE_DIRECTORY
) RVA(dir
.VirtualAddress
);
483 if(pe
->pe_header
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
)
484 dprintf_win32(stdnimp
,"Exception directory ignored\n");
486 if(pe
->pe_header
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
)
487 dprintf_win32(stdnimp
,"Security directory ignored\n");
491 dir
=pe
->pe_header
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
494 if(pe
->pe_reloc
&& (int)pe
->pe_reloc
!= RVA(dir
.VirtualAddress
))
495 fprintf(stderr
,"wrong relocation list??\n");
496 pe
->pe_reloc
= (void *) RVA(dir
.VirtualAddress
);
499 if(pe
->pe_header
->OptionalHeader
.DataDirectory
500 [IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
)
502 DEBUG_RegisterDebugInfo(fd
, pe
, load_addr
,
503 pe
->pe_header
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
,
504 pe
->pe_header
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
);
507 if(pe
->pe_header
->OptionalHeader
.DataDirectory
508 [IMAGE_DIRECTORY_ENTRY_COPYRIGHT
].Size
)
509 dprintf_win32(stdnimp
,"Copyright string ignored\n");
511 if(pe
->pe_header
->OptionalHeader
.DataDirectory
512 [IMAGE_DIRECTORY_ENTRY_GLOBALPTR
].Size
)
513 dprintf_win32(stdnimp
,"Global Pointer (MIPS) ignored\n");
515 if(pe
->pe_header
->OptionalHeader
.DataDirectory
516 [IMAGE_DIRECTORY_ENTRY_TLS
].Size
)
517 dprintf_win32(stdnimp
,"Thread local storage ignored\n");
519 if(pe
->pe_header
->OptionalHeader
.DataDirectory
520 [IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
].Size
)
521 dprintf_win32(stdnimp
,"Load Configuration directory ignored\n");
523 if(pe
->pe_header
->OptionalHeader
.DataDirectory
524 [IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
].Size
)
525 dprintf_win32(stdnimp
,"Bound Import directory ignored\n");
527 if(pe
->pe_header
->OptionalHeader
.DataDirectory
528 [IMAGE_DIRECTORY_ENTRY_IAT
].Size
)
529 dprintf_win32(stdnimp
,"Import Address Table directory ignored\n");
530 if(pe
->pe_header
->OptionalHeader
.DataDirectory
[13].Size
)
531 dprintf_win32(stdnimp
,"Unknown directory 13 ignored\n");
532 if(pe
->pe_header
->OptionalHeader
.DataDirectory
[14].Size
)
533 dprintf_win32(stdnimp
,"Unknown directory 14 ignored\n");
534 if(pe
->pe_header
->OptionalHeader
.DataDirectory
[15].Size
)
535 dprintf_win32(stdnimp
,"Unknown directory 15 ignored\n");
537 if(pe
->pe_reloc
) do_relocations(pe
);
538 if(pe
->pe_import
) fixup_imports(pe
, hModule
);
539 if(pe
->pe_export
) dump_exports(pe
->pe_export
,load_addr
);
542 /* add start of sections as debugsymbols */
543 for(i
=0;i
<pe
->pe_header
->FileHeader
.NumberOfSections
;i
++) {
544 sprintf(buffer
,"%s.%s",
545 (char*)RVA(pe
->pe_export
->Name
),
548 daddr
.off
= RVA(pe
->pe_seg
[i
].VirtualAddress
);
549 DEBUG_AddSymbol(buffer
,&daddr
, NULL
, SYM_WIN32
| SYM_FUNC
);
551 /* add entry point */
552 sprintf(buffer
,"%s.EntryPoint",(char*)RVA(pe
->pe_export
->Name
));
553 daddr
.off
=RVA(pe
->pe_header
->OptionalHeader
.AddressOfEntryPoint
);
554 DEBUG_AddSymbol(buffer
,&daddr
, NULL
, SYM_WIN32
| SYM_FUNC
);
555 /* add start of DLL */
557 DEBUG_AddSymbol((char*) RVA(pe
->pe_export
->Name
),&daddr
,
558 NULL
, SYM_WIN32
| SYM_FUNC
);
563 HINSTANCE16
MODULE_CreateInstance(HMODULE16 hModule
,LOADPARAMS
*params
);
565 HINSTANCE16
PE_LoadModule( int fd
, OFSTRUCT
*ofs
, LOADPARAMS
* params
)
568 HINSTANCE16 hInstance
;
570 struct mz_header_s mz_header
;
572 if ((hModule
= MODULE_CreateDummyModule( ofs
)) < 32) return hModule
;
573 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
574 pModule
->flags
= NE_FFLAGS_WIN32
;
576 lseek( fd
, 0, SEEK_SET
);
577 read( fd
, &mz_header
, sizeof(mz_header
) );
579 pModule
->pe_module
= PE_LoadImage( fd
, hModule
, mz_header
.ne_offset
);
581 hInstance
= MODULE_CreateInstance( hModule
, params
);
583 if (!(pModule
->pe_module
->pe_header
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
))
585 TASK_CreateTask( hModule
, hInstance
, 0,
586 params
->hEnvironment
,
587 (LPSTR
)PTR_SEG_TO_LIN( params
->cmdLine
),
588 *((WORD
*)PTR_SEG_TO_LIN(params
->showCmd
) + 1) );
593 int PE_UnloadImage( HMODULE16 hModule
)
595 printf("PEunloadImage() called!\n");
596 /* free resources, image, unmap */
600 static void PE_InitDLL(HMODULE16 hModule
)
604 unsigned int load_addr
;
606 hModule
= GetExePtr(hModule
);
607 if (!(pModule
= MODULE_GetPtr(hModule
))) return;
608 if (!(pModule
->flags
& NE_FFLAGS_WIN32
) || !(pe
= pModule
->pe_module
))
611 /* FIXME: What is the correct value for parameter 3?
612 * (the MSDN library JAN96 says 'reserved for future use')
615 /* Is this a library? And has it got an entrypoint? */
616 if ( (pe
->pe_header
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
) &&
617 (pe
->pe_header
->OptionalHeader
.AddressOfEntryPoint
)
619 load_addr
= pe
->load_addr
;
620 printf("InitPEDLL() called!\n");
622 (FARPROC32
)RVA(pe
->pe_header
->OptionalHeader
.AddressOfEntryPoint
),
630 void PE_InitializeDLLs(HMODULE16 hModule
)
634 pModule
= MODULE_GetPtr( GetExePtr(hModule
) );
635 if (pModule
->dlls_to_init
)
637 HGLOBAL16 to_init
= pModule
->dlls_to_init
;
638 pModule
->dlls_to_init
= 0;
639 for (pDLL
= (HMODULE16
*)GlobalLock16( to_init
); *pDLL
; pDLL
++)
641 PE_InitializeDLLs( *pDLL
);
644 GlobalFree16( to_init
);
646 PE_InitDLL( hModule
);