4 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
22 #include "registers.h"
23 #include "stackframe.h"
30 extern HINSTANCE
PE_LoadModule( int fd
, OFSTRUCT
*ofs
, LOADPARAMS
* params
);
32 static HMODULE16 hFirstModule
= 0;
33 static HMODULE16 hCachedModule
= 0; /* Module cached by MODULE_OpenFile */
36 static HANDLE hInitialStack32
= 0;
40 /***********************************************************************
43 NE_MODULE
*MODULE_GetPtr( HMODULE16 hModule
)
45 NE_MODULE
*pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
46 if (!pModule
|| (pModule
->magic
!= NE_SIGNATURE
) ||
47 (pModule
->self
!= hModule
)) return NULL
;
52 /***********************************************************************
55 void MODULE_DumpModule( HMODULE16 hmodule
)
63 if (!(pModule
= MODULE_GetPtr( hmodule
)))
65 fprintf( stderr
, "**** %04x is not a module handle\n", hmodule
);
69 /* Dump the module info */
71 printf( "Module %04x:\n", hmodule
);
72 printf( "count=%d flags=%04x heap=%d stack=%d\n",
73 pModule
->count
, pModule
->flags
,
74 pModule
->heap_size
, pModule
->stack_size
);
75 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
76 pModule
->cs
, pModule
->ip
, pModule
->ss
, pModule
->sp
, pModule
->dgroup
,
77 pModule
->seg_count
, pModule
->modref_count
);
78 printf( "os_flags=%d swap_area=%d version=%04x\n",
79 pModule
->os_flags
, pModule
->min_swap_area
,
80 pModule
->expected_version
);
81 if (pModule
->flags
& NE_FFLAGS_WIN32
)
82 printf( "PE module=%08x\n", (unsigned int)pModule
->pe_module
);
84 /* Dump the file info */
86 printf( "Filename: '%s'\n", NE_MODULE_NAME(pModule
) );
88 /* Dump the segment table */
90 printf( "\nSegment table:\n" );
91 pSeg
= NE_SEG_TABLE( pModule
);
92 for (i
= 0; i
< pModule
->seg_count
; i
++, pSeg
++)
93 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
94 i
+ 1, pSeg
->filepos
, pSeg
->size
, pSeg
->flags
,
95 pSeg
->minsize
, pSeg
->selector
);
97 /* Dump the resource table */
99 printf( "\nResource table:\n" );
100 if (pModule
->res_table
)
102 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->res_table
);
103 printf( "Alignment: %d\n", *pword
++ );
106 struct resource_typeinfo_s
*ptr
= (struct resource_typeinfo_s
*)pword
;
107 struct resource_nameinfo_s
*pname
= (struct resource_nameinfo_s
*)(ptr
+ 1);
108 printf( "id=%04x count=%d\n", ptr
->type_id
, ptr
->count
);
109 for (i
= 0; i
< ptr
->count
; i
++, pname
++)
110 printf( "offset=%d len=%d id=%04x\n",
111 pname
->offset
, pname
->length
, pname
->id
);
112 pword
= (WORD
*)pname
;
115 else printf( "None\n" );
117 /* Dump the resident name table */
119 printf( "\nResident-name table:\n" );
120 pstr
= (char *)pModule
+ pModule
->name_table
;
123 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
124 *(WORD
*)(pstr
+ *pstr
+ 1) );
125 pstr
+= *pstr
+ 1 + sizeof(WORD
);
128 /* Dump the module reference table */
130 printf( "\nModule ref table:\n" );
131 if (pModule
->modref_table
)
133 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->modref_table
);
134 for (i
= 0; i
< pModule
->modref_count
; i
++, pword
++)
136 printf( "%d: %04x -> '%s'\n", i
, *pword
,
137 MODULE_GetModuleName(*pword
));
140 else printf( "None\n" );
142 /* Dump the entry table */
144 printf( "\nEntry table:\n" );
145 pstr
= (char *)pModule
+ pModule
->entry_table
;
149 printf( "Bundle %d-%d: %02x\n", ordinal
, ordinal
+ *pstr
- 1, pstr
[1]);
155 else if ((BYTE
)pstr
[1] == 0xff) /* moveable */
157 struct entry_tab_movable_s
*pe
= (struct entry_tab_movable_s
*)(pstr
+2);
158 for (i
= 0; i
< *pstr
; i
++, pe
++)
159 printf( "%d: %02x:%04x (moveable)\n",
160 ordinal
++, pe
->seg_number
, pe
->offset
);
165 struct entry_tab_fixed_s
*pe
= (struct entry_tab_fixed_s
*)(pstr
+2);
166 for (i
= 0; i
< *pstr
; i
++, pe
++)
167 printf( "%d: %04x (fixed)\n",
168 ordinal
++, pe
->offset
[0] + (pe
->offset
[1] << 8) );
173 /* Dump the non-resident names table */
175 printf( "\nNon-resident names table:\n" );
176 if (pModule
->nrname_handle
)
178 pstr
= (char *)GlobalLock16( pModule
->nrname_handle
);
181 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
182 *(WORD
*)(pstr
+ *pstr
+ 1) );
183 pstr
+= *pstr
+ 1 + sizeof(WORD
);
190 /***********************************************************************
193 * Walk the module list and print the modules.
195 void MODULE_WalkModules(void)
197 HMODULE16 hModule
= hFirstModule
;
198 fprintf( stderr
, "Module Flags Name\n" );
201 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
204 fprintf( stderr
, "**** Bad module %04x in list\n", hModule
);
207 fprintf( stderr
, " %04x %04x %.*s\n", hModule
, pModule
->flags
,
208 *((char *)pModule
+ pModule
->name_table
),
209 (char *)pModule
+ pModule
->name_table
+ 1 );
210 hModule
= pModule
->next
;
215 /***********************************************************************
218 int MODULE_OpenFile( HMODULE16 hModule
)
222 const char *unixName
;
224 static int cachedfd
= -1;
226 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
227 dprintf_module( stddeb
, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
228 hModule
, hCachedModule
, cachedfd
);
229 if (!(pModule
= MODULE_GetPtr( hModule
))) return -1;
230 if (hCachedModule
== hModule
) return cachedfd
;
232 hCachedModule
= hModule
;
233 name
= NE_MODULE_NAME( pModule
);
234 if (!(unixName
= DOSFS_GetUnixFileName( name
, TRUE
)) ||
235 (cachedfd
= open( unixName
, O_RDONLY
)) == -1)
236 fprintf( stderr
, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
238 dprintf_module( stddeb
, "MODULE_OpenFile: opened '%s' -> %d\n",
244 /***********************************************************************
247 * This function translates NE segment flags to GlobalAlloc flags
249 static WORD
MODULE_Ne2MemFlags(WORD flags
)
253 if (flags
& NE_SEGFLAGS_DISCARDABLE
)
254 memflags
|= GMEM_DISCARDABLE
;
255 if (flags
& NE_SEGFLAGS_MOVEABLE
||
256 ( ! (flags
& NE_SEGFLAGS_DATA
) &&
257 ! (flags
& NE_SEGFLAGS_LOADED
) &&
258 ! (flags
& NE_SEGFLAGS_ALLOCATED
)
261 memflags
|= GMEM_MOVEABLE
;
262 memflags
|= GMEM_ZEROINIT
;
264 memflags
= GMEM_ZEROINIT
| GMEM_FIXED
;
269 /***********************************************************************
270 * MODULE_AllocateSegment (WPROCS.26)
273 DWORD
MODULE_AllocateSegment(WORD wFlags
, WORD wSize
, WORD wElem
)
275 WORD size
= wSize
<< wElem
;
276 HANDLE hMem
= GlobalAlloc16( MODULE_Ne2MemFlags(wFlags
), size
);
278 return (DWORD
)GlobalLock16(hMem
);
280 WORD selector
= HIWORD(WIN16_GlobalLock16(hMem
));
281 return MAKELONG(hMem
, selector
);
285 /***********************************************************************
286 * MODULE_CreateSegments
289 static BOOL
MODULE_CreateSegments( HMODULE16 hModule
)
291 SEGTABLEENTRY
*pSegment
;
295 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
296 pSegment
= NE_SEG_TABLE( pModule
);
297 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
299 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
300 if (i
== pModule
->ss
) minsize
+= pModule
->stack_size
;
301 /* The DGROUP is allocated by MODULE_CreateInstance */
302 if (i
== pModule
->dgroup
) continue;
303 pSegment
->selector
= GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment
->flags
),
305 !(pSegment
->flags
& NE_SEGFLAGS_DATA
),
307 FALSE
/*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
308 if (!pSegment
->selector
) return FALSE
;
311 pModule
->dgroup_entry
= pModule
->dgroup
? pModule
->seg_table
+
312 (pModule
->dgroup
- 1) * sizeof(SEGTABLEENTRY
) : 0;
318 /***********************************************************************
322 HINSTANCE16
MODULE_GetInstance( HMODULE16 hModule
)
324 SEGTABLEENTRY
*pSegment
;
327 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
328 if (pModule
->dgroup
== 0) return hModule
;
330 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
332 return pSegment
->selector
;
337 /***********************************************************************
338 * MODULE_CreateInstance
340 HINSTANCE16
MODULE_CreateInstance( HMODULE16 hModule
, LOADPARAMS
*params
)
342 SEGTABLEENTRY
*pSegment
;
345 HINSTANCE hNewInstance
, hPrevInstance
;
347 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
348 if (pModule
->dgroup
== 0) return hModule
;
350 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
351 hPrevInstance
= pSegment
->selector
;
353 /* if it's a library, create a new instance only the first time */
356 if (pModule
->flags
& NE_FFLAGS_LIBMODULE
) return hPrevInstance
;
357 if (params
== (LOADPARAMS
*)-1) return hPrevInstance
;
360 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
361 if (pModule
->ss
== pModule
->dgroup
) minsize
+= pModule
->stack_size
;
362 minsize
+= pModule
->heap_size
;
363 hNewInstance
= GLOBAL_Alloc( GMEM_ZEROINIT
| GMEM_FIXED
,
364 minsize
, hModule
, FALSE
, FALSE
, FALSE
);
365 if (!hNewInstance
) return 0;
366 pSegment
->selector
= hNewInstance
;
371 /***********************************************************************
372 * MODULE_CreateDummyModule
374 * Create a dummy NE module for Win32 or Winelib.
376 HMODULE16
MODULE_CreateDummyModule( const OFSTRUCT
*ofs
)
380 SEGTABLEENTRY
*pSegment
;
383 INT32 of_size
= sizeof(OFSTRUCT
) - sizeof(ofs
->szPathName
)
384 + strlen(ofs
->szPathName
) + 1;
385 INT32 size
= sizeof(NE_MODULE
) +
386 /* loaded file info */
388 /* segment table: DS,CS */
389 2 * sizeof(SEGTABLEENTRY
) +
392 /* several empty tables */
395 hModule
= GlobalAlloc16( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
396 if (!hModule
) return (HMODULE16
)11; /* invalid exe */
398 FarSetOwner( hModule
, hModule
);
399 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
401 /* Set all used entries */
402 pModule
->magic
= NE_SIGNATURE
;
409 pModule
->heap_size
= 0xe000;
410 pModule
->stack_size
= 0x1000;
411 pModule
->seg_count
= 2;
412 pModule
->modref_count
= 0;
413 pModule
->nrname_size
= 0;
414 pModule
->fileinfo
= sizeof(NE_MODULE
);
415 pModule
->os_flags
= NE_OSFLAGS_WINDOWS
;
416 pModule
->expected_version
= 0x030a;
417 pModule
->self
= hModule
;
419 /* Set loaded file information */
420 memcpy( pModule
+ 1, ofs
, of_size
);
421 ((OFSTRUCT
*)(pModule
+1))->cBytes
= of_size
- 1;
423 pSegment
= (SEGTABLEENTRY
*)((char*)(pModule
+ 1) + of_size
);
424 pModule
->seg_table
= pModule
->dgroup_entry
= (int)pSegment
- (int)pModule
;
427 pSegment
->flags
= NE_SEGFLAGS_DATA
;
428 pSegment
->minsize
= 0x1000;
435 pStr
= (char *)pSegment
;
436 pModule
->name_table
= (int)pStr
- (int)pModule
;
437 strcpy( pStr
, "\x08W32SXXXX" );
440 /* All tables zero terminated */
441 pModule
->res_table
= pModule
->import_table
= pModule
->entry_table
=
442 (int)pStr
- (int)pModule
;
444 MODULE_RegisterModule( pModule
);
449 /***********************************************************************
450 * MODULE_LoadExeHeader
452 static HMODULE16
MODULE_LoadExeHeader( HFILE hFile
, OFSTRUCT
*ofs
)
454 struct mz_header_s mz_header
;
455 struct ne_header_s ne_header
;
460 char *buffer
, *fastload
= NULL
;
461 int fastload_offset
= 0, fastload_length
= 0;
463 /* Read a block from either the file or the fast-load area. */
464 #define READ(offset,size,buffer) \
465 ((fastload && ((offset) >= fastload_offset) && \
466 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
467 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
468 (_llseek( hFile, mz_header.ne_offset+(offset), SEEK_SET), \
469 FILE_Read( hFile, (buffer), (size) ) == (size)))
471 _llseek( hFile
, 0, SEEK_SET
);
472 if ((FILE_Read(hFile
,&mz_header
,sizeof(mz_header
)) != sizeof(mz_header
)) ||
473 (mz_header
.mz_magic
!= MZ_SIGNATURE
))
474 return (HMODULE16
)11; /* invalid exe */
476 _llseek( hFile
, mz_header
.ne_offset
, SEEK_SET
);
477 if (FILE_Read( hFile
, &ne_header
, sizeof(ne_header
) ) != sizeof(ne_header
))
478 return (HMODULE16
)11; /* invalid exe */
480 if (ne_header
.ne_magic
== PE_SIGNATURE
) return (HMODULE16
)21; /* win32 exe */
481 if (ne_header
.ne_magic
!= NE_SIGNATURE
) return (HMODULE16
)11; /* invalid exe */
483 /* We now have a valid NE header */
485 size
= sizeof(NE_MODULE
) +
486 /* loaded file info */
487 sizeof(OFSTRUCT
)-sizeof(ofs
->szPathName
)+strlen(ofs
->szPathName
)+1+
489 ne_header
.n_segment_tab
* sizeof(SEGTABLEENTRY
) +
491 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
+
492 /* resident names table */
493 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
+
494 /* module ref table */
495 ne_header
.n_mod_ref_tab
* sizeof(WORD
) +
496 /* imported names table */
497 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
+
498 /* entry table length */
499 ne_header
.entry_tab_length
;
501 hModule
= GlobalAlloc16( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
502 if (!hModule
) return (HMODULE16
)11; /* invalid exe */
503 FarSetOwner( hModule
, hModule
);
504 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
505 memcpy( pModule
, &ne_header
, sizeof(ne_header
) );
507 pModule
->pe_module
= NULL
;
508 pModule
->self
= hModule
;
509 pModule
->self_loading_sel
= 0;
510 pData
= (BYTE
*)(pModule
+ 1);
512 /* Clear internal Wine flags in case they are set in the EXE file */
514 pModule
->flags
&= ~(NE_FFLAGS_BUILTIN
| NE_FFLAGS_WIN32
);
516 /* Read the fast-load area */
518 if (ne_header
.additional_flags
& NE_AFLAGS_FASTLOAD
)
520 fastload_offset
=ne_header
.fastload_offset
<<ne_header
.align_shift_count
;
521 fastload_length
=ne_header
.fastload_length
<<ne_header
.align_shift_count
;
522 dprintf_module( stddeb
, "Using fast-load area offset=%x len=%d\n",
523 fastload_offset
, fastload_length
);
524 if ((fastload
= (char *)malloc( fastload_length
)) != NULL
)
526 _llseek( hFile
, mz_header
.ne_offset
+ fastload_offset
, SEEK_SET
);
527 if (FILE_Read( hFile
, fastload
, fastload_length
) != fastload_length
)
535 /* Store the filename information */
537 pModule
->fileinfo
= (int)pData
- (int)pModule
;
538 size
= sizeof(OFSTRUCT
)-sizeof(ofs
->szPathName
)+strlen(ofs
->szPathName
)+1;
539 memcpy( pData
, ofs
, size
);
540 ((OFSTRUCT
*)pData
)->cBytes
= size
- 1;
543 /* Get the segment table */
545 pModule
->seg_table
= (int)pData
- (int)pModule
;
546 buffer
= malloc( ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
) );
550 struct ne_segment_table_entry_s
*pSeg
;
552 if (!READ( ne_header
.segment_tab_offset
,
553 ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
),
554 buffer
)) return (HMODULE16
)11; /* invalid exe */
555 pSeg
= (struct ne_segment_table_entry_s
*)buffer
;
556 for (i
= ne_header
.n_segment_tab
; i
> 0; i
--, pSeg
++)
558 memcpy( pData
, pSeg
, sizeof(*pSeg
) );
559 pData
+= sizeof(SEGTABLEENTRY
);
565 GlobalFree16( hModule
);
566 return (HMODULE16
)11; /* invalid exe */
569 /* Get the resource table */
571 if (ne_header
.resource_tab_offset
< ne_header
.rname_tab_offset
)
573 pModule
->res_table
= (int)pData
- (int)pModule
;
574 if (!READ(ne_header
.resource_tab_offset
,
575 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
,
576 pData
)) return (HMODULE16
)11; /* invalid exe */
577 pData
+= ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
;
579 else pModule
->res_table
= 0; /* No resource table */
581 /* Get the resident names table */
583 pModule
->name_table
= (int)pData
- (int)pModule
;
584 if (!READ( ne_header
.rname_tab_offset
,
585 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
,
588 GlobalFree16( hModule
);
589 return (HMODULE16
)11; /* invalid exe */
591 pData
+= ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
;
593 /* Get the module references table */
595 if (ne_header
.n_mod_ref_tab
> 0)
597 pModule
->modref_table
= (int)pData
- (int)pModule
;
598 if (!READ( ne_header
.moduleref_tab_offset
,
599 ne_header
.n_mod_ref_tab
* sizeof(WORD
),
600 pData
)) return (HMODULE16
)11; /* invalid exe */
601 pData
+= ne_header
.n_mod_ref_tab
* sizeof(WORD
);
603 else pModule
->modref_table
= 0; /* No module references */
605 /* Get the imported names table */
607 pModule
->import_table
= (int)pData
- (int)pModule
;
608 if (!READ( ne_header
.iname_tab_offset
,
609 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
,
612 GlobalFree16( hModule
);
613 return (HMODULE16
)11; /* invalid exe */
615 pData
+= ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
;
617 /* Get the entry table */
619 pModule
->entry_table
= (int)pData
- (int)pModule
;
620 if (!READ( ne_header
.entry_tab_offset
,
621 ne_header
.entry_tab_length
,
624 GlobalFree16( hModule
);
625 return (HMODULE16
)11; /* invalid exe */
627 pData
+= ne_header
.entry_tab_length
;
629 /* Get the non-resident names table */
631 if (ne_header
.nrname_tab_length
)
633 pModule
->nrname_handle
= GLOBAL_Alloc( 0, ne_header
.nrname_tab_length
,
634 hModule
, FALSE
, FALSE
, FALSE
);
635 if (!pModule
->nrname_handle
)
637 GlobalFree16( hModule
);
638 return (HMODULE16
)11; /* invalid exe */
640 buffer
= GlobalLock16( pModule
->nrname_handle
);
641 _llseek( hFile
, ne_header
.nrname_tab_offset
, SEEK_SET
);
642 if (FILE_Read( hFile
, buffer
, ne_header
.nrname_tab_length
)
643 != ne_header
.nrname_tab_length
)
645 GlobalFree16( pModule
->nrname_handle
);
646 GlobalFree16( hModule
);
647 return (HMODULE16
)11; /* invalid exe */
650 else pModule
->nrname_handle
= 0;
652 /* Allocate a segment for the implicitly-loaded DLLs */
654 if (pModule
->modref_count
)
656 pModule
->dlls_to_init
= GLOBAL_Alloc(GMEM_ZEROINIT
,
657 (pModule
->modref_count
+1)*sizeof(HMODULE16
),
658 hModule
, FALSE
, FALSE
, FALSE
);
659 if (!pModule
->dlls_to_init
)
661 if (pModule
->nrname_handle
) GlobalFree16( pModule
->nrname_handle
);
662 GlobalFree16( hModule
);
663 return (HMODULE16
)11; /* invalid exe */
666 else pModule
->dlls_to_init
= 0;
668 MODULE_RegisterModule( pModule
);
674 /***********************************************************************
677 * Lookup the ordinal for a given name.
679 WORD
MODULE_GetOrdinal( HMODULE16 hModule
, const char *name
)
681 char buffer
[256], *cpnt
;
685 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
687 dprintf_module( stddeb
, "MODULE_GetOrdinal(%04x,'%s')\n",
690 /* First handle names of the form '#xxxx' */
692 if (name
[0] == '#') return atoi( name
+ 1 );
694 /* Now copy and uppercase the string */
696 strcpy( buffer
, name
);
698 len
= strlen( buffer
);
700 /* First search the resident names */
702 cpnt
= (char *)pModule
+ pModule
->name_table
;
704 /* Skip the first entry (module name) */
705 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
708 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
710 dprintf_module( stddeb
, " Found: ordinal=%d\n",
711 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
712 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
714 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
717 /* Now search the non-resident names table */
719 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
720 cpnt
= (char *)GlobalLock16( pModule
->nrname_handle
);
722 /* Skip the first entry (module description string) */
723 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
726 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
728 dprintf_module( stddeb
, " Found: ordinal=%d\n",
729 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
730 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
732 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
738 /***********************************************************************
739 * MODULE_GetEntryPoint
741 * Return the entry point for a given ordinal.
743 FARPROC16
MODULE_GetEntryPoint( HMODULE16 hModule
, WORD ordinal
)
750 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
752 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
753 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
755 /* Skipping this bundle */
759 case 0: p
+= 2; break; /* unused */
760 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
761 default: p
+= 2 + *p
* 3; break; /* fixed */
770 case 0xff: /* moveable */
771 p
+= 2 + 6 * (ordinal
- curOrdinal
);
773 offset
= *(WORD
*)(p
+ 4);
777 p
+= 2 + 3 * (ordinal
- curOrdinal
);
778 offset
= *(WORD
*)(p
+ 1);
782 if (sel
== 0xfe) sel
= 0xffff; /* constant entry */
783 else sel
= (WORD
)(DWORD
)NE_SEG_TABLE(pModule
)[sel
-1].selector
;
784 return (FARPROC16
)PTR_SEG_OFF_TO_SEGPTR( sel
, offset
);
788 /***********************************************************************
789 * MODULE_SetEntryPoint
791 * Change the value of an entry point. Use with caution!
792 * It can only change the offset value, not the selector.
794 BOOL16
MODULE_SetEntryPoint( HMODULE16 hModule
, WORD ordinal
, WORD offset
)
800 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
802 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
803 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
805 /* Skipping this bundle */
809 case 0: p
+= 2; break; /* unused */
810 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
811 default: p
+= 2 + *p
* 3; break; /* fixed */
814 if (!*p
) return FALSE
;
820 case 0xff: /* moveable */
821 p
+= 2 + 6 * (ordinal
- curOrdinal
);
822 *(WORD
*)(p
+ 4) = offset
;
825 p
+= 2 + 3 * (ordinal
- curOrdinal
);
826 *(WORD
*)(p
+ 1) = offset
;
833 /***********************************************************************
834 * MODULE_GetWndProcEntry16 (not a Windows API function)
836 * Return an entry point from the WPROCS dll.
839 FARPROC16
MODULE_GetWndProcEntry16( const char *name
)
843 static HMODULE16 hModule
= 0;
845 if (!hModule
) hModule
= GetModuleHandle( "WPROCS" );
846 ordinal
= MODULE_GetOrdinal( hModule
, name
);
847 if (!(ret
= MODULE_GetEntryPoint( hModule
, ordinal
)))
848 fprintf( stderr
, "GetWndProc16: %s not found, please report\n", name
);
854 /***********************************************************************
855 * MODULE_GetModuleName
857 LPSTR
MODULE_GetModuleName( HMODULE16 hModule
)
861 static char buffer
[10];
863 if (!(pModule
= MODULE_GetPtr( hModule
))) return NULL
;
864 p
= (BYTE
*)pModule
+ pModule
->name_table
;
866 memcpy( buffer
, p
+ 1, len
);
872 /**********************************************************************
873 * MODULE_RegisterModule
875 void MODULE_RegisterModule( NE_MODULE
*pModule
)
877 pModule
->next
= hFirstModule
;
878 hFirstModule
= pModule
->self
;
882 /**********************************************************************
885 * Find a module from a path name.
887 HMODULE16
MODULE_FindModule( LPCSTR path
)
889 HMODULE16 hModule
= hFirstModule
;
890 LPCSTR filename
, dotptr
, modulepath
, modulename
;
891 BYTE len
, *name_table
;
893 if (!(filename
= strrchr( path
, '\\' ))) filename
= path
;
895 if ((dotptr
= strrchr( filename
, '.' )) != NULL
)
896 len
= (BYTE
)(dotptr
- filename
);
897 else len
= strlen( filename
);
901 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
903 modulepath
= NE_MODULE_NAME(pModule
);
904 if (!(modulename
= strrchr( modulepath
, '\\' )))
905 modulename
= modulepath
;
907 if (!lstrcmpi32A( modulename
, filename
)) return hModule
;
909 name_table
= (BYTE
*)pModule
+ pModule
->name_table
;
910 if ((*name_table
== len
) && !lstrncmpi32A(filename
, name_table
+1, len
))
912 hModule
= pModule
->next
;
918 /**********************************************************************
921 * Call a DLL's WEP, allowing it to shut down.
922 * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
924 static BOOL16
MODULE_CallWEP( HMODULE16 hModule
)
926 FARPROC16 WEP
= (FARPROC16
)0;
927 WORD ordinal
= MODULE_GetOrdinal( hModule
, "WEP" );
929 if (ordinal
) WEP
= MODULE_GetEntryPoint( hModule
, ordinal
);
932 dprintf_module( stddeb
, "module %04x doesn't have a WEP\n", hModule
);
935 return CallWindowsExitProc( WEP
, WEP_FREE_DLL
);
939 /**********************************************************************
942 * Remove a module from memory.
944 static void MODULE_FreeModule( HMODULE16 hModule
)
946 HMODULE16
*hPrevModule
;
948 SEGTABLEENTRY
*pSegment
;
952 if (!(pModule
= MODULE_GetPtr( hModule
))) return;
953 if (pModule
->flags
& NE_FFLAGS_BUILTIN
)
954 return; /* Can't free built-in module */
956 if (pModule
->flags
& NE_FFLAGS_LIBMODULE
) MODULE_CallWEP( hModule
);
958 /* Free the objects owned by the module */
960 HOOK_FreeModuleHooks( hModule
);
961 CLASS_FreeModuleClasses( hModule
);
963 /* Clear magic number just in case */
965 pModule
->magic
= pModule
->self
= 0;
967 /* Remove it from the linked list */
969 hPrevModule
= &hFirstModule
;
970 while (*hPrevModule
&& (*hPrevModule
!= hModule
))
972 hPrevModule
= &(MODULE_GetPtr( *hPrevModule
))->next
;
974 if (*hPrevModule
) *hPrevModule
= pModule
->next
;
976 /* Free all the segments */
978 pSegment
= NE_SEG_TABLE( pModule
);
979 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
981 GlobalFree16( pSegment
->selector
);
984 /* Free the referenced modules */
986 pModRef
= (HMODULE16
*)NE_MODULE_TABLE( pModule
);
987 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
989 FreeModule16( *pModRef
);
992 /* Free the module storage */
994 if (pModule
->nrname_handle
) GlobalFree16( pModule
->nrname_handle
);
995 if (pModule
->dlls_to_init
) GlobalFree16( pModule
->dlls_to_init
);
996 GlobalFree16( hModule
);
998 /* Remove module from cache */
1000 if (hCachedModule
== hModule
) hCachedModule
= 0;
1004 /**********************************************************************
1005 * LoadModule (KERNEL.45)
1007 HINSTANCE
LoadModule( LPCSTR name
, LPVOID paramBlock
)
1010 HANDLE hInstance
, hPrevInstance
;
1012 LOADPARAMS
*params
= (LOADPARAMS
*)paramBlock
;
1015 WORD
*pModRef
, *pDLLs
;
1019 hModule
= MODULE_FindModule( name
);
1021 if (!hModule
) /* We have to load the module */
1023 /* Try to load the built-in first if not disabled */
1024 if ((hModule
= BUILTIN_LoadModule( name
, FALSE
))) return hModule
;
1026 if ((hFile
= OpenFile( name
, &ofs
, OF_READ
)) == HFILE_ERROR
)
1028 /* Now try the built-in even if disabled */
1029 if ((hModule
= BUILTIN_LoadModule( name
, TRUE
)))
1031 fprintf( stderr
, "Warning: could not load Windows DLL '%s', using built-in module.\n", name
);
1034 return 2; /* File not found */
1037 /* Create the module structure */
1039 hModule
= MODULE_LoadExeHeader( hFile
, &ofs
);
1042 /* FIXME: Hack because PE_LoadModule is recursive */
1043 int fd
= dup( FILE_GetUnixHandle(hFile
) );
1045 if (hModule
== 21) hModule
= PE_LoadModule( fd
, &ofs
, paramBlock
);
1048 fprintf( stderr
, "LoadModule: can't load '%s', error=%d\n",
1053 pModule
= MODULE_GetPtr( hModule
);
1055 /* Allocate the segments for this module */
1057 MODULE_CreateSegments( hModule
);
1060 hInstance
= MODULE_CreateInstance( hModule
, (LOADPARAMS
*)paramBlock
);
1062 /* Load the referenced DLLs */
1064 pModRef
= (WORD
*)((char *)pModule
+ pModule
->modref_table
);
1065 pDLLs
= (WORD
*)GlobalLock16( pModule
->dlls_to_init
);
1066 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
1069 BYTE
*pstr
= (BYTE
*)pModule
+ pModule
->import_table
+ *pModRef
;
1070 memcpy( buffer
, pstr
+ 1, *pstr
);
1071 strcpy( buffer
+ *pstr
, ".dll" );
1072 dprintf_module( stddeb
, "Loading '%s'\n", buffer
);
1073 if (!(*pModRef
= MODULE_FindModule( buffer
)))
1075 /* If the DLL is not loaded yet, load it and store */
1076 /* its handle in the list of DLLs to initialize. */
1079 if ((hDLL
= LoadModule( buffer
, (LPVOID
)-1 )) == 2) /* file not found */
1083 /* Try with prepending the path of the current module */
1084 GetModuleFileName( hModule
, buffer
, sizeof(buffer
) );
1085 if (!(p
= strrchr( buffer
, '\\' ))) p
= buffer
;
1086 memcpy( p
+ 1, pstr
+ 1, *pstr
);
1087 strcpy( p
+ 1 + *pstr
, ".dll" );
1088 hDLL
= LoadModule( buffer
, (LPVOID
)-1 );
1092 fprintf( stderr
, "Could not load '%s' required by '%s', error = %d\n",
1093 buffer
, name
, hDLL
);
1094 return 2; /* file not found */
1096 *pModRef
= GetExePtr( hDLL
);
1097 *pDLLs
++ = *pModRef
;
1099 else /* Increment the reference count of the DLL */
1101 NE_MODULE
*pOldDLL
= MODULE_GetPtr( *pModRef
);
1102 if (pOldDLL
) pOldDLL
->count
++;
1106 /* Load the segments */
1108 if (pModule
->flags
& NE_FFLAGS_SELFLOAD
)
1111 /* Handle self loading modules */
1112 SEGTABLEENTRY
* pSegTable
= (SEGTABLEENTRY
*) NE_SEG_TABLE(pModule
);
1113 SELFLOADHEADER
*selfloadheader
;
1114 STACK16FRAME
*stack16Top
;
1115 HMODULE16 hselfload
= GetModuleHandle("WPROCS");
1116 WORD oldss
, oldsp
, saved_dgroup
= pSegTable
[pModule
->dgroup
- 1].selector
;
1117 fprintf (stderr
, "Warning: %*.*s is a self-loading module\n"
1118 "Support for self-loading modules is very experimental\n",
1119 *((BYTE
*)pModule
+ pModule
->name_table
),
1120 *((BYTE
*)pModule
+ pModule
->name_table
),
1121 (char *)pModule
+ pModule
->name_table
+ 1);
1122 NE_LoadSegment( hModule
, 1 );
1123 selfloadheader
= (SELFLOADHEADER
*)
1124 PTR_SEG_OFF_TO_LIN(pSegTable
->selector
, 0);
1125 selfloadheader
->EntryAddrProc
=
1126 MODULE_GetEntryPoint(hselfload
,27);
1127 selfloadheader
->MyAlloc
= MODULE_GetEntryPoint(hselfload
,28);
1128 selfloadheader
->SetOwner
= MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1129 pModule
->self_loading_sel
= GlobalHandleToSel(
1130 GLOBAL_Alloc (GMEM_ZEROINIT
,
1131 0xFF00, hModule
, FALSE
, FALSE
, FALSE
)
1133 oldss
= IF1632_Saved16_ss
;
1134 oldsp
= IF1632_Saved16_sp
;
1135 IF1632_Saved16_ss
= pModule
->self_loading_sel
;
1136 IF1632_Saved16_sp
= 0xFF00 - sizeof(*stack16Top
);
1137 stack16Top
= CURRENT_STACK16
;
1138 stack16Top
->saved_ss
= 0;
1139 stack16Top
->saved_sp
= 0;
1140 stack16Top
->ds
= stack16Top
->es
= pModule
->self_loading_sel
;
1141 stack16Top
->entry_point
= 0;
1142 stack16Top
->entry_ip
= 0;
1143 stack16Top
->entry_cs
= 0;
1148 if (!IF1632_Stack32_base
) {
1149 STACK32FRAME
* frame32
;
1151 /* Setup an initial 32 bit stack frame */
1152 hInitialStack32
= GLOBAL_Alloc( GMEM_FIXED
, 0x10000,
1153 hModule
, FALSE
, FALSE
,
1156 /* Create the 32-bit stack frame */
1158 *(DWORD
*)GlobalLock16(hInitialStack32
) = 0xDEADBEEF;
1159 stack32Top
= (char*)GlobalLock16(hInitialStack32
) +
1161 frame32
= (STACK32FRAME
*)stack32Top
- 1;
1162 frame32
->saved_esp
= (DWORD
)stack32Top
;
1169 frame32
->retaddr
= 0;
1170 frame32
->codeselector
= WINE_CODE_SELECTOR
;
1171 /* pTask->esp = (DWORD)frame32; */
1172 IF1632_Stack32_base
= WIN16_GlobalLock16(hInitialStack32
);
1175 /* FIXME: we probably need a DOS handle here */
1176 fd
= MODULE_OpenFile( hModule
);
1177 CallTo16_word_ww (selfloadheader
->BootApp
,
1178 pModule
->self_loading_sel
, hModule
, fd
);
1179 /* some BootApp procs overwrite the selector of dgroup */
1180 pSegTable
[pModule
->dgroup
- 1].selector
= saved_dgroup
;
1181 IF1632_Saved16_ss
= oldss
;
1182 IF1632_Saved16_sp
= oldsp
;
1183 for (i
= 2; i
<= pModule
->seg_count
; i
++) NE_LoadSegment( hModule
, i
);
1184 if (hInitialStack32
){
1185 GlobalFree16(hInitialStack32
);
1186 IF1632_Stack32_base
= hInitialStack32
= 0;
1191 for (i
= 1; i
<= pModule
->seg_count
; i
++)
1192 NE_LoadSegment( hModule
, i
);
1195 /* Fixup the functions prologs */
1197 NE_FixupPrologs( pModule
);
1199 /* Make sure the usage count is 1 on the first loading of */
1200 /* the module, even if it contains circular DLL references */
1206 pModule
= MODULE_GetPtr( hModule
);
1207 hPrevInstance
= MODULE_GetInstance( hModule
);
1208 hInstance
= MODULE_CreateInstance( hModule
, params
);
1209 if (hInstance
!= hPrevInstance
) /* not a library */
1210 NE_LoadSegment( hModule
, pModule
->dgroup
);
1214 lstrcpyn32A( ofs
.szPathName
, name
, sizeof(ofs
.szPathName
) );
1215 if ((hModule
= MODULE_CreateDummyModule( &ofs
)) < 32) return hModule
;
1216 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
1218 hInstance
= MODULE_CreateInstance( hModule
, params
);
1219 #endif /* WINELIB */
1221 /* Create a task for this instance */
1223 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
) && (paramBlock
!= (LPVOID
)-1))
1225 TASK_CreateTask( hModule
, hInstance
, hPrevInstance
,
1226 params
->hEnvironment
,
1227 (LPSTR
)PTR_SEG_TO_LIN( params
->cmdLine
),
1228 *((WORD
*)PTR_SEG_TO_LIN(params
->showCmd
)+1) );
1235 /**********************************************************************
1236 * FreeModule16 (KERNEL.46)
1238 BOOL16
FreeModule16( HMODULE16 hModule
)
1242 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1243 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
1245 dprintf_module( stddeb
, "FreeModule16: %s count %d\n",
1246 MODULE_GetModuleName(hModule
), pModule
->count
);
1247 if (--pModule
->count
== 0) MODULE_FreeModule( hModule
);
1252 /**********************************************************************
1253 * GetModuleHandle (KERNEL.47)
1255 HMODULE16
WIN16_GetModuleHandle( SEGPTR name
)
1257 if (HIWORD(name
) == 0) return GetExePtr( (HANDLE
)name
);
1258 return MODULE_FindModule( PTR_SEG_TO_LIN(name
) );
1261 HMODULE16
GetModuleHandle( LPCSTR name
)
1263 return MODULE_FindModule( name
);
1267 /**********************************************************************
1268 * GetModuleUsage (KERNEL.48)
1270 int GetModuleUsage( HANDLE hModule
)
1274 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1275 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
1276 dprintf_module( stddeb
, "GetModuleUsage(%04x): returning %d\n",
1277 hModule
, pModule
->count
);
1278 return pModule
->count
;
1282 /**********************************************************************
1283 * GetModuleFileName (KERNEL.49)
1285 int GetModuleFileName( HANDLE hModule
, LPSTR lpFileName
, short nSize
)
1289 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1290 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
1291 lstrcpyn32A( lpFileName
, NE_MODULE_NAME(pModule
), nSize
);
1292 dprintf_module( stddeb
, "GetModuleFilename: %s\n", lpFileName
);
1293 return strlen(lpFileName
);
1297 /***********************************************************************
1298 * LoadLibrary (KERNEL.95)
1300 HANDLE
LoadLibrary( LPCSTR libname
)
1303 dprintf_module( stddeb
, "LoadLibrary: (%08x) %s\n", (int)libname
, libname
);
1304 WINELIB_UNIMP("LoadLibrary()");
1309 dprintf_module( stddeb
, "LoadLibrary: (%08x) %s\n", (int)libname
, libname
);
1311 /* This does not increment the module reference count, and will
1312 * therefore cause crashes on FreeLibrary calls.
1313 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1315 handle
= LoadModule( libname
, (LPVOID
)-1 );
1316 if (handle
== (HANDLE
)2) /* file not found */
1319 lstrcpyn32A( buffer
, libname
, 252 );
1320 strcat( buffer
, ".dll" );
1321 handle
= LoadModule( buffer
, (LPVOID
)-1 );
1323 if (handle
>= (HANDLE
)32) NE_InitializeDLLs( GetExePtr(handle
) );
1329 /***********************************************************************
1330 * FreeLibrary (KERNEL.96)
1332 void FreeLibrary( HANDLE handle
)
1334 dprintf_module( stddeb
,"FreeLibrary: %04x\n", handle
);
1335 FreeModule16( handle
);
1339 /***********************************************************************
1340 * WinExec (KERNEL.166)
1342 HANDLE
WinExec( LPSTR lpCmdLine
, WORD nCmdShow
)
1345 HGLOBAL16 cmdShowHandle
, cmdLineHandle
;
1348 char *p
, *cmdline
, filename
[256];
1349 static int use_load_module
= 1;
1351 if (!(cmdShowHandle
= GlobalAlloc16( 0, 2 * sizeof(WORD
) )))
1352 return 8; /* Out of memory */
1353 if (!(cmdLineHandle
= GlobalAlloc16( 0, 256 )))
1355 GlobalFree16( cmdShowHandle
);
1356 return 8; /* Out of memory */
1359 /* Store nCmdShow */
1361 cmdShowPtr
= (WORD
*)GlobalLock16( cmdShowHandle
);
1363 cmdShowPtr
[1] = nCmdShow
;
1365 /* Build the filename and command-line */
1367 cmdline
= (char *)GlobalLock16( cmdLineHandle
);
1368 lstrcpyn32A(filename
, lpCmdLine
, sizeof(filename
) - 4 /* for extension */);
1369 for (p
= filename
; *p
&& (*p
!= ' ') && (*p
!= '\t'); p
++);
1370 if (*p
) lstrcpyn32A( cmdline
, p
+ 1, 128 );
1371 else cmdline
[0] = '\0';
1374 /* Now load the executable file */
1376 if (use_load_module
)
1379 /* WINELIB: Use LoadModule() only for the program itself */
1380 use_load_module
= 0;
1381 params
.hEnvironment
= (HANDLE
)GetDOSEnvironment();
1383 params
.hEnvironment
= (HANDLE
)SELECTOROF( GetDOSEnvironment() );
1384 #endif /* WINELIB */
1385 params
.cmdLine
= (SEGPTR
)WIN16_GlobalLock16( cmdLineHandle
);
1386 params
.showCmd
= (SEGPTR
)WIN16_GlobalLock16( cmdShowHandle
);
1387 params
.reserved
= 0;
1388 handle
= LoadModule( filename
, ¶ms
);
1389 if (handle
== 2) /* file not found */
1391 /* Check that the original file name did not have a suffix */
1392 p
= strrchr(filename
, '.');
1393 if (!p
|| (strchr(p
, '/') && strchr(p
, '\\')))
1395 p
= filename
+ strlen(filename
);
1396 strcpy( p
, ".exe" );
1397 handle
= LoadModule( filename
, ¶ms
);
1398 *p
= '\0'; /* Remove extension */
1406 /* Try to start it as a unix program */
1410 const char *unixfilename
;
1411 const char *argv
[256], **argptr
;
1412 int iconic
= (nCmdShow
== SW_SHOWMINIMIZED
||
1413 nCmdShow
== SW_SHOWMINNOACTIVE
);
1415 /* get unixfilename */
1416 if (strchr(filename
, '/') ||
1417 strchr(filename
, ':') ||
1418 strchr(filename
, '\\'))
1419 unixfilename
= DOSFS_GetUnixFileName(filename
, 1);
1420 else unixfilename
= filename
;
1426 if (iconic
) *argptr
++ = "-iconic";
1427 *argptr
++ = unixfilename
;
1431 while (*p
&& (*p
== ' ' || *p
== '\t')) *p
++ = '\0';
1434 while (*p
&& *p
!= ' ' && *p
!= '\t') p
++;
1439 execvp(argv
[0], (char**)argv
);
1447 if (iconic
) *argptr
++ = "-iconic";
1448 *argptr
++ = lpCmdLine
;
1452 execvp(argv
[0] , (char**)argv
);
1455 fprintf(stderr
, "WinExec: can't exec 'wine %s'\n", lpCmdLine
);
1461 GlobalFree16( cmdShowHandle
);
1462 GlobalFree16( cmdLineHandle
);
1465 if (handle
< (HANDLE
)32) /* Error? */
1468 /* FIXME: Yield never returns!
1469 We may want to run more applications or start the debugger
1470 before calling Yield. If we don't Yield will be called immdiately
1471 after returning. Why is it needed for Word anyway? */
1472 Yield(); /* program is executed immediately ....needed for word */
1479 /***********************************************************************
1480 * GetProcAddress16 (KERNEL.50)
1482 FARPROC16
GetProcAddress16( HMODULE16 hModule
, SEGPTR name
)
1487 if (!hModule
) hModule
= GetCurrentTask();
1488 hModule
= GetExePtr( hModule
);
1490 if (HIWORD(name
) != 0)
1492 ordinal
= MODULE_GetOrdinal( hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1493 dprintf_module( stddeb
, "GetProcAddress: %04x '%s'\n",
1494 hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1498 ordinal
= LOWORD(name
);
1499 dprintf_module( stddeb
, "GetProcAddress: %04x %04x\n",
1502 if (!ordinal
) return (FARPROC16
)0;
1504 ret
= MODULE_GetEntryPoint( hModule
, ordinal
);
1506 dprintf_module( stddeb
, "GetProcAddress: returning %08x\n", (UINT32
)ret
);
1511 /***********************************************************************
1512 * GetProcAddress32 (KERNEL32.257)
1514 FARPROC32
GetProcAddress32( HMODULE32 hModule
, LPCSTR function
)
1519 hModule
= GetExePtr( hModule
);
1520 if (!(pModule
= MODULE_GetPtr( hModule
)))
1521 return (FARPROC32
)0;
1522 if (!(pModule
->flags
& NE_FFLAGS_WIN32
) || !pModule
->pe_module
)
1523 return (FARPROC32
)0;
1524 if (pModule
->flags
& NE_FFLAGS_BUILTIN
)
1525 return BUILTIN_GetProcAddress32( pModule
, function
);
1526 return PE_FindExportedFunction( pModule
->pe_module
, function
);
1533 /**********************************************************************
1534 * GetExpWinVer (KERNEL.167)
1536 WORD
GetExpWinVer( HMODULE16 hModule
)
1538 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
1539 return pModule
? pModule
->expected_version
: 0;
1543 /**********************************************************************
1544 * ModuleFirst (TOOLHELP.59)
1546 BOOL16
ModuleFirst( MODULEENTRY
*lpme
)
1548 lpme
->wNext
= hFirstModule
;
1549 return ModuleNext( lpme
);
1553 /**********************************************************************
1554 * ModuleNext (TOOLHELP.60)
1556 BOOL16
ModuleNext( MODULEENTRY
*lpme
)
1560 if (!lpme
->wNext
) return FALSE
;
1561 if (!(pModule
= MODULE_GetPtr( lpme
->wNext
))) return FALSE
;
1562 strncpy( lpme
->szModule
, (char *)pModule
+ pModule
->name_table
,
1564 lpme
->szModule
[MAX_MODULE_NAME
] = '\0';
1565 lpme
->hModule
= lpme
->wNext
;
1566 lpme
->wcUsage
= pModule
->count
;
1567 strncpy( lpme
->szExePath
, NE_MODULE_NAME(pModule
), MAX_PATH
);
1568 lpme
->szExePath
[MAX_PATH
] = '\0';
1569 lpme
->wNext
= pModule
->next
;
1574 /**********************************************************************
1575 * ModuleFindName (TOOLHELP.61)
1577 BOOL16
ModuleFindName( MODULEENTRY
*lpme
, LPCSTR name
)
1579 lpme
->wNext
= GetModuleHandle( name
);
1580 return ModuleNext( lpme
);
1584 /**********************************************************************
1585 * ModuleFindHandle (TOOLHELP.62)
1587 BOOL16
ModuleFindHandle( MODULEENTRY
*lpme
, HMODULE16 hModule
)
1589 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1590 lpme
->wNext
= hModule
;
1591 return ModuleNext( lpme
);