4 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
20 #include "stackframe.h"
29 static HMODULE hFirstModule
= 0;
30 static HMODULE hCachedModule
= 0; /* Module cached by MODULE_OpenFile */
33 static HANDLE hInitialStack32
= 0;
34 /***********************************************************************
37 * Load a built-in module. If the 'force' parameter is FALSE, we only
38 * load the module if it has not been disabled via the -dll option.
40 #ifndef WINELIB /* JBP: Not really allowed in libwine.a (FIXME:?) */
41 static HMODULE
MODULE_LoadBuiltin( LPCSTR name
, BOOL force
)
45 SEGTABLEENTRY
*pSegTable
;
46 struct dll_table_s
*table
;
50 /* Fix the name in case we have a full path and extension */
52 if ((p
= strrchr( name
, '\\' ))) name
= p
+ 1;
53 strncpy( dllname
, name
, 15 );
55 if ((p
= strrchr( dllname
, '.' ))) *p
= '\0';
57 for (i
= 0, table
= dll_builtin_table
; i
< N_BUILTINS
; i
++, table
++)
58 if (!strcasecmp( table
->name
, dllname
)) break;
59 if (i
>= N_BUILTINS
) return 0;
60 if (!table
->used
&& !force
) return 0;
62 hModule
= GLOBAL_CreateBlock( GMEM_MOVEABLE
, table
->module_start
,
63 table
->module_end
- table
->module_start
,
64 0, FALSE
, FALSE
, FALSE
, NULL
);
65 if (!hModule
) return 0;
66 FarSetOwner( hModule
, hModule
);
68 table
->hModule
= hModule
;
70 dprintf_module( stddeb
, "Built-in %s: hmodule=%04x\n",
71 table
->name
, hModule
);
73 /* Allocate the code segment */
75 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
76 pSegTable
= NE_SEG_TABLE( pModule
);
78 pSegTable
->selector
= GLOBAL_CreateBlock( GMEM_FIXED
, table
->code_start
,
79 pSegTable
->minsize
, hModule
,
80 TRUE
, TRUE
, FALSE
, NULL
);
81 if (!pSegTable
->selector
) return 0;
84 /* Allocate the data segment */
86 pSegTable
->selector
= GLOBAL_Alloc( GMEM_FIXED
, pSegTable
->minsize
,
87 hModule
, FALSE
, FALSE
, FALSE
);
88 if (!pSegTable
->selector
) return 0;
89 memcpy( GlobalLock( pSegTable
->selector
),
90 table
->data_start
, pSegTable
->minsize
);
92 pModule
->next
= hFirstModule
;
93 hFirstModule
= hModule
;
98 /***********************************************************************
101 * Create the built-in modules.
103 BOOL
MODULE_Init(void)
105 /* For these, built-in modules are always used */
108 if (!MODULE_LoadBuiltin( "KERNEL", TRUE
) ||
109 !MODULE_LoadBuiltin( "GDI", TRUE
) ||
110 !MODULE_LoadBuiltin( "USER", TRUE
) ||
111 !MODULE_LoadBuiltin( "WINPROCS", TRUE
)) return FALSE
;
114 fprintf(stderr
, "JBP: MODULE_Init() ignored.\n");
116 /* Initialize KERNEL.178 (__WINFLAGS) with the correct flags value */
118 MODULE_SetEntryPoint( GetModuleHandle( "KERNEL" ), 178, GetWinFlags() );
123 /***********************************************************************
126 void MODULE_PrintModule( HMODULE hmodule
)
132 NE_MODULE
*pModule
= (NE_MODULE
*)GlobalLock( hmodule
);
134 /* Dump the module info */
136 printf( "Module "NPFMT
":\n", hmodule
);
137 printf( "count=%d flags=%04x heap=%d stack=%d\n",
138 pModule
->count
, pModule
->flags
,
139 pModule
->heap_size
, pModule
->stack_size
);
140 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
141 pModule
->cs
, pModule
->ip
, pModule
->ss
, pModule
->sp
, pModule
->dgroup
,
142 pModule
->seg_count
, pModule
->modref_count
);
143 printf( "os_flags=%d swap_area=%d version=%04x\n",
144 pModule
->os_flags
, pModule
->min_swap_area
,
145 pModule
->expected_version
);
147 /* Dump the file info */
149 printf( "Filename: '%s'\n",
150 ((LOADEDFILEINFO
*)((BYTE
*)pModule
+ pModule
->fileinfo
))->filename
);
152 /* Dump the segment table */
154 printf( "\nSegment table:\n" );
155 pSeg
= NE_SEG_TABLE( pModule
);
156 for (i
= 0; i
< pModule
->seg_count
; i
++, pSeg
++)
157 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel="NPFMT
"\n",
158 i
+ 1, pSeg
->filepos
, pSeg
->size
, pSeg
->flags
,
159 pSeg
->minsize
, pSeg
->selector
);
161 /* Dump the resource table */
163 printf( "\nResource table:\n" );
164 if (pModule
->res_table
)
166 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->res_table
);
167 printf( "Alignment: %d\n", *pword
++ );
170 struct resource_typeinfo_s
*ptr
= (struct resource_typeinfo_s
*)pword
;
171 struct resource_nameinfo_s
*pname
= (struct resource_nameinfo_s
*)(ptr
+ 1);
172 printf( "id=%04x count=%d\n", ptr
->type_id
, ptr
->count
);
173 for (i
= 0; i
< ptr
->count
; i
++, pname
++)
174 printf( "offset=%d len=%d id=%04x\n",
175 pname
->offset
, pname
->length
, pname
->id
);
176 pword
= (WORD
*)pname
;
179 else printf( "None\n" );
181 /* Dump the resident name table */
183 printf( "\nResident-name table:\n" );
184 pstr
= (char *)pModule
+ pModule
->name_table
;
187 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
188 *(WORD
*)(pstr
+ *pstr
+ 1) );
189 pstr
+= *pstr
+ 1 + sizeof(WORD
);
192 /* Dump the module reference table */
194 printf( "\nModule ref table:\n" );
195 if (pModule
->modref_table
)
197 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->modref_table
);
198 for (i
= 0; i
< pModule
->modref_count
; i
++, pword
++)
200 char *name
= (char *)pModule
+ pModule
->import_table
+ *pword
;
201 printf( "%d: %04x -> '%*.*s'\n",
202 i
, *pword
, *name
, *name
, name
+ 1 );
205 else printf( "None\n" );
207 /* Dump the entry table */
209 printf( "\nEntry table:\n" );
210 pstr
= (char *)pModule
+ pModule
->entry_table
;
214 printf( "Bundle %d-%d: %02x\n", ordinal
, ordinal
+ *pstr
- 1, pstr
[1]);
220 else if ((BYTE
)pstr
[1] == 0xff) /* moveable */
222 struct entry_tab_movable_s
*pe
= (struct entry_tab_movable_s
*)(pstr
+2);
223 for (i
= 0; i
< *pstr
; i
++, pe
++)
224 printf( "%d: %02x:%04x (moveable)\n",
225 ordinal
++, pe
->seg_number
, pe
->offset
);
230 struct entry_tab_fixed_s
*pe
= (struct entry_tab_fixed_s
*)(pstr
+2);
231 for (i
= 0; i
< *pstr
; i
++, pe
++)
232 printf( "%d: %04x (fixed)\n",
233 ordinal
++, pe
->offset
[0] + (pe
->offset
[1] << 8) );
238 /* Dump the non-resident names table */
240 printf( "\nNon-resident names table:\n" );
241 if (pModule
->nrname_handle
)
243 pstr
= (char *)GlobalLock( pModule
->nrname_handle
);
246 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
247 *(WORD
*)(pstr
+ *pstr
+ 1) );
248 pstr
+= *pstr
+ 1 + sizeof(WORD
);
255 /***********************************************************************
258 int MODULE_OpenFile( HMODULE hModule
)
263 static int cachedfd
= -1;
265 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
266 dprintf_module( stddeb
, "MODULE_OpenFile("NPFMT
") cache: mod="NPFMT
" fd=%d\n",
267 hModule
, hCachedModule
, cachedfd
);
268 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return -1;
269 if (hCachedModule
== hModule
) return cachedfd
;
271 hCachedModule
= hModule
;
272 name
= ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
;
273 cachedfd
= open( DOS_GetUnixFileName( name
), O_RDONLY
);
274 dprintf_module( stddeb
, "MODULE_OpenFile: opened '%s' -> %d\n",
278 /***********************************************************************
282 /* This function translates NE segment flags to GlobalAlloc flags */
284 static WORD
MODULE_Ne2MemFlags(WORD flags
)
288 if (flags
& NE_SEGFLAGS_DISCARDABLE
)
289 memflags
|= GMEM_DISCARDABLE
;
290 if (flags
& NE_SEGFLAGS_MOVEABLE
||
291 ( ! (flags
& NE_SEGFLAGS_DATA
) &&
292 ! (flags
& NE_SEGFLAGS_LOADED
) &&
293 ! (flags
& NE_SEGFLAGS_ALLOCATED
)
296 memflags
|= GMEM_MOVEABLE
;
297 memflags
|= GMEM_ZEROINIT
;
299 memflags
= GMEM_ZEROINIT
| GMEM_FIXED
;
304 /***********************************************************************
305 * MODULE_AllocateSegment (WINPROCS.26)
308 DWORD
MODULE_AllocateSegment(WORD wFlags
, WORD wSize
, WORD wElem
)
310 WORD size
= wSize
<< wElem
;
311 HANDLE hMem
= GlobalAlloc( MODULE_Ne2MemFlags(wFlags
), size
);
313 return (DWORD
)GlobalLock(hMem
);
315 WORD selector
= HIWORD(GlobalLock(hMem
));
316 return MAKELONG(hMem
, selector
);
320 /***********************************************************************
321 * MODULE_CreateSegments
324 static BOOL
MODULE_CreateSegments( HMODULE hModule
)
326 SEGTABLEENTRY
*pSegment
;
330 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
331 pSegment
= NE_SEG_TABLE( pModule
);
332 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
334 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
335 if (i
== pModule
->ss
) minsize
+= pModule
->stack_size
;
336 /* The DGROUP is allocated by MODULE_CreateInstance */
337 if (i
== pModule
->dgroup
) continue;
338 pSegment
->selector
= GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment
->flags
),
340 !(pSegment
->flags
& NE_SEGFLAGS_DATA
),
342 FALSE
/*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
343 if (!pSegment
->selector
) return FALSE
;
346 pModule
->dgroup_entry
= pModule
->dgroup
? pModule
->seg_table
+
347 (pModule
->dgroup
- 1) * sizeof(SEGTABLEENTRY
) : 0;
353 /***********************************************************************
357 static HINSTANCE
MODULE_GetInstance( HMODULE hModule
)
359 SEGTABLEENTRY
*pSegment
;
362 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
363 if (pModule
->dgroup
== 0) return hModule
;
365 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
367 return pSegment
->selector
;
372 /***********************************************************************
373 * MODULE_CreateInstance
375 HINSTANCE
MODULE_CreateInstance( HMODULE hModule
, LOADPARAMS
*params
)
377 SEGTABLEENTRY
*pSegment
;
380 HINSTANCE hNewInstance
, hPrevInstance
;
382 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
383 if (pModule
->dgroup
== 0) return hModule
;
385 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
386 hPrevInstance
= pSegment
->selector
;
388 /* if it's a library, create a new instance only the first time */
391 if (pModule
->flags
& NE_FFLAGS_LIBMODULE
) return hPrevInstance
;
392 if (params
== (LOADPARAMS
*)-1) return hPrevInstance
;
395 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
396 if (pModule
->ss
== pModule
->dgroup
) minsize
+= pModule
->stack_size
;
397 minsize
+= pModule
->heap_size
;
398 hNewInstance
= GLOBAL_Alloc( GMEM_ZEROINIT
| GMEM_FIXED
,
399 minsize
, hModule
, FALSE
, FALSE
, FALSE
);
400 if (!hNewInstance
) return 0;
401 pSegment
->selector
= hNewInstance
;
406 /***********************************************************************
407 * MODULE_LoadExeHeader
409 HMODULE
MODULE_LoadExeHeader( int fd
, OFSTRUCT
*ofs
)
411 struct mz_header_s mz_header
;
412 struct ne_header_s ne_header
;
417 char *buffer
, *fastload
= NULL
;
418 int fastload_offset
= 0, fastload_length
= 0;
420 /* Read a block from either the file or the fast-load area. */
421 #define READ(offset,size,buffer) \
422 ((fastload && ((offset) >= fastload_offset) && \
423 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
424 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
425 (lseek( fd, mz_header.ne_offset+(offset), SEEK_SET), \
426 read( fd, (buffer), (size) ) == (size)))
428 lseek( fd
, 0, SEEK_SET
);
429 if ((read( fd
, &mz_header
, sizeof(mz_header
) ) != sizeof(mz_header
)) ||
430 (mz_header
.mz_magic
!= MZ_SIGNATURE
)) return (HMODULE
)11; /* invalid exe */
432 lseek( fd
, mz_header
.ne_offset
, SEEK_SET
);
433 if (read( fd
, &ne_header
, sizeof(ne_header
) ) != sizeof(ne_header
))
434 return (HMODULE
)11; /* invalid exe */
436 if (ne_header
.ne_magic
== PE_SIGNATURE
) return (HMODULE
)21; /* win32 exe */
437 if (ne_header
.ne_magic
!= NE_SIGNATURE
) return (HMODULE
)11; /* invalid exe */
439 /* We now have a valid NE header */
441 size
= sizeof(NE_MODULE
) +
442 /* loaded file info */
443 sizeof(LOADEDFILEINFO
) + strlen(ofs
->szPathName
) +
445 ne_header
.n_segment_tab
* sizeof(SEGTABLEENTRY
) +
447 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
+
448 /* resident names table */
449 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
+
450 /* module ref table */
451 ne_header
.n_mod_ref_tab
* sizeof(WORD
) +
452 /* imported names table */
453 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
+
454 /* entry table length */
455 ne_header
.entry_tab_length
;
457 hModule
= GlobalAlloc( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
458 if (!hModule
) return (HMODULE
)11; /* invalid exe */
459 FarSetOwner( hModule
, hModule
);
460 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
461 memcpy( pModule
, &ne_header
, sizeof(NE_MODULE
) );
463 pData
= (BYTE
*)(pModule
+ 1);
465 /* Read the fast-load area */
467 if (ne_header
.additional_flags
& NE_AFLAGS_FASTLOAD
)
469 fastload_offset
=ne_header
.fastload_offset
<<ne_header
.align_shift_count
;
470 fastload_length
=ne_header
.fastload_length
<<ne_header
.align_shift_count
;
471 dprintf_module( stddeb
, "Using fast-load area offset=%x len=%d\n",
472 fastload_offset
, fastload_length
);
473 if ((fastload
= (char *)malloc( fastload_length
)) != NULL
)
475 lseek( fd
, mz_header
.ne_offset
+ fastload_offset
, SEEK_SET
);
476 if (read( fd
, fastload
, fastload_length
) != fastload_length
)
484 /* Store the filename information */
486 pModule
->fileinfo
= (int)pData
- (int)pModule
;
487 ((LOADEDFILEINFO
*)pData
)->length
= sizeof(LOADEDFILEINFO
)+strlen(ofs
->szPathName
);
488 ((LOADEDFILEINFO
*)pData
)->fixed_media
= TRUE
;
489 ((LOADEDFILEINFO
*)pData
)->error
= 0;
490 ((LOADEDFILEINFO
*)pData
)->date
= 0;
491 ((LOADEDFILEINFO
*)pData
)->time
= 0;
492 strcpy( ((LOADEDFILEINFO
*)pData
)->filename
, ofs
->szPathName
);
493 pData
+= ((LOADEDFILEINFO
*)pData
)->length
--;
495 /* Get the segment table */
497 pModule
->seg_table
= (int)pData
- (int)pModule
;
498 buffer
= malloc( ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
) );
502 struct ne_segment_table_entry_s
*pSeg
;
504 if (!READ( ne_header
.segment_tab_offset
,
505 ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
),
506 buffer
)) return (HMODULE
)11; /* invalid exe */
507 pSeg
= (struct ne_segment_table_entry_s
*)buffer
;
508 for (i
= ne_header
.n_segment_tab
; i
> 0; i
--, pSeg
++)
510 memcpy( pData
, pSeg
, sizeof(*pSeg
) );
511 pData
+= sizeof(SEGTABLEENTRY
);
515 else return (HMODULE
)11; /* invalid exe */
517 /* Get the resource table */
519 if (ne_header
.resource_tab_offset
< ne_header
.rname_tab_offset
)
521 pModule
->res_table
= (int)pData
- (int)pModule
;
522 if (!READ(ne_header
.resource_tab_offset
,
523 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
,
524 pData
)) return (HMODULE
)11; /* invalid exe */
525 pData
+= ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
;
527 else pModule
->res_table
= 0; /* No resource table */
529 /* Get the resident names table */
531 pModule
->name_table
= (int)pData
- (int)pModule
;
532 if (!READ( ne_header
.rname_tab_offset
,
533 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
,
534 pData
)) return (HMODULE
)11; /* invalid exe */
535 pData
+= ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
;
537 /* Get the module references table */
539 if (ne_header
.n_mod_ref_tab
> 0)
541 pModule
->modref_table
= (int)pData
- (int)pModule
;
542 if (!READ( ne_header
.moduleref_tab_offset
,
543 ne_header
.n_mod_ref_tab
* sizeof(WORD
),
544 pData
)) return (HMODULE
)11; /* invalid exe */
545 pData
+= ne_header
.n_mod_ref_tab
* sizeof(WORD
);
547 else pModule
->modref_table
= 0; /* No module references */
549 /* Get the imported names table */
551 pModule
->import_table
= (int)pData
- (int)pModule
;
552 if (!READ( ne_header
.iname_tab_offset
,
553 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
,
554 pData
)) return (HMODULE
)11; /* invalid exe */
555 pData
+= ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
;
557 /* Get the entry table */
559 pModule
->entry_table
= (int)pData
- (int)pModule
;
560 if (!READ( ne_header
.entry_tab_offset
,
561 ne_header
.entry_tab_length
,
562 pData
)) return (HMODULE
)11; /* invalid exe */
563 pData
+= ne_header
.entry_tab_length
;
565 /* Get the non-resident names table */
567 if (ne_header
.nrname_tab_length
)
569 pModule
->nrname_handle
= GLOBAL_Alloc( 0, ne_header
.nrname_tab_length
,
570 hModule
, FALSE
, FALSE
, FALSE
);
571 if (!pModule
->nrname_handle
) return (HMODULE
)11; /* invalid exe */
572 buffer
= GlobalLock( pModule
->nrname_handle
);
573 lseek( fd
, ne_header
.nrname_tab_offset
, SEEK_SET
);
574 if (read( fd
, buffer
, ne_header
.nrname_tab_length
)
575 != ne_header
.nrname_tab_length
) return (HMODULE
)11; /* invalid exe */
577 else pModule
->nrname_handle
= 0;
579 /* Allocate a segment for the implicitly-loaded DLLs */
581 if (pModule
->modref_count
)
583 pModule
->dlls_to_init
= GLOBAL_Alloc(GMEM_ZEROINIT
,
584 (pModule
->modref_count
+1)*sizeof(HMODULE
),
585 hModule
, FALSE
, FALSE
, FALSE
);
586 if (!pModule
->dlls_to_init
) return (HMODULE
)11; /* invalid exe */
588 else pModule
->dlls_to_init
= 0;
590 if (debugging_module
) MODULE_PrintModule( hModule
);
591 pModule
->next
= hFirstModule
;
592 hFirstModule
= hModule
;
597 /***********************************************************************
600 * Lookup the ordinal for a given name.
602 WORD
MODULE_GetOrdinal( HMODULE hModule
, char *name
)
604 char buffer
[256], *cpnt
;
608 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
610 dprintf_module( stddeb
, "MODULE_GetOrdinal("NPFMT
",'%s')\n",
613 /* First handle names of the form '#xxxx' */
615 if (name
[0] == '#') return atoi( name
+ 1 );
617 /* Now copy and uppercase the string */
619 strcpy( buffer
, name
);
621 len
= strlen( buffer
);
623 /* First search the resident names */
625 cpnt
= (char *)pModule
+ pModule
->name_table
;
627 /* Skip the first entry (module name) */
628 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
631 dprintf_module( stddeb
, " Checking '%*.*s'\n", *cpnt
, *cpnt
, cpnt
+1 );
632 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
634 dprintf_module( stddeb
, " Found: ordinal=%d\n",
635 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
636 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
638 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
641 /* Now search the non-resident names table */
643 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
644 cpnt
= (char *)GlobalLock( pModule
->nrname_handle
);
646 /* Skip the first entry (module description string) */
647 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
650 dprintf_module( stddeb
, " Checking '%*.*s'\n", *cpnt
, *cpnt
, cpnt
+1 );
651 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
653 dprintf_module( stddeb
, " Found: ordinal=%d\n",
654 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
655 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
657 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
663 /***********************************************************************
664 * MODULE_GetEntryPoint
666 * Return the entry point for a given ordinal.
668 DWORD
MODULE_GetEntryPoint( HMODULE hModule
, WORD ordinal
)
675 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
677 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
678 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
680 /* Skipping this bundle */
684 case 0: p
+= 2; break; /* unused */
685 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
686 default: p
+= 2 + *p
* 3; break; /* fixed */
695 case 0xff: /* moveable */
696 p
+= 2 + 6 * (ordinal
- curOrdinal
);
698 offset
= *(WORD
*)(p
+ 4);
702 p
+= 2 + 3 * (ordinal
- curOrdinal
);
703 offset
= *(WORD
*)(p
+ 1);
707 if (sel
== 0xfe) sel
= 0xffff; /* constant entry */
708 else sel
= NE_SEG_TABLE(pModule
)[sel
-1].selector
;
709 return MAKELONG( offset
, sel
);
713 /***********************************************************************
714 * MODULE_SetEntryPoint
716 * Change the value of an entry point. Use with caution!
717 * It can only change the offset value, not the selector.
719 BOOL
MODULE_SetEntryPoint( HMODULE hModule
, WORD ordinal
, WORD offset
)
725 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
727 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
728 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
730 /* Skipping this bundle */
734 case 0: p
+= 2; break; /* unused */
735 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
736 default: p
+= 2 + *p
* 3; break; /* fixed */
739 if (!*p
) return FALSE
;
745 case 0xff: /* moveable */
746 p
+= 2 + 6 * (ordinal
- curOrdinal
);
747 *(WORD
*)(p
+ 4) = offset
;
750 p
+= 2 + 3 * (ordinal
- curOrdinal
);
751 *(WORD
*)(p
+ 1) = offset
;
758 /***********************************************************************
759 * MODULE_GetEntryPointName
761 * Return the entry point name for a given ordinal.
762 * Used only by relay debugging.
763 * Warning: returned pointer is to a Pascal-type string.
765 LPSTR
MODULE_GetEntryPointName( HMODULE hModule
, WORD ordinal
)
770 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
772 /* First search the resident names */
774 cpnt
= (char *)pModule
+ pModule
->name_table
;
777 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
778 if (*(WORD
*)(cpnt
+ *cpnt
+ 1) == ordinal
) return cpnt
;
781 /* Now search the non-resident names table */
783 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
784 cpnt
= (char *)GlobalLock( pModule
->nrname_handle
);
787 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
788 if (*(WORD
*)(cpnt
+ *cpnt
+ 1) == ordinal
) return cpnt
;
794 /***********************************************************************
795 * MODULE_GetModuleName
797 LPSTR
MODULE_GetModuleName( HMODULE hModule
)
801 static char buffer
[10];
803 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return NULL
;
804 p
= (BYTE
*)pModule
+ pModule
->name_table
;
806 memcpy( buffer
, p
+ 1, len
);
812 /**********************************************************************
815 * Find a module from a path name.
817 HMODULE
MODULE_FindModule( LPCSTR path
)
819 HMODULE hModule
= hFirstModule
;
820 LPCSTR filename
, dotptr
, modulepath
, modulename
;
821 BYTE len
, *name_table
;
823 if (!(filename
= strrchr( path
, '\\' ))) filename
= path
;
825 if ((dotptr
= strrchr( filename
, '.' )) != NULL
)
826 len
= (BYTE
)(dotptr
- filename
);
827 else len
= strlen( filename
);
831 NE_MODULE
*pModule
= (NE_MODULE
*)GlobalLock( hModule
);
833 modulepath
= ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
;
834 if (!(modulename
= strrchr( modulepath
, '\\' )))
835 modulename
= modulepath
;
837 if (!strcasecmp( modulename
, filename
)) return hModule
;
839 name_table
= (BYTE
*)pModule
+ pModule
->name_table
;
840 if ((*name_table
== len
) && !strncasecmp(filename
, name_table
+1, len
))
842 hModule
= pModule
->next
;
848 /**********************************************************************
851 * Remove a module from memory.
853 static void MODULE_FreeModule( HMODULE hModule
)
855 HMODULE
*hPrevModule
;
857 SEGTABLEENTRY
*pSegment
;
861 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return;
862 if (pModule
->flags
& NE_FFLAGS_BUILTIN
)
863 return; /* Can't free built-in module */
865 /* FIXME: should call the exit code for the library here */
867 /* Remove it from the linked list */
869 hPrevModule
= &hFirstModule
;
870 while (*hPrevModule
&& (*hPrevModule
!= hModule
))
872 hPrevModule
= &((NE_MODULE
*)GlobalLock( *hPrevModule
))->next
;
874 if (*hPrevModule
) *hPrevModule
= pModule
->next
;
876 /* Free all the segments */
878 pSegment
= NE_SEG_TABLE( pModule
);
879 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
881 GlobalFree( pSegment
->selector
);
884 /* Free the referenced modules */
886 pModRef
= NE_MODULE_TABLE( pModule
);
887 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
889 FreeModule( *pModRef
);
892 /* Free the module storage */
894 if (pModule
->nrname_handle
) GlobalFree( pModule
->nrname_handle
);
895 if (pModule
->dlls_to_init
) GlobalFree( pModule
->dlls_to_init
);
896 GlobalFree( hModule
);
898 /* Remove module from cache */
900 if (hCachedModule
== hModule
) hCachedModule
= 0;
904 HINSTANCE
PE_LoadModule(int fd
, OFSTRUCT
*ofs
, LOADPARAMS
* params
);
906 /**********************************************************************
907 * LoadModule (KERNEL.45)
909 HINSTANCE
LoadModule( LPCSTR name
, LPVOID paramBlock
)
912 HANDLE hInstance
, hPrevInstance
;
914 LOADPARAMS
*params
= (LOADPARAMS
*)paramBlock
;
915 #ifndef WINELIB /* JBP: Disabled for now in winelib.a */
916 WORD
*pModRef
, *pDLLs
;
919 hModule
= MODULE_FindModule( name
);
921 if (!hModule
) /* We have to load the module */
925 /* Try to load the built-in first if not disabled */
926 if ((hModule
= MODULE_LoadBuiltin( name
, FALSE
))) return hModule
;
928 if (strchr( name
, '/' )) name
= DOS_GetDosFileName( name
);
929 if ((fd
= OpenFile( name
, &ofs
, OF_READ
)) == -1)
931 /* Now try the built-in even if disabled */
932 if ((hModule
= MODULE_LoadBuiltin( name
, TRUE
)))
934 fprintf( stderr
, "Warning: could not load Windows DLL '%s', using built-in module.\n", name
);
937 return 2; /* File not found */
940 /* Create the module structure */
942 if ((hModule
= MODULE_LoadExeHeader( fd
, &ofs
)) < 32)
945 return PE_LoadModule(fd
,&ofs
,paramBlock
);
947 fprintf( stderr
, "LoadModule: can't load '%s', error=%d\n",
951 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
953 /* Allocate the segments for this module */
955 MODULE_CreateSegments( hModule
);
958 hInstance
= MODULE_CreateInstance( hModule
, (LOADPARAMS
*)paramBlock
);
960 /* Load the referenced DLLs */
962 pModRef
= (WORD
*)((char *)pModule
+ pModule
->modref_table
);
963 pDLLs
= (WORD
*)GlobalLock( pModule
->dlls_to_init
);
964 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
967 BYTE
*pstr
= (BYTE
*)pModule
+ pModule
->import_table
+ *pModRef
;
968 memcpy( buffer
, pstr
+ 1, *pstr
);
969 strcpy( buffer
+ *pstr
, ".dll" );
970 dprintf_module( stddeb
, "Loading '%s'\n", buffer
);
971 if (!(*pModRef
= MODULE_FindModule( buffer
)))
973 /* If the DLL is not loaded yet, load it and store */
974 /* its handle in the list of DLLs to initialize. */
977 if ((hDLL
= LoadModule( buffer
, (LPVOID
)-1 )) == 2) /* file not found */
981 /* Try with prepending the path of the current module */
982 GetModuleFileName( hModule
, buffer
, 256 );
983 if (!(p
= strrchr( buffer
, '\\' ))) p
= buffer
;
984 memcpy( p
+ 1, pstr
+ 1, *pstr
);
985 strcpy( p
+ 1 + *pstr
, ".dll" );
986 hDLL
= LoadModule( buffer
, (LPVOID
)-1 );
990 fprintf( stderr
, "Could not load '%s' required by '%s', error = %d\n",
991 buffer
, name
, hDLL
);
992 return 2; /* file not found */
994 *pModRef
= GetExePtr( hDLL
);
997 else /* Increment the reference count of the DLL */
999 NE_MODULE
*pOldDLL
= (NE_MODULE
*)GlobalLock( *pModRef
);
1000 if (pOldDLL
) pOldDLL
->count
++;
1004 /* Load the segments */
1006 if (pModule
->flags
& NE_FFLAGS_SELFLOAD
)
1008 /* Handle self loading modules */
1009 SEGTABLEENTRY
* pSegTable
= (SEGTABLEENTRY
*) NE_SEG_TABLE(pModule
);
1010 SELFLOADHEADER
*selfloadheader
;
1011 HMODULE hselfload
= GetModuleHandle("WINPROCS");
1012 WORD oldss
, oldsp
, saved_dgroup
= pSegTable
[pModule
->dgroup
- 1].selector
;
1013 fprintf (stderr
, "Warning: %*.*s is a self-loading module\n"
1014 "Support for self-loading modules is very experimental\n",
1015 *((BYTE
*)pModule
+ pModule
->name_table
),
1016 *((BYTE
*)pModule
+ pModule
->name_table
),
1017 (char *)pModule
+ pModule
->name_table
+ 1);
1018 NE_LoadSegment( hModule
, 1 );
1019 selfloadheader
= (SELFLOADHEADER
*)
1020 PTR_SEG_OFF_TO_LIN(pSegTable
->selector
, 0);
1021 selfloadheader
->EntryAddrProc
=
1022 MODULE_GetEntryPoint(hselfload
,27);
1023 selfloadheader
->MyAlloc
= MODULE_GetEntryPoint(hselfload
,28);
1024 selfloadheader
->SetOwner
= MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1025 pModule
->self_loading_sel
= GlobalHandleToSel(
1026 GLOBAL_Alloc (GMEM_ZEROINIT
,
1027 0xFF00, hModule
, FALSE
, FALSE
, FALSE
)
1029 oldss
= IF1632_Saved16_ss
;
1030 oldsp
= IF1632_Saved16_sp
;
1031 IF1632_Saved16_ss
= pModule
->self_loading_sel
;
1032 IF1632_Saved16_sp
= 0xFF00;
1033 if (!IF1632_Stack32_base
) {
1034 STACK32FRAME
* frame32
;
1036 /* Setup an initial 32 bit stack frame */
1037 hInitialStack32
= GLOBAL_Alloc( GMEM_FIXED
, 0x10000,
1038 hModule
, FALSE
, FALSE
,
1041 /* Create the 32-bit stack frame */
1043 *(DWORD
*)GlobalLock(hInitialStack32
) = 0xDEADBEEF;
1044 stack32Top
= (char*)GlobalLock(hInitialStack32
) +
1046 frame32
= (STACK32FRAME
*)stack32Top
- 1;
1047 frame32
->saved_esp
= (DWORD
)stack32Top
;
1054 frame32
->retaddr
= 0;
1055 frame32
->codeselector
= WINE_CODE_SELECTOR
;
1056 /* pTask->esp = (DWORD)frame32; */
1057 IF1632_Stack32_base
= WIN16_GlobalLock(hInitialStack32
);
1060 CallTo16_word_ww (selfloadheader
->BootApp
,
1061 pModule
->self_loading_sel
, hModule
, fd
);
1062 /* some BootApp procs overwrite the selector of dgroup */
1063 pSegTable
[pModule
->dgroup
- 1].selector
= saved_dgroup
;
1064 IF1632_Saved16_ss
= oldss
;
1065 IF1632_Saved16_sp
= oldsp
;
1066 for (i
= 2; i
<= pModule
->seg_count
; i
++) NE_LoadSegment( hModule
, i
);
1067 if (hInitialStack32
){
1068 GlobalUnlock (hInitialStack32
);
1069 GlobalFree (hInitialStack32
);
1070 IF1632_Stack32_base
= hInitialStack32
= 0;
1075 for (i
= 1; i
<= pModule
->seg_count
; i
++)
1076 NE_LoadSegment( hModule
, i
);
1079 /* Fixup the functions prologs */
1081 NE_FixupPrologs( hModule
);
1083 /* Make sure the usage count is 1 on the first loading of */
1084 /* the module, even if it contains circular DLL references */
1088 /* Clear built-in flag in case it was set in the EXE file */
1090 pModule
->flags
&= ~NE_FFLAGS_BUILTIN
;
1094 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
1095 hPrevInstance
= MODULE_GetInstance( hModule
);
1096 hInstance
= MODULE_CreateInstance( hModule
, params
);
1097 if (hInstance
!= hPrevInstance
) /* not a library */
1098 NE_LoadSegment( hModule
, pModule
->dgroup
);
1102 hModule
= GlobalAlloc( GMEM_MOVEABLE
| GMEM_ZEROINIT
, sizeof(NE_MODULE
) );
1103 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
1105 pModule
->magic
= 0x454e;
1107 hInstance
= MODULE_CreateInstance( hModule
, (LOADPARAMS
*)paramBlock
);
1108 #endif /* WINELIB */
1110 /* Create a task for this instance */
1112 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
) && (paramBlock
!= (LPVOID
)-1))
1114 TASK_CreateTask( hModule
, hInstance
, hPrevInstance
,
1115 params
->hEnvironment
,
1116 (LPSTR
)PTR_SEG_TO_LIN( params
->cmdLine
),
1117 *((WORD
*)PTR_SEG_TO_LIN(params
->showCmd
)+1) );
1124 /**********************************************************************
1125 * FreeModule (KERNEL.46)
1127 BOOL
FreeModule( HANDLE hModule
)
1131 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1132 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
1134 dprintf_module( stddeb
, "FreeModule: %s count %d\n",
1135 MODULE_GetModuleName(hModule
), pModule
->count
);
1136 if (--pModule
->count
== 0) MODULE_FreeModule( hModule
);
1141 /**********************************************************************
1142 * GetModuleHandle (KERNEL.47)
1144 HMODULE
WIN16_GetModuleHandle( SEGPTR name
)
1147 if (HIWORD(name
) == 0) return GetExePtr( name
);
1149 if (HIWORD(name
) == 0) return GetExePtr( LOWORD(name
) );
1151 return MODULE_FindModule( PTR_SEG_TO_LIN(name
) );
1154 HMODULE
GetModuleHandle( LPCSTR name
)
1156 return MODULE_FindModule( name
);
1160 /**********************************************************************
1161 * GetModuleUsage (KERNEL.48)
1163 int GetModuleUsage( HANDLE hModule
)
1167 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1168 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
1169 dprintf_module( stddeb
, "GetModuleUsage("NPFMT
"): returning %d\n",
1170 hModule
, pModule
->count
);
1171 return pModule
->count
;
1175 /**********************************************************************
1176 * GetModuleFileName (KERNEL.49)
1178 int GetModuleFileName( HANDLE hModule
, LPSTR lpFileName
, short nSize
)
1183 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1184 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
1185 name
= ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
;
1186 strncpy( lpFileName
, name
, nSize
);
1187 lpFileName
[nSize
-1] = '\0';
1188 dprintf_module( stddeb
, "GetModuleFilename: %s\n", lpFileName
);
1189 return strlen(lpFileName
);
1193 /***********************************************************************
1194 * LoadLibrary (KERNEL.95)
1196 HANDLE
LoadLibrary( LPCSTR libname
)
1200 dprintf_module( stddeb
, "LoadLibrary: (%08x) %s\n", (int)libname
, libname
);
1201 /* This does not increment the module reference count, and will
1202 * therefore cause crashes on FreeLibrary calls.
1203 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1205 handle
= LoadModule( libname
, (LPVOID
)-1 );
1206 if (handle
== (HANDLE
)2) /* file not found */
1209 strcpy( buffer
, libname
);
1210 strcat( buffer
, ".dll" );
1211 handle
= LoadModule( buffer
, (LPVOID
)-1 );
1213 if (handle
>= (HANDLE
)32) NE_InitializeDLLs( GetExePtr(handle
) );
1218 /***********************************************************************
1219 * FreeLibrary (KERNEL.96)
1221 void FreeLibrary( HANDLE handle
)
1223 dprintf_module( stddeb
,"FreeLibrary: "NPFMT
"\n", handle
);
1224 FreeModule( handle
);
1228 /***********************************************************************
1229 * WinExec (KERNEL.166)
1231 HANDLE
WinExec( LPSTR lpCmdLine
, WORD nCmdShow
)
1234 HLOCAL cmdShowHandle
, cmdLineHandle
;
1237 char *p
, *cmdline
, filename
[256];
1239 if (!(cmdShowHandle
= GlobalAlloc( 0, 2 * sizeof(WORD
) ))) return 0;
1240 if (!(cmdLineHandle
= GlobalAlloc( 0, 256 ))) return 0;
1242 /* Store nCmdShow */
1244 cmdShowPtr
= (WORD
*)GlobalLock( cmdShowHandle
);
1246 cmdShowPtr
[1] = nCmdShow
;
1248 /* Build the filename and command-line */
1250 cmdline
= (char *)GlobalLock( cmdLineHandle
);
1251 strncpy( filename
, lpCmdLine
, 256 );
1252 filename
[255] = '\0';
1253 for (p
= filename
; *p
&& (*p
!= ' ') && (*p
!= '\t'); p
++);
1256 strncpy( cmdline
, p
+ 1, 128 );
1257 cmdline
[127] = '\0';
1259 else cmdline
[0] = '\0';
1262 /* Now load the executable file */
1264 params
.hEnvironment
= (HANDLE
)SELECTOROF( GetDOSEnvironment() );
1265 params
.cmdLine
= (SEGPTR
)WIN16_GlobalLock( cmdLineHandle
);
1266 params
.showCmd
= (SEGPTR
)WIN16_GlobalLock( cmdShowHandle
);
1267 params
.reserved
= 0;
1268 handle
= LoadModule( filename
, ¶ms
);
1269 if (handle
== (HANDLE
)2) /* file not found */
1271 /* Check that the original file name did not have a suffix */
1272 p
= strrchr(filename
, '.');
1273 if (p
&& !(strchr(p
, '/') || strchr(p
, '\\')))
1274 return handle
; /* filename already includes a suffix! */
1275 strcat( filename
, ".exe" );
1276 handle
= LoadModule( filename
, ¶ms
);
1279 GlobalFree( cmdShowHandle
);
1280 GlobalFree( cmdLineHandle
);
1283 if (handle
< (HANDLE
)32) /* Error? */
1286 /* FIXME: Yield never returns!
1287 We may want to run more applications or start the debugger
1288 before calling Yield. If we don't Yield will be called immdiately
1289 after returning. Why is it needed for Word anyway? */
1290 Yield(); /* program is executed immediately ....needed for word */
1297 /***********************************************************************
1298 * GetProcAddress (KERNEL.50)
1300 FARPROC
GetProcAddress( HANDLE hModule
, SEGPTR name
)
1305 if (!hModule
) hModule
= GetCurrentTask();
1306 hModule
= GetExePtr( hModule
);
1308 if (HIWORD(name
) != 0)
1310 ordinal
= MODULE_GetOrdinal( hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1311 dprintf_module( stddeb
, "GetProcAddress: "NPFMT
" '%s'\n",
1312 hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1316 ordinal
= LOWORD(name
);
1317 dprintf_module( stddeb
, "GetProcAddress: "NPFMT
" %04x\n",
1320 if (!ordinal
) return (FARPROC
)0;
1322 ret
= MODULE_GetEntryPoint( hModule
, ordinal
);
1324 dprintf_module( stddeb
, "GetProcAddress: returning %08lx\n", ret
);
1325 return (FARPROC
)ret
;
1330 /***********************************************************************
1331 * GetWndProcEntry16 (not a Windows API function)
1333 * Return an entry point from the WINPROCS dll.
1335 WNDPROC
GetWndProcEntry16( char *name
)
1338 static HMODULE hModule
= 0;
1340 if (!hModule
) hModule
= GetModuleHandle( "WINPROCS" );
1341 ordinal
= MODULE_GetOrdinal( hModule
, name
);
1342 return MODULE_GetEntryPoint( hModule
, ordinal
);
1347 /**********************************************************************
1348 * ModuleFirst (TOOLHELP.59)
1350 BOOL
ModuleFirst( MODULEENTRY
*lpme
)
1352 lpme
->wNext
= hFirstModule
;
1353 return ModuleNext( lpme
);
1357 /**********************************************************************
1358 * ModuleNext (TOOLHELP.60)
1360 BOOL
ModuleNext( MODULEENTRY
*lpme
)
1364 if (!lpme
->wNext
) return FALSE
;
1365 if (!(pModule
= (NE_MODULE
*)GlobalLock( lpme
->wNext
))) return FALSE
;
1366 strncpy( lpme
->szModule
, (char *)pModule
+ pModule
->name_table
,
1368 lpme
->szModule
[MAX_MODULE_NAME
] = '\0';
1369 lpme
->hModule
= lpme
->wNext
;
1370 lpme
->wcUsage
= pModule
->count
;
1371 strncpy( lpme
->szExePath
,
1372 ((LOADEDFILEINFO
*)((char*)pModule
+ pModule
->fileinfo
))->filename
,
1374 lpme
->szExePath
[MAX_PATH
] = '\0';
1375 lpme
->wNext
= pModule
->next
;
1380 /**********************************************************************
1381 * ModuleFindName (TOOLHELP.61)
1383 BOOL
ModuleFindName( MODULEENTRY
*lpme
, LPCSTR name
)
1385 lpme
->wNext
= GetModuleHandle( name
);
1386 return ModuleNext( lpme
);
1390 /**********************************************************************
1391 * ModuleFindHandle (TOOLHELP.62)
1393 BOOL
ModuleFindHandle( MODULEENTRY
*lpme
, HMODULE hModule
)
1395 hModule
= GetExePtr( hModule
); /* In case we were passed an hInstance */
1396 lpme
->wNext
= hModule
;
1397 return ModuleNext( lpme
);