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";
11 #include <linux/unistd.h>
12 #include <linux/head.h>
13 #include <linux/ldt.h>
14 #include <linux/segment.h>
20 #include "prototypes.h"
28 /* #define DEBUG_FIXUP /* */
30 extern HANDLE
CreateNewTask(HINSTANCE hInst
);
31 extern int CallToInit16(unsigned long csip
, unsigned long sssp
,
33 extern void InitializeLoadedDLLs(struct w_files
*wpnt
);
34 extern void FixupFunctionPrologs(struct w_files
* wpnt
);
36 char * GetModuleName(struct w_files
* wpnt
, int index
, char *buffer
);
37 extern char WindowsPath
[256];
38 char *WIN_ProgramName
;
44 /**********************************************************************/
46 void load_ne_header (int fd
, struct ne_header_s
*ne_header
)
48 if (read(fd
, ne_header
, sizeof(struct ne_header_s
))
49 != sizeof(struct ne_header_s
))
51 myerror("Unable to read NE header from file");
56 /**********************************************************************
58 * Load one NE format executable into memory
60 HINSTANCE
LoadNEImage(struct w_files
*wpnt
)
62 unsigned int read_size
, status
, segment
;
68 wpnt
->ne_header
= (struct ne_header_s
*) malloc(sizeof(struct ne_header_s
));
69 status
= lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
, SEEK_SET
);
70 load_ne_header (wpnt
->fd
, wpnt
->ne_header
);
74 * Create segment selectors.
76 status
= lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
+
77 wpnt
->ne_header
->segment_tab_offset
,
79 read_size
= wpnt
->ne_header
->n_segment_tab
*
80 sizeof(struct ne_segment_table_entry_s
);
81 wpnt
->seg_table
= (struct ne_segment_table_entry_s
*) malloc(read_size
);
82 if (read(wpnt
->fd
, wpnt
->seg_table
, read_size
) != read_size
)
83 myerror("Unable to read segment table header from file");
84 wpnt
->selector_table
= CreateSelectors(wpnt
);
85 wpnt
->hinstance
= (wpnt
->
86 selector_table
[wpnt
->ne_header
->auto_data_seg
-1].
89 /* Get the lookup table. This is used for looking up the addresses
90 of functions that are exported */
92 read_size
= wpnt
->ne_header
->entry_tab_length
;
93 wpnt
->lookup_table
= (char *) malloc(read_size
);
94 lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
+
95 wpnt
->ne_header
->entry_tab_offset
, SEEK_SET
);
96 if (read(wpnt
->fd
, wpnt
->lookup_table
, read_size
) != read_size
)
97 myerror("Unable to read lookup table header from file");
99 /* Get the iname table. This is used for looking up the names
100 of functions that are exported */
102 status
= lseek(wpnt
->fd
, wpnt
->ne_header
->nrname_tab_offset
, SEEK_SET
);
103 read_size
= wpnt
->ne_header
->nrname_tab_length
;
104 wpnt
->nrname_table
= (char *) malloc(read_size
);
105 if (read(wpnt
->fd
, wpnt
->nrname_table
, read_size
) != read_size
)
106 myerror("Unable to read nrname table header from file");
108 status
= lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
+
109 wpnt
->ne_header
->rname_tab_offset
, SEEK_SET
);
110 read_size
= wpnt
->ne_header
->moduleref_tab_offset
-
111 wpnt
->ne_header
->rname_tab_offset
;
112 wpnt
->rname_table
= (char *) malloc(read_size
);
113 if (read(wpnt
->fd
, wpnt
->rname_table
, read_size
) != read_size
)
114 myerror("Unable to read rname table header from file");
116 /* Now get the module name, if the current one is a filename */
117 /* nope, name by which dll is loaded is used !
119 if (strchr(wpnt->name, '\\') || strchr(wpnt->name, '/') ) {
120 wpnt->name = (char*) malloc(*wpnt->rname_table + 1);
121 memcpy(wpnt->name, wpnt->rname_table+1, *wpnt->rname_table);
123 wpnt->name[*wpnt->rname_table] = 0;
126 * Now load any DLLs that this module refers to.
128 for(i
=0; i
<wpnt
->ne_header
->n_mod_ref_tab
; i
++)
131 GetModuleName(wpnt
, i
+ 1, buff
);
133 if (strcasecmp(buff
, wpnt
->name
) != 0 )
134 LoadImage(buff
, DLL
, 0);
137 /* fixup references */
139 for (segment
= 0; segment
< wpnt
->ne_header
->n_segment_tab
; segment
++)
140 if (FixupSegment(wpnt
, segment
) < 0)
141 myerror("fixup failed.");
143 FixupFunctionPrologs(wpnt
);
144 InitializeLoadedDLLs(wpnt
);
146 return(wpnt
->hinstance
);
149 /**********************************************************************
153 GetImportedName(int fd
, struct mz_header_s
*mz_header
,
154 struct ne_header_s
*ne_header
, int name_offset
, char *buffer
)
159 status
= lseek(fd
, mz_header
->ne_offset
+ ne_header
->iname_tab_offset
+
160 name_offset
, SEEK_SET
);
162 read(fd
, &length
, 1); /* Get the length byte */
163 length
= CONV_CHAR_TO_LONG (length
);
164 read(fd
, buffer
, length
);
169 /**********************************************************************
173 GetModuleName(struct w_files
* wpnt
, int index
, char *buffer
)
176 struct mz_header_s
*mz_header
= wpnt
->mz_header
;
177 struct ne_header_s
*ne_header
= wpnt
->ne_header
;
179 WORD name_offset
, status
;
182 status
= lseek(fd
, mz_header
->ne_offset
+ ne_header
->moduleref_tab_offset
+
183 2*(index
- 1), SEEK_SET
);
185 read(fd
, &name_offset
, 2);
186 name_offset
= CONV_SHORT (name_offset
);
187 status
= lseek(fd
, mz_header
->ne_offset
+ ne_header
->iname_tab_offset
+
188 name_offset
, SEEK_SET
);
190 read(fd
, &length
, 1); /* Get the length byte */
191 length
= CONV_CHAR_TO_LONG (length
);
192 read(fd
, buffer
, length
);
195 /* Module names are always upper case */
196 for(i
=0; i
<length
; i
++)
197 if(buffer
[i
] >= 'a' && buffer
[i
] <= 'z') buffer
[i
] &= ~0x20;
204 /**********************************************************************
208 FixupSegment(struct w_files
* wpnt
, int segment_num
)
211 struct mz_header_s
* mz_header
= wpnt
->mz_header
;
212 struct ne_header_s
*ne_header
= wpnt
->ne_header
;
213 struct ne_segment_table_entry_s
*seg_table
= wpnt
->seg_table
;
214 struct segment_descriptor_s
*selector_table
= wpnt
->selector_table
;
215 struct relocation_entry_s
*rep
, *rep1
;
216 struct ne_segment_table_entry_s
*seg
;
217 struct segment_descriptor_s
*sel
;
218 struct dll_table_entry_s
*dll_table
;
221 unsigned int selector
, address
;
222 unsigned int next_addr
;
229 seg
= &seg_table
[segment_num
];
230 sel
= &selector_table
[segment_num
];
233 printf("Segment fixups for %s, segment %d, selector %x\n",
234 wpnt
->name
, segment_num
, (int) sel
->base_addr
>> 16);
237 if ((seg
->seg_data_offset
== 0) ||
238 !(seg
->seg_flags
& NE_SEGFLAGS_RELOC_DATA
))
242 * Go through the relocation table on entry at a time.
244 i
= seg
->seg_data_length
;
248 status
= lseek(fd
, seg
->seg_data_offset
*
249 (1 << ne_header
->align_shift_count
) + i
, SEEK_SET
);
251 read(fd
, &n_entries
, sizeof(short int));
252 rep
= (struct relocation_entry_s
*)
253 malloc(n_entries
* sizeof(struct relocation_entry_s
));
255 if (read(fd
,rep
, n_entries
* sizeof(struct relocation_entry_s
)) !=
256 n_entries
* sizeof(struct relocation_entry_s
))
258 myerror("Unable to read relocation information");
263 for (i
= 0; i
< n_entries
; i
++, rep
++)
266 * Get the target address corresponding to this entry.
270 switch (rep
->relocation_type
)
272 case NE_RELTYPE_ORDINALADD
:
275 case NE_RELTYPE_ORDINAL
:
276 if (GetModuleName(wpnt
, rep
->target1
,
279 fprintf(stderr
, "NE_RELTYPE_ORDINAL failed");
283 ordinal
= rep
->target2
;
285 status
= GetEntryDLLOrdinal(dll_name
, ordinal
, &selector
,
291 sprintf(s
, "Bad DLL name '%s.%d'", dll_name
, ordinal
);
297 printf("%d: %s.%d: %04.4x:%04.4x\n", i
+ 1, dll_name
, ordinal
,
302 case NE_RELTYPE_NAMEADD
:
305 case NE_RELTYPE_NAME
:
306 if (GetModuleName(wpnt
, rep
->target1
, dll_name
)
309 fprintf(stderr
,"NE_RELTYPE_NAME failed");
313 if (GetImportedName(fd
, mz_header
, ne_header
,
314 rep
->target2
, func_name
) == NULL
)
316 fprintf(stderr
,"getimportedname failed");
320 status
= GetEntryDLLName(dll_name
, func_name
, &selector
,
326 sprintf(s
, "Bad DLL name '%s (%s)'", dll_name
,func_name
);
332 printf("%d: %s %s.%d: %04.4x:%04.4x\n", i
+ 1, func_name
,
333 dll_name
, ordinal
, selector
, address
);
337 case NE_RELTYPE_INTERNAL
:
338 case NE_RELTYPE_INT1
:
339 if (rep
->target1
== 0x00ff)
341 address
= GetEntryPointFromOrdinal(wpnt
, rep
->target2
);
342 selector
= (address
>> 16) & 0xffff;
347 selector
= selector_table
[rep
->target1
-1].selector
;
348 address
= rep
->target2
;
352 printf("%d: %04.4x:%04.4x\n", i
+ 1, selector
, address
);
357 /* Relocation type 7:
359 * These appear to be used as fixups for the Windows
360 * floating point emulator. Let's just ignore them and
361 * try to use the hardware floating point. Linux should
362 * successfully emulate the coprocessor if it doesn't
366 printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
367 i
+ 1, rep
->address_type
, rep
->relocation_type
,
369 printf("TARGET %04.4x %04.4x\n", rep
->target1
, rep
->target2
);
374 fprintf(stderr
,"%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
375 i
+ 1, rep
->address_type
, rep
->relocation_type
,
377 fprintf(stderr
,"TARGET %04.4x %04.4x\n",
378 rep
->target1
, rep
->target2
);
384 * Stuff the right size result in.
386 sp
= (unsigned short *) ((char *) sel
->base_addr
+ rep
->offset
);
389 if (FindDLLTable(dll_name
) == NULL
)
392 fprintf(stderr
,"%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
393 i
+ 1, rep
->address_type
, rep
->relocation_type
,
395 fprintf(stderr
,"TARGET %04.4x %04.4x\n",
396 rep
->target1
, rep
->target2
);
397 fprintf(stderr
, " Additive = %d\n", additive
);
400 switch (rep
->address_type
)
402 case NE_RADDR_OFFSET16
:
405 printf(" %04.4x:%04.4x:%04.4x OFFSET16\n",
406 (unsigned long) sp
>> 16, (int) sp
& 0xFFFF, *sp
);
409 *sp
= (unsigned short) address
;
412 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
414 while (next_addr
!= 0xffff && !additive
);
418 case NE_RADDR_POINTER32
:
421 printf(" %04.4x:%04.4x:%04.4x POINTER32\n",
422 (unsigned long) sp
>> 16, (int) sp
& 0xFFFF, *sp
);
425 *sp
= (unsigned short) address
;
428 *(sp
+1) = (unsigned short) selector
;
429 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
431 while (next_addr
!= 0xffff && !additive
);
435 case NE_RADDR_SELECTOR
:
438 printf(" %04.4x:%04.4x:%04.4x SELECTOR\n",
439 (unsigned long) sp
>> 16, (int) sp
& 0xFFFF, *sp
);
442 *sp
= (unsigned short) selector
;
443 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
444 if (rep
->relocation_type
== NE_RELTYPE_INT1
)
447 while (next_addr
!= 0xffff && !additive
);
452 printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
453 i
+ 1, rep
->address_type
, rep
->relocation_type
,
455 printf("TARGET %04.4x %04.4x\n", rep
->target1
, rep
->target2
);
465 #endif /* !WINELIB */