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";
10 #include <linux/unistd.h>
11 #include <linux/head.h>
12 #include <linux/ldt.h>
13 #include <linux/segment.h>
18 #include "prototypes.h"
23 extern int CallToInit16(unsigned long csip
, unsigned long sssp
,
25 extern void CallTo32();
27 char * GetModuleName(struct w_files
* wpnt
, int index
, char *buffer
);
28 extern unsigned char ran_out
;
29 unsigned short WIN_StackSize
;
30 unsigned short WIN_HeapSize
;
32 struct w_files
* wine_files
= NULL
;
36 struct mz_header_s
*CurrentMZHeader
;
37 struct ne_header_s
*CurrentNEHeader
;
40 /**********************************************************************
44 DebugPrintString(char *str
)
50 /**********************************************************************
54 myerror(const char *s
)
59 fprintf(stderr
, "wine: %s\n", s
);
65 /* Load one NE format executable into memory */
66 LoadImage(char * filename
, char * modulename
)
68 unsigned int read_size
;
70 struct w_files
* wpnt
, *wpnt1
;
73 /* First allocate a spot to store the info we collect, and add it to
77 wpnt
= (struct w_files
*) malloc(sizeof(struct w_files
));
78 if(wine_files
== NULL
)
82 while(wpnt1
->next
) wpnt1
= wpnt1
->next
;
88 * Open file for reading.
90 wpnt
->fd
= open(filename
, O_RDONLY
);
96 * Establish header pointers.
98 wpnt
->filename
= strdup(filename
);
100 if(modulename
) wpnt
->name
= strdup(modulename
);
102 wpnt
->mz_header
= (struct mz_header_s
*) malloc(sizeof(struct mz_header_s
));;
103 status
= lseek(wpnt
->fd
, 0, SEEK_SET
);
104 if (read(wpnt
->fd
, wpnt
->mz_header
, sizeof(struct mz_header_s
)) !=
105 sizeof(struct mz_header_s
))
107 myerror("Unable to read MZ header from file");
109 if (wpnt
->mz_header
->must_be_0x40
!= 0x40)
110 myerror("This is not a Windows program");
112 wpnt
->ne_header
= (struct ne_header_s
*) malloc(sizeof(struct ne_header_s
));
113 status
= lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
, SEEK_SET
);
114 if (read(wpnt
->fd
, wpnt
->ne_header
, sizeof(struct ne_header_s
))
115 != sizeof(struct ne_header_s
))
117 myerror("Unable to read NE header from file");
119 if (wpnt
->ne_header
->header_type
[0] != 'N' ||
120 wpnt
->ne_header
->header_type
[1] != 'E')
121 myerror("This is not a Windows program");
123 if(wine_files
== wpnt
){
124 CurrentMZHeader
= wpnt
->mz_header
;
125 CurrentNEHeader
= wpnt
->ne_header
;
126 CurrentNEFile
= wpnt
->fd
;
128 WIN_StackSize
= wpnt
->ne_header
->stack_length
;
129 WIN_HeapSize
= wpnt
->ne_header
->local_heap_length
;
133 * Create segment selectors.
135 status
= lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
+
136 wpnt
->ne_header
->segment_tab_offset
,
138 read_size
= wpnt
->ne_header
->n_segment_tab
*
139 sizeof(struct ne_segment_table_entry_s
);
140 wpnt
->seg_table
= (struct ne_segment_table_entry_s
*) malloc(read_size
);
141 if (read(wpnt
->fd
, wpnt
->seg_table
, read_size
) != read_size
)
142 myerror("Unable to read segment table header from file");
143 wpnt
->selector_table
= CreateSelectors(wpnt
);
145 /* Get the lookup table. This is used for looking up the addresses
146 of functions that are exported */
148 read_size
= wpnt
->ne_header
->entry_tab_length
;
149 wpnt
->lookup_table
= (char *) malloc(read_size
);
150 lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
+
151 wpnt
->ne_header
->entry_tab_offset
, SEEK_SET
);
152 if (read(wpnt
->fd
, wpnt
->lookup_table
, read_size
) != read_size
)
153 myerror("Unable to read lookup table header from file");
155 /* Get the iname table. This is used for looking up the names
156 of functions that are exported */
158 status
= lseek(wpnt
->fd
, wpnt
->ne_header
->nrname_tab_offset
, SEEK_SET
);
159 read_size
= wpnt
->ne_header
->nrname_tab_length
;
160 wpnt
->nrname_table
= (char *) malloc(read_size
);
161 if (read(wpnt
->fd
, wpnt
->nrname_table
, read_size
) != read_size
)
162 myerror("Unable to read nrname table header from file");
164 status
= lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
+
165 wpnt
->ne_header
->rname_tab_offset
, SEEK_SET
);
166 read_size
= wpnt
->ne_header
->moduleref_tab_offset
-
167 wpnt
->ne_header
->rname_tab_offset
;
168 wpnt
->rname_table
= (char *) malloc(read_size
);
169 if (read(wpnt
->fd
, wpnt
->rname_table
, read_size
) != read_size
)
170 myerror("Unable to read rname table header from file");
172 /* Now get the module name */
174 wpnt
->name
= (char*) malloc(*wpnt
->rname_table
+ 1);
175 memcpy(wpnt
->name
, wpnt
->rname_table
+1, *wpnt
->rname_table
);
176 wpnt
->name
[*wpnt
->rname_table
] = 0;
179 * Now load any DLLs that this module refers to.
181 for(i
=0; i
<wpnt
->ne_header
->n_mod_ref_tab
; i
++){
185 GetModuleName(wpnt
, i
+ 1, buff
);
187 if(FindDLLTable(buff
)) continue; /* This module already loaded */
189 /* The next trick is to convert the case, and add the .dll
190 * extension if required to find the actual library. We may want
191 * to use a search path at some point as well. */
193 /* First try the straight name */
195 if(fd
= open(buff2
, O_RDONLY
) >= 0) {
197 LoadImage(buff2
, buff
);
201 /* OK, that did not work, try making it lower-case, and add the .dll
204 for(j
=0; j
<strlen(buff2
); j
++)
205 if(buff2
[j
] >= 'A' && buff2
[j
] <= 'Z') buff2
[j
] |= 0x20;
206 strcat(buff2
, ".dll");
208 if(fd
= open(buff2
, O_RDONLY
) >= 0) {
210 LoadImage(buff2
, buff
);
214 fprintf(stderr
,"Unable to load:%s\n", buff
);
219 /**********************************************************************
222 _WinMain(int argc
, char **argv
)
225 struct w_files
* wpnt
;
226 int cs_reg
, ds_reg
, ss_reg
, ip_reg
, sp_reg
;
235 fprintf(stderr
, "usage: %s FILENAME\n", argv
[0]);
239 LoadImage(argv
[1], NULL
);
243 GetEntryDLLName("USER", "INITAPP", 0, 0);
244 for(i
=0; i
<1024; i
++) {
246 j
= GetEntryPointFromOrdinal(wine_files
, i
);
248 fprintf(stderr
," %d %x\n", i
, j
);
255 for(wpnt
= wine_files
; wpnt
; wpnt
= wpnt
->next
)
256 for (segment
= 0; segment
< wpnt
->ne_header
->n_segment_tab
; segment
++)
258 if (FixupSegment(wpnt
, segment
) < 0)
260 myerror("fixup failed.");
265 * Fixup stack and jump to start.
267 ds_reg
= wine_files
->selector_table
[wine_files
->ne_header
->auto_data_seg
-1].selector
;
268 cs_reg
= wine_files
->selector_table
[wine_files
->ne_header
->cs
-1].selector
;
269 ip_reg
= wine_files
->ne_header
->ip
;
270 ss_reg
= wine_files
->selector_table
[wine_files
->ne_header
->ss
-1].selector
;
271 sp_reg
= wine_files
->ne_header
->sp
;
275 rv
= CallToInit16(cs_reg
<< 16 | ip_reg
, ss_reg
<< 16 | sp_reg
, ds_reg
);
276 printf ("rv = %x\n", rv
);
280 /**********************************************************************
284 GetImportedName(int fd
, struct mz_header_s
*mz_header
,
285 struct ne_header_s
*ne_header
, int name_offset
, char *buffer
)
292 status
= lseek(fd
, mz_header
->ne_offset
+ ne_header
->iname_tab_offset
+
293 name_offset
, SEEK_SET
);
295 read(fd
, &length
, 1); /* Get the length byte */
296 read(fd
, buffer
, length
);
301 /**********************************************************************
305 GetModuleName(struct w_files
* wpnt
, int index
, char *buffer
)
308 struct mz_header_s
*mz_header
= wpnt
->mz_header
;
309 struct ne_header_s
*ne_header
= wpnt
->ne_header
;
312 int name_offset
, status
;
315 status
= lseek(fd
, mz_header
->ne_offset
+ ne_header
->moduleref_tab_offset
+
316 2*(index
- 1), SEEK_SET
);
318 read(fd
, &name_offset
, 2);
319 status
= lseek(fd
, mz_header
->ne_offset
+ ne_header
->iname_tab_offset
+
320 name_offset
, SEEK_SET
);
322 read(fd
, &length
, 1); /* Get the length byte */
323 read(fd
, buffer
, length
);
326 /* Module names are always upper case */
327 for(i
=0; i
<length
; i
++)
328 if(buffer
[i
] >= 'a' && buffer
[i
] <= 'z') buffer
[i
] &= ~0x20;
334 /**********************************************************************
338 FixupSegment(struct w_files
* wpnt
, int segment_num
)
341 struct mz_header_s
* mz_header
= wpnt
->mz_header
;
342 struct ne_header_s
*ne_header
= wpnt
->ne_header
;
343 struct ne_segment_table_entry_s
*seg_table
= wpnt
->seg_table
;
344 struct segment_descriptor_s
*selector_table
= wpnt
->selector_table
;
346 struct relocation_entry_s
*rep
, *rep1
;
347 struct ne_segment_table_entry_s
*seg
;
348 struct segment_descriptor_s
*sel
;
349 struct dll_table_entry_s
*dll_table
;
352 unsigned int selector
, address
;
353 unsigned int next_addr
;
359 seg
= &seg_table
[segment_num
];
360 sel
= &selector_table
[segment_num
];
362 if ((seg
->seg_data_offset
== 0) ||
363 !(seg
->seg_flags
& NE_SEGFLAGS_RELOC_DATA
))
367 * Go through the relocation table on entry at a time.
369 i
= seg
->seg_data_length
;
373 status
= lseek(fd
, seg
->seg_data_offset
*
374 (1 << ne_header
->align_shift_count
) + i
, SEEK_SET
);
376 read(fd
, &n_entries
, sizeof(short int));
377 rep
= (struct relocation_entry_s
*)
378 malloc(n_entries
* sizeof(struct relocation_entry_s
));
380 if (read(fd
,rep
, n_entries
* sizeof(struct relocation_entry_s
)) !=
381 n_entries
* sizeof(struct relocation_entry_s
))
383 myerror("Unable to read relocation information");
388 for (i
= 0; i
< n_entries
; i
++, rep
++)
391 * Get the target address corresponding to this entry.
393 switch (rep
->relocation_type
)
395 case NE_RELTYPE_ORDINAL
:
396 if (GetModuleName(wpnt
, rep
->target1
,
399 fprintf(stderr
, "NE_RELTYPE_ORDINAL failed");
403 ordinal
= rep
->target2
;
405 status
= GetEntryDLLOrdinal(dll_name
, ordinal
, &selector
,
411 sprintf(s
, "Bad DLL name '%s.%d'", dll_name
, ordinal
);
417 printf("%d: %s.%d: %04.4x:%04.4x\n", i
+ 1, dll_name
, ordinal
,
422 case NE_RELTYPE_NAME
:
423 if (GetModuleName(wpnt
, rep
->target1
, dll_name
)
426 fprintf(stderr
,"NE_RELTYPE_NAME failed");
430 if (GetImportedName(fd
, mz_header
, ne_header
,
431 rep
->target2
, func_name
) == NULL
)
433 fprintf(stderr
,"getimportedname failed");
437 status
= GetEntryDLLName(dll_name
, func_name
, &selector
,
443 sprintf(s
, "Bad DLL name '%s (%s)'", dll_name
,func_name
);
449 printf("%d: %s %s.%d: %04.4x:%04.4x\n", i
+ 1, func_name
,
450 dll_name
, ordinal
, selector
, address
);
454 case NE_RELTYPE_INTERNAL
:
455 case NE_RELTYPE_INT1
:
456 if (rep
->target1
== 0x00ff)
458 address
= GetEntryPointFromOrdinal(wpnt
, rep
->target2
);
459 selector
= (address
>> 16) & 0xffff;
464 selector
= selector_table
[rep
->target1
-1].selector
;
465 address
= rep
->target2
;
469 printf("%d: %04.4x:%04.4x\n", i
+ 1, selector
, address
);
474 /* Relocation type 7:
476 * These appear to be used as fixups for the Windows
477 * floating point emulator. Let's just ignore them and
478 * try to use the hardware floating point. Linux should
479 * successfully emulate the coprocessor if it doesn't
483 printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
484 i
+ 1, rep
->address_type
, rep
->relocation_type
,
486 printf("TARGET %04.4x %04.4x\n", rep
->target1
, rep
->target2
);
492 printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
493 i
+ 1, rep
->address_type
, rep
->relocation_type
,
495 printf("TARGET %04.4x %04.4x\n", rep
->target1
, rep
->target2
);
502 * Stuff the right size result in.
504 sp
= (unsigned short *) ((char *) sel
->base_addr
+ rep
->offset
);
505 switch (rep
->address_type
)
507 case NE_RADDR_OFFSET16
:
510 *sp
= (unsigned short) address
;
511 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
513 while (next_addr
!= 0xffff);
517 case NE_RADDR_POINTER32
:
520 *sp
= (unsigned short) address
;
521 *(sp
+1) = (unsigned short) selector
;
522 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
524 while (next_addr
!= 0xffff);
528 case NE_RADDR_SELECTOR
:
531 *sp
= (unsigned short) selector
;
532 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
534 while (next_addr
!= 0xffff);
540 printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
541 i
+ 1, rep
->address_type
, rep
->relocation_type
,
543 printf("TARGET %04.4x %04.4x\n", rep
->target1
, rep
->target2
);
554 /**********************************************************************
557 FARPROC
GetProcAddress(HINSTANCE hinstance
, char *proc_name
)
559 if ((int) proc_name
& 0xffff0000)
560 printf("GetProcAddress: %#04x, '%s'\n", hinstance
, proc_name
);
562 printf("GetProcAddress: %#04x, %d\n", hinstance
, (int) proc_name
);