4 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
20 #include "stackframe.h"
28 static HMODULE hFirstModule
= 0;
29 static HMODULE hCachedModule
= 0; /* Module cached by MODULE_OpenFile */
32 /***********************************************************************
35 * Load a built-in module. If the 'force' parameter is FALSE, we only
36 * load the module if it has not been disabled via the -dll option.
38 static HMODULE
MODULE_LoadBuiltin( LPCSTR name
, BOOL force
)
40 #ifndef WINELIB /* JBP: Not really allowed in libwine.a (FIXME:?) */
43 SEGTABLEENTRY
*pSegTable
;
44 struct dll_table_s
*table
;
48 /* Fix the name in case we have a full path and extension */
50 if ((p
= strrchr( name
, '\\' ))) name
= p
+ 1;
51 strncpy( dllname
, name
, 15 );
53 if ((p
= strrchr( dllname
, '.' ))) *p
= '\0';
55 for (i
= 0, table
= dll_builtin_table
; i
< N_BUILTINS
; i
++, table
++)
56 if (!strcasecmp( table
->name
, dllname
)) break;
57 if (i
>= N_BUILTINS
) return 0;
58 if (!table
->used
&& !force
) return 0;
60 hModule
= GLOBAL_CreateBlock( GMEM_MOVEABLE
, table
->module_start
,
61 table
->module_end
- table
->module_start
,
62 0, FALSE
, FALSE
, FALSE
, NULL
);
63 if (!hModule
) return 0;
64 FarSetOwner( hModule
, hModule
);
66 table
->hModule
= hModule
;
68 dprintf_module( stddeb
, "Built-in %s: hmodule=%04x\n",
69 table
->name
, hModule
);
71 /* Allocate the code segment */
73 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
74 pSegTable
= NE_SEG_TABLE( pModule
);
76 pSegTable
->selector
= GLOBAL_CreateBlock( GMEM_FIXED
, table
->code_start
,
77 pSegTable
->minsize
, hModule
,
78 TRUE
, TRUE
, FALSE
, NULL
);
79 if (!pSegTable
->selector
) return 0;
82 /* Allocate the data segment */
84 pSegTable
->selector
= GLOBAL_Alloc( GMEM_FIXED
, pSegTable
->minsize
,
85 hModule
, FALSE
, FALSE
, FALSE
);
86 if (!pSegTable
->selector
) return 0;
87 memcpy( GlobalLock( pSegTable
->selector
),
88 table
->data_start
, pSegTable
->minsize
);
90 pModule
->next
= hFirstModule
;
91 hFirstModule
= hModule
;
96 /***********************************************************************
99 * Create the built-in modules.
101 BOOL
MODULE_Init(void)
103 /* For these, built-in modules are always used */
105 if (!MODULE_LoadBuiltin( "KERNEL", TRUE
) ||
106 !MODULE_LoadBuiltin( "GDI", TRUE
) ||
107 !MODULE_LoadBuiltin( "USER", TRUE
) ||
108 !MODULE_LoadBuiltin( "WINPROCS", TRUE
)) return FALSE
;
111 fprintf(stderr
, "JBP: MODULE_Init() ignored.\n");
113 /* Initialize KERNEL.178 (__WINFLAGS) with the correct flags value */
115 MODULE_SetEntryPoint( GetModuleHandle( "KERNEL" ), 178, GetWinFlags() );
120 /***********************************************************************
123 void MODULE_PrintModule( HMODULE hmodule
)
129 NE_MODULE
*pModule
= (NE_MODULE
*)GlobalLock( hmodule
);
131 /* Dump the module info */
133 printf( "Module "NPFMT
":\n", hmodule
);
134 printf( "count=%d flags=%04x heap=%d stack=%d\n",
135 pModule
->count
, pModule
->flags
,
136 pModule
->heap_size
, pModule
->stack_size
);
137 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
138 pModule
->cs
, pModule
->ip
, pModule
->ss
, pModule
->sp
, pModule
->dgroup
,
139 pModule
->seg_count
, pModule
->modref_count
);
140 printf( "os_flags=%d swap_area=%d version=%04x\n",
141 pModule
->os_flags
, pModule
->min_swap_area
,
142 pModule
->expected_version
);
144 /* Dump the file info */
146 printf( "Filename: '%s'\n",
147 ((LOADEDFILEINFO
*)((BYTE
*)pModule
+ pModule
->fileinfo
))->filename
);
149 /* Dump the segment table */
151 printf( "\nSegment table:\n" );
152 pSeg
= NE_SEG_TABLE( pModule
);
153 for (i
= 0; i
< pModule
->seg_count
; i
++, pSeg
++)
154 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel="NPFMT
"\n",
155 i
+ 1, pSeg
->filepos
, pSeg
->size
, pSeg
->flags
,
156 pSeg
->minsize
, pSeg
->selector
);
158 /* Dump the resource table */
160 printf( "\nResource table:\n" );
161 if (pModule
->res_table
)
163 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->res_table
);
164 printf( "Alignment: %d\n", *pword
++ );
167 struct resource_typeinfo_s
*ptr
= (struct resource_typeinfo_s
*)pword
;
168 struct resource_nameinfo_s
*pname
= (struct resource_nameinfo_s
*)(ptr
+ 1);
169 printf( "id=%04x count=%d\n", ptr
->type_id
, ptr
->count
);
170 for (i
= 0; i
< ptr
->count
; i
++, pname
++)
171 printf( "offset=%d len=%d id=%04x\n",
172 pname
->offset
, pname
->length
, pname
->id
);
173 pword
= (WORD
*)pname
;
176 else printf( "None\n" );
178 /* Dump the resident name table */
180 printf( "\nResident-name table:\n" );
181 pstr
= (char *)pModule
+ pModule
->name_table
;
184 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
185 *(WORD
*)(pstr
+ *pstr
+ 1) );
186 pstr
+= *pstr
+ 1 + sizeof(WORD
);
189 /* Dump the module reference table */
191 printf( "\nModule ref table:\n" );
192 if (pModule
->modref_table
)
194 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->modref_table
);
195 for (i
= 0; i
< pModule
->modref_count
; i
++, pword
++)
197 char *name
= (char *)pModule
+ pModule
->import_table
+ *pword
;
198 printf( "%d: %04x -> '%*.*s'\n",
199 i
, *pword
, *name
, *name
, name
+ 1 );
202 else printf( "None\n" );
204 /* Dump the entry table */
206 printf( "\nEntry table:\n" );
207 pstr
= (char *)pModule
+ pModule
->entry_table
;
211 printf( "Bundle %d-%d: %02x\n", ordinal
, ordinal
+ *pstr
- 1, pstr
[1]);
217 else if ((BYTE
)pstr
[1] == 0xff) /* moveable */
219 struct entry_tab_movable_s
*pe
= (struct entry_tab_movable_s
*)(pstr
+2);
220 for (i
= 0; i
< *pstr
; i
++, pe
++)
221 printf( "%d: %02x:%04x (moveable)\n",
222 ordinal
++, pe
->seg_number
, pe
->offset
);
227 struct entry_tab_fixed_s
*pe
= (struct entry_tab_fixed_s
*)(pstr
+2);
228 for (i
= 0; i
< *pstr
; i
++, pe
++)
229 printf( "%d: %04x (fixed)\n",
230 ordinal
++, pe
->offset
[0] + (pe
->offset
[1] << 8) );
235 /* Dump the non-resident names table */
237 printf( "\nNon-resident names table:\n" );
238 if (pModule
->nrname_handle
)
240 pstr
= (char *)GlobalLock( pModule
->nrname_handle
);
243 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
244 *(WORD
*)(pstr
+ *pstr
+ 1) );
245 pstr
+= *pstr
+ 1 + sizeof(WORD
);
252 /***********************************************************************
255 int MODULE_OpenFile( HMODULE hModule
)
260 static int cachedfd
= -1;
262 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
263 dprintf_module( stddeb
, "MODULE_OpenFile("NPFMT
") cache: mod="NPFMT
" fd=%d\n",
264 hModule
, hCachedModule
, cachedfd
);
265 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return -1;
266 if (hCachedModule
== hModule
) return cachedfd
;
268 hCachedModule
= hModule
;
269 name
= ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
;
270 cachedfd
= open( DOS_GetUnixFileName( name
), O_RDONLY
);
271 dprintf_module( stddeb
, "MODULE_OpenFile: opened '%s' -> %d\n",
275 /***********************************************************************
279 /* This function translates NE segment flags to GlobalAlloc flags */
281 static WORD
MODULE_Ne2MemFlags(WORD flags
)
285 if (flags
& NE_SEGFLAGS_DISCARDABLE
)
286 memflags
|= GMEM_DISCARDABLE
;
287 if (flags
& NE_SEGFLAGS_MOVEABLE
||
288 ( ! (flags
& NE_SEGFLAGS_DATA
) &&
289 ! (flags
& NE_SEGFLAGS_LOADED
) &&
290 ! (flags
& NE_SEGFLAGS_ALLOCATED
)
293 memflags
|= GMEM_MOVEABLE
;
294 memflags
|= GMEM_ZEROINIT
;
296 memflags
= GMEM_ZEROINIT
| GMEM_FIXED
;
301 /***********************************************************************
302 * MODULE_AllocateSegment (WINPROCS.26)
305 DWORD
MODULE_AllocateSegment(WORD wFlags
, WORD wSize
, WORD wElem
)
307 WORD size
= wSize
<< wElem
;
308 HANDLE hMem
= GlobalAlloc( MODULE_Ne2MemFlags(wFlags
), size
);
310 return (DWORD
)GlobalLock(hMem
);
312 WORD selector
= HIWORD(GlobalLock(hMem
));
313 return MAKELONG(hMem
, selector
);
317 /***********************************************************************
318 * MODULE_CreateSegments
320 static BOOL
MODULE_CreateSegments( HMODULE hModule
)
322 SEGTABLEENTRY
*pSegment
;
326 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
327 pSegment
= NE_SEG_TABLE( pModule
);
328 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
330 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
331 if (i
== pModule
->ss
) minsize
+= pModule
->stack_size
;
332 /* The DGROUP is allocated by MODULE_CreateInstance */
333 if (i
== pModule
->dgroup
) continue;
334 pSegment
->selector
= GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment
->flags
),
336 !(pSegment
->flags
& NE_SEGFLAGS_DATA
),
338 FALSE
/*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
339 if (!pSegment
->selector
) return FALSE
;
342 pModule
->dgroup_entry
= pModule
->dgroup
? pModule
->seg_table
+
343 (pModule
->dgroup
- 1) * sizeof(SEGTABLEENTRY
) : 0;
348 /***********************************************************************
351 static HINSTANCE
MODULE_GetInstance( HMODULE hModule
)
353 SEGTABLEENTRY
*pSegment
;
356 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
357 if (pModule
->dgroup
== 0) return hModule
;
359 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
361 return pSegment
->selector
;
365 /***********************************************************************
366 * MODULE_CreateInstance
368 HINSTANCE
MODULE_CreateInstance( HMODULE hModule
, LOADPARAMS
*params
)
370 SEGTABLEENTRY
*pSegment
;
373 HINSTANCE hNewInstance
, hPrevInstance
;
375 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
376 if (pModule
->dgroup
== 0) return hModule
;
378 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
379 hPrevInstance
= pSegment
->selector
;
381 /* if it's a library, create a new instance only the first time */
384 if (pModule
->flags
& NE_FFLAGS_LIBMODULE
) return hPrevInstance
;
385 if (params
== (LOADPARAMS
*)-1) return hPrevInstance
;
388 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
389 if (pModule
->ss
== pModule
->dgroup
) minsize
+= pModule
->stack_size
;
390 minsize
+= pModule
->heap_size
;
391 hNewInstance
= GLOBAL_Alloc( GMEM_ZEROINIT
| GMEM_FIXED
,
392 minsize
, hModule
, FALSE
, FALSE
, FALSE
);
393 if (!hNewInstance
) return 0;
394 pSegment
->selector
= hNewInstance
;
399 /***********************************************************************
400 * MODULE_LoadExeHeader
402 HMODULE
MODULE_LoadExeHeader( int fd
, OFSTRUCT
*ofs
)
404 struct mz_header_s mz_header
;
405 struct ne_header_s ne_header
;
410 char *buffer
, *fastload
= NULL
;
411 int fastload_offset
= 0, fastload_length
= 0;
413 /* Read a block from either the file or the fast-load area. */
414 #define READ(offset,size,buffer) \
415 ((fastload && ((offset) >= fastload_offset) && \
416 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
417 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
418 (lseek( fd, mz_header.ne_offset+(offset), SEEK_SET), \
419 read( fd, (buffer), (size) ) == (size)))
421 lseek( fd
, 0, SEEK_SET
);
422 if ((read( fd
, &mz_header
, sizeof(mz_header
) ) != sizeof(mz_header
)) ||
423 (mz_header
.mz_magic
!= MZ_SIGNATURE
)) return (HMODULE
)11; /* invalid exe */
425 lseek( fd
, mz_header
.ne_offset
, SEEK_SET
);
426 if (read( fd
, &ne_header
, sizeof(ne_header
) ) != sizeof(ne_header
))
427 return (HMODULE
)11; /* invalid exe */
429 if (ne_header
.ne_magic
== PE_SIGNATURE
) return (HMODULE
)21; /* win32 exe */
430 if (ne_header
.ne_magic
!= NE_SIGNATURE
) return (HMODULE
)11; /* invalid exe */
432 /* We now have a valid NE header */
434 size
= sizeof(NE_MODULE
) +
435 /* loaded file info */
436 sizeof(LOADEDFILEINFO
) + strlen(ofs
->szPathName
) +
438 ne_header
.n_segment_tab
* sizeof(SEGTABLEENTRY
) +
440 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
+
441 /* resident names table */
442 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
+
443 /* module ref table */
444 ne_header
.n_mod_ref_tab
* sizeof(WORD
) +
445 /* imported names table */
446 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
+
447 /* entry table length */
448 ne_header
.entry_tab_length
;
450 hModule
= GlobalAlloc( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
451 if (!hModule
) return (HMODULE
)11; /* invalid exe */
452 FarSetOwner( hModule
, hModule
);
453 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
454 memcpy( pModule
, &ne_header
, sizeof(NE_MODULE
) );
456 pData
= (BYTE
*)(pModule
+ 1);
458 /* Read the fast-load area */
460 if (ne_header
.additional_flags
& NE_AFLAGS_FASTLOAD
)
462 fastload_offset
=ne_header
.fastload_offset
<<ne_header
.align_shift_count
;
463 fastload_length
=ne_header
.fastload_length
<<ne_header
.align_shift_count
;
464 dprintf_module( stddeb
, "Using fast-load area offset=%x len=%d\n",
465 fastload_offset
, fastload_length
);
466 if ((fastload
= (char *)malloc( fastload_length
)) != NULL
)
468 lseek( fd
, mz_header
.ne_offset
+ fastload_offset
, SEEK_SET
);
469 if (read( fd
, fastload
, fastload_length
) != fastload_length
)
477 /* Store the filename information */
479 pModule
->fileinfo
= (int)pData
- (int)pModule
;
480 ((LOADEDFILEINFO
*)pData
)->length
= sizeof(LOADEDFILEINFO
)+strlen(ofs
->szPathName
);
481 ((LOADEDFILEINFO
*)pData
)->fixed_media
= TRUE
;
482 ((LOADEDFILEINFO
*)pData
)->error
= 0;
483 ((LOADEDFILEINFO
*)pData
)->date
= 0;
484 ((LOADEDFILEINFO
*)pData
)->time
= 0;
485 strcpy( ((LOADEDFILEINFO
*)pData
)->filename
, ofs
->szPathName
);
486 pData
+= ((LOADEDFILEINFO
*)pData
)->length
--;
488 /* Get the segment table */
490 pModule
->seg_table
= (int)pData
- (int)pModule
;
491 buffer
= malloc( ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
) );
495 struct ne_segment_table_entry_s
*pSeg
;
497 if (!READ( ne_header
.segment_tab_offset
,
498 ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
),
499 buffer
)) return (HMODULE
)11; /* invalid exe */
500 pSeg
= (struct ne_segment_table_entry_s
*)buffer
;
501 for (i
= ne_header
.n_segment_tab
; i
> 0; i
--, pSeg
++)
503 memcpy( pData
, pSeg
, sizeof(*pSeg
) );
504 pData
+= sizeof(SEGTABLEENTRY
);
508 else return (HMODULE
)11; /* invalid exe */
510 /* Get the resource table */
512 if (ne_header
.resource_tab_offset
< ne_header
.rname_tab_offset
)
514 pModule
->res_table
= (int)pData
- (int)pModule
;
515 if (!READ(ne_header
.resource_tab_offset
,
516 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
,
517 pData
)) return (HMODULE
)11; /* invalid exe */
518 pData
+= ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
;
520 else pModule
->res_table
= 0; /* No resource table */
522 /* Get the resident names table */
524 pModule
->name_table
= (int)pData
- (int)pModule
;
525 if (!READ( ne_header
.rname_tab_offset
,
526 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
,
527 pData
)) return (HMODULE
)11; /* invalid exe */
528 pData
+= ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
;
530 /* Get the module references table */
532 if (ne_header
.n_mod_ref_tab
> 0)
534 pModule
->modref_table
= (int)pData
- (int)pModule
;
535 if (!READ( ne_header
.moduleref_tab_offset
,
536 ne_header
.n_mod_ref_tab
* sizeof(WORD
),
537 pData
)) return (HMODULE
)11; /* invalid exe */
538 pData
+= ne_header
.n_mod_ref_tab
* sizeof(WORD
);
540 else pModule
->modref_table
= 0; /* No module references */
542 /* Get the imported names table */
544 pModule
->import_table
= (int)pData
- (int)pModule
;
545 if (!READ( ne_header
.iname_tab_offset
,
546 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
,
547 pData
)) return (HMODULE
)11; /* invalid exe */
548 pData
+= ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
;
550 /* Get the entry table */
552 pModule
->entry_table
= (int)pData
- (int)pModule
;
553 if (!READ( ne_header
.entry_tab_offset
,
554 ne_header
.entry_tab_length
,
555 pData
)) return (HMODULE
)11; /* invalid exe */
556 pData
+= ne_header
.entry_tab_length
;
558 /* Get the non-resident names table */
560 if (ne_header
.nrname_tab_length
)
562 pModule
->nrname_handle
= GLOBAL_Alloc( 0, ne_header
.nrname_tab_length
,
563 hModule
, FALSE
, FALSE
, FALSE
);
564 if (!pModule
->nrname_handle
) return (HMODULE
)11; /* invalid exe */
565 buffer
= GlobalLock( pModule
->nrname_handle
);
566 lseek( fd
, ne_header
.nrname_tab_offset
, SEEK_SET
);
567 if (read( fd
, buffer
, ne_header
.nrname_tab_length
)
568 != ne_header
.nrname_tab_length
) return (HMODULE
)11; /* invalid exe */
570 else pModule
->nrname_handle
= 0;
572 /* Allocate a segment for the implicitly-loaded DLLs */
574 if (pModule
->modref_count
)
576 pModule
->dlls_to_init
= GLOBAL_Alloc(GMEM_ZEROINIT
,
577 (pModule
->modref_count
+1)*sizeof(HMODULE
),
578 hModule
, FALSE
, FALSE
, FALSE
);
579 if (!pModule
->dlls_to_init
) return (HMODULE
)11; /* invalid exe */
581 else pModule
->dlls_to_init
= 0;
583 if (debugging_module
) MODULE_PrintModule( hModule
);
584 pModule
->next
= hFirstModule
;
585 hFirstModule
= hModule
;
590 /***********************************************************************
593 * Lookup the ordinal for a given name.
595 WORD
MODULE_GetOrdinal( HMODULE hModule
, char *name
)
597 char buffer
[256], *cpnt
;
601 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
603 dprintf_module( stddeb
, "MODULE_GetOrdinal("NPFMT
",'%s')\n",
606 /* First handle names of the form '#xxxx' */
608 if (name
[0] == '#') return atoi( name
+ 1 );
610 /* Now copy and uppercase the string */
612 strcpy( buffer
, name
);
614 len
= strlen( buffer
);
616 /* First search the resident names */
618 cpnt
= (char *)pModule
+ pModule
->name_table
;
620 /* Skip the first entry (module name) */
621 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
624 dprintf_module( stddeb
, " Checking '%*.*s'\n", *cpnt
, *cpnt
, cpnt
+1 );
625 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
627 dprintf_module( stddeb
, " Found: ordinal=%d\n",
628 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
629 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
631 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
634 /* Now search the non-resident names table */
636 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
637 cpnt
= (char *)GlobalLock( pModule
->nrname_handle
);
639 /* Skip the first entry (module description string) */
640 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
643 dprintf_module( stddeb
, " Checking '%*.*s'\n", *cpnt
, *cpnt
, cpnt
+1 );
644 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
646 dprintf_module( stddeb
, " Found: ordinal=%d\n",
647 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
648 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
650 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
656 /***********************************************************************
657 * MODULE_GetEntryPoint
659 * Return the entry point for a given ordinal.
661 DWORD
MODULE_GetEntryPoint( HMODULE hModule
, WORD ordinal
)
668 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
670 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
671 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
673 /* Skipping this bundle */
677 case 0: p
+= 2; break; /* unused */
678 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
679 default: p
+= 2 + *p
* 3; break; /* fixed */
688 case 0xff: /* moveable */
689 p
+= 2 + 6 * (ordinal
- curOrdinal
);
691 offset
= *(WORD
*)(p
+ 4);
695 p
+= 2 + 3 * (ordinal
- curOrdinal
);
696 offset
= *(WORD
*)(p
+ 1);
700 if (sel
== 0xfe) sel
= 0xffff; /* constant entry */
701 else sel
= NE_SEG_TABLE(pModule
)[sel
-1].selector
;
702 return MAKELONG( offset
, sel
);
706 /***********************************************************************
707 * MODULE_SetEntryPoint
709 * Change the value of an entry point. Use with caution!
710 * It can only change the offset value, not the selector.
712 BOOL
MODULE_SetEntryPoint( HMODULE hModule
, WORD ordinal
, WORD offset
)
718 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
720 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
721 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
723 /* Skipping this bundle */
727 case 0: p
+= 2; break; /* unused */
728 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
729 default: p
+= 2 + *p
* 3; break; /* fixed */
732 if (!*p
) return FALSE
;
738 case 0xff: /* moveable */
739 p
+= 2 + 6 * (ordinal
- curOrdinal
);
740 *(WORD
*)(p
+ 4) = offset
;
743 p
+= 2 + 3 * (ordinal
- curOrdinal
);
744 *(WORD
*)(p
+ 1) = offset
;
751 /***********************************************************************
752 * MODULE_GetEntryPointName
754 * Return the entry point name for a given ordinal.
755 * Used only by relay debugging.
756 * Warning: returned pointer is to a Pascal-type string.
758 LPSTR
MODULE_GetEntryPointName( HMODULE hModule
, WORD ordinal
)
763 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
765 /* First search the resident names */
767 cpnt
= (char *)pModule
+ pModule
->name_table
;
770 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
771 if (*(WORD
*)(cpnt
+ *cpnt
+ 1) == ordinal
) return cpnt
;
774 /* Now search the non-resident names table */
776 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
777 cpnt
= (char *)GlobalLock( pModule
->nrname_handle
);
780 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
781 if (*(WORD
*)(cpnt
+ *cpnt
+ 1) == ordinal
) return cpnt
;
787 /***********************************************************************
788 * MODULE_GetModuleName
790 LPSTR
MODULE_GetModuleName( HMODULE hModule
)
794 static char buffer
[10];
796 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return NULL
;
797 p
= (BYTE
*)pModule
+ pModule
->name_table
;
799 memcpy( buffer
, p
+ 1, len
);
805 /**********************************************************************
808 * Find a module from a path name.
810 HMODULE
MODULE_FindModule( LPCSTR path
)
812 HMODULE hModule
= hFirstModule
;
813 LPCSTR filename
, dotptr
, modulepath
, modulename
;
814 BYTE len
, *name_table
;
816 if (!(filename
= strrchr( path
, '\\' ))) filename
= path
;
818 if ((dotptr
= strrchr( filename
, '.' )) != NULL
)
819 len
= (BYTE
)(dotptr
- filename
);
820 else len
= strlen( filename
);
824 NE_MODULE
*pModule
= (NE_MODULE
*)GlobalLock( hModule
);
826 modulepath
= ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
;
827 if (!(modulename
= strrchr( modulepath
, '\\' )))
828 modulename
= modulepath
;
830 if (!strcasecmp( modulename
, filename
)) return hModule
;
832 name_table
= (BYTE
*)pModule
+ pModule
->name_table
;
833 if ((*name_table
== len
) && !strncasecmp(filename
, name_table
+1, len
))
835 hModule
= pModule
->next
;
841 /**********************************************************************
844 * Remove a module from memory.
846 static void MODULE_FreeModule( HMODULE hModule
)
848 HMODULE
*hPrevModule
;
850 SEGTABLEENTRY
*pSegment
;
854 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return;
855 if (pModule
->flags
& NE_FFLAGS_BUILTIN
)
856 return; /* Can't free built-in module */
858 /* FIXME: should call the exit code for the library here */
860 /* Remove it from the linked list */
862 hPrevModule
= &hFirstModule
;
863 while (*hPrevModule
&& (*hPrevModule
!= hModule
))
865 hPrevModule
= &((NE_MODULE
*)GlobalLock( *hPrevModule
))->next
;
867 if (*hPrevModule
) *hPrevModule
= pModule
->next
;
869 /* Free all the segments */
871 pSegment
= NE_SEG_TABLE( pModule
);
872 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
874 GlobalFree( pSegment
->selector
);
877 /* Free the referenced modules */
879 pModRef
= NE_MODULE_TABLE( pModule
);
880 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
882 FreeModule( *pModRef
);
885 /* Free the module storage */
887 if (pModule
->nrname_handle
) GlobalFree( pModule
->nrname_handle
);
888 if (pModule
->dlls_to_init
) GlobalFree( pModule
->dlls_to_init
);
889 GlobalFree( hModule
);
891 /* Remove module from cache */
893 if (hCachedModule
== hModule
) hCachedModule
= 0;
897 HINSTANCE
PE_LoadModule(int fd
, OFSTRUCT
*ofs
, LOADPARAMS
* params
);
899 /**********************************************************************
900 * LoadModule (KERNEL.45)
902 HINSTANCE
LoadModule( LPCSTR name
, LPVOID paramBlock
)
905 HANDLE hInstance
, hPrevInstance
;
907 LOADPARAMS
*params
= (LOADPARAMS
*)paramBlock
;
908 #ifndef WINELIB /* JBP: Disabled for now in winelib.a */
909 WORD
*pModRef
, *pDLLs
;
912 hModule
= MODULE_FindModule( name
);
914 if (!hModule
) /* We have to load the module */
918 /* Try to load the built-in first if not disabled */
919 if ((hModule
= MODULE_LoadBuiltin( name
, FALSE
))) return hModule
;
921 if (strchr( name
, '/' )) name
= DOS_GetDosFileName( name
);
922 if ((fd
= OpenFile( name
, &ofs
, OF_READ
)) == -1)
924 /* Now try the built-in even if disabled */
925 if ((hModule
= MODULE_LoadBuiltin( name
, TRUE
)))
927 fprintf( stderr
, "Warning: could not load Windows DLL '%s', using built-in module.\n", name
);
930 return 2; /* File not found */
933 /* Create the module structure */
935 if ((hModule
= MODULE_LoadExeHeader( fd
, &ofs
)) < 32)
938 return PE_LoadModule(fd
,&ofs
,paramBlock
);
940 fprintf( stderr
, "LoadModule: can't load '%s', error=%d\n",
944 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
946 /* Allocate the segments for this module */
948 MODULE_CreateSegments( hModule
);
951 hInstance
= MODULE_CreateInstance( hModule
, (LOADPARAMS
*)paramBlock
);
953 /* Load the referenced DLLs */
955 pModRef
= (WORD
*)((char *)pModule
+ pModule
->modref_table
);
956 pDLLs
= (WORD
*)GlobalLock( pModule
->dlls_to_init
);
957 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
960 BYTE
*pstr
= (BYTE
*)pModule
+ pModule
->import_table
+ *pModRef
;
961 memcpy( buffer
, pstr
+ 1, *pstr
);
962 strcpy( buffer
+ *pstr
, ".dll" );
963 dprintf_module( stddeb
, "Loading '%s'\n", buffer
);
964 if (!(*pModRef
= MODULE_FindModule( buffer
)))
966 /* If the DLL is not loaded yet, load it and store */
967 /* its handle in the list of DLLs to initialize. */
970 if ((hDLL
= LoadModule( buffer
, (LPVOID
)-1 )) == 2) /* file not found */
974 /* Try with prepending the path of the current module */
975 GetModuleFileName( hModule
, buffer
, 256 );
976 if (!(p
= strrchr( buffer
, '\\' ))) p
= buffer
;
977 memcpy( p
+ 1, pstr
+ 1, *pstr
);
978 strcpy( p
+ 1 + *pstr
, ".dll" );
979 hDLL
= LoadModule( buffer
, (LPVOID
)-1 );
983 fprintf( stderr
, "Could not load '%s' required by '%s', error = %d\n",
984 buffer
, name
, hDLL
);
985 return 2; /* file not found */
987 *pModRef
= GetExePtr( hDLL
);
990 else /* Increment the reference count of the DLL */
992 NE_MODULE
*pOldDLL
= (NE_MODULE
*)GlobalLock( *pModRef
);
993 if (pOldDLL
) pOldDLL
->count
++;
997 /* Load the segments */
999 if (pModule
->flags
& NE_FFLAGS_SELFLOAD
)
1001 /* Handle self loading modules */
1002 SEGTABLEENTRY
* pSegTable
= (SEGTABLEENTRY
*) NE_SEG_TABLE(pModule
);
1003 SELFLOADHEADER
*selfloadheader
;
1004 HMODULE hselfload
= GetModuleHandle("WINPROCS");
1005 WORD oldss
, oldsp
, saved_dgroup
= pSegTable
[pModule
->dgroup
- 1].selector
;
1006 fprintf (stderr
, "Warning: %*.*s is a self-loading module\n"
1007 "Support for self-loading modules is very experimental\n",
1008 *((BYTE
*)pModule
+ pModule
->name_table
),
1009 *((BYTE
*)pModule
+ pModule
->name_table
),
1010 (char *)pModule
+ pModule
->name_table
+ 1);
1011 NE_LoadSegment( hModule
, 1 );
1012 selfloadheader
= (SELFLOADHEADER
*)
1013 PTR_SEG_OFF_TO_LIN(pSegTable
->selector
, 0);
1014 selfloadheader
->EntryAddrProc
=
1015 MODULE_GetEntryPoint(hselfload
,27);
1016 selfloadheader
->MyAlloc
= MODULE_GetEntryPoint(hselfload
,28);
1017 selfloadheader
->SetOwner
= MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1018 pModule
->self_loading_sel
= GlobalHandleToSel(
1019 GLOBAL_Alloc (GMEM_ZEROINIT
,
1020 0xFF00, hModule
, FALSE
, FALSE
, FALSE
)
1022 oldss
= IF1632_Saved16_ss
;
1023 oldsp
= IF1632_Saved16_sp
;
1024 IF1632_Saved16_ss
= pModule
->self_loading_sel
;
1025 IF1632_Saved16_sp
= 0xFF00;
1026 CallTo16_word_ww (selfloadheader
->BootApp
,
1027 pModule
->self_loading_sel
, hModule
, fd
);
1028 /* some BootApp procs overwrite the selector of dgroup */
1029 pSegTable
[pModule
->dgroup
- 1].selector
= saved_dgroup
;
1030 IF1632_Saved16_ss
= oldss
;
1031 IF1632_Saved16_sp
= oldsp
;
1032 for (i
= 2; i
<= pModule
->seg_count
; i
++) NE_LoadSegment( hModule
, i
);
1036 for (i
= 1; i
<= pModule
->seg_count
; i
++)
1037 NE_LoadSegment( hModule
, i
);
1040 /* Fixup the functions prologs */
1042 NE_FixupPrologs( hModule
);
1044 /* Make sure the usage count is 1 on the first loading of */
1045 /* the module, even if it contains circular DLL references */
1049 /* Clear built-in flag in case it was set in the EXE file */
1051 pModule
->flags
&= ~NE_FFLAGS_BUILTIN
;
1055 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
1056 hPrevInstance
= MODULE_GetInstance( hModule
);
1057 hInstance
= MODULE_CreateInstance( hModule
, params
);
1058 if (hInstance
!= hPrevInstance
) /* not a library */
1059 NE_LoadSegment( hModule
, pModule
->dgroup
);
1063 hModule
= GlobalAlloc( GMEM_MOVEABLE
| GMEM_ZEROINIT
, sizeof(NE_MODULE
) );
1064 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
1066 pModule
->magic
= 0x454e;
1068 hInstance
= MODULE_CreateInstance( hModule
, (LOADPARAMS
*)paramBlock
);
1069 #endif /* WINELIB */
1071 /* Create a task for this instance */
1073 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
) && (paramBlock
!= (LPVOID
)-1))
1075 TASK_CreateTask( hModule
, hInstance
, hPrevInstance
,
1076 params
->hEnvironment
,
1077 (LPSTR
)PTR_SEG_TO_LIN( params
->cmdLine
),
1078 *((WORD
*)PTR_SEG_TO_LIN(params
->showCmd
)+1) );
1085 /**********************************************************************
1086 * FreeModule (KERNEL.46)
1088 BOOL
FreeModule( HANDLE hModule
)
1092 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1093 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
1095 dprintf_module( stddeb
, "FreeModule: %s count %d\n",
1096 MODULE_GetModuleName(hModule
), pModule
->count
);
1097 if (--pModule
->count
== 0) MODULE_FreeModule( hModule
);
1102 /**********************************************************************
1103 * GetModuleHandle (KERNEL.47)
1105 HMODULE
WIN16_GetModuleHandle( SEGPTR name
)
1108 if (HIWORD(name
) == 0) return GetExePtr( name
);
1110 if (HIWORD(name
) == 0) return GetExePtr( LOWORD(name
) );
1112 return MODULE_FindModule( PTR_SEG_TO_LIN(name
) );
1115 HMODULE
GetModuleHandle( LPCSTR name
)
1117 return MODULE_FindModule( name
);
1121 /**********************************************************************
1122 * GetModuleUsage (KERNEL.48)
1124 int GetModuleUsage( HANDLE hModule
)
1128 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1129 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
1130 dprintf_module( stddeb
, "GetModuleUsage("NPFMT
"): returning %d\n",
1131 hModule
, pModule
->count
);
1132 return pModule
->count
;
1136 /**********************************************************************
1137 * GetModuleFileName (KERNEL.49)
1139 int GetModuleFileName( HANDLE hModule
, LPSTR lpFileName
, short nSize
)
1144 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1145 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
1146 name
= ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
;
1147 strncpy( lpFileName
, name
, nSize
);
1148 lpFileName
[nSize
-1] = '\0';
1149 dprintf_module( stddeb
, "GetModuleFilename: %s\n", lpFileName
);
1150 return strlen(lpFileName
);
1154 /***********************************************************************
1155 * LoadLibrary (KERNEL.95)
1157 HANDLE
LoadLibrary( LPCSTR libname
)
1161 dprintf_module( stddeb
, "LoadLibrary: (%08x) %s\n", (int)libname
, libname
);
1162 /* This does not increment the module reference count, and will
1163 * therefore cause crashes on FreeLibrary calls.
1164 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1166 handle
= LoadModule( libname
, (LPVOID
)-1 );
1167 if (handle
== (HANDLE
)2) /* file not found */
1170 strcpy( buffer
, libname
);
1171 strcat( buffer
, ".dll" );
1172 handle
= LoadModule( buffer
, (LPVOID
)-1 );
1174 if (handle
>= (HANDLE
)32) NE_InitializeDLLs( GetExePtr(handle
) );
1179 /***********************************************************************
1180 * FreeLibrary (KERNEL.96)
1182 void FreeLibrary( HANDLE handle
)
1184 dprintf_module( stddeb
,"FreeLibrary: "NPFMT
"\n", handle
);
1185 FreeModule( handle
);
1189 /***********************************************************************
1190 * WinExec (KERNEL.166)
1192 HANDLE
WinExec( LPSTR lpCmdLine
, WORD nCmdShow
)
1195 HLOCAL cmdShowHandle
, cmdLineHandle
;
1198 char *p
, *cmdline
, filename
[256];
1200 if (!(cmdShowHandle
= GlobalAlloc( 0, 2 * sizeof(WORD
) ))) return 0;
1201 if (!(cmdLineHandle
= GlobalAlloc( 0, 256 ))) return 0;
1203 /* Store nCmdShow */
1205 cmdShowPtr
= (WORD
*)GlobalLock( cmdShowHandle
);
1207 cmdShowPtr
[1] = nCmdShow
;
1209 /* Build the filename and command-line */
1211 cmdline
= (char *)GlobalLock( cmdLineHandle
);
1212 strncpy( filename
, lpCmdLine
, 256 );
1213 filename
[255] = '\0';
1214 for (p
= filename
; *p
&& (*p
!= ' ') && (*p
!= '\t'); p
++);
1217 strncpy( cmdline
, p
+ 1, 128 );
1218 cmdline
[127] = '\0';
1220 else cmdline
[0] = '\0';
1223 /* Now load the executable file */
1225 params
.hEnvironment
= (HANDLE
)SELECTOROF( GetDOSEnvironment() );
1226 params
.cmdLine
= (SEGPTR
)WIN16_GlobalLock( cmdLineHandle
);
1227 params
.showCmd
= (SEGPTR
)WIN16_GlobalLock( cmdShowHandle
);
1228 params
.reserved
= 0;
1229 handle
= LoadModule( filename
, ¶ms
);
1230 if (handle
== (HANDLE
)2) /* file not found */
1232 strcat( filename
, ".exe" );
1233 handle
= LoadModule( filename
, ¶ms
);
1236 GlobalFree( cmdShowHandle
);
1237 GlobalFree( cmdLineHandle
);
1238 Yield(); /* program is executed immediatly ....needed for word */
1243 /***********************************************************************
1244 * GetProcAddress (KERNEL.50)
1246 FARPROC
GetProcAddress( HANDLE hModule
, SEGPTR name
)
1251 if (!hModule
) hModule
= GetCurrentTask();
1252 hModule
= GetExePtr( hModule
);
1254 if (HIWORD(name
) != 0)
1256 ordinal
= MODULE_GetOrdinal( hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1257 dprintf_module( stddeb
, "GetProcAddress: "NPFMT
" '%s'\n",
1258 hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1262 ordinal
= LOWORD(name
);
1263 dprintf_module( stddeb
, "GetProcAddress: "NPFMT
" %04x\n",
1266 if (!ordinal
) return (FARPROC
)0;
1268 ret
= MODULE_GetEntryPoint( hModule
, ordinal
);
1270 dprintf_module( stddeb
, "GetProcAddress: returning %08lx\n", ret
);
1271 return (FARPROC
)ret
;
1276 /***********************************************************************
1277 * GetWndProcEntry16 (not a Windows API function)
1279 * Return an entry point from the WINPROCS dll.
1281 WNDPROC
GetWndProcEntry16( char *name
)
1284 static HMODULE hModule
= 0;
1286 if (!hModule
) hModule
= GetModuleHandle( "WINPROCS" );
1287 ordinal
= MODULE_GetOrdinal( hModule
, name
);
1288 return MODULE_GetEntryPoint( hModule
, ordinal
);
1293 /**********************************************************************
1294 * ModuleFirst (TOOLHELP.59)
1296 BOOL
ModuleFirst( MODULEENTRY
*lpme
)
1298 lpme
->wNext
= hFirstModule
;
1299 return ModuleNext( lpme
);
1303 /**********************************************************************
1304 * ModuleNext (TOOLHELP.60)
1306 BOOL
ModuleNext( MODULEENTRY
*lpme
)
1310 if (!lpme
->wNext
) return FALSE
;
1311 if (!(pModule
= (NE_MODULE
*)GlobalLock( lpme
->wNext
))) return FALSE
;
1312 strncpy( lpme
->szModule
, (char *)pModule
+ pModule
->name_table
,
1314 lpme
->szModule
[MAX_MODULE_NAME
] = '\0';
1315 lpme
->hModule
= lpme
->wNext
;
1316 lpme
->wcUsage
= pModule
->count
;
1317 strncpy( lpme
->szExePath
,
1318 ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
,
1320 lpme
->szExePath
[MAX_PATH
] = '\0';
1321 lpme
->wNext
= pModule
->next
;
1326 /**********************************************************************
1327 * ModuleFindName (TOOLHELP.61)
1329 BOOL
ModuleFindName( MODULEENTRY
*lpme
, LPCSTR name
)
1331 lpme
->wNext
= GetModuleHandle( name
);
1332 return ModuleNext( lpme
);
1336 /**********************************************************************
1337 * ModuleFindHandle (TOOLHELP.62)
1339 BOOL
ModuleFindHandle( MODULEENTRY
*lpme
, HMODULE hModule
)
1341 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1342 lpme
->wNext
= hModule
;
1343 return ModuleNext( lpme
);