1
0
Fork 0
mirror of synced 2025-03-07 03:53:26 +01:00
wine/loader/ne_image.c
Alexandre Julliard fa68b75bad Release 950403
Sun Apr  2 18:31:12 1995  Alexandre Julliard  (julliard@sunsite.unc.edu)

	* [Configure] [if1632/Imakefile]
	Removed new build and short names options.

	* [if1632/*.c] [tools/build.c]
	Implemented compiled call-back functions for better performance;
	all the relay code is now done in assembly code generated by the
	build program.
	Relay code is no longer dependent on being loaded below 64K.

	* [loader/resource.c]
	Fixed memory leak in LoadString(). A fix will also be needed for
	other resources.

	* [memory/global.c]
	Implemented global heap arenas, so we can store informations about
	global blocks, like lock counts or owner handle.
	Implemented FarGetOwner() and FarSetOwner().
	Implemented global heap TOOLHELP functions.

	* [memory/selector.c]
	Bug fix: it was not possible to re-use a free selector.

Sun Apr 2 01:34:52 1995 Constantine Sapuntzakis  (csapuntz@mit.edu)

	*  [controls/listbox.c]
	Major work on listbox code
         - Many bugs fixed (still many bugs)
         - More messages supported
         - Code simplified

Fri Mar 31 03:27:16 EST 1995 William Magro (wmagro@tc.cornell.edu)

	* [controls/edit.c]
	Lots of bug fixes related to diappearing text, lost carets,
	highlighting, segmentation faults, occurance of random
	characters, insertion of characters over selection, misplaced
	caret location, display corruption, end of line behavior, etc.

	* [controls/widgets.c]
	EDIT class doesn't want to use CS_PARENTDC flag.

Thu Mar 30 20:58:25 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
        
	* [loader/selector.c]
	  FixupFunctionPrologs() should also handle multiple data modules.
	  (this bug only became visible because MakeProcInstance() was fixed
	  in 950319)
	
	* [misc/dosfs.c]
	  Simplified DOS_SimplifyPath.
	  Small fix to DOS_opendir to reuse an entry if an open directory
	  is opened again, to prevent "too many open directories" messages.

Thu Mar 30 12:05:05 1995 Martin von Loewis  <loewis@informatik.hu-berlin.de>

	* [if1632/compobj.spec][include/compobj.h][misc/compobj.c]
	CoDisconnectObject: new stub function

	* [include/msdos.h]
	fix DOSVERSION

	* [loader/ne_image.c]
	NE_FixupSegment: Be more generous on additive fixups

	* [if1632/user.spec][misc/network.c]
	Add more WNet* stubs

Wed Mar 29 11:47:22 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>

        * [controls/listbox.c]
	  DlgDirList(): send segptr instead of linear pointer 
	  in message to static control
	* [controls/menu.c]
	  Tried to implement ownerdrawn menuitems. Doesn't work.
	* [if1632/gdi.spec] [include/windows.h] [objects/font.c]
	  Provide a stub for GetRasterizerCaps()
	* [loader/selector.c]
	  Pass end address instead of length to LocalInit() in 
	  CreateSelectors()
	* [memory/local.c]
	  LocalInit(): If there's already a local heap in the segment, do
	  nothing and return TRUE
	* [objects/linedda.c]
	  Replaced buggy LineDDA() with a Bresenham algorithm. Should work
	  now.
	* [windows/cursor.c]
	  LoadCursor()/CreateCursor(): Cleaned up the mess. Needs some
	  more work still.

Tue Mar 21 17:54:43 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>

        * [if1632/relay.c] [if1632/callback.c] [include/dlls.h]
	  [if1632/winprocs.spec] [if1632/winprocs.c] [include/winprocs.h]
	  [controls/widgets.c] [misc/shell.c] [misc/commdlg.c]
	  [windows/nonclient.c] [misc/message.c]
	  Added a new builtin DLL that provides 16 bit entry points for all
	  the Def*Procs (DefDlgProc, ButtonProc etc.). OWL programs work
	  again.
	* [misc/shell.c]
	  RegOpenKey()/RegCreateKey() bugs fixed.
        * [loader/ne_image.c]
	  Skipping the initialization of a DLL when CS == 0 was broken.
1995-04-03 16:55:37 +00:00

504 lines
15 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
static char RCSId[] = "$Id: wine.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "neexe.h"
#include "dlls.h"
#include "windows.h"
#include "arch.h"
#include "library.h"
#include "if1632.h"
#include "selectors.h"
#include "callback.h"
#include "ne_image.h"
#include "prototypes.h"
#include "stddebug.h"
#include "debug.h"
extern unsigned short WIN_StackSize;
extern unsigned short WIN_HeapSize;
void FixupFunctionPrologs(struct w_files *);
/**********************************************************************
* GetImportedName
*/
static
char *NE_GetImportedName(struct w_files *wpnt, int name_offset, char *buffer)
{
BYTE length;
lseek(wpnt->fd, wpnt->mz_header->ne_offset +
wpnt->ne->ne_header->iname_tab_offset + name_offset, SEEK_SET);
read(wpnt->fd, &length, 1); /* Get the length byte */
read(wpnt->fd, buffer, length);
buffer[length] = 0;
return buffer;
}
struct w_files *current_exe;
WORD current_nodata=0xfd00;
/**********************************************************************
* GetModuleName
*/
static char *NE_GetModuleName(struct w_files *wpnt, int index, char *buffer)
{
BYTE length;
WORD name_offset;
int i;
lseek(wpnt->fd, wpnt->mz_header->ne_offset +
wpnt->ne->ne_header->moduleref_tab_offset + 2 * (index - 1), SEEK_SET);
read(wpnt->fd, &name_offset, 2);
name_offset = CONV_SHORT (name_offset);
lseek(wpnt->fd, wpnt->mz_header->ne_offset +
wpnt->ne->ne_header->iname_tab_offset + name_offset, SEEK_SET);
read(wpnt->fd, &length, 1); /* Get the length byte */
read(wpnt->fd, buffer, length);
buffer[length] = 0;
/* Module names are always upper case */
for(i=0; i<length; i++)
if (islower(buffer[i]))
buffer[i] = toupper(buffer[i]);
return buffer;
}
#ifndef WINELIB
/**********************************************************************
* NE_FixupSegment
*/
int NE_FixupSegment(struct w_files *wpnt, int segment_num)
{
WORD *selector_table = wpnt->ne->selector_table;
WORD selector, sel, offset;
struct relocation_entry_s *rep, *rep1;
struct ne_segment_table_entry_s *seg;
int status, ordinal, i, n_entries, additive;
unsigned short *sp;
unsigned int address;
unsigned char dll_name[257], func_name[257];
seg = &wpnt->ne->seg_table[segment_num];
sel = selector_table[segment_num];
dprintf_fixup(stddeb, "Segment fixups for %s, segment %d, selector %04x\n",
wpnt->name, segment_num, sel );
if ((seg->seg_data_offset == 0) ||
!(seg->seg_flags & NE_SEGFLAGS_RELOC_DATA))
return 0;
/*
* Go through the relocation table on entry at a time.
*/
i = seg->seg_data_length;
if (i == 0)
i = 0x10000;
status = lseek(wpnt->fd, seg->seg_data_offset *
(1 << wpnt->ne->ne_header->align_shift_count) + i, SEEK_SET);
n_entries = 0;
read(wpnt->fd, &n_entries, sizeof(short int));
rep = (struct relocation_entry_s *)
malloc(n_entries * sizeof(struct relocation_entry_s));
if (read(wpnt->fd, rep, n_entries * sizeof(struct relocation_entry_s)) !=
n_entries * sizeof(struct relocation_entry_s))
{
myerror("Unable to read relocation information");
}
rep1 = rep;
for (i = 0; i < n_entries; i++, rep++)
{
/*
* Get the target address corresponding to this entry.
*/
/* If additive, there is no target chain list. Instead, add source
and target */
additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
rep->relocation_type &= 0x3;
switch (rep->relocation_type)
{
case NE_RELTYPE_ORDINAL:
if (NE_GetModuleName(wpnt, rep->target1,
dll_name) == NULL)
{
fprintf(stderr, "NE_RELTYPE_ORDINAL failed");
return -1;
}
ordinal = rep->target2;
status = GetEntryDLLOrdinal(dll_name, ordinal, &selector,
&offset);
if (status)
{
char s[80];
sprintf(s, "Bad DLL name '%s.%d'", dll_name, ordinal);
myerror(s);
return -1;
}
dprintf_fixup(stddeb,"%d: %s.%d: %04x:%04x\n", i + 1,
dll_name, ordinal, selector, offset);
break;
case NE_RELTYPE_NAME:
if (NE_GetModuleName(wpnt, rep->target1, dll_name) == NULL) {
fprintf(stderr,"NE_RELTYPE_NAME failed");
return -1;
}
if (NE_GetImportedName(wpnt, rep->target2, func_name) == NULL) {
fprintf(stderr,"NE_getimportedname failed");
return -1;
}
status = GetEntryDLLName(dll_name, func_name, &selector,
&offset);
if (status)
{
char s[80];
sprintf(s, "Bad DLL name '%s (%s)'", dll_name,func_name);
myerror(s);
return -1;
}
dprintf_fixup(stddeb,"%d: %s %s.%d: %04x:%04x\n", i + 1,
func_name, dll_name, ordinal, selector, offset);
break;
case NE_RELTYPE_INTERNAL:
if (rep->target1 == 0x00ff)
{
address = GetEntryPointFromOrdinal(wpnt, rep->target2);
selector = (address >> 16) & 0xffff;
offset = address & 0xffff;
}
else
{
selector = selector_table[rep->target1-1];
offset = rep->target2;
}
dprintf_fixup(stddeb,"%d: %04x:%04x\n",
i + 1, selector, offset);
break;
case NE_RELTYPE_OSFIXUP:
/* Relocation type 7:
*
* These appear to be used as fixups for the Windows
* floating point emulator. Let's just ignore them and
* try to use the hardware floating point. Linux should
* successfully emulate the coprocessor if it doesn't
* exist.
*/
dprintf_fixup(stddeb,
"%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
i + 1, rep->address_type, rep->relocation_type,
rep->offset);
dprintf_fixup(stddeb,"TARGET %04x %04x\n",
rep->target1, rep->target2);
continue;
default:
dprintf_fixup(stddeb,
"%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
i + 1, rep->address_type, rep->relocation_type,
rep->offset);
dprintf_fixup(stddeb,"TARGET %04x %04x\n",
rep->target1, rep->target2);
free(rep1);
return -1;
}
/* I'm not sure why a DLL entry point fixup could be additive.
Old code used to ignore additive if the target is a built-in
DLL. This doesn't seem to work for __AHSHIFT */
if (additive && FindDLLTable(dll_name) != NULL)
dprintf_fixup(stddeb,"Additive for builtin???\n"
"%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, "
"TARGET %04x %04x\n",
i+1, rep->address_type, rep->relocation_type,
rep->offset, rep->target1, rep->target2);
address = (unsigned int)offset;
offset = rep->offset;
switch (rep->address_type)
{
case NE_RADDR_LOWBYTE:
do {
sp = PTR_SEG_OFF_TO_LIN( sel, offset );
dprintf_fixup(stddeb," %04x:%04x:%04x BYTE%s\n",
sel, offset, *sp, additive ? " additive":"");
offset = *sp;
if(additive)
*(unsigned char*)sp = (unsigned char)(address & 0xFF);
else
*(unsigned char*)sp = (unsigned char)((address+offset) & 0xFF);
}
while (offset != 0xffff && !additive);
break;
case NE_RADDR_OFFSET16:
do {
sp = PTR_SEG_OFF_TO_LIN( sel, offset );
dprintf_fixup(stddeb," %04x:%04x:%04x OFFSET16%s\n",
sel, offset, *sp, additive ? " additive" : "" );
offset = *sp;
*sp = (unsigned short) address;
if (additive) *sp += offset;
}
while (offset != 0xffff && !additive);
break;
case NE_RADDR_POINTER32:
do {
sp = PTR_SEG_OFF_TO_LIN( sel, offset );
dprintf_fixup(stddeb," %04x:%04x:%04x POINTER32%s\n",
sel, offset, *sp, additive ? " additive" : "" );
offset = *sp;
*sp = (unsigned short) address;
if (additive) *sp += offset;
*(sp+1) = selector;
}
while (offset != 0xffff && !additive);
break;
case NE_RADDR_SELECTOR:
do {
sp = PTR_SEG_OFF_TO_LIN( sel, offset );
dprintf_fixup(stddeb," %04x:%04x:%04x SELECTOR%s\n",
sel, offset, *sp, additive ? " additive" : "" );
offset = *sp;
*sp = (unsigned short) selector;
/* Borland creates additive records with offset zero. Strange, but OK */
if(additive && offset)
fprintf(stderr,"Additive selector to %4.4x.Please report\n",offset);
}
while (offset != 0xffff && !additive);
break;
default:
dprintf_fixup(stddeb,
"%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
i + 1, rep->address_type, rep->relocation_type,
rep->offset);
dprintf_fixup(stddeb,
"TARGET %04x %04x\n", rep->target1, rep->target2);
free(rep1);
return -1;
}
}
free(rep1);
return 0;
}
int NE_unloadImage(struct w_files *wpnt)
{
dprintf_fixup(stdnimp, "NEunloadImage() called!\n");
/* free resources, image */
return 1;
}
int NE_StartProgram(struct w_files *wpnt)
{
extern WORD PSPSelector;
int cs_reg, ds_reg, ip_reg;
/* Registers at initialization must be:
* ax zero
* bx stack size in bytes
* cx heap size in bytes
* si previous app instance
* di current app instance
* bp zero
* es selector to the PSP
* ds dgroup of the application
* ss stack selector
* sp top of the stack
*/
/*
* Fixup stack and jump to start.
*/
WIN_StackSize = wpnt->ne->ne_header->stack_length;
WIN_HeapSize = wpnt->ne->ne_header->local_heap_length;
cs_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->cs-1];
ip_reg = wpnt->ne->ne_header->ip;
ds_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->auto_data_seg-1];
IF1632_Saved16_ss = wpnt->ne->selector_table[wpnt->ne->ne_header->ss-1];
IF1632_Saved16_sp = wpnt->ne->ne_header->sp;
IF1632_Saved16_bp = 0;
return CallTo16_regs_( (FARPROC)(cs_reg << 16 | ip_reg), ds_reg,
PSPSelector /*es*/, 0 /*ax*/, WIN_StackSize /*bx*/,
WIN_HeapSize, 0 /*dx*/, 0 /*si*/, ds_reg /*di*/ );
}
void NE_InitDLL(struct w_files *wpnt)
{
int cs_reg, ds_reg, ip_reg, cx_reg, di_reg, rv;
extern struct w_files *current_exe;
/*
* Is this a library?
*/
if (wpnt->ne->ne_header->format_flags & 0x8000)
{
if (!(wpnt->ne->ne_header->format_flags & 0x0001))
if(wpnt->ne->ne_header->format_flags & NE_FFLAGS_MULTIPLEDATA
|| wpnt->ne->ne_header->auto_data_seg)
{
/* Not SINGLEDATA */
fprintf(stderr, "Library is not marked SINGLEDATA\n");
exit(1);
} else { /* DATA NONE DLL */
ds_reg = current_exe->ne->selector_table[
current_exe->ne->ne_header->auto_data_seg-1];
cx_reg = 0;
} else { /* DATA SINGLE DLL */
ds_reg = wpnt->ne->selector_table[wpnt->ne->
ne_header->auto_data_seg-1];
cx_reg = wpnt->ne->ne_header->local_heap_length;
}
dprintf_dll(stddeb,"InitDLL: ne_header->cs = %04x\n",wpnt->ne->ne_header->cs);
if (!wpnt->ne->ne_header->cs) cs_reg = 0;
else cs_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->cs-1];
ip_reg = wpnt->ne->ne_header->ip;
di_reg = wpnt->hinstance;
if (cs_reg) {
dprintf_dll(stddeb,"Initializing %s, cs:ip %04x:%04x, ds %04x, cx %04x\n",
wpnt->name, cs_reg, ip_reg, ds_reg, cx_reg);
rv = CallTo16_regs_( (FARPROC)(cs_reg << 16 | ip_reg), ds_reg,
0 /*es*/, 0 /*ax*/, 0 /*bx*/, cx_reg,
0 /*dx*/, 0 /*si*/, di_reg );
dprintf_exec(stddeb,"rv = %x\n", rv);
} else
dprintf_exec(stddeb,"%s skipped\n", wpnt->name);
}
}
/**********************************************************************
* NE_LoadImage
* Load one NE format executable into memory
*/
HINSTANCE NE_LoadImage(struct w_files *wpnt)
{
unsigned int read_size, status, segment;
int i;
wpnt->ne = malloc(sizeof(struct ne_data));
wpnt->ne->resnamtab = NULL;
wpnt->ne->ne_header = malloc(sizeof(struct ne_header_s));
lseek(wpnt->fd, wpnt->mz_header->ne_offset, SEEK_SET);
if (read(wpnt->fd, wpnt->ne->ne_header, sizeof(struct ne_header_s))
!= sizeof(struct ne_header_s))
myerror("Unable to read NE header from file");
if(!(wpnt->ne->ne_header->format_flags & NE_FFLAGS_LIBMODULE)){
if(current_exe)printf("Warning: more than one EXE\n");
current_exe=wpnt;
}
#ifndef WINELIB
/*
* Create segment selectors.
*/
status = lseek(wpnt->fd, wpnt->mz_header->ne_offset +
wpnt->ne->ne_header->segment_tab_offset,
SEEK_SET);
read_size = wpnt->ne->ne_header->n_segment_tab *
sizeof(struct ne_segment_table_entry_s);
wpnt->ne->seg_table = (struct ne_segment_table_entry_s *) malloc(read_size);
if (read(wpnt->fd, wpnt->ne->seg_table, read_size) != read_size)
myerror("Unable to read segment table header from file");
wpnt->ne->selector_table = CreateSelectors(wpnt);
if(wpnt->ne->ne_header->auto_data_seg==0)
{
printf("DATA NONE DLL %s\n",wpnt->name);
wpnt->hinstance=current_nodata++;
} else
wpnt->hinstance = (wpnt->ne->
selector_table[wpnt->ne->ne_header->auto_data_seg-1]);
if (wpnt->hinstance == 0)
wpnt->hinstance = 0xf000;
#endif
/* Get the lookup table. This is used for looking up the addresses
of functions that are exported */
read_size = wpnt->ne->ne_header->entry_tab_length;
wpnt->ne->lookup_table = (char *) malloc(read_size);
lseek(wpnt->fd, wpnt->mz_header->ne_offset +
wpnt->ne->ne_header->entry_tab_offset, SEEK_SET);
if (read(wpnt->fd, wpnt->ne->lookup_table, read_size) != read_size)
myerror("Unable to read lookup table header from file");
/* Get the iname table. This is used for looking up the names
of functions that are exported */
status = lseek(wpnt->fd, wpnt->ne->ne_header->nrname_tab_offset, SEEK_SET);
read_size = wpnt->ne->ne_header->nrname_tab_length;
wpnt->ne->nrname_table = (char *) malloc(read_size);
if (read(wpnt->fd, wpnt->ne->nrname_table, read_size) != read_size)
myerror("Unable to read nrname table header from file");
status = lseek(wpnt->fd, wpnt->mz_header->ne_offset +
wpnt->ne->ne_header->rname_tab_offset, SEEK_SET);
read_size = wpnt->ne->ne_header->moduleref_tab_offset -
wpnt->ne->ne_header->rname_tab_offset;
wpnt->ne->rname_table = (char *) malloc(read_size);
if (read(wpnt->fd, wpnt->ne->rname_table, read_size) != read_size)
myerror("Unable to read rname table header from file");
/*
* Now load any DLLs that this module refers to.
*/
for(i=0; i<wpnt->ne->ne_header->n_mod_ref_tab; i++)
{
char buff[14];
NE_GetModuleName(wpnt, i + 1, buff);
if (strcasecmp(buff, wpnt->name) != 0 )
LoadImage(buff, DLL, 0);
}
#ifndef WINELIB
/* fixup references */
for (segment = 0; segment < wpnt->ne->ne_header->n_segment_tab; segment++)
if (NE_FixupSegment(wpnt, segment) < 0)
myerror("fixup failed.");
FixupFunctionPrologs(wpnt);
InitializeLoadedDLLs(wpnt);
#endif
return(wpnt->hinstance);
}
#endif /* !WINELIB */