2 static char RCSId[] = "$Id: wine.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
3 static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
21 #include "selectors.h"
23 #include "prototypes.h"
27 extern unsigned short WIN_StackSize
;
28 extern unsigned short WIN_HeapSize
;
30 void FixupFunctionPrologs(struct w_files
*);
32 /**********************************************************************
36 char *NE_GetImportedName(struct w_files
*wpnt
, int name_offset
, char *buffer
)
40 lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
+
41 wpnt
->ne
->ne_header
->iname_tab_offset
+ name_offset
, SEEK_SET
);
42 read(wpnt
->fd
, &length
, 1); /* Get the length byte */
43 read(wpnt
->fd
, buffer
, length
);
49 struct w_files
*current_exe
;
50 WORD current_nodata
=0xfd00;
51 /**********************************************************************
54 static char *NE_GetModuleName(struct w_files
*wpnt
, int index
, char *buffer
)
60 lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
+
61 wpnt
->ne
->ne_header
->moduleref_tab_offset
+ 2 * (index
- 1), SEEK_SET
);
62 read(wpnt
->fd
, &name_offset
, 2);
63 name_offset
= CONV_SHORT (name_offset
);
65 lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
+
66 wpnt
->ne
->ne_header
->iname_tab_offset
+ name_offset
, SEEK_SET
);
67 read(wpnt
->fd
, &length
, 1); /* Get the length byte */
68 read(wpnt
->fd
, buffer
, length
);
71 /* Module names are always upper case */
72 for(i
=0; i
<length
; i
++)
73 if (islower(buffer
[i
]))
74 buffer
[i
] = toupper(buffer
[i
]);
80 /**********************************************************************
83 int NE_FixupSegment(struct w_files
*wpnt
, int segment_num
)
85 struct segment_descriptor_s
*selector_table
= wpnt
->ne
->selector_table
;
86 struct relocation_entry_s
*rep
, *rep1
;
87 struct ne_segment_table_entry_s
*seg
;
88 struct segment_descriptor_s
*sel
;
89 int status
, ordinal
, i
, n_entries
, additive
;
91 unsigned int selector
, address
, next_addr
;
92 unsigned char dll_name
[257], func_name
[257];
94 seg
= &wpnt
->ne
->seg_table
[segment_num
];
95 sel
= &selector_table
[segment_num
];
97 dprintf_fixup(stddeb
, "Segment fixups for %s, segment %d, selector %x\n",
98 wpnt
->name
, segment_num
, (int) sel
->base_addr
>> 16);
100 if ((seg
->seg_data_offset
== 0) ||
101 !(seg
->seg_flags
& NE_SEGFLAGS_RELOC_DATA
))
105 * Go through the relocation table on entry at a time.
107 i
= seg
->seg_data_length
;
111 status
= lseek(wpnt
->fd
, seg
->seg_data_offset
*
112 (1 << wpnt
->ne
->ne_header
->align_shift_count
) + i
, SEEK_SET
);
114 read(wpnt
->fd
, &n_entries
, sizeof(short int));
115 rep
= (struct relocation_entry_s
*)
116 malloc(n_entries
* sizeof(struct relocation_entry_s
));
118 if (read(wpnt
->fd
, rep
, n_entries
* sizeof(struct relocation_entry_s
)) !=
119 n_entries
* sizeof(struct relocation_entry_s
))
121 myerror("Unable to read relocation information");
126 for (i
= 0; i
< n_entries
; i
++, rep
++)
129 * Get the target address corresponding to this entry.
133 switch (rep
->relocation_type
)
135 case NE_RELTYPE_ORDINALADD
:
138 case NE_RELTYPE_ORDINAL
:
139 if (NE_GetModuleName(wpnt
, rep
->target1
,
142 fprintf(stderr
, "NE_RELTYPE_ORDINAL failed");
146 ordinal
= rep
->target2
;
148 status
= GetEntryDLLOrdinal(dll_name
, ordinal
, &selector
,
154 sprintf(s
, "Bad DLL name '%s.%d'", dll_name
, ordinal
);
159 dprintf_fixup(stddeb
,"%d: %s.%d: %04x:%04x\n", i
+ 1,
160 dll_name
, ordinal
, selector
, address
);
163 case NE_RELTYPE_NAMEADD
:
166 case NE_RELTYPE_NAME
:
167 if (NE_GetModuleName(wpnt
, rep
->target1
, dll_name
) == NULL
) {
168 fprintf(stderr
,"NE_RELTYPE_NAME failed");
172 if (NE_GetImportedName(wpnt
, rep
->target2
, func_name
) == NULL
) {
173 fprintf(stderr
,"NE_getimportedname failed");
177 status
= GetEntryDLLName(dll_name
, func_name
, &selector
,
183 sprintf(s
, "Bad DLL name '%s (%s)'", dll_name
,func_name
);
187 /* dprintf_fixup(stddeb,"%d: %s %s.%d: %04x:%04x\n", i + 1,
188 func_name, dll_name, ordinal, selector, address);*/
191 case NE_RELTYPE_INTERNAL
:
192 case NE_RELTYPE_INT1
:
193 if (rep
->target1
== 0x00ff)
195 address
= GetEntryPointFromOrdinal(wpnt
, rep
->target2
);
196 selector
= (address
>> 16) & 0xffff;
201 selector
= selector_table
[rep
->target1
-1].selector
;
202 address
= rep
->target2
;
205 dprintf_fixup(stddeb
,"%d: %04x:%04x\n",
206 i
+ 1, selector
, address
);
210 /* Relocation type 7:
212 * These appear to be used as fixups for the Windows
213 * floating point emulator. Let's just ignore them and
214 * try to use the hardware floating point. Linux should
215 * successfully emulate the coprocessor if it doesn't
218 dprintf_fixup(stddeb
,
219 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
220 i
+ 1, rep
->address_type
, rep
->relocation_type
,
222 dprintf_fixup(stddeb
,"TARGET %04x %04x\n",
223 rep
->target1
, rep
->target2
);
227 dprintf_fixup(stddeb
,
228 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
229 i
+ 1, rep
->address_type
, rep
->relocation_type
,
231 dprintf_fixup(stddeb
,"TARGET %04x %04x\n",
232 rep
->target1
, rep
->target2
);
238 * Stuff the right size result in.
240 sp
= (unsigned short *) ((char *) sel
->base_addr
+ rep
->offset
);
243 if (FindDLLTable(dll_name
) == NULL
)
245 dprintf_fixup(stddeb
,
246 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
247 i
+ 1, rep
->address_type
, rep
->relocation_type
,
249 dprintf_fixup(stddeb
,"TARGET %04x %04x\n",
250 rep
->target1
, rep
->target2
);
251 dprintf_fixup(stddeb
, " Additive = %d\n", additive
);
254 switch (rep
->address_type
)
256 case NE_RADDR_OFFSET16
:
258 dprintf_fixup(stddeb
," %04x:%04x:%04x OFFSET16\n",
259 (unsigned int) sp
>> 16, (int) sp
& 0xFFFF, *sp
);
261 *sp
= (unsigned short) address
;
264 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
266 while (next_addr
!= 0xffff && !additive
);
270 case NE_RADDR_POINTER32
:
272 dprintf_fixup(stddeb
," %04x:%04x:%04x POINTER32\n",
273 (unsigned int) sp
>> 16, (int) sp
& 0xFFFF, *sp
);
275 *sp
= (unsigned short) address
;
278 *(sp
+1) = (unsigned short) selector
;
279 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
281 while (next_addr
!= 0xffff && !additive
);
285 case NE_RADDR_SELECTOR
:
287 dprintf_fixup(stddeb
," %04x:%04x:%04x SELECTOR\n",
288 (unsigned int) sp
>> 16, (int) sp
& 0xFFFF, *sp
);
290 *sp
= (unsigned short) selector
;
291 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
292 if (rep
->relocation_type
== NE_RELTYPE_INT1
)
295 while (next_addr
!= 0xffff && !additive
);
300 dprintf_fixup(stddeb
,
301 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
302 i
+ 1, rep
->address_type
, rep
->relocation_type
,
304 dprintf_fixup(stddeb
,
305 "TARGET %04x %04x\n", rep
->target1
, rep
->target2
);
315 int NE_unloadImage(struct w_files
*wpnt
)
317 dprintf_fixup(stdnimp
, "NEunloadImage() called!\n");
318 /* free resources, image */
322 int NE_StartProgram(struct w_files
*wpnt
)
324 int cs_reg
, ds_reg
, ss_reg
, ip_reg
, sp_reg
;
326 * Fixup stack and jump to start.
328 WIN_StackSize
= wpnt
->ne
->ne_header
->stack_length
;
329 WIN_HeapSize
= wpnt
->ne
->ne_header
->local_heap_length
;
331 ds_reg
= wpnt
->ne
->selector_table
[wpnt
->ne
->ne_header
->auto_data_seg
-1].selector
;
332 cs_reg
= wpnt
->ne
->selector_table
[wpnt
->ne
->ne_header
->cs
-1].selector
;
333 ip_reg
= wpnt
->ne
->ne_header
->ip
;
334 ss_reg
= wpnt
->ne
->selector_table
[wpnt
->ne
->ne_header
->ss
-1].selector
;
335 sp_reg
= wpnt
->ne
->ne_header
->sp
;
337 return CallToInit16(cs_reg
<< 16 | ip_reg
, ss_reg
<< 16 | sp_reg
, ds_reg
);
340 void NE_InitDLL(struct w_files
*wpnt
)
342 int cs_reg
, ds_reg
, ip_reg
, cx_reg
, di_reg
, rv
;
343 extern struct w_files
*current_exe
;
347 if (wpnt
->ne
->ne_header
->format_flags
& 0x8000)
349 if (!(wpnt
->ne
->ne_header
->format_flags
& 0x0001))
350 if(wpnt
->ne
->ne_header
->format_flags
& NE_FFLAGS_MULTIPLEDATA
351 || wpnt
->ne
->ne_header
->auto_data_seg
)
354 fprintf(stderr
, "Library is not marked SINGLEDATA\n");
356 } else { /* DATA NONE DLL */
357 ds_reg
= current_exe
->ne
->selector_table
[
358 current_exe
->ne
->ne_header
->auto_data_seg
-1].selector
;
360 } else { /* DATA SINGLE DLL */
361 ds_reg
= wpnt
->ne
->selector_table
[wpnt
->ne
->
362 ne_header
->auto_data_seg
-1].selector
;
363 cx_reg
= wpnt
->ne
->ne_header
->local_heap_length
;
366 cs_reg
= wpnt
->ne
->selector_table
[wpnt
->ne
->ne_header
->cs
-1].selector
;
367 ip_reg
= wpnt
->ne
->ne_header
->ip
;
369 di_reg
= wpnt
->hinstance
;
372 dprintf_dll(stddeb
,"Initializing %s, cs:ip %04x:%04x, ds %04x, cx %04x\n",
373 wpnt
->name
, cs_reg
, ip_reg
, ds_reg
, cx_reg
);
375 rv
= CallTo16cx(cs_reg
<< 16 | ip_reg
, ds_reg
| (cx_reg
<<16));
376 dprintf_exec(stddeb
,"rv = %x\n", rv
);
378 dprintf_exec(stddeb
,"%s skipped\n", wpnt
->name
);
382 /**********************************************************************
384 * Load one NE format executable into memory
386 HINSTANCE
NE_LoadImage(struct w_files
*wpnt
)
388 unsigned int read_size
, status
, segment
;
391 wpnt
->ne
= malloc(sizeof(struct ne_data
));
392 wpnt
->ne
->resnamtab
= NULL
;
393 wpnt
->ne
->ne_header
= malloc(sizeof(struct ne_header_s
));
395 lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
, SEEK_SET
);
396 if (read(wpnt
->fd
, wpnt
->ne
->ne_header
, sizeof(struct ne_header_s
))
397 != sizeof(struct ne_header_s
))
398 myerror("Unable to read NE header from file");
399 if(!(wpnt
->ne
->ne_header
->format_flags
& NE_FFLAGS_LIBMODULE
)){
400 if(current_exe
)printf("Warning: more than one EXE\n");
406 * Create segment selectors.
408 status
= lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
+
409 wpnt
->ne
->ne_header
->segment_tab_offset
,
411 read_size
= wpnt
->ne
->ne_header
->n_segment_tab
*
412 sizeof(struct ne_segment_table_entry_s
);
413 wpnt
->ne
->seg_table
= (struct ne_segment_table_entry_s
*) malloc(read_size
);
414 if (read(wpnt
->fd
, wpnt
->ne
->seg_table
, read_size
) != read_size
)
415 myerror("Unable to read segment table header from file");
416 wpnt
->ne
->selector_table
= CreateSelectors(wpnt
);
417 if(wpnt
->ne
->ne_header
->auto_data_seg
==0)
419 printf("DATA NONE DLL %s\n",wpnt
->name
);
420 wpnt
->hinstance
=current_nodata
++;
422 wpnt
->hinstance
= (wpnt
->ne
->
423 selector_table
[wpnt
->ne
->ne_header
->auto_data_seg
-1].
425 if (wpnt
->hinstance
== 0)
426 wpnt
->hinstance
= 0xf000;
428 /* Get the lookup table. This is used for looking up the addresses
429 of functions that are exported */
431 read_size
= wpnt
->ne
->ne_header
->entry_tab_length
;
432 wpnt
->ne
->lookup_table
= (char *) malloc(read_size
);
433 lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
+
434 wpnt
->ne
->ne_header
->entry_tab_offset
, SEEK_SET
);
435 if (read(wpnt
->fd
, wpnt
->ne
->lookup_table
, read_size
) != read_size
)
436 myerror("Unable to read lookup table header from file");
438 /* Get the iname table. This is used for looking up the names
439 of functions that are exported */
441 status
= lseek(wpnt
->fd
, wpnt
->ne
->ne_header
->nrname_tab_offset
, SEEK_SET
);
442 read_size
= wpnt
->ne
->ne_header
->nrname_tab_length
;
443 wpnt
->ne
->nrname_table
= (char *) malloc(read_size
);
444 if (read(wpnt
->fd
, wpnt
->ne
->nrname_table
, read_size
) != read_size
)
445 myerror("Unable to read nrname table header from file");
447 status
= lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
+
448 wpnt
->ne
->ne_header
->rname_tab_offset
, SEEK_SET
);
449 read_size
= wpnt
->ne
->ne_header
->moduleref_tab_offset
-
450 wpnt
->ne
->ne_header
->rname_tab_offset
;
451 wpnt
->ne
->rname_table
= (char *) malloc(read_size
);
452 if (read(wpnt
->fd
, wpnt
->ne
->rname_table
, read_size
) != read_size
)
453 myerror("Unable to read rname table header from file");
456 * Now load any DLLs that this module refers to.
458 for(i
=0; i
<wpnt
->ne
->ne_header
->n_mod_ref_tab
; i
++)
461 NE_GetModuleName(wpnt
, i
+ 1, buff
);
463 if (strcasecmp(buff
, wpnt
->name
) != 0 )
464 LoadImage(buff
, DLL
, 0);
467 /* fixup references */
469 for (segment
= 0; segment
< wpnt
->ne
->ne_header
->n_segment_tab
; segment
++)
470 if (NE_FixupSegment(wpnt
, segment
) < 0)
471 myerror("fixup failed.");
473 FixupFunctionPrologs(wpnt
);
474 InitializeLoadedDLLs(wpnt
);
476 return(wpnt
->hinstance
);
479 #endif /* !WINELIB */