1 static char RCSId
[] = "$Id: wine.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
2 static char Copyright
[] = "Copyright Robert J. Amstadt, 1993";
12 #include <linux/head.h>
13 #include <linux/ldt.h>
14 #include <linux/segment.h>
20 #include "prototypes.h"
28 /* #define DEBUG_FIXUP /* */
29 /* #undef DEBUG_FIXUP /* */
32 extern HANDLE
CreateNewTask(HINSTANCE hInst
);
33 extern void InitializeLoadedDLLs(struct w_files
*wpnt
);
34 extern int CallToInit16(unsigned long csip
, unsigned long sssp
,
36 extern void CallTo32();
37 extern char WindowsPath
[256];
38 extern unsigned short WIN_StackSize
;
39 extern unsigned short WIN_HeapSize
;
41 int FixupSegment(struct w_files
*, int);
42 void FixupFunctionPrologs(struct w_files
*);
43 char *GetModuleName(struct w_files
* wpnt
, int index
, char *buffer
);
47 /**********************************************************************/
49 void load_ne_header (int fd
, struct ne_header_s
*ne_header
)
51 if (read(fd
, ne_header
, sizeof(struct ne_header_s
))
52 != sizeof(struct ne_header_s
))
54 myerror("Unable to read NE header from file");
59 /**********************************************************************
61 * Load one NE format executable into memory
63 HINSTANCE
LoadNEImage(struct w_files
*wpnt
)
65 unsigned int read_size
, status
, segment
;
68 wpnt
->ne
= malloc(sizeof(struct ne_data
));
69 wpnt
->ne
->resnamtab
= NULL
;
70 wpnt
->ne
->ne_header
= malloc(sizeof(struct ne_header_s
));
71 lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
, SEEK_SET
);
72 load_ne_header(wpnt
->fd
, wpnt
->ne
->ne_header
);
76 * Create segment selectors.
78 status
= lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
+
79 wpnt
->ne
->ne_header
->segment_tab_offset
,
81 read_size
= wpnt
->ne
->ne_header
->n_segment_tab
*
82 sizeof(struct ne_segment_table_entry_s
);
83 wpnt
->ne
->seg_table
= (struct ne_segment_table_entry_s
*) malloc(read_size
);
84 if (read(wpnt
->fd
, wpnt
->ne
->seg_table
, read_size
) != read_size
)
85 myerror("Unable to read segment table header from file");
86 wpnt
->ne
->selector_table
= CreateSelectors(wpnt
);
87 wpnt
->hinstance
= (wpnt
->ne
->
88 selector_table
[wpnt
->ne
->ne_header
->auto_data_seg
-1].
91 /* Get the lookup table. This is used for looking up the addresses
92 of functions that are exported */
94 read_size
= wpnt
->ne
->ne_header
->entry_tab_length
;
95 wpnt
->ne
->lookup_table
= (char *) malloc(read_size
);
96 lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
+
97 wpnt
->ne
->ne_header
->entry_tab_offset
, SEEK_SET
);
98 if (read(wpnt
->fd
, wpnt
->ne
->lookup_table
, read_size
) != read_size
)
99 myerror("Unable to read lookup table header from file");
101 /* Get the iname table. This is used for looking up the names
102 of functions that are exported */
104 status
= lseek(wpnt
->fd
, wpnt
->ne
->ne_header
->nrname_tab_offset
, SEEK_SET
);
105 read_size
= wpnt
->ne
->ne_header
->nrname_tab_length
;
106 wpnt
->ne
->nrname_table
= (char *) malloc(read_size
);
107 if (read(wpnt
->fd
, wpnt
->ne
->nrname_table
, read_size
) != read_size
)
108 myerror("Unable to read nrname table header from file");
110 status
= lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
+
111 wpnt
->ne
->ne_header
->rname_tab_offset
, SEEK_SET
);
112 read_size
= wpnt
->ne
->ne_header
->moduleref_tab_offset
-
113 wpnt
->ne
->ne_header
->rname_tab_offset
;
114 wpnt
->ne
->rname_table
= (char *) malloc(read_size
);
115 if (read(wpnt
->fd
, wpnt
->ne
->rname_table
, read_size
) != read_size
)
116 myerror("Unable to read rname table header from file");
119 * Now load any DLLs that this module refers to.
121 for(i
=0; i
<wpnt
->ne
->ne_header
->n_mod_ref_tab
; i
++)
124 GetModuleName(wpnt
, i
+ 1, buff
);
126 if (strcasecmp(buff
, wpnt
->name
) != 0 )
127 LoadImage(buff
, DLL
, 0);
130 /* fixup references */
132 for (segment
= 0; segment
< wpnt
->ne
->ne_header
->n_segment_tab
; segment
++)
133 if (FixupSegment(wpnt
, segment
) < 0)
134 myerror("fixup failed.");
136 FixupFunctionPrologs(wpnt
);
137 InitializeLoadedDLLs(wpnt
);
139 return(wpnt
->hinstance
);
142 /**********************************************************************
146 GetImportedName(int fd
, struct mz_header_s
*mz_header
,
147 struct ne_header_s
*ne_header
, int name_offset
, char *buffer
)
152 status
= lseek(fd
, mz_header
->ne_offset
+ ne_header
->iname_tab_offset
+
153 name_offset
, SEEK_SET
);
155 read(fd
, &length
, 1); /* Get the length byte */
156 length
= CONV_CHAR_TO_LONG (length
);
157 read(fd
, buffer
, length
);
162 /**********************************************************************
166 GetModuleName(struct w_files
* wpnt
, int index
, char *buffer
)
169 struct mz_header_s
*mz_header
= wpnt
->mz_header
;
170 struct ne_header_s
*ne_header
= wpnt
->ne
->ne_header
;
172 WORD name_offset
, status
;
175 status
= lseek(fd
, mz_header
->ne_offset
+ ne_header
->moduleref_tab_offset
+
176 2*(index
- 1), SEEK_SET
);
178 read(fd
, &name_offset
, 2);
179 name_offset
= CONV_SHORT (name_offset
);
180 status
= lseek(fd
, mz_header
->ne_offset
+ ne_header
->iname_tab_offset
+
181 name_offset
, SEEK_SET
);
183 read(fd
, &length
, 1); /* Get the length byte */
184 length
= CONV_CHAR_TO_LONG (length
);
185 read(fd
, buffer
, length
);
188 /* Module names are always upper case */
189 for(i
=0; i
<length
; i
++)
190 if (islower(buffer
[i
]))
191 buffer
[i
] = toupper(buffer
[i
]);
198 /**********************************************************************
202 FixupSegment(struct w_files
* wpnt
, int segment_num
)
205 struct mz_header_s
*mz_header
= wpnt
->mz_header
;
206 struct ne_header_s
*ne_header
= wpnt
->ne
->ne_header
;
207 struct ne_segment_table_entry_s
*seg_table
= wpnt
->ne
->seg_table
;
208 struct segment_descriptor_s
*selector_table
= wpnt
->ne
->selector_table
;
209 struct relocation_entry_s
*rep
, *rep1
;
210 struct ne_segment_table_entry_s
*seg
;
211 struct segment_descriptor_s
*sel
;
214 unsigned int selector
, address
;
215 unsigned int next_addr
;
222 seg
= &seg_table
[segment_num
];
223 sel
= &selector_table
[segment_num
];
225 dprintf_fixup(stddeb
, "Segment fixups for %s, segment %d, selector %x\n",
226 wpnt
->name
, segment_num
, (int) sel
->base_addr
>> 16);
228 if ((seg
->seg_data_offset
== 0) ||
229 !(seg
->seg_flags
& NE_SEGFLAGS_RELOC_DATA
))
233 * Go through the relocation table on entry at a time.
235 i
= seg
->seg_data_length
;
239 status
= lseek(fd
, seg
->seg_data_offset
*
240 (1 << ne_header
->align_shift_count
) + i
, SEEK_SET
);
242 read(fd
, &n_entries
, sizeof(short int));
243 rep
= (struct relocation_entry_s
*)
244 malloc(n_entries
* sizeof(struct relocation_entry_s
));
246 if (read(fd
,rep
, n_entries
* sizeof(struct relocation_entry_s
)) !=
247 n_entries
* sizeof(struct relocation_entry_s
))
249 myerror("Unable to read relocation information");
254 for (i
= 0; i
< n_entries
; i
++, rep
++)
257 * Get the target address corresponding to this entry.
261 switch (rep
->relocation_type
)
263 case NE_RELTYPE_ORDINALADD
:
266 case NE_RELTYPE_ORDINAL
:
267 if (GetModuleName(wpnt
, rep
->target1
,
270 fprintf(stderr
, "NE_RELTYPE_ORDINAL failed");
274 ordinal
= rep
->target2
;
276 status
= GetEntryDLLOrdinal(dll_name
, ordinal
, &selector
,
282 sprintf(s
, "Bad DLL name '%s.%d'", dll_name
, ordinal
);
287 dprintf_fixup(stddeb
,"%d: %s.%d: %04.4x:%04.4x\n", i
+ 1,
288 dll_name
, ordinal
, selector
, address
);
291 case NE_RELTYPE_NAMEADD
:
294 case NE_RELTYPE_NAME
:
295 if (GetModuleName(wpnt
, rep
->target1
, dll_name
)
298 fprintf(stderr
,"NE_RELTYPE_NAME failed");
302 if (GetImportedName(fd
, mz_header
, ne_header
,
303 rep
->target2
, func_name
) == NULL
)
305 fprintf(stderr
,"getimportedname failed");
309 status
= GetEntryDLLName(dll_name
, func_name
, &selector
,
315 sprintf(s
, "Bad DLL name '%s (%s)'", dll_name
,func_name
);
320 dprintf_fixup(stddeb
,"%d: %s %s.%d: %04.4x:%04.4x\n", i
+ 1,
321 func_name
, dll_name
, ordinal
, selector
, address
);
324 case NE_RELTYPE_INTERNAL
:
325 case NE_RELTYPE_INT1
:
326 if (rep
->target1
== 0x00ff)
328 address
= GetEntryPointFromOrdinal(wpnt
, rep
->target2
);
329 selector
= (address
>> 16) & 0xffff;
334 selector
= selector_table
[rep
->target1
-1].selector
;
335 address
= rep
->target2
;
338 dprintf_fixup(stddeb
,"%d: %04.4x:%04.4x\n",
339 i
+ 1, selector
, address
);
343 /* Relocation type 7:
345 * These appear to be used as fixups for the Windows
346 * floating point emulator. Let's just ignore them and
347 * try to use the hardware floating point. Linux should
348 * successfully emulate the coprocessor if it doesn't
351 dprintf_fixup(stddeb
,
352 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
353 i
+ 1, rep
->address_type
, rep
->relocation_type
,
355 dprintf_fixup(stddeb
,"TARGET %04.4x %04.4x\n",
356 rep
->target1
, rep
->target2
);
360 dprintf_fixup(stddeb
,
361 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
362 i
+ 1, rep
->address_type
, rep
->relocation_type
,
364 dprintf_fixup(stddeb
,"TARGET %04.4x %04.4x\n",
365 rep
->target1
, rep
->target2
);
371 * Stuff the right size result in.
373 sp
= (unsigned short *) ((char *) sel
->base_addr
+ rep
->offset
);
376 if (FindDLLTable(dll_name
) == NULL
)
378 dprintf_fixup(stddeb
,
379 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
380 i
+ 1, rep
->address_type
, rep
->relocation_type
,
382 dprintf_fixup(stddeb
,"TARGET %04.4x %04.4x\n",
383 rep
->target1
, rep
->target2
);
384 dprintf_fixup(stddeb
, " Additive = %d\n", additive
);
387 switch (rep
->address_type
)
389 case NE_RADDR_OFFSET16
:
391 dprintf_fixup(stddeb
," %04.4x:%04.4x:%04.4x OFFSET16\n",
392 (unsigned long) sp
>> 16, (int) sp
& 0xFFFF, *sp
);
394 *sp
= (unsigned short) address
;
397 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
399 while (next_addr
!= 0xffff && !additive
);
403 case NE_RADDR_POINTER32
:
405 dprintf_fixup(stddeb
," %04.4x:%04.4x:%04.4x POINTER32\n",
406 (unsigned long) sp
>> 16, (int) sp
& 0xFFFF, *sp
);
408 *sp
= (unsigned short) address
;
411 *(sp
+1) = (unsigned short) selector
;
412 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
414 while (next_addr
!= 0xffff && !additive
);
418 case NE_RADDR_SELECTOR
:
420 dprintf_fixup(stddeb
," %04.4x:%04.4x:%04.4x SELECTOR\n",
421 (unsigned long) sp
>> 16, (int) sp
& 0xFFFF, *sp
);
423 *sp
= (unsigned short) selector
;
424 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
425 if (rep
->relocation_type
== NE_RELTYPE_INT1
)
428 while (next_addr
!= 0xffff && !additive
);
433 dprintf_fixup(stddeb
,
434 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
435 i
+ 1, rep
->address_type
, rep
->relocation_type
,
437 dprintf_fixup(stddeb
,
438 "TARGET %04.4x %04.4x\n", rep
->target1
, rep
->target2
);
448 int NEunloadImage(struct w_files
*wpnt
)
450 printf("NEunloadImage() called!\n");
451 /* free resources, image */
455 int StartNEprogram(struct w_files
*wpnt
)
457 int cs_reg
, ds_reg
, ss_reg
, ip_reg
, sp_reg
;
459 * Fixup stack and jump to start.
461 WIN_StackSize
= wpnt
->ne
->ne_header
->stack_length
;
462 WIN_HeapSize
= wpnt
->ne
->ne_header
->local_heap_length
;
464 ds_reg
= wpnt
->ne
->selector_table
[wpnt
->ne
->ne_header
->auto_data_seg
-1].selector
;
465 cs_reg
= wpnt
->ne
->selector_table
[wpnt
->ne
->ne_header
->cs
-1].selector
;
466 ip_reg
= wpnt
->ne
->ne_header
->ip
;
467 ss_reg
= wpnt
->ne
->selector_table
[wpnt
->ne
->ne_header
->ss
-1].selector
;
468 sp_reg
= wpnt
->ne
->ne_header
->sp
;
470 return CallToInit16(cs_reg
<< 16 | ip_reg
, ss_reg
<< 16 | sp_reg
, ds_reg
);
473 void InitNEDLL(struct w_files
*wpnt
)
475 int cs_reg
, ds_reg
, ip_reg
, rv
;
479 if (wpnt
->ne
->ne_header
->format_flags
& 0x8000)
481 if (!(wpnt
->ne
->ne_header
->format_flags
& 0x0001))
484 fprintf(stderr
, "Library is not marked SINGLEDATA\n");
488 ds_reg
= wpnt
->ne
->selector_table
[wpnt
->ne
->
489 ne_header
->auto_data_seg
-1].selector
;
490 cs_reg
= wpnt
->ne
->selector_table
[wpnt
->ne
->ne_header
->cs
-1].selector
;
491 ip_reg
= wpnt
->ne
->ne_header
->ip
;
494 fprintf(stderr
, "Initializing %s, cs:ip %04x:%04x, ds %04x\n",
495 wpnt
->name
, cs_reg
, ip_reg
, ds_reg
);
497 rv
= CallTo16(cs_reg
<< 16 | ip_reg
, ds_reg
);
498 printf ("rv = %x\n", rv
);
500 printf("%s skipped\n", wpnt
->name
);
504 #endif /* !WINELIB */