Release 950727

Sat Jul 22 22:39:09 IDT 1995 Michael Veksler <e1678223@tochnapc2.technion.ac.il>

	* [ipc/*]
	New directory. This directory contains the new inter-wine
 	communications support. It enables DDE protocols between two wine
 	instances.  Currently it is limited to DDE, but can be enhanced to
 	support OLE between 2 different wine instances.  This is very
 	important for libwine.a DDE/OLE support.

	* [tools/ipcl]
    	A script to delete garbage IPC handles (shared memory, semaphores
 	and message queues).  The current inter-wine communication is not
 	perfect, and sometimes leaves garbage behind.

	* [if1632/relay.c] [include/atom.h] [include/global.h]
 	[loader/selector.c] [loader/task.c] [loader/module.c]
 	[loader/signal.c] [memory/global.c] [misc/atom.c]
 	[windows/class.c] [windows/message.c] [windows/win.c]
	[Imakefile]
    	Hooks for inter-wine DDE support, current Global.*Atom functions
 	renamed to Local.*Atom since Global.*Atom are used for Inter-Wine
 	DDE communication. (The first call to these functions sets up the
 	IPC structures - which otherwise cause unneeded overhead.

Mon Jul 17 19:55:21 1995  Alexandre Julliard  <julliard@sunsite.unc.edu>

	* [controls/menu.c]
	Don't crash if a NULL string is passed to menu functions.

	* [memory/selector.c]
	We now use a bit in ldt_flags_copy to indicate free LDT entries.
	Fixed a bug in SELECTOR_ReallocBlock that could cause it to
	overwrite valid LDT entries when growing a block.

	* [miscemu/instr.c]
	Emulate int xx instruction by storing the interrupt vector in
	CS:IP and returning directly. This allows a program to install an
	interrupt vector.

	* [windows/win.c]
	Added function WIN_GetTopParent to get the top-level parent of a
	window.

Sun Jul  16 18:17:17 1995  Gregory Trubetskoy <grisha@mira.com>

        * [loader/resource.c]
        Added LoadIconHandler. It doesn't do anything yet, but now you
        can use borland help files with winhelp.exe.

Sun Jul 16 11:58:45 1995 Anand Kumria <akumria@ozemail.com.au>

	* [misc/main.c]
	Fixed to return 386 Enhanced mode correctly. Also return the same
 	type of CPU, for both Enhanced and Standard mode, namely a 386.

Sun Jul 16 00:02:04 1995    Martin von Loewis <loewis@informatik.hu-berlin.de>

	* [Configure] [include/options.h] [include/wineopts.h]
	  [misc/main.c][misc/spy.c]
	  Removed support of spy file. Redirected spy messages to stddeb.
	  Removed -spy option. Added -debugmsg +spy option.

	* [debugger/dbg.y][debugger/debug.l]
	Enabled segmented addresses (seg:offs) for break and x commands.

	* [if1632/gdi.spec] [objects/region.c] [windows/graphics.c]
	  [include/region.h]
	FrameRgn, REGION_FrameRgn: New functions

	* [if1632/kernel.spec]
	IsWinOldApTask: Return false

	* [if1632/mouse.spec]
	CplApplet: Removed

	* [if1632/user.spec] [windows/win.c]
	ShowOwnedPopups: New function

	* [if1632/winsock.spec] [misc/winsocket.c]
	inet_addr, select: New prototypes in relay code
	Fixed memory layout for netdb functions (getXbyY).
	WINSOCK_ioctlsocket: Translated FIONREAD, FIONBIO, and FIOASYNC

	* [objects/clipping.c]
	RectVisible: Fixed call to LPToDP

	* [rc/winerc.c]
	main: Removed extra argument to getopt for Linux.

Tue Jul 11 00:14:41 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>

        * [controls/listbox.c]
	Yet another fix for ListBoxDirectory().
	
	* [loader/module.c] [if1632/kernel.spec]
	Make GetModuleHandle() accept instance handles as parameter.

        * [if1632/relay.c] [loader/task.c]
	Put a magic cookie at the bottom of the 32 bit stack, and check on
	each return from a 32 bit function whether it's still there. Complain
	if it's not.

        * [if1632/user.spec]
	Wrong entry for CloseDriver().

	* [misc/dos_fs.c] [loader/task.c] [include/dos_fs.h] [misc/file.c]
	[miscemu/int21.c]
	Large parts of dos_fs.c simplified. Changed it to use one
	current drive/directory per task, which is set to the module path on
	task creation.
	Prevent CorelPaint from closing stdin.
	open() with O_CREAT set must be passed three parameters.
	DOS FindFirst()/FindNext() could crash when FA_LABEL was set. Fixed,
	it's in DOS_readdir() now.

	* [misc/profile.c]
	Some badly written software (Lotus Freelance Graphics) passes a bogus
	size parameter that caused Wine to write off the end of a segment.
	Fixed. (It's probably too paranoid now.)
	
	* [multimedia/mmsystem.c] [multimedia/time.c] [multimedia/joystick.c]
	[multimedia/Imakefile] [if1632/winprocs.spec]
	16 bit entry point for MMSysTimeCallback.
	Split off time.c and joystick.c from mmsystem.c.
	
	* [objects/dib.c]
	GetDIBits(): call XGetImage() via CallTo32_LargeStack.

        * [windows/cursor.c]
	DestroyCursor(): do nothing for builtin cursors.
	
	* [windows/mdi.c]
	Half of WM_MDISETMENU implemented.
	
	* [windows/win.c]
	EnumWindows() and EnumTaskWindows() never enumerated any windows.
	Fixed.

	* [windows/*.c]
	Fixed GetParent() to return correct values for owned windows.

	* [windows/message.c]
	Don't try to activate disabled top-level windows.

        * [windows/nonclient.c]
	Work around a bug in gcc-2.7.0.
	
	* [tools/build.c] [include/stackframe.h] [memory/global.c] 
	[loader/task.c] [memory/selector.c]
	Some Visual Basic programs (and possibly others, too) expect ES to be 
	preserved by a call to an API function, so we have to save it.
	In GlobalFree() and FreeSelector(), we must clear CURRENT_STACK16->es 
	to prevent segfaults if ES contained the selector to be freed.

Sun Jul  9 20:21:20 1995  Jon Tombs  <jon@gtex02.us.es>

	* [*/*]
	Added missing prototypes to header files and relevant includes
	to reduce compile time warnings.

Sun Jul  9 18:32:56 1995  Michael Patra  <micky@marie.physik.tu-berlin.de>

	* [configure.in] [include/config.h] [*/Makefile.in]
	New configuration scheme based on autoconf.

Sat Jul  8 14:12:45 1995  Morten Welinder  <terra+@cs.cmu.edu>

	* [miscemu/ioports.c]
	Revamp to have only one in- and one out- variant, both really
 	implemented.

	* [miscemu/instr.c]
	INSTR_EmulateInstruction: Use new ioport interface.  Implement
 	string io.  Correct instruction pointer for 32-bit code.

	* [include/miscemu.h]
	Update port function prototypes.

	* [include/registers.h]
	Defined FS and GS.

Sat Jul  8 13:38:54 1995  Hans de Graaff  <graaff@twi72.twi.tudelft.nl>

	* [misc/dos_fs.c]
	ChopOffSlash(): A path consisting off a single slash is left
 	intact, and multiple slashes are all removed.
diff --git a/misc/Makefile.in b/misc/Makefile.in
new file mode 100644
index 0000000..84afd90
--- /dev/null
+++ b/misc/Makefile.in
@@ -0,0 +1,59 @@
+CC 	= @CC@
+CFLAGS 	= @CFLAGS@
+XINCL 	= @x_includes@
+TOPSRC  = @top_srcdir@
+DIVINCL = -I$(TOPSRC)/include -I$(TOPSRC)
+LD	= @LD@
+LANG	= @LANG@
+LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
+@SET_MAKE@
+
+
+MODULE 	= misc
+
+SRCS 	= atom.c clipboard.c comm.c commdlg.c compobj.c dos_fs.c \
+	driver.c exec.c escape.c file.c keyboard.c kernel32.c lstr.c \
+	main.c ole2.c ole2disp.c ole2nls.c olecli.c olesvr.c network.c \
+	profile.c rect.c shell.c sound.c spy.c stress.c user.c \
+	winsocket.c
+ 
+OBJS = $(SRCS:.c=.o)
+
+.c.o:
+	$(CC) -c $(CFLAGS) $(XINCL) $(DIVINCL) $(LANG) -o $*.o $<
+
+all: checkrc $(MODULE).o
+
+checkrc:
+	(cd $(TOPSRC)/rc; $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'LD=$(LD)' 'LDCOMBINEFLAGS=$(LDCOMBINEFLAGS)')
+
+$(MODULE).o: $(OBJS)
+	$(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $(MODULE).o
+
+depend:
+	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
+	$(CC) $(DIVINCL) $(XINCL) -MM *.c >> tmp_make
+	cp tmp_make Makefile
+	rm tmp_make
+
+clean:
+	rm -f *.o \#*\# *~ tmp_make
+
+distclean: clean
+	rm Makefile
+
+countryclean:
+	rm -f ole2nls.o shell.o commdlg.o
+
+NAMES = $(SRCS:.c=)
+
+winelibclean:
+	for i in $(NAMES); do \
+	if test `grep -c WINELIB $$i.c` -ne 0; then \
+	rm $$i.o; \
+	fi; \
+	done
+ 
+dummy:
+
+### Dependencies:
diff --git a/misc/atom.c b/misc/atom.c
index a34e062..f3286cd 100644
--- a/misc/atom.c
+++ b/misc/atom.c
@@ -329,36 +329,36 @@
 
 
 /***********************************************************************
- *           GlobalAddAtom   (USER.268)
+ *           LocalAddAtom   (USER.268)
  */
-ATOM GlobalAddAtom( LPCSTR str )
+ATOM LocalAddAtom( LPCSTR str )
 {
     return ATOM_AddAtom( USER_HeapSel, str );
 }
 
 
 /***********************************************************************
- *           GlobalDeleteAtom   (USER.269)
+ *           LocalDeleteAtom   (USER.269)
  */
-ATOM GlobalDeleteAtom( ATOM atom )
+ATOM LocalDeleteAtom( ATOM atom )
 {
     return ATOM_DeleteAtom( USER_HeapSel, atom );
 }
 
 
 /***********************************************************************
- *           GlobalFindAtom   (USER.270)
+ *           LocalFindAtom   (USER.270)
  */
-ATOM GlobalFindAtom( LPCSTR str )
+ATOM LocalFindAtom( LPCSTR str )
 {
     return ATOM_FindAtom( USER_HeapSel, str );
 }
 
 
 /***********************************************************************
- *           GlobalGetAtomName   (USER.271)
+ *           LocalGetAtomName   (USER.271)
  */
-WORD GlobalGetAtomName( ATOM atom, LPSTR buffer, short count )
+WORD LocalGetAtomName( ATOM atom, LPSTR buffer, short count )
 {
     return ATOM_GetAtomName( USER_HeapSel, atom, buffer, count );
 }
diff --git a/misc/dos_fs.c b/misc/dos_fs.c
index 08de3c0..c1fd240 100644
--- a/misc/dos_fs.c
+++ b/misc/dos_fs.c
@@ -31,6 +31,7 @@
 #include "dos_fs.h"
 #include "autoconf.h"
 #include "comm.h"
+#include "task.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -47,7 +48,7 @@
 struct DosDriveStruct {			/*  eg: */
 	char 		*rootdir;	/*  /usr/windows 	*/
 	char 		cwd[256];	/*  /			*/
-	char 		label[13];	/*  DRIVE-A		*/		
+	char 		label[13];	/*  DRIVE-A		*/
 	unsigned int	serialnumber;	/*  ABCD5678		*/
 	int 		disabled;	/*  0			*/
 };
@@ -83,146 +84,154 @@
     *s = 0;
 }
 
+/* Simplify the path in "name" by removing  "//"'s and
+   ".."'s in names like "/usr/bin/../lib/test" */
+static void DOS_SimplifyPath(char *name)
+{
+  char *l,*p;
+  BOOL changed;
+
+  dprintf_dosfs(stddeb,"SimplifyPath: Before %s\n",name);
+  do {
+    changed = FALSE;
+    while ((l = strstr(name,"//"))) {
+      strcpy(l,l+1); changed = TRUE;
+    } 
+    while ((l = strstr(name,"/../"))) {
+      *l = 0;
+      p = strrchr(name,'/');
+      if (p == NULL) p = name;
+      strcpy(p,l+3);
+      changed = TRUE;
+    }
+  } while (changed);
+  dprintf_dosfs(stddeb,"SimplifyPath: After %s\n",name);
+}
+
+
+/* ChopOffSlash takes care to strip directory slashes from the
+ * end off the path name, but leaves a single slash. Multiple
+ * slashes at the end of a path are all removed.
+ */
+
 void ChopOffSlash(char *path)
 {
-	if (path[strlen(path)-1] == '/' || path[strlen(path)-1] == '\\')
-		path[strlen(path)-1] = '\0';
+    char *p = path + strlen(path) - 1;
+    while ((*p == '\\') && (p > path)) *p-- = '\0';
 }
 
 void ToUnix(char *s)
 {
-	/*  \WINDOWS\\SYSTEM   =>   /windows/system */
-
-	char *p;
-
-	for (p = s; *p; p++) 
-	{
-		if (*p != '\\')
-			*s++ = tolower(*p);
-		else {
-			*s++ = '/';
-			if (*(p+1) == '/' || *(p+1) == '\\')
-				p++;
-		}
-	}
-	*s = '\0';
+    while(*s){
+	if (*s == '\\') *s = '/';
+	s++;
+    }
 }
 
 void ToDos(char *s)
 {
-	/* /windows//system   =>   \WINDOWS\SYSTEM */
-
-	char *p;
-	for (p = s; *p; p++) 
-	{
-		if (*p != '/')
-			*s++ = toupper(*p);
-		else {
-			*s++ = '\\';
-			if (*(p+1) == '/' || *(p+1) == '\\') 
-			    p++;
-		}
-	}
-	*s = '\0';
+    while(*s){
+	if (*s == '/') *s = '\\';
+	s++;
+    }
 }
 
 void DOS_InitFS(void)
 {
-	int x;
-	char drive[2], temp[256];
+    int x;
+    char drive[2], temp[256];
+    
+    GetPrivateProfileString("wine", "windows", "c:\\windows", 
+			    WindowsDirectory, sizeof(WindowsDirectory), WINE_INI);
+    
+    GetPrivateProfileString("wine", "system", "c:\\windows\\system", 
+			    SystemDirectory, sizeof(SystemDirectory), WINE_INI);
+    
+    GetPrivateProfileString("wine", "temp", "c:\\windows", 
+			    TempDirectory, sizeof(TempDirectory), WINE_INI);
 
-	GetPrivateProfileString("wine", "windows", "c:\\windows", 
-		WindowsDirectory, sizeof(WindowsDirectory), WINE_INI);
-
-	GetPrivateProfileString("wine", "system", "c:\\windows\\system", 
-		SystemDirectory, sizeof(SystemDirectory), WINE_INI);
-
-	GetPrivateProfileString("wine", "temp", "c:\\windows", 
-		TempDirectory, sizeof(TempDirectory), WINE_INI);
-
-	GetPrivateProfileString("wine", "path", "c:\\windows;c:\\windows\\system", 
-		WindowsPath, sizeof(WindowsPath), WINE_INI);
-
-	ChopOffSlash(WindowsDirectory);
-	ToDos(WindowsDirectory);
-
-	ChopOffSlash(SystemDirectory);
-	ToDos(SystemDirectory);
-
-	ChopOffSlash(TempDirectory);
-	ToDos(TempDirectory);
-
-	ToDos(WindowsPath);
-	ExpandTildeString(WindowsPath);
-
-	for (x=0; x!=MAX_DOS_DRIVES; x++) {
-		DosDrives[x].serialnumber = (0xEB0500L | x);
-		
-		drive[0] = 'A' + x;
-		drive[1] = '\0';
-		GetPrivateProfileString("drives", drive, "*", temp, sizeof(temp), WINE_INI);
-		if (!strcmp(temp, "*") || *temp == '\0') {
-			DosDrives[x].rootdir = NULL;		
-			DosDrives[x].cwd[0] = '\0';
-			DosDrives[x].label[0] = '\0';
-			DosDrives[x].disabled = 1;
-			continue;
-		}
-		ExpandTildeString(temp);
-		ChopOffSlash(temp);
-		DosDrives[x].rootdir = strdup(temp);
-		strcpy(DosDrives[x].rootdir, temp);
-		strcpy(DosDrives[x].cwd, "/windows/");
-		strcpy(DosDrives[x].label, "DRIVE-");
-		strcat(DosDrives[x].label, drive);
-		DosDrives[x].disabled = 0;
+    GetPrivateProfileString("wine", "path", "c:\\windows;c:\\windows\\system", 
+			    WindowsPath, sizeof(WindowsPath), WINE_INI);
+    
+    ChopOffSlash(WindowsDirectory);
+    ToDos(WindowsDirectory);
+    
+    ChopOffSlash(SystemDirectory);
+    ToDos(SystemDirectory);
+    
+    ChopOffSlash(TempDirectory);
+    ToDos(TempDirectory);
+    
+    ToDos(WindowsPath);
+    ExpandTildeString(WindowsPath);
+    
+    for (x=0; x!=MAX_DOS_DRIVES; x++) {
+	DosDrives[x].serialnumber = (0xEB0500L | x);
+	
+	drive[0] = 'A' + x;
+	drive[1] = '\0';
+	GetPrivateProfileString("drives", drive, "*", temp, sizeof(temp), WINE_INI);
+	if (!strcmp(temp, "*") || *temp == '\0') {
+	    DosDrives[x].rootdir = NULL;		
+	    DosDrives[x].cwd[0] = '\0';
+	    DosDrives[x].label[0] = '\0';
+	    DosDrives[x].disabled = 1;
+	    continue;
 	}
-	DosDrives[25].rootdir = "/";
-	strcpy(DosDrives[25].cwd, "/");
-	strcpy(DosDrives[25].label, "UNIX-FS");
-	DosDrives[25].serialnumber = 0x12345678;
-	DosDrives[25].disabled = 0;
+	ExpandTildeString(temp);
+	ChopOffSlash(temp);
+	DosDrives[x].rootdir = strdup(temp);
+	strcpy(DosDrives[x].rootdir, temp);
+	strcpy(DosDrives[x].cwd, "/windows/");
+	strcpy(DosDrives[x].label, "DRIVE-");
+	strcat(DosDrives[x].label, drive);
+	DosDrives[x].disabled = 0;
+    }
+    DosDrives[25].rootdir = "/";
+    strcpy(DosDrives[25].cwd, "/");
+    strcpy(DosDrives[25].label, "UNIX-FS");
+    DosDrives[25].serialnumber = 0x12345678;
+    DosDrives[25].disabled = 0;
+    
+    /* Get the startup directory and try to map it to a DOS drive
+     * and directory.  (i.e., if we start in /dos/windows/word and
+     * drive C is defined as /dos, the starting wd for C will be
+     * /windows/word)  Also set the default drive to whatever drive
+     * corresponds to the directory we started in.
+     */
 
-        /* Get the startup directory and try to map it to a DOS drive
-         * and directory.  (i.e., if we start in /dos/windows/word and
-         * drive C is defined as /dos, the starting wd for C will be
-         * /windows/word)  Also set the default drive to whatever drive
-         * corresponds to the directory we started in.
-         */
+    for (x=0; x!=MAX_DOS_DRIVES; x++) 
+        if (DosDrives[x].rootdir != NULL) 
+	    strcpy( DosDrives[x].cwd, "/" );
 
-        for (x=0; x!=MAX_DOS_DRIVES; x++) 
-	  if (DosDrives[x].rootdir != NULL) 
-	    strcpy( DosDrives[x].cwd, "\\" );
-
-        getcwd(temp, 254);
-        strcat(temp, "/");      /* For DOS_GetDosFileName */
-        strcpy(temp, DOS_GetDosFileName(temp));
-        if(temp[0] != 'Z')
-        {
-            ToUnix(&temp[2]);
-            strcpy(DosDrives[temp[0] - 'A'].cwd, &temp[2]);
-            DOS_SetDefaultDrive(temp[0] - 'A');
-        }
-        else
-        {
-	    DOS_SetDefaultDrive(2);
-        }
-
-	for (x=0; x!=MAX_DOS_DRIVES; x++) {
-		if (DosDrives[x].rootdir != NULL) {
-            dprintf_dosfs(stddeb, "DOSFS: %c: => %-40s %s %s %X %d\n",
-			'A'+x,
-			DosDrives[x].rootdir,
-			DosDrives[x].cwd,
-			DosDrives[x].label,
-			DosDrives[x].serialnumber,
-			DosDrives[x].disabled
-			);	
-		}
+    getcwd(temp, 254);
+    strcat(temp, "/");      /* For DOS_GetDosFileName */
+    strcpy(temp, DOS_GetDosFileName(temp));
+    if(temp[0] != 'Z')
+    {
+	ToUnix(temp + 2);
+	strcpy(DosDrives[temp[0] - 'A'].cwd, &temp[2]);
+	DOS_SetDefaultDrive(temp[0] - 'A');
+    }
+    else
+    {
+	DOS_SetDefaultDrive(2);
+    }
+    
+    for (x=0; x!=MAX_DOS_DRIVES; x++) {
+	if (DosDrives[x].rootdir != NULL) {
+	    dprintf_dosfs(stddeb, "DOSFS: %c: => %-40s %s %s %X %d\n",
+			  'A'+x,
+			  DosDrives[x].rootdir,
+			  DosDrives[x].cwd,
+			  DosDrives[x].label,
+			  DosDrives[x].serialnumber,
+			  DosDrives[x].disabled);	
 	}
-
-	for (x=0; x!=max_open_dirs ; x++)
-		DosDirs[x].inuse = 0;
+    }
+    
+    for (x=0; x!=max_open_dirs ; x++)
+        DosDirs[x].inuse = 0;
 
     dprintf_dosfs(stddeb,"wine.ini = %s\n",WINE_INI);
     dprintf_dosfs(stddeb,"win.ini = %s\n",WIN_INI);
@@ -234,11 +243,11 @@
 
 WORD DOS_GetEquipment(void)
 {
-	WORD equipment;
-	int diskdrives = 0;
-	int parallelports = 0;
-	int serialports = 0;
-	int x;
+    WORD equipment;
+    int diskdrives = 0;
+    int parallelports = 0;
+    int serialports = 0;
+    int x;
 
 /* borrowed from Ralph Brown's interrupt lists 
 
@@ -266,219 +275,102 @@
 		bit  2			(always set)
 */
 
-	if (DosDrives[0].rootdir != NULL)
-		diskdrives++;
-	if (DosDrives[1].rootdir != NULL)
-		diskdrives++;
-	if (diskdrives)
-		diskdrives--;
+    if (DosDrives[0].rootdir != NULL)
+        diskdrives++;
+    if (DosDrives[1].rootdir != NULL)
+        diskdrives++;
+    if (diskdrives)
+        diskdrives--;
 	
-	for (x=0; x!=MAX_PORTS; x++) {
-		if (COM[x].devicename)
-			serialports++;
-		if (LPT[x].devicename)
-			parallelports++;
-	}
-	if (serialports > 7)		/* 3 bits -- maximum value = 7 */
-		serialports=7;
-	if (parallelports > 3)		/* 2 bits -- maximum value = 3 */
-		parallelports=3;
-
-	equipment = (diskdrives << 6) | (serialports << 9) | 
-		    (parallelports << 14) | 0x02;
+    for (x=0; x!=MAX_PORTS; x++) {
+	if (COM[x].devicename)
+	    serialports++;
+	if (LPT[x].devicename)
+	    parallelports++;
+    }
+    if (serialports > 7)		/* 3 bits -- maximum value = 7 */
+        serialports=7;
+    if (parallelports > 3)		/* 2 bits -- maximum value = 3 */
+        parallelports=3;
+    
+    equipment = (diskdrives << 6) | (serialports << 9) | 
+                (parallelports << 14) | 0x02;
 
     dprintf_dosfs(stddeb, "DOS_GetEquipment : diskdrives = %d serialports = %d "
-			"parallelports = %d\n"
-			"DOS_GetEquipment : equipment = %d\n",
-			diskdrives, serialports, parallelports, equipment);
-
-	return (equipment);
+		  "parallelports = %d\n"
+		  "DOS_GetEquipment : equipment = %d\n",
+		  diskdrives, serialports, parallelports, equipment);
+    
+    return equipment;
 }
 
 int DOS_ValidDrive(int drive)
 {
-        int valid = 1;
+    dprintf_dosfs(stddeb,"ValidDrive %c (%d)\n",'A'+drive,drive);
 
-        dprintf_dosfs(stddeb,"ValidDrive %c (%d) -- ",'A'+drive,drive);
+    if (drive < 0 || drive >= MAX_DOS_DRIVES) return 0;
+    if (DosDrives[drive].rootdir == NULL) return 0;
+    if (DosDrives[drive].disabled) return 0;
 
-	if (drive < 0 || drive >= MAX_DOS_DRIVES)
-		valid = 0;
-	if (DosDrives[drive].rootdir == NULL)
-		valid = 0;
-	if (DosDrives[drive].disabled)
-		valid = 0;
-
-        dprintf_dosfs(stddeb, "%s\n", valid ? "Valid" : "Invalid");
-	return valid;
+    dprintf_dosfs(stddeb, " -- valid\n");
+    return 1;
 }
 
-
-int DOS_ValidDirectory(char *name)
+static void DOS_GetCurrDir_Unix(char *buffer, int drive)
 {
-	char *dirname;
-	struct stat s;
-	dprintf_dosfs(stddeb, "DOS_ValidDirectory: '%s'\n", name);
-	if ((dirname = DOS_GetUnixFileName(name)) == NULL)
-		return 0;
-	if (stat(dirname,&s))
-		return 0;
-	if (!S_ISDIR(s.st_mode))
-		return 0;
-	dprintf_dosfs(stddeb, "==> OK\n");
-	return 1;
-}
-
-
-
-/* Simplify the path in "name" by removing  "//"'s and
-   ".."'s in names like "/usr/bin/../lib/test" */
-void DOS_SimplifyPath(char *name)
-{
-  char *l,*p;
-  BOOL changed;
-
-  dprintf_dosfs(stddeb,"SimplifyPath: Before %s\n",name);
-  do {
-    changed = FALSE;
-    while ((l = strstr(name,"//"))) {
-      strcpy(l,l+1); changed = TRUE;
-    } 
-    while ((l = strstr(name,"/../"))) {
-      *l = 0;
-      p = strrchr(name,'/');
-      if (p == NULL) p = name;
-      strcpy(p,l+3);
-      changed = TRUE;
+    TDB *pTask = (TDB *)GlobalLock(GetCurrentTask());
+    
+    if (pTask != NULL && (pTask->curdrive & ~0x80) == drive) {
+	strcpy(buffer, pTask->curdir);
+	ToUnix(buffer);
+    } else {
+	strcpy(buffer, DosDrives[drive].cwd);
     }
-  } while (changed);
-  dprintf_dosfs(stddeb,"SimplifyPath: After %s\n",name);
 }
 
-
-int DOS_GetDefaultDrive(void)
-{
-    dprintf_dosfs(stddeb,"GetDefaultDrive (%c)\n",'A'+CurrentDrive);
-	return( CurrentDrive);
-}
-
-void DOS_SetDefaultDrive(int drive)
-{
-    dprintf_dosfs(stddeb,"SetDefaultDrive to %c:\n",'A'+drive);
-	if (DOS_ValidDrive(drive))
-		CurrentDrive = drive;
-}
-
-int DOS_DisableDrive(int drive)
-{
-	if (drive >= MAX_DOS_DRIVES)
-		return 0;
-	if (DosDrives[drive].rootdir == NULL)
-		return 0;
-
-	DosDrives[drive].disabled = 1;
-	return 1;
-}
-
-int DOS_EnableDrive(int drive)
-{
-	if (drive >= MAX_DOS_DRIVES)
-		return 0;
-	if (DosDrives[drive].rootdir == NULL)
-		return 0;
-
-	DosDrives[drive].disabled = 0;
-	return 1;
-}
-
-static void GetUnixDirName(char *rootdir, char *name)
-{
-	int filename = 1;
-	char *nameptr, *cwdptr;
-	
-	cwdptr = rootdir + strlen(rootdir);
-	nameptr = name;
-
-	dprintf_dosfs(stddeb,"GetUnixDirName: %s <=> %s => ",rootdir, name);
-
-	while (*nameptr) {
-		if (*nameptr == '.' & !filename) {
-			nameptr++;
-			if (*nameptr == '\0') {
-				cwdptr--;
-				break;
-			}
-			if (*nameptr == '.') {
-				cwdptr--;
-				while (cwdptr != rootdir) {
-					cwdptr--;
-					if (*cwdptr == '/') {
-						*(cwdptr+1) = '\0';
-						goto next;
-					}
-				}
-				goto next;
-			}
-			if (*nameptr == '\\' || *nameptr == '/') {
-			next:	nameptr++;		
-				filename = 0;
-				continue;
-			}
-		}
-		if (*nameptr == '\\' || *nameptr == '/') {
-			filename = 0;
-			if (nameptr == name)
-				cwdptr = rootdir;
-			*cwdptr++='/';		
-			nameptr++;
-			continue;
-		}
-		filename = 1;
-		*cwdptr++ = *nameptr++;
-	}
-	*cwdptr = '\0';
-
-	ToUnix(rootdir);
-
-	dprintf_dosfs(stddeb,"%s\n", rootdir);
-
-}
-
-char *DOS_GetUnixFileName(char *dosfilename)
+char *DOS_GetCurrentDir(int drive)
 { 
-	/*   a:\windows\system.ini  =>  /dos/windows/system.ini */
+    static char temp[256];
 
-        /* FIXME: should handle devices here (like LPT: or NUL:) */
+    if (!DOS_ValidDrive(drive)) return 0;
 
-	static char temp[256];
-	static char dostemp[256];
-	int drive;
+    DOS_GetCurrDir_Unix(temp, drive);
+    DOS_SimplifyPath( temp );
+    ToDos(temp);
+    ChopOffSlash(temp);
 
-	if (dosfilename[0] && (dosfilename[1] == ':'))
-	{
-		drive = (islower(*dosfilename) ? toupper(*dosfilename) : *dosfilename) - 'A';
-		
-		if (!DOS_ValidDrive(drive))		
-			return NULL;
-		else
-			dosfilename+=2;
-	} else
-		drive = CurrentDrive;
+    dprintf_dosfs(stddeb,"DOS_GetCWD: %c:%s\n", 'A'+drive, temp);
+    return temp + 1;
+}
 
-	/* Consider dosfilename const */
-	strncpy( dostemp, dosfilename, 255 );
-        dostemp[255] = '\0';
+char *DOS_GetUnixFileName(const char *dosfilename)
+{ 
+    /*   a:\windows\system.ini  =>  /dos/windows/system.ini */
+    
+    /* FIXME: should handle devices here (like LPT: or NUL:) */
+    
+    static char dostemp[256], temp[256];
+    int drive = DOS_GetDefaultDrive();
+    
+    if (dosfilename[0] && dosfilename[1] == ':')
+    {
+	drive = toupper(*dosfilename) - 'A';
+	dosfilename += 2;
+    }    
+    if (!DOS_ValidDrive(drive)) return NULL;
 
-        /* Expand the filename to it's full path if it doesn't
-         * start from the root.
-         */
-        DOS_ExpandToFullPath(dostemp, drive);
-
-	strcpy(temp, DosDrives[drive].rootdir);
-	strcat(temp, DosDrives[drive].cwd);
-	GetUnixDirName(temp + strlen(DosDrives[drive].rootdir), dostemp);
-
-	dprintf_dosfs(stddeb,"GetUnixFileName: %s => %s\n", dosfilename, temp);
-	return(temp);
+    strncpy( dostemp, dosfilename, 255 );
+    dostemp[255] = 0;
+    ToUnix(dostemp);
+    strcpy(temp, DosDrives[drive].rootdir);
+    if (dostemp[0] != '/') {
+	DOS_GetCurrDir_Unix(temp+strlen(temp), drive);
+    }
+    strcat(temp, dostemp);
+    DOS_SimplifyPath(temp);
+	
+    dprintf_dosfs(stddeb,"GetUnixFileName: %s => %s\n", dosfilename, temp);
+    return temp;
 }
 
 /* Note: This function works on directories as well as long as
@@ -486,136 +378,148 @@
  */
 char *DOS_GetDosFileName(char *unixfilename)
 { 
-	int i;
-	static char temp[256], rootdir[256];
-	/*   /dos/windows/system.ini => c:\windows\system.ini */
-	
-        /* Expand it if it's a relative name.
-         */
-        DOS_ExpandToFullUnixPath(unixfilename);
-
-	for (i = 0 ; i != MAX_DOS_DRIVES; i++) {
-		if (DosDrives[i].rootdir != NULL) {
- 			strcpy(rootdir, DosDrives[i].rootdir);
- 			strcat(rootdir, "/");
- 			if (strncmp(rootdir, unixfilename, strlen(rootdir)) == 0) {
- 				sprintf(temp, "%c:\\%s", 'A' + i, unixfilename + strlen(rootdir));
-				ToDos(temp);
-				return temp;
-			}	
-		}
+    int i;
+    static char temp[256], temp2[256];
+    /*   /dos/windows/system.ini => c:\windows\system.ini */
+    
+    dprintf_dosfs(stddeb,"DOS_GetDosFileName: %s\n", unixfilename);
+    if (unixfilename[0] == '/') {
+	strncpy(temp, unixfilename, 255);
+	temp[255] = 0;
+    } else {
+	/* Expand it if it's a relative name. */
+	getcwd(temp, 255);
+	if(strncmp(unixfilename, "./", 2) != 0) {
+	    strcat(temp, unixfilename + 1);
+	} else {	    
+	    strcat(temp, "/");
+	    strcat(temp, unixfilename);
 	}
-	sprintf(temp, "Z:%s", unixfilename);
-	ToDos(temp);
-	return(temp);
+    }
+    for (i = 0 ; i < MAX_DOS_DRIVES; i++) {
+	if (DosDrives[i].rootdir != NULL) {
+	    int len = strlen(DosDrives[i].rootdir);
+	    dprintf_dosfs(stddeb, "  check %c:%s\n", i+'A', DosDrives[i].rootdir);
+	    if (strncmp(DosDrives[i].rootdir, temp, len) == 0 && temp[len] == '/')
+	    {
+		sprintf(temp2, "%c:%s", 'A' + i, temp+len);
+		ToDos(temp2+2);
+		return temp2;
+	    }	
+	}
+    }
+    sprintf(temp, "Z:%s", unixfilename);
+    ToDos(temp+2);
+    return temp;
 }
 
-char *DOS_GetCurrentDir(int drive)
-{ 
-	static char temp[256];
+int DOS_ValidDirectory(int drive, char *name)
+{
+    char temp[256];
+    struct stat s;
+    
+    strcpy(temp, DosDrives[drive].rootdir);
+    strcat(temp, name);
+    if (stat(temp, &s)) return 0;
+    if (!S_ISDIR(s.st_mode)) return 0;
+    dprintf_dosfs(stddeb, "==> OK\n");
+    return 1;
+}
 
-	if (!DOS_ValidDrive(drive)) 
-		return 0;
-	
-	strcpy(temp, DosDrives[drive].cwd);
-	DOS_SimplifyPath( temp );
-	ToDos(temp);
-	ChopOffSlash(temp);
+int DOS_GetDefaultDrive(void)
+{
+    TDB *pTask = (TDB *)GlobalLock(GetCurrentTask());
+    int drive = pTask == NULL ? CurrentDrive : pTask->curdrive & ~0x80;
+    
+    dprintf_dosfs(stddeb,"GetDefaultDrive (%c)\n",'A'+drive);
+    return drive;
+}
 
-    	dprintf_dosfs(stddeb,"DOS_GetCWD: %c:%s\n", 'A'+drive, temp);
-	return (temp + 1);
+void DOS_SetDefaultDrive(int drive)
+{
+    TDB *pTask = (TDB *)GlobalLock(GetCurrentTask());
+    
+    dprintf_dosfs(stddeb,"SetDefaultDrive to %c:\n",'A'+drive);
+    if (DOS_ValidDrive(drive) && drive != DOS_GetDefaultDrive()) {
+	if (pTask == NULL) CurrentDrive = drive;
+	else {
+	    char temp[256];
+	    pTask->curdrive = drive | 0x80;
+	    strcpy(temp, DosDrives[drive].rootdir);
+	    strcat(temp, DosDrives[drive].cwd);
+	    strcpy(temp, DOS_GetDosFileName(temp));
+	    dprintf_dosfs(stddeb, "  curdir = %s\n", temp);
+	    if (strlen(temp)-2 < sizeof(pTask->curdir)) strcpy(pTask->curdir, temp+2);
+	    else fprintf(stderr, "dosfs: curdir too long\n");
+	}
+    }
+}
+
+int DOS_DisableDrive(int drive)
+{
+    if (drive >= MAX_DOS_DRIVES) return 0;
+    if (DosDrives[drive].rootdir == NULL) return 0;
+
+    DosDrives[drive].disabled = 1;
+    return 1;
+}
+
+int DOS_EnableDrive(int drive)
+{
+    if (drive >= MAX_DOS_DRIVES) return 0;
+    if (DosDrives[drive].rootdir == NULL) return 0;
+
+    DosDrives[drive].disabled = 0;
+    return 1;
 }
 
 int DOS_ChangeDir(int drive, char *dirname)
 {
-	char temp[256],old[256];
+    TDB *pTask = (TDB *)GlobalLock(GetCurrentTask());
+    char temp[256];
+    
+    if (!DOS_ValidDrive(drive)) return 0;
 
-	if (!DOS_ValidDrive(drive)) 
-		return 0;
-
+    if (dirname[0] == '\\') {
 	strcpy(temp, dirname);
-	ToUnix(temp);
-	strcpy(old, DosDrives[drive].cwd);
-	
-	GetUnixDirName(DosDrives[drive].cwd, temp);
-	strcat(DosDrives[drive].cwd,"/");
+    } else {
+	DOS_GetCurrDir_Unix(temp, drive);
+	strcat(temp, dirname);
+    }
+    ToUnix(temp);
+    strcat(temp, "/");
+    DOS_SimplifyPath(temp);
+    dprintf_dosfs(stddeb,"DOS_SetCWD: %c: %s ==> %s\n", 'A'+drive, dirname, temp);
 
-	dprintf_dosfs(stddeb,"DOS_SetCWD: %c: %s\n",'A'+drive,
-                      DosDrives[drive].cwd);
-
-	if (!DOS_ValidDirectory(DosDrives[drive].cwd))
-	{
-		strcpy(DosDrives[drive].cwd, old);
-		return 0;
-	}
-        DOS_SimplifyPath(DosDrives[drive].cwd);
-	return 1;
+    if (!DOS_ValidDirectory(drive, temp)) return 0;
+    strcpy(DosDrives[drive].cwd, temp);
+    if (pTask != NULL && DOS_GetDefaultDrive() == drive) {
+	strcpy(temp, DosDrives[drive].rootdir);
+	strcat(temp, DosDrives[drive].cwd);
+	strcpy(temp, DOS_GetDosFileName(temp));
+	dprintf_dosfs(stddeb, "  curdir = %s\n", temp);
+	if (strlen(temp)-2 < sizeof(pTask->curdir)) strcpy(pTask->curdir, temp+2);
+	else fprintf(stderr, "dosfs: curdir too long\n");
+    }
+    return 1;
 }
 
 int DOS_MakeDir(int drive, char *dirname)
 {
-	char temp[256];
-	
-	if (!DOS_ValidDrive(drive))
-		return 0;	
+    char temp[256], currdir[256];
+    
+    if (!DOS_ValidDrive(drive)) return 0;	
 
-	strcpy(temp, DosDrives[drive].cwd);
-	GetUnixDirName(temp, dirname);
-	strcat(DosDrives[drive].cwd,"/");
-
-	ToUnix(temp + strlen(DosDrives[drive].cwd));
-	mkdir(temp,0);	
-
-    	dprintf_dosfs(stddeb,
-		"DOS_MakeDir: %c:\%s => %s",'A'+drive, dirname, temp);
-	return 1;
-}
-
-/* DOS_ExpandToFullPath takes a dos-style filename and converts it
- * into a full path based on the current working directory.
- * (e.g., "foo.bar" => "d:\\moo\\foo.bar")
- */
-void DOS_ExpandToFullPath(char *filename, int drive)
-{
-        char temp[256];
-
-        dprintf_dosfs(stddeb, "DOS_ExpandToFullPath: Original = %s\n", filename);
-
-        /* If the filename starts with '/' or '\',
-         * don't bother -- we're already at the root.
-         */
-        if(filename[0] == '/' || filename[0] == '\\')
-            return;
-
-        strcpy(temp, DosDrives[drive].cwd);
-        strcat(temp, filename);
-        strcpy(filename, temp);
-
-        dprintf_dosfs(stddeb, "                      Expanded = %s\n", temp); 
-}
-
-/* DOS_ExpandToFullUnixPath takes a unix filename and converts it
- * into a full path based on the current working directory.  Thus,
- * it's probably not a good idea to get a relative name, change the
- * working directory, and then convert it...
- */
-void DOS_ExpandToFullUnixPath(char *filename)
-{
-        char temp[256];
-
-        if(filename[0] == '/')
-            return;
-
-        getcwd(temp, 255);
-        if(!strncmp(filename, "./", 2))
-                strcat(temp, filename + 1);
-        else
-        {
-                strcat(temp, "/");
-                strcat(temp, filename);
-        }
-        dprintf_dosfs(stddeb, "DOS_ExpandToFullUnixPath: %s => %s\n", filename, temp);
-        strcpy(filename, temp);
+    strcpy(temp, DosDrives[drive].rootdir);
+    DOS_GetCurrDir_Unix(currdir, drive);
+    strcat(temp, currdir);
+    strcat(temp, dirname);
+    ToUnix(temp);
+    DOS_SimplifyPath(temp);
+    mkdir(temp,0);	
+    
+    dprintf_dosfs(stddeb, "DOS_MakeDir: %c:\%s => %s",'A'+drive, dirname, temp);
+    return 1;
 }
 
 int DOS_GetSerialNumber(int drive, unsigned long *serialnumber)
@@ -641,7 +545,7 @@
 	if (!DOS_ValidDrive(drive)) 
 		return NULL;
 
-	return (DosDrives[drive].label);
+	return DosDrives[drive].label;
 }
 
 int DOS_SetVolumeLabel(int drive, char *label)
@@ -743,6 +647,7 @@
 		if (S_ISREG(filestat.st_mode)) {
 		    closedir(d);
 		    free(rootname);
+		    DOS_SimplifyPath(buffer);
 		    return buffer;
 		} 
 	    }
@@ -769,15 +674,15 @@
 	if ((fd = open(name, O_RDONLY)) != -1) {
 		close(fd);
 		filename = name;
-		return(filename);
+		return filename;
 	}
 	if ((fd = open(WINE_INI_GLOBAL, O_RDONLY)) != -1) {
 		close(fd);
 		filename = WINE_INI_GLOBAL;
-		return(filename);
+		return filename;
 	}
-	fprintf(stderr,"wine: can't open configuration file %s or %s !\n", 
-				WINE_INI_GLOBAL, WINE_INI_USER);
+	fprintf(stderr,"wine: can't open configuration file %s or %s !\n",
+		WINE_INI_GLOBAL, WINE_INI_USER);
 	exit(1);
 }
 
@@ -866,59 +771,48 @@
 
 struct dosdirent *DOS_opendir(char *dosdirname)
 {
-	int x,y;
-	char *unixdirname;
-	char temp[256];
-	DIR  *ds;
-	
-	if ((unixdirname = DOS_GetUnixFileName(dosdirname)) == NULL)
-		return NULL;
+    int x, len;
+    char *unixdirname;
+    char dirname[256];
+    DIR  *ds;
+    
+    if ((unixdirname = DOS_GetUnixFileName(dosdirname)) == NULL) return NULL;
+    
+    len = strrchr(unixdirname, '/') - unixdirname + 1;
+    strncpy(dirname, unixdirname, len);
+    dirname[len] = 0;
+    unixdirname = strrchr(unixdirname, '/') + 1;
 
-	strcpy(temp, unixdirname);
-	y = strlen(temp);
-	while (y--)
-	{
-		if (temp[y] == '/') 
-		{
-			temp[y++] = '\0';
-		        unixdirname += y;
-			break;
-		}
-	}
-
-        for (x=0; x <= max_open_dirs; x++) {
-	  if (x == max_open_dirs) {
+    for (x=0; x <= max_open_dirs; x++) {
+	if (x == max_open_dirs) {
 	    if (DosDirs) {
-	      DosDirs=(struct dosdirent*)realloc(DosDirs,(++max_open_dirs)*sizeof(DosDirs[0]));
+		DosDirs=(struct dosdirent*)realloc(DosDirs,(++max_open_dirs)*sizeof(DosDirs[0]));
 	    } else {
-	      DosDirs=(struct dosdirent*)malloc(sizeof(DosDirs[0]));
-	      max_open_dirs=1;
+		DosDirs=(struct dosdirent*)malloc(sizeof(DosDirs[0]));
+		max_open_dirs=1;
 	    }
 	    break; /* this one is definitely not in use */
-	  }
-	  if (!DosDirs[x].inuse) break;
-	  if (strcmp(DosDirs[x].unixpath,temp) == 0) break;
 	}
-        
-        strncpy(DosDirs[x].filemask, unixdirname, 12);
-        DosDirs[x].filemask[12] = 0;
-        ToDos(DosDirs[x].filemask);
-    	dprintf_dosfs(stddeb,"DOS_opendir: %s / %s\n", unixdirname, temp);
+	if (!DosDirs[x].inuse) break;
+	if (strcmp(DosDirs[x].unixpath, dirname) == 0) break;
+    }
+    
+    strncpy(DosDirs[x].filemask, unixdirname, 12);
+    DosDirs[x].filemask[12] = 0;
+    dprintf_dosfs(stddeb,"DOS_opendir: %s / %s\n", unixdirname, dirname);
 
-	DosDirs[x].inuse = 1;
-	strcpy(DosDirs[x].unixpath, temp);
-        DosDirs[x].entnum = 0;
+    DosDirs[x].inuse = 1;
+    strcpy(DosDirs[x].unixpath, dirname);
+    DosDirs[x].entnum = 0;
 
-	if ((ds = opendir(temp)) == NULL)
-		return NULL;
-	if (-1==(DosDirs[x].telldirnum=telldir(ds))) {
-		closedir(ds);
-		return NULL;
-	}
-	if (-1==closedir(ds))
-		return NULL;
+    if ((ds = opendir(dirname)) == NULL) return NULL;
+    if (-1==(DosDirs[x].telldirnum=telldir(ds))) {
+	closedir(ds);
+	return NULL;
+    }
+    if (-1==closedir(ds)) return NULL;
 
-	return &DosDirs[x];
+    return &DosDirs[x];
 }
 
 
@@ -931,22 +825,36 @@
 
 	if (!de->inuse)
 		return NULL;
-	if (-1==(ds=opendir(de->unixpath)))
-		return NULL;
+	if (!(ds=opendir(de->unixpath))) return NULL;
 	seekdir(ds,de->telldirnum); /* returns no error value. strange */
-	do {
-		if ((d = readdir(ds)) == NULL)  {
-			de->telldirnum=telldir(ds);
-			closedir(ds);
-			return NULL;
+   
+        if (de->search_attribute & FA_LABEL)  {	
+	    int drive;
+	    de->search_attribute &= ~FA_LABEL; /* don't find it again */
+	    for(drive = 0; drive < MAX_DOS_DRIVES; drive++) {
+		if (DosDrives[drive].rootdir != NULL &&
+		    strcmp(DosDrives[drive].rootdir, de->unixpath) == 0)
+		{
+		    strcpy(de->filename, DOS_GetVolumeLabel(drive));
+		    de->attribute = FA_LABEL;
+		    return de;
 		}
+	    }
+	}
+    
+	do {
+	    if ((d = readdir(ds)) == NULL)  {
+		de->telldirnum=telldir(ds);
+		closedir(ds);
+		return NULL;
+	    }
 
-                de->entnum++;   /* Increment the directory entry number */
-		strcpy(de->filename, d->d_name);
-		if (d->d_reclen > 12)
-			de->filename[12] = '\0';
-		
-		ToDos(de->filename);
+	    de->entnum++;   /* Increment the directory entry number */
+	    strcpy(de->filename, d->d_name);
+	    if (d->d_reclen > 12)
+	    de->filename[12] = '\0';
+
+	    ToDos(de->filename);
 	} while ( !match(de->filename, de->filemask) );
 
 	strcpy(temp,de->unixpath);
diff --git a/misc/exec.c b/misc/exec.c
index 635f4bd..ab5bc0e 100644
--- a/misc/exec.c
+++ b/misc/exec.c
@@ -8,7 +8,6 @@
 #include <string.h>
 #include <unistd.h>
 #include "neexe.h"
-#include "prototypes.h"
 #include "dlls.h"
 #include "windows.h"
 #include "callback.h"
diff --git a/misc/file.c b/misc/file.c
index ef45ec5..3581ce3 100644
--- a/misc/file.c
+++ b/misc/file.c
@@ -108,8 +108,8 @@
 {
     dprintf_file(stddeb, "_lclose: handle %d\n", hFile);
     
-    if (hFile == 1 || hFile == 2) {
-	fprintf( stderr, "Program attempted to close stdout or stderr!\n" );
+    if (hFile == 0 || hFile == 1 || hFile == 2) {
+	fprintf( stderr, "Program attempted to close stdin, stdout or stderr!\n" );
 	return 0;
     }
     if (close (hFile))
@@ -154,7 +154,7 @@
             ofs->nErrCode = ExtendedError;
             return -1;
         }
-        handle = open (unixfilename, (wStyle & 0x0003) | O_CREAT, 0x666);
+        handle = open (unixfilename, (wStyle & 0x0003) | O_CREAT, 0666);
         if (handle == -1)
         {
             errno_to_doserr();
@@ -325,7 +325,7 @@
 		lpszFilename, fnAttribute);
 	if ((UnixFileName = DOS_GetUnixFileName(lpszFilename)) == NULL)
   		return HFILE_ERROR;
-	handle =  open (UnixFileName, O_CREAT | O_TRUNC | O_WRONLY, 426);
+	handle =  open (UnixFileName, O_CREAT | O_TRUNC | O_WRONLY, 0666);
 
 	if (handle == -1)
 		return HFILE_ERROR;
@@ -372,8 +372,7 @@
 	
     	dprintf_file(stddeb,"GetWindowsDirectory (%s)\n",lpszSysPath);
 
-	ChopOffSlash(lpszSysPath);
-	return(strlen(lpszSysPath));
+	return strlen(lpszSysPath);
 }
 /***************************************************************************
  GetSystemDirectory
@@ -387,8 +386,7 @@
 
     	dprintf_file(stddeb,"GetSystemDirectory (%s)\n",lpszSysPath);
 
-	ChopOffSlash(lpszSysPath);
-	return(strlen(lpszSysPath));
+	return strlen(lpszSysPath);
 }
 /***************************************************************************
  GetTempFileName
diff --git a/misc/kernel32.c b/misc/kernel32.c
index 0be2b09..df6a5ba 100644
--- a/misc/kernel32.c
+++ b/misc/kernel32.c
@@ -9,6 +9,7 @@
 
 #include "windows.h"
 #include "winerror.h"
+#include <unistd.h>
 
 int WIN32_LastError;
 
diff --git a/misc/main.c b/misc/main.c
index f5f8544..3528df5 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -2,9 +2,8 @@
  * Main function.
  *
  * Copyright 1994 Alexandre Julliard
- *
-static char Copyright[] = "Copyright  Alexandre Julliard, 1994";
-*/
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -24,7 +23,6 @@
 #include "winsock.h"
 #include "options.h"
 #include "desktop.h"
-#include "prototypes.h"
 #include "dlls.h"
 #define DEBUG_DEFINE_VARIABLES
 #include "stddebug.h"
@@ -63,7 +61,6 @@
 
 struct options Options =
 {  /* default options */
-    NULL,           /* spyFilename */
     NULL,           /* desktopGeometry */
     NULL,           /* programName */
     FALSE,          /* usePrivateMap */
@@ -86,7 +83,6 @@
     { "-name",          ".name",            XrmoptionSepArg, (caddr_t)NULL },
     { "-privatemap",    ".privatemap",      XrmoptionNoArg,  (caddr_t)"on" },
     { "-synchronous",   ".synchronous",     XrmoptionNoArg,  (caddr_t)"on" },
-    { "-spy",           ".spy",             XrmoptionSepArg, (caddr_t)NULL },
     { "-debug",         ".debug",           XrmoptionNoArg,  (caddr_t)"on" },
     { "-debugmsg",      ".debugmsg",        XrmoptionSepArg, (caddr_t)NULL },
     { "-dll",           ".dll",             XrmoptionSepArg, (caddr_t)NULL },
@@ -109,11 +105,11 @@
   "    -privatemap     Use a private color map\n" \
   "    -synchronous    Turn on synchronous display mode\n" \
   "    -backingstore   Turn on backing store\n" \
-  "    -spy file       Turn on message spying to the specified file\n" \
+  "    -spy file       Obsolete. Use -debugmsg +spy for Spy messages\n" \
   "    -debugmsg name  Turn debugging-messages on or off\n" \
   "    -dll name       Enable or disable built-in DLLs\n" \
   "    -allowreadonly  Read only files may be opened in write mode\n" \
-  "    -enhanced       Start wine in enhanced mode\n"
+  "    -enhanced       Start wine in enhanced mode (like 'win /3') \n"
 
 
 
@@ -313,8 +309,6 @@
         Options.allowReadOnly = TRUE;
     if (MAIN_GetResource( db, ".enhanced", &value ))
         Options.enhanced = TRUE;
-    if (MAIN_GetResource( db, ".spy", &value))
-	Options.spyFilename = value.addr;
     if (MAIN_GetResource( db, ".depth", &value))
 	screenDepth = atoi( value.addr );
     if (MAIN_GetResource( db, ".desktop", &value))
@@ -463,14 +457,20 @@
     	KBBellPitch | KBBellDuration | KBAutoRepeatMode, &keyboard_value);
 }
 
+
+#ifdef MALLOC_DEBUGGING
 static void malloc_error()
 {
        fprintf(stderr,"malloc is not feeling well. Good bye\n");
        exit(1);
 }
+#endif  /* MALLOC_DEBUGGING */
+
 
 static void called_at_exit(void)
 {
+    extern void sync_profiles(void);
+
     sync_profiles();
     MAIN_RestoreSetup();
     WSACleanup();
@@ -485,8 +485,10 @@
     int depth_count, i;
     int *depth_list;
 
-	setbuf(stdout,NULL);
-	setbuf(stderr,NULL);
+    extern int _WinMain(int argc, char **argv);
+
+    setbuf(stdout,NULL);
+    setbuf(stderr,NULL);
 
     setlocale(LC_CTYPE,"");
 
@@ -565,9 +567,9 @@
 LONG GetWinFlags(void)
 {
   if (Options.enhanced)
-    return (WF_STANDARD | WF_ENHANCED | WF_CPU386 | WF_PMODE | WF_80x87);
+    return (WF_ENHANCED | WF_CPU386 | WF_PMODE | WF_80x87 | WF_PAGING);
   else
-    return (WF_STANDARD | WF_CPU286 | WF_PMODE | WF_80x87);
+    return (WF_STANDARD | WF_CPU386 | WF_PMODE | WF_80x87);
 }
 
 /***********************************************************************
diff --git a/misc/profile.c b/misc/profile.c
index 71e5373..0c3df91 100644
--- a/misc/profile.c
+++ b/misc/profile.c
@@ -96,7 +96,8 @@
     int state;
     TSecHeader *SecHeader = 0;
     char CharBuffer [STRSIZE];
-    char *next, *file;
+    char *next = '\0';
+    char *file;
     char c;
     char path[MAX_PATH+1];
 
@@ -287,6 +288,7 @@
 	    return (Size - 2 - left);
 	}
 	for (key = section->Keys; key; key = key->link){
+	    int slen;
 	    if (strcasecmp (key->KeyName, KeyName))
 		continue;
 	    if (set){
@@ -295,19 +297,21 @@
 		Current->changed=TRUE;
 		return 1;
 	    }
-	    ReturnedString [Size-1] = 0;
-	    strncpy (ReturnedString, key->Value, Size-1);
+	    slen = min(strlen(key->Value), Size - 1);
+	    ReturnedString[slen] = 0;
+	    strncpy (ReturnedString, key->Value, slen);
 	    dprintf_profile(stddeb,"GetSetProfile // Return ``%s''\n", ReturnedString);
 	    return 1; 
 	}
 	/* If Getting the information, then don't write the information
 	   to the INI file, need to run a couple of tests with windog */
 	/* No key found */
-	if (set)
+	if (set) {
 	    new_key (section, KeyName, Default);
-        else {
-            ReturnedString [Size-1] = 0;
-            strncpy (ReturnedString, Default, Size-1);
+        } else {
+	    int slen = min(strlen(Default), Size - 1);
+            ReturnedString[slen] = 0;
+            strncpy(ReturnedString, Default, slen);
 	    dprintf_profile(stddeb,"GetSetProfile // Key not found\n");
 	}
 	return 1;
@@ -322,8 +326,9 @@
 	Current->Section = section;
 	Current->changed = TRUE;
     } else {
-	ReturnedString [Size-1] = 0;
-	strncpy (ReturnedString, Default, Size-1);
+	int slen = min(strlen(Default), Size - 1);
+	ReturnedString[slen] = 0;
+	strncpy(ReturnedString, Default, slen);
 	dprintf_profile(stddeb,"GetSetProfile // Section not found\n");
     }
     return 1;
diff --git a/misc/spy.c b/misc/spy.c
index 7c82b10..835f8c6 100644
--- a/misc/spy.c
+++ b/misc/spy.c
@@ -8,14 +8,13 @@
 #include <X11/Xlib.h>
 #include <X11/Xresource.h>
 #include <string.h>
-#include "wineopts.h"
 #include "windows.h"
 #include "wine.h"
 #include "options.h"
+#include "stddebug.h"
+#include "debug.h"
 
-#ifndef NOSPY
-
-#define SPY_MAX_MSGNUM		0x0232
+#define SPY_MAX_MSGNUM		0x03e8
 
 const char *MessageTypeNames[SPY_MAX_MSGNUM + 1] =
 {
@@ -245,27 +244,115 @@
     "WM_MDIICONARRANGE",        /* 0x0228 */
     "WM_MDIGETACTIVE",          /* 0x0229 */
 
+    NULL, NULL, NULL, NULL, NULL, NULL,
+    /* 0x0230*/
     "WM_MDISETMENU",            /* 0x0230 */
     "WM_ENTERSIZEMOVE",		/* 0x0231 */
-    "WM_EXITSIZEMOVE"		/* 0x0232 */
+    "WM_EXITSIZEMOVE",		/* 0x0232 */
+    NULL, NULL, NULL, NULL, NULL, 
+    /* 0x0238*/
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    
+    /* 0x0240 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    /* 0x0250 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    
+    /* 0x0260 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    /* 0x0280 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    /* 0x02c0 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    /* 0x0300 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    /* 0x0340 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    /* 0x0380 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    /* 0x03c0 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    /* 0x03e0 */
+    "WM_DDE_INITIATE",  /* 0x3E0 */
+    "WM_DDE_TERMINATE",	/* 0x3E1 */
+    "WM_DDE_ADVISE",	/* 0x3E2 */
+    "WM_DDE_UNADVISE",	/* 0x3E3 */
+    "WM_DDE_ACK",	/* 0x3E4 */
+    "WM_DDE_DATA",	/* 0x3E5 */
+    "WM_DDE_REQUEST",	/* 0x3E6 */
+    "WM_DDE_POKE",	/* 0x3E7 */
+    "WM_DDE_EXECUTE"	/* 0x3E8 */
 };
 
 char SpyFilters[256+1];
 char SpyIncludes[256+1];
 
-#endif /* NOSPY */
-
 /**********************************************************************
  *					SpyMessage
  */
 void SpyMessage(HWND hwnd, WORD msg, WORD wParam, LONG lParam)
 {
-#ifndef NOSPY
     char msg_name[80];
     
-    if (SpyFp == NULL)
-	return;
-    
+	if(!debugging_spy)
+		return;
+
     if (msg > SPY_MAX_MSGNUM || MessageTypeNames[msg] == NULL)
 	sprintf(msg_name, "%04x", msg);
     else
@@ -277,10 +364,9 @@
 	strstr(SpyFilters, msg_name) == NULL)
     {
 	msg_name[strlen(msg_name) - 1] = '\0';
-	fprintf(SpyFp, "%04x  %20.20s  %04x  %04x  %08lx\n",
+	dprintf_spy(stddeb, "%04x  %20.20s  %04x  %04x  %08lx\n",
 		hwnd, msg_name, msg, wParam, lParam);
     }
-#endif
 }
 
 /**********************************************************************
@@ -288,30 +374,6 @@
  */
 void SpyInit(void)
 {
-#ifndef NOSPY
-    char filename[100];
-
-    if (SpyFp != NULL)
-	return;
-
-    if (Options.spyFilename == NULL)
-    {
-	GetPrivateProfileString("spy", "file", "", filename, sizeof(filename),
-				WINE_INI);
-    }
-    else
-	strncpy(filename, Options.spyFilename, 100);
-
-    if (strcasecmp(filename, "CON") == 0)
-	SpyFp = stdout;
-    else if (strlen(filename))
-	SpyFp = fopen(filename, "a");
-    else
-    {
-	SpyFp = NULL;
-	return;
-    }
-    
     GetPrivateProfileString("spy", "exclude", "", SpyFilters, 
 			    sizeof(SpyFilters)-1, WINE_INI);
     GetPrivateProfileString("spy", "include", "", SpyIncludes, 
@@ -323,5 +385,4 @@
     if (*SpyFilters != 0) {
       strcat(SpyFilters, ";");
     }
-#endif
 }
diff --git a/misc/user.c b/misc/user.c
index 86a09f5..98b7b1b 100644
--- a/misc/user.c
+++ b/misc/user.c
@@ -17,7 +17,6 @@
 #include "syscolor.h"
 #include "win.h"
 #include "windows.h"
-#include "prototypes.h"
 #include "user.h"
 #include "message.h"
 #include "toolhelp.h"
diff --git a/misc/winsocket.c b/misc/winsocket.c
index ee95375..2fdd5a6 100644
--- a/misc/winsocket.c
+++ b/misc/winsocket.c
@@ -20,6 +20,7 @@
 #include <netdb.h>
 #include <unistd.h>
 #include "winsock.h"
+#include "toolhelp.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -37,33 +38,36 @@
 	LONG	lParam;
 };
 
+#ifndef WINELIB
 #pragma pack(1)
+#endif
 
 #define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long))
 #define MTYPE 0xb0b0eb05
-#define WINE_PACKED __attribute__ ((packed))
+
+/* These structures are Win16 only */
 
 struct WIN_hostent  {
-	char	*h_name WINE_PACKED;		/* official name of host */
-	char	**h_aliases WINE_PACKED;	/* alias list */
-	int	h_addrtype WINE_PACKED;		/* host address type */
-	int	h_length WINE_PACKED;		/* length of address */
+	SEGPTR	h_name WINE_PACKED;		/* official name of host */
+	SEGPTR	h_aliases WINE_PACKED;	/* alias list */
+	INT	h_addrtype WINE_PACKED;		/* host address type */
+	INT	h_length WINE_PACKED;		/* length of address */
 	char	**h_addr_list WINE_PACKED;	/* list of addresses from name server */
 	char	*names[2];
 	char    hostname[200];
 };
 
 struct	WIN_protoent {
-	char	*p_name WINE_PACKED;		/* official protocol name */
-	char	**p_aliases WINE_PACKED;	/* alias list */
-	int	p_proto WINE_PACKED;		/* protocol # */
+	SEGPTR	p_name WINE_PACKED;		/* official protocol name */
+	SEGPTR	p_aliases WINE_PACKED;	/* alias list */
+	INT	p_proto WINE_PACKED;		/* protocol # */
 };
 
 struct	WIN_servent {
-	char	*s_name WINE_PACKED;		/* official service name */
-	char	**s_aliases WINE_PACKED;	/* alias list */
-	int	s_port WINE_PACKED;		/* port # */
-	char	*s_proto WINE_PACKED;		/* protocol to use */
+	SEGPTR	s_name WINE_PACKED;		/* official service name */
+	SEGPTR	s_aliases WINE_PACKED;	/* alias list */
+	INT	s_port WINE_PACKED;		/* port # */
+	SEGPTR	s_proto WINE_PACKED;		/* protocol to use */
 };
 
 struct WinSockHeap {
@@ -82,10 +86,23 @@
 	struct	WIN_protoent WSAprotoent_number;	
 	struct	WIN_servent WSAservent_name;
 	struct	WIN_servent WSAservent_port;
+	/* 8K scratch buffer for aliases and friends are hopefully enough */
+	char scratch[8192];
 };
-static struct WinSockHeap *heap;
+static struct WinSockHeap *Heap;
+static int HeapHandle;
+static int ScratchPtr;
 
+#ifndef WINELIB
+#define GET_SEG_PTR(x)	MAKELONG((int)((char*)(x)-(char*)Heap),	\
+							GlobalHandleToSel(HeapHandle))
+#else
+#define GET_SEG_PTR(x)	(x)
+#endif
+
+#ifndef WINELIB
 #pragma pack(4)
+#endif
 
 #define dump_sockaddr(a) \
 	fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
@@ -93,6 +110,28 @@
 			inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
 			ntohs(((struct sockaddr_in *)a)->sin_port))
 
+static void ResetScratch()
+{
+	ScratchPtr=0;
+}
+
+static void *scratch_alloc(int size)
+{
+	char *ret;
+	if(ScratchPtr+size > sizeof(Heap->scratch))
+		return 0;
+	ret = Heap->scratch + ScratchPtr;
+	ScratchPtr += size;
+	return ret;
+}
+
+static SEGPTR scratch_strdup(char * s)
+{
+	char *ret=scratch_alloc(strlen(s)+1);
+	strcpy(ret,s);
+	return GET_SEG_PTR(ret);
+}
+
 static WORD wsaerrno(void)
 {
 #ifdef DEBUG_WINSOCK
@@ -208,19 +247,70 @@
 }
 
 #ifndef WINELIB
-static void CONVERT_HOSTENT(struct WIN_hostent *heap, struct hostent *host)
+static SEGPTR copy_stringlist(char **list)
 {
+	SEGPTR *s_list;
+	int i;
+	for(i=0;list[i];i++)
+		;
+	s_list = scratch_alloc(sizeof(SEGPTR)*(i+1));
+	for(i=0;list[i];i++)
+	{
+		void *copy = scratch_alloc(strlen(list[i])+1);
+		strcpy(copy,list[i]);
+		s_list[i]=GET_SEG_PTR(copy);
+	}
+	s_list[i]=0;
+	return GET_SEG_PTR(s_list);
+}
+	
 
+static void CONVERT_HOSTENT(struct WIN_hostent *heapent, struct hostent *host)
+{
+	SEGPTR *addr_list;
+	int i;
+	ResetScratch();
+	strcpy(heapent->hostname,host->h_name);
+	heapent->h_name = GET_SEG_PTR(heapent->hostname);
+	/* Convert aliases. Have to create array with FAR pointers */
+	if(!host->h_aliases)
+		heapent->h_aliases = 0;
+	else
+		heapent->h_aliases = copy_stringlist(host->h_aliases);
+
+	heapent->h_addrtype = host->h_addrtype;
+	heapent->h_length = host->h_length;
+	for(i=0;host->h_addr_list[i];i++)
+		;
+	addr_list=scratch_alloc(sizeof(SEGPTR)*(i+1));
+	heapent->h_addr_list = GET_SEG_PTR(addr_list);
+	for(i=0;host->h_addr_list[i];i++)
+	{
+		void *addr=scratch_alloc(host->h_length);
+		memcpy(addr,host->h_addr_list[i],host->h_length);
+		addr_list[i]=GET_SEG_PTR(addr);
+	}
+	addr_list[i]=0;
 }
 
-static void CONVERT_PROTOENT(struct WIN_protoent *heap, struct protoent *proto)
+static void CONVERT_PROTOENT(struct WIN_protoent *heapent, 
+	struct protoent *proto)
 {
-
+	ResetScratch();
+	heapent->p_name= scratch_strdup(proto->p_name);
+	heapent->p_aliases=proto->p_aliases ? 
+			copy_stringlist(proto->p_aliases) : 0;
+	heapent->p_proto = proto->p_proto;
 }
 
-static void CONVERT_SERVENT(struct WIN_servent *heap, struct servent *serv)
+static void CONVERT_SERVENT(struct WIN_servent *heapent, struct servent *serv)
 {
-
+	ResetScratch();
+	heapent->s_name = scratch_strdup(serv->s_name);
+	heapent->s_aliases = serv->s_aliases ?
+			copy_stringlist(serv->s_aliases) : 0;
+	heapent->s_port = serv->s_port;
+	heapent->s_proto = scratch_strdup(serv->s_proto);
 }
 #else
 #define CONVERT_HOSTENT(a,b)	memcpy(a, &b, sizeof(a))
@@ -339,16 +429,45 @@
         	return NULL;
 	}
 
-	strncpy(heap->ntoa_buffer, s, sizeof(heap->ntoa_buffer) );
+	strncpy(Heap->ntoa_buffer, s, sizeof(Heap->ntoa_buffer) );
 
-	return (char *) &heap->ntoa_buffer;
+	return (char *) GET_SEG_PTR(&Heap->ntoa_buffer);
 }
 
-INT WINSOCK_ioctlsocket(SOCKET s, long cmd, u_long *argp)
+INT WINSOCK_ioctlsocket(SOCKET s, u_long cmd, u_long *argp)
 {
-	dprintf_winsock(stddeb, "WSA_ioctl: socket %d, cmd %ld, ptr %8x\n", s, cmd, (int) argp);
+	long newcmd;
+	u_long *newargp;
+	char *ctlname;
+	dprintf_winsock(stddeb, "WSA_ioctl: socket %d, cmd %lX, ptr %8x\n", s, cmd, (int) argp);
 
-	if (ioctl(s, cmd, argp) < 0) {
+	/* Why can't they all use the same ioctl numbers */
+	newcmd=cmd;
+	newargp=argp;
+	ctlname=0;
+	if(cmd == _IOR('f',127,u_long))
+	{
+		ctlname="FIONREAD";
+		newcmd=FIONREAD;
+	}else 
+	if(cmd == _IOW('f',126,u_long) || cmd == _IOR('f',126,u_long))
+	{
+		ctlname="FIONBIO";
+		newcmd=FIONBIO;
+	}else
+	if(cmd == _IOW('f',125,u_long))
+	{
+		ctlname="FIOASYNC";
+		newcmd=FIOASYNC;
+	}
+
+	if(!ctlname)
+		fprintf(stderr,"Unknown winsock ioctl. Trying anyway\n");
+	else
+		dprintf_winsock(stddeb,"Recognized as %s\n", ctlname);
+	
+
+	if (ioctl(s, newcmd, newargp) < 0) {
         	errno_to_wsaerrno();
         	return SOCKET_ERROR;
 	}
@@ -485,7 +604,10 @@
     return sock;
 }
 
-struct WIN_hostent *WINSOCK_gethostbyaddr(const char *addr, INT len, INT type)
+/*
+struct WIN_hostent *
+*/
+SEGPTR WINSOCK_gethostbyaddr(const char *addr, INT len, INT type)
 {
 	struct hostent *host;
 
@@ -495,12 +617,15 @@
         	errno_to_wsaerrno();
         	return NULL;
 	}
-	CONVERT_HOSTENT(&heap->hostent_addr, host);
+	CONVERT_HOSTENT(&Heap->hostent_addr, host);
 
-	return &heap->hostent_addr;
+	return GET_SEG_PTR(&Heap->hostent_addr);
 }
 
-struct WIN_hostent *WINSOCK_gethostbyname(const char *name)
+/*
+struct WIN_hostent *
+*/
+SEGPTR WINSOCK_gethostbyname(const char *name)
 {
 	struct hostent *host;
 
@@ -510,9 +635,9 @@
         	errno_to_wsaerrno();
         	return NULL;
 	}
-	CONVERT_HOSTENT(&heap->hostent_name, host);
+	CONVERT_HOSTENT(&Heap->hostent_name, host);
 
-	return &heap->hostent_name;
+	return GET_SEG_PTR(&Heap->hostent_name);
 }
 
 INT WINSOCK_gethostname(char *name, INT namelen)
@@ -526,7 +651,10 @@
 	return 0;
 }          
 
-struct WIN_protoent *WINSOCK_getprotobyname(char *name)
+/*
+struct WIN_protoent *
+*/
+SEGPTR WINSOCK_getprotobyname(char *name)
 {
 	struct protoent *proto;
 
@@ -536,12 +664,15 @@
         	errno_to_wsaerrno();
         	return NULL;
 	}
-	CONVERT_PROTOENT(&heap->protoent_name, proto);
+	CONVERT_PROTOENT(&Heap->protoent_name, proto);
 
-	return &heap->protoent_name;
+	return GET_SEG_PTR(&Heap->protoent_name);
 }
 
-struct WIN_protoent *WINSOCK_getprotobynumber(INT number)
+/*
+struct WIN_protoent *
+*/
+SEGPTR WINSOCK_getprotobynumber(INT number)
 {
 	struct protoent *proto;
 
@@ -551,12 +682,15 @@
         	errno_to_wsaerrno();
         	return NULL;
 	}
-	CONVERT_PROTOENT(&heap->protoent_number, proto);
+	CONVERT_PROTOENT(&Heap->protoent_number, proto);
 
-	return &heap->protoent_number;
+	return GET_SEG_PTR(&Heap->protoent_number);
 }
 
-struct WIN_servent *WINSOCK_getservbyname(const char *name, const char *proto)
+/*
+struct WIN_servent *
+*/
+SEGPTR WINSOCK_getservbyname(const char *name, const char *proto)
 {
 	struct servent *service;
 
@@ -569,12 +703,15 @@
         	errno_to_wsaerrno();
         	return NULL;
 	}
-	CONVERT_SERVENT(&heap->servent_name, service);
+	CONVERT_SERVENT(&Heap->servent_name, service);
 
-	return &heap->servent_name;
+	return GET_SEG_PTR(&Heap->servent_name);
 }
 
-struct WIN_servent *WINSOCK_getservbyport(INT port, const char *proto)
+/*
+struct WIN_servent *
+*/
+SEGPTR WINSOCK_getservbyport(INT port, const char *proto)
 {
 	struct servent *service;
 
@@ -584,9 +721,9 @@
         	errno_to_wsaerrno();
         	return NULL;
 	}
-	CONVERT_SERVENT(&heap->servent_port, service);
+	CONVERT_SERVENT(&Heap->servent_port, service);
 
-	return &heap->servent_port;
+	return GET_SEG_PTR(&Heap->servent_port);
 }
 
 /******************** winsock specific functions ************************
@@ -831,7 +968,7 @@
           
 INT WSAGetLastError(void)
 {
-	dprintf_winsock(stddeb, "WSA_GetLastError\n");
+	dprintf_winsock(stddeb, "WSA_GetLastError = %x\n", wsa_errno);
 
     return wsa_errno;
 }
@@ -886,7 +1023,6 @@
 
 INT WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
 {
-    int HeapHandle;
 
     dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
 
@@ -903,7 +1039,7 @@
     if ((HeapHandle = GlobalAlloc(GMEM_FIXED,sizeof(struct WinSockHeap))) == 0)
 	return WSASYSNOTREADY;
 
-    heap = (struct WinSockHeap *) GlobalLock(HeapHandle);
+    Heap = (struct WinSockHeap *) GlobalLock(HeapHandle);
     bcopy(&WINSOCK_data, lpWSAData, sizeof(WINSOCK_data));
 
     /* ipc stuff */