4 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
21 #include "stackframe.h"
30 extern HINSTANCE
PE_LoadModule( int fd
, OFSTRUCT
*ofs
, LOADPARAMS
* params
);
32 static HMODULE hFirstModule
= 0;
33 static HMODULE hCachedModule
= 0; /* Module cached by MODULE_OpenFile */
36 static HANDLE hInitialStack32
= 0;
38 /***********************************************************************
41 * Load a built-in module. If the 'force' parameter is FALSE, we only
42 * load the module if it has not been disabled via the -dll option.
45 static HMODULE
MODULE_LoadBuiltin( LPCSTR name
, BOOL force
)
49 SEGTABLEENTRY
*pSegTable
;
53 /* Fix the name in case we have a full path and extension */
55 if ((p
= strrchr( name
, '\\' ))) name
= p
+ 1;
56 lstrcpyn( dllname
, name
, sizeof(dllname
) );
57 if ((p
= strrchr( dllname
, '.' ))) *p
= '\0';
59 for (table
= dll_builtin_table
; table
->name
; table
++)
60 if (!lstrcmpi( table
->name
, dllname
)) break;
61 if (!table
->name
) return 0;
62 if ((table
->flags
& DLL_FLAG_NOT_USED
) && !force
) return 0;
64 hModule
= GLOBAL_CreateBlock( GMEM_MOVEABLE
, table
->module_start
,
65 table
->module_end
- table
->module_start
,
66 0, FALSE
, FALSE
, FALSE
, NULL
);
67 if (!hModule
) return 0;
68 FarSetOwner( hModule
, hModule
);
70 table
->hModule
= hModule
;
72 dprintf_module( stddeb
, "Built-in %s: hmodule=%04x\n",
73 table
->name
, hModule
);
74 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
75 pModule
->self
= hModule
;
77 if (pModule
->flags
& NE_FFLAGS_WIN32
)
79 pModule
->pe_module
= (PE_MODULE
*)table
;
81 else /* Win16 module */
83 /* Allocate the code segment */
85 pSegTable
= NE_SEG_TABLE( pModule
);
86 pSegTable
->selector
= GLOBAL_CreateBlock(GMEM_FIXED
, table
->code_start
,
87 pSegTable
->minsize
, hModule
,
88 TRUE
, TRUE
, FALSE
, NULL
);
89 if (!pSegTable
->selector
) return 0;
92 /* Allocate the data segment */
94 pSegTable
->selector
= GLOBAL_Alloc( GMEM_FIXED
, pSegTable
->minsize
,
95 hModule
, FALSE
, FALSE
, FALSE
);
96 if (!pSegTable
->selector
) return 0;
97 memcpy( GlobalLock( pSegTable
->selector
),
98 table
->data_start
, pSegTable
->minsize
);
101 pModule
->next
= hFirstModule
;
102 hFirstModule
= hModule
;
107 /***********************************************************************
110 * Create the built-in modules.
112 BOOL
MODULE_Init(void)
117 /* Load all modules marked as always used */
119 for (dll
= dll_builtin_table
; dll
->name
; dll
++)
120 if (dll
->flags
& DLL_FLAG_ALWAYS_USED
)
121 if (!MODULE_LoadBuiltin(dll
->name
, TRUE
)) return FALSE
;
123 /* Initialize KERNEL.178 (__WINFLAGS) with the correct flags value */
125 MODULE_SetEntryPoint( GetModuleHandle( "KERNEL" ), 178, GetWinFlags() );
130 /***********************************************************************
133 NE_MODULE
*MODULE_GetPtr( HMODULE hModule
)
135 NE_MODULE
*pModule
= (NE_MODULE
*)GlobalLock( hModule
);
136 if (!pModule
|| (pModule
->magic
!= NE_SIGNATURE
) ||
137 (pModule
->self
!= hModule
)) return NULL
;
142 /***********************************************************************
145 void MODULE_DumpModule( HMODULE hmodule
)
153 if (!(pModule
= MODULE_GetPtr( hmodule
)))
155 fprintf( stderr
, "**** %04x is not a module handle\n", hmodule
);
159 /* Dump the module info */
161 printf( "Module %04x:\n", hmodule
);
162 printf( "count=%d flags=%04x heap=%d stack=%d\n",
163 pModule
->count
, pModule
->flags
,
164 pModule
->heap_size
, pModule
->stack_size
);
165 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
166 pModule
->cs
, pModule
->ip
, pModule
->ss
, pModule
->sp
, pModule
->dgroup
,
167 pModule
->seg_count
, pModule
->modref_count
);
168 printf( "os_flags=%d swap_area=%d version=%04x\n",
169 pModule
->os_flags
, pModule
->min_swap_area
,
170 pModule
->expected_version
);
171 if (pModule
->flags
& NE_FFLAGS_WIN32
)
172 printf( "PE module=%08x\n", (unsigned int)pModule
->pe_module
);
174 /* Dump the file info */
176 printf( "Filename: '%s'\n", NE_MODULE_NAME(pModule
) );
178 /* Dump the segment table */
180 printf( "\nSegment table:\n" );
181 pSeg
= NE_SEG_TABLE( pModule
);
182 for (i
= 0; i
< pModule
->seg_count
; i
++, pSeg
++)
183 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
184 i
+ 1, pSeg
->filepos
, pSeg
->size
, pSeg
->flags
,
185 pSeg
->minsize
, pSeg
->selector
);
187 /* Dump the resource table */
189 printf( "\nResource table:\n" );
190 if (pModule
->res_table
)
192 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->res_table
);
193 printf( "Alignment: %d\n", *pword
++ );
196 struct resource_typeinfo_s
*ptr
= (struct resource_typeinfo_s
*)pword
;
197 struct resource_nameinfo_s
*pname
= (struct resource_nameinfo_s
*)(ptr
+ 1);
198 printf( "id=%04x count=%d\n", ptr
->type_id
, ptr
->count
);
199 for (i
= 0; i
< ptr
->count
; i
++, pname
++)
200 printf( "offset=%d len=%d id=%04x\n",
201 pname
->offset
, pname
->length
, pname
->id
);
202 pword
= (WORD
*)pname
;
205 else printf( "None\n" );
207 /* Dump the resident name table */
209 printf( "\nResident-name table:\n" );
210 pstr
= (char *)pModule
+ pModule
->name_table
;
213 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
214 *(WORD
*)(pstr
+ *pstr
+ 1) );
215 pstr
+= *pstr
+ 1 + sizeof(WORD
);
218 /* Dump the module reference table */
220 printf( "\nModule ref table:\n" );
221 if (pModule
->modref_table
)
223 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->modref_table
);
224 for (i
= 0; i
< pModule
->modref_count
; i
++, pword
++)
226 char *name
= (char *)pModule
+ pModule
->import_table
+ *pword
;
227 printf( "%d: %04x -> '%*.*s'\n",
228 i
, *pword
, *name
, *name
, name
+ 1 );
231 else printf( "None\n" );
233 /* Dump the entry table */
235 printf( "\nEntry table:\n" );
236 pstr
= (char *)pModule
+ pModule
->entry_table
;
240 printf( "Bundle %d-%d: %02x\n", ordinal
, ordinal
+ *pstr
- 1, pstr
[1]);
246 else if ((BYTE
)pstr
[1] == 0xff) /* moveable */
248 struct entry_tab_movable_s
*pe
= (struct entry_tab_movable_s
*)(pstr
+2);
249 for (i
= 0; i
< *pstr
; i
++, pe
++)
250 printf( "%d: %02x:%04x (moveable)\n",
251 ordinal
++, pe
->seg_number
, pe
->offset
);
256 struct entry_tab_fixed_s
*pe
= (struct entry_tab_fixed_s
*)(pstr
+2);
257 for (i
= 0; i
< *pstr
; i
++, pe
++)
258 printf( "%d: %04x (fixed)\n",
259 ordinal
++, pe
->offset
[0] + (pe
->offset
[1] << 8) );
264 /* Dump the non-resident names table */
266 printf( "\nNon-resident names table:\n" );
267 if (pModule
->nrname_handle
)
269 pstr
= (char *)GlobalLock( pModule
->nrname_handle
);
272 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
273 *(WORD
*)(pstr
+ *pstr
+ 1) );
274 pstr
+= *pstr
+ 1 + sizeof(WORD
);
281 /***********************************************************************
284 * Walk the module list and print the modules.
286 void MODULE_WalkModules(void)
288 HMODULE hModule
= hFirstModule
;
289 fprintf( stderr
, "Module Flags Name\n" );
292 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
295 fprintf( stderr
, "**** Bad module %04x in list\n", hModule
);
298 fprintf( stderr
, " %04x %04x %.*s\n", hModule
, pModule
->flags
,
299 *((char *)pModule
+ pModule
->name_table
),
300 (char *)pModule
+ pModule
->name_table
+ 1 );
301 hModule
= pModule
->next
;
306 /***********************************************************************
309 int MODULE_OpenFile( HMODULE hModule
)
313 const char *unixName
;
315 static int cachedfd
= -1;
317 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
318 dprintf_module( stddeb
, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
319 hModule
, hCachedModule
, cachedfd
);
320 if (!(pModule
= MODULE_GetPtr( hModule
))) return -1;
321 if (hCachedModule
== hModule
) return cachedfd
;
323 hCachedModule
= hModule
;
324 name
= NE_MODULE_NAME( pModule
);
325 if (!(unixName
= DOSFS_GetUnixFileName( name
, TRUE
)) ||
326 (cachedfd
= open( unixName
, O_RDONLY
)) == -1)
327 fprintf( stderr
, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
329 dprintf_module( stddeb
, "MODULE_OpenFile: opened '%s' -> %d\n",
335 /***********************************************************************
338 * This function translates NE segment flags to GlobalAlloc flags
340 static WORD
MODULE_Ne2MemFlags(WORD flags
)
344 if (flags
& NE_SEGFLAGS_DISCARDABLE
)
345 memflags
|= GMEM_DISCARDABLE
;
346 if (flags
& NE_SEGFLAGS_MOVEABLE
||
347 ( ! (flags
& NE_SEGFLAGS_DATA
) &&
348 ! (flags
& NE_SEGFLAGS_LOADED
) &&
349 ! (flags
& NE_SEGFLAGS_ALLOCATED
)
352 memflags
|= GMEM_MOVEABLE
;
353 memflags
|= GMEM_ZEROINIT
;
355 memflags
= GMEM_ZEROINIT
| GMEM_FIXED
;
360 /***********************************************************************
361 * MODULE_AllocateSegment (WINPROCS.26)
364 DWORD
MODULE_AllocateSegment(WORD wFlags
, WORD wSize
, WORD wElem
)
366 WORD size
= wSize
<< wElem
;
367 HANDLE hMem
= GlobalAlloc( MODULE_Ne2MemFlags(wFlags
), size
);
369 return (DWORD
)GlobalLock(hMem
);
371 WORD selector
= HIWORD(GlobalLock(hMem
));
372 return MAKELONG(hMem
, selector
);
376 /***********************************************************************
377 * MODULE_CreateSegments
380 static BOOL
MODULE_CreateSegments( HMODULE hModule
)
382 SEGTABLEENTRY
*pSegment
;
386 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
387 pSegment
= NE_SEG_TABLE( pModule
);
388 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
390 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
391 if (i
== pModule
->ss
) minsize
+= pModule
->stack_size
;
392 /* The DGROUP is allocated by MODULE_CreateInstance */
393 if (i
== pModule
->dgroup
) continue;
394 pSegment
->selector
= GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment
->flags
),
396 !(pSegment
->flags
& NE_SEGFLAGS_DATA
),
398 FALSE
/*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
399 if (!pSegment
->selector
) return FALSE
;
402 pModule
->dgroup_entry
= pModule
->dgroup
? pModule
->seg_table
+
403 (pModule
->dgroup
- 1) * sizeof(SEGTABLEENTRY
) : 0;
409 /***********************************************************************
413 static HINSTANCE
MODULE_GetInstance( HMODULE hModule
)
415 SEGTABLEENTRY
*pSegment
;
418 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
419 if (pModule
->dgroup
== 0) return hModule
;
421 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
423 return pSegment
->selector
;
428 /***********************************************************************
429 * MODULE_CreateInstance
431 HINSTANCE
MODULE_CreateInstance( HMODULE hModule
, LOADPARAMS
*params
)
433 SEGTABLEENTRY
*pSegment
;
436 HINSTANCE hNewInstance
, hPrevInstance
;
438 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
439 if (pModule
->dgroup
== 0) return hModule
;
441 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
442 hPrevInstance
= pSegment
->selector
;
444 /* if it's a library, create a new instance only the first time */
447 if (pModule
->flags
& NE_FFLAGS_LIBMODULE
) return hPrevInstance
;
448 if (params
== (LOADPARAMS
*)-1) return hPrevInstance
;
451 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
452 if (pModule
->ss
== pModule
->dgroup
) minsize
+= pModule
->stack_size
;
453 minsize
+= pModule
->heap_size
;
454 hNewInstance
= GLOBAL_Alloc( GMEM_ZEROINIT
| GMEM_FIXED
,
455 minsize
, hModule
, FALSE
, FALSE
, FALSE
);
456 if (!hNewInstance
) return 0;
457 pSegment
->selector
= hNewInstance
;
462 /***********************************************************************
463 * MODULE_LoadExeHeader
465 HMODULE
MODULE_LoadExeHeader( HFILE hFile
, OFSTRUCT
*ofs
)
467 struct mz_header_s mz_header
;
468 struct ne_header_s ne_header
;
473 char *buffer
, *fastload
= NULL
;
474 int fastload_offset
= 0, fastload_length
= 0;
476 /* Read a block from either the file or the fast-load area. */
477 #define READ(offset,size,buffer) \
478 ((fastload && ((offset) >= fastload_offset) && \
479 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
480 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
481 (_llseek( hFile, mz_header.ne_offset+(offset), SEEK_SET), \
482 FILE_Read( hFile, (buffer), (size) ) == (size)))
484 _llseek( hFile
, 0, SEEK_SET
);
485 if ((FILE_Read(hFile
,&mz_header
,sizeof(mz_header
)) != sizeof(mz_header
)) ||
486 (mz_header
.mz_magic
!= MZ_SIGNATURE
)) return (HMODULE
)11; /* invalid exe */
488 _llseek( hFile
, mz_header
.ne_offset
, SEEK_SET
);
489 if (FILE_Read( hFile
, &ne_header
, sizeof(ne_header
) ) != sizeof(ne_header
))
490 return (HMODULE
)11; /* invalid exe */
492 if (ne_header
.ne_magic
== PE_SIGNATURE
) return (HMODULE
)21; /* win32 exe */
493 if (ne_header
.ne_magic
!= NE_SIGNATURE
) return (HMODULE
)11; /* invalid exe */
495 /* We now have a valid NE header */
497 size
= sizeof(NE_MODULE
) +
498 /* loaded file info */
499 sizeof(OFSTRUCT
)-sizeof(ofs
->szPathName
)+strlen(ofs
->szPathName
)+1+
501 ne_header
.n_segment_tab
* sizeof(SEGTABLEENTRY
) +
503 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
+
504 /* resident names table */
505 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
+
506 /* module ref table */
507 ne_header
.n_mod_ref_tab
* sizeof(WORD
) +
508 /* imported names table */
509 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
+
510 /* entry table length */
511 ne_header
.entry_tab_length
;
513 hModule
= GlobalAlloc( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
514 if (!hModule
) return (HMODULE
)11; /* invalid exe */
515 FarSetOwner( hModule
, hModule
);
516 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
517 memcpy( pModule
, &ne_header
, sizeof(ne_header
) );
519 pModule
->pe_module
= NULL
;
520 pModule
->self
= hModule
;
521 pModule
->self_loading_sel
= 0;
522 pData
= (BYTE
*)(pModule
+ 1);
524 /* Clear internal Wine flags in case they are set in the EXE file */
526 pModule
->flags
&= ~(NE_FFLAGS_BUILTIN
| NE_FFLAGS_WIN32
);
528 /* Read the fast-load area */
530 if (ne_header
.additional_flags
& NE_AFLAGS_FASTLOAD
)
532 fastload_offset
=ne_header
.fastload_offset
<<ne_header
.align_shift_count
;
533 fastload_length
=ne_header
.fastload_length
<<ne_header
.align_shift_count
;
534 dprintf_module( stddeb
, "Using fast-load area offset=%x len=%d\n",
535 fastload_offset
, fastload_length
);
536 if ((fastload
= (char *)malloc( fastload_length
)) != NULL
)
538 _llseek( hFile
, mz_header
.ne_offset
+ fastload_offset
, SEEK_SET
);
539 if (FILE_Read( hFile
, fastload
, fastload_length
) != fastload_length
)
547 /* Store the filename information */
549 pModule
->fileinfo
= (int)pData
- (int)pModule
;
550 size
= sizeof(OFSTRUCT
)-sizeof(ofs
->szPathName
)+strlen(ofs
->szPathName
)+1;
551 memcpy( pData
, ofs
, size
);
552 ((OFSTRUCT
*)pData
)->cBytes
= size
- 1;
555 /* Get the segment table */
557 pModule
->seg_table
= (int)pData
- (int)pModule
;
558 buffer
= malloc( ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
) );
562 struct ne_segment_table_entry_s
*pSeg
;
564 if (!READ( ne_header
.segment_tab_offset
,
565 ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
),
566 buffer
)) return (HMODULE
)11; /* invalid exe */
567 pSeg
= (struct ne_segment_table_entry_s
*)buffer
;
568 for (i
= ne_header
.n_segment_tab
; i
> 0; i
--, pSeg
++)
570 memcpy( pData
, pSeg
, sizeof(*pSeg
) );
571 pData
+= sizeof(SEGTABLEENTRY
);
577 GlobalFree( hModule
);
578 return (HMODULE
)11; /* invalid exe */
581 /* Get the resource table */
583 if (ne_header
.resource_tab_offset
< ne_header
.rname_tab_offset
)
585 pModule
->res_table
= (int)pData
- (int)pModule
;
586 if (!READ(ne_header
.resource_tab_offset
,
587 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
,
588 pData
)) return (HMODULE
)11; /* invalid exe */
589 pData
+= ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
;
591 else pModule
->res_table
= 0; /* No resource table */
593 /* Get the resident names table */
595 pModule
->name_table
= (int)pData
- (int)pModule
;
596 if (!READ( ne_header
.rname_tab_offset
,
597 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
,
600 GlobalFree( hModule
);
601 return (HMODULE
)11; /* invalid exe */
603 pData
+= ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
;
605 /* Get the module references table */
607 if (ne_header
.n_mod_ref_tab
> 0)
609 pModule
->modref_table
= (int)pData
- (int)pModule
;
610 if (!READ( ne_header
.moduleref_tab_offset
,
611 ne_header
.n_mod_ref_tab
* sizeof(WORD
),
612 pData
)) return (HMODULE
)11; /* invalid exe */
613 pData
+= ne_header
.n_mod_ref_tab
* sizeof(WORD
);
615 else pModule
->modref_table
= 0; /* No module references */
617 /* Get the imported names table */
619 pModule
->import_table
= (int)pData
- (int)pModule
;
620 if (!READ( ne_header
.iname_tab_offset
,
621 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
,
624 GlobalFree( hModule
);
625 return (HMODULE
)11; /* invalid exe */
627 pData
+= ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
;
629 /* Get the entry table */
631 pModule
->entry_table
= (int)pData
- (int)pModule
;
632 if (!READ( ne_header
.entry_tab_offset
,
633 ne_header
.entry_tab_length
,
636 GlobalFree( hModule
);
637 return (HMODULE
)11; /* invalid exe */
639 pData
+= ne_header
.entry_tab_length
;
641 /* Get the non-resident names table */
643 if (ne_header
.nrname_tab_length
)
645 pModule
->nrname_handle
= GLOBAL_Alloc( 0, ne_header
.nrname_tab_length
,
646 hModule
, FALSE
, FALSE
, FALSE
);
647 if (!pModule
->nrname_handle
)
649 GlobalFree( hModule
);
650 return (HMODULE
)11; /* invalid exe */
652 buffer
= GlobalLock( pModule
->nrname_handle
);
653 _llseek( hFile
, ne_header
.nrname_tab_offset
, SEEK_SET
);
654 if (FILE_Read( hFile
, buffer
, ne_header
.nrname_tab_length
)
655 != ne_header
.nrname_tab_length
)
657 GlobalFree( pModule
->nrname_handle
);
658 GlobalFree( hModule
);
659 return (HMODULE
)11; /* invalid exe */
662 else pModule
->nrname_handle
= 0;
664 /* Allocate a segment for the implicitly-loaded DLLs */
666 if (pModule
->modref_count
)
668 pModule
->dlls_to_init
= GLOBAL_Alloc(GMEM_ZEROINIT
,
669 (pModule
->modref_count
+1)*sizeof(HMODULE
),
670 hModule
, FALSE
, FALSE
, FALSE
);
671 if (!pModule
->dlls_to_init
)
673 if (pModule
->nrname_handle
) GlobalFree( pModule
->nrname_handle
);
674 GlobalFree( hModule
);
675 return (HMODULE
)11; /* invalid exe */
678 else pModule
->dlls_to_init
= 0;
680 pModule
->next
= hFirstModule
;
681 hFirstModule
= hModule
;
687 /***********************************************************************
690 * Lookup the ordinal for a given name.
692 WORD
MODULE_GetOrdinal( HMODULE hModule
, const char *name
)
694 char buffer
[256], *cpnt
;
698 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
700 dprintf_module( stddeb
, "MODULE_GetOrdinal(%04x,'%s')\n",
703 /* First handle names of the form '#xxxx' */
705 if (name
[0] == '#') return atoi( name
+ 1 );
707 /* Now copy and uppercase the string */
709 strcpy( buffer
, name
);
711 len
= strlen( buffer
);
713 /* First search the resident names */
715 cpnt
= (char *)pModule
+ pModule
->name_table
;
717 /* Skip the first entry (module name) */
718 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
721 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
723 dprintf_module( stddeb
, " Found: ordinal=%d\n",
724 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
725 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
727 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
730 /* Now search the non-resident names table */
732 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
733 cpnt
= (char *)GlobalLock( pModule
->nrname_handle
);
735 /* Skip the first entry (module description string) */
736 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
739 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
741 dprintf_module( stddeb
, " Found: ordinal=%d\n",
742 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
743 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
745 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
751 /***********************************************************************
752 * MODULE_GetEntryPoint
754 * Return the entry point for a given ordinal.
756 SEGPTR
MODULE_GetEntryPoint( HMODULE hModule
, WORD ordinal
)
763 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
765 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
766 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
768 /* Skipping this bundle */
772 case 0: p
+= 2; break; /* unused */
773 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
774 default: p
+= 2 + *p
* 3; break; /* fixed */
783 case 0xff: /* moveable */
784 p
+= 2 + 6 * (ordinal
- curOrdinal
);
786 offset
= *(WORD
*)(p
+ 4);
790 p
+= 2 + 3 * (ordinal
- curOrdinal
);
791 offset
= *(WORD
*)(p
+ 1);
795 if (sel
== 0xfe) sel
= 0xffff; /* constant entry */
796 else sel
= (WORD
)(DWORD
)NE_SEG_TABLE(pModule
)[sel
-1].selector
;
797 return (SEGPTR
)MAKELONG( offset
, sel
);
801 /***********************************************************************
802 * MODULE_SetEntryPoint
804 * Change the value of an entry point. Use with caution!
805 * It can only change the offset value, not the selector.
807 BOOL
MODULE_SetEntryPoint( HMODULE hModule
, WORD ordinal
, WORD offset
)
813 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
815 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
816 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
818 /* Skipping this bundle */
822 case 0: p
+= 2; break; /* unused */
823 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
824 default: p
+= 2 + *p
* 3; break; /* fixed */
827 if (!*p
) return FALSE
;
833 case 0xff: /* moveable */
834 p
+= 2 + 6 * (ordinal
- curOrdinal
);
835 *(WORD
*)(p
+ 4) = offset
;
838 p
+= 2 + 3 * (ordinal
- curOrdinal
);
839 *(WORD
*)(p
+ 1) = offset
;
846 /***********************************************************************
847 * MODULE_GetEntryPointName
849 * Return the entry point name for a given ordinal.
850 * Used only by relay debugging.
851 * Warning: returned pointer is to a Pascal-type string.
853 LPSTR
MODULE_GetEntryPointName( HMODULE hModule
, WORD ordinal
)
858 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
860 /* First search the resident names */
862 cpnt
= (char *)pModule
+ pModule
->name_table
;
865 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
866 if (*(WORD
*)(cpnt
+ *cpnt
+ 1) == ordinal
) return cpnt
;
869 /* Now search the non-resident names table */
871 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
872 cpnt
= (char *)GlobalLock( pModule
->nrname_handle
);
875 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
876 if (*(WORD
*)(cpnt
+ *cpnt
+ 1) == ordinal
) return cpnt
;
882 /***********************************************************************
883 * MODULE_GetWndProcEntry16 (not a Windows API function)
885 * Return an entry point from the WINPROCS dll.
888 WNDPROC
MODULE_GetWndProcEntry16( const char *name
)
891 static HMODULE hModule
= 0;
893 if (!hModule
) hModule
= GetModuleHandle( "WINPROCS" );
894 ordinal
= MODULE_GetOrdinal( hModule
, name
);
895 return MODULE_GetEntryPoint( hModule
, ordinal
);
900 /***********************************************************************
901 * MODULE_GetWndProcEntry32 (not a Windows API function)
903 * Return an entry point from the WINPROCS32 dll.
906 WNDPROC
MODULE_GetWndProcEntry32( const char *name
)
908 static HMODULE hModule
= 0;
910 if (!hModule
) hModule
= GetModuleHandle( "WINPROCS32" );
911 return PE_GetProcAddress( hModule
, name
);
916 /***********************************************************************
917 * MODULE_GetModuleName
919 LPSTR
MODULE_GetModuleName( HMODULE hModule
)
923 static char buffer
[10];
925 if (!(pModule
= MODULE_GetPtr( hModule
))) return NULL
;
926 p
= (BYTE
*)pModule
+ pModule
->name_table
;
928 memcpy( buffer
, p
+ 1, len
);
934 /**********************************************************************
935 * MODULE_RegisterModule
937 void MODULE_RegisterModule( HMODULE hModule
)
939 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
940 pModule
->next
= hFirstModule
;
941 hFirstModule
= hModule
;
944 /**********************************************************************
947 * Find a module from a path name.
949 HMODULE
MODULE_FindModule( LPCSTR path
)
951 HMODULE hModule
= hFirstModule
;
952 LPCSTR filename
, dotptr
, modulepath
, modulename
;
953 BYTE len
, *name_table
;
955 if (!(filename
= strrchr( path
, '\\' ))) filename
= path
;
957 if ((dotptr
= strrchr( filename
, '.' )) != NULL
)
958 len
= (BYTE
)(dotptr
- filename
);
959 else len
= strlen( filename
);
963 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
965 modulepath
= NE_MODULE_NAME(pModule
);
966 if (!(modulename
= strrchr( modulepath
, '\\' )))
967 modulename
= modulepath
;
969 if (!lstrcmpi( modulename
, filename
)) return hModule
;
971 name_table
= (BYTE
*)pModule
+ pModule
->name_table
;
972 if ((*name_table
== len
) && !lstrncmpi(filename
, name_table
+1, len
))
974 hModule
= pModule
->next
;
980 /**********************************************************************
983 * Remove a module from memory.
985 static void MODULE_FreeModule( HMODULE hModule
)
987 HMODULE
*hPrevModule
;
989 SEGTABLEENTRY
*pSegment
;
993 if (!(pModule
= MODULE_GetPtr( hModule
))) return;
994 if (pModule
->flags
& NE_FFLAGS_BUILTIN
)
995 return; /* Can't free built-in module */
997 /* FIXME: should call the exit code for the library here */
999 /* Clear magic number just in case */
1001 pModule
->magic
= pModule
->self
= 0;
1003 /* Remove it from the linked list */
1005 hPrevModule
= &hFirstModule
;
1006 while (*hPrevModule
&& (*hPrevModule
!= hModule
))
1008 hPrevModule
= &(MODULE_GetPtr( *hPrevModule
))->next
;
1010 if (*hPrevModule
) *hPrevModule
= pModule
->next
;
1012 /* Free all the segments */
1014 pSegment
= NE_SEG_TABLE( pModule
);
1015 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
1017 GlobalFree( pSegment
->selector
);
1020 /* Free the referenced modules */
1022 pModRef
= (HMODULE
*)NE_MODULE_TABLE( pModule
);
1023 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
1025 FreeModule( *pModRef
);
1028 /* Free the module storage */
1030 if (pModule
->nrname_handle
) GlobalFree( pModule
->nrname_handle
);
1031 if (pModule
->dlls_to_init
) GlobalFree( pModule
->dlls_to_init
);
1032 GlobalFree( hModule
);
1034 /* Remove module from cache */
1036 if (hCachedModule
== hModule
) hCachedModule
= 0;
1040 /**********************************************************************
1041 * LoadModule (KERNEL.45)
1043 HINSTANCE
LoadModule( LPCSTR name
, LPVOID paramBlock
)
1046 HANDLE hInstance
, hPrevInstance
;
1048 LOADPARAMS
*params
= (LOADPARAMS
*)paramBlock
;
1050 WORD
*pModRef
, *pDLLs
;
1054 hModule
= MODULE_FindModule( name
);
1056 if (!hModule
) /* We have to load the module */
1060 /* Try to load the built-in first if not disabled */
1061 if ((hModule
= MODULE_LoadBuiltin( name
, FALSE
))) return hModule
;
1063 if ((hFile
= OpenFile( name
, &ofs
, OF_READ
)) == HFILE_ERROR
)
1065 /* Now try the built-in even if disabled */
1066 if ((hModule
= MODULE_LoadBuiltin( name
, TRUE
)))
1068 fprintf( stderr
, "Warning: could not load Windows DLL '%s', using built-in module.\n", name
);
1071 return 2; /* File not found */
1074 /* Create the module structure */
1076 hModule
= MODULE_LoadExeHeader( hFile
, &ofs
);
1079 /* FIXME: Hack because PE_LoadModule is recursive */
1080 int fd
= dup( FILE_GetUnixHandle(hFile
) );
1082 if (hModule
== 21) hModule
= PE_LoadModule( fd
, &ofs
, paramBlock
);
1085 fprintf( stderr
, "LoadModule: can't load '%s', error=%d\n",
1090 pModule
= MODULE_GetPtr( hModule
);
1092 /* Allocate the segments for this module */
1094 MODULE_CreateSegments( hModule
);
1097 hInstance
= MODULE_CreateInstance( hModule
, (LOADPARAMS
*)paramBlock
);
1099 /* Load the referenced DLLs */
1101 pModRef
= (WORD
*)((char *)pModule
+ pModule
->modref_table
);
1102 pDLLs
= (WORD
*)GlobalLock( pModule
->dlls_to_init
);
1103 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
1106 BYTE
*pstr
= (BYTE
*)pModule
+ pModule
->import_table
+ *pModRef
;
1107 memcpy( buffer
, pstr
+ 1, *pstr
);
1108 strcpy( buffer
+ *pstr
, ".dll" );
1109 dprintf_module( stddeb
, "Loading '%s'\n", buffer
);
1110 if (!(*pModRef
= MODULE_FindModule( buffer
)))
1112 /* If the DLL is not loaded yet, load it and store */
1113 /* its handle in the list of DLLs to initialize. */
1116 if ((hDLL
= LoadModule( buffer
, (LPVOID
)-1 )) == 2) /* file not found */
1120 /* Try with prepending the path of the current module */
1121 GetModuleFileName( hModule
, buffer
, 256 );
1122 if (!(p
= strrchr( buffer
, '\\' ))) p
= buffer
;
1123 memcpy( p
+ 1, pstr
+ 1, *pstr
);
1124 strcpy( p
+ 1 + *pstr
, ".dll" );
1125 hDLL
= LoadModule( buffer
, (LPVOID
)-1 );
1129 fprintf( stderr
, "Could not load '%s' required by '%s', error = %d\n",
1130 buffer
, name
, hDLL
);
1131 return 2; /* file not found */
1133 *pModRef
= GetExePtr( hDLL
);
1134 *pDLLs
++ = *pModRef
;
1136 else /* Increment the reference count of the DLL */
1138 NE_MODULE
*pOldDLL
= MODULE_GetPtr( *pModRef
);
1139 if (pOldDLL
) pOldDLL
->count
++;
1143 /* Load the segments */
1145 if (pModule
->flags
& NE_FFLAGS_SELFLOAD
)
1148 /* Handle self loading modules */
1149 SEGTABLEENTRY
* pSegTable
= (SEGTABLEENTRY
*) NE_SEG_TABLE(pModule
);
1150 SELFLOADHEADER
*selfloadheader
;
1151 HMODULE hselfload
= GetModuleHandle("WINPROCS");
1152 WORD oldss
, oldsp
, saved_dgroup
= pSegTable
[pModule
->dgroup
- 1].selector
;
1153 fprintf (stderr
, "Warning: %*.*s is a self-loading module\n"
1154 "Support for self-loading modules is very experimental\n",
1155 *((BYTE
*)pModule
+ pModule
->name_table
),
1156 *((BYTE
*)pModule
+ pModule
->name_table
),
1157 (char *)pModule
+ pModule
->name_table
+ 1);
1158 NE_LoadSegment( hModule
, 1 );
1159 selfloadheader
= (SELFLOADHEADER
*)
1160 PTR_SEG_OFF_TO_LIN(pSegTable
->selector
, 0);
1161 selfloadheader
->EntryAddrProc
=
1162 MODULE_GetEntryPoint(hselfload
,27);
1163 selfloadheader
->MyAlloc
= MODULE_GetEntryPoint(hselfload
,28);
1164 selfloadheader
->SetOwner
= MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1165 pModule
->self_loading_sel
= GlobalHandleToSel(
1166 GLOBAL_Alloc (GMEM_ZEROINIT
,
1167 0xFF00, hModule
, FALSE
, FALSE
, FALSE
)
1169 oldss
= IF1632_Saved16_ss
;
1170 oldsp
= IF1632_Saved16_sp
;
1171 IF1632_Saved16_ss
= pModule
->self_loading_sel
;
1172 IF1632_Saved16_sp
= 0xFF00;
1173 if (!IF1632_Stack32_base
) {
1174 STACK32FRAME
* frame32
;
1176 /* Setup an initial 32 bit stack frame */
1177 hInitialStack32
= GLOBAL_Alloc( GMEM_FIXED
, 0x10000,
1178 hModule
, FALSE
, FALSE
,
1181 /* Create the 32-bit stack frame */
1183 *(DWORD
*)GlobalLock(hInitialStack32
) = 0xDEADBEEF;
1184 stack32Top
= (char*)GlobalLock(hInitialStack32
) +
1186 frame32
= (STACK32FRAME
*)stack32Top
- 1;
1187 frame32
->saved_esp
= (DWORD
)stack32Top
;
1194 frame32
->retaddr
= 0;
1195 frame32
->codeselector
= WINE_CODE_SELECTOR
;
1196 /* pTask->esp = (DWORD)frame32; */
1197 IF1632_Stack32_base
= WIN16_GlobalLock(hInitialStack32
);
1200 /* FIXME: we probably need a DOS handle here */
1201 fd
= MODULE_OpenFile( hModule
);
1202 CallTo16_word_ww (selfloadheader
->BootApp
,
1203 pModule
->self_loading_sel
, hModule
, fd
);
1204 /* some BootApp procs overwrite the selector of dgroup */
1205 pSegTable
[pModule
->dgroup
- 1].selector
= saved_dgroup
;
1206 IF1632_Saved16_ss
= oldss
;
1207 IF1632_Saved16_sp
= oldsp
;
1208 for (i
= 2; i
<= pModule
->seg_count
; i
++) NE_LoadSegment( hModule
, i
);
1209 if (hInitialStack32
){
1210 GlobalUnlock (hInitialStack32
);
1211 GlobalFree (hInitialStack32
);
1212 IF1632_Stack32_base
= hInitialStack32
= 0;
1217 for (i
= 1; i
<= pModule
->seg_count
; i
++)
1218 NE_LoadSegment( hModule
, i
);
1221 /* Fixup the functions prologs */
1223 NE_FixupPrologs( pModule
);
1225 /* Make sure the usage count is 1 on the first loading of */
1226 /* the module, even if it contains circular DLL references */
1232 pModule
= MODULE_GetPtr( hModule
);
1233 hPrevInstance
= MODULE_GetInstance( hModule
);
1234 hInstance
= MODULE_CreateInstance( hModule
, params
);
1235 if (hInstance
!= hPrevInstance
) /* not a library */
1236 NE_LoadSegment( hModule
, pModule
->dgroup
);
1240 hModule
= GlobalAlloc( GMEM_MOVEABLE
| GMEM_ZEROINIT
, sizeof(NE_MODULE
) );
1241 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
1243 pModule
->magic
= NE_SIGNATURE
;
1244 pModule
->self
= hModule
;
1246 hInstance
= MODULE_CreateInstance( hModule
, (LOADPARAMS
*)paramBlock
);
1247 #endif /* WINELIB */
1249 /* Create a task for this instance */
1251 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
) && (paramBlock
!= (LPVOID
)-1))
1253 TASK_CreateTask( hModule
, hInstance
, hPrevInstance
,
1254 params
->hEnvironment
,
1255 (LPSTR
)PTR_SEG_TO_LIN( params
->cmdLine
),
1256 *((WORD
*)PTR_SEG_TO_LIN(params
->showCmd
)+1) );
1263 /**********************************************************************
1264 * FreeModule (KERNEL.46)
1266 BOOL
FreeModule( HANDLE hModule
)
1270 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1271 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
1273 dprintf_module( stddeb
, "FreeModule: %s count %d\n",
1274 MODULE_GetModuleName(hModule
), pModule
->count
);
1275 if (--pModule
->count
== 0) MODULE_FreeModule( hModule
);
1280 /**********************************************************************
1281 * GetModuleHandle (KERNEL.47)
1283 HMODULE
WIN16_GetModuleHandle( SEGPTR name
)
1285 if (HIWORD(name
) == 0) return GetExePtr( (HANDLE
)name
);
1286 return MODULE_FindModule( PTR_SEG_TO_LIN(name
) );
1289 HMODULE
GetModuleHandle( LPCSTR name
)
1291 return MODULE_FindModule( name
);
1295 /**********************************************************************
1296 * GetModuleUsage (KERNEL.48)
1298 int GetModuleUsage( HANDLE hModule
)
1302 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1303 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
1304 dprintf_module( stddeb
, "GetModuleUsage(%04x): returning %d\n",
1305 hModule
, pModule
->count
);
1306 return pModule
->count
;
1310 /**********************************************************************
1311 * GetModuleFileName (KERNEL.49)
1313 int GetModuleFileName( HANDLE hModule
, LPSTR lpFileName
, short nSize
)
1317 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1318 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
1319 lstrcpyn( lpFileName
, NE_MODULE_NAME(pModule
), nSize
);
1320 dprintf_module( stddeb
, "GetModuleFilename: %s\n", lpFileName
);
1321 return strlen(lpFileName
);
1325 /***********************************************************************
1326 * LoadLibrary (KERNEL.95)
1328 HANDLE
LoadLibrary( LPCSTR libname
)
1331 dprintf_module( stddeb
, "LoadLibrary: (%08x) %s\n", (int)libname
, libname
);
1332 WINELIB_UNIMP("LoadLibrary()");
1337 dprintf_module( stddeb
, "LoadLibrary: (%08x) %s\n", (int)libname
, libname
);
1339 /* This does not increment the module reference count, and will
1340 * therefore cause crashes on FreeLibrary calls.
1341 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1343 handle
= LoadModule( libname
, (LPVOID
)-1 );
1344 if (handle
== (HANDLE
)2) /* file not found */
1347 lstrcpyn( buffer
, libname
, 252 );
1348 strcat( buffer
, ".dll" );
1349 handle
= LoadModule( buffer
, (LPVOID
)-1 );
1351 if (handle
>= (HANDLE
)32) NE_InitializeDLLs( GetExePtr(handle
) );
1357 /***********************************************************************
1358 * FreeLibrary (KERNEL.96)
1360 void FreeLibrary( HANDLE handle
)
1362 dprintf_module( stddeb
,"FreeLibrary: %04x\n", handle
);
1363 FreeModule( handle
);
1367 /***********************************************************************
1368 * WinExec (KERNEL.166)
1370 HANDLE
WinExec( LPSTR lpCmdLine
, WORD nCmdShow
)
1373 HLOCAL cmdShowHandle
, cmdLineHandle
;
1376 char *p
, *cmdline
, filename
[256];
1377 static int use_load_module
= 1;
1379 if (!(cmdShowHandle
= GlobalAlloc( 0, 2 * sizeof(WORD
) ))) return 0;
1380 if (!(cmdLineHandle
= GlobalAlloc( 0, 256 ))) return 0;
1382 /* Store nCmdShow */
1384 cmdShowPtr
= (WORD
*)GlobalLock( cmdShowHandle
);
1386 cmdShowPtr
[1] = nCmdShow
;
1388 /* Build the filename and command-line */
1390 cmdline
= (char *)GlobalLock( cmdLineHandle
);
1391 lstrcpyn( filename
, lpCmdLine
, sizeof(filename
) - 4 /* for extension */ );
1392 for (p
= filename
; *p
&& (*p
!= ' ') && (*p
!= '\t'); p
++);
1393 if (*p
) lstrcpyn( cmdline
, p
+ 1, 128 );
1394 else cmdline
[0] = '\0';
1397 /* Now load the executable file */
1399 if (use_load_module
)
1402 /* WINELIB: Use LoadModule() only for the program itself */
1403 use_load_module
= 0;
1404 params
.hEnvironment
= (HANDLE
)GetDOSEnvironment();
1406 params
.hEnvironment
= (HANDLE
)SELECTOROF( GetDOSEnvironment() );
1407 #endif /* WINELIB */
1408 params
.cmdLine
= (SEGPTR
)WIN16_GlobalLock( cmdLineHandle
);
1409 params
.showCmd
= (SEGPTR
)WIN16_GlobalLock( cmdShowHandle
);
1410 params
.reserved
= 0;
1411 handle
= LoadModule( filename
, ¶ms
);
1412 if (handle
== 2) /* file not found */
1414 /* Check that the original file name did not have a suffix */
1415 p
= strrchr(filename
, '.');
1416 if (!p
|| (strchr(p
, '/') && strchr(p
, '\\')))
1418 p
= filename
+ strlen(filename
);
1419 strcpy( p
, ".exe" );
1420 handle
= LoadModule( filename
, ¶ms
);
1421 *p
= '\0'; /* Remove extension */
1429 /* Try to start it as a unix program */
1433 const char *unixfilename
;
1434 const char *argv
[256], **argptr
;
1435 int iconic
= (nCmdShow
== SW_SHOWMINIMIZED
||
1436 nCmdShow
== SW_SHOWMINNOACTIVE
);
1438 /* get unixfilename */
1439 if (strchr(filename
, '/') ||
1440 strchr(filename
, ':') ||
1441 strchr(filename
, '\\'))
1442 unixfilename
= DOSFS_GetUnixFileName(filename
, 1);
1443 else unixfilename
= filename
;
1449 if (iconic
) *argptr
++ = "-iconic";
1450 *argptr
++ = unixfilename
;
1454 while (*p
&& (*p
== ' ' || *p
== '\t')) *p
++ = '\0';
1457 while (*p
&& *p
!= ' ' && *p
!= '\t') p
++;
1462 execvp(argv
[0], (char**)argv
);
1470 if (iconic
) *argptr
++ = "-iconic";
1471 *argptr
++ = lpCmdLine
;
1475 execvp(argv
[0] , (char**)argv
);
1478 fprintf(stderr
, "WinExec: can't exec 'wine %s'\n", lpCmdLine
);
1484 GlobalFree( cmdShowHandle
);
1485 GlobalFree( cmdLineHandle
);
1488 if (handle
< (HANDLE
)32) /* Error? */
1491 /* FIXME: Yield never returns!
1492 We may want to run more applications or start the debugger
1493 before calling Yield. If we don't Yield will be called immdiately
1494 after returning. Why is it needed for Word anyway? */
1495 Yield(); /* program is executed immediately ....needed for word */
1502 /***********************************************************************
1503 * GetProcAddress (KERNEL.50)
1505 FARPROC
GetProcAddress( HANDLE hModule
, SEGPTR name
)
1510 if (!hModule
) hModule
= GetCurrentTask();
1511 hModule
= GetExePtr( hModule
);
1513 if (HIWORD(name
) != 0)
1515 ordinal
= MODULE_GetOrdinal( hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1516 dprintf_module( stddeb
, "GetProcAddress: %04x '%s'\n",
1517 hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1521 ordinal
= LOWORD(name
);
1522 dprintf_module( stddeb
, "GetProcAddress: %04x %04x\n",
1525 if (!ordinal
) return (FARPROC
)0;
1527 ret
= MODULE_GetEntryPoint( hModule
, ordinal
);
1529 dprintf_module( stddeb
, "GetProcAddress: returning %08lx\n", (DWORD
)ret
);
1530 return (FARPROC
)ret
;
1534 /**********************************************************************
1535 * GetExpWinVer (KERNEL.167)
1537 WORD
GetExpWinVer( HMODULE hModule
)
1539 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
1540 return pModule
? pModule
->expected_version
: 0;
1544 /**********************************************************************
1545 * ModuleFirst (TOOLHELP.59)
1547 BOOL
ModuleFirst( MODULEENTRY
*lpme
)
1549 lpme
->wNext
= hFirstModule
;
1550 return ModuleNext( lpme
);
1554 /**********************************************************************
1555 * ModuleNext (TOOLHELP.60)
1557 BOOL
ModuleNext( MODULEENTRY
*lpme
)
1561 if (!lpme
->wNext
) return FALSE
;
1562 if (!(pModule
= MODULE_GetPtr( lpme
->wNext
))) return FALSE
;
1563 strncpy( lpme
->szModule
, (char *)pModule
+ pModule
->name_table
,
1565 lpme
->szModule
[MAX_MODULE_NAME
] = '\0';
1566 lpme
->hModule
= lpme
->wNext
;
1567 lpme
->wcUsage
= pModule
->count
;
1568 strncpy( lpme
->szExePath
, NE_MODULE_NAME(pModule
), MAX_PATH
);
1569 lpme
->szExePath
[MAX_PATH
] = '\0';
1570 lpme
->wNext
= pModule
->next
;
1575 /**********************************************************************
1576 * ModuleFindName (TOOLHELP.61)
1578 BOOL
ModuleFindName( MODULEENTRY
*lpme
, LPCSTR name
)
1580 lpme
->wNext
= GetModuleHandle( name
);
1581 return ModuleNext( lpme
);
1585 /**********************************************************************
1586 * ModuleFindHandle (TOOLHELP.62)
1588 BOOL
ModuleFindHandle( MODULEENTRY
*lpme
, HMODULE hModule
)
1590 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1591 lpme
->wNext
= hModule
;
1592 return ModuleNext( lpme
);