Release 941122
[wine/multimedia.git] / loader / ne_image.c
blob8cf62a9ffe62e081c702c2e9b413a7d7ec66530e
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";
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9 #include <unistd.h>
10 #include <ctype.h>
11 #ifdef linux
12 #include <linux/head.h>
13 #include <linux/ldt.h>
14 #include <linux/segment.h>
15 #endif
16 #include <string.h>
17 #include <errno.h>
18 #include "neexe.h"
19 #include "segmem.h"
20 #include "prototypes.h"
21 #include "dlls.h"
22 #include "wine.h"
23 #include "windows.h"
24 #include "wineopts.h"
25 #include "arch.h"
26 #include "options.h"
27 #include "stddebug.h"
28 #include "debug.h"
30 extern HANDLE CreateNewTask(HINSTANCE hInst);
31 extern void InitializeLoadedDLLs(struct w_files *wpnt);
32 extern int CallToInit16(unsigned long csip, unsigned long sssp,
33 unsigned short ds);
34 extern int CallTo16cx(unsigned long csip, unsigned long dscx);
35 extern void CallTo32();
36 extern char WindowsPath[256];
37 extern unsigned short WIN_StackSize;
38 extern unsigned short WIN_HeapSize;
40 int FixupSegment(struct w_files *, int);
41 void FixupFunctionPrologs(struct w_files *);
42 char *GetModuleName(struct w_files * wpnt, int index, char *buffer);
44 #ifndef WINELIB
46 /**********************************************************************/
48 void load_ne_header (int fd, struct ne_header_s *ne_header)
50 if (read(fd, ne_header, sizeof(struct ne_header_s))
51 != sizeof(struct ne_header_s))
53 myerror("Unable to read NE header from file");
56 #endif
58 /**********************************************************************
59 * LoadNEImage
60 * Load one NE format executable into memory
62 HINSTANCE LoadNEImage(struct w_files *wpnt)
64 unsigned int read_size, status, segment;
65 int i;
67 wpnt->ne = malloc(sizeof(struct ne_data));
68 wpnt->ne->resnamtab = NULL;
69 wpnt->ne->ne_header = malloc(sizeof(struct ne_header_s));
70 lseek(wpnt->fd, wpnt->mz_header->ne_offset, SEEK_SET);
71 load_ne_header(wpnt->fd, wpnt->ne->ne_header);
73 #ifndef WINELIB
75 * Create segment selectors.
77 status = lseek(wpnt->fd, wpnt->mz_header->ne_offset +
78 wpnt->ne->ne_header->segment_tab_offset,
79 SEEK_SET);
80 read_size = wpnt->ne->ne_header->n_segment_tab *
81 sizeof(struct ne_segment_table_entry_s);
82 wpnt->ne->seg_table = (struct ne_segment_table_entry_s *) malloc(read_size);
83 if (read(wpnt->fd, wpnt->ne->seg_table, read_size) != read_size)
84 myerror("Unable to read segment table header from file");
85 wpnt->ne->selector_table = CreateSelectors(wpnt);
86 wpnt->hinstance = (wpnt->ne->
87 selector_table[wpnt->ne->ne_header->auto_data_seg-1].
88 selector);
89 #endif
90 /* Get the lookup table. This is used for looking up the addresses
91 of functions that are exported */
93 read_size = wpnt->ne->ne_header->entry_tab_length;
94 wpnt->ne->lookup_table = (char *) malloc(read_size);
95 lseek(wpnt->fd, wpnt->mz_header->ne_offset +
96 wpnt->ne->ne_header->entry_tab_offset, SEEK_SET);
97 if (read(wpnt->fd, wpnt->ne->lookup_table, read_size) != read_size)
98 myerror("Unable to read lookup table header from file");
100 /* Get the iname table. This is used for looking up the names
101 of functions that are exported */
103 status = lseek(wpnt->fd, wpnt->ne->ne_header->nrname_tab_offset, SEEK_SET);
104 read_size = wpnt->ne->ne_header->nrname_tab_length;
105 wpnt->ne->nrname_table = (char *) malloc(read_size);
106 if (read(wpnt->fd, wpnt->ne->nrname_table, read_size) != read_size)
107 myerror("Unable to read nrname table header from file");
109 status = lseek(wpnt->fd, wpnt->mz_header->ne_offset +
110 wpnt->ne->ne_header->rname_tab_offset, SEEK_SET);
111 read_size = wpnt->ne->ne_header->moduleref_tab_offset -
112 wpnt->ne->ne_header->rname_tab_offset;
113 wpnt->ne->rname_table = (char *) malloc(read_size);
114 if (read(wpnt->fd, wpnt->ne->rname_table, read_size) != read_size)
115 myerror("Unable to read rname table header from file");
118 * Now load any DLLs that this module refers to.
120 for(i=0; i<wpnt->ne->ne_header->n_mod_ref_tab; i++)
122 char buff[14];
123 GetModuleName(wpnt, i + 1, buff);
125 if (strcasecmp(buff, wpnt->name) != 0 )
126 LoadImage(buff, DLL, 0);
128 #ifndef WINELIB
129 /* fixup references */
131 for (segment = 0; segment < wpnt->ne->ne_header->n_segment_tab; segment++)
132 if (FixupSegment(wpnt, segment) < 0)
133 myerror("fixup failed.");
135 FixupFunctionPrologs(wpnt);
136 InitializeLoadedDLLs(wpnt);
137 #endif
138 return(wpnt->hinstance);
141 /**********************************************************************
142 * GetImportedName
144 char *
145 GetImportedName(int fd, struct mz_header_s *mz_header,
146 struct ne_header_s *ne_header, int name_offset, char *buffer)
148 int length;
149 int status;
151 status = lseek(fd, mz_header->ne_offset + ne_header->iname_tab_offset +
152 name_offset, SEEK_SET);
153 length = 0;
154 read(fd, &length, 1); /* Get the length byte */
155 length = CONV_CHAR_TO_LONG (length);
156 read(fd, buffer, length);
157 buffer[length] = 0;
158 return buffer;
161 /**********************************************************************
162 * GetModuleName
164 char *
165 GetModuleName(struct w_files * wpnt, int index, char *buffer)
167 int fd = wpnt->fd;
168 struct mz_header_s *mz_header = wpnt->mz_header;
169 struct ne_header_s *ne_header = wpnt->ne->ne_header;
170 int length;
171 WORD name_offset, status;
172 int i;
174 status = lseek(fd, mz_header->ne_offset + ne_header->moduleref_tab_offset +
175 2*(index - 1), SEEK_SET);
176 name_offset = 0;
177 read(fd, &name_offset, 2);
178 name_offset = CONV_SHORT (name_offset);
179 status = lseek(fd, mz_header->ne_offset + ne_header->iname_tab_offset +
180 name_offset, SEEK_SET);
181 length = 0;
182 read(fd, &length, 1); /* Get the length byte */
183 length = CONV_CHAR_TO_LONG (length);
184 read(fd, buffer, length);
185 buffer[length] = 0;
187 /* Module names are always upper case */
188 for(i=0; i<length; i++)
189 if (islower(buffer[i]))
190 buffer[i] = toupper(buffer[i]);
192 return buffer;
196 #ifndef WINELIB
197 /**********************************************************************
198 * FixupSegment
201 FixupSegment(struct w_files * wpnt, int segment_num)
203 struct mz_header_s *mz_header = wpnt->mz_header;
204 struct ne_header_s *ne_header = wpnt->ne->ne_header;
205 struct ne_segment_table_entry_s *seg_table = wpnt->ne->seg_table;
206 struct segment_descriptor_s *selector_table = wpnt->ne->selector_table;
207 struct relocation_entry_s *rep, *rep1;
208 struct ne_segment_table_entry_s *seg;
209 struct segment_descriptor_s *sel;
210 int status;
211 unsigned short *sp;
212 unsigned int selector, address;
213 unsigned int next_addr;
214 int ordinal;
215 char dll_name[257];
216 char func_name[257];
217 int i, n_entries;
218 int additive;
220 seg = &seg_table[segment_num];
221 sel = &selector_table[segment_num];
223 dprintf_fixup(stddeb, "Segment fixups for %s, segment %d, selector %x\n",
224 wpnt->name, segment_num, (int) sel->base_addr >> 16);
226 if ((seg->seg_data_offset == 0) ||
227 !(seg->seg_flags & NE_SEGFLAGS_RELOC_DATA))
228 return 0;
231 * Go through the relocation table on entry at a time.
233 i = seg->seg_data_length;
234 if (i == 0)
235 i = 0x10000;
237 status = lseek(wpnt->fd, seg->seg_data_offset *
238 (1 << ne_header->align_shift_count) + i, SEEK_SET);
239 n_entries = 0;
240 read(wpnt->fd, &n_entries, sizeof(short int));
241 rep = (struct relocation_entry_s *)
242 malloc(n_entries * sizeof(struct relocation_entry_s));
244 if (read(wpnt->fd, rep, n_entries * sizeof(struct relocation_entry_s)) !=
245 n_entries * sizeof(struct relocation_entry_s))
247 myerror("Unable to read relocation information");
250 rep1 = rep;
252 for (i = 0; i < n_entries; i++, rep++)
255 * Get the target address corresponding to this entry.
257 additive = 0;
259 switch (rep->relocation_type)
261 case NE_RELTYPE_ORDINALADD:
262 additive = 1;
264 case NE_RELTYPE_ORDINAL:
265 if (GetModuleName(wpnt, rep->target1,
266 dll_name) == NULL)
268 fprintf(stderr, "NE_RELTYPE_ORDINAL failed");
269 return -1;
272 ordinal = rep->target2;
274 status = GetEntryDLLOrdinal(dll_name, ordinal, &selector,
275 &address);
276 if (status)
278 char s[80];
280 sprintf(s, "Bad DLL name '%s.%d'", dll_name, ordinal);
281 myerror(s);
282 return -1;
285 dprintf_fixup(stddeb,"%d: %s.%d: %04x:%04x\n", i + 1,
286 dll_name, ordinal, selector, address);
287 break;
289 case NE_RELTYPE_NAMEADD:
290 additive = 1;
292 case NE_RELTYPE_NAME:
293 if (GetModuleName(wpnt, rep->target1, dll_name)
294 == NULL)
296 fprintf(stderr,"NE_RELTYPE_NAME failed");
297 return -1;
300 if (GetImportedName(wpnt->fd, mz_header, ne_header,
301 rep->target2, func_name) == NULL)
303 fprintf(stderr,"getimportedname failed");
304 return -1;
307 status = GetEntryDLLName(dll_name, func_name, &selector,
308 &address);
309 if (status)
311 char s[80];
313 sprintf(s, "Bad DLL name '%s (%s)'", dll_name,func_name);
314 myerror(s);
315 return -1;
318 dprintf_fixup(stddeb,"%d: %s %s.%d: %04x:%04x\n", i + 1,
319 func_name, dll_name, ordinal, selector, address);
320 break;
322 case NE_RELTYPE_INTERNAL:
323 case NE_RELTYPE_INT1:
324 if (rep->target1 == 0x00ff)
326 address = GetEntryPointFromOrdinal(wpnt, rep->target2);
327 selector = (address >> 16) & 0xffff;
328 address &= 0xffff;
330 else
332 selector = selector_table[rep->target1-1].selector;
333 address = rep->target2;
336 dprintf_fixup(stddeb,"%d: %04x:%04x\n",
337 i + 1, selector, address);
338 break;
340 case 7:
341 /* Relocation type 7:
343 * These appear to be used as fixups for the Windows
344 * floating point emulator. Let's just ignore them and
345 * try to use the hardware floating point. Linux should
346 * successfully emulate the coprocessor if it doesn't
347 * exist.
349 dprintf_fixup(stddeb,
350 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
351 i + 1, rep->address_type, rep->relocation_type,
352 rep->offset);
353 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
354 rep->target1, rep->target2);
355 continue;
357 default:
358 dprintf_fixup(stddeb,
359 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
360 i + 1, rep->address_type, rep->relocation_type,
361 rep->offset);
362 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
363 rep->target1, rep->target2);
364 free(rep1);
365 return -1;
369 * Stuff the right size result in.
371 sp = (unsigned short *) ((char *) sel->base_addr + rep->offset);
372 if (additive)
374 if (FindDLLTable(dll_name) == NULL)
375 additive = 2;
376 dprintf_fixup(stddeb,
377 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
378 i + 1, rep->address_type, rep->relocation_type,
379 rep->offset);
380 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
381 rep->target1, rep->target2);
382 dprintf_fixup(stddeb, " Additive = %d\n", additive);
385 switch (rep->address_type)
387 case NE_RADDR_OFFSET16:
388 do {
389 dprintf_fixup(stddeb," %04x:%04x:%04x OFFSET16\n",
390 (unsigned int) sp >> 16, (int) sp & 0xFFFF, *sp);
391 next_addr = *sp;
392 *sp = (unsigned short) address;
393 if (additive == 2)
394 *sp += next_addr;
395 sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
397 while (next_addr != 0xffff && !additive);
399 break;
401 case NE_RADDR_POINTER32:
402 do {
403 dprintf_fixup(stddeb," %04x:%04x:%04x POINTER32\n",
404 (unsigned int) sp >> 16, (int) sp & 0xFFFF, *sp);
405 next_addr = *sp;
406 *sp = (unsigned short) address;
407 if (additive == 2)
408 *sp += next_addr;
409 *(sp+1) = (unsigned short) selector;
410 sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
412 while (next_addr != 0xffff && !additive);
414 break;
416 case NE_RADDR_SELECTOR:
417 do {
418 dprintf_fixup(stddeb," %04x:%04x:%04x SELECTOR\n",
419 (unsigned int) sp >> 16, (int) sp & 0xFFFF, *sp);
420 next_addr = *sp;
421 *sp = (unsigned short) selector;
422 sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
423 if (rep->relocation_type == NE_RELTYPE_INT1)
424 break;
426 while (next_addr != 0xffff && !additive);
428 break;
430 default:
431 dprintf_fixup(stddeb,
432 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
433 i + 1, rep->address_type, rep->relocation_type,
434 rep->offset);
435 dprintf_fixup(stddeb,
436 "TARGET %04x %04x\n", rep->target1, rep->target2);
437 free(rep1);
438 return -1;
442 free(rep1);
443 return 0;
446 int NEunloadImage(struct w_files *wpnt)
448 dprintf_fixup(stdnimp, "NEunloadImage() called!\n");
449 /* free resources, image */
450 return 1;
453 int StartNEprogram(struct w_files *wpnt)
455 int cs_reg, ds_reg, ss_reg, ip_reg, sp_reg;
457 * Fixup stack and jump to start.
459 WIN_StackSize = wpnt->ne->ne_header->stack_length;
460 WIN_HeapSize = wpnt->ne->ne_header->local_heap_length;
462 ds_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->auto_data_seg-1].selector;
463 cs_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->cs-1].selector;
464 ip_reg = wpnt->ne->ne_header->ip;
465 ss_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->ss-1].selector;
466 sp_reg = wpnt->ne->ne_header->sp;
468 return CallToInit16(cs_reg << 16 | ip_reg, ss_reg << 16 | sp_reg, ds_reg);
471 void InitNEDLL(struct w_files *wpnt)
473 int cs_reg, ds_reg, ip_reg, cx_reg, rv;
475 * Is this a library?
477 if (wpnt->ne->ne_header->format_flags & 0x8000)
479 if (!(wpnt->ne->ne_header->format_flags & 0x0001))
481 /* Not SINGLEDATA */
482 fprintf(stderr, "Library is not marked SINGLEDATA\n");
483 exit(1);
486 ds_reg = wpnt->ne->selector_table[wpnt->ne->
487 ne_header->auto_data_seg-1].selector;
488 cs_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->cs-1].selector;
489 ip_reg = wpnt->ne->ne_header->ip;
491 cx_reg = wpnt->ne->ne_header->local_heap_length;
493 if (cs_reg) {
494 dprintf_dll(stddeb,"Initializing %s, cs:ip %04x:%04x, ds %04x, cx %04x\n",
495 wpnt->name, cs_reg, ip_reg, ds_reg, cx_reg);
497 rv = CallTo16cx(cs_reg << 16 | ip_reg, ds_reg | (cx_reg<<16));
498 dprintf_exec(stddeb,"rv = %x\n", rv);
499 } else
500 dprintf_exec(stddeb,"%s skipped\n", wpnt->name);
504 #endif /* !WINELIB */