diff --git a/ANNOUNCE b/ANNOUNCE
index 86723e9ff15f0077cdfab9982ccb959f3bf0ca85..703bde4ed4c2803783c278c04a3bd8b48c368d03 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 @@ Because of lags created by using mirror, this message may reach you before
 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 fc9e70be8d7c09e45d523bff16a01b39c40cc7b4..d7a84c28048f2391602a6fcbfac28810ab5bcc74 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,205 @@
+----------------------------------------------------------------------
+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>
 
diff --git a/Makefile.in b/Makefile.in
index faea81911fe7c358da408d199c359bde583c5656..0e3459b91120989d35e7bdb8c6c6abd16e91473e 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -49,6 +49,7 @@ MAIN_TARGET = @MAIN_TARGET@
 COMMONSUBDIRS = \
 	rc \
 	controls \
+	files \
 	ipc \
 	loader \
 	misc \
@@ -72,6 +73,7 @@ ALLSUBDIRS = $(COMMONSUBDIRS) $(EMUSUBDIRS) $(LIBSUBDIRS) libtest
 
 COMMONOBJS = \
 	controls/controls.o \
+	files/files.o \
 	ipc/ipc.o \
 	loader/loader.o \
 	misc/misc.o \
diff --git a/configure b/configure
index 704cc35a345a220b037a99a63c452425a0749df5..0689562737de45c54741060028f28ed7c9af622c 100755
--- a/configure
+++ b/configure
@@ -685,7 +685,6 @@ else
   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 @@ else
   # 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 @@ else
   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_library" && x_direct_test_library=Xt
 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 @@ rm -f conftest*
 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 @@ else
   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 @@ else
   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 @@ else
   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 @@ else
   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 @@ else
   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 @@ else
   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 @@ else
   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 @@ fi
 
 
 
-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 @@ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   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 @@ if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then
   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 @@ if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
   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 @@ EOF
 
 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 @@ rm -f conftest*
 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 @@ fi
 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 @@ if test "$cross_compiling" = yes; then
   :
 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 @@ if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
   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 @@ Makefile
 controls/Makefile
 debugger/Makefile
 debugger/readline/Makefile
+files/Makefile
 if1632/Makefile
 ipc/Makefile
 library/Makefile
@@ -1967,6 +2007,7 @@ Makefile
 controls/Makefile
 debugger/Makefile
 debugger/readline/Makefile
+files/Makefile
 if1632/Makefile
 ipc/Makefile
 library/Makefile
diff --git a/configure.in b/configure.in
index 27490d1f89247c0777d05f3fcf07df32160ec0dc..d8a94c0254dfa9dd473d8735ca918fd248bc73dc 100644
--- a/configure.in
+++ b/configure.in
@@ -29,8 +29,6 @@ dnl **** Check for some programs and libraries ****
 
 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 @@ AC_PROG_INSTALL
 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 @@ Makefile
 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 6c3f320212c3d3ce0c38a062945f7a162c2b0ba2..378115e1de75e08d4d249a269632abc63a1cf0ee 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 @@ BOOL DlgDirSelectComboBox(HWND hDlg, LPSTR lpStr, int nIDLBox)
 /************************************************************************
  * 					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);
-
-  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;
+    INT ret = 0;
+
+    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 b3796f493db9171e8ac2a0b091f5cb3d88de5deb..9f462c6e583a56df23baa95fc8af3f41aeb3a510 100644
--- a/controls/desktop.c
+++ b/controls/desktop.c
@@ -22,18 +22,19 @@ static char Copyright[] = "Copyright  Alexandre Julliard, 1994";
  *
  * 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 @@ BOOL SetDeskPattern(void)
 /***********************************************************************
  *           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 d1b0df792077868477e904250116edc9fbd4730d..7ecd806afc89cd5ef9e32fcd6c6df9270af02c5d 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 ListBoxGetSel(LPHEADLIST lphl, WORD wIndex)
 
 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 @@ BOOL DlgDirSelect(HWND hDlg, LPSTR lpStr, int nIDLBox)
 /************************************************************************
  * 			   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 63f424d4d03b1788f7c3d4e58ba3a66b6b92d9a6..e820d181913d9122b5d77d4dbc4b740f8835a2f5 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -57,7 +57,6 @@ extern void NC_DrawSysButton(HWND hwnd, HDC hdc, BOOL down);  /* nonclient.c */
 static HBITMAP hStdCheck = 0;
 static HBITMAP hStdMnArrow = 0;
 
-HMENU CopySysMenu();
 WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu);
 
 
@@ -102,6 +101,30 @@ static BOOL MENU_HasSysMenu( POPUPMENU *menu )
 }
 
 
+/**********************************************************************
+ *           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 @@ BOOL ChangeMenu(HMENU hMenu, UINT nPos, LPSTR lpNewItem,
     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 @@ HMENU GetSystemMenu(HWND hWnd, BOOL bRevert)
     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;
 }
 
@@ -2180,30 +2205,6 @@ HMENU LoadMenuIndirect(LPSTR menu_template)
 }
 
 
-/**********************************************************************
- *			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)
  */
diff --git a/controls/scroll.c b/controls/scroll.c
index 3d7a67e8db2fcb9876fb032e392a9453fea19b6b..ff63e0830ae58077501f912afa9aa3968103ef04 100644
--- a/controls/scroll.c
+++ b/controls/scroll.c
@@ -770,7 +770,7 @@ LONG ScrollBarWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
             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 e6de8fcc1b34b1586037cfedc85cb92b2636f684..50c66d73d489aa0db26b42b09be7aba131ad285b 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 char *local_symbols[10];
 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 8a325c7a09c85102d914484a19aa7ea3b9d1a49a..60be9104e6b4e23ef7ace809c6540ee630a165ee 100644
--- a/debugger/hash.c
+++ b/debugger/hash.c
@@ -51,7 +51,7 @@ void DEBUG_AddSymbol( const char * name, const DBG_ADDR *addr )
 
     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 9b4e09fe8a4feaba37874c39cf812c6ba1bc0866..de541605b7b9f1a3d732a627187b3582ef5b344f 100644
--- a/debugger/stack.c
+++ b/debugger/stack.c
@@ -66,6 +66,10 @@ void DEBUG_BackTrace(void)
     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 @@ void DEBUG_BackTrace(void)
           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 0000000000000000000000000000000000000000..e51262e39054700291fe74223b993dd7059364d6
--- /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 0000000000000000000000000000000000000000..5fee0609b18c49c25a41941b3264056747248558
--- /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 0000000000000000000000000000000000000000..9de0c5289f62ef4b072baf1ac7003cb3049d29c1
--- /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 0000000000000000000000000000000000000000..6f4e921edbbe1a94ccdbe50c15fc3deaa475b7f1
--- /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 0000000000000000000000000000000000000000..ae2558d6af737a2eee1c51ab32db731468726266
--- /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 0000000000000000000000000000000000000000..19cc6fb7f5715cadddd72d03d50c4d1439e1c0b9
--- /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 b8926e20f8941320410e8d45b03ab9e1c5c3ad35..8cdd78d521267b227adfbde3b70d7fc8c5311afa 100644
--- a/if1632/Makefile.in
+++ b/if1632/Makefile.in
@@ -51,4 +51,20 @@ call32.S: $(SPEC16_FILES)
 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 2d6a742d150bd9814b9a8aab8a011f0513411f14..27d236c510a719da88f65e167b676f08da384255 100644
--- a/if1632/callback.c
+++ b/if1632/callback.c
@@ -37,10 +37,12 @@ LONG CallWindowProc( WNDPROC func, HWND hwnd, WORD message,
                             (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 4249cbd605d2550581928ad83d99a41c3e26b21e..cd6027216f08703a150907ff4885a62743a78329 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -232,7 +232,7 @@ id	3
 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 3ebcb860ca0278b389e23f0e56ffbc95628588cc..86bd082a710ef4aeba03e1a7ad4d8657ee7e5572 100644
--- a/if1632/gdi32.spec
+++ b/if1632/gdi32.spec
@@ -11,7 +11,7 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 2899a60e9b2e3fdb471e9f39bc209b9fb0d4e6a9..d4e789857adc142c1c2f0493dd6ae5e549badd77 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -80,7 +80,7 @@ id	1
 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 @@ id	1
 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 @@ id	1
 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 @@ id	1
 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 e7d35234056e3996300bac1a507a717cbb4d5c66..b1c7193c10302d93b454f02bf82eccc0e7d378c5 100644
--- a/if1632/kernel32.spec
+++ b/if1632/kernel32.spec
@@ -129,7 +129,7 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 67c646173615551c7644fa575c6ac6008c355294..7da3a4751816d320da950c8af4ec4ddb4a432dee 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 @@ WIN32_builtin *RELAY32_GetBuiltinDLL(char *name)
 
 	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 @@ void *RELAY32_GetEntryPoint(char *dll_name, char *item, int hint)
 	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 @@ void *RELAY32_GetEntryPoint(char *dll_name, char *item, int hint)
 		#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 @@ void *RELAY32_GetEntryPoint(char *dll_name, char *item, int hint)
 		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 @@ void *RELAY32_GetEntryPoint(char *dll_name, char *item, int hint)
 	/* 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 3a45fda47d2d71a8cf7dcfddbffa1a6843740930..9bfe141b23fcf81169ef20f9972940f1abca0b2e 100644
--- a/if1632/toolhelp.spec
+++ b/if1632/toolhelp.spec
@@ -31,7 +31,7 @@ id	12
 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 c525e30906d7bb92127f66e996b3d93e245163e3..50f41ee71cfdb9e4edeca3890088d711bce7f538 100644
--- a/if1632/user32.spec
+++ b/if1632/user32.spec
@@ -46,7 +46,7 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 @@ base	1
 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 9789e8a3d8b1f2f6f13d44730869bf5e88fd2000..6bb7b0b34d007524898c08477f55e6afe835de6c 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 be237faba2f62597006dfe71353b7fe3744f3a39..fc7c5cb1fe56d6959b7851b7e0640c5479d43d19 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 0000000000000000000000000000000000000000..c466af8624c81d3c494d9486a1f0ca709a568320
--- /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 1200dfd52d9219143bd5790149b0608bf8c7c1e8..2bcca390f81dc1ddde0cbac81186461a9b17fe3f 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>
-
-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);
+#include <time.h>
+#include "wintypes.h"
+
+#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 0000000000000000000000000000000000000000..ab9fa9d9dc0bf5f8685fc24e7d150ccf8810a16b
--- /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 0000000000000000000000000000000000000000..1c585a4eff4b9e283f396c3c63bdc20849a1d417
--- /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 367a6399c19a8b314545b77c1b0ea8c9a00d5992..ecb4fc60945f71cd79070bddbb55d0287fa5609c 100644
--- a/include/kernel32.h
+++ b/include/kernel32.h
@@ -14,6 +14,7 @@ DWORD ErrnoToLastError(int errno_num);
 /* 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 59f292df5c8a017e1f9078e5dc9b117aa65cee5e..5a25e1e717247a7c04345d9909bb9da1fe8c92dc 100644
--- a/include/menu.h
+++ b/include/menu.h
@@ -15,8 +15,6 @@ extern void MENU_TrackMouseMenuBar( HWND hwnd, POINT pt );       /* menu.c */
 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 85159b0d960b9260f0864037212aa003fb806788..bf242b7f29991157952a39fbb8963184edfd77aa 100644
--- a/include/message.h
+++ b/include/message.h
@@ -63,6 +63,8 @@ typedef struct tagMESSAGEQUEUE
 #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 3ca58cc415060f7c86c945fe7b76b6332328e362..16417541e09925562981c4f4011820c99f83e01a 100644
--- a/include/module.h
+++ b/include/module.h
@@ -112,6 +112,7 @@ typedef struct
 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 5964d82556ccba6c023a2af5adbef76972b31a61..e399be1ae7b09a303f9ff9a4af579336bd385084 100644
--- a/include/msdos.h
+++ b/include/msdos.h
@@ -32,6 +32,22 @@ struct fcb {
 	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 @@ extern struct DosDeviceStruct LPT[MAX_PORTS];
                              *((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 */
-
-/* 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
+#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 */
+
+
+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 b83e6519bd23bf2dd8192ade110b7e5d73d32c51..220f5b23907fd37c143de7fa888fc3802edb0df5 100644
--- a/include/pe_image.h
+++ b/include/pe_image.h
@@ -9,6 +9,10 @@ struct pe_data {
 	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 @@ struct w_files
     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 @@ struct w_files
 
 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 43aa48a9e5782dea65c77fbb1e2e605b422463dd..ff85a08460956d409baaedf5e10ef1fa1981415f 100644
--- a/include/peexe.h
+++ b/include/peexe.h
@@ -167,7 +167,7 @@ struct PE_Export_Directory
   u_long * AddressOfFunctions;
   u_long * AddressOfNames;
   u_short * Address_Of_Name_Ordinals;
-  u_char ModuleName[1];
+/*  u_char ModuleName[1]; */
 };
 
 /*
@@ -213,4 +213,18 @@ struct PE_Resource_Leaf_Entry
 #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 2114b54859b49fa108394b9e95d9bde1a44d005b..93a9567ce53bdeb6832633e90087b020996687fb 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 0000000000000000000000000000000000000000..6a2ac433327dcf735c49e29f2514282c601bde27
--- /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 cf4358bbdf4969531ba452ab6a95a476c6d23981..a9d4020be5c7d1a23c369dfe1537beb5a418ddb4 100644
--- a/include/stackframe.h
+++ b/include/stackframe.h
@@ -66,9 +66,12 @@ extern DWORD IF1632_Original32_esp;
 
   /* 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 fd5604db0f3d95e4c069991f74441dfe2114e656..d2a2b30ebff37a070e0ddf8c13b7d3b1f792b89b 100644
--- a/include/task.h
+++ b/include/task.h
@@ -21,20 +21,23 @@ extern void TASK_KillCurrentTask( int exitCode );
 
 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 @@ typedef struct
     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 5ffb1b4b78476209b8cdcba2235e775e8372d3a5..43d0e7f312814b7523c560981b4f5e74fe0d8826 100644
--- a/include/toolhelp.h
+++ b/include/toolhelp.h
@@ -232,6 +232,15 @@ typedef struct
 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 3934834a878eb26686485df68376ce882d060a58..b7f82984e712e609df40fd58b29d5627c83d97f6 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -765,6 +765,9 @@ typedef struct tagLOGPEN
 #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 *LPKANJISTRUCT;
 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 DRIVE_CANNOTDETERMINE	0
-#define DRIVE_DOESNOTEXIST	1
-#define DRIVE_REMOVABLE	2
-#define DRIVE_FIXED	3
-#define DRIVE_REMOTE	4
+#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
+
+/* 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 @@ typedef struct tagDRAGINFO {
 #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 @@ int        DialogBoxParam(HANDLE,SEGPTR,HWND,WNDPROC,LONG);
 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 @@ HWND       GetParent(HWND);
 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 @@ BOOL       IsDialogMessage(HWND,LPMSG);
 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 @@ DWORD      OffsetWindowOrg(HDC,short,short);
 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 @@ void       SetDCState(HDC,HDC);
 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 @@ int        WriteComm(int,LPSTR,int);
 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 29b6c44101b786abab40acdf374b9702dd5d3d9d..8feab5476c1f7006492c38b3f6ce261a5dda2e85 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 @@ extern int runtime_cpu (void);
 static inline int runtime_cpu(void) { return 3; }
 #endif
 
+#ifndef WINELIB
 
 #if defined ( linux) 
 struct sigcontext_struct
@@ -66,4 +65,6 @@ struct sigcontext_struct
 #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 6223573e55defec4729cf6b392181f44374ea5d4..56a8fadfafddf350ad68de749c8d0a7f956ac3f6 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 @@ extern int PASCAL FAR __WSAFDIsSet(SOCKET, fd_set FAR *);
 /*
  * 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 @@ typedef WSADATA FAR *LPWSADATA;
 #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 30ecb94bc7b7554bfccccca5ef30ab2e0cebfc5c..f0cc840eda0eb9465891d0df061154cb6be3a4e5 100644
--- a/include/wintypes.h
+++ b/include/wintypes.h
@@ -48,6 +48,7 @@ typedef DWORD SEGPTR;
 #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(HTASK);
 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 e8b183df6cd0e66b7eeffeff50e26b745730948c..396fde0527b8e19c2b46d6ccbe87feca91c75837 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 5ca9b4255d4e23d390cbd05636661774822cab9d..6d249084824f9076acdc96b6175425757ee413a8 100644
--- a/ipc/dde_atom.c
+++ b/ipc/dde_atom.c
@@ -66,7 +66,7 @@ static int FindHash(LPCSTR str)	   /* ignore str case */
       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 @@ static int FindHash(LPCSTR str)	   /* ignore str case */
 	    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 48fbfbe3d0d50d9e23bdf7ee294b5465a7923e83..a87f938f0a818dfd277611a87a1ab5e0a17fd9dc 100644
--- a/library/atom.c
+++ b/library/atom.c
@@ -80,7 +80,7 @@ static ATOM ATOM_AddAtom( ATOMtoHANDLEtable** tableptr, SEGPTR name )
 	  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 @@ static ATOM ATOM_FindAtom( ATOMtoHANDLEtable** tableptr, SEGPTR name )
       {
 	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 5f4c5b52c5b7aac6da962bc9d95398d0b732506e..0d1511ec79fd41b462491bc013a1f4aaa93e3e11 100644
--- a/library/libres.c
+++ b/library/libres.c
@@ -101,7 +101,6 @@ LPVOID LIBRES_LockResource( HGLOBAL handle )
  */
 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 8f62d4ca15ceefaef723811c2a34820748a557f4..c1cb479012fa4bdf118b838a04ce32fcf755d350 100644
--- a/library/miscstubs.c
+++ b/library/miscstubs.c
@@ -45,7 +45,7 @@ WORD CallTo16_word_ ( FARPROC func, WORD arg ) { return func(arg); }
 
 void GlobalFreeAll(HANDLE owner)
 {
-  fprintf(stderr,"JBP: GlobalFreeAll() ignored.\n");
+  WINELIB_UNIMP("GlobalFreeAll()");
 }
 
 SEGPTR WIN16_GlobalLock(HGLOBAL h) 
@@ -65,7 +65,7 @@ WORD LOCAL_Size( WORD ds, HLOCAL handle )
 
 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 @@ HGLOBAL GLOBAL_CreateBlock( WORD flags, const void *ptr, DWORD size,
 			    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 @@ HGLOBAL GlobalHandle(LPCVOID a)
 
 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 @@ LRESULT ErrorProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
 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 @@ WNDPROC GetWndProcEntry16( char *name )
   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 a481683285c33b4c9ab216db981a0d2546f0beaf..0000000000000000000000000000000000000000
--- 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 fc71f796952759b7a4072691cd4b5fe85b877c26..2f5212c8cbbae49bead0bfd98baeb1dc9829e508 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 de7df1efb326507f31b7963c67f38a174a1f6c8d..8ee5a4e145a67bf006bd82d6b3439bffe3a94181 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -20,12 +20,13 @@ static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
 #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 @@ int MAIN_Init(void)
       /* 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 d46529dee6f2d00b14d4719458af0fbb6af702b4..5c9557a0aa2ef9f0d262191d22dddfbce1366e2e 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 @@ static HMODULE MODULE_LoadBuiltin( LPCSTR name, BOOL force )
     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 @@ BOOL MODULE_Init(void)
         !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 @@ int MODULE_OpenFile( HMODULE hModule )
 {
     NE_MODULE *pModule;
     char *name;
+    const char *unixName;
 
     static int cachedfd = -1;
 
@@ -271,19 +270,21 @@ int MODULE_OpenFile( HMODULE hModule )
     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;
@@ -812,6 +813,17 @@ LPSTR MODULE_GetModuleName( HMODULE hModule )
 }
 
 
+/**********************************************************************
+ *           MODULE_RegisterModule
+ */
+void MODULE_RegisterModule( HMODULE hModule )
+{
+	NE_MODULE *pModule;
+	pModule = (NE_MODULE *)GlobalLock( hModule );
+	pModule->next = hFirstModule;
+	hFirstModule = hModule;
+}
+
 /**********************************************************************
  *	    MODULE_FindModule
  *
@@ -837,10 +849,10 @@ HMODULE MODULE_FindModule( LPCSTR path )
         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 @@ HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
         /* 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 @@ HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
 
           /* 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 @@ HANDLE LoadLibrary( LPCSTR libname )
     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 eff083efbff12dbf22cdd65407d3b5b22b6a5212..80eea87e9ab2add89ed422f9a1e91fb60de2dff0 100644
--- a/loader/ne_image.c
+++ b/loader/ne_image.c
@@ -508,6 +508,11 @@ void NE_InitializeDLLs( HMODULE hModule )
     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 caf1e0da99786a626c2a0ad4347b436599ccd90e..5eee68293e0fe68439bc485e09f29fd5e9e99063 100644
--- a/loader/ne_resource.c
+++ b/loader/ne_resource.c
@@ -67,8 +67,8 @@ static DWORD NE_FindNameTableId( HMODULE hModule, SEGPTR typeId, SEGPTR resId )
                 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 @@ static DWORD NE_FindNameTableId( HMODULE hModule, SEGPTR typeId, SEGPTR resId )
                 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 @@ static HRSRC NE_FindResourceFromType( NE_MODULE *pModule,
         {
             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 @@ HRSRC NE_FindResource( HMODULE hModule, SEGPTR typeId, SEGPTR resId )
             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 @@ int NE_AccessResource( HMODULE hModule, HRSRC hRsrc )
 {
     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 8a05457afa8ab3af7a14c6b631d992efab49cba0..f7f3f72fdcc14a8fcbc5f71b11b8c3b54c53d73c 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 @@ void my_wcstombs(char * result, u_short * source, int len)
   };
 }
 
+#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 @@ char * xmmap(char * vaddr, unsigned int v_size, unsigned int r_size,
   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 dump_exports(struct PE_Export_Directory * pe_exports, unsigned int load_add
     }
 }
 
-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 @@ void fixup_imports(struct PE_Import_Directory *pe_imports,unsigned int load_addr
       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 @@ void fixup_imports(struct PE_Import_Directory *pe_imports,unsigned int load_addr
 	  }
 	  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 @@ void fixup_imports(struct PE_Import_Directory *pe_imports,unsigned int load_addr
 	  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 @@ static void dump_table(struct w_files *wpnt)
 	     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 @@ HINSTANCE PE_LoadImage(struct w_files *wpnt)
 		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 @@ HINSTANCE PE_LoadImage(struct w_files *wpnt)
 	    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 @@ HINSTANCE PE_LoadModule(int fd, OFSTRUCT *ofs, LOADPARAMS* params)
 
 	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 @@ HINSTANCE PE_LoadModule(int fd, OFSTRUCT *ofs, LOADPARAMS* params)
 	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 @@ HINSTANCE PE_LoadModule(int fd, OFSTRUCT *ofs, LOADPARAMS* params)
 	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 @@ int PE_UnloadImage(struct w_files *wpnt)
 	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 b9a356d187871bafc0b86bdb4d855c662017720a..b0d62035857b00e58ee8d542b617f3b9503b729c 100644
--- a/loader/pe_resource.c
+++ b/loader/pe_resource.c
@@ -72,7 +72,7 @@ find_resource(char *root, struct PE_Resource_Directory *resource,
 			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 @@ find_type(struct PE_Resource_Directory *resource, LPSTR resource_name,
 			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 e7f2835d3b9559e45bae6043b90a94796b2df621..5e45faf3decdcd1965135caa80da9881dc42fbf8 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 HANDLE TASK_CreateDOSEnvironment(void)
 {
     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 @@ static HANDLE TASK_CreateDOSEnvironment(void)
 
     /* 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 @@ static HANDLE TASK_CreateDOSEnvironment(void)
 
     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 @@ static HANDLE TASK_CreateDOSEnvironment(void)
     /* 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 @@ static void TASK_CreateThunks( HGLOBAL handle, WORD offset, WORD count )
  *
  * Allocate a thunk for MakeProcInstance().
  */
+#ifndef WINELIB32
 static SEGPTR TASK_AllocThunk( HTASK hTask )
 {
     TDB *pTask;
@@ -275,6 +290,7 @@ static SEGPTR TASK_AllocThunk( HTASK hTask )
     pThunk->free = *(WORD *)((BYTE *)pThunk + pThunk->free);
     return MAKELONG( base, sel );
 }
+#endif
 
 
 /***********************************************************************
@@ -282,6 +298,7 @@ static SEGPTR TASK_AllocThunk( HTASK hTask )
  *
  * Free a MakeProcInstance() thunk.
  */
+#ifndef WINELIB32
 static BOOL TASK_FreeThunk( HTASK hTask, SEGPTR thunk )
 {
     TDB *pTask;
@@ -303,6 +320,7 @@ static BOOL TASK_FreeThunk( HTASK hTask, SEGPTR thunk )
     pThunk->free = LOWORD(thunk) - base;
     return TRUE;
 }
+#endif
 
 
 /***********************************************************************
@@ -335,10 +353,7 @@ static void TASK_CallToStart(void)
     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 @@ static void TASK_CallToStart(void)
                    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 @@ HTASK TASK_CreateTask( HMODULE hModule, HANDLE hInstance, HANDLE hPrevInstance,
     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 @@ HTASK TASK_CreateTask( HMODULE hModule, HANDLE hInstance, HANDLE hPrevInstance,
     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 @@ static void TASK_DeleteTask( HTASK hTask )
 
     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 @@ void TASK_Reschedule(void)
 /***********************************************************************
  *           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 @@ void InitTask( struct sigcontext_struct context )
     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 @@ void InitTask( struct sigcontext_struct context )
     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 @@ HTASK LockCurrentTask( BOOL bLock )
 /***********************************************************************
  *           IsTaskLocked  (KERNEL.122)
  */
-WORD IsTaskLocked(void)
+HTASK IsTaskLocked(void)
 {
     return hLockedTask;
 }
@@ -905,6 +932,9 @@ void Yield(void)
  */
 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 @@ FARPROC MakeProcInstance( FARPROC func, HANDLE hInstance )
                   (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 @@ FARPROC MakeProcInstance( FARPROC func, HANDLE hInstance )
  */
 void FreeProcInstance( FARPROC func )
 {
+#ifndef WINELIB32
     dprintf_task( stddeb, "FreeProcInstance("SPFMT")\n", (SEGPTR)func );
     TASK_FreeThunk( hCurrentTask, (SEGPTR)func );
+#endif
 }
 
 
@@ -953,8 +984,6 @@ HANDLE GetCodeHandle( FARPROC proc )
     else
         handle = GlobalHandle( HIWORD(proc) );
 
-    printf( "STUB: GetCodeHandle(%08lx) returning "NPFMT"\n",
-            (DWORD)proc, handle );
     return handle;
 }
 
@@ -1049,6 +1078,21 @@ int GetInstanceData( HANDLE instance, WORD buffer, int len )
 }
 
 
+/***********************************************************************
+ *           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)
  */
@@ -1108,6 +1152,8 @@ HMODULE GetExePtr( HANDLE handle )
 
     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 @@ HMODULE GetExePtr( HANDLE handle )
     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 359158c2a8cbbad84e3c8faa64d34cbe14874230..0e42c92a414f6add396af453c302f96d9ac66713 100644
--- a/memory/atom.c
+++ b/memory/atom.c
@@ -146,7 +146,7 @@ static ATOM ATOM_AddAtom( WORD selector, SEGPTR name )
     {
 	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 @@ static ATOM ATOM_FindAtom( WORD selector, SEGPTR name )
     {
 	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 6d540a374626a8196bb3a70d8d067f2f428d0978..680e9fb10530864fb814073b1c53162ce3576198 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 GlobalEntryModule( GLOBALENTRY *pGlobal, HMODULE hModule, WORD wSeg )
  */
 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 9500f2bd51f896368075421dadc80fa377da659c..bc1c96facae4e1e7419fcd24796dc430b052b301 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 d6c2db187dfe7001d8084ccad8b45b1f20589368..bbf2e441349125790d5cf0d1edaef7d3a6de7c4c 100644
--- a/memory/selector.c
+++ b/memory/selector.c
@@ -442,3 +442,37 @@ DWORD MemoryWrite( WORD sel, DWORD offset, void *buffer, DWORD count )
     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 d6374a565d4f641a7b0b10f944431aeea21f3f74..7d0a546743141eed81343966749fbbd5f171421e 100644
--- a/misc/Makefile.in
+++ b/misc/Makefile.in
@@ -10,7 +10,6 @@ C_SRCS = \
 	driver.c \
 	exec.c \
 	escape.c \
-	file.c \
 	keyboard.c \
 	lstr.c \
 	main.c \
@@ -20,6 +19,7 @@ C_SRCS = \
 	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 06501cc4c5051506f79a34821d79177a0b86f486..107ec99f32d03b7f3fce4c52b6c1c0c40b7840b5 100644
--- a/misc/comm.c
+++ b/misc/comm.c
@@ -136,7 +136,7 @@ int BuildCommDCB(LPSTR device, DCB FAR *lpdcb)
 		"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 @@ int OpenComm(LPSTR device, UINT cbInQueue, UINT cbOutQueue)
 		"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 @@ int OpenComm(LPSTR device, UINT cbInQueue, UINT cbOutQueue)
 		}
 	} 
 	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 d147dde9b3c64b5b92b3ad8a38f4ecc6dc6557d3..8991597f0140754c4f2c8b5f2a95c4887a45e275 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 @@ static BOOL FILEDLG_ScanDir(HWND hWnd, LPSTR newPath)
   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 @@ static LONG FILEDLG_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
   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 @@ static LRESULT FILEDLG_WMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
   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 @@ static LRESULT FILEDLG_WMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
       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 @@ static LRESULT FILEDLG_WMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
 	}
       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 @@ static LRESULT FILEDLG_WMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
 	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 6235df63f38cd48f29760199014b27e263318597..b01f6b0177046c821e46501bee7f54ff74095894 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 @@ static void ExpandTildeString(char *s)
     *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 @@ int DOS_GetFreeSpace(int drive, long *size, long *available)
 #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 @@ char *WineIniFileName(void)
 	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 888701a46e5fb7a5e0b233f37ee7db05ce27296f..0000000000000000000000000000000000000000
--- 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 5d03363441f8da9b83e735dbc4b220329373668c..5f7c90adde43fe73836adc65c2010e0102199bb5 100644
--- a/misc/lstr.c
+++ b/misc/lstr.c
@@ -66,17 +66,36 @@ SEGPTR lstrcat( SEGPTR target, SEGPTR source )
 /* 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 @@ SEGPTR lstrcpy( SEGPTR target, SEGPTR source )
 }
 
 /* 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 9226c084d803d62ad5816544adf9c7d1059c39e3..0d9e9481c1fee04252a9a7e2c509d77af1322035 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 @@ BOOL ParseDebugOptions(char *options)
       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 @@ BOOL ParseDebugOptions(char *options)
       {
 	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 @@ static BOOL MAIN_ParseDLLOptions(char *options)
       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 @@ static void MAIN_ParseLanguageOption( char *arg )
     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 @@ static void MAIN_ParseOptions( int *argc, char *argv[] )
 #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 main( int argc, char *argv[] )
     int ret_val;
     int depth_count, i;
     int *depth_list;
+    struct timeval tv;
 
     extern int _WinMain(int argc, char **argv);
 
@@ -557,6 +559,8 @@ int main( int argc, char *argv[] )
     setbuf(stderr,NULL);
 
     setlocale(LC_CTYPE,"");
+    gettimeofday( &tv, NULL);
+    MSG_WineStartTicks = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
 
     XrmInitialize();
     
@@ -603,11 +607,7 @@ int main( int argc, char *argv[] )
     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 b798a5e44c585afdf03e85afa95cd15825298291..68407555380c8613558924b2a81addc321388a24 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 WNetUnlockQueueData(LPSTR szQueue)
 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 b02fe65a829cbad85173508d4d4f303c160657cb..8100e5efac110611860efdb15223aa4db8cd75fc 100644
--- a/misc/ole2nls.c
+++ b/misc/ole2nls.c
@@ -460,7 +460,7 @@ int CompareStringA(DWORD lcid, DWORD fdwStyle,
 	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 0000000000000000000000000000000000000000..52ac9d971dadd90bb3835d354b5c9f12c2a12190
--- /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 ecd1b72a0311dd0bb62f336f91adb09a3f9c4541..4790c0155486a211aff5630de10d5cbfaf697b90 100644
--- a/misc/profile.c
+++ b/misc/profile.c
@@ -58,7 +58,7 @@ static TSecHeader *is_loaded (char *FileName)
     TProfile *p = Base;
     
     while (p){
-	if (!strcasecmp (FileName, p->FileName)){
+	if (!lstrcmpi( FileName, p->FileName)){
 	    Current = p;
 	    return p->Section;
 	}
@@ -67,6 +67,26 @@ static TSecHeader *is_loaded (char *FileName)
     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 @@ static char *GetIniFileName(char *name, char *dir)
 	}
 	else
 	  strcpy(temp, name);
-	return DOS_GetUnixFileName(temp);
+	return DOSFS_GetUnixFileName(temp,TRUE);
 }
 
 static TSecHeader *load (char *filename, char **pfullname)
@@ -103,26 +123,27 @@ static TSecHeader *load (char *filename, char **pfullname)
 
     /* 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 @@ static TSecHeader *load (char *filename, char **pfullname)
 	    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 @@ static TSecHeader *load (char *filename, char **pfullname)
       }
     }
     
-    *pfullname = strdup(file);
+    *pfullname = xstrdup(file);
     dprintf_profile(stddeb,"Loading %s\n", file);
 
     firstbrace = TRUE;
@@ -205,7 +230,7 @@ static TSecHeader *load (char *filename, char **pfullname)
 	    *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 @@ static TSecHeader *load (char *filename, char **pfullname)
 	    	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 @@ static TSecHeader *load (char *filename, char **pfullname)
 		}
 	    } 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 @@ static void new_key (TSecHeader *section, char *KeyName, char *Value)
     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 @@ static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName,
     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 @@ static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName,
 
     /* 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 @@ static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName,
 	}
 	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 @@ static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName,
     /* 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 @@ static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName,
     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 @@ short GetPrivateProfileString (LPSTR AppName, LPSTR KeyName,
 	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 @@ WORD GetPrivateProfileInt (LPSTR AppName, LPSTR KeyName, short Default,
     
     /* 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 5e50505bb7d5b91eeea5174677090a5d53214b04..0d4869896195937b916cff5b52bacb3330a7756a 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -150,11 +150,11 @@ _LoadLevel(FILE *f,LPKEYSTRUCT lpKey,int tabsexp,char *buf)
 			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 @@ _LoadLevel(FILE *f,LPKEYSTRUCT lpKey,int tabsexp,char *buf)
 		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 @@ LONG RegCreateKey(HKEY hKey, LPCSTR lpSubKey, HKEY FAR *lphKey)
 	  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 e547e1c023c378b9833eaa9f8eb053f728393af2..3a92d62a0b4fc6af887b710dabe9ad7217fcede6 100644
--- a/misc/spy.c
+++ b/misc/spy.c
@@ -539,7 +539,7 @@ void SpyInit(void)
 	    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 1005ffd154e4d390da095f41a403af52085250c6..27bd40c544fb44c7535166beadeddc4dc1bdce1d 100644
--- a/misc/user.c
+++ b/misc/user.c
@@ -73,6 +73,26 @@ BOOL SystemHeapInfo( SYSHEAPINFO *pHeapInfo )
 }
 
 
+/***********************************************************************
+ *           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
  */
diff --git a/misc/user32.c b/misc/user32.c
index 5deaa83f07a69cda6c410e00cad30eb48bbd3af2..5097b8c231bfc410c2657154a46a9a6939cc20c7 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 @@ static void MSG32to16(struct WIN32_MSG *msg32,MSG *msg16)
 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 @@ ATOM USER32_RegisterClassA(WNDCLASSA* wndclass)
 	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;
 }
 
 /***********************************************************************
@@ -140,6 +147,16 @@ LONG USER32_DispatchMessageA(struct WIN32_MSG* lpmsg)
 	return ret;
 }
 
+/***********************************************************************
+ *         TranslateMessage       (USER32.555)
+ */
+BOOL USER32_TranslateMessage(struct WIN32_MSG* lpmsg)
+{
+	MSG msg;
+	MSG32to16(lpmsg,&msg);
+	return TranslateMessage(&msg);
+}
+
 /***********************************************************************
  *         CreateWindowExA        (USER32.82)
  */
@@ -147,16 +164,34 @@ 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 536e5db2b498b44ed9aa65df4ca82076d692b88a..0586e5260d7d47931a2a34ace237d349e1543af1 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 key_t wine_key = 0;
 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 @@ SOCKET WINSOCK_socket(INT af, INT type, INT protocol)
     }
     
     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 @@ static void recv_message(int sig)
 		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 @@ static void send_message( HWND hWnd, u_int wMsg, HANDLE handle, long lParam)
 
 	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 @@ HANDLE WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port, const char
 
 INT WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent)
 {
-	long event;
-	fd_set read_fds, write_fds, except_fds;
-
-	dprintf_winsock(stddeb, "WSA_AsyncSelect: socket %d, HWND "NPFMT", wMsg %d, event %ld\n", s, hWnd, wMsg, lEvent);
-
-	/* remove outstanding asyncselect() processes */
-	/* kill */
-
-	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 (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);
-
-			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);
-		}
-	}
+    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);
+
+    /* remove outstanding asyncselect() processes */
+    /* kill */
+
+    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 (lEvent & FD_READ)
+                FD_SET(s, &read_fds);
+            if (lEvent & FD_WRITE)
+                FD_SET(s, &write_fds);
+
+            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;
+            send_message(hWnd, wMsg, s, WSAMAKESELECTREPLY(event,errors));
+        }
+    }
 }
 
 INT WSAFDIsSet(INT fd, fd_set *set)
@@ -1183,7 +1182,7 @@ INT WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
     /* 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 @@ INT WSACleanup(void)
 
 	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 24dcef587940284e9ab68bee096b4823a16a9a11..58b9681359daa059974c461f573af830ea5a56da 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 @@ xrealloc (void *ptr, size_t size)
     }
     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 436c35b44e999970caf174944a107b2e247ac1e9..bde9e366c64533ec1c638fff9580f413e2d8693a 100644
--- a/miscemu/cpu.c
+++ b/miscemu/cpu.c
@@ -23,7 +23,7 @@ int runtime_cpu (void)
 	{
 	  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 1ba8f1a42bac40c69f8bf8b683dc769bb3a80223..760be10304d6bddc9b6d7d86d51f817b5e6f18fb 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 @@ void INT_Int31Handler( struct sigcontext_struct context )
     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 8b795a960cff02aa04c15134b3799dd9afb638aa..14ac461321e732396eece8af0024f08abe736197 100644
--- a/miscemu/instr.c
+++ b/miscemu/instr.c
@@ -426,8 +426,7 @@ BOOL INSTR_EmulateInstruction( struct sigcontext_struct *context )
                           (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 143e04aba0f2b0a9d5070c845d53c823bb936fd0..16b5f8f9864439f2394ee66dc054585526898dd2 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 @@ extern char TempDirectory[];
 
 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 CreateBPB(int drive, BYTE *data)
 
 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 (!DOS_ValidDrive(drive)) {
-		Error(InvalidDrive, EC_MediaError , EL_Disk);
-		AX_reg(context) = 0xffff;
-		return;
-	}
+    if (!DRIVE_IsValid(drive))
+    {
+        DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk );
+        AX_reg(context) = 0xffff;
+        return;
+    }
 	
-	if (!DOS_GetFreeSpace(drive, &size, &available)) {
-		Error(GeneralFailure, EC_MediaError , 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;
+    if (!DOS_GetFreeSpace(drive, &size, &available)) {
+        DOS_ERROR( ER_GeneralFailure, EC_MediaError, SA_Abort, EL_Disk );
+        AX_reg(context) = 0xffff;
+        return;
+    }
 
-	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 GetDriveAllocInfo(struct sigcontext_struct *context)
 
 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 GetDrivePB(struct sigcontext_struct *context, int drive)
         }
 }
 
-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 @@ static void ioctlGetDeviceInfo(struct sigcontext_struct *context)
         {
 		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 ioctlGetDeviceInfo(struct sigcontext_struct *context)
 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 @@ static void INT21_GetSystemTime(struct sigcontext_struct *context)
 					/* 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 @@ void OpenExistingFile(struct sigcontext_struct *context)
 	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 @@ void ExtendedOpenCreateFile(struct sigcontext_struct *context)
   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 @@ void ExtendedOpenCreateFile(struct sigcontext_struct *context)
   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 @@ void ExtendedOpenCreateFile(struct sigcontext_struct *context)
       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)));
-	
-	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);
-}
 
 
-static void MakeDir(struct sigcontext_struct *context)
+static int INT21_RenameFile(struct sigcontext_struct *context)
 {
-	char *dirname;
+    const char *newname, *oldname;
+    char *buffer;
 
-	dprintf_int(stddeb,"int21: makedir %s\n", (char *)PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)) );
+    /* 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)));
 	
-	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;
-	}
-
-	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);
+    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 ChangeDir(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 void RemoveDir(struct sigcontext_struct *context)
+static void INT21_ChangeDir(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;
-	}
+    int drive;
+    char *dirname = PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context));
 
-/*
-	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);
+    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 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)
+static int INT21_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);
+    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 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);
+static int INT21_FindNext(struct sigcontext_struct *context)
+{
+    FINDFILE_DTA *dta = (FINDFILE_DTA *)GetCurrentDTA();
+    DOS_DIRENT entry;
+    int count;
 
-	RESET_CFLAG(context);
+    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 void SetFileDateTime(struct sigcontext_struct *context)
+
+static int INT21_SetFileDateTime(struct sigcontext_struct *context)
 {
-	char *filename;
-	struct utimbuf filetime;
+    fprintf( stderr, "INT21_SetFileDateTime: not implemented yet.\n" );
+    return 1;
+#if 0
+    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;
+    /* 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 );
 
-	utime(filename, &filetime);
-	RESET_CFLAG(context);
+    filetime.actime = 0L;
+    filetime.modtime = filetime.actime;
+    
+    utime(filename, &filetime);
+    RESET_CFLAG(context);
+#endif
 }
 
-static void CreateTempFile(struct sigcontext_struct *context)
+
+static int INT21_CreateTempFile(struct sigcontext_struct *context)
 {
-	char temp[256];
-	int handle;
-	static int counter = 0;
+    static int counter = 0;
+    char *name = PTR_SEG_OFF_TO_LIN( DS_reg(context), DX_reg(context) );
+    char *p = name + strlen(name);
 
-	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)
-{
-	int drive;
 
-	if (DL_reg(context) == 0) drive = DOS_GetDefaultDrive();
-	else drive = DL_reg(context) - 1;
+static int INT21_GetCurrentDirectory(struct sigcontext_struct *context)
+{
+    int drive = DOS_GET_DRIVE( DL_reg(context) );
+    char *ptr = (char *)PTR_SEG_OFF_TO_LIN( DS_reg(context), SI_reg(context) );
 
-	if (!DOS_ValidDrive(drive))
-        {
-            Error( InvalidDrive, EC_NotFound, EL_Disk );
-            AX_reg(context) = InvalidDrive;
-            SET_CFLAG(context);
-            return;
-	}
+    if (!DRIVE_IsValid(drive))
+    {
+        DOS_ERROR( ER_InvalidDrive, EC_NotFound, SA_Abort, EL_Disk );
+        return 0;
+    }
 
-	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)
-{
-	int drive;
-	BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
-	DWORD serialnumber;
-	
-	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);
+static int INT21_GetDiskSerialNumber(struct sigcontext_struct *context)
+{
+    BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
+    int drive = DOS_GET_DRIVE( BL_reg(context) );
 	
-	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)
-{
-	int drive;
-	BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
-	DWORD serialnumber;
-
-	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;
-	}
+static int INT21_SetDiskSerialNumber(struct sigcontext_struct *context)
+{
+    BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
+    int drive = DOS_GET_DRIVE( BL_reg(context) );
 
-	serialnumber = dataptr[1] + (dataptr[2] << 8) + (dataptr[3] << 16) + 
-			(dataptr[4] << 24);
+    if (!DRIVE_IsValid(drive))
+    {
+        DOS_ERROR( ER_InvalidDrive, EC_NotFound, SA_Abort, EL_Disk );
+        return 0;
+    }
 
-	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 @@ static void FindFirstFCB(struct sigcontext_struct *context)
 	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 @@ static void FindFirstFCB(struct sigcontext_struct *context)
 	      {
 		*(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 @@ static void FindFirstFCB(struct sigcontext_struct *context)
 	    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 @@ static void DeleteFileFCB(struct sigcontext_struct *context)
 		return;
 	}
 
-	strcpy(temp, DOS_GetCurrentDir(drive) );
+        temp[0] = '\\';
+	strcpy(temp+1, DRIVE_GetDosCwd(drive) );
 	strcat(temp, "\\");
 	
 	ptr = temp + strlen(temp);
@@ -1126,23 +876,22 @@ static void DeleteFileFCB(struct sigcontext_struct *context)
 	}
 	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 @@ static void RenameFileFCB(struct sigcontext_struct *context)
 		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 @@ static void RenameFileFCB(struct sigcontext_struct *context)
 	}
 	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 @@ static void fLock (struct sigcontext_struct * context)
 
       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;
-
-  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); 
+    const char *unixName;
+
+    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 @@ extern void LOCAL_PrintHeap (WORD ds);
  */
 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 
-    {
-	Error (0,0,0);
-	switch(AH_reg(&context)) 
-	{
-	  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;
+        AX_reg(&context) = DOS_ExtendedError;
+        BH_reg(&context) = DOS_ErrorClass;
+        BL_reg(&context) = DOS_ErrorAction;
+        CH_reg(&context) = DOS_ErrorLocus;
+        return;
+    }
 
-	  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;
+    DOS_ERROR( 0, 0, 0, 0 );
+    RESET_CFLAG(&context);  /* Not sure if this is a good idea */
 
-	  case 0x18: /* NULL FUNCTIONS FOR CP/M COMPATIBILITY */
-	  case 0x1d:
-	  case 0x1e:
-	  case 0x20:
-	  case 0x6b: /* NULL FUNCTION */
-            AL_reg(&context) = 0;
-	    break;
+    switch(AH_reg(&context)) 
+    {
+    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 */
+    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 0x5c: /* "FLOCK" - RECORD LOCKING */
-	    fLock(&context);
-	    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 0x11: /* FIND FIRST MATCHING FILE USING FCB */
-            FindFirstFCB(&context);
-            break;
-
-	  case 0x13: /* DELETE FILE USING FCB */
-            DeleteFileFCB(&context);
-            break;
+    case 0x5c: /* "FLOCK" - RECORD LOCKING */
+        fLock(&context);
+        break;
+
+    case 0x0d: /* DISK BUFFER FLUSH */
+        RESET_CFLAG(&context); /* dos 6+ only */
+        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 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 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 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 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 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 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 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 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 0x32: /* GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE */
-	    GetDrivePB(&context, (DL_reg(&context) == 0) ?
-                                (DOS_GetDefaultDrive()) : (DL_reg(&context)-1));
-	    break;
-
-	  case 0x33: /* MULTIPLEXED */
-	    switch (AL_reg(&context))
-            {
+    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 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 0x00: /* GET CURRENT EXTENDED BREAK STATE */
                 DL_reg(&context) = 0;
 		break;
@@ -1458,403 +1188,495 @@ void DOS3Call( struct sigcontext_struct context )
 	      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 */
-            {
-                SEGPTR addr = INT_GetHandler( AL_reg(&context) );
-                ES_reg(&context) = SELECTOROF(addr);
-                BX_reg(&context) = OFFSETOF(addr);
-            }
-	    break;
+    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 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 0x38: /* GET COUNTRY-SPECIFIC INFORMATION */
+        AX_reg(&context) = 0x02; /* no country support available */
+        SET_CFLAG(&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 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 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 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 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 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 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 0x3d: /* "OPEN" - OPEN EXISTING FILE */
+        OpenExistingFile(&context);
+        break;
 
-              case 0x0d:
-                ioctlGenericBlkDevReq(&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 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 */
+    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)
+            {
+                AX_reg(&context) = DOS_ExtendedError;
                 SET_CFLAG(&context);
                 break;
-                
-	      default:
-                INT_BARF( &context, 0x21 );
-		break;
-	    }
-	    break;
+            }
+            AX_reg(&context) = LOWORD(status);
+            DX_reg(&context) = HIWORD(status);
+        }
+        break;
 
-	  case 0x45: /* "DUP" - DUPLICATE FILE HANDLE */
-            if ((AX_reg(&context) = dup(BX_reg(&context))) == 0xffff)
+    case 0x43: /* FILE ATTRIBUTES */
+        switch (AL_reg(&context))
+        {
+        case 0x00:
+            if (!INT21_GetFileAttribute(&context))
             {
-                errno_to_doserr();
-                AX_reg(&context) = ExtendedError;
+                AX_reg(&context) = DOS_ExtendedError;
                 SET_CFLAG(&context);
             }
-            else RESET_CFLAG(&context);
-	    break;
+            break;
+        case 0x01:
+            RESET_CFLAG(&context);
+            break;
+        }
+        break;
+	
+    case 0x44: /* IOCTL */
+        switch (AL_reg(&context))
+        {
+        case 0x00:
+            ioctlGetDeviceInfo(&context);
+            break;
+
+        case 0x01:
+            break;
 
-	  case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */
-            if (dup2( BX_reg(&context), CX_reg(&context) ) == -1)
+        case 0x08:   /* Check if drive is removable. */
+            switch(GetDriveType( DOS_GET_DRIVE( BL_reg(&context) )))
             {
-                errno_to_doserr();
-                AX_reg(&context) = ExtendedError;
+            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;
             }
-            else RESET_CFLAG(&context);
             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 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 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 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 0x4f: /* "FINDNEXT" - FIND NEXT MATCHING FILE */
-	    FindNext(&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 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 0x0d:
+            ioctlGenericBlkDevReq(&context);
+            break;
 
-	  case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
-            ES_reg(&context) = 0x0;
-            BX_reg(&context) = 0x0;
+        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;
-		
-	  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;
+                
+        default:
+            INT_BARF( &context, 0x21 );
+            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 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 0x5b: /* CREATE NEW FILE */
-	    CreateNewFile(&context);
-	    break;
+    case 0x48: /* ALLOCATE MEMORY */
+    case 0x49: /* FREE MEMORY */
+    case 0x4a: /* RESIZE MEMORY BLOCK */
+        INT_BARF( &context, 0x21 );
+        break;
 	
-	  case 0x5d: /* NETWORK */
-	  case 0x5e:
-	    /* network software not installed */
-	    AX_reg(&context) = NoNetwork;
-	    SET_CFLAG(&context);
-	    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 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 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
+        TASK_KillCurrentTask( AL_reg(&context) );
+        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 0x4d: /* GET RETURN CODE */
+        AX_reg(&context) = 0; /* normal exit */
+        break;
 
-	  case 0x61: /* UNUSED */
-	  case 0x63: /* UNUSED */
-	  case 0x64: /* OS/2 DOS BOX */
-	  case 0x65: /* GET EXTENDED COUNTRY INFORMATION */
-            INT_BARF( &context, 0x21 );
+    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) ))
+            {
+                AX_reg(&context) = DOS_ExtendedError;
+                SET_CFLAG(&context);
+            }
             break;
-	
-	  case 0x66: /* GLOBAL CODE PAGE TABLE */
-	    switch (AL_reg(&context))
+        case 0x01:
+            if (!INT21_SetFileDateTime(&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;
+                AX_reg(&context) = DOS_ExtendedError;
+                SET_CFLAG(&context);
+            }
+            break;
+        }
+        break;
 
-	  case 0x67: /* SET HANDLE COUNT */			
-	    RESET_CFLAG(&context);
-	    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 0x68: /* "FFLUSH" - COMMIT FILE */
-	  case 0x6a: /* COMMIT FILE */
-            fsync( BX_reg(&context) );
-	    RESET_CFLAG(&context);
-	    break;		
-	
-	  case 0x69: /* DISK SERIAL NUMBER */
-	    switch (AL_reg(&context))
-	    {
-	      case 0x00:
-		GetDiskSerialNumber(&context);
-		break;			
-	      case 0x01: 
-		SetDiskSerialNumber(&context);
-		break;
-	    }
-	    break;
-    
-	  case 0x6C: /* Extended Open/Create*/
-	    ExtendedOpenCreateFile(&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) ))
+            {
+                DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk );
+                AX_reg(&context) = DOS_ExtendedError;
+                SET_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;
+
+        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 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 */
+    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 0xea: /* NOVELL NETWARE - RETURN SHELL VERSION */
-	    break;
+    case 0x67: /* SET HANDLE COUNT */
+        SetHandleCount( BX_reg(&context) );
+        if (DOS_ExtendedError)
+        {
+            AX_reg(&context) = DOS_ExtendedError;
+            SET_CFLAG(&context);
+        }
+        break;
 
-	  default:
-            INT_BARF( &context, 0x21 );
+    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 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 */
+    case 0xea: /* NOVELL NETWARE - RETURN SHELL VERSION */
+        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 58b3858db2cb99a93ed194eed2ca7400c134be44..799816aa02aef8c4a5fd11b6e7a8aa55daaddc4b 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 @@ void INT_Int25Handler( struct sigcontext_struct context )
     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 @@ void INT_Int25Handler( struct sigcontext_struct context )
 
     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 06f70ed68f50d5a61be5e7df3589d0193acaa26e..53f1abc4bbb76043fe2b794749e8ed8ed684f1eb 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 @@ void INT_Int26Handler( struct sigcontext_struct context )
     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 @@ void INT_Int26Handler( struct sigcontext_struct context )
 
     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 a9b8b8abdcd4b1435527c0cb889714ecd397840e..97a94908fcc450ee12a7658916a1b6e70e06b30c 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_DummyHandler( struct sigcontext_struct context )
  */
 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 5c46e07fd9684740f426b8a9c5595f10c35c5c09..4c968093691dcdac3947d3631efafb1992ab53f5 100644
--- a/multimedia/audio.c
+++ b/multimedia/audio.c
@@ -138,7 +138,6 @@ static DWORD WAVE_mciOpen(UINT wDevID, DWORD dwFlags, LPMCI_WAVE_OPEN_PARMS lpPa
 		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 dc99c2abc1310be4cdaf102808e2b596b26a2ae0..c8960709645d7bc0070d5f13a7b04cbeb8dfb062 100644
--- a/multimedia/mcistring.c
+++ b/multimedia/mcistring.c
@@ -46,7 +46,7 @@ LONG ANIM_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg,
 /* 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 b734ecdf71c24e3b2fff3e36bb7477cc7127c482..00941155c36c0782b7330eaeb04b92356e27e33f 100644
--- a/multimedia/midi.c
+++ b/multimedia/midi.c
@@ -296,7 +296,6 @@ static DWORD MIDI_mciOpen(UINT wDevID, DWORD dwFlags, LPMCI_OPEN_PARMS lpParms)
     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 407d15e8d0b464184285db27a0710507152cec20..b3df1a2160a7fb461f13a51e735217d90cdac42b 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -14,6 +14,7 @@ static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 #include "metafile.h"
 #include "wine.h"
 #include "callback.h"
+#include "xmalloc.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -67,15 +68,15 @@ BOOL FONT_Init( void )
   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 c2571e0dbefb2ae0507d08a476fc6b5c4a902896..e9667ad67ca8a884f7779dd2dfb30094a2333aa2 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -789,6 +789,7 @@ static void BuildSpec32Files( char *specname )
         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 @@ static void BuildSpec32Files( char *specname )
 		}
 		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 @@ static void BuildSpec32Files( char *specname )
 		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 3980b9efb5d94d21e4c4ad4704fcd1ced958038d..9851ec68166c7147201269c873de453354f7bed7 100644
--- a/win32/Makefile.in
+++ b/win32/Makefile.in
@@ -8,12 +8,16 @@ C_SRCS = \
 	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 2188ff55d65e8c72a2637eb3feceeb95cab3c74b..1dd15bcd02de5270c00930a0d77e82cd0eb528f2 100644
--- a/win32/file.c
+++ b/win32/file.c
@@ -60,9 +60,6 @@ WINAPI HANDLE32 CreateFileMapping(HANDLE32 h,SECURITY_ATTRIBUTES *ats,
         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 @@ HANDLE32 CreateFileA(LPSTR filename, DWORD access, DWORD sharing,
     }
     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 @@ HANDLE32 CreateFileA(LPSTR filename, DWORD access, DWORD sharing,
     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 0000000000000000000000000000000000000000..7a4468fbab1be528dbc0f170c7b9edb816aac6d7
--- /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 d2e89369d870ff0140b1463048a60850c54a5219..2081fe1ebbd0fe5413feb3d538aaf859a823561c 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 @@ DWORD GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize)
  */
 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 @@ VOID GetStartupInfoA(LPSTARTUPINFO lpStartupInfo)
     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 352db665bf480aff1a60f000e2c39bdfc8bc5d84..bd55c2b874f5af1d221ad296ee9232b9d842e493 100644
--- a/win32/memory.c
+++ b/win32/memory.c
@@ -49,12 +49,20 @@ LPVOID VirtualAlloc(LPVOID lpvAddress, DWORD cbSize,
     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 @@ LPVOID VirtualAlloc(LPVOID lpvAddress, DWORD cbSize,
                                           ~(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 0000000000000000000000000000000000000000..2f2fe449d7877d30599f0bc741dbb83ba3c06775
--- /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 8fb8fe4c5b7b023e723cf3d312af0bf48bd532c0..b8e244db9aae14156bcd51434f8a2c5bb6b77801 100644
--- a/win32/process.c
+++ b/win32/process.c
@@ -82,3 +82,40 @@ HANDLE32 WINAPI GetCurrentProcess(void)
 {
 	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 0000000000000000000000000000000000000000..5add44060393bc663554a5ff2a779cb83f563da6
--- /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 0000000000000000000000000000000000000000..1d9d5a232ae471c3cfc2749f1fc07b089cf63a5e
--- /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 15ea23276c26acc7ff0d227c70c8655c044bbd80..04d90ae178a878997a93fde4ededc7b76d1b55f6 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -146,7 +146,7 @@ static BOOL DCE_GetVisRect( WND *wndPtr, BOOL clientArea, RECT *lprect )
 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 43bb4e4e9d38312d074fbecee2ef8cb1439f4b68..458232c93073393834b5f9880eefe10e76f2cf9c 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 @@ LONG DispatchMessage( LPMSG msg )
 /*    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 @@ DWORD GetTickCount(void)
 {
     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 1dcafb82d559b648ce8bd0d97003ec563f5d7eaf..92d1748f6609013cfb945bd43f81f7237dfa8f38 100644
--- a/windows/property.c
+++ b/windows/property.c
@@ -70,7 +70,7 @@ HANDLE GetProp( HWND hwnd, SEGPTR str )
         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 @@ HANDLE RemoveProp( HWND hwnd, SEGPTR str )
     {
         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 da50aec573475afd7dc50c294c47946ac968e43f..1c7d8953601d0940422d3dd27cc2793a345445d5 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 @@ HWND CreateWindowEx( DWORD exStyle, SEGPTR className, SEGPTR windowName,
     }
     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 @@ HWND CreateWindowEx( DWORD exStyle, SEGPTR className, SEGPTR windowName,
 	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 659cd2f963f786b1adc74fd7aee39593614be8fb..3a7eb9f7262edc041127341e514fe8cb02c34d4f 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -434,6 +434,7 @@ BOOL ShowWindow( HWND hwnd, int cmd )
             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;