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)
40 SEGTABLEENTRY
*pSegTable
;
41 struct dll_table_s
*table
;
45 /* Create the built-in modules */
47 for (i
= 0, table
= dll_builtin_table
; i
< N_BUILTINS
; i
++, table
++)
49 if (!table
->used
) continue;
51 hModule
= GLOBAL_CreateBlock( GMEM_MOVEABLE
, table
->module_start
,
52 table
->module_end
- table
->module_start
,
53 0, FALSE
, FALSE
, FALSE
, NULL
);
54 if (!hModule
) return FALSE
;
55 FarSetOwner( hModule
, hModule
);
57 table
->hModule
= hModule
;
59 dprintf_module( stddeb
, "Built-in %s: hmodule=%04x\n",
60 table
->name
, hModule
);
62 /* Allocate the code segment */
64 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
65 pSegTable
= NE_SEG_TABLE( pModule
);
67 pSegTable
->selector
= GLOBAL_CreateBlock(GMEM_FIXED
, table
->code_start
,
68 pSegTable
->minsize
, hModule
,
69 TRUE
, TRUE
, FALSE
, NULL
);
70 if (!pSegTable
->selector
) return FALSE
;
73 /* Allocate the data segment */
75 pSegTable
->selector
= GLOBAL_Alloc( GMEM_FIXED
, pSegTable
->minsize
,
76 hModule
, FALSE
, FALSE
, FALSE
);
77 if (!pSegTable
->selector
) return FALSE
;
78 memcpy( GlobalLock( pSegTable
->selector
), table
->data_start
,
81 pModule
->next
= hFirstModule
;
82 hFirstModule
= hModule
;
85 /* Initialize some KERNEL exported values */
87 if (!(hModule
= GetModuleHandle( "KERNEL" ))) return TRUE
;
89 /* KERNEL.178: __WINFLAGS */
90 MODULE_SetEntryPoint( hModule
, 178, GetWinFlags() );
92 /* Allocate 7 64k segments for 0000, A000, B000, C000, D000, E000, F000. */
94 dosmem
= malloc( 0x70000 );
96 MODULE_SetEntryPoint( hModule
, 183, /* KERNEL.183: __0000H */
97 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
,
98 0x10000, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
99 MODULE_SetEntryPoint( hModule
, 193, /* KERNEL.193: __0040H */
100 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
+ 0x400,
101 0x100, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
102 MODULE_SetEntryPoint( hModule
, 174, /* KERNEL.174: __A000H */
103 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
+ 0x10000,
104 0x10000, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
105 MODULE_SetEntryPoint( hModule
, 181, /* KERNEL.181: __B000H */
106 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
+ 0x20000,
107 0x10000, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
108 MODULE_SetEntryPoint( hModule
, 182, /* KERNEL.182: __B800H */
109 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
+ 0x28000,
110 0x10000, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
111 MODULE_SetEntryPoint( hModule
, 195, /* KERNEL.195: __C000H */
112 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
+ 0x30000,
113 0x10000, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
114 MODULE_SetEntryPoint( hModule
, 179, /* KERNEL.179: __D000H */
115 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
+ 0x40000,
116 0x10000, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
117 MODULE_SetEntryPoint( hModule
, 190, /* KERNEL.190: __E000H */
118 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
+ 0x50000,
119 0x10000, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
120 MODULE_SetEntryPoint( hModule
, 173, /* KERNEL.173: __ROMBIOS */
121 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
+ 0x60000,
122 0x10000, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
123 MODULE_SetEntryPoint( hModule
, 194, /* KERNEL.194: __F000H */
124 GLOBAL_CreateBlock( GMEM_FIXED
, dosmem
+ 0x60000,
125 0x10000, hModule
, FALSE
, FALSE
, FALSE
, NULL
));
130 /***********************************************************************
133 void MODULE_PrintModule( HMODULE hmodule
)
139 NE_MODULE
*pModule
= (NE_MODULE
*)GlobalLock( hmodule
);
141 /* Dump the module info */
143 printf( "Module %04x:\n", hmodule
);
144 printf( "count=%d flags=%04x heap=%d stack=%d\n",
145 pModule
->count
, pModule
->flags
,
146 pModule
->heap_size
, pModule
->stack_size
);
147 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
148 pModule
->cs
, pModule
->ip
, pModule
->ss
, pModule
->sp
, pModule
->dgroup
,
149 pModule
->seg_count
, pModule
->modref_count
);
150 printf( "os_flags=%d swap_area=%d version=%04x\n",
151 pModule
->os_flags
, pModule
->min_swap_area
,
152 pModule
->expected_version
);
154 /* Dump the file info */
156 printf( "Filename: '%s'\n",
157 ((LOADEDFILEINFO
*)((BYTE
*)pModule
+ pModule
->fileinfo
))->filename
);
159 /* Dump the segment table */
161 printf( "\nSegment table:\n" );
162 pSeg
= NE_SEG_TABLE( pModule
);
163 for (i
= 0; i
< pModule
->seg_count
; i
++, pSeg
++)
164 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
165 i
+ 1, pSeg
->filepos
, pSeg
->size
, pSeg
->flags
,
166 pSeg
->minsize
, pSeg
->selector
);
168 /* Dump the resource table */
170 printf( "\nResource table:\n" );
171 if (pModule
->res_table
)
173 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->res_table
);
174 printf( "Alignment: %d\n", *pword
++ );
177 struct resource_typeinfo_s
*ptr
= (struct resource_typeinfo_s
*)pword
;
178 struct resource_nameinfo_s
*pname
= (struct resource_nameinfo_s
*)(ptr
+ 1);
179 printf( "id=%04x count=%d\n", ptr
->type_id
, ptr
->count
);
180 for (i
= 0; i
< ptr
->count
; i
++, pname
++)
181 printf( "offset=%d len=%d id=%04x\n",
182 pname
->offset
, pname
->length
, pname
->id
);
183 pword
= (WORD
*)pname
;
186 else printf( "None\n" );
188 /* Dump the resident name table */
190 printf( "\nResident-name table:\n" );
191 pstr
= (char *)pModule
+ pModule
->name_table
;
194 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
195 *(WORD
*)(pstr
+ *pstr
+ 1) );
196 pstr
+= *pstr
+ 1 + sizeof(WORD
);
199 /* Dump the module reference table */
201 printf( "\nModule ref table:\n" );
202 if (pModule
->modref_table
)
204 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->modref_table
);
205 for (i
= 0; i
< pModule
->modref_count
; i
++, pword
++)
207 char *name
= (char *)pModule
+ pModule
->import_table
+ *pword
;
208 printf( "%d: %04x -> '%*.*s'\n",
209 i
, *pword
, *name
, *name
, name
+ 1 );
212 else printf( "None\n" );
214 /* Dump the entry table */
216 printf( "\nEntry table:\n" );
217 pstr
= (char *)pModule
+ pModule
->entry_table
;
221 printf( "Bundle %d-%d: %02x\n", ordinal
, ordinal
+ *pstr
- 1, pstr
[1]);
227 else if ((BYTE
)pstr
[1] == 0xff) /* moveable */
229 struct entry_tab_movable_s
*pe
= (struct entry_tab_movable_s
*)(pstr
+2);
230 for (i
= 0; i
< *pstr
; i
++, pe
++)
231 printf( "%d: %02x:%04x (moveable)\n",
232 ordinal
++, pe
->seg_number
, pe
->offset
);
237 struct entry_tab_fixed_s
*pe
= (struct entry_tab_fixed_s
*)(pstr
+2);
238 for (i
= 0; i
< *pstr
; i
++, pe
++)
239 printf( "%d: %04x (fixed)\n",
240 ordinal
++, pe
->offset
[0] + (pe
->offset
[1] << 8) );
245 /* Dump the non-resident names table */
247 printf( "\nNon-resident names table:\n" );
248 if (pModule
->nrname_handle
)
250 pstr
= (char *)GlobalLock( pModule
->nrname_handle
);
253 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
254 *(WORD
*)(pstr
+ *pstr
+ 1) );
255 pstr
+= *pstr
+ 1 + sizeof(WORD
);
262 /***********************************************************************
265 int MODULE_OpenFile( HMODULE hModule
)
270 static int cachedfd
= -1;
272 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
273 dprintf_module( stddeb
, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
274 hModule
, hCachedModule
, cachedfd
);
275 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return -1;
276 if (hCachedModule
== hModule
) return cachedfd
;
278 hCachedModule
= hModule
;
279 name
= ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
;
280 cachedfd
= open( DOS_GetUnixFileName( name
), O_RDONLY
);
281 dprintf_module( stddeb
, "MODULE_OpenFile: opened '%s' -> %d\n",
287 /***********************************************************************
288 * MODULE_CreateSegments
290 static BOOL
MODULE_CreateSegments( HMODULE hModule
)
292 SEGTABLEENTRY
*pSegment
;
296 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
297 pSegment
= NE_SEG_TABLE( pModule
);
298 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
300 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
301 if (i
== pModule
->ss
) minsize
+= pModule
->stack_size
;
302 /* The DGROUP is allocated by MODULE_CreateInstance */
303 if (i
== pModule
->dgroup
) continue;
304 pSegment
->selector
= GLOBAL_Alloc( GMEM_ZEROINIT
| GMEM_FIXED
,
306 !(pSegment
->flags
& NE_SEGFLAGS_DATA
),
308 FALSE
/*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
309 if (!pSegment
->selector
) return FALSE
;
312 pModule
->dgroup_entry
= pModule
->dgroup
? pModule
->seg_table
+
313 (pModule
->dgroup
- 1) * sizeof(SEGTABLEENTRY
) : 0;
318 /***********************************************************************
321 static HINSTANCE
MODULE_GetInstance( HMODULE hModule
)
323 SEGTABLEENTRY
*pSegment
;
326 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
327 if (pModule
->dgroup
== 0) return hModule
;
329 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
331 return pSegment
->selector
;
335 /***********************************************************************
336 * MODULE_CreateInstance
338 static HINSTANCE
MODULE_CreateInstance( HMODULE hModule
, LOADPARAMS
*params
)
340 SEGTABLEENTRY
*pSegment
;
343 HINSTANCE hNewInstance
, hPrevInstance
;
345 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
346 if (pModule
->dgroup
== 0) return hModule
;
348 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
349 hPrevInstance
= pSegment
->selector
;
351 /* if it's a library, create a new instance only the first time */
354 if (pModule
->flags
& NE_FFLAGS_LIBMODULE
) return hPrevInstance
;
355 if (params
== (LOADPARAMS
*)-1) return hPrevInstance
;
358 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
359 if (pModule
->ss
== pModule
->dgroup
) minsize
+= pModule
->stack_size
;
360 minsize
+= pModule
->heap_size
;
361 hNewInstance
= GLOBAL_Alloc( GMEM_ZEROINIT
| GMEM_FIXED
,
362 minsize
, hModule
, FALSE
, FALSE
, FALSE
);
363 if (!hNewInstance
) return 0;
364 pSegment
->selector
= hNewInstance
;
369 /***********************************************************************
370 * MODULE_LoadExeHeader
372 HMODULE
MODULE_LoadExeHeader( int fd
, OFSTRUCT
*ofs
)
374 struct mz_header_s mz_header
;
375 struct ne_header_s ne_header
;
380 char *buffer
, *fastload
= NULL
;
381 int fastload_offset
= 0, fastload_length
= 0;
383 /* Read a block from either the file or the fast-load area. */
384 #define READ(offset,size,buffer) \
385 ((fastload && ((offset) >= fastload_offset) && \
386 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
387 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
388 (lseek( fd, mz_header.ne_offset+(offset), SEEK_SET), \
389 read( fd, (buffer), (size) ) == (size)))
391 lseek( fd
, 0, SEEK_SET
);
392 if ((read( fd
, &mz_header
, sizeof(mz_header
) ) != sizeof(mz_header
)) ||
393 (mz_header
.mz_magic
!= MZ_SIGNATURE
)) return 11; /* invalid exe */
395 lseek( fd
, mz_header
.ne_offset
, SEEK_SET
);
396 if (read( fd
, &ne_header
, sizeof(ne_header
) ) != sizeof(ne_header
))
397 return 11; /* invalid exe */
399 if (ne_header
.ne_magic
== PE_SIGNATURE
) return 21; /* win32 exe */
400 if (ne_header
.ne_magic
!= NE_SIGNATURE
) return 11; /* invalid exe */
402 /* We now have a valid NE header */
404 size
= sizeof(NE_MODULE
) +
405 /* loaded file info */
406 sizeof(LOADEDFILEINFO
) + strlen(ofs
->szPathName
) +
408 ne_header
.n_segment_tab
* sizeof(SEGTABLEENTRY
) +
410 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
+
411 /* resident names table */
412 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
+
413 /* module ref table */
414 ne_header
.n_mod_ref_tab
* sizeof(WORD
) +
415 /* imported names table */
416 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
+
417 /* entry table length */
418 ne_header
.entry_tab_length
;
420 hModule
= GlobalAlloc( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
421 if (!hModule
) return 11; /* invalid exe */
422 FarSetOwner( hModule
, hModule
);
423 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
424 memcpy( pModule
, &ne_header
, sizeof(NE_MODULE
) );
426 pData
= (BYTE
*)(pModule
+ 1);
428 /* Read the fast-load area */
430 if (ne_header
.additional_flags
& NE_AFLAGS_FASTLOAD
)
432 fastload_offset
=ne_header
.fastload_offset
<<ne_header
.align_shift_count
;
433 fastload_length
=ne_header
.fastload_length
<<ne_header
.align_shift_count
;
434 dprintf_module( stddeb
, "Using fast-load area offset=%x len=%d\n",
435 fastload_offset
, fastload_length
);
436 if ((fastload
= (char *)malloc( fastload_length
)) != NULL
)
438 lseek( fd
, mz_header
.ne_offset
+ fastload_offset
, SEEK_SET
);
439 if (read( fd
, fastload
, fastload_length
) != fastload_length
)
447 /* Store the filename information */
449 pModule
->fileinfo
= (int)pData
- (int)pModule
;
450 ((LOADEDFILEINFO
*)pData
)->length
= sizeof(LOADEDFILEINFO
)+strlen(ofs
->szPathName
);
451 ((LOADEDFILEINFO
*)pData
)->fixed_media
= TRUE
;
452 ((LOADEDFILEINFO
*)pData
)->error
= 0;
453 ((LOADEDFILEINFO
*)pData
)->date
= 0;
454 ((LOADEDFILEINFO
*)pData
)->time
= 0;
455 strcpy( ((LOADEDFILEINFO
*)pData
)->filename
, ofs
->szPathName
);
456 pData
+= ((LOADEDFILEINFO
*)pData
)->length
--;
458 /* Get the segment table */
460 pModule
->seg_table
= (int)pData
- (int)pModule
;
461 buffer
= malloc( ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
) );
465 struct ne_segment_table_entry_s
*pSeg
;
467 if (!READ( ne_header
.segment_tab_offset
,
468 ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
),
469 buffer
)) return 11; /* invalid exe */
470 pSeg
= (struct ne_segment_table_entry_s
*)buffer
;
471 for (i
= ne_header
.n_segment_tab
; i
> 0; i
--, pSeg
++)
473 memcpy( pData
, pSeg
, sizeof(*pSeg
) );
474 pData
+= sizeof(SEGTABLEENTRY
);
478 else return 11; /* invalid exe */
480 /* Get the resource table */
482 if (ne_header
.resource_tab_offset
< ne_header
.rname_tab_offset
)
484 pModule
->res_table
= (int)pData
- (int)pModule
;
485 if (!READ(ne_header
.resource_tab_offset
,
486 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
,
487 pData
)) return 11; /* invalid exe */
488 pData
+= ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
;
490 else pModule
->res_table
= 0; /* No resource table */
492 /* Get the resident names table */
494 pModule
->name_table
= (int)pData
- (int)pModule
;
495 if (!READ( ne_header
.rname_tab_offset
,
496 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
,
497 pData
)) return 11; /* invalid exe */
498 pData
+= ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
;
500 /* Get the module references table */
502 if (ne_header
.n_mod_ref_tab
> 0)
504 pModule
->modref_table
= (int)pData
- (int)pModule
;
505 if (!READ( ne_header
.moduleref_tab_offset
,
506 ne_header
.n_mod_ref_tab
* sizeof(WORD
),
507 pData
)) return 11; /* invalid exe */
508 pData
+= ne_header
.n_mod_ref_tab
* sizeof(WORD
);
510 else pModule
->modref_table
= 0; /* No module references */
512 /* Get the imported names table */
514 pModule
->import_table
= (int)pData
- (int)pModule
;
515 if (!READ( ne_header
.iname_tab_offset
,
516 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
,
517 pData
)) return 11; /* invalid exe */
518 pData
+= ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
;
520 /* Get the entry table */
522 pModule
->entry_table
= (int)pData
- (int)pModule
;
523 if (!READ( ne_header
.entry_tab_offset
,
524 ne_header
.entry_tab_length
,
525 pData
)) return 11; /* invalid exe */
526 pData
+= ne_header
.entry_tab_length
;
528 /* Get the non-resident names table */
530 if (ne_header
.nrname_tab_length
)
532 pModule
->nrname_handle
= GLOBAL_Alloc( 0, ne_header
.nrname_tab_length
,
533 hModule
, FALSE
, FALSE
, FALSE
);
534 if (!pModule
->nrname_handle
) return 11; /* invalid exe */
535 buffer
= GlobalLock( pModule
->nrname_handle
);
536 lseek( fd
, ne_header
.nrname_tab_offset
, SEEK_SET
);
537 if (read( fd
, buffer
, ne_header
.nrname_tab_length
)
538 != ne_header
.nrname_tab_length
) return 11; /* invalid exe */
540 else pModule
->nrname_handle
= 0;
542 /* Allocate a segment for the implicitly-loaded DLLs */
544 if (pModule
->modref_count
)
546 pModule
->dlls_to_init
= GLOBAL_Alloc(GMEM_ZEROINIT
,
547 (pModule
->modref_count
+1)*sizeof(HMODULE
),
548 hModule
, FALSE
, FALSE
, FALSE
);
549 if (!pModule
->dlls_to_init
) return 11; /* invalid exe */
551 else pModule
->dlls_to_init
= 0;
553 if (debugging_module
) MODULE_PrintModule( hModule
);
554 pModule
->next
= hFirstModule
;
555 hFirstModule
= hModule
;
560 /***********************************************************************
563 * Lookup the ordinal for a given name.
565 WORD
MODULE_GetOrdinal( HMODULE hModule
, char *name
)
567 char buffer
[256], *cpnt
;
571 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
573 dprintf_module( stddeb
, "MODULE_GetOrdinal(%04x,'%s')\n",
576 /* First handle names of the form '#xxxx' */
578 if (name
[0] == '#') return atoi( name
+ 1 );
580 /* Now copy and uppercase the string */
582 strcpy( buffer
, name
);
584 len
= strlen( buffer
);
586 /* First search the resident names */
588 cpnt
= (char *)pModule
+ pModule
->name_table
;
590 /* Skip the first entry (module name) */
591 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
594 dprintf_module( stddeb
, " Checking '%*.*s'\n", *cpnt
, *cpnt
, cpnt
+1 );
595 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
597 dprintf_module( stddeb
, " Found: ordinal=%d\n",
598 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
599 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
601 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
604 /* Now search the non-resident names table */
606 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
607 cpnt
= (char *)GlobalLock( pModule
->nrname_handle
);
609 /* Skip the first entry (module description string) */
610 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
613 dprintf_module( stddeb
, " Checking '%*.*s'\n", *cpnt
, *cpnt
, cpnt
+1 );
614 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
616 dprintf_module( stddeb
, " Found: ordinal=%d\n",
617 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
618 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
620 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
626 /***********************************************************************
627 * MODULE_GetEntryPoint
629 * Return the entry point for a given ordinal.
631 DWORD
MODULE_GetEntryPoint( HMODULE hModule
, WORD ordinal
)
638 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
640 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
641 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
643 /* Skipping this bundle */
647 case 0: p
+= 2; break; /* unused */
648 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
649 default: p
+= 2 + *p
* 3; break; /* fixed */
658 case 0xff: /* moveable */
659 p
+= 2 + 6 * (ordinal
- curOrdinal
);
661 offset
= *(WORD
*)(p
+ 4);
665 p
+= 2 + 3 * (ordinal
- curOrdinal
);
666 offset
= *(WORD
*)(p
+ 1);
670 if (sel
== 0xfe) sel
= 0xffff; /* constant entry */
671 else sel
= NE_SEG_TABLE(pModule
)[sel
-1].selector
;
672 return MAKELONG( offset
, sel
);
676 /***********************************************************************
677 * MODULE_SetEntryPoint
679 * Change the value of an entry point. Use with caution!
680 * It can only change the offset value, not the selector.
682 BOOL
MODULE_SetEntryPoint( HMODULE hModule
, WORD ordinal
, WORD offset
)
688 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
690 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
691 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
693 /* Skipping this bundle */
697 case 0: p
+= 2; break; /* unused */
698 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
699 default: p
+= 2 + *p
* 3; break; /* fixed */
702 if (!*p
) return FALSE
;
708 case 0xff: /* moveable */
709 p
+= 2 + 6 * (ordinal
- curOrdinal
);
710 *(WORD
*)(p
+ 4) = offset
;
713 p
+= 2 + 3 * (ordinal
- curOrdinal
);
714 *(WORD
*)(p
+ 1) = offset
;
721 /***********************************************************************
722 * MODULE_GetEntryPointName
724 * Return the entry point name for a given ordinal.
725 * Used only by relay debugging.
726 * Warning: returned pointer is to a Pascal-type string.
728 LPSTR
MODULE_GetEntryPointName( HMODULE hModule
, WORD ordinal
)
733 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
735 /* First search the resident names */
737 cpnt
= (char *)pModule
+ pModule
->name_table
;
740 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
741 if (*(WORD
*)(cpnt
+ *cpnt
+ 1) == ordinal
) return cpnt
;
744 /* Now search the non-resident names table */
746 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
747 cpnt
= (char *)GlobalLock( pModule
->nrname_handle
);
750 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
751 if (*(WORD
*)(cpnt
+ *cpnt
+ 1) == ordinal
) return cpnt
;
757 /***********************************************************************
758 * MODULE_GetModuleName
760 LPSTR
MODULE_GetModuleName( HMODULE hModule
)
764 static char buffer
[10];
766 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return NULL
;
767 p
= (BYTE
*)pModule
+ pModule
->name_table
;
769 memcpy( buffer
, p
+ 1, len
);
775 /**********************************************************************
778 * Find a module from a path name.
780 HMODULE
MODULE_FindModule( LPCSTR path
)
782 HMODULE hModule
= hFirstModule
;
783 LPCSTR filename
, dotptr
, modulepath
, modulename
;
784 BYTE len
, *name_table
;
786 if (!(filename
= strrchr( path
, '\\' ))) filename
= path
;
788 if ((dotptr
= strrchr( filename
, '.' )) != NULL
)
789 len
= (BYTE
)(dotptr
- filename
);
790 else len
= strlen( filename
);
794 NE_MODULE
*pModule
= (NE_MODULE
*)GlobalLock( hModule
);
796 modulepath
= ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
;
797 if (!(modulename
= strrchr( modulepath
, '\\' )))
798 modulename
= modulepath
;
800 if (!strcasecmp( modulename
, filename
)) return hModule
;
802 name_table
= (BYTE
*)pModule
+ pModule
->name_table
;
803 if ((*name_table
== len
) && !strncasecmp(filename
, name_table
+1, len
))
805 hModule
= pModule
->next
;
811 /**********************************************************************
814 * Remove a module from memory.
816 static void MODULE_FreeModule( HMODULE hModule
)
818 HMODULE
*hPrevModule
;
820 SEGTABLEENTRY
*pSegment
;
824 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return;
826 /* FIXME: should call the exit code for the library here */
828 /* Remove it from the linked list */
830 hPrevModule
= &hFirstModule
;
831 while (*hPrevModule
&& (*hPrevModule
!= hModule
))
833 hPrevModule
= &((NE_MODULE
*)GlobalLock( *hPrevModule
))->next
;
835 if (*hPrevModule
) *hPrevModule
= pModule
->next
;
837 /* Free all the segments */
839 pSegment
= NE_SEG_TABLE( pModule
);
840 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
842 GlobalFree( pSegment
->selector
);
845 /* Free the referenced modules */
847 pModRef
= NE_MODULE_TABLE( pModule
);
848 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
850 FreeModule( *pModRef
);
853 /* Free the module storage */
855 if (pModule
->nrname_handle
) GlobalFree( pModule
->nrname_handle
);
856 if (pModule
->dlls_to_init
) GlobalFree( pModule
->dlls_to_init
);
857 GlobalFree( hModule
);
859 /* Remove module from cache */
861 if (hCachedModule
== hModule
) hCachedModule
= 0;
865 /**********************************************************************
866 * LoadModule (KERNEL.45)
868 HINSTANCE
LoadModule( LPCSTR name
, LPVOID paramBlock
)
871 HANDLE hInstance
, hPrevInstance
;
873 LOADPARAMS
*params
= (LOADPARAMS
*)paramBlock
;
874 WORD
*pModRef
, *pDLLs
;
877 hModule
= MODULE_FindModule( name
);
878 if (!hModule
) /* We have to load the module */
881 if (strchr( name
, '/' )) name
= DOS_GetDosFileName( name
);
882 if ((fd
= OpenFile( name
, &ofs
, OF_READ
)) == -1)
883 return 2; /* File not found */
885 /* Create the module structure */
887 if ((hModule
= MODULE_LoadExeHeader( fd
, &ofs
)) < 32)
890 fprintf( stderr
, "LoadModule: can't load '%s', error=%d\n",
894 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
896 /* Allocate the segments for this module */
898 MODULE_CreateSegments( hModule
);
901 hInstance
= MODULE_CreateInstance( hModule
, (LOADPARAMS
*)paramBlock
);
903 /* Load the referenced DLLs */
905 pModRef
= (WORD
*)((char *)pModule
+ pModule
->modref_table
);
906 pDLLs
= (WORD
*)GlobalLock( pModule
->dlls_to_init
);
907 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
910 BYTE
*pstr
= (BYTE
*)pModule
+ pModule
->import_table
+ *pModRef
;
911 memcpy( buffer
, pstr
+ 1, *pstr
);
912 strcpy( buffer
+ *pstr
, ".dll" );
913 dprintf_module( stddeb
, "Loading '%s'\n", buffer
);
914 if (!(*pModRef
= MODULE_FindModule( buffer
)))
916 /* If the DLL is not loaded yet, load it and store */
917 /* its handle in the list of DLLs to initialize. */
920 if ((hDLL
= LoadModule( buffer
, (LPVOID
)-1 )) == 2) /* file not found */
924 /* Try with prepending the path of the current module */
925 GetModuleFileName( hModule
, buffer
, 256 );
926 if (!(p
= strrchr( buffer
, '\\' ))) p
= buffer
;
927 memcpy( p
+ 1, pstr
+ 1, *pstr
);
928 strcpy( p
+ 1 + *pstr
, ".dll" );
929 hDLL
= LoadModule( buffer
, (LPVOID
)-1 );
933 fprintf( stderr
, "Could not load '%s' required by '%s', error = %d\n",
934 buffer
, name
, hDLL
);
935 return 2; /* file not found */
937 *pModRef
= GetExePtr( hDLL
);
940 else /* Increment the reference count of the DLL */
942 NE_MODULE
*pOldDLL
= (NE_MODULE
*)GlobalLock( *pModRef
);
943 if (pOldDLL
) pOldDLL
->count
++;
947 /* Load the segments */
949 for (i
= 1; i
<= pModule
->seg_count
; i
++) NE_LoadSegment( hModule
, i
);
951 /* Fixup the functions prologs */
953 NE_FixupPrologs( hModule
);
955 /* Make sure the usage count is 1 on the first loading of */
956 /* the module, even if it contains circular DLL references */
962 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
963 hPrevInstance
= MODULE_GetInstance( hModule
);
964 hInstance
= MODULE_CreateInstance( hModule
, params
);
965 if (hInstance
!= hPrevInstance
) /* not a library */
966 NE_LoadSegment( hModule
, pModule
->dgroup
);
970 /* Create a task for this instance */
972 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
) && (paramBlock
!= (LPVOID
)-1))
974 TASK_CreateTask( hModule
, hInstance
, hPrevInstance
,
975 params
->hEnvironment
,
976 (LPSTR
)PTR_SEG_TO_LIN( params
->cmdLine
),
977 *((WORD
*)PTR_SEG_TO_LIN(params
->showCmd
)+1) );
984 /**********************************************************************
985 * FreeModule (KERNEL.46)
987 BOOL
FreeModule( HANDLE hModule
)
991 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
992 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
994 dprintf_module( stddeb
, "FreeModule: %s count %d\n",
995 MODULE_GetModuleName(hModule
), pModule
->count
);
996 if (--pModule
->count
== 0) MODULE_FreeModule( hModule
);
1001 /**********************************************************************
1002 * GetModuleHandle (KERNEL.47)
1004 HMODULE
WIN16_GetModuleHandle( SEGPTR name
)
1006 if (HIWORD(name
) == 0) return GetExePtr( LOWORD(name
) );
1007 return MODULE_FindModule( PTR_SEG_TO_LIN(name
) );
1010 HMODULE
GetModuleHandle( LPCSTR name
)
1012 return MODULE_FindModule( name
);
1016 /**********************************************************************
1017 * GetModuleUsage (KERNEL.48)
1019 int GetModuleUsage( HANDLE hModule
)
1023 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1024 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
1025 dprintf_module( stddeb
, "GetModuleUsage(%04x): returning %d\n",
1026 hModule
, pModule
->count
);
1027 return pModule
->count
;
1031 /**********************************************************************
1032 * GetModuleFileName (KERNEL.49)
1034 int GetModuleFileName( HANDLE hModule
, LPSTR lpFileName
, short nSize
)
1039 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1040 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
1041 name
= ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
;
1042 strncpy( lpFileName
, name
, nSize
);
1043 lpFileName
[nSize
-1] = '\0';
1044 dprintf_module( stddeb
, "GetModuleFilename: %s\n", lpFileName
);
1045 return strlen(lpFileName
);
1049 /***********************************************************************
1050 * LoadLibrary (KERNEL.95)
1052 HANDLE
LoadLibrary( LPCSTR libname
)
1056 dprintf_module( stddeb
, "LoadLibrary: (%08x) %s\n", (int)libname
, libname
);
1057 /* This does not increment the module reference count, and will
1058 * therefore cause crashes on FreeLibrary calls.
1059 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1061 handle
= LoadModule( libname
, (LPVOID
)-1 );
1062 if (handle
== 2) /* file not found */
1065 strcpy( buffer
, libname
);
1066 strcat( buffer
, ".dll" );
1067 handle
= LoadModule( buffer
, (LPVOID
)-1 );
1069 if (handle
>= 32) NE_InitializeDLLs( GetExePtr(handle
) );
1074 /***********************************************************************
1075 * FreeLibrary (KERNEL.96)
1077 void FreeLibrary( HANDLE handle
)
1079 dprintf_module( stddeb
,"FreeLibrary: %04x\n", handle
);
1080 FreeModule( handle
);
1084 /***********************************************************************
1085 * WinExec (KERNEL.166)
1087 HANDLE
WinExec( LPSTR lpCmdLine
, WORD nCmdShow
)
1090 HLOCAL cmdShowHandle
, cmdLineHandle
;
1093 char *p
, *cmdline
, filename
[256];
1095 if (!(cmdShowHandle
= GlobalAlloc( 0, 2 * sizeof(WORD
) ))) return 0;
1096 if (!(cmdLineHandle
= GlobalAlloc( 0, 256 ))) return 0;
1098 /* Store nCmdShow */
1100 cmdShowPtr
= (WORD
*)GlobalLock( cmdShowHandle
);
1102 cmdShowPtr
[1] = nCmdShow
;
1104 /* Build the filename and command-line */
1106 cmdline
= (char *)GlobalLock( cmdLineHandle
);
1107 strncpy( filename
, lpCmdLine
, 256 );
1108 filename
[255] = '\0';
1109 for (p
= filename
; *p
&& (*p
!= ' ') && (*p
!= '\t'); p
++);
1112 strncpy( cmdline
, p
+ 1, 128 );
1113 cmdline
[127] = '\0';
1115 else cmdline
[0] = '\0';
1118 /* Now load the executable file */
1120 params
.hEnvironment
= SELECTOROF( GetDOSEnvironment() );
1121 params
.cmdLine
= WIN16_GlobalLock( cmdLineHandle
);
1122 params
.showCmd
= WIN16_GlobalLock( cmdShowHandle
);
1123 params
.reserved
= 0;
1124 handle
= LoadModule( filename
, ¶ms
);
1125 if (handle
== 2) /* file not found */
1127 strcat( filename
, ".exe" );
1128 handle
= LoadModule( filename
, ¶ms
);
1131 GlobalFree( cmdShowHandle
);
1132 GlobalFree( cmdLineHandle
);
1137 /***********************************************************************
1138 * GetProcAddress (KERNEL.50)
1140 FARPROC
GetProcAddress( HANDLE hModule
, SEGPTR name
)
1145 if (!hModule
) hModule
= GetCurrentTask();
1146 hModule
= GetExePtr( hModule
);
1148 if (HIWORD(name
) != 0)
1150 ordinal
= MODULE_GetOrdinal( hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1151 dprintf_module( stddeb
, "GetProcAddress: %04x '%s'\n",
1152 hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1156 ordinal
= LOWORD(name
);
1157 dprintf_module( stddeb
, "GetProcAddress: %04x %04x\n",
1160 if (!ordinal
) return (FARPROC
)0;
1162 ret
= MODULE_GetEntryPoint( hModule
, ordinal
);
1164 dprintf_module( stddeb
, "GetProcAddress: returning %08lx\n", ret
);
1165 return (FARPROC
)ret
;
1169 /***********************************************************************
1170 * GetWndProcEntry16 (not a Windows API function)
1172 * Return an entry point from the WINPROCS dll.
1174 WNDPROC
GetWndProcEntry16( char *name
)
1177 static HMODULE hModule
= 0;
1179 if (!hModule
) hModule
= GetModuleHandle( "WINPROCS" );
1180 ordinal
= MODULE_GetOrdinal( hModule
, name
);
1181 return MODULE_GetEntryPoint( hModule
, ordinal
);
1185 /**********************************************************************
1186 * ModuleFirst (TOOLHELP.59)
1188 BOOL
ModuleFirst( MODULEENTRY
*lpme
)
1190 lpme
->wNext
= hFirstModule
;
1191 return ModuleNext( lpme
);
1195 /**********************************************************************
1196 * ModuleNext (TOOLHELP.60)
1198 BOOL
ModuleNext( MODULEENTRY
*lpme
)
1202 if (!lpme
->wNext
) return FALSE
;
1203 if (!(pModule
= (NE_MODULE
*)GlobalLock( lpme
->wNext
))) return FALSE
;
1204 strncpy( lpme
->szModule
, (char *)pModule
+ pModule
->name_table
,
1206 lpme
->szModule
[MAX_MODULE_NAME
] = '\0';
1207 lpme
->hModule
= lpme
->wNext
;
1208 lpme
->wcUsage
= pModule
->count
;
1209 strncpy( lpme
->szExePath
,
1210 ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
,
1212 lpme
->szExePath
[MAX_PATH
] = '\0';
1213 lpme
->wNext
= pModule
->next
;
1218 /**********************************************************************
1219 * ModuleFindName (TOOLHELP.61)
1221 BOOL
ModuleFindName( MODULEENTRY
*lpme
, LPCSTR name
)
1223 lpme
->wNext
= GetModuleHandle( name
);
1224 return ModuleNext( lpme
);
1228 /**********************************************************************
1229 * ModuleFindHandle (TOOLHELP.62)
1231 BOOL
ModuleFindHandle( MODULEENTRY
*lpme
, HMODULE hModule
)
1233 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1234 lpme
->wNext
= hModule
;
1235 return ModuleNext( lpme
);