4 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
20 #include "stackframe.h"
27 static HMODULE hFirstModule
= 0;
28 static HMODULE hCachedModule
= 0; /* Module cached by MODULE_OpenFile */
31 /***********************************************************************
34 * Create the built-in modules.
36 BOOL
MODULE_Init(void)
38 extern void load_entrypoints( HMODULE
);
42 SEGTABLEENTRY
*pSegTable
;
43 struct dll_table_s
*table
;
47 /* Create the built-in modules */
49 for (i
= 0, table
= dll_builtin_table
; i
< N_BUILTINS
; i
++, table
++)
51 if (!table
->used
) continue;
53 hModule
= GLOBAL_CreateBlock( GMEM_MOVEABLE
, table
->module_start
,
54 table
->module_end
- table
->module_start
,
55 0, FALSE
, FALSE
, FALSE
, NULL
);
56 if (!hModule
) return FALSE
;
57 FarSetOwner( hModule
, hModule
);
59 table
->hModule
= hModule
;
61 dprintf_module( stddeb
, "Built-in %s: hmodule=%04x\n",
62 table
->name
, hModule
);
64 /* Allocate the code segment */
66 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
67 pSegTable
= NE_SEG_TABLE( pModule
);
69 pSegTable
->selector
= GLOBAL_CreateBlock(GMEM_FIXED
, table
->code_start
,
70 pSegTable
->minsize
, hModule
,
71 TRUE
, TRUE
, FALSE
, NULL
);
72 if (!pSegTable
->selector
) return FALSE
;
75 /* Allocate the data segment */
77 pSegTable
->selector
= GLOBAL_Alloc( GMEM_FIXED
, pSegTable
->minsize
,
78 hModule
, FALSE
, FALSE
, FALSE
);
79 if (!pSegTable
->selector
) return FALSE
;
80 memcpy( GlobalLock( pSegTable
->selector
), table
->data_start
,
83 pModule
->next
= hFirstModule
;
84 hFirstModule
= hModule
;
85 load_entrypoints( hModule
);
88 /* Initialize some KERNEL exported values */
90 if (!(hModule
= GetModuleHandle( "KERNEL" ))) return TRUE
;
92 /* KERNEL.178: __WINFLAGS */
93 MODULE_SetEntryPoint( hModule
, 178, GetWinFlags() );
95 /* Allocate 7 64k segments for 0000, A000, B000, C000, D000, E000, F000. */
97 dosmem
= malloc( 0x70000 );
99 MODULE_SetEntryPoint( hModule
, 183, /* KERNEL.183: __0000H */
100 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
,
101 0x10000, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
102 MODULE_SetEntryPoint( hModule
, 193, /* KERNEL.193: __0040H */
103 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
+ 0x400,
104 0x100, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
105 MODULE_SetEntryPoint( hModule
, 174, /* KERNEL.174: __A000H */
106 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
+ 0x10000,
107 0x10000, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
108 MODULE_SetEntryPoint( hModule
, 181, /* KERNEL.181: __B000H */
109 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
+ 0x20000,
110 0x10000, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
111 MODULE_SetEntryPoint( hModule
, 182, /* KERNEL.182: __B800H */
112 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
+ 0x28000,
113 0x10000, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
114 MODULE_SetEntryPoint( hModule
, 195, /* KERNEL.195: __C000H */
115 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
+ 0x30000,
116 0x10000, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
117 MODULE_SetEntryPoint( hModule
, 179, /* KERNEL.179: __D000H */
118 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
+ 0x40000,
119 0x10000, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
120 MODULE_SetEntryPoint( hModule
, 190, /* KERNEL.190: __E000H */
121 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
+ 0x50000,
122 0x10000, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
123 MODULE_SetEntryPoint( hModule
, 173, /* KERNEL.173: __ROMBIOS */
124 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
+ 0x60000,
125 0x10000, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
126 MODULE_SetEntryPoint( hModule
, 194, /* KERNEL.194: __F000H */
127 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
+ 0x60000,
128 0x10000, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
133 /***********************************************************************
136 void MODULE_PrintModule( HMODULE hmodule
)
142 NE_MODULE
*pModule
= (NE_MODULE
*)GlobalLock( hmodule
);
144 /* Dump the module info */
146 printf( "Module %04x:\n", hmodule
);
147 printf( "count=%d flags=%04x heap=%d stack=%d\n",
148 pModule
->count
, pModule
->flags
,
149 pModule
->heap_size
, pModule
->stack_size
);
150 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
151 pModule
->cs
, pModule
->ip
, pModule
->ss
, pModule
->sp
, pModule
->dgroup
,
152 pModule
->seg_count
, pModule
->modref_count
);
153 printf( "os_flags=%d swap_area=%d version=%04x\n",
154 pModule
->os_flags
, pModule
->min_swap_area
,
155 pModule
->expected_version
);
157 /* Dump the file info */
159 printf( "Filename: '%s'\n",
160 ((LOADEDFILEINFO
*)((BYTE
*)pModule
+ pModule
->fileinfo
))->filename
);
162 /* Dump the segment table */
164 printf( "\nSegment table:\n" );
165 pSeg
= NE_SEG_TABLE( pModule
);
166 for (i
= 0; i
< pModule
->seg_count
; i
++, pSeg
++)
167 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
168 i
+ 1, pSeg
->filepos
, pSeg
->size
, pSeg
->flags
,
169 pSeg
->minsize
, pSeg
->selector
);
171 /* Dump the resource table */
173 printf( "\nResource table:\n" );
174 if (pModule
->res_table
)
176 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->res_table
);
177 printf( "Alignment: %d\n", *pword
++ );
180 struct resource_typeinfo_s
*ptr
= (struct resource_typeinfo_s
*)pword
;
181 struct resource_nameinfo_s
*pname
= (struct resource_nameinfo_s
*)(ptr
+ 1);
182 printf( "id=%04x count=%d\n", ptr
->type_id
, ptr
->count
);
183 for (i
= 0; i
< ptr
->count
; i
++, pname
++)
184 printf( "offset=%d len=%d id=%04x\n",
185 pname
->offset
, pname
->length
, pname
->id
);
186 pword
= (WORD
*)pname
;
189 else printf( "None\n" );
191 /* Dump the resident name table */
193 printf( "\nResident-name table:\n" );
194 pstr
= (char *)pModule
+ pModule
->name_table
;
197 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
198 *(WORD
*)(pstr
+ *pstr
+ 1) );
199 pstr
+= *pstr
+ 1 + sizeof(WORD
);
202 /* Dump the module reference table */
204 printf( "\nModule ref table:\n" );
205 if (pModule
->modref_table
)
207 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->modref_table
);
208 for (i
= 0; i
< pModule
->modref_count
; i
++, pword
++)
210 char *name
= (char *)pModule
+ pModule
->import_table
+ *pword
;
211 printf( "%d: %04x -> '%*.*s'\n",
212 i
, *pword
, *name
, *name
, name
+ 1 );
215 else printf( "None\n" );
217 /* Dump the entry table */
219 printf( "\nEntry table:\n" );
220 pstr
= (char *)pModule
+ pModule
->entry_table
;
224 printf( "Bundle %d-%d: %02x\n", ordinal
, ordinal
+ *pstr
- 1, pstr
[1]);
230 else if ((BYTE
)pstr
[1] == 0xff) /* moveable */
232 struct entry_tab_movable_s
*pe
= (struct entry_tab_movable_s
*)(pstr
+2);
233 for (i
= 0; i
< *pstr
; i
++, pe
++)
234 printf( "%d: %02x:%04x (moveable)\n",
235 ordinal
++, pe
->seg_number
, pe
->offset
);
240 struct entry_tab_fixed_s
*pe
= (struct entry_tab_fixed_s
*)(pstr
+2);
241 for (i
= 0; i
< *pstr
; i
++, pe
++)
242 printf( "%d: %04x (fixed)\n",
243 ordinal
++, pe
->offset
[0] + (pe
->offset
[1] << 8) );
248 /* Dump the non-resident names table */
250 printf( "\nNon-resident names table:\n" );
251 if (pModule
->nrname_handle
)
253 pstr
= (char *)GlobalLock( pModule
->nrname_handle
);
256 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
257 *(WORD
*)(pstr
+ *pstr
+ 1) );
258 pstr
+= *pstr
+ 1 + sizeof(WORD
);
265 /***********************************************************************
268 int MODULE_OpenFile( HMODULE hModule
)
273 static int cachedfd
= -1;
275 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
276 dprintf_module( stddeb
, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
277 hModule
, hCachedModule
, cachedfd
);
278 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return -1;
279 if (hCachedModule
== hModule
) return cachedfd
;
281 hCachedModule
= hModule
;
282 name
= ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
;
283 cachedfd
= open( DOS_GetUnixFileName( name
), O_RDONLY
);
284 dprintf_module( stddeb
, "MODULE_OpenFile: opened '%s' -> %d\n",
290 /***********************************************************************
291 * MODULE_CreateSegments
293 static BOOL
MODULE_CreateSegments( HMODULE hModule
)
295 SEGTABLEENTRY
*pSegment
;
299 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
300 pSegment
= NE_SEG_TABLE( pModule
);
301 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
303 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
304 if (i
== pModule
->ss
) minsize
+= pModule
->stack_size
;
305 /* The DGROUP is allocated by MODULE_CreateInstance */
306 if (i
== pModule
->dgroup
) continue;
307 pSegment
->selector
= GLOBAL_Alloc( GMEM_ZEROINIT
| GMEM_FIXED
,
309 !(pSegment
->flags
& NE_SEGFLAGS_DATA
),
311 FALSE
/*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
312 if (!pSegment
->selector
) return FALSE
;
315 pModule
->dgroup_entry
= pModule
->dgroup
? pModule
->seg_table
+
316 (pModule
->dgroup
- 1) * sizeof(SEGTABLEENTRY
) : 0;
321 /***********************************************************************
324 static HINSTANCE
MODULE_GetInstance( HMODULE hModule
)
326 SEGTABLEENTRY
*pSegment
;
329 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
330 if (pModule
->dgroup
== 0) return hModule
;
332 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
334 return pSegment
->selector
;
338 /***********************************************************************
339 * MODULE_CreateInstance
341 static HINSTANCE
MODULE_CreateInstance( HMODULE hModule
, LOADPARAMS
*params
)
343 SEGTABLEENTRY
*pSegment
;
346 HINSTANCE hNewInstance
, hPrevInstance
;
348 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
349 if (pModule
->dgroup
== 0) return hModule
;
351 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
352 hPrevInstance
= pSegment
->selector
;
354 /* if it's a library, create a new instance only the first time */
357 if (pModule
->flags
& NE_FFLAGS_LIBMODULE
) return hPrevInstance
;
358 if (params
== (LOADPARAMS
*)-1) return hPrevInstance
;
361 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
362 if (pModule
->ss
== pModule
->dgroup
) minsize
+= pModule
->stack_size
;
363 minsize
+= pModule
->heap_size
;
364 hNewInstance
= GLOBAL_Alloc( GMEM_ZEROINIT
| GMEM_FIXED
,
365 minsize
, hModule
, FALSE
, FALSE
, FALSE
);
366 if (!hNewInstance
) return 0;
367 pSegment
->selector
= hNewInstance
;
372 /***********************************************************************
373 * MODULE_LoadExeHeader
375 HMODULE
MODULE_LoadExeHeader( int fd
, OFSTRUCT
*ofs
)
377 struct mz_header_s mz_header
;
378 struct ne_header_s ne_header
;
383 char *buffer
, *fastload
= NULL
;
384 int fastload_offset
= 0, fastload_length
= 0;
386 /* Read a block from either the file or the fast-load area. */
387 #define READ(offset,size,buffer) \
388 ((fastload && ((offset) >= fastload_offset) && \
389 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
390 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
391 (lseek( fd, mz_header.ne_offset+(offset), SEEK_SET), \
392 read( fd, (buffer), (size) ) == (size)))
394 lseek( fd
, 0, SEEK_SET
);
395 if ((read( fd
, &mz_header
, sizeof(mz_header
) ) != sizeof(mz_header
)) ||
396 (mz_header
.mz_magic
!= MZ_SIGNATURE
)) return 11; /* invalid exe */
398 lseek( fd
, mz_header
.ne_offset
, SEEK_SET
);
399 if (read( fd
, &ne_header
, sizeof(ne_header
) ) != sizeof(ne_header
))
400 return 11; /* invalid exe */
402 if (ne_header
.ne_magic
== PE_SIGNATURE
) return 21; /* win32 exe */
403 if (ne_header
.ne_magic
!= NE_SIGNATURE
) return 11; /* invalid exe */
405 /* We now have a valid NE header */
407 size
= sizeof(NE_MODULE
) +
408 /* loaded file info */
409 sizeof(LOADEDFILEINFO
) + strlen(ofs
->szPathName
) +
411 ne_header
.n_segment_tab
* sizeof(SEGTABLEENTRY
) +
413 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
+
414 /* resident names table */
415 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
+
416 /* module ref table */
417 ne_header
.n_mod_ref_tab
* sizeof(WORD
) +
418 /* imported names table */
419 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
+
420 /* entry table length */
421 ne_header
.entry_tab_length
;
423 hModule
= GlobalAlloc( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
424 if (!hModule
) return 11; /* invalid exe */
425 FarSetOwner( hModule
, hModule
);
426 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
427 memcpy( pModule
, &ne_header
, sizeof(NE_MODULE
) );
429 pData
= (BYTE
*)(pModule
+ 1);
431 /* Read the fast-load area */
433 if (ne_header
.additional_flags
& NE_AFLAGS_FASTLOAD
)
435 fastload_offset
=ne_header
.fastload_offset
<<ne_header
.align_shift_count
;
436 fastload_length
=ne_header
.fastload_length
<<ne_header
.align_shift_count
;
437 dprintf_module( stddeb
, "Using fast-load area offset=%x len=%d\n",
438 fastload_offset
, fastload_length
);
439 if ((fastload
= (char *)malloc( fastload_length
)) != NULL
)
441 lseek( fd
, mz_header
.ne_offset
+ fastload_offset
, SEEK_SET
);
442 if (read( fd
, fastload
, fastload_length
) != fastload_length
)
450 /* Store the filename information */
452 pModule
->fileinfo
= (int)pData
- (int)pModule
;
453 ((LOADEDFILEINFO
*)pData
)->length
= sizeof(LOADEDFILEINFO
)+strlen(ofs
->szPathName
);
454 ((LOADEDFILEINFO
*)pData
)->fixed_media
= TRUE
;
455 ((LOADEDFILEINFO
*)pData
)->error
= 0;
456 ((LOADEDFILEINFO
*)pData
)->date
= 0;
457 ((LOADEDFILEINFO
*)pData
)->time
= 0;
458 strcpy( ((LOADEDFILEINFO
*)pData
)->filename
, ofs
->szPathName
);
459 pData
+= ((LOADEDFILEINFO
*)pData
)->length
--;
461 /* Get the segment table */
463 pModule
->seg_table
= (int)pData
- (int)pModule
;
464 buffer
= malloc( ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
) );
468 struct ne_segment_table_entry_s
*pSeg
;
470 if (!READ( ne_header
.segment_tab_offset
,
471 ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
),
472 buffer
)) return 11; /* invalid exe */
473 pSeg
= (struct ne_segment_table_entry_s
*)buffer
;
474 for (i
= ne_header
.n_segment_tab
; i
> 0; i
--, pSeg
++)
476 memcpy( pData
, pSeg
, sizeof(*pSeg
) );
477 pData
+= sizeof(SEGTABLEENTRY
);
481 else return 11; /* invalid exe */
483 /* Get the resource table */
485 if (ne_header
.resource_tab_offset
< ne_header
.rname_tab_offset
)
487 pModule
->res_table
= (int)pData
- (int)pModule
;
488 if (!READ(ne_header
.resource_tab_offset
,
489 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
,
490 pData
)) return 11; /* invalid exe */
491 pData
+= ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
;
493 else pModule
->res_table
= 0; /* No resource table */
495 /* Get the resident names table */
497 pModule
->name_table
= (int)pData
- (int)pModule
;
498 if (!READ( ne_header
.rname_tab_offset
,
499 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
,
500 pData
)) return 11; /* invalid exe */
501 pData
+= ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
;
503 /* Get the module references table */
505 if (ne_header
.n_mod_ref_tab
> 0)
507 pModule
->modref_table
= (int)pData
- (int)pModule
;
508 if (!READ( ne_header
.moduleref_tab_offset
,
509 ne_header
.n_mod_ref_tab
* sizeof(WORD
),
510 pData
)) return 11; /* invalid exe */
511 pData
+= ne_header
.n_mod_ref_tab
* sizeof(WORD
);
513 else pModule
->modref_table
= 0; /* No module references */
515 /* Get the imported names table */
517 pModule
->import_table
= (int)pData
- (int)pModule
;
518 if (!READ( ne_header
.iname_tab_offset
,
519 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
,
520 pData
)) return 11; /* invalid exe */
521 pData
+= ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
;
523 /* Get the entry table */
525 pModule
->entry_table
= (int)pData
- (int)pModule
;
526 if (!READ( ne_header
.entry_tab_offset
,
527 ne_header
.entry_tab_length
,
528 pData
)) return 11; /* invalid exe */
529 pData
+= ne_header
.entry_tab_length
;
531 /* Get the non-resident names table */
533 if (ne_header
.nrname_tab_length
)
535 pModule
->nrname_handle
= GLOBAL_Alloc( 0, ne_header
.nrname_tab_length
,
536 hModule
, FALSE
, FALSE
, FALSE
);
537 if (!pModule
->nrname_handle
) return 11; /* invalid exe */
538 buffer
= GlobalLock( pModule
->nrname_handle
);
539 lseek( fd
, ne_header
.nrname_tab_offset
, SEEK_SET
);
540 if (read( fd
, buffer
, ne_header
.nrname_tab_length
)
541 != ne_header
.nrname_tab_length
) return 11; /* invalid exe */
543 else pModule
->nrname_handle
= 0;
545 /* Allocate a segment for the implicitly-loaded DLLs */
547 if (pModule
->modref_count
)
549 pModule
->dlls_to_init
= GLOBAL_Alloc(GMEM_ZEROINIT
,
550 (pModule
->modref_count
+1)*sizeof(HMODULE
),
551 hModule
, FALSE
, FALSE
, FALSE
);
552 if (!pModule
->dlls_to_init
) return 11; /* invalid exe */
554 else pModule
->dlls_to_init
= 0;
556 if (debugging_module
) MODULE_PrintModule( hModule
);
557 pModule
->next
= hFirstModule
;
558 hFirstModule
= hModule
;
563 /***********************************************************************
566 * Lookup the ordinal for a given name.
568 WORD
MODULE_GetOrdinal( HMODULE hModule
, char *name
)
570 char buffer
[256], *cpnt
;
574 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
576 dprintf_module( stddeb
, "MODULE_GetOrdinal(%04x,'%s')\n",
579 /* First handle names of the form '#xxxx' */
581 if (name
[0] == '#') return atoi( name
+ 1 );
583 /* Now copy and uppercase the string */
585 strcpy( buffer
, name
);
587 len
= strlen( buffer
);
589 /* First search the resident names */
591 cpnt
= (char *)pModule
+ pModule
->name_table
;
593 /* Skip the first entry (module name) */
594 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
597 dprintf_module( stddeb
, " Checking '%*.*s'\n", *cpnt
, *cpnt
, cpnt
+1 );
598 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
600 dprintf_module( stddeb
, " Found: ordinal=%d\n",
601 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
602 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
604 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
607 /* Now search the non-resident names table */
609 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
610 cpnt
= (char *)GlobalLock( pModule
->nrname_handle
);
612 /* Skip the first entry (module description string) */
613 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
616 dprintf_module( stddeb
, " Checking '%*.*s'\n", *cpnt
, *cpnt
, cpnt
+1 );
617 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
619 dprintf_module( stddeb
, " Found: ordinal=%d\n",
620 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
621 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
623 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
629 /***********************************************************************
630 * MODULE_GetEntryPoint
632 * Return the entry point for a given ordinal.
634 DWORD
MODULE_GetEntryPoint( HMODULE hModule
, WORD ordinal
)
641 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
643 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
644 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
646 /* Skipping this bundle */
650 case 0: p
+= 2; break; /* unused */
651 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
652 default: p
+= 2 + *p
* 3; break; /* fixed */
661 case 0xff: /* moveable */
662 p
+= 2 + 6 * (ordinal
- curOrdinal
);
664 offset
= *(WORD
*)(p
+ 4);
668 p
+= 2 + 3 * (ordinal
- curOrdinal
);
669 offset
= *(WORD
*)(p
+ 1);
673 if (sel
== 0xfe) sel
= 0xffff; /* constant entry */
674 else sel
= NE_SEG_TABLE(pModule
)[sel
-1].selector
;
675 return MAKELONG( offset
, sel
);
679 /***********************************************************************
680 * MODULE_SetEntryPoint
682 * Change the value of an entry point. Use with caution!
683 * It can only change the offset value, not the selector.
685 BOOL
MODULE_SetEntryPoint( HMODULE hModule
, WORD ordinal
, WORD offset
)
691 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
693 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
694 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
696 /* Skipping this bundle */
700 case 0: p
+= 2; break; /* unused */
701 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
702 default: p
+= 2 + *p
* 3; break; /* fixed */
705 if (!*p
) return FALSE
;
711 case 0xff: /* moveable */
712 p
+= 2 + 6 * (ordinal
- curOrdinal
);
713 *(WORD
*)(p
+ 4) = offset
;
716 p
+= 2 + 3 * (ordinal
- curOrdinal
);
717 *(WORD
*)(p
+ 1) = offset
;
724 /***********************************************************************
725 * MODULE_GetEntryPointName
727 * Return the entry point name for a given ordinal.
728 * Used only by relay debugging.
729 * Warning: returned pointer is to a Pascal-type string.
731 LPSTR
MODULE_GetEntryPointName( HMODULE hModule
, WORD ordinal
)
736 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
738 /* First search the resident names */
740 cpnt
= (char *)pModule
+ pModule
->name_table
;
743 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
744 if (*(WORD
*)(cpnt
+ *cpnt
+ 1) == ordinal
) return cpnt
;
747 /* Now search the non-resident names table */
749 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
750 cpnt
= (char *)GlobalLock( pModule
->nrname_handle
);
753 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
754 if (*(WORD
*)(cpnt
+ *cpnt
+ 1) == ordinal
) return cpnt
;
760 /***********************************************************************
761 * MODULE_GetModuleName
763 LPSTR
MODULE_GetModuleName( HMODULE hModule
)
767 static char buffer
[10];
769 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return NULL
;
770 p
= (BYTE
*)pModule
+ pModule
->name_table
;
772 memcpy( buffer
, p
+ 1, len
);
778 /**********************************************************************
781 * Find a module from a path name.
783 HMODULE
MODULE_FindModule( LPCSTR path
)
785 HMODULE hModule
= hFirstModule
;
786 LPCSTR filename
, dotptr
, modulepath
, modulename
;
787 BYTE len
, *name_table
;
789 if (!(filename
= strrchr( path
, '\\' ))) filename
= path
;
791 if ((dotptr
= strrchr( filename
, '.' )) != NULL
)
792 len
= (BYTE
)(dotptr
- filename
);
793 else len
= strlen( filename
);
797 NE_MODULE
*pModule
= (NE_MODULE
*)GlobalLock( hModule
);
799 modulepath
= ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
;
800 if (!(modulename
= strrchr( modulepath
, '\\' )))
801 modulename
= modulepath
;
803 if (!strcasecmp( modulename
, filename
)) return hModule
;
805 name_table
= (BYTE
*)pModule
+ pModule
->name_table
;
806 if ((*name_table
== len
) && !strncasecmp(filename
, name_table
+1, len
))
808 hModule
= pModule
->next
;
814 /**********************************************************************
817 * Remove a module from memory.
819 static void MODULE_FreeModule( HMODULE hModule
)
821 HMODULE
*hPrevModule
;
823 SEGTABLEENTRY
*pSegment
;
827 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return;
829 /* FIXME: should call the exit code for the library here */
831 /* Remove it from the linked list */
833 hPrevModule
= &hFirstModule
;
834 while (*hPrevModule
&& (*hPrevModule
!= hModule
))
836 hPrevModule
= &((NE_MODULE
*)GlobalLock( *hPrevModule
))->next
;
838 if (*hPrevModule
) *hPrevModule
= pModule
->next
;
840 /* Free all the segments */
842 pSegment
= NE_SEG_TABLE( pModule
);
843 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
845 GlobalFree( pSegment
->selector
);
848 /* Free the referenced modules */
850 pModRef
= NE_MODULE_TABLE( pModule
);
851 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
853 FreeModule( *pModRef
);
856 /* Free the module storage */
858 if (pModule
->nrname_handle
) GlobalFree( pModule
->nrname_handle
);
859 if (pModule
->dlls_to_init
) GlobalFree( pModule
->dlls_to_init
);
860 GlobalFree( hModule
);
862 /* Remove module from cache */
864 if (hCachedModule
== hModule
) hCachedModule
= 0;
868 /**********************************************************************
869 * LoadModule (KERNEL.45)
871 HINSTANCE
LoadModule( LPCSTR name
, LPVOID paramBlock
)
874 HANDLE hInstance
, hPrevInstance
;
876 LOADPARAMS
*params
= (LOADPARAMS
*)paramBlock
;
877 WORD
*pModRef
, *pDLLs
;
880 hModule
= MODULE_FindModule( name
);
881 if (!hModule
) /* We have to load the module */
884 if (strchr( name
, '/' )) name
= DOS_GetDosFileName( name
);
885 if ((fd
= OpenFile( name
, &ofs
, OF_READ
)) == -1)
886 return 2; /* File not found */
888 /* Create the module structure */
890 if ((hModule
= MODULE_LoadExeHeader( fd
, &ofs
)) < 32)
893 fprintf( stderr
, "LoadModule: can't load '%s', error=%d\n",
897 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
899 /* Allocate the segments for this module */
901 MODULE_CreateSegments( hModule
);
904 hInstance
= MODULE_CreateInstance( hModule
, (LOADPARAMS
*)paramBlock
);
906 /* Load the referenced DLLs */
908 pModRef
= (WORD
*)((char *)pModule
+ pModule
->modref_table
);
909 pDLLs
= (WORD
*)GlobalLock( pModule
->dlls_to_init
);
910 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
913 BYTE
*pstr
= (BYTE
*)pModule
+ pModule
->import_table
+ *pModRef
;
914 memcpy( buffer
, pstr
+ 1, *pstr
);
915 strcpy( buffer
+ *pstr
, ".dll" );
916 dprintf_module( stddeb
, "Loading '%s'\n", buffer
);
917 if (!(*pModRef
= MODULE_FindModule( buffer
)))
919 /* If the DLL is not loaded yet, load it and store */
920 /* its handle in the list of DLLs to initialize. */
923 if ((hDLL
= LoadModule( buffer
, (LPVOID
)-1 )) == 2) /* file not found */
927 /* Try with prepending the path of the current module */
928 GetModuleFileName( hModule
, buffer
, 256 );
929 if (!(p
= strrchr( buffer
, '\\' ))) p
= buffer
;
930 memcpy( p
+ 1, pstr
+ 1, *pstr
);
931 strcpy( p
+ 1 + *pstr
, ".dll" );
932 hDLL
= LoadModule( buffer
, (LPVOID
)-1 );
936 fprintf( stderr
, "Could not load '%s' required by '%s', error = %d\n",
937 buffer
, name
, hDLL
);
938 return 2; /* file not found */
940 *pModRef
= GetExePtr( hDLL
);
943 else /* Increment the reference count of the DLL */
945 NE_MODULE
*pOldDLL
= (NE_MODULE
*)GlobalLock( *pModRef
);
946 if (pOldDLL
) pOldDLL
->count
++;
950 /* Load the segments */
952 for (i
= 1; i
<= pModule
->seg_count
; i
++) NE_LoadSegment( hModule
, i
);
954 /* Fixup the functions prologs */
956 NE_FixupPrologs( hModule
);
958 /* Make sure the usage count is 1 on the first loading of */
959 /* the module, even if it contains circular DLL references */
965 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
966 hPrevInstance
= MODULE_GetInstance( hModule
);
967 hInstance
= MODULE_CreateInstance( hModule
, params
);
968 if (hInstance
!= hPrevInstance
) /* not a library */
969 NE_LoadSegment( hModule
, pModule
->dgroup
);
973 /* Create a task for this instance */
975 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
) && (paramBlock
!= (LPVOID
)-1))
977 TASK_CreateTask( hModule
, hInstance
, hPrevInstance
,
978 params
->hEnvironment
,
979 (LPSTR
)PTR_SEG_TO_LIN( params
->cmdLine
),
980 *((WORD
*)PTR_SEG_TO_LIN(params
->showCmd
)+1) );
987 /**********************************************************************
988 * FreeModule (KERNEL.46)
990 BOOL
FreeModule( HANDLE hModule
)
994 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
995 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
997 dprintf_module( stddeb
, "FreeModule: %s count %d\n",
998 MODULE_GetModuleName(hModule
), pModule
->count
);
999 if (--pModule
->count
== 0) MODULE_FreeModule( hModule
);
1004 /**********************************************************************
1005 * GetModuleHandle (KERNEL.47)
1007 HMODULE
WIN16_GetModuleHandle( SEGPTR name
)
1009 if (HIWORD(name
) == 0) return GetExePtr( LOWORD(name
) );
1010 return MODULE_FindModule( PTR_SEG_TO_LIN(name
) );
1013 HMODULE
GetModuleHandle( LPCSTR name
)
1015 return MODULE_FindModule( name
);
1019 /**********************************************************************
1020 * GetModuleUsage (KERNEL.48)
1022 int GetModuleUsage( HANDLE hModule
)
1026 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1027 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
1028 dprintf_module( stddeb
, "GetModuleUsage(%04x): returning %d\n",
1029 hModule
, pModule
->count
);
1030 return pModule
->count
;
1034 /**********************************************************************
1035 * GetModuleFileName (KERNEL.49)
1037 int GetModuleFileName( HANDLE hModule
, LPSTR lpFileName
, short nSize
)
1042 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1043 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
1044 name
= ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
;
1045 strncpy( lpFileName
, name
, nSize
);
1046 lpFileName
[nSize
-1] = '\0';
1047 dprintf_module( stddeb
, "GetModuleFilename: %s\n", lpFileName
);
1048 return strlen(lpFileName
);
1052 /***********************************************************************
1053 * LoadLibrary (KERNEL.95)
1055 HANDLE
LoadLibrary( LPCSTR libname
)
1059 dprintf_module( stddeb
, "LoadLibrary: (%08x) %s\n", (int)libname
, libname
);
1060 /* This does not increment the module reference count, and will
1061 * therefore cause crashes on FreeLibrary calls.
1062 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1064 handle
= LoadModule( libname
, (LPVOID
)-1 );
1065 if (handle
== 2) /* file not found */
1068 strcpy( buffer
, libname
);
1069 strcat( buffer
, ".dll" );
1070 handle
= LoadModule( buffer
, (LPVOID
)-1 );
1072 if (handle
>= 32) NE_InitializeDLLs( GetExePtr(handle
) );
1077 /***********************************************************************
1078 * FreeLibrary (KERNEL.96)
1080 void FreeLibrary( HANDLE handle
)
1082 dprintf_module( stddeb
,"FreeLibrary: %04x\n", handle
);
1083 FreeModule( handle
);
1087 /***********************************************************************
1088 * WinExec (KERNEL.166)
1090 HANDLE
WinExec( LPSTR lpCmdLine
, WORD nCmdShow
)
1093 HLOCAL cmdShowHandle
, cmdLineHandle
;
1096 char *p
, *cmdline
, filename
[256];
1098 if (!(cmdShowHandle
= GlobalAlloc( 0, 2 * sizeof(WORD
) ))) return 0;
1099 if (!(cmdLineHandle
= GlobalAlloc( 0, 256 ))) return 0;
1101 /* Store nCmdShow */
1103 cmdShowPtr
= (WORD
*)GlobalLock( cmdShowHandle
);
1105 cmdShowPtr
[1] = nCmdShow
;
1107 /* Build the filename and command-line */
1109 cmdline
= (char *)GlobalLock( cmdLineHandle
);
1110 strncpy( filename
, lpCmdLine
, 256 );
1111 filename
[255] = '\0';
1112 for (p
= filename
; *p
&& (*p
!= ' ') && (*p
!= '\t'); p
++);
1115 strncpy( cmdline
, p
+ 1, 128 );
1116 cmdline
[127] = '\0';
1118 else cmdline
[0] = '\0';
1121 /* Now load the executable file */
1123 params
.hEnvironment
= SELECTOROF( GetDOSEnvironment() );
1124 params
.cmdLine
= WIN16_GlobalLock( cmdLineHandle
);
1125 params
.showCmd
= WIN16_GlobalLock( cmdShowHandle
);
1126 params
.reserved
= 0;
1127 handle
= LoadModule( filename
, ¶ms
);
1128 if (handle
== 2) /* file not found */
1130 strcat( filename
, ".exe" );
1131 handle
= LoadModule( filename
, ¶ms
);
1134 GlobalFree( cmdShowHandle
);
1135 GlobalFree( cmdLineHandle
);
1140 /***********************************************************************
1141 * GetProcAddress (KERNEL.50)
1143 FARPROC
GetProcAddress( HANDLE hModule
, SEGPTR name
)
1148 if (!hModule
) hModule
= GetCurrentTask();
1149 hModule
= GetExePtr( hModule
);
1151 if (HIWORD(name
) != 0)
1153 ordinal
= MODULE_GetOrdinal( hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1154 dprintf_module( stddeb
, "GetProcAddress: %04x '%s'\n",
1155 hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1159 ordinal
= LOWORD(name
);
1160 dprintf_module( stddeb
, "GetProcAddress: %04x %04x\n",
1163 if (!ordinal
) return (FARPROC
)0;
1165 ret
= MODULE_GetEntryPoint( hModule
, ordinal
);
1167 dprintf_module( stddeb
, "GetProcAddress: returning %08lx\n", ret
);
1168 return (FARPROC
)ret
;
1172 /**********************************************************************
1173 * ModuleFirst (TOOLHELP.59)
1175 BOOL
ModuleFirst( MODULEENTRY
*lpme
)
1177 lpme
->wNext
= hFirstModule
;
1178 return ModuleNext( lpme
);
1182 /**********************************************************************
1183 * ModuleNext (TOOLHELP.60)
1185 BOOL
ModuleNext( MODULEENTRY
*lpme
)
1189 if (!lpme
->wNext
) return FALSE
;
1190 if (!(pModule
= (NE_MODULE
*)GlobalLock( lpme
->wNext
))) return FALSE
;
1191 strncpy( lpme
->szModule
, (char *)pModule
+ pModule
->name_table
,
1193 lpme
->szModule
[MAX_MODULE_NAME
] = '\0';
1194 lpme
->hModule
= lpme
->wNext
;
1195 lpme
->wcUsage
= pModule
->count
;
1196 strncpy( lpme
->szExePath
,
1197 ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
,
1199 lpme
->szExePath
[MAX_PATH
] = '\0';
1200 lpme
->wNext
= pModule
->next
;
1205 /**********************************************************************
1206 * ModuleFindName (TOOLHELP.61)
1208 BOOL
ModuleFindName( MODULEENTRY
*lpme
, LPCSTR name
)
1210 lpme
->wNext
= GetModuleHandle( name
);
1211 return ModuleNext( lpme
);
1215 /**********************************************************************
1216 * ModuleFindHandle (TOOLHELP.62)
1218 BOOL
ModuleFindHandle( MODULEENTRY
*lpme
, HMODULE hModule
)
1220 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1221 lpme
->wNext
= hModule
;
1222 return ModuleNext( lpme
);