Release 970804

Sun Aug  3 14:03:43 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [documentation/Makefile.in]
	Create links for files included from wine.texinfo.

	* [wine.man]
	Moved to documentation dir.

	* [if1632/builtin.c]
	Made SYSTEM.DLL always loaded by default.

	* [loader/signal.c] [if1632/signal.c]
	Split signal.c in generic/emulator-specific parts.

	* [misc/system.c] [if1632/thunk.c]
	Implemented system timer functions.
	Fixed InquireSystem parameters.

	* [msdos/ioports.c]
	Defined inb/outb functions to avoid including asm/io.h.
	Use the right instruction for word and dword direct access.

	* [multimedia/mmsystem.c]
	Fixed CallTo16 usage.

Sat Aug 2 13:05:23 1997  Andreas Mohr <100.30936@germany.net>

	* [controls/edit.c]
	When text is inserted into a newly created editline, the caret
	is placed after the text. Should be placed before the text. Fixed.

	* [files/file.c]
	Removed O_TRUNC flag from OF_WRITE mode in _lopen32().
	According to doc _lopen() never truncates files.

	* [if1632/user.spec] [misc/comm.c]
	Added stub for EnableCommNotification().

	* [misc/ver.c]
	Fixed problem with VerQueryValue*() running over end of name table
	in rare cases.

	* [msdos/int21.c]
	Enhanced ioctlGetDeviceInfo() to correctly return the current drive.

	* [multimedia/joystick.c] [windows/message.c]
	Added joystick support !!!
	Needs Linux >= 2.1.45 or joystick-0.8.0.tar.gz.

Fri Aug  1 18:02:09 1997  Morten Welinder  <terra@diku.dk>

	* [if1632/user32.spec]
	Define DrawAnimatedRects32.

	* [graphics/painting.c]
	(DrawAnimatedRects32): Create stub.

	* [misc/registry.c]
	Cope with NULL class in RegQueryInfoKey32A.

	* [if1632/user32.spec]
	Add GetMenuItemInfo32[AW].

	* [controls/menu.c]
	(InsertMenu32A): Upgrade flags to 8 hex-digits.
	(MENUEX_ParseResource): First shot at implementation.
	(LoadMenuIndirect32A): Handle extended menus.
	(GetMenuItemInfo32[AW]): First shot at implementation.

	* [include/windows.h]
	Define MFT_*, MFS_*, MIIM_* macros.  Define MENUITEMINFO[AW]
 	structures and pointers.

	* [Makefile.in]
	(etags): Add TAGS as target.

	* [if1632/comctl32.spec]
	Use Windows 95's ordinals.  Add a few missing stubs.

Thu Jul 31 14:01:13 1997  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [objects/color.c]
	Fix for 16 color mode of XFree.

	* [if1632/kernel32.spec][win32/ordinals.c]
	Moved/added some ordinal only exported functions from kernel32.dll
	(mostly thunking preparation stuff).

Wed Jul 30 09:16:38 1997  John Harvey <john@division.co.uk>

	* [graphics/win16drv/init.c] [include/win16drv.h]
        Escape(SETABORTPROC) returns success to keep pbrush.exe happy.
        Escape(NEXTBAND) implemented to make HP PCL printer driver work in
 	word.  Stub for PATBLT added to start work on printing more than
 	text.

Mon Jul 28 13:14:28 1997  Victor Schneider <vischne@ibm.net>

	* [libtest/expand.c]
	New Winelib test program.

Wed Jul 23 09:37:13 1997  Adrian Harvey <adrian@select.com.au>

	* [tools/build.c] [tools/build-spec.txt] [if1632/kernel.spec]
	  [if1632/user.spec]
	Added ability to set filename wine considers the built-in DLLs 
	to be in  to something other than name.DLL with new "file" key
	in .spec files.
	Made kernel filename KRNL386.EXE (some programs use this name 
	explicitly - ChemOffice install now starts up).
	Made user filename USER.EXE (just to be tidy).

Sun Jul 20 23:51:02 1997  David A. Cuthbert <dacut@henry.ece.cmu.edu>

	* [controls/menu.c] [misc/tweak.c] [include/tweak.h]
	Fixed MENU_KeyLeft and MENU_KeyRight to handle multiple-column
	menus.  Misc menu drawing issues for Win95 tweaks fixed.  Misc
	warnings fixed.

	* [loader/module.c]
	Spaces are now permitted in file/path names on the command line.
	If multiple matches can be made, the preferred match is the
	path/file with fewer spaces.

Tue Jul 29 02:21:15 1997  Bruce Milner <Bruce.Milner@genetics.utah.edu>

	* [misc/compobj.c]
	Added CLSIDFromString and StringFromCLSID.
diff --git a/ANNOUNCE b/ANNOUNCE
index bcff674..73a0d1a 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,13 +1,13 @@
-This is release 970720 of Wine, the MS Windows emulator.  This is still a
+This is release 970804 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-970720: (see ChangeLog for details)
-	- Preliminary Win95 look&feel implementation.
-	- Start of texinfo documentation.
+WHAT'S NEW with Wine-970804: (see ChangeLog for details)
+	- Joystick support.
+	- More Win32 stuff.
 	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -16,10 +16,10 @@
 the release is available at the ftp sites.  The sources will be available
 from the following locations:
 
-  ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-970720.tar.gz
-  ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-970720.tar.gz
-  ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-970720.tar.gz
-  ftp://ftp.progsoc.uts.edu.au/pub/Wine/development/Wine-970720.tar.gz
+  ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-970804.tar.gz
+  ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-970804.tar.gz
+  ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-970804.tar.gz
+  ftp://ftp.progsoc.uts.edu.au/pub/Wine/development/Wine-970804.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
diff --git a/BUGS b/BUGS
index 0d57d68..74110a3 100644
--- a/BUGS
+++ b/BUGS
@@ -9,6 +9,10 @@
 
 General:
 
+ * We need to do InsertMenuItem32[AW] and then code most of the other
+   inserting function in terms of this.  Without this, we cannot support
+   all the new extended menus.  Not hard, but slightly big.
+
  * TrueType, .FON rasterizer.
 
  * No thread/process scheduling support in Win32 code. 
@@ -53,5 +57,3 @@
 Where to look in source files:
 
  * grep for FIXME in the source files.
-
-
diff --git a/ChangeLog b/ChangeLog
index 74a4281..f1264ad 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,134 @@
 ----------------------------------------------------------------------
+Sun Aug  3 14:03:43 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>
+
+	* [documentation/Makefile.in]
+	Create links for files included from wine.texinfo.
+
+	* [wine.man]
+	Moved to documentation dir.
+
+	* [if1632/builtin.c]
+	Made SYSTEM.DLL always loaded by default.
+
+	* [loader/signal.c] [if1632/signal.c]
+	Split signal.c in generic/emulator-specific parts.
+
+	* [misc/system.c] [if1632/thunk.c]
+	Implemented system timer functions.
+	Fixed InquireSystem parameters.
+
+	* [msdos/ioports.c]
+	Defined inb/outb functions to avoid including asm/io.h.
+	Use the right instruction for word and dword direct access.
+
+	* [multimedia/mmsystem.c]
+	Fixed CallTo16 usage.
+
+Sat Aug 2 13:05:23 1997  Andreas Mohr <100.30936@germany.net>
+
+	* [controls/edit.c]
+	When text is inserted into a newly created editline, the caret
+	is placed after the text. Should be placed before the text. Fixed.
+
+	* [files/file.c]
+	Removed O_TRUNC flag from OF_WRITE mode in _lopen32().
+	According to doc _lopen() never truncates files.
+
+	* [if1632/user.spec] [misc/comm.c]
+	Added stub for EnableCommNotification().
+
+	* [misc/ver.c]
+	Fixed problem with VerQueryValue*() running over end of name table
+	in rare cases.
+
+	* [msdos/int21.c]
+	Enhanced ioctlGetDeviceInfo() to correctly return the current drive.
+
+	* [multimedia/joystick.c] [windows/message.c]
+	Added joystick support !!!
+	Needs Linux >= 2.1.45 or joystick-0.8.0.tar.gz.
+
+Fri Aug  1 18:02:09 1997  Morten Welinder  <terra@diku.dk>
+
+	* [if1632/user32.spec]
+	Define DrawAnimatedRects32.
+
+	* [graphics/painting.c]
+	(DrawAnimatedRects32): Create stub.
+
+	* [misc/registry.c]
+	Cope with NULL class in RegQueryInfoKey32A.
+
+	* [if1632/user32.spec]
+	Add GetMenuItemInfo32[AW].
+
+	* [controls/menu.c]
+	(InsertMenu32A): Upgrade flags to 8 hex-digits.
+	(MENUEX_ParseResource): First shot at implementation.
+	(LoadMenuIndirect32A): Handle extended menus.
+	(GetMenuItemInfo32[AW]): First shot at implementation.
+
+	* [include/windows.h]
+	Define MFT_*, MFS_*, MIIM_* macros.  Define MENUITEMINFO[AW]
+ 	structures and pointers.
+
+	* [Makefile.in]
+	(etags): Add TAGS as target.
+
+	* [if1632/comctl32.spec]
+	Use Windows 95's ordinals.  Add a few missing stubs.
+
+Thu Jul 31 14:01:13 1997  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
+
+	* [objects/color.c]
+	Fix for 16 color mode of XFree.
+
+	* [if1632/kernel32.spec][win32/ordinals.c]
+	Moved/added some ordinal only exported functions from kernel32.dll
+	(mostly thunking preparation stuff).
+
+Wed Jul 30 09:16:38 1997  John Harvey <john@division.co.uk>
+
+	* [graphics/win16drv/init.c] [include/win16drv.h]
+        Escape(SETABORTPROC) returns success to keep pbrush.exe happy.
+        Escape(NEXTBAND) implemented to make HP PCL printer driver work in
+ 	word.  Stub for PATBLT added to start work on printing more than
+ 	text.
+
+Mon Jul 28 13:14:28 1997  Victor Schneider <vischne@ibm.net>
+
+	* [libtest/expand.c]
+	New Winelib test program.
+
+Wed Jul 23 09:37:13 1997  Adrian Harvey <adrian@select.com.au>
+
+	* [tools/build.c] [tools/build-spec.txt] [if1632/kernel.spec]
+	  [if1632/user.spec]
+	Added ability to set filename wine considers the built-in DLLs 
+	to be in  to something other than name.DLL with new "file" key
+	in .spec files.
+	Made kernel filename KRNL386.EXE (some programs use this name 
+	explicitly - ChemOffice install now starts up).
+	Made user filename USER.EXE (just to be tidy).
+
+Sun Jul 20 23:51:02 1997  David A. Cuthbert <dacut@henry.ece.cmu.edu>
+
+	* [controls/menu.c] [misc/tweak.c] [include/tweak.h]
+	Fixed MENU_KeyLeft and MENU_KeyRight to handle multiple-column
+	menus.  Misc menu drawing issues for Win95 tweaks fixed.  Misc
+	warnings fixed.
+
+	* [loader/module.c]
+	Spaces are now permitted in file/path names on the command line.
+	If multiple matches can be made, the preferred match is the
+	path/file with fewer spaces.
+
+Tue Jul 29 02:21:15 1997  Bruce Milner <Bruce.Milner@genetics.utah.edu>
+
+	* [misc/compobj.c]
+	Added CLSIDFromString and StringFromCLSID.
+
+----------------------------------------------------------------------
 Sat Jul 19 13:03:01 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>
 
 	* [tools/build.c] [include/stackframe.h]
diff --git a/Make.rules.in b/Make.rules.in
index fd758a1..f637307 100644
--- a/Make.rules.in
+++ b/Make.rules.in
@@ -27,10 +27,14 @@
 YACC      = @YACC@
 LEX       = @LEX@
 LEXLIB    = @LEXLIB@
+RANLIB    = @RANLIB@
+LN_S      = @LN_S@
 DIVINCL   = -I$(TOPSRCDIR)/include -I$(TOPOBJDIR)/include -I$(SRCDIR) -I.
 ALLCFLAGS = $(CFLAGS) $(DEFS) $(OPTIONS) $(DIVINCL) $(X_CFLAGS)
 LDCOMBINE = ld -r
+AR        = ar rc
 RM        = rm -f
+MKDIR     = mkdir
 BUILD     = $(TOPOBJDIR)/tools/build@PROGEXT@
 MAKEDEP   = $(TOPOBJDIR)/tools/makedep@PROGEXT@
 WINERC    = $(TOPOBJDIR)/rc/winerc@PROGEXT@
@@ -38,6 +42,20 @@
 SUBMAKE   = $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'OPTIONS=$(OPTIONS)'
 @SET_MAKE@
 
+# Installation infos
+
+INSTALL         = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA    = @INSTALL_DATA@
+prefix          = @prefix@
+exec_prefix     = @exec_prefix@
+bindir          = @bindir@
+libdir          = @libdir@
+infodir         = @infodir@
+mandir          = @mandir@/man1
+manext          = .1
+includedir      = @includedir@/wine
+
 OBJS = $(GEN_C_SRCS:.c=.o) $(C_SRCS:.c=.o) \
        $(GEN_ASM_SRCS:.s=.o) $(ASM_SRCS:.S=.o) $(EXTRA_OBJS)
 
@@ -96,7 +114,7 @@
 	$(MAKEDEP) $(DIVINCL) -C. $(GEN_C_SRCS) -C$(SRCDIR) $(C_SRCS)
 
 clean::
-	$(RM) *.o \#*\# *~ *.bak *.orig *.rej *.flc winerctmp.c $(GEN_C_SRCS) $(GEN_C_SRCS:.c=.h) $(GEN_ASM_SRCS) $(PROGRAMS)
+	$(RM) *.o \#*\# *~ *.bak *.orig *.rej *.flc winerctmp.c core $(GEN_C_SRCS) $(GEN_C_SRCS:.c=.h) $(GEN_ASM_SRCS) $(PROGRAMS)
 
 dummy:
 
diff --git a/Makefile.in b/Makefile.in
index 61649fe..8028391 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -3,47 +3,23 @@
 # all (default):	build wine
 # clean:		remove all intermediate files
 # distclean:		also remove all files created by configure
+# install:              install everything
 # depend:		create the dependencies
-# etags:		Create a TAGS file for Emacs.
+# etags:		create a TAGS file for Emacs.
 #
-# Author: Michael Patra   <micky@marie.physik.tu-berlin.de>
-#                         <patra@itp1.physik.tu-berlin.de>
-
-# First some useful definitions
-
-SHELL     = /bin/sh
-CC        = @CC@
-CFLAGS    = @CFLAGS@
-OPTIONS   = @OPTIONS@
-X_LIBS    = @X_LIBS@
-TOPSRC    = @top_srcdir@
-XPM_LIB   = -lXpm
-XLIB      = @X_PRE_LIBS@ -lXext -lX11 @X_EXTRA_LIBS@
-LDLIBS    = @LDLIBS@
-AR        = ar rc
-RANLIB    = @RANLIB@
-RM        = rm -f
-MKDIR     = mkdir
-SUBMAKE   = $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'OPTIONS=$(OPTIONS)'
-@SET_MAKE@
-
-# Installation infos
-
-INSTALL         = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA    = @INSTALL_DATA@
-prefix          = @prefix@
-exec_prefix     = @exec_prefix@
-bindir          = @bindir@
-libdir          = @libdir@
-mandir          = @mandir@/man1
-manext          = .1
-includedir      = @includedir@/wine
 
 # Main target to build
 
 MAIN_TARGET = @MAIN_TARGET@
 
+# Directories
+
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = .
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = none
+
 COMMONSUBDIRS = \
 	rc \
 	controls \
@@ -76,6 +52,7 @@
 
 DOCSUBDIRS = documentation
 
+# All sub-directories
 ALLSUBDIRS = \
 	$(COMMONSUBDIRS) \
 	$(EMUSUBDIRS) \
@@ -83,6 +60,12 @@
 	$(PROGSUBDIRS) \
 	$(DOCSUBDIRS)
 
+# Sub-directories to run make depend into
+DEPENDSUBDIRS = $(COMMONSUBDIRS) $(LIBSUBDIRS) $(EMUSUBDIRS) $(DOCSUBDIRS)
+
+# Sub-directories to run make install into
+INSTALLSUBDIRS = $(DOCSUBDIRS)
+
 COMMONOBJS = \
 	controls/controls.o \
 	files/files.o \
@@ -109,10 +92,11 @@
 
 LIBOBJS = library/library.o
 
-
 all: $(MAIN_TARGET)
 
-install: install_$(MAIN_TARGET)
+@MAKE_RULES@
+
+install:: install_$(MAIN_TARGET)
 
 wine wine.sym: $(COMMONSUBDIRS) $(EMUSUBDIRS) dummy
 	$(CC) -o wine $(COMMONOBJS) $(EMUOBJS) $(LDOPTIONS) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LDLIBS)
@@ -120,7 +104,6 @@
 
 install_wine: dummy
 	$(INSTALL_PROGRAM) wine $(bindir)/wine
-	$(INSTALL_DATA) $(TOPSRC)/wine.man $(mandir)/wine$(manext)
 
 libwine.a: $(COMMONSUBDIRS) $(LIBSUBDIRS) dummy
 	$(RM) $@
@@ -146,17 +129,18 @@
 install_programs: dummy
 	@cd programs; $(SUBMAKE) install
 
-depend: dummy
-	for i in $(COMMONSUBDIRS) $(LIBSUBDIRS) $(EMUSUBDIRS) $(DOCSUBDIRS); do \
-	  (cd $$i; $(MAKE) depend) || exit 1; \
-	done
+install::
+	for i in $(INSTALLSUBDIRS); do (cd $$i && $(MAKE) install) || exit 1; done
 
-etags:
-	etags `find . -name '*.[chS]' -print | grep -v dbgmain`
+depend:: dummy
+	for i in $(DEPENDSUBDIRS); do (cd $$i && $(MAKE) depend) || exit 1; done
 
-clean:
+TAGS etags:
+	etags `find $(TOPSRCDIR) -name '*.[chS]' -print | grep -v dbgmain`
+
+clean::
 	for i in $(ALLSUBDIRS); do (cd $$i; $(MAKE) clean) || exit 1; done
-	for i in . include; do (cd $$i; $(RM) *.o \#*\# *~ *.bak *.orig *.rej *.flc); done
+	for i in include; do (cd $$i; $(RM) *.o \#*\# *~ *.bak *.orig *.rej *.flc); done
 	$(RM) wine wine.sym libwine.a libwine.so.1.0 TAGS
 
 distclean: clean
@@ -169,4 +153,4 @@
 include/config.h.in: configure.in include/acconfig.h
 	autoheader -l include
 
-dummy:
+### Dependencies:
diff --git a/configure b/configure
index bce2a75..d562686 100755
--- a/configure
+++ b/configure
@@ -1872,8 +1872,29 @@
 
 test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
 
+echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
+echo "configure:1877: 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
+  rm -f conftestdata
+if ln -s X conftestdata 2>/dev/null
+then
+  rm -f conftestdata
+  ac_cv_prog_LN_S="ln -s"
+else
+  ac_cv_prog_LN_S=ln
+fi
+fi
+LN_S="$ac_cv_prog_LN_S"
+if test "$ac_cv_prog_LN_S" = "ln -s"; then
+  echo "$ac_t""yes" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
 echo $ac_n "checking for i386_set_ldt in -li386""... $ac_c" 1>&6
-echo "configure:1877: checking for i386_set_ldt in -li386" >&5
+echo "configure:1898: 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
@@ -1881,7 +1902,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-li386  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1885 "configure"
+#line 1906 "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
@@ -1892,7 +1913,7 @@
 i386_set_ldt()
 ; return 0; }
 EOF
-if { (eval echo configure:1896: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1917: \"$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
@@ -1913,12 +1934,14 @@
 fi
 
 
+if test "$ac_cv_prog_LN_S" = "ln -s"; then : ; else LN_S=cp ; fi
+
 
 if test "x${GCC}" = "xyes"
 then
   CFLAGS="$CFLAGS -Wall"
   echo $ac_n "checking "for gcc strength-reduce bug"""... $ac_c" 1>&6
-echo "configure:1922: checking "for gcc strength-reduce bug"" >&5
+echo "configure:1945: 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
@@ -1926,7 +1949,7 @@
   ac_cv_c_gcc_strength_bug="yes"
 else
   cat > conftest.$ac_ext <<EOF
-#line 1930 "configure"
+#line 1953 "configure"
 #include "confdefs.h"
 
 int main(void) {
@@ -1937,7 +1960,7 @@
   exit( Array[1] != -2 );
 }
 EOF
-if { (eval echo configure:1941: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1964: \"$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
@@ -1960,7 +1983,7 @@
 
 
 echo $ac_n "checking "whether external symbols need an underscore prefix"""... $ac_c" 1>&6
-echo "configure:1964: checking "whether external symbols need an underscore prefix"" >&5
+echo "configure:1987: 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
@@ -1972,14 +1995,14 @@
 	.long 0
 EOF
 cat > conftest.$ac_ext <<EOF
-#line 1976 "configure"
+#line 1999 "configure"
 #include "confdefs.h"
 extern int ac_test;
 int main() {
 if (ac_test) return 1
 ; return 0; }
 EOF
-if { (eval echo configure:1983: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2006: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   ac_cv_c_extern_prefix="yes"
 else
@@ -2005,21 +2028,21 @@
 if test "$MAIN_TARGET" = "libwine.so.1.0"
 then
   echo $ac_n "checking "whether we can build a dll"""... $ac_c" 1>&6
-echo "configure:2009: checking "whether we can build a dll"" >&5
+echo "configure:2032: 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 2016 "configure"
+#line 2039 "configure"
 #include "confdefs.h"
 
 int main() {
 return 1
 ; return 0; }
 EOF
-if { (eval echo configure:2023: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2046: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   ac_cv_c_dll="yes"
 else
@@ -2046,12 +2069,12 @@
 for ac_func in memmove tcgetattr usleep wait4 waitpid
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2050: checking for $ac_func" >&5
+echo "configure:2073: 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 2055 "configure"
+#line 2078 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2074,7 +2097,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:2078: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2101: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -2099,12 +2122,12 @@
 done
 
 echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6
-echo "configure:2103: checking whether stat file-mode macros are broken" >&5
+echo "configure:2126: 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 2108 "configure"
+#line 2131 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -2155,12 +2178,12 @@
 fi
 
 echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:2159: checking for working const" >&5
+echo "configure:2182: 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 2164 "configure"
+#line 2187 "configure"
 #include "confdefs.h"
 
 int main() {
@@ -2209,7 +2232,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:2213: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2236: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_const=yes
 else
@@ -2230,12 +2253,12 @@
 fi
 
 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:2234: checking for ANSI C header files" >&5
+echo "configure:2257: 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 2239 "configure"
+#line 2262 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -2243,7 +2266,7 @@
 #include <float.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2247: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2270: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2260,7 +2283,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 2264 "configure"
+#line 2287 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -2278,7 +2301,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 2282 "configure"
+#line 2305 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -2299,7 +2322,7 @@
   :
 else
   cat > conftest.$ac_ext <<EOF
-#line 2303 "configure"
+#line 2326 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -2310,7 +2333,7 @@
 exit (0); }
 
 EOF
-if { (eval echo configure:2314: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2337: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
 then
   :
 else
@@ -2334,12 +2357,12 @@
 fi
 
 echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:2338: checking for size_t" >&5
+echo "configure:2361: 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 2343 "configure"
+#line 2366 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -2549,6 +2572,7 @@
 s%@RANLIB@%$RANLIB%g
 s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
 s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@LN_S@%$LN_S%g
 /@MAKE_RULES@/r $MAKE_RULES
 s%@MAKE_RULES@%%g
 
diff --git a/configure.in b/configure.in
index 530f191..9e97d28 100644
--- a/configure.in
+++ b/configure.in
@@ -38,9 +38,13 @@
 AC_PROG_LEX
 AC_PROG_RANLIB
 AC_PROG_INSTALL
+AC_PROG_LN_S
 dnl Check for -li386 for NetBSD and OpenBSD
 AC_CHECK_LIB(i386,i386_set_ldt,LDLIBS="$LDLIBS -li386")
 
+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
+
 dnl **** Check for gcc strength-reduce bug ****
 
 if test "x${GCC}" = "xyes"
diff --git a/controls/edit.c b/controls/edit.c
index 469de64..0a8a3d48 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -3013,8 +3013,12 @@
 	 *	functions can be called, and in what order.
 	 */
 	EDIT_WM_SetFont(wnd, es, 0, FALSE);
-	if (cs->lpszName && *(cs->lpszName) != '\0')
+	if (cs->lpszName && *(cs->lpszName) != '\0') {
 		EDIT_EM_ReplaceSel(wnd, es, FALSE, cs->lpszName);
+                /* if we insert text to the editline, the text scrolls out of the window, as the caret is placed after the insert pos normally; thus we reset es->selection... to 0 and update caret */
+                es->selection_start = es->selection_end = 0;
+                EDIT_EM_ScrollCaret(wnd, es);
+        }
 	return 0;
 }
 
diff --git a/controls/menu.c b/controls/menu.c
index d99b6cc..769084b 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -167,7 +167,7 @@
 	fprintf( stderr, "Unable to load default system menu\n" );
     }
 
-    dprintf_menu( stddeb, "MENU_CopySysPopup: returning %ld.\n", hMenu );
+    dprintf_menu( stddeb, "MENU_CopySysPopup: returning %d.\n", hMenu );
 
     return hMenu;
 }
@@ -279,6 +279,74 @@
 }
 
 
+/******************************************************************************
+ *
+ *   UINT32  MENU_GetStartOfNextColumn(
+ *     HMENU32  hMenu )
+ *
+ *****************************************************************************/
+
+static UINT32  MENU_GetStartOfNextColumn(
+    HMENU32  hMenu )
+{
+    POPUPMENU  *menu = (POPUPMENU *)USER_HEAP_LIN_ADDR(hMenu);
+    UINT32  i = menu->FocusedItem + 1;
+
+    if(!menu)
+	return NO_SELECTED_ITEM;
+
+    if( i == NO_SELECTED_ITEM )
+	return i;
+
+    for( ; i < menu->nItems; ++i ) {
+	if( menu->items[i].item_flags & MF_MENUBARBREAK )
+	    return i;
+    }
+
+    return NO_SELECTED_ITEM;
+}
+
+
+/******************************************************************************
+ *
+ *   UINT32  MENU_GetStartOfPrevColumn(
+ *     HMENU32  hMenu )
+ *
+ *****************************************************************************/
+
+static UINT32  MENU_GetStartOfPrevColumn(
+    HMENU32  hMenu )
+{
+    POPUPMENU const  *menu = (POPUPMENU *)USER_HEAP_LIN_ADDR(hMenu);
+    UINT32  i;
+
+    if( !menu )
+	return NO_SELECTED_ITEM;
+
+    if( menu->FocusedItem == 0 || menu->FocusedItem == NO_SELECTED_ITEM )
+	return NO_SELECTED_ITEM;
+
+    /* Find the start of the column */
+
+    for(i = menu->FocusedItem; i != 0 &&
+	    !(menu->items[i].item_flags & MF_MENUBARBREAK);
+	--i); /* empty */
+
+    if(i == 0)
+	return NO_SELECTED_ITEM;
+
+    for(--i; i != 0; --i) {
+	if(menu->items[i].item_flags & MF_MENUBARBREAK)
+	    break;
+    }
+
+    dprintf_menu( stddeb, "MENU_GetStartOfPrevColumn: ret %d.\n", i );
+
+    return i;
+}
+
+
+
 /***********************************************************************
  *           MENU_FindItem
  *
@@ -424,8 +492,8 @@
     DWORD dwSize;
     char *p;
 
-    dprintf_menu( stddeb, "MENU_CalcItemSize: HDC 0x%lx, item '%s', at "
-		  "(%d, %d) %s\n", hdc, lpitem->text, orgX, orgY,
+    dprintf_menu( stddeb, "MENU_CalcItemSize: HDC %p, item '%s', at "
+		  "(%d, %d) %s\n", (void *)hdc, lpitem->text, orgX, orgY,
 		  menuBar ? "(MenuBar)" : "" );
 
     SetRect32( &lpitem->rect, orgX, orgY, orgX, orgY );
@@ -689,12 +757,17 @@
 
     /* Draw the background */
     if(TWEAK_Win95Look) {
+	rect.left += 2;
+	rect.right -= 2;
+
+        /*
 	if(menuBar) {
 	    --rect.left;
 	    ++rect.bottom;
 	    --rect.top;
 	}
 	InflateRect32( &rect, -1, -1 );
+	*/
     }
 
     if (lpitem->item_flags & MF_HILITE) {
@@ -720,16 +793,20 @@
 
     if (!menuBar && (lpitem->item_flags & MF_MENUBARBREAK))
     {
-	SelectObject32( hdc, sysColorObjects.hpenWindowFrame );
-	MoveTo( hdc, rect.left, 0 );
-	LineTo32( hdc, rect.left, height );
+	if(TWEAK_Win95Look)
+	    TWEAK_DrawMenuSeparatorVert95(hdc, rect.left - 1, 3, height - 3);
+	else {
+	    SelectObject32( hdc, sysColorObjects.hpenWindowFrame );
+	    MoveTo( hdc, rect.left, 0 );
+	    LineTo32( hdc, rect.left, height );
+	}
     }
     if (lpitem->item_flags & MF_SEPARATOR)
     {
 	if(TWEAK_Win95Look)
-	    TWEAK_DrawMenuSeparator95(hdc, rect.left + 1,
-				      rect.top + SEPARATOR_HEIGHT / 2 + 1,
-				      rect.right - 1);
+	    TWEAK_DrawMenuSeparatorHoriz95(hdc, rect.left + 1,
+					   rect.top + SEPARATOR_HEIGHT / 2 + 1,
+					   rect.right - 1);
 	else {
 	    SelectObject32( hdc, sysColorObjects.hpenWindowFrame );
 	    MoveTo( hdc, rect.left, rect.top + SEPARATOR_HEIGHT/2 );
@@ -830,17 +907,19 @@
 			 DT_LEFT | DT_VCENTER | DT_SINGLELINE );
 	}
 	else {
-	    ++rect.left;
-	    ++rect.top;
-	    ++rect.right;
-	    ++rect.bottom;
-	    SetTextColor32(hdc, RGB(0xff, 0xff, 0xff));
-	    DrawText32A( hdc, lpitem->text, i, &rect,
-			 DT_LEFT | DT_VCENTER | DT_SINGLELINE );
-	    --rect.left;
-	    --rect.top;
-	    --rect.right;
-	    --rect.bottom;
+	    if (!(lpitem->item_flags & MF_HILITE)) {
+		++rect.left;
+		++rect.top;
+		++rect.right;
+		++rect.bottom;
+		SetTextColor32(hdc, RGB(0xff, 0xff, 0xff));
+		DrawText32A( hdc, lpitem->text, i, &rect,
+			     DT_LEFT | DT_VCENTER | DT_SINGLELINE );
+		--rect.left;
+		--rect.top;
+		--rect.right;
+		--rect.bottom;
+	    }
 	    SetTextColor32(hdc, RGB(0x80, 0x80, 0x80));
 	    DrawText32A( hdc, lpitem->text, i, &rect,
 			 DT_LEFT | DT_VCENTER | DT_SINGLELINE );
@@ -872,13 +951,16 @@
     RECT32 rect;
 
     GetClientRect32( hwnd, &rect );
-    rect.bottom -= POPUP_YSHADE * SYSMETRICS_CYBORDER;
-    rect.right -= POPUP_XSHADE * SYSMETRICS_CXBORDER;
+
+/*    if(!TWEAK_Win95Look) { */
+	rect.bottom -= POPUP_YSHADE * SYSMETRICS_CYBORDER;
+	rect.right -= POPUP_XSHADE * SYSMETRICS_CXBORDER;
+/*    } */
 
     if((hPrevBrush = SelectObject32( hdc, sysColorObjects.hbrushMenu )))
     {
 	HPEN32 hPrevPen;
-
+	
 	Rectangle32( hdc, rect.left, rect.top, rect.right, rect.bottom );
 
 	hPrevPen = SelectObject32( hdc, GetStockObject32( NULL_PEN ) );
@@ -1380,6 +1462,68 @@
 }
 
 
+/**********************************************************************
+ *         MENUEX_ParseResource
+ *
+ * Parse an extended menu resource and add items to the menu.
+ * Return a pointer to the end of the resource.
+ */
+static LPCSTR MENUEX_ParseResource( LPCSTR res, HMENU32 hMenu)
+{
+    DWORD flags;
+    DWORD state;
+    DWORD id;
+    LPCWSTR str;
+    WORD resinfo;
+
+    do
+    {
+        /* printf ("%p:", res); */
+
+        flags = GET_DWORD(res);
+        res += sizeof(DWORD);
+        state = GET_DWORD(res);
+        res += sizeof(DWORD);
+        id = GET_DWORD(res);
+        res += sizeof(DWORD);
+	resinfo = GET_WORD(res); /* FIXME: for 16-bit apps this is a byte.  */
+        res += sizeof(WORD);
+	/* Align the text on a word boundary.  */
+	res += (~((int)res - 1)) & 1;
+        str = (LPCWSTR)res;
+        res += (1 + lstrlen32W (str)) * sizeof(WCHAR);
+	/* Align the following fields on a dword boundary.  */
+	res += (~((int)res - 1)) & 3;
+
+        /* FIXME: This is inefficient and cannot be optimised away by gcc.  */
+	{
+	  LPSTR newstr = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
+	  dprintf_menu (stddeb, "Menu item: [%08lx,%08lx,%04lx,%04x,%s]\n",
+			flags, state, id, resinfo, newstr);
+	  HeapFree( GetProcessHeap(), 0, newstr );
+	}
+
+        if (resinfo & 1) /* Pop-up? */
+        {
+	    DWORD helpid = GET_DWORD(res); /* FIXME: use this.  */
+            HMENU32 hSubMenu = CreatePopupMenu32();
+	    res += sizeof(DWORD);
+            if (!hSubMenu) return NULL;
+            if (!(res = MENUEX_ParseResource( res, hSubMenu)))
+                return NULL;
+            AppendMenu32W( hMenu, flags | MF_POPUP /* HACK!  FIXME */,
+			   (UINT32)hSubMenu, (LPCWSTR)str );
+        }
+        else  /* Not a popup */
+        {
+	  AppendMenu32W( hMenu, flags, id,
+			 *(LPCWSTR)str ? (LPCWSTR)str : NULL );
+        }
+    } while (!(resinfo & MF_END));
+    return res;
+}
+
+
 /***********************************************************************
  *           MENU_GetSubPopup
  *
@@ -1861,10 +2005,20 @@
 {
     POPUPMENU *menu;
     HMENU32 hmenutmp, hmenuprev;
+    UINT32  prevcol;
 
     hmenuprev = hmenutmp = pmt->hTopMenu;
     menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenutmp );
 
+    /* Try to move 1 column left (if possible) */
+    if( (prevcol = MENU_GetStartOfPrevColumn( pmt->hCurrentMenu )) != 
+	NO_SELECTED_ITEM ) {
+	
+	MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
+			 prevcol, TRUE );
+	return;
+    }
+
     /* close topmost popup */
     while (hmenutmp != pmt->hCurrentMenu)
     {
@@ -1904,6 +2058,13 @@
 {
     HMENU32 hmenutmp;
     POPUPMENU *menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( pmt->hTopMenu );
+    UINT32  nextcol;
+
+    dprintf_menu( stddeb, "MENU_KeyRight called, cur %x (%s), top %x (%s).\n",
+		  pmt->hCurrentMenu,
+		  ((POPUPMENU *)USER_HEAP_LIN_ADDR(pmt->hCurrentMenu))->
+		     items[0].text,
+		  pmt->hTopMenu, menu->items[0].text );
 
     if ( (menu->wFlags & MF_POPUP) || (pmt->hCurrentMenu != pmt->hTopMenu))
     {
@@ -1916,6 +2077,15 @@
 	if (hmenutmp != pmt->hCurrentMenu) return;
     }
 
+    /* Check to see if there's another column */
+    if( (nextcol = MENU_GetStartOfNextColumn( pmt->hCurrentMenu )) != 
+	NO_SELECTED_ITEM ) {
+	dprintf_menu( stddeb, "KeyRight: Going to %d.\n", nextcol );
+	MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
+			 nextcol, TRUE );
+	return;
+    }
+
     if (!(menu->wFlags & MF_POPUP))	/* menu bar tracking */
     {
 	if( pmt->hCurrentMenu != pmt->hTopMenu )
@@ -2687,10 +2857,10 @@
     MENUITEM *item;
 
     if (IS_STRING_ITEM(flags) && str)
-        dprintf_menu( stddeb, "InsertMenu: hMenu %04x, pos %d, flags %04x, "
+        dprintf_menu( stddeb, "InsertMenu: hMenu %04x, pos %d, flags %08x, "
 		      "id %04x, str '%s'\n",
                       hMenu, pos, flags, id, str );
-    else dprintf_menu( stddeb, "InsertMenu: hMenu %04x, pos %d, flags %04x, "
+    else dprintf_menu( stddeb, "InsertMenu: hMenu %04x, pos %d, flags %08x, "
 		       "id %04x, str %08lx (not a string)\n",
                        hMenu, pos, flags, id, (DWORD)str );
 
@@ -3341,24 +3511,36 @@
     WORD version, offset;
     LPCSTR p = (LPCSTR)template;
 
-    dprintf_menu(stddeb,"LoadMenuIndirect16: %p\n", template );
+    dprintf_menu(stddeb,"LoadMenuIndirect32A: %p\n", template );
     version = GET_WORD(p);
     p += sizeof(WORD);
-    if (version)
-    {
+    switch (version)
+      {
+      case 0:
+	offset = GET_WORD(p);
+	p += sizeof(WORD) + offset;
+	if (!(hMenu = CreateMenu32())) return 0;
+	if (!MENU_ParseResource( p, hMenu, TRUE ))
+	  {
+	    DestroyMenu32( hMenu );
+	    return 0;
+	  }
+	return hMenu;
+      case 1:
+	offset = GET_WORD(p);
+	p += sizeof(WORD) + offset;
+	if (!(hMenu = CreateMenu32())) return 0;
+	if (!MENUEX_ParseResource( p, hMenu))
+	  {
+	    DestroyMenu32( hMenu );
+	    return 0;
+	  }
+	return hMenu;
+      default:
         fprintf( stderr, "LoadMenuIndirect32A: version %d not supported.\n",
                  version );
         return 0;
-    }
-    offset = GET_WORD(p);
-    p += sizeof(WORD) + offset;
-    if (!(hMenu = CreateMenu32())) return 0;
-    if (!MENU_ParseResource( p, hMenu, TRUE ))
-    {
-        DestroyMenu32( hMenu );
-        return 0;
-    }
-    return hMenu;
+      }
 }
 
 
@@ -3382,6 +3564,73 @@
     return (menu->wMagic == MENU_MAGIC);
 }
 
+/**********************************************************************
+ *		GetMenuItemInfo32_common
+ */
+
+static BOOL32 GetMenuItemInfo32_common ( HMENU32 hmenu, UINT32 item,
+					 BOOL32 bypos,
+					 LPMENUITEMINFO32A lpmii,
+					 BOOL32 unicode)
+{
+  MENUITEM *menu = MENU_FindItem (&hmenu, &item, bypos);
+  if (!menu) return FALSE;
+
+  if (lpmii->fMask && MIIM_TYPE)
+    {
+      lpmii->fType = menu->item_flags;
+      lpmii->dwTypeData = menu->text;
+      if (IS_STRING_ITEM (menu->item_flags))
+	{
+	  lpmii->cch = strlen (menu->text);
+	  if (unicode)
+	    ; /* UGH! FIXME */
+	}
+      else
+	lpmii->cch = 0;
+    }
+
+  if (lpmii->fMask && MIIM_STATE)
+    lpmii->fState = 0; /* FIXME -- not saved.  */
+
+  if (lpmii->wID && MIIM_ID)
+    lpmii->fType = menu->item_id;
+
+  if (lpmii->fMask && MIIM_SUBMENU)
+    lpmii->hSubMenu = menu->item_id; /* FIXME: ??? */
+
+  if (lpmii->fMask && MIIM_CHECKMARKS)
+    {
+      PCBITMAPS pCB = menu->pCB;
+      lpmii->hbmpChecked = pCB ? pCB->hCheckBit : 0;
+      lpmii->hbmpUnchecked = pCB ? pCB->hUnCheckBit : 0;
+    }
+
+  if (lpmii->fMask && MIIM_DATA)
+    lpmii->dwItemData = 0; /* FIXME -- not saved.  */
+
+  return TRUE;
+}
+
+/**********************************************************************
+ *		GetMenuItemInfo32A    (USER32.263)
+ */
+BOOL32 GetMenuItemInfo32A( HMENU32 hmenu, UINT32 item, BOOL32 bypos,
+			   LPMENUITEMINFO32A lpmii)
+{
+    return GetMenuItemInfo32_common (hmenu, item, bypos, lpmii, FALSE);
+}
+
+/**********************************************************************
+ *		GetMenuItemInfo32W    (USER32.264)
+ */
+BOOL32 GetMenuItemInfo32W( HMENU32 hmenu, UINT32 item, BOOL32 bypos,
+			   LPMENUITEMINFO32W lpmii)
+{
+    return GetMenuItemInfo32_common (hmenu, item, bypos,
+                                     (LPMENUITEMINFO32A)lpmii, TRUE);
+}
+
 
 /**********************************************************************
  *		IsMenu32    (USER32.345)
diff --git a/documentation/Makefile.in b/documentation/Makefile.in
index 2e6c4a7..fe1be2b 100644
--- a/documentation/Makefile.in
+++ b/documentation/Makefile.in
@@ -4,24 +4,43 @@
 VPATH     = @srcdir@
 MODULE    = none
 
+INCLUDES = \
+	AUTHORS \
+	LICENSE \
+	WARRANTY
+
 SOURCES = \
 	wine.texinfo \
-	$(TOPSRCDIR)/AUTHORS \
-	$(TOPSRCDIR)/LICENSE \
-	$(TOPSRCDIR)/WARRANTY
+	$(INCLUDES)
 
-all: wine.info
+INFOFILES = \
+	wine.info \
+	wine.info-1 \
+	wine.info-2
+
+DVIFILES = wine.dvi
+
+all: $(INFOFILES) $(DVIFILES)
 
 @MAKE_RULES@
 
-wine.info: $(SOURCES)
-	makeinfo -I$(TOPSRCDIR) $(SRCDIR)/wine.texinfo
+$(INFOFILES): $(SOURCES)
+	makeinfo $(SRCDIR)/wine.texinfo
 
-wine.dvi: $(SOURCES)
+$(DVIFILES): $(SOURCES)
 	texi2dvi $(SRCDIR)/wine.texinfo
 
+$(INCLUDES):
+	$(RM) $(INCLUDES)
+	for i in $(INCLUDES); do $(LN_S) $(TOPSRCDIR)/$$i $$i || exit 1; done
+
+install:: $(INFOFILES)
+	for i in $(INFOFILES); do $(INSTALL_DATA) $$i $(infodir)/$$i; done
+	$(INSTALL_DATA) $(SRCDIR)/wine.man $(mandir)/wine$(manext)
+
 clean::
-	$(RM) wine.aux wine.cp wine.cps wine.dvi wine.fn wine.fns wine.info \
-		wine.ky wine.log wine.pg wine.toc wine.tp wine.tps wine.vr
+	$(RM) $(INFOFILES) $(DVIFILES) $(INCLUDES)
+	$(RM) wine.aux wine.cp wine.cps wine.fn wine.fns wine.ky wine.log \
+		wine.pg wine.toc wine.tp wine.tps wine.vr wine.vrs
 
 ### Dependencies:
diff --git a/wine.man b/documentation/wine.man
similarity index 100%
rename from wine.man
rename to documentation/wine.man
diff --git a/documentation/wine.texinfo b/documentation/wine.texinfo
index 1099cf3..a530871 100644
--- a/documentation/wine.texinfo
+++ b/documentation/wine.texinfo
@@ -24,7 +24,8 @@
 
 @c 
 Copyright @copyright{} 1997 The Wine authors. @*
-@xref{Authors}, for a list of the copyright holders.
+@xref{Authors, The Wine Authors, The Wine Authors},
+for a list of the copyright holders.
 
 Permission is granted to make and distribute verbatim
 copies of this manual provided the copyright notice and
@@ -44,6 +45,8 @@
 
 @sp 4
 FIXME: UNIX and POSIX trademarks. @*
+DOS @*
+X11 @*
 MS-Windows, Windows-NT, Windows 95 are registered trademarks of
 Microsoft Corp. Postscript is a registered trademark of Adobe Systems
 Inc. All other product names mentioned herein are the trademarks of
@@ -57,7 +60,7 @@
 @sp 10
 
 @center @titlefont{The Wine Reference Manual}
-@center Edition 0.0.1, 6 July 1997
+@center Edition 0.0.2, 21 July 1997
 
 
 @c The following two commands start the copyright page.
@@ -65,7 +68,8 @@
 @vskip 0pt plus 1filll
 
 Copyright @copyright{} 1997 The Wine authors. @*
-@xref{Authors}, for a list of the copyright holders.
+@xref{Authors, The Wine Authors, The Wine Authors},
+for a list of the copyright holders.
 
 Permission is granted to make and distribute verbatim
 copies of this manual provided the copyright notice and
@@ -91,20 +95,24 @@
 
 @c Edit this macro manually in the above parts of the document
 @macro winemanualversion
-0.0.1
+0.0.2
 @end macro
 
 @c Edit this macro manually in the above parts of the document
 @macro winemanualdate
-6 July 1997
+21 July 1997
 @end macro
 
 @c Edit this macro manually into the TeX titlepage
-@macro winemanualtitle {}
+@macro winemanualtitle
 The Wine Reference Manual
 @end macro
 
 @c
+@macro winelib
+Winelib
+@end macro
+@c
 @c MICROSOFT
 @c
 
@@ -118,6 +126,9 @@
 @macro WIN32
 WIN32
 @end macro
+@macro WIN16
+WIN16
+@end macro
 
 @c FIXME: automatical trademark reference
 @macro WINNT
@@ -142,6 +153,15 @@
 @macro posix
 POSIX
 @end macro
+
+@macro unicode
+Unicode
+@end macro
+
+@macro ascii
+ASCII
+@end macro
+
 @c
 @c THIS MANUAL
 @c
@@ -176,10 +196,49 @@
 Not yet implemented.
 @end macro
 
+@c
+@c MACROS FOR FUNCTIONS, TYPES, CONSTANTS, VARIABLES
+@c
 
+@c Constants in the WIN32 API
+@macro defvr_cw32 {restofline}
+@defvr Constant \restofline\
+@end macro
+@macro defvrx_cw32 {restofline}
+@defvrx Constant \restofline\
+@end macro
 
+@c Functions in the WIN32 API
+@macro deftypefn_w32 {restofline}
+@deftypefn {WIN32 function} \restofline\
+@end macro
+@macro deftypefnx_w32 {restofline}
+@deftypefnx {WIN32 function} \restofline\
+@end macro
 
+@c Types in the WIN32 API
+@macro deftp_w32 {restofline}
+@deftp {Data type} \restofline\
+@end macro
+@macro deftpx_w32 {restofline}
+@deftpx {Data type} \restofline\
+@end macro
 
+@c Macros internal to Wine
+@macro deffn_winemacro {restofline}
+@deffn {Wine internal macro} \restofline\
+@end macro
+@macro deffnx_winemacro {restofline}
+@deffn {Wine internal macro} \restofline\
+@end macro
+
+@c Constants internal to Wine
+@macro defvr_cwine {restofline}
+@defvr {Wine internal constant} \restofline\
+@end macro
+@macro defvrx_cwine {restofline}
+@defvrx {Wine internal constant} \restofline\
+@end macro
 
 
 @c
@@ -203,20 +262,20 @@
 * Copying::                     License, Warranty, and Authors of Wine.
 * Introduction::                A short overview.
 * Reference Manual::            The Wine reference manual.
-* Installation::                Installing Wine.
+* Installation::                Installing and configuring Wine.
 * The Wine Project::            How to contribute to Wine.
 * Concept Index::               Index of concepts and names.
 * Type Index::                  Index of types and type qualifiers.
 * Function Index::              Index of functions and function-like
                                 macros.
-* Variable Index::              Index of variables and variable-like
-                                macros.
+* Variable Index::              Index of variables, constants, and
+                                variable-like macros.
 * File Index::                  Index of programs and files.
 @end menu
 
 @node Copying, Introduction, Top, Top
 
-@unnumbered License, Warranty, and Authors of Wine.
+@unnumbered License, Warranty, and Authors of Wine
 @cindex copying conditions for Wine
 @cindex conditions for copying Wine
 @cindex Wine copying conditions
@@ -274,11 +333,99 @@
 @node Introduction, Reference Manual, Copying, Top
 @chapter Introduction
 
-FIXME: Somebody should say some solemn words.
+@center Wine:
+@center the WINdows Emulator,
+@center or Wine Is Not an Emulator
+
+FIXME: make an easy-readable fluent text out of this.
+
+Welcome to @winemanualtitle{}. This is edition @winemanualversion{},
+last updated @winemanualdate{}.
+
+@strong{What is Wine?}
+
+Wine is a program that allows running MS-Windows programs under X11.
+
+
+Wine incorporates two features, the program loader and @winelib{}:
+@enumerate
+@item
+You can run @mswindows{} binaries (programs) in Wine. Wine contains a
+program loader which loads and executes an @mswindows{} binary. It uses
+the @winelib{} features of Wine to translate @WIN32{} and @WIN16{} calls
+to their @unix{}/X11 equivalent.
+
+Both 16 bit and 32 bit binaries can be loaded.
+@item
+@winelib{}: Wine can also be used as a library which implements the 
+@mswindows{} API on top of a @unix{} or @unix{}-like operating system
+with X11. @winelib{} (i.e. the Wine library) translates @WIN16{} or
+@WIN32{} API calls to their @unix{}/X11 equivalent.
+
+You can write a user-level application program that calls the @WIN16{}
+or @WIN32{} API functions and compile it on a @unix{} box.
+@end enumerate
+
+@strong{Status}
+
+Wine is still at development stage. The file @file{ANNOUNCE} says,
+``This is still a developer's only release.  There are many bugs and
+many unimplemented API features.  Most applications still do not work
+correctly.''
+@xref{Warranty}, for additional information.
+
+@strong{Requirements}
+
+Wine needs an 80x86 CPU to run on. Emulating the CPU is currently not
+possible.
+
+Currently, you must have one of:
+@itemize @bullet
+@item
+Linux version 0.99.13 or above
+@item
+NetBSD-current
+@item
+FreeBSD-current or FreeBSD 1.1
+@end itemize
+You need X11, and you must have @file{libXpm} installed on your system.
+
+@strong{Availability}
+
+Wine is free software. The file @file{README} says, ``Basically, you can do
+anything with it, except claim that you wrote it.''
+@xref{Copying}, for more information.
+
+@strong{Performance}
+
+Wine is expected to run @mswindows{} binaries about the same speed as
+@mswindows{} would. However, be aware that the 16 bit versions of
+@mswindows{} programs are generally slower than their 32 bit
+counterparts.
+
+@strong{Further information}
+
+You should consult the files @file{README}, @file{ANNOUNCE},
+@file{RELEASE-NOTES}, @file{BUGS}, @file{LICENSE}, and @file{WARRANTY},
+in the root directory of the Wine distribution.
+
+The Wine FAQ, available from
+@url{ftp://ftp.asgardpro.com/wine/dave/Wine.FAQ},
+@url{ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/Wine.FAQ},
+@url{ftp://rtfm.mit.edu/pub/usenet-by-group/comp.emulators.ms-windows.wine/WINE_(WINdows_Emulator)_Frequently_Asked_Questions},
+@url{ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/Wine.FAQ},
+@url{http://www.asgardpro.com/wine/index.html},
+gives answer to a lot of questions.
+
+The Wine USENET newsgroup is interesting for developers. It discusses technical
+matters about Wine. The address is: @url{news:comp.emulators.ms-windows.wine}.
+
+
 
 @xref{The Wine Project}, if you consider contributing some work.
 
 
+
 @node Reference Manual, Installation, Introduction, Top
 
 @menu
@@ -305,11 +452,10 @@
 * Memory Management::           How your programs get memory from
                                 Wine.
 * I/O Facilities::              Input/Output in Wine.
-                                .everything except communication and windows
 * Communication::               How processes can communicate.
 * Windows and Graphics::        GUI functions of @WIN32{}.
 * Errors and Exceptions::       How your program can report errors.
-                                . messaging
+                                (messaging)
 * Resources::                   Functions for dealing with resources.
 * The Registry::                FIXME missing.
 * Dynamic Link Libraries::      Functions for dealing with DLL's.
@@ -344,22 +490,22 @@
 * Type FILETIME::               The data structure used for specifying
                                 file times.
 * Compare File Times::          Compare two file times.
-* Get File Times::              Get the time attributes of a file.
 @end menu
 
 @c
 @c *** struct FILETIME ***
 @c
 @node Type FILETIME, Compare File Times, , File Times
+@subsubsection Type FILETIME
 
 @noindent
 File times in Wine are specified by the data type @code{FILETIME},
 defined in @file{windows.h}.
-
-@deftp {Data type} FILETIME
+@deftp_w32  FILETIME
+@deftpx_w32 LPFILETIME
 This is the data type for specifying file times. The file times are
 stored with 64 bit precision. The actual data type is a structure with
-two 32 bit values which are interpreted as the low and high parts of a
+two 32-bit values which are interpreted as the low and high parts of a
 64-bit value. This value gives a time measured in a granularity of 100
 nanoseconds, so 1.5 seconds are specified by a value of 15,000,000.  In
 Wine, this 64-bit value is signed, with the sign taken from the high
@@ -367,11 +513,11 @@
 
 The definition of @code{FILETIME} reads:
 @example
-typedef struct _FILETIME
+typedef struct
 @{
     INT32 dwLowDateTime;
     INT32 dwHighDateTime;
-@} FILETIME;
+@} FILETIME, *LPFILETIME;
 @end example
 
 @cindex epoch in file time
@@ -381,6 +527,8 @@
 Universal Time, which is GMT, Greenwich Mean Time). This might be
 called the @dfn{epoch} for file times. With a signed 64-bit value, this
 representation covers absolute times of 29247 years around the epoch.
+To convert this type to local time, use the function
+@code{FileTimeToLocalFileTime}. 
 
 @windiff{}
 In @mswindows{}, the elements of the structure are apparently of type
@@ -391,14 +539,13 @@
 @c
 @c *** CompareFileTime ***
 @c
-@node Compare File Times, Get File Times, Type FILETIME, File Times
+@node Compare File Times, , Type FILETIME, File Times
 
 @noindent
 The Wine function @code{CompareFileTime} compares two file times, and
 returns whether the first time is less than, equal to, or greater than
 the second file time. It is defined in @file{windows.h}.
-
-@deftypefn {WIN32 function} LONG CompareFileTime (@w{CONST FILETIME* @var{time_1},} @w{CONST FILETIME* @var{time_2})}
+@deftypefn_w32 LONG CompareFileTime (@w{CONST FILETIME* @var{time_1},} @w{CONST FILETIME* @var{time_2})}
 This function returns @code{1}, if @var{time_1} is greater than
 @var{time_2}, @code{-1} if it is less, and @code{0} if both times are
 equal. 
@@ -410,34 +557,6 @@
 @completionnone{}
 @end deftypefn
 
-@c
-@c ***GetFileTime ***
-@c
-@node Get File Times, , Compare File Times, File Times
-@noindent
-FIXME: move this function to the file IO section. @*
-The Wine function @code{GetFileTime} returns the creation time and
-the times of last the read and modification access to a file. It is
-defined in @file{windows.h}.
-
-@deftypefn {WIN32 function} BOOL GetFileTime (@w{HANDLE @var{file},} @w{LPFILETIME @var{ctime},} @w{LPFILETIME @var{atime},} @w{LPFILETIME @var{mtime})}
-This function obtains for the specified @var{file} the creation time
-@var{ctime}, the time of the last access to the file @var{atime}, and
-the time of the last modification (write) to the file, @var{mtime}.
-The @var{file} handle must have been obtained by opening the file with
-@code{GENERIC_READ} access. The file time arguments of this function are
-pointers to @code{FILETIME} variables, which are filled with a value that
-indicates an absolute time in UTC. To convert these values to local
-times, use the function @code{FileTimeToLocalFileTime}. If you do not
-need some of the times, you can pass a @code{NULL} pointer.
-The function returns @code{TRUE} on success, @code{FALSE} on failure.
-
-@winconfall{}
-
-@windiffnone{}
-@end deftypefn
-
-
 @node System Information, Memory Management, Date and Time, @WIN32{} Reference Manual
 @section System Information
 
@@ -447,6 +566,247 @@
 @node I/O Facilities, Communication, Memory Management, @WIN32{} Reference Manual
 @section I/O Facilities
 
+This section describes all input/output of a process, except for two
+topics: communication with other processes, and communication with the
+windowing system.
+
+@menu
+* I/O on Files::                Accessing the contents of files.
+* File System Interface::       Functions for manipulating files as a whole.
+@end menu
+
+@node I/O on Files, File System Interface, , I/O Facilities
+@subsection I/O on Files
+
+@node File System Interface, , I/O on Files, I/O Facilities
+@subsection File System Interface
+
+These functions are concerned with operating on files themselves, rather
+than on their contents.
+
+@menu
+* Type BY_HANDLE_FILE_INFORMATION::     The data structure used to
+                                        specify file information.
+* File attributes::                     The file attributes flags in
+                                        a file information structure.
+* Getting file information::            These functions let you obtain
+                                        information about a file.
+@end menu
+
+@node Type BY_HANDLE_FILE_INFORMATION, File attributes, , File System Interface
+@subsubsection The file information structure
+
+The file information structure of Wine is used to obtain information
+about files. It is declared in the header @file{winedows.h}.
+@deftp_w32 BY_HANDLE_FILE_INFORMATION
+This is the data type for specifying information about files as objects
+of the file system. It contains the following members:
+@table @code
+@item int dwFileAttributes
+   @cindex file attributes in file information
+   @cindex attributes of file in file information
+   @xref{File attributes}, for details.
+@item FILETIME ftCreationTime
+   @cindex creation time in file information
+   @cindex time of file creation in file information
+   The time when the file was created.
+   @xref{Type FILETIME}, for details.
+@item FILETIME ftLastAccessTime
+   @cindex access time in file information
+   @cindex time of file access in file information
+   The time when the file was last accessed.
+   @xref{Type FILETIME}, for details.
+@item FILETIME ftLastWriteTime
+   @cindex write time in file information
+   @cindex time of last file write in file information
+   The time when the file was last written to.
+   @xref{Type FILETIME}, for details.
+@item int dwVolumeSerialNumber
+   @cindex serial number of volume in file information
+   @cindex volume number (serial) in file information
+   The serial number of the volume containing the file. In Wine,
+   currently 0.
+@item int nFileSizeHigh
+   @cindex file size in file information
+   @cindex size of file in file information
+   A 32 bit value which contains the high part of the 64 bit file size.
+@item int nFileSizeLow
+   A 32 bit value which contains the low part of the 64 bit file size.
+@item int nNumberOfLinks
+   @cindex hard links number in file information
+   @cindex links (number of hard) in file information
+   This is the number of hard links to the file. In a file system which
+   does not support hard links, this is 1.
+@item int nFileIndexHigh
+   @cindex inode number in file information
+   @cindex file index in file information
+   @cindex index of file in file information
+   A 32 bit value which contains the high part of the 64 bit file
+   index. The file index is a unique number for a file on a volume.
+   This identifier cannot change while the file is opened by a process.
+   Together with the volume number, the file index is a unique
+   identifier for the file. This can be used by an application to check
+   whether two handles refer to the same file. Wine currently uses the
+   inode number for the file index.
+@item int nFileIndexLow
+   A 32 bit value which contains the low part of the 64 bit file index.
+@end table
+
+The definition of @code{BY_HANDLE_FILE_INFORMATION} reads:
+@example
+typedef struct
+@{
+  int dwFileAttributes;
+  FILETIME ftCreationTime;
+  FILETIME ftLastAccessTime;
+  FILETIME ftLastWriteTime;
+  int dwVolumeSerialNumber;
+  int nFileSizeHigh;
+  int nFileSizeLow;
+  int nNumberOfLinks;
+  int nFileIndexHigh;
+  int nFileIndexLow;
+@} BY_HANDLE_FILE_INFORMATION ;
+@end example
+
+The @code{BY_HANDLE_FILE_INFORMATION} structure can be obtained by the
+@code{GetFileInformationByHandle} function (@pxref{Getting file information}, for
+details).
+
+@windiff{}
+In @mswindows{}, the @code{int} elements of the structure are apparently
+of type @code{DWORD}.
+@end deftp
+
+@node File attributes, Getting file information, Type BY_HANDLE_FILE_INFORMATION, File System Interface
+@subsubsection The file attributes in a file information structure
+
+The file attributes in a file information structure and in other structures
+are a logical @emph{or} of one or more of the following constants:
+
+@defvr_cw32 FILE_ATTRIBUTE_READONLY
+The file is a read-only file. (Wine value: 0x0001).
+@end defvr
+@defvr_cw32 FILE_ATTRIBUTE_HIDDEN
+The file is a hidden file. Files in Wine do not have this attribute. (Wine value:
+0x0002).
+@end defvr
+@defvr_cw32 FILE_ATTRIBUTE_SYSTEM
+The file belongs to the operating system. Files in Wine do not have this
+attribute. (Wine value: 0x0004).
+@end defvr
+@defvr_cw32 FILE_ATTRIBUTE_LABEL
+This is not present in the @mswindows{} API. (Wine value: 0x0008).
+@end defvr
+@defvr_cw32 FILE_ATTRIBUTE_DIRECTORY
+The file is a directory. (Wine value: 0x0010).
+@end defvr
+@defvr_cw32 FILE_ATTRIBUTE_ARCHIVE
+The file is an archive file. All non-directory files are reported by Wine 
+to have this attribute. (Wine value: 0x0020).
+@end defvr
+@defvr_cw32 FILE_ATTRIBUTE_NORMAL
+The file does not have any other attributes set. This value must be used
+alone. In Wine, normal files are reported as archive files. (Wine value:
+0x0080).
+@end defvr
+@defvr_cw32 FILE_ATTRIBUTE_TEMPORARY
+The file is used as a temporary storage. Files in Wine do not have this
+attribute. (Wine value: 0x0100).
+@end defvr
+@defvr_cw32 FILE_ATTRIBUTE_ATOMIC_WRITE
+This is reserved for future use. Files in Wine do not have this
+attribute. (Wine value: 0x0200).
+@end defvr
+@defvr_cw32 FILE_ATTRIBUTE_XACTION_WRITE
+This is reserved for future use. Files in Wine do not have this
+attribute. (Wine value: 0x0400).
+@end defvr
+@defvr_cw32 FILE_ATTRIBUTE_COMPRESSED
+The file is compressed. Files in Wine do not have this attribute. (Wine
+value: 0x0800). 
+@end defvr
+
+@node Getting file information, , File attributes, File System Interface
+@subsubsection Getting file information
+
+The functions in this section describe how to get information about
+files. 
+
+@c
+@c *** GetFileInformationByHandle
+@c
+@noindent
+The Wine function @code{GetFileInformationByHandle} returns a file
+information structure. It is defined in @file{windows.h}.
+
+@deftypefn_w32 BOOL GetFileInformationByHandle (@w{HFILE32 @var{file},} @w{BY_HANDLE_FILE_INFORMATION *@var{info})}
+This function obtains for the specified @var{file} the file information,
+and stores it in @var{info}. The file information contains the file
+attributes, the file times, the volume serial number, the file size, the
+number of links, and a unique file identifier. The function returns
+@code{TRUE} on success, @code{FALSE} on failure.
+
+@winconfall{}
+
+@windiff{}
+The Wine function can of course only give back information that is
+accessible in the @unix{} file system. File times are produced in a
+granularity of full seconds. Most file attributes are not present in the
+@unix{} file system. @xref{File attributes}, for details. The volume
+serial number is set to 0.
+@end deftypefn
+
+
+@c
+@c *** GetFileTime ***
+@c
+@noindent
+The Wine function @code{GetFileTime} returns the creation time and
+the times of last the read and modification access to a file. It is
+defined in @file{windows.h}.
+
+@deftypefn_w32 BOOL GetFileTime (@w{HANDLE @var{file},} @w{LPFILETIME @var{ctime},} @w{LPFILETIME @var{atime},} @w{LPFILETIME @var{mtime})}
+This function obtains for the specified @var{file} the creation time
+@var{ctime}, the time of the last access to the file @var{atime}, and
+the time of the last modification (write) to the file, @var{mtime}.
+The file time arguments of this function are pointers to @code{FILETIME}
+variables, which are filled with a value that indicates an absolute time
+in UTC. @xref{Type FILETIME}, for details. If you do not need some of
+the times, you can pass a @code{NULL} pointer.
+The function returns @code{TRUE} on
+success, @code{FALSE} on failure.
+
+@winconfall{}
+
+@windiff{}
+The file times are produced in a granularity of full seconds, due to the
+underlying @unix{} file system. 
+@end deftypefn
+
+@c
+@c *** GetFileAttributes ***
+@c
+@noindent
+The Wine function @code{GetFileAttributes} returns the file attributes
+for a file. It is defined in @file{windows.h}.
+
+@deftypefn_w32 DWORD GetFileAttributes (@w{LPCTSTR @var{name})}
+This function looks up the file with name @var{name}, and returns the
+attributes of the file. @xref{File attributes}, for details on the file
+attributes. If the function is not successful, it returns a word with
+all bits set (@samp{0xffffffff}).
+
+@winconfall{}
+
+@windiff{}
+Most file attributes are not present in the
+@unix{} file system. @xref{File attributes}, for details.
+@end deftypefn
+
+
+
+
 @node Communication, Windows and Graphics, I/O Facilities, @WIN32{} Reference Manual
 @section Communication
 
@@ -465,6 +825,11 @@
 @node Dynamic Link Libraries, , The Registry, @WIN32{} Reference Manual
 @section Dynamic Link Libraries (DLL's)
 
+This section deals with API functions for handling DLL's (dynamic link
+libraries). It does not describe DLL's themselves; nor does it give
+information on how Wine handles DLL's. @xref{The build program}, for
+information on how DLL's are integrated into Wine.
+
 
 
 
@@ -483,8 +848,318 @@
 @node Tools, , Programs, Reference Manual
 @chapter Tools
 
+This chapter describes some of the tools that are used by Wine. These
+are not user-level programs which the user of Wine will
+run. @xref{Programs} for such programs.
+
+Tools are internal programs that are used to help compile or configure
+Wine.
+
+@menu
+* The build program::           A program used to build the DLL entry
+                                points from specifications in @file{if1632/}.
+@end menu
+
+
+@node The build program, , , Tools
+@section The @file{build} program
+
+@cindex modules of Wine
+@cindex Wine modules
+@cindex DLL's built-in in Wine
+@cindex Wine DLL's built-in
+@cindex built-in DLL's in Wine
+Wine contains several modules that implement various DLL's which are
+required to run @mswindows{} programs.
+
+The @file{build} program, located in the @file{tools/} directory, is
+used to create the bindings for the DLL entry points of the API functions.
+This program reads a @file{.spec}-file in the @file{if1632} directory
+and creates the assembly code that translates the function arguments
+correctly. 
+
+
+@menu
+* The spec files::              The format of the @file{.spec}-files.
+@end menu
+
+FIXME: where in Wine are the DLL's affixed?
+
+FIXME: write a description
+
+@xref{Implementing an API function}, for notes on using this program.
+
+@node The spec files, , , The build program
+@subsection The @file{.spec}-files
+@cindex DLL spec files
+@cindex spec files of DLL's
+@cindex entry points in DLL's
+
+This subsection describes the format of the @file{.spec}-files.
+
+A @file{.spec}-file contains the information about the functions,
+variables, and constants that are contained in a DLL (dynamic link
+library).
+
+To be able to interpret the contents of a @file{.spec}-file, you must
+know about the concept of ordinals.
+@menu
+* The general format::                  General format conventions.
+* Ordinals::                            Ordinals are indexes of entry
+                                        points into DLL's.
+* Spec file header::                    The header information.
+* Variable entry points::               Entries for DLL variables.
+* Function entry points::               Entries for DLL functions.
+* Special entries::                     Entries for stubs, dummy
+                                        functions, Wine symbols, and
+                                        constant values.
+@end menu
+
+@node The general format, Ordinals, , The spec files
+@subsubsection The general format
+@cindex format of spec files
+@cindex spec files format
+
+The @file{.spec}-file contains a header and a sequence of declarations.
+Each declaration describes an ordinal.
+
+The header gives general information about the DLL and its properties.
+
+Ordinal declarations are optional. That means that there is a default
+behaviour assigned to ordinals which are not mentioned in the
+@file{.spec}-file. The default handler function of an ordinal will print
+an error message when called.
+
+Comments are indicated by hash marks (@samp{#}); everything between a
+hash mark and the end of the line is ignored.
+
+Empty lines are allowed.
+@* FIXME: is that so?
+
+@node Ordinals, Spec file header, The general format, The spec files
+@subsubsection Ordinals
+@cindex ordinals in DLL's
+@cindex DLL ordinals
+
+All references to DLL objects like functions or variables are indexed by
+unique nonnegative numbers. These numbers are called
+@dfn{ordinals}. Apparently, a program can refer to a DLL function or
+variable by specifying its name or its ordinal. Although reference by
+name is the common usage, some program parts (notably DLL's themselves)
+sometimes refer to DLL entries by ordinal. Therefore, the ordinals
+cannot be chosen arbitrarily.
+@* FIXME: is that correct?
+
+@node Spec file header, Variable entry points, Ordinals, The spec files
+@subsubsection The header of a @file{.spec}-file
+
+The @file{.spec}-file starts with two mandatory definitions. The first
+line gives the name of the DLL which the @file{.spec}-file describes,
+@example
+name @var{NAME}
+@end example
+where @var{NAME} is the name of the DLL. The next line defines the type
+of the DLL, 
+@example
+type @var{TYPE}
+@end example
+with @var{TYPE} being either @samp{win16} or @samp{win32}.
+
+An optional statement of the form
+@example
+base @var{ORDINAL}
+@end example
+can be used to define the offset of the first ordinal. @var{ORDINAL}
+must be an integer number. If no base is specified, the offset is zero.
+@* FIXME: is this the offset of the first or an offset that is added to all
+ordinals?
+what is the offset? Is it added to the ordinals, or is it an address, or
+xxx?
+
+An optional statement like
+@example
+heap @var{SIZE}
+@end example
+can be used to define the size of the module local heap. This is only
+used for @WIN16{} DLL's. The local heap is the place where the segments
+of 16 bit programs can locally allocate memory, without interfering with
+one another. The default size of the local heap, if not specified, is 0.
+
+@* FIXME: to my impression, a local heap in DLL's would only be required
+if DLL functions used it. As all DLL functions in Wine are truly 32 bit
+functions that are mapped from 16 bit on being called and back to 16 bit
+on returning, a local heap should never be necessary.
+If I receive a confirmation of that here, I will state so. Otherwise I
+am missing some information on local heaps.
+But why is a heap defined in user.spec and gdi.spec?
+
+@node Variable entry points, Function entry points, Spec file header, The spec files
+@subsubsection Variable entry points of @file{.spec}-files
+
+You can declare an ordinal that holds data. Data items may be of 8, 16,
+or 32 bit in size.
+
+@example
+@var{ORDINAL} @var{VARTYPE} @var{EXPORTNAME} (@var{DATA} @var{[DATA @dots{}]})
+@end example
+
+@var{ORDINAL} is the ordinal number corresponding to the
+variable. @var{VARTYPE} must be @samp{byte}, @samp{word}, or
+@samp{long}, for 8, 16, or 32 bits respectively. @var{EXPORTNAME} will
+be the name available for dynamic linking. @var{DATA} can be a decimal
+number or a hex number preceded by @samp{0x}. Each @var{DATA} item defines
+a unit of storage.
+
+The following example defines the variable @samp{VariableA} at ordinal
+2, containing 4 bytes:
+@example
+2 byte VariableA(-1 0xff 0 0)
+@end example
+
+
+@node Function entry points, Special entries, Variable entry points, The spec files
+@subsubsection Function entry points of @file{.spec}-files
+
+@example
+@var{ORDINAL} @var{FUNCTYPE} @var{EXPORTNAME} (@var{[ARGTYPE} @dots{} @var{]}) @var{HANDLERNAME}
+@end example
+
+@var{ORDINAL} is the ordinal number corresponding to the
+function. @var{FUNCTYPE} must be chosen from this table:
+@table @samp
+@item pascal16
+A @WIN16{} function that returns a 16 bit value.
+@item pascal
+A @WIN16{} function that returns a 32 bit value.
+@item register
+A function using CPU registers to pass arguments.
+@item stdcall
+A normal @WIN32{} function.
+@item cdecl
+A @WIN32{} function using the C calling conventions. (This is presently
+only used for the built-in functions of the C runtime system).
+@end table
+
+@var{EXPORTNAME} specifies the name (prototype) available for dynamic
+linking.
+
+@var{ARGTYPE} must be chosen from this table:
+@table @samp
+@item byte
+  An 8 bit argument. Can be used in @WIN16{} functions only.
+@item word
+  A 16 bit argument. Can be used in @WIN16{} functions only.
+@item long
+  A 32 bit argument. Can be used in @WIN16{} or @WIN32{} functions.
+@item ptr
+  A linear pointer, unsegmented. Can be used in @WIN16{} or @WIN32{}
+  functions.
+@item str
+  A linear pointer, unsegmented, pointing to a null-terminated string.
+  Can be used in @WIN16{} or @WIN32{} functions.
+@item s_byte
+  A signed 8 bit argument. Can be used in @WIN16{} functions only.
+@item s_word
+  A signed 16 bit argument. Can be used in @WIN16{} functions only.
+@item s_long
+  A signed 32 bit argument. Can be used in @WIN16{} or @WIN32{}
+  functions.
+@item segptr
+  A segmented pointer. Can be used in @WIN16{} functions only.
+@item segstr
+  A segmented pointer to a null-terminated string. Can be used in
+  @WIN16{} functions only.
+@end table
+
+@var{HANDLERNAME} is the name of the actual Wine function that will
+process the request in 32-bit mode.
+
+
+@sp 2
+Here are some examples. The first example defines an entry point for the
+@code{CreateWindow()} call (the ordinal 100 is just an example):
+@example
+100 pascal CreateWindow(ptr ptr long s_word s_word s_word s_word
+                        word word word ptr) WIN_CreateWindow
+@end example
+
+The second example defines an entry point for the @code{GetFocus()} call
+(again, the ordinal 100 is an example):
+@example
+100 pascal GetFocus() WIN_GetFocus()
+@end example
+
+To declare a function that uses a variable number of arguments, specify
+the function as taking no arguments. In this special case, in @WIN32{}
+the called function will be passed a pointer to the first arg; in
+@WIN16{}, the args are available as @code{CURRENT_STACK16->args}.
+@* FIXME: create a reference here
+See the @code{wsprintf}* functions in @file{user.spec} and 
+@file{user32.spec} for an example.
+
+
+@node Special entries, , Function entry points, The spec files
+@subsubsection Special entries of @file{.spec}-files
+
+The @file{.spec}-files offer the possibility to use some special
+entries. These entries are used for stubs (which allow linking for
+non-existing functions), dummy functions that do not perform any
+operations, Wine symbols that must be referenced directly, and constant
+values.
+
+
+@strong{Stub ordinals}
+
+This pseudo function type defines a stub function. It makes the name and
+ordinal available for dynamic linking, but will terminate execution with
+an error message if the function is ever called.
+
+@example
+@var{ORDINAL} stub @var{EXPORTNAME}
+@end example
+
+@var{ORDINAL} is the ordinal number corresponding to the
+function. @var{EXPORTNAME} specifies the name (prototype) available for dynamic
+linking.
+
+@strong{Return ordinals}
+
+This pseudo function type defines a function entry point whose handler
+should do nothing but return a value.
+@example
+@var{ORDINAL} return @var{EXPORTNAME} @var{ARGLENGTH} @var{RETVALUE}
+@end example
+
+@var{ORDINAL} is replaced by the ordinal number corresponding to the
+function. @var{ARGLENGTH} is the number of bytes that need to be removed
+from the stack before returning to the caller. @var{RETVALUE} is the
+return value which will be passed back to the caller.
+
+@strong{Extern ordinals}
+
+@example
+@var{ORDINAL} extern @var{EXPORTNAME} @var{SYMBOLNAME}
+@end example
+This type defines an entry that simply maps to a Wine symbol
+(variable or function); @var{EXPORTNAME} will point to the symbol
+@var{SYMBOLNAME} that must be defined in C code. This type only works with
+@WIN32{}.
+
+
+@strong{Equate ordinals}
+
+@example
+@var{ORDINAL} equate @var{EXPORTNAME} @var{DATA}
+@end example
+
+This type defines an ordinal as an absolute value.
+@var{ORDINAL} is replaced by the ordinal number corresponding to the
+entry. @var{EXPORTNAME} will be the name available for dynamic linking.  
+@var{DATA} can be a decimal number or a hex number preceeded by @samp{0x}.
+
+
 @node Installation, The Wine Project, Reference Manual, Top
-@chapter Wine Installation
+@chapter Wine installation and configuration
 FIXME: write installation guide
 
 @menu
@@ -507,8 +1182,17 @@
 some suggestions. 
 
 @menu
-* Creating patches::            How to create patches for Wine.
-* Adding Documentation::        Templates for the documentation.
+* Implementing an API type::            How to implement a data type
+                                        of the API (a checklist).
+* Implementing an API function::        How to implement one function
+                                        of the API (a checklist).
+* API function and type naming::        How to name API functions in Wine.
+* Creating patches::                    How to create patches for Wine.
+* Adding Documentation::                Templates for the documentation.
+* File names::                          How Wine treats @mswindows{} and
+                                        @unix{} file names.
+* Wide character strings::              How Wine treats wide character
+                                        strings.
 @end menu
 
 @xref{Debugging}, for advice on how to debug Wine.
@@ -516,13 +1200,366 @@
 
 FIXME: what is most urgently needed
 
-@node Creating patches, Adding Documentation, , The Wine Project
+@node Implementing an API type, Implementing an API function, , The Wine Project
+@section Implementing an API type
+
+Here is a checklist that should help you writing your first API type. It
+will of course not tell you which elements to put into the type
+(assuming it is a structure), but it should help you along the way of
+integrating this type into Wine.
+@xref{Implementing an API function}, for comparison.
+
+@enumerate
+@item
+Find out how the type should be named in Wine and in the DLL's.
+@xref{API function and type naming}, for details.
+
+@item
+Find out where the type should go. Please try to keep the header files
+structure as similar to @mswindows{} as possible. 
+
+@item
+Prepare for the later patch (by saving the original files before you
+work on them). @xref{Creating patches}, for details.
+
+@item
+Put the type declaration into the header file.
+
+@item
+Make sure the declaration is syntactically correct, i.e. it does not
+keep Wine from compiling.
+
+@item
+Make sure the declared type is layout-compatible with
+@mswindows{}-compiled types. Especially keep an eye on the packing of
+the structure.
+@* FIXME: a reference to packed structures here.
+
+@item
+Build Wine and test the type, if possible. If you cannot test the
+type by implementing a proper API function, write a small test program
+to test it on its own. Or rather stop here.
+
+@item
+Write the documentation of the type in the @file{wine.texinfo}
+file. @xref{Adding Documentation}, for details.
+With types, be especially careful and document all the details. Also
+document all constants or flags that are used in the type.
+
+@item
+Create an entry in the @file{ChangeLog} file.
+
+@item
+Collect some of these changes, and create a patch. @xref{Creating
+patches}, for details.
+
+@item
+Mail the patch to Alexandre Julliard, @email{julliard@@lrc.epfl.ch}.
+
+@item
+Wait for the patch to appear in the official distribution.
+@end enumerate
+
+
+@node Implementing an API function, API function and type naming, Implementing an API type, The Wine Project
+@section Implementing an API function
+
+Here is a checklist that should help you writing your first API
+function. It will of course not tell you what to do in the function,
+but it should help you along the way of integrating this function into
+Wine.
+
+@enumerate
+@item
+Make sure all data types that appear in function arguments are properly
+declared in Wine. Otherwise, start with the data types.
+
+@item
+Find out how the function should be named in Wine and in the DLL's.
+@xref{API function and type naming}, for details.
+
+@item
+Find out where the function should go:
+@enumerate
+@item
+Which header file for the prototype.
+@item
+Which C source file.
+@item
+Which DLL(s), and which ordinal the function will take there. Perhaps
+the function name is already present in one of the @file{.spec}-files in
+the @file{if1632} directory.
+@end enumerate
+
+@item
+Prepare for the later patch (by saving the original files before you
+work on them). @xref{Creating patches}, for details.
+
+@item
+Put the prototype into the header file, and the code into the C file.
+
+@item
+Make sure the code compiles.
+
+@item
+Create or change the information for the DLL entry points in the
+@file{.spec}-file in the @file{if1632} directory.
+@xref{The build program}, for details of the DLL spec files.
+
+@item
+Build Wine and test the function, if possible. If you cannot test the
+function in Wine, write a small test program to test it on its own.
+
+@item
+Write the documentation of the function in the @file{wine.texinfo}
+file. @xref{Adding Documentation}, for details.
+
+@item
+Create an entry in the @file{ChangeLog} file.
+
+@item
+Collect some of these changes, and create a patch. @xref{Creating
+patches}, for details.
+
+@item
+Mail the patch to Alexandre Julliard, @email{julliard@@lrc.epfl.ch}.
+
+@item
+Wait for the patch to appear in the official distribution.
+@end enumerate
+
+
+@node API function and type naming, Creating patches, Implementing an API function, The Wine Project
+@section API function and data type naming conventions
+@cindex API function names
+@cindex API type names
+@cindex names of API functions and types
+@cindex naming scheme for API functions and types
+@cindex suffixes for API functions and types
+@cindex endings of API function and type names
+
+This section describes Wine's naming scheme for API functions and data
+types.
+
+The purpose of these naming conventions is to ensure that
+@itemize @bullet
+@item
+both the @WIN16{} and @WIN32{} API are supported within the same source
+code,
+@item
+both wide character functions (with @unicode{} strings) and 8 bit
+character functions (with @ascii{} or extended @ascii{} encoding) are
+supported, and
+@item
+the source code can be shared between the emulator and the library
+version of Wine.
+@end itemize
+
+A function or data type whose name in the @mswindows{} API is @var{xxx}
+will in the Wine code have the following name(s):
+@table @code
+@item @var{xxx}16
+This is the version for the 16 bit API. You might call it the ``16 bit
+version'' except that the function itself of course runs in true 32 bit
+mode (being part of Wine). So, the correct meaning of the suffix is that
+this function is part of the 16 bit API.
+@item @var{xxx}32
+This is the version for the 32 bit API. Use this suffix only if the
+function does not use character strings in its parameters or return
+values. Otherwise use the next two.
+@item @var{xxx}32A
+This is the version for the 32 bit API which uses @ascii{} strings (or
+rather, strings with 8 bit character encodings, i.e. the standard C
+@code{char} type). This version always goes together with another
+version, using the next suffix.
+@item @var{xxx}32W
+This is the version for the 32 bit API which uses @unicode{} strings,
+i.e. strings with wide characters. It goes together with the @ascii{}
+version.
+@end table
+
+So, where the @mswindows{} API offers one name, Wine actually has two or
+three different functions implemented (which will hopefully share a
+large part of the code).
+
+Wine allows to use its API functions in two ways. The emulator part of
+Wine provides DLL's for the @mswindows{} programs it can run. The
+library part of Wine provides a @unix{} programmer with the facility to
+use the Wine API's in a standard @unix{} program.
+
+@menu
+* Access from the emulator::    How to access API functions and types
+                                from applications that are run in the
+                                Wine emulator.
+* Access in the library::       How to access API functions and types
+                                from applications that are linked with
+                                the Wine library.
+* Access from inside Wine::     How to access API functions and types
+                                from inside the Wine code.
+@end menu
+
+@node Access from the emulator, Access in the library, , API function and type naming
+@subsection Accessing API functions and types from the emulator
+@cindex access to DLL API functions and types
+@cindex Wine emulator access to API functions and types
+@cindex emulator access to Wine API functions and types
+
+The emulator part of Wine provides the hooks for dynamically linking the
+API functions to the @mswindows{} executables (@file{.EXE}-files). The
+Wine emulator contains all versions (16 or 32 bit, @ascii{} or
+@unicode{}) of the API functions in one executable. The emulator
+performs a mapping from the @mswindows{} name of the function,
+by which the executable calls it, to one of the Wine internal names that
+have been used in coding it.
+
+This mapping is done by the built-in DLL handling code of Wine. A
+programmer of Wine has to declare the function in one of the virtual
+DLL's that are provided by Wine. The declarations are done in the
+@file{.spec}-files in the @file{if1632/} directory. @xref{The build
+program}, for details.
+
+The @mswindows{} application simply calls the API function by its
+standard @mswindows{} name. Wine will apply the correct mapping
+according to Wine's selected appearance (as a 16 bit or 32 bit emulator,
+which is a parameter on invocation of Wine).
+
+
+@node Access in the library, Access from inside Wine, Access from the emulator, API function and type naming
+@subsection Accessing API functions and types in the library
+@cindex Wine library API function and type access
+@cindex access to Wine library API functions and types
+
+If Wine is built as a library, and linked to a user-level main program,
+the user will also use the standard @mswindows{} names for the API
+functions.
+
+Some macros are defined in @file{include/wintypes.h} which perform the
+necessary name mappings. 
+
+These macros are (see the examples below):
+@deffn_winemacro WINELIB_NAME (@var{xxx})
+This macro replaces @var{xxx} by one of @var{xxx}16 or
+@var{xxx}32, depending on the definition of the symbols
+@code{WINELIB16} and @code{WINELIB32}. @var{xxx} should
+be the name of an API function that uses no string arguments.
+Use this macro with a @code{#define} to establish the API name @var{xxx}.
+@end deffn
+@deffn_winemacro WINELIB_NAME_AW (@var{xxx})
+This macro replaces @var{xxx} by one of @var{xxx}16, @var{xxx}32A, or
+@var{xxx}32W, depending on the definition of the symbols
+@code{WINELIB16}, @code{WINELIB32}, and @code{UNICODE}. @var{xxx} should
+be the name of an API function that uses string arguments.
+Use this macro with a @code{#define} to establish the API name @var{xxx}.
+@end deffn
+@deffn_winemacro DECL_WINELIB_TYPE (@var{xxx})
+This macro declares @var{xxx} to be an equivalent to @var{xxx}16 or
+@var{xxx}32, depending on the definition of the symbols
+@code{WINELIB16} and @code{WINELIB32}. @var{xxx} should
+be the name of an API data type that contains no string arguments.
+@end deffn
+@deffn_winemacro DECL_WINELIB_TYPE_AW (@var{xxx})
+This macro declares the type @var{xxx} to be an equivalent to
+@var{xxx}16, @var{xxx}32A, or @var{xxx}32W, depending on the definition
+of the symbols @code{WINELIB16}, @code{WINELIB32}, and
+@code{UNICODE}. @var{xxx} should be the name of an API data type that
+contains string arguments. 
+@end deffn
+
+If Wine is compiled as an emulator, these macros have no effect, for the
+mapping is then done by the DLL code. This means that within Wine the
+name @var{xxx} itself will not be defined.
+
+Note: If the definition of @var{xxx} is exactly the same in @WIN16{} and
+@WIN32{}, you can simply use the same name as @mswindows{}.
+
+Here are some examples:
+@example
+/* A simple type without strings */
+typedef short INT16;
+typedef int INT32;
+DECL_WINELIB_TYPE(INT);
+
+/* A type with strings */
+typedef struct @{ /* Win32 ASCII data structure */ @} WNDCLASS32A;
+typedef struct @{ /* Win32 Unicode data structure */ @} WNDCLASS32W;
+typedef struct @{ /* Win16 data structure */ @} WNDCLASS16;
+DECL_WINELIB_TYPE_AW(WNDCLASS);
+
+/* A function with strings */
+ATOM RegisterClass16( WNDCLASS16 * );
+ATOM RegisterClass32A( WNDCLASS32A * );
+ATOM RegisterClass32W( WNDCLASS32W * );
+#define RegisterClass WINELIB_NAME_AW(RegisterClass)
+@end example
+
+The Winelib user can then say (in the application program):
+@example
+    INT i;
+    WNDCLASS wc = @{ @dots{} @};
+    RegisterClass( &wc );
+@end example
+and this will use the correct declaration depending on the definitions
+@code{WINELIB16}, @code{WINELIB32}, and @code{UNICODE}.
+
+Here are the primary defines that are used when Wine is compiled as a
+library:
+@defvr_cwine WINELIB16
+If this @code{#define} is set, the Wine library is to be compiled in its
+16 bit form. That means, the 16 bit variants of all functions will be
+used and the appearance of the application linked with the Wine library
+will be that of a 16 bit application. Of course, both the application
+and the Wine library function really run in 32 bit mode. The switch only
+selects the function with the name ending in @code{@dots{}16}, which
+will perhaps have a behaviour different from its 32 bit counterpart.
+@end defvr
+@defvr_cwine WINELIB32
+If this @code{#define} is set, the Wine library is to be compiled in its
+32 bit form. That means, the 32 bit variants of all functions will be
+used and the appearance of the application linked with the Wine library
+will be that of a 32 bit application.
+@end defvr
+@defvr_cwine UNICODE
+This @code{define} is used to select one of two possible 32 bit
+variants. Functions and data types of the 32 bit API come in two
+flavours: one handling @ascii{} strings (or rather strings with
+characters encoded in 8 bit), the other @unicode{} strings. This define
+selects the correct variant. As a user of the Wine library, you are
+responsible to use the correct character type in your part of the
+application which accesses the Wine API functions and data types.
+@end defvr
+
+These switches are automatically set when Wine is compiled as a library.
+
+
+@node Access from inside Wine, , Access in the library, API function and type naming
+@subsection Accessing API functions from within Wine
+@cindex explicit names of API functions and types
+
+Within Wine and during the compilation of Wine, you cannot rely on the
+@mswindows{} names of the API functions and data types. If Wine is
+compiled as a library, they will be defined; if Wine is compiled as an
+emulator, they won't.
+
+You therefore have to access all functions and data types by their full
+names, with the proper suffix explicitely appended. In Wine, the 16 bit
+and 32 bit versions of the functions are distinct entities, which might
+(theoretically) show a completely different behaviour. They may even
+call each other (and they will quite frequently).
+
+Therefore Wine is a conglomerate that contains all two or
+three flavours of each function at once, and exports to the
+application whichever of these is appropriate. Remember that inside
+Wine, there is no memory segmentation, so all functions are 32 bit.
+The 16-to-32 bit mapping is done on exporting the DLL functions.
+
+
+@node Creating patches, Adding Documentation, API function and type naming, The Wine Project
 @section Creating patches
 @xref{Applying patches}, for instructions on applying patches.
 
 FIXME: how to create patches
 
-@node Adding Documentation, , Creating patches, The Wine Project
+@node Adding Documentation, File names, Creating patches, The Wine Project
 @section Adding Documentation
 
 @ifinfo
@@ -530,8 +1567,6 @@
 documentation. Read the text below before examining them.
 @end ifinfo
 
-FIXME they are not here in dvi
-
 @menu
 * Type Template::               How to document data types in Wine's
                                 include files.
@@ -552,6 +1587,9 @@
 
 Finally, read the info pages for @code{texinfo}.
 
+The rest of this section provides some templates which can serve as a
+start in writing documentation.
+
 @subsection Template introduction
 @iftex
 On the following pages you will find some @code{texinfo} templates, which
@@ -603,6 +1641,13 @@
 @@node Ints and Longs, NextNodeName, PreviousNodeName, ParentNodeName
 @end example
 
+After the node name, put a sectioning command, such as @samp{@@chapter},
+@samp{@@section}, @samp{@@subsection}, or @samp{@@subsubsection}.
+Without that command, cross references to the node will fail.
+@example
+@@subsubsection Type FILETIME
+@end example
+
 Start the description of the type(s) or function(s) with a single
 non-indented paragraph that gives a one-line description of the type(s)
 or function(s) and states the include files that are required.
@@ -616,11 +1661,13 @@
 description, indent all but the first of them.
 
 Then start the definition of the data type or function. Use the proper
-macro and specify a category and the  formal definition on the same
-line. For proper categories, take a look at the specialized templates.
+macro, which you will find defined in the beginning of the texinfo file.
+If appropriate, add your own macros.
 Again, put everything that belongs to the header into a single line.
+Use continuation lines for additional headers.
 @example
-@@deftp @{Data type@} FILETIME
+@@deftp_w32  FILETIME
+@@deftpx_w32 LPFILETIME
 @end example
 
 In the definition, give a verbal explanation of the data type or
@@ -647,11 +1694,11 @@
 @example
 The definition of @@code@{FILETIME@} reads:
 @@example
-typedef struct _FILETIME
+typedef struct
 @@@{
     INT32 dwLowDateTime;
     INT32 dwHighDateTime;
-@@@} FILETIME;
+@@@} FILETIME, *LPFILETIME;
 @@end example
 @end example
 
@@ -728,7 +1775,7 @@
 the times of last the read and modification access to a file. It is
 defined in @@file@{windows.h@}.
 
-@@deftypefn @{WIN32 function@} BOOL GetFileTime (@@w@{HANDLE @@var@{file@},@} @@w@{LPFILETIME @@var@{ctime@},@} @@w@{LPFILETIME @@var@{atime@},@} @@w@{LPFILETIME @@var@{mtime@})@}
+@@deftypefn_w32 BOOL GetFileTime (@@w@{HANDLE @@var@{file@},@} @@w@{LPFILETIME @@var@{ctime@},@} @@w@{LPFILETIME @@var@{atime@},@} @@w@{LPFILETIME @@var@{mtime@})@}
 This function obtains for the specified @@var@{file@} the creation time
 @@var@{ctime@}, the time of the last access to the file @@var@{atime@}, and
 the time of the last modification (write) to the file, @@var@{mtime@}.
@@ -747,8 +1794,40 @@
 @end example
 
 
+@node File names, Wide character strings, Adding Documentation, The Wine Project
+@section @mswindows{} and @unix{} file names in Wine
+@cindex file names in Wine
+@cindex Windows file names
+@cindex DOS file names in Wine
+@cindex UNIX file names in Wine
+@cindex POSIX file names in Wine
 
+FIXME:
 
+@node Wide character strings, , File names, The Wine Project
+@section Wide character strings in API functions
+@cindex unicode strings in API functions
+@cindex wide character strings in API functions
+@cindex strings in API functions
+@cindex ascii strings in API functions
+@cindex 16 bit characters in API functions
+@cindex wchar_t in API functions
+
+Presently, all wide character strings in API functions of Wine are
+internally converted to 8 bit representation. Thus, the @WIN32{} API
+with @unicode{} strings is not fully functional for the application
+programmer at present.
+
+Even so, application programmers might consider developing their
+applications in wide character format with Wine, as future versions
+might bring a change. This might come when a @unix{} filesystem can
+handle @unicode{} file names.
+
+Furthermore, the @unicode{} API is required to let Wine run @mswindows{}
+applications which have been compiled for wide character strings.
+
+In Wine, wide characters are strictly 16 bit; the @code{wchar_t} type of
+standard C can therefore not be used.
 
 @node Concept Index, , , Top
 @comment  node-name,  next,  previous,  up
@@ -767,7 +1846,7 @@
 
 @node Variable Index, , , Top
 @comment  node-name,  next,  previous,  up
-@unnumbered Variable Index
+@unnumbered Variable, Constants, and Variable-like Macros Index
 @printindex vr
 
 @node File Index, , , Top
diff --git a/files/directory.c b/files/directory.c
index 1abc4b2..6bc5c45 100644
--- a/files/directory.c
+++ b/files/directory.c
@@ -502,9 +502,9 @@
 
     /* First check the supplied parameters */
 
-    if (!(p = strrchr( name, '\\' ))) p = name;
-    if (!(p = strrchr( p, '/' ))) p = name;
-    if (strchr( p, '.' )) ext = NULL;  /* Ignore the specified extension */
+    p = strrchr( name, '.' );
+    if (p && !strchr( p, '/' ) && !strchr( p, '\\' ))
+        ext = NULL;  /* Ignore the specified extension */
     if ((*name && (name[1] == ':')) ||
         strchr( name, '/' ) || strchr( name, '\\' ))
         path = NULL;  /* Ignore path if name already contains a path */
diff --git a/files/file.c b/files/file.c
index 8b1c31e..742d518 100644
--- a/files/file.c
+++ b/files/file.c
@@ -951,7 +951,7 @@
     switch(mode & 3)
     {
     case OF_WRITE:
-        unixMode = O_WRONLY | O_TRUNC;
+        unixMode = O_WRONLY;
         break;
     case OF_READWRITE:
         unixMode = O_RDWR;
diff --git a/graphics/painting.c b/graphics/painting.c
index bad5182..ed96464 100644
--- a/graphics/painting.c
+++ b/graphics/painting.c
@@ -764,3 +764,14 @@
              hdc,rc,uType,uState );
     return TRUE;
 }
+
+/**********************************************************************
+ *          DrawFrameControl32  (USER32.152)
+ */
+BOOL32 DrawAnimatedRects32( HWND32 hwnd, int idAni,
+                           const LPRECT32 lprcFrom, const LPRECT32 lprcTo )
+{
+    fprintf( stdnimp,"DrawAnimatedRects32(%x,%d,%p,%p), empty stub!\n",
+             hwnd, idAni, lprcFrom, lprcTo );
+    return TRUE;
+}
diff --git a/graphics/win16drv/init.c b/graphics/win16drv/init.c
index ff48059..9fc2086 100644
--- a/graphics/win16drv/init.c
+++ b/graphics/win16drv/init.c
@@ -73,7 +73,7 @@
     NULL,                            /* pOffsetViewportOrgEx */
     NULL,                            /* pOffsetWindowOrgEx */
     NULL,                            /* pPaintRgn */
-    NULL,                            /* pPatBlt */
+    WIN16DRV_PatBlt,                 /* pPatBlt */
     NULL,                            /* pPie */
     NULL,                            /* pPolyPolygon */
     NULL,                            /* pPolygon */
@@ -223,13 +223,13 @@
     int nPDEVICEsize;
     PDEVICE_HEADER *pPDH;
     WIN16DRV_PDEVICE *physDev;
-
+    int numFonts;
     /* Realizing fonts */
     int nSize;
     char printerEnabled[20];
     PROFILE_GetWineIniString( "wine", "printer", "off",
                              printerEnabled, sizeof(printerEnabled) );
-    if (strcmp(printerEnabled,"on"))
+    if (lstrcmpi32A(printerEnabled,"on"))
     {
         printf("WIN16DRV_CreateDC disabled in wine.conf file\n");
         return FALSE;
@@ -323,6 +323,7 @@
 		wepfc.nCount = 0;
 		PRTDRV_EnumDFonts(physDev->segptrPDEVICE, NULL, pfnCallback, 
 				  (void *)&wepfc);
+                numFonts = wepfc.nCount;
 	    }
 	}
     }
@@ -378,7 +379,12 @@
     return TRUE;
 }
 
-
+extern BOOL32 WIN16DRV_PatBlt( struct tagDC *dc, INT32 left, INT32 top,
+                             INT32 width, INT32 height, DWORD rop )
+{
+  printf("In WIN16DRV_PatBlt\n");
+  return FALSE;
+}
 /* 
  * Escape (GDI.38)
  */
@@ -393,31 +399,56 @@
     if (dc != NULL && physDev->segptrPDEVICE != 0)
     {
 	switch(nEscape)
-	{
-	  case SETABORTPROC:
-	    printf("Escape: SetAbortProc ignored\n");
+          {
+          case SETABORTPROC:
+	    printf("Escape: SetAbortProc ignored should be stored in dc somewhere\n");
+            /* Make calling application believe this worked */
+            nRet = 1;
 	    break;
 
-	  case GETEXTENDEDTEXTMETRICS:
-	  {
-	    SEGPTR newInData =  WIN16_GlobalLock16(GlobalAlloc16(GHND, sizeof(EXTTEXTDATA)));
-            EXTTEXTDATA *textData = (EXTTEXTDATA *)(PTR_SEG_TO_LIN(newInData));
+          case NEXTBAND:
+            {
+              SEGPTR newInData =  WIN16_GlobalLock16(GlobalAlloc16(GHND, sizeof(POINT16)));
+              nRet = PRTDRV_Control(physDev->segptrPDEVICE, nEscape,
+                                    newInData, lpOutData);
+              GlobalFree16(newInData);
+              break;
+            }
 
-	    textData->nSize = cbInput;
-	    textData->lpindata = lpInData;
-	    textData->lpFont = physDev->segptrFontInfo;
-	    textData->lpXForm = win16drv_SegPtr_TextXForm;
-	    textData->lpDrawMode = win16drv_SegPtr_DrawMode;
+	  case GETEXTENDEDTEXTMETRICS:
+            {
+              SEGPTR newInData =  WIN16_GlobalLock16(GlobalAlloc16(GHND, sizeof(EXTTEXTDATA)));
+              EXTTEXTDATA *textData = (EXTTEXTDATA *)(PTR_SEG_TO_LIN(newInData));
+
+              textData->nSize = cbInput;
+              textData->lpindata = lpInData;
+              textData->lpFont = physDev->segptrFontInfo;
+              textData->lpXForm = win16drv_SegPtr_TextXForm;
+              textData->lpDrawMode = win16drv_SegPtr_DrawMode;
+              nRet = PRTDRV_Control(physDev->segptrPDEVICE, nEscape,
+                                    newInData, lpOutData);
+              GlobalFree16(newInData);
+              
+            }
+          break;
+          case STARTDOC:
 	    nRet = PRTDRV_Control(physDev->segptrPDEVICE, nEscape,
-				  newInData, lpOutData);
-	    GlobalFree16(newInData);
-            
-	  }
-        break;
-        
+				  lpInData, lpOutData);
+            if (nRet != -1)
+            {
+              SEGPTR newInData =  WIN16_GlobalLock16(GlobalAlloc16(GHND, sizeof(HDC32)));
+#define SETPRINTERDC SETABORTPROC
+              HDC32 *tmpHdc = (HDC32 *)(PTR_SEG_TO_LIN(newInData));
+              *tmpHdc = dc->hSelf;
+              PRTDRV_Control(physDev->segptrPDEVICE, SETPRINTERDC,
+                             newInData, (SEGPTR)NULL);
+              GlobalFree16(newInData);
+            }
+            break;
 	  default:
 	    nRet = PRTDRV_Control(physDev->segptrPDEVICE, nEscape,
 				  lpInData, lpOutData);
+            break;
 	}
     }
     else
diff --git a/if1632/Makefile.in b/if1632/Makefile.in
index 140ca75..20df647 100644
--- a/if1632/Makefile.in
+++ b/if1632/Makefile.in
@@ -58,6 +58,7 @@
 	builtin.c \
 	dummy.c \
 	relay.c \
+	signal.c \
 	thunk.c
 
 GEN_ASM_SRCS = \
diff --git a/if1632/builtin.c b/if1632/builtin.c
index 1675687..ebe48ad 100644
--- a/if1632/builtin.c
+++ b/if1632/builtin.c
@@ -119,6 +119,7 @@
     { &KERNEL_Descriptor,   DLL_FLAG_ALWAYS_USED },
     { &USER_Descriptor,     DLL_FLAG_ALWAYS_USED },
     { &GDI_Descriptor,      DLL_FLAG_ALWAYS_USED },
+    { &SYSTEM_Descriptor,   DLL_FLAG_ALWAYS_USED },
     { &WIN87EM_Descriptor,  DLL_FLAG_NOT_USED },
     { &SHELL_Descriptor,    0 },
     { &SOUND_Descriptor,    0 },
@@ -126,7 +127,6 @@
     { &WINSOCK_Descriptor,  0 },
     { &STRESS_Descriptor,   0 },
     { &MMSYSTEM_Descriptor, 0 },
-    { &SYSTEM_Descriptor,   0 },
     { &TOOLHELP_Descriptor, 0 },
     { &MOUSE_Descriptor,    0 },
     { &COMMDLG_Descriptor,  DLL_FLAG_NOT_USED },
diff --git a/if1632/comctl32.spec b/if1632/comctl32.spec
index 90b5e5d..be6c101 100644
--- a/if1632/comctl32.spec
+++ b/if1632/comctl32.spec
@@ -2,6 +2,10 @@
 type	win32
 base	2
 
+# Functions exported by the Win95 comctl32.dll 
+# (these need to have these exact ordinals, because some win95 dlls 
+#  import comctl32.dll by ordinal)
+
 00 stub MenuHelp
 01 stub ShowHideMenuCtl
 02 stub GetEffectiveClientRect
@@ -9,53 +13,60 @@
 04 stdcall CreateStatusWindowA(long ptr long long) CreateStatusWindow32A
 05 stub CreateToolbar
 06 stub CreateMappedBitmap
-07 stub CreatePropertySheetPage
-08 stub CreatePropertySheetPageA
-09 stub CreatePropertySheetPageW
-10 stub CreateStatusWindow
+07 stub Cctl1632_ThunkData32
+08 stub CreatePropertySheetPage
+09 stub CreatePropertySheetPageA
+10 stub CreatePropertySheetPageW
 11 stub MakeDragList
 12 stub LBItemFromPt
 13 stub DrawInsert
 14 stub CreateUpDownControl
 15 stdcall InitCommonControls() InitCommonControls
-16 stub CreateStatusWindowW
-17 stub CreateToolbarEx
-18 stub DestroyPropertySheetPage
-19 stub DrawStatusText
-20 stub DrawStatusTextW
-21 stub ImageList_Add
-22 stub ImageList_AddIcon
-23 stub ImageList_AddMasked
-24 stub ImageList_BeginDrag
-25 stub ImageList_Create
-26 stub ImageList_Destroy
-27 stub ImageList_DragEnter
-28 stub ImageList_DragLeave
-29 stub ImageList_DragMove
-30 stub ImageList_DragShowNolock
-31 stub ImageList_Draw
-32 stub ImageList_DrawEx
-33 stub ImageList_EndDrag
-34 stub ImageList_GetBkColor
-35 stub ImageList_GetDragImage
-36 stub ImageList_GetIcon
-37 stub ImageList_GetIconSize
-38 stub ImageList_GetImageCount
-39 stub ImageList_GetImageInfo
-40 stub ImageList_GetImageRect
-41 stub ImageList_LoadImage
-42 stub ImageList_LoadImageA
-43 stub ImageList_LoadImageW
-44 stub ImageList_Merge
-45 stub ImageList_Read
-46 stub ImageList_Remove
-47 stub ImageList_Replace
-48 stub ImageList_ReplaceIcon
-49 stub ImageList_SetBkColor
-50 stub ImageList_SetDragCursorImage
-51 stub ImageList_SetIconSize
-52 stub ImageList_SetOverlayImage
-53 stub ImageList_Write
-54 stub PropertySheet
-55 stub PropertySheetA
-56 stub PropertySheetW
+16 stub CreateStatusWindow
+17 stub CreateStatusWindowW
+18 stub CreateToolbarEx
+19 stub DestroyPropertySheetPage
+20 stub DllGetVersion
+21 stub DrawStatusText
+22 stub DrawStatusTextW
+23 stub ImageList_Add
+24 stub ImageList_AddIcon
+25 stub ImageList_AddMasked
+26 stub ImageList_BeginDrag
+27 stub ImageList_Copy
+28 stub ImageList_Create
+29 stub ImageList_Destroy
+30 stub ImageList_DragEnter
+31 stub ImageList_DragLeave
+32 stub ImageList_DragMove
+33 stub ImageList_DragShowNolock
+34 stub ImageList_Draw
+35 stub ImageList_DrawEx
+36 stub ImageList_EndDrag
+37 stub ImageList_GetBkColor
+38 stub ImageList_GetDragImage
+39 stub ImageList_GetIcon
+40 stub ImageList_GetIconSize
+41 stub ImageList_GetImageCount
+42 stub ImageList_GetImageInfo
+43 stub ImageList_GetImageRect
+44 stub ImageList_LoadImage
+45 stub ImageList_LoadImageA
+46 stub ImageList_LoadImageW
+47 stub ImageList_Merge
+48 stub ImageList_Read
+49 stub ImageList_Remove
+50 stub ImageList_Replace
+51 stub ImageList_ReplaceIcon
+52 stub ImageList_SetBkColor
+53 stub ImageList_SetDragCursorImage
+54 stub ImageList_SetFilter
+55 stub ImageList_SetIconSize
+56 stub ImageList_SetImageCount
+57 stub ImageList_SetOverlayImage
+58 stub ImageList_Write
+59 stub InitCommonControlsEx
+60 stub PropertySheet
+61 stub PropertySheetA
+62 stub PropertySheetW
+63 stub _TrackMouseEvent
diff --git a/if1632/compobj.spec b/if1632/compobj.spec
index e325c24..3f81756 100644
--- a/if1632/compobj.spec
+++ b/if1632/compobj.spec
@@ -19,8 +19,8 @@
 16 stub CORELEASEMARSHALDATA
 17 stub COFREEUNUSEDLIBRARIES
 18 stub ISEQUALGUID
-19 stub STRINGFROMCLSID
-20 stub CLSIDFROMSTRING
+19 pascal STRINGFROMCLSID(ptr ptr) StringFromCLSID
+20 pascal CLSIDFROMSTRING(str ptr) CLSIDFromString
 21 stub ISVALIDPTRIN
 22 stub ISVALIDPTROUT
 23 stub ISVALIDINTERFACE
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index f1ef2bd..e407b44 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -1,6 +1,7 @@
 name	gdi
 type	win16
 heap	65488  # 65536 - 16 (instance data) - 32 (stock objects)
+file	gdi.exe
 
 1   pascal   SetBkColor(word long) SetBkColor16
 2   pascal16 SetBkMode(word word) SetBkMode16
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index 7153880..39a6b41 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -1,5 +1,6 @@
 name	kernel
 type	win16
+file	krnl386.exe
 
 1   stub FatalExit
 2   stub ExitKernel
@@ -317,9 +318,9 @@
 502 stub KERNEL_502
 503 stub KERNEL_503
 511 stub KERNEL_511
-513 pascal LoadLibraryEx32W(ptr long long) LoadLibraryEx32W16
-514 stub FreeLibrary32W
-515 pascal GetProcAddress32W(long ptr) GetProcAddress32
+513 pascal   LoadLibraryEx32W(ptr long long) LoadLibraryEx32W16
+514 pascal16 FreeLibrary32W(long) FreeLibrary32
+515 pascal   GetProcAddress32W(long ptr) GetProcAddress32
 516 stub GetVDMPointer32W
 517 pascal CallProc32W() WIN16_CallProc32W
 518 stub CallProcEx32W
diff --git a/if1632/kernel32.spec b/if1632/kernel32.spec
index f824dc1..b858d62 100644
--- a/if1632/kernel32.spec
+++ b/if1632/kernel32.spec
@@ -26,14 +26,18 @@
  
 30  stub _KERNEL32_31
  
-34  stub LoadLibrary16
+33  stdcall _KERNEL32_34() _KERNEL32_34
+34  stdcall LoadLibrary16(ptr) LoadLibrary16
 35  stub FreeLibrary16
-36  stub GetProcAddress16
+36  stdcall GetProcAddress16(long ptr) WIN32_GetProcAddress16
  
 39  stub _KERNEL32_40
-
-42  return _KERNEL32_43 20 0
-44  stub _KERNEL32_45
+40  stdcall _KERNEL32_41(long long long long long) _KERNEL32_41
+41  stub _KERNEL32_42
+42  stdcall _KERNEL32_43(long ptr long ptr ptr) _KERNEL32_43
+44  register _KERNEL32_45(long) _KERNEL32_45 
+45  stdcall _KERNEL32_46(long long long long long) _KERNEL32_46
+46  stub _KERNEL32_47
  
 49  stdcall AddAtomA(ptr) AddAtom32A
 
@@ -42,7 +46,7 @@
 # WOW calls
 53  stub WOWCallback16
 54  stub WOWCallback16Ex
-55  stub WOWGetVDMPointer
+55  stdcall WOWGetVDMPointer(long long long) WOWGetVDMPointer
 56  stub WOWHandle32
 57  stub WOWHandle16
 58  stub WOWGlobalAlloc16
@@ -54,9 +58,9 @@
 64  stub WOWGlobalLockSize16
 65  stub WOWYield16
 66  stub WOWDirectedYield16
-67  stub WOWGetVDMPointerFix
-68  stub WOWGetVDMPointerUnfix
-69  stub WOW32_1
+67  stdcall WOWGetVDMPointerFix(long long long) WOWGetVDMPointerFix
+68  stdcall WOWGetVDMPointerUnfix(long) WOWGetVDMPointerUnfix
+69  stdcall WOW32_1(long long) WOW32_1
  
 71  stub RtlLargeIntegerAdd
 72  stub RtlEnlargedIntegerMultiply
@@ -73,11 +77,12 @@
 83  stub RtlConvertLongToLargeInteger
 84  stub RtlConvertUlongToLargeInteger
 
-86  stub _KERNEL32_87
-87  stub _KERNEL32_88
-
-90  stub _KERNEL32_90
-91  stub _KERNEL32_91
+86  stdcall _KERNEL32_87() _KERNEL32_87
+87  cdecl _KERNEL32_88(long long ptr) _KERNEL32_88
+88  stub _KERNEL32_89
+89  stub _KERNEL32_90
+90  register _KERNEL32_91() _KERNEL32_91
+91  stub _KERNEL32_92
 92  stdcall GETPWIN16LOCK(ptr) GetPWinLock
 96  stub ENTERSYSLEVEL
 97  stub LEAVESYSLEVEL
diff --git a/if1632/signal.c b/if1632/signal.c
new file mode 100644
index 0000000..58f0c0b
--- /dev/null
+++ b/if1632/signal.c
@@ -0,0 +1,124 @@
+/*
+ * Emulator signal handling
+ *
+ * Copyright 1995 Alexandre Julliard
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <setjmp.h>
+
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__svr4__) || defined(_SCO_DS) || defined(__EMX__)
+# if !defined(_SCO_DS) && !defined(__EMX__)
+#  include <sys/syscall.h>
+# endif
+# include <sys/param.h>
+#else
+# include <syscall.h>
+#endif
+
+#include "debugger.h"
+#include "options.h"
+#include "sigcontext.h"
+#include "miscemu.h"
+
+
+/* Signal handler declaration */
+
+#ifdef linux
+#define HANDLER_DEF(name) void name (int signal, SIGCONTEXT context_struct)
+#define HANDLER_PROLOG SIGCONTEXT *context = &context_struct; {
+#define HANDLER_EPILOG }
+#elif defined(__svr4__) || defined(_SCO_DS)
+#define HANDLER_DEF(name) void name (int signal, void *siginfo, SIGCONTEXT *context)
+#define HANDLER_PROLOG  /* nothing */
+#define HANDLER_EPILOG  /* nothing */
+#else
+#define HANDLER_DEF(name) void name (int signal, int code, SIGCONTEXT *context)
+#define HANDLER_PROLOG  /* nothing */
+#define HANDLER_EPILOG  /* nothing */
+#endif
+
+extern void SIGNAL_SetHandler( int sig, void (*func)(), int flags );
+extern BOOL32 INSTR_EmulateInstruction( SIGCONTEXT *context );
+
+
+/**********************************************************************
+ *              SIGNAL_break
+ * 
+ * Handle Ctrl-C and such
+ */
+static HANDLER_DEF(SIGNAL_break)
+{
+    HANDLER_PROLOG;
+    if (Options.debug) wine_debug( signal, context );  /* Enter our debugger */
+    else exit(0);
+    HANDLER_EPILOG;
+}
+
+
+/**********************************************************************
+ *		SIGNAL_trap
+ *
+ * SIGTRAP handler.
+ */
+static HANDLER_DEF(SIGNAL_trap)
+{
+  HANDLER_PROLOG;
+  wine_debug( signal, context );  /* Enter our debugger */
+  HANDLER_EPILOG;
+}
+
+
+/**********************************************************************
+ *		SIGNAL_fault
+ *
+ * Segfault handler.
+ */
+static HANDLER_DEF(SIGNAL_fault)
+{
+    HANDLER_PROLOG;
+    if (CS_sig(context) == WINE_CODE_SELECTOR)
+    {
+        fprintf( stderr, "Segmentation fault in Wine program (%04x:%08lx)."
+                         "  Please debug.\n",
+                 (unsigned short) CS_sig(context), EIP_sig(context));
+    }
+    else
+    {
+        if (INSTR_EmulateInstruction( context )) return;
+        fprintf( stderr, "Segmentation fault in Windows program %04x:%08lx.\n",
+                 (unsigned short) CS_sig(context), EIP_sig(context) );
+    }
+    wine_debug( signal, context );
+    HANDLER_EPILOG;
+}
+
+
+/**********************************************************************
+ *		SIGNAL_InitEmulator
+ *
+ * Initialize emulator signals.
+ */
+BOOL32 SIGNAL_InitEmulator(void)
+{
+    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( 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
+    return TRUE;
+}
diff --git a/if1632/system.spec b/if1632/system.spec
index 1352396..311643b 100644
--- a/if1632/system.spec
+++ b/if1632/system.spec
@@ -1,11 +1,11 @@
 name	system
 type	win16
 
-1 pascal   InquireSystem(word word word) InquireSystem
-2 stub CreateSystemTimer
-3 stub KillSystemTimer
-4 stub EnableSystemTimers
-5 stub DisableSystemTimers
+1 pascal   InquireSystem(word word) InquireSystem
+2 pascal16 CreateSystemTimer(word segptr) THUNK_CreateSystemTimer
+3 pascal16 KillSystemTimer(word) THUNK_KillSystemTimer
+4 pascal16 EnableSystemTimers() EnableSystemTimers
+5 pascal16 DisableSystemTimers() DisableSystemTimers
 6 pascal   GetSystemMSecCount() GetTickCount
 7 return Get80x87SaveSize 0 94
 8 stub Save80x87State
diff --git a/if1632/thunk.c b/if1632/thunk.c
index 5714096..39cf091 100644
--- a/if1632/thunk.c
+++ b/if1632/thunk.c
@@ -595,7 +595,33 @@
 }
 
 
-/*************************************************************
+/***********************************************************************
+ *           THUNK_CreateSystemTimer   (SYSTEM.2)
+ */
+WORD THUNK_CreateSystemTimer( WORD rate, FARPROC16 callback )
+{
+    THUNK *thunk = THUNK_Alloc( callback, (RELAY)CallTo16_word_ );
+    if (!thunk) return 0;
+    return CreateSystemTimer( rate, (FARPROC16)thunk );
+}
+
+
+/***********************************************************************
+ *           THUNK_KillSystemTimer   (SYSTEM.3)
+ */
+WORD THUNK_KillSystemTimer( WORD timer )
+{
+    extern WORD SYSTEM_KillSystemTimer( WORD timer );  /* misc/system.c */
+    extern FARPROC16 SYSTEM_GetTimerProc( WORD timer );  /* misc/system.c */
+
+    THUNK *thunk = (THUNK *)SYSTEM_GetTimerProc( timer );
+    WORD ret = SYSTEM_KillSystemTimer( timer );
+    if (thunk) THUNK_Free( thunk );
+    return ret;
+}
+
+
+/***********************************************************************
  *            THUNK_SetUnhandledExceptionFilter   (KERNEL32.516)
  */
 LPTOP_LEVEL_EXCEPTION_FILTER THUNK_SetUnhandledExceptionFilter(
diff --git a/if1632/user.spec b/if1632/user.spec
index aef0e5b..5f2dce1 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -1,6 +1,7 @@
 name	user
 type	win16
 heap	65520
+file	user.exe
 
 1   pascal16 MessageBox(word str str word) MessageBox16
 2   stub OldExitWindows
@@ -247,7 +248,7 @@
              CreateDialogIndirectParam16
 243 pascal   GetDialogBaseUnits() GetDialogBaseUnits
 244 pascal16 EqualRect(ptr ptr) EqualRect16
-245 stub EnableCommNotification
+245 pascal16 EnableCommNotification(s_word word s_word s_word) EnableCommNotification
 246 pascal16 ExitWindowsExec(str str) ExitWindowsExec16
 247 pascal16 GetCursor() GetCursor16
 248 pascal16 GetOpenClipboardWindow() GetOpenClipboardWindow16
diff --git a/if1632/user32.spec b/if1632/user32.spec
index 99bcd8e..2144d97 100644
--- a/if1632/user32.spec
+++ b/if1632/user32.spec
@@ -156,7 +156,7 @@
 0149 stdcall DlgDirSelectExW(long ptr long long) DlgDirSelectEx32W
 0150 stdcall DragDetect(long long long) DragDetect32
 0151 stub DragObject
-0152 stub DrawAnimatedRects
+0152 stdcall DrawAnimatedRects(long long ptr ptr) DrawAnimatedRects32
 0153 stub DrawCaption
 0154 stdcall DrawEdge(long ptr long long) DrawEdge32
 0155 stdcall DrawFocusRect(long ptr) DrawFocusRect32
@@ -267,8 +267,8 @@
 0260 stub GetMenuIndex
 0261 stdcall GetMenuItemCount(long) GetMenuItemCount32
 0262 stdcall GetMenuItemID(long long) GetMenuItemID32
-0263 stub GetMenuItemInfoA
-0264 stub GetMenuItemInfoW
+0263 stdcall GetMenuItemInfoA(long long long ptr) GetMenuItemInfo32A
+0264 stdcall GetMenuItemInfoW(long long long ptr) GetMenuItemInfo32W
 0265 stub GetMenuItemRect
 0266 stdcall GetMenuState(long long long) GetMenuState32
 0267 stdcall GetMenuStringA(long long ptr long long) GetMenuString32A
diff --git a/include/callback.h b/include/callback.h
index d1cb792..c2d1020 100644
--- a/include/callback.h
+++ b/include/callback.h
@@ -48,6 +48,8 @@
 
 #define CallDriverProc( func, dwId, msg, hdrvr, lparam1, lparam2 ) \
     CallTo16_long_lwwll( func, dwId, msg, hdrvr, lparam1, lparam2 )
+#define CallDriverCallback( func, hdev, msg, user, lparam1, lparam2 ) \
+    CallTo16_word_wwlll( func, hdev, msg, user, lparam1, lparam2 )
 #define CallTimeFuncProc( func, id, msg, dwUser, dw1, dw2 ) \
     CallTo16_word_wwlll( func, id, msg, dwUser, dw1, dw2 )
 #define CallWindowsExitProc( func, nExitType ) \
@@ -78,6 +80,8 @@
 
 #define CallDriverProc( func, dwId, msg, hdrvr, lparam1, lparam2 ) \
     (*func)( dwId, msg, hdrvr, lparam1, lparam2 )
+#define CallDriverCallback( func, hdev, msg, user, lparam1, lparam2 ) \
+    (*func)( hdev, msg, user, lparam1, lparam2 )
 #define CallTimeFuncProc( func, id, msg, dwUser, dw1, dw2 ) \
     (*func)( id, msg, dwUser, dw1, dw2 )
 #define CallWindowsExitProc( func, nExitType ) \
diff --git a/include/compobj.h b/include/compobj.h
new file mode 100644
index 0000000..baa348f
--- /dev/null
+++ b/include/compobj.h
@@ -0,0 +1,16 @@
+#if !defined(COMPOBJ_H)
+#define COMPOBJ_H
+
+struct tagCLSID {
+  DWORD	Data1;
+  WORD	Data2;
+  WORD  Data3;
+  BYTE	Data4[8];
+};
+
+typedef struct tagCLSID CLSID;
+
+OLESTATUS StringFromCLSID(const CLSID *id, LPSTR);
+OLESTATUS CLSIDFromString(const LPCSTR, CLSID *);
+
+#endif
diff --git a/include/miscemu.h b/include/miscemu.h
index dba7cff..4b5847b 100644
--- a/include/miscemu.h
+++ b/include/miscemu.h
@@ -10,7 +10,7 @@
 #include <stdio.h>
 #include "winnt.h"
 
-  /* miscemu/dosmem.c */
+  /* msdos/dosmem.c */
 extern HANDLE16 DOSMEM_BiosSeg;
 extern DWORD DOSMEM_CollateTable;
 
@@ -24,9 +24,6 @@
 extern LPVOID DOSMEM_MapDosToLinear(UINT32); /* linear DOS to Wine */
 extern UINT32 DOSMEM_MapLinearToDos(LPVOID); /* linear Wine to DOS */
 
-/* miscemu/interrupts.c */
-extern BOOL32 INT_Init(void);
-
 /* msdos/interrupts.c */
 extern FARPROC16 INT_GetHandler( BYTE intnum );
 extern void INT_SetHandler( BYTE intnum, FARPROC16 handler );
@@ -39,6 +36,14 @@
 /* msdos/int1a.c */
 extern DWORD INT1A_GetTicksSinceMidnight(void);
 
+/* loader/signal.c */
+extern BOOL32 SIGNAL_Init(void);
+extern void SIGNAL_SetHandler( int sig, void (*func)(), int flags );
+extern void SIGNAL_MaskAsyncEvents( BOOL32 flag );
+
+/* if1632/signal.c */
+extern BOOL32 SIGNAL_InitEmulator(void);
+
 #define INT_BARF(context,num) \
     fprintf( stderr, "int%x: unknown/not implemented parameters:\n" \
                      "int%x: AX %04x, BX %04x, CX %04x, DX %04x, " \
diff --git a/include/module.h b/include/module.h
index 872b498..563a2d8 100644
--- a/include/module.h
+++ b/include/module.h
@@ -126,6 +126,7 @@
 extern BOOL16 MODULE_SetEntryPoint( HMODULE16 hModule, WORD ordinal,
                                     WORD offset );
 extern FARPROC16 MODULE_GetWndProcEntry16( const char *name );
+extern FARPROC16 WIN32_GetProcAddress16( HMODULE16 hmodule, LPSTR name );
 
 /* builtin.c */
 extern BOOL16 BUILTIN_Init(void);
diff --git a/include/tweak.h b/include/tweak.h
index d2dcbf6..02ac88a 100644
--- a/include/tweak.h
+++ b/include/tweak.h
@@ -15,7 +15,9 @@
 int  TWEAK_CheckConfiguration();
 INT32  TWEAK_PartyMessageBox(LPCSTR, LPCSTR, DWORD);
 void  TWEAK_DrawReliefRect95(HDC32, RECT32 const *);
-void  TWEAK_DrawMenuSeparator95(HDC32, UINT32, UINT32, UINT32);
+void  TWEAK_DrawRevReliefRect95(HDC32, RECT32 const *);
+void  TWEAK_DrawMenuSeparatorHoriz95(HDC32, UINT32, UINT32, UINT32);
+void  TWEAK_DrawMenuSeparatorVert95(HDC32, UINT32, UINT32, UINT32);
 extern int  TWEAK_Win95Look;
 extern int  TWEAK_WineInitialized;
 extern HPEN32  TWEAK_PenFF95;
diff --git a/include/win16drv.h b/include/win16drv.h
index f7d144c..88acb12 100644
--- a/include/win16drv.h
+++ b/include/win16drv.h
@@ -188,6 +188,8 @@
                                   const RECT32 *lprect, LPCSTR str, UINT32 count,
                                   const INT32 *lpDx );
 extern HGDIOBJ32 WIN16DRV_SelectObject( DC *dc, HGDIOBJ32 handle );
+extern BOOL32 WIN16DRV_PatBlt( struct tagDC *dc, INT32 left, INT32 top,
+                               INT32 width, INT32 height, DWORD rop );
 
 
 
diff --git a/include/windows.h b/include/windows.h
index 28dd31d..06814ac 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -2844,6 +2844,67 @@
 #define MF_HELP            0x4000
 #define MF_MOUSESELECT     0x8000
 
+/* Flags for extended menu item types.  */
+#define MFT_STRING         MF_STRING
+#define MFT_BITMAP         MF_BITMAP
+#define MFT_MENUBARBREAK   MF_MENUBARBREAK
+#define MFT_MENUBREAK      MF_MENUBREAK
+#define MFT_OWNERDRAW      MF_OWNERDRAW
+#define MFT_RADIOCHECK     0x00000200L
+#define MFT_SEPARATOR      MF_SEPARATOR
+#define MFT_RIGHTORDER     0x00002000L
+#define MFT_RIGHTJUSTIFY   MF_RIGHTJUSTIFY
+
+/* Flags for extended menu item states.  */
+#define MFS_GRAYED          0x00000003L
+#define MFS_DISABLED        MFS_GRAYED
+#define MFS_CHECKED         MF_CHECKED
+#define MFS_HILITE          MF_HILITE
+#define MFS_ENABLED         MF_ENABLED
+#define MFS_UNCHECKED       MF_UNCHECKED
+#define MFS_UNHILITE        MF_UNHILITE
+#define MFS_DEFAULT         MF_DEFAULT
+
+typedef struct {
+  UINT32    cbSize;
+  UINT32    fMask;
+  UINT32    fType;
+  UINT32    fState;
+  UINT32    wID;
+  HMENU32   hSubMenu;
+  HBITMAP32 hbmpChecked;
+  HBITMAP32 hbmpUnchecked;
+  DWORD     dwItemData;
+  LPSTR     dwTypeData;
+  UINT32    cch;
+} MENUITEMINFO32A, *LPMENUITEMINFO32A;
+
+typedef struct {
+  UINT32    cbSize;
+  UINT32    fMask;
+  UINT32    fType;
+  UINT32    fState;
+  UINT32    wID;
+  HMENU32   hSubMenu;
+  HBITMAP32 hbmpChecked;
+  HBITMAP32 hbmpUnchecked;
+  DWORD     dwItemData;
+  LPWSTR    dwTypeData;
+  UINT32    cch;
+} MENUITEMINFO32W, *LPMENUITEMINFO32W;
+
+DECL_WINELIB_TYPE_AW(MENUITEMINFO);
+DECL_WINELIB_TYPE_AW(LPMENUITEMINFO);
+
+/* Field specifiers for MENUITEMINFO[AW] type.  */
+#define MIIM_STATE       0x00000001
+#define MIIM_ID          0x00000002
+#define MIIM_SUBMENU     0x00000004
+#define MIIM_CHECKMARKS  0x00000008
+#define MIIM_TYPE        0x00000010
+#define MIIM_DATA        0x00000020
+
+
 #ifndef NOWINOFFSETS
 #define GCW_HBRBACKGROUND (-10)
 #endif
@@ -5070,13 +5131,17 @@
 WORD       ChangeSelector(WORD,WORD);
 INT16      CloseComm(INT16);
 HGLOBAL16  CreateCursorIconIndirect(HINSTANCE16,CURSORICONINFO*,LPCVOID,LPCVOID);
+WORD       CreateSystemTimer(WORD,FARPROC16);
 BOOL16     DCHook(HDC16,WORD,DWORD,LPARAM);
 VOID       DirectedYield(HTASK16);
 HGLOBAL16  DirectResAlloc(HINSTANCE16,WORD,UINT16);
+VOID       DisableSystemTimers(void);
 BOOL16     DlgDirSelect(HWND16,LPSTR,INT16);
 BOOL16     DlgDirSelectComboBox(HWND16,LPSTR,INT16);
 DWORD      DumpIcon(SEGPTR,WORD*,SEGPTR*,SEGPTR*);
+BOOL16     EnableCommNotification(INT16,HWND16,INT16,INT16);
 BOOL16     EnableHardwareInput(BOOL16);
+VOID       EnableSystemTimers(void);
 INT16      ExcludeVisRect(HDC16,INT16,INT16,INT16,INT16);
 HANDLE16   FarGetOwner(HGLOBAL16);
 VOID       FarSetOwner(HGLOBAL16,HANDLE16);
@@ -5283,6 +5348,9 @@
 #define    GetFullPathName WINELIB_NAME_AW(GetFullPathName)
 VOID       GetLocalTime(LPSYSTEMTIME);
 DWORD      GetLogicalDrives(void);
+BOOL32     GetMenuItemInfo32A(HMENU32,UINT32,BOOL32,MENUITEMINFO32A*);
+BOOL32     GetMenuItemInfo32W(HMENU32,UINT32,BOOL32,MENUITEMINFO32W*);
+#define    GetMenuItemInfo WINELIB_NAME_AW(GetMenuItemInfo)
 UINT32     GetOEMCP(void);
 DWORD      GetPriorityClass(HANDLE32);
 HANDLE32   GetProcessHeap(void);
diff --git a/library/miscstubs.c b/library/miscstubs.c
index 809e3da..045f25a 100644
--- a/library/miscstubs.c
+++ b/library/miscstubs.c
@@ -12,10 +12,6 @@
 #include "global.h"
 #include "debug.h"
 
-void SIGNAL_MaskAsyncEvents( BOOL32 mask )
-{
-    /* FIXME: signals don't work in the library */
-}
 
 /* for windows/winproc.c */
 void CallFrom16_long_wwwll(void) {}
diff --git a/libtest/Makefile.in b/libtest/Makefile.in
index 32d3936..e9f772a 100644
--- a/libtest/Makefile.in
+++ b/libtest/Makefile.in
@@ -3,10 +3,11 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = none
-PROGRAMS  = hello hello2 hello3 hello4 new rolex
+PROGRAMS  = expand hello hello2 hello3 hello4 new rolex
 ALL_LIBS  = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LDLIBS)
 
 C_SRCS = \
+	expand.c \
 	hello.c \
 	hello2.c \
 	hello3.c \
@@ -21,6 +22,9 @@
 
 @MAKE_RULES@
 
+expand: expand.o
+	$(CC) -o expand expand.o $(LDOPTIONS) $(ALL_LIBS)
+
 hello: hello.o
 	$(CC) -o hello hello.o $(LDOPTIONS) $(ALL_LIBS)
 
diff --git a/libtest/expand.c b/libtest/expand.c
new file mode 100644
index 0000000..656a3d6
--- /dev/null
+++ b/libtest/expand.c
@@ -0,0 +1,76 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <windows.h>
+#include <lzexpand.h>
+
+int PASCAL WinMain(HINSTANCE hinstCurrent,
+				HINSTANCE hinstPrevious,
+				LPSTR lpCmdLine,
+				int nCmdShow)
+{
+  OFSTRUCT SourceOpenStruct1, SourceOpenStruct2;
+  char OriginalName[256], WriteBuf[256];
+  char FAR *lpzDestFile,
+  			FAR *lpzHolder = lpCmdLine,
+  			FAR *arrgv[2] = {0};
+  int wargs;
+  DWORD dwreturn;
+  HFILE hSourceFile, hDestFile;
+
+  for (wargs = 1; wargs < 3; wargs++)
+  {arrgv[wargs] = lpzHolder;
+  for (; *lpzHolder != '\0'; lpzHolder++)
+	if (*lpzHolder == ' ') {*lpzHolder++ = '\0'; break;};
+	};
+
+MessageBox((HWND)NULL, (LPCSTR)arrgv[1], (LPCSTR)"arrgv[1]:", MB_OK);
+MessageBox((HWND)NULL, (LPCSTR)arrgv[2], (LPCSTR)"arrgv[2]:", MB_OK);
+
+  hSourceFile = LZOpenFile(arrgv[1], (LPOFSTRUCT) &SourceOpenStruct1,
+			OF_READ);
+
+wsprintf(WriteBuf, "Source File Handle: %d\nNo. of args: %d",
+	   hSourceFile, wargs);
+MessageBox((HWND)NULL, (LPCSTR)WriteBuf, (LPCSTR)NULL, MB_OK);
+
+  if ((wargs == 3) && (arrgv[2] != NULL)) lpzDestFile = arrgv[2];
+  else
+  {
+  lpzDestFile = OriginalName;
+  GetExpandedName(arrgv[1], lpzDestFile);
+  };
+
+ MessageBox((HWND)NULL, (LPCSTR)lpzDestFile, (LPCSTR)"Destination File",
+		MB_OK);
+
+  hDestFile = LZOpenFile(lpzDestFile, (LPOFSTRUCT) &SourceOpenStruct2,
+			OF_CREATE | OF_WRITE);
+wsprintf(WriteBuf, "Destination File Handle: %d\nNo. of args: %d",
+	   hDestFile, wargs-1);
+MessageBox((HWND)NULL, (LPCSTR)WriteBuf, (LPCSTR)NULL, MB_OK);
+
+  dwreturn = LZCopy(hSourceFile, hDestFile);
+
+  if (dwreturn == LZERROR_BADINHANDLE)
+  	 MessageBox((HWND)NULL, (LPCSTR)"LZERROR_BADINHANDLE\n", (LPCSTR)NULL, MB_OK);
+  if (dwreturn == LZERROR_BADOUTHANDLE)
+  	 MessageBox((HWND)NULL, (LPCSTR)"LZERROR_BADOUTHANDLE\n", (LPCSTR)NULL, MB_OK);
+  if (dwreturn ==  LZERROR_BADVALUE)
+  	MessageBox((HWND)NULL,  (LPCSTR)"LZERROR_BADVALUE\n", (LPCSTR)NULL, MB_OK);
+  if (dwreturn ==  LZERROR_GLOBALLOC)
+  	MessageBox((HWND)NULL,  (LPCSTR)"LZERROR_GLOBALLOC\n", (LPCSTR)NULL, MB_OK);
+  if (dwreturn ==  LZERROR_GLOBLOCK)
+  	MessageBox((HWND)NULL,  (LPCSTR)"LZERROR_GLOBLOCK\n", (LPCSTR)NULL, MB_OK);
+  if (dwreturn ==  LZERROR_READ)
+  	MessageBox((HWND)NULL,  (LPCSTR)"LZERROR_READ\n", (LPCSTR)NULL, MB_OK);
+  if (dwreturn ==  LZERROR_WRITE)
+  	MessageBox((HWND)NULL,  (LPCSTR)"LZERROR_WRITE\n", (LPCSTR)NULL, MB_OK);
+  if ((long)dwreturn > 0L)
+   {wsprintf((LPSTR)WriteBuf, (LPCSTR)"Successful decompression from %s to %s\n",
+    			   arrgv[1], lpzDestFile);
+	MessageBox((HWND)NULL, (LPSTR)WriteBuf, (LPCSTR)NULL, MB_OK);
+	};
+  LZClose(hSourceFile); LZClose(hDestFile);
+  return dwreturn;
+}
diff --git a/loader/main.c b/loader/main.c
index 4fb3aa3..4ac8026 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -44,12 +44,7 @@
 #include "debugger.h"
 #endif
 
-/* Winelib run-time flag */
-#ifdef WINELIB
-int __winelib = 1;
-#else
-int __winelib = 0;
-#endif
+int __winelib = 1;  /* Winelib run-time flag */
 
 HANDLE32 SystemHeap = 0;
 HANDLE32 SegptrHeap = 0;
@@ -61,7 +56,6 @@
 {
     extern BOOL32 RELAY_Init(void);
     extern BOOL32 WIN16DRV_Init(void);
-    extern BOOL32 SIGNAL_Init(void);
     extern BOOL32 VIRTUAL_Init(void);
     extern BOOL32 WIDGETS_Init(void);
 
@@ -80,6 +74,9 @@
       /* Initialize DOS memory */
     if (!DOSMEM_Init()) return 0;
 
+      /* Initialize signal handling */
+    if (!SIGNAL_Init()) return 0;
+
 #ifdef WINELIB
     /* Create USER and GDI heap */
     USER_HeapSel = GlobalAlloc16( GMEM_FIXED, 0x10000 );
@@ -94,7 +91,7 @@
     if (!BUILTIN_Init()) return 0;
 
       /* Initialize signal handling */
-    if (!SIGNAL_Init()) return 0;
+    if (!SIGNAL_InitEmulator()) return 0;
 
     /* Create the Win16 printer driver */
     if (!WIN16DRV_Init()) return 0;
@@ -184,6 +181,8 @@
     int i,loaded;
     HINSTANCE16 handle;
 
+    __winelib = 0;  /* First of all, clear the Winelib flag */
+
     /*
      * Save this so that the internal debugger can get a hold of it if
      * it needs to.
diff --git a/loader/module.c b/loader/module.c
index a3522c6..bd12830 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -1162,8 +1162,9 @@
 					0xFF00, hModule, FALSE, FALSE, FALSE)
 					);
 		oldstack = IF1632_Saved16_ss_sp;
-		IF1632_Saved16_ss_sp = MAKELONG( 0xFF00 - sizeof(*stack16Top),
-                                                 pModule->self_loading_sel );
+		IF1632_Saved16_ss_sp =
+                    PTR_SEG_OFF_TO_SEGPTR( pModule->self_loading_sel,
+                                           0xff00 - sizeof(*stack16Top) );
                 stack16Top = CURRENT_STACK16;
                 stack16Top->saved_ss_sp = 0;
                 stack16Top->ebp = 0;
@@ -1458,10 +1459,11 @@
 {
     LOADPARAMS params;
     HGLOBAL16 cmdShowHandle, cmdLineHandle;
-    HINSTANCE16 handle;
+    HINSTANCE16 handle = 2;
     WORD *cmdShowPtr;
     char *p, *cmdline, filename[256];
     static int use_load_module = 1;
+    int  spacelimit = 0, exhausted = 0;
 
     if (!lpCmdLine)
         return 2;  /* File not found */
@@ -1473,115 +1475,148 @@
         return 8;  /* Out of memory */
     }
 
-      /* Store nCmdShow */
+    /* Keep trying to load a file by trying different filenames; e.g.,
+       for the cmdline "abcd efg hij", try "abcd" with args "efg hij",
+       then "abcd efg" with arg "hij", and finally "abcd efg hij" with
+       no args */
 
-    cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle );
-    cmdShowPtr[0] = 2;
-    cmdShowPtr[1] = nCmdShow;
+    while(!exhausted && handle == 2) {
+	int spacecount = 0;
 
-      /* Build the filename and command-line */
+	/* Store nCmdShow */
 
-    cmdline = (char *)GlobalLock16( cmdLineHandle );
-    lstrcpyn32A(filename, lpCmdLine, sizeof(filename) - 4 /* for extension */);
-    for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
-    if (*p) lstrcpyn32A( cmdline + 1, p + 1, 127 );
-    else cmdline[1] = '\0';
-    cmdline[0] = strlen( cmdline + 1 ) + 1;
-    *p = '\0';
+	cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle );
+	cmdShowPtr[0] = 2;
+	cmdShowPtr[1] = nCmdShow;
 
-      /* Now load the executable file */
+	/* Build the filename and command-line */
 
-    if (use_load_module)
-    {
+	cmdline = (char *)GlobalLock16( cmdLineHandle );
+	lstrcpyn32A(filename, lpCmdLine,
+		    sizeof(filename) - 4 /* for extension */);
+
+	/* Keep grabbing characters until end-of-string, tab, or until the
+	   number of spaces is greater than the spacelimit */
+
+	for (p = filename; ; p++) {
+	    if(*p == ' ') {
+		++spacecount;
+		if(spacecount > spacelimit) {
+		    ++spacelimit;
+		    break;
+		}
+	    }
+
+	    if(*p == '\0' || *p == '\t') {
+		exhausted = 1;
+		break;
+	    }
+	}
+
+	if (*p)
+	    lstrcpyn32A( cmdline + 1, p + 1, 127 );
+	else
+	    cmdline[1] = '\0';
+
+	cmdline[0] = strlen( cmdline + 1 ) + 1;
+	*p = '\0';
+
+	/* Now load the executable file */
+
+	if (use_load_module)
+	{
 #ifdef WINELIB
-        /* WINELIB: Use LoadModule() only for the program itself */
-        use_load_module = 0;
-	params.hEnvironment = (HGLOBAL16)GetDOSEnvironment();
+	    /* WINELIB: Use LoadModule() only for the program itself */
+	    use_load_module = 0;
+	    params.hEnvironment = (HGLOBAL16)GetDOSEnvironment();
 #else
-	params.hEnvironment = (HGLOBAL16)SELECTOROF( GetDOSEnvironment() );
+	    params.hEnvironment = (HGLOBAL16)SELECTOROF( GetDOSEnvironment() );
 #endif  /* WINELIB */
-	params.cmdLine  = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle );
-	params.showCmd  = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle );
-	params.reserved = 0;
-	handle = LoadModule16( filename, &params );
-	if (handle == 2)  /* file not found */
-	{
-	    /* Check that the original file name did not have a suffix */
-	    p = strrchr(filename, '.');
-	    /* if there is a '.', check if either \ OR / follow */
-	    if (!p || strchr(p, '/') || strchr(p, '\\'))
-            {
-                p = filename + strlen(filename);
-                strcpy( p, ".exe" );
-                handle = LoadModule16( filename, &params );
-                *p = '\0';  /* Remove extension */
-            }
+	    params.cmdLine  = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle );
+	    params.showCmd  = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle );
+	    params.reserved = 0;
+	    handle = LoadModule16( filename, &params );
+	    if (handle == 2)  /* file not found */
+	    {
+		/* Check that the original file name did not have a suffix */
+		p = strrchr(filename, '.');
+		/* if there is a '.', check if either \ OR / follow */
+		if (!p || strchr(p, '/') || strchr(p, '\\'))
+		{
+		    p = filename + strlen(filename);
+		    strcpy( p, ".exe" );
+		    handle = LoadModule16( filename, &params );
+		    *p = '\0';  /* Remove extension */
+		}
+	    }
 	}
-    }
-    else handle = 2;
+	else
+	    handle = 2; /* file not found */
 
-    if (handle < 32)
-    {
-        /* Try to start it as a unix program */
-        if (!fork())
+	if (handle < 32)
 	{
-            /* Child process */
-            DOS_FULL_NAME full_name;
-            const char *unixfilename = NULL;
-            const char *argv[256], **argptr;
-            int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
-                          nCmdShow == SW_SHOWMINNOACTIVE);
+	    /* Try to start it as a unix program */
+	    if (!fork())
+	    {
+		/* Child process */
+		DOS_FULL_NAME full_name;
+		const char *unixfilename = NULL;
+		const char *argv[256], **argptr;
+		int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
+			      nCmdShow == SW_SHOWMINNOACTIVE);
 
-            /* get unixfilename */
-            if (strchr(filename, '/') ||
-                strchr(filename, ':') ||
-                strchr(filename, '\\'))
-            {
-                if (DOSFS_GetFullName( filename, TRUE, &full_name ))
-                    unixfilename = full_name.long_name;
-            }
-            else unixfilename = filename;
+		/* get unixfilename */
+		if (strchr(filename, '/') ||
+		    strchr(filename, ':') ||
+		    strchr(filename, '\\'))
+		{
+		    if (DOSFS_GetFullName( filename, TRUE, &full_name ))
+			unixfilename = full_name.long_name;
+		}
+		else unixfilename = filename;
 
-            if (unixfilename)
-            {
-                /* build argv */
-                argptr = argv;
-                if (iconic) *argptr++ = "-iconic";
-                *argptr++ = unixfilename;
-                p = cmdline;
-                while (1)
-                {
-                    while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
-                    if (!*p) break;
-                    *argptr++ = p;
-                    while (*p && *p != ' ' && *p != '\t') p++;
-                }
-                *argptr++ = 0;
+		if (unixfilename)
+		{
+		    /* build argv */
+		    argptr = argv;
+		    if (iconic) *argptr++ = "-iconic";
+		    *argptr++ = unixfilename;
+		    p = cmdline;
+		    while (1)
+		    {
+			while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
+			if (!*p) break;
+			*argptr++ = p;
+			while (*p && *p != ' ' && *p != '\t') p++;
+		    }
+		    *argptr++ = 0;
 
-                /* Execute */
-                execvp(argv[0], (char**)argv);
-            }
+		    /* Execute */
+		    execvp(argv[0], (char**)argv);
+		}
 
-	    /* Failed ! */
+		/* Failed ! */
 
-            if (__winelib)
-            {
-                /* build argv */
-                argptr = argv;
-                *argptr++ = "wine";
-                if (iconic) *argptr++ = "-iconic";
-                *argptr++ = lpCmdLine;
-                *argptr++ = 0;
+		if (__winelib)
+		{
+		    /* build argv */
+		    argptr = argv;
+		    *argptr++ = "wine";
+		    if (iconic) *argptr++ = "-iconic";
+		    *argptr++ = lpCmdLine;
+		    *argptr++ = 0;
 
-                /* Execute */
-                execvp(argv[0] , (char**)argv);
+		    /* Execute */
+		    execvp(argv[0] , (char**)argv);
 
-                /* Failed ! */
-                fprintf(stderr, "WinExec: can't exec 'wine %s'\n", lpCmdLine);
-            }
-	    exit(1);
+		    /* Failed ! */
+		    fprintf(stderr, "WinExec: can't exec 'wine %s'\n",
+			    lpCmdLine);
+		}
+		exit(1);
+	    }
 	}
-    }
+    } /* while (!exhausted && handle < 32) */
 
     GlobalFree16( cmdShowHandle );
     GlobalFree16( cmdLineHandle );
@@ -1590,6 +1625,35 @@
 
 
 /***********************************************************************
+ *           WIN32_GetProcAddress16   (KERNEL32.36)
+ * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
+ */
+FARPROC16 WIN32_GetProcAddress16( HMODULE16 hModule, LPSTR name )
+{
+    WORD	ordinal;
+    FARPROC16	ret;
+
+    if (!hModule) {
+    	fprintf(stderr,"WIN32_GetProcAddress16: hModule may not be 0!\n");
+	return (FARPROC16)0;
+    }
+    hModule = GetExePtr(hModule);
+    if (HIWORD(name)) {
+        ordinal = MODULE_GetOrdinal( hModule, name );
+        dprintf_module( stddeb, "WIN32_GetProcAddress16: %04x '%s'\n",
+                        hModule, name );
+    } else {
+        ordinal = LOWORD(name);
+        dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
+                        hModule, ordinal );
+    }
+    if (!ordinal) return (FARPROC16)0;
+    ret = MODULE_GetEntryPoint( hModule, ordinal );
+    dprintf_module(stddeb,"WIN32_GetProcAddress16: returning %08x\n",(UINT32)ret);
+    return ret;
+}
+
+/***********************************************************************
  *           GetProcAddress16   (KERNEL.50)
  */
 FARPROC16 GetProcAddress16( HMODULE16 hModule, SEGPTR name )
diff --git a/loader/ne_image.c b/loader/ne_image.c
index ca2819b..3536206 100644
--- a/loader/ne_image.c
+++ b/loader/ne_image.c
@@ -77,8 +77,8 @@
  		PTR_SEG_OFF_TO_LIN(pSegTable->selector,0);
  	oldstack = IF1632_Saved16_ss_sp;
  	oldselector = pSeg->selector;
- 	IF1632_Saved16_ss_sp = MAKELONG( 0xFF00 - sizeof(*stack16Top),
-                                         pModule->self_loading_sel );
+ 	IF1632_Saved16_ss_sp = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel,
+                                                 0xff00 - sizeof(*stack16Top));
         stack16Top = CURRENT_STACK16;
         stack16Top->saved_ss_sp = 0;
         stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
diff --git a/loader/resource.c b/loader/resource.c
index a569850..6e4ac03 100644
--- a/loader/resource.c
+++ b/loader/resource.c
@@ -626,7 +626,7 @@
     if (buffer) buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen * 2 );
     retval = LoadString32W(instance,resource_id,buffer2,buflen);
 
-    if (buffer)
+    if (buffer2)
     {
         lstrcpynWtoA( buffer, buffer2, buflen );
 	HeapFree( GetProcessHeap(), 0, buffer2 );
diff --git a/loader/signal.c b/loader/signal.c
index 43aae82..1257e33 100644
--- a/loader/signal.c
+++ b/loader/signal.c
@@ -1,4 +1,8 @@
-#ifndef WINELIB
+/*
+ * Wine signal handling
+ *
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <signal.h>
@@ -21,198 +25,110 @@
 #include <syscall.h>
 #endif
 
-#include "debugger.h"
-#include "options.h"
-#include "sigcontext.h"
-#include "win.h"
+#include "miscemu.h"
 #include "winsock.h"
 
-#if !defined(BSD4_4) || defined(linux) || defined(__FreeBSD__)
-char * cstack[4096];
-#endif
 
-#ifdef linux
-extern void ___sig_restore();
-extern void ___masksig_restore();
+/* Linux sigaction function */
 
+#if defined(linux) && defined(__i386__)
 /* This is the sigaction structure from the Linux 2.1.20 kernel.  */
-
-struct kernel_sigaction {
-	__sighandler_t sa_handler;
-	unsigned long sa_mask;
-	unsigned long sa_flags;
-	void (*sa_restorer) __P ((void));
+struct kernel_sigaction
+{
+    void (*sa_handler)();
+    unsigned long sa_mask;
+    unsigned long sa_flags;
+    void (*sa_restorer)();
 };
 
 /* Similar to the sigaction function in libc, except it leaves alone the
-   restorer field */
-
-static int
-wine_sigaction(int sig,struct kernel_sigaction * new, 
-               struct kernel_sigaction * old)
+   restorer field, which is used to specify the signal stack address */
+static __inline__ int wine_sigaction( int sig, struct kernel_sigaction *new,
+                                      struct kernel_sigaction *old )
 {
-	__asm__("int $0x80":"=a" (sig)
-		:"0" (SYS_sigaction),"b" (sig),"c" (new),"d" (old));
-	if (sig>=0)
-		return 0;
-	errno = -sig;
-	return -1;
+    __asm__ __volatile__( "int $0x80"
+                          : "=a" (sig)
+                          : "0" (SYS_sigaction),
+                            "b" (sig),
+                            "c" (new),
+                            "d" (old) );
+    if (sig>=0)
+        return 0;
+    errno = -sig;
+    return -1;
 }
-#endif /* linux */
+#endif /* linux && __i386__ */
 
 
-#ifdef linux
-#define HANDLER_DEF(name) void name (int signal, SIGCONTEXT context_struct)
-#define HANDLER_PROLOG SIGCONTEXT *context = &context_struct; (void)context; {
-#define HANDLER_EPILOG }
-#elif defined(__svr4__) || defined(_SCO_DS)
-#define HANDLER_DEF(name) void name (int signal, void *siginfo, SIGCONTEXT *context)
-#define HANDLER_PROLOG  /* nothing */
-#define HANDLER_EPILOG  /* nothing */
+/* Signal stack */
+
+#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+# define SIGNAL_STACK_SIZE  MINSIGSTKSZ
+#elif defined (__svr4__) || defined(_SCO_DS)
+# define SIGNAL_STACK_SIZE  SIGSTKSZ
 #else
-#define HANDLER_DEF(name) void name (int signal, int code, SIGCONTEXT *context)
-#define HANDLER_PROLOG  /* nothing */
-#define HANDLER_EPILOG  /* nothing */
+# define SIGNAL_STACK_SIZE  4096
 #endif
 
-extern BOOL32 INSTR_EmulateInstruction( SIGCONTEXT *context );
+static char SIGNAL_Stack[SIGNAL_STACK_SIZE];
 
-/**********************************************************************
- *		wine_timer
- *
- * SIGALRM handler.
- */
-static
-HANDLER_DEF(wine_timer)
-{
-  HANDLER_PROLOG;
-  /* Should do real-time timers here */
-  DOSMEM_Tick();
-  HANDLER_EPILOG;
-}
-
-/**********************************************************************
- *              SIGNAL_break
- * 
- * Handle Ctrl-C and such
- */
-static
-HANDLER_DEF(SIGNAL_break)
-{
-  HANDLER_PROLOG;
-  if (Options.debug) wine_debug( signal, context );  /* Enter our debugger */
-  exit(0);
-  HANDLER_EPILOG;
-}
 
 /**********************************************************************
  *              SIGNAL_child
  * 
  * wait4 terminated child processes
  */
-static
-HANDLER_DEF(SIGNAL_child)
+static void SIGNAL_child(void)
 {
-  HANDLER_PROLOG;
 #ifdef HAVE_WAIT4
-  wait4( 0, NULL, WNOHANG, NULL);
+    wait4( 0, NULL, WNOHANG, NULL);
 #elif defined (HAVE_WAITPID)
-  /* I am sort-of guessing that this is the same as the wait4 call.  */
-  waitpid (0, NULL, WNOHANG);
+    /* I am sort-of guessing that this is the same as the wait4 call.  */
+    waitpid (0, NULL, WNOHANG);
 #else
-  wait(NULL);
+    wait(NULL);
 #endif
-  HANDLER_EPILOG;
-}
-
-
-/**********************************************************************
- *		SIGNAL_trap
- *
- * SIGTRAP handler.
- */
-static
-HANDLER_DEF(SIGNAL_trap)
-{
-  HANDLER_PROLOG;
-  wine_debug( signal, context );  /* Enter our debugger */
-  HANDLER_EPILOG;
-}
-
-
-/**********************************************************************
- *		SIGNAL_fault
- *
- * Segfault handler.
- */
-static
-HANDLER_DEF(SIGNAL_fault)
-{
-  HANDLER_PROLOG;
-  if (CS_sig(context) == WINE_CODE_SELECTOR)
-    {
-        fprintf( stderr, "Segmentation fault in Wine program (%04x:%08lx)."
-                         "  Please debug.\n",
-		(unsigned short) CS_sig(context), EIP_sig(context));
-    }
-  else
-    {
-        if (INSTR_EmulateInstruction( context )) return;
-        fprintf( stderr, "Segmentation fault in Windows program %04x:%08lx.\n",
-		(unsigned short) CS_sig(context), EIP_sig(context) );
-    }
-  wine_debug( signal, context );
-  HANDLER_EPILOG;
 }
 
 
 /**********************************************************************
  *		SIGNAL_SetHandler
  */
-static void SIGNAL_SetHandler( int sig, void (*func)(), int flags )
+void SIGNAL_SetHandler( int sig, void (*func)(), int flags )
 {
     int ret;
 
-#ifdef linux
+#if defined(linux) && defined(__i386__)
+
     struct kernel_sigaction sig_act;
     sig_act.sa_handler = func;
     sig_act.sa_flags = SA_RESTART | (flags) ? SA_NOMASK : 0;
     /* Point to the top of the stack, minus 4 just in case, and make
        it aligned  */
     sig_act.sa_restorer = 
-        (void (*)()) (((unsigned int)(cstack) + sizeof(cstack) - 4) & ~3);
+        (void (*)())((int)(SIGNAL_Stack + sizeof(SIGNAL_Stack) - 4) & ~3);
     ret = wine_sigaction( sig, &sig_act, NULL );
-#endif  /* linux */
 
-#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+#else  /* linux && __i386__ */
+
     struct sigaction sig_act;
     sigset_t sig_mask;
     sigemptyset(&sig_mask);
     sig_act.sa_handler = func;
+    sig_act.sa_mask = sig_mask;
+
+# if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
     sig_act.sa_flags = SA_ONSTACK;
-    sig_act.sa_mask = sig_mask;
-    ret = sigaction( sig, &sig_act, NULL );
-#endif  /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ */
-
-#if defined (__svr4__) || defined(_SCO_DS)
-    struct sigaction sig_act;
-    sigset_t sig_mask;
-    sigemptyset(&sig_mask);
-    sig_act.sa_handler = func;
+# elif defined (__svr4__) || defined(_SCO_DS)
     sig_act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART;
-    sig_act.sa_mask = sig_mask;
-    ret = sigaction( sig, &sig_act, NULL );
-#endif  /* __svr4__ || _SCO_DS */
-
-#if defined(__EMX__)
-    struct sigaction sig_act;
-    sigset_t sig_mask;
-    sigemptyset(&sig_mask);
-    sig_act.sa_handler = func;
+# elif defined(__EMX__)
     sig_act.sa_flags = 0; /* FIXME: EMX has only SA_ACK and SA_SYSV */
-    sig_act.sa_mask = sig_mask;
+# else
+    sig_act.sa_flags = 0;
+# endif
     ret = sigaction( sig, &sig_act, NULL );
-#endif  /* __EMX__ */
+
+#endif  /* linux && __i386__ */
 
     if (ret < 0)
     {
@@ -230,53 +146,23 @@
  */
 BOOL32 SIGNAL_Init(void)
 {
-#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined (__svr4__) || defined(_SCO_DS)
     struct sigaltstack ss;
-        
-    if ((ss.ss_sp = malloc(MINSIGSTKSZ)) == NULL) {
-        fprintf(stderr, "Unable to allocate signal stack (%d bytes)\n",
-                MINSIGSTKSZ);
-        return FALSE;
-    }
-    ss.ss_size = MINSIGSTKSZ;
+    ss.ss_sp    = SIGNAL_Stack;
+    ss.ss_size  = sizeof(SIGNAL_Stack);
     ss.ss_flags = 0;
-    if (sigaltstack(&ss, NULL) < 0) {
+    if (sigaltstack(&ss, NULL) < 0)
+    {
         perror("sigstack");
         return FALSE;
     }
-#endif  /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ */
-
-#if defined (__svr4__) || defined(_SCO_DS)
-    struct sigaltstack ss;
-        
-    if ((ss.ss_sp = malloc(SIGSTKSZ) ) == NULL) {
-        fprintf(stderr, "Unable to allocate signal stack (%d bytes)\n",
-                SIGSTKSZ);
-        return FALSE;
-    }
-    ss.ss_size = SIGSTKSZ;
-    ss.ss_flags = 0;
-    if (sigaltstack(&ss, NULL) < 0) {
-        perror("sigstack");
-        return FALSE;
-    }
-#endif  /* __svr4__ || _SCO_DS */
+#endif  /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __svr4__ || _SCO_DS */
     
-    SIGNAL_SetHandler( SIGALRM, (void (*)())wine_timer, 1);
-    SIGNAL_SetHandler( SIGINT,  (void (*)())SIGNAL_break, 1);
     SIGNAL_SetHandler( SIGCHLD, (void (*)())SIGNAL_child, 1);
-    SIGNAL_SetHandler( SIGSEGV, (void (*)())SIGNAL_fault, 1);
-    SIGNAL_SetHandler( SIGILL,  (void (*)())SIGNAL_fault, 1);
-    SIGNAL_SetHandler( SIGFPE,  (void (*)())SIGNAL_fault, 1);
-    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
 #ifdef CONFIG_IPC
     SIGNAL_SetHandler( SIGUSR2, (void (*)())stop_wait, 1); 	/* For IPC */
 #endif
-#ifndef __EMX__ /* FIXME */
+#ifdef SIGIO
     SIGNAL_SetHandler( SIGIO,   (void (*)())WINSOCK_sigio, 0); 
 #endif
     return TRUE;
@@ -284,34 +170,13 @@
 
 
 /**********************************************************************
- *		SIGNAL_StartBIOSTimer
- *
- * Start the BIOS tick timer.
- */
-void SIGNAL_StartBIOSTimer(void)
-{
-#ifndef __EMX__ /* FIXME: Time don't work... Use BIOS directly instead */
-    struct itimerval vt_timer;
-    static int timer_started = 0;
-
-    if (timer_started) return;
-    timer_started = 1;
-    vt_timer.it_interval.tv_sec = 0;
-    vt_timer.it_interval.tv_usec = 54929;
-    vt_timer.it_value = vt_timer.it_interval;
-
-    setitimer(ITIMER_REAL, &vt_timer, NULL);
-#endif
-}
-
-/**********************************************************************
  *              SIGNAL_MaskAsyncEvents
  */
 void SIGNAL_MaskAsyncEvents( BOOL32 flag )
 {
   sigset_t 	set;
   sigemptyset(&set);
-#ifndef __EMX__ /* FIXME */
+#ifdef SIGIO
   sigaddset(&set, SIGIO);
 #endif
   sigaddset(&set, SIGUSR1);
@@ -320,5 +185,3 @@
 #endif
   sigprocmask( (flag) ? SIG_BLOCK : SIG_UNBLOCK , &set, NULL);
 }
-
-#endif /* ifndef WINELIB */
diff --git a/loader/task.c b/loader/task.c
index 93756c8..4094ee9 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -578,9 +578,9 @@
 
       /* Create the 16-bit stack frame */
 
-    pTask->ss_sp = MAKELONG( ((pModule->sp != 0) ? pModule->sp :
-                 pSegTable[pModule->ss-1].minsize + pModule->stack_size) & ~1,
-                             hInstance );
+    pTask->ss_sp = PTR_SEG_OFF_TO_SEGPTR( hInstance,
+                        ((pModule->sp != 0) ? pModule->sp :
+                pSegTable[pModule->ss-1].minsize + pModule->stack_size) & ~1 );
     stack16Top = (char *)PTR_SEG_TO_LIN( pTask->ss_sp );
     frame16 = (STACK16FRAME *)stack16Top - 1;
     frame16->saved_ss_sp = 0;
@@ -1159,8 +1159,8 @@
 
     /* Switch to the new stack */
 
-    IF1632_Saved16_ss_sp = pTask->ss_sp = MAKELONG( ptr - sizeof(STACK16FRAME),
-                                                    seg );
+    IF1632_Saved16_ss_sp = pTask->ss_sp = PTR_SEG_OFF_TO_SEGPTR( seg,
+                                                  ptr - sizeof(STACK16FRAME) );
     newFrame = CURRENT_STACK16;
 
     /* Copy the stack frame and the local variables to the new stack */
@@ -1216,23 +1216,19 @@
 /***********************************************************************
  *           GetTaskQueueDS  (KERNEL.118)
  */
-#ifndef WINELIB
 void GetTaskQueueDS( CONTEXT *context )
 {
     DS_reg(context) = GlobalHandleToSel( GetTaskQueue(0) );
 }
-#endif  /* WINELIB */
 
 
 /***********************************************************************
  *           GetTaskQueueES  (KERNEL.119)
  */
-#ifndef WINELIB
 void GetTaskQueueES( CONTEXT *context )
 {
     ES_reg(context) = GlobalHandleToSel( GetTaskQueue(0) );
 }
-#endif  /* WINELIB */
 
 
 /***********************************************************************
diff --git a/memory/ldt.c b/memory/ldt.c
index fce33af..de1cad0 100644
--- a/memory/ldt.c
+++ b/memory/ldt.c
@@ -13,8 +13,10 @@
 #include "stddebug.h"
 #include "debug.h"
 
+#ifdef __i386__
+
 #ifdef linux
-#include <asm/unistd.h>
+#include <sys/syscall.h>
 
 struct modify_ldt_s 
 {
@@ -28,8 +30,21 @@
     unsigned int  seg_not_present : 1;
 };
 
-static __inline__ _syscall3(int, modify_ldt, int, func, void *, ptr,
-                            unsigned long, bytecount);
+static __inline__ int modify_ldt( int func, struct modify_ldt_s *ptr,
+                                  unsigned long count )
+{
+    int res;
+    __asm__ __volatile__("int $0x80"
+                         : "=a" (res)
+                         : "0" (SYS_modify_ldt),
+                           "b" (func),
+                           "c" (ptr),
+                           "d" (count) );
+    if (res >= 0) return res;
+    errno = -res;
+    return -1;
+}
+
 #endif  /* linux */
 
 #if defined(__svr4__) || defined(_SCO_DS)
@@ -44,6 +59,8 @@
 extern int i386_set_ldt(int, union descriptor *, int);
 #endif  /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */
 
+#endif  /* __i386__ */
+
 
 ldt_copy_entry ldt_copy[LDT_SIZE];
 unsigned char ldt_flags_copy[LDT_SIZE];
@@ -129,6 +146,8 @@
     /* Entry 0 must not be modified; its base and limit are always 0 */
     if (!entry) return 0;
 
+#ifdef __i386__
+
 #ifdef linux
     if (!__winelib)
     {
@@ -189,6 +208,7 @@
         }
     }
 #endif  /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */
+
 #if defined(__svr4__) || defined(_SCO_DS)
     if (!__winelib)
     {
@@ -217,6 +237,8 @@
     }    
 #endif
 
+#endif  /* __i386__ */
+
     if (ret < 0) return ret;
     ldt_copy[entry].base = content->base;
     if (!content->limit_in_pages) ldt_copy[entry].limit = content->limit;
diff --git a/memory/local.c b/memory/local.c
index 3baea5d..e54c03a 100644
--- a/memory/local.c
+++ b/memory/local.c
@@ -159,7 +159,7 @@
         next = pNext->next;
     }
 
-    dprintf_local( stddeb, "Local_AddFreeBlock %04x, next %04x\n", block, next );
+    dprintf_local( stddeb, "Local_MakeBlockFree %04x, next %04x\n", block, next );
       /* Insert the free block in the free-list */
 
     pArena->free_prev = pNext->free_prev;
diff --git a/misc/comm.c b/misc/comm.c
index 36d3f7e..d119200 100644
--- a/misc/comm.c
+++ b/misc/comm.c
@@ -407,7 +407,7 @@
 		port = device[3] - '0';
 
 		if (port-- == 0) {
-			fprintf(stderr, "comm: BUG ! COM0 doesn't exists!.\n");
+			fprintf(stderr, "comm: BUG ! COM0 doesn't exist !\n");
 			commerror = IE_BADID;
 		}
 
@@ -738,18 +738,27 @@
 	unsigned long	cnt;
 	int		rc;
 
-	lpStat->status = 0;
+	if (lpStat) {
+		lpStat->status = 0;
 
-	rc = ioctl(fd, TIOCOUTQ, &cnt);
-	lpStat->cbOutQue = cnt;
+		rc = ioctl(fd, TIOCOUTQ, &cnt);
+		if (rc) fprintf(stderr, "Error !\n");
+		lpStat->cbOutQue = cnt;
 
-	rc = ioctl(fd, TIOCINQ, &cnt);
-	lpStat->cbInQue = cnt;
+		rc = ioctl(fd, TIOCINQ, &cnt);
+                if (rc) fprintf(stderr, "Error !\n");
+		lpStat->cbInQue = cnt;
 
-    	dprintf_comm(stddeb,
-		"GetCommError: fd %d, error %d, lpStat %d %d %d\n",
-		fd, commerror,
-		lpStat->status, lpStat->cbInQue, lpStat->cbOutQue);
+    		dprintf_comm(stddeb,
+			"GetCommError: fd %d, error %d, lpStat %d %d %d\n",
+			fd, commerror,
+			lpStat->status, lpStat->cbInQue, lpStat->cbOutQue);
+	}
+	else
+		dprintf_comm(stddeb,
+                "GetCommError: fd %d, error %d, lpStat NULL\n",
+                fd, commerror);
+
 	/*
 	 * [RER] I have no idea what the following is trying to accomplish.
 	 * [RER] It is certainly not what the reference manual suggests.
@@ -1652,7 +1661,7 @@
  *	GetCommTimeouts		(KERNEL32.160)
  */
 BOOL32 GetCommTimeouts(INT32 fd,LPCOMMTIMEOUTS lptimeouts) {
-	dprintf_comm(stddeb,"GetCommTimeouts(%x,%p), empty stub.\n",
+	fprintf(stderr,"GetCommTimeouts(%x,%p), empty stub.\n",
 		fd,lptimeouts
 	);
 	return TRUE;
@@ -1662,8 +1671,19 @@
  *	SetCommTimeouts		(KERNEL32.453)
  */
 BOOL32 SetCommTimeouts(INT32 fd,LPCOMMTIMEOUTS lptimeouts) {
-	dprintf_comm(stddeb,"SetCommTimeouts(%x,%p), empty stub.\n",
+	fprintf(stderr,"SetCommTimeouts(%x,%p), empty stub.\n",
 		fd,lptimeouts
 	);
 	return TRUE;
 }
+
+/***********************************************************************
+ *           EnableCommNotification   (USER.246)
+ */
+BOOL16 EnableCommNotification( INT16 fd, HWND16 hwnd, INT16 cbWriteNotify,
+                               INT16 cbOutQueue )
+{
+	fprintf(stderr, "EnableCommNotification(%d, %x, %d, %d), empty stub.\n", fd, hwnd, cbWriteNotify, cbOutQueue);
+	return TRUE;
+}
+
diff --git a/misc/compobj.c b/misc/compobj.c
index c7c76a2..45decf8 100644
--- a/misc/compobj.c
+++ b/misc/compobj.c
@@ -7,10 +7,14 @@
 /*	At the moment, these are only empty stubs.
  */
 
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
 #include "ole.h"
 #include "ole2.h"
 #include "stddebug.h"
 #include "debug.h"
+#include "compobj.h"
 
 DWORD currentMalloc=0;
 
@@ -66,3 +70,109 @@
     dprintf_ole(stdnimp,"CoDisconnectObject:%p %lx\n",lpUnk,reserved);
     return OLE_OK;
 }
+
+/***********************************************************************
+ *           CLSIDFromString [COMPOBJ.20]
+ */
+
+/* Class id: DWORD-WORD-WORD-BYTES[2]-BYTES[6] */
+
+OLESTATUS
+CLSIDFromString(const LPCSTR idstr, CLSID *id)
+{
+  BYTE *s = (BYTE *) idstr;
+  BYTE *p;
+  int	i;
+  BYTE table[256];
+
+  dprintf_ole(stddeb,"ClsIDFromString() %s -> %p\n", idstr, id);
+
+  /* quick lookup table */
+  memset(table, 0, 256);
+
+  for (i = 0; i < 10; i++) {
+    table['0' + i] = i;
+  }
+  for (i = 0; i < 6; i++) {
+    table['A' + i] = i+10;
+    table['a' + i] = i+10;
+  }
+
+  /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
+
+  if (strlen(idstr) != 38)
+    return OLE_ERROR_OBJECT;
+
+  p = (BYTE *) id;
+
+  s++;	/* skip leading brace  */
+  for (i = 0; i < 4; i++) {
+    p[3 - i] = table[*s]<<4 | table[*(s+1)];
+    s += 2;
+  }
+  p += 4;
+  s++;	/* skip - */
+
+  for (i = 0; i < 2; i++) {
+    p[1-i] = table[*s]<<4 | table[*(s+1)];
+    s += 2;
+  }
+  p += 2;
+  s++;	/* skip - */
+
+  for (i = 0; i < 2; i++) {
+    p[1-i] = table[*s]<<4 | table[*(s+1)];
+    s += 2;
+  }
+  p += 2;
+  s++;	/* skip - */
+
+  /* these are just sequential bytes */
+  for (i = 0; i < 2; i++) {
+    *p++ = table[*s]<<4 | table[*(s+1)];
+    s += 2;
+  }
+  s++;	/* skip - */
+
+  for (i = 0; i < 6; i++) {
+    *p++ = table[*s]<<4 | table[*(s+1)];
+    s += 2;
+  }
+
+  return OLE_OK;
+}
+
+/***********************************************************************
+ *           CLSIDFromString [COMPOBJ.19]
+ */
+
+OLESTATUS
+StringFromCLSID(const CLSID *id, LPSTR idstr)
+{
+  static const char *hex = "0123456789ABCDEF";
+  char *s;
+  int	i;
+
+  sprintf(idstr, "{%08lx-%04x-%04x-%2x%2x-",
+	  id->Data1, id->Data2, id->Data3,
+	  id->Data4[0], id->Data4[1]);
+  s = &idstr[25];
+
+  /* 6 hex bytes */
+  for (i = 2; i < 8; i++) {
+    *s++ = hex[id->Data4[i]>>4];
+    *s++ = hex[id->Data4[i] & 0xf];
+  }
+
+  *s++ = '}';
+  *s++ = '\0';
+
+  for (i = strlen(idstr)-1; i >= 0; i--) {
+    idstr[i] = toupper(idstr[i]);
+  }
+
+  dprintf_ole(stddeb,"StringFromClsID: %p->%s\n", id, idstr);
+
+  return OLE_OK;
+}
+
diff --git a/misc/registry.c b/misc/registry.c
index 2719bd3..791e5db 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -26,8 +26,6 @@
 #include "xmalloc.h"
 #include "winreg.h"
 
-#define MAKE_DWORD(x,y) ((DWORD)MAKELONG(x,y))
-
 /* FIXME: following defines should be configured global ... */
 
 /* NOTE: do not append a /. linux' mkdir() WILL FAIL if you do that */
@@ -275,6 +273,7 @@
 
 	RegCreateKey16(HKEY_DYN_DATA,"\\PerfStats\\StatData",&xhkey);
 	RegCloseKey(xhkey);
+        xhkey = 0;
 	RegCreateKey16(HKEY_LOCAL_MACHINE,"\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor",&hkey);
 #ifdef linux
 	F=fopen("/proc/cpuinfo","r");
@@ -392,7 +391,7 @@
 		if (escapeeq && *s=='=')
 			doescape = 1;
 		if (*s=='\\')
-			fputc(*s,F); /* if \\ than put it twice. */
+                        fputc(*s,F); /* if \\ then put it twice. */
 		if (doescape)
 			fprintf(F,"\\u%04x",*((unsigned short*)s));
 		else
@@ -3000,7 +2999,7 @@
 		lpcbSecurityDescriptor,
 		ft
 	);
-	if (ret==ERROR_SUCCESS)
+	if (ret==ERROR_SUCCESS && lpszClass)
 		lstrcpyWtoA(lpszClass,lpszClassW);
 	if (lpcchClass)
 		*lpcchClass/=2;
diff --git a/misc/system.c b/misc/system.c
index aaeeae5..dee79bd 100644
--- a/misc/system.c
+++ b/misc/system.c
@@ -5,29 +5,187 @@
  */
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
 #include "windows.h"
+#include "miscemu.h"
+
+typedef struct
+{
+    FARPROC16 callback;  /* NULL if not in use */
+    INT32     rate;
+    INT32     ticks;
+} SYSTEM_TIMER;
+
+#define NB_SYS_TIMERS   8
+#define SYS_TIMER_RATE  54925
+
+static SYSTEM_TIMER SYS_Timers[NB_SYS_TIMERS];
+static int SYS_NbTimers = 0;
+static BOOL32 SYS_TimersDisabled = FALSE;
+
+/***********************************************************************
+ *           SYSTEM_TimerTick
+ */
+static void SYSTEM_TimerTick(void)
+{
+    int i;
+
+    for (i = 0; i < NB_SYS_TIMERS; i++)
+    {
+        if (!SYS_Timers[i].callback) continue;
+        if ((SYS_Timers[i].ticks -= SYS_TIMER_RATE) <= 0)
+        {
+            SYS_Timers[i].ticks += SYS_Timers[i].rate;
+            SYS_Timers[i].callback();
+        }
+    }
+}
+
+
+/**********************************************************************
+ *           SYSTEM_StartTicks
+ *
+ * Start the system tick timer.
+ */
+static void SYSTEM_StartTicks(void)
+{
+    static BOOL32 handler_installed = FALSE;
+
+    if (!handler_installed)
+    {
+        handler_installed = TRUE;
+        SIGNAL_SetHandler( SIGALRM, SYSTEM_TimerTick, 1 );
+    }
+#ifndef __EMX__ /* FIXME: Time don't work... Use BIOS directly instead */
+    {
+        struct itimerval vt_timer;
+
+        vt_timer.it_interval.tv_sec = 0;
+        vt_timer.it_interval.tv_usec = 54929;
+        vt_timer.it_value = vt_timer.it_interval;
+        setitimer( ITIMER_REAL, &vt_timer, NULL );
+    }
+#endif
+}
+
+
+/**********************************************************************
+ *           SYSTEM_StopTicks
+ *
+ * Stop the system tick timer.
+ */
+static void SYSTEM_StopTicks(void)
+{
+#ifndef __EMX__ /* FIXME: Time don't work... Use BIOS directly instead */
+    struct itimerval vt_timer;
+
+    vt_timer.it_interval.tv_sec = 0;
+    vt_timer.it_interval.tv_usec = 0;
+    vt_timer.it_value = vt_timer.it_interval;
+    setitimer( ITIMER_REAL, &vt_timer, NULL );
+#endif
+}
 
 
 /***********************************************************************
  *           InquireSystem   (SYSTEM.1)
- */
-DWORD InquireSystem( WORD code, WORD drive, BOOL16 enable )
+ *
+ * Note: the function always takes 2 WORD arguments, contrary to what
+ *       "Undocumented Windows" says.
+  */
+DWORD InquireSystem( WORD code, WORD arg )
 {
     WORD drivetype;
 
     switch(code)
     {
     case 0:  /* Get timer resolution */
-        return 54925;
+        return SYS_TIMER_RATE;
 
     case 1:  /* Get drive type */
-        drivetype = GetDriveType16( drive );
+        drivetype = GetDriveType16( arg );
         return MAKELONG( drivetype, drivetype );
 
     case 2:  /* Enable one-drive logic */
-        fprintf( stderr, "InquireSystem(2): set single-drive %d not supported\n", enable );
+        fprintf( stderr, "InquireSystem(2): set single-drive %d not supported\n", arg );
         return 0;
     }
     fprintf( stderr, "InquireSystem: unknown code %d\n", code );
     return 0;
 }
+
+
+/***********************************************************************
+ *           CreateSystemTimer   (SYSTEM.2)
+ */
+WORD CreateSystemTimer( WORD rate, FARPROC16 callback )
+{
+    int i;
+
+    for (i = 0; i < NB_SYS_TIMERS; i++)
+        if (!SYS_Timers[i].callback)  /* Found one */
+        {
+            SYS_Timers[i].rate = (UINT32)rate * 1000;
+            if (SYS_Timers[i].rate < SYS_TIMER_RATE)
+                SYS_Timers[i].rate = SYS_TIMER_RATE;
+            SYS_Timers[i].ticks = SYS_Timers[i].rate;
+            SYS_Timers[i].callback = callback;
+            if ((++SYS_NbTimers == 1) && !SYS_TimersDisabled)
+                SYSTEM_StartTicks();
+            return i + 1;  /* 0 means error */
+        }
+    return 0;
+}
+
+
+/***********************************************************************
+ *           KillSystemTimer   (SYSTEM.3)
+ *
+ * Note: do not confuse this function with USER.182
+ */
+WORD SYSTEM_KillSystemTimer( WORD timer )
+{
+    if (!timer || (timer > NB_SYS_TIMERS)) return timer;  /* Error */
+    SYS_Timers[timer-1].callback = NULL;
+    if ((!--SYS_NbTimers) && !SYS_TimersDisabled) SYSTEM_StopTicks();
+    return 0;
+}
+
+
+/***********************************************************************
+ *           EnableSystemTimers   (SYSTEM.4)
+ */
+void EnableSystemTimers(void)
+{
+    SYS_TimersDisabled = FALSE;
+    if (SYS_NbTimers) SYSTEM_StartTicks();
+}
+
+
+/***********************************************************************
+ *           DisableSystemTimers   (SYSTEM.5)
+ */
+void DisableSystemTimers(void)
+{
+    SYS_TimersDisabled = TRUE;
+    if (SYS_NbTimers) SYSTEM_StopTicks();
+}
+
+
+/***********************************************************************
+ *           SYSTEM_GetTimerProc
+ *
+ * Return the timer proc of a system timer. Used by thunking code.
+ */
+FARPROC16 SYSTEM_GetTimerProc( WORD timer )
+{
+    if (!timer || (timer > NB_SYS_TIMERS)) return NULL;
+    return SYS_Timers[timer-1].callback;
+}
diff --git a/misc/tweak.c b/misc/tweak.c
index a9118d5..e8f0095 100644
--- a/misc/tweak.c
+++ b/misc/tweak.c
@@ -410,16 +410,19 @@
 
 /******************************************************************************
  *
- *   void  TWEAK_DrawMenuSeparator95(
+ *   void  TWEAK_DrawRevReliefRect95(
  *      HDC32  hdc,               // Device context on which to draw
- *      UINT32  xc1,              // Left x-coordinate
- *      UINT32  yc,               // Y-coordinate of the LOWER line
- *      UINT32  xc2 )             // Right x-coordinate
+ *      RECT32 const  *rect )     // Rectangle to use
  *
- *   Draws the menu separator bar Win 95 style.
+ *   Draws the double-bordered Win95-style relief rectangle.
  *
  *   Bugs
- *        Same as those for DrawReliefRect95.
+ *        There are some checks missing from this function.  Perhaps the
+ *        SelectObject32 calls should be examined?  Hasn't failed on me (yet).
+ *
+ *        Should I really be calling X functions directly from here?  It is
+ *        an optimization, but should I be optimizing alpha code?  Probably
+ *        not.
  *
  *   Revision history
  *        08-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
@@ -427,7 +430,76 @@
  *
  *****************************************************************************/
 
-void  TWEAK_DrawMenuSeparator95(
+void  TWEAK_DrawRevReliefRect95(
+    HDC32  hdc,
+    RECT32 const  *rect )
+{
+    DC  *dc;
+    HPEN32  prevpen;
+
+    if((dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC))) {
+
+	/* Draw the top/left lines first */
+	prevpen = SelectObject32(hdc, TWEAK_Pen8095);
+	DC_SetupGCForPen(dc);
+	XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left, rect->top,
+		  rect->right - 1, rect->top);
+	XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left, rect->top,
+		  rect->left, rect->bottom - 1);
+
+	SelectObject32(hdc, TWEAK_Pen0095);
+	DC_SetupGCForPen(dc);
+	XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left + 1,
+		  rect->top + 1, rect->right - 2, rect->top + 1);
+	XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left + 1,
+		  rect->top + 1, rect->left + 1, rect->bottom - 2);
+
+
+	/* Now the bottom/right lines */
+	SelectObject32(hdc, TWEAK_PenFF95);
+	DC_SetupGCForPen(dc);
+	XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left,
+		  rect->bottom - 1, rect->right - 1, rect->bottom - 1);
+	XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->right - 1,
+		  rect->top, rect->right - 1, rect->bottom - 1);
+
+	SelectObject32(hdc, TWEAK_PenE095);
+	DC_SetupGCForPen(dc);
+	XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left + 1,
+		  rect->bottom - 2, rect->right - 2, rect->bottom - 2);
+	XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->right - 2,
+		  rect->top + 1, rect->right - 2, rect->bottom - 2);
+	
+	SelectObject32(hdc, prevpen);
+    }
+
+    return;
+}
+
+
+
+/******************************************************************************
+ *
+ *   void  TWEAK_DrawMenuSeparatorHoriz95(
+ *      HDC32  hdc,               // Device context on which to draw
+ *      UINT32  xc1,              // Left x-coordinate
+ *      UINT32  yc,               // Y-coordinate of the LOWER line
+ *      UINT32  xc2 )             // Right x-coordinate
+ *
+ *   Draws a horizontal menu separator bar Win 95 style.
+ *
+ *   Bugs
+ *        Same as those for DrawReliefRect95.
+ *
+ *   Revision history
+ *        08-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
+ *             Original implementation.
+ *        11-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
+ *             Changed name from DrawMenuSeparator95
+ *
+ *****************************************************************************/
+
+void  TWEAK_DrawMenuSeparatorHoriz95(
     HDC32  hdc,
     UINT32  xc1,
     UINT32  yc,
@@ -454,3 +526,52 @@
 
     return;
 }
+
+
+/******************************************************************************
+ *
+ *   void  TWEAK_DrawMenuSeparatorVert95(
+ *      HDC32  hdc,               // Device context on which to draw
+ *      UINT32  xc,               // X-coordinate of the RIGHT line
+ *      UINT32  yc1,              // top Y-coordinate
+ *      UINT32  yc2 )             // bottom Y-coordinate
+ *
+ *   Draws a vertical menu separator bar Win 95 style.
+ *
+ *   Bugs
+ *        Same as those for DrawReliefRect95.
+ *
+ *   Revision history
+ *        11-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
+ *             Original implementation.
+ *
+ *****************************************************************************/
+
+void  TWEAK_DrawMenuSeparatorVert95(
+    HDC32  hdc,
+    UINT32  xc,
+    UINT32  yc1,
+    UINT32  yc2 )
+{
+    DC  *dc;
+    HPEN32  prevpen;
+
+    if((dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC))) {
+
+	/* Draw the top line */
+	prevpen = SelectObject32(hdc, TWEAK_Pen8095);
+	DC_SetupGCForPen(dc);
+	XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, xc, yc1, xc,
+		  yc2);
+
+	/* And the bottom line */
+	SelectObject32(hdc, TWEAK_PenFF95);
+	DC_SetupGCForPen(dc);
+	XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, xc + 1, yc1, xc + 1,
+		  yc2);
+
+	SelectObject32(hdc, prevpen);
+    }
+
+    return;
+}
diff --git a/misc/ver.c b/misc/ver.c
index 51b9089..0a747bf 100644
--- a/misc/ver.c
+++ b/misc/ver.c
@@ -983,15 +983,15 @@
 /* in memory structure... */
 	char	name[1]; 	/* padded to dword alignment */
 /* .... 
-	char	data[datalen];     padded to dword alignemnt
+	char	data[datalen];     padded to dword alignment
 	BYTE	subdirdata[];      until nextoff
  */
 };
 
 static BYTE*
-_find_data(BYTE *block,LPCSTR str) {
+_find_data(BYTE *block,LPCSTR str, WORD buff_remain) {
 	char	*nextslash;
-	int	substrlen;
+	int	substrlen, inc_size;
 	struct	db	*db;
 
 	while (*str && *str=='\\')
@@ -1013,20 +1013,23 @@
 		dprintf_ver(stddeb,"db=%p,db->nextoff=%d,db->datalen=%d,db->name=%s,db->data=%s\n",
 			db,db->nextoff,db->datalen,db->name,(char*)((char*)db+4+((strlen(db->name)+4)&~3))
 		);
-		if (!db->nextoff)
+		if ((!db->nextoff) || (!buff_remain)) /* no more entries ? */
 			return NULL;
 
 		dprintf_ver(stddeb,"comparing with %s\n",db->name);
 		if (!strncmp(db->name,str,substrlen)) {
-			if (nextslash)
-				return _find_data(
-					block+4+((strlen(db->name)+4)&~3)+((db->datalen+3)&~3)
-					,nextslash
-				);
+			if (nextslash) {
+				inc_size = 4+((strlen(db->name)+4)&~3)+((db->datalen+3)&~3);
+
+				return _find_data( block+inc_size ,nextslash,
+							buff_remain - inc_size);
+			}
 			else
 				return block;
 		}
-		block=block+((db->nextoff+3)&~3);
+		inc_size=((db->nextoff+3)&~3);
+		block=block+inc_size;
+		buff_remain=buff_remain-inc_size;
 	}
 }
 
@@ -1044,7 +1047,7 @@
 	);
 	s=(char*)xmalloc(strlen("VS_VERSION_INFO\\")+strlen(subblock)+1);
 	strcpy(s,"VS_VERSION_INFO\\");strcat(s,subblock);
-	b=_find_data(block,s);
+	b=_find_data(block, s, *(WORD *)block);
 	if (b==NULL) {
 		*buflen=0;
 		return 0;
@@ -1071,7 +1074,7 @@
 	);
 	s=(char*)xmalloc(strlen("VS_VERSION_INFO\\")+strlen(subblock)+1);
 	strcpy(s,"VS_VERSION_INFO\\");strcat(s,subblock);
-	b=_find_data(block,s);
+	b=_find_data(block, s, *(WORD *)block);
 	if (b==NULL) {
 		*buflen=0;
 		return 0;
@@ -1100,7 +1103,7 @@
 	sb = HEAP_strdupWtoA( GetProcessHeap(), 0, subblock );
 	s=(char*)xmalloc(strlen("VS_VERSION_INFO\\")+strlen(sb)+1);
 	strcpy(s,"VS_VERSION_INFO\\");strcat(s,sb);
-	b=_find_data(block,s);
+	b=_find_data(block, s, *(WORD *)block);
 	if (b==NULL) {
 		*buflen=0;
 		HeapFree( GetProcessHeap(), 0, sb );
diff --git a/misc/winsock.c b/misc/winsock.c
index e4ecd51..159ed1c 100644
--- a/misc/winsock.c
+++ b/misc/winsock.c
@@ -42,6 +42,7 @@
 #include "heap.h"
 #include "ldt.h"
 #include "winsock.h"
+#include "miscemu.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -51,8 +52,6 @@
                         inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
                         ntohs(((struct sockaddr_in *)a)->sin_port))
 
-extern void SIGNAL_MaskAsyncEvents( BOOL32 );
-
 #pragma pack(4)
 
 /* ----------------------------------- internal data */
diff --git a/misc/wsprintf.c b/misc/wsprintf.c
index 4ca4828..9cfbc57 100644
--- a/misc/wsprintf.c
+++ b/misc/wsprintf.c
@@ -257,8 +257,15 @@
             else cur_arg = (DWORD)PTR_SEG_TO_LIN( *(SEGPTR *)args );
             args = (SEGPTR *)args + 1;
             break;
-        case WPR_HEXA:
         case WPR_SIGNED:
+            if (!(format.flags & WPRINTF_LONG))
+            {
+                cur_arg = (DWORD)(INT32)*(INT16 *)args;
+                args = (INT16 *)args + 1;
+                break;
+            }
+            /* fall through */
+        case WPR_HEXA:
         case WPR_UNSIGNED:
             if (format.flags & WPRINTF_LONG)
             {
diff --git a/miscemu/instr.c b/miscemu/instr.c
index 0d50be6..931cfe8 100644
--- a/miscemu/instr.c
+++ b/miscemu/instr.c
@@ -28,10 +28,11 @@
 {
     if (sel == 0x40)
     {
-        extern void SIGNAL_StartBIOSTimer(void);
+        static WORD sys_timer = 0;
         fprintf( stderr, "Direct access to segment 0x40 (cs:ip=%04x:%04lx).\n",
                  CS_sig(context), EIP_sig(context) );
-        SIGNAL_StartBIOSTimer();
+        if (!sys_timer)
+            sys_timer = CreateSystemTimer( 55, (FARPROC16)DOSMEM_Tick );
         return DOSMEM_BiosSeg;
     }
     return 0;  /* Can't replace selector */
diff --git a/msdos/int21.c b/msdos/int21.c
index d813682..46b0004 100644
--- a/msdos/int21.c
+++ b/msdos/int21.c
@@ -216,9 +216,11 @@
 
 static void ioctlGetDeviceInfo( CONTEXT *context )
 {
+    int curr_drive;
     dprintf_int (stddeb, "int21: ioctl (%d, GetDeviceInfo)\n", BX_reg(context));
     
-    DX_reg(context) = 0x0942;
+    curr_drive = DRIVE_GetCurrentDrive();
+    DX_reg(context) = 0x0140 + curr_drive + ((curr_drive > 1) ? 0x0800 : 0); /* no floppy */
     /* bits 0-5 are current drive
      * bit 6 - file has NOT been written..FIXME: correct?
      * bit 8 - generate int24 if no diskspace on write/ read past end of file
@@ -332,10 +334,11 @@
         SET_CFLAG(context);
     }
 #if 0
-	int handle;
-	int mode;
-	int lock;
-	
+    {
+        int handle;
+        int mode;
+        int lock;
+
         switch (AX_reg(context) & 0x0070)
 	{
 	  case 0x00:    /* compatability mode */
@@ -385,7 +388,7 @@
 	  if(result)  
 	  {
 	    errno_to_doserr();
-	    AX_reg(context) = ExtendedError;
+	    AX_reg(context) = DOS_ExtendedError;
 	    close(handle);
 	    SET_CFLAG(context);
 	    return;
@@ -396,6 +399,7 @@
 	Error (0,0,0);
 	AX_reg(context) = handle;
 	RESET_CFLAG(context);
+    }
 #endif
 }
 
diff --git a/msdos/ioports.c b/msdos/ioports.c
index 4c9ebf9..1668963 100644
--- a/msdos/ioports.c
+++ b/msdos/ioports.c
@@ -10,20 +10,15 @@
      fix that, I guess.
 */
 
-#ifdef linux
 #include <ctype.h>
-#include <unistd.h>
-#include <asm/io.h>
-#include <string.h>
-#include "options.h"
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <time.h>
+#include <unistd.h>
 #include "windows.h"
+#include "options.h"
 #include "stddebug.h"
-/* #define DEBUG_INT */
 #include "debug.h"
 
 static BYTE cmosaddress;
@@ -40,9 +35,18 @@
   0x1b, 0x7b, 0x21, 0x00, 0x00, 0x00, 0x05, 0x5f
 };
 
-#ifdef linux
-char do_direct_port_access = 0;
-char port_permissions[0x10000];
+#if defined(linux) && defined(__i386__)
+# define DIRECT_IO_ACCESS
+#else
+# undef DIRECT_IO_ACCESS
+#endif  /* linux && __i386__ */
+
+#ifdef DIRECT_IO_ACCESS
+static char do_direct_port_access = 0;
+static char port_permissions[0x10000];
+
+#define IO_READ  1
+#define IO_WRITE 2
 #endif
 
 /**********************************************************************
@@ -52,8 +56,8 @@
 /* set_IO_permissions(int val1, int val)
  * Helper function for IO_port_init
  */
-#ifdef linux
-void set_IO_permissions(int val1, int val, char rw)
+#ifdef DIRECT_IO_ACCESS
+static void set_IO_permissions(int val1, int val, char rw)
 {
 	int j;
 	if (val1 != -1) {
@@ -76,7 +80,7 @@
  * Helper function for IO_port_init
  */
 
-void do_IO_port_init_read_or_write(char* temp, char rw)
+static void do_IO_port_init_read_or_write(char* temp, char rw)
 {
 	int val, val1, i, len;
 	if (!strcasecmp(temp, "all")) {
@@ -126,32 +130,64 @@
 	}
 }
 
-#endif
+static __inline__ BYTE inb( WORD port )
+{
+    BYTE b;
+    __asm__ __volatile__( "inb %w1,%0" : "=a" (b) : "d" (port) );
+    return b;
+}
+
+static __inline__ WORD inw( WORD port )
+{
+    WORD w;
+    __asm__ __volatile__( "inw %w1,%0" : "=a" (w) : "d" (port) );
+    return w;
+}
+
+static __inline__ DWORD inl( WORD port )
+{
+    DWORD dw;
+    __asm__ __volatile__( "inl %w1,%0" : "=a" (dw) : "d" (port) );
+    return dw;
+}
+
+static __inline__ void outb( BYTE value, WORD port )
+{
+    __asm__ __volatile__( "outb %b0,%w1" : : "a" (value), "d" (port) );
+}
+
+static __inline__ void outw( WORD value, WORD port )
+{
+    __asm__ __volatile__( "outw %w0,%w1" : : "a" (value), "d" (port) );
+}
+
+static __inline__ void outl( DWORD value, WORD port )
+{
+    __asm__ __volatile__( "outl %0,%w1" : : "a" (value), "d" (port) );
+}
+
+#endif  /* DIRECT_IO_ACCESS */
 
 void IO_port_init()
 {
-#ifdef linux
+#ifdef DIRECT_IO_ACCESS
 	char temp[1024];
 
-	memset(port_permissions, 0, sizeof(port_permissions));
-	do_direct_port_access = 0;
-
 	/* Can we do that? */
 	if (!iopl(3)) {
 		iopl(0);
 
 		PROFILE_GetWineIniString( "ports", "read", "*",
 					 temp, sizeof(temp) );
-		do_IO_port_init_read_or_write(temp, 1);
+		do_IO_port_init_read_or_write(temp, IO_READ);
 		PROFILE_GetWineIniString( "ports", "write", "*",
 					 temp, sizeof(temp) );
-		do_IO_port_init_read_or_write(temp, 2);
+		do_IO_port_init_read_or_write(temp, IO_WRITE);
 	}
-
-
-#endif
+#endif  /* DIRECT_IO_ACCESS */
 }
 
+
 /**********************************************************************
  *	    IO_inport
  */
@@ -160,43 +196,50 @@
     DWORD res = 0;
     BYTE b;    
 
-#ifdef linux    
-    if (do_direct_port_access) iopl(3);
+#ifdef DIRECT_IO_ACCESS    
+    if (do_direct_port_access)
+    {
+        /* Make sure we have access to the whole range */
+        int i;
+        for (i = 0; i < count; i++)
+            if (!(port_permissions[port+i] & IO_READ)) break;
+        if (i == count)
+        {
+            iopl(3);
+            switch(count)
+            {
+                case 1: res = inb( port ); break;
+                case 2: res = inw( port ); break;
+                case 4: res = inl( port ); break;
+                default:
+                    fprintf( stderr, "IO_inport: invalid count %d\n", count);
+            }
+            iopl(0);
+            return res;
+        }
+    }
 #endif
 
     dprintf_int(stddeb, "IO: %d bytes from port 0x%02x ", count, port );
 
     while (count-- > 0)
     {
-#ifdef linux
-	    if(port_permissions[port] & 1) {		    
-		    b = inb(port);
-	    } else 
-#endif
-	    {
-		    switch (port)
-		    {
-		    case 0x70:
-			    b = cmosaddress;
-			    break;
-		    case 0x71:
-			    b = cmosimage[cmosaddress & 0x3f];
-			    break;
-		    default:
-			    fprintf( stderr, 
-				    "Direct I/O read attempted "
-				    "from port %x\n", port);
-			    b = 0xff;
-			    break;
-		    }
-	    }
-
-	    port++;
-	    res = (res << 8) | b;
+        switch (port)
+        {
+        case 0x70:
+            b = cmosaddress;
+            break;
+        case 0x71:
+            b = cmosimage[cmosaddress & 0x3f];
+            break;
+        default:
+            fprintf( stderr, "Direct I/O read attempted from port %x\n", port);
+            b = 0xff;
+            break;
+        }
+        port++;
+        res = (res << 8) | b;
     }
-#ifdef linux
-    if (do_direct_port_access) iopl(0);
-#endif
     dprintf_int(stddeb, "( 0x%lx )\n", res );
     return res;
 }
@@ -212,37 +255,47 @@
     dprintf_int( stddeb, "IO: 0x%lx (%d bytes) to port 0x%02x\n",
                  value, count, port );
 
-#ifdef linux
-    if (do_direct_port_access) iopl(3);
+#ifdef DIRECT_IO_ACCESS
+    if (do_direct_port_access)
+    {
+        /* Make sure we have access to the whole range */
+        int i;
+        for (i = 0; i < count; i++)
+            if (!(port_permissions[port+i] & IO_WRITE)) break;
+        if (i == count)
+        {
+            iopl(3);
+            switch(count)
+            {
+                case 1: outb( LOBYTE(value), port ); break;
+                case 2: outw( LOWORD(value), port ); break;
+                case 4: outl( value, port ); break;
+                default:
+                    fprintf( stderr, "IO_outport: invalid count %d\n", count);
+            }
+            iopl(0);
+            return;
+        }
+    }
 #endif
 
     while (count-- > 0)
     {
         b = value & 0xff;
         value >>= 8;
-#ifdef linux
-	if (port_permissions[port] & 2) {
-		outb(b, port);
-	} else 
-#endif
-	{
-		switch (port)
-		{
-		case 0x70:
-			cmosaddress = b & 0x7f;
-			break;
-		case 0x71:
-			cmosimage[cmosaddress & 0x3f] = b;
-			break;
-		default:
-			fprintf( stderr, "Direct I/O write attempted "
-				"to port %x\n", port );
-			break;
-		}
-	}
+        switch (port)
+        {
+        case 0x70:
+            cmosaddress = b & 0x7f;
+            break;
+        case 0x71:
+            cmosimage[cmosaddress & 0x3f] = b;
+            break;
+        default:
+            fprintf( stderr, "Direct I/O write attempted "
+                     "to port %x\n", port );
+            break;
+        }
 	port++;
     }
-#ifdef linux
-    if (do_direct_port_access) iopl(0);
-#endif
 }
diff --git a/multimedia/joystick.c b/multimedia/joystick.c
index 8bc7deb..4e643e2 100644
--- a/multimedia/joystick.c
+++ b/multimedia/joystick.c
@@ -1,7 +1,7 @@
 /*
- * MMSYTEM functions
+ * Joystick functions
  *
- * Copyright 1993 Martin Ayotte
+ * Copyright 1997 Andreas Mohr
  */
 
 #include <unistd.h>
@@ -18,13 +18,113 @@
 #include "stddebug.h"
 #include "debug.h"
 
+static int count_use[4] = {0, 0, 0, 0};
+static int dev_stat;
+static int joy_nr_open = 0;
+static BOOL16 JoyCaptured = FALSE;
+static HWND16 CaptureWnd[2] = {0, 0};
+static int joy_dev[2] = {-1, -1};
+static JOYINFO JoyCapData[2];
+static unsigned int joy_threshold[2] = {0, 0};
+
+struct js_status
+{
+    int buttons;
+    int x;
+    int y;
+};
+
+
+/**************************************************************************
+ *                              JoyOpenDriver           [internal]
+ */
+BOOL16 JoyOpenDriver(WORD wID)
+{
+	char dev_name[] = "/dev/jsx";
+
+	if (joy_dev[wID] >= 0) return TRUE;
+        dev_name[strlen(dev_name)-1]=(char) wID+0x30;
+        if ((joy_dev[wID] = open(dev_name, O_RDONLY)) >= 0) {
+		joy_nr_open++;
+		return TRUE;
+	}
+	else return FALSE;
+}
+
+/**************************************************************************
+ *                              JoyCloseDriver           [internal]
+ */
+void JoyCloseDriver(WORD wID)
+{
+	if (joy_dev[wID] >= 0) {
+		close(joy_dev[wID]);
+		joy_dev[wID] = -1;
+		joy_nr_open--;
+	}
+}
+
+/**************************************************************************
+ *                              JoySendMessages           [internal]
+ */
+void JoySendMessages(void)
+{
+	int joy;
+        struct js_status js;
+
+	if (joy_nr_open)
+	for (joy=0; joy < 4; joy++) 
+	if (joy_dev[joy] >= 0) {
+		if (count_use[joy] > 250) {
+			JoyCloseDriver(joy);
+			count_use[joy] = 0;
+		}
+		count_use[joy]++;
+	}
+	else return;
+        if (JoyCaptured == FALSE) return;
+	dprintf_mmsys(stddeb, "JoySendMessages()\n");
+        for (joy=0; joy < 4; joy++) {
+		if (JoyOpenDriver(joy) == FALSE) continue;
+                dev_stat = read(joy_dev[joy], &js, sizeof(js));
+                if (dev_stat == sizeof(js)) {
+                        js.x = js.x*37;
+                        js.y = js.y*37;
+                        if ((JoyCapData[joy].wXpos != js.x) || (JoyCapData[joy].wYpos != js.y)) {
+                                SendMessage32A(CaptureWnd[joy], MM_JOY1MOVE + joy, js.buttons, MAKELONG(js.x, js.y));
+                                JoyCapData[joy].wXpos = js.x;
+                                JoyCapData[joy].wYpos = js.y;
+                        }
+                        if (JoyCapData[joy].wButtons != js.buttons) {
+				unsigned int ButtonChanged = (WORD)(JoyCapData[joy].wButtons ^ js.buttons)<<8;
+                                if (JoyCapData[joy].wButtons < js.buttons)
+                                SendMessage32A(CaptureWnd[joy], MM_JOY1BUTTONDOWN + joy, ButtonChanged, MAKELONG(js.x, js.y));
+				else
+                                if (JoyCapData[joy].wButtons > js.buttons)
+                                SendMessage32A(CaptureWnd[joy], MM_JOY1BUTTONUP
++ joy, ButtonChanged, MAKELONG(js.x, js.y));
+                                JoyCapData[joy].wButtons = js.buttons;
+                        }
+                }
+        }
+}
+
 /**************************************************************************
  * 				JoyGetNumDevs		[MMSYSTEM.101]
  */
 WORD JoyGetNumDevs(void)
 {
-    fprintf(stdnimp, "EMPTY STUB !!! JoyGetNumDevs();\n");
-    return 0;
+int joy;
+WORD joy_cnt = 0;
+
+    dprintf_mmsys(stddeb, "JoyGetNumDevs: ");
+    for (joy=0; joy<4; joy++)
+	if (JoyOpenDriver(joy) == TRUE) {		
+		JoyCloseDriver(joy);
+		joy_cnt++;
+	}
+    dprintf_mmsys(stddeb, "returning %d\n", joy_cnt);
+    if (!joy_cnt) fprintf(stderr, "No joystick found - perhaps get joystick-0.8.0.tar.gz and load it as module or use Linux >= 2.1.45 to be able to use joysticks.\n");
+    return joy_cnt;
 }
 
 /**************************************************************************
@@ -32,8 +132,27 @@
  */
 WORD JoyGetDevCaps(WORD wID, LPJOYCAPS lpCaps, WORD wSize)
 {
-    fprintf(stdnimp, "EMPTY STUB !!! JoyGetDevCaps(%04X, %p, %d);\n",
-	    wID, lpCaps, wSize);
+    dprintf_mmsys(stderr, "JoyGetDevCaps(%04X, %p, %d);\n",
+            wID, lpCaps, wSize);
+    if (wSize != sizeof(*lpCaps)) return JOYERR_PARMS; /* FIXME: should we really return this error value ? */
+    if (JoyOpenDriver(wID) == TRUE) {
+        lpCaps->wMid = MM_MICROSOFT;
+        lpCaps->wPid = MM_PC_JOYSTICK;
+        strcpy(lpCaps->szPname, "WineJoy\0"); /* joystick product name */
+        lpCaps->wXmin = 0; /* FIXME */
+        lpCaps->wXmax = 0xffff;
+        lpCaps->wYmin = 0;
+        lpCaps->wYmax = 0xffff;
+        lpCaps->wZmin = 0;
+        lpCaps->wZmax = 0xffff;
+        lpCaps->wNumButtons = 2;
+        lpCaps->wPeriodMin = 0;
+        lpCaps->wPeriodMax = 50; /* FIXME end */
+
+	JoyCloseDriver(wID);
+        return JOYERR_NOERROR;
+    }
+    else
     return MMSYSERR_NODRIVER;
 }
 
@@ -42,8 +161,24 @@
  */
 WORD JoyGetPos(WORD wID, LPJOYINFO lpInfo)
 {
-    fprintf(stdnimp, "EMPTY STUB !!! JoyGetPos(%04X, %p);\n", wID, lpInfo);
-    return MMSYSERR_NODRIVER;
+        struct js_status js;
+
+        dprintf_mmsys(stderr, "JoyGetPos(%04X, %p):", wID, lpInfo);
+        if (JoyOpenDriver(wID) == FALSE) return MMSYSERR_NODRIVER;
+	dev_stat = read(joy_dev[wID], &js, sizeof(js));
+	if (dev_stat != sizeof(js)) {
+		JoyCloseDriver(wID);
+		return JOYERR_UNPLUGGED; /* FIXME: perhaps wrong, but what should I return else ? */
+	}
+	count_use[wID] = 0;
+	js.x = js.x*37;
+	js.y = js.y*37;
+	lpInfo->wXpos = js.x;   /* FIXME: perhaps multiply it somehow ? */
+	lpInfo->wYpos = js.y;
+	lpInfo->wZpos = 0; /* FIXME: Don't know what to do with this value as joystick driver doesn't provide a Z value */
+	lpInfo->wButtons = js.buttons;
+	dprintf_mmsys(stderr, "x: %d, y: %d, buttons: %d\n", js.x, js.y, js.buttons);
+	return JOYERR_NOERROR;
 }
 
 /**************************************************************************
@@ -51,8 +186,10 @@
  */
 WORD JoyGetThreshold(WORD wID, LPWORD lpThreshold)
 {
-    fprintf(stdnimp, "EMPTY STUB !!! JoyGetThreshold(%04X, %p);\n", wID, lpThreshold);
-    return MMSYSERR_NODRIVER;
+    dprintf_mmsys(stderr, "JoyGetThreshold(%04X, %p);\n", wID, lpThreshold);
+    if (wID > 3) return JOYERR_PARMS;
+    *lpThreshold = joy_threshold[wID];
+    return JOYERR_NOERROR;
 }
 
 /**************************************************************************
@@ -60,8 +197,12 @@
  */
 WORD JoyReleaseCapture(WORD wID)
 {
-    fprintf(stdnimp, "EMPTY STUB !!! JoyReleaseCapture(%04X);\n", wID);
-    return MMSYSERR_NODRIVER;
+    dprintf_mmsys(stderr, "JoyReleaseCapture(%04X);\n", wID);
+    JoyCaptured = FALSE;
+    JoyCloseDriver(wID);
+    joy_dev[wID] = -1;
+    CaptureWnd[wID] = 0;
+    return JOYERR_NOERROR;
 }
 
 /**************************************************************************
@@ -69,9 +210,18 @@
  */
 WORD JoySetCapture(HWND16 hWnd, WORD wID, WORD wPeriod, BOOL16 bChanged)
 {
-    fprintf(stdnimp, "EMPTY STUB !!! JoySetCapture(%04X, %04X, %d, %d);\n",
+
+    dprintf_mmsys(stderr, "JoySetCapture(%04X, %04X, %d, %d);\n",
 	    hWnd, wID, wPeriod, bChanged);
-    return MMSYSERR_NODRIVER;
+
+    if (!CaptureWnd[wID]) {
+	if (JoyOpenDriver(wID) == FALSE) return MMSYSERR_NODRIVER;
+	JoyCaptured = TRUE;
+	CaptureWnd[wID] = hWnd;
+	return JOYERR_NOERROR;
+    }
+    else
+    return JOYERR_NOCANDO; /* FIXME: what should be returned ? */
 }
 
 /**************************************************************************
@@ -79,8 +229,11 @@
  */
 WORD JoySetThreshold(WORD wID, WORD wThreshold)
 {
-    fprintf(stdnimp, "EMPTY STUB !!! JoySetThreshold(%04X, %d);\n", wID, wThreshold);
-    return MMSYSERR_NODRIVER;
+    dprintf_mmsys(stderr, "JoySetThreshold(%04X, %d);\n", wID, wThreshold);
+
+    if (wID > 3) return JOYERR_PARMS;
+    joy_threshold[wID] = wThreshold;
+    return JOYERR_NOERROR;
 }
 
 /**************************************************************************
@@ -88,6 +241,6 @@
  */
 WORD JoySetCalibration(WORD wID)
 {
-    fprintf(stdnimp, "EMPTY STUB !!! JoySetCalibration(%04X);\n", wID);
-    return MMSYSERR_NODRIVER;
+    fprintf(stderr, "EMPTY STUB !!! JoySetCalibration(%04X);\n", wID);
+    return JOYERR_NOCANDO;
 }
diff --git a/multimedia/mmsystem.c b/multimedia/mmsystem.c
index 42eace9..b4f6cf9 100644
--- a/multimedia/mmsystem.c
+++ b/multimedia/mmsystem.c
@@ -293,7 +293,8 @@
 			return FALSE;
 		case DCB_FUNCTION:
 			dprintf_mmsys(stddeb, "DriverCallback() // CALLBACK_FUNCTION !\n");
-			CallTo16_word_wwlll((FARPROC16)dwCallBack,hDev,wMsg,dwUser,dwParam1,dwParam2);
+			CallDriverCallback( (FARPROC16)dwCallBack, hDev, wMsg,
+                                            dwUser, dwParam1, dwParam2 );
 			break;
 		}
 	return TRUE;
diff --git a/objects/color.c b/objects/color.c
index 074359d..7d5c0bd 100644
--- a/objects/color.c
+++ b/objects/color.c
@@ -194,7 +194,9 @@
   int red, no_r, inc_r;
   int green, no_g, inc_g; 
   int blue, no_b, inc_b;
-
+  
+  if (cSpace.size <= NB_RESERVED_COLORS)
+  	return;
   while (i*i*i < (cSpace.size - NB_RESERVED_COLORS)) i++;
   no_r = no_g = no_b = --i;
   if ((no_r * (no_g+1) * no_b) < (cSpace.size - NB_RESERVED_COLORS)) no_g++;
@@ -623,13 +625,29 @@
 
     case TrueColor:
 	cSpace.flags |= COLOR_VIRTUAL;
-    case StaticColor:
+    case StaticColor: {
+    	int *depths,nrofdepths;
+	/* FIXME: hack to detect XFree32 XF_VGA16 ... We just have
+	 * depths 1 and 4
+	 */
+	depths=XListDepths(display,DefaultScreen(display),&nrofdepths);
+	if ((nrofdepths==2) && ((depths[0]==4) || depths[1]==4)) {
+	    cSpace.monoPlane = 1;
+	    for( white = cSpace.size - 1; !(white & 1); white >>= 1 )
+	        cSpace.monoPlane++;
+    	    cSpace.flags = (white & mask) ? COLOR_WHITESET : 0;
+	    cSpace.colorMap = DefaultColormapOfScreen( screen );
+	    XFree(depths);
+	    break;
+	}
+	XFree(depths);
         cSpace.colorMap = DefaultColormapOfScreen( screen );
         cSpace.flags |= COLOR_FIXED;
         COLOR_Computeshifts(visual->red_mask, &COLOR_Redshift, &COLOR_Redmax);
         COLOR_Computeshifts(visual->green_mask, &COLOR_Greenshift, &COLOR_Greenmax);
         COLOR_Computeshifts(visual->blue_mask, &COLOR_Blueshift, &COLOR_Bluemax);
-	break;	
+	break;
+    }
     }
 
     dprintf_palette(stddeb," visual class %i (%i)\n", 
diff --git a/programs/progman/ChangeLog b/programs/progman/ChangeLog
index 1a7c072..2d7bd4e 100644
--- a/programs/progman/ChangeLog
+++ b/programs/progman/ChangeLog
@@ -1,3 +1,8 @@
+Mon Jul 28 18:28:14 1997  Peter Schlaile <up9n@rz.uni-karlsruhe.de>
+
+	* [grpfile.c]
+	Added checksum calculation [UNTESTED!].
+
 Fri Jul 4 12:00:00 1997  Henrik Olsen <Henrik.Olsen@iaeste.dk>
 
 	* [Da.rc] (new)
diff --git a/programs/progman/grpfile.c b/programs/progman/grpfile.c
index 44f9f04..bb4a5e5 100644
--- a/programs/progman/grpfile.c
+++ b/programs/progman/grpfile.c
@@ -2,10 +2,12 @@
  * Program Manager
  *
  * Copyright 1996 Ulrich Schmid
+ *           1997 Peter Schlaile
  */
 
 #include "windows.h"
 #include "progman.h"
+#include "mmsystem.h"
 
 #define MALLOCHUNK 1000
 
@@ -370,11 +372,11 @@
     }
 
   {
-    /* Warn about the incompatibility */
+    /* Warn about the (possible) incompatibility */
     CHAR msg[MAX_PATHNAME_LEN + 200];
     wsprintf(msg,
 	     "Group files written by this DRAFT Program Manager "
-	     "cannot be read by the Microsoft Program Manager!!\n"
+	     "possibly cannot be read by the Microsoft Program Manager!!\n"
 	     "Are you sure to write %s?", szPath);
     if (IDOK != MessageBox(Globals.hMainWnd, msg, "WARNING",
 			   MB_OKCANCEL | MB_DEFBUTTON2)) return FALSE;
@@ -425,6 +427,72 @@
   *Icons += sizeXor;
 }
 
+/***********************************************************************/
+UINT16 GRPFILE_checksum;
+BOOL GRPFILE_checksum_half_word;
+BYTE GRPFILE_checksum_last_byte;
+/***********************************************************************
+ *
+ *           GRPFILE_InitChecksum
+ */
+
+static void GRPFILE_InitChecksum()
+{
+	GRPFILE_checksum = 0;
+	GRPFILE_checksum_half_word = 0;
+}
+
+/***********************************************************************
+ *
+ *           GRPFILE_GetChecksum
+ */
+
+static UINT16 GRPFILE_GetChecksum()
+{
+	return GRPFILE_checksum;
+}
+
+/***********************************************************************
+ *
+ *           GRPFILE_WriteWithChecksum
+ * 
+ * Looks crazier than it is:
+ * 
+ * chksum = 0;
+ * chksum = cksum - 1. word;
+ * chksum = cksum - 2. word;
+ * ...
+ * 
+ * if (filelen is even)
+ *      great I'm finished
+ * else
+ *      ignore last byte
+ */
+
+static UINT GRPFILE_WriteWithChecksum(HFILE file, LPCSTR str, UINT size)
+{
+	UINT i;
+	if (GRPFILE_checksum_half_word) {
+		GRPFILE_checksum -= GRPFILE_checksum_last_byte;	
+	}
+	for (i=0; i < size; i++) {
+		if (GRPFILE_checksum_half_word) {
+			GRPFILE_checksum -= str[i] << 8;
+		} else {
+			GRPFILE_checksum -= str[i];
+		}
+		GRPFILE_checksum_half_word ^= 1;
+	}
+	
+	if (GRPFILE_checksum_half_word) {
+		GRPFILE_checksum_last_byte = str[size-1];
+		GRPFILE_checksum += GRPFILE_checksum_last_byte;
+	}
+	
+	return _lwrite(file, str, size);
+}
+
+
 /***********************************************************************
  *
  *           GRPFILE_DoWriteGroupFile
@@ -439,6 +507,10 @@
   BOOL   need_extension;
   LPCSTR lpszTitle = LocalLock(group->hName);
 
+  UINT16 checksum;
+	
+  GRPFILE_InitChecksum();
+	
   /* Calculate offsets */
   NumProg = 0;
   Icons   = 0;
@@ -467,14 +539,10 @@
   /* Header */
   buffer[0] = 'P';
   buffer[1] = 'M';
-#if 0
-  buffer[2] = 'C'; /* Original magic number */
+  buffer[2] = 'C'; 
   buffer[3] = 'C';
-#else
-  buffer[2] = 'X'; /* Modified magic number: no checksum */
-  buffer[3] = 'X';
-#endif
-  PUT_SHORT(buffer,  4, 0); /* Checksum ignored */
+	
+  PUT_SHORT(buffer,  4, 0); /* Checksum zero for now, written later */
   PUT_SHORT(buffer,  6, Extension);
   /* Update group->nCmdShow */
   if (IsIconic(group->hWnd))      nCmdShow = SW_SHOWMINIMIZED;
@@ -494,7 +562,7 @@
   PUT_SHORT(buffer, 30, 0x0000); /* unknown */
   PUT_SHORT(buffer, 32, NumProg);
 
-  if (HFILE_ERROR == _lwrite(file, buffer, 34)) return FALSE;
+  if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 34)) return FALSE;
 
   /* Program table */
   CurrProg = Progs;
@@ -505,14 +573,16 @@
       PROGRAM *program = LocalLock(hProgram);
 
       PUT_SHORT(buffer, 0, CurrProg);
-      if (HFILE_ERROR == _lwrite(file, buffer, 2)) return FALSE;
+      if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 2)) 
+	      return FALSE;
 
       GRPFILE_CalculateSizes(program, &CurrProg, &CurrIcon);
       hProgram = program->hNext;
     }
 
   /* Title */
-  if (HFILE_ERROR == _lwrite(file, lpszTitle, lstrlen(lpszTitle) + 1))
+  if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, lpszTitle, 
+					       lstrlen(lpszTitle) + 1))
     return FALSE;
 
   /* Program entries */
@@ -545,10 +615,10 @@
       ptr += lstrlen(CmdLine) + 1;
       PUT_SHORT(buffer, 22, ptr);
 
-      if (HFILE_ERROR == _lwrite(file, buffer, 24) ||
-	  HFILE_ERROR == _lwrite(file, Name, lstrlen(Name) + 1) ||
-	  HFILE_ERROR == _lwrite(file, CmdLine, lstrlen(CmdLine) + 1) ||
-	  HFILE_ERROR == _lwrite(file, IconFile, lstrlen(IconFile) + 1))
+      if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 24) ||
+	  HFILE_ERROR == GRPFILE_WriteWithChecksum(file, Name, lstrlen(Name) + 1) ||
+	  HFILE_ERROR == GRPFILE_WriteWithChecksum(file, CmdLine, lstrlen(CmdLine) + 1) ||
+	  HFILE_ERROR == GRPFILE_WriteWithChecksum(file, IconFile, lstrlen(IconFile) + 1))
 	return FALSE;
 
       GRPFILE_CalculateSizes(program, &CurrProg, &CurrIcon);
@@ -574,9 +644,9 @@
       buffer[10] = iconinfo->bPlanes;
       buffer[11] = iconinfo->bBitsPerPixel;
 
-      if (HFILE_ERROR == _lwrite(file, buffer, 12) ||
-	  HFILE_ERROR == _lwrite(file, AndBits, sizeAnd) ||
-	  HFILE_ERROR == _lwrite(file, XorBits, sizeXor)) return FALSE;
+      if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 12) ||
+	  HFILE_ERROR == GRPFILE_WriteWithChecksum(file, AndBits, sizeAnd) ||
+	  HFILE_ERROR == GRPFILE_WriteWithChecksum(file, XorBits, sizeXor)) return FALSE;
 
       hProgram = program->hNext;
     }
@@ -589,7 +659,8 @@
       PUT_SHORT(buffer, 4, 0x000a);
       buffer[6] = 'P', buffer[7] = 'M';
       buffer[8] = 'C', buffer[9] = 'C';
-      if (HFILE_ERROR == _lwrite(file, buffer, 10)) return FALSE;
+      if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 10)) 
+	      return FALSE;
 
       seqnum = 0;
       hProgram = group->hPrograms;
@@ -604,8 +675,8 @@
 	      PUT_SHORT(buffer, 0, 0x8101);
 	      PUT_SHORT(buffer, 2, seqnum);
 	      PUT_SHORT(buffer, 4, 7 + lstrlen(lpszWorkDir));
-	      if (HFILE_ERROR == _lwrite(file, buffer, 6) ||
-		  HFILE_ERROR == _lwrite(file, lpszWorkDir, lstrlen(lpszWorkDir) + 1))
+	      if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 6) ||
+		  HFILE_ERROR == GRPFILE_WriteWithChecksum(file, lpszWorkDir, lstrlen(lpszWorkDir) + 1))
 		return FALSE;
 	    }
 
@@ -616,7 +687,7 @@
 	      PUT_SHORT(buffer, 2, seqnum);
 	      PUT_SHORT(buffer, 4, 8);
 	      PUT_SHORT(buffer, 6, program->nHotKey);
-	      if (HFILE_ERROR == _lwrite(file, buffer, 8)) return FALSE;
+	      if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 8)) return FALSE;
 	    }
 
 	  /* Show command */
@@ -626,7 +697,7 @@
 	      PUT_SHORT(buffer, 2, seqnum);
 	      PUT_SHORT(buffer, 4, 8);
 	      PUT_SHORT(buffer, 6, program->nCmdShow);
-	      if (HFILE_ERROR == _lwrite(file, buffer, 8)) return FALSE;
+	      if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 8)) return FALSE;
 	    }
 
 	  seqnum++;
@@ -637,9 +708,14 @@
       PUT_SHORT(buffer, 0, 0xffff);
       PUT_SHORT(buffer, 2, 0xffff);
       PUT_SHORT(buffer, 4, 0x0000);
-      if (HFILE_ERROR == _lwrite(file, buffer, 6)) return FALSE;
+      if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 6)) return FALSE;
     }
 
+  checksum = GRPFILE_GetChecksum();
+  _llseek(file, 4, SEEK_SET);
+  PUT_SHORT(buffer, 0, checksum);
+  _lwrite(file, buffer, 2);
+
   return TRUE;
 }
 
diff --git a/scheduler/process.c b/scheduler/process.c
index 6e9db29..05fa39d 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -9,9 +9,11 @@
 #include <stdio.h>
 #include <string.h>
 #include "process.h"
+#include "module.h"
 #include "file.h"
 #include "heap.h"
 #include "task.h"
+#include "ldt.h"
 #include "thread.h"
 #include "winerror.h"
 
@@ -789,107 +791,6 @@
 }
 
 /***********************************************************************
- *           _KERNEL32_18    (KERNEL32.18,Win95)
- * 'Of course you cannot directly access Windows internal structures'
- */
-extern THDB *pCurrentThread;
-DWORD
-_KERNEL32_18(DWORD processid,DWORD action) {
-	PDB32	*process;
-	TDB	*pTask;
-
-	action+=56;
-	fprintf(stderr,"_KERNEL32_18(%ld,%ld+0x38)\n",processid,action);
-	if (action>56)
-		return 0;
-	if (!processid) {
-		process=pCurrentProcess;
-		/* check if valid process */
-	} else
-		process=(PDB32*)pCurrentProcess; /* decrypt too, if needed */
-	switch (action) {
-	case 0:	/* return app compat flags */
-		pTask = (TDB*)GlobalLock16(process->task);
-		if (!pTask)
-			return 0;
-		return pTask->compat_flags;
-	case 4:	/* returns offset 0xb8 of process struct... dunno what it is */
-		return 0;
-	case 8:	/* return hinstance16 */
-		pTask = (TDB*)GlobalLock16(process->task);
-		if (!pTask)
-			return 0;
-		return pTask->hInstance;
-	case 12:/* return expected windows version */
-		pTask = (TDB*)GlobalLock16(process->task);
-		if (!pTask)
-			return 0;
-		return pTask->version;
-	case 16:/* return uncrypted pointer to current thread */
-		return (DWORD)pCurrentThread;
-	case 20:/* return uncrypted pointer to process */
-		return (DWORD)process;
-	case 24:/* return stdoutput handle from startupinfo */
-		return (DWORD)(process->env_db->startup_info->hStdOutput);
-	case 28:/* return stdinput handle from startupinfo */
-		return (DWORD)(process->env_db->startup_info->hStdInput);
-	case 32:/* get showwindow flag from startupinfo */
-		return (DWORD)(process->env_db->startup_info->wShowWindow);
-	case 36:{/* return startup x and y sizes */
-		LPSTARTUPINFO32A si = process->env_db->startup_info;
-		DWORD x,y;
-
-		x=si->dwXSize;if (x==0x80000000) x=0x8000;
-		y=si->dwYSize;if (y==0x80000000) y=0x8000;
-		return (y<<16)+x;
-	}
-	case 40:{/* return startup x and y */
-		LPSTARTUPINFO32A si = process->env_db->startup_info;
-		DWORD x,y;
-
-		x=si->dwX;if (x==0x80000000) x=0x8000;
-		y=si->dwY;if (y==0x80000000) y=0x8000;
-		return (y<<16)+x;
-	}
-	case 44:/* return startup flags */
-		return process->env_db->startup_info->dwFlags;
-	case 48:/* return uncrypted pointer to parent process (if any) */
-		return (DWORD)process->parent;
-	case 52:/* return process flags */
-		return process->flags;
-	case 56:/* unexplored */
-		return 0;
-	default:
-		fprintf(stderr,"_KERNEL32_18:unknown offset (%ld)\n",action);
-		return 0;
-	}
-	/* shouldn't come here */
-}
-
-VOID /* FIXME */
-_KERNEL32_52(DWORD arg1,CONTEXT *regs) {
-	SEGPTR *str = SEGPTR_STRDUP("ThkBuf");
-
-	fprintf(stderr,"_KERNE32_52(arg1=%08lx,%08lx)\n",arg1,EDI_reg(regs));
-
-	EAX_reg(regs) = GetProcAddress16(EDI_reg(regs),SEGPTR_GET(str));
-	fprintf(stderr,"	GetProcAddress16(\"ThkBuf\") returns %08lx\n",
-			EAX_reg(regs)
-	);
-	SEGPTR_FREE(str);
-}
-
-/***********************************************************************
- *           GetPWinLock    (KERNEL32) FIXME
- */
-VOID
-GetPWinLock(CRITICAL_SECTION **lock) {
-	static CRITICAL_SECTION plock;
-	fprintf(stderr,"GetPWinlock(%p)\n",lock);
-	*lock = &plock;
-}
-
-/***********************************************************************
  *           GetProcessVersion    (KERNEL32)
  */
 DWORD
diff --git a/scheduler/thread.c b/scheduler/thread.c
index ad4ff27..22f78f6 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -10,6 +10,7 @@
 #include "winerror.h"
 #include "heap.h"
 #include "selectors.h"
+#include "miscemu.h"
 #include "winnt.h"
 
 THDB *pCurrentThread = NULL;
diff --git a/tools/build-spec.txt b/tools/build-spec.txt
index 64917f2..8d73148 100644
--- a/tools/build-spec.txt
+++ b/tools/build-spec.txt
@@ -1,5 +1,6 @@
 name	NAME
 type    win16|win32
+[file   WINFILENAME]
 [base   ORDINAL]
 [heap   SIZE]
 
@@ -25,8 +26,12 @@
 declarations are optional, but the default handler will print an error
 message.  "base" gives the offset of the first ordinal; default is 0.
 "heap" is the size of the module local heap (only valid for Win16
-modules); default is no local heap.  Lines whose first character is a
-'#' will be ignored as comments.
+modules); default is no local heap. "file" gives the name of the
+Windows file that is replaced by the builtin. <name>.DLL is assumed if
+none is given. (This is important for kernel, which lives in the
+Windows file KRNL386.EXE).  Lines whose first character is a '#' will
+be ignored as comments.
+
 
 Variable ordinals:
 ==================
diff --git a/tools/build.c b/tools/build.c
index 6d02895..6ab1a55 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -125,7 +125,8 @@
 static ORDDEF OrdinalDefinitions[MAX_ORDINALS];
 
 static SPEC_TYPE SpecType = SPEC_INVALID;
-char DLLName[80];
+static char DLLName[80];
+static char DLLFileName[80];
 int Limit = 0;
 int Base = 0;
 int DLLHeapSize = 0;
@@ -573,6 +574,12 @@
 	{
 	    strcpy(DLLName, GetToken());
 	    strupper(DLLName);
+            if (!DLLFileName[0]) sprintf( DLLFileName, "%s.DLL", DLLName );
+	}
+	else if (strcmp(token, "file") == 0)
+	{
+	    strcpy(DLLFileName, GetToken());
+	    strupper(DLLFileName);
 	}
         else if (strcmp(token, "type") == 0)
         {
@@ -743,8 +750,8 @@
     pModule->fileinfo = (int)pFileInfo - (int)pModule;
     memset( pFileInfo, 0, sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) );
     pFileInfo->cBytes = sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName)
-                        + strlen(DLLName) + 4;
-    sprintf( pFileInfo->szPathName, "%s.DLL", DLLName );
+                        + strlen(DLLFileName);
+    strcpy( pFileInfo->szPathName, DLLFileName );
     pstr = (char *)pFileInfo + pFileInfo->cBytes + 1;
         
       /* Segment table */
@@ -928,8 +935,8 @@
     pModule->fileinfo = (int)pFileInfo - (int)pModule;
     memset( pFileInfo, 0, sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) );
     pFileInfo->cBytes = sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName)
-                        + strlen(DLLName) + 4;
-    sprintf( pFileInfo->szPathName, "%s.DLL", DLLName );
+                        + strlen(DLLFileName);
+    strcpy( pFileInfo->szPathName, DLLFileName );
     pstr = (char *)pFileInfo + pFileInfo->cBytes + 1;
         
       /* Segment table */
diff --git a/win32/Makefile.in b/win32/Makefile.in
index 0a7891a..834ad62 100644
--- a/win32/Makefile.in
+++ b/win32/Makefile.in
@@ -17,6 +17,7 @@
 	init.c \
 	k32obj.c \
 	newfns.c \
+	ordinals.c \
 	process.c \
 	security.c \
 	string32.c \
diff --git a/win32/ordinals.c b/win32/ordinals.c
new file mode 100644
index 0000000..a617b0c
--- /dev/null
+++ b/win32/ordinals.c
@@ -0,0 +1,430 @@
+/*
+ * Win32 ordinal only exported functions
+ *
+ * Copyright 1997 Marcus Meissner
+ */
+
+#include <stdio.h>
+#include "thread.h"
+#include "winerror.h"
+#include "heap.h"
+#include "selectors.h"
+#include "miscemu.h"
+#include "winnt.h"
+#include "module.h"
+#include "callback.h"
+#include "debug.h"
+#include "stddebug.h"
+
+extern THDB	*pCurrentThread;
+extern PDB32	*pCurrentProcess;
+
+/**********************************************************************
+ *           _KERNEL32_88
+ */
+DWORD
+WOW32_1(DWORD x,DWORD y) {
+    fprintf(stderr,"WOW32_1(0x%08lx,0x%08lx), stub!\n",x,y);
+    return 0;
+}
+
+/**********************************************************************
+ *           WOWGetVDMPointer	(KERNEL32.55)
+ * Get linear from segmented pointer. (MSDN lib)
+ */
+LPVOID
+WOWGetVDMPointer(DWORD vp,DWORD nrofbytes,BOOL32 protected) {
+    /* FIXME: add size check too */
+    fprintf(stdnimp,"WOWGetVDMPointer(%08lx,%ld,%d)\n",vp,nrofbytes,protected);
+    if (protected)
+	return PTR_SEG_TO_LIN(vp);
+    else
+	return DOSMEM_MapRealToLinear(vp);
+}
+
+/**********************************************************************
+ *           WOWGetVDMPointerFix (KERNEL32.55)
+ * Dito, but fix heapsegment (MSDN lib)
+ */
+LPVOID
+WOWGetVDMPointerFix(DWORD vp,DWORD nrofbytes,BOOL32 protected) {
+    /* FIXME: fix heapsegment */
+    fprintf(stdnimp,"WOWGetVDMPointerFix(%08lx,%ld,%d)\n",vp,nrofbytes,protected);
+    return WOWGetVDMPointer(vp,nrofbytes,protected);
+}
+
+/**********************************************************************
+ *           WOWGetVDMPointerUnFix (KERNEL32.56)
+ */
+void
+WOWGetVDMPointerUnfix(DWORD vp) {
+    fprintf(stdnimp,"WOWGetVDMPointerUnfix(%08lx), STUB\n",vp);
+    /* FIXME: unfix heapsegment */
+}
+
+
+/***********************************************************************
+ *           _KERNEL32_18    (KERNEL32.18)
+ * 'Of course you cannot directly access Windows internal structures'
+ */
+
+DWORD
+_KERNEL32_18(DWORD processid,DWORD action) {
+	PDB32	*process;
+	TDB	*pTask;
+
+	action+=56;
+	fprintf(stderr,"KERNEL32_18(%ld,%ld+0x38)\n",processid,action);
+	if (action>56)
+		return 0;
+	if (!processid) {
+		process=pCurrentProcess;
+		/* check if valid process */
+	} else
+		process=(PDB32*)pCurrentProcess; /* decrypt too, if needed */
+	switch (action) {
+	case 0:	/* return app compat flags */
+		pTask = (TDB*)GlobalLock16(process->task);
+		if (!pTask)
+			return 0;
+		return pTask->compat_flags;
+	case 4:	/* returns offset 0xb8 of process struct... dunno what it is */
+		return 0;
+	case 8:	/* return hinstance16 */
+		pTask = (TDB*)GlobalLock16(process->task);
+		if (!pTask)
+			return 0;
+		return pTask->hInstance;
+	case 12:/* return expected windows version */
+		pTask = (TDB*)GlobalLock16(process->task);
+		if (!pTask)
+			return 0;
+		return pTask->version;
+	case 16:/* return uncrypted pointer to current thread */
+		return (DWORD)pCurrentThread;
+	case 20:/* return uncrypted pointer to process */
+		return (DWORD)process;
+	case 24:/* return stdoutput handle from startupinfo */
+		return (DWORD)(process->env_db->startup_info->hStdOutput);
+	case 28:/* return stdinput handle from startupinfo */
+		return (DWORD)(process->env_db->startup_info->hStdInput);
+	case 32:/* get showwindow flag from startupinfo */
+		return (DWORD)(process->env_db->startup_info->wShowWindow);
+	case 36:{/* return startup x and y sizes */
+		LPSTARTUPINFO32A si = process->env_db->startup_info;
+		DWORD x,y;
+
+		x=si->dwXSize;if (x==0x80000000) x=0x8000;
+		y=si->dwYSize;if (y==0x80000000) y=0x8000;
+		return (y<<16)+x;
+	}
+	case 40:{/* return startup x and y */
+		LPSTARTUPINFO32A si = process->env_db->startup_info;
+		DWORD x,y;
+
+		x=si->dwX;if (x==0x80000000) x=0x8000;
+		y=si->dwY;if (y==0x80000000) y=0x8000;
+		return (y<<16)+x;
+	}
+	case 44:/* return startup flags */
+		return process->env_db->startup_info->dwFlags;
+	case 48:/* return uncrypted pointer to parent process (if any) */
+		return (DWORD)process->parent;
+	case 52:/* return process flags */
+		return process->flags;
+	case 56:/* unexplored */
+		return 0;
+	default:
+		fprintf(stderr,"_KERNEL32_18:unknown offset (%ld)\n",action);
+		return 0;
+	}
+	/* shouldn't come here */
+}
+
+/***********************************************************************
+ *           _KERNEL32_52    (KERNEL32.52)
+ * FIXME: what does it really do?
+ */
+VOID
+_KERNEL32_52(DWORD arg1,CONTEXT *regs) {
+	fprintf(stderr,"_KERNE32_52(arg1=%08lx,%08lx)\n",arg1,EDI_reg(regs));
+
+	EAX_reg(regs) = (DWORD)WIN32_GetProcAddress16(EDI_reg(regs),"ThkBuf");
+
+	fprintf(stderr,"	GetProcAddress16(\"ThkBuf\") returns %08lx\n",
+			EAX_reg(regs)
+	);
+}
+
+/***********************************************************************
+ *           GetPWinLock    (KERNEL32) FIXME
+ * get mutex? critical section for 16 bit mode?
+ */
+VOID
+GetPWinLock(CRITICAL_SECTION **lock) {
+	static CRITICAL_SECTION plock;
+	fprintf(stderr,"GetPWinlock(%p)\n",lock);
+	*lock = &plock;
+}
+
+/***********************************************************************
+ * 		_KERNEL32_43 	(KERNEL32.42)
+ * A thunkbuffer link routine 
+ * The thunkbuf looks like:
+ *
+ *	00: DWORD	length		? don't know exactly
+ *	04: SEGPTR	ptr		? where does it point to?
+ * The pointer ptr is written into the first DWORD of 'thunk'.
+ * (probably correct implemented)
+ */
+BOOL32
+_KERNEL32_43(LPDWORD thunk,LPCSTR thkbuf,DWORD len,LPCSTR dll16,LPCSTR dll32) {
+	HINSTANCE16	hmod;
+	LPDWORD		addr;
+	SEGPTR		segaddr;
+
+	fprintf(stderr,"_KERNEL32_43(%p,%s,0x%08lx,%s,%s)\n",thunk,thkbuf,len,dll16,dll32);
+
+	hmod = LoadLibrary16(dll16);
+	if (hmod<32) {
+		fprintf(stderr,"->failed to load 16bit DLL %s, error %d\n",dll16,hmod);
+		return NULL;
+	}
+	segaddr = (DWORD)WIN32_GetProcAddress16(hmod,(LPSTR)thkbuf);
+	if (!segaddr) {
+		fprintf(stderr,"->no %s exported from %s!\n",thkbuf,dll16);
+		return NULL;
+	}
+	addr = (LPDWORD)PTR_SEG_TO_LIN(segaddr);
+	if (addr[0] != len) {
+		fprintf(stderr,"->thkbuf length mismatch? %ld vs %ld\n",len,addr[0]);
+		return NULL;
+	}
+	if (!addr[1])
+		return 0;
+	*(DWORD*)thunk = addr[1];
+	return addr[1];
+}
+
+/***********************************************************************
+ * 		_KERNEL32_45 	(KERNEL32.44)
+ * FIXME: not sure what it does
+ */
+VOID
+_KERNEL32_45(DWORD x,CONTEXT *context) {
+	fprintf(stderr,"_KERNEL32_45(0x%08lx,%%eax=0x%08lx,%%cx=0x%04lx,%%edx=0x%08lx)\n",
+		x,(DWORD)EAX_reg(context),(DWORD)CX_reg(context),(DWORD)EDX_reg(context)
+	);
+}
+
+/***********************************************************************
+ *		(KERNEL32.40)
+ * A thunk setup routine.
+ * Expects a pointer to a preinitialized thunkbuffer in the first argument
+ * looking like:
+ *	00..03:		unknown	(some pointer to the 16bit struct?)
+ *	04: EB1E		jmp +0x20
+ *
+ *	06..23:		unknown (space for replacement code, check .90)
+ *
+ *	24:>E8xxxxxxxx		call <32bitoffset xxxxxxxx>
+ *	29: 58			pop eax
+ *	2A: 2D2500xxxx		and eax,0x2500xxxx
+ *	2F: BAxxxxxxxx		mov edx,xxxxxxxx
+ *	34: 68yyyyyyyy		push KERNEL32.90
+ *	39: C3			ret
+ *
+ *	3A: EB1E		jmp +0x20
+ *	3E ... 59:	unknown (space for replacement code?)
+ *	5A: E8xxxxxxxx		call <32bitoffset xxxxxxxx>
+ *	5F: 5A			pop edx
+ *	60: 81EA25xxxxxx	sub edx, 0x25xxxxxx
+ *	66: 52			push edx
+ *	67: 68xxxxxxxx		push xxxxxxxx
+ *	6C: 68yyyyyyyy		push KERNEL32.89
+ *	71: C3			ret
+ *	72: end?
+ * This function checks if the code is there, and replaces the yyyyyyyy entries
+ * by the functionpointers.
+ * The thunkbuf looks like:
+ *
+ *	00: DWORD	length		? don't know exactly
+ *	04: SEGPTR	ptr		? where does it point to?
+ * The segpointer ptr is written into the first DWORD of 'thunk'.
+ * (probably correct implemented)
+ */
+
+LPVOID
+_KERNEL32_41(LPBYTE thunk,LPCSTR thkbuf,DWORD len,LPCSTR dll16,LPCSTR dll32) {
+	HMODULE32	hkrnl32 = WIN32_GetModuleHandleA("KERNEL32");
+	HMODULE16	hmod;
+	LPDWORD		addr,addr2;
+	DWORD		segaddr;
+
+	fprintf(stderr,"KERNEL32_41(%p,%s,%ld,%s,%s)\n",
+		thunk,thkbuf,len,dll16,dll32
+	);
+
+	/* FIXME: add checks for valid code ... */
+	/* write pointers to kernel32.89 and kernel32.90 (+ordinal base of 1) */
+	*(DWORD*)(thunk+0x35) = (DWORD)GetProcAddress32(hkrnl32,(LPSTR)91);
+	*(DWORD*)(thunk+0x6D) = (DWORD)GetProcAddress32(hkrnl32,(LPSTR)90);
+
+	
+	hmod = LoadLibrary16(dll16);
+	if (hmod<32) {
+		fprintf(stderr,"->failed to load 16bit DLL %s, error %d\n",dll16,hmod);
+		return NULL;
+	}
+	segaddr = (DWORD)WIN32_GetProcAddress16(hmod,(LPSTR)thkbuf);
+	if (!segaddr) {
+		fprintf(stderr,"->no %s exported from %s!\n",thkbuf,dll16);
+		return NULL;
+	}
+	addr = (LPDWORD)PTR_SEG_TO_LIN(segaddr);
+	if (addr[0] != len) {
+		fprintf(stderr,"->thkbuf length mismatch? %ld vs %ld\n",len,addr[0]);
+		return NULL;
+	}
+	addr2 = PTR_SEG_TO_LIN(addr[1]);
+	if (HIWORD(addr2))
+		*(DWORD*)thunk = (DWORD)addr2;
+	return addr2;
+}
+
+/***********************************************************************
+ *							(KERNEL32.33)
+ * Returns some internal value.... probably the default environment database?
+ */
+DWORD
+_KERNEL32_34() {
+	fprintf(stderr,"KERNEL32_34(), STUB returning 0\n");
+	return 0;
+}
+
+/***********************************************************************
+ *							(KERNEL32.90)
+ * Thunk priming? function
+ * Rewrites the first part of the thunk to use the QT_Thunk interface.
+ * Replaces offset 4 ... 24 by:
+ *	
+ *  33C9                    xor ecx, ecx
+ *  8A4DFC                  mov cl , [ebp-04]
+ *  8B148Dxxxxxxxx          mov edx, [4*ecx + (EAX+EDX)]
+ *  B8yyyyyyyy              mov eax, QT_Thunk
+ *  FFE0                    jmp eax
+ *  CC                      int 03
+ *  CC                      int 03
+ *  CC                      int 03
+ *  CC                      int 03
+ *  CC                      int 03
+ *  CC                      int 03
+ *  CC                      int 03
+ *  CC                      int 03
+ *  CC                      int 03
+ *  CC                      int 03
+ *  CC                      int 03
+ *  CC                      int 03
+ *  CC                      int 03
+ * and jumps to the start of that code.
+ * (ok)
+ */
+VOID
+_KERNEL32_91(CONTEXT *context) {
+	LPBYTE	x;
+
+	fprintf(stderr,"_KERNEL32_91(eax=0x%08lx,edx=0x%08lx)\n",
+		EAX_reg(context),EDX_reg(context)
+	);
+	x = (LPBYTE)EAX_reg(context);
+	*x++ = 0x33;*x++=0xC9; /* xor ecx,ecx */
+	*x++ = 0x8A;*x++=0x4D;*x++=0xFC; /* mov cl,[ebp-04] */
+	*x++ = 0x8B;*x++=0x14;*x++=0x8D;*(DWORD*)x= EAX_reg(context)+EDX_reg(context);
+	x+=4;	/* mov edx, [4*ecx + (EAX+EDX) */
+	*x++ = 0xB8; *(DWORD*)x = (DWORD)GetProcAddress32(WIN32_GetModuleHandleA("KERNEL32"),"QT_Thunk");
+	x+=4; 	/* mov eax , QT_Thunk */
+	*x++ = 0xFF; *x++ = 0xE0;	/* jmp eax */
+	*x++ = 0xCC;	/* int 03 */
+	*x++ = 0xCC;	/* int 03 */
+	*x++ = 0xCC;	/* int 03 */
+	*x++ = 0xCC;	/* int 03 */
+	*x++ = 0xCC;	/* int 03 */
+	*x++ = 0xCC;	/* int 03 */
+	*x++ = 0xCC;	/* int 03 */
+	*x++ = 0xCC;	/* int 03 */
+	*x++ = 0xCC;	/* int 03 */
+	*x++ = 0xCC;	/* int 03 */
+	*x++ = 0xCC;	/* int 03 */
+	*x++ = 0xCC;	/* int 03 */
+	*x++ = 0xCC;	/* int 03 */
+	EIP_reg(context) = EAX_reg(context);
+}
+
+/***********************************************************************
+ *							(KERNEL32.45)
+ * Another thunkbuf link routine.
+ * The start of the thunkbuf looks like this:
+ * 	00: DWORD	length
+ *	04: SEGPTR	address for thunkbuffer pointer
+ */
+VOID
+_KERNEL32_46(LPBYTE thunk,LPSTR thkbuf,DWORD len,LPSTR dll16,LPSTR dll32) {
+	LPDWORD		addr;
+	HMODULE16	hmod;
+	SEGPTR		segaddr;
+
+	fprintf(stderr,"KERNEL32_46(%p,%s,%lx,%s,%s)\n",
+		thunk,thkbuf,len,dll16,dll32
+	);
+	hmod = LoadLibrary16(dll16);
+	if (hmod < 32) {
+		fprintf(stderr,"->couldn't load %s, error %d\n",dll16,hmod);
+		return;
+	}
+	segaddr = (SEGPTR)WIN32_GetProcAddress16(hmod,thkbuf);
+	if (!segaddr) {
+		fprintf(stderr,"-> haven't found %s in %s!\n",thkbuf,dll16);
+		return;
+	}
+	addr = (LPDWORD)PTR_SEG_TO_LIN(segaddr);
+	if (addr[0] != len) {
+		fprintf(stderr,"-> length of thkbuf differs from expected length! (%ld vs %ld)\n",addr[0],len);
+		return;
+	}
+	*(DWORD*)PTR_SEG_TO_LIN(addr[1]) = (DWORD)thunk;
+}
+
+/**********************************************************************
+ *           _KERNEL32_87
+ * Check if thunking is initialized (ss selector set up etc.)
+ */
+BOOL32 _KERNEL32_87() {
+    fprintf(stderr,"KERNEL32_87 stub, returning TRUE\n");
+    return TRUE;
+}
+
+/**********************************************************************
+ *           _KERNEL32_88
+ * One of the real thunking functions
+ * Probably implemented totally wrong.
+ */
+BOOL32 _KERNEL32_88(DWORD nr,DWORD flags,LPVOID fun,DWORD *hmm) {
+    fprintf(stderr,"KERNEL32_88(%ld,0x%08lx,%p,%p) stub, returning TRUE\n",
+	nr,flags,fun,hmm
+    );
+#ifndef WINELIB
+    switch (nr) {
+    case 0: CallTo32_0(fun);
+	break;
+    case 4: CallTo32_1(fun,hmm[0]);
+	break;
+    case 8: CallTo32_2(fun,hmm[0],hmm[1]);
+	break;
+    default:
+	fprintf(stderr,"    unsupported nr of arguments, %ld\n",nr);
+	break;
+
+    }
+#endif
+    return TRUE;
+}
diff --git a/windows/class.c b/windows/class.c
index c6fa82e..4cc7eb6 100644
--- a/windows/class.c
+++ b/windows/class.c
@@ -320,10 +320,13 @@
         return 0;
     }
 
-    dprintf_class( stddeb, "RegisterClass16: atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
+    dprintf_class( stddeb, "RegisterClass16: atom=%04x wndproc=%08lx hinst=%04x
+bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
                    atom, (DWORD)wc->lpfnWndProc, hInstance,
                    wc->hbrBackground, wc->style, wc->cbClsExtra,
-                   wc->cbWndExtra, classPtr );
+                   wc->cbWndExtra, classPtr,
+		   HIWORD(wc->lpszClassName) ?
+                       (char *)PTR_SEG_TO_LIN(wc->lpszClassName) : "" );
 
     classPtr->hIcon         = wc->hIcon;
     classPtr->hIconSm       = 0;
@@ -357,10 +360,12 @@
         return 0;
     }
 
-    dprintf_class( stddeb, "RegisterClass32A: atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
+    dprintf_class( stddeb, "RegisterClass32A: atom=%04x wndproc=%08lx
+hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
                    atom, (DWORD)wc->lpfnWndProc, hInstance,
                    wc->hbrBackground, wc->style, wc->cbClsExtra,
-                   wc->cbWndExtra, classPtr );
+                   wc->cbWndExtra, classPtr,
+                   HIWORD(wc->lpszClassName) ? wc->lpszClassName : "" );
     
     classPtr->hIcon         = (HICON16)wc->hIcon;
     classPtr->hIconSm       = 0;
diff --git a/windows/dialog.c b/windows/dialog.c
index 4024310..8b2f580 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -899,6 +899,13 @@
 
     *translate = *dispatch = FALSE;
 
+    if (message == WM_PAINT)
+    {
+        /* Apparently, we have to handle this one as well */
+        *dispatch = TRUE;
+        return TRUE;
+    }
+
       /* Only the key messages get special processing */
     if ((message != WM_KEYDOWN) &&
         (message != WM_SYSCHAR) &&
diff --git a/windows/message.c b/windows/message.c
index a124fcd..6bd4f4d 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -37,6 +37,8 @@
 extern MESSAGEQUEUE *pCursorQueue;			 /* queue.c */
 extern MESSAGEQUEUE *pActiveQueue;
 
+extern void JoySendMessages(void);
+
 DWORD MSG_WineStartTicks; /* Ticks at Wine startup */
 
 static UINT32 doubleClickSpeed = 452;
@@ -412,6 +414,9 @@
     MESSAGEQUEUE *sysMsgQueue = QUEUE_GetSysQueue();
     int i, kbd_msg, pos = sysMsgQueue->nextMessage;
 
+    /* FIXME: there has to be a better way to do this */
+    JoySendMessages();
+
     /* If the queue is empty, attempt to fill it */
     if (!sysMsgQueue->msgCount && XPending(display))
         EVENT_WaitXEvent( FALSE, FALSE );
diff --git a/windows/queue.c b/windows/queue.c
index 666f87b..4872a35 100644
--- a/windows/queue.c
+++ b/windows/queue.c
@@ -6,6 +6,7 @@
 
 #include <stdlib.h>
 #include <signal.h>
+#include "miscemu.h"
 #include "module.h"
 #include "queue.h"
 #include "task.h"
@@ -26,8 +27,6 @@
 static MESSAGEQUEUE *pMouseQueue = NULL;  /* Queue for last mouse message */
 static MESSAGEQUEUE *pKbdQueue = NULL;    /* Queue for last kbd message */
 
-extern void SIGNAL_MaskAsyncEvents(BOOL32);
-
 MESSAGEQUEUE *pCursorQueue = NULL; 
 MESSAGEQUEUE *pActiveQueue = NULL;
 
diff --git a/windows/win.c b/windows/win.c
index 371a47b..3200d5a 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -1172,6 +1172,10 @@
 {
     ATOM atom = 0;
 
+    dprintf_win(stddeb, "FindWindowEx16: %04x %04x '%s' '%s'\n", parent,
+		child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
+		title ? title : "");
+
     if (className)
     {
         /* If the atom doesn't exist, then no class */