4 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
22 #include "registers.h"
23 #include "stackframe.h"
30 extern HINSTANCE16
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 HGLOBAL16 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 HANDLE16 hMem
= GlobalAlloc16( MODULE_Ne2MemFlags(wFlags
), size
);
277 return MAKELONG( hMem
, GlobalHandleToSel(hMem
) );
280 /***********************************************************************
281 * MODULE_CreateSegments
284 static BOOL
MODULE_CreateSegments( HMODULE16 hModule
)
286 SEGTABLEENTRY
*pSegment
;
290 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
291 pSegment
= NE_SEG_TABLE( pModule
);
292 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
294 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
295 if (i
== pModule
->ss
) minsize
+= pModule
->stack_size
;
296 /* The DGROUP is allocated by MODULE_CreateInstance */
297 if (i
== pModule
->dgroup
) continue;
298 pSegment
->selector
= GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment
->flags
),
300 !(pSegment
->flags
& NE_SEGFLAGS_DATA
),
302 FALSE
/*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
303 if (!pSegment
->selector
) return FALSE
;
306 pModule
->dgroup_entry
= pModule
->dgroup
? pModule
->seg_table
+
307 (pModule
->dgroup
- 1) * sizeof(SEGTABLEENTRY
) : 0;
313 /***********************************************************************
316 HINSTANCE16
MODULE_GetInstance( HMODULE16 hModule
)
318 SEGTABLEENTRY
*pSegment
;
321 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
322 if (pModule
->dgroup
== 0) return hModule
;
324 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
326 return pSegment
->selector
;
330 /***********************************************************************
331 * MODULE_CreateInstance
333 HINSTANCE16
MODULE_CreateInstance( HMODULE16 hModule
, LOADPARAMS
*params
)
335 SEGTABLEENTRY
*pSegment
;
338 HINSTANCE16 hNewInstance
, hPrevInstance
;
340 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
341 if (pModule
->dgroup
== 0) return hModule
;
343 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
344 hPrevInstance
= pSegment
->selector
;
346 /* if it's a library, create a new instance only the first time */
349 if (pModule
->flags
& NE_FFLAGS_LIBMODULE
) return hPrevInstance
;
350 if (params
== (LOADPARAMS
*)-1) return hPrevInstance
;
353 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
354 if (pModule
->ss
== pModule
->dgroup
) minsize
+= pModule
->stack_size
;
355 minsize
+= pModule
->heap_size
;
356 hNewInstance
= GLOBAL_Alloc( GMEM_ZEROINIT
| GMEM_FIXED
,
357 minsize
, hModule
, FALSE
, FALSE
, FALSE
);
358 if (!hNewInstance
) return 0;
359 pSegment
->selector
= hNewInstance
;
364 /***********************************************************************
365 * MODULE_CreateDummyModule
367 * Create a dummy NE module for Win32 or Winelib.
369 HMODULE16
MODULE_CreateDummyModule( const OFSTRUCT
*ofs
)
373 SEGTABLEENTRY
*pSegment
;
376 INT32 of_size
= sizeof(OFSTRUCT
) - sizeof(ofs
->szPathName
)
377 + strlen(ofs
->szPathName
) + 1;
378 INT32 size
= sizeof(NE_MODULE
) +
379 /* loaded file info */
381 /* segment table: DS,CS */
382 2 * sizeof(SEGTABLEENTRY
) +
385 /* several empty tables */
388 hModule
= GlobalAlloc16( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
389 if (!hModule
) return (HMODULE16
)11; /* invalid exe */
391 FarSetOwner( hModule
, hModule
);
392 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
394 /* Set all used entries */
395 pModule
->magic
= NE_SIGNATURE
;
402 pModule
->heap_size
= 0xe000;
403 pModule
->stack_size
= 0x1000;
404 pModule
->seg_count
= 2;
405 pModule
->modref_count
= 0;
406 pModule
->nrname_size
= 0;
407 pModule
->fileinfo
= sizeof(NE_MODULE
);
408 pModule
->os_flags
= NE_OSFLAGS_WINDOWS
;
409 pModule
->expected_version
= 0x030a;
410 pModule
->self
= hModule
;
412 /* Set loaded file information */
413 memcpy( pModule
+ 1, ofs
, of_size
);
414 ((OFSTRUCT
*)(pModule
+1))->cBytes
= of_size
- 1;
416 pSegment
= (SEGTABLEENTRY
*)((char*)(pModule
+ 1) + of_size
);
417 pModule
->seg_table
= pModule
->dgroup_entry
= (int)pSegment
- (int)pModule
;
420 pSegment
->flags
= NE_SEGFLAGS_DATA
;
421 pSegment
->minsize
= 0x1000;
428 pStr
= (char *)pSegment
;
429 pModule
->name_table
= (int)pStr
- (int)pModule
;
430 strcpy( pStr
, "\x08W32SXXXX" );
433 /* All tables zero terminated */
434 pModule
->res_table
= pModule
->import_table
= pModule
->entry_table
=
435 (int)pStr
- (int)pModule
;
437 MODULE_RegisterModule( pModule
);
442 /***********************************************************************
443 * MODULE_LoadExeHeader
445 static HMODULE16
MODULE_LoadExeHeader( HFILE hFile
, OFSTRUCT
*ofs
)
447 struct mz_header_s mz_header
;
448 struct ne_header_s ne_header
;
453 char *buffer
, *fastload
= NULL
;
454 int fastload_offset
= 0, fastload_length
= 0;
456 /* Read a block from either the file or the fast-load area. */
457 #define READ(offset,size,buffer) \
458 ((fastload && ((offset) >= fastload_offset) && \
459 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
460 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
461 (_llseek( hFile, mz_header.ne_offset+(offset), SEEK_SET), \
462 _lread32( hFile, (buffer), (size) ) == (size)))
464 _llseek( hFile
, 0, SEEK_SET
);
465 if ((_lread32(hFile
,&mz_header
,sizeof(mz_header
)) != sizeof(mz_header
)) ||
466 (mz_header
.mz_magic
!= MZ_SIGNATURE
))
467 return (HMODULE16
)11; /* invalid exe */
469 _llseek( hFile
, mz_header
.ne_offset
, SEEK_SET
);
470 if (_lread32( hFile
, &ne_header
, sizeof(ne_header
) ) != sizeof(ne_header
))
471 return (HMODULE16
)11; /* invalid exe */
473 if (ne_header
.ne_magic
== PE_SIGNATURE
) return (HMODULE16
)21; /* win32 exe */
474 if (ne_header
.ne_magic
!= NE_SIGNATURE
) return (HMODULE16
)11; /* invalid exe */
476 /* We now have a valid NE header */
478 size
= sizeof(NE_MODULE
) +
479 /* loaded file info */
480 sizeof(OFSTRUCT
)-sizeof(ofs
->szPathName
)+strlen(ofs
->szPathName
)+1+
482 ne_header
.n_segment_tab
* sizeof(SEGTABLEENTRY
) +
484 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
+
485 /* resident names table */
486 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
+
487 /* module ref table */
488 ne_header
.n_mod_ref_tab
* sizeof(WORD
) +
489 /* imported names table */
490 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
+
491 /* entry table length */
492 ne_header
.entry_tab_length
;
494 hModule
= GlobalAlloc16( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
495 if (!hModule
) return (HMODULE16
)11; /* invalid exe */
496 FarSetOwner( hModule
, hModule
);
497 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
498 memcpy( pModule
, &ne_header
, sizeof(ne_header
) );
500 pModule
->pe_module
= NULL
;
501 pModule
->self
= hModule
;
502 pModule
->self_loading_sel
= 0;
503 pData
= (BYTE
*)(pModule
+ 1);
505 /* Clear internal Wine flags in case they are set in the EXE file */
507 pModule
->flags
&= ~(NE_FFLAGS_BUILTIN
| NE_FFLAGS_WIN32
);
509 /* Read the fast-load area */
511 if (ne_header
.additional_flags
& NE_AFLAGS_FASTLOAD
)
513 fastload_offset
=ne_header
.fastload_offset
<<ne_header
.align_shift_count
;
514 fastload_length
=ne_header
.fastload_length
<<ne_header
.align_shift_count
;
515 dprintf_module( stddeb
, "Using fast-load area offset=%x len=%d\n",
516 fastload_offset
, fastload_length
);
517 if ((fastload
= (char *)malloc( fastload_length
)) != NULL
)
519 _llseek( hFile
, mz_header
.ne_offset
+ fastload_offset
, SEEK_SET
);
520 if (_lread32(hFile
, fastload
, fastload_length
) != fastload_length
)
528 /* Store the filename information */
530 pModule
->fileinfo
= (int)pData
- (int)pModule
;
531 size
= sizeof(OFSTRUCT
)-sizeof(ofs
->szPathName
)+strlen(ofs
->szPathName
)+1;
532 memcpy( pData
, ofs
, size
);
533 ((OFSTRUCT
*)pData
)->cBytes
= size
- 1;
536 /* Get the segment table */
538 pModule
->seg_table
= (int)pData
- (int)pModule
;
539 buffer
= malloc( ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
) );
543 struct ne_segment_table_entry_s
*pSeg
;
545 if (!READ( ne_header
.segment_tab_offset
,
546 ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
),
547 buffer
)) return (HMODULE16
)11; /* invalid exe */
548 pSeg
= (struct ne_segment_table_entry_s
*)buffer
;
549 for (i
= ne_header
.n_segment_tab
; i
> 0; i
--, pSeg
++)
551 memcpy( pData
, pSeg
, sizeof(*pSeg
) );
552 pData
+= sizeof(SEGTABLEENTRY
);
558 GlobalFree16( hModule
);
559 return (HMODULE16
)11; /* invalid exe */
562 /* Get the resource table */
564 if (ne_header
.resource_tab_offset
< ne_header
.rname_tab_offset
)
566 pModule
->res_table
= (int)pData
- (int)pModule
;
567 if (!READ(ne_header
.resource_tab_offset
,
568 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
,
569 pData
)) return (HMODULE16
)11; /* invalid exe */
570 pData
+= ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
;
572 else pModule
->res_table
= 0; /* No resource table */
574 /* Get the resident names table */
576 pModule
->name_table
= (int)pData
- (int)pModule
;
577 if (!READ( ne_header
.rname_tab_offset
,
578 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
,
581 GlobalFree16( hModule
);
582 return (HMODULE16
)11; /* invalid exe */
584 pData
+= ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
;
586 /* Get the module references table */
588 if (ne_header
.n_mod_ref_tab
> 0)
590 pModule
->modref_table
= (int)pData
- (int)pModule
;
591 if (!READ( ne_header
.moduleref_tab_offset
,
592 ne_header
.n_mod_ref_tab
* sizeof(WORD
),
593 pData
)) return (HMODULE16
)11; /* invalid exe */
594 pData
+= ne_header
.n_mod_ref_tab
* sizeof(WORD
);
596 else pModule
->modref_table
= 0; /* No module references */
598 /* Get the imported names table */
600 pModule
->import_table
= (int)pData
- (int)pModule
;
601 if (!READ( ne_header
.iname_tab_offset
,
602 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
,
605 GlobalFree16( hModule
);
606 return (HMODULE16
)11; /* invalid exe */
608 pData
+= ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
;
610 /* Get the entry table */
612 pModule
->entry_table
= (int)pData
- (int)pModule
;
613 if (!READ( ne_header
.entry_tab_offset
,
614 ne_header
.entry_tab_length
,
617 GlobalFree16( hModule
);
618 return (HMODULE16
)11; /* invalid exe */
620 pData
+= ne_header
.entry_tab_length
;
622 /* Get the non-resident names table */
624 if (ne_header
.nrname_tab_length
)
626 pModule
->nrname_handle
= GLOBAL_Alloc( 0, ne_header
.nrname_tab_length
,
627 hModule
, FALSE
, FALSE
, FALSE
);
628 if (!pModule
->nrname_handle
)
630 GlobalFree16( hModule
);
631 return (HMODULE16
)11; /* invalid exe */
633 buffer
= GlobalLock16( pModule
->nrname_handle
);
634 _llseek( hFile
, ne_header
.nrname_tab_offset
, SEEK_SET
);
635 if (_lread32( hFile
, buffer
, ne_header
.nrname_tab_length
)
636 != ne_header
.nrname_tab_length
)
638 GlobalFree16( pModule
->nrname_handle
);
639 GlobalFree16( hModule
);
640 return (HMODULE16
)11; /* invalid exe */
643 else pModule
->nrname_handle
= 0;
645 /* Allocate a segment for the implicitly-loaded DLLs */
647 if (pModule
->modref_count
)
649 pModule
->dlls_to_init
= GLOBAL_Alloc(GMEM_ZEROINIT
,
650 (pModule
->modref_count
+1)*sizeof(HMODULE16
),
651 hModule
, FALSE
, FALSE
, FALSE
);
652 if (!pModule
->dlls_to_init
)
654 if (pModule
->nrname_handle
) GlobalFree16( pModule
->nrname_handle
);
655 GlobalFree16( hModule
);
656 return (HMODULE16
)11; /* invalid exe */
659 else pModule
->dlls_to_init
= 0;
661 MODULE_RegisterModule( pModule
);
667 /***********************************************************************
670 * Lookup the ordinal for a given name.
672 WORD
MODULE_GetOrdinal( HMODULE16 hModule
, const char *name
)
674 char buffer
[256], *cpnt
;
678 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
680 dprintf_module( stddeb
, "MODULE_GetOrdinal(%04x,'%s')\n",
683 /* First handle names of the form '#xxxx' */
685 if (name
[0] == '#') return atoi( name
+ 1 );
687 /* Now copy and uppercase the string */
689 strcpy( buffer
, name
);
691 len
= strlen( buffer
);
693 /* First search the resident names */
695 cpnt
= (char *)pModule
+ pModule
->name_table
;
697 /* Skip the first entry (module name) */
698 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
701 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
703 dprintf_module( stddeb
, " Found: ordinal=%d\n",
704 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
705 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
707 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
710 /* Now search the non-resident names table */
712 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
713 cpnt
= (char *)GlobalLock16( pModule
->nrname_handle
);
715 /* Skip the first entry (module description string) */
716 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
719 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
721 dprintf_module( stddeb
, " Found: ordinal=%d\n",
722 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
723 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
725 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
731 /***********************************************************************
732 * MODULE_GetEntryPoint
734 * Return the entry point for a given ordinal.
736 FARPROC16
MODULE_GetEntryPoint( HMODULE16 hModule
, WORD ordinal
)
743 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
745 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
746 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
748 /* Skipping this bundle */
752 case 0: p
+= 2; break; /* unused */
753 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
754 default: p
+= 2 + *p
* 3; break; /* fixed */
763 case 0xff: /* moveable */
764 p
+= 2 + 6 * (ordinal
- curOrdinal
);
766 offset
= *(WORD
*)(p
+ 4);
770 p
+= 2 + 3 * (ordinal
- curOrdinal
);
771 offset
= *(WORD
*)(p
+ 1);
775 if (sel
== 0xfe) sel
= 0xffff; /* constant entry */
776 else sel
= (WORD
)(DWORD
)NE_SEG_TABLE(pModule
)[sel
-1].selector
;
777 return (FARPROC16
)PTR_SEG_OFF_TO_SEGPTR( sel
, offset
);
781 /***********************************************************************
782 * MODULE_SetEntryPoint
784 * Change the value of an entry point. Use with caution!
785 * It can only change the offset value, not the selector.
787 BOOL16
MODULE_SetEntryPoint( HMODULE16 hModule
, WORD ordinal
, WORD offset
)
793 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
795 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
796 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
798 /* Skipping this bundle */
802 case 0: p
+= 2; break; /* unused */
803 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
804 default: p
+= 2 + *p
* 3; break; /* fixed */
807 if (!*p
) return FALSE
;
813 case 0xff: /* moveable */
814 p
+= 2 + 6 * (ordinal
- curOrdinal
);
815 *(WORD
*)(p
+ 4) = offset
;
818 p
+= 2 + 3 * (ordinal
- curOrdinal
);
819 *(WORD
*)(p
+ 1) = offset
;
826 /***********************************************************************
827 * MODULE_GetWndProcEntry16 (not a Windows API function)
829 * Return an entry point from the WPROCS dll.
832 FARPROC16
MODULE_GetWndProcEntry16( const char *name
)
836 static HMODULE16 hModule
= 0;
838 if (!hModule
) hModule
= GetModuleHandle( "WPROCS" );
839 ordinal
= MODULE_GetOrdinal( hModule
, name
);
840 if (!(ret
= MODULE_GetEntryPoint( hModule
, ordinal
)))
841 fprintf( stderr
, "GetWndProc16: %s not found, please report\n", name
);
847 /***********************************************************************
848 * MODULE_GetModuleName
850 LPSTR
MODULE_GetModuleName( HMODULE16 hModule
)
854 static char buffer
[10];
856 if (!(pModule
= MODULE_GetPtr( hModule
))) return NULL
;
857 p
= (BYTE
*)pModule
+ pModule
->name_table
;
859 memcpy( buffer
, p
+ 1, len
);
865 /**********************************************************************
866 * MODULE_RegisterModule
868 void MODULE_RegisterModule( NE_MODULE
*pModule
)
870 pModule
->next
= hFirstModule
;
871 hFirstModule
= pModule
->self
;
875 /**********************************************************************
878 * Find a module from a path name.
880 HMODULE16
MODULE_FindModule( LPCSTR path
)
882 HMODULE16 hModule
= hFirstModule
;
883 LPCSTR filename
, dotptr
, modulepath
, modulename
;
884 BYTE len
, *name_table
;
886 if (!(filename
= strrchr( path
, '\\' ))) filename
= path
;
888 if ((dotptr
= strrchr( filename
, '.' )) != NULL
)
889 len
= (BYTE
)(dotptr
- filename
);
890 else len
= strlen( filename
);
894 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
896 modulepath
= NE_MODULE_NAME(pModule
);
897 if (!(modulename
= strrchr( modulepath
, '\\' )))
898 modulename
= modulepath
;
900 if (!lstrcmpi32A( modulename
, filename
)) return hModule
;
902 name_table
= (BYTE
*)pModule
+ pModule
->name_table
;
903 if ((*name_table
== len
) && !lstrncmpi32A(filename
, name_table
+1, len
))
905 hModule
= pModule
->next
;
911 /**********************************************************************
914 * Call a DLL's WEP, allowing it to shut down.
915 * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
917 static BOOL16
MODULE_CallWEP( HMODULE16 hModule
)
919 FARPROC16 WEP
= (FARPROC16
)0;
920 WORD ordinal
= MODULE_GetOrdinal( hModule
, "WEP" );
922 if (ordinal
) WEP
= MODULE_GetEntryPoint( hModule
, ordinal
);
925 dprintf_module( stddeb
, "module %04x doesn't have a WEP\n", hModule
);
928 return CallWindowsExitProc( WEP
, WEP_FREE_DLL
);
932 /**********************************************************************
935 * Remove a module from memory.
937 static void MODULE_FreeModule( HMODULE16 hModule
)
939 HMODULE16
*hPrevModule
;
941 SEGTABLEENTRY
*pSegment
;
945 if (!(pModule
= MODULE_GetPtr( hModule
))) return;
946 if (pModule
->flags
& NE_FFLAGS_BUILTIN
)
947 return; /* Can't free built-in module */
949 if (pModule
->flags
& NE_FFLAGS_LIBMODULE
) MODULE_CallWEP( hModule
);
951 /* Free the objects owned by the module */
953 HOOK_FreeModuleHooks( hModule
);
954 CLASS_FreeModuleClasses( hModule
);
956 /* Clear magic number just in case */
958 pModule
->magic
= pModule
->self
= 0;
960 /* Remove it from the linked list */
962 hPrevModule
= &hFirstModule
;
963 while (*hPrevModule
&& (*hPrevModule
!= hModule
))
965 hPrevModule
= &(MODULE_GetPtr( *hPrevModule
))->next
;
967 if (*hPrevModule
) *hPrevModule
= pModule
->next
;
969 /* Free all the segments */
971 pSegment
= NE_SEG_TABLE( pModule
);
972 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
974 GlobalFree16( pSegment
->selector
);
977 /* Free the referenced modules */
979 pModRef
= (HMODULE16
*)NE_MODULE_TABLE( pModule
);
980 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
982 FreeModule16( *pModRef
);
985 /* Free the module storage */
987 if (pModule
->nrname_handle
) GlobalFree16( pModule
->nrname_handle
);
988 if (pModule
->dlls_to_init
) GlobalFree16( pModule
->dlls_to_init
);
989 GlobalFree16( hModule
);
991 /* Remove module from cache */
993 if (hCachedModule
== hModule
) hCachedModule
= 0;
997 /**********************************************************************
998 * LoadModule (KERNEL.45)
1000 HINSTANCE16
LoadModule( LPCSTR name
, LPVOID paramBlock
)
1003 HINSTANCE16 hInstance
, hPrevInstance
;
1005 LOADPARAMS
*params
= (LOADPARAMS
*)paramBlock
;
1008 WORD
*pModRef
, *pDLLs
;
1012 hModule
= MODULE_FindModule( name
);
1014 if (!hModule
) /* We have to load the module */
1016 /* Try to load the built-in first if not disabled */
1017 if ((hModule
= BUILTIN_LoadModule( name
, FALSE
))) return hModule
;
1019 if ((hFile
= OpenFile( name
, &ofs
, OF_READ
)) == HFILE_ERROR
)
1021 /* Now try the built-in even if disabled */
1022 if ((hModule
= BUILTIN_LoadModule( name
, TRUE
)))
1024 fprintf( stderr
, "Warning: could not load Windows DLL '%s', using built-in module.\n", name
);
1027 return 2; /* File not found */
1030 /* Create the module structure */
1032 hModule
= MODULE_LoadExeHeader( hFile
, &ofs
);
1035 /* FIXME: Hack because PE_LoadModule is recursive */
1036 int fd
= dup( FILE_GetUnixHandle(hFile
) );
1038 if (hModule
== 21) hModule
= PE_LoadModule( fd
, &ofs
, paramBlock
);
1041 fprintf( stderr
, "LoadModule: can't load '%s', error=%d\n",
1046 pModule
= MODULE_GetPtr( hModule
);
1048 /* Allocate the segments for this module */
1050 MODULE_CreateSegments( hModule
);
1053 hInstance
= MODULE_CreateInstance( hModule
, (LOADPARAMS
*)paramBlock
);
1055 /* Load the referenced DLLs */
1057 pModRef
= (WORD
*)((char *)pModule
+ pModule
->modref_table
);
1058 pDLLs
= (WORD
*)GlobalLock16( pModule
->dlls_to_init
);
1059 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
1062 BYTE
*pstr
= (BYTE
*)pModule
+ pModule
->import_table
+ *pModRef
;
1063 memcpy( buffer
, pstr
+ 1, *pstr
);
1064 strcpy( buffer
+ *pstr
, ".dll" );
1065 dprintf_module( stddeb
, "Loading '%s'\n", buffer
);
1066 if (!(*pModRef
= MODULE_FindModule( buffer
)))
1068 /* If the DLL is not loaded yet, load it and store */
1069 /* its handle in the list of DLLs to initialize. */
1072 if ((hDLL
= LoadModule( buffer
, (LPVOID
)-1 )) == 2) /* file not found */
1076 /* Try with prepending the path of the current module */
1077 GetModuleFileName( hModule
, buffer
, sizeof(buffer
) );
1078 if (!(p
= strrchr( buffer
, '\\' ))) p
= buffer
;
1079 memcpy( p
+ 1, pstr
+ 1, *pstr
);
1080 strcpy( p
+ 1 + *pstr
, ".dll" );
1081 hDLL
= LoadModule( buffer
, (LPVOID
)-1 );
1085 fprintf( stderr
, "Could not load '%s' required by '%s', error = %d\n",
1086 buffer
, name
, hDLL
);
1087 return 2; /* file not found */
1089 *pModRef
= GetExePtr( hDLL
);
1090 *pDLLs
++ = *pModRef
;
1092 else /* Increment the reference count of the DLL */
1094 NE_MODULE
*pOldDLL
= MODULE_GetPtr( *pModRef
);
1095 if (pOldDLL
) pOldDLL
->count
++;
1099 /* Load the segments */
1101 if (pModule
->flags
& NE_FFLAGS_SELFLOAD
)
1104 /* Handle self loading modules */
1105 SEGTABLEENTRY
* pSegTable
= (SEGTABLEENTRY
*) NE_SEG_TABLE(pModule
);
1106 SELFLOADHEADER
*selfloadheader
;
1107 STACK16FRAME
*stack16Top
;
1108 HMODULE16 hselfload
= GetModuleHandle("WPROCS");
1109 WORD oldss
, oldsp
, saved_dgroup
= pSegTable
[pModule
->dgroup
- 1].selector
;
1110 fprintf (stderr
, "Warning: %*.*s is a self-loading module\n"
1111 "Support for self-loading modules is very experimental\n",
1112 *((BYTE
*)pModule
+ pModule
->name_table
),
1113 *((BYTE
*)pModule
+ pModule
->name_table
),
1114 (char *)pModule
+ pModule
->name_table
+ 1);
1115 NE_LoadSegment( hModule
, 1 );
1116 selfloadheader
= (SELFLOADHEADER
*)
1117 PTR_SEG_OFF_TO_LIN(pSegTable
->selector
, 0);
1118 selfloadheader
->EntryAddrProc
=
1119 MODULE_GetEntryPoint(hselfload
,27);
1120 selfloadheader
->MyAlloc
= MODULE_GetEntryPoint(hselfload
,28);
1121 selfloadheader
->SetOwner
= MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1122 pModule
->self_loading_sel
= GlobalHandleToSel(
1123 GLOBAL_Alloc (GMEM_ZEROINIT
,
1124 0xFF00, hModule
, FALSE
, FALSE
, FALSE
)
1126 oldss
= IF1632_Saved16_ss
;
1127 oldsp
= IF1632_Saved16_sp
;
1128 IF1632_Saved16_ss
= pModule
->self_loading_sel
;
1129 IF1632_Saved16_sp
= 0xFF00 - sizeof(*stack16Top
);
1130 stack16Top
= CURRENT_STACK16
;
1131 stack16Top
->saved_ss
= 0;
1132 stack16Top
->saved_sp
= 0;
1133 stack16Top
->ds
= stack16Top
->es
= pModule
->self_loading_sel
;
1134 stack16Top
->entry_point
= 0;
1135 stack16Top
->entry_ip
= 0;
1136 stack16Top
->entry_cs
= 0;
1141 if (!IF1632_Stack32_base
) {
1142 STACK32FRAME
* frame32
;
1144 /* Setup an initial 32 bit stack frame */
1145 hInitialStack32
= GLOBAL_Alloc( GMEM_FIXED
, 0x10000,
1146 hModule
, FALSE
, FALSE
,
1149 /* Create the 32-bit stack frame */
1151 *(DWORD
*)GlobalLock16(hInitialStack32
) = 0xDEADBEEF;
1152 stack32Top
= (char*)GlobalLock16(hInitialStack32
) +
1154 frame32
= (STACK32FRAME
*)stack32Top
- 1;
1155 frame32
->saved_esp
= (DWORD
)stack32Top
;
1162 frame32
->retaddr
= 0;
1163 frame32
->codeselector
= WINE_CODE_SELECTOR
;
1164 /* pTask->esp = (DWORD)frame32; */
1165 IF1632_Stack32_base
= WIN16_GlobalLock16(hInitialStack32
);
1168 hf
= FILE_DupUnixHandle( MODULE_OpenFile( hModule
) );
1169 CallTo16_word_ww( selfloadheader
->BootApp
, hModule
, hf
);
1171 /* some BootApp procs overwrite the selector of dgroup */
1172 pSegTable
[pModule
->dgroup
- 1].selector
= saved_dgroup
;
1173 IF1632_Saved16_ss
= oldss
;
1174 IF1632_Saved16_sp
= oldsp
;
1175 for (i
= 2; i
<= pModule
->seg_count
; i
++) NE_LoadSegment( hModule
, i
);
1176 if (hInitialStack32
){
1177 GlobalFree16(hInitialStack32
);
1178 IF1632_Stack32_base
= hInitialStack32
= 0;
1183 for (i
= 1; i
<= pModule
->seg_count
; i
++)
1184 NE_LoadSegment( hModule
, i
);
1187 /* Fixup the functions prologs */
1189 NE_FixupPrologs( pModule
);
1191 /* Make sure the usage count is 1 on the first loading of */
1192 /* the module, even if it contains circular DLL references */
1198 pModule
= MODULE_GetPtr( hModule
);
1199 hPrevInstance
= MODULE_GetInstance( hModule
);
1200 hInstance
= MODULE_CreateInstance( hModule
, params
);
1201 if (hInstance
!= hPrevInstance
) /* not a library */
1202 NE_LoadSegment( hModule
, pModule
->dgroup
);
1206 lstrcpyn32A( ofs
.szPathName
, name
, sizeof(ofs
.szPathName
) );
1207 if ((hModule
= MODULE_CreateDummyModule( &ofs
)) < 32) return hModule
;
1208 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
1210 hInstance
= MODULE_CreateInstance( hModule
, params
);
1211 #endif /* WINELIB */
1213 /* Create a task for this instance */
1215 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
) && (paramBlock
!= (LPVOID
)-1))
1220 /* PowerPoint passes NULL as showCmd */
1221 if (params
->showCmd
)
1222 showcmd
= *((WORD
*)PTR_SEG_TO_LIN(params
->showCmd
)+1);
1224 showcmd
= 0; /* FIXME: correct */
1226 hTask
= TASK_CreateTask( hModule
, hInstance
, hPrevInstance
,
1227 params
->hEnvironment
,
1228 (LPSTR
)PTR_SEG_TO_LIN( params
->cmdLine
),
1231 if( hTask
&& TASK_GetNextTask(hTask
)) Yield();
1238 /**********************************************************************
1239 * FreeModule16 (KERNEL.46)
1241 BOOL16
FreeModule16( HMODULE16 hModule
)
1245 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1246 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
1248 dprintf_module( stddeb
, "FreeModule16: %s count %d\n",
1249 MODULE_GetModuleName(hModule
), pModule
->count
);
1250 if (--pModule
->count
== 0) MODULE_FreeModule( hModule
);
1255 /**********************************************************************
1256 * GetModuleHandle (KERNEL.47)
1258 HMODULE16
WIN16_GetModuleHandle( SEGPTR name
)
1260 if (HIWORD(name
) == 0) return GetExePtr( (HINSTANCE16
)name
);
1261 return MODULE_FindModule( PTR_SEG_TO_LIN(name
) );
1264 HMODULE16
GetModuleHandle( LPCSTR name
)
1266 return MODULE_FindModule( name
);
1270 /**********************************************************************
1271 * GetModuleUsage (KERNEL.48)
1273 INT16
GetModuleUsage( HINSTANCE16 hModule
)
1277 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1278 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
1279 dprintf_module( stddeb
, "GetModuleUsage(%04x): returning %d\n",
1280 hModule
, pModule
->count
);
1281 return pModule
->count
;
1285 /**********************************************************************
1286 * GetModuleFileName (KERNEL.49)
1288 INT16
GetModuleFileName( HINSTANCE16 hModule
, LPSTR lpFileName
, INT16 nSize
)
1292 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1293 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
1294 lstrcpyn32A( lpFileName
, NE_MODULE_NAME(pModule
), nSize
);
1295 dprintf_module( stddeb
, "GetModuleFilename: %s\n", lpFileName
);
1296 return strlen(lpFileName
);
1299 /**********************************************************************
1300 * GetModuleName (KERNEL.27)
1302 BOOL16
GetModuleName( HINSTANCE16 hinst
, LPSTR buf
, INT16 nSize
)
1304 LPSTR name
= MODULE_GetModuleName(hinst
);
1306 if (!name
) return FALSE
;
1307 lstrcpyn32A( buf
, name
, nSize
);
1312 /***********************************************************************
1313 * LoadLibrary (KERNEL.95)
1315 HINSTANCE16
LoadLibrary( LPCSTR libname
)
1321 fprintf( stderr
, "LoadLibrary not supported in Winelib\n" );
1324 dprintf_module( stddeb
, "LoadLibrary: (%08x) %s\n", (int)libname
, libname
);
1326 /* This does not increment the module reference count, and will
1327 * therefore cause crashes on FreeLibrary calls.
1328 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1330 handle
= LoadModule( libname
, (LPVOID
)-1 );
1331 if (handle
== (HINSTANCE16
)2) /* file not found */
1334 lstrcpyn32A( buffer
, libname
, 252 );
1335 strcat( buffer
, ".dll" );
1336 handle
= LoadModule( buffer
, (LPVOID
)-1 );
1339 if (handle
>= (HINSTANCE16
)32) NE_InitializeDLLs( GetExePtr(handle
) );
1345 /***********************************************************************
1346 * FreeLibrary (KERNEL.96)
1348 void FreeLibrary( HINSTANCE16 handle
)
1350 dprintf_module( stddeb
,"FreeLibrary: %04x\n", handle
);
1351 FreeModule16( handle
);
1355 /***********************************************************************
1356 * WinExec (KERNEL.166)
1358 HINSTANCE16
WinExec( LPSTR lpCmdLine
, WORD nCmdShow
)
1361 HGLOBAL16 cmdShowHandle
, cmdLineHandle
;
1364 char *p
, *cmdline
, filename
[256];
1365 static int use_load_module
= 1;
1367 if (!(cmdShowHandle
= GlobalAlloc16( 0, 2 * sizeof(WORD
) )))
1368 return 8; /* Out of memory */
1369 if (!(cmdLineHandle
= GlobalAlloc16( 0, 256 )))
1371 GlobalFree16( cmdShowHandle
);
1372 return 8; /* Out of memory */
1375 /* Store nCmdShow */
1377 cmdShowPtr
= (WORD
*)GlobalLock16( cmdShowHandle
);
1379 cmdShowPtr
[1] = nCmdShow
;
1381 /* Build the filename and command-line */
1383 cmdline
= (char *)GlobalLock16( cmdLineHandle
);
1384 lstrcpyn32A(filename
, lpCmdLine
, sizeof(filename
) - 4 /* for extension */);
1385 for (p
= filename
; *p
&& (*p
!= ' ') && (*p
!= '\t'); p
++);
1386 if (*p
) lstrcpyn32A( cmdline
, p
+ 1, 128 );
1387 else cmdline
[0] = '\0';
1390 /* Now load the executable file */
1392 if (use_load_module
)
1395 /* WINELIB: Use LoadModule() only for the program itself */
1396 use_load_module
= 0;
1397 params
.hEnvironment
= (HGLOBAL16
)GetDOSEnvironment();
1399 params
.hEnvironment
= (HGLOBAL16
)SELECTOROF( GetDOSEnvironment() );
1400 #endif /* WINELIB */
1401 params
.cmdLine
= (SEGPTR
)WIN16_GlobalLock16( cmdLineHandle
);
1402 params
.showCmd
= (SEGPTR
)WIN16_GlobalLock16( cmdShowHandle
);
1403 params
.reserved
= 0;
1404 handle
= LoadModule( filename
, ¶ms
);
1405 if (handle
== 2) /* file not found */
1407 /* Check that the original file name did not have a suffix */
1408 p
= strrchr(filename
, '.');
1409 if (!p
|| (strchr(p
, '/') && strchr(p
, '\\')))
1411 p
= filename
+ strlen(filename
);
1412 strcpy( p
, ".exe" );
1413 handle
= LoadModule( filename
, ¶ms
);
1414 *p
= '\0'; /* Remove extension */
1422 /* Try to start it as a unix program */
1426 const char *unixfilename
;
1427 const char *argv
[256], **argptr
;
1428 int iconic
= (nCmdShow
== SW_SHOWMINIMIZED
||
1429 nCmdShow
== SW_SHOWMINNOACTIVE
);
1431 /* get unixfilename */
1432 if (strchr(filename
, '/') ||
1433 strchr(filename
, ':') ||
1434 strchr(filename
, '\\'))
1435 unixfilename
= DOSFS_GetUnixFileName(filename
, 1);
1436 else unixfilename
= filename
;
1442 if (iconic
) *argptr
++ = "-iconic";
1443 *argptr
++ = unixfilename
;
1447 while (*p
&& (*p
== ' ' || *p
== '\t')) *p
++ = '\0';
1450 while (*p
&& *p
!= ' ' && *p
!= '\t') p
++;
1455 execvp(argv
[0], (char**)argv
);
1465 if (iconic
) *argptr
++ = "-iconic";
1466 *argptr
++ = lpCmdLine
;
1470 execvp(argv
[0] , (char**)argv
);
1473 fprintf(stderr
, "WinExec: can't exec 'wine %s'\n", lpCmdLine
);
1479 GlobalFree16( cmdShowHandle
);
1480 GlobalFree16( cmdLineHandle
);
1485 /***********************************************************************
1486 * GetProcAddress16 (KERNEL.50)
1488 FARPROC16
GetProcAddress16( HMODULE16 hModule
, SEGPTR name
)
1493 if (!hModule
) hModule
= GetCurrentTask();
1494 hModule
= GetExePtr( hModule
);
1496 if (HIWORD(name
) != 0)
1498 ordinal
= MODULE_GetOrdinal( hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1499 dprintf_module( stddeb
, "GetProcAddress: %04x '%s'\n",
1500 hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1504 ordinal
= LOWORD(name
);
1505 dprintf_module( stddeb
, "GetProcAddress: %04x %04x\n",
1508 if (!ordinal
) return (FARPROC16
)0;
1510 ret
= MODULE_GetEntryPoint( hModule
, ordinal
);
1512 dprintf_module( stddeb
, "GetProcAddress: returning %08x\n", (UINT32
)ret
);
1517 /***********************************************************************
1518 * GetProcAddress32 (KERNEL32.257)
1520 FARPROC32
GetProcAddress32( HMODULE32 hModule
, LPCSTR function
)
1525 hModule
= GetExePtr( hModule
);
1526 if (!(pModule
= MODULE_GetPtr( hModule
)))
1527 return (FARPROC32
)0;
1528 if (!(pModule
->flags
& NE_FFLAGS_WIN32
) || !pModule
->pe_module
)
1529 return (FARPROC32
)0;
1530 if (pModule
->flags
& NE_FFLAGS_BUILTIN
)
1531 return BUILTIN_GetProcAddress32( pModule
, function
);
1532 return PE_FindExportedFunction( pModule
->pe_module
, function
);
1539 /**********************************************************************
1540 * GetExpWinVer (KERNEL.167)
1542 WORD
GetExpWinVer( HMODULE16 hModule
)
1544 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
1545 return pModule
? pModule
->expected_version
: 0;
1549 /**********************************************************************
1550 * IsSharedSelector (KERNEL.345)
1552 BOOL16
IsSharedSelector( HANDLE16 selector
)
1554 /* Check whether the selector belongs to a DLL */
1555 NE_MODULE
*pModule
= MODULE_GetPtr( GetExePtr( selector
));
1556 if (!pModule
) return FALSE
;
1557 return (pModule
->flags
& NE_FFLAGS_LIBMODULE
) != 0;
1561 /**********************************************************************
1562 * ModuleFirst (TOOLHELP.59)
1564 BOOL16
ModuleFirst( MODULEENTRY
*lpme
)
1566 lpme
->wNext
= hFirstModule
;
1567 return ModuleNext( lpme
);
1571 /**********************************************************************
1572 * ModuleNext (TOOLHELP.60)
1574 BOOL16
ModuleNext( MODULEENTRY
*lpme
)
1578 if (!lpme
->wNext
) return FALSE
;
1579 if (!(pModule
= MODULE_GetPtr( lpme
->wNext
))) return FALSE
;
1580 strncpy( lpme
->szModule
, (char *)pModule
+ pModule
->name_table
,
1582 lpme
->szModule
[MAX_MODULE_NAME
] = '\0';
1583 lpme
->hModule
= lpme
->wNext
;
1584 lpme
->wcUsage
= pModule
->count
;
1585 strncpy( lpme
->szExePath
, NE_MODULE_NAME(pModule
), MAX_PATH
);
1586 lpme
->szExePath
[MAX_PATH
] = '\0';
1587 lpme
->wNext
= pModule
->next
;
1592 /**********************************************************************
1593 * ModuleFindName (TOOLHELP.61)
1595 BOOL16
ModuleFindName( MODULEENTRY
*lpme
, LPCSTR name
)
1597 lpme
->wNext
= GetModuleHandle( name
);
1598 return ModuleNext( lpme
);
1602 /**********************************************************************
1603 * ModuleFindHandle (TOOLHELP.62)
1605 BOOL16
ModuleFindHandle( MODULEENTRY
*lpme
, HMODULE16 hModule
)
1607 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1608 lpme
->wNext
= hModule
;
1609 return ModuleNext( lpme
);