4 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
20 #include "stackframe.h"
29 static HMODULE hFirstModule
= 0;
30 static HMODULE hCachedModule
= 0; /* Module cached by MODULE_OpenFile */
33 static HANDLE hInitialStack32
= 0;
35 /***********************************************************************
38 * Load a built-in module. If the 'force' parameter is FALSE, we only
39 * load the module if it has not been disabled via the -dll option.
42 static HMODULE
MODULE_LoadBuiltin( LPCSTR name
, BOOL force
)
46 SEGTABLEENTRY
*pSegTable
;
47 struct dll_table_s
*table
;
51 /* Fix the name in case we have a full path and extension */
53 if ((p
= strrchr( name
, '\\' ))) name
= p
+ 1;
54 strncpy( dllname
, name
, 15 );
56 if ((p
= strrchr( dllname
, '.' ))) *p
= '\0';
58 for (i
= 0, table
= dll_builtin_table
; i
< N_BUILTINS
; i
++, table
++)
59 if (!strcasecmp( table
->name
, dllname
)) break;
60 if (i
>= N_BUILTINS
) return 0;
61 if (!table
->used
&& !force
) return 0;
63 hModule
= GLOBAL_CreateBlock( GMEM_MOVEABLE
, table
->module_start
,
64 table
->module_end
- table
->module_start
,
65 0, FALSE
, FALSE
, FALSE
, NULL
);
66 if (!hModule
) return 0;
67 FarSetOwner( hModule
, hModule
);
69 table
->hModule
= hModule
;
71 dprintf_module( stddeb
, "Built-in %s: hmodule=%04x\n",
72 table
->name
, hModule
);
74 /* Allocate the code segment */
76 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
77 pSegTable
= NE_SEG_TABLE( pModule
);
79 pSegTable
->selector
= GLOBAL_CreateBlock( GMEM_FIXED
, table
->code_start
,
80 pSegTable
->minsize
, hModule
,
81 TRUE
, TRUE
, FALSE
, NULL
);
82 if (!pSegTable
->selector
) return 0;
85 /* Allocate the data segment */
87 pSegTable
->selector
= GLOBAL_Alloc( GMEM_FIXED
, pSegTable
->minsize
,
88 hModule
, FALSE
, FALSE
, FALSE
);
89 if (!pSegTable
->selector
) return 0;
90 memcpy( GlobalLock( pSegTable
->selector
),
91 table
->data_start
, pSegTable
->minsize
);
93 pModule
->next
= hFirstModule
;
94 hFirstModule
= hModule
;
99 /***********************************************************************
102 * Create the built-in modules.
104 BOOL
MODULE_Init(void)
106 /* For these, built-in modules are always used */
109 if (!MODULE_LoadBuiltin( "KERNEL", TRUE
) ||
110 !MODULE_LoadBuiltin( "GDI", TRUE
) ||
111 !MODULE_LoadBuiltin( "USER", TRUE
) ||
112 !MODULE_LoadBuiltin( "WINPROCS", TRUE
)) return FALSE
;
115 fprintf(stderr
, "JBP: MODULE_Init() ignored.\n");
117 /* Initialize KERNEL.178 (__WINFLAGS) with the correct flags value */
119 MODULE_SetEntryPoint( GetModuleHandle( "KERNEL" ), 178, GetWinFlags() );
124 /***********************************************************************
127 void MODULE_PrintModule( HMODULE hmodule
)
133 NE_MODULE
*pModule
= (NE_MODULE
*)GlobalLock( hmodule
);
135 /* Dump the module info */
137 printf( "Module "NPFMT
":\n", hmodule
);
138 printf( "count=%d flags=%04x heap=%d stack=%d\n",
139 pModule
->count
, pModule
->flags
,
140 pModule
->heap_size
, pModule
->stack_size
);
141 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
142 pModule
->cs
, pModule
->ip
, pModule
->ss
, pModule
->sp
, pModule
->dgroup
,
143 pModule
->seg_count
, pModule
->modref_count
);
144 printf( "os_flags=%d swap_area=%d version=%04x\n",
145 pModule
->os_flags
, pModule
->min_swap_area
,
146 pModule
->expected_version
);
148 /* Dump the file info */
150 printf( "Filename: '%s'\n",
151 ((LOADEDFILEINFO
*)((BYTE
*)pModule
+ pModule
->fileinfo
))->filename
);
153 /* Dump the segment table */
155 printf( "\nSegment table:\n" );
156 pSeg
= NE_SEG_TABLE( pModule
);
157 for (i
= 0; i
< pModule
->seg_count
; i
++, pSeg
++)
158 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel="NPFMT
"\n",
159 i
+ 1, pSeg
->filepos
, pSeg
->size
, pSeg
->flags
,
160 pSeg
->minsize
, pSeg
->selector
);
162 /* Dump the resource table */
164 printf( "\nResource table:\n" );
165 if (pModule
->res_table
)
167 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->res_table
);
168 printf( "Alignment: %d\n", *pword
++ );
171 struct resource_typeinfo_s
*ptr
= (struct resource_typeinfo_s
*)pword
;
172 struct resource_nameinfo_s
*pname
= (struct resource_nameinfo_s
*)(ptr
+ 1);
173 printf( "id=%04x count=%d\n", ptr
->type_id
, ptr
->count
);
174 for (i
= 0; i
< ptr
->count
; i
++, pname
++)
175 printf( "offset=%d len=%d id=%04x\n",
176 pname
->offset
, pname
->length
, pname
->id
);
177 pword
= (WORD
*)pname
;
180 else printf( "None\n" );
182 /* Dump the resident name table */
184 printf( "\nResident-name table:\n" );
185 pstr
= (char *)pModule
+ pModule
->name_table
;
188 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
189 *(WORD
*)(pstr
+ *pstr
+ 1) );
190 pstr
+= *pstr
+ 1 + sizeof(WORD
);
193 /* Dump the module reference table */
195 printf( "\nModule ref table:\n" );
196 if (pModule
->modref_table
)
198 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->modref_table
);
199 for (i
= 0; i
< pModule
->modref_count
; i
++, pword
++)
201 char *name
= (char *)pModule
+ pModule
->import_table
+ *pword
;
202 printf( "%d: %04x -> '%*.*s'\n",
203 i
, *pword
, *name
, *name
, name
+ 1 );
206 else printf( "None\n" );
208 /* Dump the entry table */
210 printf( "\nEntry table:\n" );
211 pstr
= (char *)pModule
+ pModule
->entry_table
;
215 printf( "Bundle %d-%d: %02x\n", ordinal
, ordinal
+ *pstr
- 1, pstr
[1]);
221 else if ((BYTE
)pstr
[1] == 0xff) /* moveable */
223 struct entry_tab_movable_s
*pe
= (struct entry_tab_movable_s
*)(pstr
+2);
224 for (i
= 0; i
< *pstr
; i
++, pe
++)
225 printf( "%d: %02x:%04x (moveable)\n",
226 ordinal
++, pe
->seg_number
, pe
->offset
);
231 struct entry_tab_fixed_s
*pe
= (struct entry_tab_fixed_s
*)(pstr
+2);
232 for (i
= 0; i
< *pstr
; i
++, pe
++)
233 printf( "%d: %04x (fixed)\n",
234 ordinal
++, pe
->offset
[0] + (pe
->offset
[1] << 8) );
239 /* Dump the non-resident names table */
241 printf( "\nNon-resident names table:\n" );
242 if (pModule
->nrname_handle
)
244 pstr
= (char *)GlobalLock( pModule
->nrname_handle
);
247 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
248 *(WORD
*)(pstr
+ *pstr
+ 1) );
249 pstr
+= *pstr
+ 1 + sizeof(WORD
);
256 /***********************************************************************
259 int MODULE_OpenFile( HMODULE hModule
)
264 static int cachedfd
= -1;
266 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
267 dprintf_module( stddeb
, "MODULE_OpenFile("NPFMT
") cache: mod="NPFMT
" fd=%d\n",
268 hModule
, hCachedModule
, cachedfd
);
269 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return -1;
270 if (hCachedModule
== hModule
) return cachedfd
;
272 hCachedModule
= hModule
;
273 name
= ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
;
274 cachedfd
= open( DOS_GetUnixFileName( name
), O_RDONLY
);
275 dprintf_module( stddeb
, "MODULE_OpenFile: opened '%s' -> %d\n",
279 /***********************************************************************
283 /* This function translates NE segment flags to GlobalAlloc flags */
285 static WORD
MODULE_Ne2MemFlags(WORD flags
)
289 if (flags
& NE_SEGFLAGS_DISCARDABLE
)
290 memflags
|= GMEM_DISCARDABLE
;
291 if (flags
& NE_SEGFLAGS_MOVEABLE
||
292 ( ! (flags
& NE_SEGFLAGS_DATA
) &&
293 ! (flags
& NE_SEGFLAGS_LOADED
) &&
294 ! (flags
& NE_SEGFLAGS_ALLOCATED
)
297 memflags
|= GMEM_MOVEABLE
;
298 memflags
|= GMEM_ZEROINIT
;
300 memflags
= GMEM_ZEROINIT
| GMEM_FIXED
;
305 /***********************************************************************
306 * MODULE_AllocateSegment (WINPROCS.26)
309 DWORD
MODULE_AllocateSegment(WORD wFlags
, WORD wSize
, WORD wElem
)
311 WORD size
= wSize
<< wElem
;
312 HANDLE hMem
= GlobalAlloc( MODULE_Ne2MemFlags(wFlags
), size
);
314 return (DWORD
)GlobalLock(hMem
);
316 WORD selector
= HIWORD(GlobalLock(hMem
));
317 return MAKELONG(hMem
, selector
);
321 /***********************************************************************
322 * MODULE_CreateSegments
325 static BOOL
MODULE_CreateSegments( HMODULE hModule
)
327 SEGTABLEENTRY
*pSegment
;
331 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
332 pSegment
= NE_SEG_TABLE( pModule
);
333 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
335 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
336 if (i
== pModule
->ss
) minsize
+= pModule
->stack_size
;
337 /* The DGROUP is allocated by MODULE_CreateInstance */
338 if (i
== pModule
->dgroup
) continue;
339 pSegment
->selector
= GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment
->flags
),
341 !(pSegment
->flags
& NE_SEGFLAGS_DATA
),
343 FALSE
/*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
344 if (!pSegment
->selector
) return FALSE
;
347 pModule
->dgroup_entry
= pModule
->dgroup
? pModule
->seg_table
+
348 (pModule
->dgroup
- 1) * sizeof(SEGTABLEENTRY
) : 0;
354 /***********************************************************************
358 static HINSTANCE
MODULE_GetInstance( HMODULE hModule
)
360 SEGTABLEENTRY
*pSegment
;
363 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
364 if (pModule
->dgroup
== 0) return hModule
;
366 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
368 return pSegment
->selector
;
373 /***********************************************************************
374 * MODULE_CreateInstance
376 HINSTANCE
MODULE_CreateInstance( HMODULE hModule
, LOADPARAMS
*params
)
378 SEGTABLEENTRY
*pSegment
;
381 HINSTANCE hNewInstance
, hPrevInstance
;
383 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
384 if (pModule
->dgroup
== 0) return hModule
;
386 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
387 hPrevInstance
= pSegment
->selector
;
389 /* if it's a library, create a new instance only the first time */
392 if (pModule
->flags
& NE_FFLAGS_LIBMODULE
) return hPrevInstance
;
393 if (params
== (LOADPARAMS
*)-1) return hPrevInstance
;
396 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
397 if (pModule
->ss
== pModule
->dgroup
) minsize
+= pModule
->stack_size
;
398 minsize
+= pModule
->heap_size
;
399 hNewInstance
= GLOBAL_Alloc( GMEM_ZEROINIT
| GMEM_FIXED
,
400 minsize
, hModule
, FALSE
, FALSE
, FALSE
);
401 if (!hNewInstance
) return 0;
402 pSegment
->selector
= hNewInstance
;
407 /***********************************************************************
408 * MODULE_LoadExeHeader
410 HMODULE
MODULE_LoadExeHeader( int fd
, OFSTRUCT
*ofs
)
412 struct mz_header_s mz_header
;
413 struct ne_header_s ne_header
;
418 char *buffer
, *fastload
= NULL
;
419 int fastload_offset
= 0, fastload_length
= 0;
421 /* Read a block from either the file or the fast-load area. */
422 #define READ(offset,size,buffer) \
423 ((fastload && ((offset) >= fastload_offset) && \
424 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
425 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
426 (lseek( fd, mz_header.ne_offset+(offset), SEEK_SET), \
427 read( fd, (buffer), (size) ) == (size)))
429 lseek( fd
, 0, SEEK_SET
);
430 if ((read( fd
, &mz_header
, sizeof(mz_header
) ) != sizeof(mz_header
)) ||
431 (mz_header
.mz_magic
!= MZ_SIGNATURE
)) return (HMODULE
)11; /* invalid exe */
433 lseek( fd
, mz_header
.ne_offset
, SEEK_SET
);
434 if (read( fd
, &ne_header
, sizeof(ne_header
) ) != sizeof(ne_header
))
435 return (HMODULE
)11; /* invalid exe */
437 if (ne_header
.ne_magic
== PE_SIGNATURE
) return (HMODULE
)21; /* win32 exe */
438 if (ne_header
.ne_magic
!= NE_SIGNATURE
) return (HMODULE
)11; /* invalid exe */
440 /* We now have a valid NE header */
442 size
= sizeof(NE_MODULE
) +
443 /* loaded file info */
444 sizeof(LOADEDFILEINFO
) + strlen(ofs
->szPathName
) +
446 ne_header
.n_segment_tab
* sizeof(SEGTABLEENTRY
) +
448 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
+
449 /* resident names table */
450 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
+
451 /* module ref table */
452 ne_header
.n_mod_ref_tab
* sizeof(WORD
) +
453 /* imported names table */
454 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
+
455 /* entry table length */
456 ne_header
.entry_tab_length
;
458 hModule
= GlobalAlloc( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
459 if (!hModule
) return (HMODULE
)11; /* invalid exe */
460 FarSetOwner( hModule
, hModule
);
461 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
462 memcpy( pModule
, &ne_header
, sizeof(NE_MODULE
) );
464 pData
= (BYTE
*)(pModule
+ 1);
466 /* Read the fast-load area */
468 if (ne_header
.additional_flags
& NE_AFLAGS_FASTLOAD
)
470 fastload_offset
=ne_header
.fastload_offset
<<ne_header
.align_shift_count
;
471 fastload_length
=ne_header
.fastload_length
<<ne_header
.align_shift_count
;
472 dprintf_module( stddeb
, "Using fast-load area offset=%x len=%d\n",
473 fastload_offset
, fastload_length
);
474 if ((fastload
= (char *)malloc( fastload_length
)) != NULL
)
476 lseek( fd
, mz_header
.ne_offset
+ fastload_offset
, SEEK_SET
);
477 if (read( fd
, fastload
, fastload_length
) != fastload_length
)
485 /* Store the filename information */
487 pModule
->fileinfo
= (int)pData
- (int)pModule
;
488 ((LOADEDFILEINFO
*)pData
)->length
= sizeof(LOADEDFILEINFO
)+strlen(ofs
->szPathName
);
489 ((LOADEDFILEINFO
*)pData
)->fixed_media
= TRUE
;
490 ((LOADEDFILEINFO
*)pData
)->error
= 0;
491 ((LOADEDFILEINFO
*)pData
)->date
= 0;
492 ((LOADEDFILEINFO
*)pData
)->time
= 0;
493 strcpy( ((LOADEDFILEINFO
*)pData
)->filename
, ofs
->szPathName
);
494 pData
+= ((LOADEDFILEINFO
*)pData
)->length
--;
496 /* Get the segment table */
498 pModule
->seg_table
= (int)pData
- (int)pModule
;
499 buffer
= malloc( ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
) );
503 struct ne_segment_table_entry_s
*pSeg
;
505 if (!READ( ne_header
.segment_tab_offset
,
506 ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
),
507 buffer
)) return (HMODULE
)11; /* invalid exe */
508 pSeg
= (struct ne_segment_table_entry_s
*)buffer
;
509 for (i
= ne_header
.n_segment_tab
; i
> 0; i
--, pSeg
++)
511 memcpy( pData
, pSeg
, sizeof(*pSeg
) );
512 pData
+= sizeof(SEGTABLEENTRY
);
516 else return (HMODULE
)11; /* invalid exe */
518 /* Get the resource table */
520 if (ne_header
.resource_tab_offset
< ne_header
.rname_tab_offset
)
522 pModule
->res_table
= (int)pData
- (int)pModule
;
523 if (!READ(ne_header
.resource_tab_offset
,
524 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
,
525 pData
)) return (HMODULE
)11; /* invalid exe */
526 pData
+= ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
;
528 else pModule
->res_table
= 0; /* No resource table */
530 /* Get the resident names table */
532 pModule
->name_table
= (int)pData
- (int)pModule
;
533 if (!READ( ne_header
.rname_tab_offset
,
534 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
,
535 pData
)) return (HMODULE
)11; /* invalid exe */
536 pData
+= ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
;
538 /* Get the module references table */
540 if (ne_header
.n_mod_ref_tab
> 0)
542 pModule
->modref_table
= (int)pData
- (int)pModule
;
543 if (!READ( ne_header
.moduleref_tab_offset
,
544 ne_header
.n_mod_ref_tab
* sizeof(WORD
),
545 pData
)) return (HMODULE
)11; /* invalid exe */
546 pData
+= ne_header
.n_mod_ref_tab
* sizeof(WORD
);
548 else pModule
->modref_table
= 0; /* No module references */
550 /* Get the imported names table */
552 pModule
->import_table
= (int)pData
- (int)pModule
;
553 if (!READ( ne_header
.iname_tab_offset
,
554 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
,
555 pData
)) return (HMODULE
)11; /* invalid exe */
556 pData
+= ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
;
558 /* Get the entry table */
560 pModule
->entry_table
= (int)pData
- (int)pModule
;
561 if (!READ( ne_header
.entry_tab_offset
,
562 ne_header
.entry_tab_length
,
563 pData
)) return (HMODULE
)11; /* invalid exe */
564 pData
+= ne_header
.entry_tab_length
;
566 /* Get the non-resident names table */
568 if (ne_header
.nrname_tab_length
)
570 pModule
->nrname_handle
= GLOBAL_Alloc( 0, ne_header
.nrname_tab_length
,
571 hModule
, FALSE
, FALSE
, FALSE
);
572 if (!pModule
->nrname_handle
) return (HMODULE
)11; /* invalid exe */
573 buffer
= GlobalLock( pModule
->nrname_handle
);
574 lseek( fd
, ne_header
.nrname_tab_offset
, SEEK_SET
);
575 if (read( fd
, buffer
, ne_header
.nrname_tab_length
)
576 != ne_header
.nrname_tab_length
) return (HMODULE
)11; /* invalid exe */
578 else pModule
->nrname_handle
= 0;
580 /* Allocate a segment for the implicitly-loaded DLLs */
582 if (pModule
->modref_count
)
584 pModule
->dlls_to_init
= GLOBAL_Alloc(GMEM_ZEROINIT
,
585 (pModule
->modref_count
+1)*sizeof(HMODULE
),
586 hModule
, FALSE
, FALSE
, FALSE
);
587 if (!pModule
->dlls_to_init
) return (HMODULE
)11; /* invalid exe */
589 else pModule
->dlls_to_init
= 0;
591 if (debugging_module
) MODULE_PrintModule( hModule
);
592 pModule
->next
= hFirstModule
;
593 hFirstModule
= hModule
;
598 /***********************************************************************
601 * Lookup the ordinal for a given name.
603 WORD
MODULE_GetOrdinal( HMODULE hModule
, char *name
)
605 char buffer
[256], *cpnt
;
609 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
611 dprintf_module( stddeb
, "MODULE_GetOrdinal("NPFMT
",'%s')\n",
614 /* First handle names of the form '#xxxx' */
616 if (name
[0] == '#') return atoi( name
+ 1 );
618 /* Now copy and uppercase the string */
620 strcpy( buffer
, name
);
622 len
= strlen( buffer
);
624 /* First search the resident names */
626 cpnt
= (char *)pModule
+ pModule
->name_table
;
628 /* Skip the first entry (module name) */
629 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
632 dprintf_module( stddeb
, " Checking '%*.*s'\n", *cpnt
, *cpnt
, cpnt
+1 );
633 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
635 dprintf_module( stddeb
, " Found: ordinal=%d\n",
636 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
637 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
639 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
642 /* Now search the non-resident names table */
644 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
645 cpnt
= (char *)GlobalLock( pModule
->nrname_handle
);
647 /* Skip the first entry (module description string) */
648 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
651 dprintf_module( stddeb
, " Checking '%*.*s'\n", *cpnt
, *cpnt
, cpnt
+1 );
652 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
654 dprintf_module( stddeb
, " Found: ordinal=%d\n",
655 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
656 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
658 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
664 /***********************************************************************
665 * MODULE_GetEntryPoint
667 * Return the entry point for a given ordinal.
669 DWORD
MODULE_GetEntryPoint( HMODULE hModule
, WORD ordinal
)
676 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
678 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
679 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
681 /* Skipping this bundle */
685 case 0: p
+= 2; break; /* unused */
686 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
687 default: p
+= 2 + *p
* 3; break; /* fixed */
696 case 0xff: /* moveable */
697 p
+= 2 + 6 * (ordinal
- curOrdinal
);
699 offset
= *(WORD
*)(p
+ 4);
703 p
+= 2 + 3 * (ordinal
- curOrdinal
);
704 offset
= *(WORD
*)(p
+ 1);
708 if (sel
== 0xfe) sel
= 0xffff; /* constant entry */
709 else sel
= (WORD
)NE_SEG_TABLE(pModule
)[sel
-1].selector
;
710 return MAKELONG( offset
, sel
);
714 /***********************************************************************
715 * MODULE_SetEntryPoint
717 * Change the value of an entry point. Use with caution!
718 * It can only change the offset value, not the selector.
720 BOOL
MODULE_SetEntryPoint( HMODULE hModule
, WORD ordinal
, WORD offset
)
726 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
728 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
729 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
731 /* Skipping this bundle */
735 case 0: p
+= 2; break; /* unused */
736 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
737 default: p
+= 2 + *p
* 3; break; /* fixed */
740 if (!*p
) return FALSE
;
746 case 0xff: /* moveable */
747 p
+= 2 + 6 * (ordinal
- curOrdinal
);
748 *(WORD
*)(p
+ 4) = offset
;
751 p
+= 2 + 3 * (ordinal
- curOrdinal
);
752 *(WORD
*)(p
+ 1) = offset
;
759 /***********************************************************************
760 * MODULE_GetEntryPointName
762 * Return the entry point name for a given ordinal.
763 * Used only by relay debugging.
764 * Warning: returned pointer is to a Pascal-type string.
766 LPSTR
MODULE_GetEntryPointName( HMODULE hModule
, WORD ordinal
)
771 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
773 /* First search the resident names */
775 cpnt
= (char *)pModule
+ pModule
->name_table
;
778 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
779 if (*(WORD
*)(cpnt
+ *cpnt
+ 1) == ordinal
) return cpnt
;
782 /* Now search the non-resident names table */
784 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
785 cpnt
= (char *)GlobalLock( pModule
->nrname_handle
);
788 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
789 if (*(WORD
*)(cpnt
+ *cpnt
+ 1) == ordinal
) return cpnt
;
795 /***********************************************************************
796 * MODULE_GetModuleName
798 LPSTR
MODULE_GetModuleName( HMODULE hModule
)
802 static char buffer
[10];
804 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return NULL
;
805 p
= (BYTE
*)pModule
+ pModule
->name_table
;
807 memcpy( buffer
, p
+ 1, len
);
813 /**********************************************************************
816 * Find a module from a path name.
818 HMODULE
MODULE_FindModule( LPCSTR path
)
820 HMODULE hModule
= hFirstModule
;
821 LPCSTR filename
, dotptr
, modulepath
, modulename
;
822 BYTE len
, *name_table
;
824 if (!(filename
= strrchr( path
, '\\' ))) filename
= path
;
826 if ((dotptr
= strrchr( filename
, '.' )) != NULL
)
827 len
= (BYTE
)(dotptr
- filename
);
828 else len
= strlen( filename
);
832 NE_MODULE
*pModule
= (NE_MODULE
*)GlobalLock( hModule
);
834 modulepath
= ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
;
835 if (!(modulename
= strrchr( modulepath
, '\\' )))
836 modulename
= modulepath
;
838 if (!strcasecmp( modulename
, filename
)) return hModule
;
840 name_table
= (BYTE
*)pModule
+ pModule
->name_table
;
841 if ((*name_table
== len
) && !strncasecmp(filename
, name_table
+1, len
))
843 hModule
= pModule
->next
;
849 /**********************************************************************
852 * Remove a module from memory.
854 static void MODULE_FreeModule( HMODULE hModule
)
856 HMODULE
*hPrevModule
;
858 SEGTABLEENTRY
*pSegment
;
862 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return;
863 if (pModule
->flags
& NE_FFLAGS_BUILTIN
)
864 return; /* Can't free built-in module */
866 /* FIXME: should call the exit code for the library here */
868 /* Remove it from the linked list */
870 hPrevModule
= &hFirstModule
;
871 while (*hPrevModule
&& (*hPrevModule
!= hModule
))
873 hPrevModule
= &((NE_MODULE
*)GlobalLock( *hPrevModule
))->next
;
875 if (*hPrevModule
) *hPrevModule
= pModule
->next
;
877 /* Free all the segments */
879 pSegment
= NE_SEG_TABLE( pModule
);
880 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
882 GlobalFree( pSegment
->selector
);
885 /* Free the referenced modules */
887 pModRef
= NE_MODULE_TABLE( pModule
);
888 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
890 FreeModule( *pModRef
);
893 /* Free the module storage */
895 if (pModule
->nrname_handle
) GlobalFree( pModule
->nrname_handle
);
896 if (pModule
->dlls_to_init
) GlobalFree( pModule
->dlls_to_init
);
897 GlobalFree( hModule
);
899 /* Remove module from cache */
901 if (hCachedModule
== hModule
) hCachedModule
= 0;
905 HINSTANCE
PE_LoadModule(int fd
, OFSTRUCT
*ofs
, LOADPARAMS
* params
);
907 /**********************************************************************
908 * LoadModule (KERNEL.45)
910 HINSTANCE
LoadModule( LPCSTR name
, LPVOID paramBlock
)
913 HANDLE hInstance
, hPrevInstance
;
915 LOADPARAMS
*params
= (LOADPARAMS
*)paramBlock
;
917 WORD
*pModRef
, *pDLLs
;
920 hModule
= MODULE_FindModule( name
);
922 if (!hModule
) /* We have to load the module */
926 /* Try to load the built-in first if not disabled */
927 if ((hModule
= MODULE_LoadBuiltin( name
, FALSE
))) return hModule
;
929 if (strchr( name
, '/' )) name
= DOS_GetDosFileName( name
);
930 if ((fd
= OpenFile( name
, &ofs
, OF_READ
)) == -1)
932 /* Now try the built-in even if disabled */
933 if ((hModule
= MODULE_LoadBuiltin( name
, TRUE
)))
935 fprintf( stderr
, "Warning: could not load Windows DLL '%s', using built-in module.\n", name
);
938 return 2; /* File not found */
941 /* Create the module structure */
943 if ((hModule
= MODULE_LoadExeHeader( fd
, &ofs
)) < 32)
946 return PE_LoadModule(fd
,&ofs
,paramBlock
);
948 fprintf( stderr
, "LoadModule: can't load '%s', error=%d\n",
952 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
954 /* Allocate the segments for this module */
956 MODULE_CreateSegments( hModule
);
959 hInstance
= MODULE_CreateInstance( hModule
, (LOADPARAMS
*)paramBlock
);
961 /* Load the referenced DLLs */
963 pModRef
= (WORD
*)((char *)pModule
+ pModule
->modref_table
);
964 pDLLs
= (WORD
*)GlobalLock( pModule
->dlls_to_init
);
965 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
968 BYTE
*pstr
= (BYTE
*)pModule
+ pModule
->import_table
+ *pModRef
;
969 memcpy( buffer
, pstr
+ 1, *pstr
);
970 strcpy( buffer
+ *pstr
, ".dll" );
971 dprintf_module( stddeb
, "Loading '%s'\n", buffer
);
972 if (!(*pModRef
= MODULE_FindModule( buffer
)))
974 /* If the DLL is not loaded yet, load it and store */
975 /* its handle in the list of DLLs to initialize. */
978 if ((hDLL
= LoadModule( buffer
, (LPVOID
)-1 )) == 2) /* file not found */
982 /* Try with prepending the path of the current module */
983 GetModuleFileName( hModule
, buffer
, 256 );
984 if (!(p
= strrchr( buffer
, '\\' ))) p
= buffer
;
985 memcpy( p
+ 1, pstr
+ 1, *pstr
);
986 strcpy( p
+ 1 + *pstr
, ".dll" );
987 hDLL
= LoadModule( buffer
, (LPVOID
)-1 );
991 fprintf( stderr
, "Could not load '%s' required by '%s', error = %d\n",
992 buffer
, name
, hDLL
);
993 return 2; /* file not found */
995 *pModRef
= GetExePtr( hDLL
);
998 else /* Increment the reference count of the DLL */
1000 NE_MODULE
*pOldDLL
= (NE_MODULE
*)GlobalLock( *pModRef
);
1001 if (pOldDLL
) pOldDLL
->count
++;
1005 /* Load the segments */
1007 if (pModule
->flags
& NE_FFLAGS_SELFLOAD
)
1009 /* Handle self loading modules */
1010 SEGTABLEENTRY
* pSegTable
= (SEGTABLEENTRY
*) NE_SEG_TABLE(pModule
);
1011 SELFLOADHEADER
*selfloadheader
;
1012 HMODULE hselfload
= GetModuleHandle("WINPROCS");
1013 WORD oldss
, oldsp
, saved_dgroup
= pSegTable
[pModule
->dgroup
- 1].selector
;
1014 fprintf (stderr
, "Warning: %*.*s is a self-loading module\n"
1015 "Support for self-loading modules is very experimental\n",
1016 *((BYTE
*)pModule
+ pModule
->name_table
),
1017 *((BYTE
*)pModule
+ pModule
->name_table
),
1018 (char *)pModule
+ pModule
->name_table
+ 1);
1019 NE_LoadSegment( hModule
, 1 );
1020 selfloadheader
= (SELFLOADHEADER
*)
1021 PTR_SEG_OFF_TO_LIN(pSegTable
->selector
, 0);
1022 selfloadheader
->EntryAddrProc
=
1023 MODULE_GetEntryPoint(hselfload
,27);
1024 selfloadheader
->MyAlloc
= MODULE_GetEntryPoint(hselfload
,28);
1025 selfloadheader
->SetOwner
= MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1026 pModule
->self_loading_sel
= GlobalHandleToSel(
1027 GLOBAL_Alloc (GMEM_ZEROINIT
,
1028 0xFF00, hModule
, FALSE
, FALSE
, FALSE
)
1030 oldss
= IF1632_Saved16_ss
;
1031 oldsp
= IF1632_Saved16_sp
;
1032 IF1632_Saved16_ss
= pModule
->self_loading_sel
;
1033 IF1632_Saved16_sp
= 0xFF00;
1034 if (!IF1632_Stack32_base
) {
1035 STACK32FRAME
* frame32
;
1037 /* Setup an initial 32 bit stack frame */
1038 hInitialStack32
= GLOBAL_Alloc( GMEM_FIXED
, 0x10000,
1039 hModule
, FALSE
, FALSE
,
1042 /* Create the 32-bit stack frame */
1044 *(DWORD
*)GlobalLock(hInitialStack32
) = 0xDEADBEEF;
1045 stack32Top
= (char*)GlobalLock(hInitialStack32
) +
1047 frame32
= (STACK32FRAME
*)stack32Top
- 1;
1048 frame32
->saved_esp
= (DWORD
)stack32Top
;
1055 frame32
->retaddr
= 0;
1056 frame32
->codeselector
= WINE_CODE_SELECTOR
;
1057 /* pTask->esp = (DWORD)frame32; */
1058 IF1632_Stack32_base
= WIN16_GlobalLock(hInitialStack32
);
1061 CallTo16_word_ww (selfloadheader
->BootApp
,
1062 pModule
->self_loading_sel
, hModule
, fd
);
1063 /* some BootApp procs overwrite the selector of dgroup */
1064 pSegTable
[pModule
->dgroup
- 1].selector
= saved_dgroup
;
1065 IF1632_Saved16_ss
= oldss
;
1066 IF1632_Saved16_sp
= oldsp
;
1067 for (i
= 2; i
<= pModule
->seg_count
; i
++) NE_LoadSegment( hModule
, i
);
1068 if (hInitialStack32
){
1069 GlobalUnlock (hInitialStack32
);
1070 GlobalFree (hInitialStack32
);
1071 IF1632_Stack32_base
= hInitialStack32
= 0;
1076 for (i
= 1; i
<= pModule
->seg_count
; i
++)
1077 NE_LoadSegment( hModule
, i
);
1080 /* Fixup the functions prologs */
1082 NE_FixupPrologs( hModule
);
1084 /* Make sure the usage count is 1 on the first loading of */
1085 /* the module, even if it contains circular DLL references */
1089 /* Clear built-in flag in case it was set in the EXE file */
1091 pModule
->flags
&= ~NE_FFLAGS_BUILTIN
;
1095 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
1096 hPrevInstance
= MODULE_GetInstance( hModule
);
1097 hInstance
= MODULE_CreateInstance( hModule
, params
);
1098 if (hInstance
!= hPrevInstance
) /* not a library */
1099 NE_LoadSegment( hModule
, pModule
->dgroup
);
1103 hModule
= GlobalAlloc( GMEM_MOVEABLE
| GMEM_ZEROINIT
, sizeof(NE_MODULE
) );
1104 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
1106 pModule
->magic
= 0x454e;
1108 hInstance
= MODULE_CreateInstance( hModule
, (LOADPARAMS
*)paramBlock
);
1109 #endif /* WINELIB */
1111 /* Create a task for this instance */
1113 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
) && (paramBlock
!= (LPVOID
)-1))
1115 TASK_CreateTask( hModule
, hInstance
, hPrevInstance
,
1116 params
->hEnvironment
,
1117 (LPSTR
)PTR_SEG_TO_LIN( params
->cmdLine
),
1118 *((WORD
*)PTR_SEG_TO_LIN(params
->showCmd
)+1) );
1125 /**********************************************************************
1126 * FreeModule (KERNEL.46)
1128 BOOL
FreeModule( HANDLE hModule
)
1132 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1133 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
1135 dprintf_module( stddeb
, "FreeModule: %s count %d\n",
1136 MODULE_GetModuleName(hModule
), pModule
->count
);
1137 if (--pModule
->count
== 0) MODULE_FreeModule( hModule
);
1142 /**********************************************************************
1143 * GetModuleHandle (KERNEL.47)
1145 HMODULE
WIN16_GetModuleHandle( SEGPTR name
)
1148 if (HIWORD(name
) == 0) return GetExePtr( name
);
1150 if (HIWORD(name
) == 0) return GetExePtr( LOWORD(name
) );
1152 return MODULE_FindModule( PTR_SEG_TO_LIN(name
) );
1155 HMODULE
GetModuleHandle( LPCSTR name
)
1157 return MODULE_FindModule( name
);
1161 /**********************************************************************
1162 * GetModuleUsage (KERNEL.48)
1164 int GetModuleUsage( HANDLE hModule
)
1168 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1169 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
1170 dprintf_module( stddeb
, "GetModuleUsage("NPFMT
"): returning %d\n",
1171 hModule
, pModule
->count
);
1172 return pModule
->count
;
1176 /**********************************************************************
1177 * GetModuleFileName (KERNEL.49)
1179 int GetModuleFileName( HANDLE hModule
, LPSTR lpFileName
, short nSize
)
1184 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1185 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
1186 name
= ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
;
1187 lstrcpyn( lpFileName
, name
, nSize
);
1188 dprintf_module( stddeb
, "GetModuleFilename: %s\n", lpFileName
);
1189 return strlen(lpFileName
);
1193 /***********************************************************************
1194 * LoadLibrary (KERNEL.95)
1196 HANDLE
LoadLibrary( LPCSTR libname
)
1199 dprintf_module( stddeb
, "LoadLibrary: (%08x) %s\n", (int)libname
, libname
);
1200 WINELIB_UNIMP("LoadLibrary()");
1205 dprintf_module( stddeb
, "LoadLibrary: (%08x) %s\n", (int)libname
, libname
);
1207 /* This does not increment the module reference count, and will
1208 * therefore cause crashes on FreeLibrary calls.
1209 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1211 handle
= LoadModule( libname
, (LPVOID
)-1 );
1212 if (handle
== (HANDLE
)2) /* file not found */
1215 strcpy( buffer
, libname
);
1216 strcat( buffer
, ".dll" );
1217 handle
= LoadModule( buffer
, (LPVOID
)-1 );
1219 if (handle
>= (HANDLE
)32) NE_InitializeDLLs( GetExePtr(handle
) );
1225 /***********************************************************************
1226 * FreeLibrary (KERNEL.96)
1228 void FreeLibrary( HANDLE handle
)
1230 dprintf_module( stddeb
,"FreeLibrary: "NPFMT
"\n", handle
);
1231 FreeModule( handle
);
1235 /***********************************************************************
1236 * WinExec (KERNEL.166)
1238 HANDLE
WinExec( LPSTR lpCmdLine
, WORD nCmdShow
)
1241 HLOCAL cmdShowHandle
, cmdLineHandle
;
1244 char *p
, *cmdline
, filename
[256];
1246 if (!(cmdShowHandle
= GlobalAlloc( 0, 2 * sizeof(WORD
) ))) return 0;
1247 if (!(cmdLineHandle
= GlobalAlloc( 0, 256 ))) return 0;
1249 /* Store nCmdShow */
1251 cmdShowPtr
= (WORD
*)GlobalLock( cmdShowHandle
);
1253 cmdShowPtr
[1] = nCmdShow
;
1255 /* Build the filename and command-line */
1257 cmdline
= (char *)GlobalLock( cmdLineHandle
);
1258 strncpy( filename
, lpCmdLine
, 256 );
1259 filename
[255] = '\0';
1260 for (p
= filename
; *p
&& (*p
!= ' ') && (*p
!= '\t'); p
++);
1263 strncpy( cmdline
, p
+ 1, 128 );
1264 cmdline
[127] = '\0';
1266 else cmdline
[0] = '\0';
1269 /* Now load the executable file */
1271 params
.hEnvironment
= (HANDLE
)SELECTOROF( GetDOSEnvironment() );
1272 params
.cmdLine
= (SEGPTR
)WIN16_GlobalLock( cmdLineHandle
);
1273 params
.showCmd
= (SEGPTR
)WIN16_GlobalLock( cmdShowHandle
);
1274 params
.reserved
= 0;
1275 handle
= LoadModule( filename
, ¶ms
);
1276 if (handle
== (HANDLE
)2) /* file not found */
1278 /* Check that the original file name did not have a suffix */
1279 p
= strrchr(filename
, '.');
1280 if (p
&& !(strchr(p
, '/') || strchr(p
, '\\')))
1281 return handle
; /* filename already includes a suffix! */
1282 strcat( filename
, ".exe" );
1283 handle
= LoadModule( filename
, ¶ms
);
1286 GlobalFree( cmdShowHandle
);
1287 GlobalFree( cmdLineHandle
);
1290 if (handle
< (HANDLE
)32) /* Error? */
1293 /* FIXME: Yield never returns!
1294 We may want to run more applications or start the debugger
1295 before calling Yield. If we don't Yield will be called immdiately
1296 after returning. Why is it needed for Word anyway? */
1297 Yield(); /* program is executed immediately ....needed for word */
1304 /***********************************************************************
1305 * GetProcAddress (KERNEL.50)
1307 FARPROC
GetProcAddress( HANDLE hModule
, SEGPTR name
)
1312 if (!hModule
) hModule
= GetCurrentTask();
1313 hModule
= GetExePtr( hModule
);
1315 if (HIWORD(name
) != 0)
1317 ordinal
= MODULE_GetOrdinal( hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1318 dprintf_module( stddeb
, "GetProcAddress: "NPFMT
" '%s'\n",
1319 hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1323 ordinal
= LOWORD(name
);
1324 dprintf_module( stddeb
, "GetProcAddress: "NPFMT
" %04x\n",
1327 if (!ordinal
) return (FARPROC
)0;
1329 ret
= MODULE_GetEntryPoint( hModule
, ordinal
);
1331 dprintf_module( stddeb
, "GetProcAddress: returning %08lx\n", ret
);
1332 return (FARPROC
)ret
;
1336 /**********************************************************************
1337 * GetExpWinVer (KERNEL.167)
1339 WORD
GetExpWinVer( HMODULE hModule
)
1341 NE_MODULE
*pModule
= (NE_MODULE
*)GlobalLock( hModule
);
1343 return pModule
->expected_version
;
1347 /***********************************************************************
1348 * GetWndProcEntry16 (not a Windows API function)
1350 * Return an entry point from the WINPROCS dll.
1353 WNDPROC
GetWndProcEntry16( char *name
)
1356 static HMODULE hModule
= 0;
1358 if (!hModule
) hModule
= GetModuleHandle( "WINPROCS" );
1359 ordinal
= MODULE_GetOrdinal( hModule
, name
);
1360 return MODULE_GetEntryPoint( hModule
, ordinal
);
1365 /**********************************************************************
1366 * ModuleFirst (TOOLHELP.59)
1368 BOOL
ModuleFirst( MODULEENTRY
*lpme
)
1370 lpme
->wNext
= hFirstModule
;
1371 return ModuleNext( lpme
);
1375 /**********************************************************************
1376 * ModuleNext (TOOLHELP.60)
1378 BOOL
ModuleNext( MODULEENTRY
*lpme
)
1382 if (!lpme
->wNext
) return FALSE
;
1383 if (!(pModule
= (NE_MODULE
*)GlobalLock( lpme
->wNext
))) return FALSE
;
1384 strncpy( lpme
->szModule
, (char *)pModule
+ pModule
->name_table
,
1386 lpme
->szModule
[MAX_MODULE_NAME
] = '\0';
1387 lpme
->hModule
= lpme
->wNext
;
1388 lpme
->wcUsage
= pModule
->count
;
1389 strncpy( lpme
->szExePath
,
1390 ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
,
1392 lpme
->szExePath
[MAX_PATH
] = '\0';
1393 lpme
->wNext
= pModule
->next
;
1398 /**********************************************************************
1399 * ModuleFindName (TOOLHELP.61)
1401 BOOL
ModuleFindName( MODULEENTRY
*lpme
, LPCSTR name
)
1403 lpme
->wNext
= GetModuleHandle( name
);
1404 return ModuleNext( lpme
);
1408 /**********************************************************************
1409 * ModuleFindHandle (TOOLHELP.62)
1411 BOOL
ModuleFindHandle( MODULEENTRY
*lpme
, HMODULE hModule
)
1413 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1414 lpme
->wNext
= hModule
;
1415 return ModuleNext( lpme
);