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"
27 /* #define DEBUG_FIXUP */
29 extern int CallToInit16(unsigned long csip, unsigned long sssp,
31 extern void CallTo32();
33 char * GetModuleName(struct w_files * wpnt, int index, char *buffer);
34 extern unsigned char ran_out;
35 extern char WindowsPath[256];
36 unsigned short WIN_StackSize;
37 unsigned short WIN_HeapSize;
39 struct w_files * wine_files = NULL;
41 int WineForceFail = 0;
45 struct mz_header_s *CurrentMZHeader;
46 struct ne_header_s *CurrentNEHeader;
50 static char *DLL_Extensions[] = { "dll", "exe", NULL };
51 static char *EXE_Extensions[] = { "exe", NULL };
52 static char *WinePath = NULL;
56 /**********************************************************************
60 myerror(const char *s)
65 fprintf(stderr, "wine: %s\n", s);
70 /**********************************************************************
71 * GetFilenameFromInstance
74 GetFilenameFromInstance(unsigned short instance)
76 register struct w_files *w = wine_files;
78 while (w && w->hinstance != instance)
88 GetFileInfo(unsigned short instance)
90 register struct w_files *w = wine_files;
92 while (w && w->hinstance != instance)
99 /**********************************************************************
103 void load_mz_header(int fd, struct mz_header_s *mz_header)
105 if (read(fd, mz_header, sizeof(struct mz_header_s)) !=
106 sizeof(struct mz_header_s))
108 myerror("Unable to read MZ header from file");
112 void load_ne_header (int fd, struct ne_header_s *ne_header)
114 if (read(fd, ne_header, sizeof(struct ne_header_s))
115 != sizeof(struct ne_header_s))
117 myerror("Unable to read NE header from file");
122 /**********************************************************************
124 * Load one NE format executable into memory
126 HINSTANCE LoadImage(char *modulename, int filetype)
128 unsigned int read_size;
130 struct w_files * wpnt, *wpnt1;
137 if (FindFile(buffer, sizeof(buffer), modulename, (filetype == EXE ?
138 EXE_Extensions : DLL_Extensions), WindowsPath) ==NULL)
140 fprintf(stderr,"LoadImage: I can't find %s !\n",modulename);
141 return (HINSTANCE) NULL;
143 fprintf(stderr,"LoadImage: loading %s (%s)\n", modulename, buffer);
145 /* First allocate a spot to store the info we collect, and add it to
149 wpnt = (struct w_files *) malloc(sizeof(struct w_files));
150 if(wine_files == NULL)
154 while(wpnt1->next) wpnt1 = wpnt1->next;
160 * Open file for reading.
162 wpnt->fd = open(buffer, O_RDONLY);
168 * Establish header pointers.
170 wpnt->filename = strdup(buffer);
172 if(modulename) wpnt->name = strdup(modulename);
174 wpnt->mz_header = (struct mz_header_s *) malloc(sizeof(struct mz_header_s));;
175 status = lseek(wpnt->fd, 0, SEEK_SET);
176 load_mz_header (wpnt->fd, wpnt->mz_header);
177 if (wpnt->mz_header->must_be_0x40 != 0x40)
178 myerror("This is not a Windows program");
180 wpnt->ne_header = (struct ne_header_s *) malloc(sizeof(struct ne_header_s));
181 status = lseek(wpnt->fd, wpnt->mz_header->ne_offset, SEEK_SET);
182 load_ne_header (wpnt->fd, wpnt->ne_header);
183 if (wpnt->ne_header->header_type[0] != 'N' ||
184 wpnt->ne_header->header_type[1] != 'E')
185 myerror("This is not a Windows program");
187 if(wine_files == wpnt){
188 CurrentMZHeader = wpnt->mz_header;
189 CurrentNEHeader = wpnt->ne_header;
190 CurrentNEFile = wpnt->fd;
192 WIN_StackSize = wpnt->ne_header->stack_length;
193 WIN_HeapSize = wpnt->ne_header->local_heap_length;
197 * Create segment selectors.
200 status = lseek(wpnt->fd, wpnt->mz_header->ne_offset +
201 wpnt->ne_header->segment_tab_offset,
203 read_size = wpnt->ne_header->n_segment_tab *
204 sizeof(struct ne_segment_table_entry_s);
205 wpnt->seg_table = (struct ne_segment_table_entry_s *) malloc(read_size);
206 if (read(wpnt->fd, wpnt->seg_table, read_size) != read_size)
207 myerror("Unable to read segment table header from file");
208 wpnt->selector_table = CreateSelectors(wpnt);
211 selector_table[wpnt->ne_header->auto_data_seg-1].selector;
213 /* Get the lookup table. This is used for looking up the addresses
214 of functions that are exported */
216 read_size = wpnt->ne_header->entry_tab_length;
217 wpnt->lookup_table = (char *) malloc(read_size);
218 lseek(wpnt->fd, wpnt->mz_header->ne_offset +
219 wpnt->ne_header->entry_tab_offset, SEEK_SET);
220 if (read(wpnt->fd, wpnt->lookup_table, read_size) != read_size)
221 myerror("Unable to read lookup table header from file");
223 /* Get the iname table. This is used for looking up the names
224 of functions that are exported */
226 status = lseek(wpnt->fd, wpnt->ne_header->nrname_tab_offset, SEEK_SET);
227 read_size = wpnt->ne_header->nrname_tab_length;
228 wpnt->nrname_table = (char *) malloc(read_size);
229 if (read(wpnt->fd, wpnt->nrname_table, read_size) != read_size)
230 myerror("Unable to read nrname table header from file");
232 status = lseek(wpnt->fd, wpnt->mz_header->ne_offset +
233 wpnt->ne_header->rname_tab_offset, SEEK_SET);
234 read_size = wpnt->ne_header->moduleref_tab_offset -
235 wpnt->ne_header->rname_tab_offset;
236 wpnt->rname_table = (char *) malloc(read_size);
237 if (read(wpnt->fd, wpnt->rname_table, read_size) != read_size)
238 myerror("Unable to read rname table header from file");
240 /* Now get the module name */
242 wpnt->name = (char*) malloc(*wpnt->rname_table + 1);
243 memcpy(wpnt->name, wpnt->rname_table+1, *wpnt->rname_table);
244 wpnt->name[*wpnt->rname_table] = 0;
247 * Now load any DLLs that this module refers to.
249 for(i=0; i<wpnt->ne_header->n_mod_ref_tab; i++){
253 GetModuleName(wpnt, i + 1, buff);
256 if(FindDLLTable(buff)) continue; /* This module already loaded */
259 LoadImage(buff, DLL);
261 fprintf(stderr,"Unable to load:%s\n", buff);
264 return(wpnt->hinstance);
268 /**********************************************************************
271 _WinMain(int argc, char **argv)
282 struct w_files * wpnt;
283 int cs_reg, ds_reg, ss_reg, ip_reg, sp_reg;
290 WinePath = malloc(1024);
292 getcwd(WinePath, 512);
294 if ((p = getenv("WINEPATH")) != NULL) {
295 strcat(WinePath, ";");
299 if (LoadImage(Argv[0], EXE) == (HINSTANCE) NULL ) {
300 fprintf(stderr, "wine: can't find %s!.\n", Argv[0]);
304 GetPrivateProfileString("wine", "SystemResources", "sysres.dll",
305 filename, sizeof(filename), WINE_INI);
307 hSysRes = LoadImage(filename, DLL);
308 if (hSysRes == (HINSTANCE)NULL)
309 fprintf(stderr, "wine: can't find %s!.\n", filename);
311 printf("System Resources Loaded // hSysRes='%04X'\n", hSysRes);
317 for(wpnt = wine_files; wpnt; wpnt = wpnt->next)
319 for (segment = 0; segment < wpnt->ne_header->n_segment_tab; segment++)
321 if (FixupSegment(wpnt, segment) < 0)
323 myerror("fixup failed.");
329 cp = strrchr(argv[0], '/');
330 if(!cp) cp = argv[0];
332 if(strcmp(cp,"winestat") == 0) {
339 * Initialize signal handling.
344 * Fixup stack and jump to start.
346 ds_reg = (wine_files->
347 selector_table[wine_files->ne_header->auto_data_seg-1].selector);
348 cs_reg = wine_files->selector_table[wine_files->ne_header->cs-1].selector;
349 ip_reg = wine_files->ne_header->ip;
350 ss_reg = wine_files->selector_table[wine_files->ne_header->ss-1].selector;
351 sp_reg = wine_files->ne_header->sp;
353 rv = CallToInit16(cs_reg << 16 | ip_reg, ss_reg << 16 | sp_reg, ds_reg);
354 printf ("rv = %x\n", rv);
357 void InitializeLoadedDLLs()
359 struct w_files * wpnt;
360 int cs_reg, ds_reg, ip_reg;
363 fprintf(stderr, "Initializing DLLs\n");
366 * Initialize libraries
369 for(wpnt = wine_files; wpnt; wpnt = wpnt->next)
374 if (wpnt->ne_header->format_flags & 0x8000)
376 if (!(wpnt->ne_header->format_flags & 0x0001))
379 fprintf(stderr, "Library is not marked SINGLEDATA\n");
383 ds_reg = wpnt->selector_table[wpnt->
384 ne_header->auto_data_seg-1].selector;
385 cs_reg = wpnt->selector_table[wpnt->ne_header->cs-1].selector;
386 ip_reg = wpnt->ne_header->ip;
388 fprintf(stderr, "Initializing %s, cs:ip %04x:%04x, ds %04x\n",
389 wpnt->name, cs_reg, ip_reg, ds_reg);
391 rv = CallTo16(cs_reg << 16 | ip_reg, ds_reg);
392 printf ("rv = %x\n", rv);
398 /**********************************************************************
402 GetImportedName(int fd, struct mz_header_s *mz_header,
403 struct ne_header_s *ne_header, int name_offset, char *buffer)
410 status = lseek(fd, mz_header->ne_offset + ne_header->iname_tab_offset +
411 name_offset, SEEK_SET);
413 read(fd, &length, 1); /* Get the length byte */
414 length = CONV_CHAR_TO_LONG (length);
415 read(fd, buffer, length);
420 /**********************************************************************
424 GetModuleName(struct w_files * wpnt, int index, char *buffer)
427 struct mz_header_s *mz_header = wpnt->mz_header;
428 struct ne_header_s *ne_header = wpnt->ne_header;
431 WORD name_offset, status;
434 status = lseek(fd, mz_header->ne_offset + ne_header->moduleref_tab_offset +
435 2*(index - 1), SEEK_SET);
437 read(fd, &name_offset, 2);
438 name_offset = CONV_SHORT (name_offset);
439 status = lseek(fd, mz_header->ne_offset + ne_header->iname_tab_offset +
440 name_offset, SEEK_SET);
442 read(fd, &length, 1); /* Get the length byte */
443 length = CONV_CHAR_TO_LONG (length);
444 read(fd, buffer, length);
447 /* Module names are always upper case */
448 for(i=0; i<length; i++)
449 if(buffer[i] >= 'a' && buffer[i] <= 'z') buffer[i] &= ~0x20;
456 /**********************************************************************
460 FixupSegment(struct w_files * wpnt, int segment_num)
463 struct mz_header_s * mz_header = wpnt->mz_header;
464 struct ne_header_s *ne_header = wpnt->ne_header;
465 struct ne_segment_table_entry_s *seg_table = wpnt->seg_table;
466 struct segment_descriptor_s *selector_table = wpnt->selector_table;
467 struct relocation_entry_s *rep, *rep1;
468 struct ne_segment_table_entry_s *seg;
469 struct segment_descriptor_s *sel;
470 struct dll_table_entry_s *dll_table;
473 unsigned int selector, address;
474 unsigned int next_addr;
481 seg = &seg_table[segment_num];
482 sel = &selector_table[segment_num];
485 printf("Segment fixups for %s, segment %d, selector %x\n",
486 wpnt->name, segment_num, (int) sel->base_addr >> 16);
489 if ((seg->seg_data_offset == 0) ||
490 !(seg->seg_flags & NE_SEGFLAGS_RELOC_DATA))
494 * Go through the relocation table on entry at a time.
496 i = seg->seg_data_length;
500 status = lseek(fd, seg->seg_data_offset *
501 (1 << ne_header->align_shift_count) + i, SEEK_SET);
503 read(fd, &n_entries, sizeof(short int));
504 rep = (struct relocation_entry_s *)
505 malloc(n_entries * sizeof(struct relocation_entry_s));
507 if (read(fd,rep, n_entries * sizeof(struct relocation_entry_s)) !=
508 n_entries * sizeof(struct relocation_entry_s))
510 myerror("Unable to read relocation information");
515 for (i = 0; i < n_entries; i++, rep++)
518 * Get the target address corresponding to this entry.
522 switch (rep->relocation_type)
524 case NE_RELTYPE_ORDINALADD:
527 case NE_RELTYPE_ORDINAL:
528 if (GetModuleName(wpnt, rep->target1,
531 fprintf(stderr, "NE_RELTYPE_ORDINAL failed");
535 ordinal = rep->target2;
537 status = GetEntryDLLOrdinal(dll_name, ordinal, &selector,
543 sprintf(s, "Bad DLL name '%s.%d'", dll_name, ordinal);
549 printf("%d: %s.%d: %04.4x:%04.4x\n", i + 1, dll_name, ordinal,
554 case NE_RELTYPE_NAMEADD:
557 case NE_RELTYPE_NAME:
558 if (GetModuleName(wpnt, rep->target1, dll_name)
561 fprintf(stderr,"NE_RELTYPE_NAME failed");
565 if (GetImportedName(fd, mz_header, ne_header,
566 rep->target2, func_name) == NULL)
568 fprintf(stderr,"getimportedname failed");
572 status = GetEntryDLLName(dll_name, func_name, &selector,
578 sprintf(s, "Bad DLL name '%s (%s)'", dll_name,func_name);
584 printf("%d: %s %s.%d: %04.4x:%04.4x\n", i + 1, func_name,
585 dll_name, ordinal, selector, address);
589 case NE_RELTYPE_INTERNAL:
590 case NE_RELTYPE_INT1:
591 if (rep->target1 == 0x00ff)
593 address = GetEntryPointFromOrdinal(wpnt, rep->target2);
594 selector = (address >> 16) & 0xffff;
599 selector = selector_table[rep->target1-1].selector;
600 address = rep->target2;
604 printf("%d: %04.4x:%04.4x\n", i + 1, selector, address);
609 /* Relocation type 7:
611 * These appear to be used as fixups for the Windows
612 * floating point emulator. Let's just ignore them and
613 * try to use the hardware floating point. Linux should
614 * successfully emulate the coprocessor if it doesn't
618 printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
619 i + 1, rep->address_type, rep->relocation_type,
621 printf("TARGET %04.4x %04.4x\n", rep->target1, rep->target2);
626 fprintf(stderr,"%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
627 i + 1, rep->address_type, rep->relocation_type,
629 fprintf(stderr,"TARGET %04.4x %04.4x\n",
630 rep->target1, rep->target2);
636 * Stuff the right size result in.
638 sp = (unsigned short *) ((char *) sel->base_addr + rep->offset);
641 if (FindDLLTable(dll_name) == NULL)
644 fprintf(stderr,"%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
645 i + 1, rep->address_type, rep->relocation_type,
647 fprintf(stderr,"TARGET %04.4x %04.4x\n",
648 rep->target1, rep->target2);
649 fprintf(stderr, " Additive = %d\n", additive);
652 switch (rep->address_type)
654 case NE_RADDR_OFFSET16:
657 printf(" %04.4x:%04.4x:%04.4x OFFSET16\n",
658 (unsigned long) sp >> 16, (int) sp & 0xFFFF, *sp);
661 *sp = (unsigned short) address;
664 sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
666 while (next_addr != 0xffff && !additive);
670 case NE_RADDR_POINTER32:
673 printf(" %04.4x:%04.4x:%04.4x POINTER32\n",
674 (unsigned long) sp >> 16, (int) sp & 0xFFFF, *sp);
677 *sp = (unsigned short) address;
680 *(sp+1) = (unsigned short) selector;
681 sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
683 while (next_addr != 0xffff && !additive);
687 case NE_RADDR_SELECTOR:
690 printf(" %04.4x:%04.4x:%04.4x SELECTOR\n",
691 (unsigned long) sp >> 16, (int) sp & 0xFFFF, *sp);
694 *sp = (unsigned short) selector;
695 sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
696 if (rep->relocation_type == NE_RELTYPE_INT1)
699 while (next_addr != 0xffff && !additive);
704 printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
705 i + 1, rep->address_type, rep->relocation_type,
707 printf("TARGET %04.4x %04.4x\n", rep->target1, rep->target2);
717 /**********************************************************************
720 FARPROC GetProcAddress(HINSTANCE hinstance, char *proc_name)
722 if ((int) proc_name & 0xffff0000)
723 printf("GetProcAddress: %#04x, '%s'\n", hinstance, proc_name);
725 printf("GetProcAddress: %#04x, %d\n", hinstance, (int) proc_name);