4 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
22 #include "stackframe.h"
31 extern HINSTANCE
PE_LoadModule( int fd
, OFSTRUCT
*ofs
, LOADPARAMS
* params
);
33 static HMODULE hFirstModule
= 0;
34 static HMODULE hCachedModule
= 0; /* Module cached by MODULE_OpenFile */
37 static HANDLE hInitialStack32
= 0;
41 /***********************************************************************
44 NE_MODULE
*MODULE_GetPtr( HMODULE hModule
)
46 NE_MODULE
*pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
47 if (!pModule
|| (pModule
->magic
!= NE_SIGNATURE
) ||
48 (pModule
->self
!= hModule
)) return NULL
;
53 /***********************************************************************
56 void MODULE_DumpModule( HMODULE hmodule
)
64 if (!(pModule
= MODULE_GetPtr( hmodule
)))
66 fprintf( stderr
, "**** %04x is not a module handle\n", hmodule
);
70 /* Dump the module info */
72 printf( "Module %04x:\n", hmodule
);
73 printf( "count=%d flags=%04x heap=%d stack=%d\n",
74 pModule
->count
, pModule
->flags
,
75 pModule
->heap_size
, pModule
->stack_size
);
76 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
77 pModule
->cs
, pModule
->ip
, pModule
->ss
, pModule
->sp
, pModule
->dgroup
,
78 pModule
->seg_count
, pModule
->modref_count
);
79 printf( "os_flags=%d swap_area=%d version=%04x\n",
80 pModule
->os_flags
, pModule
->min_swap_area
,
81 pModule
->expected_version
);
82 if (pModule
->flags
& NE_FFLAGS_WIN32
)
83 printf( "PE module=%08x\n", (unsigned int)pModule
->pe_module
);
85 /* Dump the file info */
87 printf( "Filename: '%s'\n", NE_MODULE_NAME(pModule
) );
89 /* Dump the segment table */
91 printf( "\nSegment table:\n" );
92 pSeg
= NE_SEG_TABLE( pModule
);
93 for (i
= 0; i
< pModule
->seg_count
; i
++, pSeg
++)
94 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
95 i
+ 1, pSeg
->filepos
, pSeg
->size
, pSeg
->flags
,
96 pSeg
->minsize
, pSeg
->selector
);
98 /* Dump the resource table */
100 printf( "\nResource table:\n" );
101 if (pModule
->res_table
)
103 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->res_table
);
104 printf( "Alignment: %d\n", *pword
++ );
107 struct resource_typeinfo_s
*ptr
= (struct resource_typeinfo_s
*)pword
;
108 struct resource_nameinfo_s
*pname
= (struct resource_nameinfo_s
*)(ptr
+ 1);
109 printf( "id=%04x count=%d\n", ptr
->type_id
, ptr
->count
);
110 for (i
= 0; i
< ptr
->count
; i
++, pname
++)
111 printf( "offset=%d len=%d id=%04x\n",
112 pname
->offset
, pname
->length
, pname
->id
);
113 pword
= (WORD
*)pname
;
116 else printf( "None\n" );
118 /* Dump the resident name table */
120 printf( "\nResident-name table:\n" );
121 pstr
= (char *)pModule
+ pModule
->name_table
;
124 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
125 *(WORD
*)(pstr
+ *pstr
+ 1) );
126 pstr
+= *pstr
+ 1 + sizeof(WORD
);
129 /* Dump the module reference table */
131 printf( "\nModule ref table:\n" );
132 if (pModule
->modref_table
)
134 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->modref_table
);
135 for (i
= 0; i
< pModule
->modref_count
; i
++, pword
++)
137 char *name
= (char *)pModule
+ pModule
->import_table
+ *pword
;
138 printf( "%d: %04x -> '%*.*s'\n",
139 i
, *pword
, *name
, *name
, name
+ 1 );
142 else printf( "None\n" );
144 /* Dump the entry table */
146 printf( "\nEntry table:\n" );
147 pstr
= (char *)pModule
+ pModule
->entry_table
;
151 printf( "Bundle %d-%d: %02x\n", ordinal
, ordinal
+ *pstr
- 1, pstr
[1]);
157 else if ((BYTE
)pstr
[1] == 0xff) /* moveable */
159 struct entry_tab_movable_s
*pe
= (struct entry_tab_movable_s
*)(pstr
+2);
160 for (i
= 0; i
< *pstr
; i
++, pe
++)
161 printf( "%d: %02x:%04x (moveable)\n",
162 ordinal
++, pe
->seg_number
, pe
->offset
);
167 struct entry_tab_fixed_s
*pe
= (struct entry_tab_fixed_s
*)(pstr
+2);
168 for (i
= 0; i
< *pstr
; i
++, pe
++)
169 printf( "%d: %04x (fixed)\n",
170 ordinal
++, pe
->offset
[0] + (pe
->offset
[1] << 8) );
175 /* Dump the non-resident names table */
177 printf( "\nNon-resident names table:\n" );
178 if (pModule
->nrname_handle
)
180 pstr
= (char *)GlobalLock16( pModule
->nrname_handle
);
183 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
184 *(WORD
*)(pstr
+ *pstr
+ 1) );
185 pstr
+= *pstr
+ 1 + sizeof(WORD
);
192 /***********************************************************************
195 * Walk the module list and print the modules.
197 void MODULE_WalkModules(void)
199 HMODULE hModule
= hFirstModule
;
200 fprintf( stderr
, "Module Flags Name\n" );
203 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
206 fprintf( stderr
, "**** Bad module %04x in list\n", hModule
);
209 fprintf( stderr
, " %04x %04x %.*s\n", hModule
, pModule
->flags
,
210 *((char *)pModule
+ pModule
->name_table
),
211 (char *)pModule
+ pModule
->name_table
+ 1 );
212 hModule
= pModule
->next
;
217 /***********************************************************************
220 int MODULE_OpenFile( HMODULE hModule
)
224 const char *unixName
;
226 static int cachedfd
= -1;
228 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
229 dprintf_module( stddeb
, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
230 hModule
, hCachedModule
, cachedfd
);
231 if (!(pModule
= MODULE_GetPtr( hModule
))) return -1;
232 if (hCachedModule
== hModule
) return cachedfd
;
234 hCachedModule
= hModule
;
235 name
= NE_MODULE_NAME( pModule
);
236 if (!(unixName
= DOSFS_GetUnixFileName( name
, TRUE
)) ||
237 (cachedfd
= open( unixName
, O_RDONLY
)) == -1)
238 fprintf( stderr
, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
240 dprintf_module( stddeb
, "MODULE_OpenFile: opened '%s' -> %d\n",
246 /***********************************************************************
249 * This function translates NE segment flags to GlobalAlloc flags
251 static WORD
MODULE_Ne2MemFlags(WORD flags
)
255 if (flags
& NE_SEGFLAGS_DISCARDABLE
)
256 memflags
|= GMEM_DISCARDABLE
;
257 if (flags
& NE_SEGFLAGS_MOVEABLE
||
258 ( ! (flags
& NE_SEGFLAGS_DATA
) &&
259 ! (flags
& NE_SEGFLAGS_LOADED
) &&
260 ! (flags
& NE_SEGFLAGS_ALLOCATED
)
263 memflags
|= GMEM_MOVEABLE
;
264 memflags
|= GMEM_ZEROINIT
;
266 memflags
= GMEM_ZEROINIT
| GMEM_FIXED
;
271 /***********************************************************************
272 * MODULE_AllocateSegment (WPROCS.26)
275 DWORD
MODULE_AllocateSegment(WORD wFlags
, WORD wSize
, WORD wElem
)
277 WORD size
= wSize
<< wElem
;
278 HANDLE hMem
= GlobalAlloc16( MODULE_Ne2MemFlags(wFlags
), size
);
280 return (DWORD
)GlobalLock16(hMem
);
282 WORD selector
= HIWORD(WIN16_GlobalLock16(hMem
));
283 return MAKELONG(hMem
, selector
);
287 /***********************************************************************
288 * MODULE_CreateSegments
291 static BOOL
MODULE_CreateSegments( HMODULE hModule
)
293 SEGTABLEENTRY
*pSegment
;
297 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
298 pSegment
= NE_SEG_TABLE( pModule
);
299 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
301 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
302 if (i
== pModule
->ss
) minsize
+= pModule
->stack_size
;
303 /* The DGROUP is allocated by MODULE_CreateInstance */
304 if (i
== pModule
->dgroup
) continue;
305 pSegment
->selector
= GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment
->flags
),
307 !(pSegment
->flags
& NE_SEGFLAGS_DATA
),
309 FALSE
/*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
310 if (!pSegment
->selector
) return FALSE
;
313 pModule
->dgroup_entry
= pModule
->dgroup
? pModule
->seg_table
+
314 (pModule
->dgroup
- 1) * sizeof(SEGTABLEENTRY
) : 0;
320 /***********************************************************************
324 HINSTANCE
MODULE_GetInstance( HMODULE hModule
)
326 SEGTABLEENTRY
*pSegment
;
329 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
330 if (pModule
->dgroup
== 0) return hModule
;
332 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
334 return pSegment
->selector
;
339 /***********************************************************************
340 * MODULE_CreateInstance
342 HINSTANCE
MODULE_CreateInstance( HMODULE hModule
, LOADPARAMS
*params
)
344 SEGTABLEENTRY
*pSegment
;
347 HINSTANCE hNewInstance
, hPrevInstance
;
349 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
350 if (pModule
->dgroup
== 0) return hModule
;
352 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
353 hPrevInstance
= pSegment
->selector
;
355 /* if it's a library, create a new instance only the first time */
358 if (pModule
->flags
& NE_FFLAGS_LIBMODULE
) return hPrevInstance
;
359 if (params
== (LOADPARAMS
*)-1) return hPrevInstance
;
362 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
363 if (pModule
->ss
== pModule
->dgroup
) minsize
+= pModule
->stack_size
;
364 minsize
+= pModule
->heap_size
;
365 hNewInstance
= GLOBAL_Alloc( GMEM_ZEROINIT
| GMEM_FIXED
,
366 minsize
, hModule
, FALSE
, FALSE
, FALSE
);
367 if (!hNewInstance
) return 0;
368 pSegment
->selector
= hNewInstance
;
373 /***********************************************************************
374 * MODULE_LoadExeHeader
376 static HMODULE
MODULE_LoadExeHeader( HFILE hFile
, OFSTRUCT
*ofs
)
378 struct mz_header_s mz_header
;
379 struct ne_header_s ne_header
;
384 char *buffer
, *fastload
= NULL
;
385 int fastload_offset
= 0, fastload_length
= 0;
387 /* Read a block from either the file or the fast-load area. */
388 #define READ(offset,size,buffer) \
389 ((fastload && ((offset) >= fastload_offset) && \
390 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
391 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
392 (_llseek( hFile, mz_header.ne_offset+(offset), SEEK_SET), \
393 FILE_Read( hFile, (buffer), (size) ) == (size)))
395 _llseek( hFile
, 0, SEEK_SET
);
396 if ((FILE_Read(hFile
,&mz_header
,sizeof(mz_header
)) != sizeof(mz_header
)) ||
397 (mz_header
.mz_magic
!= MZ_SIGNATURE
)) return (HMODULE
)11; /* invalid exe */
399 _llseek( hFile
, mz_header
.ne_offset
, SEEK_SET
);
400 if (FILE_Read( hFile
, &ne_header
, sizeof(ne_header
) ) != sizeof(ne_header
))
401 return (HMODULE
)11; /* invalid exe */
403 if (ne_header
.ne_magic
== PE_SIGNATURE
) return (HMODULE
)21; /* win32 exe */
404 if (ne_header
.ne_magic
!= NE_SIGNATURE
) return (HMODULE
)11; /* invalid exe */
406 /* We now have a valid NE header */
408 size
= sizeof(NE_MODULE
) +
409 /* loaded file info */
410 sizeof(OFSTRUCT
)-sizeof(ofs
->szPathName
)+strlen(ofs
->szPathName
)+1+
412 ne_header
.n_segment_tab
* sizeof(SEGTABLEENTRY
) +
414 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
+
415 /* resident names table */
416 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
+
417 /* module ref table */
418 ne_header
.n_mod_ref_tab
* sizeof(WORD
) +
419 /* imported names table */
420 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
+
421 /* entry table length */
422 ne_header
.entry_tab_length
;
424 hModule
= GlobalAlloc16( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
425 if (!hModule
) return (HMODULE
)11; /* invalid exe */
426 FarSetOwner( hModule
, hModule
);
427 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
428 memcpy( pModule
, &ne_header
, sizeof(ne_header
) );
430 pModule
->pe_module
= NULL
;
431 pModule
->self
= hModule
;
432 pModule
->self_loading_sel
= 0;
433 pData
= (BYTE
*)(pModule
+ 1);
435 /* Clear internal Wine flags in case they are set in the EXE file */
437 pModule
->flags
&= ~(NE_FFLAGS_BUILTIN
| NE_FFLAGS_WIN32
);
439 /* Read the fast-load area */
441 if (ne_header
.additional_flags
& NE_AFLAGS_FASTLOAD
)
443 fastload_offset
=ne_header
.fastload_offset
<<ne_header
.align_shift_count
;
444 fastload_length
=ne_header
.fastload_length
<<ne_header
.align_shift_count
;
445 dprintf_module( stddeb
, "Using fast-load area offset=%x len=%d\n",
446 fastload_offset
, fastload_length
);
447 if ((fastload
= (char *)malloc( fastload_length
)) != NULL
)
449 _llseek( hFile
, mz_header
.ne_offset
+ fastload_offset
, SEEK_SET
);
450 if (FILE_Read( hFile
, fastload
, fastload_length
) != fastload_length
)
458 /* Store the filename information */
460 pModule
->fileinfo
= (int)pData
- (int)pModule
;
461 size
= sizeof(OFSTRUCT
)-sizeof(ofs
->szPathName
)+strlen(ofs
->szPathName
)+1;
462 memcpy( pData
, ofs
, size
);
463 ((OFSTRUCT
*)pData
)->cBytes
= size
- 1;
466 /* Get the segment table */
468 pModule
->seg_table
= (int)pData
- (int)pModule
;
469 buffer
= malloc( ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
) );
473 struct ne_segment_table_entry_s
*pSeg
;
475 if (!READ( ne_header
.segment_tab_offset
,
476 ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
),
477 buffer
)) return (HMODULE
)11; /* invalid exe */
478 pSeg
= (struct ne_segment_table_entry_s
*)buffer
;
479 for (i
= ne_header
.n_segment_tab
; i
> 0; i
--, pSeg
++)
481 memcpy( pData
, pSeg
, sizeof(*pSeg
) );
482 pData
+= sizeof(SEGTABLEENTRY
);
488 GlobalFree16( hModule
);
489 return (HMODULE
)11; /* invalid exe */
492 /* Get the resource table */
494 if (ne_header
.resource_tab_offset
< ne_header
.rname_tab_offset
)
496 pModule
->res_table
= (int)pData
- (int)pModule
;
497 if (!READ(ne_header
.resource_tab_offset
,
498 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
,
499 pData
)) return (HMODULE
)11; /* invalid exe */
500 pData
+= ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
;
502 else pModule
->res_table
= 0; /* No resource table */
504 /* Get the resident names table */
506 pModule
->name_table
= (int)pData
- (int)pModule
;
507 if (!READ( ne_header
.rname_tab_offset
,
508 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
,
511 GlobalFree16( hModule
);
512 return (HMODULE
)11; /* invalid exe */
514 pData
+= ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
;
516 /* Get the module references table */
518 if (ne_header
.n_mod_ref_tab
> 0)
520 pModule
->modref_table
= (int)pData
- (int)pModule
;
521 if (!READ( ne_header
.moduleref_tab_offset
,
522 ne_header
.n_mod_ref_tab
* sizeof(WORD
),
523 pData
)) return (HMODULE
)11; /* invalid exe */
524 pData
+= ne_header
.n_mod_ref_tab
* sizeof(WORD
);
526 else pModule
->modref_table
= 0; /* No module references */
528 /* Get the imported names table */
530 pModule
->import_table
= (int)pData
- (int)pModule
;
531 if (!READ( ne_header
.iname_tab_offset
,
532 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
,
535 GlobalFree16( hModule
);
536 return (HMODULE
)11; /* invalid exe */
538 pData
+= ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
;
540 /* Get the entry table */
542 pModule
->entry_table
= (int)pData
- (int)pModule
;
543 if (!READ( ne_header
.entry_tab_offset
,
544 ne_header
.entry_tab_length
,
547 GlobalFree16( hModule
);
548 return (HMODULE
)11; /* invalid exe */
550 pData
+= ne_header
.entry_tab_length
;
552 /* Get the non-resident names table */
554 if (ne_header
.nrname_tab_length
)
556 pModule
->nrname_handle
= GLOBAL_Alloc( 0, ne_header
.nrname_tab_length
,
557 hModule
, FALSE
, FALSE
, FALSE
);
558 if (!pModule
->nrname_handle
)
560 GlobalFree16( hModule
);
561 return (HMODULE
)11; /* invalid exe */
563 buffer
= GlobalLock16( pModule
->nrname_handle
);
564 _llseek( hFile
, ne_header
.nrname_tab_offset
, SEEK_SET
);
565 if (FILE_Read( hFile
, buffer
, ne_header
.nrname_tab_length
)
566 != ne_header
.nrname_tab_length
)
568 GlobalFree16( pModule
->nrname_handle
);
569 GlobalFree16( hModule
);
570 return (HMODULE
)11; /* invalid exe */
573 else pModule
->nrname_handle
= 0;
575 /* Allocate a segment for the implicitly-loaded DLLs */
577 if (pModule
->modref_count
)
579 pModule
->dlls_to_init
= GLOBAL_Alloc(GMEM_ZEROINIT
,
580 (pModule
->modref_count
+1)*sizeof(HMODULE
),
581 hModule
, FALSE
, FALSE
, FALSE
);
582 if (!pModule
->dlls_to_init
)
584 if (pModule
->nrname_handle
) GlobalFree16( pModule
->nrname_handle
);
585 GlobalFree16( hModule
);
586 return (HMODULE
)11; /* invalid exe */
589 else pModule
->dlls_to_init
= 0;
591 MODULE_RegisterModule( pModule
);
597 /***********************************************************************
600 * Lookup the ordinal for a given name.
602 WORD
MODULE_GetOrdinal( HMODULE hModule
, const char *name
)
604 char buffer
[256], *cpnt
;
608 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
610 dprintf_module( stddeb
, "MODULE_GetOrdinal(%04x,'%s')\n",
613 /* First handle names of the form '#xxxx' */
615 if (name
[0] == '#') return atoi( name
+ 1 );
617 /* Now copy and uppercase the string */
619 strcpy( buffer
, name
);
621 len
= strlen( buffer
);
623 /* First search the resident names */
625 cpnt
= (char *)pModule
+ pModule
->name_table
;
627 /* Skip the first entry (module name) */
628 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
631 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
633 dprintf_module( stddeb
, " Found: ordinal=%d\n",
634 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
635 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
637 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
640 /* Now search the non-resident names table */
642 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
643 cpnt
= (char *)GlobalLock16( pModule
->nrname_handle
);
645 /* Skip the first entry (module description string) */
646 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
649 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
651 dprintf_module( stddeb
, " Found: ordinal=%d\n",
652 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
653 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
655 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
661 /***********************************************************************
662 * MODULE_GetEntryPoint
664 * Return the entry point for a given ordinal.
666 SEGPTR
MODULE_GetEntryPoint( HMODULE hModule
, WORD ordinal
)
673 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
675 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
676 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
678 /* Skipping this bundle */
682 case 0: p
+= 2; break; /* unused */
683 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
684 default: p
+= 2 + *p
* 3; break; /* fixed */
693 case 0xff: /* moveable */
694 p
+= 2 + 6 * (ordinal
- curOrdinal
);
696 offset
= *(WORD
*)(p
+ 4);
700 p
+= 2 + 3 * (ordinal
- curOrdinal
);
701 offset
= *(WORD
*)(p
+ 1);
705 if (sel
== 0xfe) sel
= 0xffff; /* constant entry */
706 else sel
= (WORD
)(DWORD
)NE_SEG_TABLE(pModule
)[sel
-1].selector
;
707 return PTR_SEG_OFF_TO_SEGPTR( sel
, offset
);
711 /***********************************************************************
712 * MODULE_SetEntryPoint
714 * Change the value of an entry point. Use with caution!
715 * It can only change the offset value, not the selector.
717 BOOL
MODULE_SetEntryPoint( HMODULE hModule
, WORD ordinal
, WORD offset
)
723 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
725 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
726 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
728 /* Skipping this bundle */
732 case 0: p
+= 2; break; /* unused */
733 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
734 default: p
+= 2 + *p
* 3; break; /* fixed */
737 if (!*p
) return FALSE
;
743 case 0xff: /* moveable */
744 p
+= 2 + 6 * (ordinal
- curOrdinal
);
745 *(WORD
*)(p
+ 4) = offset
;
748 p
+= 2 + 3 * (ordinal
- curOrdinal
);
749 *(WORD
*)(p
+ 1) = offset
;
756 /***********************************************************************
757 * MODULE_GetWndProcEntry16 (not a Windows API function)
759 * Return an entry point from the WPROCS dll.
762 FARPROC16
MODULE_GetWndProcEntry16( const char *name
)
766 static HMODULE hModule
= 0;
768 if (!hModule
) hModule
= GetModuleHandle( "WPROCS" );
769 ordinal
= MODULE_GetOrdinal( hModule
, name
);
770 if (!(ret
= MODULE_GetEntryPoint( hModule
, ordinal
)))
771 fprintf( stderr
, "GetWndProc16: %s not found, please report\n", name
);
777 /***********************************************************************
778 * MODULE_GetWndProcEntry32 (not a Windows API function)
780 * Return an entry point from the WPROCS32 dll.
783 FARPROC32
MODULE_GetWndProcEntry32( const char *name
)
786 static HMODULE hModule
= 0;
788 if (!hModule
) hModule
= GetModuleHandle( "WPROCS32" );
789 if (!(ret
= PE_GetProcAddress( hModule
, name
)))
790 fprintf( stderr
, "GetWndProc32: %s not found, please report\n", name
);
796 /***********************************************************************
797 * MODULE_GetModuleName
799 LPSTR
MODULE_GetModuleName( HMODULE hModule
)
803 static char buffer
[10];
805 if (!(pModule
= MODULE_GetPtr( hModule
))) return NULL
;
806 p
= (BYTE
*)pModule
+ pModule
->name_table
;
808 memcpy( buffer
, p
+ 1, len
);
814 /**********************************************************************
815 * MODULE_RegisterModule
817 void MODULE_RegisterModule( NE_MODULE
*pModule
)
819 pModule
->next
= hFirstModule
;
820 hFirstModule
= pModule
->self
;
824 /**********************************************************************
827 * Find a module from a path name.
829 HMODULE
MODULE_FindModule( LPCSTR path
)
831 HMODULE hModule
= hFirstModule
;
832 LPCSTR filename
, dotptr
, modulepath
, modulename
;
833 BYTE len
, *name_table
;
835 if (!(filename
= strrchr( path
, '\\' ))) filename
= path
;
837 if ((dotptr
= strrchr( filename
, '.' )) != NULL
)
838 len
= (BYTE
)(dotptr
- filename
);
839 else len
= strlen( filename
);
843 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
845 modulepath
= NE_MODULE_NAME(pModule
);
846 if (!(modulename
= strrchr( modulepath
, '\\' )))
847 modulename
= modulepath
;
849 if (!lstrcmpi( modulename
, filename
)) return hModule
;
851 name_table
= (BYTE
*)pModule
+ pModule
->name_table
;
852 if ((*name_table
== len
) && !lstrncmpi(filename
, name_table
+1, len
))
854 hModule
= pModule
->next
;
860 /**********************************************************************
863 * Remove a module from memory.
865 static void MODULE_FreeModule( HMODULE hModule
)
867 HMODULE
*hPrevModule
;
869 SEGTABLEENTRY
*pSegment
;
873 if (!(pModule
= MODULE_GetPtr( hModule
))) return;
874 if (pModule
->flags
& NE_FFLAGS_BUILTIN
)
875 return; /* Can't free built-in module */
877 /* FIXME: should call the exit code for the library here */
879 /* Free the objects owned by the module */
881 HOOK_FreeModuleHooks( hModule
);
882 CLASS_FreeModuleClasses( hModule
);
884 /* Clear magic number just in case */
886 pModule
->magic
= pModule
->self
= 0;
888 /* Remove it from the linked list */
890 hPrevModule
= &hFirstModule
;
891 while (*hPrevModule
&& (*hPrevModule
!= hModule
))
893 hPrevModule
= &(MODULE_GetPtr( *hPrevModule
))->next
;
895 if (*hPrevModule
) *hPrevModule
= pModule
->next
;
897 /* Free all the segments */
899 pSegment
= NE_SEG_TABLE( pModule
);
900 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
902 GlobalFree16( pSegment
->selector
);
905 /* Free the referenced modules */
907 pModRef
= (HMODULE
*)NE_MODULE_TABLE( pModule
);
908 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
910 FreeModule( *pModRef
);
913 /* Free the module storage */
915 if (pModule
->nrname_handle
) GlobalFree16( pModule
->nrname_handle
);
916 if (pModule
->dlls_to_init
) GlobalFree16( pModule
->dlls_to_init
);
917 GlobalFree16( hModule
);
919 /* Remove module from cache */
921 if (hCachedModule
== hModule
) hCachedModule
= 0;
925 /**********************************************************************
926 * LoadModule (KERNEL.45)
928 HINSTANCE
LoadModule( LPCSTR name
, LPVOID paramBlock
)
931 HANDLE hInstance
, hPrevInstance
;
933 LOADPARAMS
*params
= (LOADPARAMS
*)paramBlock
;
935 WORD
*pModRef
, *pDLLs
;
939 hModule
= MODULE_FindModule( name
);
941 if (!hModule
) /* We have to load the module */
945 /* Try to load the built-in first if not disabled */
946 if ((hModule
= BUILTIN_LoadModule( name
, FALSE
))) return hModule
;
948 if ((hFile
= OpenFile( name
, &ofs
, OF_READ
)) == HFILE_ERROR
)
950 /* Now try the built-in even if disabled */
951 if ((hModule
= BUILTIN_LoadModule( name
, TRUE
)))
953 fprintf( stderr
, "Warning: could not load Windows DLL '%s', using built-in module.\n", name
);
956 return 2; /* File not found */
959 /* Create the module structure */
961 hModule
= MODULE_LoadExeHeader( hFile
, &ofs
);
964 /* FIXME: Hack because PE_LoadModule is recursive */
965 int fd
= dup( FILE_GetUnixHandle(hFile
) );
967 if (hModule
== 21) hModule
= PE_LoadModule( fd
, &ofs
, paramBlock
);
970 fprintf( stderr
, "LoadModule: can't load '%s', error=%d\n",
975 pModule
= MODULE_GetPtr( hModule
);
977 /* Allocate the segments for this module */
979 MODULE_CreateSegments( hModule
);
982 hInstance
= MODULE_CreateInstance( hModule
, (LOADPARAMS
*)paramBlock
);
984 /* Load the referenced DLLs */
986 pModRef
= (WORD
*)((char *)pModule
+ pModule
->modref_table
);
987 pDLLs
= (WORD
*)GlobalLock16( pModule
->dlls_to_init
);
988 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
991 BYTE
*pstr
= (BYTE
*)pModule
+ pModule
->import_table
+ *pModRef
;
992 memcpy( buffer
, pstr
+ 1, *pstr
);
993 strcpy( buffer
+ *pstr
, ".dll" );
994 dprintf_module( stddeb
, "Loading '%s'\n", buffer
);
995 if (!(*pModRef
= MODULE_FindModule( buffer
)))
997 /* If the DLL is not loaded yet, load it and store */
998 /* its handle in the list of DLLs to initialize. */
1001 if ((hDLL
= LoadModule( buffer
, (LPVOID
)-1 )) == 2) /* file not found */
1005 /* Try with prepending the path of the current module */
1006 GetModuleFileName( hModule
, buffer
, 256 );
1007 if (!(p
= strrchr( buffer
, '\\' ))) p
= buffer
;
1008 memcpy( p
+ 1, pstr
+ 1, *pstr
);
1009 strcpy( p
+ 1 + *pstr
, ".dll" );
1010 hDLL
= LoadModule( buffer
, (LPVOID
)-1 );
1014 fprintf( stderr
, "Could not load '%s' required by '%s', error = %d\n",
1015 buffer
, name
, hDLL
);
1016 return 2; /* file not found */
1018 *pModRef
= GetExePtr( hDLL
);
1019 *pDLLs
++ = *pModRef
;
1021 else /* Increment the reference count of the DLL */
1023 NE_MODULE
*pOldDLL
= MODULE_GetPtr( *pModRef
);
1024 if (pOldDLL
) pOldDLL
->count
++;
1028 /* Load the segments */
1030 if (pModule
->flags
& NE_FFLAGS_SELFLOAD
)
1033 /* Handle self loading modules */
1034 SEGTABLEENTRY
* pSegTable
= (SEGTABLEENTRY
*) NE_SEG_TABLE(pModule
);
1035 SELFLOADHEADER
*selfloadheader
;
1036 HMODULE hselfload
= GetModuleHandle("WPROCS");
1037 WORD oldss
, oldsp
, saved_dgroup
= pSegTable
[pModule
->dgroup
- 1].selector
;
1038 fprintf (stderr
, "Warning: %*.*s is a self-loading module\n"
1039 "Support for self-loading modules is very experimental\n",
1040 *((BYTE
*)pModule
+ pModule
->name_table
),
1041 *((BYTE
*)pModule
+ pModule
->name_table
),
1042 (char *)pModule
+ pModule
->name_table
+ 1);
1043 NE_LoadSegment( hModule
, 1 );
1044 selfloadheader
= (SELFLOADHEADER
*)
1045 PTR_SEG_OFF_TO_LIN(pSegTable
->selector
, 0);
1046 selfloadheader
->EntryAddrProc
=
1047 MODULE_GetEntryPoint(hselfload
,27);
1048 selfloadheader
->MyAlloc
= MODULE_GetEntryPoint(hselfload
,28);
1049 selfloadheader
->SetOwner
= MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1050 pModule
->self_loading_sel
= GlobalHandleToSel(
1051 GLOBAL_Alloc (GMEM_ZEROINIT
,
1052 0xFF00, hModule
, FALSE
, FALSE
, FALSE
)
1054 oldss
= IF1632_Saved16_ss
;
1055 oldsp
= IF1632_Saved16_sp
;
1056 IF1632_Saved16_ss
= pModule
->self_loading_sel
;
1057 IF1632_Saved16_sp
= 0xFF00;
1058 if (!IF1632_Stack32_base
) {
1059 STACK32FRAME
* frame32
;
1061 /* Setup an initial 32 bit stack frame */
1062 hInitialStack32
= GLOBAL_Alloc( GMEM_FIXED
, 0x10000,
1063 hModule
, FALSE
, FALSE
,
1066 /* Create the 32-bit stack frame */
1068 *(DWORD
*)GlobalLock16(hInitialStack32
) = 0xDEADBEEF;
1069 stack32Top
= (char*)GlobalLock16(hInitialStack32
) +
1071 frame32
= (STACK32FRAME
*)stack32Top
- 1;
1072 frame32
->saved_esp
= (DWORD
)stack32Top
;
1079 frame32
->retaddr
= 0;
1080 frame32
->codeselector
= WINE_CODE_SELECTOR
;
1081 /* pTask->esp = (DWORD)frame32; */
1082 IF1632_Stack32_base
= WIN16_GlobalLock16(hInitialStack32
);
1085 /* FIXME: we probably need a DOS handle here */
1086 fd
= MODULE_OpenFile( hModule
);
1087 CallTo16_word_ww (selfloadheader
->BootApp
,
1088 pModule
->self_loading_sel
, hModule
, fd
);
1089 /* some BootApp procs overwrite the selector of dgroup */
1090 pSegTable
[pModule
->dgroup
- 1].selector
= saved_dgroup
;
1091 IF1632_Saved16_ss
= oldss
;
1092 IF1632_Saved16_sp
= oldsp
;
1093 for (i
= 2; i
<= pModule
->seg_count
; i
++) NE_LoadSegment( hModule
, i
);
1094 if (hInitialStack32
){
1095 GlobalFree16(hInitialStack32
);
1096 IF1632_Stack32_base
= hInitialStack32
= 0;
1101 for (i
= 1; i
<= pModule
->seg_count
; i
++)
1102 NE_LoadSegment( hModule
, i
);
1105 /* Fixup the functions prologs */
1107 NE_FixupPrologs( pModule
);
1109 /* Make sure the usage count is 1 on the first loading of */
1110 /* the module, even if it contains circular DLL references */
1116 pModule
= MODULE_GetPtr( hModule
);
1117 hPrevInstance
= MODULE_GetInstance( hModule
);
1118 hInstance
= MODULE_CreateInstance( hModule
, params
);
1119 if (hInstance
!= hPrevInstance
) /* not a library */
1120 NE_LoadSegment( hModule
, pModule
->dgroup
);
1124 hModule
= GlobalAlloc16( GMEM_MOVEABLE
| GMEM_ZEROINIT
, sizeof(NE_MODULE
));
1125 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
1127 pModule
->magic
= NE_SIGNATURE
;
1128 pModule
->self
= hModule
;
1130 hInstance
= MODULE_CreateInstance( hModule
, (LOADPARAMS
*)paramBlock
);
1131 #endif /* WINELIB */
1133 /* Create a task for this instance */
1135 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
) && (paramBlock
!= (LPVOID
)-1))
1137 TASK_CreateTask( hModule
, hInstance
, hPrevInstance
,
1138 params
->hEnvironment
,
1139 (LPSTR
)PTR_SEG_TO_LIN( params
->cmdLine
),
1140 *((WORD
*)PTR_SEG_TO_LIN(params
->showCmd
)+1) );
1147 /**********************************************************************
1148 * FreeModule (KERNEL.46)
1150 BOOL
FreeModule( HANDLE hModule
)
1154 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1155 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
1157 dprintf_module( stddeb
, "FreeModule: %s count %d\n",
1158 MODULE_GetModuleName(hModule
), pModule
->count
);
1159 if (--pModule
->count
== 0) MODULE_FreeModule( hModule
);
1164 /**********************************************************************
1165 * GetModuleHandle (KERNEL.47)
1167 HMODULE
WIN16_GetModuleHandle( SEGPTR name
)
1169 if (HIWORD(name
) == 0) return GetExePtr( (HANDLE
)name
);
1170 return MODULE_FindModule( PTR_SEG_TO_LIN(name
) );
1173 HMODULE
GetModuleHandle( LPCSTR name
)
1175 return MODULE_FindModule( name
);
1179 /**********************************************************************
1180 * GetModuleUsage (KERNEL.48)
1182 int GetModuleUsage( HANDLE hModule
)
1186 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1187 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
1188 dprintf_module( stddeb
, "GetModuleUsage(%04x): returning %d\n",
1189 hModule
, pModule
->count
);
1190 return pModule
->count
;
1194 /**********************************************************************
1195 * GetModuleFileName (KERNEL.49)
1197 int GetModuleFileName( HANDLE hModule
, LPSTR lpFileName
, short nSize
)
1201 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1202 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
1203 lstrcpyn( lpFileName
, NE_MODULE_NAME(pModule
), nSize
);
1204 dprintf_module( stddeb
, "GetModuleFilename: %s\n", lpFileName
);
1205 return strlen(lpFileName
);
1209 /***********************************************************************
1210 * LoadLibrary (KERNEL.95)
1212 HANDLE
LoadLibrary( LPCSTR libname
)
1215 dprintf_module( stddeb
, "LoadLibrary: (%08x) %s\n", (int)libname
, libname
);
1216 WINELIB_UNIMP("LoadLibrary()");
1221 dprintf_module( stddeb
, "LoadLibrary: (%08x) %s\n", (int)libname
, libname
);
1223 /* This does not increment the module reference count, and will
1224 * therefore cause crashes on FreeLibrary calls.
1225 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1227 handle
= LoadModule( libname
, (LPVOID
)-1 );
1228 if (handle
== (HANDLE
)2) /* file not found */
1231 lstrcpyn( buffer
, libname
, 252 );
1232 strcat( buffer
, ".dll" );
1233 handle
= LoadModule( buffer
, (LPVOID
)-1 );
1235 if (handle
>= (HANDLE
)32) NE_InitializeDLLs( GetExePtr(handle
) );
1241 /***********************************************************************
1242 * FreeLibrary (KERNEL.96)
1244 void FreeLibrary( HANDLE handle
)
1246 dprintf_module( stddeb
,"FreeLibrary: %04x\n", handle
);
1247 FreeModule( handle
);
1251 /***********************************************************************
1252 * WinExec (KERNEL.166)
1254 HANDLE
WinExec( LPSTR lpCmdLine
, WORD nCmdShow
)
1257 HGLOBAL16 cmdShowHandle
, cmdLineHandle
;
1260 char *p
, *cmdline
, filename
[256];
1261 static int use_load_module
= 1;
1263 if (!(cmdShowHandle
= GlobalAlloc16( 0, 2 * sizeof(WORD
) ))) return 0;
1264 if (!(cmdLineHandle
= GlobalAlloc16( 0, 256 ))) return 0;
1266 /* Store nCmdShow */
1268 cmdShowPtr
= (WORD
*)GlobalLock16( cmdShowHandle
);
1270 cmdShowPtr
[1] = nCmdShow
;
1272 /* Build the filename and command-line */
1274 cmdline
= (char *)GlobalLock16( cmdLineHandle
);
1275 lstrcpyn( filename
, lpCmdLine
, sizeof(filename
) - 4 /* for extension */ );
1276 for (p
= filename
; *p
&& (*p
!= ' ') && (*p
!= '\t'); p
++);
1277 if (*p
) lstrcpyn( cmdline
, p
+ 1, 128 );
1278 else cmdline
[0] = '\0';
1281 /* Now load the executable file */
1283 if (use_load_module
)
1286 /* WINELIB: Use LoadModule() only for the program itself */
1287 use_load_module
= 0;
1288 params
.hEnvironment
= (HANDLE
)GetDOSEnvironment();
1290 params
.hEnvironment
= (HANDLE
)SELECTOROF( GetDOSEnvironment() );
1291 #endif /* WINELIB */
1292 params
.cmdLine
= (SEGPTR
)WIN16_GlobalLock16( cmdLineHandle
);
1293 params
.showCmd
= (SEGPTR
)WIN16_GlobalLock16( cmdShowHandle
);
1294 params
.reserved
= 0;
1295 handle
= LoadModule( filename
, ¶ms
);
1296 if (handle
== 2) /* file not found */
1298 /* Check that the original file name did not have a suffix */
1299 p
= strrchr(filename
, '.');
1300 if (!p
|| (strchr(p
, '/') && strchr(p
, '\\')))
1302 p
= filename
+ strlen(filename
);
1303 strcpy( p
, ".exe" );
1304 handle
= LoadModule( filename
, ¶ms
);
1305 *p
= '\0'; /* Remove extension */
1313 /* Try to start it as a unix program */
1317 const char *unixfilename
;
1318 const char *argv
[256], **argptr
;
1319 int iconic
= (nCmdShow
== SW_SHOWMINIMIZED
||
1320 nCmdShow
== SW_SHOWMINNOACTIVE
);
1322 /* get unixfilename */
1323 if (strchr(filename
, '/') ||
1324 strchr(filename
, ':') ||
1325 strchr(filename
, '\\'))
1326 unixfilename
= DOSFS_GetUnixFileName(filename
, 1);
1327 else unixfilename
= filename
;
1333 if (iconic
) *argptr
++ = "-iconic";
1334 *argptr
++ = unixfilename
;
1338 while (*p
&& (*p
== ' ' || *p
== '\t')) *p
++ = '\0';
1341 while (*p
&& *p
!= ' ' && *p
!= '\t') p
++;
1346 execvp(argv
[0], (char**)argv
);
1354 if (iconic
) *argptr
++ = "-iconic";
1355 *argptr
++ = lpCmdLine
;
1359 execvp(argv
[0] , (char**)argv
);
1362 fprintf(stderr
, "WinExec: can't exec 'wine %s'\n", lpCmdLine
);
1368 GlobalFree16( cmdShowHandle
);
1369 GlobalFree16( cmdLineHandle
);
1372 if (handle
< (HANDLE
)32) /* Error? */
1375 /* FIXME: Yield never returns!
1376 We may want to run more applications or start the debugger
1377 before calling Yield. If we don't Yield will be called immdiately
1378 after returning. Why is it needed for Word anyway? */
1379 Yield(); /* program is executed immediately ....needed for word */
1386 /***********************************************************************
1387 * GetProcAddress (KERNEL.50)
1389 FARPROC
GetProcAddress( HANDLE hModule
, SEGPTR name
)
1394 if (!hModule
) hModule
= GetCurrentTask();
1395 hModule
= GetExePtr( hModule
);
1397 if (HIWORD(name
) != 0)
1399 ordinal
= MODULE_GetOrdinal( hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1400 dprintf_module( stddeb
, "GetProcAddress: %04x '%s'\n",
1401 hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1405 ordinal
= LOWORD(name
);
1406 dprintf_module( stddeb
, "GetProcAddress: %04x %04x\n",
1409 if (!ordinal
) return (FARPROC
)0;
1411 ret
= MODULE_GetEntryPoint( hModule
, ordinal
);
1413 dprintf_module( stddeb
, "GetProcAddress: returning %08lx\n", (DWORD
)ret
);
1414 return (FARPROC
)ret
;
1418 /**********************************************************************
1419 * GetExpWinVer (KERNEL.167)
1421 WORD
GetExpWinVer( HMODULE hModule
)
1423 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
1424 return pModule
? pModule
->expected_version
: 0;
1428 /**********************************************************************
1429 * ModuleFirst (TOOLHELP.59)
1431 BOOL
ModuleFirst( MODULEENTRY
*lpme
)
1433 lpme
->wNext
= hFirstModule
;
1434 return ModuleNext( lpme
);
1438 /**********************************************************************
1439 * ModuleNext (TOOLHELP.60)
1441 BOOL
ModuleNext( MODULEENTRY
*lpme
)
1445 if (!lpme
->wNext
) return FALSE
;
1446 if (!(pModule
= MODULE_GetPtr( lpme
->wNext
))) return FALSE
;
1447 strncpy( lpme
->szModule
, (char *)pModule
+ pModule
->name_table
,
1449 lpme
->szModule
[MAX_MODULE_NAME
] = '\0';
1450 lpme
->hModule
= lpme
->wNext
;
1451 lpme
->wcUsage
= pModule
->count
;
1452 strncpy( lpme
->szExePath
, NE_MODULE_NAME(pModule
), MAX_PATH
);
1453 lpme
->szExePath
[MAX_PATH
] = '\0';
1454 lpme
->wNext
= pModule
->next
;
1459 /**********************************************************************
1460 * ModuleFindName (TOOLHELP.61)
1462 BOOL
ModuleFindName( MODULEENTRY
*lpme
, LPCSTR name
)
1464 lpme
->wNext
= GetModuleHandle( name
);
1465 return ModuleNext( lpme
);
1469 /**********************************************************************
1470 * ModuleFindHandle (TOOLHELP.62)
1472 BOOL
ModuleFindHandle( MODULEENTRY
*lpme
, HMODULE hModule
)
1474 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1475 lpme
->wNext
= hModule
;
1476 return ModuleNext( lpme
);