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
;
44 /* Create the built-in modules */
46 for (i
= 0, table
= dll_builtin_table
; i
< N_BUILTINS
; i
++, table
++)
48 if (!table
->used
) continue;
50 hModule
= GLOBAL_CreateBlock( GMEM_MOVEABLE
, table
->module_start
,
51 table
->module_end
- table
->module_start
,
52 0, FALSE
, FALSE
, FALSE
, NULL
);
53 if (!hModule
) return FALSE
;
54 FarSetOwner( hModule
, hModule
);
56 table
->hModule
= hModule
;
58 dprintf_module( stddeb
, "Built-in %s: hmodule=%04x\n",
59 table
->name
, hModule
);
61 /* Allocate the code segment */
63 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
64 pSegTable
= NE_SEG_TABLE( pModule
);
66 pSegTable
->selector
= GLOBAL_CreateBlock(GMEM_FIXED
, table
->code_start
,
67 pSegTable
->minsize
, hModule
,
68 TRUE
, TRUE
, FALSE
, NULL
);
69 if (!pSegTable
->selector
) return FALSE
;
72 /* Allocate the data segment */
74 pSegTable
->selector
= GLOBAL_Alloc( GMEM_FIXED
, pSegTable
->minsize
,
75 hModule
, FALSE
, FALSE
, FALSE
);
76 if (!pSegTable
->selector
) return FALSE
;
77 memcpy( GlobalLock( pSegTable
->selector
), table
->data_start
,
80 pModule
->next
= hFirstModule
;
81 hFirstModule
= hModule
;
84 /* Initialize KERNEL.178 (__WINFLAGS) with the correct flags value */
86 MODULE_SetEntryPoint( GetModuleHandle( "KERNEL" ), 178, GetWinFlags() );
92 /***********************************************************************
95 void MODULE_PrintModule( HMODULE hmodule
)
101 NE_MODULE
*pModule
= (NE_MODULE
*)GlobalLock( hmodule
);
103 /* Dump the module info */
105 printf( "Module %04x:\n", hmodule
);
106 printf( "count=%d flags=%04x heap=%d stack=%d\n",
107 pModule
->count
, pModule
->flags
,
108 pModule
->heap_size
, pModule
->stack_size
);
109 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
110 pModule
->cs
, pModule
->ip
, pModule
->ss
, pModule
->sp
, pModule
->dgroup
,
111 pModule
->seg_count
, pModule
->modref_count
);
112 printf( "os_flags=%d swap_area=%d version=%04x\n",
113 pModule
->os_flags
, pModule
->min_swap_area
,
114 pModule
->expected_version
);
116 /* Dump the file info */
118 printf( "Filename: '%s'\n",
119 ((LOADEDFILEINFO
*)((BYTE
*)pModule
+ pModule
->fileinfo
))->filename
);
121 /* Dump the segment table */
123 printf( "\nSegment table:\n" );
124 pSeg
= NE_SEG_TABLE( pModule
);
125 for (i
= 0; i
< pModule
->seg_count
; i
++, pSeg
++)
126 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
127 i
+ 1, pSeg
->filepos
, pSeg
->size
, pSeg
->flags
,
128 pSeg
->minsize
, pSeg
->selector
);
130 /* Dump the resource table */
132 printf( "\nResource table:\n" );
133 if (pModule
->res_table
)
135 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->res_table
);
136 printf( "Alignment: %d\n", *pword
++ );
139 struct resource_typeinfo_s
*ptr
= (struct resource_typeinfo_s
*)pword
;
140 struct resource_nameinfo_s
*pname
= (struct resource_nameinfo_s
*)(ptr
+ 1);
141 printf( "id=%04x count=%d\n", ptr
->type_id
, ptr
->count
);
142 for (i
= 0; i
< ptr
->count
; i
++, pname
++)
143 printf( "offset=%d len=%d id=%04x\n",
144 pname
->offset
, pname
->length
, pname
->id
);
145 pword
= (WORD
*)pname
;
148 else printf( "None\n" );
150 /* Dump the resident name table */
152 printf( "\nResident-name table:\n" );
153 pstr
= (char *)pModule
+ pModule
->name_table
;
156 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
157 *(WORD
*)(pstr
+ *pstr
+ 1) );
158 pstr
+= *pstr
+ 1 + sizeof(WORD
);
161 /* Dump the module reference table */
163 printf( "\nModule ref table:\n" );
164 if (pModule
->modref_table
)
166 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->modref_table
);
167 for (i
= 0; i
< pModule
->modref_count
; i
++, pword
++)
169 char *name
= (char *)pModule
+ pModule
->import_table
+ *pword
;
170 printf( "%d: %04x -> '%*.*s'\n",
171 i
, *pword
, *name
, *name
, name
+ 1 );
174 else printf( "None\n" );
176 /* Dump the entry table */
178 printf( "\nEntry table:\n" );
179 pstr
= (char *)pModule
+ pModule
->entry_table
;
183 printf( "Bundle %d-%d: %02x\n", ordinal
, ordinal
+ *pstr
- 1, pstr
[1]);
189 else if ((BYTE
)pstr
[1] == 0xff) /* moveable */
191 struct entry_tab_movable_s
*pe
= (struct entry_tab_movable_s
*)(pstr
+2);
192 for (i
= 0; i
< *pstr
; i
++, pe
++)
193 printf( "%d: %02x:%04x (moveable)\n",
194 ordinal
++, pe
->seg_number
, pe
->offset
);
199 struct entry_tab_fixed_s
*pe
= (struct entry_tab_fixed_s
*)(pstr
+2);
200 for (i
= 0; i
< *pstr
; i
++, pe
++)
201 printf( "%d: %04x (fixed)\n",
202 ordinal
++, pe
->offset
[0] + (pe
->offset
[1] << 8) );
207 /* Dump the non-resident names table */
209 printf( "\nNon-resident names table:\n" );
210 if (pModule
->nrname_handle
)
212 pstr
= (char *)GlobalLock( pModule
->nrname_handle
);
215 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
216 *(WORD
*)(pstr
+ *pstr
+ 1) );
217 pstr
+= *pstr
+ 1 + sizeof(WORD
);
224 /***********************************************************************
227 int MODULE_OpenFile( HMODULE hModule
)
232 static int cachedfd
= -1;
234 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
235 dprintf_module( stddeb
, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
236 hModule
, hCachedModule
, cachedfd
);
237 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return -1;
238 if (hCachedModule
== hModule
) return cachedfd
;
240 hCachedModule
= hModule
;
241 name
= ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
;
242 cachedfd
= open( DOS_GetUnixFileName( name
), O_RDONLY
);
243 dprintf_module( stddeb
, "MODULE_OpenFile: opened '%s' -> %d\n",
249 /***********************************************************************
250 * MODULE_CreateSegments
252 static BOOL
MODULE_CreateSegments( HMODULE hModule
)
254 SEGTABLEENTRY
*pSegment
;
258 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
259 pSegment
= NE_SEG_TABLE( pModule
);
260 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
262 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
263 if (i
== pModule
->ss
) minsize
+= pModule
->stack_size
;
264 /* The DGROUP is allocated by MODULE_CreateInstance */
265 if (i
== pModule
->dgroup
) continue;
266 pSegment
->selector
= GLOBAL_Alloc( GMEM_ZEROINIT
| GMEM_FIXED
,
268 !(pSegment
->flags
& NE_SEGFLAGS_DATA
),
270 FALSE
/*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
271 if (!pSegment
->selector
) return FALSE
;
274 pModule
->dgroup_entry
= pModule
->dgroup
? pModule
->seg_table
+
275 (pModule
->dgroup
- 1) * sizeof(SEGTABLEENTRY
) : 0;
280 /***********************************************************************
283 static HINSTANCE
MODULE_GetInstance( HMODULE hModule
)
285 SEGTABLEENTRY
*pSegment
;
288 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
289 if (pModule
->dgroup
== 0) return hModule
;
291 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
293 return pSegment
->selector
;
297 /***********************************************************************
298 * MODULE_CreateInstance
300 static HINSTANCE
MODULE_CreateInstance( HMODULE hModule
, LOADPARAMS
*params
)
302 SEGTABLEENTRY
*pSegment
;
305 HINSTANCE hNewInstance
, hPrevInstance
;
307 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
308 if (pModule
->dgroup
== 0) return hModule
;
310 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
311 hPrevInstance
= pSegment
->selector
;
313 /* if it's a library, create a new instance only the first time */
316 if (pModule
->flags
& NE_FFLAGS_LIBMODULE
) return hPrevInstance
;
317 if (params
== (LOADPARAMS
*)-1) return hPrevInstance
;
320 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
321 if (pModule
->ss
== pModule
->dgroup
) minsize
+= pModule
->stack_size
;
322 minsize
+= pModule
->heap_size
;
323 hNewInstance
= GLOBAL_Alloc( GMEM_ZEROINIT
| GMEM_FIXED
,
324 minsize
, hModule
, FALSE
, FALSE
, FALSE
);
325 if (!hNewInstance
) return 0;
326 pSegment
->selector
= hNewInstance
;
331 /***********************************************************************
332 * MODULE_LoadExeHeader
334 HMODULE
MODULE_LoadExeHeader( int fd
, OFSTRUCT
*ofs
)
336 struct mz_header_s mz_header
;
337 struct ne_header_s ne_header
;
342 char *buffer
, *fastload
= NULL
;
343 int fastload_offset
= 0, fastload_length
= 0;
345 /* Read a block from either the file or the fast-load area. */
346 #define READ(offset,size,buffer) \
347 ((fastload && ((offset) >= fastload_offset) && \
348 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
349 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
350 (lseek( fd, mz_header.ne_offset+(offset), SEEK_SET), \
351 read( fd, (buffer), (size) ) == (size)))
353 lseek( fd
, 0, SEEK_SET
);
354 if ((read( fd
, &mz_header
, sizeof(mz_header
) ) != sizeof(mz_header
)) ||
355 (mz_header
.mz_magic
!= MZ_SIGNATURE
)) return 11; /* invalid exe */
357 lseek( fd
, mz_header
.ne_offset
, SEEK_SET
);
358 if (read( fd
, &ne_header
, sizeof(ne_header
) ) != sizeof(ne_header
))
359 return 11; /* invalid exe */
361 if (ne_header
.ne_magic
== PE_SIGNATURE
) return 21; /* win32 exe */
362 if (ne_header
.ne_magic
!= NE_SIGNATURE
) return 11; /* invalid exe */
364 /* We now have a valid NE header */
366 size
= sizeof(NE_MODULE
) +
367 /* loaded file info */
368 sizeof(LOADEDFILEINFO
) + strlen(ofs
->szPathName
) +
370 ne_header
.n_segment_tab
* sizeof(SEGTABLEENTRY
) +
372 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
+
373 /* resident names table */
374 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
+
375 /* module ref table */
376 ne_header
.n_mod_ref_tab
* sizeof(WORD
) +
377 /* imported names table */
378 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
+
379 /* entry table length */
380 ne_header
.entry_tab_length
;
382 hModule
= GlobalAlloc( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
383 if (!hModule
) return 11; /* invalid exe */
384 FarSetOwner( hModule
, hModule
);
385 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
386 memcpy( pModule
, &ne_header
, sizeof(NE_MODULE
) );
388 pData
= (BYTE
*)(pModule
+ 1);
390 /* Read the fast-load area */
392 if (ne_header
.additional_flags
& NE_AFLAGS_FASTLOAD
)
394 fastload_offset
=ne_header
.fastload_offset
<<ne_header
.align_shift_count
;
395 fastload_length
=ne_header
.fastload_length
<<ne_header
.align_shift_count
;
396 dprintf_module( stddeb
, "Using fast-load area offset=%x len=%d\n",
397 fastload_offset
, fastload_length
);
398 if ((fastload
= (char *)malloc( fastload_length
)) != NULL
)
400 lseek( fd
, mz_header
.ne_offset
+ fastload_offset
, SEEK_SET
);
401 if (read( fd
, fastload
, fastload_length
) != fastload_length
)
409 /* Store the filename information */
411 pModule
->fileinfo
= (int)pData
- (int)pModule
;
412 ((LOADEDFILEINFO
*)pData
)->length
= sizeof(LOADEDFILEINFO
)+strlen(ofs
->szPathName
);
413 ((LOADEDFILEINFO
*)pData
)->fixed_media
= TRUE
;
414 ((LOADEDFILEINFO
*)pData
)->error
= 0;
415 ((LOADEDFILEINFO
*)pData
)->date
= 0;
416 ((LOADEDFILEINFO
*)pData
)->time
= 0;
417 strcpy( ((LOADEDFILEINFO
*)pData
)->filename
, ofs
->szPathName
);
418 pData
+= ((LOADEDFILEINFO
*)pData
)->length
--;
420 /* Get the segment table */
422 pModule
->seg_table
= (int)pData
- (int)pModule
;
423 buffer
= malloc( ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
) );
427 struct ne_segment_table_entry_s
*pSeg
;
429 if (!READ( ne_header
.segment_tab_offset
,
430 ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
),
431 buffer
)) return 11; /* invalid exe */
432 pSeg
= (struct ne_segment_table_entry_s
*)buffer
;
433 for (i
= ne_header
.n_segment_tab
; i
> 0; i
--, pSeg
++)
435 memcpy( pData
, pSeg
, sizeof(*pSeg
) );
436 pData
+= sizeof(SEGTABLEENTRY
);
440 else return 11; /* invalid exe */
442 /* Get the resource table */
444 if (ne_header
.resource_tab_offset
< ne_header
.rname_tab_offset
)
446 pModule
->res_table
= (int)pData
- (int)pModule
;
447 if (!READ(ne_header
.resource_tab_offset
,
448 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
,
449 pData
)) return 11; /* invalid exe */
450 pData
+= ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
;
452 else pModule
->res_table
= 0; /* No resource table */
454 /* Get the resident names table */
456 pModule
->name_table
= (int)pData
- (int)pModule
;
457 if (!READ( ne_header
.rname_tab_offset
,
458 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
,
459 pData
)) return 11; /* invalid exe */
460 pData
+= ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
;
462 /* Get the module references table */
464 if (ne_header
.n_mod_ref_tab
> 0)
466 pModule
->modref_table
= (int)pData
- (int)pModule
;
467 if (!READ( ne_header
.moduleref_tab_offset
,
468 ne_header
.n_mod_ref_tab
* sizeof(WORD
),
469 pData
)) return 11; /* invalid exe */
470 pData
+= ne_header
.n_mod_ref_tab
* sizeof(WORD
);
472 else pModule
->modref_table
= 0; /* No module references */
474 /* Get the imported names table */
476 pModule
->import_table
= (int)pData
- (int)pModule
;
477 if (!READ( ne_header
.iname_tab_offset
,
478 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
,
479 pData
)) return 11; /* invalid exe */
480 pData
+= ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
;
482 /* Get the entry table */
484 pModule
->entry_table
= (int)pData
- (int)pModule
;
485 if (!READ( ne_header
.entry_tab_offset
,
486 ne_header
.entry_tab_length
,
487 pData
)) return 11; /* invalid exe */
488 pData
+= ne_header
.entry_tab_length
;
490 /* Get the non-resident names table */
492 if (ne_header
.nrname_tab_length
)
494 pModule
->nrname_handle
= GLOBAL_Alloc( 0, ne_header
.nrname_tab_length
,
495 hModule
, FALSE
, FALSE
, FALSE
);
496 if (!pModule
->nrname_handle
) return 11; /* invalid exe */
497 buffer
= GlobalLock( pModule
->nrname_handle
);
498 lseek( fd
, ne_header
.nrname_tab_offset
, SEEK_SET
);
499 if (read( fd
, buffer
, ne_header
.nrname_tab_length
)
500 != ne_header
.nrname_tab_length
) return 11; /* invalid exe */
502 else pModule
->nrname_handle
= 0;
504 /* Allocate a segment for the implicitly-loaded DLLs */
506 if (pModule
->modref_count
)
508 pModule
->dlls_to_init
= GLOBAL_Alloc(GMEM_ZEROINIT
,
509 (pModule
->modref_count
+1)*sizeof(HMODULE
),
510 hModule
, FALSE
, FALSE
, FALSE
);
511 if (!pModule
->dlls_to_init
) return 11; /* invalid exe */
513 else pModule
->dlls_to_init
= 0;
515 if (debugging_module
) MODULE_PrintModule( hModule
);
516 pModule
->next
= hFirstModule
;
517 hFirstModule
= hModule
;
522 /***********************************************************************
525 * Lookup the ordinal for a given name.
527 WORD
MODULE_GetOrdinal( HMODULE hModule
, char *name
)
529 char buffer
[256], *cpnt
;
533 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
535 dprintf_module( stddeb
, "MODULE_GetOrdinal(%04x,'%s')\n",
538 /* First handle names of the form '#xxxx' */
540 if (name
[0] == '#') return atoi( name
+ 1 );
542 /* Now copy and uppercase the string */
544 strcpy( buffer
, name
);
546 len
= strlen( buffer
);
548 /* First search the resident names */
550 cpnt
= (char *)pModule
+ pModule
->name_table
;
552 /* Skip the first entry (module name) */
553 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
556 dprintf_module( stddeb
, " Checking '%*.*s'\n", *cpnt
, *cpnt
, cpnt
+1 );
557 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
559 dprintf_module( stddeb
, " Found: ordinal=%d\n",
560 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
561 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
563 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
566 /* Now search the non-resident names table */
568 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
569 cpnt
= (char *)GlobalLock( pModule
->nrname_handle
);
571 /* Skip the first entry (module description string) */
572 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
575 dprintf_module( stddeb
, " Checking '%*.*s'\n", *cpnt
, *cpnt
, cpnt
+1 );
576 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
578 dprintf_module( stddeb
, " Found: ordinal=%d\n",
579 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
580 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
582 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
588 /***********************************************************************
589 * MODULE_GetEntryPoint
591 * Return the entry point for a given ordinal.
593 DWORD
MODULE_GetEntryPoint( HMODULE hModule
, WORD ordinal
)
600 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
602 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
603 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
605 /* Skipping this bundle */
609 case 0: p
+= 2; break; /* unused */
610 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
611 default: p
+= 2 + *p
* 3; break; /* fixed */
620 case 0xff: /* moveable */
621 p
+= 2 + 6 * (ordinal
- curOrdinal
);
623 offset
= *(WORD
*)(p
+ 4);
627 p
+= 2 + 3 * (ordinal
- curOrdinal
);
628 offset
= *(WORD
*)(p
+ 1);
632 if (sel
== 0xfe) sel
= 0xffff; /* constant entry */
633 else sel
= NE_SEG_TABLE(pModule
)[sel
-1].selector
;
634 return MAKELONG( offset
, sel
);
638 /***********************************************************************
639 * MODULE_SetEntryPoint
641 * Change the value of an entry point. Use with caution!
642 * It can only change the offset value, not the selector.
644 BOOL
MODULE_SetEntryPoint( HMODULE hModule
, WORD ordinal
, WORD offset
)
650 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
652 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
653 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
655 /* Skipping this bundle */
659 case 0: p
+= 2; break; /* unused */
660 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
661 default: p
+= 2 + *p
* 3; break; /* fixed */
664 if (!*p
) return FALSE
;
670 case 0xff: /* moveable */
671 p
+= 2 + 6 * (ordinal
- curOrdinal
);
672 *(WORD
*)(p
+ 4) = offset
;
675 p
+= 2 + 3 * (ordinal
- curOrdinal
);
676 *(WORD
*)(p
+ 1) = offset
;
683 /***********************************************************************
684 * MODULE_GetEntryPointName
686 * Return the entry point name for a given ordinal.
687 * Used only by relay debugging.
688 * Warning: returned pointer is to a Pascal-type string.
690 LPSTR
MODULE_GetEntryPointName( HMODULE hModule
, WORD ordinal
)
695 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
697 /* First search the resident names */
699 cpnt
= (char *)pModule
+ pModule
->name_table
;
702 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
703 if (*(WORD
*)(cpnt
+ *cpnt
+ 1) == ordinal
) return cpnt
;
706 /* Now search the non-resident names table */
708 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
709 cpnt
= (char *)GlobalLock( pModule
->nrname_handle
);
712 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
713 if (*(WORD
*)(cpnt
+ *cpnt
+ 1) == ordinal
) return cpnt
;
719 /***********************************************************************
720 * MODULE_GetModuleName
722 LPSTR
MODULE_GetModuleName( HMODULE hModule
)
726 static char buffer
[10];
728 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return NULL
;
729 p
= (BYTE
*)pModule
+ pModule
->name_table
;
731 memcpy( buffer
, p
+ 1, len
);
737 /**********************************************************************
740 * Find a module from a path name.
742 HMODULE
MODULE_FindModule( LPCSTR path
)
744 HMODULE hModule
= hFirstModule
;
745 LPCSTR filename
, dotptr
, modulepath
, modulename
;
746 BYTE len
, *name_table
;
748 if (!(filename
= strrchr( path
, '\\' ))) filename
= path
;
750 if ((dotptr
= strrchr( filename
, '.' )) != NULL
)
751 len
= (BYTE
)(dotptr
- filename
);
752 else len
= strlen( filename
);
756 NE_MODULE
*pModule
= (NE_MODULE
*)GlobalLock( hModule
);
758 modulepath
= ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
;
759 if (!(modulename
= strrchr( modulepath
, '\\' )))
760 modulename
= modulepath
;
762 if (!strcasecmp( modulename
, filename
)) return hModule
;
764 name_table
= (BYTE
*)pModule
+ pModule
->name_table
;
765 if ((*name_table
== len
) && !strncasecmp(filename
, name_table
+1, len
))
767 hModule
= pModule
->next
;
773 /**********************************************************************
776 * Remove a module from memory.
778 static void MODULE_FreeModule( HMODULE hModule
)
780 HMODULE
*hPrevModule
;
782 SEGTABLEENTRY
*pSegment
;
786 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return;
788 /* FIXME: should call the exit code for the library here */
790 /* Remove it from the linked list */
792 hPrevModule
= &hFirstModule
;
793 while (*hPrevModule
&& (*hPrevModule
!= hModule
))
795 hPrevModule
= &((NE_MODULE
*)GlobalLock( *hPrevModule
))->next
;
797 if (*hPrevModule
) *hPrevModule
= pModule
->next
;
799 /* Free all the segments */
801 pSegment
= NE_SEG_TABLE( pModule
);
802 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
804 GlobalFree( pSegment
->selector
);
807 /* Free the referenced modules */
809 pModRef
= NE_MODULE_TABLE( pModule
);
810 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
812 FreeModule( *pModRef
);
815 /* Free the module storage */
817 if (pModule
->nrname_handle
) GlobalFree( pModule
->nrname_handle
);
818 if (pModule
->dlls_to_init
) GlobalFree( pModule
->dlls_to_init
);
819 GlobalFree( hModule
);
821 /* Remove module from cache */
823 if (hCachedModule
== hModule
) hCachedModule
= 0;
827 /**********************************************************************
828 * LoadModule (KERNEL.45)
830 HINSTANCE
LoadModule( LPCSTR name
, LPVOID paramBlock
)
833 HANDLE hInstance
, hPrevInstance
;
835 LOADPARAMS
*params
= (LOADPARAMS
*)paramBlock
;
836 WORD
*pModRef
, *pDLLs
;
839 hModule
= MODULE_FindModule( name
);
840 if (!hModule
) /* We have to load the module */
843 if (strchr( name
, '/' )) name
= DOS_GetDosFileName( name
);
844 if ((fd
= OpenFile( name
, &ofs
, OF_READ
)) == -1)
845 return 2; /* File not found */
847 /* Create the module structure */
849 if ((hModule
= MODULE_LoadExeHeader( fd
, &ofs
)) < 32)
852 fprintf( stderr
, "LoadModule: can't load '%s', error=%d\n",
856 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
858 /* Allocate the segments for this module */
860 MODULE_CreateSegments( hModule
);
863 hInstance
= MODULE_CreateInstance( hModule
, (LOADPARAMS
*)paramBlock
);
865 /* Load the referenced DLLs */
867 pModRef
= (WORD
*)((char *)pModule
+ pModule
->modref_table
);
868 pDLLs
= (WORD
*)GlobalLock( pModule
->dlls_to_init
);
869 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
872 BYTE
*pstr
= (BYTE
*)pModule
+ pModule
->import_table
+ *pModRef
;
873 memcpy( buffer
, pstr
+ 1, *pstr
);
874 strcpy( buffer
+ *pstr
, ".dll" );
875 dprintf_module( stddeb
, "Loading '%s'\n", buffer
);
876 if (!(*pModRef
= MODULE_FindModule( buffer
)))
878 /* If the DLL is not loaded yet, load it and store */
879 /* its handle in the list of DLLs to initialize. */
882 if ((hDLL
= LoadModule( buffer
, (LPVOID
)-1 )) == 2) /* file not found */
886 /* Try with prepending the path of the current module */
887 GetModuleFileName( hModule
, buffer
, 256 );
888 if (!(p
= strrchr( buffer
, '\\' ))) p
= buffer
;
889 memcpy( p
+ 1, pstr
+ 1, *pstr
);
890 strcpy( p
+ 1 + *pstr
, ".dll" );
891 hDLL
= LoadModule( buffer
, (LPVOID
)-1 );
895 fprintf( stderr
, "Could not load '%s' required by '%s', error = %d\n",
896 buffer
, name
, hDLL
);
897 return 2; /* file not found */
899 *pModRef
= GetExePtr( hDLL
);
902 else /* Increment the reference count of the DLL */
904 NE_MODULE
*pOldDLL
= (NE_MODULE
*)GlobalLock( *pModRef
);
905 if (pOldDLL
) pOldDLL
->count
++;
909 /* Load the segments */
911 for (i
= 1; i
<= pModule
->seg_count
; i
++) NE_LoadSegment( hModule
, i
);
913 /* Fixup the functions prologs */
915 NE_FixupPrologs( hModule
);
917 /* Make sure the usage count is 1 on the first loading of */
918 /* the module, even if it contains circular DLL references */
924 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
925 hPrevInstance
= MODULE_GetInstance( hModule
);
926 hInstance
= MODULE_CreateInstance( hModule
, params
);
927 if (hInstance
!= hPrevInstance
) /* not a library */
928 NE_LoadSegment( hModule
, pModule
->dgroup
);
932 /* Create a task for this instance */
934 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
) && (paramBlock
!= (LPVOID
)-1))
936 TASK_CreateTask( hModule
, hInstance
, hPrevInstance
,
937 params
->hEnvironment
,
938 (LPSTR
)PTR_SEG_TO_LIN( params
->cmdLine
),
939 *((WORD
*)PTR_SEG_TO_LIN(params
->showCmd
)+1) );
946 /**********************************************************************
947 * FreeModule (KERNEL.46)
949 BOOL
FreeModule( HANDLE hModule
)
953 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
954 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
956 dprintf_module( stddeb
, "FreeModule: %s count %d\n",
957 MODULE_GetModuleName(hModule
), pModule
->count
);
958 if (--pModule
->count
== 0) MODULE_FreeModule( hModule
);
963 /**********************************************************************
964 * GetModuleHandle (KERNEL.47)
966 HMODULE
WIN16_GetModuleHandle( SEGPTR name
)
968 if (HIWORD(name
) == 0) return GetExePtr( LOWORD(name
) );
969 return MODULE_FindModule( PTR_SEG_TO_LIN(name
) );
972 HMODULE
GetModuleHandle( LPCSTR name
)
974 return MODULE_FindModule( name
);
978 /**********************************************************************
979 * GetModuleUsage (KERNEL.48)
981 int GetModuleUsage( HANDLE hModule
)
985 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
986 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
987 dprintf_module( stddeb
, "GetModuleUsage(%04x): returning %d\n",
988 hModule
, pModule
->count
);
989 return pModule
->count
;
993 /**********************************************************************
994 * GetModuleFileName (KERNEL.49)
996 int GetModuleFileName( HANDLE hModule
, LPSTR lpFileName
, short nSize
)
1001 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1002 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
1003 name
= ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
;
1004 strncpy( lpFileName
, name
, nSize
);
1005 lpFileName
[nSize
-1] = '\0';
1006 dprintf_module( stddeb
, "GetModuleFilename: %s\n", lpFileName
);
1007 return strlen(lpFileName
);
1011 /***********************************************************************
1012 * LoadLibrary (KERNEL.95)
1014 HANDLE
LoadLibrary( LPCSTR libname
)
1018 dprintf_module( stddeb
, "LoadLibrary: (%08x) %s\n", (int)libname
, libname
);
1019 /* This does not increment the module reference count, and will
1020 * therefore cause crashes on FreeLibrary calls.
1021 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1023 handle
= LoadModule( libname
, (LPVOID
)-1 );
1024 if (handle
== 2) /* file not found */
1027 strcpy( buffer
, libname
);
1028 strcat( buffer
, ".dll" );
1029 handle
= LoadModule( buffer
, (LPVOID
)-1 );
1031 if (handle
>= 32) NE_InitializeDLLs( GetExePtr(handle
) );
1036 /***********************************************************************
1037 * FreeLibrary (KERNEL.96)
1039 void FreeLibrary( HANDLE handle
)
1041 dprintf_module( stddeb
,"FreeLibrary: %04x\n", handle
);
1042 FreeModule( handle
);
1046 /***********************************************************************
1047 * WinExec (KERNEL.166)
1049 HANDLE
WinExec( LPSTR lpCmdLine
, WORD nCmdShow
)
1052 HLOCAL cmdShowHandle
, cmdLineHandle
;
1055 char *p
, *cmdline
, filename
[256];
1057 if (!(cmdShowHandle
= GlobalAlloc( 0, 2 * sizeof(WORD
) ))) return 0;
1058 if (!(cmdLineHandle
= GlobalAlloc( 0, 256 ))) return 0;
1060 /* Store nCmdShow */
1062 cmdShowPtr
= (WORD
*)GlobalLock( cmdShowHandle
);
1064 cmdShowPtr
[1] = nCmdShow
;
1066 /* Build the filename and command-line */
1068 cmdline
= (char *)GlobalLock( cmdLineHandle
);
1069 strncpy( filename
, lpCmdLine
, 256 );
1070 filename
[255] = '\0';
1071 for (p
= filename
; *p
&& (*p
!= ' ') && (*p
!= '\t'); p
++);
1074 strncpy( cmdline
, p
+ 1, 128 );
1075 cmdline
[127] = '\0';
1077 else cmdline
[0] = '\0';
1080 /* Now load the executable file */
1082 params
.hEnvironment
= SELECTOROF( GetDOSEnvironment() );
1083 params
.cmdLine
= WIN16_GlobalLock( cmdLineHandle
);
1084 params
.showCmd
= WIN16_GlobalLock( cmdShowHandle
);
1085 params
.reserved
= 0;
1086 handle
= LoadModule( filename
, ¶ms
);
1087 if (handle
== 2) /* file not found */
1089 strcat( filename
, ".exe" );
1090 handle
= LoadModule( filename
, ¶ms
);
1093 GlobalFree( cmdShowHandle
);
1094 GlobalFree( cmdLineHandle
);
1099 /***********************************************************************
1100 * GetProcAddress (KERNEL.50)
1102 FARPROC
GetProcAddress( HANDLE hModule
, SEGPTR name
)
1107 if (!hModule
) hModule
= GetCurrentTask();
1108 hModule
= GetExePtr( hModule
);
1110 if (HIWORD(name
) != 0)
1112 ordinal
= MODULE_GetOrdinal( hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1113 dprintf_module( stddeb
, "GetProcAddress: %04x '%s'\n",
1114 hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1118 ordinal
= LOWORD(name
);
1119 dprintf_module( stddeb
, "GetProcAddress: %04x %04x\n",
1122 if (!ordinal
) return (FARPROC
)0;
1124 ret
= MODULE_GetEntryPoint( hModule
, ordinal
);
1126 dprintf_module( stddeb
, "GetProcAddress: returning %08lx\n", ret
);
1127 return (FARPROC
)ret
;
1131 /***********************************************************************
1132 * GetWndProcEntry16 (not a Windows API function)
1134 * Return an entry point from the WINPROCS dll.
1136 WNDPROC
GetWndProcEntry16( char *name
)
1139 static HMODULE hModule
= 0;
1141 if (!hModule
) hModule
= GetModuleHandle( "WINPROCS" );
1142 ordinal
= MODULE_GetOrdinal( hModule
, name
);
1143 return MODULE_GetEntryPoint( hModule
, ordinal
);
1147 /**********************************************************************
1148 * ModuleFirst (TOOLHELP.59)
1150 BOOL
ModuleFirst( MODULEENTRY
*lpme
)
1152 lpme
->wNext
= hFirstModule
;
1153 return ModuleNext( lpme
);
1157 /**********************************************************************
1158 * ModuleNext (TOOLHELP.60)
1160 BOOL
ModuleNext( MODULEENTRY
*lpme
)
1164 if (!lpme
->wNext
) return FALSE
;
1165 if (!(pModule
= (NE_MODULE
*)GlobalLock( lpme
->wNext
))) return FALSE
;
1166 strncpy( lpme
->szModule
, (char *)pModule
+ pModule
->name_table
,
1168 lpme
->szModule
[MAX_MODULE_NAME
] = '\0';
1169 lpme
->hModule
= lpme
->wNext
;
1170 lpme
->wcUsage
= pModule
->count
;
1171 strncpy( lpme
->szExePath
,
1172 ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
,
1174 lpme
->szExePath
[MAX_PATH
] = '\0';
1175 lpme
->wNext
= pModule
->next
;
1180 /**********************************************************************
1181 * ModuleFindName (TOOLHELP.61)
1183 BOOL
ModuleFindName( MODULEENTRY
*lpme
, LPCSTR name
)
1185 lpme
->wNext
= GetModuleHandle( name
);
1186 return ModuleNext( lpme
);
1190 /**********************************************************************
1191 * ModuleFindHandle (TOOLHELP.62)
1193 BOOL
ModuleFindHandle( MODULEENTRY
*lpme
, HMODULE hModule
)
1195 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1196 lpme
->wNext
= hModule
;
1197 return ModuleNext( lpme
);