wine/loader/ne_image.c
Alexandre Julliard 490a27e012 Release 940607
Tue Jun  7 08:41:27 1994  Bob Amstadt  (bob@pooh)

	* loader/selector.c (FixupFunctionPrologs): 
	New function to fixup loaded DLL function prologs.  It replaces the
	do nothing code with code that loads DS with the appropriate data
	segment for the DLL.

	* misc/cursor.c (LoadCursor): 
	Disabled cursor loading from .EXE or .DLL.  The code needs to handle
	the possibility of multiple cursors in a single directory.  Also,
	it should check to see if the cursor is the right size.

	* objects/font.c (EnumFonts): 
	Checked for lpLogFontList[i] == NULL

	* objects/gdiobj.c (SetObjectOwner): 
	Removed stub.  Replaced with simple return in gdi.spec.  This
	function is not defined for the retail version of Windows.

	* memory/heap.c (WIN16_LocalHandleDelta): 
	New function.  This is really a dummy that imitates the proper
	return values.

	* loader/library.c (GetProcAddress): 
	Fixed definition of IS_BUILTIN_DLL() macro.

Mon Jun  6 18:15:40 1994  Bob Amstadt  (bob@pooh)

	* miscemu/int21.c (SeekFile): 
	Needed to return current position in DX:AX.

	* windows/utility.c (windows_wsprintf): 
	Added support for '#' in format, and fixed bug with "ptr" being
	incremented too many times.

	* miscemu/int21.c (OpenExistingFile): 
	Add code to handle opening files read-only and write-only.

	* loader/wine.c:
	Segment fixups now done in LoadImage instead of _WinMain.  This
	is necessary to support LoadLibrary().

Sun Jun  5 17:34:24 1994  Erik Bos (erik@hacktic.nl)

	* [loader/*]
		- fixed: GetModuleHandle() sometimes returned
		  a wrong handle.
		- don't init dlls when cs == 0 (lzexpand, doesn't
		  seem to have a init function)
		- LoadLibrary & LoadImage now return error instead
		  of stopping wine.
		- moved most of NE-functions into one file.
		- LoadLibrary() uses w_files list instead of its
		  own list.
		- NE exectables are now fixed-up and initialised when
		  loaded instead of only once before calling InitTask.

	* [miscemu/int15.c] [miscemu/int31.c]
	Added.	

	* [loader/selector.c]
	Stubs added for {Get|Set}SelectorLimit(), {Get|Set}SelectorBase().

	* [misc/main.c]
	Stub added for IsRomModule().

	* [miscemu/int21.c]
	Some cleanup, added heap for returning data.

Jun 6, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [tools/build.c]
	Change MAX_ORDINALS	define to higher value, 1299 entries.
	(MMSYSTEM doesn't have succesive numbers, some are around 1200).

	* [windows/utility.c]
	Bug fix in windows_wsprintf(), (twice increments ...).

	* [windows/winpos.c]
	Bug fix in SetWindowPos(), redraw was done if flag
		was set to SWP_NOREDRAW while SWP_SHOWWINDOW).

	* [misc/message.c] [controls/combo.c]
	Add an InvalidateRect() in WM_SHOWWINDOW to statisfy the new 'saveunder'.

	* [windows/win.c]
	In CreateWindowEx(), do SetMenu() calls after window creation,
		just before sending to WM_NCCALCSIZE.

	* [controls/menu.c]
	In function SetMenu(), now use SetWindowPos() with 
		flags SWP_FRAMECHANGED to readjust menu area.
	Function MenuBarCalcSize() redone.

Sun May 29 11:08:24 1994  David B. Thomas  (dt@yenta.abq.nm.us)

        * [objects/text.c]
        Fixed problems associated with DT_WORDBREAK flag.  String length
        was not being properly decremented when lines were folded, and
        wrapping was not performed when DT_NOCLIP and DT_NOPREFIX were
        both on in addition to DT_WORDBREAK.  Windows does wrapping in
        this case, and now so does wine.

Sun Jun  5 19:17:49 1994  Olaf Flebbe  (olaf@dragon)

        * [edit.c]
        cp1 was uninitialized iff lineno == 0

        *  FindFile tests for existance of file even if a full
           filename was supplied. What about unix file names?

        * [controls/listbox ]
        wndPtr was uninitialized for LB_SETTOPINDEX

        * [misc/property.c]     
        Do not free lpProp. Is it really allocated by malloc?
	{edited by Bob Amstadt: changed free() to GlobalFree()}
1994-06-08 13:57:50 +00:00

461 lines
12 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>
#ifdef linux
#include <linux/unistd.h>
#include <linux/head.h>
#include <linux/ldt.h>
#include <linux/segment.h>
#endif
#include <string.h>
#include <errno.h>
#include "neexe.h"
#include "segmem.h"
#include "prototypes.h"
#include "dlls.h"
#include "wine.h"
#include "windows.h"
#include "wineopts.h"
#include "arch.h"
#include "options.h"
/* #define DEBUG_FIXUP /* */
extern HANDLE CreateNewTask(HINSTANCE hInst);
extern int CallToInit16(unsigned long csip, unsigned long sssp,
unsigned short ds);
extern void InitializeLoadedDLLs(struct w_files *wpnt);
extern void FixupFunctionPrologs(struct w_files * wpnt);
char * GetModuleName(struct w_files * wpnt, int index, char *buffer);
extern char WindowsPath[256];
char *WIN_ProgramName;
HINSTANCE hSysRes;
#ifndef WINELIB
/**********************************************************************/
void load_ne_header (int fd, struct ne_header_s *ne_header)
{
if (read(fd, ne_header, sizeof(struct ne_header_s))
!= sizeof(struct ne_header_s))
{
myerror("Unable to read NE header from file");
}
}
/**********************************************************************
* LoadNEImage
* Load one NE format executable into memory
*/
HINSTANCE LoadNEImage(struct w_files *wpnt)
{
unsigned int read_size, status, segment;
int i;
char buffer[256];
char *fullname;
HANDLE t;
wpnt->ne_header = (struct ne_header_s *) malloc(sizeof(struct ne_header_s));
status = lseek(wpnt->fd, wpnt->mz_header->ne_offset, SEEK_SET);
load_ne_header (wpnt->fd, wpnt->ne_header);
/*
* Create segment selectors.
*/
status = lseek(wpnt->fd, wpnt->mz_header->ne_offset +
wpnt->ne_header->segment_tab_offset,
SEEK_SET);
read_size = wpnt->ne_header->n_segment_tab *
sizeof(struct ne_segment_table_entry_s);
wpnt->seg_table = (struct ne_segment_table_entry_s *) malloc(read_size);
if (read(wpnt->fd, wpnt->seg_table, read_size) != read_size)
myerror("Unable to read segment table header from file");
wpnt->selector_table = CreateSelectors(wpnt);
wpnt->hinstance = (wpnt->
selector_table[wpnt->ne_header->auto_data_seg-1].
selector);
/* Get the lookup table. This is used for looking up the addresses
of functions that are exported */
read_size = wpnt->ne_header->entry_tab_length;
wpnt->lookup_table = (char *) malloc(read_size);
lseek(wpnt->fd, wpnt->mz_header->ne_offset +
wpnt->ne_header->entry_tab_offset, SEEK_SET);
if (read(wpnt->fd, wpnt->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_header->nrname_tab_offset, SEEK_SET);
read_size = wpnt->ne_header->nrname_tab_length;
wpnt->nrname_table = (char *) malloc(read_size);
if (read(wpnt->fd, wpnt->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_header->rname_tab_offset, SEEK_SET);
read_size = wpnt->ne_header->moduleref_tab_offset -
wpnt->ne_header->rname_tab_offset;
wpnt->rname_table = (char *) malloc(read_size);
if (read(wpnt->fd, wpnt->rname_table, read_size) != read_size)
myerror("Unable to read rname table header from file");
/* Now get the module name, if the current one is a filename */
/* nope, name by which dll is loaded is used !
if (strchr(wpnt->name, '\\') || strchr(wpnt->name, '/') ) {
wpnt->name = (char*) malloc(*wpnt->rname_table + 1);
memcpy(wpnt->name, wpnt->rname_table+1, *wpnt->rname_table);
}
wpnt->name[*wpnt->rname_table] = 0;
*/
/*
* Now load any DLLs that this module refers to.
*/
for(i=0; i<wpnt->ne_header->n_mod_ref_tab; i++)
{
char buff[14];
GetModuleName(wpnt, i + 1, buff);
if (strcasecmp(buff, wpnt->name) != 0 )
LoadImage(buff, DLL, 0);
}
/* fixup references */
for (segment = 0; segment < wpnt->ne_header->n_segment_tab; segment++)
if (FixupSegment(wpnt, segment) < 0)
myerror("fixup failed.");
FixupFunctionPrologs(wpnt);
InitializeLoadedDLLs(wpnt);
return(wpnt->hinstance);
}
/**********************************************************************
* GetImportedName
*/
char *
GetImportedName(int fd, struct mz_header_s *mz_header,
struct ne_header_s *ne_header, int name_offset, char *buffer)
{
int length;
int status;
status = lseek(fd, mz_header->ne_offset + ne_header->iname_tab_offset +
name_offset, SEEK_SET);
length = 0;
read(fd, &length, 1); /* Get the length byte */
length = CONV_CHAR_TO_LONG (length);
read(fd, buffer, length);
buffer[length] = 0;
return buffer;
}
/**********************************************************************
* GetModuleName
*/
char *
GetModuleName(struct w_files * wpnt, int index, char *buffer)
{
int fd = wpnt->fd;
struct mz_header_s *mz_header = wpnt->mz_header;
struct ne_header_s *ne_header = wpnt->ne_header;
int length;
WORD name_offset, status;
int i;
status = lseek(fd, mz_header->ne_offset + ne_header->moduleref_tab_offset +
2*(index - 1), SEEK_SET);
name_offset = 0;
read(fd, &name_offset, 2);
name_offset = CONV_SHORT (name_offset);
status = lseek(fd, mz_header->ne_offset + ne_header->iname_tab_offset +
name_offset, SEEK_SET);
length = 0;
read(fd, &length, 1); /* Get the length byte */
length = CONV_CHAR_TO_LONG (length);
read(fd, buffer, length);
buffer[length] = 0;
/* Module names are always upper case */
for(i=0; i<length; i++)
if(buffer[i] >= 'a' && buffer[i] <= 'z') buffer[i] &= ~0x20;
return buffer;
}
/**********************************************************************
* FixupSegment
*/
int
FixupSegment(struct w_files * wpnt, int segment_num)
{
int fd = wpnt->fd;
struct mz_header_s * mz_header = wpnt->mz_header;
struct ne_header_s *ne_header = wpnt->ne_header;
struct ne_segment_table_entry_s *seg_table = wpnt->seg_table;
struct segment_descriptor_s *selector_table = wpnt->selector_table;
struct relocation_entry_s *rep, *rep1;
struct ne_segment_table_entry_s *seg;
struct segment_descriptor_s *sel;
struct dll_table_entry_s *dll_table;
int status;
unsigned short *sp;
unsigned int selector, address;
unsigned int next_addr;
int ordinal;
char dll_name[257];
char func_name[257];
int i, n_entries;
int additive;
seg = &seg_table[segment_num];
sel = &selector_table[segment_num];
#ifdef DEBUG_FIXUP
printf("Segment fixups for %s, segment %d, selector %x\n",
wpnt->name, segment_num, (int) sel->base_addr >> 16);
#endif
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(fd, seg->seg_data_offset *
(1 << ne_header->align_shift_count) + i, SEEK_SET);
n_entries = 0;
read(fd, &n_entries, sizeof(short int));
rep = (struct relocation_entry_s *)
malloc(n_entries * sizeof(struct relocation_entry_s));
if (read(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.
*/
additive = 0;
switch (rep->relocation_type)
{
case NE_RELTYPE_ORDINALADD:
additive = 1;
case NE_RELTYPE_ORDINAL:
if (GetModuleName(wpnt, rep->target1,
dll_name) == NULL)
{
fprintf(stderr, "NE_RELTYPE_ORDINAL failed");
return -1;
}
ordinal = rep->target2;
status = GetEntryDLLOrdinal(dll_name, ordinal, &selector,
&address);
if (status)
{
char s[80];
sprintf(s, "Bad DLL name '%s.%d'", dll_name, ordinal);
myerror(s);
return -1;
}
#ifdef DEBUG_FIXUP
printf("%d: %s.%d: %04.4x:%04.4x\n", i + 1, dll_name, ordinal,
selector, address);
#endif
break;
case NE_RELTYPE_NAMEADD:
additive = 1;
case NE_RELTYPE_NAME:
if (GetModuleName(wpnt, rep->target1, dll_name)
== NULL)
{
fprintf(stderr,"NE_RELTYPE_NAME failed");
return -1;
}
if (GetImportedName(fd, mz_header, ne_header,
rep->target2, func_name) == NULL)
{
fprintf(stderr,"getimportedname failed");
return -1;
}
status = GetEntryDLLName(dll_name, func_name, &selector,
&address);
if (status)
{
char s[80];
sprintf(s, "Bad DLL name '%s (%s)'", dll_name,func_name);
myerror(s);
return -1;
}
#ifdef DEBUG_FIXUP
printf("%d: %s %s.%d: %04.4x:%04.4x\n", i + 1, func_name,
dll_name, ordinal, selector, address);
#endif
break;
case NE_RELTYPE_INTERNAL:
case NE_RELTYPE_INT1:
if (rep->target1 == 0x00ff)
{
address = GetEntryPointFromOrdinal(wpnt, rep->target2);
selector = (address >> 16) & 0xffff;
address &= 0xffff;
}
else
{
selector = selector_table[rep->target1-1].selector;
address = rep->target2;
}
#ifdef DEBUG_FIXUP
printf("%d: %04.4x:%04.4x\n", i + 1, selector, address);
#endif
break;
case 7:
/* 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.
*/
#ifdef DEBUG_FIXUP
printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
i + 1, rep->address_type, rep->relocation_type,
rep->offset);
printf("TARGET %04.4x %04.4x\n", rep->target1, rep->target2);
#endif
continue;
default:
fprintf(stderr,"%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
i + 1, rep->address_type, rep->relocation_type,
rep->offset);
fprintf(stderr,"TARGET %04.4x %04.4x\n",
rep->target1, rep->target2);
free(rep1);
return -1;
}
/*
* Stuff the right size result in.
*/
sp = (unsigned short *) ((char *) sel->base_addr + rep->offset);
if (additive)
{
if (FindDLLTable(dll_name) == NULL)
additive = 2;
fprintf(stderr,"%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
i + 1, rep->address_type, rep->relocation_type,
rep->offset);
fprintf(stderr,"TARGET %04.4x %04.4x\n",
rep->target1, rep->target2);
fprintf(stderr, " Additive = %d\n", additive);
}
switch (rep->address_type)
{
case NE_RADDR_OFFSET16:
do {
#ifdef DEBUG_FIXUP
printf(" %04.4x:%04.4x:%04.4x OFFSET16\n",
(unsigned long) sp >> 16, (int) sp & 0xFFFF, *sp);
#endif
next_addr = *sp;
*sp = (unsigned short) address;
if (additive == 2)
*sp += next_addr;
sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
}
while (next_addr != 0xffff && !additive);
break;
case NE_RADDR_POINTER32:
do {
#ifdef DEBUG_FIXUP
printf(" %04.4x:%04.4x:%04.4x POINTER32\n",
(unsigned long) sp >> 16, (int) sp & 0xFFFF, *sp);
#endif
next_addr = *sp;
*sp = (unsigned short) address;
if (additive == 2)
*sp += next_addr;
*(sp+1) = (unsigned short) selector;
sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
}
while (next_addr != 0xffff && !additive);
break;
case NE_RADDR_SELECTOR:
do {
#ifdef DEBUG_FIXUP
printf(" %04.4x:%04.4x:%04.4x SELECTOR\n",
(unsigned long) sp >> 16, (int) sp & 0xFFFF, *sp);
#endif
next_addr = *sp;
*sp = (unsigned short) selector;
sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
if (rep->relocation_type == NE_RELTYPE_INT1)
break;
}
while (next_addr != 0xffff && !additive);
break;
default:
printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
i + 1, rep->address_type, rep->relocation_type,
rep->offset);
printf("TARGET %04.4x %04.4x\n", rep->target1, rep->target2);
free(rep1);
return -1;
}
}
free(rep1);
return 0;
}
#endif