Release 940405
[wine.git] / loader / wine.c
blob4edecaaaa33aada3f28e00c2e04902e9a92b5dde
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 #ifdef linux
11 #include <linux/unistd.h>
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"
27 /* #define DEBUG_FIXUP */
29 extern int CallToInit16(unsigned long csip, unsigned long sssp,
30 unsigned short ds);
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;
43 char **Argv;
44 int Argc;
45 struct mz_header_s *CurrentMZHeader;
46 struct ne_header_s *CurrentNEHeader;
47 int CurrentNEFile;
48 HINSTANCE hSysRes;
50 static char *DLL_Extensions[] = { "dll", "exe", NULL };
51 static char *EXE_Extensions[] = { "exe", NULL };
53 FILE *SpyFp = NULL;
55 /**********************************************************************
56 * myerror
58 void
59 myerror(const char *s)
61 if (s == NULL)
62 perror("wine");
63 else
64 fprintf(stderr, "wine: %s\n", s);
66 exit(1);
69 /**********************************************************************
70 * GetFilenameFromInstance
72 char *
73 GetFilenameFromInstance(unsigned short instance)
75 register struct w_files *w = wine_files;
77 while (w && w->hinstance != instance)
78 w = w->next;
80 if (w)
81 return w->filename;
82 else
83 return NULL;
86 struct w_files *
87 GetFileInfo(unsigned short instance)
89 register struct w_files *w = wine_files;
91 while (w && w->hinstance != instance)
92 w = w->next;
94 return w;
97 #ifndef WINELIB
98 /**********************************************************************
100 * Load MZ Header
102 void load_mz_header(int fd, struct mz_header_s *mz_header)
104 if (read(fd, mz_header, sizeof(struct mz_header_s)) !=
105 sizeof(struct mz_header_s))
107 myerror("Unable to read MZ header from file");
111 void load_ne_header (int fd, struct ne_header_s *ne_header)
113 if (read(fd, ne_header, sizeof(struct ne_header_s))
114 != sizeof(struct ne_header_s))
116 myerror("Unable to read NE header from file");
119 #endif
121 /**********************************************************************
122 * LoadImage
123 * Load one NE format executable into memory
125 HINSTANCE LoadImage(char *modulename, int filetype)
127 unsigned int read_size;
128 int i;
129 struct w_files * wpnt, *wpnt1;
130 unsigned int status;
131 char buffer[256];
134 * search file
136 if (FindFile(buffer, sizeof(buffer), modulename, (filetype == EXE ?
137 EXE_Extensions : DLL_Extensions), WindowsPath) ==NULL)
139 fprintf(stderr, "LoadImage: I can't find %s.dll | %s.exe !\n",modulename, modulename);
140 return (HINSTANCE) NULL;
142 fprintf(stderr,"LoadImage: loading %s (%s)\n", modulename, buffer);
144 /* First allocate a spot to store the info we collect, and add it to
145 * our linked list.
148 wpnt = (struct w_files *) malloc(sizeof(struct w_files));
149 if(wine_files == NULL)
150 wine_files = wpnt;
151 else {
152 wpnt1 = wine_files;
153 while(wpnt1->next) wpnt1 = wpnt1->next;
154 wpnt1->next = wpnt;
156 wpnt->next = NULL;
157 wpnt->resnamtab = (RESNAMTAB *) -1;
160 * Open file for reading.
162 wpnt->fd = open(buffer, O_RDONLY);
163 if (wpnt->fd < 0)
165 myerror(NULL);
168 * Establish header pointers.
170 wpnt->filename = strdup(buffer);
171 wpnt->name = NULL;
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.
199 #ifndef WINELIB
200 status = lseek(wpnt->fd, wpnt->mz_header->ne_offset +
201 wpnt->ne_header->segment_tab_offset,
202 SEEK_SET);
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);
209 wpnt->hinstance
210 = 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;
245 #endif
247 * Now load any DLLs that this module refers to.
249 for(i=0; i<wpnt->ne_header->n_mod_ref_tab; i++){
250 char buff[14];
251 GetModuleName(wpnt, i + 1, buff);
253 #ifndef WINELIB
254 if(FindDLLTable(buff)) continue; /* This module already loaded */
255 #endif
257 LoadImage(buff, DLL);
259 fprintf(stderr,"Unable to load:%s\n", buff);
262 return(wpnt->hinstance);
266 #ifndef WINELIB
267 /**********************************************************************
268 * main
270 int _WinMain(int argc, char **argv)
272 int segment;
273 char *p;
274 char *sysresname;
275 char filename[100];
276 #ifdef WINESTAT
277 char * cp;
278 #endif
279 struct w_files * wpnt;
280 int cs_reg, ds_reg, ss_reg, ip_reg, sp_reg;
281 int rv;
283 Argc = argc - 1;
284 Argv = argv + 1;
286 if (LoadImage(Argv[0], EXE) == (HINSTANCE) NULL ) {
287 fprintf(stderr, "wine: can't find %s!.\n", Argv[0]);
288 exit(1);
291 GetPrivateProfileString("wine", "SystemResources", "sysres.dll",
292 filename, sizeof(filename), WINE_INI);
294 hSysRes = LoadImage(filename, DLL);
295 if (hSysRes == (HINSTANCE)NULL)
296 fprintf(stderr, "wine: can't find %s!.\n", filename);
297 else
298 printf("System Resources Loaded // hSysRes='%04X'\n", hSysRes);
301 * Fixup references.
303 wpnt = wine_files;
304 for(wpnt = wine_files; wpnt; wpnt = wpnt->next)
306 for (segment = 0; segment < wpnt->ne_header->n_segment_tab; segment++)
308 if (FixupSegment(wpnt, segment) < 0)
310 myerror("fixup failed.");
315 #ifdef WINESTAT
316 cp = strrchr(argv[0], '/');
317 if(!cp) cp = argv[0];
318 else cp++;
319 if(strcmp(cp,"winestat") == 0) {
320 winestat();
321 exit(0);
323 #endif
326 * Initialize signal handling.
328 init_wine_signals();
331 * Fixup stack and jump to start.
333 ds_reg = (wine_files->
334 selector_table[wine_files->ne_header->auto_data_seg-1].selector);
335 cs_reg = wine_files->selector_table[wine_files->ne_header->cs-1].selector;
336 ip_reg = wine_files->ne_header->ip;
337 ss_reg = wine_files->selector_table[wine_files->ne_header->ss-1].selector;
338 sp_reg = wine_files->ne_header->sp;
340 rv = CallToInit16(cs_reg << 16 | ip_reg, ss_reg << 16 | sp_reg, ds_reg);
341 printf ("rv = %x\n", rv);
344 void InitializeLoadedDLLs()
346 struct w_files * wpnt;
347 int cs_reg, ds_reg, ip_reg;
348 int rv;
350 fprintf(stderr, "Initializing DLLs\n");
353 * Initialize libraries
355 wpnt = wine_files;
356 for(wpnt = wine_files; wpnt; wpnt = wpnt->next)
359 * Is this a library?
361 if (wpnt->ne_header->format_flags & 0x8000)
363 if (!(wpnt->ne_header->format_flags & 0x0001))
365 /* Not SINGLEDATA */
366 fprintf(stderr, "Library is not marked SINGLEDATA\n");
367 exit(1);
370 ds_reg = wpnt->selector_table[wpnt->
371 ne_header->auto_data_seg-1].selector;
372 cs_reg = wpnt->selector_table[wpnt->ne_header->cs-1].selector;
373 ip_reg = wpnt->ne_header->ip;
375 fprintf(stderr, "Initializing %s, cs:ip %04x:%04x, ds %04x\n",
376 wpnt->name, cs_reg, ip_reg, ds_reg);
378 rv = CallTo16(cs_reg << 16 | ip_reg, ds_reg);
379 printf ("rv = %x\n", rv);
383 #endif
386 /**********************************************************************
387 * GetImportedName
389 char *
390 GetImportedName(int fd, struct mz_header_s *mz_header,
391 struct ne_header_s *ne_header, int name_offset, char *buffer)
393 int length;
394 int status;
396 status = lseek(fd, mz_header->ne_offset + ne_header->iname_tab_offset +
397 name_offset, SEEK_SET);
398 length = 0;
399 read(fd, &length, 1); /* Get the length byte */
400 length = CONV_CHAR_TO_LONG (length);
401 read(fd, buffer, length);
402 buffer[length] = 0;
403 return buffer;
406 /**********************************************************************
407 * GetModuleName
409 char *
410 GetModuleName(struct w_files * wpnt, int index, char *buffer)
412 int fd = wpnt->fd;
413 struct mz_header_s *mz_header = wpnt->mz_header;
414 struct ne_header_s *ne_header = wpnt->ne_header;
415 int length;
416 WORD name_offset, status;
417 int i;
419 status = lseek(fd, mz_header->ne_offset + ne_header->moduleref_tab_offset +
420 2*(index - 1), SEEK_SET);
421 name_offset = 0;
422 read(fd, &name_offset, 2);
423 name_offset = CONV_SHORT (name_offset);
424 status = lseek(fd, mz_header->ne_offset + ne_header->iname_tab_offset +
425 name_offset, SEEK_SET);
426 length = 0;
427 read(fd, &length, 1); /* Get the length byte */
428 length = CONV_CHAR_TO_LONG (length);
429 read(fd, buffer, length);
430 buffer[length] = 0;
432 /* Module names are always upper case */
433 for(i=0; i<length; i++)
434 if(buffer[i] >= 'a' && buffer[i] <= 'z') buffer[i] &= ~0x20;
436 return buffer;
440 #ifndef WINELIB
441 /**********************************************************************
442 * FixupSegment
445 FixupSegment(struct w_files * wpnt, int segment_num)
447 int fd = wpnt->fd;
448 struct mz_header_s * mz_header = wpnt->mz_header;
449 struct ne_header_s *ne_header = wpnt->ne_header;
450 struct ne_segment_table_entry_s *seg_table = wpnt->seg_table;
451 struct segment_descriptor_s *selector_table = wpnt->selector_table;
452 struct relocation_entry_s *rep, *rep1;
453 struct ne_segment_table_entry_s *seg;
454 struct segment_descriptor_s *sel;
455 struct dll_table_entry_s *dll_table;
456 int status;
457 unsigned short *sp;
458 unsigned int selector, address;
459 unsigned int next_addr;
460 int ordinal;
461 char dll_name[257];
462 char func_name[257];
463 int i, n_entries;
464 int additive;
466 seg = &seg_table[segment_num];
467 sel = &selector_table[segment_num];
469 #ifdef DEBUG_FIXUP
470 printf("Segment fixups for %s, segment %d, selector %x\n",
471 wpnt->name, segment_num, (int) sel->base_addr >> 16);
472 #endif
474 if ((seg->seg_data_offset == 0) ||
475 !(seg->seg_flags & NE_SEGFLAGS_RELOC_DATA))
476 return 0;
479 * Go through the relocation table on entry at a time.
481 i = seg->seg_data_length;
482 if (i == 0)
483 i = 0x10000;
485 status = lseek(fd, seg->seg_data_offset *
486 (1 << ne_header->align_shift_count) + i, SEEK_SET);
487 n_entries = 0;
488 read(fd, &n_entries, sizeof(short int));
489 rep = (struct relocation_entry_s *)
490 malloc(n_entries * sizeof(struct relocation_entry_s));
492 if (read(fd,rep, n_entries * sizeof(struct relocation_entry_s)) !=
493 n_entries * sizeof(struct relocation_entry_s))
495 myerror("Unable to read relocation information");
498 rep1 = rep;
500 for (i = 0; i < n_entries; i++, rep++)
503 * Get the target address corresponding to this entry.
505 additive = 0;
507 switch (rep->relocation_type)
509 case NE_RELTYPE_ORDINALADD:
510 additive = 1;
512 case NE_RELTYPE_ORDINAL:
513 if (GetModuleName(wpnt, rep->target1,
514 dll_name) == NULL)
516 fprintf(stderr, "NE_RELTYPE_ORDINAL failed");
517 return -1;
520 ordinal = rep->target2;
522 status = GetEntryDLLOrdinal(dll_name, ordinal, &selector,
523 &address);
524 if (status)
526 char s[80];
528 sprintf(s, "Bad DLL name '%s.%d'", dll_name, ordinal);
529 myerror(s);
530 return -1;
533 #ifdef DEBUG_FIXUP
534 printf("%d: %s.%d: %04.4x:%04.4x\n", i + 1, dll_name, ordinal,
535 selector, address);
536 #endif
537 break;
539 case NE_RELTYPE_NAMEADD:
540 additive = 1;
542 case NE_RELTYPE_NAME:
543 if (GetModuleName(wpnt, rep->target1, dll_name)
544 == NULL)
546 fprintf(stderr,"NE_RELTYPE_NAME failed");
547 return -1;
550 if (GetImportedName(fd, mz_header, ne_header,
551 rep->target2, func_name) == NULL)
553 fprintf(stderr,"getimportedname failed");
554 return -1;
557 status = GetEntryDLLName(dll_name, func_name, &selector,
558 &address);
559 if (status)
561 char s[80];
563 sprintf(s, "Bad DLL name '%s (%s)'", dll_name,func_name);
564 myerror(s);
565 return -1;
568 #ifdef DEBUG_FIXUP
569 printf("%d: %s %s.%d: %04.4x:%04.4x\n", i + 1, func_name,
570 dll_name, ordinal, selector, address);
571 #endif
572 break;
574 case NE_RELTYPE_INTERNAL:
575 case NE_RELTYPE_INT1:
576 if (rep->target1 == 0x00ff)
578 address = GetEntryPointFromOrdinal(wpnt, rep->target2);
579 selector = (address >> 16) & 0xffff;
580 address &= 0xffff;
582 else
584 selector = selector_table[rep->target1-1].selector;
585 address = rep->target2;
588 #ifdef DEBUG_FIXUP
589 printf("%d: %04.4x:%04.4x\n", i + 1, selector, address);
590 #endif
591 break;
593 case 7:
594 /* Relocation type 7:
596 * These appear to be used as fixups for the Windows
597 * floating point emulator. Let's just ignore them and
598 * try to use the hardware floating point. Linux should
599 * successfully emulate the coprocessor if it doesn't
600 * exist.
602 #ifdef DEBUG_FIXUP
603 printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
604 i + 1, rep->address_type, rep->relocation_type,
605 rep->offset);
606 printf("TARGET %04.4x %04.4x\n", rep->target1, rep->target2);
607 #endif
608 continue;
610 default:
611 fprintf(stderr,"%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
612 i + 1, rep->address_type, rep->relocation_type,
613 rep->offset);
614 fprintf(stderr,"TARGET %04.4x %04.4x\n",
615 rep->target1, rep->target2);
616 free(rep1);
617 return -1;
621 * Stuff the right size result in.
623 sp = (unsigned short *) ((char *) sel->base_addr + rep->offset);
624 if (additive)
626 if (FindDLLTable(dll_name) == NULL)
627 additive = 2;
629 fprintf(stderr,"%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
630 i + 1, rep->address_type, rep->relocation_type,
631 rep->offset);
632 fprintf(stderr,"TARGET %04.4x %04.4x\n",
633 rep->target1, rep->target2);
634 fprintf(stderr, " Additive = %d\n", additive);
637 switch (rep->address_type)
639 case NE_RADDR_OFFSET16:
640 do {
641 #ifdef DEBUG_FIXUP
642 printf(" %04.4x:%04.4x:%04.4x OFFSET16\n",
643 (unsigned long) sp >> 16, (int) sp & 0xFFFF, *sp);
644 #endif
645 next_addr = *sp;
646 *sp = (unsigned short) address;
647 if (additive == 2)
648 *sp += next_addr;
649 sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
651 while (next_addr != 0xffff && !additive);
653 break;
655 case NE_RADDR_POINTER32:
656 do {
657 #ifdef DEBUG_FIXUP
658 printf(" %04.4x:%04.4x:%04.4x POINTER32\n",
659 (unsigned long) sp >> 16, (int) sp & 0xFFFF, *sp);
660 #endif
661 next_addr = *sp;
662 *sp = (unsigned short) address;
663 if (additive == 2)
664 *sp += next_addr;
665 *(sp+1) = (unsigned short) selector;
666 sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
668 while (next_addr != 0xffff && !additive);
670 break;
672 case NE_RADDR_SELECTOR:
673 do {
674 #ifdef DEBUG_FIXUP
675 printf(" %04.4x:%04.4x:%04.4x SELECTOR\n",
676 (unsigned long) sp >> 16, (int) sp & 0xFFFF, *sp);
677 #endif
678 next_addr = *sp;
679 *sp = (unsigned short) selector;
680 sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
681 if (rep->relocation_type == NE_RELTYPE_INT1)
682 break;
684 while (next_addr != 0xffff && !additive);
686 break;
688 default:
689 printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
690 i + 1, rep->address_type, rep->relocation_type,
691 rep->offset);
692 printf("TARGET %04.4x %04.4x\n", rep->target1, rep->target2);
693 free(rep1);
694 return -1;
698 free(rep1);
699 return 0;
702 #endif