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 int CallToInit16(unsigned long csip
, unsigned long sssp
,
32 extern void CallTo32();
34 char * GetModuleName(struct w_files
* wpnt
, int index
, char *buffer
);
35 extern unsigned char ran_out
;
36 extern char WindowsPath
[256];
37 unsigned short WIN_StackSize
;
38 unsigned short WIN_HeapSize
;
40 struct w_files
* wine_files
= NULL
;
42 int WineForceFail
= 0;
46 struct mz_header_s
*CurrentMZHeader
;
47 struct ne_header_s
*CurrentNEHeader
;
51 static char *DLL_Extensions
[] = { "dll", "exe", NULL
};
52 static char *EXE_Extensions
[] = { "exe", NULL
};
53 static char *WinePath
= NULL
;
57 /**********************************************************************
61 myerror(const char *s
)
66 fprintf(stderr
, "wine: %s\n", s
);
71 /**********************************************************************
72 * GetFilenameFromInstance
75 GetFilenameFromInstance(unsigned short instance
)
77 register struct w_files
*w
= wine_files
;
79 while (w
&& w
->hinstance
!= instance
)
89 GetFileInfo(unsigned short instance
)
91 register struct w_files
*w
= wine_files
;
93 while (w
&& w
->hinstance
!= instance
)
100 /**********************************************************************
104 void load_mz_header(int fd
, struct mz_header_s
*mz_header
)
106 if (read(fd
, mz_header
, sizeof(struct mz_header_s
)) !=
107 sizeof(struct mz_header_s
))
109 myerror("Unable to read MZ header from file");
113 void load_ne_header (int fd
, struct ne_header_s
*ne_header
)
115 if (read(fd
, ne_header
, sizeof(struct ne_header_s
))
116 != sizeof(struct ne_header_s
))
118 myerror("Unable to read NE header from file");
123 /**********************************************************************
125 * Load one NE format executable into memory
127 HINSTANCE
LoadImage(char *modulename
, int filetype
)
129 unsigned int read_size
;
131 struct w_files
* wpnt
, *wpnt1
;
138 if (FindFile(buffer
, sizeof(buffer
), modulename
, (filetype
== EXE
?
139 EXE_Extensions
: DLL_Extensions
), WindowsPath
) ==NULL
)
141 fprintf(stderr
, "LoadImage: I can't find %s.dll | %s.exe !\n",modulename
, modulename
);
142 return (HINSTANCE
) NULL
;
144 fprintf(stderr
,"LoadImage: loading %s (%s)\n", modulename
, buffer
);
146 /* First allocate a spot to store the info we collect, and add it to
150 wpnt
= (struct w_files
*) malloc(sizeof(struct w_files
));
151 if(wine_files
== NULL
)
155 while(wpnt1
->next
) wpnt1
= wpnt1
->next
;
161 * Open file for reading.
163 wpnt
->fd
= open(buffer
, O_RDONLY
);
169 * Establish header pointers.
171 wpnt
->filename
= strdup(buffer
);
173 if(modulename
) wpnt
->name
= strdup(modulename
);
175 wpnt
->mz_header
= (struct mz_header_s
*) malloc(sizeof(struct mz_header_s
));;
176 status
= lseek(wpnt
->fd
, 0, SEEK_SET
);
177 load_mz_header (wpnt
->fd
, wpnt
->mz_header
);
178 if (wpnt
->mz_header
->must_be_0x40
!= 0x40)
179 myerror("This is not a Windows program");
181 wpnt
->ne_header
= (struct ne_header_s
*) malloc(sizeof(struct ne_header_s
));
182 status
= lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
, SEEK_SET
);
183 load_ne_header (wpnt
->fd
, wpnt
->ne_header
);
184 if (wpnt
->ne_header
->header_type
[0] != 'N' ||
185 wpnt
->ne_header
->header_type
[1] != 'E')
186 myerror("This is not a Windows program");
188 if(wine_files
== wpnt
){
189 CurrentMZHeader
= wpnt
->mz_header
;
190 CurrentNEHeader
= wpnt
->ne_header
;
191 CurrentNEFile
= wpnt
->fd
;
193 WIN_StackSize
= wpnt
->ne_header
->stack_length
;
194 WIN_HeapSize
= wpnt
->ne_header
->local_heap_length
;
198 * Create segment selectors.
201 status
= lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
+
202 wpnt
->ne_header
->segment_tab_offset
,
204 read_size
= wpnt
->ne_header
->n_segment_tab
*
205 sizeof(struct ne_segment_table_entry_s
);
206 wpnt
->seg_table
= (struct ne_segment_table_entry_s
*) malloc(read_size
);
207 if (read(wpnt
->fd
, wpnt
->seg_table
, read_size
) != read_size
)
208 myerror("Unable to read segment table header from file");
209 wpnt
->selector_table
= CreateSelectors(wpnt
);
212 selector_table
[wpnt
->ne_header
->auto_data_seg
-1].selector
;
214 /* Get the lookup table. This is used for looking up the addresses
215 of functions that are exported */
217 read_size
= wpnt
->ne_header
->entry_tab_length
;
218 wpnt
->lookup_table
= (char *) malloc(read_size
);
219 lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
+
220 wpnt
->ne_header
->entry_tab_offset
, SEEK_SET
);
221 if (read(wpnt
->fd
, wpnt
->lookup_table
, read_size
) != read_size
)
222 myerror("Unable to read lookup table header from file");
224 /* Get the iname table. This is used for looking up the names
225 of functions that are exported */
227 status
= lseek(wpnt
->fd
, wpnt
->ne_header
->nrname_tab_offset
, SEEK_SET
);
228 read_size
= wpnt
->ne_header
->nrname_tab_length
;
229 wpnt
->nrname_table
= (char *) malloc(read_size
);
230 if (read(wpnt
->fd
, wpnt
->nrname_table
, read_size
) != read_size
)
231 myerror("Unable to read nrname table header from file");
233 status
= lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
+
234 wpnt
->ne_header
->rname_tab_offset
, SEEK_SET
);
235 read_size
= wpnt
->ne_header
->moduleref_tab_offset
-
236 wpnt
->ne_header
->rname_tab_offset
;
237 wpnt
->rname_table
= (char *) malloc(read_size
);
238 if (read(wpnt
->fd
, wpnt
->rname_table
, read_size
) != read_size
)
239 myerror("Unable to read rname table header from file");
241 /* Now get the module name */
243 wpnt
->name
= (char*) malloc(*wpnt
->rname_table
+ 1);
244 memcpy(wpnt
->name
, wpnt
->rname_table
+1, *wpnt
->rname_table
);
245 wpnt
->name
[*wpnt
->rname_table
] = 0;
248 * Now load any DLLs that this module refers to.
250 for(i
=0; i
<wpnt
->ne_header
->n_mod_ref_tab
; i
++){
254 GetModuleName(wpnt
, i
+ 1, buff
);
257 if(FindDLLTable(buff
)) continue; /* This module already loaded */
260 LoadImage(buff
, DLL
);
262 fprintf(stderr,"Unable to load:%s\n", buff);
265 return(wpnt
->hinstance
);
269 /**********************************************************************
272 _WinMain(int argc
, char **argv
)
283 struct w_files
* wpnt
;
284 int cs_reg
, ds_reg
, ss_reg
, ip_reg
, sp_reg
;
291 WinePath
= malloc(1024);
293 getcwd(WinePath
, 512);
295 if ((p
= getenv("WINEPATH")) != NULL
) {
296 strcat(WinePath
, ";");
300 if ((hInstMain
= LoadImage(Argv
[0], EXE
)) == (HINSTANCE
) NULL
) {
301 fprintf(stderr
, "wine: can't find %s!.\n", Argv
[0]);
305 GetPrivateProfileString("wine", "SystemResources", "sysres.dll",
306 filename
, sizeof(filename
), WINE_INI
);
308 hSysRes
= LoadImage(filename
, DLL
);
309 if (hSysRes
== (HINSTANCE
)NULL
)
310 fprintf(stderr
, "wine: can't find %s!\n", filename
);
312 printf("System Resources Loaded // hSysRes='%04X'\n", hSysRes
);
318 for(wpnt
= wine_files
; wpnt
; wpnt
= wpnt
->next
)
320 for (segment
= 0; segment
< wpnt
->ne_header
->n_segment_tab
; segment
++)
322 if (FixupSegment(wpnt
, segment
) < 0)
324 myerror("fixup failed.");
330 cp
= strrchr(argv
[0], '/');
331 if(!cp
) cp
= argv
[0];
333 if(strcmp(cp
,"winestat") == 0) {
340 * Initialize signal handling.
345 * Fixup stack and jump to start.
347 ds_reg
= (wine_files
->
348 selector_table
[wine_files
->ne_header
->auto_data_seg
-1].selector
);
349 cs_reg
= wine_files
->selector_table
[wine_files
->ne_header
->cs
-1].selector
;
350 ip_reg
= wine_files
->ne_header
->ip
;
351 ss_reg
= wine_files
->selector_table
[wine_files
->ne_header
->ss
-1].selector
;
352 sp_reg
= wine_files
->ne_header
->sp
;
354 if (Options
.debug
) wine_debug(0, NULL
);
356 rv
= CallToInit16(cs_reg
<< 16 | ip_reg
, ss_reg
<< 16 | sp_reg
, ds_reg
);
357 printf ("rv = %x\n", rv
);
360 void InitializeLoadedDLLs()
362 struct w_files
* wpnt
;
363 int cs_reg
, ds_reg
, ip_reg
;
366 fprintf(stderr
, "Initializing DLLs\n");
369 * Initialize libraries
372 for(wpnt
= wine_files
; wpnt
; wpnt
= wpnt
->next
)
377 if (wpnt
->ne_header
->format_flags
& 0x8000)
379 if (!(wpnt
->ne_header
->format_flags
& 0x0001))
382 fprintf(stderr
, "Library is not marked SINGLEDATA\n");
386 ds_reg
= wpnt
->selector_table
[wpnt
->
387 ne_header
->auto_data_seg
-1].selector
;
388 cs_reg
= wpnt
->selector_table
[wpnt
->ne_header
->cs
-1].selector
;
389 ip_reg
= wpnt
->ne_header
->ip
;
391 fprintf(stderr
, "Initializing %s, cs:ip %04x:%04x, ds %04x\n",
392 wpnt
->name
, cs_reg
, ip_reg
, ds_reg
);
394 rv
= CallTo16(cs_reg
<< 16 | ip_reg
, ds_reg
);
395 printf ("rv = %x\n", rv
);
401 /**********************************************************************
405 GetImportedName(int fd
, struct mz_header_s
*mz_header
,
406 struct ne_header_s
*ne_header
, int name_offset
, char *buffer
)
413 status
= lseek(fd
, mz_header
->ne_offset
+ ne_header
->iname_tab_offset
+
414 name_offset
, SEEK_SET
);
416 read(fd
, &length
, 1); /* Get the length byte */
417 length
= CONV_CHAR_TO_LONG (length
);
418 read(fd
, buffer
, length
);
423 /**********************************************************************
427 GetModuleName(struct w_files
* wpnt
, int index
, char *buffer
)
430 struct mz_header_s
*mz_header
= wpnt
->mz_header
;
431 struct ne_header_s
*ne_header
= wpnt
->ne_header
;
434 WORD name_offset
, status
;
437 status
= lseek(fd
, mz_header
->ne_offset
+ ne_header
->moduleref_tab_offset
+
438 2*(index
- 1), SEEK_SET
);
440 read(fd
, &name_offset
, 2);
441 name_offset
= CONV_SHORT (name_offset
);
442 status
= lseek(fd
, mz_header
->ne_offset
+ ne_header
->iname_tab_offset
+
443 name_offset
, SEEK_SET
);
445 read(fd
, &length
, 1); /* Get the length byte */
446 length
= CONV_CHAR_TO_LONG (length
);
447 read(fd
, buffer
, length
);
450 /* Module names are always upper case */
451 for(i
=0; i
<length
; i
++)
452 if(buffer
[i
] >= 'a' && buffer
[i
] <= 'z') buffer
[i
] &= ~0x20;
459 /**********************************************************************
463 FixupSegment(struct w_files
* wpnt
, int segment_num
)
466 struct mz_header_s
* mz_header
= wpnt
->mz_header
;
467 struct ne_header_s
*ne_header
= wpnt
->ne_header
;
468 struct ne_segment_table_entry_s
*seg_table
= wpnt
->seg_table
;
469 struct segment_descriptor_s
*selector_table
= wpnt
->selector_table
;
470 struct relocation_entry_s
*rep
, *rep1
;
471 struct ne_segment_table_entry_s
*seg
;
472 struct segment_descriptor_s
*sel
;
473 struct dll_table_entry_s
*dll_table
;
476 unsigned int selector
, address
;
477 unsigned int next_addr
;
484 seg
= &seg_table
[segment_num
];
485 sel
= &selector_table
[segment_num
];
488 printf("Segment fixups for %s, segment %d, selector %x\n",
489 wpnt
->name
, segment_num
, (int) sel
->base_addr
>> 16);
492 if ((seg
->seg_data_offset
== 0) ||
493 !(seg
->seg_flags
& NE_SEGFLAGS_RELOC_DATA
))
497 * Go through the relocation table on entry at a time.
499 i
= seg
->seg_data_length
;
503 status
= lseek(fd
, seg
->seg_data_offset
*
504 (1 << ne_header
->align_shift_count
) + i
, SEEK_SET
);
506 read(fd
, &n_entries
, sizeof(short int));
507 rep
= (struct relocation_entry_s
*)
508 malloc(n_entries
* sizeof(struct relocation_entry_s
));
510 if (read(fd
,rep
, n_entries
* sizeof(struct relocation_entry_s
)) !=
511 n_entries
* sizeof(struct relocation_entry_s
))
513 myerror("Unable to read relocation information");
518 for (i
= 0; i
< n_entries
; i
++, rep
++)
521 * Get the target address corresponding to this entry.
525 switch (rep
->relocation_type
)
527 case NE_RELTYPE_ORDINALADD
:
530 case NE_RELTYPE_ORDINAL
:
531 if (GetModuleName(wpnt
, rep
->target1
,
534 fprintf(stderr
, "NE_RELTYPE_ORDINAL failed");
538 ordinal
= rep
->target2
;
540 status
= GetEntryDLLOrdinal(dll_name
, ordinal
, &selector
,
546 sprintf(s
, "Bad DLL name '%s.%d'", dll_name
, ordinal
);
552 printf("%d: %s.%d: %04.4x:%04.4x\n", i
+ 1, dll_name
, ordinal
,
557 case NE_RELTYPE_NAMEADD
:
560 case NE_RELTYPE_NAME
:
561 if (GetModuleName(wpnt
, rep
->target1
, dll_name
)
564 fprintf(stderr
,"NE_RELTYPE_NAME failed");
568 if (GetImportedName(fd
, mz_header
, ne_header
,
569 rep
->target2
, func_name
) == NULL
)
571 fprintf(stderr
,"getimportedname failed");
575 status
= GetEntryDLLName(dll_name
, func_name
, &selector
,
581 sprintf(s
, "Bad DLL name '%s (%s)'", dll_name
,func_name
);
587 printf("%d: %s %s.%d: %04.4x:%04.4x\n", i
+ 1, func_name
,
588 dll_name
, ordinal
, selector
, address
);
592 case NE_RELTYPE_INTERNAL
:
593 case NE_RELTYPE_INT1
:
594 if (rep
->target1
== 0x00ff)
596 address
= GetEntryPointFromOrdinal(wpnt
, rep
->target2
);
597 selector
= (address
>> 16) & 0xffff;
602 selector
= selector_table
[rep
->target1
-1].selector
;
603 address
= rep
->target2
;
607 printf("%d: %04.4x:%04.4x\n", i
+ 1, selector
, address
);
612 /* Relocation type 7:
614 * These appear to be used as fixups for the Windows
615 * floating point emulator. Let's just ignore them and
616 * try to use the hardware floating point. Linux should
617 * successfully emulate the coprocessor if it doesn't
621 printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
622 i
+ 1, rep
->address_type
, rep
->relocation_type
,
624 printf("TARGET %04.4x %04.4x\n", rep
->target1
, rep
->target2
);
629 fprintf(stderr
,"%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
630 i
+ 1, rep
->address_type
, rep
->relocation_type
,
632 fprintf(stderr
,"TARGET %04.4x %04.4x\n",
633 rep
->target1
, rep
->target2
);
639 * Stuff the right size result in.
641 sp
= (unsigned short *) ((char *) sel
->base_addr
+ rep
->offset
);
644 if (FindDLLTable(dll_name
) == NULL
)
647 fprintf(stderr
,"%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
648 i
+ 1, rep
->address_type
, rep
->relocation_type
,
650 fprintf(stderr
,"TARGET %04.4x %04.4x\n",
651 rep
->target1
, rep
->target2
);
652 fprintf(stderr
, " Additive = %d\n", additive
);
655 switch (rep
->address_type
)
657 case NE_RADDR_OFFSET16
:
660 printf(" %04.4x:%04.4x:%04.4x OFFSET16\n",
661 (unsigned long) sp
>> 16, (int) sp
& 0xFFFF, *sp
);
664 *sp
= (unsigned short) address
;
667 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
669 while (next_addr
!= 0xffff && !additive
);
673 case NE_RADDR_POINTER32
:
676 printf(" %04.4x:%04.4x:%04.4x POINTER32\n",
677 (unsigned long) sp
>> 16, (int) sp
& 0xFFFF, *sp
);
680 *sp
= (unsigned short) address
;
683 *(sp
+1) = (unsigned short) selector
;
684 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
686 while (next_addr
!= 0xffff && !additive
);
690 case NE_RADDR_SELECTOR
:
693 printf(" %04.4x:%04.4x:%04.4x SELECTOR\n",
694 (unsigned long) sp
>> 16, (int) sp
& 0xFFFF, *sp
);
697 *sp
= (unsigned short) selector
;
698 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
699 if (rep
->relocation_type
== NE_RELTYPE_INT1
)
702 while (next_addr
!= 0xffff && !additive
);
707 printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
708 i
+ 1, rep
->address_type
, rep
->relocation_type
,
710 printf("TARGET %04.4x %04.4x\n", rep
->target1
, rep
->target2
);
720 /**********************************************************************
723 FARPROC
GetProcAddress(HINSTANCE hinstance
, char *proc_name
)
725 if ((int) proc_name
& 0xffff0000)
726 printf("GetProcAddress: %#04x, '%s'\n", hinstance
, proc_name
);
728 printf("GetProcAddress: %#04x, %d\n", hinstance
, (int) proc_name
);