Release 980104

Sat Jan  3 17:15:56 1998  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [debugger/db_disasm.c]
	Added cpuid and cmpxchg instructions.

	* [if1632/builtin.c] [relay32/builtin32.c]
	Fixed broken -dll option with Win32 DLLs.

	* [include/heap.h]
	Added SYSTEM_LOCK/SYSTEM_UNLOCK macros.

	* [configure.in] [misc/lstr.c]
	Added check for wctype.h.
	Commented out --enable-ipc option (IPC code has been broken for a
	long time anyway).

	* [scheduler/critsection.c] [scheduler/event.c]
	  [scheduler/mutex.c] [scheduler/semaphore.c]
	Implemented Win32 synchronization objects.

	* [scheduler/synchro.c]
	Implemented WaitForMultipleObjects and related functions.

	* [scheduler/thread.c]
	If possible, use clone() in CreateThread().

	* [scheduler/thread.c] [scheduler/process.c]
	Made thread and process waitable objects.
	Thread and process id values are now different from the pointers
	they represent.

	* [win32/k32obj.c]
	Moved to scheduler directory.
	Added function table for waiting operations on objects.

	* [files/file.c] [memory/virtual.c]
	Added new K32OBJ function table.

Sun Jan  1 16:48:23 1997  Andreas Mohr <100.30936@germany.net>

	* [files/file.c]
	Fixed my patch for GetTempFileName16() as needed.
	It was ...Name32A() that didn't work properly, not ...Name16().

	* [graphics/x11drv/brush.c]
	Fixed a BadMatch error.

	* [msdos/int21.c]
	Fixed INT21_FindNextFCB() to get correct volume labels e.g.
	in "file open" dialog.

	* [multimedia/joystick.c] [relay32/winmm.spec]
	Stub JoyGetPosEx().

	* [scheduler/process.c] [relay32/kernel32.spec]
	Implemented RegisterServiceProcess().

Wed Dec 31 11:14:43 1997  Lawson Whitney  <lawson_whitney@juno.com>

	* [if1632/kernel.spec] [if1632/relay.c]
	Define CallProcEx32w - Thanks to Marcus Meissner for his excellent
	CallProc32W.

	* [loader/module.c]
	Take a shot at defining FreeLibrary32W.

Sun Dec 28 12:44:04 1997  Kai Morich <kai.morich@rhein-neckar.netsurf.de>

	* [controls/menu.c]
	Menu modification from WM_INITMENUPOPUP message fixed.
	Menu items now can have different wID and hSubMenu (Win95 behavior).

	* [misc/cpu.c]
	Improved IsProcessorFeaturePresent.

Sun Dec 28 03:21:08 1997  Ove Kaaven <ovek@main.arcticnet.no>

	* [include/winsock.h] [misc/winsock.c]
	Fixed WS_SOL_SOCKET for setsockopt(), and made select() return
	empty fd_sets if timeout.

	* [objects/palette.c]
	AnimatePalette() bailed out if entire palette is animated. Fixed.

	* [objects/dib.c]
	Added some code to SetDIBitsToDevice() and its helpers to fix
	some offseting problems.

	* [objects/cursoricon.c]
	Made CreateCursor32() convert the instance handle properly. Made
	DestroyCursor() return correct success status.

Wed Dec 24 17:56:34 1997  Dimitrie O. Paun  <dimi@cs.toronto.edu>

	* [windows/syscolor.c]
	Added definition of GetSysColorPen16/32. This function does not
	exist in the Win32 API but is a very close (and natural) relative
	to GetSysColorBrush function. Moreover, it is *very* much used 
	within Wine since there are a lot of places where we need to draw
	lines with the standard colors.

	* [controls/button.c] [controls/combo.c] [controls/icontitle.c]
	  [controls/menu.c] [controls/progress.c] [controls/scroll.c]
	  [controls/updown.c] [graphics/painting.c] [misc/tweak.c]
	  [windows/defwnd.c] [windows/graphics.c] [windows/nonclient.c]
	Replaced references to sysColorObjects with the appropriate
	call to GetSysColorBrush32/GetSysColorPen32. There is no need to
	expose the implementation of these functions, even within Wine.
	This makes the code easier to understand, debug, maintain.

	* [controls/uitools.c]
	Modified most of the functions in this file to use the now
	standard pens (i.e. GetSysColorPen32). These functions made
	*heavy* use of standard pens so I expect a lot less
	CreatePen/DeleteObject calls can do only good...:)
	Plus some minor modifications (*no* functional changes though).

	* [controls/updown.c]
	Used the new DrawFrameControl32 function to paint the control.
	I also deleted UDDOWN_DrawArrow since it was no longer required.

Tue Dec 23 00:03:33 1997  Steinar Hamre  <steinarh@stud.fim.ntnu.no>

	* [configure.in]
	Added check for -lw.

	* [include/wintypes.h] [tools/build.c]
	Changes to make the assembly understandable for even sun as.
	".ascii" -> ".string", "call %foo" -> "call *%foo",
	"pushw/popw %[cdes]s" written out to ".byte 0x66\npushl/popl %[cdes]s".

	* [memory/ldt.c]
	#ifdef added so <sys/seg.h> will not be included on Solaris.

Mon Dec 22 18:55:19 1997  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [configure.in]
	Added XF86DGA check.

	* [multimedia/dsound.c][relay32/dsound.spec][include/dsound.h]
	Started DirectSound. Only stubs for now.

	* [graphics/ddraw.c][include/ddraw.h][relay32/ddraw.spec]
	Started to implement DirectDraw. Mostly stubs, some
	testcases work. Requires the XF86DGA extension to XFree86.
	(check demo/blizdemo.exe from the Diablo CD-ROM).

	* [files/drive.c]
	Return correct "CDFS" fsname so Diablo is a bit happier.

Sun Dec 21 21:45:48 1997  Kevin Cozens <kcozens@interlog.com>

	* [misc/registry.c]
	Fixed bugs in the routines which read the Windows '95 registry
	files. Added extra information regarding the format of the Windows
	'95 registry files.
diff --git a/ANNOUNCE b/ANNOUNCE
index 3f2c359..aba47d4 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,16 +1,13 @@
-This is release 971221 of Wine, the MS Windows emulator.  This is still a
+This is release 980104 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 correctly.
 
 Patches should be submitted to "julliard@lrc.epfl.ch".  Please don't
 forget to include a ChangeLog entry.
 
-WHAT'S NEW with Wine-971221: (see ChangeLog for details)
-	- Preliminary GDI paths support.
-	- DrawFrameControl implementation.
-	- Multimedia support for time and joystick functions.
-	- Win32 spec files now generate C code for Winelib.
-	- Tons of new Win32 functions and stubs.
+WHAT'S NEW with Wine-980104: (see ChangeLog for details)
+	- Beginnings of DirectDraw/DirectSound support.
+	- Preliminary threading support based on clone().
 	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -19,10 +16,10 @@
 the release is available at the ftp sites.  The sources will be available
 from the following locations:
 
-  ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-971221.tar.gz
-  ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-971221.tar.gz
-  ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-971221.tar.gz
-  ftp://ftp.progsoc.uts.edu.au/pub/Wine/development/Wine-971221.tar.gz
+  ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-980104.tar.gz
+  ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-980104.tar.gz
+  ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-980104.tar.gz
+  ftp://ftp.progsoc.uts.edu.au/pub/Wine/development/Wine-980104.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
diff --git a/ChangeLog b/ChangeLog
index aad647d..57e6fb2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,155 @@
 ----------------------------------------------------------------------
+Sat Jan  3 17:15:56 1998  Alexandre Julliard  <julliard@lrc.epfl.ch>
+
+	* [debugger/db_disasm.c]
+	Added cpuid and cmpxchg instructions.
+
+	* [if1632/builtin.c] [relay32/builtin32.c]
+	Fixed broken -dll option with Win32 DLLs.
+
+	* [include/heap.h]
+	Added SYSTEM_LOCK/SYSTEM_UNLOCK macros.
+
+	* [configure.in] [misc/lstr.c]
+	Added check for wctype.h.
+	Commented out --enable-ipc option (IPC code has been broken for a
+	long time anyway).
+
+	* [scheduler/critsection.c] [scheduler/event.c]
+	  [scheduler/mutex.c] [scheduler/semaphore.c]
+	Implemented Win32 synchronization objects.
+
+	* [scheduler/synchro.c]
+	Implemented WaitForMultipleObjects and related functions.
+
+	* [scheduler/thread.c]
+	If possible, use clone() in CreateThread().
+
+	* [scheduler/thread.c] [scheduler/process.c]
+	Made thread and process waitable objects.
+	Thread and process id values are now different from the pointers
+	they represent.
+
+	* [win32/k32obj.c]
+	Moved to scheduler directory.
+	Added function table for waiting operations on objects.
+
+	* [files/file.c] [memory/virtual.c]
+	Added new K32OBJ function table.
+
+Sun Jan  1 16:48:23 1997  Andreas Mohr <100.30936@germany.net>
+
+	* [files/file.c]
+	Fixed my patch for GetTempFileName16() as needed.
+	It was ...Name32A() that didn't work properly, not ...Name16().
+
+	* [graphics/x11drv/brush.c]
+	Fixed a BadMatch error.
+
+	* [msdos/int21.c]
+	Fixed INT21_FindNextFCB() to get correct volume labels e.g.
+	in "file open" dialog.
+
+	* [multimedia/joystick.c] [relay32/winmm.spec]
+	Stub JoyGetPosEx().
+
+	* [scheduler/process.c] [relay32/kernel32.spec]
+	Implemented RegisterServiceProcess().
+
+Wed Dec 31 11:14:43 1997  Lawson Whitney  <lawson_whitney@juno.com>
+
+	* [if1632/kernel.spec] [if1632/relay.c]
+	Define CallProcEx32w - Thanks to Marcus Meissner for his excellent
+	CallProc32W.
+
+	* [loader/module.c]
+	Take a shot at defining FreeLibrary32W.
+
+Sun Dec 28 12:44:04 1997  Kai Morich <kai.morich@rhein-neckar.netsurf.de>
+
+	* [controls/menu.c]
+	Menu modification from WM_INITMENUPOPUP message fixed.
+	Menu items now can have different wID and hSubMenu (Win95 behavior).
+
+	* [misc/cpu.c]
+	Improved IsProcessorFeaturePresent.
+
+Sun Dec 28 03:21:08 1997  Ove Kaaven <ovek@main.arcticnet.no>
+
+	* [include/winsock.h] [misc/winsock.c]
+	Fixed WS_SOL_SOCKET for setsockopt(), and made select() return
+	empty fd_sets if timeout.
+
+	* [objects/palette.c]
+	AnimatePalette() bailed out if entire palette is animated. Fixed.
+
+	* [objects/dib.c]
+	Added some code to SetDIBitsToDevice() and its helpers to fix
+	some offseting problems.
+
+	* [objects/cursoricon.c]
+	Made CreateCursor32() convert the instance handle properly. Made
+	DestroyCursor() return correct success status.
+
+Wed Dec 24 17:56:34 1997  Dimitrie O. Paun  <dimi@cs.toronto.edu>
+
+	* [windows/syscolor.c]
+	Added definition of GetSysColorPen16/32. This function does not
+	exist in the Win32 API but is a very close (and natural) relative
+	to GetSysColorBrush function. Moreover, it is *very* much used 
+	within Wine since there are a lot of places where we need to draw
+	lines with the standard colors.
+
+	* [controls/button.c] [controls/combo.c] [controls/icontitle.c]
+	  [controls/menu.c] [controls/progress.c] [controls/scroll.c]
+	  [controls/updown.c] [graphics/painting.c] [misc/tweak.c]
+	  [windows/defwnd.c] [windows/graphics.c] [windows/nonclient.c]
+	Replaced references to sysColorObjects with the appropriate
+	call to GetSysColorBrush32/GetSysColorPen32. There is no need to
+	expose the implementation of these functions, even within Wine.
+	This makes the code easier to understand, debug, maintain.
+
+	* [controls/uitools.c]
+	Modified most of the functions in this file to use the now
+	standard pens (i.e. GetSysColorPen32). These functions made
+	*heavy* use of standard pens so I expect a lot less
+	CreatePen/DeleteObject calls can do only good...:)
+	Plus some minor modifications (*no* functional changes though).
+
+	* [controls/updown.c]
+	Used the new DrawFrameControl32 function to paint the control.
+	I also deleted UDDOWN_DrawArrow since it was no longer required.
+
+Tue Dec 23 00:03:33 1997  Steinar Hamre  <steinarh@stud.fim.ntnu.no>
+
+	* [configure.in]
+	Added check for -lw.
+
+	* [include/wintypes.h] [tools/build.c]
+	Changes to make the assembly understandable for even sun as.
+	".ascii" -> ".string", "call %foo" -> "call *%foo",
+	"pushw/popw %[cdes]s" written out to ".byte 0x66\npushl/popl %[cdes]s".
+
+	* [memory/ldt.c]
+	#ifdef added so <sys/seg.h> will not be included on Solaris.
+
+Mon Dec 22 18:55:19 1997  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
+
+	* [configure.in]
+	Added XF86DGA check.
+
+	* [multimedia/dsound.c][relay32/dsound.spec][include/dsound.h]
+	Started DirectSound. Only stubs for now.
+
+	* [graphics/ddraw.c][include/ddraw.h][relay32/ddraw.spec]
+	Started to implement DirectDraw. Mostly stubs, some
+	testcases work. Requires the XF86DGA extension to XFree86.
+	(check demo/blizdemo.exe from the Diablo CD-ROM).
+
+	* [files/drive.c]
+	Return correct "CDFS" fsname so Diablo is a bit happier.
+
+----------------------------------------------------------------------
 Fri Dec 19 10:50:46 1997  Douglas Ridgway  <ridgway@winehq.com>
 
 	* [Make.rules.in] [Makefile.in] [documentation/Makefile.in]
diff --git a/Make.rules.in b/Make.rules.in
index 7b1e7d7..5cc35b7 100644
--- a/Make.rules.in
+++ b/Make.rules.in
@@ -24,7 +24,7 @@
 XPM_LIB   = -lXpm
 XLIB      = @X_PRE_LIBS@ -lXext -lX11 @X_EXTRA_LIBS@
 WINELIB   = $(WINESTUB) $(TOPOBJDIR)/@LIB_TARGET@
-LDLIBS    = @LDLIBS@
+LIBS      = @LIBS@
 YACC      = @YACC@
 LEX       = @LEX@
 LEXLIB    = @LEXLIB@
diff --git a/Makefile.in b/Makefile.in
index c34c3b6..e6db31e 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -106,7 +106,7 @@
 lib: $(LIBSUBDIRS) $(LIB_TARGET)
 
 wine wine.sym: $(LIBSUBDIRS) $(LIB_TARGET) $(EMUSUBDIRS) dummy
-	$(CC) -o wine $(EMUOBJS) $(LIB_TARGET) $(LDOPTIONS) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LDLIBS)
+	$(CC) -o wine $(EMUOBJS) $(LIB_TARGET) $(LDOPTIONS) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LIBS)
 	nm -n wine | grep -v _compiled >wine.sym
 
 libwine.a: $(LIBOBJS)
@@ -115,7 +115,7 @@
 	$(RANLIB) $@
 
 libwine.so.1.0: $(LIBOBJS)
-	$(CC) -shared -Wl,-soname,libwine.so -o$@ $(LIBOBJS) $(LDOPTIONS) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LDLIBS)
+	$(CC) -shared -Wl,-soname,libwine.so -o$@ $(LIBOBJS) $(LDOPTIONS) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LIBS)
 
 install_emu: dummy
 	$(INSTALL_PROGRAM) wine $(bindir)/wine
diff --git a/configure b/configure
index 1032ff2..20417c6 100755
--- a/configure
+++ b/configure
@@ -17,8 +17,6 @@
 ac_help="$ac_help
   --enable-dll            build the Wine library as a DLL"
 ac_help="$ac_help
-  --enable-ipc            use inter-process communication for DDE"
-ac_help="$ac_help
   --with-x                use the X Window System"
 
 # Initialize some variables set by options.
@@ -549,7 +547,7 @@
 
 
 # We want these before the checks, so the checks can modify their values.
-test -z "$LDLIBS" && LDLIBS=-lm 
+LIBS="$LIBS -lm"
 test -z "$PROGEXT" && PROGEXT="" 
 
 
@@ -570,12 +568,6 @@
 fi
 
 
-# Check whether --with-ipc or --without-ipc was given.
-if test "${with_ipc+set}" = set; then
-  withval="$with_ipc"
-  if test "$enableval" = "no"; then : ; else OPTIONS="-DCONFIG_IPC"; fi
-fi
-
 
 
 
@@ -583,7 +575,7 @@
 
 
 echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:587: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "configure:579: checking whether ${MAKE-make} sets \${MAKE}" >&5
 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -612,7 +604,7 @@
 # Extract the first word of "gcc", so it can be a program name with args.
 set dummy gcc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:616: checking for $ac_word" >&5
+echo "configure:608: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -641,7 +633,7 @@
   # Extract the first word of "cc", so it can be a program name with args.
 set dummy cc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:645: checking for $ac_word" >&5
+echo "configure:637: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -689,7 +681,7 @@
 fi
 
 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:693: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:685: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
 
 ac_ext=c
 # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@@ -699,11 +691,11 @@
 cross_compiling=$ac_cv_prog_cc_cross
 
 cat > conftest.$ac_ext <<EOF
-#line 703 "configure"
+#line 695 "configure"
 #include "confdefs.h"
 main(){return(0);}
 EOF
-if { (eval echo configure:707: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:699: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   ac_cv_prog_cc_works=yes
   # If we can't run a trivial program, we are probably using a cross compiler.
   if (./conftest; exit) 2>/dev/null; then
@@ -723,12 +715,12 @@
   { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
 fi
 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:727: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:719: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
 cross_compiling=$ac_cv_prog_cc_cross
 
 echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:732: checking whether we are using GNU C" >&5
+echo "configure:724: checking whether we are using GNU C" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -737,7 +729,7 @@
   yes;
 #endif
 EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:741: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:733: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
   ac_cv_prog_gcc=yes
 else
   ac_cv_prog_gcc=no
@@ -752,7 +744,7 @@
   ac_save_CFLAGS="$CFLAGS"
   CFLAGS=
   echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:756: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:748: checking whether ${CC-cc} accepts -g" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -780,7 +772,7 @@
 fi
 
 echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:784: checking how to run the C preprocessor" >&5
+echo "configure:776: checking how to run the C preprocessor" >&5
 # On Suns, sometimes $CPP names a directory.
 if test -n "$CPP" && test -d "$CPP"; then
   CPP=
@@ -795,13 +787,13 @@
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp.
   cat > conftest.$ac_ext <<EOF
-#line 799 "configure"
+#line 791 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:805: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:797: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   :
@@ -812,13 +804,13 @@
   rm -rf conftest*
   CPP="${CC-cc} -E -traditional-cpp"
   cat > conftest.$ac_ext <<EOF
-#line 816 "configure"
+#line 808 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:822: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:814: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   :
@@ -845,7 +837,7 @@
 # Uses ac_ vars as temps to allow command line to override cache and checks.
 # --without-x overrides everything else, but does not touch the cache.
 echo $ac_n "checking for X""... $ac_c" 1>&6
-echo "configure:849: checking for X" >&5
+echo "configure:841: checking for X" >&5
 
 # Check whether --with-x or --without-x was given.
 if test "${with_x+set}" = set; then
@@ -907,12 +899,12 @@
 
   # First, try using that file with no special directory specified.
 cat > conftest.$ac_ext <<EOF
-#line 911 "configure"
+#line 903 "configure"
 #include "confdefs.h"
 #include <$x_direct_test_include>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:916: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:908: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -981,14 +973,14 @@
   ac_save_LIBS="$LIBS"
   LIBS="-l$x_direct_test_library $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 985 "configure"
+#line 977 "configure"
 #include "confdefs.h"
 
 int main() {
 ${x_direct_test_function}()
 ; return 0; }
 EOF
-if { (eval echo configure:992: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:984: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   LIBS="$ac_save_LIBS"
 # We can link X programs with no special library path.
@@ -1094,17 +1086,17 @@
     case "`(uname -sr) 2>/dev/null`" in
     "SunOS 5"*)
       echo $ac_n "checking whether -R must be followed by a space""... $ac_c" 1>&6
-echo "configure:1098: checking whether -R must be followed by a space" >&5
+echo "configure:1090: checking whether -R must be followed by a space" >&5
       ac_xsave_LIBS="$LIBS"; LIBS="$LIBS -R$x_libraries"
       cat > conftest.$ac_ext <<EOF
-#line 1101 "configure"
+#line 1093 "configure"
 #include "confdefs.h"
 
 int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:1108: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1100: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   ac_R_nospace=yes
 else
@@ -1120,14 +1112,14 @@
       else
 	LIBS="$ac_xsave_LIBS -R $x_libraries"
 	cat > conftest.$ac_ext <<EOF
-#line 1124 "configure"
+#line 1116 "configure"
 #include "confdefs.h"
 
 int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:1131: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1123: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   ac_R_space=yes
 else
@@ -1159,7 +1151,7 @@
     # libraries were built with DECnet support.  And karl@cs.umb.edu says
     # the Alpha needs dnet_stub (dnet does not exist).
     echo $ac_n "checking for dnet_ntoa in -ldnet""... $ac_c" 1>&6
-echo "configure:1163: checking for dnet_ntoa in -ldnet" >&5
+echo "configure:1155: checking for dnet_ntoa in -ldnet" >&5
 ac_lib_var=`echo dnet'_'dnet_ntoa | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1167,7 +1159,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-ldnet  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1171 "configure"
+#line 1163 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1178,7 +1170,7 @@
 dnet_ntoa()
 ; return 0; }
 EOF
-if { (eval echo configure:1182: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1174: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1200,7 +1192,7 @@
 
     if test $ac_cv_lib_dnet_dnet_ntoa = no; then
       echo $ac_n "checking for dnet_ntoa in -ldnet_stub""... $ac_c" 1>&6
-echo "configure:1204: checking for dnet_ntoa in -ldnet_stub" >&5
+echo "configure:1196: checking for dnet_ntoa in -ldnet_stub" >&5
 ac_lib_var=`echo dnet_stub'_'dnet_ntoa | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1208,7 +1200,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-ldnet_stub  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1212 "configure"
+#line 1204 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1219,7 +1211,7 @@
 dnet_ntoa()
 ; return 0; }
 EOF
-if { (eval echo configure:1223: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1215: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1248,12 +1240,12 @@
     # The nsl library prevents programs from opening the X display
     # on Irix 5.2, according to dickey@clark.net.
     echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6
-echo "configure:1252: checking for gethostbyname" >&5
+echo "configure:1244: checking for gethostbyname" >&5
 if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1257 "configure"
+#line 1249 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char gethostbyname(); below.  */
@@ -1276,7 +1268,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:1280: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1272: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_func_gethostbyname=yes"
 else
@@ -1297,7 +1289,7 @@
 
     if test $ac_cv_func_gethostbyname = no; then
       echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6
-echo "configure:1301: checking for gethostbyname in -lnsl" >&5
+echo "configure:1293: checking for gethostbyname in -lnsl" >&5
 ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1305,7 +1297,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lnsl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1309 "configure"
+#line 1301 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1316,7 +1308,7 @@
 gethostbyname()
 ; return 0; }
 EOF
-if { (eval echo configure:1320: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1312: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1346,12 +1338,12 @@
     # -lsocket must be given before -lnsl if both are needed.
     # We assume that if connect needs -lnsl, so does gethostbyname.
     echo $ac_n "checking for connect""... $ac_c" 1>&6
-echo "configure:1350: checking for connect" >&5
+echo "configure:1342: checking for connect" >&5
 if eval "test \"`echo '$''{'ac_cv_func_connect'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1355 "configure"
+#line 1347 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char connect(); below.  */
@@ -1374,7 +1366,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:1378: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1370: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_func_connect=yes"
 else
@@ -1395,7 +1387,7 @@
 
     if test $ac_cv_func_connect = no; then
       echo $ac_n "checking for connect in -lsocket""... $ac_c" 1>&6
-echo "configure:1399: checking for connect in -lsocket" >&5
+echo "configure:1391: checking for connect in -lsocket" >&5
 ac_lib_var=`echo socket'_'connect | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1403,7 +1395,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lsocket $X_EXTRA_LIBS $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1407 "configure"
+#line 1399 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1414,7 +1406,7 @@
 connect()
 ; return 0; }
 EOF
-if { (eval echo configure:1418: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1410: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1438,12 +1430,12 @@
 
     # gomez@mi.uni-erlangen.de says -lposix is necessary on A/UX.
     echo $ac_n "checking for remove""... $ac_c" 1>&6
-echo "configure:1442: checking for remove" >&5
+echo "configure:1434: checking for remove" >&5
 if eval "test \"`echo '$''{'ac_cv_func_remove'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1447 "configure"
+#line 1439 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char remove(); below.  */
@@ -1466,7 +1458,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:1470: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1462: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_func_remove=yes"
 else
@@ -1487,7 +1479,7 @@
 
     if test $ac_cv_func_remove = no; then
       echo $ac_n "checking for remove in -lposix""... $ac_c" 1>&6
-echo "configure:1491: checking for remove in -lposix" >&5
+echo "configure:1483: checking for remove in -lposix" >&5
 ac_lib_var=`echo posix'_'remove | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1495,7 +1487,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lposix  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1499 "configure"
+#line 1491 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1506,7 +1498,7 @@
 remove()
 ; return 0; }
 EOF
-if { (eval echo configure:1510: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1502: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1530,12 +1522,12 @@
 
     # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay.
     echo $ac_n "checking for shmat""... $ac_c" 1>&6
-echo "configure:1534: checking for shmat" >&5
+echo "configure:1526: checking for shmat" >&5
 if eval "test \"`echo '$''{'ac_cv_func_shmat'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1539 "configure"
+#line 1531 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char shmat(); below.  */
@@ -1558,7 +1550,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:1562: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1554: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_func_shmat=yes"
 else
@@ -1579,7 +1571,7 @@
 
     if test $ac_cv_func_shmat = no; then
       echo $ac_n "checking for shmat in -lipc""... $ac_c" 1>&6
-echo "configure:1583: checking for shmat in -lipc" >&5
+echo "configure:1575: checking for shmat in -lipc" >&5
 ac_lib_var=`echo ipc'_'shmat | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1587,7 +1579,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lipc  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1591 "configure"
+#line 1583 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1598,7 +1590,7 @@
 shmat()
 ; return 0; }
 EOF
-if { (eval echo configure:1602: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1594: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1631,7 +1623,7 @@
   # libraries we check for below, so use a different variable.
   #  --interran@uluru.Stanford.EDU, kb@cs.umb.edu.
   echo $ac_n "checking for IceConnectionNumber in -lICE""... $ac_c" 1>&6
-echo "configure:1635: checking for IceConnectionNumber in -lICE" >&5
+echo "configure:1627: checking for IceConnectionNumber in -lICE" >&5
 ac_lib_var=`echo ICE'_'IceConnectionNumber | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1639,7 +1631,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lICE  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1643 "configure"
+#line 1635 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1650,7 +1642,7 @@
 IceConnectionNumber()
 ; return 0; }
 EOF
-if { (eval echo configure:1654: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1646: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1679,7 +1671,7 @@
 # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1683: checking for $ac_word" >&5
+echo "configure:1675: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1711,7 +1703,7 @@
 # Extract the first word of "flex", so it can be a program name with args.
 set dummy flex; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1715: checking for $ac_word" >&5
+echo "configure:1707: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1744,7 +1736,7 @@
   *) ac_lib=l ;;
   esac
   echo $ac_n "checking for yywrap in -l$ac_lib""... $ac_c" 1>&6
-echo "configure:1748: checking for yywrap in -l$ac_lib" >&5
+echo "configure:1740: checking for yywrap in -l$ac_lib" >&5
 ac_lib_var=`echo $ac_lib'_'yywrap | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1752,7 +1744,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-l$ac_lib  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1756 "configure"
+#line 1748 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1763,7 +1755,7 @@
 yywrap()
 ; return 0; }
 EOF
-if { (eval echo configure:1767: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1759: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1788,7 +1780,7 @@
 # Extract the first word of "ranlib", so it can be a program name with args.
 set dummy ranlib; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1792: checking for $ac_word" >&5
+echo "configure:1784: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1825,7 +1817,7 @@
 # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
 # ./install, which can be erroneously created by make from ./install.sh.
 echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:1829: checking for a BSD compatible install" >&5
+echo "configure:1821: checking for a BSD compatible install" >&5
 if test -z "$INSTALL"; then
 if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1875,7 +1867,7 @@
 test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
 
 echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
-echo "configure:1879: checking whether ln -s works" >&5
+echo "configure:1871: checking whether ln -s works" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1895,8 +1887,10 @@
   echo "$ac_t""no" 1>&6
 fi
 
+
+
 echo $ac_n "checking for i386_set_ldt in -li386""... $ac_c" 1>&6
-echo "configure:1900: checking for i386_set_ldt in -li386" >&5
+echo "configure:1894: checking for i386_set_ldt in -li386" >&5
 ac_lib_var=`echo i386'_'i386_set_ldt | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1904,7 +1898,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-li386  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1908 "configure"
+#line 1902 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1915,7 +1909,7 @@
 i386_set_ldt()
 ; return 0; }
 EOF
-if { (eval echo configure:1919: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1913: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1930,7 +1924,108 @@
 fi
 if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
   echo "$ac_t""yes" 1>&6
-  LDLIBS="$LDLIBS -li386"
+    ac_tr_lib=HAVE_LIB`echo i386 | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-li386 $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for iswalnum in -lw""... $ac_c" 1>&6
+echo "configure:1941: checking for iswalnum in -lw" >&5
+ac_lib_var=`echo w'_'iswalnum | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lw  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1949 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char iswalnum();
+
+int main() {
+iswalnum()
+; return 0; }
+EOF
+if { (eval echo configure:1960: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo w | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lw $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for XF86DGAQueryExtension in -lXxf86dga""... $ac_c" 1>&6
+echo "configure:1988: checking for XF86DGAQueryExtension in -lXxf86dga" >&5
+ac_lib_var=`echo Xxf86dga'_'XF86DGAQueryExtension | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lXxf86dga -lXext -lX11 $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1996 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char XF86DGAQueryExtension();
+
+int main() {
+XF86DGAQueryExtension()
+; return 0; }
+EOF
+if { (eval echo configure:2007: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo Xxf86dga | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lXxf86dga $LIBS"
+
 else
   echo "$ac_t""no" 1>&6
 fi
@@ -1943,7 +2038,7 @@
 then
   CFLAGS="$CFLAGS -Wall"
   echo $ac_n "checking "for gcc strength-reduce bug"""... $ac_c" 1>&6
-echo "configure:1947: checking "for gcc strength-reduce bug"" >&5
+echo "configure:2042: checking "for gcc strength-reduce bug"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_gcc_strength_bug'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1951,7 +2046,7 @@
   ac_cv_c_gcc_strength_bug="yes"
 else
   cat > conftest.$ac_ext <<EOF
-#line 1955 "configure"
+#line 2050 "configure"
 #include "confdefs.h"
 
 int main(void) {
@@ -1962,7 +2057,7 @@
   exit( Array[1] != -2 );
 }
 EOF
-if { (eval echo configure:1966: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2061: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
 then
   ac_cv_c_gcc_strength_bug="no"
 else
@@ -1985,7 +2080,7 @@
 
 
 echo $ac_n "checking "whether external symbols need an underscore prefix"""... $ac_c" 1>&6
-echo "configure:1989: checking "whether external symbols need an underscore prefix"" >&5
+echo "configure:2084: checking "whether external symbols need an underscore prefix"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_extern_prefix'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1997,14 +2092,14 @@
 	.long 0
 EOF
 cat > conftest.$ac_ext <<EOF
-#line 2001 "configure"
+#line 2096 "configure"
 #include "confdefs.h"
 extern int ac_test;
 int main() {
 if (ac_test) return 1
 ; return 0; }
 EOF
-if { (eval echo configure:2008: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2103: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   ac_cv_c_extern_prefix="yes"
 else
@@ -2031,21 +2126,21 @@
 if test "$LIB_TARGET" = "libwine.so.1.0"
 then
   echo $ac_n "checking "whether we can build a dll"""... $ac_c" 1>&6
-echo "configure:2035: checking "whether we can build a dll"" >&5
+echo "configure:2130: checking "whether we can build a dll"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_dll'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   saved_cflags=$CFLAGS
   CFLAGS="$CFLAGS -fPIC -shared -Wl,-soname,conftest.so.1.0"
   cat > conftest.$ac_ext <<EOF
-#line 2042 "configure"
+#line 2137 "configure"
 #include "confdefs.h"
 
 int main() {
 return 1
 ; return 0; }
 EOF
-if { (eval echo configure:2049: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2144: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   ac_cv_c_dll="yes"
 else
@@ -2070,15 +2165,15 @@
 
 
 
-for ac_func in memmove strerror tcgetattr usleep wait4 waitpid
+for ac_func in clone memmove strerror tcgetattr usleep wait4 waitpid
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2077: checking for $ac_func" >&5
+echo "configure:2172: checking for $ac_func" >&5
 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 2082 "configure"
+#line 2177 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2101,7 +2196,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:2105: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2200: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -2125,13 +2220,53 @@
 fi
 done
 
+for ac_hdr in wctype.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2228: checking for $ac_hdr" >&5
+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 2233 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2238: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ 
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
 echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6
-echo "configure:2130: checking whether stat file-mode macros are broken" >&5
+echo "configure:2265: checking whether stat file-mode macros are broken" >&5
 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 2135 "configure"
+#line 2270 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -2182,12 +2317,12 @@
 fi
 
 echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:2186: checking for working const" >&5
+echo "configure:2321: checking for working const" >&5
 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 2191 "configure"
+#line 2326 "configure"
 #include "confdefs.h"
 
 int main() {
@@ -2236,7 +2371,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:2240: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2375: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_const=yes
 else
@@ -2257,12 +2392,12 @@
 fi
 
 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:2261: checking for ANSI C header files" >&5
+echo "configure:2396: checking for ANSI C header files" >&5
 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 2266 "configure"
+#line 2401 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -2270,7 +2405,7 @@
 #include <float.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2274: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2409: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2287,7 +2422,7 @@
 if test $ac_cv_header_stdc = yes; then
   # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 2291 "configure"
+#line 2426 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -2305,7 +2440,7 @@
 if test $ac_cv_header_stdc = yes; then
   # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 2309 "configure"
+#line 2444 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -2326,7 +2461,7 @@
   :
 else
   cat > conftest.$ac_ext <<EOF
-#line 2330 "configure"
+#line 2465 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -2337,7 +2472,7 @@
 exit (0); }
 
 EOF
-if { (eval echo configure:2341: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2476: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
 then
   :
 else
@@ -2361,12 +2496,12 @@
 fi
 
 echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:2365: checking for size_t" >&5
+echo "configure:2500: checking for size_t" >&5
 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 2370 "configure"
+#line 2505 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -2563,7 +2698,6 @@
 s%@oldincludedir@%$oldincludedir%g
 s%@infodir@%$infodir%g
 s%@mandir@%$mandir%g
-s%@LDLIBS@%$LDLIBS%g
 s%@PROGEXT@%$PROGEXT%g
 s%@MAIN_TARGET@%$MAIN_TARGET%g
 s%@LIB_TARGET@%$LIB_TARGET%g
diff --git a/configure.in b/configure.in
index 11b26ab..abf9119 100644
--- a/configure.in
+++ b/configure.in
@@ -7,7 +7,7 @@
 AC_CONFIG_AUX_DIR(tools)
 
 # We want these before the checks, so the checks can modify their values.
-test -z "$LDLIBS" && LDLIBS=-lm AC_SUBST(LDLIBS)
+LIBS="$LIBS -lm"
 test -z "$PROGEXT" && PROGEXT="" AC_SUBST(PROGEXT)
 
 dnl **** Command-line arguments ****
@@ -24,15 +24,15 @@
 [  --enable-dll            build the Wine library as a DLL],
 [if test "$enableval" = "no"; then : ; else LIB_TARGET="libwine.so.1.0"; fi])
 
-AC_ARG_WITH(ipc,
-[  --enable-ipc            use inter-process communication for DDE],
-[if test "$enableval" = "no"; then : ; else OPTIONS="-DCONFIG_IPC"; fi])
+dnl AC_ARG_WITH(ipc,
+dnl [  --enable-ipc            use inter-process communication for DDE],
+dnl [if test "$enableval" = "no"; then : ; else OPTIONS="-DCONFIG_IPC"; fi])
 
 AC_SUBST(MAIN_TARGET)
 AC_SUBST(LIB_TARGET)
 AC_SUBST(OPTIONS)
 
-dnl **** Check for some programs and libraries ****
+dnl **** Check for some programs ****
 
 AC_PROG_MAKE_SET
 AC_PROG_CC
@@ -43,8 +43,15 @@
 AC_PROG_RANLIB
 AC_PROG_INSTALL
 AC_PROG_LN_S
+
+dnl **** Check for some libraries ****
+
 dnl Check for -li386 for NetBSD and OpenBSD
-AC_CHECK_LIB(i386,i386_set_ldt,LDLIBS="$LDLIBS -li386")
+AC_CHECK_LIB(i386,i386_set_ldt)
+dnl Check for -lw for Solaris
+AC_CHECK_LIB(w,iswalnum)
+dnl Check for XFree86 DGA extension
+AC_CHECK_LIB(Xxf86dga,XF86DGAQueryExtension,,,-lXext -lX11)
 
 dnl **** If ln -s doesn't work, use cp instead ****
 if test "$ac_cv_prog_LN_S" = "ln -s"; then : ; else LN_S=cp ; fi
@@ -114,7 +121,8 @@
 
 dnl **** Check for functions and header files ****
 
-AC_CHECK_FUNCS(memmove strerror tcgetattr usleep wait4 waitpid)
+AC_CHECK_FUNCS(clone memmove strerror tcgetattr usleep wait4 waitpid)
+AC_CHECK_HEADERS(wctype.h)
 AC_HEADER_STAT()
 AC_C_CONST()
 AC_TYPE_SIZE_T()
diff --git a/controls/button.c b/controls/button.c
index 836070d..9b74f1f 100644
--- a/controls/button.c
+++ b/controls/button.c
@@ -6,9 +6,9 @@
  */
 
 #include "win.h"
-#include "syscolor.h"
 #include "graphics.h"
 #include "button.h"
+#include "windows.h"
 
 static void PB_Paint( WND *wndPtr, HDC32 hDC, WORD action );
 static void PB_PaintGrayOnGray(HDC32 hDC,HFONT32 hFont,RECT32 *rc,char *text);
@@ -266,8 +266,8 @@
       /* Send WM_CTLCOLOR to allow changing the font (the colors are fixed) */
     if (infoPtr->hFont) SelectObject32( hDC, infoPtr->hFont );
     BUTTON_SEND_CTLCOLOR( wndPtr, hDC );
-    hOldPen = (HPEN32)SelectObject32(hDC, sysColorObjects.hpenWindowFrame);
-    hOldBrush = (HBRUSH32)SelectObject32(hDC, sysColorObjects.hbrushBtnFace);
+    hOldPen = (HPEN32)SelectObject32(hDC, GetSysColorPen32(COLOR_WINDOWFRAME));
+    hOldBrush =(HBRUSH32)SelectObject32(hDC,GetSysColorBrush32(COLOR_BTNFACE));
     SetBkMode32(hDC, TRANSPARENT);
     Rectangle32(hDC, rc.left, rc.top, rc.right, rc.bottom);
     if (action == ODA_DRAWENTIRE)
@@ -288,7 +288,7 @@
     if (infoPtr->state & BUTTON_HIGHLIGHTED)
     {
         /* draw button shadow: */
-        SelectObject32(hDC, sysColorObjects.hbrushBtnShadow );
+        SelectObject32(hDC, GetSysColorBrush32(COLOR_BTNSHADOW));
         PatBlt32(hDC, rc.left, rc.top, 1, rc.bottom-rc.top, PATCOPY );
         PatBlt32(hDC, rc.left, rc.top, rc.right-rc.left, 1, PATCOPY );
         rc.left += 2;  /* To position the text down and right */
@@ -300,7 +300,7 @@
     if (wndPtr->text && wndPtr->text[0])
     {
         LOGBRUSH16 lb;
-        GetObject16( sysColorObjects.hbrushBtnFace, sizeof(lb), &lb );
+        GetObject16( GetSysColorBrush32(COLOR_BTNFACE), sizeof(lb), &lb );
         if (wndPtr->dwStyle & WS_DISABLED &&
             GetSysColor32(COLOR_GRAYTEXT)==lb.lbColor)
             /* don't write gray text on gray bkg */
@@ -494,7 +494,7 @@
 
     GetClientRect16( wndPtr->hwndSelf, &rc);
     GRAPH_DrawRectangle( hDC, rc.left, rc.top + 2, rc.right - 1, rc.bottom - 1,
-					     sysColorObjects.hpenWindowFrame );
+			 GetSysColorPen32(COLOR_WINDOWFRAME) );
     if (wndPtr->text)
     {
 	if (infoPtr->hFont) SelectObject32( hDC, infoPtr->hFont );
diff --git a/controls/combo.c b/controls/combo.c
index e1ccb16..59b51cb 100644
--- a/controls/combo.c
+++ b/controls/combo.c
@@ -11,7 +11,6 @@
 
 #include "windows.h"
 #include "sysmetrics.h"
-#include "syscolor.h"
 #include "win.h"
 #include "spy.h"
 #include "user.h"
@@ -366,7 +365,7 @@
     if( lphc->wState & CBF_NOREDRAW )
         return;
 
-    hPrevBrush = (HBRUSH32)SelectObject32(hdc, sysColorObjects.hbrushBtnFace);
+    hPrevBrush=(HBRUSH32)SelectObject32(hdc,GetSysColorBrush32(COLOR_BTNFACE));
     CONV_RECT16TO32( &lphc->RectButton, &r );
 
     Rectangle32(hdc, r.left, r.top, r.right, r.bottom );
@@ -459,7 +458,7 @@
 	    {
 		/* highlight */
 
-		FillRect32( hDC, &rect, sysColorObjects.hbrushHighlight );
+		FillRect32( hDC, &rect, GetSysColorBrush32(COLOR_HIGHLIGHT) );
                 SetBkColor32( hDC, GetSysColor32( COLOR_HIGHLIGHT ) );
                 SetTextColor32( hDC, GetSysColor32( COLOR_HIGHLIGHTTEXT ) );
 		itemState = ODS_SELECTED | ODS_FOCUS;
@@ -538,9 +537,9 @@
 	  /* paint text field */
 
 	  GRAPH_DrawRectangle( hDC, lphc->RectEdit.left, lphc->RectEdit.top,
-				    lphc->RectEdit.right - lphc->RectEdit.left, 
-				    lphc->RectButton.bottom - lphc->RectButton.top,
-				    sysColorObjects.hpenWindowFrame ); 
+			       lphc->RectEdit.right - lphc->RectEdit.left, 
+			       lphc->RectButton.bottom - lphc->RectButton.top,
+			       GetSysColorPen32(COLOR_WINDOWFRAME) ); 
 	  CBPaintText( lphc, hDC );
       }
       if( hPrevBrush ) SelectObject32( hDC, hPrevBrush );
diff --git a/controls/icontitle.c b/controls/icontitle.c
index b54801e..8c4a473 100644
--- a/controls/icontitle.c
+++ b/controls/icontitle.c
@@ -9,7 +9,6 @@
 #include <unistd.h>
 #include "windows.h"
 #include "sysmetrics.h"
-#include "syscolor.h"
 #include "win.h"
 #include "desktop.h"
 #include "graphics.h"
@@ -128,7 +127,7 @@
 
     if( bActive )
     {
-	hBrush = sysColorObjects.hbrushActiveCaption;
+	hBrush = GetSysColorBrush32(COLOR_ACTIVECAPTION);
 	textColor = GetSysColor32(COLOR_CAPTIONTEXT);
     }
     else 
diff --git a/controls/menu.c b/controls/menu.c
index 8c2e984..ee5a098 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -20,7 +20,6 @@
 #include "windows.h"
 #include "bitmap.h"
 #include "gdi.h"
-#include "syscolor.h"
 #include "sysmetrics.h"
 #include "task.h"
 #include "win.h"
@@ -879,7 +878,7 @@
 	r.bottom += MENU_HighlightBottomNudge;
 	r.left += MENU_HighlightLeftNudge;
 	r.right += MENU_HighlightRightNudge;
-	FillRect32( hdc, &r, sysColorObjects.hbrushHighlight );
+	FillRect32( hdc, &r, GetSysColorBrush32(COLOR_HIGHLIGHT) );
     }
     else {
 	RECT32  r = rect;
@@ -887,7 +886,7 @@
 	r.bottom += MENU_HighlightBottomNudge;
 	r.left += MENU_HighlightLeftNudge;
 	r.right += MENU_HighlightRightNudge;
-	FillRect32( hdc, &r, sysColorObjects.hbrushMenu );
+	FillRect32( hdc, &r, GetSysColorBrush32(COLOR_MENU) );
     }
 
     SetBkMode32( hdc, TRANSPARENT );
@@ -899,7 +898,7 @@
 	if(TWEAK_Win95Look)
 	    TWEAK_DrawMenuSeparatorVert95(hdc, rect.left - 1, 3, height - 3);
 	else {
-	    SelectObject32( hdc, sysColorObjects.hpenWindowFrame );
+	    SelectObject32( hdc, GetSysColorPen32(COLOR_WINDOWFRAME) );
 	    MoveTo( hdc, rect.left, 0 );
 	    LineTo32( hdc, rect.left, height );
 	}
@@ -911,7 +910,7 @@
 					   rect.top + SEPARATOR_HEIGHT / 2 + 1,
 					   rect.right - 1);
 	else {
-	    SelectObject32( hdc, sysColorObjects.hpenWindowFrame );
+	    SelectObject32( hdc, GetSysColorPen32(COLOR_WINDOWFRAME) );
 	    MoveTo( hdc, rect.left, rect.top + SEPARATOR_HEIGHT/2 );
 	    LineTo32( hdc, rect.right, rect.top + SEPARATOR_HEIGHT/2 );
 	}
@@ -1067,7 +1066,7 @@
 	rect.right -= POPUP_XSHADE * SYSMETRICS_CXBORDER;
 /*    } */
 
-    if((hPrevBrush = SelectObject32( hdc, sysColorObjects.hbrushMenu )))
+    if((hPrevBrush = SelectObject32( hdc, GetSysColorBrush32(COLOR_MENU) )))
     {
 	HPEN32 hPrevPen;
 	
@@ -1141,10 +1140,10 @@
     if(TWEAK_Win95Look)
 	++lprect->bottom;
 
-    FillRect32(hDC, lprect, sysColorObjects.hbrushMenu );
+    FillRect32(hDC, lprect, GetSysColorBrush32(COLOR_MENU) );
 
     if(!TWEAK_Win95Look) {
-	SelectObject32( hDC, sysColorObjects.hpenWindowFrame );
+	SelectObject32( hDC, GetSysColorPen32(COLOR_WINDOWFRAME) );
 	MoveTo( hDC, lprect->left, lprect->bottom );
 	LineTo32( hDC, lprect->right, lprect->bottom );
     }
@@ -1229,9 +1228,6 @@
 	menu->FocusedItem = NO_SELECTED_ITEM;
     }
 
-    SendMessage16( hwndOwner, WM_INITMENUPOPUP, (WPARAM16)hmenu,
-                   MAKELONG( id, (menu->wFlags & MF_SYSMENU) ? 1 : 0 ));
-
     if( (wndOwner = WIN_FindWndPtr( hwndOwner )) )
     {
 	UINT32	width, height;
@@ -1438,7 +1434,7 @@
     else if (flags & MF_OWNERDRAW) item->text = (LPSTR)str;
     else item->text = NULL;
 
-    if (item->fType & MF_POPUP && item->hSubMenu != id )
+    if ((item->fType & MF_POPUP) && (flags & MF_POPUP) && (item->hSubMenu != id) )
 	DestroyMenu32( item->hSubMenu );   /* ModifyMenu() spec */
 
     if (flags & MF_POPUP)
@@ -1453,12 +1449,18 @@
             item->fState = 0;
 	    return FALSE;
         }
-    }
+    } 
+
+    item->wID = id;
+    if (flags & MF_POPUP)
+      item->hSubMenu = id;
+
+    if ((item->fType & MF_POPUP) && !(flags & MF_POPUP) )
+      flags |= MF_POPUP; /* keep popup */
 
     item->fType = flags & TYPE_MASK;
     item->fState = (flags & STATE_MASK) &
         ~(MF_HILITE | MF_MOUSESELECT | MF_BYPOSITION);
-    item->wID = item->hSubMenu = id;
 
     SetRectEmpty32( &item->rect );
     if (prevText) HeapFree( SystemHeap, 0, prevText );
@@ -1713,6 +1715,7 @@
     POPUPMENU *menu;
     MENUITEM *item;
     WND *wndPtr;
+    HDC32 hdc;
 
     if (!(menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu ))) return hmenu;
 
@@ -1722,6 +1725,25 @@
     item = &menu->items[menu->FocusedItem];
     if (!(item->fType & MF_POPUP) ||
          (item->fState & (MF_GRAYED | MF_DISABLED))) return hmenu;
+
+    /* message must be send before using item,
+       because nearly everything may by changed by the application ! */
+    rect = item->rect;
+    SendMessage16( hwndOwner, WM_INITMENUPOPUP, (WPARAM16)item->hSubMenu,
+		   MAKELONG( menu->FocusedItem, IS_SYSTEM_MENU(menu) ));
+
+    /* correct item if modified as a reaction to WM_INITMENUPOPUP-message */
+    if (!(item->fState & MF_HILITE)) 
+    {
+        if (menu->wFlags & MF_POPUP) hdc = GetDC32( menu->hWnd );
+        else hdc = GetDCEx32( menu->hWnd, 0, DCX_CACHE | DCX_WINDOW);
+        item->fState |= MF_HILITE;
+        MENU_DrawMenuItem( menu->hWnd, hdc, item, menu->Height, !(menu->wFlags & MF_POPUP) ); 
+	ReleaseDC32( menu->hWnd, hdc );
+    }
+    if (!item->rect.top && !item->rect.left && !item->rect.bottom && !item->rect.right)
+      item->rect = rect;
+
     item->fState |= MF_MOUSESELECT;
 
     if (IS_SYSTEM_MENU(menu))
@@ -2524,6 +2546,7 @@
     BOOL32 ret = FALSE;
 
     HideCaret32(0);
+    SendMessage16( hWnd, WM_INITMENUPOPUP, (WPARAM16)hMenu, 0);
     if (MENU_ShowPopup( hWnd, hMenu, 0, x, y, 0, 0 )) 
 	ret = MENU_TrackMenu( hMenu, wFlags & ~TPM_INTERNAL, 0, 0, hWnd, lpRect );
     ShowCaret32(0);
@@ -2947,8 +2970,6 @@
 
     if (!(menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu))) return -1;
     if ((nPos < 0) || (nPos >= menu->nItems)) return -1;
-    /* FIXME: Now that submenus can have ids, is this still right?  */
-    if (menu->items[nPos].fType & MF_POPUP) return -1;
     return menu->items[nPos].wID;
 }
 
diff --git a/controls/progress.c b/controls/progress.c
index c0311e2..6a6e388 100644
--- a/controls/progress.c
+++ b/controls/progress.c
@@ -12,7 +12,6 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include "windows.h"
-#include "syscolor.h"
 #include "sysmetrics.h"
 #include "progress.h"
 #include "graphics.h"
diff --git a/controls/scroll.c b/controls/scroll.c
index 4b7867e..a678d8a 100644
--- a/controls/scroll.c
+++ b/controls/scroll.c
@@ -10,7 +10,6 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include "windows.h"
-#include "syscolor.h"
 #include "sysmetrics.h"
 #include "scroll.h"
 #include "graphics.h"
@@ -388,11 +387,11 @@
 
       /* Select the correct brush and pen */
 
-    SelectObject32( hdc, sysColorObjects.hpenWindowFrame );
+    SelectObject32( hdc, GetSysColorPen32(COLOR_WINDOWFRAME) );
     if ((flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH)
     {
           /* This ought to be the color of the parent window */
-        SelectObject32( hdc, sysColorObjects.hbrushWindow );
+        SelectObject32( hdc, GetSysColorBrush32(COLOR_WINDOW) );
     }
     else
     {
@@ -402,7 +401,7 @@
                                              WM_CTLCOLORSCROLLBAR, hdc, hwnd );
             SelectObject32( hdc, hbrush );
         }
-        else SelectObject32( hdc, sysColorObjects.hbrushScrollbar );
+        else SelectObject32( hdc, GetSysColorBrush32(COLOR_SCROLLBAR) );
     }
 
       /* Calculate the scroll rectangle */
@@ -463,7 +462,7 @@
 
       /* Draw the thumb */
 
-    SelectObject32( hdc, sysColorObjects.hbrushBtnFace );
+    SelectObject32( hdc, GetSysColorBrush32(COLOR_BTNFACE) );
     Rectangle32( hdc, r.left, r.top, r.right, r.bottom );
     InflateRect32( &r, -1, -1 );
     GRAPH_DrawReliefRect( hdc, &r, 1, 2, FALSE );
@@ -903,7 +902,7 @@
 
 
 /*************************************************************************
- *           SetScrollInfo32   (USER32.500)
+ *           SetScrollInfo32   (USER32.501)
  */
 INT32 WINAPI SetScrollInfo32( HWND32 hwnd, INT32 nBar, const SCROLLINFO *info,
                               BOOL32 bRedraw )
@@ -1051,7 +1050,7 @@
 
 
 /*************************************************************************
- *           SetScrollPos32   (USER32.501)
+ *           SetScrollPos32   (USER32.502)
  */
 INT32 WINAPI SetScrollPos32( HWND32 hwnd, INT32 nBar, INT32 nPos,
                              BOOL32 bRedraw )
@@ -1104,7 +1103,7 @@
 
 
 /*************************************************************************
- *           SetScrollRange32   (USER32.502)
+ *           SetScrollRange32   (USER32.503)
  */
 BOOL32 WINAPI SetScrollRange32( HWND32 hwnd, INT32 nBar,
                                 INT32 MinVal, INT32 MaxVal, BOOL32 bRedraw )
diff --git a/controls/uitools.c b/controls/uitools.c
index e3c64de..15779a1 100644
--- a/controls/uitools.c
+++ b/controls/uitools.c
@@ -166,8 +166,8 @@
         }
     }
 
-    if(InnerI != -1) InnerPen = CreatePen32(PS_SOLID, 0, GetSysColor32((int)InnerI));
-    if(OuterI != -1) OuterPen = CreatePen32(PS_SOLID, 0, GetSysColor32((int)OuterI));
+    if(InnerI != -1) InnerPen = GetSysColorPen32(InnerI);
+    if(OuterI != -1) OuterPen = GetSysColorPen32(OuterI);
 
     MoveToEx32(hdc, 0, 0, &SavePoint);
 
@@ -315,17 +315,16 @@
     if((uFlags & BF_MIDDLE) && retval)
     {
         HBRUSH32 hbsave;
-        HBRUSH32 hb = uFlags & BF_MONO ? GetSysColorBrush32(COLOR_WINDOW)
-                                       : GetSysColorBrush32(COLOR_BTNFACE);
+        HBRUSH32 hb = GetSysColorBrush32(uFlags & BF_MONO ? COLOR_WINDOW
+					 :COLOR_BTNFACE);
         HPEN32 hpsave;
-        HPEN32 hp = CreatePen32(PS_SOLID, 0, uFlags & BF_MONO ? GetSysColor32(COLOR_WINDOW)
-                                                              : GetSysColor32(COLOR_BTNFACE));
+        HPEN32 hp = GetSysColorPen32(uFlags & BF_MONO ? COLOR_WINDOW
+				     : COLOR_BTNFACE);
         hbsave = (HBRUSH32)SelectObject32(hdc, hb);
         hpsave = (HPEN32)SelectObject32(hdc, hp);
         Polygon32(hdc, Points, 4);
         SelectObject32(hdc, hbsave);
         SelectObject32(hdc, hpsave);
-        DeleteObject32(hp);
     }
 
     /* Adjust rectangle if asked */
@@ -339,8 +338,6 @@
 
     /* Cleanup */
     SelectObject32(hdc, SavePen);
-    if(InnerI != -1) DeleteObject32(InnerPen);
-    if(OuterI != -1) DeleteObject32(OuterPen);
     MoveToEx32(hdc, SavePoint.x, SavePoint.y, NULL);
 
     return retval;
@@ -479,15 +476,15 @@
     if((uFlags & BF_BOTTOMRIGHT) == BF_BOTTOMRIGHT) RBpenplus = 1;
     if((uFlags & BF_TOPLEFT) == BF_TOPLEFT)         LTpenplus = 1;
 
-    if(LTInnerI != -1) LTInnerPen = CreatePen32(PS_SOLID, 0, GetSysColor32((int)LTInnerI));
-    if(LTOuterI != -1) LTOuterPen = CreatePen32(PS_SOLID, 0, GetSysColor32((int)LTOuterI));
-    if(RBInnerI != -1) RBInnerPen = CreatePen32(PS_SOLID, 0, GetSysColor32((int)RBInnerI));
-    if(RBOuterI != -1) RBOuterPen = CreatePen32(PS_SOLID, 0, GetSysColor32((int)RBOuterI));
+    if(LTInnerI != -1) LTInnerPen = GetSysColorPen32(LTInnerI);
+    if(LTOuterI != -1) LTOuterPen = GetSysColorPen32(LTOuterI);
+    if(RBInnerI != -1) RBInnerPen = GetSysColorPen32(RBInnerI);
+    if(RBOuterI != -1) RBOuterPen = GetSysColorPen32(RBOuterI);
 
     if((uFlags & BF_MIDDLE) && retval)
     {
-        FillRect32(hdc, &InnerRect, (uFlags & BF_MONO) ? GetSysColorBrush32(COLOR_WINDOW)
-                                                       : GetSysColorBrush32(COLOR_BTNFACE));
+        FillRect32(hdc, &InnerRect, GetSysColorBrush32(uFlags & BF_MONO ? 
+					    COLOR_WINDOW : COLOR_BTNFACE));
     }
 
     MoveToEx32(hdc, 0, 0, &SavePoint);
@@ -553,10 +550,6 @@
 
     /* Cleanup */
     SelectObject32(hdc, SavePen);
-    if(LTInnerI != -1) DeleteObject32(LTInnerPen);
-    if(LTOuterI != -1) DeleteObject32(LTOuterPen);
-    if(RBInnerI != -1) DeleteObject32(RBInnerPen);
-    if(RBOuterI != -1) DeleteObject32(RBOuterPen);
     MoveToEx32(hdc, SavePoint.x, SavePoint.y, NULL);
     return retval;
 }
@@ -771,7 +764,7 @@
         POINT32 CheckPoints[DFC_CHECKPOINTSMAX];
         int i;
         HBRUSH32 hbsave;
-        HPEN32 hp, hpsave;
+        HPEN32 hpsave;
 
         /* FIXME: This comes very close to M$'s checkmark, but not */
         /* exactly... When small or large there is a few pixels */
@@ -792,12 +785,10 @@
 
         i = (uFlags & DFCS_INACTIVE) || (uFlags & 0xff) == DFCS_BUTTON3STATE ? COLOR_BTNSHADOW : COLOR_WINDOWTEXT;
         hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(i));
-        hp = CreatePen32(PS_SOLID, 0, GetSysColor32(i));
-        hpsave = (HPEN32)SelectObject32(dc, hp);
+        hpsave = (HPEN32)SelectObject32(dc, GetSysColorPen32(i));
         Polygon32(dc, CheckPoints, DFC_CHECKPOINTSMAX);
         SelectObject32(dc, hpsave);
         SelectObject32(dc, hbsave);
-        DeleteObject32(hp);
     }
     return TRUE;
 }
@@ -818,7 +809,7 @@
     int i;
     int SmallDiam = UITOOLS_MakeSquareRect(r, &myr);
     int BorderShrink = SmallDiam / 16;
-    HPEN32 hpsave, hp;
+    HPEN32 hpsave;
     HBRUSH32 hbsave;
     int xe, ye;
     int xc, yc;
@@ -853,52 +844,36 @@
     {
         if(uFlags & (DFCS_FLAT|DFCS_MONO))
         {
-            hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_WINDOWFRAME));
-            hpsave = (HPEN32)SelectObject32(dc, hp);
+            hpsave = (HPEN32)SelectObject32(dc, GetSysColorPen32(COLOR_WINDOWFRAME));
             hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_WINDOWFRAME));
             Pie32(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
             SelectObject32(dc, hbsave);
             SelectObject32(dc, hpsave);
-            DeleteObject32(hp);
         }
         else
         {
-            hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNHIGHLIGHT));
-            hpsave = (HPEN32)SelectObject32(dc, hp);
+            hpsave = (HPEN32)SelectObject32(dc, GetSysColorPen32(COLOR_BTNHIGHLIGHT));
             hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_BTNHIGHLIGHT));
             Pie32(dc, myr.left, myr.top, myr.right, myr.bottom, myr.left-1, myr.bottom, myr.right-1, myr.top);
-            SelectObject32(dc, hbsave);
-            SelectObject32(dc, hpsave);
-            DeleteObject32(hp);
 
-            hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNSHADOW));
-            hpsave = (HPEN32)SelectObject32(dc, hp);
-            hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_BTNSHADOW));
+            SelectObject32(dc, GetSysColorPen32(COLOR_BTNSHADOW));
+            SelectObject32(dc, GetSysColorBrush32(COLOR_BTNSHADOW));
             Pie32(dc, myr.left, myr.top, myr.right, myr.bottom, myr.right+1, myr.top, myr.left+1, myr.bottom);
-            SelectObject32(dc, hbsave);
-            SelectObject32(dc, hpsave);
-            DeleteObject32(hp);
 
             myr.left   += BorderShrink;
             myr.right  -= BorderShrink;
             myr.top    += BorderShrink;
             myr.bottom -= BorderShrink;
 
-            hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_3DLIGHT));
-            hpsave = (HPEN32)SelectObject32(dc, hp);
-            hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_3DLIGHT));
+            SelectObject32(dc, GetSysColorPen32(COLOR_3DLIGHT));
+            SelectObject32(dc, GetSysColorBrush32(COLOR_3DLIGHT));
             Pie32(dc, myr.left, myr.top, myr.right, myr.bottom, myr.left-1, myr.bottom, myr.right-1, myr.top);
-            SelectObject32(dc, hbsave);
-            SelectObject32(dc, hpsave);
-            DeleteObject32(hp);
 
-            hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_3DDKSHADOW));
-            hpsave = (HPEN32)SelectObject32(dc, hp);
-            hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_3DDKSHADOW));
+            SelectObject32(dc, GetSysColorPen32(COLOR_3DDKSHADOW));
+            SelectObject32(dc, GetSysColorBrush32(COLOR_3DDKSHADOW));
             Pie32(dc, myr.left, myr.top, myr.right, myr.bottom, myr.right+1, myr.top, myr.left+1, myr.bottom);
             SelectObject32(dc, hbsave);
             SelectObject32(dc, hpsave);
-            DeleteObject32(hp);
         }
 
         i = 10*SmallDiam/16;
@@ -907,13 +882,11 @@
         myr.top    = yc - i+i/2;
         myr.bottom = yc + i/2;
         i= !(uFlags & (DFCS_INACTIVE|DFCS_PUSHED)) ? COLOR_WINDOW : COLOR_BTNFACE;
-        hp = CreatePen32(PS_SOLID, 0, GetSysColor32(i));
-        hpsave = (HPEN32)SelectObject32(dc, hp);
+        hpsave = (HPEN32)SelectObject32(dc, GetSysColorPen32(i));
         hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(i));
         Pie32(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
         SelectObject32(dc, hbsave);
         SelectObject32(dc, hpsave);
-        DeleteObject32(hp);
     }
 
     if(uFlags & DFCS_CHECKED)
@@ -927,12 +900,10 @@
 
         i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_WINDOWTEXT;
         hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(i));
-        hp = CreatePen32(PS_SOLID, 0, GetSysColor32(i));
-        hpsave = (HPEN32)SelectObject32(dc, hp);
+        hpsave = (HPEN32)SelectObject32(dc, GetSysColorPen32(i));
         Pie32(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
         SelectObject32(dc, hpsave);
         SelectObject32(dc, hbsave);
-        DeleteObject32(hp);
     }
 
     /* FIXME: M$ has a polygon in the center at relative points: */
@@ -992,7 +963,7 @@
     int SmallDiam = UITOOLS_MakeSquareRect(r, &myr)-2;
     int i;
     HBRUSH32 hbsave;
-    HPEN32 hpsave, hp;
+    HPEN32 hpsave;
     HFONT32 hfsave, hf;
     int xc = (myr.left+myr.right)/2;
     int yc = (myr.top+myr.bottom)/2;
@@ -1115,14 +1086,12 @@
     {
         /* If we have an inactive button, then you see a shadow */
         hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_BTNHIGHLIGHT));
-        hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNHIGHLIGHT));
-        hpsave = (HPEN32)SelectObject32(dc, hp);
+        hpsave = (HPEN32)SelectObject32(dc, GetSysColorPen32(COLOR_BTNHIGHLIGHT));
         Polygon32(dc, Line1, Line1N);
         if(Line2N > 0)
             Polygon32(dc, Line2, Line2N);
         SelectObject32(dc, hpsave);
         SelectObject32(dc, hbsave);
-        DeleteObject32(hp);
     }
 
     /* Correct for the shadow shift */
@@ -1138,23 +1107,15 @@
     }
 
     /* Make the final picture */
-    if(uFlags & DFCS_INACTIVE)
-    {
-        hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_BTNSHADOW));
-        hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNSHADOW));
-    }
-    else
-    {
-        hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_BTNTEXT));
-        hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNTEXT));
-    }
-    hpsave = (HPEN32)SelectObject32(dc, hp);
+    i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT;
+    hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(i));
+    hpsave = (HPEN32)SelectObject32(dc, GetSysColorPen32(i));
+
     Polygon32(dc, Line1, Line1N);
     if(Line2N > 0)
         Polygon32(dc, Line2, Line2N);
     SelectObject32(dc, hpsave);
     SelectObject32(dc, hbsave);
-    DeleteObject32(hp);
 
     return TRUE;
 }
@@ -1218,13 +1179,13 @@
         hbsave = (HBRUSH32)SelectObject32(dc, GetStockObject32(NULL_BRUSH));
         if(uFlags & (DFCS_MONO|DFCS_FLAT))
         {
-            hp = hp2 = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_WINDOWFRAME));
+            hp = hp2 = GetSysColorPen32(COLOR_WINDOWFRAME);
             hb = hb2 = GetSysColorBrush32(COLOR_WINDOWFRAME);
         }
         else
         {
-            hp  = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNHIGHLIGHT));
-            hp2 = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNSHADOW));
+            hp  = GetSysColorPen32(COLOR_BTNHIGHLIGHT);
+            hp2 = GetSysColorPen32(COLOR_BTNSHADOW);
             hb  = GetSysColorBrush32(COLOR_BTNHIGHLIGHT);
             hb2 = GetSysColorBrush32(COLOR_BTNSHADOW);
         }
@@ -1283,8 +1244,6 @@
 
         SelectObject32(dc, hpsave);
         SelectObject32(dc, hbsave);
-        DeleteObject32(hp);
-        DeleteObject32(hp2);
         return TRUE;
 
     default:
@@ -1298,12 +1257,10 @@
     if(uFlags & DFCS_INACTIVE)
     {
         hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_BTNHIGHLIGHT));
-        hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNHIGHLIGHT));
-        hpsave = (HPEN32)SelectObject32(dc, hp);
+        hpsave = (HPEN32)SelectObject32(dc, GetSysColorPen32(COLOR_BTNHIGHLIGHT));
         Polygon32(dc, Line, 3);
         SelectObject32(dc, hpsave);
         SelectObject32(dc, hbsave);
-        DeleteObject32(hp);
     }
 
     for(i = 0; i < 3; i++)
@@ -1312,21 +1269,12 @@
         Line[i].y--;
     }
 
-    if(uFlags & DFCS_INACTIVE)
-    {
-        hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_BTNSHADOW));
-        hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNSHADOW));
-    }
-    else
-    {
-        hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_BTNTEXT));
-        hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNTEXT));
-    }
-    hpsave = (HPEN32)SelectObject32(dc, hp);
+    i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT;
+    hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(i));
+    hpsave = (HPEN32)SelectObject32(dc, GetSysColorPen32(i));
     Polygon32(dc, Line, 3);
     SelectObject32(dc, hpsave);
     SelectObject32(dc, hbsave);
-    DeleteObject32(hp);
 
     return TRUE;
 }
diff --git a/controls/updown.c b/controls/updown.c
index bf81fdb..c0a2848 100644
--- a/controls/updown.c
+++ b/controls/updown.c
@@ -30,7 +30,6 @@
 #include <string.h>
 #include "windows.h"
 #include "winnls.h"
-#include "syscolor.h"
 #include "sysmetrics.h"
 #include "updown.h"
 #include "graphics.h"
@@ -269,77 +268,6 @@
 } 
 
 /***********************************************************************
- *           UPDOWN_DrawArraw
- * Draw the arrows for the up-down control. The arrows are drawn with the
- * current pen and filled with the current brush.
- * Input:
- * hdc      - the DC to draw on
- * rect     - rectangle holding the arrow
- * incr     - TRUE  if we draw the "increment" arrow
- *            FALSE if we draw the "decrement" arrow
- * pressed  - TRUE  if the arrow is pressed (clicked)
- *            FALSE if the arrow is not pressed (clicked)
- * horz     - TRUE  if the arrow is horizontal
- *            FLASE if the arrow is vertical
- */
-static void UPDOWN_DrawArrow(HDC32 hdc, RECT32 *rect, BOOL32 incr, 
-			     BOOL32 pressed, BOOL32 horz)
-{
-  const int rw = rect->right - rect->left;
-  const int rh = rect->bottom - rect->top;
-  int offset = pressed ? 1 : 0;
-  int th, x, y, len;
-
-  /* compute max extents of the triangle */
-  if(horz){ /* horizontal arrows */
-    th = (3*rh)/5-2*4;
-    if(th > rw/2)
-      th = rw/2;
-    if(th < 2)
-      th = 2;
-
-    /* compute the position of the tip */
-    y = (rect->top+rect->bottom+1)/2 + offset; 
-    if(incr)
-      x = (rect->left+rect->right+1)/2 + (2*th)/3 + offset;
-    else
-      x = (rect->left+rect->right)/2 + th/3 + offset;
-
-    for(len=1; th>0; th--, len+=2){
-      MoveToEx32(hdc, x, y, 0);
-      LineTo32(hdc, x, y+len);
-      if(incr) x--;
-      else     x++;
-      y++;
-    }  
-  }
-  else{                   /* vertical arrows */
-    th = (3*rw)/5-2*4;
-    if(th > rh/2)
-      th = rh/2;
-    if(th < 2)
-      th = 2;
-
-    /* compute the position of the tip */
-    x = (rect->left+rect->right+1)/2 + offset;
-    if(incr)
-      y = (rect->top+rect->bottom+1)/2 - th/3 + offset;
-    else
-      y = (rect->top+rect->bottom)/2 + (2*th)/3 + offset;
-
-    for(len=1; th>0; th--, len+=2){
-      MoveToEx32(hdc, x, y, 0);
-      LineTo32(hdc, x+len, y);
-      if(incr) y++;
-      else     y--;
-      x--;
-    }
-    
-  }
-
-}
-
-/***********************************************************************
  *           UPDOWN_Paint
  * Draw the arrows. The background need not be erased.
  */
@@ -350,19 +278,17 @@
   BOOL32 prssed;
   RECT32 rect;
   HDC32 hdc;
-  HBRUSH32 oldBrush;
-
+  
+  /* start painting the button */
   hdc = BeginPaint32( wndPtr->hwndSelf, &ps );
 
-  /* First select the proper brush */
-  oldBrush = wndPtr->dwStyle & WS_DISABLED ? GRAY_BRUSH : BLACK_BRUSH;
-  oldBrush = SelectObject32(hdc, GetStockObject32(oldBrush));
-
   /* Draw the incr button */
   UPDOWN_GetArrowRect(wndPtr, &rect, TRUE);
   prssed = (infoPtr->Flags & FLAG_INCR) && (infoPtr->Flags & FLAG_MOUSEIN);
-  DrawEdge32(hdc, &rect, prssed?EDGE_SUNKEN:EDGE_RAISED, BF_RECT|BF_MIDDLE);
-  UPDOWN_DrawArrow(hdc, &rect, TRUE, prssed, wndPtr->dwStyle & UDS_HORZ);
+  DrawFrameControl32(hdc, &rect, DFC_SCROLL, 
+	(wndPtr->dwStyle & UDS_HORZ ? DFCS_SCROLLLEFT : DFCS_SCROLLUP) |
+	(prssed ? DFCS_PUSHED : 0) |
+	(wndPtr->dwStyle&WS_DISABLED ? DFCS_INACTIVE : 0) );
 
   /* Draw the space between the buttons */
   rect.top = rect.bottom; rect.bottom++;
@@ -371,12 +297,13 @@
   /* Draw the decr button */
   UPDOWN_GetArrowRect(wndPtr, &rect, FALSE);
   prssed = (infoPtr->Flags & FLAG_DECR) && (infoPtr->Flags & FLAG_MOUSEIN);
-  DrawEdge32(hdc, &rect, prssed ? EDGE_SUNKEN : EDGE_RAISED, 
-	   BF_RECT | BF_SOFT | BF_MIDDLE);
-  UPDOWN_DrawArrow(hdc, &rect, FALSE, prssed, wndPtr->dwStyle & UDS_HORZ);
+  DrawFrameControl32(hdc, &rect, DFC_SCROLL, 
+	(wndPtr->dwStyle & UDS_HORZ ? DFCS_SCROLLRIGHT : DFCS_SCROLLDOWN) |
+	(prssed ? DFCS_PUSHED : 0) |
+	(wndPtr->dwStyle&WS_DISABLED ? DFCS_INACTIVE : 0) );
+
 
   /* clean-up */  
-  SelectObject32(hdc, oldBrush);
   EndPaint32( wndPtr->hwndSelf, &ps );
 }
 
diff --git a/debugger/db_disasm.c b/debugger/db_disasm.c
index 715ddbe..bd8e11f 100644
--- a/debugger/db_disasm.c
+++ b/debugger/db_disasm.c
@@ -265,7 +265,7 @@
 static const struct inst db_inst_0fax[] = {
 /*a0*/	{ "push",  FALSE, NONE,  op1(Si),     0 },
 /*a1*/	{ "pop",   FALSE, NONE,  op1(Si),     0 },
-/*a2*/	{ "",      FALSE, NONE,  0,	      0 },
+/*a2*/	{ "cpuid", FALSE, NONE,  0,	      0 },
 /*a3*/	{ "bt",    TRUE,  LONG,  op2(E,R),    0 },
 /*a4*/	{ "shld",  TRUE,  LONG,  op3(Ib,E,R), 0 },
 /*a5*/	{ "shld",  TRUE,  LONG,  op3(CL,E,R), 0 },
@@ -283,8 +283,8 @@
 };
 
 static const struct inst db_inst_0fbx[] = {
-/*b0*/	{ "",      FALSE, NONE,  0,	      0 },
-/*b1*/	{ "",      FALSE, NONE,  0,	      0 },
+/*b0*/	{ "cmpxchg",TRUE, BYTE,  op2(E, R),   0 },
+/*b1*/	{ "cmpxchg",TRUE, LONG,  op2(E, R),   0 },
 /*b2*/	{ "lss",   TRUE,  LONG,  op2(E, R),   0 },
 /*b3*/	{ "bts",   TRUE,  LONG,  op2(R, E),   0 },
 /*b4*/	{ "lfs",   TRUE,  LONG,  op2(E, R),   0 },
diff --git a/documentation/languages b/documentation/languages
index ef4aa6d..d354f2e 100644
--- a/documentation/languages
+++ b/documentation/languages
@@ -24,7 +24,7 @@
 3.  Edit include/options.h enum "WINE_LANGUAGE" to have a member called
     LANG_XX where XX is the new abbreviation.
 
-4.  Edit misc/ole2nls.c function "GetUserDefaultLCID" to contain a
+4.  Edit ole/ole2nls.c function "GetUserDefaultLCID" to contain a
     case for your language by uncommenting the return value of it.
 
 5.  Edit resources/sysrec.c to include "sysres_XX.h" where XX is the
@@ -47,7 +47,7 @@
 7.  Edit resources/Makefile.in to add the name of the new file to the
     SYSRES_SRCS variable.
 
-8.  Edit misc/ole2nls.c function "GetLocaleInfoA" to contain a case for
+8.  Edit ole/ole2nls.c function "GetLocaleInfoA" to contain a case for
     your language.
 
 9.  Re-configure, re-make dependencies, and re-make Wine.
diff --git a/files/drive.c b/files/drive.c
index 0fd582d..d5a8a86 100644
--- a/files/drive.c
+++ b/files/drive.c
@@ -623,9 +623,16 @@
     if (size > 0x7fffffff) size = 0x7fffffff;
     if (available > 0x7fffffff) available = 0x7fffffff;
 
-    *sector_bytes    = 512;
-    size            /= 512;
-    available       /= 512;
+    if (DRIVE_GetType(drive)==TYPE_CDROM) {
+	*sector_bytes    = 2048;
+	size            /= 2048;
+	available       /= 2048;
+    } else {
+	*sector_bytes    = 512;
+	size            /= 512;
+	available       /= 512;
+    }
+    /* fixme: probably have to adjust those variables too for CDFS */
     *cluster_sectors = 1;
     while (*cluster_sectors * 65530 < size) *cluster_sectors *= 2;
     *free_clusters   = available/ *cluster_sectors;
@@ -921,7 +928,7 @@
     if (!root) drive = DRIVE_GetCurrentDrive();
     else
     {
-        if ((root[1]) &&((root[1] != ':') || (root[2] != '\\')))
+        if ((root[1]) && (root[1] != ':'))
         {
             fprintf( stderr, "GetVolumeInformation: invalid root '%s'\n",root);
             return FALSE;
@@ -937,7 +944,13 @@
 
     if (filename_len) *filename_len = 12;
     if (flags) *flags = 0;
-    if (fsname) lstrcpyn32A( fsname, "FAT16", fsname_len );
+    if (fsname) {
+    	/* Diablo checks that return code ... */
+    	if (DRIVE_GetType(drive)==TYPE_CDROM)
+	    lstrcpyn32A( fsname, "CDFS", fsname_len );
+	else
+	    lstrcpyn32A( fsname, "FAT16", fsname_len );
+    }
     return TRUE;
 }
 
diff --git a/files/file.c b/files/file.c
index 10380e8..3eaaf8d 100644
--- a/files/file.c
+++ b/files/file.c
@@ -38,6 +38,18 @@
 #define MAP_ANON MAP_ANONYMOUS
 #endif
 
+static void FILE_Destroy( K32OBJ *obj );
+
+const K32OBJ_OPS FILE_Ops =
+{
+    /* Object cannot be waited upon (FIXME: for now) */
+    NULL,              /* signaled */
+    NULL,              /* satisfied */
+    NULL,              /* add_wait */
+    NULL,              /* remove_wait */
+    FILE_Destroy       /* destroy */
+};
+
 struct DOS_FILE_LOCK {
   struct DOS_FILE_LOCK *	next;
   DWORD				base;
@@ -73,6 +85,7 @@
     (*file)->type = FILE_TYPE_DISK;
 
     handle = PROCESS_AllocHandle( &(*file)->header, 0 );
+    /* If the allocation failed, the object is already destroyed */
     if (handle == INVALID_HANDLE_VALUE32) *file = NULL;
     return handle;
 }
@@ -83,7 +96,7 @@
  *
  * Destroy a DOS file.
  */
-void FILE_Destroy( K32OBJ *ptr )
+static void FILE_Destroy( K32OBJ *ptr )
 {
     FILE_OBJECT *file = (FILE_OBJECT *)ptr;
     assert( ptr->type == K32OBJ_FILE );
@@ -542,17 +555,12 @@
     }
 
     if (drive & TF_FORCEDRIVE)
-    {
-        sprintf( temppath, "%c:\\", drive & ~TF_FORCEDRIVE );
-	lstrcpyn32A( temppath + 3,
-                     DRIVE_GetDosCwd( toupper(drive & ~TF_FORCEDRIVE) - 'A'),
-                     129 );
-    }
+        sprintf(temppath,"%c:", drive & ~TF_FORCEDRIVE );
     else
     {
         GetTempPath32A( 132, temppath );
+        strcat( temppath, "\\" );
     }
-    strcat( temppath, "\\" );
     return (UINT16)GetTempFileName32A( temppath, prefix, unique, buffer );
 }
 
@@ -572,8 +580,11 @@
 
     strcpy( buffer, path );
     p = buffer + strlen(buffer);
-    /* add a \, if there isn't one ... */
-    if ((p == buffer) || (p[-1] != '\\')) *p++ = '\\';
+
+    /* add a \, if there isn't one and path is more than just the drive letter ... */
+    if ( !((strlen(buffer) == 2) && (buffer[1] == ':')) 
+	&& ((p == buffer) || (p[-1] != '\\'))) *p++ = '\\';
+
     *p++ = '~';
     for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
     sprintf( p, "%04x.tmp", num );
diff --git a/graphics/Makefile.in b/graphics/Makefile.in
index 3784c52..5481fa5 100644
--- a/graphics/Makefile.in
+++ b/graphics/Makefile.in
@@ -8,6 +8,7 @@
 C_SRCS = \
 	bitblt.c \
 	cache.c \
+	ddraw.c \
 	driver.c \
 	env.c \
 	escape.c \
diff --git a/graphics/ddraw.c b/graphics/ddraw.c
new file mode 100644
index 0000000..7248690
--- /dev/null
+++ b/graphics/ddraw.c
@@ -0,0 +1,904 @@
+/*		DirectDraw
+ *
+ * Copyright 1997 Marcus Meissner
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <assert.h>
+#include <X11/Xlib.h>
+
+#include "windows.h"
+#include "winerror.h"
+#include "interfaces.h"
+#include "gdi.h"
+#include "heap.h"
+#include "ldt.h"
+#include "dc.h"
+#include "win.h"
+#include "debug.h"
+#include "stddebug.h"
+#include "miscemu.h"
+#include "mmsystem.h"
+#include "ddraw.h"
+
+#ifdef HAVE_LIBXXF86DGA
+#include <X11/extensions/xf86dga.h>
+#endif
+
+static HRESULT WINAPI IDirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE,REFIID,LPVOID*);
+static HRESULT WINAPI IDirectDraw_QueryInterface(LPDIRECTDRAW this,REFIID refiid,LPVOID *obj);
+static HRESULT WINAPI IDirectDraw2_CreateSurface( LPDIRECTDRAW2 this,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk);
+static HRESULT WINAPI IDirectDraw_CreateSurface( LPDIRECTDRAW this,LPDDSURFACEDESC *lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk);
+static struct IDirectDrawSurface2_VTable dds2vt;
+static struct IDirectDrawSurface_VTable ddsvt;
+
+
+HRESULT WINAPI
+DirectDrawEnumerate32A(LPDDENUMCALLBACK32A ddenumproc,LPVOID data) {
+	fprintf(stderr,"DirectDrawEnumerateA(%p,%p).\n",ddenumproc,data);
+	ddenumproc(0,"WINE Display","display",data);
+	ddenumproc(&IID_IDirectDraw,"WINE DirectDraw","directdraw",data);
+	ddenumproc(&IID_IDirectDrawPalette,"WINE DirectPalette","directpalette",data);
+	return 0;
+}
+
+HRESULT WINAPI 
+DSoundHelp(DWORD x,DWORD y,DWORD z) {
+	fprintf(stderr,"DSoundHelp(0x%08lx,0x%08lx,0x%08lx),stub!\n",x,y,z);
+	return 0;
+}
+
+#ifdef HAVE_LIBXXF86DGA
+
+static int _getpixelformat(LPDIRECTDRAW ddraw,LPDDPIXELFORMAT pf) {
+	pf->dwFourCC = mmioFOURCC('R','G','B',' ');
+	if (ddraw->d.depth==8) {
+		pf->dwFlags 		= DDPF_RGB|DDPF_PALETTEINDEXEDTO8;
+		pf->x.dwRGBBitCount	= 8;
+		pf->y.dwRBitMask  	= 0;
+		pf->z.dwGBitMask  	= 0;
+		pf->xx.dwBBitMask 	= 0;
+		return 0;
+	}
+	if (ddraw->d.depth==16) {
+		pf->dwFlags       = DDPF_RGB;
+		pf->x.dwRGBBitCount  = 16;
+		pf->y.dwRBitMask  = 0x0000f800;
+		pf->z.dwGBitMask  = 0x000007e0;
+		pf->xx.dwBBitMask = 0x0000001f;
+		return 0;
+	}
+	fprintf(stderr,"_getpixelformat:oops?\n");
+	return DDERR_GENERIC;
+}
+
+
+static HRESULT WINAPI IDirectDrawSurface_Lock(
+    LPDIRECTDRAWSURFACE this,LPRECT32 lprect,LPDDSURFACEDESC lpddsd,DWORD flags, HANDLE32 hnd
+) {
+	dprintf_relay(stddeb,"IDirectDrawSurface(%p)->Lock(%p,%p,%08lx,%08lx)\n",
+		this,lprect,lpddsd,flags,(DWORD)hnd
+	);
+	fprintf(stderr,".");
+	if (lprect) {
+		/*
+		fprintf(stderr,"	lprect: %dx%d-%dx%d\n",
+			lprect->top,lprect->left,lprect->bottom,lprect->right
+		);
+		 */
+		lpddsd->lpSurface =	this->surface+
+					(lprect->top*this->lpitch)+
+					(lprect->left*(this->ddraw->d.depth/8));
+	} else
+		lpddsd->lpSurface = this->surface;
+	lpddsd->dwWidth		= this->width;
+	lpddsd->dwHeight	= this->height;
+	lpddsd->lPitch		= this->lpitch;
+	_getpixelformat(this->ddraw,&(lpddsd->ddpfPixelFormat));
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawSurface2_Lock(
+    LPDIRECTDRAWSURFACE2 this,LPRECT32 lprect,LPDDSURFACEDESC lpddsd,DWORD flags, HANDLE32 hnd
+) {
+	dprintf_relay(stddeb,"IDirectDrawSurface2(%p)->Lock(%p,%p,%08lx,%08lx)\n",
+		this,lprect,lpddsd,flags,(DWORD)hnd
+	);
+	fprintf(stderr,".");
+	if (lprect) {
+		/*
+		fprintf(stderr,"	lprect: %dx%d-%dx%d\n",
+			lprect->top,lprect->left,lprect->bottom,lprect->right
+		);
+		 */
+		lpddsd->lpSurface =	this->surface+
+					(lprect->top*this->lpitch)+
+					(lprect->left*(this->ddraw->d.depth/8));
+	} else
+		lpddsd->lpSurface = this->surface;
+	lpddsd->dwWidth		= this->width;
+	lpddsd->dwHeight	= this->height;
+	lpddsd->lPitch		= this->lpitch;
+	_getpixelformat(this->ddraw,&(lpddsd->ddpfPixelFormat));
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawSurface_Unlock(
+	LPDIRECTDRAWSURFACE this,LPVOID surface
+) {
+	dprintf_relay(stddeb,"IDirectDrawSurface(%p)->Unlock(%p)\n",this,surface);
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawSurface_Flip(
+	LPDIRECTDRAWSURFACE this,LPDIRECTDRAWSURFACE flipto,DWORD dwFlags
+) {
+	fprintf(stderr,"IDirectDrawSurface(%p)->Flip(%p,%08lx),STUB\n",this,flipto,dwFlags);
+	if (flipto) {
+		XF86DGASetViewPort(display,DefaultScreen(display),0,flipto->fb_height);
+	} else {
+		/* FIXME: flip through attached surfaces */
+		XF86DGASetViewPort(display,DefaultScreen(display),0,this->fb_height);
+	}
+	while (!XF86DGAViewPortChanged(display,DefaultScreen(display),1)) {
+	} 
+	fprintf(stderr,"flipped to new height %ld\n",flipto->fb_height);
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawSurface2_Unlock(
+	LPDIRECTDRAWSURFACE2 this,LPVOID surface
+) {
+	dprintf_relay(stddeb,"IDirectDrawSurface2(%p)->Unlock(%p)\n",this,surface);
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawSurface_SetPalette(
+	LPDIRECTDRAWSURFACE this,LPDIRECTDRAWPALETTE pal
+) {
+	fprintf(stderr,"IDirectDrawSurface(%p)->SetPalette(%p)\n",this,pal);
+	this->palette = pal;
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawSurface2_SetPalette(
+	LPDIRECTDRAWSURFACE2 this,LPDIRECTDRAWPALETTE pal
+) {
+	fprintf(stderr,"IDirectDrawSurface2(%p)->SetPalette(%p)\n",this,pal);
+	this->palette = pal;
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawSurface_Blt(
+	LPDIRECTDRAWSURFACE this,LPRECT32 rdst,LPDIRECTDRAWSURFACE src,LPRECT32 rsrc,DWORD dwFlags,LPDDBLTFX lpbltfx
+) {
+	fprintf(stderr,"IDirectDrawSurface(%p)->Blt(%p,%p,%p,%08lx,%p),stub!\n",
+		this,rdst,src,rsrc,dwFlags,lpbltfx
+	);
+	if (rdst) fprintf(stderr,"	destrect :%dx%d-%dx%d\n",rdst->left,rdst->top,rdst->right,rdst->bottom);
+	if (rsrc) fprintf(stderr,"	srcrect  :%dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
+	fprintf(stderr,"	blitfx: 0x%08lx\n",lpbltfx->dwDDFX);
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawSurface_BltFast(
+	LPDIRECTDRAWSURFACE this,DWORD dstx,DWORD dsty,LPDIRECTDRAWSURFACE src,LPRECT32 rsrc,DWORD trans
+) {
+	int	i,bpp;
+	fprintf(stderr,"IDirectDrawSurface(%p)->BltFast(%ld,%ld,%p,%p,%08lx),stub!\n",
+		this,dstx,dsty,src,rsrc,trans
+	);
+	fprintf(stderr,"	srcrect: %dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
+	bpp = this->ddraw->d.depth/8;
+	for (i=0;i<rsrc->bottom-rsrc->top;i++) {
+		memcpy(	this->surface+((i+dsty)*this->width*bpp)+dstx*bpp,
+			src->surface +(rsrc->top+i)*src->width*bpp+rsrc->left*bpp,
+			(rsrc->right-rsrc->left)*bpp
+		);
+	}
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawSurface_BltBatch(
+	LPDIRECTDRAWSURFACE this,LPDDBLTBATCH ddbltbatch,DWORD x,DWORD y
+) {
+	fprintf(stderr,"IDirectDrawSurface(%p)->BltBatch(%p,%08lx,%08lx),stub!\n",
+		this,ddbltbatch,x,y
+	);
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawSurface_GetCaps(
+	LPDIRECTDRAWSURFACE this,LPDDSCAPS caps
+) {
+	fprintf(stderr,"IDirectDrawSurface(%p)->GetCaps(%p),stub!\n",this,caps);
+	caps->dwCaps = 0; /* we cannot do anything */
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawSurface_GetSurfaceDesc(
+	LPDIRECTDRAWSURFACE this,LPDDSURFACEDESC ddsd
+) {
+	fprintf(stderr,"IDirectDrawSurface(%p)->GetSurfaceDesc(%p)\n",this,ddsd);
+	if (ddsd->dwFlags & DDSD_CAPS)
+		ddsd->ddsCaps.dwCaps = 0;
+	if (ddsd->dwFlags & DDSD_BACKBUFFERCOUNT)
+		ddsd->dwBackBufferCount = 1;
+	if (ddsd->dwFlags & DDSD_HEIGHT)
+		ddsd->dwHeight = this->height;
+	if (ddsd->dwFlags & DDSD_WIDTH)
+		ddsd->dwHeight = this->width;
+	ddsd->dwFlags &= ~(DDSD_CAPS|DDSD_BACKBUFFERCOUNT|DDSD_HEIGHT|DDSD_WIDTH);
+	if (ddsd->dwFlags)
+		fprintf(stderr,"	ddsd->flags is 0x%08lx\n",ddsd->dwFlags);
+	return 0;
+}
+
+static ULONG WINAPI IDirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE this) {
+	dprintf_relay(stddeb,"IDirectDrawSurface(%p)->AddRef()\n",this);
+	return ++(this->ref);
+}
+
+static ULONG WINAPI IDirectDrawSurface_Release(LPDIRECTDRAWSURFACE this) {
+	dprintf_relay(stddeb,"IDirectDrawSurface(%p)->Release()\n",this);
+	if (!--(this->ref)) {
+		this->ddraw->lpvtbl->fnRelease(this->ddraw);
+		HeapFree(GetProcessHeap(),0,this);
+		return 0;
+	}
+	return this->ref;
+}
+
+static ULONG WINAPI IDirectDrawSurface2_AddRef(LPDIRECTDRAWSURFACE2 this) {
+	dprintf_relay(stddeb,"IDirectDrawSurface2(%p)->AddRef()\n",this);
+	return ++(this->ref);
+}
+
+static ULONG WINAPI IDirectDrawSurface2_Release(LPDIRECTDRAWSURFACE2 this) {
+	dprintf_relay(stddeb,"IDirectDrawSurface2(%p)->Release()\n",this);
+	if (!--(this->ref)) {
+		this->ddraw->lpvtbl->fnRelease(this->ddraw);
+		HeapFree(GetProcessHeap(),0,this);
+		return 0;
+	}
+	return this->ref;
+}
+
+static HRESULT WINAPI IDirectDrawSurface2_GetAttachedSurface(
+	LPDIRECTDRAWSURFACE2 this,LPDDSCAPS lpddsd,LPDIRECTDRAWSURFACE2 *lpdsf
+) {
+	DDSURFACEDESC	ddsfd;
+	IUnknown	unk;
+
+	/* DOES NOT CREATE THEM, but uses the ones already attached to this
+	 * surface 
+	 */
+	fprintf(stderr,"IDirectDrawSurface2(%p)->GetAttachedSurface(%p,%p)\n",this,lpddsd,lpdsf);
+	/* FIXME: not correct */
+	IDirectDraw2_CreateSurface((LPDIRECTDRAW2)this->ddraw,&ddsfd,(LPDIRECTDRAWSURFACE*)lpdsf,&unk);
+
+	lpddsd->dwCaps = 0;
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawSurface_GetAttachedSurface(
+	LPDIRECTDRAWSURFACE this,LPDDSCAPS lpddsd,LPDIRECTDRAWSURFACE *lpdsf
+) {
+	LPDDSURFACEDESC	lpddsfd;
+	IUnknown	unk;
+
+	fprintf(stderr,"IDirectDrawSurface(%p)->GetAttachedSurface(%p,%p)\n",this,lpddsd,lpdsf);
+	/* FIXME: not correct */
+	IDirectDraw_CreateSurface(this->ddraw,&lpddsfd,lpdsf,&unk);
+	lpddsd->dwCaps = 0;
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawSurface_Initialize(
+	LPDIRECTDRAWSURFACE this,LPDIRECTDRAW ddraw,LPDDSURFACEDESC lpdsfd
+) {
+	fprintf(stderr,"IDirectDrawSurface(%p)->Initialize(%p,%p)\n",
+		this,ddraw,lpdsfd
+	);
+	fprintf(stderr,"	dwFlags is %08lx\n",lpdsfd->dwFlags);
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawSurface_GetPixelFormat(
+	LPDIRECTDRAWSURFACE this,LPDDPIXELFORMAT pf
+) {
+	fprintf(stderr,"IDirectDrawSurface(%p)->GetPixelFormat(%p)\n",this,pf);
+	return _getpixelformat(this->ddraw,pf);
+}
+
+static HRESULT WINAPI IDirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE this,DWORD dwFlags) {
+	fprintf(stderr,"IDirectDrawSurface(%p)->GetBltStatus(0x%08lx),stub!\n",
+		this,dwFlags
+	);
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawSurface_GetOverlayPosition(
+	LPDIRECTDRAWSURFACE this,LPLONG x1,LPLONG x2
+) {
+	fprintf(stderr,"IDirectDrawSurface(%p)->GetOverlayPosition(%p,%p),stub!\n",
+		this,x1,x2
+	);
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE this,HDC32* lphdc) {
+	fprintf(stderr,"IDirectDrawSurface(%p)->GetDC(%p),stub!\n",this,lphdc);
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawSurface2_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE2 this,LPVOID context,LPDDENUMSURFACESCALLBACK esfcb) {
+	/* none yet? */
+	return 0;
+}
+
+static struct IDirectDrawSurface2_VTable dds2vt = {
+	1/*IDirectDrawSurface2_QueryInterface*/,
+	IDirectDrawSurface2_AddRef,
+	IDirectDrawSurface2_Release,
+	4,
+	5,
+	6/*IDirectDrawSurface_Blt*/,
+	7/*IDirectDrawSurface_BltBatch*/,
+	8,
+	9,
+	IDirectDrawSurface2_EnumAttachedSurfaces,
+	11,
+	12,
+	IDirectDrawSurface2_GetAttachedSurface,
+	14,
+	15/*IDirectDrawSurface_GetCaps*/,
+	16,
+	17,
+	18,
+	19,
+	20,
+	21,
+	22,
+	23/*IDirectDrawSurface_GetSurfaceDesc*/,
+	24,
+	25,
+	IDirectDrawSurface2_Lock,
+	27,
+	28,
+	29,
+	30,
+	31,
+	IDirectDrawSurface2_SetPalette,
+	IDirectDrawSurface2_Unlock,
+	34,
+	35,
+	36,
+	37,
+	38,
+	39,
+};
+
+
+static HRESULT WINAPI IDirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE this,REFIID refiid,LPVOID *obj) {
+        char    xrefiid[50];
+
+        StringFromCLSID((LPCLSID)refiid,xrefiid);
+        fprintf(stderr,"IDirectDrawSurface(%p)->QueryInterface(%s,%p)\n",this,xrefiid,obj);
+	
+	/* thats version 2 */
+	if (	!memcmp(&IID_IDirectDrawSurface2,refiid,sizeof(IID_IDirectDrawSurface2))) {
+		this->lpvtbl->fnAddRef(this);
+		this->lpvtbl = (LPDIRECTDRAWSURFACE_VTABLE)&dds2vt;
+		*obj = this;
+		return 0;
+	}
+	/* thats us */
+	if (!memcmp(&IID_IDirectDrawSurface,refiid,sizeof(IID_IDirectDrawSurface))) {
+		this->lpvtbl->fnAddRef(this);
+		*obj = this;
+		return 0;
+	}
+    	return OLE_E_ENUM_NOMORE;
+}
+
+static struct IDirectDrawSurface_VTable ddsvt = {
+	IDirectDrawSurface_QueryInterface,
+	IDirectDrawSurface_AddRef,
+	IDirectDrawSurface_Release,
+	4,
+	5,
+	IDirectDrawSurface_Blt,
+	IDirectDrawSurface_BltBatch,
+	IDirectDrawSurface_BltFast,
+	9,
+	10,
+	11,
+	IDirectDrawSurface_Flip,
+	IDirectDrawSurface_GetAttachedSurface,
+	IDirectDrawSurface_GetBltStatus,
+	IDirectDrawSurface_GetCaps,
+	16,
+	17,
+	IDirectDrawSurface_GetDC,
+	19,
+	IDirectDrawSurface_GetOverlayPosition,
+	21,
+	IDirectDrawSurface_GetPixelFormat,
+	IDirectDrawSurface_GetSurfaceDesc,
+	IDirectDrawSurface_Initialize,
+	25,
+	IDirectDrawSurface_Lock,
+	27,
+	28,
+	29,
+	30,
+	31,
+	IDirectDrawSurface_SetPalette,
+	IDirectDrawSurface_Unlock,
+	34,
+	35,
+	36,
+};
+
+static HRESULT WINAPI IDirectDraw_CreateSurface(
+	LPDIRECTDRAW this,LPDDSURFACEDESC *lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk
+) {
+	fprintf(stderr,"IDirectDraw(%p)->CreateSurface(%p,%p,%p)\n",this,lpddsd,lpdsf,lpunk);
+	*lpdsf = (LPDIRECTDRAWSURFACE)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectDrawSurface));
+	this->lpvtbl->fnAddRef(this);
+	(*lpdsf)->ref = 1;
+	(*lpdsf)->lpvtbl = &ddsvt;
+	(*lpdsf)->surface = this->d.fb_addr+(this->d.current_height*this->d.fb_width*this->d.depth/8);
+	(*lpdsf)->fb_height = this->d.current_height; /* for setviewport */
+	this->d.current_height += this->d.fb_height;
+	(*lpdsf)->width = this->d.width;
+	(*lpdsf)->height = this->d.height;
+	(*lpdsf)->ddraw = this;
+	(*lpdsf)->lpitch = this->d.fb_width*this->d.depth/8;
+	*lpddsd = (LPDDSURFACEDESC)HeapAlloc(GetProcessHeap(),0,sizeof(DDSURFACEDESC));
+	(*lpddsd)->dwWidth = this->d.width;
+	(*lpddsd)->dwHeight = this->d.height;
+	(*lpddsd)->lPitch = this->d.fb_width*this->d.depth/8;
+	(*lpddsd)->ddsCaps.dwCaps = 0;
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDraw_DuplicateSurface(
+	LPDIRECTDRAW this,LPDIRECTDRAWSURFACE src,LPDIRECTDRAWSURFACE *dst
+) {
+	fprintf(stderr,"IDirectDraw(%p)->DuplicateSurface(%p,%p)\n",this,src,dst);
+	*dst = src; /* FIXME */
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDraw2_CreateSurface(
+	LPDIRECTDRAW2 this,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk
+) {
+	fprintf(stderr,"IDirectDraw2(%p)->CreateSurface(%p,%p,%p)\n",this,lpddsd,lpdsf,lpunk);
+	*lpdsf = (LPDIRECTDRAWSURFACE)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectDrawSurface));
+	this->lpvtbl->fnAddRef(this);
+	(*lpdsf)->ref = 1;
+	(*lpdsf)->lpvtbl = &ddsvt;
+	(*lpdsf)->surface = this->d.fb_addr+(this->d.current_height*this->d.fb_width*this->d.depth/8);
+	(*lpdsf)->width = this->d.width;
+	(*lpdsf)->height = this->d.height;
+	(*lpdsf)->ddraw = (LPDIRECTDRAW)this;
+	(*lpdsf)->fb_height = this->d.current_height;
+	(*lpdsf)->lpitch = this->d.fb_width*this->d.depth/8;
+	this->d.current_height += this->d.fb_height;
+	lpddsd->dwWidth = this->d.width;
+	lpddsd->dwHeight = this->d.height;
+	lpddsd->lPitch = this->d.fb_width*this->d.depth/8;
+	lpddsd->ddsCaps.dwCaps = 0;
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDraw_SetCooperativeLevel(
+	LPDIRECTDRAW this,HWND32 hwnd,DWORD x
+) {
+	fprintf(stderr,"IDirectDraw(%p)->SetCooperativeLevel(%08lx,%08lx),stub!\n",
+		this,(DWORD)hwnd,x
+	);
+	this->d.mainwindow = hwnd;
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDraw_SetDisplayMode(
+	LPDIRECTDRAW this,DWORD width,DWORD height,DWORD depth
+) {
+	int	i,*depths,depcount;
+	char	buf[200];
+
+	fprintf(stderr,"IDirectDraw(%p)->SetDisplayMode(%ld,%ld,%ld),stub!\n",this,width,height,depth);
+
+	depths = XListDepths(display,DefaultScreen(display),&depcount);
+	for (i=0;i<depcount;i++)
+		if (depths[i]==depth)
+			break;
+	XFree(depths);
+	if (i==depcount) {/* not found */
+		sprintf(buf,"SetDisplayMode(w=%ld,h=%ld,d=%ld), unsupported depth!",width,height,depth);
+		MessageBox32A(0,buf,"WINE DirectDraw",MB_OK|MB_ICONSTOP);
+		return DDERR_UNSUPPORTEDMODE;
+	}
+	if (this->d.fb_width < width) {
+		sprintf(buf,"SetDisplayMode(w=%ld,h=%ld,d=%ld), width %ld exceeds framebuffer width %ld",width,height,depth,width,this->d.fb_width);
+		MessageBox32A(0,buf,"WINE DirectDraw",MB_OK|MB_ICONSTOP);
+		return DDERR_UNSUPPORTEDMODE;
+	}
+	this->d.width	= width;
+	this->d.height	= height;
+	/* adjust fb_height, so we don't overlap */
+	if (this->d.fb_height < height)
+		this->d.fb_height = height;
+	this->d.depth	= depth;
+	XF86DGADirectVideo(display,DefaultScreen(display),XF86DGADirectGraphics);
+	return 0;
+}
+static HRESULT WINAPI IDirectDraw_GetCaps(
+	LPDIRECTDRAW this,LPDDCAPS caps1,LPDDCAPS caps2
+)  {
+	fprintf(stderr,"IDirectDraw(%p)->GetCaps(%p,%p),stub!\n",this,caps1,caps2);
+	caps1->dwVidMemTotal = this->d.fb_memsize;
+	caps1->dwCaps = 0; /* we cannot do anything */
+	caps1->ddsCaps.dwCaps = 0; /* we cannot do anything */
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDraw2_GetCaps(
+	LPDIRECTDRAW2 this,LPDDCAPS caps1,LPDDCAPS caps2
+)  {
+	fprintf(stderr,"IDirectDraw2(%p)->GetCaps(%p,%p),stub!\n",this,caps1,caps2);
+	caps1->dwVidMemTotal = this->d.fb_memsize;
+	caps1->dwCaps = 0; /* we cannot do anything */
+	caps1->ddsCaps.dwCaps = 0;
+	return 0;
+}
+
+
+static struct IDirectDrawClipper_VTable ddclipvt = {
+	1,2,3,4,5,6,0x10007,8,9
+};
+
+static HRESULT WINAPI IDirectDraw_CreateClipper(
+	LPDIRECTDRAW this,DWORD x,LPDIRECTDRAWCLIPPER *lpddclip,LPUNKNOWN lpunk
+) {
+	fprintf(stderr,"IDirectDraw(%p)->CreateClipper(%08lx,%p,%p),stub!\n",
+		this,x,lpddclip,lpunk
+	);
+	*lpddclip = (LPDIRECTDRAWCLIPPER)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectDrawClipper));
+	(*lpddclip)->ref = 1;
+	(*lpddclip)->lpvtbl = &ddclipvt;
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawPalette_GetEntries(
+	LPDIRECTDRAWPALETTE this,DWORD x,DWORD y,DWORD z,LPPALETTEENTRY palent
+) {
+	fprintf(stderr,"IDirectDrawPalette(%p)->GetEntries(%08lx,%08lx,%08lx,%p),stub!\n",
+		this,x,y,z,palent
+	);
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDrawPalette_SetEntries(
+	LPDIRECTDRAWPALETTE this,DWORD x,DWORD start,DWORD end,LPPALETTEENTRY palent
+) {
+	XColor		xc;
+	int		i;
+
+	fprintf(stderr,"IDirectDrawPalette(%p)->SetEntries(%08lx,%ld,%ld,%p)\n",
+		this,x,start,end,palent
+	);
+	if (!this->cm) /* should not happen */ {
+		fprintf(stderr,"no colormap in SetEntries???\n");
+		return DDERR_GENERIC;
+	}
+	XFreeColormap(display,this->cm);
+	this->cm = XCreateColormap(display,DefaultRootWindow(display),DefaultVisual(display,DefaultScreen(display)),AllocAll);
+	xc.red = xc.blue = xc.green = 0; xc.flags = DoRed|DoGreen|DoBlue; xc.pixel = 0; XStoreColor(display,this->cm,&xc);
+	xc.red = xc.blue = xc.green = 0xffff; xc.flags = DoRed|DoGreen|DoBlue; xc.pixel = 255; XStoreColor(display,this->cm,&xc);
+	for (i=start;i<end;i++) {
+		xc.red = palent[i-start].peRed<<8;
+		xc.blue = palent[i-start].peBlue<<8;
+		xc.green = palent[i-start].peGreen<<8;
+		xc.flags = DoRed|DoBlue|DoGreen;
+		xc.pixel = i;
+		XStoreColor(display,this->cm,&xc);
+	}
+	XF86DGAInstallColormap(display,DefaultScreen(display),this->cm);
+	return 0;
+}
+
+static ULONG WINAPI IDirectDrawPalette_Release(LPDIRECTDRAWPALETTE this) {
+	fprintf(stderr,"IDirectDrawPalette(%p)->Release()\n",this);
+	if (!--(this->ref)) {
+		fprintf(stderr,"IDirectDrawPalette(%p) freed!\n",this);
+		if (this->cm) {
+			XFreeColormap(display,this->cm);
+			this->cm = 0;
+		}
+		HeapFree(GetProcessHeap(),0,this);
+		return 0;
+	}
+	return this->ref;
+}
+
+static ULONG WINAPI IDirectDrawPalette_AddRef(LPDIRECTDRAWPALETTE this) {
+	fprintf(stderr,"IDirectDrawPalette(%p)->AddRef()\n",this);
+	return ++(this->ref);
+}
+
+static struct IDirectDrawPalette_VTable ddpalvt = {
+	1,
+	IDirectDrawPalette_AddRef,
+	IDirectDrawPalette_Release,
+	4,
+	IDirectDrawPalette_GetEntries,
+	6,
+	IDirectDrawPalette_SetEntries
+};
+
+static HRESULT WINAPI IDirectDraw_CreatePalette(
+	LPDIRECTDRAW this,DWORD x,LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
+) {
+	fprintf(stderr,"IDirectDraw(%p)->CreatePalette(%08lx,%p,%p,%p),stub!\n",
+		this,x,palent,lpddpal,lpunk
+	);
+	*lpddpal = (LPDIRECTDRAWPALETTE)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectDrawPalette));
+	(*lpddpal)->ref = 1;
+	(*lpddpal)->lpvtbl = &ddpalvt;
+	(*lpddpal)->ddraw = this;
+	if (this->d.depth<=8) {
+		(*lpddpal)->cm = XCreateColormap(display,DefaultRootWindow(display),DefaultVisual(display,DefaultScreen(display)),AllocAll);
+		fprintf(stderr,"created colormap...\n");
+	} else /* we don't want palettes in hicolor or truecolor */
+		(*lpddpal)->cm = 0;
+
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDraw2_CreatePalette(
+	LPDIRECTDRAW2 this,DWORD x,LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
+) {
+	return IDirectDraw_CreatePalette((LPDIRECTDRAW)this,x,palent,lpddpal,lpunk);
+}
+
+static HRESULT WINAPI IDirectDraw_WaitForVerticalBlank(
+	LPDIRECTDRAW this,DWORD x,HANDLE32 h
+) {
+	fprintf(stderr,"IDirectDraw(%p)->WaitForVerticalBlank(0x%08lx,0x%08x),stub!\n",this,x,h);
+	return 0;
+}
+
+static ULONG WINAPI IDirectDraw_AddRef(LPDIRECTDRAW this) {
+	dprintf_relay(stddeb,"IDirectDraw(%p)->AddRef()\n",this);
+	return ++(this->ref);
+}
+
+static ULONG WINAPI IDirectDraw_Release(LPDIRECTDRAW this) {
+	dprintf_relay(stddeb,"IDirectDraw(%p)->Release()\n",this);
+	if (!--(this->ref)) {
+		fprintf(stderr,"IDirectDraw::Release:freeing IDirectDraw(%p)\n",this);
+		HeapFree(GetProcessHeap(),0,this);
+		return 0;
+	}
+	return this->ref;
+}
+
+static HRESULT WINAPI IDirectDraw2_QueryInterface(
+	LPDIRECTDRAW2 this,REFIID refiid,LPVOID *obj
+) {
+	return IDirectDraw_QueryInterface((LPDIRECTDRAW)this,refiid,obj);
+}
+
+static ULONG WINAPI IDirectDraw2_AddRef(LPDIRECTDRAW2 this) {
+	return IDirectDraw_AddRef((LPDIRECTDRAW)this);
+}
+
+static ULONG WINAPI IDirectDraw2_Release(LPDIRECTDRAW2 this) {
+	return IDirectDraw_Release((LPDIRECTDRAW)this);
+}
+
+static HRESULT WINAPI IDirectDraw2_SetCooperativeLevel(
+	LPDIRECTDRAW2 this,HWND32 hwnd,DWORD x
+) {
+	fprintf(stderr,"IDirectDraw2(%p)->SetCooperativeLevel(%08lx,%08lx),stub!\n",
+		this,(DWORD)hwnd,x
+	);
+	this->d.mainwindow = hwnd;
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDraw2_SetDisplayMode(
+	LPDIRECTDRAW2 this,DWORD width,DWORD height,DWORD depth,DWORD xx,DWORD yy
+) {
+	fprintf(stderr,"IDirectDraw2(%p)->SetDisplayMode(%ld,%ld,%ld,%08lx,%08lx),stub!\n",this,width,height,depth,xx,yy);
+
+	return IDirectDraw_SetDisplayMode((LPDIRECTDRAW)this,width,height,depth);
+}
+
+static HRESULT WINAPI IDirectDraw2_RestoreDisplayMode(LPDIRECTDRAW2 this) {
+	fprintf(stderr,"IDirectDraw2(%p)->RestoreDisplayMode(),stub!\n",this);
+	XF86DGADirectVideo(display,DefaultScreen(display),0);
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDraw_RestoreDisplayMode(LPDIRECTDRAW this) {
+	fprintf(stderr,"IDirectDraw(%p)->RestoreDisplayMode(),stub!\n",this);
+	XF86DGADirectVideo(display,DefaultScreen(display),0);
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDraw2_EnumSurfaces(
+	LPDIRECTDRAW2 this,DWORD x,LPDDSURFACEDESC ddsfd,LPVOID context,LPDDENUMSURFACESCALLBACK ddsfcb
+) {
+	fprintf(stderr,"IDirectDraw2(%p)->EnumSurfaces(0x%08lx,%p,%p,%p),stub!\n",this,x,ddsfd,context,ddsfcb);
+	return 0;
+}
+
+static IDirectDraw2_VTable dd2vt = {
+	IDirectDraw2_QueryInterface,
+	IDirectDraw2_AddRef,
+	IDirectDraw2_Release,
+	4,
+	5/*IDirectDraw_CreateClipper*/,
+	IDirectDraw2_CreatePalette,
+	IDirectDraw2_CreateSurface,
+	8,
+	9,
+	IDirectDraw2_EnumSurfaces,
+	11,
+	IDirectDraw2_GetCaps,
+	13,
+	14,
+	15,
+	16,
+	17,
+	18,
+	19,
+	IDirectDraw2_RestoreDisplayMode,
+	IDirectDraw2_SetCooperativeLevel,
+	IDirectDraw2_SetDisplayMode,
+	23/*IDirectDraw_WaitForVerticalBlank*/,
+	24
+};
+
+static HRESULT WINAPI IDirectDraw_QueryInterface(
+	LPDIRECTDRAW this,REFIID refiid,LPVOID *obj
+) {
+        char    xrefiid[50];
+
+        StringFromCLSID((LPCLSID)refiid,xrefiid);
+        fprintf(stderr,"IDirectDraw(%p)->QueryInterface(%s,%p)\n",this,xrefiid,obj);
+        if (!memcmp(&IID_IDirectDraw,refiid,sizeof(IID_IDirectDraw))) {
+                *obj = this;
+		this->lpvtbl->fnAddRef(this);
+                return 0;
+        }
+        if (!memcmp(&IID_IDirectDraw2,refiid,sizeof(IID_IDirectDraw2))) {
+		/* FIXME FIXME FIXME */
+		this->lpvtbl = (LPDIRECTDRAW_VTABLE)&dd2vt;
+		this->lpvtbl->fnAddRef(this);
+                *obj = this;
+                return 0;
+        }
+        return OLE_E_ENUM_NOMORE;
+}
+
+static HRESULT WINAPI IDirectDraw_GetVerticalBlankStatus(
+	LPDIRECTDRAW this,BOOL32 *status
+) {
+        fprintf(stderr,"IDirectDraw(%p)->GetVerticalBlankSatus(%p)\n",this,status);
+	*status = TRUE;
+	return 0;
+}
+
+static HRESULT WINAPI IDirectDraw_EnumDisplayModes(
+	LPDIRECTDRAW this,DWORD dwFlags,LPDDSURFACEDESC lpddsfd,LPVOID context,LPDDENUMMODESCALLBACK modescb
+) {
+	DDSURFACEDESC	ddsfd;
+
+	fprintf(stderr,"IDirectDraw(%p)->EnumDisplayModes(0x%08lx,%p,%p,%p),stub!\n",this,dwFlags,lpddsfd,context,modescb);
+	ddsfd.dwSize = sizeof(ddsfd);
+	ddsfd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_CAPS|DDSD_BACKBUFFERCOUNT|DDSD_REFRESHRATE;
+	ddsfd.dwHeight = 480;
+	ddsfd.dwWidth = 640;
+	ddsfd.lPitch = 640;
+	ddsfd.ddsCaps.dwCaps = DDSCAPS_PALETTE|DDSCAPS_FRONTBUFFER|DDSCAPS_BACKBUFFER|DDSCAPS_FLIP|DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY|DDSCAPS_ZBUFFER;
+	ddsfd.dwBackBufferCount = 1;
+	ddsfd.x.dwRefreshRate = 60;
+	_getpixelformat(this,&(ddsfd.ddpfPixelFormat));
+	fprintf(stderr,"modescb returned: 0x%lx\n",(DWORD)modescb(&ddsfd,context));
+	return 0;
+}
+
+
+static IDirectDraw_VTable ddvt = {
+	IDirectDraw_QueryInterface,
+	IDirectDraw_AddRef,
+	IDirectDraw_Release,
+	4,
+	IDirectDraw_CreateClipper,
+	IDirectDraw_CreatePalette,
+	IDirectDraw_CreateSurface,
+	IDirectDraw_DuplicateSurface,
+	IDirectDraw_EnumDisplayModes,
+	10,
+	11,
+	IDirectDraw_GetCaps,
+	13,
+	14,
+	15,
+	16,
+	17,
+	IDirectDraw_GetVerticalBlankStatus,
+	19,
+	IDirectDraw_RestoreDisplayMode,
+	IDirectDraw_SetCooperativeLevel,
+	IDirectDraw_SetDisplayMode,
+	IDirectDraw_WaitForVerticalBlank,
+};
+
+
+HRESULT WINAPI DirectDrawCreate( LPGUID lpGUID, LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnkOuter ) {
+
+	char	xclsid[50];
+	int	memsize,banksize,width,evbase,evret,major,minor,flags,height;
+	char	*addr;
+	
+
+	if (lpGUID)
+		StringFromCLSID(lpGUID,xclsid);
+	else
+		strcpy(xclsid,"<null>");
+
+	fprintf(stderr,"DirectDrawCreate(%s,%p,%p)\n",xclsid,lplpDD,pUnkOuter);
+	if (getuid()) {
+		MessageBox32A(0,"Using the XF86DGA extensions requires the program to be run using UID 0.","WINE DirectDraw",MB_OK|MB_ICONSTOP);
+		return E_UNEXPECTED;
+	}
+	*lplpDD = (LPDIRECTDRAW)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectDraw));
+	(*lplpDD)->lpvtbl = &ddvt;
+	(*lplpDD)->ref = 1;
+	if (!XF86DGAQueryExtension(display,&evbase,&evret)) {
+		fprintf(stderr,"No XF86DGA detected.\n");
+		return 0;
+	}
+	XF86DGAQueryVersion(display,&major,&minor);
+	fprintf(stderr,"XF86DGA is version %d.%d\n",major,minor);
+	XF86DGAQueryDirectVideo(display,DefaultScreen(display),&flags);
+	if (!(flags & XF86DGADirectPresent))
+		fprintf(stderr,"direct video is NOT ENABLED.\n");
+	XF86DGAGetVideo(display,DefaultScreen(display),&addr,&width,&banksize,&memsize);
+	fprintf(stderr,"video framebuffer: begin %p, width %d,banksize %d,memsize %d\n",
+		addr,width,banksize,memsize
+	);
+	(*lplpDD)->d.fb_width = width;
+	(*lplpDD)->d.fb_addr = addr;
+	(*lplpDD)->d.fb_memsize = memsize;
+	(*lplpDD)->d.fb_banksize = banksize;
+
+	XF86DGASetViewPort(display,DefaultScreen(display),0,0);
+	while (!XF86DGAViewPortChanged(display,DefaultScreen(display),1)) {
+		fprintf(stderr,".");
+	}
+	XF86DGAGetViewPortSize(display,DefaultScreen(display),&width,&height);
+	(*lplpDD)->d.vp_width = width;
+	(*lplpDD)->d.vp_height = height;
+	(*lplpDD)->d.fb_height = height; /* FIXME: can we find out the virtual
+	 				* size somehow else ?
+					*/
+	(*lplpDD)->d.current_height = 0;
+	return 0;
+}
+#else
+
+HRESULT WINAPI DirectDrawCreate( LPGUID lpGUID, LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnkOuter ) {
+	MessageBox32A(0,"WINE DirectDraw needs the XF86DGA extensions compiled in. (libXxf86dga.a).","WINE DirectDraw",MB_OK|MB_ICONSTOP);
+	return E_OUTOFMEMORY;
+}
+#endif
diff --git a/graphics/painting.c b/graphics/painting.c
index 9b169e4..cec3d9c 100644
--- a/graphics/painting.c
+++ b/graphics/painting.c
@@ -19,7 +19,6 @@
 #include "callback.h"
 #include "heap.h"
 #include "metafile.h"
-#include "syscolor.h"
 #include "palette.h"
 #include "cache.h"
 #include "color.h"
@@ -513,7 +512,7 @@
  */
 void WINAPI DrawFocusRect32( HDC32 hdc, const RECT32* rc )
 {
-    HPEN32 hOldPen;
+    HPEN32 hOldPen, hnewPen;
     INT32 oldDrawMode, oldBkMode;
     INT32 left, top, right, bottom;
 
@@ -525,7 +524,8 @@
     right  = XLPTODP( dc, rc->right );
     bottom = YLPTODP( dc, rc->bottom );
     
-    hOldPen = SelectObject32( hdc, sysColorObjects.hpenWindowText );
+    hnewPen = CreatePen32(PS_DOT, 1, GetSysColor32(COLOR_WINDOWTEXT) );
+    hOldPen = SelectObject32( hdc, hnewPen );
     oldDrawMode = SetROP232(hdc, R2_XORPEN);
     oldBkMode = SetBkMode32(hdc, TRANSPARENT);
 
@@ -540,6 +540,7 @@
     SetBkMode32(hdc, oldBkMode);
     SetROP232(hdc, oldDrawMode);
     SelectObject32(hdc, hOldPen);
+    DeleteObject32(hnewPen);
 }
 
 
diff --git a/graphics/win16drv/init.c b/graphics/win16drv/init.c
index e00e638..faac26e 100644
--- a/graphics/win16drv/init.c
+++ b/graphics/win16drv/init.c
@@ -604,7 +604,7 @@
 
     PROFILE_GetWineIniString( "spooler", pszOutput, "",
                               psCmd, sizeof(psCmd) );
-    printf("Got printerSpoolCOmmand \"%s\"\n",psCmd);
+    printf("Got printerSpoolCommand \"%s\"\n",psCmd);
     if (!*psCmd)
         psCmdP = pszOutput;
     else
@@ -635,7 +635,7 @@
         }
         close (fds[0]);
         fd = fds[1];
-        printf("Need to execut a command and pipe the output to it\n");
+        printf("Need to execute a command and pipe the output to it\n");
     }
     else
     {
diff --git a/graphics/x11drv/brush.c b/graphics/x11drv/brush.c
index a162ad7..5b38fa6 100644
--- a/graphics/x11drv/brush.c
+++ b/graphics/x11drv/brush.c
@@ -164,10 +164,22 @@
 {
     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
     if (!bmp) return FALSE;
-    dc->u.x.brush.pixmap = XCreatePixmap( display, rootWindow,
-					  8, 8, bmp->bitmap.bmBitsPixel );
-    XCopyArea( display, bmp->pixmap, dc->u.x.brush.pixmap,
-	       BITMAP_GC(bmp), 0, 0, 8, 8, 0, 0 );
+
+    if ((dc->w.bitsPerPixel == 1) && (bmp->bitmap.bmBitsPixel != 1))
+    {
+        /* Special case: a color pattern on a monochrome DC */
+        dc->u.x.brush.pixmap = XCreatePixmap( display, rootWindow, 8, 8, 1 );
+        /* FIXME: should probably convert to monochrome instead */
+        XCopyPlane( display, bmp->pixmap, dc->u.x.brush.pixmap,
+                    BITMAP_monoGC, 0, 0, 8, 8, 0, 0, 1 );
+    }
+    else
+    {
+        dc->u.x.brush.pixmap = XCreatePixmap( display, rootWindow,
+                                              8, 8, bmp->bitmap.bmBitsPixel );
+        XCopyArea( display, bmp->pixmap, dc->u.x.brush.pixmap,
+                   BITMAP_GC(bmp), 0, 0, 8, 8, 0, 0 );
+    }
     
     if (bmp->bitmap.bmBitsPixel > 1)
     {
diff --git a/graphics/x11drv/graphics.c b/graphics/x11drv/graphics.c
index 9348d91..d6e42e4 100644
--- a/graphics/x11drv/graphics.c
+++ b/graphics/x11drv/graphics.c
@@ -25,7 +25,6 @@
 #include "bitmap.h"
 #include "callback.h"
 #include "metafile.h"
-#include "syscolor.h"
 #include "stddebug.h"
 #include "palette.h"
 #include "color.h"
diff --git a/if1632/builtin.c b/if1632/builtin.c
index 273908a..7076b1e 100644
--- a/if1632/builtin.c
+++ b/if1632/builtin.c
@@ -370,7 +370,9 @@
                 break;
             }
         }
-        if (!dll->descr) return FALSE;
+        if (!dll->descr)
+            if (!BUILTIN32_EnableDLL( str, (int)(p - str), (str[-1] == '+') ))
+                return FALSE;
         str = p;
         while (*str && (isspace(*str) || (*str == ','))) str++;
     }
@@ -389,7 +391,7 @@
     BUILTIN16_DLL *dll;
 
     fprintf(stderr,"Example: -dll -ole2    Do not use emulated OLE2.DLL\n");
-    fprintf(stderr,"Available DLLs:\n");
+    fprintf(stderr,"Available Win16 DLLs:\n");
     for (i = 0, dll = BuiltinDLLs; dll->descr; dll++)
     {
         if (!(dll->flags & DLL_FLAG_ALWAYS_USED))
@@ -397,4 +399,5 @@
                      ((++i) % 8) ? ' ' : '\n' );
     }
     fprintf(stderr,"\n");
+    BUILTIN32_PrintDLLs();
 }
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index db1dae2..69ee55f 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -327,7 +327,7 @@
 515 pascal   GetProcAddress32W(long str) GetProcAddress32
 516 pascal GetVDMPointer32W(segptr long) GetVDMPointer32W
 517 pascal CallProc32W() WIN16_CallProc32W
-518 stub CallProcEx32W
+518 pascal CallProcEx32W() WIN16_CallProcEx32W 
 519 stub KERNEL_519
 522 stub KERNEL_522
 523 stub KERNEL_523
diff --git a/if1632/relay.c b/if1632/relay.c
index 6596be5..8e247ff 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -321,10 +321,13 @@
     }
 }
 
+
 /**********************************************************************
- *	     CallProc32W    (KERNEL.517)
+ *	     RELAY_CallProc32W
+ *
+ * Helper for CallProc[Ex]32W
  */
-DWORD WINAPI WIN16_CallProc32W()
+static DWORD RELAY_CallProc32W(int Ex)
 {
 	DWORD nrofargs, argconvmask;
 	FARPROC32 proc32;
@@ -336,7 +339,7 @@
         nrofargs    = VA_ARG16( valist, DWORD );
         argconvmask = VA_ARG16( valist, DWORD );
         proc32      = VA_ARG16( valist, FARPROC32 );
-	fprintf(stderr,"CallProc32W(%ld,%ld,%p,args[",nrofargs,argconvmask,proc32);
+	fprintf(stderr,"CallProc32W(%ld,%ld,%p, Ex%d args[",nrofargs,argconvmask,proc32,Ex);
 	args = (DWORD*)HEAP_xalloc( GetProcessHeap(), 0,
                                     sizeof(DWORD)*nrofargs );
 	for (i=0;i<nrofargs;i++) {
@@ -379,9 +382,29 @@
 		break;
 	}
 	/* POP nrofargs DWORD arguments and 3 DWORD parameters */
-        STACK16_POP( (3 + nrofargs) * sizeof(DWORD) );
+        if (!Ex) STACK16_POP( (3 + nrofargs) * sizeof(DWORD) );
 
 	fprintf(stderr,"returns %08lx\n",ret);
 	HeapFree( GetProcessHeap(), 0, args );
 	return ret;
 }
+
+
+/**********************************************************************
+ *	     CallProc32W    (KERNEL.517)
+ */
+DWORD WINAPI WIN16_CallProc32W()
+{
+        return RELAY_CallProc32W(0);
+}
+
+
+/**********************************************************************
+*           CallProcEx32W()   (KERNEL.518)        
+*
+*      C - style linkage to CallProc32W - caller pops stack.
+*/ 
+DWORD WINAPI WIN16_CallProcEx32W()
+{
+	return RELAY_CallProc32W(TRUE);
+}
diff --git a/if1632/signal.c b/if1632/signal.c
index 003e062..d1df7c5 100644
--- a/if1632/signal.c
+++ b/if1632/signal.c
@@ -180,44 +180,20 @@
 
 
 /**********************************************************************
- *		SIGNAL_tick
- *
- * Tick handler.
- */
-static HANDLER_DEF(SIGNAL_tick)
-{
-    CONTEXT nt_context;
-    SIGNAL_SetSigContext( HANDLER_CONTEXT, &nt_context );
-    if (THREAD_SwitchThread( &nt_context ))
-        SIGNAL_GetSigContext( HANDLER_CONTEXT, &nt_context );
-}
-
-/**********************************************************************
  *		SIGNAL_InitEmulator
  *
  * Initialize emulator signals.
  */
 BOOL32 SIGNAL_InitEmulator(void)
 {
-    struct itimerval vt_timer;
-
     SIGNAL_SetHandler( SIGINT,  (void (*)())SIGNAL_break, 1);
     SIGNAL_SetHandler( SIGSEGV, (void (*)())SIGNAL_fault, 1);
     SIGNAL_SetHandler( SIGILL,  (void (*)())SIGNAL_fault, 1);
     SIGNAL_SetHandler( SIGFPE,  (void (*)())SIGNAL_fault, 1);
-    SIGNAL_SetHandler( SIGVTALRM, (void (*)())SIGNAL_tick,  0);
     SIGNAL_SetHandler( SIGTRAP, (void (*)())SIGNAL_trap,  1); /* debugger */
     SIGNAL_SetHandler( SIGHUP,  (void (*)())SIGNAL_trap,  1); /* forced break*/
 #ifdef SIGBUS
     SIGNAL_SetHandler( SIGBUS,  (void (*)())SIGNAL_fault, 1);
 #endif
-
-    /* Start the tick timer */
-#if 0
-    vt_timer.it_interval.tv_sec = 0;
-    vt_timer.it_interval.tv_usec = 10000;
-    vt_timer.it_value = vt_timer.it_interval;
-    setitimer( ITIMER_VIRTUAL, &vt_timer, NULL );
-#endif
     return TRUE;
 }
diff --git a/include/builtin32.h b/include/builtin32.h
index 56532a3..4d3dd3b 100644
--- a/include/builtin32.h
+++ b/include/builtin32.h
@@ -27,5 +27,7 @@
                                              unsigned int *typemask );
 extern void BUILTIN32_Unimplemented( const BUILTIN32_DESCRIPTOR *descr,
                                      int ordinal );
+extern void BUILTIN32_PrintDLLs(void);
+extern int BUILTIN32_EnableDLL( const char *name, int len, int enable );
 
 #endif /* __WINE_BUILTIN32_H */
diff --git a/include/config.h.in b/include/config.h.in
index 2d301c7..40d489b 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -18,6 +18,9 @@
 /* Define if symbols declared in assembly code need an underscore prefix */
 #undef NEED_UNDERSCORE_PREFIX
 
+/* Define if you have the clone function.  */
+#undef HAVE_CLONE
+
 /* Define if you have the memmove function.  */
 #undef HAVE_MEMMOVE
 
@@ -35,3 +38,15 @@
 
 /* Define if you have the waitpid function.  */
 #undef HAVE_WAITPID
+
+/* Define if you have the <wctype.h> header file.  */
+#undef HAVE_WCTYPE_H
+
+/* Define if you have the Xxf86dga library (-lXxf86dga).  */
+#undef HAVE_LIBXXF86DGA
+
+/* Define if you have the i386 library (-li386).  */
+#undef HAVE_LIBI386
+
+/* Define if you have the w library (-lw).  */
+#undef HAVE_LIBW
diff --git a/include/ddraw.h b/include/ddraw.h
new file mode 100644
index 0000000..3197b85
--- /dev/null
+++ b/include/ddraw.h
@@ -0,0 +1,898 @@
+#ifndef __WINE_DDRAW_H
+#define __WINE_DDRAW_H
+
+#include <X11/Xlib.h>
+
+
+DEFINE_GUID( CLSID_DirectDraw,		0xD7B70EE0,0x4340,0x11CF,0xB0,0x63,0x00,0x20,0xAF,0xC2,0xCD,0x35 );
+DEFINE_GUID( CLSID_DirectDrawClipper,	0x593817A0,0x7DB3,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xb9,0x33,0x56 );
+DEFINE_GUID( IID_IDirectDraw,		0x6C14DB80,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 );
+DEFINE_GUID( IID_IDirectDraw2,		0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 );
+DEFINE_GUID( IID_IDirectDrawSurface,	0x6C14DB81,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 );
+DEFINE_GUID( IID_IDirectDrawSurface2,	0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27 );
+DEFINE_GUID( IID_IDirectDrawPalette,	0x6C14DB84,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 );
+DEFINE_GUID( IID_IDirectDrawClipper,	0x6C14DB85,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 );
+
+typedef struct IDirectDraw IDirectDraw,*LPDIRECTDRAW;
+typedef struct IDirectDraw2 IDirectDraw2,*LPDIRECTDRAW2;
+typedef struct IDirectDrawClipper IDirectDrawClipper,*LPDIRECTDRAWCLIPPER;
+typedef struct IDirectDrawPalette IDirectDrawPalette,*LPDIRECTDRAWPALETTE;
+typedef struct IDirectDrawSurface IDirectDrawSurface,*LPDIRECTDRAWSURFACE;
+typedef struct IDirectDrawSurface2 IDirectDrawSurface2,*LPDIRECTDRAWSURFACE2;
+
+#define _FACDD		0x876
+#define MAKE_DDHRESULT( code )  MAKE_HRESULT( 1, _FACDD, code )
+
+#define DDERR_ALREADYINITIALIZED		MAKE_DDHRESULT( 5 )
+#define DDERR_CANNOTATTACHSURFACE		MAKE_DDHRESULT( 10 )
+#define DDERR_CANNOTDETACHSURFACE		MAKE_DDHRESULT( 20 )
+#define DDERR_CURRENTLYNOTAVAIL			MAKE_DDHRESULT( 40 )
+#define DDERR_EXCEPTION				MAKE_DDHRESULT( 55 )
+#define DDERR_GENERIC				E_FAIL
+#define DDERR_HEIGHTALIGN			MAKE_DDHRESULT( 90 )
+#define DDERR_INCOMPATIBLEPRIMARY		MAKE_DDHRESULT( 95 )
+#define DDERR_INVALIDCAPS			MAKE_DDHRESULT( 100 )
+#define DDERR_INVALIDCLIPLIST			MAKE_DDHRESULT( 110 )
+#define DDERR_INVALIDMODE			MAKE_DDHRESULT( 120 )
+#define DDERR_INVALIDOBJECT			MAKE_DDHRESULT( 130 )
+#define DDERR_INVALIDPARAMS			E_INVALIDARG
+#define DDERR_INVALIDPIXELFORMAT		MAKE_DDHRESULT( 145 )
+#define DDERR_INVALIDRECT			MAKE_DDHRESULT( 150 )
+#define DDERR_LOCKEDSURFACES			MAKE_DDHRESULT( 160 )
+#define DDERR_NO3D				MAKE_DDHRESULT( 170 )
+#define DDERR_NOALPHAHW				MAKE_DDHRESULT( 180 )
+#define DDERR_NOCLIPLIST			MAKE_DDHRESULT( 205 )
+#define DDERR_NOCOLORCONVHW			MAKE_DDHRESULT( 210 )
+#define DDERR_NOCOOPERATIVELEVELSET		MAKE_DDHRESULT( 212 )
+#define DDERR_NOCOLORKEY			MAKE_DDHRESULT( 215 )
+#define DDERR_NOCOLORKEYHW			MAKE_DDHRESULT( 220 )
+#define DDERR_NODIRECTDRAWSUPPORT		MAKE_DDHRESULT( 222 )
+#define DDERR_NOEXCLUSIVEMODE			MAKE_DDHRESULT( 225 )
+#define DDERR_NOFLIPHW				MAKE_DDHRESULT( 230 )
+#define DDERR_NOGDI				MAKE_DDHRESULT( 240 )
+#define DDERR_NOMIRRORHW			MAKE_DDHRESULT( 250 )
+#define DDERR_NOTFOUND				MAKE_DDHRESULT( 255 )
+#define DDERR_NOOVERLAYHW			MAKE_DDHRESULT( 260 )
+#define DDERR_NORASTEROPHW			MAKE_DDHRESULT( 280 )
+#define DDERR_NOROTATIONHW			MAKE_DDHRESULT( 290 )
+#define DDERR_NOSTRETCHHW			MAKE_DDHRESULT( 310 )
+#define DDERR_NOT4BITCOLOR			MAKE_DDHRESULT( 316 )
+#define DDERR_NOT4BITCOLORINDEX			MAKE_DDHRESULT( 317 )
+#define DDERR_NOT8BITCOLOR			MAKE_DDHRESULT( 320 )
+#define DDERR_NOTEXTUREHW			MAKE_DDHRESULT( 330 )
+#define DDERR_NOVSYNCHW				MAKE_DDHRESULT( 335 )
+#define DDERR_NOZBUFFERHW			MAKE_DDHRESULT( 340 )
+#define DDERR_NOZOVERLAYHW			MAKE_DDHRESULT( 350 )
+#define DDERR_OUTOFCAPS				MAKE_DDHRESULT( 360 )
+#define DDERR_OUTOFMEMORY			E_OUTOFMEMORY
+#define DDERR_OUTOFVIDEOMEMORY			MAKE_DDHRESULT( 380 )
+#define DDERR_OVERLAYCANTCLIP			MAKE_DDHRESULT( 382 )
+#define DDERR_OVERLAYCOLORKEYONLYONEACTIVE	MAKE_DDHRESULT( 384 )
+#define DDERR_PALETTEBUSY			MAKE_DDHRESULT( 387 )
+#define DDERR_COLORKEYNOTSET			MAKE_DDHRESULT( 400 )
+#define DDERR_SURFACEALREADYATTACHED		MAKE_DDHRESULT( 410 )
+#define DDERR_SURFACEALREADYDEPENDENT		MAKE_DDHRESULT( 420 )
+#define DDERR_SURFACEBUSY			MAKE_DDHRESULT( 430 )
+#define DDERR_CANTLOCKSURFACE			MAKE_DDHRESULT( 435 )
+#define DDERR_SURFACEISOBSCURED			MAKE_DDHRESULT( 440 )
+#define DDERR_SURFACELOST			MAKE_DDHRESULT( 450 )
+#define DDERR_SURFACENOTATTACHED		MAKE_DDHRESULT( 460 )
+#define DDERR_TOOBIGHEIGHT			MAKE_DDHRESULT( 470 )
+#define DDERR_TOOBIGSIZE			MAKE_DDHRESULT( 480 )
+#define DDERR_TOOBIGWIDTH			MAKE_DDHRESULT( 490 )
+#define DDERR_UNSUPPORTED			E_NOTIMPL
+#define DDERR_UNSUPPORTEDFORMAT			MAKE_DDHRESULT( 510 )
+#define DDERR_UNSUPPORTEDMASK			MAKE_DDHRESULT( 520 )
+#define DDERR_VERTICALBLANKINPROGRESS		MAKE_DDHRESULT( 537 )
+#define DDERR_WASSTILLDRAWING			MAKE_DDHRESULT( 540 )
+#define DDERR_XALIGN				MAKE_DDHRESULT( 560 )
+#define DDERR_INVALIDDIRECTDRAWGUID		MAKE_DDHRESULT( 561 )
+#define DDERR_DIRECTDRAWALREADYCREATED		MAKE_DDHRESULT( 562 )
+#define DDERR_NODIRECTDRAWHW			MAKE_DDHRESULT( 563 )
+#define DDERR_PRIMARYSURFACEALREADYEXISTS	MAKE_DDHRESULT( 564 )
+#define DDERR_NOEMULATION			MAKE_DDHRESULT( 565 )
+#define DDERR_REGIONTOOSMALL			MAKE_DDHRESULT( 566 )
+#define DDERR_CLIPPERISUSINGHWND		MAKE_DDHRESULT( 567 )
+#define DDERR_NOCLIPPERATTACHED			MAKE_DDHRESULT( 568 )
+#define DDERR_NOHWND				MAKE_DDHRESULT( 569 )
+#define DDERR_HWNDSUBCLASSED			MAKE_DDHRESULT( 570 )
+#define DDERR_HWNDALREADYSET			MAKE_DDHRESULT( 571 )
+#define DDERR_NOPALETTEATTACHED			MAKE_DDHRESULT( 572 )
+#define DDERR_NOPALETTEHW			MAKE_DDHRESULT( 573 )
+#define DDERR_BLTFASTCANTCLIP			MAKE_DDHRESULT( 574 )
+#define DDERR_NOBLTHW				MAKE_DDHRESULT( 575 )
+#define DDERR_NODDROPSHW			MAKE_DDHRESULT( 576 )
+#define DDERR_OVERLAYNOTVISIBLE			MAKE_DDHRESULT( 577 )
+#define DDERR_NOOVERLAYDEST			MAKE_DDHRESULT( 578 )
+#define DDERR_INVALIDPOSITION			MAKE_DDHRESULT( 579 )
+#define DDERR_NOTAOVERLAYSURFACE		MAKE_DDHRESULT( 580 )
+#define DDERR_EXCLUSIVEMODEALREADYSET		MAKE_DDHRESULT( 581 )
+#define DDERR_NOTFLIPPABLE			MAKE_DDHRESULT( 582 )
+#define DDERR_CANTDUPLICATE			MAKE_DDHRESULT( 583 )
+#define DDERR_NOTLOCKED				MAKE_DDHRESULT( 584 )
+#define DDERR_CANTCREATEDC			MAKE_DDHRESULT( 585 )
+#define DDERR_NODC				MAKE_DDHRESULT( 586 )
+#define DDERR_WRONGMODE				MAKE_DDHRESULT( 587 )
+#define DDERR_IMPLICITLYCREATED			MAKE_DDHRESULT( 588 )
+#define DDERR_NOTPALETTIZED			MAKE_DDHRESULT( 589 )
+#define DDERR_UNSUPPORTEDMODE			MAKE_DDHRESULT( 590 )
+#define DDERR_NOMIPMAPHW			MAKE_DDHRESULT( 591 )
+#define DDERR_INVALIDSURFACETYPE		MAKE_DDHRESULT( 592 )
+#define DDERR_DCALREADYCREATED			MAKE_DDHRESULT( 620 )
+#define DDERR_CANTPAGELOCK			MAKE_DDHRESULT( 640 )
+#define DDERR_CANTPAGEUNLOCK			MAKE_DDHRESULT( 660 )
+#define DDERR_NOTPAGELOCKED			MAKE_DDHRESULT( 680 )
+#define DDERR_NOTINITIALIZED			CO_E_NOTINITIALIZED
+
+/* dwFlags for Blt* */
+#define DDBLT_ALPHADEST				0x00000001
+#define DDBLT_ALPHADESTCONSTOVERRIDE		0x00000002
+#define DDBLT_ALPHADESTNEG			0x00000004
+#define DDBLT_ALPHADESTSURFACEOVERRIDE		0x00000008
+#define DDBLT_ALPHAEDGEBLEND			0x00000010
+#define DDBLT_ALPHASRC				0x00000020
+#define DDBLT_ALPHASRCCONSTOVERRIDE		0x00000040
+#define DDBLT_ALPHASRCNEG			0x00000080
+#define DDBLT_ALPHASRCSURFACEOVERRIDE		0x00000100
+#define DDBLT_ASYNC				0x00000200
+#define DDBLT_COLORFILL				0x00000400
+#define DDBLT_DDFX				0x00000800
+#define DDBLT_DDROPS				0x00001000
+#define DDBLT_KEYDEST				0x00002000
+#define DDBLT_KEYDESTOVERRIDE			0x00004000
+#define DDBLT_KEYSRC				0x00008000
+#define DDBLT_KEYSRCOVERRIDE			0x00010000
+#define DDBLT_ROP				0x00020000
+#define DDBLT_ROTATIONANGLE			0x00040000
+#define DDBLT_ZBUFFER				0x00080000
+#define DDBLT_ZBUFFERDESTCONSTOVERRIDE		0x00100000
+#define DDBLT_ZBUFFERDESTOVERRIDE		0x00200000
+#define DDBLT_ZBUFFERSRCCONSTOVERRIDE		0x00400000
+#define DDBLT_ZBUFFERSRCOVERRIDE		0x00800000
+#define DDBLT_WAIT				0x01000000
+#define DDBLT_DEPTHFILL				0x02000000
+
+/* dwTrans for BltFast */
+#define DDBLTFAST_NOCOLORKEY			0x00000000
+#define DDBLTFAST_SRCCOLORKEY			0x00000001
+#define DDBLTFAST_DESTCOLORKEY			0x00000002
+#define DDBLTFAST_WAIT				0x00000010
+
+/* dwFlags for Flip */
+#define DDFLIP_WAIT				0x00000001
+
+/* dwFlags for GetBltStatus */
+#define DDGBS_CANBLT				0x00000001
+#define DDGBS_ISBLTDONE				0x00000002
+
+/* 3d capable (no meaning?) */
+#define DDSCAPS_3D			0x00000001
+/* surface contains alpha information */
+#define DDSCAPS_ALPHA			0x00000002
+/* this surface is a backbuffer */
+#define DDSCAPS_BACKBUFFER		0x00000004
+/* complex surface structure */
+#define DDSCAPS_COMPLEX			0x00000008
+/* part of surface flipping structure */
+#define DDSCAPS_FLIP			0x00000010
+/* this surface is the frontbuffer surface */
+#define DDSCAPS_FRONTBUFFER		0x00000020
+/* this is a plain offscreen surface */
+#define DDSCAPS_OFFSCREENPLAIN		0x00000040
+/* overlay */
+#define DDSCAPS_OVERLAY			0x00000080
+/* palette objects can be created and attached to us */
+#define DDSCAPS_PALETTE			0x00000100
+/* primary surface (the one the user looks at currently)(right eye)*/
+#define DDSCAPS_PRIMARYSURFACE		0x00000200
+/* primary surface for left eye */
+#define DDSCAPS_PRIMARYSURFACELEFT	0x00000400
+/* surface exists in systemmemory */
+#define DDSCAPS_SYSTEMMEMORY		0x00000800
+/* surface can be used as a texture */
+#define DDSCAPS_TEXTURE		        0x00001000
+/* surface may be destination for 3d rendering */
+#define DDSCAPS_3DDEVICE		0x00002000
+/* surface exists in videomemory */
+#define DDSCAPS_VIDEOMEMORY		0x00004000
+/* surface changes immediately visible */
+#define DDSCAPS_VISIBLE			0x00008000
+/* write only surface */
+#define DDSCAPS_WRITEONLY		0x00010000
+/* zbuffer surface */
+#define DDSCAPS_ZBUFFER			0x00020000
+/* has its own DC */
+#define DDSCAPS_OWNDC			0x00040000
+/* surface should be able to receive live video */
+#define DDSCAPS_LIVEVIDEO		0x00080000
+/* should be able to have a hw codec decompress stuff into it */
+#define DDSCAPS_HWCODEC			0x00100000
+/* mode X (320x200 or 320x240) surface */
+#define DDSCAPS_MODEX			0x00200000
+/* one mipmap surface (1 level) */
+#define DDSCAPS_MIPMAP			0x00400000
+/* memory allocation delayed until Load() */
+#define DDSCAPS_ALLOCONLOAD		0x04000000
+
+typedef struct _DDSCAPS {
+	DWORD	dwCaps;	/* capabilities of surface wanted */
+} DDSCAPS,*LPDDSCAPS;
+
+#define	DD_ROP_SPACE	(256/32)	/* space required to store ROP array */
+
+typedef struct _DDCAPS
+{
+    DWORD	dwSize;                 /* size of the DDDRIVERCAPS structure */
+    DWORD	dwCaps;                 /* driver specific capabilities */
+    DWORD	dwCaps2;                /* more driver specific capabilites */
+    DWORD	dwCKeyCaps;             /* color key capabilities of the surface */
+    DWORD	dwFXCaps;               /* driver specific stretching and effects capabilites */
+    DWORD	dwFXAlphaCaps;          /* alpha driver specific capabilities */
+    DWORD	dwPalCaps;              /* palette capabilities */
+    DWORD	dwSVCaps;               /* stereo vision capabilities */
+    DWORD	dwAlphaBltConstBitDepths;       /* DDBD_2,4,8 */
+    DWORD	dwAlphaBltPixelBitDepths;       /* DDBD_1,2,4,8 */
+    DWORD	dwAlphaBltSurfaceBitDepths;     /* DDBD_1,2,4,8 */
+    DWORD	dwAlphaOverlayConstBitDepths;   /* DDBD_2,4,8 */
+    DWORD	dwAlphaOverlayPixelBitDepths;   /* DDBD_1,2,4,8 */
+    DWORD	dwAlphaOverlaySurfaceBitDepths; /* DDBD_1,2,4,8 */
+    DWORD	dwZBufferBitDepths;             /* DDBD_8,16,24,32 */
+    DWORD	dwVidMemTotal;          /* total amount of video memory */
+    DWORD	dwVidMemFree;           /* amount of free video memory */
+    DWORD	dwMaxVisibleOverlays;   /* maximum number of visible overlays */
+    DWORD	dwCurrVisibleOverlays;  /* current number of visible overlays */
+    DWORD	dwNumFourCCCodes;       /* number of four cc codes */
+    DWORD	dwAlignBoundarySrc;     /* source rectangle alignment */
+    DWORD	dwAlignSizeSrc;         /* source rectangle byte size */
+    DWORD	dwAlignBoundaryDest;    /* dest rectangle alignment */
+    DWORD	dwAlignSizeDest;        /* dest rectangle byte size */
+    DWORD	dwAlignStrideAlign;     /* stride alignment */
+    DWORD	dwRops[DD_ROP_SPACE];   /* ROPS supported */
+    DDSCAPS	ddsCaps;                /* DDSCAPS structure has all the general capabilities */
+    DWORD	dwMinOverlayStretch;    /* minimum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */
+    DWORD	dwMaxOverlayStretch;    /* maximum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */
+    DWORD	dwMinLiveVideoStretch;  /* minimum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */
+    DWORD	dwMaxLiveVideoStretch;  /* maximum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */
+    DWORD	dwMinHwCodecStretch;    /* minimum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */
+    DWORD	dwMaxHwCodecStretch;    /* maximum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */
+    DWORD	dwReserved1;
+    DWORD	dwReserved2;
+    DWORD	dwReserved3;
+    DWORD	dwSVBCaps;              /* driver specific capabilities for System->Vmem blts */
+    DWORD	dwSVBCKeyCaps;          /* driver color key capabilities for System->Vmem blts */
+    DWORD	dwSVBFXCaps;            /* driver FX capabilities for System->Vmem blts */
+    DWORD	dwSVBRops[DD_ROP_SPACE];/* ROPS supported for System->Vmem blts */
+    DWORD	dwVSBCaps;              /* driver specific capabilities for Vmem->System blts */
+    DWORD	dwVSBCKeyCaps;          /* driver color key capabilities for Vmem->System blts */
+    DWORD	dwVSBFXCaps;            /* driver FX capabilities for Vmem->System blts */
+    DWORD	dwVSBRops[DD_ROP_SPACE];/* ROPS supported for Vmem->System blts */
+    DWORD	dwSSBCaps;              /* driver specific capabilities for System->System blts */
+    DWORD	dwSSBCKeyCaps;          /* driver color key capabilities for System->System blts */
+    DWORD	dwSSBFXCaps;            /* driver FX capabilities for System->System blts */
+    DWORD	dwSSBRops[DD_ROP_SPACE];/* ROPS supported for System->System blts */
+    DWORD	dwReserved4;
+    DWORD	dwReserved5;
+    DWORD	dwReserved6;
+} DDCAPS,*LPDDCAPS;
+
+/* hw has 3d accel */
+#define DDCAPS_3D			0x00000001
+/* supports only boundary aligned rectangles */
+#define DDCAPS_ALIGNBOUNDARYDEST	0x00000002
+#define DDCAPS_ALIGNSIZEDEST		0x00000004
+#define DDCAPS_ALIGNBOUNDARYSRC		0x00000008
+#define DDCAPS_ALIGNSIZESRC		0x00000010
+#define DDCAPS_ALIGNSTRIDE		0x00000020
+#define DDCAPS_BLT			0x00000040
+#define DDCAPS_BLTQUEUE			0x00000080
+#define DDCAPS_BLTFOURCC		0x00000100
+#define DDCAPS_BLTSTRETCH		0x00000200
+#define DDCAPS_GDI			0x00000400
+#define DDCAPS_OVERLAY			0x00000800
+#define DDCAPS_OVERLAYCANTCLIP		0x00001000
+#define DDCAPS_OVERLAYFOURCC		0x00002000
+#define DDCAPS_OVERLAYSTRETCH		0x00004000
+#define DDCAPS_PALETTE			0x00008000
+#define DDCAPS_PALETTEVSYNC		0x00010000
+#define DDCAPS_READSCANLINE		0x00020000
+#define DDCAPS_STEREOVIEW		0x00040000
+#define DDCAPS_VBI			0x00080000
+#define DDCAPS_ZBLTS			0x00100000
+#define DDCAPS_ZOVERLAYS		0x00200000
+#define DDCAPS_COLORKEY			0x00400000
+#define DDCAPS_ALPHA			0x00800000
+#define DDCAPS_COLORKEYHWASSIST		0x01000000
+#define DDCAPS_NOHARDWARE		0x02000000
+#define DDCAPS_BLTCOLORFILL		0x04000000
+#define DDCAPS_BANKSWITCHED		0x08000000
+#define DDCAPS_BLTDEPTHFILL		0x10000000
+#define DDCAPS_CANCLIP			0x20000000
+#define DDCAPS_CANCLIPSTRETCHED		0x40000000
+#define DDCAPS_CANBLTSYSMEM		0x80000000
+
+/* dwCaps2 */
+/* driver is certified */
+#define DDCAPS2_CERTIFIED		0x00000001
+/* no 2d operations in 3d mode */
+#define DDCAPS2_NO2DDURING3DSCENE       0x00000002
+
+typedef struct _DDCOLORKEY
+{
+	DWORD	dwColorSpaceLowValue;/* low boundary of color space that is to
+                                      * be treated as Color Key, inclusive
+				      */
+	DWORD	dwColorSpaceHighValue;/* high boundary of color space that is
+                                       * to be treated as Color Key, inclusive
+				       */
+} DDCOLORKEY,*LPDDCOLORKEY;
+
+/* ddCKEYCAPS bits */
+#define DDCKEYCAPS_DESTBLT			0x00000001
+#define DDCKEYCAPS_DESTBLTCLRSPACE		0x00000002
+#define DDCKEYCAPS_DESTBLTCLRSPACEYUV		0x00000004
+#define DDCKEYCAPS_DESTBLTYUV			0x00000008
+#define DDCKEYCAPS_DESTOVERLAY			0x00000010
+#define DDCKEYCAPS_DESTOVERLAYCLRSPACE		0x00000020
+#define DDCKEYCAPS_DESTOVERLAYCLRSPACEYUV	0x00000040
+#define DDCKEYCAPS_DESTOVERLAYONEACTIVE		0x00000080
+#define DDCKEYCAPS_DESTOVERLAYYUV		0x00000100
+#define DDCKEYCAPS_SRCBLT			0x00000200
+#define DDCKEYCAPS_SRCBLTCLRSPACE		0x00000400
+#define DDCKEYCAPS_SRCBLTCLRSPACEYUV		0x00000800
+#define DDCKEYCAPS_SRCBLTYUV			0x00001000
+#define DDCKEYCAPS_SRCOVERLAY			0x00002000
+#define DDCKEYCAPS_SRCOVERLAYCLRSPACE		0x00004000
+#define DDCKEYCAPS_SRCOVERLAYCLRSPACEYUV	0x00008000
+#define DDCKEYCAPS_SRCOVERLAYONEACTIVE		0x00010000
+#define DDCKEYCAPS_SRCOVERLAYYUV		0x00020000
+#define DDCKEYCAPS_NOCOSTOVERLAY		0x00040000
+
+typedef struct _DDPIXELFORMAT {
+    DWORD	dwSize;                 /* size of structure */
+    DWORD	dwFlags;                /* pixel format flags */
+    DWORD	dwFourCC;               /* (FOURCC code) */
+    union {
+	DWORD	dwRGBBitCount;          /* how many bits per pixel (BD_4,8,16,24,32)*/
+	DWORD	dwYUVBitCount;          /* how many bits per pixel (BD_4,8,16,24,32)*/
+	DWORD	dwZBufferBitDepth;      /* how many bits for z buffers (BD_8,16,24,32)*/
+	DWORD	dwAlphaBitDepth;        /* how many bits for alpha channels (BD_1,2,4,8)*/
+    } x;
+    union {
+	DWORD	dwRBitMask;             /* mask for red bit*/
+	DWORD	dwYBitMask;             /* mask for Y bits*/
+    } y;
+    union {
+	DWORD	dwGBitMask;             /* mask for green bits*/
+	DWORD	dwUBitMask;             /* mask for U bits*/
+    } z;
+    union {
+	DWORD   dwBBitMask;             /* mask for blue bits*/
+	DWORD   dwVBitMask;             /* mask for V bits*/
+    } xx;
+    union {
+    	DWORD	dwRGBAlphaBitMask;	/* mask for alpha channel */
+    	DWORD	dwYUVAlphaBitMask;	/* mask for alpha channel */
+
+    } xy;
+} DDPIXELFORMAT,*LPDDPIXELFORMAT;
+
+/* DDCAPS.dwFXCaps */
+#define DDFXCAPS_BLTARITHSTRETCHY	0x00000020
+#define DDFXCAPS_BLTARITHSTRETCHYN	0x00000010
+#define DDFXCAPS_BLTMIRRORLEFTRIGHT	0x00000040
+#define DDFXCAPS_BLTMIRRORUPDOWN	0x00000080
+#define DDFXCAPS_BLTROTATION		0x00000100
+#define DDFXCAPS_BLTROTATION90		0x00000200
+#define DDFXCAPS_BLTSHRINKX		0x00000400
+#define DDFXCAPS_BLTSHRINKXN		0x00000800
+#define DDFXCAPS_BLTSHRINKY		0x00001000
+#define DDFXCAPS_BLTSHRINKYN		0x00002000
+#define DDFXCAPS_BLTSTRETCHX		0x00004000
+#define DDFXCAPS_BLTSTRETCHXN		0x00008000
+#define DDFXCAPS_BLTSTRETCHY		0x00010000
+#define DDFXCAPS_BLTSTRETCHYN		0x00020000
+#define DDFXCAPS_OVERLAYARITHSTRETCHY	0x00040000
+#define DDFXCAPS_OVERLAYARITHSTRETCHYN	0x00000008
+#define DDFXCAPS_OVERLAYSHRINKX		0x00080000
+#define DDFXCAPS_OVERLAYSHRINKXN	0x00100000
+#define DDFXCAPS_OVERLAYSHRINKY		0x00200000
+#define DDFXCAPS_OVERLAYSHRINKYN	0x00400000
+#define DDFXCAPS_OVERLAYSTRETCHX	0x00800000
+#define DDFXCAPS_OVERLAYSTRETCHXN	0x01000000
+#define DDFXCAPS_OVERLAYSTRETCHY	0x02000000
+#define DDFXCAPS_OVERLAYSTRETCHYN	0x04000000
+#define DDFXCAPS_OVERLAYMIRRORLEFTRIGHT	0x08000000
+#define DDFXCAPS_OVERLAYMIRRORUPDOWN	0x10000000
+
+/* DDCAPS.dwFXAlphaCaps */
+#define DDFXALPHACAPS_BLTALPHAEDGEBLEND		0x00000001
+#define DDFXALPHACAPS_BLTALPHAPIXELS		0x00000002
+#define DDFXALPHACAPS_BLTALPHAPIXELSNEG		0x00000004
+#define DDFXALPHACAPS_BLTALPHASURFACES		0x00000008
+#define DDFXALPHACAPS_BLTALPHASURFACESNEG	0x00000010
+#define DDFXALPHACAPS_OVERLAYALPHAEDGEBLEND	0x00000020
+#define DDFXALPHACAPS_OVERLAYALPHAPIXELS	0x00000040
+#define DDFXALPHACAPS_OVERLAYALPHAPIXELSNEG	0x00000080
+#define DDFXALPHACAPS_OVERLAYALPHASURFACES	0x00000100
+#define DDFXALPHACAPS_OVERLAYALPHASURFACESNEG	0x00000200
+
+/* DDCAPS.dwPalCaps */
+#define DDPCAPS_4BIT			0x00000001
+#define DDPCAPS_8BITENTRIES		0x00000002
+#define DDPCAPS_8BIT			0x00000004
+#define DDPCAPS_INITIALIZE		0x00000008
+#define DDPCAPS_PRIMARYSURFACE		0x00000010
+#define DDPCAPS_PRIMARYSURFACELEFT	0x00000020
+#define DDPCAPS_ALLOW256		0x00000040
+#define DDPCAPS_VSYNC			0x00000080
+#define DDPCAPS_1BIT			0x00000100
+#define DDPCAPS_2BIT			0x00000200
+
+/* DDCAPS.dwSVCaps */
+#define DDSVCAPS_ENIGMA			0x00000001l
+#define DDSVCAPS_FLICKER		0x00000002l
+#define DDSVCAPS_REDBLUE		0x00000004l
+#define DDSVCAPS_SPLIT			0x00000008l
+
+/* BitDepths */
+#define DDBD_1				0x00004000
+#define DDBD_2				0x00002000
+#define DDBD_4				0x00001000
+#define DDBD_8				0x00000800
+#define DDBD_16				0x00000400
+#define DDBD_24				0x00000200
+#define DDBD_32				0x00000100
+
+/* DDOVERLAYFX.dwDDFX */
+#define DDOVERFX_ARITHSTRETCHY		0x00000001
+#define DDOVERFX_MIRRORLEFTRIGHT	0x00000002
+#define DDOVERFX_MIRRORUPDOWN		0x00000004
+
+/* DDCOLORKEY.dwFlags */
+#define DDPF_ALPHAPIXELS		0x00000001
+#define DDPF_ALPHA			0x00000002
+#define DDPF_FOURCC			0x00000004
+#define DDPF_PALETTEINDEXED4		0x00000008
+#define DDPF_PALETTEINDEXEDTO8		0x00000010
+#define DDPF_PALETTEINDEXED8		0x00000020
+#define DDPF_RGB			0x00000040
+#define DDPF_COMPRESSED			0x00000080
+#define DDPF_RGBTOYUV			0x00000100
+#define DDPF_YUV			0x00000200
+#define DDPF_ZBUFFER			0x00000400
+#define DDPF_PALETTEINDEXED1		0x00000800
+#define DDPF_PALETTEINDEXED2		0x00001000
+
+/* SetCooperativeLevel dwFlags */
+#define DDSCL_FULLSCREEN		0x00000001
+#define DDSCL_ALLOWREBOOT		0x00000002
+#define DDSCL_NOWINDOWCHANGES		0x00000004
+#define DDSCL_NORMAL			0x00000008
+#define DDSCL_EXCLUSIVE			0x00000010
+#define DDSCL_ALLOWMODEX		0x00000040
+
+typedef struct _DDSURFACEDESC
+{
+	DWORD	dwSize;	/* size of the DDSURFACEDESC structure*/
+	DWORD	dwFlags;/* determines what fields are valid*/
+	DWORD	dwHeight;/* height of surface to be created*/
+	DWORD	dwWidth;/* width of input surface*/
+	LONG	lPitch;	/* distance to start of next line (return value only)*/
+	DWORD	dwBackBufferCount;	/* number of back buffers requested*/
+	union {
+		DWORD	dwMipMapCount;	/* number of mip-map levels requested*/
+		DWORD	dwZBufferBitDepth;/* depth of Z buffer requested*/
+		DWORD	dwRefreshRate;	/* refresh rate (used when display mode is described)*/
+	} x;
+	DWORD	dwAlphaBitDepth;        /* depth of alpha buffer requested*/
+	DWORD	dwReserved;             /* reserved*/
+	LPVOID	lpSurface;              /* pointer to the associated surface memory*/
+	DDCOLORKEY	ddckCKDestOverlay;/* color key for destination overlay use*/
+	DDCOLORKEY	ddckCKDestBlt;/* color key for destination blt use*/
+	DDCOLORKEY	ddckCKSrcOverlay;/* color key for source overlay use*/
+	DDCOLORKEY	ddckCKSrcBlt;/* color key for source blt use*/
+	DDPIXELFORMAT	ddpfPixelFormat;/* pixel format description of the surface*/
+	DDSCAPS		ddsCaps;/* direct draw surface capabilities*/
+} DDSURFACEDESC,*LPDDSURFACEDESC;
+
+typedef BOOL32 (CALLBACK * LPDDENUMCALLBACK32A)(GUID *, LPSTR, LPSTR, LPVOID);
+typedef BOOL32 (CALLBACK * LPDDENUMCALLBACK32W)(GUID *, LPWSTR, LPWSTR, LPVOID);
+DECL_WINELIB_TYPE_AW(LPDDENUMCALLBACK)
+
+typedef HRESULT (CALLBACK * LPDDENUMMODESCALLBACK)(LPDDSURFACEDESC, LPVOID);
+typedef HRESULT (CALLBACK * LPDDENUMSURFACESCALLBACK)(LPDIRECTDRAWSURFACE, LPDDSURFACEDESC, LPVOID);
+
+/* dwFlags field... which are valid */
+
+#define	DDSD_CAPS		0x00000001
+#define	DDSD_HEIGHT		0x00000002
+#define	DDSD_WIDTH		0x00000004
+#define	DDSD_PITCH		0x00000008
+#define	DDSD_BACKBUFFERCOUNT	0x00000020
+#define	DDSD_ZBUFFERBITDEPTH	0x00000040
+#define	DDSD_ALPHABITDEPTH	0x00000080
+#define	DDSD_PIXELFORMAT	0x00001000
+#define	DDSD_CKDESTOVERLAY	0x00002000
+#define	DDSD_CKDESTBLT		0x00004000
+#define	DDSD_CKSRCOVERLAY	0x00008000
+#define	DDSD_CKSRCBLT		0x00010000
+#define	DDSD_MIPMAPCOUNT	0x00020000
+#define	DDSD_REFRESHRATE	0x00040000
+#define	DDSD_ALL		0x0007f9ee
+
+typedef struct _DDBLTFX
+{
+    DWORD       dwSize;                         /* size of structure */
+    DWORD       dwDDFX;                         /* FX operations */
+    DWORD       dwROP;                          /* Win32 raster operations */
+    DWORD       dwDDROP;                        /* Raster operations new for DirectDraw */
+    DWORD       dwRotationAngle;                /* Rotation angle for blt */
+    DWORD       dwZBufferOpCode;                /* ZBuffer compares */
+    DWORD       dwZBufferLow;                   /* Low limit of Z buffer */
+    DWORD       dwZBufferHigh;                  /* High limit of Z buffer */
+    DWORD       dwZBufferBaseDest;              /* Destination base value */
+    DWORD       dwZDestConstBitDepth;           /* Bit depth used to specify Z constant for destination */
+    union
+    {
+        DWORD   dwZDestConst;                   /* Constant to use as Z buffer for dest */
+        LPDIRECTDRAWSURFACE lpDDSZBufferDest;   /* Surface to use as Z buffer for dest */
+    } x;
+    DWORD       dwZSrcConstBitDepth;            /* Bit depth used to specify Z constant for source */
+    union
+    {
+        DWORD   dwZSrcConst;                    /* Constant to use as Z buffer for src */
+        LPDIRECTDRAWSURFACE lpDDSZBufferSrc;    /* Surface to use as Z buffer for src */
+    } y;
+    DWORD       dwAlphaEdgeBlendBitDepth;       /* Bit depth used to specify constant for alpha edge blend */
+    DWORD       dwAlphaEdgeBlend;               /* Alpha for edge blending */
+    DWORD       dwReserved;
+    DWORD       dwAlphaDestConstBitDepth;       /* Bit depth used to specify alpha constant for destination */
+    union
+    {
+        DWORD   dwAlphaDestConst;               /* Constant to use as Alpha Channel */
+        LPDIRECTDRAWSURFACE lpDDSAlphaDest;     /* Surface to use as Alpha Channel */
+    } z;
+    DWORD       dwAlphaSrcConstBitDepth;        /* Bit depth used to specify alpha constant for source */
+    union
+    {
+        DWORD   dwAlphaSrcConst;                /* Constant to use as Alpha Channel */
+        LPDIRECTDRAWSURFACE lpDDSAlphaSrc;      /* Surface to use as Alpha Channel */
+    } a;
+    union
+    {
+        DWORD   dwFillColor;                    /* color in RGB or Palettized */
+        DWORD   dwFillDepth;                    /* depth value for z-buffer */
+        LPDIRECTDRAWSURFACE lpDDSPattern;       /* Surface to use as pattern */
+    } b;
+    DDCOLORKEY  ddckDestColorkey;               /* DestColorkey override */
+    DDCOLORKEY  ddckSrcColorkey;                /* SrcColorkey override */
+} DDBLTFX,*LPDDBLTFX;
+
+/* dwDDFX */
+/* arithmetic stretching along y axis */
+#define DDBLTFX_ARITHSTRETCHY			0x00000001
+/* mirror on y axis */
+#define DDBLTFX_MIRRORLEFTRIGHT			0x00000002
+/* mirror on x axis */
+#define DDBLTFX_MIRRORUPDOWN			0x00000004
+/* do not tear */
+#define DDBLTFX_NOTEARING			0x00000008
+/* 180 degrees clockwise rotation */
+#define DDBLTFX_ROTATE180			0x00000010
+/* 270 degrees clockwise rotation */
+#define DDBLTFX_ROTATE270			0x00000020
+/* 90 degrees clockwise rotation */
+#define DDBLTFX_ROTATE90			0x00000040
+/* dwZBufferLow and dwZBufferHigh specify limits to the copied Z values */
+#define DDBLTFX_ZBUFFERRANGE			0x00000080
+/* add dwZBufferBaseDest to every source z value before compare */
+#define DDBLTFX_ZBUFFERBASEDEST			0x00000100
+
+typedef struct _DDOVERLAYFX
+{
+    DWORD       dwSize;                         /* size of structure */
+    DWORD       dwAlphaEdgeBlendBitDepth;       /* Bit depth used to specify constant for alpha edge blend */
+    DWORD       dwAlphaEdgeBlend;               /* Constant to use as alpha for edge blend */
+    DWORD       dwReserved;
+    DWORD       dwAlphaDestConstBitDepth;       /* Bit depth used to specify alpha constant for destination */
+    union
+    {
+        DWORD   dwAlphaDestConst;               /* Constant to use as alpha channel for dest */
+        LPDIRECTDRAWSURFACE lpDDSAlphaDest;     /* Surface to use as alpha channel for dest */
+    } x;
+    DWORD       dwAlphaSrcConstBitDepth;        /* Bit depth used to specify alpha constant for source */
+    union
+    {
+        DWORD   dwAlphaSrcConst;                /* Constant to use as alpha channel for src */
+        LPDIRECTDRAWSURFACE lpDDSAlphaSrc;      /* Surface to use as alpha channel for src */
+    } y;
+    DDCOLORKEY  dckDestColorkey;                /* DestColorkey override */
+    DDCOLORKEY  dckSrcColorkey;                 /* DestColorkey override */
+    DWORD       dwDDFX;                         /* Overlay FX */
+    DWORD       dwFlags;                        /* flags */
+} DDOVERLAYFX,*LPDDOVERLAYFX;
+
+typedef struct _DDBLTBATCH
+{
+    LPRECT32		lprDest;
+    LPDIRECTDRAWSURFACE	lpDDSSrc;
+    LPRECT32		lprSrc;
+    DWORD		dwFlags;
+    LPDDBLTFX		lpDDBltFx;
+} DDBLTBATCH,*LPDDBLTBATCH;
+
+#define STDMETHOD(xfn) HRESULT (CALLBACK *fn##xfn)
+#define STDMETHOD_(ret,xfn) ret (CALLBACK *fn##xfn)
+#define PURE
+#define FAR
+#define ULONG DWORD
+#define THIS_ THIS ,
+
+#define THIS LPDIRECTDRAWPALETTE this
+
+typedef struct IDirectDrawPalette_VTable {
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawPalette methods ***/
+    STDMETHOD(GetCaps)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetEntries)(THIS_ DWORD,DWORD,DWORD,LPPALETTEENTRY) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, DWORD, LPPALETTEENTRY) PURE;
+    STDMETHOD(SetEntries)(THIS_ DWORD,DWORD,DWORD,LPPALETTEENTRY) PURE;
+} *LPDIRECTDRAWPALETTE_VTABLE,IDirectDrawPalette_VTable;
+
+struct IDirectDrawPalette {
+    LPDIRECTDRAWPALETTE_VTABLE	lpvtbl;
+    DWORD			ref;
+    LPDIRECTDRAW		ddraw;
+    Colormap			cm;
+};
+#undef THIS
+
+#define THIS LPDIRECTDRAWCLIPPER this
+typedef struct IDirectDrawClipper_VTable {
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawClipper methods ***/
+    STDMETHOD(GetClipList)(THIS_ LPRECT32, LPRGNDATA, LPDWORD) PURE;
+    STDMETHOD(GetHWnd)(THIS_ HWND32 FAR *) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, DWORD) PURE;
+    STDMETHOD(IsClipListChanged)(THIS_ BOOL32 FAR *) PURE;
+    STDMETHOD(SetClipList)(THIS_ LPRGNDATA,DWORD) PURE;
+    STDMETHOD(SetHWnd)(THIS_ DWORD, HWND32 ) PURE;
+} *LPDIRECTDRAWCLIPPER_VTABLE,IDirectDrawClipper_VTable;
+
+struct IDirectDrawClipper {
+   LPDIRECTDRAWCLIPPER_VTABLE lpvtbl;
+   DWORD ref;
+};
+#undef THIS
+
+#define THIS LPDIRECTDRAW this
+typedef struct IDirectDraw_VTable {
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDraw methods ***/
+    STDMETHOD(Compact)(THIS) PURE;
+    STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreateSurface)(THIS_  LPDDSURFACEDESC *lpddsd, LPDIRECTDRAWSURFACE FAR *,
+IUnknown FAR *) PURE;
+    STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE
+FAR * ) PURE;
+    STDMETHOD(EnumDisplayModes)( THIS_ DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK ) PURE;
+    STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK ) PURE;
+    STDMETHOD(FlipToGDISurface)(THIS) PURE;
+    STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE;
+    STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC) PURE;
+    STDMETHOD(GetFourCCCodes)(THIS_  LPDWORD, LPDWORD ) PURE;
+    STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE FAR *) PURE;
+    STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetVerticalBlankStatus)(THIS_ BOOL32* ) PURE;
+    STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE;
+    STDMETHOD(RestoreDisplayMode)(THIS) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND32, DWORD) PURE;
+    STDMETHOD(SetDisplayMode)(THIS_ DWORD width, DWORD height,DWORD depth) PURE;
+    STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE32 ) PURE;
+} *LPDIRECTDRAW_VTABLE,IDirectDraw_VTable;
+
+struct _directdrawdata {
+    DWORD			depth;
+    DWORD			vp_width,vp_height; /* viewport dimension */
+    DWORD			height,width;	/* SetDisplayMode */
+    DWORD			current_height,fb_width,fb_height,fb_banksize,fb_memsize;
+    HWND32			mainwindow;
+    void			*fb_addr;
+};
+
+
+struct IDirectDraw {
+	LPDIRECTDRAW_VTABLE	lpvtbl;
+	DWORD			ref;
+	struct _directdrawdata	d;
+};
+
+/* flags for Lock() */
+/* The default.  Set to indicate that Lock should return a valid memory pointer
+ * to the top of the specified rectangle.  If no rectangle is specified then a
+ * pointer to the top of the surface is returned.
+ */
+#define DDLOCK_SURFACEMEMORYPTR	0x00000000L
+/* Set to indicate that Lock should wait until it can obtain a valid memory
+ * pointer before returning.  If this bit is set, Lock will never return
+ * DDERR_WASSTILLDRAWING.
+ */
+#define DDLOCK_WAIT		0x00000001L
+/* Set if an event handle is being passed to Lock.  Lock will trigger the event
+ * when it can return the surface memory pointer requested.
+ */
+#define DDLOCK_EVENT		0x00000002L
+/* Indicates that the surface being locked will only be read from.  */
+#define DDLOCK_READONLY		0x00000010L
+/* Indicates that the surface being locked will only be written to */
+#define DDLOCK_WRITEONLY	0x00000020L
+
+#undef THIS
+
+#define THIS LPDIRECTDRAW2 this
+typedef struct IDirectDraw2_VTable
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDraw methods ***/
+    STDMETHOD(Compact)(THIS) PURE;
+    STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreateSurface)(THIS_  LPDDSURFACEDESC, LPDIRECTDRAWSURFACE FAR *,
+IUnknown FAR *) PURE;
+    STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE
+FAR * ) PURE;
+    STDMETHOD(EnumDisplayModes)( THIS_ DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK ) PURE;
+    STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK ) PURE;
+    STDMETHOD(FlipToGDISurface)(THIS) PURE;
+    STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE;
+    STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC) PURE;
+    STDMETHOD(GetFourCCCodes)(THIS_  LPDWORD, LPDWORD ) PURE;
+    STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE FAR *) PURE;
+    STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetVerticalBlankStatus)(THIS_ BOOL32* ) PURE;
+    STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE;
+    STDMETHOD(RestoreDisplayMode)(THIS) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND32, DWORD) PURE;
+    STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD,DWORD, DWORD, DWORD) PURE;
+    STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE32 ) PURE;
+    /*** Added in the v2 interface ***/
+    STDMETHOD(GetAvailableVidMem)(THIS_ LPDDSCAPS, LPDWORD, LPDWORD) PURE;
+} IDirectDraw2_VTable,*LPDIRECTDRAW2_VTABLE;
+/* MUST HAVE THE SAME LAYOUT AS struct IDirectDraw */
+
+struct IDirectDraw2 {
+    LPDIRECTDRAW2_VTABLE	lpvtbl;
+    DWORD			ref;
+    struct _directdrawdata	d;
+};
+#undef THIS
+
+#define THIS LPDIRECTDRAWSURFACE this
+typedef struct IDirectDrawSurface_VTable {
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawSurface methods ***/
+    STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT32) PURE;
+    STDMETHOD(Blt)(THIS_ LPRECT32,LPDIRECTDRAWSURFACE, LPRECT32,DWORD, LPDDBLTFX) PURE;
+    STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE;
+    STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE, LPRECT32,DWORD) PURE;
+    STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD,LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK) PURE;    STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
+    STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE, DWORD) PURE;
+    STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS, LPDIRECTDRAWSURFACE FAR *) PURE;
+    STDMETHOD(GetBltStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetCaps)(THIS_ LPDDSCAPS) PURE;
+    STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER FAR*) PURE;
+    STDMETHOD(GetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(GetDC)(THIS_ HDC32 FAR *) PURE;
+    STDMETHOD(GetFlipStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetOverlayPosition)(THIS_ LPLONG, LPLONG ) PURE;
+    STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE FAR*) PURE;
+    STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT) PURE;
+    STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC) PURE;
+    STDMETHOD(IsLost)(THIS) PURE;
+    STDMETHOD(Lock)(THIS_ LPRECT32,LPDDSURFACEDESC,DWORD flags,HANDLE32) PURE;
+    STDMETHOD(ReleaseDC)(THIS_ HDC32) PURE;
+    STDMETHOD(Restore)(THIS) PURE;
+    STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER) PURE;
+    STDMETHOD(SetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(SetOverlayPosition)(THIS_ LONG, LONG ) PURE;
+    STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE) PURE;
+    STDMETHOD(Unlock)(THIS_ LPVOID) PURE;
+    STDMETHOD(UpdateOverlay)(THIS_ LPRECT32, LPDIRECTDRAWSURFACE,LPRECT32,DWORD, LPDDOVERLAYFX) PURE;
+    STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD) PURE;
+    STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD, LPDIRECTDRAWSURFACE) PURE;
+} *LPDIRECTDRAWSURFACE_VTABLE,IDirectDrawSurface_VTable;
+
+struct IDirectDrawSurface {
+    LPDIRECTDRAWSURFACE_VTABLE lpvtbl;
+    DWORD		ref;
+    LPVOID		surface;
+    LPDIRECTDRAWPALETTE	palette;
+    DWORD		fb_height,lpitch,width,height;
+    LPDIRECTDRAW	ddraw;
+};
+#undef THIS
+#define THIS LPDIRECTDRAWSURFACE2 this
+
+typedef struct IDirectDrawSurface2_VTable {
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawSurface methods ***/
+    STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE2) PURE;
+    STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT32) PURE;
+    STDMETHOD(Blt)(THIS_ LPRECT32,LPDIRECTDRAWSURFACE2, LPRECT32,DWORD, LPDDBLTFX) PURE;
+    STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE;
+    STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE2, LPRECT32,DWORD) PURE;
+    STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD,LPDIRECTDRAWSURFACE2) PURE;
+    STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK) PURE;    STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
+    STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE2, DWORD) PURE;
+    STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS, LPDIRECTDRAWSURFACE2 FAR *) PURE;
+    STDMETHOD(GetBltStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetCaps)(THIS_ LPDDSCAPS) PURE;
+    STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER FAR*) PURE;
+    STDMETHOD(GetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(GetDC)(THIS_ HDC32 FAR *) PURE;
+    STDMETHOD(GetFlipStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetOverlayPosition)(THIS_ LPLONG, LPLONG ) PURE;
+    STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE FAR*) PURE;
+    STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT) PURE;
+    STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC) PURE;
+    STDMETHOD(IsLost)(THIS) PURE;
+    STDMETHOD(Lock)(THIS_ LPRECT32,LPDDSURFACEDESC,DWORD,HANDLE32) PURE;
+    STDMETHOD(ReleaseDC)(THIS_ HDC32) PURE;
+    STDMETHOD(Restore)(THIS) PURE;
+    STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER) PURE;
+    STDMETHOD(SetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(SetOverlayPosition)(THIS_ LONG, LONG ) PURE;
+    STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE) PURE;
+    STDMETHOD(Unlock)(THIS_ LPVOID) PURE;
+    STDMETHOD(UpdateOverlay)(THIS_ LPRECT32, LPDIRECTDRAWSURFACE2,LPRECT32,DWORD, LPDDOVERLAYFX) PURE;
+    STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD) PURE;
+    STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD, LPDIRECTDRAWSURFACE2) PURE;
+    /*** Added in the v2 interface ***/
+    STDMETHOD(GetDDInterface)(THIS_ LPVOID FAR *) PURE;
+    STDMETHOD(PageLock)(THIS_ DWORD) PURE;
+    STDMETHOD(PageUnlock)(THIS_ DWORD) PURE;
+} *LPDIRECTDRAWSURFACE2_VTABLE,IDirectDrawSurface2_VTable;
+
+struct IDirectDrawSurface2 {
+    LPDIRECTDRAWSURFACE2_VTABLE	lpvtbl;
+    DWORD		ref;
+    LPVOID		surface;
+    LPDIRECTDRAWPALETTE	palette;
+    DWORD		fb_height,lpitch,width,height;
+    LPDIRECTDRAW	ddraw;
+};
+#undef THIS
+
+#undef THIS_
+#undef PURE
+#undef FAR
+#undef STDMETHOD
+#undef STDMETHOD_
+
+extern HRESULT WINAPI DirectDrawCreate( LPGUID lpGUID,LPDIRECTDRAW *lplpDD,LPUNKNOWN pUnkOuter );
+#endif
diff --git a/include/dsound.h b/include/dsound.h
new file mode 100644
index 0000000..61d042b
--- /dev/null
+++ b/include/dsound.h
@@ -0,0 +1,187 @@
+#ifndef __WINE_DSOUND_H
+#define __WINE_DSOUND_H
+
+#include "mmsystem.h"
+
+/* Direct Sound Component GUID    {47D4D946-62E8-11cf-93BC-444553540000} */
+DEFINE_GUID(CLSID_DirectSound,0x47d4d946, 0x62e8, 0x11cf, 0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
+
+/* DirectSound 279afa83-4981-11ce-a521-0020af0be560 */
+DEFINE_GUID(IID_IDirectSound,0x279AFA83,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60);
+/* DirectSoundBuffer 279afa85-4981-11ce-a521-0020af0be560 */
+DEFINE_GUID(IID_IDirectSoundBuffer,0x279AFA85,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60); 
+
+typedef struct IDirectSound IDirectSound,*LPDIRECTSOUND;
+typedef struct IDirectSoundBuffer IDirectSoundBuffer,*LPDIRECTSOUNDBUFFER,**LPLPDIRECTSOUNDBUFFER;
+
+#define DSCAPS_PRIMARYMONO          0x00000001
+#define DSCAPS_PRIMARYSTEREO        0x00000002
+#define DSCAPS_PRIMARY8BIT          0x00000004
+#define DSCAPS_PRIMARY16BIT         0x00000008
+#define DSCAPS_CONTINUOUSRATE       0x00000010
+#define DSCAPS_EMULDRIVER           0x00000020
+#define DSCAPS_CERTIFIED            0x00000040
+#define DSCAPS_SECONDARYMONO        0x00000100
+#define DSCAPS_SECONDARYSTEREO      0x00000200
+#define DSCAPS_SECONDARY8BIT        0x00000400
+#define DSCAPS_SECONDARY16BIT       0x00000800
+
+typedef struct _DSCAPS
+{
+    DWORD	dwSize;
+    DWORD	dwFlags;
+    DWORD	dwMinSecondarySampleRate;
+    DWORD	dwMaxSecondarySampleRate;
+    DWORD	dwPrimaryBuffers;
+    DWORD	dwMaxHwMixingAllBuffers;
+    DWORD	dwMaxHwMixingStaticBuffers;
+    DWORD	dwMaxHwMixingStreamingBuffers;
+    DWORD	dwFreeHwMixingAllBuffers;
+    DWORD	dwFreeHwMixingStaticBuffers;
+    DWORD	dwFreeHwMixingStreamingBuffers;
+    DWORD	dwMaxHw3DAllBuffers;
+    DWORD	dwMaxHw3DStaticBuffers;
+    DWORD	dwMaxHw3DStreamingBuffers;
+    DWORD	dwFreeHw3DAllBuffers;
+    DWORD	dwFreeHw3DStaticBuffers;
+    DWORD	dwFreeHw3DStreamingBuffers;
+    DWORD	dwTotalHwMemBytes;
+    DWORD	dwFreeHwMemBytes;
+    DWORD	dwMaxContigFreeHwMemBytes;
+    DWORD	dwUnlockTransferRateHwBuffers;
+    DWORD	dwPlayCpuOverheadSwBuffers;
+    DWORD	dwReserved1;
+    DWORD	dwReserved2;
+} DSCAPS,*LPDSCAPS;
+
+#define DSBPLAY_LOOPING         0x00000001
+
+#define DSBSTATUS_PLAYING           0x00000001
+#define DSBSTATUS_BUFFERLOST        0x00000002
+#define DSBSTATUS_LOOPING           0x00000004
+
+
+#define DSBLOCK_FROMWRITECURSOR         0x00000001
+
+#define DSBCAPS_PRIMARYBUFFER       0x00000001
+#define DSBCAPS_STATIC              0x00000002
+#define DSBCAPS_LOCHARDWARE         0x00000004
+#define DSBCAPS_LOCSOFTWARE         0x00000008
+#define DSBCAPS_CTRLFREQUENCY       0x00000020
+#define DSBCAPS_CTRLPAN             0x00000040
+#define DSBCAPS_CTRLVOLUME          0x00000080
+#define DSBCAPS_CTRLDEFAULT         0x000000E0  /* Pan + volume + frequency. */
+#define DSBCAPS_CTRLALL             0x000000E0  /* All control capabilities */
+#define DSBCAPS_STICKYFOCUS         0x00004000
+#define DSBCAPS_GETCURRENTPOSITION2 0x00010000  /* More accurate play cursor under emulation*/
+
+typedef struct _DSBCAPS
+{
+    DWORD	dwSize;
+    DWORD	dwFlags;
+    DWORD	dwBufferBytes;
+    DWORD	dwUnlockTransferRate;
+    DWORD	dwPlayCpuOverhead;
+} DSBCAPS,*LPDSBCAPS;
+
+#define DSSCL_NORMAL                1
+#define DSSCL_PRIORITY              2
+#define DSSCL_EXCLUSIVE             3
+#define DSSCL_WRITEPRIMARY          4
+
+typedef struct _DSBUFFERDESC
+{
+    DWORD		dwSize;
+    DWORD		dwFlags;
+    DWORD		dwBufferBytes;
+    DWORD		dwReserved;
+    LPWAVEFORMATEX	lpwfxFormat;
+} DSBUFFERDESC,*LPDSBUFFERDESC;
+
+
+
+#define DSSPEAKER_HEADPHONE     1
+#define DSSPEAKER_MONO          2
+#define DSSPEAKER_QUAD          3
+#define DSSPEAKER_STEREO        4
+#define DSSPEAKER_SURROUND      5
+
+
+
+typedef LPVOID* LPLPVOID;
+
+typedef BOOL32 (CALLBACK *LPDSENUMCALLBACK32W)(LPGUID,LPWSTR,LPWSTR,LPVOID);
+typedef BOOL32 (CALLBACK *LPDSENUMCALLBACK32A)(LPGUID,LPSTR,LPSTR,LPVOID);
+
+extern HRESULT WINAPI DirectSoundCreate(LPGUID lpGUID,LPDIRECTSOUND * ppDS,IUnknown *pUnkOuter );
+
+#define STDMETHOD(xfn) HRESULT (CALLBACK *fn##xfn)
+#define STDMETHOD_(ret,xfn) ret (CALLBACK *fn##xfn)
+#define PURE
+#define FAR
+#define ULONG DWORD
+
+#define THIS LPDIRECTSOUND this
+#define THIS_ LPDIRECTSOUND this,
+
+typedef struct tagLPDIRECTSOUND_VTABLE
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectSound methods ***/
+
+    STDMETHOD( CreateSoundBuffer)(THIS_ LPDSBUFFERDESC, LPLPDIRECTSOUNDBUFFER, IUnknown FAR *) PURE;
+    STDMETHOD( GetCaps)(THIS_ LPDSCAPS ) PURE;
+    STDMETHOD( DuplicateSoundBuffer)(THIS_ LPDIRECTSOUNDBUFFER, LPLPDIRECTSOUNDBUFFER ) PURE;
+    STDMETHOD( SetCooperativeLevel)(THIS_ HWND32, DWORD ) PURE;
+    STDMETHOD( Compact)(THIS ) PURE;
+    STDMETHOD( GetSpeakerConfig)(THIS_ LPDWORD ) PURE;
+    STDMETHOD( SetSpeakerConfig)(THIS_ DWORD ) PURE;
+    STDMETHOD( Initialize)(THIS_ GUID FAR * ) PURE;
+} *LPDIRECTSOUND_VTABLE;
+
+struct IDirectSound {
+	LPDIRECTSOUND_VTABLE	lpvtbl;
+	DWORD			ref;
+};
+
+#undef THIS
+#undef THIS_
+#define THIS LPDIRECTSOUNDBUFFER this
+#define THIS_ LPDIRECTSOUNDBUFFER this,
+typedef struct tagLPDIRECTSOUNDBUFFER_VTABLE
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectSoundBuffer methods ***/
+
+    STDMETHOD(           GetCaps)(THIS_ LPDSBCAPS ) PURE;
+    STDMETHOD(GetCurrentPosition)(THIS_ LPDWORD,LPDWORD ) PURE;
+    STDMETHOD(         GetFormat)(THIS_ LPWAVEFORMATEX, DWORD, LPDWORD ) PURE;
+    STDMETHOD(         GetVolume)(THIS_ LPLONG ) PURE;
+    STDMETHOD(            GetPan)(THIS_ LPLONG ) PURE;
+    STDMETHOD(      GetFrequency)(THIS_ LPDWORD ) PURE;
+    STDMETHOD(         GetStatus)(THIS_ LPDWORD ) PURE;
+    STDMETHOD(        Initialize)(THIS_ LPDIRECTSOUND, LPDSBUFFERDESC ) PURE;
+    STDMETHOD(              Lock)(THIS_ DWORD,DWORD,LPVOID,LPDWORD,LPVOID,LPDWORD,DWORD ) PURE;
+    STDMETHOD(              Play)(THIS_ DWORD,DWORD,DWORD ) PURE;
+    STDMETHOD(SetCurrentPosition)(THIS_ DWORD ) PURE;
+    STDMETHOD(         SetFormat)(THIS_ LPWAVEFORMATEX ) PURE;
+    STDMETHOD(         SetVolume)(THIS_ LONG ) PURE;
+    STDMETHOD(            SetPan)(THIS_ LONG ) PURE;
+    STDMETHOD(      SetFrequency)(THIS_ DWORD ) PURE;
+    STDMETHOD(              Stop)(THIS  ) PURE;
+    STDMETHOD(            Unlock)(THIS_ LPVOID,DWORD,LPVOID,DWORD ) PURE;
+    STDMETHOD(           Restore)(THIS  ) PURE;
+} *LPDIRECTSOUNDBUFFER_VTABLE;
+
+struct IDirectSoundBuffer {
+	LPDIRECTSOUNDBUFFER_VTABLE	lpvtbl;
+	DWORD				ref;
+};
+
+#endif
diff --git a/include/file.h b/include/file.h
index badc67a..de43e1b 100644
--- a/include/file.h
+++ b/include/file.h
@@ -9,7 +9,7 @@
 
 #include <time.h>
 #include "windows.h"
-#include "handle32.h"
+#include "k32obj.h"
 
 #define MAX_PATHNAME_LEN   1024
 
@@ -35,7 +35,6 @@
 
 
 /* files/file.c */
-extern void FILE_Destroy( K32OBJ *ptr );
 extern void FILE_SetDosError(void);
 extern HFILE32 FILE_DupUnixHandle( int fd );
 extern BOOL32 FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info );
diff --git a/include/handle32.h b/include/handle32.h
deleted file mode 100644
index 9e5fca0..0000000
--- a/include/handle32.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * KERNEL32 objects
- *
- * Copyright 1996 Alexandre Julliard
- */
-
-#ifndef __WINE_HANDLE32_H
-#define __WINE_HANDLE32_H
-
-#include "wintypes.h"
-
-/* Object types */
-typedef enum
-{
-    K32OBJ_UNKNOWN = 0,
-    K32OBJ_SEMAPHORE,
-    K32OBJ_EVENT,
-    K32OBJ_MUTEX,
-    K32OBJ_CRITICAL_SECTION,
-    K32OBJ_PROCESS,
-    K32OBJ_THREAD,
-    K32OBJ_FILE,
-    K32OBJ_CHANGE,
-    K32OBJ_CONSOLE,
-    K32OBJ_SCREEN_BUFFER,
-    K32OBJ_MEM_MAPPED_FILE,
-    K32OBJ_SERIAL,
-    K32OBJ_DEVICE_IOCTL,
-    K32OBJ_PIPE,
-    K32OBJ_MAILSLOT,
-    K32OBJ_TOOLHELP_SNAPSHOT,
-    K32OBJ_SOCKET,
-    K32OBJ_NBOBJECTS
-} K32OBJ_TYPE;
-
-/* Kernel object */
-typedef struct
-{
-    K32OBJ_TYPE   type;
-    DWORD         refcount;
-} K32OBJ;
-
-/* Kernel object list entry */
-typedef struct _K32OBJ_ENTRY
-{
-    K32OBJ               *obj;
-    struct _K32OBJ_ENTRY *next;
-    struct _K32OBJ_ENTRY *prev;
-} K32OBJ_ENTRY;
-
-/* Kernel object list */
-typedef struct
-{
-    K32OBJ_ENTRY *head;
-    K32OBJ_ENTRY *tail;
-} K32OBJ_LIST;
-
-extern void K32OBJ_IncCount( K32OBJ *ptr );
-extern void K32OBJ_DecCount( K32OBJ *ptr );
-extern void K32OBJ_AddHead( K32OBJ_LIST *list, K32OBJ *ptr );
-extern void K32OBJ_AddTail( K32OBJ_LIST *list, K32OBJ *ptr );
-extern void K32OBJ_Remove( K32OBJ_LIST *list, K32OBJ *ptr );
-extern K32OBJ *K32OBJ_RemoveHead( K32OBJ_LIST *list );
-extern BOOL32 K32OBJ_AddName( K32OBJ *obj, LPCSTR name );
-extern K32OBJ *K32OBJ_FindName( LPCSTR name );
-extern K32OBJ *K32OBJ_FindNameType( LPCSTR name, K32OBJ_TYPE type );
-
-#endif /* __WINE_HANDLE32_H */
diff --git a/include/heap.h b/include/heap.h
index 8459eba..82f26e2 100644
--- a/include/heap.h
+++ b/include/heap.h
@@ -12,6 +12,7 @@
 
 extern HANDLE32 SystemHeap;
 extern HANDLE32 SegptrHeap;
+extern CRITICAL_SECTION *HEAP_SystemLock;
 
 extern int HEAP_IsInsideHeap( HANDLE32 heap, DWORD flags, LPCVOID ptr );
 extern SEGPTR HEAP_GetSegptr( HANDLE32 heap, DWORD flags, LPCVOID ptr );
@@ -36,4 +37,11 @@
 #define SEGPTR_FREE(ptr) \
          (HIWORD(ptr) ? HeapFree( SegptrHeap, 0, (ptr) ) : 0)
 
+/* System heap locking macros */
+
+#define SYSTEM_LOCK()       (EnterCriticalSection(HEAP_SystemLock))
+#define SYSTEM_UNLOCK()     (LeaveCriticalSection(HEAP_SystemLock))
+/* Use this one only when you own the lock! */
+#define SYSTEM_LOCK_COUNT() (HEAP_SystemLock->RecursionCount)
+
 #endif  /* __WINE_HEAP_H */
diff --git a/include/k32obj.h b/include/k32obj.h
new file mode 100644
index 0000000..afe3c94
--- /dev/null
+++ b/include/k32obj.h
@@ -0,0 +1,66 @@
+/*
+ * KERNEL32 objects
+ *
+ * Copyright 1996, 1998 Alexandre Julliard
+ */
+
+#ifndef __WINE_K32OBJ_H
+#define __WINE_K32OBJ_H
+
+#include "wintypes.h"
+
+/* Object types */
+typedef enum
+{
+    K32OBJ_UNKNOWN = 0,
+    K32OBJ_SEMAPHORE,
+    K32OBJ_EVENT,
+    K32OBJ_MUTEX,
+    K32OBJ_CRITICAL_SECTION,
+    K32OBJ_PROCESS,
+    K32OBJ_THREAD,
+    K32OBJ_FILE,
+    K32OBJ_CHANGE,
+    K32OBJ_CONSOLE,
+    K32OBJ_SCREEN_BUFFER,
+    K32OBJ_MEM_MAPPED_FILE,
+    K32OBJ_SERIAL,
+    K32OBJ_DEVICE_IOCTL,
+    K32OBJ_PIPE,
+    K32OBJ_MAILSLOT,
+    K32OBJ_TOOLHELP_SNAPSHOT,
+    K32OBJ_SOCKET,
+    K32OBJ_NBOBJECTS
+} K32OBJ_TYPE;
+
+/* Kernel object */
+typedef struct
+{
+    K32OBJ_TYPE   type;
+    LONG          refcount;
+} K32OBJ;
+
+/* Kernel object operations */
+typedef struct
+{
+    BOOL32 (*signaled)(K32OBJ*,DWORD);    /* Is object signaled? */
+    void   (*satisfied)(K32OBJ*,DWORD);   /* Wait on object is satisfied */
+    void   (*add_wait)(K32OBJ*,DWORD);    /* Add thread to wait queue */
+    void   (*remove_wait)(K32OBJ*,DWORD); /* Remove thread from wait queue */
+    void   (*destroy)(K32OBJ *);          /* Destroy object on refcount==0 */
+} K32OBJ_OPS;
+
+extern const K32OBJ_OPS * const K32OBJ_Ops[K32OBJ_NBOBJECTS];
+
+#define K32OBJ_OPS(obj) (K32OBJ_Ops[(obj)->type])
+
+extern void K32OBJ_IncCount( K32OBJ *ptr );
+extern void K32OBJ_DecCount( K32OBJ *ptr );
+extern BOOL32 K32OBJ_IsValid( K32OBJ *ptr, K32OBJ_TYPE type );
+extern BOOL32 K32OBJ_AddName( K32OBJ *obj, LPCSTR name );
+extern K32OBJ *K32OBJ_Create( K32OBJ_TYPE type, DWORD size, LPCSTR name,
+                              HANDLE32 *handle );
+extern K32OBJ *K32OBJ_FindName( LPCSTR name );
+extern K32OBJ *K32OBJ_FindNameType( LPCSTR name, K32OBJ_TYPE type );
+
+#endif /* __WINE_K32OBJ_H */
diff --git a/include/mmsystem.h b/include/mmsystem.h
index 6845f35..493b7ac 100644
--- a/include/mmsystem.h
+++ b/include/mmsystem.h
@@ -875,8 +875,8 @@
     WCHAR szRegKey[MAXPNAMELEN];
     WCHAR szOEMVxD[MAX_JOYSTICKOEMVXDNAME];
 } JOYCAPS32W, *LPJOYCAPS32W;
-DECL_WINELIB_TYPE_AW(JOYCAPS)
-DECL_WINELIB_TYPE_AW(LPJOYCAPS)
+DECL_WINELIB_TYPE_AW(JOYCAPS);
+DECL_WINELIB_TYPE_AW(LPJOYCAPS);
 
 typedef struct {
     UINT16 wXpos;                 /* x position */
@@ -892,8 +892,8 @@
     UINT32 wButtons;
 } JOYINFO32, *LPJOYINFO32;
 
-DECL_WINELIB_TYPE(JOYINFO)
-DECL_WINELIB_TYPE(LPJOYINFO)
+DECL_WINELIB_TYPE(JOYINFO);
+DECL_WINELIB_TYPE(LPJOYINFO);
 
 MMRESULT16 WINAPI joyGetDevCaps16 (UINT16,LPJOYCAPS16 ,UINT16);
 MMRESULT32 WINAPI joyGetDevCaps32A(UINT32,LPJOYCAPS32A,UINT32);
diff --git a/include/process.h b/include/process.h
index 3cbd14c..ca0014f 100644
--- a/include/process.h
+++ b/include/process.h
@@ -10,7 +10,7 @@
 #include "windows.h"
 #include "winbase.h"
 #include "winnt.h"
-#include "handle32.h"
+#include "k32obj.h"
 #include "pe_image.h"
 #include "task.h"
 
@@ -98,13 +98,20 @@
     LCID             locale;           /* c4 Locale to be queried by GetThreadLocale (NT) */
 } PDB32;
 
+/* PDB <-> Process id conversion macros */
+#define PROCESS_OBFUSCATOR     ((DWORD)0xdeadbeef)
+#define PROCESS_ID_TO_PDB(id)  ((PDB32 *)((id) ^ PROCESS_OBFUSCATOR))
+#define PDB_TO_PROCESS_ID(pdb) ((DWORD)(pdb) ^ PROCESS_OBFUSCATOR)
+
+/* scheduler/process.c */
 extern HANDLE32 PROCESS_AllocHandle( K32OBJ *ptr, DWORD flags);
 extern K32OBJ *PROCESS_GetObjPtr( HANDLE32 handle, K32OBJ_TYPE type );
 extern BOOL32 PROCESS_SetObjPtr( HANDLE32 handle, K32OBJ *ptr, DWORD flags );
-
 extern PDB32 *PROCESS_Create( TDB *pTask, LPCSTR cmd_line );
-extern void PROCESS_Destroy( K32OBJ *ptr );
-
 extern PDB32 *pCurrentProcess;
 
+/* scheduler/event.c */
+extern void EVENT_Set( K32OBJ *obj );
+extern K32OBJ *EVENT_Create( BOOL32 manual_reset, BOOL32 initial_state );
+
 #endif  /* __WINE_PROCESS_H */
diff --git a/include/shlobj.h b/include/shlobj.h
index d51a190..35b23cc 100644
--- a/include/shlobj.h
+++ b/include/shlobj.h
@@ -197,7 +197,7 @@
 typedef struct IShellLink IShellLink,*LPSHELLLINK;
 typedef struct IShellLink_VTable
 {
-    // *** IUnknown methods ***
+    /* *** IUnknown methods *** */
     STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE;
     STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
     STDMETHOD_(ULONG,Release) (THIS) PURE;
diff --git a/include/struct32.h b/include/struct32.h
index 70875bf..79f1b5f 100644
--- a/include/struct32.h
+++ b/include/struct32.h
@@ -1,7 +1,7 @@
 /* Structure definitions for Win32 -- used only internally */
 #ifndef __WINE__STRUCT32_H
 #define __WINE__STRUCT32_H
-#include "handle32.h"
+#include "windows.h"
 
 extern void STRUCT32_MINMAXINFO32to16( const MINMAXINFO32*, MINMAXINFO16* );
 extern void STRUCT32_MINMAXINFO16to32( const MINMAXINFO16*, MINMAXINFO32* );
diff --git a/include/syscolor.h b/include/syscolor.h
deleted file mode 100644
index 7845858..0000000
--- a/include/syscolor.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * System color objects
- *
- * Copyright  Alexandre Julliard, 1994
- */
-
-#ifndef __WINE_SYSCOLOR_H
-#define __WINE_SYSCOLOR_H
-
-#include "windows.h"
-
-struct SysColorObjects
-{
-    HBRUSH32 hbrushScrollbar;        /* COLOR_SCROLLBAR           */
-    HBRUSH32 hbrushBackground;       /* COLOR_BACKGROUND          */
-    HBRUSH32 hbrushActiveCaption;    /* COLOR_ACTIVECAPTION       */
-    HBRUSH32 hbrushInactiveCaption;  /* COLOR_INACTIVECAPTION     */
-    HBRUSH32 hbrushMenu;             /* COLOR_MENU                */
-    HBRUSH32 hbrushWindow;           /* COLOR_WINDOW              */
-    HBRUSH32 hbrushWindowFrame;      /* COLOR_WINDOWFRAME         */
-    HBRUSH32 hbrushMenuText;         /* COLOR_MENUTEXT            */
-    HBRUSH32 hbrushWindowText;       /* COLOR_WINDOWTEXT          */
-    HBRUSH32 hbrushCaptionText;      /* COLOR_CAPTIONTEXT         */
-    HBRUSH32 hbrushActiveBorder;     /* COLOR_ACTIVEBORDER        */
-    HBRUSH32 hbrushInactiveBorder;   /* COLOR_INACTIVEBORDER      */
-    HBRUSH32 hbrushAppWorkspace;     /* COLOR_APPWORKSPACE        */
-    HBRUSH32 hbrushHighlight;        /* COLOR_HIGHLIGHT           */
-    HBRUSH32 hbrushHighlightText;    /* COLOR_HIGHLIGHTTEXT       */
-    HBRUSH32 hbrushBtnFace;          /* COLOR_BTNFACE             */
-    HBRUSH32 hbrushBtnShadow;        /* COLOR_BTNSHADOW           */
-    HBRUSH32 hbrushGrayText;         /* COLOR_GRAYTEXT            */
-    HBRUSH32 hbrushBtnText;          /* COLOR_BTNTEXT             */
-    HBRUSH32 hbrushInactiveCaptionText; /* COLOR_INACTIVECAPTIONTEXT */
-    HBRUSH32 hbrushBtnHighlight;     /* COLOR_BTNHIGHLIGHT        */
-    HBRUSH32 hbrush3DDkShadow;       /* COLOR_3DDKSHADOW          */
-    HBRUSH32 hbrush3DLight;          /* COLOR_3DLIGHT             */
-    HBRUSH32 hbrushInfoText;         /* COLOR_INFOTEXT            */
-    HBRUSH32 hbrushInfoBk;           /* COLOR_INFOBK              */
-
-    HPEN32   hpenWindowFrame;        /* COLOR_WINDOWFRAME         */
-    HPEN32   hpenWindowText;         /* COLOR_WINDOWTEXT          */
-};
-
-extern void SYSCOLOR_Init(void);
-extern struct SysColorObjects sysColorObjects;
-
-#endif  /* __WINE_SYSCOLOR_H */
diff --git a/include/sysmetrics.h b/include/sysmetrics.h
index b2f7e35..a398235 100644
--- a/include/sysmetrics.h
+++ b/include/sysmetrics.h
@@ -129,7 +129,9 @@
 #define SYSMETRICS_MIDEASTENABLED       sysMetrics[SM_MIDEASTENABLED]       /* 74 */
 #define SYSMETRICS_MOUSEWHEELPRESENT    sysMetrics[SM_MOUSEWHEELPRESENT]    /* 75 */
 
-extern void SYSMETRICS_Init(void);
+extern void SYSMETRICS_Init(void);  /* sysmetrics.c */
 extern short sysMetrics[SM_CMETRICS+1];
 
+extern void SYSCOLOR_Init(void);  /* syscolor.c */
+
 #endif  /* __WINE_SYSMETRICS_H */
diff --git a/include/thread.h b/include/thread.h
index 347019e..4e9b61f 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -7,8 +7,10 @@
 #ifndef __WINE_THREAD_H
 #define __WINE_THREAD_H
 
-#include "process.h"
+#include "k32obj.h"
+#include "windows.h"
 #include "winnt.h"
+#include "selectors.h"  /* for SET_FS */
 
 /* Thread exception block */
 typedef struct _TEB
@@ -30,58 +32,100 @@
     LPVOID      *tls_ptr;        /* 2c Pointer to TLS array */
 } TEB;
 
+/* Event waiting structure */
+typedef struct
+{
+    DWORD         count;     /* Count of valid objects */
+    DWORD         signaled;  /* Index of signaled object (or WAIT_FAILED)*/
+    BOOL32        wait_all;  /* Wait for all objects flag */
+    K32OBJ       *objs[MAXIMUM_WAIT_OBJECTS];  /* Object pointers */
+} WAIT_STRUCT;
+
+struct _PDB32;
+
 /* Thread database */
 typedef struct _THDB
 {
-    K32OBJ       header;         /*  00 Kernel object header */
-    PDB32       *process;        /*  08 Process owning this thread */
-    K32OBJ      *event;          /*  0c Thread event */
-    TEB          teb;            /*  10 Thread exception block */
-    PDB32       *process2;       /*  40 Same as offset 08 (?) */
-    DWORD        flags;          /*  44 Flags */
-    DWORD        exit_code;      /*  48 Termination status */
-    WORD         teb_sel;        /*  4c Selector to TEB */
-    WORD         emu_sel;        /*  4e 80387 emulator selector */
-    DWORD        unknown1;       /*  50 Unknown */
-    void        *wait_list;      /*  54 Event waiting list */
-    DWORD        unknown2;       /*  58 Unknown */
-    void        *ring0_thread;   /*  5c Pointer to ring 0 thread */
-    void        *ptdbx;          /*  60 Pointer to TDBX structure */
-    void        *stack_base;     /*  64 Base of the stack */
-    void        *exit_stack;     /*  68 Stack pointer on thread exit */
-    void        *emu_data;       /*  6c Related to 80387 emulation */
-    DWORD        last_error;     /*  70 Last error code */
-    void        *debugger_CB;    /*  74 Debugger context block */
-    DWORD        debug_thread;   /*  78 Thread debugging this one (?) */
-    void        *pcontext;       /*  7c Thread register context */
-    DWORD        unknown3[3];    /*  80 Unknown */
-    WORD         current_ss;     /*  8c Another 16-bit stack selector */
-    WORD         pad2;           /*  8e */
-    void        *ss_table;       /*  90 Pointer to info about 16-bit stack */
-    WORD         thunk_ss;       /*  94 Yet another 16-bit stack selector */
-    WORD         pad3;           /*  96 */
-    LPVOID       tls_array[64];  /*  98 Thread local storage */
-    DWORD        delta_priority; /* 198 Priority delta */
-    DWORD        unknown4[7];    /* 19c Unknown */
-    void        *create_data;    /* 1b8 Pointer to creation structure */
-    DWORD        suspend_count;  /* 1bc SuspendThread() counter */
-    DWORD        unknown5[9];    /* 1c0 Unknown */
-    K32OBJ      *crit_section;   /* 1e4 Some critical section */
-    K32OBJ      *win16_mutex;    /* 1e8 Pointer to Win16 mutex */
-    K32OBJ      *win32_mutex;    /* 1ec Pointer to KERNEL32 mutex */
-    K32OBJ      *crit_section2;  /* 1f0 Another critical section */
-    DWORD        unknown6[3];    /* 1f4 Unknown */
+    K32OBJ         header;         /*  00 Kernel object header */
+    struct _PDB32 *process;        /*  08 Process owning this thread */
+    K32OBJ        *event;          /*  0c Thread event */
+    TEB            teb;            /*  10 Thread exception block */
+    struct _PDB32 *process2;       /*  40 Same as offset 08 (?) */
+    DWORD          flags;          /*  44 Flags */
+    DWORD          exit_code;      /*  48 Termination status */
+    WORD           teb_sel;        /*  4c Selector to TEB */
+    WORD           emu_sel;        /*  4e 80387 emulator selector */
+    DWORD          unknown1;       /*  50 Unknown */
+    WAIT_STRUCT   *wait_list;      /*  54 Event waiting list */
+    DWORD          unknown2;       /*  58 Unknown */
+    void          *ring0_thread;   /*  5c Pointer to ring 0 thread */
+    void          *ptdbx;          /*  60 Pointer to TDBX structure */
+    void          *stack_base;     /*  64 Base of the stack */
+    void          *exit_stack;     /*  68 Stack pointer on thread exit */
+    void          *emu_data;       /*  6c Related to 80387 emulation */
+    DWORD          last_error;     /*  70 Last error code */
+    void          *debugger_CB;    /*  74 Debugger context block */
+    DWORD          debug_thread;   /*  78 Thread debugging this one (?) */
+    void          *pcontext;       /*  7c Thread register context */
+    DWORD          unknown3[3];    /*  80 Unknown */
+    WORD           current_ss;     /*  8c Another 16-bit stack selector */
+    WORD           pad2;           /*  8e */
+    void          *ss_table;       /*  90 Pointer to info about 16-bit stack */
+    WORD           thunk_ss;       /*  94 Yet another 16-bit stack selector */
+    WORD           pad3;           /*  96 */
+    LPVOID         tls_array[64];  /*  98 Thread local storage */
+    DWORD          delta_priority; /* 198 Priority delta */
+    DWORD          unknown4[7];    /* 19c Unknown */
+    void          *create_data;    /* 1b8 Pointer to creation structure */
+    DWORD          suspend_count;  /* 1bc SuspendThread() counter */
+    void          *entry_point;    /* 1c0 Thread entry point (was: unknown) */
+    void          *entry_arg;      /* 1c4 Entry point arg (was: unknown) */
+    int            unix_pid;       /* 1c8 Unix thread pid (was: unknown) */
+    DWORD          unknown5[6];    /* 1cc Unknown */
+    K32OBJ        *crit_section;   /* 1e4 Some critical section */
+    K32OBJ        *win16_mutex;    /* 1e8 Pointer to Win16 mutex */
+    K32OBJ        *win32_mutex;    /* 1ec Pointer to KERNEL32 mutex */
+    K32OBJ        *crit_section2;  /* 1f0 Another critical section */
+    DWORD          unknown6[3];    /* 1f4 Unknown */
     /* The following are Wine-specific fields */
-    CONTEXT      context;        /* 200 Thread context */
+    CONTEXT        context;        /* 200 Thread context */
+    WAIT_STRUCT    wait_struct;    /*     Event wait structure */
 } THDB;
 
+/* Thread queue entry */
+typedef struct _THREAD_ENTRY
+{
+    THDB                 *thread;
+    struct _THREAD_ENTRY *next;
+} THREAD_ENTRY;
 
-extern THDB *THREAD_Create( PDB32 *pdb, DWORD stack_size,
-                            LPTHREAD_START_ROUTINE start_addr );
-extern void THREAD_Destroy( K32OBJ *ptr );
-extern THDB *THREAD_Current(void);
-extern THDB *THREAD_SwitchThread( CONTEXT *context );
+/* A thread queue is a circular list; a THREAD_QUEUE is a pointer */
+/* to the end of the queue (i.e. where we add elements) */
+typedef THREAD_ENTRY *THREAD_QUEUE;
 
+/* THDB <-> Thread id conversion macros */
+#define THREAD_OBFUSCATOR       ((DWORD)0xdeadbeef)
+#define THREAD_ID_TO_THDB(id)   ((THDB *)((id) ^ THREAD_OBFUSCATOR))
+#define THDB_TO_THREAD_ID(thdb) ((DWORD)(thdb) ^ THREAD_OBFUSCATOR)
+
+#ifdef __i386__
+/* On the i386, the current thread is in the %fs register */
+# define SET_CUR_THREAD(thdb) SET_FS((thdb)->teb_sel)
+#else
 extern THDB *pCurrentThread;
+# define SET_CUR_THREAD(thdb) (pCurrentThread = (thdb))
+#endif  /* __i386__ */
+
+
+/* scheduler/thread.c */
+extern THDB *THREAD_Create( struct _PDB32 *pdb, DWORD stack_size,
+                            LPTHREAD_START_ROUTINE start_addr, LPVOID param );
+extern THDB *THREAD_Current(void);
+extern void THREAD_AddQueue( THREAD_QUEUE *queue, THDB *thread );
+extern void THREAD_RemoveQueue( THREAD_QUEUE *queue, THDB *thread );
+
+/* scheduler/synchro.c */
+extern void SYNC_WaitForCondition( WAIT_STRUCT *wait, DWORD timeout );
+extern void SYNC_WakeUp( THREAD_QUEUE *queue, DWORD max );
 
 #endif  /* __WINE_THREAD_H */
diff --git a/include/version.h b/include/version.h
index d3413e2..bb64ee6 100644
--- a/include/version.h
+++ b/include/version.h
@@ -1 +1 @@
-#define WINE_RELEASE_INFO "Wine release 971221"
+#define WINE_RELEASE_INFO "Wine release 980104"
diff --git a/include/windows.h b/include/windows.h
index 86cb5b8..d9fe47d 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -5463,7 +5463,8 @@
     DWORD	dwLanguageId;
 } MSGBOXPARAMS32W,*LPMSGBOXPARAMS32W;
 
-DECL_WINELIB_TYPE_AW(MSGBOXPARAMS)
+DECL_WINELIB_TYPE_AW(MSGBOXPARAMS);
+DECL_WINELIB_TYPE_AW(LPMSGBOXPARAMS);
 
 #pragma pack(4)
 
@@ -5682,7 +5683,8 @@
 BOOL32      WINAPI EnumSystemLocales32W(LOCALE_ENUMPROC32W,DWORD);
 #define     EnumSystemLocales WINELIB_NAME_AW(EnumSystemLocales)
 BOOL32      WINAPI EnumThreadWindows(DWORD,WNDENUMPROC32,LPARAM);
-void        WINAPI ExitProcess(DWORD);
+VOID        WINAPI ExitProcess(DWORD);
+VOID        WINAPI ExitThread(DWORD);
 BOOL32      WINAPI ExitWindowsEx(UINT32,DWORD);
 DWORD       WINAPI ExpandEnvironmentStrings32A(LPCSTR,LPSTR,DWORD);
 DWORD       WINAPI ExpandEnvironmentStrings32W(LPCWSTR,LPWSTR,DWORD);
@@ -5783,6 +5785,9 @@
 DWORD       WINAPI HeapSize(HANDLE32,DWORD,LPVOID);
 BOOL32      WINAPI HeapUnlock(HANDLE32);
 BOOL32      WINAPI HeapValidate(HANDLE32,DWORD,LPCVOID);
+LONG        WINAPI InterlockedDecrement(LPLONG);
+LONG        WINAPI InterlockedExchange(LPLONG,LONG);
+LONG        WINAPI InterlockedIncrement(LPLONG);
 BOOL32      WINAPI IsDBCSLeadByteEx(UINT32,BYTE);
 BOOL32      WINAPI IsProcessorFeaturePresent(DWORD);
 BOOL32      WINAPI IsWindowUnicode(HWND32);
@@ -5802,6 +5807,7 @@
 BOOL32      WINAPI MoveFileEx32A(LPCSTR,LPCSTR,DWORD);
 BOOL32      WINAPI MoveFileEx32W(LPCWSTR,LPCWSTR,DWORD);
 #define     MoveFileEx WINELIB_NAME_AW(MoveFileEx)
+DWORD       WINAPI MsgWaitForMultipleObjects(DWORD,HANDLE32*,BOOL32,DWORD,DWORD);
 HANDLE32    WINAPI OpenEvent32A(DWORD,BOOL32,LPCSTR);
 HANDLE32    WINAPI OpenEvent32W(DWORD,BOOL32,LPCWSTR);
 #define     OpenEvent WINELIB_NAME_AW(OpenEvent)
@@ -5811,9 +5817,11 @@
 HANDLE32    WINAPI OpenMutex32A(DWORD,BOOL32,LPCSTR);
 HANDLE32    WINAPI OpenMutex32W(DWORD,BOOL32,LPCWSTR);
 #define     OpenMutex WINELIB_NAME_AW(OpenMutex)
+HANDLE32    WINAPI OpenProcess(DWORD,BOOL32,DWORD);
 HANDLE32    WINAPI OpenSemaphore32A(DWORD,BOOL32,LPCSTR);
 HANDLE32    WINAPI OpenSemaphore32W(DWORD,BOOL32,LPCWSTR);
 #define     OpenSemaphore WINELIB_NAME_AW(OpenSemaphore)
+BOOL32      WINAPI PulseEvent(HANDLE32);
 DWORD       WINAPI QueryDosDevice32A(LPCSTR,LPSTR,DWORD);
 DWORD       WINAPI QueryDosDevice32W(LPCWSTR,LPWSTR,DWORD);
 #define     QueryDosDevice WINELIB_NAME_AW(QueryDosDevice)
@@ -5843,6 +5851,7 @@
                                       LPDWORD,LPFILETIME);
 #define     RegQueryInfoKey WINELIB_NAME_AW(RegQueryInfoKey)
 BOOL32      WINAPI ReleaseSemaphore(HANDLE32,LONG,LPLONG);
+BOOL32      WINAPI ResetEvent(HANDLE32);
 VOID        WINAPI RtlFillMemory(LPVOID,UINT32,UINT32);
 VOID        WINAPI RtlMoveMemory(LPVOID,LPCVOID,UINT32);
 VOID        WINAPI RtlZeroMemory(LPVOID,UINT32);
@@ -5860,6 +5869,7 @@
 BOOL32      WINAPI SetEnvironmentVariable32A(LPCSTR,LPCSTR);
 BOOL32      WINAPI SetEnvironmentVariable32W(LPCWSTR,LPCWSTR);
 #define     SetEnvironmentVariable WINELIB_NAME_AW(SetEnvironmentVariable)
+BOOL32      WINAPI SetEvent(HANDLE32);
 VOID        WINAPI SetFileApisToANSI(void);
 VOID        WINAPI SetFileApisToOEM(void);
 DWORD       WINAPI SetFilePointer(HFILE32,LONG,LPLONG,DWORD);
@@ -5894,6 +5904,10 @@
 BOOL32      WINAPI VirtualQuery(LPCVOID,LPMEMORY_BASIC_INFORMATION,DWORD);
 BOOL32      WINAPI VirtualQueryEx(HANDLE32,LPCVOID,LPMEMORY_BASIC_INFORMATION,DWORD);
 BOOL32      WINAPI VirtualUnlock(LPVOID,DWORD);
+DWORD       WINAPI WaitForMultipleObjects(DWORD,const HANDLE32*,BOOL32,DWORD);
+DWORD       WINAPI WaitForMultipleObjectsEx(DWORD,const HANDLE32*,BOOL32,DWORD,BOOL32);
+DWORD       WINAPI WaitForSingleObject(HANDLE32,DWORD);
+DWORD       WINAPI WaitForSingleObjectEx(HANDLE32,DWORD,BOOL32);
 BOOL32      WINAPI WriteConsole32A(HANDLE32,LPCVOID,DWORD,LPDWORD,LPVOID);
 BOOL32      WINAPI WriteConsole32W(HANDLE32,LPCVOID,DWORD,LPDWORD,LPVOID);
 #define     WriteConsole WINELIB_NAME_AW(WriteConsole)
@@ -8160,6 +8174,8 @@
 
 /* Extra functions that don't exist in the Windows API */
 
+HPEN16      WINAPI GetSysColorPen16(INT16);
+HPEN32      WINAPI GetSysColorPen32(INT32);
 INT32       WINAPI LoadMessage32A(HINSTANCE32,UINT32,WORD,LPSTR,INT32);
 INT32       WINAPI LoadMessage32W(HINSTANCE32,UINT32,WORD,LPWSTR,INT32);
 SEGPTR      WINAPI WIN16_GlobalLock16(HGLOBAL16);
diff --git a/include/winerror.h b/include/winerror.h
index dd2f3f3..a0a996f 100644
--- a/include/winerror.h
+++ b/include/winerror.h
@@ -4,6 +4,12 @@
 
 extern int WIN32_LastError;
 
+#define MAKE_HRESULT(sev,fac,code) \
+    ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) )
+#define MAKE_SCODE(sev,fac,code) \
+        ((SCODE) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) )
+
+
 /* ERROR_UNKNOWN is a placeholder for error conditions which haven't
  * been tested yet so we're not exactly sure what will be returned.
  * All instances of ERROR_UNKNOWN should be tested under Win95/NT
@@ -37,6 +43,8 @@
 #define ERROR_FILENAME_EXCED_RANGE  206
 #define ERROR_MORE_DATA             234
 #define ERROR_NO_MORE_ITEMS         259
+#define ERROR_NOT_OWNER             288
+#define ERROR_TOO_MANY_POSTS        298
 #define ERROR_INVALID_ADDRESS       487
 #define ERROR_CAN_NOT_COMPLETE      1003
 #define ERROR_IO_DEVICE             1117
@@ -48,11 +56,13 @@
 /* HRESULT values for OLE, SHELL and other Interface stuff */
 #define	NOERROR				0
 #define	S_OK				0
+#define	E_FAIL				0x80000008
 #define	E_UNEXPECTED			0x8000FFFF
-#define	E_OUTOFMEMORY			0x8007000E
-#define	E_INVALIDARG			0x80070057
 
 #define	OLE_E_ENUM_NOMORE		0x80040002
 #define	CLASS_E_CLASSNOTAVAILABLE	0x80040111
 
+#define	E_OUTOFMEMORY			0x8007000E
+#define	E_INVALIDARG			0x80070057
+
 #endif  /* __WINE_WINERROR_H */
diff --git a/include/winnt.h b/include/winnt.h
index 0d53299..be00784 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -194,6 +194,10 @@
 #define EXCEPTION_PRIV_INSTRUCTION      STATUS_PRIVILEGED_INSTRUCTION
 #define EXCEPTION_IN_PAGE_ERROR         STATUS_IN_PAGE_ERROR
 
+#define MAXIMUM_WAIT_OBJECTS 64
+#define MAXIMUM_SUSPEND_COUNT 127
+
+
 /*
  * Return values from the actual exception handlers
  */
diff --git a/include/winsock.h b/include/winsock.h
index edee250..ca7357c 100644
--- a/include/winsock.h
+++ b/include/winsock.h
@@ -176,7 +176,7 @@
 #define WS_SOCK_RDM        4               /* reliably-delivered message */
 #define WS_SOCK_SEQPACKET  5               /* sequenced packet stream */
 
-#define WS_SOL_SOCKET		(-1)
+#define WS_SOL_SOCKET		0xffff
 #define WS_IPPROTO_TCP		6
 
 /*
diff --git a/include/wintypes.h b/include/wintypes.h
index a5ab556..527fbcb 100644
--- a/include/wintypes.h
+++ b/include/wintypes.h
@@ -59,7 +59,7 @@
 # if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ >= 7)
 #  define __stdcall __attribute__((__stdcall__))
 #  define __cdecl   __attribute__((__cdecl__))
-#  define __RESTORE_ES  __asm__ __volatile__("pushw %ds\n\tpopw %es")
+#  define __RESTORE_ES  __asm__ __volatile__("pushl %ds\n\tpopl %es")
 # else
 #  error You need gcc >= 2.7 to build Wine on a 386
 # endif  /* __GNUC__ */
diff --git a/libtest/Makefile.in b/libtest/Makefile.in
index 3a85109..11deeea 100644
--- a/libtest/Makefile.in
+++ b/libtest/Makefile.in
@@ -5,7 +5,7 @@
 MODULE    = none
 RCFLAGS   = -w16 -h
 PROGRAMS  = expand hello hello2 hello3 hello4 new rolex
-ALL_LIBS  = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LDLIBS)
+ALL_LIBS  = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LIBS)
 
 C_SRCS = \
 	expand.c \
diff --git a/loader/main.c b/loader/main.c
index ed75c11..b596be2 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -21,7 +21,6 @@
 #include "dialog.h"
 #include "drive.h"
 #include "queue.h"
-#include "syscolor.h"
 #include "sysmetrics.h"
 #include "file.h"
 #include "gdi.h"
@@ -43,10 +42,6 @@
 
 int __winelib = 1;  /* Winelib run-time flag */
 
-HANDLE32 SystemHeap = 0;
-HANDLE32 SegptrHeap = 0;
-
-
 /***********************************************************************
  *           Kernel initialisation routine
  */
diff --git a/loader/module.c b/loader/module.c
index cebaea0..6cea6c5 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -19,6 +19,7 @@
 #include "hook.h"
 #include "module.h"
 #include "neexe.h"
+#include "process.h"
 #include "resource.h"
 #include "selectors.h"
 #include "stackframe.h"
@@ -1436,7 +1437,7 @@
 	hmod = PE_LoadLibraryEx32A(buffer,hfile,flags);
     }
     /* initialize all DLLs, which haven't been initialized yet. */
-    PE_InitializeDLLs( GetCurrentProcessId(), DLL_PROCESS_ATTACH, NULL);
+    PE_InitializeDLLs( pCurrentProcess, DLL_PROCESS_ATTACH, NULL);
     return hmod;
 }
 
@@ -1472,8 +1473,9 @@
  */
 BOOL32 WINAPI FreeLibrary32(HINSTANCE32 hLibModule)
 {
-	fprintf(stderr,"FreeLibrary: empty stub\n");
-	return TRUE;
+	dprintf_module(stddeb,"FreeLibrary: hLibModule: %08x\n", hLibModule);
+	return MODULE_FreeModule(hLibModule, 
+	                         GlobalLock16(GetCurrentTask()) );
 }
 
 
diff --git a/loader/pe_image.c b/loader/pe_image.c
index 6693fe2..043404d 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -97,7 +97,7 @@
 	u_long				* function;
 	u_char				** name, *ename;
 	int				i;
-	PDB32				*process=(PDB32*)GetCurrentProcessId();
+	PDB32				*process=pCurrentProcess;
 	PE_MODREF			*pem;
 	u_long				rva_start, rva_end, addr;
 	char				* forward;
@@ -690,14 +690,14 @@
 		if (!HIWORD(hModule)) /* internal (or bad) */
 			return hModule;
 		/* check if this module is already mapped */
-		pem 	= ((PDB32*)GetCurrentProcessId())->modref_list;
+		pem 	= pCurrentProcess->modref_list;
 		while (pem) {
 			if (pem->module == hModule) return hModule;
 			pem = pem->next;
 		}
 		pModule = MODULE_GetPtr(hModule);
 		if (pModule->flags & NE_FFLAGS_BUILTIN) {
-			PDB32	*process = (PDB32*)GetCurrentProcessId();
+			PDB32	*process = pCurrentProcess;
 			IMAGE_DOS_HEADER	*dh;
 			IMAGE_NT_HEADERS	*nh;
 			IMAGE_SECTION_HEADER	*sh;
@@ -743,8 +743,7 @@
 		if (pModule->module32 < 32) return 21;
 	}
 	/* recurse */
-	pModule->module32 = PE_MapImage( pModule->module32,
-                                         (PDB32*)GetCurrentProcessId(),
+	pModule->module32 = PE_MapImage( pModule->module32, pCurrentProcess,
                                          &ofs,flags);
 	return pModule->module32;
 }
@@ -777,8 +776,7 @@
                          (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
                          *((WORD*)PTR_SEG_TO_LIN(params->showCmd) + 1) );
     }
-    pModule->module32 = PE_MapImage( hModule32, (PDB32*)GetCurrentProcessId(),
-                                     ofs, 0 );
+    pModule->module32 = PE_MapImage( hModule32, pCurrentProcess, ofs, 0 );
     return hInstance;
 }
 
@@ -812,7 +810,7 @@
     ) {
         FARPROC32 entry = (FARPROC32)RVA_PTR( pem->module,
                                           OptionalHeader.AddressOfEntryPoint );
-        dprintf_relay( stddeb, "CallTo32(entryproc=%p,module=%d,type=%ld,res=%p)\n",
+        dprintf_relay( stddeb, "CallTo32(entryproc=%p,module=%08x,type=%ld,res=%p)\n",
                        entry, pem->module, type, lpReserved );
         entry( pem->module, type, lpReserved );
     }
@@ -877,7 +875,7 @@
  */
 BOOL32 WINAPI DisableThreadLibraryCalls(HMODULE32 hModule)
 {
-	PDB32	*process = (PDB32*)GetCurrentProcessId();
+	PDB32	*process = pCurrentProcess;
 	PE_MODREF	*pem = process->modref_list;
 
 	while (pem) {
diff --git a/loader/pe_resource.c b/loader/pe_resource.c
index 0139633..4e4098c 100644
--- a/loader/pe_resource.c
+++ b/loader/pe_resource.c
@@ -33,7 +33,7 @@
 static PE_MODREF*
 HMODULE32toPE_MODREF(HMODULE32 hmod) {
 	NE_MODULE	*pModule;
-	PDB32		*pdb = (PDB32*)GetCurrentProcessId();
+	PDB32		*pdb = pCurrentProcess;
 	PE_MODREF	*pem;
 
 	if (!hmod) hmod = GetTaskDS(); /* FIXME: correct? */
diff --git a/loader/signal.c b/loader/signal.c
index d99dedc..66def5d 100644
--- a/loader/signal.c
+++ b/loader/signal.c
@@ -149,6 +149,8 @@
  */
 BOOL32 SIGNAL_Init(void)
 {
+    extern void SYNC_SetupSignals(void);
+
 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined (__svr4__) || defined(_SCO_DS)
     struct sigaltstack ss;
     ss.ss_sp    = SIGNAL_Stack;
@@ -168,6 +170,7 @@
 #ifdef SIGIO
     SIGNAL_SetHandler( SIGIO,   (void (*)())WINSOCK_sigio, 0); 
 #endif
+    SYNC_SetupSignals();
     return TRUE;
 }
 
diff --git a/loader/task.c b/loader/task.c
index 08881d6..110a799 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -340,7 +340,7 @@
     SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
 
     IF1632_Saved16_ss_sp = pTask->ss_sp;
-    SET_FS( pCurrentThread->teb_sel );
+    SET_CUR_THREAD( pTask->thdb );
     if (pModule->flags & NE_FFLAGS_WIN32)
     {
         /* FIXME: all this is an ugly hack */
@@ -526,15 +526,16 @@
 		pCurrentProcess->exe_modref->pe_module->pe_header->OptionalHeader.AddressOfEntryPoint);
      */
         pTask->thdb = THREAD_Create( pdb32,
-          PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve, 0 );
+          PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve,
+                                     NULL, NULL );
         /* FIXME: should not be done here */
-        pCurrentThread = pTask->thdb;
         PE_InitTls( pdb32 );
     }
     else
-        pTask->thdb = THREAD_Create( pdb32, 0, NULL );
+        pTask->thdb = THREAD_Create( pdb32, 0, NULL, NULL );
 
     /* FIXME: check for pTask->thdb == NULL.  */
+    SET_CUR_THREAD( pTask->thdb );
 
     /* Create the 32-bit stack frame */
 
@@ -596,8 +597,8 @@
 
     /* Delete the Win32 part of the task */
 
-    PROCESS_Destroy( &pTask->thdb->process->header );
-    THREAD_Destroy( &pTask->thdb->header );
+    K32OBJ_DecCount( &pTask->thdb->process->header );
+    K32OBJ_DecCount( &pTask->thdb->header );
 
     /* Free the task module */
 
@@ -788,8 +789,8 @@
     /* Switch to the new stack */
 
     hCurrentTask = hTask;
-    pCurrentThread = pNewTask->thdb;
-    pCurrentProcess = pCurrentThread->process;
+    SET_CUR_THREAD( pNewTask->thdb );
+    pCurrentProcess = pNewTask->thdb->process;
     IF1632_Saved16_ss_sp = pNewTask->ss_sp;
 }
 
diff --git a/memory/global.c b/memory/global.c
index 4490b8a..0830c14 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -994,7 +994,7 @@
    HGLOBAL32            hnew;
    PGLOBAL32_INTERN     pintern;
 
-   hnew=NULL;
+   hnew = 0;
    /* HeapLock(GetProcessHeap()); */
    if(flags & GMEM_MODIFY) /* modify flags */
    {
@@ -1020,7 +1020,7 @@
       else
       {
 	 SetLastError(ERROR_INVALID_PARAMETER);
-	 hnew=NULL;
+	 hnew = 0;
       }
    }
    else
@@ -1074,12 +1074,11 @@
 HGLOBAL32 WINAPI GlobalFree32(HGLOBAL32 hmem)
 {
    PGLOBAL32_INTERN pintern;
-   HGLOBAL32        hreturned=NULL;
+   HGLOBAL32        hreturned = 0;
    
    if(ISPOINTER(hmem)) /* POINTER */
    {
-      if(!HeapFree(GetProcessHeap(), 0, (LPVOID) hmem))
-         hmem=NULL;
+      if(!HeapFree(GetProcessHeap(), 0, (LPVOID) hmem)) hmem = 0;
    }
    else  /* HANDLE */
    {
diff --git a/memory/heap.c b/memory/heap.c
index 1d4aee2..9904b3d 100644
--- a/memory/heap.c
+++ b/memory/heap.c
@@ -13,6 +13,7 @@
 #include "winbase.h"
 #include "winerror.h"
 #include "winnt.h"
+#include "heap.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -92,6 +93,10 @@
 #define HEAP_DEF_SIZE        0x110000   /* Default heap size = 1Mb + 64Kb */
 #define HEAP_MIN_BLOCK_SIZE  (8+sizeof(ARENA_FREE))  /* Min. heap block size */
 
+HANDLE32 SystemHeap = 0;
+HANDLE32 SegptrHeap = 0;
+CRITICAL_SECTION *HEAP_SystemLock = NULL;
+
 
 /***********************************************************************
  *           HEAP_Dump
@@ -808,7 +813,6 @@
     heap->next          = NULL;
     heap->flags         = flags;
     heap->magic         = HEAP_MAGIC;
-    InitializeCriticalSection( &heap->critSection );
 
     /* Build the free lists */
 
@@ -828,9 +832,13 @@
 
     HEAP_CreateFreeBlock( subheap, heap + 1, subheap->size - sizeof(*heap) );
 
+    /* Initialize critical section */
+
+    InitializeCriticalSection( &heap->critSection );
+    if (!SystemHeap) HEAP_SystemLock = &heap->critSection;
+
     /* We are done */
 
-    SetLastError( 0 );
     return (HANDLE32)heap;
 }
 
@@ -1088,7 +1096,6 @@
 BOOL32 WINAPI HeapLock( HANDLE32 heap )
 {
     HEAP *heapPtr = HEAP_GetPtr( heap );
-
     if (!heapPtr) return FALSE;
     EnterCriticalSection( &heapPtr->critSection );
     return TRUE;
@@ -1101,7 +1108,6 @@
 BOOL32 WINAPI HeapUnlock( HANDLE32 heap )
 {
     HEAP *heapPtr = HEAP_GetPtr( heap );
-
     if (!heapPtr) return FALSE;
     LeaveCriticalSection( &heapPtr->critSection );
     return TRUE;
diff --git a/memory/ldt.c b/memory/ldt.c
index 62fd1b0..126e30b 100644
--- a/memory/ldt.c
+++ b/memory/ldt.c
@@ -61,8 +61,10 @@
 
 #if defined(__svr4__) || defined(_SCO_DS)
 #include <sys/sysi86.h>
+#ifndef __sun__
 #include <sys/seg.h>
 #endif
+#endif
 
 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
 #include <machine/segments.h>
diff --git a/memory/virtual.c b/memory/virtual.c
index 82d4845..9ffde82 100644
--- a/memory/virtual.c
+++ b/memory/virtual.c
@@ -95,6 +95,17 @@
 #define ROUND_SIZE(addr,size) \
    (((UINT32)(size) + ((UINT32)(addr) & page_mask) + page_mask) & ~page_mask)
 
+static void VIRTUAL_DestroyMapping( K32OBJ *obj );
+
+const K32OBJ_OPS MEM_MAPPED_FILE_Ops =
+{
+    /* Object cannot be waited upon, so we don't need these (except destroy) */
+    NULL,                      /* signaled */
+    NULL,                      /* satisfied */
+    NULL,                      /* add_wait */
+    NULL,                      /* remove_wait */
+    VIRTUAL_DestroyMapping     /* destroy */
+};
 
 /***********************************************************************
  *           VIRTUAL_GetProtStr
@@ -864,10 +875,15 @@
         if (obj->type == K32OBJ_MEM_MAPPED_FILE)
         {
             SetLastError( ERROR_ALREADY_EXISTS );
-            return PROCESS_AllocHandle( obj, 0 );
+            handle = PROCESS_AllocHandle( obj, 0 );
         }
-        SetLastError( ERROR_DUP_NAME );
-        return 0;
+        else
+        {
+            SetLastError( ERROR_DUP_NAME );
+            handle = 0;
+        }
+        K32OBJ_DecCount( obj );
+        return handle;
     }
 
     /* Check parameters */
@@ -924,15 +940,17 @@
     /* Allocate the mapping object */
 
     if (!(mapping = HeapAlloc( SystemHeap, 0, sizeof(*mapping) ))) goto error;
-    mapping->header.type = K32OBJ_MEM_MAPPED_FILE;
+    mapping->header.type     = K32OBJ_MEM_MAPPED_FILE;
     mapping->header.refcount = 1;
-    mapping->protect   = vprot;
-    mapping->size_high = size_high;
-    mapping->size_low  = ROUND_SIZE( 0, size_low );
-    mapping->file      = (FILE_OBJECT *)obj;
+    mapping->protect         = vprot;
+    mapping->size_high       = size_high;
+    mapping->size_low        = ROUND_SIZE( 0, size_low );
+    mapping->file            = (FILE_OBJECT *)obj;
 
-    handle = PROCESS_AllocHandle( &mapping->header, 0 );
-    if (handle != INVALID_HANDLE_VALUE32) return handle;
+    if (!K32OBJ_AddName( &mapping->header, name )) handle = 0;
+    else handle = PROCESS_AllocHandle( &mapping->header, 0 );
+    K32OBJ_DecCount( &mapping->header );
+    return handle;
 
 error:
     if (obj) K32OBJ_DecCount( obj );
@@ -961,9 +979,16 @@
  */
 HANDLE32 WINAPI OpenFileMapping32A( DWORD access, BOOL32 inherit, LPCSTR name )
 {
-    K32OBJ *obj = K32OBJ_FindNameType( name, K32OBJ_MEM_MAPPED_FILE );
-    if (!obj) return 0;
-    return PROCESS_AllocHandle( obj, 0 );
+    HANDLE32 handle = 0;
+    K32OBJ *obj;
+    SYSTEM_LOCK();
+    if ((obj = K32OBJ_FindNameType( name, K32OBJ_MEM_MAPPED_FILE )))
+    {
+        handle = PROCESS_AllocHandle( obj, 0 );
+        K32OBJ_DecCount( obj );
+    }
+    SYSTEM_UNLOCK();
+    return handle;
 }
 
 
@@ -984,7 +1009,7 @@
  *
  * Destroy a FILE_MAPPING object.
  */
-void VIRTUAL_DestroyMapping( K32OBJ *ptr )
+static void VIRTUAL_DestroyMapping( K32OBJ *ptr )
 {
     FILE_MAPPING *mapping = (FILE_MAPPING *)ptr;
     assert( ptr->type == K32OBJ_MEM_MAPPED_FILE );
diff --git a/misc/comm.c b/misc/comm.c
index 08f9675..73681d9 100644
--- a/misc/comm.c
+++ b/misc/comm.c
@@ -36,7 +36,6 @@
 #include "options.h"
 #include "stddebug.h"
 #include "debug.h"
-#include "handle32.h"
 
 #ifndef TIOCINQ
 #define	TIOCINQ FIONREAD
diff --git a/misc/cpu.c b/misc/cpu.c
index ffbbbbf..6a79097 100644
--- a/misc/cpu.c
+++ b/misc/cpu.c
@@ -11,6 +11,9 @@
 #include "windows.h"
 #include "winnt.h"
 
+/***********************************************************************
+ * 			GetSystemInfo            	[KERNELL32.404]
+ */
 VOID WINAPI GetSystemInfo(LPSYSTEM_INFO si)
 {
 	static int cache = 0;
@@ -101,23 +104,48 @@
 #endif  /* linux */
 }
 
+/***********************************************************************
+ *          CPU_TestProcessorFeature
+ */
+static BOOL32 CPU_TestProcessorFeature(const char* query_info, const char* query_value)
+{
+    BOOL32 flag=FALSE;
+#ifdef linux
+    char line[200],info[200],value[200],junk[200];
+    FILE *f = fopen ("/proc/cpuinfo", "r");
+    
+    if (!f)
+      return 0;
+    while (fgets(line,200,f)!=NULL) {
+      if (sscanf(line,"%s%[ \t:]%s",info,junk,value)!=3)
+	continue;
+      if (strcmp(info,query_info)==0)
+	flag = strstr(value,query_value)!=NULL;
+    }
+    fclose (f);
+#else  /* linux */
+    /* FIXME: how do we do this on other systems? */
+#endif  /* linux */
+    return flag;
+}
 
-/* IsProcessorFeaturePresent [KERNEL32.880] */
+/***********************************************************************
+ * 			IsProcessorFeaturePresent	[KERNELL32.880]
+ */
 BOOL32 WINAPI IsProcessorFeaturePresent (DWORD feature)
 {
   SYSTEM_INFO si;
   GetSystemInfo (&si);
-  /* FIXME: these are relatively stupid approximations.  */
   switch (feature)
     {
-    case PF_FLOATING_POINT_PRECISION_ERRATA:
+    case PF_FLOATING_POINT_PRECISION_ERRATA: 
       return si.wProcessorLevel == 5;
     case PF_FLOATING_POINT_EMULATED:
-      return FALSE;
+      return CPU_TestProcessorFeature("fpu","no"); break;
     case PF_COMPARE_EXCHANGE_DOUBLE:
       return si.wProcessorLevel >= 5;
     case PF_MMX_INSTRUCTIONS_AVAILABLE:
-      return FALSE;
+      return CPU_TestProcessorFeature("flags","mmx"); break;
     default:
       return FALSE;
     }
diff --git a/misc/crtdll.c b/misc/crtdll.c
index 3a12c9b..2415c39 100644
--- a/misc/crtdll.c
+++ b/misc/crtdll.c
@@ -25,6 +25,7 @@
 #include <stdarg.h>
 #include <string.h>
 #include <sys/stat.h>
+#include <sys/times.h>
 #include <unistd.h>
 #include <time.h>
 #include <ctype.h>
@@ -421,6 +422,25 @@
 }
 
 /*********************************************************************
+ *                            (CRTDLL.350)
+ */
+clock_t __cdecl CRTDLL_clock(void)
+{
+	struct tms alltimes;
+	clock_t res;
+
+	times(&alltimes);
+	res = alltimes.tms_utime + alltimes.tms_stime+
+               alltimes.tms_cutime + alltimes.tms_cstime;
+	/* Fixme: We need some symbolic representation
+	   for (Hostsystem_)CLOCKS_PER_SEC 
+	   and (Emulated_system_)CLOCKS_PER_SEC
+	   10 holds only for Windows/Linux_i86)
+	   */
+	return 10*res;
+}
+
+/*********************************************************************
  *                  _isatty       (CRTDLL.137)
  */
 BOOL32 __cdecl CRTDLL__isatty(DWORD x)
diff --git a/misc/lstr.c b/misc/lstr.c
index ce80476..234ec07 100644
--- a/misc/lstr.c
+++ b/misc/lstr.c
@@ -10,7 +10,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#include <wctype.h>
 
 #include "windows.h"
 #include "winnt.h"	/* HEAP_ macros */
@@ -22,6 +21,16 @@
 #include "stddebug.h"
 #include "debug.h"
 
+#ifdef HAVE_WCTYPE_H
+# include <wctype.h>
+#else
+# define towlower(c) tolower(c)
+# define towupper(c) toupper(c)
+# define iswalnum(c) isalnum(c)
+# define iswalpha(c) isalpha(c)
+# define iswupper(c) isupper(c)
+# define iswlower(c) islower(c)
+#endif  /* HAVE_WCTYPE_H */
 
 /* Funny to divide them between user and kernel. */
 
diff --git a/misc/main.c b/misc/main.c
index bda1779..cbc551b 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -522,6 +522,8 @@
     MAIN_RestoreSetup();
     COLOR_Cleanup();
     WINSOCK_Shutdown();
+    /* FIXME: should check for other processes or threads */
+    DeleteCriticalSection( HEAP_SystemLock );
 }
 
 /***********************************************************************
diff --git a/misc/registry.c b/misc/registry.c
index fa63c80..90e233c 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -2,6 +2,10 @@
  * 	Registry Functions
  *
  * Copyright 1996 Marcus Meissner
+ *
+ * December 21, 1997 - Kevin Cozens
+ * Fixed bugs in the _w95_loadreg() function. Added extra information
+ * regarding the format of the Windows '95 registry files.
  */
 
 #include <stdlib.h>
@@ -25,6 +29,8 @@
 #include "xmalloc.h"
 #include "winreg.h"
 
+#define	DEBUG_W95_LOADREG	0
+
 /* FIXME: following defines should be configured global ... */
 
 /* NOTE: do not append a /. linux' mkdir() WILL FAIL if you do that */
@@ -894,12 +900,19 @@
  * 0 :	"CREG"	- magic
  * 4 :	DWORD version
  * 8 :	DWORD offset_of_RGDB_part
- * 0C..1F:	? (someone fill in please)
+ * 0C..0F:	? (someone fill in please)
+ * 10:  WORD	number of RGDB blocks
+ * 12:  WORD	?
+ * 14:  WORD	always 0000?
+ * 16:  WORD	always 0001?
+ * 18..1F:	? (someone fill in please)
  *
  * 20: RGKN_section:
  *   header:
  * 	0 :		"RGKN"	- magic
- * 	4..0x1B: 	? (fill in)
+ *      4 : DWORD	offset to first RGDB section
+ *      8 : DWORD	offset to ?
+ * 	C..0x1B: 	? (fill in)
  *      0x20 ... offset_of_RGDB_part: Disk Key Entry structures
  *
  *   Disk Key Entry Structure:
@@ -928,8 +941,12 @@
  *
  * RGDB_section:
  * 	00:		"RGDB"	- magic
- *	04: DWORD	offset to next RGDB section (perhaps WORD)
- *	08...1F:	?
+ *	04: DWORD	offset to next RGDB section
+ *	08: DWORD	?
+ *	0C: WORD	always 000d?
+ *	0E: WORD	RGDB block number
+ *	10:	DWORD	? (equals value at offset 4 - value at offset 8)
+ *	14..1F:		?
  *	20.....:	disk keys
  *
  * disk key:
@@ -957,6 +974,10 @@
  * structure) and reading another RGDB_section.
  * repeat until end of file.
  *
+ * An interesting relationship exists in RGDB_section. The value at offset
+ * 10 equals the value at offset 4 minus the value at offset 8. I have no
+ * idea at the moment what this means.  (Kevin Cozens)
+ *
  * FIXME: this description needs some serious help, yes.
  */
 
@@ -984,9 +1005,10 @@
 };
 
 /* fast lookup table dkeaddr->nr */
-struct	_w95nr2da {
+struct 	_w95nr2da {
 	unsigned long		dkeaddr;
 	unsigned long		nr;
+	struct _w95key		*key;
 };
 
 
@@ -1069,27 +1091,27 @@
 
 static struct _w95key*
 _w95dkelookup(unsigned long dkeaddr,int n,struct _w95nr2da *nr2da,struct _w95key *keys) {
-	int	i;
-        int     left, right;
+int	i;
+int left, right;
 
 	if (dkeaddr == 0xFFFFFFFF)
 		return NULL;
 	if (dkeaddr<0x20)
 		return NULL;
 	dkeaddr=_w95_adj_da(dkeaddr+0x1c);
-        left=0;
-        right=n-1;
-        while(left<=right)
-        {
-           i=(left+right)/2;
-           
-           if(nr2da[i].dkeaddr == dkeaddr)
-              return keys+nr2da[i].nr;
-           else if(nr2da[i].dkeaddr < dkeaddr)
-              left=i+1;
-           else
-              right=i-1;
-        }
+	left=0;
+	right=n-1;
+	while(left<=right)
+	{
+		i=(left+right)/2;
+
+		if(nr2da[i].dkeaddr == dkeaddr)
+			return nr2da[i].key;
+		else if(nr2da[i].dkeaddr < dkeaddr)
+			left=i+1;
+		else
+			right=i-1;
+	}
 	/* 0x3C happens often, just report unusual values */
 	if (dkeaddr!=0x3c)
 		dprintf_reg(stddeb,"search hasn't found dkeaddr %lx?\n",dkeaddr);
@@ -1129,13 +1151,13 @@
 		unsigned short		valdatalen;
 		/* valname, valdata */
 	};
-	struct	_w95nr2da 	*nr2da;
+    struct  _w95nr2da   *nr2da;
 
 	HFILE32		hfd;
 	int		lastmodified;
 	char		magic[5];
-	unsigned long	nr,pos,i,where,version,rgdbsection,end,off_next_rgdb;
-	struct	_w95key	*keys;
+	unsigned long	nr,pos,i,j,where,version,rgdbsection,end,off_next_rgdb;
+	struct	_w95key	*keys,*key;
 	int		nrofdkes;
 	unsigned char	*data,*curdata,*nextrgdb;
 	OFSTRUCT	ofs;
@@ -1171,7 +1193,13 @@
 	where	= 0x40;
 	end	= rgdbsection;
 
-	nrofdkes = (end-where)/sizeof(struct dke)+100;
+	/* I removed the '+100' that was here. The adjustments to dkeaddr   */
+	/* imply alignments to the data in 'data' which would mean it is    */
+	/* larger than the number of dke entries it holds therefore nrofdkes*/
+	/* would be equal to or larger than it needs to be without the need */
+	/* for the +100 - kc                                                */
+	nrofdkes = (end-where)/sizeof(struct dke);
+
 	data = (char*)xmalloc(end-where);
 	if ((end-where)!=_lread32(hfd,data,end-where))
 		return;
@@ -1179,9 +1207,12 @@
 
 	keys = (struct _w95key*)xmalloc(nrofdkes * sizeof(struct _w95key));
 	memset(keys,'\0',nrofdkes*sizeof(struct _w95key));
-	nr2da= (struct _w95nr2da*)xmalloc(nrofdkes * sizeof(struct _w95nr2da));
-	memset(nr2da,'\0',nrofdkes*sizeof(struct _w95nr2da));
+    nr2da= (struct _w95nr2da*)xmalloc(nrofdkes * sizeof(struct _w95nr2da));
+    memset(nr2da,'\0',nrofdkes*sizeof(struct _w95nr2da));
 
+#if DEBUG_W95_LOADREG
+	dprintf_reg(stddeb,"nrofdkes = %d\n", nrofdkes);
+#endif
 	for (i=0;i<nrofdkes;i++) {
 		struct	dke	dke;
 		unsigned long 	dkeaddr;
@@ -1190,6 +1221,10 @@
 		memcpy(&dke,curdata,sizeof(dke));
 		curdata+=sizeof(dke);
 		nr = dke.nrLS + (dke.nrMS<<8);
+#if DEBUG_W95_LOADREG
+		dprintf_reg(stddeb,"%ld: nr = %ld, nrMS:nrLS = %04X:%X\n",
+					i,nr,dke.nrMS,dke.nrLS);
+#endif
 		dkeaddr=pos-4;
 		if ((dkeaddr&0xFFF)<0x018) {
 			int	diff;
@@ -1199,6 +1234,10 @@
 			curdata+=diff-sizeof(dke);
 			memcpy(&dke,curdata,sizeof(dke));
 			nr = dke.nrLS + (dke.nrMS<<8);
+#if DEBUG_W95_LOADREG
+			dprintf_reg(stddeb,"> nr = %lu, nrMS:nrLS = %04X:%X\n",
+						nr,dke.nrMS,dke.nrLS);
+#endif
 			curdata+=sizeof(dke);
 		}
 		if (((dkeaddr+0x1C)&0xFFF)<0x1C) {
@@ -1206,46 +1245,63 @@
 			 * but ONLY if we are >0x1000 already
 			 */
 			if (dkeaddr & ~0xFFF)
-				dkeaddr = dkeaddr & ~0xFFF;
+				dkeaddr &= ~0xFFF;
 		}
-		if (nr>nrofdkes) {
-			/* 0xFFFFFFFF happens often, just report unusual values */
-			if (nr!=0xFFFFFFFF)
-				dprintf_reg(stddeb,"nr %ld exceeds nrofdkes %d, skipping.\n",nr,nrofdkes);
+		/* For the time being we will assume that all values of */
+		/* nr are valid unless the following condition is true. */
+		/* This value is obtained when dke.nrLS and dke.nrMS are*/
+		/* both FFFF as dke.nrMS is only shifted by 8 before the*/
+		/* add and not 16. -kc                                  */
+		if (nr==0x0100FEFF)
 			continue;
+		for (j = 0; j < i; ++j) {
+			if (nr2da[j].nr == nr)
+				break;
 		}
-		if (keys[nr].dkeaddr) {
-			int	x;
+		if (j < i) {
+			key = nr2da[j].key;
+			if (key && key->dkeaddr) {
+				int	x;
 
-			for (x=sizeof(dke);x--;)
-				if (((char*)&dke)[x])
-					break;
-			if (x==-1)
-				break; /* finished reading if we got only 0 */
-			if (nr) {
-				if (	(dke.next!=(long)keys[nr].next)	||
-					(dke.nextsub!=(long)keys[nr].nextsub)	||
-					(dke.prevlvl!=(long)keys[nr].prevlvl) 
-				)
-					dprintf_reg(stddeb,"key doubled? nr=%ld,key->dkeaddr=%lx,dkeaddr=%lx\n",nr,keys[nr].dkeaddr,dkeaddr);
+				for (x=sizeof(dke);x--;)
+					if (((char*)&dke)[x])
+						break;
+				if (x==-1)
+					break;	/* finished reading if we got only 0 */
+				if (nr) {
+					if ((dke.next!=(long)key->next) ||
+						(dke.nextsub!=(long)key->nextsub) ||
+						(dke.prevlvl!=(long)key->prevlvl) 
+					)
+						dprintf_reg(stddeb,"key doubled? nr=%lu,key->dkeaddr=%lx,dkeaddr=%lx\n",nr,key->dkeaddr,dkeaddr);
+				}
+				continue;
 			}
-			continue;
 		}
-		nr2da[i].nr	 = nr;
+#if DEBUG_W95_LOADREG
+		dprintf_reg(stddeb,"- nr=%lu,dkeaddr=%lx\n",nr,dkeaddr);
+#endif
+		nr2da[i].nr = nr;
 		nr2da[i].dkeaddr = dkeaddr;
+		nr2da[i].key = &keys[i];
 
-		keys[nr].dkeaddr = dkeaddr;
-		keys[nr].x1 = dke.x1;
-		keys[nr].x2 = dke.x2;
-		keys[nr].x3 = dke.x3;
-		keys[nr].prevlvl= (struct _w95key*)dke.prevlvl;
-		keys[nr].nextsub= (struct _w95key*)dke.nextsub;
-		keys[nr].next 	= (struct _w95key*)dke.next;
+		keys[i].dkeaddr = dkeaddr;
+		keys[i].x1 = dke.x1;
+		keys[i].x2 = dke.x2;
+		keys[i].x3 = dke.x3;
+		keys[i].prevlvl= (struct _w95key*)dke.prevlvl;
+		keys[i].nextsub= (struct _w95key*)dke.nextsub;
+		keys[i].next 	= (struct _w95key*)dke.next;
 	}
 	free(data);
 
+	nrofdkes = i;	/* This is the real number of dke entries */
+#if DEBUG_W95_LOADREG
+	dprintf_reg(stddeb,"nrofdkes = %d\n", nrofdkes);
+#endif
+
 	qsort(nr2da,nrofdkes,sizeof(nr2da[0]),
-              (int(*)(const void *,const void*))_w95dkecomp);
+              (int(*)(const void *,const void *))_w95dkecomp);
 
 	/* STEP 2: keydata & values */
 	if (!GetFileInformationByHandle(hfd,&hfdinfo))
@@ -1267,11 +1323,12 @@
 		dprintf_reg(stddeb,"third IFF header not RGDB, but %s\n",magic);
 		return;
 	}
+
 	curdata=data+0x20;
 	while (1) {
 		struct	dkh dkh;
-		int	bytesread;
-		struct	_w95key	*key,xkey;
+		int		bytesread;
+		struct	_w95key	xkey;	/* Used inside second main loop */
 
 		bytesread = 0;
 		if (curdata>=nextrgdb) {
@@ -1294,19 +1351,26 @@
 
 		XREAD(&dkh,sizeof(dkh));
 		nr = dkh.nrLS + (dkh.nrMS<<8);
-		if ((nr>nrofdkes) || (dkh.nrLS == 0xFFFF)) {
-			if (dkh.nrLS == 0xFFFF) {
+		if (dkh.nrLS == 0xFFFF) {
 				/* skip over key using nextkeyoff */
  				curdata+=dkh.nextkeyoff-sizeof(struct dkh);
 				continue;
+		} 
+		for (i = 0; i < nrofdkes; ++i) {
+			if (nr2da[i].nr == nr && nr2da[i].dkeaddr) {
+				key = nr2da[i].key;
+				break;
 			}
-			dprintf_reg(stddeb,"haven't found nr %ld.\n",nr);
+		}
+		if (i >= nrofdkes) {
+			/* Move the next statement to just before the previous for */
+			/* loop to prevent the compiler from issuing a warning -kc */
 			key = &xkey;
 			memset(key,'\0',sizeof(xkey));
+			dprintf_reg(stddeb,"haven't found nr %lu.\n",nr);
 		} else {
-			key = keys+nr;
 			if (!key->dkeaddr)
-				dprintf_reg(stddeb,"key with nr=%ld has no dkeaddr?\n",nr);
+				dprintf_reg(stddeb,"key with nr=%lu has no dkeaddr?\n",nr);
 		}
 		key->nrofvals	= dkh.values;
 		key->name	= (char*)xmalloc(dkh.keynamelen+1);
@@ -1340,7 +1404,7 @@
 		if (bytesread != dkh.nextkeyoff) {
 			if (dkh.bytesused != bytesread)
 				dprintf_reg(stddeb,
-					"read has difference in read bytes (%d) and nextoffset (%ld) (bytesused=%ld)\n",bytesread,dkh.nextkeyoff,
+					"read has difference in read bytes (%d) and nextoffset (%lu) (bytesused=%lu)\n",bytesread,dkh.nextkeyoff,
 					dkh.bytesused
 				);
 			curdata += dkh.nextkeyoff-bytesread;
@@ -1353,6 +1417,7 @@
 	}
 	free(data);
 	_w95_walk_tree(lpkey,keys);
+	free(nr2da);
 	free(keys);
 }
 
diff --git a/misc/shellord.c b/misc/shellord.c
index 3a1a6dc..1d4f857 100644
--- a/misc/shellord.c
+++ b/misc/shellord.c
@@ -83,7 +83,7 @@
  *	 		 SHELL32_30   			[SHELL32.30]
  * get_rootdir(char*path,int drive)
  */
-DWORD WINAPI SHELL32_30(LPSTR root,BYTE drive) {
+LPSTR WINAPI SHELL32_30(LPSTR root,BYTE drive) {
 	strcpy(root,"A:\\");
 	root[0]+=drive;
 	return root;
diff --git a/misc/tweak.c b/misc/tweak.c
index 0d88d0b..3fa2782 100644
--- a/misc/tweak.c
+++ b/misc/tweak.c
@@ -33,7 +33,6 @@
 #include "graphics.h"
 #include "options.h"
 #include "stackframe.h"
-#include "syscolor.h"
 #include "tweak.h"
 #include "windows.h"
 
diff --git a/misc/ver.c b/misc/ver.c
index 883af0d..40c3241 100644
--- a/misc/ver.c
+++ b/misc/ver.c
@@ -843,8 +843,13 @@
 	LPSTR curdir,UINT32 *pcurdirlen,LPSTR destdir,UINT32 *pdestdirlen )
 {
     UINT16 curdirlen, destdirlen;
-    DWORD ret = VerFindFile16(flags,filename,windir,appdir,
-                              curdir,&curdirlen,destdir,&destdirlen);
+    DWORD ret;
+    
+    curdirlen = (UINT16)*pcurdirlen;
+    destdirlen= (UINT16)*pdestdirlen;
+
+    ret = VerFindFile16(flags,filename,windir,appdir,
+                        curdir,&curdirlen,destdir,&destdirlen);
     *pcurdirlen = curdirlen;
     *pdestdirlen = destdirlen;
     return ret;
diff --git a/misc/winsock.c b/misc/winsock.c
index b94bb3c..88c740c 100644
--- a/misc/winsock.c
+++ b/misc/winsock.c
@@ -170,6 +170,10 @@
 		    FD_SET(pws->fd, fds);
 	     }
 	}
+	if (b32)
+	     wsfds32->fd_count = 0;
+	else
+	     wsfds16->fd_count = 0;
 #undef wsfds32
 #undef wsfds16
 	return fds;
@@ -791,7 +795,7 @@
     INT32 *p = &optlen32;
     INT32 retVal;
     if( optlen ) optlen32 = *optlen; else p = NULL;
-    retVal = WINSOCK_getsockopt32( s, level, optname, optval, p );
+    retVal = WINSOCK_getsockopt32( s, (UINT16)level, optname, optval, p );
     if( optlen ) *optlen = optlen32;
     return (INT16)retVal;
 }
@@ -1226,7 +1230,7 @@
 	optval = (char*)&linger32;
 	optlen = sizeof(linger32);
     }
-    return (INT16)WINSOCK_setsockopt32( s, level, optname, optval, optlen );
+    return (INT16)WINSOCK_setsockopt32( s, (UINT16)level, optname, optval, optlen );
 }
 
 
diff --git a/misc/wsprintf.c b/misc/wsprintf.c
index 7d57209..936afd0 100644
--- a/misc/wsprintf.c
+++ b/misc/wsprintf.c
@@ -40,6 +40,8 @@
     WPRINTF_TYPE   type;
 } WPRINTF_FORMAT;
 
+static const CHAR null_stringA[] = "(null)";
+static const WCHAR null_stringW[] = { '(', 'n', 'u', 'l', 'l', ')', 0 };
 
 /***********************************************************************
  *           WPRINTF_ParseFormatA
@@ -201,11 +203,13 @@
     case WPR_WCHAR:
         return (format->precision = 1);
     case WPR_STRING:
+        if (!*(LPCSTR *)arg) *(LPCSTR *)arg = null_stringA;
         for (len = 0; !format->precision || (len < format->precision); len++)
             if (!*(*(LPCSTR *)arg + len)) break;
         if (len > maxlen) len = maxlen;
         return (format->precision = len);
     case WPR_WSTRING:
+        if (!*(LPCWSTR *)arg) *(LPCWSTR *)arg = null_stringW;
         for (len = 0; !format->precision || (len < format->precision); len++)
             if (!*(*(LPCWSTR *)arg + len)) break;
         if (len > maxlen) len = maxlen;
diff --git a/msdos/int21.c b/msdos/int21.c
index b654e5f..ae03308 100644
--- a/msdos/int21.c
+++ b/msdos/int21.c
@@ -696,7 +696,7 @@
     BYTE attr;
     int count;
 
-    if (*fcb == 0xff)
+    if (*fcb == 0xff) /* extended FCB ? */
     {
         attr = fcb[6];
         pFCB = (FINDFILE_FCB *)(fcb + 7);
@@ -718,6 +718,14 @@
     }
     pFCB->count += count;
 
+    if (*fcb == 0xff) { /* place extended FCB header before pResult if called with extended FCB */
+	*(BYTE *)pResult = 0xff;
+	(BYTE *)pResult +=6; /* leave reserved field behind */
+	*(BYTE *)pResult = entry.dwFileAttributes;
+	((BYTE *)pResult)++;
+    }
+    *(BYTE *)pResult = DOS_GET_DRIVE( pFCB->drive ); /* DOS_DIRENTRY_LAYOUT after current drive number */
+    ((BYTE *)pResult)++;
     pResult->fileattr = entry.dwFileAttributes;
     pResult->cluster  = 0;  /* what else? */
     pResult->filesize = entry.nFileSizeLow;
diff --git a/msdos/int2f.c b/msdos/int2f.c
index 2f4d56e..755e05b 100644
--- a/msdos/int2f.c
+++ b/msdos/int2f.c
@@ -57,6 +57,9 @@
     case 0xb7:  /* append */
         AL_reg(context) = 0; /* not installed */
         break;
+    case 0xbd:  /* some Novell network install check ??? */
+        AX_reg(context) = 0xa5a5; /* pretend to have Novell IPX installed */
+	break;
     default:
         INT_BARF( context, 0x2f );
         break;
diff --git a/multimedia/Makefile.in b/multimedia/Makefile.in
index 2f2f157..f4a288f 100644
--- a/multimedia/Makefile.in
+++ b/multimedia/Makefile.in
@@ -7,6 +7,7 @@
 
 C_SRCS = \
 	audio.c \
+	dsound.c \
 	joystick.c \
 	mcianim.c \
 	mcicda.c \
diff --git a/multimedia/dsound.c b/multimedia/dsound.c
new file mode 100644
index 0000000..5b3983b
--- /dev/null
+++ b/multimedia/dsound.c
@@ -0,0 +1,177 @@
+/*  			DS
+ */
+
+#include <stdio.h>
+#include "windows.h"
+#include "interfaces.h"
+#include "mmsystem.h"
+#include "dsound.h"
+
+HRESULT WINAPI DirectSoundEnumerate32A(LPDSENUMCALLBACK32A enumcb,LPVOID context) {
+	return 0;
+}
+
+static HRESULT WINAPI IDirectSoundBuffer_SetFormat(
+	LPDIRECTSOUNDBUFFER this,LPWAVEFORMATEX wfex
+) {
+	fprintf(stderr,"IDirectSoundBuffer(%p)->SetFormat(%p),stub!\n",this,wfex);
+	return 0;
+}
+
+static HRESULT WINAPI IDirectSoundBuffer_SetVolume(
+	LPDIRECTSOUNDBUFFER this,LONG vol
+) {
+	fprintf(stderr,"IDirectSoundBuffer(%p)->SetVolume(%08lx),stub!\n",this,vol);
+	return 0;
+}
+
+static HRESULT WINAPI IDirectSoundBuffer_GetVolume(
+	LPDIRECTSOUNDBUFFER this,LPLONG vol
+) {
+	fprintf(stderr,"IDirectSoundBuffer(%p)->GetVolume(%p),stub!\n",this,vol);
+	*vol = 100;
+	return 0;
+}
+
+static HRESULT WINAPI IDirectSoundBuffer_SetFrequency(
+	LPDIRECTSOUNDBUFFER this,DWORD freq
+) {
+	fprintf(stderr,"IDirectSoundBuffer(%p)->SetFrequency(%08lx),stub!\n",this,freq);
+	return 0;
+}
+
+static HRESULT WINAPI IDirectSoundBuffer_Play(
+	LPDIRECTSOUNDBUFFER this,DWORD x,DWORD y,DWORD z
+) {
+	fprintf(stderr,"IDirectSoundBuffer(%p)->Play(%08lx,%08lx,%08lx),stub!\n",
+		this,x,y,z
+	);
+	return 0;
+}
+
+static HRESULT WINAPI IDirectSoundBuffer_Stop(LPDIRECTSOUNDBUFFER this) {
+	fprintf(stderr,"IDirectSoundBuffer(%p)->Stop()\n",this);
+	return 0;
+}
+
+static DWORD WINAPI IDirectSoundBuffer_AddRef(LPDIRECTSOUNDBUFFER this) {
+	fprintf(stderr,"IDirectSoundBuffer(%p)->AddRef()\n",this);
+	return ++(this->ref);
+}
+static DWORD WINAPI IDirectSoundBuffer_Release(LPDIRECTSOUNDBUFFER this) {
+	fprintf(stderr,"IDirectSoundBuffer(%p)->Release(),stub!\n",this);
+	if (--this->ref)
+		return this->ref;
+	fprintf(stderr,"	-> IDirectSoundBuffer(%p) freed.\n",this);
+	HeapFree(GetProcessHeap(),0,this);
+	return 0;
+}
+
+static HRESULT WINAPI IDirectSoundBuffer_GetCurrentPosition(
+	LPDIRECTSOUNDBUFFER this,LPDWORD playpos,LPDWORD writepos
+) {
+	fprintf(stderr,"IDirectSoundBuffer(%p)->GetCurrentPosition(%p,%p),stub!\n",this,playpos,writepos);
+	return 0;
+}
+
+static HRESULT WINAPI IDirectSoundBuffer_GetStatus(
+	LPDIRECTSOUNDBUFFER this,LPDWORD status
+) {
+	fprintf(stderr,"IDirectSoundBuffer(%p)->GetStatus(%p),stub!\n",this,status);
+	*status = 0; /* hmm. set playing? or not ? */
+	return 0;
+}
+
+static HRESULT WINAPI IDirectSoundBuffer_Lock(
+	LPDIRECTSOUNDBUFFER this,DWORD x1,DWORD x2,LPVOID p1,LPDWORD x3,LPVOID p2,LPDWORD x4,DWORD x5
+) {
+	fprintf(stderr,"IDirectSoundBuffer(%p)->Lock(0x%08lx,0x%08lx,%p,%p,%p,%p,0x%08lx,),stub!\n",this,x1,x2,p1,x3,p2,x4,x5);
+	return 0x80000000;
+}
+
+
+static struct tagLPDIRECTSOUNDBUFFER_VTABLE dsbvt = {
+	(void *)1,
+	IDirectSoundBuffer_AddRef,
+	IDirectSoundBuffer_Release,
+	(void *)4,
+	IDirectSoundBuffer_GetCurrentPosition,
+	(void *)6,
+	IDirectSoundBuffer_GetVolume,
+	(void *)8,
+        (void *)9,
+	IDirectSoundBuffer_GetStatus,
+	(void *)11,
+	IDirectSoundBuffer_Lock,
+	IDirectSoundBuffer_Play,
+	(void *)14,
+	IDirectSoundBuffer_SetFormat,
+	IDirectSoundBuffer_SetVolume,
+	(void *)17,
+	IDirectSoundBuffer_SetFrequency,
+	IDirectSoundBuffer_Stop,
+	(void *)20
+};
+
+
+
+static HRESULT WINAPI IDirectSound_SetCooperativeLevel(
+	LPDIRECTSOUND this,HWND32 hwnd,DWORD level
+) {
+	fprintf(stderr,"IDirectSound(%p)->SetCooperativeLevel(%08lx,%ld),stub!\n",
+		this,(DWORD)hwnd,level
+	);
+	return 0;
+}
+
+
+static HRESULT WINAPI IDirectSound_CreateSoundBuffer(
+	LPDIRECTSOUND this,LPDSBUFFERDESC dsbd,LPLPDIRECTSOUNDBUFFER ppdsb,LPUNKNOWN lpunk
+) {
+	fprintf(stderr,"IDirectSound(%p)->CreateBuffer(%p,%p,%p),stub!\n",this,dsbd,ppdsb,lpunk);
+	*ppdsb = (LPDIRECTSOUNDBUFFER)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBuffer));
+	(*ppdsb)->ref =1;
+	(*ppdsb)->lpvtbl = &dsbvt;
+	return 0;
+}
+
+static HRESULT WINAPI IDirectSound_GetCaps(LPDIRECTSOUND this,LPDSCAPS dscaps) {
+	fprintf(stderr,"IDirectSound(%p)->GetCaps(%p),stub!\n",this,dscaps);
+	return 0;
+}
+
+static ULONG WINAPI IDirectSound_AddRef(LPDIRECTSOUND this) {
+	fprintf(stderr,"IDirectSound(%p)->AddRef()\n",this);
+	return ++(this->ref);
+}
+
+static ULONG WINAPI IDirectSound_Release(LPDIRECTSOUND this) {
+	fprintf(stderr,"IDirectSound(%p)->Release()\n",this);
+	if (!--(this->ref)) {
+		HeapFree(GetProcessHeap(),0,this);
+		return 0;
+	}
+	return this->ref;
+}
+
+static struct tagLPDIRECTSOUND_VTABLE dsvt = {
+	(void *)1,
+	IDirectSound_AddRef,
+	IDirectSound_Release,
+	IDirectSound_CreateSoundBuffer,
+	IDirectSound_GetCaps,
+	(void *)6,
+	IDirectSound_SetCooperativeLevel,
+	(void *)8,
+        (void *)9,
+        (void *)10,
+        (void *)11
+};
+
+HRESULT WINAPI DirectSoundCreate(LPGUID lpGUID,LPDIRECTSOUND *ppDS,IUnknown *pUnkOuter ) {
+	fprintf(stderr,"DirectSoundCreate(%p,%p,%p)\n",lpGUID,ppDS,pUnkOuter);
+	*ppDS = (LPDIRECTSOUND)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSound));
+	(*ppDS)->ref = 1;
+	(*ppDS)->lpvtbl = &dsvt;
+	return 0;
+}
diff --git a/multimedia/joystick.c b/multimedia/joystick.c
index 97f4016..e59ef65 100644
--- a/multimedia/joystick.c
+++ b/multimedia/joystick.c
@@ -2,6 +2,15 @@
  * joystick functions
  *
  * Copyright 1997 Andreas Mohr
+ *
+ * nearly all joystick functions can be regarded as obsolete,
+ * as Linux (2.1.x) now supports extended joysticks
+ * with a completely new joystick driver interface
+ * new driver's docu says:
+ * "For backward compatibility the old interface is still included,
+ * but will be dropped in the future."
+ * Thus we should implement the new interface and at most keep the old
+ * routines for backward compatibility.
  */
 
 #include <unistd.h>
@@ -250,6 +259,15 @@
 }
 
 /**************************************************************************
+ *                              JoyGetPosEx             [WINMM.31]
+ */
+MMRESULT32 WINAPI joyGetPosEx(UINT32 wID, LPJOYINFO32 lpInfo)
+{
+	/* FIXME: implement it */
+	return MMSYSERR_NODRIVER;
+}
+
+/**************************************************************************
  * 				JoyGetPos	       	[WINMM.30]
  */
 MMRESULT32 WINAPI joyGetPos32(UINT32 wID, LPJOYINFO32 lpInfo)
diff --git a/objects/brush.c b/objects/brush.c
index 8f2eb83..184eeea 100644
--- a/objects/brush.c
+++ b/objects/brush.c
@@ -7,7 +7,6 @@
 #include <stdlib.h>
 #include "brush.h"
 #include "bitmap.h"
-#include "syscolor.h"
 #include "metafile.h"
 #include "color.h"
 #include "stddebug.h"
@@ -247,80 +246,6 @@
 
 
 /***********************************************************************
- *           GetSysColorBrush16    (USER.281)
- */
-HBRUSH16 WINAPI GetSysColorBrush16( INT16 index )
-{
-    return (HBRUSH16)GetSysColorBrush32(index);
-}
-
-
-/***********************************************************************
- *           GetSysColorBrush32    (USER32.289)
- */
-HBRUSH32 WINAPI GetSysColorBrush32( INT32 index )
-{
-  switch(index){
-  case COLOR_SCROLLBAR:
-    return sysColorObjects.hbrushScrollbar;
-  case COLOR_BACKGROUND: 
-    return sysColorObjects.hbrushBackground; 
-  case COLOR_ACTIVECAPTION:
-    return sysColorObjects.hbrushActiveCaption;
-  case COLOR_INACTIVECAPTION:
-    return sysColorObjects.hbrushInactiveCaption;
-  case COLOR_MENU:
-    return sysColorObjects.hbrushMenu;
-  case COLOR_WINDOW:
-    return sysColorObjects.hbrushWindow;
-  case COLOR_WINDOWFRAME:
-    return sysColorObjects.hbrushWindowFrame;
-  case COLOR_MENUTEXT:
-    return sysColorObjects.hbrushMenuText;
-  case COLOR_WINDOWTEXT:
-    return sysColorObjects.hbrushWindowText;
-  case COLOR_CAPTIONTEXT:
-    return sysColorObjects.hbrushCaptionText;
-  case COLOR_ACTIVEBORDER:
-    return sysColorObjects.hbrushActiveBorder;
-  case COLOR_INACTIVEBORDER:
-    return sysColorObjects.hbrushInactiveBorder;
-  case COLOR_APPWORKSPACE:
-    return sysColorObjects.hbrushAppWorkspace; 
-  case COLOR_HIGHLIGHT:
-    return sysColorObjects.hbrushHighlight;
-  case COLOR_HIGHLIGHTTEXT:
-    return sysColorObjects.hbrushHighlightText;
-  case COLOR_BTNFACE: /* same as COLOR_3DFACE */
-    return sysColorObjects.hbrushBtnFace;
-  case COLOR_BTNSHADOW: /* same as COLOR_3DSHADOW */
-    return sysColorObjects.hbrushBtnShadow;
-  case COLOR_GRAYTEXT:
-    return sysColorObjects.hbrushGrayText;
-  case COLOR_BTNTEXT:
-    return sysColorObjects.hbrushBtnText;
-  case COLOR_INACTIVECAPTIONTEXT:
-    return sysColorObjects.hbrushInactiveCaptionText;
-  case COLOR_BTNHIGHLIGHT: /* same as COLOR_(3DHIGH|3DHI|BTNHI)LIGHT */
-    return sysColorObjects.hbrushBtnHighlight;
-  case COLOR_3DDKSHADOW:
-    return sysColorObjects.hbrush3DDkShadow;
-  case COLOR_3DLIGHT:
-    return sysColorObjects.hbrush3DLight;
-  case COLOR_INFOTEXT:
-    return sysColorObjects.hbrushInfoText;
-  case COLOR_INFOBK:
-    return sysColorObjects.hbrushInfoBk;
-  default:
-    fprintf( stderr, "GetSysColorBrush32: Unknown index(%d)\n", index );
-  }
-
-  return GetStockObject32(LTGRAY_BRUSH);
-
-}
-
-
-/***********************************************************************
  *           BRUSH_DeleteObject
  */
 BOOL32 BRUSH_DeleteObject( HBRUSH16 hbrush, BRUSHOBJ * brush )
diff --git a/objects/cursoricon.c b/objects/cursoricon.c
index d77a5f7..2ec3b59 100644
--- a/objects/cursoricon.c
+++ b/objects/cursoricon.c
@@ -761,7 +761,8 @@
 
     dprintf_cursor( stddeb, "CreateCursor: %dx%d spot=%d,%d xor=%p and=%p\n",
                     nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
-    return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
+    return CreateCursorIconIndirect( MODULE_HANDLEtoHMODULE16( hInstance ),
+                                     &info, lpANDbits, lpXORbits );
 }
 
 
@@ -791,7 +792,8 @@
 
     dprintf_icon( stddeb, "CreateIcon: %dx%dx%d, xor=%p, and=%p\n",
                   nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
-    return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
+    return CreateCursorIconIndirect( MODULE_HANDLEtoHMODULE16( hInstance ),
+                                     &info, lpANDbits, lpXORbits );
 }
 
 
@@ -892,7 +894,7 @@
 {
     dprintf_cursor( stddeb, "DestroyCursor: %04x\n", hCursor );
     /* FIXME: should check for OEM cursor here */
-    return (FreeResource16( hCursor ) != 0);
+    return (FreeResource16( hCursor ) == 0);
 }
 
 
diff --git a/objects/dib.c b/objects/dib.c
index b5d1cf2..0f1ef17 100644
--- a/objects/dib.c
+++ b/objects/dib.c
@@ -240,13 +240,16 @@
  *
  * Handles a single line of 1 bit data.
  */
-static void DIB_SetImageBits_1_Line(DWORD dstwidth, int *colors,
+static void DIB_SetImageBits_1_Line(DWORD dstwidth, int left, int *colors,
 				    XImage *bmpImage, int h, const BYTE *bits)
 {
     BYTE pix;
     DWORD i, x;
 
-    for (i = dstwidth/8, x = 0; (i > 0); i--)
+    dstwidth += left; bits += left >> 3;
+
+    /* FIXME: should avoid putting x<left pixels (minor speed issue) */
+    for (i = dstwidth/8, x = left&~7; (i > 0); i--)
     {
 	pix = *bits++;
 	XPutPixel( bmpImage, x++, h, colors[pix >> 7] );
@@ -277,7 +280,7 @@
  * SetDIBits for a 1-bit deep DIB.
  */
 static void DIB_SetImageBits_1( int lines, const BYTE *srcbits,
-                                DWORD srcwidth, DWORD dstwidth,
+                                DWORD srcwidth, DWORD dstwidth, int left,
                                 int *colors, XImage *bmpImage )
 {
     int h;
@@ -287,13 +290,13 @@
 
     if (lines > 0) {
 	for (h = lines-1; h >=0; h--) {
-	    DIB_SetImageBits_1_Line(dstwidth, colors, bmpImage, h, srcbits);
+	    DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h, srcbits);
 	    srcbits += linebytes;
 	}
     } else {
 	lines = -lines;
 	for (h = 0; h < lines; h++) {
-	    DIB_SetImageBits_1_Line(dstwidth, colors, bmpImage, h, srcbits);
+	    DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h, srcbits);
 	    srcbits += linebytes;
 	}
     }
@@ -306,38 +309,41 @@
  * SetDIBits for a 4-bit deep DIB.
  */
 static void DIB_SetImageBits_4( int lines, const BYTE *srcbits,
-                                DWORD srcwidth, DWORD dstwidth,
+                                DWORD srcwidth, DWORD dstwidth, int left,
                                 int *colors, XImage *bmpImage )
 {
     DWORD i, x;
     int h;
-    const BYTE *bits = srcbits;
+    const BYTE *bits = srcbits + (left >> 1);
   
     /* 32 bit aligned */
     DWORD linebytes = ((srcwidth+7)&~7)/2;
 
+    dstwidth += left;
+
+    /* FIXME: should avoid putting x<left pixels (minor speed issue) */
     if (lines > 0) {
 	for (h = lines-1; h >= 0; h--) {
-	    for (i = dstwidth/2, x = 0; i > 0; i--) {
+	    for (i = dstwidth/2, x = left&~1; i > 0; i--) {
 		BYTE pix = *bits++;
 		XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
 		XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
 	    }
 	    if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
 	    srcbits += linebytes;
-	    bits	 = srcbits;
+	    bits	 = srcbits + (left >> 1);
 	}
     } else {
 	lines = -lines;
 	for (h = 0; h < lines; h++) {
-	    for (i = dstwidth/2, x = 0; i > 0; i--) {
+	    for (i = dstwidth/2, x = left&~1; i > 0; i--) {
 		BYTE pix = *bits++;
 		XPutPixel( bmpImage, x++, h, colors[pix >> 4] );
 		XPutPixel( bmpImage, x++, h, colors[pix & 0x0f] );
 	    }
 	    if (dstwidth & 1) XPutPixel( bmpImage, x, h, colors[*bits >> 4] );
 	    srcbits += linebytes;
-	    bits	 = srcbits;
+	    bits	 = srcbits + (left >> 1);
 	}
     }
 }
@@ -355,11 +361,13 @@
  * SetDIBits for a 4-bit deep compressed DIB.
  */
 static void DIB_SetImageBits_RLE4( int lines, const BYTE *bits, DWORD width,
-                                DWORD dstwidth, int *colors, XImage *bmpImage )
+                                DWORD dstwidth, int left, int *colors, XImage *bmpImage )
 {
 	int x = 0, c, length;
 	const BYTE *begin = bits;
 
+        dstwidth += left; /* FIXME: avoid putting x<left pixels */
+
         lines--;
 	while ((int)lines >= 0)
         {
@@ -415,30 +423,32 @@
  * SetDIBits for an 8-bit deep DIB.
  */
 static void DIB_SetImageBits_8( int lines, const BYTE *srcbits,
-				DWORD srcwidth, DWORD dstwidth,
+				DWORD srcwidth, DWORD dstwidth, int left,
                                 int *colors, XImage *bmpImage )
 {
     DWORD x;
     int h;
-    const BYTE *bits = srcbits;
+    const BYTE *bits = srcbits + left;
 
     /* align to 32 bit */
     DWORD linebytes = (srcwidth + 3) & ~3;
 
+    dstwidth+=left;
+
     if (lines > 0) {
 	for (h = lines - 1; h >= 0; h--) {
-	    for (x = 0; x < dstwidth; x++, bits++) {
+	    for (x = left; x < dstwidth; x++, bits++) {
 		XPutPixel( bmpImage, x, h, colors[*bits] );
 	    }
-	    bits = (srcbits += linebytes);
+	    bits = (srcbits += linebytes) + left;
 	}
     } else {
 	lines = -lines;
 	for (h = 0; h < lines; h++) {
-	    for (x = 0; x < dstwidth; x++, bits++) {
+	    for (x = left; x < dstwidth; x++, bits++) {
 		XPutPixel( bmpImage, x, h, colors[*bits] );
 	    }
-	    bits = (srcbits += linebytes);
+	    bits = (srcbits += linebytes) + left;
 	}
     }
 }
@@ -475,7 +485,7 @@
 };
   
 static void DIB_SetImageBits_RLE8( int lines, const BYTE *bits, DWORD width,
-                                DWORD dstwidth, int *colors, XImage *bmpImage )
+                                DWORD dstwidth, int left, int *colors, XImage *bmpImage )
 {
     int x;			/* X-positon on each line.  Increases. */
     int line;			/* Line #.  Starts at lines-1, decreases */
@@ -488,6 +498,8 @@
     if (lines == 0)		/* Let's hope this doesn't happen. */
       return;
     
+    dstwidth += left; /* FIXME: avoid putting x<left pixels */
+
     /*
      * Note that the bitmap data is stored by Windows starting at the
      * bottom line of the bitmap and going upwards.  Within each line,
@@ -628,7 +640,7 @@
  * SetDIBits for a 16-bit deep DIB.
  */
 static void DIB_SetImageBits_16( int lines, const BYTE *srcbits,
-                                 DWORD srcwidth, DWORD dstwidth,
+                                 DWORD srcwidth, DWORD dstwidth, int left,
 				 DC *dc, XImage *bmpImage )
 {
     DWORD x;
@@ -640,10 +652,12 @@
     /* align to 32 bit */
     DWORD linebytes = (srcwidth * 2 + 3) & ~3;
 
-    ptr = (LPWORD) srcbits;
+    dstwidth += left;
+
+    ptr = (LPWORD) srcbits + left;
     if (lines > 0) {
 	for (h = lines - 1; h >= 0; h--) {
-	    for (x = 0; x < dstwidth; x++, ptr++) {
+	    for (x = left; x < dstwidth; x++, ptr++) {
 		val = *ptr;
 		r = (BYTE) ((val & 0x7c00) >> 7);
 		g = (BYTE) ((val & 0x03e0) >> 2);
@@ -651,12 +665,12 @@
 		XPutPixel( bmpImage, x, h,
 			   COLOR_ToPhysical(dc, RGB(r,g,b)) );
 	    }
-	    ptr = (LPWORD) (srcbits += linebytes);
+	    ptr = (LPWORD) (srcbits += linebytes) + left;
 	}
     } else {
 	lines = -lines;
 	for (h = 0; h < lines; h++) {
-	    for (x = 0; x < dstwidth; x++, ptr++) {
+	    for (x = left; x < dstwidth; x++, ptr++) {
 		val = *ptr;
 		r = (BYTE) ((val & 0x7c00) >> 7);
 		g = (BYTE) ((val & 0x03e0) >> 2);
@@ -664,7 +678,7 @@
 		XPutPixel( bmpImage, x, h,
 			   COLOR_ToPhysical(dc, RGB(r,g,b)) );
 	    }
-	    ptr = (LPWORD) (srcbits += linebytes);
+	    ptr = (LPWORD) (srcbits += linebytes) + left;
 	}
     }
 }
@@ -676,34 +690,36 @@
  * SetDIBits for a 24-bit deep DIB.
  */
 static void DIB_SetImageBits_24( int lines, const BYTE *srcbits,
-                                 DWORD srcwidth, DWORD dstwidth,
+                                 DWORD srcwidth, DWORD dstwidth, int left,
 				 DC *dc, XImage *bmpImage )
 {
     DWORD x;
-    const BYTE *bits = srcbits;
+    const BYTE *bits = srcbits + left * 3;
     int h;
   
     /* align to 32 bit */
     DWORD linebytes = (srcwidth * 3 + 3) & ~3;
 
+    dstwidth += left;
+
     /* "bits" order is reversed for some reason */
 
     if (lines > 0) {
 	for (h = lines - 1; h >= 0; h--) {
-	    for (x = 0; x < dstwidth; x++, bits += 3) {
+	    for (x = left; x < dstwidth; x++, bits += 3) {
 		XPutPixel( bmpImage, x, h, 
 			   COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
 	    }
-	    bits = (srcbits += linebytes);
+	    bits = (srcbits += linebytes) + left * 3;
 	}
     } else {
 	lines = -lines;
 	for (h = 0; h < lines; h++) {
-	    for (x = 0; x < dstwidth; x++, bits += 3) {
+	    for (x = left; x < dstwidth; x++, bits += 3) {
 		XPutPixel( bmpImage, x, h,
 			   COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
 	    }
-	    bits = (srcbits += linebytes);
+	    bits = (srcbits += linebytes) + left * 3;
 	}
     }
 }
@@ -715,31 +731,33 @@
  * SetDIBits for a 32-bit deep DIB.
  */
 static void DIB_SetImageBits_32( int lines, const BYTE *srcbits,
-                                 DWORD srcwidth, DWORD dstwidth,
+                                 DWORD srcwidth, DWORD dstwidth, int left,
 				 DC *dc, XImage *bmpImage )
 {
     DWORD x;
-    const BYTE *bits = srcbits;
+    const BYTE *bits = srcbits + left * 4;
     int h;
   
     DWORD linebytes = (srcwidth * 4);
 
+    dstwidth += left;
+
     if (lines > 0) {
 	for (h = lines - 1; h >= 0; h--) {
-	    for (x = 0; x < dstwidth; x++, bits += 4) {
+	    for (x = left; x < dstwidth; x++, bits += 4) {
 		XPutPixel( bmpImage, x, h, 
 			   COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
 	    }
-	    bits = (srcbits += linebytes);
+	    bits = (srcbits += linebytes) + left * 4;
 	}
     } else {
 	lines = -lines;
 	for (h = 0; h < lines; h++) {
-	    for (x = 0; x < dstwidth; x++, bits += 4) {
+	    for (x = left; x < dstwidth; x++, bits += 4) {
 		XPutPixel( bmpImage, x, h,
 			   COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])));
 	    }
-	    bits = (srcbits += linebytes);
+	    bits = (srcbits += linebytes) + left * 4;
 	}
     }
 }
@@ -779,34 +797,34 @@
     {
     case 1:
 	DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
-			    descr->width, colorMapping, bmpImage );
+			    descr->width, descr->xSrc, colorMapping, bmpImage );
 	break;
     case 4:
 	if (compression) DIB_SetImageBits_RLE4( descr->lines, descr->bits,
-                                                descr->infoWidth, descr->width,
+                                                descr->infoWidth, descr->width, descr->xSrc,
                                                 colorMapping, bmpImage );
 	else DIB_SetImageBits_4( descr->lines, descr->bits, descr->infoWidth,
-                                 descr->width, colorMapping, bmpImage );
+                                 descr->width, descr->xSrc, colorMapping, bmpImage );
 	break;
     case 8:
 	if (compression) DIB_SetImageBits_RLE8( descr->lines, descr->bits,
-                                                descr->infoWidth, descr->width,
+                                                descr->infoWidth, descr->width, descr->xSrc,
                                                 colorMapping, bmpImage );
 	else DIB_SetImageBits_8( descr->lines, descr->bits, descr->infoWidth,
-                                 descr->width, colorMapping, bmpImage );
+                                 descr->width, descr->xSrc, colorMapping, bmpImage );
 	break;
     case 15:
     case 16:
 	DIB_SetImageBits_16( descr->lines, descr->bits, descr->infoWidth,
-			     descr->width, descr->dc, bmpImage);
+			     descr->width, descr->xSrc, descr->dc, bmpImage);
 	break;
     case 24:
 	DIB_SetImageBits_24( descr->lines, descr->bits, descr->infoWidth,
-                             descr->width, descr->dc, bmpImage );
+                             descr->width, descr->xSrc, descr->dc, bmpImage );
 	break;
     case 32:
 	DIB_SetImageBits_32( descr->lines, descr->bits, descr->infoWidth,
-                             descr->width, descr->dc, bmpImage);
+                             descr->width, descr->xSrc, descr->dc, bmpImage);
 	break;
     default:
         fprintf( stderr, "Invalid depth %d for SetDIBits!\n", descr->infoBpp );
@@ -956,7 +974,7 @@
 {
     DIB_SETIMAGEBITS_DESCR descr;
     DC * dc;
-    DWORD width;
+    DWORD width, oldcy = cy;
     int height, tmpheight;
 
       /* Check parameters */
@@ -994,9 +1012,9 @@
     descr.drawable  = dc->u.x.drawable;
     descr.gc        = dc->u.x.gc;
     descr.xSrc      = xSrc;
-    descr.ySrc      = ySrc - startscan;
+    descr.ySrc      = tmpheight >= 0 ? lines-(ySrc-startscan)-cy+(oldcy-cy) : ySrc - startscan;
     descr.xDest     = dc->w.DCOrgX + XLPTODP( dc, xDest );
-    descr.yDest     = dc->w.DCOrgY + YLPTODP( dc, yDest );
+    descr.yDest     = dc->w.DCOrgY + YLPTODP( dc, yDest ) + (tmpheight >= 0 ? oldcy-cy : 0);
     descr.width     = cx;
     descr.height    = cy;
 
@@ -1409,13 +1427,14 @@
       BITMAP32 bmp;
       if (GetObject32A (res, sizeof (bmp), &bmp))
 	{
-	  *bits = bmp.bmBits;
-	  return res;
+            /* FIXME: this is wrong! (bmBits is always NULL) */
+            if (bits) *bits = bmp.bmBits;
+            return res;
 	}
     }
 
   /* Error.  */
   if (res) DeleteObject32 (res);
-  *bits = NULL;
-	return 0;
+  if (bits) *bits = NULL;
+  return 0;
 }
diff --git a/objects/palette.c b/objects/palette.c
index f7f4a04..a1f6153 100644
--- a/objects/palette.c
+++ b/objects/palette.c
@@ -284,7 +284,7 @@
     {
         PALETTEOBJ* palPtr = (PALETTEOBJ *)GDI_GetObjPtr(hPal, PALETTE_MAGIC);
 
-	if( (StartIndex + NumEntries) < palPtr->logpalette.palNumEntries )
+	if( (StartIndex + NumEntries) <= palPtr->logpalette.palNumEntries )
 	{
 	    UINT32 u;
 	    for( u = 0; u < NumEntries; u++ )
diff --git a/objects/region.c b/objects/region.c
index 65951ea..c68686f 100644
--- a/objects/region.c
+++ b/objects/region.c
@@ -796,3 +796,13 @@
     return result;
 }
 
+/***********************************************************************
+ *           GetRegionData   (GDI32.217)
+ * 
+ * This seems to be rather impossible with the current region implementation
+ * for it seems you cannot query X regions.
+ */
+DWORD WINAPI GetRegionData(HRGN32 hrgn,DWORD x,LPRGNDATA rgndata) {
+	fprintf(stderr,"GetRegionData(%04x,%08lx,%p), STUB!\n",hrgn,x,rgndata);
+	return 0;
+}
diff --git a/ole/compobj.c b/ole/compobj.c
index 7287bfe..96a300e 100644
--- a/ole/compobj.c
+++ b/ole/compobj.c
@@ -18,6 +18,8 @@
 #include "compobj.h"
 #include "interfaces.h"
 #include "shlobj.h"
+#include "ddraw.h"
+#include "dsound.h"
 
 DWORD currentMalloc=0;
 
diff --git a/ole/folders.c b/ole/folders.c
index cf0def5..45d5466 100644
--- a/ole/folders.c
+++ b/ole/folders.c
@@ -45,11 +45,13 @@
 }
 
 static IEnumIDList_VTable eidlvt = {
-	1,
+	(void *)1,
 	IEnumIDList_AddRef,
 	IEnumIDList_Release,
 	IEnumIDList_Next,
-	5,6,7
+	(void *)5,
+        (void *)6,
+        (void *)7
 };
 
 LPENUMIDLIST IEnumIDList_Constructor() {
@@ -109,7 +111,7 @@
 	fprintf(stderr,"IShellFolder(%p)->ParseDisplayName(%08x,%p,%s,%p,%p,%p),stub!\n",
 		this,hwndOwner,pbcReserved,lpszDisplayName,pchEaten,ppidl,pdwAttributes
 	);
-	*(DWORD*)pbcReserved = NULL;
+	*(DWORD*)pbcReserved = 0;
 	return 0;
 }
 
@@ -133,22 +135,25 @@
 	fprintf(stderr,"IShellFolder(%p)->CreateViewObject(0x%04x,%s,%p),stub!\n",
 		this,hwndOwner,xclsid,ppv
 	);
-	*(DWORD*)ppv = NULL;
+	*(DWORD*)ppv = 0;
 	return 0;
 }
 
 
 static struct IShellFolder_VTable sfvt = {
-	1,
+        (void *)1,
 	IShellFolder_AddRef,
 	IShellFolder_Release,
 	IShellFolder_ParseDisplayName,
 	IShellFolder_EnumObjects,
 	IShellFolder_BindToObject,
-	7,8,
+        (void *)7,
+        (void *)8,
 	IShellFolder_CreateViewObject,
 	IShellFolder_GetAttributesOf,
-	11,12,13
+        (void *)11,
+        (void *)12,
+        (void *)13
 };
 
 LPSHELLFOLDER IShellFolder_Constructor() {
@@ -161,7 +166,27 @@
 }
 
 static struct IShellLink_VTable slvt = {
-	1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21
+    (void *)1,
+    (void *)2,
+    (void *)3,
+    (void *)4,
+    (void *)5,
+    (void *)6,
+    (void *)7,
+    (void *)8,
+    (void *)9,
+    (void *)10,
+    (void *)11,
+    (void *)12,
+    (void *)13,
+    (void *)14,
+    (void *)15,
+    (void *)16,
+    (void *)17,
+    (void *)18,
+    (void *)19,
+    (void *)20,
+    (void *)21
 };
 
 LPSHELLLINK IShellLink_Constructor() {
diff --git a/programs/notepad/ChangeLog b/programs/notepad/ChangeLog
index aca5fa0..0a13af9 100644
--- a/programs/notepad/ChangeLog
+++ b/programs/notepad/ChangeLog
@@ -1,3 +1,8 @@
+Tue Dec 23 23:35:04 1997  Marcel Baur <mbaur@g26.ethz.ch>
+       * Fixed lots of bugs w/ resources in *.rc
+       * moved [notepad.c] into [main.c]
+       * moved [notepad.h] into [main.h]
+       
 Fri Dec 05 20:51:55 1997  Marcel Baur <mbaur@g26.ethz.ch>
        * [notepad.c] [notepad.h] [notepad.rc] [En.rc] [De.rc]
          [license.c] [license.h] [License_En.c]
diff --git a/programs/notepad/De.rc b/programs/notepad/De.rc
index ca2a109..33139b6 100644
--- a/programs/notepad/De.rc
+++ b/programs/notepad/De.rc
@@ -59,7 +59,7 @@
 #define DIALOG_PAGESETUP_TAIL        "&Fußzeile:"
 #define DIALOG_PAGESETUP_BORDERS     "Ränder"
 #define DIALOG_PAGESETUP_LEFT        "&Links:"
-#define DIALOG_PAGESETUP_RIGHT       "&Right:"
+#define DIALOG_PAGESETUP_RIGHT       "&Rechts:"
 #define DIALOG_PAGESETUP_TOP         "&Oben:"
 #define DIALOG_PAGESETUP_BOTTOM      "&Unten:"
 
@@ -73,7 +73,7 @@
 #define STRING_UNTITLED              "(unbenannt)"
 
 #define STRING_ALLFILES              "Alle Dateien (*.*)"
-#define STRING_TEXTFILES             "Textdateien (*.TXT)"
+#define STRING_TEXTFILES             "Textdateien (*.txt)"
 
 #define STRING_TOOLARGE       "'%s' ist zu gross für den Editor\n \
 Benutzen Sie bitte einen anderen Editor, um diese Datei zu bearbeiten."
@@ -88,4 +88,4 @@
 um diese Funktion \nabzuschließen. Beenden Sie eine oder mehrere \
 \nAnwendungen, um den verfügbaren Arbeitsspeicher zu \nerhöhen."
 
-
+#include "notepad.rc"
diff --git a/programs/notepad/En.rc b/programs/notepad/En.rc
index 35ab98a..e4ebc9e 100644
--- a/programs/notepad/En.rc
+++ b/programs/notepad/En.rc
@@ -73,7 +73,7 @@
 #define STRING_UNTITLED              "(untitled)"
 
 #define STRING_ALLFILES              "All files (*.*)"
-#define STRING_TEXTFILES             "Text files (*.*)"
+#define STRING_TEXTFILES             "Text files (*.txt)"
 
 #define STRING_TOOLARGE         "File '%s' ist too large for notepad.\n \
 Please use a different editor."
@@ -87,5 +87,5 @@
 task. \nClose one or more applications to increase the amount of \nfree \
 memory."
 
-
+#include "notepad.rc"
 
diff --git a/programs/notepad/Makefile.in b/programs/notepad/Makefile.in
index f8a83d6..ed5ffe1 100644
--- a/programs/notepad/Makefile.in
+++ b/programs/notepad/Makefile.in
@@ -5,7 +5,7 @@
 VPATH     = @srcdir@
 MODULE    = none
 PROGRAMS  = notepad
-ALL_LIBS  = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LDLIBS)
+ALL_LIBS  = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LIBS)
 RCFLAGS   = -w32 -h
 
 LANGUAGES   = En De
@@ -13,15 +13,13 @@
 
 MOSTSRCS = \
 	license.c \
-	notepad.c
+	main.c
 
 # Some strings need addresses >= 0x10000
 STRINGSRCS = \
 	$(LICENSELANG:%=License_%.c)
 
-RC_SRCS = \
-	notepad.rc \
-	$(LANGUAGES:%=%.rc)
+RC_SRCS = $(LANGUAGES:%=%.rc)
 
 C_SRCS = $(MOSTSRCS) $(STRINGSRCS)
 
diff --git a/programs/notepad/main.c b/programs/notepad/main.c
new file mode 100644
index 0000000..b236c09
--- /dev/null
+++ b/programs/notepad/main.c
@@ -0,0 +1,245 @@
+/*
+ * Notepad
+ *
+ * Copyright 1997 Marcel Baur <mbaur@g26.ethz.ch>
+ */
+
+#include <windows.h>
+
+#include "main.h"
+#include "license.h"
+
+NOTEPAD_GLOBALS Globals;
+
+CHAR STRING_MENU_Xx[]      = "MENU_En";
+CHAR STRING_PAGESETUP_Xx[] = "DIALOG_PAGESETUP_En";
+
+/***********************************************************************
+ *
+ *           NOTEPAD_RegisterLanguages
+ *
+ *  Handle language stuff at startup
+ */
+
+void NOTEPAD_RegisterLanguages(void) {
+
+  LPCSTR opt_lang = "En";
+  CHAR lang[3];
+  INT langnum;
+  
+ /* Find language specific string table */
+  for (langnum = 0; langnum <= MAX_LANGUAGE_NUMBER; langnum++)
+    {
+      Globals.wStringTableOffset = langnum * 0x100;
+      if (LoadString(Globals.hInstance, IDS_LANGUAGE_ID, lang, 
+            sizeof(lang)) && !lstrcmp(opt_lang, lang))
+      break;
+    }
+  if (langnum > MAX_LANGUAGE_NUMBER)
+    {
+      /* Find fallback language */
+      for (langnum = 0; langnum <= MAX_LANGUAGE_NUMBER; langnum++)
+	{
+	  Globals.wStringTableOffset = langnum * 0x100;
+	  if (LoadString(Globals.hInstance, IDS_LANGUAGE_ID, lang, sizeof(lang)))
+          break;
+	}
+      if (langnum > MAX_LANGUAGE_NUMBER)
+	{
+	MessageBox(0, "No language found", "FATAL ERROR", MB_OK);
+	return(1);
+	}
+    }
+
+  /* Change Resource names */
+  lstrcpyn(STRING_MENU_Xx + lstrlen(STRING_MENU_Xx) - 2, lang, 3);
+}
+
+
+/***********************************************************************
+ *
+ *           NOTEPAD_MenuCommand
+ *
+ *  All handling of main menu events
+ */
+
+int NOTEPAD_MenuCommand (WPARAM wParam)
+{  
+   printf("NOTEPAD_MenuCommand()\n");
+
+   switch (wParam) {
+     case NP_FILE_NEW:          break;
+     case NP_FILE_SAVE:         break;
+     case NP_FILE_SAVEAS:       break;
+     case NP_FILE_PRINT:        break;
+     case NP_FILE_PAGESETUP:    break;
+     case NP_FILE_PRINTSETUP:   break;
+
+     case NP_FILE_EXIT:         
+        PostQuitMessage(0);
+        break;
+
+     case NP_EDIT_UNDO:         break;
+     case NP_EDIT_CUT:          break;
+     case NP_EDIT_COPY:         break;
+     case NP_EDIT_PASTE:        break;
+     case NP_EDIT_DELETE:       break;
+     case NP_EDIT_TIMEDATE:     break;
+     case NP_EDIT_WRAP:         break;
+
+     case NP_SEARCH_SEARCH:     break;
+     case NP_SEARCH_NEXT:       break;
+
+     case NP_HELP_CONTENTS:     
+        printf("NP_HELP_CONTENTS\n");
+        WinHelp(Globals.hMainWnd, HELPFILE, HELP_INDEX, 0);
+        break;
+
+     case NP_HELP_SEARCH:       break;
+
+     case NP_HELP_ON_HELP:      
+        printf("NP_HELP_ON_HELP\n");
+        WinHelp(Globals.hMainWnd, HELPFILE, HELP_HELPONHELP, 0);
+        break;
+	
+     case NP_HELP_LICENSE:
+        WineLicense(Globals.hMainWnd, Globals.lpszLanguage);
+        break;
+	
+     case NP_HELP_NO_WARRANTY: 
+        printf("NP_ABOUT_NO_WARRANTY\n");
+        WineWarranty(Globals.hMainWnd, Globals.lpszLanguage);
+        break;
+
+     case NP_HELP_ABOUT_WINE:
+        printf("NP_ABOUT_WINE\n");
+        ShellAbout(Globals.hMainWnd, "WINE", "Notepad", 0);
+        break;
+
+   }
+   return 0;
+}
+
+
+
+/***********************************************************************
+ *
+ *           NOTEPAD_WndProc
+ */
+
+LRESULT NOTEPAD_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    PAINTSTRUCT ps;
+
+    switch (msg) {
+
+       case WM_CREATE:
+        printf("WM_CREATE\n");
+   	break;
+
+        case WM_PAINT:
+	  printf("WM_PAINT\n");
+          BeginPaint(hWnd, &ps);
+          EndPaint(hWnd, &ps);
+   	break;
+
+       case WM_COMMAND:
+          printf("WM_COMMAND\n");
+          NOTEPAD_MenuCommand(wParam);
+          break;
+
+       case WM_DESTROY:
+          printf("WM_DESTROY\n");
+          PostQuitMessage (0);
+          break;
+
+       default:
+          return DefWindowProc (hWnd, msg, wParam, lParam);
+    }
+    return 0l;
+}
+
+
+
+/***********************************************************************
+ *
+ *           WinMain
+ */
+
+void DumpGlobals(void) {
+
+    printf("DumpGlobals()");
+    printf(" Globals.lpszIniFile: %s\n", Globals.lpszIniFile); 
+    printf(" Globals.lpszIcoFile: %s\n", Globals.lpszIcoFile);
+    printf("Globals.lpszLanguage: %s\n", Globals.lpszLanguage);
+    printf("   Globals.hInstance: %i\n", Globals.hInstance);
+    printf("   Globals.hMainMenu: %i\n", Globals.hMainMenu);
+    
+}
+ 
+int PASCAL WinMain (HANDLE hInstance, HANDLE prev, LPSTR cmdline, int show)
+{
+    MSG      msg;
+    WNDCLASS class;
+    char className[] = "NPClass";  /* To make sure className >= 0x10000 */
+    char winName[]   = "Notepad";
+
+    printf("WinMain()\n");
+    
+    /* Setup Globals */
+
+    Globals.lpszIniFile   = "notepad.ini";
+    Globals.lpszIcoFile   = "notepad.ico";
+    Globals.lpszLanguage  = "En";
+    Globals.hInstance     = hInstance;
+    Globals.hMainMenu     = LoadMenu(Globals.hInstance, STRING_MENU_Xx);
+    Globals.hFileMenu     = GetSubMenu(Globals.hMainMenu, 0);
+    Globals.hEditMenu     = GetSubMenu(Globals.hMainMenu, 1);
+    Globals.hSearchMenu   = GetSubMenu(Globals.hMainMenu, 2);
+    Globals.hLanguageMenu = GetSubMenu(Globals.hMainMenu, 3);
+    Globals.hHelpMenu     = GetSubMenu(Globals.hMainMenu, 4);
+    Globals.hMainIcon     = ExtractIcon(Globals.hInstance, 
+                                        Globals.lpszIcoFile, 0);
+    if (!Globals.hMainIcon) Globals.hMainIcon = 
+                                  LoadIcon(0, MAKEINTRESOURCE(DEFAULTICON));
+    
+    DumpGlobals();				  
+				  
+    if (!prev){
+	class.style = CS_HREDRAW | CS_VREDRAW;
+	class.lpfnWndProc = NOTEPAD_WndProc;
+	class.cbClsExtra = 0;
+	class.cbWndExtra = 0;
+	class.hInstance  = Globals.hInstance;
+	class.hIcon      = LoadIcon (0, IDI_APPLICATION);
+	class.hCursor    = LoadCursor (0, IDC_ARROW);
+	class.hbrBackground = GetStockObject (WHITE_BRUSH);
+	class.lpszMenuName = "bla\0";
+	class.lpszClassName = (SEGPTR)className;
+    }
+    if (!RegisterClass (&class))
+	return FALSE;
+
+    Globals.hMainWnd = CreateWindow (className, winName, WS_OVERLAPPEDWINDOW,
+			CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 
+			LoadMenu(Globals.hInstance, STRING_MENU_Xx),
+			Globals.hInstance, 0);
+
+    SetMenu(Globals.hMainWnd, Globals.hMainMenu);		
+			
+    ShowWindow (Globals.hMainWnd, show);
+    UpdateWindow (Globals.hMainWnd);
+
+    while (GetMessage (&msg, 0, 0, 0)) {
+        TranslateMessage (&msg);
+        DispatchMessage (&msg);
+    }
+    return 0;
+}
+
+
+
+
+/* Local Variables:    */
+/* c-file-style: "GNU" */
+/* End:                */
diff --git a/programs/notepad/main.h b/programs/notepad/main.h
new file mode 100644
index 0000000..3c701b5
--- /dev/null
+++ b/programs/notepad/main.h
@@ -0,0 +1,99 @@
+/*
+ * Notepad (notepad.h)
+ *
+ * Copyright 1997 Marcel Baur <mbaur@g26.ethz.ch>
+ */
+
+#define MAX_STRING_LEN      255
+#define MAX_PATHNAME_LEN    1024
+#define MAX_LANGUAGE_NUMBER (NP_LAST_LANGUAGE - NP_FIRST_LANGUAGE)
+
+#define HELPFILE "notepad.hlp"
+#define DEFAULTICON OIC_WINEICON
+
+/* hide the following from winerc */
+#ifndef RC_INVOKED
+
+typedef struct
+{
+  HANDLE  hInstance;
+  HWND    hMainWnd;
+  HICON   hMainIcon;
+  HICON   hDefaultIcon;
+  HMENU   hMainMenu;
+  HMENU   hFileMenu;
+  HMENU   hEditMenu;
+  HMENU   hSearchMenu;
+  HMENU   hLanguageMenu;
+  HMENU   hHelpMenu;
+  LPCSTR  lpszIniFile;
+  LPCSTR  lpszIcoFile;
+  LPCSTR  lpszLanguage;
+  UINT    wStringTableOffset;
+} NOTEPAD_GLOBALS;
+
+extern NOTEPAD_GLOBALS Globals;
+
+/* function prototypes */
+
+/* class names */
+
+/* resource names */
+// extern CHAR[] STRING_MENU_Xx;
+
+   #define STRINGID(id) (0x##id + Globals.wStringTableOffset)
+   
+#else  /* RC_INVOKED */
+
+   #define STRINGID(id) id
+   
+#endif
+
+/* string table index */
+#define IDS_LANGUAGE_ID STRINGID(00)
+
+/* main menu */
+
+#define NP_FILE_NEW              100
+#define NP_FILE_OPEN             101
+#define NP_FILE_SAVE             102
+#define NP_FILE_SAVEAS           103
+#define NP_FILE_PRINT            104
+#define NP_FILE_PAGESETUP        105
+#define NP_FILE_PRINTSETUP       106
+#define NP_FILE_EXIT             107
+
+#define NP_EDIT_UNDO             200
+#define NP_EDIT_CUT              201
+#define NP_EDIT_COPY             202
+#define NP_EDIT_PASTE            203
+#define NP_EDIT_DELETE           204
+#define NP_EDIT_SELECTALL        205
+#define NP_EDIT_TIMEDATE         206
+#define NP_EDIT_WRAP             207
+
+#define NP_SEARCH_SEARCH         300
+#define NP_SEARCH_NEXT           301
+
+#define NP_FIRST_LANGUAGE        400
+#define NP_LAST_LANGUAGE         499
+
+#define NP_HELP_CONTENTS         500
+#define NP_HELP_SEARCH           501
+#define NP_HELP_ON_HELP          502
+#define NP_HELP_LICENSE          503
+#define NP_HELP_NO_WARRANTY      504
+#define NP_HELP_ABOUT_WINE       505
+
+
+/* Dialog `Page Setup' */
+
+#define NP_PAGESETUP_LEFT       1000
+#define NP_PAGESETUP_RIGHT      1001
+#define NP_PAGESETUP_TOP        1002
+#define NP_PAGESETUP_BOTTOM     1003
+
+
+/* Local Variables:    */
+/* c-file-style: "GNU" */
+/* End:                */
diff --git a/programs/notepad/notepad.rc b/programs/notepad/notepad.rc
index 0079af5..c3d4748 100644
--- a/programs/notepad/notepad.rc
+++ b/programs/notepad/notepad.rc
@@ -4,22 +4,25 @@
  * Copyright 1997 Marcel Baur <mbaur@g26.ethz.ch>
  */
 
-#define CONCAT(a, b) a##b
+#include "main.h"
+ 
+#define CONCAT(a, b) CONCAT1(a, b)
+#define CONCAT1(a, b) a##b
 
 /* Main Menu */
 
 CONCAT(MENU_, LANGUAGE_ID) MENU
 {
  POPUP MENU_FILE {
-   MENUITEM MENU_FILE_NEW,              NP_NEW 
-   MENUITEM MENU_FILE_OPEN,             NP_OPEN
-   MENUITEM MENU_FILE_SAVE,             NP_SAVE
-   MENUITEM MENU_FILE_SAVEAS,           NP_SAVEAS
-   MENUITEM MENU_FILE_PRINT,            NP_PRINT
-   MENUITEM MENU_FILE_PAGESETUP,        NP_PAGESETUP
-   MENUITEM MENU_FILE_PRINTSETUP,       NP_PRINTSETUP
+   MENUITEM MENU_FILE_NEW,              NP_FILE_NEW 
+   MENUITEM MENU_FILE_OPEN,             NP_FILE_OPEN
+   MENUITEM MENU_FILE_SAVE,             NP_FILE_SAVE
+   MENUITEM MENU_FILE_SAVEAS,           NP_FILE_SAVEAS
+   MENUITEM MENU_FILE_PRINT,            NP_FILE_PRINT
+   MENUITEM MENU_FILE_PAGESETUP,        NP_FILE_PAGESETUP
+   MENUITEM MENU_FILE_PRINTSETUP,       NP_FILE_PRINTSETUP
    MENUITEM SEPARATOR   
-   MENUITEM MENU_FILE_EXIT,             NP_EXIT
+   MENUITEM MENU_FILE_EXIT,             NP_FILE_EXIT
  }
  POPUP MENU_EDIT {
    MENUITEM MENU_EDIT_UNDO,             NP_EDIT_UNDO
@@ -43,16 +46,15 @@
    MENUITEM SEPARATOR
  }
  POPUP MENU_HELP {
-   MENUITEM MENU_HELP_CONTENTS,         PM_CONTENTS
-   MENUITEM MENU_HELP_SEARCH,           PM_SEARCH
-   MENUITEM MENU_HELP_HELP_ON_HELP,     PM_HELPONHELP
+   MENUITEM MENU_HELP_CONTENTS,         NP_HELP_CONTENTS
+   MENUITEM MENU_HELP_SEARCH,           NP_HELP_SEARCH
+   MENUITEM MENU_HELP_HELP_ON_HELP,     NP_HELP_ON_HELP
    MENUITEM SEPARATOR
 
  POPUP MENU_INFO {
-   MENUITEM MENU_INFO_LICENSE,        PM_LICENSE
-   MENUITEM MENU_INFO_NO_WARRANTY,    PM_NO_WARRANTY
-   MENUITEM MENU_INFO_ABOUT_WINE,     PM_ABOUT_WINE
-  }
-}
+   MENUITEM MENU_INFO_LICENSE,          NP_HELP_LICENSE
+   MENUITEM MENU_INFO_NO_WARRANTY,      NP_HELP_NO_WARRANTY
+   MENUITEM MENU_INFO_ABOUT_WINE,       NP_HELP_ABOUT_WINE
+ }
 }
 
diff --git a/programs/progman/Makefile.in b/programs/progman/Makefile.in
index 39e72fd..222f96c 100644
--- a/programs/progman/Makefile.in
+++ b/programs/progman/Makefile.in
@@ -5,7 +5,7 @@
 VPATH     = @srcdir@
 MODULE    = none
 PROGRAMS  = progman
-ALL_LIBS  = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LDLIBS)
+ALL_LIBS  = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LIBS)
 RCFLAGS   = -w32 -h
 
 LANGUAGES   = En Da De Fr Fi Ko Hu It Va
diff --git a/programs/progman/Va.rc b/programs/progman/Va.rc
index 3d5963c..b1a8d0b 100644
--- a/programs/progman/Va.rc
+++ b/programs/progman/Va.rc
@@ -3,12 +3,12 @@
  *
  * Copyright 1996 Ulrich Schmid
  *
- * Rumantsch Ladin (Vallader) added by mbaur@g26.ethz.ch
+ * Rumantsch Ladin (Vallader) added by Marcel Baur <mbaur@g26.ethz.ch>
  *
  */
 
-#define LANGUAGE_ID                  Rl
-#define LANGUAGE_NUMBER              2
+#define LANGUAGE_ID                  Va
+#define LANGUAGE_NUMBER              C
 #define LANGUAGE_MENU_ITEM           "&Vallader"
 
 /* Menu */
diff --git a/programs/progman/license.c b/programs/progman/license.c
index c73dc26..b781b65 100644
--- a/programs/progman/license.c
+++ b/programs/progman/license.c
@@ -4,13 +4,21 @@
 static LICENSE* SelectLanguage(LPCSTR Language)
 {
 #if 0
-  if (!lstrcmp(Language, "Da")) return(&WineLicense_Cz);
+  if (!lstrcmp(Language, "Cz")) return(&WineLicense_Cz);
   if (!lstrcmp(Language, "Da")) return(&WineLicense_Da);
   if (!lstrcmp(Language, "De")) return(&WineLicense_De);
+  if (!lstrcmp(Language, "En")) return(&WineLicense_En);
+  if (!lstrcmp(Language, "Eo")) return(&WineLicense_Eo);
   if (!lstrcmp(Language, "Es")) return(&WineLicense_Es);
   if (!lstrcmp(Language, "Fi")) return(&WineLicense_Fi);
   if (!lstrcmp(Language, "Fr")) return(&WineLicense_Fr);
+  if (!lstrcmp(Language, "Hu")) return(&WineLicense_Hu);
+  if (!lstrcmp(Language, "It")) return(&WineLicense_It);
+  if (!lstrcmp(Language, "Ko")) return(&WineLicense_Ko);
   if (!lstrcmp(Language, "No")) return(&WineLicense_No);
+  if (!lstrcmp(Language, "Pl")) return(&WineLicense_Pl);
+  if (!lstrcmp(Language, "Po")) return(&WineLicense_Po);
+  if (!lstrcmp(Language, "Va")) return(&WineLicense_Va);
 #endif
   return(&WineLicense_En);
 }
diff --git a/programs/progman/license.h b/programs/progman/license.h
index 97fa9ba..112e38f 100644
--- a/programs/progman/license.h
+++ b/programs/progman/license.h
@@ -7,5 +7,18 @@
   LPCSTR Warranty, WarrantyCaption;
 } LICENSE;
 
-extern LICENSE WineLicense_Cz, WineLicense_Da, WineLicense_De, WineLicense_En;
-extern LICENSE WineLicense_Es, WineLicense_Fi, WineLicense_Fr, WineLicense_No;
+extern LICENSE WineLicense_Cz;
+extern LICENSE WineLicense_Da;
+extern LICENSE WineLicense_De;
+extern LICENSE WineLicense_En;
+extern LICENSE WineLicense_Eo;
+extern LICENSE WineLicense_Es;
+extern LICENSE WineLicense_Fi;
+extern LICENSE WineLicense_Fr;
+extern LICENSE WineLicense_Hu;
+extern LICENSE WineLicense_It;
+extern LICENSE WineLicense_Ko;
+extern LICENSE WineLicense_No;
+extern LICENSE WineLicense_Pl;
+extern LICENSE WineLicense_Po;
+extern LICENSE WineLicense_Va;
diff --git a/programs/winhelp/Makefile.in b/programs/winhelp/Makefile.in
index 612a362..dbe0daf 100644
--- a/programs/winhelp/Makefile.in
+++ b/programs/winhelp/Makefile.in
@@ -5,7 +5,7 @@
 VPATH     = @srcdir@
 MODULE    = none
 PROGRAMS  = winhelp hlp2sgml
-ALL_LIBS  = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LDLIBS)
+ALL_LIBS  = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LIBS)
 RCFLAGS   = -w32 -h
 
 LANGUAGES   = En Da De Fr Fi Ko Hu It Va
@@ -25,7 +25,7 @@
 
 C_SRCS = $(MOSTSRCS) $(STRINGSRCS)
 
-MOSTOBJS = $(MOSTSRCS:.c=.o)
+MOSTOBJS = $(MOSTSRCS:.c=.o) $(EXTRA_OBJS)
 STRINGOBJS = $(STRINGSRCS:.c=.o) $(RC_SRCS:.rc=.o)
 
 all: check_winerc $(PROGRAMS)
diff --git a/programs/winver/Makefile.in b/programs/winver/Makefile.in
index 208ca04..a44ca84 100644
--- a/programs/winver/Makefile.in
+++ b/programs/winver/Makefile.in
@@ -5,7 +5,7 @@
 VPATH     = @srcdir@
 MODULE    = none
 PROGRAMS  = winver
-ALL_LIBS  = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LDLIBS)
+ALL_LIBS  = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LIBS)
 RCFLAGS   = -w32 -h
 
 C_SRCS = winver.c
diff --git a/rc/winerc.c b/rc/winerc.c
index 058343b..4a9fa3f 100644
--- a/rc/winerc.c
+++ b/rc/winerc.c
@@ -97,6 +97,12 @@
 		ret=yyparse();
 	if (header) fclose(header);
 	fclose(code);
+        if (ret) /* There was an error */
+        {
+            if (header) unlink( output_name );
+            output_name[strlen(output_name)-1] = 'c';
+            unlink( output_name );
+        }
 	return ret;
 }
 
diff --git a/relay32/Makefile.in b/relay32/Makefile.in
index 74603e6..39880ce 100644
--- a/relay32/Makefile.in
+++ b/relay32/Makefile.in
@@ -11,6 +11,8 @@
 	comdlg32.spec \
 	crtdll.spec \
 	dciman32.spec \
+	ddraw.spec \
+	dsound.spec \
 	gdi32.spec \
 	kernel32.spec \
 	lz32.spec \
diff --git a/relay32/builtin32.c b/relay32/builtin32.c
index 8bdf3eb..764acad 100644
--- a/relay32/builtin32.c
+++ b/relay32/builtin32.c
@@ -44,6 +44,8 @@
 extern const BUILTIN32_DESCRIPTOR COMDLG32_Descriptor;
 extern const BUILTIN32_DESCRIPTOR CRTDLL_Descriptor;
 extern const BUILTIN32_DESCRIPTOR DCIMAN32_Descriptor;
+extern const BUILTIN32_DESCRIPTOR DDRAW_Descriptor;
+extern const BUILTIN32_DESCRIPTOR DSOUND_Descriptor;
 extern const BUILTIN32_DESCRIPTOR GDI32_Descriptor;
 extern const BUILTIN32_DESCRIPTOR KERNEL32_Descriptor;
 extern const BUILTIN32_DESCRIPTOR LZ32_Descriptor;
@@ -70,6 +72,8 @@
     { &COMDLG32_Descriptor, NULL, TRUE  },
     { &CRTDLL_Descriptor,   NULL, TRUE  },
     { &DCIMAN32_Descriptor, NULL, TRUE  },
+    { &DDRAW_Descriptor,    NULL, TRUE  },
+    { &DSOUND_Descriptor,   NULL, TRUE  },
     { &GDI32_Descriptor,    NULL, TRUE  },
     { &KERNEL32_Descriptor, NULL, TRUE  },
     { &LZ32_Descriptor,     NULL, TRUE  },
@@ -377,3 +381,43 @@
     fprintf( stderr, "\n" );
     TASK_KillCurrentTask(1);
 }
+
+
+/***********************************************************************
+ *           BUILTIN32_EnableDLL
+ *
+ * Enable or disable a built-in DLL.
+ */
+int BUILTIN32_EnableDLL( const char *name, int len, int enable )
+{
+    int i;
+    BUILTIN32_DLL *dll;
+
+    for (i = 0, dll = BuiltinDLLs; dll->descr; dll++)
+    {
+        if (!lstrncmpi32A( name, dll->descr->name, len ))
+        {
+            dll->used = enable;
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *           BUILTIN32_PrintDLLs
+ *
+ * Print the list of built-in DLLs that can be disabled.
+ */
+void BUILTIN32_PrintDLLs(void)
+{
+    int i;
+    BUILTIN32_DLL *dll;
+
+    fprintf(stderr,"Available Win32 DLLs:\n");
+    for (i = 0, dll = BuiltinDLLs; dll->descr; dll++)
+        fprintf( stderr, "%-9s%c", dll->descr->name,
+                 ((++i) % 8) ? ' ' : '\n' );
+    fprintf(stderr,"\n");
+}
diff --git a/relay32/crtdll.spec b/relay32/crtdll.spec
index a41af77..d1bdd34 100644
--- a/relay32/crtdll.spec
+++ b/relay32/crtdll.spec
@@ -354,7 +354,7 @@
 350 cdecl calloc(long long) CRTDLL_calloc
 351 stub ceil
 352 stub clearerr
-353 cdecl clock() clock
+353 cdecl clock() CRTDLL_clock
 354 cdecl cos(double) cos
 355 cdecl cosh(double) cosh
 356 cdecl ctime(ptr) ctime
diff --git a/relay32/ddraw.spec b/relay32/ddraw.spec
new file mode 100644
index 0000000..151a1c3
--- /dev/null
+++ b/relay32/ddraw.spec
@@ -0,0 +1,28 @@
+name ddraw
+type win32
+
+   1  stub DDHAL32_VidMemAlloc
+   2  stub DDHAL32_VidMemFree
+   3  stub DDInternalLock
+   4  stub DDInternalUnlock
+   5  stdcall DSoundHelp(long long long) DSoundHelp
+   6  stdcall DirectDrawCreate(ptr ptr ptr) DirectDrawCreate
+   7  stub DirectDrawCreateClipper
+   8  stdcall DirectDrawEnumerateA(ptr ptr) DirectDrawEnumerate32A
+   9  stub DirectDrawEnumerateW
+  10  stub DllCanUnloadNow
+  11  stub DllGetClassObject
+  12  stub GetNextMipMap
+  13  stub GetSurfaceFromDC
+  14  stub HeapVidMemAllocAligned
+  15  stub InternalLock
+  16  stub InternalUnlock
+  17  stub LateAllocateSurfaceMem
+  18  stub VidMemAlloc
+  19  stub VidMemAmountFree
+  20  stub VidMemFini
+  21  stub VidMemFree
+  22  stub VidMemInit
+  23  stub VidMemLargestFree
+  24  stub thk1632_ThunkData32
+  25  stub thk3216_ThunkData32
diff --git a/relay32/dsound.spec b/relay32/dsound.spec
new file mode 100644
index 0000000..cfb19a7
--- /dev/null
+++ b/relay32/dsound.spec
@@ -0,0 +1,11 @@
+name dsound
+type win32
+
+0 stdcall DirectSoundCreate(ptr ptr ptr) DirectSoundCreate
+1 stdcall DirectSoundEnumerateA(ptr ptr) DirectSoundEnumerate32A
+2 stub DirectSoundEnumerateW
+3 stub DllCanUnloadNow
+4 stub DllGetClassObject
+5 stub DirectSoundCaptureCreate
+6 stub DirectSoundCaptureEnumerateA
+7 stub DirectSoundCaptureEnumerateW
diff --git a/relay32/gdi32.spec b/relay32/gdi32.spec
index e068279..fad209f 100644
--- a/relay32/gdi32.spec
+++ b/relay32/gdi32.spec
@@ -221,7 +221,7 @@
 214 stdcall GetROP2(long) GetROP232
 215 stub GetRandomRgn
 216 stdcall GetRasterizerCaps(ptr long) GetRasterizerCaps32
-217 stub GetRegionData
+217 stdcall GetRegionData(long long ptr) GetRegionData
 218 stdcall GetRelAbs(long) GetRelAbs32
 219 stdcall GetRgnBox(long ptr) GetRgnBox32
 220 stdcall GetStockObject(long) GetStockObject32
diff --git a/relay32/kernel32.spec b/relay32/kernel32.spec
index 7dde6b4..1d29cf2 100644
--- a/relay32/kernel32.spec
+++ b/relay32/kernel32.spec
@@ -173,7 +173,7 @@
 182 stub DefineDosDeviceA
 183 stub DefineDosDeviceW
 184 stdcall DeleteAtom(long) DeleteAtom32
-185 stdcall DeleteCriticalSection(ptr)	DeleteCriticalSection
+185 stdcall DeleteCriticalSection(ptr) DeleteCriticalSection
 186 stdcall DeleteFileA(str) DeleteFile32A
 187 stdcall DeleteFileW(wstr) DeleteFile32W
 188 stdcall DeviceIoControl(long long ptr long ptr long ptr ptr) DeviceIoControl
@@ -183,7 +183,7 @@
 192 stdcall DuplicateHandle(long long long ptr long long long) DuplicateHandle
 193 stub EndUpdateResourceA
 194 stub EndUpdateResourceW
-195 stdcall EnterCriticalSection(ptr)	EnterCriticalSection
+195 stdcall EnterCriticalSection(ptr) EnterCriticalSection
 196 stub EnumCalendarInfoA
 197 stub EnumCalendarInfoW
 198 stub EnumDateFormatsA
@@ -203,7 +203,7 @@
 212 stub EraseTape
 213 stdcall EscapeCommFunction(long long) EscapeCommFunction32
 214 stdcall ExitProcess(long) ExitProcess
-215 stub ExitThread
+215 stdcall ExitThread(long) ExitThread
 216 stdcall ExpandEnvironmentStringsA(str ptr long) ExpandEnvironmentStrings32A
 217 stdcall ExpandEnvironmentStringsW(wstr ptr long) ExpandEnvironmentStrings32W
 218 stub FT_Exit0
@@ -383,7 +383,7 @@
 392 stdcall GetShortPathNameW(wstr ptr long) GetShortPathName32W
 393 stdcall GetStartupInfoA(ptr) GetStartupInfo32A
 394 stdcall GetStartupInfoW(ptr) GetStartupInfo32W
-395 stdcall GetStdHandle(long)	GetStdHandle
+395 stdcall GetStdHandle(long) GetStdHandle
 396 stdcall GetStringTypeA(long long str long ptr) GetStringType32A
 397 stdcall GetStringTypeExA(long long str long ptr) GetStringTypeEx32A
 398 stdcall GetStringTypeExW(long long wstr long ptr) GetStringTypeEx32W
@@ -449,7 +449,7 @@
 458 stub Heap32Next
 459 stdcall HeapAlloc(long long long) HeapAlloc
 460 stdcall HeapCompact(long long) HeapCompact
-461 stdcall HeapCreate(long long long)	HeapCreate
+461 stdcall HeapCreate(long long long) HeapCreate
 462 stdcall HeapDestroy(long) HeapDestroy
 463 stdcall HeapFree(long long ptr) HeapFree
 464 stdcall HeapLock(long) HeapLock
@@ -482,7 +482,7 @@
 491 stub K32Thk1632Prolog
 492 stdcall LCMapStringA(long long str long ptr long) LCMapString32A
 493 stdcall LCMapStringW(long long wstr long ptr long) LCMapString32W
-494 stdcall LeaveCriticalSection(ptr)	LeaveCriticalSection
+494 stdcall LeaveCriticalSection(ptr) LeaveCriticalSection
 495 stdcall LoadLibraryA(str) LoadLibrary32A
 496 stdcall LoadLibraryExA(str long long) LoadLibraryEx32A
 497 stub LoadLibraryExW
@@ -531,7 +531,7 @@
 540 stdcall OpenFileMappingW(long long wstr) OpenFileMapping32W
 541 stdcall OpenMutexA(long long str) OpenMutex32A
 542 stdcall OpenMutexW(long long wstr) OpenMutex32W
-543 stdcall OpenProcess(long long long) OpenProcess32
+543 stdcall OpenProcess(long long long) OpenProcess
 544 stub OpenProfileUserMapping
 545 stdcall OpenSemaphoreA(long long str) OpenSemaphore32A
 546 stdcall OpenSemaphoreW(long long wstr) OpenSemaphore32W
@@ -545,7 +545,7 @@
 554 stub PrepareTape
 555 stub Process32First
 556 stub Process32Next
-557 stub PulseEvent
+557 stdcall PulseEvent(long) PulseEvent
 558 stdcall PurgeComm(long long) PurgeComm
 559 register QT_Thunk() QT_Thunk
 560 stdcall QueryDosDeviceA(str ptr long) QueryDosDevice32A
@@ -568,7 +568,7 @@
 577 stdcall ReadFile(long ptr long ptr ptr) ReadFile
 578 stdcall ReadFileEx(long ptr long ptr ptr) ReadFileEx
 579 stdcall ReadProcessMemory(long ptr ptr long ptr) ReadProcessMemory
-580 stub RegisterServiceProcess
+580 stdcall RegisterServiceProcess(long long) RegisterServiceProcess
 581 stdcall ReinitializeCriticalSection(ptr) ReinitializeCriticalSection
 582 stdcall ReleaseMutex(long) ReleaseMutex
 583 stdcall ReleaseSemaphore(long long ptr) ReleaseSemaphore
@@ -657,7 +657,7 @@
 666 stub SetSystemTimeAdjustment
 667 stub SetTapeParameters
 668 stub SetTapePosition
-669 stdcall SetThreadAffinityMask(long long)	SetThreadAffinityMask
+669 stdcall SetThreadAffinityMask(long long) SetThreadAffinityMask
 670 stub SetThreadContext
 671 stub SetThreadLocale
 672 stdcall SetThreadPriority(long long) SetThreadPriority
@@ -677,7 +677,7 @@
 686 stub Thread32First
 687 stub Thread32Next
 688 stdcall ThunkConnect32(ptr str str str ptr ptr) ThunkConnect32
-689 stdcall TlsAlloc()	TlsAlloc
+689 stdcall TlsAlloc() TlsAlloc
 690 stub TlsAllocInternal
 691 stdcall TlsFree(long) TlsFree
 692 stub TlsFreeInternal
@@ -710,12 +710,12 @@
 719 stub WaitCommEvent
 720 stub WaitForDebugEvent
 721 stdcall WaitForMultipleObjects(long ptr long long) WaitForMultipleObjects
-722 stub WaitForMultipleObjectsEx
+722 stdcall WaitForMultipleObjectsEx(long ptr long long long) WaitForMultipleObjectsEx
 723 stdcall WaitForSingleObject(long long) WaitForSingleObject
 724 stdcall WaitForSingleObjectEx(long long long) WaitForSingleObjectEx
 725 stub WaitNamedPipeA
 726 stub WaitNamedPipeW
-727 stdcall WideCharToMultiByte(long long wstr long ptr long ptr ptr)	WideCharToMultiByte
+727 stdcall WideCharToMultiByte(long long wstr long ptr long ptr ptr) WideCharToMultiByte
 728 stdcall WinExec(str long) WinExec32
 729 stdcall WriteConsoleA(long ptr long ptr ptr) WriteConsole32A
 730 stub WriteConsoleInputA
@@ -886,7 +886,7 @@
 895 stub SignalObjectAndWait
 896 stub SwitchToFiber
 897 stub SwitchToThread
-898 stub TryEnterCriticalSection
+898 stdcall TryEnterCriticalSection(ptr) TryEnterCriticalSection
 899 stub VirtualAllocEx
 900 stub VirtualFreeEx
 901 stub WriteFileGather
diff --git a/relay32/ntdll.spec b/relay32/ntdll.spec
index 4295ecc..531ef80 100644
--- a/relay32/ntdll.spec
+++ b/relay32/ntdll.spec
@@ -89,7 +89,7 @@
 086 stub NtCreateThread
 087 stub NtCreateTimer
 088 stub NtCreateToken
-089 register NtCurrentTeb() NtCurrentTeb
+089 stdcall NtCurrentTeb() NtCurrentTeb
 090 stub NtDelayExecution
 091 stub NtDeleteFile
 092 stub NtDeleteKey
@@ -327,7 +327,7 @@
 324 stub RtlDecompressFragment
 325 stub RtlDelete
 326 stub RtlDeleteAce
-327 stub RtlDeleteCriticalSection
+327 stdcall RtlDeleteCriticalSection(ptr) DeleteCriticalSection
 328 stub RtlDeleteElementGenericTable
 329 stub RtlDeleteRegistryValue
 330 stub RtlDeleteResource
@@ -971,3 +971,4 @@
 966 stub RtlIsValidHandle
 967 stub RtlLookupAtomInAtomTable
 968 stub RtlQueryAtomInAtomTable
+969 stdcall RtlTryEnterCriticalSection(ptr) TryEnterCriticalSection
diff --git a/relay32/relay386.c b/relay32/relay386.c
index 1531e4a..752a582 100644
--- a/relay32/relay386.c
+++ b/relay32/relay386.c
@@ -10,6 +10,7 @@
 #include "winnt.h"
 #include "windows.h"
 #include "builtin32.h"
+#include "selectors.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -30,6 +31,7 @@
     char buffer[80];
     FARPROC32 func;
     unsigned int mask, typemask;
+    WORD fs;
 
     int *args = &ret_addr;
     /* Relay addr is the return address for this function */
@@ -56,7 +58,8 @@
 	}
         else printf( "%08x", args[i] );
     }
-    printf( ") ret=%08x\n", ret_addr );
+    GET_FS( fs );
+    printf( ") ret=%08x fs=%04x\n", ret_addr, fs );
     if (*relay_addr == 0xc3) /* cdecl */
     {
         LRESULT (*cfunc)() = (LRESULT(*)())func;
@@ -138,7 +141,8 @@
             assert(FALSE);
         }
     }
-    printf( "Ret  %s() retval=%08x ret=%08x\n", buffer, ret, ret_addr );
+    printf( "Ret  %s() retval=%08x ret=%08x fs=%04x\n",
+            buffer, ret, ret_addr, fs );
     return ret;
 }
 
diff --git a/relay32/user32.spec b/relay32/user32.spec
index 5c099ba..06ce2b1 100644
--- a/relay32/user32.spec
+++ b/relay32/user32.spec
@@ -462,7 +462,7 @@
 457 stdcall SendMessageTimeoutA(long long long long ptr ptr) SendMessageTimeout32A
 458 stdcall SendMessageTimeoutW(long long long long ptr ptr) SendMessageTimeout32W
 459 stdcall SendMessageW(long long long long) SendMessage32W
-460 stub SendNotifyMessageA
+460 stdcall SendNotifyMessageA(long long long long) SendNotifyMessage32A
 461 stub SendNotifyMessageW
 462 stub ServerSetFunctionPointers
 463 stdcall SetActiveWindow(long) SetActiveWindow32
diff --git a/relay32/winmm.spec b/relay32/winmm.spec
index de1a4e5..a421088 100644
--- a/relay32/winmm.spec
+++ b/relay32/winmm.spec
@@ -31,7 +31,7 @@
  28 stdcall joyGetDevCapsW(long ptr long) joyGetDevCaps32W
  29 stdcall joyGetNumDevs() joyGetNumDevs32
  30 stdcall joyGetPos(long ptr) joyGetPos32
- 31 stub joyGetPosEx
+ 31 stdcall joyGetPosEx(long ptr) joyGetPosEx
  32 stdcall joyGetThreshold(long ptr) joyGetThreshold32
  33 stub joyReleaseCapture
  34 stub joySetCapture
diff --git a/relay32/wow32.spec b/relay32/wow32.spec
index 2f5b548..4a37728 100644
--- a/relay32/wow32.spec
+++ b/relay32/wow32.spec
@@ -1,7 +1,7 @@
 name	wow32
 type	win32
 
-#  1
+  1 stub    WOW_1
   2 stub    WOWCallback16
   3 stub    WOWCallback16Ex
   4 stub    WOWDirectedYield16
diff --git a/scheduler/Makefile.in b/scheduler/Makefile.in
index 75ff080..632f046 100644
--- a/scheduler/Makefile.in
+++ b/scheduler/Makefile.in
@@ -6,7 +6,13 @@
 MODULE    = scheduler
 
 C_SRCS = \
+	critsection.c \
+	event.c \
+	k32obj.c \
+	mutex.c \
 	process.c \
+	semaphore.c \
+	synchro.c \
 	thread.c
 
 all: $(MODULE).o
diff --git a/scheduler/critsection.c b/scheduler/critsection.c
new file mode 100644
index 0000000..7f5c5b9
--- /dev/null
+++ b/scheduler/critsection.c
@@ -0,0 +1,286 @@
+/*
+ * Win32 critical sections
+ *
+ * Copyright 1998 Alexandre Julliard
+ */
+
+/* Note: critical sections are not implemented exactly the same way
+ * than under NT (LockSemaphore should be a real semaphore handle).
+ * But since they are even more different under Win95, it probably
+ * doesn't matter... 
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/sem.h>
+#include "windows.h"
+#include "winerror.h"
+#include "winbase.h"
+#include "heap.h"
+#include "k32obj.h"
+#include "thread.h"
+
+typedef struct
+{
+    K32OBJ        header;
+    THREAD_QUEUE  wait_queue;
+    BOOL32        signaled;
+} CRIT_SECTION;
+
+
+static BOOL32 CRIT_SECTION_Signaled( K32OBJ *obj, DWORD thread_id );
+static void CRIT_SECTION_Satisfied( K32OBJ *obj, DWORD thread_id );
+static void CRIT_SECTION_AddWait( K32OBJ *obj, DWORD thread_id );
+static void CRIT_SECTION_RemoveWait( K32OBJ *obj, DWORD thread_id );
+static void CRIT_SECTION_Destroy( K32OBJ *obj );
+
+const K32OBJ_OPS CRITICAL_SECTION_Ops =
+{
+    CRIT_SECTION_Signaled,     /* signaled */
+    CRIT_SECTION_Satisfied,    /* satisfied */
+    CRIT_SECTION_AddWait,      /* add_wait */
+    CRIT_SECTION_RemoveWait,   /* remove_wait */
+    CRIT_SECTION_Destroy       /* destroy */
+};
+
+/***********************************************************************
+ *           InitializeCriticalSection   (KERNEL32.472) (NTDLL.406)
+ */
+void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
+{
+    CRIT_SECTION *obj;
+
+    crit->LockCount      = -1;
+    crit->RecursionCount = 0;
+    crit->OwningThread   = 0;
+    crit->LockSemaphore  = 0;
+    if (SystemHeap)
+    {
+        if (!(obj = (CRIT_SECTION *)HeapAlloc( SystemHeap, 0, sizeof(*obj) )))
+            return;  /* No way to return an error... */
+        obj->header.type     = K32OBJ_CRITICAL_SECTION;
+        obj->header.refcount = 1;
+        obj->wait_queue      = NULL;
+        obj->signaled        = FALSE;
+        crit->LockSemaphore  = (HANDLE32)obj;
+        crit->Reserved       = (DWORD)-1;
+    }
+    else
+    {
+        union semun val;
+        crit->Reserved = (DWORD)semget( IPC_PRIVATE, 1, IPC_CREAT | 0777 );
+        if (crit->Reserved == (DWORD)-1)
+        {
+            perror( "semget" );
+            return;
+        }
+        val.val = 0;
+        semctl( (int)crit->Reserved, 0, SETVAL, val );
+    }
+}
+
+
+/***********************************************************************
+ *           DeleteCriticalSection   (KERNEL32.185) (NTDLL.327)
+ */
+void WINAPI DeleteCriticalSection( CRITICAL_SECTION *crit )
+{
+    CRIT_SECTION *obj = (CRIT_SECTION *)crit->LockSemaphore;
+
+    if (obj)
+    {
+        if (crit->RecursionCount)  /* Should not happen */
+            fprintf( stderr, "Deleting owned critical section (%p)\n", crit );
+        crit->LockCount      = -1;
+        crit->RecursionCount = 0;
+        crit->OwningThread   = 0;
+        crit->LockSemaphore  = 0;
+        K32OBJ_DecCount( &obj->header );
+    }
+    else if (crit->Reserved != (DWORD)-1)
+    {
+        semctl( (int)crit->Reserved, 0, IPC_RMID, (union semun)0 );
+    }
+}
+
+
+/***********************************************************************
+ *           EnterCriticalSection   (KERNEL32.195) (NTDLL.344)
+ */
+void WINAPI EnterCriticalSection( CRITICAL_SECTION *crit )
+{
+    if (InterlockedIncrement( &crit->LockCount ))
+    {
+        if (crit->OwningThread == GetCurrentThreadId())
+        {
+            crit->RecursionCount++;
+            return;
+        }
+        /* Now wait for it */
+        if (crit->LockSemaphore)
+        {
+            WAIT_STRUCT *wait = &THREAD_Current()->wait_struct;
+            SYSTEM_LOCK();
+            wait->count    = 1;
+            wait->signaled = WAIT_FAILED;
+            wait->wait_all = FALSE;
+            wait->objs[0] = (K32OBJ *)crit->LockSemaphore;
+            K32OBJ_IncCount( wait->objs[0] );
+            SYNC_WaitForCondition( wait, INFINITE32 );
+            K32OBJ_DecCount( wait->objs[0] );
+            SYSTEM_UNLOCK();
+        }
+        else if (crit->Reserved != (DWORD)-1)
+        {
+            int ret;
+            struct sembuf sop;
+            sop.sem_num = 0;
+            sop.sem_op  = -1;
+            sop.sem_flg = SEM_UNDO;
+            do
+            {
+                ret = semop( (int)crit->Reserved, &sop, 1 );
+            } while ((ret == -1) && (errno == EINTR));
+        }
+        else
+        {
+            fprintf( stderr, "Uninitialized critical section (%p)\n", crit );
+            return;
+        }
+    }
+    crit->OwningThread   = GetCurrentThreadId();
+    crit->RecursionCount = 1;
+}
+
+
+/***********************************************************************
+ *           TryEnterCriticalSection   (KERNEL32.898) (NTDLL.969)
+ */
+BOOL32 WINAPI TryEnterCriticalSection( CRITICAL_SECTION *crit )
+{
+    if (InterlockedIncrement( &crit->LockCount ))
+    {
+        if (crit->OwningThread == GetCurrentThreadId())
+        {
+            crit->RecursionCount++;
+            return TRUE;
+        }
+        /* FIXME: this doesn't work */
+        InterlockedDecrement( &crit->LockCount );
+        return FALSE;
+    }
+    crit->OwningThread   = GetCurrentThreadId();
+    crit->RecursionCount = 1;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           LeaveCriticalSection   (KERNEL32.494) (NTDLL.426)
+ */
+void WINAPI LeaveCriticalSection( CRITICAL_SECTION *crit )
+{
+    if (crit->OwningThread != GetCurrentThreadId()) return;
+       
+    if (--crit->RecursionCount)
+    {
+        InterlockedDecrement( &crit->LockCount );
+        return;
+    }
+    crit->OwningThread = 0;
+    if (InterlockedDecrement( &crit->LockCount ) >= 0)
+    {
+        /* Someone is waiting */
+        if (crit->LockSemaphore)
+        {
+            CRIT_SECTION *obj = (CRIT_SECTION *)crit->LockSemaphore;
+            SYSTEM_LOCK();
+            obj->signaled = TRUE;
+            SYNC_WakeUp( &obj->wait_queue, 1 );
+            SYSTEM_UNLOCK();
+        }
+        else if (crit->Reserved != (DWORD)-1)
+        {
+            struct sembuf sop;
+            sop.sem_num = 0;
+            sop.sem_op  = 1;
+            sop.sem_flg = SEM_UNDO;
+            semop( (int)crit->Reserved, &sop, 1 );
+        }
+    }
+}
+
+
+/***********************************************************************
+ *           MakeCriticalSectionGlobal   (KERNEL32.515)
+ */
+void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
+{
+    /* Nothing to do: a critical section is always global */
+}
+
+
+/***********************************************************************
+ *           CRIT_SECTION_Signaled
+ */
+static BOOL32 CRIT_SECTION_Signaled( K32OBJ *obj, DWORD thread_id )
+{
+    CRIT_SECTION *crit = (CRIT_SECTION *)obj;
+    assert( obj->type == K32OBJ_CRITICAL_SECTION );
+    return crit->signaled;
+}
+
+
+/***********************************************************************
+ *           CRIT_SECTION_Satisfied
+ *
+ * Wait on this object has been satisfied.
+ */
+static void CRIT_SECTION_Satisfied( K32OBJ *obj, DWORD thread_id )
+{
+    CRIT_SECTION *crit = (CRIT_SECTION *)obj;
+    assert( obj->type == K32OBJ_CRITICAL_SECTION );
+    /* Only one thread is allowed to wake up */
+    crit->signaled = FALSE;
+}
+
+
+/***********************************************************************
+ *           CRIT_SECTION_AddWait
+ *
+ * Add thread to object wait queue.
+ */
+static void CRIT_SECTION_AddWait( K32OBJ *obj, DWORD thread_id )
+{
+    CRIT_SECTION *crit = (CRIT_SECTION *)obj;
+    assert( obj->type == K32OBJ_CRITICAL_SECTION );
+    THREAD_AddQueue( &crit->wait_queue, THREAD_ID_TO_THDB(thread_id) );
+}
+
+
+/***********************************************************************
+ *           CRIT_SECTION_RemoveWait
+ *
+ * Remove current thread from object wait queue.
+ */
+static void CRIT_SECTION_RemoveWait( K32OBJ *obj, DWORD thread_id )
+{
+    CRIT_SECTION *crit = (CRIT_SECTION *)obj;
+    assert( obj->type == K32OBJ_CRITICAL_SECTION );
+    THREAD_RemoveQueue( &crit->wait_queue, THREAD_ID_TO_THDB(thread_id) );
+}
+
+
+/***********************************************************************
+ *           CRIT_SECTION_Destroy
+ */
+static void CRIT_SECTION_Destroy( K32OBJ *obj )
+{
+    CRIT_SECTION *crit = (CRIT_SECTION *)obj;
+    assert( obj->type == K32OBJ_CRITICAL_SECTION );
+    /* There cannot be any thread on the list since the ref count is 0 */
+    assert( crit->wait_queue == NULL );
+    obj->type = K32OBJ_UNKNOWN;
+    HeapFree( SystemHeap, 0, crit );
+}
diff --git a/scheduler/event.c b/scheduler/event.c
new file mode 100644
index 0000000..4eb5e0c
--- /dev/null
+++ b/scheduler/event.c
@@ -0,0 +1,268 @@
+/*
+ * Win32 events
+ *
+ * Copyright 1998 Alexandre Julliard
+ */
+
+#include <assert.h>
+#include "windows.h"
+#include "winerror.h"
+#include "k32obj.h"
+#include "process.h"
+#include "thread.h"
+#include "heap.h"
+
+typedef struct
+{
+    K32OBJ        header;
+    THREAD_QUEUE  wait_queue;
+    BOOL32        manual_reset;
+    BOOL32        signaled;
+} EVENT;
+
+static BOOL32 EVENT_Signaled( K32OBJ *obj, DWORD thread_id );
+static void EVENT_Satisfied( K32OBJ *obj, DWORD thread_id );
+static void EVENT_AddWait( K32OBJ *obj, DWORD thread_id );
+static void EVENT_RemoveWait( K32OBJ *obj, DWORD thread_id );
+static void EVENT_Destroy( K32OBJ *obj );
+
+const K32OBJ_OPS EVENT_Ops =
+{
+    EVENT_Signaled,     /* signaled */
+    EVENT_Satisfied,    /* satisfied */
+    EVENT_AddWait,      /* add_wait */
+    EVENT_RemoveWait,   /* remove_wait */
+    EVENT_Destroy       /* destroy */
+};
+
+
+/***********************************************************************
+ *           EVENT_Set
+ *
+ * Implementation of SetEvent. Used by ExitThread and ExitProcess.
+ */
+void EVENT_Set( K32OBJ *obj )
+{
+    EVENT *event = (EVENT *)obj;
+    assert( obj->type == K32OBJ_EVENT );
+    SYSTEM_LOCK();
+    event->signaled = TRUE;
+    SYNC_WakeUp( &event->wait_queue, event->manual_reset ? INFINITE32 : 1 );
+    SYSTEM_UNLOCK();
+}
+
+/***********************************************************************
+ *           EVENT_Create
+ *
+ * Partial implementation of CreateEvent.
+ * Used internally by processes and threads.
+ */
+K32OBJ *EVENT_Create( BOOL32 manual_reset, BOOL32 initial_state )
+{
+    EVENT *event;
+
+    SYSTEM_LOCK();
+    if ((event = HeapAlloc( SystemHeap, 0, sizeof(*event) )))
+    {
+        event->header.type     = K32OBJ_EVENT;
+        event->header.refcount = 1;
+        event->wait_queue      = NULL;
+        event->manual_reset    = manual_reset;
+        event->signaled        = initial_state;
+    }
+    SYSTEM_UNLOCK();
+    return event ? &event->header : NULL;
+}
+
+
+/***********************************************************************
+ *           CreateEvent32A    (KERNEL32.156)
+ */
+HANDLE32 WINAPI CreateEvent32A( SECURITY_ATTRIBUTES *sa, BOOL32 manual_reset,
+                                BOOL32 initial_state, LPCSTR name )
+{
+    HANDLE32 handle;
+    EVENT *event;
+
+    SYSTEM_LOCK();
+    event = (EVENT *)K32OBJ_Create( K32OBJ_EVENT, sizeof(*event),
+                                    name, &handle );
+    if (event)
+    {
+        /* Finish initializing it */
+        event->wait_queue   = NULL;
+        event->manual_reset = manual_reset;
+        event->signaled     = initial_state;
+        K32OBJ_DecCount( &event->header );
+    }
+    SYSTEM_UNLOCK();
+    return handle;
+}
+
+
+/***********************************************************************
+ *           CreateEvent32W    (KERNEL32.157)
+ */
+HANDLE32 WINAPI CreateEvent32W( SECURITY_ATTRIBUTES *sa, BOOL32 manual_reset,
+                                BOOL32 initial_state, LPCWSTR name )
+{
+    LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
+    HANDLE32 ret = CreateEvent32A( sa, manual_reset, initial_state, nameA );
+    if (nameA) HeapFree( GetProcessHeap(), 0, nameA );
+    return ret;
+}
+
+
+/***********************************************************************
+ *           OpenEvent32A    (KERNEL32.536)
+ */
+HANDLE32 WINAPI OpenEvent32A( DWORD access, BOOL32 inherit, LPCSTR name )
+{
+    HANDLE32 handle = 0;
+    K32OBJ *obj;
+    SYSTEM_LOCK();
+    if ((obj = K32OBJ_FindNameType( name, K32OBJ_EVENT )) != NULL)
+    {
+        handle = PROCESS_AllocHandle( obj, 0 );
+        K32OBJ_DecCount( obj );
+    }
+    SYSTEM_UNLOCK();
+    return handle;
+}
+
+
+/***********************************************************************
+ *           OpenEvent32W    (KERNEL32.537)
+ */
+HANDLE32 WINAPI OpenEvent32W( DWORD access, BOOL32 inherit, LPCWSTR name )
+{
+    LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
+    HANDLE32 ret = OpenEvent32A( access, inherit, nameA );
+    if (nameA) HeapFree( GetProcessHeap(), 0, nameA );
+    return ret;
+}
+
+
+/***********************************************************************
+ *           PulseEvent    (KERNEL32.557)
+ */
+BOOL32 WINAPI PulseEvent( HANDLE32 handle )
+{
+    EVENT *event;
+    SYSTEM_LOCK();
+    if (!(event = (EVENT *)PROCESS_GetObjPtr( handle, K32OBJ_EVENT )))
+    {
+        SYSTEM_UNLOCK();
+        return FALSE;
+    }
+    event->signaled = TRUE;
+    SYNC_WakeUp( &event->wait_queue, event->manual_reset ? INFINITE32 : 1 );
+    event->signaled = FALSE;
+    K32OBJ_DecCount( &event->header );
+    SYSTEM_UNLOCK();
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           SetEvent    (KERNEL32.644)
+ */
+BOOL32 WINAPI SetEvent( HANDLE32 handle )
+{
+    EVENT *event;
+    SYSTEM_LOCK();
+    if (!(event = (EVENT *)PROCESS_GetObjPtr( handle, K32OBJ_EVENT )))
+    {
+        SYSTEM_UNLOCK();
+        return FALSE;
+    }
+    event->signaled = TRUE;
+    SYNC_WakeUp( &event->wait_queue, event->manual_reset ? INFINITE32 : 1 );
+    K32OBJ_DecCount( &event->header );
+    SYSTEM_UNLOCK();
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           ResetEvent    (KERNEL32.586)
+ */
+BOOL32 WINAPI ResetEvent( HANDLE32 handle )
+{
+    EVENT *event;
+    SYSTEM_LOCK();
+    if (!(event = (EVENT *)PROCESS_GetObjPtr( handle, K32OBJ_EVENT )))
+    {
+        SYSTEM_UNLOCK();
+        return FALSE;
+    }
+    event->signaled = FALSE;
+    K32OBJ_DecCount( &event->header );
+    SYSTEM_UNLOCK();
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           EVENT_Signaled
+ */
+static BOOL32 EVENT_Signaled( K32OBJ *obj, DWORD thread_id )
+{
+    EVENT *event = (EVENT *)obj;
+    assert( obj->type == K32OBJ_EVENT );
+    return event->signaled;
+}
+
+
+/***********************************************************************
+ *           EVENT_Satisfied
+ *
+ * Wait on this object has been satisfied.
+ */
+static void EVENT_Satisfied( K32OBJ *obj, DWORD thread_id )
+{
+    EVENT *event = (EVENT *)obj;
+    assert( obj->type == K32OBJ_EVENT );
+    /* Reset if it's an auto-reset event */
+    if (!event->manual_reset) event->signaled = FALSE;
+}
+
+
+/***********************************************************************
+ *           EVENT_AddWait
+ *
+ * Add thread to object wait queue.
+ */
+static void EVENT_AddWait( K32OBJ *obj, DWORD thread_id )
+{
+    EVENT *event = (EVENT *)obj;
+    assert( obj->type == K32OBJ_EVENT );
+    THREAD_AddQueue( &event->wait_queue, THREAD_ID_TO_THDB(thread_id) );
+}
+
+
+/***********************************************************************
+ *           EVENT_RemoveWait
+ *
+ * Remove thread from object wait queue.
+ */
+static void EVENT_RemoveWait( K32OBJ *obj, DWORD thread_id )
+{
+    EVENT *event = (EVENT *)obj;
+    assert( obj->type == K32OBJ_EVENT );
+    THREAD_RemoveQueue( &event->wait_queue, THREAD_ID_TO_THDB(thread_id) );
+}
+
+
+/***********************************************************************
+ *           EVENT_Destroy
+ */
+static void EVENT_Destroy( K32OBJ *obj )
+{
+    EVENT *event = (EVENT *)obj;
+    assert( obj->type == K32OBJ_EVENT );
+    /* There cannot be any thread on the list since the ref count is 0 */
+    assert( event->wait_queue == NULL );
+    obj->type = K32OBJ_UNKNOWN;
+    HeapFree( SystemHeap, 0, event );
+}
diff --git a/scheduler/k32obj.c b/scheduler/k32obj.c
new file mode 100644
index 0000000..c2589ce
--- /dev/null
+++ b/scheduler/k32obj.c
@@ -0,0 +1,260 @@
+/*
+ * KERNEL32 objects
+ *
+ * Copyright 1996 Alexandre Julliard
+ */
+
+#include <assert.h>
+#include "winerror.h"
+#include "k32obj.h"
+#include "heap.h"
+#include "process.h"
+
+
+/* The declarations are here to avoid including a lot of unnecessary files */
+extern const K32OBJ_OPS SEMAPHORE_Ops;
+extern const K32OBJ_OPS EVENT_Ops;
+extern const K32OBJ_OPS MUTEX_Ops;
+extern const K32OBJ_OPS CRITICAL_SECTION_Ops;
+extern const K32OBJ_OPS PROCESS_Ops;
+extern const K32OBJ_OPS THREAD_Ops;
+extern const K32OBJ_OPS FILE_Ops;
+extern const K32OBJ_OPS MEM_MAPPED_FILE_Ops;
+
+static const K32OBJ_OPS K32OBJ_NullOps =
+{
+    NULL,    /* signaled */
+    NULL,    /* satisfied */
+    NULL,    /* add_wait */
+    NULL,    /* remove_wait */
+    NULL     /* destroy */
+};
+
+const K32OBJ_OPS * const K32OBJ_Ops[K32OBJ_NBOBJECTS] =
+{
+    NULL,
+    &SEMAPHORE_Ops,         /* K32OBJ_SEMAPHORE */
+    &EVENT_Ops,             /* K32OBJ_EVENT */
+    &MUTEX_Ops,             /* K32OBJ_MUTEX */
+    &CRITICAL_SECTION_Ops,  /* K32OBJ_CRITICAL_SECTION */
+    &PROCESS_Ops,           /* K32OBJ_PROCESS */
+    &THREAD_Ops,            /* K32OBJ_THREAD */
+    &FILE_Ops,              /* K32OBJ_FILE */
+    &K32OBJ_NullOps,        /* K32OBJ_CHANGE */
+    &K32OBJ_NullOps,        /* K32OBJ_CONSOLE */
+    &K32OBJ_NullOps,        /* K32OBJ_SCREEN_BUFFER */
+    &MEM_MAPPED_FILE_Ops,   /* K32OBJ_MEM_MAPPED_FILE */
+    &K32OBJ_NullOps,        /* K32OBJ_SERIAL */
+    &K32OBJ_NullOps,        /* K32OBJ_DEVICE_IOCTL */
+    &K32OBJ_NullOps,        /* K32OBJ_PIPE */
+    &K32OBJ_NullOps,        /* K32OBJ_MAILSLOT */
+    &K32OBJ_NullOps,        /* K32OBJ_TOOLHELP_SNAPSHOT */
+    &K32OBJ_NullOps         /* K32OBJ_SOCKET */
+};
+
+typedef struct _NE
+{
+    struct _NE *next;
+    K32OBJ     *obj;
+    UINT32      len;
+    char        name[1];
+} NAME_ENTRY;
+
+static NAME_ENTRY *K32OBJ_FirstEntry = NULL;
+
+
+/***********************************************************************
+ *           K32OBJ_IncCount
+ */
+void K32OBJ_IncCount( K32OBJ *ptr )
+{
+    assert( ptr->type && ((unsigned)ptr->type < K32OBJ_NBOBJECTS) );
+    SYSTEM_LOCK();
+    ptr->refcount++;
+    SYSTEM_UNLOCK();
+    assert( ptr->refcount > 0 );  /* No wrap-around allowed */
+}
+
+
+/***********************************************************************
+ *           K32OBJ_DecCount
+ */
+void K32OBJ_DecCount( K32OBJ *ptr )
+{
+    NAME_ENTRY **pptr;
+
+    assert( ptr->type && ((unsigned)ptr->type < K32OBJ_NBOBJECTS) );
+    assert( ptr->refcount > 0 );
+    SYSTEM_LOCK();
+    if (--ptr->refcount)
+    {
+        SYSTEM_UNLOCK();
+        return;
+    }
+
+    /* Check if the object has a name entry and free it */
+
+    pptr = &K32OBJ_FirstEntry;
+    while (*pptr && ((*pptr)->obj != ptr)) pptr = &(*pptr)->next;
+    if (*pptr)
+    {
+        NAME_ENTRY *entry = *pptr;
+        *pptr = entry->next;
+        HeapFree( SystemHeap, 0, entry );
+    }
+
+    /* Free the object */
+
+    if (K32OBJ_Ops[ptr->type]->destroy) K32OBJ_Ops[ptr->type]->destroy( ptr );
+    SYSTEM_UNLOCK();
+}
+
+
+/***********************************************************************
+ *           K32OBJ_IsValid
+ *
+ * Check if a pointer is a valid kernel object
+ */
+BOOL32 K32OBJ_IsValid( K32OBJ *ptr, K32OBJ_TYPE type )
+{
+    if (IsBadReadPtr32( ptr, sizeof(*ptr) )) return FALSE;
+    return (ptr->type == type);
+}
+
+
+/***********************************************************************
+ *           K32OBJ_AddName
+ *
+ * Add a name entry for an object. We don't check for duplicates here.
+ * FIXME: should use some sort of hashing.
+ */
+BOOL32 K32OBJ_AddName( K32OBJ *obj, LPCSTR name )
+{
+    NAME_ENTRY *entry;
+    UINT32 len;
+
+    if (!name) return TRUE;  /* Anonymous object */
+    len = strlen( name );
+    SYSTEM_LOCK();
+    if (!(entry = HeapAlloc( SystemHeap, 0, sizeof(NAME_ENTRY) + len )))
+    {
+        SYSTEM_UNLOCK();
+        SetLastError( ERROR_OUTOFMEMORY );
+        return FALSE;
+    }
+    entry->next = K32OBJ_FirstEntry;
+    entry->obj = obj;
+    lstrcpy32A( entry->name, name );
+    K32OBJ_FirstEntry = entry;
+    SYSTEM_UNLOCK();
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           K32OBJ_Create
+ *
+ * Create a named kernel object.
+ * Returns NULL if there was an error _or_ if the object already existed.
+ * The refcount of the object must be decremented once it is initialized.
+ */
+K32OBJ *K32OBJ_Create( K32OBJ_TYPE type, DWORD size, LPCSTR name,
+                       HANDLE32 *handle )
+{
+    /* Check if the name already exists */
+
+    K32OBJ *obj = K32OBJ_FindName( name );
+    if (obj)
+    {
+        if (obj->type == type)
+        {
+            SetLastError( ERROR_ALREADY_EXISTS );
+            *handle = PROCESS_AllocHandle( obj, 0 );
+        }
+        else
+        {
+            SetLastError( ERROR_DUP_NAME );
+            *handle = INVALID_HANDLE_VALUE32;
+        }
+        K32OBJ_DecCount( obj );
+        return NULL;
+    }
+
+    /* Create the object */
+
+    SYSTEM_LOCK();
+    if (!(obj = HeapAlloc( SystemHeap, 0, size )))
+    {
+        SYSTEM_UNLOCK();
+        *handle = INVALID_HANDLE_VALUE32;
+        return NULL;
+    }
+    obj->type     = type;
+    obj->refcount = 1;
+
+    /* Add a name for it */
+
+    if (!K32OBJ_AddName( obj, name ))
+    {
+        /* Don't call the destroy function, as the object wasn't
+         * initialized properly */
+        HeapFree( SystemHeap, 0, obj );
+        SYSTEM_UNLOCK();
+        *handle = INVALID_HANDLE_VALUE32;
+        return NULL;
+    }
+
+    /* Allocate a handle */
+
+    *handle = PROCESS_AllocHandle( obj, 0 );
+    SYSTEM_UNLOCK();
+    return obj;
+}
+
+
+/***********************************************************************
+ *           K32OBJ_FindName
+ *
+ * Find the object referenced by a given name.
+ * The reference count is incremented.
+ */
+K32OBJ *K32OBJ_FindName( LPCSTR name )
+{
+    NAME_ENTRY *entry;
+    UINT32 len;
+
+    if (!name) return NULL;  /* Anonymous object */
+    len = strlen( name );
+    SYSTEM_LOCK();
+    entry = K32OBJ_FirstEntry;
+    while (entry)
+    {
+        if ((len == entry->len) && !lstrcmp32A( name, entry->name))
+        {
+            K32OBJ *obj = entry->obj;
+            K32OBJ_IncCount( obj );
+            SYSTEM_UNLOCK();
+            return entry->obj;
+        }
+        entry = entry->next;
+    }
+    SYSTEM_UNLOCK();
+    return NULL;
+}
+
+
+/***********************************************************************
+ *           K32OBJ_FindNameType
+ *
+ * Find an object by name and check its type.
+ * The reference count is incremented.
+ */
+K32OBJ *K32OBJ_FindNameType( LPCSTR name, K32OBJ_TYPE type )
+{
+    K32OBJ *obj = K32OBJ_FindName( name );
+    if (!obj) return NULL;
+    if (obj->type == type) return obj;
+    SetLastError( ERROR_DUP_NAME );
+    K32OBJ_DecCount( obj );
+    return NULL;
+}
diff --git a/scheduler/mutex.c b/scheduler/mutex.c
new file mode 100644
index 0000000..737789a
--- /dev/null
+++ b/scheduler/mutex.c
@@ -0,0 +1,207 @@
+/*
+ * Win32 mutexes
+ *
+ * Copyright 1998 Alexandre Julliard
+ */
+
+#include <assert.h>
+#include "windows.h"
+#include "winerror.h"
+#include "k32obj.h"
+#include "process.h"
+#include "thread.h"
+#include "heap.h"
+
+typedef struct
+{
+    K32OBJ        header;
+    THREAD_QUEUE  wait_queue;
+    DWORD         owner;
+    DWORD         count;
+} MUTEX;
+
+static BOOL32 MUTEX_Signaled( K32OBJ *obj, DWORD thread_id );
+static void MUTEX_Satisfied( K32OBJ *obj, DWORD thread_id );
+static void MUTEX_AddWait( K32OBJ *obj, DWORD thread_id );
+static void MUTEX_RemoveWait( K32OBJ *obj, DWORD thread_id );
+static void MUTEX_Destroy( K32OBJ *obj );
+
+const K32OBJ_OPS MUTEX_Ops =
+{
+    MUTEX_Signaled,    /* signaled */
+    MUTEX_Satisfied,   /* satisfied */
+    MUTEX_AddWait,     /* add_wait */
+    MUTEX_RemoveWait,  /* remove_wait */
+    MUTEX_Destroy      /* destroy */
+};
+
+
+/***********************************************************************
+ *           CreateMutex32A   (KERNEL32.166)
+ */
+HANDLE32 WINAPI CreateMutex32A( SECURITY_ATTRIBUTES *sa, BOOL32 owner,
+                                LPCSTR name )
+{
+    HANDLE32 handle;
+    MUTEX *mutex;
+
+    SYSTEM_LOCK();
+    mutex = (MUTEX *)K32OBJ_Create( K32OBJ_MUTEX, sizeof(*mutex),
+                                    name, &handle );
+    if (mutex)
+    {
+        /* Finish initializing it */
+        mutex->wait_queue = NULL;
+        if (owner)
+        {
+            mutex->owner = GetCurrentThreadId();
+            mutex->count = 1;
+        }
+        else
+        {
+            mutex->owner = 0;
+            mutex->count = 0;
+        }
+        K32OBJ_DecCount( &mutex->header );
+    }
+    SYSTEM_UNLOCK();
+    return handle;
+}
+
+
+/***********************************************************************
+ *           CreateMutex32W   (KERNEL32.167)
+ */
+HANDLE32 WINAPI CreateMutex32W( SECURITY_ATTRIBUTES *sa, BOOL32 owner,
+                                LPCWSTR name )
+{
+    LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
+    HANDLE32 ret = CreateMutex32A( sa, owner, nameA );
+    if (nameA) HeapFree( GetProcessHeap(), 0, nameA );
+    return ret;
+}
+
+
+/***********************************************************************
+ *           OpenMutex32A   (KERNEL32.541)
+ */
+HANDLE32 WINAPI OpenMutex32A( DWORD access, BOOL32 inherit, LPCSTR name )
+{
+    HANDLE32 handle = 0;
+    K32OBJ *obj;
+    SYSTEM_LOCK();
+    if ((obj = K32OBJ_FindNameType( name, K32OBJ_MUTEX )) != NULL)
+    {
+        handle = PROCESS_AllocHandle( obj, 0 );
+        K32OBJ_DecCount( obj );
+    }
+    SYSTEM_UNLOCK();
+    return handle;
+}
+
+
+/***********************************************************************
+ *           OpenMutex32W   (KERNEL32.542)
+ */
+HANDLE32 WINAPI OpenMutex32W( DWORD access, BOOL32 inherit, LPCWSTR name )
+{
+    LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
+    HANDLE32 ret = OpenMutex32A( access, inherit, nameA );
+    if (nameA) HeapFree( GetProcessHeap(), 0, nameA );
+    return ret;
+}
+
+
+/***********************************************************************
+ *           ReleaseMutex   (KERNEL32.582)
+ */
+BOOL32 WINAPI ReleaseMutex( HANDLE32 handle )
+{
+    MUTEX *mutex;
+    SYSTEM_LOCK();
+    if (!(mutex = (MUTEX *)PROCESS_GetObjPtr( handle, K32OBJ_MUTEX )))
+    {
+        SYSTEM_UNLOCK();
+        return FALSE;
+    }
+    if (!mutex->count || (mutex->owner != GetCurrentThreadId()))
+    {
+        SYSTEM_UNLOCK();
+        SetLastError( ERROR_NOT_OWNER );
+        return FALSE;
+    }
+    if (!--mutex->count)
+    {
+        mutex->owner = 0;
+        SYNC_WakeUp( &mutex->wait_queue, INFINITE32 );
+    }
+    K32OBJ_DecCount( &mutex->header );
+    SYSTEM_UNLOCK();
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           MUTEX_Signaled
+ */
+static BOOL32 MUTEX_Signaled( K32OBJ *obj, DWORD thread_id )
+{
+    MUTEX *mutex = (MUTEX *)obj;
+    assert( obj->type == K32OBJ_MUTEX );
+    return (!mutex->count || (mutex->owner == thread_id));
+}
+
+
+/***********************************************************************
+ *           MUTEX_Satisfied
+ *
+ * Wait on this object has been satisfied.
+ */
+static void MUTEX_Satisfied( K32OBJ *obj, DWORD thread_id )
+{
+    MUTEX *mutex = (MUTEX *)obj;
+    assert( obj->type == K32OBJ_MUTEX );
+    assert( !mutex->count || (mutex->owner == thread_id) );
+    mutex->owner = thread_id;
+    mutex->count++;
+}
+
+
+/***********************************************************************
+ *           MUTEX_AddWait
+ *
+ * Add a thread to the object wait queue.
+ */
+static void MUTEX_AddWait( K32OBJ *obj, DWORD thread_id )
+{
+    MUTEX *mutex = (MUTEX *)obj;
+    assert( obj->type == K32OBJ_MUTEX );
+    THREAD_AddQueue( &mutex->wait_queue, THREAD_ID_TO_THDB(thread_id) );
+}
+
+
+/***********************************************************************
+ *           MUTEX_RemoveWait
+ *
+ * Remove a thread from the object wait queue.
+ */
+static void MUTEX_RemoveWait( K32OBJ *obj, DWORD thread_id )
+{
+    MUTEX *mutex = (MUTEX *)obj;
+    assert( obj->type == K32OBJ_MUTEX );
+    THREAD_RemoveQueue( &mutex->wait_queue, THREAD_ID_TO_THDB(thread_id) );
+}
+
+
+/***********************************************************************
+ *           MUTEX_Destroy
+ */
+static void MUTEX_Destroy( K32OBJ *obj )
+{
+    MUTEX *mutex = (MUTEX *)obj;
+    assert( obj->type == K32OBJ_MUTEX );
+    /* There cannot be any thread on the list since the ref count is 0 */
+    assert( mutex->wait_queue == NULL );
+    obj->type = K32OBJ_UNKNOWN;
+    HeapFree( SystemHeap, 0, mutex );
+}
diff --git a/scheduler/process.c b/scheduler/process.c
index b819080..225dd14 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -25,6 +25,21 @@
 
 #define BOOT_HTABLE_SIZE  10
 
+static BOOL32 PROCESS_Signaled( K32OBJ *obj, DWORD thread_id );
+static void PROCESS_Satisfied( K32OBJ *obj, DWORD thread_id );
+static void PROCESS_AddWait( K32OBJ *obj, DWORD thread_id );
+static void PROCESS_RemoveWait( K32OBJ *obj, DWORD thread_id );
+static void PROCESS_Destroy( K32OBJ *obj );
+
+const K32OBJ_OPS PROCESS_Ops =
+{
+    PROCESS_Signaled,    /* signaled */
+    PROCESS_Satisfied,   /* satisfied */
+    PROCESS_AddWait,     /* add_wait */
+    PROCESS_RemoveWait,  /* remove_wait */
+    PROCESS_Destroy      /* destroy */
+};
+
 static HANDLE_ENTRY boot_handles[BOOT_HTABLE_SIZE];
 
 /***********************************************************************
@@ -46,14 +61,20 @@
  */
 static BOOL32 PROCESS_GrowHandleTable( PDB32 *process )
 {
-    HANDLE_TABLE *table = process->handle_table;
-    table = HeapReAlloc( process->system_heap, HEAP_ZERO_MEMORY, table,
+    HANDLE_TABLE *table;
+    SYSTEM_LOCK();
+    table = process->handle_table;
+    table = HeapReAlloc( process->system_heap,
+                         HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE, table,
                          sizeof(HANDLE_TABLE) +
                          (table->count+HTABLE_INC-1) * sizeof(HANDLE_ENTRY) );
-    if (!table) return FALSE;
-    table->count += HTABLE_INC;
-    process->handle_table = table;
-    return TRUE;
+    if (table)
+    {
+        table->count += HTABLE_INC;
+        process->handle_table = table;
+    }
+    SYSTEM_UNLOCK();
+    return (table != NULL);
 }
 
 
@@ -65,12 +86,14 @@
 static HANDLE32 PROCESS_AllocBootHandle( K32OBJ *ptr, DWORD flags )
 {
     HANDLE32 h;
+    SYSTEM_LOCK();
     for (h = 0; h < BOOT_HTABLE_SIZE; h++)
         if (!boot_handles[h].ptr) break;
     assert( h < BOOT_HTABLE_SIZE );
     K32OBJ_IncCount( ptr );
     boot_handles[h].flags = flags;
     boot_handles[h].ptr   = ptr;
+    SYSTEM_UNLOCK();
     return h + 1;  /* Avoid handle 0 */
 }
 
@@ -82,12 +105,16 @@
  */
 static BOOL32 PROCESS_CloseBootHandle( HANDLE32 handle )
 {
+    K32OBJ *ptr;
     HANDLE_ENTRY *entry = &boot_handles[handle - 1];
     assert( (handle > 0) && (handle <= BOOT_HTABLE_SIZE) );
+    SYSTEM_LOCK();
     assert( entry->ptr );
-    K32OBJ_DecCount( entry->ptr );
+    ptr = entry->ptr;
     entry->flags = 0;
     entry->ptr   = NULL;
+    K32OBJ_DecCount( ptr );
+    SYSTEM_UNLOCK();
     return TRUE;
 }
 
@@ -102,9 +129,11 @@
     K32OBJ *ptr;
 
     assert( (handle > 0) && (handle <= BOOT_HTABLE_SIZE) );
+    SYSTEM_LOCK();
     ptr = boot_handles[handle - 1].ptr;
     assert (ptr && (ptr->type == type));
     K32OBJ_IncCount( ptr );
+    SYSTEM_UNLOCK();
     return ptr;
 }
 
@@ -119,10 +148,13 @@
     K32OBJ *old_ptr;
 
     assert( (handle > 0) && (handle <= BOOT_HTABLE_SIZE) );
+    SYSTEM_LOCK();
     K32OBJ_IncCount( ptr );
-    if ((old_ptr = boot_handles[handle - 1].ptr)) K32OBJ_DecCount( old_ptr );
+    old_ptr = boot_handles[handle - 1].ptr;
     boot_handles[handle - 1].flags = flags;
     boot_handles[handle - 1].ptr   = ptr;
+    if (old_ptr) K32OBJ_DecCount( old_ptr );
+    SYSTEM_UNLOCK();
     return TRUE;
 }
 
@@ -139,7 +171,7 @@
 
     assert( ptr );
     if (!pCurrentProcess) return PROCESS_AllocBootHandle( ptr, flags );
-    EnterCriticalSection( &pCurrentProcess->crit_section );
+    SYSTEM_LOCK();
     K32OBJ_IncCount( ptr );
     entry = pCurrentProcess->handle_table->entries;
     for (h = 0; h < pCurrentProcess->handle_table->count; h++, entry++)
@@ -150,12 +182,12 @@
         entry = &pCurrentProcess->handle_table->entries[h];
         entry->flags = flags;
         entry->ptr   = ptr;
-        LeaveCriticalSection( &pCurrentProcess->crit_section );
+        SYSTEM_UNLOCK();
         return h + 1;  /* Avoid handle 0 */
     }
-    LeaveCriticalSection( &pCurrentProcess->crit_section );
-    SetLastError( ERROR_OUTOFMEMORY );
     K32OBJ_DecCount( ptr );
+    SYSTEM_UNLOCK();
+    SetLastError( ERROR_OUTOFMEMORY );
     return INVALID_HANDLE_VALUE32;
 }
 
@@ -170,7 +202,7 @@
 {
     K32OBJ *ptr = NULL;
     if (!pCurrentProcess) return PROCESS_GetBootObjPtr( handle, type );
-    EnterCriticalSection( &pCurrentProcess->crit_section );
+    SYSTEM_LOCK();
 
     if ((handle > 0) && (handle <= pCurrentProcess->handle_table->count))
         ptr = pCurrentProcess->handle_table->entries[handle - 1].ptr;
@@ -180,7 +212,7 @@
         K32OBJ_IncCount( ptr );
     else ptr = NULL;
 
-    LeaveCriticalSection( &pCurrentProcess->crit_section );
+    SYSTEM_UNLOCK();
     if (!ptr) SetLastError( ERROR_INVALID_HANDLE );
     return ptr;
 }
@@ -198,7 +230,7 @@
     K32OBJ *old_ptr = NULL;
 
     if (!pCurrentProcess) return PROCESS_SetBootObjPtr( handle, ptr, flags );
-    EnterCriticalSection( &pCurrentProcess->crit_section );
+    SYSTEM_LOCK();
     if ((handle > 0) && (handle <= pCurrentProcess->handle_table->count))
     {
         HANDLE_ENTRY*entry = &pCurrentProcess->handle_table->entries[handle-1];
@@ -212,8 +244,8 @@
         SetLastError( ERROR_INVALID_HANDLE );
         ret = FALSE;
     }
-    LeaveCriticalSection( &pCurrentProcess->crit_section );
     if (old_ptr) K32OBJ_DecCount( old_ptr );
+    SYSTEM_UNLOCK();
     return ret;
 }
 
@@ -227,7 +259,7 @@
     K32OBJ *ptr = NULL;
 
     if (!pCurrentProcess) return PROCESS_CloseBootHandle( handle );
-    EnterCriticalSection( &pCurrentProcess->crit_section );
+    SYSTEM_LOCK();
     if ((handle > 0) && (handle <= pCurrentProcess->handle_table->count))
     {
         HANDLE_ENTRY*entry = &pCurrentProcess->handle_table->entries[handle-1];
@@ -238,9 +270,9 @@
             ret = TRUE;
         }
     }
-    LeaveCriticalSection( &pCurrentProcess->crit_section );
-    if (!ret) SetLastError( ERROR_INVALID_HANDLE );
     if (ptr) K32OBJ_DecCount( ptr );
+    SYSTEM_UNLOCK();
+    if (!ret) SetLastError( ERROR_INVALID_HANDLE );
     return ret;
 }
 
@@ -323,10 +355,14 @@
     pdb->parent          = pCurrentProcess;
     pdb->group           = pdb;
     pdb->priority        = 8;  /* Normal */
-    pdb->heap_list       = pdb->heap;
 
     InitializeCriticalSection( &pdb->crit_section );
 
+    /* Allocate the events */
+
+    if (!(pdb->event = EVENT_Create( TRUE, FALSE ))) goto error;
+    if (!(pdb->load_done_evt = EVENT_Create( TRUE, FALSE ))) goto error;
+
     /* Create the heap */
 
     if (pModule->module32)
@@ -340,6 +376,7 @@
 	commit = 0;
     }
     if (!(pdb->heap = HeapCreate( HEAP_GROWABLE, size, commit ))) goto error;
+    pdb->heap_list = pdb->heap;
 
     if (!(pdb->env_db = HeapAlloc(pdb->heap, HEAP_ZERO_MEMORY, sizeof(ENVDB))))
         goto error;
@@ -351,6 +388,8 @@
     if (pdb->env_db) HeapFree( pdb->heap, 0, pdb->env_db );
     if (pdb->handle_table) HeapFree( pdb->system_heap, 0, pdb->handle_table );
     if (pdb->heap) HeapDestroy( pdb->heap );
+    if (pdb->load_done_evt) K32OBJ_DecCount( pdb->load_done_evt );
+    if (pdb->event) K32OBJ_DecCount( pdb->event );
     DeleteCriticalSection( &pdb->crit_section );
     HeapFree( SystemHeap, 0, pdb );
     return NULL;
@@ -358,9 +397,59 @@
 
 
 /***********************************************************************
+ *           PROCESS_Signaled
+ */
+static BOOL32 PROCESS_Signaled( K32OBJ *obj, DWORD thread_id )
+{
+    PDB32 *pdb = (PDB32 *)obj;
+    assert( obj->type == K32OBJ_PROCESS );
+    return K32OBJ_OPS( pdb->event )->signaled( pdb->event, thread_id );
+}
+
+
+/***********************************************************************
+ *           PROCESS_Satisfied
+ *
+ * Wait on this object has been satisfied.
+ */
+static void PROCESS_Satisfied( K32OBJ *obj, DWORD thread_id )
+{
+    PDB32 *pdb = (PDB32 *)obj;
+    assert( obj->type == K32OBJ_PROCESS );
+    return K32OBJ_OPS( pdb->event )->satisfied( pdb->event, thread_id );
+}
+
+
+/***********************************************************************
+ *           PROCESS_AddWait
+ *
+ * Add thread to object wait queue.
+ */
+static void PROCESS_AddWait( K32OBJ *obj, DWORD thread_id )
+{
+    PDB32 *pdb = (PDB32 *)obj;
+    assert( obj->type == K32OBJ_PROCESS );
+    return K32OBJ_OPS( pdb->event )->add_wait( pdb->event, thread_id );
+}
+
+
+/***********************************************************************
+ *           PROCESS_RemoveWait
+ *
+ * Remove thread from object wait queue.
+ */
+static void PROCESS_RemoveWait( K32OBJ *obj, DWORD thread_id )
+{
+    PDB32 *pdb = (PDB32 *)obj;
+    assert( obj->type == K32OBJ_PROCESS );
+    return K32OBJ_OPS( pdb->event )->remove_wait( pdb->event, thread_id );
+}
+
+
+/***********************************************************************
  *           PROCESS_Destroy
  */
-void PROCESS_Destroy( K32OBJ *ptr )
+static void PROCESS_Destroy( K32OBJ *ptr )
 {
     PDB32 *pdb = (PDB32 *)ptr;
     HANDLE32 handle;
@@ -376,6 +465,8 @@
     HeapFree( pdb->heap, 0, pdb->env_db );
     HeapFree( pdb->system_heap, 0, pdb->handle_table );
     HeapDestroy( pdb->heap );
+    K32OBJ_DecCount( pdb->load_done_evt );
+    K32OBJ_DecCount( pdb->event );
     DeleteCriticalSection( &pdb->crit_section );
     HeapFree( SystemHeap, 0, pdb );
 }
@@ -387,6 +478,9 @@
 void WINAPI ExitProcess( DWORD status )
 {
     __RESTORE_ES;  /* Necessary for Pietrek's showseh example program */
+    /* FIXME: should kill all running threads of this process */
+    pCurrentProcess->exit_code = status;
+    EVENT_Set( pCurrentProcess->event );
     TASK_KillCurrentTask( status );
 }
 
@@ -401,26 +495,26 @@
 
 
 /*********************************************************************
- *	OpenProcess				[KERNEL32.543]
- *
+ *           OpenProcess   (KERNEL32.543)
  */
-HANDLE32 WINAPI OpenProcess32(DWORD fdwAccess,BOOL32 bInherit,DWORD IDProcess)
+HANDLE32 WINAPI OpenProcess( DWORD access, BOOL32 inherit, DWORD id )
 {
-	if (IDProcess != (DWORD)pCurrentProcess) {
-		fprintf(stderr,"OpenProcess32(%ld,%d,%ld)\n",fdwAccess,bInherit,IDProcess);
-		/* XXX: might not be the correct error value */
-		SetLastError( ERROR_INVALID_HANDLE );
-		return 0;
-	}
-	return GetCurrentProcess();
+    PDB32 *pdb = PROCESS_ID_TO_PDB(id);
+    if (!K32OBJ_IsValid( &pdb->header, K32OBJ_PROCESS ))
+    {
+        SetLastError( ERROR_INVALID_HANDLE );
+        return 0;
+    }
+    return PROCESS_AllocHandle( &pdb->header, 0 );
 }			      
 
+
 /***********************************************************************
  *           GetCurrentProcessId   (KERNEL32.199)
  */
 DWORD WINAPI GetCurrentProcessId(void)
 {
-    return (DWORD)pCurrentProcess;
+    return PDB_TO_PROCESS_ID(pCurrentProcess);
 }
 
 
@@ -859,20 +953,25 @@
 /***********************************************************************
  *           GetProcessVersion    (KERNEL32)
  */
-DWORD WINAPI GetProcessVersion(DWORD processid)
+DWORD WINAPI GetProcessVersion( DWORD processid )
 {
-	PDB32	*process;
-	TDB	*pTask;
+    PDB32 *process;
+    TDB *pTask;
 
-	if (!processid) {
-		process=pCurrentProcess;
-		/* check if valid process */
-	} else
-		process=(PDB32*)pCurrentProcess; /* decrypt too, if needed */
-	pTask = (TDB*)GlobalLock16(process->task);
-	if (!pTask)
-		return 0;
-	return (pTask->version&0xff) | (((pTask->version >>8) & 0xff)<<16);
+    if (!processid) process = pCurrentProcess;
+    else
+    {
+        process = PROCESS_ID_TO_PDB(processid);
+        if (!K32OBJ_IsValid( &process->header, K32OBJ_PROCESS ))
+        {
+            SetLastError( ERROR_INVALID_PARAMETER );
+            return 0;
+        }
+    }
+    pTask = (TDB*)GlobalLock16(process->task);
+    if (!pTask)
+        return 0;
+    return (pTask->version&0xff) | (((pTask->version >>8) & 0xff)<<16);
 }
 
 /***********************************************************************
@@ -880,14 +979,19 @@
  */
 DWORD WINAPI GetProcessFlags(DWORD processid)
 {
-	PDB32	*process;
+    PDB32 *process;
 
-	if (!processid) {
-		process=pCurrentProcess;
-		/* check if valid process */
-	} else
-		process=(PDB32*)pCurrentProcess; /* decrypt too, if needed */
-	return process->flags;
+    if (!processid) process = pCurrentProcess;
+    else
+    {
+        process = PROCESS_ID_TO_PDB(processid);
+        if (!K32OBJ_IsValid( &process->header, K32OBJ_PROCESS ))
+        {
+            SetLastError( ERROR_INVALID_PARAMETER );
+            return 0;
+        }
+    }
+    return process->flags;
 }
 
 /***********************************************************************
@@ -951,3 +1055,15 @@
 	fprintf(stderr,"ConvertToGlobalHandle(%d),stub!\n",h);
 	return h;
 }
+
+/***********************************************************************
+ *           RegisterServiceProcess             (KERNEL32)
+ *
+ * A service process calls this function to ensure that it continues to run
+ * even after a user logged off.
+ */
+DWORD RegisterServiceProcess(DWORD dwProcessId, DWORD dwType)
+{
+	/* I don't think that Wine needs to do anything in that function */
+	return 1; /* success */
+}
diff --git a/scheduler/semaphore.c b/scheduler/semaphore.c
new file mode 100644
index 0000000..d8c1535
--- /dev/null
+++ b/scheduler/semaphore.c
@@ -0,0 +1,214 @@
+/*
+ * Win32 semaphores
+ *
+ * Copyright 1998 Alexandre Julliard
+ */
+
+#include <assert.h>
+#include "windows.h"
+#include "winerror.h"
+#include "k32obj.h"
+#include "process.h"
+#include "thread.h"
+#include "heap.h"
+
+typedef struct
+{
+    K32OBJ        header;
+    THREAD_QUEUE  wait_queue;
+    LONG          count;
+    LONG          max;
+} SEMAPHORE;
+
+static BOOL32 SEMAPHORE_Signaled( K32OBJ *obj, DWORD thread_id );
+static void SEMAPHORE_Satisfied( K32OBJ *obj, DWORD thread_id );
+static void SEMAPHORE_AddWait( K32OBJ *obj, DWORD thread_id );
+static void SEMAPHORE_RemoveWait( K32OBJ *obj, DWORD thread_id );
+static void SEMAPHORE_Destroy( K32OBJ *obj );
+
+const K32OBJ_OPS SEMAPHORE_Ops =
+{
+    SEMAPHORE_Signaled,    /* signaled */
+    SEMAPHORE_Satisfied,   /* satisfied */
+    SEMAPHORE_AddWait,     /* add_wait */
+    SEMAPHORE_RemoveWait,  /* remove_wait */
+    SEMAPHORE_Destroy      /* destroy */
+};
+
+
+/***********************************************************************
+ *           CreateSemaphore32A   (KERNEL32.174)
+ */
+HANDLE32 WINAPI CreateSemaphore32A( SECURITY_ATTRIBUTES *sa, LONG initial,
+                                    LONG max, LPCSTR name )
+{
+    HANDLE32 handle;
+    SEMAPHORE *sem;
+
+    /* Check parameters */
+
+    if ((max <= 0) || (initial < 0) || (initial > max))
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return INVALID_HANDLE_VALUE32;
+    }
+
+    SYSTEM_LOCK();
+    sem = (SEMAPHORE *)K32OBJ_Create( K32OBJ_SEMAPHORE, sizeof(*sem),
+                                      name, &handle );
+    if (sem)
+    {
+        /* Finish initializing it */
+        sem->wait_queue = NULL;
+        sem->count      = initial;
+        sem->max        = max;
+        K32OBJ_DecCount( &sem->header );
+    }
+    SYSTEM_UNLOCK();
+    return handle;
+}
+
+
+/***********************************************************************
+ *           CreateSemaphore32W   (KERNEL32.175)
+ */
+HANDLE32 WINAPI CreateSemaphore32W( SECURITY_ATTRIBUTES *sa, LONG initial,
+                                    LONG max, LPCWSTR name )
+{
+    LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
+    HANDLE32 ret = CreateSemaphore32A( sa, initial, max, nameA );
+    if (nameA) HeapFree( GetProcessHeap(), 0, nameA );
+    return ret;
+}
+
+
+/***********************************************************************
+ *           OpenSemaphore32A   (KERNEL32.545)
+ */
+HANDLE32 WINAPI OpenSemaphore32A( DWORD access, BOOL32 inherit, LPCSTR name )
+{
+    HANDLE32 handle = 0;
+    K32OBJ *obj;
+    SYSTEM_LOCK();
+    if ((obj = K32OBJ_FindNameType( name, K32OBJ_SEMAPHORE )) != NULL)
+    {
+        handle = PROCESS_AllocHandle( obj, 0 );
+        K32OBJ_DecCount( obj );
+    }
+    SYSTEM_UNLOCK();
+    return handle;
+}
+
+
+/***********************************************************************
+ *           OpenSemaphore32W   (KERNEL32.546)
+ */
+HANDLE32 WINAPI OpenSemaphore32W( DWORD access, BOOL32 inherit, LPCWSTR name )
+{
+    LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
+    HANDLE32 ret = OpenSemaphore32A( access, inherit, nameA );
+    if (nameA) HeapFree( GetProcessHeap(), 0, nameA );
+    return ret;
+}
+
+
+/***********************************************************************
+ *           ReleaseSemaphore   (KERNEL32.583)
+ */
+BOOL32 WINAPI ReleaseSemaphore( HANDLE32 handle, LONG count, LONG *previous )
+{
+    SEMAPHORE *sem;
+
+    SYSTEM_LOCK();
+    if (!(sem = (SEMAPHORE *)PROCESS_GetObjPtr( handle, K32OBJ_SEMAPHORE )))
+    {
+        SYSTEM_UNLOCK();
+        return FALSE;
+    }
+    if (previous) *previous = sem->count;
+    if (sem->count + count > sem->max)
+    {
+        SYSTEM_UNLOCK();
+        SetLastError( ERROR_TOO_MANY_POSTS );
+        return FALSE;
+    }
+    if (sem->count > 0)
+    {
+        /* There cannot be any thread waiting if the count is > 0 */
+        assert( sem->wait_queue == NULL );
+        sem->count += count;
+    }
+    else
+    {
+        sem->count = count;
+        SYNC_WakeUp( &sem->wait_queue, count );
+    }
+    K32OBJ_DecCount( &sem->header );
+    SYSTEM_UNLOCK();
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           SEMAPHORE_Signaled
+ */
+static BOOL32 SEMAPHORE_Signaled( K32OBJ *obj, DWORD thread_id )
+{
+    SEMAPHORE *sem = (SEMAPHORE *)obj;
+    assert( obj->type == K32OBJ_SEMAPHORE );
+    return (sem->count > 0);
+}
+
+
+/***********************************************************************
+ *           SEMAPHORE_Satisfied
+ *
+ * Wait on this object has been satisfied.
+ */
+static void SEMAPHORE_Satisfied( K32OBJ *obj, DWORD thread_id )
+{
+    SEMAPHORE *sem = (SEMAPHORE *)obj;
+    assert( obj->type == K32OBJ_SEMAPHORE );
+    assert( sem->count > 0 );
+    sem->count--;
+}
+
+
+/***********************************************************************
+ *           SEMAPHORE_AddWait
+ *
+ * Add current thread to object wait queue.
+ */
+static void SEMAPHORE_AddWait( K32OBJ *obj, DWORD thread_id )
+{
+    SEMAPHORE *sem = (SEMAPHORE *)obj;
+    assert( obj->type == K32OBJ_SEMAPHORE );
+    THREAD_AddQueue( &sem->wait_queue, THREAD_ID_TO_THDB(thread_id) );
+}
+
+
+/***********************************************************************
+ *           SEMAPHORE_RemoveWait
+ *
+ * Remove thread from object wait queue.
+ */
+static void SEMAPHORE_RemoveWait( K32OBJ *obj, DWORD thread_id )
+{
+    SEMAPHORE *sem = (SEMAPHORE *)obj;
+    assert( obj->type == K32OBJ_SEMAPHORE );
+    THREAD_RemoveQueue( &sem->wait_queue, THREAD_ID_TO_THDB(thread_id) );
+}
+
+
+/***********************************************************************
+ *           SEMAPHORE_Destroy
+ */
+static void SEMAPHORE_Destroy( K32OBJ *obj )
+{
+    SEMAPHORE *sem = (SEMAPHORE *)obj;
+    assert( obj->type == K32OBJ_SEMAPHORE );
+    /* There cannot be any thread on the list since the ref count is 0 */
+    assert( sem->wait_queue == NULL );
+    obj->type = K32OBJ_UNKNOWN;
+    HeapFree( SystemHeap, 0, sem );
+}
diff --git a/scheduler/synchro.c b/scheduler/synchro.c
new file mode 100644
index 0000000..2000217
--- /dev/null
+++ b/scheduler/synchro.c
@@ -0,0 +1,315 @@
+/*
+ * Win32 process and thread synchronisation
+ *
+ * Copyright 1997 Alexandre Julliard
+ */
+
+#include <assert.h>
+#include <signal.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include "k32obj.h"
+#include "heap.h"
+#include "process.h"
+#include "thread.h"
+#include "winerror.h"
+#include "stddebug.h"
+#include "debug.h"
+
+/***********************************************************************
+ *           SYNC_BuildWaitStruct
+ */
+static BOOL32 SYNC_BuildWaitStruct( DWORD count, const HANDLE32 *handles,
+                                    BOOL32 wait_all, WAIT_STRUCT *wait )
+{
+    DWORD i;
+    K32OBJ **ptr;
+
+    wait->count    = count;
+    wait->signaled = WAIT_FAILED;
+    wait->wait_all = wait_all;
+    SYSTEM_LOCK();
+    for (i = 0, ptr = wait->objs; i < count; i++, ptr++)
+    {
+        if (!(*ptr = PROCESS_GetObjPtr( handles[i], K32OBJ_UNKNOWN )))
+            break;
+        if (!K32OBJ_OPS( *ptr )->signaled)
+        {
+            /* This object type cannot be waited upon */
+            K32OBJ_DecCount( *ptr );
+            break;
+        }
+
+    }
+    if (i != count)
+    {
+        /* There was an error */
+        while (i--) K32OBJ_DecCount( wait->objs[i] );
+    }
+    SYSTEM_UNLOCK();
+    return (i == count);
+}
+
+
+/***********************************************************************
+ *           SYNC_FreeWaitStruct
+ */
+static void SYNC_FreeWaitStruct( WAIT_STRUCT *wait )
+{
+    DWORD i;
+    K32OBJ **ptr;
+    SYSTEM_LOCK();
+    for (i = 0, ptr = wait->objs; i < wait->count; i++, ptr++)
+        K32OBJ_DecCount( *ptr );
+    SYSTEM_UNLOCK();
+}
+
+
+/***********************************************************************
+ *           SYNC_CheckCondition
+ */
+static BOOL32 SYNC_CheckCondition( WAIT_STRUCT *wait, DWORD thread_id )
+{
+    DWORD i;
+    K32OBJ **ptr;
+
+    SYSTEM_LOCK();
+    if (wait->wait_all)
+    {
+        for (i = 0, ptr = wait->objs; i < wait->count; i++, ptr++)
+        {
+            if (!K32OBJ_OPS( *ptr )->signaled( *ptr, thread_id ))
+            {
+                SYSTEM_UNLOCK();
+                return FALSE;
+            }
+        }
+        /* Wait satisfied: tell it to all objects */
+        wait->signaled = WAIT_OBJECT_0;
+        for (i = 0, ptr = wait->objs; i < wait->count; i++, ptr++)
+            K32OBJ_OPS( *ptr )->satisfied( *ptr, thread_id );
+        SYSTEM_UNLOCK();
+        return TRUE;
+    }
+    else
+    {
+        for (i = 0, ptr = wait->objs; i < wait->count; i++, ptr++)
+        {
+            if (K32OBJ_OPS( *ptr )->signaled( *ptr, thread_id ))
+            {
+                /* Wait satisfied: tell it to the object */
+                wait->signaled = WAIT_OBJECT_0 + i;
+                K32OBJ_OPS( *ptr )->satisfied( *ptr, thread_id );
+                SYSTEM_UNLOCK();
+                return TRUE;
+            }
+        }
+        SYSTEM_UNLOCK();
+        return FALSE;
+    }
+}
+
+
+/***********************************************************************
+ *           SYNC_WaitForCondition
+ */
+void SYNC_WaitForCondition( WAIT_STRUCT *wait, DWORD timeout )
+{
+    DWORD i, thread_id = GetCurrentThreadId();
+    LONG count;
+    K32OBJ **ptr;
+    sigset_t set;
+
+    SYSTEM_LOCK();
+    if (SYNC_CheckCondition( wait, thread_id ))
+        goto done;  /* Condition already satisfied */
+    if (!timeout)
+    {
+        /* No need to wait */
+        wait->signaled = WAIT_TIMEOUT;
+        goto done;
+    }
+
+    /* Add ourselves to the waiting list of all objects */
+
+    for (i = 0, ptr = wait->objs; i < wait->count; i++, ptr++)
+        K32OBJ_OPS( *ptr )->add_wait( *ptr, thread_id );
+
+    /* Release the system lock completely */
+
+    count = SYSTEM_LOCK_COUNT();
+    for (i = count; i > 0; i--) SYSTEM_UNLOCK();
+
+    /* Now wait for it */
+
+    dprintf_win32( stddeb, "SYNC: starting wait (%p %04x)\n",
+                   THREAD_Current(), THREAD_Current()->teb_sel );
+
+    sigprocmask( SIG_SETMASK, NULL, &set );
+    sigdelset( &set, SIGUSR1 );
+    sigdelset( &set, SIGALRM );
+    if (timeout != INFINITE32)
+    {
+        while (wait->signaled == WAIT_FAILED)
+        {
+            struct itimerval timer;
+            DWORD start_ticks, elapsed;
+            timer.it_interval.tv_sec = timer.it_interval.tv_usec = 0;
+            timer.it_value.tv_sec = timeout / 1000;
+            timer.it_value.tv_usec = (timeout % 1000) * 1000;
+            start_ticks = GetTickCount();
+            setitimer( ITIMER_REAL, &timer, NULL );
+            sigsuspend( &set );
+            if (wait->signaled != WAIT_FAILED) break;
+            /* Recompute the timer value */
+            elapsed = GetTickCount() - start_ticks;
+            if (elapsed >= timeout) wait->signaled = WAIT_TIMEOUT;
+            else timeout -= elapsed;
+        }
+    }
+    else
+    {
+        while (wait->signaled == WAIT_FAILED)
+        {
+            sigsuspend( &set );
+        }
+    }
+
+    /* Grab the system lock again */
+
+    while (count--) SYSTEM_LOCK();
+    dprintf_win32( stddeb, "SYNC: wait finished (%p %04x)\n",
+                   THREAD_Current(), THREAD_Current()->teb_sel );
+
+    /* Remove ourselves from the lists */
+
+    for (i = 0, ptr = wait->objs; i < wait->count; i++, ptr++)
+        K32OBJ_OPS( *ptr )->remove_wait( *ptr, thread_id );
+
+done:
+    SYSTEM_UNLOCK();
+}
+
+
+/***********************************************************************
+ *           SYNC_DummySigHandler
+ *
+ * Dummy signal handler
+ */
+static void SYNC_DummySigHandler(void)
+{
+}
+
+
+/***********************************************************************
+ *           SYNC_SetupSignals
+ *
+ * Setup signal handlers for a new thread.
+ * FIXME: should merge with SIGNAL_Init.
+ */
+void SYNC_SetupSignals(void)
+{
+    sigset_t set;
+    SIGNAL_SetHandler( SIGUSR1, SYNC_DummySigHandler, 0 );
+    /* FIXME: conflicts with system timers */
+    SIGNAL_SetHandler( SIGALRM, SYNC_DummySigHandler, 0 );
+    sigemptyset( &set );
+    /* Make sure these are blocked by default */
+    sigaddset( &set, SIGUSR1 );
+    sigaddset( &set, SIGALRM );
+    sigprocmask( SIG_BLOCK , &set, NULL);
+}
+
+
+/***********************************************************************
+ *           SYNC_WakeUp
+ */
+void SYNC_WakeUp( THREAD_QUEUE *wait_queue, DWORD max )
+{
+    THREAD_ENTRY *entry;
+
+    if (!max) max = INFINITE32;
+    SYSTEM_LOCK();
+    if (!*wait_queue)
+    {
+        SYSTEM_UNLOCK();
+        return;
+    }
+    entry = (*wait_queue)->next;
+    for (;;)
+    {
+        THDB *thdb = entry->thread;
+        if (SYNC_CheckCondition( &thdb->wait_struct, THDB_TO_THREAD_ID(thdb) ))
+        {
+            dprintf_win32( stddeb, "SYNC: waking up %04x\n", thdb->teb_sel );
+            kill( thdb->unix_pid, SIGUSR1 );
+            if (!--max) break;
+        }
+        if (entry == *wait_queue) break;
+        entry = entry->next;
+    }
+    SYSTEM_UNLOCK();
+}
+
+
+/***********************************************************************
+ *           WaitForSingleObject   (KERNEL32.723)
+ */
+DWORD WINAPI WaitForSingleObject( HANDLE32 handle, DWORD timeout )
+{
+    return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, FALSE );
+}
+
+
+/***********************************************************************
+ *           WaitForSingleObjectEx   (KERNEL32.724)
+ */
+DWORD WINAPI WaitForSingleObjectEx( HANDLE32 handle, DWORD timeout,
+                                    BOOL32 alertable )
+{
+    return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, alertable );
+}
+
+
+/***********************************************************************
+ *           WaitForMultipleObjects   (KERNEL32.721)
+ */
+DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE32 *handles,
+                                     BOOL32 wait_all, DWORD timeout )
+{
+    return WaitForMultipleObjectsEx(count, handles, wait_all, timeout, FALSE);
+}
+
+
+/***********************************************************************
+ *           WaitForMultipleObjectsEx   (KERNEL32.722)
+ */
+DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE32 *handles,
+                                       BOOL32 wait_all, DWORD timeout,
+                                       BOOL32 alertable )
+{
+    WAIT_STRUCT *wait = &THREAD_Current()->wait_struct;
+
+    if (count > MAXIMUM_WAIT_OBJECTS)
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return WAIT_FAILED;
+    }
+
+    if (alertable)
+        fprintf( stderr,
+                 "WaitForMultipleObjectEx: alertable not implemented\n" );
+
+    SYSTEM_LOCK();
+    if (!SYNC_BuildWaitStruct( count, handles, wait_all, wait ))
+        wait->signaled = WAIT_FAILED;
+    else
+    {
+        /* Now wait for it */
+        SYNC_WaitForCondition( wait, timeout );
+        SYNC_FreeWaitStruct( wait );
+    }
+    SYSTEM_UNLOCK();
+    return wait->signaled;
+}
diff --git a/scheduler/thread.c b/scheduler/thread.c
index 9740086..73959d0 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -6,7 +6,10 @@
 
 #include <assert.h>
 #include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
 #include "thread.h"
+#include "process.h"
 #include "winerror.h"
 #include "heap.h"
 #include "selectors.h"
@@ -15,8 +18,40 @@
 #include "debug.h"
 #include "stddebug.h"
 
-THDB *pCurrentThread = NULL;
-static K32OBJ_LIST THREAD_List;
+#ifdef HAVE_CLONE
+# ifdef HAVE_SCHED_H
+#  include <sched.h>
+# endif
+# ifndef CLONE_VM
+#  define CLONE_VM      0x00000100
+#  define CLONE_FS      0x00000200
+#  define CLONE_FILES   0x00000400
+#  define CLONE_SIGHAND 0x00000800
+#  define CLONE_PID     0x00001000
+/* If we didn't get the flags, we probably didn't get the prototype either */
+extern int clone( int (*fn)(void *arg), void *stack, int flags, void *arg );
+# endif  /* CLONE_VM */
+#endif  /* HAVE_CLONE */
+
+#ifndef __i386__
+THDB *pCurrentThread;
+#endif
+
+static BOOL32 THREAD_Signaled( K32OBJ *obj, DWORD thread_id );
+static void THREAD_Satisfied( K32OBJ *obj, DWORD thread_id );
+static void THREAD_AddWait( K32OBJ *obj, DWORD thread_id );
+static void THREAD_RemoveWait( K32OBJ *obj, DWORD thread_id );
+static void THREAD_Destroy( K32OBJ *obj );
+
+const K32OBJ_OPS THREAD_Ops =
+{
+    THREAD_Signaled,    /* signaled */
+    THREAD_Satisfied,   /* satisfied */
+    THREAD_AddWait,     /* add_wait */
+    THREAD_RemoveWait,  /* remove_wait */
+    THREAD_Destroy      /* destroy */
+};
+
 
 /***********************************************************************
  *           THREAD_GetPtr
@@ -38,6 +73,28 @@
 }
 
 
+/**********************************************************************
+ *           NtCurrentTeb   (NTDLL.89)
+ */
+TEB * WINAPI NtCurrentTeb(void)
+{
+#ifdef __i386__
+    TEB *teb;
+    WORD ds, fs;
+
+    /* Check if we have a current thread */
+    GET_DS( ds );
+    GET_FS( fs );
+    if (fs == ds) return NULL; /* FIXME: should be an assert */
+    __asm__( "movl %%fs:(24),%0" : "=r" (teb) );
+    return teb;
+#else
+    if (!pCurrentThread) return NULL;
+    return &pCurrentThread->teb;
+#endif  /* __i386__ */
+}
+
+
 /***********************************************************************
  *           THREAD_Current
  *
@@ -45,9 +102,62 @@
  */
 THDB *THREAD_Current(void)
 {
-    /* FIXME: should probably use %fs register here */
-    assert( pCurrentThread );
-    return pCurrentThread;
+    TEB *teb = NtCurrentTeb();
+    if (!teb) return NULL;
+    return (THDB *)((char *)teb - (int)&((THDB *)0)->teb);
+}
+
+
+/***********************************************************************
+ *           THREAD_AddQueue
+ *
+ * Add a thread to a queue.
+ */
+void THREAD_AddQueue( THREAD_QUEUE *queue, THDB *thread )
+{
+    THREAD_ENTRY *entry = HeapAlloc( SystemHeap, HEAP_NO_SERIALIZE,
+                                     sizeof(*entry) );
+    assert(entry);
+    SYSTEM_LOCK();
+    entry->thread = thread;
+    if (*queue)
+    {
+        entry->next = (*queue)->next;
+        (*queue)->next = entry;
+    }
+    else entry->next = entry;
+    *queue = entry;
+    SYSTEM_UNLOCK();
+}
+
+/***********************************************************************
+ *           THREAD_RemoveQueue
+ *
+ * Remove a thread from a queue.
+ */
+void THREAD_RemoveQueue( THREAD_QUEUE *queue, THDB *thread )
+{
+    THREAD_ENTRY *entry = *queue;
+    SYSTEM_LOCK();
+    if (entry->next == entry)  /* Only one element in the queue */
+    {
+        assert( entry->thread == thread );
+        *queue = NULL;
+    }
+    else
+    {
+        THREAD_ENTRY *next;
+        while (entry->next->thread != thread)
+        {
+            entry = entry->next;
+            assert( entry != *queue );  /* Have we come all the way around? */
+        }
+        if ((next = entry->next) == *queue) *queue = entry;
+        entry->next = entry->next->next;
+        entry = next;  /* This is the one we want to free */
+    }
+    HeapFree( SystemHeap, 0, entry );
+    SYSTEM_UNLOCK();
 }
 
 
@@ -55,10 +165,11 @@
  *           THREAD_Create
  */
 THDB *THREAD_Create( PDB32 *pdb, DWORD stack_size,
-                     LPTHREAD_START_ROUTINE start_addr )
+                     LPTHREAD_START_ROUTINE start_addr, LPVOID param )
 {
     DWORD old_prot;
     WORD cs, ds;
+
     THDB *thdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(THDB) );
     if (!thdb) return NULL;
     thdb->header.type     = K32OBJ_THREAD;
@@ -69,8 +180,11 @@
     thdb->teb.stack_sel   = 0; /* FIXME */
     thdb->teb.self        = &thdb->teb;
     thdb->teb.tls_ptr     = thdb->tls_array;
+    thdb->wait_list       = &thdb->wait_struct;
     thdb->process2        = pdb;
     thdb->exit_code       = 0x103; /* STILL_ACTIVE */
+    thdb->entry_point     = start_addr;
+    thdb->entry_arg       = param;
 
     /* Allocate the stack */
 
@@ -91,6 +205,10 @@
                                          TRUE, FALSE );
     if (!thdb->teb_sel) goto error;
 
+    /* Allocate the event */
+
+    if (!(thdb->event = EVENT_Create( TRUE, FALSE ))) goto error;
+
     /* Initialize the thread context */
 
     GET_CS(cs);
@@ -104,14 +222,10 @@
     thdb->context.SegFs   = thdb->teb_sel;
     thdb->context.Eip     = (DWORD)start_addr;
     thdb->context.Esp     = (DWORD)thdb->teb.stack_top;
-
-    /* Add the thread to the linked list */
-
-    K32OBJ_AddTail( &THREAD_List, &thdb->header );
-
     return thdb;
 
 error:
+    if (thdb->event) K32OBJ_DecCount( thdb->event );
     if (thdb->teb_sel) SELECTOR_FreeBlock( thdb->teb_sel, 1 );
     if (thdb->stack_base) VirtualFree( thdb->stack_base, 0, MEM_RELEASE );
     HeapFree( SystemHeap, 0, thdb );
@@ -120,18 +234,79 @@
 
 
 /***********************************************************************
+ *           THREAD_Start
+ *
+ * Startup routine for a new thread.
+ */
+static void THREAD_Start( THDB *thdb )
+{
+    LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)thdb->entry_point;
+    thdb->unix_pid = getpid();
+    SET_FS( thdb->teb_sel );
+    ExitThread( func( thdb->entry_arg ) );
+}
+
+
+/***********************************************************************
+ *           THREAD_Signaled
+ */
+static BOOL32 THREAD_Signaled( K32OBJ *obj, DWORD thread_id )
+{
+    THDB *thdb = (THDB *)obj;
+    assert( obj->type == K32OBJ_THREAD );
+    return K32OBJ_OPS( thdb->event )->signaled( thdb->event, thread_id );
+}
+
+
+/***********************************************************************
+ *           THREAD_Satisfied
+ *
+ * Wait on this object has been satisfied.
+ */
+static void THREAD_Satisfied( K32OBJ *obj, DWORD thread_id )
+{
+    THDB *thdb = (THDB *)obj;
+    assert( obj->type == K32OBJ_THREAD );
+    return K32OBJ_OPS( thdb->event )->satisfied( thdb->event, thread_id );
+}
+
+
+/***********************************************************************
+ *           THREAD_AddWait
+ *
+ * Add thread to object wait queue.
+ */
+static void THREAD_AddWait( K32OBJ *obj, DWORD thread_id )
+{
+    THDB *thdb = (THDB *)obj;
+    assert( obj->type == K32OBJ_THREAD );
+    return K32OBJ_OPS( thdb->event )->add_wait( thdb->event, thread_id );
+}
+
+
+/***********************************************************************
+ *           THREAD_RemoveWait
+ *
+ * Remove thread from object wait queue.
+ */
+static void THREAD_RemoveWait( K32OBJ *obj, DWORD thread_id )
+{
+    THDB *thdb = (THDB *)obj;
+    assert( obj->type == K32OBJ_THREAD );
+    return K32OBJ_OPS( thdb->event )->remove_wait( thdb->event, thread_id );
+}
+
+
+/***********************************************************************
  *           THREAD_Destroy
  */
-void THREAD_Destroy( K32OBJ *ptr )
+static void THREAD_Destroy( K32OBJ *ptr )
 {
     THDB *thdb = (THDB *)ptr;
 
     assert( ptr->type == K32OBJ_THREAD );
     ptr->type = K32OBJ_UNKNOWN;
 
-    /* Note: when we get here, the thread has already been removed */
-    /* from the thread list */
-
     /* Free the associated memory */
 
 #ifdef __i386__
@@ -146,6 +321,7 @@
         }
     }
 #endif
+    K32OBJ_DecCount( thdb->event );
     SELECTOR_FreeBlock( thdb->teb_sel, 1 );
     HeapFree( SystemHeap, 0, thdb );
 
@@ -153,54 +329,57 @@
 
 
 /***********************************************************************
- *           THREAD_SwitchThread
- *
- * Return the thread we want to switch to, and switch the contexts.
- */
-THDB *THREAD_SwitchThread( CONTEXT *context )
-{
-    K32OBJ *cur;
-    THDB *next;
-    if (!pCurrentThread) return NULL;
-    cur = K32OBJ_RemoveHead( &THREAD_List );
-    K32OBJ_AddTail( &THREAD_List, cur );
-    K32OBJ_DecCount( cur );
-    next = (THDB *)THREAD_List.head;
-    if (next != pCurrentThread)
-    {
-        pCurrentThread->context = *context;
-        pCurrentThread = next;
-        *context = pCurrentThread->context;
-    }
-    return pCurrentThread;
-}
-
-
-/***********************************************************************
  *           CreateThread   (KERNEL32.63)
- *
- * The only thing missing here is actually getting the thread to run ;-)
  */
 HANDLE32 WINAPI CreateThread( LPSECURITY_ATTRIBUTES attribs, DWORD stack,
                               LPTHREAD_START_ROUTINE start, LPVOID param,
                               DWORD flags, LPDWORD id )
 {
     HANDLE32 handle;
-    THDB *thread = THREAD_Create( pCurrentProcess, stack, start );
+    THDB *thread = THREAD_Create( pCurrentProcess, stack, start, param );
     if (!thread) return INVALID_HANDLE_VALUE32;
     handle = PROCESS_AllocHandle( &thread->header, 0 );
     if (handle == INVALID_HANDLE_VALUE32)
     {
-        THREAD_Destroy( &thread->header );
+        K32OBJ_DecCount( &thread->header );
         return INVALID_HANDLE_VALUE32;
     }
-    *id = (DWORD)thread;
+#ifdef HAVE_CLONE
+    if (clone( (int (*)(void *))THREAD_Start, thread->teb.stack_top,
+               CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, thread ) < 0)
+    {
+        K32OBJ_DecCount( &thread->header );
+        return INVALID_HANDLE_VALUE32;
+    }
+#else
     fprintf( stderr, "CreateThread: stub\n" );
+#endif  /* __linux__ */
+    *id = THDB_TO_THREAD_ID( thread );
     return handle;
 }
 
 
 /***********************************************************************
+ *           ExitThread   (KERNEL32.215)
+ */
+void WINAPI ExitThread( DWORD code )
+{
+    THDB *thdb = THREAD_Current();
+    LONG count;
+
+    SYSTEM_LOCK();
+    thdb->exit_code = code;
+    EVENT_Set( thdb->event );
+    /* FIXME: should free the stack somehow */
+    K32OBJ_DecCount( &thdb->header );
+    /* Completely unlock the system lock just in case */
+    count = SYSTEM_LOCK_COUNT();
+    while (count--) SYSTEM_UNLOCK();
+    _exit( 0 );
+}
+
+
+/***********************************************************************
  *           GetCurrentThread   (KERNEL32.200)
  */
 HANDLE32 WINAPI GetCurrentThread(void)
@@ -211,11 +390,10 @@
 
 /***********************************************************************
  *           GetCurrentThreadId   (KERNEL32.201)
- * Returns crypted (xor'ed) pointer to THDB in Win95.
  */
 DWORD WINAPI GetCurrentThreadId(void)
 {
-    return (DWORD)THREAD_Current();
+    return THDB_TO_THREAD_ID( THREAD_Current() );
 }
 
 
@@ -234,10 +412,9 @@
  */
 void WINAPI SetLastError( DWORD error )
 {
-    THDB *thread;
-    if (!pCurrentThread) return;  /* FIXME */
-    thread = THREAD_Current();
-    thread->last_error = error;
+    THDB *thread = THREAD_Current();
+    /* This one must work before we have a thread (FIXME) */
+    if (thread) thread->last_error = error;
 }
 
 
@@ -354,15 +531,6 @@
 
 
 /**********************************************************************
- *           NtCurrentTeb   (NTDLL.89)
- */
-void WINAPI NtCurrentTeb( CONTEXT *context )
-{
-    EAX_reg(context) = GetSelectorBase( FS_reg(context) );
-}
-
-
-/**********************************************************************
  *           GetThreadPriority   (KERNEL32.296)
  */
 INT32 WINAPI GetThreadPriority(HANDLE32 hthread)
@@ -393,9 +561,9 @@
 /**********************************************************************
  *           TerminateThread   (KERNEL32)
  */
-BOOL32 WINAPI TerminateThread(DWORD threadid,DWORD exitcode)
+BOOL32 WINAPI TerminateThread(HANDLE32 handle,DWORD exitcode)
 {
-    fprintf(stdnimp,"TerminateThread(0x%08lx,%ld), STUB!\n",threadid,exitcode);
+    fprintf(stdnimp,"TerminateThread(0x%08x,%ld), STUB!\n",handle,exitcode);
     return TRUE;
 }
 
@@ -415,17 +583,17 @@
 /**********************************************************************
  *           ResumeThread   (KERNEL32)
  */
-BOOL32 WINAPI ResumeThread(DWORD threadid)
+BOOL32 WINAPI ResumeThread( HANDLE32 handle )
 {
-    fprintf(stdnimp,"ResumeThread(0x%08lx), STUB!\n",threadid);
+    fprintf(stdnimp,"ResumeThread(0x%08x), STUB!\n",handle);
     return TRUE;
 }
 
 /**********************************************************************
  *           SuspendThread   (KERNEL32)
  */
-BOOL32 WINAPI SuspendThread(DWORD threadid)
+BOOL32 WINAPI SuspendThread( HANDLE32 handle )
 {
-    fprintf(stdnimp,"SuspendThread(0x%08lx), STUB!\n",threadid);
+    fprintf(stdnimp,"SuspendThread(0x%08x), STUB!\n",handle);
     return TRUE;
 }
diff --git a/tools/build.c b/tools/build.c
index c692a41..ad4db74 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -1240,7 +1240,7 @@
     /* Output the DLL descriptor */
 
     fprintf( outfile, "\t.text\n" );
-    fprintf( outfile, "DLLName:\t.ascii \"%s\\0\"\n", DLLName );
+    fprintf( outfile, "DLLName:\t.string \"%s\\0\"\n", DLLName );
     fprintf( outfile, "\t.align 4\n" );
     fprintf( outfile, "\t.globl " PREFIX "%s_Descriptor\n", DLLName );
     fprintf( outfile, PREFIX "%s_Descriptor:\n", DLLName );
@@ -1459,9 +1459,9 @@
              CONTEXTOFFSET(SegCs) - sizeof(CONTEXT) );
     fprintf( outfile, "\tpushw %d(%%ebx)\n",  /* Push new ip */
              CONTEXTOFFSET(Eip) - sizeof(CONTEXT) );
-    fprintf( outfile, "\tpushw %d(%%ebx)\n",  /* Push new ds */
+    fprintf( outfile, "\tpushl %d(%%ebx)\n",  /* Push new ds */
              CONTEXTOFFSET(SegDs) - sizeof(CONTEXT) );
-    fprintf( outfile, "\tpushw %d(%%ebx)\n",  /* Push new es */
+    fprintf( outfile, "\tpushl %d(%%ebx)\n",  /* Push new es */
              CONTEXTOFFSET(SegEs) - sizeof(CONTEXT) );
     fprintf( outfile, "\tpushl %d(%%ebx)\n",
              CONTEXTOFFSET(EFlags) - sizeof(CONTEXT) );
@@ -1470,8 +1470,8 @@
              CONTEXTOFFSET(Eax) - sizeof(CONTEXT) );
     fprintf( outfile, "\tmovl %d(%%ebx),%%ebx\n",
              CONTEXTOFFSET(Ebx) - sizeof(CONTEXT) );
-    fprintf( outfile, "\tpopw %%es\n" );  /* Set es */
-    fprintf( outfile, "\tpopw %%ds\n" );  /* Set ds */
+    fprintf( outfile, "\tpopl %%es\n" );  /* Set es */
+    fprintf( outfile, "\tpopl %%ds\n" );  /* Set ds */
 }
 
 
@@ -1547,8 +1547,8 @@
     /* Restore 32-bit ds and es */
 
     fprintf( outfile, "\tpushl $0x%04x%04x\n", Data_Selector, Data_Selector );
-    fprintf( outfile, "\tpopw %%ds\n" );
-    fprintf( outfile, "\tpopw %%es\n" );
+    fprintf( outfile, "\t.byte 0x66\n\tpopl %%ds\n" );
+    fprintf( outfile, "\t.byte 0x66\n\tpopl %%es\n" );
 
 
     /* Save the 16-bit stack */
@@ -1577,8 +1577,8 @@
     /* Switch to the 32-bit stack */
 
     fprintf( outfile, "\tmovl " PREFIX "CALLTO16_Saved32_esp,%%ebp\n" );
-    fprintf( outfile, "\tpushw %%ds\n" );
-    fprintf( outfile, "\tpopw %%ss\n" );
+    fprintf( outfile, "\tpushl %%ds\n" );
+    fprintf( outfile, "\tpopl %%ss\n" );
     fprintf( outfile, "\tleal -%d(%%ebp),%%esp\n",
              reg_func ? sizeof(CONTEXT) : 4 * strlen(args) );
     if (reg_func)  /* Push the address of the context struct */
@@ -1603,7 +1603,7 @@
 
     /* Call the entry point */
 
-    fprintf( outfile, "\tcall %%eax\n" );
+    fprintf( outfile, "\tcall *%%eax\n" );
 
     /* Print the debug information after the call */
 
@@ -1675,7 +1675,7 @@
         fprintf( outfile, "\tincl %%esp\n" );
         fprintf( outfile, "\tpopl %%edx\n" );      /* Remove cs and ds */
         fprintf( outfile, "\tmovw %%dx,%%ds\n" );  /* and restore ds */
-        fprintf( outfile, "\tpopw %%es\n" );       /* Restore es */
+        fprintf( outfile, "\t.byte 0x66\n\tpopl %%es\n" );       /* Restore es */
 
         if (short_ret) fprintf( outfile, "\tpopl %%edx\n" );  /* Restore edx */
         else
@@ -1757,8 +1757,7 @@
 
     /* Call the actual CallTo16 routine (simulate a lcall) */
 
-    fprintf( outfile, "\tpushw $0\n" );
-    fprintf( outfile, "\tpushw %%cs\n" );
+    fprintf( outfile, "\tpushl %%cs\n" );
     fprintf( outfile, "\tcall do_callto16_%s\n", profile );
 
     /* Exit code */
@@ -1850,10 +1849,10 @@
 
         /* Get the 16-bit ds */
 
-        fprintf( outfile, "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(SegDs) );
+        fprintf( outfile, "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegDs) );
         /* Get ebx from the 32-bit stack */
         fprintf( outfile, "\tmovl %d(%%ebx),%%ebx\n", CONTEXTOFFSET(Ebx) );
-        fprintf( outfile, "\tpopw %%ds\n" );
+        fprintf( outfile, "\tpopl %%ds\n" );
     }
     else  /* not a register function */
     {
@@ -2046,7 +2045,7 @@
     /* Transfer the argument and call the function */
 
     fprintf( outfile, "\tpushl 12(%%ebp)\n" );
-    fprintf( outfile, "\tcall 8(%%ebp)\n" );
+    fprintf( outfile, "\tcall *8(%%ebp)\n" );
 
     /* Restore registers and return */
 
@@ -2088,11 +2087,11 @@
     /* Build the context structure */
 
     fprintf( outfile, "\tpushw $0\n" );
-    fprintf( outfile, "\tpushw %%ss\n" );
+    fprintf( outfile, "\t.byte 0x66\n\tpushl %%ss\n" );
     fprintf( outfile, "\tpushl %%eax\n" );  /* %esp place holder */
     fprintf( outfile, "\tpushfl\n" );
     fprintf( outfile, "\tpushw $0\n" );
-    fprintf( outfile, "\tpushw %%cs\n" );
+    fprintf( outfile, "\t.byte 0x66\n\tpushl %%cs\n" );
     fprintf( outfile, "\tpushl 20(%%esp)\n" );  /* %eip at time of call */
     fprintf( outfile, "\tpushl %%ebp\n" );
 
@@ -2218,7 +2217,7 @@
         for (i = 2; i < argc; i++)
         {
             fprintf( outfile, "Profile_%s:\n", argv[i] );
-            fprintf( outfile, "\t.ascii \"%s\\0\"\n", argv[i] + 5 );
+            fprintf( outfile, "\t.string \"%s\\0\"\n", argv[i] + 5 );
         }
     }
 
diff --git a/tools/fnt2bdf.c b/tools/fnt2bdf.c
index d994a99..80537be 100644
--- a/tools/fnt2bdf.c
+++ b/tools/fnt2bdf.c
@@ -191,7 +191,8 @@
       return ERROR_FILE;
     }
 
-    dump_bdf_hdr(fp, cpe_font_struct, file_buffer);
+    ic = dump_bdf_hdr(fp, cpe_font_struct, file_buffer);
+    if (ic) return (ic);
 
     /* NOW, convert all chars to UNIX (lton) notation... */
 
@@ -563,47 +564,66 @@
 		    if( !(lpfont = (unsigned char*) realloc( lpfont, length )) )
 		    {
 			fprintf(stderr, errorMemory );
-			free(lpdata);
-			return -1;
+			exit(1);
 		    }
 
 		    lseek( fd, offset, SEEK_SET );
 		    if( read(fd, lpfont, length) != length )
 		    {
 			fprintf(stderr, errorDLLRead );
-			free(lpdata); free(lpfont);
-			return -1;
+			exit(1);
 		    }
 
 		    if( (i = parse_fnt_data( lpfont, length )) )
+		    {
 			fprintf(stderr, "%s%d\n", errorFontData, i );
+			exit(1);
+		    }
 		 }
 		 free(lpfont); free(lpdata);
-		 return 0;
+		 exit(0);
 	       }
-	       else fprintf(stderr, errorEmpty );
+	       else
+	       {
+		 fprintf(stderr, errorEmpty );
+		 exit(1);
+	       }
 	       free( lpdata );
 	     }
-	     else fprintf(stderr, errorDLLRead);
+	     else
+	     {
+	       fprintf(stderr, errorDLLRead);
+	       exit(1);
+	     }
 	     break;
 
 	case FILE_FNT:
 	     if( lpdata )
 	     {
 	       if( (i = parse_fnt_data( lpdata, file_stat.st_size )) )
+	       {
 		   fprintf(stderr, "%s%d\n", errorFontData, i );
-
+		   exit(1);
+	       }
 	       free( lpdata );
 	     }
-	     else fprintf(stderr, errorFNTRead);
+	     else
+	     {
+	       fprintf(stderr, errorFNTRead);
+	       exit(1);
+	     }
 	     break;
 
 	case FILE_ERROR:
 	     fprintf(stderr, errorFile );
- 
+	     exit(1);
     }
     close(fd);
+    exit(0);
   }
-  else fprintf(stderr, errorOpenFile );
-  return -1;
+  else
+  {
+    fprintf(stderr, errorOpenFile );
+    exit(1);
+  }
 }
diff --git a/win32/Makefile.in b/win32/Makefile.in
index 7c683e1..b9acdb9 100644
--- a/win32/Makefile.in
+++ b/win32/Makefile.in
@@ -14,7 +14,6 @@
 	except.c \
 	file.c \
 	init.c \
-	k32obj.c \
 	kernel32.c \
 	newfns.c \
 	ordinals.c \
diff --git a/win32/file.c b/win32/file.c
index a0d9ab9..f634dce 100644
--- a/win32/file.c
+++ b/win32/file.c
@@ -19,7 +19,6 @@
 #include "winerror.h"
 #include "file.h"
 #include "heap.h"
-#include "handle32.h"
 #include "stddebug.h"
 #define DEBUG_WIN32
 #include "debug.h"
diff --git a/win32/init.c b/win32/init.c
index 0e19a1e..50a44cd 100644
--- a/win32/init.c
+++ b/win32/init.c
@@ -10,7 +10,6 @@
 #include <stdlib.h>
 #include "windows.h"
 #include "winerror.h"
-#include "handle32.h"
 #include "except.h"
 #include "heap.h"
 #include "task.h"
diff --git a/win32/k32obj.c b/win32/k32obj.c
deleted file mode 100644
index 9eb1b8c..0000000
--- a/win32/k32obj.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * KERNEL32 objects
- *
- * Copyright 1996 Alexandre Julliard
- */
-
-#include <assert.h>
-#include "winerror.h"
-#include "handle32.h"
-#include "heap.h"
-#include "file.h"
-#include "process.h"
-#include "thread.h"
-
-typedef void (*destroy_object)(K32OBJ *);
-
-extern void VIRTUAL_DestroyMapping( K32OBJ *obj );
-
-static const destroy_object K32OBJ_Destroy[K32OBJ_NBOBJECTS] =
-{
-    NULL,
-    NULL,                     /* K32OBJ_SEMAPHORE */
-    NULL,                     /* K32OBJ_EVENT */
-    NULL,                     /* K32OBJ_MUTEX */
-    NULL,                     /* K32OBJ_CRITICAL_SECTION */
-    PROCESS_Destroy,          /* K32OBJ_PROCESS */
-    THREAD_Destroy,           /* K32OBJ_THREAD */
-    FILE_Destroy,             /* K32OBJ_FILE */
-    NULL,                     /* K32OBJ_CHANGE */
-    NULL,                     /* K32OBJ_CONSOLE */
-    NULL,                     /* K32OBJ_SCREEN_BUFFER */
-    VIRTUAL_DestroyMapping,   /* K32OBJ_MEM_MAPPED_FILE */
-    NULL,                     /* K32OBJ_SERIAL */
-    NULL,                     /* K32OBJ_DEVICE_IOCTL */
-    NULL,                     /* K32OBJ_PIPE */
-    NULL,                     /* K32OBJ_MAILSLOT */
-    NULL,                     /* K32OBJ_TOOLHELP_SNAPSHOT */
-    NULL                      /* K32OBJ_SOCKET */
-};
-
-typedef struct _NE
-{
-    struct _NE *next;
-    K32OBJ     *obj;
-    UINT32      len;
-    char        name[1];
-} NAME_ENTRY;
-
-static NAME_ENTRY *K32OBJ_FirstEntry = NULL;
-
-
-/***********************************************************************
- *           K32OBJ_IncCount
- */
-void K32OBJ_IncCount( K32OBJ *ptr )
-{
-    /* FIXME: not atomic */
-    assert( ptr->type && ((unsigned)ptr->type < K32OBJ_NBOBJECTS) );
-    ptr->refcount++;
-}
-
-
-/***********************************************************************
- *           K32OBJ_DecCount
- */
-void K32OBJ_DecCount( K32OBJ *ptr )
-{
-    NAME_ENTRY **pptr;
-
-    /* FIXME: not atomic */
-    assert( ptr->type && ((unsigned)ptr->type < K32OBJ_NBOBJECTS) );
-    assert( ptr->refcount );
-    if (--ptr->refcount) return;
-
-    /* Check if the object has a name entry and free it */
-
-    pptr = &K32OBJ_FirstEntry;
-    while (*pptr && ((*pptr)->obj != ptr)) pptr = &(*pptr)->next;
-    if (*pptr)
-    {
-        NAME_ENTRY *entry = *pptr;
-        *pptr = entry->next;
-        HeapFree( SystemHeap, 0, entry );
-    }
-
-    /* Free the object */
-
-    if (K32OBJ_Destroy[ptr->type]) K32OBJ_Destroy[ptr->type]( ptr );
-}
-
-
-/***********************************************************************
- *           K32OBJ_AddHead
- *
- * Add an object at the head of the list and increment its ref count.
- */
-void K32OBJ_AddHead( K32OBJ_LIST *list, K32OBJ *ptr )
-{
-    K32OBJ_ENTRY *entry = HeapAlloc( SystemHeap, 0, sizeof(*entry) );
-    assert(entry);
-    K32OBJ_IncCount( ptr );
-    entry->obj = ptr;
-    if ((entry->next = list->head) != NULL) entry->next->prev = entry;
-    else list->tail = entry;
-    entry->prev = NULL;
-    list->head = entry;
-}
-
-
-/***********************************************************************
- *           K32OBJ_AddTail
- *
- * Add an object at the tail of the list and increment its ref count.
- */
-void K32OBJ_AddTail( K32OBJ_LIST *list, K32OBJ *ptr )
-{
-    K32OBJ_ENTRY *entry = HeapAlloc( SystemHeap, 0, sizeof(*entry) );
-    assert(entry);
-    K32OBJ_IncCount( ptr );
-    entry->obj = ptr;
-    if ((entry->prev = list->tail) != NULL) entry->prev->next = entry;
-    else list->head = entry;
-    entry->next = NULL;
-    list->tail = entry;
-}
-
-
-/***********************************************************************
- *           K32OBJ_Remove
- *
- * Remove an object from the list and decrement its ref count.
- */
-void K32OBJ_Remove( K32OBJ_LIST *list, K32OBJ *ptr )
-{
-    K32OBJ_ENTRY *entry = list->head;
-    while ((entry && (entry->obj != ptr))) entry = entry->next;
-    assert(entry);
-    if (entry->next) entry->next->prev = entry->prev;
-    else list->tail = entry->prev;
-    if (entry->prev) entry->prev->next = entry->next;
-    else list->head = entry->next;
-    HeapFree( SystemHeap, 0, entry );
-    K32OBJ_DecCount( ptr );
-}
-
-
-/***********************************************************************
- *           K32OBJ_RemoveHead
- *
- * Remove the head of the list; its ref count is NOT decremented.
- */
-K32OBJ *K32OBJ_RemoveHead( K32OBJ_LIST *list )
-{
-    K32OBJ *ptr;
-    K32OBJ_ENTRY *entry = list->head;
-    assert(entry);
-    assert(!entry->prev);
-    if ((list->head = entry->next) != NULL) entry->next->prev = NULL;
-    else list->tail = NULL;
-    ptr = entry->obj;
-    HeapFree( SystemHeap, 0, entry );
-    return ptr;
-}
-
-
-/***********************************************************************
- *           K32OBJ_AddName
- *
- * Add a name entry for an object. We don't check for duplicates here.
- * FIXME: should use some sort of hashing.
- */
-BOOL32 K32OBJ_AddName( K32OBJ *obj, LPCSTR name )
-{
-    NAME_ENTRY *entry;
-    UINT32 len = strlen( name );
-
-    if (!(entry = HeapAlloc( SystemHeap, 0, sizeof(NAME_ENTRY) + len )))
-    {
-        SetLastError( ERROR_OUTOFMEMORY );
-        return FALSE;
-    }
-    entry->next = K32OBJ_FirstEntry;
-    entry->obj = obj;
-    lstrcpy32A( entry->name, name );
-    K32OBJ_FirstEntry = entry;
-    return TRUE;
-}
-
-
-/***********************************************************************
- *           K32OBJ_FindName
- *
- * Find the object referenced by a given name.
- * The reference count is not incremented.
- */
-K32OBJ *K32OBJ_FindName( LPCSTR name )
-{
-    NAME_ENTRY *entry = K32OBJ_FirstEntry;
-    UINT32 len;
-
-    if (!name) return NULL;  /* Anonymous object */
-    len = strlen( name );
-    while (entry)
-    {
-        if ((len == entry->len) && !lstrcmp32A( name, entry->name))
-            return entry->obj;
-        entry = entry->next;
-    }
-    return NULL;
-}
-
-
-/***********************************************************************
- *           K32OBJ_FindNameType
- *
- * Find an object by name and check its type.
- * The reference count is not incremented.
- */
-K32OBJ *K32OBJ_FindNameType( LPCSTR name, K32OBJ_TYPE type )
-{
-    K32OBJ *obj = K32OBJ_FindName( name );
-    if (!obj) return NULL;
-    if (obj->type == type) return obj;
-    SetLastError( ERROR_DUP_NAME );
-    return NULL;
-}
diff --git a/win32/kernel32.c b/win32/kernel32.c
index a53e04e..0a651c7 100644
--- a/win32/kernel32.c
+++ b/win32/kernel32.c
@@ -12,6 +12,7 @@
 #include "user.h"
 #include "heap.h"
 #include "module.h"
+#include "process.h"
 #include "stackframe.h"
 #include "selectors.h"
 #include "task.h"
@@ -568,7 +569,7 @@
 	*x++=0x66;*x++=0x52;				/* pushl edx */
 	*x++=0xea;*(DWORD*)x=callback;x+=4;		/* jmpf callback */
 
-	*(DWORD*)(thunk+18) = GetCurrentProcessId();
+	*(PDB32**)(thunk+18) = pCurrentProcess;
 
 	sel = SELECTOR_AllocBlock( thunk , 32, SEGMENT_CODE, FALSE, FALSE );
 	return (sel<<16)|0;
diff --git a/win32/ordinals.c b/win32/ordinals.c
index 10af63b..56d2f9f 100644
--- a/win32/ordinals.c
+++ b/win32/ordinals.c
@@ -11,6 +11,7 @@
 #include "selectors.h"
 #include "miscemu.h"
 #include "winnt.h"
+#include "process.h"
 #include "module.h"
 #include "callback.h"
 #include "debug.h"
@@ -75,7 +76,7 @@
 			return 0;
 		return pTask->version;
 	case 16:/* return uncrypted pointer to current thread */
-		return (DWORD)pCurrentThread;
+		return (DWORD)THREAD_Current();
 	case 20:/* return uncrypted pointer to process */
 		return (DWORD)process;
 	case 24:/* return stdoutput handle from startupinfo */
diff --git a/win32/process.c b/win32/process.c
index fd7d102..a0085c9 100644
--- a/win32/process.c
+++ b/win32/process.c
@@ -12,332 +12,12 @@
 #include "winerror.h"
 #include "heap.h"
 #include "thread.h"
-#include "handle32.h"
+#include "process.h"
 #include "pe_image.h"
 #include "file.h"
 #include "stddebug.h"
 #include "debug.h"
 
-typedef struct {
-	K32OBJ	header;
-	DWORD	maxcount;
-	DWORD	count;
-	DWORD	initial;
-} K32SEMAPHORE;
-
-typedef struct {
-	K32OBJ	header;
-	THDB	*owning_thread; /* we are locked by this thread */
-} K32MUTEX;
-
-typedef struct {
-	K32OBJ	header;
-} K32EVENT;
-
-/***********************************************************************
- *           CreateMutexA    (KERNEL32.52)
- */
-HANDLE32 WINAPI CreateMutex32A(SECURITY_ATTRIBUTES *sa,BOOL32 on,LPCSTR name)
-{
-	K32MUTEX	*mut;
-	HANDLE32	handle;
-	K32OBJ 		*obj = K32OBJ_FindName( name );
-
-	if (obj) {
-		if (obj->type == K32OBJ_MUTEX) {
-			SetLastError( ERROR_ALREADY_EXISTS );
-			return PROCESS_AllocHandle( obj,0 );
-		}
-		SetLastError( ERROR_DUP_NAME );
-		return 0;
-	}
-	mut = (K32MUTEX*)HeapAlloc(GetProcessHeap(),0,sizeof(K32MUTEX));
-	mut->header.type = K32OBJ_MUTEX;
-	mut->header.refcount  = 1;
-	mut->owning_thread = NULL;
-	if (name)
-		K32OBJ_AddName(&(mut->header),name);
-	handle = PROCESS_AllocHandle(&(mut->header),0);
-	if (handle != INVALID_HANDLE_VALUE32) {
-		if (on)
-			mut->owning_thread = (THDB *)GetCurrentThreadId();
-		return handle;
-	}
-	K32OBJ_DecCount(&(mut->header)); /* also frees name */
-	HeapFree(GetProcessHeap(),0,mut);
-	return 0;
-}
-
-/***********************************************************************
- *           CreateMutexW    (KERNEL32.53)
- */
-HANDLE32 WINAPI CreateMutex32W(SECURITY_ATTRIBUTES *sa, BOOL32 on, LPCWSTR a)
-{
-	LPSTR		name = a?HEAP_strdupWtoA(GetProcessHeap(),0,a):NULL;
-	HANDLE32	ret;
-
-	ret = CreateMutex32A(sa,on,name);
-	if (name) HeapFree(GetProcessHeap(),0,name);
-	return ret;
-}
-
-/***********************************************************************
- *           CreateSemaphoreA    (KERNEL32.60)
- */
-HANDLE32 WINAPI CreateSemaphore32A( LPSECURITY_ATTRIBUTES sa,
-                                    LONG initial,LONG max,LPCSTR name )
-{
-	K32SEMAPHORE	*sem;
-	HANDLE32	handle;
-	K32OBJ 		*obj = K32OBJ_FindName( name );
-
-	if (obj) {
-		if (obj->type == K32OBJ_SEMAPHORE) {
-			SetLastError( ERROR_ALREADY_EXISTS );
-			return PROCESS_AllocHandle( obj,0 );
-		}
-		SetLastError( ERROR_DUP_NAME );
-		return 0;
-	}
-	sem = (K32SEMAPHORE*)HeapAlloc(GetProcessHeap(),0,sizeof(K32SEMAPHORE));
-	sem->header.type = K32OBJ_SEMAPHORE;
-	sem->header.refcount  = 1;
-
-	sem->maxcount 	= max;
-	sem->count	= initial;
-	sem->initial	= initial;
-	if (name)
-		K32OBJ_AddName(&(sem->header),name);
-	handle = PROCESS_AllocHandle(&(sem->header),0);
-	if (handle != INVALID_HANDLE_VALUE32)
-		return handle;
-	K32OBJ_DecCount(&(sem->header)); /* also frees name */
-	HeapFree(GetProcessHeap(),0,sem);
-	return 0;
-}
-
-/***********************************************************************
- *           CreateSemaphoreW    (KERNEL32.61)
- */
-HANDLE32 WINAPI CreateSemaphore32W(SECURITY_ATTRIBUTES *sa,LONG initial,LONG max,LPCWSTR a)
-{
-	LPSTR		name =a?HEAP_strdupWtoA(GetProcessHeap(),0,a):NULL;
-	HANDLE32	ret;
-
-	ret = CreateSemaphore32A(sa,initial,max,name);
-	if (a) HeapFree(GetProcessHeap(),0,name);
-	return ret;
-}
-
-
-/***********************************************************************
- *           OpenSemaphoreA    (KERNEL32.403)
- */
-HANDLE32 WINAPI OpenSemaphore32A(DWORD desired,BOOL32 inherit,LPCSTR name)
-{
-	K32OBJ 		*obj = K32OBJ_FindName( name );
-
-	if (obj) {
-		if (obj->type == K32OBJ_SEMAPHORE)
-			return PROCESS_AllocHandle( obj,0 );
-		SetLastError( ERROR_DUP_NAME );
-		return 0;
-	}
-	return 0;
-}
-
-/***********************************************************************
- *           OpenSemaphoreA    (KERNEL32.404)
- */
-HANDLE32 WINAPI OpenSemaphore32W(DWORD desired,BOOL32 inherit,LPCWSTR name)
-{
-	LPSTR	nameA = name?HEAP_strdupWtoA(GetProcessHeap(),0,name):NULL;
-	HANDLE32	ret = OpenSemaphore32A(desired,inherit,nameA);
-
-	if (name) HeapFree(GetProcessHeap(),0,nameA);
-	return ret;
-}
-
-/***********************************************************************
- *           ReleaseSemaphore    (KERNEL32.403)
- */
-BOOL32 WINAPI ReleaseSemaphore(HANDLE32 hSemaphore,LONG lReleaseCount,LPLONG lpPreviousCount)
-{
-	K32SEMAPHORE	*sem;
-
-	sem = (K32SEMAPHORE*)PROCESS_GetObjPtr(hSemaphore,K32OBJ_SEMAPHORE);
-	if (!sem)
-		return FALSE;
-	if (lpPreviousCount) *lpPreviousCount = sem->count;
-	sem->count += lReleaseCount;
-	if (sem->count>sem->maxcount) {
-		fprintf(stderr,"ReleaseSemaphore(%d,%ld,.), released more then possible??\n",hSemaphore,lReleaseCount);
-		sem->count = sem->maxcount;
-	}
-
-	/* FIXME: wake up all threads blocked on that semaphore */
-
-	K32OBJ_DecCount(&(sem->header));
-	return TRUE;
-}
-
-/***********************************************************************
- *           OpenMutexA    (KERNEL32.399)
- */
-HANDLE32 WINAPI OpenMutex32A(DWORD desiredaccess, BOOL32 inherithandle, LPCSTR name)
-{
-	K32OBJ 		*obj = K32OBJ_FindName( name );
-
-	if (obj) {
-		if (obj->type == K32OBJ_MUTEX)
-			return PROCESS_AllocHandle( obj,0 );
-		SetLastError( ERROR_DUP_NAME );
-		return 0;
-	}
-	return 0;
-}
-
-/***********************************************************************
- *           OpenMutexW    (KERNEL32.400)
- */
-HANDLE32 WINAPI OpenMutex32W(DWORD desiredaccess, BOOL32 inherithandle,
-                             LPCWSTR name)
-{
-	LPSTR		nameA=name?HEAP_strdupWtoA(GetProcessHeap(),0,name):NULL;
-	HANDLE32	ret = OpenMutex32A(desiredaccess,inherithandle,nameA);
-
-	if (name) HeapFree(GetProcessHeap(),0,nameA);
-	return ret;
-}
-
-/***********************************************************************
- *           ReleaseMutex    (KERNEL32.435)
- */
-BOOL32 WINAPI ReleaseMutex (HANDLE32 h)
-{
-	K32MUTEX	*mut = (K32MUTEX*)PROCESS_GetObjPtr(h,K32OBJ_MUTEX);
-
-	if (!mut)
-		return 0;
-	if (mut->owning_thread != (THDB *)GetCurrentThreadId()) {
-		/* set error ... */
-		K32OBJ_DecCount(&(mut->header));
-		return 0;
-	}
-	mut->owning_thread = NULL;
-
-	/* FIXME: wake up all threads blocked on this mutex */
-
-	K32OBJ_DecCount(&(mut->header));
-	return TRUE;
-}
-
-/***********************************************************************
- *           CreateEventA    (KERNEL32.43)
- */
-HANDLE32 WINAPI CreateEvent32A(SECURITY_ATTRIBUTES *sa,BOOL32 au,BOOL32 on,
-                               LPCSTR name)
-{
-	K32EVENT	*evt;
-	HANDLE32	handle;
-	K32OBJ 		*obj = K32OBJ_FindName( name );
-
-	if (obj) {
-		if (obj->type == K32OBJ_EVENT) {
-			SetLastError( ERROR_ALREADY_EXISTS );
-			return PROCESS_AllocHandle( obj,0 );
-		}
-		SetLastError( ERROR_DUP_NAME );
-		return 0;
-	}
-	evt = (K32EVENT*)HeapAlloc(GetProcessHeap(),0,sizeof(K32EVENT));
-	evt->header.type = K32OBJ_EVENT;
-	evt->header.refcount  = 1;
-	if (name)
-		K32OBJ_AddName(&(evt->header),name);
-	handle = PROCESS_AllocHandle(&(evt->header),0);
-	if (handle != INVALID_HANDLE_VALUE32)
-		return handle;
-	K32OBJ_DecCount(&(evt->header)); /* also frees name */
-	HeapFree(GetProcessHeap(),0,evt);
-	return 0;
-}
-
-/***********************************************************************
- *           CreateEventW    (KERNEL32.43)
- */
-HANDLE32 WINAPI CreateEvent32W(SECURITY_ATTRIBUTES *sa, BOOL32 au,
-                               BOOL32 on,LPCWSTR name)
-{
-	LPSTR nameA=name?HEAP_strdupWtoA(GetProcessHeap(),0,name):NULL;
-	HANDLE32 ret = CreateEvent32A(sa,au,on,nameA);
-
-	if (name) HeapFree(GetProcessHeap(),0,nameA);
-	return ret;
-}
-
-/***********************************************************************
- *           OpenEventA    (KERNEL32.394)
- */
-HANDLE32 WINAPI OpenEvent32A(DWORD desiredaccess,BOOL32 inherithandle,LPCSTR name)
-{
-	K32OBJ 		*obj = K32OBJ_FindName( name );
-
-	if (obj) {
-		if (obj->type == K32OBJ_EVENT)
-			return PROCESS_AllocHandle( obj,0 );
-		SetLastError( ERROR_DUP_NAME );
-		return 0;
-	}
-	return 0;
-}
-
-/***********************************************************************
- *           OpenEventW    (KERNEL32.395)
- */
-HANDLE32 WINAPI OpenEvent32W(DWORD desiredaccess,BOOL32 inherithandle,LPCWSTR name)
-{
-	LPSTR	nameA = name?HEAP_strdupWtoA(GetProcessHeap(),0,name):NULL;
-	HANDLE32	ret = OpenEvent32A(desiredaccess,inherithandle,nameA);
-
-	if (name) HeapFree(GetProcessHeap(),0,nameA);
-	return ret;
-}
-
-/***********************************************************************
- *           SetEvent    (KERNEL32.487)
- */
-BOOL32 WINAPI SetEvent (HANDLE32 h)
-{
-	fprintf(stderr,"SetEvent(%d) stub\n",h);
-	return 0;
-}
-/***********************************************************************
- *           ResetEvent    (KERNEL32.439)
- */
-BOOL32 WINAPI ResetEvent (HANDLE32 h)
-{
-	fprintf(stderr,"ResetEvent(%d) stub\n",h);
-	return 0;
-}
-
-/***********************************************************************
- *           WaitForSingleObject    (KERNEL32.561)
- */
-DWORD WINAPI WaitForSingleObject(HANDLE32 h, DWORD timeout)
-{
-	fprintf(stderr,"WaitForSingleObject(%d,%ld) stub\n",h,timeout);
-	return 0;
-}
-
-/***********************************************************************
- *           WaitForSingleObjectEx    (KERNEL32)
- */
-DWORD WINAPI WaitForSingleObjectEx(HANDLE32 h,DWORD timeout,BOOL32 bAlertable)
-{
-	fprintf(stderr,"WaitForSingleObjectEx(%d,%ld,%d) stub\n",h,timeout,bAlertable);
-	return 0;
-}
 
 /***********************************************************************
  *           MsgWaitForMultipleObjects    (USER32.399)
@@ -355,15 +35,6 @@
 }
 
 /***********************************************************************
- *           WaitForMultipleObjects    (KERNEL32)
- */
-DWORD WINAPI WaitForMultipleObjects(
-	DWORD nCount,HANDLE32 *pHandles,BOOL32 fWaitAll,DWORD dwMilliseconds
-) {
-	return MsgWaitForMultipleObjects(nCount,pHandles,fWaitAll,dwMilliseconds,0);
-}
-
-/***********************************************************************
  *           DuplicateHandle    (KERNEL32.78)
  */
 BOOL32 WINAPI DuplicateHandle(HANDLE32 a, HANDLE32 b, HANDLE32 c, HANDLE32 * d, DWORD e, BOOL32 f, DWORD g)
diff --git a/win32/thread.c b/win32/thread.c
index e974c29..bcd4d4a 100644
--- a/win32/thread.c
+++ b/win32/thread.c
@@ -114,13 +114,9 @@
 {
 #if defined(__i386__)&&defined(__GNUC__)	
 	LONG ret;
-	__asm__
-	(	  	 
-
-           "\tlock\n"	/* for SMP systems */
-	   "\txchgl	%0,(%1)\n"	   	  
-	   :"=r" (ret):"r" (target), "0" (value):"memory"
-	);
+	__asm__ ( /* lock for SMP systems */
+                  "lock\n\txchgl %0,(%1)"
+                  :"=r" (ret):"r" (target), "0" (value):"memory" );
 	return ret;
 #else
 	LONG ret;
@@ -134,112 +130,6 @@
 #endif	
 }
 
-/* AAARGHH some CriticalSection functions get called before we 
- * have a threadid
- */
- 
-#define GetCurrentThreadId()	(-1)
-
-/************************************************************************
-*           InitializeCriticalSection			[KERNEL32]	*
-************************************************************************/
-
-void WINAPI InitializeCriticalSection(CRITICAL_SECTION *pcritical)
-{
-   pcritical->LockCount=-1;
-   pcritical->RecursionCount=0;
-   pcritical->LockSemaphore=(HANDLE32) semget(IPC_PRIVATE,1,IPC_CREAT);
-   pcritical->OwningThread=(HANDLE32) -1;
-   pcritical->Reserved=0;
-}
-
-/************************************************************************
-*           DeleteCriticalSection			[KERNEL32]	*
-************************************************************************/
-
-void WINAPI DeleteCriticalSection(CRITICAL_SECTION *pcritical)
-{
-   semctl((int) pcritical->LockSemaphore,0,IPC_RMID, (void *)0);
-   pcritical->Reserved=-1;
-}
-
-/************************************************************************
-*           EnterCriticalSection			[KERNEL32]	*
-************************************************************************/
-
-void WINAPI EnterCriticalSection (CRITICAL_SECTION *pcritical)
-{
-   if( InterlockedIncrement(&(pcritical->LockCount)))
-   {   
-      if( pcritical->OwningThread!= (HANDLE32) GetCurrentThreadId() )
-      {                 
-         struct sembuf sop;
-                                             
-         sop.sem_num=0;
-         sop.sem_op=0;
-         sop.sem_flg=0;            
-         semop((int) pcritical->LockSemaphore,&sop,0);
-            
-         pcritical->OwningThread = (HANDLE32) GetCurrentThreadId();                
-      }
-   }
-   else
-   {      
-      pcritical->OwningThread =(HANDLE32) GetCurrentThreadId();
-   }
-   pcritical->RecursionCount++;             
-}
-
-/************************************************************************
-*           TryEnterCriticalSection			[KERNEL32]	*
-************************************************************************/
-
-BOOL32 WINAPI TryEnterCriticalSection (CRITICAL_SECTION *pcritical)
-{
-   if( InterlockedIncrement(&(pcritical->LockCount)))
-   {
-      if( pcritical->OwningThread!= (HANDLE32) GetCurrentThreadId() )
-         return FALSE;
-   }
-   else
-   {      
-      pcritical->OwningThread =(HANDLE32) GetCurrentThreadId();
-   }
-   pcritical->RecursionCount++;             
-   
-   return TRUE;
-}
-
-/************************************************************************
-*           LeaveCriticalSection			[KERNEL32]	*
-************************************************************************/
-
-void WINAPI LeaveCriticalSection(CRITICAL_SECTION *pcritical)
-{
-   /* do we actually own this critical section ??? */
-   if( pcritical->OwningThread!= (HANDLE32) GetCurrentThreadId())
-      return;
-       
-   pcritical->RecursionCount--;
-   if( pcritical->RecursionCount==0)
-   {
-      pcritical->OwningThread=(HANDLE32)-1;
-      if(InterlockedDecrement(&(pcritical->LockCount))>=0)
-      {         
-         struct sembuf sop;
-         
-         sop.sem_num=0;
-         sop.sem_op=1;
-         sop.sem_flg=0;
-         semop((int) pcritical->LockSemaphore,&sop,0);
-      }
-   }
-   else
-   {
-       InterlockedDecrement(&(pcritical->LockCount));
-   }  
-}
-
 /************************************************************************
 *           ReinitializeCriticalSection			[KERNEL32]	*
 ************************************************************************/
@@ -248,14 +138,3 @@
 {
    /* hmm ?????? */	
 }
-
-/************************************************************************
-*           MakeCriticalSectionGlobal			[KERNEL32]	*
-************************************************************************/
-
-void WINAPI MakeCriticalSectionGlobal(CRITICAL_SECTION *lpCrit)
-{
-   /* nothing (SysV Semaphores are already global) */
-   return;	
-}
-
diff --git a/win32/user32.c b/win32/user32.c
index 3080596..daeb8c9 100644
--- a/win32/user32.c
+++ b/win32/user32.c
@@ -13,7 +13,6 @@
 #include "windows.h"
 #include "winerror.h"
 #include "heap.h"
-#include "handle32.h"
 #include "struct32.h"
 #include "win.h"
 #include "debug.h"
diff --git a/windows/dce.c b/windows/dce.c
index 6fb6d56..b82bc95 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -774,11 +774,12 @@
             WND*    wnd = wndPtr->parent->child;
 	    RECT32  rect;
 	
-	    for( ; wnd != wndPtr; wnd = wnd->next )
+	    for( ; wnd && (wnd != wndPtr); wnd = wnd->next ) {
 		if( wnd->class->style & CS_SAVEBITS && 
 		    wnd->dwStyle & WS_VISIBLE &&
 		    IntersectRect32(&rect, &wndPtr->rectClient, &wnd->rectClient) )
                     wnd->flags |= WIN_SAVEUNDER_OVERRIDE;
+	    }
 	}
 	dc->w.flags &= ~DC_DIRTY;
 	dce->DCXflags &= ~DCX_DCEDIRTY;
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 002868a..644f634 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -13,7 +13,6 @@
 #include "nonclient.h"
 #include "winpos.h"
 #include "dce.h"
-#include "syscolor.h"
 #include "sysmetrics.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -79,15 +78,16 @@
 {
     if( ctlType == CTLCOLOR_SCROLLBAR)
     {
+        HBRUSH32 hb = GetSysColorBrush32(COLOR_SCROLLBAR);
 	SetBkColor32( hDC, RGB(255, 255, 255) );
 	SetTextColor32( hDC, RGB(0, 0, 0) );
-	UnrealizeObject32( sysColorObjects.hbrushScrollbar );
-        return sysColorObjects.hbrushScrollbar;
+	UnrealizeObject32( hb );
+        return hb;
     }
 
     SetBkColor32( hDC, GetSysColor32(COLOR_WINDOW) );
     SetTextColor32( hDC, GetSysColor32(COLOR_WINDOWTEXT));
-    return sysColorObjects.hbrushWindow;
+    return GetSysColorBrush32(COLOR_WINDOW);
 }
 
 
diff --git a/windows/event.c b/windows/event.c
index 69c40ec..a6888ac 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -666,8 +666,8 @@
 
     if (buttonNum >= NB_BUTTONS) return;
     if (SwappedButtons) buttonNum = NB_BUTTONS - 1 - buttonNum;
-    MouseButtonsStates[buttonNum] = 0x8000;
-    AsyncMouseButtonsStates[buttonNum] = 0x8000;
+    MouseButtonsStates[buttonNum] = TRUE;
+    AsyncMouseButtonsStates[buttonNum] = TRUE;
     hardware_event( messages[buttonNum],
 		    EVENT_XStateToKeyState( event->state ), 0L,
                     pWnd->rectWindow.left + event->x,
@@ -687,7 +687,7 @@
 
     if (buttonNum >= NB_BUTTONS) return;    
     if (SwappedButtons) buttonNum = NB_BUTTONS - 1 - buttonNum;
-    MouseButtonsStates[buttonNum] = 0;
+    MouseButtonsStates[buttonNum] = FALSE;
     hardware_event( messages[buttonNum],
 		    EVENT_XStateToKeyState( event->state ), 0L,
                     pWnd->rectWindow.left + event->x,
diff --git a/windows/graphics.c b/windows/graphics.c
index f924a8f..a4953c6 100644
--- a/windows/graphics.c
+++ b/windows/graphics.c
@@ -15,7 +15,6 @@
 #include "bitmap.h"
 #include "gdi.h"
 #include "dc.h"
-#include "syscolor.h"
 
 #define MAX_DRAWLINES 8
 
@@ -129,12 +128,12 @@
 {
     if(pressed)
 	GRAPH_DrawGenericReliefRect(hdc, rect, highlight_size, shadow_size,
-				    sysColorObjects.hbrushBtnShadow,
-				    sysColorObjects.hbrushBtnHighlight);
+				    GetSysColorBrush32(COLOR_BTNSHADOW),
+				    GetSysColorBrush32(COLOR_BTNHIGHLIGHT));
     else
 	GRAPH_DrawGenericReliefRect(hdc, rect, highlight_size, shadow_size,
-				    sysColorObjects.hbrushBtnHighlight,
-				    sysColorObjects.hbrushBtnShadow);
+				    GetSysColorBrush32(COLOR_BTNHIGHLIGHT),
+				    GetSysColorBrush32(COLOR_BTNSHADOW));
 
     return;
 }
diff --git a/windows/keyboard.c b/windows/keyboard.c
index 75a8438..2f2f594 100644
--- a/windows/keyboard.c
+++ b/windows/keyboard.c
@@ -511,13 +511,13 @@
     switch (vkey)
 	{
 	case VK_LBUTTON : /* VK_LBUTTON is 1 */
-	    retval = MouseButtonsStates[0];
+	    retval = MouseButtonsStates[0] ? 0x8000 : 0;
 	    break;
 	case VK_MBUTTON : /* VK_MBUTTON is 4 */
-	    retval = MouseButtonsStates[1];
+	    retval = MouseButtonsStates[1] ? 0x8000 : 0;
 	    break;
 	case VK_RBUTTON : /* VK_RBUTTON is 2 */
-	    retval = MouseButtonsStates[2];
+	    retval = MouseButtonsStates[2] ? 0x8000 : 0;
 	    break;
 	default :
 	    if (vkey >= 'a' && vkey <= 'z')
@@ -539,9 +539,9 @@
 {
     dprintf_key(stddeb, "GetKeyboardState()\n");
     if (lpKeyState != NULL) {
-	QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] >> 8;
-	QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] >> 8;
-	QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] >> 8;
+	QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] ? 0x80 : 0;
+	QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] ? 0x80 : 0;
+	QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] ? 0x80 : 0;
 	memcpy(lpKeyState, QueueKeyStateTable, 256);
     }
 }
@@ -554,9 +554,9 @@
     dprintf_key(stddeb, "SetKeyboardState()\n");
     if (lpKeyState != NULL) {
 	memcpy(QueueKeyStateTable, lpKeyState, 256);
-	MouseButtonsStates[0] = QueueKeyStateTable[VK_LBUTTON]? 0x8000: 0;
-	MouseButtonsStates[1] = QueueKeyStateTable[VK_MBUTTON]? 0x8000: 0;
-	MouseButtonsStates[2] = QueueKeyStateTable[VK_RBUTTON]? 0x8000: 0;
+	MouseButtonsStates[0] = (QueueKeyStateTable[VK_LBUTTON] != 0);
+	MouseButtonsStates[1] = (QueueKeyStateTable[VK_MBUTTON] != 0);
+	MouseButtonsStates[2] = (QueueKeyStateTable[VK_RBUTTON] != 0);
     }
 }
 
@@ -579,16 +579,16 @@
 
     switch (nKey) {
      case VK_LBUTTON:
-	retval = AsyncMouseButtonsStates[0] | 
-	MouseButtonsStates[0]? 0x0001: 0;
+	retval = (AsyncMouseButtonsStates[0] ? 0x0001 : 0) | 
+                 (MouseButtonsStates[0] ? 0x8000 : 0);
 	break;
      case VK_MBUTTON:
-	retval = AsyncMouseButtonsStates[1] |
-	MouseButtonsStates[1]? 0x0001: 0;
+	retval = (AsyncMouseButtonsStates[1] ? 0x0001 : 0) | 
+                 (MouseButtonsStates[1] ? 0x8000 : 0);
 	break;
      case VK_RBUTTON:
-	retval = AsyncMouseButtonsStates[2] |
-	MouseButtonsStates[2]? 0x0001: 0;
+	retval = (AsyncMouseButtonsStates[2] ? 0x0001 : 0) | 
+                 (MouseButtonsStates[2] ? 0x8000 : 0);
 	break;
      default:
 	retval = AsyncKeyStateTable[nKey] | 
@@ -596,8 +596,9 @@
 	break;
     }
 
-    memset( AsyncMouseButtonsStates, 0, 3 );  /* all states to false */
-    memset( AsyncKeyStateTable, 0, 256 );
+    /* all states to false */
+    memset( AsyncMouseButtonsStates, 0, sizeof(AsyncMouseButtonsStates) );
+    memset( AsyncKeyStateTable, 0, sizeof(AsyncKeyStateTable) );
 
     dprintf_key(stddeb, "GetAsyncKeyState(%x) -> %x\n", nKey, retval);
     return retval;
diff --git a/windows/message.c b/windows/message.c
index a62ca87..08a4d7d 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -391,16 +391,22 @@
     {
      switch (tmpMsg->message)
      {
-      case WM_LBUTTONDOWN:MouseButtonsStates[0]=AsyncMouseButtonsStates[0]=1;break;
-      case WM_LBUTTONUP:  MouseButtonsStates[0]=AsyncMouseButtonsStates[0]=0;break;
-      case WM_MBUTTONDOWN:MouseButtonsStates[1]=AsyncMouseButtonsStates[1]=1;break;
-      case WM_MBUTTONUP:  MouseButtonsStates[1]=AsyncMouseButtonsStates[1]=0;break;
-      case WM_RBUTTONDOWN:MouseButtonsStates[2]=AsyncMouseButtonsStates[2]=1;break;
-      case WM_RBUTTONUP:  MouseButtonsStates[2]=AsyncMouseButtonsStates[2]=0;break;      
+      case WM_LBUTTONDOWN:
+          MouseButtonsStates[0]=AsyncMouseButtonsStates[0]=TRUE;break;
+      case WM_LBUTTONUP:
+          MouseButtonsStates[0]=AsyncMouseButtonsStates[0]=FALSE;break;
+      case WM_MBUTTONDOWN:
+          MouseButtonsStates[1]=AsyncMouseButtonsStates[1]=TRUE;break;
+      case WM_MBUTTONUP:
+          MouseButtonsStates[1]=AsyncMouseButtonsStates[1]=FALSE;break;
+      case WM_RBUTTONDOWN:
+          MouseButtonsStates[2]=AsyncMouseButtonsStates[2]=TRUE;break;
+      case WM_RBUTTONUP:
+          MouseButtonsStates[2]=AsyncMouseButtonsStates[2]=FALSE;break;      
      }
-     AsyncKeyStateTable[VK_LBUTTON]= InputKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] << 8;
-     AsyncKeyStateTable[VK_MBUTTON]= InputKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] << 8;
-     AsyncKeyStateTable[VK_RBUTTON]= InputKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] << 8;
+     AsyncKeyStateTable[VK_LBUTTON]= InputKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] ? 0x80 : 0;
+     AsyncKeyStateTable[VK_MBUTTON]= InputKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] ? 0x80 : 0;
+     AsyncKeyStateTable[VK_RBUTTON]= InputKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] ? 0x80 : 0;
      SetCursorPos32(tmpMsg->paramL,tmpMsg->paramH);
      lParam=MAKELONG(tmpMsg->paramL,tmpMsg->paramH);
      wParam=0;             
@@ -1707,3 +1713,14 @@
 	);
 	return 0;
 }
+
+/***********************************************************************
+ *           SendNotifyMessageA    (USER32.460)
+ */
+LONG WINAPI SendNotifyMessage32A(HWND32 hwnd,UINT32 msg,WPARAM32 wParam,LPARAM lParam)
+{
+	fprintf(stderr,"SendNotifyMessage32A(%04x,%08lx,%08lx,%08lx),stub!\n",
+		hwnd,(long)msg,(long)wParam,lParam
+	);
+	return 0;
+}
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 7bdbce4..720c2ab 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -13,7 +13,6 @@
 #include "heap.h"
 #include "cursoricon.h"
 #include "dialog.h"
-#include "syscolor.h"
 #include "menu.h"
 #include "winpos.h"
 #include "hook.h"
@@ -678,15 +677,15 @@
     {
 	width = SYSMETRICS_CXDLGFRAME - 1;
 	height = SYSMETRICS_CYDLGFRAME - 1;
-        SelectObject32( hdc, active ? sysColorObjects.hbrushActiveCaption :
-                                      sysColorObjects.hbrushInactiveCaption );
+        SelectObject32( hdc, GetSysColorBrush32(active ? COLOR_ACTIVECAPTION :
+						COLOR_INACTIVECAPTION) );
     }
     else
     {
 	width = SYSMETRICS_CXFRAME - 1;
 	height = SYSMETRICS_CYFRAME - 1;
-        SelectObject32( hdc, active ? sysColorObjects.hbrushActiveBorder :
-                                      sysColorObjects.hbrushInactiveBorder );
+        SelectObject32( hdc, GetSysColorBrush32(active ? COLOR_ACTIVEBORDER :
+						COLOR_INACTIVEBORDER) );
     }
 
       /* Draw frame */
@@ -783,15 +782,15 @@
     {
 	width = SYSMETRICS_CXDLGFRAME - 1;
 	height = SYSMETRICS_CYDLGFRAME - 1;
-        SelectObject32( hdc, active ? sysColorObjects.hbrushActiveCaption :
-                                      sysColorObjects.hbrushInactiveCaption );
+        SelectObject32( hdc, GetSysColorBrush32(active ? COLOR_ACTIVECAPTION :
+						COLOR_INACTIVECAPTION) );
     }
     else
     {
 	width = sysMetrics[SM_CXFRAME] - sysMetrics[SM_CXEDGE] - 1;
 	height = sysMetrics[SM_CYFRAME] - sysMetrics[SM_CYEDGE] - 1;
-        SelectObject32( hdc, active ? sysColorObjects.hbrushActiveBorder :
-                                      sysColorObjects.hbrushInactiveBorder );
+        SelectObject32( hdc, GetSysColorBrush32(active ? COLOR_ACTIVEBORDER :
+						COLOR_INACTIVEBORDER) );
     }
 
     /* Draw frame */
@@ -868,7 +867,7 @@
     
     if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
     {
-	HBRUSH32 hbrushOld = SelectObject32(hdc, sysColorObjects.hbrushWindow);
+        HBRUSH32 hbrushOld = SelectObject32(hdc, GetSysColorBrush32(COLOR_WINDOW) );
 	PatBlt32( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
 	PatBlt32( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
 	PatBlt32( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
@@ -898,8 +897,8 @@
 	r.right -= SYSMETRICS_CXSIZE + 1;
     }
 
-    FillRect32( hdc, &r, active ? sysColorObjects.hbrushActiveCaption : 
-	                          sysColorObjects.hbrushInactiveCaption );
+    FillRect32( hdc, &r, GetSysColorBrush32(active ? COLOR_ACTIVECAPTION :
+					    COLOR_INACTIVECAPTION) );
 
     if (GetWindowText32A( hwnd, buffer, sizeof(buffer) ))
     {
@@ -948,8 +947,8 @@
 
     if (wndPtr->flags & WIN_MANAGED) return;
 
-    FillRect32( hdc, &r, active ? sysColorObjects.hbrushActiveCaption : 
-	                          sysColorObjects.hbrushInactiveCaption );
+    FillRect32( hdc, &r, GetSysColorBrush32(active ? COLOR_ACTIVECAPTION :
+					    COLOR_INACTIVECAPTION) );
 
     if (!hbitmapClose) {
 	if (!(hbitmapClose = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_CLOSE) )))
@@ -963,7 +962,7 @@
     }
     
     if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) {
-	HBRUSH32 hbrushOld = SelectObject32(hdc, sysColorObjects.hbrushWindow);
+	HBRUSH32 hbrushOld = SelectObject32(hdc, GetSysColorBrush32(COLOR_WINDOW) );
 	PatBlt32( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
 	PatBlt32( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
 	PatBlt32( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
@@ -1032,7 +1031,7 @@
     rect.right  = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
     rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
 
-    SelectObject32( hdc, sysColorObjects.hpenWindowFrame );
+    SelectObject32( hdc, GetSysColorPen32(COLOR_WINDOWFRAME) );
 
     if (!(wndPtr->flags & WIN_MANAGED))
     {
@@ -1079,7 +1078,7 @@
         RECT32 r = rect;
         r.left = r.right - SYSMETRICS_CXVSCROLL + 1;
         r.top  = r.bottom - SYSMETRICS_CYHSCROLL + 1;
-        FillRect32( hdc, &r, sysColorObjects.hbrushScrollbar );
+        FillRect32( hdc, &r, GetSysColorBrush32(COLOR_SCROLLBAR) );
     }    
 
     ReleaseDC32( hwnd, hdc );
@@ -1139,7 +1138,7 @@
     rect.right  = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
     rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
 
-    SelectObject32( hdc, sysColorObjects.hpenWindowFrame );
+    SelectObject32( hdc, GetSysColorPen32(COLOR_WINDOWFRAME) );
 
     if(!(wndPtr->flags & WIN_MANAGED)) {
         if((wndPtr->dwStyle & WS_BORDER) || (wndPtr->dwStyle & WS_DLGFRAME) ||
@@ -1206,7 +1205,7 @@
         RECT32 r = rect;
         r.left = r.right - SYSMETRICS_CXVSCROLL + 1;
         r.top  = r.bottom - SYSMETRICS_CYHSCROLL + 1;
-        FillRect32( hdc, &r, sysColorObjects.hbrushScrollbar );
+        FillRect32( hdc, &r,  GetSysColorBrush32(COLOR_SCROLLBAR) );
     }    
 
     ReleaseDC32( hwnd, hdc );
diff --git a/windows/property.c b/windows/property.c
index 09eebed..c44f871 100644
--- a/windows/property.c
+++ b/windows/property.c
@@ -24,21 +24,34 @@
  */
 static PROPERTY *PROP_FindProp( HWND32 hwnd, LPCSTR str )
 {
+    ATOM atom;
     PROPERTY *prop;
     WND *pWnd = WIN_FindWndPtr( hwnd );
 
     if (!pWnd) return NULL;
     if (HIWORD(str))
     {
+        atom = GlobalFindAtom32A( str );
         for (prop = pWnd->pProp; prop; prop = prop->next)
-            if (HIWORD(prop->string) && !lstrcmpi32A( prop->string, str ))
-                return prop;
+        {
+            if (HIWORD(prop->string))
+            {
+                if (!lstrcmpi32A( prop->string, str )) return prop;
+            }
+            else if (LOWORD(prop->string) == atom) return prop;
+        }
     }
     else  /* atom */
     {
+        atom = LOWORD(str);
         for (prop = pWnd->pProp; (prop); prop = prop->next)
-            if (!HIWORD(prop->string) && (LOWORD(prop->string) == LOWORD(str)))
-                return prop;
+        {
+            if (HIWORD(prop->string))
+            {
+                if (GlobalFindAtom32A( prop->string ) == atom) return prop;
+            }
+            else if (LOWORD(prop->string) == atom) return prop;
+        }
     }
     return NULL;
 }
@@ -159,6 +172,7 @@
  */
 HANDLE32 WINAPI RemoveProp32A( HWND32 hwnd, LPCSTR str )
 {
+    ATOM atom;
     HANDLE32 handle;
     PROPERTY **pprop, *prop;
     WND *pWnd = WIN_FindWndPtr( hwnd );
@@ -172,15 +186,27 @@
     if (!pWnd) return NULL;
     if (HIWORD(str))
     {
+        atom = GlobalFindAtom32A( str );
         for (pprop=(PROPERTY**)&pWnd->pProp; (*pprop); pprop = &(*pprop)->next)
-            if (HIWORD((*pprop)->string) &&
-                !lstrcmpi32A( (*pprop)->string, str )) break;
+        {
+            if (HIWORD((*pprop)->string))
+            {
+                if (!lstrcmpi32A( (*pprop)->string, str )) break;
+            }
+            else if (LOWORD((*pprop)->string) == atom) break;
+        }
     }
     else  /* atom */
     {
+        atom = LOWORD(str);
         for (pprop=(PROPERTY**)&pWnd->pProp; (*pprop); pprop = &(*pprop)->next)
-            if (!HIWORD((*pprop)->string) &&
-                (LOWORD((*pprop)->string) == LOWORD(str))) break;
+        {
+            if (HIWORD((*pprop)->string))
+            {
+                if (GlobalFindAtom32A( (*pprop)->string ) == atom) break;
+            }
+            else if (LOWORD((*pprop)->string) == atom) break;
+        }
     }
     if (!*pprop) return 0;
     prop   = *pprop;
diff --git a/windows/syscolor.c b/windows/syscolor.c
index 45d2f73..dd490a9 100644
--- a/windows/syscolor.c
+++ b/windows/syscolor.c
@@ -6,16 +6,11 @@
  *
  */
 
+#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include "gdi.h"
-#include "syscolor.h"
-#include "stddebug.h"
 #include "tweak.h"
-/* #define DEBUG_SYSCOLOR */
-#include "debug.h"
-
-struct SysColorObjects sysColorObjects;
 
 static const char * const DefSysColors[] =
 {
@@ -79,6 +74,8 @@
 #define NUM_SYS_COLORS     (COLOR_INFOBK+1)
 
 static COLORREF SysColors[NUM_SYS_COLORS];
+static HBRUSH32 SysColorBrushes[NUM_SYS_COLORS];
+static HPEN32   SysColorPens[NUM_SYS_COLORS];
 
 #define MAKE_SOLID(color) \
        (PALETTEINDEX(GetNearestPaletteIndex32(STOCK_DEFAULT_PALETTE,(color))))
@@ -90,114 +87,10 @@
 {
     if (index < 0 || index >= NUM_SYS_COLORS) return;
     SysColors[index] = color;
-    switch(index)
-    {
-    case COLOR_SCROLLBAR:
-	DeleteObject32( sysColorObjects.hbrushScrollbar );
-	sysColorObjects.hbrushScrollbar = CreateSolidBrush32( color );
-	break;
-    case COLOR_BACKGROUND:
-	DeleteObject32( sysColorObjects.hbrushBackground );
-	sysColorObjects.hbrushBackground = CreateSolidBrush32( color );
-	break;
-    case COLOR_ACTIVECAPTION:
-	DeleteObject32( sysColorObjects.hbrushActiveCaption );
-	sysColorObjects.hbrushActiveCaption = CreateSolidBrush32( color );
-	break;
-    case COLOR_INACTIVECAPTION:
-	DeleteObject32( sysColorObjects.hbrushInactiveCaption );
-	sysColorObjects.hbrushInactiveCaption = CreateSolidBrush32( color );
-	break;
-    case COLOR_MENU:
-	DeleteObject32( sysColorObjects.hbrushMenu );
-	sysColorObjects.hbrushMenu = CreateSolidBrush32( MAKE_SOLID(color) );
-	break;
-    case COLOR_WINDOW:
-	DeleteObject32( sysColorObjects.hbrushWindow );
-	sysColorObjects.hbrushWindow = CreateSolidBrush32( color );
-	break;
-    case COLOR_WINDOWFRAME:
-	DeleteObject32( sysColorObjects.hbrushWindowFrame );
-	sysColorObjects.hbrushWindowFrame = CreateSolidBrush32( color );
-	/* FIXME: we should not need this pen */
-	DeleteObject32( sysColorObjects.hpenWindowFrame ); 
-	sysColorObjects.hpenWindowFrame = CreatePen32( PS_SOLID, 1, color );
-	break;
-    case COLOR_MENUTEXT:
-	DeleteObject32( sysColorObjects.hbrushMenuText );
-	sysColorObjects.hbrushMenuText = CreateSolidBrush32( color );
-	break;
-    case COLOR_WINDOWTEXT:
-	DeleteObject32( sysColorObjects.hbrushWindowText );
-	sysColorObjects.hbrushWindowText = CreateSolidBrush32( color );
-	/* FIXME: we should not need this pen */
-	DeleteObject32( sysColorObjects.hpenWindowText );
-	sysColorObjects.hpenWindowText = CreatePen32( PS_DOT, 1, color );
-	break;
-    case COLOR_CAPTIONTEXT:
-	DeleteObject32( sysColorObjects.hbrushCaptionText );
-	sysColorObjects.hbrushCaptionText = CreateSolidBrush32( color );
-	break;
-    case COLOR_ACTIVEBORDER:
-	DeleteObject32( sysColorObjects.hbrushActiveBorder );
-	sysColorObjects.hbrushActiveBorder = CreateSolidBrush32( color );
-	break;
-    case COLOR_INACTIVEBORDER:
-	DeleteObject32( sysColorObjects.hbrushInactiveBorder );
-	sysColorObjects.hbrushInactiveBorder = CreateSolidBrush32( color );
-	break;
-    case COLOR_APPWORKSPACE:
-	DeleteObject32( sysColorObjects.hbrushAppWorkspace );
-	sysColorObjects.hbrushAppWorkspace = CreateSolidBrush32( color );
-	break;
-    case COLOR_HIGHLIGHT:
-	DeleteObject32( sysColorObjects.hbrushHighlight );
-	sysColorObjects.hbrushHighlight = CreateSolidBrush32( color );
-	break;
-    case COLOR_HIGHLIGHTTEXT:
-	DeleteObject32( sysColorObjects.hbrushHighlightText );
-	sysColorObjects.hbrushHighlightText = CreateSolidBrush32( color );
-	break;
-    case COLOR_BTNFACE:
-	DeleteObject32( sysColorObjects.hbrushBtnFace );
-	sysColorObjects.hbrushBtnFace = CreateSolidBrush32( color );
-	break;
-    case COLOR_BTNSHADOW:
-	DeleteObject32( sysColorObjects.hbrushBtnShadow );
-	sysColorObjects.hbrushBtnShadow = CreateSolidBrush32( color );
-	break;
-    case COLOR_GRAYTEXT:
-	DeleteObject32( sysColorObjects.hbrushGrayText );
-	sysColorObjects.hbrushGrayText = CreateSolidBrush32( color );
-    case COLOR_BTNTEXT:
-	DeleteObject32( sysColorObjects.hbrushBtnText );
-	sysColorObjects.hbrushBtnText = CreateSolidBrush32( color );
-	break;
-    case COLOR_INACTIVECAPTIONTEXT:
-	DeleteObject32( sysColorObjects.hbrushInactiveCaptionText );
-	sysColorObjects.hbrushInactiveCaptionText = CreateSolidBrush32(color);
-	break;
-    case COLOR_BTNHIGHLIGHT:
-	DeleteObject32( sysColorObjects.hbrushBtnHighlight );
-	sysColorObjects.hbrushBtnHighlight = CreateSolidBrush32( color );
-	break;
-    case COLOR_3DDKSHADOW:
-	DeleteObject32( sysColorObjects.hbrush3DDkShadow );
-	sysColorObjects.hbrush3DDkShadow = CreateSolidBrush32( color );
-	break;
-    case COLOR_3DLIGHT:
-	DeleteObject32( sysColorObjects.hbrush3DLight );
-	sysColorObjects.hbrush3DLight = CreateSolidBrush32( color );
-	break;
-    case COLOR_INFOTEXT:
-	DeleteObject32( sysColorObjects.hbrushInfoText );
-	sysColorObjects.hbrushInfoText = CreateSolidBrush32( color );
-	break;
-    case COLOR_INFOBK:
-	DeleteObject32( sysColorObjects.hbrushInfoBk );
-	sysColorObjects.hbrushInfoBk = CreateSolidBrush32( color );
-	break;
-    }
+    if (SysColorBrushes[index]) DeleteObject32( SysColorBrushes[index] );
+    SysColorBrushes[index] = CreateSolidBrush32( color );
+    if (SysColorPens[index]) DeleteObject32( SysColorPens[index] ); 
+    SysColorPens[index] = CreatePen32( PS_SOLID, 1, color );
 }
 
 
@@ -288,3 +181,49 @@
                 RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ALLCHILDREN );
     return TRUE;
 }
+
+
+/***********************************************************************
+ *           GetSysColorBrush16    (USER.281)
+ */
+HBRUSH16 WINAPI GetSysColorBrush16( INT16 index )
+{
+    return (HBRUSH16)GetSysColorBrush32(index);
+}
+
+
+/***********************************************************************
+ *           GetSysColorBrush32    (USER32.289)
+ */
+HBRUSH32 WINAPI GetSysColorBrush32( INT32 index )
+{
+    if (0 <= index && index < NUM_SYS_COLORS)
+        return SysColorBrushes[index];
+    fprintf( stderr, "GetSysColorBrush32: Unknown index(%d)\n", index );
+    return GetStockObject32(LTGRAY_BRUSH);
+}
+
+
+/***********************************************************************
+ *           GetSysColorPen16    (Not a Windows API)
+ */
+HPEN16 WINAPI GetSysColorPen16( INT16 index )
+{
+    return (HPEN16)GetSysColorPen32(index);
+}
+
+
+/***********************************************************************
+ *           GetSysColorPen32    (Not a Windows API)
+ *
+ * This function is new to the Wine lib -- it does not exist in 
+ * Windows. However, it is a natural complement for GetSysColorBrush
+ * in the Win32 API and is needed quite a bit inside Wine.
+ */
+HPEN32 WINAPI GetSysColorPen32( INT32 index )
+{
+    /* We can assert here, because this function is internal to Wine */
+    assert (0 <= index && index < NUM_SYS_COLORS);
+    return SysColorPens[index];
+
+}