Release 971221

Fri Dec 19 10:50:46 1997  Douglas Ridgway  <ridgway@winehq.com>

	* [Make.rules.in] [Makefile.in] [documentation/Makefile.in]
 	  [documentation/README.documentation]
	First cut at Wine API documentation. No longer install reference
	manual by default.

Wed Dec 17 21:32:23 1997  Andreas Mohr <100.30936@germany.net>

	* [files/file.c]
	Fixed GetTempFileName16() to use current path of requested drive
	as needed.

	* [if1632/Makefile.in] [if1632/builtin.c] [if1632/dciman32.spec]
	  [if1632/msvfw32.spec] [if1632/tapi32.spec] [if1632/wow32.spec]
	Added misc DLLs needed by various apps.

Wed Dec 17 12:01:50 1997  Morten Eriksen <mortene@sim.no>

	* [if1632/gdi32.spec] [include/windows.h] [objects/palette.c]
	Inserted empty stub for CreateHalftonePalette.

Tue Dec 16 22:08:06 1997  Huw D M Davies <h.davies1@physics.oxford.ac.uk>

	* [windows/mdi.c]
	Use VK_TAB instead of VK_SEPARATOR in TranslateMDISysAccel().

	* [graphics/metafiledrv/init.c]
	DeleteDC() on a MetaDC doesn't do anything - it shouldn't. Therefore
	fix cleanup of MetaDCs in CloseMetaFile(); they now actually get
	removed from the GDI heap!

	* [graphics/x11drv/xfont.c]
	Preserve FO_MATCH_XYINDEP flag in XFONT_MatchFIList(). Should reduce
	the number of bold-italic matches.

Tue Dec 16 20:11:43 1997  Bertho Stultiens <bertho@panter.soci.aau.dk>

	* [graphics/painting.c]
	Included an implementation of DrawState

	* [if1632/thunk.c]
	Changed many fprintfs into dprintf_thunk

	* [include/cache.h] [graphics/cache.c]
	New files to hold cached handles to regulary used GDI object.

	* [include/windows.h]
	Added DRAWSTATExx typedefs
	Added DSS_DEFAULT define for DrawState

	* [objects/text.c]
	New implementation of GrayString()

	* [controls/uitools.c]
	Implemented DrawFrameControl() functions
	Changed DrawEdge() behaviour to win95 implementation

Mon Dec 15 23:43:01 1997  Martin Boehme <boehme@informatik.mu-luebeck.de>

	* [graphics/path.c] [include/path.h] [graphics/painting.c]
	  [if1632/gdi32.spec] [include/gdi.h] [include/windows.h]
	  [objects/dc.c]
        Added preliminary support for GDI paths.

	* [objects/dc.c]
	Added DC_Init_DC_INFO function for initializing WIN_DC_INFO
	structure.

	* [include/windows.h] [include/gdi.h] [objects/gdiobj.c]
	Added DEFAULT_GUI_FONT.

	* [include/winerror.h]
	Added a few error codes.

	* [memory/heap.c]
	Changed HeapAlloc to make the correct calls to SetLastError
	(now conforms to NT's behaviour).

	* [windows/win.c]
	Changed WIN_CreateWindowEx to allow child windows with zero
	width / height.

Sun Dec 14 12:01:07 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [if1632/*] [relay32/*]
	Moved all 32-bit relay stuff to relay32/

	* [fi1632/thunk.c] [win32/kernel32.c]
	Moved all KERNEL32 ordinal functions to kernel32.c

	* [memory/selector.c]
	Initialize selectors in AllocSelectorArray.

	* [tools/build.c]
	Generate C instead of assembly for Win32 relays.
	Fixed stack corruption in CallTo16 functions, found by Bertho
	Stultiens.
	
Sun Dec 14 10:55:00 1997  Andreas Mohr <100.30936@germany.net>

	* [if1632/Makefile.in] [if1632/builtin.c] [if1632/ole2thk.spec]
	Added built-in OLE2THK.DLL. 

	* [if1632/toolhelp.spec] [include/toolhelp.h] [memory/selector.c]
	  [misc/toolhelp.c]
	Added stubs for StackTraceFirst(), StackTraceCSIPFirst(),
	StackTraceNext(), UTSelectorOffsetToLinear()
	and UTLinearToSelectorOffset().

Sat Dec 13 17:26:41 1997  Alex Korobka  <alex@trantor.pharm.sunysb.edu>

	* [misc/winsock.c]
	32-bit API fixes for reported problems (thanks to Marcus
	and David).

	* [graphics/x11drv/xfont.c]
	Little tweak in point size calculation.

	* [windows/defwnd.c] [windows/dce.c] [windows/winhelp.c]
	  [windows/winproc.c] [windows/win.c]
	Bug fixes.

Sat Dec 13 16:35:14 1997  Kai Morich <kai.morich@rhein-neckar.netsurf.de>

	* [files/dos_fs.c]
	OpenFile with empty filename and OF_PARSE returns current dir.

	* [misc/commdlg.c]
	Ignore initial dir if bogus.

	* [files/file.c]
	Locking an identic region in a file must not be an error.

	* [misc/lstr.c]
	Use wide char ctype functions.

Fri Dec 12 23:46:22 1997  Uwe Bonnes  <bon@elektron.ikp.physik.tu-darmstadt.de>

	* [file/drive.c]
	First attempt for GetDiskFreeSpaceEx.

Fri Dec 12 23:18:41 1997  Marcus Meissner  <msmeissn@cip.informatik.uni-erlangen.de>

	* [loader/pe_resource.c]	
	Fixed wrongly appearing menus problem (only use default lookups in
	last resource subtree).

	* [multimedia/*.c]
	Added win32 support for time* and joy* lowlevel drivers,
	(not excessively tested), some misc fixes and cleanups.

	* [misc/shellord.c][misc/shell.c][ole/folders.c][ole/ifs.c]
	  [include/interfaces.h][include/shlobj.h]
	Added some more undocumented SHELL32 functions, some shell folder
 	interface stubs added, SHGetMalloc, SHGetDesktopFolder,
	SHGetSpecialFolderLocation, SHGetPathFromIDList stubs added,
	IMalloc, IUnknown implemented.

	* [windows/msgbox.c]
	Implemented MessageBoxIndirect*, some internal changes.

	* [if1632/thunk.c]
	KERNEL_431 implemented.

	* [objects/gdiobj.c]
	GetCurrentObject implemented.

Wed Dec  3 01:09:17 1997  Gordon Chaffee  <chaffee@apu.cs.berkeley.edu>

	* [objects/dib.c]
	Fix a couple small DIB problems.

	* [controls/edit.c]
	Fix a typo.

	* [files/dos_fs.c]
	Try normal readdir in case fs is specified as vfat but isn't.

	* [files/profile.c]
	Implementation of WritePrivateProfileSection32A from Uwe Bonnes.

	* [misc/printdrv.c]
	OpenPrinter32A stub, helps Word97 start.

	* [objects/text.c]
	Fixup implementation of GetTextCharsetInfo.

	* [scheduler/process.c]
	Fix environment variable expansion.

	* [win32/code_page.c]
	Make MultiByteToWideChar and WideCharToMultiByte conform in return
	values and error conditions to those in Windows NT 4.0.

	* [windows/message.c]
	Fix broadcasting problems in Win32.  The Win32 docs say to use
	HWND_TOPMOST to broadcast to all Win32 Windows.

	* [memory/virtual.c] [loader/pe_image.c]
	Do not map in VirtualAlloc if address is specified and space is
	not available.  This is required by Win32.

	* [include/pen.h] [include/x11drv.h] [objects/dc.c]
	  [objects/pen.c] [graphics/x11drv/pen.c]
	Support for ExtCreatePen.

Tue Dec  2 20:22:06 1997  Morten Welinder  <terra@diku.dk>

	* [*/*.c] [*/*.h]
	Add lots of prototypes.

	* [if1632/kernel32.spec][include/windows.h][include/winnt.h]
	  [misc/cpu.c]
	Define IsProcessorFeaturePresent.

	* [misc/crtdll.c]
 	(CRTDLL__getcwd): Allocate enough memory for the terminating zero.

	* [misc/ver.c]
	Improve check for null component in _find_data[AW].  Plug leaks
	in VerQueryValue*.

	* [win32/console.c][if1632/kernel32.spec]
	Add stubs for GetConsoleCursorInfo32, SetConsoleCursorInfo32.

	* [windows/message.c][if1632/user32.spec][include/windows.h]
	Define SendMessageTimeout*.

	* [graphics/x11drv/xfont.c]
	Change algorithm of __genericCheckSum to be alignment safe.

	* [misc/main.c] [misc/winsock.c] [misc/winsock_dns.c]
	Include winsock.h early to avoid Solaris problem.

	* [include/windows.h]
	Undef FSHIFT before we define it.

	* [rc/winerc.c]
	Include <fcntl.h> instead of <sys/fcntl.h>.

	* [files/file.c]
	Use strerror in FILE_SetDosError if available.

	* [include/config.h.in] [configure.in]
	Check for strerror.

	* [objects/gdiobj.c]
	Make static font structures aligned.

Mon Dec  1 10:10:21 1997  Karl Garrison  <karlos@eznet.net>

	* [win32/console.c] [if1632/kernel32.spec] [include/windows.h]
	Added stub for GetNumberOfConsoleMouseButtons.
	Added stub for PeekConsoleInput(A,W).
	Fixed parameter list for WriteConsole(A,W).
	GetNumberOfConsoleInputEvents now returns 0 events instead of 1
	(since low-level console functions are not yet supported).
	GetConsoleMode no longer returns ENABLE_WINDOW_INPUT and
	ENABLE_MOUSE_INPUT since these are not currently implemented.
diff --git a/ANNOUNCE b/ANNOUNCE
index 93c7b24..3f2c359 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,14 +1,16 @@
-This is release 971130 of Wine, the MS Windows emulator.  This is still a
+This is release 971221 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-971130: (see ChangeLog for details)
-	- Better Win32s support.
-	- Lots of new Win32 functions.
-	- DIB handling improvements.
+WHAT'S NEW with Wine-971221: (see ChangeLog for details)
+	- Preliminary GDI paths support.
+	- DrawFrameControl implementation.
+	- Multimedia support for time and joystick functions.
+	- Win32 spec files now generate C code for Winelib.
+	- Tons of new Win32 functions and stubs.
 	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -17,10 +19,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-971130.tar.gz
-  ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-971130.tar.gz
-  ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-971130.tar.gz
-  ftp://ftp.progsoc.uts.edu.au/pub/Wine/development/Wine-971130.tar.gz
+  ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-971221.tar.gz
+  ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-971221.tar.gz
+  ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-971221.tar.gz
+  ftp://ftp.progsoc.uts.edu.au/pub/Wine/development/Wine-971221.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
diff --git a/AUTHORS b/AUTHORS
index cd18940..616a2e6 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -102,6 +102,7 @@
 William Smith,
 Dominik Strasser,
 Vadim Strizhevsky,
+Bertho Stultiens,
 Erik Svendsen,
 Tristan Tarrant,
 Andrew Taylor,
diff --git a/BUGS b/BUGS
index cc9b8c0..8e339b2 100644
--- a/BUGS
+++ b/BUGS
@@ -5,7 +5,7 @@
 add new entries and, more importantly, remove those for the 
 bugs you fixed ;-)
 ------------------------------------------------------------
-As of Nov 1997 -
+As of Dec 1997 -
 
 General:
 
@@ -32,13 +32,15 @@
 
 Miscellaneous:
 
- * Invisible controls in BCW dialogs.
+ * 16-bit Eudora 1.5.2 goes into recursion trying to display
+   a horizontal scrollbar (SetScrollPos() artifact).
 
  * mIRC 'commands' menu stays on top and will not refresh.
 
  * mIRC is unable to show 'Options' dialog.
 
- * Tab switching in mIRC 'Setup' dialog leaks memory.
+ * Tab switching in mIRC 'Setup' dialog stops erasing background
+   after a random number of repetitions.
 
  * nBytesWidth in CURSORICONINFO is bogus for some bpp
    (doesn't reflect the fact that bits are packed and 16-bit aligned).
@@ -47,7 +49,7 @@
    (probably because of bytes width stuff).
 
  * Netscape displays partially downloaded inline graphics with
-   wrong offsets. Bitmap is missing in the splash-window.
+   wrong offsets. 
 
  * Text alignment problems in Word and Write (variable pitch fonts).
 
@@ -62,6 +64,8 @@
  * AllocCSToDSAlias() shouldn't alloc alias for the same segment multiple
    times.
 
+ * X11DRV_PaintRgn doesn't respect mapping modes
+
 Where to look in source files:
 
  * grep for FIXME in the source files.
diff --git a/ChangeLog b/ChangeLog
index 76ac4ba..aad647d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,266 @@
 ----------------------------------------------------------------------
+Fri Dec 19 10:50:46 1997  Douglas Ridgway  <ridgway@winehq.com>
+
+	* [Make.rules.in] [Makefile.in] [documentation/Makefile.in]
+ 	  [documentation/README.documentation]
+	First cut at Wine API documentation. No longer install reference
+	manual by default.
+
+Wed Dec 17 21:32:23 1997  Andreas Mohr <100.30936@germany.net>
+
+	* [files/file.c]
+	Fixed GetTempFileName16() to use current path of requested drive
+	as needed.
+
+	* [if1632/Makefile.in] [if1632/builtin.c] [if1632/dciman32.spec]
+	  [if1632/msvfw32.spec] [if1632/tapi32.spec] [if1632/wow32.spec]
+	Added misc DLLs needed by various apps.
+
+Wed Dec 17 12:01:50 1997  Morten Eriksen <mortene@sim.no>
+
+	* [if1632/gdi32.spec] [include/windows.h] [objects/palette.c]
+	Inserted empty stub for CreateHalftonePalette.
+
+Tue Dec 16 22:08:06 1997  Huw D M Davies <h.davies1@physics.oxford.ac.uk>
+
+	* [windows/mdi.c]
+	Use VK_TAB instead of VK_SEPARATOR in TranslateMDISysAccel().
+
+	* [graphics/metafiledrv/init.c]
+	DeleteDC() on a MetaDC doesn't do anything - it shouldn't. Therefore
+	fix cleanup of MetaDCs in CloseMetaFile(); they now actually get
+	removed from the GDI heap!
+
+	* [graphics/x11drv/xfont.c]
+	Preserve FO_MATCH_XYINDEP flag in XFONT_MatchFIList(). Should reduce
+	the number of bold-italic matches.
+
+Tue Dec 16 20:11:43 1997  Bertho Stultiens <bertho@panter.soci.aau.dk>
+
+	* [graphics/painting.c]
+	Included an implementation of DrawState
+
+	* [if1632/thunk.c]
+	Changed many fprintfs into dprintf_thunk
+
+	* [include/cache.h] [graphics/cache.c]
+	New files to hold cached handles to regulary used GDI object.
+
+	* [include/windows.h]
+	Added DRAWSTATExx typedefs
+	Added DSS_DEFAULT define for DrawState
+
+	* [objects/text.c]
+	New implementation of GrayString()
+
+	* [controls/uitools.c]
+	Implemented DrawFrameControl() functions
+	Changed DrawEdge() behaviour to win95 implementation
+
+Mon Dec 15 23:43:01 1997  Martin Boehme <boehme@informatik.mu-luebeck.de>
+
+	* [graphics/path.c] [include/path.h] [graphics/painting.c]
+	  [if1632/gdi32.spec] [include/gdi.h] [include/windows.h]
+	  [objects/dc.c]
+        Added preliminary support for GDI paths.
+
+	* [objects/dc.c]
+	Added DC_Init_DC_INFO function for initializing WIN_DC_INFO
+	structure.
+
+	* [include/windows.h] [include/gdi.h] [objects/gdiobj.c]
+	Added DEFAULT_GUI_FONT.
+
+	* [include/winerror.h]
+	Added a few error codes.
+
+	* [memory/heap.c]
+	Changed HeapAlloc to make the correct calls to SetLastError
+	(now conforms to NT's behaviour).
+
+	* [windows/win.c]
+	Changed WIN_CreateWindowEx to allow child windows with zero
+	width / height.
+
+Sun Dec 14 12:01:07 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>
+
+	* [if1632/*] [relay32/*]
+	Moved all 32-bit relay stuff to relay32/
+
+	* [fi1632/thunk.c] [win32/kernel32.c]
+	Moved all KERNEL32 ordinal functions to kernel32.c
+
+	* [memory/selector.c]
+	Initialize selectors in AllocSelectorArray.
+
+	* [tools/build.c]
+	Generate C instead of assembly for Win32 relays.
+	Fixed stack corruption in CallTo16 functions, found by Bertho
+	Stultiens.
+	
+Sun Dec 14 10:55:00 1997  Andreas Mohr <100.30936@germany.net>
+
+	* [if1632/Makefile.in] [if1632/builtin.c] [if1632/ole2thk.spec]
+	Added built-in OLE2THK.DLL. 
+
+	* [if1632/toolhelp.spec] [include/toolhelp.h] [memory/selector.c]
+	  [misc/toolhelp.c]
+	Added stubs for StackTraceFirst(), StackTraceCSIPFirst(),
+	StackTraceNext(), UTSelectorOffsetToLinear()
+	and UTLinearToSelectorOffset().
+
+Sat Dec 13 17:26:41 1997  Alex Korobka  <alex@trantor.pharm.sunysb.edu>
+
+	* [misc/winsock.c]
+	32-bit API fixes for reported problems (thanks to Marcus
+	and David).
+
+	* [graphics/x11drv/xfont.c]
+	Little tweak in point size calculation.
+
+	* [windows/defwnd.c] [windows/dce.c] [windows/winhelp.c]
+	  [windows/winproc.c] [windows/win.c]
+	Bug fixes.
+
+Sat Dec 13 16:35:14 1997  Kai Morich <kai.morich@rhein-neckar.netsurf.de>
+
+	* [files/dos_fs.c]
+	OpenFile with empty filename and OF_PARSE returns current dir.
+
+	* [misc/commdlg.c]
+	Ignore initial dir if bogus.
+
+	* [files/file.c]
+	Locking an identic region in a file must not be an error.
+
+	* [misc/lstr.c]
+	Use wide char ctype functions.
+
+Fri Dec 12 23:46:22 1997  Uwe Bonnes  <bon@elektron.ikp.physik.tu-darmstadt.de>
+
+	* [file/drive.c]
+	First attempt for GetDiskFreeSpaceEx.
+
+Fri Dec 12 23:18:41 1997  Marcus Meissner  <msmeissn@cip.informatik.uni-erlangen.de>
+
+	* [loader/pe_resource.c]	
+	Fixed wrongly appearing menus problem (only use default lookups in
+	last resource subtree).
+
+	* [multimedia/*.c]
+	Added win32 support for time* and joy* lowlevel drivers,
+	(not excessively tested), some misc fixes and cleanups.
+
+	* [misc/shellord.c][misc/shell.c][ole/folders.c][ole/ifs.c]
+	  [include/interfaces.h][include/shlobj.h]
+	Added some more undocumented SHELL32 functions, some shell folder
+ 	interface stubs added, SHGetMalloc, SHGetDesktopFolder,
+	SHGetSpecialFolderLocation, SHGetPathFromIDList stubs added,
+	IMalloc, IUnknown implemented.
+
+	* [windows/msgbox.c]
+	Implemented MessageBoxIndirect*, some internal changes.
+
+	* [if1632/thunk.c]
+	KERNEL_431 implemented.
+
+	* [objects/gdiobj.c]
+	GetCurrentObject implemented.
+
+Wed Dec  3 01:09:17 1997  Gordon Chaffee  <chaffee@apu.cs.berkeley.edu>
+
+	* [objects/dib.c]
+	Fix a couple small DIB problems.
+
+	* [controls/edit.c]
+	Fix a typo.
+
+	* [files/dos_fs.c]
+	Try normal readdir in case fs is specified as vfat but isn't.
+
+	* [files/profile.c]
+	Implementation of WritePrivateProfileSection32A from Uwe Bonnes.
+
+	* [misc/printdrv.c]
+	OpenPrinter32A stub, helps Word97 start.
+
+	* [objects/text.c]
+	Fixup implementation of GetTextCharsetInfo.
+
+	* [scheduler/process.c]
+	Fix environment variable expansion.
+
+	* [win32/code_page.c]
+	Make MultiByteToWideChar and WideCharToMultiByte conform in return
+	values and error conditions to those in Windows NT 4.0.
+
+	* [windows/message.c]
+	Fix broadcasting problems in Win32.  The Win32 docs say to use
+	HWND_TOPMOST to broadcast to all Win32 Windows.
+
+	* [memory/virtual.c] [loader/pe_image.c]
+	Do not map in VirtualAlloc if address is specified and space is
+	not available.  This is required by Win32.
+
+	* [include/pen.h] [include/x11drv.h] [objects/dc.c]
+	  [objects/pen.c] [graphics/x11drv/pen.c]
+	Support for ExtCreatePen.
+
+Tue Dec  2 20:22:06 1997  Morten Welinder  <terra@diku.dk>
+
+	* [*/*.c] [*/*.h]
+	Add lots of prototypes.
+
+	* [if1632/kernel32.spec][include/windows.h][include/winnt.h]
+	  [misc/cpu.c]
+	Define IsProcessorFeaturePresent.
+
+	* [misc/crtdll.c]
+ 	(CRTDLL__getcwd): Allocate enough memory for the terminating zero.
+
+	* [misc/ver.c]
+	Improve check for null component in _find_data[AW].  Plug leaks
+	in VerQueryValue*.
+
+	* [win32/console.c][if1632/kernel32.spec]
+	Add stubs for GetConsoleCursorInfo32, SetConsoleCursorInfo32.
+
+	* [windows/message.c][if1632/user32.spec][include/windows.h]
+	Define SendMessageTimeout*.
+
+	* [graphics/x11drv/xfont.c]
+	Change algorithm of __genericCheckSum to be alignment safe.
+
+	* [misc/main.c] [misc/winsock.c] [misc/winsock_dns.c]
+	Include winsock.h early to avoid Solaris problem.
+
+	* [include/windows.h]
+	Undef FSHIFT before we define it.
+
+	* [rc/winerc.c]
+	Include <fcntl.h> instead of <sys/fcntl.h>.
+
+	* [files/file.c]
+	Use strerror in FILE_SetDosError if available.
+
+	* [include/config.h.in] [configure.in]
+	Check for strerror.
+
+	* [objects/gdiobj.c]
+	Make static font structures aligned.
+
+Mon Dec  1 10:10:21 1997  Karl Garrison  <karlos@eznet.net>
+
+	* [win32/console.c] [if1632/kernel32.spec] [include/windows.h]
+	Added stub for GetNumberOfConsoleMouseButtons.
+	Added stub for PeekConsoleInput(A,W).
+	Fixed parameter list for WriteConsole(A,W).
+	GetNumberOfConsoleInputEvents now returns 0 events instead of 1
+	(since low-level console functions are not yet supported).
+	GetConsoleMode no longer returns ENABLE_WINDOW_INPUT and
+	ENABLE_MOUSE_INPUT since these are not currently implemented.
+
+----------------------------------------------------------------------
 Sat Nov 29 12:35:26 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>
 
 	* [if1632/builtin.c]
diff --git a/Make.rules.in b/Make.rules.in
index e27e88b..7b1e7d7 100644
--- a/Make.rules.in
+++ b/Make.rules.in
@@ -36,6 +36,7 @@
 AR        = ar rc
 RM        = rm -f
 MKDIR     = mkdir
+C2MAN     = c2man
 BUILD     = $(TOPOBJDIR)/tools/build@PROGEXT@
 MAKEDEP   = $(TOPOBJDIR)/tools/makedep@PROGEXT@
 WINERC    = $(TOPOBJDIR)/rc/winerc@PROGEXT@
@@ -108,6 +109,10 @@
 $(MODULE).o: $(OBJS)
 	$(LDCOMBINE) $(OBJS) -o $(MODULE).o
 
+# Rule for man pages
+
+man: $(C_SRCS)
+	for i in $(C_SRCS); do $(C2MAN) -L -o$(TOPOBJDIR)/documentation/man3w -S3w $(DIVINCL) $$i; done
 
 # Misc. rules
 
diff --git a/Makefile.in b/Makefile.in
index c326756..c34c3b6 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -7,6 +7,7 @@
 # install:              install everything
 # depend:		create the dependencies
 # etags:		create a TAGS file for Emacs.
+# manpages:		compile manpages for Wine API
 #
 
 # Main target to build
@@ -24,6 +25,7 @@
 
 LIBSUBDIRS = \
 	rc \
+	tools \
 	controls \
 	files \
 	graphics \
@@ -44,11 +46,11 @@
 	windows
 
 EMUSUBDIRS = \
-	tools \
 	debugger \
 	graphics/win16drv \
 	if1632 \
-	miscemu
+	miscemu \
+	relay32
 
 PROGSUBDIRS = libtest programs
 
@@ -90,7 +92,8 @@
 	debugger/debugger.o \
 	graphics/win16drv/win16drv.o \
 	if1632/if1632.o \
-	miscemu/miscemu.o
+	miscemu/miscemu.o \
+	relay32/relay32.o
 
 all: $(MAIN_TARGET)
 
@@ -139,6 +142,10 @@
 TAGS etags:
 	etags `find $(TOPSRCDIR) -name '*.[chS]' -print | grep -v dbgmain`
 
+manpages:
+	-$(MKDIR) $(TOPOBJDIR)/documentation/man3w
+	for i in $(LIBSUBDIRS); do (cd $$i && $(MAKE) man); done
+
 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
diff --git a/configure b/configure
index 5699464..1032ff2 100755
--- a/configure
+++ b/configure
@@ -2070,7 +2070,7 @@
 
 
 
-for ac_func in memmove tcgetattr usleep wait4 waitpid
+for ac_func in memmove strerror tcgetattr usleep wait4 waitpid
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
 echo "configure:2077: checking for $ac_func" >&5
@@ -2523,10 +2523,12 @@
 objects/Makefile
 ole/Makefile
 programs/Makefile
+programs/notepad/Makefile
 programs/progman/Makefile
 programs/winhelp/Makefile
 programs/winver/Makefile
 rc/Makefile
+relay32/Makefile
 resources/Makefile
 scheduler/Makefile
 tools/Makefile
@@ -2647,10 +2649,12 @@
 objects/Makefile
 ole/Makefile
 programs/Makefile
+programs/notepad/Makefile
 programs/progman/Makefile
 programs/winhelp/Makefile
 programs/winver/Makefile
 rc/Makefile
+relay32/Makefile
 resources/Makefile
 scheduler/Makefile
 tools/Makefile
diff --git a/configure.in b/configure.in
index 8c1186c..11b26ab 100644
--- a/configure.in
+++ b/configure.in
@@ -114,7 +114,7 @@
 
 dnl **** Check for functions and header files ****
 
-AC_CHECK_FUNCS(memmove tcgetattr usleep wait4 waitpid)
+AC_CHECK_FUNCS(memmove strerror tcgetattr usleep wait4 waitpid)
 AC_HEADER_STAT()
 AC_C_CONST()
 AC_TYPE_SIZE_T()
@@ -148,10 +148,12 @@
 objects/Makefile
 ole/Makefile
 programs/Makefile
+programs/notepad/Makefile
 programs/progman/Makefile
 programs/winhelp/Makefile
 programs/winver/Makefile
 rc/Makefile
+relay32/Makefile
 resources/Makefile
 scheduler/Makefile
 tools/Makefile
diff --git a/controls/edit.c b/controls/edit.c
index b4cd3ac..303d2f1 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -3494,7 +3494,7 @@
 	e = EDIT_CharFromPos(wnd, es, x, y, &after_wrap);
 	EDIT_EM_SetSel(wnd, es, (keys & MK_SHIFT) ? es->selection_start : e, e, after_wrap);
 	EDIT_EM_ScrollCaret(wnd, es);
-	es->region_posx = es->region_posx = 0;
+	es->region_posx = es->region_posy = 0;
 	SetTimer32(wnd->hwndSelf, 0, 100, NULL);
 	return 0;
 }
diff --git a/controls/menu.c b/controls/menu.c
index 35a89f1..8c2e984 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -3878,7 +3878,7 @@
 BOOL32 WINAPI InsertMenuItem32A(HMENU32 hMenu, UINT32 uItem, BOOL32 bypos,
                                 const MENUITEMINFO32A *lpmii)
 {
-    MENUITEM *item = MENU_InsertItem(hMenu, uItem, bypos);
+    MENUITEM *item = MENU_InsertItem(hMenu, uItem, bypos ? MF_BYPOSITION : 0 );
     return SetMenuItemInfo32_common(item, lpmii, FALSE);
 }
 
@@ -3889,7 +3889,7 @@
 BOOL32 WINAPI InsertMenuItem32W(HMENU32 hMenu, UINT32 uItem, BOOL32 bypos,
                                 const MENUITEMINFO32W *lpmii)
 {
-    MENUITEM *item = MENU_InsertItem(hMenu, uItem, bypos);
+    MENUITEM *item = MENU_InsertItem(hMenu, uItem, bypos ? MF_BYPOSITION : 0 );
     return SetMenuItemInfo32_common(item, (const MENUITEMINFO32A*)lpmii, TRUE);
 }
 
diff --git a/controls/uitools.c b/controls/uitools.c
index b245ebc..e3c64de 100644
--- a/controls/uitools.c
+++ b/controls/uitools.c
@@ -2,12 +2,93 @@
  * User Interface Functions
  *
  * Copyright 1997 Dimitrie O. Paun
+ * Copyright 1997 Bertho A. Stultiens
  */
 
 #include <stdio.h>
 #include "windows.h"
 #include "debug.h"
 
+static const WORD wPattern_AA55[8] = { 0xaaaa, 0x5555, 0xaaaa, 0x5555,
+                                       0xaaaa, 0x5555, 0xaaaa, 0x5555 };
+
+/* These tables are used in:
+ * UITOOLS_DrawDiagEdge()
+ * UITOOLS_DrawRectEdge()
+ */
+static const char LTInnerNormal[] = {
+    -1,           -1,                 -1,                 -1,
+    -1,           COLOR_BTNHIGHLIGHT, COLOR_BTNHIGHLIGHT, -1,
+    -1,           COLOR_3DDKSHADOW,   COLOR_3DDKSHADOW,   -1,
+    -1,           -1,                 -1,                 -1
+};
+
+static const char LTOuterNormal[] = {
+    -1,                 COLOR_3DLIGHT,     COLOR_BTNSHADOW, -1,
+    COLOR_BTNHIGHLIGHT, COLOR_3DLIGHT,     COLOR_BTNSHADOW, -1,
+    COLOR_3DDKSHADOW,   COLOR_3DLIGHT,     COLOR_BTNSHADOW, -1,
+    -1,                 COLOR_3DLIGHT,     COLOR_BTNSHADOW, -1
+};
+
+static const char RBInnerNormal[] = {
+    -1,           -1,                -1,              -1,
+    -1,           COLOR_BTNSHADOW,   COLOR_BTNSHADOW, -1,
+    -1,           COLOR_3DLIGHT,     COLOR_3DLIGHT,   -1,
+    -1,           -1,                -1,              -1
+};
+
+static const char RBOuterNormal[] = {
+    -1,              COLOR_3DDKSHADOW,  COLOR_BTNHIGHLIGHT, -1,
+    COLOR_BTNSHADOW, COLOR_3DDKSHADOW,  COLOR_BTNHIGHLIGHT, -1,
+    COLOR_3DLIGHT,   COLOR_3DDKSHADOW,  COLOR_BTNHIGHLIGHT, -1,
+    -1,              COLOR_3DDKSHADOW,  COLOR_BTNHIGHLIGHT, -1
+};
+
+static const char LTInnerSoft[] = {
+    -1,                  -1,                -1,              -1,
+    -1,                  COLOR_3DLIGHT,     COLOR_3DLIGHT,   -1,
+    -1,                  COLOR_BTNSHADOW,   COLOR_BTNSHADOW, -1,
+    -1,                  -1,                -1,              -1
+};
+
+static const char LTOuterSoft[] = {
+    -1,              COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
+    COLOR_3DLIGHT,   COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
+    COLOR_BTNSHADOW, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
+    -1,              COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1
+};
+
+#define RBInnerSoft RBInnerNormal   /* These are the same */
+#define RBOuterSoft RBOuterNormal
+
+static const char LTRBOuterMono[] = {
+    -1,           COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
+    COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
+    COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
+    COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
+};
+
+static const char LTRBInnerMono[] = {
+    -1, -1,           -1,           -1,
+    -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
+    -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
+    -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
+};
+
+static const char LTRBOuterFlat[] = {
+    -1,                COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
+    COLOR_WINDOWFRAME, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
+    COLOR_WINDOWFRAME, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
+    COLOR_WINDOWFRAME, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
+};
+
+static const char LTRBInnerFlat[] = {
+    -1, -1,              -1,              -1,
+    -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
+    -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
+    -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
+};
+
 /***********************************************************************
  *           UITOOLS_DrawDiagEdge
  *
@@ -19,143 +100,252 @@
  * using the brushes returned by GetSysColorBrush func, but I did not have
  * the patience to implement that yet.
  */
-static BOOL32 UITOOLS_DrawDiagEdge(HDC32 hdc, RECT32 *rect, UINT32 edge,
-                                   UINT32 flags)
+/*********************************************************************
+ * 03-Dec-1997: Changed by Bertho Stultiens
+ *
+ * See also comments with UITOOLS_DrawRectEdge()
+ */
+static BOOL32 UITOOLS_DrawDiagEdge(HDC32 hdc, LPRECT32 rc, UINT32 uType, UINT32 uFlags)
 {
-  HPEN32 facePen, shadowPen, lightPen, blackPen, grayPen, nullPen;
-  HPEN32 iPen, oPen, oldPen;
-  HBRUSH32 oldBrush, faceBrush;
-  int cl, cr, ct, cb;
-  BOOL32 mainDiag;
-  POINT32 tp;
-  RECT32 r;
+    POINT32 Points[4];
+    char InnerI, OuterI;
+    HPEN32 InnerPen, OuterPen;
+    POINT32 SavePoint;
+    HPEN32 SavePen;
+    int spx, spy;
+    int epx, epy;
+    int Width = rc->right - rc->left;
+    int Height= rc->bottom - rc->top;
+    int SmallDiam = Width > Height ? Height : Width;
+    BOOL32 retval = !(   ((uType & BDR_INNER) == BDR_INNER
+                       || (uType & BDR_OUTER) == BDR_OUTER)
+                      && !(uFlags & (BF_FLAT|BF_MONO)) );
+    int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
+            + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
 
-  /* If both rasied and sunken is specified, they anihilate one another */
-  if( !((flags & BF_MONO) || (flags & BF_FLAT)) ){
-    if( (edge & BDR_RAISEDOUTER) && (edge & BDR_SUNKENOUTER) )
-      return FALSE;
-    if( (edge & BDR_RAISEDINNER) && (edge & BDR_SUNKENINNER) )
-      return FALSE;
-  }
-
-  /* Create/get the tools of the trade... */
-  facePen = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNFACE));
-  shadowPen = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNSHADOW));
-  lightPen = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNHILIGHT));
-  grayPen = CreatePen32(PS_SOLID, 0, RGB(168, 152, 144));
-  blackPen = GetStockObject32(BLACK_PEN);
-  nullPen = GetStockObject32(NULL_PEN);
-  faceBrush = GetSysColorBrush32(COLOR_BTNFACE);
-  oldPen = SelectObject32(hdc, nullPen);
-  oldBrush = SelectObject32(hdc, faceBrush);
-
-  /* this is my working rectangle */
-  r = *rect;
-
-  if(flags & BF_MONO){
-    oPen = blackPen;
-    iPen = nullPen;
-  }else if(flags & BF_FLAT){
-    oPen = shadowPen;
-    iPen = facePen;
-  }else {
-    if(flags & BF_SOFT){
-      if(flags & BF_BOTTOM){
-	oPen = (edge & BDR_RAISEDOUTER) ? blackPen : lightPen;
-	iPen = (edge & BDR_RAISEDINNER) ? shadowPen : grayPen;
-      }
-      else{
-	oPen = (edge & BDR_RAISEDOUTER) ? lightPen : blackPen;
-	iPen = (edge & BDR_RAISEDINNER) ? grayPen : shadowPen;
-      }
+    /* Init some vars */
+    OuterPen = InnerPen = (HPEN32)GetStockObject32(NULL_PEN);
+    SavePen = (HPEN32)SelectObject32(hdc, InnerPen);
+    spx = spy = epx = epy = 0; /* Satisfy the compiler... */
+    
+    /* Determine the colors of the edges */
+    if(uFlags & BF_MONO)
+    {
+        InnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
+        OuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
     }
-    else{
-      if(flags & BF_BOTTOM){
-	oPen = (edge & BDR_RAISEDOUTER) ? blackPen : lightPen;
-	iPen = (edge & BDR_RAISEDINNER) ? shadowPen : grayPen;
-      }
-      else{
-	oPen = (edge & BDR_RAISEDOUTER) ? grayPen : shadowPen;
-	iPen = (edge & BDR_RAISEDINNER) ? lightPen : blackPen;
-      }
+    else if(uFlags & BF_FLAT)
+    {
+        InnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
+        OuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
     }
-  }
-
-  if(flags & BF_BOTTOM){
-    if(flags & BF_LEFT){
-      cr = -1; cl =  0;
-      ct =  0; cb = -1;
-      mainDiag = TRUE;
-      tp.x = r.left; tp.y = r.top;
+    else if(uFlags & BF_SOFT)
+    {
+        if(uFlags & BF_BOTTOM)
+        {
+            InnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
+            OuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
+        }
+        else
+        {
+            InnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
+            OuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
+        }
     }
-    else{ /* RIGHT */
-      cr = -1; cl =  0;
-      ct =  1; cb =  0;
-      tp.x = r.left; tp.y = r.bottom-1;
-      mainDiag = FALSE;
+    else
+    {
+        if(uFlags & BF_BOTTOM)
+        {
+            InnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
+            OuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
+        }
+        else
+        {
+            InnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
+            OuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
+        }
     }
-  }
-  else{  /* TOP */
-    if(flags & BF_LEFT){
-      cr =  0; cl =  1;
-      ct =  0; cb = -1;
-      mainDiag = FALSE;
-      tp.x = r.right; tp.y = r.top;
+
+    if(InnerI != -1) InnerPen = CreatePen32(PS_SOLID, 0, GetSysColor32((int)InnerI));
+    if(OuterI != -1) OuterPen = CreatePen32(PS_SOLID, 0, GetSysColor32((int)OuterI));
+
+    MoveToEx32(hdc, 0, 0, &SavePoint);
+
+    /* Don't ask me why, but this is what is visible... */
+    /* This must be possible to do much simpler, but I fail to */
+    /* see the logic in the MS implementation (sigh...). */
+    /* So, this might look a bit brute force here (and it is), but */
+    /* it gets the job done;) */
+
+    switch(uFlags & BF_RECT)
+    {
+    case 0:
+    case BF_LEFT:
+    case BF_BOTTOM:
+    case BF_BOTTOMLEFT:
+        /* Left bottom endpoint */
+        epx = rc->left-1;
+        spx = epx + SmallDiam;
+        epy = rc->bottom;
+        spy = epy - SmallDiam;
+        break;
+
+    case BF_TOPLEFT:
+    case BF_BOTTOMRIGHT:
+        /* Left top endpoint */
+        epx = rc->left-1;
+        spx = epx + SmallDiam;
+        epy = rc->top-1;
+        spy = epy + SmallDiam;
+        break;
+
+    case BF_TOP:
+    case BF_RIGHT:
+    case BF_TOPRIGHT:
+    case BF_RIGHT|BF_LEFT:
+    case BF_RIGHT|BF_LEFT|BF_TOP:
+    case BF_BOTTOM|BF_TOP:
+    case BF_BOTTOM|BF_TOP|BF_LEFT:
+    case BF_BOTTOMRIGHT|BF_LEFT:
+    case BF_BOTTOMRIGHT|BF_TOP:
+    case BF_RECT:
+        /* Right top endpoint */
+        spx = rc->left;
+        epx = spx + SmallDiam;
+        spy = rc->bottom-1;
+        epy = spy - SmallDiam;
+        break;
     }
-    else{ /* RIGHT */
-      cr =  0; cl =  1;
-      ct =  1; cb =  0;
-      tp.x = r.right; tp.y = r.bottom-1;
-      mainDiag = TRUE;
+
+    MoveToEx32(hdc, spx, spy, NULL);
+    SelectObject32(hdc, OuterPen);
+    LineTo32(hdc, epx, epy);
+
+    SelectObject32(hdc, InnerPen);
+
+    switch(uFlags & (BF_RECT|BF_DIAGONAL))
+    {
+    case BF_DIAGONAL_ENDBOTTOMLEFT:
+    case (BF_DIAGONAL|BF_BOTTOM):
+    case BF_DIAGONAL:
+    case (BF_DIAGONAL|BF_LEFT):
+        MoveToEx32(hdc, spx-1, spy, NULL);
+        LineTo32(hdc, epx, epy-1);
+        Points[0].x = spx-add;
+        Points[0].y = spy;
+        Points[1].x = rc->left;
+        Points[1].y = rc->top;
+        Points[2].x = epx+1;
+        Points[2].y = epy-1-add;
+        Points[3] = Points[2];
+        break;
+
+    case BF_DIAGONAL_ENDBOTTOMRIGHT:
+        MoveToEx32(hdc, spx-1, spy, NULL);
+        LineTo32(hdc, epx, epy+1);
+        Points[0].x = spx-add;
+        Points[0].y = spy;
+        Points[1].x = rc->left;
+        Points[1].y = rc->bottom-1;
+        Points[2].x = epx+1;
+        Points[2].y = epy+1+add;
+        Points[3] = Points[2];
+        break;
+
+    case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP):
+    case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP|BF_LEFT):
+    case BF_DIAGONAL_ENDTOPRIGHT:
+    case (BF_DIAGONAL|BF_RIGHT|BF_TOP|BF_LEFT):
+        MoveToEx32(hdc, spx+1, spy, NULL);
+        LineTo32(hdc, epx, epy+1);
+        Points[0].x = epx-1;
+        Points[0].y = epy+1+add;
+        Points[1].x = rc->right-1;
+        Points[1].y = rc->top+add;
+        Points[2].x = rc->right-1;
+        Points[2].y = rc->bottom-1;
+        Points[3].x = spx+add;
+        Points[3].y = spy;
+        break;
+
+    case BF_DIAGONAL_ENDTOPLEFT:
+        MoveToEx32(hdc, spx, spy-1, NULL);
+        LineTo32(hdc, epx+1, epy);
+        Points[0].x = epx+1+add;
+        Points[0].y = epy+1;
+        Points[1].x = rc->right-1;
+        Points[1].y = rc->top;
+        Points[2].x = rc->right-1;
+        Points[2].y = rc->bottom-1-add;
+        Points[3].x = spx;
+        Points[3].y = spy-add;
+        break;
+
+    case (BF_DIAGONAL|BF_TOP):
+    case (BF_DIAGONAL|BF_BOTTOM|BF_TOP):
+    case (BF_DIAGONAL|BF_BOTTOM|BF_TOP|BF_LEFT):
+        MoveToEx32(hdc, spx+1, spy-1, NULL);
+        LineTo32(hdc, epx, epy);
+        Points[0].x = epx-1;
+        Points[0].y = epy+1;
+        Points[1].x = rc->right-1;
+        Points[1].y = rc->top;
+        Points[2].x = rc->right-1;
+        Points[2].y = rc->bottom-1-add;
+        Points[3].x = spx+add;
+        Points[3].y = spy-add;
+        break;
+
+    case (BF_DIAGONAL|BF_RIGHT):
+    case (BF_DIAGONAL|BF_RIGHT|BF_LEFT):
+    case (BF_DIAGONAL|BF_RIGHT|BF_LEFT|BF_BOTTOM):
+        MoveToEx32(hdc, spx, spy, NULL);
+        LineTo32(hdc, epx-1, epy+1);
+        Points[0].x = spx;
+        Points[0].y = spy;
+        Points[1].x = rc->left;
+        Points[1].y = rc->top+add;
+        Points[2].x = epx-1-add;
+        Points[2].y = epy+1+add;
+        Points[3] = Points[2];
+        break;
     }
-  }
 
-  /* if it has external edge, draw it */
-  if(edge & BDR_OUTER){
-    SelectObject32(hdc, oPen);
-    MoveToEx32(hdc, r.left, mainDiag ? r.bottom-1 : r.top, 0);
-    LineTo32(hdc, r.right, mainDiag ? r.top-1 : r.bottom);
-    r.left += cl; r.right += cr; r.top += ct; r.bottom += cb;
-  }
+    /* Fill the interior if asked */
+    if((uFlags & BF_MIDDLE) && retval)
+    {
+        HBRUSH32 hbsave;
+        HBRUSH32 hb = uFlags & BF_MONO ? GetSysColorBrush32(COLOR_WINDOW)
+                                       : GetSysColorBrush32(COLOR_BTNFACE);
+        HPEN32 hpsave;
+        HPEN32 hp = CreatePen32(PS_SOLID, 0, uFlags & BF_MONO ? GetSysColor32(COLOR_WINDOW)
+                                                              : GetSysColor32(COLOR_BTNFACE));
+        hbsave = (HBRUSH32)SelectObject32(hdc, hb);
+        hpsave = (HPEN32)SelectObject32(hdc, hp);
+        Polygon32(hdc, Points, 4);
+        SelectObject32(hdc, hbsave);
+        SelectObject32(hdc, hpsave);
+        DeleteObject32(hp);
+    }
 
-  /* if it has internal edge, draw it */
-  if(edge & BDR_INNER){
-    SelectObject32(hdc, iPen);
-    MoveToEx32(hdc, r.left, mainDiag ? r.bottom-1 : r.top, 0);
-    LineTo32(hdc, r.right, mainDiag ? r.top-1 : r.bottom);
-    r.left += cl; r.right += cr; r.top += ct; r.bottom += cb;
-  }
+    /* Adjust rectangle if asked */
+    if(uFlags & BF_ADJUST)
+    {
+        if(uFlags & BF_LEFT)   rc->left   += add;
+        if(uFlags & BF_RIGHT)  rc->right  -= add;
+        if(uFlags & BF_TOP)    rc->top    += add;
+        if(uFlags & BF_BOTTOM) rc->bottom -= add;
+    }
 
-  if((flags & BF_MIDDLE) && !(flags & BF_MONO)){
-    POINT32 p[3];
-    p[0].x = mainDiag ? r.right: r.left;
-    p[0].y = r.top;
-    p[1].x = mainDiag ? r.left : r.right;
-    p[1].y = r.bottom;
-    p[2].x = tp.x;
-    p[2].y = tp.y;
-    SelectObject32(hdc, nullPen);
-    SelectObject32(hdc, faceBrush);
-    Polygon32(hdc, p, 3);
-  }
+    /* Cleanup */
+    SelectObject32(hdc, SavePen);
+    if(InnerI != -1) DeleteObject32(InnerPen);
+    if(OuterI != -1) DeleteObject32(OuterPen);
+    MoveToEx32(hdc, SavePoint.x, SavePoint.y, NULL);
 
-  if(flags & BF_ADJUST)
-    *rect = r;
-
-  /* Restore the DC */
-  SelectObject32(hdc, oldPen);
-  SelectObject32(hdc, oldBrush);
-
-  /* Clean-up */
-  DeleteObject32(facePen);
-  DeleteObject32(shadowPen);
-  DeleteObject32(lightPen);
-  DeleteObject32(grayPen);
-
-  return TRUE;
+    return retval;
 }
 
-
 /***********************************************************************
  *           UITOOLS_DrawRectEdge
  *
@@ -167,115 +357,208 @@
  * one generated by the native DrawEdge and it is identical on all cases that
  * I tried, and I tried quite a few.
  */
-static BOOL32 UITOOLS_DrawRectEdge(HDC32 hdc, RECT32 *rect,
-                                   UINT32 edge, UINT32 flags)
+/*********************************************************************
+ * 23-Nov-1997: Changed by Bertho Stultiens
+ *
+ * Well, I started testing this and found out that there are a few things
+ * that weren't quite as win95. The following rewrite should reproduce
+ * win95 results completely.
+ * The colorselection is table-driven to avoid awfull if-statements.
+ * The table below show the color settings.
+ *
+ * Pen selection table for uFlags = 0
+ *
+ * uType |  LTI  |  LTO  |  RBI  |  RBO
+ * ------+-------+-------+-------+-------
+ *  0000 |   x   |   x   |   x   |   x
+ *  0001 |   x   |  22   |   x   |  21
+ *  0010 |   x   |  16   |   x   |  20
+ *  0011 |   x   |   x   |   x   |   x
+ * ------+-------+-------+-------+-------
+ *  0100 |   x   |  20   |   x   |  16
+ *  0101 |  20   |  22   |  16   |  21
+ *  0110 |  20   |  16   |  16   |  20
+ *  0111 |   x   |   x   |   x   |   x
+ * ------+-------+-------+-------+-------
+ *  1000 |   x   |  21   |   x   |  22
+ *  1001 |  21   |  22   |  22   |  21
+ *  1010 |  21   |  16   |  22   |  20
+ *  1011 |   x   |   x   |   x   |   x
+ * ------+-------+-------+-------+-------
+ *  1100 |   x   |   x   |   x   |   x
+ *  1101 |   x   | x (22)|   x   | x (21)
+ *  1110 |   x   | x (16)|   x   | x (20)
+ *  1111 |   x   |   x   |   x   |   x
+ *
+ * Pen selection table for uFlags = BF_SOFT
+ *
+ * uType |  LTI  |  LTO  |  RBI  |  RBO
+ * ------+-------+-------+-------+-------
+ *  0000 |   x   |   x   |   x   |   x
+ *  0001 |   x   |  20   |   x   |  21
+ *  0010 |   x   |  21   |   x   |  20
+ *  0011 |   x   |   x   |   x   |   x
+ * ------+-------+-------+-------+-------
+ *  0100 |   x   |  22   |   x   |  16
+ *  0101 |  22   |  20   |  16   |  21
+ *  0110 |  22   |  21   |  16   |  20
+ *  0111 |   x   |   x   |   x   |   x
+ * ------+-------+-------+-------+-------
+ *  1000 |   x   |  16   |   x   |  22
+ *  1001 |  16   |  20   |  22   |  21
+ *  1010 |  16   |  21   |  22   |  20
+ *  1011 |   x   |   x   |   x   |   x
+ * ------+-------+-------+-------+-------
+ *  1100 |   x   |   x   |   x   |   x
+ *  1101 |   x   | x (20)|   x   | x (21)
+ *  1110 |   x   | x (21)|   x   | x (20)
+ *  1111 |   x   |   x   |   x   |   x
+ *
+ * x = don't care; (n) = is what win95 actually uses
+ * LTI = left Top Inner line
+ * LTO = left Top Outer line
+ * RBI = Right Bottom Inner line
+ * RBO = Right Bottom Outer line
+ * 15 = COLOR_BTNFACE
+ * 16 = COLOR_BTNSHADOW
+ * 20 = COLOR_BTNHIGHLIGHT
+ * 21 = COLOR_3DDKSHADOW
+ * 22 = COLOR_3DLIGHT
+ */
+
+
+static BOOL32 UITOOLS_DrawRectEdge(HDC32 hdc, LPRECT32 rc, UINT32 uType, UINT32 uFlags)
 {
-  HBRUSH32 faceBrush, shadowBrush, lightBrush, blackBrush, grayBrush, nullBrush;
-  HBRUSH32 iNBrush, iSBrush, iEBrush, iWBrush;
-  HBRUSH32 oNBrush, oSBrush, oEBrush, oWBrush;
-  HBRUSH32 oldBrush;
-  RECT32 r;
+    char LTInnerI, LTOuterI;
+    char RBInnerI, RBOuterI;
+    HPEN32 LTInnerPen, LTOuterPen;
+    HPEN32 RBInnerPen, RBOuterPen;
+    RECT32 InnerRect = *rc;
+    POINT32 SavePoint;
+    HPEN32 SavePen;
+    int LBpenplus = 0;
+    int LTpenplus = 0;
+    int RTpenplus = 0;
+    int RBpenplus = 0;
+    BOOL32 retval = !(   ((uType & BDR_INNER) == BDR_INNER
+                       || (uType & BDR_OUTER) == BDR_OUTER)
+                      && !(uFlags & (BF_FLAT|BF_MONO)) );
+        
+    /* Init some vars */
+    LTInnerPen = LTOuterPen = RBInnerPen = RBOuterPen = (HPEN32)GetStockObject32(NULL_PEN);
+    SavePen = (HPEN32)SelectObject32(hdc, LTInnerPen);
 
-  /* If both rasied and sunken is specified, they anihilate one another */
-  if( !((flags & BF_MONO) || (flags & BF_FLAT)) ){
-    if( (edge & BDR_RAISEDOUTER) && (edge & BDR_SUNKENOUTER) )
-      return FALSE;
-    if( (edge & BDR_RAISEDINNER) && (edge & BDR_SUNKENINNER) )
-      return FALSE;
-  }
+    /* Determine the colors of the edges */
+    if(uFlags & BF_MONO)
+    {
+        LTInnerI = RBInnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
+        LTOuterI = RBOuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
+    }
+    else if(uFlags & BF_FLAT)
+    {
+        LTInnerI = RBInnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
+        LTOuterI = RBOuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
+    }
+    else if(uFlags & BF_SOFT)
+    {
+        LTInnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
+        LTOuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
+        RBInnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
+        RBOuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
+    }
+    else
+    {
+        LTInnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
+        LTOuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
+        RBInnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
+        RBOuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
+    }
 
-  faceBrush = GetSysColorBrush32(COLOR_BTNFACE);
-  shadowBrush = GetSysColorBrush32(COLOR_BTNSHADOW);
-  lightBrush = GetSysColorBrush32(COLOR_BTNHILIGHT);
-  blackBrush = GetStockObject32(BLACK_BRUSH);
-  grayBrush = GetStockObject32(LTGRAY_BRUSH);
-  nullBrush = GetStockObject32(NULL_BRUSH);
-  oldBrush = SelectObject32(hdc, nullBrush);
+    if((uFlags & BF_BOTTOMLEFT) == BF_BOTTOMLEFT)   LBpenplus = 1;
+    if((uFlags & BF_TOPRIGHT) == BF_TOPRIGHT)       RTpenplus = 1;
+    if((uFlags & BF_BOTTOMRIGHT) == BF_BOTTOMRIGHT) RBpenplus = 1;
+    if((uFlags & BF_TOPLEFT) == BF_TOPLEFT)         LTpenplus = 1;
 
-  /* this is my working rectangle */
-  r = *rect;
+    if(LTInnerI != -1) LTInnerPen = CreatePen32(PS_SOLID, 0, GetSysColor32((int)LTInnerI));
+    if(LTOuterI != -1) LTOuterPen = CreatePen32(PS_SOLID, 0, GetSysColor32((int)LTOuterI));
+    if(RBInnerI != -1) RBInnerPen = CreatePen32(PS_SOLID, 0, GetSysColor32((int)RBInnerI));
+    if(RBOuterI != -1) RBOuterPen = CreatePen32(PS_SOLID, 0, GetSysColor32((int)RBOuterI));
 
-  if(flags & BF_MONO){
-    oNBrush = oSBrush = oEBrush = oWBrush = blackBrush;
-    iNBrush = iSBrush = iEBrush = iWBrush = nullBrush;
-  }else if(flags & BF_FLAT){
-    oNBrush = oSBrush = oEBrush = oWBrush = shadowBrush;
-    iNBrush = iSBrush = iEBrush = iWBrush = faceBrush;
-  }else {
-    if(flags & BF_SOFT){
-      oNBrush = oWBrush = (edge & BDR_RAISEDOUTER) ? lightBrush  : blackBrush;
-      oSBrush = oEBrush = (edge & BDR_RAISEDOUTER) ? blackBrush  : lightBrush;
-      iNBrush = iWBrush = (edge & BDR_RAISEDINNER) ? grayBrush   : shadowBrush;
-      iSBrush = iEBrush = (edge & BDR_RAISEDINNER) ? shadowBrush : grayBrush;
+    if((uFlags & BF_MIDDLE) && retval)
+    {
+        FillRect32(hdc, &InnerRect, (uFlags & BF_MONO) ? GetSysColorBrush32(COLOR_WINDOW)
+                                                       : GetSysColorBrush32(COLOR_BTNFACE));
     }
-    else{
-      oNBrush = oWBrush = (edge & BDR_RAISEDOUTER) ? grayBrush   : shadowBrush;
-      oSBrush = oEBrush = (edge & BDR_RAISEDOUTER) ? blackBrush  : lightBrush;
-      iNBrush = iWBrush = (edge & BDR_RAISEDINNER) ? lightBrush  : blackBrush;
-      iSBrush = iEBrush = (edge & BDR_RAISEDINNER) ? shadowBrush : grayBrush;
-    }
-  }
 
-  /* if it has external edge, draw it */
-  if(edge & BDR_OUTER){
-    if(flags & BF_RIGHT){
-      SelectObject32(hdc, oEBrush);
-      PatBlt32(hdc, r.right-1, r.top, 1, r.bottom - r.top, PATCOPY);
-      r.right--;
-    }
-    if(flags & BF_BOTTOM){
-      SelectObject32(hdc, oSBrush);
-      PatBlt32(hdc, r.left, r.bottom-1, r.right-r.left, 1, PATCOPY);
-      r.bottom--;
-    }
-    if(flags & BF_LEFT){
-      SelectObject32(hdc, oWBrush);
-      PatBlt32(hdc, r.left, r.top, 1, r.bottom - r.top, PATCOPY);
-      r.left++;
-    }
-    if(flags & BF_TOP){
-      SelectObject32(hdc, oNBrush);
-      PatBlt32(hdc, r.left, r.top, r.right-r.left, 1, PATCOPY);
-      r.top++;
-    }
-  }
+    MoveToEx32(hdc, 0, 0, &SavePoint);
 
-  /* if it has internal edge, draw it */
-  if(edge & BDR_INNER){
-    if(flags & BF_RIGHT){
-      SelectObject32(hdc, iEBrush);
-      PatBlt32(hdc, r.right-1, r.top, 1, r.bottom - r.top, PATCOPY);
-      r.right--;
+    /* Draw the outer edge */
+    SelectObject32(hdc, LTOuterPen);
+    if(uFlags & BF_TOP)
+    {
+        MoveToEx32(hdc, InnerRect.left, InnerRect.top, NULL);
+        LineTo32(hdc, InnerRect.right, InnerRect.top);
     }
-    if(flags & BF_BOTTOM){
-      SelectObject32(hdc, iSBrush);
-      PatBlt32(hdc, r.left, r.bottom-1, r.right-r.left, 1, PATCOPY);
-      r.bottom--;
+    if(uFlags & BF_LEFT)
+    {
+        MoveToEx32(hdc, InnerRect.left, InnerRect.top, NULL);
+        LineTo32(hdc, InnerRect.left, InnerRect.bottom);
     }
-    if(flags & BF_LEFT){
-      SelectObject32(hdc, iWBrush);
-      PatBlt32(hdc, r.left, r.top, 1, r.bottom - r.top, PATCOPY);
-      r.left++;
+    SelectObject32(hdc, RBOuterPen);
+    if(uFlags & BF_BOTTOM)
+    {
+        MoveToEx32(hdc, InnerRect.right-1, InnerRect.bottom-1, NULL);
+        LineTo32(hdc, InnerRect.left-1, InnerRect.bottom-1);
     }
-    if(flags & BF_TOP){
-      SelectObject32(hdc, iNBrush);
-      PatBlt32(hdc, r.left, r.top, r.right-r.left, 1, PATCOPY);
-      r.top++;
+    if(uFlags & BF_RIGHT)
+    {
+        MoveToEx32(hdc, InnerRect.right-1, InnerRect.bottom-1, NULL);
+        LineTo32(hdc, InnerRect.right-1, InnerRect.top-1);
     }
-  }
 
-  /* if we got to fill the middle, to it now */
-  if((flags & BF_MIDDLE) && !(flags & BF_MONO))
-    FillRect32(hdc, &r, faceBrush);
+    /* Draw the inner edge */
+    SelectObject32(hdc, LTInnerPen);
+    if(uFlags & BF_TOP)
+    {
+        MoveToEx32(hdc, InnerRect.left+LTpenplus, InnerRect.top+1, NULL);
+        LineTo32(hdc, InnerRect.right-RTpenplus, InnerRect.top+1);
+    }
+    if(uFlags & BF_LEFT)
+    {
+        MoveToEx32(hdc, InnerRect.left+1, InnerRect.top+LTpenplus, NULL);
+        LineTo32(hdc, InnerRect.left+1, InnerRect.bottom-LBpenplus);
+    }
+    SelectObject32(hdc, RBInnerPen);
+    if(uFlags & BF_BOTTOM)
+    {
+        MoveToEx32(hdc, InnerRect.right-1-RBpenplus, InnerRect.bottom-2, NULL);
+        LineTo32(hdc, InnerRect.left-1+LBpenplus, InnerRect.bottom-2);
+    }
+    if(uFlags & BF_RIGHT)
+    {
+        MoveToEx32(hdc, InnerRect.right-2, InnerRect.bottom-1-RBpenplus, NULL);
+        LineTo32(hdc, InnerRect.right-2, InnerRect.top-1+RTpenplus);
+    }
 
-  /* adjust the rectangle if required */
-  if(flags & BF_ADJUST)
-    *rect = r;
+    /* Adjust rectangle if asked */
+    if(uFlags & BF_ADJUST)
+    {
+        int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
+                + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
+        if(uFlags & BF_LEFT)   rc->left   += add;
+        if(uFlags & BF_RIGHT)  rc->right  -= add;
+        if(uFlags & BF_TOP)    rc->top    += add;
+        if(uFlags & BF_BOTTOM) rc->bottom -= add;
+    }
 
-  /* Restore the DC */
-  SelectObject32(hdc, oldBrush);
-
-  return TRUE;
+    /* Cleanup */
+    SelectObject32(hdc, SavePen);
+    if(LTInnerI != -1) DeleteObject32(LTInnerPen);
+    if(LTOuterI != -1) DeleteObject32(LTOuterPen);
+    if(RBInnerI != -1) DeleteObject32(RBInnerPen);
+    if(RBOuterI != -1) DeleteObject32(RBOuterPen);
+    MoveToEx32(hdc, SavePoint.x, SavePoint.y, NULL);
+    return retval;
 }
 
 
@@ -309,44 +592,823 @@
 }
 
 
+/************************************************************************
+ *	UITOOLS_MakeSquareRect
+ *
+ * Utility to create a square rectangle and returning the width
+ */
+static int UITOOLS_MakeSquareRect(LPRECT32 src, LPRECT32 dst)
+{
+    int Width  = src->right - src->left;
+    int Height = src->bottom - src->top;
+    int SmallDiam = Width > Height ? Height : Width;
+
+    *dst = *src;
+
+    /* Make it a square box */
+    if(Width < Height)      /* SmallDiam == Width */
+    {
+        dst->top += (Height-Width)/2;
+        dst->bottom = dst->top + SmallDiam;
+    }
+    else if(Width > Height) /* SmallDiam == Height */
+    {
+        dst->left += (Width-Height)/2;
+        dst->right = dst->left + SmallDiam;
+    }
+
+   return SmallDiam;
+}
+
+
+/************************************************************************
+ *	UITOOLS_DFC_ButtonPush
+ *
+ * Draw a push button coming from DrawFrameControl()
+ *
+ * Does a pretty good job in emulating MS behavior. Some quirks are
+ * however there because MS uses a TrueType font (Marlett) to draw
+ * the buttons.
+ */
+static BOOL32 UITOOLS_DFC_ButtonPush(HDC32 dc, LPRECT32 r, UINT32 uFlags)
+{
+    UINT32 edge;
+    RECT32 myr = *r;
+
+    if(uFlags & (DFCS_PUSHED | DFCS_CHECKED | DFCS_FLAT))
+        edge = EDGE_SUNKEN;
+    else
+        edge = EDGE_RAISED;
+
+    if(uFlags & DFCS_CHECKED)
+    {
+        if(uFlags & DFCS_MONO)
+            UITOOLS_DrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST);
+        else
+            UITOOLS_DrawRectEdge(dc, &myr, edge, (uFlags&DFCS_FLAT)|BF_RECT|BF_SOFT|BF_ADJUST);
+
+        if(GetSysColor32(COLOR_BTNHIGHLIGHT) == RGB(255, 255, 255))
+        {
+            HBITMAP32 hbm = CreateBitmap32(8, 8, 1, 1, wPattern_AA55);
+            HBRUSH32 hbsave;
+            HBRUSH32 hb = CreatePatternBrush32(hbm);
+
+            FillRect32(dc, &myr, GetSysColorBrush32(COLOR_BTNFACE));
+            hbsave = (HBRUSH32)SelectObject32(dc, hb);
+            PatBlt32(dc, myr.left, myr.top, myr.right-myr.left, myr.bottom-myr.top, 0x00FA0089);
+            SelectObject32(dc, hbsave);
+            DeleteObject32(hb);
+            DeleteObject32(hbm);
+        }
+        else
+        {
+            FillRect32(dc, &myr, GetSysColorBrush32(COLOR_BTNHIGHLIGHT));
+        }
+    }
+    else
+    {
+        if(uFlags & DFCS_MONO)
+        {
+            UITOOLS_DrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST);
+            FillRect32(dc, &myr, GetSysColorBrush32(COLOR_BTNFACE));
+        }
+        else
+        {
+            UITOOLS_DrawRectEdge(dc, r, edge, (uFlags&DFCS_FLAT) | BF_MIDDLE |BF_SOFT| BF_RECT);
+        }
+    }
+
+    /* Adjust rectangle if asked */
+    if(uFlags & DFCS_ADJUSTRECT)
+    {
+        r->left   += 2;
+        r->right  -= 2;
+        r->top    += 2;
+        r->bottom -= 2;
+    }
+
+    return TRUE;
+}
+
+
+/************************************************************************
+ *	UITOOLS_DFC_ButtonChcek
+ *
+ * Draw a check/3state button coming from DrawFrameControl()
+ *
+ * Does a pretty good job in emulating MS behavior. Some quirks are
+ * however there because MS uses a TrueType font (Marlett) to draw
+ * the buttons.
+ */
+#define DFC_CHECKPOINTSMAX      6
+
+static BOOL32 UITOOLS_DFC_ButtonCheck(HDC32 dc, LPRECT32 r, UINT32 uFlags)
+{
+    RECT32 myr;
+    int SmallDiam = UITOOLS_MakeSquareRect(r, &myr);
+    int BorderShrink = SmallDiam / 16;
+
+    if(BorderShrink < 1) BorderShrink = 1;
+
+    /* FIXME: The FillRect() sequence doesn't work for sizes less than */
+    /* 4 pixels in diameter. Not really a problem but it isn't M$'s */
+    /* 100% equivalent. */
+    if(uFlags & (DFCS_FLAT|DFCS_MONO))
+    {
+        FillRect32(dc, &myr, GetSysColorBrush32(COLOR_WINDOWFRAME));
+        myr.left   += 2 * BorderShrink;
+        myr.right  -= 2 * BorderShrink;
+        myr.top    += 2 * BorderShrink;
+        myr.bottom -= 2 * BorderShrink;
+    }
+    else
+    {
+        FillRect32(dc, &myr, GetSysColorBrush32(COLOR_BTNHIGHLIGHT));
+        myr.right  -= BorderShrink;
+        myr.bottom -= BorderShrink;
+        FillRect32(dc, &myr, GetSysColorBrush32(COLOR_BTNSHADOW));
+        myr.left   += BorderShrink;
+        myr.top    += BorderShrink;
+        FillRect32(dc, &myr, GetSysColorBrush32(COLOR_3DLIGHT));
+        myr.right  -= BorderShrink;
+        myr.bottom -= BorderShrink;
+        FillRect32(dc, &myr, GetSysColorBrush32(COLOR_3DDKSHADOW));
+        myr.left   += BorderShrink;
+        myr.top    += BorderShrink;
+    }
+
+    if(uFlags & (DFCS_INACTIVE|DFCS_PUSHED))
+    {
+        FillRect32(dc, &myr, GetSysColorBrush32(COLOR_BTNFACE));
+    }
+    else if(uFlags & DFCS_CHECKED)
+    {
+        if(GetSysColor32(COLOR_BTNHIGHLIGHT) == RGB(255, 255, 255))
+        {
+            HBITMAP32 hbm = CreateBitmap32(8, 8, 1, 1, wPattern_AA55);
+            HBRUSH32 hbsave;
+            HBRUSH32 hb = CreatePatternBrush32(hbm);
+
+            FillRect32(dc, &myr, GetSysColorBrush32(COLOR_BTNFACE));
+            hbsave = (HBRUSH32)SelectObject32(dc, hb);
+            PatBlt32(dc, myr.left, myr.top, myr.right-myr.left, myr.bottom-myr.top, 0x00FA0089);
+            SelectObject32(dc, hbsave);
+            DeleteObject32(hb);
+            DeleteObject32(hbm);
+        }
+        else
+        {
+            FillRect32(dc, &myr, GetSysColorBrush32(COLOR_BTNHIGHLIGHT));
+        }
+    }
+    else
+    {
+        FillRect32(dc, &myr, GetSysColorBrush32(COLOR_WINDOW));
+    }
+
+    if(uFlags & DFCS_CHECKED)
+    {
+        POINT32 CheckPoints[DFC_CHECKPOINTSMAX];
+        int i;
+        HBRUSH32 hbsave;
+        HPEN32 hp, hpsave;
+
+        /* FIXME: This comes very close to M$'s checkmark, but not */
+        /* exactly... When small or large there is a few pixels */
+        /* shift. Not bad, but could be better :) */
+        UITOOLS_MakeSquareRect(r, &myr);
+        CheckPoints[0].x = myr.left + 253*SmallDiam/1000;
+        CheckPoints[0].y = myr.top  + 345*SmallDiam/1000;
+        CheckPoints[1].x = myr.left + 409*SmallDiam/1000;
+        CheckPoints[1].y = CheckPoints[0].y + (CheckPoints[1].x-CheckPoints[0].x);
+        CheckPoints[2].x = myr.left + 690*SmallDiam/1000;
+        CheckPoints[2].y = CheckPoints[1].y - (CheckPoints[2].x-CheckPoints[1].x);
+        CheckPoints[3].x = CheckPoints[2].x;
+        CheckPoints[3].y = CheckPoints[2].y + 3*SmallDiam/16;
+        CheckPoints[4].x = CheckPoints[1].x;
+        CheckPoints[4].y = CheckPoints[1].y + 3*SmallDiam/16;
+        CheckPoints[5].x = CheckPoints[0].x;
+        CheckPoints[5].y = CheckPoints[0].y + 3*SmallDiam/16;
+
+        i = (uFlags & DFCS_INACTIVE) || (uFlags & 0xff) == DFCS_BUTTON3STATE ? COLOR_BTNSHADOW : COLOR_WINDOWTEXT;
+        hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(i));
+        hp = CreatePen32(PS_SOLID, 0, GetSysColor32(i));
+        hpsave = (HPEN32)SelectObject32(dc, hp);
+        Polygon32(dc, CheckPoints, DFC_CHECKPOINTSMAX);
+        SelectObject32(dc, hpsave);
+        SelectObject32(dc, hbsave);
+        DeleteObject32(hp);
+    }
+    return TRUE;
+}
+
+
+/************************************************************************
+ *	UITOOLS_DFC_ButtonRadio
+ *
+ * Draw a radio/radioimage/radiomask button coming from DrawFrameControl()
+ *
+ * Does a pretty good job in emulating MS behavior. Some quirks are
+ * however there because MS uses a TrueType font (Marlett) to draw
+ * the buttons.
+ */
+static BOOL32 UITOOLS_DFC_ButtonRadio(HDC32 dc, LPRECT32 r, UINT32 uFlags)
+{
+    RECT32 myr;
+    int i;
+    int SmallDiam = UITOOLS_MakeSquareRect(r, &myr);
+    int BorderShrink = SmallDiam / 16;
+    HPEN32 hpsave, hp;
+    HBRUSH32 hbsave;
+    int xe, ye;
+    int xc, yc;
+
+    if(BorderShrink < 1) BorderShrink = 1;
+
+    if((uFlags & 0xff) == DFCS_BUTTONRADIOIMAGE)
+    {
+        FillRect32(dc, r, (HBRUSH32)GetStockObject32(BLACK_BRUSH));
+    }
+
+    xe = myr.left;
+    ye = myr.top  + SmallDiam - SmallDiam/2;
+
+    xc = myr.left + SmallDiam - SmallDiam/2;
+    yc = myr.top  + SmallDiam - SmallDiam/2;
+
+    /* Define bounding box */
+    i = 14*SmallDiam/16;
+    myr.left   = xc - i+i/2;
+    myr.right  = xc + i/2;
+    myr.top    = yc - i+i/2;
+    myr.bottom = yc + i/2;
+
+    if((uFlags & 0xff) == DFCS_BUTTONRADIOMASK)
+    {
+        hbsave = (HBRUSH32)SelectObject32(dc, GetStockObject32(BLACK_BRUSH));
+        Pie32(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
+        SelectObject32(dc, hbsave);
+    }
+    else
+    {
+        if(uFlags & (DFCS_FLAT|DFCS_MONO))
+        {
+            hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_WINDOWFRAME));
+            hpsave = (HPEN32)SelectObject32(dc, hp);
+            hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_WINDOWFRAME));
+            Pie32(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
+            SelectObject32(dc, hbsave);
+            SelectObject32(dc, hpsave);
+            DeleteObject32(hp);
+        }
+        else
+        {
+            hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNHIGHLIGHT));
+            hpsave = (HPEN32)SelectObject32(dc, hp);
+            hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_BTNHIGHLIGHT));
+            Pie32(dc, myr.left, myr.top, myr.right, myr.bottom, myr.left-1, myr.bottom, myr.right-1, myr.top);
+            SelectObject32(dc, hbsave);
+            SelectObject32(dc, hpsave);
+            DeleteObject32(hp);
+
+            hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNSHADOW));
+            hpsave = (HPEN32)SelectObject32(dc, hp);
+            hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_BTNSHADOW));
+            Pie32(dc, myr.left, myr.top, myr.right, myr.bottom, myr.right+1, myr.top, myr.left+1, myr.bottom);
+            SelectObject32(dc, hbsave);
+            SelectObject32(dc, hpsave);
+            DeleteObject32(hp);
+
+            myr.left   += BorderShrink;
+            myr.right  -= BorderShrink;
+            myr.top    += BorderShrink;
+            myr.bottom -= BorderShrink;
+
+            hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_3DLIGHT));
+            hpsave = (HPEN32)SelectObject32(dc, hp);
+            hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_3DLIGHT));
+            Pie32(dc, myr.left, myr.top, myr.right, myr.bottom, myr.left-1, myr.bottom, myr.right-1, myr.top);
+            SelectObject32(dc, hbsave);
+            SelectObject32(dc, hpsave);
+            DeleteObject32(hp);
+
+            hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_3DDKSHADOW));
+            hpsave = (HPEN32)SelectObject32(dc, hp);
+            hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_3DDKSHADOW));
+            Pie32(dc, myr.left, myr.top, myr.right, myr.bottom, myr.right+1, myr.top, myr.left+1, myr.bottom);
+            SelectObject32(dc, hbsave);
+            SelectObject32(dc, hpsave);
+            DeleteObject32(hp);
+        }
+
+        i = 10*SmallDiam/16;
+        myr.left   = xc - i+i/2;
+        myr.right  = xc + i/2;
+        myr.top    = yc - i+i/2;
+        myr.bottom = yc + i/2;
+        i= !(uFlags & (DFCS_INACTIVE|DFCS_PUSHED)) ? COLOR_WINDOW : COLOR_BTNFACE;
+        hp = CreatePen32(PS_SOLID, 0, GetSysColor32(i));
+        hpsave = (HPEN32)SelectObject32(dc, hp);
+        hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(i));
+        Pie32(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
+        SelectObject32(dc, hbsave);
+        SelectObject32(dc, hpsave);
+        DeleteObject32(hp);
+    }
+
+    if(uFlags & DFCS_CHECKED)
+    {
+        i = 6*SmallDiam/16;
+        i = i < 1 ? 1 : i;
+        myr.left   = xc - i+i/2;
+        myr.right  = xc + i/2;
+        myr.top    = yc - i+i/2;
+        myr.bottom = yc + i/2;
+
+        i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_WINDOWTEXT;
+        hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(i));
+        hp = CreatePen32(PS_SOLID, 0, GetSysColor32(i));
+        hpsave = (HPEN32)SelectObject32(dc, hp);
+        Pie32(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
+        SelectObject32(dc, hpsave);
+        SelectObject32(dc, hbsave);
+        DeleteObject32(hp);
+    }
+
+    /* FIXME: M$ has a polygon in the center at relative points: */
+    /* 0.476, 0.476 (times SmallDiam, SmallDiam) */
+    /* 0.476, 0.525 */
+    /* 0.500, 0.500 */
+    /* 0.500, 0.499 */
+    /* when the button is unchecked. The reason for it is unknown. The */
+    /* color is COLOR_BTNHIGHLIGHT, although the polygon gets painted at */
+    /* least 3 times (it looks like a clip-region when you see it happen). */
+    /* I do not really see a reason why this should be implemented. If you */
+    /* have a good reason, let me know. Maybe this is a quirk in the Marlett */
+    /* font. */
+
+    return TRUE;
+}
+
 /***********************************************************************
  *           UITOOLS_DrawFrameButton
  */
 static BOOL32 UITOOLS_DrawFrameButton(HDC32 hdc, LPRECT32 rc, UINT32 uState)
 {
-    fprintf( stdnimp,"DrawFrameButton(%x,%p,%x), empty stub!\n",
-             hdc,rc,uState );
+    switch(uState & 0xff)
+    {
+    case DFCS_BUTTONPUSH:
+        return UITOOLS_DFC_ButtonPush(hdc, rc, uState);
+
+    case DFCS_BUTTONCHECK:
+    case DFCS_BUTTON3STATE:
+        return UITOOLS_DFC_ButtonCheck(hdc, rc, uState);
+
+    case DFCS_BUTTONRADIOIMAGE:
+    case DFCS_BUTTONRADIOMASK:
+    case DFCS_BUTTONRADIO:
+        return UITOOLS_DFC_ButtonRadio(hdc, rc, uState);
+
+    default:
+        fprintf(stdnimp, "UITOOLS_DrawFrameButton: Report this: Invalid button state: 0x%04x\n", uState);
+    }
+
     return FALSE;
 }
 
 /***********************************************************************
  *           UITOOLS_DrawFrameCaption
+ *
+ * Draw caption buttons (win95), coming from DrawFrameControl()
  */
-static BOOL32 UITOOLS_DrawFrameCaption(HDC32 hdc, LPRECT32 rc, UINT32 uState)
+
+static BOOL32 UITOOLS_DrawFrameCaption(HDC32 dc, LPRECT32 r, UINT32 uFlags)
 {
-    fprintf( stdnimp,"DrawFrameCaption(%x,%p,%x), empty stub!\n",
-             hdc,rc,uState );
-    return FALSE;
+    POINT32 Line1[10];
+    POINT32 Line2[10];
+    int Line1N;
+    int Line2N;
+    RECT32 myr;
+    int SmallDiam = UITOOLS_MakeSquareRect(r, &myr)-2;
+    int i;
+    HBRUSH32 hbsave;
+    HPEN32 hpsave, hp;
+    HFONT32 hfsave, hf;
+    int xc = (myr.left+myr.right)/2;
+    int yc = (myr.top+myr.bottom)/2;
+    int edge, move;
+    char str[2] = "?";
+    UINT32 alignsave;
+    int bksave;
+    COLORREF clrsave;
+    SIZE32 size;
+
+    UITOOLS_DFC_ButtonPush(dc, r, uFlags & 0xff00);
+
+    switch(uFlags & 0xff)
+    {
+    case DFCS_CAPTIONCLOSE:
+        edge = 328*SmallDiam/1000;
+        move = 95*SmallDiam/1000;
+        Line1[0].x = Line2[0].x = Line1[1].x = Line2[1].x = xc - edge;
+        Line1[2].y = Line2[5].y = Line1[1].y = Line2[4].y = yc - edge;
+        Line1[3].x = Line2[3].x = Line1[4].x = Line2[4].x = xc + edge;
+        Line1[5].y = Line2[2].y = Line1[4].y = Line2[1].y = yc + edge;
+        Line1[2].x = Line2[2].x = Line1[1].x + move;
+        Line1[0].y = Line2[3].y = Line1[1].y + move;
+        Line1[5].x = Line2[5].x = Line1[4].x - move;
+        Line1[3].y = Line2[0].y = Line1[4].y - move;
+        Line1N = 6;
+        Line2N = 6;
+        break;
+
+    case DFCS_CAPTIONHELP:
+        /* This one breaks the flow */
+        /* FIXME: We need the Marlett font in order to get this right. */
+
+        hf = CreateFont32A(-SmallDiam, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
+                        ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
+                        DEFAULT_QUALITY, FIXED_PITCH|FF_DONTCARE, "System");
+        alignsave = SetTextAlign32(dc, TA_TOP|TA_LEFT);
+        bksave = SetBkMode32(dc, TRANSPARENT);
+        clrsave = GetTextColor32(dc);
+        hfsave = (HFONT32)SelectObject32(dc, hf);
+        GetTextExtentPoint32A(dc, str, 1, &size);
+
+        if(uFlags & DFCS_INACTIVE)
+        {
+            SetTextColor32(dc, GetSysColor32(COLOR_BTNHIGHLIGHT));
+            TextOut32A(dc, xc-size.cx/2+1, yc-size.cy/2+1, str, 1);
+        }
+        SetTextColor32(dc, GetSysColor32(uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
+        TextOut32A(dc, xc-size.cx/2, yc-size.cy/2, str, 1);
+
+        SelectObject32(dc, hfsave);
+        SetTextColor32(dc, clrsave);
+        SetBkMode32(dc, bksave);
+        SetTextAlign32(dc, alignsave);
+        DeleteObject32(hf);
+        return TRUE;
+
+    case DFCS_CAPTIONMIN:
+        Line1[0].x = Line1[3].x = myr.left   +  96*SmallDiam/750+2;
+        Line1[1].x = Line1[2].x = Line1[0].x + 372*SmallDiam/750;
+        Line1[0].y = Line1[1].y = myr.top    + 563*SmallDiam/750+1;
+        Line1[2].y = Line1[3].y = Line1[0].y +  92*SmallDiam/750;
+        Line1N = 4;
+        Line2N = 0;
+        break;
+
+    case DFCS_CAPTIONMAX:
+        edge = 47*SmallDiam/750;
+        Line1[0].x = Line1[5].x = myr.left +  57*SmallDiam/750+3;
+        Line1[0].y = Line1[1].y = myr.top  + 143*SmallDiam/750+1;
+        Line1[1].x = Line1[2].x = Line1[0].x + 562*SmallDiam/750;
+        Line1[5].y = Line1[4].y = Line1[0].y +  93*SmallDiam/750;
+        Line1[2].y = Line1[3].y = Line1[0].y + 513*SmallDiam/750;
+        Line1[3].x = Line1[4].x = Line1[1].x -  edge;
+
+        Line2[0].x = Line2[5].x = Line1[0].x;
+        Line2[3].x = Line2[4].x = Line1[1].x;
+        Line2[1].x = Line2[2].x = Line1[0].x + edge;
+        Line2[0].y = Line2[1].y = Line1[0].y;
+        Line2[4].y = Line2[5].y = Line1[2].y;
+        Line2[2].y = Line2[3].y = Line1[2].y - edge;
+        Line1N = 6;
+        Line2N = 6;
+        break;
+
+    case DFCS_CAPTIONRESTORE:
+        /* FIXME: this one looks bad at small sizes < 15x15 :( */
+        edge = 47*SmallDiam/750;
+        move = 420*SmallDiam/750;
+        Line1[0].x = Line1[9].x = myr.left + 198*SmallDiam/750+2;
+        Line1[0].y = Line1[1].y = myr.top  + 169*SmallDiam/750+1;
+        Line1[6].y = Line1[7].y = Line1[0].y + 93*SmallDiam/750;
+        Line1[7].x = Line1[8].x = Line1[0].x + edge;
+        Line1[1].x = Line1[2].x = Line1[0].x + move;
+        Line1[5].x = Line1[6].x = Line1[1].x - edge;
+        Line1[9].y = Line1[8].y = Line1[0].y + 187*SmallDiam/750;
+        Line1[2].y = Line1[3].y = Line1[0].y + 327*SmallDiam/750;
+        Line1[4].y = Line1[5].y = Line1[2].y - edge;
+        Line1[3].x = Line1[4].x = Line1[2].x - 140*SmallDiam/750;
+
+        Line2[1].x = Line2[2].x = Line1[3].x;
+        Line2[7].x = Line2[8].x = Line2[1].x - edge;
+        Line2[0].x = Line2[9].x = Line2[3].x = Line2[4].x = Line2[1].x - move;
+        Line2[5].x = Line2[6].x = Line2[0].x + edge;
+        Line2[0].y = Line2[1].y = Line1[9].y;
+        Line2[4].y = Line2[5].y = Line2[8].y = Line2[9].y = Line2[0].y + 93*SmallDiam/750;
+        Line2[2].y = Line2[3].y = Line2[0].y + 327*SmallDiam/750;
+        Line2[6].y = Line2[7].y = Line2[2].y - edge;
+        Line1N = 10;
+        Line2N = 10;
+        break;
+
+    default:
+        fprintf(stdnimp, "UITOOLS_DrawFrameCaption: Report this: Invalid caption; flags: 0x%04x\n", uFlags);
+        return FALSE;
+    }
+
+    /* Here the drawing takes place */
+    if(uFlags & DFCS_INACTIVE)
+    {
+        /* If we have an inactive button, then you see a shadow */
+        hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_BTNHIGHLIGHT));
+        hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNHIGHLIGHT));
+        hpsave = (HPEN32)SelectObject32(dc, hp);
+        Polygon32(dc, Line1, Line1N);
+        if(Line2N > 0)
+            Polygon32(dc, Line2, Line2N);
+        SelectObject32(dc, hpsave);
+        SelectObject32(dc, hbsave);
+        DeleteObject32(hp);
+    }
+
+    /* Correct for the shadow shift */
+    for(i = 0; i < Line1N; i++)
+    {
+        Line1[i].x--;
+        Line1[i].y--;
+    }
+    for(i = 0; i < Line2N; i++)
+    {
+        Line2[i].x--;
+        Line2[i].y--;
+    }
+
+    /* Make the final picture */
+    if(uFlags & DFCS_INACTIVE)
+    {
+        hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_BTNSHADOW));
+        hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNSHADOW));
+    }
+    else
+    {
+        hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_BTNTEXT));
+        hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNTEXT));
+    }
+    hpsave = (HPEN32)SelectObject32(dc, hp);
+    Polygon32(dc, Line1, Line1N);
+    if(Line2N > 0)
+        Polygon32(dc, Line2, Line2N);
+    SelectObject32(dc, hpsave);
+    SelectObject32(dc, hbsave);
+    DeleteObject32(hp);
+
+    return TRUE;
 }
 
-/***********************************************************************
- *           UITOOLS_DrawFrameMenu
+
+/************************************************************************
+ *      UITOOLS_DrawFrameScroll
+ *
+ * Draw a scroll-bar control coming from DrawFrameControl()
  */
-static BOOL32 UITOOLS_DrawFrameMenu(HDC32 hdc, LPRECT32 rc, UINT32 uState)
+static BOOL32 UITOOLS_DrawFrameScroll(HDC32 dc, LPRECT32 r, UINT32 uFlags)
 {
-    fprintf( stdnimp,"DrawFrameMenu32(%x,%p,%x), empty stub!\n",
-             hdc,rc,uState );
-    return FALSE;
+    POINT32 Line[4];
+    RECT32 myr;
+    int SmallDiam = UITOOLS_MakeSquareRect(r, &myr) - 2;
+    int i;
+    HBRUSH32 hbsave, hb, hb2;
+    HPEN32 hpsave, hp, hp2;
+    int tri = 310*SmallDiam/1000;
+    int d46, d93;
+
+    switch(uFlags & 0xff)
+    {
+    case DFCS_SCROLLCOMBOBOX:
+    case DFCS_SCROLLDOWN:
+        Line[2].x = myr.left + 470*SmallDiam/1000 + 2;
+        Line[2].y = myr.top  + 687*SmallDiam/1000 + 1;
+        Line[0].x = Line[2].x - tri;
+        Line[1].x = Line[2].x + tri;
+        Line[0].y = Line[1].y = Line[2].y - tri;
+        break;
+
+    case DFCS_SCROLLUP:
+        Line[2].x = myr.left + 470*SmallDiam/1000 + 2;
+        Line[2].y = myr.top  + 313*SmallDiam/1000 + 1;
+        Line[0].x = Line[2].x - tri;
+        Line[1].x = Line[2].x + tri;
+        Line[0].y = Line[1].y = Line[2].y + tri;
+        break;
+
+    case DFCS_SCROLLLEFT:
+        Line[2].x = myr.left + 313*SmallDiam/1000 + 1;
+        Line[2].y = myr.top  + 470*SmallDiam/1000 + 2;
+        Line[0].y = Line[2].y - tri;
+        Line[1].y = Line[2].y + tri;
+        Line[0].x = Line[1].x = Line[2].x + tri;
+        break;
+
+    case DFCS_SCROLLRIGHT:
+        Line[2].x = myr.left + 687*SmallDiam/1000 + 1;
+        Line[2].y = myr.top  + 470*SmallDiam/1000 + 2;
+        Line[0].y = Line[2].y - tri;
+        Line[1].y = Line[2].y + tri;
+        Line[0].x = Line[1].x = Line[2].x - tri;
+        break;
+
+    case DFCS_SCROLLSIZEGRIP:
+        /* This one breaks the flow... */
+        UITOOLS_DrawRectEdge(dc, r, EDGE_BUMP, BF_MIDDLE | ((uFlags&(DFCS_MONO|DFCS_FLAT)) ? BF_MONO : 0));
+        hpsave = (HPEN32)SelectObject32(dc, GetStockObject32(NULL_PEN));
+        hbsave = (HBRUSH32)SelectObject32(dc, GetStockObject32(NULL_BRUSH));
+        if(uFlags & (DFCS_MONO|DFCS_FLAT))
+        {
+            hp = hp2 = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_WINDOWFRAME));
+            hb = hb2 = GetSysColorBrush32(COLOR_WINDOWFRAME);
+        }
+        else
+        {
+            hp  = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNHIGHLIGHT));
+            hp2 = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNSHADOW));
+            hb  = GetSysColorBrush32(COLOR_BTNHIGHLIGHT);
+            hb2 = GetSysColorBrush32(COLOR_BTNSHADOW);
+        }
+        Line[0].x = Line[1].x = r->right-1;
+        Line[2].y = Line[3].y = r->bottom-1;
+        d46 = 46*SmallDiam/750;
+        d93 = 93*SmallDiam/750;
+
+        i = 586*SmallDiam/750;
+        Line[0].y = r->bottom - i - 1;
+        Line[3].x = r->right - i - 1;
+        Line[1].y = Line[0].y + d46;
+        Line[2].x = Line[3].x + d46;
+        SelectObject32(dc, hb);
+        SelectObject32(dc, hp);
+        Polygon32(dc, Line, 4);
+
+        Line[1].y++; Line[2].x++;
+        Line[0].y = Line[1].y + d93;
+        Line[3].x = Line[2].x + d93;
+        SelectObject32(dc, hb2);
+        SelectObject32(dc, hp2);
+        Polygon32(dc, Line, 4);
+
+        i = 398*SmallDiam/750;
+        Line[0].y = r->bottom - i - 1;
+        Line[3].x = r->right - i - 1;
+        Line[1].y = Line[0].y + d46;
+        Line[2].x = Line[3].x + d46;
+        SelectObject32(dc, hb);
+        SelectObject32(dc, hp);
+        Polygon32(dc, Line, 4);
+
+        Line[1].y++; Line[2].x++;
+        Line[0].y = Line[1].y + d93;
+        Line[3].x = Line[2].x + d93;
+        SelectObject32(dc, hb2);
+        SelectObject32(dc, hp2);
+        Polygon32(dc, Line, 4);
+
+        i = 210*SmallDiam/750;
+        Line[0].y = r->bottom - i - 1;
+        Line[3].x = r->right - i - 1;
+        Line[1].y = Line[0].y + d46;
+        Line[2].x = Line[3].x + d46;
+        SelectObject32(dc, hb);
+        SelectObject32(dc, hp);
+        Polygon32(dc, Line, 4);
+
+        Line[1].y++; Line[2].x++;
+        Line[0].y = Line[1].y + d93;
+        Line[3].x = Line[2].x + d93;
+        SelectObject32(dc, hb2);
+        SelectObject32(dc, hp2);
+        Polygon32(dc, Line, 4);
+
+        SelectObject32(dc, hpsave);
+        SelectObject32(dc, hbsave);
+        DeleteObject32(hp);
+        DeleteObject32(hp2);
+        return TRUE;
+
+    default:
+        fprintf(stdnimp, "UITOOLS_DrawFrameScroll: Report this: Invalid scroll; flags: 0x%04x\n", uFlags);
+        return FALSE;
+    }
+
+    /* Here do the real scroll-bar controls end up */
+    UITOOLS_DFC_ButtonPush(dc, r, uFlags & 0xff00);
+
+    if(uFlags & DFCS_INACTIVE)
+    {
+        hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_BTNHIGHLIGHT));
+        hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNHIGHLIGHT));
+        hpsave = (HPEN32)SelectObject32(dc, hp);
+        Polygon32(dc, Line, 3);
+        SelectObject32(dc, hpsave);
+        SelectObject32(dc, hbsave);
+        DeleteObject32(hp);
+    }
+
+    for(i = 0; i < 3; i++)
+    {
+        Line[i].x--;
+        Line[i].y--;
+    }
+
+    if(uFlags & DFCS_INACTIVE)
+    {
+        hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_BTNSHADOW));
+        hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNSHADOW));
+    }
+    else
+    {
+        hbsave = (HBRUSH32)SelectObject32(dc, GetSysColorBrush32(COLOR_BTNTEXT));
+        hp = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNTEXT));
+    }
+    hpsave = (HPEN32)SelectObject32(dc, hp);
+    Polygon32(dc, Line, 3);
+    SelectObject32(dc, hpsave);
+    SelectObject32(dc, hbsave);
+    DeleteObject32(hp);
+
+    return TRUE;
 }
 
-/***********************************************************************
- *           UITOOLS_DrawFrameScroll
+/************************************************************************
+ *      UITOOLS_DrawFrameMenu
+ *
+ * Draw a menu control coming from DrawFrameControl()
  */
-static BOOL32 UITOOLS_DrawFrameScroll(HDC32 hdc, LPRECT32 rc, UINT32 uState)
+static BOOL32 UITOOLS_DrawFrameMenu(HDC32 dc, LPRECT32 r, UINT32 uFlags)
 {
-    fprintf( stdnimp,"DrawFrameScroll32(%x,%p,%x), empty stub!\n",
-             hdc,rc,uState );
-    return FALSE;
+    POINT32 Points[6];
+    RECT32 myr;
+    int SmallDiam = UITOOLS_MakeSquareRect(r, &myr);
+    int i;
+    HBRUSH32 hbsave;
+    HPEN32 hpsave;
+    int xe, ye;
+    int xc, yc;
+    BOOL32 retval = TRUE;
+
+    /* Using black and white seems to be utterly wrong, but win95 doesn't */
+    /* use anything else. I think I tried all sys-colors to change things */
+    /* without luck. It seems as if this behavior is inherited from the */
+    /* win31 DFC() implementation... (you remember, B/W menus). */
+
+    FillRect32(dc, r, (HBRUSH32)GetStockObject32(WHITE_BRUSH));
+
+    hbsave = (HBRUSH32)SelectObject32(dc, GetStockObject32(BLACK_BRUSH));
+    hpsave = (HPEN32)SelectObject32(dc, GetStockObject32(BLACK_PEN));
+
+    switch(uFlags & 0xff)
+    {
+    case DFCS_MENUARROW:
+        i = 187*SmallDiam/750;
+        Points[2].x = myr.left + 468*SmallDiam/750;
+        Points[2].y = myr.top  + 352*SmallDiam/750+1;
+        Points[0].y = Points[2].y - i;
+        Points[1].y = Points[2].y + i;
+        Points[0].x = Points[1].x = Points[2].x - i;
+        Polygon32(dc, Points, 3);
+        break;
+
+    case DFCS_MENUBULLET:
+        xe = myr.left;
+        ye = myr.top  + SmallDiam - SmallDiam/2;
+        xc = myr.left + SmallDiam - SmallDiam/2;
+        yc = myr.top  + SmallDiam - SmallDiam/2;
+        i = 234*SmallDiam/750;
+        i = i < 1 ? 1 : i;
+        myr.left   = xc - i+i/2;
+        myr.right  = xc + i/2;
+        myr.top    = yc - i+i/2;
+        myr.bottom = yc + i/2;
+        Pie32(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
+        break;
+
+    case DFCS_MENUCHECK:
+        Points[0].x = myr.left + 253*SmallDiam/1000;
+        Points[0].y = myr.top  + 445*SmallDiam/1000;
+        Points[1].x = myr.left + 409*SmallDiam/1000;
+        Points[1].y = Points[0].y + (Points[1].x-Points[0].x);
+        Points[2].x = myr.left + 690*SmallDiam/1000;
+        Points[2].y = Points[1].y - (Points[2].x-Points[1].x);
+        Points[3].x = Points[2].x;
+        Points[3].y = Points[2].y + 3*SmallDiam/16;
+        Points[4].x = Points[1].x;
+        Points[4].y = Points[1].y + 3*SmallDiam/16;
+        Points[5].x = Points[0].x;
+        Points[5].y = Points[0].y + 3*SmallDiam/16;
+        Polygon32(dc, Points, 6);
+        break;
+
+    default:
+        fprintf(stdnimp, "UITOOLS_DrawFrameMenu: Report this: Invalid menu; flags: 0x%04x\n", uFlags);
+        retval = FALSE;
+        break;
+    }
+
+    SelectObject32(dc, hpsave);
+    SelectObject32(dc, hbsave);
+    return retval;
 }
 
 
@@ -372,6 +1434,10 @@
 BOOL32 WINAPI DrawFrameControl32( HDC32 hdc, LPRECT32 rc, UINT32 uType,
                                   UINT32 uState )
 {
+    /* Win95 doesn't support drawing in other mapping modes */
+    if(GetMapMode32(hdc) != MM_TEXT)
+        return FALSE;
+        
     switch(uType)
     {
     case DFC_BUTTON:
diff --git a/debugger/info.c b/debugger/info.c
index f5c4d4c..a1cb378 100644
--- a/debugger/info.c
+++ b/debugger/info.c
@@ -141,7 +141,7 @@
 "  delete display <disnum>\n",
 
 "Wine-specific commands:",
-"  mode [16,32]                           walk [wnd,class,queue] <handle>",
+"  mode [16,32]                           walk [wnd,class,queue,module]",
 "  info (see 'help info' for options)\n",
 
 "The 'x' command accepts repeat counts and formats (including 'i') in the",
@@ -176,13 +176,13 @@
 "  info display         Shows auto-display expressions in use",
 "  info locals          Displays values of all local vars for current frame",
 "  info maps            Dumps all virtual memory mappings",
-"  info module          Displays information about all modules",
-"  info queue <handle>  Dumps queue information",
+"  info module <handle> Displays internal module state",
+"  info queue <handle>  Displays internal queue state",
 "  info reg             Displays values in all registers at top of stack",
 "  info segments        Dumps information about all known segments",
 "  info share           Dumps information about shared libraries",
 "  info stack           Dumps information about top of stack",
-"  info wnd <handle>    Dumps information about all windows",
+"  info wnd <handle>    Displays internal window state",
 "",
 NULL
 };
diff --git a/documentation/Makefile.in b/documentation/Makefile.in
index fe1be2b..6026158 100644
--- a/documentation/Makefile.in
+++ b/documentation/Makefile.in
@@ -22,6 +22,10 @@
 
 all: $(INFOFILES) $(DVIFILES)
 
+info: $(INFOFILES)
+
+dvi: $(DVIFILES)
+
 @MAKE_RULES@
 
 $(INFOFILES): $(SOURCES)
@@ -34,13 +38,17 @@
 	$(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:: 
 	$(INSTALL_DATA) $(SRCDIR)/wine.man $(mandir)/wine$(manext)
 
+# Not done by default because of makeinfo bugs
+install_info: $(INFOFILES)
+	for i in $(INFOFILES); do $(INSTALL_DATA) $$i $(infodir)/$$i; done
+
 clean::
 	$(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
+	$(RM) -r man3w
 
 ### Dependencies:
diff --git a/documentation/README.documentation b/documentation/README.documentation
new file mode 100644
index 0000000..6a91dc6
--- /dev/null
+++ b/documentation/README.documentation
@@ -0,0 +1,122 @@
+
+			Wine Documentation README
+
+
+Wine Man Page
+
+  The man page for the wine emulator is in this directory. It is installed 
+by 'make install'.
+
+Wine Reference Manual
+
+  Texinfo source for preliminary comprehensive documentation is in
+this directory.  Use 'make info' in this directory to generate the GNU
+info version, 'make dvi' to generate the DVI version (hit 'r' to
+ignore errors), or 'make all' for both. It is no longer installed by
+default.
+
+Wine API documentation
+
+  Do a 'make manpages' in the Wine toplevel directory to generate the
+API manpages from the Wine source, or 'make man' in any source
+subdirectory to generate manpages from only that directory. The
+manpages will be deposited in [documentation/man3w].  You will need
+c2man, available as source from http://www.debian.org/ and other
+places. Apply the patch included at the end of this file for improved
+terse description formatting.  The man pages are not installed
+automatically.
+
+Other READMEs
+
+  Other informational files are in this directory as well as scattered
+through the source tree.
+
+Other resources:
+
+  Usenet: news:comp.emulators.ms-windows.wine
+  WWW:    http://www.winehq.com/
+
+
+Writing Wine API Documentation
+
+To improve the documentation of the Wine API, just add comments to the
+existing source. For example,
+
+/******************************************************************
+ *         PlayMetaFile32 (GDI32.265) Render metafile to device
+ *
+ *    The metafile is rendered in the device context specified by hdc.
+ *
+ *  RETURNS
+ *
+ *    Always returns TRUE.
+ *
+ * FIXME
+ *    Wine metafiles are not 100% binary compatible with Microsoft Windows
+ *    metafiles.
+ */
+BOOL32 WINAPI PlayMetaFile32(
+        HDC32 hdc, /* handle of device context in which to render metafile */
+        HMETAFILE32 hmf /* metafile handle */
+) {
+
+becomes, after processing with c2man and nroff -man,
+
+
+PlayMetaFile32(3w)                             PlayMetaFile32(3w)
+
+
+NAME
+       PlayMetaFile32   -   PlayMetaFile32   (GDI32.265)   Render
+       metafile to device
+
+SYNOPSIS
+       BOOL32 PlayMetaFile32
+       (
+            HDC32 hdc,
+            HMETAFILE32 hmf
+       );
+
+PARAMETERS
+       HDC32 hdc
+              Handle  of  device  context  in  which  to   render
+              metafile.
+
+       HMETAFILE32 hmf
+              Metafile handle.
+
+DESCRIPTION
+       The  metafile  is rendered in the device context specified
+       by hdc.
+
+RETURNS
+       Always returns TRUE.
+
+FIXME
+       Wine  metafiles  are  not  100%  binary  compatible   with
+       Microsoft Windows metafiles.
+
+----------------------------------------------------------------
+Patch for c2man:
+
+diff -u c2man-2.41.orig/manpage.c c2man-2.41/manpage.c
+--- c2man-2.41.orig/manpage.c	Tue Apr 23 21:13:44 1996
++++ c2man-2.41/manpage.c	Thu Dec 18 13:20:08 1997
+@@ -585,10 +585,15 @@
+ 		    const char *endterse, *afterdash = skipdash(start_line);
+ 
+ 		    /* find the end of the terse comment */
+-		    while (*c && *c != '.' && *c != '\n')
++		    while (*c && *c != '\n')
++		    {
+ 			c++;
++		      /* '.' ends terse description only if it ends sentence */
++			if (*(c-1)=='.' && *c && isspace(*c)) 
++			  break;
++		    }
+ 
+-		    endterse = *c == '.' ? c+1 : c;
++		    endterse = c;
+ 		    *terse = alloc_string(
+ 			afterdash < endterse ? afterdash : start_line,
+ 			endterse);
diff --git a/documentation/how-to-port b/documentation/how-to-port
new file mode 100644
index 0000000..5800f92
--- /dev/null
+++ b/documentation/how-to-port
@@ -0,0 +1,135 @@
+What is this?
+------------
+
+This note is a short description of
+
+* How to port Wine to your favourite operating system
+* Why you probably shouldn't use "#ifdef MyOS"
+* What to do instead.
+
+This document does not say a thing about how to port Wine to non-386
+operating systems, though.  You would need a CPU emulator.  Let's get
+Wine into a better shape on 386 first, OK?
+
+
+
+
+Why "#ifdef MyOS" is probably a mistake.
+---------------------------------------
+
+Operating systems change.  Maybe yours doesn't have the "foo.h"
+header, but maybe a future version will have it.  If you want
+to "#include <foo.h>", it doesn't matter what operating system
+you are using; it only matters whether "foo.h" is there.
+
+Furthermore, operating systems change names or "fork" into
+several ones.  An "#ifdef MyOs" will break over time.
+
+If you use the feature of Autoconf, the Gnu auto-configuration
+utility wisely, you will help future porters automatically
+because your changes will test for _features_, not names of
+operating systems.  A feature can be many things:
+
+* existance of a header file
+* existance of a library function
+* existance of libraries
+* bugs in header files, library functions, the compiler, ...
+* (you name it)
+
+You will need Gnu Autoconf, which you can get from your
+friendly Gnu mirror.  This program takes Wine's "configure.in"
+file and produces a "configure" shell script that users use to
+configure Wine to their system.
+
+There _are_ exceptions to the "avoid #ifdef MyOS" rule.  Wine,
+for example, needs the internals of the signal stack -- that
+cannot easily be described in terms of features.
+
+Let's now turn to specific porting problems and how to solve
+them.
+
+
+
+MyOS doesn't have the `foo.h' header!
+------------------------------------
+
+This first step is to make Autoconf check for this header.
+In configure.in you add a segment like this in the section
+that checks for header files (search for "header files"):
+
+  AC_CHECK_HEADER(foo.h, AC_DEFINE(HAVE_FOO_H))
+
+If your operating system supports a header file with the
+same contents but a different name, say bar.h, add a check
+for that also.
+
+Now you can change
+
+  #include <foo.h>
+
+to
+
+  #ifdef HAVE_FOO_H
+  #include <foo.h>
+  #elif defined (HAVE_BAR_H)
+  #include <bat.h>
+  #endif
+
+If your system doesn't have a corresponding header file even
+though it has the library functions being used, you might
+have to add an "#else" section to the conditional.  Avoid
+this if you can.
+
+You will also need to add "#undef HAVE_FOO_H" (etc.) to
+include/config.h.in
+
+Finish up with "make configure" and "./configure".
+
+
+MyOS doesn't have the `bar' function!
+------------------------------------
+
+A typical example of this is the `memmove'.  To solve this
+problem you would add `memmove' to the list of functions
+that Autoconf checks for.  In configure.in you search for
+AC_CHECK_FUNCS and add `memmove'.  (You will notice that
+someone already did this for this particular function.)
+
+Secondly, you will also need to add "#undef HAVE_BAR"
+to include/config.h.in
+
+The next step depends on the nature of the missing function.
+
+Case 1: It's easy to write a complete emulation of the
+  function.  (`memmove' belongs to this case.)
+
+  You add your emulation in misc/port.c surrounded by
+  "#ifndef HAVE_MEMMOVE" and "#endif".
+
+  You might have to add a prototype for your function.  If so,
+  include/miscemu.h might be the place.  Don't forget to protect
+  that definition by "#ifndef HAVE_MEMMOVE" and "#endif" also!
+
+Case 2: A general emulation is hard, but Wine is only using
+  a special case.
+
+  An example is the various "wait" calls used in SIGNAL_child
+  from loader/signal.c.  Here we have a multi-branch case on
+  features:
+
+    #ifdef HAVE_THIS
+    ...
+    #elif defined (HAVE_THAT)
+    ...
+    #elif defined (HAVE_SOMETHING_ELSE)
+    ...
+    #endif
+
+  Note that this is very different from testing on operating
+  systems.  If a new version of your operating systems comes
+  out and adds a new function, this code will magically start
+  using it.
+
+Finish up with "make configure" and "./configure".
+
+
diff --git a/files/dos_fs.c b/files/dos_fs.c
index 2ace4e0..5cd8e76 100644
--- a/files/dos_fs.c
+++ b/files/dos_fs.c
@@ -8,6 +8,7 @@
 #include <sys/types.h>
 #include <ctype.h>
 #include <dirent.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <string.h>
 #include <stdlib.h>
@@ -373,15 +374,15 @@
 #ifdef VFAT_IOCTL_READDIR_BOTH
     if (dir->fd != -1)
     {
-        if (ioctl( dir->fd, VFAT_IOCTL_READDIR_BOTH, (long)dir->dirent ) == -1)
-            return FALSE;
-        if (!dir->dirent[0].d_reclen) return FALSE;
-        if (!DOSFS_ToDosFCBFormat( dir->dirent[0].d_name, dir->short_name ))
-            dir->short_name[0] = '\0';
-        *short_name = dir->short_name;
-        if (dir->dirent[1].d_name[0]) *long_name = dir->dirent[1].d_name;
-        else *long_name = dir->dirent[0].d_name;
-        return TRUE;
+        if (ioctl( dir->fd, VFAT_IOCTL_READDIR_BOTH, (long)dir->dirent ) != -1) {
+	    if (!dir->dirent[0].d_reclen) return FALSE;
+	    if (!DOSFS_ToDosFCBFormat( dir->dirent[0].d_name, dir->short_name ))
+		dir->short_name[0] = '\0';
+	    *short_name = dir->short_name;
+	    if (dir->dirent[1].d_name[0]) *long_name = dir->dirent[1].d_name;
+	    else *long_name = dir->dirent[0].d_name;
+	    return TRUE;
+	}
     }
 #endif  /* VFAT_IOCTL_READDIR_BOTH */
 
@@ -518,8 +519,8 @@
 
     if (!(dir = DOSFS_OpenDir( path )))
     {
-        dprintf_dosfs( stddeb, "DOSFS_FindUnixName(%s,%s): can't open dir\n",
-                       path, name );
+        dprintf_dosfs( stddeb, "DOSFS_FindUnixName(%s,%s): can't open dir: %s\n",
+                       path, name, strerror(errno) );
         return FALSE;
     }
 
@@ -853,16 +854,18 @@
     p = buffer;
     *p++ = 'A' + drive;
     *p++ = ':';
-    if (IS_END_OF_NAME(*name))  /* Absolute path */
+    if (IS_END_OF_NAME(*name) && (*name))  /* Absolute path */
     {
         while ((*name == '\\') || (*name == '/')) name++;
     }
-    else  /* Relative path */
+    else  /* Relative path or empty path */
     {
         *p++ = '\\';
         lstrcpyn32A( p, DRIVE_GetDosCwd(drive), sizeof(buffer) - 3 );
         if (*p) p += strlen(p); else p--;
     }
+    if (!*name) /* empty path */
+      *p++ = '\\';
     *p = '\0';
 
     while (*name)
diff --git a/files/drive.c b/files/drive.c
index f874df8..0fd582d 100644
--- a/files/drive.c
+++ b/files/drive.c
@@ -653,6 +653,57 @@
 
 
 /***********************************************************************
+ *           GetDiskFreeSpaceEx32A   (KERNEL32.871)
+ */
+BOOL32 WINAPI GetDiskFreeSpaceEx32A( LPCSTR root,
+				     LPULARGE_INTEGER avail,
+				     LPULARGE_INTEGER total,
+				     LPULARGE_INTEGER totalfree)
+{
+    int	drive;
+    DWORD size,available;
+
+    if (!root) drive = DRIVE_GetCurrentDrive();
+    else
+    {
+        if ((root[1]) && ((root[1] != ':') || (root[2] != '\\')))
+        {
+            fprintf( stderr, "GetDiskFreeSpaceExA: invalid root '%s'\n",
+		     root );
+            return FALSE;
+        }
+        drive = toupper(root[0]) - 'A';
+    }
+    if (!DRIVE_GetFreeSpace(drive, &size, &available)) return FALSE;
+    /*FIXME: Do we have the number of bytes available to the user? */
+    avail->HighPart = total->HighPart = 0;
+    avail->LowPart = available;
+    total->LowPart = size;
+    if(totalfree)
+      {
+	totalfree->HighPart =0;
+	totalfree->LowPart=  available;
+      }
+    return TRUE;
+}
+
+/***********************************************************************
+ *           GetDiskFreeSpaceEx32W   (KERNEL32.873)
+ */
+BOOL32 WINAPI GetDiskFreeSpaceEx32W( LPCWSTR root, LPULARGE_INTEGER avail,
+				     LPULARGE_INTEGER total,
+				     LPULARGE_INTEGER  totalfree)
+{
+    LPSTR xroot;
+    BOOL32 ret;
+
+    xroot = HEAP_strdupWtoA( GetProcessHeap(), 0, root);
+    ret = GetDiskFreeSpaceEx32A( xroot, avail, total, totalfree);
+    HeapFree( GetProcessHeap(), 0, xroot );
+    return ret;
+}
+
+/***********************************************************************
  *           GetDriveType16   (KERNEL.136)
  */
 UINT16 WINAPI GetDriveType16( UINT16 drive )
diff --git a/files/file.c b/files/file.c
index cdbbe55..10380e8 100644
--- a/files/file.c
+++ b/files/file.c
@@ -147,7 +147,7 @@
     int save_errno = errno; /* errno gets overwritten by printf */
 
     dprintf_file(stddeb, "FILE_SetDosError: errno = %d %s\n", errno,
-		 sys_errlist[errno] );
+		 strerror(errno) );
     switch (save_errno)
     {
     case EAGAIN:
@@ -531,7 +531,7 @@
     char temppath[144];
 
     if (!(drive & ~TF_FORCEDRIVE)) /* drive 0 means current default drive */
-        drive |= DRIVE_GetCurrentDrive();
+        drive |= DRIVE_GetCurrentDrive() + 'A';
 
     if ((drive & TF_FORCEDRIVE) &&
         !DRIVE_IsValid( toupper(drive & ~TF_FORCEDRIVE) - 'A' ))
@@ -542,12 +542,17 @@
     }
 
     if (drive & TF_FORCEDRIVE)
-        sprintf(temppath,"%c:", drive & ~TF_FORCEDRIVE );
+    {
+        sprintf( temppath, "%c:\\", drive & ~TF_FORCEDRIVE );
+	lstrcpyn32A( temppath + 3,
+                     DRIVE_GetDosCwd( toupper(drive & ~TF_FORCEDRIVE) - 'A'),
+                     129 );
+    }
     else
     {
         GetTempPath32A( 132, temppath );
-        strcat( temppath, "\\" );
     }
+    strcat( temppath, "\\" );
     return (UINT16)GetTempFileName32A( temppath, prefix, unique, buffer );
 }
 
@@ -1603,6 +1608,8 @@
   /* check if lock overlaps a current lock for the same file */
   for (curr = locks; curr; curr = curr->next) {
     if (strcmp(curr->unix_name, file->unix_name) == 0) {
+      if ((f->l_start == curr->base) && (f->l_len == curr->len))
+	return TRUE;/* region is identic */
       if ((f->l_start < (curr->base + curr->len)) &&
 	  ((f->l_start + f->l_len) > curr->base)) {
 	/* region overlaps */
diff --git a/files/profile.c b/files/profile.c
index 875a590..545049d 100644
--- a/files/profile.c
+++ b/files/profile.c
@@ -942,6 +942,8 @@
                                          LPCSTR def_val, LPSTR buffer,
                                          INT32 len, LPCSTR filename )
 {
+    if (!filename) 
+	filename = "win.ini";
     if (PROFILE_Open( filename ))
         return PROFILE_GetString( section, entry, def_val, buffer, len );
     lstrcpyn32A( buffer, def_val, len );
@@ -1021,6 +1023,27 @@
     return res;
 }
 
+/***********************************************************************
+ *           WritePrivateProfileSection32A   (KERNEL32)
+ */
+BOOL32 WINAPI WritePrivateProfileSection32A( LPCSTR section, 
+                                            LPCSTR string, LPCSTR filename )
+{
+    char *p =(char*)string;
+
+    fprintf( stdnimp,"WritePrivateProfileSection32A empty stup\n");
+    if (debugging_profile) {
+      fprintf(stddeb,"file(%s) => [%s]\n", filename,section);
+      while (*(p+1)) {
+	fprintf(stddeb,"%s\n",p);
+        p += strlen(p);
+	p += 1;
+      }
+    }
+    
+    return FALSE;
+}
+
 
 /***********************************************************************
  *           WriteOutProfiles   (KERNEL.315)
diff --git a/graphics/Makefile.in b/graphics/Makefile.in
index 5912d90..3784c52 100644
--- a/graphics/Makefile.in
+++ b/graphics/Makefile.in
@@ -7,12 +7,14 @@
 
 C_SRCS = \
 	bitblt.c \
+	cache.c \
 	driver.c \
 	env.c \
 	escape.c \
 	fontengine.c \
 	mapping.c \
 	painting.c \
+	path.c \
 	wing.c
 
 all: $(MODULE).o
diff --git a/graphics/cache.c b/graphics/cache.c
new file mode 100644
index 0000000..5d0f184
--- /dev/null
+++ b/graphics/cache.c
@@ -0,0 +1,41 @@
+/*
+ * Wine internally cached objects to speedup some things and prevent 
+ * infinite duplication of trivial code and data. 
+ * 
+ * Copyright 1997 Bertho A. Stultiens
+ *
+ */
+
+#include "windows.h"
+#include "cache.h"
+
+static const WORD wPattern55AA[] =
+{ 
+    0x5555, 0xaaaa, 0x5555, 0xaaaa,
+    0x5555, 0xaaaa, 0x5555, 0xaaaa
+};
+
+static HBRUSH32  hPattern55AABrush = 0;
+static HBITMAP32 hPattern55AABitmap = 0;
+
+
+/*********************************************************************
+ *	CACHE_GetPattern55AABrush
+ */
+HBRUSH32 CACHE_GetPattern55AABrush(void)
+{
+    if (!hPattern55AABrush)
+        hPattern55AABrush = CreatePatternBrush32(CACHE_GetPattern55AABitmap());
+    return hPattern55AABrush;
+}
+
+
+/*********************************************************************
+ *	CACHE_GetPattern55AABitmap
+ */
+HBITMAP32 CACHE_GetPattern55AABitmap(void)
+{
+    if (!hPattern55AABitmap)
+        hPattern55AABitmap = CreateBitmap32( 8, 8, 1, 1, wPattern55AA );
+    return hPattern55AABitmap;
+}
diff --git a/graphics/metafiledrv/init.c b/graphics/metafiledrv/init.c
index b187bce..f60fe08 100644
--- a/graphics/metafiledrv/init.c
+++ b/graphics/metafiledrv/init.c
@@ -12,15 +12,13 @@
 #include "stddebug.h"
 #include "debug.h"
 
-static BOOL32 MFDRV_DeleteDC( DC *dc );
-
 static const DC_FUNCTIONS MFDRV_Funcs =
 {
     MFDRV_Arc,                       /* pArc */
     MFDRV_BitBlt,                    /* pBitBlt */
     MFDRV_Chord,                     /* pChord */
-    NULL,                            /* pCreateDC */
-    MFDRV_DeleteDC,                  /* pDeleteDC */
+    NULL, /* no implementation */    /* pCreateDC */
+    NULL, /* no implementation */    /* pDeleteDC */
     NULL,                            /* pDeleteObject */
     MFDRV_Ellipse,                   /* pEllipse */
     NULL,                            /* pEnumDeviceFonts */
@@ -30,7 +28,7 @@
     MFDRV_ExtFloodFill,              /* pExtFloodFill */
     MFDRV_ExtTextOut,                /* pExtTextOut */
     NULL,                            /* pGetCharWidth */
-    NULL /* no implementation */,    /* pGetPixel */
+    NULL, /* no implementation */    /* pGetPixel */
     NULL,                            /* pGetTextExtentPoint */
     NULL,                            /* pGetTextMetrics */
     NULL,                            /* pIntersectClipRect */
@@ -131,6 +129,7 @@
     if (physDev->mh) HeapFree( SystemHeap, 0, physDev->mh );
     HeapFree( SystemHeap, 0, physDev );
     dc->physDev = NULL;
+    GDI_FreeObject(dc->hSelf);
     return TRUE;
 }
 
@@ -154,13 +153,13 @@
         physDev->mh->mtType = METAFILE_DISK;
         if ((hFile = _lcreat32( filename, 0 )) == HFILE_ERROR32)
         {
-            DeleteDC32( dc->hSelf );
+            MFDRV_DeleteDC( dc );
             return 0;
         }
         if (_lwrite32( hFile, (LPSTR)physDev->mh,
                        sizeof(*physDev->mh)) == HFILE_ERROR32)
 	{
-            DeleteDC32( dc->hSelf );
+            MFDRV_DeleteDC( dc );
             return 0;
 	}
 	physDev->mh->mtNoParameters = hFile; /* store file descriptor here */
@@ -186,7 +185,7 @@
     
     dprintf_metafile( stddeb, "CloseMetaFile(%04x)\n", hdc );
 
-    if (!(dc = DC_GetDCPtr( hdc ))) return 0;
+    if (!(dc = (DC *) GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC ))) return 0;
     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
 
     /* Construct the end of metafile record - this is documented
@@ -195,7 +194,7 @@
 
     if (!MF_MetaParam0(dc, META_EOF))
     {
-        DeleteDC32( hdc );
+        MFDRV_DeleteDC( dc );
 	return 0;
     }	
 
@@ -205,13 +204,13 @@
 	physDev->mh->mtNoParameters = 0;
         if (_llseek32(hFile, 0L, 0) == HFILE_ERROR32)
         {
-            DeleteDC32( hdc );
+            MFDRV_DeleteDC( dc );
             return 0;
         }
         if (_lwrite32( hFile, (LPSTR)physDev->mh,
                        sizeof(*physDev->mh)) == HFILE_ERROR32)
         {
-            DeleteDC32( hdc );
+            MFDRV_DeleteDC( dc );
             return 0;
         }
         _lclose32(hFile);
@@ -223,7 +222,7 @@
                               physDev->mh->mtSize * sizeof(WORD),
                               GetCurrentPDB(), FALSE, FALSE, FALSE, NULL );
     physDev->mh = NULL;  /* So it won't be deleted */
-    DeleteDC32( hdc );
+    MFDRV_DeleteDC( dc );
     return hmf;
 }
 
diff --git a/graphics/painting.c b/graphics/painting.c
index 15cb841..9b169e4 100644
--- a/graphics/painting.c
+++ b/graphics/painting.c
@@ -2,6 +2,7 @@
  * Misc. graphics operations
  *
  * Copyright 1993, 1994 Alexandre Julliard
+ * Copyright 1997 Bertho A. Stultiens
  */
 
 #include <math.h>
@@ -20,18 +21,13 @@
 #include "metafile.h"
 #include "syscolor.h"
 #include "palette.h"
+#include "cache.h"
 #include "color.h"
 #include "region.h"
+#include "path.h"
 #include "stddebug.h"
 #include "debug.h"
 
-BOOL32 DrawDiagEdge32(HDC32 hdc, RECT32 *rect, UINT32 edge, UINT32 flags);
-BOOL32 DrawRectEdge32(HDC32 hdc, RECT32 *rect, UINT32 edge, UINT32 flags);
-BOOL32 DrawFrameButton32(HDC32 hdc, LPRECT32 rc, UINT32 uState);
-BOOL32 DrawFrameCaption32(HDC32 hdc, LPRECT32 rc, UINT32 uState);
-BOOL32 DrawFrameMenu32(HDC32 hdc, LPRECT32 rc, UINT32 uState);
-BOOL32 DrawFrameScroll32(HDC32 hdc, LPRECT32 rc, UINT32 uState);
-
 /***********************************************************************
  *           LineTo16    (GDI.19)
  */
@@ -48,6 +44,10 @@
 {
     DC * dc = DC_GetDCPtr( hdc );
 
+    if(dc && PATH_IsPathOpen(dc->w.path))
+        if(!PATH_LineTo(hdc, x, y))
+	   return FALSE;
+    
     return dc && dc->funcs->pLineTo &&
     	   dc->funcs->pLineTo(dc,x,y);
 }
@@ -87,6 +87,10 @@
 {
     DC * dc = DC_GetDCPtr( hdc );
   
+    if(dc && PATH_IsPathOpen(dc->w.path))
+        if(!PATH_MoveTo(hdc))
+	    return FALSE;
+
     return dc && dc->funcs->pMoveToEx &&
     	   dc->funcs->pMoveToEx(dc,x,y,pt);
 }
@@ -680,7 +684,7 @@
 
 
 /**********************************************************************
- *          DrawFrameControl32  (USER32.152)
+ *          DrawAnimatedRects32  (USER32.153)
  */
 BOOL32 WINAPI DrawAnimatedRects32( HWND32 hwnd, int idAni,
                                    const LPRECT32 lprcFrom,
@@ -691,13 +695,238 @@
     return TRUE;
 }
 
-BOOL32 WINAPI DrawState32A(
-	HDC32 hdc,HBRUSH32 hbrush,DRAWSTATEPROC drawstateproc,
-	LPARAM lparam,WPARAM32 wparam,INT32 x,INT32 y,INT32 z,INT32 a,UINT32 b
-) {
-	fprintf(stderr,"DrawStateA(%x,%x,%p,0x%08lx,0x%08x,%d,%d,%d,%d,%d),stub\n",
-		hdc,hbrush,drawstateproc,lparam,wparam,x,y,z,a,b
-	);
-	return TRUE;
+
+/**********************************************************************
+ *          PAINTING_DrawStateJam
+ *
+ * Jams in the requested type in the dc
+ */
+static BOOL32 PAINTING_DrawStateJam(HDC32 hdc, UINT32 opcode,
+                                    DRAWSTATEPROC32 func, LPARAM lp, WPARAM32 wp, 
+                                    LPRECT32 rc, UINT32 dtflags,
+                                    BOOL32 unicode, BOOL32 _32bit)
+{
+    HDC32 memdc;
+    HBITMAP32 hbmsave;
+    BOOL32 retval;
+    INT32 cx = rc->right - rc->left;
+    INT32 cy = rc->bottom - rc->top;
+    
+    switch(opcode)
+    {
+    case DST_TEXT:
+    case DST_PREFIXTEXT:
+        if(unicode)
+            return DrawText32W(hdc, (LPWSTR)lp, (INT32)wp, rc, dtflags);
+        else if(_32bit)
+            return DrawText32A(hdc, (LPSTR)lp, (INT32)wp, rc, dtflags);
+        else
+            return DrawText32A(hdc, (LPSTR)PTR_SEG_TO_LIN(lp), (INT32)wp, rc, dtflags);
+
+    case DST_ICON:
+        return DrawIcon32(hdc, rc->left, rc->top, (HICON32)lp);
+
+    case DST_BITMAP:
+        memdc = CreateCompatibleDC32(hdc);
+        if(!memdc) return FALSE;
+        hbmsave = (HBITMAP32)SelectObject32(memdc, (HBITMAP32)lp);
+        if(!hbmsave) 
+        {
+            DeleteDC32(memdc);
+            return FALSE;
+        }
+        retval = BitBlt32(hdc, rc->left, rc->top, cx, cy, memdc, 0, 0, SRCCOPY);
+        SelectObject32(memdc, hbmsave);
+        DeleteDC32(memdc);
+        return retval;
+            
+    case DST_COMPLEX:
+        if(func)
+            if(_32bit)
+                return func(hdc, lp, wp, cx, cy);
+            else
+                return (BOOL32)((DRAWSTATEPROC16)func)((HDC16)hdc, (LPARAM)lp, (WPARAM16)wp, (INT16)cx, (INT16)cy);
+        else
+            return FALSE;
+    }
+    return FALSE;
 }
 
+/**********************************************************************
+ *      PAINTING_DrawState32()
+ */
+static BOOL32 PAINTING_DrawState32(HDC32 hdc, HBRUSH32 hbr, 
+                                   DRAWSTATEPROC32 func, LPARAM lp, WPARAM32 wp,
+                                   INT32 x, INT32 y, INT32 cx, INT32 cy, 
+                                   UINT32 flags, BOOL32 unicode, BOOL32 _32bit)
+{
+    HBITMAP32 hbm, hbmsave;
+    HFONT32 hfsave;
+    HBRUSH32 hbsave;
+    HDC32 memdc;
+    RECT32 rc;
+    UINT32 dtflags = DT_NOCLIP;
+    COLORREF fg, bg;
+    UINT32 opcode = flags & 0xf;
+    INT32 len = wp;
+    BOOL32 retval, tmp;
+
+    if((opcode == DST_TEXT || opcode == DST_PREFIXTEXT) && !len)    /* The string is '\0' terminated */
+    {
+        if(unicode)
+            len = lstrlen32W((LPWSTR)lp);
+        else if(_32bit)
+            len = lstrlen32A((LPSTR)lp);
+        else
+            len = lstrlen32A((LPSTR)PTR_SEG_TO_LIN(lp));
+    }
+
+    /* Find out what size the image has if not given by caller */
+    if(!cx || !cy)
+    {
+        SIZE32 s;
+        CURSORICONINFO *ici;
+        BITMAPOBJ *bmp;
+
+        switch(opcode)
+        {
+        case DST_TEXT:
+        case DST_PREFIXTEXT:
+            if(unicode)
+                retval = GetTextExtentPoint32W(hdc, (LPWSTR)lp, len, &s);
+            else if(_32bit)
+                retval = GetTextExtentPoint32A(hdc, (LPSTR)lp, len, &s);
+            else
+                retval = GetTextExtentPoint32A(hdc, PTR_SEG_TO_LIN(lp), len, &s);
+            if(!retval) return FALSE;
+            break;
+            
+        case DST_ICON:
+            ici = (CURSORICONINFO *)GlobalLock16((HGLOBAL16)lp);
+            if(!ici) return FALSE;
+            s.cx = ici->nWidth;
+            s.cy = ici->nHeight;
+            GlobalUnlock16((HGLOBAL16)lp);
+            break;            
+
+        case DST_BITMAP:
+            bmp = (BITMAPOBJ *)GDI_GetObjPtr((HBITMAP16)lp, BITMAP_MAGIC);
+            if(!bmp) return FALSE;
+            s.cx = bmp->bitmap.bmWidth;
+            s.cy = bmp->bitmap.bmHeight;
+            break;
+            
+        case DST_COMPLEX: /* cx and cy must be set in this mode */
+            return FALSE;
+	}
+	            
+        if(!cx) cx = s.cx;
+        if(!cy) cy = s.cy;
+    }
+
+    rc.left   = x;
+    rc.top    = y;
+    rc.right  = x + cx;
+    rc.bottom = y + cy;
+
+    if(flags & DSS_RIGHT)    /* This one is not documented in the win32.hlp file */
+        dtflags |= DT_RIGHT;
+    if(opcode == DST_TEXT)
+        dtflags |= DT_NOPREFIX;
+
+    /* For DSS_NORMAL we just jam in the image and return */
+    if((flags & 0x7ff0) == DSS_NORMAL)
+    {
+        return PAINTING_DrawStateJam(hdc, opcode, func, lp, len, &rc, dtflags, unicode, _32bit);
+    }
+
+    /* For all other states we need to convert the image to B/W in a local bitmap */
+    /* before it is displayed */
+    fg = SetTextColor32(hdc, RGB(0, 0, 0));
+    bg = SetBkColor32(hdc, RGB(255, 255, 255));
+    hbm = NULL; hbmsave = NULL; memdc = NULL; memdc = NULL; hbsave = NULL;
+    retval = FALSE; /* assume failure */
+    
+    /* From here on we must use "goto cleanup" when something goes wrong */
+    hbm     = CreateBitmap32(cx, cy, 1, 1, NULL);
+    if(!hbm) goto cleanup;
+    memdc   = CreateCompatibleDC32(hdc);
+    if(!memdc) goto cleanup;
+    hbmsave = (HBITMAP32)SelectObject32(memdc, hbm);
+    if(!hbmsave) goto cleanup;
+    rc.left = rc.top = 0;
+    rc.right = cx;
+    rc.bottom = cy;
+    if(!FillRect32(memdc, &rc, (HBRUSH32)GetStockObject32(WHITE_BRUSH))) goto cleanup;
+    SetBkColor32(memdc, RGB(255, 255, 255));
+    SetTextColor32(memdc, RGB(0, 0, 0));
+    hfsave  = (HFONT32)SelectObject32(memdc, GetCurrentObject(hdc, OBJ_FONT));
+    if(!hfsave && (opcode == DST_TEXT || opcode == DST_PREFIXTEXT)) goto cleanup;
+    tmp = PAINTING_DrawStateJam(memdc, opcode, func, lp, len, &rc, dtflags, unicode, _32bit);
+    if(hfsave) SelectObject32(memdc, hfsave);
+    if(!tmp) goto cleanup;
+    
+    /* These states cause the image to be dithered */
+    if(flags & (DSS_UNION|DSS_DISABLED))
+    {
+        hbsave = (HBRUSH32)SelectObject32(memdc, CACHE_GetPattern55AABrush());
+        if(!hbsave) goto cleanup;
+        tmp = PatBlt32(memdc, 0, 0, cx, cy, 0x00FA0089);
+        if(hbsave) SelectObject32(memdc, hbsave);
+        if(!tmp) goto cleanup;
+    }
+
+    hbsave = (HBRUSH32)SelectObject32(hdc, hbr ? hbr : GetStockObject32(WHITE_BRUSH));
+    if(!hbsave) goto cleanup;
+    
+    if(!BitBlt32(hdc, x, y, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup;
+    
+    /* DSS_DEFAULT makes the image boldface */
+    if(flags & DSS_DEFAULT)
+    {
+        if(!BitBlt32(hdc, x+1, y, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup;
+    }
+
+    retval = TRUE; /* We succeeded */
+    
+cleanup:    
+    SetTextColor32(hdc, fg);
+    SetBkColor32(hdc, bg);
+
+    if(hbsave)  SelectObject32(hdc, hbsave);
+    if(hbmsave) SelectObject32(memdc, hbmsave);
+    if(hbm)     DeleteObject32(hbm);
+    if(memdc)   DeleteDC32(memdc);
+
+    return retval;
+}
+
+/**********************************************************************
+ *      DrawState32A()   (USER32.162)
+ */
+BOOL32 WINAPI DrawState32A(HDC32 hdc, HBRUSH32 hbr,
+                   DRAWSTATEPROC32 func, LPARAM ldata, WPARAM32 wdata,
+                   INT32 x, INT32 y, INT32 cx, INT32 cy, UINT32 flags)
+{
+    return PAINTING_DrawState32(hdc, hbr, func, ldata, wdata, x, y, cx, cy, flags, FALSE, TRUE);
+}
+
+/**********************************************************************
+ *      DrawState32W()   (USER32.163)
+ */
+BOOL32 WINAPI DrawState32W(HDC32 hdc, HBRUSH32 hbr,
+                   DRAWSTATEPROC32 func, LPARAM ldata, WPARAM32 wdata,
+                   INT32 x, INT32 y, INT32 cx, INT32 cy, UINT32 flags)
+{
+    return PAINTING_DrawState32(hdc, hbr, func, ldata, wdata, x, y, cx, cy, flags, TRUE, TRUE);
+}
+
+/**********************************************************************
+ *      DrawState16()   (USER.449)
+ */
+BOOL16 WINAPI DrawState16(HDC16 hdc, HBRUSH16 hbr,
+                   DRAWSTATEPROC16 func, LPARAM ldata, WPARAM16 wdata,
+                   INT16 x, INT16 y, INT16 cx, INT16 cy, UINT16 flags)
+{
+    return PAINTING_DrawState32(hdc, hbr, (DRAWSTATEPROC32)func, ldata, wdata, x, y, cx, cy, flags, FALSE, FALSE);
+}
diff --git a/graphics/path.c b/graphics/path.c
new file mode 100644
index 0000000..e4e4013
--- /dev/null
+++ b/graphics/path.c
@@ -0,0 +1,704 @@
+/*
+ * Graphics paths (BeginPath, EndPath etc.)
+ *
+ * Copyright 1997 Martin Boehme
+ */
+
+#include <assert.h>
+#include <malloc.h>
+
+#include "windows.h"
+#include "winerror.h"
+
+#include "dc.h"
+#include "debug.h"
+#include "path.h"
+
+/* Notes on the implementation
+ *
+ * The implementation is based on dynamically resizable arrays of points and
+ * flags. I dithered for a bit before deciding on this implementation, and
+ * I had even done a bit of work on a linked list version before switching
+ * to arrays. It's a bit of a tradeoff. When you use linked lists, the
+ * implementation of FlattenPath is easier, because you can rip the
+ * PT_BEZIERTO entries out of the middle of the list and link the
+ * corresponding PT_LINETO entries in. However, when you use arrays,
+ * PathToRegion becomes easier, since you can essentially just pass your array
+ * of points to CreatePolyPolygonRgn. Also, if I'd used linked lists, I would
+ * have had the extra effort of creating a chunk-based allocation scheme
+ * in order to use memory effectively. That's why I finally decided to use
+ * arrays. Note by the way that the array based implementation has the same
+ * linear time complexity that linked lists would have since the arrays grow
+ * exponentially.
+ *
+ * The points are stored in the path in device coordinates. This is
+ * consistent with the way Windows does things (for instance, see the Win32
+ * SDK documentation for GetPath).
+ *
+ * The word "stroke" appears in several places (e.g. in the flag
+ * GdiPath.newStroke). A stroke consists of a PT_MOVETO followed by one or
+ * more PT_LINETOs or PT_BEZIERTOs, up to, but not including, the next
+ * PT_MOVETO. Note that this is not the same as the definition of a figure;
+ * a figure can contain several strokes.
+ *
+ * I modified the drawing functions (MoveTo, LineTo etc.) to test whether
+ * the path is open and to call the corresponding function in path.c if this
+ * is the case. A more elegant approach would be to modify the function
+ * pointers in the DC_FUNCTIONS structure; however, this would be a lot more
+ * complex. Also, the performance degradation caused by my approach in the
+ * case where no path is open is so small that it cannot be measured.
+ *
+ * Martin Boehme
+ */
+
+/* FIXME: A lot of stuff isn't implemented yet. There is much more to come. */
+
+#define NUM_ENTRIES_INITIAL 16  /* Initial size of points / flags arrays  */
+#define GROW_FACTOR_NUMER    2  /* Numerator of grow factor for the array */
+#define GROW_FACTOR_DENOM    1  /* Denominator of grow factor             */
+
+
+static BOOL32 PATH_PathToRegion(const GdiPath *pPath, INT32 nPolyFillMode,
+   HRGN32 *pHrgn);
+static void   PATH_EmptyPath(GdiPath *pPath);
+static BOOL32 PATH_AddEntry(GdiPath *pPath, POINT32 point, BYTE flags);
+static BOOL32 PATH_ReserveEntries(GdiPath *pPath, INT32 numEntries);
+static BOOL32 PATH_GetPathFromHDC(HDC32 hdc, GdiPath **ppPath);
+
+/***********************************************************************
+ *           BeginPath32    (GDI32.9)
+ */
+BOOL32 WINAPI BeginPath32(HDC32 hdc)
+{
+   GdiPath *pPath;
+   
+   /* Get pointer to path */
+   if(!PATH_GetPathFromHDC(hdc, &pPath))
+   {
+      SetLastError(ERROR_INVALID_HANDLE);
+      return FALSE;
+   }
+   
+   /* If path is already open, do nothing */
+   if(pPath->state==PATH_Open)
+      return TRUE;
+
+   /* Make sure that path is empty */
+   PATH_EmptyPath(pPath);
+
+   /* Initialize variables for new path */
+   pPath->newStroke=TRUE;
+   pPath->state=PATH_Open;
+   
+   return TRUE;
+}
+
+
+/***********************************************************************
+ *           EndPath32    (GDI32.78)
+ */
+BOOL32 WINAPI EndPath32(HDC32 hdc)
+{
+   GdiPath *pPath;
+   
+   /* Get pointer to path */
+   if(!PATH_GetPathFromHDC(hdc, &pPath))
+   {
+      SetLastError(ERROR_INVALID_HANDLE);
+      return FALSE;
+   }
+   
+   /* Check that path is currently being constructed */
+   if(pPath->state!=PATH_Open)
+   {
+      SetLastError(ERROR_CAN_NOT_COMPLETE);
+      return FALSE;
+   }
+   
+   /* Set flag to indicate that path is finished */
+   pPath->state=PATH_Closed;
+   
+   return TRUE;
+}
+
+
+/***********************************************************************
+ *           AbortPath32    (GDI32.1)
+ */
+BOOL32 WINAPI AbortPath32(HDC32 hdc)
+/* FIXME: Check that SetLastError is being called correctly */
+{
+   GdiPath *pPath;
+   
+   /* Get pointer to path */
+   if(!PATH_GetPathFromHDC(hdc, &pPath))
+   {
+      SetLastError(ERROR_INVALID_PARAMETER);
+      return FALSE;
+   }
+   
+   /* Remove all entries from the path */
+   PATH_EmptyPath(pPath);
+
+   return TRUE;
+}
+
+
+/***********************************************************************
+ *           CloseFigure32    (GDI32.16)
+ */
+BOOL32 WINAPI CloseFigure32(HDC32 hdc)
+/* FIXME: Check that SetLastError is being called correctly */
+{
+   GdiPath *pPath;
+   
+   /* Get pointer to path */
+   if(!PATH_GetPathFromHDC(hdc, &pPath))
+   {
+      SetLastError(ERROR_INVALID_PARAMETER);
+      return FALSE;
+   }
+   
+   /* Check that path is open */
+   if(pPath->state!=PATH_Open)
+   {
+      SetLastError(ERROR_CAN_NOT_COMPLETE);
+      return FALSE;
+   }
+   
+   /* Set PT_CLOSEFIGURE on the last entry and start a new stroke */
+   if(pPath->numEntriesUsed)
+   {
+      pPath->pFlags[pPath->numEntriesUsed-1]|=PT_CLOSEFIGURE;
+      pPath->newStroke=TRUE;
+   }
+
+   return TRUE;
+}
+
+
+/***********************************************************************
+ *           GetPath32    (GDI32.210)
+ */
+INT32 WINAPI GetPath32(HDC32 hdc, LPPOINT32 pPoints, LPBYTE pTypes,
+   INT32 nSize)
+{
+   GdiPath *pPath;
+   BOOL32  temp_flag;
+   
+   /* Get pointer to path */
+   if(!PATH_GetPathFromHDC(hdc, &pPath))
+   {
+      SetLastError(ERROR_INVALID_PARAMETER);
+      return -1;
+   }
+   
+   /* Check that path is closed */
+   if(pPath->state!=PATH_Closed)
+   {
+      SetLastError(ERROR_CAN_NOT_COMPLETE);
+      return -1;
+   }
+   
+   if(nSize==0)
+      return pPath->numEntriesUsed;
+   else if(nSize<pPath->numEntriesUsed)
+   {
+      SetLastError(ERROR_INVALID_PARAMETER);
+      return -1;
+   }
+   else
+   {
+      memcpy(pPoints, pPath->pPoints, sizeof(POINT32)*pPath->numEntriesUsed);
+      memcpy(pTypes, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed);
+
+      /* Convert the points to logical coordinates */
+      temp_flag=DPtoLP32(hdc, pPoints, pPath->numEntriesUsed);
+
+      /* Since hdc is valid, conversion should never fail */
+      assert(temp_flag);
+      
+      return pPath->numEntriesUsed;
+   }
+}
+
+
+/***********************************************************************
+ *           PathToRegion32    (GDI32.261)
+ */
+HRGN32 WINAPI PathToRegion32(HDC32 hdc)
+/* FIXME: Check that SetLastError is being called correctly */
+/* The documentation does not state this explicitly, but a test under Windows
+ * shows that the region which is returned should be in device coordinates.
+ */
+{
+   GdiPath *pPath;
+   HRGN32  hrgnRval;
+
+   /* Get pointer to path */
+   if(!PATH_GetPathFromHDC(hdc, &pPath))
+   {
+      SetLastError(ERROR_INVALID_PARAMETER);
+      return 0;
+   }
+   
+   /* Check that path is closed */
+   if(pPath->state!=PATH_Closed)
+   {
+      SetLastError(ERROR_CAN_NOT_COMPLETE);
+      return 0;
+   }
+   
+   /* FIXME: Should we empty the path even if conversion failed? */
+   if(PATH_PathToRegion(pPath, GetPolyFillMode32(hdc), &hrgnRval))
+      PATH_EmptyPath(pPath);
+   else
+      hrgnRval=0;
+
+   return hrgnRval;
+}
+
+
+/***********************************************************************
+ *           FillPath32    (GDI32.100)
+ */
+BOOL32 WINAPI FillPath32(HDC32 hdc)
+/* FIXME: Check that SetLastError is being called correctly */
+{
+   GdiPath *pPath;
+   INT32   mapMode;
+   POINT32 ptViewportExt, ptViewportOrg, ptWindowExt, ptWindowOrg;
+   HRGN32  hrgn;
+   
+   /* Get pointer to path */
+   if(!PATH_GetPathFromHDC(hdc, &pPath))
+   {
+      SetLastError(ERROR_INVALID_PARAMETER);
+      return FALSE;
+   }
+   
+   /* Check that path is closed */
+   if(pPath->state!=PATH_Closed)
+   {
+      SetLastError(ERROR_CAN_NOT_COMPLETE);
+      return FALSE;
+   }
+   
+   /* Construct a region from the path and fill it */
+   if(PATH_PathToRegion(pPath, GetPolyFillMode32(hdc), &hrgn))
+   {
+      /* Since PaintRgn interprets the region as being in logical coordinates
+       * but the points we store for the path are already in device
+       * coordinates, we have to set the mapping mode to MM_TEXT temporarily.
+       */
+       
+      /* Save the information about the old mapping mode */
+      mapMode=GetMapMode32(hdc);
+      GetViewportExtEx32(hdc, &ptViewportExt);
+      GetViewportOrgEx32(hdc, &ptViewportOrg);
+      GetWindowExtEx32(hdc, &ptWindowExt);
+      GetWindowOrgEx32(hdc, &ptWindowOrg);
+      
+      /* FIXME: Once world transforms become available, we will have to do
+       * a GetWorldTransform, too (along with a SetWorldTransform later on).
+       * Moral: Perhaps I should have used SaveDC right away. The reason why
+       * I didn't is that I wanted to avoid the overhead of a full SaveDC
+       * (especially since SaveDC now saves the current path as well).
+       */
+
+      /* Set MM_TEXT */
+      SetMapMode32(hdc, MM_TEXT);
+      
+      /* Paint the region */
+      PaintRgn32(hdc, hrgn);
+
+      /* Restore the old mapping mode */
+      SetMapMode32(hdc, mapMode);
+      SetViewportExtEx32(hdc, ptViewportExt.x, ptViewportExt.y, NULL);
+      SetViewportOrgEx32(hdc, ptViewportOrg.x, ptViewportOrg.y, NULL);
+      SetWindowExtEx32(hdc, ptWindowExt.x, ptWindowExt.y, NULL);
+      SetWindowOrgEx32(hdc, ptWindowOrg.x, ptWindowOrg.y, NULL);
+
+      /* Empty the path */
+      PATH_EmptyPath(pPath);
+      return TRUE;
+   }
+   else
+   {
+      /* FIXME: Should the path be emptied even if conversion failed? */
+      /* PATH_EmptyPath(pPath); */
+      return FALSE;
+   }
+}
+
+
+/***********************************************************************
+ *           SelectClipPath32    (GDI32.296)
+ */
+BOOL32 WINAPI SelectClipPath32(HDC32 hdc, int iMode)
+/* FIXME: Check that SetLastError is being called correctly */
+{
+   GdiPath *pPath;
+   HRGN32  hrgnPath, hrgnClip;
+   BOOL32  success = FALSE;
+   
+   /* Get pointer to path */
+   if(!PATH_GetPathFromHDC(hdc, &pPath))
+   {
+      SetLastError(ERROR_INVALID_PARAMETER);
+      return FALSE;
+   }
+   
+   /* Check that path is closed */
+   if(pPath->state!=PATH_Closed)
+   {
+      SetLastError(ERROR_CAN_NOT_COMPLETE);
+      return FALSE;
+   }
+   
+   /* Construct a region from the path */
+   if(PATH_PathToRegion(pPath, GetPolyFillMode32(hdc), &hrgnPath))
+   {
+      hrgnClip=CreateRectRgn32(0, 0, 0, 0);
+      if(hrgnClip!=NULL)
+      {
+         success=(GetClipRgn32(hdc, hrgnClip)!=-1) &&
+	    (CombineRgn32(hrgnClip, hrgnClip, hrgnPath, iMode)!=ERROR) &&
+	    (SelectClipRgn32(hdc, hrgnClip)!=ERROR);
+	 DeleteObject32(hrgnClip);
+      }
+
+      DeleteObject32(hrgnPath);
+
+      /* Empty the path */
+      if(success)
+         PATH_EmptyPath(pPath);
+      /* FIXME: Should this function delete the path even if it failed? */
+
+      return success;
+   }
+   else
+      return FALSE;
+}
+
+
+/***********************************************************************
+ * Exported functions
+ */
+
+/* PATH_InitGdiPath
+ *
+ * Initializes the GdiPath structure.
+ */
+void PATH_InitGdiPath(GdiPath *pPath)
+{
+   assert(pPath!=NULL);
+
+   pPath->state=PATH_Null;
+   pPath->pPoints=NULL;
+   pPath->pFlags=NULL;
+   pPath->numEntriesUsed=0;
+   pPath->numEntriesAllocated=0;
+}
+
+/* PATH_DestroyGdiPath
+ *
+ * Destroys a GdiPath structure (frees the memory in the arrays).
+ */
+void PATH_DestroyGdiPath(GdiPath *pPath)
+{
+   assert(pPath!=NULL);
+
+   free(pPath->pPoints);
+   free(pPath->pFlags);
+}
+
+/* PATH_AssignGdiPath
+ *
+ * Copies the GdiPath structure "pPathSrc" to "pPathDest". A deep copy is
+ * performed, i.e. the contents of the pPoints and pFlags arrays are copied,
+ * not just the pointers. Since this means that the arrays in pPathDest may
+ * need to be resized, pPathDest should have been initialized using
+ * PATH_InitGdiPath (in C++, this function would be an assignment operator,
+ * not a copy constructor).
+ * Returns TRUE if successful, else FALSE.
+ */
+BOOL32 PATH_AssignGdiPath(GdiPath *pPathDest, const GdiPath *pPathSrc)
+{
+   assert(pPathDest!=NULL && pPathSrc!=NULL);
+
+   /* Make sure destination arrays are big enough */
+   if(!PATH_ReserveEntries(pPathDest, pPathSrc->numEntriesUsed))
+      return FALSE;
+
+   /* Perform the copy operation */
+   memcpy(pPathDest->pPoints, pPathSrc->pPoints,
+      sizeof(POINT32)*pPathSrc->numEntriesUsed);
+   memcpy(pPathDest->pFlags, pPathSrc->pFlags,
+      sizeof(INT32)*pPathSrc->numEntriesUsed);
+   pPathDest->state=pPathSrc->state;
+   pPathDest->numEntriesUsed=pPathSrc->numEntriesUsed;
+   pPathDest->newStroke=pPathSrc->newStroke;
+
+   return TRUE;
+}
+
+/* PATH_MoveTo
+ *
+ * Should be called when a MoveTo is performed on a DC that has an
+ * open path. This starts a new stroke. Returns TRUE if successful, else
+ * FALSE.
+ */
+BOOL32 PATH_MoveTo(HDC32 hdc)
+{
+   GdiPath *pPath;
+   
+   /* Get pointer to path */
+   if(!PATH_GetPathFromHDC(hdc, &pPath))
+      return FALSE;
+   
+   /* Check that path is open */
+   if(pPath->state!=PATH_Open)
+      /* FIXME: Do we have to call SetLastError? */
+      return FALSE;
+
+   /* Start a new stroke */
+   pPath->newStroke=TRUE;
+
+   return TRUE;
+}
+
+/* PATH_LineTo
+ *
+ * Should be called when a LineTo is performed on a DC that has an
+ * open path. This adds a PT_LINETO entry to the path (and possibly
+ * a PT_MOVETO entry, if this is the first LineTo in a stroke).
+ * Returns TRUE if successful, else FALSE.
+ */
+BOOL32 PATH_LineTo(HDC32 hdc, INT32 x, INT32 y)
+{
+   GdiPath *pPath;
+   POINT32 point, pointCurPos;
+   
+   /* Get pointer to path */
+   if(!PATH_GetPathFromHDC(hdc, &pPath))
+      return FALSE;
+   
+   /* Check that path is open */
+   if(pPath->state!=PATH_Open)
+      /* FIXME: Do we have to call SetLastError? */
+      return FALSE;
+
+   /* Convert point to device coordinates */
+   point.x=x;
+   point.y=y;
+   if(!LPtoDP32(hdc, &point, 1))
+      return FALSE;
+   
+   /* Add a PT_MOVETO if necessary */
+   if(pPath->newStroke)
+   {
+      pPath->newStroke=FALSE;
+      if(!GetCurrentPositionEx32(hdc, &pointCurPos) ||
+         !LPtoDP32(hdc, &pointCurPos, 1))
+         return FALSE;
+      if(!PATH_AddEntry(pPath, pointCurPos, PT_MOVETO))
+         return FALSE;
+   }
+   
+   /* Add a PT_LINETO entry */
+   return PATH_AddEntry(pPath, point, PT_LINETO);
+}
+
+
+/***********************************************************************
+ * Internal functions
+ */
+
+/* PATH_PathToRegion
+ *
+ * Creates a region from the specified path using the specified polygon
+ * filling mode. The path is left unchanged. A handle to the region that
+ * was created is stored in *pHrgn. If successful, TRUE is returned; if an
+ * error occurs, SetLastError is called with the appropriate value and
+ * FALSE is returned.
+ */
+static BOOL32 PATH_PathToRegion(const GdiPath *pPath, INT32 nPolyFillMode,
+   HRGN32 *pHrgn)
+{
+   int    numStrokes, iStroke, i;
+   INT32  *pNumPointsInStroke;
+   HRGN32 hrgn;
+
+   assert(pPath!=NULL);
+   assert(pHrgn!=NULL);
+   
+   /* FIXME: What happens when number of points is zero? */
+   
+   /* First pass: Find out how many strokes there are in the path */
+   /* FIXME: We could eliminate this with some bookkeeping in GdiPath */
+   numStrokes=0;
+   for(i=0; i<pPath->numEntriesUsed; i++)
+      if((pPath->pFlags[i] & ~PT_CLOSEFIGURE) == PT_MOVETO)
+         numStrokes++;
+
+   /* Allocate memory for number-of-points-in-stroke array */
+   pNumPointsInStroke=(int *)malloc(sizeof(int)*numStrokes);
+   if(!pNumPointsInStroke)
+   {
+      SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+      return FALSE;
+   }
+   
+   /* Second pass: remember number of points in each polygon */
+   iStroke=-1;  /* Will get incremented to 0 at beginning of first stroke */
+   for(i=0; i<pPath->numEntriesUsed; i++)
+   {
+      /* Is this the beginning of a new stroke? */
+      if((pPath->pFlags[i] & ~PT_CLOSEFIGURE) == PT_MOVETO)
+      {
+         iStroke++;
+	 pNumPointsInStroke[iStroke]=0;
+      }
+
+      pNumPointsInStroke[iStroke]++;
+   }
+
+   /* Create a region from the strokes */
+   hrgn=CreatePolyPolygonRgn32(pPath->pPoints, pNumPointsInStroke,
+      numStrokes, nPolyFillMode);
+   if(hrgn==NULL)
+   {
+      SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+      return FALSE;
+   }
+
+   /* Free memory for number-of-points-in-stroke array */
+   free(pNumPointsInStroke);
+
+   /* Success! */
+   *pHrgn=hrgn;
+   return TRUE;
+}
+
+/* PATH_EmptyPath
+ *
+ * Removes all entries from the path and sets the path state to PATH_Null.
+ */
+static void PATH_EmptyPath(GdiPath *pPath)
+{
+   assert(pPath!=NULL);
+
+   pPath->state=PATH_Null;
+   pPath->numEntriesUsed=0;
+}
+
+/* PATH_AddEntry
+ *
+ * Adds an entry to the path. For "flags", pass either PT_MOVETO, PT_LINETO
+ * or PT_BEZIERTO, optionally ORed with PT_CLOSEFIGURE. Returns TRUE if
+ * successful, FALSE otherwise (e.g. if not enough memory was available).
+ */
+BOOL32 PATH_AddEntry(GdiPath *pPath, POINT32 point, BYTE flags)
+{
+   assert(pPath!=NULL);
+   
+   /* Check that path is open */
+   if(pPath->state!=PATH_Open)
+      return FALSE;
+   
+   /* Reserve enough memory for an extra path entry */
+   if(!PATH_ReserveEntries(pPath, pPath->numEntriesUsed+1))
+      return FALSE;
+
+   /* Store information in path entry */
+   pPath->pPoints[pPath->numEntriesUsed]=point;
+   pPath->pFlags[pPath->numEntriesUsed]=flags;
+
+   /* Increment entry count */
+   pPath->numEntriesUsed++;
+
+   return TRUE;
+}
+
+/* PATH_ReserveEntries
+ *
+ * Ensures that at least "numEntries" entries (for points and flags) have
+ * been allocated; allocates larger arrays and copies the existing entries
+ * to those arrays, if necessary. Returns TRUE if successful, else FALSE.
+ */
+static BOOL32 PATH_ReserveEntries(GdiPath *pPath, INT32 numEntries)
+{
+   INT32   numEntriesToAllocate;
+   POINT32 *pPointsNew;
+   BYTE    *pFlagsNew;
+   
+   assert(pPath!=NULL);
+   assert(numEntries>=0);
+
+   /* Do we have to allocate more memory? */
+   if(numEntries > pPath->numEntriesAllocated)
+   {
+      /* Find number of entries to allocate. We let the size of the array
+       * grow exponentially, since that will guarantee linear time
+       * complexity. */
+      if(pPath->numEntriesAllocated)
+      {
+	 numEntriesToAllocate=pPath->numEntriesAllocated;
+	 while(numEntriesToAllocate<numEntries)
+	    numEntriesToAllocate=numEntriesToAllocate*GROW_FACTOR_NUMER/
+	       GROW_FACTOR_DENOM;
+      }
+      else
+         numEntriesToAllocate=NUM_ENTRIES_INITIAL;
+
+      /* Allocate new arrays */
+      pPointsNew=(POINT32 *)malloc(numEntriesToAllocate * sizeof(POINT32));
+      if(!pPointsNew)
+         return FALSE;
+      pFlagsNew=(BYTE *)malloc(numEntriesToAllocate * sizeof(BYTE));
+      if(!pFlagsNew)
+      {
+         free(pPointsNew);
+	 return FALSE;
+      }
+
+      /* Copy old arrays to new arrays and discard old arrays */
+      if(pPath->pPoints)
+      {
+         assert(pPath->pFlags);
+
+	 memcpy(pPointsNew, pPath->pPoints,
+	     sizeof(POINT32)*pPath->numEntriesUsed);
+	 memcpy(pFlagsNew, pPath->pFlags,
+	     sizeof(BYTE)*pPath->numEntriesUsed);
+
+	 free(pPath->pPoints);
+	 free(pPath->pFlags);
+      }
+      pPath->pPoints=pPointsNew;
+      pPath->pFlags=pFlagsNew;
+      pPath->numEntriesAllocated=numEntriesToAllocate;
+   }
+
+   return TRUE;
+}
+
+/* PATH_GetPathFromHDC
+ *
+ * Retrieves a pointer to the GdiPath structure contained in an HDC and
+ * places it in *ppPath. TRUE is returned if successful, FALSE otherwise.
+ */
+static BOOL32 PATH_GetPathFromHDC(HDC32 hdc, GdiPath **ppPath)
+{
+   DC *pDC;
+
+   pDC=DC_GetDCPtr(hdc);
+   if(pDC)
+   {
+      *ppPath=&pDC->w.path;
+      return TRUE;
+   }
+   else
+      return FALSE;
+}
diff --git a/graphics/win16drv/graphics.c b/graphics/win16drv/graphics.c
index ec2a72e..2452542 100644
--- a/graphics/win16drv/graphics.c
+++ b/graphics/win16drv/graphics.c
@@ -4,8 +4,11 @@
  * Copyright 1997 John Harvey
  */
 
+#include <stdio.h>
 #include "heap.h"
 #include "win16drv.h"
+#include "stddebug.h"
+#include "debug.h"
 
 /**********************************************************************
  *	     WIN16DRV_MoveToEx
@@ -57,9 +60,9 @@
     WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dc->physDev;
     BOOL32 bRet = 0;
     POINT16 points[2];
-    printf("In WIN16drv_Rectangle, x %d y %d DCOrgX %d y %d\n",
+    dprintf_win16drv(stddeb, "In WIN16DRV_Rectangle, x %d y %d DCOrgX %d y %d\n",
            left, top, dc->w.DCOrgX, dc->w.DCOrgY);
-    printf("In WIN16drv_Rectangle, VPortOrgX %d y %d\n",
+    dprintf_win16drv(stddeb, "In WIN16DRV_Rectangle, VPortOrgX %d y %d\n",
            dc->vportOrgX, dc->vportOrgY);
     points[0].x = XLPTODP(dc, left);
     points[0].y = YLPTODP(dc, top);
diff --git a/graphics/win16drv/init.c b/graphics/win16drv/init.c
index 6281186..e00e638 100644
--- a/graphics/win16drv/init.c
+++ b/graphics/win16drv/init.c
@@ -386,8 +386,8 @@
     return TRUE;
 }
 
-extern BOOL32 WIN16DRV_PatBlt( struct tagDC *dc, INT32 left, INT32 top,
-                             INT32 width, INT32 height, DWORD rop )
+BOOL32 WIN16DRV_PatBlt( struct tagDC *dc, INT32 left, INT32 top,
+			INT32 width, INT32 height, DWORD rop )
 {
   
     WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dc->physDev;
diff --git a/graphics/wing.c b/graphics/wing.c
index 58be554..f2b71dd 100644
--- a/graphics/wing.c
+++ b/graphics/wing.c
@@ -44,7 +44,7 @@
 
 static BITMAPINFOHEADER __bmpiWinG = { 0, 1, -1, 1, 8, BI_RGB, 1, 0, 0, 0, 0 };
 
-static void __initWinG()
+static void __initWinG(void)
 {
   if( __WinGOK < 0 )
   {
diff --git a/graphics/x11drv/graphics.c b/graphics/x11drv/graphics.c
index ec80312..9348d91 100644
--- a/graphics/x11drv/graphics.c
+++ b/graphics/x11drv/graphics.c
@@ -250,11 +250,14 @@
         bottom -= (width + 1) / 2;
     }
 
-    if (DC_SetupGCForBrush( dc ))
-	XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
-		        dc->w.DCOrgX + left + (width + 1) / 2,
-		        dc->w.DCOrgY + top + (width + 1) / 2,
-		        right-left-width-1, bottom-top-width-1);
+    if ((right > left + width) && (bottom > top + width))
+    {
+        if (DC_SetupGCForBrush( dc ))
+            XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
+                            dc->w.DCOrgX + left + (width + 1) / 2,
+                            dc->w.DCOrgY + top + (width + 1) / 2,
+                            right-left-width-1, bottom-top-width-1);
+    }
     if (DC_SetupGCForPen( dc ))
 	XDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc,
 		        dc->w.DCOrgX + left, dc->w.DCOrgY + top,
diff --git a/graphics/x11drv/init.c b/graphics/x11drv/init.c
index 6cfd5a1..e415104 100644
--- a/graphics/x11drv/init.c
+++ b/graphics/x11drv/init.c
@@ -108,8 +108,6 @@
  */
 BOOL32 X11DRV_Init(void)
 {
-    extern BOOL32 COLOR_Init();
-
     /* FIXME: colormap management should be merged with the X11DRV */
 
     if( !COLOR_Init() ) return FALSE;
diff --git a/graphics/x11drv/pen.c b/graphics/x11drv/pen.c
index 8516569..3a424cf 100644
--- a/graphics/x11drv/pen.c
+++ b/graphics/x11drv/pen.c
@@ -13,6 +13,7 @@
 static const char PEN_dot[]        = { 1,1 };      /* --  --  --  --  --  -- */
 static const char PEN_dashdot[]    = { 4,3,2,3 };  /* ----   --   ----   --  */
 static const char PEN_dashdotdot[] = { 4,2,2,2,2,2 }; /* ----  --  --  ----  */
+static const char PEN_alternate[]  = { 1,1 };      /* FIXME */
 
 /***********************************************************************
  *           PEN_SelectObject
@@ -22,12 +23,15 @@
     HPEN32 prevHandle = dc->w.hPen;
 
     dc->w.hPen = hpen;
-    dc->u.x.pen.style = pen->logpen.lopnStyle;
+    dc->u.x.pen.style = pen->logpen.lopnStyle & PS_STYLE_MASK;
+    dc->u.x.pen.endcap = pen->logpen.lopnStyle & PS_ENDCAP_MASK;
+    dc->u.x.pen.linejoin = pen->logpen.lopnStyle & PS_JOIN_MASK;
+
     dc->u.x.pen.width = pen->logpen.lopnWidth.x * dc->vportExtX / dc->wndExtX;
     if (dc->u.x.pen.width < 0) dc->u.x.pen.width = -dc->u.x.pen.width;
     if (dc->u.x.pen.width == 1) dc->u.x.pen.width = 0;  /* Faster */
     dc->u.x.pen.pixel = COLOR_ToPhysical( dc, pen->logpen.lopnColor );    
-    switch(pen->logpen.lopnStyle)
+    switch(pen->logpen.lopnStyle & PS_STYLE_MASK)
     {
       case PS_DASH:
 	dc->u.x.pen.dashes = (char *)PEN_dash;
@@ -45,6 +49,14 @@
 	dc->u.x.pen.dashes = (char *)PEN_dashdotdot;
 	dc->u.x.pen.dash_len = 6;
 	break;
+      case PS_ALTERNATE:
+	/* FIXME: should be alternating _pixels_ that are set */
+	dc->u.x.pen.dashes = (char *)PEN_alternate;
+	dc->u.x.pen.dash_len = 2;
+	break;
+      case PS_USERSTYLE:
+	/* FIXME */
+	break;
     }
     
     return prevHandle;
diff --git a/graphics/x11drv/xfont.c b/graphics/x11drv/xfont.c
index 9b988cf..be3bb66 100644
--- a/graphics/x11drv/xfont.c
+++ b/graphics/x11drv/xfont.c
@@ -170,13 +170,14 @@
    return checksum;
 }
 
-static UINT16   __genericCheckSum( UINT16* ptr, int size )
+static UINT16   __genericCheckSum( const void *ptr, int size )
 {
-   UINT16	checksum = 0;
-   unsigned	i;
+   unsigned int checksum = 0;
+   const char *p = (const char *)ptr;
+   while (size-- > 0)
+     checksum ^= (checksum << 3) + (checksum >> 29) + *p++;
 
-   for( i = 0, size >>= 1; i < size; i++ ) checksum ^= *ptr++;
-   return checksum;
+   return checksum & 0xffff;
 }
 
 /*************************************************************************
@@ -613,7 +614,7 @@
     fi->df.dfExternalLeading = (INT16)el;
 
     fi->df.dfPoints = (INT16)(((INT32)(fi->df.dfPixHeight - 
-				       fi->df.dfInternalLeading) * 72) / fi->df.dfVertRes);
+	       fi->df.dfInternalLeading) * 72 + (fi->df.dfVertRes >> 1)) / fi->df.dfVertRes);
 
     if( xfs->min_bounds.width != xfs->max_bounds.width )
         fi->df.dfPitchAndFamily |= TMPF_FIXED_PITCH; /* au contraire! */
@@ -831,25 +832,25 @@
     }
 
     for( up = 0; relocTable[up]; up++ )
-      if( PROFILE_GetWineIniString( INIFontSection, relocTable[up], "", buffer, 128 ) )
-      {
-	while( *buffer && isspace(*buffer) ) buffer++;
-	for( fr = NULL, pfr = fontList; pfr; pfr = pfr->next )
+	if( PROFILE_GetWineIniString( INIFontSection, relocTable[up], "", buffer, 128 ) )
 	{
-	     i = lstrlen32A( pfr->resource );
-	     if( !lstrncmpi32A( pfr->resource, buffer, i) )
-	     {
-		 if( fr )
-		 {
-		     fr->next = pfr->next;
-		     pfr->next = fontList;
-		     fontList = pfr;
-		 }
-		 break;
-	     }
-	     fr = pfr;
+	    while( *buffer && isspace(*buffer) ) buffer++;
+	    for( fr = NULL, pfr = fontList; pfr; pfr = pfr->next )
+	    {
+		i = lstrlen32A( pfr->resource );
+		if( !lstrncmpi32A( pfr->resource, buffer, i) )
+		{
+		    if( fr )
+		    {
+			fr->next = pfr->next;
+			pfr->next = fontList;
+			fontList = pfr;
+		    }
+		    break;
+		}
+		fr = pfr;
+	    }
 	}
-      }
 }
 
 /***********************************************************************
@@ -1078,7 +1079,7 @@
 			   pfi->df.dfFace = pfr->lfFaceName;
 			   pfi->df.dfHorizRes = pfi->df.dfVertRes = res;
 			   pfi->df.dfPoints = (INT16)(((INT32)(pfi->df.dfPixHeight -
-					pfi->df.dfInternalLeading) * 72) / res );
+				pfi->df.dfInternalLeading) * 72 + (res >> 1)) / res );
 			   pfi->next = pfi + 1;
 
 			   if( j > pfr->count ) break;
@@ -1244,9 +1245,10 @@
 
     /* Make sure this is a valid key */
     if((strncasecmp(key, INISubSection, 5) == 0) ||
-       (strcasecmp(key, INIDefault) == 0) ||
-       (strcasecmp(key, INIGlobalMetrics) == 0) ||
-       (strcasecmp(key, INIResolution) == 0) ) 
+       (strcasecmp( key, INIDefault) == 0) ||
+       (strcasecmp( key, INIDefaultFixed) == 0) ||
+       (strcasecmp( key, INIGlobalMetrics) == 0) ||
+       (strcasecmp( key, INIResolution) == 0) ) 
     {
 	/* Valid key; make sure the value doesn't contain a wildcard */
 	if(strchr(value, '*')) {
@@ -1331,7 +1333,7 @@
 #endif
 
      j = lstrlen32A( x_pattern[i] );
-     if( j ) x_checksum ^= __genericCheckSum( (UINT16*)(x_pattern[i]), j );
+     if( j ) x_checksum ^= __genericCheckSum( x_pattern[i], j );
   }
   x_checksum |= X_PFONT_MAGIC;
 
@@ -1557,7 +1559,8 @@
 
    if( plf->lfCharSet == DEFAULT_CHARSET )
    {
-       if( (pfi->df.dfCharSet!= ANSI_CHARSET) && (pfi->df.dfCharSet!=DEFAULT_CHARSET) ) penalty += 0x200;
+       if( (pfi->df.dfCharSet!= ANSI_CHARSET) && (pfi->df.dfCharSet!=DEFAULT_CHARSET) ) 
+	    penalty += 0x200;
    }
    else if (plf->lfCharSet != pfi->df.dfCharSet) penalty += 0x200;
 
@@ -1650,9 +1653,11 @@
 {
   BOOL32        skipRaster = (pfm->flags & FO_MATCH_NORASTER);
   UINT32        current_score, score = (UINT32)(-1);
+  UINT16        origflags = pfm->flags; /* Preserve FO_MATCH_XYINDEP */
   fontMatch     fm = *pfm;
 
-  for( fm.pfi = pfm->pfr->fi; fm.pfi && score; fm.pfi = fm.pfi->next )
+  for( fm.pfi = pfm->pfr->fi; fm.pfi && score; fm.pfi = fm.pfi->next,
+      fm.flags = origflags )
   {
      if( skipRaster && !(fm.pfi->fi_flags & FI_SCALABLE) )
          continue;
diff --git a/if1632/Makefile.in b/if1632/Makefile.in
index 63fb303..26e1e7a 100644
--- a/if1632/Makefile.in
+++ b/if1632/Makefile.in
@@ -6,56 +6,39 @@
 MODULE    = if1632
 
 DLLS = \
-	advapi32.spec \
-	comctl32.spec \
-	comdlg32.spec \
 	commdlg.spec \
 	compobj.spec \
-	crtdll.spec \
 	ddeml.spec \
 	gdi.spec \
-	gdi32.spec \
 	kernel.spec \
-	kernel32.spec \
 	keyboard.spec \
-	lz32.spec \
 	lzexpand.spec \
 	mmsystem.spec \
 	mouse.spec \
-	mpr.spec \
-	ntdll.spec \
 	ole2.spec \
 	ole2conv.spec \
 	ole2disp.spec \
 	ole2nls.spec \
 	ole2prox.spec \
-	ole32.spec \
+	ole2thk.spec \
 	olecli.spec \
-	olecli32.spec \
 	olesvr.spec \
-	olesvr32.spec \
 	shell.spec \
-	shell32.spec \
 	sound.spec \
 	storage.spec \
 	stress.spec \
 	system.spec \
 	toolhelp.spec \
 	user.spec \
-	user32.spec \
 	ver.spec \
-	version.spec \
-	w32skrnl.spec \
 	w32sys.spec \
 	win32s16.spec \
 	win87em.spec \
 	winaspi.spec \
+	windebug.spec \
 	wing.spec \
-	winmm.spec \
 	winsock.spec \
-	winspool.spec \
-	wprocs.spec \
-	wsock32.spec
+	wprocs.spec
 
 SPEC_FILES = $(DLLS:.spec=.s)
 
@@ -68,7 +51,6 @@
 
 GEN_ASM_SRCS = \
 	$(SPEC_FILES) \
-	call32.s \
 	callfrom16.s \
 	callto16.s
 
@@ -86,9 +68,6 @@
 callfrom16.s: $(SPEC_FILES)
 	$(BUILD) -o $@ -callfrom16 `cat $(SPEC_FILES) | grep CallFrom16_ | sed 's/.*CallFrom16_\(.*\)/\1/' | sort | uniq`
 
-call32.s: $(BUILD)
-	$(BUILD) -o $@ -call32
-
 callto16.s: $(SRCDIR)/thunk.c $(BUILD)
 	$(BUILD) -o $@ -callto16 $(SRCDIR)/thunk.c
 
diff --git a/if1632/builtin.c b/if1632/builtin.c
index f514004..273908a 100644
--- a/if1632/builtin.c
+++ b/if1632/builtin.c
@@ -8,6 +8,7 @@
 #include <ctype.h>
 #include <string.h>
 #include "windows.h"
+#include "builtin32.h"
 #include "gdi.h"
 #include "global.h"
 #include "heap.h"
@@ -34,158 +35,89 @@
 
 typedef struct
 {
-    const char         *name;       /* DLL name */
-    int                 base;       /* Ordinal base */
-    int                 nb_funcs;   /* Number of functions */
-    int                 nb_names;   /* Number of function names */
-    const void        **functions;  /* Pointer to function table */
-    const char * const *names;      /* Pointer to names table */
-    const WORD         *ordinals;   /* Pointer to ordinals table */
-    const BYTE         *args;       /* Pointer to argument lengths */
-    const DWORD        *argtypes;   /* Pointer to argument types bitmask */
-} WIN32_DESCRIPTOR;
-
-typedef union
-{
-    const char *name;               /* DLL name */
-    WIN16_DESCRIPTOR win16;         /* Descriptor for Win16 DLL */
-    WIN32_DESCRIPTOR win32;         /* Descriptor for Win32 DLL */
-} DLL_DESCRIPTOR;
-
-typedef struct
-{
-    BYTE  call;                    /* 0xe8 call callfrom32 (relative) */
-    DWORD callfrom32 WINE_PACKED;  /* RELAY_CallFrom32 relative addr */
-    BYTE  ret;                     /* 0xc2 ret $n  or  0xc3 ret */
-    WORD  args;                    /* nb of args to remove from the stack */
-} DEBUG_ENTRY_POINT;
-
-typedef struct
-{
-    const DLL_DESCRIPTOR *descr;     /* DLL descriptor */
-    DEBUG_ENTRY_POINT    *dbg_funcs; /* Relay debugging functions table */
-    int                   flags;     /* flags (see below) */
-} BUILTIN_DLL;
+    const WIN16_DESCRIPTOR *descr;     /* DLL descriptor */
+    int                     flags;     /* flags (see below) */
+} BUILTIN16_DLL;
 
 /* DLL flags */
 #define DLL_FLAG_NOT_USED    0x01  /* Use original Windows DLL if possible */
 #define DLL_FLAG_ALWAYS_USED 0x02  /* Always use built-in DLL */
-#define DLL_FLAG_WIN32       0x04  /* DLL is a Win32 DLL */
 
 /* 16-bit DLLs */
 
-extern const DLL_DESCRIPTOR KERNEL_Descriptor;
-extern const DLL_DESCRIPTOR USER_Descriptor;
-extern const DLL_DESCRIPTOR GDI_Descriptor;
-extern const DLL_DESCRIPTOR WIN87EM_Descriptor;
-extern const DLL_DESCRIPTOR MMSYSTEM_Descriptor;
-extern const DLL_DESCRIPTOR SHELL_Descriptor;
-extern const DLL_DESCRIPTOR SOUND_Descriptor;
-extern const DLL_DESCRIPTOR KEYBOARD_Descriptor;
-extern const DLL_DESCRIPTOR WINSOCK_Descriptor;
-extern const DLL_DESCRIPTOR STRESS_Descriptor;
-extern const DLL_DESCRIPTOR SYSTEM_Descriptor;
-extern const DLL_DESCRIPTOR TOOLHELP_Descriptor;
-extern const DLL_DESCRIPTOR MOUSE_Descriptor;
-extern const DLL_DESCRIPTOR COMMDLG_Descriptor;
-extern const DLL_DESCRIPTOR OLE2_Descriptor;
-extern const DLL_DESCRIPTOR OLE2CONV_Descriptor;
-extern const DLL_DESCRIPTOR OLE2DISP_Descriptor;
-extern const DLL_DESCRIPTOR OLE2NLS_Descriptor;
-extern const DLL_DESCRIPTOR OLE2PROX_Descriptor;
-extern const DLL_DESCRIPTOR OLECLI_Descriptor;
-extern const DLL_DESCRIPTOR OLESVR_Descriptor;
-extern const DLL_DESCRIPTOR COMPOBJ_Descriptor;
-extern const DLL_DESCRIPTOR STORAGE_Descriptor;
-extern const DLL_DESCRIPTOR WPROCS_Descriptor;
-extern const DLL_DESCRIPTOR DDEML_Descriptor;
-extern const DLL_DESCRIPTOR LZEXPAND_Descriptor;
-extern const DLL_DESCRIPTOR VER_Descriptor;
-extern const DLL_DESCRIPTOR W32SYS_Descriptor;
-extern const DLL_DESCRIPTOR WIN32S16_Descriptor;
-extern const DLL_DESCRIPTOR WING_Descriptor;
-extern const DLL_DESCRIPTOR WINASPI_Descriptor;
-
-/* 32-bit DLLs */
-
-extern const DLL_DESCRIPTOR ADVAPI32_Descriptor;
-extern const DLL_DESCRIPTOR COMCTL32_Descriptor;
-extern const DLL_DESCRIPTOR COMDLG32_Descriptor;
-extern const DLL_DESCRIPTOR CRTDLL_Descriptor;
-extern const DLL_DESCRIPTOR GDI32_Descriptor;
-extern const DLL_DESCRIPTOR KERNEL32_Descriptor;
-extern const DLL_DESCRIPTOR LZ32_Descriptor;
-extern const DLL_DESCRIPTOR MPR_Descriptor;
-extern const DLL_DESCRIPTOR NTDLL_Descriptor;
-extern const DLL_DESCRIPTOR OLE32_Descriptor;
-extern const DLL_DESCRIPTOR OLECLI32_Descriptor;
-extern const DLL_DESCRIPTOR OLESVR32_Descriptor;
-extern const DLL_DESCRIPTOR SHELL32_Descriptor;
-extern const DLL_DESCRIPTOR USER32_Descriptor;
-extern const DLL_DESCRIPTOR VERSION_Descriptor;
-extern const DLL_DESCRIPTOR W32SKRNL_Descriptor;
-extern const DLL_DESCRIPTOR WINMM_Descriptor;
-extern const DLL_DESCRIPTOR WINSPOOL_Descriptor;
-extern const DLL_DESCRIPTOR WSOCK32_Descriptor;
+extern const WIN16_DESCRIPTOR COMMDLG_Descriptor;
+extern const WIN16_DESCRIPTOR COMPOBJ_Descriptor;
+extern const WIN16_DESCRIPTOR DDEML_Descriptor;
+extern const WIN16_DESCRIPTOR GDI_Descriptor;
+extern const WIN16_DESCRIPTOR KERNEL_Descriptor;
+extern const WIN16_DESCRIPTOR KEYBOARD_Descriptor;
+extern const WIN16_DESCRIPTOR LZEXPAND_Descriptor;
+extern const WIN16_DESCRIPTOR MMSYSTEM_Descriptor;
+extern const WIN16_DESCRIPTOR MOUSE_Descriptor;
+extern const WIN16_DESCRIPTOR OLE2CONV_Descriptor;
+extern const WIN16_DESCRIPTOR OLE2DISP_Descriptor;
+extern const WIN16_DESCRIPTOR OLE2NLS_Descriptor;
+extern const WIN16_DESCRIPTOR OLE2PROX_Descriptor;
+extern const WIN16_DESCRIPTOR OLE2THK_Descriptor;
+extern const WIN16_DESCRIPTOR OLE2_Descriptor;
+extern const WIN16_DESCRIPTOR OLECLI_Descriptor;
+extern const WIN16_DESCRIPTOR OLESVR_Descriptor;
+extern const WIN16_DESCRIPTOR SHELL_Descriptor;
+extern const WIN16_DESCRIPTOR SOUND_Descriptor;
+extern const WIN16_DESCRIPTOR STORAGE_Descriptor;
+extern const WIN16_DESCRIPTOR STRESS_Descriptor;
+extern const WIN16_DESCRIPTOR SYSTEM_Descriptor;
+extern const WIN16_DESCRIPTOR TOOLHELP_Descriptor;
+extern const WIN16_DESCRIPTOR USER_Descriptor;
+extern const WIN16_DESCRIPTOR VER_Descriptor;
+extern const WIN16_DESCRIPTOR W32SYS_Descriptor;
+extern const WIN16_DESCRIPTOR WIN32S16_Descriptor;
+extern const WIN16_DESCRIPTOR WIN87EM_Descriptor;
+extern const WIN16_DESCRIPTOR WINASPI_Descriptor;
+extern const WIN16_DESCRIPTOR WINDEBUG_Descriptor;
+extern const WIN16_DESCRIPTOR WING_Descriptor;
+extern const WIN16_DESCRIPTOR WINSOCK_Descriptor;
+extern const WIN16_DESCRIPTOR WPROCS_Descriptor;
 
 /* Table of all built-in DLLs */
 
-static BUILTIN_DLL BuiltinDLLs[] =
+static BUILTIN16_DLL BuiltinDLLs[] =
 {
-    /* Win16 DLLs */
-    { &KERNEL_Descriptor,   NULL, DLL_FLAG_ALWAYS_USED },
-    { &USER_Descriptor,     NULL, DLL_FLAG_ALWAYS_USED },
-    { &GDI_Descriptor,      NULL, DLL_FLAG_ALWAYS_USED },
-    { &SYSTEM_Descriptor,   NULL, DLL_FLAG_ALWAYS_USED },
-    { &WIN87EM_Descriptor,  NULL, DLL_FLAG_NOT_USED },
-    { &SHELL_Descriptor,    NULL, 0 },
-    { &SOUND_Descriptor,    NULL, 0 },
-    { &KEYBOARD_Descriptor, NULL, 0 },
-    { &WINSOCK_Descriptor,  NULL, 0 },
-    { &STRESS_Descriptor,   NULL, 0 },
-    { &MMSYSTEM_Descriptor, NULL, 0 },
-    { &TOOLHELP_Descriptor, NULL, 0 },
-    { &MOUSE_Descriptor,    NULL, 0 },
-    { &COMMDLG_Descriptor,  NULL, DLL_FLAG_NOT_USED },
-    { &OLE2_Descriptor,     NULL, DLL_FLAG_NOT_USED },
-    { &OLE2CONV_Descriptor, NULL, DLL_FLAG_NOT_USED },
-    { &OLE2DISP_Descriptor, NULL, DLL_FLAG_NOT_USED },
-    { &OLE2NLS_Descriptor,  NULL, DLL_FLAG_NOT_USED },
-    { &OLE2PROX_Descriptor, NULL, DLL_FLAG_NOT_USED },
-    { &OLECLI_Descriptor,   NULL, DLL_FLAG_NOT_USED },
-    { &OLESVR_Descriptor,   NULL, DLL_FLAG_NOT_USED },
-    { &COMPOBJ_Descriptor,  NULL, DLL_FLAG_NOT_USED },
-    { &STORAGE_Descriptor,  NULL, DLL_FLAG_NOT_USED },
-    { &WPROCS_Descriptor,   NULL, DLL_FLAG_ALWAYS_USED },
-    { &DDEML_Descriptor,    NULL, DLL_FLAG_NOT_USED },
-    { &LZEXPAND_Descriptor, NULL, 0 },
-    { &VER_Descriptor,      NULL, 0 },
-    { &W32SYS_Descriptor,   NULL, 0 },
-    { &WIN32S16_Descriptor, NULL, 0 },
-    { &WING_Descriptor,     NULL, 0 },
-    { &WINASPI_Descriptor,  NULL, 0 },
-    /* Win32 DLLs */
-    { &ADVAPI32_Descriptor, NULL, DLL_FLAG_WIN32 },
-    { &COMCTL32_Descriptor, NULL, DLL_FLAG_WIN32 | DLL_FLAG_NOT_USED },
-    { &COMDLG32_Descriptor, NULL, DLL_FLAG_WIN32 },
-    { &CRTDLL_Descriptor,   NULL, DLL_FLAG_WIN32 },
-    { &GDI32_Descriptor,    NULL, DLL_FLAG_WIN32 },
-    { &KERNEL32_Descriptor, NULL, DLL_FLAG_WIN32 },
-    { &LZ32_Descriptor,     NULL, DLL_FLAG_WIN32 },
-    { &MPR_Descriptor,      NULL, DLL_FLAG_WIN32 },
-    { &NTDLL_Descriptor,    NULL, DLL_FLAG_WIN32 },
-    { &OLE32_Descriptor,    NULL, DLL_FLAG_WIN32 | DLL_FLAG_NOT_USED },
-    { &OLECLI32_Descriptor, NULL, DLL_FLAG_WIN32 | DLL_FLAG_NOT_USED },
-    { &OLESVR32_Descriptor, NULL, DLL_FLAG_WIN32 | DLL_FLAG_NOT_USED },
-    { &SHELL32_Descriptor,  NULL, DLL_FLAG_WIN32 },
-    { &USER32_Descriptor,   NULL, DLL_FLAG_WIN32 },
-    { &VERSION_Descriptor,  NULL, DLL_FLAG_WIN32 },
-    { &W32SKRNL_Descriptor, NULL, DLL_FLAG_WIN32 },
-    { &WINMM_Descriptor,    NULL, DLL_FLAG_WIN32 },
-    { &WINSPOOL_Descriptor, NULL, DLL_FLAG_WIN32 },
-    { &WSOCK32_Descriptor,  NULL, DLL_FLAG_WIN32 },
+    { &KERNEL_Descriptor,   DLL_FLAG_ALWAYS_USED },
+    { &USER_Descriptor,     DLL_FLAG_ALWAYS_USED },
+    { &GDI_Descriptor,      DLL_FLAG_ALWAYS_USED },
+    { &SYSTEM_Descriptor,   DLL_FLAG_ALWAYS_USED },
+    { &WPROCS_Descriptor,   DLL_FLAG_ALWAYS_USED },
+    { &WINDEBUG_Descriptor, DLL_FLAG_ALWAYS_USED },
+    { &COMMDLG_Descriptor,  DLL_FLAG_NOT_USED },
+    { &COMPOBJ_Descriptor,  DLL_FLAG_NOT_USED },
+    { &DDEML_Descriptor,    DLL_FLAG_NOT_USED },
+    { &KEYBOARD_Descriptor, 0 },
+    { &LZEXPAND_Descriptor, 0 },
+    { &MMSYSTEM_Descriptor, 0 },
+    { &MOUSE_Descriptor,    0 },
+    { &OLE2CONV_Descriptor, DLL_FLAG_NOT_USED },
+    { &OLE2DISP_Descriptor, DLL_FLAG_NOT_USED },
+    { &OLE2NLS_Descriptor,  DLL_FLAG_NOT_USED },
+    { &OLE2PROX_Descriptor, DLL_FLAG_NOT_USED },
+    { &OLE2THK_Descriptor,  DLL_FLAG_NOT_USED },
+    { &OLE2_Descriptor,     DLL_FLAG_NOT_USED },
+    { &OLECLI_Descriptor,   DLL_FLAG_NOT_USED },
+    { &OLESVR_Descriptor,   DLL_FLAG_NOT_USED },
+    { &SHELL_Descriptor,    0 },
+    { &SOUND_Descriptor,    0 },
+    { &STORAGE_Descriptor,  DLL_FLAG_NOT_USED },
+    { &STRESS_Descriptor,   0 },
+    { &TOOLHELP_Descriptor, 0 },
+    { &VER_Descriptor,      0 },
+    { &W32SYS_Descriptor,   0 },
+    { &WIN32S16_Descriptor, 0 },
+    { &WIN87EM_Descriptor,  DLL_FLAG_NOT_USED },
+    { &WINASPI_Descriptor,  0 },
+    { &WING_Descriptor,     0 },
+    { &WINSOCK_Descriptor,  0 },
     /* Last entry */
-    { NULL, NULL, 0 }
+    { NULL, 0 }
 };
 
   /* Ordinal number for interrupt 0 handler in WPROCS.DLL */
@@ -243,210 +175,21 @@
 
 
 /***********************************************************************
- *           BUILTIN_DoLoadModule32
- *
- * Load a built-in Win32 module. Helper function for BUILTIN_LoadModule
- * and BUILTIN_Init.
- */
-static HMODULE32 BUILTIN_DoLoadModule32( BUILTIN_DLL *dll )
-{
-    extern void RELAY_CallFrom32();
-
-    HMODULE16 hModule;
-    NE_MODULE *pModule;
-    OFSTRUCT ofs;
-    IMAGE_DATA_DIRECTORY *dir;
-    IMAGE_DOS_HEADER *dos;
-    IMAGE_NT_HEADERS *nt;
-    IMAGE_SECTION_HEADER *sec;
-    IMAGE_EXPORT_DIRECTORY *exp;
-    LPVOID *funcs;
-    LPSTR *names;
-    DEBUG_ENTRY_POINT *entry;
-    PE_MODREF *pem;
-    INT32 i, size;
-    BYTE *addr;
-
-    /* Allocate the module */
-
-    size = (sizeof(IMAGE_DOS_HEADER)
-            + sizeof(IMAGE_NT_HEADERS)
-            + 2 * sizeof(IMAGE_SECTION_HEADER)
-            + sizeof(IMAGE_EXPORT_DIRECTORY)
-            + dll->descr->win32.nb_funcs * sizeof(LPVOID)
-            + dll->descr->win32.nb_names * sizeof(LPSTR));
-    if (debugging_relay)
-        size += dll->descr->win32.nb_funcs * sizeof(DEBUG_ENTRY_POINT);
-    addr  = VirtualAlloc( NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
-    if (!addr) return 0;
-    dos   = (IMAGE_DOS_HEADER *)addr;
-    nt    = (IMAGE_NT_HEADERS *)(dos + 1);
-    sec   = (IMAGE_SECTION_HEADER *)(nt + 1);
-    exp   = (IMAGE_EXPORT_DIRECTORY *)(sec + 2);
-    funcs = (LPVOID *)(exp + 1);
-    names = (LPSTR *)(funcs + dll->descr->win32.nb_funcs);
-    entry = (DEBUG_ENTRY_POINT *)(names + dll->descr->win32.nb_names);
-
-    /* Build the DOS and NT headers */
-
-    dos->e_magic  = IMAGE_DOS_SIGNATURE;
-    dos->e_lfanew = sizeof(*dos);
-
-    nt->Signature                       = IMAGE_NT_SIGNATURE;
-    nt->FileHeader.Machine              = IMAGE_FILE_MACHINE_I386;
-    nt->FileHeader.NumberOfSections     = 2;  /* exports + code */
-    nt->FileHeader.SizeOfOptionalHeader = sizeof(nt->OptionalHeader);
-    nt->FileHeader.Characteristics      = IMAGE_FILE_DLL;
-
-    nt->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
-    nt->OptionalHeader.SizeOfCode                  = 0x1000;
-    nt->OptionalHeader.SizeOfInitializedData       = 0;
-    nt->OptionalHeader.SizeOfUninitializedData     = 0;
-    nt->OptionalHeader.ImageBase                   = (DWORD)addr;
-    nt->OptionalHeader.SectionAlignment            = 0x1000;
-    nt->OptionalHeader.FileAlignment               = 0x1000;
-    nt->OptionalHeader.MajorOperatingSystemVersion = 1;
-    nt->OptionalHeader.MinorOperatingSystemVersion = 0;
-    nt->OptionalHeader.MajorSubsystemVersion       = 4;
-    nt->OptionalHeader.MinorSubsystemVersion       = 0;
-    nt->OptionalHeader.SizeOfImage                 = size;
-    nt->OptionalHeader.SizeOfHeaders               = (BYTE *)exp - addr;
-    nt->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
-
-    /* Build the export directory */
-
-    dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
-    dir->VirtualAddress = (BYTE *)exp - addr;
-    dir->Size = sizeof(*exp)
-                + dll->descr->win32.nb_funcs * sizeof(LPVOID)
-                + dll->descr->win32.nb_names * sizeof(LPSTR);
-
-    /* Build the exports section */
-
-    strcpy( sec->Name, ".edata" );
-    sec->Misc.VirtualSize = dir->Size;
-    sec->VirtualAddress   = (BYTE *)exp - addr;
-    sec->SizeOfRawData    = dir->Size;
-    sec->PointerToRawData = (BYTE *)exp - addr;
-    sec->Characteristics  = (IMAGE_SCN_CNT_INITIALIZED_DATA |
-                             IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ |
-                             IMAGE_SCN_MEM_WRITE);
-
-    /* Build the code section */
-
-    sec++;
-    strcpy( sec->Name, ".code" );
-    if (debugging_relay)
-        sec->SizeOfRawData = dll->descr->win32.nb_funcs * sizeof(DEBUG_ENTRY_POINT);
-    else
-        sec->SizeOfRawData = 1;
-    sec->Misc.VirtualSize = sec->SizeOfRawData;
-    sec->VirtualAddress   = (BYTE *)entry - addr;
-    sec->PointerToRawData = (BYTE *)entry - addr;
-    sec->Characteristics  = (IMAGE_SCN_CNT_INITIALIZED_DATA |
-                             IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ);
-
-    /* Build the exports section data */
-
-    exp->Name                  = (BYTE *)dll->descr->name - addr;  /*??*/
-    exp->Base                  = dll->descr->win32.base;
-    exp->NumberOfFunctions     = dll->descr->win32.nb_funcs;
-    exp->NumberOfNames         = dll->descr->win32.nb_names;
-    exp->AddressOfFunctions    = (LPDWORD *)((BYTE *)funcs - addr);
-    exp->AddressOfNames        = (LPDWORD *)((BYTE *)names - addr);
-    exp->AddressOfNameOrdinals = (LPWORD *)((BYTE *)dll->descr->win32.ordinals - addr);
-
-    /* Build the funcs table */
-
-    if (debugging_relay)
-    {
-        dll->dbg_funcs = entry;
-        for (i = 0; i < dll->descr->win32.nb_funcs; i++, funcs++, entry++)
-        {
-            BYTE args = dll->descr->win32.args[i];
-            entry->call = 0xe8;  /* call */
-            switch(args)
-            {
-            case 0xfe:  /* register func */
-                entry->callfrom32 = (DWORD)dll->descr->win32.functions[i] -
-                                    (DWORD)&entry->ret;
-                entry->ret        = 0x90;  /* nop */
-                entry->args       = 0;
-                *funcs = (LPVOID)((BYTE *)entry - addr);
-                break;
-            case 0xff:  /* stub or extern */
-                if (dll->descr->win32.functions[i])
-                    *funcs = (LPVOID)((BYTE *)dll->descr->win32.functions[i]
-                                              - addr);
-                break;
-            default:  /* normal function (stdcall or cdecl) */
-                entry->callfrom32 = (DWORD)RELAY_CallFrom32 -
-                                    (DWORD)&entry->ret;
-                entry->ret        = (args & 0x80) ? 0xc3 : 0xc2; /*ret/ret $n*/
-                entry->args       = (args & 0x7f) * sizeof(int);
-                *funcs = (LPVOID)((BYTE *)entry - addr);
-                break;
-            }
-        }
-    }
-    else
-    {
-        for (i = 0; i < dll->descr->win32.nb_funcs; i++, funcs++)
-            if (dll->descr->win32.functions[i])
-                *funcs = (LPVOID)((BYTE *)dll->descr->win32.functions[i]
-                                           - addr);
-    }
-
-    /* Build the names table */
-
-    for (i = 0; i < exp->NumberOfNames; i++, names++)
-        if (dll->descr->win32.names[i])
-            *names = (LPSTR)((BYTE *)dll->descr->win32.names[i] - addr);
-
-    /* Create a modref */
-
-    pem = (PE_MODREF *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
-                                  sizeof(*pem) );
-    pem->module = (HMODULE32)addr;
-    pem->pe_export = exp;
-    pem->next = pCurrentProcess->modref_list;
-    pCurrentProcess->modref_list = pem;
-
-    /* Create a Win16 dummy module */
-
-    sprintf( ofs.szPathName, "%s.DLL", dll->descr->name );
-    hModule = MODULE_CreateDummyModule( &ofs );
-    pModule = (NE_MODULE *)GlobalLock16( hModule );
-    pModule->flags = NE_FFLAGS_SINGLEDATA | NE_FFLAGS_BUILTIN |
-                     NE_FFLAGS_LIBMODULE | NE_FFLAGS_WIN32;
-    pModule->module32 = (HMODULE32)addr;
-    return pModule->module32;
-}
-
-
-/***********************************************************************
  *           BUILTIN_Init
  *
  * Load all built-in modules marked as 'always used'.
  */
 BOOL32 BUILTIN_Init(void)
 {
-    BUILTIN_DLL *dll;
+    BUILTIN16_DLL *dll;
     NE_MODULE *pModule;
     WORD vector;
     HMODULE16 hModule;
 
     for (dll = BuiltinDLLs; dll->descr; dll++)
     {
-        if (!(dll->flags & DLL_FLAG_ALWAYS_USED)) continue;
-        if (dll->flags & DLL_FLAG_WIN32)
-        {
-            if (!BUILTIN_DoLoadModule32( dll )) return FALSE;
-        }
-        else
-        {
-            if (!BUILTIN_DoLoadModule16( &dll->descr->win16 )) return FALSE;
-        }
+        if (dll->flags & DLL_FLAG_ALWAYS_USED)
+            if (!BUILTIN_DoLoadModule16( dll->descr )) return FALSE;
     }
 
     /* Set the USER and GDI heap selectors */
@@ -488,7 +231,7 @@
  */
 HMODULE32 BUILTIN_LoadModule( LPCSTR name, BOOL32 force )
 {
-    BUILTIN_DLL *table;
+    BUILTIN16_DLL *table;
     char dllname[16], *p;
 
     /* Fix the name in case we have a full path and extension */
@@ -499,13 +242,10 @@
 
     for (table = BuiltinDLLs; table->descr; table++)
         if (!lstrcmpi32A( table->descr->name, dllname )) break;
-    if (!table->descr) return 0;
+    if (!table->descr) return BUILTIN32_LoadModule( name, force );
     if ((table->flags & DLL_FLAG_NOT_USED) && !force) return 0;
 
-    if (table->flags & DLL_FLAG_WIN32)
-        return BUILTIN_DoLoadModule32( table );
-    else
-        return BUILTIN_DoLoadModule16( &table->descr->win16 );
+    return BUILTIN_DoLoadModule16( table->descr );
 }
 
 
@@ -584,45 +324,6 @@
 }
 
 
-/***********************************************************************
- *           BUILTIN_GetEntryPoint32
- *
- * Return the name of the DLL entry point corresponding
- * to a relay entry point address. This is used only by relay debugging.
- *
- * This function _must_ return the real entry point to call
- * after the debug info is printed.
- */
-FARPROC32 BUILTIN_GetEntryPoint32( char *buffer, void *relay, DWORD *typemask )
-{
-    BUILTIN_DLL *dll;
-    int ordinal, i;
-    const WIN32_DESCRIPTOR *descr;
-
-    /* First find the module */
-
-    for (dll = BuiltinDLLs; dll->descr; dll++)
-        if ((dll->flags & DLL_FLAG_WIN32) &&
-            ((void *)dll->dbg_funcs <= relay) &&
-            ((void *)(dll->dbg_funcs + dll->descr->win32.nb_funcs) > relay))
-            break;
-    assert(dll->descr);
-    descr = &dll->descr->win32;
-
-    /* Now find the function */
-
-    ordinal = ((DWORD)relay-(DWORD)dll->dbg_funcs) / sizeof(DEBUG_ENTRY_POINT);
-    for (i = 0; i < descr->nb_names; i++)
-        if (descr->ordinals[i] == ordinal) break;
-    assert( i < descr->nb_names );
-
-    sprintf( buffer, "%s.%d: %s", descr->name, ordinal + descr->base,
-             descr->names[i] );
-    *typemask = descr->argtypes[ordinal];
-    return (FARPROC32)descr->functions[ordinal];
-}
-
-
 /**********************************************************************
  *	    BUILTIN_DefaultIntHandler
  *
@@ -644,7 +345,7 @@
  */
 BOOL32 BUILTIN_ParseDLLOptions( const char *str )
 {
-    BUILTIN_DLL *dll;
+    BUILTIN16_DLL *dll;
     const char *p;
 
     while (*str)
@@ -685,7 +386,7 @@
 void BUILTIN_PrintDLLs(void)
 {
     int i;
-    BUILTIN_DLL *dll;
+    BUILTIN16_DLL *dll;
 
     fprintf(stderr,"Example: -dll -ole2    Do not use emulated OLE2.DLL\n");
     fprintf(stderr,"Available DLLs:\n");
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index c7fa8da..db1dae2 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -213,16 +213,16 @@
 213 stub KERNEL_213
 214 stub KERNEL_214
 216 pascal   RegEnumKey(long long ptr long) RegEnumKey16
-217 pascal   RegOpenKey(long ptr ptr) RegOpenKey16
-218 pascal   RegCreateKey(long ptr ptr) RegCreateKey16
-219 pascal   RegDeleteKey(long ptr) RegDeleteKey16
+217 pascal   RegOpenKey(long str ptr) RegOpenKey16
+218 pascal   RegCreateKey(long str ptr) RegCreateKey16
+219 pascal   RegDeleteKey(long str) RegDeleteKey16
 220 pascal   RegCloseKey(long) RegCloseKey
-221 pascal   RegSetValue(long ptr long ptr long) RegSetValue16
-222 pascal   RegDeleteValue(long ptr) RegDeleteValue16
+221 pascal   RegSetValue(long str long ptr long) RegSetValue16
+222 pascal   RegDeleteValue(long str) RegDeleteValue16
 223 pascal   RegEnumValue(long long ptr ptr ptr ptr ptr ptr) RegEnumValue16
-224 pascal   RegQueryValue(long ptr ptr ptr) RegQueryValue16
-225 pascal   RegQueryValueEx(long ptr ptr ptr ptr ptr) RegQueryValueEx16
-226 pascal   RegSetValueEx(long ptr long long ptr long) RegSetValueEx16
+224 pascal   RegQueryValue(long str ptr ptr) RegQueryValue16
+225 pascal   RegQueryValueEx(long str ptr ptr ptr ptr) RegQueryValueEx16
+226 pascal   RegSetValueEx(long str long long ptr long) RegSetValueEx16
 227 pascal   RegFlushKey(long) RegFlushKey
 228 stub K228
 229 stub K229
@@ -298,7 +298,7 @@
 420 pascal   GetFileAttributes(ptr) GetFileAttributes16
 421 pascal16 SetFileAttributes(ptr long) SetFileAttributes16
 422 pascal16 GetDiskFreeSpace(ptr ptr ptr ptr ptr) GetDiskFreeSpace16 
-431 stub KERNEL_431
+431 pascal16 KERNEL_431(str word) KERNEL_431
 432 stub FileTimeToLocalFileTime
 435 stub KERNEL_435
 439 stub KERNEL_439
diff --git a/if1632/mmsystem.spec b/if1632/mmsystem.spec
index c0178e1..cd9889a 100644
--- a/if1632/mmsystem.spec
+++ b/if1632/mmsystem.spec
@@ -12,14 +12,14 @@
 32     stub    STACKENTER
 33     stub    STACKLEAVE
 34     stub    MMDRVINSTALL
-101    pascal  JOYGETNUMDEVS() JoyGetNumDevs
-102    pascal  JOYGETDEVCAPS(word ptr word) JoyGetDevCaps
-103    pascal  JOYGETPOS(word ptr) JoyGetPos
-104    pascal  JOYGETTHRESHOLD(word ptr) JoyGetThreshold
-105    pascal  JOYRELEASECAPTURE(word) JoyReleaseCapture
-106    pascal  JOYSETCAPTURE(word word word word) JoySetCapture
-107    pascal  JOYSETTHRESHOLD(word word) JoySetThreshold
-109    pascal  JOYSETCALIBRATION(word) JoySetCalibration
+101    pascal  joyGetNumDevs() joyGetNumDevs16
+102    pascal  joyGetDevCaps(word ptr word) joyGetDevCaps16
+103    pascal  joyGetPos(word ptr) joyGetPos16
+104    pascal  joyGetThreshold(word ptr) joyGetThreshold16
+105    pascal  joyReleaseCapture(word) joyReleaseCapture16
+106    pascal  joySetCapture(word word word word) joySetCapture16
+107    pascal  joySetThreshold(word word) joySetThreshold16
+109    pascal  joySetCalibration(word) joySetCalibration16
 110    stub    JOYGETPOSEX
 111    stub    JOYCONFIGCHANGED
 201    pascal  midiOutGetNumDevs() midiOutGetNumDevs16
@@ -99,20 +99,20 @@
 512    pascal  waveInGetPosition(word ptr word) waveInGetPosition16
 513    pascal  waveInGetID(word ptr) waveInGetID16
 514    pascal  waveInMessage(word word long long) waveInMessage16
-601    pascal  timeGetSystemTime(ptr word) timeGetSystemTime
-602    pascal  timeSetEvent(word word segptr long word) timeSetEvent
-603    pascal  timeKillEvent(word) timeKillEvent
-604    pascal  timeGetDevCaps(ptr word) timeGetDevCaps
-605    pascal  timeBeginPeriod(word) timeBeginPeriod
-606    pascal  timeEndPeriod(word) timeEndPeriod
+601    pascal  timeGetSystemTime(ptr word) timeGetSystemTime16
+602    pascal  timeSetEvent(word word segptr long word) timeSetEvent16
+603    pascal  timeKillEvent(word) timeKillEvent16
+604    pascal  timeGetDevCaps(ptr word) timeGetDevCaps16
+605    pascal  timeBeginPeriod(word) timeBeginPeriod16
+606    pascal  timeEndPeriod(word) timeEndPeriod16
 607    pascal  timeGetTime() timeGetTime
 701    pascal  MCISENDCOMMAND(word word long long) mciSendCommand
 702    pascal  MCISENDSTRING(str ptr word word) mciSendString
-703    pascal  MCIGETDEVICEID(ptr) mciGetDeviceID
-705    stub    MCILOADCOMMANDRESOURCE
+703    pascal  mciGetDeviceID(ptr) mciGetDeviceID
+705    pascal  mciLoadCommandResource(word str word) mciLoadCommandResource16
 706    pascal  mciGetErrorString(long ptr word) mciGetErrorString16
-707    stub    MCISETDRIVERDATA
-708    stub    MCIGETDRIVERDATA
+707    pascal  mciSetDriverData(word long) mciSetDriverData16
+708    pascal  mciGetDriverData(word) mciGetDriverData16
 710    stub    MCIDRIVERYIELD
 711    stub    MCIDRIVERNOTIFY
 712    stub    MCIEXECUTE
@@ -131,9 +131,9 @@
 807    pascal  mixerGetLineControls(word ptr long) mixerGetLineControls16
 808    pascal  mixerGetControlDetails(word ptr long) mixerGetControlDetails16
 809    pascal  mixerSetControlDetails(word ptr long) mixerSetControlDetails16
-900    stub    MMTASKCREATE
+900    pascal  mmTaskCreate(ptr long long) mmTaskCreate16
 902    stub    MMTASKBLOCK
-903    stub    MMTASKSIGNAL
+903    pascal  mmTaskSignal(word) mmTaskSignal16
 904    stub    MMGETCURRENTTASK
 905    stub    MMTASKYIELD
 1100   pascal  DRVOPEN(str str long) DrvOpen
@@ -141,12 +141,12 @@
 1102   pascal  DRVSENDMESSAGE(word word long long) DrvSendMessage
 1103   pascal  DRVGETMODULEHANDLE(word) DrvGetModuleHandle
 1104   pascal  DRVDEFDRIVERPROC(long word word long long) DrvDefDriverProc
-1120   stub    MMTHREADCREATE
-1121   stub    MMTHREADSIGNAL
+1120   pascal  mmThreadCreate(ptr ptr long long) mmThreadCreate16
+1121   pascal  mmThreadSignal(word) mmThreadSignal16
 1122   stub    MMTHREADBLOCK
 1123   stub    MMTHREADISCURRENT
 1124   stub    MMTHREADISVALID
-1125   stub    MMTHREADGETTASK
+1125   pascal  mmThreadGetTask(word) mmThreadGetTask16
 1150   stub    MMSHOWMMCPLPROPERTYSHEET
 1210   pascal  mmioOpen(str ptr long) mmioOpen16
 1211   pascal  MMIOCLOSE(word word) mmioClose
diff --git a/if1632/ole2thk.spec b/if1632/ole2thk.spec
new file mode 100644
index 0000000..e945a98
--- /dev/null
+++ b/if1632/ole2thk.spec
@@ -0,0 +1,10 @@
+name	ole2thk
+type	win16
+
+1 stub WEP
+2 stub ROT16_ISRUNNING16
+3 stub ISWIN32SHANDLE
+4 stub ___EXPORTEDSTUB
+5 stub COTHKCOMMON
+6 stub ROT16_GETTIMEOFLASTCHANGE16
+7 stub ROT16_GETOBJECT16
diff --git a/if1632/relay.c b/if1632/relay.c
index a49114d..6596be5 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -232,208 +232,6 @@
 }
 
 
-/***********************************************************************
- *           RELAY_CallFrom32
- *
- * Stack layout on entry to this function:
- *  ...      ...
- * (esp+12)  arg2
- * (esp+8)   arg1
- * (esp+4)   ret_addr
- * (esp)     return addr to relay code
- */
-int RELAY_CallFrom32( int ret_addr, ... )
-{
-    int i, ret;
-    char buffer[80];
-    FARPROC32 func;
-    DWORD mask, typemask;
-
-    int *args = &ret_addr;
-    /* Relay addr is the return address for this function */
-    BYTE *relay_addr = (BYTE *)args[-1];
-    WORD nb_args = *(WORD *)(relay_addr + 1) / sizeof(int);
-
-    assert(debugging_relay);
-    func = BUILTIN_GetEntryPoint32( buffer, relay_addr - 5, &typemask );
-    printf( "Call %s(", buffer );
-    args++;
-    for (i = 0, mask = 3; i < nb_args; i++, mask <<= 2)
-    {
-        if (i) printf( "," );
-	if ((typemask & mask) && HIWORD(args[i]))
-        {
-	    if (typemask & (2<<(2*i)))
-            {
-                char buff[80];
-                lstrcpynWtoA( buff, (LPWSTR)args[i], sizeof(buff) );
-	    	printf( "%08x L\"%s\"", args[i], buff );
-	    }
-            else printf( "%08x \"%s\"", args[i], (char *)args[i] );
-	}
-        else printf( "%08x", args[i] );
-    }
-    printf( ") ret=%08x\n", ret_addr );
-    if (*relay_addr == 0xc3) /* cdecl */
-    {
-        LRESULT (*cfunc)() = (LRESULT(*)())func;
-        switch(nb_args)
-        {
-        case 0: ret = cfunc(); break;
-        case 1: ret = cfunc(args[0]); break;
-        case 2: ret = cfunc(args[0],args[1]); break;
-        case 3: ret = cfunc(args[0],args[1],args[2]); break;
-        case 4: ret = cfunc(args[0],args[1],args[2],args[3]); break;
-        case 5: ret = cfunc(args[0],args[1],args[2],args[3],args[4]); break;
-        case 6: ret = cfunc(args[0],args[1],args[2],args[3],args[4],
-                            args[5]); break;
-        case 7: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
-                            args[6]); break;
-        case 8: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
-                            args[6],args[7]); break;
-        case 9: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
-                            args[6],args[7],args[8]); break;
-        case 10: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
-                             args[6],args[7],args[8],args[9]); break;
-        case 11: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
-                             args[6],args[7],args[8],args[9],args[10]); break;
-        case 12: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
-                             args[6],args[7],args[8],args[9],args[10],
-                             args[11]); break;
-        case 13: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
-                             args[6],args[7],args[8],args[9],args[10],args[11],
-                             args[12]); break;
-        case 14: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
-                             args[6],args[7],args[8],args[9],args[10],args[11],
-                             args[12],args[13]); break;
-        case 15: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
-                             args[6],args[7],args[8],args[9],args[10],args[11],
-                             args[12],args[13],args[14]); break;
-        default:
-            fprintf( stderr, "RELAY_CallFrom32: Unsupported nb args %d\n",
-                     nb_args );
-            assert(FALSE);
-        }
-    }
-    else  /* stdcall */
-    {
-        switch(nb_args)
-        {
-        case 0: ret = func(); break;
-        case 1: ret = func(args[0]); break;
-        case 2: ret = func(args[0],args[1]); break;
-        case 3: ret = func(args[0],args[1],args[2]); break;
-        case 4: ret = func(args[0],args[1],args[2],args[3]); break;
-        case 5: ret = func(args[0],args[1],args[2],args[3],args[4]); break;
-        case 6: ret = func(args[0],args[1],args[2],args[3],args[4],
-                           args[5]); break;
-        case 7: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
-                           args[6]); break;
-        case 8: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
-                           args[6],args[7]); break;
-        case 9: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
-                           args[6],args[7],args[8]); break;
-        case 10: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
-                            args[6],args[7],args[8],args[9]); break;
-        case 11: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
-                            args[6],args[7],args[8],args[9],args[10]); break;
-        case 12: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
-                            args[6],args[7],args[8],args[9],args[10],
-                            args[11]); break;
-        case 13: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
-                            args[6],args[7],args[8],args[9],args[10],args[11],
-                            args[12]); break;
-        case 14: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
-                            args[6],args[7],args[8],args[9],args[10],args[11],
-                            args[12],args[13]); break;
-        case 15: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
-                            args[6],args[7],args[8],args[9],args[10],args[11],
-                            args[12],args[13],args[14]); break;
-        default:
-            fprintf( stderr, "RELAY_CallFrom32: Unsupported nb args %d\n",
-                     nb_args );
-            assert(FALSE);
-        }
-    }
-    printf( "Ret  %s() retval=%08x ret=%08x\n", buffer, ret, ret_addr );
-    return ret;
-}
-
-
-/***********************************************************************
- *           RELAY_CallFrom32Regs
- *
- * 'stack' points to the relay addr on the stack.
- * Stack layout:
- *  ...      ...
- * (esp+216) ret_addr
- * (esp+212) return to relay debugging code (only when debugging_relay)
- * (esp+208) entry point to call
- * (esp+4)   CONTEXT
- * (esp)     return addr to relay code
- */
-void RELAY_CallFrom32Regs( CONTEXT context,
-                           void (CALLBACK *entry_point)(CONTEXT *),
-                           BYTE *relay_addr, int ret_addr )
-{
-    if (!debugging_relay)
-    {
-        /* Simply call the entry point */
-        entry_point( &context );
-    }
-    else
-    {
-        char buffer[80];
-        DWORD typemask;
-
-    	__RESTORE_ES;
-        /* Fixup the context structure because of the extra parameter */
-        /* pushed by the relay debugging code */
-
-        EIP_reg(&context) = ret_addr;
-        ESP_reg(&context) += sizeof(int);
-
-        BUILTIN_GetEntryPoint32( buffer, relay_addr - 5, &typemask );
-        printf("Call %s(regs) ret=%08x\n", buffer, ret_addr );
-        printf(" EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx ESI=%08lx EDI=%08lx\n",
-                EAX_reg(&context), EBX_reg(&context), ECX_reg(&context),
-                EDX_reg(&context), ESI_reg(&context), EDI_reg(&context) );
-        printf(" EBP=%08lx ESP=%08lx EIP=%08lx DS=%04lx ES=%04lx FS=%04lx GS=%04lx EFL=%08lx\n",
-                EBP_reg(&context), ESP_reg(&context), EIP_reg(&context),
-                DS_reg(&context), ES_reg(&context), FS_reg(&context),
-                GS_reg(&context), EFL_reg(&context) );
-
-        /* Now call the real function */
-        entry_point( &context );
-
-        printf("Ret  %s() retval=regs ret=%08x\n", buffer, ret_addr );
-        printf(" EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx ESI=%08lx EDI=%08lx\n",
-                EAX_reg(&context), EBX_reg(&context), ECX_reg(&context),
-                EDX_reg(&context), ESI_reg(&context), EDI_reg(&context) );
-        printf(" EBP=%08lx ESP=%08lx EIP=%08lx DS=%04lx ES=%04lx FS=%04lx GS=%04lx EFL=%08lx\n",
-                EBP_reg(&context), ESP_reg(&context), EIP_reg(&context),
-                DS_reg(&context), ES_reg(&context), FS_reg(&context),
-                GS_reg(&context), EFL_reg(&context) );
-    }
-}
-
-
-/***********************************************************************
- *           RELAY_Unimplemented32
- *
- * This function is called for unimplemented 32-bit entry points (declared
- * as 'stub' in the spec file).
- */
-void RELAY_Unimplemented32( const char *dll_name, int ordinal,
-                            const char *func_name, int ret_addr )
-{
-    __RESTORE_ES;  /* Just in case */
-    fprintf( stderr, "No handler for Win32 routine %s.%d: %s (called from %08x)\n",
-             dll_name, ordinal, func_name, ret_addr );
-    TASK_KillCurrentTask(1);
-}
-
-
 /**********************************************************************
  *	     Catch    (KERNEL.55)
  *
diff --git a/if1632/thunk.c b/if1632/thunk.c
index 4a9a446..5bb6eba 100644
--- a/if1632/thunk.c
+++ b/if1632/thunk.c
@@ -1,10 +1,10 @@
 /*
- * Emulator and Win95 thunks
+ * Emulator thunks
  *
  * Copyright 1996, 1997 Alexandre Julliard
- * Copyright 1997 Marcus Meissner
  */
 
+#include <stdio.h>
 #include "windows.h"
 #include "callback.h"
 #include "resource.h"
@@ -26,8 +26,8 @@
 /* by the build program to generate the file if1632/callto16.S */
 
 /* ### start build ### */
-extern LONG CALLBACK CallTo16_regs_short(const CONTEXT *context, INT32 offset);
-extern LONG CALLBACK CallTo16_regs_long (const CONTEXT *context, INT32 offset);
+extern LONG CALLBACK CallTo16_sreg_(const CONTEXT *context, INT32 offset);
+extern LONG CALLBACK CallTo16_lreg_(const CONTEXT *context, INT32 offset);
 extern WORD CALLBACK CallTo16_word_     (FARPROC16);
 extern WORD CALLBACK CallTo16_word_w    (FARPROC16,WORD);
 extern LONG CALLBACK CallTo16_long_l    (FARPROC16,LONG);
@@ -98,7 +98,8 @@
 /* Callbacks function table for the emulator */
 static const CALLBACKS_TABLE CALLBACK_EmulatorTable =
 {
-    (void *)CallTo16_regs_short,           /* CallRegisterProc */
+    (void *)CallTo16_sreg_,                /* CallRegisterShortProc */
+    (void *)CallTo16_lreg_,                /* CallRegisterLongProc */
     THUNK_CallTaskReschedule,              /* CallTaskRescheduleProc */
     CallFrom16_long_wwwll,                 /* CallFrom16WndProc */
     THUNK_CallWndProc16,                   /* CallWndProc */
@@ -110,6 +111,7 @@
     (void *)CallTo16_word_ww,              /* CallBootAppProc */
     (void *)CallTo16_word_www,             /* CallLoadAppSegProc */
     (void *)CallTo16_word_,                /* CallSystemTimerProc */
+    (void *)CallTo16_long_l,               /* CallWOWCallbackProc */
     (void *)CallTo16_long_l,               /* CallASPIPostProc */
     (void *)CallTo16_word_lwll,            /* CallDrvControlProc */
     (void *)CallTo16_word_lwlll,           /* CallDrvEnableProc */
@@ -183,7 +185,7 @@
             return;
         }
     }
-    fprintf( stderr, "THUNK_Free: invalid thunk addr %p\n", thunk );
+    dprintf_thunk( stddeb, "THUNK_Free: invalid thunk addr %p\n", thunk );
 }
 
 
@@ -246,7 +248,7 @@
     args[4] = hwnd;
     /* args[5] and args[6] are used by relay code to store the stack pointer */
 
-    ret = CallTo16_regs_short( &context, -(5 * sizeof(WORD)) );
+    ret = CallTo16_sreg_( &context, -(5 * sizeof(WORD)) );
     if (offset) STACK16_POP(offset);
     return ret;
 }
@@ -572,598 +574,3 @@
     }
     return NULL;
 }
-
-
-/***********************************************************************
- *                                                                     *
- *                 Win95 internal thunks                               *
- *                                                                     *
- ***********************************************************************/
-
-/***********************************************************************
- * Generates a FT_Prolog call.
- *	
- *  0FB6D1                  movzbl edx,cl
- *  8B1495xxxxxxxx	    mov edx,[4*edx + xxxxxxxx]
- *  68xxxxxxxx		    push FT_Prolog
- *  C3			    lret
- */
-static void _write_ftprolog(LPBYTE thunk,DWORD thunkstart) {
-	LPBYTE	x;
-
-	x	= thunk;
-	*x++	= 0x0f;*x++=0xb6;*x++=0xd1; /* movzbl edx,cl */
-	*x++	= 0x8B;*x++=0x14;*x++=0x95;*(DWORD*)x= thunkstart;
-	x+=4;	/* mov edx, [4*edx + thunkstart] */
-	*x++	= 0x68; *(DWORD*)x = (DWORD)GetProcAddress32(GetModuleHandle32A("KERNEL32"),"FT_Prolog");
-	x+=4; 	/* push FT_Prolog */
-	*x++	= 0xC3;		/* lret */
-	/* fill rest with 0xCC / int 3 */
-}
-
-/***********************************************************************
- *			FT_PrologPrime			(KERNEL32.89)
- */
-void WINAPI FT_PrologPrime(DWORD startind,LPBYTE thunk) {
-	_write_ftprolog(thunk,*(DWORD*)(startind+thunk));
-}
-
-/***********************************************************************
- * Generates a QT_Thunk style call.
- *	
- *  33C9                    xor ecx, ecx
- *  8A4DFC                  mov cl , [ebp-04]
- *  8B148Dxxxxxxxx          mov edx, [4*ecx + (EAX+EDX)]
- *  B8yyyyyyyy              mov eax, QT_Thunk
- *  FFE0                    jmp eax
- */
-static void _write_qtthunk(LPBYTE start,DWORD thunkstart) {
-	LPBYTE	x;
-
-	x	= start;
-	*x++	= 0x33;*x++=0xC9; /* xor ecx,ecx */
-	*x++	= 0x8A;*x++=0x4D;*x++=0xFC; /* movb cl,[ebp-04] */
-	*x++	= 0x8B;*x++=0x14;*x++=0x8D;*(DWORD*)x= thunkstart;
-	x+=4;	/* mov edx, [4*ecx + (EAX+EDX) */
-	*x++	= 0xB8; *(DWORD*)x = (DWORD)GetProcAddress32(GetModuleHandle32A("KERNEL32"),"QT_Thunk");
-	x+=4; 	/* mov eax , QT_Thunk */
-	*x++	= 0xFF; *x++ = 0xE0;	/* jmp eax */
-	/* should fill the rest of the 32 bytes with 0xCC */
-}
-
-/***********************************************************************
- *		ThunkConnect32		(KERNEL32)
- * Connects a 32bit and a 16bit thunkbuffer.
- */
-struct thunkstruct
-{
-	char	magic[4];
-	DWORD	length;
-	DWORD	ptr;
-	DWORD	x0C;
-
-	DWORD	x10;
-	DWORD	x14;
-	DWORD	x18;
-	DWORD	x1C;
-	DWORD	x20;
-};
-
-UINT32 WINAPI ThunkConnect32( struct thunkstruct *ths, LPSTR thunkfun16,
-                              LPSTR module16, LPSTR module32, HMODULE32 hmod32,
-                              DWORD dllinitarg1 )
-{
-	HINSTANCE16	hmm;
-	SEGPTR		thkbuf;
-	struct	thunkstruct	*ths16;
-
-	fprintf(stdnimp,"ThunkConnect32(<struct>,%s,%s,%s,%x,%lx)\n",
-		thunkfun16,module32,module16,hmod32,dllinitarg1
-	);
-	fprintf(stdnimp,"	magic = %c%c%c%c\n",
-		ths->magic[0],
-		ths->magic[1],
-		ths->magic[2],
-		ths->magic[3]
-	);
-	fprintf(stdnimp,"	length = %lx\n",ths->length);
-	if (lstrncmp32A(ths->magic,"SL01",4)&&lstrncmp32A(ths->magic,"LS01",4))
-		return 0;
-	hmm=LoadModule16(module16,NULL);
-	if (hmm<=32)
-		return 0;
-	thkbuf=(SEGPTR)WIN32_GetProcAddress16(hmm,thunkfun16);
-	if (!thkbuf)
-		return 0;
-	ths16=(struct thunkstruct*)PTR_SEG_TO_LIN(thkbuf);
-	if (lstrncmp32A(ths16->magic,ths->magic,4))
-		return 0;
-
-	if (!lstrncmp32A(ths->magic,"SL01",4))  {
-		if (ths16->length != ths->length)
-			return 0;
-		ths->x0C = (DWORD)ths16;
-
-		fprintf(stderr,"	ths16 magic is 0x%08lx\n",*(DWORD*)ths16->magic);
-		if (*((DWORD*)ths16->magic) != 0x0000304C)
-			return 0;
-		if (!*(WORD*)(((LPBYTE)ths16)+0x12))
-			return 0;
-		
-	}
-	if (!lstrncmp32A(ths->magic,"LS01",4))  {
-		if (ths16->length != ths->length)
-			return 0;
-		ths->ptr = (DWORD)PTR_SEG_TO_LIN(ths16->ptr);
-		/* code offset for QT_Thunk is at 0x1C...  */
-		_write_qtthunk (((LPBYTE)ths) + ths->x1C,ths->ptr);
-		/* code offset for FT_Prolog is at 0x20...  */
-		_write_ftprolog(((LPBYTE)ths) + ths->x20,ths->ptr);
-		return 1;
-	}
-	return TRUE;
-}
-
-
-/**********************************************************************
- * 		QT_Thunk			(KERNEL32)
- *
- * The target address is in EDX.
- * The 16 bit arguments start at ESP+4.
- * The number of 16bit argumentbytes is EBP-ESP-0x44 (68 Byte thunksetup).
- * [ok]
- */
-VOID WINAPI QT_Thunk(CONTEXT *context)
-{
-	CONTEXT	context16;
-	DWORD	argsize;
-
-	memcpy(&context16,context,sizeof(context16));
-
-	CS_reg(&context16)	 = HIWORD(EDX_reg(context));
-	IP_reg(&context16)	 = LOWORD(EDX_reg(context));
-
-	argsize = EBP_reg(context)-ESP_reg(context)-0x44;
-
-	/* additional 4 bytes used by the relaycode for storing the stackptr */
-	memcpy(	((LPBYTE)CURRENT_STACK16)-argsize-4,
-		(LPBYTE)ESP_reg(context)+4,
-		argsize
-	);
-	EAX_reg(context) = CallTo16_regs_short(&context16,-argsize);
-}
-
-
-/**********************************************************************
- *           WOWCallback16 (KERNEL32.62)
- */
-DWORD WINAPI WOWCallback16(FARPROC16 fproc,DWORD arg)
-{
-	DWORD	ret;
-	fprintf(stderr,"WOWCallback16(%p,0x%08lx) ",fproc,arg);
-	ret =  CallTo16_long_l(fproc,arg);
-	fprintf(stderr,"... returns %ld\n",ret);
-	return ret;
-}
-
-/***********************************************************************
- *           _KERNEL32_52    (KERNEL32.52)
- * Returns a pointer to ThkBuf in the 16bit library SYSTHUNK.DLL.
- * [ok probably]
- */
-LPVOID WINAPI _KERNEL32_52()
-{
-	HMODULE32	hmod = LoadLibrary16("systhunk.dll");
-
-	if (hmod<=32)
-		return 0;
-	return PTR_SEG_TO_LIN(WIN32_GetProcAddress16(hmod,"ThkBuf"));
-}
-
-/***********************************************************************
- * 		_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)
- * [ok probably]
- */
-DWORD WINAPI _KERNEL32_43(LPDWORD thunk,LPCSTR thkbuf,DWORD len,
-                           LPCSTR dll16,LPCSTR dll32)
-{
-	HINSTANCE16	hmod;
-	LPDWORD		addr;
-	SEGPTR		segaddr;
-
-	hmod = LoadLibrary16(dll16);
-	if (hmod<32) {
-		fprintf(stderr,"KERNEL32_43->failed to load 16bit DLL %s, error %d\n",dll16,hmod);
-		return 0;
-	}
-	segaddr = (DWORD)WIN32_GetProcAddress16(hmod,(LPSTR)thkbuf);
-	if (!segaddr) {
-		fprintf(stderr,"KERNEL32_43->no %s exported from %s!\n",thkbuf,dll16);
-		return 0;
-	}
-	addr = (LPDWORD)PTR_SEG_TO_LIN(segaddr);
-	if (addr[0] != len) {
-		fprintf(stderr,"KERNEL32_43->thkbuf length mismatch? %ld vs %ld\n",len,addr[0]);
-		return 0;
-	}
-	if (!addr[1])
-		return 0;
-	*(DWORD*)thunk = addr[1];
-	return addr[1];
-}
-
-/***********************************************************************
- * 		_KERNEL32_45 	(KERNEL32.44)
- * Another 32->16 thunk, the difference to QT_Thunk is, that the called routine
- * uses 0x66 lret, and that we have to pass CX in DI.
- * (there seems to be some kind of BL/BX return magic too...)
- *
- * [doesn't crash anymore]
- */
-VOID WINAPI _KERNEL32_45(CONTEXT *context)
-{
-	CONTEXT	context16;
-	LPBYTE	curstack;
-	DWORD	ret,stacksize;
-
-	fprintf(stderr,"KERNEL32_45(%%eax=0x%08lx(%%cx=0x%04lx,%%edx=0x%08lx))\n",
-		(DWORD)EAX_reg(context),(DWORD)CX_reg(context),(DWORD)EDX_reg(context)
-	);
-	stacksize = EBP_reg(context)-ESP_reg(context);
-	fprintf(stderr,"	stacksize = %ld\n",stacksize);
-
-	memcpy(&context16,context,sizeof(context16));
-
-	DI_reg(&context16)	 = CX_reg(context);
-	CS_reg(&context16)	 = HIWORD(EAX_reg(context));
-	IP_reg(&context16)	 = LOWORD(EAX_reg(context));
-
-	curstack = PTR_SEG_TO_LIN(STACK16_PUSH(stacksize));
-	memcpy(curstack-stacksize,(LPBYTE)ESP_reg(context),stacksize);
-	ret = CallTo16_regs_long(&context16,0);
-	STACK16_POP(stacksize);
-
-	fprintf(stderr,". returned %08lx\n",ret);
-	EAX_reg(context) 	 = ret;
-}
-
-/***********************************************************************
- * 		_KERNEL32_40 	(KERNEL32.40)
- * YET Another 32->16 thunk, the difference to the others is still mysterious
- * target address is EDX
- *
- * [crashes]
- */
-VOID WINAPI _KERNEL32_40(CONTEXT *context)
-{
-	CONTEXT	context16;
-	LPBYTE	curstack;
-	DWORD	ret,stacksize;
-
-	fprintf(stderr,"_KERNEL32_40(EDX=0x%08lx)\n",
-		EDX_reg(context)
-	);
-	stacksize = EBP_reg(context)-ESP_reg(context);
-	fprintf(stderr,"	stacksize = %ld\n",stacksize);
-	fprintf(stderr,"on top of stack: 0x%04x\n",*(WORD*)ESP_reg(context));
-
-	memcpy(&context16,context,sizeof(context16));
-
-	CS_reg(&context16)	 = HIWORD(EDX_reg(context));
-	IP_reg(&context16)	 = LOWORD(EDX_reg(context));
-
-	curstack = PTR_SEG_TO_LIN(STACK16_PUSH(stacksize));
-	memcpy(curstack-stacksize,(LPBYTE)ESP_reg(context),stacksize);
-	ret = CallTo16_regs_short(&context16,0);
-	STACK16_POP(stacksize);
-
-	fprintf(stderr,". returned %08lx\n",ret);
-	EAX_reg(context) 	 = ret;
-}
-
-/***********************************************************************
- *		(KERNEL32.41)
- * A thunk setup routine.
- * Expects a pointer to a preinitialized thunkbuffer in the first argument
- * looking like:
- *	00..03:		unknown	(pointer, check _41, _43, _46)
- *	04: EB1E		jmp +0x20
- *
- *	06..23:		unknown (space for replacement code, check .90)
- *
- *	24:>E800000000		call offset 29
- *	29:>58			pop eax		   ( target of call )
- *	2A: 2D25000000		sub eax,0x00000025 ( now points to offset 4 )
- *	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'.
- * [ok probably]
- */
-
-LPVOID WINAPI _KERNEL32_41(LPBYTE thunk,LPCSTR thkbuf,DWORD len,LPCSTR dll16,
-                           LPCSTR dll32)
-{
-	HMODULE32	hkrnl32 = GetModuleHandle32A("KERNEL32");
-	HMODULE16	hmod;
-	LPDWORD		addr,addr2;
-	DWORD		segaddr;
-
-	/* 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)90);
-	*(DWORD*)(thunk+0x6D) = (DWORD)GetProcAddress32(hkrnl32,(LPSTR)89);
-
-	
-	hmod = LoadLibrary16(dll16);
-	if (hmod<32) {
-		fprintf(stderr,"KERNEL32_41->failed to load 16bit DLL %s, error %d\n",dll16,hmod);
-		return NULL;
-	}
-	segaddr = (DWORD)WIN32_GetProcAddress16(hmod,(LPSTR)thkbuf);
-	if (!segaddr) {
-		fprintf(stderr,"KERNEL32_41->no %s exported from %s!\n",thkbuf,dll16);
-		return NULL;
-	}
-	addr = (LPDWORD)PTR_SEG_TO_LIN(segaddr);
-	if (addr[0] != len) {
-		fprintf(stderr,"KERNEL32_41->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.90)
- * QT Thunk priming function
- * Rewrites the first part of the thunk to use the QT_Thunk interface
- * and jumps to the start of that code.
- * [ok]
- */
-VOID WINAPI _KERNEL32_90(CONTEXT *context)
-{
-	_write_qtthunk((LPBYTE)EAX_reg(context),*(DWORD*)(EAX_reg(context)+EDX_reg(context)));
-	/* we just call the real QT_Thunk right now 
-	 * we can bypass the relaycode, for we already have the registercontext
-	 */
-	EDX_reg(context) = *(DWORD*)((*(DWORD*)(EAX_reg(context)+EDX_reg(context)))+4*(((BYTE*)EBP_reg(context))[-4]));
-	return QT_Thunk(context);
-}
-
-/***********************************************************************
- *							(KERNEL32.45)
- * Another thunkbuf link routine.
- * The start of the thunkbuf looks like this:
- * 	00: DWORD	length
- *	04: SEGPTR	address for thunkbuffer pointer
- * [ok probably]
- */
-VOID WINAPI _KERNEL32_46(LPBYTE thunk,LPSTR thkbuf,DWORD len,LPSTR dll16,
-                         LPSTR dll32)
-{
-	LPDWORD		addr;
-	HMODULE16	hmod;
-	SEGPTR		segaddr;
-
-	hmod = LoadLibrary16(dll16);
-	if (hmod < 32) {
-		fprintf(stderr,"KERNEL32_46->couldn't load %s, error %d\n",dll16,hmod);
-		return;
-	}
-	segaddr = (SEGPTR)WIN32_GetProcAddress16(hmod,thkbuf);
-	if (!segaddr) {
-		fprintf(stderr,"KERNEL32_46-> haven't found %s in %s!\n",thkbuf,dll16);
-		return;
-	}
-	addr = (LPDWORD)PTR_SEG_TO_LIN(segaddr);
-	if (addr[0] != len) {
-		fprintf(stderr,"KERNEL32_46-> 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.)
- * We do that differently, so just return TRUE.
- * [ok]
- */
-BOOL32 WINAPI _KERNEL32_87()
-{
-    return TRUE;
-}
-
-/**********************************************************************
- *           _KERNEL32_88
- * One of the real thunking functions. This one seems to be for 32<->32
- * thunks. It should probably be capable of crossing processboundaries.
- *
- * And YES, I've seen nr=48 (somewhere in the Win95 32<->16 OLE coupling)
- * [ok]
- */
-DWORD WINAPIV _KERNEL32_88( DWORD nr, DWORD flags, FARPROC32 fun, ... )
-{
-    DWORD i,ret;
-    DWORD *args = ((DWORD *)&fun) + 1;
-
-    fprintf(stderr,"KERNEL32_88(%ld,0x%08lx,%p,[ ",nr,flags,fun);
-    for (i=0;i<nr/4;i++) fprintf(stderr,"0x%08lx,",args[i]);
-    fprintf(stderr,"])");
-    switch (nr) {
-    case 0:	ret = fun();
-		break;
-    case 4:	ret = fun(args[0]);
-		break;
-    case 8:	ret = fun(args[0],args[1]);
-		break;
-    case 12:	ret = fun(args[0],args[1],args[2]);
-		break;
-    case 16:	ret = fun(args[0],args[1],args[2],args[3]);
-		break;
-    case 20:	ret = fun(args[0],args[1],args[2],args[3],args[4]);
-		break;
-    case 24:	ret = fun(args[0],args[1],args[2],args[3],args[4],args[5]);
-		break;
-    case 28:	ret = fun(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
-		break;
-    case 32:	ret = fun(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
-		break;
-    case 36:	ret = fun(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
-		break;
-    case 40:	ret = fun(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
-		break;
-    case 44:	ret = fun(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
-		break;
-    case 48:	ret = fun(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
-		break;
-    default:
-	fprintf(stderr,"    unsupported nr of arguments, %ld\n",nr);
-	ret = 0;
-	break;
-
-    }
-    fprintf(stderr," returning %ld ...\n",ret);
-    return ret;
-}
-
-/**********************************************************************
- * 		KERNEL_619		(KERNEL)
- * Seems to store y and z depending on x in some internal lists...
- */
-WORD WINAPI _KERNEL_619(WORD x,DWORD y,DWORD z)
-{
-    fprintf(stderr,"KERNEL_619(0x%04x,0x%08lx,0x%08lx)\n",x,y,z);
-    return x;
-}
-
-/**********************************************************************
- *			AllocSLCallback		(KERNEL32)
- *
- * Win95 uses some structchains for callbacks. It allocates them
- * in blocks of 100 entries, size 32 bytes each, layout:
- * blockstart:
- * 	0:	PTR	nextblockstart
- *	4:	entry	*first;
- *	8:	WORD	sel ( start points to blockstart)
- *	A:	WORD	unknown
- * 100xentry:
- *	00..17:		Code
- *	18:	PDB	*owning_process;
- *	1C:	PTR	blockstart
- *
- * We ignore this for now. (Just a note for further developers)
- * FIXME: use this method, so we don't waste selectors...
- *
- * Following code is then generated by AllocSLCallback. The code is 16 bit, so
- * the 0x66 prefix switches from word->long registers.
- *
- *	665A		pop	edx 
- *	6668x arg2 x 	pushl	<arg2>
- *	6652		push	edx
- *	EAx arg1 x	jmpf	<arg1>
- *
- * returns the startaddress of this thunk.
- *
- * Note, that they look very similair to the ones allocates by THUNK_Alloc.
- */
-DWORD WINAPI
-AllocSLCallback(DWORD finalizer,DWORD callback) {
-	LPBYTE	x,thunk = HeapAlloc( GetProcessHeap(), 0, 32 );
-	WORD	sel;
-
-	x=thunk;
-	*x++=0x66;*x++=0x5a;				/* popl edx */
-	*x++=0x66;*x++=0x68;*(DWORD*)x=finalizer;x+=4;	/* pushl finalizer */
-	*x++=0x66;*x++=0x52;				/* pushl edx */
-	*x++=0xea;*(DWORD*)x=callback;x+=4;		/* jmpf callback */
-
-	*(DWORD*)(thunk+18) = GetCurrentProcessId();
-
-	sel = SELECTOR_AllocBlock( thunk , 32, SEGMENT_CODE, FALSE, FALSE );
-	return (sel<<16)|0;
-}
-
-void WINAPI
-FreeSLCallback(DWORD x) {
-	fprintf(stderr,"FreeSLCallback(0x%08lx)\n",x);
-}
-
-/**********************************************************************
- * 		KERNEL_358		(KERNEL)
- * Allocates a code segment which starts at the address passed in x. limit
- * 0xfffff, and returns the pointer to the start.
- */
-DWORD WINAPI
-_KERNEL_358(DWORD x) {
-	WORD	sel;
-
-	fprintf(stderr,"_KERNEL_358(0x%08lx),stub\n",x);
-	if (!HIWORD(x))
-		return x;
-
-	sel = SELECTOR_AllocBlock( PTR_SEG_TO_LIN(x) , 0xffff, SEGMENT_CODE, FALSE, FALSE );
-	return (sel<<16)|(0x0000);
-}
-
-/**********************************************************************
- * 		KERNEL_359		(KERNEL)
- * Frees the code segment of the passed linear pointer (This has usually
- * been allocated by _KERNEL_358).
- */
-VOID WINAPI
-_KERNEL_359(DWORD x) {
-	DWORD	savedsssp;
-
-	fprintf(stderr,"_KERNEL_359(0x%08lx),stub\n",x);
-	if ((HIWORD(x) & 7)!=7)
-		return;
-	savedsssp = IF1632_Saved16_ss_sp;IF1632_Saved16_ss_sp = 0;
-	SELECTOR_FreeBlock(x>>16,1);
-	IF1632_Saved16_ss_sp = savedsssp;
-	return;
-}
-
-/**********************************************************************
- * 		KERNEL_472		(KERNEL)
- * something like GetCurrenthInstance.
- */
-VOID WINAPI
-_KERNEL_472(CONTEXT *context) {
-	fprintf(stderr,"_KERNEL_472(0x%08lx),stub\n",EAX_reg(context));
-	if (!EAX_reg(context)) {
-		TDB *pTask = (TDB*)GlobalLock16(GetCurrentTask());
-		AX_reg(context)=pTask->hInstance;
-		return;
-	}
-	if (!HIWORD(EAX_reg(context)))
-		return; /* returns the passed value */
-	/* hmm ... fixme */
-}
diff --git a/if1632/toolhelp.spec b/if1632/toolhelp.spec
index c3837e9..9940d99 100644
--- a/if1632/toolhelp.spec
+++ b/if1632/toolhelp.spec
@@ -17,9 +17,9 @@
 63 pascal16 TaskFirst(ptr) TaskFirst
 64 pascal16 TaskNext(ptr) TaskNext
 65 pascal16 TaskFindHandle(ptr word) TaskFindHandle
-66 stub STACKTRACEFIRST
-67 stub STACKTRACECSIPFIRST
-68 stub STACKTRACENEXT
+66 pascal16 StackTraceFirst(ptr word) StackTraceFirst
+67 pascal16 StackTraceCSIPFirst(ptr word word word word) StackTraceCSIPFirst
+68 pascal16 StackTraceNext(ptr) StackTraceNext
 69 pascal16 ClassFirst(ptr) ClassFirst
 70 pascal16 ClassNext(ptr) ClassNext
 71 pascal16 SystemHeapInfo(ptr) SystemHeapInfo
diff --git a/if1632/user.spec b/if1632/user.spec
index fef3bfc..814a19f 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -346,7 +346,7 @@
 383 stub GetWindowContextHelpID
 384 stub SetMenuContextHelpID
 385 stub GetMenuContextHelpID
-389 stub LoadImage
+389 pascal LoadImage(word segstr word word word word) LoadImage16
 390 stub CopyImage
 391 stub SignalProc32
 394 pascal16 DrawIconEx(word word word word word word word word word) DrawIconEx16
@@ -373,7 +373,7 @@
 417 pascal   GetMenuCheckMarkDimensions() GetMenuCheckMarkDimensions
 418 pascal16 SetMenuItemBitmaps(word word word word word) SetMenuItemBitmaps16
 420 pascal16 wsprintf() WIN16_wsprintf16
-421 pascal16 wvsprintf(ptr ptr ptr) wvsprintf16
+421 pascal16 wvsprintf(ptr str ptr) wvsprintf16
 422 pascal16 DlgDirSelectEx(word ptr word word) DlgDirSelectEx16
 423 pascal16 DlgDirSelectComboBoxEx(word ptr word word) DlgDirSelectComboBoxEx16
 427 pascal16 FindWindowEx(word word segstr str) FindWindowEx16
diff --git a/if1632/win32s16.spec b/if1632/win32s16.spec
index 2457c88..a82aff2 100644
--- a/if1632/win32s16.spec
+++ b/if1632/win32s16.spec
@@ -2,7 +2,7 @@
 type	win16
 
 1 stub WEP
-2 stub BOOTTASK
+2 pascal16 BootTask() BootTask
 3 stub CREATEPROCESS
 4 stub WAITFORDEBUGEVENT
 5 pascal CONTINUEDEBUGEVENT(long long long) ContinueDebugEvent
@@ -48,8 +48,8 @@
 45 stub FAPILOG16
 46 stub ALLOCCALLBACK
 47 stub LINEARTOHUGESELECTOROFFSET
-48 stub UTSELECTOROFFSETTOLINEAR
-49 stub UTLINEARTOSELECTOROFFSET
+48 pascal UTSelectorOffsetToLinear(ptr) UTSelectorOffsetToLinear
+49 pascal UTLinearToSelectorOffset(ptr) UTLinearToSelectorOffset
 50 stub SELFOREIGNTIB
 51 stub MYGLOBALREALLOC
 52 stub CREATEPEHEADER
diff --git a/if1632/windebug.spec b/if1632/windebug.spec
new file mode 100644
index 0000000..7b4fb6b
--- /dev/null
+++ b/if1632/windebug.spec
@@ -0,0 +1,6 @@
+name	windebug
+type	win16
+
+  1 stub     WINDEBUG
+  2 stub     WEP
+  3 pascal   WinNotify() WinNotify
diff --git a/if1632/winsock.spec b/if1632/winsock.spec
index 2548e10..e8564bb 100644
--- a/if1632/winsock.spec
+++ b/if1632/winsock.spec
@@ -16,7 +16,7 @@
 8   pascal   htonl(long) WINSOCK_htonl
 9   pascal16 htons(word) WINSOCK_htons
 10  pascal   inet_addr(ptr) WINSOCK_inet_addr
-11  pascal   inet_ntoa(long) WINSOCK_inet_ntoa
+11  pascal   inet_ntoa(long) WINSOCK_inet_ntoa16
 12  pascal16 ioctlsocket(word long ptr) WINSOCK_ioctlsocket16
 13  pascal16 listen(word word) WINSOCK_listen16
 14  pascal   ntohl(long) WINSOCK_ntohl
@@ -36,20 +36,20 @@
 55  pascal   getservbyname(ptr ptr) WINSOCK_getservbyname16
 56  pascal   getservbyport(word ptr) WINSOCK_getservbyport16
 57  pascal   gethostname(ptr word) WINSOCK_gethostname16
-101 pascal16 WSAAsyncSelect(word word word long) WSAAsyncSelect
+101 pascal16 WSAAsyncSelect(word word word long) WSAAsyncSelect16
 102 pascal16 WSAAsyncGetHostByAddr(word word ptr word word segptr word)
-             WSAAsyncGetHostByAddr
+             WSAAsyncGetHostByAddr16
 103 pascal16 WSAAsyncGetHostByName(word word ptr segptr word)
-             WSAAsyncGetHostByName
+             WSAAsyncGetHostByName16
 104 pascal16 WSAAsyncGetProtoByNumber(word word word segptr word)
-             WSAAsyncGetProtoByNumber
+             WSAAsyncGetProtoByNumber16
 105 pascal16 WSAAsyncGetProtoByName(word word ptr segptr word)
-             WSAAsyncGetProtoByName
+             WSAAsyncGetProtoByName16
 106 pascal16 WSAAsyncGetServByPort(word word word ptr segptr word)
-             WSAAsyncGetServByPort
+             WSAAsyncGetServByPort16
 107 pascal16 WSAAsyncGetServByName(word word ptr ptr segptr word)
-             WSAAsyncGetServByName
-108 pascal16 WSACancelAsyncRequest(word) WSACancelAsyncRequest
+             WSAAsyncGetServByName16
+108 pascal16 WSACancelAsyncRequest(word) WSACancelAsyncRequest16
 109 pascal16 WSASetBlockingHook(segptr) WSASetBlockingHook16
 110 pascal16 WSAUnhookBlockingHook() WSAUnhookBlockingHook16
 111 pascal16 WSAGetLastError() WSAGetLastError
diff --git a/include/builtin32.h b/include/builtin32.h
new file mode 100644
index 0000000..56532a3
--- /dev/null
+++ b/include/builtin32.h
@@ -0,0 +1,31 @@
+/*
+ * Win32 built-in DLLs definitions
+ *
+ * Copyright 1997 Alexandre Julliard
+ */
+
+#ifndef __WINE_BUILTIN32_H
+#define __WINE_BUILTIN32_H
+
+typedef void (*ENTRYPOINT32)();
+
+typedef struct
+{
+    const char           *name;         /* DLL name */
+    int                   base;         /* Ordinal base */
+    int                   nb_funcs;     /* Number of functions */
+    int                   nb_names;     /* Number of function names */
+    int                   nb_reg_funcs; /* Number of register functions */
+    const ENTRYPOINT32   *functions;    /* Pointer to function table */
+    const char * const   *names;        /* Pointer to names table */
+    const unsigned short *ordinals;     /* Pointer to ordinals table */
+    const unsigned char  *args;         /* Pointer to argument lengths */
+    const unsigned int   *argtypes;     /* Pointer to argument types bitmask */
+} BUILTIN32_DESCRIPTOR;
+
+extern ENTRYPOINT32 BUILTIN32_GetEntryPoint( char *buffer, void *relay,
+                                             unsigned int *typemask );
+extern void BUILTIN32_Unimplemented( const BUILTIN32_DESCRIPTOR *descr,
+                                     int ordinal );
+
+#endif /* __WINE_BUILTIN32_H */
diff --git a/include/cache.h b/include/cache.h
new file mode 100644
index 0000000..aa10b03
--- /dev/null
+++ b/include/cache.h
@@ -0,0 +1,17 @@
+/*
+ * Wine internally cached objects to speedup some things and prevent 
+ * infinite duplication of trivial code and data. 
+ * 
+ * Copyright 1997 Bertho A. Stultiens
+ *
+ */
+
+#ifndef __WINE_CACHE_H
+#define __WINE_CACHE_H
+
+#include "wintypes.h"
+
+HBRUSH32  CACHE_GetPattern55AABrush(void);
+HBITMAP32 CACHE_GetPattern55AABitmap(void);
+
+#endif /* __WINE_CACHE_H */
diff --git a/include/callback.h b/include/callback.h
index 86b604f..c02abcc 100644
--- a/include/callback.h
+++ b/include/callback.h
@@ -19,7 +19,8 @@
 
 typedef struct
 {
-    VOID (CALLBACK *CallRegisterProc)( CONTEXT *, INT32 );
+    LONG (CALLBACK *CallRegisterShortProc)( CONTEXT *, INT32 );
+    LONG (CALLBACK *CallRegisterLongProc)( CONTEXT *, INT32 );
     VOID (CALLBACK *CallTaskRescheduleProc)(void);
     VOID (CALLBACK *CallFrom16WndProc)(void);
     LRESULT (CALLBACK *CallWndProc)( WNDPROC16, HWND16, UINT16,
@@ -36,6 +37,7 @@
     VOID (CALLBACK *CallBootAppProc)( FARPROC16, HANDLE16, HFILE16 );
     WORD (CALLBACK *CallLoadAppSegProc)( FARPROC16, HANDLE16, HFILE16, WORD );
     VOID (CALLBACK *CallSystemTimerProc)( FARPROC16 );
+    DWORD (CALLBACK *CallWOWCallbackProc)( FARPROC16, DWORD );
     LRESULT (CALLBACK *CallASPIPostProc)( FARPROC16, SEGPTR );
     /* Following are the graphics driver callbacks */
     WORD (CALLBACK *CallDrvControlProc)( FARPROC16, SEGPTR, WORD,
diff --git a/include/color.h b/include/color.h
index 735e629..d226a19 100644
--- a/include/color.h
+++ b/include/color.h
@@ -14,6 +14,7 @@
 #define PC_SYS_RESERVED 0x40		/* system palentry is not to be mapped to */
 #define PC_SYS_MAPPED   0x10		/* logical palentry is a direct alias for system palentry */
 
+extern BOOL32     COLOR_Init(void);
 extern void	  COLOR_Cleanup(void);
 extern COLORREF	  COLOR_ToLogical(int pixel);
 extern int 	  COLOR_ToPhysical( DC *dc, COLORREF color );
@@ -22,11 +23,13 @@
 extern Colormap	  COLOR_GetColormap();
 extern UINT16	  COLOR_GetSystemPaletteSize();
 extern UINT16	  COLOR_GetSystemPaletteFlags();
+extern const PALETTEENTRY* COLOR_GetSystemPaletteTemplate(void);
 extern BOOL32	  COLOR_GetMonoPlane( int* );
 
 extern COLORREF	  COLOR_LookupNearestColor( PALETTEENTRY*, int, COLORREF );
 extern int        COLOR_PaletteLookupPixel( PALETTEENTRY*, int, int* , COLORREF, BOOL32 );
 extern COLORREF   COLOR_GetSystemPaletteEntry(UINT32);
+extern int COLOR_LookupSystemPixel(COLORREF col);
 
 extern int 	COLOR_mapEGAPixel[16];
 extern int* 	COLOR_PaletteToPixel;
diff --git a/include/compobj.h b/include/compobj.h
index 9aca771..6f2289f 100644
--- a/include/compobj.h
+++ b/include/compobj.h
@@ -11,7 +11,7 @@
     BYTE  Data4[8];
 };
 
-typedef struct tagGUID	GUID;
+typedef struct tagGUID	GUID,*LPGUID;
 typedef struct tagGUID	CLSID,*LPCLSID,*REFCLSID;
 typedef struct tagGUID	IID,*REFIID,*LPIID;
 
diff --git a/include/config.h.in b/include/config.h.in
index 12cd82d..2d301c7 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -21,6 +21,9 @@
 /* Define if you have the memmove function.  */
 #undef HAVE_MEMMOVE
 
+/* Define if you have the strerror function.  */
+#undef HAVE_STRERROR
+
 /* Define if you have the tcgetattr function.  */
 #undef HAVE_TCGETATTR
 
diff --git a/include/cursoricon.h b/include/cursoricon.h
index 14c34b8..691487e 100644
--- a/include/cursoricon.h
+++ b/include/cursoricon.h
@@ -50,6 +50,9 @@
 
 #pragma pack(4)
 
+extern HCURSOR16 CURSORICON_IconToCursor( HICON16 hIcon,
+                                          BOOL32 bSemiTransparent );
+
 extern Cursor CURSORICON_XCursor;  /* Current X cursor */
 
 #endif /* __WINE_CURSORICON_H */
diff --git a/include/dce.h b/include/dce.h
index 11d235f..089ad22 100644
--- a/include/dce.h
+++ b/include/dce.h
@@ -22,6 +22,7 @@
 
 #define DCX_DCEEMPTY		0x00000800
 #define DCX_DCEBUSY		0x00001000
+#define DCX_DCEDIRTY		0x00002000
 #define DCX_WINDOWPAINT		0x00020000
 #define DCX_KEEPCLIPRGN		0x00040000
 #define DCX_NOCLIPCHILDREN      0x00080000
diff --git a/include/debug.h b/include/debug.h
index 365c0ea..a34519d 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -78,6 +78,7 @@
 #undef DEBUG_STRING
 #undef DEBUG_TASK
 #undef DEBUG_TEXT
+#undef DEBUG_THUNK
 #undef DEBUG_TIMER
 #undef DEBUG_TOOLHELP
 #undef DEBUG_TWEAK
@@ -164,6 +165,7 @@
 #define DEBUG_STRING
 #define DEBUG_TASK
 #define DEBUG_TEXT
+#define DEBUG_THUNK
 #define DEBUG_TIMER
 #define DEBUG_TOOLHELP
 #define DEBUG_TWEAK
@@ -540,6 +542,11 @@
 #else
     0,
 #endif
+#ifdef DEBUG_THUNK
+    1,
+#else
+    0,
+#endif
 #ifdef DEBUG_TIMER
     1,
 #else
@@ -1539,8 +1546,21 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_timer if(!debug_msg_enabled[72]) ; else fprintf
-#define debugging_timer debug_msg_enabled[72]
+#define dprintf_thunk if(!debug_msg_enabled[72]) ; else fprintf
+#define debugging_thunk debug_msg_enabled[72]
+#else
+#ifdef DEBUG_THUNK
+#define dprintf_thunk fprintf
+#define debugging_thunk 1
+#else
+#define dprintf_thunk while(0) fprintf
+#define debugging_thunk 0
+#endif
+#endif
+
+#ifdef DEBUG_RUNTIME
+#define dprintf_timer if(!debug_msg_enabled[73]) ; else fprintf
+#define debugging_timer debug_msg_enabled[73]
 #else
 #ifdef DEBUG_TIMER
 #define dprintf_timer fprintf
@@ -1552,8 +1572,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_toolhelp if(!debug_msg_enabled[73]) ; else fprintf
-#define debugging_toolhelp debug_msg_enabled[73]
+#define dprintf_toolhelp if(!debug_msg_enabled[74]) ; else fprintf
+#define debugging_toolhelp debug_msg_enabled[74]
 #else
 #ifdef DEBUG_TOOLHELP
 #define dprintf_toolhelp fprintf
@@ -1565,8 +1585,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_tweak if(!debug_msg_enabled[74]) ; else fprintf
-#define debugging_tweak debug_msg_enabled[74]
+#define dprintf_tweak if(!debug_msg_enabled[75]) ; else fprintf
+#define debugging_tweak debug_msg_enabled[75]
 #else
 #ifdef DEBUG_TWEAK
 #define dprintf_tweak fprintf
@@ -1578,8 +1598,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_updown if(!debug_msg_enabled[75]) ; else fprintf
-#define debugging_updown debug_msg_enabled[75]
+#define dprintf_updown if(!debug_msg_enabled[76]) ; else fprintf
+#define debugging_updown debug_msg_enabled[76]
 #else
 #ifdef DEBUG_UPDOWN
 #define dprintf_updown fprintf
@@ -1591,8 +1611,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_ver if(!debug_msg_enabled[76]) ; else fprintf
-#define debugging_ver debug_msg_enabled[76]
+#define dprintf_ver if(!debug_msg_enabled[77]) ; else fprintf
+#define debugging_ver debug_msg_enabled[77]
 #else
 #ifdef DEBUG_VER
 #define dprintf_ver fprintf
@@ -1604,8 +1624,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_virtual if(!debug_msg_enabled[77]) ; else fprintf
-#define debugging_virtual debug_msg_enabled[77]
+#define dprintf_virtual if(!debug_msg_enabled[78]) ; else fprintf
+#define debugging_virtual debug_msg_enabled[78]
 #else
 #ifdef DEBUG_VIRTUAL
 #define dprintf_virtual fprintf
@@ -1617,8 +1637,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_vxd if(!debug_msg_enabled[78]) ; else fprintf
-#define debugging_vxd debug_msg_enabled[78]
+#define dprintf_vxd if(!debug_msg_enabled[79]) ; else fprintf
+#define debugging_vxd debug_msg_enabled[79]
 #else
 #ifdef DEBUG_VXD
 #define dprintf_vxd fprintf
@@ -1630,8 +1650,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_win if(!debug_msg_enabled[79]) ; else fprintf
-#define debugging_win debug_msg_enabled[79]
+#define dprintf_win if(!debug_msg_enabled[80]) ; else fprintf
+#define debugging_win debug_msg_enabled[80]
 #else
 #ifdef DEBUG_WIN
 #define dprintf_win fprintf
@@ -1643,8 +1663,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_win16drv if(!debug_msg_enabled[80]) ; else fprintf
-#define debugging_win16drv debug_msg_enabled[80]
+#define dprintf_win16drv if(!debug_msg_enabled[81]) ; else fprintf
+#define debugging_win16drv debug_msg_enabled[81]
 #else
 #ifdef DEBUG_WIN16DRV
 #define dprintf_win16drv fprintf
@@ -1656,8 +1676,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_win32 if(!debug_msg_enabled[81]) ; else fprintf
-#define debugging_win32 debug_msg_enabled[81]
+#define dprintf_win32 if(!debug_msg_enabled[82]) ; else fprintf
+#define debugging_win32 debug_msg_enabled[82]
 #else
 #ifdef DEBUG_WIN32
 #define dprintf_win32 fprintf
@@ -1669,8 +1689,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_winsock if(!debug_msg_enabled[82]) ; else fprintf
-#define debugging_winsock debug_msg_enabled[82]
+#define dprintf_winsock if(!debug_msg_enabled[83]) ; else fprintf
+#define debugging_winsock debug_msg_enabled[83]
 #else
 #ifdef DEBUG_WINSOCK
 #define dprintf_winsock fprintf
@@ -1757,6 +1777,7 @@
     "string",
     "task",
     "text",
+    "thunk",
     "timer",
     "toolhelp",
     "tweak",
diff --git a/include/gdi.h b/include/gdi.h
index d744a41..ed90b94 100644
--- a/include/gdi.h
+++ b/include/gdi.h
@@ -11,6 +11,7 @@
 #include "ldt.h"
 #include "local.h"
 #include "x11drv.h"
+#include "path.h"
 
   /* GDI objects magic numbers */
 #define PEN_MAGIC             0x4f47
@@ -100,6 +101,8 @@
     HBITMAP16     hFirstBitmap; /* Bitmap selected at creation of the DC */
     HANDLE16      hDevice;
     HPALETTE16    hPalette;
+    
+    GdiPath       path;
 
     WORD          ROPmode;
     WORD          polyFillMode;
@@ -246,7 +249,7 @@
 
   /* Stock objects handles */
 
-#define NB_STOCK_OBJECTS          (SYSTEM_FIXED_FONT + 1)
+#define NB_STOCK_OBJECTS          (DEFAULT_GUI_FONT + 1)
 
 #define STOCK_WHITE_BRUSH       ((HBRUSH16)(FIRST_STOCK_HANDLE+WHITE_BRUSH))
 #define STOCK_LTGRAY_BRUSH      ((HBRUSH16)(FIRST_STOCK_HANDLE+LTGRAY_BRUSH))
@@ -265,11 +268,12 @@
 #define STOCK_DEVICE_DEFAULT_FONT ((HFONT16)(FIRST_STOCK_HANDLE+DEVICE_DEFAULT_FONT))
 #define STOCK_DEFAULT_PALETTE   ((HPALETTE16)(FIRST_STOCK_HANDLE+DEFAULT_PALETTE))
 #define STOCK_SYSTEM_FIXED_FONT ((HFONT16)(FIRST_STOCK_HANDLE+SYSTEM_FIXED_FONT))
+#define STOCK_DEFAULT_GUI_FONT  ((HFONT16)(FIRST_STOCK_HANDLE+DEFAULT_GUI_FONT))
 
 #define FIRST_STOCK_FONT        STOCK_OEM_FIXED_FONT
-#define LAST_STOCK_FONT         STOCK_SYSTEM_FIXED_FONT
+#define LAST_STOCK_FONT         STOCK_DEFAULT_GUI_FONT
 
-#define LAST_STOCK_HANDLE       ((DWORD)STOCK_SYSTEM_FIXED_FONT)
+#define LAST_STOCK_HANDLE       ((DWORD)STOCK_DEFAULT_GUI_FONT)
 
   /* Device <-> logical coords conversion */
 
diff --git a/include/interfaces.h b/include/interfaces.h
index 5e912da..ef70a22 100644
--- a/include/interfaces.h
+++ b/include/interfaces.h
@@ -5,6 +5,13 @@
 #include "ole2.h"
 #include "compobj.h"
 
+#define STDMETHOD(xfn) HRESULT (CALLBACK *fn##xfn)
+#define STDMETHOD_(ret,xfn) ret (CALLBACK *fn##xfn)
+#define PURE
+#define FAR
+#define	THIS_ THIS,
+
+
 DEFINE_OLEGUID(IID_IUnknown,0,0,0);
 DEFINE_OLEGUID(IID_IClassFactory,1,0,0);
 DEFINE_OLEGUID(IID_IMalloc,2,0,0);
@@ -18,28 +25,65 @@
 DEFINE_OLEGUID(IID_IMessageFilter,0x16,0,0);
 DEFINE_OLEGUID(IID_IStdMarshalInfo,0x18,0,0);
 
-typedef struct tagUNKNOWN *LPUNKNOWN,IUnknown;
+#define THIS LPUNKNOWN this
+typedef struct IUnknown *LPUNKNOWN,IUnknown;
 typedef struct {
-	HRESULT	(CALLBACK *fnQueryInterface)(LPUNKNOWN this,REFIID refiid,LPVOID *obj);
-	HRESULT	(CALLBACK *fnAddRef)(LPUNKNOWN this);
-	HRESULT	(CALLBACK *fnRelease)(LPUNKNOWN this);
-} *LPUNKNOWN_VTABLE;
+	STDMETHOD(QueryInterface) (THIS_ REFIID riid,LPVOID FAR* ppvObj) PURE;
+	STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+	STDMETHOD_(ULONG,Release) (THIS) PURE;
+} *LPUNKNOWN_VTABLE,IUnknown_VTable;
 
-struct tagUNKNOWN {
+struct IUnknown {
 	LPUNKNOWN_VTABLE	lpvtbl;
-	/* internal stuff. Not needed until we actually implement IUnknown */
+	DWORD			ref;
 };
+#undef THIS
 
-typedef struct tagCLASSFACTORY *LPCLASSFACTORY,IClassFactory;
+#define THIS LPCLASSFACTORY this
+typedef struct IClassFactory *LPCLASSFACTORY,IClassFactory;
 typedef struct {
-	HRESULT	(CALLBACK *fnQueryInterface)(LPCLASSFACTORY this,REFIID refiid,LPVOID *obj);
-	HRESULT	(CALLBACK *fnAddRef)(LPCLASSFACTORY this);
-	HRESULT	(CALLBACK *fnRelease)(LPCLASSFACTORY this);
-	HRESULT (CALLBACK *fnCreateInstance)(LPCLASSFACTORY this,LPUNKNOWN pUnkOuter,REFIID riid,LPVOID * ppvObject);
-} *LPCLASSFACTORY_VTABLE;
+	STDMETHOD(QueryInterface) (THIS_ REFIID riid,LPVOID FAR* ppvObj) PURE;
+	STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+	STDMETHOD_(ULONG,Release) (THIS) PURE;
+	STDMETHOD(CreateInstance) (THIS_ LPUNKNOWN pUnkOuter, REFIID riid, LPVOID FAR* ppvObject) PURE;
+} *LPCLASSFACTORY_VTABLE,IClassFactory_VTable;
 
-struct tagCLASSFACTORY {
-	LPCLASSFACTORY_VTABLE lpvtbl;
-	/*internal stuff. Not needed until we actually implement IClassFactory*/
+struct IClassFactory {
+	LPCLASSFACTORY_VTABLE	lpvtbl;
+	DWORD			ref;
 };
+#undef THIS
+
+#define THIS LPMALLOC this
+typedef struct IMalloc *LPMALLOC,IMalloc;
+typedef struct {
+	STDMETHOD(QueryInterface) (THIS_ REFIID riid,LPVOID FAR* ppvObj) PURE;
+	STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+	STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+	STDMETHOD_(LPVOID,Alloc) ( THIS_ DWORD cb);
+	STDMETHOD_(LPVOID,Realloc) ( THIS_ LPVOID pv,DWORD cb);
+	STDMETHOD_(VOID,Free) ( THIS_ LPVOID pv);
+	STDMETHOD_(DWORD,GetSize) ( THIS_ LPVOID pv);
+	STDMETHOD_(LPINT32,DidAlloc) ( THIS_ LPVOID pv);
+	STDMETHOD_(LPVOID,HeapMinimize) ( THIS );
+} *LPMALLOC_VTABLE,IMalloc_VTable;
+
+struct IMalloc {
+	LPMALLOC_VTABLE lpvtbl;
+	DWORD		ref;
+};
+#undef THIS
+
+/* private prototypes for the constructors */
+#ifdef __WINE__
+LPUNKNOWN	IUnknown_Constructor();
+LPMALLOC	IMalloc_Constructor();
+#endif
+
+#undef STDMETHOD
+#undef STDMETHOD_
+#undef PURE
+#undef FAR
+#undef THIS_
 #endif /*_WINE_INTERFACES_H*/
diff --git a/include/mmsystem.h b/include/mmsystem.h
index fa5a50b..6845f35 100644
--- a/include/mmsystem.h
+++ b/include/mmsystem.h
@@ -18,6 +18,7 @@
 
 #define MAXPNAMELEN      32     /* max product name length (including NULL) */
 #define MAXERRORLENGTH   128    /* max error text length (including NULL) */
+#define MAX_JOYSTICKOEMVXDNAME	260
 
 typedef WORD    VERSION;        /* major (high byte), minor (low byte) */
 
@@ -27,6 +28,9 @@
 typedef UINT16	MCIDEVICEID16;
 typedef UINT32	MCIDEVICEID32;
 DECL_WINELIB_TYPE(MCIDEVICEID);
+typedef	UINT16	MMRESULT16;
+typedef	UINT32	MMRESULT32;
+DECL_WINELIB_TYPE(MMRESULT);
 
 typedef struct {
     UINT16    wType;		/* indicates the contents of the union */
@@ -733,24 +737,45 @@
 #define TIMERR_NOCANDO        (TIMERR_BASE+1)      /* request not completed */
 #define TIMERR_STRUCT         (TIMERR_BASE+33)     /* time struct size */
 
-typedef void (CALLBACK *LPTIMECALLBACK) (UINT16 uTimerID, UINT16 uMessage, DWORD dwUser, DWORD dw1, DWORD dw2);
+typedef void (CALLBACK *LPTIMECALLBACK16)(UINT16 uTimerID, UINT16 uMessage, DWORD dwUser, DWORD dw1, DWORD dw2);
+typedef void (CALLBACK *LPTIMECALLBACK32)(UINT32 uTimerID, UINT32 uMessage, DWORD dwUser, DWORD dw1, DWORD dw2);
+DECL_WINELIB_TYPE(LPTIMECALLBACK);
 
 #define TIME_ONESHOT    0   /* program timer for single event */
 #define TIME_PERIODIC   1   /* program for continuous periodic event */
 
 typedef struct {
-    UINT16    wPeriodMin;     /* minimum period supported  */
-    UINT16    wPeriodMax;     /* maximum period supported  */
-} TIMECAPS, *LPTIMECAPS;
+    UINT16	wPeriodMin;	/* minimum period supported  */
+    UINT16	wPeriodMax;	/* maximum period supported  */
+} TIMECAPS16,*LPTIMECAPS16;
 
-UINT16 WINAPI timeGetSystemTime(LPMMTIME16 lpTime, UINT16 uSize);
-DWORD WINAPI timeGetTime(void);
-UINT16 WINAPI timeSetEvent(UINT16 uDelay, UINT16 uResolution,
-    LPTIMECALLBACK lpFunction, DWORD dwUser, UINT16 uFlags);
-UINT16 WINAPI timeKillEvent(UINT16 uTimerID);
-UINT16 WINAPI timeGetDevCaps(TIMECAPS * lpTimeCaps, UINT16 uSize);
-UINT16 WINAPI timeBeginPeriod(UINT16 uPeriod);
-UINT16 WINAPI timeEndPeriod(UINT16 uPeriod);
+typedef struct {
+    UINT32	wPeriodMin;
+    UINT32	wPeriodMax;
+} TIMECAPS32, *LPTIMECAPS32;
+
+DECL_WINELIB_TYPE(TIMECAPS);
+DECL_WINELIB_TYPE(LPTIMECAPS);
+
+MMRESULT16 WINAPI timeGetSystemTime16(LPMMTIME16,UINT16);
+MMRESULT32 WINAPI timeGetSystemTime32(LPMMTIME32,UINT32);
+#define timeGetSystemTime WINELIB_NAME(timeGetSystemTime)
+DWORD WINAPI timeGetTime();	/* same for win32/win16 */
+MMRESULT16 WINAPI timeSetEvent16(UINT16,UINT16,LPTIMECALLBACK16,DWORD,UINT16);
+MMRESULT32 WINAPI timeSetEvent32(UINT32,UINT32,LPTIMECALLBACK32,DWORD,UINT32);
+#define timeSetEvent WINELIB_NAME(timeSetEvent)
+MMRESULT16 WINAPI timeKillEvent16(UINT16);
+MMRESULT32 WINAPI timeKillEvent32(UINT32);
+#define timeKillEvent WINELIB_NAME(timeKillEvent)
+MMRESULT16 WINAPI timeGetDevCaps16(LPTIMECAPS16,UINT16);
+MMRESULT32 WINAPI timeGetDevCaps32(LPTIMECAPS32,UINT32);
+#define timeGetDevCaps WINELIB_NAME(timeGetDevCaps)
+MMRESULT16 WINAPI timeBeginPeriod16(UINT16);
+MMRESULT32 WINAPI timeBeginPeriod32(UINT32);
+#define timeBeginPeriod WINELIB_NAME(timeBeginPeriod)
+MMRESULT16 WINAPI timeEndPeriod16(UINT16);
+MMRESULT32 WINAPI timeEndPeriod32(UINT32);
+#define timeEndPeriod WINELIB_NAME(timeEndPeriod)
 
 #define JOYERR_NOERROR        (0)                  /* no error */
 #define JOYERR_PARMS          (JOYERR_BASE+5)      /* bad parameters */
@@ -770,8 +795,8 @@
 #define JOYSTICKID2         1
 
 typedef struct {
-    UINT16 wMid;                  /* manufacturer ID */
-    UINT16 wPid;                  /* product ID */
+    WORD wMid;                  /* manufacturer ID */
+    WORD wPid;                  /* product ID */
     char szPname[MAXPNAMELEN];  /* product name (NULL terminated string) */
     UINT16 wXmin;                 /* minimum x position value */
     UINT16 wXmax;                 /* maximum x position value */
@@ -782,23 +807,116 @@
     UINT16 wNumButtons;           /* number of buttons */
     UINT16 wPeriodMin;            /* minimum message period when captured */
     UINT16 wPeriodMax;            /* maximum message period when captured */
-} JOYCAPS, *LPJOYCAPS;
+    /* win95,nt4 additions: */
+    UINT16 wRmin;		/* minimum r position value */
+    UINT16 wRmax;		/* maximum r position value */
+    UINT16 wUmin;		/* minimum u (5th axis) position value */
+    UINT16 wUmax;		/* maximum u (5th axis) position value */
+    UINT16 wVmin;		/* minimum v (6th axis) position value */
+    UINT16 wVmax;		/* maximum v (6th axis) position value */
+    UINT16 wCaps;		/* joystick capabilites */
+    UINT16 wMaxAxes;		/* maximum number of axes supported */
+    UINT16 wNumAxes;		/* number of axes in use */
+    UINT16 wMaxButtons;		/* maximum number of buttons supported */
+    CHAR szRegKey[MAXPNAMELEN]; /* registry key */
+    CHAR szOEMVxD[MAX_JOYSTICKOEMVXDNAME]; /* OEM VxD in use */
+} JOYCAPS16, *LPJOYCAPS16;
+
+typedef struct {
+    WORD wMid;
+    WORD wPid;
+    CHAR szPname[MAXPNAMELEN];
+    UINT32 wXmin;
+    UINT32 wXmax;
+    UINT32 wYmin;
+    UINT32 wYmax;
+    UINT32 wZmin;
+    UINT32 wZmax;
+    UINT32 wNumButtons;
+    UINT32 wPeriodMin;
+    UINT32 wPeriodMax;
+    UINT32 wRmin;
+    UINT32 wRmax;
+    UINT32 wUmin;
+    UINT32 wUmax;
+    UINT32 wVmin;
+    UINT32 wVmax;
+    UINT32 wCaps;
+    UINT32 wMaxAxes;
+    UINT32 wNumAxes;
+    UINT32 wMaxButtons;
+    CHAR szRegKey[MAXPNAMELEN];
+    CHAR szOEMVxD[MAX_JOYSTICKOEMVXDNAME];
+} JOYCAPS32A, *LPJOYCAPS32A;
+
+typedef struct {
+    WORD wMid;
+    WORD wPid;
+    WCHAR szPname[MAXPNAMELEN];
+    UINT32 wXmin;
+    UINT32 wXmax;
+    UINT32 wYmin;
+    UINT32 wYmax;
+    UINT32 wZmin;
+    UINT32 wZmax;
+    UINT32 wNumButtons;
+    UINT32 wPeriodMin;
+    UINT32 wPeriodMax;
+    UINT32 wRmin;
+    UINT32 wRmax;
+    UINT32 wUmin;
+    UINT32 wUmax;
+    UINT32 wVmin;
+    UINT32 wVmax;
+    UINT32 wCaps;
+    UINT32 wMaxAxes;
+    UINT32 wNumAxes;
+    UINT32 wMaxButtons;
+    WCHAR szRegKey[MAXPNAMELEN];
+    WCHAR szOEMVxD[MAX_JOYSTICKOEMVXDNAME];
+} JOYCAPS32W, *LPJOYCAPS32W;
+DECL_WINELIB_TYPE_AW(JOYCAPS)
+DECL_WINELIB_TYPE_AW(LPJOYCAPS)
 
 typedef struct {
     UINT16 wXpos;                 /* x position */
     UINT16 wYpos;                 /* y position */
     UINT16 wZpos;                 /* z position */
     UINT16 wButtons;              /* button states */
-} JOYINFO, *LPJOYINFO;
+} JOYINFO16, *LPJOYINFO16;
 
-UINT16 WINAPI joyGetDevCaps(UINT16 uJoyID, JOYCAPS * lpCaps, UINT16 uSize);
-UINT16 WINAPI joyGetNumDevs(void);
-UINT16 WINAPI joyGetPos(UINT16 uJoyID, JOYINFO * lpInfo);
-UINT16 WINAPI joyGetThreshold(UINT16 uJoyID, UINT16 * lpuThreshold);
-UINT16 WINAPI joyReleaseCapture(UINT16 uJoyID);
-UINT16 WINAPI joySetCapture(HWND16 hwnd, UINT16 uJoyID, UINT16 uPeriod,
-    BOOL16 bChanged);
-UINT16 WINAPI joySetThreshold(UINT16 uJoyID, UINT16 uThreshold);
+typedef struct {
+    UINT32 wXpos;
+    UINT32 wYpos;
+    UINT32 wZpos;
+    UINT32 wButtons;
+} JOYINFO32, *LPJOYINFO32;
+
+DECL_WINELIB_TYPE(JOYINFO)
+DECL_WINELIB_TYPE(LPJOYINFO)
+
+MMRESULT16 WINAPI joyGetDevCaps16 (UINT16,LPJOYCAPS16 ,UINT16);
+MMRESULT32 WINAPI joyGetDevCaps32A(UINT32,LPJOYCAPS32A,UINT32);
+MMRESULT32 WINAPI joyGetDevCaps32W(UINT32,LPJOYCAPS32W,UINT32);
+#define joyGetDevCaps WINELIB_NAME_AW(joyGetDevCaps)
+UINT16 WINAPI joyGetNumDevs16(void);
+UINT32 WINAPI joyGetNumDevs32(void);
+#define joyGetNumDevs WINELIB_NAME(joyGetNumDevs)
+MMRESULT16 WINAPI joyGetPos16(UINT16,LPJOYINFO16);
+MMRESULT32 WINAPI joyGetPos32(UINT32,LPJOYINFO32);
+#define joyGetPos WINELIB_NAME(joyGetPos)
+MMRESULT16 WINAPI joyGetThreshold16(UINT16,UINT16*);
+MMRESULT32 WINAPI joyGetThreshold32(UINT32,UINT32*);
+#define joyGetThreshold WINELIB_NAME(joyGetThreshold)
+MMRESULT16 WINAPI joyReleaseCapture16(UINT16);
+MMRESULT32 WINAPI joyReleaseCapture32(UINT32);
+#define joyReleaseCapture WINELIB_NAME(joyReleaseCapture)
+MMRESULT16 WINAPI joySetCapture16(HWND16,UINT16,UINT16,BOOL16);
+MMRESULT32 WINAPI joySetCapture32(HWND32,UINT32,UINT32,BOOL32);
+#define joySetCapture WINELIB_NAME(joySetCapture)
+MMRESULT16 WINAPI joySetThreshold16(UINT16,UINT16);
+MMRESULT32 WINAPI joySetThreshold32(UINT32,UINT32);
+#define joySetThreshold WINELIB_NAME(joySetThreshold)
 
 typedef struct {
 	WORD		wMid;		/* manufacturer id */
@@ -2560,11 +2678,11 @@
 } MIDIOPENDESC, *LPMIDIOPENDESC;
 
 typedef struct {
-	UINT16		wDelay;
-	UINT16		wResolution;
-	LPTIMECALLBACK	lpFunction;
-	DWORD		dwUser;
-	UINT16		wFlags;
+	UINT16			wDelay;
+	UINT16			wResolution;
+	LPTIMECALLBACK16	lpFunction;
+	DWORD			dwUser;
+	UINT16			wFlags;
 } TIMEREVENT, *LPTIMEREVENT;
 
 typedef struct tMIXEROPENDESC
@@ -2603,6 +2721,16 @@
                              WORD wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2);
 DWORD WINAPI auxMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
 					DWORD dwParam1, DWORD dwParam2);
+
+struct LINUX_MCIDRIVER {
+	HDRVR16			hdrv;
+	DRIVERPROC16		driverproc;
+	MCI_OPEN_DRIVER_PARMS	modp;
+	MCI_OPEN_PARMS16	mop;
+	DWORD			private;
+};
+
+#pragma pack(4)
 DWORD WINAPI mixMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
 					DWORD dwParam1, DWORD dwParam2);
 DWORD WINAPI midMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
diff --git a/include/ntdll.h b/include/ntdll.h
index 2f1bf8b..28f3583 100644
--- a/include/ntdll.h
+++ b/include/ntdll.h
@@ -156,6 +156,27 @@
 	LPWSTR	Buffer;
 } UNICODE_STRING,*LPUNICODE_STRING;
 
+
+BOOL32 WINAPI IsValidSid(LPSID);
+BOOL32 WINAPI EqualSid(LPSID,LPSID);
+BOOL32 WINAPI EqualPrefixSid(LPSID,LPSID);
+DWORD  WINAPI GetSidLengthRequired(BYTE);
+BOOL32 WINAPI AllocateAndInitializeSid(LPSID_IDENTIFIER_AUTHORITY,BYTE,DWORD,
+                                       DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,
+                                       DWORD,LPSID*);
+VOID*  WINAPI FreeSid(LPSID);
+BOOL32 WINAPI InitializeSecurityDescriptor(SECURITY_DESCRIPTOR*,DWORD);
+BOOL32 WINAPI InitializeSid(LPSID,LPSID_IDENTIFIER_AUTHORITY,BYTE);
+DWORD* WINAPI GetSidSubAuthority(LPSID,DWORD);
+BYTE * WINAPI GetSidSubAuthorityCount(LPSID);
+DWORD  WINAPI GetLengthSid(LPSID);
+BOOL32 WINAPI CopySid(DWORD,LPSID,LPSID);
+BOOL32 WINAPI LookupAccountSid32A(LPCSTR,PSID,LPCSTR,LPDWORD,LPCSTR,LPDWORD,
+                                  PSID_NAME_USE);
+BOOL32 WINAPI LookupAccountSid32W(LPCWSTR,PSID,LPCWSTR,LPDWORD,LPCWSTR,LPDWORD,
+                                  PSID_NAME_USE);
+LPSID_IDENTIFIER_AUTHORITY WINAPI GetSidIdentifierAuthority(LPSID);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/path.h b/include/path.h
new file mode 100644
index 0000000..fbf00e1
--- /dev/null
+++ b/include/path.h
@@ -0,0 +1,45 @@
+/*
+ * Graphics paths (BeginPath, EndPath etc.)
+ *
+ * Copyright 1997 Martin Boehme
+ */
+
+#ifndef __WINE_PATH_H
+#define __WINE_PATH_H
+
+/* It should not be necessary to access the contents of the GdiPath
+ * structure directly; if you find that the exported functions don't
+ * allow you to do what you want, then please place a new exported
+ * function that does this job in path.c.
+ */
+
+typedef enum tagGdiPathState
+{
+   PATH_Null,
+   PATH_Open,
+   PATH_Closed
+} GdiPathState;
+
+typedef struct tagGdiPath
+{
+   GdiPathState state;
+   POINT32      *pPoints;
+   BYTE         *pFlags;
+   int          numEntriesUsed, numEntriesAllocated;
+   BOOL32       newStroke;
+} GdiPath;
+
+#define PATH_IsPathOpen(path) ((path).state==PATH_Open)
+/* Returns TRUE if the specified path is in the open state, i.e. in the
+ * state where points will be added to the path, or FALSE otherwise. This
+ * function is implemented as a macro for performance reasons.
+ */
+
+extern void   PATH_InitGdiPath(GdiPath *pPath);
+extern void   PATH_DestroyGdiPath(GdiPath *pPath);
+extern BOOL32 PATH_AssignGdiPath(GdiPath *pPathDest,
+   const GdiPath *pPathSrc);
+extern BOOL32 PATH_MoveTo(HDC32 hdc);
+extern BOOL32 PATH_LineTo(HDC32 hdc, INT32 x, INT32 y);
+
+#endif /* __WINE_PATH_H */
diff --git a/include/pe_image.h b/include/pe_image.h
index b432c83..b6876e9 100644
--- a/include/pe_image.h
+++ b/include/pe_image.h
@@ -41,6 +41,6 @@
 struct _PDB32; /* forward definition */
 extern void PE_InitializeDLLs(struct _PDB32*,DWORD,LPVOID);
 
-extern LPIMAGE_RESOURCE_DIRECTORY GetResDirEntryW(LPIMAGE_RESOURCE_DIRECTORY,LPCWSTR,DWORD);
+extern LPIMAGE_RESOURCE_DIRECTORY GetResDirEntryW(LPIMAGE_RESOURCE_DIRECTORY,LPCWSTR,DWORD,BOOL32);
 
 #endif /* __WINE_PE_IMAGE_H */
diff --git a/include/shell.h b/include/shell.h
index 2ddf3a3..ee0ba36 100644
--- a/include/shell.h
+++ b/include/shell.h
@@ -32,6 +32,16 @@
 	/* memory block with filenames follows */     
 } DROPFILESTRUCT, *LPDROPFILESTRUCT; 
 
+typedef struct _NOTIFYICONDATA {
+	DWORD cbSize;
+	HWND32 hWnd;
+	UINT32 uID;
+	UINT32 uFlags;
+	UINT32 uCallbackMessage;
+	HICON32 hIcon;
+	CHAR szTip[64];
+} NOTIFYICONDATA, *PNOTIFYICONDATA;
+
 typedef struct tagSHFILEINFO32A {
 	HICON32	hIcon;			/* icon */
 	int	iIcon;			/* icon index */
@@ -59,8 +69,6 @@
 	LPARAM	lParam;
 } APPBARDATA, *PAPPBARDATA;
 
-DECL_WINELIB_TYPE(APPBARDATA);
-
 #define SHGFI_ICON              0x000000100     /* get icon */
 #define SHGFI_DISPLAYNAME       0x000000200     /* get display name */
 #define SHGFI_TYPENAME          0x000000400     /* get type name */
@@ -87,4 +95,22 @@
 #define SE_ERR_DDEBUSY          30
 #define SE_ERR_NOASSOC          31
 
+#define	CSIDL_DESKTOP		0x0000
+#define	CSIDL_PROGRAMS		0x0002
+#define	CSIDL_CONTROLS		0x0003
+#define	CSIDL_PRINTERS		0x0004
+#define	CSIDL_PERSONAL		0x0005
+#define	CSIDL_FAVORITES		0x0006
+#define	CSIDL_STARTUP		0x0007
+#define	CSIDL_RECENT		0x0008
+#define	CSIDL_SENDTO		0x0009
+#define	CSIDL_BITBUCKET		0x000a
+#define	CSIDL_STARTMENU		0x000b
+#define	CSIDL_DESKTOPDIRECTORY	0x0010
+#define	CSIDL_DRIVES		0x0011
+#define	CSIDL_NETWORK		0x0012
+#define	CSIDL_NETHOOD		0x0013
+#define	CSIDL_FONTS		0x0014
+#define	CSIDL_TEMPLATES		0x0015
+
 #endif  /* __WINE_SHELL_H */
diff --git a/include/shlobj.h b/include/shlobj.h
index bb06efe..d51a190 100644
--- a/include/shlobj.h
+++ b/include/shlobj.h
@@ -1,12 +1,19 @@
 #ifndef _WINE_SHLOBJ_H
 #define _WINE_SHLOBJ_H
 
+#include "shell.h"
 #include "ole.h"
 #include "ole2.h"
 #include "compobj.h"
 
+#define STDMETHOD(xfn) HRESULT (CALLBACK *fn##xfn)
+#define STDMETHOD_(type,xfn) type (CALLBACK *fn##xfn)
+#define PURE
+#define FAR
+#define THIS_ THIS,
+
+
 typedef LPVOID	LPBC; /* *IBindCtx really */
-typedef LPVOID	LPSTRRET,LPENUMIDLIST;
 
 /*
  * shell32 classids
@@ -28,6 +35,21 @@
 DEFINE_SHLGUID(IID_IEnumIDList,         0x000214F2L, 0, 0);
 DEFINE_SHLGUID(IID_IFileViewerSite,     0x000214F3L, 0, 0);
 
+#define	STRRET_WSTR	0x0000
+#define	STRRET_OFFSET	0x0001
+#define	STRRET_CSTR	0x0002
+
+typedef struct _STRRET
+{
+    UINT32 uType;		/* STRRET_xxx */
+    union
+    {
+        LPWSTR	pOleStr;	/* OLESTR that will be freed */
+        UINT32	uOffset;	/* Offset into SHITEMID (ANSI) */
+        char	cStr[MAX_PATH];	/* Buffer to fill in */
+    } DUMMYUNIONNAME;
+} STRRET,*LPSTRRET;
+
 typedef struct {
 	WORD		cb;	/* nr of bytes in this item */
 	BYTE		abID[1];/* first byte in this item */
@@ -37,29 +59,198 @@
 	SHITEMID	mkid; /* first itemid in list */
 } ITEMIDLIST,*LPITEMIDLIST,*LPCITEMIDLIST;
 
-/* The IShellFolder interface ... the basic interface for a lot of stuff */
+/*****************************************************************************
+ * IEnumIDList interface
+ */
+#define THIS LPENUMIDLIST this
+
+typedef struct IEnumIDList IEnumIDList,*LPENUMIDLIST;
+typedef struct IEnumIDList_VTable {
+    /* *** IUnknown methods *** */
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+    /* *** IEnumIDList methods *** */
+    STDMETHOD(Next)  (THIS_ ULONG celt,
+                      LPITEMIDLIST *rgelt,
+                      ULONG *pceltFetched) PURE;
+    STDMETHOD(Skip)  (THIS_ ULONG celt) PURE;
+    STDMETHOD(Reset) (THIS) PURE;
+    STDMETHOD(Clone) (THIS_ IEnumIDList **ppenum) PURE;
+} IEnumIDList_VTable,*LPENUMIDLIST_VTABLE;
+
+struct IEnumIDList {
+	LPENUMIDLIST_VTABLE	lpvtbl;
+	DWORD			ref;
+};
+#undef THIS
+/************************************************************************
+ * The IShellFolder interface ... the basic interface for a lot of stuff
+ */
+
+#define THIS LPSHELLFOLDER this
+
+/* IShellFolder::GetDisplayNameOf/SetNameOf uFlags */
+typedef enum
+{
+    SHGDN_NORMAL            = 0,        /* default (display purpose) */
+    SHGDN_INFOLDER          = 1,        /* displayed under a folder (relative)*/
+    SHGDN_FORPARSING        = 0x8000,   /* for ParseDisplayName or path */
+} SHGNO;
+
+/* IShellFolder::EnumObjects */
+typedef enum tagSHCONTF
+{
+    SHCONTF_FOLDERS         = 32,       /* for shell browser */
+    SHCONTF_NONFOLDERS      = 64,       /* for default view */
+    SHCONTF_INCLUDEHIDDEN   = 128,      /* for hidden/system objects */
+} SHCONTF;
+
+/* from oleidl.h */
+#define	DROPEFFECT_NONE		0
+#define	DROPEFFECT_COPY		1
+#define	DROPEFFECT_MOVE		2
+#define	DROPEFFECT_LINK		4
+#define	DROPEFFECT_SCROLL       0x80000000
+
+/* IShellFolder::GetAttributesOf flags */
+#define SFGAO_CANCOPY           DROPEFFECT_COPY /* Objects can be copied */
+#define SFGAO_CANMOVE           DROPEFFECT_MOVE /* Objects can be moved */
+#define SFGAO_CANLINK           DROPEFFECT_LINK /* Objects can be linked */
+#define SFGAO_CANRENAME         0x00000010L     /* Objects can be renamed */
+#define SFGAO_CANDELETE         0x00000020L     /* Objects can be deleted */
+#define SFGAO_HASPROPSHEET      0x00000040L     /* Objects have property sheets */
+#define SFGAO_DROPTARGET        0x00000100L     /* Objects are drop target */
+#define SFGAO_CAPABILITYMASK    0x00000177L
+#define SFGAO_LINK              0x00010000L     /* Shortcut (link) */
+#define SFGAO_SHARE             0x00020000L     /* shared */
+#define SFGAO_READONLY          0x00040000L     /* read-only */
+#define SFGAO_GHOSTED           0x00080000L     /* ghosted icon */
+#define SFGAO_DISPLAYATTRMASK   0x000F0000L
+#define SFGAO_FILESYSANCESTOR   0x10000000L     /* It contains file system folder */
+#define SFGAO_FOLDER            0x20000000L     /* It's a folder. */
+#define SFGAO_FILESYSTEM        0x40000000L     /* is a file system thing (file/folder/root) */
+#define SFGAO_HASSUBFOLDER      0x80000000L     /* Expandable in the map pane */
+#define SFGAO_CONTENTSMASK      0x80000000L
+#define SFGAO_VALIDATE          0x01000000L     /* invalidate cached information */
+#define SFGAO_REMOVABLE        0x02000000L      /* is this removeable media? */
+
 
 typedef struct tagSHELLFOLDER *LPSHELLFOLDER,IShellFolder;
-typedef struct {
-	HRESULT	(CALLBACK *fnQueryInterface)(LPSHELLFOLDER this,REFIID refiid,LPVOID *obj);
-	HRESULT	(CALLBACK *fnAddRef)(LPSHELLFOLDER this);
-	HRESULT	(CALLBACK *fnRelease)(LPSHELLFOLDER this);
-	/* IShellFolder methods */
+typedef struct IShellFolder_VTable {
+    /* *** IUnknown methods *** */
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
 
-	HRESULT (CALLBACK *fnParseDisplayName) (LPSHELLFOLDER this,HWND32 hwndOwner,LPBC pbcReserved,LPOLESTR lpszDisplayName,DWORD * pchEaten,LPITEMIDLIST * ppidl, DWORD *pdwAttributes) ;
-
-	HRESULT (CALLBACK *fnEnumObjects)( LPSHELLFOLDER this,HWND32 hwndOwner, DWORD grfFlags, LPENUMIDLIST* ppenumIDList);
-	HRESULT (CALLBACK *fnBindToObject)(LPSHELLFOLDER this, LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut);
-	HRESULT (CALLBACK *fnBindToStorage)(LPSHELLFOLDER this, LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvObj);
-    	HRESULT (CALLBACK *fnCompareIDs) (LPSHELLFOLDER this, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);
-	HRESULT (CALLBACK *fnCreateViewObject) (LPSHELLFOLDER this, HWND32 hwndOwner, REFIID riid, LPVOID * ppvOut);
-	HRESULT (CALLBACK *fnGetAttributesOf)  (LPSHELLFOLDER this, UINT32 cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut);
-	HRESULT (CALLBACK *fnGetUIObjectOf)    (LPSHELLFOLDER this, HWND32 hwndOwner, UINT32 cidl, LPCITEMIDLIST * apidl, REFIID riid, UINT32 * prgfInOut, LPVOID * ppvOut);
-	HRESULT (CALLBACK *fnGetDisplayNameOf) (LPSHELLFOLDER this, LPCITEMIDLIST pidl, DWORD uFlags, LPSTRRET lpName);
-	HRESULT (CALLBACK *fnSetNameOf)        (LPSHELLFOLDER this, HWND32 hwndOwner, LPCITEMIDLIST pidl, LPCOLESTR lpszName, DWORD uFlags, LPITEMIDLIST * ppidlOut);
-} *LPSHELLFOLDER_VTABLE;
+    /* *** IShellFolder methods *** */
+    STDMETHOD(ParseDisplayName) (THIS_ HWND32 hwndOwner,
+        LPBC pbcReserved, LPOLESTR lpszDisplayName,
+        ULONG * pchEaten, LPITEMIDLIST * ppidl, ULONG *pdwAttributes) PURE;
+    STDMETHOD(EnumObjects) ( THIS_ HWND32 hwndOwner, DWORD grfFlags, LPENUMIDLIST
+* ppenumIDList) PURE;
+    STDMETHOD(BindToObject)     (THIS_ LPCITEMIDLIST pidl, LPBC pbcReserved,
+                                 REFIID riid, LPVOID * ppvOut) PURE;
+    STDMETHOD(BindToStorage)    (THIS_ LPCITEMIDLIST pidl, LPBC pbcReserved,
+                                 REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD(CompareIDs)       (THIS_ LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) PURE;
+    STDMETHOD(CreateViewObject) (THIS_ HWND32 hwndOwner, REFIID riid, LPVOID * ppvOut) PURE;
+    STDMETHOD(GetAttributesOf)  (THIS_ UINT32 cidl, LPCITEMIDLIST * apidl,
+                                    ULONG * rgfInOut) PURE;
+    STDMETHOD(GetUIObjectOf)    (THIS_ HWND32 hwndOwner, UINT32 cidl, LPCITEMIDLIST
+* apidl,
+                                 REFIID riid, UINT32 * prgfInOut, LPVOID * ppvOut) PURE;
+    STDMETHOD(GetDisplayNameOf) (THIS_ LPCITEMIDLIST pidl, DWORD uFlags, LPSTRRET lpName) PURE;
+    STDMETHOD(SetNameOf)        (THIS_ HWND32 hwndOwner, LPCITEMIDLIST pidl,
+                                 LPCOLESTR lpszName, DWORD uFlags,
+                                 LPITEMIDLIST * ppidlOut) PURE;
+} *LPSHELLFOLDER_VTABLE,IShellFolder_VTable;
 
 struct tagSHELLFOLDER {
-	LPSHELLFOLDER_VTABLE	*lpvtbl;
+	LPSHELLFOLDER_VTABLE	lpvtbl;
+	DWORD			ref;
 };
+
+#undef THIS
+
+/****************************************************************************
+ * IShellLink interface
+ */
+
+#define THIS LPSHELLLINK this
+/* IShellLink::Resolve fFlags */
+typedef enum {
+    SLR_NO_UI           = 0x0001,
+    SLR_ANY_MATCH       = 0x0002,
+    SLR_UPDATE          = 0x0004,
+} SLR_FLAGS;
+
+/* IShellLink::GetPath fFlags */
+typedef enum {
+    SLGP_SHORTPATH      = 0x0001,
+    SLGP_UNCPRIORITY    = 0x0002,
+} SLGP_FLAGS;
+
+
+
+typedef struct IShellLink IShellLink,*LPSHELLLINK;
+typedef struct IShellLink_VTable
+{
+    // *** IUnknown methods ***
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+    STDMETHOD(GetPath)(THIS_ LPSTR pszFile, INT32 cchMaxPath, WIN32_FIND_DATA32A *pfd, DWORD fFlags) PURE;
+
+    STDMETHOD(GetIDList)(THIS_ LPITEMIDLIST * ppidl) PURE;
+    STDMETHOD(SetIDList)(THIS_ LPCITEMIDLIST pidl) PURE;
+
+    STDMETHOD(GetDescription)(THIS_ LPSTR pszName, int cchMaxName) PURE;
+    STDMETHOD(SetDescription)(THIS_ LPCSTR pszName) PURE;
+
+    STDMETHOD(GetWorkingDirectory)(THIS_ LPSTR pszDir, int cchMaxPath) PURE;
+    STDMETHOD(SetWorkingDirectory)(THIS_ LPCSTR pszDir) PURE;
+
+    STDMETHOD(GetArguments)(THIS_ LPSTR pszArgs, int cchMaxPath) PURE;
+    STDMETHOD(SetArguments)(THIS_ LPCSTR pszArgs) PURE;
+
+    STDMETHOD(GetHotkey)(THIS_ WORD *pwHotkey) PURE;
+    STDMETHOD(SetHotkey)(THIS_ WORD wHotkey) PURE;
+
+    STDMETHOD(GetShowCmd)(THIS_ INT32 *piShowCmd) PURE;
+    STDMETHOD(SetShowCmd)(THIS_ INT32 iShowCmd) PURE;
+
+    STDMETHOD(GetIconLocation)(THIS_ LPSTR pszIconPath, INT32 cchIconPath, INT32 *piIcon) PURE;
+    STDMETHOD(SetIconLocation)(THIS_ LPCSTR pszIconPath, INT32 iIcon) PURE;
+
+    STDMETHOD(SetRelativePath)(THIS_ LPCSTR pszPathRel, DWORD dwReserved) PURE;
+
+    STDMETHOD(Resolve)(THIS_ HWND32 hwnd, DWORD fFlags) PURE;
+
+    STDMETHOD(SetPath)(THIS_ LPCSTR pszFile) PURE;
+} IShellLink_VTable,*LPSHELLLINK_VTABLE;
+
+struct IShellLink {
+	LPSHELLLINK_VTABLE	lpvtbl;
+	DWORD			ref;
+};
+
+#undef THIS
+
+#ifdef __WINE__
+extern LPSHELLFOLDER IShellFolder_Constructor();
+extern LPSHELLLINK IShellLink_Constructor();
+extern LPENUMIDLIST IEnumIDList_Constructor();
+#endif
+
+DWORD WINAPI SHELL32_DllGetClassObject(LPCLSID,REFIID,LPVOID*);
+
+#undef PURE
+#undef FAR
+#undef THIS
+#undef THIS_
+#undef STDMETHOD
+#undef STDMETHOD_
 #endif /*_WINE_SHLOBJ_H*/
diff --git a/include/stddebug.h b/include/stddebug.h
index 8f73efc..0f51994 100644
--- a/include/stddebug.h
+++ b/include/stddebug.h
@@ -148,6 +148,7 @@
 #undef DEBUG_STRING
 #undef DEBUG_TASK
 #undef DEBUG_TEXT
+#undef DEBUG_THUNK
 #undef DEBUG_TIMER
 #undef DEBUG_TOOLHELP
 #undef DEBUG_TWEAK
@@ -234,6 +235,7 @@
 #define DEBUG_STRING
 #define DEBUG_TASK
 #define DEBUG_TEXT
+#define DEBUG_THUNK
 #define DEBUG_TIMER
 #define DEBUG_TOOLHELP
 #define DEBUG_TWEAK
diff --git a/include/task.h b/include/task.h
index ef54135..460f5de 100644
--- a/include/task.h
+++ b/include/task.h
@@ -131,5 +131,6 @@
                                 UINT16 cmdShow );
 extern void TASK_KillCurrentTask( INT16 exitCode );
 extern HTASK16 TASK_GetNextTask( HTASK16 hTask );
+extern void TASK_Reschedule(void);
 
 #endif /* __WINE_TASK_H */
diff --git a/include/toolhelp.h b/include/toolhelp.h
index 8d1cd81..1d2ddb7 100644
--- a/include/toolhelp.h
+++ b/include/toolhelp.h
@@ -348,6 +348,18 @@
     void      **lpBadParam;
 } NFYLOGPARAMERROR;
 
+typedef struct {
+    DWORD dwSize;
+    HTASK16 hTask;
+    WORD wSS;
+    WORD wBP;
+    WORD wCS;
+    WORD wIP;
+    HMODULE16 hModule;
+    WORD wSegment;
+    WORD wFlags;
+} STACKTRACEENTRY;
+
 #pragma pack(4)
 
 #endif /* __WINE_TOOLHELP_H */
diff --git a/include/user.h b/include/user.h
index 68e023f..b235b76 100644
--- a/include/user.h
+++ b/include/user.h
@@ -24,5 +24,8 @@
          ((handle) ? PTR_SEG_OFF_TO_SEGPTR(USER_HeapSel, (handle)) : (SEGPTR)0)
 
 void USER_SignalProc(HANDLE16, UINT16, UINT16, HINSTANCE16, HQUEUE16);
+void USER_ExitWindows(void);
+HGLOBAL16 USER_CallDefaultRsrcHandler( HGLOBAL16 hMemObj, HMODULE16 hModule,
+				       HRSRC16 hRsrc );
 
 #endif  /* __WINE_USER_H */
diff --git a/include/version.h b/include/version.h
index b0cfc85..d3413e2 100644
--- a/include/version.h
+++ b/include/version.h
@@ -1 +1 @@
-#define WINE_RELEASE_INFO "Wine release 971130"
+#define WINE_RELEASE_INFO "Wine release 971221"
diff --git a/include/windows.h b/include/windows.h
index 997208a..86cb5b8 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -1591,13 +1591,30 @@
 DECL_WINELIB_TYPE(LOGPEN);
 DECL_WINELIB_TYPE(LPLOGPEN);
 
-#define PS_SOLID	  0
-#define PS_DASH           1
-#define PS_DOT            2
-#define PS_DASHDOT        3
-#define PS_DASHDOTDOT     4
-#define PS_NULL 	  5
-#define PS_INSIDEFRAME 	  6
+#define PS_SOLID         0x00000000
+#define PS_DASH          0x00000001
+#define PS_DOT           0x00000002
+#define PS_DASHDOT       0x00000003
+#define PS_DASHDOTDOT    0x00000004
+#define PS_NULL          0x00000005
+#define PS_INSIDEFRAME   0x00000006
+#define PS_USERSTYLE     0x00000007
+#define PS_ALTERNATE     0x00000008
+#define PS_STYLE_MASK    0x0000000f
+
+#define PS_ENDCAP_ROUND  0x00000000
+#define PS_ENDCAP_SQUARE 0x00000100
+#define PS_ENDCAP_FLAT   0x00000200
+#define PS_ENDCAP_MASK   0x00000f00
+
+#define PS_JOIN_ROUND    0x00000000
+#define PS_JOIN_BEVEL    0x00001000
+#define PS_JOIN_MITER    0x00002000
+#define PS_JOIN_MASK     0x0000f000
+
+#define PS_COSMETIC      0x00000000
+#define PS_GEOMETRIC     0x00010000
+#define PS_TYPE_MASK     0x000f0000
 
   /* Regions */
 
@@ -1947,6 +1964,10 @@
 	HBITMAP32	hbmColor;
 } ICONINFO,*LPICONINFO;
 
+#ifdef FSHIFT
+/* Gcc on Solaris has a version of this that we don't care about.  */
+#undef FSHIFT
+#endif
 
 #define	FVIRTKEY	TRUE          /* Assumed to be == TRUE */
 #define	FNOINVERT	0x02
@@ -2557,6 +2578,7 @@
 #define DEVICE_DEFAULT_FONT 14
 #define DEFAULT_PALETTE     15
 #define SYSTEM_FIXED_FONT   16
+#define DEFAULT_GUI_FONT    17
 
 /* DragObject stuff */
 
@@ -3038,33 +3060,47 @@
 #define GCW_HBRBACKGROUND (-10)
 #endif
 
-#define MB_OK               0x0000
-#define MB_OKCANCEL         0x0001
-#define MB_ABORTRETRYIGNORE 0x0002
-#define MB_YESNOCANCEL      0x0003
-#define MB_YESNO            0x0004
-#define MB_RETRYCANCEL      0x0005
-#define MB_TYPEMASK         0x000F
+#define MB_OK			0x00000000
+#define MB_OKCANCEL		0x00000001
+#define MB_ABORTRETRYIGNORE	0x00000002
+#define MB_YESNOCANCEL		0x00000003
+#define MB_YESNO		0x00000004
+#define MB_RETRYCANCEL		0x00000005
+#define MB_TYPEMASK		0x0000000F
 
-#define MB_ICONHAND         0x0010
-#define MB_ICONQUESTION     0x0020
-#define MB_ICONEXCLAMATION  0x0030
-#define MB_ICONASTERISK     0x0040
-#define MB_ICONMASK         0x00F0
+#define MB_ICONHAND		0x00000010
+#define MB_ICONQUESTION		0x00000020
+#define MB_ICONEXCLAMATION	0x00000030
+#define MB_ICONASTERISK		0x00000040
+#define	MB_USERICON		0x00000080
+#define MB_ICONMASK		0x000000F0
 
-#define MB_ICONINFORMATION  MB_ICONASTERISK
-#define MB_ICONSTOP         MB_ICONHAND
+#define MB_ICONINFORMATION	MB_ICONASTERISK
+#define MB_ICONSTOP		MB_ICONHAND
+#define MB_ICONWARNING		MB_ICONEXCLAMATION
+#define MB_ICONERROR		MB_ICONHAND
 
-#define MB_DEFBUTTON1       0x0000
-#define MB_DEFBUTTON2       0x0100
-#define MB_DEFBUTTON3       0x0200
-#define MB_DEFMASK          0x0F00
+#define MB_DEFBUTTON1		0x00000000
+#define MB_DEFBUTTON2		0x00000100
+#define MB_DEFBUTTON3		0x00000200
+#define MB_DEFBUTTON4		0x00000300
+#define MB_DEFMASK		0x00000F00
 
-#define MB_APPLMODAL        0x0000
-#define MB_SYSTEMMODAL      0x1000
-#define MB_TASKMODAL        0x2000
+#define MB_APPLMODAL		0x00000000
+#define MB_SYSTEMMODAL		0x00001000
+#define MB_TASKMODAL		0x00002000
+#define MB_MODEMASK		0x00003000
 
-#define MB_NOFOCUS          0x8000
+#define MB_HELP			0x00004000
+#define MB_NOFOCUS		0x00008000
+#define MB_MISCMASK		0x0000C000
+
+#define MB_SETFOREGROUND	0x00010000
+#define MB_DEFAULT_DESKTOP_ONLY	0x00020000
+#define MB_SERVICE_NOTIFICATION	0x00040000
+#define MB_TOPMOST		0x00040000
+#define MB_RIGHT		0x00080000
+#define MB_RTLREADING		0x00100000
 
 
 #define DT_TOP 0
@@ -3165,7 +3201,9 @@
 #define DFCS_MONO               0x8000
 
 /* DrawState defines ... */
-typedef BOOL32 (CALLBACK *DRAWSTATEPROC)(HDC32,LPARAM,WPARAM32,INT32,INT32);
+typedef BOOL16 (CALLBACK *DRAWSTATEPROC16)(HDC16,LPARAM,WPARAM16,INT16,INT16);
+typedef BOOL32 (CALLBACK *DRAWSTATEPROC32)(HDC32,LPARAM,WPARAM32,INT32,INT32);
+DECL_WINELIB_TYPE(DRAWSTATEPROC);
 
 /* Image type */
 #define	DST_COMPLEX	0x0000
@@ -3178,6 +3216,7 @@
 #define	DSS_NORMAL	0x0000
 #define	DSS_UNION	0x0010  /* Gray string appearance */
 #define	DSS_DISABLED	0x0020
+#define	DSS_DEFAULT	0x0040  /* Make it bold */
 #define	DSS_MONO	0x0080
 #define	DSS_RIGHT	0x8000
 
@@ -4875,6 +4914,20 @@
 DECL_WINELIB_TYPE_AW(DEVMODE);
 DECL_WINELIB_TYPE_AW(LPDEVMODE);
 
+typedef struct _PRINTER_DEFAULTS32A {
+    LPSTR        pDatatype;
+    LPDEVMODE32A pDevMode;
+    ACCESS_MASK  DesiredAccess;
+} PRINTER_DEFAULTS32A, *LPPRINTER_DEFAULTS32A;
+
+typedef struct _PRINTER_DEFAULTS32W {
+    LPWSTR       pDatatype;
+    LPDEVMODE32W pDevMode;
+    ACCESS_MASK  DesiredAccess;
+} PRINTER_DEFAULTS32W, *LPPRINTER_DEFAULTS32W;
+
+DECL_WINELIB_TYPE_AW(PRINTER_DEFAULTS);
+
 typedef struct _SYSTEM_POWER_STATUS
 {
   BOOL16  ACLineStatus;
@@ -4910,6 +4963,12 @@
 #define LR_LOADREALSIZE		0x0020
 #define LR_LOADMAP3DCOLORS	0x1000
 
+/* Flags for PolyDraw and GetPath */
+#define PT_CLOSEFIGURE          0x0001
+#define PT_LINETO               0x0002
+#define PT_BEZIERTO             0x0004
+#define PT_MOVETO               0x0006
+
 typedef struct _LARGE_INTEGER
 {
     DWORD    LowPart;
@@ -5333,6 +5392,79 @@
     } HighWord;
 } LDT_ENTRY, *LPLDT_ENTRY;
 
+#define	RDH_RECTANGLES  1
+
+typedef struct _RGNDATAHEADER {
+    DWORD	dwSize;
+    DWORD	iType;
+    DWORD	nCount;
+    DWORD	nRgnSize;
+    RECT32	rcBound;
+} RGNDATAHEADER,*LPRGNDATAHEADER;
+
+typedef struct _RGNDATA {
+    RGNDATAHEADER	rdh;
+    char		Buffer[1];
+} RGNDATA,*PRGNDATA,*LPRGNDATA;
+
+#define	HELPINFO_WINDOW		0x0001
+#define	HELPINFO_MENUITEM	0x0002
+typedef struct			/* Structure pointed to by lParam of WM_HELP */
+{
+    UINT32	cbSize;		/* Size in bytes of this struct  */
+    INT32	iContextType;	/* Either HELPINFO_WINDOW or HELPINFO_MENUITEM */
+    INT32	iCtrlId;	/* Control Id or a Menu item Id. */
+    HANDLE32	hItemHandle;	/* hWnd of control or hMenu.     */
+    DWORD	dwContextId;	/* Context Id associated with this item */
+    POINT32	MousePos;	/* Mouse Position in screen co-ordinates */
+}  HELPINFO,*LPHELPINFO;
+
+typedef void (CALLBACK *MSGBOXCALLBACK)(LPHELPINFO lpHelpInfo);
+
+typedef struct /* not sure if the 16bit version is correct */
+{
+    UINT16	cbSize;
+    HWND16	hwndOwner;
+    HINSTANCE16	hInstance;
+    LPCSTR	lpszText;
+    LPCSTR	lpszCaption;
+    DWORD	dwStyle;
+    LPCSTR	lpszIcon;
+    DWORD	dwContextHelpId;
+    MSGBOXCALLBACK	lpfnMsgBoxCallback;
+    DWORD	dwLanguageId;
+} MSGBOXPARAMS16,*LPMSGBOXPARAMS16;
+
+typedef struct
+{
+    UINT32	cbSize;
+    HWND32	hwndOwner;
+    HINSTANCE32	hInstance;
+    LPCSTR	lpszText;
+    LPCSTR	lpszCaption;
+    DWORD	dwStyle;
+    LPCSTR	lpszIcon;
+    DWORD	dwContextHelpId;
+    MSGBOXCALLBACK	lpfnMsgBoxCallback;
+    DWORD	dwLanguageId;
+} MSGBOXPARAMS32A,*LPMSGBOXPARAMS32A;
+
+typedef struct
+{
+    UINT32	cbSize;
+    HWND32	hwndOwner;
+    HINSTANCE32	hInstance;
+    LPCWSTR	lpszText;
+    LPCWSTR	lpszCaption;
+    DWORD	dwStyle;
+    LPCWSTR	lpszIcon;
+    DWORD	dwContextHelpId;
+    MSGBOXCALLBACK	lpfnMsgBoxCallback;
+    DWORD	dwLanguageId;
+} MSGBOXPARAMS32W,*LPMSGBOXPARAMS32W;
+
+DECL_WINELIB_TYPE_AW(MSGBOXPARAMS)
+
 #pragma pack(4)
 
 /* Declarations for functions that exist only in Win16 */
@@ -5390,6 +5522,7 @@
 DWORD       WINAPI GetFileResourceSize(LPCSTR,SEGPTR,SEGPTR,LPDWORD);
 DWORD       WINAPI GetFileResource(LPCSTR,SEGPTR,SEGPTR,DWORD,DWORD,LPVOID);
 DWORD       WINAPI GetHeapSpaces(HMODULE16);
+WORD        WINAPI GetIconID(HGLOBAL16,DWORD);
 INT16       WINAPI GetInstanceData(HINSTANCE16,WORD,INT16);
 HGLOBAL16   WINAPI GetMetaFileBits(HMETAFILE16);
 BOOL16      WINAPI GetModuleName(HINSTANCE16,LPSTR,INT16);
@@ -5434,6 +5567,7 @@
 WORD        WINAPI LocalCountFree(void);
 WORD        WINAPI LocalHandleDelta(WORD);
 WORD        WINAPI LocalHeapSize(void);
+HICON16     WINAPI LoadIconHandler(HGLOBAL16,BOOL16);
 BOOL16      WINAPI LocalInit(HANDLE16,WORD,WORD);
 FARPROC16   WINAPI LocalNotify(FARPROC16);
 HTASK16     WINAPI LockCurrentTask(BOOL16);
@@ -5509,6 +5643,7 @@
 HFILE32     WINAPI CreateFile32W(LPCWSTR,DWORD,DWORD,LPSECURITY_ATTRIBUTES,
                                  DWORD,DWORD,HANDLE32);
 #define     CreateFile WINELIB_NAME_AW(CreateFile)
+HPALETTE32  WINAPI CreateHalftonePalette(HDC32);
 HANDLE32    WINAPI CreateFileMapping32A(HANDLE32,LPSECURITY_ATTRIBUTES,DWORD,
                                         DWORD,DWORD,LPCSTR);
 HANDLE32    WINAPI CreateFileMapping32W(HANDLE32,LPSECURITY_ATTRIBUTES,DWORD,
@@ -5558,7 +5693,11 @@
 HRSRC32     WINAPI FindResourceEx32A(HINSTANCE32,LPCSTR,LPCSTR,WORD);
 HRSRC32     WINAPI FindResourceEx32W(HINSTANCE32,LPCWSTR,LPCWSTR,WORD);
 #define     FindResourceEx WINELIB_NAME_AW(FindResourceEx)
+BOOL32      WINAPI FlushConsoleInputBuffer(HANDLE32);
 BOOL32      WINAPI FlushFileBuffers(HFILE32);
+DWORD       WINAPI FormatMessage32A(DWORD,LPCVOID,DWORD,DWORD,LPSTR,
+				    DWORD,LPDWORD);
+#define     FormatMessage WINELIB_NAME_AW(FormatMessage)
 BOOL32      WINAPI FreeEnvironmentStrings32A(LPSTR);
 BOOL32      WINAPI FreeEnvironmentStrings32W(LPWSTR);
 #define     FreeEnvironmentStrings WINELIB_NAME_AW(FreeEnvironmentStrings)
@@ -5570,7 +5709,14 @@
 BOOL32      WINAPI GetComputerName32A(LPSTR,LPDWORD);
 BOOL32      WINAPI GetComputerName32W(LPWSTR,LPDWORD);
 #define     GetComputerName WINELIB_NAME_AW(GetComputerName)
+UINT32      WINAPI GetConsoleCP();
+BOOL32      WINAPI GetConsoleMode(HANDLE32,LPDWORD);
+UINT32      WINAPI GetConsoleOutputCP();
+DWORD       WINAPI GetConsoleTitle32A(LPSTR,DWORD);
+DWORD       WINAPI GetConsoleTitle32W(LPWSTR,DWORD);
+#define     GetConsoleTitle WINELIB_NAME_AW(GetConsoleTitle)
 BOOL32      WINAPI GetCPInfo(UINT32,LPCPINFO);
+HANDLE32    WINAPI GetCurrentObject(HDC32,UINT32);
 HANDLE32    WINAPI GetCurrentProcess(void);
 DWORD       WINAPI GetCurrentProcessId(void);
 HANDLE32    WINAPI GetCurrentThread(void);
@@ -5589,11 +5735,14 @@
 DWORD       WINAPI GetFullPathName32A(LPCSTR,DWORD,LPSTR,LPSTR*);
 DWORD       WINAPI GetFullPathName32W(LPCWSTR,DWORD,LPWSTR,LPWSTR*);
 #define     GetFullPathName WINELIB_NAME_AW(GetFullPathName)
+DWORD       WINAPI GetLargestConsoleWindowSize(HANDLE32);
 VOID        WINAPI GetLocalTime(LPSYSTEMTIME);
 DWORD       WINAPI GetLogicalDrives(void);
 BOOL32      WINAPI GetMenuItemInfo32A(HMENU32,UINT32,BOOL32,MENUITEMINFO32A*);
 BOOL32      WINAPI GetMenuItemInfo32W(HMENU32,UINT32,BOOL32,MENUITEMINFO32W*);
 #define     GetMenuItemInfo WINELIB_NAME_AW(GetMenuItemInfo)
+BOOL32      WINAPI GetNumberOfConsoleInputEvents(HANDLE32,LPDWORD);
+BOOL32      WINAPI GetNumberOfConsoleMouseButtons(LPDWORD);
 DWORD       WINAPI GetObjectType(HANDLE32);
 UINT32      WINAPI GetOEMCP(void);
 DWORD       WINAPI GetPriorityClass(HANDLE32);
@@ -5635,6 +5784,7 @@
 BOOL32      WINAPI HeapUnlock(HANDLE32);
 BOOL32      WINAPI HeapValidate(HANDLE32,DWORD,LPCVOID);
 BOOL32      WINAPI IsDBCSLeadByteEx(UINT32,BYTE);
+BOOL32      WINAPI IsProcessorFeaturePresent(DWORD);
 BOOL32      WINAPI IsWindowUnicode(HWND32);
 BOOL32      WINAPI IsValidLocale(DWORD,DWORD);
 BOOL32      WINAPI LocalFileTimeToFileTime(const FILETIME*,LPFILETIME);
@@ -5702,6 +5852,7 @@
 BOOL32      WINAPI SetBrushOrgEx(HDC32,INT32,INT32,LPPOINT32);
 BOOL32      WINAPI SetCommMask(INT32,DWORD);
 BOOL32      WINAPI SetCommTimeouts(INT32,LPCOMMTIMEOUTS);
+BOOL32      WINAPI SetConsoleMode(HANDLE32,DWORD);
 BOOL32      WINAPI SetConsoleTitle32A(LPCSTR);
 BOOL32      WINAPI SetConsoleTitle32W(LPCWSTR);
 #define     SetConsoleTitle WINELIB_NAME_AW(SetConsoleTitle)
@@ -5743,8 +5894,8 @@
 BOOL32      WINAPI VirtualQuery(LPCVOID,LPMEMORY_BASIC_INFORMATION,DWORD);
 BOOL32      WINAPI VirtualQueryEx(HANDLE32,LPCVOID,LPMEMORY_BASIC_INFORMATION,DWORD);
 BOOL32      WINAPI VirtualUnlock(LPVOID,DWORD);
-BOOL32      WINAPI WriteConsole32A(HANDLE32,LPVOID,DWORD,LPDWORD,LPVOID);
-BOOL32      WINAPI WriteConsole32W(HANDLE32,LPVOID,DWORD,LPDWORD,LPVOID);
+BOOL32      WINAPI WriteConsole32A(HANDLE32,LPCVOID,DWORD,LPDWORD,LPVOID);
+BOOL32      WINAPI WriteConsole32W(HANDLE32,LPCVOID,DWORD,LPDWORD,LPVOID);
 #define     WriteConsole WINELIB_NAME_AW(WriteConsole)
 BOOL32      WINAPI WriteFile(HFILE32,LPVOID,DWORD,LPDWORD,LPOVERLAPPED);
 
@@ -5778,6 +5929,9 @@
 
 /* Declarations for functions that change between Win16 and Win32 */
 
+BOOL16      WINAPI AbortPath16(HDC16);
+BOOL32      WINAPI AbortPath32(HDC32);
+#define     AbortPath WINELIB_NAME(AbortPath)
 LRESULT     WINAPI AboutDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
 LRESULT     WINAPI AboutDlgProc32(HWND32,UINT32,WPARAM32,LPARAM);
 #define     AboutDlgProc WINELIB_NAME(AboutDlgProc)
@@ -5855,6 +6009,9 @@
 HDC16       WINAPI BeginPaint16(HWND16,LPPAINTSTRUCT16);
 HDC32       WINAPI BeginPaint32(HWND32,LPPAINTSTRUCT32);
 #define     BeginPaint WINELIB_NAME(BeginPaint)
+BOOL16      WINAPI BeginPath16(HDC16);
+BOOL32      WINAPI BeginPath32(HDC32);
+#define     BeginPath WINELIB_NAME(BeginPath)
 BOOL16      WINAPI BitBlt16(HDC16,INT16,INT16,INT16,INT16,HDC16,INT16,INT16,DWORD);
 BOOL32      WINAPI BitBlt32(HDC32,INT32,INT32,INT32,INT32,HDC32,INT32,INT32,DWORD);
 #define     BitBlt WINELIB_NAME(BitBlt)
@@ -5946,6 +6103,9 @@
 BOOL16      WINAPI CloseClipboard16(void);
 BOOL32      WINAPI CloseClipboard32(void);
 #define     CloseClipboard WINELIB_NAME(CloseClipboard)
+BOOL16      WINAPI CloseFigure16(HDC16);
+BOOL32      WINAPI CloseFigure32(HDC32);
+#define     CloseFigure WINELIB_NAME(CloseFigure)
 HMETAFILE16 WINAPI CloseMetaFile16(HDC16);
 HMETAFILE32 WINAPI CloseMetaFile32(HDC32);
 #define     CloseMetaFile WINELIB_NAME(CloseMetaFile)
@@ -6304,6 +6464,9 @@
 BOOL16      WINAPI EndPaint16(HWND16,const PAINTSTRUCT16*);
 BOOL32      WINAPI EndPaint32(HWND32,const PAINTSTRUCT32*);
 #define     EndPaint WINELIB_NAME(EndPaint)
+BOOL16      WINAPI EndPath16(HDC16);
+BOOL32      WINAPI EndPath32(HDC32);
+#define     EndPath WINELIB_NAME(EndPath)
 BOOL16      WINAPI EnumChildWindows16(HWND16,WNDENUMPROC16,LPARAM);
 BOOL32      WINAPI EnumChildWindows32(HWND32,WNDENUMPROC32,LPARAM);
 #define     EnumChildWindows WINELIB_NAME(EnumChildWindows)
@@ -6360,6 +6523,9 @@
 BOOL16      WINAPI ExitWindows16(DWORD,UINT16);
 #define     ExitWindows32(a,b) ExitWindowsEx(EWX_LOGOFF,0xffffffff)
 #define     ExitWindows WINELIB_NAME(ExitWindows)
+HPEN16      WINAPI ExtCreatePen16(DWORD,DWORD,const LOGBRUSH16*,DWORD,const DWORD*);
+HPEN32      WINAPI ExtCreatePen32(DWORD,DWORD,const LOGBRUSH32*,DWORD,const DWORD*);
+#define     ExtCreatePen WINELIB_NAME(ExtCreatePen)
 BOOL16      WINAPI ExtFloodFill16(HDC16,INT16,INT16,COLORREF,UINT16);
 BOOL32      WINAPI ExtFloodFill32(HDC32,INT32,INT32,COLORREF,UINT32);
 #define     ExtFloodFill WINELIB_NAME(ExtFloodFill)
@@ -6382,6 +6548,9 @@
 void        WINAPI FatalAppExit32A(UINT32,LPCSTR);
 void        WINAPI FatalAppExit32W(UINT32,LPCWSTR);
 #define     FatalAppExit WINELIB_NAME_AW(FatalAppExit)
+BOOL16      WINAPI FillPath16(HDC16);
+BOOL32      WINAPI FillPath32(HDC32);
+#define     FillPath WINELIB_NAME(FillPath)
 INT16       WINAPI FillRect16(HDC16,const RECT16*,HBRUSH16);
 INT32       WINAPI FillRect32(HDC32,const RECT32*,HBRUSH32);
 #define     FillRect WINELIB_NAME(FillRect)
@@ -6402,11 +6571,11 @@
 HANDLE16    WINAPI FindFirstFile16(LPCSTR,LPWIN32_FIND_DATA32A);
 HANDLE32    WINAPI FindFirstFile32A(LPCSTR,LPWIN32_FIND_DATA32A);
 HANDLE32    WINAPI FindFirstFile32W(LPCWSTR,LPWIN32_FIND_DATA32W);
-#define     FindFirst WINELIB_NAME_AW(FindFirst)
+#define     FindFirstFile WINELIB_NAME_AW(FindFirstFile)
 BOOL16      WINAPI FindNextFile16(HANDLE16,LPWIN32_FIND_DATA32A);
 BOOL32      WINAPI FindNextFile32A(HANDLE32,LPWIN32_FIND_DATA32A);
 BOOL32      WINAPI FindNextFile32W(HANDLE32,LPWIN32_FIND_DATA32W);
-#define     FindNext WINELIB_NAME_AW(FindNext)
+#define     FindNextFile WINELIB_NAME_AW(FindNextFile)
 HRSRC16     WINAPI FindResource16(HINSTANCE16,SEGPTR,SEGPTR);
 HRSRC32     WINAPI FindResource32A(HINSTANCE32,LPCSTR,LPCSTR);
 HRSRC32     WINAPI FindResource32W(HINSTANCE32,LPCWSTR,LPCWSTR);
@@ -6563,6 +6732,9 @@
 INT16       WINAPI GetDeviceCaps16(HDC16,INT16);
 INT32       WINAPI GetDeviceCaps32(HDC32,INT32);
 #define     GetDeviceCaps WINELIB_NAME(GetDeviceCaps)
+UINT16      WINAPI GetDIBColorTable16(HDC16,UINT16,UINT16,RGBQUAD*);
+UINT32      WINAPI GetDIBColorTable32(HDC32,UINT32,UINT32,RGBQUAD*);
+#define     GetDIBColorTable WINELIB_NAME(GetDIBColorTable)
 INT16       WINAPI GetDIBits16(HDC16,HBITMAP16,UINT16,UINT16,LPSTR,LPBITMAPINFO,UINT16);
 INT32       WINAPI GetDIBits32(HDC32,HBITMAP32,UINT32,UINT32,LPSTR,LPBITMAPINFO,UINT32);
 #define     GetDIBits WINELIB_NAME(GetDIBits)
@@ -6718,6 +6890,9 @@
 HWND16      WINAPI GetParent16(HWND16);
 HWND32      WINAPI GetParent32(HWND32);
 #define     GetParent WINELIB_NAME(GetParent)
+INT16       WINAPI GetPath16(HDC16,LPPOINT16,LPBYTE,INT16);
+INT32       WINAPI GetPath32(HDC32,LPPOINT32,LPBYTE,INT32);
+#define     GetPath WINELIB_NAME(GetPath)
 COLORREF    WINAPI GetPixel16(HDC16,INT16,INT16);
 COLORREF    WINAPI GetPixel32(HDC32,INT32,INT32);
 #define     GetPixel WINELIB_NAME(GetPixel)
@@ -7228,6 +7403,10 @@
 INT32       WINAPI MessageBox32A(HWND32,LPCSTR,LPCSTR,UINT32);
 INT32       WINAPI MessageBox32W(HWND32,LPCWSTR,LPCWSTR,UINT32);
 #define     MessageBox WINELIB_NAME_AW(MessageBox)
+INT16       WINAPI MessageBoxIndirect16(LPMSGBOXPARAMS16);
+INT32       WINAPI MessageBoxIndirect32A(LPMSGBOXPARAMS32A);
+INT32       WINAPI MessageBoxIndirect32W(LPMSGBOXPARAMS32W);
+#define     MessageBoxIndirect WINELIB_NAME_AW(MessageBoxIndirect)
 BOOL16      WINAPI ModifyMenu16(HMENU16,UINT16,UINT16,UINT16,SEGPTR);
 BOOL32      WINAPI ModifyMenu32A(HMENU32,UINT32,UINT32,UINT32,LPCSTR);
 BOOL32      WINAPI ModifyMenu32W(HMENU32,UINT32,UINT32,UINT32,LPCWSTR);
@@ -7292,6 +7471,9 @@
 BOOL16      WINAPI PatBlt16(HDC16,INT16,INT16,INT16,INT16,DWORD);
 BOOL32      WINAPI PatBlt32(HDC32,INT32,INT32,INT32,INT32,DWORD);
 #define     PatBlt WINELIB_NAME(PatBlt)
+HRGN16      WINAPI PathToRegion16(HDC16);
+HRGN32      WINAPI PathToRegion32(HDC32);
+#define     PathToRegion WINELIB_NAME(PathToRegion)
 BOOL16      WINAPI PeekMessage16(LPMSG16,HWND16,UINT16,UINT16,UINT16);
 BOOL32      WINAPI PeekMessage32A(LPMSG32,HWND32,UINT32,UINT32,UINT32);
 BOOL32      WINAPI PeekMessage32W(LPMSG32,HWND32,UINT32,UINT32,UINT32);
@@ -7469,6 +7651,9 @@
 INT32       WINAPI ScrollWindowEx32(HWND32,INT32,INT32,const RECT32*,
                                     const RECT32*,HRGN32,LPRECT32,UINT32);
 #define     ScrollWindowEx WINELIB_NAME(ScrollWindowEx)
+BOOL16      WINAPI SelectClipPath16(HDC16,INT16);
+BOOL32      WINAPI SelectClipPath32(HDC32,INT32);
+#define     SelectClipPath WINELIB_NAME(SelectClipPath)
 INT16       WINAPI SelectClipRgn16(HDC16,HRGN16);
 INT32       WINAPI SelectClipRgn32(HDC32,HRGN32);
 #define     SelectClipRgn WINELIB_NAME(SelectClipRgn)
@@ -7486,6 +7671,13 @@
 LRESULT     WINAPI SendMessage32A(HWND32,UINT32,WPARAM32,LPARAM);
 LRESULT     WINAPI SendMessage32W(HWND32,UINT32,WPARAM32,LPARAM);
 #define     SendMessage WINELIB_NAME_AW(SendMessage)
+LRESULT     WINAPI SendMessageTimeout16(HWND16,UINT16,WPARAM16,LPARAM,UINT16,
+					UINT16,LPWORD);
+LRESULT     WINAPI SendMessageTimeout32A(HWND32,UINT32,WPARAM32,LPARAM,UINT32,
+					 UINT32,LPDWORD);
+LRESULT     WINAPI SendMessageTimeout32W(HWND32,UINT32,WPARAM32,LPARAM,UINT32,
+					 UINT32,LPDWORD);
+#define     SendMessageTimeout WINELIB_NAME_AW(SendMessageTimeout)
 HWND16      WINAPI SetActiveWindow16(HWND16);
 HWND32      WINAPI SetActiveWindow32(HWND32);
 #define     SetActiveWindow WINELIB_NAME(SetActiveWindow)
@@ -7542,6 +7734,9 @@
 BOOL16      WINAPI SetDeskWallPaper16(LPCSTR);
 BOOL32      WINAPI SetDeskWallPaper32(LPCSTR);
 #define     SetDeskWallPaper WINELIB_NAME(SetDeskWallPaper)
+UINT16      WINAPI SetDIBColorTable16(HDC16,UINT16,UINT16,RGBQUAD*);
+UINT32      WINAPI SetDIBColorTable32(HDC32,UINT32,UINT32,RGBQUAD*);
+#define     SetDIBColorTable WINELIB_NAME(SetDIBColorTable)
 INT16       WINAPI SetDIBits16(HDC16,HBITMAP16,UINT16,UINT16,LPCVOID,const BITMAPINFO*,UINT16);
 INT32       WINAPI SetDIBits32(HDC32,HBITMAP32,UINT32,UINT32,LPCVOID,const BITMAPINFO*,UINT32);
 #define     SetDIBits WINELIB_NAME(SetDIBits)
diff --git a/include/winerror.h b/include/winerror.h
index ce1a3fe..dd2f3f3 100644
--- a/include/winerror.h
+++ b/include/winerror.h
@@ -17,6 +17,7 @@
 #define ERROR_TOO_MANY_OPEN_FILES   4
 #define ERROR_ACCESS_DENIED         5
 #define ERROR_INVALID_HANDLE        6
+#define ERROR_NOT_ENOUGH_MEMORY     8
 #define ERROR_BAD_FORMAT            11
 #define ERROR_OUTOFMEMORY           14
 #define ERROR_NO_MORE_FILES         18
@@ -28,6 +29,7 @@
 #define ERROR_BROKEN_PIPE           109
 #define ERROR_DISK_FULL             112
 #define ERROR_CALL_NOT_IMPLEMENTED  120
+#define ERROR_INSUFFICIENT_BUFFER   122
 #define ERROR_SEEK_ON_DEVICE        132
 #define ERROR_DIR_NOT_EMPTY         145
 #define ERROR_BUSY                  170
@@ -35,9 +37,22 @@
 #define ERROR_FILENAME_EXCED_RANGE  206
 #define ERROR_MORE_DATA             234
 #define ERROR_NO_MORE_ITEMS         259
+#define ERROR_INVALID_ADDRESS       487
+#define ERROR_CAN_NOT_COMPLETE      1003
 #define ERROR_IO_DEVICE             1117
 #define ERROR_POSSIBLE_DEADLOCK     1131
 #define ERROR_BAD_DEVICE            1200
 #define ERROR_NO_NETWORK            1222
+#define ERROR_COMMITMENT_LIMIT      1455
+
+/* HRESULT values for OLE, SHELL and other Interface stuff */
+#define	NOERROR				0
+#define	S_OK				0
+#define	E_UNEXPECTED			0x8000FFFF
+#define	E_OUTOFMEMORY			0x8007000E
+#define	E_INVALIDARG			0x80070057
+
+#define	OLE_E_ENUM_NOMORE		0x80040002
+#define	CLASS_E_CLASSNOTAVAILABLE	0x80040111
 
 #endif  /* __WINE_WINERROR_H */
diff --git a/include/winnt.h b/include/winnt.h
index a23df14..0d53299 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -24,6 +24,12 @@
 #define HEAP_WINE_SEGPTR                0x01000000  /* Not a Win32 flag */
 #define HEAP_WINE_CODESEG               0x02000000  /* Not a Win32 flag */
 
+/* Processor feature flags.  */
+#define PF_FLOATING_POINT_PRECISION_ERRATA    0
+#define PF_FLOATING_POINT_EMULATED            1
+#define PF_COMPARE_EXCHANGE_DOUBLE            2
+#define PF_MMX_INSTRUCTIONS_AVAILABLE         3
+
 /* The Win32 register context */
 
 #define CONTEXT_i386      0x00010000
diff --git a/include/winpos.h b/include/winpos.h
index f07431e..a572d93 100644
--- a/include/winpos.h
+++ b/include/winpos.h
@@ -41,5 +41,8 @@
 extern LONG WINPOS_HandleWindowPosChanging16(WND *wndPtr, WINDOWPOS16 *winpos);
 extern LONG WINPOS_HandleWindowPosChanging32(WND *wndPtr, WINDOWPOS32 *winpos);
 extern INT16 WINPOS_WindowFromPoint( WND* scopeWnd, POINT16 pt, WND **ppWnd );
+extern void WINPOS_CheckInternalPos( HWND32 hwnd );
+extern BOOL32 WINPOS_ActivateOtherWindow(WND* pWnd);
+extern BOOL32 WINPOS_CreateInternalPosAtom(void);
 
 #endif  /* __WINE_WINPOS_H */
diff --git a/include/winsock.h b/include/winsock.h
index d202655..edee250 100644
--- a/include/winsock.h
+++ b/include/winsock.h
@@ -61,46 +61,62 @@
 {
         UINT16    fd_count;               /* how many are SET? */
         SOCKET16  fd_array[FD_SETSIZE];   /* an array of SOCKETs */
-} ws_fd_set;
+} ws_fd_set16;
+
+typedef struct
+{
+        UINT32    fd_count;               /* how many are SET? */
+        SOCKET32  fd_array[FD_SETSIZE];   /* an array of SOCKETs */
+} ws_fd_set32;
 
 /* ws_fd_set operations */
 
-INT16 WINAPI __WSAFDIsSet16( SOCKET16, ws_fd_set * );
-INT32 WINAPI __WSAFDIsSet32( SOCKET32, ws_fd_set * );
+INT16 WINAPI __WSAFDIsSet16( SOCKET16, ws_fd_set16 * );
+INT32 WINAPI __WSAFDIsSet32( SOCKET32, ws_fd_set32 * );
 #define __WSAFDIsSet WINELIB_NAME(__WSAFDIsSet);
 
-#define WS_FD_CLR(fd, set) do { \
+#define __WS_FD_CLR(fd, set, cast) do { \
     UINT16 __i; \
-    for (__i = 0; __i < ((ws_fd_set*)(set))->fd_count ; __i++) \
+    for (__i = 0; __i < ((cast*)(set))->fd_count ; __i++) \
     { \
-        if (((ws_fd_set*)(set))->fd_array[__i] == fd) \
+        if (((cast*)(set))->fd_array[__i] == fd) \
 	{ \
-            while (__i < ((ws_fd_set*)(set))->fd_count-1) \
+            while (__i < ((cast*)(set))->fd_count-1) \
 	    { \
-                ((ws_fd_set*)(set))->fd_array[__i] = \
-                    ((ws_fd_set*)(set))->fd_array[__i+1]; \
+                ((cast*)(set))->fd_array[__i] = \
+                    ((cast*)(set))->fd_array[__i+1]; \
                 __i++; \
             } \
-            ((ws_fd_set*)(set))->fd_count--; \
+            ((cast*)(set))->fd_count--; \
             break; \
         } \
     } \
 } while(0)
+#define WS_FD_CLR16(fd, set)	__WS_FD_CLR((fd),(set), ws_fd_set16)
+#define WS_FD_CLR32(fd, set)	__WS_FD_CLR((fd),(set), ws_fd_set32)
+#define WS_FD_CLR 		WINELIB_NAME(WS_FD_CLR);
 
-#define WS_FD_SET(fd, set) do { \
-    if (((ws_fd_set*)(set))->fd_count < FD_SETSIZE) \
-        ((ws_fd_set*)(set))->fd_array[((ws_fd_set*)(set))->fd_count++]=(fd);\
+#define __WS_FD_SET(fd, set, cast) do { \
+    if (((cast*)(set))->fd_count < FD_SETSIZE) \
+        ((cast*)(set))->fd_array[((cast*)(set))->fd_count++]=(fd);\
 } while(0)
+#define WS_FD_SET16(fd, set)    __WS_FD_SET((fd),(set), ws_fd_set16)
+#define WS_FD_SET32(fd, set)    __WS_FD_SET((fd),(set), ws_fd_set32)
+#define WS_FD_SET		WINELIB_NAME(WS_FD_SET);
 
-#define WS_FD_ZERO(set) (((ws_fd_set*)(set))->fd_count=0)
+#define WS_FD_ZERO16(set) (((ws_fd_set16*)(set))->fd_count=0)
+#define WS_FD_ZERO32(set) (((ws_fd_set32*)(set))->fd_count=0)
+#define WS_FD_ZERO		WINELIB_NAME(WS_FD_ZERO);
 
-#define WS_FD_ISSET(fd, set) __WSAFDIsSet((SOCKET16)(fd), (ws_fd_set*)(set))
+#define WS_FD_ISSET16(fd, set) __WSAFDIsSet16((SOCKET16)(fd), (ws_fd_set16*)(set))
+#define WS_FD_ISSET32(fd, set) __WSAFDIsSet32((SOCKET32)(fd), (ws_fd_set32*)(set))
+#define WS_FD_ISSET		WINELIB_NAME(WS_FD_ISSET);
 
 /* 
  * Internet address (old style... should be updated) 
  */
 
-typedef struct ws_addr_in
+struct ws_in_addr
 {
         union {
                 struct { BYTE   s_b1,s_b2,s_b3,s_b4; } S_un_b;
@@ -113,15 +129,15 @@
 #define ws_imp   S_un.S_un_w.s_w2	/* imp */
 #define ws_impno S_un.S_un_b.s_b4	/* imp # */
 #define ws_lh    S_un.S_un_b.s_b3	/* logical host */
-} _ws_in_addr;
+};
 
-typedef struct ws_sockaddr_in
+struct ws_sockaddr_in
 {
         INT16		sin_family;
         UINT16 		sin_port;
-        _ws_in_addr 	sin_addr;
-        char    	sin_zero[8];
-} _ws_sockaddr_in;
+        struct ws_in_addr sin_addr;
+        BYTE    	sin_zero[8];
+};
 
 #define WSADESCRIPTION_LEN      256
 #define WSASYS_STATUS_LEN       128
@@ -356,27 +372,51 @@
 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc);
 FARPROC32 WINAPI WSASetBlockingHook32(FARPROC32 lpBlockFunc);
 #define   WSASetBlockingHook WINELIB_NAME(WSASetBlockingHook)
-HANDLE16  WINAPI WSAAsyncGetServByName(HWND16 hWnd, UINT16 wMsg,
-                                       LPCSTR name, LPCSTR proto,
-                                       SEGPTR buf, INT16 buflen);
 
-HANDLE16  WINAPI WSAAsyncGetServByPort(HWND16 hWnd, UINT16 wMsg, INT16 port,
-                                       LPCSTR proto, SEGPTR buf, INT16 buflen);
+HANDLE16  WINAPI WSAAsyncGetServByName16(HWND16 hWnd, UINT16 wMsg, LPCSTR name, LPCSTR proto,
+                                         SEGPTR buf, INT16 buflen);
+HANDLE32  WINAPI WSAAsyncGetServByName32(HWND32 hWnd, UINT32 uMsg, LPCSTR name, LPCSTR proto,
+					 LPSTR sbuf, INT32 buflen);
+#define   WSAAsyncGetServByName WINELIB_NAME(WSAAsyncGetServByName)
 
-HANDLE16  WINAPI WSAAsyncGetProtoByName(HWND16 hWnd, UINT16 wMsg,
-                                        LPCSTR name, SEGPTR buf, INT16 buflen);
+HANDLE16  WINAPI WSAAsyncGetServByPort16(HWND16 hWnd, UINT16 wMsg, INT16 port,
+                                         LPCSTR proto, SEGPTR buf, INT16 buflen);
+HANDLE32  WINAPI WSAAsyncGetServByPort32(HWND32 hWnd, UINT32 uMsg, INT32 port,
+					 LPCSTR proto, LPSTR sbuf, INT32 buflen);
+#define   WSAAsyncGetServByPort WINELIB_NAME(WSAAsyncGetServByPort)
 
-HANDLE16  WINAPI WSAAsyncGetProtoByNumber(HWND16 hWnd, UINT16 wMsg,
-                                       INT16 number, SEGPTR buf, INT16 buflen);
+HANDLE16  WINAPI WSAAsyncGetProtoByName16(HWND16 hWnd, UINT16 wMsg,
+                                          LPCSTR name, SEGPTR buf, INT16 buflen);
+HANDLE32  WINAPI WSAAsyncGetProtoByName32(HWND32 hWnd, UINT32 uMsg,
+					  LPCSTR name, LPSTR sbuf, INT32 buflen);
+#define   WSAAsyncGetProtoByByName WINELIB_NAME(WSAAsyncGetProtoByByName)
 
-HANDLE16  WINAPI WSAAsyncGetHostByName(HWND16 hWnd, UINT16 wMsg,
-                                       LPCSTR name, SEGPTR buf, INT16 buflen);
+HANDLE16  WINAPI WSAAsyncGetProtoByNumber16(HWND16 hWnd, UINT16 wMsg,
+                                            INT16 number, SEGPTR buf, INT16 buflen);
+HANDLE32  WINAPI WSAAsyncGetProtoByNumber32(HWND32 hWnd, UINT32 uMsg,
+					    INT32 number, LPSTR sbuf, INT32 buflen);
+#define   WSAAsyncGetProtoByNumber WINELIB_NAME(WSAAsyncGetProtoByNumber)
 
-HANDLE16  WINAPI WSAAsyncGetHostByAddr(HWND16 hWnd, UINT16 wMsg, LPCSTR addr,
+HANDLE16  WINAPI WSAAsyncGetHostByName16(HWND16 hWnd, UINT16 wMsg,
+                                         LPCSTR name, SEGPTR buf, INT16 buflen);
+HANDLE32  WINAPI WSAAsyncGetHostByName32(HWND32 hWnd, UINT32 uMsg,
+					 LPCSTR name, LPSTR sbuf, INT32 buflen);
+#define   WSAAsyncGetHostByName WINELIB_NAME(WSAAsyncGetHostByName)
+
+HANDLE16  WINAPI WSAAsyncGetHostByAddr16(HWND16 hWnd, UINT16 wMsg, LPCSTR addr,
                               INT16 len, INT16 type, SEGPTR buf, INT16 buflen);
-INT16 	  WINAPI WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle);
-INT16     WINAPI WSAAsyncSelect(SOCKET16 s, HWND16 hWnd, UINT16 wMsg,
-                                UINT32 lEvent);
+HANDLE32  WINAPI WSAAsyncGetHostByAddr32(HWND32 hWnd, UINT32 uMsg, LPCSTR addr,
+			      INT32 len, INT32 type, LPSTR sbuf, INT32 buflen);
+#define   WSAAsyncGetHostByAddr WINELIB_NAME(WSAAsyncGetHostByAddr)
+
+INT16 	  WINAPI WSACancelAsyncRequest16(HANDLE16 hAsyncTaskHandle);
+INT32     WINAPI WSACancelAsyncRequest32(HANDLE32 hAsyncTaskHandle);
+#define   WSACancelAsyncRequest WINELIB_NAME(WSACancelAsyncRequest)
+
+INT16     WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, UINT32 lEvent);
+INT32     WINAPI WSAAsyncSelect32(SOCKET32 s, HWND32 hWnd, UINT32 uMsg, UINT32 lEvent);
+#define   WSAAsyncSelect WINELIB_NAME(WSAAsyncSelect)
+
 
 #ifdef __cplusplus
 }
@@ -458,12 +498,18 @@
 
   /* custom data */
 
-  HWND16        hWnd;				/* hWnd to post */ 
-  UINT16        uMsg;				/* uMsg message to. */
+  HWND32        hWnd;				/* hWnd to post */ 
+  UINT32        uMsg;				/* uMsg message to. */
 
-  SEGPTR	buffer_base;			/* buffer to copy result to */
-  UINT16        buflen;
-  UINT16	flags;				/* WSMSG_ASYNC_... */
+  union 
+  {
+    SEGPTR seg_base;
+    LPSTR  lin_base;
+    void*  ptr_base;
+  } 		b;				/* buffer to copy result to */
+
+  UINT32        buflen;
+  UINT32	flags;				/* WSMSG_ASYNC_... */
 } ws_async_op;
 
 #define WSMSG_ASYNC_HOSTBYNAME  0x0001
@@ -472,6 +518,7 @@
 #define WSMSG_ASYNC_PROTOBYNUM  0x0020
 #define WSMSG_ASYNC_SERVBYNAME  0x0100
 #define WSMSG_ASYNC_SERVBYPORT  0x0200
+#define WSMSG_ASYNC_WIN32	0x1000
 #define WSMSG_DEAD_AOP		0x8000
 
 typedef struct __sop	/* WSAAsyncSelect() control struct */
@@ -479,8 +526,8 @@
   struct __sop *next, *prev;
 
   struct __ws*  pws;
-  HWND16        hWnd;
-  UINT16        uMsg;
+  HWND32        hWnd;
+  UINT32        uMsg;
 } ws_select_op;
 
 typedef struct	__ws	/* socket */
diff --git a/include/wintypes.h b/include/wintypes.h
index 5092157..a5ab556 100644
--- a/include/wintypes.h
+++ b/include/wintypes.h
@@ -88,6 +88,7 @@
 typedef unsigned int    UINT32;
 typedef unsigned short  WORD;
 typedef unsigned long   DWORD;
+typedef unsigned long   ULONG;
 typedef unsigned char   BYTE;
 typedef long            LONG;
 typedef char            CHAR;
diff --git a/include/x11drv.h b/include/x11drv.h
index da3588f..0db6b86 100644
--- a/include/x11drv.h
+++ b/include/x11drv.h
@@ -14,6 +14,8 @@
 typedef struct
 {
     int          style;
+    int          endcap;
+    int          linejoin;
     int          pixel;
     int          width;
     char *       dashes;
diff --git a/loader/module.c b/loader/module.c
index f35bae4..cebaea0 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -526,7 +526,7 @@
 
     if (ne_header.ne_magic == IMAGE_OS2_SIGNATURE_LX) {
       fprintf(stderr, "Sorry, this is an OS/2 linear executable (LX) file !\n");
-      return (HMODULE32)11;
+      return (HMODULE32)12;
     }
     /* We now have a valid NE header */
 
@@ -1508,9 +1508,9 @@
  *
  * FIXME: rough guesswork, don't know what "Private" means
  */
-HMODULE32 WINAPI PrivateLoadLibrary(LPCSTR libname)
+HINSTANCE32 WINAPI PrivateLoadLibrary(LPCSTR libname)
 {
-        return LoadLibrary16(libname);
+        return (HINSTANCE32)LoadLibrary16(libname);
 }
 
 
@@ -1529,9 +1529,9 @@
  *
  * FIXME: rough guesswork, don't know what "Private" means
  */
-void WINAPI PrivateFreeLibrary(HMODULE32 handle)
+void WINAPI PrivateFreeLibrary(HINSTANCE32 handle)
 {
-	FreeLibrary16(handle);
+	FreeLibrary16((HINSTANCE16)handle);
 }
 
 
diff --git a/loader/ne_image.c b/loader/ne_image.c
index d42e5bc..98a8a9c 100644
--- a/loader/ne_image.c
+++ b/loader/ne_image.c
@@ -55,8 +55,8 @@
     if (!pSeg->filepos) return TRUE;  /* No file image, just return */
 	
     fd = MODULE_OpenFile( pModule->self );
-    dprintf_module( stddeb, "Loading segment %d, selector=%04x\n",
-                    segnum, pSeg->selector );
+    dprintf_module( stddeb, "Loading segment %d, selector=%04x, flags=%04x\n",
+                    segnum, pSeg->selector, pSeg->flags );
     lseek( fd, pSeg->filepos << pModule->alignment, SEEK_SET );
     if (pSeg->size) size = pSeg->size;
     else if (pSeg->minsize) size = pSeg->minsize;
@@ -631,7 +631,7 @@
     dprintf_dll( stddeb, "Calling LibMain, cs:ip=%04lx:%04x ds=%04lx di=%04x cx=%04x\n", 
                  CS_reg(&context), IP_reg(&context), DS_reg(&context),
                  DI_reg(&context), CX_reg(&context) );
-    Callbacks->CallRegisterProc( &context, 0 );
+    Callbacks->CallRegisterShortProc( &context, 0 );
     return TRUE;
 }
 
@@ -674,4 +674,5 @@
 /* It does nothing */
 void WINAPI PatchCodeHandle(HANDLE16 hSel)
 {
+	fprintf(stderr,"PatchCodeHandle(%04x),stub!\n",hSel);
 }
diff --git a/loader/pe_image.c b/loader/pe_image.c
index 1485cb6..6693fe2 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -167,7 +167,7 @@
 }
 
 void 
-fixup_imports (PDB32 *process,PE_MODREF *pem)
+fixup_imports (PDB32 *process,PE_MODREF *pem,HMODULE32 hModule)
 {
     IMAGE_IMPORT_DESCRIPTOR	*pe_imp;
     int	fixup_failed		= 0;
@@ -207,10 +207,10 @@
 	/* don't use MODULE_Load, Win32 creates new task differently */
 	res = PE_LoadLibraryEx32A( name, 0, 0 );
 	if (res <= (HMODULE32) 32) {
-	    char *p, buffer[256];
+	    char *p, buffer[1024];
 
 	    /* Try with prepending the path of the current module */
-	    GetModuleFileName32A( pem->module, buffer, sizeof (buffer));
+	    GetModuleFileName32A( hModule, buffer, sizeof (buffer));
 	    if (!(p = strrchr (buffer, '\\')))
 		p = buffer;
 	    strcpy (p + 1, name);
@@ -522,6 +522,11 @@
 	load_addr = (DWORD)VirtualAlloc( (void*)load_addr, vma_size,
                                          MEM_RESERVE | MEM_COMMIT,
                                          PAGE_EXECUTE_READWRITE );
+	if (load_addr == 0) {
+		load_addr = (DWORD)VirtualAlloc( NULL, vma_size,
+						 MEM_RESERVE | MEM_COMMIT,
+						 PAGE_EXECUTE_READWRITE );
+	}
 	pem->module = (HMODULE32)load_addr;
 
 	dprintf_win32(stddeb, "Load addr is really %lx, range %x\n",
@@ -647,7 +652,7 @@
 
 	if(pem->pe_reloc)	do_relocations(pem);
 	if(pem->pe_export)	dump_exports(pem->module);
-	if(pem->pe_import)	fixup_imports(process,pem);
+	if(pem->pe_import)	fixup_imports(process,pem,hModule);
   		
 	if (pem->pe_export)
 		modname = (char*)RVA(pem->pe_export->Name);
@@ -671,6 +676,7 @@
 /******************************************************************************
  * The PE Library Loader frontend. 
  * FIXME: handle the flags.
+ *        internal module handling should be made better here (and in builtin.c)
  */
 HMODULE32 PE_LoadLibraryEx32A (LPCSTR name, HFILE32 hFile, DWORD flags) {
 	OFSTRUCT	ofs;
@@ -690,6 +696,27 @@
 			pem = pem->next;
 		}
 		pModule = MODULE_GetPtr(hModule);
+		if (pModule->flags & NE_FFLAGS_BUILTIN) {
+			PDB32	*process = (PDB32*)GetCurrentProcessId();
+			IMAGE_DOS_HEADER	*dh;
+			IMAGE_NT_HEADERS	*nh;
+			IMAGE_SECTION_HEADER	*sh;
+
+			/* we only come here if we already have 'loaded' the
+			 * internal dll but in another process. Just create
+			 * a PE_MODREF and return.
+			 */
+			pem = (PE_MODREF*)HeapAlloc(GetProcessHeap(),
+				HEAP_ZERO_MEMORY,sizeof(*pem));
+			pem->module 	     = hModule;
+			dh = (IMAGE_DOS_HEADER*)pem->module;
+			nh = (IMAGE_NT_HEADERS*)(dh+1);
+			sh = (IMAGE_SECTION_HEADER*)(nh+1);
+			pem->pe_export	     = (IMAGE_EXPORT_DIRECTORY*)(sh+2);
+			pem->next	     = process->modref_list;
+			process->modref_list = pem;
+			return hModule;
+		}
 	} else {
 
 		/* try to load builtin, enabled modules first */
diff --git a/loader/pe_resource.c b/loader/pe_resource.c
index 4ba09dd..0139633 100644
--- a/loader/pe_resource.c
+++ b/loader/pe_resource.c
@@ -53,7 +53,8 @@
  *
  */
 LPIMAGE_RESOURCE_DIRECTORY GetResDirEntryW(LPIMAGE_RESOURCE_DIRECTORY resdirptr,
-					   LPCWSTR name,DWORD root)
+					   LPCWSTR name,DWORD root,
+					   BOOL32 allowdefault)
 {
     int entrynum;
     LPIMAGE_RESOURCE_DIRECTORY_ENTRY entryTable;
@@ -64,7 +65,7 @@
 		char	buf[10];
 
 		lstrcpynWtoA(buf,name+1,10);
-		return GetResDirEntryW(resdirptr,(LPCWSTR)atoi(buf),root);
+		return GetResDirEntryW(resdirptr,(LPCWSTR)atoi(buf),root,allowdefault);
 	}
 	entryTable = (LPIMAGE_RESOURCE_DIRECTORY_ENTRY) (
 			(BYTE *) resdirptr + 
@@ -94,7 +95,7 @@
 			root +
 			entryTable[entrynum].u2.s.OffsetToDirectory);
 	/* just use first entry if no default can be found */
-	if (!name && resdirptr->NumberOfIdEntries)
+	if (allowdefault && !name && resdirptr->NumberOfIdEntries)
 		return (LPIMAGE_RESOURCE_DIRECTORY) (
 			root +
 			entryTable[0].u2.s.OffsetToDirectory);
@@ -118,14 +119,14 @@
 
     resdirptr = pem->pe_resource;
     root = (DWORD) resdirptr;
-    if ((resdirptr = GetResDirEntryW(resdirptr, type, root)) == NULL)
+    if ((resdirptr = GetResDirEntryW(resdirptr, type, root, FALSE)) == NULL)
 	return 0;
-    if ((resdirptr = GetResDirEntryW(resdirptr, name, root)) == NULL)
+    if ((resdirptr = GetResDirEntryW(resdirptr, name, root, FALSE)) == NULL)
 	return 0;
-    result = (HANDLE32)GetResDirEntryW(resdirptr, (LPCWSTR)(UINT32)lang, root);
+    result = (HANDLE32)GetResDirEntryW(resdirptr, (LPCWSTR)(UINT32)lang, root, FALSE);
 	/* Try LANG_NEUTRAL, too */
     if(!result)
-        return (HANDLE32)GetResDirEntryW(resdirptr, (LPCWSTR)0, root);
+        return (HANDLE32)GetResDirEntryW(resdirptr, (LPCWSTR)0, root, TRUE);
     return result;
 }
 
@@ -243,7 +244,7 @@
 	typeW = HEAP_strdupAtoW(heap,0,type);
     else
 	typeW = (LPWSTR)type;
-    resdir = GetResDirEntryW(resdir,typeW,(DWORD)pem->pe_resource);
+    resdir = GetResDirEntryW(resdir,typeW,(DWORD)pem->pe_resource,FALSE);
     if (HIWORD(typeW))
     	HeapFree(heap,0,typeW);
     if (!resdir)
@@ -282,7 +283,7 @@
     	return FALSE;
 
     resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
-    resdir = GetResDirEntryW(resdir,type,(DWORD)pem->pe_resource);
+    resdir = GetResDirEntryW(resdir,type,(DWORD)pem->pe_resource,FALSE);
     if (!resdir)
     	return FALSE;
     et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
@@ -324,7 +325,7 @@
 	nameW = HEAP_strdupAtoW(heap,0,name);
     else
     	nameW = (LPWSTR)name;
-    resdir = GetResDirEntryW(resdir,nameW,(DWORD)pem->pe_resource);
+    resdir = GetResDirEntryW(resdir,nameW,(DWORD)pem->pe_resource,FALSE);
     if (HIWORD(nameW))
     	HeapFree(heap,0,nameW);
     if (!resdir)
@@ -333,7 +334,7 @@
 	typeW = HEAP_strdupAtoW(heap,0,type);
     else
 	typeW = (LPWSTR)type;
-    resdir = GetResDirEntryW(resdir,typeW,(DWORD)pem->pe_resource);
+    resdir = GetResDirEntryW(resdir,typeW,(DWORD)pem->pe_resource,FALSE);
     if (HIWORD(typeW))
     	HeapFree(heap,0,typeW);
     if (!resdir)
@@ -367,10 +368,10 @@
     	return FALSE;
 
     resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
-    resdir = GetResDirEntryW(resdir,name,(DWORD)pem->pe_resource);
+    resdir = GetResDirEntryW(resdir,name,(DWORD)pem->pe_resource,FALSE);
     if (!resdir)
     	return FALSE;
-    resdir = GetResDirEntryW(resdir,type,(DWORD)pem->pe_resource);
+    resdir = GetResDirEntryW(resdir,type,(DWORD)pem->pe_resource,FALSE);
     if (!resdir)
     	return FALSE;
     et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
diff --git a/loader/task.c b/loader/task.c
index cf981d4..08881d6 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -386,7 +386,7 @@
                       SELECTOROF(IF1632_Saved16_ss_sp),
                       OFFSETOF(IF1632_Saved16_ss_sp) );
 
-        Callbacks->CallRegisterProc( &context, 0 );
+        Callbacks->CallRegisterShortProc( &context, 0 );
         /* This should never return */
         fprintf( stderr, "TASK_CallToStart: Main program returned!\n" );
         TASK_KillCurrentTask( 1 );
@@ -629,8 +629,6 @@
  */
 void TASK_KillCurrentTask( INT16 exitCode )
 {
-    extern void USER_ExitWindows(void);
-
     TDB* pTask = (TDB*) GlobalLock16( hCurrentTask );
     if (!pTask) USER_ExitWindows();  /* No current task yet */
 
diff --git a/memory/heap.c b/memory/heap.c
index 0cf20f5..1d4aee2 100644
--- a/memory/heap.c
+++ b/memory/heap.c
@@ -885,7 +885,7 @@
         dprintf_heap( stddeb, "HeapAlloc(%08x,%08lx,%08lx): returning NULL\n",
                   heap, flags, size  );
         if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap );
-        SetLastError( ERROR_OUTOFMEMORY );
+        SetLastError( ERROR_COMMITMENT_LIMIT );
         return NULL;
     }
 
@@ -911,7 +911,6 @@
     else if (debugging_heap) memset( pInUse + 1, ARENA_INUSE_FILLER, size );
 
     if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap );
-    SetLastError( 0 );
 
     dprintf_heap( stddeb, "HeapAlloc(%08x,%08lx,%08lx): returning %08lx\n",
                   heap, flags, size, (DWORD)(pInUse + 1) );
diff --git a/memory/selector.c b/memory/selector.c
index 5c47775..410c0d5 100644
--- a/memory/selector.c
+++ b/memory/selector.c
@@ -22,7 +22,8 @@
  */
 WORD WINAPI AllocSelectorArray( WORD count )
 {
-    WORD i, size = 0;
+    WORD i, sel, size = 0;
+    ldt_entry entry;
 
     if (!count) return 0;
     for (i = FIRST_LDT_ENTRY_TO_ALLOC; i < LDT_SIZE; i++)
@@ -31,9 +32,22 @@
         else if (++size >= count) break;
     }
     if (i == LDT_SIZE) return 0;
-    /* Mark selector as allocated */
-    while (size--) ldt_flags_copy[i--] |= LDT_FLAGS_ALLOCATED;
-    return ENTRY_TO_SELECTOR( i + 1 );
+    sel = i - size + 1;
+
+    entry.base           = 0;
+    entry.type           = SEGMENT_DATA;
+    entry.seg_32bit      = FALSE;
+    entry.read_only      = FALSE;
+    entry.limit_in_pages = FALSE;
+    entry.limit          = 1;  /* avoid 0 base and limit */
+
+    for (i = 0; i < count; i++)
+    {
+        /* Mark selector as allocated */
+        ldt_flags_copy[sel + i] |= LDT_FLAGS_ALLOCATED;
+        LDT_SetEntry( sel + i, &entry );
+    }
+    return ENTRY_TO_SELECTOR( sel );
 }
 
 
@@ -652,3 +666,24 @@
     fprintf(stdnimp,"WOWGetVDMPointerUnfix(%08lx), STUB\n",vp);
     /* FIXME: unfix heapsegment */
 }
+
+/***********************************************************************
+ *           UTSelectorOffsetToLinear       (WIN32S16.48)
+ *
+ * rough guesswork, but seems to work (I had no "reasonable" docu)
+ */
+LPVOID WINAPI UTSelectorOffsetToLinear(SEGPTR sptr)
+{
+        return PTR_SEG_TO_LIN(sptr);
+}
+
+/***********************************************************************
+ *           UTLinearToSelectorOffset       (WIN32S16.49)
+ *
+ * FIXME: I don't know if that's the right way to do linear -> segmented
+ */
+SEGPTR WINAPI UTLinearToSelectorOffset(LPVOID lptr)
+{
+    fprintf( stderr, "UTLinearToSelectorOffset(%p): stub\n", lptr );
+    return (SEGPTR)lptr;
+}
diff --git a/memory/virtual.c b/memory/virtual.c
index 7ae69be..82d4845 100644
--- a/memory/virtual.c
+++ b/memory/virtual.c
@@ -21,6 +21,10 @@
 #include "stddebug.h"
 #include "debug.h"
 
+#ifndef MS_SYNC
+#define MS_SYNC 0
+#endif
+
 /* File mapping */
 typedef struct
 {
@@ -190,6 +194,8 @@
 
     /* Create the view structure */
 
+    assert( !(base & page_mask) );
+    assert( !(size & page_mask) );
     size >>= page_shift;
     if (!(view = (FILE_VIEW *)malloc( sizeof(*view) + size - 1 ))) return NULL;
     view->base    = base;
@@ -490,6 +496,13 @@
             if (view_size > size)
                 FILE_munmap( (void *)(ptr + size), 0, view_size - size );
         }
+        else if (ptr != base)
+        {
+            /* We couldn't get the address we wanted */
+            FILE_munmap( (void *)ptr, 0, view_size );
+	    SetLastError( ERROR_INVALID_ADDRESS );
+	    return NULL;
+        }
         if (!(view = VIRTUAL_CreateView( ptr, size, 0, 0, vprot, NULL )))
         {
             FILE_munmap( (void *)ptr, 0, size );
@@ -1097,7 +1110,7 @@
         return FALSE;
     }
     if (!cbFlush) cbFlush = view->size;
-    if (!msync( addr, cbFlush, MS_SYNC )) return TRUE;
+    if (!msync( (void *)addr, cbFlush, MS_SYNC )) return TRUE;
     SetLastError( ERROR_INVALID_PARAMETER );
     return FALSE;
 
diff --git a/misc/Makefile.in b/misc/Makefile.in
index 4bbbe90..f9722db 100644
--- a/misc/Makefile.in
+++ b/misc/Makefile.in
@@ -37,6 +37,8 @@
 	w32scomb.c \
 	w32skrnl.c \
 	w32sys.c \
+	win32s16.c \
+	windebug.c \
 	winsock.c \
 	winsock_dns.c \
 	wsprintf.c \
diff --git a/misc/callback.c b/misc/callback.c
index c379a90..34e5f02 100644
--- a/misc/callback.c
+++ b/misc/callback.c
@@ -7,8 +7,8 @@
 #include <assert.h>
 #include <stdio.h>
 #include "callback.h"
+#include "task.h"
 
-extern void TASK_Reschedule(void);  /* loader/task.c */
 
 /**********************************************************************
  *	     CALLBACK_CallWndProc
@@ -24,10 +24,11 @@
 /**********************************************************************
  *	     CALLBACK_CallRegisterProc
  */
-static VOID WINAPI CALLBACK_CallRegisterProc( CONTEXT *context, INT32 offset)
+static LONG WINAPI CALLBACK_CallRegisterProc( CONTEXT *context, INT32 offset)
 {
     fprintf( stderr, "Cannot call a register proc in Winelib\n" );
     assert( FALSE );
+    return 0;
 }
 
 
@@ -123,6 +124,15 @@
     return proc( ptr );
 }
 
+
+/**********************************************************************
+ *	     CALLBACK_CallWOWCallbackProc
+ */
+static DWORD WINAPI CALLBACK_CallWOWCallbackProc( FARPROC16 proc, DWORD dw )
+{
+    return proc( dw );
+}
+
 /**********************************************************************
  *	     CALLBACK_WinelibTable
  *
@@ -130,7 +140,8 @@
  */
 static const CALLBACKS_TABLE CALLBACK_WinelibTable =
 {
-    CALLBACK_CallRegisterProc,     /* CallRegisterProc */
+    CALLBACK_CallRegisterProc,     /* CallRegisterShortProc */
+    CALLBACK_CallRegisterProc,     /* CallRegisterLongProc */
     TASK_Reschedule,               /* CallTaskRescheduleProc */
     NULL,                          /* CallFrom16WndProc */
     CALLBACK_CallWndProc,          /* CallWndProc */
@@ -142,6 +153,7 @@
     CALLBACK_CallBootAppProc,      /* CallBootAppProc */
     CALLBACK_CallLoadAppSegProc,   /* CallLoadAppSegProc */
     CALLBACK_CallSystemTimerProc,  /* CallSystemTimerProc */
+    CALLBACK_CallWOWCallbackProc,  /* CallWOWCallbackProc */
     CALLBACK_CallASPIPostProc,     /* CallASPIPostProc */
     /* The graphics driver callbacks are never used in Winelib */
     NULL,                          /* CallDrvControlProc */
diff --git a/misc/commdlg.c b/misc/commdlg.c
index 83fa922..d422c87 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -538,10 +538,14 @@
     }
   else
     *tmpstr = 0;
-  if (!FILEDLG_ScanDir(hWnd, tmpstr))
-    fprintf(stderr, "FileDlg: couldn't read initial directory %s!\n", tmpstr);
-  /* select current drive in combo 2 */
-  n = DRIVE_GetCurrentDrive();
+  if (!FILEDLG_ScanDir(hWnd, tmpstr)) {
+    *tmpstr = 0;
+    if (!FILEDLG_ScanDir(hWnd, tmpstr))
+      fprintf(stderr, "FileDlg: couldn't read initial directory %s!\n",tmpstr);
+  }
+  /* select current drive in combo 2, omit missing drives */
+  for(i=0, n=-1; i<=DRIVE_GetCurrentDrive(); i++)
+    if (DRIVE_IsValid(i))                  n++;
   SendDlgItemMessage16(hWnd, cmb2, CB_SETCURSEL16, n, 0);
   if (!(lpofn->Flags & OFN_SHOWHELP))
     ShowWindow32(GetDlgItem32(hWnd, pshHelp), SW_HIDE);
diff --git a/misc/cpu.c b/misc/cpu.c
index 014c546..ffbbbbf 100644
--- a/misc/cpu.c
+++ b/misc/cpu.c
@@ -1,7 +1,7 @@
 /*
  * What processor?
  *
- * Copyright 1995 Morten Welinder
+ * Copyright 1995,1997 Morten Welinder
  * Copyright 1997 Marcus Meissner
  */
 
@@ -9,6 +9,7 @@
 #include <ctype.h>
 #include <string.h>
 #include "windows.h"
+#include "winnt.h"
 
 VOID WINAPI GetSystemInfo(LPSYSTEM_INFO si)
 {
@@ -99,3 +100,25 @@
 	return;
 #endif  /* linux */
 }
+
+
+/* IsProcessorFeaturePresent [KERNEL32.880] */
+BOOL32 WINAPI IsProcessorFeaturePresent (DWORD feature)
+{
+  SYSTEM_INFO si;
+  GetSystemInfo (&si);
+  /* FIXME: these are relatively stupid approximations.  */
+  switch (feature)
+    {
+    case PF_FLOATING_POINT_PRECISION_ERRATA:
+      return si.wProcessorLevel == 5;
+    case PF_FLOATING_POINT_EMULATED:
+      return FALSE;
+    case PF_COMPARE_EXCHANGE_DOUBLE:
+      return si.wProcessorLevel >= 5;
+    case PF_MMX_INSTRUCTIONS_AVAILABLE:
+      return FALSE;
+    default:
+      return FALSE;
+    }
+}
diff --git a/misc/crtdll.c b/misc/crtdll.c
index 7ffa01a..3a12c9b 100644
--- a/misc/crtdll.c
+++ b/misc/crtdll.c
@@ -30,6 +30,7 @@
 #include <ctype.h>
 #include <math.h>
 #include <fcntl.h>
+#include <setjmp.h>
 #include "win.h"
 #include "windows.h"
 #include "stddebug.h"
@@ -438,7 +439,7 @@
 	if (fd == -1)
 	  len = -1;
 	else if (fd<=2)
-	  len = (UINT32)write(fd,buf,(LONG)len);
+	  len = (UINT32)write(fd,buf,(LONG)count);
 	else
 	  len = _lwrite32(fd,buf,count);
 	dprintf_crtdll(stddeb,"CRTDLL_write %d/%d byte to dfh %d from %p,\n",
@@ -456,6 +457,8 @@
  *  FIXME           _exit           (CRTDLL.87)
  *  FIXME           exit            (CRTDLL.359)
  *
+ * atexit-processing comes to mind -- MW.
+ *
  */
 void __cdecl CRTDLL__cexit(INT32 ret)
 {
@@ -502,10 +505,13 @@
  */
 LPSTR __cdecl CRTDLL_gets(LPSTR buf)
 {
+   char * ret;
   /* BAD, for the whole WINE process blocks... just done this way to test
    * windows95's ftp.exe.
    */
-    return gets(buf);
+   ret = gets(buf);
+   dprintf_crtdll(stddeb,"CRTDLL_gets got %s\n",ret);
+   return ret;
 }
 
 
@@ -762,12 +768,12 @@
   bp = buffer + strlen(buffer);
   i = strlen(buffer) + strlen(x) +2;
 
-  /* Calculate needed buffer size tp prevent overflow*/
+  /* Calculate needed buffer size to prevent overflow.  */
   while (*y) {
     if (*y =='\\') i++;
     y++;
   }
-  /* if buffer to short, exit */
+  /* If buffer too short, exit.  */
   if (i > SYSBUF_LENGTH) {
     dprintf_crtdll(stddeb,"_system buffer to small\n");
     return 127;
@@ -780,7 +786,7 @@
     bp++; y++;
     if (*(y-1) =='\\') *bp++ = '\\';
   }
-  /* remove spaces from end of string */
+  /* Remove spaces from end of string.  */
   while (*(y-1) == ' ') {
     bp--;y--;
   }
@@ -836,6 +842,16 @@
 
 
 /*********************************************************************
+ *                  longjmp        (CRTDLL.426)
+ */
+VOID __cdecl CRTDLL_longjmp(jmp_buf env, int val)
+{
+    dprintf_crtdll(stdnimp,"CRTDLL_longjmp semistup, expect crash\n");
+    dprintf_crtdll(stddeb, "CRTDLL_longjmp semistup, expect crash\n");
+    return longjmp(env, val);
+}
+
+/*********************************************************************
  *                  malloc        (CRTDLL.427)
  */
 VOID* __cdecl CRTDLL_malloc(DWORD size)
@@ -1088,14 +1104,14 @@
 /*********************************************************************
  *                  wcschr           (CRTDLL.504)
  */
-LPWSTR __cdecl CRTDLL_wcschr(LPWSTR str,WCHAR xchar)
+LPWSTR __cdecl CRTDLL_wcschr(LPCWSTR str,WCHAR xchar)
 {
-	LPWSTR	s;
+	LPCWSTR	s;
 
 	s=str;
 	do {
 		if (*s==xchar)
-			return s;
+			return (LPWSTR)s;
 	} while (*s++);
 	return NULL;
 }
@@ -1345,7 +1361,7 @@
 {
 
 /* Slightly modified lstrcpynAtoW functions from memory/strings.c
- *  We need the numberr of characters transfered 
+ *  We need the number of characters transfered 
  *  FIXME: No multibyte support yet
  */
 
@@ -1522,9 +1538,8 @@
 
   len = size;
   if (!buf) {
-    len = size;
     if (size < 0) /* allocate as big as nescessary */
-      len =GetCurrentDirectory32A(1,test);
+      len =GetCurrentDirectory32A(1,test) + 1;
     if(!(buf = CRTDLL_malloc(len)))
     {
 	/* set error to OutOfRange */
diff --git a/misc/lstr.c b/misc/lstr.c
index 2d7db18..ce80476 100644
--- a/misc/lstr.c
+++ b/misc/lstr.c
@@ -10,40 +10,50 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
+#include <wctype.h>
 
 #include "windows.h"
 #include "winnt.h"	/* HEAP_ macros */
+#include "task.h"
 #include "heap.h"
 #include "ldt.h"
+#include "stackframe.h"
 #include "module.h"
 #include "stddebug.h"
 #include "debug.h"
 
-#define ToUpper(c)	toupper(c)
-#define ToLower(c)	tolower(c)
-
 
 /* Funny to divide them between user and kernel. */
 
-/* IsCharAlpha USER 433 */
+/* be careful: always use functions from wctype.h if character > 255 */
+
+/***********************************************************************
+ *		IsCharAlpha (USER.433)
+ */
 BOOL16 WINAPI IsCharAlpha16(CHAR ch)
 {
   return isalpha(ch);   /* This is probably not right for NLS */
 }
 
-/* IsCharAlphanumeric USER 434 */
+/***********************************************************************
+ *		IsCharAlphanumeric (USER.434)
+ */
 BOOL16 WINAPI IsCharAlphaNumeric16(CHAR ch)
 {
     return isalnum(ch);
 }
 
-/* IsCharUpper USER 435 */
+/***********************************************************************
+ *		IsCharUpper (USER.435)
+ */
 BOOL16 WINAPI IsCharUpper16(CHAR ch)
 {
   return isupper(ch);
 }
 
-/* IsCharLower USER 436 */
+/***********************************************************************
+ *		IsCharLower (USER.436)
+ */
 BOOL16 WINAPI IsCharLower16(CHAR ch)
 {
   return islower(ch);
@@ -64,7 +74,7 @@
         for (s = PTR_SEG_TO_LIN(strOrChar); *s; s++) *s = toupper(*s);
         return strOrChar;
     }
-    else return (SEGPTR)ToUpper( (int)strOrChar );
+    else return toupper((char)strOrChar);
 }
 
 
@@ -93,7 +103,7 @@
         for (s = PTR_SEG_TO_LIN( strOrChar ); *s; s++) *s = tolower( *s );
         return strOrChar;
     }
-    else return (SEGPTR)tolower( (int)strOrChar );
+    else return tolower((char)strOrChar);
 }
 
 
@@ -274,7 +284,7 @@
         }
         return x;
     }
-    else return (LPSTR)tolower(LOWORD(x));
+    else return (LPSTR)tolower((char)(int)x);
 }
 
 /***********************************************************************
@@ -285,6 +295,7 @@
 {
     DWORD done=0;
 
+    if (!x) return 0; /* YES */
     while (*x && (buflen--))
     {
         *x=tolower(*x);
@@ -302,9 +313,10 @@
 {
     DWORD done=0;
 
+    if (!x) return 0; /* YES */
     while (*x && (buflen--))
     {
-        *x=tolower(*x);
+        *x=towlower(*x);
         x++;
         done++;
     }
@@ -322,12 +334,12 @@
         LPWSTR s = x;
         while (*s)
         {
-            *s=tolower(*s);
+            *s=towlower(*s);
             s++;
         }
         return x;
     }
-    else return (LPWSTR)tolower(LOWORD(x));
+    else return (LPWSTR)towlower(LOWORD(x));
 }
 
 /***********************************************************************
@@ -346,7 +358,7 @@
         }
         return x;
     }
-    else return (LPSTR)toupper(LOWORD(x));
+    return (LPSTR)toupper((char)(int)x);
 }
 
 /***********************************************************************
@@ -357,6 +369,7 @@
 {
     DWORD done=0;
 
+    if (!x) return 0; /* YES */
     while (*x && (buflen--))
     {
         *x=toupper(*x);
@@ -374,9 +387,10 @@
 {
     DWORD done=0;
 
+    if (!x) return 0; /* YES */
     while (*x && (buflen--))
     {
-        *x=toupper(*x);
+        *x=towupper(*x);
         x++;
         done++;
     }
@@ -394,12 +408,12 @@
         LPWSTR s = x;
         while (*s)
         {
-            *s=toupper(*s);
+            *s=towupper(*s);
             s++;
         }
         return x;
     }
-    else return (LPWSTR)toupper(LOWORD(x));
+    else return (LPWSTR)towupper(LOWORD(x));
 }
 
 /***********************************************************************
@@ -426,7 +440,7 @@
  */
 BOOL32 WINAPI IsCharAlphaNumeric32W(WCHAR x)
 {
-    return isalnum(x);
+    return iswalnum(x);
 }
 
 /***********************************************************************
@@ -435,7 +449,7 @@
  */
 BOOL32 WINAPI IsCharAlpha32W(WCHAR x)
 {
-    return isalpha(x);
+    return iswalpha(x);
 }
 
 /***********************************************************************
@@ -453,7 +467,7 @@
  */
 BOOL32 WINAPI IsCharLower32W(WCHAR x)
 {
-    return islower(x);
+    return iswlower(x);
 }
 
 /***********************************************************************
@@ -471,7 +485,7 @@
  */
 BOOL32 WINAPI IsCharUpper32W(WCHAR x)
 {
-    return isupper(x);
+    return iswupper(x);
 }
 
 /***********************************************************************
diff --git a/misc/main.c b/misc/main.c
index 02984ae..bda1779 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -18,12 +18,12 @@
 #include <X11/Xutil.h>
 #include <X11/Xlocale.h>
 #include <X11/cursorfont.h>
+#include "winsock.h"
 #include "heap.h"
 #include "message.h"
 #include "msdos.h"
 #include "windows.h"
 #include "color.h"
-#include "winsock.h"
 #include "options.h"
 #include "desktop.h"
 #include "process.h"
diff --git a/misc/network.c b/misc/network.c
index 12ed9fa..58b8cbd 100644
--- a/misc/network.c
+++ b/misc/network.c
@@ -156,7 +156,7 @@
 /**************************************************************************
  *				WNetGetConnection	[USER.512]
  */
-int WINAPI WNetGetConnection16(LPSTR lpLocalName, 
+int WINAPI WNetGetConnection16(LPCSTR lpLocalName, 
                                LPSTR lpRemoteName, UINT16 *cbRemoteName)
 {
     const char *path;
diff --git a/misc/port.c b/misc/port.c
index b16ff0f..f98a951 100644
--- a/misc/port.c
+++ b/misc/port.c
@@ -49,3 +49,11 @@
     return dest;
 }
 #endif  /* HAVE_MEMMOVE */
+
+#ifndef HAVE_STRERROR
+const char *strerror( int err )
+{
+    /* Let's hope we have sys_errlist then */
+    return sys_errlist[err];
+}
+#endif  /* HAVE_STRERROR */
diff --git a/misc/printdrv.c b/misc/printdrv.c
index 94ca696..3c73581 100644
--- a/misc/printdrv.c
+++ b/misc/printdrv.c
@@ -89,6 +89,14 @@
     return 1;
 }
 
+BOOL32 WINAPI OpenPrinter32A(LPSTR lpPrinterName,HANDLE32 *phPrinter,
+			     LPPRINTER_DEFAULTS32A pDefault)
+{
+    fprintf(stderr,"OpenPrinter32A(%s,%p,%p), stub\n",
+	    lpPrinterName, phPrinter, pDefault);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
 BOOL32  WINAPI EnumPrinters32A(DWORD dwType, LPSTR lpszName,
 			       DWORD dwLevel, LPBYTE lpbPrinters,
 			       DWORD cbBuf, LPDWORD lpdwNeeded,
diff --git a/misc/shell.c b/misc/shell.c
index 66a94ce..d0bd6ba 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -8,6 +8,7 @@
 #include <unistd.h>
 #include <ctype.h>
 #include "windows.h"
+#include "winerror.h"
 #include "file.h"
 #include "shell.h"
 #include "heap.h"
@@ -125,6 +126,7 @@
     "William Smith",
     "Dominik Strasser",
     "Vadim Strizhevsky",
+    "Bertho Stultiens",
     "Erik Svendsen",
     "Tristan Tarrant",
     "Andrew Taylor",
@@ -181,9 +183,6 @@
 
 #pragma pack(4)
 
-extern HICON16   WINAPI LoadIconHandler( HGLOBAL16 hResource, BOOL16 bNew );
-extern WORD 	 WINAPI GetIconID( HGLOBAL16 hResource, DWORD resType );
-
 static const char*	lpstrMsgWndCreated = "OTHERWINDOWCREATED";
 static const char*	lpstrMsgWndDestroyed = "OTHERWINDOWDESTROYED";
 static const char*	lpstrMsgShellActivate = "ACTIVATESHELLWINDOW";
@@ -754,6 +753,29 @@
     return ret;
 }
 
+/*************************************************************************
+ *				Shell_NotifyIcon	[SHELL32.249]
+ *	FIXME
+ *	This function is supposed to deal with the systray.
+ *	Any ideas on how this is to be implimented?
+ */
+BOOL32 WINAPI Shell_NotifyIcon(	DWORD dwMessage,
+				PNOTIFYICONDATA pnid )
+{
+    return FALSE;
+}
+
+/*************************************************************************
+ *				Shell_NotifyIcon	[SHELL32.240]
+ *	FIXME
+ *	This function is supposed to deal with the systray.
+ *	Any ideas on how this is to be implimented?
+ */
+BOOL32 WINAPI Shell_NotifyIconA(DWORD dwMessage,
+				PNOTIFYICONDATA pnid )
+{
+    return FALSE;
+}
 
 /*************************************************************************
  *				SHELL_GetResourceTable
@@ -1048,7 +1070,7 @@
 		_lclose32( hFile);
 		return 0;
 	}
-	icongroupresdir = GetResDirEntryW(rootresdir,(LPWSTR)RT_GROUP_ICON,(DWORD)rootresdir);
+	icongroupresdir = GetResDirEntryW(rootresdir,(LPWSTR)RT_GROUP_ICON,(DWORD)rootresdir,FALSE);
 	if (!icongroupresdir) {
 		fprintf(stderr,"InternalExtractIcon: No Icongroupresourcedirectory!\n");
 		UnmapViewOfFile(peimage);
@@ -1094,7 +1116,7 @@
 		/* go down this resource entry, name */
 		resdir = (LPIMAGE_RESOURCE_DIRECTORY)((DWORD)rootresdir+(xresent->u2.s.OffsetToDirectory));
 		/* default language (0) */
-		resdir = GetResDirEntryW(resdir,(LPWSTR)0,(DWORD)rootresdir);
+		resdir = GetResDirEntryW(resdir,(LPWSTR)0,(DWORD)rootresdir,TRUE);
 		igdataent = (LPIMAGE_RESOURCE_DATA_ENTRY)resdir;
 
 		/* lookup address in mapped image for virtual address */
@@ -1116,13 +1138,9 @@
 		/* found */
 		cid = (CURSORICONDIR*)igdata;
 		cids[i] = cid;
-		fprintf(stderr,"cursoricondir %d: idType %d, idCount %d\n",
-			i,cid->idType,cid->idCount
-		);
 		RetPtr[i] = LookupIconIdFromDirectoryEx32(igdata,TRUE,SYSMETRICS_CXICON,SYSMETRICS_CYICON,0);
-		fprintf(stderr,"-> best match is %08x\n",RetPtr[i]);
 	}
-	iconresdir=GetResDirEntryW(rootresdir,(LPWSTR)RT_ICON,(DWORD)rootresdir);
+	iconresdir=GetResDirEntryW(rootresdir,(LPWSTR)RT_ICON,(DWORD)rootresdir,FALSE);
 	if (!iconresdir) {
 	    fprintf(stderr,"InternalExtractIcon: No Iconresourcedirectory!\n");
 	    UnmapViewOfFile(peimage);
@@ -1133,8 +1151,8 @@
 	for (i=0;i<n;i++) {
 	    LPIMAGE_RESOURCE_DIRECTORY	xresdir;
 
-	    xresdir = GetResDirEntryW(iconresdir,(LPWSTR)RetPtr[i],(DWORD)rootresdir);
-	    xresdir = GetResDirEntryW(xresdir,(LPWSTR)0,(DWORD)rootresdir);
+	    xresdir = GetResDirEntryW(iconresdir,(LPWSTR)RetPtr[i],(DWORD)rootresdir,FALSE);
+	    xresdir = GetResDirEntryW(xresdir,(LPWSTR)0,(DWORD)rootresdir,TRUE);
 
 	    idataent = (LPIMAGE_RESOURCE_DATA_ENTRY)xresdir;
 
@@ -1214,6 +1232,12 @@
  * Return icon for given file (either from file itself or from associated
  * executable) and patch parameters if needed.
  */
+HICON32 WINAPI ExtractAssociatedIcon32A(HINSTANCE32 hInst,LPSTR lpIconPath,
+	LPWORD lpiIcon)
+{
+	return ExtractAssociatedIcon16(hInst,lpIconPath,lpiIcon);
+}
+
 HICON16 WINAPI ExtractAssociatedIcon16(HINSTANCE16 hInst,LPSTR lpIconPath,
 	LPWORD lpiIcon)
 {
@@ -1541,26 +1565,101 @@
  *
  * http://premium.microsoft.com/msdn/library/sdkdoc/api2_48fo.htm
  */
-
-/* This is the wrong place, but where is the right one?  */
-#if 0
-#define E_OUTOFMEMORY 0x8007000EL
-
-HRESULT32 WINAPI SHELL32_DllGetClassObject (REFCLSID32 clsid,
-					    REFIID32 riid,
-					    LPVOID *ppv)
+DWORD WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid,REFIID iid,LPVOID *ppv)
 {
-  HRESULT32 hres = E_OUTOFMEMORY; 
-  *ppv = NULL; 
+    char	xclsid[50],xiid[50];
+    HRESULT	hres = E_OUTOFMEMORY;
 
-  fprintf (stdnimp, "SHELL32_DllGetClassObject (0x%x,0x%x,%p) -- STUB\n",
-	   clsid, riid, ppv);
 
-  return hres;
-}
-#endif
+    StringFromCLSID((LPCLSID)rclsid,xclsid);
+    StringFromCLSID((LPCLSID)iid,xiid);
+    fprintf(stderr,"SHELL32_DllGetClassObject(%s,%s,%p)\n",xclsid,xiid,ppv);
 
-DWORD WINAPI SHGetDesktopFolder(LPSHELLFOLDER *shellfolder) {
-	*shellfolder = NULL;
+    *ppv = NULL;
+/* SDK example code looks like this:
+ *
+    HRESULT	hres = E_OUTOFMEMORY;
+
+    *ppv = NULL;
+    CClassFactory *pClassFactory = new CClassFactory(rclsid);
+    
+    if (pClassFactory) {
+    	hRes = pClassFactory->QueryInterface(riid,ppv);
+	pClassFactory->Release();
+    }
+    return hRes;
+ *
+ * The magic of the whole stuff is still unclear to me, so just hack together 
+ * something.
+ */
+  
+    if (!memcmp(rclsid,&CLSID_ShellDesktop,sizeof(CLSID_ShellDesktop))) {
+    	fprintf(stderr,"	requested CLSID_ShellDesktop, creating it.\n");
+	*ppv = IShellFolder_Constructor();
+	/* FIXME: Initialize this folder to be the shell desktop folder */
 	return 0;
+    }
+
+    fprintf (stdnimp, "	-> clsid not found. returning E_OUTOFMEMORY.\n");
+    return hres;
 }
+
+/*************************************************************************
+ *			 SHGetDesktopFolder		[SHELL32.216]
+ * returns the interface to the shell desktop folder.
+ *
+ * [SDK header win95/shlobj.h: This is equivalent to call CoCreateInstance with
+ *  CLSID_ShellDesktop.
+ *
+ *  CoCreateInstance(CLSID_Desktop, NULL,
+ *                   CLSCTX_INPROC, IID_IShellFolder, &pshf);
+ * ]
+ * So what we are doing is currently wrong....
+ */
+DWORD WINAPI SHGetDesktopFolder(LPSHELLFOLDER *shellfolder) {
+	*shellfolder = IShellFolder_Constructor();
+	return NOERROR;
+}
+
+/*************************************************************************
+ *			 SHGetMalloc			[SHELL32.220]
+ * returns the interface to shell malloc.
+ *
+ * [SDK header win95/shlobj.h:
+ * equivalent to:  #define SHGetMalloc(ppmem)   CoGetMalloc(MEMCTX_TASK, ppmem)
+ * ]
+ * What we are currently doing is not very wrong, since we always use the same
+ * heap (ProcessHeap).
+ */
+DWORD WINAPI SHGetMalloc(LPMALLOC *lpmal) {
+	fprintf(stderr,"SHGetMalloc()\n");
+	*lpmal = IMalloc_Constructor();
+	return NOERROR;
+}
+
+/*************************************************************************
+ *			 SHGetSpecialFolderLocation	[SHELL32.223]
+ * returns the PIDL of a special folder
+ *
+ * nFolder is a CSIDL_xxxxx.
+ */
+HRESULT WINAPI SHGetSpecialFolderLocation(HWND32 hwndOwner, INT32 nFolder, LPITEMIDLIST * ppidl) {
+	fprintf(stderr,"SHGetSpecialFolderLocation(%04x,%d,%p),stub!\n",
+		hwndOwner,nFolder,ppidl
+	);
+	*ppidl = (LPITEMIDLIST)HeapAlloc(GetProcessHeap(),0,2*sizeof(ITEMIDLIST));
+	/* FIXME: we return only the empty ITEMIDLIST currently. */
+	(*ppidl)->mkid.cb = 0;
+	return NOERROR;
+}
+
+/*************************************************************************
+ *			 SHGetPathFromIDList		[SHELL32.221]
+ * returns the path from a passed PIDL.
+ */
+BOOL32 WINAPI SHGetPathFromIDList(LPCITEMIDLIST pidl,LPSTR pszPath) {
+	fprintf(stderr,"SHGetPathFromIDList(%p,%p),stub!\n",pidl,pszPath);
+	lstrcpy32A(pszPath,"E:\\"); /* FIXME */
+	return NOERROR;
+}
+
diff --git a/misc/shellord.c b/misc/shellord.c
index f3a1191..3a1a6dc 100644
--- a/misc/shellord.c
+++ b/misc/shellord.c
@@ -32,6 +32,81 @@
 #include "winreg.h"
 
 /*************************************************************************
+ *	 		 SHELL32_2   			[SHELL32.2]
+ */
+DWORD WINAPI SHELL32_2(HWND32 hwnd,DWORD x2,DWORD x3,DWORD x4,DWORD x5,DWORD x6) {
+	fprintf(stderr,"SHELL32_2(0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",
+		hwnd,x2,x3,x4,x5,x6
+	);
+	return 0;
+}
+/*************************************************************************
+ *	 		 SHELL32_16   			[SHELL32.16]
+ * find_lastitem_in_itemidlist()
+ */
+LPSHITEMID WINAPI SHELL32_16(LPITEMIDLIST iil) {
+	LPSHITEMID	lastsii,sii;
+
+	if (!iil)
+		return NULL;
+	sii = &(iil->mkid);
+	lastsii = sii;
+	while (sii->cb) {
+		lastsii = sii;
+		sii = (LPSHITEMID)(((char*)sii)+sii->cb);
+	}
+	return lastsii;
+}
+/*************************************************************************
+ *	 		 SHELL32_29   			[SHELL32.29]
+ * is_rootdir(const char*path)
+ */
+BOOL32 WINAPI SHELL32_29(LPCSTR x) {
+	if (!lstrcmp32A(x+1,":\\"))		/* "X:\" */
+		return 1;
+	if (!lstrcmp32A(x,"\\"))		/* "\" */
+		return 1;
+	if (x[0]=='\\' && x[1]=='\\') {		/* UNC "\\<xx>\" */
+		int	foundbackslash = 0;
+		x=x+2;
+		while (*x) {
+			if (*x++=='\\')
+				foundbackslash++;
+		}
+		if (foundbackslash<=1)	/* max 1 \ more ... */
+			return 1;
+	}
+	return 0;
+}
+
+/*************************************************************************
+ *	 		 SHELL32_30   			[SHELL32.30]
+ * get_rootdir(char*path,int drive)
+ */
+DWORD WINAPI SHELL32_30(LPSTR root,BYTE drive) {
+	strcpy(root,"A:\\");
+	root[0]+=drive;
+	return root;
+}
+
+/*************************************************************************
+ *					SHELL32_31      [SHELL32.31]
+ * returns pointer to last . in last pathcomponent or at \0.
+ */
+LPSTR WINAPI SHELL32_31(LPSTR path) {
+    LPSTR   lastpoint = NULL;
+
+    while (*path) {
+	if (*path=='\\'||*path==' ')
+	    lastpoint=NULL;
+	if (*path=='.')
+	    lastpoint=path;
+	path++;
+    }
+    return lastpoint?lastpoint:path;
+}
+
+/*************************************************************************
  *				SHELL32_32	[SHELL32.32]
  * append \ if there is none
  */
@@ -48,6 +123,27 @@
 }
 
 /*************************************************************************
+ *				SHELL32_33      [SHELL32.33]
+ * remove spaces from beginning and end of passed string
+ */
+LPSTR WINAPI SHELL32_33(LPSTR str) {
+    LPSTR x = str;
+
+    while (*x==' ') x++;
+    if (x!=str)
+	lstrcpy32A(str,x);
+    if (!*str)
+	return str;
+    x=str+strlen(str)-1;
+    while (*x==' ')
+	x--;
+    if (*x==' ')
+	*x='\0';
+    return x;
+}
+
+
+/*************************************************************************
  *				SHELL32_34	[SHELL32.34]
  * basename(char *fn);
  */
@@ -135,6 +231,27 @@
 }
 
 /*************************************************************************
+ *				SHELL32_39	[SHELL32.39]
+ * isUNC(const char*path);
+ */
+BOOL32 WINAPI SHELL32_39(LPCSTR path) {
+	if ((path[0]=='\\') && (path[1]=='\\'))
+		return TRUE;
+	return FALSE;
+}
+
+/*************************************************************************
+ *				SHELL32_45	[SHELL32.45]
+ * file_exists(char *fn);
+ */
+BOOL32 WINAPI SHELL32_45(LPSTR fn) {
+    if (GetFileAttributes32A(fn)==-1)
+    	return FALSE;
+    else
+    	return TRUE;
+}
+
+/*************************************************************************
  *				SHELL32_52	[SHELL32.52]
  * look for next arg in string. handle "quoted" strings
  * returns pointer to argument *AFTER* the space. Or to the \0.
@@ -153,14 +270,95 @@
 }
 
 /*************************************************************************
- *				SHELL32_45	[SHELL32.45]
- * file_exists(char *fn);
+ *				SHELL32_56      [SHELL32.56]
+ * unquote string (remove ")
  */
-BOOL32 WINAPI SHELL32_45(LPSTR fn) {
-    if (GetFileAttributes32A(fn)==-1)
-    	return FALSE;
-    else
-    	return TRUE;
+VOID WINAPI SHELL32_56(LPSTR str) {
+    DWORD      len = lstrlen32A(str);
+
+    if (*str!='"') return;
+    if (str[len-1]!='"') return;
+    str[len-1]='\0';
+    lstrcpy32A(str,str+1);
+    return;
+}
+
+/*************************************************************************
+ *	 		 SHELL32_58   			[SHELL32.58]
+ */
+DWORD WINAPI SHELL32_58(LPCSTR src,DWORD x2,LPSTR target,DWORD pathlen) {
+	fprintf(stderr,"SHELL32_58(%s,0x%08lx,%p,%ld),STUB!\n",
+		src,x2,target,pathlen
+	);
+	if (!src)
+		return 0;
+	return 0;
+}
+
+/*************************************************************************
+ *	 		 SHELL32_62   			[SHELL32.62]
+ */
+DWORD WINAPI SHELL32_62(DWORD x,DWORD y,DWORD z,DWORD a) {
+	fprintf(stderr,"SHELL32_62(%08lx,%08lx,%08lx,%08lx),stub!\n",x,y,z,a);
+	return 0xffffffff;
+}
+
+/*************************************************************************
+ *                      SHELL32_63                     [SHELL32.63]
+ */
+DWORD WINAPI SHELL32_63(HWND32 howner, LPSTR targetbuf, DWORD len, DWORD x, LPCSTR suffix, LPCSTR y, LPCSTR cmd) {
+    fprintf(stderr,"SHELL32_63(%04x,%p,%ld,%08lx,%s,%s,%s),stub!\n",
+	    howner,targetbuf,len,x,suffix,y,cmd
+    );
+    /* puts up a Open Dialog and requests input into targetbuf */
+    /* OFN_HIDEREADONLY|OFN_NOCHANGEDIR|OFN_FILEMUSTEXIST|OFN_unknown */
+    lstrcpy32A(targetbuf,"x:\\s3.exe");
+    return 1;
+}
+
+/*************************************************************************
+ *                      SHELL32_68                     [SHELL32.68]
+ */
+DWORD WINAPI SHELL32_68(DWORD x,DWORD y,DWORD z) {
+	fprintf(stderr,"SHELL32_68(0x%08lx,0x%08lx,0x%08lx),stub!\n",
+		x,y,z
+	);
+	return 0;
+}
+/*************************************************************************
+ *			 SHELL32_71   			[SHELL32.71]
+ * returns internal shell values in the passed pointers
+ */
+BOOL32 WINAPI SHELL32_71(LPDWORD x,LPDWORD y) {
+
+	fprintf(stderr,"SHELL32_71(%p,%p),stub!\n",x,y);
+	return TRUE;
+}
+
+/*************************************************************************
+ *			 SHELL32_72   			[SHELL32.72]
+ * dunno. something with icons
+ */
+void WINAPI SHELL32_72(LPSTR x,DWORD y,DWORD z) {
+	fprintf(stderr,"SHELL32_72(%s,%08lx,%08lx),stub!\n",x,y,z);
+}
+
+/*************************************************************************
+ *			 SHELL32_89   			[SHELL32.89]
+ */
+DWORD WINAPI SHELL32_89(DWORD x1,DWORD x2,DWORD x3) {
+	fprintf(stderr,"SHELL32_89(0x%08lx,0x%08lx,0x%08lx),stub!\n",
+		x1,x2,x3
+	);
+	return 0;
+}
+
+/*************************************************************************
+ *				SHELL32_119	[SHELL32.119]
+ * unknown
+ */
+void WINAPI SHELL32_119(LPVOID x) {
+    fprintf(stderr,"SHELL32_119(%p(%s)),stub\n",x,(char *)x);
 }
 
 /*************************************************************************
@@ -182,14 +380,6 @@
 }
 
 /*************************************************************************
- *				SHELL32_119	[SHELL32.119]
- * unknown
- */
-void WINAPI SHELL32_119(LPVOID x) {
-    fprintf(stderr,"SHELL32_119(%p),stub\n",x);
-}
-
-/*************************************************************************
  *				SHELL32_75	[SHELL32.75]
  * unknown
  */
@@ -198,16 +388,26 @@
     return TRUE;
 }
 
-DWORD WINAPI
-SHELL32_DllGetClassObject(REFCLSID *clsid,REFIID *iid,LPVOID *x) {
-	char	xclsid[50],xiid[50];
-
-	StringFromCLSID((LPCLSID)clsid,xclsid);
-	StringFromCLSID((LPCLSID)iid,xiid);
-	fprintf(stderr,"SHELL32_DllGetClassObject(%s,%s,%p), STUB\n",xclsid,xiid,x);
+/*************************************************************************
+ *	 		 SHELL32_77   			[SHELL32.77]
+ */
+DWORD WINAPI SHELL32_77(DWORD x,DWORD y,DWORD z) {
+	fprintf(stderr,"SHELL32_77(%08lx,%08lx,%08lx),stub!\n",x,y,z);
 	return 0;
 }
 
+/*************************************************************************
+ *	 		 SHELL32_79   			[SHELL32.79]
+ * create_directory_and_notify(...)
+ */
+DWORD WINAPI SHELL32_79(LPCSTR dir,LPVOID xvoid) {
+	fprintf(stderr,"mkdir %s,%p\n",dir,xvoid);
+	if (!CreateDirectory32A(dir,xvoid))
+		return FALSE;
+	/* SHChangeNotify(8,1,dir,0); */
+	return TRUE;
+}
+
 static FARPROC32 _find_moduleproc(LPSTR dllname,HMODULE32 *xhmod,LPSTR name) {
 	HMODULE32	hmod;
 	FARPROC32	dllunload,nameproc;
@@ -236,18 +436,26 @@
 ) {
 	DWORD	WINAPI	(*dllgetclassob)(REFCLSID,REFIID,LPVOID);
 	DWORD		hres;
+/*
 	LPCLASSFACTORY	classfac;
+ */
 
 	dllgetclassob = (DWORD(*)(REFCLSID,REFIID,LPVOID))_find_moduleproc(dllname,NULL,"DllGetClassObject");
 	if (!dllgetclassob)
 		return 0x80070000|GetLastError();
 
-	hres = (*dllgetclassob)(clsid,(REFIID)&IID_IClassFactory,&classfac);
+/* FIXME */
+	hres = (*dllgetclassob)(clsid,(REFIID)&IID_IClassFactory,inst);
 	if (hres<0)
 		return hres;
 
+/*
+	hres = (*dllgetclassob)(clsid,(REFIID)&IID_IClassFactory,&classfac);
+	if (hres<0)
+		return hres;
 	classfac->lpvtbl->fnCreateInstance(classfac,unknownouter,refiid,inst);
 	classfac->lpvtbl->fnRelease(classfac);
+ */
 	return 0;
 }
 /*************************************************************************
@@ -321,24 +529,6 @@
 
 
 /*************************************************************************
- *			 SHELL32_71   			[SHELL32.71]
- * returns internal shell values in the passed pointers
- */
-BOOL32 WINAPI SHELL32_71(LPDWORD x,LPDWORD y) {
-
-	fprintf(stderr,"SHELL32_71(%p,%p),stub!\n",x,y);
-	return TRUE;
-}
-
-/*************************************************************************
- *			 SHELL32_72   			[SHELL32.72]
- * dunno. something with icons
- */
-void WINAPI SHELL32_72(LPSTR x,DWORD y,DWORD z) {
-	fprintf(stderr,"SHELL32_72(%s,%08lx,%08lx),stub!\n",x,y,z);
-}
-
-/*************************************************************************
  *			 SHELL32_100   			[SHELL32.100]
  * walks through policy table, queries <app> key, <type> value, returns 
  * queried (DWORD) value.
@@ -375,56 +565,6 @@
 	
 }
 
-DWORD WINAPI SHELL32_77(DWORD x,DWORD y,DWORD z) {
-	fprintf(stderr,"SHELL32_77(%08lx,%08lx,%08lx),stub!\n",x,y,z);
-	return 0;
-}
-
-/*************************************************************************
- *	 		 SHELL32_79   			[SHELL32.79]
- * create_directory_and_notify(...)
- */
-DWORD WINAPI SHELL32_79(LPCSTR dir,LPVOID xvoid) {
-	fprintf(stderr,"mkdir %s,%p\n",dir,xvoid);
-	if (!CreateDirectory32A(dir,xvoid))
-		return FALSE;
-	/* SHChangeNotify(8,1,dir,0); */
-	return TRUE;
-}
-
-/*************************************************************************
- *	 		 SHELL32_165   			[SHELL32.165]
- * create_path_and_notify(...)
- */
-DWORD WINAPI SHELL32_165(DWORD x,LPCSTR path) {
-	if (SHELL32_79(path,(LPVOID)x))
-		return 0;
-	fprintf(stderr,"SHELL32_165(%08lx,%s),stub!\n",x,path);
-	return 0;
-}
-
-/*************************************************************************
- *	 		 SHELL32_29   			[SHELL32.29]
- * is_rootdir(const char*path)
- */
-BOOL32 WINAPI SHELL32_29(LPCSTR x) {
-	if (!lstrcmp32A(x+1,":\\"))		/* "X:\" */
-		return 1;
-	if (!lstrcmp32A(x,"\\"))		/* "\" */
-		return 1;
-	if (x[0]=='\\' && x[1]=='\\') {		/* UNC "\\<xx>\" */
-		int	foundbackslash = 0;
-		x=x+2;
-		while (*x) {
-			if (*x++=='\\')
-				foundbackslash++;
-		}
-		if (foundbackslash<=1)	/* max 1 \ more ... */
-			return 1;
-	}
-	return 0;
-}
-
 /*************************************************************************
  *	 		 SHELL32_152   			[SHELL32.152]
  * itemlist_length
@@ -443,6 +583,34 @@
 }
 
 /*************************************************************************
+ *                      SHELL32_158                    [SHELL32.158]
+ */
+LPSTR WINAPI SHELL32_158(LPSTR path,DWORD y,DWORD z) {
+    fprintf(stderr,"SHELL32_158(%s,%08lx,%08lx)\n",path,y,z);
+    path = SHELL32_31(path);
+    return *path?(path+1):path;
+}
+
+/*************************************************************************
+ *	 		 SHELL32_165   			[SHELL32.165]
+ * create_path_and_notify(...)
+ */
+DWORD WINAPI SHELL32_165(DWORD x,LPCSTR path) {
+	if (SHELL32_79(path,(LPVOID)x))
+		return 0;
+	fprintf(stderr,"SHELL32_165(%08lx,%s),stub!\n",x,path);
+	return 0;
+}
+
+/*************************************************************************
+ *	 		 SHELL32_195   			[SHELL32.195]
+ * free_ptr() - frees memory using IMalloc
+ */
+DWORD WINAPI SHELL32_195(LPVOID x) {
+	return LocalFree32((HANDLE32)x);
+}
+
+/*************************************************************************
  *	 		 SHELL32_196   			[SHELL32.196]
  * void *task_alloc(DWORD len), uses SHMalloc allocator
  */
@@ -481,32 +649,6 @@
 }
 
 /*************************************************************************
- *	 		 SHELL32_16   			[SHELL32.16]
- * find_lastitem_in_itemidlist()
- */
-LPSHITEMID WINAPI SHELL32_16(LPITEMIDLIST iil) {
-	LPSHITEMID	lastsii,sii;
-
-	if (!iil)
-		return NULL;
-	sii = &(iil->mkid);
-	lastsii = sii;
-	while (sii->cb) {
-		lastsii = sii;
-		sii = (LPSHITEMID)(((char*)sii)+sii->cb);
-	}
-	return lastsii;
-}
-
-/*************************************************************************
- *	 		 SHELL32_195   			[SHELL32.195]
- * free_ptr() - frees memory using IMalloc
- */
-DWORD WINAPI SHELL32_195(LPVOID x) {
-	return LocalFree32((HANDLE32)x);
-}
-
-/*************************************************************************
  *	 		 SHELL32_155   			[SHELL32.155]
  * free_check_ptr - frees memory (if not NULL) allocated by SHMalloc allocator
  */
@@ -515,11 +657,3 @@
 		return 0;
 	return SHELL32_195(x);
 }
-
-/*************************************************************************
- *	 		 SHELL32_62   			[SHELL32.62]
- */
-DWORD WINAPI SHELL32_62(DWORD x,DWORD y,DWORD z,DWORD a) {
-	fprintf(stderr,"SHELL32_62(%08lx,%08lx,%08lx,%08lx),stub!\n",x,y,z,a);
-	return 0xffffffff;
-}
diff --git a/misc/toolhelp.c b/misc/toolhelp.c
index c9ceabb..afbdc46 100644
--- a/misc/toolhelp.c
+++ b/misc/toolhelp.c
@@ -70,3 +70,18 @@
     nrofnotifys--;
     return TRUE;
 }
+
+BOOL16 WINAPI StackTraceCSIPFirst(STACKTRACEENTRY *ste, WORD wSS, WORD wCS, WORD wIP, WORD wBP)
+{
+    return TRUE;
+}
+
+BOOL16 WINAPI StackTraceFirst(STACKTRACEENTRY *ste, HTASK16 Task)
+{
+    return TRUE;
+}
+
+BOOL16 WINAPI StackTraceNext(STACKTRACEENTRY *ste)
+{
+    return TRUE;
+}
diff --git a/misc/ver.c b/misc/ver.c
index 422e6c3..883af0d 100644
--- a/misc/ver.c
+++ b/misc/ver.c
@@ -310,10 +310,6 @@
 	}
 }
 
-extern LPIMAGE_RESOURCE_DIRECTORY GetResDirEntryW(
-	LPIMAGE_RESOURCE_DIRECTORY resdirptr,LPCWSTR name,DWORD root
-);
-
 /* Loads the specified PE resource.
  * FIXME: shouldn't load the whole image
  */
@@ -368,20 +364,20 @@
 			continue;
 	}
 	resourcedir = (LPIMAGE_RESOURCE_DIRECTORY)(image+resdir.VirtualAddress);
-	xresdir = GetResDirEntryW(resourcedir,typeid,(DWORD)resourcedir);
+	xresdir = GetResDirEntryW(resourcedir,typeid,(DWORD)resourcedir,FALSE);
 	if (!xresdir) {
 		dprintf_ver(stddeb,"...no typeid entry found for %p\n",typeid);
 		HeapFree(GetProcessHeap(),0,image);
 		return 0;
 	}
-	xresdir = GetResDirEntryW(xresdir,resid,(DWORD)resourcedir);
+	xresdir = GetResDirEntryW(xresdir,resid,(DWORD)resourcedir,FALSE);
 	if (!xresdir) {
 		dprintf_ver(stddeb,"...no resid entry found for %p\n",resid);
 		HeapFree(GetProcessHeap(),0,image);
 		return 0;
 	}
 	
-	xresdir = GetResDirEntryW(xresdir,0,(DWORD)resourcedir);
+	xresdir = GetResDirEntryW(xresdir,0,(DWORD)resourcedir,TRUE);
 	if (!xresdir) {
 		dprintf_ver(stddeb,"...no 0 (default language) entry found for %p\n",resid);
 		HeapFree(GetProcessHeap(),0,image);
@@ -1181,7 +1177,8 @@
 			nextslash++;
 		if (!*nextslash)
 			nextslash=NULL;
-	}
+	} else if (*str == 0)
+		return NULL;
 
 
 	while (1) {
@@ -1208,7 +1205,7 @@
 }
 
 /* this one used for Win32 resources, which are always in UNICODE format */
-extern LPWSTR CRTDLL_wcschr(LPCWSTR str,WCHAR xchar);
+extern LPWSTR __cdecl CRTDLL_wcschr(LPCWSTR str,WCHAR xchar);
 static BYTE*
 _find_dataW(BYTE *block,LPCWSTR str, int buff_remain) {
 	LPWSTR	nextslash;
@@ -1227,7 +1224,8 @@
 			nextslash++;
 		if (!*nextslash)
 			nextslash=NULL;
-	}
+	} else if (*str == 0)
+		return NULL;
 
 
 	while (1) {
@@ -1298,6 +1296,7 @@
 		if (!b) {
 			fprintf(stderr,"key %s not found in versionresource.\n",s);
 			*buflen=0;
+			free (s);
 			return 0;
 		}
 		db=(struct dbW*)b;
@@ -1315,6 +1314,7 @@
 		if (!b) {
 			fprintf(stderr,"key %s not found in versionresource.\n",s);
 			*buflen=0;
+			free (s);
 			return 0;
 		}
 		db=(struct dbA*)b;
@@ -1358,6 +1358,7 @@
 		if (!b) {
 			fprintf(stderr,"key %s not found in versionresource.\n",s);
 			*buflen=0;
+			free (s);
 			return 0;
 		}
 		db	= (struct dbW*)b;
@@ -1369,12 +1370,15 @@
 		    HeapFree(GetProcessHeap(),0,xs);
 		} else
 		    dprintf_ver(stderr,"->%p\n",b);
+		/* This is a leak.  */
+		b = HEAP_strdupWtoA(GetProcessHeap(),0,(WCHAR*)b);
 	} else {
 		struct	dbA	*db;
 		b=_find_dataA(block,s,*(WORD*)block);
 		if (!b) {
 			fprintf(stderr,"key %s not found in versionresource.\n",subblock);
 			*buflen=0;
+			free (s);
 			return 0;
 		}
 		db=(struct dbA*)b;
diff --git a/misc/w32scomb.c b/misc/w32scomb.c
index 54d1d5c..9d2ac9e 100644
--- a/misc/w32scomb.c
+++ b/misc/w32scomb.c
@@ -10,13 +10,14 @@
 #include <stdlib.h>
 #include "windows.h"
 #include "module.h"
+#include "ldt.h"
 
 /***********************************************************************
  *           Get16DLLAddress       (KERNEL32)
  *
  * rough guesswork, but seems to work
  */
-FARPROC16 Get16DLLAddress(HMODULE32 handle, LPSTR name) {
+FARPROC16 WINAPI Get16DLLAddress(HMODULE16 handle, LPSTR name) {
         if (!handle) handle=GetModuleHandle16("WIN32S16");
         return (FARPROC16)WIN32_GetProcAddress16(handle, name);
 }
diff --git a/misc/w32skrnl.c b/misc/w32skrnl.c
index af8dae5..f05cc99 100644
--- a/misc/w32skrnl.c
+++ b/misc/w32skrnl.c
@@ -10,7 +10,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 
-LPSTR WINAPI GetWin32sDirectory()
+LPSTR WINAPI GetWin32sDirectory(void)
 {
     static char *sysdir;
     LPSTR text;
@@ -24,7 +24,7 @@
 }
 
 /* FIXME */
-SEGPTR WINAPI _GetThunkBuff()
+SEGPTR WINAPI _GetThunkBuff(void)
 {
 	return (SEGPTR)NULL;
 }
diff --git a/misc/win32s16.c b/misc/win32s16.c
new file mode 100644
index 0000000..382e146
--- /dev/null
+++ b/misc/win32s16.c
@@ -0,0 +1,16 @@
+/*
+ * WIN32S16
+ * DLL for Win32s
+ *
+ * Copyright (c) 1997 Andreas Mohr
+ */
+
+#include "windows.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+void BootTask()
+{
+	fprintf(stderr, "BootTask(): should only be used by WIN32S.EXE.\n");
+}
diff --git a/misc/windebug.c b/misc/windebug.c
new file mode 100644
index 0000000..30f4d2c
--- /dev/null
+++ b/misc/windebug.c
@@ -0,0 +1,20 @@
+/*
+ * WINDEBUG.DLL
+ *
+ * Copyright (c) 1997 Andreas Mohr
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "windows.h"
+#include "module.h"
+
+/***********************************************************************
+ *           WinNotify       (WINDEBUG.1)
+ *  written without _any_ docu
+ */
+DWORD WinNotify() {
+	fprintf(stderr, "WinNotify(): stub !\n");
+	return NULL;
+}
diff --git a/misc/winsock.c b/misc/winsock.c
index a5d4dc9..b94bb3c 100644
--- a/misc/winsock.c
+++ b/misc/winsock.c
@@ -4,7 +4,6 @@
  * 
  * (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
  *
- * TODO: 32-bit asynchronous services.
  */
  
 #include <stdio.h>
@@ -32,13 +31,13 @@
 #include <netdb.h>
 #include <unistd.h>
 
+#include "winsock.h"
 #include "windows.h"
 #include "winnt.h"
 #include "heap.h"
 #include "ldt.h"
 #include "task.h"
 #include "message.h"
-#include "winsock.h"
 #include "miscemu.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -148,25 +147,31 @@
     return NULL;
 }
 
-static fd_set* fd_set_import( fd_set* fds, LPWSINFO pwsi, ws_fd_set* ws, int* highfd )
+static fd_set* fd_set_import( fd_set* fds, LPWSINFO pwsi, void* wsfds, int* highfd, BOOL32 b32 )
 {
     /* translate Winsock fd set into local fd set */
 
-    if( ws ) 
+    if( wsfds ) 
     { 
-	int 	i;
-	ws_socket*  pws;
+#define wsfds16	((ws_fd_set16*)wsfds)
+#define wsfds32 ((ws_fd_set32*)wsfds)
+	ws_socket* pws;
+	int i, count;
 
 	FD_ZERO(fds);
-	for( i = 0; i < (ws->fd_count) ; i++ ) 
+	count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
+	for( i = 0; i < count; i++ )
 	{
-	    pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]);
-	    if( _check_ws(pwsi, pws) ) 
-	    {
-		if( pws->fd > *highfd ) *highfd = pws->fd; 
-		FD_SET(pws->fd, fds); 
-	    }
+	     pws = (b32) ? (ws_socket*)WS_HANDLE2PTR(wsfds32->fd_array[i])
+			 : (ws_socket*)WS_HANDLE2PTR(wsfds16->fd_array[i]);
+	     if( _check_ws(pwsi, pws) )
+             {
+		    if( pws->fd > *highfd ) *highfd = pws->fd;
+		    FD_SET(pws->fd, fds);
+	     }
 	}
+#undef wsfds32
+#undef wsfds16
 	return fds;
     }
     return NULL;
@@ -182,20 +187,23 @@
     return optval != 0;
 }
 
-static int fd_set_export( LPWSINFO pwsi, fd_set* fds, fd_set* exceptfds, ws_fd_set* ws )
+static int fd_set_export( LPWSINFO pwsi, fd_set* fds, fd_set* exceptfds, void* wsfds, BOOL32 b32 )
 {
     int num_err = 0;
 
     /* translate local fd set into Winsock fd set, adding
      * errors to exceptfds (only if app requested it) */
 
-    if( ws )
+    if( wsfds )
     {
-	int i, j, count = ws->fd_count;
+#define wsfds16 ((ws_fd_set16*)wsfds)
+#define wsfds32 ((ws_fd_set32*)wsfds)
+	int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
 
 	for( i = 0, j = 0; i < count; i++ )
 	{
-	    ws_socket *pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]);
+	    ws_socket *pws = (b32) ? (ws_socket*)WS_HANDLE2PTR(wsfds32->fd_array[i])
+				   : (ws_socket*)WS_HANDLE2PTR(wsfds16->fd_array[i]);
 	    int fd = pws->fd;
 
 	    if( _check_ws(pwsi, pws) && FD_ISSET(fd, fds) )
@@ -206,11 +214,19 @@
 		    num_err++;
 		}
 		else
-		    ws->fd_array[j++] = ws->fd_array[i];
+		    if( b32 )
+			wsfds32->fd_array[j++] = wsfds32->fd_array[i];
+		    else
+			wsfds16->fd_array[j++] = wsfds16->fd_array[i];
 	    }
 	}
-	ws->fd_count = j;
+
+	if( b32 ) wsfds32->fd_count = j;
+	else wsfds16->fd_count = j;
+
 	dprintf_winsock(stddeb, "\n");
+#undef wsfds32
+#undef wsfds16
     }
     return num_err;
 }
@@ -386,7 +402,7 @@
 	    if( pwsi->sock[i].psop )
 	    {
 		n++;
-		WSAAsyncSelect( (SOCKET16)WS_PTR2HANDLE(pwsi->sock + i), 0, 0, 0 );
+		WSAAsyncSelect32( (SOCKET16)WS_PTR2HANDLE(pwsi->sock + i), 0, 0, 0 );
 	    }
             close(pwsi->sock[i].fd); j++; 
         }
@@ -504,8 +520,8 @@
 		    EVENT_AddIO( pws->fd, EVENT_IO_READ );	/* reenabler */
 
 		    /* async select the accept()'ed socket */
-		    WSAAsyncSelect( s, pws->psop->hWnd, pws->psop->uMsg,
-				    pws->flags & ~WS_FD_ACCEPT );
+		    WSAAsyncSelect32( s, pws->psop->hWnd, pws->psop->uMsg,
+				      pws->flags & ~WS_FD_ACCEPT );
 		}
 		return s;
             } 
@@ -538,13 +554,13 @@
 
     dprintf_winsock(stddeb, "WS_BIND(%08x): socket %04x, ptr %8x, length %d\n", 
 			   (unsigned)pwsi, s, (int) name, namelen);
-#if DEBUG_SOCKADDR
+/* #if DEBUG_SOCKADDR */
     dump_sockaddr(name);
-#endif
+/* #endif */
 
     if ( _check_ws(pwsi, pws) )
       if ( namelen >= sizeof(*name) ) 
-	if ( ((struct sockaddr_in *)name)->sin_family == AF_INET )
+	if ( ((struct ws_sockaddr_in *)name)->sin_family == AF_INET )
 	  if ( bind(pws->fd, name, namelen) < 0 ) 
 	  {
 	     int	loc_errno = errno;
@@ -585,7 +601,7 @@
     { 
 	int	fd = pws->fd;
 
-	if( pws->psop ) WSAAsyncSelect( s, 0, 0, 0 );
+	if( pws->psop ) WSAAsyncSelect32( s, 0, 0, 0 );
 
 	pws->fd = -1;
 	pws->flags = (unsigned)pwsi->last_free;
@@ -789,7 +805,7 @@
  */
 u_short WINAPI WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
 /***********************************************************************
- *		inet_addr()		(WINSOCK.10)
+ *		inet_addr()		(WINSOCK.10)(WSOCK32.10)
  */
 u_long WINAPI WINSOCK_inet_addr(char *cp)      { return( inet_addr(cp) ); }
 /***********************************************************************
@@ -802,34 +818,40 @@
 u_short WINAPI WINSOCK_ntohs(u_short netshort)  { return( ntohs(netshort) ); }
 
 /***********************************************************************
- *		inet_ntoa()		(WINSOCK.11)
+ *		inet_ntoa()		(WINSOCK.11)(WSOCK32.11)
  */
-SEGPTR WINAPI WINSOCK_inet_ntoa(struct in_addr in)
+char* WINAPI WINSOCK_inet_ntoa32(struct in_addr in)
 {
   /* use "buffer for dummies" here because some applications have 
    * propensity to decode addresses in ws_hostent structure without 
    * saving them first...
    */
 
-  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+    LPWSINFO      pwsi = wsi_find(GetCurrentTask());
 
-  if( pwsi )
-  {
-    char*	s = inet_ntoa(in);
-    if( s ) 
+    if( pwsi )
     {
-	if( pwsi->dbuffer == NULL )
-	    if((pwsi->dbuffer = (char*) SEGPTR_ALLOC(32)) == NULL )
-	    {
-		pwsi->err = WSAENOBUFS;
-		return (SEGPTR)NULL;
-	    }
-	strncpy(pwsi->dbuffer, s, 32 );
-	return SEGPTR_GET(pwsi->dbuffer); 
+	char*	s = inet_ntoa(in);
+	if( s ) 
+	{
+	    if( pwsi->dbuffer == NULL )
+		if((pwsi->dbuffer = (char*) SEGPTR_ALLOC(32)) == NULL )
+		{
+		    pwsi->err = WSAENOBUFS;
+		    return NULL;
+		}
+	    strncpy(pwsi->dbuffer, s, 32 );
+	    return pwsi->dbuffer; 
+	}
+	pwsi->err = wsaErrno();
     }
-    pwsi->err = wsaErrno();
-  }
-  return (SEGPTR)NULL;
+    return NULL;
+}
+
+SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
+{
+  char* retVal = WINSOCK_inet_ntoa32(in);
+  return retVal ? SEGPTR_GET(retVal) : (SEGPTR)NULL;
 }
 
 /***********************************************************************
@@ -1019,16 +1041,15 @@
 }
 
 /***********************************************************************
- *		select()		(WINSOCK.18)
+ *		select()		(WINSOCK.18)(WSOCK32.18)
  */
-INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set *ws_readfds,
-                              ws_fd_set *ws_writefds, ws_fd_set *ws_exceptfds,
-                              struct timeval *timeout)
+static INT32 __ws_select( BOOL32 b32, void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
+			  struct timeval *timeout )
 {
     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
 	
-    dprintf_winsock(stddeb, "WS_SELECT(%08x): nfds %d (ignored), read %8x, write %8x, excp %8x\n", 
-    (unsigned) pwsi, nfds, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
+    dprintf_winsock(stddeb, "WS_SELECT(%08x): read %8x, write %8x, excp %8x\n", 
+    (unsigned) pwsi, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
 
     if( pwsi )
     {
@@ -1036,28 +1057,41 @@
 	fd_set      readfds, writefds, exceptfds;
 	fd_set     *p_read, *p_write, *p_except;
 
-	p_read = fd_set_import(&readfds, pwsi, ws_readfds, &highfd);
-	p_write = fd_set_import(&writefds, pwsi, ws_writefds, &highfd);
-	p_except = fd_set_import(&exceptfds, pwsi, ws_exceptfds, &highfd);
+	p_read = fd_set_import(&readfds, pwsi, ws_readfds, &highfd, b32);
+	p_write = fd_set_import(&writefds, pwsi, ws_writefds, &highfd, b32);
+	p_except = fd_set_import(&exceptfds, pwsi, ws_exceptfds, &highfd, b32);
 
 	if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeout)) >= 0 )
 	{
 	    if( highfd )
 	    {
-		fd_set_export(pwsi, &readfds, p_except, ws_readfds);
-		fd_set_export(pwsi, &writefds, p_except, ws_writefds);
+		fd_set_export(pwsi, &readfds, p_except, ws_readfds, b32);
+		fd_set_export(pwsi, &writefds, p_except, ws_writefds, b32);
 
 		if (p_except && ws_exceptfds)
 		{
-		    int i, j, count = ws_exceptfds->fd_count;
+#define wsfds16 ((ws_fd_set16*)ws_exceptfds)
+#define wsfds32 ((ws_fd_set32*)ws_exceptfds)
+		    int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
 
 		    for (i = j = 0; i < count; i++)
 		    {
-			ws_socket *pws = (ws_socket *)WS_HANDLE2PTR(ws_exceptfds->fd_array[i]);
+			ws_socket *pws = (b32) ? (ws_socket *)WS_HANDLE2PTR(wsfds32->fd_array[i])
+					       : (ws_socket *)WS_HANDLE2PTR(wsfds16->fd_array[i]);
 			if( _check_ws(pwsi, pws) && FD_ISSET(pws->fd, &exceptfds) )
-			    ws_exceptfds->fd_array[j++] = ws_exceptfds->fd_array[i];
+			{
+			    if( b32 )
+				wsfds32->fd_array[j++] = wsfds32->fd_array[i];
+			    else
+				wsfds16->fd_array[j++] = wsfds16->fd_array[i];
+			}
 		    }
-		    ws_exceptfds->fd_count = j;
+		    if( b32 )
+			wsfds32->fd_count = j;
+		    else
+			wsfds16->fd_count = j;
+#undef wsfds32
+#undef wsfds16
 		}
 	    }
 	    return highfd; 
@@ -1067,15 +1101,19 @@
     return SOCKET_ERROR;
 }
 
-/***********************************************************************
- *              select()		(WSOCK32.18)
- */
-INT32 WINAPI WINSOCK_select32(INT32 nfds, ws_fd_set *ws_readfds,
-                              ws_fd_set *ws_writefds, ws_fd_set *ws_exceptfds,
+INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
+                              ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
+                              struct timeval *timeout)
+{
+    return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
+}
+
+INT32 WINAPI WINSOCK_select32(INT32 nfds, ws_fd_set32 *ws_readfds,
+                              ws_fd_set32 *ws_writefds, ws_fd_set32 *ws_exceptfds,
                               struct timeval *timeout)
 {
     /* struct timeval is the same for both 32- and 16-bit code */
-    return WINSOCK_select16( (INT16)nfds, ws_readfds, ws_writefds, ws_exceptfds, timeout );
+    return (INT32)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
 }
 
 
@@ -1088,7 +1126,7 @@
     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
 
     dprintf_winsock(stddeb, "WS_SEND(%08x): socket %04x, ptr %08x, length %d, flags %d\n", 
-			  (unsigned)pwsi, s, (unsigned) buf, len, flags);
+			   (unsigned)pwsi, s, (unsigned) buf, len, flags);
     if( _check_ws(pwsi, pws) )
     {
 	int	length;
@@ -1221,7 +1259,7 @@
 
 		case 2: /* drop all */
 		default:
-			WSAAsyncSelect( s, 0, 0, 0 );
+			WSAAsyncSelect32( s, 0, 0, 0 );
 			break;
 	    }
 
@@ -1586,23 +1624,40 @@
  */
 
 /* winsock_dns.c */
-extern HANDLE16 __WSAsyncDBQuery(LPWSINFO pwsi, HWND16 hWnd, UINT16 uMsg, INT16 type, LPCSTR init,
-				 INT16 len, LPCSTR proto, SEGPTR sbuf, INT16 buflen, UINT32 flag);
+extern HANDLE16 __WSAsyncDBQuery(LPWSINFO pwsi, HWND32 hWnd, UINT32 uMsg, INT32 type, LPCSTR init,
+				 INT32 len, LPCSTR proto, void* sbuf, INT32 buflen, UINT32 flag);
 
 /***********************************************************************
  *       WSAAsyncGetHostByAddr()	(WINSOCK.102)
  */
-HANDLE16 WINAPI WSAAsyncGetHostByAddr(HWND16 hWnd, UINT16 uMsg, LPCSTR addr,
+HANDLE16 WINAPI WSAAsyncGetHostByAddr16(HWND16 hWnd, UINT16 uMsg, LPCSTR addr,
                                INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen)
 {
   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
 
-  dprintf_winsock(stddeb, "WS_AsyncGetHostByAddr(%08x): hwnd %04x, msg %04x, addr %08x[%i]\n",
+  dprintf_winsock(stddeb, "WS_AsyncGetHostByAddr16(%08x): hwnd %04x, msg %04x, addr %08x[%i]\n",
                           (unsigned)pwsi, hWnd, uMsg, (unsigned)addr , len );
 
   if( pwsi ) 
     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, type, addr, len,
-			    NULL, sbuf, buflen, WSMSG_ASYNC_HOSTBYADDR );
+			    NULL, (void*)sbuf, buflen, WSMSG_ASYNC_HOSTBYADDR );
+  return 0;
+}
+
+/***********************************************************************
+ *       WSAAsyncGetHostByAddr()        (WSOCK32.102)
+ */
+HANDLE32 WINAPI WSAAsyncGetHostByAddr32(HWND32 hWnd, UINT32 uMsg, LPCSTR addr,
+                               INT32 len, INT32 type, LPSTR sbuf, INT32 buflen)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_AsyncGetHostByAddr32(%08x): hwnd %04x, msg %08x, addr %08x[%i]\n",
+                          (unsigned)pwsi, (HWND16)hWnd, uMsg, (unsigned)addr , len );
+
+  if( pwsi )
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, type, addr, len,
+                            NULL, (void*)sbuf, buflen, WSMSG_ASYNC_HOSTBYADDR | WSMSG_ASYNC_WIN32);
   return 0;
 }
 
@@ -1610,17 +1665,17 @@
 /***********************************************************************
  *       WSAAsyncGetHostByName()	(WINSOCK.103)
  */
-HANDLE16 WINAPI WSAAsyncGetHostByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
+HANDLE16 WINAPI WSAAsyncGetHostByName16(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
                                       SEGPTR sbuf, INT16 buflen)
 {
   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
 
-  dprintf_winsock(stddeb, "WS_AsyncGetHostByName(%08x): hwnd %04x, msg %04x, host %s, buffer %i\n",
-                          (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (int)buflen );
+  dprintf_winsock(stddeb, "WS_AsyncGetHostByName16(%08x): hwnd %04x, msg %04x, host %s, 
+buffer %i\n", (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (int)buflen );
 
   if( pwsi )
     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, 0, name, 0,
-                            NULL, sbuf, buflen, WSMSG_ASYNC_HOSTBYNAME );
+                            NULL, (void*)sbuf, buflen, WSMSG_ASYNC_HOSTBYNAME );
   return 0;
 }                     
 
@@ -1628,12 +1683,14 @@
  *       WSAAsyncGetHostByName32()	(WSOCK32.103)
  */
 HANDLE32 WINAPI WSAAsyncGetHostByName32(HWND32 hWnd, UINT32 uMsg, LPCSTR name, 
-                                      LPSTR sbuf, INT32 buflen)
+					LPSTR sbuf, INT32 buflen)
 {
   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
-  dprintf_winsock(stddeb, "WS_AsyncGetHostByName(%08x): hwnd %04x, msg %04x, host %s, buffer %i\n",
-                          (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (int)buflen );
-
+  dprintf_winsock(stddeb, "WS_AsyncGetHostByName32(%08x): hwnd %04x, msg %08x, host %s, 
+buffer %i\n", (unsigned)pwsi, (HWND16)hWnd, uMsg, (name)?name:NULL_STRING, (int)buflen );
+  if( pwsi )
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, 0, name, 0,
+ 			    NULL, (void*)sbuf, buflen, WSMSG_ASYNC_HOSTBYNAME | WSMSG_ASYNC_WIN32);
   return 0;
 }                     
 
@@ -1641,17 +1698,34 @@
 /***********************************************************************
  *       WSAAsyncGetProtoByName()	(WINSOCK.105)
  */
-HANDLE16 WINAPI WSAAsyncGetProtoByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
-                                       SEGPTR sbuf, INT16 buflen)
+HANDLE16 WINAPI WSAAsyncGetProtoByName16(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
+                                         SEGPTR sbuf, INT16 buflen)
 {
   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
 
-  dprintf_winsock(stddeb, "WS_AsyncGetProtoByName(%08x): hwnd %04x, msg %04x, protocol %s\n",
-                          (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING );
+  dprintf_winsock(stddeb, "WS_AsyncGetProtoByName16(%08x): hwnd %04x, msg %08x, protocol %s\n",
+                          (unsigned)pwsi, (HWND16)hWnd, uMsg, (name)?name:NULL_STRING );
 
   if( pwsi )
     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, 0, name, 0,
-                            NULL, sbuf, buflen, WSMSG_ASYNC_PROTOBYNAME );
+                            NULL, (void*)sbuf, buflen, WSMSG_ASYNC_PROTOBYNAME );
+  return 0;
+}
+
+/***********************************************************************
+ *       WSAAsyncGetProtoByName()       (WSOCK32.105)
+ */
+HANDLE32 WINAPI WSAAsyncGetProtoByName32(HWND32 hWnd, UINT32 uMsg, LPCSTR name,
+                                         LPSTR sbuf, INT32 buflen)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_AsyncGetProtoByName32(%08x): hwnd %04x, msg %08x, protocol %s\n",
+                          (unsigned)pwsi, (HWND16)hWnd, uMsg, (name)?name:NULL_STRING );
+
+  if( pwsi )
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, 0, name, 0,
+                            NULL, (void*)sbuf, buflen, WSMSG_ASYNC_PROTOBYNAME | WSMSG_ASYNC_WIN32);
   return 0;
 }
 
@@ -1659,17 +1733,34 @@
 /***********************************************************************
  *       WSAAsyncGetProtoByNumber()	(WINSOCK.104)
  */
-HANDLE16 WINAPI WSAAsyncGetProtoByNumber(HWND16 hWnd, UINT16 uMsg, INT16 number, 
-                                         SEGPTR sbuf, INT16 buflen)
+HANDLE16 WINAPI WSAAsyncGetProtoByNumber16(HWND16 hWnd, UINT16 uMsg, INT16 number, 
+                                           SEGPTR sbuf, INT16 buflen)
 {
   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
 
-  dprintf_winsock(stddeb, "WS_AsyncGetProtoByNumber(%08x): hwnd %04x, msg %04x, num %i\n",
+  dprintf_winsock(stddeb, "WS_AsyncGetProtoByNumber16(%08x): hwnd %04x, msg %04x, num %i\n",
                           (unsigned)pwsi, hWnd, uMsg, number );
 
   if( pwsi )
     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, number, NULL, 0,
-                            NULL, sbuf, buflen, WSMSG_ASYNC_PROTOBYNUM );
+                            NULL, (void*)sbuf, buflen, WSMSG_ASYNC_PROTOBYNUM );
+  return 0;
+}
+
+/***********************************************************************
+ *       WSAAsyncGetProtoByNumber()     (WSOCK32.104)
+ */
+HANDLE32 WINAPI WSAAsyncGetProtoByNumber32(HWND32 hWnd, UINT32 uMsg, INT32 number,
+                                           LPSTR sbuf, INT32 buflen)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_AsyncGetProtoByNumber32(%08x): hwnd %04x, msg %08x, num %i\n",
+                          (unsigned)pwsi, (HWND16)hWnd, uMsg, number );
+
+  if( pwsi )
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, number, NULL, 0,
+                            NULL, (void*)sbuf, buflen, WSMSG_ASYNC_PROTOBYNUM | WSMSG_ASYNC_WIN32);
   return 0;
 }
 
@@ -1677,65 +1768,105 @@
 /***********************************************************************
  *       WSAAsyncGetServByName()	(WINSOCK.107)
  */
-HANDLE16 WINAPI WSAAsyncGetServByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
-                                      LPCSTR proto, SEGPTR sbuf, INT16 buflen)
+HANDLE16 WINAPI WSAAsyncGetServByName16(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
+                                        LPCSTR proto, SEGPTR sbuf, INT16 buflen)
 {
   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
 
-  dprintf_winsock(stddeb, "WS_AsyncGetServByName(%08x): hwnd %04x, msg %04x, name %s, proto %s\n",
+  dprintf_winsock(stddeb, "WS_AsyncGetServByName16(%08x): hwnd %04x, msg %04x, name %s, proto %s\n",
                    (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING );
 
   if( pwsi )
     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, 0, name, 0,
-                            proto, sbuf, buflen, WSMSG_ASYNC_SERVBYNAME );
+                            proto, (void*)sbuf, buflen, WSMSG_ASYNC_SERVBYNAME );
   return 0;
 }
 
 /***********************************************************************
+ *       WSAAsyncGetServByName()        (WSOCK32.107)
+ */
+HANDLE32 WINAPI WSAAsyncGetServByName32(HWND32 hWnd, UINT32 uMsg, LPCSTR name,
+                                        LPCSTR proto, LPSTR sbuf, INT32 buflen)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_AsyncGetServByName32(%08x): hwnd %04x, msg %08x, name %s, proto %s\n",
+           (unsigned)pwsi, (HWND16)hWnd, uMsg, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING );
+  if( pwsi )
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, 0, name, 0,
+                            proto, (void*)sbuf, buflen, WSMSG_ASYNC_SERVBYNAME | WSMSG_ASYNC_WIN32);
+  return 0;
+}
+
+
+/***********************************************************************
  *       WSAAsyncGetServByPort()	(WINSOCK.106)
  */
-HANDLE16 WINAPI WSAAsyncGetServByPort(HWND16 hWnd, UINT16 uMsg, INT16 port, 
-                                      LPCSTR proto, SEGPTR sbuf, INT16 buflen)
+HANDLE16 WINAPI WSAAsyncGetServByPort16(HWND16 hWnd, UINT16 uMsg, INT16 port, 
+                                        LPCSTR proto, SEGPTR sbuf, INT16 buflen)
 {
   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
 
-  dprintf_winsock(stddeb, "WS_AsyncGetServByPort(%08x): hwnd %04x, msg %04x, port %i, proto %s\n",
+  dprintf_winsock(stddeb, "WS_AsyncGetServByPort16(%08x): hwnd %04x, msg %04x, port %i, proto %s\n",
                            (unsigned)pwsi, hWnd, uMsg, port, (proto)?proto:NULL_STRING );
 
   if( pwsi )
       return __WSAsyncDBQuery(pwsi, hWnd, uMsg, port, proto, 0,
-                              NULL, sbuf, buflen, WSMSG_ASYNC_SERVBYPORT );
+                              NULL, (void*)sbuf, buflen, WSMSG_ASYNC_SERVBYPORT );
   return 0;
 }
 
 /***********************************************************************
- *       WSACancelAsyncRequest()	(WINSOCK.108)
+ *       WSAAsyncGetServByPort()        (WSOCK32.106)
  */
-INT16 WINAPI WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle)
+HANDLE32 WINAPI WSAAsyncGetServByPort32(HWND32 hWnd, UINT32 uMsg, INT32 port,
+                                        LPCSTR proto, LPSTR sbuf, INT32 buflen)
 {
-  INT16			retVal = SOCKET_ERROR;
   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
-  ws_async_op*		p_aop = (ws_async_op*)WS_HANDLE2PTR(hAsyncTaskHandle);
 
-  dprintf_winsock(stddeb, "WS_CancelAsyncRequest(%08x): handle %04x\n", 
-			   (unsigned)pwsi, hAsyncTaskHandle);
+  dprintf_winsock(stddeb, "WS_AsyncGetServByPort32(%08x): hwnd %04x, msg %08x, port %i, proto %s\n",
+                           (unsigned)pwsi, (HWND16)hWnd, uMsg, port, (proto)?proto:NULL_STRING );
+
   if( pwsi )
-  {
-      SIGNAL_MaskAsyncEvents( TRUE );	/* block SIGIO */
-      if( WINSOCK_cancel_async_op(p_aop) )
-      {
-	  WS_FREE(p_aop);
-	  pwsi->num_async_rq--;
-	  retVal = 0;
-      }
-      else pwsi->err = WSAEINVAL;
-      SIGNAL_MaskAsyncEvents( FALSE );
-  }
-  return retVal;
+      return __WSAsyncDBQuery(pwsi, hWnd, uMsg, port, proto, 0,
+             NULL, (void*)sbuf, buflen, WSMSG_ASYNC_SERVBYPORT | WSMSG_ASYNC_WIN32);
+  return 0;
+}
+
+
+/***********************************************************************
+ *       WSACancelAsyncRequest()	(WINSOCK.108)(WSOCK32.109)
+ */
+INT32 WINAPI WSACancelAsyncRequest32(HANDLE32 hAsyncTaskHandle)
+{
+    INT32		retVal = SOCKET_ERROR;
+    LPWSINFO		pwsi = wsi_find(GetCurrentTask());
+    ws_async_op*	p_aop = (ws_async_op*)WS_HANDLE2PTR(hAsyncTaskHandle);
+
+    dprintf_winsock(stddeb, "WS_CancelAsyncRequest(%08x): handle %08x\n", 
+			   (unsigned)pwsi, hAsyncTaskHandle);
+    if( pwsi )
+    {
+	SIGNAL_MaskAsyncEvents( TRUE );	/* block SIGIO */
+	if( WINSOCK_cancel_async_op(p_aop) )
+	{
+	    WS_FREE(p_aop);
+	    pwsi->num_async_rq--;
+	    retVal = 0;
+	}
+	else pwsi->err = WSAEINVAL;
+	SIGNAL_MaskAsyncEvents( FALSE );
+    }
+    return retVal;
+}
+
+INT16 WINAPI WSACancelAsyncRequest16(HANDLE16 hAsyncTaskHandle)
+{
+    return (HANDLE16)WSACancelAsyncRequest16((HANDLE32)hAsyncTaskHandle);
 }
 
 /***********************************************************************
- *      WSAAsyncSelect()		(WINSOCK.101)
+ *      WSAAsyncSelect()		(WINSOCK.101)(WSOCK32.101)
  */
 
 static ws_select_op* __ws_select_list = NULL;
@@ -1838,7 +1969,7 @@
 		    /* this will be reenabled when send() or sendto() fail with
 		     * WSAEWOULDBLOCK */
 
-		    if( PostMessage16( psop->hWnd, psop->uMsg, (WPARAM16)WS_PTR2HANDLE(psop->pws), 
+		    if( PostMessage32A( psop->hWnd, psop->uMsg, (WPARAM32)WS_PTR2HANDLE(psop->pws), 
 			              (LPARAM)WSAMAKESELECTREPLY( WS_FD_WRITE, 0 ) ) )
 		    {
 			dprintf_winsock(stddeb, "\t    hwnd %04x - %04x, %08x\n",
@@ -1905,8 +2036,8 @@
 	    {
 		dprintf_winsock(stddeb, "\t    hwnd %04x - %04x, %08x\n", 
 				psop->hWnd, psop->uMsg, (unsigned)dwEvent );
-		PostMessage16( psop->hWnd, psop->uMsg, 
-			      (WPARAM16)WS_PTR2HANDLE(psop->pws), (LPARAM)dwEvent );
+		PostMessage32A( psop->hWnd, psop->uMsg, 
+			      (WPARAM32)WS_PTR2HANDLE(psop->pws), (LPARAM)dwEvent );
 		bPost = FALSE;
 		num_posted++;
 	    }
@@ -1918,14 +2049,13 @@
     return ( num_posted ) ? TRUE : FALSE;
 }
 
-
-INT16 WINAPI WSAAsyncSelect(SOCKET16 s, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent)
+INT32 WINAPI WSAAsyncSelect32(SOCKET32 s, HWND32 hWnd, UINT32 uMsg, UINT32 lEvent)
 {
     ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
     LPWSINFO      pwsi = wsi_find(GetCurrentTask());
 
-    dprintf_winsock(stddeb, "WS_AsyncSelect(%08x): %04x, hWnd %04x, uMsg %04x, event %08x\n",
-			  (unsigned)pwsi, s, hWnd, uMsg, (unsigned)lEvent );
+    dprintf_winsock(stddeb, "WS_AsyncSelect(%08x): %04x, hWnd %04x, uMsg %08x, event %08x\n",
+			  (unsigned)pwsi, (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
     if( _check_ws(pwsi, pws) )
     {
 	ws_select_op* psop;
@@ -1996,15 +2126,20 @@
     return SOCKET_ERROR; 
 }
 
+INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, UINT32 lEvent)
+{
+    return (INT16)WSAAsyncSelect32( s, hWnd, wMsg, lEvent );
+}
+
 
 /***********************************************************************
  *	__WSAFDIsSet()			(WINSOCK.151)
  */
-INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set *set)
+INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
 {
   int i = set->fd_count;
   
-  dprintf_winsock(stddeb, "__WSAFDIsSet(%d,%8lx)\n", s,(unsigned long)set);
+  dprintf_winsock(stddeb, "__WSAFDIsSet16(%d,%8lx)\n", s,(unsigned long)set);
     
   while (i--)
       if (set->fd_array[i] == s) return 1;
@@ -2014,9 +2149,15 @@
 /***********************************************************************
  *      __WSAFDIsSet()			(WSOCK32.151)
  */
-INT32 WINAPI __WSAFDIsSet32(SOCKET32 s, ws_fd_set *set)
+INT32 WINAPI __WSAFDIsSet32(SOCKET32 s, ws_fd_set32 *set)
 {
-    return __WSAFDIsSet16( (SOCKET16)s, set );
+  int i = set->fd_count;
+
+  dprintf_winsock(stddeb, "__WSAFDIsSet32(%d,%8lx)\n", s,(unsigned long)set);
+
+  while (i--)
+      if (set->fd_array[i] == s) return 1;
+  return 0;
 }
 
 /***********************************************************************
@@ -2121,25 +2262,74 @@
     return SOCKET_ERROR;
 }
 
+/*
+ *      TCP/IP action codes.
+ */
+
+
+#define WSCNTL_TCPIP_QUERY_INFO             0x00000000
+#define WSCNTL_TCPIP_SET_INFO               0x00000001
+#define WSCNTL_TCPIP_ICMP_ECHO              0x00000002
+#define WSCNTL_TCPIP_TEST                   0x00000003
+
+
 /***********************************************************************
  *      WsControl()
+ *
+ * WsControl seems to be an undocumented Win95 function. A lot of 
+ * discussion about WsControl can be found on the net, e.g.
+ * Subject:      Re: WSOCK32.DLL WsControl Exported Function
+ * From:         "Peter Rindfuss" <rindfuss-s@medea.wz-berlin.de>
+ * Date:         1997/08/17
  */
-VOID WINAPI WsControl(DWORD x1,DWORD x2,LPDWORD x3,LPDWORD x4,
-                      LPDWORD x5,LPDWORD x6) 
+
+DWORD WINAPI WsControl(DWORD protocoll,DWORD action,
+		      LPVOID inbuf,LPDWORD inbuflen,
+                      LPVOID outbuf,LPDWORD outbuflen) 
 {
-	fprintf(stdnimp,"WsControl(%lx,%lx,%p,%p,%p,%p)\n",
-		x1,x2,x3,x4,x5,x6
-	);
-	fprintf(stdnimp,"WsControl(x,x,%lx,%lx,%lx,%lx)\n",
-		x3?*x3:0,x4?*x4:0,x5?*x5:0,x6?*x6:0
-	);
+
+  switch (action) {
+  case WSCNTL_TCPIP_ICMP_ECHO:
+    {
+      unsigned int addr = *(unsigned int*)inbuf;
+#if 0
+      int timeout= *(unsigned int*)(inbuf+4);
+      short x1 = *(unsigned short*)(inbuf+8);
+      short sendbufsize = *(unsigned short*)(inbuf+10);
+      char x2 = *(unsigned char*)(inbuf+12);
+      char ttl = *(unsigned char*)(inbuf+13);
+      char service = *(unsigned char*)(inbuf+14);
+      char type= *(unsigned char*)(inbuf+15); /* 0x2: don't fragment*/
+#endif      
+      
+      fprintf(stdnimp,"WsControl(ICMP_ECHO) to 0x%08x stub \n",
+	      addr);
+      break;
+    }
+  default:
+    fprintf(stdnimp,"WsControl(%lx,%lx,%p,%p,%p,%p) stub\n",
+	    protocoll,action,inbuf,inbuflen,outbuf,outbuflen);
+  }
+  return FALSE;
+}
+/*********************************************************
+ *       WS_s_perror         WSOCK32.1108 
+ */
+void WINAPI WS_s_perror(LPCSTR message)
+{
+    fprintf(stdnimp,"s_perror %s stub\n",message);
 	return;
 }
+
+
 /* ----------------------------------- end of API stuff */
 
-
-
-/* ----------------------------------- helper functions */
+/* ----------------------------------- helper functions -
+ *
+ * TODO: Merge WS_dup_..() stuff into one function that
+ * would operate with a generic structure containing internal
+ * pointers (via some sort of a template).
+ */
 
 static int list_size(char** l, int item_size)
 {
@@ -2193,34 +2383,29 @@
    int size = hostent_size(p_he);
    if( size )
    {
-     char*           p_name,*p_aliases,*p_addr,*p_base,*p;
+     struct ws_hostent* p_to;
+     char* p_name,*p_aliases,*p_addr,*p_base,*p;
 
      _check_buffer(pwsi, size);
+     p_to = (struct ws_hostent*)pwsi->buffer;
      p = pwsi->buffer;
      p_base = (flag & WS_DUP_OFFSET) ? NULL
 				     : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
-     p += (flag & WS_DUP_NATIVE) ? sizeof(struct hostent) : sizeof(struct ws_hostent);
+     p += sizeof(struct ws_hostent);
      p_name = p;
      strcpy(p, p_he->h_name); p += strlen(p) + 1;
      p_aliases = p;
      p += list_dup(p_he->h_aliases, p, p_base + (p - pwsi->buffer), 0);
      p_addr = p;
      list_dup(p_he->h_addr_list, p, p_base + (p - pwsi->buffer), p_he->h_length);
-     if( flag & WS_DUP_NATIVE )
-     { struct hostent* p_to = (struct hostent*)pwsi->buffer;
-       p_to->h_addrtype = p_he->h_addrtype; p_to->h_length = p_he->h_length;
-       p_to->h_name = p_base + (p_name - pwsi->buffer);
-       p_to->h_aliases = (char**)(p_base + (p_aliases - pwsi->buffer));
-       p_to->h_addr_list = (char**)(p_base + (p_addr - pwsi->buffer)); }
-     else
-     { struct ws_hostent* p_to = (struct ws_hostent*)pwsi->buffer;
-       p_to->h_addrtype = (INT16)p_he->h_addrtype; 
-       p_to->h_length = (INT16)p_he->h_length;
-       p_to->h_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
-       p_to->h_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer));
-       p_to->h_addr_list = (SEGPTR)(p_base + (p_addr - pwsi->buffer));
 
-       return (size + sizeof(struct ws_hostent) - sizeof(struct hostent)); }
+     p_to->h_addrtype = (INT16)p_he->h_addrtype; 
+     p_to->h_length = (INT16)p_he->h_length;
+     p_to->h_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
+     p_to->h_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer));
+     p_to->h_addr_list = (SEGPTR)(p_base + (p_addr - pwsi->buffer));
+
+     size += (sizeof(struct ws_hostent) - sizeof(struct hostent));
    }
    return size;
 }
@@ -2242,28 +2427,25 @@
    int size = protoent_size(p_pe);
    if( size )
    {
-     char*            p_name,*p_aliases,*p_base,*p;
+     struct ws_protoent* p_to;
+     char* p_name,*p_aliases,*p_base,*p;
 
      _check_buffer(pwsi, size);
+     p_to = (struct ws_protoent*)pwsi->buffer;
      p = pwsi->buffer; 
      p_base = (flag & WS_DUP_OFFSET) ? NULL
 				     : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
-     p += (flag & WS_DUP_NATIVE)? sizeof(struct protoent) : sizeof(struct ws_protoent);
+     p += sizeof(struct ws_protoent);
      p_name = p;
      strcpy(p, p_pe->p_name); p += strlen(p) + 1;
      p_aliases = p;
      list_dup(p_pe->p_aliases, p, p_base + (p - pwsi->buffer), 0);
-     if( flag & WS_DUP_NATIVE )
-     { struct protoent* p_to = (struct protoent*)pwsi->buffer;
-       p_to->p_proto = p_pe->p_proto;
-       p_to->p_name = p_base + (p_name - pwsi->buffer); 
-       p_to->p_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); }
-     else
-     { struct ws_protoent* p_to = (struct ws_protoent*)pwsi->buffer;
-       p_to->p_proto = (INT16)p_pe->p_proto;
-       p_to->p_name = (SEGPTR)(p_base) + (p_name - pwsi->buffer);
-       p_to->p_aliases = (SEGPTR)((p_base) + (p_aliases - pwsi->buffer)); 
-       return (size + sizeof(struct ws_protoent) - sizeof(struct protoent)); }
+
+     p_to->p_proto = (INT16)p_pe->p_proto;
+     p_to->p_name = (SEGPTR)(p_base) + (p_name - pwsi->buffer);
+     p_to->p_aliases = (SEGPTR)((p_base) + (p_aliases - pwsi->buffer)); 
+
+     size += (sizeof(struct ws_protoent) - sizeof(struct protoent));
    }
    return size;
 }
@@ -2285,9 +2467,11 @@
    int size = servent_size(p_se);
    if( size )
    {
-     char*           p_name,*p_aliases,*p_proto,*p_base,*p;
+     struct ws_servent* p_to;
+     char* p_name,*p_aliases,*p_proto,*p_base,*p;
 
      _check_buffer(pwsi, size);
+     p_to = (struct ws_servent*)pwsi->buffer;
      p = pwsi->buffer;
      p_base = (flag & WS_DUP_OFFSET) ? NULL 
 				     : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
@@ -2299,19 +2483,12 @@
      p_aliases = p;
      list_dup(p_se->s_aliases, p, p_base + (p - pwsi->buffer), 0);
 
-     if( flag & WS_DUP_NATIVE )
-     { struct servent* p_to = (struct servent*)pwsi->buffer;
-       p_to->s_port = p_se->s_port;
-       p_to->s_name = p_base + (p_name - pwsi->buffer); 
-       p_to->s_proto = p_base + (p_proto - pwsi->buffer);
-       p_to->s_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); }
-     else
-     { struct ws_servent* p_to = (struct ws_servent*)pwsi->buffer;
-       p_to->s_port = (INT16)p_se->s_port;
-       p_to->s_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
-       p_to->s_proto = (SEGPTR)(p_base + (p_proto - pwsi->buffer));
-       p_to->s_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer)); 
-       return (size + sizeof(struct ws_servent) - sizeof(struct servent)); }
+     p_to->s_port = (INT16)p_se->s_port;
+     p_to->s_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
+     p_to->s_proto = (SEGPTR)(p_base + (p_proto - pwsi->buffer));
+     p_to->s_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer)); 
+
+     size += (sizeof(struct ws_servent) - sizeof(struct servent));
    }
    return size;
 }
@@ -2323,7 +2500,7 @@
     int	loc_errno = errno; 
 #if defined(__FreeBSD__)
        dprintf_winsock(stderr, "winsock: errno %d, (%s).\n", 
-                			 errno, sys_errlist[errno]);
+                			 errno, strerror(errno));
 #else
        dprintf_winsock(stderr, "winsock: errno %d\n", errno);
 #endif
@@ -2398,7 +2575,7 @@
 
 #if defined(__FreeBSD__)
     dprintf_winsock(stderr, "winsock: h_errno %d, (%s).\n", 
-               	    h_errno, sys_errlist[h_errno]);
+               	    h_errno, strerror(h_errno));
 #else
     dprintf_winsock(stderr, "winsock: h_errno %d.\n", h_errno);
 #ifndef sun
diff --git a/misc/winsock_dns.c b/misc/winsock_dns.c
index 173f6bb..94224de 100644
--- a/misc/winsock_dns.c
+++ b/misc/winsock_dns.c
@@ -29,12 +29,12 @@
 
 extern int h_errno;
 
+#include "winsock.h"
 #include "windows.h"
 #include "heap.h"
 #include "ldt.h"
 #include "message.h"
 #include "miscemu.h"
-#include "winsock.h"
 #include "debug.h"
 
 #ifndef FASYNC
@@ -67,9 +67,9 @@
 static fd_set		__async_io_fdset;
 static ws_async_op*	__async_op_list = NULL;
 
-static void fixup_wshe(struct ws_hostent* p_wshe, SEGPTR base);
-static void fixup_wspe(struct ws_protoent* p_wspe, SEGPTR base);
-static void fixup_wsse(struct ws_servent* p_wsse, SEGPTR base);
+static void fixup_wshe(struct ws_hostent* p_wshe, void* base);
+static void fixup_wspe(struct ws_protoent* p_wspe, void* base);
+static void fixup_wsse(struct ws_servent* p_wsse, void* base);
 
 extern void EVENT_AddIO( int fd, unsigned flag );
 extern void EVENT_DeleteIO( int fd, unsigned flag );
@@ -274,19 +274,21 @@
     {
 	if( (int)LOWORD(lLength) <= p_aop->buflen )
 	{
-            char* buffer = (char*)PTR_SEG_TO_LIN(p_aop->buffer_base);
+            char* buffer = (p_aop->flags & WSMSG_ASYNC_WIN32)
+		  ? p_aop->b.lin_base : (char*)PTR_SEG_TO_LIN(p_aop->b.seg_base);
+
             read(p_aop->fd[0], buffer, LOWORD(lLength));
             switch( p_aop->flags )
             {
 		case WSMSG_ASYNC_HOSTBYNAME:
 		case WSMSG_ASYNC_HOSTBYADDR:
-		     fixup_wshe((struct ws_hostent*)buffer, p_aop->buffer_base); break;
+		     fixup_wshe((struct ws_hostent*)buffer, p_aop->b.ptr_base); break;
 		case WSMSG_ASYNC_PROTOBYNAME:
 		case WSMSG_ASYNC_PROTOBYNUM:
-		     fixup_wspe((struct ws_protoent*)buffer, p_aop->buffer_base); break;
+		     fixup_wspe((struct ws_protoent*)buffer, p_aop->b.ptr_base); break;
 		case WSMSG_ASYNC_SERVBYNAME:
 		case WSMSG_ASYNC_SERVBYPORT:
-		     fixup_wsse((struct ws_servent*)buffer, p_aop->buffer_base); break;
+		     fixup_wsse((struct ws_servent*)buffer, p_aop->b.ptr_base); break;
 		default:
                      if( p_aop->flags ) fprintf(stderr,"Received unknown async request!\n");
                      return AOP_CONTROL_REMOVE;
@@ -302,14 +304,14 @@
 
     /* FIXME: update num_async_rq */
     EVENT_DeleteIO( p_aop->fd[0], EVENT_IO_READ );
-    PostMessage16( p_aop->hWnd, p_aop->uMsg, __ws_gethandle(p_aop), (LPARAM)lLength );
+    PostMessage32A( p_aop->hWnd, p_aop->uMsg, __ws_gethandle(p_aop), (LPARAM)lLength );
     
     return AOP_CONTROL_REMOVE;  /* one-shot request */
 }
 
 
-HANDLE16 __WSAsyncDBQuery(LPWSINFO pwsi, HWND16 hWnd, UINT16 uMsg, INT16 type, LPSTR init,
-		  	  INT16 len, LPSTR proto, SEGPTR sbuf, INT16 buflen, UINT32 flag)
+HANDLE16 __WSAsyncDBQuery(LPWSINFO pwsi, HWND32 hWnd, UINT32 uMsg, INT32 type, LPSTR init,
+		  	  INT32 len, LPSTR proto, void* sbuf, INT32 buflen, UINT32 flag)
 {
     /* queue 'flag' request and fork off its handler */
 
@@ -328,7 +330,8 @@
 
 	    async_ctl.ws_aop->hWnd = hWnd;
 	    async_ctl.ws_aop->uMsg = uMsg;
-	    async_ctl.ws_aop->buffer_base = sbuf; async_ctl.ws_aop->buflen = buflen;
+	    async_ctl.ws_aop->b.ptr_base = sbuf; 
+	    async_ctl.ws_aop->buflen = buflen;
 	    async_ctl.ws_aop->flags = flag;
 	    async_ctl.ws_aop->aop_control = &aop_control;
 
@@ -441,19 +444,20 @@
 
   close(async_ctl.ws_aop->fd[0]);
 
-  dprintf_winsock(stddeb,"DNS: getting hostent for [%s]\n", async_ctl.rq.name );
-
   p_he = (flag & WSMSG_ASYNC_HOSTBYNAME)
 	 ? gethostbyname(async_ctl.rq.name)
 	 : gethostbyaddr(async_ctl.rq.name,
 		 	 async_ctl.ilength, async_ctl.type);
-  dprintf_winsock(stddeb,"DNS: done!\n");
 
-  if( p_he ) size = WS_dup_he(pwsi, p_he, WS_DUP_SEGPTR | WS_DUP_OFFSET );
+  dprintf_winsock(stddeb,"DNS: got hostent for [%s]\n", async_ctl.rq.name );
+
+  if( p_he ) /* convert to the Winsock format with internal pointers as offsets */
+      size = WS_dup_he(pwsi, p_he, WS_DUP_OFFSET | 
+		     ((flag & WSMSG_ASYNC_WIN32) ? WS_DUP_LINEAR : WS_DUP_SEGPTR) );
   if( size )
   {
-     async_ctl.buffer = pwsi->buffer;
-     async_ctl.ilength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 );
+      async_ctl.buffer = pwsi->buffer;
+      async_ctl.ilength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 );
      _async_notify( flag );
   }
   else _async_fail();
@@ -468,11 +472,16 @@
   p_pe = (flag & WSMSG_ASYNC_PROTOBYNAME)
 	 ? getprotobyname(async_ctl.rq.name)
 	 : getprotobynumber(async_ctl.type);
-  if( p_pe ) size = WS_dup_pe(pwsi, p_pe, WS_DUP_SEGPTR | WS_DUP_OFFSET );
+
+  dprintf_winsock(stddeb,"DNS: got protoent for [%s]\n", async_ctl.rq.name );
+
+  if( p_pe ) /* convert to the Winsock format with internal pointers as offsets */
+      size = WS_dup_pe(pwsi, p_pe, WS_DUP_OFFSET |
+		     ((flag & WSMSG_ASYNC_WIN32) ? WS_DUP_LINEAR : WS_DUP_SEGPTR) );
   if( size )
   {
-     async_ctl.buffer = pwsi->buffer;
-     async_ctl.ilength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 );
+      async_ctl.buffer = pwsi->buffer;
+      async_ctl.ilength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 );
      _async_notify( flag );
   } 
   else _async_fail();
@@ -487,19 +496,32 @@
   p_se = (flag & WSMSG_ASYNC_SERVBYNAME)
 	 ? getservbyname(async_ctl.rq.name, async_ctl.buffer)
 	 : getservbyport(async_ctl.type, async_ctl.buffer);
-  if( p_se ) size = WS_dup_se(pwsi, p_se, WS_DUP_SEGPTR | WS_DUP_OFFSET );
+
+  if( p_se ) /* convert to the Winsock format with internal pointers as offsets */
+      size = WS_dup_se(pwsi, p_se, WS_DUP_OFFSET |
+		      ((flag & WSMSG_ASYNC_WIN32) ? WS_DUP_LINEAR : WS_DUP_SEGPTR) );
   if( size )
   {
-     async_ctl.buffer = pwsi->buffer;
-     async_ctl.ilength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 );
+      async_ctl.buffer = pwsi->buffer;
+      async_ctl.ilength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 );
      _async_notify( flag );
   }
   else _async_fail();
 }
 
-/* ----------------------------------- helper functions */
+/* ----------------------------------- helper functions -
+ *
+ * Raw results from pipe contain internal pointers stored as
+ * offsets relative to the beginning of the buffer and we need
+ * to apply a fixup before passing them to applications.
+ *
+ * NOTE: It is possible to exploit the fact that fork() doesn't 
+ * change the buffer address by storing fixed up pointers right 
+ * in the handler. However, this will get in the way if we ever 
+ * get to implementing DNS helper daemon a-la Netscape.
+ */
 
-void fixup_wshe(struct ws_hostent* p_wshe, SEGPTR base)
+void fixup_wshe(struct ws_hostent* p_wshe, void* base)
 {
    /* add 'base' to ws_hostent pointers to convert them from offsets */
 
@@ -515,7 +537,7 @@
    for(i=0;p_addr[i];i++) p_addr[i] += (unsigned)base;
 }
 
-void fixup_wspe(struct ws_protoent* p_wspe, SEGPTR base)
+void fixup_wspe(struct ws_protoent* p_wspe, void* base)
 {
    int i;
    unsigned*       p_aliases = (unsigned*)((char*)p_wspe + (unsigned)p_wspe->p_aliases);
@@ -524,7 +546,7 @@
    for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
 }
 
-void fixup_wsse(struct ws_servent* p_wsse, SEGPTR base)
+void fixup_wsse(struct ws_servent* p_wsse, void* base)
 {
    int i;
    unsigned*       p_aliases = (unsigned*)((char*)p_wsse + (unsigned)p_wsse->s_aliases);
diff --git a/miscemu/instr.c b/miscemu/instr.c
index c101d21..46cd421 100644
--- a/miscemu/instr.c
+++ b/miscemu/instr.c
@@ -22,20 +22,23 @@
  *           INSTR_ReplaceSelector
  *
  * Try to replace an invalid selector by a valid one.
- * For now, only selector 0x40 is handled here.
+ * The only selector where it is allowed to do "mov ax,40;mov es,ax"
+ * is the so called 'bimodal' selector 0x40, which points to the BIOS
+ * data segment. Used by (at least) Borland products (and programs compiled 
+ * using Borland products).
+ *
+ * See Undocumented Windows, Chapter 5, __0040.
  */
 static WORD INSTR_ReplaceSelector( SIGCONTEXT *context, WORD sel)
 {
     if (sel == 0x40)
     {
         static WORD sys_timer = 0;
-        fprintf( stderr, "Direct access to segment 0x40 (cs:ip=%04x:%04lx).\n",
-                 CS_sig(context), EIP_sig(context) );
         if (!sys_timer)
             sys_timer = CreateSystemTimer( 55, (FARPROC16)DOSMEM_Tick );
         return DOSMEM_BiosSeg;
     }
-    return 0;  /* Can't replace selector */
+    return 0;  /* Can't replace selector, crashdump */
 }
 
 
diff --git a/msdos/int13.c b/msdos/int13.c
index eb9560c..1e86258 100644
--- a/msdos/int13.c
+++ b/msdos/int13.c
@@ -25,15 +25,13 @@
 		break;
 	       
 	case 0x05:                                     /* FORMAT TRACK */
+        case 0x06:             /* FORMAT TRACK AND SET BAD SECTOR FLAGS */
+        case 0x07:             /* FORMAT DRIVE STARTING AT GIVEN TRACK  */
+       /* despite of what Ralf Brown says, 0x06 and 0x07 seem to set CFLAG, too (at least my BIOS does that) */
 		AH_reg(context) = 0x0c;
                 SET_CFLAG(context);
 		break;
 
-	case 0x06:             /* FORMAT TRACK AND SET BAD SECTOR FLAGS */
-	case 0x07:             /* FORMAT DRIVE STARTING AT GIVEN TRACK  */ 
-		AH_reg(context) = 0x0c;
-		break;
-
 	case 0x08:                              /* GET DRIVE PARAMETERS  */
 		AH_reg(context) = (DL_reg(context) & 0x80) ? 0x07 : 0x01;
                 SET_CFLAG(context);
diff --git a/multimedia/audio.c b/multimedia/audio.c
index 0d5e14c..58d8365 100644
--- a/multimedia/audio.c
+++ b/multimedia/audio.c
@@ -1738,7 +1738,7 @@
  * 				AUDIO_DriverProc		[sample driver]
  */
 LONG WAVE_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg, 
-						DWORD dwParam1, DWORD dwParam2)
+		     DWORD dwParam1, DWORD dwParam2)
 {
 #if defined(linux) || defined(__FreeBSD__)
 	dprintf_mciwave(stddeb,"WAVE_DriverProc(%08lX, %04X, %04X, %08lX, %08lX)\n", 
diff --git a/multimedia/joystick.c b/multimedia/joystick.c
index cdd65ab..97f4016 100644
--- a/multimedia/joystick.c
+++ b/multimedia/joystick.c
@@ -1,5 +1,5 @@
 /*
- * Joystick functions
+ * joystick functions
  *
  * Copyright 1997 Andreas Mohr
  */
@@ -21,10 +21,10 @@
 static int count_use[4] = {0, 0, 0, 0};
 static int dev_stat;
 static int joy_nr_open = 0;
-static BOOL16 JoyCaptured = FALSE;
+static BOOL16 joyCaptured = FALSE;
 static HWND16 CaptureWnd[2] = {0, 0};
 static int joy_dev[2] = {-1, -1};
-static JOYINFO JoyCapData[2];
+static JOYINFO16 joyCapData[2];
 static unsigned int joy_threshold[2] = {0, 0};
 
 struct js_status
@@ -36,9 +36,9 @@
 
 
 /**************************************************************************
- *                              JoyOpenDriver           [internal]
+ *                              joyOpenDriver           [internal]
  */
-BOOL16 JoyOpenDriver(WORD wID)
+BOOL16 joyOpenDriver(WORD wID)
 {
 	char dev_name[] = "/dev/jsx";
 
@@ -52,9 +52,9 @@
 }
 
 /**************************************************************************
- *                              JoyCloseDriver           [internal]
+ *                              joyCloseDriver           [internal]
  */
-void JoyCloseDriver(WORD wID)
+void joyCloseDriver(WORD wID)
 {
 	if (joy_dev[wID] >= 0) {
 		close(joy_dev[wID]);
@@ -64,9 +64,9 @@
 }
 
 /**************************************************************************
- *                              JoySendMessages           [internal]
+ *                              joySendMessages           [internal]
  */
-void JoySendMessages(void)
+void joySendMessages(void)
 {
 	int joy;
         struct js_status js;
@@ -75,67 +75,146 @@
 	for (joy=0; joy < 4; joy++) 
 	if (joy_dev[joy] >= 0) {
 		if (count_use[joy] > 250) {
-			JoyCloseDriver(joy);
+			joyCloseDriver(joy);
 			count_use[joy] = 0;
 		}
 		count_use[joy]++;
 	}
 	else return;
-        if (JoyCaptured == FALSE) return;
+        if (joyCaptured == FALSE) return;
 	dprintf_mmsys(stddeb, "JoySendMessages()\n");
         for (joy=0; joy < 4; joy++) {
-		if (JoyOpenDriver(joy) == FALSE) continue;
+		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)) {
+                        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;
+                                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)
+                        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)
+                                if (joyCapData[joy].wButtons > js.buttons)
                                 SendMessage32A(CaptureWnd[joy], MM_JOY1BUTTONUP
 + joy, ButtonChanged, MAKELONG(js.x, js.y));
-                                JoyCapData[joy].wButtons = js.buttons;
+                                joyCapData[joy].wButtons = js.buttons;
                         }
                 }
         }
 }
 
+
 /**************************************************************************
  * 				JoyGetNumDevs		[MMSYSTEM.101]
  */
-WORD WINAPI JoyGetNumDevs(void)
+UINT32 WINAPI joyGetNumDevs32(void)
 {
-int joy;
-WORD joy_cnt = 0;
+	return joyGetNumDevs16();
+}
+
+/**************************************************************************
+ * 				JoyGetNumDevs		[MMSYSTEM.101]
+ */
+UINT16 WINAPI joyGetNumDevs16(void)
+{
+    int joy;
+    UINT16 joy_cnt = 0;
 
     dprintf_mmsys(stddeb, "JoyGetNumDevs: ");
     for (joy=0; joy<4; joy++)
-	if (JoyOpenDriver(joy) == TRUE) {		
-		JoyCloseDriver(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;
 }
 
 /**************************************************************************
+ * 				JoyGetDevCaps		[WINMM.27]
+ */
+MMRESULT32 WINAPI joyGetDevCaps32A(UINT32 wID, LPJOYCAPS32A lpCaps,UINT32 wSize)
+{
+	JOYCAPS16	jc16;
+	MMRESULT16	ret = joyGetDevCaps16(wID,&jc16,sizeof(jc16));
+
+	lpCaps->wMid = jc16.wMid;
+	lpCaps->wPid = jc16.wPid;
+	lstrcpy32A(lpCaps->szPname,jc16.szPname);
+        lpCaps->wXmin = jc16.wXmin;
+        lpCaps->wXmax = jc16.wXmax;
+        lpCaps->wYmin = jc16.wYmin;
+        lpCaps->wYmax = jc16.wYmax;
+        lpCaps->wZmin = jc16.wZmin;
+        lpCaps->wZmax = jc16.wZmax;
+        lpCaps->wNumButtons = jc16.wNumButtons;
+        lpCaps->wPeriodMin = jc16.wPeriodMin;
+        lpCaps->wPeriodMax = jc16.wPeriodMax;
+
+        lpCaps->wRmin = jc16.wRmin;
+        lpCaps->wRmax = jc16.wRmax;
+        lpCaps->wUmin = jc16.wUmin;
+        lpCaps->wUmax = jc16.wUmax;
+        lpCaps->wVmin = jc16.wVmin;
+        lpCaps->wVmax = jc16.wVmax;
+        lpCaps->wCaps = jc16.wCaps;
+        lpCaps->wMaxAxes = jc16.wMaxAxes;
+        lpCaps->wNumAxes = jc16.wNumAxes;
+        lpCaps->wMaxButtons = jc16.wMaxButtons;
+        lstrcpy32A(lpCaps->szRegKey,jc16.szRegKey);
+        lstrcpy32A(lpCaps->szOEMVxD,jc16.szOEMVxD);
+	return ret;
+}
+
+/**************************************************************************
+ * 				JoyGetDevCaps		[WINMM.28]
+ */
+MMRESULT32 WINAPI joyGetDevCaps32W(UINT32 wID, LPJOYCAPS32W lpCaps,UINT32 wSize)
+{
+	JOYCAPS16	jc16;
+	MMRESULT16	ret = joyGetDevCaps16(wID,&jc16,sizeof(jc16));
+
+	lpCaps->wMid = jc16.wMid;
+	lpCaps->wPid = jc16.wPid;
+	lstrcpyAtoW(lpCaps->szPname,jc16.szPname);
+        lpCaps->wXmin = jc16.wXmin;
+        lpCaps->wXmax = jc16.wXmax;
+        lpCaps->wYmin = jc16.wYmin;
+        lpCaps->wYmax = jc16.wYmax;
+        lpCaps->wZmin = jc16.wZmin;
+        lpCaps->wZmax = jc16.wZmax;
+        lpCaps->wNumButtons = jc16.wNumButtons;
+        lpCaps->wPeriodMin = jc16.wPeriodMin;
+        lpCaps->wPeriodMax = jc16.wPeriodMax;
+
+        lpCaps->wRmin = jc16.wRmin;
+        lpCaps->wRmax = jc16.wRmax;
+        lpCaps->wUmin = jc16.wUmin;
+        lpCaps->wUmax = jc16.wUmax;
+        lpCaps->wVmin = jc16.wVmin;
+        lpCaps->wVmax = jc16.wVmax;
+        lpCaps->wCaps = jc16.wCaps;
+        lpCaps->wMaxAxes = jc16.wMaxAxes;
+        lpCaps->wNumAxes = jc16.wNumAxes;
+        lpCaps->wMaxButtons = jc16.wMaxButtons;
+        lstrcpyAtoW(lpCaps->szRegKey,jc16.szRegKey);
+        lstrcpyAtoW(lpCaps->szOEMVxD,jc16.szOEMVxD);
+	return ret;
+}
+/**************************************************************************
  * 				JoyGetDevCaps		[MMSYSTEM.102]
  */
-WORD WINAPI JoyGetDevCaps(WORD wID, LPJOYCAPS lpCaps, WORD wSize)
+MMRESULT16 WINAPI joyGetDevCaps16(UINT16 wID, LPJOYCAPS16 lpCaps, UINT16 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) {
+    if (joyOpenDriver(wID) == TRUE) {
         lpCaps->wMid = MM_MICROSOFT;
         lpCaps->wPid = MM_PC_JOYSTICK;
         strcpy(lpCaps->szPname, "WineJoy"); /* joystick product name */
@@ -148,8 +227,22 @@
         lpCaps->wNumButtons = 2;
         lpCaps->wPeriodMin = 0;
         lpCaps->wPeriodMax = 50; /* FIXME end */
-
-	JoyCloseDriver(wID);
+	if (wSize == sizeof(JOYCAPS16)) {
+		/* complete 95 structure */
+		lpCaps->wRmin = 0;
+		lpCaps->wRmax = 0xffff;
+		lpCaps->wUmin = 0;
+		lpCaps->wUmax = 0xffff;
+		lpCaps->wVmin = 0;
+		lpCaps->wVmax = 0xffff;
+		lpCaps->wCaps = 0;
+		lpCaps->wMaxAxes = 6;
+		lpCaps->wNumAxes = 2;
+		lpCaps->wMaxButtons = 3;
+		strcpy(lpCaps->szRegKey,"");
+		strcpy(lpCaps->szOEMVxD,"");
+	}
+	joyCloseDriver(wID);
         return JOYERR_NOERROR;
     }
     else
@@ -157,17 +250,32 @@
 }
 
 /**************************************************************************
+ * 				JoyGetPos	       	[WINMM.30]
+ */
+MMRESULT32 WINAPI joyGetPos32(UINT32 wID, LPJOYINFO32 lpInfo)
+{
+	JOYINFO16	ji;
+	MMRESULT16	ret = joyGetPos16(wID,&ji);
+
+	lpInfo->wXpos = ji.wXpos;
+	lpInfo->wYpos = ji.wYpos;
+	lpInfo->wZpos = ji.wZpos;
+	lpInfo->wButtons = ji.wButtons;
+	return ret;
+}
+
+/**************************************************************************
  * 				JoyGetPos	       	[MMSYSTEM.103]
  */
-WORD WINAPI JoyGetPos(WORD wID, LPJOYINFO lpInfo)
+MMRESULT16 WINAPI joyGetPos16(UINT16 wID, LPJOYINFO16 lpInfo)
 {
         struct js_status js;
 
         dprintf_mmsys(stderr, "JoyGetPos(%04X, %p):", wID, lpInfo);
-        if (JoyOpenDriver(wID) == FALSE) return MMSYSERR_NODRIVER;
+        if (joyOpenDriver(wID) == FALSE) return MMSYSERR_NODRIVER;
 	dev_stat = read(joy_dev[wID], &js, sizeof(js));
 	if (dev_stat != sizeof(js)) {
-		JoyCloseDriver(wID);
+		joyCloseDriver(wID);
 		return JOYERR_UNPLUGGED; /* FIXME: perhaps wrong, but what should I return else ? */
 	}
 	count_use[wID] = 0;
@@ -182,9 +290,21 @@
 }
 
 /**************************************************************************
+ * 				JoyGetThreshold		[WINMM.32]
+ */
+MMRESULT32 WINAPI joyGetThreshold32(UINT32 wID, LPUINT32 lpThreshold)
+{
+	UINT16		thresh;
+	MMRESULT16	ret = joyGetThreshold16(wID,&thresh);
+
+	*lpThreshold = thresh;
+	return ret;
+}
+
+/**************************************************************************
  * 				JoyGetThreshold		[MMSYSTEM.104]
  */
-WORD WINAPI JoyGetThreshold(WORD wID, LPWORD lpThreshold)
+MMRESULT16 WINAPI joyGetThreshold16(UINT16 wID, LPUINT16 lpThreshold)
 {
     dprintf_mmsys(stderr, "JoyGetThreshold(%04X, %p);\n", wID, lpThreshold);
     if (wID > 3) return JOYERR_PARMS;
@@ -193,13 +313,21 @@
 }
 
 /**************************************************************************
+ * 				JoyReleaseCapture	[WINMM.33]
+ */
+MMRESULT32 WINAPI joyReleaseCapture32(UINT32 wID)
+{
+	return joyReleaseCapture16(wID);
+}
+
+/**************************************************************************
  * 				JoyReleaseCapture	[MMSYSTEM.105]
  */
-WORD WINAPI JoyReleaseCapture(WORD wID)
+MMRESULT16 WINAPI joyReleaseCapture16(UINT16 wID)
 {
     dprintf_mmsys(stderr, "JoyReleaseCapture(%04X);\n", wID);
-    JoyCaptured = FALSE;
-    JoyCloseDriver(wID);
+    joyCaptured = FALSE;
+    joyCloseDriver(wID);
     joy_dev[wID] = -1;
     CaptureWnd[wID] = 0;
     return JOYERR_NOERROR;
@@ -208,15 +336,23 @@
 /**************************************************************************
  * 				JoySetCapture		[MMSYSTEM.106]
  */
-WORD WINAPI JoySetCapture(HWND16 hWnd, WORD wID, WORD wPeriod, BOOL16 bChanged)
+MMRESULT32 WINAPI joySetCapture32(HWND32 hWnd,UINT32 wID,UINT32 wPeriod,BOOL32 bChanged)
+{
+	return joySetCapture16(hWnd,wID,wPeriod,bChanged);
+}
+
+/**************************************************************************
+ * 				JoySetCapture		[MMSYSTEM.106]
+ */
+MMRESULT16 WINAPI joySetCapture16(HWND16 hWnd,UINT16 wID,UINT16 wPeriod,BOOL16 bChanged)
 {
 
     dprintf_mmsys(stderr, "JoySetCapture(%04X, %04X, %d, %d);\n",
 	    hWnd, wID, wPeriod, bChanged);
 
     if (!CaptureWnd[wID]) {
-	if (JoyOpenDriver(wID) == FALSE) return MMSYSERR_NODRIVER;
-	JoyCaptured = TRUE;
+	if (joyOpenDriver(wID) == FALSE) return MMSYSERR_NODRIVER;
+	joyCaptured = TRUE;
 	CaptureWnd[wID] = hWnd;
 	return JOYERR_NOERROR;
     }
@@ -225,9 +361,16 @@
 }
 
 /**************************************************************************
+ * 				JoySetThreshold		[WINMM.35]
+ */
+MMRESULT32 WINAPI joySetThreshold32(UINT32 wID, UINT32 wThreshold)
+{
+	return joySetThreshold16(wID,wThreshold);
+}
+/**************************************************************************
  * 				JoySetThreshold		[MMSYSTEM.107]
  */
-WORD WINAPI JoySetThreshold(WORD wID, WORD wThreshold)
+MMRESULT16 WINAPI joySetThreshold16(UINT16 wID, UINT16 wThreshold)
 {
     dprintf_mmsys(stderr, "JoySetThreshold(%04X, %d);\n", wID, wThreshold);
 
@@ -239,8 +382,8 @@
 /**************************************************************************
  * 				JoySetCalibration	[MMSYSTEM.109]
  */
-WORD WINAPI JoySetCalibration(WORD wID)
+MMRESULT16 WINAPI joySetCalibration16(UINT16 wID)
 {
-    fprintf(stderr, "EMPTY STUB !!! JoySetCalibration(%04X);\n", wID);
+    fprintf(stderr, "EMPTY STUB !!! joySetCalibration(%04X);\n", wID);
     return JOYERR_NOCANDO;
 }
diff --git a/multimedia/mcianim.c b/multimedia/mcianim.c
index 7b44e39..39fcdf1 100644
--- a/multimedia/mcianim.c
+++ b/multimedia/mcianim.c
@@ -605,7 +605,7 @@
 * 				ANIM_DriverProc		[sample driver]
 */
 LONG ANIM_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg, 
-							DWORD dwParam1, DWORD dwParam2)
+		     DWORD dwParam1, DWORD dwParam2)
 {
 #if defined(linux) || defined(__FreeBSD__)
 	switch(wMsg) {
diff --git a/multimedia/mcicda.c b/multimedia/mcicda.c
index d92d840..65a3375 100644
--- a/multimedia/mcicda.c
+++ b/multimedia/mcicda.c
@@ -1026,7 +1026,7 @@
 * 				CDAUDIO_DriverProc		[sample driver]
 */
 LONG CDAUDIO_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg, 
-							DWORD dwParam1, DWORD dwParam2)
+			DWORD dwParam1, DWORD dwParam2)
 {
 #if defined(linux) || defined(__FreeBSD__)
 	switch(wMsg) {
diff --git a/multimedia/mcistring.c b/multimedia/mcistring.c
index 298bd5c..88cf60a 100644
--- a/multimedia/mcistring.c
+++ b/multimedia/mcistring.c
@@ -23,20 +23,17 @@
 #include "user.h"
 #include "driver.h"
 #include "mmsystem.h"
+#include "callback.h"
 #include "stddebug.h"
 #include "debug.h"
 #include "xmalloc.h"
 
 
-extern MCI_OPEN_DRIVER_PARMS	mciDrv[MAXMCIDRIVERS];
-
-/* FIXME: I need to remember the aliasname of a spec. driver. 
- *        and this is the easiest way. *sigh*
- */
-extern MCI_OPEN_PARMS16		mciOpenDrv[MAXMCIDRIVERS];
+extern struct LINUX_MCIDRIVER mciDrv[MAXMCIDRIVERS];
 
 #define GetDrv(wDevID) (&mciDrv[MMSYSTEM_DevIDToIndex(wDevID)])
-#define GetOpenDrv(wDevID) (&mciOpenDrv[MMSYSTEM_DevIDToIndex(wDevID)])
+#define GetOpenDrv(wDevID) (&(GetDrv(wDevID)->mop))
+
 extern int MMSYSTEM_DevIDToIndex(UINT16 wDevID);
 extern UINT16 MMSYSTEM_FirstDevID(void);
 extern UINT16 MMSYSTEM_NextDevID(UINT16 wDevID);
@@ -80,24 +77,25 @@
 #define _MCI_CALL_DRIVER(cmd,params) \
 	switch(uDevTyp) {\
 	case MCI_DEVTYPE_CD_AUDIO:\
-		res=CDAUDIO_DriverProc(GetDrv(wDevID)->wDeviceID,0,cmd,dwFlags, (DWORD)(params));\
+		res=CDAUDIO_DriverProc(GetDrv(wDevID)->modp.wDeviceID,0,cmd,dwFlags, (DWORD)(params));\
 		break;\
 	case MCI_DEVTYPE_WAVEFORM_AUDIO:\
-		res=WAVE_DriverProc(GetDrv(wDevID)->wDeviceID,0,cmd,dwFlags,(DWORD)(params));\
+		res=WAVE_DriverProc(GetDrv(wDevID)->modp.wDeviceID,0,cmd,dwFlags,(DWORD)(params));\
 		break;\
 	case MCI_DEVTYPE_SEQUENCER:\
-		res=MIDI_DriverProc(GetDrv(wDevID)->wDeviceID,0,cmd,dwFlags,(DWORD)(params));\
+		res=MIDI_DriverProc(GetDrv(wDevID)->modp.wDeviceID,0,cmd,dwFlags,(DWORD)(params));\
 		break;\
 	case MCI_DEVTYPE_ANIMATION:\
-		res=ANIM_DriverProc(GetDrv(wDevID)->wDeviceID,0,cmd,dwFlags,(DWORD)(params));\
+		res=ANIM_DriverProc(GetDrv(wDevID)->modp.wDeviceID,0,cmd,dwFlags,(DWORD)(params));\
 		break;\
 	case MCI_DEVTYPE_DIGITAL_VIDEO:\
 		dprintf_mci(stddeb,"_MCI_CALL_DRIVER //No DIGITAL_VIDEO yet !\n");\
 		res=MCIERR_DEVICE_NOT_INSTALLED;\
 		break;\
 	default:\
-		dprintf_mci(stddeb,"_MCI_CALL_DRIVER //Invalid Device Name '%s' !\n",dev);\
-		res=MCIERR_INVALID_DEVICE_NAME;\
+		/*res = Callbacks->CallDriverProc(GetDrv(wDevID)->driverproc,GetDrv(wDevID)->modp.wDeviceID,GetDrv(wDevID)->hdrv,cmd,dwFlags,(DWORD)(params));\
+		break;*/\
+		res = MCIERR_DEVICE_NOT_INSTALLED;\
 		break;\
 	}
 /* print a DWORD in the specified timeformat */
@@ -335,17 +333,17 @@
 		return MCIERR_INVALID_DEVICE_NAME;
 	}
 	wDevID=MMSYSTEM_FirstDevID();
-	while(GetDrv(wDevID)->wType) {
+	while(GetDrv(wDevID)->modp.wType) {
 		wDevID = MMSYSTEM_NextDevID(wDevID);
 		if (!MMSYSTEM_DevIDValid(wDevID)) {
-			dprintf_mci(stddeb, __FILE__":MCISTR_Open:MAXMCIDRIVERS reached!\n");
+			dprintf_mci(stddeb, __FILE__":MCISTR_Open:MAXMCIDRIVERS reached (%x) !\n", wDevID);
 			SEGPTR_FREE(PTR_SEG_TO_LIN(pU->openParams.lpstrElementName));
 			SEGPTR_FREE(pU);
 			return MCIERR_INTERNAL;
 		}
 	}
-	GetDrv(wDevID)->wType		= uDevTyp;
-	GetDrv(wDevID)->wDeviceID	= 0;  /* FIXME? for multiple devices */
+	GetDrv(wDevID)->modp.wType	= uDevTyp;
+	GetDrv(wDevID)->modp.wDeviceID	= 0;  /* FIXME? for multiple devices */
 	pU->openParams.dwCallback	= hwndCallback ;
 	pU->openParams.wDeviceID	= wDevID;
 	pU->ovlyopenParams.dwStyle	= 0; 
@@ -2190,7 +2188,7 @@
 				return MCIERR_INVALID_DEVICE_NAME;
 			}
 		}
-		uDevTyp=GetDrv(wDevID)->wType;
+		uDevTyp=GetDrv(wDevID)->modp.wType;
 	}
 
  	for (i=0;MCISTR_cmdtable[i].cmd!=NULL;i++) {
diff --git a/multimedia/midi.c b/multimedia/midi.c
index 471a4d1..f38d5dd 100644
--- a/multimedia/midi.c
+++ b/multimedia/midi.c
@@ -1347,7 +1347,7 @@
  * 				MIDI_DriverProc		[sample driver]
  */
 LONG MIDI_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg, 
-						DWORD dwParam1, DWORD dwParam2)
+		     DWORD dwParam1, DWORD dwParam2)
 {
 #if defined(linux) || defined(__FreeBSD__)
 	switch(wMsg) {
diff --git a/multimedia/mixer.c b/multimedia/mixer.c
index 14ec17a..89f9394 100644
--- a/multimedia/mixer.c
+++ b/multimedia/mixer.c
@@ -39,7 +39,6 @@
 {
 #ifdef linux
 	int 		mixer,mask;
-	struct	mixer_info	mi;
 
 	dprintf_mmaux(stddeb,"MIX_GetDevCaps(%04X, %p, %lu);\n", wDevID, lpCaps, dwSize);
 	if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
@@ -47,16 +46,10 @@
 		dprintf_mmaux(stddeb,"MIX_GetDevCaps // mixer device not available !\n");
 		return MMSYSERR_NOTENABLED;
 	}
-	if (ioctl(mixer, SOUND_MIXER_INFO, &mi) == -1) {
-		close(mixer);
-		perror("ioctl mixer SOUND_MIXER_INFO");
-		return MMSYSERR_NOTENABLED;
-	}
-	fprintf(stderr,"SOUND_MIXER_INFO returns { \"%s\",\"%s\" }\n",mi.id,mi.name);
 	lpCaps->wMid = 0xAA;
 	lpCaps->wPid = 0x55;
 	lpCaps->vDriverVersion = 0x0100;
-	strcpy(lpCaps->szPname,mi.name);
+	strcpy(lpCaps->szPname,"WINE Generic Mixer");
 	if (ioctl(mixer, SOUND_MIXER_READ_DEVMASK, &mask) == -1) {
 		close(mixer);
 		perror("ioctl mixer SOUND_MIXER_DEVMASK");
diff --git a/multimedia/mmsystem.c b/multimedia/mmsystem.c
index 159e78f..ad9d211 100644
--- a/multimedia/mmsystem.c
+++ b/multimedia/mmsystem.c
@@ -23,6 +23,7 @@
 #include "file.h"
 #include "mmsystem.h"
 #include "stddebug.h"
+/* #define DEBUG_MMSYS */
 #include "debug.h"
 #include "xmalloc.h"
 #include "callback.h"
@@ -31,11 +32,7 @@
 static int	InstalledListLen;
 static LPSTR	lpInstallNames = NULL;
 
-MCI_OPEN_DRIVER_PARMS	mciDrv[MAXMCIDRIVERS];
-/* struct below is to remember alias/devicenames for mcistring.c 
- * FIXME: should use some internal struct ... 
- */
-MCI_OPEN_PARMS16 mciOpenDrv[MAXMCIDRIVERS];
+struct LINUX_MCIDRIVER mciDrv[MAXMCIDRIVERS];
 
 UINT16 midiGetErrorText(UINT16 uError, LPSTR lpText, UINT16 uSize);
 static UINT16 waveGetErrorText(UINT16 uError, LPSTR lpText, UINT16 uSize);
@@ -53,7 +50,7 @@
 
 
 #define GetDrv(wDevID) (&mciDrv[MMSYSTEM_DevIDToIndex(wDevID)])
-#define GetOpenDrv(wDevID) (&mciOpenDrv[MMSYSTEM_DevIDToIndex(wDevID)])
+#define GetOpenDrv(wDevID) (&(GetDrv(wDevID)->mop))
 
 /* The wDevID's returned by wine were originally in the range 
  * 0 - (MAXMCIDRIVERS - 1) and used directly as array indices.
@@ -122,25 +119,22 @@
 }
 
 /**************************************************************************
-* 				PlaySoundA		[WINMM.1]
-*/
+ * 				PlaySoundA		[WINMM.1]
+ */
 BOOL32 WINAPI PlaySound32A(LPCSTR pszSound, HMODULE32 hmod, DWORD fdwSound)
 {
-  dprintf_mmsys(stddeb, "PlaySoundA: pszSound='%s' hmod=%04X fdwSound=%08lX\n",
+  dprintf_mmsys(stddeb, "PlaySoundA: pszSound='%p' hmod=%04X fdwSound=%08lX\n",
 		pszSound, hmod, fdwSound);
   if(hmod != 0 || !(fdwSound & SND_FILENAME)) {
     fprintf(stderr, "PlaySoundA: only disk sound files are supported\n");
     return FALSE;
-  } else {
-    BOOL16 bSound;
-    bSound = sndPlaySound(pszSound, (UINT16) fdwSound);
-    return (BOOL32) bSound;
-  }
+  } else
+    return  sndPlaySound(pszSound, (UINT16) fdwSound);
 }
 
 /**************************************************************************
-* 				PlaySoundW		[WINMM.18]
-*/
+ * 				PlaySoundW		[WINMM.18]
+ */
 BOOL32 WINAPI PlaySound32W(LPCWSTR pszSound, HMODULE32 hmod, DWORD fdwSound)
 {
   LPSTR pszSoundA = HEAP_strdupWtoA(GetProcessHeap(),0,pszSound);
@@ -537,7 +531,7 @@
 /**************************************************************************
  * 				mixerGetLineControlsA	[WINMM.104]
  */
-UINT32 mixerGetLineControls32A(HMIXEROBJ32 hmix,LPMIXERLINECONTROLS32A lpmlc,DWORD fdwControls) {
+UINT32 WINAPI mixerGetLineControls32A(HMIXEROBJ32 hmix,LPMIXERLINECONTROLS32A lpmlc,DWORD fdwControls) {
 	fprintf(stderr,"mixerGetLineControlsA(%04x,%p,%08lx),stub!\n",
 		hmix,lpmlc,fdwControls
 	);
@@ -547,7 +541,7 @@
 /**************************************************************************
  * 				mixerGetLineControlsW	[WINMM.105]
  */
-UINT32 mixerGetLineControls32W(HMIXEROBJ32 hmix,LPMIXERLINECONTROLS32W lpmlc,DWORD fdwControls) {
+UINT32 WINAPI mixerGetLineControls32W(HMIXEROBJ32 hmix,LPMIXERLINECONTROLS32W lpmlc,DWORD fdwControls) {
 	fprintf(stderr,"mixerGetLineControlsA(%04x,%p,%08lx),stub!\n",
 		hmix,lpmlc,fdwControls
 	);
@@ -557,7 +551,7 @@
 /**************************************************************************
  * 				mixerGetLineControls	[MMSYSTEM.807]
  */
-UINT16 mixerGetLineControls16(HMIXEROBJ16 hmix,LPMIXERLINECONTROLS16 lpmlc,DWORD fdwControls) {
+UINT16 WINAPI mixerGetLineControls16(HMIXEROBJ16 hmix,LPMIXERLINECONTROLS16 lpmlc,DWORD fdwControls) {
 	fprintf(stderr,"mixerGetLineControls(%04x,%p,%08lx),stub!\n",
 		hmix,lpmlc,fdwControls
 	);
@@ -567,7 +561,7 @@
 /**************************************************************************
  * 				mixerGetLineInfoA	[WINMM.106]
  */
-UINT32 mixerGetLineInfo32A(HMIXEROBJ32 hmix,LPMIXERLINE32A lpml,DWORD fdwInfo) {
+UINT32 WINAPI mixerGetLineInfo32A(HMIXEROBJ32 hmix,LPMIXERLINE32A lpml,DWORD fdwInfo) {
 	MIXERLINE16	ml16;
 	UINT32		ret;
 
@@ -599,7 +593,7 @@
 /**************************************************************************
  * 				mixerGetLineInfoW	[WINMM.107]
  */
-UINT32 mixerGetLineInfo32W(HMIXEROBJ32 hmix,LPMIXERLINE32W lpml,DWORD fdwInfo) {
+UINT32 WINAPI mixerGetLineInfo32W(HMIXEROBJ32 hmix,LPMIXERLINE32W lpml,DWORD fdwInfo) {
 	MIXERLINE16	ml16;
 	UINT32		ret;
 
@@ -631,7 +625,7 @@
 /**************************************************************************
  * 				mixerGetLineInfo	[MMSYSTEM.805]
  */
-UINT16 mixerGetLineInfo16(HMIXEROBJ16 hmix,LPMIXERLINE16 lpml,DWORD fdwInfo) {
+UINT16 WINAPI mixerGetLineInfo16(HMIXEROBJ16 hmix,LPMIXERLINE16 lpml,DWORD fdwInfo) {
 	UINT16 devid =  _get_mixerID_from_handle(hmix,fdwInfo);
 
 	fprintf(stderr,"mixerGetLineInfo16(%04x,%p[line %08lx],%08lx)\n",
@@ -643,7 +637,7 @@
 /**************************************************************************
  * 				mixerSetControlDetails	[WINMM.111]
  */
-UINT32 mixerSetControlDetails32(HMIXEROBJ32 hmix,LPMIXERCONTROLDETAILS32 lpmcd,DWORD fdwDetails) {
+UINT32 WINAPI mixerSetControlDetails32(HMIXEROBJ32 hmix,LPMIXERCONTROLDETAILS32 lpmcd,DWORD fdwDetails) {
 	fprintf(stderr,"mixerSetControlDetails32(%04x,%p,%08lx),stub!\n",
 		hmix,lpmcd,fdwDetails
 	);
@@ -653,7 +647,7 @@
 /**************************************************************************
  * 				mixerSetControlDetails	[MMSYSTEM.809]
  */
-UINT16 mixerSetControlDetails16(HMIXEROBJ16 hmix,LPMIXERCONTROLDETAILS16 lpmcd,DWORD fdwDetails) {
+UINT16 WINAPI mixerSetControlDetails16(HMIXEROBJ16 hmix,LPMIXERCONTROLDETAILS16 lpmcd,DWORD fdwDetails) {
 	fprintf(stderr,"mixerSetControlDetails16(%04x,%p,%08lx),stub!\n",
 		hmix,lpmcd,fdwDetails
 	);
@@ -663,7 +657,7 @@
 /**************************************************************************
  * 				mixerMessage		[WINMM.109]
  */
-UINT32 mixerMessage32(HMIXER32 hmix,UINT32 uMsg,DWORD dwParam1,DWORD dwParam2) {
+UINT32 WINAPI mixerMessage32(HMIXER32 hmix,UINT32 uMsg,DWORD dwParam1,DWORD dwParam2) {
 	LPMIXEROPENDESC	lpmod;
 	UINT16	uDeviceID;
 
@@ -679,7 +673,7 @@
 /**************************************************************************
  * 				mixerMessage		[MMSYSTEM.804]
  */
-UINT16 mixerMessage16(HMIXER16 hmix,UINT16 uMsg,DWORD dwParam1,DWORD dwParam2) {
+UINT16 WINAPI mixerMessage16(HMIXER16 hmix,UINT16 uMsg,DWORD dwParam1,DWORD dwParam2) {
 	LPMIXEROPENDESC	lpmod;
 	UINT16	uDeviceID;
 
@@ -1164,7 +1158,7 @@
 	dprintf_mmsys(stddeb, "mciOpen(%08lX, %p (%p))\n", dwParam, lp16Parms, lpParms);
 	if (lp16Parms == NULL) return MCIERR_INTERNAL;
 
-	while(GetDrv(wDevID)->wType != 0) {
+	while(GetDrv(wDevID)->modp.wType != 0) {
 		wDevID = MMSYSTEM_NextDevID(wDevID);
 		if (!MMSYSTEM_DevIDValid(wDevID)) {
 			dprintf_mmsys(stddeb, "MCI_OPEN // MAXMCIDRIVERS reached !\n");
@@ -1204,8 +1198,21 @@
 			if (strcmp(str,"*") == 0) {
 				dprintf_mmsys(stddeb,"No [mci extensions] entry for %s found.\n",t);
 				return MCIERR_EXTENSION_NOT_FOUND;
+#if testing16
 			} else  {
-				dprintf_mmsys(stddeb,"[mci extensions] entry %s for %s not supported.\n",str,t);
+				HDRVR16 hdrv = OpenDriver(str,"mci",NULL);
+				if (hdrv) {
+					HMODULE16	hmod;
+
+					hmod = GetDriverModuleHandle(hdrv);
+					GetDrv(wDevID)->hdrv = hdrv;
+					GetDrv(wDevID)->driverproc = GetProcAddress16(hmod,SEGPTR_GET(SEGPTR_STRDUP("DRIVERPROC")));
+					uDevTyp = MCI_DEVTYPE_OTHER;
+				} else {
+					dprintf_mmsys(stddeb,"[mci extensions] entry %s for %s not supported.\n",str,t);
+					return MCIERR_DEVICE_NOT_INSTALLED;
+				}
+#endif
 			}
 		} else
 			return MCIERR_EXTENSION_NOT_FOUND;
@@ -1245,11 +1252,26 @@
 			} else
 			if (strcmp(str, "AVIVIDEO") == 0) {
 				uDevTyp = MCI_DEVTYPE_DIGITAL_VIDEO;
+			} else {
+#if testing16
+				HDRVR16 hdrv;
+				fprintf(stderr,"trying to load driver...\n");
+				hdrv = OpenDriver(str,"mci",NULL);
+				if (hdrv) {
+					HMODULE16	hmod;
+
+					hmod = GetDriverModuleHandle(hdrv);
+					GetDrv(wDevID)->hdrv = hdrv;
+					GetDrv(wDevID)->driverproc = GetProcAddress16(hmod,SEGPTR_GET(SEGPTR_STRDUP("DRIVERPROC")));
+					uDevTyp = MCI_DEVTYPE_OTHER;
+				} else
+#endif
+					return MCIERR_DEVICE_NOT_INSTALLED;
 			}
 		}
 	}
-	GetDrv(wDevID)->wType = uDevTyp;
-	GetDrv(wDevID)->wDeviceID = 0;  /* FIXME? for multiple devices */
+	GetDrv(wDevID)->modp.wType = uDevTyp;
+	GetDrv(wDevID)->modp.wDeviceID = 0;  /* FIXME? for multiple devices */
 	lpParms->wDeviceID = wDevID;
 	dprintf_mmsys(stddeb, "MCI_OPEN // mcidev=%d, uDevTyp=%04X wDeviceID=%04X !\n", 
 				wDevID, uDevTyp, lpParms->wDeviceID);
@@ -1263,7 +1285,7 @@
 	  dwret =  WAVE_DriverProc( 0, 0, MCI_OPEN_DRIVER, 
 				   dwParam, (DWORD)lp16Parms);
 	  break;
-        case MCI_DEVTYPE_SEQUENCER:
+	case MCI_DEVTYPE_SEQUENCER:
 	  dwret = MIDI_DriverProc( 0, 0, MCI_OPEN_DRIVER, 
 				  dwParam, (DWORD)lp16Parms);
 	  break;
@@ -1275,7 +1297,10 @@
 	  dprintf_mmsys(stddeb, "MCI_OPEN // No DIGITAL_VIDEO yet !\n");
 	  return MCIERR_DEVICE_NOT_INSTALLED;
         default:
+#if testing16
+	  dwret = Callbacks->CallDriverProc(GetDrv(wDevID)->driverproc,0,GetDrv(wDevID)->hdrv,MCI_OPEN_DRIVER,dwParam,(DWORD)lp16Parms);
 	  dprintf_mmsys(stddeb, "MCI_OPEN // Invalid Device Name '%08lx' !\n", (DWORD)lpParms->lpstrDeviceType);
+#endif
 	  return MCIERR_INVALID_DEVICE_NAME;
         }
 
@@ -1289,40 +1314,56 @@
 	return dwret;
 }
 
+/**************************************************************************
+ * 			mciGetDriverData			[MMSYSTEM.708]
+ */
+DWORD WINAPI mciGetDriverData16(HDRVR16 hdrv) {
+	fprintf(stderr,"mciGetDriverData(%04x),stub!\n",hdrv);
+	return 0x42;
+}
 
 /**************************************************************************
-* 				mciClose				[internal]
-*/
+ * 			mciSetDriverData			[MMSYSTEM.707]
+ */
+DWORD WINAPI mciSetDriverData16(HDRVR16 hdrv,DWORD data) {
+	fprintf(stderr,"mciSetDriverData(%04x,%08lx),stub!\n",hdrv,data);
+	return 0;
+}
+
+/**************************************************************************
+ * 			mciClose				[internal]
+ */
 DWORD mciClose(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
 {
 	DWORD	dwRet = MCIERR_INTERNAL;
 
 	dprintf_mmsys(stddeb, "mciClose(%04x, %08lX, %p)\n", wDevID, dwParam, lpParms);
-	switch(GetDrv(wDevID)->wType) {
-		case MCI_DEVTYPE_CD_AUDIO:
-			dwRet = CDAUDIO_DriverProc(GetDrv(wDevID)->wDeviceID,0,
-                                           MCI_CLOSE, dwParam, (DWORD)lpParms);
-			break;
-		case MCI_DEVTYPE_WAVEFORM_AUDIO:
-			dwRet = WAVE_DriverProc(GetDrv(wDevID)->wDeviceID, 0, 
-						MCI_CLOSE, dwParam,
-                                                (DWORD)lpParms);
-			break;
-		case MCI_DEVTYPE_SEQUENCER:
-			dwRet = MIDI_DriverProc(GetDrv(wDevID)->wDeviceID, 0, 
-						MCI_CLOSE, dwParam,
-                                                (DWORD)lpParms);
-			break;
-		case MCI_DEVTYPE_ANIMATION:
-			dwRet = ANIM_DriverProc(GetDrv(wDevID)->wDeviceID, 0, 
-						MCI_CLOSE, dwParam,
-                                                (DWORD)lpParms);
-			break;
-		default:
-			dprintf_mmsys(stddeb, "mciClose() // unknown device type=%04X !\n", GetDrv(wDevID)->wType);
-			dwRet = MCIERR_DEVICE_NOT_INSTALLED;
-		}
-	GetDrv(wDevID)->wType = 0;
+	switch(GetDrv(wDevID)->modp.wType) {
+	case MCI_DEVTYPE_CD_AUDIO:
+		dwRet = CDAUDIO_DriverProc(GetDrv(wDevID)->modp.wDeviceID,0,
+				   MCI_CLOSE, dwParam, (DWORD)lpParms);
+		break;
+	case MCI_DEVTYPE_WAVEFORM_AUDIO:
+		dwRet = WAVE_DriverProc(GetDrv(wDevID)->modp.wDeviceID, 0, 
+					MCI_CLOSE, dwParam,
+					(DWORD)lpParms);
+		break;
+	case MCI_DEVTYPE_SEQUENCER:
+		dwRet = MIDI_DriverProc(GetDrv(wDevID)->modp.wDeviceID, 0, 
+					MCI_CLOSE, dwParam,
+					(DWORD)lpParms);
+		break;
+	/*
+	case MCI_DEVTYPE_ANIMATION:
+		dwRet = ANIM_DriverProc(GetDrv(wDevID)->modp.wDeviceID, 0, 
+					MCI_CLOSE, dwParam,
+					(DWORD)lpParms);
+		break;
+	 */
+	default:
+		dwRet = Callbacks->CallDriverProc(GetDrv(wDevID)->driverproc,GetDrv(wDevID)->modp.wDeviceID,GetDrv(wDevID)->hdrv,MCI_CLOSE,dwParam,(DWORD)lpParms);
+	}
+	GetDrv(wDevID)->modp.wType = 0;
 
 	if (dwParam&MCI_NOTIFY)
 	  mciDriverNotify(lpParms->dwCallback,wDevID,
@@ -1334,8 +1375,8 @@
 
 
 /**************************************************************************
-* 			mciSysinfo				[internal]
-*/
+ * 			mciSysinfo				[internal]
+ */
 DWORD mciSysInfo(DWORD dwFlags, LPMCI_SYSINFO_PARMS16 lpParms)
 {
 	int	len;
@@ -1382,6 +1423,63 @@
 }
 
 /**************************************************************************
+ *                    	mciLoadCommandResource
+ */
+UINT16 mciLoadCommandResource16(HANDLE16 hinst,LPCSTR resname,UINT16 type)
+{
+      char            buf[200];
+      OFSTRUCT        ofs;
+      HANDLE16        xhinst;
+      HRSRC16         hrsrc;
+      HGLOBAL16       hmem;
+      LPSTR           segstr;
+      SEGPTR          xmem;
+      LPBYTE          lmem;
+      static          mcidevtype = 0;
+
+      fprintf(stderr,"mciLoadCommandResource16(%04x,%s,%d),stub!\n",
+              hinst,resname,type
+      );
+      if (!lstrcmpi32A(resname,"core")) {
+              fprintf(stderr,"mciLoadCommandResource(...,\"core\",...), have to use internal tables... (not there yet)\n");
+              return 0;
+      }
+      /* if file exists "resname.mci", then load resource "resname" from it
+       * otherwise directly from driver
+       */
+      strcpy(buf,resname);
+      strcat(buf,".mci");
+      if (OpenFile32(buf,&ofs,OF_EXIST)!=HFILE_ERROR32) {
+              xhinst = LoadLibrary16(buf);
+              if (xhinst >32)
+                      hinst = xhinst;
+      } /* else use passed hinst */
+      segstr = SEGPTR_STRDUP(resname);
+      hrsrc = FindResource16(hinst,SEGPTR_GET(segstr),type);
+      SEGPTR_FREE(segstr);
+      if (!hrsrc) {
+              fprintf(stderr,"mciLoadCommandResource:no special commandlist found in resource\n");
+              return MCI_NO_COMMAND_TABLE;
+      }
+      hmem = LoadResource16(hinst,hrsrc);
+      if (!hmem) {
+              fprintf(stderr,"mciLoadCommandResource:couldn't load resource??\n");
+              return MCI_NO_COMMAND_TABLE;
+      }
+      xmem = WIN16_LockResource16(hmem);
+      if (!xmem) {
+              fprintf(stderr,"mciLoadCommandResource:couldn't lock resource??\n");
+              FreeResource16(hmem);
+              return MCI_NO_COMMAND_TABLE;
+      }
+      lmem = PTR_SEG_TO_LIN(xmem);
+      fprintf(stderr,"first resource entry is %s\n",(char*)lmem);
+      /* parse resource, register stuff, return unique id */
+      return ++mcidevtype;
+}
+
+
+/**************************************************************************
  * 			mciSound				[internal]
  *  not used anymore ??
 
@@ -1441,8 +1539,19 @@
 }
 
 /**************************************************************************
-* 				mciSendCommand			[MMSYSTEM.701]
-*/
+ * 				mciSendCommandA			[WINMM.49]
+ */
+DWORD WINAPI mciSendCommand32A(UINT32 wDevID, UINT32 wMsg, DWORD dwParam1,
+                            DWORD dwParam2)
+{
+	fprintf(stderr,"mciSendCommand32A(%08x,%08x,%08lx,%08lx),stub!\n",
+		wDevID,wMsg,dwParam1,dwParam2
+	);
+	return 0; /* ok */
+}
+/**************************************************************************
+ * 				mciSendCommand			[MMSYSTEM.701]
+ */
 DWORD WINAPI mciSendCommand(UINT16 wDevID, UINT16 wMsg, DWORD dwParam1,
                             DWORD dwParam2)
 {
@@ -1460,24 +1569,28 @@
         return mciSysInfo( dwParam1,
                            (LPMCI_SYSINFO_PARMS16)PTR_SEG_TO_LIN(dwParam2));
     default:
-        switch(GetDrv(wDevID)->wType)
+        switch(GetDrv(wDevID)->modp.wType)
         {
         case MCI_DEVTYPE_CD_AUDIO:
-            return CDAUDIO_DriverProc(GetDrv(wDevID)->wDeviceID, hDrv, 
+            return CDAUDIO_DriverProc(GetDrv(wDevID)->modp.wDeviceID, hDrv, 
                                       wMsg, dwParam1, dwParam2);
         case MCI_DEVTYPE_WAVEFORM_AUDIO:
-            return WAVE_DriverProc(GetDrv(wDevID)->wDeviceID, hDrv, 
+            return WAVE_DriverProc(GetDrv(wDevID)->modp.wDeviceID, hDrv, 
                                    wMsg, dwParam1, dwParam2);
         case MCI_DEVTYPE_SEQUENCER:
-            return MIDI_DriverProc(GetDrv(wDevID)->wDeviceID, hDrv, 
+            return MIDI_DriverProc(GetDrv(wDevID)->modp.wDeviceID, hDrv, 
                                    wMsg, dwParam1, dwParam2);
+	/*
         case MCI_DEVTYPE_ANIMATION:
-            return ANIM_DriverProc(GetDrv(wDevID)->wDeviceID, hDrv, 
+            return ANIM_DriverProc(GetDrv(wDevID)->modp.wDeviceID, hDrv, 
                                    wMsg, dwParam1, dwParam2);
+ 	 */
         default:
+	    return Callbacks->CallDriverProc(GetDrv(wDevID)->driverproc,GetDrv(wDevID)->modp.wDeviceID,GetDrv(wDevID)->hdrv,MCI_CLOSE,dwParam1,dwParam2);
+
             dprintf_mci(stddeb,
                         "mciSendCommand() // unknown device type=%04X !\n", 
-                        GetDrv(wDevID)->wType);
+                        GetDrv(wDevID)->modp.wType);
         }
     }
     return MMSYSERR_INVALPARAM;
@@ -1498,7 +1611,7 @@
 	return 0;
 
     wDevID = MMSYSTEM_FirstDevID();
-    while(MMSYSTEM_DevIDValid(wDevID) && GetDrv(wDevID)->wType) {
+    while(MMSYSTEM_DevIDValid(wDevID) && GetDrv(wDevID)->modp.wType) {
 	if (GetOpenDrv(wDevID)->lpstrDeviceType && 
             strcmp(PTR_SEG_TO_LIN(GetOpenDrv(wDevID)->lpstrDeviceType), lpstrName) == 0)
 	    return wDevID;
@@ -3941,10 +4054,63 @@
 
 
 /**************************************************************************
-* 				DrvDefDriverProc	[MMSYSTEM.1104]
-*/
+ * 				DrvDefDriverProc	[MMSYSTEM.1104]
+ */
 LRESULT WINAPI DrvDefDriverProc(DWORD dwDriverID, HDRVR16 hDriv, WORD wMsg, 
                                 DWORD dwParam1, DWORD dwParam2)
 {
 	return DefDriverProc(dwDriverID, hDriv, wMsg, dwParam1, dwParam2);
 }
+
+/**************************************************************************
+ * 				mmThreadCreate		[MMSYSTEM.1120]
+ */
+LRESULT WINAPI mmThreadCreate16(LPVOID x1, LPWORD x2, DWORD x3, DWORD x4) {
+	fprintf(stderr,"mmThreadCreate16(%p,%p,%08lx,%08lx),stub!\n",
+		x1,x2,x3,x4
+	);
+	*x2 = 0xbabe;
+	return 0;
+}
+
+/**************************************************************************
+ * 				mmThreadGetTask		[MMSYSTEM.1125]
+ */
+LRESULT WINAPI mmThreadGetTask16(WORD hnd) {
+	fprintf(stderr,"mmThreadGetTask16(%04x),stub!\n",hnd);
+	return GetCurrentTask();
+}
+
+/**************************************************************************
+ * 				mmThreadSignal		[MMSYSTEM.1121]
+ */
+LRESULT WINAPI mmThreadSignal16(WORD hnd) {
+	fprintf(stderr,"mmThreadSignal16(%04x), stub!\n",hnd);
+	return 0;
+}
+
+/**************************************************************************
+ * 				mmTaskCreate		[MMSYSTEM.900]
+ */
+LRESULT WINAPI mmTaskCreate16(LPWORD lphnd,DWORD x1,DWORD x2) {
+	fprintf(stderr,"mmTaskCreate16(%p,%08lx,%08lx),stub!\n",lphnd,x1,x2);
+	*lphnd = 0xcafe;
+	return 0;
+}
+
+/**************************************************************************
+ * 				mmTaskSignal		[MMSYSTEM.903]
+ */
+LRESULT WINAPI mmTaskSignal16(HTASK16 ht) {
+	fprintf(stderr,"mmTaskSignal(%04x),stub!\n",ht);
+	return PostAppMessage16(ht,0x400,0,0);
+}
+
+/**************************************************************************
+ * 				mciDriverYield		[MMSYSTEM.710]
+ */
+LRESULT WINAPI mciDriverYield16(HANDLE16 hnd) {
+	fprintf(stderr,"mciDriverYield16(%04x),stub!\n",hnd);
+	return 0;
+}
+
diff --git a/multimedia/time.c b/multimedia/time.c
index c631ce0..7a4eb6d 100644
--- a/multimedia/time.c
+++ b/multimedia/time.c
@@ -24,14 +24,15 @@
 static MMTIME16 mmSysTimeSMPTE;
 
 typedef struct tagTIMERENTRY {
-    WORD wDelay;
-    WORD wResol;
+    UINT32	wDelay;
+    UINT32	wResol;
     FARPROC16 lpFunc;
-    HINSTANCE16 hInstance;
-    DWORD dwUser;
-    WORD wFlags;
-    WORD wTimerID;
-    WORD wCurTime;
+    HINSTANCE32	hInstance;
+    DWORD	dwUser;
+    UINT32	wFlags;
+    UINT32	wTimerID;
+    UINT32	wCurTime;
+    UINT32	iswin32;
     struct tagTIMERENTRY *Next;
 } TIMERENTRY, *LPTIMERENTRY;
 
@@ -58,6 +59,7 @@
 	lpTimer->wCurTime--;
 	if (lpTimer->wCurTime == 0) {
 	    lpTimer->wCurTime = lpTimer->wDelay;
+
 	    if (lpTimer->lpFunc != (FARPROC16) NULL) {
 		dprintf_mmtime(stddeb, "MMSysTimeCallback // before CallBack16 !\n");
 		dprintf_mmtime(stddeb, "MMSysTimeCallback // lpFunc=%p wTimerID=%04X dwUser=%08lX !\n",
@@ -77,15 +79,19 @@
  *	    PostMessage), and must reside in DLL (therefore uses stack of active application). So I 
  *          guess current implementation via SetTimer has to be improved upon.		
  */
-
-		Callbacks->CallTimeFuncProc(lpTimer->lpFunc, lpTimer->wTimerID,
-                                            0, lpTimer->dwUser, 0, 0 );
+ 		if (lpTimer->iswin32)
+			lpTimer->lpFunc(lpTimer->wTimerID,0,lpTimer->dwUser,0,0);
+		else
+			Callbacks->CallTimeFuncProc(lpTimer->lpFunc,
+						    lpTimer->wTimerID,0,
+						    lpTimer->dwUser,0,0
+			);
 
 		dprintf_mmtime(stddeb, "MMSysTimeCallback // after CallBack16 !\n");
 		fflush(stdout);
 	    }
 	    if (lpTimer->wFlags & TIME_ONESHOT)
-		timeKillEvent(lpTimer->wTimerID);
+		timeKillEvent32(lpTimer->wTimerID);
 	}
 	lpTimer = lpTimer->Next;
     }
@@ -112,11 +118,24 @@
 }
 
 /**************************************************************************
+ * 				timeGetSystemTime	[WINMM.140]
+ */
+MMRESULT32 WINAPI timeGetSystemTime32(LPMMTIME32 lpTime, UINT32 wSize)
+{
+    dprintf_mmsys(stddeb, "timeGetSystemTime32(%p, %u);\n", lpTime, wSize);
+    if (!mmTimeStarted)
+	StartMMTime();
+    lpTime->wType = TIME_MS;
+    lpTime->u.ms = mmSysTimeMS.u.ms;
+    return 0;
+}
+
+/**************************************************************************
  * 				timeGetSystemTime	[MMSYSTEM.601]
  */
-WORD WINAPI timeGetSystemTime(LPMMTIME16 lpTime, WORD wSize)
+MMRESULT16 WINAPI timeGetSystemTime16(LPMMTIME16 lpTime, UINT16 wSize)
 {
-    dprintf_mmsys(stddeb, "timeGetSystemTime(%p, %u);\n", lpTime, wSize);
+    dprintf_mmsys(stddeb, "timeGetSystemTime16(%p, %u);\n", lpTime, wSize);
     if (!mmTimeStarted)
 	StartMMTime();
     lpTime->wType = TIME_MS;
@@ -127,8 +146,49 @@
 /**************************************************************************
  * 				timeSetEvent		[MMSYSTEM.602]
  */
-WORD WINAPI timeSetEvent(WORD wDelay, WORD wResol, LPTIMECALLBACK lpFunc,
-                         DWORD dwUser, WORD wFlags)
+MMRESULT32 WINAPI timeSetEvent32(UINT32 wDelay,UINT32 wResol,
+				 LPTIMECALLBACK32 lpFunc,DWORD dwUser,
+				 UINT32 wFlags)
+{
+    WORD wNewID = 0;
+    LPTIMERENTRY lpNewTimer;
+    LPTIMERENTRY lpTimer = lpTimerList;
+
+    dprintf_mmtime(stddeb, "timeSetEvent32(%u, %u, %p, %08lX, %04X);\n",
+		  wDelay, wResol, lpFunc, dwUser, wFlags);
+    if (!mmTimeStarted)
+	StartMMTime();
+    lpNewTimer = (LPTIMERENTRY)xmalloc(sizeof(TIMERENTRY));
+    if (lpNewTimer == NULL)
+	return 0;
+    while (lpTimer != NULL) {
+	wNewID = MAX(wNewID, lpTimer->wTimerID);
+	lpTimer = lpTimer->Next;
+    }
+
+    lpNewTimer->Next = lpTimerList;
+    lpTimerList = lpNewTimer;
+    lpNewTimer->wTimerID = wNewID + 1;
+    lpNewTimer->wCurTime = wDelay;
+    lpNewTimer->wDelay = wDelay;
+    lpNewTimer->wResol = wResol;
+    lpNewTimer->lpFunc = (FARPROC16) lpFunc;
+    lpNewTimer->iswin32 = 1;
+    lpNewTimer->hInstance = GetTaskDS();
+	dprintf_mmtime(stddeb, "timeSetEvent // hInstance=%04X !\n", lpNewTimer->hInstance);
+	dprintf_mmtime(stddeb, "timeSetEvent // lpFunc=%p !\n", 
+				lpFunc);
+    lpNewTimer->dwUser = dwUser;
+    lpNewTimer->wFlags = wFlags;
+    return lpNewTimer->wTimerID;
+}
+
+/**************************************************************************
+ * 				timeSetEvent		[MMSYSTEM.602]
+ */
+MMRESULT16 WINAPI timeSetEvent16(UINT16 wDelay, UINT16 wResol,
+				 LPTIMECALLBACK16 lpFunc,DWORD dwUser,
+				 UINT16 wFlags)
 {
     WORD wNewID = 0;
     LPTIMERENTRY lpNewTimer;
@@ -152,6 +212,7 @@
     lpNewTimer->wDelay = wDelay;
     lpNewTimer->wResol = wResol;
     lpNewTimer->lpFunc = (FARPROC16) lpFunc;
+    lpNewTimer->iswin32 = 0;
     lpNewTimer->hInstance = GetTaskDS();
 	dprintf_mmtime(stddeb, "timeSetEvent // hInstance=%04X !\n", lpNewTimer->hInstance);
 	dprintf_mmtime(stddeb, "timeSetEvent // PTR_SEG_TO_LIN(lpFunc)=%p !\n", 
@@ -162,9 +223,9 @@
 }
 
 /**************************************************************************
- * 				timeKillEvent		[MMSYSTEM.603]
+ * 				timeKillEvent		[WINMM.142]
  */
-WORD WINAPI timeKillEvent(WORD wID)
+MMRESULT32 WINAPI timeKillEvent32(UINT32 wID)
 {
     LPTIMERENTRY xlptimer,*lpTimer = &lpTimerList;
     while (*lpTimer) {
@@ -180,9 +241,17 @@
 }
 
 /**************************************************************************
- * 				timeGetDevCaps		[MMSYSTEM.604]
+ * 				timeKillEvent		[MMSYSTEM.603]
  */
-WORD WINAPI timeGetDevCaps(LPTIMECAPS lpCaps, WORD wSize)
+MMRESULT16 WINAPI timeKillEvent16(UINT16 wID)
+{
+    return timeKillEvent32(wID);
+}
+
+/**************************************************************************
+ * 				timeGetDevCaps		[WINMM.139]
+ */
+MMRESULT32 WINAPI timeGetDevCaps32(LPTIMECAPS32 lpCaps,UINT32 wSize)
 {
     dprintf_mmtime(stddeb, "timeGetDevCaps(%p, %u) !\n", lpCaps, wSize);
     if (!mmTimeStarted)
@@ -193,9 +262,34 @@
 }
 
 /**************************************************************************
+ * 				timeGetDevCaps		[MMSYSTEM.604]
+ */
+MMRESULT16 WINAPI timeGetDevCaps16(LPTIMECAPS16 lpCaps, UINT16 wSize)
+{
+    dprintf_mmtime(stddeb, "timeGetDevCaps(%p, %u) !\n", lpCaps, wSize);
+    if (!mmTimeStarted)
+	StartMMTime();
+    lpCaps->wPeriodMin = MMSYSTIME_MININTERVAL;
+    lpCaps->wPeriodMax = MMSYSTIME_MAXINTERVAL;
+    return 0;
+}
+
+/**************************************************************************
+ * 				timeBeginPeriod		[WINMM.137]
+ */
+MMRESULT32 WINAPI timeBeginPeriod32(UINT32 wPeriod)
+{
+    dprintf_mmtime(stddeb, "timeBeginPeriod32(%u) !\n", wPeriod);
+    if (!mmTimeStarted)
+	StartMMTime();
+    if (wPeriod < MMSYSTIME_MININTERVAL || wPeriod > MMSYSTIME_MAXINTERVAL) 
+        return TIMERR_NOCANDO;
+    return 0;
+}
+/**************************************************************************
  * 				timeBeginPeriod		[MMSYSTEM.605]
  */
-WORD WINAPI timeBeginPeriod(WORD wPeriod)
+MMRESULT16 WINAPI timeBeginPeriod16(UINT16 wPeriod)
 {
     dprintf_mmtime(stddeb, "timeBeginPeriod(%u) !\n", wPeriod);
     if (!mmTimeStarted)
@@ -206,9 +300,9 @@
 }
 
 /**************************************************************************
- * 				timeEndPeriod		[MMSYSTEM.606]
+ * 				timeEndPeriod		[WINMM.138]
  */
-WORD WINAPI timeEndPeriod(WORD wPeriod)
+MMRESULT32 WINAPI timeEndPeriod32(UINT32 wPeriod)
 {
     dprintf_mmtime(stddeb, "timeEndPeriod(%u) !\n", wPeriod);
     if (wPeriod < MMSYSTIME_MININTERVAL || wPeriod > MMSYSTIME_MAXINTERVAL) 
@@ -217,13 +311,30 @@
 }
 
 /**************************************************************************
- * 				timeGetTime    		[MMSYSTEM.607]
+ * 				timeEndPeriod		[MMSYSTEM.606]
+ */
+MMRESULT16 WINAPI timeEndPeriod16(UINT16 wPeriod)
+{
+    dprintf_mmtime(stddeb, "timeEndPeriod(%u) !\n", wPeriod);
+    if (wPeriod < MMSYSTIME_MININTERVAL || wPeriod > MMSYSTIME_MAXINTERVAL) 
+        return TIMERR_NOCANDO;
+    return 0;
+}
+
+/**************************************************************************
+ * 				timeGetTime    [MMSYSTEM.607][WINMM.141]
  */
 DWORD WINAPI timeGetTime()
 {
+    static DWORD lasttick=0;
+    DWORD	newtick;
+
     dprintf_mmtime(stddeb, "timeGetTime(); !\n");
     if (!mmTimeStarted)
 	StartMMTime();
+    newtick = GetTickCount();
+    mmSysTimeMS.u.ms+=newtick-lasttick; /* FIXME: faked timer */
+    lasttick = newtick;
     dprintf_mmtime(stddeb, "timeGetTime() // Time = %ld\n",mmSysTimeMS.u.ms);
     return mmSysTimeMS.u.ms;
 }
diff --git a/objects/bitmap.c b/objects/bitmap.c
index c6fbbe1..4092719 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -489,6 +489,29 @@
     return height * bmp->bitmap.bmWidthBytes;
 }
 
+HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
+                             INT16 desiredx, INT16 desiredy, UINT16 loadflags)
+{
+	if (HIWORD(name)) {
+		fprintf(stddeb,"LoadImage16(0x%04x,%s,%d,%d,%d,0x%08x)\n",
+			hinst,(char *)PTR_SEG_TO_LIN(name),type,desiredx,desiredy,loadflags
+		);
+	} else {
+		fprintf(stddeb,"LoadImage16(0x%04x,%p,%d,%d,%d,0x%08x)\n",
+			hinst,name,type,desiredx,desiredy,loadflags
+		);
+	}
+	switch (type) {
+	case IMAGE_BITMAP:
+		return LoadBitmap16(hinst,name);
+	case IMAGE_ICON:
+		return LoadIcon16(hinst,name);
+	case IMAGE_CURSOR:
+		return LoadCursor16(hinst,name);
+	}
+	return 0;
+	
+}
 /**********************************************************************
  *	    LoadImageA    (USER32.364)
  * FIXME: implementation still lacks nearly all features, see LR_*
diff --git a/objects/brush.c b/objects/brush.c
index 5ef84fb..8f2eb83 100644
--- a/objects/brush.c
+++ b/objects/brush.c
@@ -236,6 +236,15 @@
     return TRUE;
 }
 
+/***********************************************************************
+ *           FixBrushOrgEx    (GDI32.102)
+ * SDK says discontinued, but in Win95 GDI32 this is the same as SetBrushOrgEx
+ */
+BOOL32 WINAPI FixBrushOrgEx( HDC32 hdc, INT32 x, INT32 y, LPPOINT32 oldorg )
+{
+    return SetBrushOrgEx(hdc,x,y,oldorg);
+}
+
 
 /***********************************************************************
  *           GetSysColorBrush16    (USER.281)
diff --git a/objects/cursoricon.c b/objects/cursoricon.c
index a9a7a06..d77a5f7 100644
--- a/objects/cursoricon.c
+++ b/objects/cursoricon.c
@@ -41,9 +41,9 @@
 #include "stddebug.h"
 #include "debug.h"
 #include "task.h"
+#include "user.h"
 
 extern UINT16 COLOR_GetSystemPaletteSize();
-extern HGLOBAL16 USER_CallDefaultRsrcHandler( HGLOBAL16, HMODULE16, HRSRC16 );
 
 Cursor CURSORICON_XCursor = None;    /* Current X cursor */
 static HCURSOR32 hActiveCursor = 0;  /* Active cursor */
@@ -440,6 +440,27 @@
 }
 
 
+ /**********************************************************************
+ *          CreateIconFromResource          (USER32)
+ */
+HICON32 WINAPI CreateIconFromResource32( LPBYTE bits, UINT32 cbSize,
+                                           BOOL32 bIcon, DWORD dwVersion)
+/*FIXME: bon@elektron.ikp.physik.tu-darmstadt.de 971130: Test with weditres
+	 showed only blank layout. Couldn't determine if this is a problem
+	 with CreateIconFromResource32 or the application. The application
+	 windows behaves strange (no redraw) before  CreateIconFromResource32
+*/
+{
+    HICON32 ret;
+    ret = CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, 0,0,0);
+    fprintf(stdnimp,"CreateIconFromResource3 probably only a stub\n");
+    dprintf_icon(stddeb, 
+	"CreateIconFromResource32 %s at %p size %d winver %d return 0x%04x\n",
+                 (bIcon)?"Icon":"Cursor",bits,cbSize,bIcon,ret);
+    return ret;
+}
+
+
 /**********************************************************************
  *          CreateIconFromResourceEx32          (USER32.76)
  */
diff --git a/objects/dc.c b/objects/dc.c
index 2e0e1c1..7ff616d 100644
--- a/objects/dc.c
+++ b/objects/dc.c
@@ -18,46 +18,6 @@
 
 extern void CLIPPING_UpdateGCRegion( DC * dc );     /* objects/clipping.c */
 
-  /* Default DC values */
-static const WIN_DC_INFO DC_defaultValues =
-{
-    0,                      /* flags */
-    NULL,                   /* devCaps */
-    0,                      /* hClipRgn */
-    0,                      /* hVisRgn */
-    0,                      /* hGCClipRgn */
-    STOCK_BLACK_PEN,        /* hPen */
-    STOCK_WHITE_BRUSH,      /* hBrush */
-    STOCK_SYSTEM_FONT,      /* hFont */
-    0,                      /* hBitmap */
-    0,                      /* hFirstBitmap */
-    0,                      /* hDevice */
-    STOCK_DEFAULT_PALETTE,  /* hPalette */
-    R2_COPYPEN,             /* ROPmode */
-    ALTERNATE,              /* polyFillMode */
-    BLACKONWHITE,           /* stretchBltMode */
-    ABSOLUTE,               /* relAbsMode */
-    OPAQUE,                 /* backgroundMode */
-    RGB( 255, 255, 255 ),   /* backgroundColor */
-    RGB( 0, 0, 0 ),         /* textColor */
-    0,                      /* backgroundPixel */
-    0,                      /* textPixel */
-    0,                      /* brushOrgX */
-    0,                      /* brushOrgY */
-    TA_LEFT | TA_TOP | TA_NOUPDATECP,  /* textAlign */
-    0,                      /* charExtra */
-    0,                      /* breakTotalExtra */
-    0,                      /* breakCount */
-    0,                      /* breakExtra */
-    0,                      /* breakRem */
-    1,                      /* bitsPerPixel */
-    MM_TEXT,                /* MapMode */
-    GM_COMPATIBLE,          /* GraphicsMode */
-    0,                      /* DCOrgX */
-    0,                      /* DCOrgY */
-    0,                      /* CursPosX */
-    0                       /* CursPosY */
-};
 
   /* ROP code to GC function conversion */
 const int DC_XROPfunction[16] =
@@ -134,6 +94,54 @@
 
 
 /***********************************************************************
+ *           DC_Init_DC_INFO
+ *
+ * Fill the WIN_DC_INFO structure.
+ */
+static void DC_Init_DC_INFO( WIN_DC_INFO *win_dc_info )
+{
+    win_dc_info->flags           = 0;
+    win_dc_info->devCaps         = NULL;
+    win_dc_info->hClipRgn        = 0;
+    win_dc_info->hVisRgn         = 0;
+    win_dc_info->hGCClipRgn      = 0;
+    win_dc_info->hPen            = STOCK_BLACK_PEN;
+    win_dc_info->hBrush          = STOCK_WHITE_BRUSH;
+    win_dc_info->hFont           = STOCK_SYSTEM_FONT;
+    win_dc_info->hBitmap         = 0;
+    win_dc_info->hFirstBitmap    = 0;
+    win_dc_info->hDevice         = 0;
+    win_dc_info->hPalette        = STOCK_DEFAULT_PALETTE;
+    win_dc_info->ROPmode         = R2_COPYPEN;
+    win_dc_info->polyFillMode    = ALTERNATE;
+    win_dc_info->stretchBltMode  = BLACKONWHITE;
+    win_dc_info->relAbsMode      = ABSOLUTE;
+    win_dc_info->backgroundMode  = OPAQUE;
+    win_dc_info->backgroundColor = RGB( 255, 255, 255 );
+    win_dc_info->textColor       = RGB( 0, 0, 0 );
+    win_dc_info->backgroundPixel = 0;
+    win_dc_info->textPixel       = 0;
+    win_dc_info->brushOrgX       = 0;
+    win_dc_info->brushOrgY       = 0;
+    win_dc_info->textAlign       = TA_LEFT | TA_TOP | TA_NOUPDATECP;
+    win_dc_info->charExtra       = 0;
+    win_dc_info->breakTotalExtra = 0;
+    win_dc_info->breakCount      = 0;
+    win_dc_info->breakExtra      = 0;
+    win_dc_info->breakRem        = 0;
+    win_dc_info->bitsPerPixel    = 1;
+    win_dc_info->MapMode         = MM_TEXT;
+    win_dc_info->GraphicsMode    = GM_COMPATIBLE;
+    win_dc_info->DCOrgX          = 0;
+    win_dc_info->DCOrgY          = 0;
+    win_dc_info->CursPosX        = 0;
+    win_dc_info->CursPosY        = 0;
+
+    PATH_InitGdiPath(&win_dc_info->path);
+}
+
+
+/***********************************************************************
  *           DC_AllocDC
  */
 DC *DC_AllocDC( const DC_FUNCTIONS *funcs )
@@ -159,7 +167,8 @@
     dc->vportExtX  = 1;
     dc->vportExtY  = 1;
 
-    memcpy( &dc->w, &DC_defaultValues, sizeof(DC_defaultValues) );
+    DC_Init_DC_INFO( &dc->w );
+
     return dc;
 }
 
@@ -349,8 +358,32 @@
     }
     else val.line_style = LineSolid;
     val.line_width = dc->u.x.pen.width;
-    val.cap_style  = (val.line_width <= 1) ? CapNotLast : CapRound;
-    val.join_style = JoinMiter;
+    if (val.line_width <= 1) {
+	val.cap_style = CapNotLast;
+    } else {
+	switch (dc->u.x.pen.endcap)
+	{
+	case PS_ENDCAP_SQUARE:
+	    val.cap_style = CapProjecting;
+	    break;
+	case PS_ENDCAP_FLAT:
+	    val.cap_style = CapButt;
+	    break;
+	case PS_ENDCAP_ROUND:
+	default:
+	    val.cap_style = CapRound;
+	}
+    }
+    switch (dc->u.x.pen.linejoin)
+    {
+    case PS_JOIN_BEVEL:
+	val.join_style = JoinBevel;
+    case PS_JOIN_MITER:
+	val.join_style = JoinMiter;
+    case PS_JOIN_ROUND:
+    default:
+	val.join_style = JoinRound;
+    }
     XChangeGC( display, dc->u.x.gc, 
 	       GCFunction | GCForeground | GCBackground | GCLineWidth |
 	       GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle, &val );
@@ -453,6 +486,8 @@
     newdc->hSelf = (HDC32)handle;
     newdc->saveLevel = 0;
 
+    PATH_InitGdiPath( &newdc->w.path );
+    
     /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
 
     newdc->w.hGCClipRgn = newdc->w.hVisRgn = 0;
@@ -572,6 +607,21 @@
       return 0;
     }
     dcs = (DC *) GDI_HEAP_LOCK( hdcs );
+
+    /* Copy path. The reason why path saving / restoring is in SaveDC/
+     * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
+     * functions are only in Win16 (which doesn't have paths) and that
+     * SetDCState doesn't allow us to signal an error (which can happen
+     * when copying paths).
+     */
+    if (!PATH_AssignGdiPath( &dcs->w.path, &dc->w.path ))
+    {
+        GDI_HEAP_UNLOCK( hdc );
+	GDI_HEAP_UNLOCK( hdcs );
+	DeleteDC32( hdcs );
+	return 0;
+    }
+    
     dcs->header.hNext = dc->header.hNext;
     dc->header.hNext = hdcs;
     dprintf_dc(stddeb, "SaveDC(%04x): returning %d\n", hdc, dc->saveLevel+1 );
@@ -597,6 +647,7 @@
 BOOL32 WINAPI RestoreDC32( HDC32 hdc, INT32 level )
 {
     DC * dc, * dcs;
+    BOOL32 success;
 
     dprintf_dc(stddeb, "RestoreDC: %04x %d\n", hdc, level );
     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
@@ -620,6 +671,7 @@
       return FALSE;
     }
     
+    success=TRUE;
     while (dc->saveLevel >= level)
     {
 	HDC16 hdcs = dc->header.hNext;
@@ -629,11 +681,18 @@
 	  return FALSE;
 	}	
 	dc->header.hNext = dcs->header.hNext;
-	if (--dc->saveLevel < level) SetDCState( hdc, hdcs );
+	if (--dc->saveLevel < level)
+	{
+	    SetDCState( hdc, hdcs );
+            if (!PATH_AssignGdiPath( &dc->w.path, &dcs->w.path ))
+		/* FIXME: This might not be quite right, since we're
+		 * returning FALSE but still destroying the saved DC state */
+	        success=FALSE;
+	}
 	DeleteDC32( hdcs );
     }
     GDI_HEAP_UNLOCK( hdc );
-    return TRUE;
+    return success;
 }
 
 
@@ -823,6 +882,8 @@
     if (dc->w.hVisRgn) DeleteObject32( dc->w.hVisRgn );
     if (dc->w.hGCClipRgn) DeleteObject32( dc->w.hGCClipRgn );
     
+    PATH_DestroyGdiPath(&dc->w.path);
+    
     return GDI_FreeObject( hdc );
 }
 
diff --git a/objects/dib.c b/objects/dib.c
index 3c1be2e..b5d1cf2 100644
--- a/objects/dib.c
+++ b/objects/dib.c
@@ -291,6 +291,7 @@
 	    srcbits += linebytes;
 	}
     } else {
+	lines = -lines;
 	for (h = 0; h < lines; h++) {
 	    DIB_SetImageBits_1_Line(dstwidth, colors, bmpImage, h, srcbits);
 	    srcbits += linebytes;
@@ -327,6 +328,7 @@
 	    bits	 = srcbits;
 	}
     } else {
+	lines = -lines;
 	for (h = 0; h < lines; h++) {
 	    for (i = dstwidth/2, x = 0; i > 0; i--) {
 		BYTE pix = *bits++;
@@ -731,6 +733,7 @@
 	    bits = (srcbits += linebytes);
 	}
     } else {
+	lines = -lines;
 	for (h = 0; h < lines; h++) {
 	    for (x = 0; x < dstwidth; x++, bits += 4) {
 		XPutPixel( bmpImage, x, h,
diff --git a/objects/gdiobj.c b/objects/gdiobj.c
index dd49530..fe3c6f9 100644
--- a/objects/gdiobj.c
+++ b/objects/gdiobj.c
@@ -90,6 +90,10 @@
     { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
       0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
 };
+/* Filler to make the location counter dword aligned again.  This is necessary
+   since (a) FONTOBJ is packed, (b) gcc places initialised variables in the code
+   segment, and (c) Solaris assembler is stupid.  */
+static UINT16 align_OEMFixedFont = 1;
 
 static FONTOBJ AnsiFixedFont =
 {
@@ -97,6 +101,7 @@
     { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
       0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
 };
+static UINT16 align_AnsiFixedFont = 1;
 
 static FONTOBJ AnsiVarFont =
 {
@@ -104,6 +109,7 @@
     { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
       0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
 };
+static UINT16 align_AnsiVarFont = 1;
 
 static FONTOBJ SystemFont =
 {
@@ -111,6 +117,7 @@
     { 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
       0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "System" }
 };
+static UINT16 align_SystemFont = 1;
 
 static FONTOBJ DeviceDefaultFont =
 {
@@ -118,6 +125,7 @@
     { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
       0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
 };
+static UINT16 align_DeviceDefaultFont = 1;
 
 static FONTOBJ SystemFixedFont =
 {
@@ -125,6 +133,16 @@
     { 12, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
       0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
 };
+static UINT16 align_SystemFixedFont = 1;
+
+/* FIXME: Is this correct? */
+static FONTOBJ DefaultGuiFont =
+{
+    { 9, FONT_MAGIC, 1 },   /* header */
+    { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+      0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
+};
+static UINT16 align_DefaultGuiFont = 1;
 
 
 static GDIOBJHDR * StockObjects[NB_STOCK_OBJECTS] =
@@ -145,7 +163,8 @@
     (GDIOBJHDR *) &SystemFont,
     (GDIOBJHDR *) &DeviceDefaultFont,
     NULL,            /* DEFAULT_PALETTE created by PALETTE_Init */
-    (GDIOBJHDR *) &SystemFixedFont
+    (GDIOBJHDR *) &SystemFixedFont,
+    (GDIOBJHDR *) &DefaultGuiFont
 };
 
 /******************************************************************************
@@ -213,6 +232,15 @@
     extern BOOL32 X11DRV_Init(void);
     extern BOOL32 DIB_Init(void);
 
+    /* Kill some warnings.  */
+    (void)align_OEMFixedFont;
+    (void)align_AnsiFixedFont;
+    (void)align_AnsiVarFont;
+    (void)align_SystemFont;
+    (void)align_DeviceDefaultFont;
+    (void)align_SystemFixedFont;
+    (void)align_DefaultGuiFont;
+
     /* TWEAK: Initialize font hints */
     ReadFontInformation("OEMFixed", &OEMFixedFont, 12, 0, 0, 0, 0);
     ReadFontInformation("AnsiFixed", &AnsiFixedFont, 12, 0, 0, 0, 0);
@@ -515,6 +543,28 @@
     return GetObject32A( handle, count, buffer );
 }
 
+/***********************************************************************
+ *           GetCurrentObject    	(GDI32.166)
+ */
+HANDLE32 WINAPI GetCurrentObject(HDC32 hdc,UINT32 type)
+{
+    DC * dc = DC_GetDCPtr( hdc );
+
+    if (!dc) 
+    	return 0;
+    switch (type) {
+    case OBJ_PEN:	return dc->w.hPen;
+    case OBJ_BRUSH:	return dc->w.hBrush;
+    case OBJ_PAL:	return dc->w.hPalette;
+    case OBJ_FONT:	return dc->w.hFont;
+    case OBJ_BITMAP:	return dc->w.hBitmap;
+    default:
+    	/* the SDK only mentions those above */
+    	fprintf(stderr,"GetCurrentObject(%08x,%d), unknown type.\n",hdc,type);
+	return 0;
+    }
+}
+
 
 /***********************************************************************
  *           SelectObject16    (GDI.45)
diff --git a/objects/metafile.c b/objects/metafile.c
index 7785313..373c851 100644
--- a/objects/metafile.c
+++ b/objects/metafile.c
@@ -277,6 +277,10 @@
 	mr = (METARECORD *)((char *)mh + offset);
 	dprintf_metafile(stddeb,"offset = %04x size = %08lx function = %04x\n",
 			 offset,mr->rdSize,mr->rdFunction);
+	if (!mr->rdSize) {
+		fprintf(stderr,"METAFILE entry got size 0 at offset %d, total mf length is %ld\n",offset,mh->mtSize*2);
+		break; /* would loop endlessly otherwise */
+	}
 	offset += mr->rdSize * 2;
 	PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
     }
@@ -650,6 +654,8 @@
             dxx = (LPINT16)(sot+(((s1+1)>>1)*2));	   
           else 
 	  {
+	   dprintf_metafile(stddeb,"EXTTEXTOUT: %s  len: %ld\n",
+             sot,mr->rdSize);
            fprintf(stderr,
 	     "Please report: PlayMetaFile/ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
 		   len,s1,mr->rdSize,mr->rdParam[3]);
diff --git a/objects/palette.c b/objects/palette.c
index c8adcaa..f7f4a04 100644
--- a/objects/palette.c
+++ b/objects/palette.c
@@ -20,9 +20,6 @@
 /* #define DEBUG_PALETTE */
 #include "debug.h"
 
- /* lookup pixel among static entries of the system palette */
-extern int COLOR_LookupSystemPixel(COLORREF);
-
 static UINT32 SystemPaletteUse = SYSPAL_STATIC;  /* currently not considered */
 
 static HPALETTE16 hPrimaryPalette = 0; /* used for WM_PALETTECHANGED */
@@ -36,8 +33,6 @@
  */
 HPALETTE16 PALETTE_Init(void)
 {
-    extern const PALETTEENTRY* COLOR_GetSystemPaletteTemplate(void);
-
     int                 i;
     HPALETTE16          hpalette;
     LOGPALETTE *        palPtr;
@@ -117,6 +112,14 @@
     return hpalette;
 }
 
+/***********************************************************************
+ *           CreateHalftonePalette   (GDI32.47)
+ */
+HPALETTE32 WINAPI CreateHalftonePalette(HDC32 hdc)
+{
+  fprintf(stdnimp,"CreateHalftonePalette: empty stub!\n");
+  return NULL;
+}
 
 /***********************************************************************
  *           GetPaletteEntries16    (GDI.363)
diff --git a/objects/pen.c b/objects/pen.c
index c2c63ad..ca3a191 100644
--- a/objects/pen.c
+++ b/objects/pen.c
@@ -73,6 +73,30 @@
     return hpen;
 }
 
+/***********************************************************************
+ *           ExtCreatePen32    (GDI32.93)
+ *
+ * FIXME: PS_USERSTYLE not handled
+ */
+
+HPEN32 WINAPI ExtCreatePen32( DWORD style, DWORD width,
+                              const LOGBRUSH32 * brush, DWORD style_count,
+                              const DWORD *style_bits )
+{
+    LOGPEN32 logpen;
+
+    if ((style & PS_STYLE_MASK) == PS_USERSTYLE)
+	fprintf(stderr, "ExtCreatePen: PS_USERSTYLE not handled\n");
+    if ((style & PS_TYPE_MASK) == PS_GEOMETRIC)
+	if (brush->lbHatch)
+	    fprintf(stderr, "ExtCreatePen: Hatches not implemented\n");
+
+    logpen.lopnStyle = style & ~PS_TYPE_MASK;
+    logpen.lopnWidth.x = (style & PS_GEOMETRIC) ? width : 1;
+    logpen.lopnWidth.y = 0;
+    logpen.lopnColor = brush->lbColor;
+    return CreatePenIndirect32( &logpen );
+}
 
 /***********************************************************************
  *           PEN_GetObject16
diff --git a/objects/text.c b/objects/text.c
index 04f8f8b..60ec10c 100644
--- a/objects/text.c
+++ b/objects/text.c
@@ -13,6 +13,7 @@
 #include "stddebug.h"
 /* #define DEBUG_TEXT */
 #include "debug.h"
+#include "cache.h"
 
 #define TAB     9
 #define LF     10
@@ -420,21 +421,117 @@
 
 
 /***********************************************************************
+ *           TEXT_GrayString
+ *
+ * FIXME: The call to 16-bit code only works because the wine GDI is a 16-bit
+ * heap and we can guarantee that the handles fit in an INT16. We have to
+ * rethink the strategy once the migration to NT handles is complete.
+ * We are going to get a lot of code-duplication once this migration is
+ * completed...
+ * 
+ */
+static BOOL32 TEXT_GrayString(HDC32 hdc, HBRUSH32 hb, 
+                              GRAYSTRINGPROC32 fn, LPARAM lp, INT32 len,
+                              INT32 x, INT32 y, INT32 cx, INT32 cy, 
+                              BOOL32 unicode, BOOL32 _32bit)
+{
+    HBITMAP32 hbm, hbmsave;
+    HBRUSH32 hbsave;
+    HFONT32 hfsave;
+    HDC32 memdc = CreateCompatibleDC32(hdc);
+    int slen = len;
+    BOOL32 retval = TRUE;
+    RECT32 r;
+    COLORREF fg, bg;
+
+    if(!hdc) return FALSE;
+    
+    if(len == 0)
+    {
+        if(unicode)
+    	    slen = lstrlen32W((LPCWSTR)lp);
+    	else if(_32bit)
+    	    slen = lstrlen32A((LPCSTR)lp);
+    	else
+    	    slen = lstrlen32A((LPCSTR)PTR_SEG_TO_LIN(lp));
+    }
+
+    if((cx == 0 || cy == 0) && slen != -1)
+    {
+        SIZE32 s;
+        if(unicode)
+            GetTextExtentPoint32W(hdc, (LPCWSTR)lp, slen, &s);
+        else if(_32bit)
+            GetTextExtentPoint32A(hdc, (LPCSTR)lp, slen, &s);
+        else
+            GetTextExtentPoint32A(hdc, (LPCSTR)PTR_SEG_TO_LIN(lp), slen, &s);
+        if(cx == 0) cx = s.cx;
+        if(cy == 0) cy = s.cy;
+    }
+
+    r.left = r.top = 0;
+    r.right = cx;
+    r.bottom = cy;
+
+    hbm = CreateBitmap32(cx, cy, 1, 1, NULL);
+    hbmsave = (HBITMAP32)SelectObject32(memdc, hbm);
+    FillRect32(memdc, &r, (HBRUSH32)GetStockObject32(BLACK_BRUSH));
+    SetTextColor32(memdc, RGB(255, 255, 255));
+    SetBkColor32(memdc, RGB(0, 0, 0));
+    hfsave = (HFONT32)SelectObject32(memdc, GetCurrentObject(hdc, OBJ_FONT));
+            
+    if(fn)
+        if(_32bit)
+            retval = fn(memdc, lp, slen);
+        else
+            retval = (BOOL32)((BOOL16)((GRAYSTRINGPROC16)fn)((HDC16)memdc, lp, (INT16)slen));
+    else
+        if(unicode)
+            TextOut32W(memdc, 0, 0, (LPCWSTR)lp, slen);
+        else if(_32bit)
+            TextOut32A(memdc, 0, 0, (LPCSTR)lp, slen);
+        else
+            TextOut32A(memdc, 0, 0, (LPCSTR)PTR_SEG_TO_LIN(lp), slen);
+
+    SelectObject32(memdc, hfsave);
+
+/*
+ * Windows doc says that the bitmap isn't grayed when len == -1 and
+ * the callback function returns FALSE. However, testing this on
+ * win95 showed otherwise...
+*/
+#ifdef GRAYSTRING_USING_DOCUMENTED_BEHAVIOUR
+    if(retval || len != -1)
+#endif
+    {
+        hbsave = (HBRUSH32)SelectObject32(memdc, CACHE_GetPattern55AABrush());
+        PatBlt32(memdc, 0, 0, cx, cy, 0x000A0329);
+        SelectObject32(memdc, hbsave);
+    }
+
+    if(hb) hbsave = (HBRUSH32)SelectObject32(hdc, hb);
+    fg = SetTextColor32(hdc, RGB(0, 0, 0));
+    bg = SetBkColor32(hdc, RGB(255, 255, 255));
+    BitBlt32(hdc, x, y, cx, cy, memdc, 0, 0, 0x00E20746);
+    SetTextColor32(hdc, fg);
+    SetBkColor32(hdc, bg);
+    if(hb) SelectObject32(hdc, hbsave);
+
+    SelectObject32(memdc, hbmsave);
+    DeleteObject32(hbm);
+    DeleteDC32(memdc);
+    return retval;
+}
+
+
+/***********************************************************************
  *           GrayString16   (USER.185)
  */
 BOOL16 WINAPI GrayString16( HDC16 hdc, HBRUSH16 hbr, GRAYSTRINGPROC16 gsprc,
                             LPARAM lParam, INT16 cch, INT16 x, INT16 y,
                             INT16 cx, INT16 cy )
 {
-    BOOL16 ret;
-    COLORREF current_color;
-
-    if (!cch) cch = lstrlen16( (LPCSTR)PTR_SEG_TO_LIN(lParam) );
-    if (gsprc) return gsprc( hdc, lParam, cch );
-    current_color = SetTextColor32( hdc, GetSysColor32(COLOR_GRAYTEXT) );
-    ret = TextOut16( hdc, x, y, (LPCSTR)PTR_SEG_TO_LIN(lParam), cch );
-    SetTextColor32( hdc, current_color );
-    return ret;
+    return TEXT_GrayString(hdc, hbr, (GRAYSTRINGPROC32)gsprc, lParam, cch, x, y, cx, cy, FALSE, FALSE);
 }
 
 
@@ -445,15 +542,7 @@
                              LPARAM lParam, INT32 cch, INT32 x, INT32 y,
                              INT32 cx, INT32 cy )
 {
-    BOOL32 ret;
-    COLORREF current_color;
-
-    if (!cch) cch = lstrlen32A( (LPCSTR)lParam );
-    if (gsprc) return gsprc( hdc, lParam, cch );
-    current_color = SetTextColor32( hdc, GetSysColor32(COLOR_GRAYTEXT) );
-    ret = TextOut32A( hdc, x, y, (LPCSTR)lParam, cch );
-    SetTextColor32( hdc, current_color );
-    return ret;
+    return TEXT_GrayString(hdc, hbr, gsprc, lParam, cch, x, y, cx, cy, FALSE, TRUE);
 }
 
 
@@ -464,15 +553,7 @@
                              LPARAM lParam, INT32 cch, INT32 x, INT32 y,
                              INT32 cx, INT32 cy )
 {
-    BOOL32 ret;
-    COLORREF current_color;
-
-    if (!cch) cch = lstrlen32W( (LPCWSTR)lParam );
-    if (gsprc) return gsprc( hdc, lParam, cch );
-    current_color = SetTextColor32( hdc, GetSysColor32(COLOR_GRAYTEXT) );
-    ret = TextOut32W( hdc, x, y, (LPCWSTR)lParam, cch );
-    SetTextColor32( hdc, current_color );
-    return ret;
+    return TEXT_GrayString(hdc, hbr, gsprc, lParam, cch, x, y, cx, cy, TRUE, TRUE);
 }
 
 
@@ -655,8 +736,10 @@
 INT32 WINAPI GetTextCharsetInfo(HDC32 hdc,LPCHARSETINFO csi,DWORD flags)
 {
     fprintf(stdnimp,"GetTextCharsetInfo(0x%x,%p,%08lx), stub!\n",hdc,csi,flags);
-    csi->ciCharset = DEFAULT_CHARSET;
-    csi->ciACP = GetACP();
+    if (csi) {
+	csi->ciCharset = DEFAULT_CHARSET;
+	csi->ciACP = GetACP();
+    }
     /* ... fill fontstruct too ... */
     return DEFAULT_CHARSET;
 }
diff --git a/ole/Makefile.in b/ole/Makefile.in
index feeca6c..1d923733 100644
--- a/ole/Makefile.in
+++ b/ole/Makefile.in
@@ -7,6 +7,8 @@
 
 C_SRCS = \
 	compobj.c \
+	ifs.c \
+	folders.c \
 	ole2.c \
 	ole2disp.c \
 	ole2nls.c \
@@ -18,4 +20,3 @@
 @MAKE_RULES@
 
 ### Dependencies:
-
diff --git a/ole/folders.c b/ole/folders.c
new file mode 100644
index 0000000..cf0def5
--- /dev/null
+++ b/ole/folders.c
@@ -0,0 +1,174 @@
+/*
+ *	Shell Folder stuff
+ *
+ *	Copyright 1997	Marcus Meissner
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ole.h"
+#include "ole2.h"
+#include "stddebug.h"
+#include "debug.h"
+#include "compobj.h"
+#include "interfaces.h"
+#include "shlobj.h"
+
+/******************************************************************************
+ * IEnumIDList implementation
+ */
+
+static ULONG WINAPI IEnumIDList_AddRef(LPENUMIDLIST this) {
+	fprintf(stderr,"IEnumIDList(%p)->AddRef()\n",this);
+	return ++(this->ref);
+}
+
+static ULONG WINAPI IEnumIDList_Release(LPENUMIDLIST this) {
+	fprintf(stderr,"IEnumIDList(%p)->Release()\n",this);
+	if (!--(this->ref)) {
+		fprintf(stderr,"	-> freeing IEnumIDList(%p)\n",this);
+		HeapFree(GetProcessHeap(),0,this);
+		return 0;
+	}
+	return this->ref;
+}
+
+static HRESULT WINAPI IEnumIDList_Next(
+	LPENUMIDLIST this,ULONG celt,LPITEMIDLIST *rgelt,ULONG *pceltFetched
+) {
+	fprintf(stderr,"IEnumIDList(%p)->Next(%ld,%p,%p),stub!\n",
+		this,celt,rgelt,pceltFetched
+	);
+	*pceltFetched = 0; /* we don't have any ... */
+	return 0;
+}
+
+static IEnumIDList_VTable eidlvt = {
+	1,
+	IEnumIDList_AddRef,
+	IEnumIDList_Release,
+	IEnumIDList_Next,
+	5,6,7
+};
+
+LPENUMIDLIST IEnumIDList_Constructor() {
+	LPENUMIDLIST	lpeidl;
+
+	lpeidl= (LPENUMIDLIST)HeapAlloc(GetProcessHeap(),0,sizeof(IEnumIDList));
+	lpeidl->ref = 1;
+	lpeidl->lpvtbl = &eidlvt;
+	return lpeidl;
+}
+
+/******************************************************************************
+ * IShellFolder implementation
+ */
+static ULONG WINAPI IShellFolder_Release(LPSHELLFOLDER this) {
+	fprintf(stderr,"IShellFolder(%p)->Release()\n",this);
+	if (!--(this->ref)) {
+		fprintf(stderr,"	-> freeing IShellFolder(%p)\n",this);
+		HeapFree(GetProcessHeap(),0,this);
+		return 0;
+	}
+	return this->ref;
+}
+
+static ULONG WINAPI IShellFolder_AddRef(LPSHELLFOLDER this) {
+	fprintf(stderr,"IShellFolder(%p)->AddRef()\n",this);
+	return ++(this->ref);
+}
+
+static HRESULT WINAPI IShellFolder_GetAttributesOf(
+	LPSHELLFOLDER this,UINT32 cidl,LPCITEMIDLIST *apidl,DWORD *rgfInOut
+) {
+	fprintf(stderr,"IShellFolder(%p)->GetAttributesOf(%d,%p,%p),stub!\n",
+		this,cidl,apidl,rgfInOut
+	);
+	return 0;
+}
+
+static HRESULT WINAPI IShellFolder_BindToObject(
+	LPSHELLFOLDER this,LPCITEMIDLIST pidl,LPBC pbcReserved,REFIID riid,LPVOID * ppvOut
+) {
+	char	xclsid[50];
+
+	StringFromCLSID(riid,xclsid);
+	fprintf(stderr,"IShellFolder(%p)->BindToObject(%p,%p,%s,%p),stub!\n",
+		this,pidl,pbcReserved,xclsid,ppvOut
+	);
+	*ppvOut = IShellFolder_Constructor();
+	return 0;
+}
+
+static HRESULT WINAPI IShellFolder_ParseDisplayName(
+	LPSHELLFOLDER this,HWND32 hwndOwner,LPBC pbcReserved,
+	LPOLESTR lpszDisplayName,DWORD *pchEaten,LPITEMIDLIST *ppidl,
+	DWORD *pdwAttributes
+) {
+	fprintf(stderr,"IShellFolder(%p)->ParseDisplayName(%08x,%p,%s,%p,%p,%p),stub!\n",
+		this,hwndOwner,pbcReserved,lpszDisplayName,pchEaten,ppidl,pdwAttributes
+	);
+	*(DWORD*)pbcReserved = NULL;
+	return 0;
+}
+
+static HRESULT WINAPI IShellFolder_EnumObjects(
+	LPSHELLFOLDER this,HWND32 hwndOwner,DWORD grfFlags,
+	LPENUMIDLIST* ppenumIDList
+) {
+	fprintf(stderr,"IShellFolder(%p)->EnumObjects(0x%04x,0x%08lx,%p),stub!\n",
+		this,hwndOwner,grfFlags,ppenumIDList
+	);
+	*ppenumIDList = IEnumIDList_Constructor();
+	return 0;
+}
+
+static HRESULT WINAPI IShellFolder_CreateViewObject(
+	LPSHELLFOLDER this,HWND32 hwndOwner,REFIID riid,LPVOID *ppv
+) {
+	char	xclsid[50];
+
+	StringFromCLSID(riid,xclsid);
+	fprintf(stderr,"IShellFolder(%p)->CreateViewObject(0x%04x,%s,%p),stub!\n",
+		this,hwndOwner,xclsid,ppv
+	);
+	*(DWORD*)ppv = NULL;
+	return 0;
+}
+
+
+static struct IShellFolder_VTable sfvt = {
+	1,
+	IShellFolder_AddRef,
+	IShellFolder_Release,
+	IShellFolder_ParseDisplayName,
+	IShellFolder_EnumObjects,
+	IShellFolder_BindToObject,
+	7,8,
+	IShellFolder_CreateViewObject,
+	IShellFolder_GetAttributesOf,
+	11,12,13
+};
+
+LPSHELLFOLDER IShellFolder_Constructor() {
+	LPSHELLFOLDER	sf;
+
+	sf = (LPSHELLFOLDER)HeapAlloc(GetProcessHeap(),0,sizeof(IShellFolder));
+	sf->ref		= 1;
+	sf->lpvtbl	= &sfvt;
+	return sf;
+}
+
+static struct IShellLink_VTable slvt = {
+	1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21
+};
+
+LPSHELLLINK IShellLink_Constructor() {
+	LPSHELLLINK sl;
+
+	sl = (LPSHELLLINK)HeapAlloc(GetProcessHeap(),0,sizeof(IShellLink));
+	sl->ref = 1;
+	sl->lpvtbl = &slvt;
+	return sl;
+}
diff --git a/ole/ifs.c b/ole/ifs.c
new file mode 100644
index 0000000..958a0ae
--- /dev/null
+++ b/ole/ifs.c
@@ -0,0 +1,136 @@
+/*
+ *	basic interfaces
+ *
+ *	Copyright 1997	Marcus Meissner
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include "winerror.h"
+#include "ole.h"
+#include "ole2.h"
+#include "compobj.h"
+#include "interfaces.h"
+#include "shlobj.h"
+#include "stddebug.h"
+#include "debug.h"
+
+static ULONG WINAPI IUnknown_AddRef(LPUNKNOWN this) { 
+	dprintf_relay(stddeb,"IUnknown(%p)->AddRef()\n",this);
+	return ++(this->ref);
+}
+static ULONG WINAPI IUnknown_Release(LPUNKNOWN this) {
+	dprintf_relay(stddeb,"IUnknown(%p)->Release()\n",this);
+	if (!--(this->ref)) {
+		HeapFree(GetProcessHeap(),0,this);
+		return 0;
+	}
+	return this->ref;
+}
+
+static HRESULT WINAPI IUnknown_QueryInterface(LPUNKNOWN this,REFIID refiid,LPVOID *obj) {
+	char	xrefiid[50];
+
+	StringFromCLSID((LPCLSID)refiid,xrefiid);
+	dprintf_relay(stddeb,"IUnknown(%p)->QueryInterface(%s,%p)\n",this,xrefiid,obj);
+
+	if (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown))) {
+		*obj = this;
+		return 0; 
+	}
+	return OLE_E_ENUM_NOMORE; 
+}
+
+static IUnknown_VTable uvt = {
+	IUnknown_QueryInterface,
+	IUnknown_AddRef,
+	IUnknown_Release
+};
+
+
+LPUNKNOWN
+IUnknown_Constructor() {
+	LPUNKNOWN	unk;
+
+	fprintf(stderr,"cloning IUnknown.\n");
+	unk = (LPUNKNOWN)HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown));
+	unk->lpvtbl	= &uvt;
+	unk->ref	= 1;
+	return unk;
+}
+
+static ULONG WINAPI IMalloc_AddRef(LPMALLOC this) {
+	dprintf_relay(stddeb,"IMalloc(%p)->AddRef()\n",this);
+	return 1; /* cannot be freed */
+}
+
+static ULONG WINAPI IMalloc_Release(LPMALLOC this) {
+	dprintf_relay(stddeb,"IMalloc(%p)->Release()\n",this);
+	return 1; /* cannot be freed */
+}
+
+static HRESULT WINAPI IMalloc_QueryInterface(LPMALLOC this,REFIID refiid,LPVOID *obj) {
+	char	xrefiid[50];
+
+	StringFromCLSID((LPCLSID)refiid,xrefiid);
+	dprintf_relay(stddeb,"IMalloc(%p)->QueryInterface(%s,%p)\n",this,xrefiid,obj);
+	if (	!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown)) ||
+		!memcmp(&IID_IMalloc,refiid,sizeof(IID_IMalloc))
+	) {
+		*obj = this;
+		return 0;
+	}
+	return OLE_E_ENUM_NOMORE; 
+}
+
+static LPVOID WINAPI IMalloc_Alloc(LPMALLOC this,DWORD cb) {
+	dprintf_relay(stddeb,"IMalloc(%p)->Alloc(%ld)\n",this,cb);
+	return HeapAlloc(GetProcessHeap(),0,cb);
+}
+
+static LPVOID WINAPI IMalloc_Realloc(LPMALLOC this,LPVOID pv,DWORD cb) {
+	dprintf_relay(stddeb,"IMalloc(%p)->Realloc(%p,%ld)\n",this,pv,cb);
+	return HeapReAlloc(GetProcessHeap(),0,pv,cb);
+}
+static VOID WINAPI IMalloc_Free(LPMALLOC this,LPVOID pv) {
+	dprintf_relay(stddeb,"IMalloc(%p)->Free(%p)\n",this,pv);
+	HeapFree(GetProcessHeap(),0,pv);
+}
+
+static DWORD WINAPI IMalloc_GetSize(LPMALLOC this,LPVOID pv) {
+	dprintf_relay(stddeb,"IMalloc(%p)->GetSize(%p)\n",this,pv);
+	return HeapSize(GetProcessHeap(),0,pv);
+}
+
+static LPINT32 WINAPI IMalloc_DidAlloc(LPMALLOC this,LPVOID pv) {
+	dprintf_relay(stddeb,"IMalloc(%p)->DidAlloc(%p)\n",this,pv);
+	return (LPINT32)0xffffffff;
+}
+static LPVOID WINAPI IMalloc_HeapMinimize(LPMALLOC this) {
+	dprintf_relay(stddeb,"IMalloc(%p)->HeapMinimize()\n",this);
+	return NULL;
+}
+
+static IMalloc_VTable VT_IMalloc = {
+	IMalloc_QueryInterface,
+	IMalloc_AddRef,
+	IMalloc_Release,
+	IMalloc_Alloc,
+	IMalloc_Realloc,
+	IMalloc_Free,
+	IMalloc_GetSize,
+	IMalloc_DidAlloc,
+	IMalloc_HeapMinimize,
+};
+
+LPMALLOC
+IMalloc_Constructor() {
+	LPMALLOC	this;
+
+	fprintf(stderr,"cloning IMalloc\n");
+	this = (LPMALLOC)HeapAlloc(GetProcessHeap(),0,sizeof(IMalloc));
+	this->lpvtbl = &VT_IMalloc;
+	this->ref = 1;
+	return this;
+}
diff --git a/programs/Makefile.in b/programs/Makefile.in
index 0118d6d..2f2e839 100644
--- a/programs/Makefile.in
+++ b/programs/Makefile.in
@@ -1,4 +1,8 @@
-SUBDIRS = progman winhelp winver
+SUBDIRS = \
+	notepad \
+	progman \
+	winhelp \
+	winver
 
 all: $(SUBDIRS)
 
diff --git a/programs/notepad/ChangeLog b/programs/notepad/ChangeLog
new file mode 100644
index 0000000..aca5fa0
--- /dev/null
+++ b/programs/notepad/ChangeLog
@@ -0,0 +1,5 @@
+Fri Dec 05 20:51:55 1997  Marcel Baur <mbaur@g26.ethz.ch>
+       * [notepad.c] [notepad.h] [notepad.rc] [En.rc] [De.rc]
+         [license.c] [license.h] [License_En.c]
+         [README] [TODO] [ChangeLog]
+         Originals by Marcel Baur
diff --git a/programs/notepad/De.rc b/programs/notepad/De.rc
new file mode 100644
index 0000000..ca2a109
--- /dev/null
+++ b/programs/notepad/De.rc
@@ -0,0 +1,91 @@
+/*
+ * Notepad (German resources)
+ *
+ * Copyright 1997 Marcel Baur <mbaur@g26.ethz.ch>
+ */
+
+#define LANGUAGE_ID                  De
+#define LANGUAGE_NUMBER              2
+#define LANGUAGE_MENU_ITEM           "&Deutsch"
+
+/* Menu */
+
+#define MENU_FILE                    "&Datei"
+#define MENU_FILE_NEW                "&Neu..."
+#define MENU_FILE_OPEN               "Ö&ffnen..."
+#define MENU_FILE_SAVE               "&Speichern"
+#define MENU_FILE_SAVEAS             "Speichern &unter..."
+#define MENU_FILE_PRINT              "&Drucken"
+#define MENU_FILE_PAGESETUP          "Seite ein&richten..."
+#define MENU_FILE_PRINTSETUP         "Drucker&einrichtung..."
+#define MENU_FILE_EXIT               "&Beenden"
+
+#define MENU_EDIT                    "&Bearbeiten"
+#define MENU_EDIT_UNDO               "&Rückgängig\tStrg+Z"
+#define MENU_EDIT_CUT                "&Ausschneiden\tStrg+X"
+#define MENU_EDIT_COPY               "&Kopieren\tStrg+C"
+#define MENU_EDIT_PASTE              "&Einfügen\tStrg+V"
+#define MENU_EDIT_DELETE             "&Löschen\tEntf"
+#define MENU_EDIT_SELECTALL          "Alles &markieren"
+#define MENU_EDIT_TIMEDATE           "&Uhrzeit/Datum\tF5"
+#define MENU_EDIT_WRAP               "&Zeilenumbruch"
+
+#define MENU_SEARCH                  "&Suchen"
+#define MENU_SEARCH_SEARCH           "Suchen..."
+#define MENU_SEARCH_NEXT             "&Weitersuchen\tF3"
+
+#define MENU_LANGUAGE                "&Sprache"
+
+#define MENU_HELP                    "&Hilfe"
+#define MENU_HELP_CONTENTS           "&Inhalt"
+#define MENU_HELP_SEARCH             "&Suchen..."
+#define MENU_HELP_HELP_ON_HELP       "&Hilfe benutzen"
+
+#define MENU_INFO                    "Inf&o..."
+#define MENU_INFO_LICENSE            "&Lizenz"
+#define MENU_INFO_NO_WARRANTY        "&KEINE GARANTIE"
+#define MENU_INFO_ABOUT_WINE         "&Über WINE"
+
+
+/* Dialogs */
+
+#define DIALOG_OK                    "OK"
+#define DIALOG_CANCEL                "Abbrechen"
+#define DIALOG_BROWSE                "&Durchsuchen..."
+#define DIALOG_HELP                  "&Hilfe"
+
+#define DIALOG_PAGESETUP_CAPTION     "Seite einrichten"
+#define DIALOG_PAGESETUP_HEAD        "&Kopfzeile:"
+#define DIALOG_PAGESETUP_TAIL        "&Fußzeile:"
+#define DIALOG_PAGESETUP_BORDERS     "Ränder"
+#define DIALOG_PAGESETUP_LEFT        "&Links:"
+#define DIALOG_PAGESETUP_RIGHT       "&Right:"
+#define DIALOG_PAGESETUP_TOP         "&Oben:"
+#define DIALOG_PAGESETUP_BOTTOM      "&Unten:"
+
+
+/* Strings */
+#define STRING_NOTEPAD               "Editor"
+#define STRING_ERROR                 "FEHLER"
+#define STRING_WARNING               "ACHTUNG"
+#define STRING_INFO                  "Information"
+
+#define STRING_UNTITLED              "(unbenannt)"
+
+#define STRING_ALLFILES              "Alle Dateien (*.*)"
+#define STRING_TEXTFILES             "Textdateien (*.TXT)"
+
+#define STRING_TOOLARGE       "'%s' ist zu gross für den Editor\n \
+Benutzen Sie bitte einen anderen Editor, um diese Datei zu bearbeiten."
+
+#define STRING_NOTEXT         "Sie haben keinen Text eingegeben, der \
+gespeichert\n werden könnte. Geben Sie Text ein, und versuchen Sie es \
+\nerneut."
+
+#define STRING_NOTFOUND       "'%s' kann nicht gefunden werden."
+
+#define STRING_OUT_OF_MEMORY  "Nicht genügend Arbeitsspeicher, \
+um diese Funktion \nabzuschließen. Beenden Sie eine oder mehrere \
+\nAnwendungen, um den verfügbaren Arbeitsspeicher zu \nerhöhen."
+
+
diff --git a/programs/notepad/En.rc b/programs/notepad/En.rc
new file mode 100644
index 0000000..35ab98a
--- /dev/null
+++ b/programs/notepad/En.rc
@@ -0,0 +1,91 @@
+/*
+ * Notepad (English resources)
+ *
+ * Copyright 1997 Marcel Baur <mbaur@g26.ethz.ch>
+ * FIXME: See TODO about how to fix weak translations.
+ */
+
+#define LANGUAGE_ID                  En
+#define LANGUAGE_NUMBER              0
+#define LANGUAGE_MENU_ITEM           "&English"
+
+/* Menu */
+
+#define MENU_FILE                    "&File"
+#define MENU_FILE_NEW                "&New..."
+#define MENU_FILE_OPEN               "O&pen"
+#define MENU_FILE_SAVE               "&Save"
+#define MENU_FILE_SAVEAS             "&Save as..."
+#define MENU_FILE_PRINT              "&Print"
+#define MENU_FILE_PAGESETUP          "Page Se&tup..."
+#define MENU_FILE_PRINTSETUP         "P&rinter Setup..."
+#define MENU_FILE_EXIT               "&Exit"
+
+#define MENU_EDIT                    "&Edit"
+#define MENU_EDIT_UNDO               "&Undo\tCtrl+Z"
+#define MENU_EDIT_CUT                "Cu&t\Ctrl+X"
+#define MENU_EDIT_COPY               "&Copy\tCtrl+C"
+#define MENU_EDIT_PASTE              "&Paste\tCtrl+V"
+#define MENU_EDIT_DELETE             "&Delete\tDel"
+#define MENU_EDIT_SELECTALL          "Select &all"
+#define MENU_EDIT_TIMEDATE           "&Time/Date\tF5"
+#define MENU_EDIT_WRAP               "&Wrap long lines"
+
+#define MENU_SEARCH                  "&Search"
+#define MENU_SEARCH_SEARCH           "Search..."
+#define MENU_SEARCH_NEXT             "&Search next\tF3"
+
+#define MENU_LANGUAGE                "&Language"
+
+#define MENU_HELP                    "&Help"
+#define MENU_HELP_CONTENTS           "&Contents"
+#define MENU_HELP_SEARCH             "&Search..."
+#define MENU_HELP_HELP_ON_HELP       "&Help on help"
+
+#define MENU_INFO                    "Inf&o..."
+#define MENU_INFO_LICENSE            "&License"
+#define MENU_INFO_NO_WARRANTY        "&NO WARRANTY"
+#define MENU_INFO_ABOUT_WINE         "&About Wine"
+
+/* Dialogs */
+
+#define DIALOG_OK                    "OK"
+#define DIALOG_CANCEL                "Cancel"
+#define DIALOG_BROWSE                "&Browse..."
+#define DIALOG_HELP                  "&Help"
+
+#define DIALOG_PAGESETUP_CAPTION     "Page Setup"
+#define DIALOG_PAGESETUP_HEAD        "&Header:"
+#define DIALOG_PAGESETUP_TAIL        "&Footer:"
+#define DIALOG_PAGESETUP_BORDER      "Borders:"
+#define DIALOG_PAGESETUP_LEFT        "&Left:"
+#define DIALOG_PAGESETUP_RIGHT       "&Right:"
+#define DIALOG_PAGESETUP_TOP         "&Top:"
+#define DIALOG_PAGESETUP_BOTTOM      "&Bottom:"
+
+
+/* Strings */
+#define STRING_NOTEPAD               "Notepad"
+#define STRING_ERROR                 "ERROR"
+#define STRING_WARNING               "WARNING"
+#define STRING_INFO                  "Information"
+
+#define STRING_UNTITLED              "(untitled)"
+
+#define STRING_ALLFILES              "All files (*.*)"
+#define STRING_TEXTFILES             "Text files (*.*)"
+
+#define STRING_TOOLARGE         "File '%s' ist too large for notepad.\n \
+Please use a different editor."
+
+#define STRING_NOTEXT           "You didn't enter any text. \
+\nPlease type something and try again"
+
+#define STRING_NOTFOUND         "'%s' can not be found."
+
+#define STRING_OUT_OF_MEMORY    "Not enough memory to complete this \
+task. \nClose one or more applications to increase the amount of \nfree \
+memory."
+
+
+
diff --git a/programs/notepad/License_En.c b/programs/notepad/License_En.c
new file mode 100644
index 0000000..bec66d9
--- /dev/null
+++ b/programs/notepad/License_En.c
@@ -0,0 +1,48 @@
+#include "windows.h"
+#include "license.h"
+
+static CHAR LicenseCaption_En[] = "LICENSE";
+static CHAR License_En[] = "\
+You may without charge, royalty or other payment, copy and\
+ distribute copies of this work and derivative works of this work\
+ in source or binary form provided that: (1)\
+ you appropriately publish on each copy an appropriate copyright\
+ notice; (2) faithfully reproduce all prior copyright notices\
+ included in the original work (you may also add your own\
+ copyright notice); and (3) agree to indemnify and hold all prior\
+ authors, copyright holders and licensors of the work harmless\
+ from and against all damages arising from use of the work.\
+\n\
+You may distribute sources of derivative works of the work\
+ provided that (1) (a) all source files of the original work that\
+ have been modified, (b) all source files of the derivative work\
+ that contain any party of the original work, and (c) all source\
+ files of the derivative work that are necessary to compile, link\
+ and run the derivative work without unresolved external calls and\
+ with the same functionality of the original work (\"Necessary\
+ Sources\") carry a prominent notice explaining the nature and date\
+ of the modification and/or creation.  You are encouraged to make\
+ the Necessary Sources available under this license in order to\
+ further the development and acceptance of the work.\
+\n\
+EXCEPT AS OTHERWISE RESTRICTED BY LAW, THIS WORK IS PROVIDED\
+ WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES OF ANY KIND, INCLUDING\
+ BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF FITNESS FOR A\
+ PARTICULAR PURPOSE, MERCHANTABILITY OR TITLE.  EXCEPT AS\
+ OTHERWISE PROVIDED BY LAW, NO AUTHOR, COPYRIGHT HOLDER OR\
+ LICENSOR SHALL BE LIABLE TO YOU FOR DAMAGES OF ANY KIND, EVEN IF\
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.";
+
+static CHAR NoWarrantyCaption_En[] = "NO WARRANTY";
+static CHAR NoWarranty_En[] = "\
+EXCEPT AS OTHERWISE RESTRICTED BY LAW, THIS WORK IS PROVIDED\
+ WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES OF ANY KIND, INCLUDING\
+ BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF FITNESS FOR A\
+ PARTICULAR PURPOSE, MERCHANTABILITY OR TITLE.  EXCEPT AS\
+ OTHERWISE PROVIDED BY LAW, NO AUTHOR, COPYRIGHT HOLDER OR\
+ LICENSOR SHALL BE LIABLE TO YOU FOR DAMAGES OF ANY KIND, EVEN IF\
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.";
+
+LICENSE WineLicense_En = {License_En, LicenseCaption_En,
+			  NoWarranty_En, NoWarrantyCaption_En};
+
diff --git a/programs/notepad/Makefile.in b/programs/notepad/Makefile.in
new file mode 100644
index 0000000..f8a83d6
--- /dev/null
+++ b/programs/notepad/Makefile.in
@@ -0,0 +1,47 @@
+DEFS      = -DWINELIB
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = none
+PROGRAMS  = notepad
+ALL_LIBS  = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LDLIBS)
+RCFLAGS   = -w32 -h
+
+LANGUAGES   = En De
+LICENSELANG = En
+
+MOSTSRCS = \
+	license.c \
+	notepad.c
+
+# Some strings need addresses >= 0x10000
+STRINGSRCS = \
+	$(LICENSELANG:%=License_%.c)
+
+RC_SRCS = \
+	notepad.rc \
+	$(LANGUAGES:%=%.rc)
+
+C_SRCS = $(MOSTSRCS) $(STRINGSRCS)
+
+MOSTOBJS = $(MOSTSRCS:.c=.o)
+STRINGOBJS = $(STRINGSRCS:.c=.o) $(RC_SRCS:.rc=.o)
+
+all: check_winerc $(PROGRAMS)
+
+depend:: $(RC_SRCS:.rc=.h)
+
+@MAKE_RULES@
+
+notepad: $(MOSTOBJS) $(STRINGOBJS)
+	$(CC) -o notepad $(MOSTOBJS) $(LDOPTIONS) $(ALL_LIBS) $(STRINGOBJS)
+
+install: dummy
+	$(INSTALL_PROGRAM) notepad $(bindir)/notepad
+
+$(RC_SRCS:.rc=.c) $(RC_SRCS:.rc=.h): $(WINERC)
+
+dummy:
+
+### Dependencies:
diff --git a/programs/notepad/README b/programs/notepad/README
new file mode 100644
index 0000000..2e03ea9
--- /dev/null
+++ b/programs/notepad/README
@@ -0,0 +1,19 @@
+
+NOTEPAD for WINE
+================
+
+This is an early release of notepad and most of the code is still 
+broken. It will probably compile but the application will not make
+much sense yet.
+
+Please see file TODO for things to do and keep the file ChangeLog
+up to date.
+
+Code is currently under heavy construction. Nearly all files will 
+change until next release. You can speed up development of notepad
+if you send patches and additions directly to my personal email 
+address <mbaur@g26.ethz.ch>.
+
+I also try to read news:comp.emulators.ms-windows.wine frequently, 
+so I can also integrate patches posted via usenet.
+
diff --git a/programs/notepad/TODO b/programs/notepad/TODO
new file mode 100644
index 0000000..d2d28b4
--- /dev/null
+++ b/programs/notepad/TODO
@@ -0,0 +1,8 @@
+
+ - En.rc is translated from german version of Notepad. 
+   I don't know what the real strings are, as I do not have an english
+   copy of Notepad. Please check strings in En.rc and submit corrections.
+
+ - create new *.rc files for all languages you know.
+
+
diff --git a/programs/notepad/license.c b/programs/notepad/license.c
new file mode 100644
index 0000000..eee36e1
--- /dev/null
+++ b/programs/notepad/license.c
@@ -0,0 +1,45 @@
+/*
+ * Notepad (license.h)
+ */
+
+#include "windows.h"
+#include "license.h"
+
+static LICENSE* SelectLanguage(LPCSTR Language)
+{
+/*  if (!lstrcmp(Language, "Cz")) return(&WineLicense_Cz); */
+/*  if (!lstrcmp(Language, "Da")) return(&WineLicense_Da); */
+/*  if (!lstrcmp(Language, "De")) return(&WineLicense_De); */
+/*  if (!lstrcmp(Language, "En")) return(&WineLicense_En); */
+/*  if (!lstrcmp(Language, "Eo")) return(&WineLicense_Eo); */
+/*  if (!lstrcmp(Language, "Es")) return(&WineLicense_Es); */
+/*  if (!lstrcmp(Language, "Fi")) return(&WineLicense_Fi); */
+/*  if (!lstrcmp(Language, "Fr")) return(&WineLicense_Fr); */
+/*  if (!lstrcmp(Language, "Hu")) return(&WineLicense_Hu); */
+/*  if (!lstrcmp(Language, "It")) return(&WineLicense_It); */
+/*  if (!lstrcmp(Langauge, "Ko")) return(&WineLicense_Ko); */
+/*  if (!lstrcmp(Language, "No")) return(&WineLicense_No); */
+/*  if (!lstrcmp(Language, "Pl")) return(&WineLicense_Pl); */
+/*  if (!lstrcmp(Language, "Po")) return(&WineLicense_Po); */
+/*  if (!lstrcmp(Language, "Va")) return(&WineLicense_Va); */
+  return(&WineLicense_En);
+}
+
+
+VOID WineLicense(HWND Wnd, LPCSTR Language)
+{
+  LICENSE *License = SelectLanguage(Language);
+
+  MessageBox(Wnd, License->License, License->LicenseCaption,
+	     MB_ICONINFORMATION | MB_OK);
+}
+
+
+VOID WineWarranty(HWND Wnd, LPCSTR Language)
+{
+  LICENSE *License = SelectLanguage(Language);
+
+  MessageBox(Wnd, License->Warranty, License->WarrantyCaption,
+	     MB_ICONEXCLAMATION | MB_OK);
+}
+
diff --git a/programs/notepad/license.h b/programs/notepad/license.h
new file mode 100644
index 0000000..c9a1e8d
--- /dev/null
+++ b/programs/notepad/license.h
@@ -0,0 +1,29 @@
+/*
+ * Notepad (license.h)
+ */
+
+VOID WineLicense(HWND hWnd, LPCSTR lpszLanguage);
+VOID WineWarranty(HWND hWnd, LPCSTR language);
+
+typedef struct
+{
+  LPCSTR License, LicenseCaption;
+  LPCSTR Warranty, WarrantyCaption;
+} LICENSE;
+
+/* extern LICENSE WineLicense_Cz; */
+/* extern LICENSE WineLicense_Da; */
+/* extern LICENSE WineLicense_De; */
+extern LICENSE WineLicense_En;
+/* extern LICENSE WineLicense_Eo; */
+/* extern LICENSE WineLicense_Es; */
+/* extern LICENSE WineLicense_Fi; */
+/* extern LICENSE WineLicense_Fr; */
+/* extern LICENSE WineLicense_Hu; */
+/* extern LICENSE WineLicense_It; */
+/* extern LICENSE WineLicense_Ko; */
+/* extern LICENSE WineLicense_No; */
+/* extern LICENSE WineLicense_Pl; */
+/* extern LICENSE WineLicense_Po; */
+/* extern LICENSE WineLicense_Va; */
+
diff --git a/programs/notepad/notepad.rc b/programs/notepad/notepad.rc
new file mode 100644
index 0000000..0079af5
--- /dev/null
+++ b/programs/notepad/notepad.rc
@@ -0,0 +1,58 @@
+/*
+ * Notepad (notepad.rc)
+ *
+ * Copyright 1997 Marcel Baur <mbaur@g26.ethz.ch>
+ */
+
+#define CONCAT(a, b) a##b
+
+/* Main Menu */
+
+CONCAT(MENU_, LANGUAGE_ID) MENU
+{
+ POPUP MENU_FILE {
+   MENUITEM MENU_FILE_NEW,              NP_NEW 
+   MENUITEM MENU_FILE_OPEN,             NP_OPEN
+   MENUITEM MENU_FILE_SAVE,             NP_SAVE
+   MENUITEM MENU_FILE_SAVEAS,           NP_SAVEAS
+   MENUITEM MENU_FILE_PRINT,            NP_PRINT
+   MENUITEM MENU_FILE_PAGESETUP,        NP_PAGESETUP
+   MENUITEM MENU_FILE_PRINTSETUP,       NP_PRINTSETUP
+   MENUITEM SEPARATOR   
+   MENUITEM MENU_FILE_EXIT,             NP_EXIT
+ }
+ POPUP MENU_EDIT {
+   MENUITEM MENU_EDIT_UNDO,             NP_EDIT_UNDO
+   MENUITEM SEPARATOR
+   MENUITEM MENU_EDIT_CUT,              NP_EDIT_CUT,     GRAYED
+   MENUITEM MENU_EDIT_COPY,             NP_EDIT_COPY,    GRAYED
+   MENUITEM MENU_EDIT_PASTE,            NP_EDIT_PASTE,   GRAYED
+   MENUITEM MENU_EDIT_DELETE,           NP_EDIT_DELETE,  GRAYED
+   MENUITEM SEPARATOR
+   MENUITEM MENU_EDIT_SELECTALL,        NP_EDIT_SELECTALL
+   MENUITEM MENU_EDIT_TIMEDATE,         NP_EDIT_TIMEDATE
+   MENUITEM SEPARATOR
+   MENUITEM MENU_EDIT_WRAP,             NP_EDIT_WRAP
+ }
+ POPUP MENU_SEARCH {
+   MENUITEM MENU_SEARCH_SEARCH,         NP_SEARCH_SEARCH
+   MENUITEM MENU_SEARCH_NEXT,           NP_SEARCH_NEXT
+ }
+ POPUP MENU_LANGUAGE {
+   /* Dummy item, will be removed */
+   MENUITEM SEPARATOR
+ }
+ POPUP MENU_HELP {
+   MENUITEM MENU_HELP_CONTENTS,         PM_CONTENTS
+   MENUITEM MENU_HELP_SEARCH,           PM_SEARCH
+   MENUITEM MENU_HELP_HELP_ON_HELP,     PM_HELPONHELP
+   MENUITEM SEPARATOR
+
+ POPUP MENU_INFO {
+   MENUITEM MENU_INFO_LICENSE,        PM_LICENSE
+   MENUITEM MENU_INFO_NO_WARRANTY,    PM_NO_WARRANTY
+   MENUITEM MENU_INFO_ABOUT_WINE,     PM_ABOUT_WINE
+  }
+}
+}
+
diff --git a/rc/winerc.c b/rc/winerc.c
index ea8aa65..058343b 100644
--- a/rc/winerc.c
+++ b/rc/winerc.c
@@ -8,7 +8,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/stat.h>
-#include <sys/fcntl.h>
+#include <fcntl.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <string.h>
diff --git a/relay32/Makefile.in b/relay32/Makefile.in
new file mode 100644
index 0000000..74603e6
--- /dev/null
+++ b/relay32/Makefile.in
@@ -0,0 +1,63 @@
+DEFS      = @DLLFLAGS@ -D__WINE__
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = relay32
+
+DLLS = \
+	advapi32.spec \
+	comctl32.spec \
+	comdlg32.spec \
+	crtdll.spec \
+	dciman32.spec \
+	gdi32.spec \
+	kernel32.spec \
+	lz32.spec \
+	mpr.spec \
+	msvfw32.spec \
+	ntdll.spec \
+	ole32.spec \
+	olecli32.spec \
+	olesvr32.spec \
+	shell32.spec \
+	tapi32.spec \
+	user32.spec \
+	version.spec \
+	w32skrnl.spec \
+	winmm.spec \
+	winspool.spec \
+	wow32.spec \
+	wsock32.spec
+
+C_SRCS = \
+	builtin32.c \
+	relay386.c
+
+SPEC_FILES = $(DLLS:.spec=.c)
+
+EXTRA_OBJS = $(DLLS:.spec=.o)
+
+GEN_ASM_SRCS = \
+	call32.s
+
+.SUFFIXES: .spec
+
+.spec.c:
+	$(BUILD) -o $@ -spec $<
+
+all: checkbuild $(MODULE).o
+
+@MAKE_RULES@
+
+$(SPEC_FILES): $(BUILD)
+
+$(EXTRA_OBJS): $(TOPSRCDIR)/include/builtin32.h
+
+call32.s: $(BUILD)
+	$(BUILD) -o $@ -call32
+
+clean::
+	$(RM) $(SPEC_FILES)
+
+### Dependencies:
diff --git a/if1632/advapi32.spec b/relay32/advapi32.spec
similarity index 100%
rename from if1632/advapi32.spec
rename to relay32/advapi32.spec
diff --git a/relay32/builtin32.c b/relay32/builtin32.c
new file mode 100644
index 0000000..8bdf3eb
--- /dev/null
+++ b/relay32/builtin32.c
@@ -0,0 +1,379 @@
+/*
+ * Win32 builtin functions
+ *
+ * Copyright 1997 Alexandre Julliard
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include "builtin32.h"
+#include "module.h"
+#include "task.h"
+#include "process.h"
+#include "stddebug.h"
+#include "debug.h"
+
+typedef struct
+{
+    BYTE  call;                    /* 0xe8 call callfrom32 (relative) */
+    DWORD callfrom32 WINE_PACKED;  /* RELAY_CallFrom32 relative addr */
+    BYTE  ret;                     /* 0xc2 ret $n  or  0xc3 ret */
+    WORD  args;                    /* nb of args to remove from the stack */
+} DEBUG_ENTRY_POINT;
+
+typedef struct
+{
+    BYTE  pushl;                   /* 0x68 pushl $func_to_call */
+    DWORD func WINE_PACKED;        /* func to call */
+    BYTE  jmp;                     /* 0xe9 jmp CALL32_Regs (relative) */
+    DWORD call32_regs WINE_PACKED; /* CALL32_Regs relative addr */
+    WORD  nop;                     /* 0x9090 nop;nop */
+} REG_ENTRY_POINT;
+
+typedef struct
+{
+    const BUILTIN32_DESCRIPTOR *descr;     /* DLL descriptor */
+    DEBUG_ENTRY_POINT          *dbg_funcs; /* Relay debugging functions table*/
+    BOOL32                      used;      /* Used by default */
+} BUILTIN32_DLL;
+
+
+extern const BUILTIN32_DESCRIPTOR ADVAPI32_Descriptor;
+extern const BUILTIN32_DESCRIPTOR COMCTL32_Descriptor;
+extern const BUILTIN32_DESCRIPTOR COMDLG32_Descriptor;
+extern const BUILTIN32_DESCRIPTOR CRTDLL_Descriptor;
+extern const BUILTIN32_DESCRIPTOR DCIMAN32_Descriptor;
+extern const BUILTIN32_DESCRIPTOR GDI32_Descriptor;
+extern const BUILTIN32_DESCRIPTOR KERNEL32_Descriptor;
+extern const BUILTIN32_DESCRIPTOR LZ32_Descriptor;
+extern const BUILTIN32_DESCRIPTOR MPR_Descriptor;
+extern const BUILTIN32_DESCRIPTOR MSVFW32_Descriptor;
+extern const BUILTIN32_DESCRIPTOR NTDLL_Descriptor;
+extern const BUILTIN32_DESCRIPTOR OLE32_Descriptor;
+extern const BUILTIN32_DESCRIPTOR OLECLI32_Descriptor;
+extern const BUILTIN32_DESCRIPTOR OLESVR32_Descriptor;
+extern const BUILTIN32_DESCRIPTOR SHELL32_Descriptor;
+extern const BUILTIN32_DESCRIPTOR TAPI32_Descriptor;
+extern const BUILTIN32_DESCRIPTOR USER32_Descriptor;
+extern const BUILTIN32_DESCRIPTOR VERSION_Descriptor;
+extern const BUILTIN32_DESCRIPTOR W32SKRNL_Descriptor;
+extern const BUILTIN32_DESCRIPTOR WINMM_Descriptor;
+extern const BUILTIN32_DESCRIPTOR WINSPOOL_Descriptor;
+extern const BUILTIN32_DESCRIPTOR WOW32_Descriptor;
+extern const BUILTIN32_DESCRIPTOR WSOCK32_Descriptor;
+
+static BUILTIN32_DLL BuiltinDLLs[] =
+{
+    { &ADVAPI32_Descriptor, NULL, TRUE  },
+    { &COMCTL32_Descriptor, NULL, FALSE },
+    { &COMDLG32_Descriptor, NULL, TRUE  },
+    { &CRTDLL_Descriptor,   NULL, TRUE  },
+    { &DCIMAN32_Descriptor, NULL, TRUE  },
+    { &GDI32_Descriptor,    NULL, TRUE  },
+    { &KERNEL32_Descriptor, NULL, TRUE  },
+    { &LZ32_Descriptor,     NULL, TRUE  },
+    { &MPR_Descriptor,      NULL, TRUE  },
+    { &MSVFW32_Descriptor,  NULL, TRUE  },
+    { &NTDLL_Descriptor,    NULL, TRUE  },
+    { &OLE32_Descriptor,    NULL, FALSE },
+    { &OLECLI32_Descriptor, NULL, FALSE },
+    { &OLESVR32_Descriptor, NULL, FALSE },
+    { &SHELL32_Descriptor,  NULL, TRUE  },
+    { &TAPI32_Descriptor,   NULL, TRUE  },
+    { &USER32_Descriptor,   NULL, TRUE  },
+    { &VERSION_Descriptor,  NULL, TRUE  },
+    { &W32SKRNL_Descriptor, NULL, TRUE  },
+    { &WINMM_Descriptor,    NULL, TRUE  },
+    { &WINSPOOL_Descriptor, NULL, TRUE  },
+    { &WOW32_Descriptor,    NULL, TRUE  },
+    { &WSOCK32_Descriptor,  NULL, TRUE  },
+    /* Last entry */
+    { NULL, NULL, FALSE }
+};
+
+
+/***********************************************************************
+ *           BUILTIN32_DoLoadModule
+ *
+ * Load a built-in Win32 module. Helper function for BUILTIN32_LoadModule.
+ */
+static HMODULE32 BUILTIN32_DoLoadModule( BUILTIN32_DLL *dll )
+{
+    extern void RELAY_CallFrom32();
+    extern void CALL32_Regs();
+
+    HMODULE16 hModule;
+    NE_MODULE *pModule;
+    OFSTRUCT ofs;
+    IMAGE_DATA_DIRECTORY *dir;
+    IMAGE_DOS_HEADER *dos;
+    IMAGE_NT_HEADERS *nt;
+    IMAGE_SECTION_HEADER *sec;
+    IMAGE_EXPORT_DIRECTORY *exp;
+    LPVOID *funcs;
+    LPSTR *names;
+    DEBUG_ENTRY_POINT *debug;
+    REG_ENTRY_POINT *regs;
+    PE_MODREF *pem;
+    INT32 i, size;
+    BYTE *addr;
+
+    /* Allocate the module */
+
+    size = (sizeof(IMAGE_DOS_HEADER)
+            + sizeof(IMAGE_NT_HEADERS)
+            + 2 * sizeof(IMAGE_SECTION_HEADER)
+            + sizeof(IMAGE_EXPORT_DIRECTORY)
+            + dll->descr->nb_funcs * sizeof(LPVOID)
+            + dll->descr->nb_names * sizeof(LPSTR)
+            + dll->descr->nb_reg_funcs * sizeof(REG_ENTRY_POINT));
+#ifdef __i386__
+    if (debugging_relay)
+        size += dll->descr->nb_funcs * sizeof(DEBUG_ENTRY_POINT);
+#endif
+    addr  = VirtualAlloc( NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
+    if (!addr) return 0;
+    dos   = (IMAGE_DOS_HEADER *)addr;
+    nt    = (IMAGE_NT_HEADERS *)(dos + 1);
+    sec   = (IMAGE_SECTION_HEADER *)(nt + 1);
+    exp   = (IMAGE_EXPORT_DIRECTORY *)(sec + 2);
+    funcs = (LPVOID *)(exp + 1);
+    names = (LPSTR *)(funcs + dll->descr->nb_funcs);
+    regs  = (REG_ENTRY_POINT *)(names + dll->descr->nb_names);
+    debug = (DEBUG_ENTRY_POINT *)(regs + dll->descr->nb_reg_funcs);
+
+    /* Build the DOS and NT headers */
+
+    dos->e_magic  = IMAGE_DOS_SIGNATURE;
+    dos->e_lfanew = sizeof(*dos);
+
+    nt->Signature                       = IMAGE_NT_SIGNATURE;
+    nt->FileHeader.Machine              = IMAGE_FILE_MACHINE_I386;
+    nt->FileHeader.NumberOfSections     = 2;  /* exports + code */
+    nt->FileHeader.SizeOfOptionalHeader = sizeof(nt->OptionalHeader);
+    nt->FileHeader.Characteristics      = IMAGE_FILE_DLL;
+
+    nt->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
+    nt->OptionalHeader.SizeOfCode                  = 0x1000;
+    nt->OptionalHeader.SizeOfInitializedData       = 0;
+    nt->OptionalHeader.SizeOfUninitializedData     = 0;
+    nt->OptionalHeader.ImageBase                   = (DWORD)addr;
+    nt->OptionalHeader.SectionAlignment            = 0x1000;
+    nt->OptionalHeader.FileAlignment               = 0x1000;
+    nt->OptionalHeader.MajorOperatingSystemVersion = 1;
+    nt->OptionalHeader.MinorOperatingSystemVersion = 0;
+    nt->OptionalHeader.MajorSubsystemVersion       = 4;
+    nt->OptionalHeader.MinorSubsystemVersion       = 0;
+    nt->OptionalHeader.SizeOfImage                 = size;
+    nt->OptionalHeader.SizeOfHeaders               = (BYTE *)exp - addr;
+    nt->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
+
+    /* Build the export directory */
+
+    dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
+    dir->VirtualAddress = (BYTE *)exp - addr;
+    dir->Size = sizeof(*exp)
+                + dll->descr->nb_funcs * sizeof(LPVOID)
+                + dll->descr->nb_names * sizeof(LPSTR);
+
+    /* Build the exports section */
+
+    strcpy( sec->Name, ".edata" );
+    sec->Misc.VirtualSize = dir->Size;
+    sec->VirtualAddress   = (BYTE *)exp - addr;
+    sec->SizeOfRawData    = dir->Size;
+    sec->PointerToRawData = (BYTE *)exp - addr;
+    sec->Characteristics  = (IMAGE_SCN_CNT_INITIALIZED_DATA |
+                             IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ |
+                             IMAGE_SCN_MEM_WRITE);
+
+    /* Build the code section */
+
+    sec++;
+    strcpy( sec->Name, ".code" );
+    sec->SizeOfRawData = dll->descr->nb_reg_funcs * sizeof(REG_ENTRY_POINT);
+#ifdef __i386__
+    if (debugging_relay)
+        sec->SizeOfRawData += dll->descr->nb_funcs * sizeof(DEBUG_ENTRY_POINT);
+#endif
+    sec->Misc.VirtualSize = sec->SizeOfRawData;
+    sec->VirtualAddress   = (BYTE *)regs - addr;
+    sec->PointerToRawData = (BYTE *)regs - addr;
+    sec->Characteristics  = (IMAGE_SCN_CNT_INITIALIZED_DATA |
+                             IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ);
+
+    /* Build the exports section data */
+
+    exp->Name                  = (BYTE *)dll->descr->name - addr;  /*??*/
+    exp->Base                  = dll->descr->base;
+    exp->NumberOfFunctions     = dll->descr->nb_funcs;
+    exp->NumberOfNames         = dll->descr->nb_names;
+    exp->AddressOfFunctions    = (LPDWORD *)((BYTE *)funcs - addr);
+    exp->AddressOfNames        = (LPDWORD *)((BYTE *)names - addr);
+    exp->AddressOfNameOrdinals = (LPWORD *)((BYTE *)dll->descr->ordinals - addr);
+
+    /* Build the funcs table */
+
+    if (debugging_relay) dll->dbg_funcs = debug;
+    for (i = 0; i < dll->descr->nb_funcs; i++, funcs++, debug++)
+    {
+        BYTE args = dll->descr->args[i];
+        if (!dll->descr->functions[i]) continue;
+#ifdef __i386__
+        switch(args)
+        {
+        case 0xfe:  /* register func */
+            regs->pushl       = 0x68;
+            regs->func        = (DWORD)dll->descr->functions[i];
+            regs->jmp         = 0xe9;
+            regs->call32_regs = (DWORD)CALL32_Regs - (DWORD)&regs->nop;
+            regs->nop         = 0x9090;
+            if (debugging_relay)
+            {
+                debug->call       = 0xe8;
+                debug->callfrom32 = (DWORD)regs - (DWORD)&debug->ret;
+                debug->ret        = 0x90;  /* nop */
+                debug->args       = 0;
+                *funcs = (LPVOID)((BYTE *)debug - addr);
+            }
+            else *funcs = (LPVOID)((BYTE *)regs - addr);
+            regs++;
+            break;
+        case 0xff:  /* stub or extern */
+            *funcs = (LPVOID)((BYTE *)dll->descr->functions[i] - addr);
+            break;
+        default:  /* normal function (stdcall or cdecl) */
+            if (debugging_relay)
+            {
+                debug->call       = 0xe8;
+                debug->callfrom32 = (DWORD)RELAY_CallFrom32 -
+                                    (DWORD)&debug->ret;
+                debug->ret        = (args & 0x80) ? 0xc3 : 0xc2; /*ret/ret $n*/
+                debug->args       = (args & 0x7f) * sizeof(int);
+                *funcs = (LPVOID)((BYTE *)debug - addr);
+            }
+            else
+                *funcs = (LPVOID)((BYTE *)dll->descr->functions[i] - addr);
+            break;
+        }
+#else  /* __i386__ */
+        *funcs = (LPVOID)((BYTE *)dll->descr->functions[i] - addr);
+#endif  /* __i386__ */
+    }
+
+    /* Build the names table */
+
+    for (i = 0; i < exp->NumberOfNames; i++, names++)
+        if (dll->descr->names[i])
+            *names = (LPSTR)((BYTE *)dll->descr->names[i] - addr);
+
+    /* Create a modref */
+
+    pem = (PE_MODREF *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+                                  sizeof(*pem) );
+    pem->module = (HMODULE32)addr;
+    pem->pe_export = exp;
+    pem->next = pCurrentProcess->modref_list;
+    pCurrentProcess->modref_list = pem;
+
+    /* Create a Win16 dummy module */
+
+    sprintf( ofs.szPathName, "%s.DLL", dll->descr->name );
+    hModule = MODULE_CreateDummyModule( &ofs );
+    pModule = (NE_MODULE *)GlobalLock16( hModule );
+    pModule->flags = NE_FFLAGS_SINGLEDATA | NE_FFLAGS_BUILTIN |
+                     NE_FFLAGS_LIBMODULE | NE_FFLAGS_WIN32;
+    pModule->module32 = (HMODULE32)addr;
+    return pModule->module32;
+}
+
+
+/***********************************************************************
+ *           BUILTIN32_LoadModule
+ *
+ * Load a built-in module. If the 'force' parameter is FALSE, we only
+ * load the module if it has not been disabled via the -dll option.
+ */
+HMODULE32 BUILTIN32_LoadModule( LPCSTR name, BOOL32 force )
+{
+    BUILTIN32_DLL *table;
+    char dllname[16], *p;
+
+    /* Fix the name in case we have a full path and extension */
+
+    if ((p = strrchr( name, '\\' ))) name = p + 1;
+    lstrcpyn32A( dllname, name, sizeof(dllname) );
+    if ((p = strrchr( dllname, '.' ))) *p = '\0';
+
+    for (table = BuiltinDLLs; table->descr; table++)
+        if (!lstrcmpi32A( table->descr->name, dllname )) break;
+    if (!table->descr) return 0;
+    if (!table->used && !force) return 0;
+
+    return BUILTIN32_DoLoadModule( table );
+}
+
+
+/***********************************************************************
+ *           BUILTIN32_GetEntryPoint
+ *
+ * Return the name of the DLL entry point corresponding
+ * to a relay entry point address. This is used only by relay debugging.
+ *
+ * This function _must_ return the real entry point to call
+ * after the debug info is printed.
+ */
+ENTRYPOINT32 BUILTIN32_GetEntryPoint( char *buffer, void *relay,
+                                      unsigned int *typemask )
+{
+    BUILTIN32_DLL *dll;
+    int ordinal, i;
+
+    /* First find the module */
+
+    for (dll = BuiltinDLLs; dll->descr; dll++)
+        if (((void *)dll->dbg_funcs <= relay) &&
+            ((void *)(dll->dbg_funcs + dll->descr->nb_funcs) > relay))
+            break;
+    assert(dll->descr);
+
+    /* Now find the function */
+
+    ordinal = ((DWORD)relay-(DWORD)dll->dbg_funcs) / sizeof(DEBUG_ENTRY_POINT);
+    for (i = 0; i < dll->descr->nb_names; i++)
+        if (dll->descr->ordinals[i] == ordinal) break;
+    assert( i < dll->descr->nb_names );
+
+    sprintf( buffer, "%s.%d: %s", dll->descr->name, ordinal + dll->descr->base,
+             dll->descr->names[i] );
+    *typemask = dll->descr->argtypes[ordinal];
+    return dll->descr->functions[ordinal];
+}
+
+
+/***********************************************************************
+ *           BUILTIN32_Unimplemented
+ *
+ * This function is called for unimplemented 32-bit entry points (declared
+ * as 'stub' in the spec file).
+ */
+void BUILTIN32_Unimplemented( const BUILTIN32_DESCRIPTOR *descr, int ordinal )
+{
+    const char *func_name = "???";
+    int i;
+
+    __RESTORE_ES;  /* Just in case */
+
+    for (i = 0; i < descr->nb_names; i++)
+        if (descr->ordinals[i] + descr->base == ordinal) break;
+    if (i < descr->nb_names) func_name = descr->names[i];
+
+    fprintf( stderr, "No handler for Win32 routine %s.%d: %s",
+             descr->name, ordinal, func_name );
+#ifdef __GNUC__
+    fprintf( stderr, " (called from %p)", __builtin_return_address(1) );
+#endif
+    fprintf( stderr, "\n" );
+    TASK_KillCurrentTask(1);
+}
diff --git a/if1632/comctl32.spec b/relay32/comctl32.spec
similarity index 100%
rename from if1632/comctl32.spec
rename to relay32/comctl32.spec
diff --git a/if1632/comdlg32.spec b/relay32/comdlg32.spec
similarity index 100%
rename from if1632/comdlg32.spec
rename to relay32/comdlg32.spec
diff --git a/if1632/crtdll.spec b/relay32/crtdll.spec
similarity index 99%
rename from if1632/crtdll.spec
rename to relay32/crtdll.spec
index 91b4e2d..a41af77 100644
--- a/if1632/crtdll.spec
+++ b/relay32/crtdll.spec
@@ -427,7 +427,7 @@
 423 cdecl localtime(ptr) localtime
 424 cdecl log(double) log
 425 cdecl log10(double) log10
-426 stub longjmp
+426 cdecl longjmp(ptr long) CRTDLL_longjmp
 427 cdecl malloc(ptr) CRTDLL_malloc
 428 cdecl mblen(ptr long) CRTDLL_mblen
 429 cdecl mbstowcs(ptr ptr long) CRTDLL_mbstowcs
diff --git a/relay32/dciman32.spec b/relay32/dciman32.spec
new file mode 100644
index 0000000..c7d10bc
--- /dev/null
+++ b/relay32/dciman32.spec
@@ -0,0 +1,25 @@
+name	dciman32
+type	win32
+
+  1 stub    DCIBeginAccess
+  2 stub    DCICloseProvider
+  3 stub    DCICreateOffscreen
+  4 stub    DCICreateOverlay
+  5 stub    DCICreatePrimary
+  6 stub    DCIDestroy
+  7 stub    DCIDraw
+  8 stub    DCIEndAccess
+  9 stub    DCIEnum
+ 10 stub    DCIOpenProvider
+ 11 stub    DCISetClipList
+ 12 stub    DCISetDestination
+ 13 stub    DCISetSrcDestClip
+ 14 stub    DllEntryPoint
+ 15 stub    GetDCRegionData
+ 16 stub    GetWindowRegionData
+ 17 stub    WinWatchClose
+ 18 stub    WinWatchDidStatusChange
+ 19 stub    WinWatchGetClipList
+ 20 stub    WinWatchNotify
+ 21 stub    WinWatchOpen
+ 22 stub    dcithk_ThunkData32
diff --git a/if1632/gdi32.spec b/relay32/gdi32.spec
similarity index 96%
rename from if1632/gdi32.spec
rename to relay32/gdi32.spec
index 686cfcf..e068279 100644
--- a/if1632/gdi32.spec
+++ b/relay32/gdi32.spec
@@ -2,7 +2,7 @@
 type	win32
 
   0 stub AbortDoc
-  1 stub AbortPath
+  1 stdcall AbortPath(long) AbortPath32
   2 stdcall AddFontResourceA(str) AddFontResource32A
   3 stub AddFontResourceTracking
   4 stdcall AddFontResourceW(wstr) AddFontResource32W
@@ -10,14 +10,14 @@
   6 stdcall AnimatePalette(long long long ptr) AnimatePalette32
   7 stdcall Arc(long long long long long long long long long) Arc32
   8 stub ArcTo
-  9 stub BeginPath
+  9 stdcall BeginPath(long) BeginPath32
  10 stdcall BitBlt(long long long long long long long long long) BitBlt32
  11 stub CancelDC
  12 stub CheckColorsInGamut
  13 stub ChoosePixelFormat
  14 stdcall Chord(long long long long long long long long long) Chord32
  15 stub CloseEnhMetaFile
- 16 stub CloseFigure
+ 16 stdcall CloseFigure(long) CloseFigure32
  17 stub CloseMetaFile
  18 stub ColorMatchToTarget
  19 stdcall CombineRgn(long long long long) CombineRgn32
@@ -50,7 +50,7 @@
  45 stdcall CreateFontIndirectW(ptr) CreateFontIndirect32W
  46 stdcall CreateFontW(long long long long long long long long
                         long long long long long wstr) CreateFont32W
- 47 stub CreateHalftonePalette
+ 47 stdcall CreateHalftonePalette(long) CreateHalftonePalette
  48 stdcall CreateHatchBrush(long long) CreateHatchBrush32
  49 stdcall CreateICA(str str str ptr) CreateIC32A
  50 stdcall CreateICW(wstr wstr wstr ptr) CreateIC32W
@@ -82,7 +82,7 @@
  75 stdcall Ellipse(long long long long long) Ellipse32
  76 stub EndDoc
  77 stub EndPage
- 78 stub EndPath
+ 78 stdcall EndPath(long) EndPath32
  79 stub EnumEnhMetaFile
  80 stdcall EnumFontFamiliesA(long str ptr long) EnumFontFamilies32A
  81 stdcall EnumFontFamiliesExA(long str ptr long long) EnumFontFamiliesEx32A
@@ -97,16 +97,16 @@
  90 stdcall EqualRgn(long long) EqualRgn32
  91 stdcall Escape(long long long ptr ptr) Escape32
  92 stdcall ExcludeClipRect(long long long long long) ExcludeClipRect32
- 93 stub ExtCreatePen
+ 93 stdcall ExtCreatePen(long long ptr long ptr) ExtCreatePen32
  94 stub ExtCreateRegion
  95 stdcall ExtEscape(long long long ptr long ptr) ExtEscape32
  96 stdcall ExtFloodFill(long long long long long) ExtFloodFill32
  97 stub ExtSelectClipRgn
  98 stdcall ExtTextOutA(long long long long ptr str long ptr) ExtTextOut32A
  99 stdcall ExtTextOutW(long long long long ptr wstr long ptr) ExtTextOut32W
-100 stub FillPath
+100 stdcall FillPath(long) FillPath32
 101 stdcall FillRgn(long long long) FillRgn32
-102 stub FixBrushOrgEx
+102 stdcall FixBrushOrgEx(long long long ptr) FixBrushOrgEx
 103 stub FlattenPath
 104 stdcall FloodFill(long long long long) FloodFill32
 105 stdcall FrameRgn(long long long long long) FrameRgn32
@@ -170,7 +170,7 @@
 163 stdcall GetClipRgn(long long) GetClipRgn32
 164 stub GetColorAdjustment
 165 stub GetColorSpace
-166 stub GetCurrentObject
+166 stdcall GetCurrentObject(long long) GetCurrentObject
 167 stdcall GetCurrentPositionEx(long ptr) GetCurrentPositionEx32
 168 stdcall GetDCOrgEx(long ptr) GetDCOrgEx
 169 stdcall GetDIBColorTable(long long long ptr) GetDIBColorTable32
@@ -214,7 +214,7 @@
 207 stub GetOutlineTextMetricsA
 208 stub GetOutlineTextMetricsW
 209 stdcall GetPaletteEntries(long long long ptr) GetPaletteEntries32
-210 stub GetPath
+210 stdcall GetPath(long ptr ptr long) GetPath32
 211 stdcall GetPixel(long long long) GetPixel32
 212 stub GetPixelFormat
 213 stdcall GetPolyFillMode(long) GetPolyFillMode32
@@ -265,7 +265,7 @@
 258 stdcall OffsetWindowOrgEx(long long long ptr) OffsetWindowOrgEx32
 259 stdcall PaintRgn(long long) PaintRgn32
 260 stdcall PatBlt(long long long long long long) PatBlt32
-261 stub PathToRegion
+261 stdcall PathToRegion(long) PathToRegion32
 262 stdcall Pie(long long long long long long long long long) Pie32
 263 stub PlayEnhMetaFile
 264 stub PlayEnhMetaFileRecord
@@ -300,7 +300,7 @@
 293 stdcall ScaleViewportExtEx(long long long long long ptr) ScaleViewportExtEx32
 294 stdcall ScaleWindowExtEx(long long long long long ptr) ScaleWindowExtEx32
 295 stub SelectBrushLocal
-296 stub SelectClipPath
+296 stdcall SelectClipPath(long long) SelectClipPath32
 297 stdcall SelectClipRgn(long long) SelectClipRgn32
 298 stub SelectFontLocal
 299 stdcall SelectObject(long long) SelectObject32
diff --git a/if1632/kernel32.spec b/relay32/kernel32.spec
similarity index 97%
rename from if1632/kernel32.spec
rename to relay32/kernel32.spec
index 4de6ca3..7dde6b4 100644
--- a/if1632/kernel32.spec
+++ b/relay32/kernel32.spec
@@ -169,7 +169,7 @@
 178 stdcall CreateThread(ptr long ptr long long ptr) CreateThread
 179 stub CreateToolhelp32Snapshot
 180 stub DebugActiveProcess
-181 register DebugBreak() DebugBreak32
+181 stub DebugBreak
 182 stub DefineDosDeviceA
 183 stub DefineDosDeviceW
 184 stdcall DeleteAtom(long) DeleteAtom32
@@ -236,11 +236,11 @@
 245 stdcall FindAtomW(wstr) FindAtom32W
 247 stub FindCloseChangeNotification
 246 stdcall FindClose(long) FindClose32
-248 stub FindFirstChangeNotificationA
+248 stdcall FindFirstChangeNotificationA(str long long) FindFirstChangeNotification32A
 249 stub FindFirstChangeNotificationW
 250 stdcall FindFirstFileA(str ptr) FindFirstFile32A
 251 stdcall FindFirstFileW(wstr ptr) FindFirstFile32W
-252 stub FindNextChangeNotification
+252 stdcall FindNextChangeNotification(long) FindNextChangeNotification
 253 stdcall FindNextFileA(long ptr) FindNextFile32A
 254 stdcall FindNextFileW(long ptr) FindNextFile32W
 255 stdcall FindResourceA(long str str) FindResource32A
@@ -284,7 +284,7 @@
 293 stdcall GetComputerNameA(ptr ptr) GetComputerName32A
 294 stdcall GetComputerNameW(ptr ptr) GetComputerName32W
 295 stdcall GetConsoleCP() GetConsoleCP
-296 stub GetConsoleCursorInfo
+296 stdcall GetConsoleCursorInfo(long ptr) GetConsoleCursorInfo32
 297 stdcall GetConsoleMode(long ptr) GetConsoleMode
 298 stdcall GetConsoleOutputCP() GetConsoleOutputCP
 299 stdcall GetConsoleScreenBufferInfo(long ptr) GetConsoleScreenBufferInfo
@@ -346,7 +346,7 @@
 355 stub GetNumberFormatA
 356 stub GetNumberFormatW
 357 stdcall GetNumberOfConsoleInputEvents(long ptr) GetNumberOfConsoleInputEvents
-358 stub GetNumberOfConsoleMouseButtons
+358 stdcall GetNumberOfConsoleMouseButtons(long ptr) GetNumberOfConsoleMouseButtons
 359 stdcall GetOEMCP() GetOEMCP
 360 stub GetOverlappedResult
 361 stdcall GetPriorityClass(long) GetPriorityClass
@@ -538,8 +538,8 @@
 547 stub OpenVxDHandle
 548 stdcall OutputDebugStringA(str) OutputDebugString32A
 549 stdcall OutputDebugStringW(wstr) OutputDebugString32W
-550 stub PeekConsoleInputA
-551 stub PeekConsoleInputW
+550 stdcall PeekConsoleInputA(ptr ptr long ptr) PeekConsoleInput32A
+551 stdcall PeekConsoleInputW(ptr ptr long ptr) PeekConsoleInput32W
 552 stub PeekNamedPipe
 553 stub PostQueuedCompletionStatus
 554 stub PrepareTape
@@ -590,7 +590,7 @@
 599 register SMapLS_IP_EBP_36() SMapLS_IP_EBP_36
 600 register SMapLS_IP_EBP_40() SMapLS_IP_EBP_40
 601 register SMapLS_IP_EBP_8() SMapLS_IP_EBP_8
-602 stub SUnMapLS
+602 register SUnMapLS() SUnMapLS
 603 register SUnMapLS_IP_EBP_12() SUnMapLS_IP_EBP_12
 604 register SUnMapLS_IP_EBP_16() SUnMapLS_IP_EBP_16
 605 register SUnMapLS_IP_EBP_20() SUnMapLS_IP_EBP_20
@@ -614,7 +614,7 @@
 623 stub SetConsoleActiveScreenBuffer
 624 stub SetConsoleCP
 625 stdcall SetConsoleCtrlHandler(ptr long) SetConsoleCtrlHandler
-626 stub SetConsoleCursorInfo
+626 stdcall SetConsoleCursorInfo(long ptr) SetConsoleCursorInfo32
 627 stdcall SetConsoleCursorPosition(long long) SetConsoleCursorPosition
 628 stdcall SetConsoleMode(long long) SetConsoleMode
 629 stub SetConsoleOutputCP
@@ -728,7 +728,7 @@
 737 stdcall WriteConsoleW(long ptr long ptr ptr) WriteConsole32W
 738 stdcall WriteFile(long ptr long ptr ptr) WriteFile
 739 stub WriteFileEx
-740 stub WritePrivateProfileSectionA
+740 stdcall WritePrivateProfileSectionA(str str str) WritePrivateProfileSection32A
 741 stub WritePrivateProfileSectionW
 742 stdcall WritePrivateProfileStringA(str str str str) WritePrivateProfileString32A
 743 stdcall WritePrivateProfileStringW(wstr wstr wstr wstr) WritePrivateProfileString32W
@@ -860,15 +860,15 @@
 868 stub GetConsoleInputExeNameW
 869 stub GetConsoleKeyboardLayoutNameA
 870 stub GetConsoleKeyboardLayoutNameW
-871 stub GetDiskFreeSpaceExA
-873 stub GetDiskFreeSpaceExW
+871 stdcall GetDiskFreeSpaceExA (str ptr ptr ptr) GetDiskFreeSpaceEx32A
+873 stdcall GetDiskFreeSpaceExW (wstr ptr ptr ptr) GetDiskFreeSpaceEx32W
 874 stub GetFileAttributesExA
 875 stub GetFileAttributesExW
 876 stub GetProcessPriorityBoost
 877 stub GetThreadPriorityBoost
 878 stub InterlockedCompareExchange
 879 stub InterlockedExchangeAdd
-880 stub IsProcessorFeaturePresent
+880 stdcall IsProcessorFeaturePresent(long) IsProcessorFeaturePresent
 881 stub OpenWaitableTimerA
 882 stub OpenWaitableTimerW
 883 stub ReadConsoleInputExA
diff --git a/if1632/lz32.spec b/relay32/lz32.spec
similarity index 100%
rename from if1632/lz32.spec
rename to relay32/lz32.spec
diff --git a/if1632/mpr.spec b/relay32/mpr.spec
similarity index 100%
rename from if1632/mpr.spec
rename to relay32/mpr.spec
diff --git a/relay32/msvfw32.spec b/relay32/msvfw32.spec
new file mode 100644
index 0000000..1f75461
--- /dev/null
+++ b/relay32/msvfw32.spec
@@ -0,0 +1,52 @@
+name	msvfw32
+type	win32
+
+  2 stub    VideoForWindowsVersion
+  3 stub    DrawDibBegin
+  4 stub    DrawDibChangePalette
+  5 stub    DrawDibClose
+  6 stub    DrawDibDraw
+  7 stub    DrawDibEnd
+  8 stub    DrawDibGetBuffer
+  9 stub    DrawDibGetPalette
+ 10 stub    DrawDibOpen
+ 11 stub    DrawDibProfileDisplay
+ 12 stub    DrawDibRealize
+ 13 stub    DrawDibSetPalette
+ 14 stub    DrawDibStart
+ 15 stub    DrawDibStop
+ 16 stub    DrawDibTime
+ 17 stub    GetOpenFileNamePreview
+ 18 stub    GetOpenFileNamePreviewA
+ 19 stub    GetOpenFileNamePreviewW
+ 20 stub    GetSaveFileNamePreviewA
+ 21 stub    GetSaveFileNamePreviewW
+ 22 stub    ICClose
+ 23 stub    ICCompress
+ 24 stub    ICCompressorChoose
+ 25 stub    ICCompressorFree
+ 26 stub    ICDecompress
+ 27 stub    ICDraw
+ 28 stub    ICDrawBegin
+ 29 stub    ICGetDisplayFormat
+ 30 stub    ICGetInfo
+ 31 stub    ICImageCompress
+ 32 stub    ICImageDecompress
+ 33 stub    ICInfo
+ 34 stub    ICInstall
+ 35 stub    ICLocate
+ 36 stub    ICMThunk32
+ 37 stub    ICOpen
+ 38 stub    ICOpenFunction
+ 39 stub    ICRemove
+ 40 stub    ICSendMessage
+ 41 stub    ICSeqCompressFrame
+ 42 stub    ICSeqCompressFrameEnd
+ 43 stub    ICSeqCompressFrameStart
+ 44 stub    MCIWndCreate
+ 45 stub    MCIWndCreateA
+ 46 stub    MCIWndCreateW
+ 47 stub    MCIWndRegisterClass
+ 48 stub    StretchDIB
+ 49 stub    ls_ThunkData32
+ 50 stub    sl_ThunkData32
diff --git a/if1632/ntdll.spec b/relay32/ntdll.spec
similarity index 100%
rename from if1632/ntdll.spec
rename to relay32/ntdll.spec
diff --git a/if1632/ole32.spec b/relay32/ole32.spec
similarity index 92%
rename from if1632/ole32.spec
rename to relay32/ole32.spec
index 18cec80..3faa9e5 100644
--- a/if1632/ole32.spec
+++ b/relay32/ole32.spec
@@ -3,12 +3,12 @@
 
   1 stub BindMoniker
   2 stub CLSIDFromProgID
-  3 stub CLSIDFromString
-  4 stub CoBuildVersion
+  3 stdcall CLSIDFromString(str ptr) CLSIDFromString
+  4 stdcall CoBuildVersion() CoBuildVersion
   5 stub CoCreateFreeThreadedMarshaler
   6 stub CoCreateGuid
   7 stub CoCreateInstance
-  8 stub CoDisconnectObject
+  8 stdcall CoDisconnectObject(ptr long) CoDisconnectObject
   9 stub CoDosDateTimeToFileTime
  10 stub CoFileTimeNow
  11 stub CoFileTimeToDosDateTime
@@ -20,13 +20,13 @@
  17 stub CoGetCurrentLogicalThreadId
  18 stub CoGetCurrentProcess
  19 stub CoGetInterfaceAndReleaseStream
- 20 stub CoGetMalloc
+ 20 stdcall CoGetMalloc(long ptr) CoGetMalloc
  21 stub CoGetMarshalSizeMax
  22 stub CoGetPSClsid
  23 stub CoGetStandardMarshal
  24 stub CoGetState
  25 stub CoGetTreatAsClass
- 26 stub CoInitialize
+ 26 stdcall CoInitialize(long) CoInitialize
  27 stub CoInitializeWOW
  28 stub CoIsHandlerConnected
  29 stub CoIsOle1Class
@@ -47,7 +47,7 @@
  44 stub CoTaskMemFree
  45 stub CoTaskMemRealloc
  46 stub CoTreatAsClass
- 47 stub CoUninitialize
+ 47 stdcall CoUninitialize() CoUnitialize
  48 stub CoUnloadingWOW
  49 stub CoUnmarshalHresult
  50 stub CoUnmarshalInterface
@@ -151,7 +151,7 @@
 148 stub StgOpenStorage
 149 stub StgOpenStorageOnILockBytes
 150 stub StgSetTimes
-151 stub StringFromCLSID
+151 stdcall StringFromCLSID(ptr ptr) StringFromCLSID
 152 stub StringFromGUID2
 153 stub StringFromIID
 154 stub UtConvertDvtd16toDvtd32
diff --git a/if1632/olecli32.spec b/relay32/olecli32.spec
similarity index 100%
rename from if1632/olecli32.spec
rename to relay32/olecli32.spec
diff --git a/if1632/olesvr32.spec b/relay32/olesvr32.spec
similarity index 100%
rename from if1632/olesvr32.spec
rename to relay32/olesvr32.spec
diff --git a/relay32/relay386.c b/relay32/relay386.c
new file mode 100644
index 0000000..1531e4a
--- /dev/null
+++ b/relay32/relay386.c
@@ -0,0 +1,203 @@
+/*
+ * 386-specific Win32 relay functions
+ *
+ * Copyright 1997 Alexandre Julliard
+ */
+
+#ifdef __i386__
+
+#include <assert.h>
+#include "winnt.h"
+#include "windows.h"
+#include "builtin32.h"
+#include "stddebug.h"
+#include "debug.h"
+
+
+/***********************************************************************
+ *           RELAY_CallFrom32
+ *
+ * Stack layout on entry to this function:
+ *  ...      ...
+ * (esp+12)  arg2
+ * (esp+8)   arg1
+ * (esp+4)   ret_addr
+ * (esp)     return addr to relay code
+ */
+int RELAY_CallFrom32( int ret_addr, ... )
+{
+    int i, ret;
+    char buffer[80];
+    FARPROC32 func;
+    unsigned int mask, typemask;
+
+    int *args = &ret_addr;
+    /* Relay addr is the return address for this function */
+    BYTE *relay_addr = (BYTE *)args[-1];
+    WORD nb_args = *(WORD *)(relay_addr + 1) / sizeof(int);
+
+    assert(debugging_relay);
+    func = (FARPROC32)BUILTIN32_GetEntryPoint( buffer, relay_addr - 5,
+                                               &typemask );
+    printf( "Call %s(", buffer );
+    args++;
+    for (i = 0, mask = 3; i < nb_args; i++, mask <<= 2)
+    {
+        if (i) printf( "," );
+	if ((typemask & mask) && HIWORD(args[i]))
+        {
+	    if (typemask & (2<<(2*i)))
+            {
+                char buff[80];
+                lstrcpynWtoA( buff, (LPWSTR)args[i], sizeof(buff) );
+	    	printf( "%08x L\"%s\"", args[i], buff );
+	    }
+            else printf( "%08x \"%s\"", args[i], (char *)args[i] );
+	}
+        else printf( "%08x", args[i] );
+    }
+    printf( ") ret=%08x\n", ret_addr );
+    if (*relay_addr == 0xc3) /* cdecl */
+    {
+        LRESULT (*cfunc)() = (LRESULT(*)())func;
+        switch(nb_args)
+        {
+        case 0: ret = cfunc(); break;
+        case 1: ret = cfunc(args[0]); break;
+        case 2: ret = cfunc(args[0],args[1]); break;
+        case 3: ret = cfunc(args[0],args[1],args[2]); break;
+        case 4: ret = cfunc(args[0],args[1],args[2],args[3]); break;
+        case 5: ret = cfunc(args[0],args[1],args[2],args[3],args[4]); break;
+        case 6: ret = cfunc(args[0],args[1],args[2],args[3],args[4],
+                            args[5]); break;
+        case 7: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
+                            args[6]); break;
+        case 8: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
+                            args[6],args[7]); break;
+        case 9: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
+                            args[6],args[7],args[8]); break;
+        case 10: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
+                             args[6],args[7],args[8],args[9]); break;
+        case 11: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
+                             args[6],args[7],args[8],args[9],args[10]); break;
+        case 12: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
+                             args[6],args[7],args[8],args[9],args[10],
+                             args[11]); break;
+        case 13: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
+                             args[6],args[7],args[8],args[9],args[10],args[11],
+                             args[12]); break;
+        case 14: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
+                             args[6],args[7],args[8],args[9],args[10],args[11],
+                             args[12],args[13]); break;
+        case 15: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
+                             args[6],args[7],args[8],args[9],args[10],args[11],
+                             args[12],args[13],args[14]); break;
+        default:
+            fprintf( stderr, "RELAY_CallFrom32: Unsupported nb args %d\n",
+                     nb_args );
+            assert(FALSE);
+        }
+    }
+    else  /* stdcall */
+    {
+        switch(nb_args)
+        {
+        case 0: ret = func(); break;
+        case 1: ret = func(args[0]); break;
+        case 2: ret = func(args[0],args[1]); break;
+        case 3: ret = func(args[0],args[1],args[2]); break;
+        case 4: ret = func(args[0],args[1],args[2],args[3]); break;
+        case 5: ret = func(args[0],args[1],args[2],args[3],args[4]); break;
+        case 6: ret = func(args[0],args[1],args[2],args[3],args[4],
+                           args[5]); break;
+        case 7: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
+                           args[6]); break;
+        case 8: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
+                           args[6],args[7]); break;
+        case 9: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
+                           args[6],args[7],args[8]); break;
+        case 10: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
+                            args[6],args[7],args[8],args[9]); break;
+        case 11: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
+                            args[6],args[7],args[8],args[9],args[10]); break;
+        case 12: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
+                            args[6],args[7],args[8],args[9],args[10],
+                            args[11]); break;
+        case 13: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
+                            args[6],args[7],args[8],args[9],args[10],args[11],
+                            args[12]); break;
+        case 14: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
+                            args[6],args[7],args[8],args[9],args[10],args[11],
+                            args[12],args[13]); break;
+        case 15: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
+                            args[6],args[7],args[8],args[9],args[10],args[11],
+                            args[12],args[13],args[14]); break;
+        default:
+            fprintf( stderr, "RELAY_CallFrom32: Unsupported nb args %d\n",
+                     nb_args );
+            assert(FALSE);
+        }
+    }
+    printf( "Ret  %s() retval=%08x ret=%08x\n", buffer, ret, ret_addr );
+    return ret;
+}
+
+
+/***********************************************************************
+ *           RELAY_CallFrom32Regs
+ *
+ * 'stack' points to the relay addr on the stack.
+ * Stack layout:
+ *  ...      ...
+ * (esp+216) ret_addr
+ * (esp+212) return to relay debugging code (only when debugging_relay)
+ * (esp+208) entry point to call
+ * (esp+4)   CONTEXT
+ * (esp)     return addr to relay code
+ */
+void RELAY_CallFrom32Regs( CONTEXT context,
+                           void (CALLBACK *entry_point)(CONTEXT *),
+                           BYTE *relay_addr, int ret_addr )
+{
+    if (!debugging_relay)
+    {
+        /* Simply call the entry point */
+        entry_point( &context );
+    }
+    else
+    {
+        char buffer[80];
+        unsigned int typemask;
+
+    	__RESTORE_ES;
+        /* Fixup the context structure because of the extra parameter */
+        /* pushed by the relay debugging code */
+
+        EIP_reg(&context) = ret_addr;
+        ESP_reg(&context) += sizeof(int);
+
+        BUILTIN32_GetEntryPoint( buffer, relay_addr - 5, &typemask );
+        printf("Call %s(regs) ret=%08x\n", buffer, ret_addr );
+        printf(" EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx ESI=%08lx EDI=%08lx\n",
+                EAX_reg(&context), EBX_reg(&context), ECX_reg(&context),
+                EDX_reg(&context), ESI_reg(&context), EDI_reg(&context) );
+        printf(" EBP=%08lx ESP=%08lx EIP=%08lx DS=%04lx ES=%04lx FS=%04lx GS=%04lx EFL=%08lx\n",
+                EBP_reg(&context), ESP_reg(&context), EIP_reg(&context),
+                DS_reg(&context), ES_reg(&context), FS_reg(&context),
+                GS_reg(&context), EFL_reg(&context) );
+
+        /* Now call the real function */
+        entry_point( &context );
+
+        printf("Ret  %s() retval=regs ret=%08x\n", buffer, ret_addr );
+        printf(" EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx ESI=%08lx EDI=%08lx\n",
+                EAX_reg(&context), EBX_reg(&context), ECX_reg(&context),
+                EDX_reg(&context), ESI_reg(&context), EDI_reg(&context) );
+        printf(" EBP=%08lx ESP=%08lx EIP=%08lx DS=%04lx ES=%04lx FS=%04lx GS=%04lx EFL=%08lx\n",
+                EBP_reg(&context), ESP_reg(&context), EIP_reg(&context),
+                DS_reg(&context), ES_reg(&context), FS_reg(&context),
+                GS_reg(&context), EFL_reg(&context) );
+    }
+}
+
+#endif  /* __i386__ */
diff --git a/if1632/shell32.spec b/relay32/shell32.spec
similarity index 90%
rename from if1632/shell32.spec
rename to relay32/shell32.spec
index 9867e60..f31d8a3 100644
--- a/if1632/shell32.spec
+++ b/relay32/shell32.spec
@@ -5,7 +5,7 @@
 # (these need to have these exact ordinals, for some win95 dlls 
 #  import shell32.dll by ordinal)
 
-   2 stub SHELL32_2
+   2 stdcall SHELL32_2(long long long long long long) SHELL32_2
    3 stub CheckEscapesA
    4 stub SHELL32_4
    5 stub SHELL32_5
@@ -29,10 +29,10 @@
   27 stub SHELL32_27
   28 stub SHELL32_28
   29 stdcall SHELL32_29(str) SHELL32_29
-  30 stub SHELL32_30
-  31 stub SHELL32_31
+  30 stdcall SHELL32_30(ptr long) SHELL32_30
+  31 stdcall SHELL32_31(str) SHELL32_31
   32 stdcall SHELL32_32(str) SHELL32_32
-  33 stub SHELL32_33
+  33 stdcall SHELL32_33(str) SHELL32_33
   34 stdcall SHELL32_34(str) SHELL32_34
   35 stdcall SHELL32_35(str) SHELL32_35
   36 stdcall SHELL32_36(str str) SHELL32_36
@@ -55,19 +55,19 @@
   53 stub DragQueryFileAorW
   54 stub DragQueryFileW
   55 stub SHELL32_55
-  56 stub SHELL32_56
+  56 stdcall SHELL32_56(str) SHELL32_56
   57 stub SHELL32_57
-  58 stub SHELL32_58
+  58 stdcall SHELL32_58(long long long long) SHELL32_58
   59 stub SHELL32_59
   60 stub SHELL32_60
   61 stub SHELL32_61
   62 stdcall SHELL32_62(long long long long) SHELL32_62
-  63 stub SHELL32_63
+  63 stdcall SHELL32_63(long long long long str str str) SHELL32_63
   64 stub SHELL32_64
   65 stub SHELL32_65
   66 stub SHELL32_66
   67 stub SHELL32_67
-  68 stub SHELL32_68
+  68 stdcall SHELL32_68(long long long) SHELL32_68
   69 stub SHELL32_69
   70 stub SHELL32_70
   71 stdcall SHELL32_71(ptr ptr) SHELL32_71
@@ -88,7 +88,7 @@
   86 stub SHELL32_86
   87 stub SHELL32_87
   88 stub SHELL32_88
-  89 stub SHELL32_89
+  89 stdcall SHELL32_89(long long long) SHELL32_89
   90 stub SHELL32_90
   91 stub SHELL32_91
   92 stub SHELL32_92
@@ -100,7 +100,7 @@
   98 stub SHELL32_98
   99 stub SHELL32_99
  100 stdcall SHELL32_100(long) SHELL32_100
- 101 stub ExtractAssociatedIconExA
+ 101 stdcall ExtractAssociatedIconA(long ptr long) ExtractAssociatedIcon32A
  102 stdcall SHELL32_102(ptr ptr long ptr ptr) SHELL32_102
  103 stub SHELL32_103
  104 stub SHELL32_104
@@ -219,10 +219,10 @@
  217 stdcall SHGetFileInfo(ptr long ptr long long) SHGetFileInfo32A
  218 stdcall SHGetFileInfoA(ptr long ptr long long) SHGetFileInfo32A
  219 stub SHGetInstanceExplorer
- 220 stub SHGetMalloc
- 221 stub SHGetPathFromIDList
+ 220 stdcall SHGetMalloc(ptr) SHGetMalloc
+ 221 stdcall SHGetPathFromIDList(ptr ptr) SHGetPathFromIDList
  222 stub SHGetPathFromIDListA
- 223 stub SHGetSpecialFolderLocation
+ 223 stdcall SHGetSpecialFolderLocation(long long ptr) SHGetSpecialFolderLocation
  224 stub SHHelpShortcuts_RunDLL
  225 stub SHLoadInProc
  226 stub SheChangeDirA
@@ -248,8 +248,8 @@
  246 stub ShellExecuteEx
  247 stub ShellExecuteExA
  248 stub ShellExecuteW
- 249 stub Shell_NotifyIcon
- 250 stub Shell_NotifyIconA
+ 249 stdcall Shell_NotifyIcon(long ptr) Shell_NotifyIcon
+ 250 stdcall Shell_NotifyIconA(long ptr) Shell_NotifyIconA
  251 stub Shl1632_ThunkData32
  252 stub Shl3216_ThunkData32
  505 stub SHELL32_505
diff --git a/relay32/tapi32.spec b/relay32/tapi32.spec
new file mode 100644
index 0000000..011d0ab
--- /dev/null
+++ b/relay32/tapi32.spec
@@ -0,0 +1,117 @@
+name	tapi32
+type	win32
+
+  1 stub    lineAccept
+  2 stub    lineAddProvider
+  3 stub    lineAddToConference
+  4 stub    lineAnswer
+  5 stub    lineBlindTransfer
+  6 stub    lineClose
+  7 stub    lineCompleteCall
+  8 stub    lineCompleteTransfer
+  9 stub    lineConfigDialog
+ 10 stub    lineConfigDialogEdit
+ 11 stub    lineConfigProvider
+ 12 stub    lineDeallocateCall
+ 13 stub    lineDevSpecific
+ 14 stub    lineDevSpecificFeature
+ 15 stub    lineDial
+ 16 stub    lineDrop
+ 17 stub    lineForward
+ 18 stub    lineGatherDigits
+ 19 stub    lineGenerateDigits
+ 20 stub    lineGenerateTone
+ 21 stub    lineGetAddressCaps
+ 22 stub    lineGetAddressID
+ 23 stub    lineGetAddressStatus
+ 24 stub    lineGetAppPriority
+ 25 stub    lineGetCallInfo
+ 26 stub    lineGetCallStatus
+ 27 stub    lineGetConfRelatedCalls
+ 28 stub    lineGetCountry
+ 29 stub    lineGetDevCaps
+ 30 stub    lineGetDevConfig
+ 31 stub    lineGetID
+ 32 stub    lineGetIcon
+ 33 stub    lineGetLineDevStatus
+ 34 stub    lineGetNewCalls
+ 35 stub    lineGetNumRings
+ 36 stub    lineGetProviderList
+ 37 stub    lineGetRequest
+ 38 stub    lineGetStatusMessages
+ 39 stub    lineGetTranslateCaps
+ 40 stub    lineHandoff
+ 41 stub    lineHold
+ 42 stub    lineInitialize
+ 43 stub    lineMakeCall
+ 44 stub    lineMonitorDigits
+ 45 stub    lineMonitorMedia
+ 46 stub    lineMonitorTones
+ 47 stub    lineNegotiateAPIVersion
+ 48 stub    lineNegotiateExtVersion
+ 49 stub    lineOpen
+ 50 stub    linePark
+ 51 stub    linePickup
+ 52 stub    linePrepareAddToConference
+ 53 stub    lineRedirect
+ 54 stub    lineRegisterRequestRecipient
+ 55 stub    lineReleaseUserUserInfo
+ 56 stub    lineRemoveFromConference
+ 57 stub    lineRemoveProvider
+ 58 stub    lineSecureCall
+ 59 stub    lineSendUserUserInfo
+ 60 stub    lineSetAppPriority
+ 61 stub    lineSetAppSpecific
+ 62 stub    lineSetCallParams
+ 63 stub    lineSetCallPrivilege
+ 64 stub    lineSetCurrentLocation
+ 65 stub    lineSetDevConfig
+ 66 stub    lineSetMediaControl
+ 67 stub    lineSetMediaMode
+ 68 stub    lineSetNumRings
+ 69 stub    lineSetStatusMessages
+ 70 stub    lineSetTerminal
+ 71 stub    lineSetTollList
+ 72 stub    lineSetupConference
+ 73 stub    lineSetupTransfer
+ 74 stub    lineShutdown
+ 75 stub    lineSwapHold
+ 76 stub    lineTranslateAddress
+ 77 stub    lineTranslateDialog
+ 78 stub    lineUncompleteCall
+ 79 stub    lineUnhold
+ 80 stub    lineUnpark
+ 81 stub    phoneClose
+ 82 stub    phoneConfigDialog
+ 83 stub    phoneDevSpecific
+ 84 stub    phoneGetButtonInfo
+ 85 stub    phoneGetData
+ 86 stub    phoneGetDevCaps
+ 87 stub    phoneGetDisplay
+ 88 stub    phoneGetGain
+ 89 stub    phoneGetHookSwitch
+ 90 stub    phoneGetID
+ 91 stub    phoneGetIcon
+ 92 stub    phoneGetLamp
+ 93 stub    phoneGetRing
+ 94 stub    phoneGetStatus
+ 95 stub    phoneGetStatusMessages
+ 96 stub    phoneGetVolume
+ 97 stub    phoneInitialize
+ 98 stub    phoneNegotiateAPIVersion
+ 99 stub    phoneNegotiateExtVersion
+100 stub    phoneOpen
+101 stub    phoneSetButtonInfo
+102 stub    phoneSetData
+103 stub    phoneSetDisplay
+104 stub    phoneSetGain
+105 stub    phoneSetHookSwitch
+106 stub    phoneSetLamp
+107 stub    phoneSetRing
+108 stub    phoneSetStatusMessages
+109 stub    phoneSetVolume
+110 stub    phoneShutdown
+111 stub    tapiGetLocationInfo
+112 stub    tapiRequestDrop
+113 stub    tapiRequestMakeCall
+114 stub    tapiRequestMediaCall
diff --git a/if1632/user32.spec b/relay32/user32.spec
similarity index 98%
rename from if1632/user32.spec
rename to relay32/user32.spec
index f0f98be..5c099ba 100644
--- a/if1632/user32.spec
+++ b/relay32/user32.spec
@@ -76,7 +76,7 @@
  73 stdcall CreateDialogParamA(long ptr long ptr long) CreateDialogParam32A
  74 stdcall CreateDialogParamW(long ptr long ptr long) CreateDialogParam32W
  75 stdcall CreateIcon(long long long long long ptr ptr) CreateIcon32
- 76 stub CreateIconFromResource
+ 76 stdcall CreateIconFromResource (ptr long long long) CreateIconFromResource32
  77 stdcall CreateIconFromResourceEx(ptr long long long long long long) CreateIconFromResourceEx32
  78 stdcall CreateIconIndirect(ptr) CreateIconIndirect
  79 stub CreateMDIWindowA
@@ -396,8 +396,8 @@
 391 stdcall MessageBoxA(long str str long) MessageBox32A
 392 stdcall MessageBoxExA(long str str long long) MessageBoxEx32A
 393 stdcall MessageBoxExW(long wstr wstr long long) MessageBoxEx32W
-394 stub MessageBoxIndirectA
-395 stub MessageBoxIndirectW
+394 stdcall MessageBoxIndirectA(ptr) MessageBoxIndirect32A
+395 stdcall MessageBoxIndirectW(ptr) MessageBoxIndirect32W
 396 stdcall MessageBoxW(long wstr wstr long) MessageBox32W
 397 stdcall ModifyMenuA(long long long long ptr) ModifyMenu32A
 398 stdcall ModifyMenuW(long long long long ptr) ModifyMenu32W
@@ -459,8 +459,8 @@
 454 stdcall SendMessageA(long long long long) SendMessage32A
 455 stub SendMessageCallbackA
 456 stub SendMessageCallbackW
-457 stub SendMessageTimeoutA
-458 stub SendMessageTimeoutW
+457 stdcall SendMessageTimeoutA(long long long long ptr ptr) SendMessageTimeout32A
+458 stdcall SendMessageTimeoutW(long long long long ptr ptr) SendMessageTimeout32W
 459 stdcall SendMessageW(long long long long) SendMessage32W
 460 stub SendNotifyMessageA
 461 stub SendNotifyMessageW
@@ -589,8 +589,8 @@
 584 stub mouse_event
 585 varargs wsprintfA() wsprintf32A
 586 varargs wsprintfW() wsprintf32W
-587 stdcall wvsprintfA(str str ptr) wvsprintf32A
-588 stdcall wvsprintfW(wstr wstr ptr) wvsprintf32W
+587 stdcall wvsprintfA(ptr str ptr) wvsprintf32A
+588 stdcall wvsprintfW(ptr wstr ptr) wvsprintf32W
 #late additions
 589 stub ChangeDisplaySettingsA
 590 stub ChangeDisplaySettingsW
diff --git a/if1632/version.spec b/relay32/version.spec
similarity index 100%
rename from if1632/version.spec
rename to relay32/version.spec
diff --git a/if1632/w32skrnl.spec b/relay32/w32skrnl.spec
similarity index 100%
rename from if1632/w32skrnl.spec
rename to relay32/w32skrnl.spec
diff --git a/if1632/winmm.spec b/relay32/winmm.spec
similarity index 90%
rename from if1632/winmm.spec
rename to relay32/winmm.spec
index 3c70167..de1a4e5 100644
--- a/if1632/winmm.spec
+++ b/relay32/winmm.spec
@@ -2,6 +2,8 @@
 type win32
 
   1 stdcall PlaySoundA(ptr long long) PlaySound32A
+  2 stdcall WINMM_2(ptr long long) PlaySound32A
+  3 stub WINMM_3
   4 stub CloseDriver
   5 stub DefDriverProc
   6 stub DriverCallback
@@ -15,7 +17,7 @@
  14 stub GetDriverModuleHandle
  15 stdcall OpenDriver(ptr ptr long) OpenDriver
  16 stub OpenDriverA
- 17 stub PlaySound
+ 17 stdcall PlaySound(ptr long long) PlaySound32A
  18 stdcall PlaySoundW(ptr long long) PlaySound32W
  19 stub SendDriverMessage
  20 stdcall auxGetDevCapsA(long ptr long) auxGetDevCaps32A
@@ -25,12 +27,12 @@
  24 stdcall auxOutMessage(long long long long) auxOutMessage32
  25 stdcall auxSetVolume(long long) auxSetVolume32
  26 stub joyConfigChanged
- 27 stub joyGetDevCapsA
- 28 stub joyGetDevCapsW
- 29 stub joyGetNumDevs
- 30 stub joyGetPos
+ 27 stdcall joyGetDevCapsA(long ptr long) joyGetDevCaps32A
+ 28 stdcall joyGetDevCapsW(long ptr long) joyGetDevCaps32W
+ 29 stdcall joyGetNumDevs() joyGetNumDevs32
+ 30 stdcall joyGetPos(long ptr) joyGetPos32
  31 stub joyGetPosEx
- 32 stub joyGetThreshold
+ 32 stdcall joyGetThreshold(long ptr) joyGetThreshold32
  33 stub joyReleaseCapture
  34 stub joySetCapture
  35 stub joySetThreshold
@@ -47,7 +49,7 @@
  46 stdcall mciGetErrorStringW(long ptr long) mciGetErrorString32W
  47 stub mciGetYieldProc
  48 stub mciLoadCommandResource
- 49 stub mciSendCommandA
+ 49 stdcall mciSendCommandA(long long long long) mciSendCommand32A
  50 stub mciSendCommandW
  51 stdcall mciSendStringA(ptr ptr long long) mciSendString
  52 stub mciSendStringW
@@ -135,13 +137,13 @@
 134 stdcall mmsystemGetVersion() mmsystemGetVersion32
 135 stdcall sndPlaySoundA(ptr long) sndPlaySound
 136 stub sndPlaySoundW
-137 stub timeBeginPeriod
-138 stub timeEndPeriod
-139 stub timeGetDevCaps
-140 stub timeGetSystemTime
+137 stdcall timeBeginPeriod(long) timeBeginPeriod32
+138 stdcall timeEndPeriod(long) timeEndPeriod32
+139 stdcall timeGetDevCaps(ptr long) timeGetDevCaps32
+140 stdcall timeGetSystemTime(ptr long) timeGetSystemTime32
 141 stdcall timeGetTime() timeGetTime
-142 stub timeKillEvent
-143 stub timeSetEvent
+142 stdcall timeKillEvent(long) timeKillEvent32
+143 stdcall timeSetEvent(long long ptr long long) timeSetEvent32
 144 stdcall waveInAddBuffer(long ptr long) waveInAddBuffer32
 145 stdcall waveInClose(long) waveInClose32
 146 stdcall waveInGetDevCapsA(long ptr long) waveInGetDevCaps32A
diff --git a/if1632/winspool.spec b/relay32/winspool.spec
similarity index 98%
rename from if1632/winspool.spec
rename to relay32/winspool.spec
index f5bd31a..be7721f 100644
--- a/if1632/winspool.spec
+++ b/relay32/winspool.spec
@@ -96,7 +96,7 @@
 193 stub GetPrinterDriverW
 194 stub GetPrinterW
 195 stub InitializeDll
-196 stub OpenPrinterA
+196 stdcall OpenPrinterA(str ptr ptr) OpenPrinter32A
 197 stub OpenPrinterW
 198 stub PlayGdiScriptOnPrinterIC
 199 stub PrinterMessageBoxA
diff --git a/relay32/wow32.spec b/relay32/wow32.spec
new file mode 100644
index 0000000..2f5b548
--- /dev/null
+++ b/relay32/wow32.spec
@@ -0,0 +1,20 @@
+name	wow32
+type	win32
+
+#  1
+  2 stub    WOWCallback16
+  3 stub    WOWCallback16Ex
+  4 stub    WOWDirectedYield16
+  5 stub    WOWGetVDMPointer
+  6 stub    WOWGetVDMPointerFix
+  7 stub    WOWGetVDMPointerUnfix
+  8 stub    WOWGlobalAlloc16
+  9 stub    WOWGlobalAllocLock16
+ 10 stub    WOWGlobalFree16
+ 11 stub    WOWGlobalLock16
+ 12 stub    WOWGlobalLockSize16
+ 13 stub    WOWGlobalUnlock16
+ 14 stub    WOWGlobalUnlockFree16
+ 15 stub    WOWHandle16
+ 16 stub    WOWHandle32
+ 17 stub    WOWYield16
diff --git a/if1632/wsock32.spec b/relay32/wsock32.spec
similarity index 78%
rename from if1632/wsock32.spec
rename to relay32/wsock32.spec
index 829fe95..7dc4def 100644
--- a/if1632/wsock32.spec
+++ b/relay32/wsock32.spec
@@ -10,8 +10,8 @@
 007 stdcall getsockopt(long long long ptr ptr) WINSOCK_getsockopt32
 008 stdcall htonl(long) WINSOCK_htonl
 009 stdcall htons(long) WINSOCK_htons
-010 stdcall inet_addr(ptr) inet_addr
-011 stdcall inet_ntoa(ptr) inet_ntoa
+010 stdcall inet_addr(ptr) WINSOCK_inet_addr
+011 stdcall inet_ntoa(ptr) WINSOCK_inet_ntoa32
 012 stdcall ioctlsocket(long long ptr) WINSOCK_ioctlsocket32
 013 stdcall listen(long long) WINSOCK_listen32
 014 stdcall ntohl(long) WINSOCK_ntohl
@@ -31,14 +31,14 @@
 055 stdcall getservbyname(str str) WINSOCK_getservbyname32
 056 stdcall getservbyport(long str) WINSOCK_getservbyport32
 057 stdcall gethostname(ptr long) WINSOCK_gethostname32
-101 stdcall WSAAsyncSelect(long long long long) WSAAsyncSelect
-102 stub WSAAsyncGetHostByAddr
+101 stdcall WSAAsyncSelect(long long long long) WSAAsyncSelect32
+102 stdcall WSAAsyncGetHostByAddr(long long ptr long long ptr long) WSAAsyncGetHostByAddr32
 103 stdcall WSAAsyncGetHostByName(long long ptr ptr long) WSAAsyncGetHostByName32
-104 stub WSAAsyncGetProtoByNumber
-105 stub WSAAsyncGetProtoByName
-106 stub WSAAsyncGetServByPort
-107 stub WSAAsyncGetServByName
-108 stub WSACancelAsyncRequest
+104 stdcall WSAAsyncGetProtoByNumber(long long long ptr long) WSAAsyncGetProtoByNumber32
+105 stdcall WSAAsyncGetProtoByName(long long ptr ptr long) WSAAsyncGetProtoByName32
+106 stdcall WSAAsyncGetServByPort(long long long ptr ptr long) WSAAsyncGetServByPort32
+107 stdcall WSAAsyncGetServByName(long long ptr ptr ptr long) WSAAsyncGetServByName32
+108 stdcall WSACancelAsyncRequest(long) WSACancelAsyncRequest32
 109 stdcall WSASetBlockingHook(ptr) WSASetBlockingHook32
 110 stdcall WSAUnhookBlockingHook() WSAUnhookBlockingHook32
 111 stdcall WSAGetLastError() WSAGetLastError
@@ -52,7 +52,7 @@
 # applications *should* 'degrade gracefully if these are not present
 # ... as it is, they don't
 #1000 stub WSApSetPostRoutine
-1001 stdcall WsControl(long long long long long long) WsControl
+1001 stdcall WsControl(long long ptr ptr ptr ptr) WsControl
 1100 stdcall inet_network(ptr) inet_network
 1101 stdcall getnetbyname(ptr) getnetbyname
 #1102 stub rcmd
@@ -61,7 +61,7 @@
 #1105 stub sethostname
 #1106 stub dn_expand
 1107 stub WSARecvEx
-1108 stub s_perror
+1108 stdcall s_perror(ptr) WS_s_perror
 1109 stub GetAddressByNameA
 1110 stub GetAddressByNameW
 #1111 stub EnumProtocolsA
diff --git a/resources/sysres_De.rc b/resources/sysres_De.rc
index b866fd4..3534338 100644
--- a/resources/sysres_De.rc
+++ b/resources/sysres_De.rc
@@ -17,14 +17,14 @@
 {
 	POPUP ""
 	BEGIN
-		MENUITEM "&Undo", EM_UNDO32
+		MENUITEM "&Rückgängig", EM_UNDO32
 		MENUITEM SEPARATOR
-		MENUITEM "Cu&t", WM_CUT
-		MENUITEM "&Copy", WM_COPY
-		MENUITEM "&Paste", WM_PASTE
-		MENUITEM "&Delete", WM_CLEAR
+		MENUITEM "&Ausschneiden", WM_CUT
+		MENUITEM "&Kopieren", WM_COPY
+		MENUITEM "&Einfügen", WM_PASTE
+		MENUITEM "&Löschen", WM_CLEAR
 		MENUITEM SEPARATOR
-		MENUITEM "Select &All", EM_SETSEL32
+		MENUITEM "&Alles markieren", EM_SETSEL32
 	END
 }
 
diff --git a/scheduler/process.c b/scheduler/process.c
index e3bd71b..b819080 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -658,6 +658,7 @@
 				ret = GetEnvironmentVariable32A(x,d,cursize-(d-xdst));
 				if (ret) {
 					d+=strlen(d);
+					s=end;
 				} else {
 					CHECK_FREE(strlen(x)+2);
 					*d++='%';
@@ -667,9 +668,9 @@
 				}
 				HeapFree(heap,0,x);
 			} else
-				*d=*s;
+				*d++=*s;
 
-			s++;d++;
+			s++;
 		} else {
 			CHECK_FREE(1);
 			*d++=*s++;
diff --git a/tools/build.c b/tools/build.c
index 3f39bda..c692a41 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -960,102 +960,47 @@
 /*******************************************************************
  *         BuildSpec32File
  *
- * Build a Win32 assembly file from a spec file.
+ * Build a Win32 C file from a spec file.
  */
 static int BuildSpec32File( char * specfile, FILE *outfile )
 {
     ORDDEF *odp;
-    int i, nb_names, nb_stubs;
-    char buffer[1024];
-    unsigned char *args, *p;
+    int i, nb_names, nb_reg_funcs = 0;
 
-    fprintf( outfile, "/* File generated automatically; do not edit! */\n" );
-    fprintf( outfile, "\t.file\t\"%s\"\n", specfile );
-#ifdef USE_STABS
-    getcwd(buffer, sizeof(buffer));
-
-    /*
-     * The stabs help the internal debugger as they are an indication that it
-     * is sensible to step into a thunk/trampoline.
-     */
-    fprintf( outfile, ".stabs \"%s/\",100,0,0,Code_Start\n", buffer);
-    fprintf( outfile, ".stabs \"%s\",100,0,0,Code_Start\n", specfile);
-#endif
-
-    fprintf( outfile, "\t.text\n" );
-    fprintf( outfile, "\t.align 4\n" );
-    fprintf( outfile, "Code_Start:\n" );
-
-    /* Output code for all register functions */
-
-    for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
-    {
-        if (odp->type != TYPE_REGISTER) continue;
-        fprintf( outfile, "\n/* %s.%d (%s) */\n", DLLName, i, odp->name);
-        fprintf( outfile, "\t.align 4\n" );
-#ifdef USE_STABS
-        fprintf( outfile, ".stabs \"%s_%d:F1\",36,0,%d,%s_%d\n", 
-                 DLLName, i, odp->lineno, DLLName, i);
-#endif
-        fprintf( outfile, "%s_%d:\n", DLLName, i );
-#ifdef USE_STABS
-        fprintf( outfile, ".stabn 68,0,%d,0\n", odp->lineno);
-#endif
-        fprintf( outfile, "\tpushl $" PREFIX "%s\n",odp->u.func.link_name);
-        fprintf( outfile, "\tjmp " PREFIX "CALL32_Regs\n" );
-    }
+    fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n\n",
+             specfile );
+    fprintf( outfile, "#include \"builtin32.h\"\n\n" );
 
     /* Output code for all stubs functions */
 
-    nb_stubs = 0;
+    fprintf( outfile, "extern const BUILTIN32_DESCRIPTOR %s_Descriptor;\n",
+             DLLName );
     for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
     {
         if (odp->type != TYPE_STUB) continue;
-        fprintf( outfile, "\n/* %s.%d (%s) */\n", DLLName, i, odp->name);
-#ifdef USE_STABS
-        fprintf( outfile, ".stabs \"%s_%d:F1\",36,0,%d,%s_%d\n", 
-                 DLLName, i, odp->lineno, DLLName, i);
-#endif
-        fprintf( outfile, "%s_%d:\n", DLLName, i );
-#ifdef USE_STABS
-        fprintf( outfile, ".stabn 68,0,%d,0\n", odp->lineno);
-#endif
-        fprintf( outfile, "\tpushl $Name_%d\n", i );
-        fprintf( outfile, "\tpushl $%d\n", i );
-        if (++nb_stubs == 1)
-        {
-            fprintf( outfile, "DoStub:\n" );
-            fprintf( outfile, "\tpushl $DLLName\n" );
-            fprintf( outfile, "\tcall " PREFIX "RELAY_Unimplemented32\n" );
-        }
-        else fprintf( outfile, "\tjmp DoStub\n" );
+        fprintf( outfile, "static void __stub_%d() { BUILTIN32_Unimplemented(&%s_Descriptor,%d); }\n",
+                 i, DLLName, i );
     }
 
-    /* Output the DLL functions table */
+    /* Output the DLL functions prototypes */
 
-    fprintf( outfile, "\t.text\n" );
-    fprintf( outfile, "\t.align 4\n" );
-    fprintf( outfile, "Functions:\n" );
     for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
     {
         switch(odp->type)
         {
-        case TYPE_INVALID:
-            fprintf( outfile, "\t.long 0\n" );
-            break;
         case TYPE_VARARGS:
-            fprintf( outfile, "\t.long " PREFIX "%s\n",odp->u.vargs.link_name);
+            fprintf( outfile, "extern void %s();\n", odp->u.vargs.link_name );
             break;
         case TYPE_EXTERN:
-            fprintf( outfile, "\t.long " PREFIX "%s\n", odp->u.ext.link_name );
-            break;
-        case TYPE_STDCALL:
-        case TYPE_CDECL:
-            fprintf( outfile, "\t.long " PREFIX "%s\n", odp->u.func.link_name);
+            fprintf( outfile, "extern void %s();\n", odp->u.ext.link_name );
             break;
         case TYPE_REGISTER:
+        case TYPE_STDCALL:
+        case TYPE_CDECL:
+            fprintf( outfile, "extern void %s();\n", odp->u.func.link_name );
+            break;
+        case TYPE_INVALID:
         case TYPE_STUB:
-            fprintf( outfile, "\t.long %s_%d\n", DLLName, i );
             break;
         default:
             fprintf(stderr,"build: function type %d not available for Win32\n",
@@ -1064,18 +1009,54 @@
         }
     }
 
-    /* Output the DLL names table */
+    /* Output the DLL functions table */
 
-    fprintf( outfile, "FuncNames:\n" );
+    fprintf( outfile, "\nstatic const ENTRYPOINT32 Functions[%d] =\n{\n",
+             Limit - Base + 1 );
     for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
     {
-        if (odp->type != TYPE_INVALID)
-            fprintf( outfile, "\t.long Name_%d\n", i );
+        switch(odp->type)
+        {
+        case TYPE_INVALID:
+            fprintf( outfile, "    0" );
+            break;
+        case TYPE_VARARGS:
+            fprintf( outfile, "    %s", odp->u.vargs.link_name );
+            break;
+        case TYPE_EXTERN:
+            fprintf( outfile, "    %s", odp->u.ext.link_name );
+            break;
+        case TYPE_REGISTER:
+        case TYPE_STDCALL:
+        case TYPE_CDECL:
+            fprintf( outfile, "    %s", odp->u.func.link_name);
+            break;
+        case TYPE_STUB:
+            fprintf( outfile, "    __stub_%d", i );
+            break;
+        default:
+            return -1;
+        }
+        if (i < Limit) fprintf( outfile, ",\n" );
     }
+    fprintf( outfile, "\n};\n\n" );
+
+    /* Output the DLL names table */
+
+    nb_names = 0;
+    fprintf( outfile, "static const char * const FuncNames[] =\n{\n" );
+    for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
+    {
+        if (odp->type == TYPE_INVALID) continue;
+        if (nb_names++) fprintf( outfile, ",\n" );
+        fprintf( outfile, "    \"%s\"", odp->name );
+    }
+    fprintf( outfile, "\n};\n\n" );
 
     /* Output the DLL argument types */
 
-    fprintf( outfile, "ArgTypes:\n" );
+    fprintf( outfile, "static const unsigned int ArgTypes[%d] =\n{\n",
+             Limit - Base + 1 );
     for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
     {
     	unsigned int j, mask = 0;
@@ -1085,73 +1066,67 @@
                 if (odp->u.func.arg_types[j] == 't') mask |= 1<< (j*2);
                 if (odp->u.func.arg_types[j] == 'W') mask |= 2<< (j*2);
 	    }
-	fprintf( outfile, "\t.long %d\n",mask);
+	fprintf( outfile, "    %d", mask );
+        if (i < Limit) fprintf( outfile, ",\n" );
     }
+    fprintf( outfile, "\n};\n\n" );
 
     /* Output the DLL ordinals table */
 
-    fprintf( outfile, "FuncOrdinals:\n" );
+    fprintf( outfile, "static const unsigned short FuncOrdinals[] =\n{\n" );
     nb_names = 0;
     for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
     {
         if (odp->type == TYPE_INVALID) continue;
-        nb_names++;
-        /* Some assemblers do not have .word */
-        fprintf( outfile, "\t.byte %d,%d\n",
-                 LOBYTE(i - Base), HIBYTE(i - Base) );
+        if (nb_names++) fprintf( outfile, ",\n" );
+        fprintf( outfile, "    %d", i - Base );
     }
-
-    /* Output the DLL names */
-
-    for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
-    {
-        if (odp->type != TYPE_INVALID)
-            fprintf( outfile, "Name_%d:\t.ascii \"%s\\0\"\n", i, odp->name );
-    }
+    fprintf( outfile, "\n};\n\n" );
 
     /* Output the DLL functions arguments */
 
-    args = p = (unsigned char *)xmalloc( Limit - Base + 1 );
+    fprintf( outfile, "static const unsigned char FuncArgs[%d] =\n{\n",
+             Limit - Base + 1 );
     for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
     {
+        unsigned char args;
         switch(odp->type)
         {
         case TYPE_STDCALL:
-            *p++ = (unsigned char)strlen(odp->u.func.arg_types);
+            args = (unsigned char)strlen(odp->u.func.arg_types);
             break;
         case TYPE_CDECL:
-            *p++ = 0x80 | (unsigned char)strlen(odp->u.func.arg_types);
+            args = 0x80 | (unsigned char)strlen(odp->u.func.arg_types);
             break;
         case TYPE_REGISTER:
-            *p++ = 0xfe;
+            args = 0xfe;
+            nb_reg_funcs++;
             break;
         default:
-            *p++ = 0xff;
+            args = 0xff;
             break;
         }
+        fprintf( outfile, "    0x%02x", args );
+        if (i < Limit) fprintf( outfile, ",\n" );
     }
-    DumpBytes( outfile, args, Limit - Base + 1, NULL, "FuncArgs" );
+    fprintf( outfile, "\n};\n\n" );
 
     /* Output the DLL descriptor */
 
-    fprintf( outfile, "DLLName:\t.ascii \"%s\\0\"\n", DLLName );
-    fprintf( outfile, "\t.align 4\n" );
-    fprintf( outfile, "\t.globl " PREFIX "%s_Descriptor\n", DLLName );
-    fprintf( outfile, PREFIX "%s_Descriptor:\n", DLLName );
-    fprintf( outfile, "\t.long DLLName\n" );          /* Name */
-    fprintf( outfile, "\t.long %d\n", Base );         /* Base */
-    fprintf( outfile, "\t.long %d\n", Limit+1-Base ); /* Number of functions */
-    fprintf( outfile, "\t.long %d\n", nb_names );     /* Number of names */
-    fprintf( outfile, "\t.long Functions\n" );        /* Functions */
-    fprintf( outfile, "\t.long FuncNames\n" );        /* Function names */
-    fprintf( outfile, "\t.long FuncOrdinals\n" );     /* Function ordinals */
-    fprintf( outfile, "\t.long FuncArgs\n" );         /* Function arguments */
-    fprintf( outfile, "\t.long ArgTypes\n" );         /* Function argtypes */
-#ifdef USE_STABS
-    fprintf( outfile, "\t.text\n");
-    fprintf( outfile, "\t.stabs \"\",100,0,0,.Letext\n");
-    fprintf( outfile, ".Letext:\n");
-#endif
+    fprintf( outfile, "const BUILTIN32_DESCRIPTOR %s_Descriptor =\n{\n",
+             DLLName );
+    fprintf( outfile, "    \"%s\",\n", DLLName );
+    fprintf( outfile, "    %d,\n", Base );
+    fprintf( outfile, "    %d,\n", Limit - Base + 1 );
+    fprintf( outfile, "    %d,\n", nb_names );
+    fprintf( outfile, "    %d,\n", nb_reg_funcs );
+    fprintf( outfile,
+             "    Functions,\n"
+             "    FuncNames,\n"
+             "    FuncOrdinals,\n"
+             "    FuncArgs,\n"
+             "    ArgTypes\n"
+             "};\n" );
     return 0;
 }
 
@@ -1747,7 +1722,8 @@
  * Prototypes for the CallTo16 functions:
  *   extern WINAPI WORD CallTo16_word_xxx( FARPROC16 func, args... );
  *   extern WINAPI LONG CallTo16_long_xxx( FARPROC16 func, args... );
- *   extern WINAPI void CallTo16_regs_{short,long}( const CONTEXT *context );
+ *   extern WINAPI void CallTo16_sreg_( const CONTEXT *context );
+ *   extern WINAPI void CallTo16_lreg_( const CONTEXT *context );
  */
 static void BuildCallTo16Func( FILE *outfile, char *profile )
 {
@@ -1756,7 +1732,8 @@
     char *args = profile + 5;
 
     if (!strncmp( "word_", profile, 5 )) short_ret = 1;
-    else if (!strncmp( "regs_", profile, 5 )) reg_func = 1;
+    else if (!strncmp( "sreg_", profile, 5 )) reg_func = 1;
+    else if (!strncmp( "lreg_", profile, 5 )) reg_func = 2;
     else if (strncmp( "long_", profile, 5 ))
     {
         fprintf( stderr, "Invalid function name '%s'.\n", profile );
@@ -1793,7 +1770,7 @@
         fprintf( outfile, PREFIX "CALLTO16_Restore:\n" );
     }
     fprintf( outfile, "\tpopl %%ebp\n" );
-    fprintf( outfile, "\tret $%d\n", strlen(args) + 1 );
+    fprintf( outfile, "\tret $%d\n", 4 * strlen(args) + 4 );
 
     /* Start of the actual CallTo16 routine */
 
@@ -1853,10 +1830,10 @@
         fprintf( outfile, "\tmovl %d(%%ebx),%%edi\n", CONTEXTOFFSET(Edi) );
 
         /* Push the return address 
-	 * With _short suffix, we push 16:16 address (normal lret)
-	 * With _long suffix, we push 16:32 address (0x66 lret, for KERNEL32_45)
+	 * With sreg suffix, we push 16:16 address (normal lret)
+	 * With lreg suffix, we push 16:32 address (0x66 lret, for KERNEL32_45)
 	 */
-	if (!strncmp(profile,"regs_short",10))
+	if (reg_func == 1)
 	    fprintf( outfile, "\tpushl " PREFIX "CALLTO16_RetAddr_regs\n" );
 	else 
 	{
@@ -2042,6 +2019,7 @@
     fprintf( outfile, ".stabs \"CALL32_Init:F1\",36,0,0," PREFIX "CALL32_Init\n");
 #endif
     fprintf( outfile, "\t.globl " PREFIX "CALL32_Init\n" );
+    fprintf( outfile, "\t.type " PREFIX "CALL32_Init,@function\n" );
     fprintf( outfile, PREFIX "CALL32_Init:\n" );
     fprintf( outfile, "\tleal -256(%%esp),%%eax\n" );
     fprintf( outfile, "\tmovl %%eax,CALL32_Original32_esp\n" );
@@ -2350,6 +2328,8 @@
     fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
     fprintf( outfile, "\t.text\n" );
 
+#ifdef __i386__
+
 #ifdef USE_STABS
     fprintf( outfile, "\t.file\t\"%s\"\n", outname );
     getcwd(buffer, sizeof(buffer));
@@ -2379,6 +2359,12 @@
     fprintf( outfile, ".Letext:\n");
 #endif
 
+#else  /* __i386__ */
+
+    /* Just to avoid an empty file */
+    fprintf( outfile, "\t.long 0\n" );
+
+#endif  /* __i386__ */
     return 0;
 }
 
diff --git a/win32/Makefile.in b/win32/Makefile.in
index d42613d..7c683e1 100644
--- a/win32/Makefile.in
+++ b/win32/Makefile.in
@@ -15,6 +15,7 @@
 	file.c \
 	init.c \
 	k32obj.c \
+	kernel32.c \
 	newfns.c \
 	ordinals.c \
 	process.c \
diff --git a/win32/code_page.c b/win32/code_page.c
index ed6ea822..2771061 100644
--- a/win32/code_page.c
+++ b/win32/code_page.c
@@ -85,54 +85,82 @@
 /***********************************************************************
  *              MultiByteToWideChar                (KERNEL32.392)
  */
-int WINAPI MultiByteToWideChar(UINT32 page, DWORD flags, char *src, int srclen,
+int WINAPI MultiByteToWideChar(UINT32 page, DWORD flags,
+			       const char *src, int srclen,
                                WCHAR *dst, int dstlen)
 {
-    if (srclen == -1)
-   	 srclen = lstrlen32A(src)+1;
-    if (!dstlen || !dst)
-         return srclen;
+    int ret;
 
-    lstrcpynAtoW(dst,src,srclen); /* FIXME */
-    return srclen-1;
+    if (srclen == -1)
+	srclen = lstrlen32A(src)+1;
+    if (!dstlen || !dst)
+	return srclen;
+
+    ret = srclen;
+    while (srclen > 0 && dstlen > 0) {
+	*dst = (WCHAR)(unsigned char)*src;
+	if (!*src)
+	    return ret;
+	dst++;    src++;
+	dstlen--; srclen--;
+    }
+    if (dstlen == 0) {
+	SetLastError(ERROR_INSUFFICIENT_BUFFER);
+	return 0;
+    }
+    return ret;
 }
 
 int WINAPI WideCharToMultiByte(UINT32 page, DWORD flags, WCHAR *src, int srclen,
                                char *dst, int dstlen, char* defchar, BOOL32 *used)
 {
-	int count = 0;
-	int dont_copy= (dstlen==0);
-	if(page!=GetACP() && page!=CP_OEMCP && page!=CP_ACP)
-		fprintf(stdnimp,"Conversion in CP %d not supported\n",page);
+    int count = 0;
+    int eos = 0;
+    int dont_copy= (dstlen==0);
+    if (page!=GetACP() && page!=CP_OEMCP && page!=CP_ACP)
+	fprintf(stdnimp,"Conversion in CP %d not supported\n",page);
 #if 0
-	if(flags)
-		fprintf(stdnimp,"WideCharToMultiByte flags %lx not supported\n",flags);
+    if (flags)
+	fprintf(stdnimp,"WideCharToMultiByte flags %lx not supported\n",flags);
 #endif
-	if(used)
-		*used=0;
-	while(srclen && (dont_copy || dstlen))
-	{
-		if(!dont_copy){
-			if(*src<256)
-				*dst = *src;
-			else
-			{
-				/* FIXME: Is this correct ?*/
-				if(flags & WC_DEFAULTCHAR){
-					*dst = defchar ? *defchar : '?';
-					if(used)*used=1;
-				}
-			}
-			dstlen--;
-			dst++;
-		}
-		count++;
-		if(!*src)
-			break;
-		if(srclen!=-1)srclen--;
-		src++;
+    if(used)
+	*used=0;
+    if (srclen == -1)
+	srclen = lstrlen32W(src)+1;
+    while(srclen && (dont_copy || dstlen))
+    {
+	if(!dont_copy){
+	    if(*src<256)
+		*dst = *src;
+	    else
+	    {
+		/* ??? The WC_DEFAULTCHAR flag only gets used in
+		 * combination with the WC_COMPOSITECHECK flag or at
+		 * least this is what it seems from using the function
+		 * on NT4.0 in combination with reading the documentation.
+		 */
+		*dst = defchar ? *defchar : '?';
+		if(used)*used=1;
+	    }
+	    dstlen--;
+	    dst++;
 	}
+	count++;
+	srclen--;
+	if(!*src) {
+	    eos = 1;
+	    break;
+	}
+	src++;
+    }
+    if (dont_copy)
 	return count;
+
+    if (!eos && srclen > 0) {
+	SetLastError(ERROR_INSUFFICIENT_BUFFER);
+	return 0;
+    }
+    return count;
 }
 
 
diff --git a/win32/console.c b/win32/console.c
index d10a1ca..fa8166f 100644
--- a/win32/console.c
+++ b/win32/console.c
@@ -2,6 +2,7 @@
  * Win32 kernel functions
  *
  * Copyright 1995 Martin von Loewis and Cameron Heide
+ * Copyright 1997 Karl Garrison
  */
 
 #include <stdio.h>
@@ -81,9 +82,7 @@
 {
 	*mode = 	ENABLE_PROCESSED_INPUT	|
 			ENABLE_LINE_INPUT	|
-			ENABLE_ECHO_INPUT	|
-			ENABLE_WINDOW_INPUT	|
-			ENABLE_MOUSE_INPUT;
+			ENABLE_ECHO_INPUT;
 	return TRUE;
 }
 
@@ -118,7 +117,7 @@
  *            WriteConsoleA   (KERNEL32.567)
  */
 BOOL32 WINAPI WriteConsole32A( HANDLE32 hConsoleOutput,
-                               LPVOID lpBuffer,
+                               LPCVOID lpBuffer,
                                DWORD nNumberOfCharsToWrite,
                                LPDWORD lpNumberOfCharsWritten,
                                LPVOID lpReserved )
@@ -133,7 +132,7 @@
  *            WriteConsoleW   (KERNEL32.577)
  */
 BOOL32 WINAPI WriteConsole32W( HANDLE32 hConsoleOutput,
-                               LPVOID lpBuffer,
+                               LPCVOID lpBuffer,
                                DWORD nNumberOfCharsToWrite,
                                LPDWORD lpNumberOfCharsWritten,
                                LPVOID lpReserved )
@@ -199,7 +198,8 @@
 /***********************************************************************
  *            FlushConsoleInputBuffer   (KERNEL32.132)
  */
-BOOL32 WINAPI FlushConsoleInputBuffer(HANDLE32 hConsoleInput){
+BOOL32 WINAPI FlushConsoleInputBuffer(HANDLE32 hConsoleInput)
+{
     fprintf(stderr,"FlushConsoleInputBuffer(%d)\n",hConsoleInput);
     return TRUE;
 }
@@ -222,6 +222,70 @@
  */
 BOOL32 WINAPI GetNumberOfConsoleInputEvents(HANDLE32 hcon,LPDWORD nrofevents)
 {
-	*nrofevents = 1;
+	*nrofevents = 0;
 	return TRUE;
 }
+
+/***********************************************************************
+ *            GetNumberOfConsoleMouseButtons   (KERNEL32.358)
+ */
+BOOL32 WINAPI GetNumberOfConsoleMouseButtons(LPDWORD nrofbuttons)
+{
+    *nrofbuttons = 2;
+    fprintf(stderr,"GetNumberOfConsoleMouseButtons: STUB returning 2\n");
+    return TRUE;
+}
+
+/***********************************************************************
+ *            PeekConsoleInputA   (KERNEL32.550)
+ */
+BOOL32 WINAPI PeekConsoleInput32A(HANDLE32 hConsoleInput,
+                                  LPDWORD pirBuffer,
+                                  DWORD cInRecords,
+                                  LPDWORD lpcRead)
+/* FIXME: pirBuffer should be a pointer to an INPUT_RECORD structure
+   -Karl Garrison (12/01/97) */
+{
+    pirBuffer = NULL;
+    cInRecords = 0;
+    *lpcRead = 0;
+    fprintf(stderr,"GetNumberOfConsoleMouseButtons: STUB returning NULL\n");
+	return TRUE;
+}
+
+/***********************************************************************
+ *            PeekConsoleInputW   (KERNEL32.551)
+ */
+BOOL32 WINAPI PeekConsoleInput32W(HANDLE32 hConsoleInput,
+                                  LPDWORD pirBuffer,
+                                  DWORD cInRecords,
+                                  LPDWORD lpcRead)
+/* FIXME: pirBuffer should be a pointer to an INPUT_RECORD structure
+   -Karl Garrison (12/01/97) */
+{
+    pirBuffer = NULL;
+    cInRecords = 0;
+    *lpcRead = 0;
+    fprintf(stderr,"GetNumberOfConsoleMouseButtons: STUB returning NULL\n");
+    return TRUE;
+}
+
+/***********************************************************************
+ *            GetConsoleCursorInfo32   (KERNEL32.296)
+ */
+BOOL32 WINAPI GetConsoleCursorInfo32(HANDLE32 hcon, LPDWORD cinfo)
+{
+  cinfo[0] = 10; /* 10% of character box is cursor.  */
+  cinfo[1] = TRUE;  /* Cursur is visible.  */
+  fprintf (stdnimp, "GetConsoleCursorInfo32 -- STUB!\n");
+  return TRUE;
+}
+
+/***********************************************************************
+ *            SetConsoleCursorInfo32   (KERNEL32.626)
+ */
+BOOL32 WINAPI SetConsoleCursorInfo32(HANDLE32 hcon, LPDWORD cinfo)
+{
+  fprintf (stdnimp, "SetConsoleCursorInfo32 -- STUB!\n");
+  return TRUE;
+}
diff --git a/win32/environment.c b/win32/environment.c
index 90a0bf3..65ad44d 100644
--- a/win32/environment.c
+++ b/win32/environment.c
@@ -29,9 +29,9 @@
  */
 LPCWSTR WINAPI GetCommandLine32W(void)
 {
-    static WCHAR buffer[256];
+    static WCHAR buffer[1024];
 
-    lstrcpynAtoW(buffer,GetCommandLine32A(),256);
+    lstrcpynAtoW(buffer,GetCommandLine32A(),1024);
     return buffer;
 }
 
diff --git a/win32/kernel32.c b/win32/kernel32.c
new file mode 100644
index 0000000..a53e04e
--- /dev/null
+++ b/win32/kernel32.c
@@ -0,0 +1,663 @@
+/*
+ * KERNEL32 thunks and other undocumented stuff
+ *
+ * Copyright 1997 Marcus Meissner
+ */
+
+#include <stdio.h>
+#include "windows.h"
+#include "callback.h"
+#include "resource.h"
+#include "task.h"
+#include "user.h"
+#include "heap.h"
+#include "module.h"
+#include "stackframe.h"
+#include "selectors.h"
+#include "task.h"
+#include "win.h"
+#include "stddebug.h"
+#include "debug.h"
+
+/***********************************************************************
+ *                                                                     *
+ *                 Win95 internal thunks                               *
+ *                                                                     *
+ ***********************************************************************/
+
+/***********************************************************************
+ * Generates a FT_Prolog call.
+ *	
+ *  0FB6D1                  movzbl edx,cl
+ *  8B1495xxxxxxxx	    mov edx,[4*edx + xxxxxxxx]
+ *  68xxxxxxxx		    push FT_Prolog
+ *  C3			    lret
+ */
+static void _write_ftprolog(LPBYTE thunk,DWORD thunkstart) {
+	LPBYTE	x;
+
+	x	= thunk;
+	*x++	= 0x0f;*x++=0xb6;*x++=0xd1; /* movzbl edx,cl */
+	*x++	= 0x8B;*x++=0x14;*x++=0x95;*(DWORD*)x= thunkstart;
+	x+=4;	/* mov edx, [4*edx + thunkstart] */
+	*x++	= 0x68; *(DWORD*)x = (DWORD)GetProcAddress32(GetModuleHandle32A("KERNEL32"),"FT_Prolog");
+	x+=4; 	/* push FT_Prolog */
+	*x++	= 0xC3;		/* lret */
+	/* fill rest with 0xCC / int 3 */
+}
+
+/***********************************************************************
+ *			FT_PrologPrime			(KERNEL32.89)
+ */
+void WINAPI FT_PrologPrime(DWORD startind,LPBYTE thunk) {
+	_write_ftprolog(thunk,*(DWORD*)(startind+thunk));
+}
+
+/***********************************************************************
+ * Generates a QT_Thunk style call.
+ *	
+ *  33C9                    xor ecx, ecx
+ *  8A4DFC                  mov cl , [ebp-04]
+ *  8B148Dxxxxxxxx          mov edx, [4*ecx + (EAX+EDX)]
+ *  B8yyyyyyyy              mov eax, QT_Thunk
+ *  FFE0                    jmp eax
+ */
+static void _write_qtthunk(LPBYTE start,DWORD thunkstart) {
+	LPBYTE	x;
+
+	x	= start;
+	*x++	= 0x33;*x++=0xC9; /* xor ecx,ecx */
+	*x++	= 0x8A;*x++=0x4D;*x++=0xFC; /* movb cl,[ebp-04] */
+	*x++	= 0x8B;*x++=0x14;*x++=0x8D;*(DWORD*)x= thunkstart;
+	x+=4;	/* mov edx, [4*ecx + (EAX+EDX) */
+	*x++	= 0xB8; *(DWORD*)x = (DWORD)GetProcAddress32(GetModuleHandle32A("KERNEL32"),"QT_Thunk");
+	x+=4; 	/* mov eax , QT_Thunk */
+	*x++	= 0xFF; *x++ = 0xE0;	/* jmp eax */
+	/* should fill the rest of the 32 bytes with 0xCC */
+}
+
+/***********************************************************************
+ *		ThunkConnect32		(KERNEL32)
+ * Connects a 32bit and a 16bit thunkbuffer.
+ */
+struct thunkstruct
+{
+	char	magic[4];
+	DWORD	length;
+	DWORD	ptr;
+	DWORD	x0C;
+
+	DWORD	x10;
+	DWORD	x14;
+	DWORD	x18;
+	DWORD	x1C;
+	DWORD	x20;
+};
+
+UINT32 WINAPI ThunkConnect32( struct thunkstruct *ths, LPSTR thunkfun16,
+                              LPSTR module16, LPSTR module32, HMODULE32 hmod32,
+                              DWORD dllinitarg1 )
+{
+	HINSTANCE16	hmm;
+	SEGPTR		thkbuf;
+	struct	thunkstruct	*ths16;
+
+	dprintf_thunk(stddeb,"ThunkConnect32(<struct>,%s,%s,%s,%x,%lx)\n",
+		thunkfun16,module32,module16,hmod32,dllinitarg1
+	);
+	dprintf_thunk(stddeb,"	magic = %c%c%c%c\n",
+		ths->magic[0],
+		ths->magic[1],
+		ths->magic[2],
+		ths->magic[3]
+	);
+	dprintf_thunk(stddeb,"	length = %lx\n",ths->length);
+	if (lstrncmp32A(ths->magic,"SL01",4)&&lstrncmp32A(ths->magic,"LS01",4))
+		return 0;
+	hmm=LoadModule16(module16,NULL);
+	if (hmm<=32)
+		return 0;
+	thkbuf=(SEGPTR)WIN32_GetProcAddress16(hmm,thunkfun16);
+	if (!thkbuf)
+		return 0;
+	ths16=(struct thunkstruct*)PTR_SEG_TO_LIN(thkbuf);
+	if (lstrncmp32A(ths16->magic,ths->magic,4))
+		return 0;
+
+	if (!lstrncmp32A(ths->magic,"SL01",4))  {
+		if (ths16->length != ths->length)
+			return 0;
+		ths->x0C = (DWORD)ths16;
+
+		dprintf_thunk(stddeb,"	ths16 magic is 0x%08lx\n",*(DWORD*)ths16->magic);
+		if (*((DWORD*)ths16->magic) != 0x0000304C)
+			return 0;
+		if (!*(WORD*)(((LPBYTE)ths16)+0x12))
+			return 0;
+		
+	}
+	if (!lstrncmp32A(ths->magic,"LS01",4))  {
+		if (ths16->length != ths->length)
+			return 0;
+		ths->ptr = (DWORD)PTR_SEG_TO_LIN(ths16->ptr);
+		/* code offset for QT_Thunk is at 0x1C...  */
+		_write_qtthunk (((LPBYTE)ths) + ths->x1C,ths->ptr);
+		/* code offset for FT_Prolog is at 0x20...  */
+		_write_ftprolog(((LPBYTE)ths) + ths->x20,ths->ptr);
+		return 1;
+	}
+	return TRUE;
+}
+
+
+/**********************************************************************
+ * 		QT_Thunk			(KERNEL32)
+ *
+ * The target address is in EDX.
+ * The 16 bit arguments start at ESP+4.
+ * The number of 16bit argumentbytes is EBP-ESP-0x44 (68 Byte thunksetup).
+ * [ok]
+ */
+VOID WINAPI QT_Thunk(CONTEXT *context)
+{
+	CONTEXT	context16;
+	DWORD	argsize;
+
+	memcpy(&context16,context,sizeof(context16));
+
+	CS_reg(&context16)	 = HIWORD(EDX_reg(context));
+	IP_reg(&context16)	 = LOWORD(EDX_reg(context));
+
+	argsize = EBP_reg(context)-ESP_reg(context)-0x44;
+
+	/* additional 4 bytes used by the relaycode for storing the stackptr */
+	memcpy(	((LPBYTE)CURRENT_STACK16)-argsize-4,
+		(LPBYTE)ESP_reg(context)+4,
+		argsize
+	);
+	EAX_reg(context) = Callbacks->CallRegisterShortProc(&context16,
+                                                            -argsize);
+}
+
+
+/**********************************************************************
+ *           WOWCallback16 (KERNEL32.62)
+ */
+DWORD WINAPI WOWCallback16(FARPROC16 fproc,DWORD arg)
+{
+	DWORD	ret;
+	dprintf_thunk(stddeb,"WOWCallback16(%p,0x%08lx) ",fproc,arg);
+	ret =  Callbacks->CallWOWCallbackProc(fproc,arg);
+	dprintf_thunk(stddeb,"... returns %ld\n",ret);
+	return ret;
+}
+
+/***********************************************************************
+ *           _KERNEL32_52    (KERNEL32.52)
+ * Returns a pointer to ThkBuf in the 16bit library SYSTHUNK.DLL.
+ * [ok probably]
+ */
+LPVOID WINAPI _KERNEL32_52()
+{
+	HMODULE32	hmod = LoadLibrary16("systhunk.dll");
+
+	dprintf_thunk(stddeb, "_KERNEL32_52: systhunk.dll module %d\n", hmod);
+	
+	if (hmod<=32)
+		return 0;
+	return PTR_SEG_TO_LIN(WIN32_GetProcAddress16(hmod,"ThkBuf"));
+}
+
+/***********************************************************************
+ * 		_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)
+ * [ok probably]
+ */
+DWORD WINAPI _KERNEL32_43(LPDWORD thunk,LPCSTR thkbuf,DWORD len,
+                           LPCSTR dll16,LPCSTR dll32)
+{
+	HINSTANCE16	hmod;
+	LPDWORD		addr;
+	SEGPTR		segaddr;
+
+	hmod = LoadLibrary16(dll16);
+	if (hmod<32) {
+		fprintf(stderr,"KERNEL32_43->failed to load 16bit DLL %s, error %d\n",dll16,hmod);
+		return 0;
+	}
+	segaddr = (DWORD)WIN32_GetProcAddress16(hmod,(LPSTR)thkbuf);
+	if (!segaddr) {
+		fprintf(stderr,"KERNEL32_43->no %s exported from %s!\n",thkbuf,dll16);
+		return 0;
+	}
+	addr = (LPDWORD)PTR_SEG_TO_LIN(segaddr);
+	if (addr[0] != len) {
+		fprintf(stderr,"KERNEL32_43->thkbuf length mismatch? %ld vs %ld\n",len,addr[0]);
+		return 0;
+	}
+	if (!addr[1])
+		return 0;
+	*(DWORD*)thunk = addr[1];
+
+	dprintf_thunk(stddeb, "_KERNEL32_43: loaded module %d, func %s (%d) @ %p (%p), returning %p\n",
+		      hmod, HIWORD(thkbuf)==0 ? "<ordinal>" : thkbuf, (int)thkbuf, (void*)segaddr, addr, (void*)addr[1]);
+
+	return addr[1];
+}
+
+/***********************************************************************
+ * 		_KERNEL32_45 	(KERNEL32.44)
+ * Another 32->16 thunk, the difference to QT_Thunk is, that the called routine
+ * uses 0x66 lret, and that we have to pass CX in DI.
+ * (there seems to be some kind of BL/BX return magic too...)
+ *
+ * [doesn't crash anymore]
+ */
+VOID WINAPI _KERNEL32_45(CONTEXT *context)
+{
+	CONTEXT	context16;
+	LPBYTE	curstack;
+	DWORD	ret,stacksize;
+
+	dprintf_thunk(stddeb,"KERNEL32_45(%%eax=0x%08lx(%%cx=0x%04lx,%%edx=0x%08lx))\n",
+		(DWORD)EAX_reg(context),(DWORD)CX_reg(context),(DWORD)EDX_reg(context)
+	);
+	stacksize = EBP_reg(context)-ESP_reg(context);
+	dprintf_thunk(stddeb,"	stacksize = %ld\n",stacksize);
+
+	memcpy(&context16,context,sizeof(context16));
+
+	DI_reg(&context16)	 = CX_reg(context);
+	CS_reg(&context16)	 = HIWORD(EAX_reg(context));
+	IP_reg(&context16)	 = LOWORD(EAX_reg(context));
+
+	curstack = PTR_SEG_TO_LIN(STACK16_PUSH(stacksize));
+	memcpy(curstack-stacksize,(LPBYTE)ESP_reg(context),stacksize);
+	ret = Callbacks->CallRegisterLongProc(&context16,0);
+	STACK16_POP(stacksize);
+
+	dprintf_thunk(stddeb,". returned %08lx\n",ret);
+	EAX_reg(context) 	 = ret;
+}
+
+/***********************************************************************
+ * 		_KERNEL32_40 	(KERNEL32.40)
+ * YET Another 32->16 thunk, the difference to the others is still mysterious
+ * target address is EDX
+ *
+ * [crashes]
+ */
+VOID WINAPI _KERNEL32_40(CONTEXT *context)
+{
+	CONTEXT	context16;
+	LPBYTE	curstack;
+	DWORD	ret,stacksize;
+
+	dprintf_thunk(stddeb,"_KERNEL32_40(EDX=0x%08lx)\n",
+		EDX_reg(context)
+	);
+	stacksize = EBP_reg(context)-ESP_reg(context);
+	dprintf_thunk(stddeb,"	stacksize = %ld\n",stacksize);
+	dprintf_thunk(stddeb,"on top of stack: 0x%04x\n",*(WORD*)ESP_reg(context));
+
+	memcpy(&context16,context,sizeof(context16));
+
+	CS_reg(&context16)	 = HIWORD(EDX_reg(context));
+	IP_reg(&context16)	 = LOWORD(EDX_reg(context));
+
+	curstack = PTR_SEG_TO_LIN(STACK16_PUSH(stacksize));
+	memcpy(curstack-stacksize,(LPBYTE)ESP_reg(context),stacksize);
+	ret = Callbacks->CallRegisterShortProc(&context16,0);
+	STACK16_POP(stacksize);
+
+	dprintf_thunk(stddeb,". returned %08lx\n",ret);
+	EAX_reg(context) 	 = ret;
+}
+
+
+/***********************************************************************
+ *		(KERNEL32.41)
+ * A thunk setup routine.
+ * Expects a pointer to a preinitialized thunkbuffer in the first argument
+ * looking like:
+ *	00..03:		unknown	(pointer, check _41, _43, _46)
+ *	04: EB1E		jmp +0x20
+ *
+ *	06..23:		unknown (space for replacement code, check .90)
+ *
+ *	24:>E800000000		call offset 29
+ *	29:>58			pop eax		   ( target of call )
+ *	2A: 2D25000000		sub eax,0x00000025 ( now points to offset 4 )
+ *	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'.
+ * [ok probably]
+ */
+
+LPVOID WINAPI _KERNEL32_41(LPBYTE thunk,LPCSTR thkbuf,DWORD len,LPCSTR dll16,
+                           LPCSTR dll32)
+{
+	HMODULE32	hkrnl32 = GetModuleHandle32A("KERNEL32");
+	HMODULE16	hmod;
+	LPDWORD		addr,addr2;
+	DWORD		segaddr;
+
+	/* 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)90);
+	*(DWORD*)(thunk+0x6D) = (DWORD)GetProcAddress32(hkrnl32,(LPSTR)89);
+
+	
+	hmod = LoadLibrary16(dll16);
+	if (hmod<32) {
+		fprintf(stderr,"KERNEL32_41->failed to load 16bit DLL %s, error %d\n",dll16,hmod);
+		return NULL;
+	}
+	segaddr = (DWORD)WIN32_GetProcAddress16(hmod,(LPSTR)thkbuf);
+	if (!segaddr) {
+		fprintf(stderr,"KERNEL32_41->no %s exported from %s!\n",thkbuf,dll16);
+		return NULL;
+	}
+	addr = (LPDWORD)PTR_SEG_TO_LIN(segaddr);
+	if (addr[0] != len) {
+		fprintf(stderr,"KERNEL32_41->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;
+
+	dprintf_thunk(stddeb, "_KERNEL32_41: loaded module %d, func %s(%d) @ %p (%p), returning %p\n",
+		      hmod, HIWORD(thkbuf)==0 ? "<ordinal>" : thkbuf, (int)thkbuf, (void*)segaddr, addr, addr2);
+
+	return addr2;
+}
+
+/***********************************************************************
+ *							(KERNEL32.90)
+ * QT Thunk priming function
+ * Rewrites the first part of the thunk to use the QT_Thunk interface
+ * and jumps to the start of that code.
+ * [ok]
+ */
+VOID WINAPI _KERNEL32_90(CONTEXT *context)
+{
+	dprintf_thunk(stddeb, "_KERNEL32_90: QT Thunk priming; context %p\n", context);
+	
+	_write_qtthunk((LPBYTE)EAX_reg(context),*(DWORD*)(EAX_reg(context)+EDX_reg(context)));
+	/* we just call the real QT_Thunk right now 
+	 * we can bypass the relaycode, for we already have the registercontext
+	 */
+	EDX_reg(context) = *(DWORD*)((*(DWORD*)(EAX_reg(context)+EDX_reg(context)))+4*(((BYTE*)EBP_reg(context))[-4]));
+	return QT_Thunk(context);
+}
+
+/***********************************************************************
+ *							(KERNEL32.45)
+ * Another thunkbuf link routine.
+ * The start of the thunkbuf looks like this:
+ * 	00: DWORD	length
+ *	04: SEGPTR	address for thunkbuffer pointer
+ * [ok probably]
+ */
+VOID WINAPI _KERNEL32_46(LPBYTE thunk,LPSTR thkbuf,DWORD len,LPSTR dll16,
+                         LPSTR dll32)
+{
+	LPDWORD		addr;
+	HMODULE16	hmod;
+	SEGPTR		segaddr;
+
+	hmod = LoadLibrary16(dll16);
+	if (hmod < 32) {
+		fprintf(stderr,"KERNEL32_46->couldn't load %s, error %d\n",dll16,hmod);
+		return;
+	}
+	segaddr = (SEGPTR)WIN32_GetProcAddress16(hmod,thkbuf);
+	if (!segaddr) {
+		fprintf(stderr,"KERNEL32_46-> haven't found %s in %s!\n",thkbuf,dll16);
+		return;
+	}
+	addr = (LPDWORD)PTR_SEG_TO_LIN(segaddr);
+	if (addr[0] != len) {
+		fprintf(stderr,"KERNEL32_46-> length of thkbuf differs from expected length! (%ld vs %ld)\n",addr[0],len);
+		return;
+	}
+	*(DWORD*)PTR_SEG_TO_LIN(addr[1]) = (DWORD)thunk;
+
+	dprintf_thunk(stddeb, "_KERNEL32_46: loaded module %d, func %s(%d) @ %p (%p)\n",
+		      hmod, HIWORD(thkbuf)==0 ? "<ordinal>" : thkbuf, (int)thkbuf, (void*)segaddr, addr);
+}
+
+/**********************************************************************
+ *           _KERNEL32_87
+ * Check if thunking is initialized (ss selector set up etc.)
+ * We do that differently, so just return TRUE.
+ * [ok]
+ */
+BOOL32 WINAPI _KERNEL32_87()
+{
+    dprintf_thunk(stddeb, "_KERNEL32_87: Yes, thunking is initialized\n");
+    return TRUE;
+}
+
+/**********************************************************************
+ *           _KERNEL32_88
+ * One of the real thunking functions. This one seems to be for 32<->32
+ * thunks. It should probably be capable of crossing processboundaries.
+ *
+ * And YES, I've seen nr=48 (somewhere in the Win95 32<->16 OLE coupling)
+ * [ok]
+ */
+DWORD WINAPIV _KERNEL32_88( DWORD nr, DWORD flags, FARPROC32 fun, ... )
+{
+    DWORD i,ret;
+    DWORD *args = ((DWORD *)&fun) + 1;
+
+    dprintf_thunk(stddeb,"KERNEL32_88(%ld,0x%08lx,%p,[ ",nr,flags,fun);
+    for (i=0;i<nr/4;i++) { dprintf_thunk(stddeb,"0x%08lx,",args[i]); }
+    dprintf_thunk(stddeb,"])\n");
+    switch (nr) {
+    case 0:	ret = fun();
+		break;
+    case 4:	ret = fun(args[0]);
+		break;
+    case 8:	ret = fun(args[0],args[1]);
+		break;
+    case 12:	ret = fun(args[0],args[1],args[2]);
+		break;
+    case 16:	ret = fun(args[0],args[1],args[2],args[3]);
+		break;
+    case 20:	ret = fun(args[0],args[1],args[2],args[3],args[4]);
+		break;
+    case 24:	ret = fun(args[0],args[1],args[2],args[3],args[4],args[5]);
+		break;
+    case 28:	ret = fun(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
+		break;
+    case 32:	ret = fun(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
+		break;
+    case 36:	ret = fun(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
+		break;
+    case 40:	ret = fun(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
+		break;
+    case 44:	ret = fun(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
+		break;
+    case 48:	ret = fun(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
+		break;
+    default:
+	fprintf(stderr,"_KERNEL32_88: unsupported nr of arguments, %ld\n",nr);
+	ret = 0;
+	break;
+
+    }
+    dprintf_thunk(stddeb," returning %ld ...\n",ret);
+    return ret;
+}
+
+/**********************************************************************
+ * 		KERNEL_619		(KERNEL)
+ * Seems to store y and z depending on x in some internal lists...
+ */
+WORD WINAPI _KERNEL_619(WORD x,DWORD y,DWORD z)
+{
+    fprintf(stderr,"KERNEL_619(0x%04x,0x%08lx,0x%08lx)\n",x,y,z);
+    return x;
+}
+
+/**********************************************************************
+ *			AllocSLCallback		(KERNEL32)
+ *
+ * Win95 uses some structchains for callbacks. It allocates them
+ * in blocks of 100 entries, size 32 bytes each, layout:
+ * blockstart:
+ * 	0:	PTR	nextblockstart
+ *	4:	entry	*first;
+ *	8:	WORD	sel ( start points to blockstart)
+ *	A:	WORD	unknown
+ * 100xentry:
+ *	00..17:		Code
+ *	18:	PDB	*owning_process;
+ *	1C:	PTR	blockstart
+ *
+ * We ignore this for now. (Just a note for further developers)
+ * FIXME: use this method, so we don't waste selectors...
+ *
+ * Following code is then generated by AllocSLCallback. The code is 16 bit, so
+ * the 0x66 prefix switches from word->long registers.
+ *
+ *	665A		pop	edx 
+ *	6668x arg2 x 	pushl	<arg2>
+ *	6652		push	edx
+ *	EAx arg1 x	jmpf	<arg1>
+ *
+ * returns the startaddress of this thunk.
+ *
+ * Note, that they look very similair to the ones allocates by THUNK_Alloc.
+ */
+DWORD WINAPI
+AllocSLCallback(DWORD finalizer,DWORD callback) {
+	LPBYTE	x,thunk = HeapAlloc( GetProcessHeap(), 0, 32 );
+	WORD	sel;
+
+	x=thunk;
+	*x++=0x66;*x++=0x5a;				/* popl edx */
+	*x++=0x66;*x++=0x68;*(DWORD*)x=finalizer;x+=4;	/* pushl finalizer */
+	*x++=0x66;*x++=0x52;				/* pushl edx */
+	*x++=0xea;*(DWORD*)x=callback;x+=4;		/* jmpf callback */
+
+	*(DWORD*)(thunk+18) = GetCurrentProcessId();
+
+	sel = SELECTOR_AllocBlock( thunk , 32, SEGMENT_CODE, FALSE, FALSE );
+	return (sel<<16)|0;
+}
+
+void WINAPI
+FreeSLCallback(DWORD x) {
+	fprintf(stderr,"FreeSLCallback(0x%08lx)\n",x);
+}
+
+/**********************************************************************
+ * 		KERNEL_358		(KERNEL)
+ * Allocates a code segment which starts at the address passed in x. limit
+ * 0xfffff, and returns the pointer to the start.
+ */
+DWORD WINAPI
+_KERNEL_358(DWORD x) {
+	WORD	sel;
+
+	fprintf(stderr,"_KERNEL_358(0x%08lx),stub\n",x);
+	if (!HIWORD(x))
+		return x;
+
+	sel = SELECTOR_AllocBlock( PTR_SEG_TO_LIN(x) , 0xffff, SEGMENT_CODE, FALSE, FALSE );
+	return (sel<<16)|(0x0000);
+}
+
+/**********************************************************************
+ * 		KERNEL_359		(KERNEL)
+ * Frees the code segment of the passed linear pointer (This has usually
+ * been allocated by _KERNEL_358).
+ */
+VOID WINAPI
+_KERNEL_359(DWORD x) {
+	DWORD	savedsssp;
+
+	fprintf(stderr,"_KERNEL_359(0x%08lx),stub\n",x);
+	if ((HIWORD(x) & 7)!=7)
+		return;
+	savedsssp = IF1632_Saved16_ss_sp;IF1632_Saved16_ss_sp = 0;
+	SELECTOR_FreeBlock(x>>16,1);
+	IF1632_Saved16_ss_sp = savedsssp;
+	return;
+}
+
+/**********************************************************************
+ * 		KERNEL_472		(KERNEL)
+ * something like GetCurrenthInstance.
+ */
+VOID WINAPI
+_KERNEL_472(CONTEXT *context) {
+	fprintf(stderr,"_KERNEL_472(0x%08lx),stub\n",EAX_reg(context));
+	if (!EAX_reg(context)) {
+		TDB *pTask = (TDB*)GlobalLock16(GetCurrentTask());
+		AX_reg(context)=pTask->hInstance;
+		return;
+	}
+	if (!HIWORD(EAX_reg(context)))
+		return; /* returns the passed value */
+	/* hmm ... fixme */
+}
+
+/**********************************************************************
+ * 		KERNEL_431		(KERNEL.431)
+ * IsPeFile
+ */
+BOOL16 WINAPI KERNEL_431(LPSTR fn,WORD x) {
+	IMAGE_DOS_HEADER	mzh;
+	HFILE32			hf;
+	OFSTRUCT		ofs;
+	DWORD			xmagic;
+
+	hf = OpenFile32(fn,&ofs,OF_READ);
+	if (hf==HFILE_ERROR32)
+		return FALSE;
+	if (sizeof(mzh)!=_lread32(hf,&mzh,sizeof(mzh))) {
+		_lclose32(hf);
+		return FALSE;
+	}
+	if (mzh.e_magic!=IMAGE_DOS_SIGNATURE) {
+		fprintf(stderr,"file has not got dos signature!\n");
+		_lclose32(hf);
+		return FALSE;
+	}
+	_llseek32(hf,mzh.e_lfanew,SEEK_SET);
+	if (sizeof(DWORD)!=_lread32(hf,&xmagic,sizeof(DWORD))) {
+		_lclose32(hf);
+		return FALSE;
+	}
+	_lclose32(hf);
+	return (xmagic == IMAGE_NT_SIGNATURE);
+}
diff --git a/win32/newfns.c b/win32/newfns.c
index 3192451..1ef72e5 100644
--- a/win32/newfns.c
+++ b/win32/newfns.c
@@ -49,6 +49,17 @@
 	return FALSE;
 }
 
+HANDLE32 WINAPI FindFirstChangeNotification32A(LPCSTR lpPathName,BOOL32 bWatchSubtree,DWORD dwNotifyFilter) {
+	fprintf(stderr,"FindFirstChangeNotification(%s,%d,%08lx),stub\n",
+		lpPathName,bWatchSubtree,dwNotifyFilter
+	);
+	return 0xcafebabe;
+}
+
+BOOL32 WINAPI FindNextChangeNotification(HANDLE32 fcnhandle) {
+	fprintf(stderr,"FindNextChangeNotification(%08x),stub!\n",fcnhandle);
+	return FALSE;
+}
 
 /****************************************************************************
  *		QueryPerformanceFrequency (KERNEL32.565)
diff --git a/win32/ordinals.c b/win32/ordinals.c
index 576d25b..10af63b 100644
--- a/win32/ordinals.c
+++ b/win32/ordinals.c
@@ -16,9 +16,6 @@
 #include "debug.h"
 #include "stddebug.h"
 
-extern THDB	*pCurrentThread;
-extern PDB32	*pCurrentProcess;
-
 static CRITICAL_SECTION Win16Mutex;
 
 /***********************************************
diff --git a/win32/thread.c b/win32/thread.c
index e33755a..e974c29 100644
--- a/win32/thread.c
+++ b/win32/thread.c
@@ -159,7 +159,7 @@
 
 void WINAPI DeleteCriticalSection(CRITICAL_SECTION *pcritical)
 {
-   semctl((int) pcritical->LockSemaphore,0,IPC_RMID,(union semun)NULL);
+   semctl((int) pcritical->LockSemaphore,0,IPC_RMID, (void *)0);
    pcritical->Reserved=-1;
 }
 
diff --git a/windows/dce.c b/windows/dce.c
index 2d3b506..6fb6d56 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -12,8 +12,9 @@
  *
  * DCX_DCEEMPTY    - dce is uninitialized
  * DCX_DCEBUSY     - dce is in use
- * DCX_KEEPCLIPRGN - ReleaseDC should preserve the clipping region
- * DCX_WINDOWPAINT - BeginPaint specific flag
+ * DCX_DCEDIRTY    - ReleaseDC() should wipe instead of caching
+ * DCX_KEEPCLIPRGN - ReleaseDC() should not delete the clipping region
+ * DCX_WINDOWPAINT - BeginPaint() is in effect
  */
 
 #include "options.h"
@@ -192,7 +193,17 @@
     if (dce->DCXflags & DCX_CACHE)
     {
         SetDCState( dce->hDC, defaultDCstate );
-        dce->DCXflags &= ~DCX_DCEBUSY;	/* but without DCX_DCEEMPTY */
+        dce->DCXflags &= ~DCX_DCEBUSY;
+	if (dce->DCXflags & DCX_DCEDIRTY)
+	{
+	    /* don't keep around invalidated entries 
+	     * because SetDCState() disables hVisRgn updates
+	     * by removing dirty bit. */
+
+	    dce->hwndCurrent = 0;
+	    dce->DCXflags &= DCX_CACHE;
+	    dce->DCXflags |= DCX_DCEEMPTY;
+	}
     }
     return 1;
 }
@@ -261,11 +272,12 @@
 				}
 				else
 				{
-				    /* Set dirty bit in the hDC */
+				    /* Set dirty bits in the hDC and DCE structs */
 
 				    dprintf_dc(stddeb,"\tfixed up %08x dce [%04x]\n", 
 						(unsigned)dce, wndCurrent->hwndSelf);
 
+				    dce->DCXflags |= DCX_DCEDIRTY;
 				    SetHookFlags(dce->hDC, DCHF_INVALIDATEVISRGN);
 				    bRet = TRUE;
 				}
@@ -769,6 +781,7 @@
                     wnd->flags |= WIN_SAVEUNDER_OVERRIDE;
 	}
 	dc->w.flags &= ~DC_DIRTY;
+	dce->DCXflags &= ~DCX_DCEDIRTY;
 	SelectVisRgn( hdc, hrgnVisible );
     }
     else
@@ -908,7 +921,8 @@
                     else
                          CombineRgn32(hVisRgn, hVisRgn, dce->hClipRgn, 
                                       (dce->DCXflags & DCX_EXCLUDERGN)? RGN_DIFF:RGN_AND);
-	       }  
+	       }
+	       dce->DCXflags &= ~DCX_DCEDIRTY;
 	       SelectVisRgn(hDC, hVisRgn);
 	       DeleteObject32( hVisRgn );
 	   }
diff --git a/windows/defwnd.c b/windows/defwnd.c
index e50d00b..002868a 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -12,6 +12,7 @@
 #include "heap.h"
 #include "nonclient.h"
 #include "winpos.h"
+#include "dce.h"
 #include "syscolor.h"
 #include "sysmetrics.h"
 #include "stddebug.h"
@@ -28,8 +29,6 @@
 static short iF10Key = 0;
 static short iMenuSysKey = 0;
 
-extern void  EndMenu(void);
-
 /***********************************************************************
  *           DEFWND_HandleWindowPosChanged
  *
@@ -91,6 +90,33 @@
     return sysColorObjects.hbrushWindow;
 }
 
+
+/***********************************************************************
+ *           DEFWND_SetRedraw
+ */
+static void DEFWND_SetRedraw( WND* wndPtr, WPARAM32 wParam )
+{
+    BOOL32 bVisible = wndPtr->dwStyle & WS_VISIBLE;
+
+    if( wParam )
+    {
+	if( !bVisible )
+	{
+	    wndPtr->dwStyle |= WS_VISIBLE;
+	    DCE_InvalidateDCE( wndPtr->parent, &wndPtr->rectWindow );
+	}
+    }
+    else if( bVisible )
+    {
+	if( wndPtr->dwStyle & WS_MINIMIZE ) wParam = RDW_VALIDATE;
+	else wParam = RDW_ALLCHILDREN | RDW_VALIDATE;
+
+	PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, wParam, 0 );
+	DCE_InvalidateDCE( wndPtr->parent, &wndPtr->rectWindow );
+	wndPtr->dwStyle &= ~WS_VISIBLE;
+    }
+}
+
 /***********************************************************************
  *           DEFWND_DefWinProc
  *
@@ -167,14 +193,7 @@
 	}
 
     case WM_SETREDRAW:
-        if(wParam)
-            SetWindowPos32( wndPtr->hwndSelf, NULL, 0, 0, 0, 0,
-                SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
-                SWP_NOACTIVATE | SWP_NOREDRAW );
-        else
-            SetWindowPos32( wndPtr->hwndSelf, NULL, 0, 0, 0, 0,
-                SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
-                SWP_NOACTIVATE | SWP_NOREDRAW );
+	DEFWND_SetRedraw( wndPtr, wParam );
         return 0;
 
     case WM_CLOSE:
diff --git a/windows/dialog.c b/windows/dialog.c
index b68151e..f469c61 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -66,7 +66,7 @@
  *
  * Initialisation of the dialog manager.
  */
-BOOL32 DIALOG_Init()
+BOOL32 DIALOG_Init(void)
 {
     TEXTMETRIC16 tm;
     HDC16 hdc;
diff --git a/windows/mdi.c b/windows/mdi.c
index 54babe0..e9e1980 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -1512,7 +1512,7 @@
 		switch( msg->wParam )
 		{
 		    case VK_F6:
-		    case VK_SEPARATOR:
+		    case VK_TAB:
 			 wParam = ( GetKeyState32(VK_SHIFT) & 0x8000 )
 				  ? SC_NEXTWINDOW : SC_PREVWINDOW;
 			 break;
diff --git a/windows/message.c b/windows/message.c
index 01e0c070..a62ca87 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -37,7 +37,7 @@
 extern MESSAGEQUEUE *pCursorQueue;			 /* queue.c */
 extern MESSAGEQUEUE *pActiveQueue;
 
-extern void JoySendMessages(void);
+extern void joySendMessages(void);
 
 DWORD MSG_WineStartTicks; /* Ticks at Wine startup */
 
@@ -440,7 +440,7 @@
     int i, kbd_msg, pos = sysMsgQueue->nextMessage;
 
     /* FIXME: there has to be a better way to do this */
-    JoySendMessages();
+    joySendMessages();
 
     /* If the queue is empty, attempt to fill it */
     if (!sysMsgQueue->msgCount && XPending(display))
@@ -1136,7 +1136,7 @@
     WND **list, **ppWnd;
     LRESULT ret;
 
-    if (hwnd == HWND_BROADCAST)
+    if (hwnd == HWND_BROADCAST || hwnd == HWND_TOPMOST)
     {
         if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
             return TRUE;
@@ -1178,7 +1178,7 @@
 
 
 /***********************************************************************
- *           SendMessage32W   (USER32.458)
+ *           SendMessage32W   (USER32.459)
  */
 LRESULT WINAPI SendMessage32W( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
                                LPARAM lParam )
@@ -1187,7 +1187,7 @@
     WND **list, **ppWnd;
     LRESULT ret;
 
-    if (hwnd == HWND_BROADCAST)
+    if (hwnd == HWND_BROADCAST || hwnd == HWND_TOPMOST)
     {
         if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
             return TRUE;
@@ -1228,6 +1228,42 @@
 
 
 /***********************************************************************
+ *           SendMessageTimeout16    (not a WINAPI)
+ */
+LRESULT WINAPI SendMessageTimeout16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
+				     LPARAM lParam, UINT16 flags,
+				     UINT16 timeout, LPWORD resultp)
+{
+  fprintf (stdnimp, "SendMessageTimeout16 -- semistub\n");
+  return SendMessage16 (hwnd, msg, wParam, lParam);
+}
+
+
+/***********************************************************************
+ *           SendMessageTimeout32A   (USER32.457)
+ */
+LRESULT WINAPI SendMessageTimeout32A( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
+				      LPARAM lParam, UINT32 flags,
+				      UINT32 timeout, LPDWORD resultp)
+{
+  fprintf (stdnimp, "SendMessageTimeout32A -- semistub\n");
+  return SendMessage32A (hwnd, msg, wParam, lParam);
+}
+
+
+/***********************************************************************
+ *           SendMessageTimeout32W   (USER32.458)
+ */
+LRESULT WINAPI SendMessageTimeout32W( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
+				      LPARAM lParam, UINT32 flags,
+				      UINT32 timeout, LPDWORD resultp)
+{
+  fprintf (stdnimp, "SendMessageTimeout32W -- semistub\n");
+  return SendMessage32W (hwnd, msg, wParam, lParam);
+}
+
+
+/***********************************************************************
  *           WaitMessage    (USER.112) (USER32.577)
  */
 void WINAPI WaitMessage( void )
diff --git a/windows/msgbox.c b/windows/msgbox.c
index 627e0cf..f5f90bd 100644
--- a/windows/msgbox.c
+++ b/windows/msgbox.c
@@ -13,14 +13,6 @@
 #include "resource.h"
 #include "task.h"
 
-typedef struct
-{
-    LPCSTR title;
-    LPCSTR text;
-    UINT32 type;
-} MSGBOX, *LPMSGBOX;
-
-
 /**************************************************************************
  *           MSGBOX_DlgProc
  *
@@ -29,7 +21,8 @@
 static LRESULT CALLBACK MSGBOX_DlgProc( HWND32 hwnd, UINT32 message,
                                         WPARAM32 wParam, LPARAM lParam )
 {
-  LPMSGBOX lpmb;
+  LPMSGBOXPARAMS32A lpmb;
+
   RECT32 rect, textrect;
   HWND32 hItem;
   HDC32 hdc;
@@ -39,11 +32,11 @@
   
   switch(message) {
    case WM_INITDIALOG:
-    lpmb = (LPMSGBOX)lParam;
-    if (lpmb->title) SetWindowText32A(hwnd, lpmb->title);
-    SetWindowText32A(GetDlgItem32(hwnd, 100), lpmb->text);
+    lpmb = (LPMSGBOXPARAMS32A)lParam;
+    if (lpmb->lpszCaption) SetWindowText32A(hwnd, lpmb->lpszCaption);
+    SetWindowText32A(GetDlgItem32(hwnd, 100), lpmb->lpszText);
     /* Hide not selected buttons */
-    switch(lpmb->type & MB_TYPEMASK) {
+    switch(lpmb->dwStyle & MB_TYPEMASK) {
      case MB_OK:
       ShowWindow32(GetDlgItem32(hwnd, 2), SW_HIDE);
       /* fall through */
@@ -71,7 +64,7 @@
       break;
     }
     /* Set the icon */
-    switch(lpmb->type & MB_ICONMASK) {
+    switch(lpmb->dwStyle & MB_ICONMASK) {
      case MB_ICONEXCLAMATION:
       SendDlgItemMessage16(hwnd, stc1, STM_SETICON16,
                            (WPARAM16)LoadIcon16(0, IDI_EXCLAMATION), 0);
@@ -121,7 +114,7 @@
     
     GetClientRect32(hItem, &rect);
     hdc = GetDC32(hItem);
-    lRet = DrawText32A( hdc, lpmb->text, -1, &rect,
+    lRet = DrawText32A( hdc, lpmb->lpszText, -1, &rect,
                         DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK | DT_CALCRECT);
     theight = rect.bottom  - rect.top;
     tiheight = 16 + MAX(iheight, theight);
@@ -150,7 +143,7 @@
       /* some arithmetic to get the right order for YesNoCancel windows */
       hItem = GetDlgItem32(hwnd, (i + 5) % 7 + 1);
       if (GetWindowLong32A(hItem, GWL_STYLE) & WS_VISIBLE) {
-	if (buttons++ == ((lpmb->type & MB_DEFMASK) >> 8)) {
+	if (buttons++ == ((lpmb->dwStyle & MB_DEFMASK) >> 8)) {
 	  SetFocus32(hItem);
 	  SendMessage32A( hItem, BM_SETSTYLE32, BS_DEFPUSHBUTTON, TRUE );
 	}
@@ -195,13 +188,13 @@
  */
 INT32 WINAPI MessageBox32A(HWND32 hWnd, LPCSTR text, LPCSTR title, UINT32 type)
 {
-    MSGBOX mbox;
+    MSGBOXPARAMS32A mbox;
 
     if (!text) text="<WINE-NULL>";
     if (!title) title="<WINE-NULL>";
-    mbox.title = title;
-    mbox.text  = text;
-    mbox.type  = type;
+    mbox.lpszCaption = title;
+    mbox.lpszText  = text;
+    mbox.dwStyle  = type;
     return DialogBoxIndirectParam32A( WIN_GetWindowInstance(hWnd),
                                       SYSRES_GetResPtr( SYSRES_DIALOG_MSGBOX ),
                                       hWnd, MSGBOX_DlgProc, (LPARAM)&mbox );
@@ -243,6 +236,31 @@
     return MessageBox32W(hWnd,text,title,type);
 }
 
+/**************************************************************************
+ *           MessageBoxIndirect32A   (USER32.394)
+ */
+INT32 WINAPI MessageBoxIndirect32A( LPMSGBOXPARAMS32A msgbox )
+{
+    return DialogBoxIndirectParam32A( msgbox->hInstance,
+   				      SYSRES_GetResPtr( SYSRES_DIALOG_MSGBOX ),
+                                      msgbox->hwndOwner, MSGBOX_DlgProc,
+				      (LPARAM)msgbox );
+}
+
+/**************************************************************************
+ *           MessageBoxIndirect32W   (USER32.395)
+ */
+INT32 WINAPI MessageBoxIndirect32W( LPMSGBOXPARAMS32W msgbox )
+{
+    MSGBOXPARAMS32A	msgboxa;
+
+    memcpy(&msgboxa,msgbox,sizeof(msgboxa));
+    if (msgbox->lpszCaption)	lstrcpyWtoA(msgboxa.lpszCaption,msgbox->lpszCaption);
+    if (msgbox->lpszText)	lstrcpyWtoA(msgboxa.lpszText,msgbox->lpszText);
+
+    return MessageBoxIndirect32A(&msgboxa);
+}
+
 
 /**************************************************************************
  *           FatalAppExit16   (KERNEL.137)
diff --git a/windows/nonclient.c b/windows/nonclient.c
index e9b2489..7bdbce4 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -11,7 +11,7 @@
 #include "sysmetrics.h"
 #include "user.h"
 #include "heap.h"
-#include "shell.h"
+#include "cursoricon.h"
 #include "dialog.h"
 #include "syscolor.h"
 #include "menu.h"
@@ -67,8 +67,6 @@
 #define ON_BOTTOM_BORDER(hit) \
  (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
 
-extern HCURSOR16 CURSORICON_IconToCursor( HICON16, BOOL32 );
-
 /***********************************************************************
  *           NC_AdjustRect
  *
diff --git a/windows/painting.c b/windows/painting.c
index 9ab73d4..eeb1c78 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -144,6 +144,10 @@
     }
 
     GetRgnBox16( InquireVisRgn(lps->hdc), &lps->rcPaint );
+
+dprintf_win(stddeb,"box = (%i,%i - %i,%i)\n", lps->rcPaint.left, lps->rcPaint.top,
+		    lps->rcPaint.right, lps->rcPaint.bottom );
+
     DPtoLP16( lps->hdc, (LPPOINT16)&lps->rcPaint, 2 );
 
     if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
diff --git a/windows/scroll.c b/windows/scroll.c
index fdc9f4a..b4daae6 100644
--- a/windows/scroll.c
+++ b/windows/scroll.c
@@ -387,7 +387,7 @@
         else if( bUpdate ) hrgnUpdate = CreateRectRgn32( 0, 0, 0, 0 );
 
 	hDC = GetDCEx32( hwnd, hrgnClip, DCX_CACHE | DCX_USESTYLE | 
-		        (flags & SW_SCROLLCHILDREN) ? DCX_NOCLIPCHILDREN : 0 );
+		       ((flags & SW_SCROLLCHILDREN) ? DCX_NOCLIPCHILDREN : 0) );
 	if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
 	{
 	    POINT32 dst, src;
diff --git a/windows/win.c b/windows/win.c
index 5f6fbc0..c8ac1c4 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -45,11 +45,7 @@
 
 extern BOOL32 ICONTITLE_Init(void);
 extern BOOL32 MENU_PatchResidentPopup( HQUEUE16, WND* );
-extern HCURSOR16 CURSORICON_IconToCursor(HICON16, BOOL32);
 extern HWND32 CARET_GetHwnd(void);
-extern BOOL32 WINPOS_CreateInternalPosAtom(void);
-extern void   WINPOS_CheckInternalPos(HWND32);
-extern BOOL32 WINPOS_ActivateOtherWindow(WND* pWnd);
 extern BOOL32 EVENT_CheckFocus(void);
 
 /***********************************************************************
@@ -623,8 +619,17 @@
         if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
         if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
     }
-    if (cs->cx <= 0) cs->cx = 1;
-    if (cs->cy <= 0) cs->cy = 1;
+
+    if(cs->style & WS_CHILD)
+    {
+        if(cs->cx < 0) cs->cx = 0;
+        if(cs->cy < 0) cs->cy = 0;
+    }
+    else
+    {
+        if (cs->cx <= 0) cs->cx = 1;
+        if (cs->cy <= 0) cs->cy = 1;
+    }
 
     wndPtr->rectWindow.left   = cs->x;
     wndPtr->rectWindow.top    = cs->y;
@@ -1148,13 +1153,15 @@
             return 0;
     }
 
+
     for ( ; pWnd; pWnd = pWnd->next)
     {
         if (className && !(pWnd->dwStyle & WS_CHILD))
         {
-            if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
+            if (!(pClass = CLASS_FindClassByAtom( className, GetExePtr(pWnd->hInstance))))
                 continue;  /* Skip this window */
         }
+
         if (pClass && (pWnd->class != pClass))
             continue;  /* Not the right class */
 
diff --git a/windows/winhelp.c b/windows/winhelp.c
index 3b0576f..d8521d4 100644
--- a/windows/winhelp.c
+++ b/windows/winhelp.c
@@ -28,21 +28,28 @@
 BOOL32 WINAPI WinHelp32A( HWND32 hWnd, LPCSTR lpHelpFile, UINT32 wCommand,
                           DWORD dwData )
 {
-	static WORD WM_WINHELP=0;
+	static WORD WM_WINHELP = 0;
 	HWND32 hDest;
 	LPWINHELP lpwh;
 	HGLOBAL16 hwh;
 	int size,dsize,nlen;
         if (wCommand != HELP_QUIT)  /* FIXME */
-            if(WinExec32("winhelp.exe -x",SW_SHOWNORMAL)<=32)
+	{
+            if (WinExec32("winhelp.exe -x",SW_SHOWNORMAL) <= 32)
 		return FALSE;
-	/* FIXME: Should be directed yield, to let winhelp open the window */
-	Yield16();
-	if(!WM_WINHELP) {
+
+	    /* NOTE: Probably, this should be directed yield, 
+		     to let winhelp open the window in all cases. */
+	    Yield16();
+	}
+
+	if(!WM_WINHELP) 
+	{
 		WM_WINHELP=RegisterWindowMessage32A("WM_WINHELP");
 		if(!WM_WINHELP)
 			return FALSE;
 	}
+
 	hDest = FindWindow32A( "MS_WINHELP", NULL );
 	if(!hDest)
 		if(wCommand == HELP_QUIT)
diff --git a/windows/winproc.c b/windows/winproc.c
index 259b384..1402b6c 100644
--- a/windows/winproc.c
+++ b/windows/winproc.c
@@ -76,18 +76,18 @@
           (WNDPROC16)((pproc)->thunk.t_from32.proc) : \
           (WNDPROC16)((pproc)->thunk.t_from16.proc))
 
-LRESULT WINPROC_CallProc16To32A( HWND16 hwnd, UINT16 msg,
-                                 WPARAM16 wParam, LPARAM lParam,
-                                 WNDPROC32 func );
-LRESULT WINPROC_CallProc16To32W( HWND16 hwnd, UINT16 msg,
-                                 WPARAM16 wParam, LPARAM lParam,
-                                 WNDPROC32 func );
 static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND32 hwnd,
                                                UINT32 msg, WPARAM32 wParam,
                                                LPARAM lParam );
 static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND32 hwnd,
                                                UINT32 msg, WPARAM32 wParam,
                                                LPARAM lParam );
+static LRESULT WINPROC_CallProc16To32A( HWND16 hwnd, UINT16 msg,
+					WPARAM16 wParam, LPARAM lParam,
+					WNDPROC32 func );
+static LRESULT WINPROC_CallProc16To32W( HWND16 hwnd, UINT16 msg,
+					WPARAM16 wParam, LPARAM lParam,
+					WNDPROC32 func );
 
 static HANDLE32 WinProcHeap;
 
@@ -739,8 +739,13 @@
         *plparam   = (LPARAM)(HMENU32)HIWORD(*plparam);
         return 0;
     case WM_MDIACTIVATE:
-        *pwparam32 = (WPARAM32)(HWND32)HIWORD(*plparam);
-        *plparam   = (LPARAM)(HWND32)LOWORD(*plparam);
+	if( *plparam )
+	{
+	    *pwparam32 = (WPARAM32)(HWND32)HIWORD(*plparam);
+	    *plparam   = (LPARAM)(HWND32)LOWORD(*plparam);
+	}
+	else /* message sent to MDI client */
+	    *pwparam32 = wParam16;
         return 0;
     case WM_NCCALCSIZE:
         {
@@ -1343,9 +1348,17 @@
         *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
         return 0;
     case WM_MDIACTIVATE:
-        *pwparam16 = ((HWND32)*plparam == hwnd);
-        *plparam = MAKELPARAM( (HWND16)LOWORD(*plparam),
-                               (HWND16)LOWORD(wParam32) );
+	if( WIDGETS_IsControl32(WIN_FindWndPtr(hwnd), BIC32_MDICLIENT) )
+	{
+	    *pwparam16 = (HWND32)wParam32;
+	    *plparam = 0;
+	}
+	else
+	{
+	    *pwparam16 = ((HWND32)*plparam == hwnd);
+	    *plparam = MAKELPARAM( (HWND16)LOWORD(*plparam),
+				   (HWND16)LOWORD(wParam32) );
+	}
         return 0;
     case WM_NCCALCSIZE:
         {