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 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 HINSTANCE 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 FILE_Read( hFile, (buffer), (size) ) == (size)))
464 _llseek( hFile
, 0, SEEK_SET
);
465 if ((FILE_Read(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 (FILE_Read( 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 (FILE_Read( 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 (FILE_Read( 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 HINSTANCE
LoadModule( LPCSTR name
, LPVOID paramBlock
)
1003 HANDLE 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 /* FIXME: we probably need a DOS handle here */
1169 hf
= FILE_DupUnixHandle( MODULE_OpenFile( hModule
) );
1170 CallTo16_word_ww( selfloadheader
->BootApp
, hModule
, hf
);
1172 /* some BootApp procs overwrite the selector of dgroup */
1173 pSegTable
[pModule
->dgroup
- 1].selector
= saved_dgroup
;
1174 IF1632_Saved16_ss
= oldss
;
1175 IF1632_Saved16_sp
= oldsp
;
1176 for (i
= 2; i
<= pModule
->seg_count
; i
++) NE_LoadSegment( hModule
, i
);
1177 if (hInitialStack32
){
1178 GlobalFree16(hInitialStack32
);
1179 IF1632_Stack32_base
= hInitialStack32
= 0;
1184 for (i
= 1; i
<= pModule
->seg_count
; i
++)
1185 NE_LoadSegment( hModule
, i
);
1188 /* Fixup the functions prologs */
1190 NE_FixupPrologs( pModule
);
1192 /* Make sure the usage count is 1 on the first loading of */
1193 /* the module, even if it contains circular DLL references */
1199 pModule
= MODULE_GetPtr( hModule
);
1200 hPrevInstance
= MODULE_GetInstance( hModule
);
1201 hInstance
= MODULE_CreateInstance( hModule
, params
);
1202 if (hInstance
!= hPrevInstance
) /* not a library */
1203 NE_LoadSegment( hModule
, pModule
->dgroup
);
1207 lstrcpyn32A( ofs
.szPathName
, name
, sizeof(ofs
.szPathName
) );
1208 if ((hModule
= MODULE_CreateDummyModule( &ofs
)) < 32) return hModule
;
1209 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
1211 hInstance
= MODULE_CreateInstance( hModule
, params
);
1212 #endif /* WINELIB */
1214 /* Create a task for this instance */
1216 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 */
1225 TASK_CreateTask( hModule
, hInstance
, hPrevInstance
,
1226 params
->hEnvironment
,
1227 (LPSTR
)PTR_SEG_TO_LIN( params
->cmdLine
),
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
);
1296 /**********************************************************************
1297 * GetModuleName (KERNEL.27)
1299 BOOL16
GetModuleName( HINSTANCE16 hinst
, LPSTR buf
, INT16 nSize
)
1301 LPSTR name
= MODULE_GetModuleName(hinst
);
1303 if (!name
) return FALSE
;
1304 lstrcpyn32A( buf
, name
, nSize
);
1309 /***********************************************************************
1310 * LoadLibrary (KERNEL.95)
1312 HANDLE
LoadLibrary( LPCSTR libname
)
1318 fprintf( stderr
, "LoadLibrary not supported in Winelib\n" );
1321 dprintf_module( stddeb
, "LoadLibrary: (%08x) %s\n", (int)libname
, libname
);
1323 /* This does not increment the module reference count, and will
1324 * therefore cause crashes on FreeLibrary calls.
1325 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1327 handle
= LoadModule( libname
, (LPVOID
)-1 );
1328 if (handle
== (HANDLE
)2) /* file not found */
1331 lstrcpyn32A( buffer
, libname
, 252 );
1332 strcat( buffer
, ".dll" );
1333 handle
= LoadModule( buffer
, (LPVOID
)-1 );
1336 if (handle
>= (HANDLE
)32) NE_InitializeDLLs( GetExePtr(handle
) );
1342 /***********************************************************************
1343 * FreeLibrary (KERNEL.96)
1345 void FreeLibrary( HANDLE handle
)
1347 dprintf_module( stddeb
,"FreeLibrary: %04x\n", handle
);
1348 FreeModule16( handle
);
1352 /***********************************************************************
1353 * WinExec (KERNEL.166)
1355 HANDLE
WinExec( LPSTR lpCmdLine
, WORD nCmdShow
)
1358 HGLOBAL16 cmdShowHandle
, cmdLineHandle
;
1361 char *p
, *cmdline
, filename
[256];
1362 static int use_load_module
= 1;
1364 if (!(cmdShowHandle
= GlobalAlloc16( 0, 2 * sizeof(WORD
) )))
1365 return 8; /* Out of memory */
1366 if (!(cmdLineHandle
= GlobalAlloc16( 0, 256 )))
1368 GlobalFree16( cmdShowHandle
);
1369 return 8; /* Out of memory */
1372 /* Store nCmdShow */
1374 cmdShowPtr
= (WORD
*)GlobalLock16( cmdShowHandle
);
1376 cmdShowPtr
[1] = nCmdShow
;
1378 /* Build the filename and command-line */
1380 cmdline
= (char *)GlobalLock16( cmdLineHandle
);
1381 lstrcpyn32A(filename
, lpCmdLine
, sizeof(filename
) - 4 /* for extension */);
1382 for (p
= filename
; *p
&& (*p
!= ' ') && (*p
!= '\t'); p
++);
1383 if (*p
) lstrcpyn32A( cmdline
, p
+ 1, 128 );
1384 else cmdline
[0] = '\0';
1387 /* Now load the executable file */
1389 if (use_load_module
)
1392 /* WINELIB: Use LoadModule() only for the program itself */
1393 use_load_module
= 0;
1394 params
.hEnvironment
= (HANDLE
)GetDOSEnvironment();
1396 params
.hEnvironment
= (HANDLE
)SELECTOROF( GetDOSEnvironment() );
1397 #endif /* WINELIB */
1398 params
.cmdLine
= (SEGPTR
)WIN16_GlobalLock16( cmdLineHandle
);
1399 params
.showCmd
= (SEGPTR
)WIN16_GlobalLock16( cmdShowHandle
);
1400 params
.reserved
= 0;
1401 handle
= LoadModule( filename
, ¶ms
);
1402 if (handle
== 2) /* file not found */
1404 /* Check that the original file name did not have a suffix */
1405 p
= strrchr(filename
, '.');
1406 if (!p
|| (strchr(p
, '/') && strchr(p
, '\\')))
1408 p
= filename
+ strlen(filename
);
1409 strcpy( p
, ".exe" );
1410 handle
= LoadModule( filename
, ¶ms
);
1411 *p
= '\0'; /* Remove extension */
1419 /* Try to start it as a unix program */
1423 const char *unixfilename
;
1424 const char *argv
[256], **argptr
;
1425 int iconic
= (nCmdShow
== SW_SHOWMINIMIZED
||
1426 nCmdShow
== SW_SHOWMINNOACTIVE
);
1428 /* get unixfilename */
1429 if (strchr(filename
, '/') ||
1430 strchr(filename
, ':') ||
1431 strchr(filename
, '\\'))
1432 unixfilename
= DOSFS_GetUnixFileName(filename
, 1);
1433 else unixfilename
= filename
;
1439 if (iconic
) *argptr
++ = "-iconic";
1440 *argptr
++ = unixfilename
;
1444 while (*p
&& (*p
== ' ' || *p
== '\t')) *p
++ = '\0';
1447 while (*p
&& *p
!= ' ' && *p
!= '\t') p
++;
1452 execvp(argv
[0], (char**)argv
);
1462 if (iconic
) *argptr
++ = "-iconic";
1463 *argptr
++ = lpCmdLine
;
1467 execvp(argv
[0] , (char**)argv
);
1470 fprintf(stderr
, "WinExec: can't exec 'wine %s'\n", lpCmdLine
);
1476 GlobalFree16( cmdShowHandle
);
1477 GlobalFree16( cmdLineHandle
);
1480 if (handle
< (HANDLE
)32) /* Error? */
1483 /* FIXME: Yield never returns!
1484 We may want to run more applications or start the debugger
1485 before calling Yield. If we don't Yield will be called immdiately
1486 after returning. Why is it needed for Word anyway? */
1487 Yield(); /* program is executed immediately ....needed for word */
1494 /***********************************************************************
1495 * GetProcAddress16 (KERNEL.50)
1497 FARPROC16
GetProcAddress16( HMODULE16 hModule
, SEGPTR name
)
1502 if (!hModule
) hModule
= GetCurrentTask();
1503 hModule
= GetExePtr( hModule
);
1505 if (HIWORD(name
) != 0)
1507 ordinal
= MODULE_GetOrdinal( hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1508 dprintf_module( stddeb
, "GetProcAddress: %04x '%s'\n",
1509 hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1513 ordinal
= LOWORD(name
);
1514 dprintf_module( stddeb
, "GetProcAddress: %04x %04x\n",
1517 if (!ordinal
) return (FARPROC16
)0;
1519 ret
= MODULE_GetEntryPoint( hModule
, ordinal
);
1521 dprintf_module( stddeb
, "GetProcAddress: returning %08x\n", (UINT32
)ret
);
1526 /***********************************************************************
1527 * GetProcAddress32 (KERNEL32.257)
1529 FARPROC32
GetProcAddress32( HMODULE32 hModule
, LPCSTR function
)
1534 hModule
= GetExePtr( hModule
);
1535 if (!(pModule
= MODULE_GetPtr( hModule
)))
1536 return (FARPROC32
)0;
1537 if (!(pModule
->flags
& NE_FFLAGS_WIN32
) || !pModule
->pe_module
)
1538 return (FARPROC32
)0;
1539 if (pModule
->flags
& NE_FFLAGS_BUILTIN
)
1540 return BUILTIN_GetProcAddress32( pModule
, function
);
1541 return PE_FindExportedFunction( pModule
->pe_module
, function
);
1548 /**********************************************************************
1549 * GetExpWinVer (KERNEL.167)
1551 WORD
GetExpWinVer( HMODULE16 hModule
)
1553 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
1554 return pModule
? pModule
->expected_version
: 0;
1558 /**********************************************************************
1559 * IsSharedSelector (KERNEL.345)
1561 BOOL16
IsSharedSelector( HANDLE16 selector
)
1563 /* Check whether the selector belongs to a DLL */
1564 NE_MODULE
*pModule
= MODULE_GetPtr( GetExePtr( selector
));
1565 if (!pModule
) return FALSE
;
1566 return (pModule
->flags
& NE_FFLAGS_LIBMODULE
) != 0;
1570 /**********************************************************************
1571 * ModuleFirst (TOOLHELP.59)
1573 BOOL16
ModuleFirst( MODULEENTRY
*lpme
)
1575 lpme
->wNext
= hFirstModule
;
1576 return ModuleNext( lpme
);
1580 /**********************************************************************
1581 * ModuleNext (TOOLHELP.60)
1583 BOOL16
ModuleNext( MODULEENTRY
*lpme
)
1587 if (!lpme
->wNext
) return FALSE
;
1588 if (!(pModule
= MODULE_GetPtr( lpme
->wNext
))) return FALSE
;
1589 strncpy( lpme
->szModule
, (char *)pModule
+ pModule
->name_table
,
1591 lpme
->szModule
[MAX_MODULE_NAME
] = '\0';
1592 lpme
->hModule
= lpme
->wNext
;
1593 lpme
->wcUsage
= pModule
->count
;
1594 strncpy( lpme
->szExePath
, NE_MODULE_NAME(pModule
), MAX_PATH
);
1595 lpme
->szExePath
[MAX_PATH
] = '\0';
1596 lpme
->wNext
= pModule
->next
;
1601 /**********************************************************************
1602 * ModuleFindName (TOOLHELP.61)
1604 BOOL16
ModuleFindName( MODULEENTRY
*lpme
, LPCSTR name
)
1606 lpme
->wNext
= GetModuleHandle( name
);
1607 return ModuleNext( lpme
);
1611 /**********************************************************************
1612 * ModuleFindHandle (TOOLHELP.62)
1614 BOOL16
ModuleFindHandle( MODULEENTRY
*lpme
, HMODULE16 hModule
)
1616 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1617 lpme
->wNext
= hModule
;
1618 return ModuleNext( lpme
);