Release 960114

Sun Jan 14 13:45:22 1996  Alexandre Julliard  <julliard@sunsite.unc.edu>

	* [configure.in]
	Added check for gcc strength-reduce bug.

	* [controls/listbox.c]
	Changed ListBoxDirectory() to use the new DOS file functions.

	* [controls/menu.c]
	Fixed parameters for DeleteMenu() call in ChangeMenu().

	* [debugger/stack.c]
	Also display current frame in back-trace.

	* [files/directory.c] [files/dos_fs.c] [files/drive.c] [files/file.c]
	Complete rewrite of the DOS file handling.
	Implemented per-task file handles.
	Removed default Z: drive; needs to be put explicitely in wine.ini
	if desired.

	* [loader/module.c]
	Fixed file descriptor leak in LoadModule().

	* [loader/task.c]
	Initialise PDB file handle table in TASK_CreateTask().
	Close file handles on task termination.
	Implemented SetErrorMode().

	* [misc/network.c]
	Fixed WNetGetConnection() to use GetDriveType().

	* [misc/xmalloc.c]
	Added function xstrdup().

	* [miscemu/int21.c]
	Many changes for new DOS file functions.

	* [miscemu/interrupts.c]
	Moved DOS_GetEquipment() function into INT_Int11Handler().

	* [windows/win.c]
	Bug fix: create system menu before sending WM_NCCREATE.

	* [*/*.c]
	Replaced strcasecmp and strncasecmp by lstrcmpi and lstrncmpi for
	better portability.

Sat Jan 13 16:13:02 1996  Jim Peterson <jspeter@birch.ee.vt.edu>

	* [include/wintypes.h]
	Added 'typedef HGLOBAL GOBALHANDLE;'.  This is not precisely in line
	with the true windows 'typedef HANDLE GLOBALHANDLE;', but I believe
	it should suffice.

	* [include/winsock.h]
	Added '#include <arpa/inet.h>' for various declarations.  '#ifdef'-ed
	out some old style internet address #define's.

	* [loader/task.c]
	Made MakeProcInstance() return first parameter #ifdef WINELIB32.
	Made FreeProcInstance() do nothing #ifdef WINELIB32.
	'#ifdef'-ed out TASK_AllocThunk(), as it was unused in WINELIB32.

	* [library/miscstubs.c]
	Made GetWndProcEntry16() return ACTIVATEAPP_callback() when called
	with name="ActivateAppProc".  This hardly seems correct, but it's my
	best guess as to how the emulator responds.

Sat Jan  6 17:57:45 1996  Martin von Loewis <loewis@informatik.hu-berlin.de>

	* [if1632/kernel32.spec][win32/process.c]
	WIN32_GetProcAddress, LoadLibraryA: new functions

	* [if1632/relay32.c]
	RELAY32_GetEntryPoint: Removed code to load PE DLLs

	* [include/pe_image.h][include/pe_exe.h]
	struct pe_data: new fields base_addr,load_addr,vma_size,pe_reloc
	struct PE_Reloc_Block: new structure

	* [loader/module.c]
	MODULE_RegisterModule: new function

	* [loader/pe_image.c]
	PE_FindExportedFunction,PE_GetProcAddress: new functions
	fixup_imports: expect struct w_files* now, fill dlls_to_init,
	               load PE DLLs
	do_relocations: new functions
	calc_vma_size: renamed from dump_table
	PE_LoadImage: use malloc to allocate memory for image
	PE_InitDLL: expect HMODULE
	PE_InitializeDLLs: new function

	* [loader/task.c]
	NE_InitializeDLLs: branch to PE_InitializeDLLs for PE modules
	GetExePtr: Accept PE modules

	* [misc/commdlg.c]
	FILEDLG_WMCommand: unpack WIN32 WM_COMMAND appropriately for WineLib

Thu Jan  4 11:36:21 1996  Manfred Weichel <Manfred.Weichel@mch.sni.de>

	* [misc/port.c]
	New file with usleep() function for SVR4.

	* [configure.in]
	Check for usleep() function.

Tue Jan 02 14:00:00 1996  Anand Kumria <akumria@ozemail.com.au>

	* [if1632/toolhelp.spec] [include/toolhelp.h]
	  [misc/user.c] [windows/message.c]
	Implement TOOLHELP.80 TimerCount. Fix GetTickCount.

	* [winsocket.c]
	Fixed ENOENT error.

	* [miscemu/dpmi.c]
	Implement DPMI Get Page Size (AX=0604, INT 31)

	* [memory/global.c]
	Implement TOOLHELP.72 GetMemManInfo.

Mon Jan  2 10:33:00 1996  Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>

	* [if1632/callback.c]
	CallWindowProc() - When calling RELAY32_CallWindowProc, check
	whether lParam should be a SEGPTR, and if so convert it to one.

	* [if1632/gdi.spec] [if1632/kernel32.spec] [if1632/user32.spec]
	Numerous functions added, mostly calls to original (win16)
 	functions.  Note that some (many) of these are probably not
 	strictly correct, but with these additions freecell will at least
 	display its main window though it is garbled.

	* [if1632/winprocs.spec]
	Completely rewritten - all WndProcs now have win32 versions to
	help with the lparam SEGPTR fix in callback.c

	* [include/kernel32.h]
	LPTCSTR defined.

	* [include/peexe.h]
	Definition of PE_Export_Directory amended.

	* [include/resource32.h]
	New file.

	* [include/stackframe.h]
	Definition of MAKE_SEGPTR macro #ifdef'd out and replaced with
	prototype for replacement function in memory/selector.c which
	can operate on any given memory address. This is currently
	required for win32 support. It is a dreadful cludge, and will
	certainly slow down other programs. If you are not interested
	in win32 development you may wish to reverse this patch.

	* [include/windows.h]
	Definition of SW_SHOWDEFAULT added.

	* [loader/pe_image.c]
	Extensive rewrites of xmmap() fixup_imports().
	PE_LoadImage() - initialisation of bss added, extraction of
	module name fixed, initialisation of DLL added.
	PE_InitDLL() - now does something.
	PE_Win32CallToStart() - initialisation of TEB pointed to by
	fs added.
	PE_InitTEB() created to perform TEB initialisation.

	* [memory/selector.c] 
	New function MAKE_SEGPTR() - see include/stackframe.h above.

	* [misc/user32.c]
	USER32_RegisterClassA(), CreateWindowExA() memory allocation
	method changed. This is probably now unnecessary with the
	new MAKE_SEGPTR handling code.
	USER32_DefWndProcA() removed to win32/winprocs.c
	USER32_TranslateMessage added.

	* [tools/build.c]
	handling of win32 spec files changed to support gcc2.6.X
	this requires optimisations to be disabled.

	* [win32/resource.c] [win32/newfns.c] [win32/heap.c] [win32/winprocs.c]
	New files.

	* [win32/Makefile.in]
	New files heap.c, newfns.c, resource.c and winprocs.c added to build.

	* [win32/file.c]
	New function W32_SetHandleCount.

	* [win32/init.c]
	WIN32_GetModuleHandle() - now returns handle of running process
	if called with NULL.
	GetStartupInfoA() - set cbReserved2 to 0.

	* [win32/memory.c]
	VirtualAlloc() - set mmap() file parameter to -1 instead of 0 to make
	it work with FreeBSD. Also check for return value. Removed extra
	return.

	* [windows/winpos.c]
	ShowWindow() - SW_SHOWDEFAULT handling kludged in.
diff --git a/ANNOUNCE b/ANNOUNCE
index 86723e9..703bde4 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,13 +1,13 @@
-This is release 951226 of Wine the MS Windows emulator.  This is still a
+This is release 960114 of Wine the MS Windows emulator.  This is still a
 developer's only release.  There are many bugs and many unimplemented API
 features.  Most applications still do not work.
 
 Patches should be submitted to "wine-new@amscons.com".  Please don't forget
 to include a ChangeLog entry.  I'll make a new release every other week.
 
-WHAT'S NEW with Wine-951226: (see ChangeLog for details)
-	- Many more Winelib fixes.
-	- Language is now a run-time option.
+WHAT'S NEW with Wine-960114: (see ChangeLog for details)
+	- Complete rewrite of the file handling; still has a few bugs.
+	- Tons of new Win32 code.
 	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -16,10 +16,10 @@
 the release is available at the ftp sites.  The sources will be available
 from the following locations:
 
-    sunsite.unc.edu:/pub/Linux/ALPHA/wine/Wine-951226.tar.gz
-    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-951226.tar.gz
-    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-951226.tar.gz
-    aris.com:/pub/linux/ALPHA/Wine/development/Wine-951226.tar.gz
+    sunsite.unc.edu:/pub/Linux/ALPHA/wine/Wine-960114.tar.gz
+    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960114.tar.gz
+    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960114.tar.gz
+    aris.com:/pub/linux/ALPHA/Wine/development/Wine-960114.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
diff --git a/ChangeLog b/ChangeLog
index fc9e70b..d7a84c2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,206 @@
 ----------------------------------------------------------------------
+Sun Jan 14 13:45:22 1996  Alexandre Julliard  <julliard@sunsite.unc.edu>
+
+	* [configure.in]
+	Added check for gcc strength-reduce bug.
+
+	* [controls/listbox.c]
+	Changed ListBoxDirectory() to use the new DOS file functions.
+
+	* [controls/menu.c]
+	Fixed parameters for DeleteMenu() call in ChangeMenu().
+
+	* [debugger/stack.c]
+	Also display current frame in back-trace.
+
+	* [files/directory.c] [files/dos_fs.c] [files/drive.c] [files/file.c]
+	Complete rewrite of the DOS file handling.
+	Implemented per-task file handles.
+	Removed default Z: drive; needs to be put explicitely in wine.ini
+	if desired.
+
+	* [loader/module.c]
+	Fixed file descriptor leak in LoadModule().
+
+	* [loader/task.c]
+	Initialise PDB file handle table in TASK_CreateTask().
+	Close file handles on task termination.
+	Implemented SetErrorMode().
+
+	* [misc/network.c]
+	Fixed WNetGetConnection() to use GetDriveType().
+
+	* [misc/xmalloc.c]
+	Added function xstrdup().
+
+	* [miscemu/int21.c]
+	Many changes for new DOS file functions.
+
+	* [miscemu/interrupts.c]
+	Moved DOS_GetEquipment() function into INT_Int11Handler().
+
+	* [windows/win.c]
+	Bug fix: create system menu before sending WM_NCCREATE.
+
+	* [*/*.c]
+	Replaced strcasecmp and strncasecmp by lstrcmpi and lstrncmpi for
+	better portability.
+
+Sat Jan 13 16:13:02 1996  Jim Peterson <jspeter@birch.ee.vt.edu>
+
+	* [include/wintypes.h]
+	Added 'typedef HGLOBAL GOBALHANDLE;'.  This is not precisely in line
+	with the true windows 'typedef HANDLE GLOBALHANDLE;', but I believe
+	it should suffice.
+
+	* [include/winsock.h]
+	Added '#include <arpa/inet.h>' for various declarations.  '#ifdef'-ed
+	out some old style internet address #define's.
+
+	* [loader/task.c]
+	Made MakeProcInstance() return first parameter #ifdef WINELIB32.
+	Made FreeProcInstance() do nothing #ifdef WINELIB32.
+	'#ifdef'-ed out TASK_AllocThunk(), as it was unused in WINELIB32.
+
+	* [library/miscstubs.c]
+	Made GetWndProcEntry16() return ACTIVATEAPP_callback() when called
+	with name="ActivateAppProc".  This hardly seems correct, but it's my
+	best guess as to how the emulator responds.
+
+Sat Jan  6 17:57:45 1996  Martin von Loewis <loewis@informatik.hu-berlin.de>
+
+	* [if1632/kernel32.spec][win32/process.c]
+	WIN32_GetProcAddress, LoadLibraryA: new functions
+
+	* [if1632/relay32.c]
+	RELAY32_GetEntryPoint: Removed code to load PE DLLs
+
+	* [include/pe_image.h][include/pe_exe.h]
+	struct pe_data: new fields base_addr,load_addr,vma_size,pe_reloc
+	struct PE_Reloc_Block: new structure
+
+	* [loader/module.c]
+	MODULE_RegisterModule: new function
+
+	* [loader/pe_image.c]
+	PE_FindExportedFunction,PE_GetProcAddress: new functions
+	fixup_imports: expect struct w_files* now, fill dlls_to_init,
+	               load PE DLLs
+	do_relocations: new functions
+	calc_vma_size: renamed from dump_table
+	PE_LoadImage: use malloc to allocate memory for image
+	PE_InitDLL: expect HMODULE
+	PE_InitializeDLLs: new function
+
+	* [loader/task.c]
+	NE_InitializeDLLs: branch to PE_InitializeDLLs for PE modules
+	GetExePtr: Accept PE modules
+
+	* [misc/commdlg.c]
+	FILEDLG_WMCommand: unpack WIN32 WM_COMMAND appropriately for WineLib
+
+Thu Jan  4 11:36:21 1996  Manfred Weichel <Manfred.Weichel@mch.sni.de>
+
+	* [misc/port.c]
+	New file with usleep() function for SVR4.
+
+	* [configure.in]
+	Check for usleep() function.
+
+Tue Jan 02 14:00:00 1996  Anand Kumria <akumria@ozemail.com.au>
+
+	* [if1632/toolhelp.spec] [include/toolhelp.h]
+	  [misc/user.c] [windows/message.c]
+	Implement TOOLHELP.80 TimerCount. Fix GetTickCount.
+
+	* [miscemu/dpmi.c]
+	Implement DPMI Get Page Size (AX=0604, INT 31)
+
+	* [memory/global.c]
+	Implement TOOLHELP.72 GetMemManInfo.
+
+Mon Jan  2 10:33:00 1996  Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>
+
+	* [if1632/callback.c]
+	CallWindowProc() - When calling RELAY32_CallWindowProc, check
+	whether lParam should be a SEGPTR, and if so convert it to one.
+
+	* [if1632/gdi.spec] [if1632/kernel32.spec] [if1632/user32.spec]
+	Numerous functions added, mostly calls to original (win16)
+ 	functions.  Note that some (many) of these are probably not
+ 	strictly correct, but with these additions freecell will at least
+ 	display its main window though it is garbled.
+
+	* [if1632/winprocs.spec]
+	Completely rewritten - all WndProcs now have win32 versions to
+	help with the lparam SEGPTR fix in callback.c
+
+	* [include/kernel32.h]
+	LPTCSTR defined.
+
+	* [include/peexe.h]
+	Definition of PE_Export_Directory amended.
+
+	* [include/resource32.h]
+	New file.
+
+	* [include/stackframe.h]
+	Definition of MAKE_SEGPTR macro #ifdef'd out and replaced with
+	prototype for replacement function in memory/selector.c which
+	can operate on any given memory address. This is currently
+	required for win32 support. It is a dreadful cludge, and will
+	certainly slow down other programs. If you are not interested
+	in win32 development you may wish to reverse this patch.
+
+	* [include/windows.h]
+	Definition of SW_SHOWDEFAULT added.
+
+	* [loader/pe_image.c]
+	Extensive rewrites of xmmap() fixup_imports().
+	PE_LoadImage() - initialisation of bss added, extraction of
+	module name fixed, initialisation of DLL added.
+	PE_InitDLL() - now does something.
+	PE_Win32CallToStart() - initialisation of TEB pointed to by
+	fs added.
+	PE_InitTEB() created to perform TEB initialisation.
+
+	* [memory/selector.c] 
+	New function MAKE_SEGPTR() - see include/stackframe.h above.
+
+	* [misc/user32.c]
+	USER32_RegisterClassA(), CreateWindowExA() memory allocation
+	method changed. This is probably now unnecessary with the
+	new MAKE_SEGPTR handling code.
+	USER32_DefWndProcA() removed to win32/winprocs.c
+	USER32_TranslateMessage added.
+
+	* [tools/build.c]
+	handling of win32 spec files changed to support gcc2.6.X
+	this requires optimisations to be disabled.
+
+	* [win32/resource.c] [win32/newfns.c] [win32/heap.c] [win32/winprocs.c]
+	New files.
+
+	* [win32/Makefile.in]
+	New files heap.c, newfns.c, resource.c and winprocs.c added to build.
+
+	* [win32/file.c]
+	New function W32_SetHandleCount.
+
+	* [win32/init.c]
+	WIN32_GetModuleHandle() - now returns handle of running process
+	if called with NULL.
+	GetStartupInfoA() - set cbReserved2 to 0.
+
+	* [win32/memory.c]
+	VirtualAlloc() - set mmap() file parameter to -1 instead of 0 to make
+	it work with FreeBSD. Also check for return value. Removed extra
+	return.
+
+	* [windows/winpos.c]
+	ShowWindow() - SW_SHOWDEFAULT handling kludged in.
+
+----------------------------------------------------------------------
 Sat Dec 23 18:15:59 1995  Alexandre Julliard  <julliard@sunsite.unc.edu>
 
 	* [configure.in] [Makefile.in] [tools/install-sh]
diff --git a/Makefile.in b/Makefile.in
index faea819..0e3459b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -49,6 +49,7 @@
 COMMONSUBDIRS = \
 	rc \
 	controls \
+	files \
 	ipc \
 	loader \
 	misc \
@@ -72,6 +73,7 @@
 
 COMMONOBJS = \
 	controls/controls.o \
+	files/files.o \
 	ipc/ipc.o \
 	loader/loader.o \
 	misc/misc.o \
diff --git a/configure b/configure
index 704cc35..0689562 100755
--- a/configure
+++ b/configure
@@ -685,7 +685,6 @@
   test "${CFLAGS+set}" = set || CFLAGS="-g"
 fi
 
-test "x${GCC}" = "xyes" && CFLAGS="$CFLAGS -Wall -fno-strength-reduce"
 echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
 # On Suns, sometimes $CPP names a directory.
 if test -n "$CPP" && test -d "$CPP"; then
@@ -701,7 +700,7 @@
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp.
   cat > conftest.$ac_ext <<EOF
-#line 705 "configure"
+#line 704 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
@@ -715,7 +714,7 @@
   rm -rf conftest*
   CPP="${CC-cc} -E -traditional-cpp"
   cat > conftest.$ac_ext <<EOF
-#line 719 "configure"
+#line 718 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
@@ -821,7 +820,7 @@
 test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc
 test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h
 cat > conftest.$ac_ext <<EOF
-#line 825 "configure"
+#line 824 "configure"
 #include "confdefs.h"
 #include <$x_direct_test_include>
 EOF
@@ -884,7 +883,7 @@
 ac_save_LIBS="$LIBS"
 LIBS="-l$x_direct_test_library $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 888 "configure"
+#line 887 "configure"
 #include "confdefs.h"
 
 int main() { return 0; }
@@ -1003,7 +1002,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lICE  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1007 "configure"
+#line 1006 "configure"
 #include "confdefs.h"
 
 int main() { return 0; }
@@ -1047,7 +1046,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-ldnet  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1051 "configure"
+#line 1050 "configure"
 #include "confdefs.h"
 
 int main() { return 0; }
@@ -1082,7 +1081,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-ldnet_stub  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1086 "configure"
+#line 1085 "configure"
 #include "confdefs.h"
 
 int main() { return 0; }
@@ -1122,7 +1121,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lnsl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1126 "configure"
+#line 1125 "configure"
 #include "confdefs.h"
 
 int main() { return 0; }
@@ -1161,7 +1160,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lsocket  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1165 "configure"
+#line 1164 "configure"
 #include "confdefs.h"
 
 int main() { return 0; }
@@ -1266,7 +1265,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-l$ac_lib  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1270 "configure"
+#line 1269 "configure"
 #include "confdefs.h"
 
 int main() { return 0; }
@@ -1389,7 +1388,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-li386  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1393 "configure"
+#line 1392 "configure"
 #include "confdefs.h"
 
 int main() { return 0; }
@@ -1417,14 +1416,80 @@
 
 
 
-for ac_func in tcgetattr
+if test "x${GCC}" = "xyes"
+then
+  CFLAGS="$CFLAGS -Wall"
+  # If we cannot run a trivial program, we must be cross compiling.
+echo $ac_n "checking whether cross-compiling""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_c_cross'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_c_cross=yes
+else
+cat > conftest.$ac_ext <<EOF
+#line 1432 "configure"
+#include "confdefs.h"
+main(){return(0);}
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+  ac_cv_c_cross=no
+else
+  ac_cv_c_cross=yes
+fi
+fi
+rm -fr conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_cross" 1>&6
+cross_compiling=$ac_cv_c_cross
+
+  echo $ac_n "checking "for gcc strength-reduce bug"""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_c_gcc_strength_bug'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_c_gcc_strength_bug="yes"
+else
+cat > conftest.$ac_ext <<EOF
+#line 1457 "configure"
+#include "confdefs.h"
+
+int main(void) {
+  static int Array3;
+  unsigned int B = 3;
+  int i;
+  for(i=0; i<B; i++) Arrayi = i - 3;
+  exit( Array1 != -2 );
+}
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+  ac_cv_c_gcc_strength_bug="no"
+else
+  ac_cv_c_gcc_strength_bug="yes"
+fi
+fi
+rm -fr conftest* 
+fi
+
+echo "$ac_t""$ac_cv_c_gcc_strength_bug" 1>&6
+  if test "$ac_cv_c_gcc_strength_bug" = "yes"
+  then
+    CFLAGS="$CFLAGS -fno-strength-reduce"
+  fi
+fi
+
+
+for ac_func in tcgetattr usleep
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1428 "configure"
+#line 1493 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -1476,7 +1541,7 @@
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1480 "configure"
+#line 1545 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
@@ -1509,7 +1574,7 @@
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1513 "configure"
+#line 1578 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -1564,7 +1629,7 @@
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1568 "configure"
+#line 1633 "configure"
 #include "confdefs.h"
 
 int main() { return 0; }
@@ -1633,38 +1698,12 @@
 
 fi
 
-# If we cannot run a trivial program, we must be cross compiling.
-echo $ac_n "checking whether cross-compiling""... $ac_c" 1>&6
-if eval "test \"`echo '$''{'ac_cv_c_cross'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  if test "$cross_compiling" = yes; then
-  ac_cv_c_cross=yes
-else
-cat > conftest.$ac_ext <<EOF
-#line 1646 "configure"
-#include "confdefs.h"
-main(){return(0);}
-EOF
-eval $ac_link
-if test -s conftest && (./conftest; exit) 2>/dev/null; then
-  ac_cv_c_cross=no
-else
-  ac_cv_c_cross=yes
-fi
-fi
-rm -fr conftest*
-fi
-
-echo "$ac_t""$ac_cv_c_cross" 1>&6
-cross_compiling=$ac_cv_c_cross
-
 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1668 "configure"
+#line 1707 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -1686,7 +1725,7 @@
 if test $ac_cv_header_stdc = yes; then
   # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 1690 "configure"
+#line 1729 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -1704,7 +1743,7 @@
 if test $ac_cv_header_stdc = yes; then
   # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 1708 "configure"
+#line 1747 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -1725,7 +1764,7 @@
   :
 else
 cat > conftest.$ac_ext <<EOF
-#line 1729 "configure"
+#line 1768 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -1760,7 +1799,7 @@
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1764 "configure"
+#line 1803 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -1896,6 +1935,7 @@
 controls/Makefile
 debugger/Makefile
 debugger/readline/Makefile
+files/Makefile
 if1632/Makefile
 ipc/Makefile
 library/Makefile
@@ -1967,6 +2007,7 @@
 controls/Makefile
 debugger/Makefile
 debugger/readline/Makefile
+files/Makefile
 if1632/Makefile
 ipc/Makefile
 library/Makefile
diff --git a/configure.in b/configure.in
index 27490d1..d8a94c0 100644
--- a/configure.in
+++ b/configure.in
@@ -29,8 +29,6 @@
 
 AC_PROG_MAKE_SET
 AC_PROG_CC
-dnl Add some options for gcc
-test "x${GCC}" = "xyes" && CFLAGS="$CFLAGS -Wall -fno-strength-reduce"
 AC_PROG_CPP
 AC_PATH_XTRA
 AC_PROG_YACC
@@ -40,9 +38,33 @@
 dnl Check for -li386 for NetBSD
 AC_CHECK_LIB(i386,i386_set_ldt,LDLIBS="$LDLIBS -li386")
 
+dnl **** Check for gcc strength-reduce bug ****
+
+if test "x${GCC}" = "xyes"
+then
+  CFLAGS="$CFLAGS -Wall"
+  AC_C_CROSS
+  AC_CACHE_CHECK( "for gcc strength-reduce bug", ac_cv_c_gcc_strength_bug,
+                  AC_TRY_RUN([
+int main(void) {
+  static int Array[3];
+  unsigned int B = 3;
+  int i;
+  for(i=0; i<B; i++) Array[i] = i - 3;
+  exit( Array[1] != -2 );
+}],
+    ac_cv_c_gcc_strength_bug="no",
+    ac_cv_c_gcc_strength_bug="yes",
+    ac_cv_c_gcc_strength_bug="yes") )
+  if test "$ac_cv_c_gcc_strength_bug" = "yes"
+  then
+    CFLAGS="$CFLAGS -fno-strength-reduce"
+  fi
+fi
+
 dnl **** Check for functions and header files ****
 
-AC_CHECK_FUNCS(tcgetattr)
+AC_CHECK_FUNCS(tcgetattr usleep)
 AC_CHECK_HEADERS(stdlib.h)
 AC_HEADER_STAT()
 AC_C_CONST()
@@ -59,6 +81,7 @@
 controls/Makefile
 debugger/Makefile
 debugger/readline/Makefile
+files/Makefile
 if1632/Makefile
 ipc/Makefile
 library/Makefile
diff --git a/controls/combo.c b/controls/combo.c
index 6c3f320..378115e 100644
--- a/controls/combo.c
+++ b/controls/combo.c
@@ -20,6 +20,7 @@
 #include "graphics.h"
 #include "listbox.h"
 #include "dos_fs.h"
+#include "drive.h"
 #include "stddebug.h"
 #include "debug.h"
 #include "xmalloc.h"
@@ -996,48 +997,28 @@
 /************************************************************************
  * 					DlgDirListComboBox     [USER.195]
  */
-int DlgDirListComboBox(HWND hDlg, SEGPTR PathSpec,
-		       int nIDLBox, int nIDStat, WORD wType)
+INT DlgDirListComboBox( HWND hDlg, SEGPTR path, INT idCBox,
+                        INT idStatic, WORD wType )
 {
-  HWND	hWnd;
-  int ret;
-  LPSTR lpPathSpec = PTR_SEG_TO_LIN(PathSpec);
+    INT ret = 0;
 
-  dprintf_combo(stddeb,"DlgDirListComboBox("NPFMT", '%s', %d, %d, %04X) \n",
-		  hDlg, lpPathSpec, nIDLBox, nIDStat, wType);
-  if (nIDLBox) {
-    LPHEADLIST lphl;
-    LPHEADCOMBO lphc;
-    hWnd = GetDlgItem(hDlg, nIDLBox);
-    lphl = ComboGetListHeader(hWnd);
-    lphc = ComboGetStorageHeader(hWnd);
-    ListBoxResetContent(lphl);
-    ret = ListBoxDirectory(lphl, wType, lpPathSpec);
-    ComboUpdateWindow(hWnd, lphl, lphc, TRUE);
-  } else {
-    ret = 0;
-  }
-  if (nIDStat) {
-      int drive;
-      HANDLE hTemp;
-      char *temp;
-      drive = DOS_GetDefaultDrive();
-      hTemp = USER_HEAP_ALLOC( 256 );
-      temp = (char *) USER_HEAP_LIN_ADDR( hTemp );
-      strcpy( temp+3, DOS_GetCurrentDir(drive) );
-      if( temp[3] == '\\' ) {
-	temp[1] = 'A'+drive;
-	temp[2] = ':';
-	SendDlgItemMessage( hDlg, nIDStat, WM_SETTEXT, 0,
-                            (LPARAM)(USER_HEAP_SEG_ADDR(hTemp) + 1) );
-      } else {
-	temp[0] = 'A'+drive;
-	temp[1] = ':';
-	temp[2] = '\\';
-	SendDlgItemMessage( hDlg, nIDStat, WM_SETTEXT, 0,
-                            (LPARAM)USER_HEAP_SEG_ADDR(hTemp) );
-      }
-      USER_HEAP_FREE( hTemp );
-  } 
-  return ret;
+    dprintf_combo( stddeb,"DlgDirListComboBox("NPFMT",%08lx,%d,%d,%04X) \n",
+                   hDlg, (DWORD)path, idCBox, idStatic, wType );
+
+    if (idCBox)
+    {
+        SendDlgItemMessage( hDlg, idCBox, CB_RESETCONTENT, 0, 0 );
+        ret = (SendDlgItemMessage( hDlg, idCBox, CB_DIR, wType, path ) >= 0);
+    }
+    if (idStatic)
+    {
+        char temp[256];
+        int drive = DRIVE_GetCurrentDrive();
+        strcpy( temp, "A:\\" );
+        temp[0] += drive;
+        lstrcpyn( temp+3, DRIVE_GetDosCwd(drive), 253 );
+        SendDlgItemMessage( hDlg, idStatic, WM_SETTEXT,
+                            0, (LPARAM)MAKE_SEGPTR(temp) );
+    } 
+    return ret;
 }
diff --git a/controls/desktop.c b/controls/desktop.c
index b3796f4..9f462c6 100644
--- a/controls/desktop.c
+++ b/controls/desktop.c
@@ -22,18 +22,19 @@
  *
  * Load a bitmap from a file. Used by SetDeskWallPaper().
  */
-static HBITMAP DESKTOP_LoadBitmap( HDC hdc, char *filename )
+static HBITMAP DESKTOP_LoadBitmap( HDC hdc, const char *filename )
 {
     BITMAPFILEHEADER *fileHeader;
     BITMAPINFO *bitmapInfo;
     HBITMAP hbitmap;
-    char *unixFileName, *buffer;
+    char *buffer;
+    const char *unixFileName;
     int file;
     long size;
 
       /* Read all the file into memory */
 
-    if (!(unixFileName = DOS_GetUnixFileName( filename ))) return 0;
+    if (!(unixFileName = DOSFS_GetUnixFileName( filename, TRUE ))) return 0;
     if ((file = open( unixFileName, O_RDONLY )) == -1) return 0;
     size = lseek( file, 0, SEEK_END );
     if (!(buffer = (char *)malloc( size )))
@@ -159,7 +160,7 @@
 /***********************************************************************
  *           SetDeskWallPaper   (USER.285)
  */
-BOOL SetDeskWallPaper( LPSTR filename )
+BOOL SetDeskWallPaper( LPCSTR filename )
 {
     HBITMAP hbitmap;
     HDC hdc;
diff --git a/controls/listbox.c b/controls/listbox.c
index d1b0df7..7ecd806 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -24,6 +24,8 @@
 #include "msdos.h"
 #include "listbox.h"
 #include "dos_fs.h"
+#include "drive.h"
+#include "stackframe.h"
 #include "stddebug.h"
 #include "debug.h"
 #include "xmalloc.h"
@@ -633,65 +635,79 @@
 
 int ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPSTR filespec)
 {
-  struct dosdirent *dp, *dp_old;
-  char temp[256];
-  int   drive;
-  LPSTR tstr;
+    const char *pathPtr, *maskPtr;
+    char mask[12], path[MAX_PATHNAME_LEN];
+    int skip, count;
+    DOS_DIRENT entry;
+
+    char temp[256];
+    int   drive;
+    LPSTR tstr;
 
   dprintf_listbox(stddeb,"ListBoxDirectory: %s, %4x\n",filespec,attrib);
 
   if (strchr(filespec, '\\') || strchr(filespec, ':')) {
-    drive = DOS_GetDefaultDrive();
     if (filespec[1] == ':') {
       drive = toupper(filespec[0]) - 'A';
       filespec += 2;
     }
+    else drive = DRIVE_GetCurrentDrive();
     strcpy(temp,filespec);
     tstr = strrchr(temp, '\\');
     if (tstr != NULL) {
       *(tstr+1) = 0;
       filespec += tstr - temp + 1;
-      if (!DOS_ChangeDir( drive, temp )) return 0;
+      if (!DRIVE_Chdir( drive, temp )) return 0;
     }
-    DOS_SetDefaultDrive( drive );
+    DRIVE_SetCurrentDrive( drive );
     dprintf_listbox(stddeb,"Changing directory to %c:%s, filemask is %s\n",
 		    drive+'A', temp, filespec);
   }
 
-  if ((dp = (struct dosdirent *)DOS_opendir(filespec)) ==NULL) return 0;
-  dp_old = dp;
-  while ((dp = (struct dosdirent *)DOS_readdir(dp))) {
-    if (!dp->inuse) break;
-    dprintf_listbox(stddeb, "ListBoxDirectory %p '%s' !\n", dp->filename, 
-		    dp->filename);
-    if (dp->attribute & FA_DIREC) {
-      if (attrib & DDL_DIRECTORY && strcmp(dp->filename, ".") != 0) {
-	sprintf(temp, "[%s]", dp->filename);
-	if (ListBoxAddString(lphl, temp) == LB_ERR) break;
-      }
-    } 
-    else {
-      if (attrib & DDL_EXCLUSIVE) {
-	if (attrib & (DDL_READWRITE | DDL_READONLY | DDL_HIDDEN | DDL_SYSTEM)) {
-	  if (ListBoxAddString(lphl, dp->filename) == LB_ERR) break;
-	}
-      } else {
-	if (ListBoxAddString(lphl, dp->filename) == LB_ERR) break;
-      }
+
+    if (!(maskPtr = DOSFS_ToDosFCBFormat( filespec ))) return 0;
+    strcpy( mask, maskPtr );
+    if (!(pathPtr = DOSFS_GetUnixFileName( ".", TRUE ))) return 0;
+    lstrcpyn( path, pathPtr, sizeof(path) );
+    skip  = 0;
+    drive = DRIVE_GetCurrentDrive();
+    
+    while ((count = DOSFS_FindNext( path, mask, drive,
+                                    attrib, skip, &entry )) > 0)
+    {
+        skip += count;
+        if (entry.attr & FA_DIRECTORY)
+        {
+            if ((attrib & DDL_DIRECTORY) && strcmp(entry.name, "."))
+            {
+                sprintf(temp, "[%s]", entry.name);
+                if (ListBoxAddString(lphl, temp) == LB_ERR) break;
+            }
+        }
+        else  /* not a directory */
+        {
+            if (!(attrib & DDL_EXCLUSIVE) ||
+                ((attrib & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)) ==
+                 (entry.attr & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE))))
+            {
+                if (ListBoxAddString(lphl, entry.name) == LB_ERR) break;
+            }
+        }
     }
-  }
-  DOS_closedir(dp_old);
-  
-  if (attrib & DDL_DRIVES) {
-    int x;
-    for (x = 0; x != MAX_DOS_DRIVES ; x++) {
-      if (DOS_ValidDrive(x)) {
-	sprintf(temp, "[-%c-]", 'a'+x);
-	if (ListBoxInsertString(lphl, (UINT)-1, temp) == LB_ERR) break;
-      }		
+
+    if (attrib & DDL_DRIVES)
+    {
+        int x;
+        for (x = 0; x < MAX_DOS_DRIVES; x++)
+        {
+            if (DRIVE_IsValid(x))
+            {
+                sprintf(temp, "[-%c-]", 'a'+x);
+                if (ListBoxInsertString(lphl, (UINT)-1, temp) == LB_ERR) break;
+            }
+        }
     }
-  }
-  return 1;
+    return 1;
 }
 
 /* ------------------------- dimensions ------------------------- */
@@ -1923,45 +1939,26 @@
 /************************************************************************
  * 			   DlgDirList		       	[USER.100]
  */
-int DlgDirList(HWND hDlg, LPSTR lpPathSpec, 
-	       int nIDLBox, int nIDStat, WORD wType)
+INT DlgDirList( HWND hDlg, SEGPTR path, INT idLBox, INT idStatic, WORD wType ) 
 {
-  HWND	hWnd;
-  int ret;
+    INT ret = 0;
   
-  dprintf_listbox(stddeb,"DlgDirList("NPFMT", '%s', %d, %d, %04X) \n",
-		  hDlg, lpPathSpec, nIDLBox, nIDStat, wType);
-  if (nIDLBox)  {
-    LPHEADLIST lphl;
-    hWnd = GetDlgItem(hDlg, nIDLBox);
-    lphl = ListBoxGetStorageHeader(hWnd);
-    ListBoxResetContent(lphl);
-    ret = ListBoxDirectory(lphl, wType, lpPathSpec);
-    ListBoxUpdateWindow(hWnd, lphl, TRUE);
-  } else {
-    ret = 0;
-  }
-  if (nIDStat) {
-      int drive;
-      HANDLE hTemp;
-      char *temp;
-      drive = DOS_GetDefaultDrive();
-      hTemp = USER_HEAP_ALLOC( 256 );
-      temp = (char *) USER_HEAP_LIN_ADDR( hTemp );
-      strcpy( temp+3, DOS_GetCurrentDir(drive) );
-      if( temp[3] == '\\' ) {
-	temp[1] = 'A'+drive;
-	temp[2] = ':';
-	SendDlgItemMessage( hDlg, nIDStat, WM_SETTEXT, 0,
-                            (LPARAM)(USER_HEAP_SEG_ADDR(hTemp) + 1) );
-      } else {
-	temp[0] = 'A'+drive;
-	temp[1] = ':';
-	temp[2] = '\\';
-	SendDlgItemMessage( hDlg, nIDStat, WM_SETTEXT, 0,
-                            (LPARAM)USER_HEAP_SEG_ADDR(hTemp) );
-      }
-      USER_HEAP_FREE( hTemp );
-  } 
-  return ret;
+    dprintf_listbox( stddeb, "DlgDirList("NPFMT", %08lx, %d, %d, %04X) \n",
+                     hDlg, (DWORD)path, idLBox, idStatic, wType );
+    if (idLBox)
+    {
+        SendDlgItemMessage( hDlg, idLBox, LB_RESETCONTENT, 0, 0 );
+        ret = (SendDlgItemMessage( hDlg, idLBox, LB_DIR, wType, path ) >= 0);
+    }
+    if (idStatic)
+    {
+        char temp[256];
+        int drive = DRIVE_GetCurrentDrive();
+        strcpy( temp, "A:\\" );
+        temp[0] += drive;
+        lstrcpyn( temp+3, DRIVE_GetDosCwd(drive), 253 );
+        SendDlgItemMessage( hDlg, idStatic, WM_SETTEXT,
+                            0, (LPARAM)MAKE_SEGPTR(temp) );
+    } 
+    return ret;
 }
diff --git a/controls/menu.c b/controls/menu.c
index 63f424d..e820d18 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -57,7 +57,6 @@
 static HBITMAP hStdCheck = 0;
 static HBITMAP hStdMnArrow = 0;
 
-HMENU CopySysMenu();
 WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu);
 
 
@@ -102,6 +101,30 @@
 }
 
 
+/**********************************************************************
+ *           MENU_CopySysMenu
+ */
+static HMENU MENU_CopySysMenu(void)
+{
+    HMENU hMenu;
+    HGLOBAL handle;
+    POPUPMENU *menu;
+
+    if (!(handle = SYSRES_LoadResource( SYSRES_MENU_SYSMENU ))) return 0;
+    hMenu = LoadMenuIndirect( GlobalLock( handle ) );
+    SYSRES_FreeResource( handle );
+    if (!hMenu)
+    {
+	dprintf_menu(stddeb,"No SYSMENU\n");
+	return 0;
+    }
+    menu = (POPUPMENU*) USER_HEAP_LIN_ADDR(hMenu);
+    menu->wFlags |= MF_SYSMENU | MF_POPUP;
+    dprintf_menu(stddeb,"CopySysMenu hMenu="NPFMT" !\n", hMenu);
+    return hMenu;
+}
+
+
 /***********************************************************************
  *           MENU_IsInSysMenu
  *
@@ -1549,8 +1572,10 @@
     return AppendMenu(hMenu, wFlags & ~MF_APPEND, wItemID, lpNewItem);
   }
   if (wFlags & MF_DELETE) {
-    return DeleteMenu(hMenu, wFlags & MF_BYPOSITION ? nPos : wItemID, 
-		      wFlags & ~MF_DELETE);
+    /* FIXME: Word passes the item id in nPos and 0 or 0xffff as id */
+    /* for MF_DELETE. We should check the parameters for all others */
+    /* MF_* actions also (anybody got a doc on ChangeMenu?). */
+    return DeleteMenu(hMenu, nPos, wFlags & ~MF_DELETE);
   }
   if (wFlags & MF_CHANGE) {
     return ModifyMenu(hMenu, nPos, wFlags & ~MF_CHANGE, wItemID, lpNewItem);
@@ -2015,8 +2040,8 @@
     if (!wndPtr) return 0;
 
     if (!bRevert) return wndPtr->hSysMenu;
-    DestroyMenu(wndPtr->hSysMenu);
-    wndPtr->hSysMenu = CopySysMenu();
+    if (wndPtr->hSysMenu) DestroyMenu(wndPtr->hSysMenu);
+    wndPtr->hSysMenu = MENU_CopySysMenu();
     return wndPtr->hSysMenu;
 }
 
@@ -2181,30 +2206,6 @@
 
 
 /**********************************************************************
- *			CopySysMenu (Internal)
- */
-HMENU CopySysMenu()
-{
-    HMENU hMenu;
-    HGLOBAL handle;
-    LPPOPUPMENU menu;
-
-    if (!(handle = SYSRES_LoadResource( SYSRES_MENU_SYSMENU ))) return 0;
-    hMenu = LoadMenuIndirect( GlobalLock( handle ) );
-    SYSRES_FreeResource( handle );
-    if(!hMenu)
-    {
-	dprintf_menu(stddeb,"No SYSMENU\n");
-	return 0;
-    }
-    menu = (POPUPMENU*) USER_HEAP_LIN_ADDR(hMenu);
-    menu->wFlags |= MF_SYSMENU|MF_POPUP;
-    dprintf_menu(stddeb,"CopySysMenu hMenu="NPFMT" !\n", hMenu);
-    return hMenu;
-}
-
-
-/**********************************************************************
  *			ParseMenuResource (from Resource or Template)
  */
 WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu)
diff --git a/controls/scroll.c b/controls/scroll.c
index 3d7a67e..ff63e08 100644
--- a/controls/scroll.c
+++ b/controls/scroll.c
@@ -770,7 +770,7 @@
             if (lpCreat->style & SBS_SIZEBOX)
             {
                 fprintf( stdnimp, "Unimplemented style SBS_SIZEBOX.\n" );
-                return -1;
+                return 0;  /* FIXME */
             }
             
 	    if (lpCreat->style & SBS_VERT)
diff --git a/debugger/debug.l b/debugger/debug.l
index e6de8fc..50c66d7 100644
--- a/debugger/debug.l
+++ b/debugger/debug.l
@@ -10,6 +10,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include "debugger.h"
+#include "xmalloc.h"
 #include "y.tab.h"
 
 #ifdef USE_READLINE
@@ -202,7 +203,7 @@
 static int next_symbol;
 
 char * make_symbol(char * symbol){
-        return local_symbols[next_symbol++] = strdup(symbol);
+        return local_symbols[next_symbol++] = xstrdup(symbol);
 }
 
 void
diff --git a/debugger/hash.c b/debugger/hash.c
index 8a325c7..60be910 100644
--- a/debugger/hash.c
+++ b/debugger/hash.c
@@ -51,7 +51,7 @@
 
     new = (struct name_hash *) xmalloc(sizeof(struct name_hash));
     new->addr = *addr;
-    new->name = strdup(name);
+    new->name = xstrdup(name);
     new->next = NULL;
     hash = name_hash(name);
 
diff --git a/debugger/stack.c b/debugger/stack.c
index 9b4e09f..de54160 100644
--- a/debugger/stack.c
+++ b/debugger/stack.c
@@ -66,6 +66,10 @@
     if (SS_reg(DEBUG_context) == WINE_DATA_SELECTOR)  /* 32-bit mode */
     {
         addr.seg = 0;
+        fprintf(stderr,"%d ",frameno++);
+        addr.off = EIP_reg(DEBUG_context);
+        DEBUG_PrintAddress( &addr, 32 );
+        fprintf( stderr, "\n" );
         addr.off = EBP_reg(DEBUG_context);
         for (;;)
         {
@@ -87,7 +91,12 @@
           fprintf( stderr, "Not implemented: 32-bit backtrace on a different stack segment.\n" );
           return;
       }
-      addr.seg = SS_reg(DEBUG_context);
+      fprintf( stderr,"%d ", frameno++ );
+      addr.seg = cs;
+      addr.off = IP_reg(DEBUG_context);
+      DEBUG_PrintAddress( &addr, 16 );
+      fprintf( stderr, "\n" );
+      addr.seg = ss;
       addr.off = BP_reg(DEBUG_context) & ~1;
       for (;;)
       {
diff --git a/documentation/languages b/documentation/languages
new file mode 100644
index 0000000..e51262e
--- /dev/null
+++ b/documentation/languages
@@ -0,0 +1,64 @@
+This file documents the necessary procedure for adding a new language
+to the list of languages that Wine can display system menus and forms
+in.
+
+To add a new language you need to be able to translate the relatively
+few texts, of course.  You will need very little knowledge of
+programming, so you have almost no excuses for not adding your language,
+right?  We should easily be able to support 20 languages within a few
+months, get going!  Apart from re-compilation it'll take you about an
+hour.
+
+To add a new language to the list of languages that Wine can handle
+you must...
+
+1.  Edit resources/Makefile.in variable "LANGUAGES" to include a new
+    abbreviation for the language.
+
+2.  Edit ./wine.man (search for -language) to show the new language
+    abbreviation.
+
+3.  Edit misc/main.c variable "langNames" to contain the new language
+    abbreviation.  Also edit macro "USAGE" to show the new abbreviation.
+
+4.  Edit include/options.h enum "WINE_LANGUAGE" to have a member called
+    LANG_XX where XX is the new abbreviation.
+
+5.  Edit misc/ole2nls.c function "GetUserDefaultLCID" to contain an
+    extra case for your language.  The correct return values seem to
+    be a mystery, but don't worry.
+
+6.  Edit resources/sysrec.c to include "sysres_XX.h" where XX is the
+    abbreviation for your language.  (That file will be produced auto-
+    matically.)  Edit variable "SYSRES_Resources" to contain an entry
+    for your language.
+
+7.  Create a new file, resources/sysres_XX.rc, where XX is the
+    abbreviation that you chose.  Your best bet is to copy one of the
+    other *.rc files and start translating.  [Warning: the author of
+    this file does not know the details of the structure of these
+    files.  There seems to be no need to, however.]
+
+    In menus, the character "&" means that the next character will
+    be highlighted and that pressing that letter will select the item.
+    You should place these "&"s suitably for your language, not just
+    copy the positions from (say) English.  In particular, items within
+    one menu should have different highlighted letters.
+
+8.  Edit misc/ole2nls.c function "GetLocaleInfoA" to contain a case for
+    your language.
+
+9.  Re-configure, re-make dependencies, and re-make Wine.
+
+10. Check your new menus and forms; when they're ok, submit patches
+    for inclusion in the next Wine release, see file ./ANNOUNCE for
+    details about where to submit.
+
+
+January 1996
+Morten Welinder
+
+[I hope I got all the places where changes are needed.  If you see any
+place missing from the above list, submit a patch to this file please.
+Also note that re-organization of the source code might change the list
+of places.]
diff --git a/files/Makefile.in b/files/Makefile.in
new file mode 100644
index 0000000..5fee060
--- /dev/null
+++ b/files/Makefile.in
@@ -0,0 +1,14 @@
+TOPSRC = @top_srcdir@
+MODULE = files
+
+C_SRCS = \
+	directory.c \
+	dos_fs.c \
+	drive.c \
+	file.c
+
+all: $(MODULE).o
+
+@MAKE_RULES@
+
+### Dependencies:
diff --git a/files/directory.c b/files/directory.c
new file mode 100644
index 0000000..9de0c52
--- /dev/null
+++ b/files/directory.c
@@ -0,0 +1,245 @@
+/*
+ * DOS directories functions
+ *
+ * Copyright 1995 Alexandre Julliard
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "windows.h"
+#include "dos_fs.h"
+#include "drive.h"
+#include "file.h"
+#include "msdos.h"
+#include "xmalloc.h"
+#include "stddebug.h"
+#include "debug.h"
+
+#define MAX_PATH_ELEMENTS 20
+
+static char *DIR_WindowsDosDir;
+static char *DIR_WindowsUnixDir;
+static char *DIR_SystemDosDir;
+static char *DIR_SystemUnixDir;
+static char *DIR_TempDosDir;
+static char *DIR_TempUnixDir;
+
+static char *DIR_DosPath[MAX_PATH_ELEMENTS];  /* Path in DOS format */
+static char *DIR_UnixPath[MAX_PATH_ELEMENTS]; /* Path in Unix format */
+static int DIR_PathElements = 0;
+
+/***********************************************************************
+ *           DIR_GetPath
+ *
+ * Get a path name from the wine.ini file and make sure it is valid.
+ */
+static int DIR_GetPath( const char *keyname, const char *defval,
+                        char **dos_path, char **unix_path )
+{
+    char path[MAX_PATHNAME_LEN];
+    const char *dos_name ,*unix_name;
+    BYTE attr;
+
+    GetPrivateProfileString( "wine", keyname, defval,
+                             path, sizeof(path), WineIniFileName() );
+    if (!(unix_name = DOSFS_GetUnixFileName( path, TRUE )) ||
+        !FILE_Stat( unix_name, &attr, NULL, NULL, NULL ) ||
+        !(attr & FA_DIRECTORY))
+    {
+        fprintf(stderr, "Invalid path '%s' for %s directory\n", path, keyname);
+        return 0;
+    }
+    if (!(dos_name = DOSFS_GetDosTrueName( unix_name, TRUE )))
+    {
+        fprintf( stderr, "Could not get DOS name for %s directory '%s'\n",
+                 keyname, unix_name );
+        return 0;
+    }
+    *unix_path = xstrdup( unix_name );
+    *dos_path  = xstrdup( dos_name );
+    return 1;
+}
+
+
+/***********************************************************************
+ *           DIR_ParseWindowsPath
+ */
+void DIR_ParseWindowsPath( char *path )
+{
+    char *p;
+    const char *dos_name ,*unix_name;
+    BYTE attr;
+    int i;
+
+    for ( ; path && *path; path = p)
+    {
+        p = strchr( path, ';' );
+        if (p) while (*p == ';') *p++ = '\0';
+
+        if (DIR_PathElements >= MAX_PATH_ELEMENTS)
+        {
+            fprintf( stderr, "Warning: path has more than %d elements.\n",
+                     MAX_PATH_ELEMENTS );
+            break;
+        }
+        if (!(unix_name = DOSFS_GetUnixFileName( path, TRUE )) ||
+            !FILE_Stat( unix_name, &attr, NULL, NULL, NULL ) ||
+            !(attr & FA_DIRECTORY))
+        {
+            fprintf(stderr,"Warning: invalid dir '%s' in path, deleting it.\n",
+                    path );
+            continue;
+        }
+        if (!(dos_name = DOSFS_GetDosTrueName( unix_name, TRUE )))
+        {
+            fprintf( stderr, "Warning: could not get DOS name for '%s' in path, deleting it.\n",
+                     unix_name );
+            continue;
+        }
+        DIR_UnixPath[DIR_PathElements] = xstrdup( unix_name );
+        DIR_DosPath[DIR_PathElements]  = xstrdup( dos_name );
+        DIR_PathElements++;
+    }
+
+    if (debugging_dosfs)
+        for (i = 0; i < DIR_PathElements; i++)
+        {
+            dprintf_dosfs( stddeb, "Path[%d]: %s = %s\n",
+                           i, DIR_DosPath[i], DIR_UnixPath[i] );
+        }
+}
+
+
+/***********************************************************************
+ *           DIR_Init
+ */
+int DIR_Init(void)
+{
+    char path[MAX_PATHNAME_LEN];
+    int drive;
+    const char *cwd;
+
+    if (!getcwd( path, MAX_PATHNAME_LEN ))
+    {
+        perror( "Could not get current directory" );
+        return 0;
+    }
+    cwd = path;
+    if ((drive = DRIVE_FindDriveRoot( &cwd )) == -1)
+    {
+        fprintf( stderr, "Warning: could not find DOS drive for cwd %s; starting in windows directory.\n",
+                 cwd );
+    }
+    else
+    {
+        cwd = DOSFS_GetDosTrueName( path, TRUE );
+        DRIVE_SetCurrentDrive( drive );
+        DRIVE_Chdir( drive, cwd + 2 );
+    }
+
+    if (!(DIR_GetPath( "windows", "c:\\windows",
+                       &DIR_WindowsDosDir, &DIR_WindowsUnixDir ))) return 0;
+    if (!(DIR_GetPath( "system", "c:\\windows\\system",
+                       &DIR_SystemDosDir, &DIR_SystemUnixDir ))) return 0;
+    if (!(DIR_GetPath( "temp", "c:\\windows",
+                       &DIR_TempDosDir, &DIR_TempUnixDir ))) return 0;
+
+    if (drive == -1)
+    {
+        drive = DIR_WindowsDosDir[0] - 'A';
+        DRIVE_SetCurrentDrive( drive );
+        DRIVE_Chdir( drive, DIR_WindowsDosDir + 2 );
+    }
+
+    GetPrivateProfileString( "wine", "path", "c:\\windows;c:\\windows\\system",
+                             path, sizeof(path), WineIniFileName() );
+    DIR_ParseWindowsPath( path );
+
+    dprintf_dosfs( stddeb, "WindowsDir = %s\nSystemDir  = %s\n",
+                   DIR_WindowsDosDir, DIR_SystemDosDir );
+    dprintf_dosfs( stddeb, "TempDir    = %s\nCwd        = %c:\\%s\n",
+                   DIR_TempDosDir, 'A' + drive, DRIVE_GetDosCwd( drive ) );
+    return 1;
+}
+
+
+/***********************************************************************
+ *           DIR_GetTempDosDir
+ */
+UINT DIR_GetTempDosDir( LPSTR path, UINT count )
+{
+    if (path) lstrcpyn( path, DIR_TempDosDir, count );
+    return strlen( DIR_TempDosDir );
+}
+
+
+/***********************************************************************
+ *           DIR_GetTempUnixDir
+ */
+UINT DIR_GetTempUnixDir( LPSTR path, UINT count )
+{
+    if (path) lstrcpyn( path, DIR_TempUnixDir, count );
+    return strlen( DIR_TempUnixDir );
+}
+
+
+/***********************************************************************
+ *           DIR_GetWindowsUnixDir
+ */
+UINT DIR_GetWindowsUnixDir( LPSTR path, UINT count )
+{
+    if (path) lstrcpyn( path, DIR_WindowsUnixDir, count );
+    return strlen( DIR_WindowsUnixDir );
+}
+
+
+/***********************************************************************
+ *           DIR_GetSystemUnixDir
+ */
+UINT DIR_GetSystemUnixDir( LPSTR path, UINT count )
+{
+    if (path) lstrcpyn( path, DIR_SystemUnixDir, count );
+    return strlen( DIR_SystemUnixDir );
+}
+
+
+/***********************************************************************
+ *           DIR_GetDosPath
+ */
+UINT DIR_GetDosPath( int element, LPSTR path, UINT count )
+{
+    if ((element < 0) || (element >= DIR_PathElements)) return 0;
+    if (path) lstrcpyn( path, DIR_DosPath[element], count );
+    return strlen( DIR_DosPath[element] );
+}
+
+
+/***********************************************************************
+ *           GetTempDrive   (KERNEL.92)
+ */
+BYTE GetTempDrive( BYTE ignored )
+{
+    return DIR_TempDosDir[0];
+}
+
+
+/***********************************************************************
+ *           GetWindowsDirectory   (KERNEL.134)
+ */
+UINT GetWindowsDirectory( LPSTR path, UINT count )
+{
+    if (path) lstrcpyn( path, DIR_WindowsDosDir, count );
+    return strlen( DIR_WindowsDosDir );
+}
+
+
+/***********************************************************************
+ *           GetSystemDirectory   (KERNEL.135)
+ */
+UINT GetSystemDirectory( LPSTR path, UINT count )
+{
+    if (path) lstrcpyn( path, DIR_SystemDosDir, count );
+    return strlen( DIR_SystemDosDir );
+}
diff --git a/files/dos_fs.c b/files/dos_fs.c
new file mode 100644
index 0000000..6f4e921
--- /dev/null
+++ b/files/dos_fs.c
@@ -0,0 +1,689 @@
+/*
+ * DOS file system functions
+ *
+ * Copyright 1993 Erik Bos
+ * Copyright 1996 Alexandre Julliard
+ */
+
+#include <ctype.h>
+#include <dirent.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <time.h>
+#ifdef __svr4__
+#include <sys/statfs.h>
+#endif
+
+#include "windows.h"
+#include "dos_fs.h"
+#include "drive.h"
+#include "file.h"
+#include "msdos.h"
+#include "stddebug.h"
+#include "debug.h"
+
+/* Chars we don't want to see in DOS file names */
+#define INVALID_DOS_CHARS  "*?<>|\"+=,; "
+
+static const char *DOSFS_Devices[][2] =
+{
+    { "CON",  "" },
+    { "PRN",  "" },
+    { "NUL",  "/dev/null" },
+    { "AUX",  "" },
+    { "LPT1", "" },
+    { "LPT2", "" },
+    { "LPT3", "" },
+    { "LPT4", "" },
+    { "COM1", "" },
+    { "COM2", "" },
+    { "COM3", "" },
+    { "COM4", "" }
+};
+
+#define GET_DRIVE(path) \
+    (((path)[1] == ':') ? toupper((path)[0]) - 'A' : DOSFS_CurDrive)
+
+    /* DOS extended error status */
+WORD DOS_ExtendedError;
+BYTE DOS_ErrorClass;
+BYTE DOS_ErrorAction;
+BYTE DOS_ErrorLocus;
+
+
+/***********************************************************************
+ *           DOSFS_ValidDOSName
+ *
+ * Return 1 if Unix file 'name' is also a valid MS-DOS name
+ * (i.e. contains only valid DOS chars, lower-case only, fits in 8.3 format).
+ * File name can be terminated by '\0', '\\' or '/'.
+ */
+static int DOSFS_ValidDOSName( const char *name )
+{
+    static const char invalid_chars[] = INVALID_DOS_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    const char *p = name;
+    int len = 0;
+
+    if (*p == '.')
+    {
+        /* Check for "." and ".." */
+        p++;
+        if (*p == '.') p++;
+        /* All other names beginning with '.' are invalid */
+        return (IS_END_OF_NAME(*p));
+    }
+    while (!IS_END_OF_NAME(*p))
+    {
+        if (strchr( invalid_chars, *p )) return 0;  /* Invalid char */
+        if (*p == '.') break;  /* Start of the extension */
+        if (++len > 8) return 0;  /* Name too long */
+        p++;
+    }
+    if (*p != '.') return 1;  /* End of name */
+    p++;
+    if (IS_END_OF_NAME(*p)) return 0;  /* Empty extension not allowed */
+    len = 0;
+    while (!IS_END_OF_NAME(*p))
+    {
+        if (strchr( invalid_chars, *p )) return 0;  /* Invalid char */
+        if (*p == '.') return 0;  /* Second extension not allowed */
+        if (++len > 3) return 0;  /* Extension too long */
+        p++;
+    }
+    return 1;
+}
+
+
+/***********************************************************************
+ *           DOSFS_CheckDotDot
+ *
+ * Remove all '.' and '..' at the beginning of 'name'.
+ */
+static const char * DOSFS_CheckDotDot( const char *name, char *buffer,
+                                       char sep , int *len )
+{
+    char *p = buffer + strlen(buffer);
+
+    while (*name == '.')
+    {
+        if (IS_END_OF_NAME(name[1]))
+        {
+            name++;
+            while ((*name == '\\') || (*name == '/')) name++;
+        }
+        else if ((name[1] == '.') && IS_END_OF_NAME(name[2]))
+        {
+            name += 2;
+            while ((*name == '\\') || (*name == '/')) name++;
+            while ((p > buffer) && (*p != sep)) { p--; (*len)++; }
+            *p = '\0';  /* Remove trailing separator */
+        }
+        else break;
+    }
+    return name;
+}
+
+
+/***********************************************************************
+ *           DOSFS_ToDosFCBFormat
+ *
+ * Convert a file name to DOS FCB format (8+3 chars, padded with blanks),
+ * expanding wild cards and converting to upper-case in the process.
+ * File name can be terminated by '\0', '\\' or '/'.
+ * Return NULL if the name is not a valid DOS name.
+ */
+const char *DOSFS_ToDosFCBFormat( const char *name )
+{
+    static const char invalid_chars[] = INVALID_DOS_CHARS;
+    static char buffer[12];
+    const char *p = name;
+    int i;
+
+    /* Check for "." and ".." */
+    if (*p == '.')
+    {
+        p++;
+        strcpy( buffer, ".          " );
+        if (*p == '.') p++;
+        return (!*p || (*p == '/') || (*p == '\\')) ? buffer : NULL;
+    }
+
+    for (i = 0; i < 8; i++)
+    {
+        switch(*p)
+        {
+        case '\0':
+        case '\\':
+        case '/':
+        case '.':
+            buffer[i] = ' ';
+            break;
+        case '?':
+            p++;
+            /* fall through */
+        case '*':
+            buffer[i] = '?';
+            break;
+        default:
+            if (strchr( invalid_chars, *p )) return NULL;
+            buffer[i] = toupper(*p);
+            p++;
+            break;
+        }
+    }
+
+    if (*p == '*')
+    {
+        /* Skip all chars after wildcard up to first dot */
+        while (*p && (*p != '/') && (*p != '\\') && (*p != '.')) p++;
+    }
+    else
+    {
+        /* Check if name too long */
+        if (*p && (*p != '/') && (*p != '\\') && (*p != '.')) return NULL;
+    }
+    if (*p == '.') p++;  /* Skip dot */
+
+    for (i = 8; i < 11; i++)
+    {
+        switch(*p)
+        {
+        case '\0':
+        case '\\':
+        case '/':
+            buffer[i] = ' ';
+            break;
+        case '.':
+            return NULL;  /* Second extension not allowed */
+        case '?':
+            p++;
+            /* fall through */
+        case '*':
+            buffer[i] = '?';
+            break;
+        default:
+            if (strchr( invalid_chars, *p )) return NULL;
+            buffer[i] = toupper(*p);
+            p++;
+            break;
+        }
+    }
+    buffer[11] = '\0';
+    return buffer;
+}
+
+
+/***********************************************************************
+ *           DOSFS_ToDosDTAFormat
+ *
+ * Convert a file name from FCB to DTA format (name.ext, null-terminated)
+ * converting to upper-case in the process.
+ * File name can be terminated by '\0', '\\' or '/'.
+ * Return NULL if the name is not a valid DOS name.
+ */
+const char *DOSFS_ToDosDTAFormat( const char *name )
+{
+    static char buffer[13];
+    char *p;
+
+    memcpy( buffer, name, 8 );
+    for (p = buffer + 8; (p > buffer) && (p[-1] == ' '); p--);
+    *p++ = '.';
+    memcpy( p, name + 8, 3 );
+    for (p += 3; p[-1] == ' '; p--);
+    if (p[-1] == '.') p--;
+    *p = '\0';
+    return buffer;
+}
+
+
+/***********************************************************************
+ *           DOSFS_Match
+ *
+ * Check a DOS file name against a mask (both in FCB format).
+ */
+static int DOSFS_Match( const char *mask, const char *name )
+{
+    int i;
+    for (i = 11; i > 0; i--, mask++, name++)
+        if ((*mask != '?') && (*mask != *name)) return 0;
+    return 1;
+}
+
+
+/***********************************************************************
+ *           DOSFS_ToDosDateTime
+ *
+ * Convert a Unix time in the DOS date/time format.
+ */
+void DOSFS_ToDosDateTime( time_t *unixtime, WORD *pDate, WORD *pTime )
+{
+    struct tm *tm = localtime( unixtime );
+    if (pTime)
+        *pTime = (tm->tm_hour << 11) + (tm->tm_min << 5) + (tm->tm_sec / 2);
+    if (pDate)
+        *pDate = ((tm->tm_year - 80) << 9) + (tm->tm_mon << 5) + tm->tm_mday;
+}
+
+
+/***********************************************************************
+ *           DOSFS_Hash
+ *
+ * Transform a Unix file name into a hashed DOS name. If the name is a valid
+ * DOS name, it is converted to upper-case; otherwise it is replaced by a
+ * hashed version that fits in 8.3 format.
+ * File name can be terminated by '\0', '\\' or '/'.
+ */
+static const char *DOSFS_Hash( const char *name, int dir_format )
+{
+    static const char invalid_chars[] = INVALID_DOS_CHARS "~.";
+    static const char hash_chars[32] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
+
+    static char buffer[13];
+    const char *p, *ext;
+    char *dst;
+    unsigned short hash;
+    int i;
+
+    if (dir_format) strcpy( buffer, "           " );
+
+    if (DOSFS_ValidDOSName( name ))
+    {
+        /* Check for '.' and '..' */
+        if (*name == '.')
+        {
+            buffer[0] = '.';
+            if (!dir_format) buffer[1] = buffer[2] = '\0';
+            if (name[1] == '.') buffer[1] = '.';
+            return buffer;
+        }
+
+        /* Simply copy the name, converting to uppercase */
+
+        for (dst = buffer; !IS_END_OF_NAME(*name) && (*name != '.'); name++)
+            *dst++ = toupper(*name);
+        if (*name == '.')
+        {
+            if (dir_format) dst = buffer + 8;
+            else *dst++ = '.';
+            for (name++; !IS_END_OF_NAME(*name); name++)
+                *dst++ = toupper(*name);
+        }
+        if (!dir_format) *dst = '\0';
+    }
+    else
+    {
+        /* Compute the hash code of the file name */
+        /* If you know something about hash functions, feel free to */
+        /* insert a better algorithm here... */
+        for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++)
+            hash = (hash << 3) ^ (hash >> 5) ^ *p ^ (p[1] << 8);
+        hash = (hash << 3) ^ (hash >> 5) ^ *p;  /* Last character */
+        
+        /* Find last dot for start of the extension */
+        for (p = name+1, ext = NULL; !IS_END_OF_NAME(*p); p++)
+            if (*p == '.') ext = p;
+        if (ext && IS_END_OF_NAME(ext[1]))
+            ext = NULL;  /* Empty extension ignored */
+
+        /* Copy first 4 chars, replacing invalid chars with '_' */
+        for (i = 4, p = name, dst = buffer; i > 0; i--, p++)
+        {
+            if (IS_END_OF_NAME(*p) || (p == ext)) break;
+            *dst++ = strchr( invalid_chars, *p ) ? '_' : toupper(*p);
+        }
+        /* Pad to 5 chars with '~' */
+        while (i-- >= 0) *dst++ = '~';
+
+        /* Insert hash code converted to 3 ASCII chars */
+        *dst++ = hash_chars[(hash >> 10) & 0x1f];
+        *dst++ = hash_chars[(hash >> 5) & 0x1f];
+        *dst++ = hash_chars[hash & 0x1f];
+
+        /* Copy the first 3 chars of the extension (if any) */
+        if (ext)
+        {
+            if (!dir_format) *dst++ = '.';
+            for (i = 3, ext++; (i > 0) && !IS_END_OF_NAME(*ext); i--, ext++)
+                *dst++ = toupper(*ext);
+        }
+        if (!dir_format) *dst = '\0';
+    }
+    return buffer;
+}
+
+
+/***********************************************************************
+ *           DOSFS_FindUnixName
+ *
+ * Find the Unix file name in a given directory that corresponds to
+ * a file name (either in Unix or DOS format).
+ * File name can be terminated by '\0', '\\' or '/'.
+ * Return 1 if OK, 0 if no file name matches.
+ */
+static int DOSFS_FindUnixName( const char *path, const char *name,
+                               char *buffer, int maxlen )
+{
+    DIR *dir;
+    struct dirent *dirent;
+
+    const char *dos_name = DOSFS_ToDosFCBFormat( name );
+    const char *p = strchr( name, '/' );
+    int len = p ? (int)(p - name) : strlen(name);
+
+    dprintf_dosfs( stddeb, "DOSFS_FindUnixName: %s %s\n", path, name );
+
+    if ((p = strchr( name, '\\' ))) len = MIN( (int)(p - name), len );
+
+    if (!(dir = opendir( path )))
+    {
+        dprintf_dosfs( stddeb, "DOSFS_FindUnixName(%s,%s): can't open dir\n",
+                       path, name );
+        return 0;
+    }
+    while ((dirent = readdir( dir )) != NULL)
+    {
+        /* Check against Unix name */
+        if ((len == strlen(dirent->d_name) &&
+             !memcmp( dirent->d_name, name, len ))) break;
+        if (dos_name)
+        {
+            /* Check against hashed DOS name */
+            const char *hash_name = DOSFS_Hash( dirent->d_name, TRUE );
+            if (!strcmp( dos_name, hash_name )) break;
+        }
+    }
+    if (dirent) lstrcpyn( buffer, dirent->d_name, maxlen );
+    closedir( dir );
+    dprintf_dosfs( stddeb, "DOSFS_FindUnixName(%s,%s) -> %s\n",
+                   path, name, dirent ? buffer : "** Not found **" );
+    return (dirent != NULL);
+}
+
+
+/***********************************************************************
+ *           DOSFS_IsDevice
+ *
+ * Check if a DOS file name represents a DOS device. Returns the name
+ * of the associated Unix device, or NULL if not found.
+ */
+const char *DOSFS_IsDevice( const char *name )
+{
+    int i;
+    const char *p;
+
+    if (name[1] == ':') name += 2;
+    if ((p = strrchr( name, '/' ))) name = p + 1;
+    if ((p = strrchr( name, '\\' ))) name = p + 1;
+    for (i = 0; i < sizeof(DOSFS_Devices)/sizeof(DOSFS_Devices[0]); i++)
+    {
+        const char *dev = DOSFS_Devices[i][0];
+        if (!lstrncmpi( dev, name, strlen(dev) ))
+        {
+            p = name + strlen( dev );
+            if (*p == ':') p++;
+            if (!*p || (*p == '.')) return DOSFS_Devices[i][1];
+        }
+    }
+    return NULL;
+}
+
+
+/***********************************************************************
+ *           DOSFS_GetUnixFileName
+ *
+ * Convert a file name (DOS or mixed DOS/Unix format) to a valid Unix name.
+ * Return NULL if one of the path components does not exist. The last path
+ * component is only checked if 'check_last' is non-zero.
+ */
+const char * DOSFS_GetUnixFileName( const char * name, int check_last )
+{
+    static char buffer[MAX_PATHNAME_LEN];
+    int drive, len, found;
+    char *p, *root;
+
+    dprintf_dosfs( stddeb, "DOSFS_GetUnixFileName: %s\n", name );
+    if (name[1] == ':')
+    {
+        drive = toupper(name[0]) - 'A';
+        name += 2;
+    }
+    else if (name[0] == '/') /* Absolute Unix path? */
+    {
+        if ((drive = DRIVE_FindDriveRoot( &name )) == -1)
+        {
+            fprintf( stderr, "Warning: %s not accessible from a DOS drive\n",
+                     name );
+            /* Assume it really was a DOS name */
+            drive = DRIVE_GetCurrentDrive();            
+        }
+    }
+    else drive = DRIVE_GetCurrentDrive();
+
+    if (!DRIVE_IsValid(drive))
+    {
+        DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk );
+        return NULL;
+    }
+    lstrcpyn( buffer, DRIVE_GetRoot(drive), MAX_PATHNAME_LEN );
+    if (buffer[1]) root = buffer + strlen(buffer);
+    else root = buffer;  /* root directory */
+
+    if ((*name == '\\') || (*name == '/'))
+    {
+        while ((*name == '\\') || (*name == '/')) name++;
+    }
+    else
+    {
+        lstrcpyn( root + 1, DRIVE_GetUnixCwd(drive),
+                  MAX_PATHNAME_LEN - (int)(root - buffer) - 1 );
+        if (root[1]) *root = '/';
+    }
+
+    p = buffer[1] ? buffer + strlen(buffer) : buffer;
+    len = MAX_PATHNAME_LEN - strlen(buffer);
+    found = 1;
+    while (*name && found)
+    {
+        const char *newname = DOSFS_CheckDotDot( name, root, '/', &len );
+        if (newname != name)
+        {
+            p = root + strlen(root);
+            name = newname;
+            continue;
+        }
+        if (len <= 1)
+        {
+            DOS_ERROR( ER_PathNotFound, EC_NotFound, SA_Abort, EL_Disk );
+            return NULL;
+        }
+        if ((found = DOSFS_FindUnixName( buffer, name, p+1, len-1 )))
+        {
+            *p = '/';
+            len -= strlen(p);
+            p += strlen(p);
+            while (!IS_END_OF_NAME(*name)) name++;
+        }
+        else
+        {
+            *p++ = '/';
+            for (len--; !IS_END_OF_NAME(*name) && (len > 1); name++, len--)
+                *p++ = tolower(*name);
+            *p = '\0';
+        }
+        while ((*name == '\\') || (*name == '/')) name++;
+    }
+    if (!found)
+    {
+        if (*name)  /* Not last */
+        {
+            DOS_ERROR( ER_PathNotFound, EC_NotFound, SA_Abort, EL_Disk );
+            return NULL;
+        }
+        if (check_last)
+        {
+            DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
+            return NULL;
+        }
+    }
+    if (!buffer[0]) strcpy( buffer, "/" );
+    dprintf_dosfs( stddeb, "DOSFS_GetUnixFileName: returning %s\n", buffer );
+    return buffer;
+}
+
+
+/***********************************************************************
+ *           DOSFS_GetDosTrueName
+ *
+ * Convert a file name (DOS or Unix format) to a complete DOS name.
+ * Return NULL if the path name is invalid or too long.
+ * The unix_format flag is a hint that the file name is in Unix format.
+ */
+const char * DOSFS_GetDosTrueName( const char *name, int unix_format )
+{
+    static char buffer[MAX_PATHNAME_LEN];
+    int drive, len;
+    char *p;
+
+    dprintf_dosfs( stddeb, "DOSFS_GetDosTrueName(%s,%d)\n", name, unix_format);
+    if (name[1] == ':')
+    {
+        drive = toupper(name[0]) - 'A';
+        name += 2;
+    }
+    else if (name[0] == '/') /* Absolute Unix path? */
+    {
+        if ((drive = DRIVE_FindDriveRoot( &name )) == -1)
+        {
+            fprintf( stderr, "Warning: %s not accessible from a DOS drive\n",
+                     name );
+            /* Assume it really was a DOS name */
+            drive = DRIVE_GetCurrentDrive();            
+        }
+    }
+    else drive = DRIVE_GetCurrentDrive();
+
+    if (!DRIVE_IsValid(drive))
+    {
+        DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk );
+        return NULL;
+    }
+
+    strcpy( buffer, "A:\\" );
+    buffer[0] += drive;
+    if ((name[0] == '\\') || (name[0] == '/'))
+    {
+        while ((*name == '\\') || (*name == '/')) name++;
+        p = buffer + 2;
+    }
+    else
+    {
+        lstrcpyn( buffer + 3, DRIVE_GetDosCwd(drive), len - 3 );
+        if (buffer[3]) p = buffer + strlen(buffer);
+        else p = buffer + 2;
+    }
+    len = MAX_PATHNAME_LEN - (int)(p - buffer);
+
+    while (*name)
+    {
+        const char *newname = DOSFS_CheckDotDot( name, buffer+2, '\\', &len );
+        if (newname != name)
+        {
+            p = buffer + strlen(buffer);
+            name = newname;
+            continue;
+        }
+        if (len <= 1)
+        {
+            DOS_ERROR( ER_PathNotFound, EC_NotFound, SA_Abort, EL_Disk );
+            return NULL;
+        }
+        *p++ = '\\';
+        if (unix_format)  /* Hash it into a DOS name */
+        {
+            lstrcpyn( p, DOSFS_Hash( name, FALSE ), len );
+            len -= strlen(p);
+            p += strlen(p);
+            while (!IS_END_OF_NAME(*name)) name++;
+        }
+        else  /* Already DOS format, simply upper-case it */
+        {
+            while (!IS_END_OF_NAME(*name) && (len > 1))
+            {
+                *p++ = toupper(*name);
+                name++;
+                len--;
+            }
+        }
+        while ((*name == '\\') || (*name == '/')) name++;
+    }
+    *p = '\0';
+    if (!buffer[2])
+    {
+        buffer[2] = '\\';
+        buffer[3] = '\0';
+    }
+    dprintf_dosfs( stddeb, "DOSFS_GetDosTrueName: returning %s\n", buffer );
+    return buffer;
+}
+
+
+/***********************************************************************
+ *           DOSFS_FindNext
+ *
+ * Find the next matching file. Return the number of entries read to find
+ * the matching one, or 0 if no more entries.
+ */
+int DOSFS_FindNext( const char *path, const char *mask, int drive,
+                    BYTE attr, int skip, DOS_DIRENT *entry )
+{
+    DIR *dir;
+    struct dirent *dirent;
+    int count = 0;
+    char buffer[MAX_PATHNAME_LEN], *p;
+    const char *hash_name;
+    
+    if ((attr & ~(FA_UNUSED | FA_ARCHIVE | FA_RDONLY)) == FA_LABEL)
+    {
+        time_t now = time(NULL);
+        if (skip) return 0;
+        strcpy( entry->name, DRIVE_GetLabel( drive ) );
+        entry->attr = FA_LABEL;
+        entry->size = 0;
+        DOSFS_ToDosDateTime( &now, &entry->date, &entry->time );
+        return 1;
+    }
+
+    if (!(dir = opendir( path ))) return 0;
+    strcpy( buffer, path );
+    strcat( buffer, "/" );
+    p = buffer + strlen(buffer);
+    attr |= FA_UNUSED | FA_ARCHIVE | FA_RDONLY;
+
+    while ((dirent = readdir( dir )) != NULL)
+    {
+        if (skip-- > 0) continue;
+        count++;
+        hash_name = DOSFS_Hash( dirent->d_name, TRUE );
+        if (!DOSFS_Match( mask, hash_name )) continue;
+        strcpy( p, dirent->d_name );
+
+        if (!FILE_Stat( buffer, &entry->attr, &entry->size,
+                        &entry->date, &entry->time ))
+        {
+            fprintf( stderr, "DOSFS_FindNext: can't stat %s\n", buffer );
+            continue;
+        }
+        if (entry->attr & ~attr) continue;
+        strcpy( entry->name, hash_name );
+        lstrcpyn( entry->unixname, dirent->d_name, sizeof(entry->unixname) );
+        dprintf_dosfs( stddeb, "DOSFS_FindNext: returning %s %02x %ld\n",
+                       entry->name, entry->attr, entry->size );
+        closedir( dir );
+        return count;
+    }
+    closedir( dir );
+    return 0;  /* End of directory */
+}
diff --git a/files/drive.c b/files/drive.c
new file mode 100644
index 0000000..ae2558d
--- /dev/null
+++ b/files/drive.c
@@ -0,0 +1,349 @@
+/*
+ * DOS drive handling functions
+ *
+ * Copyright 1993 Erik Bos
+ * Copyright 1996 Alexandre Julliard
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "windows.h"
+#include "dos_fs.h"
+#include "drive.h"
+#include "file.h"
+#include "msdos.h"
+#include "task.h"
+#include "xmalloc.h"
+#include "stddebug.h"
+#include "debug.h"
+
+typedef struct
+{
+    char *root;      /* root dir in Unix format without trailing '/' */
+    char *dos_cwd;   /* cwd in DOS format without leading or trailing '\' */
+    char *unix_cwd;  /* cwd in Unix format without leading or trailing '/' */
+    char  label[12]; /* drive label */
+    DWORD serial;    /* drive serial number */
+    WORD  type;      /* drive type */
+    BYTE  disabled;  /* disabled flag */
+} DOSDRIVE;
+
+static DOSDRIVE DOSDrives[MAX_DOS_DRIVES];
+static int DRIVE_CurDrive = 0;
+
+static HTASK DRIVE_LastTask = 0;
+
+/***********************************************************************
+ *           DRIVE_Init
+ */
+int DRIVE_Init(void)
+{
+    int i, count = 0;
+    char drive[2] = "A";
+    char path[MAX_PATHNAME_LEN];
+    char *p;
+
+    for (i = 0; i < MAX_DOS_DRIVES; i++, drive[0]++)
+    {
+        GetPrivateProfileString( "drives", drive, "",
+                                 path, sizeof(path)-1, WineIniFileName() );
+        if (path[0])
+        {
+            p = path + strlen(path) - 1;
+            while ((p > path) && ((*p == '/') || (*p == '\\'))) *p-- = '\0';
+            DOSDrives[i].root     = xstrdup( path );
+            DOSDrives[i].dos_cwd  = xstrdup( "" );
+            DOSDrives[i].unix_cwd = xstrdup( "" );
+            sprintf( DOSDrives[i].label, "DRIVE-%c    ", drive[0] );
+            DOSDrives[i].serial   = 0x12345678;
+            DOSDrives[i].type     = (i < 2) ? DRIVE_REMOVABLE : DRIVE_FIXED;
+            DOSDrives[i].disabled = 0;
+            count++;
+        }
+        dprintf_dosfs( stddeb, "Drive %c -> %s\n", 'A' + i,
+                       path[0] ? path : "** None **" );
+    }
+
+    if (!count) 
+    {
+        fprintf( stderr, "Warning: no valid DOS drive found\n" );
+        /* Create a C drive pointing to Unix root dir */
+        DOSDrives[i].root     = xstrdup( "/" );
+        DOSDrives[i].dos_cwd  = xstrdup( "" );
+        DOSDrives[i].unix_cwd = xstrdup( "" );
+        sprintf( DOSDrives[i].label, "DRIVE-%c    ", drive[0] );
+        DOSDrives[i].serial   = 0x12345678;
+        DOSDrives[i].type     = DRIVE_FIXED;
+        DOSDrives[i].disabled = 0;
+    }
+
+    /* Make the first hard disk the current drive */
+    for (i = 0; i < MAX_DOS_DRIVES; i++, drive[0]++)
+    {
+        if (DOSDrives[i].root && !DOSDrives[i].disabled &&
+            DOSDrives[i].type != DRIVE_REMOVABLE)
+        {
+            DRIVE_CurDrive = i;
+            break;
+        }
+    }
+    return 1;
+}
+
+
+/***********************************************************************
+ *           DRIVE_IsValid
+ */
+int DRIVE_IsValid( int drive )
+{
+    if ((drive < 0) || (drive >= MAX_DOS_DRIVES)) return 0;
+    return (DOSDrives[drive].root && !DOSDrives[drive].disabled);
+}
+
+
+/***********************************************************************
+ *           DRIVE_GetCurrentDrive
+ */
+int DRIVE_GetCurrentDrive(void)
+{
+    TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() );
+    if (pTask && (pTask->curdrive & 0x80)) return pTask->curdrive & ~0x80;
+    return DRIVE_CurDrive;
+}
+
+
+/***********************************************************************
+ *           DRIVE_SetCurrentDrive
+ */
+int DRIVE_SetCurrentDrive( int drive )
+{
+    TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() );
+    if (!DRIVE_IsValid( drive ))
+    {
+        DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk );
+        return 0;
+    }
+    dprintf_dosfs( stddeb, "DRIVE_SetCurrentDrive: %c:\n", 'A' + drive );
+    DRIVE_CurDrive = drive;
+    if (pTask) pTask->curdrive = drive | 0x80;
+    return 1;
+}
+
+
+/***********************************************************************
+ *           DRIVE_FindDriveRoot
+ *
+ * Find a drive for which the root matches the begginning of the given path.
+ * This can be used to translate a Unix path into a drive + DOS path.
+ * Return value is the drive, or -1 on error. On success, path is modified
+ * to point to the beginning of the DOS path.
+ * FIXME: this only does a textual comparison of the path names, and won't
+ *        work well in the presence of symbolic links.
+ */
+int DRIVE_FindDriveRoot( const char **path )
+{
+    int drive;
+    const char *p1, *p2;
+
+    dprintf_dosfs( stddeb, "DRIVE_FindDriveRoot: searching '%s'\n", *path );
+    for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
+    {
+        if (!DOSDrives[drive].root || DOSDrives[drive].disabled) continue;
+        p1 = *path;
+        p2 = DOSDrives[drive].root;
+        dprintf_dosfs( stddeb, "DRIVE_FindDriveRoot: checking %c: '%s'\n",
+                       'A' + drive, p2 );
+        for (;;)
+        {
+            while ((*p1 == '\\') || (*p1 == '/')) p1++;
+            while (*p2 == '/') p2++;
+            while ((*p1 == *p2) && (*p2) && (*p2 != '/')) p1++, p2++;
+            if (!*p2)
+            {
+                if (IS_END_OF_NAME(*p1)) /* OK, found it */
+                {
+                    *path = p1;
+                    return drive;
+                }
+            }
+            else if (*p2 == '/')
+            {
+                if (IS_END_OF_NAME(*p1))
+                    continue;  /* Go to next path element */
+            }
+            break;  /* No match, go to next drive */
+        }
+    }
+    return -1;
+}
+
+
+/***********************************************************************
+ *           DRIVE_GetRoot
+ */
+const char * DRIVE_GetRoot( int drive )
+{
+    if (!DRIVE_IsValid( drive )) return NULL;
+    return DOSDrives[drive].root;
+}
+
+
+/***********************************************************************
+ *           DRIVE_GetDosCwd
+ */
+const char * DRIVE_GetDosCwd( int drive )
+{
+    TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() );
+    if (!DRIVE_IsValid( drive )) return NULL;
+
+    /* Check if we need to change the directory to the new task. */
+    if (pTask && (pTask->curdrive & 0x80) &&    /* The task drive is valid */
+        ((pTask->curdrive & ~0x80) == drive) && /* and it's the one we want */
+        (DRIVE_LastTask != GetCurrentTask()))   /* and the task changed */
+    {
+        /* Perform the task-switch */
+        if (!DRIVE_Chdir( drive, pTask->curdir )) DRIVE_Chdir( drive, "\\" );
+        DRIVE_LastTask = GetCurrentTask();
+    }
+    return DOSDrives[drive].dos_cwd;
+}
+
+
+/***********************************************************************
+ *           DRIVE_GetUnixCwd
+ */
+const char * DRIVE_GetUnixCwd( int drive )
+{
+    TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() );
+    if (!DRIVE_IsValid( drive )) return NULL;
+
+    /* Check if we need to change the directory to the new task. */
+    if (pTask && (pTask->curdrive & 0x80) &&    /* The task drive is valid */
+        ((pTask->curdrive & ~0x80) == drive) && /* and it's the one we want */
+        (DRIVE_LastTask != GetCurrentTask()))   /* and the task changed */
+    {
+        /* Perform the task-switch */
+        if (!DRIVE_Chdir( drive, pTask->curdir )) DRIVE_Chdir( drive, "\\" );
+        DRIVE_LastTask = GetCurrentTask();
+    }
+    return DOSDrives[drive].unix_cwd;
+}
+
+
+/***********************************************************************
+ *           DRIVE_GetLabel
+ */
+const char * DRIVE_GetLabel( int drive )
+{
+    if (!DRIVE_IsValid( drive )) return NULL;
+    return DOSDrives[drive].label;
+}
+
+
+/***********************************************************************
+ *           DRIVE_GetSerialNumber
+ */
+DWORD DRIVE_GetSerialNumber( int drive )
+{
+    if (!DRIVE_IsValid( drive )) return 0;
+    return DOSDrives[drive].serial;
+}
+
+
+/***********************************************************************
+ *           DRIVE_SetSerialNumber
+ */
+int DRIVE_SetSerialNumber( int drive, DWORD serial )
+{
+    if (!DRIVE_IsValid( drive )) return 0;
+    DOSDrives[drive].serial = serial;
+    return 1;
+}
+
+
+/***********************************************************************
+ *           DRIVE_Chdir
+ */
+int DRIVE_Chdir( int drive, const char *path )
+{
+    char buffer[MAX_PATHNAME_LEN];
+    const char *unix_cwd, *dos_cwd;
+    BYTE attr;
+    TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() );
+
+    dprintf_dosfs( stddeb, "DRIVE_Chdir(%c:,%s)\n", 'A' + drive, path );
+    strcpy( buffer, "A:" );
+    buffer[0] += drive;
+    lstrcpyn( buffer + 2, path, sizeof(buffer) - 2 );
+
+    if (!(unix_cwd = DOSFS_GetUnixFileName( buffer, TRUE ))) return 0;
+    if (!FILE_Stat( unix_cwd, &attr, NULL, NULL, NULL )) return 0;
+    if (!(attr & FA_DIRECTORY))
+    {
+        DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
+        return 0;
+    }
+    unix_cwd += strlen( DOSDrives[drive].root );
+    while (*unix_cwd == '/') unix_cwd++;
+    buffer[2] = '/';
+    lstrcpyn( buffer + 3, unix_cwd, sizeof(buffer) - 3 );
+    if (!(dos_cwd = DOSFS_GetDosTrueName( buffer, TRUE ))) return 0;
+
+    dprintf_dosfs( stddeb, "DRIVE_Chdir(%c:): unix_cwd=%s dos_cwd=%s\n",
+                   'A' + drive, unix_cwd, dos_cwd + 3 );
+
+    free( DOSDrives[drive].dos_cwd );
+    free( DOSDrives[drive].unix_cwd );
+    DOSDrives[drive].dos_cwd  = xstrdup( dos_cwd + 3 );
+    DOSDrives[drive].unix_cwd = xstrdup( unix_cwd );
+
+    if (pTask && (pTask->curdrive & 0x80) && 
+        ((pTask->curdrive & ~0x80) == drive))
+    {
+        lstrcpyn( pTask->curdir, dos_cwd + 2, sizeof(pTask->curdir) );
+        DRIVE_LastTask = GetCurrentTask();
+    }
+    return 1;
+}
+
+
+/***********************************************************************
+ *           DRIVE_Disable
+ */
+int DRIVE_Disable( int drive  )
+{
+    if ((drive < 0) || (drive >= MAX_DOS_DRIVES) || !DOSDrives[drive].root)
+    {
+        DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk );
+        return 0;
+    }
+    DOSDrives[drive].disabled = 1;
+    return 1;
+}
+
+
+/***********************************************************************
+ *           DRIVE_Enable
+ */
+int DRIVE_Enable( int drive  )
+{
+    if ((drive < 0) || (drive >= MAX_DOS_DRIVES) || !DOSDrives[drive].root)
+    {
+        DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk );
+        return 0;
+    }
+    DOSDrives[drive].disabled = 0;
+    return 1;
+}
+
+
+/***********************************************************************
+ *           GetDriveType   (KERNEL.136)
+ */
+WORD GetDriveType( INT drive )
+{
+    dprintf_dosfs( stddeb, "GetDriveType(%c:)\n", 'A' + drive );
+    if (!DRIVE_IsValid(drive)) return 0;
+    return DOSDrives[drive].type;
+}
diff --git a/files/file.c b/files/file.c
new file mode 100644
index 0000000..19cc6fb
--- /dev/null
+++ b/files/file.c
@@ -0,0 +1,906 @@
+/*
+ * File handling functions
+ *
+ * Copyright 1993 John Burton
+ * Copyright 1996 Alexandre Julliard
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "windows.h"
+#include "directory.h"
+#include "dos_fs.h"
+#include "drive.h"
+#include "global.h"
+#include "msdos.h"
+#include "options.h"
+#include "ldt.h"
+#include "task.h"
+#include "stddebug.h"
+#include "debug.h"
+
+
+/***********************************************************************
+ *           FILE_SetDosError
+ *
+ * Set the DOS error code from errno.
+ */
+void FILE_SetDosError(void)
+{
+    switch (errno)
+    {
+    case EAGAIN:
+        DOS_ERROR( ER_ShareViolation, EC_Temporary, SA_Retry, EL_Disk );
+        break;
+    case EBADF:
+        DOS_ERROR( ER_InvalidHandle, EC_ProgramError, SA_Abort, EL_Disk );
+        break;
+    case ENOSPC:
+        DOS_ERROR( ER_DiskFull, EC_MediaError, SA_Abort, EL_Disk );
+        break;				
+    case EACCES:
+    case EPERM:
+    case EROFS:
+        DOS_ERROR( ER_WriteProtected, EC_AccessDenied, SA_Abort, EL_Disk );
+        break;
+    case EBUSY:
+        DOS_ERROR( ER_LockViolation, EC_AccessDenied, SA_Abort, EL_Disk );
+        break;		
+    case ENOENT:
+        DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
+        break;				
+    case EISDIR:
+        DOS_ERROR( ER_CanNotMakeDir, EC_AccessDenied, SA_Abort, EL_Unknown );
+        break;
+    case ENFILE:
+    case EMFILE:
+        DOS_ERROR( ER_NoMoreFiles, EC_MediaError, SA_Abort, EL_Unknown );
+        break;
+    case EEXIST:
+        DOS_ERROR( ER_FileExists, EC_Exists, SA_Abort, EL_Disk );
+        break;				
+    default:
+        perror( "int21: unknown errno" );
+        DOS_ERROR( ER_GeneralFailure, EC_SystemFailure, SA_Abort, EL_Unknown );
+        break;
+    }
+}
+
+
+/***********************************************************************
+ *           FILE_AllocTaskHandle
+ *
+ * Allocate a DOS file handle for the current task.
+ */
+static HFILE FILE_AllocTaskHandle( int handle )
+{
+    PDB *pdb = (PDB *)GlobalLock( GetCurrentPDB() );
+    BYTE *files, *fp;
+    WORD i;
+
+    if (!pdb)
+    {
+        fprintf(stderr,"FILE_MakeTaskHandle: internal error, no current PDB.\n");
+        exit(1);
+    }
+    fp = files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
+    for (i = pdb->nbFiles; (i > 0) && (*fp != 0xff); i--, fp++);
+    if (!i || (handle >= 0xff))  /* No more handles */
+    {
+        DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError, SA_Abort, EL_Disk );
+        return -1;
+    }
+    *fp = (BYTE)handle;
+    return (HFILE)(fp - files);
+}
+
+
+/***********************************************************************
+ *           FILE_FreeTaskHandle
+ *
+ * Free a DOS file handle for the current task.
+ */
+static void FILE_FreeTaskHandle( HFILE handle )
+{
+    PDB *pdb = (PDB *)GlobalLock( GetCurrentPDB() );
+    BYTE *files;
+    
+    if (!pdb)
+    {
+        fprintf(stderr,"FILE_FreeTaskHandle: internal error, no current PDB.\n");
+        exit(1);
+    }
+    files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
+    if ((handle<0) || (handle >= (INT)pdb->nbFiles) || (files[handle] == 0xff))
+    {
+        fprintf( stderr, "FILE_FreeTaskHandle: invalid file handle %d\n",
+                 handle );
+        return;
+    }
+    files[handle] = 0xff;
+}
+
+
+/***********************************************************************
+ *           FILE_GetUnixHandle
+ *
+ * Return the Unix file handle associated to a DOS file handle.
+ */
+int FILE_GetUnixHandle( HFILE handle )
+{
+    PDB *pdb = (PDB *)GlobalLock( GetCurrentPDB() );
+    BYTE *files;
+    
+    if (!pdb)
+    {
+        fprintf(stderr,"FILE_GetUnixHandle: internal error, no current PDB.\n");
+        exit(1);
+    }
+    files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
+    if ((handle<0) || (handle >= (INT)pdb->nbFiles) || (files[handle] == 0xff))
+    {
+        DOS_ERROR( ER_InvalidHandle, EC_ProgramError, SA_Abort, EL_Disk );
+        return -1;
+    }
+    return (int)files[handle];
+}
+
+
+/***********************************************************************
+ *           FILE_CloseAllFiles
+ *
+ * Close all open files of a given PDB. Used on task termination.
+ */
+void FILE_CloseAllFiles( HANDLE hPDB )
+{
+    BYTE *files;
+    WORD count;
+    PDB *pdb = (PDB *)GlobalLock( hPDB );
+
+    if (!pdb) return;
+    files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
+    for (count = pdb->nbFiles; count > 0; count--, files++)
+    {
+        if (*files != 0xff)
+        {
+            close( (int)*files );
+            *files = 0xff;
+        }
+    }
+}
+
+
+/***********************************************************************
+ *           FILE_Open
+ */
+int FILE_Open( LPCSTR path, int mode )
+{
+    const char *unixName;
+    int handle;
+
+    dprintf_file(stddeb, "FILE_Open: '%s' %04x\n", path, mode );
+    if ((unixName = DOSFS_IsDevice( path )) != NULL)
+    {
+        dprintf_file( stddeb, "FILE_Open: opening device '%s'\n", unixName );
+        if (!unixName[0])  /* Non-existing device */
+        {
+            DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
+            return -1;
+        }
+        handle = open( unixName, mode );
+    }
+    else
+    {
+        if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return -1;
+
+        if ((handle = open( unixName, mode )) == -1)
+        {
+            if (Options.allowReadOnly && (mode == O_RDWR))
+            {
+                if ((handle = open( unixName, O_RDONLY )) != -1)
+                    fprintf( stderr, "Warning: could not open %s for writing, opening read-only.\n", unixName );
+            }
+        }
+    }
+    if (handle == -1) FILE_SetDosError();
+    return handle;
+}
+
+
+/***********************************************************************
+ *           FILE_Create
+ */
+int FILE_Create( LPCSTR path, int mode, int unique )
+{
+    const char *unixName;
+    int handle;
+
+    dprintf_file(stddeb, "FILE_Create: '%s' %04x %d\n", path, mode, unique );
+
+    if ((unixName = DOSFS_IsDevice( path )) != NULL)
+    {
+        dprintf_file(stddeb, "FILE_Create: creating device '%s'!\n", unixName);
+        DOS_ERROR( ER_AccessDenied, EC_NotFound, SA_Abort, EL_Disk );
+        return -1;
+    }
+
+    if (!(unixName = DOSFS_GetUnixFileName( path, FALSE ))) return -1;
+    if ((handle = open( unixName,
+                        O_CREAT | O_TRUNC | O_RDWR | (unique ? O_EXCL : 0),
+                        mode )) == -1)
+        FILE_SetDosError();
+    return handle;
+}
+
+
+/***********************************************************************
+ *           FILE_Unlink
+ */
+int FILE_Unlink( LPCSTR path )
+{
+    const char *unixName;
+
+    dprintf_file(stddeb, "FILE_Unlink: '%s'\n", path );
+
+    if ((unixName = DOSFS_IsDevice( path )) != NULL)
+    {
+        dprintf_file(stddeb, "FILE_Unlink: removing device '%s'!\n", unixName);
+        DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
+        return 0;
+    }
+
+    if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return 0;
+    if (unlink( unixName ) == -1)
+    {
+        FILE_SetDosError();
+        return 0;
+    }
+    return 1;
+}
+
+
+/***********************************************************************
+ *           FILE_Stat
+ *
+ * Stat a Unix path name. Return 1 if OK.
+ */
+int FILE_Stat( LPCSTR unixName, BYTE *pattr, DWORD *psize,
+               WORD *pdate, WORD *ptime )
+{
+    struct stat st;
+
+    if (stat( unixName, &st ) == -1)
+    {
+        FILE_SetDosError();
+        return 0;
+    }
+    if (pattr) *pattr = FA_ARCHIVE | (S_ISDIR(st.st_mode) ? FA_DIRECTORY : 0);
+    if (psize) *psize = st.st_size;
+    DOSFS_ToDosDateTime( &st.st_mtime, pdate, ptime );
+    return 1;
+}
+
+
+/***********************************************************************
+ *           FILE_Fstat
+ *
+ * Stat a DOS handle. Return 1 if OK.
+ */
+int FILE_Fstat( HFILE hFile, BYTE *pattr, DWORD *psize,
+                WORD *pdate, WORD *ptime )
+{
+    struct stat st;
+    int handle;
+
+    if ((handle = FILE_GetUnixHandle( hFile )) == -1) return 0;
+    if (fstat( handle, &st ) == -1)
+    {
+        FILE_SetDosError();
+        return 0;
+    }
+    if (pattr) *pattr = FA_ARCHIVE | (S_ISDIR(st.st_mode) ? FA_DIRECTORY : 0);
+    if (psize) *psize = st.st_size;
+    DOSFS_ToDosDateTime( &st.st_mtime, pdate, ptime );
+    return 1;
+}
+
+
+/***********************************************************************
+ *           FILE_MakeDir
+ */
+int FILE_MakeDir( LPCSTR path )
+{
+    const char *unixName;
+
+    dprintf_file(stddeb, "FILE_MakeDir: '%s'\n", path );
+
+    if ((unixName = DOSFS_IsDevice( path )) != NULL)
+    {
+        dprintf_file(stddeb, "FILE_MakeDir: device '%s'!\n", unixName);
+        DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
+        return 0;
+    }
+    if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return 0;
+    if ((mkdir( unixName, 0777 ) == -1) && (errno != EEXIST))
+    {
+        FILE_SetDosError();
+        return 0;
+    }
+    return 1;
+}
+
+
+/***********************************************************************
+ *           FILE_RemoveDir
+ */
+int FILE_RemoveDir( LPCSTR path )
+{
+    const char *unixName;
+
+    dprintf_file(stddeb, "FILE_RemoveDir: '%s'\n", path );
+
+    if ((unixName = DOSFS_IsDevice( path )) != NULL)
+    {
+        dprintf_file(stddeb, "FILE_RemoveDir: device '%s'!\n", unixName);
+        DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
+        return 0;
+    }
+    if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return 0;
+    if (rmdir( unixName ) == -1)
+    {
+        FILE_SetDosError();
+        return 0;
+    }
+    return 1;
+}
+
+
+/***********************************************************************
+ *           FILE_Dup
+ *
+ * dup() function for DOS handles.
+ */
+HFILE FILE_Dup( HFILE hFile )
+{
+    int handle, newhandle;
+    HFILE dosHandle;
+
+    if ((handle = FILE_GetUnixHandle( hFile )) == -1) return HFILE_ERROR;
+    if ((newhandle = dup(handle)) == -1)
+    {
+        FILE_SetDosError();
+        return HFILE_ERROR;
+    }
+    if ((dosHandle = FILE_AllocTaskHandle( newhandle )) == HFILE_ERROR)
+        close( newhandle );
+    return dosHandle;
+}
+
+
+/***********************************************************************
+ *           FILE_Dup2
+ *
+ * dup2() function for DOS handles.
+ */
+HFILE FILE_Dup2( HFILE hFile1, HFILE hFile2 )
+{
+    PDB *pdb = (PDB *)GlobalLock( GetCurrentPDB() );
+    BYTE *files;
+    int handle, newhandle;
+
+    if ((handle = FILE_GetUnixHandle( hFile1 )) == -1) return HFILE_ERROR;
+    if ((hFile2 < 0) || (hFile2 >= (INT)pdb->nbFiles))
+    {
+        DOS_ERROR( ER_InvalidHandle, EC_ProgramError, SA_Abort, EL_Disk );
+        return HFILE_ERROR;
+    }
+
+    if ((newhandle = dup(handle)) == -1)
+    {
+        FILE_SetDosError();
+        return HFILE_ERROR;
+    }
+    if (newhandle >= 0xff)
+    {
+        DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError, SA_Abort, EL_Disk );
+        close( newhandle );
+        return HFILE_ERROR;
+    }
+    files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
+    if (files[hFile2] != 0xff) close( files[hFile2] );
+    files[hFile2] = (BYTE)newhandle;
+    return hFile2;
+}
+
+
+/***********************************************************************
+ *           FILE_OpenFile
+ *
+ * Implementation of API function OpenFile(). Returns a Unix file handle.
+ */
+int FILE_OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode )
+{
+    const char *unixName, *dosName;
+    char *p;
+    int handle, len, i, unixMode;
+    struct stat st;
+
+    ofs->cBytes = sizeof(OFSTRUCT);
+    ofs->nErrCode = 0;
+    if (mode & OF_REOPEN) name = ofs->szPathName;
+    dprintf_file( stddeb, "Openfile: %s %04x\n", name, mode );
+
+    /* OF_PARSE simply fills the structure */
+
+    if (mode & OF_PARSE)
+    {
+        if (!(dosName = DOSFS_GetDosTrueName( name, FALSE )))
+        {
+            ofs->nErrCode = DOS_ExtendedError;
+            return -1;
+        }
+        lstrcpyn( ofs->szPathName, dosName, sizeof(ofs->szPathName) );
+        ofs->fFixedDisk = (GetDriveType( dosName[0]-'A' ) != DRIVE_REMOVABLE);
+        return 0;
+    }
+
+    /* OF_CREATE is completely different from all other options, so
+       handle it first */
+
+    if (mode & OF_CREATE)
+    {
+        if ((unixName = DOSFS_GetUnixFileName( name, FALSE )) == NULL)
+        {
+            ofs->nErrCode = DOS_ExtendedError;
+            return -1;
+        }
+        dprintf_file( stddeb, "OpenFile: creating '%s'\n", unixName );
+        handle = open( unixName, O_TRUNC | O_RDWR | O_CREAT, 0666 );
+        if (handle == -1)
+        {
+            FILE_SetDosError();
+            ofs->nErrCode = DOS_ExtendedError;
+            return -1;
+        }   
+        lstrcpyn( ofs->szPathName, DOSFS_GetDosTrueName( name, FALSE ),
+                  sizeof(ofs->szPathName) );
+        return handle;
+    }
+
+    /* Now look for the file */
+
+    /* First try the current directory */
+
+    lstrcpyn( ofs->szPathName, name, sizeof(ofs->szPathName) );
+    if ((unixName = DOSFS_GetUnixFileName( ofs->szPathName, TRUE )) != NULL)
+        goto found;
+
+    /* Now try some different paths if none was specified */
+
+    if ((mode & OF_SEARCH) && !(mode & OF_REOPEN))
+    {
+        if (name[1] == ':') name += 2;
+        if ((p = strrchr( name, '\\' ))) name = p + 1;
+        if ((p = strrchr( name, '/' ))) name = p + 1;
+        if (!name[0]) goto not_found;
+    }
+    else
+    {
+        if ((name[1] == ':') || strchr( name, '/' ) || strchr( name, '\\' ))
+            goto not_found;
+    }
+
+    if ((len = sizeof(ofs->szPathName) - strlen(name) - 1) < 0) goto not_found;
+
+    /* Try the Windows directory */
+
+    GetWindowsDirectory( ofs->szPathName, len );
+    strcat( ofs->szPathName, "\\" );
+    strcat( ofs->szPathName, name );
+    if ((unixName = DOSFS_GetUnixFileName( ofs->szPathName, TRUE )) != NULL)
+        goto found;
+
+    /* Try the Windows system directory */
+
+    GetSystemDirectory( ofs->szPathName, len );
+    strcat( ofs->szPathName, "\\" );
+    strcat( ofs->szPathName, name );
+    if ((unixName = DOSFS_GetUnixFileName( ofs->szPathName, TRUE )) != NULL)
+        goto found;
+
+    /* Try the path of the current executable */
+
+    if (GetCurrentTask())
+    {
+        GetModuleFileName( GetCurrentTask(), ofs->szPathName, len );
+        if ((p = strrchr( ofs->szPathName, '\\' )))
+        {
+            strcpy( p + 1, name );
+            if ((unixName = DOSFS_GetUnixFileName( ofs->szPathName, TRUE )))
+                goto found;
+        }
+    }
+
+    /* Try all directories in path */
+
+    for (i = 0; ; i++)
+    {
+        if (!DIR_GetDosPath( i, ofs->szPathName, len )) break;
+        strcat( ofs->szPathName, "\\" );
+        strcat( ofs->szPathName, name );
+        if ((unixName = DOSFS_GetUnixFileName( ofs->szPathName, TRUE)) != NULL)
+            goto found;
+    }
+
+not_found:
+    dprintf_file( stddeb, "OpenFile: '%s' not found\n", name );
+    DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
+    ofs->nErrCode = ER_FileNotFound;
+    return -1;
+
+found:
+    dprintf_file( stddeb, "OpenFile: found '%s'\n", unixName );
+    lstrcpyn( ofs->szPathName, DOSFS_GetDosTrueName( ofs->szPathName, FALSE ),
+              sizeof(ofs->szPathName) );
+
+    if (mode & OF_PARSE) return 0;
+
+    if (mode & OF_DELETE)
+    {
+        if (unlink( unixName ) == -1) goto not_found;
+        return 0;
+    }
+
+    switch(mode & 3)
+    {
+    case OF_WRITE:
+        unixMode = O_WRONLY; break;
+    case OF_READWRITE:
+        unixMode = O_RDWR; break;
+    case OF_READ:
+    default:
+        unixMode = O_RDONLY; break;
+    }
+
+    if ((handle = open( unixName, unixMode )) == -1)
+    {
+        if (Options.allowReadOnly && (unixMode == O_RDWR))
+        {
+            if ((handle = open( unixName, O_RDONLY )) != -1)
+                fprintf( stderr, "Warning: could not open %s for writing, opening read-only.\n", unixName );
+        }
+    }
+    if (handle == -1) goto not_found;
+
+    if (fstat( handle, &st ) != -1)
+    {
+        if ((mode & OF_VERIFY) && (mode & OF_REOPEN))
+        {
+            if (memcmp( ofs->reserved, &st.st_mtime, sizeof(ofs->reserved) ))
+                return -1;
+        }
+        memcpy( ofs->reserved, &st.st_mtime, sizeof(ofs->reserved) );
+    }
+
+    if (mode & OF_EXIST) close( handle );
+
+    return handle;
+}
+
+
+/***********************************************************************
+ *           GetTempFileName   (KERNEL.97)
+ */
+INT GetTempFileName( BYTE drive, LPCSTR prefix, UINT unique, LPSTR buffer )
+{
+    int i, handle;
+    UINT num = unique ? (unique & 0xffff) : time(NULL) & 0xffff;
+    char *p;
+
+    if (drive & TF_FORCEDRIVE)
+    {
+        sprintf( buffer, "%c:", drive & ~TF_FORCEDRIVE );
+    }
+    else
+    {
+        DIR_GetTempDosDir( buffer, 132 );  /* buffer must be at least 144 */
+        strcat( buffer, "\\" );
+    }
+
+    p = buffer + strlen(buffer);
+    for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
+    sprintf( p, "%04x.tmp", num );
+
+    if (unique)
+    {
+        lstrcpyn( buffer, DOSFS_GetDosTrueName( buffer, FALSE ), 144 );
+        dprintf_file( stddeb, "GetTempFileName: returning %s\n", buffer );
+        return unique;
+    }
+
+    /* Now try to create it */
+
+    do
+    {
+        if ((handle = FILE_Create( buffer, 0666, TRUE )) != -1)
+        {  /* We created it */
+            dprintf_file( stddeb, "GetTempFileName: created %s\n", buffer );
+            close( handle );
+            break;
+        }
+        if (DOS_ExtendedError != ER_FileExists) break;  /* No need to go on */
+        num++;
+        sprintf( p, "%04x.tmp", num );
+    } while (num != (unique & 0xffff));
+
+    lstrcpyn( buffer, DOSFS_GetDosTrueName( buffer, FALSE ), 144 );
+    dprintf_file( stddeb, "GetTempFileName: returning %s\n", buffer );
+    return num;
+}
+
+
+/***********************************************************************
+ *           OpenFile   (KERNEL.74)
+ */
+HFILE OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode )
+{
+    int unixHandle;
+    HFILE handle;
+
+    if ((unixHandle = FILE_OpenFile( name, ofs, mode )) == -1)
+        return HFILE_ERROR;
+    if ((handle = FILE_AllocTaskHandle( unixHandle )) == HFILE_ERROR)
+    {
+        ofs->nErrCode = DOS_ExtendedError;
+        if (unixHandle) close( unixHandle );
+    }
+    if (!unixHandle) FILE_FreeTaskHandle( handle );
+    return handle;
+}
+
+
+/***********************************************************************
+ *           _lclose   (KERNEL.81)
+ */
+HFILE _lclose( HFILE hFile )
+{
+    int handle;
+
+    dprintf_file( stddeb, "_lclose: handle %d\n", hFile );
+    
+    if ((handle = FILE_GetUnixHandle( hFile )) == -1) return HFILE_ERROR;
+    if (handle <= 2)
+    {
+        fprintf( stderr, "_lclose: internal error: closing handle %d\n", handle );
+        exit(1);
+    }
+    FILE_FreeTaskHandle( hFile );
+    close( handle );
+    return 0;
+}
+
+
+/***********************************************************************
+ *           _lread   (KERNEL.82)
+ */
+INT _lread( HFILE hFile, LPSTR buffer, WORD count )
+{
+    return (INT)_hread( hFile, buffer, (LONG)count );
+}
+
+
+/***********************************************************************
+ *           _lcreat   (KERNEL.83)
+ */
+INT _lcreat( LPCSTR path, INT attr )
+{
+    int unixHandle, mode;
+    HFILE handle;
+    
+    dprintf_file( stddeb, "_lcreat: %s %02x\n", path, attr );
+    mode = (attr & 1) ? 0444 : 0666;
+    if ((unixHandle = FILE_Create( path, mode, FALSE )) == -1)
+        return HFILE_ERROR;
+    if ((handle = FILE_AllocTaskHandle( unixHandle )) == HFILE_ERROR)
+        close( unixHandle );
+    return handle;
+}
+
+
+/***********************************************************************
+ *           _lcreat_uniq   (Not a Windows API)
+ */
+INT _lcreat_uniq( LPCSTR path, INT attr )
+{
+    int unixHandle, mode;
+    HFILE handle;
+    
+    dprintf_file( stddeb, "_lcreat: %s %02x\n", path, attr );
+    mode = (attr & 1) ? 0444 : 0666;
+    if ((unixHandle = FILE_Create( path, mode, TRUE )) == -1)
+        return HFILE_ERROR;
+    if ((handle = FILE_AllocTaskHandle( unixHandle )) == HFILE_ERROR)
+        close( unixHandle );
+    return handle;
+}
+
+
+/***********************************************************************
+ *           _llseek   (KERNEL.84)
+ */
+LONG _llseek( HFILE hFile, LONG lOffset, INT nOrigin )
+{
+    int handle, origin, result;
+	
+    dprintf_file( stddeb, "_llseek: handle %d, offset %ld, origin %d\n", 
+                  hFile, lOffset, nOrigin);
+
+    if ((handle = FILE_GetUnixHandle( hFile )) == -1) return HFILE_ERROR;
+    switch(nOrigin)
+    {
+        case 1:  origin = SEEK_CUR; break;
+        case 2:  origin = SEEK_END; break;
+        default: origin = SEEK_SET; break;
+    }
+
+    if ((result = lseek( handle, lOffset, origin )) == -1) FILE_SetDosError();
+    return (result == -1) ? HFILE_ERROR : result;
+}
+
+
+/***********************************************************************
+ *           _lopen   (KERNEL.85)
+ */
+HFILE _lopen( LPCSTR path, INT mode )
+{
+    int unixHandle;
+    int unixMode;
+    HFILE handle;
+
+    dprintf_file(stddeb, "_lopen('%s',%04x)\n", path, mode );
+
+    switch(mode & 3)
+    {
+    case OF_WRITE:
+        unixMode = O_WRONLY | O_TRUNC;
+        break;
+    case OF_READWRITE:
+        unixMode = O_RDWR;
+        break;
+    case OF_READ:
+    default:
+        unixMode = O_RDONLY;
+        break;
+    }
+    if ((unixHandle = FILE_Open( path, unixMode )) == -1) return HFILE_ERROR;
+    if ((handle = FILE_AllocTaskHandle( unixHandle )) == HFILE_ERROR)
+        close( unixHandle );
+    return handle;
+}
+
+
+/***********************************************************************
+ *           _lwrite   (KERNEL.86)
+ */
+INT _lwrite( HFILE hFile, LPCSTR buffer, WORD count )
+{
+    return (INT)_hwrite( hFile, buffer, (LONG)count );
+}
+
+
+/***********************************************************************
+ *           _hread   (KERNEL.349)
+ */
+LONG _hread( HFILE hFile, LPSTR buffer, LONG count )
+{
+    int handle;
+    LONG result;
+
+    dprintf_file( stddeb, "_hread: %d %p %ld\n", hFile, buffer, count );
+  
+    if ((handle = FILE_GetUnixHandle( hFile )) == -1) return HFILE_ERROR;
+    if (!count) return 0;
+    if ((result = read( handle, buffer, count )) == -1) FILE_SetDosError();
+    return (result == -1) ? HFILE_ERROR : result;
+}
+
+
+/***********************************************************************
+ *           _hwrite   (KERNEL.350)
+ */
+LONG _hwrite( HFILE hFile, LPCSTR buffer, LONG count )
+{
+    int handle;
+    LONG result;
+
+    dprintf_file( stddeb, "_hwrite: %d %p %ld\n", hFile, buffer, count );
+
+    if ((handle = FILE_GetUnixHandle( hFile )) == -1) return HFILE_ERROR;
+    
+    if (count == 0)  /* Expand or truncate at current position */
+        result = ftruncate( handle, lseek( handle, 0, SEEK_CUR ) );
+    else
+        result = write( handle, buffer, count );
+
+    if (result == -1) FILE_SetDosError();
+    return (result == -1) ? HFILE_ERROR : result;
+}
+
+
+/***********************************************************************
+ *           SetHandleCount   (KERNEL.199)
+ */
+WORD SetHandleCount( WORD count )
+{
+    HANDLE hPDB = GetCurrentPDB();
+    PDB *pdb = (PDB *)GlobalLock( hPDB );
+    BYTE *files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
+    WORD i;
+
+    dprintf_file( stddeb, "SetHandleCount(%d)\n", count );
+
+    if (count < 20) count = 20;  /* No point in going below 20 */
+    else if (count > 254) count = 254;
+
+    /* If shrinking the table, make sure all extra file handles are closed */
+    if (count < pdb->nbFiles)
+    {
+        for (i = count; i < pdb->nbFiles; i++)
+            if (files[i] != 0xff)  /* File open */
+            {
+                DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError,
+                           SA_Abort, EL_Disk );
+                return pdb->nbFiles;
+            }
+    }
+
+    if (count == 20)
+    {
+        if (pdb->nbFiles > 20)
+        {
+            memcpy( pdb->fileHandles, files, 20 );
+#ifdef WINELIB
+            GlobalFree( pdb->fileHandlesPtr );
+            pdb->fileHandlesPtr = pdb->fileHandles;
+#else
+            GlobalFree( GlobalHandle( SELECTOROF(pdb->fileHandlesPtr) ));
+            pdb->fileHandlesPtr = (SEGPTR)MAKELONG( 0x18,
+                                                   GlobalHandleToSel( hPDB ) );
+#endif
+            pdb->nbFiles = 20;
+        }
+    }
+    else  /* More than 20, need a new file handles table */
+    {
+        BYTE *newfiles;
+        HANDLE newhandle = GlobalAlloc( GMEM_MOVEABLE, count );
+        if (!newhandle)
+        {
+            DOS_ERROR( ER_OutOfMemory, EC_OutOfResource, SA_Abort, EL_Memory );
+            return pdb->nbFiles;
+        }
+        newfiles = (BYTE *)GlobalLock( newhandle );
+        if (count > pdb->nbFiles)
+        {
+            memcpy( newfiles, files, pdb->nbFiles );
+            memset( newfiles + pdb->nbFiles, 0xff, count - pdb->nbFiles );
+        }
+        else memcpy( newfiles, files, count );
+#ifdef WINELIB
+        if (pdb->nbFiles > 20) GlobalFree( pdb->fileHandlesPtr );
+#else
+        if (pdb->nbFiles > 20)
+            GlobalFree( GlobalHandle( SELECTOROF(pdb->fileHandlesPtr) ));
+#endif
+        pdb->fileHandlesPtr = WIN16_GlobalLock( newhandle );
+        pdb->nbFiles = count;
+    }
+    return pdb->nbFiles;
+}
diff --git a/if1632/Makefile.in b/if1632/Makefile.in
index b8926e2..8cdd78d 100644
--- a/if1632/Makefile.in
+++ b/if1632/Makefile.in
@@ -51,4 +51,20 @@
 clean::
 	rm -f $(SPEC16_FILES) $(SPEC32_FILES) call32.S call16.S
 
+# Kludge: don't use optimisation flags to compile these files
+advapi32.o: advapi32.c
+	$(CC) -c $(DEFS) $(DIVINCL) $(EXTRA_DEFS) -o advapi32.o advapi32.c
+comdlg32.o: comdlg32.c
+	$(CC) -c $(DEFS) $(DIVINCL) $(EXTRA_DEFS) -o comdlg32.o comdlg32.c
+gdi32.o: gdi32.c
+	$(CC) -c $(DEFS) $(DIVINCL) $(EXTRA_DEFS) -o gdi32.o gdi32.c
+kernel32.o: kernel32.c
+	$(CC) -c $(DEFS) $(DIVINCL) $(EXTRA_DEFS) -o kernel32.o kernel32.c
+shell32.o: shell32.c
+	$(CC) -c $(DEFS) $(DIVINCL) $(EXTRA_DEFS) -o shell32.o shell32.c
+user32.o: user32.c
+	$(CC) -c $(DEFS) $(DIVINCL) $(EXTRA_DEFS) -o user32.o user32.c
+winprocs32.o: winprocs32.c
+	$(CC) -c $(DEFS) $(DIVINCL) $(EXTRA_DEFS) -o winprocs32.o winprocs32.c
+
 ### Dependencies:
diff --git a/if1632/callback.c b/if1632/callback.c
index 2d6a742..27d236c 100644
--- a/if1632/callback.c
+++ b/if1632/callback.c
@@ -37,10 +37,12 @@
                             (hwnd,message,wParam,lParam);
     if(!a->win32)
         fprintf(stderr,"Where is the Win32 callback?\n");
-    return RELAY32_CallWindowProc(a->win32,hwnd,message,wParam,lParam);
+    if (UsesLParamPtr(message))
+	return RELAY32_CallWindowProc(a->win32,hwnd,message,wParam,lParam ? PTR_SEG_TO_LIN(lParam): 0);
+    else
+	return RELAY32_CallWindowProc(a->win32,hwnd,message,wParam,lParam);
 }
 
-
 /**********************************************************************
  *	     Catch    (KERNEL.55)
  */
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index 4249cbd..cd60272 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -232,7 +232,7 @@
 346 pascal16 SetTextAlign(word word) SetTextAlign
 348 pascal16 Chord(word s_word s_word s_word s_word s_word s_word
                    s_word s_word) Chord
-349 pascal SetMapperFlags(word word) SetMapperFlags
+349 pascal SetMapperFlags(word long) SetMapperFlags
 350 pascal16 GetCharWidth(word word word ptr) GetCharWidth
 351 pascal16 ExtTextOut(word s_word s_word word ptr ptr s_word ptr) ExtTextOut
 352 stub GetPhysicalFontHandle
diff --git a/if1632/gdi32.spec b/if1632/gdi32.spec
index 3ebcb86..86bd082 100644
--- a/if1632/gdi32.spec
+++ b/if1632/gdi32.spec
@@ -11,7 +11,7 @@
 0007 stub Arc
 0008 stub ArcTo
 0009 stub BeginPath
-0010 stub BitBlt
+0010 stdcall BitBlt(long long long long long long long long long) BitBlt
 0011 stub CancelDC
 0012 stub CheckColorsInGamut
 0013 stub ChoosePixelFormat
@@ -31,8 +31,8 @@
 0027 stub CreateBrushIndirect
 0028 stub CreateColorSpaceA
 0029 stub CreateColorSpaceW
-0030 stub CreateCompatibleBitmap
-0031 stub CreateCompatibleDC
+0030 stdcall CreateCompatibleBitmap(long long long) CreateCompatibleBitmap
+0031 stdcall CreateCompatibleDC(long) CreateCompatibleDC
 0032 stub CreateDCA
 0033 stub CreateDCW
 0034 stub CreateDIBPatternBrush
@@ -50,13 +50,13 @@
 0046 stub CreateFontW
 0047 stub CreateHalftonePalette
 0048 stub CreateHatchBrush
-0049 stub CreateICA
+0049 stdcall CreateICA(ptr ptr ptr ptr) CreateIC
 0050 stub CreateICW
 0051 stub CreateMetaFileA
 0052 stub CreateMetaFileW
 0053 stub CreatePalette
 0054 stub CreatePatternBrush
-0055 stub CreatePen
+0055 stdcall CreatePen(long long long) CreatePen
 0056 stub CreatePenIndirect
 0057 stub CreatePolyPolygonRgn
 0058 stub CreatePolygonRgn
@@ -65,10 +65,10 @@
 0061 stub CreateRoundRectRgn
 0062 stub CreateScalableFontResourceA
 0063 stub CreateScalableFontResourceW
-0064 stub CreateSolidBrush
+0064 stdcall CreateSolidBrush(long) CreateSolidBrush
 0065 stub DPtoLP
 0066 stub DeleteColorSpace
-0067 stub DeleteDC
+0067 stdcall DeleteDC(long) DeleteDC
 0068 stub DeleteEnhMetaFile
 0069 stub DeleteMetaFile
 0070 stub DeleteObject
@@ -172,7 +172,7 @@
 0168 stub GetDCOrgEx
 0169 stub GetDIBColorTable
 0170 stub GetDIBits
-0171 stub GetDeviceCaps
+0171 stdcall GetDeviceCaps(long long) GetDeviceCaps
 0172 stub GetDeviceGammaRamp
 0173 stub GetETM
 0174 stub GetEnhMetaFileA
@@ -205,7 +205,7 @@
 0201 stub GetMiterLimit
 0202 stub GetNearestColor
 0203 stub GetNearestPaletteIndex
-0204 stub GetObjectA
+0204 stdcall GetObjectA(long long ptr) GetObject
 0205 stub GetObjectType
 0206 stub GetObjectW
 0207 stub GetOutlineTextMetricsA
@@ -233,7 +233,7 @@
 0229 stub GetTextExtentExPointW
 0230 stub GetTextExtentPoint32A
 0231 stub GetTextExtentPoint32W
-0232 stub GetTextExtentPointA
+0232 stdcall GetTextExtentPointA(long ptr long ptr) GetTextExtentPoint
 0233 stub GetTextExtentPointW
 0234 stub GetTextFaceA
 0235 stub GetTextFaceW
@@ -250,18 +250,18 @@
 0246 stub InvertRgn
 0247 stub LPtoDP
 0248 stub LineDDA
-0249 stub LineTo
+0249 stdcall LineTo(long long long) LineTo
 0250 stub LoadImageColorMatcherA
 0251 stub LoadImageColorMatcherW
 0252 stub MaskBlt
 0253 stub ModifyWorldTransform
-0254 stub MoveToEx
+0254 stdcall MoveToEx(long long long ptr) MoveToEx
 0255 stub OffsetClipRgn
 0256 stub OffsetRgn
 0257 stub OffsetViewportOrgEx
 0258 stub OffsetWindowOrgEx
 0259 stub PaintRgn
-0260 stub PatBlt
+0260 stdcall PatBlt(long long long long long long) PatBlt
 0261 stub PathToRegion
 0262 stub Pie
 0263 stub PlayEnhMetaFile
@@ -300,13 +300,13 @@
 0296 stub SelectClipPath
 0297 stub SelectClipRgn
 0298 stub SelectFontLocal
-0299 stub SelectObject
+0299 stdcall SelectObject(long long) SelectObject
 0300 stub SelectPalette
 0301 stub SetAbortProc
 0302 stub SetArcDirection
 0303 stub SetBitmapBits
 0304 stub SetBitmapDimensionEx
-0305 stub SetBkColor
+0305 stdcall SetBkColor(long long) SetBkColor
 0306 stub SetBkMode
 0307 stub SetBoundsRect
 0308 stub SetBrushOrgEx
@@ -339,7 +339,7 @@
 0335 stub SetSystemPaletteUse
 0336 stub SetTextAlign
 0337 stub SetTextCharacterExtra
-0338 stub SetTextColor
+0338 stdcall SetTextColor(long long) SetTextColor
 0339 stub SetTextJustification
 0340 stub SetViewportExtEx
 0341 stub SetViewportOrgEx
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index 2899a60..d4e7898 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -80,7 +80,7 @@
 81  pascal16 _lclose(word) _lclose
 82  pascal16 _lread(word ptr word) _lread
 83  pascal16 _lcreat(ptr word) _lcreat
-84  pascal _llseek(word long word) _llseek
+84  pascal   _llseek(word long word) _llseek
 85  pascal16 _lopen(ptr word) _lopen
 86  pascal16 _lwrite(word ptr word) _lwrite
 87  pascal16 RESERVED5(ptr ptr) lstrcmp
@@ -103,7 +103,7 @@
 104 stub GetCodeInfo
 105 stub GetExeVersion
 106 pascal SetSwapAreaSize(word) SetSwapAreaSize
-107 pascal SetErrorMode(word) SetErrorMode
+107 pascal16 SetErrorMode(word) SetErrorMode
 108 stub SwitchStackTo
 109 stub SwitchStackBack
 110 pascal16 PatchCodeHandle(word) PatchCodeHandle
@@ -205,15 +205,15 @@
 205 stub CVWBreak
 206 pascal16 AllocSelectorArray(word) AllocSelectorArray
 207 return IsDBCSLeadByte 2 0
-216 stub RegEnumKey
-217 stub RegOpenKey
-218 stub RegCreateKey
+216 pascal   RegEnumKey(long long ptr long) RegEnumKey
+217 pascal   RegOpenKey(long ptr ptr) RegOpenKey
+218 pascal   RegCreateKey(long ptr ptr) RegCreateKey
 219 stub RegDeleteValue
-220 stub RegCloseKey
-221 stub RegSetValue
+220 pascal   RegCloseKey(long) RegCloseKey
+221 pascal   RegSetValue(long ptr long ptr long) RegSetValue
 222 stub RegDeleteValue
 223 stub RegEnumValue
-224 stub RegQueryValue
+224 pascal   RegQueryValue(long ptr ptr ptr) RegQueryValue
 225 stub RegQueryValueEx
 226 stub RegSetValueEx
 227 stub RegFlushKey
@@ -255,9 +255,9 @@
 345 stub IsSharedSelector
 346 pascal16 IsBadHugeReadPtr(segptr long) IsBadHugeReadPtr
 347 pascal16 IsBadHugeWritePtr(segptr long) IsBadHugeWritePtr
-348 pascal hmemcpy(ptr ptr long) hmemcpy
-349 pascal _hread(word ptr long) _hread
-350 pascal _hwrite(word ptr long) _hwrite
+348 pascal16 hmemcpy(ptr ptr long) hmemcpy
+349 pascal   _hread(word ptr long) _hread
+350 pascal   _hwrite(word ptr long) _hwrite
 #351 BUNNY_351
 352 stub lstrcatn
 353 pascal lstrcpyn(segptr segptr word) WIN16_lstrcpyn
diff --git a/if1632/kernel32.spec b/if1632/kernel32.spec
index e7d3523..b1c7193 100644
--- a/if1632/kernel32.spec
+++ b/if1632/kernel32.spec
@@ -129,7 +129,7 @@
 0125 stub FindNextChangeNotification
 0126 stub FindNextFileA
 0127 stub FindNextFileW
-0128 stub FindResourceA
+0128 stdcall FindResourceA(long ptr ptr) FindResource32
 0129 stub FindResourceExA
 0130 stub FindResourceExW
 0131 stub FindResourceW
@@ -146,7 +146,7 @@
 0142 stub FreeEnvironmentStringsW
 0143 stub FreeLibrary
 0144 stub FreeLibraryAndExitThread
-0145 stub FreeResource
+0145 stdcall FreeResource(long) FreeResource32
 0146 stub FreeVirtualBuffer
 0147 stub GenerateConsoleCtrlEvent
 0148    stdcall GetACP() GetACP
@@ -252,13 +252,13 @@
 0248    stdcall GetOEMCP() GetOEMCP
 0249 stub GetOverlappedResult
 0250 stub GetPriorityClass
-0251 stub GetPrivateProfileIntA
+0251 stdcall GetPrivateProfileIntA(ptr ptr long ptr) GetPrivateProfileInt
 0252 stub GetPrivateProfileIntW
 0253 stub GetPrivateProfileSectionA
 0254 stub GetPrivateProfileSectionW
 0255 stub GetPrivateProfileStringA
 0256 stub GetPrivateProfileStringW
-0257 stub GetProcAddress
+0257	stdcall GetProcAddress(long long)	WIN32_GetProcAddress
 0258 stub GetProcessAffinityMask
 0259	return GetProcessHeap 0 0
 0260 stub GetProcessHeaps
@@ -336,7 +336,7 @@
 0331 stub GlobalUnfix
 0332 stub GlobalUnlock
 0333 stub GlobalWire
-0334 stub HeapAlloc
+0334 stdcall HeapAlloc(long long long) HeapAlloc
 0335 stub HeapCompact
 0336 stub HeapCreate
 0337 stub HeapDestroy
@@ -367,12 +367,12 @@
 0362 stub LCMapStringA
 0363 stub LCMapStringW
 0364 stub LeaveCriticalSection
-0365 stub LoadLibraryA
+0365	stdcall LoadLibraryA(long)		LoadLibraryA
 0366 stub LoadLibraryExA
 0367 stub LoadLibraryExW
 0368 stub LoadLibraryW
 0369 stub LoadModule
-0370 stub LoadResource
+0370 stdcall LoadResource(long long) LoadResource32
 0371	stdcall LocalAlloc(long long)	GlobalAlloc32
 0372 stub LocalCompact
 0373 stub LocalFileTimeToFileTime
@@ -420,7 +420,7 @@
 0415 stub QueryPerformanceCounter
 0416 stub QueryPerformanceFrequency
 0417 stub QueryWin31IniFilesMappedToRegistry
-0418 stub RaiseException
+0418 stdcall RaiseException(long long long ptr) RaiseException
 0419 stub ReadConsoleA
 0420 stub ReadConsoleInputA
 0421 stub ReadConsoleInputW
@@ -496,7 +496,7 @@
 0491 stub SetFileAttributesW
 0492    stdcall SetFilePointer(long long ptr long) SetFilePointer
 0493 stub SetFileTime
-0494 stub SetHandleCount
+0494    stdcall SetHandleCount(long) W32_SetHandleCount
 0495 stub SetHandleInformation
 0496 stub SetLastConsoleEventActive
 0497    stdcall SetLastError(long) SetLastError
diff --git a/if1632/relay32.c b/if1632/relay32.c
index 67c6461..7da3a47 100644
--- a/if1632/relay32.c
+++ b/if1632/relay32.c
@@ -15,8 +15,8 @@
 #include "pe_image.h"
 #include "peexe.h"
 #include "relay32.h"
+#include "xmalloc.h"
 #include "stddebug.h"
-/* #define DEBUG_RELAY */
 #include "debug.h"
 
 WIN32_builtin	*WIN32_builtin_list;
@@ -54,7 +54,7 @@
 
 	len = (cp=strchr(name,'.')) ? (cp-name) : strlen(name);
 	for(it=WIN32_builtin_list;it;it=it->next)
-	if(strncasecmp(name,it->name,len)==0)
+	if(lstrncmpi(name,it->name,len)==0)
 		return it;
 	return NULL;
 }
@@ -78,19 +78,22 @@
 	int i;
   	u_short * ordinal;
   	u_long * function;
-  	u_char ** name, *ename;
+  	u_char ** name;
 	struct PE_Export_Directory * pe_exports;
 	unsigned int load_addr;
 
 	dprintf_module(stddeb, "Looking for %s in %s, hint %x\n",
 		item ? item: "(no name)", dll_name, hint);
 	dll=RELAY32_GetBuiltinDLL(dll_name);
+	/* This should deal with built-in DLLs only. See pe_module on loading
+	   PE DLLs */
+#if 0
 	if(!dll) {
 		if(!wine_files || !wine_files->name ||
-		   strcasecmp(dll_name, wine_files->name)) {
+		   lstrcmpi(dll_name, wine_files->name)) {
 			LoadModule(dll_name, (LPVOID) -1);
 			if(!wine_files || !wine_files->name ||
-		   	   strcasecmp(dll_name, wine_files->name)) 
+		   	   lstrcmpi(dll_name, wine_files->name)) 
 				return 0;
 		}
 		load_addr = wine_files->load_addr;
@@ -118,7 +121,7 @@
 		#if 0
 		if(hint && hint<dll->size && !dll->functions[hint].name)
 		{
-			dll->functions[hint].name=strdup(item);
+			dll->functions[hint].name=xstrdup(item);
 			dprintf_module(stddeb, "Returning unimplemented function %s.%d\n",
 				dll_name,hint);
 			return dll->functions[hint].definition;
@@ -127,6 +130,7 @@
 		printf("Not found\n");
 		return 0;
 	}
+#endif
 	/* import by ordinal */
 	if(!item){
 		if(hint && hint<dll->size)return dll->functions[hint].definition;
@@ -145,12 +149,11 @@
 	/* function at hint has no name (unimplemented) */
 	if(hint && hint<dll->size && !dll->functions[hint].name)
 	{
-		dll->functions[hint].name=strdup(item);
+		dll->functions[hint].name=xstrdup(item);
 		dprintf_module(stddeb, "Returning unimplemented function %s.%d\n",
 			dll_name,hint);
 		return dll->functions[hint].definition;
 	}
-	printf("Not found\n");
 	return 0;
 }
 
diff --git a/if1632/toolhelp.spec b/if1632/toolhelp.spec
index 3a45fda..9bfe141 100644
--- a/if1632/toolhelp.spec
+++ b/if1632/toolhelp.spec
@@ -31,7 +31,7 @@
 77 stub TERMINATEAPP
 78 pascal   MemoryRead(word long ptr long) MemoryRead
 79 pascal   MemoryWrite(word long ptr long) MemoryWrite
-80 stub TIMERCOUNT
+80 pascal16 TimerCount(ptr) TimerCount
 81 stub TASKSETCSIP
 82 stub TASKGETCSIP
 83 stub TASKSWITCH
diff --git a/if1632/user32.spec b/if1632/user32.spec
index c525e30..50f41ee 100644
--- a/if1632/user32.spec
+++ b/if1632/user32.spec
@@ -46,7 +46,7 @@
 0042 stub CharUpperBuffW
 0043 stub CharUpperW
 0044 stub CheckDlgButton
-0045 stub CheckMenuItem
+0045 stdcall CheckMenuItem(long long long) CheckMenuItem
 0046 stub CheckMenuRadioItem
 0047 stub CheckRadioButton
 0048 stub ChildWindowFromPoint
@@ -162,10 +162,10 @@
 0157 stub DrawFrameControl
 0158 stub DrawIcon
 0159 stub DrawIconEx
-0160 stub DrawMenuBar
+0160 stdcall DrawMenuBar(long) DrawMenuBar
 0161 stub DrawStateA
 0162 stub DrawStateW
-0163 stub DrawTextA
+0163 stdcall DrawTextA(long ptr long ptr long) DrawText
 0164 stub DrawTextExA
 0165 stub DrawTextExW
 0166 stub DrawTextW
@@ -221,7 +221,7 @@
 0216 stub GetClassNameA
 0217 stub GetClassNameW
 0218 stub GetClassWord
-0219 stub GetClientRect
+0219 stdcall GetClientRect(long long) GetClientRect
 0220 stub GetClipCursor
 0221 stub GetClipboardData
 0222 stub GetClipboardFormatNameA
@@ -231,7 +231,7 @@
 0226 stub GetCursor
 0227 stub GetCursorInfo
 0228 stub GetCursorPos
-0229 stub GetDC
+0229 stdcall GetDC(long) GetDC
 0230 stub GetDCEx
 0231 stub GetDesktopWindow
 0232 stub GetDialogBaseUnits
@@ -258,7 +258,7 @@
 0253 stub GetKeyboardState
 0254 stub GetKeyboardType
 0255 stub GetLastActivePopup
-0256 stub GetMenu
+0256 stdcall GetMenu(long) GetMenu
 0257 stub GetMenuCheckMarkDimensions
 0258 stub GetMenuContextHelpId
 0259 stub GetMenuDefaultItem
@@ -293,7 +293,7 @@
 0288 	stdcall GetSysColor(long) GetSysColor
 0289 stub GetSysColorBrush
 0290 stub GetSystemMenu
-0291 stub GetSystemMetrics
+0291 stdcall GetSystemMetrics(long) GetSystemMetrics
 0292 stub GetTabbedTextExtentA
 0293 stub GetTabbedTextExtentW
 0294 stub GetThreadDesktop
@@ -305,7 +305,7 @@
 0300 stub GetUserObjectSecurity
 0301 stub GetWindow
 0302 stub GetWindowContextHelpId
-0303 stub GetWindowDC
+0303 stdcall GetWindowDC(long) GetWindowDC
 0304 stub GetWindowLongA
 0305 stub GetWindowLongW
 0306 stub GetWindowPlacement
@@ -346,7 +346,7 @@
 0341 stub IsDialogMessageA
 0342 stub IsDialogMessageW
 0343 stub IsDlgButtonChecked
-0344 stub IsIconic
+0344 stdcall IsIconic(long) IsIconic
 0345 stub IsMenu
 0346 stub IsRectEmpty
 0347 stub IsWindow
@@ -356,16 +356,17 @@
 0351 stub IsZoomed
 0352 stub KillSystemTimer
 0353 stub KillTimer
-0354 	stdcall LoadAcceleratorsA(long ptr) LoadAccelerators
+0354 	stdcall LoadAcceleratorsA(long ptr) LoadAccelerators32
 0355 stub LoadAcceleratorsW
-0356 	stdcall LoadBitmapA(long ptr) LoadBitmap
+0356 	stdcall LoadBitmapA(long ptr) LoadBitmapA32
+0357 	stdcall LoadBitmapW(long ptr) LoadBitmapW32
 0357 stub LoadBitmapW
 0358 	stdcall LoadCursorA(long ptr) LoadCursor
 0359 stub LoadCursorFromFileA
 0360 stub LoadCursorFromFileW
 0361 stub LoadCursorW
-0362 	stdcall LoadIconA(long ptr) LoadIcon
-0363 stub LoadIconW
+0362 	stdcall LoadIconA(long ptr) LoadIconA32
+0363 stdcall LoadIconW(long ptr) LoadIconW32
 0364 stub LoadImageA
 0365 stub LoadImageW
 0366 stub LoadKeyboardLayoutA
@@ -376,8 +377,8 @@
 0371 stub LoadMenuIndirectW
 0372 stub LoadMenuW
 0373 stub LoadRemoteFonts
-0374 	stdcall LoadStringA(long long ptr long) LoadString
-0375 stub LoadStringW
+0374 	stdcall LoadStringA(long long ptr long) LoadStringA32
+0375 	stdcall LoadStringW(long long ptr long) LoadString32
 0376 stub LockWindowStation
 0377 stub LockWindowUpdate
 0378 stub LookupIconIdFromDirectory
@@ -422,7 +423,7 @@
 0417 stub PlaySoundEvent
 0418 stub PostMessageA
 0419 stub PostMessageW
-0420 stub PostQuitMessage
+0420 stdcall PostQuitMessage(long) PostQuitMessage
 0421 stub PostThreadMessageA
 0422 stub PostThreadMessageW
 0423 stub PtInRect
@@ -441,7 +442,7 @@
 0436 stub RegisterWindowMessageA
 0437 stub RegisterWindowMessageW
 0438 stub ReleaseCapture
-0439 stub ReleaseDC
+0439 stdcall ReleaseDC(long long) ReleaseDC
 0440 stub RemoveMenu
 0441 stub RemovePropA
 0442 stub RemovePropW
@@ -531,7 +532,7 @@
 0526 stub SetWindowsHookExW
 0527 stub SetWindowsHookW
 0528 stub ShowCaret
-0529 stub ShowCursor
+0529 stdcall ShowCursor(long) ShowCursor
 0530 stub ShowOwnedPopups
 0531 stub ShowScrollBar
 0532 stub ShowStartGlass
@@ -553,11 +554,11 @@
 0548 stub TrackPopupMenu
 0549 stub TrackPopupMenuEx
 0550 stub TranslateAccelerator
-0551 stub TranslateAcceleratorA
+0551 stdcall TranslateAcceleratorA(long long ptr) TranslateAccelerator
 0552 stub TranslateAcceleratorW
 0553 stub TranslateCharsetInfo
 0554 stub TranslateMDISysAccel
-0555 stub TranslateMessage
+0555 stdcall TranslateMessage(ptr) USER32_TranslateMessage
 0556 stub UnhookWindowsHook
 0557 stub UnhookWindowsHookEx
 0558 stub UnionRect
diff --git a/if1632/winprocs32.spec b/if1632/winprocs32.spec
index 9789e8a..6bb7b0b 100644
--- a/if1632/winprocs32.spec
+++ b/if1632/winprocs32.spec
@@ -1,25 +1,25 @@
 name	winprocs32
 
-1  stdcall ButtonWndProc(long long long long) ButtonWndProc
-2  stdcall StaticWndProc(long long long long) StaticWndProc
-3  stdcall ScrollBarWndProc(long long long long) ScrollBarWndProc
-4  stdcall ListBoxWndProc(long long long long) ListBoxWndProc
-5  stdcall ComboBoxWndProc(long long long long) ComboBoxWndProc
-6  stdcall EditWndProc(long long long long) EditWndProc
-7  stdcall PopupMenuWndProc(long long long long) PopupMenuWndProc
-8  stdcall DesktopWndProc(long long long long) DesktopWndProc
-9  stdcall DefDlgProc(long long long long) DefDlgProc
-10 stdcall MDIClientWndProc(long long long long) MDIClientWndProc
-11 stdcall DefWindowProc(long long long long) DefWindowProc
-12 stdcall DefMDIChildProc(long long long long) DefMDIChildProc
-13 stdcall SystemMessageBoxProc(long long long long) SystemMessageBoxProc
-14 stdcall FileOpenDlgProc(long long long long) FileOpenDlgProc
-15 stdcall FileSaveDlgProc(long long long long) FileSaveDlgProc
-16 stdcall ColorDlgProc(long long long long) ColorDlgProc
-17 stdcall FindTextDlgProc(long long long long) FindTextDlgProc
-18 stdcall ReplaceTextDlgProc(long long long long) ReplaceTextDlgProc
-19 stdcall PrintSetupDlgProc(long long long long) PrintSetupDlgProc
-20 stdcall PrintDlgProc(long long long long) PrintDlgProc
-21 stdcall AboutDlgProc(long long long long) AboutDlgProc
-22 stdcall ComboLBoxWndProc(long long long long) ComboLBoxWndProc
+1  stdcall ButtonWndProc(long long long long) ButtonWndProc32
+2  stdcall StaticWndProc(long long long long) StaticWndProc32
+3  stdcall ScrollBarWndProc(long long long long) ScrollBarWndProc32
+4  stdcall ListBoxWndProc(long long long long) ListBoxWndProc32
+5  stdcall ComboBoxWndProc(long long long long) ComboBoxWndProc32
+6  stdcall EditWndProc(long long long long) EditWndProc32
+7  stdcall PopupMenuWndProc(long long long long) PopupMenuWndProc32
+8  stdcall DesktopWndProc(long long long long) DesktopWndProc32
+9  stdcall DefDlgProc(long long long long) DefDlgProc32
+10 stdcall MDIClientWndProc(long long long long) MDIClientWndProc32
+11 stdcall DefWindowProc(long long long long) DefWindowProc32
+12 stdcall DefMDIChildProc(long long long long) DefMDIChildProc32
+13 stdcall SystemMessageBoxProc(long long long long) SystemMessageBoxProc32
+14 stdcall FileOpenDlgProc(long long long long) FileOpenDlgProc32
+15 stdcall FileSaveDlgProc(long long long long) FileSaveDlgProc32
+16 stdcall ColorDlgProc(long long long long) ColorDlgProc32
+17 stdcall FindTextDlgProc(long long long long) FindTextDlgProc32
+18 stdcall ReplaceTextDlgProc(long long long long) ReplaceTextDlgProc32
+19 stdcall PrintSetupDlgProc(long long long long) PrintSetupDlgProc32
+20 stdcall PrintDlgProc(long long long long) PrintDlgProc32
+21 stdcall AboutDlgProc(long long long long) AboutDlgProc32
+22 stdcall ComboLBoxWndProc(long long long long) ComboLBoxWndProc32
 23 stdcall CARET_Callback(long long long long) CARET_Callback
diff --git a/include/arch.h b/include/arch.h
index be237fa..fc7c5cb 100644
--- a/include/arch.h
+++ b/include/arch.h
@@ -6,8 +6,8 @@
 
 #if defined (mc68000) || defined (sparc)
 
-#define CONV_LONG(a) (((a)&0xFF) << 24) | (((a) & 0xFF00) << 8) | (((unsigned long)(a) & 0xFF0000) >> 8) | ((unsigned long)((a)&0xFF000000) >> 24) 
-#define CONV_SHORT(a) (((a) & 0xFF) << 8) | (((unsigned long)(a) & 0xFF00) >> 8)
+#define CONV_LONG(a) (((int)(a)&0xFF) << 24) | (((int)(a) & 0xFF00) << 8) | (((unsigned long)(a) & 0xFF0000) >> 8) | (((unsigned long)(a)&0xFF000000) >> 24) 
+#define CONV_SHORT(a) (((int)(a) & 0xFF) << 8) | (((unsigned long)(a) & 0xFF00) >> 8)
 #define CONV_CHAR_TO_LONG(x) ((unsigned long)(x) >> 24)
 #define CONV_SHORT_TO_LONG(x) ((unsigned long)(x) >> 16)
 
diff --git a/include/directory.h b/include/directory.h
new file mode 100644
index 0000000..c466af8
--- /dev/null
+++ b/include/directory.h
@@ -0,0 +1,18 @@
+/*
+ * DOS directory handling declarations
+ *
+ * Copyright 1996 Alexandre Julliard
+ */
+
+#ifndef __WINE_DIRECTORY_H
+#define __WINE_DIRECTORY_H
+
+extern int DIR_Init(void);
+extern UINT DIR_GetWindowsUnixDir( LPSTR path, UINT count );
+extern UINT DIR_GetSystemUnixDir( LPSTR path, UINT count );
+extern UINT DIR_GetTempUnixDir( LPSTR path, UINT count );
+extern UINT DIR_GetTempDosDir( LPSTR path, UINT count );
+extern UINT DIR_GetDosPath( int element, LPSTR path, UINT count );
+extern UINT DIR_GetUnixPath( int element, LPSTR path, UINT count );
+
+#endif  /* __WINE_DIRECTORY_H */
diff --git a/include/dos_fs.h b/include/dos_fs.h
index 1200dfd..2bcca39 100644
--- a/include/dos_fs.h
+++ b/include/dos_fs.h
@@ -1,37 +1,42 @@
+/*
+ * DOS file system declarations
+ *
+ * Copyright 1996 Alexandre Julliard
+ */
+
 #ifndef __WINE_DOS_FS_H
 #define __WINE_DOS_FS_H
 
-#include <wintypes.h>
+#include <time.h>
+#include "wintypes.h"
 
-extern void DOS_InitFS(void);
-extern WORD DOS_GetEquipment(void);
-extern int DOS_ValidDrive(int drive);
-extern int DOS_GetDefaultDrive(void); 
-extern void DOS_SetDefaultDrive(int drive);
-extern void ToUnix(char *s); 
-extern void ToDos(char *s); 
-extern int DOS_DisableDrive(int drive);
-extern int DOS_EnableDrive(int drive); 
-extern char *DOS_GetUnixFileName(const char *dosfilename);
-extern char *DOS_GetDosFileName(char *unixfilename);
-extern char *DOS_GetCurrentDir(int drive);
-extern int DOS_ChangeDir(int drive, char *dirname);
-extern int DOS_MakeDir(int drive, char *dirname);
-extern int DOS_GetSerialNumber(int drive, unsigned long *serialnumber); 
-extern int DOS_SetSerialNumber(int drive, unsigned long serialnumber); 
-extern char *DOS_GetVolumeLabel(int drive);
-extern int DOS_SetVolumeLabel(int drive, char *label);
+#define MAX_FILENAME_LEN   256
+#define MAX_PATHNAME_LEN   1024
+
+typedef struct
+{
+    char   name[12];                    /* File name in FCB format */
+    char   unixname[MAX_FILENAME_LEN];  /* Unix file name */
+    DWORD  size;                        /* File size in bytes */
+    WORD   date;                        /* File date in DOS format */
+    WORD   time;                        /* File time in DOS format */
+    BYTE   attr;                        /* File DOS attributes */
+} DOS_DIRENT;
+
+#define IS_END_OF_NAME(ch)  (!(ch) || ((ch) == '/') || ((ch) == '\\'))
+
+extern void DOSFS_ToDosDateTime( time_t *unixtime, WORD *pDate, WORD *pTime );
+extern const char *DOSFS_ToDosFCBFormat( const char *name );
+extern const char *DOSFS_ToDosDTAFormat( const char *name );
+extern const char *DOSFS_IsDevice( const char *name );
+extern const char * DOSFS_GetUnixFileName( const char * name, int check_last );
+extern const char * DOSFS_GetDosTrueName( const char *name, int unix_format );
+extern int DOSFS_GetDosFileName( const char *name, char *buffer, int len );
+extern int DOSFS_FindNext( const char *path, const char *mask, int drive,
+                           BYTE attr, int skip, DOS_DIRENT *entry );
+
+
 extern int DOS_GetFreeSpace(int drive, long *size, long *available);
-extern char *DOS_FindFile(char *buffer, int buflen, const char *rootname, char **extensions, char *path);
 extern char *WineIniFileName(void);
-extern char *WinIniFileName(void); 
-extern struct dosdirent *DOS_opendir(char *dosdirname); 
-extern struct dosdirent *DOS_readdir(struct dosdirent *de);
-extern void DOS_closedir(struct dosdirent *de);
-extern char *DOS_GetRedirectedDir(int drive);
-extern void errno_to_doserr(void);
-extern int DOS_Error(int extended, int class, int locus);
-
-extern char WindowsPath[256];
 
 #endif /* __WINE_DOS_FS_H */
diff --git a/include/drive.h b/include/drive.h
new file mode 100644
index 0000000..ab9fa9d
--- /dev/null
+++ b/include/drive.h
@@ -0,0 +1,29 @@
+/*
+ * DOS drive handling declarations
+ *
+ * Copyright 1995 Alexandre Julliard
+ */
+
+#ifndef __WINE_DRIVE_H
+#define __WINE_DRIVE_H
+
+#include "wintypes.h"
+
+#define MAX_DOS_DRIVES  26
+
+extern int DRIVE_Init(void);
+extern int DRIVE_IsValid( int drive );
+extern int DRIVE_GetCurrentDrive(void);
+extern int DRIVE_SetCurrentDrive( int drive );
+extern int DRIVE_FindDriveRoot( const char **path );
+extern const char * DRIVE_GetRoot( int drive );
+extern const char * DRIVE_GetDosCwd( int drive );
+extern const char * DRIVE_GetUnixCwd( int drive );
+extern const char * DRIVE_GetLabel( int drive );
+extern DWORD DRIVE_GetSerialNumber( int drive );
+extern int DRIVE_SetSerialNumber( int drive, DWORD serial );
+extern int DRIVE_Chdir( int drive, const char *path );
+extern int DRIVE_Disable( int drive  );
+extern int DRIVE_Enable( int drive  );
+
+#endif  /* __WINE_DRIVE_H */
diff --git a/include/file.h b/include/file.h
new file mode 100644
index 0000000..1c585a4
--- /dev/null
+++ b/include/file.h
@@ -0,0 +1,29 @@
+/*
+ * File handling declarations
+ *
+ * Copyright 1996 Alexandre Julliard
+ */
+
+#ifndef __WINE_FILE_H
+#define __WINE_FILE_H
+
+#include "windows.h"
+
+extern void FILE_SetDosError(void);
+extern int FILE_GetUnixHandle( HFILE handle );
+extern void FILE_CloseAllFiles( HANDLE hPDB );
+extern int FILE_Open( LPCSTR path, int mode );
+extern int FILE_Create( LPCSTR path, int mode, int unique );
+extern int FILE_Stat( LPCSTR unixName, BYTE *pattr, DWORD *psize,
+                      WORD *pdate, WORD *ptime );
+extern int FILE_Fstat( HFILE hFile, BYTE *pattr, DWORD *psize,
+                       WORD *pdate, WORD *ptime );
+extern int FILE_Unlink( LPCSTR path );
+extern int FILE_MakeDir( LPCSTR path );
+extern int FILE_RemoveDir( LPCSTR path );
+extern HFILE FILE_Dup( HFILE hFile );
+extern HFILE FILE_Dup2( HFILE hFile1, HFILE hFile2 );
+extern int FILE_OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode );
+extern INT _lcreat_uniq( LPCSTR path, INT attr );
+
+#endif  /* __WINE_FILE_H */
diff --git a/include/kernel32.h b/include/kernel32.h
index 367a639..ecb4fc6 100644
--- a/include/kernel32.h
+++ b/include/kernel32.h
@@ -14,6 +14,7 @@
 /* Linux's wchar_t is unsigned long but Win32 wants unsigned short
  */
 typedef unsigned short WCHAR;
+typedef WCHAR *LPTSTR;
 
 /* Code page information.
  */
diff --git a/include/menu.h b/include/menu.h
index 59f292d..5a25e1e 100644
--- a/include/menu.h
+++ b/include/menu.h
@@ -15,8 +15,6 @@
 extern void MENU_TrackKbdMenuBar( HWND hwnd, UINT wParam );      /* menu.c */
 extern UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect,
 			      HWND hwnd, BOOL suppress_draw );   /* menu.c */
-extern HMENU CopySysMenu(); /* menu.c */
-
 extern LRESULT PopupMenuWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam );
 
 typedef struct tagMENUITEM
diff --git a/include/message.h b/include/message.h
index 85159b0..bf242b7 100644
--- a/include/message.h
+++ b/include/message.h
@@ -63,6 +63,8 @@
 #pragma pack(4)
 #endif
 
+extern DWORD MSG_WineStartTicks;  /* Ticks at Wine startup */
+
 extern void MSG_IncPaintCount( HANDLE hQueue );
 extern void MSG_DecPaintCount( HANDLE hQueue );
 extern void MSG_IncTimerCount( HANDLE hQueue );
diff --git a/include/module.h b/include/module.h
index 3ca58cc..1641754 100644
--- a/include/module.h
+++ b/include/module.h
@@ -112,6 +112,7 @@
 extern BOOL MODULE_Init(void);
 extern int MODULE_OpenFile( HMODULE hModule );
 extern LPSTR MODULE_GetModuleName( HMODULE hModule );
+extern void MODULE_RegisterModule( HMODULE hModule );
 extern WORD MODULE_GetOrdinal( HMODULE hModule, char *name );
 extern SEGPTR MODULE_GetEntryPoint( HMODULE hModule, WORD ordinal );
 extern BOOL MODULE_SetEntryPoint( HMODULE hModule, WORD ordinal, WORD offset );
diff --git a/include/msdos.h b/include/msdos.h
index 5964d82..e399be1 100644
--- a/include/msdos.h
+++ b/include/msdos.h
@@ -32,6 +32,22 @@
 	BYTE dummy2[9];
 };
 
+/* DTA layout for FindFirst/FindNext */
+typedef struct
+{
+    BYTE   drive;                /* 00 drive letter */
+    char   mask[11];             /* 01 search template */
+    BYTE   search_attr;          /* 0c search attributes */
+    WORD   count WINE_PACKED;    /* 0d entry count within directory */
+    WORD   cluster WINE_PACKED;  /* 0f cluster of parent directory */
+    char  *unixPath WINE_PACKED; /* 11 unix path (was: reserved) */
+    BYTE   fileattr;             /* 15 file attributes */
+    WORD   filetime;             /* 16 file time */
+    WORD   filedate;             /* 18 file date */
+    DWORD  filesize WINE_PACKED; /* 1a file size */
+    char   filename[13];         /* 1e file name + extension */
+} FINDFILE_DTA;
+
 
 #define DOSVERSION 0x1606      /* Major version in low byte: DOS 6.22 */
 #define WINDOSVER  0x0616      /* Windows reports the DOS version reversed */
@@ -48,89 +64,94 @@
                              *((BYTE*)((a)+1)) = ((b)>>8) & 0xff;\
                         } while(0)
 			
-#define setdword(a,b)	do { *(BYTE*)(a)	= (b) & 0xff; \
-			     *((BYTE*)(a)+1) = ((b)>>8) & 0xff; \
-			     *((BYTE*)(a)+2) = ((b)>>16) & 0xff; \
-			     *((BYTE*)(a)+3) = ((b)>>24) & 0xff; \
-                        } while(0)
-
-#define getword(a)	( (WORD)*(BYTE*)(a) + \
-			  ((WORD)*((BYTE*)(a) + 1) << 8))
-
-#define getdword(a)	( (DWORD)*(BYTE*)(a) + \
-			  (DWORD)(*((BYTE*)(a) + 1) << 8) + \
-			  (DWORD)(*((BYTE*)(a) + 2) << 16) + \
-			  (DWORD)(*((BYTE*)(a) + 3) << 24))
 
 /* dos file attributes */
 
-#define FA_NORMAL   0x00        /* Normal file, no attributes */
-#define FA_RDONLY   0x01        /* Read only attribute */
-#define FA_HIDDEN   0x02        /* Hidden file */
-#define FA_SYSTEM   0x04        /* System file */
-#define FA_LABEL    0x08        /* Volume label */
-#define FA_DIREC    0x10        /* Directory */
-#define FA_ARCH     0x20        /* Archive */
+#define FA_NORMAL    0x00        /* Normal file, no attributes */
+#define FA_RDONLY    0x01        /* Read only attribute */
+#define FA_HIDDEN    0x02        /* Hidden file */
+#define FA_SYSTEM    0x04        /* System file */
+#define FA_LABEL     0x08        /* Volume label */
+#define FA_DIRECTORY 0x10        /* Directory */
+#define FA_ARCHIVE   0x20        /* Archive */
+#define FA_UNUSED    0x40        /* Unused */
 
-/* extended error codes */
 
-#define NoError		0x00
-#define InvalidFunction 0x01
-#define FileNotFound	0x02
-#define PathNotFound	0x03
-#define AccessDenied	0x05
-#define InvalidHandle	0x06
-#define MCBDestroyed	0x07
-#define	OutOfMemory	0x08
-#define MCBInvalid	0x09
-#define DataInvalid	0x0d
-#define InvalidDrive	0x0f
-#define CanNotRemoveCwd	0x10
-#define	NotSameDevice	0x11
-#define NoMoreFiles	0x12
-#define WriteProtected  0x13
-#define	UnknownUnit	0x14
-#define DriveNotReady	0x15
-#define UnknownCommand	0x16
-#define CRCError	0x17
-#define	BadRqLength	0x18
-#define SeekError	0x19
-#define	UnknownMedia	0x1a
-#define	SectorNotFound	0x1b
-#define OutOfPaper	0x1c
-#define WriteFault	0x1d
-#define ReadFault	0x1e
-#define	GeneralFailure	0x1f
-#define ShareViolation	0x20
-#define LockViolation	0x21
-#define DiskFull	0x27
-#define NoNetwork	0x49
-#define FileExists	0x50
-#define CanNotMakeDir	0x52
+extern WORD DOS_ExtendedError;
+extern BYTE DOS_ErrorClass, DOS_ErrorAction, DOS_ErrorLocus;
+
+#define DOS_ERROR(err,class,action,locus) \
+    ( DOS_ErrorClass = (class), DOS_ErrorAction = (action), \
+      DOS_ErrorLocus = (locus), DOS_ExtendedError = (err) )
+
+/* Error codes */
+
+#define ER_NoError           0x00
+#define ER_InvalidFunction   0x01
+#define ER_FileNotFound      0x02
+#define ER_PathNotFound      0x03
+#define ER_TooManyOpenFiles  0x04
+#define ER_AccessDenied      0x05
+#define ER_InvalidHandle     0x06
+#define ER_MCBDestroyed      0x07
+#define ER_OutOfMemory       0x08
+#define ER_MCBInvalid        0x09
+#define ER_EnvironInvalid    0x0a
+#define ER_FormatInvalid     0x0b
+#define ER_AccessCodeInvalid 0x0c
+#define ER_DataInvalid       0x0d
+#define ER_InvalidDrive      0x0f
+#define ER_CanNotRemoveCwd   0x10
+#define ER_NotSameDevice     0x11
+#define ER_NoMoreFiles       0x12
+#define ER_WriteProtected    0x13
+#define ER_UnknownUnit       0x14
+#define ER_DriveNotReady     0x15
+#define ER_UnknownCommand    0x16
+#define ER_CRCError          0x17
+#define ER_BadRqLength       0x18
+#define ER_SeekError         0x19
+#define ER_UnknownMedia      0x1a
+#define ER_SectorNotFound    0x1b
+#define ER_OutOfPaper        0x1c
+#define ER_WriteFault        0x1d
+#define ER_ReadFault         0x1e
+#define ER_GeneralFailure    0x1f
+#define ER_ShareViolation    0x20
+#define ER_LockViolation     0x21
+#define ER_DiskFull          0x27
+#define ER_NoNetwork         0x49
+#define ER_FileExists        0x50
+#define ER_CanNotMakeDir     0x52
 
 /* Error classes */
 
-#define EC_Temporary	0x02
-#define EC_AccessDenied	0x03
-#define EC_AppError	0x04
-#define EC_SystemFailure 0x06
-#define EC_NotFound	0x08
-#define	EC_MediaError	0x0b
-#define EC_Exists	0x0c
-#define	EC_Unknown	0x0d
+#define EC_OutOfResource     0x01
+#define EC_Temporary         0x02
+#define EC_AccessDenied      0x03
+#define EC_InternalError     0x04
+#define EC_HardwareFailure   0x05
+#define EC_SystemFailure     0x06
+#define EC_ProgramError      0x07
+#define EC_NotFound          0x08
+#define EC_MediaError        0x0b
+#define EC_Exists            0x0c
+#define EC_Unknown           0x0d
 
 /* Suggested actions */
 
-#define	SA_Retry	0x01
-#define SA_Abort	0x04
-#define SA_Ignore	0x06
-#define SA_Ask4Retry	0x07
+#define SA_Retry             0x01
+#define SA_DelayedRetry      0x02
+#define SA_Abort             0x04
+#define SA_Ignore            0x06
+#define SA_Ask4Retry         0x07
 
 /* Error locus */
 
-#define EL_Unknown	0x01
-#define EL_Disk		0x02
-#define EL_Network	0x03
-#define EL_Memory	0x05
+#define EL_Unknown           0x01
+#define EL_Disk              0x02
+#define EL_Network           0x03
+#define EL_Serial            0x04
+#define EL_Memory            0x05
 
 #endif /* __MSDOS_H */
diff --git a/include/pe_image.h b/include/pe_image.h
index b83e651..220f5b2 100644
--- a/include/pe_image.h
+++ b/include/pe_image.h
@@ -9,6 +9,10 @@
 	struct PE_Import_Directory *pe_import;
 	struct PE_Export_Directory *pe_export;
 	struct PE_Resource_Directory *pe_resource;
+	struct PE_Reloc_Block *pe_reloc;
+	int base_addr;
+	int load_addr;
+	int vma_size;
 	int resource_offset; /* offset to resource typedirectory in file */
 };
 
@@ -18,7 +22,6 @@
     char * name;   /* Name, as it appears in the windows binaries */
     char * filename; /* Actual name of the unix file that satisfies this */
     int type;        /* DLL or EXE */
-    int fd;
     HINSTANCE hinstance;
     HMODULE hModule;
     int initialised;
@@ -31,8 +34,7 @@
 
 extern int PE_unloadImage(struct w_files *wpnt);
 extern int PE_StartProgram(struct w_files *wpnt);
-extern void PE_InitDLL(struct w_files *wpnt);
-extern HINSTANCE PE_LoadImage(struct w_files *wpnt);
+extern void PE_InitDLL(HMODULE hModule);
 extern void my_wcstombs(char * result, u_short * source, int len);
 extern struct w_files *wine_files;
 
diff --git a/include/peexe.h b/include/peexe.h
index 43aa48a..ff85a08 100644
--- a/include/peexe.h
+++ b/include/peexe.h
@@ -167,7 +167,7 @@
   u_long * AddressOfFunctions;
   u_long * AddressOfNames;
   u_short * Address_Of_Name_Ordinals;
-  u_char ModuleName[1];
+/*  u_char ModuleName[1]; */
 };
 
 /*
@@ -213,4 +213,18 @@
 #define IMAGE_RESOURCE_NAME_IS_STRING    0x80000000
 #define IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000
 
+struct PE_Reloc_Block
+{
+	u_long PageRVA;
+	u_long BlockSize;
+	short Relocations[1];
+};
+
+#define IMAGE_REL_BASED_ABSOLUTE 		0
+#define IMAGE_REL_BASED_HIGH			1
+#define IMAGE_REL_BASED_LOW				2
+#define IMAGE_REL_BASED_HIGHLOW			3
+#define IMAGE_REL_BASED_HIGHADJ			4
+#define IMAGE_REL_BASED_MIPS_JMPADDR	5
+
 #endif /* __WINE_PEEXE_H */
diff --git a/include/registers.h b/include/registers.h
index 2114b54..93a9567 100644
--- a/include/registers.h
+++ b/include/registers.h
@@ -106,10 +106,18 @@
 
                             
 #define EIP_reg(context)      ((context)->uc_mcontext.gregs[EIP])
+#ifdef R_ESP
 #define ESP_reg(context)     ((context)->uc_mcontext.gregs[R_ESP])
+#else
+#define ESP_reg(context)     ((context)->uc_mcontext.gregs[ESP])
+#endif
                             
 #define IP_reg(context)      (*(WORD*)(&(context)->uc_mcontext.gregs[EIP]))
+#ifdef R_ESP
 #define SP_reg(context)      (*(WORD*)(&(context)->uc_mcontext.gregs[R_ESP]))
+#else
+#define SP_reg(context)      (*(WORD*)(&(context)->uc_mcontext.gregs[ESP]))
+#endif
                             
 #define SET_CFLAG(context)   (EFL_reg(context) |= 0x0001)
 #define RESET_CFLAG(context) (EFL_reg(context) &= 0xfffffffe)
diff --git a/include/resource32.h b/include/resource32.h
new file mode 100644
index 0000000..6a2ac43
--- /dev/null
+++ b/include/resource32.h
@@ -0,0 +1,47 @@
+/*
+ * Win32 functions, structures, and types related to resources
+ *
+ * Copyright 1995 Thomas Sandford
+ *
+ */
+
+#ifndef __WINE_RESOURCE32_H
+#define __WINE_RESOURCE32_H
+
+#include <stddef.h>
+
+HANDLE32 FindResource32( HINSTANCE hModule, LPCTSTR name, LPCTSTR type );
+HANDLE32 LoadResource32( HINSTANCE hModule, HANDLE32 hRsrc );
+LPVOID LockResource32( HANDLE32 handle );
+BOOL FreeResource32( HANDLE32 handle );
+INT AccessResource32( HINSTANCE hModule, HRSRC hRsrc );
+DWORD SizeofResource32( HINSTANCE hModule, HRSRC hRsrc );
+int LoadString32(HINSTANCE instance, DWORD resource_id, LPTSTR buffer, int buflen);
+
+typedef struct _IMAGE_RESOURCE_DIRECTORY {
+	DWORD Characteristics;
+	DWORD TimeDateStamp;
+	WORD MajorVersion;
+	WORD MinorVersion;
+	WORD NumberOfNamedEntries;
+	WORD NumberOfIdEntries;
+} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;
+
+typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
+	DWORD Name;
+	DWORD OffsetToData;
+} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;
+
+typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
+	DWORD OffsetToData;
+	DWORD Size;
+	DWORD CodePage;
+	DWORD Reserved;
+} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY;
+
+typedef struct _IMAGE_RESOURCE_DIR_STRING_U {
+	WORD Length;
+	WCHAR NameString[1];
+} IMAGE_RESOURCE_DIR_STRING_U, *PIMAGE_RESOURCE_DIR_STRING_U;
+
+#endif  /* __WINE_RESOURCE32_H */
diff --git a/include/stackframe.h b/include/stackframe.h
index cf4358b..a9d4020 100644
--- a/include/stackframe.h
+++ b/include/stackframe.h
@@ -66,9 +66,12 @@
 
   /* Make a segmented pointer from a pointer to a variable located */
   /* on the 32-bit stack for the current task. */
+#if 0
 #define MAKE_SEGPTR(ptr) \
      ((SEGPTR)IF1632_Stack32_base + \
       ((DWORD)(ptr) - (DWORD)PTR_SEG_TO_LIN(IF1632_Stack32_base)))
+#endif
+SEGPTR MAKE_SEGPTR(void *ptr);
 #else
 #define CURRENT_STACK16	error.error
 #define CURRENT_DS		0
diff --git a/include/task.h b/include/task.h
index fd5604d..d2a2b30 100644
--- a/include/task.h
+++ b/include/task.h
@@ -21,20 +21,23 @@
 
 typedef struct
 {
-    WORD   int20;            /* int 20h instruction */
-    WORD   nextParagraph;    /* Segment of next paragraph */
+    WORD   int20;                   /* 00 int 20h instruction */
+    WORD   nextParagraph;           /* 02 Segment of next paragraph */
     BYTE   reserved1;
-    BYTE   dispatcher[5];    /* Long call to DOS */
-    SEGPTR savedint22;       /* Saved int 22h handler */
-    SEGPTR savedint23;       /* Saved int 23h handler */
-    SEGPTR savedint24;       /* Saved int 24h handler */
-    WORD   parentPSP;        /* Selector of parent PSP */
-    BYTE   fileHandles[20];  /* Open file handles */
-    HANDLE environment;      /* Selector of environment */
-    WORD   reserved2[23];
-    BYTE   fcb1[16];         /* First FCB */
-    BYTE   fcb2[20];         /* Second FCB */
-    BYTE   cmdLine[128];     /* Command-line (first byte is length) */
+    BYTE   dispatcher[5];           /* 05 Long call to DOS */
+    SEGPTR savedint22 WINE_PACKED;  /* 0a Saved int 22h handler */
+    SEGPTR savedint23 WINE_PACKED;  /* 0e Saved int 23h handler */
+    SEGPTR savedint24 WINE_PACKED;  /* 12 Saved int 24h handler */
+    WORD   parentPSP;               /* 16 Selector of parent PSP */
+    BYTE   fileHandles[20];         /* 18 Open file handles */
+    HANDLE environment;             /* 2c Selector of environment */
+    WORD   reserved2[2];
+    WORD   nbFiles;                 /* 32 Number of file handles */
+    SEGPTR fileHandlesPtr;          /* 34 Pointer to file handle table */
+    WORD   reserved3[18];
+    BYTE   fcb1[16];                /* 5c First FCB */
+    BYTE   fcb2[20];                /* 6c Second FCB */
+    BYTE   cmdLine[128];            /* 80 Command-line (first byte is len) */
 } PDB;
 
 
@@ -66,7 +69,7 @@
     DWORD   esp;                        /* 32-bit stack pointer */
     WORD    ctrlword8087;               /* 80x87 control word */
     WORD    flags;                      /* Task flags */
-    WORD    error_flags;                /* Error handling flags */
+    UINT    error_mode;                 /* Error mode (see SetErrorMode) */
     WORD    version;                    /* Expected Windows version */
     HANDLE  hInstance;                  /* Instance handle for this task */
     HMODULE hModule;                    /* Module handle */
diff --git a/include/toolhelp.h b/include/toolhelp.h
index 5ffb1b4..43d0e7f 100644
--- a/include/toolhelp.h
+++ b/include/toolhelp.h
@@ -232,6 +232,15 @@
 BOOL MemManInfo(LPMEMMANINFO lpEnhMode);
 BOOL SystemHeapInfo( SYSHEAPINFO *pHeapInfo );
 
+/* timer info */
+
+typedef struct tagTIMERINFO {
+	DWORD dwSize;
+	DWORD dwmsSinceStart;
+	DWORD dwmsThisVM;
+} TIMERINFO;
+
+BOOL TimerInfo( TIMERINFO *pTimerInfo );
 
 /* Window classes */
 
diff --git a/include/windows.h b/include/windows.h
index 3934834..b7f8298 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -765,6 +765,9 @@
 #define WINDING           2
 
   /* Background modes */
+#ifdef TRANSPARENT  /*Apparently some broken svr4 includes define TRANSPARENT*/
+#undef TRANSPARENT
+#endif
 #define TRANSPARENT       1
 #define OPAQUE            2
 
@@ -1034,37 +1037,42 @@
 typedef KANJISTRUCT *NPKANJISTRUCT;
 typedef KANJISTRUCT *PKANJISTRUCT;
 
-typedef struct {
-	BYTE cBytes, fFixedDisk;
-	WORD nErrCode;
-	BYTE reserved[4], szPathName[128];
+typedef struct
+{
+    BYTE cBytes;
+    BYTE fFixedDisk;
+    WORD nErrCode;
+    BYTE reserved[4];
+    BYTE szPathName[128];
 } OFSTRUCT;
-typedef OFSTRUCT *POFSTRUCT;
-typedef OFSTRUCT *NPOFSTRUCT;
 typedef OFSTRUCT *LPOFSTRUCT;
 
-#define OF_READ 0x0000
-#define OF_WRITE 0x0001
-#define OF_READWRITE 0x0002
-#define OF_CANCEL 0x0800
-#define OF_CREATE 0x1000
-#define OF_DELETE 0x0200
-#define OF_EXIST 0x4000
-#define OF_PARSE 0x0100
-#define OF_PROMPT 0x2000
-#define OF_REOPEN 0x8000
-#define OF_SHARE_COMPAT 0x0000
-#define OF_SHARE_DENY_NONE 0x0040
-#define OF_SHARE_DENY_READ 0x0030
-#define OF_SHARE_DENY_WRITE 0x0020
-#define OF_SHARE_EXCLUSIVE 0x0010
-#define OF_VERIFY 0x0400
+#define OF_READ               0x0000
+#define OF_WRITE              0x0001
+#define OF_READWRITE          0x0002
+#define OF_SHARE_COMPAT       0x0000
+#define OF_SHARE_EXCLUSIVE    0x0010
+#define OF_SHARE_DENY_WRITE   0x0020
+#define OF_SHARE_DENY_READ    0x0030
+#define OF_SHARE_DENY_NONE    0x0040
+#define OF_PARSE              0x0100
+#define OF_DELETE             0x0200
+#define OF_VERIFY             0x0400   /* Used with OF_REOPEN */
+#define OF_SEARCH             0x0400   /* Used without OF_REOPEN */
+#define OF_CANCEL             0x0800
+#define OF_CREATE             0x1000
+#define OF_PROMPT             0x2000
+#define OF_EXIST              0x4000
+#define OF_REOPEN             0x8000
 
-#define DRIVE_CANNOTDETERMINE	0
-#define DRIVE_DOESNOTEXIST	1
-#define DRIVE_REMOVABLE	2
-#define DRIVE_FIXED	3
-#define DRIVE_REMOTE	4
+/* GetTempFileName() Flags */
+#define TF_FORCEDRIVE	        0x80
+
+#define DRIVE_CANNOTDETERMINE      0
+#define DRIVE_DOESNOTEXIST         1
+#define DRIVE_REMOVABLE            2
+#define DRIVE_FIXED                3
+#define DRIVE_REMOTE               4
 
 #define HFILE_ERROR	-1
 
@@ -1687,6 +1695,8 @@
 #define SW_SHOWMINNOACTIVE  7
 #define SW_SHOWNA           8
 #define SW_RESTORE          9
+#define SW_SHOWDEFAULT	    10
+#define SW_MAX		    10
 
   /* WM_SIZE message wParam values */
 #define SIZE_RESTORED        0
@@ -2648,8 +2658,8 @@
 HANDLE     DirectResAlloc(HANDLE,WORD,WORD);
 void       DirectedYield(HTASK);
 LONG       DispatchMessage(LPMSG);
-int        DlgDirList(HWND,LPSTR,int,int,WORD);
-int        DlgDirListComboBox(HWND,SEGPTR,int,int,WORD);
+INT        DlgDirList(HWND,SEGPTR,INT,INT,WORD);
+INT        DlgDirListComboBox(HWND,SEGPTR,INT,INT,WORD);
 BOOL       DlgDirSelect(HWND,LPSTR,int);
 BOOL       DlgDirSelectComboBox(HWND,LPSTR,int);
 BOOL       DragDetect(HWND,POINT);
@@ -2808,11 +2818,11 @@
 DWORD      GetPixel(HDC,short,short);
 WORD       GetPolyFillMode(HDC);
 int        GetPriorityClipboardFormat(WORD*,short);
-WORD       GetPrivateProfileInt(LPSTR,LPSTR,short,LPSTR);
-short      GetPrivateProfileString(LPSTR,LPSTR,LPSTR,LPSTR,short,LPSTR);
+WORD       GetPrivateProfileInt(LPCSTR,LPCSTR,short,LPCSTR);
+short      GetPrivateProfileString(LPCSTR,LPCSTR,LPCSTR,LPSTR,short,LPCSTR);
 FARPROC    GetProcAddress(HANDLE,SEGPTR);
-WORD       GetProfileInt(LPSTR,LPSTR,int);
-int        GetProfileString(LPSTR,LPSTR,LPSTR,LPSTR,int);
+WORD       GetProfileInt(LPCSTR,LPCSTR,int);
+int        GetProfileString(LPCSTR,LPCSTR,LPCSTR,LPSTR,int);
 HANDLE     GetProp(HWND,SEGPTR);
 WORD       GetROP2(HDC);
 WORD       GetRelAbs(HDC);
@@ -2933,6 +2943,7 @@
 WORD       IsDlgButtonChecked(HWND,WORD);
 BOOL       IsIconic(HWND);
 BOOL       IsRectEmpty(LPRECT);
+HTASK      IsTaskLocked(void);
 BOOL       IsTwoByteCharPrefix(char);
 BOOL       IsWindow(HWND);
 BOOL       IsWindowEnabled(HWND);
@@ -2996,7 +3007,7 @@
 BOOL       OffsetWindowOrgEx(HDC,short,short,LPPOINT);
 BOOL       OpenClipboard(HWND);
 int        OpenComm(LPSTR,UINT,UINT);
-INT        OpenFile(LPCSTR,LPOFSTRUCT,UINT);
+HFILE      OpenFile(LPCSTR,OFSTRUCT*,UINT);
 BOOL       OpenIcon(HWND);
 int        OpenSound(void);
 void       OutputDebugString(LPSTR);
@@ -3088,12 +3099,12 @@
 int        SetDIBits(HDC,HANDLE,WORD,WORD,LPSTR,LPBITMAPINFO,WORD);
 int        SetDIBitsToDevice(HDC,short,short,WORD,WORD,WORD,WORD,WORD,WORD,LPSTR,LPBITMAPINFO,WORD);
 BOOL       SetDeskPattern(void);
-BOOL       SetDeskWallPaper(LPSTR);
+BOOL       SetDeskWallPaper(LPCSTR);
 void       SetDlgItemInt(HWND,WORD,WORD,BOOL);
 void       SetDlgItemText(HWND,WORD,SEGPTR);
 void       SetDoubleClickTime(WORD);
 int        SetEnvironment(LPSTR,LPSTR,WORD);
-BOOL       SetErrorMode(WORD);
+UINT       SetErrorMode(UINT);
 HWND       SetFocus(HWND);
 WORD       SetHandleCount(WORD);
 void       SetInternalWindowPos(HWND,WORD,LPRECT,LPPOINT);
@@ -3206,19 +3217,20 @@
 BOOL       WritePrivateProfileString(LPSTR,LPSTR,LPSTR,LPSTR);
 BOOL       WriteProfileString(LPSTR,LPSTR,LPSTR);
 void       Yield(void);
-LONG       _hread(INT,LPSTR,LONG);
-LONG       _hwrite(INT,LPCSTR,LONG);
-INT        _lclose(INT);
-INT        _lcreat(LPSTR,INT);
-LONG       _llseek(INT,LONG,INT);
-INT        _lopen(LPSTR,INT);
-INT        _lread(INT,LPSTR,WORD);
-INT        _lwrite(INT,LPCSTR,WORD);
+LONG       _hread(HFILE,LPSTR,LONG);
+LONG       _hwrite(HFILE,LPCSTR,LONG);
+HFILE      _lclose(HFILE);
+HFILE      _lcreat(LPCSTR,INT);
+LONG       _llseek(HFILE,LONG,INT);
+HFILE      _lopen(LPCSTR,INT);
+INT        _lread(HFILE,LPSTR,WORD);
+INT        _lwrite(HFILE,LPCSTR,WORD);
 SEGPTR     lstrcat(SEGPTR,SEGPTR);
 INT        lstrcmp(LPCSTR,LPCSTR);
 INT        lstrcmpi(LPCSTR,LPCSTR);
+INT        lstrncmpi(LPCSTR,LPCSTR,int);
 SEGPTR     lstrcpy(SEGPTR,SEGPTR);
-char *     lstrcpyn(char *,char *,int);
+char *     lstrcpyn(char *,const char *,int);
 INT        lstrlen(LPCSTR);
 int        wvsprintf(LPSTR,LPSTR,LPSTR);
 
diff --git a/include/wine.h b/include/wine.h
index 29b6c44..8feab54 100644
--- a/include/wine.h
+++ b/include/wine.h
@@ -1,11 +1,9 @@
-#ifndef  WINE_H
-#define  WINE_H
+#ifndef  __WINE_WINE_H
+#define  __WINE_WINE_H
 
 extern char *WineIniFileName(void);
-extern char *WinIniFileName(void);
 
 #define WINE_INI WineIniFileName()
-#define WIN_INI WinIniFileName()
 
 #ifdef i386
 extern int runtime_cpu (void);
@@ -13,6 +11,7 @@
 static inline int runtime_cpu(void) { return 3; }
 #endif
 
+#ifndef WINELIB
 
 #if defined ( linux) 
 struct sigcontext_struct
@@ -66,4 +65,6 @@
 #define WINE_CODE_SELECTOR 0x1f
 #endif
 
-#endif /* WINE_H */
+#endif  /* WINELIB */
+
+#endif /* __WINE_WINE_H */
diff --git a/include/winsock.h b/include/winsock.h
index 6223573..56a8fad 100644
--- a/include/winsock.h
+++ b/include/winsock.h
@@ -7,6 +7,7 @@
 #ifndef _WINSOCKAPI_
 #define _WINSOCKAPI_
 
+#include <arpa/inet.h>
 #include <sys/types.h>
 #include <sys/time.h>
 #include <fcntl.h>
@@ -26,12 +27,14 @@
 /*
  * Internet address (old style... should be updated)
  */
+#ifdef WS_USE_OLD_STYLE
 #define s_addr  S_un.S_addr	/* can be used for most tcp & ip code */
 #define s_host  S_un.S_un_b.s_b2	/* host on imp */
 #define s_net   S_un.S_un_b.s_b1	/* network */
 #define s_imp   S_un.S_un_w.s_w2	/* imp */
 #define s_impno S_un.S_un_b.s_b4	/* imp # */
 #define s_lh    S_un.S_un_b.s_b3	/* logical host */
+#endif
 
 #define WSADESCRIPTION_LEN      256
 #define WSASYS_STATUS_LEN       128
@@ -62,23 +65,6 @@
 #define SO_DONTLINGER   (u_int)(~SO_LINGER)
 #endif
 
-#ifndef _SYS_SOCKET_H_
-#ifndef _sys_socket_h
-#ifndef _NET_TRANSPORT_SOCKET_H
-#ifndef _NET_SOCKET_H
-/*
- * Structure used by kernel to pass protocol
- * information in raw sockets.
- */
-struct sockproto {
-        u_short sp_family;              /* address family */
-        u_short sp_protocol;            /* protocol */
-};
-#endif
-#endif
-#endif
-#endif
-
 /*
  * Maximum queue length specifiable by listen.
  */
diff --git a/include/wintypes.h b/include/wintypes.h
index 30ecb94..f0cc840 100644
--- a/include/wintypes.h
+++ b/include/wintypes.h
@@ -48,6 +48,7 @@
 #endif
 typedef LONG LPARAM;
 typedef LONG LRESULT;
+typedef INT HFILE;
 typedef DWORD HHOOK;
 typedef char *LPSTR;
 typedef const char *LPCSTR;
@@ -90,6 +91,8 @@
 DECLARE_HANDLE(HWND);
 DECLARE_HANDLE(LOCALHANDLE);
 
+typedef HGLOBAL GLOBALHANDLE;
+
 #ifdef WINELIB
 typedef long (*FARPROC)();
 typedef LRESULT (*WNDPROC)(HWND,UINT,WPARAM,LPARAM);
diff --git a/include/xmalloc.h b/include/xmalloc.h
index e8b183d..396fde0 100644
--- a/include/xmalloc.h
+++ b/include/xmalloc.h
@@ -1,3 +1,6 @@
+#ifndef __WINE_XMALLOC_H
+#define __WINE_XMALLOC_H
+
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #else
@@ -6,3 +9,6 @@
 
 void *xmalloc (size_t);
 void *xrealloc (void *, size_t);
+char *xstrdup( const char * );
+
+#endif  /* __WINE_XMALLOC_H */
diff --git a/ipc/dde_atom.c b/ipc/dde_atom.c
index 5ca9b42..6d24908 100644
--- a/ipc/dde_atom.c
+++ b/ipc/dde_atom.c
@@ -66,7 +66,7 @@
       deleted=hash1;
       break;
     default :			   /* non empty atom entry */
-      if (  strcasecmp( OFS2AtomStr(atom_ofs) , str) == 0)
+      if (lstrcmpi( OFS2AtomStr(atom_ofs) , str) == 0)
 	 return hash1;		   /* found string in atom table */
   }
   hash2%= DDE_ATOMS-1 ;		   /* hash2=0..(DDE_ATOMS-2) */
@@ -92,7 +92,7 @@
 	    deleted= i;
 	 break;
        default :		   /* nonempty atom entry */
-	 if (  strcasecmp( OFS2AtomStr(atom_ofs) , str) == 0)
+	 if (lstrcmpi( OFS2AtomStr(atom_ofs) , str) == 0)
 	    return i;	   /* found string in atom table */
      }
   }
diff --git a/library/atom.c b/library/atom.c
index 48fbfbe..a87f938 100644
--- a/library/atom.c
+++ b/library/atom.c
@@ -80,7 +80,7 @@
 	  FirstUnusedIndex=Index;
 	}
 	else if ((table->a2h[i].length == len) && 
-		 (!strncasecmp( table->a2h[i].str, str, len )))
+		 (!lstrncmpi( table->a2h[i].str, str, len )))
 	{
 	    table->a2h[i].refCount++;
 	    return Index;
@@ -176,7 +176,7 @@
       {
 	if ((table->a2h[i].refCount != 0) &&
 	    (table->a2h[i].length == len) && 
-	    (!strncasecmp( table->a2h[i].str, str, len )))
+	    (!lstrncmpi( table->a2h[i].str, str, len )))
 	  return Index;
       }
       table=table->next;
diff --git a/library/libres.c b/library/libres.c
index 5f4c5b5..0d1511e 100644
--- a/library/libres.c
+++ b/library/libres.c
@@ -101,7 +101,6 @@
  */
 BOOL LIBRES_FreeResource( HGLOBAL handle )
 {
-  WINELIB_UNIMP("LIBRES_FreeResource()");
   return 0; /* Obsolete in Win32 */
 }
 
diff --git a/library/miscstubs.c b/library/miscstubs.c
index 8f62d4c..c1cb479 100644
--- a/library/miscstubs.c
+++ b/library/miscstubs.c
@@ -45,7 +45,7 @@
 
 void GlobalFreeAll(HANDLE owner)
 {
-  fprintf(stderr,"JBP: GlobalFreeAll() ignored.\n");
+  WINELIB_UNIMP("GlobalFreeAll()");
 }
 
 SEGPTR WIN16_GlobalLock(HGLOBAL h) 
@@ -65,7 +65,7 @@
 
 void FarSetOwner(HANDLE a, WORD b)
 {
-  fprintf(stderr,"JBP: FarSetOwner() ignored.\n");
+  WINELIB_UNIMP("FarSetOwner()");
 }
 
 #define GLOBAL_MAX_ALLOC_SIZE 0x00ff0000  /* Largest allocation is 16M - 64K */
@@ -114,13 +114,11 @@
 			    BOOL is32Bit, BOOL isReadOnly,
 			    SHMDATA *shmdata)
 {
-/*  fprintf(stderr,"JBP: GLOBAL_CreateBlock() faked.\n");*/
   return (HGLOBAL)ptr;
 }
 
 BOOL GLOBAL_FreeBlock( HGLOBAL handle )
 {
-/*  fprintf(stderr,"JBP: GLOBAL_FreeBlock() ignored.\n");*/
   return 1;
 }
 
@@ -132,10 +130,10 @@
 
 void *RELAY32_GetEntryPoint(char *dll_name, char *item, int hint)
 {
-/*  fprintf(stderr,"JBP: RELAY32_GetEntryPoint() ignored.\n");*/
   return NULL;
 }
 
+extern LRESULT ACTIVATEAPP_callback(HWND,UINT,WPARAM,LPARAM);
 extern LRESULT AboutDlgProc(HWND,UINT,WPARAM,LPARAM);
 extern LRESULT ButtonWndProc(HWND,UINT,WPARAM,LPARAM);
 extern LRESULT CARET_Callback(HWND,UINT,WPARAM,LPARAM);
@@ -172,6 +170,7 @@
 WNDPROC GetWndProcEntry16( char *name )
 {
 #define MAP_STR_TO_PROC(str,proc) if(!strcmp(name,str))return proc
+  MAP_STR_TO_PROC("ActivateAppProc",ACTIVATEAPP_callback);
   MAP_STR_TO_PROC("AboutDlgProc",AboutDlgProc);
   MAP_STR_TO_PROC("ButtonWndProc",ButtonWndProc);
   MAP_STR_TO_PROC("CARET_Callback",CARET_Callback);
@@ -194,5 +193,6 @@
   MAP_STR_TO_PROC("StaticWndProc",StaticWndProc);
   MAP_STR_TO_PROC("SystemMessageBoxProc",SystemMessageBoxProc);
   MAP_STR_TO_PROC("TASK_Reschedule",TASK_Reschedule);
+  fprintf(stderr,"warning: No mapping for %s(), add one in library/miscstubs.c\n",name);
   return ErrorProc;
 }
diff --git a/libtest/README.rolex b/libtest/README.rolex
deleted file mode 100644
index a481683..0000000
--- a/libtest/README.rolex
+++ /dev/null
@@ -1,8 +0,0 @@
-Windows clock application for WINE (by Jim Peterson)
-
-This is a translation of a Turbo Pascal OWL application I made once,
-so it's a little flaky (tons of globals, functions that could have
-been in-lined, etc.).  The file rolex.exe is a Win32 application
-compiled using this source code and Borland C++ 4.0.
-
-To try it out, type 'make rolex' or 'wine ./rolex.exe' (which fails).
diff --git a/libtest/rolex.c b/libtest/rolex.c
index fc71f79..2f5212c 100644
--- a/libtest/rolex.c
+++ b/libtest/rolex.c
@@ -1,3 +1,16 @@
+/*********************************************************************
+ *                                                                   *
+ *  rolex.c: Windows clock application for WINE (by Jim Peterson)    *
+ *                                                                   *
+ *  This is a translation of a Turbo Pascal OWL application I made   *
+ *  once, so it's a little flaky (tons of globals, functions that    *
+ *  could have been in-lined, etc.).  The source code should easily  *
+ *  compile with a standard Win32 C compiler.                        *
+ *                                                                   *
+ *  To try it out, type 'make rolex'.                                *
+ *                                                                   *
+ *********************************************************************/
+
 #include <math.h>
 #include <string.h>
 #include "windows.h"
diff --git a/loader/main.c b/loader/main.c
index de7df1e..8ee5a4e 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -20,12 +20,13 @@
 #include "kernel32.h"
 #include "atom.h"
 #include "dialog.h"
+#include "directory.h"
+#include "drive.h"
 #include "message.h"
 #include "syscolor.h"
 #include "sysmetrics.h"
 #include "gdi.h"
 #include "debugger.h"
-#include "dos_fs.h"
 #include "dlls.h"
 #include "miscemu.h"
 #include "neexe.h"
@@ -63,8 +64,11 @@
       /* Create built-in modules */
     if (!MODULE_Init()) return 0;
 
-      /* Initialize the DOS file system */
-    DOS_InitFS();
+    /* Initialise DOS drives */
+    if (!DRIVE_Init()) return 0;
+
+    /* Initialise DOS directories */
+    if (!DIR_Init()) return 0;
 
       /* Initialize tasks */
     if (!TASK_Init()) return 0;
diff --git a/loader/module.c b/loader/module.c
index d46529d..5c9557a 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -13,6 +13,7 @@
 #include "windows.h"
 #include "dlls.h"
 #include "dos_fs.h"
+#include "file.h"
 #include "global.h"
 #include "ldt.h"
 #include "module.h"
@@ -56,7 +57,7 @@
     if ((p = strrchr( dllname, '.' ))) *p = '\0';
 
     for (i = 0, table = dll_builtin_table; i < N_BUILTINS; i++, table++)
-        if (!strcasecmp( table->name, dllname )) break;
+        if (!lstrcmpi( table->name, dllname )) break;
     if (i >= N_BUILTINS) return 0;
     if (!table->used && !force) return 0;
 
@@ -110,9 +111,6 @@
         !MODULE_LoadBuiltin( "GDI", TRUE ) ||
         !MODULE_LoadBuiltin( "USER", TRUE ) ||
         !MODULE_LoadBuiltin( "WINPROCS", TRUE )) return FALSE;
-
-#else
-    fprintf(stderr, "JBP: MODULE_Init() ignored.\n");
 #endif
     /* Initialize KERNEL.178 (__WINFLAGS) with the correct flags value */
 
@@ -260,6 +258,7 @@
 {
     NE_MODULE *pModule;
     char *name;
+    const char *unixName;
 
     static int cachedfd = -1;
 
@@ -271,19 +270,21 @@
     close( cachedfd );
     hCachedModule = hModule;
     name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
-    if ((cachedfd = open( DOS_GetUnixFileName( name ), O_RDONLY )) == -1)
+    if (!(unixName = DOSFS_GetUnixFileName( name, TRUE )) ||
+        (cachedfd = open( unixName, O_RDONLY )) == -1)
         fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module "NPFMT"\n",
                  name, hModule );
     dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
                     name, cachedfd );
     return cachedfd;
 }
+
+
 /***********************************************************************
  *           MODULE_Ne2MemFlags
+ *
+ * This function translates NE segment flags to GlobalAlloc flags
  */
-
-/* This function translates NE segment flags to GlobalAlloc flags */
-
 static WORD MODULE_Ne2MemFlags(WORD flags)
 { 
     WORD memflags = 0;
@@ -813,6 +814,17 @@
 
 
 /**********************************************************************
+ *           MODULE_RegisterModule
+ */
+void MODULE_RegisterModule( HMODULE hModule )
+{
+	NE_MODULE *pModule;
+	pModule = (NE_MODULE *)GlobalLock( hModule );
+	pModule->next = hFirstModule;
+	hFirstModule = hModule;
+}
+
+/**********************************************************************
  *	    MODULE_FindModule
  *
  * Find a module from a path name.
@@ -837,10 +849,10 @@
         if (!(modulename = strrchr( modulepath, '\\' )))
             modulename = modulepath;
         else modulename++;
-        if (!strcasecmp( modulename, filename )) return hModule;
+        if (!lstrcmpi( modulename, filename )) return hModule;
 
         name_table = (BYTE *)pModule + pModule->name_table;
-        if ((*name_table == len) && !strncasecmp(filename, name_table+1, len))
+        if ((*name_table == len) && !lstrncmpi(filename, name_table+1, len))
             return hModule;
         hModule = pModule->next;
     }
@@ -928,8 +940,7 @@
         /* Try to load the built-in first if not disabled */
         if ((hModule = MODULE_LoadBuiltin( name, FALSE ))) return hModule;
 
-        if (strchr( name, '/' )) name = DOS_GetDosFileName( name );
-        if ((fd = OpenFile( name, &ofs, OF_READ )) == -1)
+        if ((fd = FILE_OpenFile( name, &ofs, OF_READ )) == -1)
         {
             /* Now try the built-in even if disabled */
             if ((hModule = MODULE_LoadBuiltin( name, TRUE )))
@@ -942,11 +953,11 @@
 
           /* Create the module structure */
 
-        if ((hModule = MODULE_LoadExeHeader( fd, &ofs )) < 32)
+        hModule = MODULE_LoadExeHeader( fd, &ofs );
+        if (hModule == 21) hModule = PE_LoadModule( fd, &ofs, paramBlock );
+        close( fd );
+        if (hModule < 32)
         {
-			if(hModule == 21)
-				return PE_LoadModule(fd,&ofs,paramBlock);
-            close( fd );
             fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
                      name, hModule );
             return hModule;
@@ -1214,7 +1225,7 @@
     if (handle == (HANDLE)2)  /* file not found */
     {
         char buffer[256];
-        strcpy( buffer, libname );
+        lstrcpyn( buffer, libname, 252 );
         strcat( buffer, ".dll" );
         handle = LoadModule( buffer, (LPVOID)-1 );
     }
diff --git a/loader/ne_image.c b/loader/ne_image.c
index eff083e..80eea87 100644
--- a/loader/ne_image.c
+++ b/loader/ne_image.c
@@ -508,6 +508,11 @@
     HMODULE *pDLL;
 
     pModule = (NE_MODULE *)GlobalLock( hModule );
+	if (pModule->magic == PE_SIGNATURE)
+	{
+		PE_InitializeDLLs(hModule);
+		return;
+	}
     if (pModule->dlls_to_init)
     {
 	HANDLE to_init = pModule->dlls_to_init;
diff --git a/loader/ne_resource.c b/loader/ne_resource.c
index caf1e0d..5eee682 100644
--- a/loader/ne_resource.c
+++ b/loader/ne_resource.c
@@ -67,8 +67,8 @@
                 if (p[1] & 0x8000)
                 {
                     if (!HIWORD(typeId)) continue;
-                    if (strcasecmp( (char *)PTR_SEG_TO_LIN(typeId),
-                                   (char *)(p + 3) )) continue;
+                    if (lstrcmpi( (char *)PTR_SEG_TO_LIN(typeId),
+                                  (char *)(p + 3) )) continue;
                 }
                 else if (HIWORD(typeId) || ((typeId & ~0x8000)!= p[1]))
                   continue;
@@ -78,7 +78,7 @@
                 if (p[2] & 0x8000)
                 {
                     if (!HIWORD(resId)) continue;
-                    if (strcasecmp( (char *)PTR_SEG_TO_LIN(resId),
+                    if (lstrcmpi( (char *)PTR_SEG_TO_LIN(resId),
                                (char*)(p+3)+strlen((char*)(p+3))+1 )) continue;
                     
                 }
@@ -119,7 +119,7 @@
         {
             if (pNameInfo->id & 0x8000) continue;
             p = (BYTE *)pModule + pModule->res_table + pNameInfo->id;
-            if ((*p == len) && !strncasecmp( p+1, str, len ))
+            if ((*p == len) && !lstrncmpi( p+1, str, len ))
                 return (HRSRC)((int)pNameInfo - (int)pModule);
         }
     }
@@ -167,7 +167,7 @@
             if (!(pTypeInfo->type_id & 0x8000))
             {
                 BYTE *p = (BYTE*)pModule+pModule->res_table+pTypeInfo->type_id;
-                if ((*p == len) && !strncasecmp( p+1, str, len ))
+                if ((*p == len) && !lstrncmpi( p+1, str, len ))
                 {
                     dprintf_resource( stddeb, "  Found type '%s'\n", str );
                     hRsrc = NE_FindResourceFromType(pModule, pTypeInfo, resId);
@@ -240,20 +240,21 @@
 {
     NE_MODULE *pModule;
     NE_NAMEINFO *pNameInfo=NULL;
-    WORD sizeShift;
     char *name;
     int fd;
 
     pModule = (NE_MODULE *)GlobalLock( hModule );
-    if (!pModule || !pModule->res_table) return 0;
+    if (!pModule || !pModule->res_table) return -1;
 #ifndef WINELIB
     pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
 #endif
 
     name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
-    fd = open( DOS_GetUnixFileName(name), O_RDONLY );
-    sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
-    lseek( fd, (int)pNameInfo->offset << sizeShift, SEEK_SET );
+    if ((fd = _lopen( name, OF_READ )) != -1)
+    {
+        WORD sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
+        _llseek( fd, (int)pNameInfo->offset << sizeShift, SEEK_SET );
+    }
     return fd;
 }
 
diff --git a/loader/pe_image.c b/loader/pe_image.c
index 8a05457..f7f3f72 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -33,8 +33,6 @@
 #include "debug.h"
 #include "xmalloc.h"
 
-#define MAP_ANONYMOUS	0x20
-
 struct w_files *wine_files = NULL;
 
 void my_wcstombs(char * result, u_short * source, int len)
@@ -48,6 +46,7 @@
   };
 }
 
+#if 0
 char * xmmap(char * vaddr, unsigned int v_size, unsigned int r_size,
 	int prot, int flags, int fd, unsigned int file_offset)
 {
@@ -75,6 +74,7 @@
   read(fd, vaddr, v_size);
   return vaddr;
 };
+#endif
 
 void dump_exports(struct PE_Export_Directory * pe_exports, unsigned int load_addr)
 { 
@@ -102,14 +102,76 @@
     }
 }
 
-void fixup_imports(struct PE_Import_Directory *pe_imports,unsigned int load_addr)
+DWORD PE_FindExportedFunction(struct w_files* wpnt, char* funcName)
+{
+	struct PE_Export_Directory * exports = wpnt->pe->pe_export;
+	unsigned load_addr = wpnt->pe->load_addr;
+	u_short * ordinal;
+	u_long * function;
+	u_char ** name, *ename;
+	int i;
+	if(!exports)return 0;
+	ordinal = (u_short *) (((char *) load_addr) + (int) exports->Address_Of_Name_Ordinals);
+	function = (u_long *)  (((char *) load_addr) + (int) exports->AddressOfFunctions);
+	name = (u_char **)  (((char *) load_addr) + (int) exports->AddressOfNames);
+	for(i=0; i<exports->Number_Of_Functions; i++)
+	{
+		ename =  (char *) (((char *) load_addr) + (int) *name);
+		if(strcmp(ename,funcName)==0)
+			return load_addr+*function;
+		function++;
+		ordinal++;
+		name++;
+	}
+	return 0;
+}
+
+DWORD PE_GetProcAddress(HMODULE hModule, char* function)
+{
+	struct w_files *wpnt;
+	for(wpnt=wine_files;wpnt;wpnt=wpnt->next)
+		if(wpnt->hModule==hModule) break;
+	if(!wpnt)return 0;
+	return PE_FindExportedFunction(wpnt,function);
+}
+
+void fixup_imports(struct w_files* wpnt)
 { 
   struct PE_Import_Directory * pe_imp;
   int fixup_failed=0;
+  unsigned int load_addr = wpnt->pe->load_addr;
+  int i;
+  NE_MODULE *ne_mod;
+  HMODULE *mod_ptr;
 
  /* OK, now dump the import list */
   dprintf_win32(stddeb, "\nDumping imports list\n");
-  pe_imp = pe_imports;
+
+  /* first, count the number of imported non-internal modules */
+  pe_imp = wpnt->pe->pe_import;
+  for(i=0;pe_imp->ModuleName;pe_imp++)
+  	i++;
+
+  /* Now, allocate memory for dlls_to_init */
+  ne_mod = GlobalLock(wpnt->hModule);
+  ne_mod->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,(i+1) * sizeof(HMODULE),
+  					wpnt->hModule, FALSE, FALSE, FALSE );
+  mod_ptr = GlobalLock(ne_mod->dlls_to_init);
+  /* load the modules and put their handles into the list */
+  for(i=0,pe_imp = wpnt->pe->pe_import;pe_imp->ModuleName;pe_imp++)
+  {
+  	char *name = (char*)load_addr+pe_imp->ModuleName;
+  	if(RELAY32_GetBuiltinDLL(name))
+		continue;
+	mod_ptr[i] = LoadModule(name,(LPVOID)-1);
+	if(mod_ptr[i]<=(HMODULE)32)
+	{
+		fprintf(stderr,"Module %s not found\n",name);
+		exit(0);
+	}
+	i++;
+  }
+  pe_imp = wpnt->pe->pe_import;
   while (pe_imp->ModuleName)
     {
       char * Module;
@@ -126,6 +188,8 @@
       if (c) *c = 0;
 #endif
 
+   if(pe_imp->Import_List != 0) { /* original microsoft style */
+      dprintf_win32(stddeb, "Microsoft style imports used\n");
       import_list = (unsigned int *) 
 	(((unsigned int) load_addr) + pe_imp->Import_List);
 	  thunk_list = (unsigned int *)
@@ -142,7 +206,12 @@
 	  }
 	  dprintf_win32(stddeb, "--- %s %s.%d\n", pe_name->Name, Module, pe_name->Hint);
 #ifndef WINELIB /* FIXME: JBP: Should this happen in libwine.a? */
+	/* Both calls should be unified into GetProcAddress */
 	  *thunk_list=(unsigned int)RELAY32_GetEntryPoint(Module,pe_name->Name,pe_name->Hint);
+	  if(*thunk_list == 0)
+	  	*thunk_list = WIN32_GetProcAddress(MODULE_FindModule(Module),
+				pe_name->Name);
+
 #else
 	  fprintf(stderr,"JBP: Call to RELAY32_GetEntryPoint being ignored.\n");
 #endif
@@ -155,12 +224,35 @@
 	  import_list++;
 	  thunk_list++;
 	}
-      pe_imp++;
-    };
-	if(fixup_failed)exit(1);
+    } else { /* Borland style */
+      dprintf_win32(stddeb, "Borland style imports used\n");
+      thunk_list = (unsigned int *)
+        (((unsigned int) load_addr) + pe_imp->Thunk_List);
+      while(*thunk_list) {
+        pe_name = (struct pe_import_name *) ((int) load_addr + *thunk_list);
+        if((unsigned)pe_name & 0x80000000) {
+          fprintf(stderr,"Import by ordinal not supported\n");
+          exit(0);
+        }
+        dprintf_win32(stddeb, "--- %s %s.%d\n", pe_name->Name, Module, pe_name->Hint);
+#ifndef WINELIB /* FIXME: JBP: Should this happen in libwine.a? */
+        *thunk_list=(unsigned int)RELAY32_GetEntryPoint(Module,pe_name->Name,pe_name->Hint);
+#else
+        fprintf(stderr,"JBP: Call to RELAY32_GetEntryPoint being ignored.\n");
+#endif
+        if(!*thunk_list) {
+          fprintf(stderr,"No implementation for %s.%d\n",Module, pe_name->Hint);
+          fixup_failed=1;
+        }
+        thunk_list++;
+      }
+    }
+    pe_imp++;
+  }
+  if(fixup_failed)exit(1);
 }
 
-static void dump_table(struct w_files *wpnt)
+static void calc_vma_size(struct w_files *wpnt)
 {
   int i;
 
@@ -179,48 +271,138 @@
 	     wpnt->pe->pe_seg[i].NumberOfRelocations,
 	     wpnt->pe->pe_seg[i].NumberOfLinenumbers,
 	     wpnt->pe->pe_seg[i].Characteristics);
+	  wpnt->pe->vma_size = max(wpnt->pe->vma_size,
+	  		wpnt->pe->pe_seg[i].Virtual_Address + 
+			wpnt->pe->pe_seg[i].Size_Of_Raw_Data);
     }
 }
 
+static void do_relocations(struct w_files *wpnt)
+{
+	int delta = wpnt->pe->load_addr - wpnt->pe->base_addr;
+	struct PE_Reloc_Block *r = wpnt->pe->pe_reloc;
+	int hdelta = (delta >> 16) & 0xFFFF;
+	int ldelta = delta & 0xFFFF;
+	/* int reloc_size = */
+	if(delta == 0)
+		/* Nothing to do */
+		return;
+	while(r->PageRVA)
+	{
+		char *page = (char*)wpnt->pe->load_addr + r->PageRVA;
+		int count = (r->BlockSize - 8)/2;
+		int i;
+		dprintf_fixup(stddeb, "%x relocations for page %lx\n",
+			count, r->PageRVA);
+		/* patching in reverse order */
+		for(i=0;i<count;i++)
+		{
+			int offset = r->Relocations[i] & 0xFFF;
+			int type = r->Relocations[i] >> 12;
+			dprintf_fixup(stddeb,"patching %x type %x\n", offset, type);
+			switch(type)
+			{
+			case IMAGE_REL_BASED_ABSOLUTE: break;
+			case IMAGE_REL_BASED_HIGH:
+				*(short*)(page+offset) += hdelta;
+				break;
+			case IMAGE_REL_BASED_LOW:
+				*(short*)(page+offset) += ldelta;
+				break;
+			case IMAGE_REL_BASED_HIGHLOW:
+#if 1
+				*(int*)(page+offset) += delta;
+#else
+				{ int h=*(unsigned short*)(page+offset);
+				  int l=r->Relocations[++i];
+				  *(unsigned int*)(page + offset) = (h<<16) + l + delta;
+				}
+#endif
+				break;
+			case IMAGE_REL_BASED_HIGHADJ:
+				fprintf(stderr, "Don't know what to do with IMAGE_REL_BASED_HIGHADJ\n");
+				break;
+			case IMAGE_REL_BASED_MIPS_JMPADDR:
+				fprintf(stderr, "Is this a MIPS machine ???\n");
+				break;
+			default:
+				fprintf(stderr, "Unknown fixup type\n");
+				break;
+			}
+		}
+		r = (struct PE_Reloc_Block*)((char*)r + r->BlockSize);
+	}
+}
+		
+
+	
+	
+
 /**********************************************************************
  *			PE_LoadImage
  * Load one PE format executable into memory
  */
-HINSTANCE PE_LoadImage(struct w_files *wpnt)
+static HINSTANCE PE_LoadImage( int fd, struct w_files *wpnt )
 {
 	int i, result;
-        unsigned int load_addr;
+    unsigned int load_addr;
 
 	wpnt->pe = xmalloc(sizeof(struct pe_data));
 	memset(wpnt->pe,0,sizeof(struct pe_data));
 	wpnt->pe->pe_header = xmalloc(sizeof(struct pe_header_s));
 
 	/* read PE header */
-	lseek(wpnt->fd, wpnt->mz_header->ne_offset, SEEK_SET);
-	read(wpnt->fd, wpnt->pe->pe_header, sizeof(struct pe_header_s));
+	lseek( fd, wpnt->mz_header->ne_offset, SEEK_SET);
+	read( fd, wpnt->pe->pe_header, sizeof(struct pe_header_s));
 
 	/* read sections */
 	wpnt->pe->pe_seg = xmalloc(sizeof(struct pe_segment_table) * 
 				   wpnt->pe->pe_header->coff.NumberOfSections);
-	read(wpnt->fd, wpnt->pe->pe_seg, sizeof(struct pe_segment_table) * 
+	read( fd, wpnt->pe->pe_seg, sizeof(struct pe_segment_table) * 
 			wpnt->pe->pe_header->coff.NumberOfSections);
 
 	load_addr = wpnt->pe->pe_header->opt_coff.BaseOfImage;
+	wpnt->pe->base_addr=load_addr;
+	wpnt->pe->vma_size=0;
 	dprintf_win32(stddeb, "Load addr is %x\n",load_addr);
-	dump_table(wpnt);
+	calc_vma_size(wpnt);
+
+	/* We use malloc here, while a huge part of that address space does
+	   not be supported by actual memory. It has to be contiguous, though.
+	   I don't know if mmap("/dev/null"); would do any better.
+	   What I'd really like to do is a Win32 style VirtualAlloc/MapViewOfFile
+	   sequence */
+	load_addr = wpnt->pe->load_addr = malloc(wpnt->pe->vma_size);
+	dprintf_win32(stddeb, "Load addr is really %x, range %x\n",
+		wpnt->pe->load_addr, wpnt->pe->vma_size);
+
 
 	for(i=0; i < wpnt->pe->pe_header->coff.NumberOfSections; i++)
 	{
+		/* load only non-BSS segments */
+		if(wpnt->pe->pe_seg[i].Characteristics & 
+			~ IMAGE_SCN_TYPE_CNT_UNINITIALIZED_DATA)
+		if(lseek(fd,wpnt->pe->pe_seg[i].PointerToRawData,SEEK_SET) == -1
+		|| read(fd,load_addr + wpnt->pe->pe_seg[i].Virtual_Address,
+				wpnt->pe->pe_seg[i].Size_Of_Raw_Data) 
+				!= wpnt->pe->pe_seg[i].Size_Of_Raw_Data)
+		{
+			fprintf(stderr,"Failed to load section %x\n", i);
+			exit(0);
+		}
+		result = load_addr + wpnt->pe->pe_seg[i].Virtual_Address;
+#if 0
 	if(!load_addr) {
+		
 		result = (int)xmmap((char *)0, wpnt->pe->pe_seg[i].Virtual_Size,
 			wpnt->pe->pe_seg[i].Size_Of_Raw_Data, 7,
-			MAP_PRIVATE, wpnt->fd, wpnt->pe->pe_seg[i].PointerToRawData);
+			MAP_PRIVATE, fd, wpnt->pe->pe_seg[i].PointerToRawData);
 		load_addr = (unsigned int) result -  wpnt->pe->pe_seg[i].Virtual_Address;
 	} else {
 		result = (int)xmmap((char *) load_addr + wpnt->pe->pe_seg[i].Virtual_Address, 
 			  wpnt->pe->pe_seg[i].Virtual_Size,
 		      wpnt->pe->pe_seg[i].Size_Of_Raw_Data, 7, MAP_PRIVATE | MAP_FIXED, 
-		      wpnt->fd, wpnt->pe->pe_seg[i].PointerToRawData);
+		      fd, wpnt->pe->pe_seg[i].PointerToRawData);
 	}
 	if(result==-1){
 		fprintf(stderr,"Could not load section %x to desired address %lx\n",
@@ -228,6 +410,13 @@
 		fprintf(stderr,"Need to implement relocations now\n");
 		exit(0);
 	}
+#endif
+
+        if(strcmp(wpnt->pe->pe_seg[i].Name, ".bss") == 0)
+            memset((void *)result, 0, 
+                   wpnt->pe->pe_seg[i].Virtual_Size ?
+                   wpnt->pe->pe_seg[i].Virtual_Size :
+                   wpnt->pe->pe_seg[i].Size_Of_Raw_Data);
 
 	if(strcmp(wpnt->pe->pe_seg[i].Name, ".idata") == 0)
 		wpnt->pe->pe_import = (struct PE_Import_Directory *) result;
@@ -242,10 +431,16 @@
 	    wpnt->pe->resource_offset = wpnt->pe->pe_seg[i].Virtual_Address - 
 					wpnt->pe->pe_seg[i].PointerToRawData;
 	    }
+	
+	if(strcmp(wpnt->pe->pe_seg[i].Name, ".reloc") == 0)
+		wpnt->pe->pe_reloc = (struct PE_Reloc_Block *) result;
+
 	}
 
-	if(wpnt->pe->pe_import) fixup_imports(wpnt->pe->pe_import,load_addr);
+
+	if(wpnt->pe->pe_import) fixup_imports(wpnt);
 	if(wpnt->pe->pe_export) dump_exports(wpnt->pe->pe_export,load_addr);
+	if(wpnt->pe->pe_reloc) do_relocations(wpnt);
   
 	wpnt->hinstance = (HINSTANCE)0x8000;
 	wpnt->load_addr = load_addr;
@@ -271,7 +466,6 @@
 
 	wpnt=xmalloc(sizeof(struct w_files));
 	wpnt->ofs=*ofs;
-	wpnt->fd=fd;
 	wpnt->type=0;
 	wpnt->hinstance=0;
 	wpnt->hModule=0;
@@ -348,7 +542,9 @@
 	pModule->res_table=pModule->import_table=pModule->entry_table=
 		(int)pStr-(int)pModule;
 
-	PE_LoadImage(wpnt);
+        MODULE_RegisterModule(hModule);
+
+	PE_LoadImage( fd, wpnt );
 
 	pModule->heap_size=0x1000;
 	pModule->stack_size=0xE000;
@@ -358,34 +554,38 @@
 	wpnt->hinstance=hInstance;
 
 	if (wpnt->pe->pe_export) {
-		wpnt->name = xmalloc(strlen(wpnt->pe->pe_export->ModuleName)+1);
-		strcpy(wpnt->name, wpnt->pe->pe_export->ModuleName);
+		pStr = ((unsigned char *)(wpnt->load_addr))+wpnt->pe->pe_export->Name;
+		wpnt->name = xstrdup(pStr);
 	} else {
-		wpnt->name = xmalloc(strlen(ofs->szPathName)+1);
-		strcpy(wpnt->name, ofs->szPathName);
+		wpnt->name = xstrdup( ofs->szPathName );
 	}
 
 	wpnt->next=wine_files;
 	wine_files=wpnt;
 
-	if (!(wpnt->pe->pe_header->coff.Characteristics & IMAGE_FILE_DLL))
-	TASK_CreateTask(hModule,hInstance,0,
+        /* FIXME: Is this really the correct place to initialise the DLL? */
+	if ((wpnt->pe->pe_header->coff.Characteristics & IMAGE_FILE_DLL)) {
+            PE_InitDLL(wpnt);
+        } else {
+            TASK_CreateTask(hModule,hInstance,0,
 		params->hEnvironment,(LPSTR)PTR_SEG_TO_LIN(params->cmdLine),
 		*((WORD*)PTR_SEG_TO_LIN(params->showCmd)+1));
-	
+	}
 	return hInstance;
 }
 
 int USER_InitApp(HINSTANCE hInstance);
+void PE_InitTEB(int hTEB);
 
 void PE_Win32CallToStart(struct sigcontext_struct context)
 {
 	int fs;
 	struct w_files *wpnt=wine_files;
-	fs=(int)GlobalAlloc(GHND,0x10000);
 	dprintf_win32(stddeb,"Going to start Win32 program\n");	
 	InitTask(context);
 	USER_InitApp(wpnt->hModule);
+        fs=(int)GlobalAlloc(GHND,0x10000);
+        PE_InitTEB(fs);
 	__asm__ __volatile__("movw %w0,%%fs"::"r" (fs));
 	((void(*)())(wpnt->load_addr+wpnt->pe->pe_header->opt_coff.AddressOfEntryPoint))();
 }
@@ -397,11 +597,68 @@
 	return 1;
 }
 
-void PE_InitDLL(struct w_files *wpnt)
+void PE_InitDLL(HMODULE hModule)
 {
+	struct w_files *wpnt;
+	hModule = GetExePtr(hModule);
+	for(wpnt = wine_files;wpnt && wpnt->hModule != hModule;
+		wpnt = wpnt->next) /*nothing*/;
+	if(!wpnt || wpnt->initialised)
+		return;
+        /* FIXME: What are the correct values for parameters 2 and 3? */
+        
 	/* Is this a library? */
 	if (wpnt->pe->pe_header->coff.Characteristics & IMAGE_FILE_DLL) {
+		/* Should call DLLEntryPoint here */
 		printf("InitPEDLL() called!\n");
+		wpnt->initialised = 1;
+                ((void(*)())(wpnt->load_addr+wpnt->pe->pe_header->opt_coff.AddressOfEntryPoint))(wpnt->hModule, 0, 0);
 	}
 }
+
+
+/* FIXME: This stuff is all on a "well it works" basis. An implementation
+based on some kind of documentation would be greatly appreciated :-) */
+
+typedef struct
+{
+    void        *Except;
+    void        *stack;
+    int	        dummy1[4];
+    struct TEB  *TEBDSAlias;
+    int	        dummy2[2];
+    int	        taskid;
+} TEB;
+
+void PE_InitTEB(int hTEB)
+{
+    TDB *pTask;
+    TEB *pTEB;
+
+    pTask = (TDB *)(GlobalLock(GetCurrentTask() & 0xffff));
+    pTEB = (TEB *)(PTR_SEG_OFF_TO_LIN(hTEB, 0));
+    pTEB->stack = (void *)(GlobalLock(pTask->hStack32));
+    pTEB->Except = (void *)(-1); 
+    pTEB->TEBDSAlias = pTEB;
+    pTEB->taskid = getpid();
+}
+
+void PE_InitializeDLLs(HMODULE hModule)
+{
+	NE_MODULE *pModule;
+	HMODULE *pDLL;
+	pModule = (NE_MODULE *)GlobalLock( GetExePtr(hModule) );
+	if (pModule->dlls_to_init)
+	{
+		HANDLE to_init = pModule->dlls_to_init;
+		pModule->dlls_to_init = 0;
+		for (pDLL = (HMODULE *)GlobalLock( to_init ); *pDLL; pDLL++)
+		{
+			PE_InitializeDLLs( *pDLL );
+			PE_InitDLL( *pDLL );
+		}
+		GlobalFree( to_init );
+	}
+	PE_InitDLL( hModule );
+}
 #endif /* WINELIB */
diff --git a/loader/pe_resource.c b/loader/pe_resource.c
index b9a356d..b0d6203 100644
--- a/loader/pe_resource.c
+++ b/loader/pe_resource.c
@@ -72,7 +72,7 @@
 			memset(res_name, 0, sizeof(res_name));
 			my_wcstombs(res_name, name->NameString, name->Length);
 			dprintf_resource(stddeb, "\tPE_findresource: name %s\n", res_name);
-			if (strcasecmp(res_name, resource_name) == 0) 
+			if (lstrcmpi(res_name, resource_name) == 0) 
 				return find_lang(root, (struct PE_Resource_Directory *) (root + (type_dir->OffsetToData & ~IMAGE_RESOURCE_DATA_IS_DIRECTORY)), r);
 			type_dir++;
 		}
@@ -107,7 +107,7 @@
 			my_wcstombs(res_name, name->NameString, name->Length);
 			dprintf_resource(stddeb, "PE_findtype: type %s\n", 
 				res_name);
-			if (strcasecmp(res_name, type_name) == 0) 
+			if (lstrcmpi(res_name, type_name) == 0) 
 				return find_resource(root, (struct PE_Resource_Directory *) (root + (type_dir->OffsetToData & ~IMAGE_RESOURCE_DATA_IS_DIRECTORY)), resource_name, r);
 			type_dir++;
 		}
diff --git a/loader/task.c b/loader/task.c
index e7f2835..5e45faf 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -10,7 +10,9 @@
 #include "windows.h"
 #include "task.h"
 #include "callback.h"
+#include "directory.h"
 #include "dos_fs.h"
+#include "file.h"
 #include "debugger.h"
 #include "global.h"
 #include "instance.h"
@@ -75,11 +77,10 @@
 {
     static const char program_name[] = "KRNL386.EXE";
     char **e, *p;
-    int initial_size, size;
+    int initial_size, size, i, winpathlen, windirlen, sysdirlen;
     HANDLE handle;
 
     extern char **environ;
-    extern char WindowsDirectory[], SystemDirectory[];
 
     /* DOS environment format:
      * ASCIIZ   string 1
@@ -95,20 +96,27 @@
 
     /* First compute the size of the fixed part of the environment */
 
-    initial_size = 5 +                            /* PATH= */
-                   strlen(WindowsPath) + 1 +      /* path value */
-                   7 +                            /* windir= */
-                   strlen(WindowsDirectory) + 1 + /* windir value */
-                   1 +                            /* BYTE 0 at end */
-                   sizeof(WORD) +                 /* WORD 1 */
-                   strlen(SystemDirectory) + 1 +  /* program directory */
-                   strlen(program_name) + 1;      /* program name */
+    for (i = winpathlen = 0; ; i++)
+    {
+        int len = DIR_GetDosPath( i, NULL, 0 );
+        if (!len) break;
+        winpathlen += len + 1;
+    }
+    if (!winpathlen) winpathlen = 1;
+    windirlen  = GetWindowsDirectory( NULL, 0 ) + 1;
+    sysdirlen  = GetSystemDirectory( NULL, 0 ) + 1;
+    initial_size = 5 + winpathlen +           /* PATH=xxxx */
+                   7 + windirlen +            /* windir=xxxx */
+                   1 +                        /* BYTE 0 at end */
+                   sizeof(WORD) +             /* WORD 1 */
+                   sysdirlen +                /* program directory */
+                   strlen(program_name) + 1;  /* program name */
 
     /* Compute the total size of the Unix environment (except path) */
 
     for (e = environ, size = initial_size; *e; e++)
     {
-	if (strncasecmp(*e, "path=", 5))
+	if (lstrncmpi(*e, "path=", 5))
 	{
             int len = strlen(*e) + 1;
             if (size + len >= 32767)
@@ -130,7 +138,7 @@
 
     for (e = environ, size = initial_size; *e; e++)
     {
-	if (strncasecmp(*e, "path=", 5))
+	if (lstrncmpi(*e, "path=", 5))
 	{
             int len = strlen(*e) + 1;
             if (size + len >= 32767) break;
@@ -143,19 +151,25 @@
     /* Now add the path and Windows directory */
 
     strcpy( p, "PATH=" );
-    strcat( p, WindowsPath );
-    p += strlen(p) + 1;
+    for (i = 0, p += 5; ; i++)
+    {
+        if (!DIR_GetDosPath( i, p, winpathlen )) break;
+        p += strlen(p);
+        *p++ = ';';
+    }
+    if (p[-1] == ';') p[-1] = '\0';
+    else p++;
 
     strcpy( p, "windir=" );
-    strcat( p, WindowsDirectory );
-    p += strlen(p) + 1;
+    GetWindowsDirectory( p + 7, windirlen );
+    p += 7 + windirlen;
 
     /* Now add the program name */
 
     *p++ = '\0';
     *(WORD *)p = 1;
     p += sizeof(WORD);
-    strcpy( p, SystemDirectory );
+    GetSystemDirectory( p, sysdirlen );
     strcat( p, "\\" );
     strcat( p, program_name );
 
@@ -247,6 +261,7 @@
  *
  * Allocate a thunk for MakeProcInstance().
  */
+#ifndef WINELIB32
 static SEGPTR TASK_AllocThunk( HTASK hTask )
 {
     TDB *pTask;
@@ -275,6 +290,7 @@
     pThunk->free = *(WORD *)((BYTE *)pThunk + pThunk->free);
     return MAKELONG( base, sel );
 }
+#endif
 
 
 /***********************************************************************
@@ -282,6 +298,7 @@
  *
  * Free a MakeProcInstance() thunk.
  */
+#ifndef WINELIB32
 static BOOL TASK_FreeThunk( HTASK hTask, SEGPTR thunk )
 {
     TDB *pTask;
@@ -303,6 +320,7 @@
     pThunk->free = LOWORD(thunk) - base;
     return TRUE;
 }
+#endif
 
 
 /***********************************************************************
@@ -335,10 +353,7 @@
     cs_reg = pSegTable[pModule->cs - 1].selector;
     ip_reg = pModule->ip;
     ds_reg = pSegTable[pModule->dgroup - 1].selector;
-#ifndef WINELIB
-/* JBP: I doubt a CallTo16_regs_ is possible in libwine.a, and IF1632 is not
- *      allowed.
- */
+
     IF1632_Saved16_ss = pTask->ss;
     IF1632_Saved16_sp = pTask->sp;
     dprintf_task( stddeb, "Starting main program: cs:ip=%04x:%04x ds=%04x ss:sp=%04x:%04x\n",
@@ -349,11 +364,7 @@
                    pTask->hPDB /*es*/, 0 /*bp*/, 0 /*ax*/,
                    pModule->stack_size /*bx*/, pModule->heap_size /*cx*/,
                    0 /*dx*/, 0 /*si*/, ds_reg /*di*/ );
-#else
-    fprintf(stderr, "JBP: Ignoring main program: cs:ip=%04x:%04x ds=%04x ss:sp=%04x:%04x\n",
-                 cs_reg, ip_reg, ds_reg,
-                 pTask->ss, pTask->sp);
-#endif
+
     /* This should never return */
     fprintf( stderr, "TASK_CallToStart: Main program returned!\n" );
     TASK_KillCurrentTask( 1 );
@@ -426,12 +437,13 @@
     pTask->hParent       = hCurrentTask;
 #ifdef WINELIB
     pTask->curdrive      = 'C' - 'A' + 0x80;
+    strcpy( pTask->curdir, "\\" );
 #else
     pTask->curdrive      = filename[0] - 'A' + 0x80;
+    strcpy( pTask->curdir, filename+2 );
 #endif
     pTask->magic         = TDB_MAGIC;
     pTask->nCmdShow      = cmdShow;
-    strcpy( pTask->curdir, filename+2 );
 
       /* Create the thunks block */
 
@@ -442,30 +454,35 @@
     name = MODULE_GetModuleName( hModule );
     strncpy( pTask->module_name, name, sizeof(pTask->module_name) );
 
+      /* Allocate a selector for the PDB */
+
+    pTask->hPDB = GLOBAL_CreateBlock( GMEM_FIXED, &pTask->pdb, sizeof(PDB),
+                                      hModule, FALSE, FALSE, FALSE, NULL );
+
       /* Fill the PDB */
 
     pTask->pdb.int20 = 0x20cd;
+#ifndef WINELIB
     pTask->pdb.dispatcher[0] = 0x9a;  /* ljmp */
     *(DWORD *)&pTask->pdb.dispatcher[1] = MODULE_GetEntryPoint( GetModuleHandle("KERNEL"), 102 );  /* KERNEL.102 is DOS3Call() */
-#ifndef WINELIB
     pTask->pdb.savedint22 = INT_GetHandler( 0x22 );
     pTask->pdb.savedint23 = INT_GetHandler( 0x23 );
     pTask->pdb.savedint24 = INT_GetHandler( 0x24 );
+    pTask->pdb.fileHandlesPtr = (SEGPTR)MAKELONG( 0x18,
+                                              GlobalHandleToSel(pTask->hPDB) );
+#else
+    pTask->pdb.fileHandlesPtr = pTask->pdb.fileHandles;
 #endif
-    pTask->pdb.environment = hEnvironment;
-    strncpy( pTask->pdb.cmdLine + 1, cmdLine, 126 );
-    pTask->pdb.cmdLine[127] = '\0';
+    memset( pTask->pdb.fileHandles, 0xff, sizeof(pTask->pdb.fileHandles) );
+    pTask->pdb.environment    = hEnvironment;
+    pTask->pdb.nbFiles        = 20;
+    lstrcpyn( pTask->pdb.cmdLine + 1, cmdLine, 127 );
     pTask->pdb.cmdLine[0] = strlen( pTask->pdb.cmdLine + 1 );
 
       /* Get the compatibility flags */
 
     pTask->compat_flags = GetProfileInt( name, "Compatibility", 0 );
 
-      /* Allocate a selector for the PDB */
-
-    pTask->hPDB = GLOBAL_CreateBlock( GMEM_FIXED, &pTask->pdb, sizeof(PDB),
-                                      hModule, FALSE, FALSE, FALSE, NULL );
-
       /* Allocate a code segment alias for the TDB */
 
     pTask->hCSAlias = GLOBAL_CreateBlock( GMEM_FIXED, (void *)pTask,
@@ -561,6 +578,10 @@
 
     if (!(pTask = (TDB *)GlobalLock( hTask ))) return;
 
+    /* Close all open files of this task */
+
+    FILE_CloseAllFiles( pTask->hPDB );
+
       /* Free the task module */
 
     FreeModule( pTask->hModule );
@@ -718,7 +739,11 @@
 /***********************************************************************
  *           InitTask  (KERNEL.91)
  */
+#ifdef WINELIB
+void InitTask(void)
+#else
 void InitTask( struct sigcontext_struct context )
+#endif
 {
     static int firstTask = 1;
     TDB *pTask;
@@ -727,7 +752,9 @@
     INSTANCEDATA *pinstance;
     LONG stacklow, stackhi;
 
+#ifndef WINELIB
     EAX_reg(&context) = 0;
+#endif
     if (!(pTask = (TDB *)GlobalLock( hCurrentTask ))) return;
     if (!(pModule = (NE_MODULE *)GlobalLock( pTask->hModule ))) return;
 
@@ -782,7 +809,7 @@
     pinstance = (INSTANCEDATA *)PTR_SEG_OFF_TO_LIN(CURRENT_DS, 0);
     pinstance->stackbottom = stackhi; /* yup, that's right. Confused me too. */
     pinstance->stacktop    = stacklow; 
-#ifndef WINELIB /* FIXME: JBP: IF1632 not allowed in libwine.a */
+#ifndef WINELIB
     pinstance->stackmin    = IF1632_Saved16_sp;
 #endif
 }
@@ -857,7 +884,7 @@
 /***********************************************************************
  *           IsTaskLocked  (KERNEL.122)
  */
-WORD IsTaskLocked(void)
+HTASK IsTaskLocked(void)
 {
     return hLockedTask;
 }
@@ -905,6 +932,9 @@
  */
 FARPROC MakeProcInstance( FARPROC func, HANDLE hInstance )
 {
+#ifdef WINELIB32
+    return func; /* func can be called directly in Win32 */
+#else
     BYTE *thunk;
     SEGPTR thunkaddr;
     
@@ -916,13 +946,12 @@
                   (SEGPTR)func, hInstance, (SEGPTR)thunkaddr );
     
     *thunk++ = 0xb8;    /* movw instance, %ax */
-#ifndef WINELIB
     *thunk++ = (BYTE)(hInstance & 0xff);
     *thunk++ = (BYTE)(hInstance >> 8);
-#endif
     *thunk++ = 0xea;    /* ljmp func */
     *(DWORD *)thunk = (DWORD)func;
     return (FARPROC)thunkaddr;
+#endif
 }
 
 
@@ -931,8 +960,10 @@
  */
 void FreeProcInstance( FARPROC func )
 {
+#ifndef WINELIB32
     dprintf_task( stddeb, "FreeProcInstance("SPFMT")\n", (SEGPTR)func );
     TASK_FreeThunk( hCurrentTask, (SEGPTR)func );
+#endif
 }
 
 
@@ -953,8 +984,6 @@
     else
         handle = GlobalHandle( HIWORD(proc) );
 
-    printf( "STUB: GetCodeHandle(%08lx) returning "NPFMT"\n",
-            (DWORD)proc, handle );
     return handle;
 }
 
@@ -1050,6 +1079,21 @@
 
 
 /***********************************************************************
+ *           SetErrorMode   (KERNEL.107)
+ */
+UINT SetErrorMode( UINT mode )
+{
+    TDB *pTask;
+    UINT oldMode;
+
+    if (!(pTask = (TDB *)GlobalLock( hCurrentTask ))) return 0;
+    oldMode = pTask->error_mode;
+    pTask->error_mode = mode;
+    return oldMode;
+}
+
+
+/***********************************************************************
  *           GetDOSEnvironment   (KERNEL.131)
  */
 SEGPTR GetDOSEnvironment(void)
@@ -1108,6 +1152,8 @@
 
     if (!(ptr = GlobalLock( handle ))) return 0;
     if (((NE_MODULE *)ptr)->magic == NE_SIGNATURE) return handle;
+	/* Fake modules describing PE modules have a PE signature */
+    if (((NE_MODULE *)ptr)->magic == PE_SIGNATURE) return handle;
 
       /* Check the owner for module handle */
 
@@ -1115,10 +1161,10 @@
     owner = FarGetOwner( handle );
 #else
     owner = NULL;
-    fprintf(stderr,"JBP: FarGetOwner() ignored.\n");
 #endif
     if (!(ptr = GlobalLock( owner ))) return 0;
     if (((NE_MODULE *)ptr)->magic == NE_SIGNATURE) return owner;
+    if (((NE_MODULE *)ptr)->magic == PE_SIGNATURE) return owner;
 
       /* Search for this handle and its owner inside all tasks */
 
diff --git a/memory/atom.c b/memory/atom.c
index 359158c..0e42c92 100644
--- a/memory/atom.c
+++ b/memory/atom.c
@@ -146,7 +146,7 @@
     {
 	entryPtr = ATOM_MakePtr( selector, entry );
 	if ((entryPtr->length == len) && 
-	    (!strncasecmp( entryPtr->str, str, len )))
+	    (!lstrncmpi( entryPtr->str, str, len )))
 	{
 	    entryPtr->refCount++;
 	    return HANDLETOATOM( entry );
@@ -227,7 +227,7 @@
     {
 	ATOMENTRY * entryPtr = ATOM_MakePtr( selector, entry );
 	if ((entryPtr->length == len) && 
-	    (!strncasecmp( entryPtr->str, str, len )))
+	    (!lstrncmpi( entryPtr->str, str, len )))
 	    return HANDLETOATOM( entry );
 	entry = entryPtr->next;
     }
diff --git a/memory/global.c b/memory/global.c
index 6d540a3..680e9fb 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -6,6 +6,7 @@
 
 #include <sys/types.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include <string.h>
 
 #include "windows.h"
@@ -755,7 +756,48 @@
  */
 BOOL MemManInfo( MEMMANINFO *pInfo )
 {
+#ifdef linux
+    /* FIXME: does not take into account the dwSize member
+     * could be corrupting memory therefore
+     */
+    /* shamefully stolen from free */
+    DWORD availmem = 0;
+    DWORD totalmem = 0;
+    FILE *meminfo;
+    char buf[80];
+    int col[5];
+    int n;
+
+    if ((meminfo = fopen("/proc/meminfo", "r")) < 0) {
+        perror("wine: open");
+        exit(1);
+    }
+
+    fgets(buf, 80, meminfo); /* read first line */
+    while ( fgets(buf, 80, meminfo) ) {
+        n = sscanf( buf, "%*s %d %d %d %d %d", &col[0], &col[1], &col[2], &col[3], &col[4]);
+        if ( n < 1 ) continue; /* escape the loop at the top */
+        totalmem += col[0];
+        availmem += col[2] + col[4];
+    }
+
+    fprintf(stderr,"MemManInfo called with dwSize = %ld\n",pInfo->dwSize);
+    pInfo->wPageSize = getpagesize();
+    pInfo->dwLargestFreeBlock = availmem;
+    pInfo->dwTotalLinearSpace = totalmem / pInfo->wPageSize;
+    pInfo->dwMaxPagesAvailable = pInfo->dwLargestFreeBlock / pInfo->wPageSize;
+    pInfo->dwMaxPagesLockable = pInfo->dwMaxPagesLockable;
+    /* FIXME: the next three are not quite correct */
+    pInfo->dwTotalUnlockedPages = pInfo->dwMaxPagesAvailable;
+    pInfo->dwFreePages = pInfo->dwMaxPagesAvailable;
+    pInfo->dwTotalPages = pInfo->dwMaxPagesAvailable;
+    /* FIXME: the three above are not quite correct */
+    pInfo->dwFreeLinearSpace = pInfo->dwMaxPagesAvailable;
+    pInfo->dwSwapFilePages = 0L;
     return TRUE;
+#else
+    return TRUE;
+#endif
 }
 
 /***********************************************************************
diff --git a/memory/ldt.c b/memory/ldt.c
index 9500f2b..bc1c96f 100644
--- a/memory/ldt.c
+++ b/memory/ldt.c
@@ -7,11 +7,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#ifdef __svr4__
 #include <string.h>
-#else
-#include <strings.h>
-#endif
 #include <errno.h>
 #include "ldt.h"
 #include "stddebug.h"
diff --git a/memory/selector.c b/memory/selector.c
index d6c2db1..bbf2e44 100644
--- a/memory/selector.c
+++ b/memory/selector.c
@@ -442,3 +442,37 @@
     memcpy( ((char *)GET_SEL_BASE(sel)) + offset, buffer, count );
     return count;
 }
+
+#ifndef WINELIB
+SEGPTR MAKE_SEGPTR(void * ptr)
+
+{
+    SEGPTR result;
+    int entry;
+
+    if (!ptr)
+	return ptr;
+    if (!((unsigned)ptr & 0xffff0000)) {
+ 	fprintf(stderr, "Invalid pointer %08x has been passed to MAKE_SEGPTR. This was\n", ptr);
+	fprintf(stderr, "probably caused by an unnecessary call to PTR_SEG_TO_LIN.\n");
+	fprintf(stderr, "Forcing call to debugger\n");
+	ptr = *(void **)0;
+    }
+    result = (SEGPTR) (IF1632_Stack32_base) +
+	     ((DWORD)(ptr) - (DWORD) PTR_SEG_TO_LIN(IF1632_Stack32_base));
+    if (PTR_SEG_TO_LIN(result) == ptr)
+	return result;
+    
+    for (entry = 0; entry < LDT_SIZE; entry++) {
+	if (ldt_copy[entry].base && 
+	    (ldt_copy[entry].limit < 0x10000) &&
+	    ((unsigned) ptr >= ldt_copy[entry].base) &&
+	    ((unsigned) ptr < (ldt_copy[entry].base + ldt_copy[entry].limit))) {
+		return ((ENTRY_TO_SELECTOR(entry) << 16) | 
+                       ((unsigned) ptr - ldt_copy[entry].base));
+	}
+    }
+    entry = SELECTOR_AllocBlock((void *)((unsigned)ptr & 0xffff0000), 0x10000, SEGMENT_DATA, 0, 0);
+    return ((entry << 16) | ((unsigned) ptr & 0xffff));
+}
+#endif
diff --git a/misc/Makefile.in b/misc/Makefile.in
index d6374a5..7d0a546 100644
--- a/misc/Makefile.in
+++ b/misc/Makefile.in
@@ -10,7 +10,6 @@
 	driver.c \
 	exec.c \
 	escape.c \
-	file.c \
 	keyboard.c \
 	lstr.c \
 	main.c \
@@ -20,6 +19,7 @@
 	ole2nls.c \
 	olecli.c \
 	olesvr.c \
+	port.c \
 	profile.c \
 	rect.c \
 	shell.c \
diff --git a/misc/comm.c b/misc/comm.c
index 06501cc..107ec99 100644
--- a/misc/comm.c
+++ b/misc/comm.c
@@ -136,7 +136,7 @@
 		"BuildCommDCB: (%s), ptr %p\n", device, lpdcb);
 	commerror = 0;
 
-	if (!strncasecmp(device,"COM",3)) {
+	if (!lstrncmpi(device,"COM",3)) {
 		port = device[3] - '0';
 	
 
@@ -227,7 +227,7 @@
 		"OpenComm: %s, %d, %d\n", device, cbInQueue, cbOutQueue);
 	commerror = 0;
 
-	if (!strncasecmp(device,"COM",3)) {
+	if (!lstrncmpi(device,"COM",3)) {
 		port = device[3] - '0';
 
 		if (port-- == 0) {
@@ -256,7 +256,7 @@
 		}
 	} 
 	else 
-	if (!strncasecmp(device,"LPT",3)) {
+	if (!lstrncmpi(device,"LPT",3)) {
 		port = device[3] - '0';
 	
 		if (!ValidLPTPort(port)) {
diff --git a/misc/commdlg.c b/misc/commdlg.c
index d147dde..8991597 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -15,6 +15,7 @@
 #include "selectors.h"
 #include "resource.h"
 #include "dos_fs.h"
+#include "drive.h"
 #include "stackframe.h"
 
 static	DWORD 		CommDlgLastError = 0;
@@ -164,9 +165,9 @@
   strncpy(str,newPath,511); str[511]=0;
   SendDlgItemMessage(hWnd, edt1, WM_GETTEXT, 511, (LPARAM)MAKE_SEGPTR(str2));
   strncat(str,str2,511-strlen(str)); str[511]=0;
-  if (!DlgDirList(hWnd, str, lst1, 0, 0x0000)) return FALSE;
-  DlgDirList(hWnd, "*.*", lst2, stc1, 0x8010);
-  
+  if (!DlgDirList(hWnd, MAKE_SEGPTR(str), lst1, 0, 0x0000)) return FALSE;
+  strcpy( str, "*.*" );
+  DlgDirList(hWnd, MAKE_SEGPTR(str), lst2, stc1, 0x8010);
   return TRUE;
 }
 
@@ -360,7 +361,7 @@
   if (!FILEDLG_ScanDir(hWnd, tmpstr))
     fprintf(stderr, "FileDlg: couldn't read initial directory %s!\n", tmpstr);
   /* select current drive in combo 2 */
-  n = DOS_GetDefaultDrive();
+  n = DRIVE_GetCurrentDrive();
   SendDlgItemMessage(hWnd, cmb2, CB_SETCURSEL, n, 0);
   if (!(lpofn->Flags & OFN_SHOWHELP))
     ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
@@ -378,13 +379,23 @@
   LPOPENFILENAME lpofn;
   char tmpstr[512], tmpstr2[512];
   LPSTR pstr, pstr2;
+  UINT control,notification;
+
+  /* Notifications are packaged differently in Win32 */
+#ifdef WINELIB32
+  control = LOWORD(wParam);
+  notification = HIWORD(wParam);
+#else
+  control = wParam;
+  notification = HIWORD(lParam);
+#endif
     
   lpofn = (LPOPENFILENAME)GetWindowLong(hWnd, DWL_USER);
-  switch (wParam)
+  switch (control)
     {
     case lst1: /* file list */
       FILEDLG_StripEditControl(hWnd);
-      if (HIWORD(lParam) == LBN_DBLCLK)
+      if (notification == LBN_DBLCLK)
 	goto almost_ok;
       lRet = SendDlgItemMessage(hWnd, lst1, LB_GETCURSEL, 0, 0);
       if (lRet == LB_ERR) return TRUE;
@@ -394,7 +405,7 @@
       return TRUE;
     case lst2: /* directory list */
       FILEDLG_StripEditControl(hWnd);
-      if (HIWORD(lParam) == LBN_DBLCLK)
+      if (notification == LBN_DBLCLK)
 	{
 	  lRet = SendDlgItemMessage(hWnd, lst2, LB_GETCURSEL, 0, 0);
 	  if (lRet == LB_ERR) return TRUE;
@@ -410,7 +421,7 @@
 	}
       return TRUE;
     case cmb1: /* file type drop list */
-      if (HIWORD(lParam) == CBN_SELCHANGE) 
+      if (notification == CBN_SELCHANGE) 
 	{
 	  *tmpstr = 0;
 	  goto reset_scan;
@@ -494,12 +505,11 @@
 	SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, (LPARAM)MAKE_SEGPTR(tmpstr));
       ShowWindow(hWnd, SW_HIDE);
       {
-	int drive;
-	drive = DOS_GetDefaultDrive();
+	int drive = DRIVE_GetCurrentDrive();
 	tmpstr2[0] = 'A'+ drive;
 	tmpstr2[1] = ':';
 	tmpstr2[2] = '\\';
-	strncpy(tmpstr2 + 3, DOS_GetCurrentDir(drive), 507); tmpstr2[510]=0;
+	strncpy(tmpstr2 + 3, DRIVE_GetDosCwd(drive), 507); tmpstr2[510]=0;
 	if (strlen(tmpstr2) > 3)
 	   strcat(tmpstr2, "\\");
 	strncat(tmpstr2, tmpstr, 511-strlen(tmpstr2)); tmpstr2[511]=0;
diff --git a/misc/dos_fs.c b/misc/dos_fs.c
index 6235df6..b01f6b0 100644
--- a/misc/dos_fs.c
+++ b/misc/dos_fs.c
@@ -40,77 +40,6 @@
 #include "xmalloc.h"
 
 #define WINE_INI_USER "~/.winerc"
-#define MAX_DOS_DRIVES	26
-
-extern char WindowsDirectory[256], SystemDirectory[256],TempDirectory[256];
-
-char WindowsPath[256];
-
-static int CurrentDrive = 2;
-
-struct DosDriveStruct {			/*  eg: */
-	char 		*rootdir;	/*  /usr/windows 	*/
-	char 		cwd[256];	/*  /			*/
-	char 		label[13];	/*  DRIVE-A		*/
-	unsigned int	serialnumber;	/*  ABCD5678		*/
-	int 		disabled;	/*  0			*/
-};
-
-static struct DosDriveStruct DosDrives[MAX_DOS_DRIVES];
-static struct dosdirent *DosDirs=NULL;
-
-WORD ExtendedError;
-BYTE ErrorClass, Action, ErrorLocus;
-
-int DOS_Error(int e, int class, int el)
-{
-	ErrorClass = class;
-	Action = SA_Ask4Retry;
-	ErrorLocus = el;
-	ExtendedError = e;
-
-	return e;
-}
-
-void errno_to_doserr(void)
-{
-	switch (errno) {
-		case EAGAIN:
-			DOS_Error (ShareViolation, EC_Temporary, EL_Unknown);
-			break;
-		case EBADF:
-			DOS_Error (InvalidHandle, EC_AppError, EL_Unknown);
-			break;
-		case ENOSPC:
-			DOS_Error (DiskFull, EC_MediaError, EL_Disk);
-			break;				
-		case EACCES:
-		case EPERM:
-		case EROFS:
-			DOS_Error (WriteProtected, EC_AccessDenied, EL_Unknown);
-			break;
-		case EBUSY:
-			DOS_Error (LockViolation, EC_AccessDenied, EL_Unknown);
-			break;		
-		case ENOENT:
-			DOS_Error (FileNotFound, EC_NotFound, EL_Unknown);
-			break;				
-		case EISDIR:
-			DOS_Error (CanNotMakeDir, EC_AccessDenied, EL_Unknown);
-			break;
-		case ENFILE:
-		case EMFILE:
-			DOS_Error (NoMoreFiles, EC_MediaError, EL_Unknown);
-			break;
-		case EEXIST:
-			DOS_Error (FileExists, EC_Exists, EL_Disk);
-			break;				
-		default:
-			dprintf_int(stddeb, "int21: unknown errno %d!\n", errno);
-			DOS_Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
-			break;
-	}
-}
 
 
 static void ExpandTildeString(char *s)
@@ -141,503 +70,22 @@
     *s = 0;
 }
 
-/* Simplify the path in "name" by removing  "//"'s, "/./"'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 ((l = strstr(name, "/./"))) {
-      strcpy(l, l+2); 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)
-{
-    char *p = path + strlen(path) - 1;
-    while ((*p == '\\') && (p > path)) *p-- = '\0';
-}
-
-void ToUnix(char *s)
-{
-    while(*s){
-	if (*s == '\\') *s = '/';
-	*s=tolower(*s); /* umsdos fs can't read files without :( */
-	s++;
-    }
-}
-
-void ToDos(char *s)
-{
-    while(*s){
-	if (*s == '/') *s = '\\';
-	s++;
-    }
-}
-
-void DOS_InitFS(void)
-{
-    int x;
-    char drive[2], temp[256];
-    struct dosdirent *dp;    
-    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;
-    }
-    DosDrives[25].rootdir = "/";
-    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.
-     */
-
-    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(DosDrives[25].cwd, temp );
-    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);	
-	}
-    }
-    dp = DosDirs;
-    while (dp)
-    {
-        dp->inuse = 0;
-        dp = dp->next;
-    }
-
-    dprintf_dosfs(stddeb,"wine.ini = %s\n",WINE_INI);
-    dprintf_dosfs(stddeb,"win.ini = %s\n",WIN_INI);
-    dprintf_dosfs(stddeb,"windir = %s\n",WindowsDirectory);
-    dprintf_dosfs(stddeb,"sysdir = %s\n",SystemDirectory);
-    dprintf_dosfs(stddeb,"tempdir = %s\n",TempDirectory);
-    dprintf_dosfs(stddeb,"path = %s\n",WindowsPath);
-}
-
-WORD DOS_GetEquipment(void)
-{
-    WORD equipment;
-    int diskdrives = 0;
-    int parallelports = 0;
-    int serialports = 0;
-    int x;
-
-/* borrowed from Ralph Brown's interrupt lists 
-
-		    bits 15-14: number of parallel devices
-		    bit     13: [Conv] Internal modem
-		    bit     12: reserved
-		    bits 11- 9: number of serial devices
-		    bit      8: reserved
-		    bits  7- 6: number of diskette drives minus one
-		    bits  5- 4: Initial video mode:
-				    00b = EGA,VGA,PGA
-				    01b = 40 x 25 color
-				    10b = 80 x 25 color
-				    11b = 80 x 25 mono
-		    bit      3: reserved
-		    bit      2: [PS] =1 if pointing device
-				[non-PS] reserved
-		    bit      1: =1 if math co-processor
-		    bit      0: =1 if diskette available for boot
-*/
-/*  Currently the only of these bits correctly set are:
-		bits 15-14 		} Added by William Owen Smith, 
-		bits 11-9		} wos@dcs.warwick.ac.uk
-		bits 7-6
-		bit  2			(always set)
-*/
-
-    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;
-
-    dprintf_dosfs(stddeb, "DOS_GetEquipment : diskdrives = %d serialports = %d "
-		  "parallelports = %d\n"
-		  "DOS_GetEquipment : equipment = %d\n",
-		  diskdrives, serialports, parallelports, equipment);
-    
-    return equipment;
-}
-
-int DOS_ValidDrive(int drive)
-{
-    dprintf_dosfs(stddeb,"ValidDrive %c (%d)\n",'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;
-
-    dprintf_dosfs(stddeb, " -- valid\n");
-    return 1;
-}
-
-static void DOS_GetCurrDir_Unix(char *buffer, int drive)
-{
-    TDB *pTask = (TDB *)GlobalLock(GetCurrentTask());
-    
-    if (pTask != NULL && (pTask->curdrive & ~0x80) == drive) {
-	strcpy(buffer, pTask->curdir);
-	ToUnix(buffer);
-    } else {
-	strcpy(buffer, DosDrives[drive].cwd);
-    }
-}
-
-char *DOS_GetCurrentDir(int drive)
-{ 
-    static char temp[256];
-
-    if (!DOS_ValidDrive(drive)) return 0;
-
-    DOS_GetCurrDir_Unix(temp, drive);
-    DOS_SimplifyPath( temp );
-    ToDos(temp);
-    ChopOffSlash(temp);
-
-    dprintf_dosfs(stddeb,"DOS_GetCWD: %c:%s\n", 'A'+drive, temp);
-    return temp + 1;
-}
-
-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;
-
-    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
- * the directory ends in a slash.
- */
-char *DOS_GetDosFileName(char *unixfilename)
-{ 
-    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);
-	}
-    }
-    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;
-}
-
-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;
-}
-
-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;
-}
-
-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)
-{
-    TDB *pTask = (TDB *)GlobalLock(GetCurrentTask());
-    char temp[256];
-    
-    if (!DOS_ValidDrive(drive)) return 0;
-
-    if (dirname[0] == '\\') {
-	strcpy(temp, dirname);
-    } 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);
-
-    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], currdir[256];
-    
-    if (!DOS_ValidDrive(drive)) return 0;	
-
-    strcpy(temp, DosDrives[drive].rootdir);
-    DOS_GetCurrDir_Unix(currdir, drive);
-    strcat(temp, currdir);
-    strcat(temp, dirname);
-    ToUnix(temp);
-    DOS_SimplifyPath(temp);
-    if (mkdir(temp, S_IRWXU | S_IRWXG | S_IRWXO) == -1)
-    {
-        dprintf_dosfs(stddeb, "DOS_MakeDir: %c:\%s => %s failed errno %d",'A'+drive, dirname, temp, errno);
-        return 0;
-    }
-    dprintf_dosfs(stddeb, "DOS_MakeDir: %c:\%s => %s",'A'+drive, dirname, temp);
-    return 1;
-}
-
-int DOS_GetSerialNumber(int drive, unsigned long *serialnumber)
-{
-	if (!DOS_ValidDrive(drive)) 
-		return 0;
-
-	*serialnumber = DosDrives[drive].serialnumber;
-	return 1;
-}
-
-int DOS_SetSerialNumber(int drive, unsigned long serialnumber)
-{
-	if (!DOS_ValidDrive(drive)) 
-		return 0;
-
-	DosDrives[drive].serialnumber = serialnumber;
-	return 1;
-}
-
-char *DOS_GetVolumeLabel(int drive)
-{
-	if (!DOS_ValidDrive(drive)) 
-		return NULL;
-
-	return DosDrives[drive].label;
-}
-
-int DOS_SetVolumeLabel(int drive, char *label)
-{
-	if (!DOS_ValidDrive(drive)) 
-		return 0;
-
-	strncpy(DosDrives[drive].label, label, 8);
-	return 1;
-}
 
 int DOS_GetFreeSpace(int drive, long *size, long *available)
 {
-	struct statfs info;
+    struct statfs info;
+    const char *root;
 
-	if (!DOS_ValidDrive(drive))
-		return 0;
+    if (!DRIVE_IsValid(drive)) return 0;
+    root = DRIVE_GetRoot(drive);
 
 #ifdef __svr4__
-	if (statfs(DosDrives[drive].rootdir, &info, 0, 0) < 0) {
+	if (statfs( root, &info, 0, 0) < 0) {
 #else
-	if (statfs(DosDrives[drive].rootdir, &info) < 0) {
+	if (statfs( root, &info) < 0) {
 #endif
-		fprintf(stderr,"dosfs: cannot do statfs(%s)\n",
-			DosDrives[drive].rootdir);
+		fprintf(stderr,"dosfs: cannot do statfs(%s)\n", root );
 		return 0;
 	}
 
@@ -647,91 +95,9 @@
 #else
 	*available = info.f_bavail * info.f_bsize;
 #endif
-
 	return 1;
 }
 
-char *DOS_FindFile(char *buffer, int buflen, const char *filename, char **extensions, 
-		char *path)
-{
-    char *workingpath, *dirname, *rootname, **e;
-    DIR *d;
-    struct dirent *f;
-    int rootnamelen;
-    struct stat filestat;
-
-    if (strchr(filename, '\\') != NULL)
-    {
-	strncpy(buffer, DOS_GetUnixFileName(filename), buflen);
-	stat( buffer, &filestat);
-	if (S_ISREG(filestat.st_mode))
-	    return buffer;
-	else
-	    return NULL;
-    }
-
-    if (strchr(filename, '/') != NULL)
-    {
-	strncpy(buffer, filename, buflen);
-	return buffer;
-    }
-
-    dprintf_dosfs(stddeb,"DOS_FindFile: looking for %s\n", filename);
-    rootnamelen = strlen(filename);
-    rootname = strdup(filename);
-    ToUnix(rootname);
-    workingpath = strdup(path);
-
-    for(dirname = strtok(workingpath, ";"); 
-	dirname != NULL;
-	dirname = strtok(NULL, ";"))
-    {
-	if (strchr(dirname, '\\') != NULL)
-		d = opendir( DOS_GetUnixFileName(dirname) );
-	else
-		d = opendir( dirname );
-
-    	dprintf_dosfs(stddeb,"in %s\n",dirname);
-	if (d != NULL)
-	{
-	    while ((f = readdir(d)) != NULL)
-	    {		
-		if (strcasecmp(rootname, f->d_name) != 0) {
-		    if (strncasecmp(rootname, f->d_name, rootnamelen) != 0
-		      || extensions == NULL 
-		      || f->d_name[rootnamelen] != '.')
-		        continue;
-
-		    for (e = extensions; *e != NULL; e++) {
-			if (strcasecmp(*e, f->d_name + rootnamelen + 1) == 0)
-			    break;
-		    }
-		    if (*e == NULL) continue;
-		}
-
-		if (strchr(dirname, '\\') != NULL) {
-		    strncpy(buffer, DOS_GetUnixFileName(dirname), buflen);
-		} else {
-		    strncpy(buffer, dirname, buflen);
-		}
-
-		strncat(buffer, "/", buflen - strlen(buffer));
-		strncat(buffer, f->d_name, buflen - strlen(buffer));
-		
-		stat(buffer, &filestat);
-		if (S_ISREG(filestat.st_mode)) {
-		    closedir(d);
-		    free(rootname);
-		    DOS_SimplifyPath(buffer);
-		    return buffer;
-		} 
-	    }
-	    closedir(d);
-	}
-    }
-    return NULL;
-}
-
 /**********************************************************************
  *		WineIniFileName
  */
@@ -761,210 +127,3 @@
 	exit(1);
 }
 
-char *WinIniFileName(void)
-{
-	static char *name = NULL;
-	
-	if (name)
-		return name;
-		
-	name = xmalloc(1024);
-
-	strcpy(name, DOS_GetUnixFileName(WindowsDirectory));
-	strcat(name, "/");
-	strcat(name, "win.ini");
-
-	name = xrealloc(name, strlen(name) + 1);
-	
-	return name;
-}
-
-static int match(char *filename, char *filemask)
-{
-        char name[12], mask[12];
-        int i;
-
-        dprintf_dosfs(stddeb, "match: %s, %s\n", filename, filemask);
- 
-	for( i=0; i<11; i++ ) {
-	  name[i] = ' ';
-	  mask[i] = ' ';
-	}
-	name[11] = 0;
-	mask[11] = 0; 
- 
-	for( i=0; i<8; i++ )
-	  if( !(*filename) || *filename == '.' )
-  	    break;
-	  else
-            name[i] = toupper( *filename++ );
-        while( *filename && *filename != '.' )
-	  filename++;
-        if( *filename )
-	  filename++;
-        for( i=8; i<11; i++ )
-	  if( !(*filename) )
-	    break;
-	  else
-	    name[i] = toupper( *filename++ );
-
-	for( i=0; i<8; i++ )
-	  if( !(*filemask) || *filemask == '.' )
-	    break;
-	  else if( *filemask == '*' ) {
-	    int j;
-	    for( j=i; j<8; j++ )
-	      mask[j] = '?';
-	    break;
-          }
-	  else
-	    mask[i] = toupper( *filemask++ );
-	while( *filemask && *filemask != '.' )
-	  filemask++;	   
-	if( *filemask )
-	  filemask++;
-	for( i=8; i<11; i++ )
-	  if( !(*filemask) )
-	    break;
-	  else if (*filemask == '*' ) {
-	    int j;
-	    for( j=i; j<11; j++ )
-	      mask[j] = '?';
-	    break;
-	  }
-	  else
-	    mask[i] = toupper( *filemask++ );
-	
-    	dprintf_dosfs(stddeb, "changed to: %s, %s\n", name, mask);
-
-	for( i=0; i<11; i++ )
-	  if( ( name[i] != mask[i] ) && ( mask[i] != '?' ) )
-	    return 0;
-
-	return 1;
-}
-
-struct dosdirent *DOS_opendir(char *dosdirname)
-{
-    int len;
-    char *unixdirname;
-    char dirname[256];
-    DIR  *ds;
-    struct dosdirent *dp;
-    
-    if ((unixdirname = DOS_GetUnixFileName(dosdirname)) == NULL) return NULL;
-    
-    len = strrchr(unixdirname, '/') - unixdirname + 1;
-    strncpy(dirname, unixdirname, len);
-    dirname[len] = 0;
-    unixdirname = strrchr(unixdirname, '/') + 1;
-    if ((ds = opendir(dirname)) == NULL)
-        return NULL;
-
-    dp = DosDirs;
-    while (dp)
-    {
-        if (dp->inuse)
-            break;
-        if (strcmp(dp->unixpath, dirname) == 0)
-            break;
-        dp = dp->next;
-    }
-    if (!dp)
-    {
-        dp = xmalloc(sizeof(struct dosdirent));
-        dp->next = DosDirs;
-        DosDirs = dp;
-    }
-    
-    strncpy(dp->filemask, unixdirname, 12);
-    dp->filemask[12] = 0;
-    dprintf_dosfs(stddeb,"DOS_opendir: %s / %s\n", unixdirname, dirname);
-
-    dp->inuse = 1;
-    strcpy(dp->unixpath, dirname);
-    dp->entnum = 0;
-
-    if (closedir(ds) == -1) 
-    {
-        dp->inuse = 0;
-        return NULL;
-    }
-    return dp;
-}
-
-
-struct dosdirent *DOS_readdir(struct dosdirent *de)
-{
-	char temp[WINE_PATH_LENGTH];
-	struct dirent *d;
-	struct stat st;
-	DIR	*ds;
-	int	i;
-
-	if (!de->inuse)
-		return NULL;
-	if (!(ds=opendir(de->unixpath))) return NULL;
-	/* skip all already read directory entries. 
-	 * the dir has hopefully not been modified in the meantime
-	 */
-	for (i=de->entnum;i--;)
-		readdir(ds);
-   
-        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 {
-	    de->entnum++;   /* Increment the directory entry number */
-	    if ((d = readdir(ds)) == NULL)  {
-		closedir(ds);
-		return NULL;
-	    }
-	    strcpy(de->filename, d->d_name);
-	    if (d->d_reclen > 12)
-	    de->filename[12] = '\0';
-	    ToDos(de->filename);
-
-	    strcpy(temp,de->unixpath);
-	    strcat(temp,"/");
-	    strcat(temp,d->d_name);
-	    stat (temp, &st);
-	    de->attribute = 0x0;
-	    if S_ISDIR(st.st_mode)
-	      de->attribute |= FA_DIREC;
-
-	} while (!(de->attribute & FA_DIREC) &&
-		 !match(de->filename, de->filemask) );
-
-
-	de->filesize = st.st_size;
-	de->filetime = st.st_mtime;
-
-	closedir(ds);
-	return de;
-}
-
-void DOS_closedir(struct dosdirent *de)
-{
-	if (de && de->inuse)
-		de->inuse = 0;
-}
-
-char *DOS_GetRedirectedDir(int drive)
-{
-    if(DOS_ValidDrive(drive))
-        return (DosDrives[drive].rootdir);
-    else
-        return ("/");
-}
diff --git a/misc/file.c b/misc/file.c
deleted file mode 100644
index 888701a..0000000
--- a/misc/file.c
+++ /dev/null
@@ -1,468 +0,0 @@
-/************************************************************************
- * FILE.C     Copyright (C) 1993 John Burton
- *
- * File I/O routines for the Linux Wine Project.
- *
- * WARNING : Many options of OpenFile are not yet implemeted.
- *
- * NOV 93 Erik Bos (erik@xs4all.nl)
- *		- removed ParseDosFileName, and DosDrive structures.
- *		- structures dynamically configured at runtime.
- *		- _lopen modified to use DOS_GetUnixFileName.
- *		- Existing functions modified to use dosfs functions.
- *		- Added _llseek, _lcreat, GetDriveType, GetTempDrive, 
- *		  GetWindowsDirectory, GetSystemDirectory, GetTempFileName.
- *
- ************************************************************************/
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <unistd.h>
-#include <time.h>
-#include <sys/stat.h>
-#include <string.h>
-#include "dos_fs.h"
-#include "windows.h"
-#include "msdos.h"
-#include "options.h"
-#include "stddebug.h"
-#include "debug.h"
-
-#define MAX_PATH 255
-
-char WindowsDirectory[256], SystemDirectory[256], TempDirectory[256];
-
-/***************************************************************************
- _lopen 
-
- Emulate the _lopen windows call
- ***************************************************************************/
-INT _lopen (LPSTR lpPathName, INT iReadWrite)
-{
-  int  handle;
-  char *UnixFileName;
-  int mode = 0;
-
-  dprintf_file(stddeb, "_lopen: open('%s', %X);\n", lpPathName, iReadWrite);
-  if ((UnixFileName = DOS_GetUnixFileName(lpPathName)) == NULL)
-  	return HFILE_ERROR;
-  switch(iReadWrite & 3)
-  {
-  case OF_READ:      mode = O_RDONLY; break;
-  case OF_WRITE:     mode = O_WRONLY | O_TRUNC; break;
-  case OF_READWRITE: mode = O_RDWR; break;
-  }
-  handle = open( UnixFileName, mode );
-  if (( handle == -1 ) && Options.allowReadOnly)
-    handle = open( UnixFileName, O_RDONLY );
-
-  dprintf_file(stddeb, "_lopen: open: %s (handle %d)\n", UnixFileName, handle);
-
-  if (handle == -1)
-  	return HFILE_ERROR;
-  else
-  	return handle;
-}
-
-/***************************************************************************
- _lread
- ***************************************************************************/
-INT _lread (INT hFile, LPSTR lpBuffer, WORD wBytes)
-{
-  int result;
-
-  dprintf_file(stddeb, "_lread: handle %d, buffer = %p, length = %d\n",
-	  		hFile, lpBuffer, wBytes);
-  
-  result = (wBytes == 0) ? 0 : read (hFile, lpBuffer, wBytes);
-
-  if (result == -1)
-  	return HFILE_ERROR;
-  else
-  	return result;
-}
-
-/****************************************************************************
- _lwrite
-****************************************************************************/
-INT _lwrite (INT hFile, LPCSTR lpBuffer, WORD wBytes)
-{
-    int result;
-
-    dprintf_file(stddeb, "_lwrite: handle %d, buffer = %p, length = %d\n",
-		 hFile, lpBuffer, wBytes);
-
-    if(wBytes == 0) {  /* Expand the file size if necessary */
-	char toWrite = 0;
-	off_t prev, end;
-	
-	prev = lseek(hFile, 0, SEEK_CUR);
-	if(prev == -1) return HFILE_ERROR;
-	end = lseek(hFile, 0, SEEK_END);
-	if(end == -1) return HFILE_ERROR;
-	if(prev > end) {
-	    lseek(hFile, prev-1, SEEK_SET);
-	    result = write(hFile, &toWrite, 1) - 1;
-	    if(result == -2) ++result;
-	}
-	else {
-	    lseek(hFile, prev, SEEK_SET);
-	    result = 0;
-	}
-    }
-    else result = write (hFile, lpBuffer, wBytes);
-
-    if (result == -1)
-        return HFILE_ERROR;
-    else
-        return result;
-}
-
-/***************************************************************************
- _lclose
- ***************************************************************************/
-INT _lclose (INT hFile)
-{
-    dprintf_file(stddeb, "_lclose: handle %d\n", hFile);
-    
-    if (hFile == 0 || hFile == 1 || hFile == 2) {
-	fprintf( stderr, "Program attempted to close stdin, stdout or stderr!\n" );
-	return 0;
-    }
-    if (close (hFile))
-        return HFILE_ERROR;
-    else
-        return 0;
-}
-
-/**************************************************************************
- OpenFile
- **************************************************************************/
-INT OpenFile (LPCSTR lpFileName, LPOFSTRUCT ofs, UINT wStyle)
-{
-    char         filename[MAX_PATH+1];
-    int          action;
-    struct stat  s;
-    struct tm   *now;
-    int          res, handle;
-    int          verify_time = 0;
-  
-    dprintf_file(stddeb,"Openfile(%s,<struct>,%X)\n",lpFileName,wStyle);
- 
-    action = wStyle & 0xff00;
-  
-    /* OF_CREATE is completly different from all other options, so
-       handle it first */
-
-    if (action & OF_CREATE)
-    {
-        char *unixfilename;
-
-        if (!(action & OF_REOPEN)) strcpy(ofs->szPathName, lpFileName);
-        ofs->cBytes = sizeof(OFSTRUCT);
-        ofs->fFixedDisk = FALSE;
-        ofs->nErrCode = 0;
-        *((int*)ofs->reserved) = 0;
-
-        if ((unixfilename = DOS_GetUnixFileName (ofs->szPathName)) == NULL)
-        {
-            errno_to_doserr();
-            ofs->nErrCode = ExtendedError;
-            return -1;
-        }
-	/* Apparently, at least the OF_READ parameter is ignored when
-	 * a file is created. Using O_RDWR makes the most sense.
-	 */
-        handle = open (unixfilename, O_TRUNC | O_RDWR | O_CREAT, 0666);
-        if (handle == -1)
-        {
-            errno_to_doserr();
-            ofs->nErrCode = ExtendedError;
-        }   
-        return handle;
-    }
-
-
-    /* If path isn't given, try to find the file. */
-
-    if (!(action & OF_REOPEN))
-    {
-	char temp[MAX_PATH + 1];
-	
-	if(index(lpFileName,'\\') || index(lpFileName,'/') || 
-	   index(lpFileName,':')) 
-	{
-	    strcpy (filename,lpFileName);
-	    goto found;
-	}
-	/* Try current directory */
-	if (DOS_FindFile(temp, MAX_PATH, lpFileName, NULL, ".")) {
-	    strcpy(filename, DOS_GetDosFileName(temp));
-	    goto found;
-	}
-
-	/* Try Windows directory */
-	GetWindowsDirectory(filename, MAX_PATH);
-	if (DOS_FindFile(temp, MAX_PATH, lpFileName, NULL, filename)) {
-	    strcpy(filename, DOS_GetDosFileName(temp));
-	    goto found;
-	}
-	
-	/* Try Windows system directory */
-	GetSystemDirectory(filename, MAX_PATH);
-	if (DOS_FindFile(temp, MAX_PATH, lpFileName, NULL, filename)) {
-	    strcpy(filename, DOS_GetDosFileName(temp));
-	    goto found;
-	}
-
-	/* Try the path of the current executable */
-	if (GetCurrentTask())
-	{
-	    char *p;
-	    GetModuleFileName( GetCurrentTask(), filename, MAX_PATH );
-	    if ((p = strrchr( filename, '\\' )))
-	    {
-		p[1] = '\0';
-		if (DOS_FindFile(temp, MAX_PATH, lpFileName, NULL, filename)) {
-		    strcpy(filename, DOS_GetDosFileName(temp));
-		    goto found;
-		}
-	    }
-	}
-
-	/* Try all directories in path */
-
-	if (DOS_FindFile(temp,MAX_PATH,lpFileName,NULL,WindowsPath))
-	{
-	    strcpy(filename, DOS_GetDosFileName(temp));
-	    goto found;
-	}
-	/* ??? shouldn't we give an error here? */
-	strcpy (filename, lpFileName);
-	
-	found:
-	
-	ofs->cBytes = sizeof(OFSTRUCT);
-	ofs->fFixedDisk = FALSE;
-	strcpy(ofs->szPathName, filename);
-	ofs->nErrCode = 0;
-        if (!(action & OF_VERIFY))
-          *((int*)ofs->reserved) = 0;
-    }
-    
-
-    if (action & OF_PARSE)
-        return 0;
-
-    if (action & OF_DELETE)
-      return unlink(DOS_GetUnixFileName(ofs->szPathName));
-    /* FIXME: I suppose we should check return codes here like stat below */
-
-    /* Now on to getting some information about that file */
-
-    if ((res = stat(DOS_GetUnixFileName(ofs->szPathName), &s)))
-      {
-      errno_to_doserr();
-      ofs->nErrCode = ExtendedError;
-      return -1;
-    }
-    
-    now = localtime (&s.st_mtime);
-
-    if (action & OF_VERIFY)
-      verify_time = *((int*)ofs->reserved);
-    
-    *((WORD*)(&ofs->reserved[2]))=
-         ((now->tm_hour * 0x2000) + (now->tm_min * 0x20) + (now->tm_sec / 2));
-    *((WORD*)(&ofs->reserved[0]))=
-         ((now->tm_year * 0x200) + (now->tm_mon * 0x20) + now->tm_mday);
-
-    if (action & OF_VERIFY)
-      return (verify_time != *((int*)ofs->reserved));
-
-    if ((handle = _lopen( ofs->szPathName, wStyle )) == -1)
-    {
-        ofs->nErrCode = 2;  /* not found */
-        return -1;
-    }
-    if (action & OF_EXIST) close(handle);
-    return handle;
-}
-
-
-/**************************************************************************
- SetHandleCount
-
- Changes the number of file handles available to the application.  Since
- Linux isn't limited to 20 files, this one's easy. - SL
- **************************************************************************/
-
-#if !defined (OPEN_MAX)
-/* This one is for the Sun */
-#define OPEN_MAX _POSIX_OPEN_MAX
-#endif
-WORD SetHandleCount (WORD wNumber)
-{
-  dprintf_file(stddeb,"SetHandleCount(%d)\n",wNumber);
-  return((wNumber<OPEN_MAX) ? wNumber : OPEN_MAX);
-}
-
-/***************************************************************************
- _llseek
- ***************************************************************************/
-LONG _llseek (INT hFile, LONG lOffset, INT nOrigin)
-{
-	int origin;
-	
-  	dprintf_file(stddeb, "_llseek: handle %d, offset %ld, origin %d\n", 
-		hFile, lOffset, nOrigin);
-
-	switch (nOrigin) {
-		case 1: origin = SEEK_CUR;
-			break;
-		case 2: origin = SEEK_END;
-			break;
-		default: origin = SEEK_SET;
-			break;
-	}
-
-	return lseek(hFile, lOffset, origin);
-}
-
-/***************************************************************************
- _lcreat
- ***************************************************************************/
-INT _lcreat (LPSTR lpszFilename, INT fnAttribute)
-{
-	int handle;
-	char *UnixFileName;
-
-    	dprintf_file(stddeb, "_lcreat: filename %s, attributes %d\n",
-		lpszFilename, fnAttribute);
-	if ((UnixFileName = DOS_GetUnixFileName(lpszFilename)) == NULL)
-  		return HFILE_ERROR;
-	handle =  open (UnixFileName, O_CREAT | O_TRUNC | O_RDWR, 0666);
-
-	if (handle == -1)
-		return HFILE_ERROR;
-	else
-		return handle;
-}
-
-/***************************************************************************
- GetDriveType
- ***************************************************************************/
-WORD GetDriveType(INT drive)
-{
-
-    	dprintf_file(stddeb,"GetDriveType %c:\n",'A'+drive);
- 
-        /* File Damager thinks that only return code 0 is bad enough 
-	 * -Al K
-	 */
-
-	if (!DOS_ValidDrive(drive))
-		return DRIVE_CANNOTDETERMINE;
-
-	if (drive == 0 || drive == 1)
-		return DRIVE_REMOVABLE;
-		 
-	return DRIVE_FIXED;
-}
-
-/***************************************************************************
- GetTempDrive
- ***************************************************************************/
-BYTE GetTempDrive(BYTE chDriveLetter)
-{
-    dprintf_file(stddeb,"GetTempDrive (%d)\n",chDriveLetter);
-    if (TempDirectory[1] == ':') return TempDirectory[0];
-    else return 'C';
-}
-
-/***************************************************************************
- GetWindowsDirectory
- ***************************************************************************/
-UINT GetWindowsDirectory(LPSTR lpszSysPath, UINT cbSysPath)
-{
-	if (cbSysPath < strlen(WindowsDirectory)) 
-		*lpszSysPath = 0;
-	else
-		strcpy(lpszSysPath, WindowsDirectory);
-	
-    	dprintf_file(stddeb,"GetWindowsDirectory (%s)\n",lpszSysPath);
-
-	return strlen(lpszSysPath);
-}
-/***************************************************************************
- GetSystemDirectory
- ***************************************************************************/
-UINT GetSystemDirectory(LPSTR lpszSysPath, UINT cbSysPath)
-{
-	if (cbSysPath < strlen(SystemDirectory))
-		*lpszSysPath = 0;
-	else
-		strcpy(lpszSysPath, SystemDirectory);
-
-    	dprintf_file(stddeb,"GetSystemDirectory (%s)\n",lpszSysPath);
-
-	return strlen(lpszSysPath);
-}
-/***************************************************************************
- GetTempFileName
- ***************************************************************************/
-INT GetTempFileName(BYTE bDriveLetter, LPCSTR lpszPrefixString, UINT uUnique, LPSTR lpszTempFileName)
-{
-	int unique;
-	int handle;
-	char tempname[256];
-	
-	if (uUnique == 0)
-		unique = time(NULL)%99999L;
-	else
-		unique = uUnique%99999L;
-
-	strcpy(tempname,lpszPrefixString);
-	tempname[3]='\0';
-
-	sprintf(lpszTempFileName,"%s\\%s%d.tmp", TempDirectory, tempname, 
-		unique);
-
-	ToDos(lpszTempFileName);
-
-    	dprintf_file(stddeb,"GetTempFilename: %c %s %d => %s\n",bDriveLetter,
-		lpszPrefixString,uUnique,lpszTempFileName);
-	if ((handle = _lcreat (lpszTempFileName, 0x0000)) == -1) {
-		fprintf(stderr,"GetTempFilename: can't create temp file '%s' !\n", lpszTempFileName);
-	}
-	else
-		close(handle);
-
-	return unique;
-}
-
-/***************************************************************************
- SetErrorMode
- ***************************************************************************/
-WORD SetErrorMode(WORD x)
-{
-    dprintf_file(stdnimp,"wine: SetErrorMode %4x (ignored)\n",x);
-
-    return 1;
-}
-
-/***************************************************************************
- _hread
- ***************************************************************************/
-LONG _hread(INT hf, LPSTR hpvBuffer, LONG cbBuffer)
-{
-    return (cbBuffer == 0) ? 0 : read(hf, hpvBuffer, cbBuffer);
-}
-/***************************************************************************
- _hwrite
- ***************************************************************************/
-LONG _hwrite(INT hf, LPCSTR hpvBuffer, LONG cbBuffer)
-{
-    return (cbBuffer == 0) ? 0 : write(hf, hpvBuffer, cbBuffer);
-}
diff --git a/misc/lstr.c b/misc/lstr.c
index 5d03363..5f7c90a 100644
--- a/misc/lstr.c
+++ b/misc/lstr.c
@@ -66,17 +66,36 @@
 /* USER.430 */
 INT lstrcmp(LPCSTR str1,LPCSTR str2)
 {
-  return strcmp(str1,str2);
+    return strcmp( str1, str2 );
 }
 
 /* USER.471 */
-INT lstrcmpi(LPCSTR str1,LPCSTR str2)
+INT lstrcmpi( LPCSTR str1, LPCSTR str2 )
 {
-  int i;
-  i=0;
-  while((toupper(str1[i])==toupper(str2[i]))&&(str1[i]!=0))
-    i++;
-  return toupper(str1[i])-toupper(str2[i]);
+    INT res;
+
+    while (*str1)
+    {
+        if ((res = toupper(*str1) - toupper(*str2)) != 0) return res;
+        str1++;
+        str2++;
+    }
+    return toupper(*str1) - toupper(*str2);
+}
+
+/* Not a Windows API*/
+INT lstrncmpi( LPCSTR str1, LPCSTR str2, int n )
+{
+    INT res;
+
+    if (!n) return 0;
+    while ((--n > 0) && *str1)
+    {
+        if ((res = toupper(*str1) - toupper(*str2)) != 0) return res;
+        str1++;
+        str2++;
+    }
+    return toupper(*str1) - toupper(*str2);
 }
 
 /* KERNEL.88 */
@@ -87,13 +106,13 @@
 }
 
 /* KERNEL.353 32-bit version*/
-char *lstrcpyn(char *dst, char *src, int n)
+char *lstrcpyn( char *dst, const char *src, int n )
 {
     char *tmp = dst;
     while(n-- > 1 && *src)
-    	*dst++ = *src++;
-    *dst = 0;
-    return tmp;
+    	*tmp++ = *src++;
+    *tmp = 0;
+    return dst;
 }
 
 /* KERNEL.353 16-bit version*/
diff --git a/misc/main.c b/misc/main.c
index 9226c08..0d9e948 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -7,6 +7,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include <ctype.h>
 #include <locale.h>
 #ifdef MALLOC_DEBUGGING
@@ -17,9 +18,9 @@
 #include <X11/Xutil.h>
 #include <X11/cursorfont.h>
 #include "wine.h"
+#include "message.h"
 #include "msdos.h"
 #include "windows.h"
-#include "miscemu.h"
 #include "winsock.h"
 #include "options.h"
 #include "desktop.h"
@@ -226,7 +227,7 @@
       l=strchr(options,',')-options;
     else
       l=strlen(options);
-    if (!strncasecmp(options+1,"all",l-1))
+    if (!lstrncmpi(options+1,"all",l-1))
       {
 	int i;
 	for (i=0;i<sizeof(debug_msg_enabled)/sizeof(short);i++)
@@ -236,7 +237,7 @@
       {
 	int i;
 	for (i=0;i<sizeof(debug_msg_enabled)/sizeof(short);i++)
-	  if (debug_msg_name && (!strncasecmp(options+1,debug_msg_name[i],l-1)))
+	  if (debug_msg_name && (!lstrncmpi(options+1,debug_msg_name[i],l-1)))
 	    {
 	      debug_msg_enabled[i]=(*options=='+');
 	      break;
@@ -275,7 +276,7 @@
       l=strchr(options,',')-options;
     else l=strlen(options);
     for (i=0;i<N_BUILTINS;i++)
-         if (!strncasecmp(options+1,dll_builtin_table[i].name,l-1))
+         if (!lstrncmpi(options+1,dll_builtin_table[i].name,l-1))
            {
              dll_builtin_table[i].used = (*options=='+');
              break;
@@ -306,7 +307,7 @@
     Options.language = LANG_En;  /* First language */
     for (p = langNames; *p; p++)
     {
-        if (!strcasecmp( *p, arg )) return;
+        if (!lstrcmpi( *p, arg )) return;
         Options.language++;
     }
     fprintf( stderr, "Invalid language specified '%s'. Supported languages are: ", arg );
@@ -335,7 +336,7 @@
 #ifdef WINELIB
     /* Need to assemble command line and pass it to WinMain */
 #else
-    if (*argc < 2 || strcasecmp(argv[1], "-h") == 0) 
+    if (*argc < 2 || lstrcmpi(argv[1], "-h") == 0) 
     	MAIN_Usage( argv[0] );
 #endif
 
@@ -550,6 +551,7 @@
     int ret_val;
     int depth_count, i;
     int *depth_list;
+    struct timeval tv;
 
     extern int _WinMain(int argc, char **argv);
 
@@ -557,6 +559,8 @@
     setbuf(stderr,NULL);
 
     setlocale(LC_CTYPE,"");
+    gettimeofday( &tv, NULL);
+    MSG_WineStartTicks = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
 
     XrmInitialize();
     
@@ -603,11 +607,7 @@
     else rootWindow = DefaultRootWindow( display );
 
     MAIN_SaveSetup();
-#ifndef sparc
     atexit(called_at_exit);
-#else
-    on_exit (called_at_exit, 0);
-#endif
 
     ret_val = _WinMain( argc, argv );
 
diff --git a/misc/network.c b/misc/network.c
index b798a5e..6840755 100644
--- a/misc/network.c
+++ b/misc/network.c
@@ -3,12 +3,10 @@
  */
 
 #include <ctype.h>
-#include "stdio.h"
-#include "windows.h"
-#include "user.h"
+#include <stdio.h>
 
-#include "msdos.h"
-#include "dos_fs.h"
+#include "windows.h"
+#include "drive.h"
 
 #define WN_SUCCESS       			0x0000
 #define WN_NOT_SUPPORTED 			0x0001
@@ -158,29 +156,28 @@
 int WNetGetConnection(LPSTR lpLocalName, 
 	LPSTR lpRemoteName, UINT FAR *cbRemoteName)
 {
-    int drive, rc;
+    const char *path;
 
-    if(lpLocalName[1] == ':')
+    if (lpLocalName[1] == ':')
     {
-        drive = toupper(lpLocalName[0]) - 'A';
-        if(!DOS_ValidDrive(drive))
-            rc = WN_NOT_CONNECTED;
-        else
+        int drive = toupper(lpLocalName[0]) - 'A';
+        switch(GetDriveType(drive))
         {
-            if(strlen(DOS_GetRedirectedDir(drive)) + 1 > *cbRemoteName)
-                rc = WN_MORE_DATA;
-            else
-            {
-                strcpy(lpRemoteName, DOS_GetRedirectedDir(drive));
-                *cbRemoteName = strlen(lpRemoteName) + 1;
-                rc = WN_SUCCESS;
-            }
+        case DRIVE_CANNOTDETERMINE:
+        case DRIVE_DOESNOTEXIST:
+            return WN_BAD_LOCALNAME;
+        case DRIVE_REMOVABLE:
+        case DRIVE_FIXED:
+            return WN_NOT_CONNECTED;
+        case DRIVE_REMOTE:
+            path = DRIVE_GetDosCwd(drive);
+            if (strlen(path) + 1 > *cbRemoteName) return WN_MORE_DATA;
+            strcpy( lpRemoteName, path );
+            *cbRemoteName = strlen(lpRemoteName) + 1;
+            return WN_SUCCESS;
         }
     }
-    else
-        rc = WN_BAD_LOCALNAME;
-
-    return rc;
+    return WN_BAD_LOCALNAME;
 }
 
 /**************************************************************************
diff --git a/misc/ole2nls.c b/misc/ole2nls.c
index b02fe65a..8100e5e 100644
--- a/misc/ole2nls.c
+++ b/misc/ole2nls.c
@@ -460,7 +460,7 @@
 	l2 = (l2==-1)?strlen(s2):l2;
 	len = l1<l2 ? l1:l2;
 	ret = (fdwStyle & NORM_IGNORECASE) ?
-		strncasecmp(s1,s2,len)	:
+		lstrncmpi(s1,s2,len)	:
 		strncmp(s1,s2,len);
 	/* not equal, return 1 or 3 */
 	if(ret!=0)return ret+2;
diff --git a/misc/port.c b/misc/port.c
new file mode 100644
index 0000000..52ac9d9
--- /dev/null
+++ b/misc/port.c
@@ -0,0 +1,22 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#ifndef HAVE_USLEEP
+
+unsigned int usleep (unsigned int useconds)
+{
+    struct timeval delay;
+
+    delay.tv_sec = 0;
+    delay.tv_usec = useconds;
+
+    (void) select (0, (fd_set *) NULL, (fd_set *) NULL, (fd_set *) NULL,
+		   &delay);
+    return 0;
+}
+
+#endif /* HAVE_USLEEP */
+
+
+
diff --git a/misc/profile.c b/misc/profile.c
index ecd1b72..4790c01 100644
--- a/misc/profile.c
+++ b/misc/profile.c
@@ -58,7 +58,7 @@
     TProfile *p = Base;
     
     while (p){
-	if (!strcasecmp (FileName, p->FileName)){
+	if (!lstrcmpi( FileName, p->FileName)){
 	    Current = p;
 	    return p->Section;
 	}
@@ -67,6 +67,26 @@
     return 0;
 }
 
+#define WIN_INI WinIniFileName()
+
+static char *WinIniFileName(void)
+{
+    static char *name = NULL;
+    int len;
+    const char *unixName;
+
+    if (name) return name;
+
+    len = GetWindowsDirectory( NULL, 0 ) + 9;
+    name = xmalloc( len );
+    GetWindowsDirectory( name, len );
+    strcat( name, "/win.ini" );
+    if (!(unixName = DOSFS_GetUnixFileName( name, TRUE ))) return NULL;
+    free( name );
+    name = strdup( unixName );
+    return name;
+}
+
 static char *GetIniFileName(char *name, char *dir)
 {
 	char temp[256];
@@ -81,7 +101,7 @@
 	}
 	else
 	  strcpy(temp, name);
-	return DOS_GetUnixFileName(temp);
+	return DOSFS_GetUnixFileName(temp,TRUE);
 }
 
 static TSecHeader *load (char *filename, char **pfullname)
@@ -103,26 +123,27 @@
 
     /* First try it as is */
     file = GetIniFileName(filename, "");
-    f = fopen(file, "r");
-    
-    if (f == NULL) {
-
+    if (!file || !(f = fopen(file, "r")))
+    {
       if  ((purefilename = strrchr( filename, '\\' )))
 	purefilename++; 
       else if  ((purefilename = strrchr( filename, '/' ))) 
 	purefilename++; 
       else
 	purefilename = filename;
-      ToUnix(purefilename);
 
       /* Now try the Windows directory */
       GetWindowsDirectory(path, sizeof(path));
-      file = GetIniFileName(purefilename, path);
-      dprintf_profile(stddeb,"Trying to load  in windows directory file %s\n",
-		      file);
-      f = fopen(file, "r");
-    
-      if (f == NULL) { 	/* Try the path of the current executable */
+      if ((file = GetIniFileName(purefilename, path)))
+      {
+          dprintf_profile(stddeb,"Trying to load  in windows directory file %s\n",
+                          file);
+          f = fopen(file, "r");
+      }
+      else f = NULL;
+
+      if (f == NULL)
+      { 	/* Try the path of the current executable */
     
 	if (GetCurrentTask())
 	{
@@ -131,30 +152,34 @@
 	    if ((p = strrchr( path, '\\' )))
 	    {
 		p[0] = '\0'; /* Remove trailing slash */
-		file = GetIniFileName(purefilename, path);
-		dprintf_profile(stddeb,
-				"Trying to load in current directory%s\n",
-				file);
-		f = fopen(file, "r");
+		if ((file = GetIniFileName(purefilename, path)))
+                {
+                    dprintf_profile(stddeb,
+                                    "Trying to load in current directory%s\n",
+                                    file);
+                    f = fopen(file, "r");
+                }
 	    }
 	}
     }
       if (f == NULL) { 	/* And now in $HOME/.wine */
 	
-	strcpy(file,getenv("HOME"));
-	strcat(file, "/.wine/");
-	strcat(file, purefilename);
-	dprintf_profile(stddeb,"Trying to load in user-directory %s\n", file);
+	strcpy(path,getenv("HOME"));
+	strcat(path, "/.wine/");
+	strcat(path, purefilename);
+	dprintf_profile(stddeb,"Trying to load in user-directory %s\n", path);
+        file = path;
 	f = fopen(file, "r");
       }
       
       if (f == NULL) {
 	/* FIXED: we ought to create it now (in which directory?) */
 	/* lets do it in ~/.wine */
-	strcpy(file,getenv("HOME"));
-	strcat(file, "/.wine/");
-	strcat(file, purefilename);
-	dprintf_profile(stddeb,"Creating %s\n", file);
+	strcpy(path,getenv("HOME"));
+	strcat(path, "/.wine/");
+	strcat(path, purefilename);
+	dprintf_profile(stddeb,"Creating %s\n", path);
+        file = path;
 	f = fopen(file, "w+");
     if (f == NULL) {
 	fprintf(stderr, "profile.c: load() can't find file %s\n", filename);
@@ -163,7 +188,7 @@
       }
     }
     
-    *pfullname = strdup(file);
+    *pfullname = xstrdup(file);
     dprintf_profile(stddeb,"Loading %s\n", file);
 
     firstbrace = TRUE;
@@ -205,7 +230,7 @@
 	    *lastnonspc = 0;
 	    if (!strlen(CharBuffer))
 	    	fprintf(stderr, "warning: empty section name in ini file\n");
-	    SecHeader->AppName = strdup (CharBuffer);
+	    SecHeader->AppName = xstrdup (CharBuffer);
 	    dprintf_profile(stddeb,"%s: section %s\n", file, CharBuffer);
 	    firstbrace = FALSE;
 	} else if (SecHeader) {
@@ -232,7 +257,7 @@
 	    	fprintf(stderr, "warning: empty key name in ini file\n");
 	    SecHeader->Keys = (TKeys *) xmalloc (sizeof (TKeys));
 	    SecHeader->Keys->link = temp;
-	    SecHeader->Keys->KeyName = strdup (CharBuffer);
+	    SecHeader->Keys->KeyName = xstrdup (CharBuffer);
 
 	    dprintf_profile(stddeb,"%s:   key %s\n", file, CharBuffer);
 	    
@@ -251,7 +276,7 @@
 		}
 	    } while(bufsize < STRSIZE-1);
 	    *lastnonspc = 0;
-	    SecHeader->Keys->Value = strdup (CharBuffer);
+	    SecHeader->Keys->Value = xstrdup (CharBuffer);
 	    dprintf_profile (stddeb, "[%s] (%s)=%s\n", SecHeader->AppName,
 			     SecHeader->Keys->KeyName, SecHeader->Keys->Value);
 	    if (c == ';') {
@@ -275,8 +300,8 @@
     TKeys *key;
     
     key = (TKeys *) xmalloc (sizeof (TKeys));
-    key->KeyName = strdup (KeyName);
-    key->Value   = strdup (Value);
+    key->KeyName = xstrdup (KeyName);
+    key->Value   = xstrdup (Value);
     key->link = section->Keys;
     section->Keys = key;
 }
@@ -297,7 +322,7 @@
     if (!(section = is_loaded (FileName))){
 	New = (TProfile *) xmalloc (sizeof (TProfile));
 	New->link = Base;
-	New->FileName = strdup (FileName);
+	New->FileName = xstrdup (FileName);
 	New->Section = load (FileName, &New->FullName);
 	New->changed = FALSE;
 	Base = New;
@@ -307,7 +332,7 @@
 
     /* Start search */
     for (; section; section = section->link){
-	if (strcasecmp (section->AppName, AppName))
+	if (lstrcmpi(section->AppName, AppName))
 	    continue;
 
 	/* If no key value given, then list all the keys */
@@ -333,11 +358,11 @@
 	}
 	for (key = section->Keys; key; key = key->link){
 	    int slen;
-	    if (strcasecmp (key->KeyName, KeyName))
+	    if (lstrcmpi(key->KeyName, KeyName))
 		continue;
 	    if (set){
 		free (key->Value);
-		key->Value = strdup (Default ? Default : "");
+		key->Value = xstrdup (Default ? Default : "");
 		Current->changed=TRUE;
 		return 1;
 	    }
@@ -362,7 +387,7 @@
     /* Non existent section */
     if (set){
 	section = (TSecHeader *) xmalloc (sizeof (TSecHeader));
-	section->AppName = strdup (AppName);
+	section->AppName = xstrdup (AppName);
 	section->Keys = 0;
 	new_key (section, KeyName, Default);
 	section->link = Current->Section;
@@ -376,9 +401,9 @@
     return 1;
 }
 
-short GetPrivateProfileString (LPSTR AppName, LPSTR KeyName,
-			       LPSTR Default, LPSTR ReturnedString,
-			       short Size, LPSTR FileName)
+short GetPrivateProfileString (LPCSTR AppName, LPCSTR KeyName,
+			       LPCSTR Default, LPSTR ReturnedString,
+			       short Size, LPCSTR FileName)
 {
     int v;
 
@@ -391,15 +416,15 @@
 	return Size - v;
 }
 
-int GetProfileString (LPSTR AppName, LPSTR KeyName, LPSTR Default, 
+int GetProfileString (LPCSTR AppName, LPCSTR KeyName, LPCSTR Default, 
 		      LPSTR ReturnedString, int Size)
 {
     return GetPrivateProfileString (AppName, KeyName, Default,
-				    ReturnedString, Size, WIN_INI);
+				    ReturnedString, Size, WIN_INI );
 }
 
-WORD GetPrivateProfileInt (LPSTR AppName, LPSTR KeyName, short Default,
-			   LPSTR File)
+WORD GetPrivateProfileInt (LPCSTR AppName, LPCSTR KeyName, short Default,
+			   LPCSTR File)
 {
     static char IntBuf[10];
     static char buf[10];
@@ -408,14 +433,14 @@
     
     /* Check the exact semantic with the SDK */
     GetPrivateProfileString (AppName, KeyName, buf, IntBuf, 10, File);
-    if (!strcasecmp (IntBuf, "true"))
+    if (!lstrcmpi(IntBuf, "true"))
 	return 1;
-    if (!strcasecmp (IntBuf, "yes"))
+    if (!lstrcmpi(IntBuf, "yes"))
 	return 1;
     return strtoul( IntBuf, NULL, 0 );
 }
 
-WORD GetProfileInt (LPSTR AppName, LPSTR KeyName, int Default)
+WORD GetProfileInt (LPCSTR AppName, LPCSTR KeyName, int Default)
 {
     return GetPrivateProfileInt (AppName, KeyName, Default, WIN_INI);
 }
diff --git a/misc/shell.c b/misc/shell.c
index 5e50505..0d48698 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -150,11 +150,11 @@
 			if (NULL!=(t=strchr(s,'='))) {
 				*t='\0';t++;
 				lpNewKey->dwType	= REG_SZ;
-				lpNewKey->lpSubKey	= strdup(s);
-				lpNewKey->lpValue	= strdup(t);
+				lpNewKey->lpSubKey	= xstrdup(s);
+				lpNewKey->lpValue	= xstrdup(t);
 			} else {
 				lpNewKey->dwType	= REG_SZ;
-				lpNewKey->lpSubKey	= strdup(s);
+				lpNewKey->lpSubKey	= xstrdup(s);
 			}
 			_LoadLevel(f,lpNewKey,tabsexp+1,buf);
 		}
@@ -175,11 +175,11 @@
 		if (NULL!=(t=strchr(s,'='))) {
 			*t='\0';t++;
 			lpNewKey->dwType	= REG_SZ;
-			lpNewKey->lpSubKey	= strdup(s);
-			lpNewKey->lpValue	= strdup(t);
+			lpNewKey->lpSubKey	= xstrdup(s);
+			lpNewKey->lpValue	= xstrdup(t);
 		} else {
 			lpNewKey->dwType	= REG_SZ;
-			lpNewKey->lpSubKey	= strdup(s);
+			lpNewKey->lpSubKey	= xstrdup(s);
 		}
 		lpKey=lpNewKey;
 	}
@@ -280,6 +280,7 @@
 	  lpKey = lphTopKey; break;
         case HKEY_CLASSES_ROOT: /* == 1 */
         case 0x80000000:
+        case 0x80000001:
           lpKey = lphRootKey; break;
         default: 
 	  dprintf_reg(stddeb,"RegCreateKey // specific key = %08lX !\n", (DWORD)hKey);
diff --git a/misc/spy.c b/misc/spy.c
index e547e1c..3a92d62 100644
--- a/misc/spy.c
+++ b/misc/spy.c
@@ -539,7 +539,7 @@
 	    if(MessageTypeNames[i])
 	       if(strstr(lpstrBuffer,MessageTypeNames[i])) SpyFilters[i] = TRUE; 
 
-    GetPrivateProfileString("spy", "Include", "",lpstrBuffer ,511 , WINE_INI);
+    GetPrivateProfileString("spy", "Include", "INCLUDEALL",lpstrBuffer ,511 , WINE_INI);
     dprintf_message(stddeb,"SpyInit: Include=%s\n",lpstrBuffer);
     if( *lpstrBuffer != 0 )
       if(strstr(lpstrBuffer,"INCLUDEALL"))
diff --git a/misc/user.c b/misc/user.c
index 1005ffd..27bd40c 100644
--- a/misc/user.c
+++ b/misc/user.c
@@ -74,6 +74,26 @@
 
 
 /***********************************************************************
+ *           TimerCount   (TOOLHELP.80)
+ */
+BOOL TimerCount( TIMERINFO *pTimerInfo )
+{
+        /* FIXME
+         * In standard mode, dwmsSinceStart = dwmsThisVM 
+         *
+         * I tested this, under Windows in enhanced mode, and
+         * if you never switch VM (ie start/stop DOS) these
+         * values should be the same as well. 
+         *
+         * Also, Wine should adjust for the hardware timer
+         * to reduce the amount of error to ~1ms. 
+         * I can't be bothered, can you?
+         */
+        pTimerInfo->dwmsSinceStart = pTimerInfo->dwmsThisVM = GetTickCount();
+        return TRUE;
+}
+
+/***********************************************************************
  *           USER_HeapInit
  */
 BOOL USER_HeapInit(void)
diff --git a/misc/user32.c b/misc/user32.c
index 5deaa83..5097b8c 100644
--- a/misc/user32.c
+++ b/misc/user32.c
@@ -13,6 +13,7 @@
 #include "relay32.h"
 #include "alias.h"
 #include "stackframe.h"
+#include "xmalloc.h"
 
 /* Structure copy functions */
 static void MSG16to32(MSG *msg16,struct WIN32_MSG *msg32)
@@ -43,7 +44,11 @@
 ATOM USER32_RegisterClassA(WNDCLASSA* wndclass)
 {
 	WNDCLASS copy;
-	char *s1,*s2;
+	HANDLE classh = 0, menuh = 0;
+	SEGPTR classsegp, menusegp;
+	char *classbuf, *menubuf;
+
+	ATOM retval;
 	copy.style=wndclass->style;
 	ALIAS_RegisterAlias(0,0,(DWORD)wndclass->lpfnWndProc);
 	copy.lpfnWndProc=wndclass->lpfnWndProc;
@@ -53,29 +58,31 @@
 	copy.hIcon=(HICON)wndclass->hIcon;
 	copy.hCursor=(HCURSOR)wndclass->hCursor;
 	copy.hbrBackground=(HBRUSH)wndclass->hbrBackground;
+
+	/* FIXME: There has to be a better way of doing this - but neither
+	malloc nor alloca will work */
+
 	if(wndclass->lpszMenuName)
 	{
-		s1=alloca(strlen(wndclass->lpszMenuName)+1);
-		strcpy(s1,wndclass->lpszMenuName);
-		copy.lpszMenuName=MAKE_SEGPTR(s1);
+		menuh = GlobalAlloc(0, strlen(wndclass->lpszMenuName)+1);
+		menusegp = WIN16_GlobalLock(menuh);
+		menubuf = PTR_SEG_TO_LIN(menusegp);
+		strcpy( menubuf, wndclass->lpszMenuName);
+		copy.lpszMenuName=menusegp;
 	}else
 		copy.lpszMenuName=0;
 	if(wndclass->lpszClassName)
 	{
-		s2=alloca(strlen(wndclass->lpszClassName)+1);
-		strcpy(s2,wndclass->lpszClassName);
-		copy.lpszClassName=MAKE_SEGPTR(s2);
+		classh = GlobalAlloc(0, strlen(wndclass->lpszClassName)+1);
+		classsegp = WIN16_GlobalLock(classh);
+		classbuf = PTR_SEG_TO_LIN(classsegp);
+		strcpy( classbuf, wndclass->lpszClassName);
+		copy.lpszClassName=classsegp;
 	}
-	return RegisterClass(&copy);
-}
-
-/***********************************************************************
- *          DefWindowProcA       (USER32.125)
- */
-LRESULT USER32_DefWindowProcA(DWORD hwnd,DWORD msg,DWORD wParam,DWORD lParam)
-{
-	/* some messages certainly need special casing. We come to that later */
-	return DefWindowProc((HWND)hwnd,msg,wParam,lParam);
+	retval = RegisterClass(&copy);
+	GlobalFree(menuh);
+	GlobalFree(classh);
+	return retval;
 }
 
 /***********************************************************************
@@ -141,22 +148,50 @@
 }
 
 /***********************************************************************
+ *         TranslateMessage       (USER32.555)
+ */
+BOOL USER32_TranslateMessage(struct WIN32_MSG* lpmsg)
+{
+	MSG msg;
+	MSG32to16(lpmsg,&msg);
+	return TranslateMessage(&msg);
+}
+
+/***********************************************************************
  *         CreateWindowExA        (USER32.82)
  */
 DWORD USER32_CreateWindowExA(long flags,char* class,char *title,
 	long style,int x,int y,int width,int height,DWORD parent,DWORD menu,
 	DWORD instance,DWORD param)
 {
+    DWORD retval;
+    HANDLE classh, titleh;
+    SEGPTR classsegp, titlesegp;
     char *classbuf, *titlebuf;
+
     /*Have to translate CW_USEDEFAULT */
     if(x==0x80000000)x=CW_USEDEFAULT;
+    if(y==0x80000000)y=CW_USEDEFAULT;
     if(width==0x80000000)width=CW_USEDEFAULT;
-    classbuf = alloca( strlen(class)+1 );
+    if(height==0x80000000)height=CW_USEDEFAULT;
+
+    /* FIXME: There has to be a better way of doing this - but neither
+    malloc nor alloca will work */
+
+    classh = GlobalAlloc(0, strlen(class)+1);
+    titleh = GlobalAlloc(0, strlen(title)+1);
+    classsegp = WIN16_GlobalLock(classh);
+    titlesegp = WIN16_GlobalLock(titleh);
+    classbuf = PTR_SEG_TO_LIN(classsegp);
+    titlebuf = PTR_SEG_TO_LIN(titlesegp);
     strcpy( classbuf, class );
-    titlebuf = alloca( strlen(title)+1 );
     strcpy( titlebuf, title );
-    return (DWORD) CreateWindowEx(flags,MAKE_SEGPTR(classbuf),
-				  MAKE_SEGPTR(titlebuf),style,x,y,width,height,
+    
+    retval = (DWORD) CreateWindowEx(flags,classsegp,
+				  titlesegp,style,x,y,width,height,
 				  (HWND)parent,(HMENU)menu,(HINSTANCE)instance,
 				  (LPVOID)param);
+    GlobalFree(classh);
+    GlobalFree(titleh);
+    return retval;
 }
diff --git a/misc/winsocket.c b/misc/winsocket.c
index 536e5db..0586e52 100644
--- a/misc/winsocket.c
+++ b/misc/winsocket.c
@@ -23,7 +23,7 @@
 #include <errno.h>
 #include <netdb.h>
 #include <unistd.h>
-#undef TRANSPARENT
+
 #include "winsock.h"
 #include "toolhelp.h"
 #include "stddebug.h"
@@ -35,9 +35,7 @@
 static FARPROC BlockFunction;
 static fd_set fd_in_use;
 
-#ifdef __FreeBSD__
 extern int h_errno;
-#endif /* __FreeBSD__ */
 
 struct ipc_packet {
 	long	mtype;
@@ -660,11 +658,10 @@
     }
     
     if (sock > 0xffff) {
-	/* we set the value of wsa_errno directly, because 
-	 * only support socket numbers up to 0xffff. The
-	 * value return indicates there are no descriptors available
+	/* we only support socket numbers up to 0xffff. The return
+	 * value indicates there are no more descriptors available
 	 */
-	wsa_errno = WSAEMFILE;
+        WSASetLastError(WSAEMFILE);
 	return INVALID_SOCKET;
     }
 
@@ -846,7 +843,7 @@
 		if (!message_is_valid) {
 			if (msgrcv(wine_key, (struct msgbuf*)&(message), 
 				   IPC_PACKET_SIZE, MTYPE, IPC_NOWAIT) == -1) {
-				perror("wine: msgrcv");
+				perror("wine: winsock: msgrcv");
 				break;
 			}
 		}
@@ -877,7 +874,7 @@
 
 	if (msgsnd(wine_key, (struct msgbuf*)&(message),  
 		   IPC_PACKET_SIZE, 0/*IPC_NOWAIT*/) == -1)
-		perror("wine: msgsnd");
+		perror("wine: winsock: msgsnd");
 		
 	kill(getppid(), SIGUSR1);
 }
@@ -1046,42 +1043,44 @@
 
 INT WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent)
 {
-	long event;
-	fd_set read_fds, write_fds, except_fds;
+    long event;
+    fd_set read_fds, write_fds, except_fds;
+    int errors = 0;
 
-	dprintf_winsock(stddeb, "WSA_AsyncSelect: socket %d, HWND "NPFMT", wMsg %d, event %ld\n", s, hWnd, wMsg, lEvent);
+    dprintf_winsock(stddeb, "WSA_AsyncSelect: socket %d, HWND "NPFMT", wMsg %d, event %ld\n", s, hWnd, wMsg, lEvent);
 
-	/* remove outstanding asyncselect() processes */
-	/* kill */
+    /* remove outstanding asyncselect() processes */
+    /* kill */
 
-	if (wMsg == 0 && lEvent == 0) 
-		return 0;
+    if (wMsg == 0 && lEvent == 0) 
+        return 0;
 
-	if (fork()) {
-		return 0;
-	} else {
-		while (1) {
-			FD_ZERO(&read_fds);
-			FD_ZERO(&write_fds);
-			FD_ZERO(&except_fds);
+    if (fork()) {
+        return 0;
+    } else {
+        while (1) {
+            FD_ZERO(&read_fds);
+            FD_ZERO(&write_fds);
+            FD_ZERO(&except_fds);
 
-			if (lEvent & FD_READ)
-				FD_SET(s, &read_fds);
-			if (lEvent & FD_WRITE)
-				FD_SET(s, &write_fds);
+            if (lEvent & FD_READ)
+                FD_SET(s, &read_fds);
+            if (lEvent & FD_WRITE)
+                FD_SET(s, &write_fds);
 
-			fcntl(s, F_SETFL, O_NONBLOCK);
-			select(s + 1, &read_fds, &write_fds, &except_fds, NULL);
+            fcntl(s, F_SETFL, O_NONBLOCK);
+            if (select(s + 1, &read_fds, &write_fds, &except_fds, NULL)<0) {
+                errors = wsaerrno();
+            }
 
-			event = 0;
-			if (FD_ISSET(s, &read_fds))
-				event |= FD_READ;
-			if (FD_ISSET(s, &write_fds))
-				event |= FD_WRITE;
-	/* FIXME: the first time through we get a winsock error of 2, why? */
-			send_message(hWnd, wMsg, (HANDLE)s, (wsaerrno() << 16) | event);
-		}
-	}
+            event = 0;
+            if (FD_ISSET(s, &read_fds))
+                event |= FD_READ;
+            if (FD_ISSET(s, &write_fds))
+                event |= FD_WRITE;
+            send_message(hWnd, wMsg, s, WSAMAKESELECTREPLY(event,errors));
+        }
+    }
 }
 
 INT WSAFDIsSet(INT fd, fd_set *set)
@@ -1183,7 +1182,7 @@
     /* ipc stuff */
 
     if ((wine_key = msgget(IPC_PRIVATE, 0600)) == -1)
-	perror("wine: msgget"); 
+	perror("wine: winsock: msgget"); 
 
     signal(SIGUSR1, recv_message);
 
@@ -1201,7 +1200,7 @@
 
 	if (wine_key)
 		if (msgctl(wine_key, IPC_RMID, NULL) == -1)
-			perror("wine: shmctl");
+			perror("wine: winsock: shmctl");
 
 	for (fd = 0; fd != FD_SETSIZE; fd++)
 		if (FD_ISSET(fd, &fd_in_use))
diff --git a/misc/xmalloc.c b/misc/xmalloc.c
index 24dcef5..58b9681 100644
--- a/misc/xmalloc.c
+++ b/misc/xmalloc.c
@@ -14,6 +14,7 @@
 */
 
 #include <stdio.h>
+#include <string.h>
 #include "xmalloc.h"
 
 void *
@@ -42,3 +43,15 @@
     }
     return res;
 }
+
+
+char *xstrdup( const char *str )
+{
+    char *res = strdup( str );
+    if (!res)
+    {
+        fprintf (stderr, "Virtual memory exhausted.\n");
+        exit (1);
+    }
+    return res;
+}
diff --git a/miscemu/cpu.c b/miscemu/cpu.c
index 436c35b..bde9e36 100644
--- a/miscemu/cpu.c
+++ b/miscemu/cpu.c
@@ -23,7 +23,7 @@
 	{
 	  char info[5], value[5];
 	  while (fscanf (f, " %4s%*s : %4s%*s", info, value) == 2)
-	    if (!strcasecmp (info, "cpu"))
+	    if (!lstrcmpi (info, "cpu"))
 	      {
 		if (isdigit (value[0]) && value[1] == '8'
 		    && value[2] == '6' && value[3] == 0)
diff --git a/miscemu/dpmi.c b/miscemu/dpmi.c
index 1ba8f1a..760be10 100644
--- a/miscemu/dpmi.c
+++ b/miscemu/dpmi.c
@@ -5,6 +5,7 @@
  */
 
 #include <stdio.h>
+#include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
 #include "windows.h"
@@ -240,6 +241,11 @@
     case 0x0601:  /* Unlock linear region */
         break;  /* Just ignore it */
 
+    case 0x0604:  /* Get page size */
+        BX_reg(&context) = 0;
+        CX_reg(&context) = 4096;
+	break;
+
     default:
         INT_BARF( &context, 0x31 );
         AX_reg(&context) = 0x8001;  /* unsupported function */
diff --git a/miscemu/instr.c b/miscemu/instr.c
index 8b795a9..14ac461 100644
--- a/miscemu/instr.c
+++ b/miscemu/instr.c
@@ -426,8 +426,7 @@
                           (long_addr ? ECX_reg(context) : CX_reg(context)) : 1;
 	      int opsize = (typ & 1) ? (long_op ? 4 : 2) : 1;
 	      int step = (EFL_reg(context) & 0x400) ? -opsize : +opsize;
-	      int seg = outp ? (segprefix >= 0 ? segprefix : DS_reg(context))
-                             : ES_reg(context);  /* FIXME: is this right? */
+	      int seg = outp ? DS_reg(context) : ES_reg(context);  /* FIXME: is this right? */
 
 	      if (outp)
 		/* FIXME: Check segment readable.  */
diff --git a/miscemu/int21.c b/miscemu/int21.c
index 143e04a..16b5f8f 100644
--- a/miscemu/int21.c
+++ b/miscemu/int21.c
@@ -16,6 +16,8 @@
 #include <utime.h>
 #include <ctype.h>
 #include "dos_fs.h"
+#include "drive.h"
+#include "file.h"
 #include "windows.h"
 #include "msdos.h"
 #include "registers.h"
@@ -23,6 +25,7 @@
 #include "task.h"
 #include "options.h"
 #include "miscemu.h"
+#include "xmalloc.h"
 #include "stddebug.h"
 #include "debug.h"
 #ifdef __svr4__
@@ -31,6 +34,10 @@
 #define LOCK_SH  1
 #define LOCK_NB  8
 #endif
+
+
+#define DOS_GET_DRIVE(reg) ((reg) ? (reg) - 1 : DRIVE_GetCurrentDrive())
+
 /* Define the drive parameter block, as used by int21/1F
  * and int21/32.  This table can be accessed through the
  * global 'dpb' pointer, which points into the local dos
@@ -78,7 +85,7 @@
 
 static int Error(int e, int class, int el)
 {
-  return DOS_Error(e,class,el);
+    return DOS_ERROR( e, class, SA_Abort, el );
 }
 
 
@@ -135,53 +142,48 @@
 
 static void GetFreeDiskSpace(struct sigcontext_struct *context)
 {
-	int drive;
-	long size,available;
+    long size,available;
+    int drive = DOS_GET_DRIVE( DL_reg(context) );
 
-	if (DL_reg(context) == 0) drive = DOS_GetDefaultDrive();
-	else drive = DL_reg(context) - 1;
+    if (!DRIVE_IsValid(drive))
+    {
+        DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk );
+        AX_reg(context) = 0xffff;
+        return;
+    }
 	
-	if (!DOS_ValidDrive(drive)) {
-		Error(InvalidDrive, EC_MediaError , EL_Disk);
-		AX_reg(context) = 0xffff;
-		return;
-	}
-	
-	if (!DOS_GetFreeSpace(drive, &size, &available)) {
-		Error(GeneralFailure, EC_MediaError , EL_Disk);
-		AX_reg(context) = 0xffff;
-		return;
-	}
+    if (!DOS_GetFreeSpace(drive, &size, &available)) {
+        DOS_ERROR( ER_GeneralFailure, EC_MediaError, SA_Abort, EL_Disk );
+        AX_reg(context) = 0xffff;
+        return;
+    }
 
-	AX_reg(context) = (drive < 2) ? 1 : 64;  /* 64 for hard-disks, 1 for diskettes */
-	CX_reg(context) = 512;
-
-	BX_reg(context) = (available / (CX_reg(context) * AX_reg(context)));
-	DX_reg(context) = (size / (CX_reg(context) * AX_reg(context)));
-	Error (0,0,0);
+    AX_reg(context) = (drive < 2) ? 1 : 64;  /* 64 for hard-disks, 1 for diskettes */
+    CX_reg(context) = 512;
+    BX_reg(context) = (available / (CX_reg(context) * AX_reg(context)));
+    DX_reg(context) = (size / (CX_reg(context) * AX_reg(context)));
+    Error (0,0,0);
 }
 
 static void GetDriveAllocInfo(struct sigcontext_struct *context)
 {
-        int drive;
-	long size, available;
+    long size, available;
+    int drive = DOS_GET_DRIVE( DL_reg(context) );
 	
-	if (DL_reg(context) == 0) drive = DOS_GetDefaultDrive();
-	else drive = DL_reg(context) - 1;
+    if (!DRIVE_IsValid(drive))
+    {
+        AX_reg(context) = 4;
+        CX_reg(context) = 512;
+        DX_reg(context) = 0;
+        DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk );
+        return;
+    }
 
-	if (!DOS_ValidDrive(drive))
+	if (!DOS_GetFreeSpace(drive, &size, &available))
         {
-		AX_reg(context) = 4;
-		CX_reg(context) = 512;
-		DX_reg(context) = 0;
-		Error (InvalidDrive, EC_MediaError, EL_Disk);
-		return;
-	}
-
-	if (!DOS_GetFreeSpace(drive, &size, &available)) {
-		Error(GeneralFailure, EC_MediaError , EL_Disk);
-		AX_reg(context) = 0xffff;
-		return;
+            DOS_ERROR( ER_GeneralFailure, EC_MediaError, SA_Abort, EL_Disk );
+            AX_reg(context) = 0xffff;
+            return;
 	}
 	
 	AX_reg(context) = (drive < 2) ? 1 : 64;  /* 64 for hard-disks, 1 for diskettes */
@@ -197,10 +199,10 @@
 
 static void GetDrivePB(struct sigcontext_struct *context, int drive)
 {
-        if(!DOS_ValidDrive(drive))
+        if(!DRIVE_IsValid(drive))
         {
-	        Error (InvalidDrive, EC_MediaError, EL_Disk);
-                AX_reg(context) = 0x00ff;
+            DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk );
+            AX_reg(context) = 0x00ff;
         }
         else
         {
@@ -237,116 +239,6 @@
         }
 }
 
-static void ReadFile(struct sigcontext_struct *context)
-{
-	char *ptr;
-	int size;
-
-	/* can't read from stdout / stderr */
-	if ((BX_reg(context) == 1) || (BX_reg(context) == 2)) {
-		Error (InvalidHandle, EL_Unknown, EC_Unknown);
-		AX_reg(context) = InvalidHandle;
-		SET_CFLAG(context);
-        	dprintf_int(stddeb, "int21: read (%d, void *, 0x%x) = EBADF\n",
-                            BX_reg(context), CX_reg(context));
-		return;
-	}
-
-	ptr = PTR_SEG_OFF_TO_LIN (DS_reg(context),DX_reg(context));
-	if (BX_reg(context) == 0) {
-		*ptr = EOF;
-		Error (0,0,0);
-		AX_reg(context) = 1;
-		RESET_CFLAG(context);
-        	dprintf_int(stddeb, "int21: read (%d, void *, 0x%x) = EOF\n",
-                            BX_reg(context), CX_reg(context));
-		return;
-	} else {
-		size = read(BX_reg(context), ptr, CX_reg(context));
-        	dprintf_int(stddeb,"int21: read(%d, %04x:%04x, 0x%x) = 0x%x\n",
-                            BX_reg(context), DS_reg(context), DX_reg(context),
-                            CX_reg(context), size );
-		if (size == -1) {
-			errno_to_doserr();
-			AX_reg(context) = ExtendedError;
-			SET_CFLAG(context);
-			return;
-		}		
-		Error (0,0,0);
-		AX_reg(context) = size;
-		RESET_CFLAG(context);
-	}
-}
-
-static void WriteFile(struct sigcontext_struct *context)
-{
-	char *ptr;
-	int x,size;
-	
-	ptr = PTR_SEG_OFF_TO_LIN (DS_reg(context),DX_reg(context));
-	
-	if (BX_reg(context) == 0) {
-		Error (InvalidHandle, EC_Unknown, EL_Unknown);
-		EAX_reg(context) = InvalidHandle;
-		SET_CFLAG(context);
-		return;
-	}
-
-	if (BX_reg(context) < 3) {
-		for (x = 0;x != CX_reg(context);x++) {
-			dprintf_int(stddeb, "%c", *ptr++);
-		}
-		fflush(stddeb);
-
-		Error (0,0,0);
-		AX_reg(context) = CX_reg(context);
-		RESET_CFLAG(context);
-	} else {
-		/* well, this function already handles everything we need */
-		size = _lwrite(BX_reg(context),ptr,CX_reg(context));
-		if (size == -1) { /* HFILE_ERROR == -1 */
-			errno_to_doserr();
-			AX_reg(context) = ExtendedError;
-			SET_CFLAG(context);
-			return;
-		}		
-		Error (0,0,0);
-		AX_reg(context) = size;
-		RESET_CFLAG(context);
-	}
-}
-
-static void SeekFile(struct sigcontext_struct *context)
-{
-	off_t status, fileoffset;
-	
-	switch (AL_reg(context))
-        {
-		case 1: fileoffset = SEEK_CUR;
-			break;
-		case 2: fileoffset = SEEK_END;
-			break;
-		default:
-		case 0: fileoffset = SEEK_SET;
-			break;
-	}
-        status = lseek(BX_reg(context), (CX_reg(context) << 16) + DX_reg(context), fileoffset);
-
-	dprintf_int (stddeb, "int21: seek (%d, 0x%x, %d) = 0x%lx\n",
-			BX_reg(context), (CX_reg(context) << 16) + DX_reg(context), AL_reg(context), status);
-
-	if (status == -1)
-        {
-		errno_to_doserr();
-		AX_reg(context) = ExtendedError;
-                SET_CFLAG(context);
-		return;
-	}		
-	Error (0,0,0);
-	AX_reg(context) = LOWORD(status);
-	DX_reg(context) = HIWORD(status);
-	RESET_CFLAG(context);
-}
 
 static void ioctlGetDeviceInfo(struct sigcontext_struct *context)
 {
@@ -357,6 +249,8 @@
         {
 		case 0:
 		case 1:
+                    DX_reg(context) = 2;  /* FIXME */
+                    break;
 		case 2:
 			DX_reg(context) = 0x80d0 | (1 << (BX_reg(context) != 0));
                         RESET_CFLAG(context);
@@ -387,17 +281,14 @@
 static void ioctlGenericBlkDevReq(struct sigcontext_struct *context)
 {
 	BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
-	int drive;
+	int drive = DOS_GET_DRIVE( BL_reg(context) );
 
-	if (BL_reg(context) == 0) drive = DOS_GetDefaultDrive();
-	else drive = BL_reg(context) - 1;
-
-	if (!DOS_ValidDrive(drive))
+	if (!DRIVE_IsValid(drive))
         {
-                Error( FileNotFound, EC_NotFound, EL_Disk );
-                AX_reg(context) = FileNotFound;
-		SET_CFLAG(context);
-		return;
+            DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
+            AX_reg(context) = DOS_ExtendedError;
+            SET_CFLAG(context);
+            return;
 	}
 
 	if (CH_reg(context) != 0x08)
@@ -459,68 +350,32 @@
 					/* Note hundredths of seconds */
 }
 
-static void GetExtendedErrorInfo(struct sigcontext_struct *context)
-{
-	AX_reg(context) = ExtendedError;
-	BX_reg(context) = (ErrorClass << 8) | Action;
-	CH_reg(context) = ErrorLocus;
-}
-
 static void CreateFile(struct sigcontext_struct *context)
 {
-    int handle;
-    handle = open(DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context),
-                                                          DX_reg(context))), 
-		  O_CREAT | O_TRUNC | O_RDWR, 0666 );
-    if (handle == -1) {
-	errno_to_doserr();
-	AX_reg(context) = ExtendedError;
+    AX_reg(context) = _lcreat( PTR_SEG_OFF_TO_LIN( DS_reg(context),
+                                          DX_reg(context) ), CX_reg(context) );
+    if (AX_reg(context) == (WORD)HFILE_ERROR)
+    {
+	AX_reg(context) = DOS_ExtendedError;
 	SET_CFLAG(context);
-	return;
     }
-    Error (0,0,0);
-    AX_reg(context) = handle;
-    RESET_CFLAG(context);
 }
 
+
 void OpenExistingFile(struct sigcontext_struct *context)
 {
+    AX_reg(context) = _lopen( PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)),
+                              AL_reg(context) );
+    if (AX_reg(context) == (WORD)HFILE_ERROR)
+    {
+        AX_reg(context) = DOS_ExtendedError;
+        SET_CFLAG(context);
+    }
+#if 0
 	int handle;
 	int mode;
 	int lock;
 	
-	switch (AX_reg(context) & 0x0007)
-	{
-	  case 0:
-	    mode = O_RDONLY;
-	    break;
-	    
-	  case 1:
-	    mode = O_WRONLY;
-	    break;
-
-	  default:
-	    mode = O_RDWR;
-	    break;
-	}
-
-	if ((handle = open(DOS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context))),
-                           mode)) == -1)
-        {
-            if( Options.allowReadOnly )
-                handle = open( DOS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context))),
-                               O_RDONLY );
-            if( handle == -1 )
-            {
-		dprintf_int (stddeb, "int21: open (%s, %d) = -1\n",
-			DOS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context))), mode);
-                errno_to_doserr();
-                AX_reg(context) = ExtendedError;
-                SET_CFLAG(context);
-                return;
-            }
-	}		
-
 	dprintf_int (stddeb, "int21: open (%s, %d) = %d\n",
 		DOS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),
                                              DX_reg(context))), mode, handle);
@@ -585,28 +440,22 @@
 	Error (0,0,0);
 	AX_reg(context) = handle;
 	RESET_CFLAG(context);
+#endif
 }
 
 static void CloseFile(struct sigcontext_struct *context)
 {
-	dprintf_int (stddeb, "int21: close (%d)\n", BX_reg(context));
-
-	if (_lclose( BX_reg(context) ))
-        {
-		errno_to_doserr();
-		AX_reg(context) = ExtendedError;
-		SET_CFLAG(context);
-		return;
-	}
-	Error (0,0,0);
-	AX_reg(context) = NoError;
-	RESET_CFLAG(context);
+    if ((AX_reg(context) = _lclose( BX_reg(context) )) != 0)
+    {
+        AX_reg(context) = DOS_ExtendedError;
+        SET_CFLAG(context);
+    }
 }
 
 void ExtendedOpenCreateFile(struct sigcontext_struct *context)
 {
   dprintf_int(stddeb, "int21: extended open/create: file= %s \n",
-	      DOS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context))));
+	      DOSFS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context)),FALSE));
   /* Shuffle arguments to call OpenExistingFile */
   AL_reg(context) = BL_reg(context);
   DX_reg(context) = SI_reg(context);
@@ -615,7 +464,7 @@
   if ((EFL_reg(context) & 0x0001)==0) 
     { /* It exists */
       dprintf_int(stddeb, "int21: extended open/create %s exists \n",
-		  DOS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context))));
+		  DOSFS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context)),TRUE));
       /* Now decide what do do */
       if ((DL_reg(context) & 0x0007)== 0)
 	{
@@ -668,7 +517,7 @@
   else /* file does not exist */
     {
      dprintf_int(stddeb, "int21: extended open/create %s dosen't exists \n",
-		  DOS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context))));
+		  DOSFS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context)),FALSE));
       if ((DL_reg(context) & 0x00F0)== 0) {
 	CX_reg(context) = 0;
 	SET_CFLAG(context);
@@ -689,318 +538,222 @@
       return;
     }
 }
-static void RenameFile(struct sigcontext_struct *context)
-{
-	char *newname, *oldname;
 
-        /* FIXME: should not rename over an existing file */
-	dprintf_int(stddeb,"int21: renaming %s to %s\n",
-                  (char *)PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)),
-                  (char *)PTR_SEG_OFF_TO_LIN(ES_reg(context),DI_reg(context)));
+
+static int INT21_RenameFile(struct sigcontext_struct *context)
+{
+    const char *newname, *oldname;
+    char *buffer;
+
+    /* FIXME: should not rename over an existing file */
+    dprintf_int(stddeb,"int21: renaming %s to %s\n",
+                (char *)PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)),
+                (char *)PTR_SEG_OFF_TO_LIN(ES_reg(context),DI_reg(context)));
 	
-	oldname = DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context),
-                                                          DX_reg(context)) );
-	newname = DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(ES_reg(context),
-                                                          DI_reg(context)) );
-
-	rename( oldname, newname);
-	RESET_CFLAG(context);
+    oldname = DOSFS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context),
+                                                DX_reg(context)), TRUE );
+    if (!oldname) return 0;
+    buffer = xstrdup( oldname );
+    newname = DOSFS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(ES_reg(context),
+                                                   DI_reg(context)), FALSE );
+    if (!newname)
+    {
+        free( buffer );
+        return 0;
+    }
+    
+    if (rename( buffer, newname) == -1)
+    {
+        FILE_SetDosError();
+        free( buffer );
+        return 0;
+    }
+    free( buffer );
+    return 1;
 }
 
 
-static void MakeDir(struct sigcontext_struct *context)
+static void INT21_ChangeDir(struct sigcontext_struct *context)
 {
-	char *dirname;
+    int drive;
+    char *dirname = PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context));
 
-	dprintf_int(stddeb,"int21: makedir %s\n", (char *)PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)) );
+    dprintf_int(stddeb,"int21: changedir %s\n", dirname);
+    if (dirname[1] == ':')
+    {
+        drive = toupper(dirname[0]) - 'A';
+        dirname += 2;
+    }
+    else drive = DRIVE_GetCurrentDrive();
+    if (!DRIVE_Chdir( drive, dirname ))
+    {
+        AX_reg(context) = DOS_ExtendedError;
+        SET_CFLAG(context);
+    }
+}
+
+
+static int INT21_FindFirst(struct sigcontext_struct *context)
+{
+    const char *path, *unixPath, *mask;
+    char *p;
+    FINDFILE_DTA *dta = (FINDFILE_DTA *)GetCurrentDTA();
+
+    path = (const char *)PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
+    dta->unixPath = NULL;
+    if (!(unixPath = DOSFS_GetUnixFileName( path, FALSE )))
+    {
+        AX_reg(context) = DOS_ExtendedError;
+        SET_CFLAG(context);
+        return 0;
+    }
+    dta->unixPath = xstrdup( unixPath );
+    p = strrchr( dta->unixPath, '/' );
+    *p = '\0';
+    if (!(mask = DOSFS_ToDosFCBFormat( p + 1 )))
+    {
+        free( dta->unixPath );
+        dta->unixPath = NULL;
+        DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
+        AX_reg(context) = ER_FileNotFound;
+        SET_CFLAG(context);
+        return 0;
+    }
+    memcpy( dta->mask, mask, sizeof(dta->mask) );
+    dta->drive = (path[1] == ':') ? toupper(path[0]) - 'A'
+                                  : DRIVE_GetCurrentDrive();
+    dta->count = 0;
+    dta->search_attr = CL_reg(context);
+    return 1;
+}
+
+
+static int INT21_FindNext(struct sigcontext_struct *context)
+{
+    FINDFILE_DTA *dta = (FINDFILE_DTA *)GetCurrentDTA();
+    DOS_DIRENT entry;
+    int count;
+
+    if (!dta->unixPath) return 0;
+    if (!(count = DOSFS_FindNext( dta->unixPath, dta->mask, dta->drive,
+                                  dta->search_attr, dta->count, &entry )))
+    {
+        free( dta->unixPath );
+        dta->unixPath = NULL;
+        return 0;
+    }
+    if ((int)dta->count + count > 0xffff)
+    {
+        fprintf( stderr, "Too many directory entries in %s\n", dta->unixPath );
+        free( dta->unixPath );
+        dta->unixPath = NULL;
+        return 0;
+    }
+    dta->count += count;
+    dta->fileattr = entry.attr;
+    dta->filetime = entry.time;
+    dta->filedate = entry.date;
+    dta->filesize = entry.size;
+    strcpy( dta->filename, DOSFS_ToDosDTAFormat( entry.name ) );
+    return 1;
+}
+
+
+static int INT21_SetFileDateTime(struct sigcontext_struct *context)
+{
+    fprintf( stderr, "INT21_SetFileDateTime: not implemented yet.\n" );
+    return 1;
+#if 0
+    char *filename;
+    struct utimbuf filetime;
 	
-	if ((dirname = DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context),
-                                                               DX_reg(context)) ))== NULL) {
-            Error( CanNotMakeDir, EC_AccessDenied, EL_Disk );
-            AX_reg(context) = CanNotMakeDir;
-            SET_CFLAG(context);
-            return;
-	}
+    /* FIXME: Argument isn't the name of the file in DS:DX,
+       but the file handle in BX */
+    filename = DOSFS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context),
+                                                         DX_reg(context)),TRUE );
 
-	if ((mkdir(dirname, S_IRWXU | S_IRWXG | S_IRWXO) == -1)  && errno!=EEXIST) {
-            Error( CanNotMakeDir, EC_AccessDenied, EL_Disk );
-            AX_reg(context) = CanNotMakeDir;
-            SET_CFLAG(context);
-            return;
-	}
-	RESET_CFLAG(context);
+    filetime.actime = 0L;
+    filetime.modtime = filetime.actime;
+    
+    utime(filename, &filetime);
+    RESET_CFLAG(context);
+#endif
 }
 
-static void ChangeDir(struct sigcontext_struct *context)
+
+static int INT21_CreateTempFile(struct sigcontext_struct *context)
 {
-	int drive;
-	char *dirname = PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context));
-	drive = DOS_GetDefaultDrive();
-	dprintf_int(stddeb,"int21: changedir %s\n", dirname);
-	if (dirname != NULL && dirname[1] == ':') {
-		drive = toupper(dirname[0]) - 'A';
-		dirname += 2;
-		}
-	if (!DOS_ChangeDir(drive, dirname))
-	{
-		SET_CFLAG(context);
-		AX_reg(context)=0x03;
-	}
-}
+    static int counter = 0;
+    char *name = PTR_SEG_OFF_TO_LIN( DS_reg(context), DX_reg(context) );
+    char *p = name + strlen(name);
 
-static void RemoveDir(struct sigcontext_struct *context)
-{
-	char *dirname;
-
-	dprintf_int(stddeb,"int21: removedir %s\n", (char *)PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)) );
-
-	if ((dirname = DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)) ))== NULL) {
-            Error( PathNotFound, EC_NotFound, EL_Disk );
-            AX_reg(context) = PathNotFound;
-            SET_CFLAG(context);
-            return;
-	}
-
-/*
-	if (strcmp(unixname,DosDrives[drive].CurrentDirectory)) {
-		AL = CanNotRemoveCwd;
-		SET_CFLAG(context);
-	}
-*/	
-	if (rmdir(dirname) == -1) {
-            Error( AccessDenied, EC_AccessDenied, EL_Disk );
-            AX_reg(context) = AccessDenied;
-            SET_CFLAG(context);
-            return;
-	} 
-	RESET_CFLAG(context);
-}
-
-static void FindNext(struct sigcontext_struct *context)
-{
-	struct dosdirent *dp;
-        struct tm *t;
-	BYTE *dta = GetCurrentDTA();
-        
-        memcpy(&dp, dta+0x11, sizeof(dp));
-
-        dprintf_int(stddeb, "int21: FindNext, dta %p, dp %p\n", dta, dp);
-	do {
-		if ((dp = DOS_readdir(dp)) == NULL) {
-			Error(NoMoreFiles, EC_MediaError , EL_Disk);
-			AX_reg(context) = NoMoreFiles;
-			SET_CFLAG(context);
-			return;
-		}
-	} /* while (*(dta + 0x0c) != dp->attribute);*/
-        while ( ( dp->search_attribute & dp->attribute) != dp->attribute);
-	
-  	*(dta + 0x15) = dp->attribute;
-        setword(&dta[0x0d], dp->entnum);
-
-        t = localtime(&(dp->filetime));
-	setword(&dta[0x16], (t->tm_hour << 11) + (t->tm_min << 5) +
-                (t->tm_sec / 2)); /* time */
-	setword(&dta[0x18], ((t->tm_year - 80) << 9) + (t->tm_mon << 5) +
-                (t->tm_mday)); /* date */
-	setdword(&dta[0x1a], dp->filesize);
-	strncpy(dta + 0x1e, dp->filename, 12);
-        *(dta + 0x1e + 13) = 0;
-        AnsiUpper(dta+0x1e);
-
-	AX_reg(context) = 0;
-	RESET_CFLAG(context);
-
-        dprintf_int(stddeb, "int21: FindNext -- (%s) index=%d size=%ld\n", dp->filename, dp->entnum, dp->filesize);
-}
-
-static void FindFirst(struct sigcontext_struct *context)
-{
-	BYTE drive, *path = PTR_SEG_OFF_TO_LIN(DS_reg(context),
-                                               DX_reg(context));
-	struct dosdirent *dp;
-
-	BYTE *dta = GetCurrentDTA();
-
-        dprintf_int(stddeb, "int21: FindFirst path = %s\n", path);
-
-	if ((*path)&&(path[1] == ':')) {
-		drive = (islower(*path) ? toupper(*path) : *path) - 'A';
-
-		if (!DOS_ValidDrive(drive)) {
-			Error(InvalidDrive, EC_MediaError , EL_Disk);
-			AX_reg(context) = InvalidDrive;
-			SET_CFLAG(context);
-			return;
-		}
-	} else
-		drive = DOS_GetDefaultDrive();
-
-	*dta = drive;
-	memset(dta + 1 , '?', 11);
-	*(dta + 0x0c) = ECX_reg(context) & (FA_LABEL | FA_DIREC);
-
-	if ((dp = DOS_opendir(path)) == NULL) {
-		Error(PathNotFound, EC_MediaError, EL_Disk);
-		AX_reg(context) = FileNotFound;
-		SET_CFLAG(context);
-		return;
-	}
-
-	dp->search_attribute = ECX_reg(context) & (FA_LABEL | FA_DIREC);
-	memcpy(dta + 0x11, &dp, sizeof(dp));
-	FindNext(context);
-
-}
-
-static void GetFileDateTime(struct sigcontext_struct *context)
-{
-	struct stat filestat;
-	struct tm *now;
-
-        fstat( BX_reg(context), &filestat );
-	now = localtime (&filestat.st_mtime);
-	
-	CX_reg(context) = ((now->tm_hour * 0x2000) + (now->tm_min * 0x20) + now->tm_sec/2);
-	DX_reg(context) = (((now->tm_year + 1900 - 1980) * 0x200) +
-              (now->tm_mon * 0x20) + now->tm_mday);
-
-	RESET_CFLAG(context);
-}
-
-static void SetFileDateTime(struct sigcontext_struct *context)
-{
-	char *filename;
-	struct utimbuf filetime;
-	
-        /* FIXME: Argument isn't the name of the file in DS:DX,
-           but the file handle in BX */
-	filename = DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context),
-                                                           DX_reg(context)) );
-
-	filetime.actime = 0L;
-	filetime.modtime = filetime.actime;
-
-	utime(filename, &filetime);
-	RESET_CFLAG(context);
-}
-
-static void CreateTempFile(struct sigcontext_struct *context)
-{
-	char temp[256];
-	int handle;
-	static int counter = 0;
-
-	sprintf(temp,"%s\\win%d.%03d",TempDirectory,(int) getpid(), counter);
+    for (;;)
+    {
+        sprintf( p, "wine%04x.%03d", (int)getpid(), counter );
         counter = (counter + 1) % 1000;
 
-	dprintf_int(stddeb,"CreateTempFile %s\n",temp);
-
-	handle = open(DOS_GetUnixFileName(temp), O_CREAT | O_TRUNC | O_RDWR, 0666);
-
-	if (handle == -1) {
-            Error( WriteProtected, EC_AccessDenied, EL_Disk );
-            AX_reg(context) = WriteProtected;
-            SET_CFLAG(context);
-            return;
-	}
-
-	strcpy(PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)), temp);
-	
-	AX_reg(context) = handle;
-	RESET_CFLAG(context);
-}
-
-static void CreateNewFile(struct sigcontext_struct *context)
-{
-	int handle;
-	
-	if ((handle = open(DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)) ),
-                           O_CREAT | O_EXCL | O_RDWR, 0666)) == -1)
+        if ((AX_reg(context) = _lcreat_uniq( name, 0 )) != (WORD)HFILE_ERROR)
         {
-            Error( WriteProtected, EC_AccessDenied, EL_Disk );
-            AX_reg(context) = WriteProtected;
-            SET_CFLAG(context);
-            return;
-	}
-
-	AX_reg(context) = handle;
-	RESET_CFLAG(context);
+            dprintf_int( stddeb, "INT21_CreateTempFile: created %s\n", name );
+            return 1;
+        }
+        if (DOS_ExtendedError != ER_FileExists) return 0;
+    }
 }
 
-static void GetCurrentDirectory(struct sigcontext_struct *context)
+
+static int INT21_GetCurrentDirectory(struct sigcontext_struct *context)
 {
-	int drive;
+    int drive = DOS_GET_DRIVE( DL_reg(context) );
+    char *ptr = (char *)PTR_SEG_OFF_TO_LIN( DS_reg(context), SI_reg(context) );
 
-	if (DL_reg(context) == 0) drive = DOS_GetDefaultDrive();
-	else drive = DL_reg(context) - 1;
+    if (!DRIVE_IsValid(drive))
+    {
+        DOS_ERROR( ER_InvalidDrive, EC_NotFound, SA_Abort, EL_Disk );
+        return 0;
+    }
 
-	if (!DOS_ValidDrive(drive))
-        {
-            Error( InvalidDrive, EC_NotFound, EL_Disk );
-            AX_reg(context) = InvalidDrive;
-            SET_CFLAG(context);
-            return;
-	}
-
-	strcpy(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context)),
-               DOS_GetCurrentDir(drive) );
-	RESET_CFLAG(context);
+    lstrcpyn( ptr, DRIVE_GetDosCwd(drive), 64 );
+    if (!ptr[0]) strcpy( ptr, "\\" );
+    return 1;
 }
 
-static void GetDiskSerialNumber(struct sigcontext_struct *context)
+
+static int INT21_GetDiskSerialNumber(struct sigcontext_struct *context)
 {
-	int drive;
-	BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
-	DWORD serialnumber;
+    BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
+    int drive = DOS_GET_DRIVE( BL_reg(context) );
 	
-	if (BL_reg(context) == 0) drive = DOS_GetDefaultDrive();
-	else drive = BL_reg(context) - 1;
-
-	if (!DOS_ValidDrive(drive))
-        {
-            Error( InvalidDrive, EC_NotFound, EL_Disk );
-            AX_reg(context) = InvalidDrive;
-            SET_CFLAG(context);
-            return;
-	}
-
-	DOS_GetSerialNumber(drive, &serialnumber);
-
-	setword(dataptr, 0);
-	setdword(&dataptr[2], serialnumber);
-	strncpy(dataptr + 6, DOS_GetVolumeLabel(drive), 8);
-	strncpy(dataptr + 0x11, "FAT16   ", 8);
-	
-	AX_reg(context) = 0;
-	RESET_CFLAG(context);
+    if (!DRIVE_IsValid(drive))
+    {
+        DOS_ERROR( ER_InvalidDrive, EC_NotFound, SA_Abort, EL_Disk );
+        return 0;
+    }
+    
+    *(WORD *)dataptr = 0;
+    *(DWORD *)(dataptr + 2) = DRIVE_GetSerialNumber( drive );
+    memcpy( dataptr + 6, DRIVE_GetLabel( drive ), 11 );
+    strncpy(dataptr + 0x11, "FAT16   ", 8);
+    return 1;
 }
 
-static void SetDiskSerialNumber(struct sigcontext_struct *context)
+
+static int INT21_SetDiskSerialNumber(struct sigcontext_struct *context)
 {
-	int drive;
-	BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
-	DWORD serialnumber;
+    BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
+    int drive = DOS_GET_DRIVE( BL_reg(context) );
 
-	if (BL_reg(context) == 0) drive = DOS_GetDefaultDrive();
-	else drive = BL_reg(context) - 1;
+    if (!DRIVE_IsValid(drive))
+    {
+        DOS_ERROR( ER_InvalidDrive, EC_NotFound, SA_Abort, EL_Disk );
+        return 0;
+    }
 
-	if (!DOS_ValidDrive(drive))
-        {
-            Error( InvalidDrive, EC_NotFound, EL_Disk );
-            AX_reg(context) = InvalidDrive;
-            SET_CFLAG(context);
-            return;
-	}
-
-	serialnumber = dataptr[1] + (dataptr[2] << 8) + (dataptr[3] << 16) + 
-			(dataptr[4] << 24);
-
-	DOS_SetSerialNumber(drive, serialnumber);
-	AX_reg(context) = 1;
-	RESET_CFLAG(context);
+    DRIVE_SetSerialNumber( drive, *(DWORD *)(dataptr + 2) );
+    return 1;
 }
 
+
 static void DumpFCB(BYTE *fcb)
 {
 	int x, y;
@@ -1044,15 +797,15 @@
 	if (standard_fcb->drive)
 	  {
 	    drive = standard_fcb->drive - 1;
-	    if (!DOS_ValidDrive(drive))
+	    if (!DRIVE_IsValid(drive))
 	      {
-		Error (InvalidDrive, EC_MediaError, EL_Disk);
-		AX_reg(context) = 0xff;
-		return;
+                  DOS_ERROR(ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk);
+                  AX_reg(context) = 0xff;
+                  return;
 	      }
 	  }
 	else
-	  drive = DOS_GetDefaultDrive();
+	  drive = DRIVE_GetCurrentDrive();
 
 	output_fcb->drive = drive;
 
@@ -1062,19 +815,17 @@
 	      {
 		*(dta+6) = FA_LABEL;
 		memset(&output_fcb->name, ' ', 11);
-		if (DOS_GetVolumeLabel(drive) != NULL) 
-		  {
-		    strncpy(output_fcb->name, DOS_GetVolumeLabel(drive), 11);
-		    AX_reg(context) = 0x00;
-		    return;
-		  }
+                memcpy(output_fcb->name, DRIVE_GetLabel(drive), 11);
+                AX_reg(context) = 0x00;
+                return;
 	      }
 	  }
 
 	strncpy(output_fcb->name, standard_fcb->name, 11);
 	if (*fcb == 0xff)
-	  *(dta+6) = ( *(fcb+6) & (!FA_DIREC));
+	  *(dta+6) = ( *(fcb+6) & (!FA_DIRECTORY));
 
+#if 0
 	sprintf(path,"%c:*.*",drive+'A');
 	if ((output_fcb->directory = DOS_opendir(path))==NULL)
 	  {
@@ -1082,25 +833,23 @@
 	    AX_reg(context) = 0xff;
 	    return;
 	  }
-	
+#endif	
 }
 
 
 static void DeleteFileFCB(struct sigcontext_struct *context)
 {
+    fprintf( stderr, "DeleteFileFCB: not implemented yet\n" );
+#if 0
 	BYTE *fcb = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
-	int drive;
 	struct dosdirent *dp;
 	char temp[256], *ptr;
+        int drive = DOS_GET_DRIVE( *fcb );
 
 	DumpFCB( fcb );
 
-	if (*fcb)
-		drive = *fcb - 1;
-	else
-		drive = DOS_GetDefaultDrive();
-
-	strcpy(temp, DOS_GetCurrentDir(drive));
+        temp[0] = '\\';
+	strcpy(temp+1, DRIVE_GetDosCwd(drive));
 	strcat(temp, "\\");
 	strncat(temp, fcb + 1, 8);
 	ChopOffWhiteSpace(temp);
@@ -1113,7 +862,8 @@
 		return;
 	}
 
-	strcpy(temp, DOS_GetCurrentDir(drive) );
+        temp[0] = '\\';
+	strcpy(temp+1, DRIVE_GetDosCwd(drive) );
 	strcat(temp, "\\");
 	
 	ptr = temp + strlen(temp);
@@ -1126,23 +876,22 @@
 	}
 	DOS_closedir(dp);
 	AX_reg(context) = 0;
+#endif
 }
 
 static void RenameFileFCB(struct sigcontext_struct *context)
 {
+    fprintf( stderr, "RenameFileFCB: not implemented yet\n" );
+#if 0
 	BYTE *fcb = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
-	int drive;
 	struct dosdirent *dp;
 	char temp[256], oldname[256], newname[256], *oldnameptr, *newnameptr;
+        int drive = DOS_GET_DRIVE( *fcb );
 
 	DumpFCB( fcb );
 
-	if (*fcb)
-		drive = *fcb - 1;
-	else
-		drive = DOS_GetDefaultDrive();
-
-	strcpy(temp, DOS_GetCurrentDir(drive));
+        temp[0] = '\\';
+	strcpy(temp+1, DRIVE_GetDosCwd(drive) );
 	strcat(temp, "\\");
 	strncat(temp, fcb + 1, 8);
 	ChopOffWhiteSpace(temp);
@@ -1155,12 +904,11 @@
 		return;
 	}
 
-	strcpy(oldname, DOS_GetCurrentDir(drive) );
+        oldname[0] = '\\';
+	strcpy(oldname+1, DRIVE_GetDosCwd(drive) );
 	strcat(oldname, "\\");
+        strcpy( newname, oldname );
 	oldnameptr = oldname + strlen(oldname);
-
-	strcpy(newname, DOS_GetCurrentDir(drive) );
-	strcat(newname, "\\");
 	newnameptr = newname + strlen(newname);
 	
 	while (DOS_readdir(dp) != NULL)
@@ -1172,12 +920,14 @@
 	}
 	DOS_closedir(dp);
 	AX_reg(context) = 0;
+#endif
 }
 
 
 
 static void fLock (struct sigcontext_struct * context)
 {
+#if 0
     struct flock f;
     int result,retries=sharing_retries;
 
@@ -1217,43 +967,26 @@
 
       if(result)  
       {
-         errno_to_doserr();
-         AX_reg(context) = ExtendedError;
-         SET_CFLAG(context);
-         return;
+          FILE_SetDosError();
+          AX_reg(context) = DOS_ExtendedError;
+          SET_CFLAG(context);
+          return;
       }
-
-       Error (0,0,0);
-       RESET_CFLAG(context);
+#endif
 } 
 
 
-static void GetFileAttribute (struct sigcontext_struct * context)
+static int INT21_GetFileAttribute (struct sigcontext_struct * context)
 {
-  char *filename = PTR_SEG_OFF_TO_LIN (DS_reg(context),DX_reg(context));
-  struct stat s;
-  int res;
+    const char *unixName;
 
-  res = stat(DOS_GetUnixFileName(filename), &s);
-  if (res==-1)
-  {
-    errno_to_doserr();
-    AX_reg(context) = ExtendedError;
-    SET_CFLAG(context);
-    return;
-  }
-  
-  CX_reg(context) = 0;
-  if (S_ISDIR(s.st_mode))
-    CX_reg(context) |= 0x10;
-  if ((S_IWRITE & s.st_mode) != S_IWRITE)
-    CX_reg(context) |= 0x01;
-
-  dprintf_int (stddeb, "int21: GetFileAttributes (%s) = 0x%x\n",
-		filename, CX_reg(context) );
-
-  RESET_CFLAG(context);
-  Error (0,0,0); 
+    unixName = DOSFS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)), TRUE );
+    if (!unixName) return 0;
+    if (!FILE_Stat( unixName, &CL_reg(context), NULL, NULL, NULL )) return 0;
+    CH_reg(context) = 0;
+    dprintf_int( stddeb, "INT21_GetFileAttributes(%s) = 0x%x\n",
+                 unixName, CX_reg(context) );
+    return 1;
 }
 
 
@@ -1264,176 +997,173 @@
  */
 void DOS3Call( struct sigcontext_struct context )
 {
-    int drive;
+    dprintf_int( stddeb, "int21: AX=%04x BX=%04x CX=%04x DX=%04x "
+                 "SI=%04x DI=%04x DS=%04x ES=%04x EFL=%08lx\n",
+                 AX_reg(&context), BX_reg(&context), CX_reg(&context),
+                 DX_reg(&context), SI_reg(&context), DI_reg(&context),
+                 DS_reg(&context), ES_reg(&context), EFL_reg(&context));
 
-    if (AH_reg(&context) == 0x59) 
+    if (AH_reg(&context) == 0x59)  /* Get extended error info */
     {
-	GetExtendedErrorInfo(&context);
-	return;
-    } 
-    else 
+        AX_reg(&context) = DOS_ExtendedError;
+        BH_reg(&context) = DOS_ErrorClass;
+        BL_reg(&context) = DOS_ErrorAction;
+        CH_reg(&context) = DOS_ErrorLocus;
+        return;
+    }
+
+    DOS_ERROR( 0, 0, 0, 0 );
+    RESET_CFLAG(&context);  /* Not sure if this is a good idea */
+
+    switch(AH_reg(&context)) 
     {
-	Error (0,0,0);
-	switch(AH_reg(&context)) 
-	{
-	  case 0x00: /* TERMINATE PROGRAM */
-            TASK_KillCurrentTask( 0 );
-            break;
+    case 0x00: /* TERMINATE PROGRAM */
+        TASK_KillCurrentTask( 0 );
+        break;
 
-	  case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
-	  case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
-	  case 0x03: /* READ CHARACTER FROM STDAUX  */
-	  case 0x04: /* WRITE CHARACTER TO STDAUX */
-	  case 0x05: /* WRITE CHARACTER TO PRINTER */
-	  case 0x06: /* DIRECT CONSOLE IN/OUTPUT */
-	  case 0x07: /* DIRECT CHARACTER INPUT, WITHOUT ECHO */
-	  case 0x08: /* CHARACTER INPUT WITHOUT ECHO */
-	  case 0x09: /* WRITE STRING TO STANDARD OUTPUT */
-	  case 0x0a: /* BUFFERED INPUT */
-	  case 0x0b: /* GET STDIN STATUS */
-	  case 0x0c: /* FLUSH BUFFER AND READ STANDARD INPUT */
-	  case 0x0f: /* OPEN FILE USING FCB */
-	  case 0x10: /* CLOSE FILE USING FCB */
-	  case 0x12: /* FIND NEXT MATCHING FILE USING FCB */
-	  case 0x14: /* SEQUENTIAL READ FROM FCB FILE */		
-	  case 0x15: /* SEQUENTIAL WRITE TO FCB FILE */
-	  case 0x16: /* CREATE OR TRUNCATE FILE USING FCB */
-	  case 0x21: /* READ RANDOM RECORD FROM FCB FILE */
-	  case 0x22: /* WRITE RANDOM RECORD TO FCB FILE */
-	  case 0x23: /* GET FILE SIZE FOR FCB */
-	  case 0x24: /* SET RANDOM RECORD NUMBER FOR FCB */
-	  case 0x26: /* CREATE NEW PROGRAM SEGMENT PREFIX */
-	  case 0x27: /* RANDOM BLOCK READ FROM FCB FILE */
-	  case 0x28: /* RANDOM BLOCK WRITE TO FCB FILE */
-	  case 0x29: /* PARSE FILENAME INTO FCB */
-	  case 0x2e: /* SET VERIFY FLAG */
-            INT_BARF( &context, 0x21 );
-	    break;
+    case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
+    case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
+    case 0x03: /* READ CHARACTER FROM STDAUX  */
+    case 0x04: /* WRITE CHARACTER TO STDAUX */
+    case 0x05: /* WRITE CHARACTER TO PRINTER */
+    case 0x06: /* DIRECT CONSOLE IN/OUTPUT */
+    case 0x07: /* DIRECT CHARACTER INPUT, WITHOUT ECHO */
+    case 0x08: /* CHARACTER INPUT WITHOUT ECHO */
+    case 0x09: /* WRITE STRING TO STANDARD OUTPUT */
+    case 0x0a: /* BUFFERED INPUT */
+    case 0x0b: /* GET STDIN STATUS */
+    case 0x0c: /* FLUSH BUFFER AND READ STANDARD INPUT */
+    case 0x0f: /* OPEN FILE USING FCB */
+    case 0x10: /* CLOSE FILE USING FCB */
+    case 0x12: /* FIND NEXT MATCHING FILE USING FCB */
+    case 0x14: /* SEQUENTIAL READ FROM FCB FILE */		
+    case 0x15: /* SEQUENTIAL WRITE TO FCB FILE */
+    case 0x16: /* CREATE OR TRUNCATE FILE USING FCB */
+    case 0x21: /* READ RANDOM RECORD FROM FCB FILE */
+    case 0x22: /* WRITE RANDOM RECORD TO FCB FILE */
+    case 0x23: /* GET FILE SIZE FOR FCB */
+    case 0x24: /* SET RANDOM RECORD NUMBER FOR FCB */
+    case 0x26: /* CREATE NEW PROGRAM SEGMENT PREFIX */
+    case 0x27: /* RANDOM BLOCK READ FROM FCB FILE */
+    case 0x28: /* RANDOM BLOCK WRITE TO FCB FILE */
+    case 0x29: /* PARSE FILENAME INTO FCB */
+    case 0x2e: /* SET VERIFY FLAG */
+    case 0x37: /* "SWITCHAR" - GET SWITCH CHARACTER
+                  "SWITCHAR" - SET SWITCH CHARACTER
+                  "AVAILDEV" - SPECIFY \DEV\ PREFIX USE */
+    case 0x54: /* GET VERIFY FLAG */
+        INT_BARF( &context, 0x21 );
+        break;
 
-	  case 0x37: /* "SWITCHAR" - GET SWITCH CHARACTER
-			"SWITCHAR" - SET SWITCH CHARACTER
-			"AVAILDEV" - SPECIFY \DEV\ PREFIX USE */
-	  case 0x54: /* GET VERIFY FLAG */
-            INT_BARF( &context, 0x21 );
-	    break;
-
-	  case 0x18: /* NULL FUNCTIONS FOR CP/M COMPATIBILITY */
-	  case 0x1d:
-	  case 0x1e:
-	  case 0x20:
-	  case 0x6b: /* NULL FUNCTION */
-            AL_reg(&context) = 0;
-	    break;
+    case 0x18: /* NULL FUNCTIONS FOR CP/M COMPATIBILITY */
+    case 0x1d:
+    case 0x1e:
+    case 0x20:
+    case 0x6b: /* NULL FUNCTION */
+        AL_reg(&context) = 0;
+        break;
 	
-	  case 0x5c: /* "FLOCK" - RECORD LOCKING */
-	    fLock(&context);
-	    break;
+    case 0x5c: /* "FLOCK" - RECORD LOCKING */
+        fLock(&context);
+        break;
 
-	  case 0x0d: /* DISK BUFFER FLUSH */
-            RESET_CFLAG(&context); /* dos 6+ only */
-            break;
+    case 0x0d: /* DISK BUFFER FLUSH */
+        RESET_CFLAG(&context); /* dos 6+ only */
+        break;
 
-	  case 0x0e: /* SELECT DEFAULT DRIVE */
-		if (!DOS_ValidDrive(DL_reg(&context)))
-                    Error (InvalidDrive, EC_MediaError, EL_Disk);
-		else
-                {
-                    DOS_SetDefaultDrive(DL_reg(&context));
-                    Error(0,0,0);
-		}
-                AL_reg(&context) = MAX_DOS_DRIVES;
-		break;
+    case 0x0e: /* SELECT DEFAULT DRIVE */
+        DRIVE_SetCurrentDrive( DL_reg(&context) );
+        AL_reg(&context) = MAX_DOS_DRIVES;
+        break;
 
-	  case 0x11: /* FIND FIRST MATCHING FILE USING FCB */
-            FindFirstFCB(&context);
-            break;
+    case 0x11: /* FIND FIRST MATCHING FILE USING FCB */
+        FindFirstFCB(&context);
+        break;
 
-	  case 0x13: /* DELETE FILE USING FCB */
-            DeleteFileFCB(&context);
-            break;
+    case 0x13: /* DELETE FILE USING FCB */
+        DeleteFileFCB(&context);
+        break;
             
-	  case 0x17: /* RENAME FILE USING FCB */
-            RenameFileFCB(&context);
-            break;
+    case 0x17: /* RENAME FILE USING FCB */
+        RenameFileFCB(&context);
+        break;
 
-	  case 0x19: /* GET CURRENT DEFAULT DRIVE */
-		AL_reg(&context) = DOS_GetDefaultDrive();
-		Error (0,0,0);
-	    break;
+    case 0x19: /* GET CURRENT DEFAULT DRIVE */
+        AL_reg(&context) = DRIVE_GetCurrentDrive();
+        break;
 
-	  case 0x1a: /* SET DISK TRANSFER AREA ADDRESS */
-            {
-                TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() );
-                pTask->dta = MAKELONG( DX_reg(&context), DS_reg(&context) );
-                dprintf_int(stddeb, "int21: Set DTA: %08lx\n", pTask->dta);
-            }
-            break;
+    case 0x1a: /* SET DISK TRANSFER AREA ADDRESS */
+        {
+            TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() );
+            pTask->dta = MAKELONG( DX_reg(&context), DS_reg(&context) );
+            dprintf_int(stddeb, "int21: Set DTA: %08lx\n", pTask->dta);
+        }
+        break;
 
-	  case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */
-            DL_reg(&context) = 0;
-	    GetDriveAllocInfo(&context);
-	    break;
+    case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */
+        DL_reg(&context) = 0;
+        GetDriveAllocInfo(&context);
+        break;
 	
-	  case 0x1c: /* GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE */
-	    GetDriveAllocInfo(&context);
-	    break;
+    case 0x1c: /* GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE */
+        GetDriveAllocInfo(&context);
+        break;
 
-	  case 0x1f: /* GET DRIVE PARAMETER BLOCK FOR DEFAULT DRIVE */
-	    GetDrivePB(&context, DOS_GetDefaultDrive());
-	    break;
+    case 0x1f: /* GET DRIVE PARAMETER BLOCK FOR DEFAULT DRIVE */
+        GetDrivePB(&context, DRIVE_GetCurrentDrive());
+        break;
 		
-	  case 0x25: /* SET INTERRUPT VECTOR */
-            INT_SetHandler( AL_reg(&context),
-                            MAKELONG( DX_reg(&context), DS_reg(&context) ) );
-            break;
+    case 0x25: /* SET INTERRUPT VECTOR */
+        INT_SetHandler( AL_reg(&context),
+                        MAKELONG( DX_reg(&context), DS_reg(&context) ) );
+        break;
 
-	  case 0x2a: /* GET SYSTEM DATE */
-	    GetSystemDate(&context);
-            break;
+    case 0x2a: /* GET SYSTEM DATE */
+        GetSystemDate(&context);
+        break;
 
-          case 0x2b: /* SET SYSTEM DATE */
-            fprintf( stdnimp, "SetSystemDate(%02d/%02d/%04d): not allowed\n",
-                     DL_reg(&context), DH_reg(&context), CX_reg(&context) );
-            AL_reg(&context) = 0;  /* Let's pretend we succeeded */
-            break;
+    case 0x2b: /* SET SYSTEM DATE */
+        fprintf( stdnimp, "SetSystemDate(%02d/%02d/%04d): not allowed\n",
+                 DL_reg(&context), DH_reg(&context), CX_reg(&context) );
+        AL_reg(&context) = 0;  /* Let's pretend we succeeded */
+        break;
 
-	  case 0x2c: /* GET SYSTEM TIME */
-	    INT21_GetSystemTime(&context);
-	    break;
+    case 0x2c: /* GET SYSTEM TIME */
+        INT21_GetSystemTime(&context);
+        break;
 
-          case 0x2d: /* SET SYSTEM TIME */
-            fprintf( stdnimp, "SetSystemTime(%02d:%02d:%02d.%02d): not allowed\n",
-                     CH_reg(&context), CL_reg(&context),
-                     DH_reg(&context), DL_reg(&context) );
-            AL_reg(&context) = 0;  /* Let's pretend we succeeded */
-            break;
+    case 0x2d: /* SET SYSTEM TIME */
+        fprintf( stdnimp, "SetSystemTime(%02d:%02d:%02d.%02d): not allowed\n",
+                 CH_reg(&context), CL_reg(&context),
+                 DH_reg(&context), DL_reg(&context) );
+        AL_reg(&context) = 0;  /* Let's pretend we succeeded */
+        break;
 
-	  case 0x2f: /* GET DISK TRANSFER AREA ADDRESS */
-            {
-                TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() );
-                ES_reg(&context) = SELECTOROF( pTask->dta );
-                BX_reg(&context) = OFFSETOF( pTask->dta );
-            }
-            break;
+    case 0x2f: /* GET DISK TRANSFER AREA ADDRESS */
+        {
+            TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() );
+            ES_reg(&context) = SELECTOROF( pTask->dta );
+            BX_reg(&context) = OFFSETOF( pTask->dta );
+        }
+        break;
             
-	  case 0x30: /* GET DOS VERSION */
-	    AX_reg(&context) = DOSVERSION;
-	    BX_reg(&context) = 0x0012;     /* 0x123456 is Wine's serial # */
-	    CX_reg(&context) = 0x3456;
-	    break;
+    case 0x30: /* GET DOS VERSION */
+        AX_reg(&context) = DOSVERSION;
+        BX_reg(&context) = 0x0012;     /* 0x123456 is Wine's serial # */
+        CX_reg(&context) = 0x3456;
+        break;
 
-	  case 0x31: /* TERMINATE AND STAY RESIDENT */
-            INT_BARF( &context, 0x21 );
-	    break;
+    case 0x31: /* TERMINATE AND STAY RESIDENT */
+        INT_BARF( &context, 0x21 );
+        break;
 
-	  case 0x32: /* GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE */
-	    GetDrivePB(&context, (DL_reg(&context) == 0) ?
-                                (DOS_GetDefaultDrive()) : (DL_reg(&context)-1));
-	    break;
+    case 0x32: /* GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE */
+        GetDrivePB(&context, DOS_GET_DRIVE( DL_reg(&context) ) );
+        break;
 
-	  case 0x33: /* MULTIPLEXED */
-	    switch (AL_reg(&context))
-            {
+    case 0x33: /* MULTIPLEXED */
+        switch (AL_reg(&context))
+        {
 	      case 0x00: /* GET CURRENT EXTENDED BREAK STATE */
                 DL_reg(&context) = 0;
 		break;
@@ -1458,403 +1188,495 @@
 	      default:
                 INT_BARF( &context, 0x21 );
 		break;			
-	    }
-	    break;	
+        }
+        break;	
 	    
-	  case 0x34: /* GET ADDRESS OF INDOS FLAG */
-		ES_reg(&context) = DosHeapHandle;
-		BX_reg(&context) = (int)&heap->InDosFlag - (int)heap;
-	    break;
+    case 0x34: /* GET ADDRESS OF INDOS FLAG */
+        ES_reg(&context) = DosHeapHandle;
+        BX_reg(&context) = (int)&heap->InDosFlag - (int)heap;
+        break;
 
-	  case 0x35: /* GET INTERRUPT VECTOR */
+    case 0x35: /* GET INTERRUPT VECTOR */
+        {
+            SEGPTR addr = INT_GetHandler( AL_reg(&context) );
+            ES_reg(&context) = SELECTOROF(addr);
+            BX_reg(&context) = OFFSETOF(addr);
+        }
+        break;
+
+    case 0x36: /* GET FREE DISK SPACE */
+        GetFreeDiskSpace(&context);
+        break;
+
+    case 0x38: /* GET COUNTRY-SPECIFIC INFORMATION */
+        AX_reg(&context) = 0x02; /* no country support available */
+        SET_CFLAG(&context);
+        break;
+
+    case 0x39: /* "MKDIR" - CREATE SUBDIRECTORY */
+        if (!FILE_MakeDir( PTR_SEG_OFF_TO_LIN( DS_reg(&context),
+                                               DX_reg(&context) )))
+        {
+            AX_reg(&context) = DOS_ExtendedError;
+            SET_CFLAG(&context);
+        }
+        break;
+	
+    case 0x3a: /* "RMDIR" - REMOVE SUBDIRECTORY */
+        if (!FILE_RemoveDir( PTR_SEG_OFF_TO_LIN( DS_reg(&context),
+                                                 DX_reg(&context) )))
+        {
+            AX_reg(&context) = DOS_ExtendedError;
+            SET_CFLAG(&context);
+        }
+        break;
+
+    case 0x3b: /* "CHDIR" - SET CURRENT DIRECTORY */
+        INT21_ChangeDir(&context);
+        break;
+	
+    case 0x3c: /* "CREAT" - CREATE OR TRUNCATE FILE */
+        AX_reg(&context) = _lcreat( PTR_SEG_OFF_TO_LIN( DS_reg(&context),
+                                    DX_reg(&context) ), CX_reg(&context) );
+        if (AX_reg(&context) == (WORD)HFILE_ERROR)
+        {
+            AX_reg(&context) = DOS_ExtendedError;
+            SET_CFLAG(&context);
+        }
+        break;
+
+    case 0x3d: /* "OPEN" - OPEN EXISTING FILE */
+        OpenExistingFile(&context);
+        break;
+
+    case 0x3e: /* "CLOSE" - CLOSE FILE */
+        if ((AX_reg(&context) = _lclose( BX_reg(&context) )) != 0)
+        {
+            AX_reg(&context) = DOS_ExtendedError;
+            SET_CFLAG(&context);
+        }
+        break;
+
+    case 0x3f: /* "READ" - READ FROM FILE OR DEVICE */
+        if ((AX_reg(&context) = _lread( BX_reg(&context),
+                       PTR_SEG_OFF_TO_LIN( DS_reg(&context),DX_reg(&context) ),
+                       CX_reg(&context))) == (WORD)HFILE_ERROR)
+        {
+            AX_reg(&context) = DOS_ExtendedError;
+            SET_CFLAG(&context);
+        }
+        break;
+
+    case 0x40: /* "WRITE" - WRITE TO FILE OR DEVICE */
+        if ((AX_reg(&context) = _lwrite( BX_reg(&context),
+                       PTR_SEG_OFF_TO_LIN( DS_reg(&context),DX_reg(&context) ),
+                       CX_reg(&context))) == (WORD)HFILE_ERROR)
+        {
+            AX_reg(&context) = DOS_ExtendedError;
+            SET_CFLAG(&context);
+        }
+        break;
+
+    case 0x41: /* "UNLINK" - DELETE FILE */
+        if (!FILE_Unlink( PTR_SEG_OFF_TO_LIN( DS_reg(&context),
+                                              DX_reg(&context) )))
+        {
+            AX_reg(&context) = DOS_ExtendedError;
+            SET_CFLAG(&context);
+        }		
+        break;
+
+    case 0x42: /* "LSEEK" - SET CURRENT FILE POSITION */
+        {
+            LONG status = _llseek( BX_reg(&context),
+                                   MAKELONG(DX_reg(&context),CX_reg(&context)),
+                                   AL_reg(&context) );
+            if (status == HFILE_ERROR)
             {
-                SEGPTR addr = INT_GetHandler( AL_reg(&context) );
-                ES_reg(&context) = SELECTOROF(addr);
-                BX_reg(&context) = OFFSETOF(addr);
-            }
-	    break;
-
-	  case 0x36: /* GET FREE DISK SPACE */
-	    GetFreeDiskSpace(&context);
-	    break;
-
-	  case 0x38: /* GET COUNTRY-SPECIFIC INFORMATION */
-	    AX_reg(&context) = 0x02; /* no country support available */
-	    SET_CFLAG(&context);
-	    break;
-		
-	  case 0x39: /* "MKDIR" - CREATE SUBDIRECTORY */
-	    MakeDir(&context);
-	    break;
-	
-	  case 0x3a: /* "RMDIR" - REMOVE SUBDIRECTORY */
-	    RemoveDir(&context);
-	    break;
-	
-	  case 0x3b: /* "CHDIR" - SET CURRENT DIRECTORY */
-	    ChangeDir(&context);
-	    break;
-	
-	  case 0x3c: /* "CREAT" - CREATE OR TRUNCATE FILE */
-	    CreateFile(&context);
-	    break;
-
-	  case 0x3d: /* "OPEN" - OPEN EXISTING FILE */
-	    OpenExistingFile(&context);
-	    break;
-	
-	  case 0x3e: /* "CLOSE" - CLOSE FILE */
-	    CloseFile(&context);
-	    break;
-	
-	  case 0x3f: /* "READ" - READ FROM FILE OR DEVICE */
-	    ReadFile(&context);
-	    break;
-	
-	  case 0x40: /* "WRITE" - WRITE TO FILE OR DEVICE */
-	    WriteFile(&context);
-	    break;
-	
-	  case 0x41: /* "UNLINK" - DELETE FILE */
-		if (unlink( DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(&context),DX_reg(&context))) ) == -1) {
-			errno_to_doserr();
-			AX_reg(&context) = ExtendedError;
-			SET_CFLAG(&context);
-			break;
-		}		
-		Error(0,0,0);
-		RESET_CFLAG(&context);
-		break;
-	
-	  case 0x42: /* "LSEEK" - SET CURRENT FILE POSITION */
-	    SeekFile(&context);
-	    break;
-	    
-	  case 0x43: /* FILE ATTRIBUTES */
-	    switch (AL_reg(&context))
-	    {
-	      case 0x00:
-                        GetFileAttribute(&context);
-		break;
-	      case 0x01:
-			RESET_CFLAG(&context);
-		break;
-	    }
-	    break;
-		
-	  case 0x44: /* IOCTL */
-	    switch (AL_reg(&context))
-	    {
-              case 0x00:
-                ioctlGetDeviceInfo(&context);
-		break;
-
-	      case 0x01:
-
-	        break;
-              case 0x08:   /* Check if drive is removable. */
-                drive = BL_reg(&context) ? (BL_reg(&context) - 1)
-                                        : DOS_GetDefaultDrive();
-                if(!DOS_ValidDrive(drive))
-                {
-                    Error( InvalidDrive, EC_NotFound, EL_Disk );
-                    AX_reg(&context) = InvalidDrive;
-                    SET_CFLAG(&context);
-                }
-                else
-                {
-                    if (drive > 1)
-                        AX_reg(&context) = 1;   /* not removable */
-                    else
-                        AX_reg(&context) = 0;      /* removable */
-                    RESET_CFLAG(&context);
-                }
-                break;
-		   
-	      case 0x09:   /* CHECK IF BLOCK DEVICE REMOTE */
-                drive = BL_reg(&context) ? (BL_reg(&context) - 1)
-                                        : DOS_GetDefaultDrive();
-                if(!DOS_ValidDrive(drive))
-                {
-                    Error( InvalidDrive, EC_NotFound, EL_Disk );
-                    AX_reg(&context) = InvalidDrive;
-                    SET_CFLAG(&context);
-                }
-                else
-                {
-		    DX_reg(&context) = (1<<9) | (1<<12) | (1<<15);
-		    RESET_CFLAG(&context);
-                }
-		break;
-	      case 0x0a: /* check if handle (BX) is remote */
-	      	/* returns DX, bit 15 set if remote, bit 14 set if date/time
-	      	 * not set on close
-	      	 */
-		DX_reg(&context) = 0;
-		RESET_CFLAG(&context);
-		break;
-	      case 0x0b:   /* SET SHARING RETRY COUNT */
-		if (!CX_reg(&context))
-		{ 
-		  AX_reg(&context) = 1;
-		  SET_CFLAG(&context);
-		  break;
-		}
-		sharing_pause = CX_reg(&context);
-		if (!DX_reg(&context))
-		  sharing_retries = DX_reg(&context);
-		RESET_CFLAG(&context);
-		break;
-
-              case 0x0d:
-                ioctlGenericBlkDevReq(&context);
-                break;
-
-              case 0x0F:   /* Set logical drive mapping */
-                /* FIXME: Not implemented at the moment, always returns error
-                 */
-		fprintf(stdnimp,"Attempt to map drive %02x\n",BL_reg(&context));
-                AX_reg(&context) = 0x0001; /* invalid function */
+                AX_reg(&context) = DOS_ExtendedError;
                 SET_CFLAG(&context);
                 break;
+            }
+            AX_reg(&context) = LOWORD(status);
+            DX_reg(&context) = HIWORD(status);
+        }
+        break;
+
+    case 0x43: /* FILE ATTRIBUTES */
+        switch (AL_reg(&context))
+        {
+        case 0x00:
+            if (!INT21_GetFileAttribute(&context))
+            {
+                AX_reg(&context) = DOS_ExtendedError;
+                SET_CFLAG(&context);
+            }
+            break;
+        case 0x01:
+            RESET_CFLAG(&context);
+            break;
+        }
+        break;
+	
+    case 0x44: /* IOCTL */
+        switch (AL_reg(&context))
+        {
+        case 0x00:
+            ioctlGetDeviceInfo(&context);
+            break;
+
+        case 0x01:
+            break;
+
+        case 0x08:   /* Check if drive is removable. */
+            switch(GetDriveType( DOS_GET_DRIVE( BL_reg(&context) )))
+            {
+            case DRIVE_CANNOTDETERMINE:
+                DOS_ERROR( ER_InvalidDrive, EC_NotFound, SA_Abort, EL_Disk );
+                AX_reg(&context) = ER_InvalidDrive;
+                SET_CFLAG(&context);
+                break;
+            case DRIVE_REMOVABLE:
+                AX_reg(&context) = 0;      /* removable */
+                break;
+            default:
+                AX_reg(&context) = 1;   /* not removable */
+                break;
+            }
+            break;
+
+        case 0x09:   /* CHECK IF BLOCK DEVICE REMOTE */
+            switch(GetDriveType( DOS_GET_DRIVE( BL_reg(&context) )))
+            {
+            case DRIVE_CANNOTDETERMINE:
+                DOS_ERROR( ER_InvalidDrive, EC_NotFound, SA_Abort, EL_Disk );
+                AX_reg(&context) = ER_InvalidDrive;
+                SET_CFLAG(&context);
+                break;
+            case DRIVE_REMOTE:
+                DX_reg(&context) = (1<<9) | (1<<12);  /* remote */
+                break;
+            default:
+                DX_reg(&context) = 0;  /* FIXME: use driver attr here */
+                break;
+            }
+            break;
+
+        case 0x0a: /* check if handle (BX) is remote */
+            /* returns DX, bit 15 set if remote, bit 14 set if date/time
+             * not set on close
+             */
+            DX_reg(&context) = 0;
+            break;
+
+        case 0x0b:   /* SET SHARING RETRY COUNT */
+            if (!CX_reg(&context))
+            { 
+                AX_reg(&context) = 1;
+                SET_CFLAG(&context);
+                break;
+            }
+            sharing_pause = CX_reg(&context);
+            if (!DX_reg(&context))
+                sharing_retries = DX_reg(&context);
+            RESET_CFLAG(&context);
+            break;
+
+        case 0x0d:
+            ioctlGenericBlkDevReq(&context);
+            break;
+
+        case 0x0F:   /* Set logical drive mapping */
+            /* FIXME: Not implemented at the moment, always returns error
+             */
+            INT_BARF( &context, 0x21 );
+            AX_reg(&context) = 0x0001; /* invalid function */
+            SET_CFLAG(&context);
+            break;
                 
-	      default:
-                INT_BARF( &context, 0x21 );
-		break;
-	    }
-	    break;
+        default:
+            INT_BARF( &context, 0x21 );
+            break;
+        }
+        break;
 
-	  case 0x45: /* "DUP" - DUPLICATE FILE HANDLE */
-            if ((AX_reg(&context) = dup(BX_reg(&context))) == 0xffff)
+    case 0x45: /* "DUP" - DUPLICATE FILE HANDLE */
+        if ((AX_reg(&context) = FILE_Dup(BX_reg(&context))) == (WORD)HFILE_ERROR)
+        {
+            AX_reg(&context) = DOS_ExtendedError;
+            SET_CFLAG(&context);
+        }
+        break;
+
+    case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */
+        if (FILE_Dup2( BX_reg(&context), CX_reg(&context) ) == HFILE_ERROR)
+        {
+            AX_reg(&context) = DOS_ExtendedError;
+            SET_CFLAG(&context);
+        }
+        break;
+
+    case 0x47: /* "CWD" - GET CURRENT DIRECTORY */
+        if (!INT21_GetCurrentDirectory(&context))
+        {
+            AX_reg(&context) = DOS_ExtendedError;
+            SET_CFLAG(&context);
+        }
+        else AX_reg(&context) = 0x0100; 
+        /* intlist: many Microsoft products for Windows rely on this */
+        break;
+	
+    case 0x48: /* ALLOCATE MEMORY */
+    case 0x49: /* FREE MEMORY */
+    case 0x4a: /* RESIZE MEMORY BLOCK */
+        INT_BARF( &context, 0x21 );
+        break;
+	
+    case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
+        WinExec( PTR_SEG_OFF_TO_LIN( DS_reg(&context), DX_reg(&context) ),
+                 SW_NORMAL );
+        break;		
+	
+    case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
+        TASK_KillCurrentTask( AL_reg(&context) );
+        break;
+
+    case 0x4d: /* GET RETURN CODE */
+        AX_reg(&context) = 0; /* normal exit */
+        break;
+
+    case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */
+        if (!INT21_FindFirst(&context)) break;
+        /* fall through */
+
+    case 0x4f: /* "FINDNEXT" - FIND NEXT MATCHING FILE */
+        if (!INT21_FindNext(&context))
+        {
+            DOS_ERROR( ER_NoMoreFiles, EC_MediaError, SA_Abort, EL_Disk );
+            AX_reg(&context) = ER_NoMoreFiles;
+            SET_CFLAG(&context);
+        }
+        break;
+
+    case 0x51: /* GET PSP ADDRESS */
+    case 0x62: /* GET PSP ADDRESS */
+        /* FIXME: should we return the original DOS PSP upon */
+        /*        Windows startup ? */
+        BX_reg(&context) = GetCurrentPDB();
+        break;
+
+    case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
+        ES_reg(&context) = 0x0;
+        BX_reg(&context) = 0x0;
+        INT_BARF( &context, 0x21 );
+        break;
+
+    case 0x56: /* "RENAME" - RENAME FILE */
+        if (!INT21_RenameFile(&context))
+        {
+            AX_reg(&context) = DOS_ExtendedError;
+            SET_CFLAG(&context);
+        }
+        break;
+
+    case 0x57: /* FILE DATE AND TIME */
+        switch (AL_reg(&context))
+        {
+        case 0x00:
+            if (!FILE_Fstat( BX_reg(&context), NULL, NULL,
+                             &DX_reg(&context), &CX_reg(&context) ))
             {
-                errno_to_doserr();
-                AX_reg(&context) = ExtendedError;
+                AX_reg(&context) = DOS_ExtendedError;
                 SET_CFLAG(&context);
             }
-            else RESET_CFLAG(&context);
-	    break;
-
-	  case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */
-            if (dup2( BX_reg(&context), CX_reg(&context) ) == -1)
+            break;
+        case 0x01:
+            if (!INT21_SetFileDateTime(&context))
             {
-                errno_to_doserr();
-                AX_reg(&context) = ExtendedError;
+                AX_reg(&context) = DOS_ExtendedError;
                 SET_CFLAG(&context);
             }
-            else RESET_CFLAG(&context);
             break;
+        }
+        break;
 
-	  case 0x47: /* "CWD" - GET CURRENT DIRECTORY */
-	    GetCurrentDirectory(&context);
-	    AX_reg(&context) = 0x0100; 
-	    /* intlist: many Microsoft products for Windows rely on this */
-	    break;
-	
-	  case 0x48: /* ALLOCATE MEMORY */
-	  case 0x49: /* FREE MEMORY */
-	  case 0x4a: /* RESIZE MEMORY BLOCK */
-            INT_BARF( &context, 0x21 );
+    case 0x58: /* GET OR SET MEMORY/UMB ALLOCATION STRATEGY */
+        switch (AL_reg(&context))
+        {
+        case 0x00:
+            AX_reg(&context) = 1;
             break;
-	
-	  case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
-            WinExec( PTR_SEG_OFF_TO_LIN(DS_reg(&context),DX_reg(&context)),
-                     SW_NORMAL );
-	    break;		
-	
-	  case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
-            TASK_KillCurrentTask( AL_reg(&context) );
-	    break;
-
-	  case 0x4d: /* GET RETURN CODE */
-	    AX_reg(&context) = NoError; /* normal exit */
-	    break;
-
-	  case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */
-	    FindFirst(&context);
-	    break;
-
-	  case 0x4f: /* "FINDNEXT" - FIND NEXT MATCHING FILE */
-	    FindNext(&context);
-	    break;
-
-	  case 0x51: /* GET PSP ADDRESS */
-	  case 0x62: /* GET PSP ADDRESS */
-	    /* FIXME: should we return the original DOS PSP upon */
-	    /*        Windows startup ? */
-	    BX_reg(&context) = GetCurrentPDB();
-	    break;
-
-	  case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
-            ES_reg(&context) = 0x0;
-            BX_reg(&context) = 0x0;
-            INT_BARF( &context, 0x21 );
+        case 0x02:
+            AX_reg(&context) = 0;
             break;
-		
-	  case 0x56: /* "RENAME" - RENAME FILE */
-	    RenameFile(&context);
-	    break;
-	
-	  case 0x57: /* FILE DATE AND TIME */
-	    switch (AL_reg(&context))
-	    {
-	      case 0x00:
-		GetFileDateTime(&context);
-		break;
-	      case 0x01:
-		SetFileDateTime(&context);
-		break;
-	    }
-	    break;
-
-	  case 0x58: /* GET OR SET MEMORY/UMB ALLOCATION STRATEGY */
-	    switch (AL_reg(&context))
-	    {
-	      case 0x00:
-		AX_reg(&context) = 1;
-		break;
-	      case 0x02:
-		AX_reg(&context) = 0;
-		break;
-	      case 0x01:
-	      case 0x03:
-		break;
-	    }
-	    RESET_CFLAG(&context);
-	    break;
-	
-	  case 0x5a: /* CREATE TEMPORARY FILE */
-	    CreateTempFile(&context);
-	    break;
-	
-	  case 0x5b: /* CREATE NEW FILE */
-	    CreateNewFile(&context);
-	    break;
-	
-	  case 0x5d: /* NETWORK */
-	  case 0x5e:
-	    /* network software not installed */
-	    AX_reg(&context) = NoNetwork;
-	    SET_CFLAG(&context);
-	    break;
-	
-	  case 0x5f: /* NETWORK */
-	    switch (AL_reg(&context))
-	    {
-	      case 0x07: /* ENABLE DRIVE */
-		if (!DOS_EnableDrive(DL_reg(&context))) 
-		{
-		    Error(InvalidDrive, EC_MediaError , EL_Disk);
-		    AX_reg(&context) = InvalidDrive;
-		    SET_CFLAG(&context);
-		    break;
-		}
-		else 
-		{
-		    RESET_CFLAG(&context);
-		    break;
-		}
-	      case 0x08: /* DISABLE DRIVE */
-		if (!DOS_DisableDrive(DL_reg(&context)))
-		{
-		    Error(InvalidDrive, EC_MediaError , EL_Disk);
-		    AX_reg(&context) = InvalidDrive;
-		    SET_CFLAG(&context);
-		    break;
-		} 
-		else 
-		{
-		    RESET_CFLAG(&context);
-		    break;
-		}
-	      default:
-		/* network software not installed */
-		AX_reg(&context) = NoNetwork; 
-		SET_CFLAG(&context);
-		break;
-	    }
-	    break;
-
-	  case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */
-		strncpy(PTR_SEG_OFF_TO_LIN(ES_reg(&context),DI_reg(&context)),
-                        PTR_SEG_OFF_TO_LIN(DS_reg(&context),SI_reg(&context)),
-                        strlen(PTR_SEG_OFF_TO_LIN(DS_reg(&context),SI_reg(&context))) & 0x7f);
-		RESET_CFLAG(&context);
-	    break;
-
-	  case 0x61: /* UNUSED */
-	  case 0x63: /* UNUSED */
-	  case 0x64: /* OS/2 DOS BOX */
-	  case 0x65: /* GET EXTENDED COUNTRY INFORMATION */
-            INT_BARF( &context, 0x21 );
+        case 0x01:
+        case 0x03:
             break;
-	
-	  case 0x66: /* GLOBAL CODE PAGE TABLE */
-	    switch (AL_reg(&context))
+        }
+        RESET_CFLAG(&context);
+        break;
+
+    case 0x5a: /* CREATE TEMPORARY FILE */
+        if (!INT21_CreateTempFile(&context))
+        {
+            AX_reg(&context) = DOS_ExtendedError;
+            SET_CFLAG(&context);
+        }
+        break;
+
+    case 0x5b: /* CREATE NEW FILE */
+        if ((AX_reg(&context) = _lcreat_uniq( PTR_SEG_OFF_TO_LIN(DS_reg(&context),DX_reg(&context)), 0 )) == (WORD)HFILE_ERROR)
+        {
+            AX_reg(&context) = DOS_ExtendedError;
+            SET_CFLAG(&context);
+        }
+        break;
+
+    case 0x5d: /* NETWORK */
+    case 0x5e:
+        /* network software not installed */
+        DOS_ERROR( ER_NoNetwork, EC_NotFound, SA_Abort, EL_Network );
+        AX_reg(&context) = DOS_ExtendedError;
+        SET_CFLAG(&context);
+        break;
+
+    case 0x5f: /* NETWORK */
+        switch (AL_reg(&context))
+        {
+        case 0x07: /* ENABLE DRIVE */
+            if (!DRIVE_Enable( DL_reg(&context) ))
             {
-	      case 0x01:
-		DX_reg(&context) = BX_reg(&context) = CodePage;
-		RESET_CFLAG(&context);
-		break;			
-	      case 0x02: 
-		CodePage = BX_reg(&context);
-		RESET_CFLAG(&context);
-		break;
-	    }
-	    break;
+                DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk );
+                AX_reg(&context) = DOS_ExtendedError;
+                SET_CFLAG(&context);
+            }
+            break;
 
-	  case 0x67: /* SET HANDLE COUNT */			
-	    RESET_CFLAG(&context);
-	    break;
+        case 0x08: /* DISABLE DRIVE */
+            if (!DRIVE_Disable( DL_reg(&context) ))
+            {
+                DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk );
+                AX_reg(&context) = DOS_ExtendedError;
+                SET_CFLAG(&context);
+            } 
+            break;
 
-	  case 0x68: /* "FFLUSH" - COMMIT FILE */
-	  case 0x6a: /* COMMIT FILE */
-            fsync( BX_reg(&context) );
-	    RESET_CFLAG(&context);
-	    break;		
+        default:
+            /* network software not installed */
+            DOS_ERROR( ER_NoNetwork, EC_NotFound, SA_Abort, EL_Network );
+            AX_reg(&context) = DOS_ExtendedError;
+            SET_CFLAG(&context);
+            break;
+        }
+        break;
+
+    case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */
+        {
+            const char *truename = DOSFS_GetDosTrueName( PTR_SEG_OFF_TO_LIN(DS_reg(&context),SI_reg(&context) ), FALSE );
+            if (!truename)
+            {
+                AX_reg(&context) = DOS_ExtendedError;
+                SET_CFLAG(&context);
+            }
+            else
+            {
+                lstrcpyn(PTR_SEG_OFF_TO_LIN(ES_reg(&context),DI_reg(&context)),
+                         truename, 128 );
+                AX_reg(&context) = 0;
+            }
+        }
+        break;
+
+    case 0x61: /* UNUSED */
+    case 0x63: /* UNUSED */
+    case 0x64: /* OS/2 DOS BOX */
+    case 0x65: /* GET EXTENDED COUNTRY INFORMATION */
+        INT_BARF( &context, 0x21 );
+        break;
 	
-	  case 0x69: /* DISK SERIAL NUMBER */
-	    switch (AL_reg(&context))
-	    {
-	      case 0x00:
-		GetDiskSerialNumber(&context);
-		break;			
-	      case 0x01: 
-		SetDiskSerialNumber(&context);
-		break;
-	    }
-	    break;
+    case 0x66: /* GLOBAL CODE PAGE TABLE */
+        switch (AL_reg(&context))
+        {
+        case 0x01:
+            DX_reg(&context) = BX_reg(&context) = CodePage;
+            RESET_CFLAG(&context);
+            break;			
+        case 0x02: 
+            CodePage = BX_reg(&context);
+            RESET_CFLAG(&context);
+            break;
+        }
+        break;
+
+    case 0x67: /* SET HANDLE COUNT */
+        SetHandleCount( BX_reg(&context) );
+        if (DOS_ExtendedError)
+        {
+            AX_reg(&context) = DOS_ExtendedError;
+            SET_CFLAG(&context);
+        }
+        break;
+
+    case 0x68: /* "FFLUSH" - COMMIT FILE */
+    case 0x6a: /* COMMIT FILE */
+        if (fsync( FILE_GetUnixHandle( BX_reg(&context) )) == -1)
+        {
+            FILE_SetDosError();
+            AX_reg(&context) = DOS_ExtendedError;
+            SET_CFLAG(&context);
+        }
+        break;		
+	
+    case 0x69: /* DISK SERIAL NUMBER */
+        switch (AL_reg(&context))
+        {
+        case 0x00:
+            if (!INT21_GetDiskSerialNumber(&context))
+            {
+                AX_reg(&context) = DOS_ExtendedError;
+                SET_CFLAG(&context);
+            }
+            else AX_reg(&context) = 0;
+            break;
+        case 0x01:
+            if (!INT21_SetDiskSerialNumber(&context))
+            {
+                AX_reg(&context) = DOS_ExtendedError;
+                SET_CFLAG(&context);
+            }
+            else AX_reg(&context) = 1;
+            break;
+        }
+        break;
     
-	  case 0x6C: /* Extended Open/Create*/
-	    ExtendedOpenCreateFile(&context);
-	    break;
+    case 0x6C: /* Extended Open/Create*/
+        ExtendedOpenCreateFile(&context);
+        break;
 	
-          case 0x70: /* MS-DOS 7 (Windows95) - ??? (country-specific?)*/
-          case 0x71: /* MS-DOS 7 (Chicago) - LONG FILENAME FUNCTIONS */
-          case 0x72: /* MS-DOS 7 (Windows95) - ??? */
-          case 0x73: /* MS-DOS 7 (Windows95) - DRIVE LOCKING ??? */
-            dprintf_int(stddeb,"int21: windows95 function AX %04x\n",
- 			AX_reg(&context));
- 	    dprintf_int(stddeb, "        returning unimplemented\n");
- 	    SET_CFLAG(&context);
- 	    AL_reg(&context) = 0;
- 	    break;
+    case 0x70: /* MS-DOS 7 (Windows95) - ??? (country-specific?)*/
+    case 0x71: /* MS-DOS 7 (Chicago) - LONG FILENAME FUNCTIONS */
+    case 0x72: /* MS-DOS 7 (Windows95) - ??? */
+    case 0x73: /* MS-DOS 7 (Windows95) - DRIVE LOCKING ??? */
+        dprintf_int(stddeb,"int21: windows95 function AX %04x\n",
+                    AX_reg(&context));
+        dprintf_int(stddeb, "        returning unimplemented\n");
+        SET_CFLAG(&context);
+        AL_reg(&context) = 0;
+        break;
 
-          case 0xdc: /* CONNECTION SERVICES - GET CONNECTION NUMBER */
-            break;
+    case 0xdc: /* CONNECTION SERVICES - GET CONNECTION NUMBER */
+    case 0xea: /* NOVELL NETWARE - RETURN SHELL VERSION */
+        break;
 
-	  case 0xea: /* NOVELL NETWARE - RETURN SHELL VERSION */
-	    break;
-
-	  default:
-            INT_BARF( &context, 0x21 );
-            break;
-	}
+    default:
+        INT_BARF( &context, 0x21 );
+        break;
     }
-    dprintf_int(stddeb,"ret21: AX %04x, BX %04x, CX %04x, DX %04x, "
-                "SI %04x, DI %04x, DS %04x, ES %04x EFL %08lx\n",
-                AX_reg(&context), BX_reg(&context), CX_reg(&context),
-                DX_reg(&context), SI_reg(&context), DI_reg(&context),
-                DS_reg(&context), ES_reg(&context), EFL_reg(&context));
+    dprintf_int( stddeb, "ret21: AX=%04x BX=%04x CX=%04x DX=%04x "
+                 "SI=%04x DI=%04x DS=%04x ES=%04x EFL=%08lx\n",
+                 AX_reg(&context), BX_reg(&context), CX_reg(&context),
+                 DX_reg(&context), SI_reg(&context), DI_reg(&context),
+                 DS_reg(&context), ES_reg(&context), EFL_reg(&context));
 }
 
 
diff --git a/miscemu/int25.c b/miscemu/int25.c
index 58b3858..799816a 100644
--- a/miscemu/int25.c
+++ b/miscemu/int25.c
@@ -6,7 +6,7 @@
 #include "ldt.h"
 #include "wine.h"
 #include "miscemu.h"
-#include "dos_fs.h"
+#include "drive.h"
 #include "stddebug.h"
 /* #define DEBUG_INT */
 #include "debug.h"
@@ -21,7 +21,7 @@
     BYTE *dataptr = PTR_SEG_OFF_TO_LIN( DS_reg(&context), BX_reg(&context) );
     DWORD begin, length;
 
-    if (!DOS_ValidDrive(AL_reg(&context)))
+    if (!DRIVE_IsValid(AL_reg(&context)))
     {
         SET_CFLAG(&context);
         AX_reg(&context) = 0x0101;        /* unknown unit */
@@ -30,9 +30,9 @@
 
     if (CX_reg(&context) == 0xffff)
     {
-        begin = getdword(dataptr);
-        length = getword(&dataptr[4]);
-        dataptr = (BYTE *) PTR_SEG_TO_LIN(getdword(&dataptr[6]));
+        begin   = *(DWORD *)dataptr;
+        length  = *(WORD *)(dataptr + 4);
+        dataptr = (BYTE *)PTR_SEG_TO_LIN( *(SEGPTR *)(dataptr + 6) );
     }
     else
     {
diff --git a/miscemu/int26.c b/miscemu/int26.c
index 06f70ed..53f1abc 100644
--- a/miscemu/int26.c
+++ b/miscemu/int26.c
@@ -5,7 +5,7 @@
 #include "ldt.h"
 #include "wine.h"
 #include "miscemu.h"
-#include "dos_fs.h"
+#include "drive.h"
 #include "stddebug.h"
 /* #define DEBUG_INT */
 #include "debug.h"
@@ -20,7 +20,7 @@
     BYTE *dataptr = PTR_SEG_OFF_TO_LIN( DS_reg(&context), BX_reg(&context) );
     DWORD begin, length;
 
-    if (!DOS_ValidDrive(AL_reg(&context)))
+    if (!DRIVE_IsValid(AL_reg(&context)))
     {
         SET_CFLAG(&context);
         AX_reg(&context) = 0x0101;        /* unknown unit */
@@ -29,9 +29,9 @@
 
     if (CX_reg(&context) == 0xffff)
     {
-        begin = getdword(dataptr);
-        length = getword(&dataptr[4]);
-        dataptr = (BYTE *) PTR_SEG_TO_LIN(getdword(&dataptr[6]));
+        begin   = *(DWORD *)dataptr;
+        length  = *(WORD *)(dataptr + 4);
+        dataptr = (BYTE *)PTR_SEG_TO_LIN( *(SEGPTR *)(dataptr + 6) );
     }
     else
     {
diff --git a/miscemu/interrupts.c b/miscemu/interrupts.c
index a9b8b8a..97a9490 100644
--- a/miscemu/interrupts.c
+++ b/miscemu/interrupts.c
@@ -5,8 +5,9 @@
  */
 
 #include "windows.h"
+#include "drive.h"
 #include "miscemu.h"
-#include "dos_fs.h"
+#include "msdos.h"
 #include "module.h"
 #include "registers.h"
 #include "stackframe.h"
@@ -81,7 +82,55 @@
  */
 void INT_Int11Handler( struct sigcontext_struct context )
 {
-    AX_reg(&context) = DOS_GetEquipment();
+    int diskdrives = 0;
+    int parallelports = 0;
+    int serialports = 0;
+    int x;
+
+/* borrowed from Ralph Brown's interrupt lists 
+
+		    bits 15-14: number of parallel devices
+		    bit     13: [Conv] Internal modem
+		    bit     12: reserved
+		    bits 11- 9: number of serial devices
+		    bit      8: reserved
+		    bits  7- 6: number of diskette drives minus one
+		    bits  5- 4: Initial video mode:
+				    00b = EGA,VGA,PGA
+				    01b = 40 x 25 color
+				    10b = 80 x 25 color
+				    11b = 80 x 25 mono
+		    bit      3: reserved
+		    bit      2: [PS] =1 if pointing device
+				[non-PS] reserved
+		    bit      1: =1 if math co-processor
+		    bit      0: =1 if diskette available for boot
+*/
+/*  Currently the only of these bits correctly set are:
+		bits 15-14 		} Added by William Owen Smith, 
+		bits 11-9		} wos@dcs.warwick.ac.uk
+		bits 7-6
+		bit  2			(always set)
+*/
+
+    if (DRIVE_IsValid(0)) diskdrives++;
+    if (DRIVE_IsValid(1)) 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;
+    
+    AX_reg(&context) = (diskdrives << 6) | (serialports << 9) | 
+                       (parallelports << 14) | 0x02;
 }
 
 
diff --git a/multimedia/audio.c b/multimedia/audio.c
index 5c46e07..4c96809 100644
--- a/multimedia/audio.c
+++ b/multimedia/audio.c
@@ -138,7 +138,6 @@
 		lpstrElementName = (LPSTR)PTR_SEG_TO_LIN(lpParms->lpstrElementName);
 		dprintf_mciwave(stddeb,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n",
 						lpstrElementName);
-/*		printf("WAVE_mciOpen // cdw='%s'\n", DOS_GetCurrentDir(DOS_GetDefaultDrive())); */
 		if (strlen(lpstrElementName) > 0) {
 			strcpy(str, lpstrElementName);
 			AnsiUpper(str);
diff --git a/multimedia/mcistring.c b/multimedia/mcistring.c
index dc99c2a..c896070 100644
--- a/multimedia/mcistring.c
+++ b/multimedia/mcistring.c
@@ -46,7 +46,7 @@
 /* The reason why I just don't lowercase the keywords array in 
  * mciSendString is left as an exercise to the reader.
  */
-#define STRCMP(x,y) strcasecmp(x,y)
+#define STRCMP(x,y) lstrcmpi(x,y)
 
 /* standard functionparameters for all functions */
 #define _MCISTR_PROTO_ \
diff --git a/multimedia/midi.c b/multimedia/midi.c
index b734ecd..0094115 100644
--- a/multimedia/midi.c
+++ b/multimedia/midi.c
@@ -296,7 +296,6 @@
     if (dwFlags & MCI_OPEN_ELEMENT) {
 		lpstrElementName = (LPSTR)PTR_SEG_TO_LIN(lpParms->lpstrElementName);
 		dprintf_midi(stddeb, "MIDI_mciOpen // MCI_OPEN_ELEMENT '%s' !\n", lpstrElementName);
-/*		dprintf_midi(stddeb, "MIDI_mciOpen // cdw='%s'\n", DOS_GetCurrentDir(DOS_GetDefaultDrive())); */
 		if (strlen(lpstrElementName) > 0) {
 			strcpy(str, lpstrElementName);
 			AnsiUpper(str);
diff --git a/objects/font.c b/objects/font.c
index 407d15e..b3df1a2 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -14,6 +14,7 @@
 #include "metafile.h"
 #include "wine.h"
 #include "callback.h"
+#include "xmalloc.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -67,15 +68,15 @@
   if( GetPrivateProfileString("fonts", NULL, "*", temp, sizeof(temp), WINE_INI) > 2 ) {
     for( ptr = temp, i = 1; strlen(ptr) != 0; ptr += strlen(ptr) + 1 )
       if( strcmp( ptr, "default" ) )
-	FontNames[i++].window = strdup( ptr );
+	FontNames[i++].window = xstrdup( ptr );
     FontSize = i;
 
     for( i = 1; i < FontSize; i++ ) {
       GetPrivateProfileString("fonts", FontNames[i].window, "*", temp, sizeof(temp), WINE_INI);
-      FontNames[i].x11 = strdup( temp );
+      FontNames[i].x11 = xstrdup( temp );
     }
     GetPrivateProfileString("fonts", "default", "*", temp, sizeof(temp), WINE_INI);
-    FontNames[0].x11 = strdup( temp );
+    FontNames[0].x11 = xstrdup( temp );
 
   } else {
     FontNames[0].window = NULL; FontNames[0].x11 = "*-helvetica";
diff --git a/tools/build.c b/tools/build.c
index c2571e0..e9667ad 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -789,6 +789,7 @@
         case TYPE_CDECL:
 	    varargs=0;
             argc=strlen(fdp->arg_types);
+#if 0
 	    if(odp->type == TYPE_STDCALL)
 	    {
 		/* Output a function prototype with stdcall attribute */
@@ -810,22 +811,34 @@
 		}
 		printf( ") __attribute((stdcall));\n" );
 	    }
-
+#endif
             printf( "void %s_%d(", UpperDLLName, i);
             for(argno=0;argno<argc;argno++)
             {
+	      if(odp->type == TYPE_STDCALL) {
+                switch(fdp->arg_types[argno])
+                {
+                case 'p': printf( "void *");break;
+                case 'l': printf( "int ");break;
+		default:
+                    fprintf(stderr, "Not supported argument type %c\n",
+                            fdp->arg_types[argno]);
+                    exit(1);
+                }
+	      } else {
                 switch(fdp->arg_types[argno])
                 {
                 case 'p': printf( "void *");break;
                 case 'l': printf( "int ");break;
                 case '.': printf( "... ");varargs=argno;break;
-                default:
+		default:
                     fprintf(stderr, "Not supported argument type %c\n",
                             fdp->arg_types[argno]);
                     exit(1);
                 }
-                if(fdp->arg_types[argno]!='.') putchar( 'a'+argno );
-                if (argno!=argc-1) putchar( ',' );
+	      }
+              if(fdp->arg_types[argno]!='.') putchar( 'a'+argno );
+              if (argno!=argc-1) putchar( ',' );
             }
             printf( ")" );
             printf( "\n{\n" );
@@ -849,7 +862,14 @@
 		else putchar('a'+argno);
                 if (argno!=argc-1) putchar(',');
             }
-            printf( ");\n}\n\n");
+            printf( ");\n");
+	    if(odp->type == TYPE_STDCALL) {
+	    	printf( "\t__asm__ __volatile__ (\"movl %%ebp,%%esp\");\n");
+	    	printf( "\t__asm__ __volatile__ (\"popl %%ebp\");\n");
+	    	printf( "\t__asm__ __volatile__ (\"addl $%d,%%esp\");\n", argc*4+4);
+	    	printf( "\t__asm__ __volatile__ (\"jmp -%d(%%esp)\");\n", argc*4+4);
+	    }
+	    printf( "}\n\n");
             break;
         case TYPE_RETURN:
             printf( "void %s_%d()\n{\n\t", UpperDLLName, i);
diff --git a/win32/Makefile.in b/win32/Makefile.in
index 3980b9e..9851ec6 100644
--- a/win32/Makefile.in
+++ b/win32/Makefile.in
@@ -8,12 +8,16 @@
 	environment.c \
 	error.c \
 	file.c \
+	heap.c \
 	init.c \
 	memory.c \
+	newfns.c \
 	object_mgt.c \
 	process.c \
+	resource.c \
 	thread.c \
-	time.c
+	time.c \
+	winprocs.c
 
 all: $(MODULE).o
 
diff --git a/win32/file.c b/win32/file.c
index 2188ff5..1dd15bc 100644
--- a/win32/file.c
+++ b/win32/file.c
@@ -60,9 +60,6 @@
         return INVALID_HANDLE_VALUE;
     }
     fd = open(lpName, O_CREAT, 0666);
-    #if 0
-    fd = open(DOS_GetUnixFileName(lpName), 0, 0666);
-    #endif
     if(fd == -1)
     {
         SetLastError(ErrnoToLastError(errno));
@@ -374,13 +371,13 @@
     }
     else
     {
+        const char *unixName = DOSFS_GetUnixFileName( filename, FALSE );
         type = FILE_TYPE_DISK;
 
         /* Try to open the file.
          */
-        fd = open(DOS_GetUnixFileName(filename),
-                  access_flags | create_flags, 0666);
-        if(fd == -1)
+        if (!unixName ||
+            ((fd = open(unixName, access_flags | create_flags, 0666)) == -1))
         {
             SetLastError(ErrnoToLastError(errno));
             return INVALID_HANDLE_VALUE;
@@ -406,6 +403,15 @@
     return (HANDLE32)file_obj;
 }
 
+/*************************************************************************
+ *              W32_SetHandleCount             (KERNEL32.??)
+ *
+ */
+UINT W32_SetHandleCount(UINT cHandles)
+{
+    return SetHandleCount(cHandles);
+}
+
 int CloseFileHandle(FILE_OBJECT *hFile)
 {
     /* If it's one of the 3 standard handles, don't really
diff --git a/win32/heap.c b/win32/heap.c
new file mode 100644
index 0000000..7a4468f
--- /dev/null
+++ b/win32/heap.c
@@ -0,0 +1,38 @@
+/*
+ * Win32 kernel functions
+ *
+ * Copyright 1995 Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include "windows.h"
+#include "winerror.h"
+#include "kernel32.h"
+#include "winbase.h"
+#include "stddebug.h"
+#include "debug.h"
+
+#define HEAP_ZERO_MEMORY	0x8
+
+/* FIXME: these functions do *not* implement the win32 API properly. They
+are here merely as "get you going" aids */
+
+/***********************************************************************
+ *           HeapAlloc			(KERNEL32.222)
+ *
+ */
+LPVOID HeapAlloc(HANDLE hHeap, DWORD dwFlags, DWORD dwBytes)
+
+{
+	void *result;
+
+	result = malloc(dwBytes);
+	if(result && (dwFlags & HEAP_ZERO_MEMORY))
+		memset(result, 0, dwBytes);
+	return result;
+}
diff --git a/win32/init.c b/win32/init.c
index d2e8936..2081fe1 100644
--- a/win32/init.c
+++ b/win32/init.c
@@ -11,6 +11,7 @@
 #include "winerror.h"
 #include "kernel32.h"
 #include "handle32.h"
+#include "pe_image.h"
 #include "stddebug.h"
 #define DEBUG_WIN32
 #include "debug.h"
@@ -72,10 +73,13 @@
  */
 HMODULE WIN32_GetModuleHandle(char *module)
 {
-    if(module == NULL)
-        return (HMODULE)0;
-    else
-        return GetModuleHandle(module);
+    HMODULE hModule;
+
+    dprintf_win32(stddeb, "GetModuleHandle: %s\n", module ? module : "NULL");
+    if (module == NULL) hModule = GetExePtr( GetCurrentTask() );
+    else hModule = GetModuleHandle(module);
+    dprintf_win32(stddeb, "GetModuleHandle: returning %d\n", hModule );
+    return hModule;
 }
 
 /***********************************************************************
@@ -88,6 +92,7 @@
     lpStartupInfo->lpDesktop = "Desktop";
     lpStartupInfo->lpTitle = "Title";
 
+    lpStartupInfo->cbReserved2 = 0;
     lpStartupInfo->lpReserved2 = NULL; /* must be NULL for VC runtime */
     lpStartupInfo->hStdInput  = (HANDLE)0;
     lpStartupInfo->hStdOutput = (HANDLE)1;
diff --git a/win32/memory.c b/win32/memory.c
index 352db66..bd55c2b 100644
--- a/win32/memory.c
+++ b/win32/memory.c
@@ -49,12 +49,20 @@
     if (fdwAllocationType & MEM_RESERVE || !lpvAddress) {
         ptr = mmap((void *)((((unsigned long)lpvAddress-1) & 0xFFFF0000L) 
 	                + 0x00010000L),
-		   cbSize, PROT_NONE, MAP_ANON|MAP_PRIVATE,0,0);
+		   cbSize, PROT_NONE, MAP_ANON|MAP_PRIVATE,-1,0);
+	if (ptr == (caddr_t) -1) {
+	    dprintf_win32(stddeb, "VirtualAlloc: returning NULL");
+	    return (LPVOID) NULL;
+	}
         if (lpvAddress && ((unsigned long)ptr & 0xFFFF0000L)) {
 	    munmap(ptr, cbSize);
 	    cbSize += 65535;
 	    ptr =  mmap(lpvAddress, cbSize, 
-	                PROT_NONE, MAP_ANON|MAP_PRIVATE,0,0);
+	                PROT_NONE, MAP_ANON|MAP_PRIVATE,-1,0);
+	    if (ptr == (caddr_t) -1) {
+		dprintf_win32(stddeb, "VirtualAlloc: returning NULL");
+		return (LPVOID) NULL;
+	    }
 	    ptr = (void *)((((unsigned long)ptr-1) & 0xFFFF0000L)+0x00010000L);
 	}
 	/* remember the size for VirtualFree since it's going to be handed
@@ -84,7 +92,6 @@
                                           ~(PAGE_GUARD | PAGE_NOCACHE));
 	mprotect(ptr, cbSize, prot);
     }
-    return ptr;
 #if 0
 /* kludge for gnu-win32 */
     if (fdwAllocationType & MEM_RESERVE) return sbrk(0);
diff --git a/win32/newfns.c b/win32/newfns.c
new file mode 100644
index 0000000..2f2fe44
--- /dev/null
+++ b/win32/newfns.c
@@ -0,0 +1,47 @@
+/*
+ * Win32 miscellaneous functions
+ *
+ * Copyright 1995 Thomas Sandford (tdgsandf@prds-grn.demon.co.uk)
+ */
+
+/* Misc. new functions - they should be moved into appropriate files
+at a later date. */
+
+#include <stdio.h>
+#include "windows.h"
+#include "winerror.h"
+#include "kernel32.h"
+#include "stddebug.h"
+#include "debug.h"
+
+/***********************************************************************
+ *           RaiseException		(KERNEL32.??)
+ *
+ * Stub function - does not allow exceptions to be caught yet
+ */
+WINAPI VOID RaiseException(DWORD dwExceptionCode,
+		    DWORD dwExceptionFlags,
+		    DWORD cArguments,
+		    const DWORD * lpArguments)
+{
+    ExitProcess(dwExceptionCode); /* what status should be used here ? */
+}
+
+/***********************************************************************
+ *           GetProcAddress		(KERNEL32.257)
+ *
+ */
+WINAPI FARPROC W32_GetProcAddress(HMODULE hModule,
+			      LPCSTR lpszProc)
+{
+    char *modulename;
+
+    modulename = MODULE_GetModuleName(hModule);
+    if (modulename == NULL)
+	return (FARPROC) NULL;
+    if (((int) lpszProc) & 0xffff) 
+	return RELAY32_GetEntryPoint(modulename, lpszProc, 0);
+    else
+	return RELAY32_GetEntryPoint(modulename, (char *) NULL, (int) lpszProc);
+}
+
diff --git a/win32/process.c b/win32/process.c
index 8fb8fe4..b8e244d 100644
--- a/win32/process.c
+++ b/win32/process.c
@@ -82,3 +82,40 @@
 {
 	return 0;
 }
+
+/***********************************************************************
+ *           LoadLibraryA         (KERNEL32.365)
+ * copied from LoadLibrary
+ * This does not currently support built-in libraries
+ */
+HANDLE32 WINAPI LoadLibraryA(char *libname)
+{
+	HANDLE handle;
+	dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
+	handle = LoadModule( libname, (LPVOID)-1 );
+	if (handle == (HANDLE) -1)
+	{
+		char buffer[256];
+		strcpy( buffer, libname );
+		strcat( buffer, ".dll" );
+		handle = LoadModule( buffer, (LPVOID)-1 );
+	}
+	/* Obtain module handle and call initialization function */
+#ifndef WINELIB
+	if (handle >= (HANDLE)32) PE_InitializeDLLs( GetExePtr(handle));
+#endif
+	return handle;
+}
+
+
+#ifndef WINELIB
+/***********************************************************************
+ *          WIN32_GetProcAddress
+ */
+void* WINAPI WIN32_GetProcAddress(HANDLE32 hModule, char* function)
+{
+	dprintf_module( stddeb, "WIN32_GetProcAddress(%08x,%s)\n",
+		hModule, function);
+	return PE_GetProcAddress(GetExePtr(hModule),function);
+}
+#endif  /* WINELIB */
diff --git a/win32/resource.c b/win32/resource.c
new file mode 100644
index 0000000..5add440
--- /dev/null
+++ b/win32/resource.c
@@ -0,0 +1,353 @@
+/*
+ * Win32 Resources
+ *
+ * Copyright 1995 Thomas Sandford
+ *
+ * Based on the Win16 resource handling code in loader/resource.c
+ * Copyright 1993 Robert J. Amstadt
+ * Copyright 1995 Alexandre Julliard
+ *
+ * This is not even at ALPHA level yet. Don't expect it to work!
+ */
+
+#include <sys/types.h>
+#include "wintypes.h"
+#include "windows.h"
+#include "kernel32.h"
+#include "pe_image.h"
+#include "handle32.h"
+#include "resource32.h"
+#include "neexe.h"
+#include "accel.h"
+#include "xmalloc.h"
+#include "stddebug.h"
+#include "debug.h"
+
+int language = 0x0409;
+
+#define PrintId(name) \
+    if (HIWORD((DWORD)name)) \
+        dprintf_resource( stddeb, "'%s'", name); \
+    else \
+        dprintf_resource( stddeb, "#%04x", LOWORD(name)); 
+
+/**********************************************************************
+ *	    GetResDirEntry
+ *
+ *	Helper function - goes down one level of PE resource tree
+ *
+ */
+PIMAGE_RESOURCE_DIRECTORY GetResDirEntry(PIMAGE_RESOURCE_DIRECTORY resdirptr,
+					 LPCSTR name,
+					 DWORD root)
+{
+    int entrynum;
+    PIMAGE_RESOURCE_DIRECTORY_ENTRY entryTable;
+
+    if (HIWORD(name)) {
+    /* FIXME: what about #xxx names? */
+	entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (
+			(BYTE *) resdirptr + 
+                        sizeof(IMAGE_RESOURCE_DIRECTORY));
+	for (entrynum = 0; entrynum < resdirptr->NumberOfNamedEntries; entrynum++)
+	    /* do what??? */ ;
+	return NULL;
+    } else {
+	entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (
+			(BYTE *) resdirptr + 
+                        sizeof(IMAGE_RESOURCE_DIRECTORY) +
+			resdirptr->NumberOfNamedEntries * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
+	for (entrynum = 0; entrynum < resdirptr->NumberOfIdEntries; entrynum++)
+	    if ((DWORD)entryTable[entrynum].Name == (DWORD)name)
+		return (PIMAGE_RESOURCE_DIRECTORY) (
+			root +
+			(entryTable[entrynum].OffsetToData & 0x7fffffff));
+	return NULL;
+    }
+}
+
+/**********************************************************************
+ *	    FindResource    (KERNEL.60)
+ */
+HANDLE32 FindResource32( HINSTANCE hModule, LPCTSTR name, LPCTSTR type )
+{
+#ifndef WINELIB
+    struct w_files *wptr = wine_files;
+    PIMAGE_RESOURCE_DIRECTORY resdirptr;
+    DWORD root;
+
+#if 0
+    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+#endif
+    dprintf_resource(stddeb, "FindResource: module=%08x type=", hModule );
+    PrintId( type );
+    dprintf_resource( stddeb, " name=" );
+    PrintId( name );
+    dprintf_resource( stddeb, "\n" );
+    while (wptr != NULL && (wptr->hModule != hModule))
+	wptr = wptr->next;
+    if ((wptr == NULL) || (wptr->pe == NULL) || (wptr->pe->pe_resource == NULL))
+	return 0;
+    resdirptr = (PIMAGE_RESOURCE_DIRECTORY) wptr->pe->pe_resource;
+    root = (DWORD) resdirptr;
+    if ((resdirptr = GetResDirEntry(resdirptr, type, root)) == NULL)
+	return 0;
+    if ((resdirptr = GetResDirEntry(resdirptr, name, root)) == NULL)
+	return 0;
+    return (HANDLE32) GetResDirEntry(resdirptr, (LPCSTR)language, root);
+#else
+    return LIBRES_FindResource( hModule, name, type );
+#endif
+}
+
+
+/**********************************************************************
+ *	    LoadResource    (KERNEL.61)
+ */
+HANDLE32 LoadResource32( HINSTANCE hModule, HANDLE32 hRsrc )
+{
+#ifndef WINELIB
+    struct w_files *wptr = wine_files;
+
+#if 0
+    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+#endif
+    dprintf_resource(stddeb, "LoadResource: module="NPFMT" res="NPFMT"\n",
+                     hModule, hRsrc );
+    if (!hRsrc) return 0;
+    while (wptr != NULL && (wptr->hModule != hModule))
+	wptr = wptr->next;
+    if ((wptr == NULL) || (wptr->pe == NULL) || (wptr->pe->pe_resource == NULL))
+	return 0;
+    return (HANDLE32) (wptr->load_addr+((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData);
+#else
+    return LIBRES_LoadResource( hModule, hRsrc );
+#endif
+}
+
+
+/**********************************************************************
+ *	    LockResource    (KERNEL.62)
+ */
+LPVOID LockResource32( HANDLE32 handle )
+{
+	return (LPVOID) handle;
+}
+
+/**********************************************************************
+ *	    FreeResource    (KERNEL.63)
+ */
+BOOL FreeResource32( HANDLE32 handle )
+{
+    /* no longer used in Win32 */
+    return TRUE;
+}
+
+/**********************************************************************
+ *	    AccessResource    (KERNEL.64)
+ */
+INT AccessResource32( HINSTANCE hModule, HRSRC hRsrc )
+{
+    WORD *pModule;
+
+    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    dprintf_resource(stddeb, "AccessResource: module="NPFMT" res="NPFMT"\n",
+                     hModule, hRsrc );
+    if (!hRsrc) return 0;
+    if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
+#ifndef WINELIB
+    switch(*pModule)
+    {
+      case NE_SIGNATURE:
+        return NE_AccessResource( hModule, hRsrc );
+      case PE_SIGNATURE:
+        return 0;
+      default:
+        return 0;
+    }
+#else
+        return LIBRES_AccessResource( hModule, hRsrc );
+#endif
+}
+
+
+/**********************************************************************
+ *	    SizeofResource    (KERNEL.65)
+ */
+DWORD SizeofResource32( HINSTANCE hModule, HRSRC hRsrc )
+{
+    WORD *pModule;
+
+    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    dprintf_resource(stddeb, "SizeofResource: module="NPFMT" res="NPFMT"\n",
+                     hModule, hRsrc );
+    if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
+#ifndef WINELIB
+    switch(*pModule)
+    {
+      case NE_SIGNATURE:
+        return NE_SizeofResource( hModule, hRsrc );
+      case PE_SIGNATURE:
+        return 0;
+      default:
+        return 0;
+    }
+#else
+    return LIBRES_SizeofResource( hModule, hRsrc );
+#endif
+}
+
+/**********************************************************************
+ *			LoadAccelerators	[USER.177]
+*/
+HANDLE LoadAccelerators32(HINSTANCE instance, LPCTSTR lpTableName)
+{
+    HANDLE 	hAccel;
+    HANDLE 	rsc_mem;
+    HRSRC hRsrc;
+    BYTE 	*lp;
+    ACCELHEADER	*lpAccelTbl;
+    int 	i, n;
+
+    if (HIWORD(lpTableName))
+        dprintf_accel( stddeb, "LoadAccelerators: "NPFMT" '%s'\n",
+                      instance, (char *)( lpTableName ) );
+    else
+        dprintf_accel( stddeb, "LoadAccelerators: "NPFMT" %04x\n",
+                       instance, LOWORD(lpTableName) );
+
+    if (!(hRsrc = FindResource( instance, lpTableName, RT_ACCELERATOR )))
+      return 0;
+    if (!(rsc_mem = LoadResource( instance, hRsrc ))) return 0;
+
+    lp = (BYTE *)LockResource(rsc_mem);
+    n = SizeofResource( instance, hRsrc ) / sizeof(ACCELENTRY);
+    hAccel = GlobalAlloc(GMEM_MOVEABLE, 
+    	sizeof(ACCELHEADER) + (n + 1)*sizeof(ACCELENTRY));
+    lpAccelTbl = (LPACCELHEADER)GlobalLock(hAccel);
+    lpAccelTbl->wCount = 0;
+    for (i = 0; i < n; i++) {
+	lpAccelTbl->tbl[i].type = *(lp++);
+	lpAccelTbl->tbl[i].wEvent = *((WORD *)lp);
+	lp += 2;
+	lpAccelTbl->tbl[i].wIDval = *((WORD *)lp);
+	lp += 2;
+    	if (lpAccelTbl->tbl[i].wEvent == 0) break;
+	dprintf_accel(stddeb,
+		"Accelerator #%u / event=%04X id=%04X type=%02X \n", 
+		i, lpAccelTbl->tbl[i].wEvent, lpAccelTbl->tbl[i].wIDval, 
+		lpAccelTbl->tbl[i].type);
+	lpAccelTbl->wCount++;
+ 	}
+    GlobalUnlock(hAccel);
+    FreeResource( rsc_mem );
+    return hAccel;
+}
+
+/**********************************************************************
+ *					LoadString
+ */
+int
+LoadString32(HINSTANCE instance, DWORD resource_id, LPTSTR buffer, int buflen)
+{
+    HANDLE32 hmem, hrsrc;
+    WCHAR *p;
+    int string_num;
+    int i;
+
+    dprintf_resource(stddeb, "LoadString: instance = "NPFMT", id = %04x, buffer = %08x, "
+	   "length = %d\n", instance, resource_id, (int) buffer, buflen);
+
+    hrsrc = FindResource32( instance, (resource_id>>4)+1, RT_STRING );
+    if (!hrsrc) return 0;
+    hmem = LoadResource32( instance, hrsrc );
+    if (!hmem) return 0;
+    
+    p = LockResource32(hmem);
+    string_num = resource_id & 0x000f;
+    for (i = 0; i < string_num; i++)
+	p += *p + 1;
+    
+    dprintf_resource( stddeb, "strlen = %d\n", (int)*p );
+    
+    i = MIN(buflen - 1, *p);
+    if (buffer == NULL)
+	return i;
+    if (i > 0) {
+	memcpy(buffer, p + 1, i * sizeof (WCHAR));
+	buffer[i] = (WCHAR) 0;
+    } else {
+	if (buflen > 1) {
+	    buffer[0] = (WCHAR) 0;
+	    return 0;
+	}
+	fprintf(stderr,"LoadString // I dont know why , but caller give buflen=%d *p=%d !\n", buflen, *p);
+	fprintf(stderr,"LoadString // and try to obtain string '%s'\n", p + 1);
+    }
+    dprintf_resource(stddeb,"LoadString // '%s' copied !\n", buffer);
+    return i;
+}
+
+/**********************************************************************
+ *					LoadStringA
+ */
+int
+LoadStringA32(HINSTANCE instance, DWORD resource_id, LPSTR buffer, int buflen)
+{
+    WCHAR *buffer2 = xmalloc(buflen*2);
+    int retval = LoadString32(instance, resource_id, buffer2, buflen);
+
+    while (*buffer2) 
+	*buffer++ = (char) *buffer2++;
+    *buffer = 0;
+    return retval;
+}
+
+HICON LoadIconW32(HINSTANCE hisnt, LPCTSTR lpszIcon)
+
+{
+	return LoadIcon(0, IDI_APPLICATION);
+}
+
+HICON LoadIconA32(HINSTANCE hinst, LPCTSTR lpszIcon)
+
+{
+	return LoadIconW32(hinst, lpszIcon);
+}
+/**********************************************************************
+ *	    LoadBitmapW
+ */
+HBITMAP LoadBitmapW32( HANDLE instance, LPCTSTR name )
+{
+    HBITMAP hbitmap = 0;
+    HDC hdc;
+    HANDLE32 hRsrc;
+    HANDLE32 handle;
+    BITMAPINFO *info;
+
+    if (!instance)  /* OEM bitmap */
+    {
+        if (HIWORD((int)name)) return 0;
+        return OBM_LoadBitmap( LOWORD((int)name) );
+    }
+
+    if (!(hRsrc = FindResource32( instance, name, RT_BITMAP ))) return 0;
+    if (!(handle = LoadResource32( instance, hRsrc ))) return 0;
+
+    info = (BITMAPINFO *)LockResource32( handle );
+    if ((hdc = GetDC(0)) != 0)
+    {
+        char *bits = (char *)info + DIB_BitmapInfoSize( info, DIB_RGB_COLORS );
+        hbitmap = CreateDIBitmap( hdc, &info->bmiHeader, CBM_INIT,
+                                  bits, info, DIB_RGB_COLORS );
+        ReleaseDC( 0, hdc );
+    }
+    return hbitmap;
+}
+/**********************************************************************
+ *	    LoadBitmapA
+ */
+HBITMAP LoadBitmapA32( HANDLE instance, LPCTSTR name )
+{
+    return LoadBitmapW32(instance, name);
+}
diff --git a/win32/winprocs.c b/win32/winprocs.c
new file mode 100644
index 0000000..1d9d5a2
--- /dev/null
+++ b/win32/winprocs.c
@@ -0,0 +1,241 @@
+/*
+ * Win32 WndProc function stubs
+ *
+ * Copyright 1995 Thomas Sandford (tdgsandf@prds-grn.demon.co.uk)
+ *
+ * These functions are simply lParam fixers for the Win16 routines
+ */
+
+#include <stdio.h>
+#include "windows.h"
+#include "winerror.h"
+#include "kernel32.h"
+#include "wincon.h"
+#include "stackframe.h"
+#include "stddebug.h"
+#include "debug.h"
+
+BOOL UsesLParamPtr(DWORD message)
+
+{
+    switch (message) {
+	case WM_NCCREATE:
+	case WM_NCCALCSIZE:
+	case WM_WINDOWPOSCHANGING:
+	case WM_WINDOWPOSCHANGED:
+	case WM_GETTEXT:
+	case WM_SETTEXT:
+	case WM_GETMINMAXINFO:
+	    return TRUE;
+	default:
+	    return FALSE;
+    }
+}
+
+LRESULT USER32_DefWindowProcA(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return DefWindowProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return DefWindowProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT ButtonWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return ButtonWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return ButtonWndProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT StaticWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return StaticWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return StaticWndProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT ScrollBarWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return ScrollBarWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return ScrollBarWndProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT ListBoxWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return ListBoxWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return ListBoxWndProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT ComboBoxWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return ComboBoxWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return ComboBoxWndProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT EditWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return EditWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return EditWndProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT PopupMenuWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return PopupMenuWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return PopupMenuWndProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT DesktopWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return DesktopWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return DesktopWndProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT DefDlgProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return DefDlgProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return DefDlgProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT MDIClientWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return MDIClientWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return MDIClientWndProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT DefWindowProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return DefWindowProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return DefWindowProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT DefMDIChildProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return DefMDIChildProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return DefMDIChildProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT SystemMessageBoxProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return SystemMessageBoxProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return SystemMessageBoxProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT FileOpenDlgProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return FileOpenDlgProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return FileOpenDlgProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT FileSaveDlgProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return FileSaveDlgProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return FileSaveDlgProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT ColorDlgProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return ColorDlgProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return ColorDlgProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT FindTextDlgProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return FindTextDlgProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return FindTextDlgProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT ReplaceTextDlgProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return ReplaceTextDlgProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return ReplaceTextDlgProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT PrintSetupDlgProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return PrintSetupDlgProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return PrintSetupDlgProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT PrintDlgProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return PrintDlgProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return PrintDlgProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT AboutDlgProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return AboutDlgProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return AboutDlgProc((HWND)hwnd, msg, wParam, lParam);
+}
+
+LRESULT ComboLBoxWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
+
+{
+    if (UsesLParamPtr(msg))
+	return ComboLBoxWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam));
+    else
+	return ComboLBoxWndProc((HWND)hwnd, msg, wParam, lParam);
+}
+
diff --git a/windows/dce.c b/windows/dce.c
index 15ea232..04d90ae 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -146,7 +146,7 @@
 static HRGN DCE_ClipWindows( HWND hwndStart, HWND hwndEnd,
                              HRGN hrgn, int xoffset, int yoffset )
 {
-    HRGN hrgnTmp, hrgnNew;
+    HRGN hrgnTmp = 0, hrgnNew = 0;
     WND *wndPtr;
 
     if (!hwndStart) return hrgn;
diff --git a/windows/message.c b/windows/message.c
index 43bb4e4..458232c 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -30,6 +30,8 @@
 extern BOOL TIMER_CheckTimer( LONG *next, MSG *msg,
 			      HWND hwnd, BOOL remove );  /* timer.c */
 
+DWORD MSG_WineStartTicks;  /* Ticks at Wine startup */
+
 /* ------- Internal Queues ------ */
 
 static HANDLE hmemSysMsgQueue = 0;
@@ -1243,12 +1245,14 @@
 /*    HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
     retval = CallWindowProc( wndPtr->lpfnWndProc, msg->hwnd, msg->message,
 			     msg->wParam, msg->lParam );
-    if (painting && IsWindow(msg->hwnd) &&
-        (wndPtr->flags & WIN_NEEDS_BEGINPAINT))
+    if (painting && (wndPtr = WIN_FindWndPtr( msg->hwnd )) &&
+        (wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate)
     {
 	fprintf(stderr, "BeginPaint not called on WM_PAINT for hwnd "NPFMT"!\n", 
 		msg->hwnd);
 	wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
+        /* Validate the update region to avoid infinite WM_PAINT loop */
+        ValidateRect( msg->hwnd, NULL );
     }
     return retval;
 }
@@ -1307,7 +1311,7 @@
 {
     struct timeval t;
     gettimeofday( &t, NULL );
-    return (t.tv_sec * 1000) + (t.tv_usec / 1000);
+    return ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - MSG_WineStartTicks;
 }
 
 /***********************************************************************
diff --git a/windows/property.c b/windows/property.c
index 1dcafb8..92d1748 100644
--- a/windows/property.c
+++ b/windows/property.c
@@ -70,7 +70,7 @@
         PROPERTY *prop = (PROPERTY *)USER_HEAP_LIN_ADDR(hProp);
         if (HIWORD(str))
         {
-            if (!prop->atom && !strcasecmp( prop->string, PTR_SEG_TO_LIN(str)))
+            if (!prop->atom && !lstrcmpi( prop->string, PTR_SEG_TO_LIN(str)))
                 return prop->hData;
         }
         else if (prop->atom && (prop->atom == LOWORD(str))) return prop->hData;
@@ -95,7 +95,7 @@
     {
         PROPERTY *prop = (PROPERTY *)USER_HEAP_LIN_ADDR( *hProp );
         if ((HIWORD(str) && !prop->atom &&
-             !strcasecmp( prop->string, PTR_SEG_TO_LIN(str))) ||
+             !lstrcmpi( prop->string, PTR_SEG_TO_LIN(str))) ||
             (!HIWORD(str) && prop->atom && (prop->atom == LOWORD(str))))
         {
             HANDLE hNext = prop->next;
diff --git a/windows/win.c b/windows/win.c
index da50aec..1c7d895 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -13,7 +13,6 @@
 #include "user.h"
 #include "dce.h"
 #include "sysmetrics.h"
-#include "menu.h"
 #include "cursoricon.h"
 #include "event.h"
 #include "message.h"
@@ -481,6 +480,8 @@
     }
     else wndPtr->wIDmenu = (UINT)menu;
 
+    GetSystemMenu( hwnd, TRUE );  /* Create a copy of the system menu */
+
       /* Send the WM_CREATE message */
 
     createStruct.lpCreateParams = (LPSTR)data;
@@ -517,9 +518,6 @@
 	return 0;
     }
 
-      /* Create a copy of SysMenu */
-    if (style & WS_SYSMENU) wndPtr->hSysMenu = CopySysMenu();
-
     WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LONG)hwnd );
 
     /* Show the window, maximizing or minimizing if needed */
diff --git a/windows/winpos.c b/windows/winpos.c
index 659cd2f..3a7eb9f 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -434,6 +434,7 @@
             if (GetActiveWindow()) swpflags |= SWP_NOACTIVATE;
             /* fall through */
 	case SW_SHOWNORMAL:  /* same as SW_NORMAL: */
+	case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
 	case SW_RESTORE:
 	    swpflags |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;