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 fd
= MODULE_OpenFile( hModule
);
1170 CallTo16_word_ww (selfloadheader
->BootApp
,
1171 pModule
->self_loading_sel
, hModule
, fd
);
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))
1218 TASK_CreateTask( hModule
, hInstance
, hPrevInstance
,
1219 params
->hEnvironment
,
1220 (LPSTR
)PTR_SEG_TO_LIN( params
->cmdLine
),
1221 *((WORD
*)PTR_SEG_TO_LIN(params
->showCmd
)+1) );
1228 /**********************************************************************
1229 * FreeModule16 (KERNEL.46)
1231 BOOL16
FreeModule16( HMODULE16 hModule
)
1235 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1236 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
1238 dprintf_module( stddeb
, "FreeModule16: %s count %d\n",
1239 MODULE_GetModuleName(hModule
), pModule
->count
);
1240 if (--pModule
->count
== 0) MODULE_FreeModule( hModule
);
1245 /**********************************************************************
1246 * GetModuleHandle (KERNEL.47)
1248 HMODULE16
WIN16_GetModuleHandle( SEGPTR name
)
1250 if (HIWORD(name
) == 0) return GetExePtr( (HANDLE
)name
);
1251 return MODULE_FindModule( PTR_SEG_TO_LIN(name
) );
1254 HMODULE16
GetModuleHandle( LPCSTR name
)
1256 return MODULE_FindModule( name
);
1260 /**********************************************************************
1261 * GetModuleUsage (KERNEL.48)
1263 int GetModuleUsage( HANDLE hModule
)
1267 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1268 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
1269 dprintf_module( stddeb
, "GetModuleUsage(%04x): returning %d\n",
1270 hModule
, pModule
->count
);
1271 return pModule
->count
;
1275 /**********************************************************************
1276 * GetModuleFileName (KERNEL.49)
1278 int GetModuleFileName( HANDLE hModule
, LPSTR lpFileName
, short nSize
)
1282 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1283 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
1284 lstrcpyn32A( lpFileName
, NE_MODULE_NAME(pModule
), nSize
);
1285 dprintf_module( stddeb
, "GetModuleFilename: %s\n", lpFileName
);
1286 return strlen(lpFileName
);
1290 /***********************************************************************
1291 * LoadLibrary (KERNEL.95)
1293 HANDLE
LoadLibrary( LPCSTR libname
)
1299 fprintf( stderr
, "LoadLibrary not supported in Winelib\n" );
1302 dprintf_module( stddeb
, "LoadLibrary: (%08x) %s\n", (int)libname
, libname
);
1304 /* This does not increment the module reference count, and will
1305 * therefore cause crashes on FreeLibrary calls.
1306 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1308 handle
= LoadModule( libname
, (LPVOID
)-1 );
1309 if (handle
== (HANDLE
)2) /* file not found */
1312 lstrcpyn32A( buffer
, libname
, 252 );
1313 strcat( buffer
, ".dll" );
1314 handle
= LoadModule( buffer
, (LPVOID
)-1 );
1317 if (handle
>= (HANDLE
)32) NE_InitializeDLLs( GetExePtr(handle
) );
1323 /***********************************************************************
1324 * FreeLibrary (KERNEL.96)
1326 void FreeLibrary( HANDLE handle
)
1328 dprintf_module( stddeb
,"FreeLibrary: %04x\n", handle
);
1329 FreeModule16( handle
);
1333 /***********************************************************************
1334 * WinExec (KERNEL.166)
1336 HANDLE
WinExec( LPSTR lpCmdLine
, WORD nCmdShow
)
1339 HGLOBAL16 cmdShowHandle
, cmdLineHandle
;
1342 char *p
, *cmdline
, filename
[256];
1343 static int use_load_module
= 1;
1345 if (!(cmdShowHandle
= GlobalAlloc16( 0, 2 * sizeof(WORD
) )))
1346 return 8; /* Out of memory */
1347 if (!(cmdLineHandle
= GlobalAlloc16( 0, 256 )))
1349 GlobalFree16( cmdShowHandle
);
1350 return 8; /* Out of memory */
1353 /* Store nCmdShow */
1355 cmdShowPtr
= (WORD
*)GlobalLock16( cmdShowHandle
);
1357 cmdShowPtr
[1] = nCmdShow
;
1359 /* Build the filename and command-line */
1361 cmdline
= (char *)GlobalLock16( cmdLineHandle
);
1362 lstrcpyn32A(filename
, lpCmdLine
, sizeof(filename
) - 4 /* for extension */);
1363 for (p
= filename
; *p
&& (*p
!= ' ') && (*p
!= '\t'); p
++);
1364 if (*p
) lstrcpyn32A( cmdline
, p
+ 1, 128 );
1365 else cmdline
[0] = '\0';
1368 /* Now load the executable file */
1370 if (use_load_module
)
1373 /* WINELIB: Use LoadModule() only for the program itself */
1374 use_load_module
= 0;
1375 params
.hEnvironment
= (HANDLE
)GetDOSEnvironment();
1377 params
.hEnvironment
= (HANDLE
)SELECTOROF( GetDOSEnvironment() );
1378 #endif /* WINELIB */
1379 params
.cmdLine
= (SEGPTR
)WIN16_GlobalLock16( cmdLineHandle
);
1380 params
.showCmd
= (SEGPTR
)WIN16_GlobalLock16( cmdShowHandle
);
1381 params
.reserved
= 0;
1382 handle
= LoadModule( filename
, ¶ms
);
1383 if (handle
== 2) /* file not found */
1385 /* Check that the original file name did not have a suffix */
1386 p
= strrchr(filename
, '.');
1387 if (!p
|| (strchr(p
, '/') && strchr(p
, '\\')))
1389 p
= filename
+ strlen(filename
);
1390 strcpy( p
, ".exe" );
1391 handle
= LoadModule( filename
, ¶ms
);
1392 *p
= '\0'; /* Remove extension */
1400 /* Try to start it as a unix program */
1404 const char *unixfilename
;
1405 const char *argv
[256], **argptr
;
1406 int iconic
= (nCmdShow
== SW_SHOWMINIMIZED
||
1407 nCmdShow
== SW_SHOWMINNOACTIVE
);
1409 /* get unixfilename */
1410 if (strchr(filename
, '/') ||
1411 strchr(filename
, ':') ||
1412 strchr(filename
, '\\'))
1413 unixfilename
= DOSFS_GetUnixFileName(filename
, 1);
1414 else unixfilename
= filename
;
1420 if (iconic
) *argptr
++ = "-iconic";
1421 *argptr
++ = unixfilename
;
1425 while (*p
&& (*p
== ' ' || *p
== '\t')) *p
++ = '\0';
1428 while (*p
&& *p
!= ' ' && *p
!= '\t') p
++;
1433 execvp(argv
[0], (char**)argv
);
1443 if (iconic
) *argptr
++ = "-iconic";
1444 *argptr
++ = lpCmdLine
;
1448 execvp(argv
[0] , (char**)argv
);
1451 fprintf(stderr
, "WinExec: can't exec 'wine %s'\n", lpCmdLine
);
1457 GlobalFree16( cmdShowHandle
);
1458 GlobalFree16( cmdLineHandle
);
1461 if (handle
< (HANDLE
)32) /* Error? */
1464 /* FIXME: Yield never returns!
1465 We may want to run more applications or start the debugger
1466 before calling Yield. If we don't Yield will be called immdiately
1467 after returning. Why is it needed for Word anyway? */
1468 Yield(); /* program is executed immediately ....needed for word */
1475 /***********************************************************************
1476 * GetProcAddress16 (KERNEL.50)
1478 FARPROC16
GetProcAddress16( HMODULE16 hModule
, SEGPTR name
)
1483 if (!hModule
) hModule
= GetCurrentTask();
1484 hModule
= GetExePtr( hModule
);
1486 if (HIWORD(name
) != 0)
1488 ordinal
= MODULE_GetOrdinal( hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1489 dprintf_module( stddeb
, "GetProcAddress: %04x '%s'\n",
1490 hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1494 ordinal
= LOWORD(name
);
1495 dprintf_module( stddeb
, "GetProcAddress: %04x %04x\n",
1498 if (!ordinal
) return (FARPROC16
)0;
1500 ret
= MODULE_GetEntryPoint( hModule
, ordinal
);
1502 dprintf_module( stddeb
, "GetProcAddress: returning %08x\n", (UINT32
)ret
);
1507 /***********************************************************************
1508 * GetProcAddress32 (KERNEL32.257)
1510 FARPROC32
GetProcAddress32( HMODULE32 hModule
, LPCSTR function
)
1515 hModule
= GetExePtr( hModule
);
1516 if (!(pModule
= MODULE_GetPtr( hModule
)))
1517 return (FARPROC32
)0;
1518 if (!(pModule
->flags
& NE_FFLAGS_WIN32
) || !pModule
->pe_module
)
1519 return (FARPROC32
)0;
1520 if (pModule
->flags
& NE_FFLAGS_BUILTIN
)
1521 return BUILTIN_GetProcAddress32( pModule
, function
);
1522 return PE_FindExportedFunction( pModule
->pe_module
, function
);
1529 /**********************************************************************
1530 * GetExpWinVer (KERNEL.167)
1532 WORD
GetExpWinVer( HMODULE16 hModule
)
1534 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
1535 return pModule
? pModule
->expected_version
: 0;
1539 /**********************************************************************
1540 * ModuleFirst (TOOLHELP.59)
1542 BOOL16
ModuleFirst( MODULEENTRY
*lpme
)
1544 lpme
->wNext
= hFirstModule
;
1545 return ModuleNext( lpme
);
1549 /**********************************************************************
1550 * ModuleNext (TOOLHELP.60)
1552 BOOL16
ModuleNext( MODULEENTRY
*lpme
)
1556 if (!lpme
->wNext
) return FALSE
;
1557 if (!(pModule
= MODULE_GetPtr( lpme
->wNext
))) return FALSE
;
1558 strncpy( lpme
->szModule
, (char *)pModule
+ pModule
->name_table
,
1560 lpme
->szModule
[MAX_MODULE_NAME
] = '\0';
1561 lpme
->hModule
= lpme
->wNext
;
1562 lpme
->wcUsage
= pModule
->count
;
1563 strncpy( lpme
->szExePath
, NE_MODULE_NAME(pModule
), MAX_PATH
);
1564 lpme
->szExePath
[MAX_PATH
] = '\0';
1565 lpme
->wNext
= pModule
->next
;
1570 /**********************************************************************
1571 * ModuleFindName (TOOLHELP.61)
1573 BOOL16
ModuleFindName( MODULEENTRY
*lpme
, LPCSTR name
)
1575 lpme
->wNext
= GetModuleHandle( name
);
1576 return ModuleNext( lpme
);
1580 /**********************************************************************
1581 * ModuleFindHandle (TOOLHELP.62)
1583 BOOL16
ModuleFindHandle( MODULEENTRY
*lpme
, HMODULE16 hModule
)
1585 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1586 lpme
->wNext
= hModule
;
1587 return ModuleNext( lpme
);