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()}
diff --git a/loader/ne_image.c b/loader/ne_image.c
new file mode 100644
index 0000000..98b3059
--- /dev/null
+++ b/loader/ne_image.c
@@ -0,0 +1,461 @@
+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