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
};
55 /**********************************************************************
59 myerror(const char *s
)
64 fprintf(stderr
, "wine: %s\n", s
);
69 /**********************************************************************
70 * GetFilenameFromInstance
73 GetFilenameFromInstance(unsigned short instance
)
75 register struct w_files
*w
= wine_files
;
77 while (w
&& w
->hinstance
!= instance
)
87 GetFileInfo(unsigned short instance
)
89 register struct w_files
*w
= wine_files
;
91 while (w
&& w
->hinstance
!= instance
)
98 /**********************************************************************
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");
121 /**********************************************************************
123 * Load one NE format executable into memory
125 HINSTANCE
LoadImage(char *modulename
, int filetype
)
127 unsigned int read_size
;
129 struct w_files
* wpnt
, *wpnt1
;
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
148 wpnt
= (struct w_files
*) malloc(sizeof(struct w_files
));
149 if(wine_files
== NULL
)
153 while(wpnt1
->next
) wpnt1
= wpnt1
->next
;
157 wpnt
->resnamtab
= (RESNAMTAB
*) -1;
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
++){
251 GetModuleName(wpnt
, i
+ 1, buff
);
254 if(FindDLLTable(buff
)) continue; /* This module already loaded */
257 LoadImage(buff
, DLL
);
259 fprintf(stderr,"Unable to load:%s\n", buff);
262 return(wpnt
->hinstance
);
267 /**********************************************************************
270 int _WinMain(int argc
, char **argv
)
279 struct w_files
* wpnt
;
280 int cs_reg
, ds_reg
, ss_reg
, ip_reg
, sp_reg
;
286 if (LoadImage(Argv
[0], EXE
) == (HINSTANCE
) NULL
) {
287 fprintf(stderr
, "wine: can't find %s!.\n", Argv
[0]);
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
);
298 printf("System Resources Loaded // hSysRes='%04X'\n", hSysRes
);
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.");
316 cp
= strrchr(argv
[0], '/');
317 if(!cp
) cp
= argv
[0];
319 if(strcmp(cp
,"winestat") == 0) {
326 * Initialize signal handling.
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
;
350 fprintf(stderr
, "Initializing DLLs\n");
353 * Initialize libraries
356 for(wpnt
= wine_files
; wpnt
; wpnt
= wpnt
->next
)
361 if (wpnt
->ne_header
->format_flags
& 0x8000)
363 if (!(wpnt
->ne_header
->format_flags
& 0x0001))
366 fprintf(stderr
, "Library is not marked SINGLEDATA\n");
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
);
386 /**********************************************************************
390 GetImportedName(int fd
, struct mz_header_s
*mz_header
,
391 struct ne_header_s
*ne_header
, int name_offset
, char *buffer
)
396 status
= lseek(fd
, mz_header
->ne_offset
+ ne_header
->iname_tab_offset
+
397 name_offset
, SEEK_SET
);
399 read(fd
, &length
, 1); /* Get the length byte */
400 length
= CONV_CHAR_TO_LONG (length
);
401 read(fd
, buffer
, length
);
406 /**********************************************************************
410 GetModuleName(struct w_files
* wpnt
, int index
, char *buffer
)
413 struct mz_header_s
*mz_header
= wpnt
->mz_header
;
414 struct ne_header_s
*ne_header
= wpnt
->ne_header
;
416 WORD name_offset
, status
;
419 status
= lseek(fd
, mz_header
->ne_offset
+ ne_header
->moduleref_tab_offset
+
420 2*(index
- 1), SEEK_SET
);
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
);
427 read(fd
, &length
, 1); /* Get the length byte */
428 length
= CONV_CHAR_TO_LONG (length
);
429 read(fd
, buffer
, length
);
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;
441 /**********************************************************************
445 FixupSegment(struct w_files
* wpnt
, int segment_num
)
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
;
458 unsigned int selector
, address
;
459 unsigned int next_addr
;
466 seg
= &seg_table
[segment_num
];
467 sel
= &selector_table
[segment_num
];
470 printf("Segment fixups for %s, segment %d, selector %x\n",
471 wpnt
->name
, segment_num
, (int) sel
->base_addr
>> 16);
474 if ((seg
->seg_data_offset
== 0) ||
475 !(seg
->seg_flags
& NE_SEGFLAGS_RELOC_DATA
))
479 * Go through the relocation table on entry at a time.
481 i
= seg
->seg_data_length
;
485 status
= lseek(fd
, seg
->seg_data_offset
*
486 (1 << ne_header
->align_shift_count
) + i
, SEEK_SET
);
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");
500 for (i
= 0; i
< n_entries
; i
++, rep
++)
503 * Get the target address corresponding to this entry.
507 switch (rep
->relocation_type
)
509 case NE_RELTYPE_ORDINALADD
:
512 case NE_RELTYPE_ORDINAL
:
513 if (GetModuleName(wpnt
, rep
->target1
,
516 fprintf(stderr
, "NE_RELTYPE_ORDINAL failed");
520 ordinal
= rep
->target2
;
522 status
= GetEntryDLLOrdinal(dll_name
, ordinal
, &selector
,
528 sprintf(s
, "Bad DLL name '%s.%d'", dll_name
, ordinal
);
534 printf("%d: %s.%d: %04.4x:%04.4x\n", i
+ 1, dll_name
, ordinal
,
539 case NE_RELTYPE_NAMEADD
:
542 case NE_RELTYPE_NAME
:
543 if (GetModuleName(wpnt
, rep
->target1
, dll_name
)
546 fprintf(stderr
,"NE_RELTYPE_NAME failed");
550 if (GetImportedName(fd
, mz_header
, ne_header
,
551 rep
->target2
, func_name
) == NULL
)
553 fprintf(stderr
,"getimportedname failed");
557 status
= GetEntryDLLName(dll_name
, func_name
, &selector
,
563 sprintf(s
, "Bad DLL name '%s (%s)'", dll_name
,func_name
);
569 printf("%d: %s %s.%d: %04.4x:%04.4x\n", i
+ 1, func_name
,
570 dll_name
, ordinal
, selector
, address
);
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;
584 selector
= selector_table
[rep
->target1
-1].selector
;
585 address
= rep
->target2
;
589 printf("%d: %04.4x:%04.4x\n", i
+ 1, selector
, address
);
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
603 printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
604 i
+ 1, rep
->address_type
, rep
->relocation_type
,
606 printf("TARGET %04.4x %04.4x\n", rep
->target1
, rep
->target2
);
611 fprintf(stderr
,"%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
612 i
+ 1, rep
->address_type
, rep
->relocation_type
,
614 fprintf(stderr
,"TARGET %04.4x %04.4x\n",
615 rep
->target1
, rep
->target2
);
621 * Stuff the right size result in.
623 sp
= (unsigned short *) ((char *) sel
->base_addr
+ rep
->offset
);
626 if (FindDLLTable(dll_name
) == NULL
)
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
);
634 fprintf(stderr
, " Additive = %d\n", additive
);
637 switch (rep
->address_type
)
639 case NE_RADDR_OFFSET16
:
642 printf(" %04.4x:%04.4x:%04.4x OFFSET16\n",
643 (unsigned long) sp
>> 16, (int) sp
& 0xFFFF, *sp
);
646 *sp
= (unsigned short) address
;
649 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
651 while (next_addr
!= 0xffff && !additive
);
655 case NE_RADDR_POINTER32
:
658 printf(" %04.4x:%04.4x:%04.4x POINTER32\n",
659 (unsigned long) sp
>> 16, (int) sp
& 0xFFFF, *sp
);
662 *sp
= (unsigned short) address
;
665 *(sp
+1) = (unsigned short) selector
;
666 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
668 while (next_addr
!= 0xffff && !additive
);
672 case NE_RADDR_SELECTOR
:
675 printf(" %04.4x:%04.4x:%04.4x SELECTOR\n",
676 (unsigned long) sp
>> 16, (int) sp
& 0xFFFF, *sp
);
679 *sp
= (unsigned short) selector
;
680 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
681 if (rep
->relocation_type
== NE_RELTYPE_INT1
)
684 while (next_addr
!= 0xffff && !additive
);
689 printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
690 i
+ 1, rep
->address_type
, rep
->relocation_type
,
692 printf("TARGET %04.4x %04.4x\n", rep
->target1
, rep
->target2
);