Release 980601

Sun May 31 13:40:13 1998  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [if1632/signal.c]
	Added display of exception name.

	* [loader/task.c]
	Yet another attempt at fixing SwitchStackTo/SwitchStackBack.

	* [memory/selector.c] [relay32/builtin32.c] [tools/build.c]
	  [win32/kernel32.c]
	Generate an assembly stub for Win32 register functions to make
	their names available at link time.

	* [programs/*/Makefile.in]
	Added hacks to support old resource compiler.

Fri May 29 16:27:14 1998  Marcus Meissner <marcus@jet.franken.de>

	* [tools/testrun]
	Merge of my testscripts at home into one single perl program
	(tested with perl5). Works only on Linux due to 'ps' and 'ipcs'
	magic.

	* [controls/menu.c]
	Added some DefaultMenuItem stubs.

	* [debugger/stabs.c]
	Fixed stabs loading, now supports (int,int) typeinfo format used
	by gcc-2.8 and egcs-1. If it still crashes, please mail me.

	* [if1632/][relay32/]
	Added msvideo.dll (stubs only)
	Replaced some ptr by str for stringcases
	Added some new stubs (VxDCall, FindCloseNotif....)

	* [misc/network.c]
	Some argument fixes.

	* [misc/registry.c][misc/cpu.c]
	Registry initialization partially rewritten and enhanced.

	* [scheduler/*.c]
	Some additions so we don't do kill(0,SIGUSR1) (kill processgroup
	instead of targeted thread)
	Added SetThreadContext.

Thu May 28 23:59:59 1998  Bertho Stultiens <bertho@akhphd.au.dk>

	* [tools/wrc/*]
	New resource compiler version 1.0.0 (28-May-1998)

	* [Make.rules.in] [Makefile.in]
	Changed and added rc rules to point to tools/wrc/wrc.

	* [configure.in] [include/config.h.in]
	Added check for function 'stricmp'.

	* [include/resource.h]
	Commented out the old resource structure to catch references.
	It also includes wrc_rsc.h.

	* [include/wrc_rsc.h]
	New file. Definitions for the resources generated with wrc.

	* [include/windows.h]
	Added #ifdef RC_INVOKED to exclude stdarg.h.
	Added SS_NOTIFY flag.

	* [include/winnls.h]
	Added SUBLANG_* definitions and corrected some defaults.

	* [loader/libres.c]
	Changed the sysres load functions to support wrc generated
	resources.

	* [resource/sysres_*.rc]
	Added #include <windows.h>

	* [resource/sysres.c]
	Changed declarations to match wrc's output

	* [resource/Makefile.in]
	Changed rules to work with wrc.

	* [tools/makedep.c]
	Changed generation of .rc file dependencies to .s target.

Thu May 28 22:28:39 1998  Eric Kohl <ekohl@abo.rhein-zeitung.de>

	* [files/file.c][include/windows.c][relay32/kernel32.spec]
	Implemented GetFileAttributesEx32A/W.

	* [misc/imagelist.h][include/commctrl.h][relay32/comctl32.spec]
	Added ImageList_Read and ImageList_Write stubs.
	Added ImageList_AddIcon function.
	Added ImageList_LoadImage. It is the same as ImageList_LoadImage32A.

	* [controls/header.c]
	Fixed bitmap drawing bug.
	Added full bitmap support.

	* [include/commctrl.h]
	Added missing header macros.

	* [controls/toolbar.c][include/toolbar.h][include/commctrl.h]
	  [controls/commctrl.c] [relay32/comctl32.spec]
	First implementation of toolbar control.
	Implemented CreateToolbar, CreateToolbarEx and CreateMappedBitmap.

	* [controls/progress.c][controls/status.c]
	Some code cleanup.

	* [controls/commctrl.c][include/commctrl.h][relay32/comctl32.spec]
	Removed CreateStatusWindow16 and DrawStatusText16.
	CreateStatusWindow is the same as CreateStatusWindow32A.
	DrawStatusText is the same as DrawStatusText32A.

Thu May 28 16:01:28 1998  Matthew J. Francis  <asbel@dial.pipex.com>

	* [objects/bitmap.c] [objects/bitmap.h] [objects/oembitmap.c]
	  [objects/dc.c] [graphics/x11drv/bitblt.c]
	Added partial implementation of CreateDIBSection, with great thanks
	to Ulrich Weigand <weigand@informatik.uni-erlangen.de> for
	contributing the bulk of the patch.

Wed May 27 19:04:31 1998  Ulrich Weigand <weigand@informatik.uni-erlangen.de>

	* [win32/kernel32.c] [if1632/thunk.c] [include/flatthunk.h]
	ThunkConnect16 and related functions moved to emulator.

	* [loader/ne/segment.c]
	Call DllEntryPoint with correct arguments.

	* [relay32/builtin32.c]
	Bugfix: Relay debugging did not work for multiple processes.

	* [controls/menu.c]
	Bugfix: dwItemData was not set for MF_OWNERDRAW menus.

	* [if1632/relay.c] [relay32/relay386.c]
	Relay messages converted to use DPRINTF.

	* [controls/desktop.c] [relay32/user32.spec]
	Implemented PaintDesktop.

	* [files/profile.c] [if1632/kernel.spec] [misc/network.c]
	  [misc/printdrv.c] [relay32/winspool.spec] 
	  [win32/ordinals.c] [relay32/kernel32.spec]
	Some stubs added.

	* [relay32/mpr.spec]
	All ordinals were off by one.

Tue May 26 13:32:57 1998  Bill Hawes <whawes@star.net>

	* [misc/lstr.c] [include/casemap.h] [tools/unimap.pl]
	Added Unicode case conversion routines towupper/towlower,
	with mapping tables casemap.h created by tools/unimap.pl.

	* [misc/ntdll.c] [include/winnls.h] [relay32/ntdll.spec]
	  [relay32/advapi.spec]
	Minimal implementation of IsTextUnicode, just enough to get
	NT4 notepad to open ascii/unicode files.

	* [Make.rules.in] [resources/sysres_En.rc]
	Added include file dlgs.h for building resource files, so that
	resources can refer to defined values (e.g. pshHelp).

	* [misc/crtdll.c] [relay32/crtdll.spec]
	Use towupper/towlower for 32W case conversions.

	* [memory/string.c]
	Use towupper for 32W case conversions.

	* [ole/ole2nls.c]
	Use towupper for 32W case conversions; fix mem leak; minor cleanup

	* [controls/edit.c]
	Added soft break flag to edit state. Print unknown action values
	for WM_VSCROLL (action 190 occurs when running NT4 notepad.)

Mon May 25 22:42:40 1998  Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>

	* [files/file.c]
	Care for a pathological case in SetFilePointer.

	* [graphics/x11drv/xfont.c]
	Handle longer Font names in LFD_ComposeLFD and try to catch errors.

	* [loader/pe_image.c]
	Unload Dummymodule when PE_LoadLibraryEx32A fails with
	PE_LoadImage (makes Encarta 98 installer proceed).

	* [misc/registry.c]
	Move a check for a special case in RegCreateKeyEx32W after the
	check for existence.

Tue May 25 20:18:26 1998  Matthew Becker <mbecker@glasscity.net>

	* [misc/ntdll.c]
	Added some stubs, just guessing at the size of their param lists.

	* [misc/registry.c]
	Added stubs for RegUnLoadKey, RegSetKeySecurity, RegSaveKey,
	RegRestoreKey, and RegReplaceKey

	* [programs/regtest/regtest.c]
	Updated registry testing program.

Sun May 24 18:11:40 1998  Alex Priem <alexp@sci.kun.nl>

	* [file/profile.c]
	Added flag 'return_values' to PROFILE_GetSection.

Sun May 24 13:41:10 1998  James Juran <jrj120@psu.edu>

	* [misc/shell.c] [files/directory.c]
	Documentation/debugging info additions.

	* [*/*.c] [include/*.h]
	Moved many extern function definitions to appropriate header files.
	Cleaned up a few compile warnings.
	If #include "debug.h" is present, removed #include <stdio.h>.
	debug.h includes stdio.h, so it is not necessary to include both.

	* [graphics/*.c] [if1632/signal.c] [ipc/*.c] [scheduler/*.c]
	  [win32/*.c] [windows/*.c]
	Final patch to convert fprintf statements to new debugging interface.
	Some fprintfs are still left, especially in the debugger/ directory.
	However, IMHO, it's not worth the effort to change the rest.

Fri May 22 21:58:35 1998  Morten Welinder  <terra@diku.dk>

	* [windows/keyboard.c]
	Correct handling of keys "`-=[]\;',./".

Fri May 22 12:06:00 1998  Per Lindström <pelinstr@algonet.se>

	* [include/windows.h] [relay32/kernel32.spec] [win32/console.c]
	Added stub for ReadConsoleOutputCharacter32A.

Thu May 21 16:45:48 1998  Pascal Cuoq <pcuoq@ens-lyon.fr>

	* [ole/ole2nls.c]
	Began better implementation of LCMapString32A.
	Not very well tested yet, and still need improvements.

	* [controls/scroll.c]
	Documented functions.

Wed May 20 21:37:56 1998  Peter Hunnisett <hunnise@nortel.ca>

	* [include/windows.h][misc/main.c]
	Change SystemParameterInfo to support SPI_GETHIGHCONTRAST. Also
	include some missing SPI_ definitions.

	* [include/dsound.h][multimedia/dsound.c][relay32/dplayx.spec]
	Added stubs for DirectPlayLobbyCreate[AW]. Not sure if these
	should go into a new files dplayx.c? Anyone care?

	* [include/winnls.h]
	Added two missing flags for the CompareString32 functions.
diff --git a/ANNOUNCE b/ANNOUNCE
index e199bae..6fd775c 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,13 +1,14 @@
-This is release 980517 of Wine, the MS Windows emulator.  This is still a
+This is release 980601 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-980517: (see ChangeLog for details)
-	- Lots of common controls improvements.
-	- Better thunking support.
+WHAT'S NEW with Wine-980601: (see ChangeLog for details)
+	- New resource compiler.
+	- Toolbar control.
+	- Partial implementation of CreateDIBSection.
 	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -16,10 +17,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-980517.tar.gz
-  ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-980517.tar.gz
-  ftp://ftp.infomagic.com/pub/mirrors/linux/sunsite/ALPHA/wine/development/Wine-980517.tar.gz
-  ftp://ftp.progsoc.uts.edu.au/pub/Wine/development/Wine-980517.tar.gz
+  ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-980601.tar.gz
+  ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-980601.tar.gz
+  ftp://ftp.infomagic.com/pub/mirrors/linux/sunsite/ALPHA/wine/development/Wine-980601.tar.gz
+  ftp://ftp.progsoc.uts.edu.au/pub/Wine/development/Wine-980601.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
diff --git a/AUTHORS b/AUTHORS
index 402ded9..6e4acf4 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -23,6 +23,7 @@
 Niels de Carpentier,
 Gordon Chaffee,
 Jimen Ching,
+Pascal Cuoq,
 David A. Cuthbert,
 Huw D. M. Davies,
 Roman Dolejsi,
@@ -34,6 +35,7 @@
 Claus Fischer,
 Olaf Flebbe,
 Chad Fraleigh,
+Matthew Francis,
 Peter Galbavy,
 Ramon Garcia,
 Matthew Ghio,
@@ -42,6 +44,7 @@
 Charles M. Hannum,
 Adrian Harvey,
 John Harvey,
+Bill Hawes,
 Cameron Heide,
 Jochen Hoenicke,
 Onno Hovers,
@@ -123,6 +126,7 @@
 Ronan Waide,
 Eric Warnke,
 Manfred Weichel,
+Ulrich Weigand,
 Morten Welinder,
 Len White,
 Lawson Whitney,
diff --git a/ChangeLog b/ChangeLog
index b5888c3..ca76271 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,268 @@
 ----------------------------------------------------------------------
+Sun May 31 13:40:13 1998  Alexandre Julliard  <julliard@lrc.epfl.ch>
+
+	* [if1632/signal.c]
+	Added display of exception name.
+
+	* [loader/task.c]
+	Yet another attempt at fixing SwitchStackTo/SwitchStackBack.
+
+	* [memory/selector.c] [relay32/builtin32.c] [tools/build.c]
+	  [win32/kernel32.c]
+	Generate an assembly stub for Win32 register functions to make
+	their names available at link time.
+
+	* [programs/*/Makefile.in]
+	Added hacks to support old resource compiler.
+
+Fri May 29 16:27:14 1998  Marcus Meissner <marcus@jet.franken.de>
+
+	* [tools/testrun]
+	Merge of my testscripts at home into one single perl program
+	(tested with perl5). Works only on Linux due to 'ps' and 'ipcs'
+	magic.
+
+	* [controls/menu.c]
+	Added some DefaultMenuItem stubs.
+
+	* [debugger/stabs.c]
+	Fixed stabs loading, now supports (int,int) typeinfo format used
+	by gcc-2.8 and egcs-1. If it still crashes, please mail me.
+
+	* [if1632/][relay32/]
+	Added msvideo.dll (stubs only)
+	Replaced some ptr by str for stringcases
+	Added some new stubs (VxDCall, FindCloseNotif....)
+
+	* [misc/network.c]
+	Some argument fixes.
+
+	* [misc/registry.c][misc/cpu.c]
+	Registry initialization partially rewritten and enhanced.
+
+	* [scheduler/*.c]
+	Some additions so we don't do kill(0,SIGUSR1) (kill processgroup
+	instead of targeted thread)
+	Added SetThreadContext.
+
+Thu May 28 23:59:59 1998  Bertho Stultiens <bertho@akhphd.au.dk>
+
+	* [tools/wrc/*]
+	New resource compiler version 1.0.0 (28-May-1998)
+
+	* [Make.rules.in] [Makefile.in]
+	Changed and added rc rules to point to tools/wrc/wrc.
+
+	* [configure.in] [include/config.h.in]
+	Added check for function 'stricmp'.
+
+	* [include/resource.h]
+	Commented out the old resource structure to catch references.
+	It also includes wrc_rsc.h.
+
+	* [include/wrc_rsc.h]
+	New file. Definitions for the resources generated with wrc.
+
+	* [include/windows.h]
+	Added #ifdef RC_INVOKED to exclude stdarg.h.
+	Added SS_NOTIFY flag.
+
+	* [include/winnls.h]
+	Added SUBLANG_* definitions and corrected some defaults.
+
+	* [loader/libres.c]
+	Changed the sysres load functions to support wrc generated
+	resources.
+
+	* [resource/sysres_*.rc]
+	Added #include <windows.h>
+
+	* [resource/sysres.c]
+	Changed declarations to match wrc's output
+
+	* [resource/Makefile.in]
+	Changed rules to work with wrc.
+
+	* [tools/makedep.c]
+	Changed generation of .rc file dependencies to .s target.
+
+Thu May 28 22:28:39 1998  Eric Kohl <ekohl@abo.rhein-zeitung.de>
+
+	* [files/file.c][include/windows.c][relay32/kernel32.spec]
+	Implemented GetFileAttributesEx32A/W.
+
+	* [misc/imagelist.h][include/commctrl.h][relay32/comctl32.spec]
+	Added ImageList_Read and ImageList_Write stubs.
+	Added ImageList_AddIcon function.
+	Added ImageList_LoadImage. It is the same as ImageList_LoadImage32A.
+
+	* [controls/header.c]
+	Fixed bitmap drawing bug.
+	Added full bitmap support.
+
+	* [include/commctrl.h]
+	Added missing header macros.
+
+	* [controls/toolbar.c][include/toolbar.h][include/commctrl.h]
+	  [controls/commctrl.c] [relay32/comctl32.spec]
+	First implementation of toolbar control.
+	Implemented CreateToolbar, CreateToolbarEx and CreateMappedBitmap.
+
+	* [controls/progress.c][controls/status.c]
+	Some code cleanup.
+
+	* [controls/commctrl.c][include/commctrl.h][relay32/comctl32.spec]
+	Removed CreateStatusWindow16 and DrawStatusText16.
+	CreateStatusWindow is the same as CreateStatusWindow32A.
+	DrawStatusText is the same as DrawStatusText32A.
+
+Thu May 28 16:01:28 1998  Matthew J. Francis  <asbel@dial.pipex.com>
+
+	* [objects/bitmap.c] [objects/bitmap.h] [objects/oembitmap.c]
+	  [objects/dc.c] [graphics/x11drv/bitblt.c]
+	Added partial implementation of CreateDIBSection, with great thanks
+	to Ulrich Weigand <weigand@informatik.uni-erlangen.de> for
+	contributing the bulk of the patch.
+
+Wed May 27 19:04:31 1998  Ulrich Weigand <weigand@informatik.uni-erlangen.de>
+
+	* [win32/kernel32.c] [if1632/thunk.c] [include/flatthunk.h]
+	ThunkConnect16 and related functions moved to emulator.
+
+	* [loader/ne/segment.c]
+	Call DllEntryPoint with correct arguments.
+
+	* [relay32/builtin32.c]
+	Bugfix: Relay debugging did not work for multiple processes.
+
+	* [controls/menu.c]
+	Bugfix: dwItemData was not set for MF_OWNERDRAW menus.
+
+	* [if1632/relay.c] [relay32/relay386.c]
+	Relay messages converted to use DPRINTF.
+
+	* [controls/desktop.c] [relay32/user32.spec]
+	Implemented PaintDesktop.
+
+	* [files/profile.c] [if1632/kernel.spec] [misc/network.c]
+	  [misc/printdrv.c] [relay32/winspool.spec] 
+	  [win32/ordinals.c] [relay32/kernel32.spec]
+	Some stubs added.
+
+	* [relay32/mpr.spec]
+	All ordinals were off by one.
+
+Tue May 26 13:32:57 1998  Bill Hawes <whawes@star.net>
+
+	* [misc/lstr.c] [include/casemap.h] [tools/unimap.pl]
+	Added Unicode case conversion routines towupper/towlower,
+	with mapping tables casemap.h created by tools/unimap.pl.
+
+	* [misc/ntdll.c] [include/winnls.h] [relay32/ntdll.spec]
+	  [relay32/advapi.spec]
+	Minimal implementation of IsTextUnicode, just enough to get
+	NT4 notepad to open ascii/unicode files.
+
+	* [Make.rules.in] [resources/sysres_En.rc]
+	Added include file dlgs.h for building resource files, so that
+	resources can refer to defined values (e.g. pshHelp).
+
+	* [misc/crtdll.c] [relay32/crtdll.spec]
+	Use towupper/towlower for 32W case conversions.
+
+	* [memory/string.c]
+	Use towupper for 32W case conversions.
+
+	* [ole/ole2nls.c]
+	Use towupper for 32W case conversions; fix mem leak; minor cleanup
+
+	* [controls/edit.c]
+	Added soft break flag to edit state. Print unknown action values
+	for WM_VSCROLL (action 190 occurs when running NT4 notepad.)
+
+Mon May 25 22:42:40 1998  Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
+
+	* [files/file.c]
+	Care for a pathological case in SetFilePointer.
+
+	* [graphics/x11drv/xfont.c]
+	Handle longer Font names in LFD_ComposeLFD and try to catch errors.
+
+	* [loader/pe_image.c]
+	Unload Dummymodule when PE_LoadLibraryEx32A fails with
+	PE_LoadImage (makes Encarta 98 installer proceed).
+
+	* [misc/registry.c]
+	Move a check for a special case in RegCreateKeyEx32W after the
+	check for existence.
+
+Tue May 25 20:18:26 1998  Matthew Becker <mbecker@glasscity.net>
+
+	* [misc/ntdll.c]
+	Added some stubs, just guessing at the size of their param lists.
+
+	* [misc/registry.c]
+	Added stubs for RegUnLoadKey, RegSetKeySecurity, RegSaveKey,
+	RegRestoreKey, and RegReplaceKey
+
+	* [programs/regtest/regtest.c]
+	Updated registry testing program.
+
+Sun May 24 18:11:40 1998  Alex Priem <alexp@sci.kun.nl>
+
+	* [file/profile.c]
+	Added flag 'return_values' to PROFILE_GetSection.
+
+Sun May 24 13:41:10 1998  James Juran <jrj120@psu.edu>
+
+	* [misc/shell.c] [files/directory.c]
+	Documentation/debugging info additions.
+
+	* [*/*.c] [include/*.h]
+	Moved many extern function definitions to appropriate header files.
+	Cleaned up a few compile warnings.
+	If #include "debug.h" is present, removed #include <stdio.h>.
+	debug.h includes stdio.h, so it is not necessary to include both.
+
+	* [graphics/*.c] [if1632/signal.c] [ipc/*.c] [scheduler/*.c]
+	  [win32/*.c] [windows/*.c]
+	Final patch to convert fprintf statements to new debugging interface.
+	Some fprintfs are still left, especially in the debugger/ directory.
+	However, IMHO, it's not worth the effort to change the rest.
+
+Fri May 22 21:58:35 1998  Morten Welinder  <terra@diku.dk>
+
+	* [windows/keyboard.c]
+	Correct handling of keys "`-=[]\;',./".
+
+Fri May 22 12:06:00 1998  Per Lindström <pelinstr@algonet.se>
+
+	* [include/windows.h] [relay32/kernel32.spec] [win32/console.c]
+	Added stub for ReadConsoleOutputCharacter32A.
+
+Thu May 21 16:45:48 1998  Pascal Cuoq <pcuoq@ens-lyon.fr>
+
+	* [ole/ole2nls.c]
+	Began better implementation of LCMapString32A.
+	Not very well tested yet, and still need improvements.
+
+	* [controls/scroll.c]
+	Documented functions.
+
+Wed May 20 21:37:56 1998  Peter Hunnisett <hunnise@nortel.ca>
+
+	* [include/windows.h][misc/main.c]
+	Change SystemParameterInfo to support SPI_GETHIGHCONTRAST. Also
+	include some missing SPI_ definitions.
+
+	* [include/dsound.h][multimedia/dsound.c][relay32/dplayx.spec]
+	Added stubs for DirectPlayLobbyCreate[AW]. Not sure if these
+	should go into a new files dplayx.c? Anyone care?
+
+	* [include/winnls.h]
+	Added two missing flags for the CompareString32 functions.
+
+----------------------------------------------------------------------
 Sun May 17 16:23:56 1998  Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
 
 	* [file/profile.c]
diff --git a/Make.rules.in b/Make.rules.in
index 9080b93..5fefa53 100644
--- a/Make.rules.in
+++ b/Make.rules.in
@@ -11,6 +11,7 @@
 # RC_SRCS      : resource source files (optional)
 # EXTRA_SRCS   : extra source files for make depend (optional)
 # EXTRA_OBJS   : extra object files (optional)
+# WRCEXTRA     : extra wrc flags (e.g. '-p _SysRes') (optional)
 
 # First some useful definitions
 
@@ -42,6 +43,8 @@
 BUILD     = $(TOPOBJDIR)/tools/build@PROGEXT@
 MAKEDEP   = $(TOPOBJDIR)/tools/makedep@PROGEXT@
 WINERC    = $(TOPOBJDIR)/rc/winerc@PROGEXT@
+WRC       = $(TOPOBJDIR)/tools/wrc/wrc@PROGEXT@
+WRCFLAGS  = -t -c
 WINESTUB  = $(TOPOBJDIR)/library/winestub.o
 SUBMAKE   = $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'OPTIONS=$(OPTIONS)'
 @SET_MAKE@
@@ -65,7 +68,7 @@
 
 # Implicit rules
 
-.SUFFIXES: .rc
+.SUFFIXES: .rc .res
 
 .c.o:
 	$(CC) -c $(ALLCFLAGS) -o $*.o $<
@@ -76,26 +79,46 @@
 .S.o:
 	$(CC) -c -o $*.o $<  
 
-.rc.c:
-	echo "#include \"windows.h\"" >$*-tmp.c
-	echo WINDOWS_H_ENDS_HERE >>$*-tmp.c
-	cat $< >>$*-tmp.c
-	$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P $*-tmp.c | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | $(WINERC) $(RCFLAGS) -c -o $* -p $*
-	$(RM) $*-tmp.c
+.rc.s:
+	$(WRC) $(WRCFLAGS) $(WRCEXTRA) $(DIVINCL) $<
 
 .rc.h:
-	echo "#include \"windows.h\"" >$*-tmp.c
-	echo WINDOWS_H_ENDS_HERE >>$*-tmp.c
-	cat $< >>$*-tmp.c
-	$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P $*-tmp.c | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | $(WINERC) $(RCFLAGS) -c -o $* -p $*
-	$(RM) $*-tmp.c
+	$(WRC) $(WRCFLAGS) $(WRCEXTRA) $(DIVINCL) -nh $<
+
+.rc.res:
+	$(WRC) $(WRCFLAGS) $(WRCEXTRA) $(DIVINCL) -r $<
+
+.res.s:
+	$(WRC) $(WRCFLAGS) $(WRCEXTRA) -b $<
+
+.res.h:
+	$(WRC) $(WRCFLAGS) $(WRCEXTRA) -bnh $<
+
+# Obsolete
+#.rc.c:
+#	echo "#include \"windows.h\"" >$*-tmp.c
+#	echo WINDOWS_H_ENDS_HERE >>$*-tmp.c
+#	cat $< >>$*-tmp.c
+#	$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P $*-tmp.c | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | $(WINERC) $(RCFLAGS) -c -o $* -p $*
+#	$(RM) $*-tmp.c
+#
+#.rc.h:
+#	echo "#include \"windows.h\"" >$*-tmp.c
+#	echo WINDOWS_H_ENDS_HERE >>$*-tmp.c
+#	cat $< >>$*-tmp.c
+#	$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P $*-tmp.c | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | $(WINERC) $(RCFLAGS) -c -o $* -p $*
+#	$(RM) $*-tmp.c
+#
 
 
-# Rule to rebuild resource compiler
+# Rule to rebuild the resource compiler
 
 $(WINERC) check_winerc:
 	cd $(TOPOBJDIR)/rc; $(SUBMAKE) winerc@PROGEXT@
 
+$(WRC) check_wrc:
+	cd $(TOPOBJDIR)/tools/wrc; $(SUBMAKE) wrc@PROGEXT@
+
 # Rule to rebuild the 'makedep' program
 
 $(MAKEDEP) check_makedep:
@@ -132,7 +155,7 @@
 	$(MAKEDEP) $(DIVINCL) -C$(SRCDIR) $(C_SRCS) $(RC_SRCS) $(EXTRA_SRCS)
 
 clean::
-	$(RM) *.o \#*\# *~ *% *.bak *.orig *.rej *.flc *-tmp.c y.tab.c y.tab.h lex.yy.c core $(GEN_ASM_SRCS) $(RC_SRCS:.rc=.c) $(RC_SRCS:.rc=.h) $(PROGRAMS)
+	$(RM) *.o \#*\# *~ *% *.bak *.orig *.rej *.flc *-tmp.c y.tab.c y.tab.h lex.yy.c core $(GEN_ASM_SRCS) $(RC_SRCS:.rc=.s) $(RC_SRCS:.rc=.h) $(PROGRAMS)
 
 dummy:
 
diff --git a/Makefile.in b/Makefile.in
index ad023d9..9fe1c38 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -26,6 +26,7 @@
 LIBSUBDIRS = \
 	rc \
 	tools \
+	tools/wrc \
 	controls \
 	files \
 	graphics \
diff --git a/configure b/configure
index 5863cb2..338b548 100755
--- a/configure
+++ b/configure
@@ -2407,7 +2407,7 @@
 fi
 
 
-for ac_func in clone getpagesize memmove sigaltstack strerror tcgetattr timegm usleep wait4 waitpid
+for ac_func in clone getpagesize memmove sigaltstack strerror stricmp tcgetattr timegm usleep wait4 waitpid
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
 echo "configure:2414: checking for $ac_func" >&5
@@ -3291,6 +3291,7 @@
 resources/Makefile
 scheduler/Makefile
 tools/Makefile
+tools/wrc/Makefile
 tsx11/Makefile
 win32/Makefile
 windows/Makefile  include/config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
@@ -3422,6 +3423,7 @@
 resources/Makefile
 scheduler/Makefile
 tools/Makefile
+tools/wrc/Makefile
 tsx11/Makefile
 win32/Makefile
 windows/Makefile "}
diff --git a/configure.in b/configure.in
index 43e2627..91bc37d 100644
--- a/configure.in
+++ b/configure.in
@@ -214,7 +214,7 @@
 
 dnl **** Check for functions and header files ****
 
-AC_CHECK_FUNCS(clone getpagesize memmove sigaltstack strerror tcgetattr timegm usleep wait4 waitpid)
+AC_CHECK_FUNCS(clone getpagesize memmove sigaltstack strerror stricmp tcgetattr timegm usleep wait4 waitpid)
 AC_CHECK_HEADERS(wctype.h sys/syscall.h syscall.h sys/param.h sys/vfs.h sys/mount.h sys/statfs.h float.h linux/cdrom.h sys/cdio.h sys/filio.h)
 AC_HEADER_STAT()
 AC_C_CONST()
@@ -449,6 +449,7 @@
 resources/Makefile
 scheduler/Makefile
 tools/Makefile
+tools/wrc/Makefile
 tsx11/Makefile
 win32/Makefile
 windows/Makefile ])
diff --git a/controls/Makefile.in b/controls/Makefile.in
index 736c00b..ff92f5c 100644
--- a/controls/Makefile.in
+++ b/controls/Makefile.in
@@ -19,6 +19,7 @@
 	scroll.c \
 	static.c \
 	status.c \
+	toolbar.c \
 	uitools.c \
 	updown.c \
 	widgets.c
diff --git a/controls/combo.c b/controls/combo.c
index db24ec3..1b8e1d7 100644
--- a/controls/combo.c
+++ b/controls/combo.c
@@ -6,7 +6,6 @@
  * FIXME: roll up in Netscape 3.01.
  */
 
-#include <stdio.h>
 #include <string.h>
 
 #include "windows.h"
diff --git a/controls/commctrl.c b/controls/commctrl.c
index 245eb86..93de092 100644
--- a/controls/commctrl.c
+++ b/controls/commctrl.c
@@ -11,12 +11,13 @@
 #include "header.h"
 #include "progress.h"
 #include "status.h"
+#include "toolbar.h"
 #include "updown.h"
 #include "debug.h"
 
 
 /***********************************************************************
- *           DrawStatusText32A   (COMCTL32.5)
+ * DrawStatusText32A [COMCTL32.5][COMCTL32.27]
  */
 void WINAPI DrawStatusText32A( HDC32 hdc, LPRECT32 lprc, LPCSTR text,
                                UINT32 style )
@@ -55,22 +56,7 @@
 }
 
 /***********************************************************************
- *           DrawStatusText16   (COMCTL32.27)
- */
-void WINAPI DrawStatusText16( HDC16 hdc, LPRECT16 lprc, LPCSTR text,
-			      UINT16 style )
-{
-  if(!lprc)
-    DrawStatusText32A((HDC32)hdc, 0, text, (UINT32)style);
-  else{    
-    RECT32 rect32;
-    CONV_RECT16TO32( lprc, &rect32 );
-    DrawStatusText32A((HDC32)hdc, &rect32, text, (UINT32)style);
-  }
-}
-
-/***********************************************************************
- *           CreateStatusWindow32A   (COMCTL32.6)
+ * CreateStatusWindow32A [COMCTL32.6][COMCTL32.21]
  */
 HWND32 WINAPI CreateStatusWindow32A( INT32 style, LPCSTR text, HWND32 parent,
                                      UINT32 wid )
@@ -82,18 +68,6 @@
 }
 
 /***********************************************************************
- *           CreateStatusWindow16   (COMCTL32.21)
- */
-HWND16 WINAPI CreateStatusWindow16( INT16 style, LPCSTR text, HWND16 parent,
-				    UINT16 wid )
-{
-    return CreateWindow16(STATUSCLASSNAME16, text, style, 
-			   CW_USEDEFAULT16, CW_USEDEFAULT16,
-			   CW_USEDEFAULT16, CW_USEDEFAULT16, 
-			   parent, wid, 0, 0);
-}
-
-/***********************************************************************
  *           CreateStatusWindow32W   (COMCTL32.22)
  */
 HWND32 WINAPI CreateStatusWindow32W( INT32 style, LPCWSTR text, HWND32 parent,
@@ -177,7 +151,7 @@
         break;
 
       case ICC_BAR_CLASSES:
-        TRACE (commctrl, "No toolbar class implemented!\n");
+	TOOLBAR_Register ();
 	STATUS_Register ();
         TRACE (commctrl, "No trackbar class implemented!\n");
         TRACE (commctrl, "No tooltip class implemented!\n");
@@ -208,6 +182,7 @@
         TRACE (commctrl, "No month calendar class implemented!\n");
         TRACE (commctrl, "No date picker class implemented!\n");
         TRACE (commctrl, "No time picker class implemented!\n");
+        UPDOWN_Register ();
         break;
 
       case ICC_USEREX_CLASSES:
@@ -288,3 +263,81 @@
             break;
     }
 }
+
+
+/***********************************************************************
+ * CreateToolbarEx [COMCTL32.32]
+ *
+ *
+ *
+ */
+
+HWND32 WINAPI
+CreateToolbarEx (HWND32 hwnd, DWORD style, UINT32 wID, INT32 nBitmaps,
+                 HINSTANCE32 hBMInst, UINT32 wBMID, LPCTBBUTTON lpButtons,
+                 INT32 iNumButtons, INT32 dxButton, INT32 dyButton,
+                 INT32 dxBitmap, INT32 dyBitmap, UINT32 uStructSize)
+{
+    HWND32 hwndTB =
+        CreateWindowEx32A(0, TOOLBARCLASSNAME32A, "", style, 0, 0, 0, 0,
+			  hwnd, (HMENU32)wID, 0, NULL);
+    if(hwndTB) {
+	TBADDBITMAP tbab;
+
+        SendMessage32A (hwndTB, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
+
+	/* set bitmap and button size */
+
+	/* add bitmaps */
+	tbab.hInst = hBMInst;
+	tbab.nID   = wBMID;
+	SendMessage32A (hwndTB, TB_ADDBITMAP,
+			(WPARAM32)nBitmaps, (LPARAM)&tbab);
+
+	/* add buttons */
+	SendMessage32A (hwndTB, TB_ADDBUTTONS32A,
+			(WPARAM32)iNumButtons, (LPARAM)&lpButtons);
+    }
+
+    return (hwndTB);
+}
+
+
+/***********************************************************************
+ * CreateMappedBitmap [COMCTL32.8]
+ *
+ *
+ *
+ */
+
+HBITMAP32 WINAPI
+CreateMappedBitmap (HINSTANCE32 hInstance, INT32 idBitmap, UINT32 wFlags,
+		    LPCOLORMAP lpColorMap, INT32 iNumMaps)
+{
+    HBITMAP32 hbm;
+
+    FIXME (commctrl, "semi-stub!\n");
+
+    hbm = LoadBitmap32A (hInstance, MAKEINTRESOURCE32A(idBitmap));
+
+    return hbm;
+ }
+
+
+/***********************************************************************
+ * CreateToolbar [COMCTL32.7]
+ *
+ *
+ *
+ */
+
+HWND32 WINAPI
+CreateToolbar (HWND32 hwnd, DWORD style, UINT32 wID, INT32 nBitmaps,
+	       HINSTANCE32 hBMInst, UINT32 wBMID,
+	       LPCOLDTBBUTTON lpButtons,INT32 iNumButtons)
+{
+    return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
+			    hBMInst, wBMID, (LPCTBBUTTON)lpButtons,
+			    iNumButtons, 0, 0, 0, 0, sizeof (OLDTBBUTTON));
+}
+
diff --git a/controls/desktop.c b/controls/desktop.c
index 520bb56..52add8a 100644
--- a/controls/desktop.c
+++ b/controls/desktop.c
@@ -166,6 +166,18 @@
     return 0;
 }
 
+/***********************************************************************
+ *           PaintDesktop   (USER32.415)
+ *
+ */
+BOOL32 WINAPI PaintDesktop(HDC32 hdc)
+{
+    HWND32 hwnd = GetDesktopWindow32();
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+    DESKTOPINFO *infoPtr = (DESKTOPINFO *)wndPtr->wExtra;
+
+    return DESKTOP_DoEraseBkgnd( hwnd, hdc, infoPtr );
+}
 
 /***********************************************************************
  *           SetDeskPattern   (USER.279)
diff --git a/controls/edit.c b/controls/edit.c
index ab11776..d8407bc 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -11,7 +11,6 @@
  *	please read EDIT.TODO (and update it when you change things)
  */
 
-#include <stdio.h>
 #include "windows.h"
 #include "winnt.h"
 #include "win.h"
@@ -41,6 +40,7 @@
 #define EF_HSCROLL_HACK		0x0040	/* we already have informed the user of the hacked handler */
 #define EF_AFTER_WRAP		0x0080	/* the caret is displayed after the last character of a
 					   wrapped line, instead of in front of the next character */
+#define EF_USE_SOFTBRK		0x0100	/* Enable soft breaks in text. */
 
 typedef BOOL32 *LPBOOL32;
 
@@ -1948,10 +1948,15 @@
  *
  *	EM_FMTLINES
  *
+ * Enable or disable soft breaks.
  */
 static BOOL32 EDIT_EM_FmtLines(WND *wnd, EDITSTATE *es, BOOL32 add_eol)
 {
-	FIXME(edit, "message not implemented\n");
+	es->flags &= ~EF_USE_SOFTBRK;
+	if (add_eol) {
+		es->flags |= EF_USE_SOFTBRK;
+		FIXME(edit, "soft break enabled, not implemented\n");
+	}
 	return add_eol;
 }
 
@@ -1965,7 +1970,7 @@
  *	However, with this message a 32 bit application requests
  *	a handle to 32 bit moveable local heap memory, where it expects
  *	to find the text.
- *	It's a pitty that from this moment on we have to use this
+ *	It's a pity that from this moment on we have to use this
  *	local heap, because applications may rely on the handle
  *	in the future.
  *
@@ -3896,7 +3901,8 @@
 		break;
 
 	default:
-		ERR(edit, "undocumented WM_VSCROLL parameter, please report\n");
+		ERR(edit, "undocumented WM_VSCROLL action %d, please report\n",
+			action);
 		return 0;
 	}
 	if (dy)
diff --git a/controls/header.c b/controls/header.c
index 35a1357..18bbfaa 100644
--- a/controls/header.c
+++ b/controls/header.c
@@ -4,15 +4,20 @@
  *  Copyright 1998 Eric Kohl
  *
  *  TODO:
- *   - Bitmap support (partially).
  *   - Imagelist support (partially).
- *   - Hottrack support (partially).
- *   - Control specific cursors (over dividers).
+ *   - Callback items.
  *   - Owner draw support.
  *   - Order list support.
+ *   - Control specific cursors (over dividers).
+ *   - Hottrack support (partially).
  *   - Custom draw support (including Notifications).
  *   - Drag and Drop support (including Notifications).
  *   - Unicode support.
+ *
+ *  FIXME:
+ *   - Replace DrawText32A by DrawTextEx32A(...|DT_ENDELLIPSIS) in
+ *     HEADER_DrawItem.
+ *   - Little flaw when drawing a bitmap on the right side of the text.
  */
 
 #include "windows.h"
@@ -29,10 +34,6 @@
 #define VERT_BORDER     4
 #define DIVIDER_WIDTH  10
 
-#define UNKNOWN_PARAM(msg, wParam, lParam) WARN(header, \
-        "Unknown parameter(s) for message " #msg     \
-	"(%04x): wp=%04x lp=%08lx\n", msg, wParam, lParam); 
-
 #define HEADER_GetInfoPtr(wndPtr) ((HEADER_INFO *)wndPtr->wExtra[0])
 
 
@@ -76,6 +77,8 @@
 	    HDC32    hdcBitmap;
 	    INT32    yD, yS, cx, cy, rx, ry;
 
+	    GetObject32A (phdi->hbm, sizeof(BITMAP32), (LPVOID)&bmp);
+
 	    ry = r.bottom - r.top;
 	    rx = r.right - r.left;
 
@@ -98,7 +101,6 @@
 		cx = rx - 6;
 	    }
 
-	    GetObject32A (phdi->hbm, sizeof(BITMAP32), (LPVOID)&bmp);
 	    hdcBitmap = CreateCompatibleDC32 (hdc);
 	    SelectObject32 (hdcBitmap, phdi->hbm);
 	    BitBlt32 (hdc, r.left + 3, yD, cx, cy, hdcBitmap, 0, yS, SRCCOPY);
@@ -107,24 +109,63 @@
 	    r.left += (bmp.bmWidth + 3);
 	}
 
-/*
+
 	if ((phdi->fmt & HDF_BITMAP_ON_RIGHT) && (phdi->hbm)) {
 	    BITMAP32 bmp;
 	    HDC32    hdcBitmap;
+	    INT32    xD, yD, yS, cx, cy, rx, ry, tx;
+	    RECT32   textRect;
 
 	    GetObject32A (phdi->hbm, sizeof(BITMAP32), (LPVOID)&bmp);
 
+	    textRect = r;
+            DrawText32A(hdc, phdi->pszText, lstrlen32A(phdi->pszText),
+	   	  &textRect, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_CALCRECT);
+	    tx = textRect.right - textRect.left;
+	    ry = r.bottom - r.top;
+	    rx = r.right - r.left;
 
+	    if (ry >= bmp.bmHeight) {
+		cy = bmp.bmHeight;
+		yD = r.top + (ry - bmp.bmHeight) / 2;
+		yS = 0;
+	    }
+	    else {
+		cy = ry;
+		yD = r.top;
+		yS = (bmp.bmHeight - ry) / 2;
+
+	    }
+
+	    if (r.left + tx + bmp.bmWidth + 9 <= r.right) {
+		cx = bmp.bmWidth;
+		xD = r.left + tx + 6;
+	    }
+	    else {
+		if (rx >= bmp.bmWidth + 6) {
+		    cx = bmp.bmWidth;
+		    xD = r.right - bmp.bmWidth - 3;
+		    r.right = xD - 3;
+		}
+		else {
+		    cx = rx - 3;
+		    xD = r.left;
+		    r.right = r.left;
+		}
+	    }
+
+	    hdcBitmap = CreateCompatibleDC32 (hdc);
+	    SelectObject32 (hdcBitmap, phdi->hbm);
+	    BitBlt32 (hdc, xD, yD, cx, cy, hdcBitmap, 0, yS, SRCCOPY);
+	    DeleteDC32 (hdcBitmap);
 	}
-*/
 
-/*
 	if (phdi->fmt & HDF_IMAGE) {
+	    HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
 
-	    ImageList_Draw (....);
 
+//	    ImageList_Draw (infoPtr->himl, phdi->iImage,...);
 	}
-*/
 
         if ((phdi->fmt & HDF_STRING) && (phdi->pszText)) {
             oldBkMode = SetBkMode32(hdc, TRANSPARENT);
diff --git a/controls/listbox.c b/controls/listbox.c
index e6301a7..60ea183 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -5,7 +5,6 @@
  */
 
 #include <string.h>
-#include <stdio.h>
 #include "windows.h"
 #include "winerror.h"
 #include "drive.h"
diff --git a/controls/menu.c b/controls/menu.c
index 78aaf0a..81bc680 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -15,7 +15,6 @@
 #include <assert.h>
 #include <ctype.h>
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include "windows.h"
 #include "bitmap.h"
@@ -77,6 +76,7 @@
     HWND32      hWnd;         /* Window containing the menu */
     MENUITEM   *items;        /* Array of menu items */
     UINT32      FocusedItem;  /* Currently focused item */
+    WORD	defitem;      /* default item position. Unused (except for set/get)*/
 } POPUPMENU, *LPPOPUPMENU;
 
 /* internal flags for menu tracking */
@@ -1444,9 +1444,13 @@
         }
     }
     else if (flags & MF_BITMAP) item->text = (LPSTR)(HBITMAP32)LOWORD(str);
-    else if (flags & MF_OWNERDRAW) item->text = (LPSTR)str;
     else item->text = NULL;
 
+    if (flags & MF_OWNERDRAW) 
+        item->dwItemData = (DWORD)str;
+    else
+        item->dwItemData = 0;
+
     if ((item->fType & MF_POPUP) && (flags & MF_POPUP) && (item->hSubMenu != id) )
 	DestroyMenu32( item->hSubMenu );   /* ModifyMenu() spec */
 
@@ -3032,7 +3036,6 @@
 	((POPUPMENU *)USER_HEAP_LIN_ADDR((HMENU16)id))->wFlags |= MF_POPUP;
 
     item->hCheckBit = item->hUnCheckBit = 0;
-    item->dwItemData = 0;
     return TRUE;
 }
 
@@ -3735,7 +3738,7 @@
 					 LPMENUITEMINFO32A lpmii,
 					 BOOL32 unicode)
 {
-  MENUITEM *menu = MENU_FindItem (&hmenu, &item, bypos);
+  MENUITEM *menu = MENU_FindItem (&hmenu, &item, bypos? MF_BYPOSITION : 0);
     debug_print_menuitem("GetMenuItemInfo32_common: ", menu, "");
     if (!menu)
 	return FALSE;
@@ -3853,7 +3856,7 @@
 BOOL32 WINAPI SetMenuItemInfo32A(HMENU32 hmenu, UINT32 item, BOOL32 bypos,
                                  const MENUITEMINFO32A *lpmii) 
 {
-    return SetMenuItemInfo32_common(MENU_FindItem(&hmenu, &item, bypos),
+    return SetMenuItemInfo32_common(MENU_FindItem(&hmenu, &item, bypos? MF_BYPOSITION : 0),
 				    lpmii, FALSE);
 }
 
@@ -3863,7 +3866,7 @@
 BOOL32 WINAPI SetMenuItemInfo32W(HMENU32 hmenu, UINT32 item, BOOL32 bypos,
                                  const MENUITEMINFO32W *lpmii)
 {
-    return SetMenuItemInfo32_common(MENU_FindItem(&hmenu, &item, bypos),
+    return SetMenuItemInfo32_common(MENU_FindItem(&hmenu, &item, bypos? MF_BYPOSITION : 0),
 				    (const MENUITEMINFO32A*)lpmii, TRUE);
 }
 
@@ -3872,14 +3875,36 @@
  */
 BOOL32 WINAPI SetMenuDefaultItem32(HMENU32 hmenu, UINT32 item, BOOL32 bypos)
 {
-    MENUITEM *menu = MENU_FindItem(&hmenu, &item, bypos);
-    if (!menu) return FALSE;
-    debug_print_menuitem("SetMenuDefaultItem32: ", menu, "");
+    MENUITEM *menuitem = MENU_FindItem(&hmenu, &item, bypos);
+    POPUPMENU *menu;
+
+    if (!menuitem) return FALSE;
+    if (!(menu = (POPUPMENU *) USER_HEAP_LIN_ADDR(hmenu))) return FALSE;
+
+    menu->defitem = item; /* position */
+
+    debug_print_menuitem("SetMenuDefaultItem32: ", menuitem, "");
     FIXME(menu, "(0x%x,%d,%d), empty stub!\n",
 		  hmenu, item, bypos);
     return TRUE;
 }
 
+/**********************************************************************
+ *		GetMenuDefaultItem32    (USER32.260)
+ */
+UINT32 WINAPI GetMenuDefaultItem32(HMENU32 hmenu, UINT32 bypos, UINT32 flags)
+{
+    POPUPMENU *menu;
+
+    if (!(menu = (POPUPMENU *) USER_HEAP_LIN_ADDR(hmenu))) return 0; /*FIXME*/
+
+    FIXME(menu, "(0x%x,%d,%d), stub!\n", hmenu, bypos, flags);
+    if (bypos & MF_BYPOSITION)
+    	return menu->defitem;
+    else
+    	return menu->items[menu->defitem].wID;
+}
+
 /*******************************************************************
  *              InsertMenuItem16   (USER.441)
  *
diff --git a/controls/progress.c b/controls/progress.c
index 7937d2b..d83cb93 100644
--- a/controls/progress.c
+++ b/controls/progress.c
@@ -159,9 +159,10 @@
     {
     case WM_CREATE:
       /* allocate memory for info struct */
-      wndPtr->wExtra[0] = HeapAlloc (SystemHeap, HEAP_ZERO_MEMORY,
+      infoPtr = (PROGRESS_INFO *)HeapAlloc (SystemHeap, HEAP_ZERO_MEMORY,
                                      sizeof(PROGRESS_INFO));
-      infoPtr = (PROGRESS_INFO *)wndPtr->wExtra[0];
+      wndPtr->wExtra[0] = (DWORD)infoPtr;
+
       /* initialize the info struct */
       infoPtr->MinVal=0; 
       infoPtr->MaxVal=100;
@@ -169,11 +170,11 @@
       infoPtr->Step=10;
       infoPtr->ColorBar=CLR_DEFAULT;
       infoPtr->ColorBk=CLR_DEFAULT;
-      TRACE(updown, "Progress Ctrl creation, hwnd=%04x\n", hwnd);
+      TRACE(progress, "Progress Ctrl creation, hwnd=%04x\n", hwnd);
       break;
     
     case WM_DESTROY:
-      TRACE(updown, "Progress Ctrl destruction, hwnd=%04x\n", hwnd);
+      TRACE(progress, "Progress Ctrl destruction, hwnd=%04x\n", hwnd);
       HeapFree (SystemHeap, 0, infoPtr);
       break;
 
@@ -183,10 +184,12 @@
       return 1;
 	
     case WM_GETFONT:
+      FIXME (progress, "WM_GETFONT - empty message!\n");
       /* FIXME: What do we need to do? */
       break;
 
     case WM_SETFONT:
+      FIXME (progress, "WM_SETFONT - empty message!\n");
       /* FIXME: What do we need to do? */
       break;
 
diff --git a/controls/scroll.c b/controls/scroll.c
index ec71eb4..4f844cf 100644
--- a/controls/scroll.c
+++ b/controls/scroll.c
@@ -6,7 +6,6 @@
  */
 
 #include <stdlib.h>
-#include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include "windows.h"
@@ -900,9 +899,23 @@
 
 /*************************************************************************
  *           SetScrollInfo32   (USER32.501)
+ * SetScrollInfo32 can be used to set the position, upper bound, 
+ * lower bound, and page size of a scrollbar control.
+ *
+ * RETURNS
+ *    Scrollbar position
+ *
+ * NOTE
+ *    For 100 lines of text to be displayed in a window of 25 lines,
+ *  one would for instance use info->nMin=0, info->nMax=75
+ *  (corresponding to the 76 different positions of the window on
+ *  the text), and info->nPage=25.
  */
-INT32 WINAPI SetScrollInfo32( HWND32 hwnd, INT32 nBar, const SCROLLINFO *info,
-                              BOOL32 bRedraw )
+INT32 WINAPI SetScrollInfo32( 
+HWND32 hwnd /* [I] Handle of window whose scrollbar will be affected */, 
+INT32 nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */, 
+const SCROLLINFO *info /* [I] Specifies what to change and new values */,
+BOOL32 bRedraw /* [I] Should scrollbar be redrawn afterwards ? */)
 {
     SCROLLBAR_INFO *infoPtr;
     UINT32 new_flags;
@@ -1019,8 +1032,15 @@
 
 /*************************************************************************
  *           GetScrollInfo32   (USER32.284)
+ * GetScrollInfo32 can be used to retrieve the position, upper bound, 
+ * lower bound, and page size of a scrollbar control.
+ *
+ * RETURNS STD
  */
-BOOL32 WINAPI GetScrollInfo32( HWND32 hwnd, INT32 nBar, LPSCROLLINFO info )
+BOOL32 WINAPI GetScrollInfo32( 
+  HWND32 hwnd /* [I] Handle of window */ , 
+  INT32 nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */, 
+  LPSCROLLINFO info /* [IO] (info.fMask [I] specifies which values are to retrieve) */)
 {
     SCROLLBAR_INFO *infoPtr;
 
@@ -1054,9 +1074,20 @@
 
 /*************************************************************************
  *           SetScrollPos32   (USER32.502)
+ *
+ * RETURNS
+ *    Success: Scrollbar position
+ *    Failure: 0
+ *
+ * REMARKS
+ *    Note the ambiguity when 0 is returned.  Use GetLastError
+ *    to make sure there was an error (and to know which one).
  */
-INT32 WINAPI SetScrollPos32( HWND32 hwnd, INT32 nBar, INT32 nPos,
-                             BOOL32 bRedraw )
+INT32 WINAPI SetScrollPos32( 
+HWND32 hwnd /* [I] Handle of window whose scrollbar will be affected */,
+INT32 nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */,
+INT32 nPos /* [I] New value */,
+BOOL32 bRedraw /* [I] Should scrollbar be redrawn afterwards ? */ )
 {
     SCROLLINFO info;
     SCROLLBAR_INFO *infoPtr;
@@ -1083,8 +1114,18 @@
 
 /*************************************************************************
  *           GetScrollPos32   (USER32.285)
+ *
+ * RETURNS
+ *    Success: Current position
+ *    Failure: 0   
+ *
+ * REMARKS
+ *    Note the ambiguity when 0 is returned.  Use GetLastError
+ *    to make sure there was an error (and to know which one).
  */
-INT32 WINAPI GetScrollPos32( HWND32 hwnd, INT32 nBar )
+INT32 WINAPI GetScrollPos32( 
+HWND32 hwnd, /* [I] Handle of window */
+INT32 nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */)
 {
     SCROLLBAR_INFO *infoPtr;
 
@@ -1107,9 +1148,15 @@
 
 /*************************************************************************
  *           SetScrollRange32   (USER32.503)
+ *
+ * RETURNS STD
  */
-BOOL32 WINAPI SetScrollRange32( HWND32 hwnd, INT32 nBar,
-                                INT32 MinVal, INT32 MaxVal, BOOL32 bRedraw )
+BOOL32 WINAPI SetScrollRange32( 
+HWND32 hwnd, /* [I] Handle of window whose scrollbar will be affected */
+INT32 nBar, /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */
+INT32 MinVal, /* [I] New minimum value */
+INT32 MaxVal, /* [I] New maximum value */
+BOOL32 bRedraw /* [I] Should scrollbar be redrawn afterwards ? */)
 {
     SCROLLINFO info;
 
@@ -1172,9 +1219,14 @@
 
 /*************************************************************************
  *           GetScrollRange32   (USER32.286)
+ *
+ * RETURNS STD
  */
-BOOL32 WINAPI GetScrollRange32( HWND32 hwnd, INT32 nBar,
-                                LPINT32 lpMin, LPINT32 lpMax)
+BOOL32 WINAPI GetScrollRange32( 
+HWND32 hwnd, /* [I] Handle of window */
+INT32 nBar, /* [I] One of SB_HORZ, SB_VERT, or SB_CTL  */
+LPINT32 lpMin, /* [O] Where to store minimum value */
+LPINT32 lpMax /* [O] Where to store maximum value */)
 {
     SCROLLBAR_INFO *infoPtr;
 
@@ -1201,8 +1253,13 @@
 
 /*************************************************************************
  *           ShowScrollBar32   (USER32.532)
+ *
+ * RETURNS STD
  */
-BOOL32 WINAPI ShowScrollBar32( HWND32 hwnd, INT32 nBar, BOOL32 fShow )
+BOOL32 WINAPI ShowScrollBar32( 
+HWND32 hwnd, /* [I] Handle of window whose scrollbar(s) will be affected   */
+INT32 nBar, /* [I] One of SB_HORZ, SB_VERT, SB_BOTH or SB_CTL */
+BOOL32 fShow /* [I] TRUE = show, FALSE = hide  */)
 {
     WND *wndPtr = WIN_FindWndPtr( hwnd );
 
diff --git a/controls/static.c b/controls/static.c
index e088d27..01f386c 100644
--- a/controls/static.c
+++ b/controls/static.c
@@ -5,7 +5,6 @@
  *
  */
 
-#include <stdio.h>
 #include "windows.h"
 #include "win.h"
 #include "bitmap.h"
diff --git a/controls/status.c b/controls/status.c
index e1d8b95..a24a47b 100644
--- a/controls/status.c
+++ b/controls/status.c
@@ -5,8 +5,6 @@
  * Copyright 1998 Eric Kohl
  */
 
-#include <stdio.h>
-
 #include "windows.h"
 #include "status.h"
 #include "commctrl.h"
@@ -21,16 +19,10 @@
 
 /*
  * Fixme/Todo
- * 1) Don't hard code bar to bottom of window, allow CCS_TOP also
- * 2) Add 'non hack' version of icon drawing code
+ * 1) Don't hard code bar to bottom of window, allow CCS_TOP also.
+ + 2) Tooltip support.
  */
 
-#define __GET_ICON_INFO_HACK__
-
-#ifdef __GET_ICON_INFO_HACK__
-#include "bitmap.h"
-#endif
-
 #define _MAX(a,b) (((a)>(b))?(a):(b))
 #define _MIN(a,b) (((a)>(b))?(b):(a))
 
@@ -92,61 +84,20 @@
     RECT32 r = *lprc;
     UINT32 border = BDR_SUNKENOUTER;
 
-    if(style==SBT_POPOUT)
+    if (style==SBT_POPOUT)
       border = BDR_RAISEDOUTER;
-    else if(style==SBT_NOBORDERS)
+    else if (style==SBT_NOBORDERS)
       border = 0;
 
     DrawEdge32(hdc, &r, border, BF_RECT|BF_ADJUST);
 
     /* draw the icon */
     if (hIcon) {
-#ifdef __GET_ICON_INFO_HACK__
-        HBITMAP32 hbmImage;
-        HBITMAP32 hbmMask;
-        CURSORICONINFO *ptr;
-        HDC32 hdcSrc;
-	INT32 y, cy, ry, ty;
+	INT32 cy = r.bottom - r.top;
 
-        if (ptr = (CURSORICONINFO *)GlobalLock16(hIcon)) {
-        hbmMask  = CreateBitmap32 (ptr->nWidth, ptr->nHeight, 1, 1, 
-                                   (char *)(ptr + 1));
-        hbmImage = CreateBitmap32 (ptr->nWidth, ptr->nHeight, ptr->bPlanes,
-                                   ptr->bBitsPerPixel,
-                                   (char *)(ptr + 1) + ptr->nHeight * 
-                                   BITMAP_WIDTH_BYTES(ptr->nWidth, 1));
 	r.left += 2;
-	ry = r.bottom - r.top;
-	if (ry >= ptr->nHeight) {
-	    /* full view of icon */
-	    y = 0;
-	    cy = ptr->nHeight;
-	    ty = r.top + (ry - ptr->nHeight) / 2;
-	}
-	else {
-	    /* partial view of icon */
-	    y = (ptr->nHeight - ry) / 2;
-	    cy = ry;
-	    ty = r.top;
-	}
-
-	    hdcSrc = CreateCompatibleDC32 (hdc);
-	    SelectObject32 (hdcSrc, hbmMask);
-	    BitBlt32 (hdc, r.left, r.top, ptr->nWidth, cy,
-		      hdcSrc, 0, y, SRCAND);
-	    SelectObject32 (hdcSrc, hbmImage);
-	    BitBlt32 (hdc, r.left, r.top, ptr->nWidth, cy,
-		      hdcSrc, 0, y, SRCPAINT);
-	    DeleteDC32 (hdcSrc);
-
-	    r.left += ptr->nWidth;
-	    DeleteObject32 (hbmImage);
-	    DeleteObject32 (hbmMask);
-	    GlobalUnlock16 (hIcon);
-	}
-#else
-	/* FIXME: no "non hack" version available!!! */
-#endif
+	DrawIconEx32 (hdc, r.left, r.top, hIcon, cy, cy, 0, 0, DI_NORMAL);
+	r.left += cy;
     }
 
     /* now draw text */
@@ -378,10 +329,11 @@
     STATUSWINDOWINFO *self;
 
     wndPtr = WIN_FindWndPtr(hwnd);
-    wndPtr->wExtra[0] = HeapAlloc (SystemHeap, HEAP_ZERO_MEMORY,
-				   sizeof(STATUSWINDOWINFO));
+    self = (STATUSWINDOWINFO*)HeapAlloc (SystemHeap, HEAP_ZERO_MEMORY,
+					 sizeof(STATUSWINDOWINFO));
 
-    self = (STATUSWINDOWINFO*)wndPtr->wExtra[0];
+    wndPtr->wExtra[0] = (DWORD)self;
+
     self->numParts = 1;
     self->parts = 0;
     self->simple = FALSE;
@@ -397,33 +349,33 @@
     self->part0.hIcon = 0;
 
     /* initialize first part */
-    self->parts = HeapAlloc(SystemHeap, HEAP_ZERO_MEMORY,
-			    sizeof(STATUSWINDOWPART));
+    self->parts = HeapAlloc (SystemHeap, HEAP_ZERO_MEMORY,
+			     sizeof(STATUSWINDOWPART));
     self->parts[0].bound = rect;
     self->parts[0].text = 0;
     self->parts[0].x = -1;
     self->parts[0].style = 0;
     self->parts[0].hIcon = 0;
 
-    if (len = lstrlen32A( lpCreate->lpszName ) ) {
-        self->parts[0].text = HeapAlloc( SystemHeap, 0, len + 1 );
-        lstrcpy32A( self->parts[0].text, lpCreate->lpszName );
+    if ((len = lstrlen32A (lpCreate->lpszName))) {
+        self->parts[0].text = HeapAlloc (SystemHeap, 0, len + 1);
+        lstrcpy32A (self->parts[0].text, lpCreate->lpszName);
     }
 
     height = 20;
-    if ((hdc = GetDC32(0))) {
+    if ((hdc = GetDC32 (0))) {
 	TEXTMETRIC32A tm;
 	GetTextMetrics32A(hdc, &tm);
 	self->textHeight = tm.tmHeight;
 	ReleaseDC32(0, hdc);
     }
 
-    parent = GetParent32(hwnd);
-    GetClientRect32(parent, &rect);
+    parent = GetParent32 (hwnd);
+    GetClientRect32 (parent, &rect);
     width = rect.right - rect.left;
     self->height = self->textHeight + 4 + VERT_BORDER;
-    MoveWindow32(hwnd, lpCreate->x, lpCreate->y-1, width, self->height, FALSE);
-    SW_SetPartBounds(hwnd, self);
+    MoveWindow32 (hwnd, lpCreate->x, lpCreate->y-1, width, self->height, FALSE);
+    SW_SetPartBounds (hwnd, self);
     return 0;
 }
 
@@ -495,12 +447,11 @@
 static LRESULT
 SW_SetMinHeight(STATUSWINDOWINFO *self, HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
 {
-    INT32	width, height, x, y;
+    INT32	width, x, y;
     RECT32	parent_rect;
     HWND32	parent;
 
     if (IsWindowVisible32 (hwnd)) {
-	/* width and height don't apply */
 	parent = GetParent32(hwnd);
 	GetClientRect32(parent, &parent_rect);
 	self->height = (INT32)wParam + VERT_BORDER;
@@ -531,12 +482,10 @@
 
 
 static LRESULT
-SW_SetIcon(STATUSWINDOWINFO *self, HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
+SW_SetIcon (STATUSWINDOWINFO *self, HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
 {
-    HDC32    hdc;
-    INT32    nPart;
+    INT32  nPart = (INT32)wParam & 0x00ff;
 
-    nPart = (INT32)wParam & 0x00ff;
     if ((nPart < -1) || (nPart >= self->numParts)) return FALSE;
 
     if (nPart == -1) {
@@ -558,7 +507,7 @@
     INT32    nPart;
 
     nPart = (INT32)wParam & 0x00ff;
-    if ((nPart < -1) || (nPart >= self->numParts)) return NULL;
+    if ((nPart < -1) || (nPart >= self->numParts)) return 0;
 
     if (nPart == -1)
         return (self->part0.hIcon);
@@ -663,7 +612,6 @@
 static LRESULT
 SW_NcLButtonDown (HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
 {
-//    TRACE (status, "WM_NCLBUTTONDOWN\n");
     PostMessage32A (GetParent32 (hwnd), WM_NCLBUTTONDOWN,
 		    wParam, lParam);
     return 0;
@@ -673,7 +621,6 @@
 static LRESULT
 SW_NcLButtonUp (HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
 {
-//    TRACE (status, "WM_NCLBUTTONUP\n");
     PostMessage32A (GetParent32 (hwnd), WM_NCLBUTTONUP,
 		    wParam, lParam);
     return 0;
@@ -722,8 +669,8 @@
         HeapFree(SystemHeap, 0, part->text);
     part->text = 0;
     if (lParam && (len = lstrlen32A((LPCSTR)lParam))) {
-        part->text = HeapAlloc(SystemHeap, 0, len+1);
-        lstrcpy32A(part->text, (LPCSTR)lParam);
+        part->text = HeapAlloc (SystemHeap, 0, len+1);
+        lstrcpy32A (part->text, (LPCSTR)lParam);
     }
     InvalidateRect32(hwnd, &part->bound, FALSE);
 
@@ -735,7 +682,7 @@
 SW_Size(STATUSWINDOWINFO *self, HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
 {
     /* Need to resize width to match parent */
-    INT32	width, height, x, y;
+    INT32	width, x, y;
     RECT32	parent_rect;
     HWND32	parent;
 
@@ -836,7 +783,7 @@
     case WM_NCHITTEST:
         return SW_NcHitTest (wndPtr, wParam, lParam);
 
-   case WM_NCLBUTTONDOWN:
+    case WM_NCLBUTTONDOWN:
 	return SW_NcLButtonDown (hwnd, wParam, lParam);
 
     case WM_NCLBUTTONUP:
@@ -862,25 +809,25 @@
 
 
 /***********************************************************************
- *           STATUS_Register [Internal]
+ * STATUS_Register [Internal]
  *
  * Registers the status window class.
  */
-void STATUS_Register(void)
+void STATUS_Register (void)
 {
     WNDCLASS32A wndClass;
 
-    if( GlobalFindAtom32A( STATUSCLASSNAME32A ) ) return;
+    if (GlobalFindAtom32A (STATUSCLASSNAME32A)) return;
 
-    ZeroMemory( &wndClass, sizeof( WNDCLASS32A ) );
+    ZeroMemory (&wndClass, sizeof(WNDCLASS32A));
     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW;
     wndClass.lpfnWndProc   = (WNDPROC32)StatusWindowProc;
     wndClass.cbClsExtra    = 0;
     wndClass.cbWndExtra    = sizeof(STATUSWINDOWINFO *);
-    wndClass.hCursor       = LoadCursor32A( 0, IDC_ARROW32A );
+    wndClass.hCursor       = LoadCursor32A (0, IDC_ARROW32A);
     wndClass.hbrBackground = (HBRUSH32)(COLOR_3DFACE + 1);
     wndClass.lpszClassName = STATUSCLASSNAME32A;
  
-    RegisterClass32A( &wndClass );
+    RegisterClass32A (&wndClass);
 }
 
diff --git a/controls/toolbar.c b/controls/toolbar.c
new file mode 100644
index 0000000..86a1e6c
--- /dev/null
+++ b/controls/toolbar.c
@@ -0,0 +1,1290 @@
+/*
+ * Toolbar control
+ *
+ * Copyright 1998 Eric Kohl
+ *
+ * NOTES
+ *   PLEASE don't try to improve or change this code right now. Many
+ *   features are still missing, but I'm working on it. I want to avoid
+ *   any confusion. This note will be removed as soon as most of the
+ *   features are implemented.
+ *     Eric <ekohl@abo.rhein-zeitung.de>
+ *
+ * TODO:
+ *   - Many messages.
+ *   - All notifications.
+ *   - Tooltip support.
+ *   - Unicode suppport.
+ *   - Internal COMMCTL32 bitmaps.
+ *   - Customize dialog.
+ *
+ * Testing:
+ *   - Run tests using Waite Group Windows95 API Bible Volume 2.
+ *     The second cdrom contains executables addstr.exe, btncount.exe,
+ *     btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe,
+ *     enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe,
+ *     indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe,
+ *     setparnt.exe, setrows.exe, toolwnd.exe.
+ *   - additional features.
+ */
+
+#include "windows.h"
+#include "commctrl.h"
+#include "toolbar.h"
+#include "heap.h"
+#include "win.h"
+#include "debug.h"
+
+
+#define SEPARATOR_WIDTH  12
+
+
+
+
+
+#define TOOLBAR_GetInfoPtr(wndPtr) ((TOOLBAR_INFO *)wndPtr->wExtra[0])
+
+
+static void
+TOOLBAR_DrawButton (WND *wndPtr, TBUTTON_INFO *btnPtr, HDC32 hdc)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    RECT32 rc;
+
+    if (btnPtr->fsState & TBSTATE_HIDDEN) return;
+
+    rc = btnPtr->rect;
+    if (btnPtr->fsStyle & TBSTYLE_SEP) {
+
+    }
+    else {
+	if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
+	    /* button is disabled */
+	    DrawEdge32 (hdc, &rc, EDGE_RAISED,
+			BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
+	    ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
+			    rc.left+2, rc.top+2, ILD_NORMAL);
+	    return;
+	}
+
+	/* TBSTYLE_BUTTON */
+	if (btnPtr->fsState & TBSTATE_PRESSED) {
+	    DrawEdge32 (hdc, &rc, EDGE_SUNKEN,
+			BF_RECT | BF_MIDDLE | BF_ADJUST);
+	    ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
+			    rc.left+3, rc.top+3, ILD_NORMAL);
+	    return;
+	}
+	else {
+	    DrawEdge32 (hdc, &rc, EDGE_RAISED,
+			BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
+	    ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
+			    rc.left+2, rc.top+2, ILD_NORMAL);
+	}
+    }
+}
+
+
+
+static void
+TOOLBAR_Refresh (WND *wndPtr, HDC32 hdc)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    TBUTTON_INFO *btnPtr;
+    INT32 i;
+
+
+    /* draw buttons */
+
+    btnPtr = infoPtr->buttons;
+    for (i = 0; i < infoPtr->nNumButtons; i++) {
+	TOOLBAR_DrawButton (wndPtr, btnPtr, hdc);
+	btnPtr++;
+    }
+}
+
+
+static void
+TOOLBAR_CalcToolbar (WND *wndPtr)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    TBUTTON_INFO *btnPtr;
+    RECT32 rect;
+    INT32 i;
+
+    rect.left   = infoPtr->nIndent;
+    rect.top    = infoPtr->nButtonTop;
+//    rect.right  = rect.left + infoPtr->nButtonWidth;
+    rect.bottom = rect.top + infoPtr->nButtonHeight;
+
+    btnPtr = infoPtr->buttons;
+    for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
+	if (btnPtr->fsState & TBSTATE_HIDDEN) {
+	    btnPtr->rect.left = 0;
+	    btnPtr->rect.right = 0;
+	    btnPtr->rect.top = 0;
+	    btnPtr->rect.bottom = 0;
+	    continue;
+	}
+
+	btnPtr->rect = rect;
+	if (btnPtr->fsStyle & TBSTYLE_SEP)
+	    btnPtr->rect.right = btnPtr->rect.left + SEPARATOR_WIDTH;
+	else
+	    btnPtr->rect.right = btnPtr->rect.left + infoPtr->nButtonWidth;
+	rect.left = btnPtr->rect.right;
+    }
+}
+
+
+static INT32
+TOOLBAR_InternalHitTest (WND *wndPtr, LPPOINT32 lpPt)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    TBUTTON_INFO *btnPtr;
+    INT32 i;
+    
+
+    btnPtr = infoPtr->buttons;
+    for (i = 0; i < infoPtr->nNumButtons; i++) {
+	if (btnPtr->fsStyle & TBSTYLE_SEP) {
+	    if (PtInRect32 (&btnPtr->rect, *lpPt)) {
+//		TRACE (toolbar, " ON SEPARATOR %d!\n", i);
+		return -i;
+	    }
+	}
+	else {
+	    if (PtInRect32 (&btnPtr->rect, *lpPt)) {
+//		TRACE (toolbar, " ON BUTTON %d!\n", i);
+		return i;
+	    }
+
+	}
+
+	btnPtr++;
+    }
+
+//    TRACE (toolbar, " NOWHERE!\n");
+    return -1;
+}
+
+
+static INT32
+TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT32 idCommand)
+{
+    TBUTTON_INFO *btnPtr;
+    INT32 i;
+
+    btnPtr = infoPtr->buttons;
+    for (i = 0; i < infoPtr->nNumButtons; i++) {
+	if (btnPtr->idCommand == idCommand)
+	    return i;
+	btnPtr++;
+    }
+    return -1;
+}
+
+
+static LRESULT
+TOOLBAR_AddBitmap (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
+
+    if ((!lpAddBmp) || ((INT32)wParam <= 0))
+	return -1;
+
+    TRACE (toolbar, "adding %d bitmaps!\n", wParam);
+
+    if (!(infoPtr->himlDef)) {
+	/* create new default image list */
+	TRACE (toolbar, "creating default image list!\n");
+	infoPtr->himlDef =
+	    ImageList_Create (infoPtr->nBitmapWidth, 
+			      infoPtr->nBitmapHeight, ILC_COLOR | ILC_MASK,
+			      (INT32)wParam, 2);
+    }
+
+    if (!(infoPtr->himlDis)) {
+	/* create new disabled image list */
+	TRACE (toolbar, "creating disabled image list!\n");
+	infoPtr->himlDis =
+	    ImageList_Create (infoPtr->nBitmapWidth, 
+			      infoPtr->nBitmapHeight, ILC_COLOR | ILC_MASK,
+			      (INT32)wParam, 2);
+    }
+
+
+    /* Add bitmaps to the default image list */
+    if (lpAddBmp->hInst == (HINSTANCE32)0) {
+
+	ImageList_Add (infoPtr->himlDef, (HBITMAP32)lpAddBmp->nID, 0);
+    }
+    else if (lpAddBmp->hInst == HINST_COMMCTRL) {
+	/* add internal bitmaps */
+	FIXME (toolbar, "internal bitmaps not supported!\n");
+
+	/* Hack to "add" some reserved images within the image list 
+	   to get the right image indices */
+	ImageList_SetImageCount (infoPtr->himlDef,
+	    ImageList_GetImageCount (infoPtr->himlDef) + (INT32)wParam);
+    }
+    else {
+	HBITMAP32 hBmp =
+	    LoadBitmap32A (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
+
+	ImageList_Add (infoPtr->himlDef, hBmp, (HBITMAP32)0);
+
+	DeleteObject32 (hBmp); 
+    }
+
+
+    /* Add bitmaps to the disabled image list */
+
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLBAR_AddButtons32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
+    INT32 nOldButtons, nNewButtons, nAddButtons, nCount;
+    HDC32 hdc;
+
+    TRACE (toolbar, "adding %d buttons!\n", wParam);
+
+    nAddButtons = (UINT32)wParam;
+    nOldButtons = infoPtr->nNumButtons;
+    nNewButtons = nOldButtons + nAddButtons;
+
+    if (infoPtr->nNumButtons == 0) {
+	infoPtr->buttons =
+	    HeapAlloc (SystemHeap, HEAP_ZERO_MEMORY,
+		       sizeof (TBUTTON_INFO) * nNewButtons);
+    }
+    else {
+	TBUTTON_INFO *oldButtons = infoPtr->buttons;
+	infoPtr->buttons =
+	    HeapAlloc (SystemHeap, HEAP_ZERO_MEMORY,
+		       sizeof (TBUTTON_INFO) * nNewButtons);
+	memcpy (&infoPtr->buttons[0], &oldButtons[0],
+		nOldButtons * sizeof(TBUTTON_INFO));
+        HeapFree (SystemHeap, 0, oldButtons);
+    }
+
+    infoPtr->nNumButtons = nNewButtons;
+
+    /* insert new button data (bad implementation)*/
+    for (nCount = 0; nCount < nAddButtons; nCount++) {
+	infoPtr->buttons[nOldButtons+nCount].iBitmap   = lpTbb[nCount].iBitmap;
+	infoPtr->buttons[nOldButtons+nCount].idCommand = lpTbb[nCount].idCommand;
+	infoPtr->buttons[nOldButtons+nCount].fsState   = lpTbb[nCount].fsState;
+	infoPtr->buttons[nOldButtons+nCount].fsStyle   = lpTbb[nCount].fsStyle;
+	infoPtr->buttons[nOldButtons+nCount].dwData    = lpTbb[nCount].dwData;
+	infoPtr->buttons[nOldButtons+nCount].iString   = lpTbb[nCount].iString;
+    }
+
+    TOOLBAR_CalcToolbar (wndPtr);
+
+    hdc = GetDC32 (wndPtr->hwndSelf);
+    TOOLBAR_Refresh (wndPtr, hdc);
+    ReleaseDC32 (wndPtr->hwndSelf, hdc);
+
+    return TRUE;
+}
+
+
+// << TOOLBAR_AddString32A >>
+// << TOOLBAR_AutoSize >>
+
+
+static LRESULT
+TOOLBAR_ButtonCount (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+
+    return infoPtr->nNumButtons;
+}
+
+
+static LRESULT
+TOOLBAR_ButtonStructSize (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+
+    infoPtr->dwStructSize = (DWORD)wParam;
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLBAR_ChangeBitmap (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    TBUTTON_INFO *btnPtr;
+    HDC32 hdc;
+    INT32 nIndex;
+
+    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT32)wParam);
+    if (nIndex == -1)
+	return FALSE;
+
+    btnPtr = &infoPtr->buttons[nIndex];
+    btnPtr->iBitmap = LOWORD(lParam);
+
+    hdc = GetDC32 (wndPtr->hwndSelf);
+    TOOLBAR_DrawButton (wndPtr, btnPtr, hdc);
+    ReleaseDC32 (wndPtr->hwndSelf, hdc);
+
+    return TRUE;
+}
+
+
+/*
+static LRESULT
+TOOLBAR_CheckButton (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    TBUTTON_INFO *btnPtr;
+    HDC32 hdc;
+    INT32 nIndex;
+
+    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT32)wParam);
+    if (nIndex == -1)
+	return FALSE;
+
+    btnPtr = &infoPtr->buttons[nIndex];
+    if (LOWORD(lParam) == FALSE)
+	btnPtr->fsState &= ~TBSTATE_CHECKED;
+    else
+	btnPtr->fsState |= TBSTATE_CHECKED;
+
+    hdc = GetDC32 (wndPtr->hwndSelf);
+    TOOLBAR_DrawButton (wndPtr, btnPtr, hdc);
+    ReleaseDC32 (wndPtr->hwndSelf, hdc);
+
+    return TRUE;
+}
+*/
+
+
+static LRESULT
+TOOLBAR_CommandToIndex (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+
+    return TOOLBAR_GetButtonIndex (infoPtr, (INT32)wParam);
+}
+
+
+// << TOOLBAR_Customize >>
+
+
+static LRESULT
+TOOLBAR_DeleteButton (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    INT32 iIndex = (INT32)wParam;
+
+    if ((iIndex < 0) || (iIndex >= infoPtr->nNumButtons))
+	return FALSE;
+
+    if (infoPtr->nNumButtons == 1) {
+	TRACE (toolbar, " simple delete!\n");
+	HeapFree (SystemHeap, 0, infoPtr->buttons);
+	infoPtr->buttons = NULL;
+	infoPtr->nNumButtons = 0;
+    }
+    else {
+
+        TRACE(header, "complex delete! [iIndex=%d]\n", iIndex);
+
+    }
+
+    TOOLBAR_CalcToolbar (wndPtr);
+
+    InvalidateRect32 (wndPtr->hwndSelf, NULL, TRUE);
+    UpdateWindow32 (wndPtr->hwndSelf);
+
+    return TRUE;
+}
+
+
+static LRESULT
+TOOLBAR_EnableButton (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    TBUTTON_INFO *btnPtr;
+    HDC32 hdc;
+    INT32 nIndex;
+
+    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT32)wParam);
+    if (nIndex == -1)
+	return FALSE;
+
+    btnPtr = &infoPtr->buttons[nIndex];
+    if (LOWORD(lParam) == FALSE)
+	btnPtr->fsState &= ~TBSTATE_ENABLED;
+    else
+	btnPtr->fsState |= TBSTATE_ENABLED;
+
+    hdc = GetDC32 (wndPtr->hwndSelf);
+    TOOLBAR_DrawButton (wndPtr, btnPtr, hdc);
+    ReleaseDC32 (wndPtr->hwndSelf, hdc);
+
+    return TRUE;
+}
+
+
+// << TOOLBAR_GetAnchorHighlight >>
+
+
+static LRESULT
+TOOLBAR_GetBitmap (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    INT32 nIndex;
+
+    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT32)wParam);
+    if (nIndex == -1)
+	return 0;
+
+    return infoPtr->buttons[nIndex].iBitmap;
+}
+
+
+// << TOOLBAR_GetBitmapFlags >>
+// << TOOLBAR_GetButton >>
+// << ... >>
+
+
+static LRESULT
+TOOLBAR_HideButton (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    TBUTTON_INFO *btnPtr;
+    INT32 nIndex;
+
+    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT32)wParam);
+    if (nIndex == -1)
+	return FALSE;
+
+    btnPtr = &infoPtr->buttons[nIndex];
+    if (LOWORD(lParam) == FALSE)
+	btnPtr->fsState &= ~TBSTATE_HIDDEN;
+    else
+	btnPtr->fsState |= TBSTATE_HIDDEN;
+
+    TOOLBAR_CalcToolbar (wndPtr);
+
+    InvalidateRect32 (wndPtr->hwndSelf, NULL, TRUE);
+    UpdateWindow32 (wndPtr->hwndSelf);
+
+    return TRUE;
+}
+
+
+static LRESULT
+TOOLBAR_HitTest (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    return TOOLBAR_InternalHitTest (wndPtr, (LPPOINT32)lParam);
+}
+
+
+static LRESULT
+TOOLBAR_IsButtonChecked (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    INT32 nIndex;
+
+    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT32)wParam);
+    if (nIndex == -1)
+	return FALSE;
+
+    return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
+}
+
+
+static LRESULT
+TOOLBAR_IsButtonEnabled (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    INT32 nIndex;
+
+    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT32)wParam);
+    if (nIndex == -1)
+	return FALSE;
+
+    return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
+}
+
+
+static LRESULT
+TOOLBAR_IsButtonHidden (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    INT32 nIndex;
+
+    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT32)wParam);
+    if (nIndex == -1)
+	return FALSE;
+
+    return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
+}
+
+
+static LRESULT
+TOOLBAR_IsButtonHighlighted (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    INT32 nIndex;
+
+    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT32)wParam);
+    if (nIndex == -1)
+	return FALSE;
+
+    return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
+}
+
+
+static LRESULT
+TOOLBAR_IsButtonIndeterminate (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    INT32 nIndex;
+
+    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT32)wParam);
+    if (nIndex == -1)
+	return FALSE;
+
+    return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
+}
+
+
+static LRESULT
+TOOLBAR_IsButtonPressed (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    INT32 nIndex;
+
+    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT32)wParam);
+    if (nIndex == -1)
+	return FALSE;
+
+    return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
+}
+
+
+// << TOOLBAR_LoadImages >>
+// << TOOLBAR_MapAccelerator >>
+// << TOOLBAR_MarkButton >>
+// << TOOLBAR_MoveButton >>
+
+
+static LRESULT
+TOOLBAR_PressButton (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    TBUTTON_INFO *btnPtr;
+    HDC32 hdc;
+    INT32 nIndex;
+
+    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT32)wParam);
+    if (nIndex == -1)
+	return FALSE;
+
+    btnPtr = &infoPtr->buttons[nIndex];
+    if (LOWORD(lParam) == FALSE)
+	btnPtr->fsState &= ~TBSTATE_PRESSED;
+    else
+	btnPtr->fsState |= TBSTATE_PRESSED;
+
+    hdc = GetDC32 (wndPtr->hwndSelf);
+    TOOLBAR_DrawButton (wndPtr, btnPtr, hdc);
+    ReleaseDC32 (wndPtr->hwndSelf, hdc);
+
+    return TRUE;
+}
+
+
+// << TOOLBAR_ReplaceBitmap >>
+// << TOOLBAR_SaveRestore >>
+// << TOOLBAR_SetAnchorHighlight >>
+
+static LRESULT
+TOOLBAR_SetBitmapSize (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+
+    if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
+	return FALSE;
+
+    infoPtr->nBitmapWidth = (INT32)LOWORD(lParam);
+    infoPtr->nBitmapHeight = (INT32)HIWORD(lParam);
+
+    return TRUE;
+}
+
+
+// << TOOLBAR_SetButtonInfo >>
+
+
+static LRESULT
+TOOLBAR_SetButtonSize (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+
+    if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
+	return FALSE;
+
+    infoPtr->nButtonWidth = (INT32)LOWORD(lParam);
+    infoPtr->nButtonHeight = (INT32)HIWORD(lParam);
+
+    return TRUE;
+}
+
+
+// << TOOLBAR_SetButtonWidth >>
+
+
+static LRESULT
+TOOLBAR_SetCmdId (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    INT32 nIndex = (INT32)wParam;
+
+    if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
+	return FALSE;
+
+    infoPtr->buttons[nIndex].idCommand = (INT32)lParam;
+
+    return TRUE;
+}
+
+
+
+static LRESULT
+TOOLBAR_SetIndent (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    HDC32 hdc;
+
+    infoPtr->nIndent = (INT32)wParam;
+    TOOLBAR_CalcToolbar (wndPtr);
+    hdc = GetDC32 (wndPtr->hwndSelf);
+    TOOLBAR_Refresh (wndPtr, hdc);
+    ReleaseDC32 (wndPtr->hwndSelf, hdc);
+
+    return TRUE;
+}
+
+
+
+static LRESULT
+TOOLBAR_SetState (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    TBUTTON_INFO *btnPtr;
+    HDC32 hdc;
+    INT32 nIndex;
+
+    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT32)wParam);
+    if (nIndex == -1)
+	return FALSE;
+
+    btnPtr = &infoPtr->buttons[nIndex];
+    btnPtr->fsState = LOWORD(lParam);
+
+    hdc = GetDC32 (wndPtr->hwndSelf);
+    TOOLBAR_DrawButton (wndPtr, btnPtr, hdc);
+    ReleaseDC32 (wndPtr->hwndSelf, hdc);
+
+    return TRUE;
+}
+
+
+static LRESULT
+TOOLBAR_SetStyle (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    TBUTTON_INFO *btnPtr;
+    HDC32 hdc;
+    INT32 nIndex;
+
+    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT32)wParam);
+    if (nIndex == -1)
+	return FALSE;
+
+    btnPtr = &infoPtr->buttons[nIndex];
+    btnPtr->fsStyle = LOWORD(lParam);
+
+    hdc = GetDC32 (wndPtr->hwndSelf);
+    TOOLBAR_DrawButton (wndPtr, btnPtr, hdc);
+    ReleaseDC32 (wndPtr->hwndSelf, hdc);
+
+    return TRUE;
+}
+
+
+// << TOOLBAR_SetToolTips >>
+// << TOOLBAR_SetUnicodeFormat >>
+
+
+static LRESULT
+TOOLBAR_Create (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr;
+
+    /* allocate memory for info structure */
+    infoPtr = (TOOLBAR_INFO *)HeapAlloc (SystemHeap, HEAP_ZERO_MEMORY,
+                                   sizeof(TOOLBAR_INFO));
+    wndPtr->wExtra[0] = (DWORD)infoPtr;
+
+    infoPtr->nButtonHeight = 22;
+    infoPtr->nButtonWidth = 24;
+    infoPtr->nButtonTop = 2;
+    infoPtr->nBitmapHeight = 15;
+    infoPtr->nBitmapWidth = 16;
+
+    infoPtr->nHeight = infoPtr->nButtonHeight + 6;
+
+    infoPtr->bCaptured = 0;
+    infoPtr->nButtonDown = -1;
+    infoPtr->nOldHit = -1;
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLBAR_Destroy (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+
+    /* delete button data */
+    if (infoPtr->buttons)
+	HeapFree (SystemHeap, 0, infoPtr->buttons);
+
+    /* destroy default image list */
+    if (infoPtr->himlDef)
+	ImageList_Destroy (infoPtr->himlDef);
+
+    /* destroy disabled image list */
+    if (infoPtr->himlDis)
+	ImageList_Destroy (infoPtr->himlDis);
+
+    /* destroy hot image list */
+    if (infoPtr->himlHot)
+	ImageList_Destroy (infoPtr->himlHot);
+
+    /* free toolbar info data */
+    HeapFree (SystemHeap, 0, infoPtr);
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLBAR_LButtonDblClk (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    TBUTTON_INFO *btnPtr;
+    POINT32 pt;
+    INT32   nHit;
+    HDC32   hdc;
+
+    pt.x = (INT32)LOWORD(lParam);
+    pt.y = (INT32)HIWORD(lParam);
+    nHit = TOOLBAR_InternalHitTest (wndPtr, &pt);
+
+    if (nHit >= 0) {
+	btnPtr = &infoPtr->buttons[nHit];
+	if (!(btnPtr->fsState & TBSTATE_ENABLED))
+	    return 0;
+	SetCapture32 (wndPtr->hwndSelf);
+	infoPtr->bCaptured = TRUE;
+	infoPtr->nButtonDown = nHit;
+
+	btnPtr->fsState |= TBSTATE_PRESSED;
+
+	hdc = GetDC32 (wndPtr->hwndSelf);
+	TOOLBAR_DrawButton (wndPtr, btnPtr, hdc);
+	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+    }
+    else if (wndPtr->dwStyle & CCS_ADJUSTABLE) {
+	/* customize */
+
+	FIXME (toolbar, "customization not implemented!\n");
+    }
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLBAR_LButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    TBUTTON_INFO *btnPtr;
+    POINT32 pt;
+    INT32   nHit;
+    HDC32   hdc;
+
+    pt.x = (INT32)LOWORD(lParam);
+    pt.y = (INT32)HIWORD(lParam);
+    nHit = TOOLBAR_InternalHitTest (wndPtr, &pt);
+
+    if (nHit >= 0) {
+	btnPtr = &infoPtr->buttons[nHit];
+	if (!(btnPtr->fsState & TBSTATE_ENABLED))
+	    return 0;
+
+	SetCapture32 (wndPtr->hwndSelf);
+	infoPtr->bCaptured = TRUE;
+	infoPtr->nButtonDown = nHit;
+	infoPtr->nOldHit = nHit;
+
+	btnPtr->fsState |= TBSTATE_PRESSED;
+
+	hdc = GetDC32 (wndPtr->hwndSelf);
+	TOOLBAR_DrawButton (wndPtr, btnPtr, hdc);
+	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+    }
+    
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLBAR_LButtonUp (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    TBUTTON_INFO *btnPtr;
+    POINT32 pt;
+    INT32   nHit;
+    HDC32   hdc;
+
+    pt.x = (INT32)LOWORD(lParam);
+    pt.y = (INT32)HIWORD(lParam);
+    nHit = TOOLBAR_InternalHitTest (wndPtr, &pt);
+
+    if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) {
+
+	btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
+
+
+
+
+	btnPtr->fsState &= ~TBSTATE_PRESSED;
+	infoPtr->nButtonDown = -1;
+	infoPtr->nOldHit = -1;
+
+	infoPtr->bCaptured = FALSE;
+	ReleaseCapture ();
+
+	hdc = GetDC32 (wndPtr->hwndSelf);
+	TOOLBAR_DrawButton (wndPtr, btnPtr, hdc);
+	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+
+	SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_COMMAND,
+			MAKEWPARAM(btnPtr->idCommand, 0),
+			(LPARAM)wndPtr->hwndSelf);
+    }
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLBAR_MouseMove (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    TBUTTON_INFO *btnPtr;
+    POINT32 pt;
+    INT32   nHit;
+    HDC32   hdc;
+
+    pt.x = (INT32)LOWORD(lParam);
+    pt.y = (INT32)HIWORD(lParam);
+    nHit = TOOLBAR_InternalHitTest (wndPtr, &pt);
+
+    if (infoPtr->bCaptured) {
+	if (infoPtr->nOldHit != nHit) {
+	    btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
+	    if (infoPtr->nOldHit == infoPtr->nButtonDown) {
+		btnPtr->fsState &= ~TBSTATE_PRESSED;
+		hdc = GetDC32 (wndPtr->hwndSelf);
+		TOOLBAR_DrawButton (wndPtr, btnPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
+	    }
+	    else if (nHit == infoPtr->nButtonDown) {
+		btnPtr->fsState |= TBSTATE_PRESSED;
+		hdc = GetDC32 (wndPtr->hwndSelf);
+		TOOLBAR_DrawButton (wndPtr, btnPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
+	    }
+	}
+	infoPtr->nOldHit = nHit;
+    }
+
+    return 0;
+}
+
+
+
+
+
+static LRESULT
+TOOLBAR_NCCalcSize (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    RECT32 tmpRect = {0, 0, 0, 0};
+    LPRECT32 winRect;
+
+//    DefWindowProc32A (wndPtr->hwndSelf, WM_NCCALCSIZE, wParam, lParam);
+
+    winRect = (LPRECT32)lParam;
+
+//    if (wndPtr->dwStyle & WS_BORDER)
+//	InflateRect32 (&tmpRect, 1, 1);
+
+    if (!(wndPtr->dwStyle & CCS_NODIVIDER)) {
+	tmpRect.top -= 2;
+	tmpRect.bottom -= 2;
+    }
+
+    winRect->left   -= tmpRect.left;   
+    winRect->top    -= tmpRect.top;   
+    winRect->right  -= tmpRect.right;   
+    winRect->bottom -= tmpRect.bottom;   
+
+    return DefWindowProc32A (wndPtr->hwndSelf, WM_NCCALCSIZE, wParam, lParam);
+//    return 0;
+}
+
+
+static LRESULT
+TOOLBAR_NCPaint (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    HDC32 hdc;
+    RECT32 rect;
+    HWND32 hwnd = wndPtr->hwndSelf;
+
+    if ( wndPtr->dwStyle & WS_MINIMIZE ||
+	!WIN_IsWindowDrawable( wndPtr, 0 )) return 0; /* Nothing to do */
+
+    DefWindowProc32A (hwnd, WM_NCPAINT, wParam, lParam);
+
+    if (!(hdc = GetDCEx32( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ))) return 0;
+
+    if (ExcludeVisRect( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
+		        wndPtr->rectClient.top-wndPtr->rectWindow.top,
+		        wndPtr->rectClient.right-wndPtr->rectWindow.left,
+		        wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
+	== NULLREGION)
+    {
+	ReleaseDC32( hwnd, hdc );
+	return 0;
+    }
+
+    if (!(wndPtr->flags & WIN_MANAGED)) {
+	if (!(wndPtr->dwStyle & CCS_NODIVIDER)) {
+	    rect.left = wndPtr->rectClient.left;
+	    rect.top = wndPtr->rectClient.top - 2;
+	    rect.right = wndPtr->rectClient.right;
+
+	    SelectObject32 ( hdc, GetSysColorPen32 (COLOR_3DSHADOW));
+	    MoveToEx32 (hdc, rect.left, rect.top, NULL);
+	    LineTo32 (hdc, rect.right, rect.top);
+	    rect.top++;
+	    SelectObject32 ( hdc, GetSysColorPen32 (COLOR_3DHILIGHT));
+	    MoveToEx32 (hdc, rect.left, rect.top, NULL);
+	    LineTo32 (hdc, rect.right, rect.top);
+	}
+
+    }
+
+    ReleaseDC32( hwnd, hdc );
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLBAR_Paint (WND *wndPtr, WPARAM32 wParam)
+{
+    HDC32 hdc;
+    PAINTSTRUCT32 ps;
+
+    hdc = wParam==0 ? BeginPaint32 (wndPtr->hwndSelf, &ps) : (HDC32)wParam;
+    TOOLBAR_Refresh (wndPtr, hdc);
+    if (!wParam)
+	EndPaint32 (wndPtr->hwndSelf, &ps);
+    return 0;
+}
+
+
+static LRESULT
+TOOLBAR_Size (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    RECT32 parent_rect;
+    HWND32 parent;
+    INT32  flags;
+
+    flags = (INT32) wParam;
+
+    /* FIXME for flags =
+     * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED, SIZE_RESTORED
+     */
+
+//    if (flags == SIZE_RESTORED) {
+	/* width and height don't apply */
+	parent = GetParent32 (wndPtr->hwndSelf);
+	GetClientRect32(parent, &parent_rect);
+        infoPtr->nWidth = parent_rect.right - parent_rect.left;
+	MoveWindow32(wndPtr->hwndSelf, parent_rect.left, parent_rect.top, //0, 0,
+		     infoPtr->nWidth, infoPtr->nHeight, TRUE);
+//    }
+    return 0;
+}
+
+
+
+
+
+
+
+LRESULT WINAPI
+ToolbarWindowProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam)
+{
+    WND *wndPtr = WIN_FindWndPtr(hwnd);
+
+    switch (uMsg)
+    {
+	case TB_ADDBITMAP:
+	    return TOOLBAR_AddBitmap (wndPtr, wParam, lParam);
+
+	case TB_ADDBUTTONS32A:
+	    return TOOLBAR_AddButtons32A (wndPtr, wParam, lParam);
+
+//	case TB_ADDSTRING32A:
+//	    return TOOLBAR_AddString32A (wndPtr, wParam, lParam);
+
+//	case TB_AUTOSIZE:
+//	    return TOOLBAR_AutoSize (wndPtr, wParam, lParam);
+
+	case TB_BUTTONCOUNT:
+	    return TOOLBAR_ButtonCount (wndPtr, wParam, lParam);
+
+	case TB_BUTTONSTRUCTSIZE:
+	    return TOOLBAR_ButtonStructSize (wndPtr, wParam, lParam);
+
+	case TB_CHANGEBITMAP:
+	    return TOOLBAR_ChangeBitmap (wndPtr, wParam, lParam);
+
+//	case TB_CHECKBUTTON:
+//	    return TOOLBAR_CheckButton (wndPtr, wParam, lParam);
+
+	case TB_COMMANDTOINDEX:
+	    return TOOLBAR_CommandToIndex (wndPtr, wParam, lParam);
+
+//	case TB_CUSTOMIZE:
+
+	case TB_DELETEBUTTON:
+	    return TOOLBAR_DeleteButton (wndPtr, wParam, lParam);
+
+	case TB_ENABLEBUTTON:
+	    return TOOLBAR_EnableButton (wndPtr, wParam, lParam);
+
+//	case TB_GETANCHORHIGHLIGHT:		/* 4.71 */
+
+	case TB_GETBITMAP:
+	    return TOOLBAR_GetBitmap (wndPtr, wParam, lParam);
+
+//	case TB_GETBITMAPFLAGS:
+//	case TB_GETDISABLEDIMAGELIST:		/* 4.70 */
+//	case TB_GETEXTENDEDSTYLE:		/* 4.71 */
+//	case TB_GETHOTIMAGELIST:		/* 4.70 */
+//	case TB_GETHOTITEM:			/* 4.71 */
+//	case TB_GETIMAGELIST:			/* 4.70 */
+//	case TB_GETINSERTMARK:			/* 4.71 */
+//	case TB_GETINSERTMARKCOLOR:		/* 4.71 */
+//	case TB_GETITEMRECT:
+//	case TB_GETMAXSIZE:			/* 4.71 */
+//	case TB_GETOBJECT:			/* 4.71 */
+//	case TB_GETPADDING:			/* 4.71 */
+//	case TB_GETRECT:			/* 4.70 */
+//	case TB_GETROWS:
+//	case TB_GETSTATE:
+//	case TB_GETSTYLE:			/* 4.70 */
+//	case TB_GETTEXTROWS:			/* 4.70 */
+//	case TB_GETTOOLTIPS:
+//	case TB_GETUNICODEFORMAT:
+
+	case TB_HIDEBUTTON:
+	    return TOOLBAR_HideButton (wndPtr, wParam, lParam);
+
+	case TB_HITTEST:
+	    return TOOLBAR_HitTest (wndPtr, wParam, lParam);
+
+//	case TB_INDETERMINATE:
+//	    return TOOLBAR_Indeterminate (wndPtr, wParam, lParam);
+
+//	case TB_INSERTBUTTON:
+//	    return TOOLBAR_InsertButton (wndPtr, wParam, lParam);
+
+//	case TB_INSERTMARKHITTEST:		/* 4.71 */
+
+	case TB_ISBUTTONCHECKED:
+	    return TOOLBAR_IsButtonChecked (wndPtr, wParam, lParam);
+
+	case TB_ISBUTTONENABLED:
+	    return TOOLBAR_IsButtonEnabled (wndPtr, wParam, lParam);
+
+	case TB_ISBUTTONHIDDEN:
+	    return TOOLBAR_IsButtonHidden (wndPtr, wParam, lParam);
+
+	case TB_ISBUTTONHIGHLIGHTED:
+	    return TOOLBAR_IsButtonHighlighted (wndPtr, wParam, lParam);
+
+	case TB_ISBUTTONINDETERMINATE:
+	    return TOOLBAR_IsButtonIndeterminate (wndPtr, wParam, lParam);
+
+	case TB_ISBUTTONPRESSED:
+	    return TOOLBAR_IsButtonPressed (wndPtr, wParam, lParam);
+
+//	case TB_LOADIMAGES:			/* 4.70 */
+//	case TB_MAPACCELERATOR:			/* 4.71 */
+
+//	case TB_MARKBUTTON:			/* 4.71 */
+//	    return TOOLBAR_MarkButton (wndPtr, wParam, lParam);
+
+//	case TB_MOVEBUTTON:			/* 4.71 */
+
+	case TB_PRESSBUTTON:
+	    return TOOLBAR_PressButton (wndPtr, wParam, lParam);
+
+//	case TB_REPLACEBITMAP:
+//	case TB_SAVERESTORE:
+//	case TB_SETANCHORHIGHLIGHT:		/* 4.71 */
+
+	case TB_SETBITMAPSIZE:
+	    return TOOLBAR_SetBitmapSize (wndPtr, wParam, lParam);
+
+//	case TB_SETBUTTONINFO:			/* 4.71 */
+
+	case TB_SETBUTTONSIZE:
+	    return TOOLBAR_SetButtonSize (wndPtr, wParam, lParam);
+
+//	case TB_SETBUTTONWIDTH:			/* 4.70 */
+
+	case TB_SETCMDID:
+	    return TOOLBAR_SetCmdId (wndPtr, wParam, lParam);
+
+//	case TB_SETCOLORSCHEME:			/* 4.71 */
+//	case TB_SETDISABLEDIMAGELIST:		/* 4.70 */
+//	case TB_SETDRAWTEXTFLAGS:		/* 4.71 */
+//	case TB_SETEXTENDEDSTYLE:		/* 4.71 */
+//	case TB_SETHOTIMAGELIST:		/* 4.70 */
+//	case TB_SETHOTITEM:			/* 4.71 */
+//	case TB_SETIMAGELIST:			/* 4.70 */
+
+	case TB_SETINDENT:
+	    return TOOLBAR_SetIndent (wndPtr, wParam, lParam);
+
+//	case TB_SETINSERTMARK:			/* 4.71 */
+//	case TB_SETINSERTMARKCOLOR:		/* 4.71 */
+//	case TB_SETMAXTEXTROWS:			/* 4.70 */
+//	case TB_SETPADDING:			/* 4.71 */
+//	case TB_SETPARENT:
+//	case TB_SETROWS:
+
+	case TB_SETSTATE:
+	    return TOOLBAR_SetState (wndPtr, wParam, lParam);
+
+	case TB_SETSTYLE:
+	    return TOOLBAR_SetStyle (wndPtr, wParam, lParam);
+
+//	case TB_SETTOOLTIPS:
+//	case TB_SETUNICODEFORMAT:
+
+	case WM_CREATE:
+	    return TOOLBAR_Create (wndPtr, wParam, lParam);
+
+	case WM_DESTROY:
+	    return TOOLBAR_Destroy (wndPtr, wParam, lParam);
+
+	case WM_LBUTTONDBLCLK:
+	    return TOOLBAR_LButtonDblClk (wndPtr, wParam, lParam);
+
+	case WM_LBUTTONDOWN:
+	    return TOOLBAR_LButtonDown (wndPtr, wParam, lParam);
+
+	case WM_LBUTTONUP:
+	    return TOOLBAR_LButtonUp (wndPtr, wParam, lParam);
+
+	case WM_MOUSEMOVE:
+	    return TOOLBAR_MouseMove (wndPtr, wParam, lParam);
+
+//	case WM_NCACTIVATE:
+//	    return TOOLBAR_NCActivate (wndPtr, wParam, lParam);
+
+	case WM_NCCALCSIZE:
+	    return TOOLBAR_NCCalcSize (wndPtr, wParam, lParam);
+
+	case WM_NCPAINT:
+	    return TOOLBAR_NCPaint (wndPtr, wParam, lParam);
+
+//	case WM_NOTIFY:
+
+	case WM_PAINT:
+	    return TOOLBAR_Paint (wndPtr, wParam);
+
+	case WM_SIZE:
+	    return TOOLBAR_Size (wndPtr, wParam, lParam);
+
+//	case WM_SYSCOLORCHANGE:
+
+//	case WM_WININICHANGE:
+
+	case WM_CHARTOITEM:
+	case WM_COMMAND:
+	case WM_DRAWITEM:
+	case WM_MEASUREITEM:
+	case WM_VKEYTOITEM:
+	    return SendMessage32A (GetParent32 (hwnd), uMsg, wParam, lParam);
+
+	default:
+	    if (uMsg >= WM_USER)
+		ERR (toolbar, "unknown msg %04x wp=%08x lp=%08lx\n",
+		     uMsg, wParam, lParam);
+	    return DefWindowProc32A (hwnd, uMsg, wParam, lParam);
+    }
+    return 0;
+}
+
+
+void
+TOOLBAR_Register (void)
+{
+    WNDCLASS32A wndClass;
+
+    if (GlobalFindAtom32A (TOOLBARCLASSNAME32A)) return;
+
+    ZeroMemory (&wndClass, sizeof(WNDCLASS32A));
+    wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
+    wndClass.lpfnWndProc   = (WNDPROC32)ToolbarWindowProc;
+    wndClass.cbClsExtra    = 0;
+    wndClass.cbWndExtra    = sizeof(TOOLBAR_INFO *);
+    wndClass.hCursor       = LoadCursor32A (0, IDC_ARROW32A);
+    wndClass.hbrBackground = (HBRUSH32)(COLOR_3DFACE + 1);
+    wndClass.lpszClassName = TOOLBARCLASSNAME32A;
+ 
+    RegisterClass32A (&wndClass);
+}
+
diff --git a/controls/uitools.c b/controls/uitools.c
index dd58668..0169b00 100644
--- a/controls/uitools.c
+++ b/controls/uitools.c
@@ -5,7 +5,6 @@
  * Copyright 1997 Bertho A. Stultiens
  */
 
-#include <stdio.h>
 #include "windows.h"
 #include "debug.h"
 
diff --git a/controls/updown.c b/controls/updown.c
index 66c2532..d71ba9d 100644
--- a/controls/updown.c
+++ b/controls/updown.c
@@ -25,7 +25,6 @@
  */
 
 #include <stdlib.h>
-#include <stdio.h>
 #include <assert.h>
 #include <string.h>
 #include "windows.h"
diff --git a/debugger/db_disasm.c b/debugger/db_disasm.c
index 05686a7..65fb9e5 100644
--- a/debugger/db_disasm.c
+++ b/debugger/db_disasm.c
@@ -25,7 +25,7 @@
  */
 /*
  * HISTORY
- * $Log:	db_disasm.c,v $
+ *
  * Revision 2.6  92/01/03  20:05:00  dbg
  * 	Add a switch to disassemble 16-bit code.
  * 	Fix spelling of 'lods' opcodes.
diff --git a/debugger/dbg.y b/debugger/dbg.y
index 7a06c40..14fd3b0 100644
--- a/debugger/dbg.y
+++ b/debugger/dbg.y
@@ -10,6 +10,7 @@
 #include <signal.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include "winbase.h"
 #include "class.h"
 #include "module.h"
 #include "options.h"
@@ -565,20 +566,20 @@
 
 void wine_debug( int signal, SIGCONTEXT *regs )
 {
-    DEBUG_SetSigContext( regs );
 #if 0
-    DWORD *stack = (DWORD *)ESP_reg(&DEBUG_context);
+    DWORD *stack = (DWORD *)ESP_sig(regs);
     *(--stack) = 0;
     *(--stack) = 0;
     *(--stack) = EH_NONCONTINUABLE;
     *(--stack) = EXCEPTION_ACCESS_VIOLATION;
-    *(--stack) = EIP_reg(&DEBUG_context);
-    ESP_reg(&DEBUG_context) = (DWORD)stack;
-    EIP_reg(&DEBUG_context) = GetProcAddress32( GetModuleHandle("KERNEL32"),
-                                                "RaiseException" );
-#endif
+    *(--stack) = EIP_sig(regs);
+    ESP_sig(regs) = (DWORD)stack;
+    EIP_sig(regs) = (DWORD)RaiseException;
+#else
+    DEBUG_SetSigContext( regs );
     DEBUG_Main( signal );
     DEBUG_GetSigContext( regs );
+#endif
 }
 
 int yyerror(char * s)
@@ -586,4 +587,3 @@
 	fprintf(stderr,"%s\n", s);
         return 0;
 }
-
diff --git a/debugger/stabs.c b/debugger/stabs.c
index 36fbe2c..3af1ef9 100644
--- a/debugger/stabs.c
+++ b/debugger/stabs.c
@@ -6,6 +6,7 @@
 
 #include <sys/types.h>
 #include <fcntl.h>
+#include <assert.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
 #include <limits.h>
@@ -128,14 +129,85 @@
    * ':'.
    */
   while(*source != '\0' && *source != ':')
-    {
       *dest++ = *source++;
-    }
   *dest++ = '\0';
 }
 
 #define MAX_TD_NESTING	128
 
+static int **typenums;
+static int *nroftypenums=NULL;
+static int nrofnroftypenums=0;
+static int curtypenum = 0;
+
+static
+int
+DEBUG_FileSubNr2StabEnum(int filenr,int subnr) {
+    if (nrofnroftypenums<=filenr) {
+    	nroftypenums = xrealloc(nroftypenums,sizeof(nroftypenums[0])*(filenr+1));
+	memset(nroftypenums+nrofnroftypenums,0,(filenr+1-nrofnroftypenums)*sizeof(nroftypenums[0]));
+	typenums = xrealloc(typenums,sizeof(typenums[0])*(filenr+1));
+	memset(typenums+nrofnroftypenums,0,sizeof(typenums[0])*(filenr+1-nrofnroftypenums));
+	nrofnroftypenums=filenr+1;
+    }
+    if (nroftypenums[filenr]<=subnr) {
+    	typenums[filenr] = xrealloc(typenums[filenr],sizeof(typenums[0][0])*(subnr+1));
+	memset(typenums[filenr]+nroftypenums[filenr],0,sizeof(typenums[0][0])*(subnr+1-nroftypenums[filenr]));
+	nroftypenums[filenr] = subnr+1;
+    }
+    if (!typenums[filenr][subnr])
+    	typenums[filenr][subnr]=++curtypenum;
+
+    if( num_stab_types <= curtypenum ) {
+	num_stab_types = curtypenum + 256;
+	stab_types = (struct datatype **) xrealloc(stab_types, 
+		    num_stab_types * sizeof(struct datatype *)
+	);
+    }
+    //fprintf(stderr,"(%d,%d) is %d\n",filenr,subnr,typenums[filenr][subnr]);
+    return typenums[filenr][subnr];
+}
+
+static
+int
+DEBUG_ReadTypeEnumBackwards(char*x) {
+    int	filenr,subnr;
+
+    if (*x==')') {
+	while (*x!='(')
+	    x--;
+	x++;				/* '(' */
+	filenr=strtol(x,&x,10);		/* <int> */
+	assert(*(x++)==',');		/* ',' */
+	subnr=strtol(x,&x,10);		/* <int> */
+	assert(*(x++)==')');		/* ')' */
+    } else {
+	while ((*x>='0') && (*x<='9'))
+	    x--;
+	filenr = 0;
+	subnr = atol(x+1);
+    }
+    return DEBUG_FileSubNr2StabEnum(filenr,subnr);
+}
+
+static 
+int
+DEBUG_ReadTypeEnum(char **x) {
+    int filenr,subnr;
+
+    if (**x=='(') {
+	(*x)++;					/* '(' */
+	filenr=strtol(*x,x,10);			/* <int> */
+	(*x)++;					/* ',' */
+	subnr=strtol(*x,x,10);			/* <int> */
+	(*x)++;					/* ')' */
+    } else {
+    	filenr = 0;
+	subnr = strtol(*x,x,10);		/* <int> */
+    }
+    return DEBUG_FileSubNr2StabEnum(filenr,subnr);
+}
+
 static
 int
 DEBUG_RegisterTypedef(const char * name, struct datatype ** types, int ndef)
@@ -144,12 +216,10 @@
   struct known_typedef * ktd;
 
   if( ndef == 1 )
-    {
       return TRUE;
-    }
 
-  ktd = (struct known_typedef *) malloc(sizeof(struct known_typedef) 
-					+ ndef * sizeof(struct datatype *));
+  ktd = (struct known_typedef *) xmalloc(sizeof(struct known_typedef) 
+					 + ndef * sizeof(struct datatype *));
   
   hash = stab_hash(name);
 
@@ -171,27 +241,18 @@
   int			 hash;
   struct known_typedef * ktd;
   char		       * ptr;
-  char		       * tc;
-  int			 typenum;
 
   hash = stab_hash(name);
 
   for(ktd = ktd_head[hash]; ktd; ktd = ktd->next)
-    {
-      if(    (ktd->name[0] == name[0])
-	  && (strcmp(name, ktd->name) == 0) )
-	{
+      if ((ktd->name[0] == name[0]) && (strcmp(name, ktd->name) == 0) )
 	  break;
-	}
-    }
 
   /*
    * Didn't find it.  This must be a new one.
    */
   if( ktd == NULL )
-    {
       return FALSE;
-    }
 
   /*
    * Examine the stab to make sure it has the same number of definitions.
@@ -200,9 +261,7 @@
   for(ptr = strchr(stab, '='); ptr; ptr = strchr(ptr+1, '='))
     {
       if( count >= ktd->ndefs )
-	{
 	  return FALSE;
-	}
 
       /*
        * Make sure the types of all of the objects is consistent with
@@ -221,6 +280,7 @@
 	  expect = ARRAY;
 	  break;
 	case '1':
+	case '(':
 	case 'r':
 	  expect = BASIC;
 	  break;
@@ -234,52 +294,24 @@
 	  expect = FUNC;
 	  break;
 	default:
-	  fprintf(stderr, "Unknown type.\n");
+	  fprintf(stderr, "Unknown type (%c).\n",ptr[1]);
           return FALSE;
 	}
       if( expect != DEBUG_GetType(ktd->types[count]) )
-	{
 	  return FALSE;
-	}
       count++;
     }
 
   if( ktd->ndefs != count )
-    {
       return FALSE;
-    }
 
   /*
-   * OK, this one is safe.  Go through, dig out all of the type numbers,
-   * and substitute the appropriate things.
+   * Go through, dig out all of the type numbers, and substitute the
+   * appropriate things.
    */
   count = 0;
   for(ptr = strchr(stab, '='); ptr; ptr = strchr(ptr+1, '='))
-    {
-      /*
-       * Back up until we get to a non-numeric character.  This is the type
-       * number.
-       */
-      tc = ptr - 1;
-      while( *tc >= '0' && *tc <= '9' )
-	{
-	  tc--;
-	}
-      
-      typenum = atol(tc + 1);
-      if( num_stab_types <= typenum )
-	{
-	  num_stab_types = typenum + 32;
-	  stab_types = (struct datatype **) xrealloc(stab_types, 
-						     num_stab_types * sizeof(struct datatype *));
-	  if( stab_types == NULL )
-	    {
-	      return FALSE;
-	    }
-	}
-
-      stab_types[typenum] = ktd->types[count++];
-    }
+      stab_types[DEBUG_ReadTypeEnumBackwards(ptr-1)] = ktd->types[count++];
 
   return TRUE;
 }
@@ -322,7 +354,6 @@
   int		    ntypes = 0;
   int		    offset;
   const char	  * orig_typename;
-  int		    rtn = FALSE;
   int		    size;
   char		  * tc;
   char		  * tc2;
@@ -330,10 +361,8 @@
 
   orig_typename = typename;
 
-  if( DEBUG_HandlePreviousTypedef(typename, ptr) == TRUE )
-    {
+  if( DEBUG_HandlePreviousTypedef(typename, ptr) )
       return TRUE;
-    }
 
   /* 
    * Go from back to front.  First we go through and figure out what
@@ -347,22 +376,7 @@
        * Back up until we get to a non-numeric character.  This is the type
        * number.
        */
-      tc = c - 1;
-      while( *tc >= '0' && *tc <= '9' )
-	{
-	  tc--;
-	}
-      typenum = atol(tc + 1);
-      if( num_stab_types <= typenum )
-	{
-	  num_stab_types = typenum + 32;
-	  stab_types = (struct datatype **) xrealloc(stab_types, 
-						     num_stab_types * sizeof(struct datatype *));
-	  if( stab_types == NULL )
-	    {
-	      goto leave;
-	    }
-	}
+      typenum = DEBUG_ReadTypeEnumBackwards(c-1);
 
       if( ntypes >= MAX_TD_NESTING )
 	{
@@ -388,6 +402,7 @@
 	  stab_types[typenum] = DEBUG_NewDataType(ARRAY, NULL);
 	  curr_types[ntypes++] = stab_types[typenum];
 	  break;
+	case '(':
 	case '1':
 	case 'r':
 	  stab_types[typenum] = DEBUG_NewDataType(BASIC, typename);
@@ -407,7 +422,7 @@
 	  curr_types[ntypes++] = stab_types[typenum];
 	  break;
 	default:
-	  fprintf(stderr, "Unknown type.\n");
+	  fprintf(stderr, "Unknown type (%c).\n",c[1]);
 	}
       typename = NULL;
     }
@@ -426,16 +441,7 @@
       */
      for( c = strrchr(ptr, '='); c != NULL; c = strrchr(ptr, '=') )
        {
-	 /*
-	  * Back up until we get to a non-numeric character.  This is the type
-	  * number.
-	  */
-	 tc = c - 1;
-	 while( *tc >= '0' && *tc <= '9' )
-	   {
-	     tc--;
-	   }
-	 typenum = atol(tc + 1);
+         int typenum = DEBUG_ReadTypeEnumBackwards(c-1);
 	 curr_type = stab_types[typenum];
 	 
 	 switch(c[1])
@@ -443,34 +449,24 @@
 	   case 'x':
 	     tc = c + 3;
 	     while( *tc != ':' )
-	       {
-		 tc ++;
-	       }
+		 tc++;
 	     tc++;
 	     if( *tc == '\0' )
-	       {
 		 *c = '\0';
-	       }
 	     else
-	       {
 		 strcpy(c, tc);
-	       }
-	     
 	     break;
 	   case '*':
 	   case 'f':
 	     tc = c + 2;
-	     datatype = stab_types[strtol(tc, &tc, 10)];
+	     datatype = stab_types[DEBUG_ReadTypeEnum(&tc)];
 	     DEBUG_SetPointerType(curr_type, datatype);
 	     if( *tc == '\0' )
-	       {
 		 *c = '\0';
-	       }
 	     else
-	       {
 		 strcpy(c, tc);
-	       }
 	     break;
+	   case '(':
 	   case '1':
 	   case 'r':
 	     /*
@@ -479,25 +475,27 @@
 	     *c = '\0';
 	     break;
 	   case 'a':
-	     tc  = c + 5;
-	     arrmin = strtol(tc, &tc, 10);
-	     tc++;
-	     arrmax = strtol(tc, &tc, 10);
-	     tc++;
-	     datatype = stab_types[strtol(tc, &tc, 10)];
+	     /* ar<typeinfo_nodef>;<int>;<int>;<typeinfo>,<int>,<int>;; */
+
+	     tc  = c + 3;
+	     assert(c[2]=='r');
+	     DEBUG_ReadTypeEnum(&tc);
+	     assert(*(tc++)==';'); 			/* ';' */
+	     arrmin = strtol(tc, &tc, 10); 		/* <int> */
+	     assert(*(tc++)==';'); 			/* ';' */
+	     arrmax = strtol(tc, &tc, 10);		/* <int> */
+	     assert(*(tc++)==';'); 			/* ';' */
+	     datatype = stab_types[DEBUG_ReadTypeEnum(&tc)]; /* <typeinfo> */
 	     if( *tc == '\0' )
-	       {
 		 *c = '\0';
-	       }
 	     else
-	       {
 		 strcpy(c, tc);
-	       }
-	     
 	     DEBUG_SetArrayParams(curr_type, arrmin, arrmax, datatype);
 	     break;
 	   case 's':
-	   case 'u':
+	   case 'u': {
+	     int failure = 0;
+
 	     tc = c + 2;
 	     if( DEBUG_SetStructSize(curr_type, strtol(tc, &tc, 10)) == FALSE )
 	       {
@@ -506,20 +504,14 @@
 		  * so just skip forward to the end of the definition.
 		  */
 		 while( tc[0] != ';' && tc[1] != ';' )
-		   {
 		     tc++;
-		   }
 		 
 		 tc += 2;
 		 
 		 if( *tc == '\0' )
-		   {
 		     *c = '\0';
-		   }
 		 else
-		   {
 		     strcpy(c, tc + 1);
-		   }
 		 continue;
 	       }
 
@@ -528,30 +520,44 @@
 	      */
 	     while(*tc != ';')
 	       {
+	         char *ti;
 		 tc2 = element_name;
 		 while(*tc != ':')
-		   {
 		     *tc2++ = *tc++;
-		   }
 		 tc++;
 		 *tc2++ = '\0';
-		 datatype = stab_types[strtol(tc, &tc, 10)];
+		 ti=tc;
+		 datatype = stab_types[DEBUG_ReadTypeEnum(&tc)];
+		 *tc='\0';
 		 tc++;
 		 offset  = strtol(tc, &tc, 10);
 		 tc++;
 		 size  = strtol(tc, &tc, 10);
 		 tc++;
-		 DEBUG_AddStructElement(curr_type, element_name, datatype, offset, size);
+		 if (datatype)
+		    DEBUG_AddStructElement(curr_type, element_name, datatype, offset, size);
+		 else {
+		    failure = 1;
+		    /* ... but proceed parsing to the end of the stab */
+		 }
 	       }
+
+	     if (failure) {
+	        /* if we had a undeclared value this one is undeclared too.
+		 * remove it from the stab_types. 
+		 * I just set it to NULL to detect bugs in my thoughtprocess.
+		 * FIXME: leaks the memory for the structure elements.
+		 * FIXME: such structures should have been optimized away
+		 *        by ld.
+		 */
+	     	stab_types[typenum] = NULL;
+	     }
 	     if( *tc == '\0' )
-	       {
 		 *c = '\0';
-	       }
 	     else
-	       {
 		 strcpy(c, tc + 1);
-	       }
 	     break;
+	   }
 	   case 'e':
 	     tc = c + 2;
 	     /*
@@ -561,9 +567,7 @@
 	       {
 		 tc2 = element_name;
 		 while(*tc != ':')
-		   {
 		     *tc2++ = *tc++;
-		   }
 		 tc++;
 		 *tc2++ = '\0';
 		 offset  = strtol(tc, &tc, 10);
@@ -571,25 +575,17 @@
 		 DEBUG_AddStructElement(curr_type, element_name, NULL, offset, 0);
 	       }
 	     if( *tc == '\0' )
-	       {
 		 *c = '\0';
-	       }
 	     else
-	       {
 		 strcpy(c, tc + 1);
-	       }
 	     break;
 	   default:
-	     fprintf(stderr, "Unknown type.\n");
+	     fprintf(stderr, "Unknown type (%c).\n",c[1]);
 	     break;
 	   }
        }
      
-     rtn = TRUE;
-     
-leave:
-     
-     return rtn;
+     return TRUE;
 
 }
 
@@ -597,7 +593,6 @@
 DEBUG_ParseStabType(const char * stab)
 {
   char * c;
-  int    typenum;
 
   /*
    * Look through the stab definition, and figure out what datatype
@@ -606,9 +601,7 @@
    */
   c = strchr(stab, ':');
   if( c == NULL )
-    {
       return NULL;
-    }
 
   c++;
   /*
@@ -616,15 +609,11 @@
    * of symbol.  Skip it.
    */
   c++;
-
-  typenum = atol(c);
-
-  if( typenum < num_stab_types && stab_types[typenum] != NULL )
-    {
-      return stab_types[typenum];
-    }
-
-  return NULL;
+  /* 
+   * The next is either an integer or a (integer,integer).
+   * The DEBUG_ReadTypeEnum takes care that stab_types is large enough.
+   */
+  return stab_types[DEBUG_ReadTypeEnum(&c)];
 }
 
 static 
@@ -664,10 +653,6 @@
    */
   stabbufflen = 65536;
   stabbuff = (char *) xmalloc(stabbufflen);
-  if( stabbuff == NULL )
-    {
-      goto leave;
-    }
 
   strtabinc = 0;
   stabbuff[0] = '\0';
@@ -686,10 +671,6 @@
 	    {
 	      stabbufflen += 65536;
 	      stabbuff = (char *) xrealloc(stabbuff, stabbufflen);
-	      if( stabbuff == NULL )
-		{
-		  goto leave;
-		}
 	    }
 	  strncat(stabbuff, ptr, len - 1);
 	  continue;
@@ -886,7 +867,11 @@
 	       * The datatypes that we would need to use are reset when
 	       * we start a new file.
 	       */
-	      memset(stab_types, 0, num_stab_types * sizeof(stab_types));
+	      memset(stab_types, 0, num_stab_types * sizeof(stab_types[0]));
+	      /*
+	      for (i=0;i<nrofnroftypenums;i++)
+		memset(typenums[i],0,sizeof(typenums[i][0])*nroftypenums[i]);
+	       */
 	    }
 	  else
 	    {
@@ -946,8 +931,6 @@
 #endif
     }
 
-leave:
-
   if( stab_types != NULL )
     {
       free(stab_types);
@@ -1025,9 +1008,7 @@
        */
       if(    (DEBUG_GetSymbolValue(symname, -1, &new_addr, FALSE ) == TRUE)
 	  && (new_addr.off == (load_offset + symp->st_value)) )
-	{
 	  continue;
-	}
 
       new_addr.seg = 0;
       new_addr.type = NULL;
@@ -1035,22 +1016,16 @@
       flags = SYM_WINE | (ELF32_ST_BIND(symp->st_info) == STT_FUNC 
 			  ? SYM_FUNC : SYM_DATA);
       if( ELF32_ST_BIND(symp->st_info) == STB_GLOBAL )
-	{
 	  curr_sym = DEBUG_AddSymbol( symname, &new_addr, NULL, flags );
-	}
       else
-	{
 	  curr_sym = DEBUG_AddSymbol( symname, &new_addr, curfile, flags );
-	}
 
       /*
        * Record the size of the symbol.  This can come in handy in
        * some cases.  Not really used yet, however.
        */
       if(  symp->st_size != 0 )
-	{
 	  DEBUG_SetSymbolSize(curr_sym, symp->st_size);
-	}
     }
 
   return TRUE;
@@ -1078,9 +1053,7 @@
    * Make sure we can stat and open this file.
    */
   if( filename == NULL )
-    {
       goto leave;
-    }
 
   status = stat(filename, &statbuf);
   if( status == -1 )
@@ -1116,9 +1089,7 @@
    */
   fd = open(filename, O_RDONLY);
   if( fd == -1 )
-    {
       goto leave;
-    }
 
 
   /*
@@ -1127,9 +1098,7 @@
   addr = mmap(0, statbuf.st_size, PROT_READ, 
 	      MAP_PRIVATE, fd, 0);
   if( addr == (char *) 0xffffffff )
-    {
       goto leave;
-    }
 
   /*
    * Give a nice status message here...
@@ -1145,13 +1114,9 @@
   ehptr = (Elf32_Ehdr *) addr;
 
   if( load_offset == 0 )
-    {
       DEBUG_RegisterELFDebugInfo(ehptr->e_entry, statbuf.st_size, filename);
-    }
   else
-    {
       DEBUG_RegisterELFDebugInfo(load_offset, statbuf.st_size, filename);
-    }
 
   spnt = (Elf32_Shdr *) (addr + ehptr->e_shoff);
   nsect = ehptr->e_shnum;
@@ -1162,20 +1127,14 @@
   for(i=0; i < nsect; i++)
     {
       if( strcmp(shstrtab + spnt[i].sh_name, ".stab") == 0 )
-	{
 	  stabsect = i;
-	}
 
       if( strcmp(shstrtab + spnt[i].sh_name, ".stabstr") == 0 )
-	{
 	  stabstrsect = i;
-	}
     }
 
   if( stabsect == -1 || stabstrsect == -1 )
-    {
       goto leave;
-    }
 
   /*
    * OK, now just parse all of the stabs.
@@ -1187,38 +1146,28 @@
 			 spnt[stabstrsect].sh_size);
 
   if( rtn != TRUE )
-    {
       goto leave;
-    }
 
   for(i=0; i < nsect; i++)
     {
       if(    (strcmp(shstrtab + spnt[i].sh_name, ".symtab") == 0)
 	  && (spnt[i].sh_type == SHT_SYMTAB) )
-	{
 	  DEBUG_ProcessElfSymtab(addr, load_offset, 
 				 spnt + i, spnt + spnt[i].sh_link);
-	}
 
       if(    (strcmp(shstrtab + spnt[i].sh_name, ".dynsym") == 0)
 	  && (spnt[i].sh_type == SHT_DYNSYM) )
-	{
 	  DEBUG_ProcessElfSymtab(addr, load_offset, 
 				 spnt + i, spnt + spnt[i].sh_link);
-	}
     }
 
 leave:
 
   if( addr != (char *) 0xffffffff )
-    {
       munmap(addr, statbuf.st_size);
-    }
 
   if( fd != -1 )
-    {
       close(fd);
-    }
 
   return (rtn);
 
@@ -1241,9 +1190,7 @@
    * Make sure we can stat and open this file.
    */
   if( exe_name == NULL )
-    {
       goto leave;
-    }
 
   DEBUG_ProcessElfObject(exe_name, 0);
 
@@ -1254,27 +1201,19 @@
    */
   dynpnt = _DYNAMIC;
   if( dynpnt == NULL )
-    {
       goto leave;
-    }
 
   /*
    * Now walk the dynamic section (of the executable, looking for a DT_DEBUG
    * entry.
    */
   for(; dynpnt->d_tag != DT_NULL; dynpnt++)
-    {
       if( dynpnt->d_tag == DT_DEBUG )
-	{
 	  break;
-	}
-    }
 
   if(    (dynpnt->d_tag != DT_DEBUG)
       || (dynpnt->d_un.d_ptr == 0) )
-    {
       goto leave;
-    }
 
   /*
    * OK, now dig into the actual tables themselves.
@@ -1297,14 +1236,10 @@
        */
       ehdr = (Elf32_Ehdr *) lpnt->l_addr;
       if( (lpnt->l_addr == 0) || (ehdr->e_type != ET_DYN) )
-	{
 	  continue;
-	}
 
       if( lpnt->l_name != NULL )
-	{
 	  DEBUG_ProcessElfObject(lpnt->l_name, lpnt->l_addr);
-	}
     }
 
   rtn = TRUE;
@@ -1340,24 +1275,18 @@
    * Make sure we can stat and open this file.
    */
   if( exe_name == NULL )
-    {
       goto leave;
-    }
 
   status = stat(exe_name, &statbuf);
   if( status == -1 )
-    {
       goto leave;
-    }
 
   /*
    * Now open the file, so that we can mmap() it.
    */
   fd = open(exe_name, O_RDONLY);
   if( fd == -1 )
-    {
       goto leave;
-    }
 
 
   /*
@@ -1366,9 +1295,7 @@
   addr = mmap(0, statbuf.st_size, PROT_READ, 
 	      MAP_PRIVATE, fd, 0);
   if( addr == (char *) 0xffffffff )
-    {
       goto leave;
-    }
 
   ahdr = (struct exec *) addr;
 
@@ -1390,14 +1317,10 @@
 leave:
 
   if( addr != (char *) 0xffffffff )
-    {
       munmap(addr, statbuf.st_size);
-    }
 
   if( fd != -1 )
-    {
       close(fd);
-    }
 
   return (rtn);
 
diff --git a/documentation/ttfserver b/documentation/ttfserver
new file mode 100644
index 0000000..8c30199
--- /dev/null
+++ b/documentation/ttfserver
@@ -0,0 +1,50 @@
+1. Get freetype-1.0.full.tar.gz 
+2. Read docus, unpack, configure and install
+3. Test the library, e.g. "ftview 20 /dosc/win95/fonts/times "
+4. Get xfsft-beta1e.linux-i586
+5. Install it and start it when booting, e.g. in an rc-script. 
+	The manpage for xfs applies.
+6. Follow the hints given by williamc@dai.ed.ac.uk
+==========
+I got xfsft from http://www.dcs.ed.ac.uk/home/jec/progindex.html.
+I have it running all the time.  Here is /usr/X11R6/lib/X11/fs/config:
+clone-self = on
+use-syslog = off
+catalogue = /c/windows/fonts
+error-file = /usr/X11R6/lib/X11/fs/fs-errors
+default-point-size = 120
+default-resolutions = 75,75,100,100
+Obviously /c/windows/fonts is where my Windows fonts on my
+Win95 C: drive live; could be e.g. /mnt/dosC/windows/system
+for Win31.
+In /c/windows/fonts/fonts.scale I have
+14
+arial.ttf -monotype-arial-medium-r-normal--0-0-0-0-p-0-iso8859-1
+arialbd.ttf -monotype-arial-bold-r-normal--0-0-0-0-p-0-iso8859-1
+arialbi.ttf -monotype-arial-bold-o-normal--0-0-0-0-p-0-iso8859-1
+ariali.ttf -monotype-arial-medium-o-normal--0-0-0-0-p-0-iso8859-1
+cour.ttf -monotype-courier-medium-r-normal--0-0-0-0-p-0-iso8859-1
+courbd.ttf -monotype-courier-bold-r-normal--0-0-0-0-p-0-iso8859-1
+courbi.ttf -monotype-courier-bold-o-normal--0-0-0-0-p-0-iso8859-1
+couri.ttf -monotype-courier-medium-o-normal--0-0-0-0-p-0-iso8859-1
+times.ttf -monotype-times-medium-r-normal--0-0-0-0-p-0-iso8859-1
+timesbd.ttf -monotype-times-bold-r-normal--0-0-0-0-p-0-iso8859-1
+timesbi.ttf -monotype-times-bold-i-normal--0-0-0-0-p-0-iso8859-1
+timesi.ttf -monotype-times-medium-i-normal--0-0-0-0-p-0-iso8859-1
+symbol.ttf -monotype-symbol-medium-r-normal--0-0-0-0-p-0-microsoft-symbol
+wingding.ttf -microsoft-wingdings-medium-r-normal--0-0-0-0-p-0-microsoft-symbol
+                                                             
+In /c/windows/fonts/fonts.dir I have exactly the same.
+
+In /usr/X11R6/lib/X11/XF86Config I have
+FontPath "tcp/localhost:7100"
+in front of the other FontPath lines.
+That's it!  As an interesting by-product of course, all those web
+pages which specify Arial come up in Arial in Netscape ...
+=======
+7. Shut down X and restart ( and debug errors you did while setting
+   up everything.
+
+8. Test with e.g "xlsfont |grep arial"
+
+Hope this helps
\ No newline at end of file
diff --git a/files/directory.c b/files/directory.c
index 1c98caa..aa975a4 100644
--- a/files/directory.c
+++ b/files/directory.c
@@ -465,9 +465,11 @@
 
     if (pdb->flags & PDB32_WIN16_PROC) {
 	if (!GetCurrentTask()) return FALSE;
-	GetModuleFileName16( GetCurrentTask(), buffer, sizeof(buffer) );
+	if (!GetModuleFileName16( GetCurrentTask(), buffer, sizeof(buffer) ))
+		buffer[0]='\0';
     } else {
-	GetModuleFileName32A( 0, buffer, sizeof(buffer) );
+	if (!GetModuleFileName32A( 0, buffer, sizeof(buffer) ))
+		buffer[0]='\0';
     }
     if (!(p = strrchr( buffer, '\\' ))) return FALSE;
     if (sizeof(buffer) - (++p - buffer) <= strlen(name)) return FALSE;
@@ -568,7 +570,31 @@
 
 
 /***********************************************************************
- *           SearchPath32A   (KERNEL32.447)
+ * SearchPath32A [KERNEL32.447]
+ *
+ * Searches for a specified file in the search path.
+ *
+ * PARAMS
+ *    path	[I] Path to search
+ *    name	[I] Filename to search for.
+ *    ext	[I] File extension to append to file name. The first
+ *		    character must be a period. This parameter is
+ *                  specified only if the filename given does not
+ *                  contain an extension.
+ *    buflen	[I] size of buffer, in characters
+ *    buffer	[O] buffer for found filename
+ *    lastpart  [O] address of pointer to last used character in
+ *                  buffer (the final '\')
+ *
+ * RETURNS
+ *    Success: length of string copied into buffer, not including
+ *             terminating null character. If the filename found is
+ *             longer than the length of the buffer, the length of the
+ *             filename is returned.
+ *    Failure: Zero
+ * 
+ * NOTES
+ *    Should call SetLastError(but currently doesn't).
  */
 DWORD WINAPI SearchPath32A( LPCSTR path, LPCSTR name, LPCSTR ext, DWORD buflen,
                             LPSTR buffer, LPSTR *lastpart )
@@ -587,6 +613,7 @@
         for (p = buffer; *p; p++) if (*p == '/') *p = '\\';
         if (lastpart) *lastpart = strrchr( buffer, '\\' ) + 1;
     }
+    TRACE(dosfs, "Returning %d\n", (*res ? strlen(res) + 2 : 3));
     return *res ? strlen(res) + 2 : 3;
 }
 
diff --git a/files/dos_fs.c b/files/dos_fs.c
index 39fba17..4d9586f 100644
--- a/files/dos_fs.c
+++ b/files/dos_fs.c
@@ -13,7 +13,6 @@
 #include <fcntl.h>
 #include <string.h>
 #include <stdlib.h>
-#include <stdio.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <time.h>
diff --git a/files/file.c b/files/file.c
index d94b7ff..983353e 100644
--- a/files/file.c
+++ b/files/file.c
@@ -9,7 +9,6 @@
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/errno.h>
@@ -1004,7 +1003,15 @@
     }
 
     if ((result = lseek( file->unix_handle, distance, origin )) == -1)
+      {
+	/* care for this pathological case:
+	   SetFilePointer(00000006,ffffffff,00000000,00000002)
+	   ret=0062ab4a fs=01c7 */
+	if ((distance != -1))
         FILE_SetDosError();
+	else
+	  result = 0;
+      }
     FILE_ReleaseFile( file );
     return (DWORD)result;
 }
@@ -1850,3 +1857,53 @@
   return TRUE;
 }
 
+/**************************************************************************
+ * GetFileAttributesEx32A [KERNEL32.874]
+ */
+BOOL32 WINAPI GetFileAttributesEx32A(
+	LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
+	LPVOID lpFileInformation)
+{
+    DOS_FULL_NAME full_name;
+    BY_HANDLE_FILE_INFORMATION info;
+    
+    if (lpFileName == NULL) return FALSE;
+    if (lpFileInformation == NULL) return FALSE;
+
+    if (fInfoLevelId == GetFileExInfoStandard) {
+	LPWIN32_FILE_ATTRIBUTE_DATA lpFad = 
+	    (LPWIN32_FILE_ATTRIBUTE_DATA) lpFileInformation;
+	if (!DOSFS_GetFullName( lpFileName, TRUE, &full_name )) return FALSE;
+	if (!FILE_Stat( full_name.long_name, &info )) return FALSE;
+
+	lpFad->dwFileAttributes = info.dwFileAttributes;
+	lpFad->ftCreationTime   = info.ftCreationTime;
+	lpFad->ftLastAccessTime = info.ftLastAccessTime;
+	lpFad->ftLastWriteTime  = info.ftLastWriteTime;
+	lpFad->nFileSizeHigh    = info.nFileSizeHigh;
+	lpFad->nFileSizeLow     = info.nFileSizeLow;
+    }
+    else {
+	FIXME (file, "invalid info level %d!\n", fInfoLevelId);
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/**************************************************************************
+ * GetFileAttributesEx32W [KERNEL32.875]
+ */
+BOOL32 WINAPI GetFileAttributesEx32W(
+	LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
+	LPVOID lpFileInformation)
+{
+    LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFileName );
+    BOOL32 res = 
+	GetFileAttributesEx32A( nameA, fInfoLevelId, lpFileInformation);
+    HeapFree( GetProcessHeap(), 0, nameA );
+    return res;
+}
+
+
diff --git a/files/profile.c b/files/profile.c
index e1c3544..f53800f 100644
--- a/files/profile.c
+++ b/files/profile.c
@@ -6,7 +6,6 @@
  */
 
 #include <ctype.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -459,10 +458,12 @@
 /***********************************************************************
  *           PROFILE_GetSection
  *
- * Enumerate all the keys of a section.
+ * Returns all keys of a section.
+ * If return_values is TRUE, also include the corrseponding values.
  */
 static INT32 PROFILE_GetSection( PROFILESECTION *section, LPCSTR section_name,
-                                 LPSTR buffer, INT32 len, BOOL32 handle_env )
+                                 LPSTR buffer, INT32 len, BOOL32 handle_env,
+				 BOOL32 return_values )
 {
     PROFILEKEY *key;
     while (section)
@@ -477,6 +478,13 @@
                 PROFILE_CopyEntry( buffer, key->name, len - 1, handle_env );
                 len -= strlen(buffer) + 1;
                 buffer += strlen(buffer) + 1;
+		if (return_values && key->value) {
+			buffer[-1] = '=';
+			PROFILE_CopyEntry ( buffer,
+				key->value, len - 1, handle_env );
+			len -= strlen(buffer) + 1;
+			buffer += strlen(buffer) + 1;
+                }
             }
             *buffer = '\0';
             if (len < 1)
@@ -518,7 +526,8 @@
                          section, key_name, def_val, buffer );
         return strlen( buffer );
     }
-    return PROFILE_GetSection(CurProfile.section, section, buffer, len, FALSE);
+    return PROFILE_GetSection(CurProfile.section, section, buffer, len,
+				FALSE, FALSE);
 }
 
 
@@ -588,7 +597,7 @@
                          section, key_name, def, buffer );
         return strlen( buffer );
     }
-    return PROFILE_GetSection( WineProfile, section, buffer, len, TRUE );
+    return PROFILE_GetSection( WineProfile, section, buffer, len, TRUE, FALSE );
 }
 
 
@@ -988,7 +997,9 @@
                                           INT32 len, LPCSTR filename )
 {
     if (PROFILE_Open( filename ))
-        return PROFILE_GetString( section, NULL, NULL, buffer, len );
+        return PROFILE_GetSection(CurProfile.section, section, buffer, len,
+                                FALSE, TRUE);
+
     return 0;
 }
 
@@ -1052,6 +1063,16 @@
     return FALSE;
 }
 
+/***********************************************************************
+ *           GetPrivateProfileSectionNames16   (KERNEL.143)
+ */
+WORD WINAPI GetPrivateProfileSectionNames16( LPSTR buffer, WORD size,
+                                             LPCSTR filename )
+{
+    FIXME(profile, "(%p,%d,%s):stub\n", buffer, size, filename);
+    buffer[0] = buffer[1] = '\0';
+    return 0;
+}
 
 /***********************************************************************
  *           WriteOutProfiles   (KERNEL.315)
diff --git a/graphics/ddraw.c b/graphics/ddraw.c
index 66df804..bd37998 100644
--- a/graphics/ddraw.c
+++ b/graphics/ddraw.c
@@ -48,7 +48,6 @@
  */
 
 #include "config.h"
-#include <stdio.h>
 #include <unistd.h>
 #include <assert.h>
 #include "ts_xlib.h"
diff --git a/graphics/driver.c b/graphics/driver.c
index 7c09b2b..a22cd6d 100644
--- a/graphics/driver.c
+++ b/graphics/driver.c
@@ -4,7 +4,6 @@
  * Copyright 1996 Alexandre Julliard
  */
 
-#include <stdio.h>
 #include "gdi.h"
 #include "heap.h"
 #include "debug.h"
diff --git a/graphics/win16drv/objects.c b/graphics/win16drv/objects.c
index 709bd80..44426aa 100644
--- a/graphics/win16drv/objects.c
+++ b/graphics/win16drv/objects.c
@@ -42,7 +42,7 @@
         ret = WIN16DRV_BRUSH_SelectObject( dc, handle, (BRUSHOBJ *)ptr );	  
         break;
     case BITMAP_MAGIC:
-        fprintf(stderr, "WIN16DRV_SelectObject for BITMAP not implemented\n");
+        FIXME(gdi, "WIN16DRV_SelectObject for BITMAP not implemented\n");
         ret = 1;
         break;
     case FONT_MAGIC:
diff --git a/graphics/win16drv/prtdrv.c b/graphics/win16drv/prtdrv.c
index 43bb7e8..0fdf1a6 100644
--- a/graphics/win16drv/prtdrv.c
+++ b/graphics/win16drv/prtdrv.c
@@ -133,7 +133,7 @@
     }
     if (!bSlotFound)
     {
-	fprintf(stderr,"Too many printers drivers loaded\n");
+	WARN(win16drv,"Too many printers drivers loaded\n");
 	return NULL;
     }
 
@@ -148,7 +148,7 @@
     if (hInst <= 32)
     {
 	/* Failed to load driver */
-	fprintf(stderr, "Failed to load printer driver %s\n", pszDriver);
+	WARN(win16drv, "Failed to load printer driver %s\n", pszDriver);
     } else {
         TRACE(win16drv, "Loaded the library\n");
 	/* Allocate some memory for printer driver info */
@@ -297,7 +297,7 @@
 	if(lpFaceName)
 	    SEGPTR_FREE(lP2);
     } else 
-        fprintf(stderr,"Failed to find device\n");
+        WARN(win16drv,"Failed to find device\n");
     
     TRACE(win16drv, "return %x\n", wRet);
     return wRet;
@@ -340,7 +340,7 @@
                                               lP1, wP2, lP3, lP4 );
     }
     else 
-        fprintf(stderr,"Failed to find device\n");
+        WARN(win16drv,"Failed to find device\n");
     
     TRACE(win16drv, "return %x\n", wRet);
     return wRet;
@@ -395,7 +395,7 @@
 	    clip = HeapAlloc( SystemHeap, 0, size );
 	    if(!clip) 
 	    {
-	        fprintf(stderr, "Can't alloc clip array in PRTDRV_Output\n");
+	        WARN(win16drv, "Can't alloc clip array in PRTDRV_Output\n");
 		return FALSE;
 	    }
 	    GetRegionData( hClipRgn, size, clip );
@@ -486,8 +486,7 @@
 
         case DRVOBJ_PBITMAP:
         default:
-	    fprintf(stderr, 
-	       "PRTDRV_RealizeObject: Object type %d not supported\n", wStyle);
+	    WARN(win16drv, "Object type %d not supported\n", wStyle);
             nSize = 0;
             
 	}
@@ -670,26 +669,27 @@
 
 int WINAPI dmRealizeObject(LPPDEVICE lpDestDev, INT16 wStyle, LPSTR lpInObj, LPSTR lpOutObj, SEGPTR lpTextXForm)
 {
-    fprintf(stderr, "dmRealizeObject(lpDestDev: %08x, wStyle: %04x, lpInObj: %08x, lpOutObj: %08x, lpTextXForm: %08x): stub: ", (UINT32)lpDestDev, wStyle, (UINT32)lpInObj, (UINT32)lpOutObj, (UINT32)lpTextXForm);
+    FIXME(win16drv, "(lpDestDev=%08x,wStyle=%04x,lpInObj=%08x,lpOutObj=%08x,lpTextXForm=%08x): stub\n",
+        (UINT32)lpDestDev, wStyle, (UINT32)lpInObj, (UINT32)lpOutObj, (UINT32)lpTextXForm);
     if (wStyle < 0) { /* Free extra memory of given object's structure */
 	switch ( -wStyle ) {
             case DRVOBJ_PEN:    {
                                 /* LPLOGPEN16 DeletePen = (LPLOGPEN16)lpInObj; */
 
-                                fprintf(stderr, "DRVOBJ_PEN_delete\n");
+                                TRACE(win16drv, "DRVOBJ_PEN_delete\n");
 				break;
                                 }
             case DRVOBJ_BRUSH:	{
-				fprintf(stderr, "DRVOBJ_BRUSH_delete\n");
+				TRACE(win16drv, "DRVOBJ_BRUSH_delete\n");
                                 break;
 				}
             case DRVOBJ_FONT:	{
 				/* LPTEXTXFORM16 TextXForm
 					= (LPTEXTXFORM16)lpTextXForm; */
-				fprintf(stderr, "DRVOBJ_FONT_delete\n");
+				TRACE(win16drv, "DRVOBJ_FONT_delete\n");
                                 break;
 				}
-            case DRVOBJ_PBITMAP:        fprintf(stderr, "DRVOBJ_PBITMAP_delete\n");
+            case DRVOBJ_PBITMAP:        TRACE(win16drv, "DRVOBJ_PBITMAP_delete\n");
                                 break;
 	}
     }
@@ -699,7 +699,7 @@
 	    case DRVOBJ_PEN: {
 				LPLOGPEN16 InPen  = (LPLOGPEN16)lpInObj;
 
-				fprintf(stderr, "DRVOBJ_PEN\n");
+				TRACE(win16drv, "DRVOBJ_PEN\n");
 				if (lpOutObj) {
 				    if (InPen->lopnStyle == PS_NULL) {
 					*(DWORD *)lpOutObj = 0;
@@ -722,7 +722,7 @@
 				LPLOGBRUSH16 OutBrush = (LPLOGBRUSH16)lpOutObj;
                                 /* LPPOINT16 Point = (LPPOINT16)lpTextXForm; */
 
-				fprintf(stderr, "DRVOBJ_BRUSH\n");
+				TRACE(win16drv, "DRVOBJ_BRUSH\n");
 				if (!lpOutObj) return sizeof(LOGBRUSH16);
 				else {
 				    OutBrush->lbStyle = InBrush->lbStyle;
@@ -736,10 +736,10 @@
 	    case DRVOBJ_FONT: {
                                 /* LPTEXTXFORM16 TextXForm
                                         = (LPTEXTXFORM16)lpTextXForm; */
-                                fprintf(stderr, "DRVOBJ_FONT\n");
+                                TRACE(win16drv, "DRVOBJ_FONT\n");
 				return 0;/* DISPLAY.DRV doesn't realize fonts */
 			      }
-	    case DRVOBJ_PBITMAP:	fprintf(stderr, "DRVOBJ_PBITMAP\n");
+	    case DRVOBJ_PBITMAP:	TRACE(win16drv, "DRVOBJ_PBITMAP\n");
 					return 0; /* create memory bitmap */
 	}
     }
diff --git a/graphics/wing.c b/graphics/wing.c
index 962a752..f6dffa1 100644
--- a/graphics/wing.c
+++ b/graphics/wing.c
@@ -19,8 +19,6 @@
 #include "xmalloc.h"
 #include "debug.h"
 
-extern void CLIPPING_UpdateGCRegion(DC* );
-
 typedef enum WING_DITHER_TYPE
 {
   WING_DISPERSED_4x4, WING_DISPERSED_8x8, WING_CLUSTERED_4x4
diff --git a/graphics/x11drv/bitblt.c b/graphics/x11drv/bitblt.c
index de68103..699d67c 100644
--- a/graphics/x11drv/bitblt.c
+++ b/graphics/x11drv/bitblt.c
@@ -38,8 +38,6 @@
 #define SWAP_INT32(i1,i2) \
     do { INT32 __t = *(i1); *(i1) = *(i2); *(i2) = __t; } while(0)
 
-extern void CLIPPING_UpdateGCRegion(DC* );
-
 static const unsigned char BITBLT_Opcodes[256][MAX_OP_LEN] =
 {
     { OP(PAT,DST,GXclear) },                         /* 0x00  0              */
@@ -1381,9 +1379,11 @@
     struct StretchBlt_params params = { dc, left, top, width, height,
                                         NULL, 0, 0, 0, 0, rop };
     BOOL32 result;
+    DIB_UpdateDIBSection( dc, FALSE );
     EnterCriticalSection( &X11DRV_CritSection );
     result = (BOOL32)CALL_LARGE_STACK( BITBLT_DoStretchBlt, &params );
     LeaveCriticalSection( &X11DRV_CritSection );
+    DIB_UpdateDIBSection( dc, TRUE );
     return result;
 }
 
@@ -1398,9 +1398,13 @@
     struct StretchBlt_params params = { dcDst, xDst, yDst, width, height,
                                         dcSrc, xSrc, ySrc, width, height, rop};
     BOOL32 result;
+    DIB_UpdateDIBSection( dcDst, FALSE );
+    DIB_UpdateDIBSection( dcSrc, FALSE );
     EnterCriticalSection( &X11DRV_CritSection );
     result = (BOOL32)CALL_LARGE_STACK( BITBLT_DoStretchBlt, &params );
     LeaveCriticalSection( &X11DRV_CritSection );
+    DIB_UpdateDIBSection( dcDst, TRUE );
+    DIB_UpdateDIBSection( dcSrc, TRUE );
     return result;
 }
 
@@ -1417,8 +1421,12 @@
                                         dcSrc, xSrc, ySrc, widthSrc, heightSrc,
                                         rop };
     BOOL32 result;
+    DIB_UpdateDIBSection( dcDst, FALSE );
+    DIB_UpdateDIBSection( dcSrc, FALSE );
     EnterCriticalSection( &X11DRV_CritSection );
     result = (BOOL32)CALL_LARGE_STACK( BITBLT_DoStretchBlt, &params );
     LeaveCriticalSection( &X11DRV_CritSection );
+    DIB_UpdateDIBSection( dcDst, TRUE );
+    DIB_UpdateDIBSection( dcSrc, TRUE );
     return result;
 }
diff --git a/graphics/x11drv/bitmap.c b/graphics/x11drv/bitmap.c
index 960c3c7..d9aa981 100644
--- a/graphics/x11drv/bitmap.c
+++ b/graphics/x11drv/bitmap.c
@@ -15,8 +15,6 @@
 #include "heap.h"
 #include "debug.h"
 
-extern void CLIPPING_UpdateGCRegion(DC* );
-
 /***********************************************************************
  *           X11DRV_BITMAP_Init
  */
diff --git a/graphics/x11drv/clipping.c b/graphics/x11drv/clipping.c
index 8e87ce5..88b3455 100644
--- a/graphics/x11drv/clipping.c
+++ b/graphics/x11drv/clipping.c
@@ -24,7 +24,7 @@
     RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr(dc->w.hGCClipRgn, REGION_MAGIC);
     if (!obj)
     {
-        fprintf( stderr, "X11DRV_SetDeviceClipping: Rgn is 0. Please report this.\n");
+        ERR(x11drv, "Rgn is 0. Please report this.\n");
         exit(1);
     }
     
@@ -38,7 +38,7 @@
 			    sizeof(*pXrect) * obj->rgn->numRects );
 	if(!pXrect)
 	{
-	    fprintf(stderr, "X11DRV_SetDeviceClipping() can't alloc buffer\n");
+	    WARN(x11drv, "Can't alloc buffer\n");
 	    return;
 	}
 
diff --git a/graphics/x11drv/xfont.c b/graphics/x11drv/xfont.c
index aaf0e20..2378ec3 100644
--- a/graphics/x11drv/xfont.c
+++ b/graphics/x11drv/xfont.c
@@ -19,6 +19,7 @@
 #include "ts_xlib.h"
 #include <X11/Xatom.h>
 #include <math.h>
+#include <assert.h>
 #include "heap.h"
 #include "options.h"
 #include "x11font.h"
@@ -29,7 +30,7 @@
 #define X_FMC_MAGIC		(0x0000CAFE)
 
 #define MAX_FONT_FAMILIES	64
-#define MAX_LFD_LENGTH		128
+#define MAX_LFD_LENGTH		256
 
 #define REMOVE_SUBSETS		1
 #define UNMARK_SUBSETS		0
@@ -396,6 +397,7 @@
    const char*  lpEncoding = NULL;
    char         h_string[64], point_string[64];
 
+   *(lpLFD+MAX_LFD_LENGTH-1)=0;
    lstrcpy32A( lpLFD, fo->fr->resource );
 
 /* add weight */
@@ -543,6 +545,7 @@
    }
 
    TRACE(font,"\tLFD: %s\n", lpLFD );
+   assert(*(lpLFD+MAX_LFD_LENGTH-1)==0); /* check if overwrittem */
    return TRUE;
 }
 
@@ -1242,7 +1245,7 @@
     PROFILE_EnumerateWineIniSection("Fonts", &XFONT_CheckIniCallback,
                     (void *)&found);
     if(found)
-    fprintf(stderr, fontmsgepilogue);
+    MSG(fontmsgepilogue);
 
     return 1;
 }
@@ -1267,21 +1270,21 @@
 	/* Valid key; make sure the value doesn't contain a wildcard */
 	if(strchr(value, '*')) {
 	    if(*(int *)found == 0) {
-		fprintf(stderr, fontmsgprologue);
+		MSG(fontmsgprologue);
 		++*(int *)found;
 	    }
 
-	    fprintf(stderr, "     %s=%s [no wildcards allowed]\n", key, value);
+	    MSG("     %s=%s [no wildcards allowed]\n", key, value);
 	}
     }
     else {
 	/* Not a valid key */
 	if(*(int *)found == 0) {
-	    fprintf(stderr, fontmsgprologue);
+	    MSG(fontmsgprologue);
 	    ++*(int *)found;
     }
 
-	fprintf(stderr, "     %s=%s [obsolete]\n", key, value);
+	MSG("     %s=%s [obsolete]\n", key, value);
     }
 
     return;
diff --git a/if1632/Makefile.in b/if1632/Makefile.in
index 9e9fe8f..dfad2dd 100644
--- a/if1632/Makefile.in
+++ b/if1632/Makefile.in
@@ -15,6 +15,7 @@
 	lzexpand.spec \
 	mmsystem.spec \
 	mouse.spec \
+	msvideo.spec \
 	ole2.spec \
 	ole2conv.spec \
 	ole2disp.spec \
diff --git a/if1632/builtin.c b/if1632/builtin.c
index 74fdbd6..ba9db19 100644
--- a/if1632/builtin.c
+++ b/if1632/builtin.c
@@ -53,6 +53,7 @@
 extern const WIN16_DESCRIPTOR LZEXPAND_Descriptor;
 extern const WIN16_DESCRIPTOR MMSYSTEM_Descriptor;
 extern const WIN16_DESCRIPTOR MOUSE_Descriptor;
+extern const WIN16_DESCRIPTOR MSVIDEO_Descriptor;
 extern const WIN16_DESCRIPTOR OLE2CONV_Descriptor;
 extern const WIN16_DESCRIPTOR OLE2DISP_Descriptor;
 extern const WIN16_DESCRIPTOR OLE2NLS_Descriptor;
@@ -96,6 +97,7 @@
     { &LZEXPAND_Descriptor, 0 },
     { &MMSYSTEM_Descriptor, 0 },
     { &MOUSE_Descriptor,    0 },
+    { &MSVIDEO_Descriptor,  0 },
     { &OLE2CONV_Descriptor, DLL_FLAG_NOT_USED },
     { &OLE2DISP_Descriptor, DLL_FLAG_NOT_USED },
     { &OLE2NLS_Descriptor,  DLL_FLAG_NOT_USED },
diff --git a/if1632/dummy.c b/if1632/dummy.c
index 4c67b5d..d81a159 100644
--- a/if1632/dummy.c
+++ b/if1632/dummy.c
@@ -2,7 +2,6 @@
  * Dummy function definitions
  */
 
-#include <stdio.h>
 #include "wintypes.h"
 #include "debug.h"
 
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index ad451d3..38bd366 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -107,7 +107,7 @@
 106 pascal SetSwapAreaSize(word) SetSwapAreaSize16
 107 pascal16 SetErrorMode(word) SetErrorMode16
 108 pascal16 SwitchStackTo(word word word) SwitchStackTo
-109 register SwitchStackBack(word word word) SwitchStackBack
+109 register SwitchStackBack() SwitchStackBack
 110 pascal16 PatchCodeHandle(word) PatchCodeHandle
 111 pascal   GlobalWire(word) GlobalWire16
 112 pascal16 GlobalUnWire(word) GlobalUnWire16
@@ -143,7 +143,7 @@
 140 pascal16 SetSigHandler(segptr ptr ptr word word) SetSigHandler
 141 stub InitTask1
 142 stub GetProfileSectionNames
-143 stub GetPrivateProfileSectionNames
+143 pascal16 GetPrivateProfileSectionNames(ptr word str) GetPrivateProfileSectionNames16
 144 pascal16 CreateDirectory(ptr ptr) CreateDirectory16
 145 pascal16 RemoveDirectory(ptr) RemoveDirectory16
 146 pascal16 DeleteFile(ptr) DeleteFile16
@@ -280,7 +280,7 @@
 357 pascal MapSL(segptr) MapSL
 358 pascal MapLS(long) MapLS
 359 pascal UnMapLS(segptr) UnMapLS
-360 stub OpenFileEx
+360 pascal16 OpenFileEx(str ptr word) OpenFile16
 #361 PIGLET_361
 365 stub KERNEL_365
 403 pascal16 FarSetOwner(word word) FarSetOwner
@@ -311,6 +311,8 @@
 447 stub KERNEL_447
 449 pascal KERNEL_449() KERNEL_449
 450 pascal16 KERNEL_450() stub_KERNEL_450
+452 stub KERNEL_452
+453 stub KERNEL_453
 454 equate __FLATCS 0   # initialized by BUILTIN_Init()
 455 equate __FLATDS 0   # initialized by BUILTIN_Init()
 471 pascal KERNEL_471() _KERNEL_471
@@ -321,6 +323,7 @@
 481 stub KERNEL_481
 482 pascal LoadLibrary32(str) LoadLibrary32A
 485 stub KERNEL_485
+486 stub KERNEL_486
 491 stub RegisterServiceProcess
 500 stub KERNEL_500
 502 stub KERNEL_502
diff --git a/if1632/msvideo.spec b/if1632/msvideo.spec
new file mode 100644
index 0000000..f3b6e1a
--- /dev/null
+++ b/if1632/msvideo.spec
@@ -0,0 +1,69 @@
+name msvideo
+type win16
+
+2 stub VIDEOFORWINDOWSVERSION
+20 stub VIDEOGETNUMDEVS
+21 stub VIDEOGETERRORTEXT
+22 stub VIDEOCAPDRIVERDESCANDVER
+28 stub VIDEOOPEN
+29 stub VIDEOCLOSE
+30 stub VIDEODIALOG
+31 stub VIDEOFRAME
+32 stub VIDEOCONFIGURE
+33 stub VIDEOCONFIGURESTORAGE
+34 stub VIDEOGETCHANNELCAPS
+35 stub VIDEOUPDATE
+40 stub VIDEOSTREAMADDBUFFER
+41 stub VIDEOSTREAMFINI
+42 stub VIDEOSTREAMGETERROR
+43 stub VIDEOSTREAMGETPOSITION
+44 stub VIDEOSTREAMINIT
+46 stub VIDEOSTREAMPREPAREHEADER
+47 stub VIDEOSTREAMRESET
+49 stub VIDEOSTREAMSTART
+50 stub VIDEOSTREAMSTOP
+51 stub VIDEOSTREAMUNPREPAREHEADER
+52 stub VIDEOSTREAMALLOCHDRANDBUFFER
+53 stub VIDEOSTREAMFREEHDRANDBUFFER
+60 stub VIDEOMESSAGE
+102 stub DRAWDIBOPEN
+103 stub DRAWDIBCLOSE
+104 stub DRAWDIBBEGIN
+105 stub DRAWDIBEND
+106 stub DRAWDIBDRAW
+108 stub DRAWDIBGETPALETTE
+110 stub DRAWDIBSETPALETTE
+111 stub DRAWDIBCHANGEPALETTE
+112 stub DRAWDIBREALIZE
+113 stub DRAWDIBTIME
+114 stub DRAWDIBPROFILEDISPLAY
+115 stub STRETCHDIB
+118 stub DRAWDIBSTART
+119 stub DRAWDIBSTOP
+120 stub DRAWDIBGETBUFFER
+200 stub ICINFO
+201 stub ICINSTALL
+202 stub ICREMOVE
+203 stub ICOPEN
+204 stub ICCLOSE
+205 stub ICSENDMESSAGE
+206 stub ICOPENFUNCTION
+207 stub _ICMESSAGE
+212 stub ICGETINFO
+213 stub ICLOCATE
+224 stub _ICCOMPRESS
+230 stub _ICDECOMPRESS
+232 stub _ICDRAWBEGIN
+234 stub _ICDRAW
+239 stub ICGETDISPLAYFORMAT
+240 stub ICIMAGECOMPRESS
+241 stub ICIMAGEDECOMPRESS
+242 stub ICCOMPRESSORCHOOSE
+243 stub ICCOMPRESSORFREE
+244 stub ICSEQCOMPRESSFRAMESTART
+245 stub ICSEQCOMPRESSFRAMEEND
+246 stub ICSEQCOMPRESSFRAME
+250 stub _MCIWNDCREATE
+251 stub _MCIWNDREGISTERCLASS
+252 stub GETOPENFILENAMEPREVIEW
+253 stub GETSAVEFILENAMEPREVIEW
diff --git a/if1632/relay.c b/if1632/relay.c
index 1999d76..3135d9c 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -4,7 +4,6 @@
  */
 
 #include <assert.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include "windows.h"
 #include "winnt.h"
@@ -71,9 +70,9 @@
     if (!TRACE_ON(relay)) return;
 
     frame = CURRENT_STACK16;
-    printf( "Call %s(", BUILTIN_GetEntryPoint16( frame->entry_cs,
-                                                 frame->entry_ip,
-                                                 &ordinal ));
+    DPRINTF( "Call %s(", BUILTIN_GetEntryPoint16( frame->entry_cs,
+                                                  frame->entry_ip,
+                                                  &ordinal ));
     VA_START16( args16 );
 
     if (func_type & 4)  /* cdecl */
@@ -84,32 +83,32 @@
             {
             case 'w':
             case 's':
-                printf( "0x%04x", *(WORD *)args16 );
+                DPRINTF( "0x%04x", *(WORD *)args16 );
                 args16 += 2;
                 break;
             case 'l':
-                printf( "0x%08x", *(int *)args16 );
+                DPRINTF( "0x%08x", *(int *)args16 );
                 args16 += 4;
                 break;
             case 't':
-                printf( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
+                DPRINTF( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
                 if (HIWORD(*(SEGPTR *)args16))
                     debug_dumpstr( (LPSTR)PTR_SEG_TO_LIN(*(SEGPTR *)args16 ));
                 args16 += 4;
                 break;
             case 'p':
-                printf( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
+                DPRINTF( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
                 args16 += 4;
                 break;
             case 'T':
-                printf( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
+                DPRINTF( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
                 if (HIWORD( *(SEGPTR *)args16 ))
                     debug_dumpstr( (LPSTR)PTR_SEG_TO_LIN(*(SEGPTR *)args16 ));
                 args16 += 4;
                 break;
             }
             args++;
-            if (*args) printf( "," );
+            if (*args) DPRINTF( "," );
         }
     }
     else  /* not cdecl */
@@ -139,42 +138,42 @@
             case 'w':
             case 's':
                 args16 -= 2;
-                printf( "0x%04x", *(WORD *)args16 );
+                DPRINTF( "0x%04x", *(WORD *)args16 );
                 break;
             case 'l':
                 args16 -= 4;
-                printf( "0x%08x", *(int *)args16 );
+                DPRINTF( "0x%08x", *(int *)args16 );
                 break;
             case 't':
                 args16 -= 4;
-                printf( "0x%08x", *(int *)args16 );
+                DPRINTF( "0x%08x", *(int *)args16 );
                 if (HIWORD(*(SEGPTR *)args16))
                     debug_dumpstr( (LPSTR)PTR_SEG_TO_LIN(*(SEGPTR *)args16 ));
                 break;
             case 'p':
                 args16 -= 4;
-                printf( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
+                DPRINTF( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
                 break;
             case 'T':
                 args16 -= 4;
-                printf( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
+                DPRINTF( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
                 if (HIWORD( *(SEGPTR *)args16 ))
                     debug_dumpstr( (LPSTR)PTR_SEG_TO_LIN(*(SEGPTR *)args16 ));
                 break;
             }
             args++;
-            if (*args) printf( "," );
+            if (*args) DPRINTF( "," );
         }
     }
 
-    printf( ") ret=%04x:%04x ds=%04x\n", frame->cs, frame->ip, frame->ds );
+    DPRINTF( ") ret=%04x:%04x ds=%04x\n", frame->cs, frame->ip, frame->ds );
     VA_END16( args16 );
 
     if (func_type & 2)  /* register function */
-        printf( "     AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n",
-                AX_reg(context), BX_reg(context), CX_reg(context),
-                DX_reg(context), SI_reg(context), DI_reg(context),
-                (WORD)ES_reg(context), EFL_reg(context) );
+        DPRINTF( "     AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n",
+                 AX_reg(context), BX_reg(context), CX_reg(context),
+                 DX_reg(context), SI_reg(context), DI_reg(context),
+                 (WORD)ES_reg(context), EFL_reg(context) );
 }
 
 
@@ -188,23 +187,23 @@
 
     if (!TRACE_ON(relay)) return;
     frame = CURRENT_STACK16;
-    printf( "Ret  %s() ", BUILTIN_GetEntryPoint16( frame->entry_cs,
+    DPRINTF( "Ret  %s() ", BUILTIN_GetEntryPoint16( frame->entry_cs,
                                                    frame->entry_ip,
                                                    &ordinal ));
     switch(func_type)
     {
     case 0: /* long */
-        printf( "retval=0x%08x ret=%04x:%04x ds=%04x\n",
-                ret_val, frame->cs, frame->ip, frame->ds );
+        DPRINTF( "retval=0x%08x ret=%04x:%04x ds=%04x\n",
+                 ret_val, frame->cs, frame->ip, frame->ds );
         break;
     case 1: /* word */
-        printf( "retval=0x%04x ret=%04x:%04x ds=%04x\n",
-                ret_val & 0xffff, frame->cs, frame->ip, frame->ds );
+        DPRINTF( "retval=0x%04x ret=%04x:%04x ds=%04x\n",
+                 ret_val & 0xffff, frame->cs, frame->ip, frame->ds );
         break;
     case 2: /* regs */
-        printf( "retval=none ret=%04x:%04x ds=%04x\n",
+        DPRINTF("retval=none ret=%04x:%04x ds=%04x\n",
                 (WORD)CS_reg(context), IP_reg(context), (WORD)DS_reg(context));
-        printf( "     AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n",
+        DPRINTF("     AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n",
                 AX_reg(context), BX_reg(context), CX_reg(context),
                 DX_reg(context), SI_reg(context), DI_reg(context),
                 (WORD)ES_reg(context), EFL_reg(context) );
@@ -251,25 +250,25 @@
     {
         CONTEXT *context = (CONTEXT *)stack[0];
         WORD *stack16 = (WORD *)THREAD_STACK16(thdb);
-        printf( "CallTo16(func=%04lx:%04x,ds=%04lx",
+        DPRINTF("CallTo16(func=%04lx:%04x,ds=%04lx",
                 CS_reg(context), IP_reg(context), DS_reg(context) );
         nb_args = stack[1] / sizeof(WORD);
         while (nb_args--) printf( ",0x%04x", *(--stack16) );
-        printf( ") ss:sp=%04x:%04x\n", SELECTOROF(thdb->cur_stack),
+        DPRINTF(") ss:sp=%04x:%04x\n", SELECTOROF(thdb->cur_stack),
                 OFFSETOF(thdb->cur_stack) );
-        printf( "     AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x BP=%04x ES=%04x\n",
+        DPRINTF("     AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x BP=%04x ES=%04x\n",
                 AX_reg(context), BX_reg(context), CX_reg(context),
                 DX_reg(context), SI_reg(context), DI_reg(context),
                 BP_reg(context), (WORD)ES_reg(context) );
     }
     else
     {
-        printf( "CallTo16(func=%04x:%04x,ds=%04x",
+        DPRINTF("CallTo16(func=%04x:%04x,ds=%04x",
                 HIWORD(stack[0]), LOWORD(stack[0]),
                 SELECTOROF(thdb->cur_stack) );
         stack++;
-        while (nb_args--) printf( ",0x%04x", *stack++ );
-        printf( ") ss:sp=%04x:%04x\n", SELECTOROF(thdb->cur_stack),
+        while (nb_args--) DPRINTF(",0x%04x", *stack++ );
+        DPRINTF(") ss:sp=%04x:%04x\n", SELECTOROF(thdb->cur_stack),
                 OFFSETOF(thdb->cur_stack) );
     }
 }
diff --git a/if1632/signal.c b/if1632/signal.c
index 9c22d82..a310cf8 100644
--- a/if1632/signal.c
+++ b/if1632/signal.c
@@ -4,7 +4,6 @@
  * Copyright 1995 Alexandre Julliard
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <signal.h>
 #include <string.h>
@@ -24,6 +23,30 @@
 #include "thread.h"
 #include "debug.h"
 
+static const char * const SIGNAL_traps[] =
+{
+    "Division by zero exception",      /* 0 */
+    "Debug exception",                 /* 1 */
+    "NMI interrupt",                   /* 2 */
+    "Breakpoint exception",            /* 3 */
+    "Overflow exception",              /* 4 */
+    "Bound range exception",           /* 5 */
+    "Invalid opcode exception",        /* 6 */
+    "Device not available exception",  /* 7 */
+    "Double fault exception",          /* 8 */
+    "Coprocessor segment overrun",     /* 9 */
+    "Invalid TSS exception",           /* 10 */
+    "Segment not present exception",   /* 11 */
+    "Stack fault",                     /* 12 */
+    "General protection fault",        /* 13 */
+    "Page fault",                      /* 14 */
+    "Unknown exception",               /* 15 */
+    "Floating point exception",        /* 16 */
+    "Alignment check exception",       /* 17 */
+    "Machine check exception"          /* 18 */
+};
+
+#define NB_TRAPS  (sizeof(SIGNAL_traps) / sizeof(SIGNAL_traps[0]))
 
 extern void SIGNAL_SetHandler( int sig, void (*func)(), int flags );
 extern BOOL32 INSTR_EmulateInstruction( SIGCONTEXT *context );
@@ -62,20 +85,25 @@
  */
 static HANDLER_DEF(SIGNAL_fault)
 {
+    const char *fault = "Segmentation fault";
+
     HANDLER_INIT();
     if (INSTR_EmulateInstruction( HANDLER_CONTEXT )) return;
+#ifdef TRAP_sig
+    if (TRAP_sig( HANDLER_CONTEXT ) < NB_TRAPS)
+        fault = SIGNAL_traps[TRAP_sig( HANDLER_CONTEXT )];
+#endif
     if (IS_SELECTOR_SYSTEM(CS_sig(HANDLER_CONTEXT)))
     {
-        MSG("Segmentation fault in 32-bit code (0x%08lx).\n",
-            EIP_sig(HANDLER_CONTEXT) );
+        MSG("%s in 32-bit code (0x%08lx).\n", fault, EIP_sig(HANDLER_CONTEXT));
     }
     else
     {
-        MSG("Segmentation fault in 16-bit code (%04x:%04lx).\n",
+        MSG("%s in 16-bit code (%04x:%04lx).\n", fault,
             (WORD)CS_sig(HANDLER_CONTEXT), EIP_sig(HANDLER_CONTEXT) );
     }
 #ifdef CR2_sig
-    fprintf(stderr,"Fault address is 0x%08lx\n",CR2_sig(HANDLER_CONTEXT));
+    MSG("Fault address is 0x%08lx\n",CR2_sig(HANDLER_CONTEXT));
 #endif
     wine_debug( signal, HANDLER_CONTEXT );
 }
diff --git a/if1632/thunk.c b/if1632/thunk.c
index c4740d4..fec3b9e 100644
--- a/if1632/thunk.c
+++ b/if1632/thunk.c
@@ -2,9 +2,9 @@
  * Emulator thunks
  *
  * Copyright 1996, 1997 Alexandre Julliard
+ * Copyright 1998       Ulrich Weigand
  */
 
-#include <stdio.h>
 #include "windows.h"
 #include "callback.h"
 #include "resource.h"
@@ -13,12 +13,14 @@
 #include "heap.h"
 #include "hook.h"
 #include "module.h"
+#include "process.h"
 #include "stackframe.h"
 #include "selectors.h"
 #include "task.h"
 #include "except.h"
 #include "win.h"
 #include "debug.h"
+#include "flatthunk.h"
 
 
 /* List of the 16-bit callback functions. This list is used  */
@@ -710,3 +712,238 @@
     	*pdwret = ret;
     return TRUE;
 }
+
+
+/***********************************************************************
+ * 16->32 Flat Thunk routines:
+ */
+
+/***********************************************************************
+ *              ThunkConnect16          (KERNEL.651)
+ * Connects a 32bit and a 16bit thunkbuffer.
+ */
+UINT32 WINAPI ThunkConnect16(
+        LPSTR module16,              /* [in] name of win16 dll */
+        LPSTR module32,              /* [in] name of win32 dll */
+        HINSTANCE16 hInst16,         /* [in] hInst of win16 dll */
+        DWORD dwReason,              /* [in] initialisation argument */
+        struct ThunkDataCommon *TD,  /* [in/out] thunkbuffer */
+        LPSTR thunkfun32,            /* [in] win32 thunkfunction */
+        WORD CS                      /* [in] CS of win16 dll */
+) {
+    BOOL32 directionSL;
+
+    if (!lstrncmp32A(TD->magic, "SL01", 4))
+    {
+        directionSL = TRUE;
+
+        TRACE(thunk, "SL01 thunk %s (%lx) -> %s (%s), Reason: %ld\n",
+                     module16, (DWORD)TD, module32, thunkfun32, dwReason);
+    }
+    else if (!lstrncmp32A(TD->magic, "LS01", 4))
+    {
+        directionSL = FALSE;
+
+        TRACE(thunk, "LS01 thunk %s (%lx) <- %s (%s), Reason: %ld\n",
+                     module16, (DWORD)TD, module32, thunkfun32, dwReason);
+    }
+    else
+    {
+        ERR(thunk, "Invalid magic %c%c%c%c\n",
+                   TD->magic[0], TD->magic[1], TD->magic[2], TD->magic[3]);
+        return 0;
+    }
+
+    switch (dwReason)
+    {
+        case DLL_PROCESS_ATTACH:
+            if (directionSL)
+            {
+                struct ThunkDataSL16 *SL16 = (struct ThunkDataSL16 *)TD;
+                struct ThunkDataSL   *SL   = SL16->fpData;
+
+                if (SL == NULL)
+                {
+                    SL = HeapAlloc(GetProcessHeap(), 0, sizeof(*SL));
+
+                    SL->common   = SL16->common;
+                    SL->flags1   = SL16->flags1;
+                    SL->flags2   = SL16->flags2;
+
+                    SL->apiDB    = PTR_SEG_TO_LIN(SL16->apiDatabase);
+                    SL->targetDB = NULL;
+
+                    lstrcpyn32A(SL->pszDll16, module16, 255);
+                    lstrcpyn32A(SL->pszDll32, module32, 255);
+
+                    /* We should create a SEGPTR to the ThunkDataSL,
+                       but since the contents are not in the original format,
+                       any access to this by 16-bit code would crash anyway. */
+                    SL16->spData = 0;
+                    SL16->fpData = SL;
+                }
+
+
+                if (SL->flags2 & 0x80000000)
+                {
+                    TRACE(thunk, "Preloading 32-bit library\n");
+                    LoadLibrary32A(module32);
+                }
+            }
+            else
+            {
+                /* nothing to do */
+            }
+            break;
+
+        case DLL_PROCESS_DETACH:
+            /* FIXME: cleanup */
+            break;
+    }
+
+    return 1;
+}
+
+
+/***********************************************************************
+ *           C16ThkSL                           (KERNEL.630)
+ */
+
+void WINAPI C16ThkSL(CONTEXT *context)
+{
+    extern void CallFrom16_t_long_(void);
+    LPBYTE stub = PTR_SEG_TO_LIN(EAX_reg(context)), x = stub;
+    WORD cs, ds;
+    GET_CS(cs);
+    GET_DS(ds);
+
+    /* We produce the following code:
+     *
+     *   mov ax, __FLATDS
+     *   mov es, ax
+     *   movzx ecx, cx
+     *   mov edx, es:[ecx + $EDX]
+     *   push bp
+     *   push edx
+     *   call __FLATCS:CallFrom16_t_long_
+     */
+
+    *x++ = 0xB8; *((WORD *)x)++ = ds;
+    *x++ = 0x8E; *x++ = 0xC0;
+    *x++ = 0x60; *x++ = 0x0F; *x++ = 0xB7; *x++ = 0xC9;
+    *x++ = 0x67; *x++ = 0x66; *x++ = 0x26; *x++ = 0x8B;
+                 *x++ = 0x91; *((DWORD *)x)++ = EDX_reg(context);
+
+    *x++ = 0x55;
+    *x++ = 0x66; *x++ = 0x52;
+    *x++ = 0x66; *x++ = 0x9A; *((DWORD *)x)++ = (DWORD)CallFrom16_t_long_;
+                              *((WORD *)x)++ = cs;
+
+    /* Jump to the stub code just created */
+    IP_reg(context) = LOWORD(EAX_reg(context));
+    CS_reg(context) = HIWORD(EAX_reg(context));
+
+    /* Since C16ThkSL got called by a jmp, we need to leave the
+       orginal return address on the stack */
+    SP_reg(context) -= 4;
+}
+
+/***********************************************************************
+ *           C16ThkSL01                         (KERNEL.631)
+ */
+
+void WINAPI C16ThkSL01(CONTEXT *context)
+{
+    LPBYTE stub = PTR_SEG_TO_LIN(EAX_reg(context)), x = stub;
+
+    if (stub)
+    {
+        struct ThunkDataSL16 *SL16 = PTR_SEG_TO_LIN(EDX_reg(context));
+        struct ThunkDataSL *td = SL16->fpData;
+
+        extern void CallFrom16_t_long_(void);
+        DWORD procAddress = (DWORD)GetProcAddress16(GetModuleHandle16("KERNEL"), 631);
+        WORD cs;
+        GET_CS(cs);
+
+        if (!td)
+        {
+            ERR(thunk, "ThunkConnect16 was not called!\n");
+            return;
+        }
+
+        TRACE(thunk, "Creating stub for ThunkDataSL %08lx\n", (DWORD)td);
+
+
+        /* We produce the following code:
+         *
+         *   xor eax, eax
+         *   mov edx, $td
+         *   call C16ThkSL01
+         *   push bp
+         *   push edx
+         *   call __FLATCS:CallFrom16_t_long_
+         */
+
+        *x++ = 0x66; *x++ = 0x33; *x++ = 0xC0;
+        *x++ = 0x66; *x++ = 0xBA; *((DWORD *)x)++ = (DWORD)td;
+        *x++ = 0x9A; *((DWORD *)x)++ = procAddress;
+
+        *x++ = 0x55;
+        *x++ = 0x66; *x++ = 0x52;
+        *x++ = 0x66; *x++ = 0x9A; *((DWORD *)x)++ = (DWORD)CallFrom16_t_long_;
+                                  *((WORD *)x)++ = cs;
+
+        /* Jump to the stub code just created */
+        IP_reg(context) = LOWORD(EAX_reg(context));
+        CS_reg(context) = HIWORD(EAX_reg(context));
+
+        /* Since C16ThkSL01 got called by a jmp, we need to leave the
+           orginal return address on the stack */
+        SP_reg(context) -= 4;
+    }
+    else
+    {
+        struct ThunkDataSL *td = (struct ThunkDataSL *)EDX_reg(context);
+        DWORD targetNr = CX_reg(context) / 4;
+        struct SLTargetDB *tdb;
+
+        TRACE(thunk, "Process %08lx calling target %ld of ThunkDataSL %08lx\n",
+                     (DWORD)PROCESS_Current(), targetNr, (DWORD)td);
+
+        for (tdb = td->targetDB; tdb; tdb = tdb->next)
+            if (tdb->process == PROCESS_Current())
+                break;
+
+        if (!tdb)
+        {
+            TRACE(thunk, "Loading 32-bit library %s\n", td->pszDll32);
+            LoadLibrary32A(td->pszDll32);
+
+            for (tdb = td->targetDB; tdb; tdb = tdb->next)
+                if (tdb->process == PROCESS_Current())
+                    break;
+        }
+
+        if (tdb)
+        {
+            EDX_reg(context) = tdb->targetTable[targetNr];
+
+            TRACE(thunk, "Call target is %08lx\n", EDX_reg(context));
+        }
+        else
+        {
+            WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
+            DX_reg(context) = HIWORD(td->apiDB[targetNr].errorReturnValue);
+            AX_reg(context) = LOWORD(td->apiDB[targetNr].errorReturnValue);
+            IP_reg(context) = stack[2];
+            CS_reg(context) = stack[3];
+            SP_reg(context) += td->apiDB[targetNr].nrArgBytes + 4;
+
+            /* Win95 allows delayed loading of the 32-bit DLL.
+               We don't do that at the moment. */
+            ERR(thunk, "Process %08lx did not ThunkConnect32 %s to %s\n",
+                       (DWORD)PROCESS_Current(), td->pszDll32, td->pszDll16);
+        }
+    }
+}
diff --git a/if1632/user.spec b/if1632/user.spec
index 5eea87b..570aa21 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -462,8 +462,8 @@
 514 pascal16 WNetDeviceMode(word) WNetDeviceMode
 515 pascal16 WNetBrowseDialog(word word ptr) WNetBrowseDialog
 516 pascal16 WNetGetUser(ptr ptr ptr) WNetGetUser
-517 pascal16 WNetAddConnection(ptr ptr ptr) WNetAddConnection16
-518 pascal16 WNetCancelConnection(ptr word) WNetCancelConnection
+517 pascal16 WNetAddConnection(str str str) WNetAddConnection16
+518 pascal16 WNetCancelConnection(str word) WNetCancelConnection
 519 pascal16 WNetGetError(ptr) WNetGetError
 520 pascal16 WNetGetErrorText(word ptr ptr) WNetGetErrorText
 521 stub WNetEnable
diff --git a/if1632/winsock.spec b/if1632/winsock.spec
index e8564bb..58e91e1 100644
--- a/if1632/winsock.spec
+++ b/if1632/winsock.spec
@@ -39,15 +39,15 @@
 101 pascal16 WSAAsyncSelect(word word word long) WSAAsyncSelect16
 102 pascal16 WSAAsyncGetHostByAddr(word word ptr word word segptr word)
              WSAAsyncGetHostByAddr16
-103 pascal16 WSAAsyncGetHostByName(word word ptr segptr word)
+103 pascal16 WSAAsyncGetHostByName(word word str segptr word)
              WSAAsyncGetHostByName16
 104 pascal16 WSAAsyncGetProtoByNumber(word word word segptr word)
              WSAAsyncGetProtoByNumber16
-105 pascal16 WSAAsyncGetProtoByName(word word ptr segptr word)
+105 pascal16 WSAAsyncGetProtoByName(word word str segptr word)
              WSAAsyncGetProtoByName16
-106 pascal16 WSAAsyncGetServByPort(word word word ptr segptr word)
+106 pascal16 WSAAsyncGetServByPort(word word word str segptr word)
              WSAAsyncGetServByPort16
-107 pascal16 WSAAsyncGetServByName(word word ptr ptr segptr word)
+107 pascal16 WSAAsyncGetServByName(word word str str segptr word)
              WSAAsyncGetServByName16
 108 pascal16 WSACancelAsyncRequest(word) WSACancelAsyncRequest16
 109 pascal16 WSASetBlockingHook(segptr) WSASetBlockingHook16
diff --git a/include/bitmap.h b/include/bitmap.h
index 3690de2..042c4a7 100644
--- a/include/bitmap.h
+++ b/include/bitmap.h
@@ -29,6 +29,12 @@
     BITMAP16    bitmap;
     Pixmap      pixmap;
     SIZE16      size;   /* For SetBitmapDimension() */
+
+    /* For device-independent bitmaps: */
+    DIBSECTION *dibSection;
+    RGBQUAD    *colorMap;
+    int         nColorMap;
+
 } BITMAPOBJ;
 
   /* GCs used for B&W and color bitmap operations */
@@ -62,6 +68,8 @@
 extern int DIB_GetDIBWidthBytes( int width, int depth );
 extern int DIB_GetXImageWidthBytes( int width, int depth );
 extern int DIB_BitmapInfoSize( BITMAPINFO * info, WORD coloruse );
+extern void DIB_UpdateDIBSection( DC *dc, BOOL32 toDIB );
+
 
   /* objects/oembitmap.c */
 extern BOOL32 OBM_Init(void);
diff --git a/include/builtin32.h b/include/builtin32.h
index 4d3dd3b..05cf106 100644
--- a/include/builtin32.h
+++ b/include/builtin32.h
@@ -15,7 +15,6 @@
     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 */
diff --git a/include/casemap.h b/include/casemap.h
new file mode 100644
index 0000000..9a03b57
--- /dev/null
+++ b/include/casemap.h
@@ -0,0 +1,905 @@
+/*
+ * Automatically generated file -- do not edit!
+ * (Use tools/unimap.pl for generation)
+ *
+ * Mapping tables for Unicode case conversion
+ */
+
+/* Lowercase mappings 0000 - 00FF */
+static const WCHAR lblk00[256] = {
+	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+	0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+	0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+	0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+	0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+	0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+	0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+	0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+	0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+	0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+	0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+	0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+	0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+	0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+	0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+	0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+	0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+	0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+	0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+	0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+	0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+	0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+	0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+	0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+	0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+	0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+	0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00D7,
+	0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00DF,
+	0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+	0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+	0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+	0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF,
+};
+
+/* Lowercase mappings 0100 - 01FF */
+static const WCHAR lblk01[256] = {
+	0x0101, 0x0101, 0x0103, 0x0103, 0x0105, 0x0105, 0x0107, 0x0107,
+	0x0109, 0x0109, 0x010B, 0x010B, 0x010D, 0x010D, 0x010F, 0x010F,
+	0x0111, 0x0111, 0x0113, 0x0113, 0x0115, 0x0115, 0x0117, 0x0117,
+	0x0119, 0x0119, 0x011B, 0x011B, 0x011D, 0x011D, 0x011F, 0x011F,
+	0x0121, 0x0121, 0x0123, 0x0123, 0x0125, 0x0125, 0x0127, 0x0127,
+	0x0129, 0x0129, 0x012B, 0x012B, 0x012D, 0x012D, 0x012F, 0x012F,
+	0x0069, 0x0131, 0x0133, 0x0133, 0x0135, 0x0135, 0x0137, 0x0137,
+	0x0138, 0x013A, 0x013A, 0x013C, 0x013C, 0x013E, 0x013E, 0x0140,
+	0x0140, 0x0142, 0x0142, 0x0144, 0x0144, 0x0146, 0x0146, 0x0148,
+	0x0148, 0x0149, 0x014B, 0x014B, 0x014D, 0x014D, 0x014F, 0x014F,
+	0x0151, 0x0151, 0x0153, 0x0153, 0x0155, 0x0155, 0x0157, 0x0157,
+	0x0159, 0x0159, 0x015B, 0x015B, 0x015D, 0x015D, 0x015F, 0x015F,
+	0x0161, 0x0161, 0x0163, 0x0163, 0x0165, 0x0165, 0x0167, 0x0167,
+	0x0169, 0x0169, 0x016B, 0x016B, 0x016D, 0x016D, 0x016F, 0x016F,
+	0x0171, 0x0171, 0x0173, 0x0173, 0x0175, 0x0175, 0x0177, 0x0177,
+	0x00FF, 0x017A, 0x017A, 0x017C, 0x017C, 0x017E, 0x017E, 0x017F,
+	0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,
+	0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x0258, 0x0259,
+	0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,
+	0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x019F,
+	0x01A1, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x01A6, 0x01A8,
+	0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01B0,
+	0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292,
+	0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,
+	0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9,
+	0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC, 0x01CE, 0x01CE, 0x01D0,
+	0x01D0, 0x01D2, 0x01D2, 0x01D4, 0x01D4, 0x01D6, 0x01D6, 0x01D8,
+	0x01D8, 0x01DA, 0x01DA, 0x01DC, 0x01DC, 0x01DD, 0x01DF, 0x01DF,
+	0x01E1, 0x01E1, 0x01E3, 0x01E3, 0x01E5, 0x01E5, 0x01E7, 0x01E7,
+	0x01E9, 0x01E9, 0x01EB, 0x01EB, 0x01ED, 0x01ED, 0x01EF, 0x01EF,
+	0x01F0, 0x01F3, 0x01F3, 0x01F3, 0x01F5, 0x01F5, 0x01F6, 0x01F7,
+	0x01F8, 0x01F9, 0x01FB, 0x01FB, 0x01FD, 0x01FD, 0x01FF, 0x01FF,
+};
+
+/* Lowercase mappings 0200 - 02FF */
+static const WCHAR lblk02[256] = {
+	0x0201, 0x0201, 0x0203, 0x0203, 0x0205, 0x0205, 0x0207, 0x0207,
+	0x0209, 0x0209, 0x020B, 0x020B, 0x020D, 0x020D, 0x020F, 0x020F,
+	0x0211, 0x0211, 0x0213, 0x0213, 0x0215, 0x0215, 0x0217, 0x0217,
+	0x0218, 0x0219, 0x021A, 0x021B, 0x021C, 0x021D, 0x021E, 0x021F,
+	0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0226, 0x0227,
+	0x0228, 0x0229, 0x022A, 0x022B, 0x022C, 0x022D, 0x022E, 0x022F,
+	0x0230, 0x0231, 0x0232, 0x0233, 0x0234, 0x0235, 0x0236, 0x0237,
+	0x0238, 0x0239, 0x023A, 0x023B, 0x023C, 0x023D, 0x023E, 0x023F,
+	0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247,
+	0x0248, 0x0249, 0x024A, 0x024B, 0x024C, 0x024D, 0x024E, 0x024F,
+	0x0250, 0x0251, 0x0252, 0x0253, 0x0254, 0x0255, 0x0256, 0x0257,
+	0x0258, 0x0259, 0x025A, 0x025B, 0x025C, 0x025D, 0x025E, 0x025F,
+	0x0260, 0x0261, 0x0262, 0x0263, 0x0264, 0x0265, 0x0266, 0x0267,
+	0x0268, 0x0269, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x026F,
+	0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277,
+	0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F,
+	0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0286, 0x0287,
+	0x0288, 0x0289, 0x028A, 0x028B, 0x028C, 0x028D, 0x028E, 0x028F,
+	0x0290, 0x0291, 0x0292, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297,
+	0x0298, 0x0299, 0x029A, 0x029B, 0x029C, 0x029D, 0x029E, 0x029F,
+	0x02A0, 0x02A1, 0x02A2, 0x02A3, 0x02A4, 0x02A5, 0x02A6, 0x02A7,
+	0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC, 0x02AD, 0x02AE, 0x02AF,
+	0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6, 0x02B7,
+	0x02B8, 0x02B9, 0x02BA, 0x02BB, 0x02BC, 0x02BD, 0x02BE, 0x02BF,
+	0x02C0, 0x02C1, 0x02C2, 0x02C3, 0x02C4, 0x02C5, 0x02C6, 0x02C7,
+	0x02C8, 0x02C9, 0x02CA, 0x02CB, 0x02CC, 0x02CD, 0x02CE, 0x02CF,
+	0x02D0, 0x02D1, 0x02D2, 0x02D3, 0x02D4, 0x02D5, 0x02D6, 0x02D7,
+	0x02D8, 0x02D9, 0x02DA, 0x02DB, 0x02DC, 0x02DD, 0x02DE, 0x02DF,
+	0x02E0, 0x02E1, 0x02E2, 0x02E3, 0x02E4, 0x02E5, 0x02E6, 0x02E7,
+	0x02E8, 0x02E9, 0x02EA, 0x02EB, 0x02EC, 0x02ED, 0x02EE, 0x02EF,
+	0x02F0, 0x02F1, 0x02F2, 0x02F3, 0x02F4, 0x02F5, 0x02F6, 0x02F7,
+	0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, 0x02FD, 0x02FE, 0x02FF,
+};
+
+/* Lowercase mappings 0300 - 03FF */
+static const WCHAR lblk03[256] = {
+	0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307,
+	0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F,
+	0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317,
+	0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F,
+	0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327,
+	0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F,
+	0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337,
+	0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F,
+	0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347,
+	0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F,
+	0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357,
+	0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F,
+	0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367,
+	0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F,
+	0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377,
+	0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x037F,
+	0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x03AC, 0x0387,
+	0x03AD, 0x03AE, 0x03AF, 0x038B, 0x03CC, 0x038D, 0x03CD, 0x03CE,
+	0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
+	0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+	0x03C0, 0x03C1, 0x03A2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
+	0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
+	0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
+	0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+	0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
+	0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF,
+	0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,
+	0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF,
+	0x03E0, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7,
+	0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,
+	0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7,
+	0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF,
+};
+
+/* Lowercase mappings 0400 - 04FF */
+static const WCHAR lblk04[256] = {
+	0x0400, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
+	0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x040D, 0x045E, 0x045F,
+	0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+	0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+	0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+	0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+	0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+	0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+	0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+	0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+	0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
+	0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F,
+	0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467,
+	0x0469, 0x0469, 0x046B, 0x046B, 0x046D, 0x046D, 0x046F, 0x046F,
+	0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0477, 0x0477,
+	0x0479, 0x0479, 0x047B, 0x047B, 0x047D, 0x047D, 0x047F, 0x047F,
+	0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,
+	0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F,
+	0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497,
+	0x0499, 0x0499, 0x049B, 0x049B, 0x049D, 0x049D, 0x049F, 0x049F,
+	0x04A1, 0x04A1, 0x04A3, 0x04A3, 0x04A5, 0x04A5, 0x04A7, 0x04A7,
+	0x04A9, 0x04A9, 0x04AB, 0x04AB, 0x04AD, 0x04AD, 0x04AF, 0x04AF,
+	0x04B1, 0x04B1, 0x04B3, 0x04B3, 0x04B5, 0x04B5, 0x04B7, 0x04B7,
+	0x04B9, 0x04B9, 0x04BB, 0x04BB, 0x04BD, 0x04BD, 0x04BF, 0x04BF,
+	0x04C0, 0x04C2, 0x04C2, 0x04C4, 0x04C4, 0x04C5, 0x04C6, 0x04C8,
+	0x04C8, 0x04C9, 0x04CA, 0x04CC, 0x04CC, 0x04CD, 0x04CE, 0x04CF,
+	0x04D1, 0x04D1, 0x04D3, 0x04D3, 0x04D5, 0x04D5, 0x04D7, 0x04D7,
+	0x04D9, 0x04D9, 0x04DB, 0x04DB, 0x04DD, 0x04DD, 0x04DF, 0x04DF,
+	0x04E1, 0x04E1, 0x04E3, 0x04E3, 0x04E5, 0x04E5, 0x04E7, 0x04E7,
+	0x04E9, 0x04E9, 0x04EB, 0x04EB, 0x04EC, 0x04ED, 0x04EF, 0x04EF,
+	0x04F1, 0x04F1, 0x04F3, 0x04F3, 0x04F5, 0x04F5, 0x04F6, 0x04F7,
+	0x04F9, 0x04F9, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF,
+};
+
+/* Lowercase mappings 0500 - 05FF */
+static const WCHAR lblk05[256] = {
+	0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507,
+	0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F,
+	0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517,
+	0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F,
+	0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527,
+	0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F,
+	0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
+	0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
+	0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
+	0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
+	0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557,
+	0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F,
+	0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
+	0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
+	0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
+	0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
+	0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587,
+	0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F,
+	0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597,
+	0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F,
+	0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7,
+	0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF,
+	0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
+	0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
+	0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7,
+	0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF,
+	0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
+	0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
+	0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
+	0x05E8, 0x05E9, 0x05EA, 0x05EB, 0x05EC, 0x05ED, 0x05EE, 0x05EF,
+	0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7,
+	0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF,
+};
+
+/* Lowercase mappings 1000 - 10FF */
+static const WCHAR lblk10[256] = {
+	0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
+	0x1008, 0x1009, 0x100A, 0x100B, 0x100C, 0x100D, 0x100E, 0x100F,
+	0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017,
+	0x1018, 0x1019, 0x101A, 0x101B, 0x101C, 0x101D, 0x101E, 0x101F,
+	0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
+	0x1028, 0x1029, 0x102A, 0x102B, 0x102C, 0x102D, 0x102E, 0x102F,
+	0x1030, 0x1031, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037,
+	0x1038, 0x1039, 0x103A, 0x103B, 0x103C, 0x103D, 0x103E, 0x103F,
+	0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047,
+	0x1048, 0x1049, 0x104A, 0x104B, 0x104C, 0x104D, 0x104E, 0x104F,
+	0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057,
+	0x1058, 0x1059, 0x105A, 0x105B, 0x105C, 0x105D, 0x105E, 0x105F,
+	0x1060, 0x1061, 0x1062, 0x1063, 0x1064, 0x1065, 0x1066, 0x1067,
+	0x1068, 0x1069, 0x106A, 0x106B, 0x106C, 0x106D, 0x106E, 0x106F,
+	0x1070, 0x1071, 0x1072, 0x1073, 0x1074, 0x1075, 0x1076, 0x1077,
+	0x1078, 0x1079, 0x107A, 0x107B, 0x107C, 0x107D, 0x107E, 0x107F,
+	0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087,
+	0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F,
+	0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097,
+	0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x109F,
+	0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7,
+	0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF,
+	0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7,
+	0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF,
+	0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10C6, 0x10C7,
+	0x10C8, 0x10C9, 0x10CA, 0x10CB, 0x10CC, 0x10CD, 0x10CE, 0x10CF,
+	0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7,
+	0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF,
+	0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7,
+	0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF,
+	0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10F6, 0x10F7,
+	0x10F8, 0x10F9, 0x10FA, 0x10FB, 0x10FC, 0x10FD, 0x10FE, 0x10FF,
+};
+
+/* Lowercase mappings 1E00 - 1EFF */
+static const WCHAR lblk1E[256] = {
+	0x1E01, 0x1E01, 0x1E03, 0x1E03, 0x1E05, 0x1E05, 0x1E07, 0x1E07,
+	0x1E09, 0x1E09, 0x1E0B, 0x1E0B, 0x1E0D, 0x1E0D, 0x1E0F, 0x1E0F,
+	0x1E11, 0x1E11, 0x1E13, 0x1E13, 0x1E15, 0x1E15, 0x1E17, 0x1E17,
+	0x1E19, 0x1E19, 0x1E1B, 0x1E1B, 0x1E1D, 0x1E1D, 0x1E1F, 0x1E1F,
+	0x1E21, 0x1E21, 0x1E23, 0x1E23, 0x1E25, 0x1E25, 0x1E27, 0x1E27,
+	0x1E29, 0x1E29, 0x1E2B, 0x1E2B, 0x1E2D, 0x1E2D, 0x1E2F, 0x1E2F,
+	0x1E31, 0x1E31, 0x1E33, 0x1E33, 0x1E35, 0x1E35, 0x1E37, 0x1E37,
+	0x1E39, 0x1E39, 0x1E3B, 0x1E3B, 0x1E3D, 0x1E3D, 0x1E3F, 0x1E3F,
+	0x1E41, 0x1E41, 0x1E43, 0x1E43, 0x1E45, 0x1E45, 0x1E47, 0x1E47,
+	0x1E49, 0x1E49, 0x1E4B, 0x1E4B, 0x1E4D, 0x1E4D, 0x1E4F, 0x1E4F,
+	0x1E51, 0x1E51, 0x1E53, 0x1E53, 0x1E55, 0x1E55, 0x1E57, 0x1E57,
+	0x1E59, 0x1E59, 0x1E5B, 0x1E5B, 0x1E5D, 0x1E5D, 0x1E5F, 0x1E5F,
+	0x1E61, 0x1E61, 0x1E63, 0x1E63, 0x1E65, 0x1E65, 0x1E67, 0x1E67,
+	0x1E69, 0x1E69, 0x1E6B, 0x1E6B, 0x1E6D, 0x1E6D, 0x1E6F, 0x1E6F,
+	0x1E71, 0x1E71, 0x1E73, 0x1E73, 0x1E75, 0x1E75, 0x1E77, 0x1E77,
+	0x1E79, 0x1E79, 0x1E7B, 0x1E7B, 0x1E7D, 0x1E7D, 0x1E7F, 0x1E7F,
+	0x1E81, 0x1E81, 0x1E83, 0x1E83, 0x1E85, 0x1E85, 0x1E87, 0x1E87,
+	0x1E89, 0x1E89, 0x1E8B, 0x1E8B, 0x1E8D, 0x1E8D, 0x1E8F, 0x1E8F,
+	0x1E91, 0x1E91, 0x1E93, 0x1E93, 0x1E95, 0x1E95, 0x1E96, 0x1E97,
+	0x1E98, 0x1E99, 0x1E9A, 0x1E9B, 0x1E9C, 0x1E9D, 0x1E9E, 0x1E9F,
+	0x1EA1, 0x1EA1, 0x1EA3, 0x1EA3, 0x1EA5, 0x1EA5, 0x1EA7, 0x1EA7,
+	0x1EA9, 0x1EA9, 0x1EAB, 0x1EAB, 0x1EAD, 0x1EAD, 0x1EAF, 0x1EAF,
+	0x1EB1, 0x1EB1, 0x1EB3, 0x1EB3, 0x1EB5, 0x1EB5, 0x1EB7, 0x1EB7,
+	0x1EB9, 0x1EB9, 0x1EBB, 0x1EBB, 0x1EBD, 0x1EBD, 0x1EBF, 0x1EBF,
+	0x1EC1, 0x1EC1, 0x1EC3, 0x1EC3, 0x1EC5, 0x1EC5, 0x1EC7, 0x1EC7,
+	0x1EC9, 0x1EC9, 0x1ECB, 0x1ECB, 0x1ECD, 0x1ECD, 0x1ECF, 0x1ECF,
+	0x1ED1, 0x1ED1, 0x1ED3, 0x1ED3, 0x1ED5, 0x1ED5, 0x1ED7, 0x1ED7,
+	0x1ED9, 0x1ED9, 0x1EDB, 0x1EDB, 0x1EDD, 0x1EDD, 0x1EDF, 0x1EDF,
+	0x1EE1, 0x1EE1, 0x1EE3, 0x1EE3, 0x1EE5, 0x1EE5, 0x1EE7, 0x1EE7,
+	0x1EE9, 0x1EE9, 0x1EEB, 0x1EEB, 0x1EED, 0x1EED, 0x1EEF, 0x1EEF,
+	0x1EF1, 0x1EF1, 0x1EF3, 0x1EF3, 0x1EF5, 0x1EF5, 0x1EF7, 0x1EF7,
+	0x1EF9, 0x1EF9, 0x1EFA, 0x1EFB, 0x1EFC, 0x1EFD, 0x1EFE, 0x1EFF,
+};
+
+/* Lowercase mappings 1F00 - 1FFF */
+static const WCHAR lblk1F[256] = {
+	0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
+	0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
+	0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x1F16, 0x1F17,
+	0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x1F1E, 0x1F1F,
+	0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,
+	0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,
+	0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,
+	0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,
+	0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x1F46, 0x1F47,
+	0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x1F4E, 0x1F4F,
+	0x1F50, 0x1F51, 0x1F52, 0x1F53, 0x1F54, 0x1F55, 0x1F56, 0x1F57,
+	0x1F58, 0x1F51, 0x1F5A, 0x1F53, 0x1F5C, 0x1F55, 0x1F5E, 0x1F57,
+	0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
+	0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
+	0x1F70, 0x1F71, 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1F76, 0x1F77,
+	0x1F78, 0x1F79, 0x1F7A, 0x1F7B, 0x1F7C, 0x1F7D, 0x1F7E, 0x1F7F,
+	0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,
+	0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,
+	0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,
+	0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,
+	0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,
+	0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,
+	0x1FB0, 0x1FB1, 0x1FB2, 0x1FB3, 0x1FB4, 0x1FB5, 0x1FB6, 0x1FB7,
+	0x1FB0, 0x1FB1, 0x1F70, 0x1F71, 0x1FB3, 0x1FBD, 0x1FBE, 0x1FBF,
+	0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3, 0x1FC4, 0x1FC5, 0x1FC6, 0x1FC7,
+	0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1FC3, 0x1FCD, 0x1FCE, 0x1FCF,
+	0x1FD0, 0x1FD1, 0x1FD2, 0x1FD3, 0x1FD4, 0x1FD5, 0x1FD6, 0x1FD7,
+	0x1FD0, 0x1FD1, 0x1F76, 0x1F77, 0x1FDC, 0x1FDD, 0x1FDE, 0x1FDF,
+	0x1FE0, 0x1FE1, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FE5, 0x1FE6, 0x1FE7,
+	0x1FE0, 0x1FE1, 0x1F7A, 0x1F7B, 0x1FE5, 0x1FED, 0x1FEE, 0x1FEF,
+	0x1FF0, 0x1FF1, 0x1FF2, 0x1FF3, 0x1FF4, 0x1FF5, 0x1FF6, 0x1FF7,
+	0x1F78, 0x1F79, 0x1F7C, 0x1F7D, 0x1FF3, 0x1FFD, 0x1FFE, 0x1FFF,
+};
+
+/* Lowercase mappings 2100 - 21FF */
+static const WCHAR lblk21[256] = {
+	0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107,
+	0x2108, 0x2109, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F,
+	0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117,
+	0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F,
+	0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x2126, 0x2127,
+	0x2128, 0x2129, 0x212A, 0x212B, 0x212C, 0x212D, 0x212E, 0x212F,
+	0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137,
+	0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, 0x213F,
+	0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147,
+	0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F,
+	0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157,
+	0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F,
+	0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
+	0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
+	0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
+	0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
+	0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187,
+	0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, 0x218F,
+	0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197,
+	0x2198, 0x2199, 0x219A, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F,
+	0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7,
+	0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF,
+	0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7,
+	0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF,
+	0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7,
+	0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF,
+	0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7,
+	0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF,
+	0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7,
+	0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF,
+	0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7,
+	0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF,
+};
+
+/* Lowercase mappings 2400 - 24FF */
+static const WCHAR lblk24[256] = {
+	0x2400, 0x2401, 0x2402, 0x2403, 0x2404, 0x2405, 0x2406, 0x2407,
+	0x2408, 0x2409, 0x240A, 0x240B, 0x240C, 0x240D, 0x240E, 0x240F,
+	0x2410, 0x2411, 0x2412, 0x2413, 0x2414, 0x2415, 0x2416, 0x2417,
+	0x2418, 0x2419, 0x241A, 0x241B, 0x241C, 0x241D, 0x241E, 0x241F,
+	0x2420, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427,
+	0x2428, 0x2429, 0x242A, 0x242B, 0x242C, 0x242D, 0x242E, 0x242F,
+	0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437,
+	0x2438, 0x2439, 0x243A, 0x243B, 0x243C, 0x243D, 0x243E, 0x243F,
+	0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447,
+	0x2448, 0x2449, 0x244A, 0x244B, 0x244C, 0x244D, 0x244E, 0x244F,
+	0x2450, 0x2451, 0x2452, 0x2453, 0x2454, 0x2455, 0x2456, 0x2457,
+	0x2458, 0x2459, 0x245A, 0x245B, 0x245C, 0x245D, 0x245E, 0x245F,
+	0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467,
+	0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, 0x246F,
+	0x2470, 0x2471, 0x2472, 0x2473, 0x2474, 0x2475, 0x2476, 0x2477,
+	0x2478, 0x2479, 0x247A, 0x247B, 0x247C, 0x247D, 0x247E, 0x247F,
+	0x2480, 0x2481, 0x2482, 0x2483, 0x2484, 0x2485, 0x2486, 0x2487,
+	0x2488, 0x2489, 0x248A, 0x248B, 0x248C, 0x248D, 0x248E, 0x248F,
+	0x2490, 0x2491, 0x2492, 0x2493, 0x2494, 0x2495, 0x2496, 0x2497,
+	0x2498, 0x2499, 0x249A, 0x249B, 0x249C, 0x249D, 0x249E, 0x249F,
+	0x24A0, 0x24A1, 0x24A2, 0x24A3, 0x24A4, 0x24A5, 0x24A6, 0x24A7,
+	0x24A8, 0x24A9, 0x24AA, 0x24AB, 0x24AC, 0x24AD, 0x24AE, 0x24AF,
+	0x24B0, 0x24B1, 0x24B2, 0x24B3, 0x24B4, 0x24B5, 0x24D0, 0x24D1,
+	0x24D2, 0x24D3, 0x24D4, 0x24D5, 0x24D6, 0x24D7, 0x24D8, 0x24D9,
+	0x24DA, 0x24DB, 0x24DC, 0x24DD, 0x24DE, 0x24DF, 0x24E0, 0x24E1,
+	0x24E2, 0x24E3, 0x24E4, 0x24E5, 0x24E6, 0x24E7, 0x24E8, 0x24E9,
+	0x24D0, 0x24D1, 0x24D2, 0x24D3, 0x24D4, 0x24D5, 0x24D6, 0x24D7,
+	0x24D8, 0x24D9, 0x24DA, 0x24DB, 0x24DC, 0x24DD, 0x24DE, 0x24DF,
+	0x24E0, 0x24E1, 0x24E2, 0x24E3, 0x24E4, 0x24E5, 0x24E6, 0x24E7,
+	0x24E8, 0x24E9, 0x24EA, 0x24EB, 0x24EC, 0x24ED, 0x24EE, 0x24EF,
+	0x24F0, 0x24F1, 0x24F2, 0x24F3, 0x24F4, 0x24F5, 0x24F6, 0x24F7,
+	0x24F8, 0x24F9, 0x24FA, 0x24FB, 0x24FC, 0x24FD, 0x24FE, 0x24FF,
+};
+
+/* Lowercase mappings FF00 - FFFF */
+static const WCHAR lblkFF[256] = {
+	0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07,
+	0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F,
+	0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17,
+	0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F,
+	0xFF20, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
+	0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
+	0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
+	0xFF58, 0xFF59, 0xFF5A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F,
+	0xFF40, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
+	0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
+	0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
+	0xFF58, 0xFF59, 0xFF5A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F,
+	0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67,
+	0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F,
+	0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77,
+	0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F,
+	0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87,
+	0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F,
+	0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97,
+	0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F,
+	0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7,
+	0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF,
+	0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7,
+	0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF,
+	0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7,
+	0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF,
+	0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7,
+	0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF,
+	0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7,
+	0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF,
+	0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7,
+	0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF,
+};
+
+static const WCHAR * const lwrtable[256] = {
+	lblk00, lblk01, lblk02, lblk03, lblk04, lblk05, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	lblk10, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, lblk1E, lblk1F,
+	000000, lblk21, 000000, 000000, lblk24, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, lblkFF,
+};
+
+/* Uppercase mappings 0000 - 00FF */
+static const WCHAR ublk00[256] = {
+	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+	0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+	0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+	0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+	0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+	0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+	0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+	0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+	0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+	0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+	0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+	0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+	0x0060, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+	0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+	0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+	0x0058, 0x0059, 0x005A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+	0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+	0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+	0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+	0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+	0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+	0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+	0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+	0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+	0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+	0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+	0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+	0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+	0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+	0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+	0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00F7,
+	0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x0178,
+};
+
+/* Uppercase mappings 0100 - 01FF */
+static const WCHAR ublk01[256] = {
+	0x0100, 0x0100, 0x0102, 0x0102, 0x0104, 0x0104, 0x0106, 0x0106,
+	0x0108, 0x0108, 0x010A, 0x010A, 0x010C, 0x010C, 0x010E, 0x010E,
+	0x0110, 0x0110, 0x0112, 0x0112, 0x0114, 0x0114, 0x0116, 0x0116,
+	0x0118, 0x0118, 0x011A, 0x011A, 0x011C, 0x011C, 0x011E, 0x011E,
+	0x0120, 0x0120, 0x0122, 0x0122, 0x0124, 0x0124, 0x0126, 0x0126,
+	0x0128, 0x0128, 0x012A, 0x012A, 0x012C, 0x012C, 0x012E, 0x012E,
+	0x0130, 0x0049, 0x0132, 0x0132, 0x0134, 0x0134, 0x0136, 0x0136,
+	0x0138, 0x0139, 0x0139, 0x013B, 0x013B, 0x013D, 0x013D, 0x013F,
+	0x013F, 0x0141, 0x0141, 0x0143, 0x0143, 0x0145, 0x0145, 0x0147,
+	0x0147, 0x0149, 0x014A, 0x014A, 0x014C, 0x014C, 0x014E, 0x014E,
+	0x0150, 0x0150, 0x0152, 0x0152, 0x0154, 0x0154, 0x0156, 0x0156,
+	0x0158, 0x0158, 0x015A, 0x015A, 0x015C, 0x015C, 0x015E, 0x015E,
+	0x0160, 0x0160, 0x0162, 0x0162, 0x0164, 0x0164, 0x0166, 0x0166,
+	0x0168, 0x0168, 0x016A, 0x016A, 0x016C, 0x016C, 0x016E, 0x016E,
+	0x0170, 0x0170, 0x0172, 0x0172, 0x0174, 0x0174, 0x0176, 0x0176,
+	0x0178, 0x0179, 0x0179, 0x017B, 0x017B, 0x017D, 0x017D, 0x0053,
+	0x0180, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187,
+	0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F,
+	0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x0195, 0x0196, 0x0197,
+	0x0198, 0x0198, 0x019A, 0x019B, 0x019C, 0x019D, 0x019E, 0x019F,
+	0x01A0, 0x01A0, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7,
+	0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x01AF,
+	0x01AF, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7,
+	0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01BF,
+	0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C4, 0x01C4, 0x01C7,
+	0x01C7, 0x01C7, 0x01CA, 0x01CA, 0x01CA, 0x01CD, 0x01CD, 0x01CF,
+	0x01CF, 0x01D1, 0x01D1, 0x01D3, 0x01D3, 0x01D5, 0x01D5, 0x01D7,
+	0x01D7, 0x01D9, 0x01D9, 0x01DB, 0x01DB, 0x01DD, 0x01DE, 0x01DE,
+	0x01E0, 0x01E0, 0x01E2, 0x01E2, 0x01E4, 0x01E4, 0x01E6, 0x01E6,
+	0x01E8, 0x01E8, 0x01EA, 0x01EA, 0x01EC, 0x01EC, 0x01EE, 0x01EE,
+	0x01F0, 0x01F1, 0x01F1, 0x01F1, 0x01F4, 0x01F4, 0x01F6, 0x01F7,
+	0x01F8, 0x01F9, 0x01FA, 0x01FA, 0x01FC, 0x01FC, 0x01FE, 0x01FE,
+};
+
+/* Uppercase mappings 0200 - 02FF */
+static const WCHAR ublk02[256] = {
+	0x0200, 0x0200, 0x0202, 0x0202, 0x0204, 0x0204, 0x0206, 0x0206,
+	0x0208, 0x0208, 0x020A, 0x020A, 0x020C, 0x020C, 0x020E, 0x020E,
+	0x0210, 0x0210, 0x0212, 0x0212, 0x0214, 0x0214, 0x0216, 0x0216,
+	0x0218, 0x0219, 0x021A, 0x021B, 0x021C, 0x021D, 0x021E, 0x021F,
+	0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0226, 0x0227,
+	0x0228, 0x0229, 0x022A, 0x022B, 0x022C, 0x022D, 0x022E, 0x022F,
+	0x0230, 0x0231, 0x0232, 0x0233, 0x0234, 0x0235, 0x0236, 0x0237,
+	0x0238, 0x0239, 0x023A, 0x023B, 0x023C, 0x023D, 0x023E, 0x023F,
+	0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247,
+	0x0248, 0x0249, 0x024A, 0x024B, 0x024C, 0x024D, 0x024E, 0x024F,
+	0x0250, 0x0251, 0x0252, 0x0181, 0x0186, 0x0255, 0x0189, 0x018A,
+	0x018E, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F,
+	0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267,
+	0x0197, 0x0196, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x019C,
+	0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277,
+	0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F,
+	0x0280, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287,
+	0x01AE, 0x0289, 0x01B1, 0x01B2, 0x028C, 0x028D, 0x028E, 0x028F,
+	0x0290, 0x0291, 0x01B7, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297,
+	0x0298, 0x0299, 0x029A, 0x029B, 0x029C, 0x029D, 0x029E, 0x029F,
+	0x02A0, 0x02A1, 0x02A2, 0x02A3, 0x02A4, 0x02A5, 0x02A6, 0x02A7,
+	0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC, 0x02AD, 0x02AE, 0x02AF,
+	0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6, 0x02B7,
+	0x02B8, 0x02B9, 0x02BA, 0x02BB, 0x02BC, 0x02BD, 0x02BE, 0x02BF,
+	0x02C0, 0x02C1, 0x02C2, 0x02C3, 0x02C4, 0x02C5, 0x02C6, 0x02C7,
+	0x02C8, 0x02C9, 0x02CA, 0x02CB, 0x02CC, 0x02CD, 0x02CE, 0x02CF,
+	0x02D0, 0x02D1, 0x02D2, 0x02D3, 0x02D4, 0x02D5, 0x02D6, 0x02D7,
+	0x02D8, 0x02D9, 0x02DA, 0x02DB, 0x02DC, 0x02DD, 0x02DE, 0x02DF,
+	0x02E0, 0x02E1, 0x02E2, 0x02E3, 0x02E4, 0x02E5, 0x02E6, 0x02E7,
+	0x02E8, 0x02E9, 0x02EA, 0x02EB, 0x02EC, 0x02ED, 0x02EE, 0x02EF,
+	0x02F0, 0x02F1, 0x02F2, 0x02F3, 0x02F4, 0x02F5, 0x02F6, 0x02F7,
+	0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, 0x02FD, 0x02FE, 0x02FF,
+};
+
+/* Uppercase mappings 0300 - 03FF */
+static const WCHAR ublk03[256] = {
+	0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307,
+	0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F,
+	0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317,
+	0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F,
+	0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327,
+	0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F,
+	0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337,
+	0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F,
+	0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347,
+	0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F,
+	0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357,
+	0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F,
+	0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367,
+	0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F,
+	0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377,
+	0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x037F,
+	0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387,
+	0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F,
+	0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+	0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+	0x03A0, 0x03A1, 0x03A2, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
+	0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x0386, 0x0388, 0x0389, 0x038A,
+	0x03B0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+	0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+	0x03A0, 0x03A1, 0x03C2, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
+	0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x03CF,
+	0x0392, 0x0398, 0x03D2, 0x03D3, 0x03D4, 0x03A6, 0x03A0, 0x03D7,
+	0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF,
+	0x03E0, 0x03E1, 0x03E2, 0x03E2, 0x03E4, 0x03E4, 0x03E6, 0x03E6,
+	0x03E8, 0x03E8, 0x03EA, 0x03EA, 0x03EC, 0x03EC, 0x03EE, 0x03EE,
+	0x039A, 0x03A1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7,
+	0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF,
+};
+
+/* Uppercase mappings 0400 - 04FF */
+static const WCHAR ublk04[256] = {
+	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
+	0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040D, 0x040E, 0x040F,
+	0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+	0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
+	0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+	0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+	0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+	0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
+	0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+	0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+	0x0450, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
+	0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x045D, 0x040E, 0x040F,
+	0x0460, 0x0460, 0x0462, 0x0462, 0x0464, 0x0464, 0x0466, 0x0466,
+	0x0468, 0x0468, 0x046A, 0x046A, 0x046C, 0x046C, 0x046E, 0x046E,
+	0x0470, 0x0470, 0x0472, 0x0472, 0x0474, 0x0474, 0x0476, 0x0476,
+	0x0478, 0x0478, 0x047A, 0x047A, 0x047C, 0x047C, 0x047E, 0x047E,
+	0x0480, 0x0480, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,
+	0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F,
+	0x0490, 0x0490, 0x0492, 0x0492, 0x0494, 0x0494, 0x0496, 0x0496,
+	0x0498, 0x0498, 0x049A, 0x049A, 0x049C, 0x049C, 0x049E, 0x049E,
+	0x04A0, 0x04A0, 0x04A2, 0x04A2, 0x04A4, 0x04A4, 0x04A6, 0x04A6,
+	0x04A8, 0x04A8, 0x04AA, 0x04AA, 0x04AC, 0x04AC, 0x04AE, 0x04AE,
+	0x04B0, 0x04B0, 0x04B2, 0x04B2, 0x04B4, 0x04B4, 0x04B6, 0x04B6,
+	0x04B8, 0x04B8, 0x04BA, 0x04BA, 0x04BC, 0x04BC, 0x04BE, 0x04BE,
+	0x04C0, 0x04C1, 0x04C1, 0x04C3, 0x04C3, 0x04C5, 0x04C6, 0x04C7,
+	0x04C7, 0x04C9, 0x04CA, 0x04CB, 0x04CB, 0x04CD, 0x04CE, 0x04CF,
+	0x04D0, 0x04D0, 0x04D2, 0x04D2, 0x04D4, 0x04D4, 0x04D6, 0x04D6,
+	0x04D8, 0x04D8, 0x04DA, 0x04DA, 0x04DC, 0x04DC, 0x04DE, 0x04DE,
+	0x04E0, 0x04E0, 0x04E2, 0x04E2, 0x04E4, 0x04E4, 0x04E6, 0x04E6,
+	0x04E8, 0x04E8, 0x04EA, 0x04EA, 0x04EC, 0x04ED, 0x04EE, 0x04EE,
+	0x04F0, 0x04F0, 0x04F2, 0x04F2, 0x04F4, 0x04F4, 0x04F6, 0x04F7,
+	0x04F8, 0x04F8, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF,
+};
+
+/* Uppercase mappings 0500 - 05FF */
+static const WCHAR ublk05[256] = {
+	0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507,
+	0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F,
+	0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517,
+	0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F,
+	0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527,
+	0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F,
+	0x0530, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537,
+	0x0538, 0x0539, 0x053A, 0x053B, 0x053C, 0x053D, 0x053E, 0x053F,
+	0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547,
+	0x0548, 0x0549, 0x054A, 0x054B, 0x054C, 0x054D, 0x054E, 0x054F,
+	0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0557,
+	0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F,
+	0x0560, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537,
+	0x0538, 0x0539, 0x053A, 0x053B, 0x053C, 0x053D, 0x053E, 0x053F,
+	0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547,
+	0x0548, 0x0549, 0x054A, 0x054B, 0x054C, 0x054D, 0x054E, 0x054F,
+	0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0587,
+	0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F,
+	0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597,
+	0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F,
+	0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7,
+	0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF,
+	0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
+	0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
+	0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7,
+	0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF,
+	0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
+	0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
+	0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
+	0x05E8, 0x05E9, 0x05EA, 0x05EB, 0x05EC, 0x05ED, 0x05EE, 0x05EF,
+	0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7,
+	0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF,
+};
+
+/* Uppercase mappings 1E00 - 1EFF */
+static const WCHAR ublk1E[256] = {
+	0x1E00, 0x1E00, 0x1E02, 0x1E02, 0x1E04, 0x1E04, 0x1E06, 0x1E06,
+	0x1E08, 0x1E08, 0x1E0A, 0x1E0A, 0x1E0C, 0x1E0C, 0x1E0E, 0x1E0E,
+	0x1E10, 0x1E10, 0x1E12, 0x1E12, 0x1E14, 0x1E14, 0x1E16, 0x1E16,
+	0x1E18, 0x1E18, 0x1E1A, 0x1E1A, 0x1E1C, 0x1E1C, 0x1E1E, 0x1E1E,
+	0x1E20, 0x1E20, 0x1E22, 0x1E22, 0x1E24, 0x1E24, 0x1E26, 0x1E26,
+	0x1E28, 0x1E28, 0x1E2A, 0x1E2A, 0x1E2C, 0x1E2C, 0x1E2E, 0x1E2E,
+	0x1E30, 0x1E30, 0x1E32, 0x1E32, 0x1E34, 0x1E34, 0x1E36, 0x1E36,
+	0x1E38, 0x1E38, 0x1E3A, 0x1E3A, 0x1E3C, 0x1E3C, 0x1E3E, 0x1E3E,
+	0x1E40, 0x1E40, 0x1E42, 0x1E42, 0x1E44, 0x1E44, 0x1E46, 0x1E46,
+	0x1E48, 0x1E48, 0x1E4A, 0x1E4A, 0x1E4C, 0x1E4C, 0x1E4E, 0x1E4E,
+	0x1E50, 0x1E50, 0x1E52, 0x1E52, 0x1E54, 0x1E54, 0x1E56, 0x1E56,
+	0x1E58, 0x1E58, 0x1E5A, 0x1E5A, 0x1E5C, 0x1E5C, 0x1E5E, 0x1E5E,
+	0x1E60, 0x1E60, 0x1E62, 0x1E62, 0x1E64, 0x1E64, 0x1E66, 0x1E66,
+	0x1E68, 0x1E68, 0x1E6A, 0x1E6A, 0x1E6C, 0x1E6C, 0x1E6E, 0x1E6E,
+	0x1E70, 0x1E70, 0x1E72, 0x1E72, 0x1E74, 0x1E74, 0x1E76, 0x1E76,
+	0x1E78, 0x1E78, 0x1E7A, 0x1E7A, 0x1E7C, 0x1E7C, 0x1E7E, 0x1E7E,
+	0x1E80, 0x1E80, 0x1E82, 0x1E82, 0x1E84, 0x1E84, 0x1E86, 0x1E86,
+	0x1E88, 0x1E88, 0x1E8A, 0x1E8A, 0x1E8C, 0x1E8C, 0x1E8E, 0x1E8E,
+	0x1E90, 0x1E90, 0x1E92, 0x1E92, 0x1E94, 0x1E94, 0x1E96, 0x1E97,
+	0x1E98, 0x1E99, 0x1E9A, 0x1E9B, 0x1E9C, 0x1E9D, 0x1E9E, 0x1E9F,
+	0x1EA0, 0x1EA0, 0x1EA2, 0x1EA2, 0x1EA4, 0x1EA4, 0x1EA6, 0x1EA6,
+	0x1EA8, 0x1EA8, 0x1EAA, 0x1EAA, 0x1EAC, 0x1EAC, 0x1EAE, 0x1EAE,
+	0x1EB0, 0x1EB0, 0x1EB2, 0x1EB2, 0x1EB4, 0x1EB4, 0x1EB6, 0x1EB6,
+	0x1EB8, 0x1EB8, 0x1EBA, 0x1EBA, 0x1EBC, 0x1EBC, 0x1EBE, 0x1EBE,
+	0x1EC0, 0x1EC0, 0x1EC2, 0x1EC2, 0x1EC4, 0x1EC4, 0x1EC6, 0x1EC6,
+	0x1EC8, 0x1EC8, 0x1ECA, 0x1ECA, 0x1ECC, 0x1ECC, 0x1ECE, 0x1ECE,
+	0x1ED0, 0x1ED0, 0x1ED2, 0x1ED2, 0x1ED4, 0x1ED4, 0x1ED6, 0x1ED6,
+	0x1ED8, 0x1ED8, 0x1EDA, 0x1EDA, 0x1EDC, 0x1EDC, 0x1EDE, 0x1EDE,
+	0x1EE0, 0x1EE0, 0x1EE2, 0x1EE2, 0x1EE4, 0x1EE4, 0x1EE6, 0x1EE6,
+	0x1EE8, 0x1EE8, 0x1EEA, 0x1EEA, 0x1EEC, 0x1EEC, 0x1EEE, 0x1EEE,
+	0x1EF0, 0x1EF0, 0x1EF2, 0x1EF2, 0x1EF4, 0x1EF4, 0x1EF6, 0x1EF6,
+	0x1EF8, 0x1EF8, 0x1EFA, 0x1EFB, 0x1EFC, 0x1EFD, 0x1EFE, 0x1EFF,
+};
+
+/* Uppercase mappings 1F00 - 1FFF */
+static const WCHAR ublk1F[256] = {
+	0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,
+	0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,
+	0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x1F16, 0x1F17,
+	0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x1F1E, 0x1F1F,
+	0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,
+	0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,
+	0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,
+	0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,
+	0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x1F46, 0x1F47,
+	0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x1F4E, 0x1F4F,
+	0x1F50, 0x1F59, 0x1F52, 0x1F5B, 0x1F54, 0x1F5D, 0x1F56, 0x1F5F,
+	0x1F58, 0x1F59, 0x1F5A, 0x1F5B, 0x1F5C, 0x1F5D, 0x1F5E, 0x1F5F,
+	0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,
+	0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,
+	0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB,
+	0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, 0x1F7E, 0x1F7F,
+	0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,
+	0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,
+	0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,
+	0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,
+	0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,
+	0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,
+	0x1FB8, 0x1FB9, 0x1FB2, 0x1FBC, 0x1FB4, 0x1FB5, 0x1FB6, 0x1FB7,
+	0x1FB8, 0x1FB9, 0x1FBA, 0x1FBB, 0x1FBC, 0x1FBD, 0x1FBE, 0x1FBF,
+	0x1FC0, 0x1FC1, 0x1FC2, 0x1FCC, 0x1FC4, 0x1FC5, 0x1FC6, 0x1FC7,
+	0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FCC, 0x1FCD, 0x1FCE, 0x1FCF,
+	0x1FD8, 0x1FD9, 0x1FD2, 0x1FD3, 0x1FD4, 0x1FD5, 0x1FD6, 0x1FD7,
+	0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB, 0x1FDC, 0x1FDD, 0x1FDE, 0x1FDF,
+	0x1FE8, 0x1FE9, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FEC, 0x1FE6, 0x1FE7,
+	0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB, 0x1FEC, 0x1FED, 0x1FEE, 0x1FEF,
+	0x1FF0, 0x1FF1, 0x1FF2, 0x1FFC, 0x1FF4, 0x1FF5, 0x1FF6, 0x1FF7,
+	0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB, 0x1FFC, 0x1FFD, 0x1FFE, 0x1FFF,
+};
+
+/* Uppercase mappings 2100 - 21FF */
+static const WCHAR ublk21[256] = {
+	0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107,
+	0x2108, 0x2109, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F,
+	0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117,
+	0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F,
+	0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x2126, 0x2127,
+	0x2128, 0x2129, 0x212A, 0x212B, 0x212C, 0x212D, 0x212E, 0x212F,
+	0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137,
+	0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, 0x213F,
+	0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147,
+	0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F,
+	0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157,
+	0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F,
+	0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167,
+	0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F,
+	0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167,
+	0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F,
+	0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187,
+	0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, 0x218F,
+	0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197,
+	0x2198, 0x2199, 0x219A, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F,
+	0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7,
+	0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF,
+	0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7,
+	0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF,
+	0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7,
+	0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF,
+	0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7,
+	0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF,
+	0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7,
+	0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF,
+	0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7,
+	0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF,
+};
+
+/* Uppercase mappings 2400 - 24FF */
+static const WCHAR ublk24[256] = {
+	0x2400, 0x2401, 0x2402, 0x2403, 0x2404, 0x2405, 0x2406, 0x2407,
+	0x2408, 0x2409, 0x240A, 0x240B, 0x240C, 0x240D, 0x240E, 0x240F,
+	0x2410, 0x2411, 0x2412, 0x2413, 0x2414, 0x2415, 0x2416, 0x2417,
+	0x2418, 0x2419, 0x241A, 0x241B, 0x241C, 0x241D, 0x241E, 0x241F,
+	0x2420, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427,
+	0x2428, 0x2429, 0x242A, 0x242B, 0x242C, 0x242D, 0x242E, 0x242F,
+	0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437,
+	0x2438, 0x2439, 0x243A, 0x243B, 0x243C, 0x243D, 0x243E, 0x243F,
+	0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447,
+	0x2448, 0x2449, 0x244A, 0x244B, 0x244C, 0x244D, 0x244E, 0x244F,
+	0x2450, 0x2451, 0x2452, 0x2453, 0x2454, 0x2455, 0x2456, 0x2457,
+	0x2458, 0x2459, 0x245A, 0x245B, 0x245C, 0x245D, 0x245E, 0x245F,
+	0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467,
+	0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, 0x246F,
+	0x2470, 0x2471, 0x2472, 0x2473, 0x2474, 0x2475, 0x2476, 0x2477,
+	0x2478, 0x2479, 0x247A, 0x247B, 0x247C, 0x247D, 0x247E, 0x247F,
+	0x2480, 0x2481, 0x2482, 0x2483, 0x2484, 0x2485, 0x2486, 0x2487,
+	0x2488, 0x2489, 0x248A, 0x248B, 0x248C, 0x248D, 0x248E, 0x248F,
+	0x2490, 0x2491, 0x2492, 0x2493, 0x2494, 0x2495, 0x2496, 0x2497,
+	0x2498, 0x2499, 0x249A, 0x249B, 0x249C, 0x249D, 0x249E, 0x249F,
+	0x24A0, 0x24A1, 0x24A2, 0x24A3, 0x24A4, 0x24A5, 0x24A6, 0x24A7,
+	0x24A8, 0x24A9, 0x24AA, 0x24AB, 0x24AC, 0x24AD, 0x24AE, 0x24AF,
+	0x24B0, 0x24B1, 0x24B2, 0x24B3, 0x24B4, 0x24B5, 0x24B6, 0x24B7,
+	0x24B8, 0x24B9, 0x24BA, 0x24BB, 0x24BC, 0x24BD, 0x24BE, 0x24BF,
+	0x24C0, 0x24C1, 0x24C2, 0x24C3, 0x24C4, 0x24C5, 0x24C6, 0x24C7,
+	0x24C8, 0x24C9, 0x24CA, 0x24CB, 0x24CC, 0x24CD, 0x24CE, 0x24CF,
+	0x24B6, 0x24B7, 0x24B8, 0x24B9, 0x24BA, 0x24BB, 0x24BC, 0x24BD,
+	0x24BE, 0x24BF, 0x24C0, 0x24C1, 0x24C2, 0x24C3, 0x24C4, 0x24C5,
+	0x24C6, 0x24C7, 0x24C8, 0x24C9, 0x24CA, 0x24CB, 0x24CC, 0x24CD,
+	0x24CE, 0x24CF, 0x24EA, 0x24EB, 0x24EC, 0x24ED, 0x24EE, 0x24EF,
+	0x24F0, 0x24F1, 0x24F2, 0x24F3, 0x24F4, 0x24F5, 0x24F6, 0x24F7,
+	0x24F8, 0x24F9, 0x24FA, 0x24FB, 0x24FC, 0x24FD, 0x24FE, 0x24FF,
+};
+
+/* Uppercase mappings FF00 - FFFF */
+static const WCHAR ublkFF[256] = {
+	0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07,
+	0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F,
+	0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17,
+	0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F,
+	0xFF20, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27,
+	0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F,
+	0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37,
+	0xFF38, 0xFF39, 0xFF3A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F,
+	0xFF40, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27,
+	0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F,
+	0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37,
+	0xFF38, 0xFF39, 0xFF3A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F,
+	0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67,
+	0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F,
+	0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77,
+	0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F,
+	0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87,
+	0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F,
+	0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97,
+	0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F,
+	0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7,
+	0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF,
+	0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7,
+	0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF,
+	0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7,
+	0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF,
+	0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7,
+	0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF,
+	0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7,
+	0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF,
+	0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7,
+	0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF,
+};
+
+static const WCHAR * const uprtable[256] = {
+	ublk00, ublk01, ublk02, ublk03, ublk04, ublk05, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, ublk1E, ublk1F,
+	000000, ublk21, 000000, 000000, ublk24, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
+	000000, 000000, 000000, 000000, 000000, 000000, 000000, ublkFF,
+};
+
diff --git a/include/commctrl.h b/include/commctrl.h
index a2670e8..c57c992 100644
--- a/include/commctrl.h
+++ b/include/commctrl.h
@@ -192,14 +192,12 @@
  
 /* Functions prototypes */
 
-HWND16     WINAPI CreateStatusWindow16(INT16,LPCSTR,HWND16,UINT16);
 HWND32     WINAPI CreateStatusWindow32A(INT32,LPCSTR,HWND32,UINT32);
 HWND32     WINAPI CreateStatusWindow32W(INT32,LPCWSTR,HWND32,UINT32);
 #define    CreateStatusWindow WINELIB_NAME_AW(CreateStatusWindow)
 HWND32     WINAPI CreateUpDownControl(DWORD,INT32,INT32,INT32,INT32,
                                       HWND32,INT32,HINSTANCE32,HWND32,
                                       INT32,INT32,INT32);
-VOID       WINAPI DrawStatusText16(HDC16,LPRECT16,LPCSTR,UINT16);
 VOID       WINAPI DrawStatusText32A(HDC32,LPRECT32,LPCSTR,UINT32);
 VOID       WINAPI DrawStatusText32W(HDC32,LPRECT32,LPCWSTR,UINT32);
 #define    DrawStatusText WINELIB_NAME_AW(DrawStatusText)
@@ -276,6 +274,7 @@
 
  
 INT32      WINAPI ImageList_Add(HIMAGELIST,HBITMAP32,HBITMAP32);
+INT32      WINAPI ImageList_AddIcon (HIMAGELIST, HICON32);
 INT32      WINAPI ImageList_AddMasked(HIMAGELIST,HBITMAP32,COLORREF);
 BOOL32     WINAPI ImageList_BeginDrag(HIMAGELIST,INT32,INT32,INT32);
 BOOL32     WINAPI ImageList_Copy(HIMAGELIST,INT32,HIMAGELIST,INT32,INT32);
@@ -284,7 +283,7 @@
 BOOL32     WINAPI ImageList_DragEnter(HWND32,INT32,INT32);
 BOOL32     WINAPI ImageList_DragLeave(HWND32); 
 BOOL32     WINAPI ImageList_DragMove(INT32,INT32);
-BOOL32     WINAPI ImageList_DragShowNolock (BOOL32 bShow);
+BOOL32     WINAPI ImageList_DragShowNolock (BOOL32);
 BOOL32     WINAPI ImageList_Draw(HIMAGELIST,INT32,HDC32,INT32,INT32,UINT32);
 BOOL32     WINAPI ImageList_DrawEx(HIMAGELIST,INT32,HDC32,INT32,INT32,INT32,
                                    INT32,COLORREF,COLORREF,UINT32);
@@ -304,18 +303,25 @@
                                          COLORREF,UINT32,UINT32);
 #define    ImageList_LoadImage WINELIB_NAME_AW(ImageList_LoadImage)
 HIMAGELIST WINAPI ImageList_Merge(HIMAGELIST,INT32,HIMAGELIST,INT32,INT32,INT32);
-
+#ifdef __IStream_INTREFACE_DEFINED__
+HIMAGELIST WINAPI ImageList_Read (LPSTREAM32);
+#endif
 BOOL32     WINAPI ImageList_Remove(HIMAGELIST,INT32);
 BOOL32     WINAPI ImageList_Replace(HIMAGELIST,INT32,HBITMAP32,HBITMAP32);
 INT32      WINAPI ImageList_ReplaceIcon(HIMAGELIST,INT32,HICON32);
-
 COLORREF   WINAPI ImageList_SetBkColor(HIMAGELIST,COLORREF);
 BOOL32     WINAPI ImageList_SetDragCursorImage(HIMAGELIST,INT32,INT32,INT32);
+
 BOOL32     WINAPI ImageList_SetIconSize (HIMAGELIST,INT32,INT32);
 BOOL32     WINAPI ImageList_SetImageCount (HIMAGELIST,INT32);
 BOOL32     WINAPI ImageList_SetOverlayImage(HIMAGELIST,INT32,INT32);
+#ifdef __IStream_INTREFACE_DEFINED__
+BOOL32     WINAPI ImageList_Write (HIMAGELIST, LPSTREAM32);
+#endif
 
+#ifndef __WINE__
 #define ImageList_AddIcon(himl,hicon) ImageList_ReplaceIcon(himl,-1,hicon)
+#endif
 #define ImageList_ExtractIcon(hi,himl,i) ImageList_GetIcon(himl,i,0)
 #define ImageList_LoadBitmap(hi,lpbmp,cx,cGrow,crMask) \
   ImageList_LoadImage(hi,lpbmp,cx,cGrow,crMask,IMAGE_BITMAP,0)
@@ -415,11 +421,6 @@
 #define HDN_BEGINDRACK          (HDN_FIRST-10)
 #define HDN_ENDDRACK            (HDN_FIRST-11)
 
-
-#define Header_Layout(hwndHD,playout) \
-  (BOOL32)SendMessage32A((hwndHD),HDM_LAYOUT,0,(LPARAM)(LPHDLAYOUT)(playout))
-
-
 typedef struct _HD_LAYOUT
 {
     RECT32      *prc;
@@ -428,7 +429,6 @@
 
 #define HD_LAYOUT   HDLAYOUT
 
-
 typedef struct _HD_ITEMA
 {
     UINT32    mask;
@@ -442,7 +442,6 @@
     INT32     iOrder;
 } HD_ITEMA;
 
-
 typedef struct _HD_HITTESTINFO
 {
     POINT32 pt;
@@ -452,7 +451,6 @@
 
 #define HD_HITTESTINFO   HDHITTESTINFO
 
-
 typedef struct tagNMHEADERA
 {
     NMHDR    hdr;
@@ -462,4 +460,191 @@
 } NMHEADERA, *LPNMHEADERA;
 
 
+#define Header_GetItemCount(hwndHD) \
+  (INT32)SendMessage32A((hwndHD),HDM_GETITEMCOUNT,0,0L)
+#define Header_InsertItem(hwndHD,i,phdi) \
+  (INT32)SendMessage32A((hwndHD),HDM_INSERTITEM,(WPARAM32)(INT32)(i),\
+			(LPARAM)(const HD_ITEMA*)(phdi))
+#define Header_DeleteItem(hwndHD,i) \
+  (BOOL32)SendMessage32A((hwndHD),HDM_DELETEITEM,(WPARAM32)(INT32)(i),0L)
+#define Header_GetItem(hwndHD,i,phdi) \
+  (BOOL32)SendMessage32A((hwndHD),HDM_GETITEM,(WPARAM32)(INT32)(i),(LPARAM)(HD_ITEMA*)(phdi))
+#define Header_SetItem(hwndHD,i,phdi) \
+  (BOOL32)SendMessage32A((hwndHD),HDM_SETITEM,(WPARAM32)(INT32)(i),(LPARAM)(const HD_ITEMA*)(phdi))
+#define Header_Layout(hwndHD,playout) \
+  (BOOL32)SendMessage32A((hwndHD),HDM_LAYOUT,0,(LPARAM)(LPHDLAYOUT)(playout))
+#define Header_GetItemRect(hwnd,iItem,lprc) \
+  (BOOL32)SendMessage32A((hwnd),HDM_GETITEMRECT,(WPARAM32)iItem,(LPARAM)lprc)
+#define Header_SetImageList(hwnd,himl) \
+  (HIMAGELIST)SendMessage32A((hwnd),HDM_SETIMAGELIST,0,(LPARAM)himl)
+#define Header_GetImageList(hwnd) \
+  (HIMAGELIST)SendMessage32A((hwnd),HDM_GETIMAGELIST,0,0)
+#define Header_OrderToIndex(hwnd,i) \
+  (INT32)SendMessage32A((hwnd),HDM_ORDERTOINDEX,(WPARAM32)i,0)
+#define Header_CreateDragImage(hwnd,i) \
+  (HIMAGELIST)SendMessage32A((hwnd),HDM_CREATEDRAGIMAGE,(WPARAM32)i,0)
+#define Header_GetOrderArray(hwnd,iCount,lpi) \
+  (BOOL32)SendMessage32A((hwnd),HDM_GETORDERARRAY,(WPARAM32)iCount,(LPARAM)lpi)
+#define Header_SetOrderArray(hwnd,iCount,lpi) \
+  (BOOL32)SendMessage32A((hwnd),HDM_SETORDERARRAY,(WPARAM32)iCount,(LPARAM)lpi)
+#define Header_SetHotDivider(hwnd,fPos,dw) \
+  (INT32)SendMessage32A((hwnd),HDM_SETHOTDIVIDER,(WPARAM32)fPos,(LPARAM)dw)
+#define Header_SetUnicodeFormat(hwnd,fUnicode) \
+  (BOOL32)SendMessage32A((hwnd),HDM_SETUNICODEFORMAT,(WPARAM32)(fUnicode),0)
+#define Header_GetUnicodeFormat(hwnd) \
+  (BOOL32)SendMessage32A((hwnd),HDM_GETUNICODEFORMAT,0,0)
+
+
+/* Toolbar */
+
+#define TOOLBARCLASSNAME16        "ToolbarWindow" 
+#define TOOLBARCLASSNAME32W       L"ToolbarWindow32" 
+#define TOOLBARCLASSNAME32A       "ToolbarWindow32" 
+#define TOOLBARCLASSNAME WINELIB_NAME_AW(TOOLBARCLASSNAME)
+
+ 
+#define CMB_MASKED              0x02 
+ 
+#define TBSTATE_CHECKED         0x01 
+#define TBSTATE_PRESSED         0x02 
+#define TBSTATE_ENABLED         0x04 
+#define TBSTATE_HIDDEN          0x08 
+#define TBSTATE_INDETERMINATE   0x10 
+#define TBSTATE_WRAP            0x20 
+#define TBSTATE_ELLIPSES        0x40
+#define TBSTATE_MARKED          0x80 
+ 
+ 
+#define TBSTYLE_BUTTON          0x00 
+#define TBSTYLE_SEP             0x01 
+#define TBSTYLE_CHECK           0x02 
+#define TBSTYLE_GROUP           0x04 
+#define TBSTYLE_CHECKGROUP      (TBSTYLE_GROUP | TBSTYLE_CHECK) 
+#define TBSTYLE_DROPDOWN        0x08 
+ 
+#define TBSTYLE_TOOLTIPS        0x0100 
+#define TBSTYLE_WRAPABLE        0x0200 
+#define TBSTYLE_ALTDRAG         0x0400 
+#define TBSTYLE_FLAT            0x0800 
+#define TBSTYLE_LIST            0x1000 
+#define TBSTYLE_CUSTOMERASE     0x2000 
+ 
+#define TB_ENABLEBUTTON          (WM_USER+1)
+#define TB_CHECKBUTTON           (WM_USER+2)
+#define TB_PRESSBUTTON           (WM_USER+3)
+#define TB_HIDEBUTTON            (WM_USER+4)
+#define TB_INDETERMINATE         (WM_USER+5)
+#define TB_ISBUTTONENABLED       (WM_USER+9) 
+#define TB_ISBUTTONCHECKED       (WM_USER+10) 
+#define TB_ISBUTTONPRESSED       (WM_USER+11) 
+#define TB_ISBUTTONHIDDEN        (WM_USER+12) 
+#define TB_ISBUTTONINDETERMINATE (WM_USER+13)
+#define TB_ISBUTTONHIGHLIGHTED   (WM_USER+14)
+#define TB_SETSTATE              (WM_USER+17)
+#define TB_GETSTATE              (WM_USER+18)
+#define TB_ADDBITMAP             (WM_USER+19)
+#define TB_ADDBUTTONS32A         (WM_USER+20)
+#define TB_ADDBUTTONS32W         (WM_USER+68)
+#define TB_ADDBUTTONS WINELIB_NAME_AW(TB_ADDBUTTONS)
+#define TB_HITTEST               (WM_USER+69)
+#define TB_INSERTBUTTON32A       (WM_USER+21)
+#define TB_INSERTBUTTON32W       (WM_USER+67)
+#define TB_INSERTBUTTON WINELIB_NAME_AW(TB_INSERTBUTTON)
+#define TB_DELETEBUTTON          (WM_USER+22)
+#define TB_GETBUTTON             (WM_USER+23)
+#define TB_BUTTONCOUNT           (WM_USER+24)
+#define TB_COMMANDTOINDEX        (WM_USER+25)
+#define TB_SAVERESTORE32A        (WM_USER+26)
+#define TB_SAVERESTORE32W        (WM_USER+76)
+#define TB_SAVERESTORE WINELIB_NAME_AW(TB_SAVERESTORE)
+#define TB_CUSTOMIZE             (WM_USER+27)
+#define TB_ADDSTRING32A          (WM_USER+28) 
+#define TB_ADDSTRING32W          (WM_USER+77) 
+#define TB_ADDSTRING WINELIB_NAME_AW(TB_ADDSTRING)
+#define TB_GETITEMRECT           (WM_USER+29)
+#define TB_BUTTONSTRUCTSIZE      (WM_USER+30)
+#define TB_SETBUTTONSIZE         (WM_USER+31)
+#define TB_SETBITMAPSIZE         (WM_USER+32)
+#define TB_AUTOSIZE              (WM_USER+33)
+#define TB_GETTOOLTIPS           (WM_USER+35)
+#define TB_SETTOOLTIPS           (WM_USER+36)
+#define TB_SETPARENT             (WM_USER+37)
+#define TB_SETROWS               (WM_USER+39)
+#define TB_GETROWS               (WM_USER+40)
+#define TB_SETCMDID              (WM_USER+42)
+#define TB_CHANGEBITMAP          (WM_USER+43)
+#define TB_GETBITMAP             (WM_USER+44)
+#define TB_GETBUTTONTEXT32A      (WM_USER+45)
+#define TB_GETBUTTONTEXT32W      (WM_USER+75)
+#define TB_GETBUTTONTEXT WINELIB_NAME_AW(TB_GETBUTTONTEXT)
+#define TB_REPLACEBITMAP         (WM_USER+46)
+#define TB_SETINDENT             (WM_USER+47)
+#define TB_SETIMAGELIST          (WM_USER+48)
+#define TB_GETIMAGELIST          (WM_USER+49)
+#define TB_LOADIMAGES            (WM_USER+50)
+#define TB_GETRECT               (WM_USER+51) /* wParam is the Cmd instead of index */
+#define TB_SETHOTIMAGELIST       (WM_USER+52)
+#define TB_GETHOTIMAGELIST       (WM_USER+53)
+#define TB_SETDISABLEDIMAGELIST  (WM_USER+54)
+#define TB_GETDISABLEDIMAGELIST  (WM_USER+55)
+#define TB_SETSTYLE              (WM_USER+56)
+#define TB_GETSTYLE              (WM_USER+57)
+#define TB_GETBUTTONSIZE         (WM_USER+58)
+#define TB_SETBUTTONWIDTH        (WM_USER+59)
+#define TB_SETMAXTEXTROWS        (WM_USER+60)
+#define TB_GETTEXTROWS           (WM_USER+61)
+
+
+/* This is just for old CreateToolbar. */
+/* Don't use it in new programs. */
+typedef struct _OLDTBBUTTON {
+    INT32 iBitmap;
+    INT32 idCommand;
+    BYTE  fsState;
+    BYTE  fsStyle;
+    BYTE  bReserved[2];
+    DWORD dwData;
+} OLDTBBUTTON, *POLDTBBUTTON, *LPOLDTBBUTTON;
+typedef const OLDTBBUTTON *LPCOLDTBBUTTON;
+
+
+typedef struct _TBBUTTON {
+    INT32 iBitmap;
+    INT32 idCommand;
+    BYTE  fsState;
+    BYTE  fsStyle;
+    BYTE  bReserved[2];
+    DWORD dwData;
+    INT32 iString;
+} TBBUTTON, *PTBBUTTON, *LPTBBUTTON;
+typedef const TBBUTTON *LPCTBBUTTON;
+
+
+typedef struct _COLORMAP {
+    COLORREF from;
+    COLORREF to;
+} COLORMAP, *LPCOLORMAP;
+
+typedef struct tagTBADDBITMAP {
+    HINSTANCE32 hInst;
+    UINT32      nID;
+} TBADDBITMAP, *LPTBADDBITMAP;
+
+#define HINST_COMMCTRL         ((HINSTANCE32)-1)
+
+
+HWND32 WINAPI
+CreateToolbar(HWND32, DWORD, UINT32, INT32, HINSTANCE32,
+              UINT32, LPCOLDTBBUTTON, INT32); 
+ 
+HWND32 WINAPI
+CreateToolbarEx(HWND32, DWORD, UINT32, INT32,
+                HINSTANCE32, UINT32, LPCTBBUTTON, 
+                INT32, INT32, INT32, INT32, INT32, UINT32); 
+
+HBITMAP32 WINAPI
+CreateMappedBitmap (HINSTANCE32, INT32, UINT32, LPCOLORMAP, INT32); 
+
+
+
 #endif  /* __WINE_COMMCTRL_H */
diff --git a/include/commdlg.h b/include/commdlg.h
index b0cbfdd..a54499d 100644
--- a/include/commdlg.h
+++ b/include/commdlg.h
@@ -113,8 +113,8 @@
 	LPCWSTR		lpTemplateName;
 } OPENFILENAME32W,*LPOPENFILENAME32W;
 
-DECL_WINELIB_TYPE_AW(OPENFILENAME);
-DECL_WINELIB_TYPE_AW(LPOPENFILENAME);
+DECL_WINELIB_TYPE_AW(OPENFILENAME)
+DECL_WINELIB_TYPE_AW(LPOPENFILENAME)
 
 typedef UINT32 (CALLBACK *LPCCHOOKPROC) (HWND32, UINT32, WPARAM32, LPARAM);
 
@@ -157,8 +157,8 @@
 } CHOOSECOLOR32W;
 typedef CHOOSECOLOR32W *LPCHOOSECOLOR32W;
 
-DECL_WINELIB_TYPE_AW(CHOOSECOLOR);
-DECL_WINELIB_TYPE_AW(LPCHOOSECOLOR);
+DECL_WINELIB_TYPE_AW(CHOOSECOLOR)
+DECL_WINELIB_TYPE_AW(LPCHOOSECOLOR)
 
 
 #define CC_RGBINIT               0x00000001
@@ -214,8 +214,8 @@
 	LPCWSTR		lpTemplateName;
 	} FINDREPLACE32W, *LPFINDREPLACE32W;
 	
-DECL_WINELIB_TYPE_AW(FINDREPLACE);
-DECL_WINELIB_TYPE_AW(LPFINDREPLACE);
+DECL_WINELIB_TYPE_AW(FINDREPLACE)
+DECL_WINELIB_TYPE_AW(LPFINDREPLACE)
 	
 #define FR_DOWN                         0x00000001
 #define FR_WHOLEWORD                    0x00000002
@@ -303,8 +303,8 @@
 	INT32		nSizeMax; 
 } CHOOSEFONT32W, *LPCHOOSEFONT32W;
 
-DECL_WINELIB_TYPE_AW(CHOOSEFONT);
-DECL_WINELIB_TYPE_AW(LPCHOOSEFONT);
+DECL_WINELIB_TYPE_AW(CHOOSEFONT)
+DECL_WINELIB_TYPE_AW(LPCHOOSEFONT)
 
 #pragma pack(4)
 
@@ -433,8 +433,8 @@
     HGLOBAL32        hSetupTemplate;
 } PRINTDLG32W, *LPPRINTDLG32W;
 
-DECL_WINELIB_TYPE_AW(PRINTDLG);
-DECL_WINELIB_TYPE_AW(LPPRINTDLG);
+DECL_WINELIB_TYPE_AW(PRINTDLG)
+DECL_WINELIB_TYPE_AW(LPPRINTDLG)
 
 #define PD_ALLPAGES                  0x00000000
 #define PD_SELECTION                 0x00000001
diff --git a/include/config.h.in b/include/config.h.in
index 1642cb4..6a7a4c1 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -69,6 +69,9 @@
 /* Define if you have the strerror function.  */
 #undef HAVE_STRERROR
 
+/* Define if you have the stricmp function.  */
+#undef HAVE_STRICMP
+
 /* Define if you have the tcgetattr function.  */
 #undef HAVE_TCGETATTR
 
diff --git a/include/crtdll.h b/include/crtdll.h
index c5d9f4e..a272ce5 100644
--- a/include/crtdll.h
+++ b/include/crtdll.h
@@ -22,4 +22,7 @@
 #define CRTDLL_LEADBYTE		0x8000
 #define CRTDLL_ALPHA		(0x0100|CRTDLL_UPPER|CRTDLL_LOWER)
 
-#endif
+/* function prototypes used in crtdll.c */
+extern int LastErrorToErrno(DWORD);
+
+#endif /* __WINE_CRTDLL_H */
diff --git a/include/dc.h b/include/dc.h
index ea1a393..f94e0a2 100644
--- a/include/dc.h
+++ b/include/dc.h
@@ -25,7 +25,9 @@
 
 extern const int DC_XROPfunction[];
 
+/* objects/clipping.c */
 INT32 CLIPPING_IntersectClipRect( DC * dc, INT32 left, INT32 top,
-                                  INT32 right, INT32 bottom, UINT32 flags );
+    INT32 right, INT32 bottom, UINT32 flags );
+extern void CLIPPING_UpdateGCRegion( DC * dc );
 
 #endif /* __WINE_DC_H */
diff --git a/include/ddeml.h b/include/ddeml.h
index 09c2e20..375448c 100644
--- a/include/ddeml.h
+++ b/include/ddeml.h
@@ -19,7 +19,7 @@
                                            HDDEDATA,DWORD,DWORD);
 typedef HDDEDATA (CALLBACK *PFNCALLBACK32)(UINT32,UINT32,HCONV,HSZ,HSZ,
                                            HDDEDATA,DWORD,DWORD);
-DECL_WINELIB_TYPE(PFNCALLBACK);
+DECL_WINELIB_TYPE(PFNCALLBACK)
 
 typedef struct
 {
@@ -41,8 +41,8 @@
     DWORD   dwSecurity;
 } CONVCONTEXT32, *LPCONVCONTEXT32;
 
-DECL_WINELIB_TYPE(CONVCONTEXT);
-DECL_WINELIB_TYPE(LPCONVCONTEXT);
+DECL_WINELIB_TYPE(CONVCONTEXT)
+DECL_WINELIB_TYPE(LPCONVCONTEXT)
 
 UINT16    WINAPI DdeInitialize16(LPDWORD,PFNCALLBACK16,DWORD,DWORD);
 UINT32    WINAPI DdeInitialize32A(LPDWORD,PFNCALLBACK32,DWORD,DWORD);
@@ -54,7 +54,9 @@
 HCONVLIST WINAPI DdeConnectList16(DWORD,HSZ,HSZ,HCONVLIST,LPCONVCONTEXT16);
 HCONVLIST WINAPI DdeConnectList32(DWORD,HSZ,HSZ,HCONVLIST,LPCONVCONTEXT32);
 #define   DdeConnectList WINELIB_NAME(DdeConnectList)
-HCONV     WINAPI DdeQueryNextServer(HCONVLIST, HCONV);
+HCONV     WINAPI DdeQueryNextServer16(HCONVLIST, HCONV);
+HCONV     WINAPI DdeQueryNextServer32(HCONVLIST, HCONV);
+#define   DdeQueryNextServer WINELIB_NAME(DdeQueryNextServer)
 BOOL16    WINAPI DdeDisconnectList16(HCONVLIST);
 BOOL32    WINAPI DdeDisconnectList32(HCONVLIST);
 #define   DdeDisConnectList WINELIB_NAME(DdeDisconnectList)
diff --git a/include/ddraw.h b/include/ddraw.h
index f17f035..04d49c5 100644
--- a/include/ddraw.h
+++ b/include/ddraw.h
@@ -668,7 +668,7 @@
 
 typedef BOOL32 (CALLBACK * LPDDENUMCALLBACK32A)(GUID *, LPSTR, LPSTR, LPVOID);
 typedef BOOL32 (CALLBACK * LPDDENUMCALLBACK32W)(GUID *, LPWSTR, LPWSTR, LPVOID);
-DECL_WINELIB_TYPE_AW(LPDDENUMCALLBACK);
+DECL_WINELIB_TYPE_AW(LPDDENUMCALLBACK)
 
 typedef HRESULT (CALLBACK * LPDDENUMMODESCALLBACK)(LPDDSURFACEDESC, LPVOID);
 typedef HRESULT (CALLBACK * LPDDENUMSURFACESCALLBACK)(LPDIRECTDRAWSURFACE, LPDDSURFACEDESC, LPVOID);
@@ -676,7 +676,7 @@
 typedef HANDLE32 HMONITOR;
 typedef BOOL32 (CALLBACK * LPDDENUMCALLBACKEX32A)(GUID *, LPSTR, LPSTR, LPVOID, HMONITOR);
 typedef BOOL32 (CALLBACK * LPDDENUMCALLBACKEX32W)(GUID *, LPWSTR, LPWSTR, LPVOID, HMONITOR);
-DECL_WINELIB_TYPE_AW(LPDDENUMCALLBACKEX);
+DECL_WINELIB_TYPE_AW(LPDDENUMCALLBACKEX)
 
 HRESULT WINAPI DirectDrawEnumerateExA( LPDDENUMCALLBACKEX32A lpCallback, LPVOID lpContext, DWORD dwFlags);
 HRESULT WINAPI DirectDrawEnumerateExW( LPDDENUMCALLBACKEX32W lpCallback, LPVOID lpContext, DWORD dwFlags);
diff --git a/include/debug.h b/include/debug.h
index e9e1b33..3d1702a 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -30,94 +30,97 @@
 #define dbch_ddraw 22
 #define dbch_debug 23
 #define dbch_dialog 24
-#define dbch_dll 25
-#define dbch_dosfs 26
-#define dbch_dosmem 27
-#define dbch_driver 28
-#define dbch_dsound 29
-#define dbch_edit 30
-#define dbch_event 31
-#define dbch_exec 32
-#define dbch_file 33
-#define dbch_fixup 34
-#define dbch_font 35
-#define dbch_gdi 36
-#define dbch_global 37
-#define dbch_graphics 38
-#define dbch_header 39
-#define dbch_heap 40
-#define dbch_hook 41
-#define dbch_icon 42
-#define dbch_imagelist 43
-#define dbch_int 44
-#define dbch_int21 45
-#define dbch_int31 46
-#define dbch_key 47
-#define dbch_keyboard 48
-#define dbch_ldt 49
-#define dbch_listbox 50
-#define dbch_local 51
-#define dbch_mci 52
-#define dbch_mcianim 53
-#define dbch_mciwave 54
-#define dbch_mdi 55
-#define dbch_menu 56
-#define dbch_message 57
-#define dbch_metafile 58
-#define dbch_midi 59
-#define dbch_mmaux 60
-#define dbch_mmio 61
-#define dbch_mmsys 62
-#define dbch_mmtime 63
-#define dbch_module 64
-#define dbch_mpr 65
-#define dbch_msg 66
-#define dbch_nonclient 67
-#define dbch_ntdll 68
-#define dbch_ole 69
-#define dbch_palette 70
-#define dbch_print 71
-#define dbch_profile 72
-#define dbch_progress 73
-#define dbch_prop 74
-#define dbch_reg 75
-#define dbch_region 76
-#define dbch_relay 77
-#define dbch_resource 78
-#define dbch_scroll 79
-#define dbch_security 80
-#define dbch_segment 81
-#define dbch_selector 82
-#define dbch_sem 83
-#define dbch_sendmsg 84
-#define dbch_shell 85
-#define dbch_shm 86
-#define dbch_sound 87
-#define dbch_static 88
-#define dbch_status 89
-#define dbch_stress 90
-#define dbch_string 91
-#define dbch_system 92
-#define dbch_task 93
-#define dbch_text 94
-#define dbch_thread 95
-#define dbch_thunk 96
-#define dbch_timer 97
-#define dbch_toolhelp 98
-#define dbch_tweak 99
-#define dbch_uitools 100
-#define dbch_updown 101
-#define dbch_ver 102
-#define dbch_virtual 103
-#define dbch_vxd 104
-#define dbch_win 105
-#define dbch_win16drv 106
-#define dbch_win32 107
-#define dbch_wing 108
-#define dbch_winsock 109
-#define dbch_wnet 110
-#define dbch_x11 111
-#define dbch_x11drv 112
+#define dbch_dinput 25
+#define dbch_dll 26
+#define dbch_dosfs 27
+#define dbch_dosmem 28
+#define dbch_driver 29
+#define dbch_dsound 30
+#define dbch_edit 31
+#define dbch_event 32
+#define dbch_exec 33
+#define dbch_file 34
+#define dbch_fixup 35
+#define dbch_font 36
+#define dbch_gdi 37
+#define dbch_global 38
+#define dbch_graphics 39
+#define dbch_header 40
+#define dbch_heap 41
+#define dbch_hook 42
+#define dbch_icon 43
+#define dbch_imagelist 44
+#define dbch_int 45
+#define dbch_int21 46
+#define dbch_int31 47
+#define dbch_key 48
+#define dbch_keyboard 49
+#define dbch_ldt 50
+#define dbch_listbox 51
+#define dbch_local 52
+#define dbch_mci 53
+#define dbch_mcianim 54
+#define dbch_mciwave 55
+#define dbch_mdi 56
+#define dbch_menu 57
+#define dbch_message 58
+#define dbch_metafile 59
+#define dbch_midi 60
+#define dbch_mmaux 61
+#define dbch_mmio 62
+#define dbch_mmsys 63
+#define dbch_mmtime 64
+#define dbch_module 65
+#define dbch_mpr 66
+#define dbch_msg 67
+#define dbch_nonclient 68
+#define dbch_ntdll 69
+#define dbch_ole 70
+#define dbch_palette 71
+#define dbch_print 72
+#define dbch_process 73
+#define dbch_profile 74
+#define dbch_progress 75
+#define dbch_prop 76
+#define dbch_reg 77
+#define dbch_region 78
+#define dbch_relay 79
+#define dbch_resource 80
+#define dbch_scroll 81
+#define dbch_security 82
+#define dbch_segment 83
+#define dbch_selector 84
+#define dbch_sem 85
+#define dbch_sendmsg 86
+#define dbch_shell 87
+#define dbch_shm 88
+#define dbch_sound 89
+#define dbch_static 90
+#define dbch_stress 91
+#define dbch_string 92
+#define dbch_syscolor 93
+#define dbch_system 94
+#define dbch_task 95
+#define dbch_text 96
+#define dbch_thread 97
+#define dbch_thunk 98
+#define dbch_timer 99
+#define dbch_toolbar 100
+#define dbch_toolhelp 101
+#define dbch_tweak 102
+#define dbch_uitools 103
+#define dbch_updown 104
+#define dbch_ver 105
+#define dbch_virtual 106
+#define dbch_vxd 107
+#define dbch_win 108
+#define dbch_win16drv 109
+#define dbch_win32 110
+#define dbch_wing 111
+#define dbch_winsock 112
+#define dbch_wnet 113
+#define dbch_x11 114
+#define dbch_x11drv 115
 /* Definitions for classes identifiers */
 #define dbcl_fixme 0
 #define dbcl_err 1
diff --git a/include/debugdefs.h b/include/debugdefs.h
index ea98744..96704c8 100644
--- a/include/debugdefs.h
+++ b/include/debugdefs.h
@@ -4,7 +4,7 @@
 #include "debugtools.h"
 #endif
 
-#define DEBUG_CHANNEL_COUNT 113
+#define DEBUG_CHANNEL_COUNT 116
 #ifdef DEBUG_RUNTIME
 short debug_msg_enabled[][DEBUG_CLASS_COUNT] = {
 {1, 1, 0, 0},
@@ -120,6 +120,9 @@
 {1, 1, 0, 0},
 {1, 1, 0, 0},
 {1, 1, 0, 0},
+{1, 1, 0, 0},
+{1, 1, 0, 0},
+{1, 1, 0, 0},
 };
 const char* debug_ch_name[] = {
 "accel",
@@ -147,6 +150,7 @@
 "ddraw",
 "debug",
 "dialog",
+"dinput",
 "dll",
 "dosfs",
 "dosmem",
@@ -194,6 +198,7 @@
 "ole",
 "palette",
 "print",
+"process",
 "profile",
 "progress",
 "prop",
@@ -211,15 +216,16 @@
 "shm",
 "sound",
 "static",
-"status",
 "stress",
 "string",
+"syscolor",
 "system",
 "task",
 "text",
 "thread",
 "thunk",
 "timer",
+"toolbar",
 "toolhelp",
 "tweak",
 "uitools",
diff --git a/include/dinput.h b/include/dinput.h
index d103e7b..de79972 100644
--- a/include/dinput.h
+++ b/include/dinput.h
@@ -155,8 +155,8 @@
     WORD	wReserved;
 #endif /* DIRECTINPUT_VERSION >= 0x0500 */
 } DIDEVICEOBJECTINSTANCE32W, *LPDIDEVICEOBJECTINSTANCE32W,*LPCDIDEVICEOBJECTINSTANCE32W;
-DECL_WINELIB_TYPE_AW(LPDIDEVICEOBJECTINSTANCE);
-DECL_WINELIB_TYPE_AW(DIDEVICEOBJECTINSTANCE);
+DECL_WINELIB_TYPE_AW(LPDIDEVICEOBJECTINSTANCE)
+DECL_WINELIB_TYPE_AW(DIDEVICEOBJECTINSTANCE)
 
 
 typedef struct {
@@ -186,17 +186,17 @@
     WORD	wUsage;
 #endif /* DIRECTINPUT_VERSION >= 0x0500 */
 } DIDEVICEINSTANCE32W, *LPDIDEVICEINSTANCE32W, *LPCDIDEVICEINSTANCE32W;
-DECL_WINELIB_TYPE_AW(DIDEVICEINSTANCE);
-DECL_WINELIB_TYPE_AW(LPDIDEVICEINSTANCE);
-DECL_WINELIB_TYPE_AW(LPCDIDEVICEINSTANCE);
+DECL_WINELIB_TYPE_AW(DIDEVICEINSTANCE)
+DECL_WINELIB_TYPE_AW(LPDIDEVICEINSTANCE)
+DECL_WINELIB_TYPE_AW(LPCDIDEVICEINSTANCE)
 
 typedef BOOL32 (CALLBACK * LPDIENUMDEVICESCALLBACK32A)(LPCDIDEVICEINSTANCE32A,LPVOID);
 typedef BOOL32 (CALLBACK * LPDIENUMDEVICESCALLBACK32W)(LPCDIDEVICEINSTANCE32W,LPVOID);
-DECL_WINELIB_TYPE_AW(LPDIENUMDEVICESCALLBACK);
+DECL_WINELIB_TYPE_AW(LPDIENUMDEVICESCALLBACK)
 
 typedef BOOL32 (CALLBACK * LPDIENUMDEVICEOBJECTSCALLBACK32A)(LPCDIDEVICEOBJECTINSTANCE32A, LPVOID);
 typedef BOOL32 (CALLBACK * LPDIENUMDEVICEOBJECTSCALLBACK32W)(LPCDIDEVICEOBJECTINSTANCE32W,LPVOID);
-DECL_WINELIB_TYPE_AW(LPDIENUMDEVICEOBJECTSCALLBACK);
+DECL_WINELIB_TYPE_AW(LPDIENUMDEVICEOBJECTSCALLBACK)
 
 #define DIK_ESCAPE          0x01
 #define DIK_1               0x02
diff --git a/include/dsound.h b/include/dsound.h
index 081696b..af7a6a8 100644
--- a/include/dsound.h
+++ b/include/dsound.h
@@ -246,10 +246,34 @@
 	LPDIRECTSOUNDBUFFER		dsb;
 };
 #undef THIS
-
 #undef STDMETHOD
 #undef STDMETHOD_
 #undef PURE
 #undef FAR
 #undef THIS_
+
+/* DirectPlayLobby stuff */
+/* {AF465C71-9588-11cf-A020-00AA006157AC} */
+DEFINE_GUID(IID_IDirectPlayLobby, 0xaf465c71, 0x9588, 0x11cf, 0xa0, 0x20, 0x0, 0xaa, 0x0, 0x61, 0x57, 0xac);
+/* {26C66A70-B367-11cf-A024-00AA006157AC} */
+DEFINE_GUID(IID_IDirectPlayLobbyA, 0x26c66a70, 0xb367, 0x11cf, 0xa0, 0x24, 0x0, 0xaa, 0x0, 0x61, 0x57, 0xac);
+/* {0194C220-A303-11d0-9C4F-00A0C905425E} */
+DEFINE_GUID(IID_IDirectPlayLobby2, 0x194c220, 0xa303, 0x11d0, 0x9c, 0x4f, 0x0, 0xa0, 0xc9, 0x5, 0x42, 0x5e);
+/* {1BB4AF80-A303-11d0-9C4F-00A0C905425E} */
+DEFINE_GUID(IID_IDirectPlayLobby2A, 0x1bb4af80, 0xa303, 0x11d0, 0x9c, 0x4f, 0x0, 0xa0, 0xc9, 0x5, 0x42, 0x5e);
+/* {2FE8F810-B2A5-11d0-A787-0000F803ABFC} */
+DEFINE_GUID(CLSID_DirectPlayLobby, 0x2fe8f810, 0xb2a5, 0x11d0, 0xa7, 0x87, 0x0, 0x0, 0xf8, 0x3, 0xab, 0xfc);
+
+typedef struct IDirectPlayLobby     *LPDIRECTPLAYLOBBY;
+typedef struct IDirectPlayLobby     *LPDIRECTPLAYLOBBYA;
+typedef struct IDirectPlayLobby     IDirectPlayLobbyA;
+
+typedef struct IDirectPlayLobby2    *LPDIRECTPLAYLOBBY2;
+typedef struct IDirectPlayLobby2    *LPDIRECTPLAYLOBBY2A;
+typedef struct IDirectPlayLobby2    IDirectPlayLobby2A;
+
+extern HRESULT WINAPI DirectPlayLobbyCreateW(LPGUID, LPDIRECTPLAYLOBBY *, IUnknown *, LPVOID, DWORD );
+
+extern HRESULT WINAPI DirectPlayLobbyCreateA(LPGUID, LPDIRECTPLAYLOBBYA *, IUnknown *, LPVOID, DWORD );
+
 #endif
diff --git a/include/except.h b/include/except.h
index 8028060..c954177 100644
--- a/include/except.h
+++ b/include/except.h
@@ -32,13 +32,6 @@
   PEXCEPTION_HANDLER       Handler;
 } EXCEPTION_FRAME, *PEXCEPTION_FRAME;
 
-/*
- * Function definitions  
- */
- 
-void WINAPI RaiseException(DWORD exccode, DWORD excflags, 
-                           DWORD nargs, const LPDWORD pargs,
-                           PCONTEXT pcontext /* Wine additional parameter */); 
                         
 /*
  *  this undocumented function is called when an exception
@@ -53,11 +46,9 @@
  *  a fourth parameter, that is used as the eax in the 
  *  context.   
  */
-
 void WINAPI RtlUnwind( PEXCEPTION_FRAME pestframe,
                        LPVOID unusedEIP,
                        PEXCEPTION_RECORD pexcrec,
-                       DWORD contextEAX,
-                       PCONTEXT pcontext /* Wine additional parameter */ );
+                       DWORD contextEAX );
 
 #endif  /* __WINE_EXCEPT_H */
diff --git a/include/flatthunk.h b/include/flatthunk.h
new file mode 100644
index 0000000..57e4257
--- /dev/null
+++ b/include/flatthunk.h
@@ -0,0 +1,111 @@
+/*
+ * Win95 Flat Thunk data structures
+ *
+ * Copyright 1998 Ulrich Weigand
+ */
+
+#ifndef __WINE_FLATTHUNK_H
+#define __WINE_FLATTHUNK_H
+
+struct ThunkDataCommon
+{
+    char                   magic[4];         /* 00 */
+    DWORD                  checksum;         /* 04 */
+};
+
+struct ThunkDataLS16
+{
+    struct ThunkDataCommon common;           /* 00 */
+    SEGPTR                 targetTable;      /* 08 */
+    DWORD                  firstTime;        /* 0C */
+};
+
+struct ThunkDataLS32
+{
+    struct ThunkDataCommon common;           /* 00 */
+    DWORD *                targetTable;      /* 08 */
+    char                   lateBinding[4];   /* 0C */
+    DWORD                  flags;            /* 10 */
+    DWORD                  reserved1;        /* 14 */
+    DWORD                  reserved2;        /* 18 */
+    DWORD                  offsetQTThunk;    /* 1C */
+    DWORD                  offsetFTProlog;   /* 20 */
+};
+
+struct ThunkDataSL16
+{
+    struct ThunkDataCommon common;            /* 00 */
+    DWORD                  flags1;            /* 08 */
+    DWORD                  reserved1;         /* 0C */
+    struct ThunkDataSL *   fpData;            /* 10 */
+    SEGPTR                 spData;            /* 14 */
+    DWORD                  reserved2;         /* 18 */
+    char                   lateBinding[4];    /* 1C */
+    DWORD                  flags2;            /* 20 */
+    DWORD                  reserved3;         /* 20 */
+    SEGPTR                 apiDatabase;       /* 28 */
+};
+
+struct ThunkDataSL32
+{
+    struct ThunkDataCommon common;            /* 00 */
+    DWORD                  reserved1;         /* 08 */
+    struct ThunkDataSL *   data;              /* 0C */
+    char                   lateBinding[4];    /* 10 */
+    DWORD                  flags;             /* 14 */
+    DWORD                  reserved2;         /* 18 */
+    DWORD                  reserved3;         /* 1C */
+    DWORD                  offsetTargetTable; /* 20 */
+};
+
+struct ThunkDataSL
+{
+#if 0
+    This structure differs from the Win95 original,
+    but this should not matter since it is strictly internal to
+    the thunk handling routines in KRNL386 / KERNEL32.
+
+    For reference, here is the Win95 layout:
+
+    struct ThunkDataCommon common;            /* 00 */
+    DWORD                  flags1;            /* 08 */
+    SEGPTR                 apiDatabase;       /* 0C */
+    WORD                   exePtr;            /* 10 */
+    WORD                   segMBA;            /* 12 */
+    DWORD                  lenMBATotal;       /* 14 */
+    DWORD                  lenMBAUsed;        /* 18 */
+    DWORD                  flags2;            /* 1C */
+    char                   pszDll16[256];     /* 20 */
+    char                   pszDll32[256];     /*120 */
+
+    We do it differently since all our thunk handling is done
+    by 32-bit code. Therefore we do not need do provide
+    easy access to this data, especially the process target
+    table database, for 16-bit code.
+#endif
+
+    struct ThunkDataCommon common;
+    DWORD                  flags1;
+    struct SLApiDB *       apiDB;
+    struct SLTargetDB *    targetDB;
+    DWORD                  flags2;
+    char                   pszDll16[256];
+    char                   pszDll32[256];
+};
+
+struct SLTargetDB
+{
+     struct SLTargetDB *   next;
+     PDB32 *               process;
+     DWORD *               targetTable;
+};
+
+struct SLApiDB
+{
+    DWORD                  nrArgBytes;
+    DWORD                  errorReturnValue;
+};
+
+
+#endif /* __WINE_FLATTHUNK_H */
+
diff --git a/include/gdi.h b/include/gdi.h
index 07ab5a2..ae40bd1 100644
--- a/include/gdi.h
+++ b/include/gdi.h
@@ -429,6 +429,8 @@
 extern const DC_FUNCTIONS *DRIVER_FindDriver( LPCSTR name );
 extern BOOL32 DRIVER_UnregisterDriver( LPCSTR name );
 
+extern BOOL32 DIB_Init(void);
+
 extern Display * display;
 extern Screen * screen;
 extern Window rootWindow;
diff --git a/include/global.h b/include/global.h
index 7acb6a7..5c8cc9b 100644
--- a/include/global.h
+++ b/include/global.h
@@ -28,6 +28,7 @@
 extern WORD GlobalHandleToSel( HGLOBAL16 handle );
 
 /* memory/virtual.c */
+extern BOOL32 VIRTUAL_Init( void );
 extern DWORD VIRTUAL_GetPageSize(void);
 extern DWORD VIRTUAL_GetGranularity(void);
 
diff --git a/include/interfaces.h b/include/interfaces.h
index e8f2993..da42f15 100644
--- a/include/interfaces.h
+++ b/include/interfaces.h
@@ -107,6 +107,8 @@
 LPMALLOC32	IMalloc32_Constructor();
 #endif
 
+HRESULT WINAPI CoGetMalloc32(DWORD, LPMALLOC32*);
+
 #undef STDMETHOD
 #undef STDMETHOD_
 #undef PURE
diff --git a/include/main.h b/include/main.h
index ea3a29c..ef3a94c 100644
--- a/include/main.h
+++ b/include/main.h
@@ -10,4 +10,7 @@
 extern BOOL32 MAIN_UserInit(void);
 extern BOOL32 MAIN_WineInit( int *argc, char *argv[] );
 
+extern BOOL32 RELAY_Init(void);
+extern void* CALL32_Init(void);
+
 #endif  /* __WINE_MAIN_H */
diff --git a/include/menu.h b/include/menu.h
index c270b84..9192190 100644
--- a/include/menu.h
+++ b/include/menu.h
@@ -9,6 +9,7 @@
 extern HMENU32 MENU_GetSysMenu(HWND32 hWndOwner, HMENU32 hSysPopup);
 extern UINT32 MENU_GetMenuBarHeight( HWND32 hwnd, UINT32 menubarWidth,
                                      INT32 orgX, INT32 orgY );
+extern BOOL32 MENU_PatchResidentPopup( HQUEUE16, WND* );
 extern void MENU_TrackMouseMenuBar( WND *wnd, INT32 ht, POINT32 pt );
 extern void MENU_TrackKbdMenuBar( WND *wnd, UINT32 wParam, INT32 vkey );
 extern UINT32 MENU_DrawMenuBar( HDC32 hDC, LPRECT32 lprect,
diff --git a/include/message.h b/include/message.h
index ecf33c4..6946e70 100644
--- a/include/message.h
+++ b/include/message.h
@@ -31,6 +31,10 @@
 #define EVENT_IO_EXCEPT		2
 
 /* event.c */
+extern void EVENT_AddIO( int fd, unsigned flag );
+extern BOOL32 EVENT_CheckFocus( void );
+extern void EVENT_DeleteIO( int fd, unsigned flag );
+extern BOOL32 EVENT_Init( void );
 extern BOOL32 EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek );
 extern void EVENT_Synchronize(void);
 extern void EVENT_ProcessEvent( XEvent *event );
@@ -40,4 +44,6 @@
 extern HWND32 EVENT_Capture( HWND32, INT16 );
 extern INT16 EVENT_GetCaptureInfo(void);
 
+extern void joySendMessages(void);
+
 #endif  /* __WINE_MESSAGE_H */
diff --git a/include/mmsystem.h b/include/mmsystem.h
index f293176..c2011bf 100644
--- a/include/mmsystem.h
+++ b/include/mmsystem.h
@@ -24,13 +24,13 @@
 
 typedef UINT16	MMVERSION16;
 typedef UINT32	MMVERSION32;
-DECL_WINELIB_TYPE(MMVERSION);
+DECL_WINELIB_TYPE(MMVERSION)
 typedef UINT16	MCIDEVICEID16;
 typedef UINT32	MCIDEVICEID32;
-DECL_WINELIB_TYPE(MCIDEVICEID);
+DECL_WINELIB_TYPE(MCIDEVICEID)
 typedef	UINT16	MMRESULT16;
 typedef	UINT32	MMRESULT32;
-DECL_WINELIB_TYPE(MMRESULT);
+DECL_WINELIB_TYPE(MMRESULT)
 
 typedef struct {
     UINT16    wType;		/* indicates the contents of the union */
@@ -72,8 +72,8 @@
 	} midi;
     } u;
 } MMTIME32,  *LPMMTIME32;
-DECL_WINELIB_TYPE(MMTIME);
-DECL_WINELIB_TYPE(LPMMTIME);
+DECL_WINELIB_TYPE(MMTIME)
+DECL_WINELIB_TYPE(LPMMTIME)
 
 #define TIME_MS         0x0001  /* time in milliseconds */
 #define TIME_SAMPLES    0x0002  /* number of wave samples */
@@ -261,8 +261,8 @@
     WORD	wReserved1;		/* padding */
     DWORD	dwSupport;		/* functionality supported by driver */
 } WAVEOUTCAPS32W, *LPWAVEOUTCAPS32W;
-DECL_WINELIB_TYPE_AW(WAVEOUTCAPS);
-DECL_WINELIB_TYPE_AW(LPWAVEOUTCAPS);
+DECL_WINELIB_TYPE_AW(WAVEOUTCAPS)
+DECL_WINELIB_TYPE_AW(LPWAVEOUTCAPS)
 
 #define WAVECAPS_PITCH          0x0001   /* supports pitch control */
 #define WAVECAPS_PLAYBACKRATE   0x0002   /* supports playback rate control */
@@ -297,8 +297,8 @@
     WORD	wChannels;		/* number of channels supported */
     WORD	wReserved1;
 } WAVEINCAPS32W, *LPWAVEINCAPS32W;
-DECL_WINELIB_TYPE_AW(WAVEINCAPS);
-DECL_WINELIB_TYPE_AW(LPWAVEINCAPS);
+DECL_WINELIB_TYPE_AW(WAVEINCAPS)
+DECL_WINELIB_TYPE_AW(LPWAVEINCAPS)
 
 #define WAVE_INVALIDFORMAT     0x00000000       /* invalid format */
 #define WAVE_FORMAT_1M08       0x00000001       /* 11.025 kHz, Mono,   8-bit  */
@@ -530,8 +530,8 @@
     DWORD	dwSupport;	/* functionality supported by driver */
 } MIDIOUTCAPS32W, *LPMIDIOUTCAPS32W;
 
-DECL_WINELIB_TYPE_AW(MIDIOUTCAPS);
-DECL_WINELIB_TYPE_AW(LPMIDIOUTCAPS);
+DECL_WINELIB_TYPE_AW(MIDIOUTCAPS)
+DECL_WINELIB_TYPE_AW(LPMIDIOUTCAPS)
 
 #define MOD_MIDIPORT    1  /* output port */
 #define MOD_SYNTH       2  /* generic internal synth */
@@ -567,8 +567,8 @@
     DWORD	dwSupport;	/* included in win95 and higher */
 } MIDIINCAPS32W, *LPMIDIINCAPS32W;
 
-DECL_WINELIB_TYPE_AW(MIDIINCAPS);
-DECL_WINELIB_TYPE_AW(LPMIDIINCAPS);
+DECL_WINELIB_TYPE_AW(MIDIINCAPS)
+DECL_WINELIB_TYPE_AW(LPMIDIINCAPS)
 
 typedef struct {
     LPSTR	lpData;		/* pointer to locked data block */
@@ -741,7 +741,7 @@
 
 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);
+DECL_WINELIB_TYPE(LPTIMECALLBACK)
 
 #define TIME_ONESHOT    0   /* program timer for single event */
 #define TIME_PERIODIC   1   /* program for continuous periodic event */
@@ -756,8 +756,8 @@
     UINT32	wPeriodMax;
 } TIMECAPS32, *LPTIMECAPS32;
 
-DECL_WINELIB_TYPE(TIMECAPS);
-DECL_WINELIB_TYPE(LPTIMECAPS);
+DECL_WINELIB_TYPE(TIMECAPS)
+DECL_WINELIB_TYPE(LPTIMECAPS)
 
 MMRESULT16 WINAPI timeGetSystemTime16(LPMMTIME16,UINT16);
 MMRESULT32 WINAPI timeGetSystemTime32(LPMMTIME32,UINT32);
@@ -922,8 +922,8 @@
     WCHAR szRegKey[MAXPNAMELEN];
     WCHAR szOEMVxD[MAX_JOYSTICKOEMVXDNAME];
 } JOYCAPS32W, *LPJOYCAPS32W;
-DECL_WINELIB_TYPE_AW(JOYCAPS);
-DECL_WINELIB_TYPE_AW(LPJOYCAPS);
+DECL_WINELIB_TYPE_AW(JOYCAPS)
+DECL_WINELIB_TYPE_AW(LPJOYCAPS)
 
 typedef struct {
     UINT16 wXpos;                 /* x position */
@@ -955,8 +955,8 @@
     DWORD	dwReserved2;	/* reserved for future expansion */
 } JOYINFOEX,*LPJOYINFOEX;
 
-DECL_WINELIB_TYPE(JOYINFO);
-DECL_WINELIB_TYPE(LPJOYINFO);
+DECL_WINELIB_TYPE(JOYINFO)
+DECL_WINELIB_TYPE(LPJOYINFO)
 
 MMRESULT16 WINAPI joyGetDevCaps16 (UINT16,LPJOYCAPS16 ,UINT16);
 MMRESULT32 WINAPI joyGetDevCaps32A(UINT32,LPJOYCAPS32A,UINT32);
@@ -1009,8 +1009,8 @@
 	DWORD		cDestinations;
 } MIXERCAPS32W,*LPMIXERCAPS32W;
 
-DECL_WINELIB_TYPE_AW(MIXERCAPS);
-DECL_WINELIB_TYPE_AW(LPMIXERCAPS);
+DECL_WINELIB_TYPE_AW(MIXERCAPS)
+DECL_WINELIB_TYPE_AW(LPMIXERCAPS)
 
 #define MIXER_SHORT_NAME_CHARS	16
 #define MIXER_LONG_NAME_CHARS	64
@@ -1125,8 +1125,8 @@
     } Target;
 } MIXERLINE32W, *LPMIXERLINE32W;
 
-DECL_WINELIB_TYPE_AW(MIXERLINE);
-DECL_WINELIB_TYPE_AW(LPMIXERLINE);
+DECL_WINELIB_TYPE_AW(MIXERLINE)
+DECL_WINELIB_TYPE_AW(LPMIXERLINE)
 
 /*  MIXERCONTROL.fdwControl */
 #define	MIXERCONTROL_CONTROLF_UNIFORM	0x00000001L
@@ -1276,8 +1276,8 @@
     } Metrics;
 } MIXERCONTROL32W, *LPMIXERCONTROL32W;
 
-DECL_WINELIB_TYPE_AW(MIXERCONTROL);
-DECL_WINELIB_TYPE_AW(LPMIXERCONTROL);
+DECL_WINELIB_TYPE_AW(MIXERCONTROL)
+DECL_WINELIB_TYPE_AW(LPMIXERCONTROL)
 
 typedef struct {
     DWORD	cbStruct;	/* size in bytes of MIXERLINECONTROLS */
@@ -1315,8 +1315,8 @@
     LPMIXERCONTROL32W	pamxctrl;
 } MIXERLINECONTROLS32W, *LPMIXERLINECONTROLS32W;
 
-DECL_WINELIB_TYPE_AW(MIXERLINECONTROLS);
-DECL_WINELIB_TYPE_AW(LPMIXERLINECONTROLS);
+DECL_WINELIB_TYPE_AW(MIXERLINECONTROLS)
+DECL_WINELIB_TYPE_AW(LPMIXERLINECONTROLS)
 
 typedef struct {
     DWORD	cbStruct;	/* size in bytes of MIXERCONTROLDETAILS */
@@ -1342,8 +1342,8 @@
     LPVOID	paDetails;
 } MIXERCONTROLDETAILS32,*LPMIXERCONTROLDETAILS32;
 
-DECL_WINELIB_TYPE(MIXERCONTROLDETAILS);
-DECL_WINELIB_TYPE(LPMIXERCONTROLDETAILS);
+DECL_WINELIB_TYPE(MIXERCONTROLDETAILS)
+DECL_WINELIB_TYPE(LPMIXERCONTROLDETAILS)
 
 typedef struct {
     DWORD	dwParam1;
@@ -1363,8 +1363,8 @@
     WCHAR	szName[MIXER_LONG_NAME_CHARS];
 } MIXERCONTROLDETAILS_LISTTEXT32W,*LPMIXERCONTROLDETAILS_LISTTEXT32W;
 
-DECL_WINELIB_TYPE_AW(MIXERCONTROLDETAILS_LISTTEXT);
-DECL_WINELIB_TYPE_AW(LPMIXERCONTROLDETAILS_LISTTEXT);
+DECL_WINELIB_TYPE_AW(MIXERCONTROLDETAILS_LISTTEXT)
+DECL_WINELIB_TYPE_AW(LPMIXERCONTROLDETAILS_LISTTEXT)
 
 /*  MIXER_GETCONTROLDETAILSF_VALUE */
 typedef struct {
@@ -1458,7 +1458,7 @@
                                       LPARAM lParam1, LPARAM lParam2);
 typedef LONG (CALLBACK *LPMMIOPROC32)(LPSTR lpmmioinfo, UINT32 uMessage,
                                       LPARAM lParam1, LPARAM lParam2);
-DECL_WINELIB_TYPE(LPMMIOPROC);
+DECL_WINELIB_TYPE(LPMMIOPROC)
 
 typedef struct {
         DWORD		dwFlags;	/* general status flags */
@@ -1916,8 +1916,8 @@
 	LPWSTR		lpstrAlias;
 } MCI_OPEN_PARMS32W, *LPMCI_OPEN_PARMS32W;
 
-DECL_WINELIB_TYPE_AW(MCI_OPEN_PARMS);
-DECL_WINELIB_TYPE_AW(LPMCI_OPEN_PARMS);
+DECL_WINELIB_TYPE_AW(MCI_OPEN_PARMS)
+DECL_WINELIB_TYPE_AW(LPMCI_OPEN_PARMS)
 
 typedef struct {
 	DWORD   dwCallback;
@@ -1955,8 +1955,8 @@
 	DWORD   dwRetSize;
 } MCI_INFO_PARMS32W, *LPMCI_INFO_PARMS32W;
 
-DECL_WINELIB_TYPE_AW(MCI_INFO_PARMS);
-DECL_WINELIB_TYPE_AW(LPMCI_INFO_PARMS);
+DECL_WINELIB_TYPE_AW(MCI_INFO_PARMS)
+DECL_WINELIB_TYPE_AW(LPMCI_INFO_PARMS)
 
 typedef struct {
 	DWORD   dwCallback;
@@ -1989,8 +1989,8 @@
 	UINT32	wDeviceType;
 } MCI_SYSINFO_PARMS32W, *LPMCI_SYSINFO_PARMS32W;
 
-DECL_WINELIB_TYPE_AW(MCI_SYSINFO_PARMS);
-DECL_WINELIB_TYPE_AW(LPMCI_SYSINFO_PARMS);
+DECL_WINELIB_TYPE_AW(MCI_SYSINFO_PARMS)
+DECL_WINELIB_TYPE_AW(LPMCI_SYSINFO_PARMS)
 
 typedef struct {
 	DWORD   dwCallback;
@@ -2012,8 +2012,8 @@
 	HWND32	hwndBreak;
 } MCI_BREAK_PARMS32, *LPMCI_BREAK_PARMS32;
 
-DECL_WINELIB_TYPE(MCI_BREAK_PARMS);
-DECL_WINELIB_TYPE(LPMCI_BREAK_PARMS);
+DECL_WINELIB_TYPE(MCI_BREAK_PARMS)
+DECL_WINELIB_TYPE(LPMCI_BREAK_PARMS)
 
 typedef struct {
 	DWORD   dwCallback;
@@ -2040,8 +2040,8 @@
 	LPCWSTR	lpfilename;
 } MCI_LOAD_PARMS32W, *LPMCI_LOAD_PARMS32W;
 
-DECL_WINELIB_TYPE_AW(MCI_LOAD_PARMS);
-DECL_WINELIB_TYPE_AW(LPMCI_LOAD_PARMS);
+DECL_WINELIB_TYPE_AW(MCI_LOAD_PARMS)
+DECL_WINELIB_TYPE_AW(LPMCI_LOAD_PARMS)
 
 typedef struct {
 	DWORD   dwCallback;
@@ -2114,8 +2114,8 @@
 	LPCWSTR	lpstrCommand;
 } MCI_VD_ESCAPE_PARMS32W, *LPMCI_VD_ESCAPE_PARMS32W;
 
-DECL_WINELIB_TYPE_AW(MCI_VD_ESCAPE_PARMS);
-DECL_WINELIB_TYPE_AW(LPMCI_VD_ESCAPE_PARMS);
+DECL_WINELIB_TYPE_AW(MCI_VD_ESCAPE_PARMS)
+DECL_WINELIB_TYPE_AW(LPMCI_VD_ESCAPE_PARMS)
 
 #define MCI_WAVE_OPEN_BUFFER            0x00010000L
 
@@ -2171,8 +2171,8 @@
 	DWORD   	dwBufferSeconds;
 } MCI_WAVE_OPEN_PARMS32W, *LPMCI_WAVE_OPEN_PARMS32W;
 
-DECL_WINELIB_TYPE_AW(MCI_WAVE_OPEN_PARMS);
-DECL_WINELIB_TYPE_AW(LPMCI_WAVE_OPEN_PARMS);
+DECL_WINELIB_TYPE_AW(MCI_WAVE_OPEN_PARMS)
+DECL_WINELIB_TYPE_AW(LPMCI_WAVE_OPEN_PARMS)
 
 typedef struct {
 	DWORD   dwCallback;
@@ -2214,8 +2214,8 @@
 	UINT32	wBitsPerSample;
 } MCI_WAVE_SET_PARMS32, * LPMCI_WAVE_SET_PARMS32;
 
-DECL_WINELIB_TYPE(MCI_WAVE_SET_PARMS);
-DECL_WINELIB_TYPE(LPMCI_WAVE_SET_PARMS);
+DECL_WINELIB_TYPE(MCI_WAVE_SET_PARMS)
+DECL_WINELIB_TYPE(LPMCI_WAVE_SET_PARMS)
 
 #define     MCI_SEQ_DIV_PPQN            (0 + MCI_SEQ_OFFSET)
 #define     MCI_SEQ_DIV_SMPTE_24        (1 + MCI_SEQ_OFFSET)
@@ -2334,8 +2334,8 @@
 	HWND32		hWndParent;
 } MCI_ANIM_OPEN_PARMS32W, *LPMCI_ANIM_OPEN_PARMS32W;
 
-DECL_WINELIB_TYPE_AW(MCI_ANIM_OPEN_PARMS);
-DECL_WINELIB_TYPE_AW(LPMCI_ANIM_OPEN_PARMS);
+DECL_WINELIB_TYPE_AW(MCI_ANIM_OPEN_PARMS)
+DECL_WINELIB_TYPE_AW(LPMCI_ANIM_OPEN_PARMS)
 
 typedef struct {
 	DWORD   dwCallback;
@@ -2372,8 +2372,8 @@
 	LPCWSTR	lpstrText;
 } MCI_ANIM_WINDOW_PARMS32W, *LPMCI_ANIM_WINDOW_PARMS32W;
 
-DECL_WINELIB_TYPE_AW(MCI_ANIM_WINDOW_PARMS);
-DECL_WINELIB_TYPE_AW(LPMCI_ANIM_WINDOW_PARMS);
+DECL_WINELIB_TYPE_AW(MCI_ANIM_WINDOW_PARMS)
+DECL_WINELIB_TYPE_AW(LPMCI_ANIM_WINDOW_PARMS)
 
 typedef struct {
 	DWORD   dwCallback;
@@ -2395,8 +2395,8 @@
 #endif  /* ifdef MCI_USE_OFFEXT */
 } MCI_ANIM_RECT_PARMS32, *LPMCI_ANIM_RECT_PARMS32;
 
-DECL_WINELIB_TYPE(MCI_ANIM_RECT_PARMS);
-DECL_WINELIB_TYPE(LPMCI_ANIM_RECT_PARMS);
+DECL_WINELIB_TYPE(MCI_ANIM_RECT_PARMS)
+DECL_WINELIB_TYPE(LPMCI_ANIM_RECT_PARMS)
 
 typedef struct {
 	DWORD   dwCallback;
@@ -2410,8 +2410,8 @@
 	HDC32   hDC;
 } MCI_ANIM_UPDATE_PARMS32, *LPMCI_ANIM_UPDATE_PARMS32;
 
-DECL_WINELIB_TYPE(MCI_ANIM_UPDATE_PARMS);
-DECL_WINELIB_TYPE(LPMCI_ANIM_UPDATE_PARMS);
+DECL_WINELIB_TYPE(MCI_ANIM_UPDATE_PARMS)
+DECL_WINELIB_TYPE(LPMCI_ANIM_UPDATE_PARMS)
 
 #define MCI_OVLY_OPEN_WS                0x00010000L
 #define MCI_OVLY_OPEN_PARENT            0x00020000L
@@ -2476,8 +2476,8 @@
 	HWND32		hWndParent;
 } MCI_OVLY_OPEN_PARMS32W, *LPMCI_OVLY_OPEN_PARMS32W;
 
-DECL_WINELIB_TYPE_AW(MCI_OVLY_OPEN_PARMS);
-DECL_WINELIB_TYPE_AW(LPMCI_OVLY_OPEN_PARMS);
+DECL_WINELIB_TYPE_AW(MCI_OVLY_OPEN_PARMS)
+DECL_WINELIB_TYPE_AW(LPMCI_OVLY_OPEN_PARMS)
 
 typedef struct {
 	DWORD	dwCallback;
@@ -2502,8 +2502,8 @@
 	LPCWSTR	lpstrText;
 } MCI_OVLY_WINDOW_PARMS32W, *LPMCI_OVLY_WINDOW_PARMS32W;
 
-DECL_WINELIB_TYPE_AW(MCI_OVLY_WINDOW_PARMS);
-DECL_WINELIB_TYPE_AW(LPMCI_OVLY_WINDOW_PARMS);
+DECL_WINELIB_TYPE_AW(MCI_OVLY_WINDOW_PARMS)
+DECL_WINELIB_TYPE_AW(LPMCI_OVLY_WINDOW_PARMS)
 
 typedef struct {
 	DWORD   dwCallback;
@@ -2525,8 +2525,8 @@
 #endif  /* ifdef MCI_USE_OFFEXT */
 } MCI_OVLY_RECT_PARMS32, *LPMCI_OVLY_RECT_PARMS32;
 
-DECL_WINELIB_TYPE(MCI_OVLY_RECT_PARMS);
-DECL_WINELIB_TYPE(LPMCI_OVLY_RECT_PARMS);
+DECL_WINELIB_TYPE(MCI_OVLY_RECT_PARMS)
+DECL_WINELIB_TYPE(LPMCI_OVLY_RECT_PARMS)
 
 typedef struct {
 	DWORD   dwCallback;
@@ -2546,8 +2546,8 @@
 	RECT32  rc;
 } MCI_OVLY_SAVE_PARMS32W, *LPMCI_OVLY_SAVE_PARMS32W;
 
-DECL_WINELIB_TYPE_AW(MCI_OVLY_SAVE_PARMS);
-DECL_WINELIB_TYPE_AW(LPMCI_OVLY_SAVE_PARMS);
+DECL_WINELIB_TYPE_AW(MCI_OVLY_SAVE_PARMS)
+DECL_WINELIB_TYPE_AW(LPMCI_OVLY_SAVE_PARMS)
 
 typedef struct {
 	DWORD	dwCallback;
@@ -2567,8 +2567,8 @@
 	RECT32	rc;
 } MCI_OVLY_LOAD_PARMS32W, *LPMCI_OVLY_LOAD_PARMS32W;
 
-DECL_WINELIB_TYPE_AW(MCI_OVLY_LOAD_PARMS);
-DECL_WINELIB_TYPE_AW(LPMCI_OVLY_LOAD_PARMS);
+DECL_WINELIB_TYPE_AW(MCI_OVLY_LOAD_PARMS)
+DECL_WINELIB_TYPE_AW(LPMCI_OVLY_LOAD_PARMS)
 
 /**************************************************************
  * 		Linux MMSYSTEM Internals & Sample Audio Drivers
diff --git a/include/module.h b/include/module.h
index b998b6f..c0bb276 100644
--- a/include/module.h
+++ b/include/module.h
@@ -65,6 +65,8 @@
 
   /* Self-loading modules contain this structure in their first segment */
 
+#pragma pack(1)
+
 typedef struct
 {
     WORD      version;       /* Must be 0xA0 */
@@ -80,8 +82,6 @@
     FARPROC16 SetOwner;      /* Set Owner procedure, exported by wine */
 } SELFLOADHEADER;
 
-#pragma pack(1)
-
   /* Parameters for LoadModule() */
 typedef struct
 {
@@ -102,7 +102,7 @@
 #pragma pack(4)
 
 /* internal representation of 32bit modules. per process. */
-typedef enum { MODULE32_PE=1, MODULE32_ELF, /* ... */ } MODULE32_TYPE;
+typedef enum { MODULE32_PE=1, MODULE32_ELF /* ,... */ } MODULE32_TYPE;
 typedef struct _wine_modref
 {
 	struct _wine_modref	*next;
diff --git a/include/multimedia.h b/include/multimedia.h
index cb70d5c..d2dcc9c 100644
--- a/include/multimedia.h
+++ b/include/multimedia.h
@@ -73,4 +73,8 @@
 	HLOCAL16	hMidiHdr;
 	WORD	dwStatus;
 } LINUX_MCIMIDI;
+
+/* function prototypes */
+extern BOOL32 MULTIMEDIA_Init( void );
+
 #endif /* __WINE_MULTIMEDIA_H */
diff --git a/include/ole.h b/include/ole.h
index 42ba711..c21f067 100644
--- a/include/ole.h
+++ b/include/ole.h
@@ -17,11 +17,11 @@
 typedef BSTR32		*LPBSTR32;
 typedef LPWSTR		LPOLESTR32;
 typedef LPCWSTR		LPCOLESTR32;
-DECL_WINELIB_TYPE(OLECHAR);
-DECL_WINELIB_TYPE(LPOLESTR);
-DECL_WINELIB_TYPE(LPCOLESTR);
-DECL_WINELIB_TYPE(BSTR);
-DECL_WINELIB_TYPE(LPBSTR);
+DECL_WINELIB_TYPE(OLECHAR)
+DECL_WINELIB_TYPE(LPOLESTR)
+DECL_WINELIB_TYPE(LPCOLESTR)
+DECL_WINELIB_TYPE(BSTR)
+DECL_WINELIB_TYPE(LPBSTR)
 
 #define OLESTR16(x) x
 #define OLESTR32(x) L##x	/* probably wrong */
diff --git a/include/process.h b/include/process.h
index dbdfbf3..e669c2d 100644
--- a/include/process.h
+++ b/include/process.h
@@ -130,6 +130,7 @@
 extern void HANDLE_CloseAll( PDB32 *pdb, K32OBJ *ptr );
 
 /* scheduler/process.c */
+extern BOOL32 PROCESS_Init( void );
 extern PDB32 *PROCESS_Current(void);
 extern PDB32 *PROCESS_GetPtr( HANDLE32 handle, DWORD access );
 extern PDB32 *PROCESS_IdToPDB( DWORD id );
diff --git a/include/queue.h b/include/queue.h
index 14354ec..38136c5 100644
--- a/include/queue.h
+++ b/include/queue.h
@@ -95,6 +95,7 @@
 extern int QUEUE_FindMsg( MESSAGEQUEUE * msgQueue, HWND32 hwnd,
                           int first, int last );
 extern void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, int pos );
+extern void QUEUE_FlushMessages(HQUEUE16);
 extern void hardware_event( WORD message, WORD wParam, LONG lParam,
 			    int xPos, int yPos, DWORD time, DWORD extraInfo );
 
diff --git a/include/resource.h b/include/resource.h
index 0c89906..430763c 100644
--- a/include/resource.h
+++ b/include/resource.h
@@ -9,14 +9,24 @@
 
 #include "windows.h"
 
-struct resource
-{
-    int id;
-    int type;
-    const char *name;
-    const unsigned char* bytes;
-    unsigned size;
-};
+#ifndef __WRC_RSC_H
+#include "wrc_rsc.h"
+#endif
+
+/*
+ * BS: I comment this out to catch all occurences
+ * of reference to this structure which is now
+ * rendered obsolete.
+ *
+ * struct resource
+ * {
+ *     int id;
+ *     int type;
+ *     const char *name;
+ *     const unsigned char* bytes;
+ *     unsigned size;
+ * };
+ */
 
 /* Built-in resources */
 typedef enum
@@ -35,7 +45,7 @@
     SYSRES_DIALOG_REPLACE_TEXT
 } SYSTEM_RESOURCE;
 
-extern void LIBRES_RegisterResources(const struct resource* const * Res);
+extern void LIBRES_RegisterResources(const wrc_resource32_t * const * Res);
 
 #if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ >= 7)
 #define WINE_CONSTRUCTOR  __attribute__((constructor))
diff --git a/include/shell.h b/include/shell.h
index ee0ba36..27bb795 100644
--- a/include/shell.h
+++ b/include/shell.h
@@ -58,7 +58,7 @@
 	WCHAR	szTypeName[80];		/* type name */
 } SHFILEINFO32W;
 
-DECL_WINELIB_TYPE_AW(SHFILEINFO);
+DECL_WINELIB_TYPE_AW(SHFILEINFO)
 
 typedef struct _AppBarData {
 	DWORD	cbSize;
diff --git a/include/sig_context.h b/include/sig_context.h
index b1edc30..50def94 100644
--- a/include/sig_context.h
+++ b/include/sig_context.h
@@ -124,6 +124,7 @@
 #define FS_sig(context)      ((context)->sc_fs)
 #define GS_sig(context)      ((context)->sc_gs)
 #define CR2_sig(context)     ((context)->cr2)
+#define TRAP_sig(context)    ((context)->sc_trapno)
 #endif
                             
 #ifndef __FreeBSD__         
diff --git a/include/stackframe.h b/include/stackframe.h
index 5394c05..7a0196a 100644
--- a/include/stackframe.h
+++ b/include/stackframe.h
@@ -1,7 +1,7 @@
 /*
- * 16-bit mode stack frame layout
+ * 16-bit and 32-bit mode stack frame layout
  *
- * Copyright 1995 Alexandre Julliard
+ * Copyright 1995, 1998 Alexandre Julliard
  */
 
 #ifndef __WINE_STACKFRAME_H
@@ -78,4 +78,13 @@
           sizeof(STACK16FRAME)), \
   (thdb)->cur_stack += (size))
 
+/* Push a DWORD on the 32-bit stack */
+#define STACK32_PUSH(context,val) (*--((DWORD *)ESP_reg(context)) = (val))
+
+/* Pop a DWORD from the 32-bit stack */
+#define STACK32_POP(context) (*((DWORD *)ESP_reg(context))++)
+
+/* Win32 register functions */
+#define REGS_ENTRYPOINT(name) void WINAPI __regs_##name( CONTEXT *context )
+
 #endif /* __WINE_STACKFRAME_H */
diff --git a/include/storage.h b/include/storage.h
index dce219b..c25baf4 100644
--- a/include/storage.h
+++ b/include/storage.h
@@ -42,7 +42,7 @@
 
 typedef LPOLESTR16 *SNB16;
 typedef LPOLESTR32 *SNB32;
-DECL_WINELIB_TYPE(SNB);
+DECL_WINELIB_TYPE(SNB)
 
 typedef struct IStorage16 IStorage16,*LPSTORAGE16;
 typedef struct IStorage32 IStorage32,*LPSTORAGE32;
diff --git a/include/thread.h b/include/thread.h
index 090ce62..096eadf 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -139,6 +139,7 @@
 /* scheduler/synchro.c */
 extern void SYNC_WaitForCondition( WAIT_STRUCT *wait, DWORD timeout );
 extern void SYNC_WakeUp( THREAD_QUEUE *queue, DWORD max );
+extern void SYNC_SetupSignals(void);
 
 /* scheduler/sysdeps.c */
 extern int SYSDEPS_SpawnThread( THDB *thread );
diff --git a/include/toolbar.h b/include/toolbar.h
new file mode 100644
index 0000000..0cad32a
--- /dev/null
+++ b/include/toolbar.h
@@ -0,0 +1,55 @@
+/*
+ * Toolbar class extra info
+ *
+ * Copyright 1998 Eric Kohl
+ */
+
+#ifndef __WINE_TOOLBAR_H
+#define __WINE_TOOLBAR_H
+
+
+typedef struct tagTBUTTON_INFO
+{
+    INT32 iBitmap;
+    INT32 idCommand;
+    BYTE  fsState;
+    BYTE  fsStyle;
+    DWORD dwData;
+    INT32 iString;
+
+    RECT32 rect;
+
+} TBUTTON_INFO; 
+
+
+typedef struct tagTOOLBAR_INFO
+{
+    DWORD      dwStructSize;   /* Size of TBBUTTON-Struct */
+    INT32      nHeight;        /* Height of the Toolbar */
+    INT32      nWidth;         /* Width of the Toolbar */
+    INT32      nButtonTop;     /* top of the button rectangle */
+    INT32      nButtonHeight;
+    INT32      nButtonWidth;
+    INT32      nBitmapHeight;
+    INT32      nBitmapWidth;
+    INT32      nIndent;
+
+    INT32      nNumButtons;     /* Number of buttons */
+    INT32      nNumBitmaps;
+    INT32      nNumStrings;
+
+    BOOL32     bCaptured;
+    INT32      nButtonDown;
+    INT32      nOldHit;
+
+    HIMAGELIST himlDef;         /* default image list */
+    HIMAGELIST himlHot;         /* hot image list */
+    HIMAGELIST himlDis;         /* disabled image list */
+
+    TBUTTON_INFO *buttons;
+} TOOLBAR_INFO;
+
+
+extern void TOOLBAR_Register (void);
+
+#endif  /* __WINE_TOOLBAR_H */
diff --git a/include/version.h b/include/version.h
index 31e094f..0cc36b3 100644
--- a/include/version.h
+++ b/include/version.h
@@ -1 +1 @@
-#define WINE_RELEASE_INFO "Wine release 980517"
+#define WINE_RELEASE_INFO "Wine release 980601"
diff --git a/include/win.h b/include/win.h
index ebe47ce..9cffbe7 100644
--- a/include/win.h
+++ b/include/win.h
@@ -129,6 +129,10 @@
 extern HINSTANCE32 WIN_GetWindowInstance( HWND32 hwnd );
 extern WND**  WIN_BuildWinArray( WND *wndPtr, UINT32 bwa, UINT32* pnum );
 
+extern HWND32 CARET_GetHwnd(void);
+extern void CARET_GetRect(LPRECT32 lprc);  /* windows/caret.c */
+
+extern BOOL16 DRAG_QueryUpdate( HWND32, SEGPTR, BOOL32 );
 extern void DEFWND_SetText( WND *wndPtr, LPCSTR text );
 extern HBRUSH32 DEFWND_ControlColor( HDC32 hDC, UINT16 ctlType );     /* windows/defwnd.c */
 
@@ -138,9 +142,17 @@
                                   HRGN32 hrgnUpdate, UINT32 flags,
                                   UINT32 control );		      /* windows/painting.c */
 
-extern BOOL32 WIDGETS_IsControl32( WND* pWnd, BUILTIN_CLASS32 cls );  /* controls/widgets.c */
+/* controls/widgets.c */
+extern BOOL32 WIDGETS_Init( void );
+extern BOOL32 WIDGETS_IsControl32( WND* pWnd, BUILTIN_CLASS32 cls );  
 
-extern HWND32 ICONTITLE_Create( WND* );				      /* controls/icontitle.c */
+/* controls/icontitle.c */
+extern HWND32 ICONTITLE_Create( WND* );
+extern BOOL32 ICONTITLE_Init( void );
+
+/* windows/focus.c */
+extern void FOCUS_SetXFocus( HWND32 );
+extern void FOCUS_SwitchFocus( HWND32 , HWND32 );
 
 extern Display * display;
 extern Screen * screen;
diff --git a/include/win16drv.h b/include/win16drv.h
index d34e173..1298786 100644
--- a/include/win16drv.h
+++ b/include/win16drv.h
@@ -203,6 +203,7 @@
 
 /* Wine driver functions */
 
+extern BOOL32 WIN16DRV_Init(void);
 extern BOOL32 WIN16DRV_GetCharWidth( struct tagDC *dc, UINT32 firstChar, UINT32 lastChar,
 				   LPINT32 buffer );
 
diff --git a/include/winbase.h b/include/winbase.h
index 78835f2..22dc183 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -178,6 +178,7 @@
 void      WINAPI InitializeCriticalSection(CRITICAL_SECTION *lpCrit);
 void      WINAPI LeaveCriticalSection(CRITICAL_SECTION *lpCrit);
 HANDLE32  WINAPI OpenProcess(DWORD access, BOOL32 inherit, DWORD id);
+void      WINAPI RaiseException(DWORD,DWORD,DWORD,const LPDWORD);
 int       WINAPI TerminateProcess(HANDLE32 h, int ret);
 
 #endif  /* __WINE_WINBASE_H */
diff --git a/include/windows.h b/include/windows.h
index 957eb19..e28a171 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -5,7 +5,10 @@
 extern "C" {
 #endif
 
+#ifndef RC_INVOKED
 #include <stdarg.h>
+#endif
+
 #include "wintypes.h"
 
 #pragma pack(1)
@@ -2498,7 +2501,7 @@
 #define CSTF_TXIM	0x40
 
 /* SystemParametersInfo */
-
+/* defines below are for all win versions */
 #define SPI_GETBEEP               1
 #define SPI_SETBEEP               2
 #define SPI_GETMOUSE              3
@@ -2532,17 +2535,7 @@
 #define SPI_SETICONTITLELOGFONT   34
 #define SPI_GETFASTTASKSWITCH     35
 #define SPI_SETFASTTASKSWITCH     36
-#define SPI_SETDRAGFULLWINDOWS    37
-#define SPI_GETDRAGFULLWINDOWS    38
-#define SPI_GETNONCLIENTMETRICS   41
-#define SPI_SETNONCLIENTMETRICS   42
-#define SPI_GETMINIMIZEDMETRICS   43
-#define SPI_SETMINIMIZEDMETRICS   44
-#define SPI_GETICONMETRICS        45
-#define SPI_SETICONMETRICS        46
-#define SPI_SETWORKAREA           47
-#define SPI_GETWORKAREA           48
-#define SPI_SETPENWINDOWS         49
+
 #define SPI_GETFILTERKEYS         50
 #define SPI_SETFILTERKEYS         51
 #define SPI_GETTOGGLEKEYS         52
@@ -2555,10 +2548,25 @@
 #define SPI_SETSTICKYKEYS         59
 #define SPI_GETACCESSTIMEOUT      60
 #define SPI_SETACCESSTIMEOUT      61
-#define SPI_GETSERIALKEYS         62
-#define SPI_SETSERIALKEYS         63
+
 #define SPI_GETSOUNDSENTRY        64
 #define SPI_SETSOUNDSENTRY        65
+
+/* defines below are for all win versions WINVER >= 0x0400 */
+#define SPI_SETDRAGFULLWINDOWS    37
+#define SPI_GETDRAGFULLWINDOWS    38
+#define SPI_GETNONCLIENTMETRICS   41
+#define SPI_SETNONCLIENTMETRICS   42
+#define SPI_GETMINIMIZEDMETRICS   43
+#define SPI_SETMINIMIZEDMETRICS   44
+#define SPI_GETICONMETRICS        45
+#define SPI_SETICONMETRICS        46
+#define SPI_SETWORKAREA           47
+#define SPI_GETWORKAREA           48
+#define SPI_SETPENWINDOWS         49
+
+#define SPI_GETSERIALKEYS         62
+#define SPI_SETSERIALKEYS         63
 #define SPI_GETHIGHCONTRAST       66
 #define SPI_SETHIGHCONTRAST       67
 #define SPI_GETKEYBOARDPREF       68
@@ -2588,12 +2596,78 @@
 #define SPI_GETWINDOWSEXTENSION   92
 #define SPI_SETMOUSETRAILS        93
 #define SPI_GETMOUSETRAILS        94
-#define SPI_SCREENSAVERRUNNING    97
+#define SPI_SETSCREENSAVERRUNNING 97
+#define SPI_SCREENSAVERRUNNING    SPI_SETSCREENSAVERRUNNING
+
+/* defines below are for all win versions (_WIN32_WINNT >= 0x0400) ||
+ *                                        (_WIN32_WINDOWS > 0x0400) */
+#define SPI_GETMOUSEHOVERWIDTH    98
+#define SPI_SETMOUSEHOVERWIDTH    99
+#define SPI_GETMOUSEHOVERHEIGHT   100
+#define SPI_SETMOUSEHOVERHEIGHT   101
+#define SPI_GETMOUSEHOVERTIME     102
+#define SPI_SETMOUSEHOVERTIME     103
+#define SPI_GETWHEELSCROLLLINES   104
+#define SPI_SETWHEELSCROLLLINES   105
+
+#define SPI_GETSHOWIMEUI          110
+#define SPI_SETSHOWIMEUI          111
+
+/* defines below are for all win versions WINVER >= 0x0500 */
+#define SPI_GETMOUSESPEED         112
+#define SPI_SETMOUSESPEED         113
+#define SPI_GETSCREENSAVERRUNNING 114
+
+#define SPI_GETACTIVEWINDOWTRACKING    0x1000
+#define SPI_SETACTIVEWINDOWTRACKING    0x1001
+#define SPI_GETMENUANIMATION           0x1002
+#define SPI_SETMENUANIMATION           0x1003
+#define SPI_GETCOMBOBOXANIMATION       0x1004
+#define SPI_SETCOMBOBOXANIMATION       0x1005
+#define SPI_GETLISTBOXSMOOTHSCROLLING  0x1006
+#define SPI_SETLISTBOXSMOOTHSCROLLING  0x1007
+#define SPI_GETGRADIENTCAPTIONS        0x1008
+#define SPI_SETGRADIENTCAPTIONS        0x1009
+#define SPI_GETMENUUNDERLINES          0x100A
+#define SPI_SETMENUUNDERLINES          0x100B
+#define SPI_GETACTIVEWNDTRKZORDER      0x100C
+#define SPI_SETACTIVEWNDTRKZORDER      0x100D
+#define SPI_GETHOTTRACKING             0x100E
+#define SPI_SETHOTTRACKING             0x100F
+#define SPI_GETFOREGROUNDLOCKTIMEOUT   0x2000
+#define SPI_SETFOREGROUNDLOCKTIMEOUT   0x2001
+#define SPI_GETACTIVEWNDTRKTIMEOUT     0x2002
+#define SPI_SETACTIVEWNDTRKTIMEOUT     0x2003
+#define SPI_GETFOREGROUNDFLASHCOUNT    0x2004
+#define SPI_SETFOREGROUNDFLASHCOUNT    0x2005
 
 /* SystemParametersInfo flags */
 
-#define SPIF_UPDATEINIFILE		1
-#define SPIF_SENDWININICHANGE		2
+#define SPIF_UPDATEINIFILE              1
+#define SPIF_SENDWININICHANGE           2
+#define SPIF_SENDCHANGE                 SPIF_SENDWININICHANGE
+
+/* flags for HIGHCONTRAST dwFlags field */
+#define HCF_HIGHCONTRASTON  0x00000001
+#define HCF_AVAILABLE       0x00000002
+#define HCF_HOTKEYACTIVE    0x00000004
+#define HCF_CONFIRMHOTKEY   0x00000008
+#define HCF_HOTKEYSOUND     0x00000010
+#define HCF_INDICATOR       0x00000020
+#define HCF_HOTKEYAVAILABLE 0x00000040
+typedef struct tagHIGHCONTRASTA
+{
+    UINT32  cbSize;
+    DWORD   dwFlags;
+    LPSTR   lpszDefaultScheme;
+}   HIGHCONTRASTA, *LPHIGHCONTRASTA;
+
+typedef struct tagHIGHCONTRASTW
+{
+    UINT32  cbSize;
+    DWORD   dwFlags;
+    LPWSTR  lpszDefaultScheme;
+}   HIGHCONTRASTW, *LPHIGHCONTRASTW;
 
 /* GetFreeSystemResources() parameters */
 
@@ -3622,6 +3696,7 @@
 #define SS_TYPEMASK         0x0000001FL
 
 #define SS_NOPREFIX         0x00000080L
+#define SS_NOTIFY           0x00000100L
 #define SS_CENTERIMAGE      0x00000200L
 #define SS_RIGHTJUST        0x00000400L
 #define SS_REALSIZEIMAGE    0x00000800L
@@ -4446,9 +4521,19 @@
 #define VK_LMENU            0xA4
 #define VK_RMENU            0xA5
 /*                          0xA6-0xB9  Unassigned */
-/*                          0xBA-0xC0  OEM specific */
+#define VK_OEM_1            0xBA
+#define VK_OEM_PLUS         0xBB
+#define VK_OEM_COMMA        0xBC
+#define VK_OEM_MINUS        0xBD
+#define VK_OEM_PERIOD       0xBE
+#define VK_OEM_2            0xBF
+#define VK_OEM_3            0xC0
 /*                          0xC1-0xDA  Unassigned */
-/*                          0xDB-0xE4  OEM specific */
+#define VK_OEM_4            0xDB
+#define VK_OEM_5            0xDC
+#define VK_OEM_6            0xDD
+#define VK_OEM_7            0xDE
+/*                          0xDF-0xE4  OEM specific */
 
 #define VK_PROCESSKEY       0xE5
 
@@ -5948,6 +6033,19 @@
     UINT32 NegativeOrder;
 } NUMBERFMT32W;
 
+typedef enum _GET_FILEEX_INFO_LEVELS {
+    GetFileExInfoStandard
+} GET_FILEEX_INFO_LEVELS;
+
+typedef struct _WIN32_FILE_ATTRIBUTES_DATA {
+    DWORD    dwFileAttributes;
+    FILETIME ftCreationTime;
+    FILETIME ftLastAccessTime;
+    FILETIME ftLastWriteTime;
+    DWORD    nFileSizeHigh;
+    DWORD    nFileSizeLow;
+} WIN32_FILE_ATTRIBUTE_DATA, *LPWIN32_FILE_ATTRIBUTE_DATA;
+
 
 
 
@@ -6239,6 +6337,9 @@
 DWORD       WINAPI GetEnvironmentVariable32A(LPCSTR,LPSTR,DWORD);
 DWORD       WINAPI GetEnvironmentVariable32W(LPCWSTR,LPWSTR,DWORD);
 #define     GetEnvironmentVariable WINELIB_NAME_AW(GetEnvironmentVariable)
+BOOL32      WINAPI GetFileAttributesEx32A(LPCSTR,GET_FILEEX_INFO_LEVELS,LPVOID);
+BOOL32      WINAPI GetFileAttributesEx32W(LPCWSTR,GET_FILEEX_INFO_LEVELS,LPVOID);
+#define     GetFileattributesEx WINELIB_NAME_AW(GetFileAttributesEx)
 DWORD       WINAPI GetFileInformationByHandle(HFILE32,BY_HANDLE_FILE_INFORMATION*);
 DWORD       WINAPI GetFileSize(HFILE32,LPDWORD);
 BOOL32      WINAPI GetFileTime(HFILE32,LPFILETIME,LPFILETIME,LPFILETIME);
@@ -6366,6 +6467,9 @@
 BOOL32      WINAPI ReadConsole32A(HANDLE32,LPVOID,DWORD,LPDWORD,LPVOID);
 BOOL32      WINAPI ReadConsole32W(HANDLE32,LPVOID,DWORD,LPDWORD,LPVOID);
 #define     ReadConsole WINELIB_NAME_AW(ReadConsole)
+BOOL32      WINAPI ReadConsoleOutputCharacter32A(HANDLE32,LPSTR,DWORD,
+						 COORD,LPDWORD);
+#define     ReadConsoleOutputCharacter WINELIB_NAME_AW(ReadConsoleOutputCharacter)
 BOOL32      WINAPI ReadFile(HANDLE32,LPVOID,DWORD,LPDWORD,LPOVERLAPPED);
 LONG        WINAPI RegConnectRegistry32A(LPCSTR,HKEY,LPHKEY);
 LONG        WINAPI RegConnectRegistry32W(LPCWSTR,HKEY,LPHKEY);
@@ -6398,6 +6502,19 @@
                                       LPDWORD,LPDWORD,LPDWORD,LPDWORD,LPDWORD,
                                       LPDWORD,LPFILETIME);
 #define     RegQueryInfoKey WINELIB_NAME_AW(RegQueryInfoKey)
+LONG        WINAPI RegReplaceKey32A(HKEY,LPCSTR,LPCSTR,LPCSTR);
+LONG        WINAPI RegReplaceKey32W(HKEY,LPCWSTR,LPCWSTR,LPCWSTR);
+#define     RegReplaceKey WINELIB_NAME_AW(RegReplaceKey)
+LONG        WINAPI RegRestoreKey32A(HKEY,LPCSTR,DWORD);
+LONG        WINAPI RegRestoreKey32W(HKEY,LPCWSTR,DWORD);
+#define     RegRestoreKey WINELIB_NAME_AW(RegRestoreKey)
+LONG        WINAPI RegSaveKey32A(HKEY,LPCSTR,LPSECURITY_ATTRIBUTES);
+LONG        WINAPI RegSaveKey32W(HKEY,LPCWSTR,LPSECURITY_ATTRIBUTES);
+#define     RegSaveKey WINELIB_NAME_AW(RegSaveKey)
+LONG        WINAPI RegSetKeySecurity(HKEY,SECURITY_INFORMATION,LPSECURITY_DESCRIPTOR);
+LONG        WINAPI RegUnLoadKey32A(HKEY,LPCSTR);
+LONG        WINAPI RegUnLoadKey32W(HKEY,LPCWSTR);
+#define     RegUnLoadKey WINELIB_NAME_AW(RegUnLoadKey)
 BOOL32      WINAPI ReleaseSemaphore(HANDLE32,LONG,LPLONG);
 BOOL32      WINAPI ResetEvent(HANDLE32);
 VOID        WINAPI RtlFillMemory(LPVOID,UINT32,UINT32);
@@ -8737,9 +8854,9 @@
 BOOL32      WINAPI WinHelp32A(HWND32,LPCSTR,UINT32,DWORD);
 BOOL32      WINAPI WinHelp32W(HWND32,LPCWSTR,UINT32,DWORD);
 #define     WinHelp WINELIB_NAME_AW(WinHelp)
-UINT16      WNetAddConnection16(LPSTR,LPSTR,LPSTR);
-UINT32      WNetAddConnection32A(LPSTR,LPSTR,LPSTR);
-UINT32      WNetAddConnection32W(LPWSTR,LPWSTR,LPWSTR);
+UINT16      WINAPI WNetAddConnection16(LPCSTR,LPCSTR,LPCSTR);
+UINT32      WINAPI WNetAddConnection32A(LPCSTR,LPCSTR,LPCSTR);
+UINT32      WINAPI WNetAddConnection32W(LPCWSTR,LPCWSTR,LPCWSTR);
 #define     WNetAddConnection WINELIB_NAME_AW(WNetAddConnection)
 INT16       WINAPIV wsnprintf16(LPSTR,UINT16,LPCSTR,...);
 INT32       WINAPIV wsnprintf32A(LPSTR,UINT32,LPCSTR,...);
diff --git a/include/winnls.h b/include/winnls.h
index af6d7de..4967925 100644
--- a/include/winnls.h
+++ b/include/winnls.h
@@ -116,18 +116,29 @@
 #define NORM_IGNORENONSPACE			2
 #define NORM_IGNORESYMBOLS			4
 #define NORM_STRINGSORT				0x1000
+#define NORM_IGNOREKANATYPE                     0x00010000
+#define NORM_IGNOREWIDTH                        0x00020000
 
-#define CP_ACP						0
-#define CP_OEMCP					1
+#define CP_ACP					0
+#define CP_OEMCP				1
 
 #define WC_DEFAULTCHECK				0x00000100
 #define WC_COMPOSITECHECK			0x00000200
 #define WC_DISCARDNS				0x00000010
-#define WC_SEPCHARS					0x00000020
+#define WC_SEPCHARS				0x00000020
 #define WC_DEFAULTCHAR				0x00000040
 
-#define MAKELCID(l, s)    (MAKELONG(l, s))
-#define MAKELANGID(p, s)  ((((WORD)(s))<<10) | (WORD)(p))
+#define MAKELCID(l, s)		(MAKELONG(l, s))
+
+#define MAKELANGID(p, s)	((((WORD)(s))<<10) | (WORD)(p))
+#define PRIMARYLANGID(l)	((WORD)(l) & 0x3ff)
+#define SUBLANGID(l)		((WORD)(l) >> 10)
+
+#define LANG_SYSTEM_DEFAULT	(MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT))
+#define LANG_USER_DEFAULT	(MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT))
+#define LOCALE_SYSTEM_DEFAULT	(MAKELCID(LANG_SYSTEM_DEFAULT, SORT_DEFAULT))
+#define LOCALE_USER_DEFAULT	(MAKELCID(LANG_USER_DEFAULT, SORT_DEFAULT)) 
+
 
 /* Language IDs (were in winnt.h,  for some reason) */
 
@@ -178,17 +189,86 @@
 #define LANG_TURKISH                     0x1f
 #define LANG_UKRAINIAN                   0x22
 
-/* "default"ish values */
+/* Sublanguage definitions */
+#define SUBLANG_NEUTRAL                  0x00    /* language neutral */
+#define SUBLANG_DEFAULT                  0x01    /* user default */
+#define SUBLANG_SYS_DEFAULT              0x02    /* system default */
 
-#define SORT_DEFAULT      0
-#define SUBLANG_DEFAULT   1
-#define SUBLANG_SYS_DEFAULT 1 /* FIXME: I don't know if this is right */
+#define SUBLANG_ARABIC                   0x01
+#define SUBLANG_ARABIC_IRAQ              0x02
+#define SUBLANG_ARABIC_EGYPT             0x03
+#define SUBLANG_ARABIC_LIBYA             0x04
+#define SUBLANG_ARABIC_ALGERIA           0x05
+#define SUBLANG_ARABIC_MOROCCO           0x06
+#define SUBLANG_ARABIC_TUNISIA           0x07
+#define SUBLANG_ARABIC_OMAN              0x08
+#define SUBLANG_ARABIC_YEMEN             0x09
+#define SUBLANG_ARABIC_SYRIA             0x10
+#define SUBLANG_ARABIC_JORDAN            0x11
+#define SUBLANG_ARABIC_LEBANON           0x12
+#define SUBLANG_ARABIC_KUWAIT            0x13
+#define SUBLANG_ARABIC_UAE               0x14
+#define SUBLANG_ARABIC_BAHRAIN           0x15
+#define SUBLANG_ARABIC_QATAR             0x16
+#define SUBLANG_CHINESE_TRADITIONAL      0x01
+#define SUBLANG_CHINESE_SIMPLIFIED       0x02
+#define SUBLANG_CHINESE_HONGKONG         0x03
+#define SUBLANG_CHINESE_SINGAPORE        0x04
+#define SUBLANG_DUTCH                    0x01
+#define SUBLANG_DUTCH_BELGIAN            0x02
+#define SUBLANG_ENGLISH_US               0x01
+#define SUBLANG_ENGLISH_UK               0x02
+#define SUBLANG_ENGLISH_AUS              0x03
+#define SUBLANG_ENGLISH_CAN              0x04
+#define SUBLANG_ENGLISH_NZ               0x05
+#define SUBLANG_ENGLISH_EIRE             0x06
+#define SUBLANG_ENGLISH_SAFRICA          0x07
+#define SUBLANG_ENGLISH_JAMAICA          0x08
+#define SUBLANG_ENGLISH_CARRIBEAN        0x09
+#define SUBLANG_FRENCH                   0x01
+#define SUBLANG_FRENCH_BELGIAN           0x02
+#define SUBLANG_FRENCH_CANADIAN          0x03
+#define SUBLANG_FRENCH_SWISS             0x04
+#define SUBLANG_FRENCH_LUXEMBOURG        0x05
+#define SUBLANG_GERMAN                   0x01
+#define SUBLANG_GERMAN_SWISS             0x02
+#define SUBLANG_GERMAN_AUSTRIAN          0x03
+#define SUBLANG_GERMAN_LUXEMBOURG        0x04
+#define SUBLANG_GERMAN_LIECHTENSTEIN     0x05
+#define SUBLANG_ITALIAN                  0x01
+#define SUBLANG_ITALIAN_SWISS            0x02
+#define SUBLANG_KOREAN                   0x01
+#define SUBLANG_KOREAN_JOHAB             0x02
+#define SUBLANG_NORWEGIAN_BOKMAL         0x01
+#define SUBLANG_NORWEGIAN_NYNORSK        0x02
+#define SUBLANG_PORTUGUESE               0x02
+#define SUBLANG_PORTUGUESE_BRAZILIAN     0x01
+#define SUBLANG_SPANISH                  0x01
+#define SUBLANG_SPANISH_MEXICAN          0x02
+#define SUBLANG_SPANISH_MODERN           0x03
+#define SUBLANG_SPANISH_GUATEMALA        0x04
+#define SUBLANG_SPANISH_COSTARICA        0x05
+#define SUBLANG_SPANISH_PANAMA           0x06
+#define SUBLANG_SPANISH_DOMINICAN        0x07
+#define SUBLANG_SPANISH_VENEZUELA        0x08
+#define SUBLANG_SPANISH_COLOMBIA         0x09
+#define SUBLANG_SPANISH_PERU             0x10
+#define SUBLANG_SPANISH_ARGENTINA        0x11
+#define SUBLANG_SPANISH_ECUADOR          0x12
+#define SUBLANG_SPANISH_CHILE            0x13
+#define SUBLANG_SPANISH_URUGUAY          0x14
+#define SUBLANG_SPANISH_PARAGUAY         0x15
+#define SUBLANG_SPANISH_BOLIVIA          0x16
 
+/* Sort definitions */
+#define SORT_DEFAULT                     0x0
+#define SORT_JAPANESE_XJIS               0x0
+#define SORT_JAPANESE_UNICODE            0x1
+#define SORT_CHINESE_BIG5                0x0
+#define SORT_CHINESE_UNICODE             0x1
+#define SORT_KOREAN_KSC                  0x0
+#define SORT_KOREAN_UNICODE              0x1
 
-#define LANG_SYSTEM_DEFAULT   (MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT))
-#define LANG_USER_DEFAULT     (MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT))
-#define LOCALE_SYSTEM_DEFAULT (MAKELCID(LANG_SYSTEM_DEFAULT, SORT_DEFAULT))
-#define LOCALE_USER_DEFAULT   (MAKELCID(LANG_USER_DEFAULT, SORT_DEFAULT)) 
 
 /* Locale Dependent Mapping Flags */
 #define LCMAP_LOWERCASE	0x00000100	/* lower case letters */
@@ -196,6 +276,8 @@
 #define LCMAP_SORTKEY	0x00000400	/* WC sort key (normalize) */
 #define LCMAP_BYTEREV	0x00000800	/* byte reversal */
 
+#define SORT_STRINGSORT 0x00001000      /* take punctuation into account */
+
 #define LCMAP_HIRAGANA	0x00100000	/* map katakana to hiragana */
 #define LCMAP_KATAKANA	0x00200000	/* map hiragana to katakana */
 #define LCMAP_HALFWIDTH	0x00400000	/* map double byte to single byte */
@@ -216,5 +298,21 @@
 /* use this in a WineLib program if you really want all types */
 #define LOCALE_TIMEDATEBOTH    0x00000300  /* full set */
 
+/* Prototypes for Unicode case conversion routines */
+WCHAR towupper(WCHAR);
+WCHAR towlower(WCHAR);
+
+/* Definitions for IsTextUnicode() function */
+#define IS_TEXT_UNICODE_ASCII16		0x0001
+#define IS_TEXT_UNICODE_SIGNATURE	0x0008
+#define IS_TEXT_UNICODE_REVERSE_ASCII16	0x0010
+#define IS_TEXT_UNICODE_REVERSE_SIGNATURE 0x0080
+#define IS_TEXT_UNICODE_ILLEGAL_CHARS	0x0100
+#define IS_TEXT_UNICODE_ODD_LENGTH	0x0200
+
+/* Tests that we currently implement */
+#define ITU_IMPLEMENTED_TESTS \
+	IS_TEXT_UNICODE_SIGNATURE| \
+	IS_TEXT_UNICODE_ODD_LENGTH
 
 #endif  /* __WINE_WINNLS_H */
diff --git a/include/winnt.h b/include/winnt.h
index 0dca3f7..641df93 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -356,4 +356,11 @@
 #define FILE_GENERIC_EXECUTE      (STANDARD_RIGHTS_EXECUTE | FILE_EXECUTE | \
                                    FILE_READ_ATTRIBUTES | SYNCHRONIZE)
 
+
+/* Registry security values */
+#define OWNER_SECURITY_INFORMATION  0x00000001
+#define GROUP_SECURITY_INFORMATION  0x00000002
+#define DACL_SECURITY_INFORMATION   0x00000004
+#define SACL_SECURITY_INFORMATION   0x00000008
+
 #endif  /* __WINE_WINNT_H */
diff --git a/include/winsock.h b/include/winsock.h
index f8bf7ef..aa4bdca 100644
--- a/include/winsock.h
+++ b/include/winsock.h
@@ -15,6 +15,7 @@
 #include <netdb.h>
 #include <sys/socket.h>
 #include "windows.h"
+#include "task.h"
 
 #pragma pack(1)
 
@@ -164,8 +165,8 @@
 #define INVALID_SOCKET32 	   (~0)
 #define SOCKET_ERROR               (-1)
 
-DECL_WINELIB_TYPE(INVALID_SOCKET);
-DECL_WINELIB_TYPE(SOCKET);
+DECL_WINELIB_TYPE(INVALID_SOCKET)
+DECL_WINELIB_TYPE(SOCKET)
 
 /*
  * Types
@@ -563,6 +564,7 @@
   HTASK16               tid;    		/* owning task id - process might be better */
 } WSINFO, *LPWSINFO;
 
+/* function prototypes */
 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag);
 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag);
 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag);
@@ -571,6 +573,11 @@
 void WS_do_async_getproto(LPWSINFO, unsigned);
 void WS_do_async_getserv(LPWSINFO, unsigned);
 
+/* winsock_dns.c */
+extern HANDLE16 __WSAsyncDBQuery(LPWSINFO pwsi, HWND32 hWnd, UINT32 uMsg, 
+    INT32 type, LPCSTR init, INT32 len, LPCSTR proto, void* sbuf, 
+    INT32 buflen, UINT32 flag);
+
 int WINSOCK_async_io(int fd, int async);
 int WINSOCK_unblock_io(int fd, int noblock);
 
@@ -586,5 +593,7 @@
 UINT16 wsaErrno(void);
 UINT16 wsaHerrno(void);
 
+extern INT32 WINSOCK_DeleteTaskWSI( TDB* pTask, struct _WSINFO* );
+
 #endif  /* _WINSOCKAPI_ */
 
diff --git a/include/wrc_rsc.h b/include/wrc_rsc.h
new file mode 100644
index 0000000..7abfdf9
--- /dev/null
+++ b/include/wrc_rsc.h
@@ -0,0 +1,46 @@
+/*
+ * Wine Resource Compiler structure definitions
+ *
+ * Copyright 1998 Bertho A. Stultiens
+ *
+ */
+
+#if !defined(__WRC_RSC_H) && !defined(__WINE_WRC_RSC_H)
+#define __WRC_RSC_H
+#define __WINE_WRC_RSC_H
+
+#ifndef __WINE_WINTYPES_H
+#include <wintypes.h>		/* For types in structure */
+#endif
+
+/*
+ * Note on the resource and type names:
+ *
+ * These are (if non-null) pointers to a pascal-style
+ * string. The first character (BYTE for 16 bit and WCHAR
+ * for 32 bit resources) contains the length and the
+ * rest is the string. They are _not_ '\0' terminated!
+ */
+
+typedef struct wrc_resource16
+{
+	INT32	resid;		/* The resource id if resname == NULL */
+	LPSTR	resname;
+	INT32	restype;	/* The resource type-id if typename == NULL */
+	LPSTR	typename;
+	LPBYTE	data;		/* Actual resource data */
+	UINT32	datasize;	/* The size of the resource */
+} wrc_resource16_t;
+
+typedef struct wrc_resource32
+{
+	INT32	resid;		/* The resource id if resname == NULL */
+	LPWSTR	resname;
+	INT32	restype;	/* The resource type-id if typename == NULL */
+	LPWSTR	typename;
+	LPBYTE	data;		/* Actual resource data */
+	UINT32	datasize;	/* The size of the resource */
+} wrc_resource32_t;
+
+#endif
+
diff --git a/include/x11drv.h b/include/x11drv.h
index 78d911d..c96a6fc 100644
--- a/include/x11drv.h
+++ b/include/x11drv.h
@@ -51,6 +51,7 @@
 struct tagDC;
 struct tagDeviceCaps;
 
+extern BOOL32 X11DRV_Init(void);
 extern BOOL32 X11DRV_BitBlt( struct tagDC *dcDst, INT32 xDst, INT32 yDst,
                              INT32 width, INT32 height, struct tagDC *dcSrc,
                              INT32 xSrc, INT32 ySrc, DWORD rop );
@@ -116,4 +117,6 @@
 
 extern CRITICAL_SECTION X11DRV_CritSection;
 
+extern void _XInitImageFuncPtrs(XImage *);
+
 #endif  /* __WINE_X11DRV_H */
diff --git a/ipc/dde_atom.c b/ipc/dde_atom.c
index 504280f..f1cd4bf 100644
--- a/ipc/dde_atom.c
+++ b/ipc/dde_atom.c
@@ -11,7 +11,6 @@
 #include <ctype.h>
 #include <string.h>
 #include <stdlib.h>
-#include <stdio.h>
 #include "dde_atom.h"
 #include "shm_main_blk.h"
 #include "shm_fragment.h"
@@ -187,7 +186,7 @@
   switch (atom_ofs=ATOM_OFS(atom_idx)) {
     case DELETED:
     case EMPTY:
-      fprintf(stderr,"trying to free unallocated atom %d\n", atom);
+      WARN(atom, "Trying to free unallocated atom %d\n", atom);
       retval=atom;
       break;
     default :
@@ -273,7 +272,7 @@
   shm_read_wait(main_block->sem);
   atom_ofs=ATOM_OFS(atom_idx);
   if (atom_ofs==EMPTY || atom_ofs==DELETED) {
-     fprintf(stderr,"GlobalGetAtomName: illegal atom=%d\n",(int)atom);
+     WARN(atom,"Illegal atom=%d\n",(int)atom);
      size=0;
   } else {			   /* non empty entry */
      /* string length will be at most count-1, find actual size */
diff --git a/ipc/dde_mem.c b/ipc/dde_mem.c
index 504b330..ecfd164 100644
--- a/ipc/dde_mem.c
+++ b/ipc/dde_mem.c
@@ -9,7 +9,6 @@
  */
 #ifdef CONFIG_IPC
 
-#include <stdio.h>
 #include <assert.h>
 #include "debug.h"
 #include "ldt.h"
@@ -136,7 +135,7 @@
        h_info= (struct handle_info *)
 	  shm_FragPtrAlloc(block, size+sizeof(struct handle_info));
        if (h_info==NULL) {
-	  fprintf(stderr,"DDE_malloc: BUG! unallocated fragment\n");
+	  ERR(global,"BUG! unallocated fragment\n");
 	  shm_write_signal(main_block->proc[curr_proc_idx].sem);
 	  return 0;
        }
diff --git a/ipc/dde_proc.c b/ipc/dde_proc.c
index 5d4ae1d..379538f 100644
--- a/ipc/dde_proc.c
+++ b/ipc/dde_proc.c
@@ -139,7 +139,7 @@
   }
   else	{
      fflush(stdout);
-     fprintf(stderr,"dde_proc_add: Can't allocate process\n");
+     WARN(dde,"Can't allocate process\n");
   }
   shm_write_signal(main_block->sem);
 }
@@ -231,7 +231,7 @@
 	return TRUE;
      } else {
 	fflush(stdout);
-	fprintf(stderr,"get_ack: DDE_DoOneMessage: timeout\n");
+	WARN(dde,"get_ack: DDE_DoOneMessage: timeout\n");
 	return FALSE;
      }
   }
@@ -278,8 +278,7 @@
     return IDX_TO_HWND(dde_wnd_idx);
   }
 
-  fprintf(stderr,
-	  "HWND_Local2Remote: Can't map any more windows to DDE windows\n");
+  WARN(dde, "Can't map any more windows to DDE windows\n");
   return 0;			
 }
 
diff --git a/ipc/shm_block.c b/ipc/shm_block.c
index 6feabd5..25e3881 100644
--- a/ipc/shm_block.c
+++ b/ipc/shm_block.c
@@ -12,7 +12,6 @@
 #define inline __inline__
 #include <sys/types.h>
 #include <sys/sem.h>
-#include <stdio.h>
 #include <assert.h>
 #include <unistd.h>
 #include <stdlib.h>
diff --git a/ipc/shm_fragment.c b/ipc/shm_fragment.c
index f5ec7bf..dac3431 100644
--- a/ipc/shm_fragment.c
+++ b/ipc/shm_fragment.c
@@ -167,14 +167,14 @@
 
   item=block->free_list;
   if (item==0) {
-     fprintf(stddeb,"no free fragments");
+     DUMP("no free fragments");
   } else {
      for (; item ; item=fragment->info.next) {
 	fragment=FRAG_PTR(block,item);
-	fprintf(stddeb,"{0x%04x,0x%04x} ",item,fragment->size);
+	DUMP("{0x%04x,0x%04x} ",item,fragment->size);
      }
   }
-  fprintf(stddeb," [total free=%04x]\n",block->free);
+  DUMP(" [total free=%04x]\n",block->free);
   fflush(stddeb);
 }
 
diff --git a/ipc/shm_main_blk.c b/ipc/shm_main_blk.c
index 7c6e90e..4458f5c 100644
--- a/ipc/shm_main_blk.c
+++ b/ipc/shm_main_blk.c
@@ -12,7 +12,6 @@
 #define inline __inline__
 #include <sys/types.h>
 #include <sys/sem.h>
-#include <stdio.h>
 #include <time.h>
 #include <assert.h>
 #include <unistd.h>
@@ -252,8 +251,7 @@
 {
   if ( !shm_locate_MainBlock(WineKey)
        && !shm_create_MainBlock(WineKey)) { 
-     fflush(stdout);
-     fprintf(stderr,"shm_init: failed to init main shm block\n");
+     ERR(shm, "Failed to init main shm block\n");
      exit(1);
   }
 
diff --git a/ipc/shm_semaph.c b/ipc/shm_semaph.c
index 3fbe0ad..d63f1e5 100644
--- a/ipc/shm_semaph.c
+++ b/ipc/shm_semaph.c
@@ -13,7 +13,6 @@
 #include <assert.h>
 #include <unistd.h>
 #include <sys/sem.h>
-#include <stdio.h>
 #include <errno.h>
 #include "debug.h"
 #include "shm_semaph.h"
@@ -42,8 +41,8 @@
   } while (ret<0 && errno==EINTR);  /* interrupted system call? */
   
   if (ret<0) 
-     fprintf(stderr,"failed semaphore lock for read. semid=%d,errno=%d\n",
-	     semid, errno);
+     WARN(sem,"(semid=%d,errno=%d): Failed semaphore lock for read\n",
+         semid, errno);
 }
 void shm_write_wait(shm_sem semid)
 {
@@ -68,7 +67,7 @@
   } while (ret<0 && errno==EINTR);  /* interrupted system call? */
 
   if (ret<0) 			   /* test for the error */
-     fprintf(stderr,"failed semaphore lock for write. semid=%d,errno=%d\n",
+     WARN(sem,"(semid=%d,errno=%d): Failed semaphore lock for write\n",
 	     semid, errno);
 }
 void shm_write_signal(shm_sem semid)
@@ -90,7 +89,7 @@
   } while (ret<0 && errno==EINTR);  /* interrupted system call? */
 
   if (ret<0) 			   /* test for the error */
-     fprintf(stderr,"failed semaphore unlock for write. semid=%d,errno=%d\n",
+     WARN(sem,"(semid=%d,errno=%d): Failed semaphore unlock for write\n",
 	     semid, errno);
 }
 
@@ -109,7 +108,7 @@
   } while (ret<0 && errno==EINTR);  /* interrupted system call? */
 
   if (ret<0) 			   /* test for the error */
-     fprintf(stderr,"failed semaphore unlock for read. semid=%d,errno=%d\n",
+     WARN(sem,"(semid=%d,errno=%d): Failed semaphore unlock for read\n",
 	     semid, errno);
 }
 
diff --git a/loader/libres.c b/loader/libres.c
index eb9598b..3579b0a 100644
--- a/loader/libres.c
+++ b/loader/libres.c
@@ -4,7 +4,6 @@
  * Copied and modified heavily from loader/resource.c
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include "debug.h"
 #include "libres.h"
@@ -14,13 +13,13 @@
 
 typedef struct RLE
 {
-    const struct resource* const * Resources;  /* NULL-terminated array of pointers */
+    const wrc_resource32_t * const * Resources;  /* NULL-terminated array of pointers */
     struct RLE* next;
 } ResListE;
 
 static ResListE* ResourceList=NULL;
 
-void LIBRES_RegisterResources(const struct resource* const * Res)
+void LIBRES_RegisterResources(const wrc_resource32_t * const * Res)
 {
   ResListE** Curr;
   ResListE* n;
@@ -38,7 +37,7 @@
 {
   int nameid=0,typeid;
   ResListE* ResBlock;
-  const struct resource* const * Res;
+  const wrc_resource32_t* const * Res;
 
   if(HIWORD(name))
   {
@@ -72,15 +71,16 @@
   else
     typeid=LOWORD(type);
   
+  /* FIXME: types can be strings */
   for(ResBlock=ResourceList; ResBlock; ResBlock=ResBlock->next)
     for(Res=ResBlock->Resources; *Res; Res++)
       if(name)
       {
-	if((*Res)->type==typeid && !lstrcmpi32W((LPCWSTR)(*Res)->name,name))
+	if((*Res)->restype==typeid && !lstrncmpi32W((LPCWSTR)((*Res)->resname+1), name, *((*Res)->resname)))
 	  return (HRSRC32)*Res;
       }
       else
-	if((*Res)->type==typeid && (*Res)->id==nameid)
+	if((*Res)->restype==typeid && (*Res)->resid==nameid)
 	  return (HRSRC32)*Res;
   return 0;
 }
@@ -91,7 +91,7 @@
  */
 HGLOBAL32 LIBRES_LoadResource( HINSTANCE32 hModule, HRSRC32 hRsrc )
 {
-  return (HGLOBAL32)(((struct resource*)hRsrc)->bytes);
+  return (HGLOBAL32)(((wrc_resource32_t*)hRsrc)->data);
 }
 
 
@@ -100,5 +100,5 @@
  */
 DWORD LIBRES_SizeofResource( HINSTANCE32 hModule, HRSRC32 hRsrc )
 {
-  return (DWORD)(((struct resource*)hRsrc)->size);
+  return (DWORD)(((wrc_resource32_t*)hRsrc)->datasize);
 }
diff --git a/loader/main.c b/loader/main.c
index 5b1eaec..5f592a6 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -2,7 +2,6 @@
  * Main initialization code
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -16,6 +15,8 @@
 #include "win.h"
 #include "main.h"
 #include "menu.h"
+#include "message.h"
+#include "multimedia.h"
 #include "atom.h"
 #include "dialog.h"
 #include "drive.h"
@@ -27,6 +28,7 @@
 #include "keyboard.h"
 #include "miscemu.h"
 #include "options.h"
+#include "process.h"
 #include "spy.h"
 #include "tweak.h"
 #include "user.h"
@@ -43,8 +45,6 @@
  */
 BOOL32 MAIN_KernelInit(void)
 {
-    extern BOOL32 EVENT_Init(void);
-
     /* Initialize signal handling */
     if (!SIGNAL_Init()) return FALSE;
 
@@ -78,9 +78,6 @@
  */
 BOOL32 MAIN_UserInit(void)
 {
-    extern BOOL32 WIDGETS_Init(void);
-    extern BOOL32 MULTIMEDIA_Init(void);
-
     int queueSize;
 
     /* Create USER and GDI heap */
@@ -160,8 +157,6 @@
  */
 BOOL32 MAIN_WinelibInit( int *argc, char *argv[] )
 {
-    extern BOOL32 PROCESS_Init(void);
-
     /* Create the initial process */
     if (!PROCESS_Init()) return FALSE;
 
diff --git a/loader/module.c b/loader/module.c
index 17f1bb0..c04e2b2 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -7,7 +7,6 @@
 #include <assert.h>
 #include <fcntl.h>
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include <sys/types.h>
 #include <unistd.h>
diff --git a/loader/ne/module.c b/loader/ne/module.c
index 0a2fe70..893c834 100644
--- a/loader/ne/module.c
+++ b/loader/ne/module.c
@@ -49,7 +49,7 @@
 
     if (!(pModule = NE_GetPtr( hModule )))
     {
-        fprintf( stderr, "**** %04x is not a module handle\n", hModule );
+        MSG( "**** %04x is not a module handle\n", hModule );
         return;
     }
 
@@ -189,16 +189,16 @@
 void NE_WalkModules(void)
 {
     HMODULE16 hModule = hFirstModule;
-    fprintf( stderr, "Module Flags Name\n" );
+    MSG( "Module Flags Name\n" );
     while (hModule)
     {
         NE_MODULE *pModule = NE_GetPtr( hModule );
         if (!pModule)
         {
-            fprintf( stderr, "**** Bad module %04x in list\n", hModule );
+            MSG( "Bad module %04x in list\n", hModule );
             return;
         }
-        fprintf( stderr, " %04x  %04x  %.*s\n", hModule, pModule->flags,
+        MSG( " %04x  %04x  %.*s\n", hModule, pModule->flags,
                  *((char *)pModule + pModule->name_table),
                  (char *)pModule + pModule->name_table + 1 );
         hModule = pModule->next;
@@ -716,11 +716,7 @@
 /**********************************************************************
  *	    NE_LoadModule
  *
- * Implementation of LoadModule().
- *
- * cmd_line must contain the whole command-line, including argv[0] (and
- * without a preceding length byte).
- * If cmd_line is NULL, the module is loaded as a library even if it is a .exe
+ * Implementation of LoadModule16().
  */
 HINSTANCE16 NE_LoadModule( LPCSTR name, HINSTANCE16 *hPrevInstance,
                            BOOL32 implicit, BOOL32 lib_only )
diff --git a/loader/ne/resource.c b/loader/ne/resource.c
index 807871d..7339467 100644
--- a/loader/ne/resource.c
+++ b/loader/ne/resource.c
@@ -513,7 +513,7 @@
     NE_TYPEINFO *pTypeInfo;
     NE_NAMEINFO *pNameInfo;
     WORD count;
-    NE_MODULE *pModule = NE_GetPtr( GetExePtr(handle) );
+    NE_MODULE *pModule = NE_GetPtr( FarGetOwner(handle) );
 
     if (!handle || !pModule || !pModule->res_table) return handle;
 
diff --git a/loader/ne/segment.c b/loader/ne/segment.c
index a6478a5..719d6d1 100644
--- a/loader/ne/segment.c
+++ b/loader/ne/segment.c
@@ -521,6 +521,46 @@
     }
 }
 
+/***********************************************************************
+ *           NE_GetDLLInitParams
+ */
+static VOID NE_GetDLLInitParams( NE_MODULE *pModule, 
+				 WORD *hInst, WORD *ds, WORD *heap )
+{
+    SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
+
+    if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
+    {
+        if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
+        {
+            /* Not SINGLEDATA */
+            ERR(dll, "Library is not marked SINGLEDATA\n");
+            exit(1);
+        }
+        else  /* DATA NONE DLL */
+        {
+            *ds = 0;
+            *heap = 0;
+        }
+    }
+    else  /* DATA SINGLE DLL */
+    {
+	if (pModule->dgroup) {
+            *ds   = pSegTable[pModule->dgroup-1].selector;
+            *heap = pModule->heap_size;
+	}
+	else /* hmm, DLL has no dgroup,
+		but why has it NE_FFLAGS_SINGLEDATA set ?
+		Buggy DLL compiler ? */
+	{
+            *ds   = 0;
+            *heap = 0;
+	}
+    }
+
+    *hInst = *ds ? *ds : pModule->self;
+}
+
 
 /***********************************************************************
  *           NE_InitDLL
@@ -530,15 +570,9 @@
 static BOOL32 NE_InitDLL( TDB* pTask, NE_MODULE *pModule )
 {
     SEGTABLEENTRY *pSegTable;
+    WORD hInst, ds, heap, fs;
     CONTEXT context;
 
-    /* Registers at initialization must be:
-     * cx     heap size
-     * di     library instance
-     * ds     data segment if any
-     * es:si  command line (always 0)
-     */
-
     pSegTable = NE_SEG_TABLE( pModule );
 
     if (!(pModule->flags & NE_FFLAGS_LIBMODULE) ||
@@ -556,42 +590,29 @@
 
     if (!pModule->cs) return TRUE;  /* no initialization code */
 
+
+    /* Registers at initialization must be:
+     * cx     heap size
+     * di     library instance
+     * ds     data segment if any
+     * es:si  command line (always 0)
+     */
+
     memset( &context, 0, sizeof(context) );
 
-    if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
-    {
-        if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
-        {
-            /* Not SINGLEDATA */
-            ERR(dll, "Library is not marked SINGLEDATA\n");
-            exit(1);
-        }
-        else  /* DATA NONE DLL */
-        {
-            DS_reg(&context)  = 0;
-            ECX_reg(&context) = 0;
-        }
-    }
-    else  /* DATA SINGLE DLL */
-    {
-	if (pModule->dgroup) {
-            DS_reg(&context)  = pSegTable[pModule->dgroup-1].selector;
-            ECX_reg(&context) = pModule->heap_size;
-	}
-	else /* hmm, DLL has no dgroup,
-		but why has it NE_FFLAGS_SINGLEDATA set ?
-		Buggy DLL compiler ? */
-	{
-            DS_reg(&context)  = 0;
-            ECX_reg(&context) = 0;
-	}
-    }
+    NE_GetDLLInitParams( pModule, &hInst, &ds, &heap );
+    GET_FS( fs );
+
+    ECX_reg(&context) = heap;
+    EDI_reg(&context) = hInst;
+    DS_reg(&context)  = ds;
+    ES_reg(&context)  = ds;   /* who knows ... */
+    FS_reg(&context)  = fs;
 
     CS_reg(&context)  = pSegTable[pModule->cs-1].selector;
     EIP_reg(&context) = pModule->ip;
     EBP_reg(&context) = OFFSETOF(THREAD_Current()->cur_stack)
                           + (WORD)&((STACK16FRAME*)0)->bp;
-    EDI_reg(&context) = DS_reg(&context) ? DS_reg(&context) : pModule->self;
 
 
     pModule->cs = 0;  /* Don't initialize it twice */
@@ -610,6 +631,7 @@
 
 static void NE_CallDllEntryPoint( NE_MODULE *pModule, DWORD dwReason )
 {
+    WORD hInst, ds, heap, fs;
     FARPROC16 entryPoint;
     WORD ordinal;
     CONTEXT context;
@@ -622,15 +644,22 @@
 
     memset( &context, 0, sizeof(context) );
 
+    NE_GetDLLInitParams( pModule, &hInst, &ds, &heap );
+    GET_FS( fs );
+
+    DS_reg(&context) = ds;
+    ES_reg(&context) = ds;   /* who knows ... */
+    FS_reg(&context) = fs;
+
     CS_reg(&context) = HIWORD(entryPoint);
     IP_reg(&context) = LOWORD(entryPoint);
     EBP_reg(&context) =  OFFSETOF( thdb->cur_stack )
                          + (WORD)&((STACK16FRAME*)0)->bp;
 
     *(DWORD *)(stack -  4) = dwReason;      /* dwReason */
-    *(WORD *) (stack -  6) = pModule->self; /* hInst */
-    *(WORD *) (stack -  8) = 0;             /* wDS */
-    *(WORD *) (stack - 10) = 0;             /* wHeapSize */
+    *(WORD *) (stack -  6) = hInst;         /* hInst */
+    *(WORD *) (stack -  8) = ds;            /* wDS */
+    *(WORD *) (stack - 10) = heap;          /* wHeapSize */
     *(DWORD *)(stack - 14) = 0;             /* dwReserved1 */
     *(WORD *) (stack - 16) = 0;             /* wReserved2 */
 
diff --git a/loader/pe_image.c b/loader/pe_image.c
index 3d2dfbd..ef6734a 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -38,7 +38,6 @@
 
 #include <errno.h>
 #include <assert.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -251,7 +250,7 @@
 	    res = PE_LoadLibraryEx32A( buffer, process, 0, 0 );
 	}
 	if (res <= (HMODULE32) 32) {
-	    WARN (module, "Module %s not found\n", name);
+	    ERR (module, "Module %s not found\n", name);
 	    return res;
 	}
 	xwm = wm->next;
@@ -793,6 +792,7 @@
         if (wm->module < 32) 
         {
 	    process->modref_list = wm->next;
+	    FreeLibrary16( hModule);
 	    HeapFree(process->heap,0,wm);
 	    ERR(win32,"can't load %s\n",ofs.szPathName);
             return 21; /* FIXME: probably 0 */
diff --git a/loader/resource.c b/loader/resource.c
index c4bec2f..e4b2a2a 100644
--- a/loader/resource.c
+++ b/loader/resource.c
@@ -6,7 +6,6 @@
  */
 
 #include <assert.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
diff --git a/loader/task.c b/loader/task.c
index 2d25eac..a842c08 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -4,7 +4,6 @@
  * Copyright 1995 Alexandre Julliard
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -29,6 +28,7 @@
 #include "thread.h"
 #include "toolhelp.h"
 #include "winnt.h"
+#include "winsock.h"
 #include "thread.h"
 #include "debug.h"
 #include "dde_proc.h"
@@ -36,8 +36,6 @@
   /* Min. number of thunks allocated when creating a new segment */
 #define MIN_THUNKS  32
 
-extern INT32 WINSOCK_DeleteTaskWSI( TDB* pTask, struct _WSINFO* );
-
   /* Pointer to function to switch to a larger stack */
 int (*IF1632_CallLargeStack)( int (*func)(), void *arg ) = NULL;
 
@@ -971,7 +969,11 @@
 
     /* Save the old stack */
 
-    pData->old_ss_sp   = pTask->thdb->cur_stack;
+    oldFrame = THREAD_STACK16( pTask->thdb );
+    /* pop frame + args and push bp */
+    pData->old_ss_sp   = pTask->thdb->cur_stack - sizeof(STACK16FRAME)
+                           - 2 * sizeof(WORD);
+    *(WORD *)PTR_SEG_TO_LIN(pData->old_ss_sp) = oldFrame->bp;
     pData->stacktop    = top;
     pData->stackmin    = ptr;
     pData->stackbottom = ptr;
@@ -981,15 +983,16 @@
     /* Note: we need to take the 3 arguments into account; otherwise,
      * the stack will underflow upon return from this function.
      */
-    oldFrame = (STACK16FRAME *)PTR_SEG_TO_LIN( pTask->thdb->cur_stack );
-    pTask->thdb->cur_stack = PTR_SEG_OFF_TO_SEGPTR( seg,
-                             ptr - sizeof(STACK16FRAME) - 3 * sizeof(WORD) );
-    newFrame = (STACK16FRAME *)PTR_SEG_TO_LIN( pTask->thdb->cur_stack );
+    copySize = oldFrame->bp - OFFSETOF(pData->old_ss_sp);
+    copySize += 3 * sizeof(WORD) + sizeof(STACK16FRAME);
+    pTask->thdb->cur_stack = PTR_SEG_OFF_TO_SEGPTR( seg, ptr - copySize );
+    newFrame = THREAD_STACK16( pTask->thdb );
 
     /* Copy the stack frame and the local variables to the new stack */
 
-    copySize = oldFrame->bp - OFFSETOF(pData->old_ss_sp);
-    memmove( newFrame, oldFrame, MAX( copySize, sizeof(STACK16FRAME) ));
+    memmove( newFrame, oldFrame, copySize );
+    newFrame->bp = ptr;
+    *(WORD *)PTR_SEG_OFF_TO_LIN( seg, ptr ) = 0;  /* clear previous bp */
 }
 
 
@@ -1013,18 +1016,23 @@
     TRACE(task, "restoring stack %04x:%04x\n",
 		 SELECTOROF(pData->old_ss_sp), OFFSETOF(pData->old_ss_sp) );
 
-    oldFrame = (STACK16FRAME *)PTR_SEG_TO_LIN( pTask->thdb->cur_stack );
+    oldFrame = THREAD_STACK16( pTask->thdb );
+
+    /* Pop bp from the previous stack */
+
+    BP_reg(context) = *(WORD *)PTR_SEG_TO_LIN(pData->old_ss_sp);
+    pData->old_ss_sp += sizeof(WORD);
 
     /* Switch back to the old stack */
 
-    pTask->thdb->cur_stack = pData->old_ss_sp;
+    pTask->thdb->cur_stack = pData->old_ss_sp - sizeof(STACK16FRAME);
     SS_reg(context)  = SELECTOROF(pData->old_ss_sp);
-    ESP_reg(context) = OFFSETOF(pData->old_ss_sp);
+    ESP_reg(context) = OFFSETOF(pData->old_ss_sp) - sizeof(DWORD); /*ret addr*/
     pData->old_ss_sp = 0;
 
     /* Build a stack frame for the return */
 
-    newFrame = (STACK16FRAME *)PTR_SEG_TO_LIN( pTask->thdb->cur_stack );
+    newFrame = THREAD_STACK16( pTask->thdb );
     newFrame->frame32 = oldFrame->frame32;
     if (TRACE_ON(relay))
     {
diff --git a/memory/heap.c b/memory/heap.c
index b604f7c..6585ac5 100644
--- a/memory/heap.c
+++ b/memory/heap.c
@@ -5,7 +5,6 @@
  */
 
 #include <assert.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "windows.h"
diff --git a/memory/ldt.c b/memory/ldt.c
index 4ebd231..1441907 100644
--- a/memory/ldt.c
+++ b/memory/ldt.c
@@ -5,7 +5,6 @@
  * Copyright 1995 Alexandre Julliard
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
diff --git a/memory/selector.c b/memory/selector.c
index 8edbc2e..f6290d8 100644
--- a/memory/selector.c
+++ b/memory/selector.c
@@ -621,17 +621,17 @@
     EAX_reg(context) = ptr;
 }
 
-void WINAPI SMapLS_IP_EBP_8(CONTEXT *context)  {x_SMapLS_IP_EBP_x(context,8);}
-void WINAPI SMapLS_IP_EBP_12(CONTEXT *context) {x_SMapLS_IP_EBP_x(context,12);}
-void WINAPI SMapLS_IP_EBP_16(CONTEXT *context) {x_SMapLS_IP_EBP_x(context,16);}
-void WINAPI SMapLS_IP_EBP_20(CONTEXT *context) {x_SMapLS_IP_EBP_x(context,20);}
-void WINAPI SMapLS_IP_EBP_24(CONTEXT *context) {x_SMapLS_IP_EBP_x(context,24);}
-void WINAPI SMapLS_IP_EBP_28(CONTEXT *context) {x_SMapLS_IP_EBP_x(context,28);}
-void WINAPI SMapLS_IP_EBP_32(CONTEXT *context) {x_SMapLS_IP_EBP_x(context,32);}
-void WINAPI SMapLS_IP_EBP_36(CONTEXT *context) {x_SMapLS_IP_EBP_x(context,36);}
-void WINAPI SMapLS_IP_EBP_40(CONTEXT *context) {x_SMapLS_IP_EBP_x(context,40);}
+REGS_ENTRYPOINT(SMapLS_IP_EBP_8)  {x_SMapLS_IP_EBP_x(context,8);}
+REGS_ENTRYPOINT(SMapLS_IP_EBP_12) {x_SMapLS_IP_EBP_x(context,12);}
+REGS_ENTRYPOINT(SMapLS_IP_EBP_16) {x_SMapLS_IP_EBP_x(context,16);}
+REGS_ENTRYPOINT(SMapLS_IP_EBP_20) {x_SMapLS_IP_EBP_x(context,20);}
+REGS_ENTRYPOINT(SMapLS_IP_EBP_24) {x_SMapLS_IP_EBP_x(context,24);}
+REGS_ENTRYPOINT(SMapLS_IP_EBP_28) {x_SMapLS_IP_EBP_x(context,28);}
+REGS_ENTRYPOINT(SMapLS_IP_EBP_32) {x_SMapLS_IP_EBP_x(context,32);}
+REGS_ENTRYPOINT(SMapLS_IP_EBP_36) {x_SMapLS_IP_EBP_x(context,36);}
+REGS_ENTRYPOINT(SMapLS_IP_EBP_40) {x_SMapLS_IP_EBP_x(context,40);}
 
-void WINAPI SMapLS(CONTEXT *context)
+REGS_ENTRYPOINT(SMapLS)
 {
     if (EAX_reg(context)>=0x10000) {
 	EAX_reg(context) = MapLS((LPVOID)EAX_reg(context));
@@ -641,7 +641,7 @@
     }
 }
 
-void WINAPI SUnMapLS(CONTEXT *context)
+REGS_ENTRYPOINT(SUnMapLS)
 {
     if (EAX_reg(context)>=0x10000)
 	UnMapLS((SEGPTR)EAX_reg(context));
@@ -653,15 +653,15 @@
 		UnMapLS(*(DWORD*)(EBP_reg(context)+argoff));
 	*(DWORD*)(EBP_reg(context)+argoff)=0;
 }
-void WINAPI SUnMapLS_IP_EBP_8(CONTEXT *context) { x_SUnMapLS_IP_EBP_x(context,12); }
-void WINAPI SUnMapLS_IP_EBP_12(CONTEXT *context) { x_SUnMapLS_IP_EBP_x(context,12); }
-void WINAPI SUnMapLS_IP_EBP_16(CONTEXT *context) { x_SUnMapLS_IP_EBP_x(context,16); }
-void WINAPI SUnMapLS_IP_EBP_20(CONTEXT *context) { x_SUnMapLS_IP_EBP_x(context,20); }
-void WINAPI SUnMapLS_IP_EBP_24(CONTEXT *context) { x_SUnMapLS_IP_EBP_x(context,24); }
-void WINAPI SUnMapLS_IP_EBP_28(CONTEXT *context) { x_SUnMapLS_IP_EBP_x(context,28); }
-void WINAPI SUnMapLS_IP_EBP_32(CONTEXT *context) { x_SUnMapLS_IP_EBP_x(context,32); }
-void WINAPI SUnMapLS_IP_EBP_36(CONTEXT *context) { x_SUnMapLS_IP_EBP_x(context,36); }
-void WINAPI SUnMapLS_IP_EBP_40(CONTEXT *context) { x_SUnMapLS_IP_EBP_x(context,40); }
+REGS_ENTRYPOINT(SUnMapLS_IP_EBP_8)  { x_SUnMapLS_IP_EBP_x(context,12); }
+REGS_ENTRYPOINT(SUnMapLS_IP_EBP_12) { x_SUnMapLS_IP_EBP_x(context,12); }
+REGS_ENTRYPOINT(SUnMapLS_IP_EBP_16) { x_SUnMapLS_IP_EBP_x(context,16); }
+REGS_ENTRYPOINT(SUnMapLS_IP_EBP_20) { x_SUnMapLS_IP_EBP_x(context,20); }
+REGS_ENTRYPOINT(SUnMapLS_IP_EBP_24) { x_SUnMapLS_IP_EBP_x(context,24); }
+REGS_ENTRYPOINT(SUnMapLS_IP_EBP_28) { x_SUnMapLS_IP_EBP_x(context,28); }
+REGS_ENTRYPOINT(SUnMapLS_IP_EBP_32) { x_SUnMapLS_IP_EBP_x(context,32); }
+REGS_ENTRYPOINT(SUnMapLS_IP_EBP_36) { x_SUnMapLS_IP_EBP_x(context,36); }
+REGS_ENTRYPOINT(SUnMapLS_IP_EBP_40) { x_SUnMapLS_IP_EBP_x(context,40); }
 
 /**********************************************************************
  * 		AllocMappedBuffer	(KERNEL32.38)
@@ -682,7 +682,7 @@
  *       The SEGPTR is used by the caller!
  */
 
-void WINAPI AllocMappedBuffer(CONTEXT *context)
+REGS_ENTRYPOINT(AllocMappedBuffer)
 {
     HGLOBAL32 handle = GlobalAlloc32(0, EDI_reg(context) + 8);
     DWORD *buffer = (DWORD *)GlobalLock32(handle);
@@ -715,7 +715,7 @@
  * Input: EDI register: pointer to buffer
  */
 
-void WINAPI FreeMappedBuffer(CONTEXT *context)
+REGS_ENTRYPOINT(FreeMappedBuffer)
 {
     if (EDI_reg(context))
     {
diff --git a/memory/string.c b/memory/string.c
index ee0db67..92d1a88 100644
--- a/memory/string.c
+++ b/memory/string.c
@@ -230,12 +230,11 @@
     }
     while (*str1)
     {
-        /* FIXME: Unicode */
-        if ((res = toupper(*str1) - toupper(*str2)) != 0) return res;
+        if ((res = towupper(*str1) - towupper(*str2)) != 0) return res;
         str1++;
         str2++;
     }
-    return toupper(*str1) - toupper(*str2);
+    return towupper(*str1) - towupper(*str2);
 }
 
 
@@ -408,12 +407,11 @@
     if (!n) return 0;
     while ((--n > 0) && *str1)
     {
-        /* FIXME: Unicode */
-        if ((res = toupper(*str1) - toupper(*str2)) != 0) return res;
+        if ((res = towupper(*str1) - towupper(*str2)) != 0) return res;
         str1++;
         str2++;
     }
-    return toupper(*str1) - toupper(*str2);
+    return towupper(*str1) - towupper(*str2);
 }
 
 
diff --git a/memory/virtual.c b/memory/virtual.c
index d2759e6..c033543 100644
--- a/memory/virtual.c
+++ b/memory/virtual.c
@@ -6,7 +6,6 @@
 
 #include <assert.h>
 #include <fcntl.h>
-#include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
diff --git a/misc/aspi.c b/misc/aspi.c
index bf38b29..51e11b0 100644
--- a/misc/aspi.c
+++ b/misc/aspi.c
@@ -1,5 +1,4 @@
 #include <stdlib.h>
-#include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <errno.h>
@@ -310,7 +309,7 @@
     WARN(aspi, "Not enough bytes written to scsi device bytes=%d .. %d\n", in_len, status);
     if (status < 0) {
 	if (myerror == ENOMEM) {
-	    fprintf(stderr, "ASPI: Linux generic scsi driver\n  You probably need to re-compile your kernel with a larger SG_BIG_BUFF value (sg.h)\n  Suggest 130560\n");
+	    MSG("ASPI: Linux generic scsi driver\n  You probably need to re-compile your kernel with a larger SG_BIG_BUFF value (sg.h)\n  Suggest 130560\n");
 	}
 	WARN(aspi, "errno: = %d\n", myerror);
     }
diff --git a/misc/callback.c b/misc/callback.c
index 2dcf883..a39119a 100644
--- a/misc/callback.c
+++ b/misc/callback.c
@@ -5,7 +5,6 @@
  */
 
 #include <assert.h>
-#include <stdio.h>
 #include "debug.h"
 #include "windows.h"
 #include "callback.h"
diff --git a/misc/comm.c b/misc/comm.c
index 21ca5e8..fe67f6f 100644
--- a/misc/comm.c
+++ b/misc/comm.c
@@ -18,7 +18,6 @@
 
 #include "config.h"
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <termios.h>
 #include <fcntl.h>
diff --git a/misc/commdlg.c b/misc/commdlg.c
index ff5e275..1e3cfec 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -5,7 +5,6 @@
  * Copyright 1996 Albrecht Kleine
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "win.h"
diff --git a/misc/cpu.c b/misc/cpu.c
index 390c477..37c9f1b 100644
--- a/misc/cpu.c
+++ b/misc/cpu.c
@@ -2,10 +2,9 @@
  * What processor?
  *
  * Copyright 1995,1997 Morten Welinder
- * Copyright 1997 Marcus Meissner
+ * Copyright 1997-1998 Marcus Meissner
  */
 
-#include <stdio.h>
 #include <ctype.h>
 #include <string.h>
 #include "global.h"
@@ -15,19 +14,33 @@
 #include "winreg.h"
 #include "debug.h"
 
-/* Should this write to the registry? */
-#define DO_REG FALSE
-
 static BYTE PF[64] = {0,};
 
 /***********************************************************************
  * 			GetSystemInfo            	[KERNELL32.404]
+ *
+ * Gets the current system information.
+ *
+ * On the first call it reads cached values, so it doesn't have to determine
+ * them repeatedly. On Linux, the /proc/cpuinfo special file is used.
+ *
+ * It creates a registry subhierarchy, looking like:
+ * \HARDWARE\DESCRIPTION\System\CentralProcessor\<processornumber>\
+ *							Identifier (CPU x86)
+ * Note that there is a hierarchy for every processor installed, so this
+ * supports multiprocessor systems. This is done like Win95 does it, I think.
+ *							
+ * It also creates a cached flag array for IsProcessorFeaturePresent().
+ *
+ * RETURNS
+ *	nothing, really
  */
-VOID WINAPI GetSystemInfo(LPSYSTEM_INFO si)
-{
+VOID WINAPI GetSystemInfo(
+	LPSYSTEM_INFO si	/* [out] system information */
+) {
 	static int cache = 0;
 	static SYSTEM_INFO cachedsi;
-	HKEY	hkey;
+	HKEY	xhkey=0,hkey;
 	char	buf[20];
 
 	if (cache) {
@@ -55,17 +68,12 @@
 	cache = 1; /* even if there is no more info, we now have a cacheentry */
 	memcpy(si,&cachedsi,sizeof(*si));
 
-	/* hmm, reasonable processor feature defaults? */
+	/* Hmm, reasonable processor feature defaults? */
 
-        /* The registry calls were removed because they were being called 
-           before the registries were loaded, and they were giving errors */
         /* Create this registry key for all systems */
-
-#if DO_REG
 	if (RegCreateKey16(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System\\CentralProcessor",&hkey)!=ERROR_SUCCESS) {
             WARN(reg,"Unable to register CPU information\n");
         }
-#endif
 
 #ifdef linux
 	{
@@ -74,7 +82,7 @@
 
 	if (!f)
 		return;
-        /*xhkey = 0;*/
+        xhkey = 0;
 	while (fgets(line,200,f)!=NULL) {
 		char	*s,*value;
 
@@ -108,12 +116,10 @@
 					break;
 				}
 			}
-#if DO_REG
 			/* set the CPU type of the current processor */
 			sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
-			if (hkey)
-				RegSetValueEx32A(hkey,"Identifier",0,REG_SZ,buf,strlen(buf));
-#endif
+			if (xhkey)
+				RegSetValueEx32A(xhkey,"Identifier",0,REG_SZ,buf,strlen(buf));
 			continue;
 		}
 		/* old 2.0 method */
@@ -138,12 +144,10 @@
 					break;
 				}
 			}
-#if DO_REG
 			/* set the CPU type of the current processor */
 			sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
-			if (hkey)
-				RegSetValueEx32A(hkey,"Identifier",0,REG_SZ,buf,strlen(buf));
-#endif
+			if (xhkey)
+				RegSetValueEx32A(xhkey,"Identifier",0,REG_SZ,buf,strlen(buf));
 			continue;
 		}
 		if (!lstrncmpi32A(line,"fdiv_bug",strlen("fdiv_bug"))) {
@@ -166,14 +170,13 @@
 				if (x+1>cachedsi.dwNumberOfProcessors)
 					cachedsi.dwNumberOfProcessors=x+1;
 
-#if 0
-			/* create a new processor subkey */
-                        /* What exactly is trying to be done here? */
+			/* Create a new processor subkey on a multiprocessor
+			 * system
+			 */
 			sprintf(buf,"%d",x);
 			if (xhkey)
 				RegCloseKey(xhkey);
 			RegCreateKey16(hkey,buf,&xhkey);
-#endif
 		}
 		if (!lstrncmpi32A(line,"stepping",strlen("stepping"))) {
 			int	x;
@@ -195,31 +198,27 @@
 #else  /* linux */
 	/* FIXME: how do we do this on other systems? */
 
-#if 0
+	RegCreateKey16(hkey,"0",&xhkey);
 	RegSetValueEx32A(xhkey,"Identifier",0,REG_SZ,"CPU 386",strlen("CPU 386"));
-#endif
-
 #endif  /* !linux */
-
-#if 0
-	(xhkey)
+	if (xhkey)
 		RegCloseKey(xhkey);
-#endif
-#if DO_REG
-    if (hkey)
-        RegCloseKey(hkey);
-#endif
-
+	if (hkey)
+		RegCloseKey(hkey);
 }
 
 
 /***********************************************************************
  * 			IsProcessorFeaturePresent	[KERNELL32.880]
+ * RETURNS:
+ *	TRUE if processorfeature present
+ *	FALSE otherwise
  */
-BOOL32 WINAPI IsProcessorFeaturePresent (DWORD feature)
-{
+BOOL32 WINAPI IsProcessorFeaturePresent (
+	DWORD feature	/* [in] feature number, see PF_ defines */
+) {
   SYSTEM_INFO si;
-  GetSystemInfo (&si); /* to ensure the information is loaded and cached */
+  GetSystemInfo (&si); /* To ensure the information is loaded and cached */
 
   if (feature < 64)
     return PF[feature];
diff --git a/misc/crtdll.c b/misc/crtdll.c
index 0acad29..3d410ea 100644
--- a/misc/crtdll.c
+++ b/misc/crtdll.c
@@ -21,7 +21,6 @@
 /* FIXME: all the file handling is hopelessly broken -- AJ */
 
 #include <errno.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
@@ -44,13 +43,12 @@
 #include "file.h"
 #include "except.h"
 #include "options.h"
+#include "winnls.h"
 
 extern int FILE_GetUnixHandle( HFILE32  );
 
 static DOS_FULL_NAME CRTDLL_tmpname;
 
-extern INT32 WIN32_wsprintf32W( DWORD *args );
-
 UINT32 CRTDLL_argc_dll;         /* CRTDLL.23 */
 LPSTR *CRTDLL_argv_dll;         /* CRTDLL.24 */
 LPSTR  CRTDLL_acmdln_dll;       /* CRTDLL.38 */
@@ -199,23 +197,16 @@
 /*******************************************************************
  *         _global_unwind2  (CRTDLL.129)
  */
-void __cdecl CRTDLL__global_unwind2( CONTEXT *context )
+void __cdecl CRTDLL__global_unwind2( PEXCEPTION_FRAME frame )
 {
-    /* Retrieve the arguments (args[0] is return addr, args[1] is first arg) */
-    DWORD *args = (DWORD *)ESP_reg(context);
-    RtlUnwind( (PEXCEPTION_FRAME)args[1], (LPVOID)EIP_reg(context),
-               NULL, 0, context );
+    RtlUnwind( frame, 0, NULL, 0 );
 }
 
 /*******************************************************************
  *         _local_unwind2  (CRTDLL.173)
  */
-void __cdecl CRTDLL__local_unwind2( CONTEXT *context )
+void __cdecl CRTDLL__local_unwind2( PEXCEPTION_FRAME endframe, DWORD nr )
 {
-    /* Retrieve the arguments (args[0] is return addr, args[1] is first arg) */
-    DWORD *args = (DWORD *)ESP_reg(context);
-    PEXCEPTION_FRAME endframe = (PEXCEPTION_FRAME)args[1];
-    DWORD nr = args[2];
     TRACE(crtdll,"(%p,%ld)\n",endframe,nr);
 }
 
@@ -902,7 +893,7 @@
 	LPWSTR	y=x;
 
 	while (*y) {
-		*y=toupper(*y);
+		*y=towupper(*y);
 		y++;
 	}
 	return x;
@@ -916,7 +907,7 @@
 	LPWSTR	y=x;
 
 	while (*y) {
-		*y=tolower(*y);
+		*y=towlower(*y);
 		y++;
 	}
 	return x;
@@ -1294,14 +1285,6 @@
 }
 
 /*********************************************************************
- *                  towupper           (CRTDLL.494)
- */
-WCHAR __cdecl CRTDLL_towupper(WCHAR x)
-{
-    return (WCHAR)toupper((CHAR)x);
-}
-
-/*********************************************************************
  *                  _wcsicmp           (CRTDLL.321)
  */
 DWORD __cdecl CRTDLL__wcsicmp( LPCWSTR s1, LPCWSTR s2 )
@@ -1692,8 +1675,7 @@
 LPINT32 __cdecl CRTDLL__errno()
 {
 	static	int crtdllerrno;
-	extern int LastErrorToErrno(DWORD);
-
+	
 	/* FIXME: we should set the error at the failing function call time */
 	crtdllerrno = LastErrorToErrno(GetLastError());
 	return &crtdllerrno;
diff --git a/misc/ddeml.c b/misc/ddeml.c
index 4bbc1fe..9a54694 100644
--- a/misc/ddeml.c
+++ b/misc/ddeml.c
@@ -7,7 +7,6 @@
 
 /* Only empty stubs for now */
 
-#include <stdio.h>
 #include "ddeml.h"
 #include "debug.h"
 
@@ -283,7 +282,7 @@
  */
 BOOL32 WINAPI DdeFreeStringHandle32( DWORD idInst, HSZ hsz )
 {
-    FIXME( ddeml, "(%d,%d): stub\n",idInst, hsz );
+    FIXME( ddeml, "(%ld,%ld): stub\n",idInst, hsz );
     return TRUE;
 }
 
diff --git a/misc/error.c b/misc/error.c
index 4ae65a7..4f32d0b 100644
--- a/misc/error.c
+++ b/misc/error.c
@@ -4,7 +4,6 @@
  * Copyright 1997 Andrew Taylor
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
diff --git a/misc/imagelist.c b/misc/imagelist.c
index 95c27d9..ecd6d31 100644
--- a/misc/imagelist.c
+++ b/misc/imagelist.c
@@ -4,13 +4,12 @@
  *  Copyright 1998 Eric Kohl
  *
  *  TODO:
- *    - Improve error checking in some functions.
- *    - Fix ILD_TRANSPARENT error in ImageList_DrawIndirect.
  *    - Fix offsets in ImageList_DrawIndirect.
+ *    - Fix ILD_TRANSPARENT error in ImageList_DrawIndirect.
  *    - Fix ImageList_GetIcon (might be a result of the
  *      ILD_TRANSPARENT error in ImageList_DrawIndirect).
  *    - Fix drag functions.
- *    - Fix all other stubs.
+ *    - Fix ImageList_Read and ImageList_Write.
  *    - Add ImageList_SetFilter (undocumented).
  *      BTW does anybody know anything about this function???
  *        - It removes 12 Bytes from the stack (3 Parameters).
@@ -18,10 +17,6 @@
  *        - Second parameter COULD be an index?????
  *        - Third parameter.... ?????????????????????
  *
- *  Testing:
- *    - Test ImageList_GetImageRect (undocumented).
- *    - Test all the other functions.
- *
  *  Comments:
  *    - ImageList_Draw, ImageList_DrawEx and ImageList_GetIcon use
  *      ImageList_DrawIndirect. Since ImageList_DrawIndirect is still
@@ -43,6 +38,8 @@
 #define __GET_ICON_INFO_HACK__ 
  
 #include "windows.h"
+#include "compobj.h"
+#include "storage.h"
 #include "imagelist.h"
 #include "commctrl.h"
 #include "debug.h"
@@ -64,6 +61,13 @@
 static INT32      nInternalDragHotspotX = 0;
 static INT32      nInternalDragHotspotY = 0;
 
+static HWND32     hwndInternalDrag = 0;
+static INT32      xInternalPos = 0;
+static INT32      yInternalPos = 0;
+
+static HDC32      hdcBackBuffer = 0;
+static HBITMAP32  hbmBackBuffer = 0;
+
 
 /*************************************************************************
  * IMAGELIST_InternalExpandBitmaps [Internal] 
@@ -227,6 +231,27 @@
 
 
 /*************************************************************************
+ * ImageList_AddIcon [COMCTL32.40]
+ *
+ * Adds an icon to an image list.
+ *
+ * PARAMS
+ *     himl  [I] image list handle
+ *     hIcon [I] icon handle
+ *
+ * RETURNS
+ *     Success: index of the new image
+ *     Failure: -1
+ */
+
+INT32 WINAPI
+ImageList_AddIcon (HIMAGELIST himl, HICON32 hIcon)
+{
+    return (ImageList_ReplaceIcon (himl, -1, hIcon));
+}
+
+
+/*************************************************************************
  * ImageList_AddMasked [COMCTL32.41] 
  *
  * Adds an image or images to an image list and creates a mask from the
@@ -620,9 +645,6 @@
  *     Success: TRUE
  *     Failure: FALSE
  *
- * FIXME
- *     This is still an empty stub.
- *
  * NOTES
  *     The position of the drag image is relative to the window, not
  *     the client area.
@@ -631,7 +653,21 @@
 BOOL32 WINAPI
 ImageList_DragEnter (HWND32 hwndLock, INT32 x, INT32 y)
 {
-    FIXME (imagelist, "empty stub!\n");
+    if (himlInternalDrag == NULL) return (FALSE);
+
+    if (hwndLock)
+	hwndInternalDrag = hwndLock;
+    else
+	hwndInternalDrag = GetDesktopWindow32 ();
+
+    xInternalPos = x;
+    yInternalPos = y;
+
+    hdcBackBuffer = CreateCompatibleDC32 (0);
+    hbmBackBuffer = CreateCompatibleBitmap32 (hdcBackBuffer,
+		himlInternalDrag->cx, himlInternalDrag->cy);
+
+    ImageList_DragShowNolock (TRUE);
 
     return (FALSE);
 }
@@ -648,17 +684,22 @@
  * RETURNS
  *     Success: TRUE
  *     Failure: FALSE
- *
- * FIXME
- *     This is still an empty stub.
  */
 
 BOOL32 WINAPI
 ImageList_DragLeave (HWND32 hwndLock)
 {
-    FIXME (imagelist, "empty stub!\n");
+    if (hwndLock)
+	hwndInternalDrag = hwndLock;
+    else
+	hwndInternalDrag = GetDesktopWindow32 ();
 
-    return (FALSE);
+    ImageList_DragShowNolock (FALSE);
+
+    DeleteDC32 (hdcBackBuffer);
+    DeleteObject32 (hbmBackBuffer);
+
+    return (TRUE);
 }
 
 
@@ -678,15 +719,17 @@
  * NOTES
  *     The position of the drag image is relative to the window, not
  *     the client area.
- *
- * FIXME
- *     This is still an empty stub.
  */
 
 BOOL32 WINAPI
 ImageList_DragMove (INT32 x, INT32 y)
 {
-    FIXME (imagelist, "empty stub!\n");
+    ImageList_DragShowNolock (FALSE);
+
+    xInternalPos = x;
+    yInternalPos = y;
+
+    ImageList_DragShowNolock (TRUE);
 
     return (FALSE);
 }
@@ -705,13 +748,36 @@
  *     Failure: FALSE
  *
  * FIXME
- *     This is still an empty stub.
+ *     semi-stub.
  */
 
 BOOL32 WINAPI
 ImageList_DragShowNolock (BOOL32 bShow)
 {
-    FIXME (imagelist, "empty stub!\n");
+    HDC32 hdcDrag;
+
+    FIXME (imagelist, "semi-stub!\n");
+    TRACE (imagelist, "bShow=0x%X!\n", bShow);
+
+    hdcDrag = GetDCEx32 (hwndInternalDrag, 0,
+			 DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
+
+    if (bShow) {
+	/* show drag image */
+
+	/* save background */
+
+	/* draw drag image */
+
+    }
+    else {
+	/* hide drag image */
+
+	/* restore background */
+
+    }
+
+    ReleaseDC32 (hwndInternalDrag, hdcDrag);
 
     return (FALSE);
 }
@@ -775,8 +841,8 @@
  *     hdc    [I] device context handle
  *     x      [I] X position
  *     y      [I] Y position
- *     xOffs  [I] 
- *     yOffs  [I]
+ *     xOffs  [I] X offset
+ *     yOffs  [I] Y offset
  *     rgbBk  [I] background color
  *     rgbFg  [I] foreground color
  *     fStyle [I] drawing flags
@@ -824,11 +890,11 @@
  * Draws an image using ...
  *
  * PARAMS
- *     pimldp [I] pointer to ...
+ *     pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
  *
  * RETURNS
- *     Success:
- *     Failure:
+ *     Success: TRUE
+ *     Failure: FALSE
  */
 
 BOOL32 WINAPI
@@ -850,6 +916,8 @@
     if (pimldp == NULL) return (FALSE);
     if (pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS)) return (FALSE);
     if (pimldp->himl == NULL) return (FALSE);
+    if ((pimldp->i < 0) || (pimldp->i >= pimldp->himl->cCurImage))
+	return (FALSE);
 
     himlLocal = pimldp->himl;
     
@@ -1013,7 +1081,7 @@
  *
  * RETURNS
  *     Success: Handle of duplicated image list.
- *     Failure: 0
+ *     Failure: NULL
  */
 
 HIMAGELIST WINAPI
@@ -1061,7 +1129,7 @@
  * Finishes a drag operation.
  *
  * PARAMS
- *     no
+ *     no Parameters
  *
  * RETURNS
  *     Success: TRUE
@@ -1074,7 +1142,7 @@
 BOOL32 WINAPI
 ImageList_EndDrag (VOID)
 {
-    FIXME (imagelist, "partially implemented!\n");
+    FIXME (imagelist, "semi-stub!\n");
 
     if (himlInternalDrag)
     {
@@ -1100,14 +1168,15 @@
  *     himl [I] Image list handle.
  *
  * RETURNS
- *     Background color.
+ *     Success: background color
+ *     Failure: CLR_NONE
  */
 
 COLORREF WINAPI
 ImageList_GetBkColor (HIMAGELIST himl)
 {
-//    if (himl == NULL)
-//	return CLR_NONE;
+    if (himl == NULL)
+	return CLR_NONE;
 
     return (himl->clrBk);
 }
@@ -1133,7 +1202,7 @@
 HIMAGELIST WINAPI
 ImageList_GetDragImage (POINT32 *ppt, POINT32 *pptHotspot)
 {
-    FIXME (imagelist, "partially imlemented!\n");
+    FIXME (imagelist, "semi-stub!\n");
 
     if (himlInternalDrag)
         return (himlInternalDrag);
@@ -1165,6 +1234,9 @@
     HDC32    hdc;
     INT32    nWidth, nHeight;
 
+    if (himl == NULL) return 0;
+    if ((i < 0) || (i >= himl->cCurImage)) return 0;
+
     nWidth = GetSystemMetrics32 (SM_CXICON);
     nHeight = GetSystemMetrics32 (SM_CYICON);
 
@@ -1230,7 +1302,7 @@
 
 
 /*************************************************************************
- * ImageList_GetIconCount [COMCTL32.59]
+ * ImageList_GetImageCount [COMCTL32.59]
  *
  * Returns the number of images in an image list.
  *
@@ -1239,14 +1311,14 @@
  *
  * RETURNS
  *     Success: Number of images.
- *     Failure: ???? (Number of what...)
+ *     Failure: 0
  */
 
 INT32 WINAPI
 ImageList_GetImageCount (HIMAGELIST himl)
 {
-//    if (himl == NULL)
-//	return -1;
+    if (himl == NULL)
+	return 0;
 
     return (himl->cCurImage);
 }
@@ -1271,6 +1343,7 @@
 ImageList_GetImageInfo (HIMAGELIST himl, INT32 i, IMAGEINFO *pImageInfo)
 {
     if ((himl == NULL) || (pImageInfo == NULL)) return (FALSE);
+    if ((i < 0) || (i >= himl->cCurImage)) return (FALSE);
 
     pImageInfo->hbmImage = himl->hbmImage;
     pImageInfo->hbmMask  = himl->hbmMask;
@@ -1295,22 +1368,18 @@
  *     lpRect [O] pointer to the image rectangle
  *
  * RETURNS
- *    Success: TRUE ????
- *    Failure: FALSE ????
+ *    Success: TRUE
+ *    Failure: FALSE
  *
  * NOTES
  *    This is an UNDOCUMENTED function!!!
- *
- * BUGS
- *    I don't know if it really returns a BOOL32 or something else!!!??
  */
 
 BOOL32 WINAPI
 ImageList_GetImageRect (HIMAGELIST himl, INT32 i, LPRECT32 lpRect)
 {
-    if (himl == NULL) return (FALSE);
+    if ((himl == NULL) || (lpRect == NULL)) return (FALSE);
     if ((i < 0) || (i >= himl->cCurImage)) return (FALSE);
-    if (lpRect == NULL) return (FALSE);
 
     lpRect->left = i * himl->cx;
     lpRect->top = 0;
@@ -1322,23 +1391,25 @@
 
 
 /*************************************************************************
- * ImageList_LoadImage32A   [COMCTL32.63]
+ * ImageList_LoadImage32A [COMCTL32.62][COMCTL32.63]
  *
  * Creates an image list from a bitmap, icon or cursor.
  *
  * PARAMS
- *     hi      [I]
- *     lpbmp   [I]
- *     cx      [I]
- *     cy      [I]
- *     cGrow   [I]
- *     clrMask [I]
- *     uType   [I]
- *     uFlags  [I]
+ *     hi      [I] instance handle
+ *     lpbmp   [I] name or id of the image
+ *     cx      [I] width of each image
+ *     cGrow   [I] number of images to expand
+ *     clrMask [I] mask color
+ *     uType   [I] type of image to load
+ *     uFlags  [I] loading flags
  *
  * RETURNS
- *     Success:
- *     Failure:
+ *     Success: handle of the loaded image
+ *     Failure: NULL
+ *
+ * SEE
+ *     LoadImage ()
  */
 
 HIMAGELIST WINAPI
@@ -1404,18 +1475,20 @@
  * Creates an image list from a bitmap, icon or cursor.
  *
  * PARAMS
- *     hi      [I]
- *     lpbmp   [I]
- *     cx      [I]
- *     cy      [I]
- *     cGrow   [I]
- *     clrMask [I]
- *     uType   [I]
- *     uFlags  [I]
+ *     hi      [I] instance handle
+ *     lpbmp   [I] name or id of the image
+ *     cx      [I] width of each image
+ *     cGrow   [I] number of images to expand
+ *     clrMask [I] mask color
+ *     uType   [I] type of image to load
+ *     uFlags  [I] loading flags
  *
  * RETURNS
- *     Success:
- *     Failure:
+ *     Success: handle of the loaded image
+ *     Failure: NULL
+ *
+ * SEE
+ *     LoadImage ()
  */
 
 HIMAGELIST WINAPI
@@ -1493,8 +1566,8 @@
  *     dy    [I] Y offset of the second image relative to the first.
  *
  * RETURNS
- *     Success:
- *     Failure:
+ *     Success: handle of the merged image list.
+ *     Failure: NULL
  */
 
 HIMAGELIST WINAPI
@@ -1607,19 +1680,22 @@
  * RETURNS
  *     Success: image list handle
  *     Failure: NULL
+ *
+ * NOTES
+ *     This function can not be implemented yet, because
+ *     IStream32::Read is not implemented.
+ *
+ * BUGS
+ *     empty stub.
  */
 
-#if 0
-#if __IStream_INTERFACE_DEFINED__
-HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm)
+HIMAGELIST WINAPI ImageList_Read (LPSTREAM32 pstm)
 {
     FIXME (imagelist, "empty stub!\n");
 
 
     return (NULL);
 }
-#endif /* __IStream_INTERFACE_DEFINED__ */
-#endif /* 0 */
 
 
 /*************************************************************************
@@ -1642,18 +1718,18 @@
     INT32     cxNew, nCount;
 
     if ((i < -1) || (i >= himl->cCurImage)) {
-        ERR (imagelist, "Index out of range! %d\n", i);
+        ERR (imagelist, "index out of range! %d\n", i);
         return (FALSE);
     }
 
     if (himl->cCurImage == 0) {
-        ERR (imagelist, "List is already empty!\n");
+        ERR (imagelist, "image list is already empty!\n");
         return (FALSE);
     }
 
     if (i == -1) {
         /* remove all */
-        TRACE (imagelist, "Remove all!\n");
+        TRACE (imagelist, "remove all!\n");
 
         himl->cMaxImage = himl->cInitial + himl->cGrow;
         himl->cCurImage = 0;
@@ -1946,7 +2022,7 @@
  *     Failure: FALSE
  *
  * BUGS
- *     empty stub.
+ *     semi-stub.
  */
 
 BOOL32 WINAPI
@@ -1955,7 +2031,7 @@
 {
     HIMAGELIST himlTemp;
 
-    FIXME (imagelist, "empty stub!\n");
+    FIXME (imagelist, "semi-stub!\n");
 
     if (himlInternalDrag == NULL) return (FALSE);
 
@@ -1986,11 +2062,11 @@
  *     dwFilter [I] ???
  *
  * RETURNS
- *     Success: TRUE
- *     Failure: FALSE
+ *     Success: TRUE ???
+ *     Failure: FALSE ???
  *
  * BUGS
- *     undocumented!!!!
+ *     This is an UNDOCUMENTED function!!!!
  *     empty stub.
  */
 
@@ -2025,6 +2101,8 @@
 {
     INT32 nCount;
 
+    if (himl == NULL) return (FALSE);
+
     /* remove all images*/
     himl->cMaxImage  = himl->cInitial + himl->cGrow;
     himl->cCurImage  = 0;
@@ -2151,7 +2229,7 @@
     if ((iImage < 0) || (iImage > himl->cCurImage)) return (FALSE);
     
     himl->nOvlIdx[iOverlay - 1] = iImage;
-    return (TRUE);
+    return TRUE;
 }
 
 
@@ -2168,20 +2246,21 @@
  *     Success: TRUE
  *     Failure: FALSE
  *
+ * NOTES
+ *     This function can not be implemented yet, because
+ *     IStream32::Write is not implemented.
+ *
  * BUGS
  *     empty stub.
  */
 
-#if 0
-#if __IStream_INTERFACE_DEFINED__
 BOOL32 WINAPI
-ImageList_Write (HIMAGELIST himl, LPSTREAM pstm)
+ImageList_Write (HIMAGELIST himl, LPSTREAM32 pstm)
 {
     FIXME (imagelist, "empty stub!\n");
 
+    if (himl == NULL) return (FALSE);
 
-    return (FALSE);
+    return FALSE;
 }
-#endif  /* __IStream_INTERFACE_DEFINED__ */
-#endif  /* 0 */
 
diff --git a/misc/lstr.c b/misc/lstr.c
index 1491d4f..bffd1e7 100644
--- a/misc/lstr.c
+++ b/misc/lstr.c
@@ -7,7 +7,6 @@
 
 #include "config.h"
 
-#include <stdio.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
@@ -16,8 +15,6 @@
 #ifdef HAVE_WCTYPE_H
 # include <wctype.h>
 #else
-# define towlower(c) tolower(c)
-# define towupper(c) toupper(c)
 # define iswalnum(c) isalnum(c)
 # define iswalpha(c) isalpha(c)
 # define iswupper(c) isupper(c)
@@ -38,6 +35,27 @@
 
 /* be careful: always use functions from wctype.h if character > 255 */
 
+/*
+ * Unicode case conversion routines ... these should be used where
+ * toupper/tolower are used for ASCII.
+ */
+#ifndef HAVE_WCTYPE_H
+/* FIXME: should probably get rid of wctype.h altogether */
+#include "casemap.h"
+
+WCHAR _towupper(WCHAR code)
+{
+    const WCHAR * ptr = uprtable[HIBYTE(code)];
+    return ptr ? ptr[LOBYTE(code)] : code;
+}
+
+WCHAR _towlower(WCHAR code)
+{
+    const WCHAR * ptr = lwrtable[HIBYTE(code)];
+    return ptr ? ptr[LOBYTE(code)] : code;
+}
+#endif  /* HAVE_WCTYPE_H */
+
 /***********************************************************************
  *		IsCharAlpha (USER.433)
  */
@@ -350,7 +368,7 @@
         }
         return x;
     }
-    else return (LPWSTR)towlower(LOWORD(x));
+    else return (LPWSTR)((UINT32)towlower(LOWORD(x)));
 }
 
 /***********************************************************************
@@ -424,7 +442,7 @@
         }
         return x;
     }
-    else return (LPWSTR)towupper(LOWORD(x));
+    else return (LPWSTR)((UINT32)towupper(LOWORD(x)));
 }
 
 /***********************************************************************
diff --git a/misc/lzexpand.c b/misc/lzexpand.c
index 6bc9f44..792a7db 100644
--- a/misc/lzexpand.c
+++ b/misc/lzexpand.c
@@ -8,7 +8,6 @@
  */
 
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <ctype.h>
diff --git a/misc/main.c b/misc/main.c
index 6d7f47d..49ef6df 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -4,7 +4,6 @@
  * Copyright 1994 Alexandre Julliard
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -596,9 +595,13 @@
 
     if (Options.desktopGeometry && Options.managed)
     {
+#if 0
         MSG( "%s: -managed and -desktop options cannot be used together\n",
                  Options.programName );
         exit(1);
+#else
+        Options.managed = FALSE;
+#endif
     }
 
     screen       = DefaultScreenOfDisplay( display );
@@ -813,7 +816,27 @@
                 uParam = sizeof(ANIMATIONINFO);
                 break;
         }
- 
+
+        case SPI_GETHIGHCONTRAST:
+        {
+                LPHIGHCONTRASTA lpHighContrastA = (LPHIGHCONTRASTA)lpvParam;
+
+                FIXME(system,"SPI_GETHIGHCONTRAST not fully implemented\n");
+
+                if ( lpHighContrastA->cbSize == sizeof( HIGHCONTRASTA ) )
+                {
+                        /* Indicate that there is no high contrast available */
+                        lpHighContrastA->dwFlags = 0;
+                        lpHighContrastA->lpszDefaultScheme = NULL;
+                }
+                else
+                {
+                        return FALSE;
+                }
+
+                break;
+        }
+
 	default:
 		return SystemParametersInfo16(uAction,uParam,lpvParam,fuWinIni);
 	}
@@ -993,7 +1016,6 @@
 		case SPI_SETFASTTASKSWITCH:
 		case SPI_SETKEYBOARDDELAY:
 		case SPI_SETKEYBOARDSPEED:
-	        case SPI_GETHIGHCONTRAST:
 			WARN(system, "Option %d ignored.\n", uAction);
 			break;
 
@@ -1069,6 +1091,26 @@
 	break;
     }
 
+    case SPI_GETHIGHCONTRAST:
+    {
+       LPHIGHCONTRASTA lpHighContrastW = (LPHIGHCONTRASTW)lpvParam;
+
+       FIXME(system,"SPI_GETHIGHCONTRAST not fully implemented\n");
+
+       if ( lpHighContrastW->cbSize == sizeof( HIGHCONTRASTW ) )
+       {
+          /* Indicate that there is no high contrast available */
+          lpHighContrastW->dwFlags = 0;
+          lpHighContrastW->lpszDefaultScheme = NULL;
+       }
+       else
+       {
+          return FALSE;
+       }
+
+       break;
+    }
+
     default:
         return SystemParametersInfo32A(uAction,uParam,lpvParam,fuWinIni);
 	
diff --git a/misc/network.c b/misc/network.c
index 2c17dcb..7936383 100644
--- a/misc/network.c
+++ b/misc/network.c
@@ -7,7 +7,6 @@
  */
 
 #include <ctype.h>
-#include <stdio.h>
 
 #include "windows.h"
 #include "winerror.h"
@@ -22,16 +21,16 @@
  * Redirects a local device (either a disk drive or printer port)
  * to a shared device on a remote server.
  */
-UINT16 WINAPI WNetAddConnection16(LPSTR lpNetPath, LPSTR lpPassWord,
-                                LPSTR lpLocalName)
+UINT16 WINAPI WNetAddConnection16(LPCSTR lpNetPath, LPCSTR lpPassWord,
+                                LPCSTR lpLocalName)
 {	
    return WNetAddConnection32A(lpNetPath, lpPassWord, lpLocalName);
 }
 
 /* [MPR.50] */
 
-UINT32 WNetAddConnection32A(LPSTR NetPath, LPSTR PassWord,
-			    LPSTR LocalName)
+UINT32 WINAPI WNetAddConnection32A(LPCSTR NetPath, LPCSTR PassWord,
+			    LPCSTR LocalName)
 {
    FIXME(wnet, "('%s', %p, '%s'): stub\n",
 	 NetPath, PassWord, LocalName);
@@ -40,9 +39,9 @@
 
 /* [MPR.51] */
 
-UINT32 WNetAddConnection32W(LPWSTR NetPath, 
-			    LPWSTR PassWord,
-			    LPWSTR LocalName)
+UINT32 WINAPI WNetAddConnection32W(LPCWSTR NetPath, 
+			    LPCWSTR PassWord,
+			    LPCWSTR LocalName)
 {
    FIXME(wnet, " stub!\n");
    return WN_NO_NETWORK;
@@ -52,7 +51,7 @@
  * WNetAddConnection2_32A [MPR.46] 
  */
 
-UINT32
+UINT32 WINAPI
 WNetAddConnection2_32A(LPNETRESOURCE32A netresource, /* [in] */
 		       LPCSTR password,        /* [in] */     
 		       LPCSTR username,        /* [in] */
@@ -68,7 +67,7 @@
  * WNetAddConnection2W [MPR.47]
  */
 
-UINT32
+UINT32 WINAPI
 WNetAddConnection2_32W(LPNETRESOURCE32W netresource, /* [in] */
 		       LPCWSTR password,        /* [in] */     
 		       LPCWSTR username,        /* [in] */
@@ -83,7 +82,7 @@
  * WNetAddConnection3_32A [MPR.48]
  */
 
-UINT32 WNetAddConnection3_32A(HWND32 owner,
+UINT32 WINAPI WNetAddConnection3_32A(HWND32 owner,
 		      LPNETRESOURCE32A netresource,
 		      LPCSTR password,
 		      LPCSTR username,
@@ -98,7 +97,7 @@
  * WNetAddConnection3W [MPR.49]
  */
 
-UINT32 WNetAddConnection3_32W(HWND32 owner,
+UINT32 WINAPI WNetAddConnection3_32W(HWND32 owner,
 			      LPNETRESOURCE32W netresource,
 			      LPCWSTR username,
 			      LPCWSTR password,
@@ -113,7 +112,7 @@
 /********************************************************************
  *   WNetCancelConnection	[USER.518]  undirects a local device
  */
-UINT16 WINAPI WNetCancelConnection(LPSTR lpName, BOOL16 bForce)
+UINT16 WINAPI WNetCancelConnection(LPCSTR lpName, BOOL16 bForce)
 {
     FIXME(wnet, "('%s', %04X): stub\n", lpName, bForce);
     return WN_NO_NETWORK;
@@ -552,11 +551,11 @@
 /**************************************************************************
  *				WNetOpenEnumA		[MPR.92]
  */
-UINT32 WINAPI WNetOpenEnum32A(DWORD dwScope, DWORD dwType, 
+UINT32 WINAPI WNetOpenEnum32A(DWORD dwScope, DWORD dwType, DWORD dwUsage,
                               LPNETRESOURCE32A lpNet, HANDLE32 *lphEnum)
 {
-	FIXME(wnet, "(%08lX, %08lX, %p, %p): stub\n",
-	      dwScope, dwType, lpNet, lphEnum);
+	FIXME(wnet, "(%08lX, %08lX, %08lX, %p, %p): stub\n",
+	      dwScope, dwType, dwUsage, lpNet, lphEnum);
 	return WN_NO_NETWORK;
 }
 
@@ -614,7 +613,7 @@
     return WN_ACCESS_DENIED;
 }
 
-/* ****************************************************************
+/*****************************************************************
  *     MultinetGetConnectionPerformanceA [MPR.25]
  *
  * RETURNS
@@ -629,5 +628,27 @@
 	LPNETCONNECTINFOSTRUCT lpNetConnectInfoStruct
 ) {
 	FIXME(mpr,"(%p,%p): stub\n",lpNetResource,lpNetConnectInfoStruct);
+	return WN_NO_NETWORK;
+}
+
+
+/*****************************************************************
+ *  [MPR.22]
+ */
+
+DWORD WINAPI _MPR_22(DWORD x)
+{
+	FIXME(mpr,"(%lx): stub\n",x);
+	return 0;
+}
+
+/*****************************************************************
+ *  [MPR.25]
+ */
+
+DWORD WINAPI _MPR_25(DWORD x, DWORD y)
+{
+	FIXME(mpr,"(%lx,%lx): stub\n",x,y);
 	return 1;
 }
+
diff --git a/misc/ntdll.c b/misc/ntdll.c
index 7744f95..21efb50 100644
--- a/misc/ntdll.c
+++ b/misc/ntdll.c
@@ -4,7 +4,6 @@
  * Copyright 1996 Marcus Meissner
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
@@ -12,6 +11,7 @@
 #include <math.h>
 #include "win.h"
 #include "windows.h"
+#include "winnls.h"
 #include "ntdll.h"
 #include "heap.h"
 #include "debug.h"
@@ -204,7 +204,7 @@
  */
 LPVOID WINAPI RtlNormalizeProcessParams(LPVOID x)
 {
-    FIXME(ntdll,"(%p), stub.\n",x);
+    FIXME(ntdll,"(%p), stub\n",x);
     return x;
 }
 
@@ -429,8 +429,8 @@
  */
 DWORD WINAPI RtlNtStatusToDosError(DWORD error)
 {
-	/* FIXME: map STATUS_ to ERROR_ */
-	return error;
+    FIXME(ntdll, "(%x): map STATUS_ to ERROR_\n",error);
+    return error;
 }
 
 /**************************************************************************
@@ -438,8 +438,8 @@
  */
 DWORD WINAPI RtlGetNtProductType(LPVOID x)
 {
-	/* FIXME : find documentation for this one */
-	return 0;
+    FIXME(ntdll, "(%p): stub\n", x);
+    return 0;
 }
 
 /**************************************************************************
@@ -463,7 +463,7 @@
 	s=dest->Buffer;t=src->Buffer;
 	/* len is in bytes */
 	for (i=0;i<len/2;i++)
-		s[i]=toupper(t[i]);
+		s[i] = towupper(t[i]);
 	return STATUS_SUCCESS;
 }
 
@@ -484,6 +484,49 @@
 }
 
 /**************************************************************************
+ *                 RtlIsTextUnicode			[NTDLL]
+ *
+ *	Apply various feeble heuristics to guess whether
+ *	the text buffer contains Unicode.
+ *	FIXME: should implement more tests.
+ */
+DWORD WINAPI RtlIsTextUnicode(LPVOID buf, DWORD len, DWORD *pf)
+{
+	LPWSTR s = buf;
+	DWORD flags = -1, out_flags = 0;
+
+	if (!len)
+		goto out;
+	if (pf)
+		flags = *pf;
+	/*
+	 * Apply various tests to the text string. According to the
+	 * docs, each test "passed" sets the corresponding flag in
+	 * the output flags. But some of the tests are mutually
+	 * exclusive, so I don't see how you could pass all tests ...
+	 */
+
+	/* Check for an odd length ... pass if even. */
+	if (!(len & 1))
+		out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
+
+	/* Check for the special unicode marker byte. */
+	if (*s == 0xFEFF)
+		out_flags |= IS_TEXT_UNICODE_SIGNATURE;
+
+	/*
+	 * Check whether the string passed all of the tests.
+	 */
+	flags &= ITU_IMPLEMENTED_TESTS;
+	if ((out_flags & flags) != flags)
+		len = 0;
+out:
+	if (pf)
+		*pf = out_flags;
+	return len;
+}
+
+/**************************************************************************
  *                 RtlDosPathNameToNtPathName_U		[NTDLL]
  *
  * FIXME: convert to UNC or whatever is expected here
@@ -504,7 +547,7 @@
  */
 DWORD WINAPI NtOpenFile(DWORD x1,DWORD flags,DWORD x3,DWORD x4,DWORD alignment,DWORD x6)
 {
-	FIXME(ntdll,"(%08lx,%08lx,%08lx,%08lx,%08lx,%08lx)\n",
+	FIXME(ntdll,"(%08lx,%08lx,%08lx,%08lx,%08lx,%08lx): stub\n",
 	      x1,flags,x3,x4,alignment,x6);
 	/* returns file io completion status */
 	return 0;
@@ -517,4 +560,77 @@
 void NTDLL_chkstk(void)
 {
     /* FIXME: should subtract %eax bytes from stack pointer */
+    FIXME(ntdll, "(void): stub\n");
 }
+
+
+/**************************************************************************
+ * NtOpenDirectoryObject [NTDLL.124]
+ */
+DWORD WINAPI NtOpenDirectoryObject(DWORD x1,DWORD x2,DWORD x3)
+{
+    FIXME(ntdll,"(%lx,%lx,%lx): stub\n",x1,x2,x3);
+    return 0;
+}
+
+
+/**************************************************************************
+ * NtQueryDirectoryObject [NTDLL.149]
+ */
+DWORD WINAPI NtQueryDirectoryObject(DWORD x1, DWORD x2)
+{
+    FIXME(ntdll,"(%lx,%lx): stub\n",x1,x2);
+    return 0;
+}
+
+
+/**************************************************************************
+ * RtlFreeAnsiString [NTDLL.373]
+ */
+DWORD WINAPI RtlFreeAnsiString(DWORD x1)
+{
+    FIXME(ntdll,"(%lx): stub\n",x1);
+    return 0;
+}
+
+
+/**************************************************************************
+ * NtQuerySystemInformation [NTDLL.168]
+ */
+DWORD WINAPI NtQuerySystemInformation( DWORD x1 )
+{
+    FIXME(ntdll,"(%lx): stub\n",x1);
+    return 0;
+}
+
+
+/******************************************************************************
+ * NtQueryObject [NTDLL.161]
+ */
+DWORD WINAPI NtQueryObject( DWORD x1, DWORD x2 )
+{
+    FIXME(ntdll,"(%lx,%lx): stub\n",x1,x2);
+    return 0;
+}
+
+
+/******************************************************************************
+ * RtlTimeToElapsedTimeFields [NTDLL.502]
+ */
+DWORD WINAPI RtlTimeToElapsedTimeFields( DWORD x1 )
+{
+    FIXME(ntdll,"(%lx): stub\n",x1);
+    return 0;
+}
+
+
+/******************************************************************************
+ * NtSetInformationProcess [NTDLL.207]
+ */
+DWORD WINAPI NtSetInformationProcess( DWORD x1 )
+{
+    FIXME(ntdll,"(%lx): stub\n",x1);
+    return 0;
+}
+
+
diff --git a/misc/printdrv.c b/misc/printdrv.c
index 7389ed3..20c2207 100644
--- a/misc/printdrv.c
+++ b/misc/printdrv.c
@@ -5,7 +5,6 @@
  */
 
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include "windows.h"
@@ -106,3 +105,9 @@
     *lpdwReturned=0;
     return TRUE;
 }
+BOOL32 WINAPI AddMonitor32A(LPCSTR pName, DWORD Level, LPBYTE pMonitors)
+{
+    FIXME(print, "(%s,%lx,%p):stub!\n", pName, Level, pMonitors);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
diff --git a/misc/registry.c b/misc/registry.c
index d4569e6..55307e5 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -20,7 +20,6 @@
  */
 
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <ctype.h>
@@ -40,11 +39,7 @@
 #include "xmalloc.h"
 #include "winreg.h"
 
-void SHELL_StartupRegistry();
-
-/* This is not used anywhere */
-#define	DEBUG_W95_LOADREG	0
-
+static void REGISTRY_Init();
 /* FIXME: following defines should be configured global ... */
 
 /* NOTE: do not append a /. linux' mkdir() WILL FAIL if you do that */
@@ -102,6 +97,10 @@
  * FIXME
  *   Are these doing the same as HEAP_strdupAtoW and HEAP_strdupWtoA?
  *   If so, can we remove them?
+ * ANSWER
+ *   No, the memory handling functions are called very often in here, 
+ *   just replacing them by HeapAlloc(SystemHeap,...) makes registry
+ *   loading 100 times slower. -MM
  */
 static LPWSTR strdupA2W(LPCSTR src)
 {
@@ -214,59 +213,101 @@
 }
 
 
-/* debug function, converts a unicode into a static memory area 
- * (sub for using two static strings, in case we need them in a single call)
- *
- * FIXME
- *    This seems to be used the same as debugstr_w.
- *    If so, can this one go away?
- */
-LPSTR
-W2C(LPCWSTR x,int sub) {
-	static	LPSTR	unicodedebug[2]={NULL,NULL};
-	if (x==NULL)
-		return "<NULL>";
-	if (sub!=0 && sub!=1)
-		return "<W2C:bad sub>";
-	if (unicodedebug[sub]) HeapFree( SystemHeap, 0, unicodedebug[sub] );
-	unicodedebug[sub] = HEAP_strdupWtoA( SystemHeap, 0, x );
-	return unicodedebug[sub];
-}
-
-
 /******************************************************************************
  * lookup_hkey [Internal]
+ * 
+ * Just as the name says. Creates the root keys on demand, so we can call the
+ * Reg* functions at any time.
  *
  * RETURNS
  *    Success: Pointer to key structure
  *    Failure: NULL
  */
+#define ADD_ROOT_KEY(xx) \
+	xx = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));\
+	memset(xx,'\0',sizeof(KEYSTRUCT));\
+	xx->keyname= strdupA2W("<should_not_appear_anywhere>");
+
 static LPKEYSTRUCT lookup_hkey( HKEY hkey )
 {
 	switch (hkey) {
-    /* These seem erroneous */
-    /*	case 0x00000000: */
-    /*	case 0x00000001: */
-	case HKEY_CLASSES_ROOT:
+	/* 0 and 1 are valid rootkeys in win16 shell.dll and are used by
+	 * some programs. Do not remove those cases. -MM
+	 */
+    	case 0x00000000:
+	case 0x00000001:
+	case HKEY_CLASSES_ROOT: {
+		if (!key_classes_root) {
+			HKEY	cl_r_hkey;
+
+			/* calls lookup_hkey recursively, TWICE */
+			if (RegCreateKey16(HKEY_LOCAL_MACHINE,"SOFTWARE\\Classes",&cl_r_hkey)!=ERROR_SUCCESS) {
+				ERR(reg,"Could not create HKLM\\SOFTWARE\\Classes. This is impossible.\n");
+				exit(1);
+			}
+			key_classes_root = lookup_hkey(cl_r_hkey);
+		}
 		return key_classes_root;
+	}
 	case HKEY_CURRENT_USER:
+		if (!key_current_user) {
+			HKEY	c_u_hkey;
+			struct	passwd	*pwd;
+
+			pwd=getpwuid(getuid());
+			/* calls lookup_hkey recursively, TWICE */
+			if (pwd && pwd->pw_name) {
+				if (RegCreateKey16(HKEY_USERS,pwd->pw_name,&c_u_hkey)!=ERROR_SUCCESS) {
+					ERR(reg,"Could not create HU\\%s. This is impossible.\n",pwd->pw_name);
+					exit(1);
+				}
+				key_current_user = lookup_hkey(c_u_hkey);
+			} else {
+				/* nothing found, use standalone */
+				ADD_ROOT_KEY(key_current_user);
+			}
+		}
 		return key_current_user;
 	case HKEY_LOCAL_MACHINE:
+		if (!key_local_machine) {
+			ADD_ROOT_KEY(key_local_machine);
+			REGISTRY_Init();
+		}
 		return key_local_machine;
 	case HKEY_USERS:
+		if (!key_users) {
+			ADD_ROOT_KEY(key_users);
+		}
 		return key_users;
 	case HKEY_PERFORMANCE_DATA:
+		if (!key_performance_data) {
+			ADD_ROOT_KEY(key_performance_data);
+		}
 		return key_performance_data;
 	case HKEY_DYN_DATA:
+		if (!key_dyn_data) {
+			ADD_ROOT_KEY(key_dyn_data);
+		}
 		return key_dyn_data;
 	case HKEY_CURRENT_CONFIG:
+		if (!key_current_config) {
+			ADD_ROOT_KEY(key_current_config);
+		}
 		return key_current_config;
 	default:
 		return get_handle(hkey);
 	}
 	/*NOTREACHED*/
 }
-
+#undef ADD_ROOT_KEY
+/* so we don't accidently access them ... */
+#define key_current_config NULL NULL
+#define key_current_user NULL NULL
+#define key_users NULL NULL
+#define key_local_machine NULL NULL
+#define key_classes_root NULL NULL
+#define key_dyn_data NULL NULL
+#define key_performance_data NULL NULL
 
 /******************************************************************************
  * split_keypath [Internal]
@@ -322,62 +363,14 @@
 
 
 /******************************************************************************
- * SHELL_Init [Internal]
- * Shell initialisation, allocates keys. 
+ * REGISTRY_Init [Internal]
+ * Registry initialisation, allocates some default keys. 
  */
-void SHELL_Init() {
-	struct	passwd	*pwd;
-
-	HKEY	cl_r_hkey,c_u_hkey;
-#define ADD_ROOT_KEY(xx) \
-	xx = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));\
-	memset(xx,'\0',sizeof(KEYSTRUCT));\
-	xx->keyname= strdupA2W("<should_not_appear_anywhere>");
-
-	ADD_ROOT_KEY(key_local_machine);
-	if (RegCreateKey16(HKEY_LOCAL_MACHINE,"SOFTWARE\\Classes",&cl_r_hkey)!=ERROR_SUCCESS) {
-		ERR(reg,"Could not create HKLM\\SOFTWARE\\Classes. This is impossible.\n");
-		exit(1);
-	}
-	key_classes_root = lookup_hkey(cl_r_hkey);
-
-	ADD_ROOT_KEY(key_users);
-
-#if 0
-	/* FIXME: load all users and their resp. pwd->pw_dir/.wine/user.reg 
-	 *	  (later, when a win32 registry editing tool becomes avail.)
-	 */
-	while (pwd=getpwent()) {
-		if (pwd->pw_name == NULL)
-			continue;
-		RegCreateKey16(HKEY_USERS,pwd->pw_name,&c_u_hkey);
-		RegCloseKey(c_u_hkey);
-	}
-#endif
-	pwd=getpwuid(getuid());
-	if (pwd && pwd->pw_name) {
-		RegCreateKey16(HKEY_USERS,pwd->pw_name,&c_u_hkey);
-		key_current_user = lookup_hkey(c_u_hkey);
-	} else {
-		ADD_ROOT_KEY(key_current_user);
-	}
-	ADD_ROOT_KEY(key_performance_data);
-	ADD_ROOT_KEY(key_current_config);
-	ADD_ROOT_KEY(key_dyn_data);
-#undef ADD_ROOT_KEY
-	SHELL_StartupRegistry();
-}
-
-
-/******************************************************************************
- * SHELL_StartupRegistry [Internal]
- */
-void SHELL_StartupRegistry( void )
-{
+static void REGISTRY_Init() {
 	HKEY	hkey;
 	char	buf[200];
 
-    TRACE(reg,"(void)\n");
+	TRACE(reg,"(void)\n");
 
 	RegCreateKey16(HKEY_DYN_DATA,"PerfStats\\StatData",&hkey);
 	RegCloseKey(hkey);
@@ -599,7 +592,7 @@
 		strcat(fn,"/"SAVE_CURRENT_USER);
 		tmp = (char*)xmalloc(strlen(fn)+strlen(".tmp")+1);
 		strcpy(tmp,fn);strcat(tmp,".tmp");
-		if (_savereg(key_current_user,tmp,all)) {
+		if (_savereg(lookup_hkey(HKEY_CURRENT_USER),tmp,all)) {
 			if (-1==rename(tmp,fn)) {
 				perror("rename tmp registry");
 				unlink(tmp);
@@ -612,7 +605,7 @@
 		strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
 		tmp = (char*)xmalloc(strlen(fn)+strlen(".tmp")+1);
 		strcpy(tmp,fn);strcat(tmp,".tmp");
-		if (_savereg(key_local_machine,tmp,all)) {
+		if (_savereg(lookup_hkey(HKEY_LOCAL_MACHINE),tmp,all)) {
 			if (-1==rename(tmp,fn)) {
 				perror("rename tmp registry");
 				unlink(tmp);
@@ -1508,10 +1501,9 @@
 	OFSTRUCT		ofs;
 	BY_HANDLE_FILE_INFORMATION hfinfo;
 	time_t			lastmodified;
-	HKEY			hkey;
 	LPKEYSTRUCT		lpkey;
 
-    TRACE(reg,"(void)\n");
+	TRACE(reg,"(void)\n");
 
 	hf = OpenFile32("reg.dat",&ofs,OF_READ);
 	if (hf==HFILE_ERROR32)
@@ -1564,10 +1556,7 @@
 		return;
 	}
 	lastmodified = DOSFS_FileTimeToUnixTime(&hfinfo.ftLastWriteTime,NULL);
-
-	if (RegCreateKey16(HKEY_LOCAL_MACHINE,"SOFTWARE\\Classes",&hkey)!=ERROR_SUCCESS)
-		return;
-	lpkey = lookup_hkey(hkey);
+	lpkey = lookup_hkey(HKEY_CLASSES_ROOT);
 	__w31_dumptree(tab[0].w1,txt,tab,&head,lpkey,lastmodified,0);
 	free(tab);
 	free(txt);
@@ -1586,17 +1575,14 @@
 	LPKEYSTRUCT	lpkey;
 	HKEY		hkey;
 
-    TRACE(reg,"(void)\n");
-
-	if (key_classes_root==NULL)
-		SHELL_Init();
+	TRACE(reg,"(void)\n");
 
 	/* Load windows 3.1 entries */
 	_w31_loadreg();
 	/* Load windows 95 entries */
-	_w95_loadreg("C:\\system.1st",	key_local_machine);
-	_w95_loadreg("system.dat",	key_local_machine);
-	_w95_loadreg("user.dat",	key_users);
+	_w95_loadreg("C:\\system.1st",	lookup_hkey(HKEY_LOCAL_MACHINE));
+	_w95_loadreg("system.dat",	lookup_hkey(HKEY_LOCAL_MACHINE));
+	_w95_loadreg("user.dat",	lookup_hkey(HKEY_USERS));
 
 	/* the global user default is loaded under HKEY_USERS\\.Default */
 	RegCreateKey16(HKEY_USERS,".Default",&hkey);
@@ -1606,11 +1592,11 @@
 	_wine_loadreg(lpkey,SAVE_USERS_DEFAULT,0);
 
 	/* HKEY_USERS\\.Default is copied to HKEY_CURRENT_USER */
-	_copy_registry(lpkey,key_current_user);
+	_copy_registry(lpkey,lookup_hkey(HKEY_CURRENT_USER));
 	RegCloseKey(hkey);
 
 	/* the global machine defaults */
-	_wine_loadreg(key_local_machine,SAVE_LOCAL_MACHINE_DEFAULT,0);
+	_wine_loadreg(lookup_hkey(HKEY_LOCAL_MACHINE),SAVE_LOCAL_MACHINE_DEFAULT,0);
 
 	/* load the user saved registries */
 
@@ -1621,12 +1607,12 @@
 		fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_CURRENT_USER)+2);
 		strcpy(fn,pwd->pw_dir);
 		strcat(fn,WINE_PREFIX"/"SAVE_CURRENT_USER);
-		_wine_loadreg(key_current_user,fn,REG_OPTION_TAINTED);
+		_wine_loadreg(lookup_hkey(HKEY_CURRENT_USER),fn,REG_OPTION_TAINTED);
 		free(fn);
 		fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+2);
 		strcpy(fn,pwd->pw_dir);
 		strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
-		_wine_loadreg(key_local_machine,fn,REG_OPTION_TAINTED);
+		_wine_loadreg(lookup_hkey(HKEY_LOCAL_MACHINE),fn,REG_OPTION_TAINTED);
 		free(fn);
 	} else
 		WARN(reg,"Failed to get homedirectory of UID %d.\n",getuid());
@@ -1828,11 +1814,6 @@
     if (!lpNextKey)
         return ERROR_BADKEY;
 
-    if (lpszSubKey[0] == '\\') {
-        WARN(reg,"Subkey %s must not begin with backslash.\n",debugstr_w(lpszSubKey));
-        return ERROR_BAD_PATHNAME;
-    }
-
 	if (!lpszSubKey || !*lpszSubKey) {
 		add_handle(++currenthandle,lpNextKey,samDesired);
 		*retkey=currenthandle;
@@ -1841,6 +1822,11 @@
 		return ERROR_SUCCESS;
 	}
 
+    if (lpszSubKey[0] == '\\') {
+        WARN(reg,"Subkey %s must not begin with backslash.\n",debugstr_w(lpszSubKey));
+        return ERROR_BAD_PATHNAME;
+    }
+
 	split_keypath(lpszSubKey,&wps,&wpc);
 	i 	= 0;
 	while ((i<wpc) && (wps[i][0]=='\0')) i++;
@@ -2388,7 +2374,7 @@
             TRACE(reg," Data(binary)\n");
             break;
         case REG_DWORD:
-            TRACE(reg," Data(dword)=%lx\n", (DWORD)*lpbData);
+            TRACE(reg," Data(dword)=%lx\n", (DWORD)lpbData);
             break;
         default:
             TRACE(reg,"Unknown type: %ld\n", dwType);
@@ -2500,7 +2486,7 @@
 	DWORD	ret;
 
 	TRACE(reg,"(%x,%s,%ld,%s,%ld)\n",
-		hkey,W2C(lpszSubKey,0),dwType,W2C(lpszData,0),cbData
+		hkey,debugstr_w(lpszSubKey),dwType,debugstr_w(lpszData),cbData
 	);
 	if (lpszSubKey && *lpszSubKey) {
 		ret=RegCreateKey32W(hkey,lpszSubKey,&xhkey);
@@ -2514,7 +2500,7 @@
 	}
 	if (cbData!=2*lstrlen32W(lpszData)+2) {
 		TRACE(reg,"RegSetValueX called with len=%ld != strlen(%s)+1=%d!\n",
-			cbData,W2C(lpszData,0),2*lstrlen32W(lpszData)+2
+			cbData,debugstr_w(lpszData),2*lstrlen32W(lpszData)+2
 		);
 		cbData=2*lstrlen32W(lpszData)+2;
 	}
@@ -2913,7 +2899,7 @@
 		lpxkey=lpNextKey->nextsub;
 		while (lpxkey) {
 			TRACE(reg, "  Scanning [%s]\n",
-				     W2C (lpxkey->keyname, 0));
+				     debugstr_w(lpxkey->keyname));
 			if (!lstrcmpi32W(wps[i],lpxkey->keyname))
 				break;
 			lpxkey=lpxkey->next;
@@ -2931,7 +2917,7 @@
 	lplpPrevKey = &(lpNextKey->nextsub);
 	while (lpxkey) {
 		TRACE(reg, "  Scanning [%s]\n",
-			     W2C (lpxkey->keyname, 0));
+			     debugstr_w(lpxkey->keyname));
 		if (!lstrcmpi32W(wps[i],lpxkey->keyname))
 			break;
 		lplpPrevKey	= &(lpxkey->next);
@@ -3312,3 +3298,115 @@
     return ERROR_SUCCESS;
 }
 
+
+/******************************************************************************
+ * RegUnLoadKey32W [ADVAPI32.173]
+ */
+LONG WINAPI RegUnLoadKey32W( HKEY hkey, LPCWSTR lpSubKey )
+{
+    FIXME(reg,"(%x,%s): stub\n",hkey, debugstr_w(lpSubKey));
+    return ERROR_SUCCESS;
+}
+
+
+/******************************************************************************
+ * RegUnLoadKey32A [ADVAPI32.172]
+ */
+LONG WINAPI RegUnLoadKey32A( HKEY hkey, LPCSTR lpSubKey )
+{
+    LONG ret;
+    LPWSTR lpSubKeyW = HEAP_strdupAtoW( GetProcessHeap(), 0, lpSubKey );
+    ret = RegUnLoadKey32W( hkey, lpSubKeyW );
+    HeapFree( GetProcessHeap(), 0, lpSubKeyW );
+    return ret;
+}
+
+
+/******************************************************************************
+ * RegSetKeySecurity [ADVAPI32.167]
+ */
+LONG WINAPI RegSetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInfo,
+                               LPSECURITY_DESCRIPTOR pSecurityDesc )
+{
+    FIXME(reg, "%x,%ld,%p): stub\n", hkey, SecurityInfo, pSecurityDesc);
+    return ERROR_SUCCESS;
+}
+
+
+/******************************************************************************
+ * RegSaveKey32W [ADVAPI32.166]
+ */
+LONG WINAPI RegSaveKey32W( HKEY hkey, LPCWSTR lpFile, 
+                           LPSECURITY_ATTRIBUTES sa )
+{
+    FIXME(reg, "%x,%s,%p): stub\n", hkey, debugstr_w(lpFile), sa);
+    return ERROR_SUCCESS;
+}
+
+
+/******************************************************************************
+ * RegSaveKey32A [ADVAPI32.165]
+ */
+LONG WINAPI RegSaveKey32A( HKEY hkey, LPCSTR lpFile, 
+                           LPSECURITY_ATTRIBUTES sa )
+{
+    LONG ret;
+    LPWSTR lpFileW = HEAP_strdupAtoW(GetProcessHeap(), 0, lpFile);
+    ret = RegSaveKey32W( hkey, lpFileW, sa );
+    HeapFree( GetProcessHeap(), 0, lpFileW );
+    return ret;
+}
+
+
+/******************************************************************************
+ * RegRestoreKey32W [ADVAPI32.164]
+ */
+LONG WINAPI RegRestoreKey32W( HKEY hkey, LPCWSTR lpFile, DWORD dwFlags )
+{
+    FIXME(reg, "%x,%s,%ld): stub\n", hkey, debugstr_w(lpFile), dwFlags);
+    return ERROR_SUCCESS;
+}
+
+
+/******************************************************************************
+ * RegRestoreKey32A [ADVAPI32.163]
+ */
+LONG WINAPI RegRestoreKey32A( HKEY hkey, LPCSTR lpFile, DWORD dwFlags )
+{
+    LONG ret;
+    LPWSTR lpFileW = HEAP_strdupAtoW(GetProcessHeap(), 0, lpFile);
+    ret = RegRestoreKey32W( hkey, lpFileW, dwFlags );
+    HeapFree( GetProcessHeap(), 0, lpFileW );
+    return ret;
+}
+
+
+/******************************************************************************
+ * RegReplaceKey32W [ADVAPI32.162]
+ */
+LONG WINAPI RegReplaceKey32W( HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpNewFile,
+                              LPCWSTR lpOldFile )
+{
+    FIXME(reg, "%x,%s,%s,%s): stub\n", hkey, debugstr_w(lpSubKey), 
+          debugstr_w(lpNewFile),debugstr_w(lpOldFile));
+    return ERROR_SUCCESS;
+}
+
+
+/******************************************************************************
+ * RegReplaceKey32A [ADVAPI32.161]
+ */
+LONG WINAPI RegReplaceKey32A( HKEY hkey, LPCSTR lpSubKey, LPCSTR lpNewFile,
+                              LPCSTR lpOldFile )
+{
+    LONG ret;
+    LPWSTR lpSubKeyW = HEAP_strdupAtoW(GetProcessHeap(), 0, lpSubKey);
+    LPWSTR lpNewFileW = HEAP_strdupAtoW(GetProcessHeap(), 0, lpNewFile);
+    LPWSTR lpOldFileW = HEAP_strdupAtoW(GetProcessHeap(), 0, lpOldFile);
+    ret = RegReplaceKey32W( hkey, lpSubKeyW, lpNewFileW, lpOldFileW );
+    HeapFree( GetProcessHeap(), 0, lpOldFileW );
+    HeapFree( GetProcessHeap(), 0, lpNewFileW );
+    HeapFree( GetProcessHeap(), 0, lpSubKeyW );
+    return ret;
+}
+
diff --git a/misc/shell.c b/misc/shell.c
index 0520d69..4ac0d7c 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -3,7 +3,6 @@
  */
 #include <assert.h>
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <ctype.h>
@@ -45,6 +44,7 @@
     "Niels de Carpentier",
     "Gordon Chaffee",
     "Jimen Ching",
+    "Pascal Cuoq",
     "David A. Cuthbert",
     "Huw D. M. Davies",
     "Roman Dolejsi",
@@ -56,6 +56,7 @@
     "Claus Fischer",
     "Olaf Flebbe",
     "Chad Fraleigh",
+    "Matthew Francis",
     "Peter Galbavy",
     "Ramon Garcia",
     "Matthew Ghio",
@@ -64,6 +65,7 @@
     "Charles M. Hannum",
     "Adrian Harvey",
     "John Harvey",
+    "Bill Hawes",
     "Cameron Heide",
     "Jochen Hoenicke",
     "Onno Hovers",
@@ -145,6 +147,7 @@
     "Ronan Waide",
     "Eric Warnke",
     "Manfred Weichel",
+    "Ulrich Weigand",
     "Morten Welinder",
     "Len White",
     "Lawson Whitney",
@@ -279,7 +282,8 @@
 }
 
 /*************************************************************************
- *				SHELL_FindExecutable
+ *	SHELL_FindExecutable [Internal]
+ *
  * Utility for code sharing between FindExecutable and ShellExecute
  */
 static HINSTANCE32 SHELL_FindExecutable( LPCSTR lpFile, 
@@ -298,27 +302,34 @@
     int i;                  /* random counter */
     char xlpFile[256];      /* result of SearchPath */
 
-    TRACE(exec, "%s\n",
-                 (lpFile != NULL?lpFile:"-") );
+    TRACE(exec, "%s\n", (lpFile != NULL?lpFile:"-") );
+
     lpResult[0]='\0'; /* Start off with an empty return string */
 
     /* trap NULL parameters on entry */
     if (( lpFile == NULL ) || ( lpResult == NULL ) || ( lpOperation == NULL ))
     {
-	/* FIXME - should throw a warning, perhaps! */
-	return 2; /* File not found. Close enough, I guess. */
+	WARN(exec, "(lpFile=%s,lpResult=%s,lpOperation=%s): NULL parameter\n",
+           lpFile, lpOperation, lpResult);
+        return 2; /* File not found. Close enough, I guess. */
     }
 
     if (SearchPath32A( NULL, lpFile,".exe",sizeof(xlpFile),xlpFile,NULL))
+    {
+	TRACE(exec, "SearchPath32A returned non-zero\n");
         lpFile = xlpFile;
+    }
 
     /* First thing we need is the file's extension */
     extension = strrchr( xlpFile, '.' ); /* Assume last "." is the one; */
 					/* File->Run in progman uses */
 					/* .\FILE.EXE :( */
+    TRACE(exec, "xlpFile=%s,extension=%s\n", xlpFile, extension);
+
     if ((extension == NULL) || (extension == &xlpFile[strlen(xlpFile)]))
     {
-	return 31; /* no association */
+        WARN(exec, "Returning 31 - No association\n");
+        return 31; /* no association */
     }
 
     /* Make local copy & lowercase it for reg & 'programs=' lookup */
@@ -1658,8 +1669,3 @@
 	lstrcpy32A(pszPath,"E:\\"); /* FIXME */
 	return NOERROR;
 }
-
-
-
-
-
diff --git a/misc/shellord.c b/misc/shellord.c
index 344ea11..41f0538 100644
--- a/misc/shellord.c
+++ b/misc/shellord.c
@@ -10,11 +10,11 @@
  * Copyright 1997 Marcus Meissner
  */
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <ctype.h>
 #include "windows.h"
+#include "winerror.h"
 #include "file.h"
 #include "shell.h"
 #include "heap.h"
@@ -251,6 +251,14 @@
 }
 
 /*************************************************************************
+ *				SHELL32_51	[SHELL32.51]
+ */
+DWORD WINAPI SHELL32_51(LPCSTR s,DWORD x2,DWORD x3) {
+	FIXME(shell,"(%s,0x%08lx,0x%08lx),stub!\n",s,x2,x3);
+	return 0;
+}
+
+/*************************************************************************
  *				SHELL32_52	[SHELL32.52]
  * look for next arg in string. handle "quoted" strings
  * returns pointer to argument *AFTER* the space. Or to the \0.
@@ -453,8 +461,12 @@
 
  */
 	hres = (*dllgetclassob)(clsid,(REFIID)&IID_IClassFactory,&classfac);
-	if (hres<0)
+	if (hres<0 || (hres>=0x80000000))
 		return hres;
+	if (!classfac) {
+		FIXME(shell,"no classfactory, but hres is 0x%ld!\n",hres);
+		return E_FAIL;
+	}
 	classfac->lpvtbl->fnCreateInstance(classfac,unknownouter,refiid,inst);
 	classfac->lpvtbl->fnRelease(classfac);
 	return 0;
@@ -671,3 +683,21 @@
     return 0;
 }
 
+/*************************************************************************
+ * SHELL32_86 [SHELL32.86]
+ * unknown
+ */
+DWORD WINAPI SHELL32_86(HWND32 hwnd,DWORD x2) {
+    FIXME(shell,"(0x%08lx,0x%08lx):stub.\n",hwnd,x2);
+    return 0;
+}
+
+/*************************************************************************
+ * SHELL32_87 [SHELL32.87]
+ * unknown
+ */
+DWORD WINAPI SHELL32_87(DWORD x) {
+    FIXME(shell,"(0x%08lx):stub.\n",x);
+    return 0;
+}
+
diff --git a/misc/sound.c b/misc/sound.c
index 9de81f0..337bc48 100644
--- a/misc/sound.c
+++ b/misc/sound.c
@@ -1,10 +1,8 @@
 /*
-static char RCSId[] = "$Id: heap.c,v 1.3 1993/07/04 04:04:21 root Exp root $";
-static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
-*/
+ *  Copyright  Robert J. Amstadt, 1993
+ */
 
 #include <stdlib.h>
-#include <stdio.h>
 #include "windows.h"
 #include "debug.h"
 
diff --git a/misc/spy.c b/misc/spy.c
index 979ad23..0419c05 100644
--- a/misc/spy.c
+++ b/misc/spy.c
@@ -6,7 +6,6 @@
  */
 
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include "windows.h"
 #include "win.h"
diff --git a/misc/stress.c b/misc/stress.c
index 6320dfa..7a7f9f4 100644
--- a/misc/stress.c
+++ b/misc/stress.c
@@ -1,4 +1,3 @@
-#include <stdio.h>
 #include <limits.h>
 #include "windows.h"
 #include "stress.h"
diff --git a/misc/system.c b/misc/system.c
index 99fbcfb..77e4940 100644
--- a/misc/system.c
+++ b/misc/system.c
@@ -4,7 +4,6 @@
  * Copyright 1996 Alexandre Julliard
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <signal.h>
 #include <time.h>
diff --git a/misc/toolhelp.c b/misc/toolhelp.c
index a6520d8..606416b 100644
--- a/misc/toolhelp.c
+++ b/misc/toolhelp.c
@@ -5,7 +5,6 @@
  */
 
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <ctype.h>
diff --git a/misc/tweak.c b/misc/tweak.c
index 603f9df..5e7e6af 100644
--- a/misc/tweak.c
+++ b/misc/tweak.c
@@ -24,7 +24,6 @@
  *
  *****************************************************************************/
 
-#include <stdio.h>
 #include <malloc.h>
 #include "ts_xlib.h"
 #include <string.h>
diff --git a/misc/ver.c b/misc/ver.c
index 851b37b..0c8149b 100644
--- a/misc/ver.c
+++ b/misc/ver.c
@@ -5,7 +5,6 @@
  * Copyright 1997 David Cuthbert
  */
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include <unistd.h>
diff --git a/misc/version.c b/misc/version.c
index 2b125e2..89cb8cd 100644
--- a/misc/version.c
+++ b/misc/version.c
@@ -5,7 +5,6 @@
  * Copyright 1997 Marcus Meissner
  */
 
-#include <stdio.h>
 #include <string.h>
 #include "windows.h"
 #include "winbase.h"
diff --git a/misc/win32s16.c b/misc/win32s16.c
index fde1b28..5fc0484 100644
--- a/misc/win32s16.c
+++ b/misc/win32s16.c
@@ -9,7 +9,6 @@
 #include "debug.h"
 #include <string.h>
 #include <stdlib.h>
-#include <stdio.h>
 
 void BootTask()
 {
diff --git a/misc/windebug.c b/misc/windebug.c
index 5e74cf4..c22c712 100644
--- a/misc/windebug.c
+++ b/misc/windebug.c
@@ -4,7 +4,6 @@
  * Copyright (c) 1997 Andreas Mohr
  */
 
-#include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include "windows.h"
diff --git a/misc/winsock.c b/misc/winsock.c
index 24d5242..4dae6c4 100644
--- a/misc/winsock.c
+++ b/misc/winsock.c
@@ -12,7 +12,6 @@
  
 #include "config.h"
 
-#include <stdio.h>
 #include <string.h>
 #include <signal.h>
 #include <sys/types.h>
@@ -98,9 +97,6 @@
 static int   _check_ws(LPWSINFO pwsi, ws_socket* pws);
 static char* _check_buffer(LPWSINFO pwsi, int size);
 
-extern void EVENT_AddIO( int fd, unsigned flag );
-extern void EVENT_DeleteIO( int fd, unsigned flag );
-
 /***********************************************************************
  *          convert_sockopt()
  *
@@ -1676,14 +1672,6 @@
 
 
 /***********************************************************************
- *          Asynchronous DNS services
- */
-
-/* winsock_dns.c */
-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 WSAAsyncGetHostByAddr16(HWND16 hWnd, UINT16 uMsg, LPCSTR addr,
diff --git a/misc/winsock_dns.c b/misc/winsock_dns.c
index dc9b298..3cb1fe0 100644
--- a/misc/winsock_dns.c
+++ b/misc/winsock_dns.c
@@ -77,9 +77,6 @@
 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 );
-
 /* ----------------------------------- async/non-blocking I/O */
 
 int WINSOCK_async_io(int fd, int async)
@@ -321,8 +318,8 @@
 }
 
 
-HANDLE16 __WSAsyncDBQuery(LPWSINFO pwsi, HWND32 hWnd, UINT32 uMsg, INT32 type, LPSTR init,
-		  	  INT32 len, LPSTR proto, void* sbuf, INT32 buflen, UINT32 flag)
+HANDLE16 __WSAsyncDBQuery(LPWSINFO pwsi, HWND32 hWnd, UINT32 uMsg, INT32 type, 
+    LPCSTR init, INT32 len, LPCSTR proto, void* sbuf, INT32 buflen, UINT32 flag)
 {
     /* queue 'flag' request and fork off its handler */
 
@@ -336,7 +333,7 @@
 	{
 	    async_ctl.rq.init = (char*)init;
 	    async_ctl.ilength = len;
-	    async_ctl.buffer = proto;
+	    async_ctl.buffer = (char*)proto;
 	    async_ctl.type = type;
 
 	    async_ctl.ws_aop->hWnd = hWnd;
diff --git a/misc/wsprintf.c b/misc/wsprintf.c
index fcfd589..96b23b4 100644
--- a/misc/wsprintf.c
+++ b/misc/wsprintf.c
@@ -5,7 +5,6 @@
  */
 
 #include <stdarg.h>
-#include <stdio.h>
 #include <string.h>
 #include "windows.h"
 #include "ldt.h"
diff --git a/misc/xmalloc.c b/misc/xmalloc.c
index 8ff7b38..3faa6a8 100644
--- a/misc/xmalloc.c
+++ b/misc/xmalloc.c
@@ -13,7 +13,6 @@
 
 */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "xmalloc.h"
diff --git a/miscemu/emulate.c b/miscemu/emulate.c
index f141a44..0d95dad 100644
--- a/miscemu/emulate.c
+++ b/miscemu/emulate.c
@@ -1,5 +1,4 @@
 #include <stdlib.h>
-#include <stdio.h>
 #include "miscemu.h"
 #include "debug.h"
 
diff --git a/miscemu/instr.c b/miscemu/instr.c
index 1b6570d..465f16c 100644
--- a/miscemu/instr.c
+++ b/miscemu/instr.c
@@ -4,7 +4,6 @@
  * Copyright 1995 Alexandre Julliard
  */
 
-#include <stdio.h>
 #include "windows.h"
 #include "ldt.h"
 #include "miscemu.h"
@@ -299,6 +298,7 @@
 
     long_op = long_addr = IS_SELECTOR_32BIT(CS_sig(context));
     instr = (BYTE *)MAKE_PTR(CS_sig(context),EIP_sig(context));
+    if (!instr) return FALSE;
 
     /* First handle any possible prefix */
 
diff --git a/miscemu/main.c b/miscemu/main.c
index 1f53c89..4174b0e 100644
--- a/miscemu/main.c
+++ b/miscemu/main.c
@@ -3,14 +3,16 @@
  *
  */
 
-#include "windows.h"
 #include "callback.h"
+#include "debug.h"
 #include "debugger.h"
 #include "main.h"
 #include "miscemu.h"
 #include "module.h"
 #include "options.h"
-#include "debug.h"
+#include "process.h"
+#include "win16drv.h"
+#include "windows.h"
 
 
 /***********************************************************************
@@ -18,9 +20,6 @@
  */
 BOOL32 MAIN_EmulatorInit(void)
 {
-    extern BOOL32 WIN16DRV_Init(void);
-    extern BOOL32 RELAY_Init(void);
-
     /* Initialize the kernel */
     if (!MAIN_KernelInit()) return FALSE;
 
@@ -43,8 +42,6 @@
  */
 int main( int argc, char *argv[] )
 {
-    extern BOOL32 PROCESS_Init(void);
-    extern void *CALL32_Init(void);
     extern char * DEBUG_argv0;
 
     int i,loaded;
diff --git a/msdos/dosmem.c b/msdos/dosmem.c
index 6048ec5..0226450 100644
--- a/msdos/dosmem.c
+++ b/msdos/dosmem.c
@@ -6,7 +6,6 @@
  */
 
 #include <signal.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "windows.h"
diff --git a/msdos/dpmi.c b/msdos/dpmi.c
index 36d7058..d7128d9 100644
--- a/msdos/dpmi.c
+++ b/msdos/dpmi.c
@@ -4,7 +4,6 @@
  * Copyright 1995 Alexandre Julliard
  */
 
-#include <stdio.h>
 #include <unistd.h>
 #include <string.h>
 #include "windows.h"
@@ -374,14 +373,18 @@
     switch(AX_reg(context))
     {
     case 0x0000:  /* Allocate LDT descriptors */
+    	TRACE(int31,"allocate LDT descriptors (%d)\n",CX_reg(context));
         if (!(AX_reg(context) = AllocSelectorArray( CX_reg(context) )))
         {
+    	    TRACE(int31,"failed\n");
             AX_reg(context) = 0x8011;  /* descriptor unavailable */
             SET_CFLAG(context);
         }
+	TRACE(int31,"success, array starts at 0x%04x\n",AX_reg(context));
         break;
 
     case 0x0001:  /* Free LDT descriptor */
+    	TRACE(int31,"free LDT descriptor (0x%04x)\n",BX_reg(context));
         if (FreeSelector( BX_reg(context) ))
         {
             AX_reg(context) = 0x8022;  /* invalid selector */
@@ -399,6 +402,7 @@
         break;
 
     case 0x0002:  /* Real mode segment to descriptor */
+    	TRACE(int31,"real mode segment to descriptor (0x%04x)\n",BX_reg(context));
         {
             WORD entryPoint = 0;  /* KERNEL entry point for descriptor */
             switch(BX_reg(context))
@@ -424,18 +428,22 @@
         break;
 
     case 0x0003:  /* Get next selector increment */
+    	TRACE(int31,"get selector increment (__AHINCR)\n");
         AX_reg(context) = __AHINCR;
         break;
 
     case 0x0004:  /* Lock selector (not supported) */
+    	FIXME(int31,"lock selector not supported\n");
         AX_reg(context) = 0;  /* FIXME: is this a correct return value? */
         break;
 
     case 0x0005:  /* Unlock selector (not supported) */
+    	FIXME(int31,"unlock selector not supported\n");
         AX_reg(context) = 0;  /* FIXME: is this a correct return value? */
         break;
 
     case 0x0006:  /* Get selector base address */
+    	TRACE(int31,"get selector base address (0x%04x)\n",BX_reg(context));
         if (!(dw = GetSelectorBase( BX_reg(context) )))
         {
             AX_reg(context) = 0x8022;  /* invalid selector */
@@ -449,20 +457,24 @@
         break;
 
     case 0x0007:  /* Set selector base address */
+    	TRACE(int31,"set selector base address (0x%04x,0x%08lx)\n",BX_reg(context),MAKELONG(DX_reg(context),CX_reg(context)));
         SetSelectorBase( BX_reg(context),
                          MAKELONG( DX_reg(context), CX_reg(context) ) );
         break;
 
     case 0x0008:  /* Set selector limit */
+    	TRACE(int31,"set selector limit (0x%04x,0x%08lx)\n",BX_reg(context),MAKELONG(DX_reg(context),CX_reg(context)));
         SetSelectorLimit( BX_reg(context),
                           MAKELONG( DX_reg(context), CX_reg(context) ) );
         break;
 
     case 0x0009:  /* Set selector access rights */
+    	TRACE(int31,"set selector access rights(0x%04x,0x%04x)\n",BX_reg(context),CX_reg(context));
         SelectorAccessRights( BX_reg(context), 1, CX_reg(context) );
         break;
 
     case 0x000a:  /* Allocate selector alias */
+    	TRACE(int31,"allocate selector alias (0x%04x)\n",BX_reg(context));
         if (!(AX_reg(context) = AllocCStoDSAlias( BX_reg(context) )))
         {
             AX_reg(context) = 0x8011;  /* descriptor unavailable */
@@ -471,6 +483,7 @@
         break;
 
     case 0x000b:  /* Get descriptor */
+    	TRACE(int31,"get descriptor (0x%04x)\n",BX_reg(context));
         {
             ldt_entry entry;
             LDT_GetEntry( SELECTOR_TO_ENTRY( BX_reg(context) ), &entry );
@@ -481,6 +494,7 @@
         break;
 
     case 0x000c:  /* Set descriptor */
+    	TRACE(int31,"set descriptor (0x%04x)\n",BX_reg(context));
         {
             ldt_entry entry;
             LDT_BytesToEntry( PTR_SEG_OFF_TO_LIN( ES_reg(context),
@@ -490,6 +504,7 @@
         break;
 
     case 0x000d:  /* Allocate specific LDT descriptor */
+    	FIXME(int31,"allocate descriptor (0x%04x), stub!\n",BX_reg(context));
         AX_reg(context) = 0x8011; /* descriptor unavailable */
         SET_CFLAG(context);
         break;
@@ -503,12 +518,14 @@
     	SET_CFLAG(context);
         break;
     case 0x0204:  /* Get protected mode interrupt vector */
+    	TRACE(int31,"get protected mode interrupt handler (0x%02x), stub!\n",BL_reg(context));
 	dw = (DWORD)INT_GetHandler( BL_reg(context) );
 	CX_reg(context) = HIWORD(dw);
 	DX_reg(context) = LOWORD(dw);
 	break;
 
     case 0x0205:  /* Set protected mode interrupt vector */
+    	TRACE(int31,"set protected mode interrupt handler (0x%02x,0x%08lx), stub!\n",BL_reg(context),PTR_SEG_OFF_TO_LIN(CX_reg(context),DX_reg(context)));
 	INT_SetHandler( BL_reg(context),
                         (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( CX_reg(context),
                                                           DX_reg(context) ));
@@ -540,6 +557,7 @@
 	break;
 
     case 0x0400:  /* Get DPMI version */
+        TRACE(int31,"get DPMI version\n");
     	{
 	    SYSTEM_INFO si;
 
@@ -551,6 +569,7 @@
 	    break;
 	}
     case 0x0500:  /* Get free memory information */
+        TRACE(int31,"get free memory information\n");
         {
             MEMMANINFO mmi;
 
@@ -564,6 +583,7 @@
             break;
         }
     case 0x0501:  /* Allocate memory block */
+        TRACE(int31,"allocate memory block (%ld)\n",MAKELONG(CX_reg(context),BX_reg(context)));
 	if (!(ptr = (BYTE *)VirtualAlloc(NULL, MAKELONG(CX_reg(context), BX_reg(context)), MEM_COMMIT, PAGE_EXECUTE_READWRITE)))
         {
             AX_reg(context) = 0x8012;  /* linear memory not available */
@@ -577,10 +597,12 @@
         break;
 
     case 0x0502:  /* Free memory block */
+        TRACE(int31,"free memory block (0x%08lx)\n",MAKELONG(DI_reg(context),SI_reg(context)));
 	VirtualFree((void *)MAKELONG(DI_reg(context), SI_reg(context)), 0, MEM_RELEASE);
         break;
 
     case 0x0503:  /* Resize memory block */
+        TRACE(int31,"resize memory block (0x%08lx,%ld)\n",MAKELONG(DI_reg(context),SI_reg(context)),MAKELONG(CX_reg(context),BX_reg(context)));
         if (!(ptr = (BYTE *)HeapReAlloc( GetProcessHeap(), 0,
                            (void *)MAKELONG(DI_reg(context),SI_reg(context)),
                                    MAKELONG(CX_reg(context),BX_reg(context)))))
@@ -596,29 +618,37 @@
         break;
 
     case 0x0600:  /* Lock linear region */
+        FIXME(int31,"lock linear region unimplemented\n");
         break;  /* Just ignore it */
 
     case 0x0601:  /* Unlock linear region */
+        FIXME(int31,"unlock linear region unimplemented\n");
         break;  /* Just ignore it */
 
     case 0x0602:  /* Unlock real-mode region */
+        FIXME(int31,"unlock realmode region unimplemented\n");
         break;  /* Just ignore it */
 
     case 0x0603:  /* Lock real-mode region */
+        FIXME(int31,"lock realmode region unimplemented\n");
         break;  /* Just ignore it */
 
     case 0x0604:  /* Get page size */
+        TRACE(int31,"get pagesize\n");
         BX_reg(context) = 0;
-        CX_reg(context) = 4096;
+        CX_reg(context) = VIRTUAL_GetPageSize();
 	break;
 
     case 0x0702:  /* Mark page as demand-paging candidate */
+        FIXME(int31,"mark page as demand-paging candidate\n");
         break;  /* Just ignore it */
 
     case 0x0703:  /* Discard page contents */
+        FIXME(int31,"discard page contents\n");
         break;  /* Just ignore it */
 
      case 0x0800:  /* Physical address mapping */
+        FIXME(int31,"map real to linear (0x%08lx)\n",MAKELONG(CX_reg(context),BX_reg(context)));
          if(!(ptr=DOSMEM_MapRealToLinear(MAKELONG(CX_reg(context),BX_reg(context)))))
          {
              AX_reg(context) = 0x8021; 
diff --git a/msdos/int10.c b/msdos/int10.c
index 2f37107..d58c29e 100644
--- a/msdos/int10.c
+++ b/msdos/int10.c
@@ -2,7 +2,6 @@
  * BIOS interrupt 10h handler
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include "miscemu.h"
 /* #define DEBUG_INT */
diff --git a/msdos/int11.c b/msdos/int11.c
index 4de3d41..08ce32d 100644
--- a/msdos/int11.c
+++ b/msdos/int11.c
@@ -2,7 +2,6 @@
  * BIOS interrupt 11h handler
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include "miscemu.h"
 #include "msdos.h"
diff --git a/msdos/int13.c b/msdos/int13.c
index 68719d2..dc42119 100644
--- a/msdos/int13.c
+++ b/msdos/int13.c
@@ -2,7 +2,6 @@
  * BIOS interrupt 13h handler
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/types.h>
diff --git a/msdos/int15.c b/msdos/int15.c
index 7bc9c6a..ca046d1 100644
--- a/msdos/int15.c
+++ b/msdos/int15.c
@@ -2,7 +2,6 @@
  * BIOS interrupt 15h handler
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include "miscemu.h"
 #include "debug.h"
diff --git a/msdos/int1a.c b/msdos/int1a.c
index 350a9a9..1436bb3 100644
--- a/msdos/int1a.c
+++ b/msdos/int1a.c
@@ -4,7 +4,6 @@
 
 #include <time.h>
 #include <sys/time.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include "options.h"
 #include "miscemu.h"
diff --git a/msdos/int20.c b/msdos/int20.c
index 8ed6684..e53813a 100644
--- a/msdos/int20.c
+++ b/msdos/int20.c
@@ -2,7 +2,6 @@
  * DOS interrupt 20h handler (TERMINATE PROGRAM)
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include "miscemu.h"
 /* #define DEBUG_INT */
diff --git a/msdos/int21.c b/msdos/int21.c
index bd3c772..723deb3 100644
--- a/msdos/int21.c
+++ b/msdos/int21.c
@@ -5,7 +5,6 @@
 #include <time.h>
 #include <fcntl.h>
 #include <errno.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <sys/file.h>
 #include <string.h>
@@ -920,9 +919,6 @@
 	return seg_LOL+(WORD)&((DOS_LISTOFLISTS*)0)->ptr_first_DPB;
 }
 
-
-extern void LOCAL_PrintHeap (WORD ds);
-
 /***********************************************************************
  *           DOS3Call  (KERNEL.102)
  */
diff --git a/msdos/int25.c b/msdos/int25.c
index 6f16d88..c2709aa 100644
--- a/msdos/int25.c
+++ b/msdos/int25.c
@@ -2,7 +2,6 @@
  * DOS interrupt 25h handler
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <fcntl.h>
diff --git a/msdos/int26.c b/msdos/int26.c
index 0ad1b41..44c5e89 100644
--- a/msdos/int26.c
+++ b/msdos/int26.c
@@ -2,7 +2,6 @@
  * DOS interrupt 26h handler
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <fcntl.h>
 #include <unistd.h>
diff --git a/msdos/int2a.c b/msdos/int2a.c
index dcad173..1924a35 100644
--- a/msdos/int2a.c
+++ b/msdos/int2a.c
@@ -2,7 +2,6 @@
  * DOS interrupt 2ah handler
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include "msdos.h"
 #include "miscemu.h"
diff --git a/msdos/int2f.c b/msdos/int2f.c
index 7ab8ede..40878f1 100644
--- a/msdos/int2f.c
+++ b/msdos/int2f.c
@@ -2,7 +2,6 @@
  * DOS interrupt 2fh handler
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
diff --git a/msdos/int3d.c b/msdos/int3d.c
index 57b9995..1319036 100644
--- a/msdos/int3d.c
+++ b/msdos/int3d.c
@@ -3,7 +3,6 @@
  * Copyright 1997 Len White
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include "msdos.h"
 #include "miscemu.h"
diff --git a/msdos/ioports.c b/msdos/ioports.c
index 4233fff..7c94280 100644
--- a/msdos/ioports.c
+++ b/msdos/ioports.c
@@ -11,7 +11,6 @@
 */
 
 #include <ctype.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
@@ -87,7 +86,7 @@
 {
 	int val, val1, i, len;
 	if (!strcasecmp(temp, "all")) {
-		fprintf(stderr, "Warning!!! Granting FULL IO port access to"
+		MSG("Warning!!! Granting FULL IO port access to"
 			" windoze programs!\nWarning!!! "
 			"*** THIS IS NOT AT ALL "
 			"RECOMMENDED!!! ***\n");
diff --git a/msdos/vxd.c b/msdos/vxd.c
index 60a120d..708cd36 100644
--- a/msdos/vxd.c
+++ b/msdos/vxd.c
@@ -4,7 +4,6 @@
  * Copyright 1995 Anand Kumria
  */
 
-#include <stdio.h>
 #include "windows.h"
 #include "msdos.h"
 #include "miscemu.h"
diff --git a/multimedia/audio.c b/multimedia/audio.c
index 92d6e6e..caf63c6 100644
--- a/multimedia/audio.c
+++ b/multimedia/audio.c
@@ -13,7 +13,6 @@
 
 #define DEBUG_MCIWAVE
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
diff --git a/multimedia/dsound.c b/multimedia/dsound.c
index 4d4ac1c..63519fa 100644
--- a/multimedia/dsound.c
+++ b/multimedia/dsound.c
@@ -29,7 +29,6 @@
  */
 
 #include "config.h"
-#include <stdio.h>
 #include <assert.h>
 #include <sys/types.h>
 #include <sys/time.h>
@@ -930,3 +929,25 @@
     return S_FALSE;
 }
 
+/***************************************************************************
+ *   DirectPlayLobbyCreateW (DPLAYX.5)
+ *
+ */
+HRESULT WINAPI DirectPlayLobbyCreateW( LPGUID lpGUID, LPDIRECTPLAYLOBBY *a,
+                                       IUnknown *b, LPVOID c, DWORD d )
+{
+  FIXME(dsound,"lpGUID=%p a=%p b=%p c=%p d=%08lx :stub\n",lpGUID,a,b,c,d);
+  return E_FAIL;
+}
+
+/***************************************************************************
+ *  DirectPlayLobbyCreateA   (DPLAYX.4)
+ *
+ */
+HRESULT WINAPI DirectPlayLobbyCreateA( LPGUID lpGUID, LPDIRECTPLAYLOBBYA *a,
+                                       IUnknown *b, LPVOID c, DWORD d )
+{
+  FIXME(dsound,"lpGUID=%p a=%p b=%p c=%p d=%08lx :stub\n",lpGUID,a,b,c,d);
+  return E_FAIL;
+}
+
diff --git a/multimedia/joystick.c b/multimedia/joystick.c
index 7873daa..102f13a 100644
--- a/multimedia/joystick.c
+++ b/multimedia/joystick.c
@@ -14,7 +14,6 @@
  */
 
 #include <unistd.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <fcntl.h>
diff --git a/multimedia/mcianim.c b/multimedia/mcianim.c
index e56f503..ed74df6 100644
--- a/multimedia/mcianim.c
+++ b/multimedia/mcianim.c
@@ -4,7 +4,6 @@
  * Copyright 1994 Martin Ayotte
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
diff --git a/multimedia/mcicda.c b/multimedia/mcicda.c
index 77ce44b..ea34de9 100644
--- a/multimedia/mcicda.c
+++ b/multimedia/mcicda.c
@@ -4,7 +4,6 @@
  * Copyright 1994 Martin Ayotte
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
diff --git a/multimedia/mcistring.c b/multimedia/mcistring.c
index 3318d65..8343241 100644
--- a/multimedia/mcistring.c
+++ b/multimedia/mcistring.c
@@ -12,7 +12,6 @@
  */
 
 #include <unistd.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <fcntl.h>
diff --git a/multimedia/midi.c b/multimedia/midi.c
index 5bea87c..eec0f82 100644
--- a/multimedia/midi.c
+++ b/multimedia/midi.c
@@ -4,7 +4,6 @@
  * Copyright 1994 Martin Ayotte
  */
 
-#include <stdio.h>
 #include <errno.h>
 #include <string.h>
 #include <stdlib.h>
diff --git a/multimedia/mixer.c b/multimedia/mixer.c
index 4b554e6..1c29e47 100644
--- a/multimedia/mixer.c
+++ b/multimedia/mixer.c
@@ -4,7 +4,6 @@
  * Copyright 1997 Marcus Meissner
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
diff --git a/multimedia/mmaux.c b/multimedia/mmaux.c
index 8d2673d..5bbbf81 100644
--- a/multimedia/mmaux.c
+++ b/multimedia/mmaux.c
@@ -6,7 +6,6 @@
 
 #define EMULATE_SB16
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
diff --git a/multimedia/mmio.c b/multimedia/mmio.c
index 0e67f41..32922ed 100644
--- a/multimedia/mmio.c
+++ b/multimedia/mmio.c
@@ -9,7 +9,6 @@
  */
 
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
diff --git a/multimedia/mmsystem.c b/multimedia/mmsystem.c
index d40000e..275cc17 100644
--- a/multimedia/mmsystem.c
+++ b/multimedia/mmsystem.c
@@ -8,7 +8,6 @@
  */
 
 #include <unistd.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <fcntl.h>
diff --git a/multimedia/time.c b/multimedia/time.c
index a1ae385..7426605 100644
--- a/multimedia/time.c
+++ b/multimedia/time.c
@@ -4,7 +4,6 @@
  * Copyright 1993 Martin Ayotte
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "windows.h"
diff --git a/objects/bitmap.c b/objects/bitmap.c
index 241eaf3..0a3dbdf 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -4,7 +4,6 @@
  * Copyright 1993 Alexandre Julliard
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "ts_xlib.h"
@@ -176,6 +175,10 @@
     bmpObjPtr->bitmap.bmWidthBytes = (INT16)BITMAP_WIDTH_BYTES( width, bpp );
     bmpObjPtr->bitmap.bmBits = NULL;
 
+    bmpObjPtr->dibSection = NULL;
+    bmpObjPtr->colorMap = NULL;
+    bmpObjPtr->nColorMap = 0;
+
       /* Create the pixmap */
     bmpObjPtr->pixmap = TSXCreatePixmap(display, rootWindow, width, height, bpp);
     if (!bmpObjPtr->pixmap)
@@ -824,6 +827,19 @@
       shmdt(p->si.shmaddr);  /* already marked for destruction */
     }
 #endif
+
+    if (bmp->dibSection)
+    {
+	DIBSECTION *dib = bmp->dibSection;
+
+	if (!dib->dshSection && dib->dsBm.bmBits)
+	    HeapFree(GetProcessHeap(), 0, dib->dsBm.bmBits);
+
+	HeapFree(GetProcessHeap(), 0, dib);
+    }
+    if (bmp->colorMap)
+	HeapFree(GetProcessHeap(), 0, bmp->colorMap);
+
     return GDI_FreeObject( hbitmap );
 }
 
@@ -833,9 +849,17 @@
  */
 INT16 BITMAP_GetObject16( BITMAPOBJ * bmp, INT16 count, LPVOID buffer )
 {
-    if (count > sizeof(bmp->bitmap)) count = sizeof(bmp->bitmap);
-    memcpy( buffer, &bmp->bitmap, count );
-    return count;
+    if (bmp->dibSection)
+    {
+	FIXME(bitmap, "not implemented for DIBs\n");
+	return 0;
+    }
+    else
+    {
+	if (count > sizeof(bmp->bitmap)) count = sizeof(bmp->bitmap);
+	memcpy( buffer, &bmp->bitmap, count );
+	return count;
+    }
 }
     
 
@@ -844,17 +868,34 @@
  */
 INT32 BITMAP_GetObject32( BITMAPOBJ * bmp, INT32 count, LPVOID buffer )
 {
-    BITMAP32 bmp32;
-    bmp32.bmType       = bmp->bitmap.bmType;
-    bmp32.bmWidth      = bmp->bitmap.bmWidth;
-    bmp32.bmHeight     = bmp->bitmap.bmHeight;
-    bmp32.bmWidthBytes = bmp->bitmap.bmWidthBytes;
-    bmp32.bmPlanes     = bmp->bitmap.bmPlanes;
-    bmp32.bmBitsPixel  = bmp->bitmap.bmBitsPixel;
-    bmp32.bmBits       = NULL;
-    if (count > sizeof(bmp32)) count = sizeof(bmp32);
-    memcpy( buffer, &bmp32, count );
-    return count;
+    if (bmp->dibSection)
+    {
+	if (count < sizeof(DIBSECTION))
+	{
+	    if (count > sizeof(BITMAP32)) count = sizeof(BITMAP32);
+	}
+	else
+	{
+	    if (count > sizeof(DIBSECTION)) count = sizeof(DIBSECTION);
+	}
+
+	memcpy( buffer, bmp->dibSection, count );
+	return count;
+    }
+    else
+    {
+	BITMAP32 bmp32;
+	bmp32.bmType       = bmp->bitmap.bmType;
+	bmp32.bmWidth      = bmp->bitmap.bmWidth;
+	bmp32.bmHeight     = bmp->bitmap.bmHeight;
+	bmp32.bmWidthBytes = bmp->bitmap.bmWidthBytes;
+	bmp32.bmPlanes     = bmp->bitmap.bmPlanes;
+	bmp32.bmBitsPixel  = bmp->bitmap.bmBitsPixel;
+	bmp32.bmBits       = NULL;
+	if (count > sizeof(bmp32)) count = sizeof(bmp32);
+	memcpy( buffer, &bmp32, count );
+	return count;
+    }
 }
     
 
diff --git a/objects/clipping.c b/objects/clipping.c
index 7025d74..ac7119e 100644
--- a/objects/clipping.c
+++ b/objects/clipping.c
@@ -4,7 +4,6 @@
  * Copyright 1993 Alexandre Julliard
  */
 
-#include <stdio.h>
 #include "dc.h"
 #include "metafile.h"
 #include "region.h"
diff --git a/objects/color.c b/objects/color.c
index 50779dc..6487adb 100644
--- a/objects/color.c
+++ b/objects/color.c
@@ -7,7 +7,6 @@
 
 #include <stdlib.h>
 #include "ts_xlib.h"
-#include <stdio.h>
 #include <string.h>
 #include "windows.h"
 #include "options.h"
diff --git a/objects/cursoricon.c b/objects/cursoricon.c
index 74da477..439660f 100644
--- a/objects/cursoricon.c
+++ b/objects/cursoricon.c
@@ -42,9 +42,7 @@
 #include "task.h"
 #include "user.h"
 #include "keyboard.h"
-
-extern UINT16 COLOR_GetSystemPaletteSize();
-extern void _XInitImageFuncPtrs(XImage *);
+#include "x11drv.h"
 
 Cursor CURSORICON_XCursor = None;    /* Current X cursor */
 static HCURSOR32 hActiveCursor = 0;  /* Active cursor */
diff --git a/objects/dc.c b/objects/dc.c
index f608b09..80a5b94 100644
--- a/objects/dc.c
+++ b/objects/dc.c
@@ -7,6 +7,7 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include "dc.h"
 #include "gdi.h"
 #include "heap.h"
 #include "metafile.h"
@@ -16,9 +17,6 @@
 #include "winerror.h"
 #include "x11font.h"
 
-extern void CLIPPING_UpdateGCRegion( DC * dc );     /* objects/clipping.c */
-
-
   /* ROP code to GC function conversion */
 const int DC_XROPfunction[16] =
 {
diff --git a/objects/dib.c b/objects/dib.c
index a5ae6e3..e41edeb 100644
--- a/objects/dib.c
+++ b/objects/dib.c
@@ -4,7 +4,6 @@
  * Copyright 1993,1994  Alexandre Julliard
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include "ts_xlib.h"
 #include "ts_xutil.h"
@@ -15,8 +14,6 @@
 #include "color.h"
 #include "debug.h"
 
-extern void CLIPPING_UpdateGCRegion(DC* );
-
 static int bitmapDepthTable[] = { 8, 1, 32, 16, 24, 15, 4, 0 };
 static int ximageDepthTable[] = { 0, 0, 0,  0,  0,  0,  0 };
 
@@ -30,8 +27,9 @@
     DWORD             infoWidth;
     WORD              depth;
     WORD              infoBpp;
-    const BITMAPINFO *info;
-    WORD              coloruse;
+    WORD              compression;
+    RGBQUAD          *colorMap;
+    int               nColorMap;
     Drawable          drawable;
     GC                gc;
     int               xSrc;
@@ -145,13 +143,14 @@
  * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
  */
 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
-                              int *height, WORD *bpp )
+                              int *height, WORD *bpp, WORD *compr )
 {
     if (header->biSize == sizeof(BITMAPINFOHEADER))
     {
         *width  = header->biWidth;
         *height = header->biHeight;
         *bpp    = header->biBitCount;
+        *compr  = header->biCompression;
         return 1;
     }
     if (header->biSize == sizeof(BITMAPCOREHEADER))
@@ -160,6 +159,7 @@
         *width  = core->bcWidth;
         *height = core->bcHeight;
         *bpp    = core->bcBitCount;
+        *compr  = 0;
         return 0;
     }
     WARN(bitmap, "(%ld): wrong size for header\n", header->biSize );
@@ -171,15 +171,15 @@
  *           DIB_BuildColorMap
  *
  * Build the color map from the bitmap palette. Should not be called
- * for a 24-bit deep bitmap.
+ * for a >8-bit deep bitmap.
  */
-static int *DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth,
-                               const BITMAPINFO *info )
+static RGBQUAD *DIB_BuildColorMap( const BITMAPINFO *info, 
+				   HPALETTE16 hPalette, int *nColors )
 {
     int i, colors;
     BOOL32 isInfo;
     WORD *colorPtr;
-    int *colorMapping;
+    RGBQUAD *colorMapping;
 
     if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
     {
@@ -192,45 +192,90 @@
         colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
         colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
     }
-    if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
-                                          colors * sizeof(int) ))) return NULL;
 
-    if (coloruse == DIB_RGB_COLORS)
+    if (colors > 256)
+    {
+        ERR(bitmap, "DIB_BuildColorMap called with >256 colors!\n");
+        return NULL;
+    }
+
+    if (!(colorMapping = (RGBQUAD *)HeapAlloc(GetProcessHeap(), 0,
+                                              colors * sizeof(RGBQUAD) ))) 
+	return NULL;
+
+    if (hPalette == 0) /* DIB_RGB_COLORS */
     {
         if (isInfo)
         {
             RGBQUAD * rgb = (RGBQUAD *)colorPtr;
-        
-            if (depth == 1)  /* Monochrome */
-                for (i = 0; i < colors; i++, rgb++)
-                    colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen + 
-                                       rgb->rgbBlue > 255*3/2);
-            else
-                for (i = 0; i < colors; i++, rgb++)
-                    colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgb->rgbRed,
-                                                                rgb->rgbGreen,
-                                                                rgb->rgbBlue));
+
+            for (i = 0; i < colors; i++, rgb++)
+                colorMapping[i] = *rgb;
         }
         else
         {
             RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
         
-            if (depth == 1)  /* Monochrome */
-                for (i = 0; i < colors; i++, rgb++)
-                    colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen + 
-                                       rgb->rgbtBlue > 255*3/2);
-            else
-                for (i = 0; i < colors; i++, rgb++)
-                    colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgb->rgbtRed,
-                                                               rgb->rgbtGreen,
-                                                               rgb->rgbtBlue));
+            for (i = 0; i < colors; i++, rgb++)
+                colorMapping[i].rgbRed   = rgb->rgbtRed,
+                colorMapping[i].rgbGreen = rgb->rgbtGreen,
+                colorMapping[i].rgbBlue  = rgb->rgbtBlue;
         }
     }
     else  /* DIB_PAL_COLORS */
     {
+	PALETTEOBJ *palPtr = (PALETTEOBJ *)GDI_GetObjPtr(hPalette, PALETTE_MAGIC);
+	if (!palPtr) 
+	{
+	    HeapFree(GetProcessHeap(), 0, colorMapping);
+	    return NULL;
+	}
+
         for (i = 0; i < colors; i++, colorPtr++)
-            colorMapping[i] = COLOR_ToPhysical( dc, PALETTEINDEX(*colorPtr) );
+	    if (*colorPtr >= palPtr->logpalette.palNumEntries)
+	    {
+		colorMapping[i].rgbRed   = 0;
+		colorMapping[i].rgbGreen = 0;
+		colorMapping[i].rgbBlue  = 0;
+	    }
+	    else
+	    {
+		PALETTEENTRY *pe = palPtr->logpalette.palPalEntry + *colorPtr;
+		colorMapping[i].rgbRed   = pe->peRed;
+		colorMapping[i].rgbGreen = pe->peGreen;
+		colorMapping[i].rgbBlue  = pe->peBlue;
+	    }
+	
+	GDI_HEAP_UNLOCK(hPalette);
     }
+
+    *nColors = colors;
+    return colorMapping;
+}
+
+/***********************************************************************
+ *           DIB_PhysicalColorMap
+ *
+ * Translate color map to physical colors
+ */
+static int *DIB_PhysicalColorMap( DC *dc, int depth, 
+				  RGBQUAD *colorMap, int nColorMap)
+{
+    int *colorMapping, i;
+
+    if (!nColorMap) return NULL;
+    if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
+                                          nColorMap * sizeof(int) ))) return NULL;
+
+    if (depth == 1) /* Monochrome */
+	for (i = 0; i < nColorMap; i++, colorMap++)
+	    colorMapping[i] = (colorMap->rgbRed + colorMap->rgbGreen + 
+                               colorMap->rgbBlue > 255*3/2);
+    else
+	for (i = 0; i < nColorMap; i++, colorMap++)
+            colorMapping[i] = COLOR_ToPhysical( dc, RGB(colorMap->rgbRed,
+                                                        colorMap->rgbGreen,
+                                                        colorMap->rgbBlue));
     return colorMapping;
 }
 
@@ -771,17 +816,13 @@
 {
     int *colorMapping;
     XImage *bmpImage;
-    DWORD compression = 0;
     int lines;
 
-    if (descr->info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
-        compression = descr->info->bmiHeader.biCompression;
-
-      /* Build the color mapping table */
+      /* Translate the color mapping table */
 
     if (descr->infoBpp > 8) colorMapping = NULL;
-    else if (!(colorMapping = DIB_BuildColorMap( descr->dc, descr->coloruse,
-                                                 descr->depth, descr->info )))
+    else if (!(colorMapping = DIB_PhysicalColorMap( descr->dc, descr->depth,
+						    descr->colorMap, descr->nColorMap )))
         return 0;
 
     if( descr->dc->w.flags & DC_DIRTY ) CLIPPING_UpdateGCRegion(descr->dc);
@@ -798,14 +839,14 @@
 			    descr->width, descr->xSrc, colorMapping, bmpImage );
 	break;
     case 4:
-	if (compression) DIB_SetImageBits_RLE4( descr->lines, descr->bits,
+	if (descr->compression) DIB_SetImageBits_RLE4( descr->lines, descr->bits,
                                                 descr->infoWidth, descr->width, descr->xSrc,
                                                 colorMapping, bmpImage );
 	else DIB_SetImageBits_4( descr->lines, descr->bits, descr->infoWidth,
                                  descr->width, descr->xSrc, colorMapping, bmpImage );
 	break;
     case 8:
-	if (compression) DIB_SetImageBits_RLE8( descr->lines, descr->bits,
+	if (descr->compression) DIB_SetImageBits_RLE8( descr->lines, descr->bits,
                                                 descr->infoWidth, descr->width, descr->xSrc,
                                                 colorMapping, bmpImage );
 	else DIB_SetImageBits_8( descr->lines, descr->bits, descr->infoWidth,
@@ -925,7 +966,7 @@
         return 0;
     }
     if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
-                           &descr.infoBpp ) == -1)
+                           &descr.infoBpp, &descr.compression ) == -1)
     {
         GDI_HEAP_UNLOCK( hbitmap );
         GDI_HEAP_UNLOCK( hdc );
@@ -941,11 +982,25 @@
     }
     if (startscan + lines > height) lines = height - startscan;
 
+    if (descr.infoBpp <= 8)
+    {
+        descr.colorMap = DIB_BuildColorMap( info, coloruse == DIB_PAL_COLORS?
+                                            descr.dc->w.hPalette : 0, 
+                                            &descr.nColorMap);
+
+        if (!descr.colorMap)
+        {
+            GDI_HEAP_UNLOCK( hbitmap );
+            GDI_HEAP_UNLOCK( hdc );
+            return 0;
+        } 
+    }
+
+
+
     descr.bits      = bits;
     descr.lines     = tmpheight >= 0 ? lines : -lines;
     descr.depth     = bmp->bitmap.bmBitsPixel;
-    descr.info      = info;
-    descr.coloruse  = coloruse;
     descr.drawable  = bmp->pixmap;
     descr.gc        = BITMAP_GC(bmp);
     descr.xSrc      = 0;
@@ -959,6 +1014,8 @@
     result = CALL_LARGE_STACK( DIB_SetImageBits, &descr );
     LeaveCriticalSection( &X11DRV_CritSection );
 
+    HeapFree(GetProcessHeap(), 0, descr.colorMap);
+
     GDI_HEAP_UNLOCK( hdc );
     GDI_HEAP_UNLOCK( hbitmap );
     return result;
@@ -1000,8 +1057,8 @@
 	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
 	if (!dc) return 0;
     }
-    if (DIB_GetBitmapInfo( &info->bmiHeader, &width,
-                           &height, &descr.infoBpp ) == -1)
+    if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, 
+			   &descr.infoBpp, &descr.compression ) == -1)
         return 0;
     tmpheight = height;
     if (height < 0) height = -height;
@@ -1017,13 +1074,21 @@
     DC_SetupGCForText( dc );  /* To have the correct colors */
     TSXSetFunction( display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
 
+    if (descr.infoBpp <= 8)
+    {
+        descr.colorMap = DIB_BuildColorMap( info, coloruse == DIB_PAL_COLORS?
+                                            descr.dc->w.hPalette : 0, 
+                                            &descr.nColorMap );
+
+        if (!descr.colorMap)
+            return 0;
+    }
+
     descr.dc        = dc;
     descr.bits      = bits;
     descr.lines     = tmpheight >= 0 ? lines : -lines;
     descr.infoWidth = width;
     descr.depth     = dc->w.bitsPerPixel;
-    descr.info      = info;
-    descr.coloruse  = coloruse;
     descr.drawable  = dc->u.x.drawable;
     descr.gc        = dc->u.x.gc;
     descr.xSrc      = xSrc;
@@ -1036,6 +1101,8 @@
     EnterCriticalSection( &X11DRV_CritSection );
     result = CALL_LARGE_STACK( DIB_SetImageBits, &descr );
     LeaveCriticalSection( &X11DRV_CritSection );
+
+    HeapFree(GetProcessHeap(), 0, descr.colorMap);
     return result;
 }
 
@@ -1161,7 +1228,7 @@
     PALETTEOBJ * palette;
     XImage * bmpImage;
     int i, x, y;
-        
+
     if (!lines) return 0;
     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) 
@@ -1193,7 +1260,7 @@
 	    else ((WORD *)info->bmiColors)[i] = (WORD)i;
 	}
     }
-    
+
     if (bits)
     {	
 	BYTE*	bbits = bits;
@@ -1367,8 +1434,9 @@
     DWORD width;
     int height;
     WORD bpp;
+    WORD compr;
 
-    if (DIB_GetBitmapInfo( header, &width, &height, &bpp ) == -1) return 0;
+    if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
     if (height < 0) height = -height;
 
     /* Check if we should create a monochrome or color bitmap. */
@@ -1415,7 +1483,7 @@
 
     /* Now create the bitmap */
 
-    handle = fColor ? CreateCompatibleBitmap32( hdc, width, height ) :
+    handle = fColor ? CreateBitmap32( width, height, 1, screenDepth, NULL ) :
                       CreateBitmap32( width, height, 1, 1, NULL );
     if (!handle) return 0;
 
@@ -1431,7 +1499,7 @@
 				     LPVOID **bits, HANDLE16 section,
 				     DWORD offset)
 {
-  return CreateDIBSection32 (hdc, bmi, usage, bits, section, offset);
+    return CreateDIBSection32(hdc, bmi, usage, bits, section, offset);
 }
 
 /***********************************************************************
@@ -1441,35 +1509,173 @@
 				     LPVOID **bits,HANDLE32 section,
 				     DWORD offset)
 {
-  HBITMAP32 res = 0;
+    HBITMAP32 res = 0;
+    BITMAPOBJ *bmp = NULL;
+    DIBSECTION *dib = NULL;
+    RGBQUAD *colorMap = NULL;
+    int nColorMap;
 
-  FIXME(bitmap,
-	  "(%d,[w=%ld,h=%ld],%d,%p,0x%08x,%ld),semistub\n",
-	  hdc,bmi->bmiHeader.biWidth,bmi->bmiHeader.biHeight,
-	  usage,bits,section,offset);
+    /* Fill BITMAP32 structure with DIB data */
+    BITMAPINFOHEADER *bi = &bmi->bmiHeader;
+    BITMAP32 bm;
 
-  if (bmi->bmiHeader.biHeight < 0 ) bmi->bmiHeader.biHeight = -bmi->bmiHeader.biHeight;
-  if (bmi->bmiHeader.biWidth < 0 ) bmi->bmiHeader.biWidth = -bmi->bmiHeader.biWidth;
-  /* FIXME.  The following line isn't quite right.  */
-  res = CreateDIBitmap32 (hdc, &bmi->bmiHeader, 0, NULL, bmi, 0);
-  if (res)
+    TRACE(bitmap, "format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
+	  bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
+	  bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
+
+    if (bi->biCompression)
     {
-      BITMAP32 bmp;
-      if (GetObject32A (res, sizeof (bmp), &bmp))
-	{
-            /* FIXME: this is wrong! (bmBits is always NULL) */
-            if (bits) *bits = bmp.bmBits;
-	    /* hmpf */
-	    TRACE(bitmap,"allocating %ld bytes of memory\n",
-                bmi->bmiHeader.biWidth*bmi->bmiHeader.biHeight*4);
-	    if (bits) *bits = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
-                bmi->bmiHeader.biWidth*bmi->bmiHeader.biHeight*4);
-            return res;
-	}
+	FIXME(bitmap, "Compression not implemented!\n");
+	return 0;
     }
 
-  /* Error.  */
-  if (res) DeleteObject32 (res);
-  if (bits) *bits = NULL;
-  return 0;
+    bm.bmType = 0;
+    bm.bmWidth = bi->biWidth;
+    bm.bmHeight = bi->biHeight;
+    bm.bmWidthBytes = DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
+    bm.bmPlanes = bi->biPlanes;
+    bm.bmBitsPixel = bi->biBitCount;
+    bm.bmBits = NULL;
+
+    /* Get storage location for DIB bits */
+    if (section)
+	FIXME(bitmap, "section != NULL not implemented!\n");	
+    else
+    {
+	INT32 totalSize = bi->biSizeImage? bi->biSizeImage
+                                         : bm.bmWidthBytes * bm.bmHeight;
+
+	bm.bmBits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, totalSize);
+    }
+
+    /* Allocate Memory for DIB and fill structure */
+    if (bm.bmBits)
+	dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DIBSECTION));
+    if (dib)
+    {
+	dib->dsBm = bm;
+	dib->dsBmih = *bi;
+	/* FIXME: dib->dsBitfields ??? */
+	dib->dshSection = section;
+	dib->dsOffset = offset;
+    }
+
+    /* Create Color Map */
+    if (dib && bm.bmBitsPixel <= 8)
+    {
+        HPALETTE16 hPalette = 0;
+        if (usage == DIB_PAL_COLORS)
+        {
+            DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
+            if (!dc) 
+	        dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+            if (dc)
+	    {
+		hPalette = dc->w.hPalette;
+		GDI_HEAP_UNLOCK(hdc);
+	    }
+	}
+	colorMap = DIB_BuildColorMap(bmi, hPalette, &nColorMap);
+    }
+
+    /* Create Device Dependent Bitmap and add DIB/ColorMap info */
+    if (dib) 
+    {
+       res = CreateDIBitmap32(hdc, bi, 0, NULL, bmi, usage);
+       bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
+       if (bmp)
+       {
+	    bmp->dibSection = dib;
+            bmp->colorMap   = colorMap;
+	    bmp->nColorMap  = nColorMap;
+	    GDI_HEAP_UNLOCK(res);
+       }
+    }
+
+    /* Clean up in case of errors */
+    if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
+    {
+	if (bm.bmBits && section) 
+	    HeapFree(GetProcessHeap(), 0, bm.bmBits), bm.bmBits = NULL;
+
+	if (colorMap) HeapFree(GetProcessHeap(), 0, colorMap), colorMap = NULL;
+	if (dib) HeapFree(GetProcessHeap(), 0, dib), dib = NULL;
+	if (res) DeleteObject32(res), res = 0;
+    }
+
+    /* Return BITMAP handle and storage location */
+    if (bm.bmBits && bits) *bits = bm.bmBits;
+    return res;
 }
+
+/***********************************************************************
+ *           DIB_UpdateDIBSection
+ */
+void DIB_UpdateDIBSection( DC *dc, BOOL32 toDIB )
+{
+    BITMAPOBJ *bmp;
+    DIBSECTION *dib;
+
+    /* Ensure this is a Compatible DC that has a DIB section selected */
+
+    if (!dc) return;
+    if (!(dc->w.flags & DC_MEMORY)) return;
+
+    bmp = (BITMAPOBJ *)GDI_GetObjPtr( dc->w.hBitmap, BITMAP_MAGIC );
+    if (!bmp) return;
+
+    dib = bmp->dibSection;
+    if (!dib)
+    {
+	GDI_HEAP_UNLOCK(dc->w.hBitmap);
+	return;
+    }
+
+  
+    /* Copy Pixmap to bits */
+    if (toDIB)
+    {
+        /* Expect colour corruption if you uncomment this. -MF */
+//        BITMAPINFO bi;
+//        bi.bmiHeader = dib->dsBmih;
+//        bi.bmiHeader.biClrUsed = 0; /* don't copy palette */
+//        TRACE(bitmap, "Copying from Pixmap to DIB bits\n");
+//        GetDIBits32( dc->hSelf, dc->w.hBitmap, 0, dib->dsBmih.biHeight,
+//                     dib->dsBm.bmBits, &bi, 0 );
+    }
+
+    /* Copy bits to Pixmap */
+    else
+    {
+    	DIB_SETIMAGEBITS_DESCR descr;
+
+	TRACE(bitmap, "Copying from DIB bits to Pixmap\n"); 
+	if (DIB_GetBitmapInfo( &dib->dsBmih, &descr.infoWidth, &descr.lines,
+			       &descr.infoBpp, &descr.compression ) == -1)
+	{
+	    GDI_HEAP_UNLOCK(dc->w.hBitmap);
+	    return;
+	}
+
+        descr.dc        = dc;
+        descr.colorMap  = bmp->colorMap;
+        descr.nColorMap = bmp->nColorMap;
+        descr.bits      = dib->dsBm.bmBits;
+        descr.depth     = bmp->bitmap.bmBitsPixel;
+        descr.drawable  = bmp->pixmap;
+        descr.gc        = BITMAP_GC(bmp);
+        descr.xSrc      = 0;
+        descr.ySrc      = 0;
+        descr.xDest     = 0;
+        descr.yDest     = 0;
+        descr.width     = bmp->bitmap.bmWidth;
+        descr.height    = bmp->bitmap.bmHeight;
+
+        EnterCriticalSection( &X11DRV_CritSection );
+        CALL_LARGE_STACK( DIB_SetImageBits, &descr );
+        LeaveCriticalSection( &X11DRV_CritSection );
+    }
+
+    GDI_HEAP_UNLOCK(dc->w.hBitmap);
+}
+
diff --git a/objects/enhmetafile.c b/objects/enhmetafile.c
index 8c34bf9..9275278 100644
--- a/objects/enhmetafile.c
+++ b/objects/enhmetafile.c
@@ -3,7 +3,6 @@
   Copyright 1998, Douglas Ridgway
 */
 
-#include <stdio.h>
 #include <string.h>
 #include "windows.h"
 #include "gdi.h"
diff --git a/objects/font.c b/objects/font.c
index 7117e7e..6f5a911 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -5,7 +5,6 @@
  *           1997 Alex Korobka
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "font.h"
diff --git a/objects/gdiobj.c b/objects/gdiobj.c
index ae4ad7e..22c8722 100644
--- a/objects/gdiobj.c
+++ b/objects/gdiobj.c
@@ -5,7 +5,6 @@
  */
 
 #include <stdlib.h>
-#include <stdio.h>
 #include "color.h"
 #include "bitmap.h"
 #include "brush.h"
@@ -227,9 +226,6 @@
  */
 BOOL32 GDI_Init(void)
 {
-    extern BOOL32 X11DRV_Init(void);
-    extern BOOL32 DIB_Init(void);
-
     /* Kill some warnings.  */
     (void)align_OEMFixedFont;
     (void)align_AnsiFixedFont;
diff --git a/objects/oembitmap.c b/objects/oembitmap.c
index 862ec52..8dbd25f 100644
--- a/objects/oembitmap.c
+++ b/objects/oembitmap.c
@@ -336,6 +336,11 @@
     bmpObjPtr->bitmap.bmPlanes     = 1;
     bmpObjPtr->bitmap.bmBitsPixel  = bpp;
     bmpObjPtr->bitmap.bmBits       = (SEGPTR)NULL;
+
+    bmpObjPtr->dibSection          = NULL;
+    bmpObjPtr->colorMap            = NULL;
+    bmpObjPtr->nColorMap           = 0;
+
     GDI_HEAP_UNLOCK( hbitmap );
     return hbitmap;
 }
diff --git a/objects/region.c b/objects/region.c
index a9aee1c..6c79e1e 100644
--- a/objects/region.c
+++ b/objects/region.c
@@ -80,7 +80,6 @@
  * the y-x-banding that's so nice to have...
  */
 
-#include <stdio.h>
 #include "region.h"
 #include "debug.h"
 #include "heap.h"
diff --git a/ole/folders.c b/ole/folders.c
index 6d159f5..a9fc717 100644
--- a/ole/folders.c
+++ b/ole/folders.c
@@ -110,7 +110,8 @@
 	FIXME(ole,"(%p)->(%08x,%p,%p,%p,%p,%p),stub!\n",
 		this,hwndOwner,pbcReserved,lpszDisplayName,pchEaten,ppidl,pdwAttributes
 	);
-	*(DWORD*)pbcReserved = 0;
+	if (pbcReserved)
+		*(DWORD*)pbcReserved = 0;
 	return 0;
 }
 
diff --git a/ole/ole2nls.c b/ole/ole2nls.c
index c1d6fca..abba660 100644
--- a/ole/ole2nls.c
+++ b/ole/ole2nls.c
@@ -138,7 +138,7 @@
 	{0x0403,"Katalanisch"},
 	{0x0404,"Traditionales Chinesisch"},
 	{0x0405,"Tschecisch"},
-	{0x0406,"Ddnisch"},
+	{0x0406,"Dänisch"},
 	{0x0407,"Deutsch"},
 	{0x0408,"Griechisch"},
 	{0x0409,"Amerikanisches Englisch"},
@@ -1710,7 +1710,7 @@
 {
 	int len,ret;
 	if(fdwStyle & NORM_IGNORENONSPACE)
-		FIXME(ole, "IGNORENONSPACE not supprted\n");
+		FIXME(ole, "IGNORENONSPACE not supported\n");
 	if(fdwStyle & NORM_IGNORESYMBOLS)
 		FIXME(ole, "IGNORESYMBOLS not supported\n");
 	/* Is strcmp defaulting to string sort or to word sort?? */
@@ -1960,19 +1960,23 @@
 DWORD WINAPI VerLanguageName16(UINT16 langid,LPSTR langname,UINT16 langnamelen)
 {
 	int	i;
-	char	*buf;
+	DWORD	result;
+	char	buffer[80];
 
 	TRACE(ver,"(%d,%p,%d)\n",langid,langname,langnamelen);
 	/* First, check \System\CurrentControlSet\control\Nls\Locale\<langid>
 	 * from the registry. 
 	 */
-	buf=(char*)malloc(strlen("\\System\\CurrentControlSet\\control\\Nls\\Locale\\")+9);
-	sprintf(buf,"\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x",langid);
-	if (ERROR_SUCCESS==RegQueryValue16(HKEY_LOCAL_MACHINE,buf,langname,(LPDWORD)&langnamelen)) {
+	sprintf(buffer,
+		"\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x",
+		langid);
+	result = RegQueryValue16(HKEY_LOCAL_MACHINE, buffer, langname,
+				(LPDWORD)&langnamelen);
+	if (result == ERROR_SUCCESS) {
 		langname[langnamelen-1]='\0';
 		return langnamelen;
 	}
-	/* if that fails, use the interal table */
+	/* if that fails, use the internal table */
 	for (i=0;languages[i].langid!=0;i++)
 		if (langid==languages[i].langid)
 			break;
@@ -1997,101 +2001,608 @@
                                 UINT32 langnamelen)
 {
 	int	i;
-	char	buffer[80];
 	LPWSTR	keyname;
+	DWORD	result;
+	char	buffer[80];
 
 	/* First, check \System\CurrentControlSet\control\Nls\Locale\<langid>
 	 * from the registry. 
 	 */
-	sprintf(buffer,"\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x",langid);
+	sprintf(buffer,
+		"\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x",
+		langid);
 	keyname = HEAP_strdupAtoW( GetProcessHeap(), 0, buffer );
-	if (ERROR_SUCCESS==RegQueryValue32W(HKEY_LOCAL_MACHINE,keyname,langname,(LPDWORD)&langnamelen)) {
-		HeapFree( GetProcessHeap(), 0, keyname );
-		return langnamelen;
+	result = RegQueryValue32W(HKEY_LOCAL_MACHINE, keyname, langname,
+				(LPDWORD)&langnamelen);
+	HeapFree( GetProcessHeap(), 0, keyname );
+	if (result != ERROR_SUCCESS) {
+		/* if that fails, use the internal table */
+		for (i=0;languages[i].langid!=0;i++)
+			if (langid==languages[i].langid)
+				break;
+        	lstrcpyAtoW( langname, languages[i].langname );
+		langnamelen = strlen(languages[i].langname);
+	 	/* same as strlenW(langname); */
 	}
-        HeapFree( GetProcessHeap(), 0, keyname );
-	/* if that fails, use the interal table */
-	for (i=0;languages[i].langid!=0;i++)
-		if (langid==languages[i].langid)
-			break;
-        lstrcpyAtoW( langname, languages[i].langname );
-	return strlen(languages[i].langname); /* same as strlenW(langname); */
+	return langnamelen;
+}
+ 
+static int is_punctuation(unsigned char c)
+{
+  /* punctuation characters are :
+     39, 45, 127-129, 141-144, 150-151, 157-158, 173 */
+  if (c>=141)
+  {
+    if (c<=151)
+      return (c<=144) || (c>=150);
+    if (c<=158)
+      return (c>=157);
+    return (c==173);
+  }
+  if (c>=127)
+    return (c<=129);
+  return (c==39) || (c==45);
 }
 
-
-INT32 WINAPI LCMapString32A(
-	LCID lcid,DWORD mapflags,LPCSTR srcstr,INT32 srclen,LPSTR dststr,
-	INT32 dstlen
-) {
-	int	i,len;
-
-	TRACE(string,"(0x%04lx,0x%08lx,%s,%d,%p,%d)\n",
-		lcid,mapflags,srcstr,srclen,dststr,dstlen);
-	if (!dstlen || !dststr) {
-		dststr = (LPSTR)srcstr;
-	}
-	if (!srclen) srclen = strlen(srcstr);
-	if (!dstlen) dstlen = strlen(dststr);
-	len = dstlen;
-	if (srclen < len)
-		len = srclen;
-	if (mapflags & LCMAP_LOWERCASE) {
-		for (i=0;i<len;i++)
-			dststr[i]=tolower(srcstr[i]);
-		mapflags &= ~LCMAP_LOWERCASE;
-	}
-	if (mapflags & LCMAP_UPPERCASE) {
-		for (i=0;i<len;i++)
-			dststr[i]=toupper(srcstr[i]);
-		mapflags &= ~LCMAP_UPPERCASE;
-	}
-	if (mapflags)
-	  {
-	    FIXME(ole,"(0x%04lx,0x%08lx,%p,%d,%p,%d): "
-		  "unimplemented flags: 0x%08lx\n",
-		  lcid,mapflags,srcstr,srclen,dststr,dstlen,mapflags);
-	  }
-	return len;
+static int identity(int c)
+{
+  return c;
 }
 
-/* FIXME: implement everyhting & correct */
+static const unsigned char LCM_Unicode_LUT[] = {
+  7      ,   2, /*   -  32 */
+  7      ,  28, /* ! -  33 */
+  7      ,  29, /* " -  34 */ /* " */
+  7      ,  31, /* # -  35 */
+  7      ,  33, /* $ -  36 */
+  7      ,  35, /* % -  37 */
+  7      ,  37, /* & -  38 */
+  6      , 128, /* ' -  39 */
+  7      ,  39, /* ( -  40 */
+  7      ,  42, /* ) -  41 */
+  7      ,  45, /* * -  42 */
+  8      ,   3, /* + -  43 */
+  7      ,  47, /* , -  44 */
+  6      , 130, /* - -  45 */
+  7      ,  51, /* . -  46 */
+  7      ,  53, /* / -  47 */
+ 12      ,   3, /* 0 -  48 */
+ 12      ,  33, /* 1 -  49 */
+ 12      ,  51, /* 2 -  50 */
+ 12      ,  70, /* 3 -  51 */
+ 12      ,  88, /* 4 -  52 */
+ 12      , 106, /* 5 -  53 */
+ 12      , 125, /* 6 -  54 */
+ 12      , 144, /* 7 -  55 */
+ 12      , 162, /* 8 -  56 */
+ 12      , 180, /* 9 -  57 */
+  7      ,  55, /* : -  58 */
+  7      ,  58, /* ; -  59 */
+  8      ,  14, /* < -  60 */
+  8      ,  18, /* = -  61 */
+  8      ,  20, /* > -  62 */
+  7      ,  60, /* ? -  63 */
+  7      ,  62, /* @ -  64 */
+ 14      ,   2, /* A -  65 */
+ 14      ,   9, /* B -  66 */
+ 14      ,  10, /* C -  67 */
+ 14      ,  26, /* D -  68 */
+ 14      ,  33, /* E -  69 */
+ 14      ,  35, /* F -  70 */
+ 14      ,  37, /* G -  71 */
+ 14      ,  44, /* H -  72 */
+ 14      ,  50, /* I -  73 */
+ 14      ,  53, /* J -  74 */
+ 14      ,  54, /* K -  75 */
+ 14      ,  72, /* L -  76 */
+ 14      ,  81, /* M -  77 */
+ 14      , 112, /* N -  78 */
+ 14      , 124, /* O -  79 */
+ 14      , 126, /* P -  80 */
+ 14      , 137, /* Q -  81 */
+ 14      , 138, /* R -  82 */
+ 14      , 145, /* S -  83 */
+ 14      , 153, /* T -  84 */
+ 14      , 159, /* U -  85 */
+ 14      , 162, /* V -  86 */
+ 14      , 164, /* W -  87 */
+ 14      , 166, /* X -  88 */
+ 14      , 167, /* Y -  89 */
+ 14      , 169, /* Z -  90 */
+  7      ,  63, /* [ -  91 */
+  7      ,  65, /* \ -  92 */
+  7      ,  66, /* ] -  93 */
+  7      ,  67, /* ^ -  94 */
+  7      ,  68, /* _ -  95 */
+  7      ,  72, /* ` -  96 */
+ 14      ,   2, /* a -  97 */
+ 14      ,   9, /* b -  98 */
+ 14      ,  10, /* c -  99 */
+ 14      ,  26, /* d - 100 */
+ 14      ,  33, /* e - 101 */
+ 14      ,  35, /* f - 102 */
+ 14      ,  37, /* g - 103 */
+ 14      ,  44, /* h - 104 */
+ 14      ,  50, /* i - 105 */
+ 14      ,  53, /* j - 106 */
+ 14      ,  54, /* k - 107 */
+ 14      ,  72, /* l - 108 */
+ 14      ,  81, /* m - 109 */
+ 14      , 112, /* n - 110 */
+ 14      , 124, /* o - 111 */
+ 14      , 126, /* p - 112 */
+ 14      , 137, /* q - 113 */
+ 14      , 138, /* r - 114 */
+ 14      , 145, /* s - 115 */
+ 14      , 153, /* t - 116 */
+ 14      , 159, /* u - 117 */
+ 14      , 162, /* v - 118 */
+ 14      , 164, /* w - 119 */
+ 14      , 166, /* x - 120 */
+ 14      , 167, /* y - 121 */
+ 14      , 169, /* z - 122 */
+  7      ,  74, /* { - 123 */
+  7      ,  76, /* | - 124 */
+  7      ,  78, /* } - 125 */
+  7      ,  80, /* ~ - 126 */
+  6      ,  29, /*  - 127 */
+  6      ,  30, /* € - 128 */
+  6      ,  31, /*  - 129 */
+  7      , 123, /* ‚ - 130 */
+ 14      ,  35, /* ƒ - 131 */
+  7      , 127, /* „ - 132 */
+ 10      ,  21, /* … - 133 */
+ 10      ,  15, /* † - 134 */
+ 10      ,  16, /* ‡ - 135 */
+  7      ,  67, /* ˆ - 136 */
+ 10      ,  22, /* ‰ - 137 */
+ 14      , 145, /* Š - 138 */
+  7      , 136, /* ‹ - 139 */
+ 14 + 16 , 124, /* Π- 140 */
+  6      ,  43, /*  - 141 */
+  6      ,  44, /* Ž - 142 */
+  6      ,  45, /*  - 143 */
+  6      ,  46, /*  - 144 */
+  7      , 121, /* ‘ - 145 */
+  7      , 122, /* ’ - 146 */
+  7      , 125, /* “ - 147 */
+  7      , 126, /* ” - 148 */
+ 10      ,  17, /* • - 149 */
+  6      , 137, /* – - 150 */
+  6      , 139, /* — - 151 */
+  7      ,  93, /* ˜ - 152 */
+ 14      , 156, /* ™ - 153 */
+ 14      , 145, /* š - 154 */
+  7      , 137, /* › - 155 */
+ 14 + 16 , 124, /* œ - 156 */
+  6      ,  59, /*  - 157 */
+  6      ,  60, /* ž - 158 */
+ 14      , 167, /* Ÿ - 159 */
+  7      ,   4, /*   - 160 */
+  7      ,  81, /* ¡ - 161 */
+ 10      ,   2, /* ¢ - 162 */
+ 10      ,   3, /* £ - 163 */
+ 10      ,   4, /* ¤ - 164 */
+ 10      ,   5, /* ¥ - 165 */
+  7      ,  82, /* ¦ - 166 */
+ 10      ,   6, /* § - 167 */
+  7      ,  83, /* ¨ - 168 */
+ 10      ,   7, /* © - 169 */
+ 14      ,   2, /* ª - 170 */
+  8      ,  24, /* « - 171 */
+ 10      ,   8, /* ¬ - 172 */
+  6      , 131, /* ­ - 173 */
+ 10      ,   9, /* ® - 174 */
+  7      ,  84, /* ¯ - 175 */
+ 10      ,  10, /* ° - 176 */
+  8      ,  23, /* ± - 177 */
+ 12      ,  51, /* ² - 178 */
+ 12      ,  70, /* ³ - 179 */
+  7      ,  85, /* ´ - 180 */
+ 10      ,  11, /* µ - 181 */
+ 10      ,  12, /* ¶ - 182 */
+ 10      ,  13, /* · - 183 */
+  7      ,  86, /* ¸ - 184 */
+ 12      ,  33, /* ¹ - 185 */
+ 14      , 124, /* º - 186 */
+  8      ,  26, /* » - 187 */
+ 12      ,  21, /* ¼ - 188 */
+ 12      ,  25, /* ½ - 189 */
+ 12      ,  29, /* ¾ - 190 */
+  7      ,  87, /* ¿ - 191 */
+ 14      ,   2, /* À - 192 */
+ 14      ,   2, /* Á - 193 */
+ 14      ,   2, /* Â - 194 */
+ 14      ,   2, /* Ã - 195 */
+ 14      ,   2, /* Ä - 196 */
+ 14      ,   2, /* Å - 197 */
+ 14 + 16 ,   2, /* Æ - 198 */
+ 14      ,  10, /* Ç - 199 */
+ 14      ,  33, /* È - 200 */
+ 14      ,  33, /* É - 201 */
+ 14      ,  33, /* Ê - 202 */
+ 14      ,  33, /* Ë - 203 */
+ 14      ,  50, /* Ì - 204 */
+ 14      ,  50, /* Í - 205 */
+ 14      ,  50, /* Î - 206 */
+ 14      ,  50, /* Ï - 207 */
+ 14      ,  26, /* Ð - 208 */
+ 14      , 112, /* Ñ - 209 */
+ 14      , 124, /* Ò - 210 */
+ 14      , 124, /* Ó - 211 */
+ 14      , 124, /* Ô - 212 */
+ 14      , 124, /* Õ - 213 */
+ 14      , 124, /* Ö - 214 */
+  8      ,  28, /* × - 215 */
+ 14      , 124, /* Ø - 216 */
+ 14      , 159, /* Ù - 217 */
+ 14      , 159, /* Ú - 218 */
+ 14      , 159, /* Û - 219 */
+ 14      , 159, /* Ü - 220 */
+ 14      , 167, /* Ý - 221 */
+ 14 + 32 , 153, /* Þ - 222 */
+ 14 + 48 , 145, /* ß - 223 */
+ 14      ,   2, /* à - 224 */
+ 14      ,   2, /* á - 225 */
+ 14      ,   2, /* â - 226 */
+ 14      ,   2, /* ã - 227 */
+ 14      ,   2, /* ä - 228 */
+ 14      ,   2, /* å - 229 */
+ 14 + 16 ,   2, /* æ - 230 */
+ 14      ,  10, /* ç - 231 */
+ 14      ,  33, /* è - 232 */
+ 14      ,  33, /* é - 233 */
+ 14      ,  33, /* ê - 234 */
+ 14      ,  33, /* ë - 235 */
+ 14      ,  50, /* ì - 236 */
+ 14      ,  50, /* í - 237 */
+ 14      ,  50, /* î - 238 */
+ 14      ,  50, /* ï - 239 */
+ 14      ,  26, /* ð - 240 */
+ 14      , 112, /* ñ - 241 */
+ 14      , 124, /* ò - 242 */
+ 14      , 124, /* ó - 243 */
+ 14      , 124, /* ô - 244 */
+ 14      , 124, /* õ - 245 */
+ 14      , 124, /* ö - 246 */
+  8      ,  29, /* ÷ - 247 */
+ 14      , 124, /* ø - 248 */
+ 14      , 159, /* ù - 249 */
+ 14      , 159, /* ú - 250 */
+ 14      , 159, /* û - 251 */
+ 14      , 159, /* ü - 252 */
+ 14      , 167, /* ý - 253 */
+ 14 + 32 , 153, /* þ - 254 */
+ 14      , 167  /* ÿ - 255 */ };
 
+static const unsigned char LCM_Unicode_LUT_2[] = { 33, 44, 145 };
+
+#define LCM_Diacritic_Start 131
+
+static const unsigned char LCM_Diacritic_LUT[] = { 
+123,  /* ƒ - 131 */
+  2,  /* „ - 132 */
+  2,  /* … - 133 */
+  2,  /* † - 134 */
+  2,  /* ‡ - 135 */
+  3,  /* ˆ - 136 */
+  2,  /* ‰ - 137 */
+ 20,  /* Š - 138 */
+  2,  /* ‹ - 139 */
+  2,  /* Π- 140 */
+  2,  /*  - 141 */
+  2,  /* Ž - 142 */
+  2,  /*  - 143 */
+  2,  /*  - 144 */
+  2,  /* ‘ - 145 */
+  2,  /* ’ - 146 */
+  2,  /* “ - 147 */
+  2,  /* ” - 148 */
+  2,  /* • - 149 */
+  2,  /* – - 150 */
+  2,  /* — - 151 */
+  2,  /* ˜ - 152 */
+  2,  /* ™ - 153 */
+ 20,  /* š - 154 */
+  2,  /* › - 155 */
+  2,  /* œ - 156 */
+  2,  /*  - 157 */
+  2,  /* ž - 158 */
+ 19,  /* Ÿ - 159 */
+  2,  /*   - 160 */
+  2,  /* ¡ - 161 */
+  2,  /* ¢ - 162 */
+  2,  /* £ - 163 */
+  2,  /* ¤ - 164 */
+  2,  /* ¥ - 165 */
+  2,  /* ¦ - 166 */
+  2,  /* § - 167 */
+  2,  /* ¨ - 168 */
+  2,  /* © - 169 */
+  3,  /* ª - 170 */
+  2,  /* « - 171 */
+  2,  /* ¬ - 172 */
+  2,  /* ­ - 173 */
+  2,  /* ® - 174 */
+  2,  /* ¯ - 175 */
+  2,  /* ° - 176 */
+  2,  /* ± - 177 */
+  2,  /* ² - 178 */
+  2,  /* ³ - 179 */
+  2,  /* ´ - 180 */
+  2,  /* µ - 181 */
+  2,  /* ¶ - 182 */
+  2,  /* · - 183 */
+  2,  /* ¸ - 184 */
+  2,  /* ¹ - 185 */
+  3,  /* º - 186 */
+  2,  /* » - 187 */
+  2,  /* ¼ - 188 */
+  2,  /* ½ - 189 */
+  2,  /* ¾ - 190 */
+  2,  /* ¿ - 191 */
+ 15,  /* À - 192 */
+ 14,  /* Á - 193 */
+ 18,  /* Â - 194 */
+ 25,  /* Ã - 195 */
+ 19,  /* Ä - 196 */
+ 26,  /* Å - 197 */
+  2,  /* Æ - 198 */
+ 28,  /* Ç - 199 */
+ 15,  /* È - 200 */
+ 14,  /* É - 201 */
+ 18,  /* Ê - 202 */
+ 19,  /* Ë - 203 */
+ 15,  /* Ì - 204 */
+ 14,  /* Í - 205 */
+ 18,  /* Î - 206 */
+ 19,  /* Ï - 207 */
+104,  /* Ð - 208 */
+ 25,  /* Ñ - 209 */
+ 15,  /* Ò - 210 */
+ 14,  /* Ó - 211 */
+ 18,  /* Ô - 212 */
+ 25,  /* Õ - 213 */
+ 19,  /* Ö - 214 */
+  2,  /* × - 215 */
+ 33,  /* Ø - 216 */
+ 15,  /* Ù - 217 */
+ 14,  /* Ú - 218 */
+ 18,  /* Û - 219 */
+ 19,  /* Ü - 220 */
+ 14,  /* Ý - 221 */
+  2,  /* Þ - 222 */
+  2,  /* ß - 223 */
+ 15,  /* à - 224 */
+ 14,  /* á - 225 */
+ 18,  /* â - 226 */
+ 25,  /* ã - 227 */
+ 19,  /* ä - 228 */
+ 26,  /* å - 229 */
+  2,  /* æ - 230 */
+ 28,  /* ç - 231 */
+ 15,  /* è - 232 */
+ 14,  /* é - 233 */
+ 18,  /* ê - 234 */
+ 19,  /* ë - 235 */
+ 15,  /* ì - 236 */
+ 14,  /* í - 237 */
+ 18,  /* î - 238 */
+ 19,  /* ï - 239 */
+104,  /* ð - 240 */
+ 25,  /* ñ - 241 */
+ 15,  /* ò - 242 */
+ 14,  /* ó - 243 */
+ 18,  /* ô - 244 */
+ 25,  /* õ - 245 */
+ 19,  /* ö - 246 */
+  2,  /* ÷ - 247 */
+ 33,  /* ø - 248 */
+ 15,  /* ù - 249 */
+ 14,  /* ú - 250 */
+ 18,  /* û - 251 */
+ 19,  /* ü - 252 */
+ 14,  /* ý - 253 */
+  2,  /* þ - 254 */
+ 19,  /* ÿ - 255 */
+} ;
+
+/*************************************************************************
+ * Convert a string, or generate a sort key from it.
+ *
+ * If (mapflags & LCMAP_SORTKEY), the function will generate
+ * a sort key for the source string.  Else, it will convert it
+ * accordingly to the flags LCMAP_UPPERCASE, LCMAP_LOWERCASE,...
+ *
+ * RETURNS
+ *    Error : (destination buffer too small) 0.
+ *    Success : length of the result string.
+ *
+ * REMARKS
+ *    If called with scrlen = -1, the function will compute the length
+ *      of the 0-terminated string strsrc by itself.      
+ */
+ INT32 WINAPI LCMapString32A(
+	LCID lcid /* locale identifier created with MAKELCID; 
+		     LOCALE_SYSTEM_DEFAULT and LOCALE_USER_DEFAULT are predefined
+		     values. */,
+	DWORD mapflags /* flags */,
+	LPCSTR srcstr  /* source buffer */,
+	INT32 srclen   /* source length */,
+	LPSTR dststr   /* destination buffer */,
+	INT32 dstlen   /* destination buffer length */) 
+{
+  int i;
+ 
+  TRACE(string,"(0x%04lx,0x%08lx,%s,%d,%p,%d)\n",
+	lcid,mapflags,srcstr,srclen,dststr,dstlen);
+
+  if ((dststr==NULL) || (srcstr==NULL))
+    return 0;
+  if (srclen==-1) 
+    srclen = lstrlen32A(srcstr);
+
+  if (mapflags & ~ ( LCMAP_UPPERCASE | LCMAP_LOWERCASE | LCMAP_SORTKEY |
+		     SORT_STRINGSORT) )
+  {
+    FIXME(string,"(0x%04lx,0x%08lx,%p,%d,%p,%d): "
+	  "unimplemented flags: 0x%08lx\n",
+	  lcid,mapflags,srcstr,srclen,dststr,dstlen,mapflags);
+  }
+  
+  if ( !(mapflags & LCMAP_SORTKEY) )
+  {
+    int (*f)(int)=identity; 
+
+    if (dstlen==0)
+      return srclen;  /* dstlen=0 means "do nothing but return required length" */
+    if (dstlen<srclen)
+      return 0;       /* it's an error */
+    if (mapflags & LCMAP_UPPERCASE)
+      f = toupper;
+    else if (mapflags & LCMAP_LOWERCASE)
+      f = tolower;
+    for (i=0; i < srclen; i++)
+      dststr[i] = (CHAR) f(srcstr[i]);
+    return srclen;
+  }
+
+  /* else ... (mapflags & LCMAP_SORTKEY)  */
+  {
+    int unicode_len=0;
+    int case_len=0;
+    int diacritic_len=0;
+    char *case_component;
+    char *diacritic_component;
+    int room,count;
+    int flag_stringsort = mapflags & SORT_STRINGSORT;
+
+    /* compute how much room we will need */
+    for (i=0;i<srclen;i++)
+    {
+      int ofs;
+      if ((srcstr[i]!='\0') && (flag_stringsort || !is_punctuation(srcstr[i])))
+      {
+	unicode_len++;
+	if(((unsigned char)srcstr[i])<=31)
+	{
+	  FIXME(string," control characters in argument string\n");
+	  return 0;
+	}
+	if ( LCM_Unicode_LUT[2*((unsigned char)srcstr[i]-32)] & ~15 )
+	  unicode_len++;             /* double letter */
+      }
+	  
+      if (isupper(srcstr[i]))
+	case_len=unicode_len; 
+
+      ofs = (unsigned char)srcstr[i] - LCM_Diacritic_Start;
+      if ((ofs>=0) && (LCM_Diacritic_LUT[ofs]!=2))
+	diacritic_len=unicode_len;
+    }
+
+    room =  2 * unicode_len         /* "unicode" component */
+      +     diacritic_len           /* "diacritic" component */
+      +     case_len                /* "case" component */
+      +     4                       /* four '\1' separators */
+      +     1  ;                    /* terminal '\0' */
+    if (dstlen==0)
+      return room;      
+    else if (dstlen<room)
+      return 0;   
+
+    /* locate each component, write separators */
+    diacritic_component = dststr + 2*unicode_len ;
+    *diacritic_component++ = '\1'; 
+
+    case_component = diacritic_component + diacritic_len ;
+    *case_component++ = '\1'; 
+
+    /* read source string char by char, write 
+       corresponding weight in each component. */
+    for (i=0,count=0;count<unicode_len;i++)
+    {
+      unsigned char c=srcstr[i];
+      if ( (c!='\0') && (flag_stringsort || !is_punctuation(c)) )
+      {
+	int type,longcode;
+	int LUT_offset = 2*(c-32);
+	type = LCM_Unicode_LUT[LUT_offset];
+	longcode = type >> 4;
+	type &= 15;
+	dststr[2*count] = type;
+	dststr[2*count+1] = LCM_Unicode_LUT[LUT_offset+1];  
+	if (longcode)
+	{
+	  if (count<case_len)
+	    case_component[count] = ( isupper(srcstr[i]) ? 18 : 2 ) ;
+	  if (count<diacritic_len)
+	    diacritic_component[count] = 2; /* assumption: a double letter
+					       is never accented */
+	  count++;
+
+	  dststr[2*count] = type;
+	  dststr[2*count+1] = *(LCM_Unicode_LUT_2 - 1 + longcode); 
+	  /* 16 in the first column of LCM_Unicode_LUT  -->  longcode = 1 
+	     32 in the first column of LCM_Unicode_LUT  -->  longcode = 2 
+	     48 in the first column of LCM_Unicode_LUT  -->  longcode = 3 */
+	}
+
+	if (count<case_len)
+	  case_component[count] = ( isupper(srcstr[i]) ? 18 : 2 ) ;
+	if (count<diacritic_len)
+	{
+	  int ofs = (unsigned char)srcstr[i] - LCM_Diacritic_Start;
+	  diacritic_component[count] = (ofs>=0 ? LCM_Diacritic_LUT[ofs] : 2);
+	}
+	count++;
+      }
+    }
+    dststr[room-3] = dststr[room-2] = '\1';
+    dststr[room-1] = '\0';
+    return room;
+  }
+}
+ 
 INT32 WINAPI LCMapString32W(
 	LCID lcid,DWORD mapflags,LPCWSTR srcstr,INT32 srclen,LPWSTR dststr,
-	INT32 dstlen
-) {
-	int	i,len;
+	INT32 dstlen)
+{
+  int i;
+ 
+  TRACE(string,"(0x%04lx,0x%08lx,%p,%d,%p,%d)\n",
+	lcid,mapflags,srcstr,srclen,dststr,dstlen);
 
-	TRACE(string,"(0x%04lx,0x%08lx,%p,%d,%p,%d)\n",
-		lcid,mapflags,srcstr,srclen,dststr,dstlen
-	);
-	if (!dstlen || !dststr) {
-		dststr = (LPWSTR)srcstr;
-	}
-	if (!srclen) srclen = lstrlen32W(srcstr);
-	if (!dstlen) dstlen = lstrlen32W(dststr);
-	len = dstlen;
-	if (srclen < len)
-		len = srclen;
-	if (mapflags & LCMAP_LOWERCASE) {
-		for (i=0;i<len;i++)
-			dststr[i]=tolower(srcstr[i]);
-		mapflags &= ~LCMAP_LOWERCASE;
-	}
-	if (mapflags & LCMAP_UPPERCASE) {
-		for (i=0;i<len;i++)
-			dststr[i]=toupper(srcstr[i]);
-		mapflags &= ~LCMAP_UPPERCASE;
-	}
-	if (mapflags)
-	  {
-	    FIXME(ole,"(0x%04lx,0x%08lx,%p,%d,%p,%d): "
-		  "unimplemented flags: 0x%08lx\n",
-		  lcid,mapflags,srcstr,srclen,dststr,dstlen,mapflags);
-	  }
-	return len;
+  if ((dststr==NULL) || (srcstr==NULL))
+    return 0;
+  if (srclen==-1) 
+    srclen = lstrlen32W(srcstr);
+  if (mapflags & LCMAP_SORTKEY) 
+  {
+    FIXME(string,"(0x%04lx,0x%08lx,%p,%d,%p,%d): "
+	  "unimplemented flags: 0x%08lx\n",
+	  lcid,mapflags,srcstr,srclen,dststr,dstlen,mapflags);
+    return 0;
+  }
+  else
+  {
+    int (*f)(int)=identity; 
+
+    if (dstlen==0)
+      return srclen;  
+    if (dstlen<srclen)
+      return 0;       
+    if (mapflags & LCMAP_UPPERCASE)
+      f = toupper;
+    else if (mapflags & LCMAP_LOWERCASE)
+      f = tolower;
+    for (i=0; i < srclen; i++)
+      dststr[i] = (WCHAR) f(srcstr[i]);
+    return srclen;
+  }
 }
 
+
 /*****************************************************************
  *
  *  OLE_GetFormatA() [internal]
@@ -2626,12 +3137,11 @@
 
 /**************************************************************************
  *              GetNumberFormat32A	(KERNEL32.355)
+ * NOTE: type of lpFormat should be CONST NUMBERFORMAT 
  */
 INT32 WINAPI GetNumberFormat32A(LCID locale, DWORD dwflags,
 			       LPCSTR lpvalue,  char *lpFormat,
 			       LPSTR lpNumberStr, int cchNumber)
-/* NOTE: type of lpFormat should be CONST NUMBERFORMAT */
-
 {
  int n;
 
@@ -2704,7 +3214,6 @@
 /* ****************************************************************
  *  GetTimeFormat32W()  [KERNEL32.423] Makes a Unicode string of the time
  * 
-
  *
  */
 
@@ -2736,39 +3245,40 @@
       realformat = format;
    } else if (locale) {
       /* allocate memory */
+      retval = ERROR_INSUFFICIENT_BUFFER;
       fmt_buf = malloc((fmt_buf_size+=7) * sizeof(WCHAR));
-      if (!fmt_buf) {
-	 SetLastError(ERROR_INSUFFICIENT_BUFFER);
-	 WARN(ole, "could not allocate %d chars of memory\n", fmt_buf_size); 
-	 return 0;
-      };
+      if (!fmt_buf)
+	goto out_nomem;
+
       while(!GetLocaleInfo32W(locale, LOCALE_STIMEFORMAT,
 			      fmt_buf, fmt_buf_size)) {
-	 fmt_buf = realloc(fmt_buf, 
+	retval = ERROR_OUTOFMEMORY;
+	fmt_buf = realloc(fmt_buf, 
 			   (fmt_buf_size += 10) * sizeof(WCHAR));
-	 if (!fmt_buf) {
-	    SetLastError(ERROR_OUTOFMEMORY);
-	    WARN(ole, "could not allocate %d chars of memory\n", fmt_buf_size); 
-	    return 0;
-	 };
-      };
+	if (!fmt_buf)
+		goto out_nomem;
+      }
       realformat = fmt_buf;
    } else {
       FIXME(ole,  "caller gave no locale,  no format;  what should we do?\n");
       SetLastError(ERROR_BAD_FORMAT);
-   };
-   if (!locale) {
+   }
+   if (!locale)
       locale = GetSystemDefaultLCID();
-}
 
    realtime = xtime;
    if (!realtime) {
       realtime = &t;
       GetSystemTime(realtime);
-   };
-
+   }
 
    retval = OLE_GetFormatW(locale, flags, realtime, realformat, timestr,  timelen);
-   if (fmt_buf) free(fmt_buf);
+   if (fmt_buf)
+	free(fmt_buf);
    return retval;
+
+out_nomem:
+	SetLastError(retval);
+	WARN(ole, "could not allocate %d chars of memory\n", fmt_buf_size); 
+	return 0;
 }
diff --git a/ole/storage.c b/ole/storage.c
index 04dfd3f..768549b 100644
--- a/ole/storage.c
+++ b/ole/storage.c
@@ -7,7 +7,6 @@
  * Copyright 1998 Marcus Meissner
  */
 
-#include <stdio.h>
 #include <assert.h>
 #include <time.h>
 #include <string.h>
@@ -1504,27 +1503,27 @@
 	OFSTRUCT	ofs;
 	BYTE		magic[24];
 
-	TRACE(ole,"(\'%s\')",fn);
+	TRACE(ole,"(\'%s\')\n",fn);
 	hf = OpenFile32(fn,&ofs,OF_SHARE_DENY_NONE);
 	if (hf==HFILE_ERROR32)
 		return STG_E_FILENOTFOUND;
 	if (24!=_lread32(hf,magic,24)) {
-		fprintf(stderr," too short\n");
+		WARN(ole," too short\n");
 		_lclose32(hf);
 		return S_FALSE;
 	}
 	if (!memcmp(magic,STORAGE_magic,8)) {
-		fprintf(stderr," -> YES\n");
+		WARN(ole," -> YES\n");
 		_lclose32(hf);
 		return S_OK;
 	}
 	if (!memcmp(magic,STORAGE_notmagic,8)) {
-		fprintf(stderr," -> NO\n");
+		WARN(ole," -> NO\n");
 		_lclose32(hf);
 		return S_FALSE;
 	}
 	if (!memcmp(magic,STORAGE_oldmagic,8)) {
-		fprintf(stderr," -> old format\n");
+		WARN(ole," -> old format\n");
 		_lclose32(hf);
 		return STG_E_OLDFORMAT;
 	}
@@ -1560,7 +1559,7 @@
 	_create_istorage16(ppstgOpen);
 	hf = CreateFile32A(pwcsName,GENERIC_READ,0,NULL,0,0,0);
 	if (hf==INVALID_HANDLE_VALUE32) {
-		fprintf(stderr,"couldn't open file for storage\n");
+		WARN(ole,"Couldn't open file for storage\n");
 		return E_FAIL;
 	}
 	lpstg = (LPSTORAGE16)PTR_SEG_TO_LIN(*ppstgOpen);
diff --git a/programs/clock/ChangeLog b/programs/clock/ChangeLog
index 5d9c791..1162765 100644
--- a/programs/clock/ChangeLog
+++ b/programs/clock/ChangeLog
@@ -1,13 +1,27 @@
+Thu May 28 20:42:13 1998  Marcel Baur <mbaur@g26.ethz.ch>
+       * [language.c]
+         UpdateWindowCaption(), locale and date
+         UpdateMenuCheckmarks()
+         General code cleanup (removed obsolete printf's)
+         
+Thu May 28 20:10:36 1998  Mikolaj Zalewski <mikolajz@ids.edu.pl>
+       * [main.c] [winclock.h]
+         Fixed destroyed background
+
+Mon May 25 14:30:32 1998  Henrik Olsen <henrik@iaeste.dk>
+       * [Da.rc]
+         Added Danish language support.
+
 Wed Mar 11 23:10:37 1998  Karl Backström <karl_b@geocities.com>
        * [main.c]
-	 Started with the digital clock.
+         Started with the digital clock.
 
 Tue Feb 24 23:26:40 1998  Karl Backström <karl_b@geocities.com>
        * [language.c] [language.h] NEW
-	 Moved language stuff here.
+         Moved language stuff here.
        * [main.c] [winclock.c] [clock.rc]
-	 Made the clock appear in the center.
-	 Fixed problems with menues.
+         Made the clock appear in the center.
+         Fixed problems with menues.
 
 Mon Feb 23 19:59:27 1998  Marcel Baur <mbaur@g26.ethz.ch>
        * [ChangeLog] [De.rc] [En.rc] [Sw.rc] [clock.rc]
@@ -15,4 +29,5 @@
          [README] [TODO]
          [main.c] [main.h] [winclock.c] [winclock.h]
 
-	 Originals by Marcel Baur
+         Originals by Marcel Baur
+
diff --git a/programs/clock/Da.rc b/programs/clock/Da.rc
new file mode 100644
index 0000000..e53c30c
--- /dev/null
+++ b/programs/clock/Da.rc
@@ -0,0 +1,33 @@
+/*
+ * Clock (Danish resources)
+ *
+ * Copyright 1998 Henrik Olsen <henrik@iaeste.dk>
+ */
+
+#define LANGUAGE_ID                  Da
+#define LANGUAGE_NUMBER              6
+#define LANGUAGE_MENU_ITEM           "&Dansk"
+
+/* Menu */
+
+#define MENU_PROPERTIES              "&Instillinger"
+#define MENU_ANALOG                  "&Analog"
+#define MENU_DIGITAL                 "&Digital"
+#define MENU_FONT                    "&Skrifttype..."
+#define MENU_WITHOUT_TITLE           "Skjul Titel&linje"
+#define MENU_ON_TOP                  "&Altid øverst"
+#define MENU_SECONDS                 "Se&kunder"
+#define MENU_DATE                    "Da&to"
+
+#define MENU_LANGUAGE                "S&prog"
+
+#define MENU_INFO                    "Inf&o..."
+#define MENU_INFO_LICENSE            "&Licens"
+#define MENU_INFO_NO_WARRANTY        "&NO WARRANTY"
+#define MENU_INFO_ABOUT_WINE         "&Om Ur..."
+
+/* Strings */
+#define STRING_CLOCK                 "Ur"
+
+
+#include "clock.rc"
diff --git a/programs/clock/Makefile.in b/programs/clock/Makefile.in
index 06b37d1..fdbd2cc 100644
--- a/programs/clock/Makefile.in
+++ b/programs/clock/Makefile.in
@@ -8,7 +8,7 @@
 ALL_LIBS  = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LIBS)
 RCFLAGS   = -w32 -h
 
-LANGUAGES   = En De Sw
+LANGUAGES   = En Da De Sw
 LICENSELANG = En
 
 MOSTSRCS = \
@@ -34,6 +34,23 @@
 
 @MAKE_RULES@
 
+# Rules for using old resource compiler
+.rc.c:
+	echo "#include \"windows.h\"" >$*-tmp.c
+	echo WINDOWS_H_ENDS_HERE >>$*-tmp.c
+	cat $< >>$*-tmp.c
+	$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P $*-tmp.c | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | $(WINERC) $(RCFLAGS) -c -o $* -p $*
+	$(RM) $*-tmp.c
+.rc.h:
+	echo "#include \"windows.h\"" >$*-tmp.c
+	echo WINDOWS_H_ENDS_HERE >>$*-tmp.c
+	cat $< >>$*-tmp.c
+	$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P $*-tmp.c | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | $(WINERC) $(RCFLAGS) -c -o $* -p $*
+	$(RM) $*-tmp.c
+clean::
+	$(RM) $(RC_SRCS:.rc=.c)
+
+
 clock: $(MOSTOBJS) $(STRINGOBJS)
 	$(CC) -o clock $(MOSTOBJS) $(LDOPTIONS) $(ALL_LIBS) $(STRINGOBJS)
 
diff --git a/programs/clock/language.c b/programs/clock/language.c
index c5683d6..aa920a7 100644
--- a/programs/clock/language.c
+++ b/programs/clock/language.c
@@ -9,12 +9,73 @@
 #include "windows.h"
 #include "main.h"
 #include "language.h"
+#include "winnls.h"
 #ifdef WINELIB
 #include "options.h"
 #endif
 
 CHAR STRING_MENU_Xx[]      = "MENU_Xx";
 
+VOID LANGUAGE_UpdateMenuCheckmarks(VOID) {
+
+    if(Globals.bAnalog == TRUE) {
+    
+        /* analog clock */
+        
+        CheckMenuItem(Globals.hPropertiesMenu, CL_ANALOG, \
+                       MF_BYCOMMAND | MF_CHECKED);
+        CheckMenuItem(Globals.hPropertiesMenu, CL_DIGITAL, \
+                       MF_BYCOMMAND | MF_UNCHECKED);
+        EnableMenuItem(Globals.hPropertiesMenu, CL_FONT, \
+                       MF_BYCOMMAND | MF_GRAYED);
+    }
+        else 
+    {
+    
+        /* digital clock */
+        
+        CheckMenuItem(Globals.hPropertiesMenu, CL_ANALOG, \
+                       MF_BYCOMMAND | MF_UNCHECKED);
+        CheckMenuItem(Globals.hPropertiesMenu, CL_DIGITAL, \
+                       MF_BYCOMMAND | MF_CHECKED);
+    }
+    
+    CheckMenuItem(Globals.hPropertiesMenu, CL_WITHOUT_TITLE, MF_BYCOMMAND | \
+                 (Globals.bWithoutTitle ? MF_CHECKED : MF_UNCHECKED));
+    CheckMenuItem(Globals.hPropertiesMenu, CL_ON_TOP, MF_BYCOMMAND | \
+                 (Globals.bAlwaysOnTop ? MF_CHECKED : MF_UNCHECKED));
+    CheckMenuItem(Globals.hPropertiesMenu, CL_SECONDS, MF_BYCOMMAND | \
+                 (Globals.bSeconds ? MF_CHECKED : MF_UNCHECKED));
+    CheckMenuItem(Globals.hPropertiesMenu, CL_DATE, MF_BYCOMMAND | \
+                 (Globals.bDate ? MF_CHECKED : MF_UNCHECKED));
+}
+
+VOID LANGUAGE_UpdateWindowCaption(VOID) {
+
+  CHAR szCaption[MAX_STRING_LEN];
+  CHAR szDate[MAX_STRING_LEN];
+  
+  LPSTR date = szDate;
+  
+  SYSTEMTIME st;
+  LPSYSTEMTIME lpst = &st;
+
+  GetLocalTime(&st);
+  GetDateFormat(LOCALE_USER_DEFAULT, LOCALE_SLONGDATE, lpst, NULL, date,
+                MAX_STRING_LEN);
+
+  /* Set frame caption */
+  LoadString(Globals.hInstance, IDS_CLOCK, szCaption, sizeof(szCaption));
+  if (Globals.bDate) {
+     lstrcat(szCaption, " - ");
+     lstrcat(szCaption, szDate);
+  }
+  SetWindowText(Globals.hMainWnd, szCaption);
+
+}
+
+
+
 static BOOL LANGUAGE_LoadStringOther(UINT num, UINT ids, LPSTR str, UINT len)
 {
   ids -= Globals.wStringTableOffset;
@@ -29,18 +90,18 @@
 
   for (i = 0; i <= MAX_LANGUAGE_NUMBER; i++)
     if (LANGUAGE_LoadStringOther(i, IDS_LANGUAGE_ID, newlang, sizeof(newlang)) &&
-	!lstrcmp(lang, newlang))
+        !lstrcmp(lang, newlang))
       {
         LANGUAGE_SelectByNumber(i);
-	return;
+        return;
       }
 
   /* Fallback */
     for (i = 0; i <= MAX_LANGUAGE_NUMBER; i++)
     if (LANGUAGE_LoadStringOther(i, IDS_LANGUAGE_ID, newlang, sizeof(newlang)))
       {
-	LANGUAGE_SelectByNumber(i);
-	return;
+        LANGUAGE_SelectByNumber(i);
+        return;
       }
 
   MessageBox(Globals.hMainWnd, "No language found", "FATAL ERROR", MB_OK);
@@ -51,7 +112,7 @@
 {
   INT    i;
   CHAR   lang[3];
-  CHAR   caption[MAX_STRING_LEN];
+
   CHAR   item[MAX_STRING_LEN];
   HMENU  hMainMenu;
 
@@ -62,9 +123,7 @@
   LoadString(Globals.hInstance, IDS_LANGUAGE_ID, lang, sizeof(lang));
   Globals.lpszLanguage = lang;
 
-  /* Set frame caption */
-  LoadString(Globals.hInstance, IDS_CLOCK, caption, sizeof(caption));
-  SetWindowText(Globals.hMainWnd, caption);
+  LANGUAGE_UpdateWindowCaption();
 
   /* Change Resource names */
   lstrcpyn(STRING_MENU_Xx    + sizeof(STRING_MENU_Xx)    - 3, lang, 3);
@@ -72,8 +131,8 @@
   /* Create menu */
   hMainMenu = LoadMenu(Globals.hInstance, STRING_MENU_Xx);
     Globals.hPropertiesMenu     = GetSubMenu(hMainMenu, 0);
-    Globals.hLanguageMenu 	= GetSubMenu(hMainMenu, 1);
-    Globals.hInfoMenu     	= GetSubMenu(hMainMenu, 2);
+    Globals.hLanguageMenu       = GetSubMenu(hMainMenu, 1);
+    Globals.hInfoMenu           = GetSubMenu(hMainMenu, 2);
 
   /* Remove dummy item */
   RemoveMenu(Globals.hLanguageMenu, 0, MF_BYPOSITION);
@@ -81,7 +140,7 @@
   for (i = 0; i <= MAX_LANGUAGE_NUMBER; i++)
     if (LANGUAGE_LoadStringOther(i, IDS_LANGUAGE_MENU_ITEM, item, sizeof(item)))
       AppendMenu(Globals.hLanguageMenu, MF_STRING | MF_BYCOMMAND,
-		 CL_FIRST_LANGUAGE + i, item);
+                 CL_FIRST_LANGUAGE + i, item);
 
   SetMenu(Globals.hMainWnd, hMainMenu);
 
@@ -93,32 +152,11 @@
   /* Update system menus */
   for (i = 0; Languages[i].name && lstrcmp(lang, Languages[i].name);) i++;
   if (Languages[i].name) Options.language = i;
-
 #endif
 
-/* Specific for clock */
-if(Globals.bAnalog == TRUE) {
-	CheckMenuItem(Globals.hPropertiesMenu, CL_ANALOG, \
-                       MF_BYCOMMAND | MF_CHECKED);
-        CheckMenuItem(Globals.hPropertiesMenu, CL_DIGITAL, \
-                       MF_BYCOMMAND | MF_UNCHECKED);
-	EnableMenuItem(Globals.hPropertiesMenu, CL_FONT, \
-                       MF_BYCOMMAND | MF_GRAYED);
-}
-else {
-	CheckMenuItem(Globals.hPropertiesMenu, CL_ANALOG, \
-                       MF_BYCOMMAND | MF_UNCHECKED);
-        CheckMenuItem(Globals.hPropertiesMenu, CL_DIGITAL, \
-                       MF_BYCOMMAND | MF_CHECKED);
-}
-	CheckMenuItem(Globals.hPropertiesMenu, CL_WITHOUT_TITLE, MF_BYCOMMAND | \
-	                     (Globals.bWithoutTitle ? MF_CHECKED : MF_UNCHECKED));
-	CheckMenuItem(Globals.hPropertiesMenu, CL_ON_TOP, MF_BYCOMMAND | \
-	                     (Globals.bAlwaysOnTop ? MF_CHECKED : MF_UNCHECKED));
-	CheckMenuItem(Globals.hPropertiesMenu, CL_SECONDS, MF_BYCOMMAND | \
-	                     (Globals.bSeconds ? MF_CHECKED : MF_UNCHECKED));
-	CheckMenuItem(Globals.hPropertiesMenu, CL_DATE, MF_BYCOMMAND | \
-	                     (Globals.bDate ? MF_CHECKED : MF_UNCHECKED));
+   /* specific for Clock: */
+
+   LANGUAGE_UpdateMenuCheckmarks();
 }
 
 VOID LANGUAGE_DefaultHandle(WPARAM wParam)
@@ -130,20 +168,19 @@
 
 VOID LANGUAGE_Init(VOID)
 {
+  CHAR szBuffer[MAX_PATHNAME_LEN];
+
   #ifdef WINELIB
    Globals.lpszLanguage = Languages[Options.language].name;
   #endif
-//  #else
-  printf("Globals.lpszLanguage == %s\n", Globals.lpszLanguage);
+  
   if (Globals.lpszLanguage == "En") {
-    CHAR buffer[MAX_PATHNAME_LEN], *p;
-    printf("Muu\n");
-    PROFILE_GetWineIniString("programs", "language", "En", 
-                             buffer, sizeof(buffer));
-  Globals.lpszLanguage = p = LocalLock(LocalAlloc(LMEM_FIXED, lstrlen(buffer)));
-  hmemcpy(p, buffer, 1 + lstrlen(buffer)); }
-//  #endif
-//  if (!Globals.lpszLanguage) Globals.lpszLanguage = "En";
+        PROFILE_GetWineIniString("programs", "language", "En", szBuffer, 
+                                  sizeof(szBuffer));       
+        Globals.lpszLanguage = LocalLock(LocalAlloc(LMEM_FIXED, lstrlen(szBuffer)));
+
+        hmemcpy(Globals.lpszLanguage, szBuffer, 1+lstrlen(szBuffer)); 
+  }
 }
 
 /* Local Variables:    */
diff --git a/programs/clock/language.h b/programs/clock/language.h
index 27d5c48..36331af 100644
--- a/programs/clock/language.h
+++ b/programs/clock/language.h
@@ -5,6 +5,8 @@
  * Copyright 1998 Karl Backström <karl_b@geocities.com>
  */
 
+VOID LANGUAGE_UpdateWindowCaption(VOID);
+VOID LANGUAGE_UpdateMenuCheckmarks(VOID);
 VOID LANGUAGE_SelectByNumber(UINT num);
 VOID LANGUAGE_SelectByName(LPCSTR lang);
 VOID LANGUAGE_DefaultHandle(WPARAM wParam);
diff --git a/programs/clock/main.c b/programs/clock/main.c
index 5d86501..d73558b 100644
--- a/programs/clock/main.c
+++ b/programs/clock/main.c
@@ -38,92 +38,61 @@
 
 int CLOCK_MenuCommand (WPARAM wParam)
 {  
-   CHAR   caption[MAX_STRING_LEN];
    switch (wParam) {
      case CL_ANALOG: {
          Globals.bAnalog = TRUE;
-	 CheckMenuItem(Globals.hPropertiesMenu, CL_ANALOG, \
-	               MF_BYCOMMAND | MF_CHECKED);
-	 CheckMenuItem(Globals.hPropertiesMenu, CL_DIGITAL, \
-	               MF_BYCOMMAND | MF_UNCHECKED);
-	 EnableMenuItem(Globals.hPropertiesMenu, CL_FONT, \
-                       MF_BYCOMMAND | MF_GRAYED);
+         LANGUAGE_UpdateMenuCheckmarks();
 	 SendMessage(Globals.hMainWnd, WM_PAINT, 0, 0);
 	 break;	     
        } 
      case CL_DIGITAL: {
          Globals.bAnalog = FALSE;
-	 CheckMenuItem(Globals.hPropertiesMenu, CL_ANALOG, \
-	               MF_BYCOMMAND | MF_UNCHECKED);
-	 CheckMenuItem(Globals.hPropertiesMenu, CL_DIGITAL, \
-	               MF_BYCOMMAND | MF_CHECKED);
-	 EnableMenuItem(Globals.hPropertiesMenu, CL_FONT, \
-                       MF_BYCOMMAND | MF_ENABLED);
+         LANGUAGE_UpdateMenuCheckmarks();
 	 SendMessage(Globals.hMainWnd, WM_PAINT, 0, 0);
 	 break;	       
        }
-     case CL_FONT:
-	MAIN_FileChooseFont();
-       break;
-     case CL_WITHOUT_TITLE:
-       Globals.bWithoutTitle = !Globals.bWithoutTitle;
-       CheckMenuItem(Globals.hPropertiesMenu, CL_WITHOUT_TITLE, MF_BYCOMMAND | \
-                     (Globals.bWithoutTitle ? MF_CHECKED : MF_UNCHECKED));
-	SetMenu(Globals.hMainWnd, NULL);
-  	SetWindowText(Globals.hMainWnd, NULL);
-    	UpdateWindow (Globals.hMainWnd);
-        printf("NO TITLE:");
-       break;
-     case CL_ON_TOP:
-       Globals.bAlwaysOnTop = !Globals.bAlwaysOnTop;
-       CheckMenuItem(Globals.hPropertiesMenu, CL_ON_TOP, MF_BYCOMMAND | \
-                     (Globals.bAlwaysOnTop ? MF_CHECKED : MF_UNCHECKED));
-       break;
-     case CL_SECONDS:
-       Globals.bSeconds = !Globals.bSeconds;
-       CheckMenuItem(Globals.hPropertiesMenu, CL_SECONDS, MF_BYCOMMAND | \
-                     (Globals.bSeconds ? MF_CHECKED : MF_UNCHECKED));
-       SendMessage(Globals.hMainWnd, WM_PAINT, 0, 0);
-       break;
-     case CL_DATE:
-       Globals.bDate = !Globals.bDate;
-       CheckMenuItem(Globals.hPropertiesMenu, CL_DATE, MF_BYCOMMAND | \
-                     (Globals.bDate ? MF_CHECKED : MF_UNCHECKED));
-       LoadString(Globals.hInstance, IDS_CLOCK, caption, sizeof(caption));
-       if (Globals.bDate)
-       {
-	 if (Globals.bAnalog)
-	 {
-	   /* FIXME: Add date to caption */
-	   SetWindowText(Globals.hMainWnd, caption);
-	 }
-	 else
-	 {
-	 }
+     case CL_FONT: {
+         MAIN_FileChooseFont();
+         break;
        }
-       else 
-       {
-	 if (Globals.bAnalog)
-         {
-           SetWindowText(Globals.hMainWnd, caption);
-         }
-         else
-         {
-         }
+     case CL_WITHOUT_TITLE: {     
+         Globals.bWithoutTitle = !Globals.bWithoutTitle;
+         LANGUAGE_UpdateWindowCaption();
+         LANGUAGE_UpdateMenuCheckmarks();
+         break;
+       } 
+     case CL_ON_TOP: {
+         Globals.bAlwaysOnTop = !Globals.bAlwaysOnTop;
+         LANGUAGE_UpdateMenuCheckmarks();
+         break;
+       }  
+     case CL_SECONDS: {
+         Globals.bSeconds = !Globals.bSeconds;
+         LANGUAGE_UpdateMenuCheckmarks();
+         SendMessage(Globals.hMainWnd, WM_PAINT, 0, 0);
+         break;
        }
-       break;
-     case CL_INFO_LICENSE:
-       WineLicense(Globals.hMainWnd, Globals.lpszLanguage);
-       break;
-     case CL_INFO_NO_WARRANTY:
-       WineWarranty(Globals.hMainWnd, Globals.lpszLanguage);
-       break;
-     case CL_INFO_ABOUT_WINE:
-       ShellAbout(Globals.hMainWnd, "Clock", "Clock\n" WINE_RELEASE_INFO, 0);
-     break;
+     case CL_DATE: {
+         Globals.bDate = !Globals.bDate;
+         LANGUAGE_UpdateMenuCheckmarks();
+         LANGUAGE_UpdateWindowCaption();
+         break;
+       }
+     case CL_INFO_LICENSE: {
+         WineLicense(Globals.hMainWnd, Globals.lpszLanguage);
+         break;
+       }
+     case CL_INFO_NO_WARRANTY: {
+         WineWarranty(Globals.hMainWnd, Globals.lpszLanguage);
+         break;
+       }
+     case CL_INFO_ABOUT_WINE: {
+         ShellAbout(Globals.hMainWnd, "Clock", "Clock\n" WINE_RELEASE_INFO, 0);
+         break;
+       }
      // Handle languages
      default:
-       LANGUAGE_DefaultHandle(wParam); 
+         LANGUAGE_DefaultHandle(wParam); 
    }
    return 0;
 }
@@ -131,23 +100,26 @@
 VOID MAIN_FileChooseFont(VOID) {
 
   CHOOSEFONT font;
-        font.lStructSize       = 0;
-        font.hwndOwner         = Globals.hMainWnd;
-        font.hDC               = NULL;
-        font.lpLogFont         = 0;
-        font.iPointSize        = 0;
-        font.Flags             = 0;
-        font.rgbColors         = 0;
-        font.lCustData         = 0;
-        font.lpfnHook          = 0;
-        font.lpTemplateName    = 0;
-        font.hInstance         = Globals.hInstance;
-        font.lpszStyle         = LF_FACESIZE;
-        font.nFontType         = 0;
-        font.nSizeMin          = 0;
-        font.nSizeMax          = 0;
+  
+        font.lStructSize     = sizeof(font);
+        font.hwndOwner       = Globals.hMainWnd;
+        font.hDC             = NULL;
+        font.lpLogFont       = 0;
+        font.iPointSize      = 0;
+        font.Flags           = 0;
+        font.rgbColors       = 0;
+        font.lCustData       = 0;
+        font.lpfnHook        = 0;
+        font.lpTemplateName  = 0;
+        font.hInstance       = Globals.hInstance;
+        font.lpszStyle       = LF_FACESIZE;
+        font.nFontType       = 0;
+        font.nSizeMin        = 0;
+        font.nSizeMax        = 0;
 
-        if (ChooseFont(&font));
+        if (ChooseFont(&font)) {
+            /* do nothing yet */
+        };
 
 }
 
@@ -160,54 +132,60 @@
 {
     PAINTSTRUCT ps;
     HDC context;
-    CHAR   caption[MAX_STRING_LEN];
 
     switch (msg) {
 
-       case WM_CREATE:
-        printf("WM_CREATE\n");
-   	break;
+        case WM_CREATE: {
+            printf("WM_CREATE\n");
+   	    break;
+        }
 
-        case WM_RBUTTONUP:
-	  printf("WM_RBUTTONUP\n");
-	Globals.bWithoutTitle = !Globals.bWithoutTitle;
-	SetMenu(Globals.hMainWnd, Globals.hMainMenu);
-        UpdateWindow (Globals.hMainWnd);
-	CheckMenuItem(Globals.hPropertiesMenu, CL_WITHOUT_TITLE, \
-                       MF_BYCOMMAND | MF_UNCHECKED);
-	LoadString(Globals.hInstance, IDS_CLOCK, caption, sizeof(caption));
-        SetWindowText(Globals.hMainWnd, caption);
-	break;
+        case WM_RBUTTONUP: {
+	    printf("WM_RBUTTONUP\n");
+            Globals.bWithoutTitle = !Globals.bWithoutTitle;
+            LANGUAGE_UpdateMenuCheckmarks();               
+            LANGUAGE_UpdateWindowCaption();
+            UpdateWindow (Globals.hMainWnd);
+            break;
+        }
 
-	case WM_PAINT:
-	  printf("WM_PAINT\n");
-	  context = BeginPaint(hWnd, &ps);
-	  if(Globals.bAnalog) {
-	    DrawFace(context);
-	    Idle(context);
-	  }
-	  else {
+	case WM_PAINT: {
+            printf("WM_PAINT\n");
+            context = BeginPaint(hWnd, &ps);
+	    if(Globals.bAnalog) {
+	        DrawFace(context);
+	        Idle(context);
+	    }
+	       else 
+            {
+               /* do nothing */
+            }
+            EndPaint(hWnd, &ps);
+            break;
+        }
 
-	  }
-          EndPaint(hWnd, &ps);
-   	break;
-
-       case WM_SIZE:
-          printf("WM_SIZE\n");
-	  Globals.MaxX = LOWORD(lParam);
-	  Globals.MaxY = HIWORD(lParam);
-	  break;
+        case WM_SIZE: {
+            printf("WM_SIZE\n");
+	    Globals.MaxX = LOWORD(lParam);
+	    Globals.MaxY = HIWORD(lParam);
+            OldHour.DontRedraw   = TRUE;
+            OldMinute.DontRedraw = TRUE;
+            OldSecond.DontRedraw = TRUE;
+	    break;
+        }
 	  
-       case WM_COMMAND:
-          CLOCK_MenuCommand(wParam);
-          break;
+        case WM_COMMAND: {
+            CLOCK_MenuCommand(wParam);
+            break;
+        } 
 
-       case WM_DESTROY:
-          printf("WM_DESTROY\n");
-          PostQuitMessage (0);
-          break;
+        case WM_DESTROY: {
+            printf("WM_DESTROY\n");
+            PostQuitMessage (0);
+            break;
+        }
 
-       default:
+        default:
           return DefWindowProc (hWnd, msg, wParam, lParam);
     }
     return 0l;
@@ -220,21 +198,11 @@
  *           WinMain
  */
 
-void DumpGlobals(void) {
-
-    printf("DumpGlobals()\n");
-    printf(" Globals.lpszIniFile: %s\n", Globals.lpszIniFile); 
-    printf(" Globals.lpszIcoFile: %s\n", Globals.lpszIcoFile);
-    printf("Globals.lpszLanguage: %s\n", Globals.lpszLanguage);
-    printf("   Globals.hInstance: %i\n", Globals.hInstance);
-    printf("   Globals.hMainMenu: %i\n", Globals.hMainMenu);
-    
-}
- 
 int PASCAL WinMain (HANDLE hInstance, HANDLE prev, LPSTR cmdline, int show)
 {
     MSG      msg;
     WNDCLASS class;
+    
     char className[] = "CLClass";  /* To make sure className >= 0x10000 */
     char winName[]   = "Clock";
 
@@ -248,22 +216,21 @@
     printf("WinMain()\n");
     
     /* Setup Globals */
-    Globals.bAnalog	  = TRUE;
-    Globals.bSeconds      = TRUE;
-    Globals.lpszIniFile   = "clock.ini";
-    Globals.lpszIcoFile   = "clock.ico";
+    Globals.bAnalog	    = TRUE;
+    Globals.bSeconds        = TRUE;
+    Globals.lpszIniFile     = "clock.ini";
+    Globals.lpszIcoFile     = "clock.ico";
 
-  /* Select Language */
+    /* Select Language */
     LANGUAGE_Init();
 
-    Globals.hInstance     = hInstance;
-    Globals.hMainIcon     = ExtractIcon(Globals.hInstance, 
-                                        Globals.lpszIcoFile, 0);
+    Globals.hInstance       = hInstance;
+    Globals.hMainIcon       = ExtractIcon(Globals.hInstance, 
+                                          Globals.lpszIcoFile, 0);
+                                          
     if (!Globals.hMainIcon) Globals.hMainIcon = 
                                   LoadIcon(0, MAKEINTRESOURCE(DEFAULTICON));
 
-    DumpGlobals();				  
-				  
     if (!prev){
 	class.style         = CS_HREDRAW | CS_VREDRAW;
 	class.lpfnWndProc   = CLOCK_WndProc;
@@ -273,11 +240,11 @@
 	class.hIcon         = LoadIcon (0, IDI_APPLICATION);
 	class.hCursor       = LoadCursor (0, IDC_ARROW);
 	class.hbrBackground = GetStockObject (GRAY_BRUSH);
-	class.lpszMenuName  = "\0";
+	class.lpszMenuName  = 0;
 	class.lpszClassName = className;
     }
-    if (!RegisterClass (&class))
-	return FALSE;
+
+    if (!RegisterClass (&class)) return FALSE;
 
     Globals.hMainWnd = CreateWindow (className, winName, WS_OVERLAPPEDWINDOW,
 			CW_USEDEFAULT, 0, CW_USEDEFAULT, Globals.MaxX, Globals.MaxY, 
@@ -287,12 +254,9 @@
     LANGUAGE_SelectByName(Globals.lpszLanguage);
     SetMenu(Globals.hMainWnd, Globals.hMainMenu);
 
-//    Globals.hPopupMenu1 = CreatePopupMenu();
-//    Globals.hSystemMenu = GetSystemMenu(Globals.hMainWnd, TRUE);
-//    printf("%i", Globals.hSystemMenu);
+    Globals.hSystemMenu = GetSystemMenu(Globals.hMainWnd, TRUE);
     
-    AppendMenu(Globals.hSystemMenu, MF_STRING | MF_BYCOMMAND,
-                 1000, "item");
+    AppendMenu(Globals.hSystemMenu, MF_STRING | MF_BYCOMMAND, 1000, "item");
     SetSystemMenu(Globals.hMainWnd, Globals.hSystemMenu);
 
     EnableMenuItem(Globals.hPropertiesMenu, CL_FONT, \
@@ -301,14 +265,14 @@
     UpdateWindow (Globals.hMainWnd);
 
     while (TRUE) {
-      Sleep(1);
-      if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
-        if (msg.message == WM_QUIT) return msg.wParam;
-	TranslateMessage(&msg);
-	DispatchMessage(&msg);
-	Idle(NULL);
-      }
-      else Idle(NULL);
+        Sleep(1);
+        if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
+                if (msg.message == WM_QUIT) return msg.wParam;
+	        TranslateMessage(&msg);
+	        DispatchMessage(&msg);
+	        Idle(NULL);
+        }
+          else Idle(NULL);
     }
 
     // We will never reach the following statement !  
diff --git a/programs/clock/winclock.c b/programs/clock/winclock.c
index 5ec60e7..8a3dea0 100644
--- a/programs/clock/winclock.c
+++ b/programs/clock/winclock.c
@@ -86,18 +86,21 @@
 
 void DrawHourHand(HDC dc)
 {
+  if (OldHour.DontRedraw) return;
   MoveToEx(dc, OldHour.StartX, OldHour.StartY, NULL);
   LineTo(dc, OldHour.EndX, OldHour.EndY);
 }
 
 void DrawMinuteHand(HDC dc)
 {
+  if (OldMinute.DontRedraw) return;
   MoveToEx(dc, OldMinute.StartX, OldMinute.StartY, NULL);
   LineTo(dc, OldMinute.EndX, OldMinute.EndY);
 }
 
 void DrawSecondHand(HDC dc)
 {
+    if (OldSecond.DontRedraw) return;
     MoveToEx(dc, OldSecond.StartX, OldSecond.StartY, NULL);
     LineTo(dc, OldSecond.EndX, OldSecond.EndY);
 }
@@ -116,6 +119,7 @@
   if (Globals.bAnalog && rv)DrawHourHand(dc);
   OldHour.StartX = Sx; OldHour.EndX = Ex;
   OldHour.StartY = Sy; OldHour.EndY = Ey;
+  OldHour.DontRedraw=FALSE;
   return rv;
 }
 
@@ -133,6 +137,7 @@
   if (Globals.bAnalog && rv)DrawMinuteHand(dc);
   OldMinute.StartX = Sx; OldMinute.EndX = Ex;
   OldMinute.StartY = Sy; OldMinute.EndY = Ey;
+  OldMinute.DontRedraw=FALSE;
   return rv;
 }
 
@@ -152,6 +157,7 @@
     if (Globals.bAnalog && rv)DrawSecondHand(dc);
     OldSecond.StartX = Sx; OldSecond.EndX = Ex;
     OldSecond.StartY = Sy; OldSecond.EndY = Ey;
+    OldSecond.DontRedraw=FALSE;
   }
   
   return rv;
diff --git a/programs/clock/winclock.h b/programs/clock/winclock.h
index bbeb73d..d30fbbc 100644
--- a/programs/clock/winclock.h
+++ b/programs/clock/winclock.h
@@ -12,8 +12,11 @@
 typedef struct
 {
   int StartX,StartY,EndX,EndY;
+  BOOL DontRedraw;
 } HandData;
 
+extern HandData OldMinute, OldHour, OldSecond;
+
 /* function prototypes */
 
 
diff --git a/programs/notepad/ChangeLog b/programs/notepad/ChangeLog
index ba72d95..0c2d705 100644
--- a/programs/notepad/ChangeLog
+++ b/programs/notepad/ChangeLog
@@ -1,3 +1,7 @@
+Henrik Olsen <henrik@iaeste.dk>
+        * [Da.rc]
+        Added Danish language support.
+
 Fri May 15 23:59:22 1998  Marcel Baur <mbaur@g26.ethz.ch>
         * Date/Time now uses locale-specific formats
         * Language-specific window caption, displays file being edited.
diff --git a/programs/notepad/Da.rc b/programs/notepad/Da.rc
new file mode 100644
index 0000000..668390f
--- /dev/null
+++ b/programs/notepad/Da.rc
@@ -0,0 +1,91 @@
+/*
+ * Notepad (Danish resources)
+ *
+ * Copyright 1998 Henrik Olsen <henrik@iaeste.dk>
+ */
+
+#define LANGUAGE_ID                  Da
+#define LANGUAGE_NUMBER              6
+#define LANGUAGE_MENU_ITEM           "&Dansk"
+
+/* Menu */
+
+#define MENU_FILE                    "&Filef"
+#define MENU_FILE_NEW                "&Ny..."
+#define MENU_FILE_OPEN               "Å&bn\tEnter"
+#define MENU_FILE_SAVE               "&Gem"
+#define MENU_FILE_SAVEAS             "Gem so&m..."
+#define MENU_FILE_PRINT              "&Udskriv"
+#define MENU_FILE_PAGESETUP          "Side&opsætning..."
+#define MENU_FILE_PRINTSETUP         "&Indstil printer..."
+#define MENU_FILE_EXIT               "&Afslut"
+
+#define MENU_EDIT                    "&Rediger"
+#define MENU_EDIT_UNDO               "&Fortryd\tCtrl+Z"
+#define MENU_EDIT_CUT                "&Klip\tCtrl+X"
+#define MENU_EDIT_COPY               "K&opier\tCtrl+C"
+#define MENU_EDIT_PASTE              "Sæt &ind\tCtrl+V"
+#define MENU_EDIT_DELETE             "&Slet\tDel"
+#define MENU_EDIT_SELECTALL          "Marker &alt"
+#define MENU_EDIT_TIMEDATE           "&Dato/tid\tF5"
+#define MENU_EDIT_WRAP               "Automatisk &linjeskift"
+
+#define MENU_SEARCH                  "&Søg"
+#define MENU_SEARCH_SEARCH           "&Søg..."
+#define MENU_SEARCH_NEXT             "&Find næste\tF3"
+
+#define MENU_LANGUAGE                "S&prog"
+
+#define MENU_HELP                    "&Hjælp"
+#define MENU_HELP_CONTENTS           "&Indhold"
+#define MENU_HELP_SEARCH             "&Søg efter hjælp om..."
+#define MENU_HELP_HELP_ON_HELP       "&Brug af Hjælp"
+
+#define MENU_INFO                    "&Om Notesblok..."
+#define MENU_INFO_LICENSE            "&Licens"
+#define MENU_INFO_NO_WARRANTY        "&NO WARRANTY"
+#define MENU_INFO_ABOUT_WINE         "&Om WINE"
+
+/* Dialogs */
+#define DIALOG_OK                    "OK"
+#define DIALOG_CANCEL                "Annuller"
+#define DIALOG_BROWSE                "&Gennemse..."
+#define DIALOG_HELP                  "&Hjælp"
+
+#define DIALOG_PAGESETUP_CAPTION     "Sideopsætning"
+#define DIALOG_PAGESETUP_HEAD        "&Sidehoved:"
+#define DIALOG_PAGESETUP_TAIL        "Side&fod:"
+#define DIALOG_PAGESETUP_MARGIN      "Margener:"
+#define DIALOG_PAGESETUP_LEFT        "&Venstre:"
+#define DIALOG_PAGESETUP_RIGHT       "&Højre:"
+#define DIALOG_PAGESETUP_TOP         "&Top:"
+#define DIALOG_PAGESETUP_BOTTOM      "&Bund:"
+
+
+/* Strings */
+#define STRING_NOTEPAD               "Notesblok"
+#define STRING_ERROR                 "FEJL"
+#define STRING_WARNING               "ADVARSEL"
+#define STRING_INFO                  "Information"
+
+#define STRING_UNTITLED              "(ikke-navngivet)"
+
+#define STRING_ALL_FILES             "Alle filer (*.*)"
+#define STRING_TEXT_FILES_TXT        "Tekst filer (*.txt)"
+
+#define STRING_TOOLARGE         "Filen '%s' er for stor til Notesblok. \
+\nBrug en anden editor til at redigere filen."
+
+#define STRING_NOTEXT           "Du har ikke skrevet noget tekst. \
+\nSkriv noget tekst, og prøv så igen"
+
+#define STRING_NOTFOUND         "Kan ikke finde '%s'."
+
+#define STRING_OUT_OF_MEMORY    "Der er ikke nok hukommelse til at udføre \
+denne operation. \nAfslut et eller flere aktive programmer for at frigøre \
+hukommelse, og prøv så igen."
+
+#include "notepad.rc"
+
+
+
diff --git a/programs/notepad/Makefile.in b/programs/notepad/Makefile.in
index 3d62b9a..f6fe961 100644
--- a/programs/notepad/Makefile.in
+++ b/programs/notepad/Makefile.in
@@ -8,7 +8,7 @@
 ALL_LIBS  = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LIBS)
 RCFLAGS   = -w32 -h
 
-LANGUAGES   = En De Fr Sw
+LANGUAGES   = En Da De Fr Sw
 LICENSELANG = En
 
 MOSTSRCS = \
@@ -34,6 +34,23 @@
 
 @MAKE_RULES@
 
+# Rules for using old resource compiler
+.rc.c:
+	echo "#include \"windows.h\"" >$*-tmp.c
+	echo WINDOWS_H_ENDS_HERE >>$*-tmp.c
+	cat $< >>$*-tmp.c
+	$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P $*-tmp.c | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | $(WINERC) $(RCFLAGS) -c -o $* -p $*
+	$(RM) $*-tmp.c
+.rc.h:
+	echo "#include \"windows.h\"" >$*-tmp.c
+	echo WINDOWS_H_ENDS_HERE >>$*-tmp.c
+	cat $< >>$*-tmp.c
+	$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P $*-tmp.c | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | $(WINERC) $(RCFLAGS) -c -o $* -p $*
+	$(RM) $*-tmp.c
+clean::
+	$(RM) $(RC_SRCS:.rc=.c)
+
+
 notepad: $(MOSTOBJS) $(STRINGOBJS)
 	$(CC) -o notepad $(MOSTOBJS) $(LDOPTIONS) $(ALL_LIBS) $(STRINGOBJS)
 
diff --git a/programs/progman/ChangeLog b/programs/progman/ChangeLog
index a32b13e..9db8ab8 100644
--- a/programs/progman/ChangeLog
+++ b/programs/progman/ChangeLog
@@ -7,7 +7,7 @@
 	* [grpfile.c]
 	Added checksum calculation [UNTESTED!].
 
-Fri Jul 4 12:00:00 1997  Henrik Olsen <Henrik.Olsen@iaeste.dk>
+Fri Jul 4 12:00:00 1997  Henrik Olsen <henrik@iaeste.dk>
 
 	* [Da.rc] (new)
 	Added Danish language support.
diff --git a/programs/progman/Da.rc b/programs/progman/Da.rc
index 8ddb852..ed3d124 100644
--- a/programs/progman/Da.rc
+++ b/programs/progman/Da.rc
@@ -1,7 +1,7 @@
 /*
  * Program Manager
  *
- * Copyright 1997 Henrik Olsen
+ * Copyright 1997 Henrik Olsen <henrik@iaeste.dk>
  */
 
 #define LANGUAGE_ID                  Da
diff --git a/programs/progman/Makefile.in b/programs/progman/Makefile.in
index f387edb..4af58b8 100644
--- a/programs/progman/Makefile.in
+++ b/programs/progman/Makefile.in
@@ -39,6 +39,23 @@
 
 @MAKE_RULES@
 
+# Rules for using old resource compiler
+.rc.c:
+	echo "#include \"windows.h\"" >$*-tmp.c
+	echo WINDOWS_H_ENDS_HERE >>$*-tmp.c
+	cat $< >>$*-tmp.c
+	$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P $*-tmp.c | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | $(WINERC) $(RCFLAGS) -c -o $* -p $*
+	$(RM) $*-tmp.c
+.rc.h:
+	echo "#include \"windows.h\"" >$*-tmp.c
+	echo WINDOWS_H_ENDS_HERE >>$*-tmp.c
+	cat $< >>$*-tmp.c
+	$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P $*-tmp.c | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | $(WINERC) $(RCFLAGS) -c -o $* -p $*
+	$(RM) $*-tmp.c
+clean::
+	$(RM) $(RC_SRCS:.rc=.c)
+
+
 progman: $(MOSTOBJS) $(STRINGOBJS)
 	$(CC) -o progman $(MOSTOBJS) $(LDOPTIONS) $(ALL_LIBS) $(STRINGOBJS)
 
diff --git a/programs/regtest/ChangeLog b/programs/regtest/ChangeLog
index ef84110..a52acef 100644
--- a/programs/regtest/ChangeLog
+++ b/programs/regtest/ChangeLog
@@ -1,3 +1,8 @@
+Tue May 26 16:56:48 1997  Matthew Becker <mbecker@glasscity.net>
+
+	* [regtest.c]
+	More improvements, untested because of WineLib issue.
+
 Wed May 13 22:58:05 1997  Matthew Becker <mbecker@glasscity.net>
 
 	* [regtest.c] (new)
diff --git a/programs/regtest/regtest.c b/programs/regtest/regtest.c
index f879d9c..d038cbb 100644
--- a/programs/regtest/regtest.c
+++ b/programs/regtest/regtest.c
@@ -1,20 +1,33 @@
 /*
  * Registry testing program
  *
+ * Copyright 1998 Matthew Becker
+ *
  * The return codes were generated in an NT40 environment, using lcc-win32
  *
- * Copyright 1998 by Matthew Becker (mbecker@glasscity.net)
+ * NOTES
+ *    When compiling under lcc-win32, I get three (3) warning, but they all
+ *    seem to be issues with lcc.
  *
-*/
+ *    If creating a new testing sequence, please try to clean up any
+ *    registry changes that are made.
+ */
 
 #include <stdio.h>
 #include <malloc.h>
 #include <windows.h>
 #include <winreg.h>
 #include <winerror.h>
+#include <winnt.h>
+
+/* True this when security is implemented */
+#define CHECK_SAM FALSE
 
 /*
  * NOTES: These individual routines are listed in alphabetical order.
+ *
+ * They are meant to test error conditions.  Success conditions are
+ * tested in the sequences found at the end.
  */
 
 /******************************************************************************
@@ -23,22 +36,17 @@
 void TestCloseKey()
 {
     long lSts;
-    HKEY hkey;
     fprintf(stderr, "Testing RegCloseKey...\n");
 
-    hkey = (HKEY)0;
-    lSts = RegCloseKey(hkey);
+    lSts = RegCloseKey((HKEY)2);
     if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 1:%ld\n",lSts);
 
-    hkey = (HKEY)-2;
-    lSts = RegCloseKey(hkey);
-    if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 2:%ld\n",lSts);
+    lSts = RegCloseKey(HKEY_LOCAL_MACHINE);
+    if (lSts != ERROR_SUCCESS) fprintf(stderr, " 2:%ld\n",lSts);
 
+    /* Check twice just for kicks */
     lSts = RegCloseKey(HKEY_LOCAL_MACHINE);
     if (lSts != ERROR_SUCCESS) fprintf(stderr, " 3:%ld\n",lSts);
-
-    lSts = RegCloseKey(HKEY_LOCAL_MACHINE);
-    if (lSts != ERROR_SUCCESS) fprintf(stderr, " 4:%ld\n",lSts);
 }
 
 /******************************************************************************
@@ -50,11 +58,16 @@
     HKEY hkey;
     fprintf(stderr, "Testing RegConnectRegistry...\n");
 
-    lSts = RegConnectRegistry("",0,&hkey);
+    lSts = RegConnectRegistry("",(HKEY)2,&hkey);
     if (lSts != ERROR_SUCCESS) fprintf(stderr, " 1:%ld\n",lSts);
 
     lSts = RegConnectRegistry("",HKEY_LOCAL_MACHINE,&hkey);
     if (lSts != ERROR_SUCCESS) fprintf(stderr, " 2:%ld\n",lSts);
+
+#if TOO_SLOW
+    lSts = RegConnectRegistry("\\\\regtest",HKEY_LOCAL_MACHINE,&hkey);
+    if (lSts != ERROR_BAD_NETPATH) fprintf(stderr, " 3:%ld\n",lSts);
+#endif
 }
 
 /******************************************************************************
@@ -62,18 +75,26 @@
  */
 void TestCreateKey()
 {
-    HKEY hKeyIn;
     long lSts;
     HKEY hkey;
 
     fprintf(stderr, "Testing RegCreateKey...\n");
 
-    hKeyIn = (HKEY)1;
-    lSts = RegCreateKey(hKeyIn,"",&hkey);
+    lSts = RegCreateKey((HKEY)2,"",&hkey);
     if (lSts != ERROR_BADKEY) fprintf(stderr, " 1:%ld\n",lSts);
 
+    lSts = RegCreateKey(HKEY_LOCAL_MACHINE,"",&hkey);
+    if (lSts != ERROR_SUCCESS) fprintf(stderr, " 2:%ld\n",lSts);
+    RegCloseKey(hkey);
+
     lSts = RegCreateKey(HKEY_LOCAL_MACHINE,"\\asdf",&hkey);
-    if (lSts != ERROR_BAD_PATHNAME) fprintf(stderr, " 2:%ld\n",lSts);
+    if (lSts != ERROR_BAD_PATHNAME) fprintf(stderr, " 3:%ld\n",lSts);
+
+    lSts = RegCreateKey(HKEY_LOCAL_MACHINE,"asdf\\",&hkey);
+    if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 4:%ld\n",lSts);
+
+    lSts = RegCreateKey(HKEY_LOCAL_MACHINE,"\\asdf\\",&hkey);
+    if (lSts != ERROR_BAD_PATHNAME) fprintf(stderr, " 5:%ld\n",lSts);
 }
 
 /******************************************************************************
@@ -81,22 +102,27 @@
  */
 void TestCreateKeyEx()
 {
-    HKEY hKeyIn;
     long lSts;
     HKEY hkey;
     DWORD dwDisp;
 
     fprintf(stderr, "Testing RegCreateKeyEx...\n");
 
-    hKeyIn = (HKEY)1;
-    lSts = RegCreateKeyEx(hKeyIn,"",0,"",0,0,NULL,&hkey,&dwDisp);
-    if (lSts != ERROR_SUCCESS) fprintf(stderr, " 1:%ld\n",lSts);
+    lSts = RegCreateKeyEx((HKEY)2,"",0,"",0,0,NULL,&hkey,&dwDisp);
+    if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 1:%ld\n",lSts);
 
-    lSts = RegCreateKeyEx(hKeyIn,"regtest",0,"",0,0,NULL,&hkey,&dwDisp);
-    if (lSts != ERROR_SUCCESS) fprintf(stderr, " 2:%ld\n",lSts);
+    lSts = RegCreateKeyEx(HKEY_LOCAL_MACHINE,"regtest",0,"",0,0,NULL,&hkey,
+                          &dwDisp);
+    if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 2:%ld\n",lSts);
 
-    lSts = RegCreateKeyEx(hKeyIn,"regtest",0,"asdf",0,KEY_ALL_ACCESS,NULL,&hkey,&dwDisp);
-    if (lSts != ERROR_SUCCESS) fprintf(stderr, " 3:%ld\n",lSts);
+    lSts = RegCreateKeyEx(HKEY_LOCAL_MACHINE,"regtest",0,"asdf",0,
+                          KEY_ALL_ACCESS,NULL,&hkey,&dwDisp);
+    if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 3:%ld\n",lSts);
+
+    lSts = RegCreateKeyEx(HKEY_LOCAL_MACHINE,"regtest",0,"",0,
+                          KEY_ALL_ACCESS,NULL,&hkey,&dwDisp);
+    if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 4:%ld\n",lSts);
+
 }
 
 /******************************************************************************
@@ -105,15 +131,18 @@
 void TestDeleteKey()
 {
     long lSts;
-    HKEY hkey;
     fprintf(stderr, "Testing RegDeleteKey...\n");
 
-    hkey = (HKEY)0;
-    lSts = RegDeleteKey(hkey, "asdf");
+    lSts = RegDeleteKey((HKEY)2, "asdf");
     if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 1:%ld\n",lSts);
 
     lSts = RegDeleteKey(HKEY_CURRENT_USER, "asdf");
     if (lSts != ERROR_FILE_NOT_FOUND) fprintf(stderr, " 2:%ld\n",lSts);
+
+#if CHECK_SAM
+    lSts = RegDeleteKey(HKEY_CURRENT_USER, "");
+    if (lSts != ERROR_ACCESS_DENIED) fprintf(stderr, " 3:%ld\n",lSts);
+#endif
 }
 
 /******************************************************************************
@@ -122,15 +151,19 @@
 void TestDeleteValue()
 {
     long lSts;
-    HKEY hkey;
     fprintf(stderr, "Testing RegDeleteValue...\n");
 
-    hkey = (HKEY)0;
-    lSts = RegDeleteValue(hkey, "asdf");
+    lSts = RegDeleteValue((HKEY)2, "asdf");
     if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 1:%ld\n",lSts);
 
-    lSts = RegDeleteValue(HKEY_CURRENT_USER, "asdf");
+    lSts = RegDeleteValue(HKEY_CURRENT_USER, "");
     if (lSts != ERROR_FILE_NOT_FOUND) fprintf(stderr, " 2:%ld\n",lSts);
+
+    lSts = RegDeleteValue(HKEY_CURRENT_USER, "asdf");
+    if (lSts != ERROR_FILE_NOT_FOUND) fprintf(stderr, " 3:%ld\n",lSts);
+
+    lSts = RegDeleteValue(HKEY_CURRENT_USER, "\\asdf");
+    if (lSts != ERROR_FILE_NOT_FOUND) fprintf(stderr, " 4:%ld\n",lSts);
 }
 
 /******************************************************************************
@@ -141,14 +174,12 @@
     long lSts;
     char *sVal;
     long lVal;
-    HKEY hkey;
 
     fprintf(stderr, "Testing RegEnumKey...\n");
-    sVal = (char *)malloc(1 * sizeof(char));
-    lVal = sizeof(sVal);
+    lVal = 1;
+    sVal = (char *)malloc(lVal * sizeof(char));
 
-    hkey = (HKEY)0;
-    lSts = RegEnumKey(hkey,3,sVal,lVal);
+    lSts = RegEnumKey((HKEY)2,3,sVal,lVal);
     if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 1:%ld\n",lSts);
 
     lSts = RegEnumKey(HKEY_CURRENT_USER,-1,sVal,lVal);
@@ -171,13 +202,19 @@
     FILETIME ft;
 
     fprintf(stderr, "Testing RegEnumKeyEx...\n");
-    sVal = (char *)malloc(80 * sizeof(char));
-    lLen1= sizeof(sVal);
-    sClass = (char *)malloc(10 * sizeof(char));
-    lLen2 = sizeof(sClass);
+    lLen1 = 1;
+    sVal = (char *)malloc(lLen1 * sizeof(char));
+    lLen2 = 1;
+    sClass = (char *)malloc(lLen2 * sizeof(char));
 
-    lSts = RegEnumKeyEx(0,0,sVal,&lLen1,0,sClass,&lLen2,&ft);
+    lSts = RegEnumKeyEx((HKEY)2,0,sVal,&lLen1,0,sClass,&lLen2,&ft);
     if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 1:%ld\n",lSts);
+
+    lSts = RegEnumKeyEx(HKEY_LOCAL_MACHINE,0,sVal,&lLen1,0,sClass,&lLen2,&ft);
+    if (lSts != ERROR_MORE_DATA) fprintf(stderr, " 2:%ld\n",lSts);
+
+    lSts = RegEnumKeyEx(HKEY_LOCAL_MACHINE,0,sVal,&lLen1,0,sClass,&lLen2,&ft);
+    if (lSts != ERROR_MORE_DATA) fprintf(stderr, " 3:%ld\n",lSts);
 }
 
 /******************************************************************************
@@ -191,23 +228,21 @@
     unsigned long lType;
     unsigned long lLen1;
     char *bVal;
-    HKEY hkey;
 
     fprintf(stderr, "Testing RegEnumValue...\n");
-    sVal = (char *)malloc(80 * sizeof(char));
-    bVal = (char *)malloc(80 * sizeof(char));
-    lVal = sizeof(sVal);
-    lLen1 = sizeof(bVal);
+    lVal = 1;
+    sVal = (char *)malloc(lVal * sizeof(char));
+    lLen1 = 1;
+    bVal = (char *)malloc(lLen1 * sizeof(char));
 
-    hkey = (HKEY)0;
-    lSts = RegEnumValue(hkey,-1,sVal,&lVal,0,&lType,NULL,&lLen1);
+    lSts = RegEnumValue((HKEY)2,-1,sVal,&lVal,0,&lType,NULL,&lLen1);
     if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 1:%ld\n",lSts);
 
     lSts = RegEnumValue(HKEY_LOCAL_MACHINE,-1,sVal,&lVal,0,&lType,NULL,&lLen1);
     if (lSts != ERROR_NO_MORE_ITEMS) fprintf(stderr, " 2:%ld\n",lSts);
 
     lSts = RegEnumValue(HKEY_LOCAL_MACHINE,0,sVal,&lVal,0,&lType,NULL,&lLen1);
-    if (lSts != ERROR_NO_MORE_ITEMS) fprintf(stderr, " 3:%ld\n",lSts);
+    if (lSts != ERROR_SUCCESS) fprintf(stderr, " 3:%ld\n",lSts);
 
     lSts = RegEnumValue(HKEY_LOCAL_MACHINE,1,sVal,&lVal,0,&lType,bVal,&lLen1);
     if (lSts != ERROR_NO_MORE_ITEMS) fprintf(stderr, " 4:%ld\n",lSts);
@@ -221,7 +256,7 @@
     long lSts;
     fprintf(stderr, "Testing RegFlushKey...\n");
 
-    lSts = RegFlushKey(0);
+    lSts = RegFlushKey((HKEY)2);
     if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 1:%ld\n",lSts);
 
     lSts = RegFlushKey(HKEY_LOCAL_MACHINE);
@@ -237,21 +272,17 @@
     SECURITY_INFORMATION si;
     SECURITY_DESCRIPTOR sd;
     unsigned long lLen;
-    HKEY hkey;
 
     fprintf(stderr, "Testing RegGetKeySecurity...\n");
     lLen = sizeof(sd);
 
-    hkey = (HKEY)0;
-    lSts = RegGetKeySecurity(hkey,si,&sd,&lLen);
+    lSts = RegGetKeySecurity((HKEY)2,si,&sd,&lLen);
     if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 1:%ld\n",lSts);
 
     lSts = RegGetKeySecurity(HKEY_LOCAL_MACHINE,si,&sd,&lLen);
     if (lSts != ERROR_INSUFFICIENT_BUFFER) fprintf(stderr, " 2:%ld\n",lSts);
 
-#if 0
     si = GROUP_SECURITY_INFORMATION;
-#endif
     lSts = RegGetKeySecurity(HKEY_LOCAL_MACHINE,si,&sd,&lLen);
     if (lSts != ERROR_SUCCESS) fprintf(stderr, " 3:%ld\n",lSts);
 }
@@ -264,8 +295,8 @@
     long lSts;
     fprintf(stderr, "Testing RegLoadKey...\n");
 
-    lSts = RegLoadKey(0,"","");
-    if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 1:%ld\n",lSts);
+    lSts = RegLoadKey((HKEY)2,"","");
+    if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 1:%ld\n",lSts);
 
     lSts = RegLoadKey(HKEY_CURRENT_USER,"","");
     if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 2:%ld\n",lSts);
@@ -273,8 +304,16 @@
     lSts = RegLoadKey(HKEY_CURRENT_USER,"regtest","");
     if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 3:%ld\n",lSts);
 
+    lSts = RegLoadKey(HKEY_CURRENT_USER,"\\regtest","");
+    if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 4:%ld\n",lSts);
+
+#if CHECK_SAM
     lSts = RegLoadKey(HKEY_CURRENT_USER,"regtest","regtest.dat");
-    if (lSts != ERROR_PRIVILEGE_NOT_HELD) fprintf(stderr, " 4:%ld\n",lSts);
+    if (lSts != ERROR_PRIVILEGE_NOT_HELD) fprintf(stderr, " 5:%ld\n",lSts);
+
+    lSts = RegLoadKey(HKEY_CURRENT_USER,"\\regtest","regtest.dat");
+    if (lSts != ERROR_PRIVILEGE_NOT_HELD) fprintf(stderr, " 6:%ld\n",lSts);
+#endif
 }
 
 /******************************************************************************
@@ -284,20 +323,19 @@
 {
     long lSts;
     HANDLE hEvent;
-    HKEY hkey;
 
     fprintf(stderr, "Testing RegNotifyChangeKeyValue...\n");
-    hEvent = 0;
+    hEvent = (HANDLE)0;
 
-    hkey = (HKEY)2;
-    lSts = RegNotifyChangeKeyValue(hkey, TRUE, REG_NOTIFY_CHANGE_NAME, 0, 0);
+    lSts = RegNotifyChangeKeyValue((HKEY)2, TRUE, REG_NOTIFY_CHANGE_NAME, 0, 0);
     if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 1:%ld\n",lSts);
 
     lSts = RegNotifyChangeKeyValue(HKEY_CURRENT_USER, TRUE, REG_NOTIFY_CHANGE_NAME, 0, 1);
     if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 2:%ld\n",lSts);
 
+    hEvent = (HANDLE)HKEY_CURRENT_USER;
     lSts = RegNotifyChangeKeyValue(HKEY_CURRENT_USER, TRUE, REG_NOTIFY_CHANGE_NAME, hEvent, 1);
-    if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 3:%ld\n",lSts);
+    if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 3:%ld\n",lSts);
 }
 
 /******************************************************************************
@@ -309,13 +347,14 @@
     HKEY hkey;
     fprintf(stderr, "Testing RegOpenKey...\n");
 
-    lSts = RegOpenKey(0, "",&hkey);
+    lSts = RegOpenKey((HKEY)2, "",&hkey);
     if (lSts != ERROR_SUCCESS) fprintf(stderr, " 1:%ld\n",lSts);
+    RegCloseKey(hkey);
 
-    lSts = RegOpenKey(0, "regtest",&hkey);
+    lSts = RegOpenKey((HKEY)2, "regtest",&hkey);
     if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 2:%ld\n",lSts);
 
-    lSts = RegOpenKey(HKEY_CURRENT_USER, "regtest1",&hkey);
+    lSts = RegOpenKey(HKEY_CURRENT_USER, "regtest",&hkey);
     if (lSts != ERROR_FILE_NOT_FOUND) fprintf(stderr, " 3:%ld\n",lSts);
 
     lSts = RegOpenKey(HKEY_CURRENT_USER, "\\regtest",&hkey);
@@ -328,16 +367,20 @@
 void TestOpenKeyEx()
 {
     long lSts;
-    HKEY hkeyIn;
     HKEY hkey;
     fprintf(stderr, "Testing RegOpenKeyEx...\n");
 
-    hkeyIn = (HKEY)0;
-    lSts = RegOpenKeyEx(hkeyIn,"",0,KEY_ALL_ACCESS,&hkey);
+    lSts = RegOpenKeyEx((HKEY)2,"",0,KEY_ALL_ACCESS,&hkey);
     if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 1:%ld\n",lSts);
 
     lSts = RegOpenKeyEx(HKEY_CURRENT_USER,"\\regtest",0,KEY_ALL_ACCESS,&hkey);
     if (lSts != ERROR_BAD_PATHNAME) fprintf(stderr, " 2:%ld\n",lSts);
+
+    lSts = RegOpenKeyEx(HKEY_CURRENT_USER,"regtest",0,0,&hkey);
+    if (lSts != ERROR_FILE_NOT_FOUND) fprintf(stderr, " 3:%ld\n",lSts);
+
+    lSts = RegOpenKeyEx(HKEY_CURRENT_USER,"regtest\\",0,0,&hkey);
+    if (lSts != ERROR_FILE_NOT_FOUND) fprintf(stderr, " 3:%ld\n",lSts);
 }
 
 /******************************************************************************
@@ -345,7 +388,31 @@
  */
 void TestQueryInfoKey()
 {
+    long lSts;
+    char *sClass;
+    unsigned long lClass;
+    unsigned long lSubKeys;
+    unsigned long lMaxSubLen;
+    unsigned long lMaxClassLen;
+    unsigned long lValues;
+    unsigned long lMaxValNameLen;
+    unsigned long lMaxValLen;
+    unsigned long lSecDescLen;
+    FILETIME ft;
     fprintf(stderr, "Testing RegQueryInfoKey...\n");
+
+    lClass = 1;
+    sClass = (char *)malloc(lClass * sizeof(char));
+
+    lSts = RegQueryInfoKey((HKEY)2,sClass,&lClass,0,&lSubKeys,&lMaxSubLen,
+                           &lMaxClassLen,&lValues,&lMaxValNameLen,&lMaxValLen,
+                           &lSecDescLen, &ft);
+    if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 1:%ld\n",lSts);
+
+    lSts = RegQueryInfoKey(HKEY_CURRENT_USER,sClass,&lClass,0,&lSubKeys,
+                           &lMaxSubLen,&lMaxClassLen,&lValues,&lMaxValNameLen,
+                           &lMaxValLen,&lSecDescLen, &ft);
+    if (lSts != ERROR_SUCCESS) fprintf(stderr, " 2:%ld\n",lSts);
 }
 
 /******************************************************************************
@@ -354,16 +421,14 @@
 void TestQueryValue()
 {
     long lSts;
-    HKEY hkey;
     long lLen;
     char *sVal;
 
     fprintf(stderr, "Testing RegQueryValue...\n");
-    hkey = (HKEY)0;
     sVal = (char *)malloc(80 * sizeof(char));
     lLen = strlen(sVal);
 
-    lSts = RegQueryValue(hkey,"",NULL,&lLen);
+    lSts = RegQueryValue((HKEY)2,"",NULL,&lLen);
     if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 1:%ld\n",lSts);
 
     lSts = RegQueryValue(HKEY_CURRENT_USER,"",NULL,&lLen);
@@ -381,7 +446,23 @@
  */
 void TestQueryValueEx()
 {
+    char *sVal;
+    long lSts;
+    unsigned long lType;
+    unsigned long lLen;
+
     fprintf(stderr, "Testing RegQueryValueEx...\n");
+    lLen = 80;
+    sVal = (char *)malloc(lLen * sizeof(char));
+
+    lSts = RegQueryValueEx((HKEY)2,"",0,&lType,sVal,&lLen);
+    if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 1:%ld\n",lSts);
+
+    lSts = RegQueryValueEx(HKEY_CURRENT_USER,"",(LPDWORD)1,&lType,sVal,&lLen);
+    if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 2:%ld\n",lSts);
+
+    lSts = RegQueryValueEx(HKEY_LOCAL_MACHINE,"",0,&lType,sVal,&lLen);
+    if (lSts != ERROR_SUCCESS) fprintf(stderr, " 3:%ld\n",lSts);
 }
 
 /******************************************************************************
@@ -389,7 +470,20 @@
  */
 void TestReplaceKey()
 {
+    long lSts;
+
     fprintf(stderr, "Testing RegReplaceKey...\n");
+
+    lSts = RegReplaceKey((HKEY)2,"","","");
+    if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 1:%ld\n",lSts);
+
+#if CHECK_SAM
+    lSts = RegReplaceKey(HKEY_LOCAL_MACHINE,"","","");
+    if (lSts != ERROR_ACCESS_DENIED) fprintf(stderr, " 2:%ld\n",lSts);
+
+    lSts = RegReplaceKey(HKEY_LOCAL_MACHINE,"Software","","");
+    if (lSts != ERROR_ACCESS_DENIED) fprintf(stderr, " 3:%ld\n",lSts);
+#endif
 }
 
 /******************************************************************************
@@ -397,9 +491,128 @@
  */
 void TestRestoreKey()
 {
+    long lSts;
     fprintf(stderr, "Testing RegRestoreKey...\n");
+
+    lSts = RegRestoreKey((HKEY)2,"",0);
+    if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 1:%ld\n",lSts);
+
+    lSts = RegRestoreKey(HKEY_LOCAL_MACHINE,"",0);
+    if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 2:%ld\n",lSts);
+
+    lSts = RegRestoreKey(HKEY_LOCAL_MACHINE,"a.a",0);
+    if (lSts != ERROR_FILE_NOT_FOUND) fprintf(stderr, " 3:%ld\n",lSts);
 }
 
+/******************************************************************************
+ * TestSaveKey
+ */
+void TestSaveKey()
+{
+    long lSts;
+    fprintf(stderr, "Testing RegSaveKey...\n");
+
+    lSts = RegSaveKey((HKEY)2,"",NULL);
+    if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 1:%ld\n",lSts);
+
+    lSts = RegSaveKey(HKEY_LOCAL_MACHINE,"",NULL);
+    if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 2:%ld\n",lSts);
+
+#if CHECK_SAM
+    lSts = RegSaveKey(HKEY_LOCAL_MACHINE,"a.a",NULL);
+    if (lSts != ERROR_PRIVILEGE_NOT_HELD) fprintf(stderr, " 3:%ld\n",lSts);
+#endif
+}
+
+/******************************************************************************
+ * TestSetKeySecurity
+ */
+void TestSetKeySecurity()
+{
+    long lSts;
+    SECURITY_DESCRIPTOR sd;
+    fprintf(stderr, "Testing RegSetKeySecurity...\n");
+
+    lSts = RegSetKeySecurity((HKEY)2,0,NULL);
+    if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 1:%ld\n",lSts);
+
+    lSts = RegSetKeySecurity(HKEY_LOCAL_MACHINE,0,NULL);
+    if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 2:%ld\n",lSts);
+
+    lSts = RegSetKeySecurity(HKEY_LOCAL_MACHINE,OWNER_SECURITY_INFORMATION,NULL);
+    if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 3:%ld\n",lSts);
+
+    lSts = RegSetKeySecurity(HKEY_LOCAL_MACHINE,OWNER_SECURITY_INFORMATION,&sd);
+    if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 4:%ld\n",lSts);
+}
+
+/******************************************************************************
+ * TestSetValue
+ */
+void TestSetValue()
+{
+    long lSts;
+    fprintf(stderr, "Testing RegSetValue...\n");
+
+#if MAKE_NT_CRASH
+    lSts = RegSetValue((HKEY)2,"",0,NULL,0);
+    if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 1:%ld\n",lSts);
+#endif
+
+#if MAKE_NT_CRASH
+    lSts = RegSetValue((HKEY)2,"regtest",0,NULL,0);
+    if (lSts != ERROR_INVALID_PARAMETER) fprintf(stderr, " 2:%ld\n",lSts);
+#endif
+
+#if MAKE_NT_CRASH
+    lSts = RegSetValue((HKEY)2,"regtest",REG_SZ,NULL,0);
+    if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 3:%ld\n",lSts);
+#endif
+
+#if MAKE_NT_CRASH
+    lSts = RegSetValue(HKEY_LOCAL_MACHINE,"regtest",REG_SZ,NULL,0);
+    if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 4:%ld\n",lSts);
+#endif
+}
+
+/******************************************************************************
+ * TestSetValueEx
+ */
+void TestSetValueEx()
+{
+    long lSts;
+    fprintf(stderr, "Testing RegSetValueEx...\n");
+
+    lSts = RegSetValueEx((HKEY)2,"",0,0,NULL,0);
+    if (lSts != ERROR_INVALID_HANDLE) fprintf(stderr, " 1:%ld\n",lSts);
+
+    lSts = RegSetValueEx(HKEY_LOCAL_MACHINE,"",0,0,NULL,0);
+    if (lSts != ERROR_SUCCESS) fprintf(stderr, " 2:%ld\n",lSts);
+}
+
+/******************************************************************************
+ * TestUnLoadKey
+ */
+void TestUnLoadKey()
+{
+    long lSts;
+    fprintf(stderr, "Testing RegUnloadKey...\n");
+
+#if CHECK_SAM
+    lSts = RegUnLoadKey((HKEY)2,"");
+    if (lSts != ERROR_PRIVILEGE_NOT_HELD) fprintf(stderr, " 1:%ld\n",lSts);
+
+    lSts = RegUnLoadKey(HKEY_LOCAL_MACHINE,"");
+    if (lSts != ERROR_PRIVILEGE_NOT_HELD) fprintf(stderr, " 2:%ld\n",lSts);
+
+    lSts = RegUnLoadKey(HKEY_LOCAL_MACHINE,"\\regtest");
+    if (lSts != ERROR_PRIVILEGE_NOT_HELD) fprintf(stderr, " 3:%ld\n",lSts);
+#endif
+}
+
+/******************************************************************************
+ * TestSequence1
+ */
 void TestSequence1()
 {
     HKEY hkey;
@@ -409,6 +622,13 @@
 
     lSts = RegCreateKey(HKEY_CURRENT_USER,"regtest",&hkey);
     if (lSts != ERROR_SUCCESS) fprintf(stderr, " 1:%ld\n",lSts);
+
+    fprintf(stderr, " hkey=0x%x\n", hkey);
+
+    lSts = RegDeleteKey(HKEY_CURRENT_USER, "regtest");
+    if (lSts != ERROR_SUCCESS) fprintf(stderr, " 2:%ld\n",lSts);
+    lSts = RegCloseKey(hkey);
+    if (lSts != ERROR_SUCCESS) fprintf(stderr, " 3:%ld\n",lSts);
 }
 
 
@@ -436,13 +656,11 @@
     TestQueryValueEx();
     TestReplaceKey();
     TestRestoreKey();
-/*
     TestSaveKey();
     TestSetKeySecurity();
     TestSetValue();
     TestSetValueEx();
-    TestUnloadKey();
-*/
+    TestUnLoadKey();
 
     /* Now we have some sequence testing */
     TestSequence1();
diff --git a/programs/view/Makefile.in b/programs/view/Makefile.in
index b222aef..df891ad 100644
--- a/programs/view/Makefile.in
+++ b/programs/view/Makefile.in
@@ -22,6 +22,23 @@
 
 @MAKE_RULES@
 
+# Rules for using old resource compiler
+.rc.c:
+	echo "#include \"windows.h\"" >$*-tmp.c
+	echo WINDOWS_H_ENDS_HERE >>$*-tmp.c
+	cat $< >>$*-tmp.c
+	$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P $*-tmp.c | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | $(WINERC) $(RCFLAGS) -c -o $* -p $*
+	$(RM) $*-tmp.c
+.rc.h:
+	echo "#include \"windows.h\"" >$*-tmp.c
+	echo WINDOWS_H_ENDS_HERE >>$*-tmp.c
+	cat $< >>$*-tmp.c
+	$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P $*-tmp.c | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | $(WINERC) $(RCFLAGS) -c -o $* -p $*
+	$(RM) $*-tmp.c
+clean::
+	$(RM) $(RC_SRCS:.rc=.c)
+
+
 view: $(OBJS)
 	$(CC) -o view $(OBJS) $(LDOPTIONS) $(ALL_LIBS)
 
diff --git a/programs/winhelp/Makefile.in b/programs/winhelp/Makefile.in
index fa90628..2b71249c 100644
--- a/programs/winhelp/Makefile.in
+++ b/programs/winhelp/Makefile.in
@@ -34,6 +34,22 @@
 
 @MAKE_RULES@
 
+# Rules for using old resource compiler
+.rc.c:
+	echo "#include \"windows.h\"" >$*-tmp.c
+	echo WINDOWS_H_ENDS_HERE >>$*-tmp.c
+	cat $< >>$*-tmp.c
+	$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P $*-tmp.c | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | $(WINERC) $(RCFLAGS) -c -o $* -p $*
+	$(RM) $*-tmp.c
+.rc.h:
+	echo "#include \"windows.h\"" >$*-tmp.c
+	echo WINDOWS_H_ENDS_HERE >>$*-tmp.c
+	cat $< >>$*-tmp.c
+	$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P $*-tmp.c | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | $(WINERC) $(RCFLAGS) -c -o $* -p $*
+	$(RM) $*-tmp.c
+clean::
+	$(RM) $(RC_SRCS:.rc=.c)
+
 # Some strings need addresses >= 0x10000
 winhelp: $(MOSTOBJS) $(STRINGOBJS)
 	$(CC) -o winhelp $(MOSTOBJS) $(LDOPTIONS) $(ALL_LIBS) $(STRINGOBJS)
diff --git a/relay32/advapi32.spec b/relay32/advapi32.spec
index cadd3aa..b3fcc0d 100644
--- a/relay32/advapi32.spec
+++ b/relay32/advapi32.spec
@@ -78,7 +78,7 @@
 0074 stdcall InitializeSid(ptr ptr long) InitializeSid
 0075 stub InitiateSystemShutdownA
 0076 stub InitiateSystemShutdownW
-0077 stub IsTextUnicode
+0077 stdcall IsTextUnicode(ptr long ptr) RtlIsTextUnicode
 0078 stub IsValidAcl
 0079 stub IsValidSecurityDescriptor
 0080 stdcall IsValidSid(ptr) IsValidSid
@@ -162,19 +162,19 @@
 0158 stdcall RegQueryValueExW(long wstr ptr ptr ptr ptr) RegQueryValueEx32W
 0159 stdcall RegQueryValueW(long wstr ptr ptr) RegQueryValue32W
 0160 stub RegRemapPreDefKey
-0161 stub RegReplaceKeyA
-0162 stub RegReplaceKeyW
-0163 stub RegRestoreKeyA
-0164 stub RegRestoreKeyW
-0165 stub RegSaveKeyA
-0166 stub RegSaveKeyW
-0167 stub RegSetKeySecurity
+0161 stdcall RegReplaceKeyA(long str str str) RegReplaceKey32A
+0162 stdcall RegReplaceKeyW(long wstr wstr wstr) RegReplaceKey32W
+0163 stdcall RegRestoreKeyA(long str long) RegRestoreKey32A
+0164 stdcall RegRestoreKeyW(long wstr long) RegRestoreKey32W
+0165 stdcall RegSaveKeyA(long ptr ptr) RegSaveKey32A
+0166 stdcall RegSaveKeyW(long ptr ptr) RegSaveKey32W
+0167 stdcall RegSetKeySecurity(long long ptr) RegSetKeySecurity
 0168 stdcall RegSetValueA(long str long ptr long) RegSetValue32A
 0169 stdcall RegSetValueExA(long str long long ptr long) RegSetValueEx32A
 0170 stdcall RegSetValueExW(long wstr long long ptr long) RegSetValueEx32W
 0171 stdcall RegSetValueW(long wstr long ptr long) RegSetValue32W
-0172 stub RegUnLoadKeyA
-0173 stub RegUnLoadKeyW
+0172 stdcall RegUnLoadKeyA(long str) RegUnLoadKey32A
+0173 stdcall RegUnLoadKeyW(long wstr) RegUnLoadKey32W
 0174 stdcall RegisterEventSourceA(ptr ptr) RegisterEventSource32A
 0175 stdcall RegisterEventSourceW(ptr ptr) RegisterEventSource32W
 0176 stub RegisterServiceCtrlHandlerA
diff --git a/relay32/builtin32.c b/relay32/builtin32.c
index ee17a69..3e238ca 100644
--- a/relay32/builtin32.c
+++ b/relay32/builtin32.c
@@ -5,7 +5,6 @@
  */
 
 #include <assert.h>
-#include <stdio.h>
 #include <string.h>
 #include "builtin32.h"
 #include "module.h"
@@ -24,17 +23,7 @@
 
 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;
 
@@ -72,38 +61,38 @@
 
 static BUILTIN32_DLL BuiltinDLLs[] =
 {
-    { &ADVAPI32_Descriptor, NULL, TRUE  },
-    { &COMCTL32_Descriptor, NULL, FALSE },
-    { &COMDLG32_Descriptor, NULL, TRUE  },
-    { &CRTDLL_Descriptor,   NULL, TRUE  },
-    { &DCIMAN32_Descriptor, NULL, FALSE },
-    { &DDRAW_Descriptor,    NULL, TRUE  },
-    { &DINPUT_Descriptor,   NULL, TRUE  },
-    { &DPLAY_Descriptor,    NULL, TRUE  },
-    { &DPLAYX_Descriptor,   NULL, TRUE  },
-    { &DSOUND_Descriptor,   NULL, TRUE  },
-    { &GDI32_Descriptor,    NULL, TRUE  },
-    { &KERNEL32_Descriptor, NULL, TRUE  },
-    { &LZ32_Descriptor,     NULL, TRUE  },
-    { &MPR_Descriptor,      NULL, TRUE  },
-    { &MSVFW32_Descriptor,  NULL, FALSE },
-    { &NTDLL_Descriptor,    NULL, TRUE  },
-    { &OLE32_Descriptor,    NULL, FALSE },
-    { &OLEAUT32_Descriptor, NULL, FALSE },
-    { &OLECLI32_Descriptor, NULL, FALSE },
-    { &OLESVR32_Descriptor, NULL, FALSE },
-    { &SHELL32_Descriptor,  NULL, TRUE  },
-    { &TAPI32_Descriptor,   NULL, FALSE },
-    { &USER32_Descriptor,   NULL, TRUE  },
-    { &VERSION_Descriptor,  NULL, TRUE  },
-    { &W32SKRNL_Descriptor, NULL, TRUE  },
-    { &WINMM_Descriptor,    NULL, TRUE  },
-    { &WINSPOOL_Descriptor, NULL, TRUE  },
-    { &WNASPI32_Descriptor, NULL, TRUE  },
-    { &WOW32_Descriptor,    NULL, TRUE  },
-    { &WSOCK32_Descriptor,  NULL, TRUE  },
+    { &ADVAPI32_Descriptor, TRUE  },
+    { &COMCTL32_Descriptor, FALSE },
+    { &COMDLG32_Descriptor, TRUE  },
+    { &CRTDLL_Descriptor,   TRUE  },
+    { &DCIMAN32_Descriptor, FALSE },
+    { &DDRAW_Descriptor,    TRUE  },
+    { &DINPUT_Descriptor,   TRUE  },
+    { &DPLAY_Descriptor,    TRUE  },
+    { &DPLAYX_Descriptor,   TRUE  },
+    { &DSOUND_Descriptor,   TRUE  },
+    { &GDI32_Descriptor,    TRUE  },
+    { &KERNEL32_Descriptor, TRUE  },
+    { &LZ32_Descriptor,     TRUE  },
+    { &MPR_Descriptor,      TRUE  },
+    { &MSVFW32_Descriptor,  FALSE },
+    { &NTDLL_Descriptor,    TRUE  },
+    { &OLE32_Descriptor,    FALSE },
+    { &OLEAUT32_Descriptor, FALSE },
+    { &OLECLI32_Descriptor, FALSE },
+    { &OLESVR32_Descriptor, FALSE },
+    { &SHELL32_Descriptor,  TRUE  },
+    { &TAPI32_Descriptor,   FALSE },
+    { &USER32_Descriptor,   TRUE  },
+    { &VERSION_Descriptor,  TRUE  },
+    { &W32SKRNL_Descriptor, TRUE  },
+    { &WINMM_Descriptor,    TRUE  },
+    { &WINSPOOL_Descriptor, TRUE  },
+    { &WNASPI32_Descriptor, TRUE  },
+    { &WOW32_Descriptor,    TRUE  },
+    { &WSOCK32_Descriptor,  TRUE  },
     /* Last entry */
-    { NULL, NULL, FALSE }
+    { NULL, FALSE }
 };
 
 
@@ -115,7 +104,6 @@
 static HMODULE32 BUILTIN32_DoLoadModule( BUILTIN32_DLL *dll, PDB32 *pdb )
 {
     extern void RELAY_CallFrom32();
-    extern void CALL32_Regs();
 
     HMODULE16 hModule;
     NE_MODULE *pModule;
@@ -128,7 +116,6 @@
     LPVOID *funcs;
     LPSTR *names;
     DEBUG_ENTRY_POINT *debug;
-    REG_ENTRY_POINT *regs;
     WINE_MODREF *wm;
     PE_MODREF *pem;
     INT32 i, size;
@@ -141,8 +128,7 @@
             + 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));
+            + dll->descr->nb_names * sizeof(LPSTR));
 #ifdef __i386__
     if (TRACE_ON(relay))
         size += dll->descr->nb_funcs * sizeof(DEBUG_ENTRY_POINT);
@@ -155,8 +141,7 @@
     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);
+    debug = (DEBUG_ENTRY_POINT *)(names + dll->descr->nb_names);
 
     /* Build the DOS and NT headers */
 
@@ -207,14 +192,14 @@
 
     sec++;
     strcpy( sec->Name, ".code" );
-    sec->SizeOfRawData = dll->descr->nb_reg_funcs * sizeof(REG_ENTRY_POINT);
+    sec->SizeOfRawData = 0;
 #ifdef __i386__
     if (TRACE_ON(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->VirtualAddress   = (BYTE *)debug - addr;
+    sec->PointerToRawData = (BYTE *)debug - addr;
     sec->Characteristics  = (IMAGE_SCN_CNT_INITIALIZED_DATA |
                              IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ);
 
@@ -230,50 +215,34 @@
 
     /* Build the funcs table */
 
-    if (TRACE_ON(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;
+        *funcs = (LPVOID)((BYTE *)dll->descr->functions[i] - addr);
 #ifdef __i386__
+        if (!TRACE_ON(relay)) continue;
         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 (TRACE_ON(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++;
+            debug->call       = 0xe8;
+            debug->callfrom32 = (DWORD)dll->descr->functions[i] -
+                                (DWORD)&debug->ret;
+            debug->ret        = 0x90;  /* nop */
+            debug->args       = 0;
+            *funcs = (LPVOID)((BYTE *)debug - addr);
             break;
         case 0xff:  /* stub or extern */
-            *funcs = (LPVOID)((BYTE *)dll->descr->functions[i] - addr);
             break;
         default:  /* normal function (stdcall or cdecl) */
-            if (TRACE_ON(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);
+            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);
             break;
         }
-#else  /* __i386__ */
-        *funcs = (LPVOID)((BYTE *)dll->descr->functions[i] - addr);
 #endif  /* __i386__ */
     }
 
@@ -349,19 +318,31 @@
                                       unsigned int *typemask )
 {
     BUILTIN32_DLL *dll;
-    int ordinal, i;
+    HMODULE32 hModule;
+    int ordinal = 0, 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;
+        if (dll->used 
+            && ((hModule = GetModuleHandle32A(dll->descr->name)) != 0))
+        {
+            IMAGE_SECTION_HEADER *sec = PE_SECTIONS(hModule);
+            DEBUG_ENTRY_POINT *debug = 
+                 (DEBUG_ENTRY_POINT *)((DWORD)hModule + sec[1].VirtualAddress);
+            DEBUG_ENTRY_POINT *func = (DEBUG_ENTRY_POINT *)relay;
+
+            if (debug <= func && func < debug + dll->descr->nb_funcs)
+            {
+                ordinal = func - debug;
+                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 );
@@ -390,12 +371,12 @@
         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",
+    MSG( "No handler for Win32 routine %s.%d: %s",
              descr->name, ordinal, func_name );
 #ifdef __GNUC__
-    fprintf( stderr, " (called from %p)", __builtin_return_address(1) );
+    MSG( " (called from %p)", __builtin_return_address(1) );
 #endif
-    fprintf( stderr, "\n" );
+    MSG( "\n" );
     TASK_KillCurrentTask(1);
 }
 
@@ -432,9 +413,9 @@
     int i;
     BUILTIN32_DLL *dll;
 
-    fprintf(stderr,"Available Win32 DLLs:\n");
+    MSG("Available Win32 DLLs:\n");
     for (i = 0, dll = BuiltinDLLs; dll->descr; dll++)
-        fprintf( stderr, "%-9s%c", dll->descr->name,
+        MSG("%-9s%c", dll->descr->name,
                  ((++i) % 8) ? ' ' : '\n' );
-    fprintf(stderr,"\n");
+    MSG("\n");
 }
diff --git a/relay32/comctl32.spec b/relay32/comctl32.spec
index f4448c3..a493dcf 100644
--- a/relay32/comctl32.spec
+++ b/relay32/comctl32.spec
@@ -11,8 +11,8 @@
   4 stub GetEffectiveClientRect
   5 stdcall DrawStatusTextA(long ptr ptr long) DrawStatusText32A
   6 stdcall CreateStatusWindowA(long ptr long long) CreateStatusWindow32A
-  7 stub CreateToolbar
-  8 stub CreateMappedBitmap
+  7 stdcall CreateToolbar(long long long long long long ptr long) CreateToolbar
+  8 stdcall CreateMappedBitmap(long long long ptr long) CreateMappedBitmap
   9 stub COMCTL32_9
  10 stub COMCTL32_10
  11 stub COMCTL32_11
@@ -25,15 +25,13 @@
  18 stub CreatePropertySheetPage
  19 stub CreatePropertySheetPageA
  20 stub CreatePropertySheetPageW
-# 21 pascal16 CreateStatusWindow(word ptr word word) CreateStatusWindow16
- 21 stub CreateStatusWindow
+ 21 stdcall CreateStatusWindow(long ptr long long) CreateStatusWindow32A
  22 stdcall CreateStatusWindowW(long ptr long long) CreateStatusWindow32W
- 23 stub CreateToolbarEx
+ 23 stdcall CreateToolbarEx(long long long long long long ptr long long long long long long) CreateToolbarEx
  24 stub DestroyPropertySheetPage
  25 stub DllGetVersion
  26 stub DllInstall
-# 27 pascal16 DrawStatusText(word ptr ptr word) DrawStatusText16
- 27 stub DrawStatusText
+ 27 stdcall DrawStatusText(long ptr ptr long) DrawStatusText32A
  28 stdcall DrawStatusTextW(long ptr ptr long) DrawStatusText32W
  29 stub FlatSB_EnableScrollBar
  30 stub FlatSB_GetScrollInfo
@@ -46,7 +44,7 @@
  37 stub FlatSB_SetScrollRange
  38 stub FlatSB_ShowScrollBar
  39 stdcall ImageList_Add(ptr long long) ImageList_Add
- 40 stub ImageList_AddIcon
+ 40 stdcall ImageList_AddIcon(ptr long) ImageList_AddIcon
  41 stdcall ImageList_AddMasked(ptr long long) ImageList_AddMasked
  42 stdcall ImageList_BeginDrag(ptr long long long) ImageList_BeginDrag
  43 stdcall ImageList_Copy(ptr long ptr long long) ImageList_Copy
@@ -68,11 +66,11 @@
  59 stdcall ImageList_GetImageCount(ptr) ImageList_GetImageCount
  60 stdcall ImageList_GetImageInfo(ptr long ptr) ImageList_GetImageInfo
  61 stdcall ImageList_GetImageRect(ptr long ptr) ImageList_GetImageRect
- 62 stub ImageList_LoadImage
+ 63 stdcall ImageList_LoadImage(long ptr long long long long long) ImageList_LoadImage32A
  63 stdcall ImageList_LoadImageA(long ptr long long long long long) ImageList_LoadImage32A
  64 stdcall ImageList_LoadImageW(long ptr long long long long long) ImageList_LoadImage32W
  65 stdcall ImageList_Merge(ptr long ptr long long long) ImageList_Merge
- 66 stub ImageList_Read
+ 66 stdcall ImageList_Read(ptr) ImageList_Read
  67 stdcall ImageList_Remove(ptr long) ImageList_Remove
  68 stdcall ImageList_Replace(ptr long long long) ImageList_Replace
  69 stdcall ImageList_ReplaceIcon(ptr long long) ImageList_ReplaceIcon
@@ -86,7 +84,7 @@
  77 stdcall ImageList_SetIconSize(ptr long long) ImageList_SetIconSize
  78 stdcall ImageList_SetImageCount(ptr long) ImageList_SetImageCount
  79 stdcall ImageList_SetOverlayImage(ptr long long) ImageList_SetOverlayImage
- 80 stub ImageList_Write
+ 80 stdcall ImageList_Write(ptr ptr) ImageList_Write
  81 stdcall InitCommonControlsEx(ptr) InitCommonControlsEx
  82 stub InitializeFlatSB
  83 stub PropertySheet
@@ -122,6 +120,7 @@
 325 stub DSA_SetItem
 326 stub DSA_DeleteItem
 327 stub DSA_DeleteAllItems
+
 328 stub DPA_Create
 329 stub DPA_Destroy
 330 stub DPA_Grow
diff --git a/relay32/crtdll.spec b/relay32/crtdll.spec
index 84d6025..5259e53 100644
--- a/relay32/crtdll.spec
+++ b/relay32/crtdll.spec
@@ -130,7 +130,7 @@
 126 stub _getpid
 127 stub _getsystime
 128 stub _getw
-129 register _global_unwind2() CRTDLL__global_unwind2
+129 cdecl _global_unwind2(ptr) CRTDLL__global_unwind2
 130 stub _heapchk
 131 stub _heapmin
 132 stub _heapset
@@ -174,7 +174,7 @@
 170 stub _kbhit
 171 stub _lfind
 172 stub _loaddll
-173 register _local_unwind2() CRTDLL__local_unwind2
+173 cdecl _local_unwind2(ptr long) CRTDLL__local_unwind2
 174 stub _locking
 175 stub _logb
 176 cdecl _lrotl (long long) CRTDLL__lrotl
@@ -494,8 +494,8 @@
 490 cdecl tmpnam(str) CRTDLL_tmpnam
 491 cdecl tolower(long) tolower
 492 cdecl toupper(long) toupper
-493 stub towlower
-494 cdecl towupper(long) CRTDLL_towupper
+493 cdecl towlower(long) towlower
+494 cdecl towupper(long) towupper
 495 stub ungetc
 496 stub ungetwc
 497 cdecl vfprintf(ptr str ptr) CRTDLL_vfprintf
diff --git a/relay32/dplayx.spec b/relay32/dplayx.spec
index 7a7cd75..cffce80 100644
--- a/relay32/dplayx.spec
+++ b/relay32/dplayx.spec
@@ -4,6 +4,6 @@
   1 stub DirectPlayCreate
   2 stub DirectPlayEnumerateA
   3 stub DirectPlayEnumerateW
-  4 stub DirectPlayLobbyCreateA
-  5 stub DirectPlayLobbyCreateW
+  4 stdcall DirectPlayLobbyCreateA(ptr ptr ptr ptr long) DirectPlayLobbyCreateA
+  5 stdcall DirectPlayLobbyCreateW(ptr ptr ptr ptr long) DirectPlayLobbyCreateW
   9 stub DirectPlayEnumerate
diff --git a/relay32/kernel32.spec b/relay32/kernel32.spec
index 5ec21f3..42e0af7 100644
--- a/relay32/kernel32.spec
+++ b/relay32/kernel32.spec
@@ -12,15 +12,15 @@
 # - code generated by the MS Thunk Compiler
 # - symbols exported by the Oct 94 beta version of kernel32.dll
 
-  1 stub VxDCall0
-  2 stub VxDCall1
-  3 stub VxDCall2
-  4 stub VxDCall3
-  5 stub VxDCall4
-  6 stub VxDCall5
-  7 stub VxDCall6
-  8 stub VxDCall7
-  9 stub VxDCall8
+  1 stdcall VxDCall0(long) VxDCall
+  2 stdcall VxDCall1(long) VxDCall
+  3 stdcall VxDCall2(long) VxDCall
+  4 stdcall VxDCall3(long) VxDCall
+  5 stdcall VxDCall4(long) VxDCall
+  6 stdcall VxDCall5(long) VxDCall
+  7 stdcall VxDCall6(long) VxDCall
+  8 stdcall VxDCall7(long) VxDCall
+  9 stdcall VxDCall8(long) VxDCall
  10 stdcall k32CharToOemA(str str) CharToOem32A
  11 stdcall k32CharToOemBuffA(str str long) CharToOemBuff32A
  12 stdcall k32OemToCharA(ptr ptr) OemToChar32A
@@ -59,8 +59,8 @@
  45 register Common32ThkLS() Common32ThkLS 
  46 stdcall ThunkInitSL(long str long str str) ThunkInitSL
  47 stub LogCBThkSL
- 48 stub ReleaseThunkLock
- 49 stub RestoreThunkLock
+ 48 stdcall ReleaseThunkLock(ptr) ReleaseThunkLock
+ 49 stdcall RestoreThunkLock(long) RestoreThunkLock
  50 stdcall AddAtomA(str) AddAtom32A
  51 stub W32S_BackTo32
  52 stdcall GetThunkBuff() GetThunkBuff
@@ -107,9 +107,9 @@
  93 stdcall GetpWin16Lock(ptr) GetpWin16Lock
  94 stub _CheckNotSysLevel
  95 stub _ConfirmSysLevel
- 96 stub _ConfirmWin16Lock
- 97 stub _EnterSysLevel
- 98 stub _LeaveSysLevel
+ 96 stdcall _ConfirmWin16Lock() _ConfirmWin16Lock
+ 97 stdcall _EnterSysLevel(ptr) _EnterSysLevel
+ 98 stdcall _LeaveSysLevel(ptr) _LeaveSysLevel
  99 stdcall _KERNEL32_99(long) _KERNEL32_99
 100 stdcall _KERNEL32_100(long long long) _KERNEL32_100
 101 stub _KERNEL32_101
@@ -193,7 +193,9 @@
 178 stdcall CreateThread(ptr long ptr long long ptr) CreateThread
 179 stub CreateToolhelp32Snapshot
 180 stub DebugActiveProcess
-181 register DebugBreak() DebugBreak
+# FIXME
+#181 register DebugBreak() DebugBreak
+181 stub DebugBreak
 182 stub DefineDosDeviceA
 183 stub DefineDosDeviceW
 184 stdcall DeleteAtom(long) DeleteAtom32
@@ -258,7 +260,7 @@
 243 stdcall FillConsoleOutputCharacterW(long long long long ptr) FillConsoleOutputCharacterW
 244 stdcall FindAtomA(str) FindAtom32A
 245 stdcall FindAtomW(wstr) FindAtom32W
-247 stub FindCloseChangeNotification
+247 stdcall FindCloseChangeNotification(long) FindCloseChangeNotification
 246 stdcall FindClose(long) FindClose32
 248 stdcall FindFirstChangeNotificationA(str long long) FindFirstChangeNotification32A
 249 stub FindFirstChangeNotificationW
@@ -579,13 +581,13 @@
 564 stdcall QueryPerformanceCounter(ptr) QueryPerformanceCounter
 565 stdcall QueryPerformanceFrequency(ptr) QueryPerformanceFrequency
 566 stub QueueUserAPC
-567 register RaiseException() EXC_RaiseException
+567 register RaiseException() RaiseException
 568 stdcall ReadConsoleA(long ptr long ptr ptr) ReadConsole32A
 569 stdcall ReadConsoleInputA(long ptr long ptr) ReadConsoleInputA
 570 stub ReadConsoleInputW
 571 stub ReadConsoleOutputA
 572 stub ReadConsoleOutputAttribute
-573 stub ReadConsoleOutputCharacterA
+573 stdcall ReadConsoleOutputCharacterA(long ptr long long ptr) ReadConsoleOutputCharacter32A
 574 stub ReadConsoleOutputCharacterW
 575 stub ReadConsoleOutputW
 576 stdcall ReadConsoleW(long ptr long ptr ptr) ReadConsole32W
@@ -602,7 +604,7 @@
 587 stdcall ResumeThread(long) ResumeThread
 588 stdcall RtlFillMemory(ptr long long) RtlFillMemory
 589 stdcall RtlMoveMemory(ptr ptr long) RtlMoveMemory
-590 register RtlUnwind() EXC_RtlUnwind
+590 register RtlUnwind() RtlUnwind
 591 stdcall RtlZeroMemory(ptr long) RtlZeroMemory
 592 register SMapLS() SMapLS
 593 register SMapLS_IP_EBP_12() SMapLS_IP_EBP_12
@@ -886,8 +888,8 @@
 870 stub GetConsoleKeyboardLayoutNameW
 871 stdcall GetDiskFreeSpaceExA (str ptr ptr ptr) GetDiskFreeSpaceEx32A
 873 stdcall GetDiskFreeSpaceExW (wstr ptr ptr ptr) GetDiskFreeSpaceEx32W
-874 stub GetFileAttributesExA
-875 stub GetFileAttributesExW
+874 stdcall GetFileAttributesExA(str long ptr) GetFileAttributesEx32A
+875 stdcall GetFileAttributesExW(wstr long ptr) GetFileAttributesEx32W
 876 stub GetProcessPriorityBoost
 877 stub GetThreadPriorityBoost
 878 stub InterlockedCompareExchange
diff --git a/relay32/mpr.spec b/relay32/mpr.spec
index ce8e821..aa2516a 100644
--- a/relay32/mpr.spec
+++ b/relay32/mpr.spec
@@ -1,90 +1,113 @@
 name mpr
 type win32
 
-0009 stub DllCanUnloadNow
-0010 stub DllGetClassObject
-0025 stdcall MultinetGetConnectionPerformanceA(ptr ptr) MultinetGetConnectionPerformance32A
-0026 stub MultinetGetConnectionPerformanceW
-0027 stub MultinetGetErrorTextA
-0028 stub MultinetGetErrorTextW
-0029 stub NPSAuthenticationDialogA
-0030 stub NPSCopyStringA
-0031 stub NPSDeviceGetNumberA
-0032 stub NPSDeviceGetStringA
-0033 stub NPSGetProviderHandleA
-0034 stub NPSGetProviderNameA
-0035 stub NPSGetSectionNameA
-0036 stub NPSNotifyGetContextA
-0037 stub NPSNotifyRegisterA
-0038 stub NPSSetCustomTextA
-0039 stub NPSSetExtendedErrorA
-0040 stub PwdChangePasswordA
-0041 stub PwdChangePasswordW
-0042 stub PwdGetPasswordStatusA
-0043 stub PwdGetPasswordStatusW
-0044 stub PwdSetPasswordStatusA
-0045 stub PwdSetPasswordStatusW
-0046 stdcall WNetAddConnection2A(ptr str str long) WNetAddConnection2_32A
-0047 stdcall WNetAddConnection2W(ptr wstr wstr long) WNetAddConnection2_32W
-0048 stdcall WNetAddConnection3A(long ptr str str long) WNetAddConnection3_32A
-0049 stdcall WNetAddConnection3W(long ptr wstr wstr long) WNetAddConnection3_32W
-0050 stdcall WNetAddConnectionA(str str str) WNetAddConnection32A
-0051 stdcall WNetAddConnectionW(wstr wstr wstr) WNetAddConnection32W
-0052 stdcall WNetCachePassword(str long str long long) WNetCachePassword
-0053 stub WNetCancelConnection2A
-0054 stub WNetCancelConnection2W
-0055 stub WNetCancelConnectionA
-0056 stub WNetCancelConnectionW
-0057 stub WNetCloseEnum
-0060 stub WNetConnectionDialog
-0058 stub WNetConnectionDialog1A
-0059 stub WNetConnectionDialog1W
-0063 stub WNetDisconnectDialog
-0061 stub WNetDisconnectDialog1A
-0062 stub WNetDisconnectDialog1W
-0064 stub WNetEnumCachedPasswords
-0065 stub WNetEnumResourceA
-0066 stub WNetEnumResourceW
-0067 stub WNetFormatNetworkNameA
-0068 stub WNetFormatNetworkNameW
-0069 stdcall WNetGetCachedPassword(ptr long ptr ptr long) WNetGetCachedPassword
-0070 stdcall WNetGetConnectionA(ptr ptr ptr) WNetGetConnection32A
-0071 stub WNetGetConnectionW
-0072 stub WNetGetHomeDirectoryA
-0073 stub WNetGetHomeDirectoryW
-0074 stub WNetGetLastErrorA
-0075 stub WNetGetLastErrorW
-0076 stub WNetGetNetworkInformationA
-0077 stub WNetGetNetworkInformationW
-0078 stub WNetGetProviderNameA
-0079 stub WNetGetProviderNameW
-0080 stdcall WNetGetResourceInformationA(ptr ptr ptr ptr) WNetGetResourceInformation32A
-0081 stub WNetGetResourceInformationW
-0082 stub WNetGetResourceParentA
-0083 stub WNetGetResourceParentW
-0084 stub WNetGetUniversalNameA
-0085 stub WNetGetUniversalNameW
-0086 stub WNetGetUserA
-0087 stub WNetGetUserW
-0088 stub WNetLogoffA
-0089 stub WNetLogoffW
-0090 stub WNetLogonA
-0091 stub WNetLogonW
-0092 stdcall WNetOpenEnumA(long long ptr ptr) WNetOpenEnum32A
-0093 stub WNetOpenEnumW
-0094 stub WNetRemoveCachedPassword
-0095 stub WNetRestoreConnectionA
-0096 stub WNetRestoreConnectionW
-0097 stub WNetSetConnectionA
-0098 stub WNetSetConnectionW
-0099 stub WNetUseConnectionA
-0100 stub WNetUseConnectionW
-0101 stub WNetVerifyPasswordA
-0102 stub WNetVerifyPasswordW 
+0001 stub MPR_1
+0002 stub MPR_2
+0003 stub MPR_3
+0004 stub MPR_4
+0005 stub MPR_5
+0006 stub MPR_6
+0007 stub MPR_7
+0008 stub MPR_8
+0009 stub MPR_9
+0010 stub DllCanUnloadNow
+0011 stub DllGetClassObject
+0012 stub MPR_12
+0013 stub MPR_13
+0014 stub MPR_14
+0015 stub MPR_15
+0016 stub MPR_16
+0017 stub MPR_17
+0018 stub MPR_18
+0019 stub MPR_19
+0020 stub MPR_20
+0021 stub MPR_21
+0022 stdcall MPR_22(long) _MPR_22
+0023 stub MPR_23
+0024 stub MPR_24
+0025 stdcall MPR_25(str long) _MPR_25
+0026 stdcall MultinetGetConnectionPerformanceA(ptr ptr) MultinetGetConnectionPerformance32A
+0027 stub MultinetGetConnectionPerformanceW
+0028 stub MultinetGetErrorTextA
+0029 stub MultinetGetErrorTextW
+0030 stub NPSAuthenticationDialogA
+0031 stub NPSCopyStringA
+0032 stub NPSDeviceGetNumberA
+0033 stub NPSDeviceGetStringA
+0034 stub NPSGetProviderHandleA
+0035 stub NPSGetProviderNameA
+0036 stub NPSGetSectionNameA
+0037 stub NPSNotifyGetContextA
+0038 stub NPSNotifyRegisterA
+0039 stub NPSSetCustomTextA
+0040 stub NPSSetExtendedErrorA
+0041 stub PwdChangePasswordA
+0042 stub PwdChangePasswordW
+0043 stub PwdGetPasswordStatusA
+0044 stub PwdGetPasswordStatusW
+0045 stub PwdSetPasswordStatusA
+0046 stub PwdSetPasswordStatusW
+0047 stdcall WNetAddConnection2A(ptr str str long) WNetAddConnection2_32A
+0048 stdcall WNetAddConnection2W(ptr wstr wstr long) WNetAddConnection2_32W
+0049 stdcall WNetAddConnection3A(long ptr str str long) WNetAddConnection3_32A
+0050 stdcall WNetAddConnection3W(long ptr wstr wstr long) WNetAddConnection3_32W
+0051 stdcall WNetAddConnectionA(str str str) WNetAddConnection32A
+0052 stdcall WNetAddConnectionW(wstr wstr wstr) WNetAddConnection32W
+0053 stdcall WNetCachePassword(str long str long long) WNetCachePassword
+0054 stub WNetCancelConnection2A
+0055 stub WNetCancelConnection2W
+0056 stub WNetCancelConnectionA
+0057 stub WNetCancelConnectionW
+0058 stub WNetCloseEnum
+0059 stub WNetConnectionDialog1A
+0060 stub WNetConnectionDialog1W
+0061 stub WNetConnectionDialog
+0062 stub WNetDisconnectDialog1A
+0063 stub WNetDisconnectDialog1W
+0064 stub WNetDisconnectDialog
+0065 stub WNetEnumCachedPasswords
+0066 stub WNetEnumResourceA
+0067 stub WNetEnumResourceW
+0068 stub WNetFormatNetworkNameA
+0069 stub WNetFormatNetworkNameW
+0070 stdcall WNetGetCachedPassword(ptr long ptr ptr long) WNetGetCachedPassword
+0071 stdcall WNetGetConnectionA(ptr ptr ptr) WNetGetConnection32A
+0072 stub WNetGetConnectionW
+0073 stub WNetGetHomeDirectoryA
+0074 stub WNetGetHomeDirectoryW
+0075 stub WNetGetLastErrorA
+0076 stub WNetGetLastErrorW
+0077 stub WNetGetNetworkInformationA
+0078 stub WNetGetNetworkInformationW
+0079 stub WNetGetProviderNameA
+0080 stub WNetGetProviderNameW
+0081 stdcall WNetGetResourceInformationA(ptr ptr ptr ptr) WNetGetResourceInformation32A
+0082 stub WNetGetResourceInformationW
+0083 stub WNetGetResourceParentA
+0084 stub WNetGetResourceParentW
+0085 stub WNetGetUniversalNameA
+0086 stub WNetGetUniversalNameW
+0087 stub WNetGetUserA
+0088 stub WNetGetUserW
+0089 stub WNetLogoffA
+0090 stub WNetLogoffW
+0091 stub WNetLogonA
+0092 stub WNetLogonW
+0093 stdcall WNetOpenEnumA(long long long ptr ptr) WNetOpenEnum32A
+0094 stub WNetOpenEnumW
+0095 stub WNetRemoveCachedPassword
+0096 stub WNetRestoreConnectionA
+0097 stub WNetRestoreConnectionW
+0098 stub WNetSetConnectionA
+0099 stub WNetSetConnectionW
+0100 stub WNetUseConnectionA
+0101 stub WNetUseConnectionW
+0102 stub WNetVerifyPasswordA
+0103 stub WNetVerifyPasswordW 
 #additions
-0103 stub WNetRestoreConnection
-0104 stub WNetLogonNotify
-0105 stub WNetPasswordChangeNotify
-0106 stub WNetGetPropertyTextA
-0107 stub WNetPropertyDialogA
-0108 stub WNetGetDirectoryTypeA
+0104 stub WNetRestoreConnection
+0105 stub WNetLogonNotify
+0106 stub WNetPasswordChangeNotify
+0107 stub WNetGetPropertyTextA
+0108 stub WNetPropertyDialogA
+0109 stub WNetGetDirectoryTypeA
diff --git a/relay32/ntdll.spec b/relay32/ntdll.spec
index 4e6bad6..d8aba3b 100644
--- a/relay32/ntdll.spec
+++ b/relay32/ntdll.spec
@@ -124,7 +124,7 @@
 121 stub NtMapViewOfSection
 122 stub NtNotifyChangeDirectoryFile
 123 stub NtNotifyChangeKey
-124 stub NtOpenDirectoryObject
+124 stdcall NtOpenDirectoryObject(long long long) NtOpenDirectoryObject
 125 stub NtOpenEvent
 126 stub NtOpenEventPair
 127 stdcall NtOpenFile(ptr long ptr ptr long long) NtOpenFile
@@ -149,7 +149,7 @@
 146 stub NtQueryAttributesFile
 147 stub NtQueryDefaultLocale
 148 stub NtQueryDirectoryFile
-149 stub NtQueryDirectoryObject
+149 stdcall NtQueryDirectoryObject(long long) NtQueryDirectoryObject
 150 stub NtQueryEaFile
 151 stub NtQueryEvent
 152 stub NtQueryInformationFile
@@ -161,14 +161,14 @@
 158 stub NtQueryIoCompletion
 159 stub NtQueryKey
 160 stub NtQueryMutant
-161 stub NtQueryObject
+161 stdcall NtQueryObject(long long) NtQueryObject
 162 stub NtQueryPerformanceCounter
 163 stub NtQuerySection
 164 stub NtQuerySecurityObject
 165 stub NtQuerySemaphore
 166 stub NtQuerySymbolicLinkObject
 167 stub NtQuerySystemEnvironmentValue
-168 stub NtQuerySystemInformation
+168 stdcall NtQuerySystemInformation(long) NtQuerySystemInformation
 169 stub NtQuerySystemTime
 170 stub NtQueryTimer
 171 stub NtQueryTimerResolution
@@ -207,7 +207,7 @@
 204 stub NtSetInformationFile
 205 stub NtSetInformationKey
 206 stub NtSetInformationObject
-207 stub NtSetInformationProcess
+207 stdcall NtSetInformationProcess(long) NtSetInformationProcess
 208 stub NtSetInformationThread
 209 stub NtSetInformationToken
 210 stub NtSetIntervalProfile
@@ -373,7 +373,7 @@
 370 stdcall RtlFirstFreeAce(ptr ptr) RtlFirstFreeAce
 371 stub RtlFormatCurrentUserKeyPath
 372 stub RtlFormatMessage
-373 stub RtlFreeAnsiString
+373 stdcall RtlFreeAnsiString(long) RtlFreeAnsiString
 374 stdcall RtlFreeHeap(long long long) HeapFree
 375 stub RtlFreeOemString
 376 stub RtlFreeSid
@@ -417,7 +417,7 @@
 414 stub RtlIsDosDeviceName_U
 415 stub RtlIsGenericTableEmpty
 416 stub RtlIsNameLegalDOS8Dot3
-417 stub RtlIsTextUnicode
+417 stdcall RtlIsTextUnicode(ptr long ptr) RtlIsTextUnicode
 418 stub RtlLargeIntegerAdd
 419 stub RtlLargeIntegerArithmeticShift
 420 stub RtlLargeIntegerDivide
@@ -502,7 +502,7 @@
 499 stub RtlSubtreeSuccessor
 500 stub RtlSystemTimeToLocalTime
 501 stub RtlTimeFieldsToTime
-502 stub RtlTimeToElapsedTimeFields
+502 stdcall RtlTimeToElapsedTimeFields(long) RtlTimeToElapsedTimeFields
 503 stub RtlTimeToSecondsSince1970
 504 stub RtlTimeToSecondsSince1980
 505 stub RtlTimeToTimeFields
@@ -936,7 +936,7 @@
 933 cdecl vsprintf(ptr str ptr) CRTDLL_vsprintf
 934 cdecl wcscat(wstr wstr) CRTDLL_wcscat
 935 cdecl wcschr(wstr long) CRTDLL_wcschr
-936 stub wcscmp
+936 cdecl wcscmp(wstr wstr) CRTDLL_wcscmp
 937 cdecl wcscpy(ptr wstr) CRTDLL_wcscpy
 938 stub wcscspn
 939 cdecl wcslen(wstr) CRTDLL_wcslen
diff --git a/relay32/relay386.c b/relay32/relay386.c
index bbe9933..612bbc5 100644
--- a/relay32/relay386.c
+++ b/relay32/relay386.c
@@ -40,30 +40,22 @@
     assert(TRACE_ON(relay));
     func = (FARPROC32)BUILTIN32_GetEntryPoint( buffer, relay_addr - 5,
                                                &typemask );
-    printf( "Call %s(", buffer );
+    DPRINTF( "Call %s(", buffer );
     args++;
     for (i = 0, mask = 3; i < nb_args; i++, mask <<= 2)
     {
-        if (i) printf( "," );
+        if (i) DPRINTF( "," );
 	if ((typemask & mask) && HIWORD(args[i]))
         {
 	    if (typemask & (2<<(2*i)))
-            {
-                char buff[80];
-                lstrcpynWtoA( buff, (LPWSTR)args[i], sizeof(buff) );
-		buff[sizeof(buff)-1]='\0';
-	    	printf( "%08x L", args[i] );
-		debug_dumpstr( buff );
-	    }
-            else {
-	    	printf( "%08x ", args[i] );
-		debug_dumpstr((LPCSTR)args[i]);
-	    }
+	    	DPRINTF( "%08x L%s", args[i], debugstr_w((LPWSTR)args[i]) );
+            else
+	    	DPRINTF( "%08x %s", args[i], debugstr_a((LPCSTR)args[i]) );
 	}
-        else printf( "%08x", args[i] );
+        else DPRINTF( "%08x", args[i] );
     }
     GET_FS( fs );
-    printf( ") ret=%08x fs=%04x\n", ret_addr, fs );
+    DPRINTF( ") ret=%08x fs=%04x\n", ret_addr, fs );
     if (*relay_addr == 0xc3) /* cdecl */
     {
         LRESULT (*cfunc)() = (LRESULT(*)())func;
@@ -100,7 +92,7 @@
                              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",
+            ERR(relay, "Unsupported nb args %d\n",
                      nb_args );
             assert(FALSE);
         }
@@ -140,13 +132,12 @@
                             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 );
+            ERR(relay, "Unsupported nb args %d\n",nb_args );
             assert(FALSE);
         }
     }
-    printf( "Ret  %s() retval=%08x ret=%08x fs=%04x\n",
-            buffer, ret, ret_addr, fs );
+    DPRINTF( "Ret  %s() retval=%08x ret=%08x fs=%04x\n",
+             buffer, ret, ret_addr, fs );
     return ret;
 }
 
@@ -220,11 +211,11 @@
 	EIP_reg(&context) = *(DWORD *)ESP_reg(&context);
 
         BUILTIN32_GetEntryPoint( buffer, relay_addr - 5, &typemask );
-        printf("Call %s(regs) ret=%08x\n", buffer, *(int *)ESP_reg(&context) );
-        printf(" EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx ESI=%08lx EDI=%08lx\n",
+        DPRINTF("Call %s(regs) ret=%08x\n", buffer, *(int *)ESP_reg(&context) );
+        DPRINTF(" 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",
+        DPRINTF(" 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) );
@@ -232,11 +223,11 @@
         /* Now call the real function */
         entry_point( &context );
 
-        printf("Ret  %s() retval=regs ret=%08x\n", buffer, *(int *)ESP_reg(&context) );
-        printf(" EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx ESI=%08lx EDI=%08lx\n",
+        DPRINTF("Ret  %s() retval=regs ret=%08x\n", buffer, *(int *)ESP_reg(&context) );
+        DPRINTF(" 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",
+        DPRINTF(" 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) );
diff --git a/relay32/shell32.spec b/relay32/shell32.spec
index c815d0c..703f574 100644
--- a/relay32/shell32.spec
+++ b/relay32/shell32.spec
@@ -10,7 +10,7 @@
    4 stub SHELL32_4
    5 stub SHELL32_5
    6 stub CheckEscapesW
-   7 stdcall CommandLineToArgvW(ptr ptr) CommandLineToArgvW
+   7 stdcall CommandLineToArgvW(wstr ptr) CommandLineToArgvW
    8 stub Control_FillCache_RunDLL
   12 stdcall Control_RunDLL(long long long long) Control_RunDLL
   14 stdcall DllGetClassObject(long long ptr) SHELL32_DllGetClassObject
@@ -50,7 +50,7 @@
   48 stub SHELL32_48
   49 stub SHELL32_49
   50 stub DragQueryFileA
-  51 stub SHELL32_51
+  51 stdcall SHELL32_51(str long long) SHELL32_51
   52 stdcall SHELL32_52(str) SHELL32_52
   53 stub DragQueryFileAorW
   54 stub DragQueryFileW
@@ -81,12 +81,12 @@
   79 stdcall SHELL32_79(str ptr) SHELL32_79
   80 stub DuplicateIcon
   81 stub SHELL32_81
-  82 stub ExtractAssociatedIconA
+  82 stdcall ExtractAssociatedIconA(long ptr long) ExtractAssociatedIcon32A
   83 stub SHELL32_83
   84 stub SHELL32_84
   85 stdcall SHELL32_85(long long long long) SHELL32_85
-  86 stub SHELL32_86
-  87 stub SHELL32_87
+  86 stdcall SHELL32_86(long ptr) SHELL32_86
+  87 stdcall SHELL32_87(long) SHELL32_87
   88 stub SHELL32_88
   89 stdcall SHELL32_89(long long long) SHELL32_89
   90 stub SHELL32_90
@@ -100,7 +100,7 @@
   98 stub SHELL32_98
   99 stub SHELL32_99
  100 stdcall SHELL32_100(long) SHELL32_100
- 101 stdcall ExtractAssociatedIconA(long ptr long) ExtractAssociatedIcon32A
+ 101 stub ExtractAssociatedIconExA
  102 stdcall SHELL32_102(ptr ptr long ptr ptr) SHELL32_102
  103 stub SHELL32_103
  104 stub SHELL32_104
@@ -242,9 +242,9 @@
  240 stub SheSetCurDrive
  241 stub SheShortenPathA
  242 stub SheShortenPathW
- 243 stdcall ShellAboutA(long ptr ptr long) ShellAbout32A
- 244 stdcall ShellAboutW(long ptr ptr long) ShellAbout32W
- 245 stdcall ShellExecuteA(long ptr ptr ptr ptr long) ShellExecute32A
+ 243 stdcall ShellAboutA(long str str long) ShellAbout32A
+ 244 stdcall ShellAboutW(long wstr wstr long) ShellAbout32W
+ 245 stdcall ShellExecuteA(long str str str str long) ShellExecute32A
  246 stub ShellExecuteEx
  247 stub ShellExecuteExA
  248 stub ShellExecuteW
diff --git a/relay32/user32.spec b/relay32/user32.spec
index 910a6a1..71e816c 100644
--- a/relay32/user32.spec
+++ b/relay32/user32.spec
@@ -262,7 +262,7 @@
 257 stdcall GetMenu(long) GetMenu32
 258 stdcall GetMenuCheckMarkDimensions() GetMenuCheckMarkDimensions
 259 stub GetMenuContextHelpId
-260 stub GetMenuDefaultItem
+260 stdcall GetMenuDefaultItem(long long long) GetMenuDefaultItem32
 261 stub GetMenuIndex
 262 stdcall GetMenuItemCount(long) GetMenuItemCount32
 263 stdcall GetMenuItemID(long long) GetMenuItemID32
@@ -417,7 +417,7 @@
 412 stub OpenWindowStationA
 413 stub OpenWindowStationW
 414 stub PackDDElParam
-415 stub PaintDesktop
+415 stdcall PaintDesktop(long) PaintDesktop
 416 stdcall PeekMessageA(ptr long long long long) PeekMessage32A
 417 stdcall PeekMessageW(ptr long long long long) PeekMessage32W
 418 stub PlaySoundEvent
diff --git a/relay32/winspool.spec b/relay32/winspool.spec
index be7721f..9e05933 100644
--- a/relay32/winspool.spec
+++ b/relay32/winspool.spec
@@ -7,7 +7,7 @@
 104 stub AddFormW
 105 stub AddJobA
 106 stub AddJobW
-107 stub AddMonitorA
+107 stdcall AddMonitorA(str long ptr) AddMonitor32A
 108 stub AddMonitorW
 109 stub AddPortA
 110 stub AddPortExA
@@ -66,7 +66,7 @@
 163 stub EnumJobsW
 164 stub EnumMonitorsA
 165 stub EnumMonitorsW
-166 stub EnumPortsA
+166 stdcall EnumPortsA(ptr long ptr ptr ptr ptr) EnumPorts32A
 167 stub EnumPortsW
 168 stub EnumPrintProcessorDatatypesA
 169 stub EnumPrintProcessorDatatypesW
diff --git a/relay32/wsock32.spec b/relay32/wsock32.spec
index 7dc4def..de18bce 100644
--- a/relay32/wsock32.spec
+++ b/relay32/wsock32.spec
@@ -33,11 +33,11 @@
 057 stdcall gethostname(ptr long) WINSOCK_gethostname32
 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
+103 stdcall WSAAsyncGetHostByName(long long str ptr long) WSAAsyncGetHostByName32
 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
+105 stdcall WSAAsyncGetProtoByName(long long str ptr long) WSAAsyncGetProtoByName32
+106 stdcall WSAAsyncGetServByPort(long long long str ptr long) WSAAsyncGetServByPort32
+107 stdcall WSAAsyncGetServByName(long long str str ptr long) WSAAsyncGetServByName32
 108 stdcall WSACancelAsyncRequest(long) WSACancelAsyncRequest32
 109 stdcall WSASetBlockingHook(ptr) WSASetBlockingHook32
 110 stdcall WSAUnhookBlockingHook() WSAUnhookBlockingHook32
@@ -53,15 +53,15 @@
 # ... as it is, they don't
 #1000 stub WSApSetPostRoutine
 1001 stdcall WsControl(long long ptr ptr ptr ptr) WsControl
-1100 stdcall inet_network(ptr) inet_network
-1101 stdcall getnetbyname(ptr) getnetbyname
+1100 stdcall inet_network(str) inet_network
+1101 stdcall getnetbyname(str) getnetbyname
 #1102 stub rcmd
 #1103 stub rexec
 #1104 stub rresvport
 #1105 stub sethostname
 #1106 stub dn_expand
 1107 stub WSARecvEx
-1108 stdcall s_perror(ptr) WS_s_perror
+1108 stdcall s_perror(str) WS_s_perror
 1109 stub GetAddressByNameA
 1110 stub GetAddressByNameW
 #1111 stub EnumProtocolsA
diff --git a/resources/Makefile.in b/resources/Makefile.in
index deaf256..8eb1b18 100644
--- a/resources/Makefile.in
+++ b/resources/Makefile.in
@@ -4,7 +4,8 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = resources
-RCFLAGS   = -w32
+#RCFLAGS   = -w32
+WRCEXTRA  = -p $*
 
 RC_SRCS = \
 	sysres_Ca.rc \
@@ -26,10 +27,10 @@
 
 C_SRCS = sysres.c
 
-all: check_winerc $(MODULE).o
+all: check_wrc $(MODULE).o
 
 @MAKE_RULES@
 
-$(RC_SRCS:.rc=.c): $(WINERC)
+$(RC_SRCS:.rc=.s): $(WRC)
 
 ### Dependencies:
diff --git a/resources/sysres.c b/resources/sysres.c
index 25c6d9f..3f3975d 100644
--- a/resources/sysres.c
+++ b/resources/sysres.c
@@ -8,42 +8,43 @@
 #include "global.h"
 #include "options.h"
 #include "resource.h"
+#include "wrc_rsc.h"
 
-extern const struct resource * const sysres_En_Table[];
-extern const struct resource * const sysres_Es_Table[];
-extern const struct resource * const sysres_De_Table[];
-extern const struct resource * const sysres_No_Table[];
-extern const struct resource * const sysres_Fr_Table[];
-extern const struct resource * const sysres_Fi_Table[];
-extern const struct resource * const sysres_Da_Table[];
-extern const struct resource * const sysres_Cz_Table[];
-extern const struct resource * const sysres_Eo_Table[];
-extern const struct resource * const sysres_It_Table[];
-extern const struct resource * const sysres_Ko_Table[];
-extern const struct resource * const sysres_Hu_Table[];
-extern const struct resource * const sysres_Pl_Table[];
-extern const struct resource * const sysres_Po_Table[];
-extern const struct resource * const sysres_Sw_Table[];
-extern const struct resource * const sysres_Ca_Table[];
+extern const wrc_resource32_t * const sysres_En_ResTable[];
+extern const wrc_resource32_t * const sysres_Es_ResTable[];
+extern const wrc_resource32_t * const sysres_De_ResTable[];
+extern const wrc_resource32_t * const sysres_No_ResTable[];
+extern const wrc_resource32_t * const sysres_Fr_ResTable[];
+extern const wrc_resource32_t * const sysres_Fi_ResTable[];
+extern const wrc_resource32_t * const sysres_Da_ResTable[];
+extern const wrc_resource32_t * const sysres_Cz_ResTable[];
+extern const wrc_resource32_t * const sysres_Eo_ResTable[];
+extern const wrc_resource32_t * const sysres_It_ResTable[];
+extern const wrc_resource32_t * const sysres_Ko_ResTable[];
+extern const wrc_resource32_t * const sysres_Hu_ResTable[];
+extern const wrc_resource32_t * const sysres_Pl_ResTable[];
+extern const wrc_resource32_t * const sysres_Po_ResTable[];
+extern const wrc_resource32_t * const sysres_Sw_ResTable[];
+extern const wrc_resource32_t * const sysres_Ca_ResTable[];
 
-static const struct resource * const * SYSRES_Resources[] =
+static const wrc_resource32_t * const * SYSRES_Resources[] =
 {
-    sysres_En_Table,  /* LANG_En */
-    sysres_Es_Table,  /* LANG_Es */
-    sysres_De_Table,  /* LANG_De */
-    sysres_No_Table,  /* LANG_No */
-    sysres_Fr_Table,  /* LANG_Fr */
-    sysres_Fi_Table,  /* LANG_Fi */
-    sysres_Da_Table,  /* LANG_Da */
-    sysres_Cz_Table,  /* LANG_Cz */
-    sysres_Eo_Table,  /* LANG_Eo */
-    sysres_It_Table,  /* LANG_It */
-    sysres_Ko_Table,  /* LANG_Ko */
-    sysres_Hu_Table,  /* LANG_Hu */
-    sysres_Pl_Table,  /* LANG_Pl */
-    sysres_Po_Table,  /* LANG_Po */
-    sysres_Sw_Table,  /* LANG_Sw */
-    sysres_Ca_Table   /* LANG_Ca */
+    sysres_En_ResTable,  /* LANG_En */
+    sysres_Es_ResTable,  /* LANG_Es */
+    sysres_De_ResTable,  /* LANG_De */
+    sysres_No_ResTable,  /* LANG_No */
+    sysres_Fr_ResTable,  /* LANG_Fr */
+    sysres_Fi_ResTable,  /* LANG_Fi */
+    sysres_Da_ResTable,  /* LANG_Da */
+    sysres_Cz_ResTable,  /* LANG_Cz */
+    sysres_Eo_ResTable,  /* LANG_Eo */
+    sysres_It_ResTable,  /* LANG_It */
+    sysres_Ko_ResTable,  /* LANG_Ko */
+    sysres_Hu_ResTable,  /* LANG_Hu */
+    sysres_Pl_ResTable,  /* LANG_Pl */
+    sysres_Po_ResTable,  /* LANG_Po */
+    sysres_Sw_ResTable,  /* LANG_Sw */
+    sysres_Ca_ResTable   /* LANG_Ca */
 };
 
 
@@ -54,7 +55,7 @@
  */
 LPCVOID SYSRES_GetResPtr( SYSTEM_RESOURCE id )
 {
-    return SYSRES_Resources[Options.language][id]->bytes;
+    return SYSRES_Resources[Options.language][id]->data;
 }
 
 
@@ -65,10 +66,10 @@
  */
 HGLOBAL16 SYSRES_LoadResource( SYSTEM_RESOURCE id )
 {
-    const struct resource *resPtr;
+    const wrc_resource32_t *resPtr;
 
     resPtr = SYSRES_Resources[Options.language][id];
-    return GLOBAL_CreateBlock( GMEM_FIXED, resPtr->bytes, resPtr->size,
+    return GLOBAL_CreateBlock( GMEM_FIXED, resPtr->data, resPtr->datasize,
 			       GetCurrentPDB(), FALSE, FALSE, TRUE, NULL );
 }
 
diff --git a/resources/sysres_Ca.rc b/resources/sysres_Ca.rc
index 6bcdaaf..fb4ae3a 100644
--- a/resources/sysres_Ca.rc
+++ b/resources/sysres_Ca.rc
@@ -1,3 +1,4 @@
+#include <windows.h>
 
 SYSMENU MENU LOADONCALL MOVEABLE DISCARDABLE
 {
diff --git a/resources/sysres_Cz.rc b/resources/sysres_Cz.rc
index 7718eda..5207288 100644
--- a/resources/sysres_Cz.rc
+++ b/resources/sysres_Cz.rc
@@ -1,3 +1,5 @@
+#include <windows.h>
+
 SYSMENU MENU LOADONCALL MOVEABLE DISCARDABLE
 {
  MENUITEM "&Obnov", 61728
diff --git a/resources/sysres_Da.rc b/resources/sysres_Da.rc
index ec99cd6..5f5651b 100644
--- a/resources/sysres_Da.rc
+++ b/resources/sysres_Da.rc
@@ -1,3 +1,5 @@
+#include <windows.h>
+
 SYSMENU MENU LOADONCALL MOVEABLE DISCARDABLE
 {
  MENUITEM "&Genopret", 61728
@@ -51,7 +53,7 @@
  LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER
  ICON "", 1088, 189, 10, 14, 16
  LTEXT "", 100, 8, 10, 137, 33
- LTEXT "Wine was brought to you by:", 98, 8, 55, 137, 10
+ LTEXT "Wine havde ikke været mulig uden hjælp fra disse personer:", 98, 8, 55, 137, 10
 }
 
 OPEN_FILE DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 275, 134
diff --git a/resources/sysres_De.rc b/resources/sysres_De.rc
index 3534338..16162e6 100644
--- a/resources/sysres_De.rc
+++ b/resources/sysres_De.rc
@@ -1,3 +1,5 @@
+#include <windows.h>
+
 SYSMENU MENU LOADONCALL MOVEABLE DISCARDABLE 
 {
  MENUITEM "&Wiederherstellen", 61728
diff --git a/resources/sysres_En.rc b/resources/sysres_En.rc
index 9501580..1838f4b 100644
--- a/resources/sysres_En.rc
+++ b/resources/sysres_En.rc
@@ -1,3 +1,6 @@
+#include <windows.h>
+#include <dlgs.h>
+
 SYSMENU MENU LOADONCALL MOVEABLE DISCARDABLE
 {
  MENUITEM "&Restore", 61728
@@ -33,7 +36,7 @@
 BEGIN
         ICON "", 1088, 8, 20, 16, 16, WS_CHILD | WS_VISIBLE
         LTEXT "", 100, 32, 4, 176, 48, WS_CHILD | WS_VISIBLE | WS_GROUP
-        PUSHBUTTON "&Ok", 1, 16, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+        PUSHBUTTON "&OK", 1, 16, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
         PUSHBUTTON "&Cancel", 2, 64, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
         PUSHBUTTON "&Abort", 3, 112, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
         PUSHBUTTON "&Retry", 4, 160, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
@@ -47,7 +50,7 @@
 CAPTION "About %s"
 FONT 10, "System"
 {
- DEFPUSHBUTTON "OK", 1, 153, 130, 50, 12
+ DEFPUSHBUTTON "OK", 1, 153, 130, 50, 12, WS_TABSTOP
  LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER
  ICON "", 1088, 189, 10, 14, 16
  LTEXT "", 100, 8, 10, 137, 33
@@ -131,7 +134,7 @@
  LTEXT "[none]", 1088, 35, 35, 120, 9
  RADIOBUTTON "Specific &Printer", 1057, 16, 50, 80, 12
  COMBOBOX 1136, 35, 65, 149, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP
- DEFPUSHBUTTON "Ok", 1, 206, 6, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
+ DEFPUSHBUTTON "OK", 1, 206, 6, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
  PUSHBUTTON "Cancel", 2, 206, 24, 56, 14, WS_GROUP | WS_TABSTOP
  PUSHBUTTON "&Setup", 1024, 206, 46, 56, 14, WS_GROUP | WS_TABSTOP
  GROUPBOX "Orientation", 1073, 6, 85, 100, 50, BS_GROUPBOX
@@ -161,10 +164,10 @@
     LTEXT           "&Size:",1090,179,3,30,9
     COMBOBOX        1138,179,13,32,54, CBS_OWNERDRAWFIXED | CBS_HASSTRINGS | CBS_DISABLENOSCROLL |
                     WS_VSCROLL | WS_TABSTOP | CBS_SIMPLE | CBS_SORT
-    DEFPUSHBUTTON   "OK",IDOK,218,6,40,14,WS_GROUP
-    PUSHBUTTON      "Cancel",IDCANCEL,218,23,40,14,WS_GROUP
-    PUSHBUTTON      "&Apply", 1026,218,40,40,14,WS_GROUP
-    PUSHBUTTON      "&Help" , 1038,218,57,40,14,WS_GROUP
+    DEFPUSHBUTTON   "OK",IDOK,218,6,40,14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON 
+    PUSHBUTTON      "Cancel",IDCANCEL,218,23,40,14,WS_GROUP | WS_TABSTOP
+    PUSHBUTTON      "&Apply", 1026,218,40,40,14,WS_GROUP | WS_TABSTOP
+    PUSHBUTTON      "&Help" , 1038,218,57,40,14,WS_GROUP | WS_TABSTOP
     GROUPBOX        "Effects",1072,6,72,84,34,WS_GROUP
     CHECKBOX	    "Stri&keout", 1040, 10,82,50,10, BS_AUTOCHECKBOX | WS_TABSTOP
     CHECKBOX 	    "&Underline", 1041, 10,94,50,10, BS_AUTOCHECKBOX 
@@ -201,7 +204,7 @@
  CONTROL "" ,710,"STATIC",WS_BORDER|SS_SIMPLE|WS_TABSTOP|WS_GROUP, 152,4,118,116
  CONTROL "" ,702,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP, 278,4,8,116
  CONTROL "" ,709,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP, 152,124,40,26
- DEFPUSHBUTTON "Ok",  1,  4, 166, 44, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
+ DEFPUSHBUTTON "OK",  1,  4, 166, 44, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
  PUSHBUTTON "Cancel", 2, 52, 166, 44, 14, WS_GROUP | WS_TABSTOP
  PUSHBUTTON "Help", 1038,100,166, 44, 14
  PUSHBUTTON "&Add to Custom Colors",    712/*1024*/, 152, 166, 142, 14, WS_GROUP | WS_TABSTOP
@@ -222,9 +225,10 @@
  GROUPBOX "Direction", 1072, 107, 26, 68, 28
  CONTROL "&Up", 1056, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 111, 38, 20, 12
  CONTROL "&Down", 1057, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 138, 38, 30, 12
- DEFPUSHBUTTON "&Find Next", 1, 182, 5, 50, 14, WS_GROUP | WS_TABSTOP
- PUSHBUTTON "Cancel", 2, 182, 23, 50, 14, WS_GROUP | WS_TABSTOP
- PUSHBUTTON "&Help", 1038, 182, 45, 50, 14, WS_GROUP | WS_TABSTOP
+
+ DEFPUSHBUTTON "&Find Next", IDOK, 182,  5, 50, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON 
+ PUSHBUTTON "Cancel", IDCANCEL	 , 182, 23, 50, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "&Help", pshHelp	 , 182, 45, 50, 14, WS_GROUP | WS_TABSTOP
 }
 
 
@@ -239,9 +243,10 @@
  EDITTEXT 1153, 54, 24, 114, 12, ES_AUTOHSCROLL | WS_BORDER | WS_GROUP | WS_TABSTOP
  CHECKBOX "Match &Whole Word Only", 1040, 5, 46, 104, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
  CHECKBOX "Match &Case", 1041, 5, 62, 59, 12, BS_AUTOCHECKBOX | WS_TABSTOP
- DEFPUSHBUTTON "&Find Next", 1, 174, 4, 50, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
- PUSHBUTTON "&Replace", 1024, 174, 21, 50, 14, WS_GROUP | WS_TABSTOP
- PUSHBUTTON "Replace &All", 1025, 174, 38, 50, 14, WS_GROUP | WS_TABSTOP
- PUSHBUTTON "Cancel", 2, 174, 55, 50, 14, WS_GROUP | WS_TABSTOP
- PUSHBUTTON "&Help", 1038, 174, 75, 50, 14, WS_GROUP | WS_TABSTOP
+
+ DEFPUSHBUTTON "&Find Next", IDOK, 174,  4, 50, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON 
+ PUSHBUTTON "&Replace", psh1	 , 174, 21, 50, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Replace &All", psh2 , 174, 38, 50, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Cancel", IDCANCEL	 , 174, 55, 50, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "&Help", pshHelp	 , 174, 75, 50, 14, WS_GROUP | WS_TABSTOP
 }
diff --git a/resources/sysres_Eo.rc b/resources/sysres_Eo.rc
index 2fa6e80..a17069b 100644
--- a/resources/sysres_Eo.rc
+++ b/resources/sysres_Eo.rc
@@ -1,3 +1,5 @@
+#include <windows.h>
+
 SYSMENU MENU LOADONCALL MOVEABLE DISCARDABLE
 {
  MENUITEM "&Renormaligu", 61728
diff --git a/resources/sysres_Es.rc b/resources/sysres_Es.rc
index 387d8bb..fc1b4b8 100644
--- a/resources/sysres_Es.rc
+++ b/resources/sysres_Es.rc
@@ -1,3 +1,5 @@
+#include <windows.h>
+
 
 SYSMENU MENU LOADONCALL MOVEABLE DISCARDABLE
 {
diff --git a/resources/sysres_Fi.rc b/resources/sysres_Fi.rc
index 369873c..128d621 100644
--- a/resources/sysres_Fi.rc
+++ b/resources/sysres_Fi.rc
@@ -1,3 +1,5 @@
+#include <windows.h>
+
 SYSMENU MENU LOADONCALL MOVEABLE DISCARDABLE
 {
  MENUITEM "&Palauta", 61728
diff --git a/resources/sysres_Fr.rc b/resources/sysres_Fr.rc
index 4fa9535..5bd3304 100644
--- a/resources/sysres_Fr.rc
+++ b/resources/sysres_Fr.rc
@@ -1,3 +1,5 @@
+#include <windows.h>
+
 
 SYSMENU MENU LOADONCALL MOVEABLE DISCARDABLE
 {
diff --git a/resources/sysres_Hu.rc b/resources/sysres_Hu.rc
index 66cf281..91eca64 100644
--- a/resources/sysres_Hu.rc
+++ b/resources/sysres_Hu.rc
@@ -1,3 +1,5 @@
+#include <windows.h>
+
 SYSMENU MENU LOADONCALL MOVEABLE DISCARDABLE
 BEGIN
  MENUITEM "&Visszaállítás", 61728
diff --git a/resources/sysres_It.rc b/resources/sysres_It.rc
index bd78672..3b387af 100644
--- a/resources/sysres_It.rc
+++ b/resources/sysres_It.rc
@@ -1,3 +1,5 @@
+#include <windows.h>
+
 SYSMENU MENU LOADONCALL MOVEABLE DISCARDABLE
 {
  MENUITEM "&Ripristina", 61728
diff --git a/resources/sysres_Ko.rc b/resources/sysres_Ko.rc
index 7810c12..544733e 100644
--- a/resources/sysres_Ko.rc
+++ b/resources/sysres_Ko.rc
@@ -1,3 +1,5 @@
+#include <windows.h>
+
 SYSMENU MENU LOADONCALL MOVEABLE DISCARDABLE
 {
  MENUITEM "º¹±Í(&R)", 61728
diff --git a/resources/sysres_No.rc b/resources/sysres_No.rc
index 5850bf1..0181b98 100644
--- a/resources/sysres_No.rc
+++ b/resources/sysres_No.rc
@@ -1,3 +1,5 @@
+#include <windows.h>
+
 SYSMENU MENU LOADONCALL MOVEABLE DISCARDABLE
 {
  MENUITEM "&Gjenopprett", 61728
diff --git a/resources/sysres_Pl.rc b/resources/sysres_Pl.rc
index 80260bc..e28b3a2 100644
--- a/resources/sysres_Pl.rc
+++ b/resources/sysres_Pl.rc
@@ -1,3 +1,5 @@
+#include <windows.h>
+
 SYSMENU MENU LOADONCALL MOVEABLE DISCARDABLE
 {
 	MENUITEM "&Przywróæ", 61728
diff --git a/resources/sysres_Po.rc b/resources/sysres_Po.rc
index 200b8d2..d0ca54b 100644
--- a/resources/sysres_Po.rc
+++ b/resources/sysres_Po.rc
@@ -1,3 +1,5 @@
+#include <windows.h>
+
 SYSMENU MENU LOADONCALL MOVEABLE DISCARDABLE
 {
  MENUITEM "&Restaurar", 61728
diff --git a/resources/sysres_Sw.rc b/resources/sysres_Sw.rc
index af9ba49..b5b40ee 100644
--- a/resources/sysres_Sw.rc
+++ b/resources/sysres_Sw.rc
@@ -1,3 +1,5 @@
+#include <windows.h>
+
 SYSMENU MENU LOADONCALL MOVEABLE DISCARDABLE
 {
  MENUITEM "&Återställ", 61728
diff --git a/scheduler/critsection.c b/scheduler/critsection.c
index 9c92351..4893712 100644
--- a/scheduler/critsection.c
+++ b/scheduler/critsection.c
@@ -15,6 +15,7 @@
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/sem.h>
+#include "debug.h"
 #include "windows.h"
 #include "winerror.h"
 #include "winbase.h"
@@ -102,7 +103,7 @@
     if (obj)
     {
         if (crit->RecursionCount)  /* Should not happen */
-            fprintf( stderr, "Deleting owned critical section (%p)\n", crit );
+            MSG("Deleting owned critical section (%p)\n", crit );
         crit->LockCount      = -1;
         crit->RecursionCount = 0;
         crit->OwningThread   = 0;
@@ -156,7 +157,7 @@
         }
         else
         {
-            fprintf( stderr, "Uninitialized critical section (%p)\n", crit );
+            MSG( "Uninitialized critical section (%p)\n", crit );
             return;
         }
     }
diff --git a/scheduler/handle.c b/scheduler/handle.c
index e6630aa..72b301d 100644
--- a/scheduler/handle.c
+++ b/scheduler/handle.c
@@ -6,6 +6,7 @@
 
 #include <assert.h>
 #include <stdio.h>
+#include "debug.h"
 #include "winbase.h"
 #include "winerror.h"
 #include "heap.h"
@@ -150,7 +151,7 @@
     {
         HANDLE_ENTRY *entry = &pdb->handle_table->entries[handle];
         if ((entry->access & access) != access)
-            fprintf( stderr, "Warning: handle %08x bad access (acc=%08lx req=%08lx)\n",
+            WARN(win32, "Handle %08x bad access (acc=%08lx req=%08lx)\n",
                      handle, entry->access, access );
         ptr = entry->ptr;
         if (ptr && ((type == K32OBJ_UNKNOWN) || (ptr->type == type)))
diff --git a/scheduler/process.c b/scheduler/process.c
index 361875e..2254d63 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -6,11 +6,11 @@
 
 #include <assert.h>
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include "process.h"
 #include "module.h"
 #include "file.h"
+#include "global.h"
 #include "heap.h"
 #include "task.h"
 #include "ldt.h"
@@ -209,7 +209,6 @@
  */
 BOOL32 PROCESS_Init(void)
 {
-    extern BOOL32 VIRTUAL_Init(void);
     extern BOOL32 THREAD_InitDone;
     PDB32 *pdb;
     THDB *thdb;
@@ -224,6 +223,7 @@
     /* Create the initial process and thread structures */
     if (!(pdb = PROCESS_CreatePDB( NULL ))) return FALSE;
     if (!(thdb = THREAD_Create( pdb, 0, FALSE, NULL, NULL ))) return FALSE;
+    thdb->unix_pid = getpid();
     SET_CUR_THREAD( thdb );
     THREAD_InitDone = TRUE;
 
@@ -278,6 +278,8 @@
         size = 0;
     if (!(thdb = THREAD_Create( pdb, size, FALSE, NULL, NULL ))) goto error;
 
+    thdb->unix_pid = getpid(); /* FIXME: wrong here ... */
+
     /* Create a Win16 task for this process */
 
     pdb->task = TASK_Create( thdb, pModule, hInstance, hPrevInstance, cmdShow);
@@ -451,7 +453,7 @@
     	pdb->priority = 0x00000018;
     	break;
     default:
-    	fprintf(stderr,"SetPriorityClass: unknown priority class %ld\n",priorityclass);
+    	WARN(process,"Unknown priority class %ld\n",priorityclass);
 	break;
     }
     K32OBJ_DecCount( &pdb->header );
@@ -483,7 +485,7 @@
 	    ret = REALTIME_PRIORITY_CLASS;
 	    break;
 	default:
-	    fprintf(stderr,"GetPriorityClass: unknown priority %ld\n",pdb->priority);
+	    WARN(process,"Unknown priority %ld\n",pdb->priority);
 	}
 	K32OBJ_DecCount( &pdb->header );
     }
@@ -588,10 +590,8 @@
 BOOL32 WINAPI SetProcessWorkingSetSize(HANDLE32 hProcess,DWORD minset,
                                        DWORD maxset)
 {
-	fprintf(stderr,"SetProcessWorkingSetSize(0x%08x,%ld,%ld), STUB!\n",
-		hProcess,minset,maxset
-	);
-	return TRUE;
+    FIXME(process,"(0x%08x,%ld,%ld): stub\n",hProcess,minset,maxset);
+    return TRUE;
 }
 
 /***********************************************************************
@@ -600,9 +600,7 @@
 BOOL32 WINAPI GetProcessWorkingSetSize(HANDLE32 hProcess,LPDWORD minset,
                                        LPDWORD maxset)
 {
-	fprintf(stderr,"SetProcessWorkingSetSize(0x%08x,%p,%p), STUB!\n",
-		hProcess,minset,maxset
-	);
+	FIXME(process,"(0x%08x,%p,%p): stub\n",hProcess,minset,maxset);
 	/* 32 MB working set size */
 	if (minset) *minset = 32*1024*1024;
 	if (maxset) *maxset = 32*1024*1024;
@@ -614,10 +612,8 @@
  */
 BOOL32 WINAPI SetProcessShutdownParameters(DWORD level,DWORD flags)
 {
-	fprintf(stderr,"SetProcessShutdownParameters(%ld,0x%08lx), STUB!\n",
-		level,flags
-	);
-	return TRUE;
+    FIXME(process,"(%ld,0x%08lx): stub\n",level,flags);
+    return TRUE;
 }
 
 /***********************************************************************
@@ -654,7 +650,7 @@
  */
 HANDLE32 WINAPI ConvertToGlobalHandle(HANDLE32 h)
 {
-	fprintf(stderr,"ConvertToGlobalHandle(%d),stub!\n",h);
+	FIXME(process,"(%d): stub\n",h);
 	return h;
 }
 
diff --git a/scheduler/synchro.c b/scheduler/synchro.c
index 0220503..bb4a110 100644
--- a/scheduler/synchro.c
+++ b/scheduler/synchro.c
@@ -6,7 +6,6 @@
 
 #include <assert.h>
 #include <signal.h>
-#include <stdio.h>
 #include <sys/time.h>
 #include <unistd.h>
 #include "k32obj.h"
@@ -245,7 +244,10 @@
         if (SYNC_CheckCondition( &thdb->wait_struct, THDB_TO_THREAD_ID(thdb) ))
         {
             TRACE(win32, "waking up %04x\n", thdb->teb_sel );
-            kill( thdb->unix_pid, SIGUSR1 );
+            if (thdb->unix_pid)
+	    	kill( thdb->unix_pid, SIGUSR1 );
+	    else
+	    	FIXME(win32,"have got unix_pid 0\n");
             if (!--max) break;
         }
         if (entry == *wait_queue) break;
@@ -300,8 +302,7 @@
     }
 
     if (alertable)
-        fprintf( stderr,
-                 "WaitForMultipleObjectEx: alertable not implemented\n" );
+        FIXME(win32, "alertable not implemented\n" );
 
     SYSTEM_LOCK();
     if (!SYNC_BuildWaitStruct( count, handles, wait_all, wait ))
diff --git a/scheduler/sysdeps.c b/scheduler/sysdeps.c
index b1a7c56..8599c5f 100644
--- a/scheduler/sysdeps.c
+++ b/scheduler/sysdeps.c
@@ -99,7 +99,7 @@
                CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, thread ) < 0)
         return -1;
 #else
-    fprintf( stderr, "CreateThread: stub\n" );
+    FIXME(thread, "CreateThread: stub\n" );
 #endif  /* __linux__ */
     return 0;
 }
diff --git a/scheduler/thread.c b/scheduler/thread.c
index 5e065ff..e9d27b1 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -5,7 +5,6 @@
  */
 
 #include <assert.h>
-#include <stdio.h>
 #include <signal.h>
 #include <unistd.h>
 #include "thread.h"
@@ -167,7 +166,7 @@
     if (stack_size<1024*1024)
     	stack_size = 1024 * 1024;
     if (stack_size >= 16*1024*1024)
-    	fprintf(stderr,"Warning:Thread stack size is %ld MB.\n",stack_size/1024/1024);
+    	WARN(thread,"Thread stack size is %ld MB.\n",stack_size/1024/1024);
     thdb->stack_base = VirtualAlloc(NULL,
                                     stack_size + (alloc_stack16 ? 0x10000 : 0),
                                     MEM_COMMIT, PAGE_EXECUTE_READWRITE );
@@ -566,6 +565,24 @@
 
 
 /***********************************************************************
+ * SetThreadContext [KERNEL32.670]  Sets context of thread.
+ *
+ * RETURNS
+ *    Success: TRUE
+ *    Failure: FALSE
+ */
+BOOL32 WINAPI SetThreadContext(
+    HANDLE32 handle,  /* [in]  Handle to thread with context */
+    CONTEXT *context) /* [out] Address of context structure */
+{
+    THDB *thread = THREAD_GetPtr( handle, THREAD_GET_CONTEXT );
+    if (!thread) return FALSE;
+    *context = thread->context;
+    K32OBJ_DecCount( &thread->header );
+    return TRUE;
+}
+
+/***********************************************************************
  * GetThreadContext [KERNEL32.294]  Retrieves context of thread.
  *
  * RETURNS
diff --git a/tools/build.c b/tools/build.c
index 319b6e7..bc36294 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -971,7 +971,7 @@
 static int BuildSpec32File( char * specfile, FILE *outfile )
 {
     ORDDEF *odp;
-    int i, nb_names, nb_reg_funcs = 0;
+    int i, nb_names;
 
     fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n\n",
              specfile );
@@ -988,6 +988,25 @@
                  i, DLLName, i );
     }
 
+    /* Output code for all register functions */
+
+    fprintf( outfile, "#ifdef __i386__\n" );
+    for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
+    {
+        if (odp->type != TYPE_REGISTER) continue;
+        fprintf( outfile,
+                 "__asm__(\".align 4\\n\\t\"\n"
+                 "        \".globl " PREFIX "%s\\n\\t\"\n"
+                 "        \".type " PREFIX "%s,@function\\n\\t\"\n"
+                 "        \"%s:\\n\\t\"\n"
+                 "        \"pushl $" PREFIX "__regs_%s\\n\\t\"\n"
+                 "        \"pushl $" PREFIX "CALL32_Regs\\n\\t\"\n"
+                 "        \"ret\");\n",
+                 odp->u.func.link_name, odp->u.func.link_name,
+                 odp->u.func.link_name, odp->u.func.link_name );
+    }
+    fprintf( outfile, "#endif\n" );
+
     /* Output the DLL functions prototypes */
 
     for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
@@ -1106,7 +1125,6 @@
             break;
         case TYPE_REGISTER:
             args = 0xfe;
-            nb_reg_funcs++;
             break;
         default:
             args = 0xff;
@@ -1125,7 +1143,6 @@
     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"
diff --git a/tools/makedep.c b/tools/makedep.c
index 11f77d3..c45eb0c 100644
--- a/tools/makedep.c
+++ b/tools/makedep.c
@@ -279,7 +279,7 @@
         else if (!strcmp( ext, ".rc" ))  /* resource file */
         {
             *ext = '\0';
-            fprintf( file, "%s.c %s.h: %s", obj, obj, pFile->filename );
+            fprintf( file, "%s.s: %s", obj, pFile->filename );
             *column += 2 * strlen(obj) + strlen(pFile->filename) + 7;
         }
         else
diff --git a/tools/testrun b/tools/testrun
new file mode 100755
index 0000000..499e134
--- /dev/null
+++ b/tools/testrun
@@ -0,0 +1,274 @@
+#!/usr/bin/perl
+# Copyright 1996-1998 Marcus Meissner
+# IPC remove code Copyright 1995 Michael Veksler
+#
+# This perl script automatically test runs ALL windows .exe and .scr binaries
+# it finds (and can access) on your computer. It creates a subdirectory called
+# runs/ and stores the output there. It also does (unique) diffs between runs.
+#
+# It only reruns the test if ChangeLog or the executeable is NEWER than the
+# run file. (If you want to rerun everything inbetween releases, touch
+# ChangeLog.)
+
+#
+# BEGIN OF USER CONFIGURATION
+#
+# Path to WINE executeable. If not specified, 'wine' is searched in the path.
+#
+$wine = 'wine';
+#
+# WINE options. -managed when using a windowmanager is probably not good in
+# automatic testruns.
+#
+$wineoptions='';
+#
+# Path to WINE ChangeLog. Used as timestamp for new releases...
+#
+$changelog = '/home/marcus/wine/ChangeLog';
+# 
+# How long before automatically killing all subprocesses
+# 30 is good for automatic testing, 300 or more for interactive testing.
+#
+$waittime = 30;
+#
+#diff command
+#
+$diff='diff -u';
+#
+# truncate at how-much-lines
+#
+$trunclines=200;
+#
+$<||die "Running this script under UID 0 is a great security risk (and risk for existing windows installations on mounted DOS/W95 partitions). If you really want to, comment out this line.\n";
+#
+# END OF USER CONFIGURATION
+#
+
+if (! -d "runs") { die "no subdirectory runs/ found in $cwd. Please create one first!\n";}
+
+# look for the exact path to wine executeable in case we need it for a 
+# replacement changelog.
+if (! ($wine =~ /\//)) { # no path specified. Look it up.
+	@paths = split(/:/,$ENV{'PATH'});
+	foreach $path (@paths) {
+		if (-e "$path/$wine" && -x "$path/$wine") {
+			$wine = "$path/$wine";
+			last;
+		}
+	}
+}
+
+# if we don't have a changelog use the modification date of the WINE executeable
+if (! -e $changelog) {
+	$changelog = $wine;
+}
+
+# sanity check so we just fill runs/ with errors.
+(-x $wine)  || die "no $wine executable found!\n";
+# dito. will print usage
+system("$wine -h >/dev/null")||die "wine call failed:$!\n";
+
+print "Using $wine as WINE executeable.\n";
+print "Using $changelog as testrun timereference.\n";
+
+chomp($cwd = `pwd`);
+
+# Find out all present semaphores so we don't remove them later.
+$IPC_RMID=0;
+$USER=$ENV{'USER'};
+open(IPCS,"ipcs|");
+while(<IPCS>) {
+    split;
+    # try to find out the IPC-ID, assume it is the first number.
+    foreach (@_) {
+	$_ ne int($_) && next;	# not a decimal number
+	$num=$_;
+	last;
+    }
+    if (/sem/i .. /^\s*$/ ) {
+	index($_,$USER)>=0 || next;
+	$sem_used{$num}=1;
+	print "found $num\n";
+    }
+}
+close(IPCS);
+
+sub kill_subprocesses {
+	local($killedalready,%parentof,%kids,$changed,%cmdline);
+
+	# FIXME: Linux ps dependend...
+	#
+	open(PSAUX,"ps --format pid,ppid,comm|");
+	# lookup all processes, remember their parents and cmdlines.
+	%parentof=();
+	while (<PSAUX>) {
+		if (/\s*(\d*)\s*(\d*)\s*(\S*)/) {
+			$parentof{$1}=$2;
+			$cmdline{$1}=$3;
+		}
+	}
+	close(PSAUX);
+
+	# find out all kids of this perlscript
+	%kids = ();
+	$kids{$$} = 1;
+	$changed = 1;
+	while ($changed) {
+		$changed = 0;
+		foreach (keys %parentof) {
+			next if ($kids{$_});
+			if ($kids{$parentof{$_}}) {
+				$changed = 1;
+				$kids{$_}=1;
+			}
+		}
+	}
+	# .. but do not consider us for killing
+	delete $kids{$$};
+	# remove all processes killed in the meantime from %killedalready.
+	foreach $pid (keys %killedalready) {
+		delete $killedalready{$pid} if (!$kids{$pid} );
+	}
+	# kill all subprocesses called 'wine'. Do not kill find, diff, sh
+	# and friends, which are also subprocesses of us.
+	foreach (keys %kids) {
+		next unless ($cmdline{$_} =~ /wine/);
+		# if we have already killed it using -TERM, use -KILL
+		if ($killedalready{$_}) {
+			kill(9,$_);	# FIXME: use correct number?
+		} else {
+			kill(15,$_);	# FIXME: use correct number?
+		}
+		$killedalready{$_}=1;
+	}
+	alarm($waittime);		# wait again...
+};
+
+# borrowed from tools/ipcl. See comments there.
+# killing wine subprocesses unluckily leaves all of their IPC stuff lying
+# around. We have to wipe it or we run out of it.
+sub cleanup_wine_ipc {
+	open(IPCS,"ipcs|");
+	while(<IPCS>) {
+	    split;
+	    # try to find out the IPC-ID, assume it is the first number.
+	    foreach (@_) {
+		$_ ne int($_) && next;	# not a decimal number
+		$num=$_;
+		last;
+	    }
+	    # was there before start of this script, skip it.
+	    #
+	    # FIXME: this doesn't work for programs started during the testrun.
+	    #
+	    if (/sem/i .. /^\s*$/ ) {
+		index($_,$USER)>=0 || next;
+		push(@sem,$num);
+	    }
+	}
+	foreach (@sem) {
+	    $sem_used{$_} && next;
+	    semctl($_, 0, $IPC_RMID,0);
+	}
+	close(IPCS);
+}
+
+# kill all subwineprocesses for automatic runs.
+sub alarmhandler {
+	print "timer triggered.\n";
+	&kill_subprocesses;
+}
+
+$SIG{'ALRM'} = "alarmhandler";
+
+# NOTE: following find will also cross NFS mounts, so be sure to have nothing
+# mounted that's not on campus or add relevant ! -fstype nfs or similar.
+#
+
+open(FIND,"find / -type f  \\( -name \"*.EXE\" -o -name \"*.exe\" -o -name \"*.scr\" -o -name \"*.SCR\" \\) -print|");
+while ($exe=<FIND>) {
+	chop($exe);
+
+	# This could change during a testrun (by doing 'make' for instance)
+	# FIXME: doesn't handle missing libwine.so during compile...
+	(-x $wine)  || die "no $wine executable found!\n";
+
+	# Skip all mssetup, acmsetup , installshield whatever exes. 
+	# they seem to work, mostly and starting them is just annoying.
+	next if ($exe =~ /acmsetup/);
+	next if ($exe =~ /unwise/);
+	next if ($exe =~ /testexit/);
+	next if ($exe =~ /_msset/);
+	next if ($exe =~ /isun/i);
+	next if ($exe =~ /st4u/);
+	next if ($exe =~ /st5u/);
+	next if ($exe =~ /_mstest/);
+	next if ($exe =~ /_isdel/);
+	next if ($exe =~ /ms-setup/);
+	next if ($exe =~ /~mss/);
+	next if ($exe =~ /unin/);
+
+	$runfile = $exe;
+	$runfile =~ s/[\/ ]/_/g;
+	$runfile =~ s/\.exe$//g;
+	$runfile =~ s/\.scr$//ig;
+	$flag=0;
+	#
+	# Check if changelog is newer, if not, continue
+	#
+	if (	-e "runs/${runfile}.out" && 
+		(-M $changelog > -M "runs/${runfile}.out") && 
+		(-M $exe > -M "runs/${runfile}.out")
+	) {
+		#print "skipping $exe, already done.\n";
+		next;
+	}
+
+	# check runfile if the exe is a DOS executeable or 
+	# of different architecture (win32)
+	if (open(RUNFILE,"runs/$runfile.out")) {
+		while ($xrun=<RUNFILE>) {
+			chop($xrun);
+			if ($xrun=~ /LoadModule:.*error=11$/) {
+				$flag=1;
+				last;
+			}
+			if ($xrun=~ /LoadModule:.*error=21$/) {
+				$flag=2;
+				last;
+			}
+		}
+		close(RUNFILE);
+		if ($flag==1) {
+			#print "skipping $exe, seems to be a DOS executable.\n";
+			next;
+		}
+		if ($flag==2) {
+			#print "skipping $exe, seems to be a non i386 executable.\n";
+			next;
+		}
+	}
+	# now testrun...
+	print "$exe:\n";
+	$dir = $exe;
+	$dir =~ s/^(.*)\/[^\/]*$/$1/; #cut of the basename.
+
+	alarm($waittime);
+
+	chdir($dir)||die "$dir:$!";
+	if ($exe =~ /\.scr/i) {
+		system("echo quit|$wine $wineoptions \"$exe /s\" >$cwd/${runfile}.out 2>&1");
+	} else {
+		system("echo quit|$wine $wineoptions \"$exe\" >$cwd/${runfile}.out 2>&1");
+	}
+	alarm(1000);# so it doesn't trigger in the diff, kill or find.
+
+	system("touch $cwd/runs/${runfile}.out");
+	system("$diff $cwd/runs/${runfile}.out $cwd/${runfile}.out");
+	system("head -$trunclines $cwd/${runfile}.out >$cwd/runs/${runfile}.out");
+	unlink("$cwd/${runfile}.out");
+	&kill_subprocesses;
+	&cleanup_wine_ipc;
+	chdir($cwd);
+}
+close(FIND);
diff --git a/tools/unimap.pl b/tools/unimap.pl
new file mode 100644
index 0000000..0b3282f
--- /dev/null
+++ b/tools/unimap.pl
@@ -0,0 +1,121 @@
+#!/usr/bin/perl
+#
+# Reads the Unicode 2.0 "unidata2.txt" file and selects encodings
+# for case pairs, then builds an include file "casemap.h" for the
+# case conversion routines. 
+
+use integer
+
+$INFILE	= "unidata2.txt";
+$OUT	= ">casemap.h";
+$TEST	= ">allcodes";
+
+# Open the data file ...
+open INFILE	or die "Can't open input file $INFILE!\n";
+open OUT	or die "Can't open output file $OUT!\n";
+open TEST	or die "Can't open output file $OUT!\n";
+
+#Initialize the upper and lower hashes
+%lwrtable = ();
+%uprtable = ();
+@low = ("0") x 256;
+@upr = ("0") x 256;
+
+while ($line = <INFILE> )
+{
+	# Decode the fields ...
+	($code, $name, $cat, $comb, $bidi, 
+	 $decomp, $dec, $dig, $num, $mirror, 
+	 $oldname, $comment, $upper, $lower, $title) = split /;/, $line;
+
+	#Get the high byte of the code
+	$high = substr $code, 0, 2;
+	if ($lower ne "") {
+		$low[hex $high] = "lblk" . $high;
+		$lwrtable{$code} = $lower;
+	}
+	if ($upper ne "") {
+		$upr[hex $high] = "ublk" . $high;
+		$uprtable{$code} = $upper;
+	}
+	#Write everything to the test file
+	printf TEST "%s %s %s\n", $code, 
+		$upper ne "" ? $upper : "0000",
+		$lower ne "" ? $lower : "0000";
+
+}
+close(FILE);
+close TEST;
+
+#Generate the header file
+print OUT "/*\n";
+print OUT " * Automatically generated file -- do not edit!\n";
+print OUT " * (Use tools/unimap.pl for generation)\n";
+print OUT " *\n";
+print OUT " * Mapping tables for Unicode case conversion\n";
+print OUT " */\n\n";
+
+#Write out the non-trivial mappings
+for ($high = 0; $high < 256; $high++) {
+	#Check whether the table is needed
+	if (length $low[$high] < 6) {
+		next;
+	}
+	printf OUT "/* Lowercase mappings %02X00 - %02XFF */\n",
+		$high, $high;
+	printf OUT "static const WCHAR lblk%02X[256] = {\n", $high;
+	for ($low = 0; $low < 256; $low += 8) {
+		@patch = ();
+		for ($i = 0; $i < 8; $i++) {
+			$code = sprintf "%02X%02X", $high, $low + $i;
+			$map = $lwrtable{$code};
+			if ($map eq "") {
+				$map = $code;
+			}
+			$patch[$i] = "0x" . $map;
+		}
+		printf OUT "\t%s, %s, %s, %s, %s, %s, %s, %s,\n",
+			@patch;
+	}
+	print OUT "};\n\n";
+}
+print OUT "static const WCHAR * const lwrtable[256] = {\n";
+for ($i = 0; $i < 256; $i += 8) {
+	@patch = @low[$i+0 .. $i+7];
+	printf OUT "\t%06s, %06s, %06s, %06s, %06s, %06s, %06s, %06s,\n",
+		@patch;
+}
+print OUT "};\n\n";
+
+for ($high = 0; $high < 256; $high++) {
+	#Check whether the table is needed
+	if (length $upr[$high] < 6) {
+		next;
+	}
+	printf OUT "/* Uppercase mappings %02X00 - %02XFF */\n",
+		$high, $high;
+	printf OUT "static const WCHAR ublk%02X[256] = {\n", $high;
+	for ($low = 0; $low < 256; $low += 8) {
+		@patch = ();
+		for ($i = 0; $i < 8; $i++) {
+			$code = sprintf "%02X%02X", $high, $low + $i;
+			$map = $uprtable{$code};
+			if ($map eq "") {
+				$map = $code;
+			}
+			$patch[$i] = "0x" . $map;
+		}
+		printf OUT "\t%s, %s, %s, %s, %s, %s, %s, %s,\n",
+			@patch;
+	}
+	print OUT "};\n\n";
+}
+print OUT "static const WCHAR * const uprtable[256] = {\n";
+for ($i = 0; $i < 256; $i += 8) {
+	@patch = @upr[$i+0 .. $i+7];
+	printf OUT "\t%06s, %06s, %06s, %06s, %06s, %06s, %06s, %06s,\n",
+		@patch;
+}
+print OUT "};\n\n";
+
+close(OUT);
diff --git a/tools/wrc/Makefile.in b/tools/wrc/Makefile.in
new file mode 100644
index 0000000..85eae63
--- /dev/null
+++ b/tools/wrc/Makefile.in
@@ -0,0 +1,41 @@
+DEFS      = -D__WINE__
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+
+PROGRAMS = wrc@PROGEXT@
+MODULE   = none
+
+C_SRCS = \
+	dumpres.c \
+	genres.c \
+	newstruc.c \
+	preproc.c \
+	readres.c \
+	utils.c \
+	wrc.c \
+	writeres.c
+
+EXTRA_SRCS = parser.y parser.l
+EXTRA_OBJS = y.tab.o lex.yy.o
+
+all: $(PROGRAMS)
+
+depend:: y.tab.h
+
+@MAKE_RULES@
+
+wrc@PROGEXT@: $(OBJS)
+	$(CC) $(CFLAGS) -o wrc@PROGEXT@ $(OBJS) $(LEXLIB)
+
+y.tab.c y.tab.h: parser.y
+	$(YACC) -d -t $(SRCDIR)/parser.y
+
+lex.yy.c: parser.l
+	$(LEX) -8 $(SRCDIR)/parser.l
+
+clean::
+	$(RM) y.tab.c y.tab.h lex.yy.c
+
+### Dependencies:
diff --git a/tools/wrc/README.wrc b/tools/wrc/README.wrc
new file mode 100644
index 0000000..7c2b47a
--- /dev/null
+++ b/tools/wrc/README.wrc
@@ -0,0 +1,258 @@
+This is the first release (1.0.0 (28-May-1998)) of the new resource compiler
+'wrc'. It improves the winerc implementation by these features:
+
+- source preprocessing
+- 16 and 32 bit support
+- LANGUAGE support (32 bit only)
+- almost all resource types are supported
+- enhanced expression capabilities and resource naming
+- indirect loadable resources
+- NE/PE resource directory generation
+- binary .res file generation/reading
+
+Wrc generates an assembly file that can be assembled with GNU's gas, or
+passed to gcc. The assembly became necessary for two reasons. First, C does
+not ensure relative position of declared data. Secondly, C complaints about
+complex initialization schemes that became necessary with the NE/PE
+directory generation.
+
+
+Wrc command-line
+----------------
+You can get this message by typing 'wrc -?':
+
+Usage: wrc [options...] [infile[.rc|.res]]
+   -a n        Alignment of resource (win16 only, default is 4)
+   -b          Create a C array from a binary .res file
+   -c          Add 'const' prefix to C constants
+   -C cp       Set the resource's codepage to cp (default is 0)
+   -d n        Set debug level to 'n'
+   -D id[=val] Define preprocessor identifier id=val
+   -e          Disable recognition of win32 keywords in 16bit compile
+   -g          Add symbols to the global c namespace
+   -h          Also generate a .h file
+   -H file     Same as -h but written to file
+   -I path     Set include search dir to path (multiple -I allowed)
+   -l lan      Set default language to lan (default is neutral {0})
+   -n          Do not generate .s file
+   -o file     Output to file (default is infile.[res|s|h]
+   -p prefix   Give a prefix for the generated names
+   -r          Create binary .res file (compile only)
+   -s          Add structure with win32/16 (PE/NE) resource directory
+   -t          Generate indirect loadable resource tables
+   -T          Generate only indirect loadable resources tables
+   -V          Print version end exit
+   -w 16|32    Select win16 or win32 output (default is win32)
+   -W          Enable pedantic warnings
+
+Input is taken from stdin if no sourcefile specified.
+
+Debug level 'n' is a bitmask with following meaning:
+    * 0x01 Tell which resource is parsed (verbose mode)
+    * 0x02 Dump internal structures
+    * 0x04 Create a parser trace (yydebug=1)
+
+The -o option only applies to the final destination file, which is
+in case of normal compile a .s file. You must use the '-H header.h'
+option to override the header-filename.
+If no input filename is given and the output name is not overridden
+with -o and/or -H, then the output is written to "wrc.tab.[sh]"
+
+
+Preprocessing
+-------------
+The build-in preprocessor is not a full implementation of the C counterpart.
+Wrc does not understand function-type macros. These are discarded as they
+are scanned. This will be a future project. Wrc does understand these:
+#define
+#if
+#ifdef
+#ifndef
+#elif
+#else
+#endif
+#error
+
+Also 'defined' is supported as operator (both with and without parenthesis).
+'#if' expressions can be anything valid that evaluates to an integer
+expression (where 0 is false and anything else is true). Others (#pragma,
+#line) are ignored. A special case '#' generates an error. This is due to
+the implementation to enable generation of errors on preprocessing and will
+be improved in the future.
+
+
+16 and 32 bit support
+---------------------
+All of wrc is layed out in such a way that it enables compilation of both 16
+and 32 bit resources. They mainly differ in code-generation and extra
+keywords. Win32 keywords are recognized by default in 16 bit compile. You
+can disable recognition of win32 reserved keywords by using the '-e' option,
+if you encounter .rc-files that use win32 reserved keywords (I strongly
+recommend that you just rename things in the source).
+
+
+Language support
+----------------
+Wrc also understands the LANGUAGE keyword (win32 only) for both global and
+local definitions of language. There are differences with respect to MS' and
+Borland's implementation. Wrc uses 0,0 as the default language if non is
+specified. Both MS and Borland use the language of the system that the
+compiler runs on.
+
+Not all resource-types can have local language keywords attached yet
+(notably: BITMAP, CURSOR, ICON and usertype). This is due to implementation
+of filename-scanning and the complexity that it poses. This will be changed
+in the next release.
+
+
+Resource types supported
+------------------------
+All types are supported except for:
+- FONT
+- MESSAGETABLE
+- extensions like TOOLBAR and the like
+
+These types will be implemented as soon as I get a proper specification of
+the layout.
+
+Note: Usertype resources with character strings as types have a different
+layout and do not accept expressions when a numerical type is specified. The
+must be enclosed in double quotes. These are examples of valid usertype
+resources:
+
+MyName "MyType" mydata.bin
+MyName 12345 mydata.bin
+MyName "MyType" "mydata.bin"
+MyName 12345 "mydata.bin"
+
+MyName "MyType"
+{
+  ..., data, ...
+}
+
+or
+
+MyName 12345
+{
+ ..., data, ...
+}
+
+
+Expression capabilities and resource names
+------------------------------------------
+You can use an expression in most places where the resource definition
+expects a number (except usertype type). Operators supported: 
+()	parenthesis
+*	multiply
+/	divide
++	add
+-	minus/substract
+|	binary or
+&	binary and
+~	binary not (unary operator though)
+NOT	... (sigh)
+
+Minus (-) can both be unary and binary. The NOT operator is (primarily)
+used to disable window styles but I strongly suggest to refrain from using
+this operator.
+There is a shift/reduce conflict on the unary minus, but this is not
+problematic. I was too lazy to make a new expression parser (next version or
+so). Unary plus (+) would cause another confilct, so I let it out for now.
+
+Resource names can be both numerical (expressions) and character typed. Wrc
+does supports this insane (deep sigh) construct:
+
+MENU MENU
+{
+ ...
+}
+
+It is _ONLY_ supported for backwards compatibility so that old sources can
+be compiled with winelib. DO NOT USE IT IN NEW RESOURCES, PLEASE!
+
+
+Indirect loadable resources
+---------------------------
+
+Wrc can generate tables for indirect resource loading like winerc did. There
+are two new structures defined in 'wine-base-dir/include/wrc_rsc.h':
+
+typedef struct wrc_resource16
+{
+        INT32   resid;          /* The resource id if resname == NULL */
+        LPSTR   resname;
+        INT32   restype;        /* The resource type-id if typename == NULL */
+        LPSTR   typename;
+        LPBYTE  data;           /* Actual resource data */
+        UINT32  datasize;       /* The size of the resource */
+} wrc_resource16_t;
+
+typedef struct wrc_resource32
+{
+        INT32   resid;          /* The resource id if resname == NULL */
+        LPWSTR  resname;
+        INT32   restype;        /* The resource type-id if typename == NULL */
+        LPWSTR  typename;
+        LPBYTE  data;           /* Actual resource data */
+        UINT32  datasize;       /* The size of the resource */
+} wrc_resource32_t;
+
+The extension to winerc lies in the addition of the 'typename' field to
+support usertype resoursec with names for types.
+
+Note that _ALL_ names generated by wrc and to be used in interfacing with
+wine are PASCAL-style strings, unlike winerc. The first element contains the
+length and the strings are _not_ '\0'-terminated!
+
+You can also generate header files with wrc when specifying the '-h' or
+'-H<filename>' option.
+
+
+NE/PE resource directory generation
+-----------------------------------
+A windows executable has a table/directory of resources avalable in that
+module. Wrc will generate this directory with the '-s' option and place it
+in the assembly output (and header-file). This will enable the separation
+of different modules (dlls) in wine, which is the next project after wrc.
+
+The layout of the PE directory should be exactly like the executable file.
+The NE-directory layout _DIFFERS_ from the real NE-executable in such way
+that all offsets to actual resource-data is relative to the NE-directory and
+_NOT_ the beginning of the file.
+
+
+Binary .res file generation/reading
+-----------------------------------
+Wrc can both generate (32 and 16 bit) and read (32 bit only) .res-files.
+These can be used as intermediate files or binary files can be imported from
+other sources. The reading of 16 bit .res-files is on the list for the next
+release.
+
+You cannot convert 32 bit .res-files into 16 bit output or vice versa. I
+might implement 16 bit res into 32 bit output in the future, but I stronly
+oppose to the other way arround.
+
+
+Bugs
+----
+Inherent to programs you have bugs. These I know are there, plus a few
+things that I noted in the above text (more lack of implementation than bug
+though):
+- No codepage translation
+- UNICODE translations are not/not correct implemented
+- No documentation ('wrc -?' gives command-line options though)
+- grep for FIXME in the source
+
+
+Reporting bugs and patches
+--------------------------
+Send problems to the wine newsgroup or, preferrably,  directly to me at:
+
+bertho@akhphd.au.dk
+
+Please send the problematic rc-source with the bug so I can reproduce it.
+Patches should _not_ be send to Alexandre but to me. I will then review the
+change and send a full patch to be included into the new wine release (I
+prefer 'diff -u' format). You can always upload suggestions to wine
+headquarters, but be sure to send me a copy.
+
diff --git a/tools/wrc/dumpres.c b/tools/wrc/dumpres.c
new file mode 100644
index 0000000..33c09f4
--- /dev/null
+++ b/tools/wrc/dumpres.c
@@ -0,0 +1,907 @@
+/*
+ * Copyrignt 1998 Bertho A. Stultiens (BS)
+ *
+ * 16-Apr-1998 BS	- Yeah, dump it to stdout.
+ *
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include <config.h>
+#include "wrc.h"
+#include "dumpres.h"
+
+/*
+ *****************************************************************************
+ * Function	: get_typename
+ * Syntax	: char *get_typename(resource_t* r)
+ * Input	:
+ *	r	- Resource description
+ * Output	: A pointer to a string representing the resource type
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+char *get_typename(resource_t* r)
+{
+	switch(r->type){
+	case res_acc:	return "ACCELERATOR";
+	case res_bmp:	return "BITMAP";
+	case res_cur:	return "CURSOR";
+	case res_curg:	return "GROUP_CURSOR";
+	case res_dlg:	return "DIALOG";
+	case res_dlgex:	return "DIALOGEX";
+	case res_fnt:	return "FONT";
+	case res_ico:	return "ICON";
+	case res_icog:	return "GROUP_ICON";
+	case res_men:	return "MENU";
+	case res_menex:	return "MENUEX";
+	case res_rdt:	return "RCDATA";
+	case res_stt:	return "STRINGTABLE";
+	case res_usr:   return "UserResource";
+	case res_msg:	return "MESSAGETABLE";
+	case res_ver:	return "VERSIONINFO";
+	default: 	return "Unknown";
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	: strncpyWtoA
+ * Syntax	: char *strncpyWtoA(char *cs, short *ws, int maxlen)
+ * Input	:
+ *	cs	- Pointer to buffer to receive result
+ *	ws	- Source wide-string
+ *	maxlen	- Max chars to copy
+ * Output	: 'cs'
+ * Description	: Copy a unicode string to ascii. Copying stops after the
+ *		  first occuring '\0' or when maxlen-1 chars are copied. The
+ *		  String is always nul terminated.
+ * Remarks	: No codepage translation is done.
+ *****************************************************************************
+*/
+char *strncpyWtoA(char *cs, short *ws, int maxlen)
+{
+	char *cptr = cs;
+	while(*ws && maxlen-1)
+	{
+		if(*ws < -128 || *ws > 127)
+			printf("***Warning: Unicode string contains non-printable chars***");
+		*cptr++ = (char)*ws++;
+		maxlen--;
+	}
+	*cptr = '\0';
+	return cs;
+}
+
+/*
+ *****************************************************************************
+ * Function	: print_string
+ * Syntax	: void print_string(string_t *str)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void print_string(string_t *str)
+{
+	char buffer[512];
+	if(!str)
+		printf("<none>");
+	else if(str->type == str_char)
+		printf("\"%s\"", str->str.cstr);
+	else
+	{
+		strncpyWtoA(buffer, str->str.wstr, sizeof(buffer));
+		printf("L\"%s\"", buffer);
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	: get_nameid_str
+ * Syntax	: char *get_nameid_str(name_id_t *n)
+ * Input	:
+ *	n	- nameid to convert to text
+ * Output	: A pointer to the name.
+ * Description	:
+ * Remarks	: Not reentrant because of static buffer
+ *****************************************************************************
+*/
+char *get_nameid_str(name_id_t *n)
+{
+	static char buffer[256];
+
+	if(!n)
+		return "<none>";
+
+	if(n->type == name_ord)
+	{
+		sprintf(buffer, "%d", n->name.i_name);
+		return buffer;
+	}
+	else if(n->type == name_str)
+	{
+		if(n->name.s_name->type == str_char)
+			return n->name.s_name->str.cstr;
+		else
+		{
+			strncpyWtoA(buffer, n->name.s_name->str.wstr, sizeof(buffer));
+			return buffer;
+		}
+	}
+	else
+		return "Hoooo, report this: wrong type in nameid";
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_memopt
+ * Syntax	: void dump_memopt(DWORD memopt)
+ * Input	:
+ *	memopt	- flag bits of the options set
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_memopt(DWORD memopt)
+{
+	printf("Memory/load options: ");
+	if(memopt & 0x0040)
+		printf("PRELOAD ");
+	else
+		printf("LOADONCALL ");
+	if(memopt & 0x0010)
+		printf("MOVEABLE ");
+	else
+		printf("FIXED ");
+	if(memopt & 0x0020)
+		printf("PURE ");
+	else
+		printf("IMPURE ");
+	if(memopt & 0x1000)
+		printf("DISCARDABLE");
+	printf("\n");
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_lvc
+ * Syntax	: void dump_lvc(lvc_t *l)
+ * Input	:
+ *	l	- pointer to lvc structure
+ * Output	:
+ * Description	: Dump language, version and characteristics
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_lvc(lvc_t *l)
+{
+	if(l->language)
+		printf("LANGUAGE %04x, %04x\n", l->language->id, l->language->sub);
+	else
+		printf("LANGUAGE <not set>\n");
+
+	if(l->version)
+		printf("VERSION %08lx\n", *(l->version));
+	else
+		printf("VERSION <not set>\n");
+
+	if(l->characts)
+		printf("CHARACTERISTICS %08lx\n", *(l->characts));
+	else
+		printf("CHARACTERISTICS <not set>\n");
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_raw_data
+ * Syntax	: void dump_raw_data(raw_data_t *d)
+ * Input	:
+ *	d	- Raw data descriptor
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_raw_data(raw_data_t *d)
+{
+	int n;
+	int i;
+	int j;
+
+	if(!d)
+	{
+		printf("<none>");
+		return;
+	}
+	printf("Rawdata size: %d\n", d->size);
+	if(debuglevel < 2)
+		return;
+
+	for(n = 0; n < d->size; n++)
+	{
+		if((n % 16) == 0)
+			if(n)
+			{
+				printf("- ");
+				for(i = 0; i < 16; i++)
+					printf("%c", isprint(d->data[n-16+i]) ? d->data[n-16+i] : '.');
+				printf("\n%08x: ", n);
+			}
+			else
+				printf("%08x: ", n);
+		printf("%02x ", d->data[n] & 0xff);
+	}
+	printf("- ");
+	j = d->size % 16;
+	if(!j)
+		j = 16;
+	for(i = 0; i < j; i++)
+		printf("%c", isprint(d->data[n-j+i]) ? d->data[n-j+i] : '.');
+	printf("\n");
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_accelerator
+ * Syntax	: void dump_accelerator(resource_t *acc)
+ * Input	:
+ *	acc	- Accelerator resource descriptor
+ * Output	: nop
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_accelerator(accelerator_t *acc)
+{
+	event_t *ev = acc->events;
+
+	dump_memopt(acc->memopt);
+	dump_lvc(&(acc->lvc));
+
+	printf("Events: %s\n", ev ? "" : "<none>");
+	while(ev)
+	{
+		printf("Key=");
+		if(isprint(ev->key))
+			printf("\"%c\"", ev->key);
+		else if(iscntrl(ev->key))
+			printf("\"^%c\"", ev->key +'@');
+		else
+			printf("\\x%02x", ev->key & 0xff);
+
+		printf(" Id=%d flags=%04x\n", ev->id, ev->flags);
+		ev = ev->next;
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_cursor
+ * Syntax	: void dump_cursor(cursor_t *cur)
+ * Input	:
+ *	cur	- Cursor resource descriptor
+ * Output	: nop
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_cursor(cursor_t *cur)
+{
+	printf("Id: %d\n", cur->id);
+	printf("Width: %d\n", cur->width);
+	printf("Height: %d\n", cur->height);
+	printf("X Hotspot: %d\n", cur->xhot);
+	printf("Y Hotspot: %d\n", cur->yhot);
+	dump_raw_data(cur->data);
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_cursor_group
+ * Syntax	: void dump_cursor_group(cursor_group_t *cur)
+ * Input	:
+ *	cur	- Cursor group resource descriptor
+ * Output	: nop
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_cursor_group(cursor_group_t *curg)
+{
+	dump_memopt(curg->memopt);
+	printf("There are %d cursors in this group\n", curg->ncursor);
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_icon
+ * Syntax	: void dump_icon(icon_t *ico)
+ * Input	:
+ *	ico	- Icon resource descriptor
+ * Output	: nop
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_icon(icon_t *ico)
+{
+	printf("Id: %d\n", ico->id);
+	printf("Width: %d\n", ico->width);
+	printf("Height: %d\n", ico->height);
+	printf("NColor: %d\n", ico->nclr);
+	printf("NPlanes: %d\n", ico->planes);
+	printf("NBits: %d\n", ico->bits);
+	dump_raw_data(ico->data);
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_icon_group
+ * Syntax	: void dump_icon_group(icon_group_t *ico)
+ * Input	:
+ *	ico	- Icon group resource descriptor
+ * Output	: nop
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_icon_group(icon_group_t *icog)
+{
+	dump_memopt(icog->memopt);
+	printf("There are %d icons in this group\n", icog->nicon);
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_font
+ * Syntax	: void dump_font(font_t *fnt)
+ * Input	:
+ *	fnt	- Font resource descriptor
+ * Output	: nop
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_font(font_t *fnt)
+{
+	dump_memopt(fnt->memopt);
+	dump_raw_data(fnt->data);
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_bitmap
+ * Syntax	: void dump_bitmap(bitmap_t *bmp)
+ * Input	:
+ *	bmp	- Bitmap resource descriptor
+ * Output	: nop
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_bitmap(bitmap_t *bmp)
+{
+	dump_memopt(bmp->memopt);
+	dump_raw_data(bmp->data);
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_rcdata
+ * Syntax	: void dump_rcdata(rcdata_t *rdt)
+ * Input	:
+ *	rdt	- RCData resource descriptor
+ * Output	: nop
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_rcdata(rcdata_t *rdt)
+{
+	dump_memopt(rdt->memopt);
+	dump_raw_data(rdt->data);
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_user
+ * Syntax	: void dump_user(user_t *usr)
+ * Input	:
+ *	usr	- User resource descriptor
+ * Output	: nop
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_user(user_t *usr)
+{
+	dump_memopt(usr->memopt);
+	printf("Class %s\n", get_nameid_str(usr->type));
+	dump_raw_data(usr->data);
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_messagetable
+ * Syntax	: void dump_messagetable(messagetable_t *msg)
+ * Input	:
+ *	msg	- Messagetable resource descriptor
+ * Output	: nop
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_messagetable(messagetable_t *msg)
+{
+	dump_raw_data(msg->data);
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_stringtable
+ * Syntax	: void dump_stringtable(stringtable_t *stt)
+ * Input	:
+ *	stt	- Stringtable resource descriptor
+ * Output	: nop
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_stringtable(stringtable_t *stt)
+{
+	int i;
+	for(; stt; stt = stt->next)
+	{
+		printf("{\n");
+		dump_memopt(stt->memopt);
+		dump_lvc(&(stt->lvc));
+		for(i = 0; i < stt->nentries; i++)
+		{
+			printf("Id=%-5d (%d) ", stt->idbase+i, stt->entries[i].id);
+			if(stt->entries[i].str)
+				print_string(stt->entries[i].str);
+			else
+				printf("<none>");
+			printf("\n");
+		}
+		printf("}\n");
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_control
+ * Syntax	: void dump_control(control_t *ctrl)
+ * Input	:
+ *	ctrl	- Control resource descriptor
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_control(control_t *ctrl)
+{
+	printf("Control {\n\tClass: %s\n", get_nameid_str(ctrl->ctlclass));
+	printf("\tText: "); print_string(ctrl->title); printf("\n");
+	printf("\tId: %d\n", ctrl->id);
+	printf("\tx, y, w, h: %d, %d, %d, %d\n", ctrl->x, ctrl->y, ctrl->width, ctrl->height);
+	if(ctrl->gotstyle)
+		printf("\tStyle: %08lx\n", ctrl->style);
+	if(ctrl->gotexstyle)
+		printf("\tExStyle: %08lx\n", ctrl->exstyle);
+	if(ctrl->gothelpid)
+		printf("\tHelpid: %ld\n", ctrl->helpid);
+	if(ctrl->extra)
+	{
+		printf("\t");
+		dump_raw_data(ctrl->extra);
+	}
+	printf("}\n");
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_dialog
+ * Syntax	: void dump_dialog(dialog_t *dlg)
+ * Input	:
+ *	dlg	- Dialog resource descriptor
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_dialog(dialog_t *dlg)
+{
+	control_t *c = dlg->controls;
+
+	dump_memopt(dlg->memopt);
+	dump_lvc(&(dlg->lvc));
+	printf("x, y, w, h: %d, %d, %d, %d\n", dlg->x, dlg->y, dlg->width, dlg->height);
+	if(dlg->gotstyle)
+		printf("Style: %08lx\n", dlg->style);
+	if(dlg->gotexstyle)
+		printf("ExStyle: %08lx\n", dlg->exstyle);
+	printf("Menu: %s\n", get_nameid_str(dlg->menu));
+	printf("Class: %s\n", get_nameid_str(dlg->dlgclass));
+	printf("Title: "); print_string(dlg->title); printf("\n");
+	printf("Font: ");
+	if(!dlg->font)
+		printf("<none>\n");
+	else
+	{
+		printf("%d, ", dlg->font->size);
+		print_string(dlg->font->name);
+		printf("\n");
+	}
+	while(c)
+	{
+		dump_control(c);
+		c = c->next;
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_dialogex
+ * Syntax	: void dump_dialogex(dialogex_t *dlgex)
+ * Input	:
+ *	dlgex	- DialogEx resource descriptor
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_dialogex(dialogex_t *dlgex)
+{
+	control_t *c = dlgex->controls;
+
+	dump_memopt(dlgex->memopt);
+	dump_lvc(&(dlgex->lvc));
+	printf("x, y, w, h: %d, %d, %d, %d\n", dlgex->x, dlgex->y, dlgex->width, dlgex->height);
+	if(dlgex->gotstyle)
+		printf("Style: %08lx\n", dlgex->style);
+	if(dlgex->gotexstyle)
+		printf("ExStyle: %08lx\n", dlgex->exstyle);
+	if(dlgex->gothelpid)
+		printf("Helpid: %ld\n", dlgex->helpid);
+	printf("Menu: %s\n", get_nameid_str(dlgex->menu));
+	printf("Class: %s\n", get_nameid_str(dlgex->dlgclass));
+	printf("Title: "); print_string(dlgex->title); printf("\n");
+	printf("Font: ");
+	if(!dlgex->font)
+		printf("<none>\n");
+	else
+	{
+		printf("%d, ", dlgex->font->size);
+		print_string(dlgex->font->name);
+		printf(", %d, %d\n", dlgex->font->weight, dlgex->font->italic);
+	}
+	while(c)
+	{
+		dump_control(c);
+		c = c->next;
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_menu_item
+ * Syntax	: void dump_menu_item(menu_item_t *item)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_menu_item(menu_item_t *item)
+{
+	while(item)
+	{
+		if(item->popup)
+		{
+			printf("POPUP ");
+			print_string(item->name);
+			printf("\n");
+			dump_menu_item(item->popup);
+		}
+		else
+		{
+			printf("MENUITEM ");
+			if(item->name)
+			{
+				print_string(item->name);
+				printf(", %d, %08lx", item->id, item->state);
+			}
+			else
+				printf("SEPARATOR");
+			printf("\n");
+		}
+		item = item->next;
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_menu
+ * Syntax	: void dump_menu(menu_t *men)
+ * Input	:
+ *	men	- Menu resource descriptor
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_menu(menu_t *men)
+{
+	dump_memopt(men->memopt);
+	dump_lvc(&(men->lvc));
+	dump_menu_item(men->items);
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_menuex_item
+ * Syntax	: void dump_menuex_item(menuex_item_t *item)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_menuex_item(menuex_item_t *item)
+{
+	while(item)
+	{
+		if(item->popup)
+		{
+			printf("POPUP ");
+			print_string(item->name);
+			if(item->gotid)
+				printf(", Id=%d", item->id);
+			if(item->gottype)
+				printf(", Type=%ld", item->type);
+			if(item->gotstate)
+				printf(", State=%08lx", item->state);
+			if(item->gothelpid)
+				printf(", HelpId=%d", item->helpid);
+			printf("\n");
+			dump_menuex_item(item->popup);
+		}
+		else
+		{
+			printf("MENUITEM ");
+			if(item->name)
+			{
+				print_string(item->name);
+				if(item->gotid)
+					printf(", Id=%d", item->id);
+				if(item->gottype)
+					printf(", Type=%ld", item->type);
+				if(item->gotstate)
+					printf(", State=%08lx", item->state);
+				if(item->gothelpid)
+					printf(", HelpId=%d", item->helpid);
+			}
+			else
+				printf("SEPARATOR");
+			printf("\n");
+		}
+		item = item->next;
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_menuex
+ * Syntax	: void dump_menuex(dialogex_t *menex)
+ * Input	:
+ *	menex	- MenuEx resource descriptor
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_menuex(menuex_t *menex)
+{
+	dump_memopt(menex->memopt);
+	dump_lvc(&(menex->lvc));
+	dump_menuex_item(menex->items);
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_ver_value
+ * Syntax	: void dump_ver_value(ver_value_t *val)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_ver_value(ver_value_t *val)
+{
+	extern void dump_ver_block(ver_block_t *);
+	if(val->type == val_str)
+	{
+		printf("VALUE ");
+		print_string(val->key);
+		printf(" ");
+		print_string(val->value.str);
+		printf("\n");
+	}
+	else if(val->type == val_words)
+	{
+		int i;
+		printf("VALUE");
+		print_string(val->key);
+		for(i = 0; i < val->value.words->nwords; i++)
+			printf(" %04x", val->value.words->words[i]);
+		printf("\n");
+	}
+	else if(val->type == val_block)
+	{
+		dump_ver_block(val->value.block);
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_ver_block
+ * Syntax	: void dump_ver_block(ver_block_t *blk)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_ver_block(ver_block_t *blk)
+{
+	ver_value_t *val = blk->values;
+	printf("BLOCK ");
+	print_string(blk->name);
+	printf("\n{\n");
+	while(val)
+	{
+		dump_ver_value(val);
+		val = val->next;
+	}
+	printf("}\n");
+}
+
+/*
+ *****************************************************************************
+ * Function	: dump_versioninfo
+ * Syntax	: void dump_versioninfo(versioninfo_t *ver)
+ * Input	:
+ *	ver	- Versioninfo resource descriptor
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_versioninfo(versioninfo_t *ver)
+{
+	ver_block_t *blk = ver->blocks;
+
+	if(ver->gotit.fv)
+		printf("FILEVERSION %04x, %04x, %04x, %04x\n",
+			ver->filever_maj1,
+			ver->filever_maj2,
+			ver->filever_min1,
+			ver->filever_min2);
+	if(ver->gotit.pv)
+		printf("PRODUCTVERSION %04x, %04x, %04x, %04x\n",
+			ver->prodver_maj1,
+			ver->prodver_maj2,
+			ver->prodver_min1,
+			ver->prodver_min2);
+	if(ver->gotit.fo)
+		printf("FILEOS %08x\n", ver->fileos);
+	if(ver->gotit.ff)
+		printf("FILEFLAGS %08x\n", ver->fileflags);
+	if(ver->gotit.ffm)
+		printf("FILEFLAGSMASK %08x\n", ver->fileflagsmask);
+	if(ver->gotit.ft)
+		printf("FILETYPE %08x\n", ver->filetype);
+	if(ver->gotit.fst)
+		printf("FILESUBTYPE %08x\n", ver->filesubtype);
+	while(blk)
+	{
+		dump_ver_block(blk);
+		blk = blk->next;
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	:
+ * Syntax	:
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+/*
+ *****************************************************************************
+ * Function	: dump_resources
+ * Syntax	: void dump_resources(resource_t *top)
+ * Input	:
+ *	top	- Top of the resource tree
+ * Output	:
+ *	nop
+ * Description	: Dump the parsed resource-tree to stdout
+ * Remarks	:
+ *****************************************************************************
+*/
+void dump_resources(resource_t *top)
+{
+	printf("Internal resource-tree dump:\n");
+	while(top)
+	{
+		printf("Resource: %s\nId: %s\n",
+		       get_typename(top),
+		       get_nameid_str(top->name));
+		switch(top->type)
+		{
+		case res_acc:
+			dump_accelerator(top->res.acc);
+			break;
+		case res_bmp:
+			dump_bitmap(top->res.bmp);
+			break;
+		case res_cur:
+			dump_cursor(top->res.cur);
+			break;
+		case res_curg:
+			dump_cursor_group(top->res.curg);
+			break;
+		case res_dlg:
+			dump_dialog(top->res.dlg);
+			break;
+		case res_dlgex:
+			dump_dialogex(top->res.dlgex);
+			break;
+		case res_fnt:
+			dump_font(top->res.fnt);
+			break;
+		case res_icog:
+			dump_icon_group(top->res.icog);
+			break;
+		case res_ico:
+			dump_icon(top->res.ico);
+			break;
+		case res_men:
+			dump_menu(top->res.men);
+			break;
+		case res_menex:
+			dump_menuex(top->res.menex);
+			break;
+		case res_rdt:
+			dump_rcdata(top->res.rdt);
+			break;
+		case res_stt:
+			dump_stringtable(top->res.stt);
+			break;
+		case res_usr:
+			dump_user(top->res.usr);
+			break;
+		case res_msg:
+			dump_messagetable(top->res.msg);
+			break;
+		case res_ver:
+			dump_versioninfo(top->res.ver);
+			break;
+		default:
+			printf("Report this: Unknown resource type parsed %08x\n", top->type);
+		}
+		printf("\n");
+		top = top->next;
+	}
+}
+
diff --git a/tools/wrc/dumpres.h b/tools/wrc/dumpres.h
new file mode 100644
index 0000000..75e9650
--- /dev/null
+++ b/tools/wrc/dumpres.h
@@ -0,0 +1,18 @@
+/*
+ * Dump resource prototypes
+ *
+ * Copyright 1998 Bertho A. Stultiens (BS)
+ *
+ */
+
+#ifndef __WRC_DUMPRES_H
+#define __WRC_DUMPRES_H
+
+#ifndef __WRC_WRCTYPES_H
+#include "wrctypes.h"
+#endif
+
+char *get_typename(resource_t* r);
+void dump_resources(resource_t *top);
+
+#endif
diff --git a/tools/wrc/genres.c b/tools/wrc/genres.c
new file mode 100644
index 0000000..b9e831c
--- /dev/null
+++ b/tools/wrc/genres.c
@@ -0,0 +1,1668 @@
+/*
+ * Generate .res format from a resource-tree
+ *
+ * Copyright 1998 Bertho A. Stultiens
+ *
+ * 25-May-1998 BS	- Added simple unicode -> char conversion for resource
+ *			  names in .s and .h files.  
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <config.h>
+#include "wrc.h"
+#include "genres.h"
+#include "utils.h"
+
+#define SetResSize(res, tag)	*(DWORD *)&((res)->data[(tag)]) = \
+				(res)->size - *(DWORD *)&((res)->data[(tag)])
+
+res_t *new_res(void)
+{
+	res_t *r;
+	r = (res_t *)xmalloc(sizeof(res_t));
+	r->allocsize = RES_BLOCKSIZE;
+	r->size = 0;
+	r->data = (char *)xmalloc(RES_BLOCKSIZE);
+	return r;
+}
+
+res_t *grow_res(res_t *r, int add)
+{
+	r->allocsize += add;
+	r->data = (char *)xrealloc(r->data, r->allocsize);
+	return r;
+}
+
+/*
+ *****************************************************************************
+ * Function	: put_byte
+ *		  put_word
+ *		  put_dword
+ * Syntax	: void put_byte(res_t *res, unsigned c)
+ *		  void put_word(res_t *res, unsigned w)
+ *		  void put_dword(res_t *res, unsigned d)
+ * Input	:
+ *	res	- Binary resource to put the data in
+ *	c, w, d	- Data to put
+ * Output	: nop
+ * Description	: Put primitives that put an item in the binary resource.
+ *		  The data array grows automatically.
+ * Remarks	:
+ *****************************************************************************
+*/
+void put_byte(res_t *res, unsigned c)
+{
+	if(res->allocsize - res->size < sizeof(char))
+		grow_res(res, RES_BLOCKSIZE);
+	*(char *)&(res->data[res->size]) = (char)c;
+	res->size += sizeof(char);
+}
+
+void put_word(res_t *res, unsigned w)
+{
+	if(res->allocsize - res->size < sizeof(WORD))
+		grow_res(res, RES_BLOCKSIZE);
+	*(WORD *)&(res->data[res->size]) = (WORD)w;
+	res->size += sizeof(WORD);
+}
+
+void put_dword(res_t *res, unsigned d)
+{
+	if(res->allocsize - res->size < sizeof(DWORD))
+		grow_res(res, RES_BLOCKSIZE);
+	*(DWORD *)&(res->data[res->size]) = (DWORD)d;
+	res->size += sizeof(DWORD);
+}
+
+void put_pad(res_t *res)
+{
+	while(res->size & 0x3)
+		put_byte(res, 0);
+}
+
+/*
+ *****************************************************************************
+ * Function	: string_to_upper
+ * Syntax	: void string_to_upper(string_t *str)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	: FIXME: codepages...
+ *****************************************************************************
+*/
+void string_to_upper(string_t *str)
+{
+	if(str->type == str_char)
+	{
+		char *cptr = str->str.cstr;
+		for(; *cptr; cptr++)
+			*cptr = (char)toupper(*cptr);
+	}
+	else if(str->type == str_unicode)
+	{
+		short *sptr = str->str.wstr;
+		for(; *sptr; sptr++)
+			if(isalpha(*sptr))
+				*sptr = (short)toupper(*sptr);
+	}
+	else
+	{
+		internal_error(__FILE__, __LINE__, "Invalid string type %d", str->type);
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	: put_string
+ * Syntax	: void put_string(res_t *res, string_t *str, enum str_e type,
+ *				  int isterm)
+ * Input	:
+ *	res	- Binary resource to put the data in
+ *	str	- String to put
+ *	type	- Data has to be written in either str_char or str_unicode
+ *	isterm	- The string is '\0' terminated (disregard the string's
+ *		  size member)
+ * Output	: nop
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void put_string(res_t *res, string_t *str, enum str_e type, int isterm)
+{
+	int cnt;
+	int c = !0;
+	assert(res != NULL);
+	assert(str != NULL);
+	if(!isterm && str->size == 0)
+	{
+		warning("String length is zero, not written");
+		return;
+	}
+
+	if(str->type == str_unicode && type == str_unicode)
+	{
+		for(cnt = 0; cnt < str->size; cnt++)
+		{
+			c = str->str.wstr[cnt];
+			put_word(res, c);
+			if(isterm && !c)
+				break;
+		}
+		if(isterm && (str->size == 0 || (cnt == str->size && c)))
+			put_word(res, 0);
+	}
+	else if(str->type == str_char && type == str_char)
+	{
+		for(cnt = 0; cnt < str->size; cnt++)
+		{
+			c = str->str.cstr[cnt];
+			put_byte(res, c);
+			if(isterm && !c)
+				break;
+		}
+		if(isterm && (str->size == 0 || (cnt == str->size && c)))
+			put_byte(res, 0);
+	}
+	else if(str->type == str_unicode && type == str_char)
+	{
+		for(cnt = 0; cnt < str->size; cnt++)
+		{
+			c = str->str.wstr[cnt];
+			put_byte(res, c);
+			if(isterm && !c)
+				break;
+		}
+		if(isterm && (str->size == 0 || (cnt == str->size && c)))
+			put_byte(res, 0);
+	}
+	else /* str->type == str_char && type == str_unicode */
+	{
+		for(cnt = 0; cnt < str->size; cnt++)
+		{
+			c = str->str.cstr[cnt];
+			put_word(res, c & 0xff);
+			if(isterm && !c)
+				break;
+		}
+		if(isterm && (str->size == 0 || (cnt == str->size && c)))
+			put_word(res, 0);
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	: put_name_id
+ * Syntax	: void put_name_id(res_t *res, name_id_t *nid, int upcase)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void put_name_id(res_t *res, name_id_t *nid, int upcase)
+{
+	if(nid->type == name_ord)
+	{
+		if(win32)
+			put_word(res, 0xffff);
+		else
+			put_byte(res, 0xff);
+		put_word(res, (WORD)nid->name.i_name);
+	}
+	else if(nid->type == name_str)
+	{
+		if(upcase)
+			string_to_upper(nid->name.s_name);
+		put_string(res, nid->name.s_name, win32 ? str_unicode : str_char, TRUE);
+	}
+	else
+	{
+		internal_error(__FILE__, __LINE__, "Invalid name_id type %d", nid->type);
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	: put_lvc
+ * Syntax	: void put_lvc(res_t *res, lvc_t *lvc)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void put_lvc(res_t *res, lvc_t *lvc)
+{
+	if(lvc && lvc->language)
+		put_word(res, MAKELANGID(lvc->language->id, lvc->language->sub));
+	else
+		put_word(res, 0);	/* Neutral */
+	if(lvc && lvc->version)
+		put_dword(res, *(lvc->version));
+	else
+		put_dword(res, 0);
+	if(lvc && lvc->characts)
+		put_dword(res, *(lvc->characts));
+	else
+		put_dword(res, 0);
+}
+
+/*
+ *****************************************************************************
+ * Function	: put_raw_data
+ * Syntax	: void put_raw_data(res_t *res, raw_data_t *raw, int offset)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void put_raw_data(res_t *res, raw_data_t *raw, int offset)
+{
+	int wsize = raw->size - offset;
+	if(res->allocsize - res->size < wsize)
+		grow_res(res, wsize);
+	memcpy(&(res->data[res->size]), raw->data + offset, wsize);
+	res->size += wsize;
+}
+
+/*
+ *****************************************************************************
+ * Function	: put_res_header
+ * Syntax	: intput_res_header(res_t *res, int type, name_id_t *ntype,
+ *				    name_id_t *name, DWORD memopt, lvc_t *lvc)
+ *
+ * Input	:
+ *	res	- Binary resource descriptor to write to
+ *	type	- Resource identifier (if ntype == NULL)
+ *	ntype	- Name id of type
+ *	name	- Resource's name
+ *	memopt	- Resource's memory options to write
+ *	lvc	- Language, version and characteristics (win32 only)
+ * Output	: An index to the resource size field. The resource size field
+ *		  contains the header size upon exit.
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+int put_res_header(res_t *res, int type, name_id_t *ntype, name_id_t *name,
+		      DWORD memopt, lvc_t *lvc)
+{
+	if(win32)
+	{
+		put_dword(res, 0);		/* We will overwrite these later */
+		put_dword(res, 0);
+		if(!ntype)
+		{
+			put_word(res, 0xffff);		/* ResType */
+			put_word(res, type);
+		}
+		else
+			put_name_id(res, ntype, TRUE);
+		put_name_id(res, name, TRUE);	/* ResName */
+		put_pad(res);
+		put_dword(res, 0);		/* DataVersion */
+		put_word(res, memopt);		/* Memory options */
+		put_lvc(res, lvc);		/* Language, version and characts */
+		((DWORD *)res->data)[0] = res->size;	/* Set preliminary resource */
+		((DWORD *)res->data)[1] = res->size;	/* Set HeaderSize */
+		res->dataidx = res->size;
+		return 0;
+	}
+	else /* win16 */
+	{
+		int tag;
+		if(!ntype)
+		{
+			put_byte(res, 0xff);		/* ResType */
+			put_word(res, type);
+		}
+		else
+			put_name_id(res, ntype, TRUE);
+		put_name_id(res, name, TRUE);	/* ResName */
+		put_word(res, memopt);		/* Memory options */
+		tag = res->size;
+		put_dword(res, 0);		/* ResSize overwritten later*/
+		*(DWORD *)&(res->data[tag]) = res->size;
+		res->dataidx = res->size;
+		return tag;
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	: accelerator2res
+ * Syntax	: res_t *accelerator2res(name_id_t *name, accelerator_t *acc)
+ * Input	:
+ *	name	- Name/ordinal of the resource
+ *	acc	- The accelerator descriptor
+ * Output	: New .res format structure
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+res_t *accelerator2res(name_id_t *name, accelerator_t *acc)
+{
+	int restag;
+	res_t *res;
+	event_t *ev;
+	assert(name != NULL);
+	assert(acc != NULL);
+
+	ev = acc->events;
+	res = new_res();
+	if(win32)
+	{
+		restag = put_res_header(res, WRC_RT_ACCELERATOR, NULL, name, acc->memopt, &(acc->lvc));
+		while(ev)
+		{
+			put_word(res, ev->flags | (ev->next ? 0 : 0x80));
+			put_word(res, ev->key);
+			put_word(res, ev->id);
+			put_word(res, 0);	/* Padding */
+			ev = ev->next;
+		}
+		put_pad(res);
+	}
+	else /* win16 */
+	{
+		restag = put_res_header(res, WRC_RT_ACCELERATOR, NULL, name, acc->memopt, NULL);
+		while(ev)
+		{
+			put_byte(res, ev->flags | (ev->next ? 0 : 0x80));
+			put_word(res, ev->key);
+			put_word(res, ev->id);
+			ev = ev->next;
+		}
+	}
+	/* Set ResourceSize */
+	SetResSize(res, restag);
+	return res;
+}
+
+/*
+ *****************************************************************************
+ * Function	: dialog2res
+ * Syntax	: res_t *dialog2res(name_id_t *name, dialog_t *dlg)
+ * Input	:
+ *	name	- Name/ordinal of the resource
+ *	dlg	- The dialog descriptor
+ * Output	: New .res format structure
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+res_t *dialog2res(name_id_t *name, dialog_t *dlg)
+{
+	int restag;
+	res_t *res;
+	control_t *ctrl;
+	int tag_nctrl;
+	int nctrl = 0;
+	assert(name != NULL);
+	assert(dlg != NULL);
+
+	ctrl = dlg->controls;
+	res = new_res();
+	if(win32)
+	{
+		restag = put_res_header(res, WRC_RT_DIALOG, NULL, name, dlg->memopt, &(dlg->lvc));
+
+		put_dword(res, dlg->style);
+		put_dword(res, dlg->gotexstyle ? dlg->exstyle : 0);
+		tag_nctrl = res->size;
+		put_word(res, 0);		/* Number of controls */
+		put_word(res, dlg->x);
+		put_word(res, dlg->y);
+		put_word(res, dlg->width);
+		put_word(res, dlg->height);
+		if(dlg->menu)
+			put_name_id(res, dlg->menu, TRUE);
+		else
+			put_word(res, 0);
+		if(dlg->dlgclass)
+			put_name_id(res, dlg->dlgclass, TRUE);
+		else
+			put_word(res, 0);
+		if(dlg->title)
+			put_string(res, dlg->title, str_unicode, TRUE);
+		else
+			put_word(res, 0);
+		if(dlg->font)
+		{
+			put_word(res, dlg->font->size);
+			put_string(res, dlg->font->name, str_unicode, TRUE);
+		}
+
+		put_pad(res);
+		while(ctrl)
+		{
+			/* FIXME: what is default control style? */
+			put_dword(res, ctrl->gotstyle ? ctrl->style : WS_CHILD);
+			put_dword(res, ctrl->gotexstyle ? ctrl->exstyle : 0);
+			put_word(res, ctrl->x);
+			put_word(res, ctrl->y);
+			put_word(res, ctrl->width);
+			put_word(res, ctrl->height);
+			put_word(res, ctrl->id);
+			if(ctrl->ctlclass)
+				put_name_id(res, ctrl->ctlclass, TRUE);
+			else
+				internal_error(__FILE__, __LINE__, "Control has no control-class");
+			if(ctrl->title)
+				put_string(res, ctrl->title, str_unicode, TRUE);
+			else
+				put_word(res, 0);
+			if(ctrl->extra)
+			{
+				put_word(res, ctrl->extra->size+2);
+				put_pad(res);
+				put_raw_data(res, ctrl->extra, 0);
+			}
+			else
+				put_word(res, 0);
+
+			if(ctrl->next)
+				put_pad(res);
+			nctrl++;
+			ctrl = ctrl->next;
+		}
+		/* Set number of controls */
+		*(WORD *)&((char *)res->data)[tag_nctrl] = (WORD)nctrl;
+	}
+	else /* win16 */
+	{
+		restag = put_res_header(res, WRC_RT_DIALOG, NULL, name, dlg->memopt, NULL);
+
+		put_dword(res, dlg->gotstyle ? dlg->style : WS_POPUPWINDOW);
+		tag_nctrl = res->size;
+		put_byte(res, 0);		/* Number of controls */
+		put_word(res, dlg->x);
+		put_word(res, dlg->y);
+		put_word(res, dlg->width);
+		put_word(res, dlg->height);
+		if(dlg->menu)
+			put_name_id(res, dlg->menu, TRUE);
+		else
+			put_byte(res, 0);
+		if(dlg->dlgclass)
+			put_name_id(res, dlg->dlgclass, TRUE);
+		else
+			put_byte(res, 0);
+		if(dlg->title)
+			put_string(res, dlg->title, str_char, TRUE);
+		else
+			put_byte(res, 0);
+		if(dlg->font)
+		{
+			put_word(res, dlg->font->size);
+			put_string(res, dlg->font->name, str_char, TRUE);
+		}
+
+		while(ctrl)
+		{
+			put_word(res, ctrl->x);
+			put_word(res, ctrl->y);
+			put_word(res, ctrl->width);
+			put_word(res, ctrl->height);
+			put_word(res, ctrl->id);
+			put_dword(res, ctrl->gotstyle ? ctrl->style : WS_CHILD);
+			if(ctrl->ctlclass)
+			{
+				if(ctrl->ctlclass->type == name_ord
+				&& ctrl->ctlclass->name.i_name >= 0x80
+				&& ctrl->ctlclass->name.i_name <= 0x85)
+					put_byte(res, ctrl->ctlclass->name.i_name);
+				else if(ctrl->ctlclass->type == name_str)
+					put_name_id(res, ctrl->ctlclass, FALSE);
+				else
+					error("Unknown control-class %04x", ctrl->ctlclass->name.i_name);
+			}
+			else
+				internal_error(__FILE__, __LINE__, "Control has no control-class");
+			if(ctrl->title)
+				put_string(res, ctrl->title, str_char, TRUE);
+			else
+				put_byte(res, 0);
+
+			/* FIXME: What is this extra byte doing here? */
+			put_byte(res, 0);
+			
+			nctrl++;
+			ctrl = ctrl->next;
+		}
+		/* Set number of controls */
+		((char *)res->data)[tag_nctrl] = (char)nctrl;
+	}
+	/* Set ResourceSize */
+	SetResSize(res, restag);
+	return res;
+}
+
+/*
+ *****************************************************************************
+ * Function	: dialogex2res
+ * Syntax	: res_t *dialogex2res(name_id_t *name, dialogex_t *dlgex)
+ * Input	:
+ *	name	- Name/ordinal of the resource
+ *	dlgex	- The dialogex descriptor
+ * Output	: New .res format structure
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+res_t *dialogex2res(name_id_t *name, dialogex_t *dlgex)
+{
+	int restag;
+	res_t *res;
+	control_t *ctrl;
+	int tag_nctrl;
+	int nctrl = 0;
+	assert(name != NULL);
+	assert(dlgex != NULL);
+
+	ctrl = dlgex->controls;
+	res = new_res();
+	if(win32)
+	{
+		restag = put_res_header(res, WRC_RT_DIALOG, NULL, name, dlgex->memopt, &(dlgex->lvc));
+
+		/* FIXME: MS doc says thet the first word must contain 0xffff
+		 * and the second 0x0001 to signal a DLGTEMPLATEEX. Borland's
+		 * compiler reverses the two words.
+		 * I don't know which one to choose, but I write it as Mr. B
+		 * writes it.
+		 */
+		put_word(res, 1);		/* Signature */
+		put_word(res, 0xffff);		/* DlgVer */
+		put_dword(res, dlgex->gothelpid ? dlgex->helpid : 0);
+		put_dword(res, dlgex->gotexstyle ? dlgex->exstyle : 0);
+		put_dword(res, dlgex->gotstyle ? dlgex->style : WS_POPUPWINDOW);
+		tag_nctrl = res->size;
+		put_word(res, 0);		/* Number of controls */
+		put_word(res, dlgex->x);
+		put_word(res, dlgex->y);
+		put_word(res, dlgex->width);
+		put_word(res, dlgex->height);
+		if(dlgex->menu)
+			put_name_id(res, dlgex->menu, TRUE);
+		else
+			put_word(res, 0);
+		if(dlgex->dlgclass)
+			put_name_id(res, dlgex->dlgclass, TRUE);
+		else
+			put_word(res, 0);
+		if(dlgex->title)
+			put_string(res, dlgex->title, str_unicode, TRUE);
+		else
+			put_word(res, 0);
+		if(dlgex->font)
+		{
+			put_word(res, dlgex->font->size);
+			put_word(res, dlgex->font->weight);
+			/* FIXME: ? TRUE should be sufficient to say that its
+			 * italic, but Borland's compiler says its 0x0101.
+			 * I just copy it here, and hope for the best.
+			 */
+			put_word(res, dlgex->font->italic ? 0x0101 : 0);
+			put_string(res, dlgex->font->name, str_unicode, TRUE);
+		}
+
+		put_pad(res);
+		while(ctrl)
+		{
+			put_dword(res, ctrl->gothelpid ? ctrl->helpid : 0);
+			put_dword(res, ctrl->gotexstyle ? ctrl->exstyle : 0);
+			/* FIXME: what is default control style? */
+			put_dword(res, ctrl->gotstyle ? ctrl->style : WS_CHILD | WS_VISIBLE);
+			put_word(res, ctrl->x);
+			put_word(res, ctrl->y);
+			put_word(res, ctrl->width);
+			put_word(res, ctrl->height);
+			put_word(res, ctrl->id);
+			/* FIXME: Pad is _NOT_ documented!?! */
+			put_pad(res);
+			if(ctrl->ctlclass)
+				put_name_id(res, ctrl->ctlclass, TRUE);
+			else
+				internal_error(__FILE__, __LINE__, "Control has no control-class");
+			if(ctrl->title)
+				put_string(res, ctrl->title, str_unicode, TRUE);
+			else
+				put_word(res, 0);
+			if(ctrl->extra)
+			{
+				put_pad(res);
+				put_word(res, ctrl->extra->size);
+				put_raw_data(res, ctrl->extra, 0);
+			}
+			else
+				put_word(res, 0);
+
+			put_pad(res);
+			nctrl++;
+			ctrl = ctrl->next;
+		}
+		/* Set number of controls */
+		*(WORD *)&((char *)res->data)[tag_nctrl] = (WORD)nctrl;
+		/* Set ResourceSize */
+		SetResSize(res, restag);
+		put_pad(res);
+	}
+	else /* win16 */
+	{
+		/* Do not generate anything in 16-bit mode */
+		free(res->data);
+		free(res);
+		return NULL;
+	}
+	return res;
+}
+
+/*
+ *****************************************************************************
+ * Function	: menuitem2res
+ * Syntax	: void menuitem2res(res_t *res, menu_item_t *item)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	: Self recursive
+ *****************************************************************************
+*/
+void menuitem2res(res_t *res, menu_item_t *menitem)
+{
+	menu_item_t *itm = menitem;
+	if(win32)
+	{
+		while(itm)
+		{
+			put_word(res, itm->state | (itm->popup ? MF_POPUP : 0) | (!itm->next ? MF_END : 0));
+			if(!itm->popup)
+				put_word(res, itm->id);
+			if(itm->name)
+				put_string(res, itm->name, str_unicode, TRUE);
+			else
+				put_word(res, 0);
+			if(itm->popup)
+				menuitem2res(res, itm->popup);
+			itm = itm->next;
+		}
+	}
+	else /* win16 */
+	{
+		while(itm)
+		{
+			put_word(res, itm->state | (itm->popup ? MF_POPUP : 0) | (!itm->next ? MF_END : 0));
+			if(!itm->popup)
+				put_word(res, itm->id);
+			if(itm->name)
+				put_string(res, itm->name, str_char, TRUE);
+			else
+				put_byte(res, 0);
+			if(itm->popup)
+				menuitem2res(res, itm->popup);
+			itm = itm->next;
+		}
+	}
+
+}
+
+/*
+ *****************************************************************************
+ * Function	: menu2res
+ * Syntax	: res_t *menu2res(name_id_t *name, menu_t *men)
+ * Input	:
+ *	name	- Name/ordinal of the resource
+ *	men	- The menu descriptor
+ * Output	: New .res format structure
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+res_t *menu2res(name_id_t *name, menu_t *men)
+{
+	int restag;
+	res_t *res;
+	assert(name != NULL);
+	assert(men != NULL);
+
+	res = new_res();
+	restag = put_res_header(res, WRC_RT_MENU, NULL, name, men->memopt, win32 ? &(men->lvc) : NULL);
+
+	put_dword(res, 0);		/* Menuheader: Version and HeaderSize */
+	menuitem2res(res, men->items);
+	/* Set ResourceSize */
+	SetResSize(res, restag);
+	if(win32)
+		put_pad(res);
+	return res;
+}
+
+/*
+ *****************************************************************************
+ * Function	: menuexitem2res
+ * Syntax	: void menuexitem2res(res_t *res, menuex_item_t *item)
+ * Input	:
+ * Output	: nop
+ * Description	:
+ * Remarks	: Self recursive
+ *****************************************************************************
+*/
+void menuexitem2res(res_t *res, menuex_item_t *menitem)
+{
+	menuex_item_t *itm = menitem;
+	assert(win32 != 0);
+	while(itm)
+	{
+		put_dword(res, itm->gottype ? itm->type : 0);
+		put_dword(res, itm->gotstate ? itm->state : 0);
+		put_dword(res, itm->gotid ? itm->id : 0);	/* FIXME: Docu. says word */
+		put_word(res, (itm->popup ? 0x01 : 0) | (!itm->next ? MF_END : 0));
+		if(itm->name)
+			put_string(res, itm->name, str_unicode, TRUE);
+		else
+			put_word(res, 0);
+		put_pad(res);
+		if(itm->popup)
+		{
+			put_dword(res, itm->gothelpid ? itm->helpid : 0);
+			menuexitem2res(res, itm->popup);
+		}
+		itm = itm->next;
+	}
+
+}
+
+/*
+ *****************************************************************************
+ * Function	: menuex2res
+ * Syntax	: res_t *menuex2res(name_id_t *name, menuex_t *menex)
+ * Input	:
+ *	name	- Name/ordinal of the resource
+ *	menex	- The menuex descriptor
+ * Output	: New .res format structure
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+res_t *menuex2res(name_id_t *name, menuex_t *menex)
+{
+	int restag;
+	res_t *res;
+	assert(name != NULL);
+	assert(menex != NULL);
+
+	res = new_res();
+	if(win32)
+	{
+		/* FIXME: Borland's rc compiler writes the default system's
+		 * language if none specified (0x406 for me that is). I believe
+		 * that this is a Borland bug (brc32 ver. 5.01), as the default
+		 * should be 0 (system default).
+		 */
+		restag = put_res_header(res, WRC_RT_MENU, NULL, name, menex->memopt, &(menex->lvc));
+
+		put_word(res, 1);		/* Menuheader: Version */
+		put_word(res, 4);		/* Offset */
+		put_dword(res, 0);		/* HelpId */
+		put_pad(res);
+		menuexitem2res(res, menex->items);
+		/* Set ResourceSize */
+		SetResSize(res, restag);
+		put_pad(res);
+	}
+	else /* win16 */
+	{
+		/* Do not generate anything in 16-bit mode */
+		free(res->data);
+		free(res);
+		return NULL;
+	}
+	return res;
+}
+
+/*
+ *****************************************************************************
+ * Function	: cursorgroup2res
+ * Syntax	: res_t *cursorgroup2res(name_id_t *name, cursor_group_t *curg)
+ * Input	:
+ *	name	- Name/ordinal of the resource
+ *	curg	- The cursor descriptor
+ * Output	: New .res format structure
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+res_t *cursorgroup2res(name_id_t *name, cursor_group_t *curg)
+{
+	int restag;
+	res_t *res;
+	cursor_t *cur;
+	assert(name != NULL);
+	assert(curg != NULL);
+
+	res = new_res();
+	restag = put_res_header(res, WRC_RT_GROUP_CURSOR, NULL, name, curg->memopt, NULL);
+	if(win32)
+	{
+		/* FIXME: Borland's rc compiler writes the default system's
+		 * language if none specified (0x406 for me that is). I believe
+		 * that this is a Borland bug (brc32 ver. 5.01), as the default
+		 * should be 0 (system default).
+		 */
+
+		put_word(res, 0);	/* Reserved */
+		/* FIXME: The ResType in the NEWHEADER structure should
+		 * contain 14 according to the MS win32 doc. This is
+		 * not the case with the BRC compiler and I really doubt
+		 * the latter. Putting one here is compliant to win16 spec,
+		 * but who knows the true value?
+		 */
+		put_word(res, 2);	/* ResType */
+		put_word(res, curg->ncursor);
+#if 0
+		for(cur = curg->cursorlist; cur; cur = cur->next)
+#else
+		cur = curg->cursorlist;
+		while(cur->next)
+			cur = cur->next;
+		for(; cur; cur = cur->prev)
+#endif
+		{
+			put_word(res, cur->width);
+			/* FIXME: The height of a cursor is half the size of
+			 * the bitmap's height. BRC puts the height from the
+			 * BITMAPINFOHEADER here instead of the cursorfile's
+			 * height. MS doesn't seem to care...
+			 */
+			put_word(res, cur->height);
+			/* FIXME: The next two are reversed in BRC and I don't
+			 * know why. Probably a bug. But, we can safely ignore
+			 * it because win16 does not support color cursors.
+			 * A warning should have been generated by the parser.
+			 */
+			put_word(res, cur->planes);
+			put_word(res, cur->bits);
+			/* FIXME: The +4 is the hotspot in the cursor resource.
+			 * However, I cound not find this in the documentation.
+			 * The hotspot bytes must either be included or MS
+			 * doesn't care.
+			 */
+			put_dword(res, cur->data->size +4);
+			put_word(res, cur->id);
+		}
+	}
+	else /* win16 */
+	{
+		put_word(res, 0);	/* Reserved */
+		put_word(res, 2);	/* ResType */
+		put_word(res, curg->ncursor);
+#if 0
+		for(cur = curg->cursorlist; cur; cur = cur->next)
+#else
+		cur = curg->cursorlist;
+		while(cur->next)
+			cur = cur->next;
+		for(; cur; cur = cur->prev)
+#endif
+		{
+			put_word(res, cur->width);
+			/* FIXME: The height of a cursor is half the size of
+			 * the bitmap's height. BRC puts the height from the
+			 * BITMAPINFOHEADER here instead of the cursorfile's
+			 * height. MS doesn't seem to care...
+			 */
+			put_word(res, cur->height);
+			/* FIXME: The next two are reversed in BRC and I don't
+			 * know why. Probably a bug. But, we can safely ignore
+			 * it because win16 does not support color cursors.
+			 * A warning should have been generated by the parser.
+			 */
+			put_word(res, cur->planes);
+			put_word(res, cur->bits);
+			/* FIXME: The +4 is the hotspot in the cursor resource.
+			 * However, I cound not find this in the documentation.
+			 * The hotspot bytes must either be included or MS
+			 * doesn't care.
+			 */
+			put_dword(res, cur->data->size +4);
+			put_word(res, cur->id);
+		}
+	}
+	SetResSize(res, restag);	/* Set ResourceSize */
+	if(win32)
+		put_pad(res);
+
+	return res;
+}
+
+/*
+ *****************************************************************************
+ * Function	: cursor2res
+ * Syntax	: res_t *cursor2res(cursor_t *cur)
+ * Input	:
+ *	cur	- The cursor descriptor
+ * Output	: New .res format structure
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+res_t *cursor2res(cursor_t *cur)
+{
+	int restag;
+	res_t *res;
+	name_id_t name;
+
+	assert(cur != NULL);
+
+	res = new_res();
+	name.type = name_ord;
+	name.name.i_name = cur->id;
+	/* FIXME: Borland's rc compiler writes the default system's
+	 * language if none specified (0x406 for me that is). I believe
+	 * that this is a Borland bug (brc32 ver. 5.01), as the default
+	 * should be 0 (system default).
+	 */
+	restag = put_res_header(res, WRC_RT_CURSOR, NULL, &name, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, NULL);
+	put_word(res, cur->xhot);
+	put_word(res, cur->yhot);
+	put_raw_data(res, cur->data, 0);
+
+	SetResSize(res, restag);	/* Set ResourceSize */
+	if(win32)
+		put_pad(res);
+
+	return res;
+}
+
+/*
+ *****************************************************************************
+ * Function	: icongroup2res
+ * Syntax	: res_t *icongroup2res(name_id_t *name, icon_group_t *icog)
+ * Input	:
+ *	name	- Name/ordinal of the resource
+ *	icog	- The icon group descriptor
+ * Output	: New .res format structure
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+res_t *icongroup2res(name_id_t *name, icon_group_t *icog)
+{
+	int restag;
+	res_t *res;
+	icon_t *ico;
+	assert(name != NULL);
+	assert(icog != NULL);
+
+	res = new_res();
+	restag = put_res_header(res, WRC_RT_GROUP_ICON, NULL, name, icog->memopt, NULL);
+	if(win32)
+	{
+		/* FIXME: Borland's rc compiler writes the default system's
+		 * language if none specified (0x406 for me that is). I believe
+		 * that this is a Borland bug (brc32 ver. 5.01), as the default
+		 * should be 0 (system default).
+		 */
+
+		put_word(res, 0);	/* Reserved */
+		/* FIXME: The ResType in the NEWHEADER structure should
+		 * contain 14 according to the MS win32 doc. This is
+		 * not the case with the BRC compiler and I really doubt
+		 * the latter. Putting one here is compliant to win16 spec,
+		 * but who knows the true value?
+		 */
+		put_word(res, 1);	/* ResType */
+		put_word(res, icog->nicon);
+		for(ico = icog->iconlist; ico; ico = ico->next)
+		{
+			put_byte(res, ico->width);
+			put_byte(res, ico->height);
+			put_byte(res, ico->nclr);
+			put_byte(res, 0);	/* Reserved */
+			put_word(res, ico->planes);
+			put_word(res, ico->bits);
+			put_dword(res, ico->data->size);
+			put_word(res, ico->id);
+		}
+	}
+	else /* win16 */
+	{
+		put_word(res, 0);	/* Reserved */
+		put_word(res, 1);	/* ResType */
+		put_word(res, icog->nicon);
+		for(ico = icog->iconlist; ico; ico = ico->next)
+		{
+			put_byte(res, ico->width);
+			put_byte(res, ico->height);
+			put_byte(res, ico->nclr);
+			put_byte(res, 0);	/* Reserved */
+			put_word(res, ico->planes);
+			put_word(res, ico->bits);
+			put_dword(res, ico->data->size);
+			put_word(res, ico->id);
+		}
+	}
+	SetResSize(res, restag);	/* Set ResourceSize */
+	if(win32)
+		put_pad(res);
+
+	return res;
+}
+
+/*
+ *****************************************************************************
+ * Function	: icon2res
+ * Syntax	: res_t *icon2res(icon_t *ico)
+ * Input	:
+ *	ico	- The icon descriptor
+ * Output	: New .res format structure
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+res_t *icon2res(icon_t *ico)
+{
+	int restag;
+	res_t *res;
+	name_id_t name;
+
+	assert(ico != NULL);
+
+	res = new_res();
+	name.type = name_ord;
+	name.name.i_name = ico->id;
+	/* FIXME: Borland's rc compiler writes the default system's
+	 * language if none specified (0x406 for me that is). I believe
+	 * that this is a Borland bug (brc32 ver. 5.01), as the default
+	 * should be 0 (system default).
+	 */
+	restag = put_res_header(res, WRC_RT_ICON, NULL, &name, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, NULL);
+	put_raw_data(res, ico->data, 0);
+
+	SetResSize(res, restag);	/* Set ResourceSize */
+	if(win32)
+		put_pad(res);
+
+	return res;
+}
+
+/*
+ *****************************************************************************
+ * Function	: bitmap2res
+ * Syntax	: res_t *bitmap2res(name_id_t *name, bitmap_t *bmp)
+ * Input	:
+ *	name	- Name/ordinal of the resource
+ *	bmp	- The bitmap descriptor
+ * Output	: New .res format structure
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+res_t *bitmap2res(name_id_t *name, bitmap_t *bmp)
+{
+	int restag;
+	res_t *res;
+	assert(name != NULL);
+	assert(bmp != NULL);
+
+	HEAPCHECK();
+	res = new_res();
+	HEAPCHECK();
+	restag = put_res_header(res, WRC_RT_BITMAP, NULL, name, bmp->memopt, NULL);
+	HEAPCHECK();
+	if(bmp->data->data[0] == 'B'
+	&& bmp->data->data[1] == 'M'
+	&& ((BITMAPFILEHEADER *)bmp->data->data)->bfSize == bmp->data->size
+	&& bmp->data->size >= sizeof(BITMAPFILEHEADER))
+	{
+		/* The File header is still attached, don't write it */
+		put_raw_data(res, bmp->data, sizeof(BITMAPFILEHEADER));
+	}
+	else
+	{
+		put_raw_data(res, bmp->data, 0);
+	}
+	HEAPCHECK();
+	/* Set ResourceSize */
+	SetResSize(res, restag);
+	HEAPCHECK();
+	if(win32)
+		put_pad(res);
+	HEAPCHECK();
+	return res;
+}
+
+/*
+ *****************************************************************************
+ * Function	: font2res
+ * Syntax	: res_t *font2res(name_id_t *name, font_t *fnt)
+ * Input	:
+ *	name	- Name/ordinal of the resource
+ *	fnt	- The font descriptor
+ * Output	: New .res format structure
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+res_t *font2res(name_id_t *name, font_t *fnt)
+{
+	assert(name != NULL);
+	assert(fnt != NULL);
+	warning("Fonts not yet implemented");
+	return NULL;
+}
+
+/*
+ *****************************************************************************
+ * Function	: rcdata2res
+ * Syntax	: res_t *rcdata2res(name_id_t *name, rcdata_t *rdt)
+ * Input	:
+ *	name	- Name/ordinal of the resource
+ *	rdt	- The rcdata descriptor
+ * Output	: New .res format structure
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+res_t *rcdata2res(name_id_t *name, rcdata_t *rdt)
+{
+	int restag;
+	res_t *res;
+	assert(name != NULL);
+	assert(rdt != NULL);
+
+	res = new_res();
+	restag = put_res_header(res, WRC_RT_RCDATA, NULL, name, rdt->memopt, NULL);
+	put_raw_data(res, rdt->data, 0);
+	/* Set ResourceSize */
+	SetResSize(res, restag);
+	if(win32)
+		put_pad(res);
+	return res;
+}
+
+/*
+ *****************************************************************************
+ * Function	: messagetable2res
+ * Syntax	: res_t *messagetable2res(name_id_t *name, messagetable_t *msg)
+ * Input	:
+ *	name	- Name/ordinal of the resource
+ *	msg	- The messagetable descriptor
+ * Output	: New .res format structure
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+res_t *messagetable2res(name_id_t *name, messagetable_t *msg)
+{
+	assert(name != NULL);
+	assert(msg != NULL);
+	warning("Messagetable not yet implemented");
+	return NULL;
+}
+
+/*
+ *****************************************************************************
+ * Function	: stringtable2res
+ * Syntax	: res_t *stringtable2res(stringtable_t *stt)
+ * Input	:
+ *	stt	- The stringtable descriptor
+ * Output	: New .res format structure
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+res_t *stringtable2res(stringtable_t *stt)
+{
+	res_t *res;
+	name_id_t name;
+	int i;
+	int restag;
+	DWORD lastsize = 0;
+
+	assert(stt != NULL);
+	res = new_res();
+
+	for(; stt; stt = stt->next)
+	{
+		if(!stt->nentries)
+		{
+			warning("Empty internal stringtable");
+			continue;
+		}
+		name.type = name_ord;
+		name.name.i_name = (stt->idbase >> 4) + 1;
+		restag = put_res_header(res, WRC_RT_STRING, NULL, &name, stt->memopt, win32 ? &(stt->lvc) : NULL);
+		for(i = 0; i < stt->nentries; i++)
+		{
+			if(stt->entries[i].str)
+			{
+				if(win32)
+					put_word(res, stt->entries[i].str->size);
+				else
+					put_byte(res, stt->entries[i].str->size);
+				put_string(res, stt->entries[i].str, win32 ? str_unicode : str_char, FALSE);
+			}
+			else
+			{
+				if(win32)
+					put_word(res, 0);
+				else
+					put_byte(res, 0);
+			}
+		}
+		/* Set ResourceSize */
+		SetResSize(res, restag - lastsize);
+		if(win32)
+			put_pad(res);
+		lastsize = res->size;
+	}
+	return res;
+}
+
+/*
+ *****************************************************************************
+ * Function	: user2res
+ * Syntax	: res_t *user2res(name_id_t *name, user_t *usr)
+ * Input	:
+ *	name	- Name/ordinal of the resource
+ *	usr	- The userresource descriptor
+ * Output	: New .res format structure
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+res_t *user2res(name_id_t *name, user_t *usr)
+{
+	int restag;
+	res_t *res;
+	assert(name != NULL);
+	assert(usr != NULL);
+
+	res = new_res();
+	restag = put_res_header(res, 0, usr->type, name, usr->memopt, NULL);
+	put_raw_data(res, usr->data, 0);
+	/* Set ResourceSize */
+	SetResSize(res, restag);
+	if(win32)
+		put_pad(res);
+	return res;
+}
+
+/*
+ *****************************************************************************
+ * Function	: versionblock2res
+ * Syntax	: void versionblock2res(res_t *res, ver_block_t *blk)
+ * Input	:
+ *	res	- Binary resource to write to
+ *	blk	- The version block to be written
+ * Output	:
+ * Description	:
+ * Remarks	: Self recursive
+ *****************************************************************************
+*/
+void versionblock2res(res_t *res, ver_block_t *blk, int level)
+{
+	ver_value_t *val;
+	int blksizetag;
+	int valblksizetag;
+	int valvalsizetag;
+	int tag;
+	int i;
+
+	blksizetag = res->size;
+	put_word(res, 0);	/* Will be overwritten later */
+	put_word(res, 0);
+	if(win32)
+		put_word(res, 0);	/* level ? */
+	put_string(res, blk->name, win32 ? str_unicode : str_char, TRUE);
+	put_pad(res);
+	for(val = blk->values; val; val = val->next)
+	{
+		if(val->type == val_str)
+		{
+			valblksizetag = res->size;
+			put_word(res, 0);	/* Will be overwritten later */
+			valvalsizetag = res->size;
+			put_word(res, 0);	/* Will be overwritten later */
+			if(win32)
+			{
+				put_word(res, level);
+			}
+			put_string(res, val->key, win32 ? str_unicode : str_char, TRUE);
+			put_pad(res);
+			tag = res->size;
+			put_string(res, val->value.str, win32 ? str_unicode : str_char, TRUE);
+			if(win32)
+				*(WORD *)&(res->data[valvalsizetag]) = (WORD)((res->size - tag) >> 1);
+			else
+				*(WORD *)&(res->data[valvalsizetag]) = (WORD)(res->size - tag);
+			*(WORD *)&(res->data[valblksizetag]) = (WORD)(res->size - valblksizetag);
+			put_pad(res);
+		}
+		else if(val->type == val_words)
+		{
+			valblksizetag = res->size;
+			put_word(res, 0);	/* Will be overwritten later */
+			valvalsizetag = res->size;
+			put_word(res, 0);	/* Will be overwritten later */
+			if(win32)
+			{
+				put_word(res, level);
+			}
+			put_string(res, val->key, win32 ? str_unicode : str_char, TRUE);
+			put_pad(res);
+			tag = res->size;
+			for(i = 0; i < val->value.words->nwords; i++)
+			{
+				put_word(res, val->value.words->words[i]);
+			}
+			*(WORD *)&(res->data[valvalsizetag]) = (WORD)(res->size - tag);
+			*(WORD *)&(res->data[valblksizetag]) = (WORD)(res->size - valblksizetag);
+			put_pad(res);
+		}
+		else if(val->type == val_block)
+		{
+			versionblock2res(res, val->value.block, level+1);
+		}
+		else
+		{
+			internal_error(__FILE__, __LINE__, "Invalid value indicator %d in VERSIONINFO", val->type);
+		}
+	}
+
+	/* Set blocksize */
+	*(WORD *)&(res->data[blksizetag]) = (WORD)(res->size - blksizetag);
+}
+
+/*
+ *****************************************************************************
+ * Function	: versioninfo2res
+ * Syntax	: res_t *versioninfo2res(name_id_t *name, versioninfo_t *ver)
+ * Input	:
+ *	name	- Name/ordinal of the resource
+ *	ver	- The versioninfo descriptor
+ * Output	: New .res format structure
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+res_t *versioninfo2res(name_id_t *name, versioninfo_t *ver)
+{
+	int restag;
+	int rootblocksizetag;
+	int valsizetag;
+	int tag;
+	res_t *res;
+	string_t vsvi;
+	ver_block_t *blk;
+
+	assert(name != NULL);
+	assert(ver != NULL);
+
+	vsvi.type = str_char;
+	vsvi.str.cstr = "VS_VERSION_INFO";
+	vsvi.size = 15; /* Excl. termination */
+
+	res = new_res();
+	restag = put_res_header(res, WRC_RT_VERSION, NULL, name, WRC_MO_MOVEABLE | WRC_MO_PURE, NULL);
+	rootblocksizetag = res->size;
+	put_word(res, 0);	/* BlockSize filled in later */
+	valsizetag = res->size;
+	put_word(res, 0);	/* ValueSize filled in later*/
+	if(win32)
+		put_word(res, 0);	/* Tree-level ? */
+	put_string(res, &vsvi, win32 ? str_unicode : str_char, TRUE);
+	if(win32)
+		put_pad(res);
+	tag = res->size;
+	put_dword(res, VS_FFI_SIGNATURE);
+	put_dword(res, VS_FFI_STRUCVERSION);
+	put_dword(res, (ver->filever_maj1 << 16) + (ver->filever_maj2 & 0xffff));
+	put_dword(res, (ver->filever_min1 << 16) + (ver->filever_min2 & 0xffff));
+	put_dword(res, (ver->prodver_maj1 << 16) + (ver->prodver_maj2 & 0xffff));
+	put_dword(res, (ver->prodver_min1 << 16) + (ver->prodver_min2 & 0xffff));
+	put_dword(res, ver->fileflagsmask);
+	put_dword(res, ver->fileflags);
+	put_dword(res, ver->fileos);
+	put_dword(res, ver->filetype);
+	put_dword(res, ver->filesubtype);
+	put_dword(res, 0);		/* FileDateMS */
+	put_dword(res, 0);		/* FileDateLS */
+	/* Set ValueSize */
+	*(WORD *)&(res->data[valsizetag]) = (WORD)(res->size - tag);
+	/* Descend into the blocks */
+	for(blk = ver->blocks; blk; blk = blk->next)
+		versionblock2res(res, blk, 0);
+	/* Set root block's size */
+	*(WORD *)&(res->data[rootblocksizetag]) = (WORD)(res->size - rootblocksizetag);
+
+	SetResSize(res, restag);
+	if(win32)
+		put_pad(res);
+
+	return res;
+}
+
+/*
+ *****************************************************************************
+ * Function	: prep_nid_for_label
+ * Syntax	: char *prep_nid_for_label(name_id_t *nid)
+ * Input	:
+ * Output	:
+ * Description	: Converts a resource name into the first 32 (or less)
+ *		  characters of the name with conversions.
+ * Remarks	:
+ *****************************************************************************
+*/
+#define MAXNAMELEN	32
+char *prep_nid_for_label(name_id_t *nid)
+{
+	static char buf[MAXNAMELEN+1];
+
+	assert(nid != NULL);
+
+	if(nid->type == name_str && nid->name.s_name->type == str_unicode)
+	{
+		short *sptr;
+		int i;
+		sptr = nid->name.s_name->str.wstr;
+		buf[0] = '\0';
+		for(i = 0; *sptr && i < MAXNAMELEN; i++)
+		{
+			if((unsigned)*sptr < 0x80 && isprint((char)*sptr))
+				buf[i] = *sptr++;
+			else
+				warning("Resourcename (str_unicode) contain unprintable characters or invalid translation, ignored");
+		}
+		buf[i] = '\0';
+	}
+	else if(nid->type == name_str && nid->name.s_name->type == str_char)
+	{
+		char *cptr;
+		int i;
+		cptr = nid->name.s_name->str.cstr;
+		buf[0] = '\0';
+		for(i = 0; *cptr && i < MAXNAMELEN; i++)
+		{
+			if((unsigned)*cptr < 0x80 && isprint(*cptr))
+				buf[i] = *cptr++;
+			else
+				warning("Resourcename (str_char) contain unprintable characters, ignored");
+		}
+		buf[i] = '\0';
+	}
+	else if(nid->type == name_ord)
+	{
+		sprintf(buf, "%u", nid->name.i_name);
+	}
+	else
+	{
+		internal_error(__FILE__, __LINE__, "Resource name_id with invalid type %d", nid->type);
+	}
+	return buf;
+}
+#undef MAXNAMELEN
+
+/*
+ *****************************************************************************
+ * Function	: make_c_name
+ * Syntax	: char *make_c_name(char *base, name_id_t *nid, language_t *lan)
+ * Input	:
+ * Output	:
+ * Description	: Converts a resource name into a valid c-identifier in the
+ *		  form "_base_nid".
+ * Remarks	:
+ *****************************************************************************
+*/
+char *make_c_name(char *base, name_id_t *nid, language_t *lan)
+{
+	int nlen;
+	char *buf;
+	char *ret;
+	char lanbuf[6];
+
+	sprintf(lanbuf, "%d", lan ? MAKELANGID(lan->id, lan->sub) : 0);
+	buf = prep_nid_for_label(nid);
+	nlen = strlen(buf) + strlen(lanbuf);
+	nlen += strlen(base) + 4; /* three time '_' and '\0' */
+	ret = (char *)xmalloc(nlen);
+	strcpy(ret, "_");
+	strcat(ret, base);
+	strcat(ret, "_");
+	strcat(ret, buf);
+	strcat(ret, "_");
+	strcat(ret, lanbuf);
+	return ret;
+}
+
+/*
+ *****************************************************************************
+ * Function	: get_c_typename
+ * Syntax	: char *get_c_typename(enum res_e type)
+ * Input	:
+ * Output	:
+ * Description	: Convert resource enum to char string to be used in c-name
+ *		  creation.
+ * Remarks	:
+ *****************************************************************************
+*/
+char *get_c_typename(enum res_e type)
+{
+	switch(type)
+	{
+	case res_acc:	return "Acc";
+	case res_bmp:	return "Bmp";
+	case res_cur:	return "Cur";
+	case res_curg:	return "CurGrp";
+	case res_dlg:
+	case res_dlgex:	return "Dlg";
+	case res_fnt:	return "Fnt";
+	case res_ico:	return "Ico";
+	case res_icog:	return "IcoGrp";
+	case res_men:
+	case res_menex:	return "Men";
+	case res_rdt:	return "RCDat";
+	case res_stt:	return "StrTab";
+	case res_usr:	return "Usr";
+	case res_msg:	return "MsgTab";
+	case res_ver:	return "VerInf";
+	default:	return "Oops";
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	: resources2res
+ * Syntax	: void resources2res(resource_t *top)
+ * Input	:
+ *	top	- The resource-tree to convert
+ * Output	:
+ * Description	: Convert logical resource descriptors into binary data
+ * Remarks	:
+ *****************************************************************************
+*/
+void resources2res(resource_t *top)
+{
+	while(top)
+	{
+		switch(top->type)
+		{
+		case res_acc:
+			if(!top->binres)
+				top->binres = accelerator2res(top->name, top->res.acc);
+			break;
+		case res_bmp:
+			if(!top->binres)
+				top->binres = bitmap2res(top->name, top->res.bmp);
+			break;
+		case res_cur:
+			if(!top->binres)
+				top->binres = cursor2res(top->res.cur);
+			break;
+		case res_curg:
+			if(!top->binres)
+				top->binres = cursorgroup2res(top->name, top->res.curg);
+			break;
+		case res_dlg:
+			if(!top->binres)
+				top->binres = dialog2res(top->name, top->res.dlg);
+			break;
+		case res_dlgex:
+			if(!top->binres)
+				top->binres = dialogex2res(top->name, top->res.dlgex);
+			break;
+		case res_fnt:
+			if(!top->binres)
+				top->binres = font2res(top->name, top->res.fnt);
+			break;
+		case res_ico:
+			if(!top->binres)
+				top->binres = icon2res(top->res.ico);
+			break;
+		case res_icog:
+			if(!top->binres)
+				top->binres = icongroup2res(top->name, top->res.icog);
+			break;
+		case res_men:
+			if(!top->binres)
+				top->binres = menu2res(top->name, top->res.men);
+			break;
+		case res_menex:
+			if(!top->binres)
+				top->binres = menuex2res(top->name, top->res.menex);
+			break;
+		case res_rdt:
+			if(!top->binres)
+				top->binres = rcdata2res(top->name, top->res.rdt);
+			break;
+		case res_stt:
+			if(!top->binres)
+				top->binres = stringtable2res(top->res.stt);
+			break;
+		case res_usr:
+			if(!top->binres)
+				top->binres = user2res(top->name, top->res.usr);
+			break;
+		case res_msg:
+			if(!top->binres)
+				top->binres = messagetable2res(top->name, top->res.msg);
+			break;
+		case res_ver:
+			if(!top->binres)
+				top->binres = versioninfo2res(top->name, top->res.ver);
+			break;
+		default:
+			internal_error(__FILE__, __LINE__, "Unknown resource type encountered %d in binary res generation", top->type);
+		}
+		top->c_name = make_c_name(get_c_typename(top->type), top->name, top->lan);
+		top = top->next;
+	}
+}
+
diff --git a/tools/wrc/genres.h b/tools/wrc/genres.h
new file mode 100644
index 0000000..0f4d9d2
--- /dev/null
+++ b/tools/wrc/genres.h
@@ -0,0 +1,25 @@
+/*
+ * Generate resource prototypes
+ *
+ * Copyright 1998 Bertho A. Stultiens (BS)
+ *
+ */
+
+#ifndef __WRC_GENRES_H
+#define __WRC_GENRES_H
+
+#ifndef __WRC_WRCTYPES_H
+#include "wrctypes.h"
+#endif
+
+res_t *new_res(void);
+res_t *grow_res(res_t *r, int add);
+void put_byte(res_t *res, unsigned c);
+void put_word(res_t *res, unsigned w);
+void put_dword(res_t *res, unsigned d);
+void resources2res(resource_t *top);
+char *get_c_typename(enum res_e type);
+char *make_c_name(char *base, name_id_t *nid, language_t *lan);
+char *prep_nid_for_label(name_id_t *nid);
+
+#endif
diff --git a/tools/wrc/newstruc.c b/tools/wrc/newstruc.c
new file mode 100644
index 0000000..6d33c4b
--- /dev/null
+++ b/tools/wrc/newstruc.c
@@ -0,0 +1,251 @@
+/*
+ * Create dynamic new structures of various types
+ * and some utils in that trend.
+ *
+ * Copyright 1998 Bertho A. Stultiens
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <config.h>
+#include "wrc.h"
+#include "newstruc.h"
+#include "utils.h"
+#include "parser.h"
+
+/* Generate new_* functions that have no parameters (NOTE: no ';') */
+__NEW_STRUCT_FUNC(dialog)
+__NEW_STRUCT_FUNC(dialogex)
+__NEW_STRUCT_FUNC(name_id)
+__NEW_STRUCT_FUNC(menu)
+__NEW_STRUCT_FUNC(menuex)
+__NEW_STRUCT_FUNC(menu_item)
+__NEW_STRUCT_FUNC(menuex_item)
+__NEW_STRUCT_FUNC(control)
+__NEW_STRUCT_FUNC(icon)
+__NEW_STRUCT_FUNC(cursor)
+__NEW_STRUCT_FUNC(versioninfo)
+__NEW_STRUCT_FUNC(ver_value)
+__NEW_STRUCT_FUNC(ver_block)
+__NEW_STRUCT_FUNC(stt_entry)
+__NEW_STRUCT_FUNC(accelerator)
+__NEW_STRUCT_FUNC(event)
+__NEW_STRUCT_FUNC(raw_data)
+__NEW_STRUCT_FUNC(lvc)
+__NEW_STRUCT_FUNC(res_count)
+__NEW_STRUCT_FUNC(string)
+
+/* New instances for all types of structures */
+/* Very inefficient (in size), but very functional :-]
+ * Especially for type-checking.
+ */
+resource_t *new_resource(enum res_e t, void *res, int memopt, language_t *lan)
+{
+	resource_t *r = (resource_t *)xmalloc(sizeof(resource_t));
+	r->type = t;
+	r->res.overlay = res;
+	r->memopt = memopt;
+	r->lan = lan;
+	return r;
+}
+
+version_t *new_version(DWORD v)
+{
+	version_t *vp = (version_t *)xmalloc(sizeof(version_t));
+	*vp = v;
+	return vp;
+}
+
+characts_t *new_characts(DWORD c)
+{
+	characts_t *cp = (characts_t *)xmalloc(sizeof(characts_t));
+	*cp = c;
+	return cp;
+}
+
+language_t *new_language(int id, int sub)
+{
+	language_t *lan = (language_t *)xmalloc(sizeof(language_t));
+	lan->id = id;
+	lan->sub = sub;
+	return lan;
+}
+
+language_t *dup_language(language_t *l)
+{
+	if(!l) return NULL;
+	return new_language(l->id, l->sub);
+}
+
+version_t *dup_version(version_t *v)
+{
+	if(!v) return NULL;
+	return new_version(*v);
+}
+
+characts_t *dup_characts(characts_t *c)
+{
+	if(!c) return NULL;
+	return new_characts(*c);
+}
+
+rcdata_t *new_rcdata(raw_data_t *rd, int *memopt)
+{
+	rcdata_t *rc = (rcdata_t *)xmalloc(sizeof(rcdata_t));
+	rc->data = rd;
+	if(memopt)
+	{
+		rc->memopt = *memopt;
+		free(memopt);
+	}
+	else
+		rc->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
+	return rc;
+}
+
+font_id_t *new_font_id(int size, string_t *face, int weight, int italic)
+{
+	font_id_t *fid = (font_id_t *)xmalloc(sizeof(font_id_t));
+	fid->name = face;
+	fid->size = size;
+	fid->weight = weight;
+	fid->italic = italic;
+	return fid;
+}
+
+user_t *new_user(name_id_t *type, raw_data_t *rd, int *memopt)
+{
+	user_t *usr = (user_t *)xmalloc(sizeof(user_t));
+	usr->data = rd;
+	if(memopt)
+	{
+		usr->memopt = *memopt;
+		free(memopt);
+	}
+	else
+		usr->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
+	usr->type = type;
+	return usr;
+}
+
+font_t *new_font(raw_data_t *rd, int *memopt)
+{
+	font_t *fnt = (font_t *)xmalloc(sizeof(font_t));
+	fnt->data = rd;
+	if(memopt)
+	{
+		fnt->memopt = *memopt;
+		free(memopt);
+	}
+	else
+		fnt->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
+	return fnt;
+}
+
+icon_group_t *new_icon_group(raw_data_t *rd, int *memopt)
+{
+	icon_group_t *icog = (icon_group_t *)xmalloc(sizeof(icon_group_t));
+	if(memopt)
+	{
+		icog->memopt = *memopt;
+		free(memopt);
+	}
+	else
+		icog->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
+	split_icons(rd, icog, &(icog->nicon));
+	free(rd->data);
+	free(rd);
+	return icog;
+}
+
+cursor_group_t *new_cursor_group(raw_data_t *rd, int *memopt)
+{
+	cursor_group_t *curg = (cursor_group_t *)xmalloc(sizeof(cursor_group_t));
+	if(memopt)
+	{
+		curg->memopt = *memopt;
+		free(memopt);
+	}
+	else
+		curg->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
+	split_cursors(rd, curg, &(curg->ncursor));
+	free(rd->data);
+	free(rd);
+	return curg;
+}
+
+bitmap_t *new_bitmap(raw_data_t *rd, int *memopt)
+{
+	bitmap_t *bmp = (bitmap_t *)xmalloc(sizeof(bitmap_t));
+	bmp->data = rd;
+	if(memopt)
+	{
+		bmp->memopt = *memopt;
+		free(memopt);
+	}
+	else
+		bmp->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
+	return bmp;
+}
+
+ver_words_t *new_ver_words(int i)
+{
+	ver_words_t *w = (ver_words_t *)xmalloc(sizeof(ver_words_t));
+	w->words = (WORD *)xmalloc(sizeof(WORD));
+	w->words[0] = (WORD)i;
+	w->nwords = 1;
+	return w;
+}
+
+ver_words_t *add_ver_words(ver_words_t *w, int i)
+{
+	w->words = (WORD *)xrealloc(w->words, (w->nwords+1) * sizeof(WORD));
+	w->words[w->nwords] = (WORD)i;
+	w->nwords++;
+	return w;
+}
+
+messagetable_t *new_messagetable(raw_data_t *rd)
+{
+	messagetable_t *msg = (messagetable_t *)xmalloc(sizeof(messagetable_t));
+	msg->data = rd;
+	return msg;
+}
+
+void copy_raw_data(raw_data_t *dst, raw_data_t *src, int offs, int len)
+{
+	assert(offs <= src->size);
+	assert(offs + len <= src->size);
+	if(!dst->data)
+	{
+		dst->data = (char *)xmalloc(len);
+		dst->size = 0;
+	}
+	else
+		dst->data = (char *)xrealloc(dst->data, dst->size + len);
+	/* dst->size holds the offset to copy to */
+	memcpy(dst->data + dst->size, src->data + offs, len);
+	dst->size += len;
+}
+
+int *new_int(int i)
+{
+	int *ip = (int *)xmalloc(sizeof(int));
+	*ip = i;
+	return ip;
+}
+
+stringtable_t *new_stringtable(lvc_t *lvc)
+{
+	stringtable_t *stt = (stringtable_t *)xmalloc(sizeof(stringtable_t));
+
+	if(lvc)
+		stt->lvc = *lvc;
+
+	return stt;
+}
+
+
diff --git a/tools/wrc/newstruc.h b/tools/wrc/newstruc.h
new file mode 100644
index 0000000..61d3907
--- /dev/null
+++ b/tools/wrc/newstruc.h
@@ -0,0 +1,66 @@
+/*
+ * Create dynamic new structures of various types
+ *
+ * Copyright 1998 Bertho A. Stultiens
+ *
+ */
+
+#ifndef __WRC_NEWSTRUC_H
+#define __WRC_NEWSTRUC_H
+
+#ifndef __WRC_WRCTYPES_H
+#include "wrctypes.h"
+#endif
+
+#define __NEW_STRUCT_FUNC(p)	\
+	p##_t *new_##p(void)\
+	{\
+		return (p##_t *)xmalloc(sizeof(p##_t));\
+	}
+
+#define __NEW_STRUCT_PROTO(p)	p##_t *new_##p(void)
+
+__NEW_STRUCT_PROTO(dialog);
+__NEW_STRUCT_PROTO(dialogex);
+__NEW_STRUCT_PROTO(name_id);
+__NEW_STRUCT_PROTO(menu);
+__NEW_STRUCT_PROTO(menuex);
+__NEW_STRUCT_PROTO(menu_item);
+__NEW_STRUCT_PROTO(menuex_item);
+__NEW_STRUCT_PROTO(control);
+__NEW_STRUCT_PROTO(icon);
+__NEW_STRUCT_PROTO(cursor);
+__NEW_STRUCT_PROTO(versioninfo);
+__NEW_STRUCT_PROTO(ver_value);
+__NEW_STRUCT_PROTO(ver_block);
+__NEW_STRUCT_PROTO(stt_entry);
+__NEW_STRUCT_PROTO(accelerator);
+__NEW_STRUCT_PROTO(event);
+__NEW_STRUCT_PROTO(raw_data);
+__NEW_STRUCT_PROTO(lvc);
+__NEW_STRUCT_PROTO(res_count);
+__NEW_STRUCT_PROTO(string);
+
+resource_t *new_resource(enum res_e t, void *res, int memopt, language_t *lan);
+version_t *new_version(DWORD v);
+characts_t *new_characts(DWORD c);
+language_t *new_language(int id, int sub);
+language_t *dup_language(language_t *l);
+version_t *dup_version(version_t *v);
+characts_t *dup_characts(characts_t *c);
+rcdata_t *new_rcdata(raw_data_t *rd, int *memopt);
+font_id_t *new_font_id(int size, string_t *face, int weight, int italic);
+user_t *new_user(name_id_t *type, raw_data_t *rd, int *memopt);
+font_t *new_font(raw_data_t *rd, int *memopt);
+icon_group_t *new_icon_group(raw_data_t *rd, int *memopt);
+cursor_group_t *new_cursor_group(raw_data_t *rd, int *memopt);
+bitmap_t *new_bitmap(raw_data_t *rd, int *memopt);
+ver_words_t *new_ver_words(int i);
+ver_words_t *add_ver_words(ver_words_t *w, int i);
+messagetable_t *new_messagetable(raw_data_t *rd);
+void copy_raw_data(raw_data_t *dst, raw_data_t *src, int offs, int len);
+int *new_int(int i);
+stringtable_t *new_stringtable(lvc_t *lvc);
+
+#endif
+
diff --git a/tools/wrc/parser.h b/tools/wrc/parser.h
new file mode 100644
index 0000000..a038371
--- /dev/null
+++ b/tools/wrc/parser.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 1998 Bertho A. Stultiens (BS)
+ *
+ * Shared things between parser.l and parser.y and some others
+ */
+
+#ifndef __WRC_PARSER_H
+#define __WRC_PARSER_H
+
+/* From parser.y */
+extern int yydebug;
+extern int indialog;		/* Set when parsing dialogs */
+extern int want_rscname;	/* Set when a resource's name is required */
+
+int yyparse(void);
+void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico);
+void split_cursors(raw_data_t *rd, cursor_group_t *curg, int *ncur);
+
+/* From parser.l */
+extern FILE *yyin;
+extern int line_number;
+
+int yylex(void);
+void set_yywf(void);
+void set_pp_ignore(int state);
+void push_to(int start);
+void pop_start(void);
+void strip_til_semicolon(void);
+void strip_til_parenthesis(void);
+
+#endif
+
diff --git a/tools/wrc/parser.l b/tools/wrc/parser.l
new file mode 100644
index 0000000..7b411d8
--- /dev/null
+++ b/tools/wrc/parser.l
@@ -0,0 +1,862 @@
+/* -*-C-*-
+ *
+ * Copyright 1994 Martin von Loewis
+ * Copyright 1998 Bertho A. Stultiens (BS)
+ *
+ * 19-May-1998 BS	- Started to build a preprocessor.
+ *			- Changed keyword processing completely to
+ *			  table-lookups.
+ *
+ * 20-Apr-1998 BS	- Added ';' comment stripping
+ *
+ * 17-Apr-1998 BS	- Made the win32 keywords optional when compiling in
+ *			  16bit mode
+ *
+ * 15-Apr-1998 BS	- Changed string handling to include escapes
+ *			- Added unicode string handling (no codepage
+ *			  translation though).
+ *			- 'Borrowed' the main idea of string scanning from
+ *			  the flex manual pages.
+ *			- Added conditional handling of scanning depending
+ *			  on the state of the parser. This was mainly required
+ *			  to distinguish a file to load or raw data that
+ *			  follows. MS's definition of filenames is rather
+ *			  complex... It can be unquoted or double quoted. If
+ *			  double quoted, then the '\\' char is not automatically
+ *			  escaped according to Borland's rc compiler, but it
+ *			  accepts both "\\path\\file.rc" and "\path\file.rc".
+ *			  This makes life very hard! I go for the escaped
+ *			  version, as this seems to be the documented way...
+ *			- Single quoted strings are now parsed and converted
+ *			  here.
+ *			- Added comment stripping. The implementation is
+ *			  'borrowed' from the flex manpages.
+ *			- Rebuild string processing so that it may contain
+ *			  escaped '\0'.
+ */
+
+/* Exclusive rules when looking for a filename */
+%x yywf
+/* Exclusive string handling */
+%x yystr
+/* Exclusive unicode string handling */
+%x yylstr
+/* Exclusive rcdata single quoted data handling */
+%x yyrcd
+/* Exclusive comment eating... */
+%x comment
+/* Preprocessor exclusives */
+%x pp_incl
+%x pp_def
+%x pp_undef
+%x pp_if
+%x pp_ifdef
+%x pp_ifndef
+%x pp_elif
+%x pp_else
+%x pp_endif
+%x pp_error
+/* Set when accumulating #define's expansion text */
+%x pp_def_s
+/* Set when processing function type defines */
+%x pp_ignore
+/* Set when need to strip to eol */
+%x pp_ignore_eol
+/* Set when handling a false #if case */
+%x pp_false
+/* Set when stripping c-junk */
+%x pp_strips
+%x pp_stripp
+%x pp_stripp_final
+
+/*%option stack*/
+%option never-interactive
+/*%option noyywrap */
+/* Some shortcut definitions */
+ws	[ \f\t\r]
+cident	[a-zA-Z_][0-9a-zA-Z_]*
+
+%{
+
+/*#define LEX_DEBUG*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <config.h>
+#include "wrc.h"
+#include "utils.h"
+#include "preproc.h"
+#include "parser.h"
+#include "newstruc.h"
+
+#include "y.tab.h"
+
+#define YY_USE_PROTOS
+#define YY_NO_UNPUT
+
+raw_data_t *new_raw_data(void);
+
+void addcchar(char c);
+void addwchar(short s);
+string_t *get_buffered_cstring(void);
+string_t *get_buffered_wstring(void);
+string_t *make_string(char *s);
+
+int line_number = 1;
+static char cbuffer[1024];	/* Buffers for string collection */
+static int cbufidx;
+static short wbuffer[1024];
+static int wbufidx;
+static int want_nl = 0;		/* Set when newline needs to go to parser */
+static int want_ident = 0;	/* Set is #ifdef, #ifndef or defined is seen */
+static int stripslevel = 0;	/* Count {} during pp_strips mode */
+static int stripplevel = 0;	/* Count () during pp_strips mode */
+static char *substtext = NULL;	/* Holds the substition text while getting a define */
+static int cjunk_tagline;	/* Where did we start stripping (helps error tracking) */
+
+#ifdef YY_USE_STACK
+void push_to(int start)	{ yy_push_state(start); }
+void pop_start(void)	{ yy_pop_state(start); }
+#else
+#define MAXSTARTSTACK	32
+static int startstack[MAXSTARTSTACK];
+static int startstackidx = 0;
+
+void push_to(int start)
+{
+	if(yydebug)
+		printf("push_to(%d): %d -> %d\n", line_number, YY_START, start);
+	if(startstackidx >= MAXSTARTSTACK-1)
+		internal_error(__FILE__, __LINE__, "Start condition stack overflow");
+	startstack[startstackidx++] = YY_START;
+	BEGIN(start);
+}
+
+void pop_start(void)
+{
+	if(yydebug)
+		printf("pop_start(%d): %d <- %d\n", line_number, startstack[startstackidx-1], YY_START);
+	if(startstackidx <= 0)
+		internal_error(__FILE__, __LINE__, "Start condition stack underflow");
+	--startstackidx;
+	BEGIN(startstack[startstackidx]);
+}
+#endif
+
+
+struct bufferstackentry {
+	YY_BUFFER_STATE	bufferstate;	/* Buffer to switch back to */
+	struct pp_entry	*define;	/* Points to expanding define
+					   or NULL if handling includes
+					 */
+	int line_number;		/* Line that we were handling */
+	char *filename;			/* Filename that we were handling */
+};
+
+#define MAXBUFFERSTACK 128
+static struct bufferstackentry bufferstack[MAXBUFFERSTACK];
+static int bufferstackidx = 0;
+
+void push_buffer(YY_BUFFER_STATE buf, struct pp_entry *ppp, char *filename)
+{
+	if(yydebug)
+		printf("push_buffer: %p %p %p\n", buf, ppp, filename);
+	if(bufferstackidx >= MAXBUFFERSTACK-1)
+		internal_error(__FILE__, __LINE__, "Buffer stack overflow");
+	memset(&bufferstack[bufferstackidx], 0, sizeof(bufferstack[0]));
+	bufferstack[bufferstackidx].bufferstate = buf;
+	bufferstack[bufferstackidx].define = ppp;
+	if(ppp)
+		ppp->expanding = 1;
+	else if(filename)
+	{
+		/* These will track the yyerror to the correct file and line */
+		bufferstack[bufferstackidx].line_number = line_number;
+		line_number = 1;
+		bufferstack[bufferstackidx].filename = input_name;
+		input_name = filename;
+	}
+	else
+		internal_error(__FILE__, __LINE__, "Pushing buffer without knowing where to go to");
+	bufferstackidx++;
+}
+
+YY_BUFFER_STATE pop_buffer(void)
+{
+	if(bufferstackidx <= 0)
+		return (YY_BUFFER_STATE)0;
+	bufferstackidx--;
+	if(bufferstack[bufferstackidx].define)
+		bufferstack[bufferstackidx].define->expanding = 0;
+	else
+	{
+		line_number = bufferstack[bufferstackidx].line_number;
+		input_name = bufferstack[bufferstackidx].filename;
+		fclose(yyin);
+	}
+	if(yydebug)
+		printf("pop_buffer: %p %p (%d) %p\n",
+			bufferstack[bufferstackidx].bufferstate,
+			bufferstack[bufferstackidx].define,
+			bufferstack[bufferstackidx].line_number,
+			bufferstack[bufferstackidx].filename);
+	yy_switch_to_buffer(bufferstack[bufferstackidx].bufferstate);
+	return bufferstack[bufferstackidx].bufferstate;
+}
+
+void do_include(char *name, int namelen)
+{
+	char *cpy = (char *)xmalloc(namelen);
+	strcpy(cpy, name+1);	/* strip leading " or < */
+	cpy[namelen-2] = '\0';	/* strip trailing " or > */
+	if((yyin = open_include(cpy, name[0] == '"')) == NULL)
+		yyerror("Unable to open include file %s", cpy);
+	push_buffer(YY_CURRENT_BUFFER, NULL, cpy);
+	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+}
+
+
+struct keyword {
+	char	*keyword;
+	int	token;
+	int	isextension;
+	int	needcase;
+	int	alwayskeyword;
+};
+
+static struct keyword keywords[] = {
+	{ "ACCELERATORS", ACCELERATORS, 0, 0, 0},
+	{ "ALT", ALT, 0, 0, 0},
+	{ "ASCII", ASCII, 0, 0, 0},
+	{ "AUTO3STATE", AUTO3STATE, 1, 0, 0},
+	{ "AUTOCHECKBOX", AUTOCHECKBOX, 1, 0, 0},
+	{ "AUTORADIOBUTTON", AUTORADIOBUTTON, 1, 0, 0},
+	{ "BEGIN", tBEGIN, 0, 0, 1},
+	{ "BITMAP", tBITMAP, 0, 0, 0},
+	{ "BLOCK", BLOCK, 0, 0, 1},
+	{ "CAPTION", CAPTION, 0, 0, 0},
+	{ "CHARACTERISTICS", CHARACTERISTICS, 1, 0, 0},
+	{ "CHECKBOX", CHECKBOX, 0, 0, 0},
+	{ "CHECKED", CHECKED, 0, 0, 0},
+	{ "CLASS", CLASS, 0, 0, 0},
+	{ "COMBOBOX", COMBOBOX, 0, 0, 0},
+	{ "CONTROL", CONTROL, 0, 0, 0},
+	{ "CTEXT", CTEXT, 0, 0, 0},
+	{ "CURSOR", CURSOR, 0, 0, 0},
+	{ "defined", tDEFINED, 0, 1, 1},
+	{ "DEFPUSHBUTTON", DEFPUSHBUTTON, 0, 0, 1},
+	{ "DIALOG", DIALOG, 0, 0, 0},
+	{ "DIALOGEX", DIALOGEX, 1, 0, 0},
+	{ "DISCARDABLE", DISCARDABLE, 0, 0, 0},
+	{ "EDITTEXT", EDITTEXT, 0, 0, 0},
+	{ "END", tEND, 0, 0, 1},
+	{ "EXSTYLE", EXSTYLE, 0, 0, 0},
+	{ "extern", tEXTERN, 0, 1, 1},
+	{ "FILEFLAGS", FILEFLAGS, 0, 0, 0},
+	{ "FILEFLAGSMASK", FILEFLAGSMASK, 0, 0, 0},
+	{ "FILEOS", FILEOS, 0, 0, 0},
+	{ "FILESUBTYPE", FILESUBTYPE, 0, 0, 0},
+	{ "FILETYPE", FILETYPE, 0, 0, 0},
+	{ "FILEVERSION", FILEVERSION, 0, 0, 0},
+	{ "FIXED", tFIXED, 0, 0, 0},
+	{ "FONT", FONT, 0, 0, 0},
+	{ "GRAYED", GRAYED, 0, 0, 0},
+	{ "GROUPBOX", GROUPBOX, 0, 0, 0},
+	{ "HELP", HELP, 0, 0, 0},
+	{ "ICON", ICON, 0, 0, 0},
+	{ "IMPURE", IMPURE, 0, 0, 0},
+	{ "INACTIVE", INACTIVE, 0, 0, 0},
+	{ "LANGUAGE", LANGUAGE, 1, 0, 1},
+	{ "LISTBOX", LISTBOX, 0, 0, 0},
+	{ "LOADONCALL", LOADONCALL, 0, 0, 0},
+	{ "LTEXT", LTEXT, 0, 0, 0},
+	{ "MENU", MENU, 0, 0, 0},
+	{ "MENUBARBREAK", MENUBARBREAK, 0, 0, 0},
+	{ "MENUBREAK", MENUBREAK, 0, 0, 0},
+	{ "MENUEX", MENUEX, 1, 0, 0},
+	{ "MENUITEM", MENUITEM, 0, 0, 0},
+	{ "MESSAGETABLE", MESSAGETABLE, 1, 0, 0},
+	{ "MOVEABLE", MOVEABLE, 0, 0, 0},
+	{ "NOINVERT", NOINVERT, 0, 0, 0},
+	{ "NOT", NOT, 0, 0, 0},
+	{ "POPUP", POPUP, 0, 0, 0},
+	{ "PRELOAD", PRELOAD, 0, 0, 0},
+	{ "PRODUCTVERSION", PRODUCTVERSION, 0, 0, 0},
+	{ "PURE", tPURE, 0, 0, 0},
+	{ "PUSHBUTTON", PUSHBUTTON, 0, 0, 0},
+	{ "RADIOBUTTON", RADIOBUTTON, 0, 0, 0},
+	{ "RCDATA", RCDATA, 0, 0, 0},
+	{ "RTEXT", RTEXT, 0, 0, 0},
+	{ "SCROLLBAR", SCROLLBAR, 0, 0, 0},
+	{ "SEPARATOR", SEPARATOR, 0, 0, 0},
+	{ "SHIFT", SHIFT, 0, 0, 0},
+	{ "STATE3", STATE3, 1, 0, 0},
+	{ "STRING", tSTRING, 0, 0, 0},
+	{ "STRINGTABLE", STRINGTABLE, 0, 0, 1},
+	{ "STYLE", STYLE, 0, 0, 0},
+	{ "typedef", tTYPEDEF, 0, 1, 1},
+	{ "VALUE", VALUE, 0, 0, 0},
+	{ "VERSION", VERSION, 1, 0, 0},
+	{ "VERSIONINFO", VERSIONINFO, 0, 0, 0},
+	{ "VIRTKEY", VIRTKEY, 0, 0, 0}
+};
+
+#define NKEYWORDS	(sizeof(keywords)/sizeof(keywords[0]))
+#define KWP(p)		((struct keyword *)(p))
+int kw_cmp_func(const void *s1, const void *s2)
+{
+	int ret;
+	ret = stricmp(KWP(s1)->keyword, KWP(s2)->keyword);
+	if(!ret && (KWP(s1)->needcase || KWP(s2)->needcase))
+		return strcmp(KWP(s1)->keyword, KWP(s2)->keyword);
+	else
+		return ret;
+}
+
+#define KW_BSEARCH
+#define DO_SORT
+struct keyword *iskeyword(char *kw)
+{
+	struct keyword *kwp;
+	struct keyword key;
+	key.keyword = kw;
+	key.needcase = 0;
+#ifdef DO_SORT
+	{
+		/* Make sure that it is sorted for bsearsh */
+		static int sorted = 0;
+		if(!sorted)
+		{
+			qsort(keywords, NKEYWORDS, sizeof(keywords[0]), kw_cmp_func);
+			sorted = 1;
+		}
+	}
+#endif
+#ifdef KW_BSEARCH
+	kwp = bsearch(&key, keywords, NKEYWORDS, sizeof(keywords[0]), kw_cmp_func);
+#else
+	{
+		int i;
+		for(i = 0; i < NKEYWORDS; i++)
+		{
+			if(!kw_cmp_func(&key, &keywords[i]))
+				break;
+		}
+		if(i < NKEYWORDS)
+			kwp = &keywords[i];
+		else
+			kwp = NULL;
+	}
+#endif
+
+#ifdef LEX_DEBUG
+	if(kwp && !strcmp(kwp->keyword, "LANGUAGE"))
+		printf("Got Language\n");
+#endif
+	if(kwp == NULL || (kwp->isextension && !extensions))
+		return NULL;
+	else
+		return kwp;
+}
+
+void add_to_substtext(char *text, int len)
+{
+	if(!substtext)
+	{
+		substtext = xstrdup(text);
+	}
+	else
+	{
+		substtext = (char *)xrealloc(substtext, strlen(substtext)+len+1);
+		strcat(substtext, text);
+	}
+}
+
+%}
+
+%%
+	/* #include handling */
+^{ws}*#{ws}*include{ws}*	push_to(pp_incl);
+<pp_incl>\<[^\n\>]+\>		do_include(yytext, yyleng); pop_start();
+<pp_incl>\"[^\n\>]+\"		do_include(yytext, yyleng); pop_start();
+<pp_incl>.		yyerror("Malformed #include");
+
+	/* #define handling */
+^{ws}*#{ws}*define{ws}*	push_to(pp_def);
+<pp_def>{cident}	{
+				set_define(yytext);
+				push_to(pp_def_s);
+			}
+<pp_def>{cident}\(	push_to(pp_ignore); /* Ignore function-like defines for now*/
+<pp_def>.		yyerror("Malformed #define");
+
+<pp_ignore,pp_def_s>[^\/\\\n]*	{
+			if(YY_START == pp_def_s)
+				add_to_substtext(yytext, yyleng);
+		}
+<pp_ignore,pp_def_s>\/[^\/\*][^\/\\\n]*	{ /* Comment is handled in normal handling */
+			if(YY_START == pp_def_s)
+				add_to_substtext(yytext, yyleng);
+		}
+<pp_ignore,pp_def_s>\\{ws}*\n	line_number++;	/* Line continuation */
+<pp_ignore,pp_def_s>\n		{
+			if(YY_START == pp_def_s)
+			{
+				add_define(substtext ? substtext : "");
+				free(substtext);
+				substtext = NULL;
+			}
+			line_number++;
+			pop_start();
+			pop_start();
+		}
+
+	/* #undef handling */
+^{ws}*#{ws}*undef{ws}*	push_to(pp_undef);
+<pp_undef>{cident}	{
+				del_define(yytext);
+				pop_start();
+				/*push_to(pp_ignore);*/
+			}
+
+	/* Conditional handling */
+<INITIAL,pp_strips,pp_stripp,pp_false>^{ws}*#{ws}*if{ws}*	{
+			if(YY_START == pp_false)
+			{
+				if(yydebug)
+					printf("(%d)#if ignored\n", line_number);
+				push_if(0, 0, 1);
+				push_to(pp_ignore_eol);
+			}
+			else
+			{
+				push_to(INITIAL);
+				want_nl = 1;
+				return tIF;
+			}
+		}
+<INITIAL,pp_strips,pp_stripp,pp_false>^{ws}*#{ws}*ifdef{ws}*	{
+			if(YY_START == pp_false)
+			{
+				if(yydebug)
+					printf("(%d)#ifdef ignored\n", line_number);
+				push_if(0, 0, 1);
+				push_to(pp_ignore_eol);
+			}
+			else
+			{
+				push_to(INITIAL);
+				want_nl = 1;
+				want_ident = 1;
+				return tIFDEF;
+			}
+		}
+<INITIAL,pp_strips,pp_stripp,pp_false>^{ws}*#{ws}*ifndef{ws}*	{
+			if(YY_START == pp_false)
+			{
+				if(yydebug)
+					printf("(%d)#ifndef ignored\n", line_number);
+				push_if(0, 0, 1);
+				push_to(pp_ignore_eol);
+			}
+			else
+			{
+				push_to(INITIAL);
+				want_nl = 1;
+				want_ident = 1;
+				return tIFNDEF;
+			}
+		}
+<INITIAL,pp_strips,pp_stripp,pp_false>^{ws}*#{ws}*elif{ws}*	{
+			if(!isnevertrue_if())
+			{
+				push_to(INITIAL);
+				want_nl = 1;
+				return tELIF;
+			}
+			else if(YY_START == pp_false)
+				push_to(pp_ignore_eol);
+			if(yydebug)
+				printf("(%d)#elif ignored\n", line_number);
+		}
+<INITIAL,pp_strips,pp_stripp,pp_false>^{ws}*#{ws}*else{ws}*	{
+			if(!isnevertrue_if())
+			{
+				push_to(INITIAL);
+				want_nl = 1;
+				return tELSE;
+			}
+			if(yydebug)
+				printf("(%d)#else ignored\n", line_number);
+		}
+<INITIAL,pp_strips,pp_stripp,pp_false>^{ws}*#{ws}*endif{ws}*	{
+			if(!isnevertrue_if())
+			{
+				want_nl = 1;
+				return tENDIF;
+			}
+			else
+			{
+				if(yydebug)
+					printf("(%d)#endif ignored\n", line_number);
+				pop_if();
+			}
+		}
+
+	/* The error directive */
+^{ws}*#{ws}*error{ws}*	push_to(pp_error);
+<pp_error>[^\n]*	yyerror("Error directive: %s", yytext);
+
+	/* preprocessor junk */
+^{ws}*#{ws}*pragma[^\n]*	;	/* Ignore #pragma */
+^{ws}*#{ws}*line[^\n]*		;	/* Ignore #line */
+ /* We'll get an error on malformed #xxx statements
+  * by not recognising '#' at all. This helps tracking
+  * preprocessor errors.
+  */
+ /*^{ws}*#{ws}*			;	 Ignore # */
+
+<pp_strips>\{		stripslevel++;
+<pp_strips>\}		stripslevel--;
+<pp_strips>;		if(!stripslevel) pop_start();
+<pp_strips>[^\{\};\n#]*	; /* Ignore rest */
+
+<pp_stripp>\(		stripplevel++;
+<pp_stripp>\)		{
+				stripplevel--;
+				if(!stripplevel)
+				{
+					pop_start();
+					push_to(pp_stripp_final);
+				}
+			}
+<pp_stripp>[^\(\);\n#]*	; /* Ignore rest */
+
+<pp_stripp_final>{ws}*	; /* Ignore */
+<pp_stripp_final>;	pop_start(); /* Kill the semicolon */
+<pp_stripp_final>\n	line_number++; pop_start();
+<pp_stripp_final>.	yyless(0); pop_start();
+
+<pp_false>.		;	/* Ignore everything except #xxx during false #if state */
+
+<pp_ignore_eol>[^\n]*	pop_start();
+
+ /* These are special cases due to filename scanning */
+<yywf>[Dd][Ii][Ss][Cc][Aa][Rr][Dd][Aa][Bb][Ll][Ee]	return DISCARDABLE;
+<yywf>[Ff][Ii][Xx][Ee][Dd]				return tFIXED;
+<yywf>[Ii][Mm][Pp][Uu][Rr][Ee]				return IMPURE;
+<yywf>[Mm][Oo][Vv][Ee][Aa][Bb][Ll][Ee]			return MOVEABLE;
+<yywf>[Ll][Oo][Aa][Dd][Oo][Nn][Cc][Aa][Ll][Ll]		return LOADONCALL;
+<yywf>[Pp][Rr][Ee][Ll][Oo][Aa][Dd]			return PRELOAD;
+<yywf>[Pp][Uu][Rr][Ee]					return tPURE;
+
+\{			return tBEGIN;
+\}			return tEND;
+
+[0-9]+[lL]?		{ yylval.num = atoi(yytext); return NUMBER; }
+0[xX][0-9A-Fa-f]+[lL]?	{ yylval.num = strtoul(yytext,0,16); return NUMBER; }
+0[oO][0-7]+		{ yylval.num = strtoul(yytext+2,0,8); return NUMBER; }
+[A-Za-z_0-9]+		{
+				struct keyword *token;
+				struct pp_entry *ppp;
+
+				want_rscname = 0;
+				
+				if(want_ident)
+				{
+					/* Prevent preprocessor subst */
+					want_ident = 0;
+					yylval.str = make_string(yytext);
+				#ifdef LEX_DEBUG
+					printf("want IDENT (%s, %d): <%s>\n", input_name, line_number, yytext);
+				#endif
+					return IDENT;
+				}
+				else if((ppp = pp_lookup(yytext)) != NULL)
+				{
+					/* Do preprocessor substitution,
+					 * but expand only if macro is not
+					 * already expanding.
+					 */
+					if(!ppp->expanding)
+					{
+				#ifdef LEX_DEBUG
+						printf("expand IDENT (%s, %d): <%s>\n", input_name, line_number, yytext);
+				#endif
+						push_buffer(YY_CURRENT_BUFFER, ppp, NULL);
+						yy_scan_string(ppp->subst);
+					}
+				}
+				else if((token = iskeyword(yytext)) != NULL
+				  && !(!token->alwayskeyword && want_rscname))
+				{
+					switch(token->token)
+					{
+					case tDEFINED:
+						want_ident = 1;
+						break;
+					/*case RCDATA:*/
+					case CURSOR:
+					case tBITMAP:
+					case MESSAGETABLE:
+						push_to(yywf);
+						break;
+					case FONT:
+					case ICON:
+						if(!indialog)
+							push_to(yywf);
+						break;
+					case DIALOG:
+					case DIALOGEX:
+						indialog = 1;
+						break;
+					}
+					return token->token;
+				}
+				else
+				{
+					yylval.str = make_string(yytext);
+				#ifdef LEX_DEBUG
+					printf("%s IDENT (%s, %d): <%s>\n",
+						want_rscname ? "rscname" : "just",
+						input_name,
+						line_number,
+						yytext);
+				#endif
+					return IDENT;
+				}
+			}
+\|\|			return LOGOR;
+\&\&			return LOGAND;
+\=\=			return EQ;
+\!\=			return NE;
+\<\=			return LTE;
+\>\=			return GTE;
+
+<yywf>[^ \f\t\r\n]*	{ pop_start(); yylval.str = make_string(yytext); return FILENAME; }
+<yywf>\"[^\"]*\"	{ pop_start(); yylval.str = make_string(yytext); return FILENAME; }
+
+L\"			{
+				push_to(yylstr);
+				wbufidx = 0;
+				if(!win32)
+					yywarning("16bit resource contains unicode strings\n");
+			}
+<yylstr>\"		{
+				pop_start();
+				yylval.str = get_buffered_wstring();
+				return tSTRING;
+			}
+<yylstr>\n		yyerror("Unterminated string");
+<yylstr>\\[0-7]{1,6}	{ /* octal escape sequence */
+				int result;
+				result = strtol(yytext+1, 0, 8);
+				if ( result > 0xffff )
+					yyerror("Character constant out of range");
+				addwchar((short)result);
+			}
+<yylstr>\\x[0-9a-fA-F]{4} {  /* hex escape sequence */
+				int result;
+				result = strtol(yytext+2, 0, 16);
+				addwchar((short)result);
+			}
+<yylstr>\\[0-9]+	yyerror("Bad escape secuence");
+<yylstr>\\a		addwchar('\a');
+<yylstr>\\b		addwchar('\b');
+<yylstr>\\f		addwchar('\f');
+<yylstr>\\n		addwchar('\n');
+<yylstr>\\r		addwchar('\r');
+<yylstr>\\t		addwchar('\t');
+<yylstr>\\v		addwchar('\v');
+<yylstr>\\(.|\n)	addwchar(yytext[1]);
+<yylstr>[^\\\n\"]+	{
+				char *yptr = yytext;
+				while(*yptr)	/* FIXME: codepage translation */
+					addwchar(*yptr++ & 0xff);
+			}
+
+\"			{
+				push_to(yystr);
+				cbufidx = 0;
+			}
+<yystr>\"		{
+				pop_start();
+				yylval.str = get_buffered_cstring();
+				return tSTRING;
+			}
+<yystr>\n		yyerror("Unterminated string");
+<yystr>\\[0-7]{1,3}	{ /* octal escape sequence */
+				int result;
+				result = strtol(yytext+1, 0, 8);
+				if ( result > 0xff )
+					yyerror("Character constant out of range");
+				addcchar((char)result);
+			}
+<yystr>\\x[0-9a-fA-F]{2} {  /* hex escape sequence */
+				int result;
+				result = strtol(yytext+2, 0, 16);
+				addcchar((char)result);
+			}
+<yystr>\\[0-9]+		yyerror("Bad escape secuence");
+<yystr>\\a		addcchar('\a');
+<yystr>\\b		addcchar('\b');
+<yystr>\\f		addcchar('\f');
+<yystr>\\n		addcchar('\n');
+<yystr>\\r		addcchar('\r');
+<yystr>\\t		addcchar('\t');
+<yystr>\\v		addcchar('\v');
+<yystr>\\(.|\n)		addcchar(yytext[1]);
+<yystr>[^\\\n\"]+	{
+				char *yptr = yytext;
+				while(*yptr)
+					addcchar(*yptr++);
+			}
+
+
+
+\'			{
+				push_to(yyrcd);
+				cbufidx = 0;
+			}
+<yyrcd>\'		{
+				pop_start();
+				yylval.raw = new_raw_data();
+				yylval.raw->size = cbufidx;
+				yylval.raw->data = xmalloc(yylval.raw->size);
+				memcpy(yylval.raw->data, cbuffer, yylval.raw->size);
+				return RAWDATA;
+			}
+<yyrcd>[0-9a-fA-F]{2}	{
+				int result;
+				result = strtol(yytext, 0, 16);
+				addcchar((char)result);
+			}
+<yyrcd>{ws}+		;	/* Ignore space */
+<yyrcd>.		yyerror("Malformed data-line");
+
+<INITIAL,pp_ignore,pp_def_s>"/*"	push_to(comment);	/* Eat comment */
+<comment>[^*\n]*	;
+<comment>"*"+[^*/\n]*	;
+<comment>\n		line_number++;
+<comment>"*"+"/"	pop_start();
+
+;[^\n]*			; /* Eat comment */
+<INITIAL,pp_ignore,pp_def_s>"//"[^\n]*		; /* Eat comment */
+
+<INITIAL,yywf,pp_false,pp_strips,pp_stripp>\n	{
+				if(YY_START == yywf)
+					pop_start();
+				line_number++;
+				if(want_nl)
+				{
+					want_nl = 0;
+					return tNL;
+				}
+			}
+<INITIAL,yywf>{ws}+	;	/* Eat whitespace */
+
+<INITIAL>.		return yytext[0];
+<<EOF>>			{
+				YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+				if(!pop_buffer())
+					if(YY_START == pp_strips || YY_START == pp_stripp || YY_START == pp_stripp_final)
+						yyerror("Unexpected end of file during c-junk scanning (started at %d)", cjunk_tagline);
+					else
+						yyterminate();
+				yy_delete_buffer(b);
+			}
+%%
+
+#ifndef yywrap
+int yywrap(void)
+{
+//	if(bufferstackidx > 0)
+//	{
+//		return 0;
+//	}
+	return 1;
+}
+#endif
+
+/* These dup functions copy the enclosed '\0' from
+ * the resource string.
+ */
+void addcchar(char c)
+{
+	if(cbufidx >= sizeof(cbuffer))
+		internal_error(__FILE__, __LINE__, "Character buffer overflow");
+	cbuffer[cbufidx++] = c;
+}
+
+void addwchar(short s)
+{
+	if(wbufidx >= sizeof(wbuffer))
+		internal_error(__FILE__, __LINE__, "Wide character buffer overflow");
+	wbuffer[wbufidx++] = (short)(s & 0xff);
+}
+
+string_t *get_buffered_cstring(void)
+{
+	string_t *str = new_string();
+	str->size = cbufidx;
+	str->type = str_char;
+	str->str.cstr = (char *)xmalloc(cbufidx+1);
+	memcpy(str->str.cstr, cbuffer, cbufidx);
+	str->str.cstr[cbufidx] = '\0';
+/*	printf("got cstring \"%s\"\n", str->str.cstr); */
+	return str;
+}
+
+string_t *get_buffered_wstring(void)
+{
+	string_t *str = new_string();
+	str->size = wbufidx;
+	str->type = str_unicode;
+	str->str.wstr = (short *)xmalloc(2*(wbufidx+1));
+	memcpy(str->str.wstr, wbuffer, wbufidx);
+	str->str.wstr[wbufidx] = 0;
+	return str;
+}
+
+string_t *make_string(char *s)
+{
+	string_t *str = new_string();
+	str->size = strlen(s);
+	str->type = str_char;
+	str->str.cstr = (char *)xmalloc(str->size+1);
+	memcpy(str->str.cstr, s, str->size+1);
+	return str;
+}
+
+/* Called from the parser to signal filename request */
+void set_yywf(void)
+{
+	push_to(yywf);
+}
+
+/* Called from the parser to signal preprocessor if case */
+void set_pp_ignore(int state)
+{
+	if(state)
+		push_to(pp_false);
+	else
+		pop_start();
+}
+
+/* Called from the parser to kill c-junk */
+void strip_til_semicolon(void)
+{
+	cjunk_tagline = line_number;
+	push_to(pp_strips);
+}
+
+void strip_til_parenthesis(void)
+{
+	cjunk_tagline = line_number;
+	stripplevel = 1;	/* One scanned already */
+	push_to(pp_stripp);
+}
+
+
diff --git a/tools/wrc/parser.y b/tools/wrc/parser.y
new file mode 100644
index 0000000..6186da9
--- /dev/null
+++ b/tools/wrc/parser.y
@@ -0,0 +1,2264 @@
+%{
+/*
+ * Copyright  Martin von Loewis, 1994
+ * Copyright 1998 Bertho A. Stultiens (BS)
+ *
+ * 25-May-1998 BS	- Found out that I need to support language, version
+ *			  and characteristics in inline resources (bitmap,
+ *			  cursor, etc) but they can also be specified with
+ *			  a filename. This renders my filename-scanning scheme
+ *			  worthless. Need to build newline parsing to solve
+ *			  this one.
+ *			  It will come with version 1.1.0 (sigh).
+ *
+ * 19-May-1998 BS	- Started to build a builtin preprocessor
+ *
+ * 30-Apr-1998 BS	- Redid the stringtable parsing/handling. My previous
+ *			  ideas had some serious flaws.
+ *
+ * 27-Apr-1998 BS	- Removed a lot of dead comments and put it in a doc
+ *			  file.
+ *
+ * 21-Apr-1998 BS	- Added correct behavior for cursors and icons.
+ *			- This file is growing too big. It is time to strip
+ *			  things and put it in a support file.
+ *
+ * 19-Apr-1998 BS	- Tagged the stringtable resource so that only one
+ *			  resource will be created. This because the table
+ *			  has a different layout than other resources. The
+ *			  table has to be sorted, and divided into smaller
+ *			  resource entries (see comment in source).
+ *
+ * 17-Apr-1998 BS	- Almost all strings, including identifiers, are parsed
+ *			  as string_t which include unicode strings upon
+ *			  input.
+ *			- Parser now emits a warning when compiling win32
+ *			  extensions in win16 mode.
+ *
+ * 16-Apr-1998 BS	- Raw data elements are now *optionally* seperated
+ *			  by commas. Read the comments in file sq2dq.l.
+ *			- FIXME: there are instances in the source that rely
+ *			  on the fact that int==32bit and pointers are int size.
+ *			- Fixed the conflict in menuex by changing a rule
+ *			  back into right recursion. See note in source.
+ *			- UserType resources cannot have an expression as its
+ *			  typeclass. See note in source.
+ *
+ * 15-Apr-1998 BS	- Changed all right recursion into left recursion to
+ *			  get reduction of the parsestack.
+ *			  This also helps communication between bison and flex.
+ *			  Main advantage is that the Empty rule gets reduced
+ *			  first, which is used to allocate/link things.
+ *			  It also added a shift/reduce conflict in the menuex
+ *			  handling, due to expression/option possibility,
+ *			  although not serious.
+ *
+ * 14-Apr-1998 BS	- Redone almost the entire parser. We're not talking
+ *			  about making it more efficient, but readable (for me)
+ *			  and slightly easier to expand/change.
+ *			  This is done primarily by using more reduce states
+ *			  with many (intuitive) types for the various resource
+ *			  statements.
+ *			- Added expression handling for all resources where a
+ *			  number is accepted (not only for win32). Also added
+ *			  multiply and division (not MS compatible, but handy).
+ *			  Unary minus introduced a shift/reduce conflict, but
+ *			  it is not serious.
+ *
+ * 13-Apr-1998 BS	- Reordered a lot of things
+ *			- Made the source more readable
+ *			- Added Win32 resource definitions
+ *			- Corrected syntax problems with an old yacc (;)
+ *			- Added extra comment about grammar
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <config.h>
+#include "wrc.h"
+#include "utils.h"
+#include "newstruc.h"
+#include "dumpres.h"
+#include "preproc.h"
+#include "parser.h"
+
+#ifdef __BORLANDC__
+#pragma warn -sig
+#endif
+
+DWORD andmask;		/* Used to parse 'NOT NUMBER' expressions */
+int indialog = 0;	/* Signal flex that we're parsing a dialog */
+int want_rscname = 0;	/* Set when a resource's name is required */
+stringtable_t *tagstt;	/* Stringtable tag.
+			 * It is set while parsing a stringtable to one of
+			 * the stringtables in the sttres list or a new one
+			 * if the language was not parsed before.
+			 */
+stringtable_t *sttres;	/* Stringtable resources. This holds the list of
+			 * stringtables with different lanuages
+			 */
+/* Set to the current options of the currently scanning stringtable */
+static int *tagstt_memopt;
+static characts_t *tagstt_characts;
+static version_t *tagstt_version;
+
+/* Prototypes of here defined functions */
+void split_cursors(raw_data_t *rd, cursor_group_t *curg, int *ncur);
+void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico);
+int alloc_cursor_id(void);
+int alloc_icon_id(void);
+void ins_stt_entry(stt_entry_t *ste);
+int check_stt_entry(stringtable_t *tabs, stt_entry_t *ste);
+event_t *get_event_head(event_t *p);
+control_t *get_control_head(control_t *p);
+ver_value_t *get_ver_value_head(ver_value_t *p);
+ver_block_t *get_ver_block_head(ver_block_t *p);
+resource_t *get_resource_head(resource_t *p);
+menuex_item_t *get_itemex_head(menuex_item_t *p);
+menu_item_t *get_item_head(menu_item_t *p);
+raw_data_t *merge_raw_data_str(raw_data_t *r1, string_t *str);
+raw_data_t *merge_raw_data_int(raw_data_t *r1, int i);
+raw_data_t *merge_raw_data(raw_data_t *r1, raw_data_t *r2);
+raw_data_t *str2raw_data(string_t *str);
+raw_data_t *int2raw_data(int i);
+raw_data_t *load_file(string_t *name);
+itemex_opt_t *new_itemex_opt(int id, int type, int state, int helpid);
+event_t *add_string_event(string_t *key, int id, int flags, event_t *prev);
+event_t *add_event(int key, int id, int flags, event_t *prev);
+dialogex_t *dialogex_version(version_t *v, dialogex_t *dlg);
+dialogex_t *dialogex_characteristics(characts_t *c, dialogex_t *dlg);
+dialogex_t *dialogex_language(language_t *l, dialogex_t *dlg);
+dialogex_t *dialogex_menu(name_id_t *m, dialogex_t *dlg);
+dialogex_t *dialogex_class(name_id_t *n, dialogex_t *dlg);
+dialogex_t *dialogex_font(font_id_t *f, dialogex_t *dlg);
+dialogex_t *dialogex_caption(string_t *s, dialogex_t *dlg);
+dialogex_t *dialogex_exstyle(int st, dialogex_t *dlg);
+dialogex_t *dialogex_style(int st, dialogex_t *dlg);
+name_id_t *convert_ctlclass(name_id_t *cls);
+control_t *ins_ctrl(int type, int style, control_t *ctrl, control_t *prev);
+dialog_t *dialog_version(version_t *v, dialog_t *dlg);
+dialog_t *dialog_characteristics(characts_t *c, dialog_t *dlg);
+dialog_t *dialog_language(language_t *l, dialog_t *dlg);
+dialog_t *dialog_menu(name_id_t *m, dialog_t *dlg);
+dialog_t *dialog_class(name_id_t *n, dialog_t *dlg);
+dialog_t *dialog_font(font_id_t *f, dialog_t *dlg);
+dialog_t *dialog_caption(string_t *s, dialog_t *dlg);
+dialog_t *dialog_exstyle(int st, dialog_t *dlg);
+dialog_t *dialog_style(int st, dialog_t *dlg);
+resource_t *build_stt_resources(stringtable_t *stthead);
+stringtable_t *find_stringtable(lvc_t *lvc);
+
+%}
+%union{
+	string_t	*str;
+	int		num;
+	int		*iptr;
+	resource_t	*res;
+	accelerator_t	*acc;
+	bitmap_t	*bmp;
+	cursor_t	*cur;
+	cursor_group_t	*curg;
+	dialog_t	*dlg;
+	dialogex_t	*dlgex;
+	font_t		*fnt;
+	icon_t		*ico;
+	icon_group_t	*icog;
+	menu_t		*men;
+	menuex_t	*menex;
+	rcdata_t	*rdt;
+	stringtable_t	*stt;
+	stt_entry_t	*stte;
+	user_t		*usr;
+	messagetable_t	*msg;
+	versioninfo_t	*veri;
+	control_t	*ctl;
+	name_id_t	*nid;
+	font_id_t	*fntid;
+	language_t	*lan;
+	version_t	*ver;
+	characts_t	*chars;
+	event_t		*event;
+	menu_item_t	*menitm;
+	menuex_item_t	*menexitm;
+	itemex_opt_t	*exopt;
+	raw_data_t	*raw;
+	lvc_t		*lvc;
+	ver_value_t	*val;
+	ver_block_t	*blk;
+	ver_words_t	*verw;
+}
+
+%token tIF tIFDEF tIFNDEF tELSE tELIF tENDIF tDEFINED tNL
+%token tTYPEDEF tEXTERN
+%token <num> NUMBER
+%token <str> tSTRING IDENT FILENAME
+%token <raw> RAWDATA
+%token ACCELERATORS tBITMAP CURSOR DIALOG DIALOGEX MENU MENUEX MESSAGETABLE
+%token RCDATA VERSIONINFO STRINGTABLE FONT ICON
+%token AUTO3STATE AUTOCHECKBOX AUTORADIOBUTTON CHECKBOX DEFPUSHBUTTON
+%token PUSHBUTTON RADIOBUTTON STATE3 /* PUSHBOX */
+%token GROUPBOX COMBOBOX LISTBOX SCROLLBAR
+%token CONTROL EDITTEXT
+%token RTEXT CTEXT LTEXT
+%token BLOCK VALUE
+%token SHIFT ALT ASCII VIRTKEY GRAYED CHECKED INACTIVE NOINVERT
+%token tPURE IMPURE DISCARDABLE LOADONCALL PRELOAD tFIXED MOVEABLE
+%token CLASS CAPTION CHARACTERISTICS EXSTYLE STYLE VERSION LANGUAGE
+%token FILEVERSION PRODUCTVERSION FILEFLAGSMASK FILEOS FILETYPE FILEFLAGS FILESUBTYPE
+%token MENUBARBREAK MENUBREAK MENUITEM POPUP SEPARATOR
+%token HELP
+%token tSTRING IDENT RAWDATA
+%token tBEGIN tEND
+%left LOGOR
+%left LOGAND
+%left '|'
+%left '^'
+%left '&'
+%left EQ NE
+%left '<' LTE '>' GTE
+%left '+' '-'
+%left '*' '/'
+%right '~' '!' NOT
+
+%type <res> 	resource_file resource resources resource_definition
+%type <stt>	stringtable strings
+%type <fnt>	font
+%type <icog>	icon
+%type <acc> 	accelerators
+%type <event> 	events
+%type <bmp> 	bitmap
+%type <curg> 	cursor
+%type <dlg> 	dialog dlg_attributes
+%type <ctl> 	ctrls gen_ctrl lab_ctrl ctrl_desc iconinfo
+%type <iptr>	optional_style helpid
+%type <dlgex> 	dialogex dlgex_attribs
+%type <ctl>	exctrls gen_exctrl lab_exctrl exctrl_desc
+%type <rdt> 	rcdata
+%type <raw>	raw_data raw_elements opt_data
+%type <veri> 	versioninfo fix_version
+%type <verw>	ver_words
+%type <blk>	ver_blocks ver_block
+%type <val>	ver_values ver_value
+%type <men> 	menu
+%type <menitm>	item_definitions menu_body
+%type <menex>	menuex
+%type <menexitm> itemex_definitions menuex_body
+%type <exopt>	itemex_p_options itemex_options
+%type <msg> 	messagetable
+%type <usr> 	userres
+%type <num> 	item_options
+%type <nid> 	nameid ctlclass usertype
+%type <num> 	acc_opt
+%type <iptr>	loadmemopts lamo lama
+%type <fntid>	opt_font opt_exfont
+%type <lvc>	opt_lvc
+%type <lan>	opt_language
+%type <chars>	opt_characts
+%type <ver>	opt_version
+%type <num>	expr xpr dummy
+%type <iptr>	e_expr
+%type <iptr>	pp_expr pp_constant
+
+%%
+
+resource_file
+	: resources {
+		resource_t *rsc;
+		/* First add stringtables to the resource-list */
+		rsc = build_stt_resources(sttres);
+		/* 'build_stt_resources' returns a head and $1 is a tail */
+		if($1)
+		{
+			$1->next = rsc;
+			if(rsc)
+				rsc->prev = $1;
+		}
+		else
+			$1 = rsc;
+		/* Final statement before were done */
+		resource_top = get_resource_head($1);
+		}
+	;
+
+/* Resources are put into a linked list */
+resources
+	: /* Empty */		{ $$ = NULL; want_rscname = 1; }
+	| resources resource	{
+		if($2)
+		{
+			resource_t *tail = $2;
+			resource_t *head = $2;
+			while(tail->next)
+				tail = tail->next;
+			while(head->prev)
+				head = head->prev;
+			head->prev = $1;
+			if($1)
+				$1->next = head;
+			$$ = tail;
+		}
+		else if($1)
+		{
+			resource_t *tail = $1;
+			while(tail->next)
+				tail = tail->next;
+			$$ = tail;
+		}
+		else
+			$$ = NULL;
+		want_rscname = 1;
+		}
+	| resources preprocessor		{ $$ = $1; want_rscname = 1; }
+	| resources cjunk			{ $$ = $1; want_rscname = 1; }
+	;
+
+/* The buildin preprocessor */
+preprocessor
+	: tIF pp_expr tNL	{ pop_start(); push_if($2 ? *($2) : 0, 0, 0); if($2) free($2);}
+	| tIFDEF IDENT tNL	{ pop_start(); push_if(pp_lookup($2->str.cstr) != NULL, 0, 0); }
+	| tIFNDEF IDENT tNL	{ pop_start(); push_if(pp_lookup($2->str.cstr) == NULL, 0, 0); }
+	| tELIF pp_expr tNL	{ pop_start(); push_if($2 ? *($2) : 0, pop_if(), 0); if($2) free($2); }
+	| tELSE tNL		{ pop_start(); push_if(1, pop_if(), 0); }
+	| tENDIF tNL		{ pop_if(); }
+	;
+
+pp_expr	: pp_constant			{ $$ = $1; }
+	| pp_expr LOGOR pp_expr		{ $$ = new_int($1 && $3 ? (*$1 || *$3) : 0); if($1) free($1); if($3) free($3); }
+	| pp_expr LOGAND pp_expr	{ $$ = new_int($1 && $3 ? (*$1 && *$3) : 0); if($1) free($1); if($3) free($3); }
+	| pp_expr '+' pp_expr		{ $$ = new_int($1 && $3 ? (*$1  + *$3) : 0); if($1) free($1); if($3) free($3); }
+	| pp_expr '-' pp_expr		{ $$ = new_int($1 && $3 ? (*$1  - *$3) : 0); if($1) free($1); if($3) free($3); }
+	| pp_expr '^' pp_expr		{ $$ = new_int($1 && $3 ? (*$1  ^ *$3) : 0); if($1) free($1); if($3) free($3); }
+	| pp_expr EQ pp_expr		{ $$ = new_int($1 && $3 ? (*$1 == *$3) : 0); if($1) free($1); if($3) free($3); }
+	| pp_expr NE pp_expr		{ $$ = new_int($1 && $3 ? (*$1 != *$3) : 0); if($1) free($1); if($3) free($3); }
+	| pp_expr '<' pp_expr		{ $$ = new_int($1 && $3 ? (*$1  < *$3) : 0); if($1) free($1); if($3) free($3); }
+	| pp_expr '>' pp_expr		{ $$ = new_int($1 && $3 ? (*$1  > *$3) : 0); if($1) free($1); if($3) free($3); }
+	| pp_expr LTE pp_expr		{ $$ = new_int($1 && $3 ? (*$1 <= *$3) : 0); if($1) free($1); if($3) free($3); }
+	| pp_expr GTE pp_expr		{ $$ = new_int($1 && $3 ? (*$1 >= *$3) : 0); if($1) free($1); if($3) free($3); }
+	| '~' pp_expr			{ $$ = $2; if($2) *$2 = ~(*$2); }
+	| '+' pp_expr			{ $$ = $2; }
+	| '-' pp_expr			{ $$ = $2; if($2) *$2 = -(*$2); }
+	| '!' pp_expr			{ $$ = $2; if($2) *$2 = !(*$2); }
+	| '(' pp_expr ')'		{ $$ = $2; }
+	;
+
+pp_constant
+	: NUMBER			{ $$ = new_int($1); }
+	| IDENT				{ $$ = NULL; }
+	| tDEFINED IDENT		{ $$ = new_int(pp_lookup($2->str.cstr) != NULL); }
+	| tDEFINED '(' IDENT ')'	{ $$ = new_int(pp_lookup($3->str.cstr) != NULL); }
+	;
+
+/* C ignore stuff */
+cjunk	: tTYPEDEF			{ strip_til_semicolon(); }
+	| tEXTERN			{ strip_til_semicolon(); }
+	| IDENT IDENT			{ strip_til_semicolon(); }
+	| IDENT '('			{ strip_til_parenthesis(); }
+	| IDENT '*'			{ strip_til_semicolon(); }
+	;
+
+/* Parse top level resource definitions etc. */
+resource
+	: nameid resource_definition {
+		$$ = $2;
+		if($$)
+		{
+			$$->name = $1;
+			if($1->type == name_ord)
+			{
+				chat("Got %s (%d)",get_typename($2),$1->name.i_name);
+			}
+			else if($1->type == name_str)
+			{
+				chat("Got %s (%s)",get_typename($2),$1->name.s_name->str.cstr);
+			}
+		}
+		}
+	| stringtable {
+		/* Don't do anything, stringtables are converted to
+		 * resource_t structures when we are finished parsing and
+		 * the final rule of the parser is reduced (see above)
+		 */
+		$$ = NULL;
+		chat("Got STRINGTABLE");
+		}
+	| opt_language {
+		if(!win32)
+			yywarning("LANGUAGE not supported in 16-bit mode");
+		if(currentlanguage)
+			free(currentlanguage);
+		currentlanguage = $1;
+		$$ = NULL;
+		}
+	;
+
+/* FIXME:
+ * The problem here is that MENU MENU {...} is a valid (!) resource.
+ * The name-identifier is "MENU". We cannot parse this without generating
+ * an error. It would mean that a list of keywords must be added here
+ * and converted into a valid name_id_t structure.
+ */
+nameid	: expr	{
+		$$ = new_name_id();
+		$$->type = name_ord;
+		$$->name.i_name = $1;
+		want_rscname = 0;
+		}
+	| IDENT	{
+		$$ = new_name_id();
+		$$->type = name_str;
+		$$->name.s_name = $1;
+		want_rscname = 0;
+		}
+	;
+
+/* get the value for a single resource*/
+resource_definition
+	: accelerators	{ $$ = new_resource(res_acc, $1, $1->memopt, $1->lvc.language); }
+	| bitmap	{ $$ = new_resource(res_bmp, $1, $1->memopt, currentlanguage); }
+	| cursor {
+		resource_t *rsc;
+		cursor_t *cur;
+		$$ = rsc = new_resource(res_curg, $1, $1->memopt, currentlanguage);
+		for(cur = $1->cursorlist; cur; cur = cur->next)
+		{
+			rsc->prev = new_resource(res_cur, cur, $1->memopt, currentlanguage);
+			rsc->prev->next = rsc;
+			rsc = rsc->prev;
+			rsc->name = new_name_id();
+			rsc->name->type = name_ord;
+			rsc->name->name.i_name = cur->id;
+		}
+		}
+	| dialog	{ $$ = new_resource(res_dlg, $1, $1->memopt, $1->lvc.language); }
+	| dialogex {
+		if(win32)
+			$$ = new_resource(res_dlgex, $1, $1->memopt, $1->lvc.language);
+		else
+			$$ = NULL;
+		}
+	| font		{ $$=new_resource(res_fnt, $1, $1->memopt, currentlanguage); }
+	| icon {
+		resource_t *rsc;
+		icon_t *ico;
+		$$ = rsc = new_resource(res_icog, $1, $1->memopt, currentlanguage);
+		for(ico = $1->iconlist; ico; ico = ico->next)
+		{
+			rsc->prev = new_resource(res_ico, ico, $1->memopt, currentlanguage);
+			rsc->prev->next = rsc;
+			rsc = rsc->prev;
+			rsc->name = new_name_id();
+			rsc->name->type = name_ord;
+			rsc->name->name.i_name = ico->id;
+		}
+		}
+	| menu		{ $$ = new_resource(res_men, $1, $1->memopt, $1->lvc.language); }
+	| menuex {
+		if(win32)
+			$$ = new_resource(res_menex, $1, $1->memopt, $1->lvc.language);
+		else
+			$$ = NULL;
+		}
+	| messagetable	{ $$ = new_resource(res_msg, $1, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, currentlanguage); }
+	| rcdata	{ $$ = new_resource(res_rdt, $1, $1->memopt, $1->lvc.language); }
+	| userres	{ $$ = new_resource(res_usr, $1, $1->memopt, currentlanguage); }
+	| versioninfo	{ $$ = new_resource(res_ver, $1, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, currentlanguage); }
+	;
+
+/* ------------------------------ Bitmap ------------------------------ */
+bitmap	: tBITMAP loadmemopts FILENAME	{ $$ = new_bitmap(load_file($3), $2); }
+	| tBITMAP loadmemopts raw_data	{ $$ = new_bitmap($3, $2); }
+	;
+
+/* ------------------------------ Cursor ------------------------------ */
+cursor	: CURSOR loadmemopts FILENAME	{ $$ = new_cursor_group(load_file($3), $2); }
+	| CURSOR loadmemopts raw_data	{ $$ = new_cursor_group($3, $2); }
+	;
+
+/* ------------------------------ Font ------------------------------ */
+/* FIXME: Should we allow raw_data here? */
+font	: FONT loadmemopts FILENAME	{ $$ = new_font(load_file($3), $2); }
+	;
+
+/* ------------------------------ Icon ------------------------------ */
+icon	: ICON loadmemopts FILENAME	{ $$ = new_icon_group(load_file($3), $2); }
+	| ICON loadmemopts raw_data	{ $$ = new_icon_group($3, $2); }
+	;
+
+/* ------------------------------ MessageTable ------------------------------ */
+/* It might be interesting to implement the MS Message compiler here as well
+ * to get everything in one source. Might be a future project.
+ */
+messagetable
+	: MESSAGETABLE FILENAME	{
+		if(!win32)
+			yywarning("MESSAGETABLE not supported in 16-bit mode");
+		$$ = new_messagetable(load_file($2));
+		}
+	;
+
+/* ------------------------------ RCData ------------------------------ */
+rcdata	: RCDATA loadmemopts opt_lvc raw_data {
+		$$ = new_rcdata($4, $2);
+		if($3)
+		{
+			$$->lvc = *($3);
+			free($3);
+		}
+		if(!$$->lvc.language)
+			$$->lvc.language = dup_language(currentlanguage);
+		}
+	;
+
+/* ------------------------------ UserType ------------------------------ */
+userres	: usertype loadmemopts FILENAME	{ $$ = new_user($1, load_file($3), $2); }
+	| usertype loadmemopts raw_data	{ $$ = new_user($1, $3, $2); }
+	;
+
+/* NOTE: This here is an exception where I do not allow an expression.
+ * Reason for this is that it is not possible to set the 'yywf' condition
+ * for flex if loadmemopts is empty. Reading an expression requires a
+ * lookahead to determine its end. In this case here, that would mean that
+ * the filename has been read as IDENT or tSTRING, which is incorrect.
+ * Note also that IDENT cannot be used as a file-name because it is lacking
+ * the '.'.
+ */
+
+/* I also allow string identifiers as classtypes. Not MS implemented, but
+ * seems to be reasonable to implement.
+ */
+/* Allowing anything else than NUMBER makes it very hard to get rid of
+ * prototypes. So, I remove IDENT to be able to get prototypes out of the
+ * world.
+ */
+usertype: NUMBER {
+		$$ = new_name_id();
+		$$->type = name_ord;
+		$$->name.i_name = $1;
+		set_yywf();
+		}
+/*	| IDENT {
+		$$ = new_name_id();
+		$$->type = name_str;
+		$$->name.s_name = $1;
+		set_yywf();
+		}
+*/	| tSTRING {
+		$$ = new_name_id();
+		$$->type = name_str;
+		$$->name.s_name = $1;
+		set_yywf();
+		}
+	;
+
+/* ------------------------------ Accelerator ------------------------------ */
+accelerators
+	: ACCELERATORS loadmemopts opt_lvc tBEGIN events tEND {
+		$$ = new_accelerator();
+		if($2)
+		{
+			$$->memopt = *($2);
+			free($2);
+		}
+		else
+		{
+			$$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
+		}
+		if(!$5)
+			yyerror("Accelerator table must have at least one entry");
+		$$->events = get_event_head($5);
+		if($3)
+		{
+			$$->lvc = *($3);
+			free($3);
+		}
+		if(!$$->lvc.language)
+			$$->lvc.language = dup_language(currentlanguage);
+		}
+	;
+
+events	: /* Empty */ 				{ $$=NULL; }
+	| events tSTRING ',' expr acc_opt	{ $$=add_string_event($2, $4, $5, $1); }
+	| events expr ',' expr acc_opt		{ $$=add_event($2, $4, $5, $1); }
+	;
+
+acc_opt	: /* Empty */		{ $$=0; }
+	| acc_opt ',' NOINVERT 	{ $$=$1 | WRC_AF_NOINVERT; }
+	| acc_opt ',' SHIFT	{ $$=$1 | WRC_AF_SHIFT; }
+	| acc_opt ',' CONTROL	{ $$=$1 | WRC_AF_CONTROL; }
+	| acc_opt ',' ALT	{ $$=$1 | WRC_AF_ALT; }
+	| acc_opt ',' ASCII	{ $$=$1 | WRC_AF_ASCII; }
+	| acc_opt ',' VIRTKEY	{ $$=$1 | WRC_AF_VIRTKEY; }
+	;
+
+/* ------------------------------ Dialog ------------------------------ */
+/* FIXME: Support EXSTYLE in the dialog line itself */
+dialog	: DIALOG loadmemopts expr ',' expr ',' expr ',' expr dlg_attributes
+	  tBEGIN  ctrls tEND {
+		if($2)
+		{
+			$10->memopt = *($2);
+			free($2);
+		}
+		else
+			$10->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
+		$10->x = $3;
+		$10->y = $5;
+		$10->width = $7;
+		$10->height = $9;
+		$10->controls = get_control_head($12);
+		$$ = $10;
+		if(!$$->gotstyle)
+		{
+			$$->style = WS_POPUP;
+			$$->gotstyle = TRUE;
+		}
+		if($$->title)
+			$$->style |= WS_CAPTION;
+		if($$->font)
+			$$->style |= DS_SETFONT;
+		indialog = FALSE;
+		if(!$$->lvc.language)
+			$$->lvc.language = dup_language(currentlanguage);
+		}
+	;
+
+dlg_attributes
+	: /* Empty */			{ $$=new_dialog(); }
+	| dlg_attributes STYLE expr	{ $$=dialog_style($3,$1); }
+	| dlg_attributes EXSTYLE expr	{ $$=dialog_exstyle($3,$1); }
+	| dlg_attributes CAPTION tSTRING { $$=dialog_caption($3,$1); }
+	| dlg_attributes opt_font	{ $$=dialog_font($2,$1); }
+	| dlg_attributes CLASS nameid	{ $$=dialog_class($3,$1); }
+	| dlg_attributes MENU nameid	{ $$=dialog_menu($3,$1); }
+	| dlg_attributes opt_language	{ $$=dialog_language($2,$1); }
+	| dlg_attributes opt_characts	{ $$=dialog_characteristics($2,$1); }
+	| dlg_attributes opt_version	{ $$=dialog_version($2,$1); }
+	;
+
+ctrls	: /* Empty */				{ $$ = NULL; }
+	| ctrls CONTROL		gen_ctrl	{ $$=ins_ctrl(-1, 0, $3, $1); }
+	| ctrls EDITTEXT	ctrl_desc	{ $$=ins_ctrl(CT_EDIT, 0, $3, $1); }
+	| ctrls LISTBOX		ctrl_desc	{ $$=ins_ctrl(CT_LISTBOX, 0, $3, $1); }
+	| ctrls COMBOBOX	ctrl_desc	{ $$=ins_ctrl(CT_COMBOBOX, 0, $3, $1); }
+	| ctrls SCROLLBAR	ctrl_desc	{ $$=ins_ctrl(CT_SCROLLBAR, 0, $3, $1); }
+	| ctrls CHECKBOX	lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_CHECKBOX, $3, $1); }
+	| ctrls DEFPUSHBUTTON	lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_DEFPUSHBUTTON, $3, $1); }
+	| ctrls GROUPBOX	lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_GROUPBOX, $3, $1);}
+	| ctrls PUSHBUTTON	lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_PUSHBUTTON, $3, $1); }
+/*	| ctrls PUSHBOX		lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_PUSHBOX, $3, $1); } */
+	| ctrls RADIOBUTTON	lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_RADIOBUTTON, $3, $1); }
+	| ctrls AUTO3STATE	lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_AUTO3STATE, $3, $1); }
+	| ctrls STATE3		lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_3STATE, $3, $1); }
+	| ctrls AUTOCHECKBOX	lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_AUTOCHECKBOX, $3, $1); }
+	| ctrls AUTORADIOBUTTON lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_AUTORADIOBUTTON, $3, $1); }
+	| ctrls LTEXT		lab_ctrl	{ $$=ins_ctrl(CT_STATIC, SS_LEFT, $3, $1); }
+	| ctrls CTEXT		lab_ctrl	{ $$=ins_ctrl(CT_STATIC, SS_CENTER, $3, $1); }
+	| ctrls RTEXT		lab_ctrl	{ $$=ins_ctrl(CT_STATIC, SS_RIGHT, $3, $1); }
+	/* special treatment for icons, as the extent is optional */
+	| ctrls ICON tSTRING ',' expr ',' expr ',' expr iconinfo {
+		$10->title = $3;
+		$10->id = $5;
+		$10->x = $7;
+		$10->y = $9;
+		$$ = ins_ctrl(CT_STATIC, SS_ICON, $10, $1);
+		}
+	;
+
+lab_ctrl
+	: tSTRING ',' expr ',' expr ',' expr ',' expr ',' expr optional_style {
+		$$=new_control();
+		$$->title = $1;
+		$$->id = $3;
+		$$->x = $5;
+		$$->y = $7;
+		$$->width = $9;
+		$$->height = $11;
+		if($12)
+		{
+			$$->style = *($12);
+			$$->gotstyle = TRUE;
+			free($12);
+		}
+		}
+	;
+
+ctrl_desc
+	: expr ',' expr ',' expr ',' expr ',' expr optional_style {
+		$$ = new_control();
+		$$->id = $1;
+		$$->x = $3;
+		$$->y = $5;
+		$$->width = $7;
+		$$->height = $9;
+		if($10)
+		{
+			$$->style = *($10);
+			$$->gotstyle = TRUE;
+			free($10);
+		}
+		}
+	;
+
+iconinfo: /* Empty */
+		{ $$ = new_control(); }
+
+	| ',' expr ',' expr {
+		$$ = new_control();
+		$$->width = $2;
+		$$->height = $4;
+		}
+	| ',' expr ',' expr ',' expr {
+		$$ = new_control();
+		$$->width = $2;
+		$$->height = $4;
+		$$->style = $6;
+		$$->gotstyle = TRUE;
+		}
+	| ',' expr ',' expr ',' expr ',' expr {
+		$$ = new_control();
+		$$->width = $2;
+		$$->height = $4;
+		$$->style = $6;
+		$$->gotstyle = TRUE;
+		$$->exstyle = $8;
+		$$->gotexstyle = TRUE;
+		}
+	;
+
+gen_ctrl: tSTRING ',' expr ',' ctlclass ',' expr ',' expr ',' expr ',' expr ',' expr ',' expr {
+		$$=new_control();
+		$$->title = $1;
+		$$->id = $3;
+		$$->ctlclass = convert_ctlclass($5);
+		$$->style = $7;
+		$$->gotstyle = TRUE;
+		$$->x = $9;
+		$$->y = $11;
+		$$->width = $13;
+		$$->height = $15;
+		$$->exstyle = $17;
+		$$->gotexstyle = TRUE;
+		}
+	| tSTRING ',' expr ',' ctlclass ',' expr ',' expr ',' expr ',' expr ',' expr {
+		$$=new_control();
+		$$->title = $1;
+		$$->id = $3;
+		$$->ctlclass = convert_ctlclass($5);
+		$$->style = $7;
+		$$->gotstyle = TRUE;
+		$$->x = $9;
+		$$->y = $11;
+		$$->width = $13;
+		$$->height = $15;
+		}
+	;
+
+opt_font
+	: FONT expr ',' tSTRING	{ $$ = new_font_id($2, $4, 0, 0); }
+	;
+
+optional_style		/* Abbused once to get optional ExStyle */
+	: /* Empty */	{ $$ = NULL; }
+	| ',' expr	{ $$ = new_int($2); }
+	;
+
+ctlclass
+	: expr	{
+		$$ = new_name_id();
+		$$->type = name_ord;
+		$$->name.i_name = $1;
+		}
+	| tSTRING {
+		$$ = new_name_id();
+		$$->type = name_str;
+		$$->name.s_name = $1;
+		}
+	;
+
+/* ------------------------------ DialogEx ------------------------------ */
+dialogex: DIALOGEX loadmemopts expr ',' expr ',' expr ',' expr helpid dlgex_attribs
+	  tBEGIN  exctrls tEND {
+		if(!win32)
+			yywarning("DIALOGEX not supported in 16-bit mode");
+		if($2)
+		{
+			$11->memopt = *($2);
+			free($2);
+		}
+		else
+			$11->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
+		$11->x = $3;
+		$11->y = $5;
+		$11->width = $7;
+		$11->height = $9;
+		if($10)
+		{
+			$11->helpid = *($10);
+			$11->gothelpid = TRUE;
+			free($10);
+		}
+		$11->controls = get_control_head($13);
+		$$ = $11;
+		if(!$$->gotstyle)
+		{
+			$$->style = WS_POPUP;
+			$$->gotstyle = TRUE;
+		}
+		if($$->title)
+			$$->style |= WS_CAPTION;
+		if($$->font)
+			$$->style |= DS_SETFONT;
+		indialog = FALSE;
+		if(!$$->lvc.language)
+			$$->lvc.language = dup_language(currentlanguage);
+		}
+	;
+
+dlgex_attribs
+	: /* Empty */			{ $$=new_dialogex(); }
+	| dlgex_attribs STYLE expr	{ $$=dialogex_style($3,$1); }
+	| dlgex_attribs EXSTYLE expr	{ $$=dialogex_exstyle($3,$1); }
+	| dlgex_attribs CAPTION tSTRING { $$=dialogex_caption($3,$1); }
+	| dlgex_attribs opt_exfont	{ $$=dialogex_font($2,$1); }
+	| dlgex_attribs CLASS nameid	{ $$=dialogex_class($3,$1); }
+	| dlgex_attribs MENU nameid	{ $$=dialogex_menu($3,$1); }
+	| dlgex_attribs opt_language	{ $$=dialogex_language($2,$1); }
+	| dlgex_attribs opt_characts	{ $$=dialogex_characteristics($2,$1); }
+	| dlgex_attribs opt_version	{ $$=dialogex_version($2,$1); }
+	;
+
+exctrls	: /* Empty */				{ $$ = NULL; }
+	| exctrls CONTROL	gen_exctrl	{ $$=ins_ctrl(-1, 0, $3, $1); }
+	| exctrls EDITTEXT	exctrl_desc	{ $$=ins_ctrl(CT_EDIT, 0, $3, $1); }
+	| exctrls LISTBOX	exctrl_desc	{ $$=ins_ctrl(CT_LISTBOX, 0, $3, $1); }
+	| exctrls COMBOBOX	exctrl_desc	{ $$=ins_ctrl(CT_COMBOBOX, 0, $3, $1); }
+	| exctrls SCROLLBAR	exctrl_desc	{ $$=ins_ctrl(CT_SCROLLBAR, 0, $3, $1); }
+	| exctrls CHECKBOX	lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_CHECKBOX, $3, $1); }
+	| exctrls DEFPUSHBUTTON	lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_DEFPUSHBUTTON, $3, $1); }
+	| exctrls GROUPBOX	lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_GROUPBOX, $3, $1);}
+	| exctrls PUSHBUTTON	lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_PUSHBUTTON, $3, $1); }
+/*	| exctrls PUSHBOX	lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_PUSHBOX, $3, $1); } */
+	| exctrls RADIOBUTTON	lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_RADIOBUTTON, $3, $1); }
+	| exctrls AUTO3STATE	lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_AUTO3STATE, $3, $1); }
+	| exctrls STATE3	lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_3STATE, $3, $1); }
+	| exctrls AUTOCHECKBOX	lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_AUTOCHECKBOX, $3, $1); }
+	| exctrls AUTORADIOBUTTON lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_AUTORADIOBUTTON, $3, $1); }
+	| exctrls LTEXT		lab_exctrl	{ $$=ins_ctrl(CT_STATIC, SS_LEFT, $3, $1); }
+	| exctrls CTEXT		lab_exctrl	{ $$=ins_ctrl(CT_STATIC, SS_CENTER, $3, $1); }
+	| exctrls RTEXT		lab_exctrl	{ $$=ins_ctrl(CT_STATIC, SS_RIGHT, $3, $1); }
+	/* special treatment for icons, as the extent is optional */
+	| exctrls ICON tSTRING ',' expr ',' expr ',' expr iconinfo {
+		$10->title = $3;
+		$10->id = $5;
+		$10->x = $7;
+		$10->y = $9;
+		$$ = ins_ctrl(CT_STATIC, SS_ICON, $10, $1);
+		}
+	;
+
+gen_exctrl
+	: tSTRING ',' expr ',' ctlclass ',' expr ',' expr ',' expr ',' expr ','
+	  expr ',' e_expr helpid opt_data {
+		$$=new_control();
+		$$->title = $1;
+		$$->id = $3;
+		$$->ctlclass = convert_ctlclass($5);
+		$$->style = $7;
+		$$->gotstyle = TRUE;
+		$$->x = $9;
+		$$->y = $11;
+		$$->width = $13;
+		$$->height = $15;
+		if($17)
+		{
+			$$->exstyle = *($17);
+			$$->gotexstyle = TRUE;
+			free($17);
+		}
+		if($18)
+		{
+			$$->helpid = *($18);
+			$$->gothelpid = TRUE;
+			free($18);
+		}
+		$$->extra = $19;
+		}
+	| tSTRING ',' expr ',' ctlclass ',' expr ',' expr ',' expr ',' expr ',' expr opt_data {
+		$$=new_control();
+		$$->title = $1;
+		$$->id = $3;
+		$$->style = $7;
+		$$->gotstyle = TRUE;
+		$$->ctlclass = convert_ctlclass($5);
+		$$->x = $9;
+		$$->y = $11;
+		$$->width = $13;
+		$$->height = $15;
+		$$->extra = $16;
+		}
+	;
+
+lab_exctrl
+	: tSTRING ',' expr ',' expr ',' expr ',' expr ',' expr optional_style opt_data {
+		$$=new_control();
+		$$->title = $1;
+		$$->id = $3;
+		$$->x = $5;
+		$$->y = $7;
+		$$->width = $9;
+		$$->height = $11;
+		if($12)
+		{
+			$$->style = *($12);
+			$$->gotstyle = TRUE;
+			free($12);
+		}
+		$$->extra = $13;
+		}
+	;
+
+exctrl_desc
+	: expr ',' expr ',' expr ',' expr ',' expr optional_style opt_data {
+		$$ = new_control();
+		$$->id = $1;
+		$$->x = $3;
+		$$->y = $5;
+		$$->width = $7;
+		$$->height = $9;
+		if($10)
+		{
+			$$->style = *($10);
+			$$->gotstyle = TRUE;
+			free($10);
+		}
+		$$->extra = $11;
+		}
+	;
+
+opt_data: /* Empty */	{ $$ = NULL; }
+	| raw_data	{ $$ = $1; }
+	;
+
+helpid	: /* Empty */	{ $$ = NULL; }
+	| ',' expr	{ $$ = new_int($2); }
+	;
+
+opt_exfont
+	: FONT expr ',' tSTRING ',' expr ',' expr	{ $$ = new_font_id($2, $4, $6, $8); }
+	;
+
+/* ------------------------------ Menu ------------------------------ */
+menu	: MENU loadmemopts opt_lvc menu_body {
+		if(!$4)
+			yyerror("Menu must contain items");
+		$$ = new_menu();
+		if($2)
+		{
+			$$->memopt = *($2);
+			free($2);
+		}
+		else
+			$$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
+		$$->items = get_item_head($4);
+		if($3)
+		{
+			$$->lvc = *($3);
+			free($3);
+		}
+		if(!$$->lvc.language)
+			$$->lvc.language = dup_language(currentlanguage);
+		}
+	;
+
+menu_body
+	: tBEGIN item_definitions tEND	{ $$ = $2; }
+	;
+
+item_definitions
+	: /* Empty */	{$$ = NULL;}
+	| item_definitions MENUITEM tSTRING ',' expr item_options {
+		$$=new_menu_item();
+		$$->prev = $1;
+		if($1)
+			$1->next = $$;
+		$$->id =  $5;
+		$$->state = $6;
+		$$->name = $3;
+		}
+	| item_definitions MENUITEM SEPARATOR {
+		$$=new_menu_item();
+		$$->prev = $1;
+		if($1)
+			$1->next = $$;
+		}
+	| item_definitions POPUP tSTRING item_options menu_body {
+		$$ = new_menu_item();
+		$$->prev = $1;
+		if($1)
+			$1->next = $$;
+		$$->popup = get_item_head($5);
+		$$->name = $3;
+		}
+	;
+
+/* NOTE: item_options is right recursive because it would introduce
+ * a shift/reduce conflict on ',' in itemex_options due to the
+ * empty rule here. The parser is now forced to look beyond the ','
+ * before reducing (force shift).
+ * Right recursion here is not a problem because we cannot expect
+ * more than 7 parserstack places to be occupied while parsing this
+ * (who would want to specify a MF_x flag twice?).
+ */
+item_options
+	: /* Empty */			{ $$ = 0; }
+	| ',' CHECKED	item_options	{ $$ = $3 | MF_CHECKED; }
+	| ',' GRAYED	item_options	{ $$ = $3 | MF_GRAYED; }
+	| ',' HELP	item_options	{ $$ = $3 | MF_HELP; }
+	| ',' INACTIVE	item_options	{ $$ = $3 | MF_DISABLED; }
+	| ',' MENUBARBREAK item_options	{ $$ = $3 | MF_MENUBARBREAK; }
+	| ',' MENUBREAK	item_options	{ $$ = $3 | MF_MENUBREAK; }
+	;
+
+/* ------------------------------ MenuEx ------------------------------ */
+menuex	: MENUEX loadmemopts opt_lvc menuex_body	{
+		if(!win32)
+			yywarning("MENUEX not supported in 16-bit mode");
+		if(!$4)
+			yyerror("MenuEx must contain items");
+		$$ = new_menuex();
+		if($2)
+		{
+			$$->memopt = *($2);
+			free($2);
+		}
+		else
+			$$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
+		$$->items = get_itemex_head($4);
+		if($3)
+		{
+			$$->lvc = *($3);
+			free($3);
+		}
+		if(!$$->lvc.language)
+			$$->lvc.language = dup_language(currentlanguage);
+		}
+	;
+
+menuex_body
+	: tBEGIN itemex_definitions tEND { $$ = $2; }
+	;
+
+itemex_definitions
+	: /* Empty */	{$$ = NULL; }
+	| itemex_definitions MENUITEM tSTRING itemex_options {
+		$$ = new_menuex_item();
+		$$->prev = $1;
+		if($1)
+			$1->next = $$;
+		$$->name = $3;
+		$$->id = $4->id;
+		$$->type = $4->type;
+		$$->state = $4->state;
+		$$->helpid = $4->helpid;
+		$$->gotid = $4->gotid;
+		$$->gottype = $4->gottype;
+		$$->gotstate = $4->gotstate;
+		$$->gothelpid = $4->gothelpid;
+		free($4);
+		}
+	| itemex_definitions MENUITEM SEPARATOR {
+		$$ = new_menuex_item();
+		$$->prev = $1;
+		if($1)
+			$1->next = $$;
+		}
+	| itemex_definitions POPUP tSTRING itemex_p_options menuex_body {
+		$$ = new_menuex_item();
+		$$->prev = $1;
+		if($1)
+			$1->next = $$;
+		$$->popup = get_itemex_head($5);
+		$$->name = $3;
+		$$->id = $4->id;
+		$$->type = $4->type;
+		$$->state = $4->state;
+		$$->helpid = $4->helpid;
+		$$->gotid = $4->gotid;
+		$$->gottype = $4->gottype;
+		$$->gotstate = $4->gotstate;
+		$$->gothelpid = $4->gothelpid;
+		free($4);
+		}
+	;
+
+itemex_options
+	: /* Empty */			{ $$ = new_itemex_opt(0, 0, 0, 0); }
+	| ',' expr {
+		$$ = new_itemex_opt($2, 0, 0, 0);
+		$$->gotid = TRUE;
+		}
+	| ',' e_expr ',' e_expr item_options {
+		$$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $5, 0);
+		$$->gotid = TRUE;
+		$$->gottype = TRUE;
+		$$->gotstate = TRUE;
+		if($2) free($2);
+		if($4) free($4);
+		}
+	| ',' e_expr ',' e_expr ',' expr {
+		$$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $6, 0);
+		$$->gotid = TRUE;
+		$$->gottype = TRUE;
+		$$->gotstate = TRUE;
+		if($2) free($2);
+		if($4) free($4);
+		}
+	;
+
+itemex_p_options
+	: /* Empty */			{ $$ = new_itemex_opt(0, 0, 0, 0); }
+	| ',' expr {
+		$$ = new_itemex_opt($2, 0, 0, 0);
+		$$->gotid = TRUE;
+		}
+	| ',' e_expr ',' expr {
+		$$ = new_itemex_opt($2 ? *($2) : 0, $4, 0, 0);
+		if($2) free($2);
+		$$->gotid = TRUE;
+		$$->gottype = TRUE;
+		}
+	| ',' e_expr ',' e_expr ',' expr {
+		$$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $6, 0);
+		if($2) free($2);
+		if($4) free($4);
+		$$->gotid = TRUE;
+		$$->gottype = TRUE;
+		$$->gotstate = TRUE;
+		}
+	| ',' e_expr ',' e_expr ',' e_expr ',' expr {
+		$$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $6 ? *($6) : 0, $8);
+		if($2) free($2);
+		if($4) free($4);
+		if($6) free($6);
+		$$->gotid = TRUE;
+		$$->gottype = TRUE;
+		$$->gotstate = TRUE;
+		$$->gothelpid = TRUE;
+		}
+	;
+
+/* ------------------------------ StringTable ------------------------------ */
+/* Stringtables are parsed differently than other resources because their
+ * layout is substantially different from other resources.
+ * The table is parsed through a _global_ variable 'tagstt' which holds the
+ * current stringtable descriptor (stringtable_t *) and 'sttres' that holds a
+ * list of stringtables of different languages.
+ */
+stringtable
+	: stt_head tBEGIN strings tEND {
+		if(!$3)
+		{
+			yyerror("Stringtable must have at least one entry");
+		}
+		else
+		{
+			stringtable_t *stt;
+			/* Check if we added to a language table or created
+			 * a new one.
+			 */
+			 for(stt = sttres; stt; stt = stt->next)
+			 {
+				if(stt == tagstt)
+					break;
+			 }
+			 if(!stt)
+			 {
+				/* It is a new one */
+				if(sttres)
+				{
+					sttres->prev = tagstt;
+					tagstt->next = sttres;
+					sttres = tagstt;
+				}
+				else
+					sttres = tagstt;
+			 }
+			 /* Else were done */
+		}
+		if(tagstt_memopt)
+		{
+			free(tagstt_memopt);
+			tagstt_memopt = NULL;
+		}
+
+		$$ = tagstt;
+		}
+	;
+
+/* This is to get the language of the currently parsed stringtable */
+stt_head: STRINGTABLE loadmemopts opt_lvc {
+		if((tagstt = find_stringtable($3)) == NULL)
+			tagstt = new_stringtable($3);
+		tagstt_memopt = $2;
+		tagstt_version = $3->version;
+		tagstt_characts = $3->characts;
+		if($3)
+			free($3);
+		}
+	;
+
+strings	: /* Empty */	{ $$ = NULL; }
+	| strings expr opt_comma tSTRING {
+		int i;
+		assert(tagstt != NULL);
+		/* Search for the ID */
+		for(i = 0; i < tagstt->nentries; i++)
+		{
+			if(tagstt->entries[i].id == $2)
+				yyerror("Stringtable ID %d already in use", $2);
+		}
+		/* If we get here, then we have a new unique entry */
+		tagstt->nentries++;
+		tagstt->entries = xrealloc(tagstt->entries, sizeof(tagstt->entries[0]) * tagstt->nentries);
+		tagstt->entries[tagstt->nentries-1].id = $2;
+		tagstt->entries[tagstt->nentries-1].str = $4;
+		if(tagstt_memopt)
+			tagstt->entries[tagstt->nentries-1].memopt = *tagstt_memopt;
+		else
+			tagstt->entries[tagstt->nentries-1].memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE | WRC_MO_PURE;
+		tagstt->entries[tagstt->nentries-1].version = tagstt_version;
+		tagstt->entries[tagstt->nentries-1].characts = tagstt_characts;
+
+		if(!win32 && $4->size > 254)
+			yyerror("Stringtable entry more than 254 characters");
+		if(win32 && $4->size > 65534) /* Hmm..., does this happen? */
+			yyerror("Stringtable entry more than 65534 characters (probably something else that went wrong)");
+		$$ = tagstt;
+		}
+	;
+
+opt_comma	/* There seem to be two ways to specify a stringtable... */
+	: /* Empty */
+	| ','
+	;
+
+/* ------------------------------ VersionInfo ------------------------------ */
+versioninfo
+	: VERSIONINFO fix_version tBEGIN ver_blocks tEND {
+		$$ = $2;
+		$2->blocks = get_ver_block_head($4);
+		}
+	;
+
+fix_version
+	: /* Empty */			{ $$ = new_versioninfo(); }
+	| fix_version FILEVERSION expr ',' expr ',' expr ',' expr {
+		if($1->gotit.fv)
+			yyerror("FILEVERSION already defined");
+		$$ = $1;
+		$$->filever_maj1 = $3;
+		$$->filever_maj2 = $5;
+		$$->filever_min1 = $7;
+		$$->filever_min2 = $9;
+		$$->gotit.fv = 1;
+		}
+	| fix_version PRODUCTVERSION expr ',' expr ',' expr ',' expr {
+		if($1->gotit.pv)
+			yyerror("PRODUCTVERSION already defined");
+		$$ = $1;
+		$$->prodver_maj1 = $3;
+		$$->prodver_maj2 = $5;
+		$$->prodver_min1 = $7;
+		$$->prodver_min2 = $9;
+		$$->gotit.pv = 1;
+		}
+	| fix_version FILEFLAGS expr {
+		if($1->gotit.ff)
+			yyerror("FILEFLAGS already defined");
+		$$ = $1;
+		$$->fileflags = $3;
+		$$->gotit.ff = 1;
+		}
+	| fix_version FILEFLAGSMASK expr {
+		if($1->gotit.ffm)
+			yyerror("FILEFLAGSMASK already defined");
+		$$ = $1;
+		$$->fileflagsmask = $3;
+		$$->gotit.ffm = 1;
+		}
+	| fix_version FILEOS expr {
+		if($1->gotit.fo)
+			yyerror("FILEOS already defined");
+		$$ = $1;
+		$$->fileos = $3;
+		$$->gotit.fo = 1;
+		}
+	| fix_version FILETYPE expr {
+		if($1->gotit.ft)
+			yyerror("FILETYPE already defined");
+		$$ = $1;
+		$$->filetype = $3;
+		$$->gotit.ft = 1;
+		}
+	| fix_version FILESUBTYPE expr {
+		if($1->gotit.fst)
+			yyerror("FILESUBTYPE already defined");
+		$$ = $1;
+		$$->filesubtype = $3;
+		$$->gotit.fst = 1;
+		}
+	;
+
+ver_blocks
+	: /* Empty */			{ $$ = NULL; }
+	| ver_blocks ver_block {
+		$$ = $2;
+		$$->prev = $1;
+		if($1)
+			$1->next = $$;
+		}
+	;
+
+ver_block
+	: BLOCK tSTRING tBEGIN ver_values tEND {
+		$$ = new_ver_block();
+		$$->name = $2;
+		$$->values = get_ver_value_head($4);
+		}
+	;
+
+ver_values
+	: /* Empty */			{ $$ = NULL; }
+	| ver_values ver_value {
+		$$ = $2;
+		$$->prev = $1;
+		if($1)
+			$1->next = $$;
+		}
+	;
+
+ver_value
+	: ver_block {
+		$$ = new_ver_value();
+		$$->type = val_block;
+		$$->value.block = $1;
+		}
+	| VALUE tSTRING ',' tSTRING {
+		$$ = new_ver_value();
+		$$->type = val_str;
+		$$->key = $2;
+		$$->value.str = $4;
+		}
+	| VALUE tSTRING ',' ver_words {
+		$$ = new_ver_value();
+		$$->type = val_words;
+		$$->key = $2;
+		$$->value.words = $4;
+		}
+	;
+
+ver_words
+	: expr			{ $$ = new_ver_words($1); }
+	| ver_words ',' expr	{ $$ = add_ver_words($1, $3); }
+	;
+
+/* ------------------------------ Memory options ------------------------------ */
+loadmemopts
+	: /* Empty */		{ $$ = NULL; }
+	| loadmemopts lamo {
+		if($1)
+		{
+			*($1) |= *($2);
+			$$ = $1;
+			free($2);
+		}
+		else
+			$$ = $2;
+		}
+	| loadmemopts lama {
+		if($1)
+		{
+			*($1) &= *($2);
+			$$ = $1;
+			free($2);
+		}
+		else
+		{
+			*$2 &= WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE | WRC_MO_PURE;
+			$$ = $2;
+		}
+		}
+	;
+
+lamo	: PRELOAD	{ $$ = new_int(WRC_MO_PRELOAD); }
+	| MOVEABLE	{ $$ = new_int(WRC_MO_MOVEABLE); }
+	| DISCARDABLE	{ $$ = new_int(WRC_MO_DISCARDABLE); }
+	| tPURE		{ $$ = new_int(WRC_MO_PURE); }
+	;
+
+lama	: LOADONCALL	{ $$ = new_int(~WRC_MO_PRELOAD); }
+	| tFIXED	{ $$ = new_int(~WRC_MO_MOVEABLE); }
+	| IMPURE	{ $$ = new_int(~WRC_MO_PURE); }
+	;
+
+/* ------------------------------ Win32 options ------------------------------ */
+opt_lvc	: /* Empty */		{ $$ = new_lvc(); }
+	| opt_lvc opt_language {
+		if(!win32)
+			yywarning("LANGUAGE not supported in 16-bit mode");
+		if($1->language)
+			yyerror("Language already defined");
+		$$ = $1;
+		$1->language = $2;
+		}
+	| opt_lvc opt_characts {
+		if(!win32)
+			yywarning("CHARACTERISTICS not supported in 16-bit mode");
+		if($1->characts)
+			yyerror("Characteristics already defined");
+		$$ = $1;
+		$1->characts = $2;
+		}
+	| opt_lvc opt_version {
+		if(!win32)
+			yywarning("VERSION not supported in 16-bit mode");
+		if($1->version)
+			yyerror("Version already defined");
+		$$ = $1;
+		$1->version = $2;
+		}
+	;
+
+opt_language
+	: LANGUAGE expr ',' expr	{ $$ = new_language($2, $4); }
+	;
+
+opt_characts
+	: CHARACTERISTICS expr		{ $$ = new_characts($2); }
+	;
+
+opt_version
+	: VERSION expr			{ $$ = new_version($2); }
+	;
+
+/* ------------------------------ Raw data handking ------------------------------ */
+raw_data: tBEGIN raw_elements tEND	{ $$ = $2; }
+	;
+
+raw_elements
+	: RAWDATA			{ $$ = $1; }
+	| NUMBER			{ $$ = int2raw_data($1); }
+	| tSTRING			{ $$ = str2raw_data($1); }
+	| raw_elements opt_comma RAWDATA   { $$ = merge_raw_data($1, $3); free($3->data); free($3); }
+	| raw_elements opt_comma NUMBER	   { $$ = merge_raw_data_int($1, $3); }
+	| raw_elements opt_comma tSTRING   { $$ = merge_raw_data_str($1, $3); }
+	;
+
+/* ------------------------------ Win32 expressions ------------------------------ */
+/* All win16 numbers are also handled here. This is inconsistent with MS'
+ * resource compiler, but what the heck, its just handy to have.
+ */
+e_expr	: /* Empty */	{ $$ = 0; }
+	| expr		{ $$ = new_int($1); }
+	;
+expr	: dummy xpr	{ $$ = ($2) & andmask; }
+	;
+
+dummy	: /* Empty */	{ $$ = 0; andmask = -1; }
+	;
+
+xpr	: xpr '+' xpr	{ $$ = ($1) + ($3); }
+	| xpr '-' xpr	{ $$ = ($1) - ($3); }
+	| xpr '|' xpr	{ $$ = ($1) | ($3); }
+	| xpr '&' xpr	{ $$ = ($1) & ($3); }
+	| xpr '*' xpr	{ $$ = ($1) * ($3); }
+	| xpr '/' xpr	{ $$ = ($1) / ($3); }
+	| '~' xpr	{ $$ = ~($2); }
+	| '-' xpr	{ $$ = -($2); }		/* FIXME: shift/reduce conflict */
+/*	| '+' xpr	{ $$ = $2; } */
+	| '(' xpr ')'	{ $$ = $2; }
+	| NUMBER	{ $$ = $1; want_rscname = 0; }
+	| NOT NUMBER	{ $$ = 0; andmask &= ~($2); }
+	;
+%%
+/* Dialog specific functions */
+dialog_t *dialog_style(int st, dialog_t *dlg)
+{
+	DWORD s = 0;
+	assert(dlg != NULL);
+	if(dlg->gotstyle)
+	{
+		yywarning("Style already defined, or-ing together");
+		s = dlg->style;
+	}
+	dlg->style = st | s;
+	dlg->gotstyle = TRUE;
+	return dlg;
+}
+
+dialog_t *dialog_exstyle(int st, dialog_t *dlg)
+{
+	DWORD s = 0;
+	assert(dlg != NULL);
+	if(dlg->gotexstyle)
+	{
+		yywarning("ExStyle already defined, or-ing together");
+		s = dlg->style;
+	}
+	dlg->exstyle = st | s;
+	dlg->gotexstyle = TRUE;
+	return dlg;
+}
+
+dialog_t *dialog_caption(string_t *s, dialog_t *dlg)
+{
+	assert(dlg != NULL);
+	if(dlg->title)
+		yyerror("Caption already defined");
+	dlg->title = s;
+	return dlg;
+}
+
+dialog_t *dialog_font(font_id_t *f, dialog_t *dlg)
+{
+	assert(dlg != NULL);
+	if(dlg->font)
+		yyerror("Font already defined");
+	dlg->font = f;
+	return dlg;
+}
+
+dialog_t *dialog_class(name_id_t *n, dialog_t *dlg)
+{
+	assert(dlg != NULL);
+	if(dlg->dlgclass)
+		yyerror("Class already defined");
+	dlg->dlgclass = n;
+	return dlg;
+}
+
+dialog_t *dialog_menu(name_id_t *m, dialog_t *dlg)
+{
+	assert(dlg != NULL);
+	if(dlg->menu)
+		yyerror("Menu already defined");
+	dlg->menu = m;
+	return dlg;
+}
+
+dialog_t *dialog_language(language_t *l, dialog_t *dlg)
+{
+	assert(dlg != NULL);
+	if(dlg->lvc.language)
+		yyerror("Language already defined");
+	dlg->lvc.language = l;
+	return dlg;
+}
+
+dialog_t *dialog_characteristics(characts_t *c, dialog_t *dlg)
+{
+	assert(dlg != NULL);
+	if(dlg->lvc.characts)
+		yyerror("Characteristics already defined");
+	dlg->lvc.characts = c;
+	return dlg;
+}
+
+dialog_t *dialog_version(version_t *v, dialog_t *dlg)
+{
+	assert(dlg != NULL);
+	if(dlg->lvc.version)
+		yyerror("Version already defined");
+	dlg->lvc.version = v;
+	return dlg;
+}
+
+/* Controls specific functions */
+control_t *ins_ctrl(int type, int style, control_t *ctrl, control_t *prev)
+{
+	assert(ctrl != NULL);
+	ctrl->prev = prev;
+	if(prev)
+		prev->next = ctrl;
+	if(type != -1)
+	{
+		ctrl->ctlclass = new_name_id();
+		ctrl->ctlclass->type = name_ord;
+		ctrl->ctlclass->name.i_name = type;
+	}
+
+	/* Hm... this seems to be jammed in at all time... */
+	ctrl->style |= WS_CHILD | WS_VISIBLE;
+	switch(type)
+	{
+	case CT_BUTTON:
+		ctrl->style |= style;
+		if(style != BS_GROUPBOX && style != BS_RADIOBUTTON)
+			ctrl->style |= WS_TABSTOP;
+		break;
+	case CT_EDIT:
+		ctrl->style |= WS_TABSTOP | WS_BORDER;
+		break;
+	case CT_LISTBOX:
+		ctrl->style |= LBS_NOTIFY | WS_BORDER;
+		break;
+	case CT_COMBOBOX:
+		ctrl->style |= CBS_SIMPLE;
+		break;
+	case CT_STATIC:
+		ctrl->style |= style;
+		if(style == SS_CENTER || style == SS_LEFT || style == SS_RIGHT)
+			ctrl->style |= WS_GROUP;
+		break;
+	}
+
+	if(!ctrl->gotstyle)	/* Handle default style setting */
+	{
+		switch(type)
+		{
+		case CT_EDIT:
+			ctrl->style |= ES_LEFT;
+			break;
+		case CT_LISTBOX:
+			ctrl->style |= LBS_NOTIFY;
+			break;
+		case CT_COMBOBOX:
+			ctrl->style |= CBS_SIMPLE | WS_TABSTOP;
+			break;
+		case CT_SCROLLBAR:
+			ctrl->style |= SBS_HORZ;
+			break;
+		case CT_BUTTON:
+			switch(style)
+			{
+			case BS_CHECKBOX:
+			case BS_DEFPUSHBUTTON:
+			case BS_PUSHBUTTON:
+			case BS_GROUPBOX:
+/*			case BS_PUSHBOX:	*/
+			case BS_AUTORADIOBUTTON:
+			case BS_AUTO3STATE:
+			case BS_3STATE:
+			case BS_AUTOCHECKBOX:
+				ctrl->style |= WS_TABSTOP;
+				break;
+			default:
+				yywarning("Unknown default button control-style 0x%08x", style);
+			case BS_RADIOBUTTON:
+				break;
+			}
+			break;
+
+		case CT_STATIC:
+			switch(style)
+			{
+			case SS_LEFT:
+			case SS_RIGHT:
+			case SS_CENTER:
+				ctrl->style |= WS_GROUP;
+				break;
+			case SS_ICON:	/* Special case */
+				break;
+			default:
+				yywarning("Unknown default static control-style 0x%08x", style);
+				break;
+			}
+			break;
+		case -1:	/* Generic control */
+			goto byebye;
+
+		default:
+			yyerror("Internal error (report this): Got weird control type 0x%08x", type);
+		}
+	}
+
+	/* The SS_ICON flag is always forced in for icon controls */
+	if(type == CT_STATIC && style == SS_ICON)
+		ctrl->style |= SS_ICON;
+
+	ctrl->gotstyle = TRUE;
+byebye:
+	return ctrl;
+}
+
+name_id_t *convert_ctlclass(name_id_t *cls)
+{
+	char *cc;
+	int iclass;
+
+	if(cls->type == name_ord)
+		return cls;
+	assert(cls->type == name_str);
+	if(cls->type == str_unicode)
+	{
+		yyerror("Don't yet support unicode class comparison");
+	}
+	else
+		cc = cls->name.s_name->str.cstr;
+
+	if(!stricmp("BUTTON", cc))
+		iclass = CT_BUTTON;
+	else if(!stricmp("COMBOBOX", cc))
+		iclass = CT_COMBOBOX;
+	else if(!stricmp("LISTBOX", cc))
+		iclass = CT_LISTBOX;
+	else if(!stricmp("EDIT", cc))
+		iclass = CT_EDIT;
+	else if(!stricmp("STATIC", cc))
+		iclass = CT_STATIC;
+	else if(!stricmp("SCROLLBAR", cc))
+		iclass = CT_SCROLLBAR;
+	else
+		return cls;	/* No default, return user controlclass */
+
+	free(cls->name.s_name->str.cstr);
+	free(cls->name.s_name);
+	cls->type = name_ord;
+	cls->name.i_name = iclass;
+	return cls;
+}
+
+/* DialogEx specific functions */
+dialogex_t *dialogex_style(int st, dialogex_t *dlg)
+{
+	DWORD s = 0;
+	assert(dlg != NULL);
+	if(dlg->gotstyle)
+	{
+		yywarning("Style already defined, or-ing together");
+		s = dlg->style;
+	}
+	dlg->style = st | s;
+	dlg->gotstyle = TRUE;
+	return dlg;
+}
+
+dialogex_t *dialogex_exstyle(int st, dialogex_t *dlg)
+{
+	DWORD s = 0;
+	assert(dlg != NULL);
+	if(dlg->gotexstyle)
+	{
+		yywarning("ExStyle already defined, or-ing together");
+		s = dlg->exstyle;
+	}
+	dlg->exstyle = st | s;
+	dlg->gotexstyle = TRUE;
+	return dlg;
+}
+
+dialogex_t *dialogex_caption(string_t *s, dialogex_t *dlg)
+{
+	assert(dlg != NULL);
+	if(dlg->title)
+		yyerror("Caption already defined");
+	dlg->title = s;
+	return dlg;
+}
+
+dialogex_t *dialogex_font(font_id_t *f, dialogex_t *dlg)
+{
+	assert(dlg != NULL);
+	if(dlg->font)
+		yyerror("Font already defined");
+	dlg->font = f;
+	return dlg;
+}
+
+dialogex_t *dialogex_class(name_id_t *n, dialogex_t *dlg)
+{
+	assert(dlg != NULL);
+	if(dlg->dlgclass)
+		yyerror("Class already defined");
+	dlg->dlgclass = n;
+	return dlg;
+}
+
+dialogex_t *dialogex_menu(name_id_t *m, dialogex_t *dlg)
+{
+	assert(dlg != NULL);
+	if(dlg->menu)
+		yyerror("Menu already defined");
+	dlg->menu = m;
+	return dlg;
+}
+
+dialogex_t *dialogex_language(language_t *l, dialogex_t *dlg)
+{
+	assert(dlg != NULL);
+	if(dlg->lvc.language)
+		yyerror("Language already defined");
+	dlg->lvc.language = l;
+	return dlg;
+}
+
+dialogex_t *dialogex_characteristics(characts_t *c, dialogex_t *dlg)
+{
+	assert(dlg != NULL);
+	if(dlg->lvc.characts)
+		yyerror("Characteristics already defined");
+	dlg->lvc.characts = c;
+	return dlg;
+}
+
+dialogex_t *dialogex_version(version_t *v, dialogex_t *dlg)
+{
+	assert(dlg != NULL);
+	if(dlg->lvc.version)
+		yyerror("Version already defined");
+	dlg->lvc.version = v;
+	return dlg;
+}
+
+/* Accelerator specific functions */
+event_t *add_event(int key, int id, int flags, event_t *prev)
+{
+	event_t *ev = new_event();
+
+	if((flags & (WRC_AF_VIRTKEY | WRC_AF_ASCII)) == (WRC_AF_VIRTKEY | WRC_AF_ASCII))
+		yyerror("Cannot use both ASCII and VIRTKEY");
+
+	ev->key = key;
+	ev->id = id;
+	ev->flags = flags & ~WRC_AF_ASCII;
+	ev->prev = prev;
+	if(prev)
+		prev->next = ev;
+	return ev;
+}
+
+event_t *add_string_event(string_t *key, int id, int flags, event_t *prev)
+{
+	int keycode;
+	event_t *ev = new_event();
+
+	if(key->type != str_char)
+		yyerror("Key code must be an ascii string");
+
+	if((flags & WRC_AF_VIRTKEY) && (!isupper(key->str.cstr[0]) || !isdigit(key->str.cstr[0])))
+		yyerror("VIRTKEY code is not equal to ascii value");
+
+	if(key->str.cstr[0] == '^')
+	{
+		keycode = toupper(key->str.cstr[1]) - '@';
+		if(keycode >= ' ')
+			yyerror("Control-code out of range");
+	}
+	else
+		keycode = key->str.cstr[0];
+	ev->key = keycode;
+	ev->id = id;
+	ev->flags = flags & ~WRC_AF_ASCII;
+	ev->prev = prev;
+	if(prev)
+		prev->next = ev;
+	return ev;
+}
+
+/* MenuEx specific functions */
+itemex_opt_t *new_itemex_opt(int id, int type, int state, int helpid)
+{
+	itemex_opt_t *opt = (itemex_opt_t *)xmalloc(sizeof(itemex_opt_t));
+	opt->id = id;
+	opt->type = type;
+	opt->state = state;
+	opt->helpid = helpid;
+	return opt;
+}
+
+/* Raw data functions */
+raw_data_t *load_file(string_t *name)
+{
+	FILE *fp;
+	raw_data_t *rd;
+	if(name->type != str_char)
+		yyerror("Filename must be ASCII string");
+		
+	fp = fopen(name->str.cstr, "rb");
+	if(!fp)
+		yyerror("Cannot open file %s", name);
+	rd = new_raw_data();
+	fseek(fp, 0, SEEK_END);
+	rd->size = ftell(fp);
+	fseek(fp, 0, SEEK_SET);
+	rd->data = (char *)xmalloc(rd->size);
+	fread(rd->data, rd->size, 1, fp);
+	fclose(fp);
+	HEAPCHECK();
+	return rd;
+}
+
+raw_data_t *int2raw_data(int i)
+{
+	raw_data_t *rd;
+	rd = new_raw_data();
+	rd->size = sizeof(short);
+	rd->data = (char *)xmalloc(rd->size);
+	*(short *)(rd->data) = (short)i;
+	return rd;
+}
+
+raw_data_t *str2raw_data(string_t *str)
+{
+	raw_data_t *rd;
+	rd = new_raw_data();
+	rd->size = str->size * (str->type == str_char ? 1 : 2);
+	rd->data = (char *)xmalloc(rd->size);
+	memcpy(rd->data, str->str.cstr, rd->size);
+	return rd;
+}
+
+raw_data_t *merge_raw_data(raw_data_t *r1, raw_data_t *r2)
+{
+	r1->data = xrealloc(r1->data, r1->size + r2->size);
+	memcpy(r1->data + r1->size, r2->data, r2->size);
+	r1->size += r2->size;
+	return r1;
+}
+
+raw_data_t *merge_raw_data_int(raw_data_t *r1, int i)
+{
+	raw_data_t *t = int2raw_data(i);
+	merge_raw_data(r1, t);
+	free(t->data);
+	free(t);
+	return r1;
+}
+
+raw_data_t *merge_raw_data_str(raw_data_t *r1, string_t *str)
+{
+	raw_data_t *t = str2raw_data(str);
+	merge_raw_data(r1, t);
+	free(t->data);
+	free(t);
+	return r1;
+}
+
+/* Function the go back in a list to get the head */
+menu_item_t *get_item_head(menu_item_t *p)
+{
+	if(!p)
+		return NULL;
+	while(p->prev)
+		p = p->prev;
+	return p;
+}
+
+menuex_item_t *get_itemex_head(menuex_item_t *p)
+{
+	if(!p)
+		return NULL;
+	while(p->prev)
+		p = p->prev;
+	return p;
+}
+
+resource_t *get_resource_head(resource_t *p)
+{
+	if(!p)
+		return NULL;
+	while(p->prev)
+		p = p->prev;
+	return p;
+}
+
+ver_block_t *get_ver_block_head(ver_block_t *p)
+{
+	if(!p)
+		return NULL;
+	while(p->prev)
+		p = p->prev;
+	return p;
+}
+
+ver_value_t *get_ver_value_head(ver_value_t *p)
+{
+	if(!p)
+		return NULL;
+	while(p->prev)
+		p = p->prev;
+	return p;
+}
+
+control_t *get_control_head(control_t *p)
+{
+	if(!p)
+		return NULL;
+	while(p->prev)
+		p = p->prev;
+	return p;
+}
+
+event_t *get_event_head(event_t *p)
+{
+	if(!p)
+		return NULL;
+	while(p->prev)
+		p = p->prev;
+	return p;
+}
+
+/* Find a stringtable with given language */
+stringtable_t *find_stringtable(lvc_t *lvc)
+{
+	stringtable_t *stt;
+
+	assert(lvc != NULL);
+
+	if(!lvc->language)
+		lvc->language = currentlanguage;
+
+	for(stt = sttres; stt; stt = stt->next)
+	{
+		if(stt->lvc.language->id == lvc->language->id
+		&& stt->lvc.language->id == lvc->language->id)
+		{
+			/* Found a table with the same language */
+			/* The version and characteristics are now handled
+			 * in the generation of the individual stringtables.
+			 * This enables localized analysis.
+			if((stt->lvc.version && lvc->version && *(stt->lvc.version) != *(lvc->version))
+			|| (!stt->lvc.version && lvc->version)
+			|| (stt->lvc.version && !lvc->version))
+				yywarning("Stringtable's versions are not the same, using first definition");
+
+			if((stt->lvc.characts && lvc->characts && *(stt->lvc.characts) != *(lvc->characts))
+			|| (!stt->lvc.characts && lvc->characts)
+			|| (stt->lvc.characts && !lvc->characts))
+				yywarning("Stringtable's characteristics are not the same, using first definition");
+			*/
+			return stt;
+		}
+	}
+	return NULL;
+}
+
+/* qsort sorting function for string table entries */
+#define STE(p)	((stt_entry_t *)(p))
+int sort_stt_entry(const void *e1, const void *e2)
+{
+	return STE(e1)->id - STE(e2)->id;
+}
+#undef STE
+
+resource_t *build_stt_resources(stringtable_t *stthead)
+{
+	stringtable_t *stt;
+	stringtable_t *newstt;
+	resource_t *rsc;
+	resource_t *rsclist = NULL;
+	resource_t *rsctail = NULL;
+	int i;
+	int j;
+	DWORD andsum;
+	DWORD orsum;
+	characts_t *characts;
+	version_t *version;
+
+	if(!stthead)
+		return NULL;
+
+	/* For all languages defined */
+	for(stt = stthead; stt; stt = stt->next)
+	{
+		assert(stt->nentries > 0);
+
+		/* Sort the entries */
+		if(stt->nentries > 1)
+			qsort(stt->entries, stt->nentries, sizeof(stt->entries[0]), sort_stt_entry);
+
+		for(i = 0; i < stt->nentries; )
+		{
+			newstt = new_stringtable(&stt->lvc);
+			newstt->entries = (stt_entry_t *)xmalloc(16 * sizeof(stt_entry_t));
+			newstt->nentries = 16;
+			newstt->idbase = stt->entries[i].id & ~0xf;
+			for(j = 0; j < 16 && i < stt->nentries; j++)
+			{
+				if(stt->entries[i].id - newstt->idbase == j)
+				{
+					newstt->entries[j] = stt->entries[i];
+					i++;
+				}
+			}
+			andsum = ~0;
+			orsum = 0;
+			characts = NULL;
+			version = NULL;
+			/* Check individual memory options and get
+			 * the first characteristics/version
+			 */
+			for(j = 0; j < 16; j++)
+			{
+				if(!newstt->entries[j].str)
+					continue;
+				andsum &= newstt->entries[j].memopt;
+				orsum |= newstt->entries[j].memopt;
+				if(!characts)
+					characts = newstt->entries[j].characts;
+				if(!version)
+					version = newstt->entries[j].version;
+			}
+			if(andsum != orsum)
+			{
+				warning("Stringtable's memory options are not equal (idbase: %d)", newstt->idbase);
+			}
+			/* Check version and characteristics */
+			for(j = 0; j < 16; j++)
+			{
+				if(characts
+				&& newstt->entries[j].characts
+				&& *newstt->entries[j].characts != *characts)
+					warning("Stringtable's characteristics are not the same (idbase: %d)", newstt->idbase);
+				if(version
+				&& newstt->entries[j].version
+				&& *newstt->entries[j].version != *version)
+					warning("Stringtable's versions are not the same (idbase: %d)", newstt->idbase);
+			}
+			rsc = new_resource(res_stt, newstt, newstt->memopt, newstt->lvc.language);
+			rsc->name = new_name_id();
+			rsc->name->type = name_ord;
+			rsc->name->name.i_name = (newstt->idbase >> 4) + 1;
+			rsc->memopt = andsum; /* Set to least common denominator */
+			newstt->memopt = andsum;
+			newstt->lvc.characts = characts;
+			newstt->lvc.version = version;
+			if(!rsclist)
+			{
+				rsclist = rsc;
+				rsctail = rsc;
+			}
+			else
+			{
+				rsctail->next = rsc;
+				rsc->prev = rsctail;
+				rsctail = rsc;
+			}
+		}
+	}
+	return rsclist;
+}
+
+/* Cursor and icon splitter functions */
+int alloc_icon_id(void)
+{
+	static int icon_id = 1;
+	return icon_id++;
+}
+
+int alloc_cursor_id(void)
+{
+	static int cursor_id = 1;
+	return cursor_id++;
+}
+
+#define BPTR(base)	((char *)(rd->data + (base)))
+#define WPTR(base)	((WORD *)(rd->data + (base)))
+#define DPTR(base)	((DWORD *)(rd->data + (base)))
+void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico)
+{
+	int cnt;
+	int i;
+	icon_dir_entry_t *ide;
+	icon_t *ico;
+	icon_t *list = NULL;
+
+	/* FIXME: Distinguish between normal and animated icons (RIFF format) */
+	if(WPTR(0)[1] != 1)
+		yyerror("Icon resource data has invalid type id %d", WPTR(0)[1]);
+	cnt = WPTR(0)[2];
+	ide = (icon_dir_entry_t *)&(WPTR(0)[3]);
+	for(i = 0; i < cnt; i++)
+	{
+		ico = new_icon();
+		ico->id = alloc_icon_id();
+		if(ide[i].offset > rd->size
+		|| ide[i].offset + ide[i].ressize > rd->size)
+			yyerror("Icon resource data corrupt");
+		ico->width = ide[i].width;
+		ico->height = ide[i].height;
+		ico->nclr = ide[i].nclr;
+		ico->planes = ide[i].planes;
+		ico->bits = ide[i].bits;
+		if(!ico->planes)
+		{
+			/* Argh! They did not fill out the resdir structure */
+			ico->planes = ((BITMAPINFOHEADER *)BPTR(ide[i].offset))->biPlanes;
+		}
+		if(!ico->bits)
+		{
+			/* Argh! They did not fill out the resdir structure */
+			ico->bits = ((BITMAPINFOHEADER *)BPTR(ide[i].offset))->biBitCount;
+		}
+		ico->data = new_raw_data();
+		copy_raw_data(ico->data, rd, ide[i].offset, ide[i].ressize);
+		if(!list)
+		{
+			list = ico;
+		}
+		else
+		{
+			ico->next = list;
+			list->prev = ico;
+			list = ico;
+		}
+	}
+	icog->iconlist = list;
+	*nico = cnt;
+}
+
+void split_cursors(raw_data_t *rd, cursor_group_t *curg, int *ncur)
+{
+	int cnt;
+	int i;
+	cursor_dir_entry_t *cde;
+	cursor_t *cur;
+	cursor_t *list = NULL;
+
+	/* FIXME: Distinguish between normal and animated cursors (RIFF format)*/
+	if(WPTR(0)[1] != 2)
+		yyerror("Cursor resource data has invalid type id %d", WPTR(0)[1]);
+	cnt = WPTR(0)[2];
+	cde = (cursor_dir_entry_t *)&(WPTR(0)[3]);
+	for(i = 0; i < cnt; i++)
+	{
+		cur = new_cursor();
+		cur->id = alloc_cursor_id();
+		if(cde[i].offset > rd->size
+		|| cde[i].offset + cde[i].ressize > rd->size)
+			yyerror("Cursor resource data corrupt");
+		cur->width = cde[i].width;
+		cur->height = cde[i].height;
+		cur->nclr = cde[i].nclr;
+		/* The next two are to support color cursors */
+		cur->planes = ((BITMAPINFOHEADER *)BPTR(cde[i].offset))->biPlanes;
+		cur->bits = ((BITMAPINFOHEADER *)BPTR(cde[i].offset))->biBitCount;
+		if(!win32 && (cur->planes != 1 || cur->bits != 1))
+			yywarning("Win16 cursor contains colors");
+		cur->xhot = cde[i].xhot;
+		cur->yhot = cde[i].yhot;
+		cur->data = new_raw_data();
+		copy_raw_data(cur->data, rd, cde[i].offset, cde[i].ressize);
+		if(!list)
+		{
+			list = cur;
+		}
+		else
+		{
+			cur->next = list;
+			list->prev = cur;
+			list = cur;
+		}
+	}
+	curg->cursorlist = list;
+	*ncur = cnt;
+}
+
+#undef	BPTR
+#undef	WPTR
+#undef	DPTR
+
+
diff --git a/tools/wrc/preproc.c b/tools/wrc/preproc.c
new file mode 100644
index 0000000..d523bc5
--- /dev/null
+++ b/tools/wrc/preproc.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright 1998 Bertho A. Stultiens (BS)
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <config.h>
+#include "wrc.h"
+#include "utils.h"
+#include "preproc.h"
+#include "parser.h"
+
+
+extern void set_pp_ignore(int);	/* From parser.l */
+
+static char *current_define;
+
+#define HASHKEY		2039
+static struct pp_entry *pp_defines[HASHKEY];
+
+#define MAXIFSTACK	64
+static struct if_state ifstack[MAXIFSTACK];
+static int ifstackidx = 0;
+
+#if 0
+void pp_status(void)
+{
+	int i;
+	int sum;
+	int total = 0;
+	struct pp_entry *ppp;
+
+	printf("Defines statistics:\n");
+	for(i = 0; i < HASHKEY; i++)
+	{
+		sum = 0;
+		for(ppp = pp_defines[i]; ppp; ppp = ppp->next)
+			sum++;
+		total += sum;
+		printf("%4d, %3d\n", i, sum);
+	}
+	printf("Total defines: %d\n", total);
+}
+#pragma exit pp_status
+#endif
+
+/* Don't comment on the hash, its primitive but functional... */
+int pp_hash(char *str)
+{
+	int sum = 0;
+	while(*str)
+		sum += *str++;
+	return sum % HASHKEY;
+}
+
+struct pp_entry *pp_lookup(char *ident)
+{
+	int index = pp_hash(ident);
+	struct pp_entry *ppp;
+	for(ppp = pp_defines[index]; ppp; ppp = ppp->next)
+	{
+		if(!strcmp(ident, ppp->ident))
+			return ppp;
+	}
+	return NULL;
+}
+
+void set_define(char *name)
+{
+	current_define = xstrdup(name);
+}
+
+void del_define(char *name)
+{
+	int index;
+	struct pp_entry *ppp;
+
+	if((ppp = pp_lookup(name)) == NULL)
+	{
+		if(pedantic)
+			yywarning("%s was not defined", name);
+		return;
+	}
+
+	index = pp_hash(name);
+	if(pp_defines[index] == ppp)
+	{
+		pp_defines[index] = ppp->next;
+		if(pp_defines[index])
+			pp_defines[index]->prev = NULL;
+	}
+	else
+	{
+		ppp->prev->next = ppp->next;
+		if(ppp->next)
+			ppp->next->prev = ppp->prev;
+	}
+	free(ppp);
+}
+
+void add_define(char *text)
+{
+	int len;
+	char *cptr;
+	int index = pp_hash(current_define);
+	struct pp_entry *ppp;
+	if(pp_lookup(current_define) != NULL)
+	{
+		if(pedantic)
+			yywarning("Redefinition of %s", current_define);
+		del_define(current_define);
+	}
+	ppp = (struct pp_entry *)xmalloc(sizeof(struct pp_entry));
+	ppp->ident = current_define;
+	ppp->subst = xstrdup(text);
+	ppp->next = pp_defines[index];
+	pp_defines[index] = ppp;
+	if(ppp->next)
+		ppp->next->prev = ppp;
+	/* Strip trailing white space from subst text */
+	len = strlen(ppp->subst);
+	while(len && strchr(" \t\r\n", ppp->subst[len-1]))
+	{
+		ppp->subst[--len] = '\0';
+	}
+	/* Strip leading white space from subst text */
+	for(cptr = ppp->subst; *cptr && strchr(" \t\r", *cptr); cptr++)
+		;
+	if(ppp->subst != cptr)
+		memmove(ppp->subst, cptr, strlen(cptr)+1);
+	if(yydebug)
+		printf("Added (%s, %d) <%s> to <%s>\n", input_name, line_number, ppp->ident, ppp->subst);
+}
+
+void add_cmdline_define(char *set)
+{
+	char *cpy = xstrdup(set);	/* Because gcc passes a R/O string */
+	char *cptr = strchr(cpy, '=');
+	if(cptr)
+		*cptr = '\0';
+	set_define(cpy);
+	add_define(cptr ? cptr+1 : "");
+	free(cpy);
+}
+
+#if defined(_Windows) || defined(__MSDOS__)
+#define INCLUDESEPARATOR	";"
+#else
+#define INCLUDESEPARATOR	":"
+#endif
+
+static char **includepath;
+static int nincludepath = 0;
+
+void add_include_path(char *path)
+{
+	char *tok;
+	char *cpy = xstrdup(path);
+
+	tok = strtok(cpy, INCLUDESEPARATOR);
+	while(tok)
+	{
+		char *dir;
+		char *cptr;
+		if(strlen(tok) == 0)
+			continue;
+		dir = xstrdup(tok);
+		for(cptr = dir; *cptr; cptr++)
+		{
+			/* Convert to forward slash */
+			if(*cptr == '\\')
+				*cptr = '/';
+		}
+		/* Kill eventual trailing '/' */
+		if(*(cptr = dir + strlen(dir)-1) == '/')
+			*cptr = '\0';
+
+		/* Add to list */
+		nincludepath++;
+		includepath = (char **)xrealloc(includepath, nincludepath * sizeof(*includepath));
+		includepath[nincludepath-1] = dir;
+		tok = strtok(NULL, INCLUDESEPARATOR);
+	}
+	free(cpy);
+}
+
+FILE *open_include(const char *name, int search)
+{
+	char *cpy = xstrdup(name);
+	char *cptr;
+	FILE *fp;
+	int i;
+
+	for(cptr = cpy; *cptr; cptr++)
+	{
+		/* kill double backslash */
+		if(*cptr == '\\' && *(cptr+1) == '\\')
+			memmove(cptr, cptr+1, strlen(cptr));
+		/* Convert to forward slash */
+		if(*cptr == '\\')
+			*cptr = '/';
+	}
+
+	if(search)
+	{
+		/* Search current dir and then -I path */
+		fp = fopen(name, "rt");
+		if(fp)
+		{
+			if(yydebug)
+				printf("Going to include <%s>\n", name);
+			free(cpy);
+			return fp;
+		}
+	}
+	/* Search -I path */
+	for(i = 0; i < nincludepath; i++)
+	{
+		char *path;
+		path = (char *)xmalloc(strlen(includepath[i]) + strlen(cpy) + 2);
+		strcpy(path, includepath[i]);
+		strcat(path, "/");
+		strcat(path, cpy);
+		fp = fopen(path, "rt");
+		if(fp && yydebug)
+			printf("Going to include <%s>\n", path);
+		free(path);
+		if(fp)
+		{
+			free(cpy);
+			return fp;
+		}
+
+	}
+	free(cpy);
+	return NULL;
+}
+
+void push_if(int truecase, int wastrue, int nevertrue)
+{
+	if(ifstackidx >= MAXIFSTACK-1)
+		internal_error(__FILE__, __LINE__, "#if stack overflow");
+	ifstack[ifstackidx].current = truecase && !wastrue;
+	ifstack[ifstackidx].hasbeentrue = wastrue;
+	ifstack[ifstackidx].nevertrue = nevertrue;
+	if(nevertrue || !(truecase && !wastrue))
+		set_pp_ignore(1);
+	if(yydebug)
+		printf("push_if: %d %d %d (%d %d %d)\n",
+			truecase,
+			wastrue,
+			nevertrue,
+			ifstack[ifstackidx].current,
+			ifstack[ifstackidx].hasbeentrue,
+			ifstack[ifstackidx].nevertrue);
+	ifstackidx++;
+}
+
+int pop_if(void)
+{
+	if(ifstackidx <= 0)
+		yyerror("#endif without #if|#ifdef|#ifndef (#if stack underflow)");
+	ifstackidx--;
+	if(yydebug)
+		printf("pop_if: %d %d %d\n",
+			ifstack[ifstackidx].current,
+			ifstack[ifstackidx].hasbeentrue,
+			ifstack[ifstackidx].nevertrue);
+	if(ifstack[ifstackidx].nevertrue || !ifstack[ifstackidx].current)
+		set_pp_ignore(0);
+	return ifstack[ifstackidx].hasbeentrue || ifstack[ifstackidx].current;
+}
+
+int isnevertrue_if(void)
+{
+	return ifstackidx > 0 && ifstack[ifstackidx-1].nevertrue;
+}
+
diff --git a/tools/wrc/preproc.h b/tools/wrc/preproc.h
new file mode 100644
index 0000000..c8f13f7
--- /dev/null
+++ b/tools/wrc/preproc.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 1998 Bertho A. Stultiens (BS)
+ *
+ */
+
+#ifndef __WRC_PREPROC_H
+#define __WRC_PREPROC_H
+
+struct pp_entry {
+	struct pp_entry *next;
+	struct pp_entry *prev;
+	char	*ident;
+	char	*subst;
+	int	expanding;
+};
+
+struct if_state {
+	int	current;
+	int	hasbeentrue;
+	int	nevertrue;
+};
+
+struct pp_entry *pp_lookup(char *ident);
+void set_define(char *name);
+void del_define(char *name);
+void add_define(char *text);
+void add_cmdline_define(char *set);
+FILE *open_include(const char *name, int search);
+void add_include_path(char *path);
+void push_if(int truecase, int wastrue, int nevertrue);
+int pop_if(void);
+int isnevertrue_if(void);
+
+#endif
+
diff --git a/tools/wrc/readres.c b/tools/wrc/readres.c
new file mode 100644
index 0000000..c2fdc6d
--- /dev/null
+++ b/tools/wrc/readres.c
@@ -0,0 +1,369 @@
+/*
+ * Read a .res file and create a resource-tree
+ *
+ * Copyright 1998 Bertho A. Stultiens
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <config.h>
+#include "wrc.h"
+#include "readres.h"
+#include "newstruc.h"
+#include "utils.h"
+#include "genres.h"
+
+struct resheader32 {
+	DWORD	ressize;	/* 0 */
+	DWORD	hdrsize;	/* 0x20 */
+	WORD	restype1;	/* 0xffff */
+	WORD	restype2;	/* 0 */
+	WORD	resname1;	/* 0xffff */
+	WORD	resname2;	/* 0 */
+	DWORD	dversion;	/* 0 */
+	WORD	memopt;		/* 0 */
+	WORD	language;	/* 0 */
+	DWORD	version;	/* 0 */
+	DWORD	characts;	/* 0 */
+} emptyheader = {0, 0x20, 0xffff, 0, 0xffff, 0, 0, 0, 0, 0, 0};
+
+/*
+ *****************************************************************************
+ * Function	:
+ * Syntax	:
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+/*
+ *****************************************************************************
+ * Function	:
+ * Syntax	:
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+/*
+ *****************************************************************************
+ * Function	:
+ * Syntax	:
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+int read_data(FILE *fp, size_t size, void *buf)
+{
+	int r;
+	int pos = ftell(fp);
+	r = fread(buf, 1, size, fp);
+	if(r == size)
+		return 0;
+	if(r == 0 && ftell(fp) - pos > 0)
+		return 1;
+	else
+		return -1;
+}
+
+/*
+ *****************************************************************************
+ * Function	:
+ * Syntax	:
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+enum res_e res_type_from_id(name_id_t *nid)
+{
+	if(nid->type == name_str)
+		return res_usr;
+
+	if(nid->type != name_ord)
+		internal_error(__FILE__, __LINE__, "Invalid name_id descriptor %d", nid->type);
+
+	switch(nid->name.i_name)
+	{
+	case WRC_RT_CURSOR:		return res_cur;
+	case WRC_RT_BITMAP:		return res_bmp;
+	case WRC_RT_ICON:		return res_ico;
+	case WRC_RT_MENU:		return res_men;
+	case WRC_RT_DIALOG:		return res_dlg;
+	case WRC_RT_STRING:		return res_stt;
+	case WRC_RT_FONTDIR:		return res_fntdir;
+	case WRC_RT_FONT:		return res_fnt;
+	case WRC_RT_ACCELERATOR:	return res_acc;
+	case WRC_RT_RCDATA:		return res_rdt;
+	case WRC_RT_MESSAGETABLE:	return res_msg;
+	case WRC_RT_GROUP_CURSOR:	return res_curg;
+	case WRC_RT_GROUP_ICON:		return res_icog;
+	case WRC_RT_VERSION:		return res_ver;
+
+	default:
+	case WRC_RT_DLGINCLUDE:
+	case WRC_RT_PLUGPLAY:
+	case WRC_RT_VXD:
+	case WRC_RT_ANICURSOR:
+	case WRC_RT_ANIICON:
+		warning("Cannot be sure of resource type, using usertype settings");
+		return res_usr;
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	:
+ * Syntax	:
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+#define get_word(idx)	(*((WORD *)(&res->data[idx])))
+#define get_dword(idx)	(*((DWORD *)(&res->data[idx])))
+
+resource_t *read_res32(FILE *fp)
+{
+	static char wrong_format[] = "Wrong resfile format (32bit)";
+	DWORD ressize;
+	DWORD hdrsize;
+	DWORD totsize;
+	WORD memopt;
+	WORD language;
+	int err;
+	res_t *res;
+	resource_t *rsc;
+	resource_t *tail = NULL;
+	resource_t *list = NULL;
+	name_id_t *type = NULL;
+	name_id_t *name = NULL;
+	int idx;
+	enum res_e res_type;
+	user_t *usrres;
+
+	while(1)
+	{
+		/* Get headersize and resource size */
+		err = read_data(fp, sizeof(ressize), &ressize);
+		if(err < 0)
+			break;
+		else if(err > 0)
+			error(wrong_format);
+		err = read_data(fp, sizeof(hdrsize), &hdrsize);
+		if(err)
+			error(wrong_format);
+
+		/* Align sizes and compute total size */
+		totsize = hdrsize;
+		if(hdrsize & 3)
+		{
+			warning("Hu? .res header needed alignment (anything can happen now)");
+			totsize += 4 - (hdrsize & 3);
+		}
+		totsize += ressize;
+		if(ressize & 3)
+			totsize += 4 - (ressize & 3);
+
+		/* Read in entire data-block */
+		fseek(fp, -8, SEEK_CUR);
+		res = new_res();
+		if(res->allocsize < totsize)
+			grow_res(res, totsize - res->allocsize + 8);
+		err = read_data(fp, totsize, res->data);
+		if(err)
+			error(wrong_format);
+
+		res->dataidx = hdrsize;
+		res->size = hdrsize + ressize;
+
+		/* Analyse the content of the header */
+		idx = 8;
+		/* Get restype */
+		if(get_word(idx) == 0xffff)
+		{
+			idx += sizeof(WORD);
+			type = new_name_id();
+			type->type = name_ord;
+			type->name.i_name = get_word(idx);
+			idx += sizeof(WORD);
+		}
+		else if(get_word(idx) == 0)
+		{
+			error("ResType name has zero length (32 bit)");
+		}
+		else
+		{
+			int tag = idx;
+			string_t *str;
+			while(1)
+			{
+				idx += sizeof(WORD);
+				if(!get_word(idx))
+					break;
+			}
+			idx += sizeof(WORD);
+			str = new_string();
+			str->type = str_unicode;
+			str->size = (idx - tag) / 2;
+			str->str.wstr = (short *)xmalloc(idx-tag+2);
+			memcpy(str->str.wstr, &res->data[tag], idx-tag);
+			str->str.wstr[str->size] = 0;
+			type = new_name_id();
+			type->type = name_str;
+			type->name.s_name = str;
+		}
+		/* Get resname */
+		if(get_word(idx) == 0xffff)
+		{
+			idx += sizeof(WORD);
+			name = new_name_id();
+			name->type = name_ord;
+			name->name.i_name = get_word(idx);
+			idx += sizeof(WORD);
+		}
+		else if(get_word(idx) == 0)
+		{
+			error("ResName name has zero length (32 bit)");
+		}
+		else
+		{
+			int tag = idx;
+			string_t *str;
+			while(1)
+			{
+				idx += sizeof(WORD);
+				if(!get_word(idx))
+					break;
+			}
+			idx += sizeof(WORD);
+			str = new_string();
+			str->type = str_unicode;
+			str->size = (idx - tag) / 2;
+			str->str.wstr = (short *)xmalloc(idx-tag+2);
+			memcpy(str->str.wstr, &res->data[tag], idx-tag);
+			str->str.wstr[str->size] = 0;
+			name = new_name_id();
+			name->type = name_str;
+			name->name.s_name = str;
+		}
+
+		/* align */
+		if(idx & 0x3)
+			idx += 4 - (idx & 3);
+
+		idx += sizeof(DWORD);	/* Skip DataVersion */
+		memopt = get_word(idx);
+		idx += sizeof(WORD);
+		language = get_word(idx);
+
+		/* Build a resource_t list */
+		res_type = res_type_from_id(type);
+		if(res_type == res_usr)
+		{
+			/* User-type has custom ResType for .[s|h] generation */
+			usrres = new_user(type, NULL, new_int(memopt));
+		}
+		else
+			usrres = NULL;
+		rsc = new_resource(res_type,
+				   usrres,
+				   memopt,
+				   new_language(PRIMARYLANGID(language),
+						SUBLANGID(language)));
+		rsc->binres = res;
+		rsc->name = name;
+		rsc->c_name = make_c_name(get_c_typename(res_type), name, rsc->lan);
+		if(!list)
+		{
+			list = rsc;
+			tail = rsc;
+		}
+		else
+		{
+			rsc->prev = tail;
+			tail->next = rsc;
+			tail = rsc;
+		}
+	}
+	return list;
+}
+
+/*
+ *****************************************************************************
+ * Function	:
+ * Syntax	:
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+resource_t *read_res16(FILE *fp)
+{
+	internal_error(__FILE__, __LINE__, "Can't yet read 16 bit .res files");
+	return NULL;
+}
+
+/*
+ *****************************************************************************
+ * Function	: read_resfile
+ * Syntax	: resource_t *read_resfile(char *inname)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+resource_t *read_resfile(char *inname)
+{
+	FILE *fp;
+	struct resheader32 rh;
+	int is32bit;
+	resource_t *top;
+
+	fp = fopen(inname, "rb");
+	if(!fp)
+		error("Could not open inputfile %s", inname);
+
+	/* Determine 16 or 32 bit .res file */
+	if(fread(&rh, 1, sizeof(rh), fp) != sizeof(rh))
+		is32bit = 0;
+	else
+	{
+		if(!memcmp(&emptyheader, &rh, sizeof(rh)))
+			is32bit = 1;
+		else
+			is32bit = 0;
+	}
+
+	if(is32bit && !win32)
+		error("Cannot convert 32-bit .res-file into 16-bit resources (and will, hopefully never, implement it)");
+
+	if(!is32bit && win32)
+		error("Cannot (yet) convert 16-bit .res-file into 32-bit resources");
+
+	if(!is32bit)
+	{
+		fseek(fp, 0, SEEK_SET);
+		top = read_res16(fp);
+	}
+	else
+	{
+		top = read_res32(fp);
+	}
+
+	fclose(fp);
+
+	return top;
+}
diff --git a/tools/wrc/readres.h b/tools/wrc/readres.h
new file mode 100644
index 0000000..e87da51
--- /dev/null
+++ b/tools/wrc/readres.h
@@ -0,0 +1,17 @@
+/*
+ * Read binary resource prototypes
+ *
+ * Copyright 1998 Bertho A. Stultiens (BS)
+ *
+ */
+
+#ifndef __WRC_READRES_H
+#define __WRC_READRES_H
+
+#ifndef __WRC_WRCTYPES_H
+#include "wrctypes.h"
+#endif
+
+resource_t *read_resfile(char *inname);
+
+#endif
diff --git a/tools/wrc/utils.c b/tools/wrc/utils.c
new file mode 100644
index 0000000..fd2832f
--- /dev/null
+++ b/tools/wrc/utils.c
Binary files differ
diff --git a/tools/wrc/utils.h b/tools/wrc/utils.h
new file mode 100644
index 0000000..e16613a
--- /dev/null
+++ b/tools/wrc/utils.h
@@ -0,0 +1,40 @@
+/*
+ * Utility routines' prototypes etc.
+ *
+ * Copyright 1998 Bertho A. Stultiens (BS)
+ *
+ */
+
+#ifndef __WRC_UTILS_H
+#define __WRC_UTILS_H
+
+#ifndef __WRC_WRCTYPES_H
+#include "wrctypes.h"
+#endif
+
+#include <stddef.h>	/* size_t */
+
+void *xmalloc(size_t);
+void *xrealloc(void *, size_t);
+char *xstrdup(const char *str);
+
+int yyerror(const char *s, ...);
+int yywarning(const char *s, ...);
+void internal_error(const char *file, int line, const char *s, ...);
+void error(const char *s, ...);
+void warning(const char *s, ...);
+void chat(const char *s, ...);
+
+char *dup_basename(const char *name, const char *ext);
+int string_compare(const string_t *s1, const string_t *s2);
+int wstrlen(const short *s);
+short *wstrcpy(short *dst, const short *src);
+int wstricmp(const short *s1, const short *s2);
+char *dupwstr2cstr(const short *str);
+short *dupcstr2wstr(const char *str);
+
+#ifndef HAVE_STRICMP
+int stricmp(const char *s1, const char *s2);
+#endif
+
+#endif
diff --git a/tools/wrc/wrc.c b/tools/wrc/wrc.c
new file mode 100644
index 0000000..910cf14
--- /dev/null
+++ b/tools/wrc/wrc.c
@@ -0,0 +1,492 @@
+/*
+ *
+ * Copyright  Martin von Loewis, 1994
+ * Copyrignt 1998 Bertho A. Stultiens (BS)
+ *
+ * 21-May-1998 BS	- Removed the CPP option. Its internal now.
+ *			- Added implementations for defines and includes
+ *			  on the commandline.
+ *
+ * 30-Apr-1998 BS	- The options now contain nearly the entire alphabet.
+ *			  Seems to be a sign for too much freedom. I implemeted
+ *			  most of them as a user choice possibility for things
+ *			  that I do not know what to put there by default.
+ *			- -l and -L options are now known as -t and -T.
+ *
+ * 23-Apr-1998 BS	- Finally gave up on backward compatibility on the
+ *			  commandline (after a blessing from the newsgroup).
+ *			  So, I changed the lot.
+ *
+ * 17-Apr-1998 BS	- Added many new command-line options but took care
+ *			  that it would not break old scripts (sigh).
+ *
+ * 16-Apr-1998 BS	- There is not much left of the original source...
+ *			  I had to rewrite most of it because the parser
+ *			  changed completely with all the types etc..
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <config.h>
+#include "wrc.h"
+#include "utils.h"
+#include "writeres.h"
+#include "readres.h"
+#include "dumpres.h"
+#include "genres.h"
+#include "newstruc.h"
+#include "preproc.h"
+#include "parser.h"
+
+char usage[] = "Usage: wrc [options...] [infile[.rc|.res]]\n"
+	"   -a n        Alignment of resource (win16 only, default is 4)\n"
+	"   -b          Create a C array from a binary .res file\n"
+	"   -c          Add 'const' prefix to C constants\n"
+	"   -C cp       Set the resource's codepage to cp (default is 0)\n"
+	"   -d n        Set debug level to 'n'\n"
+	"   -D id[=val] Define preprocessor identifier id=val\n"
+	"   -e          Disable recognition of win32 keywords in 16bit compile\n"
+	"   -g          Add symbols to the global c namespace\n"
+	"   -h          Also generate a .h file\n"
+	"   -H file     Same as -h but written to file\n"
+	"   -I path     Set include search dir to path (multiple -I allowed)\n"
+	"   -l lan      Set default language to lan (default is neutral {0})\n"
+	"   -n          Do not generate .s file\n"
+	"   -o file     Output to file (default is infile.[res|s|h]\n"
+	"   -p prefix   Give a prefix for the generated names\n"
+	"   -r          Create binary .res file (compile only)\n"
+	"   -s          Add structure with win32/16 (PE/NE) resource directory\n"
+	"   -t          Generate indirect loadable resource tables\n"
+	"   -T          Generate only indirect loadable resources tables\n"
+	"   -V          Print version end exit\n"
+	"   -w 16|32    Select win16 or win32 output (default is win32)\n"
+	"   -W          Enable pedantic warnings\n"
+	"Input is taken from stdin if no sourcefile specified.\n"
+	"Debug level 'n' is a bitmask with following meaning:\n"
+	"    * 0x01 Tell which resource is parsed (verbose mode)\n"
+	"    * 0x02 Dump internal structures\n"
+	"    * 0x04 Create a parser trace (yydebug=1)\n"
+	"The -o option only applies to the final destination file, which is\n"
+	"in case of normal compile a .s file. You must use the '-H header.h'\n"
+	"option to override the header-filename.\n"
+	"If no input filename is given and the output name is not overridden\n"
+	"with -o and/or -H, then the output is written to \"wrc.tab.[sh]\"\n"
+	;
+
+char version_string[] = "Wine Resource Compiler Version " WRC_FULLVERSION "\n"
+			"Copyright 1998 Bertho A. Stultiens\n"
+			"          1994 Martin von Loewis\n";
+
+/*
+ * Default prefix for resource names used in the C array.
+ * Option '-p name' sets it to 'name'
+ */
+char *prefix = "_Resource";
+
+/*
+ * Set if compiling in 32bit mode (default).
+ */
+int win32 = 1;
+
+/*
+ * Set when generated C variables should be prefixed with 'const'
+ */
+int constant = 0;
+
+/*
+ * Create a .res file from the source and exit (-r option).
+ * The compiler actually always creates this file, and then
+ * converts it into whatever is requested. The compiler just
+ * stops after the res-file when create_res is set.
+ */
+int create_res = 0;
+
+/*
+ * debuglevel == DEBUGLEVEL_NONE	Don't bother
+ * debuglevel & DEBUGLEVEL_CHAT		Say whats done
+ * debuglevel & DEBUGLEVEL_DUMP		Dump internal structures
+ * debuglevel & DEBUGLEVEL_TRACE	Create parser trace
+ */
+int debuglevel = DEBUGLEVEL_NONE;
+
+/*
+ * Recognize win32 keywords if set (-w 32 enforces this),
+ * otherwise set with -e option.
+ */
+int extensions = 1;
+
+/*
+ * Set when creating C array from .res file (-b option).
+ */
+int binary = 0;
+
+/*
+ * Set when an additional C-header is to be created in compile (-h option).
+ */
+int create_header = 0;
+
+/*
+ * Set when the NE/PE resource directory should be dumped into
+ * the output file.
+ */
+int create_dir = 0;
+
+/*
+ * Set when all symbols should be added to the global namespace (-g option)
+ */
+int global = 0;
+
+/*
+ * Set when indirect loadable resource tables should be created (-t)
+ */
+int indirect = 0;
+
+/*
+ * Set when _only_ indirect loadable resource tables should be created (-T)
+ */
+int indirect_only = 0;
+
+/*
+ * NE segment resource aligment (-a option)
+ */
+int alignment = 4;
+int alignment_pwr;
+
+/*
+ * Cleared when the assembly file must be suppressed (-n option)
+ */
+int create_s = 1;
+
+/*
+ * Language setting for resources (-l option)
+ */
+language_t *currentlanguage = NULL;
+
+/*
+ * The codepage to write in win32 PE resource segment (-C option)
+ */
+DWORD codepage = 0;
+
+/*
+ * Set when extra warnings should be generated (-W option)
+ */
+int pedantic = 0;
+
+char *output_name;		/* The name given by the -o option */
+char *input_name;		/* The name given on the command-line */
+char *header_name;		/* The name given by the -H option */
+
+char *cmdline;			/* The entire commandline */
+
+resource_t *resource_top;	/* The top of the parsed resources */
+
+int getopt (int argc, char *const *argv, const char *optstring);
+
+int main(int argc,char *argv[])
+{
+	extern char* optarg;
+	extern int   optind;
+	int optc;
+	int lose = 0;
+	int ret;
+	int a;
+	int i;
+	int cmdlen;
+
+	/* First rebuild the commandline to put in destination */
+	/* Could be done through env[], but not all OS-es support it */
+	cmdlen = 4; /* for "wrc " */
+	for(i = 1; i < argc; i++)
+		cmdlen += strlen(argv[i]) + 1;
+	cmdline = (char *)xmalloc(cmdlen);
+	strcpy(cmdline, "wrc ");
+	for(i = 1; i < argc; i++)
+	{
+		strcat(cmdline, argv[i]);
+		if(i < argc-1)
+			strcat(cmdline, " ");
+	}
+
+	while((optc = getopt(argc, argv, "a:bcC:d:D:eghH:I:l:no:p:rstTVw:W")) != EOF)
+	{
+		switch(optc)
+		{
+		case 'a':
+			alignment = atoi(optarg);
+			break;
+		case 'b':
+			binary = 1;
+			break;
+		case 'c':
+			constant = 1;
+			break;
+		case 'C':
+			codepage = strtol(optarg, NULL, 0);
+			break;
+		case 'd':
+			debuglevel = strtol(optarg, NULL, 0);
+			break;
+		case 'D':
+			add_cmdline_define(optarg);
+			break;
+		case 'e':
+			extensions = 0;
+			break;
+		case 'g':
+			global = 1;
+			break;
+		case 'H':
+			header_name = strdup(optarg);
+			/* Fall through */
+		case 'h':
+			create_header = 1;
+			break;
+		case 'I':
+			add_include_path(optarg);
+			break;
+		case 'l':
+			{
+				int lan;
+				lan = strtol(optarg, NULL, 0);
+				currentlanguage = new_language(PRIMARYLANGID(lan), SUBLANGID(lan));
+			}
+			break;
+		case 'n':
+			create_s = 0;
+			break;
+		case 'o':
+			output_name = strdup(optarg);
+			break;
+		case 'p':
+			prefix = strdup(optarg);
+			break;
+		case 'r':
+			create_res = 1;
+			break;
+		case 's':
+			create_dir = 1;
+			break;
+		case 'T':
+			indirect_only = 1;
+			/* Fall through */
+		case 't':
+			indirect = 1;
+			break;
+		case 'V':
+			printf(version_string);
+			exit(0);
+			break;
+		case 'w':
+			if(!strcmp(optarg, "16"))
+				win32 = 0;
+			else if(!strcmp(optarg, "32"))
+				win32 = 1;
+			else
+				lose++;
+			break;
+		case 'W':
+			pedantic = 1;
+			break;
+		default:
+			lose++;
+			break;
+		}
+	}
+
+	if(lose)
+	{
+		fprintf(stderr, usage);
+		return 1;
+	}
+
+	/* Check the command line options for invalid combinations */
+	if(win32)
+	{
+		if(!extensions)
+		{
+			warning("Option -e ignored with 32bit compile\n");
+			extensions = 1;
+		}
+	}
+
+	if(create_res)
+	{
+		if(constant)
+		{
+			warning("Option -c ignored with compile to .res\n");
+			constant = 0;
+		}
+
+		if(create_header)
+		{
+			warning("Option -[h|H] ignored with compile to .res\n");
+			create_header = 0;
+		}
+
+		if(indirect)
+		{
+			warning("Option -l ignored with compile to .res\n");
+			indirect = 0;
+		}
+
+		if(indirect_only)
+		{
+			warning("Option -L ignored with compile to .res\n");
+			indirect_only = 0;
+		}
+
+		if(global)
+		{
+			warning("Option -g ignored with compile to .res\n");
+			global = 0;
+		}
+
+		if(create_dir)
+		{
+			error("Option -r and -s cannot be used together\n");
+		}
+
+		if(binary)
+		{
+			error("Option -r and -b cannot be used together\n");
+		}
+	}
+
+	/* Set alignment power */
+	a = alignment;
+	for(alignment_pwr = 0; alignment_pwr < 10 && a > 1; alignment_pwr++)
+	{
+		a >>= 1;
+	}
+	if(a != 1)
+	{
+		error("Alignment must be between 1 and 1024");
+	}
+	if((1 << alignment_pwr) != alignment)
+	{
+		error("Alignment must be a power of 2");
+	}
+
+	/* Kill io buffering when some kind of debuglevel is enabled */
+	if(debuglevel)
+	{
+		setbuf(stdout,0);
+		setbuf(stderr,0);
+	}
+
+	yydebug = debuglevel & DEBUGLEVEL_TRACE ? 1 : 0;
+
+	/* Set the default defined stuff */
+	add_cmdline_define("RC_INVOKED=1");
+	add_cmdline_define("__WRC__=1");
+	if(win32)
+	{
+		add_cmdline_define("__WIN32__=1");
+		add_cmdline_define("__FLAT__=1");
+	}
+
+	/* Check if the user set a language, else set default */
+	if(!currentlanguage)
+		currentlanguage = new_language(0, 0);
+
+	/* Check for input file on command-line */
+	if(optind < argc)
+	{
+		input_name = argv[optind];
+		yyin = fopen(input_name, "rb");
+		if(!yyin)
+		{
+			error("Could not open %s\n", input_name);
+		}
+	}
+	else
+	{
+		yyin = stdin;
+	}
+
+	if(binary && !input_name)
+	{
+		error("Binary mode requires .res file as input");
+	}
+
+	if(!output_name)
+	{
+		output_name = dup_basename(input_name, binary ? ".res" : ".rc");
+		strcat(output_name, create_res ? ".res" : ".s");
+	}
+
+	if(!header_name && !create_res)
+	{
+		header_name = dup_basename(input_name, binary ? ".res" : ".rc");
+		strcat(header_name, ".h");
+	}
+
+	if(!binary)
+	{
+		/* Go from .rc to .res or .s */
+		chat("Starting parse");
+		ret = yyparse();
+
+		if(input_name)
+			fclose(yyin);
+
+		if(ret)
+		{
+			/* Error during parse */
+			exit(1);
+		}
+
+		if(debuglevel & DEBUGLEVEL_DUMP)
+			dump_resources(resource_top);
+
+		/* Convert the internal lists to binary data */
+		resources2res(resource_top);
+
+		if(create_res)
+		{
+			chat("Writing .res-file");
+			write_resfile(output_name, resource_top);
+		}
+		else
+		{
+			if(create_s)
+			{
+				chat("Writing .s-file");
+				write_s_file(output_name, resource_top);
+			}
+			if(create_header)
+			{
+				chat("Writing .h-file");
+				write_h_file(header_name, resource_top);
+			}
+		}
+
+	}
+	else
+	{
+		/* Go from .res to .s */
+		chat("Reading .res-file");
+		resource_top = read_resfile(input_name);
+		if(create_s)
+		{
+			chat("Writing .s-file");
+			write_s_file(output_name, resource_top);
+		}
+		if(create_header)
+		{
+			chat("Writing .h-file");
+			write_h_file(header_name, resource_top);
+		}
+	}
+
+	return 0;
+}
+
+
+
+
diff --git a/tools/wrc/wrc.doc b/tools/wrc/wrc.doc
new file mode 100644
index 0000000..94846aa
--- /dev/null
+++ b/tools/wrc/wrc.doc
@@ -0,0 +1,174 @@
+
+
+/*****************************************************************************\
+ * Win32 Resource files grammar:
+ *
+ * Top level keywords/resource items:
+ *	nameID ACCELERATOR
+ *	[CHARACTERISTICS dword]
+ *	[LANGUAGE language, sublanguage]
+ *	[VERSION dword]
+ *	BEGIN
+ *		event, IDvalue [, type] [options]
+ *		...
+ *	END
+ *-------------
+ *	nameID BITMAP [loadmem] filename
+ *-------------
+ *	nameID BITMAP [loadmem]
+ *	BEGIN
+ *		rawdata
+ *	END
+ *-------------
+ *	nameID CURSOR [loadmem] filename
+ *-------------
+ *	nameID CURSOR [loadmem]
+ *	BEGIN
+ *		rawdata
+ *	END
+ *-------------
+ *	nameID DIALOG [loadmem] [EXSTYLE=extended-styles] x, y, width, height
+ *	[CAPTION "text"]
+ *	[CHARACTERISTICS dword]
+ *	[CLASS class]
+ *	[EXSTYLE=extended-styles]
+ *	[FONT pointsize, face]
+ *	[LANGUAGE language, sublanguage]
+ *	[MENU menuname]
+ *	[STYLE styles]
+ *	[VERSION dword]
+ *	BEGIN
+ *		[controls]
+ *	END
+ *-------------
+ *	nameID DIALOGEX [loadmem] x, y, width, height [, helpID]
+ *	[CAPTION "text"]
+ *	[CHARACTERISTICS dword]
+ *	[CLASS class]
+ *	[EXSTYLE=extended-styles]
+ *	[FONT pointsize, face, weight, italic]
+ *	[LANGUAGE language, sublanguage]
+ *	[MENU menuname]
+ *	[STYLE styles]
+ *	[VERSION dword]
+ *	BEGIN
+ *		[controls]
+ *	END
+ *-------------
+ *	nameID FONT [loadmem] filename
+ *-------------
+ *	nameID ICON [loadmem] filename
+ *-------------
+ *	nameID ICON [loadmem]
+ *	BEGIN
+ *		rawdata
+ *	END
+ *-------------
+ *	LANGUAGE languageID, sublanguageID
+ *-------------
+ *	nameID MENU [loadmem]
+ *	[CHARACTERISTICS dword]
+ *	[LANGUAGE language, sublanguage]
+ *	[VERSION dword]
+ *	BEGIN
+ *		[menuitems]
+ *	END
+ *-------------
+ *	nameID MENUEX [loadmem]
+ *	[CHARACTERISTICS dword]
+ *	[LANGUAGE language, sublanguage]
+ *	[VERSION dword]
+ *	BEGIN
+ *		[menuexitems]
+ *	END
+ *-------------
+ *	nameID MESSAGETABLE [loadmem] filename
+ *-------------
+ *	nameID RCDATA [loadmem]
+ *	[CHARACTERISTICS dword]
+ *	[LANGUAGE language, sublanguage]
+ *	[VERSION dword]
+ *	BEGIN
+ *		[raw-data]
+ *	END
+ *-------------
+ *	STRINGTABLE [loadmem]
+ *	[CHARACTERISTICS dword]
+ *	[LANGUAGE language, sublanguage]
+ *	[VERSION dword]
+ *	BEGIN
+ *		[stringID, "text"]
+ *		...
+ *	END
+ *-------------
+ *	versionID VERSIONINFO
+ *	FILEVERSION	maj1, maj2, min1, min2
+ *	PRODUCTVERSION	maj1, maj2, min1, min2
+ *	FILEFLAGSMASK	(VS_FFI_FILEFLAGMASK)
+ *	FILEOS		(VOS_*)
+ *	FILETYPE	(VFT_*)
+ *	FILEFLAGS	(VS_FF_*)
+ *	FILESUBTYPE	(VFT2_*)
+ *	BEGIN
+ *		BLOCK "StringFileInfo"
+ *		BEGIN
+ *			BLOCK "language-charset"
+ *			BEGIN
+ *				[VALUE "Comments", "yep\0"]
+ *				VALUE "CompanyName", "Wine Developer Team\0"
+ *				VALUE "FileDescription", "Resource compiler\0"
+ *				VALUE "FileVersion", "0.01 alpha\0"
+ *				VALUE "InternalName", "winerc\0"
+ *				[VALUE "LegalCopyright", "Copyright (c) B.A. Stultiens 1998\0"]
+ *				[VALUE "LegalTrademarks", "...\0"]
+ *				VALUE "OriginalFilename", "winerc\0"
+ *				[VALUE "PrivateBuild", "Yes always!\0"
+ *				VALUE "ProductName", "Wine\0"
+ *				VALUE "ProductVersion", "0.01 alpha\0"
+ *				[VALUE "SpecialBuild", "No never! Well, maybe.\0"
+ *			END
+ *		END
+ *		BLOCK "VarFileInfo"
+ *		BEGIN
+ *			VALUE "Translation", languageID, charsetID
+ *		END
+ *	END
+ *-------------
+ *	nameID typeID [loadmem] filename
+ *-------------
+ *	nameID typeID [loadmem]
+ *	BEGIN
+ *		[raw-data]
+ *	END
+ *
+ *****************************************************************************
+ *
+ * Dialog controls:
+ *	CONTROL		text, ID, class, style, x, y, width, height [, exstyle]
+ *
+ *	LTEXT		text, ID, x, y, width, height [, style [, exstyle]]
+ *	CTEXT		text, ID, x, y, width, height [, style [, exstyle]]
+ *	RTEXT		text, ID, x, y, width, height [, style [, exstyle]]
+ *
+ *	ICON		text, ID, x, y, [width, height , style [, exstyle]]
+ *
+ *	EDITTEXT	ID, x, y, width, height [, style [, exstyle]]
+ *
+ *	AUTO3STATE	text, ID, x, y, width, height [, style [, exstyle]]
+ *	AUTOCHECKBOX	text, ID, x, y, width, height [, style [, exstyle]]
+ *	AUTORADIOBUTTON	text, ID, x, y, width, height [, style [, exstyle]]
+ *	STATE3		text, ID, x, y, width, height [, style [, exstyle]]
+ *	CHECKBOX	text, ID, x, y, width, height [, style [, exstyle]]
+ *	PUSHBUTTON	text, ID, x, y, width, height [, style [, exstyle]]
+ *	RADIOBUTTON	text, ID, x, y, width, height [, style [, exstyle]]
+ *	DEFPUSHBUTTON	text, ID, x, y, width, height [, style [, exstyle]]
+ *
+ *	COMBOBOX	text, ID, x, y, width, height [, style [, exstyle]]
+ *	GROUPBOX	text, ID, x, y, width, height [, style [, exstyle]]
+ *	LISTBOX		text, ID, x, y, width, height [, style [, exstyle]]
+ *	SCROLLBAR	text, ID, x, y, width, height [, style [, exstyle]]
+ *
+ * FIXME: This is documented, but I don't know the BS_PUSHBOX style
+ *	PUSHBOX		text, ID, x, y, width, height [, style [, exstyle]]
+\*****************************************************************************/
+
diff --git a/tools/wrc/wrc.h b/tools/wrc/wrc.h
new file mode 100644
index 0000000..13ad29e
--- /dev/null
+++ b/tools/wrc/wrc.h
@@ -0,0 +1,89 @@
+/*
+ * Main definitions and externals
+ *
+ * Copyright 1998 Bertho A. Stultiens (BS)
+ *
+ */
+
+#ifndef __WRC_WRC_H
+#define __WRC_WRC_H
+
+#ifndef __WRC_WRCTYPES_H
+#include "wrctypes.h"
+#endif
+
+#define WRC_VERSION	"1.0.0"
+#define WRC_RELEASEDATE	"(28-May-1998)"
+#define WRC_FULLVERSION WRC_VERSION " " WRC_RELEASEDATE
+
+/* Only used in heavy debugging sessions */
+#define HEAPCHECK()
+
+/* Memory/load flags */
+#define WRC_MO_MOVEABLE		0x0010
+#define WRC_MO_PURE		0x0020
+#define WRC_MO_PRELOAD		0x0040
+#define WRC_MO_DISCARDABLE	0x1000
+
+/* Resource type IDs */
+#define WRC_RT_CURSOR		(1)
+#define WRC_RT_BITMAP		(2)
+#define WRC_RT_ICON		(3)
+#define WRC_RT_MENU		(4)
+#define WRC_RT_DIALOG		(5)
+#define WRC_RT_STRING		(6)
+#define WRC_RT_FONTDIR		(7)
+#define WRC_RT_FONT		(8)
+#define WRC_RT_ACCELERATOR	(9)
+#define WRC_RT_RCDATA		(10)
+#define WRC_RT_MESSAGETABLE	(11)
+#define WRC_RT_GROUP_CURSOR	(12)
+#define WRC_RT_GROUP_ICON	(14)
+#define WRC_RT_VERSION		(16)
+#define WRC_RT_DLGINCLUDE	(17)
+#define WRC_RT_PLUGPLAY		(19)
+#define WRC_RT_VXD		(20)
+#define WRC_RT_ANICURSOR	(21)
+#define WRC_RT_ANIICON		(22)
+
+/* Default class type IDs */
+#define CT_BUTTON	0x80
+#define CT_EDIT		0x81
+#define CT_STATIC 	0x82
+#define CT_LISTBOX	0x83
+#define CT_SCROLLBAR	0x84
+#define CT_COMBOBOX	0x85
+
+/* From wrc.c */
+extern int debuglevel;
+#define DEBUGLEVEL_NONE		0x0000
+#define DEBUGLEVEL_CHAT		0x0001
+#define DEBUGLEVEL_DUMP		0x0002
+#define DEBUGLEVEL_TRACE	0x0004
+
+extern int win32;
+extern int constant;
+extern int create_res;
+extern int extensions;
+extern int binary;
+extern int create_header;
+extern int create_dir;
+extern int global;
+extern int indirect;
+extern int indirect_only;
+extern int alignment;
+extern int alignment_pwr;
+extern int create_s;
+extern DWORD codepage;
+extern int pedantic;
+
+extern char *prefix;
+extern char *output_name;
+extern char *input_name;
+extern char *header_name;
+extern char *cmdline;			
+
+extern resource_t *resource_top;
+extern language_t *currentlanguage;
+
+#endif
diff --git a/tools/wrc/wrctypes.h b/tools/wrc/wrctypes.h
new file mode 100644
index 0000000..00075de
--- /dev/null
+++ b/tools/wrc/wrctypes.h
@@ -0,0 +1,467 @@
+/*
+ * General type definitions
+ *
+ * Copyright 1998 Bertho A. Stultiens (BS)
+ *
+ */
+
+#ifndef __WRC_WRCTYPES_H
+#define __WRC_WRCTYPES_H
+
+/* First is MS style, second wine style */
+#if !defined(_INC_WINDOWS) && !defined(__WINE_WINDOWS_H)
+#include "windows.h"
+#endif
+
+#ifndef MAKELANGID
+#include "winnls.h"
+#endif
+
+#ifndef VS_FFI_SIGNATURE
+#include "ver.h"
+#endif
+
+
+/* Binary resource structure */
+#define RES_BLOCKSIZE	512
+
+typedef struct res {
+	int	allocsize;	/* Allocated datablock size */
+	int	size;		/* Actual size of data */
+	int	dataidx;	/* Tag behind the resource-header */
+	char	*data;
+} res_t;
+
+/* Resource strings are slightly more complex because they include '\0' */
+enum str_e {str_char, str_unicode};
+
+typedef struct string {
+	int 		size;
+	enum str_e	type;
+	union {
+		char *cstr;
+		short *wstr;
+	} str;
+} string_t;
+
+/* Resources are identified either by name or by number */
+enum name_e {name_str, name_ord};
+
+typedef struct name_id {
+	union {
+		string_t *s_name;
+		int	i_name;
+	} name;
+	enum name_e type;
+} name_id_t;
+
+/* Language definitions */
+typedef struct language {
+	int	id;
+	int	sub;
+} language_t;
+
+typedef DWORD characts_t;
+typedef DWORD version_t;
+
+typedef struct lvc {
+	language_t	*language;
+	version_t	*version;
+	characts_t	*characts;
+} lvc_t;
+
+typedef struct font_id {
+	string_t	*name;
+	int		size;
+	int		weight;
+	int		italic;
+} font_id_t;
+
+/* resource types */
+/* These are in the same order (and ordinal) as the RT_xxx
+ * defines. This is _required_.
+ * I rolled my own numbers for the win32 extension that are
+ * documented, but generate either old RT_xxx numbers, or
+ * don't have an ordinal associated (user type).
+ * I don't know any specs for those noted such, for that matter,
+ * I don't even know whether they can be generated other than by
+ * using a user-type resource.
+ */
+enum res_e {
+	res_0 = 0,
+	res_cur,
+	res_ico,
+	res_bmp,
+	res_men,
+	res_dlg,
+	res_stt,
+	res_fntdir,
+	res_fnt,
+	res_acc,
+	res_rdt,
+	res_msg,
+	res_curg,
+	res_13,		/* Hm, wonder why its not used... */
+	res_icog,
+	res_15,
+	res_ver,
+	res_dlginc,	/* Not implemented, no layout available */
+	res_18,
+	res_pnp,	/* Not implemented, no layout available */
+	res_vxd,	/* Not implemented, no layout available */
+	res_anicur,	/* Not implemented, no layout available */
+	res_aniico,	/* Not implemented, no layout available */
+
+	res_menex = 256 + 4,
+	res_dlgex,
+	res_usr,
+};
+
+/* Raw bytes in a row... */
+typedef struct raw_data {
+	int	size;
+	char	*data;
+} raw_data_t;
+
+/* Dialog structures */
+typedef struct control {
+	struct control	*next;		/* List of controls */
+	struct control	*prev;
+	name_id_t	*ctlclass;	/* ControlClass */
+	string_t	*title;		/* Title of control */
+	int		id;
+	int		x;		/* Position */
+	int		y;
+	int		width;		/* Size */
+	int		height;
+	DWORD		style;		/* Style */
+	DWORD		exstyle;
+	DWORD		helpid;		/* EX: */
+	int		gotstyle;	/* Used to determine whether the default */
+	int		gotexstyle;	/* styles must be set */
+	int		gothelpid;
+	raw_data_t	*extra;		/* EX: number of extra bytes in resource */
+} control_t;
+
+typedef struct dialog {
+	DWORD		memopt;
+	int		x;		/* Position */
+	int		y;
+	int		width;		/* Size */
+	int		height;
+	DWORD		style;		/* Style */
+	DWORD		exstyle;
+	int		gotstyle;	/* Used to determine whether the default */
+	int		gotexstyle;	/* styles must be set */
+	name_id_t	*menu;
+	name_id_t	*dlgclass;
+	string_t	*title;
+	font_id_t	*font;
+	lvc_t		lvc;
+	control_t	*controls;
+} dialog_t;
+
+/* DialogEx structures */
+typedef struct dialogex {
+	DWORD		memopt;
+	int		x;		/* Position */
+	int		y;
+	int		width;		/* Size */
+	int		height;
+	DWORD		style;		/* Style */
+	DWORD		exstyle;
+	DWORD		helpid;		/* EX: */
+	int		gotstyle;	/* Used to determine whether the default */
+	int		gotexstyle;	/* styles must be set */
+	int		gothelpid;
+	name_id_t	*menu;
+	name_id_t	*dlgclass;
+	string_t	*title;
+	font_id_t	*font;
+	lvc_t		lvc;
+	control_t	*controls;
+} dialogex_t;
+
+/* Menu structures */
+typedef struct menu_item {
+	struct menu_item *next;
+	struct menu_item *prev;
+	struct menu_item *popup;
+	int		id;
+	DWORD		state;
+	string_t	*name;
+} menu_item_t;
+
+typedef struct menu {
+	DWORD		memopt;
+	lvc_t		lvc;
+	menu_item_t	*items;
+} menu_t;
+
+/* MenuEx structures */
+typedef struct menuex_item {
+	struct menuex_item *next;
+	struct menuex_item *prev;
+	struct menuex_item *popup;
+	int		id;
+	DWORD		type;
+	DWORD		state;
+	int		helpid;
+	string_t	*name;
+	int		gotid;
+	int		gottype;
+	int		gotstate;
+	int		gothelpid;
+} menuex_item_t;
+
+typedef struct menuex {
+	DWORD		memopt;
+	lvc_t		lvc;
+	menuex_item_t	*items;
+} menuex_t;
+
+typedef struct itemex_opt
+{
+	int	id;
+	DWORD	type;
+	DWORD	state;
+	int	helpid;
+	int	gotid;
+	int	gottype;
+	int	gotstate;
+	int	gothelpid;
+} itemex_opt_t;
+
+/* RC structures for types read from file or supplied binary */
+typedef struct font {
+	DWORD		memopt;
+	raw_data_t	*data;
+} font_t;
+
+typedef struct icon_dir_entry {
+    BYTE  width;	/* From the SKD doc. */
+    BYTE  height;
+    BYTE  nclr;
+    BYTE  reserved;
+    WORD  planes;
+    WORD  bits;
+    DWORD ressize;
+    DWORD offset;
+} icon_dir_entry_t;
+
+typedef struct icon {
+	struct icon	*next;
+	struct icon	*prev;
+	int		id;	/* Unique icon id within resource file */
+	int		width;	/* Field from the IconDirEntry */
+	int		height;
+	int		nclr;
+	int		planes;
+	int		bits;
+	raw_data_t	*data;
+} icon_t;
+
+typedef struct icon_group {
+	DWORD		memopt;
+	icon_t		*iconlist;
+	int		nicon;
+} icon_group_t;
+
+typedef struct cursor_dir_entry {
+    BYTE  width;	/* From the SKD doc. */
+    BYTE  height;
+    BYTE  nclr;
+    BYTE  reserved;
+    WORD  xhot;
+    WORD  yhot;
+    DWORD ressize;
+    DWORD offset;
+} cursor_dir_entry_t;
+
+typedef struct cursor {
+	struct cursor	*next;
+	struct cursor	*prev;
+	int		id;	/* Unique icon id within resource file */
+	int		width;	/* Field from the CursorDirEntry */
+	int		height;
+	int		nclr;
+	int		planes;
+	int		bits;
+	int		xhot;
+	int		yhot;
+	raw_data_t	*data;
+} cursor_t;
+
+typedef struct cursor_group {
+	DWORD		memopt;
+	cursor_t	*cursorlist;
+	int		ncursor;
+} cursor_group_t;
+
+typedef struct bitmap {
+	DWORD		memopt;
+	raw_data_t	*data;
+} bitmap_t;
+
+typedef struct rcdata {
+	DWORD		memopt;
+	lvc_t		lvc;
+	raw_data_t	*data;
+} rcdata_t;
+
+typedef struct user {
+	DWORD		memopt;
+	name_id_t	*type;
+	raw_data_t	*data;
+} user_t;
+
+typedef struct messagetable {
+	raw_data_t	*data;
+} messagetable_t;
+
+/* StringTable structures */
+typedef struct stt_entry {
+	string_t		*str;
+	int			id;
+	DWORD			memopt;
+	characts_t		*characts;
+	version_t		*version;
+} stt_entry_t;
+
+typedef struct stringtable {
+	struct stringtable	*next;
+	struct stringtable	*prev;
+	DWORD			memopt;
+	lvc_t			lvc;
+	int			idbase;
+	int			nentries;
+	stt_entry_t		*entries;
+} stringtable_t;
+
+/* VersionInfo structures */
+enum ver_val_e {val_str, val_words, val_block};
+
+struct ver_block;	/* Forward ref */
+
+typedef struct ver_words {
+	WORD	*words;
+	int	nwords;
+} ver_words_t;
+
+typedef struct ver_value {
+	struct ver_value	*next;
+	struct ver_value	*prev;
+	string_t		*key;
+	union {
+		string_t		*str;
+		ver_words_t		*words;
+		struct ver_block	*block;
+	} value;
+	enum ver_val_e		type;
+} ver_value_t;
+
+typedef struct ver_block {
+	struct ver_block	*next;
+	struct ver_block	*prev;
+	string_t		*name;
+	ver_value_t		*values;
+} ver_block_t;
+
+typedef struct versioninfo {
+	int	filever_maj1;
+	int	filever_maj2;
+	int	filever_min1;
+	int	filever_min2;
+	int	prodver_maj1;
+	int	prodver_maj2;
+	int	prodver_min1;
+	int	prodver_min2;
+	int	fileos;
+	int	fileflags;
+	int	fileflagsmask;
+	int	filetype;
+	int	filesubtype;
+	struct {
+		int fv:1;
+		int pv:1;
+		int fo:1;
+		int ff:1;
+		int ffm:1;
+		int ft:1;
+		int fst:1;
+	} gotit;
+	ver_block_t	*blocks;
+} versioninfo_t;
+
+/* Accelerator structures */
+#define WRC_AF_VIRTKEY	0x0001
+#define WRC_AF_NOINVERT	0x0002
+#define WRC_AF_SHIFT	0x0004
+#define WRC_AF_CONTROL	0x0008
+#define WRC_AF_ALT	0x0010
+#define WRC_AF_ASCII	0x4000
+
+typedef struct event {
+	struct event	*next;
+	struct event	*prev;
+	int		flags;
+	int		key;
+	int		id;
+} event_t;
+
+typedef struct accelerator {
+	DWORD		memopt;
+	lvc_t		lvc;
+	event_t		*events;
+} accelerator_t;
+
+/* A top-level resource node */
+typedef struct resource {
+	struct resource	*next;
+	struct resource *prev;
+	enum res_e	type;
+	name_id_t	*name;	/* resource's name */
+	language_t	*lan;	/* Only used as a sorting key and c-name creation*/
+	union {
+		accelerator_t	*acc;
+		bitmap_t	*bmp;
+		cursor_t	*cur;
+		cursor_group_t	*curg;
+		dialog_t	*dlg;
+		dialogex_t	*dlgex;
+		font_t		*fnt;
+		icon_t		*ico;
+		icon_group_t	*icog;
+		menu_t		*men;
+		menuex_t	*menex;
+		messagetable_t	*msg;
+		rcdata_t	*rdt;
+		stringtable_t	*stt;
+		user_t		*usr;
+		versioninfo_t	*ver;
+		void		*overlay; /* To catch all types at once... */
+	} res;
+	res_t		*binres;	/* To binary converted resource */
+	char		*c_name;	/* BaseName in output */
+	DWORD		memopt;
+} resource_t;
+
+/* Resource count */
+typedef struct res32_count {
+	int			count;
+	resource_t		**rsc;
+} res32_count_t;
+
+typedef struct res_count {
+	name_id_t		type;
+	int			count;		/* win16 mode */
+	resource_t		**rscarray;
+	int			count32;
+	res32_count_t		*rsc32array;	/* win32 mode */
+	int			n_id_entries;
+	int			n_name_entries;
+} res_count_t;
+
+#endif
+
+
diff --git a/tools/wrc/writeres.c b/tools/wrc/writeres.c
new file mode 100644
index 0000000..18084f0
--- /dev/null
+++ b/tools/wrc/writeres.c
@@ -0,0 +1,1134 @@
+/*
+ * Write .res, .s and .h file(s) from a resource-tree
+ *
+ * Copyright 1998 Bertho A. Stultiens
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+
+#include <config.h>
+#include "wrc.h"
+#include "writeres.h"
+#include "genres.h"
+#include "newstruc.h"
+#include "utils.h"
+
+char s_file_head_str[] =
+	"#\n"
+	"# This file is generated with wrc version " WRC_FULLVERSION ". Do not edit!\n"
+	"# Source : %s\n"
+	"# Cmdline: %s\n"
+	"# Date   : %s"
+	"#\n\n"
+	"\t.data\n\n"
+	;
+
+char s_file_tail_str[] =
+	"# <eof>\n\n"
+	;
+
+char h_file_head_str[] =
+	"/*\n"
+	" * This file is generated with wrc version " WRC_FULLVERSION ". Do not edit!\n"
+	" * Source : %s\n"
+	" * Cmdline: %s\n"
+	" * Date   : %s"
+	" */\n\n"
+	"#ifndef __%08x_H\n"	/* This becomes the data of compile */
+	"#define __%08x_H\n\n"
+	"#ifndef __WRC_RSC_H\n"
+	"#include <wrc_rsc.h>\n"
+	"#endif\n\n"
+	;
+
+char h_file_tail_str[] =
+	"#endif\n"
+	"/* <eof> */\n\n"
+	;
+
+char _NEResTab[] = "_NEResTab";
+char _PEResTab[] = "_PEResTab";
+char _ResTable[] = "_ResTable";
+
+res_count_t *rcarray = NULL;
+int rccount = 0;
+int n_id_entries = 0;
+int n_name_entries = 0;
+
+time_t now;
+
+/*
+ *****************************************************************************
+ * Function	: write_resfile
+ * Syntax	: void write_resfile(char *outname, resource_t *top)
+ * Input	:
+ *	outname	- Filename to write to
+ *	top	- The resource-tree to convert
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void write_resfile(char *outname, resource_t *top)
+{
+	FILE *fo;
+	int ret;
+	char zeros[3] = {0, 0, 0};
+
+	fo = fopen(outname, "wb");
+	if(!fo)
+	{
+		error("Could not open %s\n", outname);
+	}
+
+	if(win32)
+	{
+		/* Put an empty resource first to signal win32 format */
+		res_t *res = new_res();
+		put_dword(res, 0);		/* ResSize */
+		put_dword(res, 0x00000020);	/* HeaderSize */
+		put_word(res, 0xffff);		/* ResType */
+		put_word(res, 0);
+		put_word(res, 0xffff);		/* ResName */
+		put_word(res, 0);
+		put_dword(res, 0);		/* DataVersion */
+		put_word(res, 0);		/* Memory options */
+		put_word(res, 0);		/* Language */
+		put_dword(res, 0);		/* Version */
+		put_dword(res, 0);		/* Charateristics */
+		ret = fwrite(res->data, 1, res->size, fo);
+		if(ret != res->size)
+		{
+			fclose(fo);
+			error("Error writing %s", outname);
+		}
+		free(res);
+	}
+
+	for(; top; top = top->next)
+	{
+		if(!top->binres)
+			continue;
+
+		ret = fwrite(top->binres->data, 1, top->binres->size, fo);
+		if(ret != top->binres->size)
+		{
+			fclose(fo);
+			error("Error writing %s", outname);
+		}
+		if(win32 && (top->binres->size & 0x03))
+		{
+			/* Write padding */
+			ret = fwrite(zeros, 1, 4 - (top->binres->size & 0x03), fo);
+			if(ret != 4 - (top->binres->size & 0x03))
+			{
+				fclose(fo);
+				error("Error writing %s", outname);
+			}
+		}
+	}
+	fclose(fo);
+}
+
+/*
+ *****************************************************************************
+ * Function	: write_s_res
+ * Syntax	: void write_s_res(FILE *fp, res_t *res)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+#define BYTESPERLINE	8
+void write_s_res(FILE *fp, res_t *res)
+{
+	int idx = res->dataidx;
+	int end = res->size;
+	int rest = (end - idx) % BYTESPERLINE;
+	int lines = (end - idx) / BYTESPERLINE;
+	int i, j;
+
+	for(i = 0 ; i < lines; i++)
+	{
+		fprintf(fp, "\t.byte\t");
+		for(j = 0; j < BYTESPERLINE; j++, idx++)
+		{
+			fprintf(fp, "0x%02x%s", res->data[idx] & 0xff,
+					j == BYTESPERLINE-1 ? "" : ", ");
+		}
+		fprintf(fp, "\n");
+	}
+	if(rest)
+	{
+		fprintf(fp, "\t.byte\t");
+		for(j = 0; j < rest; j++, idx++)
+		{
+			fprintf(fp, "0x%02x%s", res->data[idx] & 0xff,
+					j == rest-1 ? "" : ", ");
+		}
+		fprintf(fp, "\n");
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	: write_name_str
+ * Syntax	: void write_name_str(FILE *fp, name_id_t *nid)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	: One level self recursive for string type conversion
+ *****************************************************************************
+*/
+void write_name_str(FILE *fp, name_id_t *nid)
+{
+	res_t res;
+	assert(nid->type == name_str);
+
+	if(!win32 && nid->name.s_name->type == str_char)
+	{
+		res.size = strlen(nid->name.s_name->str.cstr) + 1;
+		if(res.size > 254)
+			error("Can't write strings larger than 254 bytes");
+		if(res.size == 0)
+			internal_error(__FILE__, __LINE__, "Attempt to write empty string");
+		res.dataidx = 0;
+		res.data = (char *)xmalloc(res.size);
+		res.data[0] = (char)res.size;
+		strcpy(res.data+1, nid->name.s_name->str.cstr);
+		write_s_res(fp, &res);
+		free(res.data);
+	}
+	else if(!win32 && nid->name.s_name->type == str_unicode)
+	{
+		name_id_t lnid;
+		string_t str;
+
+		lnid.type = name_str;
+		lnid.name.s_name = &str;
+		str.type = str_char;
+		str.str.cstr = dupwstr2cstr(nid->name.s_name->str.wstr);
+		write_name_str(fp, &lnid);
+		free(str.str.cstr);
+	}
+	else if(win32 && nid->name.s_name->type == str_char)
+	{
+		name_id_t lnid;
+		string_t str;
+
+		lnid.type = name_str;
+		lnid.name.s_name = &str;
+		str.type = str_unicode;
+		str.str.wstr = dupcstr2wstr(nid->name.s_name->str.cstr);
+		write_name_str(fp, &lnid);
+		free(str.str.wstr);
+	}
+	else  if(win32 && nid->name.s_name->type == str_unicode)
+	{
+		res.size = wstrlen(nid->name.s_name->str.wstr) + 1;
+		if(res.size > 65534)
+			error("Can't write strings larger than 65534 bytes");
+		if(res.size == 0)
+			internal_error(__FILE__, __LINE__, "Attempt to write empty string");
+		res.dataidx = 0;
+		res.data = (char *)xmalloc(res.size * 2);
+		((short *)res.data)[0] = (char)res.size;
+		wstrcpy((short *)(res.data+2), nid->name.s_name->str.wstr);
+		res.size *= 2; /* Function writes bytes, not shorts... */
+		write_s_res(fp, &res);
+		free(res.data);
+	}
+	else
+	{
+		internal_error(__FILE__, __LINE__, "Hmm, requested to write a string of unknown type %d",
+				nid->name.s_name->type);
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	: compare_name_id
+ * Syntax	: int compare_name_id(name_id_t *n1, name_id_t *n2)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+int compare_name_id(name_id_t *n1, name_id_t *n2)
+{
+	if(n1->type == name_ord && n2->type == name_ord)
+	{
+		return n1->name.i_name - n2->name.i_name;
+	}
+	else if(n1->type == name_str && n2->type == name_str)
+	{
+		if(n1->name.s_name->type == str_char
+		&& n2->name.s_name->type == str_char)
+		{
+			return stricmp(n1->name.s_name->str.cstr, n2->name.s_name->str.cstr);
+		}
+		else if(n1->name.s_name->type == str_unicode
+		&& n2->name.s_name->type == str_unicode)
+		{
+			return wstricmp(n1->name.s_name->str.wstr, n2->name.s_name->str.wstr);
+		}
+		else
+		{
+			internal_error(__FILE__, __LINE__, "Can't yet compare strings of mixed type");
+		}
+	}
+	else if(n1->type == name_ord && n2->type == name_str)
+		return -1;
+	else if(n1->type == name_str && n2->type == name_ord)
+		return 1;
+	else
+		internal_error(__FILE__, __LINE__, "Comparing name-ids with unknown types (%d, %d)",
+				n1->type, n2->type);
+
+	return 0; /* Keep the compiler happy */
+}
+
+/*
+ *****************************************************************************
+ * Function	: find_counter
+ * Syntax	: res_count_t *find_counter(name_id_t *type)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+res_count_t *find_counter(name_id_t *type)
+{
+	int i;
+	for(i = 0; i < rccount; i++)
+	{
+		if(!compare_name_id(type, &(rcarray[i].type)))
+			return &rcarray[i];
+	}
+	return NULL;
+}
+
+/*
+ *****************************************************************************
+ * Function	: count_resources
+ * Syntax	: res_count_t *count_resources(resource_t *top)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	: The whole lot is converted into arrays because they are
+ *		  easy sortable. Makes the lot almost unreadable, but it
+ *		  works (I hope). Basically you have to keep in mind that
+ *		  the lot is a three-dimensional structure for win32 and a
+ *		  two-dimensional structure for win16.
+ *****************************************************************************
+*/
+#define RCT(v)	(*((resource_t **)(v)))
+/* qsort sorting function */
+int sort_name_id(const void *e1, const void *e2)
+{
+	return compare_name_id(RCT(e1)->name, RCT(e2)->name);
+}
+
+int sort_language(const void *e1, const void *e2)
+{
+	assert((RCT(e1)->lan) != NULL);
+	assert((RCT(e2)->lan) != NULL);
+
+	return MAKELANGID(RCT(e1)->lan->id, RCT(e1)->lan->sub)
+	     - MAKELANGID(RCT(e2)->lan->id, RCT(e2)->lan->sub);
+}
+#undef RCT
+#define RCT(v)	((res_count_t *)(v))
+int sort_type(const void *e1, const void *e2)
+{
+	return compare_name_id(&(RCT(e1)->type), &(RCT(e2)->type));
+}
+#undef RCT
+
+void count_resources(resource_t *top)
+{
+	resource_t *rsc;
+	res_count_t *rcp;
+	name_id_t nid;
+	int i, j;
+
+	for(rsc = top; rsc; rsc = rsc->next)
+	{
+		if(!rsc->binres)
+			continue;
+		switch(rsc->type)
+		{
+		case res_dlgex:
+			nid.name.i_name = WRC_RT_DIALOG;
+			nid.type = name_ord;
+			break;
+		case res_menex:
+			nid.name.i_name = WRC_RT_MENU;
+			nid.type = name_ord;
+			break;
+		case res_usr:
+			nid = *(rsc->res.usr->type);
+			break;
+		default:
+			nid.name.i_name = rsc->type;
+			nid.type = name_ord;
+		}
+
+		if((rcp = find_counter(&nid)) == NULL)
+		{
+			/* Count the number of uniq ids and names */
+
+			if(nid.type == name_ord)
+				n_id_entries++;
+			else
+				n_name_entries++;
+
+			if(!rcarray)
+			{
+				rcarray = (res_count_t *)xmalloc(sizeof(res_count_t));
+				rccount = 1;
+				rcarray[0].count = 1;
+				rcarray[0].type = nid;
+				rcarray[0].rscarray = (resource_t **)xmalloc(sizeof(resource_t *));
+				rcarray[0].rscarray[0] = rsc;
+			}
+			else
+			{
+				rccount++;
+				rcarray = (res_count_t *)xrealloc(rcarray, rccount * sizeof(res_count_t));
+				rcarray[rccount-1].count = 1;
+				rcarray[rccount-1].type = nid;
+				rcarray[rccount-1].rscarray = (resource_t **)xmalloc(sizeof(resource_t *));
+				rcarray[rccount-1].rscarray[0] = rsc;
+			}
+		}
+		else
+		{
+			rcp->count++;
+			rcp->rscarray = (resource_t **)xrealloc(rcp->rscarray, rcp->count * sizeof(resource_t *));
+			rcp->rscarray[rcp->count-1] = rsc;
+		}
+	}
+
+	if(!win32)
+	{
+		/* We're done, win16 requires no special sorting */
+		return;
+	}
+
+	/* We now have a unsorted list of types with an array of res_count_t
+	 * in rcarray[0..rccount-1]. And we have names of one type in the
+	 * rcarray[x].rsc[0..rcarray[x].count-1] arrays.
+	 * The list needs to be sorted for win32's top level tree structure.
+	 */
+
+	/* Sort the types */
+	if(rccount > 1)
+		qsort(rcarray, rccount, sizeof(rcarray[0]), sort_type);
+
+	/* Now sort the name-id arrays */
+	for(i = 0; i < rccount; i++)
+	{
+		if(rcarray[i].count > 1)
+			qsort(rcarray[i].rscarray, rcarray[i].count, sizeof(rcarray[0].rscarray[0]), sort_name_id);
+	}
+
+	/* Now split the name-id arrays into name/language
+	 * subs. Don't look at the awfull expressions...
+	 * We do this by taking the array elements out of rscarray and putting
+	 * together a new array in rsc32array.
+	 */
+	for(i = 0; i < rccount; i++)
+	{
+		res_count_t *rcap;
+
+		assert(rcarray[i].count >= 1);
+
+		/* rcap points to the current type we are dealing with */
+		rcap = &(rcarray[i]);
+
+		/* Insert the first name-id */
+		rcap->rsc32array = (res32_count_t *)xmalloc(sizeof(res32_count_t));
+		rcap->count32 = 1;
+		rcap->rsc32array[0].rsc = (resource_t **)xmalloc(sizeof(resource_t *));
+		rcap->rsc32array[0].count = 1;
+		rcap->rsc32array[0].rsc[0] = rcap->rscarray[0];
+		if(rcap->rscarray[0]->name->type == name_ord)
+		{
+			rcap->n_id_entries = 1;
+			rcap->n_name_entries = 0;
+		}
+		else
+		{
+			rcap->n_id_entries = 0;
+			rcap->n_name_entries = 1;
+		}
+
+		/* Now loop over the resting resources of the current type
+		 * to find duplicate names (which should have different
+		 * languages).
+		 */
+		for(j = 1; j < rcap->count; j++)
+		{
+			res32_count_t *r32cp;
+
+			/* r32cp points to the current res32_count structure
+			 * that holds the resource name we are processing.
+			 */
+			r32cp = &(rcap->rsc32array[rcap->count32-1]);
+
+			if(!compare_name_id(r32cp->rsc[0]->name, rcarray[i].rscarray[j]->name))
+			{
+				/* Names are the same, add to list */
+				r32cp->count++;
+				r32cp->rsc = (resource_t **)xrealloc(r32cp->rsc, r32cp->count * sizeof(resource_t *));
+				r32cp->rsc[r32cp->count-1] = rcap->rscarray[j];
+
+				if(rcap->rscarray[j]->name->type == name_ord)
+				{
+					rcap->n_id_entries = 1;
+					rcap->n_name_entries = 0;
+				}
+				else
+				{
+					rcap->n_id_entries = 0;
+					rcap->n_name_entries = 1;
+				}
+			}
+			else
+			{
+				/* New name-id, sort the old one by
+				 * language and create new list
+				 */
+				if(r32cp->count > 1)
+					qsort(r32cp->rsc, r32cp->count, sizeof(r32cp->rsc[0]), sort_language);
+				rcap->count32++;
+				rcap->rsc32array = (res32_count_t*)xrealloc(rcap->rsc32array, rcap->count32 * sizeof(res32_count_t));
+				rcap->rsc32array[rcap->count32-1].rsc = (resource_t **)xmalloc(sizeof(resource_t *));
+				rcap->rsc32array[rcap->count32-1].count = 1;
+				rcap->rsc32array[rcap->count32-1].rsc[0] = rcap->rscarray[j];
+
+				if(rcap->rscarray[j]->name->type == name_ord)
+					rcap->n_id_entries++;
+				else
+					rcap->n_name_entries++;
+			}
+		}
+		/* Also sort the languages of the last name group */
+		if(rcap->rsc32array[rcap->count32-1].count > 1)
+			qsort(rcap->rsc32array[rcap->count32-1].rsc,
+			      rcap->rsc32array[rcap->count32-1].count,
+			      sizeof(rcap->rsc32array[rcap->count32-1].rsc[0]),
+			      sort_language);
+	}
+}
+
+/*
+ *****************************************************************************
+ * Function	: write_pe_segment
+ * Syntax	: void write_pe_segment(FILE *fp, resource_t *top)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void write_pe_segment(FILE *fp, resource_t *top)
+{
+	int i;
+
+	fprintf(fp, "\t.align\t4\n");
+	fprintf(fp, "%s%s:\n", prefix, _PEResTab);
+	fprintf(fp, "\t.globl\t%s%s\n", prefix, _PEResTab);
+	/* Flags */
+	fprintf(fp, "\t.long\t0\n");
+	/* Time/Date stamp */
+	fprintf(fp, "\t.long\t0x%08lx\n", now);
+	/* Version */
+	fprintf(fp, "\t.long\t0\n");	/* FIXME: must version be filled out? */
+	/* # of id entries, # of name entries */
+	fprintf(fp, "\t.short\t%d, %d\n", n_name_entries, n_id_entries);
+
+	/* Write the type level of the tree */
+	for(i = 0; i < rccount; i++)
+	{
+		res_count_t *rcp;
+		char *label;
+
+		rcp = &rcarray[i];
+
+		/* TypeId */
+		if(rcp->type.type == name_ord)
+			fprintf(fp, "\t.long\t%d\n", rcp->type.name.i_name);
+		else
+		{
+			char *name = prep_nid_for_label(&(rcp->type));
+			fprintf(fp, "\t.long\t(%s_%s_typename - %s%s) | 0x80000000\n",
+				prefix,
+				name,
+				prefix,
+				_PEResTab);
+		}
+		/* Offset */
+		label = prep_nid_for_label(&(rcp->type));
+		fprintf(fp, "\t.long\t(.L%s - %s%s) | 0x80000000\n",
+			label,
+			prefix,
+			_PEResTab);
+	}
+
+	/* Write the name level of the tree */
+
+	for(i = 0; i < rccount; i++)
+	{
+		res_count_t *rcp;
+		char *typelabel;
+		char *namelabel;
+		int j;
+
+		rcp = &rcarray[i];
+
+		typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
+		fprintf(fp, ".L%s:\n", typelabel);
+
+		fprintf(fp, "\t.long\t0\n");		/* Flags */
+		fprintf(fp, "\t.long\t0x%08lx\n", now);	/* TimeDate */
+		fprintf(fp, "\t.long\t0\n");	/* FIXME: must version be filled out? */
+		fprintf(fp, "\t.short\t%d, %d\n", rcp->n_name_entries, rcp->n_id_entries);
+		for(j = 0; j < rcp->count32; j++)
+		{
+			resource_t *rsc = rcp->rsc32array[j].rsc[0];
+			/* NameId */
+			if(rsc->name->type == name_ord)
+				fprintf(fp, "\t.long\t%d\n", rsc->name->name.i_name);
+			else
+			{
+				fprintf(fp, "\t.long\t(%s%s_name - %s%s) | 0x80000000\n",
+					prefix,
+					rsc->c_name,
+					prefix,
+					_PEResTab);
+			}
+			/* Maybe FIXME: Unescape the tree (ommit 0x80000000) and
+			 * put the offset to the resource data entry.
+			 * ?? Is unescaping worth while ??
+			 */
+			/* Offset */
+			namelabel = prep_nid_for_label(rsc->name);
+			fprintf(fp, "\t.long\t(.L%s_%s - %s%s) | 0x80000000\n",
+				typelabel,
+				namelabel,
+				prefix,
+				_PEResTab);
+		}
+		free(typelabel);
+	}
+
+	/* Write the language level of the tree */
+
+	for(i = 0; i < rccount; i++)
+	{
+		res_count_t *rcp;
+		char *namelabel;
+		char *typelabel;
+		int j;
+
+		rcp = &rcarray[i];
+		typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
+
+		for(j = 0; j < rcp->count32; j++)
+		{
+			res32_count_t *r32cp = &(rcp->rsc32array[j]);
+			int k;
+
+			namelabel = xstrdup(prep_nid_for_label(r32cp->rsc[0]->name));
+			fprintf(fp, ".L%s_%s:\n", typelabel, namelabel);
+
+			fprintf(fp, "\t.long\t0\n");		/* Flags */
+			fprintf(fp, "\t.long\t0x%08lx\n", now);	/* TimeDate */
+			fprintf(fp, "\t.long\t0\n");	/* FIXME: must version be filled out? */
+			fprintf(fp, "\t.short\t0, %d\n", r32cp->count);
+
+			for(k = 0; k < r32cp->count; k++)
+			{
+				resource_t *rsc = r32cp->rsc[k];
+				assert(rsc->lan != NULL);
+				/* LanguageId */
+				fprintf(fp, "\t.long\t0x%08x\n", rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0);
+				/* Offset */
+				fprintf(fp, "\t.long\t.L%s_%s_%d - %s%s\n",
+					typelabel,
+					namelabel,
+					rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0,
+					prefix,
+					_PEResTab);
+			}
+			free(namelabel);
+		}
+		free(typelabel);
+	}
+
+	/* Write the resource table itself */
+
+	for(i = 0; i < rccount; i++)
+	{
+		res_count_t *rcp;
+		char *namelabel;
+		char *typelabel;
+		int j;
+
+		rcp = &rcarray[i];
+		typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
+
+		for(j = 0; j < rcp->count32; j++)
+		{
+			res32_count_t *r32cp = &(rcp->rsc32array[j]);
+			int k;
+
+			namelabel = xstrdup(prep_nid_for_label(r32cp->rsc[0]->name));
+
+			for(k = 0; k < r32cp->count; k++)
+			{
+				resource_t *rsc = r32cp->rsc[k];
+
+				assert(rsc->lan != NULL);
+
+				fprintf(fp, ".L%s_%s_%d:\n",
+					typelabel,
+					namelabel,
+					rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0);
+
+				/* Data RVA */
+				fprintf(fp, "\t.long\t%s%s_data - %s%s\n",
+					prefix,
+					rsc->c_name,
+					prefix,
+					_PEResTab);
+				/* Size */
+				fprintf(fp, "\t.long\t%d\n",
+					rsc->binres->size - rsc->binres->dataidx);
+				/* CodePage */
+				fprintf(fp, "\t.long\t%ld\n", codepage);
+				/* Reserved */
+				fprintf(fp, "\t.long\t0\n");
+			}
+			free(namelabel);
+		}
+		free(typelabel);
+	}
+
+}
+
+/*
+ *****************************************************************************
+ * Function	: write_ne_segment
+ * Syntax	: void write_ne_segment(FILE *fp, resource_t *top)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void write_ne_segment(FILE *fp, resource_t *top)
+{
+	int i, j;
+
+	fprintf(fp, "\t.align\t4\n");
+	fprintf(fp, "%s%s:\n", prefix, _NEResTab);
+	fprintf(fp, "\t.globl\t%s%s\n", prefix, _NEResTab);
+
+	/* AlignmentShift */
+	fprintf(fp, "\t.short\t%d\n", alignment_pwr);
+
+	/* TypeInfo */
+	for(i = 0; i < rccount; i++)
+	{
+		res_count_t *rcp = &rcarray[i];
+
+		/* TypeId */
+		if(rcp->type.type == name_ord)
+			fprintf(fp, "\t.short\t0x%04x\n", rcp->type.name.i_name | 0x8000);
+		else
+			fprintf(fp, "\t.short\t%s_%s_typename - %s%s\n",
+				prefix,
+				rcp->type.name.s_name->str.cstr,
+				prefix,
+				_NEResTab);
+		/* ResourceCount */
+		fprintf(fp, "\t.short\t%d\n", rcp->count);
+		/* Reserved */
+		fprintf(fp, "\t.long\t0\n");
+		/* NameInfo */
+		for(j = 0; j < rcp->count; j++)
+		{
+			/* FIXME: dividing by `alignment` doesn't seem to
+			 * work with as (GAS). Shifting results in the
+			 * correct behaviour. Maybe an as bug or just my
+			 * lack of knowing as expression-syntax.
+			 */
+			/* Offset */
+/*
+ * VERY IMPORTANT:
+ * The offset is relative to the beginning of the NE resource segment
+ * and _NOT_ to the file-beginning. This is because we do not have a
+ * file based resource, but a simulated NE segment. The offset _is_
+ * scaled by the AlignShift field.
+ * All other things are as the MS doc describes (alignment etc.)
+ */
+			fprintf(fp, "\t.short\t(%s%s_data - %s%s) >> %d\n",
+				prefix,
+				rcp->rscarray[j]->c_name,
+				prefix,
+				_NEResTab,
+				alignment_pwr);
+			/* Length */
+			fprintf(fp, "\t.short\t%d\n",
+				rcp->rscarray[j]->binres->size - rcp->rscarray[j]->binres->dataidx);
+			/* Flags */
+			fprintf(fp, "\t.short\t0x%04x\n", (WORD)rcp->rscarray[j]->memopt);
+			/* Id */
+			if(rcp->rscarray[j]->name->type == name_ord)
+				fprintf(fp, "\t.short\t0x%04x\n", rcp->rscarray[j]->name->name.i_name | 0x8000);
+			else
+				fprintf(fp, "\t.short\t%s%s_name - %s%s\n",
+				prefix,
+				rcp->rscarray[j]->c_name,
+				prefix,
+				_NEResTab);
+			/* Handle and Usage */
+			fprintf(fp, "\t.short\t0, 0\n");
+		}
+	}
+	/* EndTypes */
+	fprintf(fp, "\t.short\t0\n");
+}
+
+/*
+ *****************************************************************************
+ * Function	: write_rsc_names
+ * Syntax	: void write_rsc_names(FILE *fp, resource_t *top)
+ * Input	:
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void write_rsc_names(FILE *fp, resource_t *top)
+{
+	int i, j;
+	
+	if(win32)
+	{
+		/* Write the names */
+
+		for(i = 0; i < rccount; i++)
+		{
+			res_count_t *rcp;
+
+			rcp = &rcarray[i];
+
+			if(rcp->type.type == name_str)
+			{
+				char *name = prep_nid_for_label(&(rcp->type));
+				fprintf(fp, "%s_%s_typename:\n",
+					prefix,
+					name);
+				write_name_str(fp, &(rcp->type));
+			}
+
+			for(j = 0; j < rcp->count32; j++)
+			{
+				resource_t *rsc = rcp->rsc32array[j].rsc[0];
+
+				if(rsc->name->type == name_str)
+				{
+					fprintf(fp, "%s%s_name:\n",
+						prefix,
+						rsc->c_name);
+					write_name_str(fp, rsc->name);
+				}
+			}
+		}
+	}
+	else
+	{
+		/* ResourceNames */
+		for(i = 0; i < rccount; i++)
+		{
+			res_count_t *rcp = &rcarray[i];
+
+			for(j = 0; j < rcp->count; j++)
+			{
+				if(rcp->type.type == name_str)
+				{
+					fprintf(fp, "%s_%s_typename:\n",
+						prefix,
+						rcp->type.name.s_name->str.cstr);
+					write_name_str(fp, &(rcp->type));
+				}
+				if(rcp->rscarray[j]->name->type == name_str)
+				{
+					fprintf(fp, "%s%s_name:\n",
+						prefix,
+						rcp->rscarray[j]->c_name);
+					write_name_str(fp, rcp->rscarray[j]->name);
+				}
+			}
+		}
+		/* EndNames */
+		
+		/* This is to end the NE resource table */
+		if(create_dir)
+			fprintf(fp, "\t.byte\t0\n");
+	}
+
+	fprintf(fp, "\n");
+}
+
+/*
+ *****************************************************************************
+ * Function	: write_s_file
+ * Syntax	: void write_s_file(char *outname, resource_t *top)
+ * Input	:
+ *	outname	- Filename to write to
+ *	top	- The resource-tree to convert
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void write_s_file(char *outname, resource_t *top)
+{
+	FILE *fo;
+	resource_t *rsc;
+
+	fo = fopen(outname, "wt");
+	if(!fo)
+	{
+		error("Could not open %s\n", outname);
+	}
+
+	now = time(NULL);
+	fprintf(fo, s_file_head_str, input_name, cmdline, ctime(&now));
+
+	/* Get an idea how many we have and restructure the tables */
+	count_resources(top);
+
+	/* First write the segment tables */
+	if(create_dir)
+	{
+		if(win32)
+			write_pe_segment(fo, top);
+		else
+			write_ne_segment(fo, top);
+	}
+
+	/* Dump the names */
+	write_rsc_names(fo, top);
+	
+	if(!indirect_only)
+	{
+		/* Write the resource data */
+		fprintf(fo, "#\n# Resource binary data\n#\n");
+		for(rsc = top; rsc; rsc = rsc->next)
+		{
+			if(!rsc->binres)
+				continue;
+
+			fprintf(fo, "\t.align\t%d\n", win32 ? 4 : alignment);
+			fprintf(fo, "%s%s_data:\n", prefix, rsc->c_name);
+			if(global)
+				fprintf(fo, "\t.globl\t%s%s_data\n", prefix, rsc->c_name);
+
+			write_s_res(fo, rsc->binres);
+
+			fprintf(fo, "\n");
+		}
+	}
+
+	if(indirect)
+	{
+		/* Write the indirection structures */
+		fprintf(fo, "\n#\n# Resource indirection structures\n#\n");
+		fprintf(fo, "\t.align\t4\n");
+		for(rsc = top; rsc; rsc = rsc->next)
+		{
+			int type;
+			char *type_name = NULL;
+
+			if(!rsc->binres)
+				continue;
+
+			switch(rsc->type)
+			{
+			case res_menex:
+				type = WRC_RT_MENU;
+				break;
+			case res_dlgex:
+				type = WRC_RT_DIALOG;
+				break;
+			case res_usr:
+				assert(rsc->res.usr->type != NULL);
+				type_name = prep_nid_for_label(rsc->res.usr->type);
+				type = 0;
+				break;
+			default:
+				type = rsc->type;
+			}
+
+			/*
+			 * This follows a structure like:
+			 * struct wrc_resource {
+			 * 	INT32	id;
+			 *	RSCNAME	*resname;
+			 *	INT32	restype;
+			 *	RSCNAME	*typename;
+			 *	void	*data;
+			 *	UINT32	datasize;
+			 * };
+			 * The 'RSCNAME' is a pascal-style string where the
+			 * first byte/word denotes the size and the rest the string
+			 * itself.
+			 */
+			fprintf(fo, "%s%s:\n", prefix, rsc->c_name);
+			if(global)
+				fprintf(fo, "\t.globl\t%s%s\n", prefix, rsc->c_name);
+			fprintf(fo, "\t.long\t%d, %s%s%s, %d, %s%s%s%s, %s%s_data, %d\n",
+				rsc->name->type == name_ord ? rsc->name->name.i_name : 0,
+				rsc->name->type == name_ord ? "0" : prefix,
+				rsc->name->type == name_ord ? "" : rsc->c_name,
+				rsc->name->type == name_ord ? "" : "_name",
+				type,
+				type ? "0" : prefix,
+				type ? "" : "_",
+				type ? "" : type_name,
+				type ? "" : "_typename",
+				prefix,
+				rsc->c_name,
+				rsc->binres->size - rsc->binres->dataidx);
+			fprintf(fo, "\n");
+		}
+		fprintf(fo, "\n");
+
+		/* Write the indirection table */
+		fprintf(fo, "#\n# Resource indirection table\n#\n");
+		fprintf(fo, "\t.align\t4\n");
+		fprintf(fo, "%s%s:\n", prefix, _ResTable);
+		fprintf(fo, "\t.globl\t%s%s\n", prefix, _ResTable);
+		for(rsc = top; rsc; rsc = rsc->next)
+		{
+			fprintf(fo, "\t.long\t%s%s\n", prefix, rsc->c_name);
+		}
+		fprintf(fo, "\t.long\t0\n");
+		fprintf(fo, "\n");
+	}
+
+	fprintf(fo, s_file_tail_str);
+	fclose(fo);
+}
+
+/*
+ *****************************************************************************
+ * Function	: write_h_file
+ * Syntax	: void write_h_file(char *outname, resource_t *top)
+ * Input	:
+ *	outname	- Filename to write to
+ *	top	- The resource-tree to convert
+ * Output	:
+ * Description	:
+ * Remarks	:
+ *****************************************************************************
+*/
+void write_h_file(char *outname, resource_t *top)
+{
+	FILE *fo;
+	resource_t *rsc;
+	char *h_prefix;
+	int cnameidx;
+
+	if(prefix[0] == '_')
+	{
+		h_prefix = prefix + 1;
+		cnameidx = 0;
+	}
+	else if(prefix[0] == '\0')
+	{
+		h_prefix = prefix;
+		cnameidx = 1;
+	}
+	else
+	{
+		h_prefix = prefix;
+		cnameidx = 0;
+		warning("Resources might not be visible in c-namespace (missing '_' in prefix)\n");
+	}
+
+	fo = fopen(outname, "wt");
+	if(!fo)
+	{
+		error("Could not open %s\n", outname);
+	}
+
+	time(&now);
+	fprintf(fo, h_file_head_str, input_name, cmdline, ctime(&now), now, now);
+
+	/* First write the segment tables reference */
+	if(create_dir)
+	{
+		fprintf(fo, "extern %schar %s%s[];\n\n",
+			constant ? "const " : "",
+			h_prefix,
+			(win32 ? _PEResTab : _NEResTab) + cnameidx);
+	}
+
+	/* Write the resource data */
+	for(rsc = top; global && rsc; rsc = rsc->next)
+	{
+		if(!rsc->binres)
+			continue;
+
+		fprintf(fo, "extern %schar %s%s_data[];\n",
+			constant ? "const " : "",
+			h_prefix,
+			rsc->c_name + cnameidx);
+	}
+
+	if(indirect)
+	{
+		if(global)
+			fprintf(fo, "\n");
+
+		/* Write the indirection structures */
+		for(rsc = top; global && rsc; rsc = rsc->next)
+		{
+			fprintf(fo, "extern %swrc_resource%d_t %s%s;\n",
+				constant ? "const " : "",
+				win32 ? 32 : 16,
+				h_prefix,
+				rsc->c_name + cnameidx);
+		}
+
+		if(global)
+			fprintf(fo, "\n");
+
+		/* Write the indirection table */
+		fprintf(fo, "extern %swrc_resource%d_t %s%s[];\n\n",
+			constant ? "const " : "",
+			win32 ? 32 : 16,
+			h_prefix,
+			_ResTable + cnameidx);
+	}
+
+	fprintf(fo, h_file_tail_str);
+	fclose(fo);
+}
+
+
diff --git a/tools/wrc/writeres.h b/tools/wrc/writeres.h
new file mode 100644
index 0000000..08da1b2
--- /dev/null
+++ b/tools/wrc/writeres.h
@@ -0,0 +1,19 @@
+/*
+ * Write resource prototypes
+ *
+ * Copyright 1998 Bertho A. Stultiens (BS)
+ *
+ */
+
+#ifndef __WRC_WRITERES_H
+#define __WRC_WRITERES_H
+
+#ifndef __WRC_WRCTYPES_H
+#include "wrctypes.h"
+#endif
+
+void write_resfile(char *outname, resource_t *top);
+void write_s_file(char *outname, resource_t *top);
+void write_h_file(char *outname, resource_t *top);
+
+#endif
diff --git a/win32/advapi.c b/win32/advapi.c
index cee2675..0b39d0a 100644
--- a/win32/advapi.c
+++ b/win32/advapi.c
@@ -4,7 +4,6 @@
  * Copyright 1995 Sven Verdoolaege
  */
 
-#include <stdio.h>
 #include <unistd.h>
 #include <time.h>
 #include "windows.h"
diff --git a/win32/code_page.c b/win32/code_page.c
index f730121..ec18479 100644
--- a/win32/code_page.c
+++ b/win32/code_page.c
@@ -4,7 +4,6 @@
  * Copyright 1995 Martin von Loewis and Cameron Heide
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include "windows.h"
 #include "winerror.h"
diff --git a/win32/console.c b/win32/console.c
index 18cb158..505bfea 100644
--- a/win32/console.c
+++ b/win32/console.c
@@ -6,7 +6,6 @@
  * Copyright 1998 John Richardson
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <termios.h>
@@ -1126,3 +1125,17 @@
     return TRUE;
 }
 
+/******************************************************************************
+ * ReadConsoleOutputCharacter32A [KERNEL32.573]
+ * 
+ * BUGS
+ *   Unimplemented
+ */
+BOOL32 WINAPI ReadConsoleOutputCharacter32A(HANDLE32 hConsoleOutput, 
+	      LPSTR lpstr, DWORD dword, COORD coord, LPDWORD lpdword)
+{
+    FIXME(console, "(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput,lpstr,
+	  dword,coord.x,coord.y,lpdword);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
diff --git a/win32/error.c b/win32/error.c
index 39d2832..3c2ee11 100644
--- a/win32/error.c
+++ b/win32/error.c
@@ -4,7 +4,6 @@
  * Copyright 1995 Martin von Loewis and Cameron Heide
  */
 
-#include <stdio.h>
 #include <errno.h>
 #include "windows.h"
 #include "winerror.h"
diff --git a/win32/except.c b/win32/except.c
index fedd40b..63674db 100644
--- a/win32/except.c
+++ b/win32/except.c
@@ -32,7 +32,6 @@
  */
 
 #include <assert.h>
-#include <stdio.h>
 #include "windows.h"
 #include "winerror.h"
 #include "ldt.h"
@@ -40,6 +39,7 @@
 #include "thread.h"
 #include "debug.h"
 #include "except.h"
+#include "stackframe.h"
 
 #define TEB_EXCEPTION_FRAME(pcontext) \
     ((PEXCEPTION_FRAME)((TEB *)GET_SEL_BASE((pcontext)->SegFs))->except)
@@ -49,16 +49,27 @@
  *
  *  This function is undocumented. This is the general idea of 
  *  RtlUnwind, though. Note that error handling is not yet implemented.
+ *
+ * The real prototype is:
+ * void WINAPI EXC_RtlUnwind( PEXCEPTION_FRAME pEndFrame, LPVOID unusedEip, 
+ *                            PEXCEPTION_RECORD pRecord, DWORD returnEax );
  */
-void WINAPI RtlUnwind( PEXCEPTION_FRAME pEndFrame, LPVOID unusedEip, 
-                       PEXCEPTION_RECORD pRecord, DWORD returnEax,
-                       PCONTEXT pcontext /* Wine additional parameter */ )
-{   
-   EXCEPTION_RECORD record;
-   DWORD            dispatch;
-   int              retval;
-  
-   EAX_reg(pcontext) = returnEax;
+REGS_ENTRYPOINT(RtlUnwind)
+{
+    EXCEPTION_RECORD record;
+    DWORD            dispatch;
+    int              retval;
+    PEXCEPTION_FRAME pEndFrame;
+    PEXCEPTION_RECORD pRecord;
+
+    /* get the arguments from the stack */
+
+    DWORD ret        = STACK32_POP(context);  /* return addr */
+    pEndFrame        = (PEXCEPTION_FRAME)STACK32_POP(context);
+    (void)STACK32_POP(context);  /* unused arg */
+    pRecord          = (PEXCEPTION_RECORD)STACK32_POP(context);
+    EAX_reg(context) = STACK32_POP(context);
+    STACK32_PUSH(context,ret);  /* restore return addr */
    
    /* build an exception record, if we do not have one */
    if(!pRecord)
@@ -66,7 +77,7 @@
      record.ExceptionCode    = STATUS_INVALID_DISPOSITION;
      record.ExceptionFlags   = 0;
      record.ExceptionRecord  = NULL;
-     record.ExceptionAddress = (LPVOID)EIP_reg(pcontext); 
+     record.ExceptionAddress = (LPVOID)EIP_reg(context); 
      record.NumberParameters = 0;
      pRecord = &record;
    }
@@ -77,67 +88,68 @@
      pRecord->ExceptionFlags|=EH_UNWINDING | EH_EXIT_UNWIND;
   
    /* get chain of exception frames */      
-   while ((TEB_EXCEPTION_FRAME(pcontext) != NULL) &&
-          (TEB_EXCEPTION_FRAME(pcontext) != ((void *)0xffffffff)) &&
-          (TEB_EXCEPTION_FRAME(pcontext) != pEndFrame))
+   while ((TEB_EXCEPTION_FRAME(context) != NULL) &&
+          (TEB_EXCEPTION_FRAME(context) != ((void *)0xffffffff)) &&
+          (TEB_EXCEPTION_FRAME(context) != pEndFrame))
    {
        TRACE(win32, "calling exception handler at 0x%x\n",
-                      (int)TEB_EXCEPTION_FRAME(pcontext)->Handler );
+                      (int)TEB_EXCEPTION_FRAME(context)->Handler );
 
        dispatch=0;       
-       retval = TEB_EXCEPTION_FRAME(pcontext)->Handler( pRecord,
-                                                TEB_EXCEPTION_FRAME(pcontext),
-                                                pcontext, &dispatch);
+       retval = TEB_EXCEPTION_FRAME(context)->Handler( pRecord,
+                                                TEB_EXCEPTION_FRAME(context),
+                                                context, &dispatch);
                                          
        TRACE(win32,"exception handler returns 0x%x, dispatch=0x%x\n",
                               retval, (int) dispatch);
   
        if (	(retval == ExceptionCollidedUnwind) &&
-           	(TEB_EXCEPTION_FRAME(pcontext) != (LPVOID)dispatch)
+           	(TEB_EXCEPTION_FRAME(context) != (LPVOID)dispatch)
        )
-           TEB_EXCEPTION_FRAME(pcontext) = (LPVOID)dispatch;
-       else if (	(TEB_EXCEPTION_FRAME(pcontext) != pEndFrame) &&
-           		(TEB_EXCEPTION_FRAME(pcontext) != TEB_EXCEPTION_FRAME(pcontext)->Prev)
+           TEB_EXCEPTION_FRAME(context) = (LPVOID)dispatch;
+       else if (	(TEB_EXCEPTION_FRAME(context) != pEndFrame) &&
+           		(TEB_EXCEPTION_FRAME(context) != TEB_EXCEPTION_FRAME(context)->Prev)
        )
-           TEB_EXCEPTION_FRAME(pcontext) = TEB_EXCEPTION_FRAME(pcontext)->Prev;
+           TEB_EXCEPTION_FRAME(context) = TEB_EXCEPTION_FRAME(context)->Prev;
        else
           break;  
    }
 }
 
-/* This is the real entry point called by relay debugging code */
-void EXC_RtlUnwind( CONTEXT *context )
-{
-    /* Retrieve the arguments (args[0] is return addr, args[1] is first arg) */
-    DWORD *args = (DWORD *)ESP_reg(context);
-    ESP_reg(context) += 4 * sizeof(DWORD);  /* Pop the arguments */
-    RtlUnwind( (PEXCEPTION_FRAME)args[1], (LPVOID)args[2],
-               (PEXCEPTION_RECORD)args[3], args[4], context );
-}
-
 
 /*******************************************************************
  *         RaiseException  (KERNEL32.418)
+ *
+ * The real prototype is:
+ * void WINAPI EXC_RaiseException(DWORD dwExceptionCode,
+ *                                DWORD dwExceptionFlags,
+ *                                DWORD cArguments,
+ *                                const LPDWORD lpArguments );
  */
-void WINAPI RaiseException(DWORD dwExceptionCode,
-                           DWORD dwExceptionFlags,
-                           DWORD cArguments,
-                           const LPDWORD lpArguments,
-                           PCONTEXT pcontext /* Wine additional parameter */ )
+REGS_ENTRYPOINT(RaiseException)
 {
     PEXCEPTION_FRAME    pframe; 
     EXCEPTION_RECORD    record;
     DWORD               dispatch; /* is this used in raising exceptions ?? */
     int                 retval;
     int                 i;
-    
+
+    /* Get the arguments from the stack */
+
+    DWORD ret                 = STACK32_POP(context);  /* return addr */
+    DWORD dwExceptionCode     = STACK32_POP(context);
+    DWORD dwExceptionFlags    = STACK32_POP(context);
+    DWORD cArguments          = STACK32_POP(context);
+    const LPDWORD lpArguments = (LPDWORD)STACK32_POP(context);
+    STACK32_PUSH(context,ret);  /* Restore the return address */
+
     /* compose an exception record */ 
     
     record.ExceptionCode       = dwExceptionCode;   
     record.ExceptionFlags      = dwExceptionFlags;
     record.ExceptionRecord     = NULL;
     record.NumberParameters    = cArguments;
-    record.ExceptionAddress    = (LPVOID)EIP_reg(pcontext);
+    record.ExceptionAddress    = (LPVOID)EIP_reg(context);
     
     if (lpArguments) for( i = 0; i < cArguments; i++)
         record.ExceptionInformation[i] = lpArguments[i];
@@ -145,7 +157,7 @@
     /* get chain of exception frames */    
     
     retval = ExceptionContinueSearch;    
-    pframe = TEB_EXCEPTION_FRAME( pcontext );
+    pframe = TEB_EXCEPTION_FRAME( context );
     
     while((pframe!=NULL)&&(pframe!=((void *)0xFFFFFFFF)))
     {
@@ -153,8 +165,8 @@
                                                 (int) pframe->Handler);
        dispatch=0;  
        TRACE(relay,"(except=%p,record=%p,frame=%p,context=%p,dispatch=%p)\n",
-                     pframe->Handler, &record, pframe, pcontext, &dispatch );
-       retval=pframe->Handler(&record,pframe,pcontext,&dispatch);
+                     pframe->Handler, &record, pframe, context, &dispatch );
+       retval=pframe->Handler(&record,pframe,context,&dispatch);
  
        TRACE(win32,"exception handler returns 0x%x, dispatch=0x%x\n",
                               retval, (int) dispatch);
@@ -172,14 +184,6 @@
    }
 }
 
-/* This is the real entry point called by relay debugging code */
-void EXC_RaiseException( CONTEXT *context )
-{
-    /* Retrieve the arguments (args[0] is return addr, args[1] is first arg) */
-    DWORD *args = (DWORD *)ESP_reg(context);
-    ESP_reg(context) += 4 * sizeof(DWORD);  /* Pop the arguments */
-    RaiseException( args[1], args[2], args[3], (LPDWORD)args[4], context );
-}
 
 /*******************************************************************
  *         UnhandledExceptionFilter   (KERNEL32.537)
diff --git a/win32/file.c b/win32/file.c
index c999fb3..49a2d77 100644
--- a/win32/file.c
+++ b/win32/file.c
@@ -5,7 +5,6 @@
  */
 
 #include <errno.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/types.h>
diff --git a/win32/init.c b/win32/init.c
index 0b61153..6a646cb 100644
--- a/win32/init.c
+++ b/win32/init.c
@@ -5,7 +5,6 @@
  */
 
 #include <string.h>
-#include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include "windows.h"
diff --git a/win32/kernel32.c b/win32/kernel32.c
index 133d6a0..b01a40c 100644
--- a/win32/kernel32.c
+++ b/win32/kernel32.c
@@ -5,7 +5,6 @@
  * Copyright 1998      Ulrich Weigand
  */
 
-#include <stdio.h>
 #include "windows.h"
 #include "callback.h"
 #include "resource.h"
@@ -20,6 +19,8 @@
 #include "task.h"
 #include "win.h"
 #include "debug.h"
+#include "flatthunk.h"
+
 
 /***********************************************************************
  *                                                                     *
@@ -75,110 +76,6 @@
 	/* should fill the rest of the 32 bytes with 0xCC */
 }
 
-
-/***********************************************************************
- * ThunkConnect data structures
- */
-
-struct ThunkDataCommon
-{
-    char                   magic[4];         /* 00 */
-    DWORD                  checksum;         /* 04 */
-};
-
-struct ThunkDataLS16
-{
-    struct ThunkDataCommon common;           /* 00 */
-    SEGPTR                 targetTable;      /* 08 */
-    DWORD                  firstTime;        /* 0C */
-};
-
-struct ThunkDataLS32
-{
-    struct ThunkDataCommon common;           /* 00 */
-    DWORD *                targetTable;      /* 08 */
-    char                   lateBinding[4];   /* 0C */
-    DWORD                  flags;            /* 10 */
-    DWORD                  reserved1;        /* 14 */
-    DWORD                  reserved2;        /* 18 */
-    DWORD                  offsetQTThunk;    /* 1C */
-    DWORD                  offsetFTProlog;   /* 20 */
-};
-
-struct ThunkDataSL16
-{
-    struct ThunkDataCommon common;            /* 00 */
-    DWORD                  flags1;            /* 08 */
-    DWORD                  reserved1;         /* 0C */
-    struct ThunkDataSL *   fpData;            /* 10 */
-    SEGPTR                 spData;            /* 14 */
-    DWORD                  reserved2;         /* 18 */
-    char                   lateBinding[4];    /* 1C */
-    DWORD                  flags2;            /* 20 */
-    DWORD                  reserved3;         /* 20 */
-    SEGPTR                 apiDatabase;       /* 28 */
-};
-
-struct ThunkDataSL32
-{
-    struct ThunkDataCommon common;            /* 00 */
-    DWORD                  reserved1;         /* 08 */
-    struct ThunkDataSL *   data;              /* 0C */
-    char                   lateBinding[4];    /* 10 */
-    DWORD                  flags;             /* 14 */
-    DWORD                  reserved2;         /* 18 */
-    DWORD                  reserved3;         /* 1C */
-    DWORD                  offsetTargetTable; /* 20 */
-};
-
-struct ThunkDataSL
-{
-#if 0
-    This structure differs from the Win95 original,
-    but this should not matter since it is strictly internal to 
-    the thunk handling routines in KRNL386 / KERNEL32.
-
-    For reference, here is the Win95 layout:
-
-    struct ThunkDataCommon common;            /* 00 */
-    DWORD                  flags1;            /* 08 */
-    SEGPTR                 apiDatabase;       /* 0C */
-    WORD                   exePtr;            /* 10 */
-    WORD                   segMBA;            /* 12 */
-    DWORD                  lenMBATotal;       /* 14 */
-    DWORD                  lenMBAUsed;        /* 18 */
-    DWORD                  flags2;            /* 1C */
-    char                   pszDll16[256];     /* 20 */
-    char                   pszDll32[256];     /*120 */
-  
-    We do it differently since all our thunk handling is done
-    by 32-bit code. Therefore we do not need do provide
-    easy access to this data, especially the process target
-    table database, for 16-bit code.
-#endif
-    
-    struct ThunkDataCommon common;
-    DWORD                  flags1;
-    struct SLApiDB *       apiDB;
-    struct SLTargetDB *    targetDB;
-    DWORD                  flags2;
-    char                   pszDll16[256];
-    char                   pszDll32[256];
-};
-
-struct SLTargetDB
-{
-     struct SLTargetDB *   next;
-     PDB32 *               process;
-     DWORD *               targetTable;
-};
-
-struct SLApiDB
-{
-    DWORD                  nrArgBytes;
-    DWORD                  errorReturnValue;
-};
-
 /***********************************************************************
  *           GetThunkStuff    (KERNEL32.53)
  */
@@ -292,93 +189,6 @@
     return 1;
 }
 
-/***********************************************************************
- *		ThunkConnect16		(KERNEL.651)
- * Connects a 32bit and a 16bit thunkbuffer.
- */
-UINT32 WINAPI ThunkConnect16( 
-	LPSTR module16,              /* [in] name of win16 dll */
-	LPSTR module32,              /* [in] name of win32 dll */
-	HINSTANCE16 hInst16,         /* [in] hInst of win16 dll */
-	DWORD dwReason,              /* [in] initialisation argument */
-	struct ThunkDataCommon *TD,  /* [in/out] thunkbuffer */
-	LPSTR thunkfun32,            /* [in] win32 thunkfunction */
-        WORD CS                      /* [in] CS of win16 dll */
-) {
-    BOOL32 directionSL;
-
-    if (!lstrncmp32A(TD->magic, "SL01", 4))
-    {
-        directionSL = TRUE;
-
-        TRACE(thunk, "SL01 thunk %s (%lx) -> %s (%s), Reason: %ld\n",
-                     module16, (DWORD)TD, module32, thunkfun32, dwReason);
-    }
-    else if (!lstrncmp32A(TD->magic, "LS01", 4))
-    {
-        directionSL = FALSE;
-
-        TRACE(thunk, "LS01 thunk %s (%lx) <- %s (%s), Reason: %ld\n",
-                     module16, (DWORD)TD, module32, thunkfun32, dwReason);
-    }
-    else
-    {
-        ERR(thunk, "Invalid magic %c%c%c%c\n", 
-                   TD->magic[0], TD->magic[1], TD->magic[2], TD->magic[3]);
-        return 0;
-    }
-    
-    switch (dwReason)
-    {
-        case DLL_PROCESS_ATTACH:
-            if (directionSL)
-            {
-                struct ThunkDataSL16 *SL16 = (struct ThunkDataSL16 *)TD;
-                struct ThunkDataSL   *SL   = SL16->fpData;
-
-                if (SL == NULL)
-                {
-                    SL = HeapAlloc(GetProcessHeap(), 0, sizeof(*SL));
-
-                    SL->common   = SL16->common;
-                    SL->flags1   = SL16->flags1;
-                    SL->flags2   = SL16->flags2;
-
-                    SL->apiDB    = PTR_SEG_TO_LIN(SL16->apiDatabase);
-                    SL->targetDB = NULL;
-
-                    lstrcpyn32A(SL->pszDll16, module16, 255);
-                    lstrcpyn32A(SL->pszDll32, module32, 255);
-
-                    /* We should create a SEGPTR to the ThunkDataSL,
-                       but since the contents are not in the original format,
-                       any access to this by 16-bit code would crash anyway. */
-                    SL16->spData = 0;
-                    SL16->fpData = SL;
-                }
-
-
-                if (SL->flags2 & 0x80000000)
-                {
-                    TRACE(thunk, "Preloading 32-bit library\n");
-                    LoadLibrary32A(module32);
-                }
-            }
-            else
-            {
-                /* nothing to do */
-            }
-            break;
-
-        case DLL_PROCESS_DETACH:
-            /* FIXME: cleanup */
-            break;
-    }
-
-    return 1;
-}
-
-
 /**********************************************************************
  * 		QT_Thunk			(KERNEL32)
  *
@@ -387,7 +197,7 @@
  * The number of 16bit argumentbytes is EBP-ESP-0x44 (68 Byte thunksetup).
  * [ok]
  */
-VOID WINAPI QT_Thunk(CONTEXT *context)
+REGS_ENTRYPOINT(QT_Thunk)
 {
     CONTEXT context16;
     DWORD argsize;
@@ -453,16 +263,13 @@
  *         
  */
 
-#define POP_DWORD(ctx)		(*((DWORD *)ESP_reg(ctx))++)
-#define PUSH_DWORD(ctx, val) 	*--((DWORD *)ESP_reg(ctx)) = (val)
-
-VOID WINAPI FT_Prolog(CONTEXT *context)
+REGS_ENTRYPOINT(FT_Prolog)
 {
     /* Pop return address to thunk code */
-    EIP_reg(context) = POP_DWORD(context);
+    EIP_reg(context) = STACK32_POP(context);
 
     /* Build stack frame */
-    PUSH_DWORD(context, EBP_reg(context));
+    STACK32_PUSH(context, EBP_reg(context));
     EBP_reg(context) = ESP_reg(context);
 
     /* Allocate 64-byte Thunk Buffer */
@@ -480,7 +287,7 @@
     *(DWORD *)(EBP_reg(context) - 52) = EDX_reg(context);
     
     /* Push return address back onto stack */
-    PUSH_DWORD(context, EIP_reg(context));
+    STACK32_PUSH(context, EIP_reg(context));
 }
 
 /**********************************************************************
@@ -504,7 +311,7 @@
  *        sufficient ...
  */
 
-VOID WINAPI FT_Thunk(CONTEXT *context)
+REGS_ENTRYPOINT(FT_Thunk)
 {
     DWORD mapESPrelative = *(DWORD *)(EBP_reg(context) - 20);
     DWORD callTarget     = *(DWORD *)(EBP_reg(context) - 52);
@@ -549,7 +356,7 @@
  * the given number of arguments from the caller's stack).
  */
 
-VOID WINAPI FT_Exit(CONTEXT *context, int nPopArgs)
+static void FT_Exit(CONTEXT *context, int nPopArgs)
 {
     /* Return value is in EBX */
     EAX_reg(context) = EBX_reg(context);
@@ -561,31 +368,31 @@
 
     /* Clean up stack frame */
     ESP_reg(context) = EBP_reg(context);
-    EBP_reg(context) = POP_DWORD(context);
+    EBP_reg(context) = STACK32_POP(context);
 
     /* Pop return address to CALLER of thunk code */
-    EIP_reg(context) = POP_DWORD(context);
+    EIP_reg(context) = STACK32_POP(context);
     /* Remove arguments */
     ESP_reg(context) += nPopArgs;
     /* Push return address back onto stack */
-    PUSH_DWORD(context, EIP_reg(context));
+    STACK32_PUSH(context, EIP_reg(context));
 }
 
-VOID WINAPI FT_Exit0 (CONTEXT *context) { FT_Exit(context,  0); }
-VOID WINAPI FT_Exit4 (CONTEXT *context) { FT_Exit(context,  4); }
-VOID WINAPI FT_Exit8 (CONTEXT *context) { FT_Exit(context,  8); }
-VOID WINAPI FT_Exit12(CONTEXT *context) { FT_Exit(context, 12); }
-VOID WINAPI FT_Exit16(CONTEXT *context) { FT_Exit(context, 16); }
-VOID WINAPI FT_Exit20(CONTEXT *context) { FT_Exit(context, 20); }
-VOID WINAPI FT_Exit24(CONTEXT *context) { FT_Exit(context, 24); }
-VOID WINAPI FT_Exit28(CONTEXT *context) { FT_Exit(context, 28); }
-VOID WINAPI FT_Exit32(CONTEXT *context) { FT_Exit(context, 32); }
-VOID WINAPI FT_Exit36(CONTEXT *context) { FT_Exit(context, 36); }
-VOID WINAPI FT_Exit40(CONTEXT *context) { FT_Exit(context, 40); }
-VOID WINAPI FT_Exit44(CONTEXT *context) { FT_Exit(context, 44); }
-VOID WINAPI FT_Exit48(CONTEXT *context) { FT_Exit(context, 48); }
-VOID WINAPI FT_Exit52(CONTEXT *context) { FT_Exit(context, 52); }
-VOID WINAPI FT_Exit56(CONTEXT *context) { FT_Exit(context, 56); }
+REGS_ENTRYPOINT(FT_Exit0)  { FT_Exit(context,  0); }
+REGS_ENTRYPOINT(FT_Exit4)  { FT_Exit(context,  4); }
+REGS_ENTRYPOINT(FT_Exit8)  { FT_Exit(context,  8); }
+REGS_ENTRYPOINT(FT_Exit12) { FT_Exit(context, 12); }
+REGS_ENTRYPOINT(FT_Exit16) { FT_Exit(context, 16); }
+REGS_ENTRYPOINT(FT_Exit20) { FT_Exit(context, 20); }
+REGS_ENTRYPOINT(FT_Exit24) { FT_Exit(context, 24); }
+REGS_ENTRYPOINT(FT_Exit28) { FT_Exit(context, 28); }
+REGS_ENTRYPOINT(FT_Exit32) { FT_Exit(context, 32); }
+REGS_ENTRYPOINT(FT_Exit36) { FT_Exit(context, 36); }
+REGS_ENTRYPOINT(FT_Exit40) { FT_Exit(context, 40); }
+REGS_ENTRYPOINT(FT_Exit44) { FT_Exit(context, 44); }
+REGS_ENTRYPOINT(FT_Exit48) { FT_Exit(context, 48); }
+REGS_ENTRYPOINT(FT_Exit52) { FT_Exit(context, 52); }
+REGS_ENTRYPOINT(FT_Exit56) { FT_Exit(context, 56); }
 
 
 /**********************************************************************
@@ -711,7 +518,7 @@
  *        (Those two values should be equal anyway ...?)
  * 
  */
-VOID WINAPI Common32ThkLS(CONTEXT *context)
+REGS_ENTRYPOINT(Common32ThkLS)
 {
     CONTEXT context16;
     DWORD argsize;
@@ -734,9 +541,9 @@
 
     /* Clean up caller's stack frame */
 
-    EIP_reg(context) = POP_DWORD(context);
+    EIP_reg(context) = STACK32_POP(context);
     ESP_reg(context) += argsize;
-    PUSH_DWORD(context, EIP_reg(context));
+    STACK32_PUSH(context, EIP_reg(context));
 }
 
 /***********************************************************************
@@ -766,7 +573,7 @@
  * (Note that this function seems only to be used for
  *  OLECLI32 -> OLECLI and OLESVR32 -> OLESVR thunking.)
  */
-VOID WINAPI OT_32ThkLSF(CONTEXT *context)
+REGS_ENTRYPOINT(OT_32ThkLSF)
 {
     CONTEXT context16;
     DWORD argsize;
@@ -891,10 +698,10 @@
  * Note: The two DWORD arguments get popped from the stack.
  *        
  */
-VOID WINAPI FT_PrologPrime(CONTEXT *context)
+REGS_ENTRYPOINT(FT_PrologPrime)
 {
-    DWORD  targetTableOffset = POP_DWORD(context);
-    LPBYTE relayCode = (LPBYTE)POP_DWORD(context);
+    DWORD  targetTableOffset = STACK32_POP(context);
+    LPBYTE relayCode = (LPBYTE)STACK32_POP(context);
     DWORD *targetTable = *(DWORD **)(relayCode+targetTableOffset);
     DWORD  targetNr = LOBYTE(ECX_reg(context));
 
@@ -903,7 +710,7 @@
     /* We should actually call the relay code now, */
     /* but we skip it and go directly to FT_Prolog */
     EDX_reg(context) = targetTable[targetNr];
-    FT_Prolog(context);
+    __regs_FT_Prolog(context);
 }
 
 /***********************************************************************
@@ -917,7 +724,7 @@
  *         EAX    start of relay code
  *      
  */
-VOID WINAPI QT_ThunkPrime(CONTEXT *context)
+REGS_ENTRYPOINT(QT_ThunkPrime)
 {
     DWORD  targetTableOffset = EDX_reg(context);
     LPBYTE relayCode = (LPBYTE)EAX_reg(context);
@@ -929,7 +736,7 @@
     /* We should actually call the relay code now, */
     /* but we skip it and go directly to QT_Thunk */
     EDX_reg(context) = targetTable[targetNr];
-    QT_Thunk(context);
+    __regs_QT_Thunk(context);
 }
 
 /***********************************************************************
@@ -1040,7 +847,7 @@
     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);
+	WARN(thunk,"Unsupported nr of arguments, %ld\n",nr);
 	ret = 0;
 	break;
 
@@ -1055,7 +862,7 @@
  */
 WORD WINAPI _KERNEL_619(WORD x,DWORD y,DWORD z)
 {
-    fprintf(stderr,"KERNEL_619(0x%04x,0x%08lx,0x%08lx)\n",x,y,z);
+    FIXME(thunk,"(0x%04x,0x%08lx,0x%08lx): stub\n",x,y,z);
     return x;
 }
 
@@ -1168,7 +975,7 @@
 FreeSLCallback(
 	DWORD x	/* [in] 16 bit callback (segmented pointer?) */
 ) {
-	fprintf(stderr,"FreeSLCallback(0x%08lx)\n",x);
+	FIXME(win32,"(0x%08lx): stub\n",x);
 }
 
 
@@ -1190,7 +997,7 @@
  */
 VOID WINAPI
 _KERNEL_472(CONTEXT *context) {
-	fprintf(stderr,"_KERNEL_472(0x%08lx),stub\n",EAX_reg(context));
+	FIXME(win32,"(0x%08lx): stub\n",EAX_reg(context));
 	if (!EAX_reg(context)) {
 		TDB *pTask = (TDB*)GlobalLock16(GetCurrentTask());
 		AX_reg(context)=pTask->hInstance;
@@ -1229,7 +1036,7 @@
 		return FALSE;
 	}
 	if (mzh.e_magic!=IMAGE_DOS_SIGNATURE) {
-		fprintf(stderr,"file has not got dos signature!\n");
+		WARN(dosmem,"File has not got dos signature!\n");
 		_lclose32(hf);
 		return FALSE;
 	}
@@ -1254,158 +1061,14 @@
 	WORD handle,		/* [in] win16 handle */
 	WOW_HANDLE_TYPE type	/* [in] handle type */
 ) {
-	fprintf(stderr,"WOWHandle32(0x%04x,%d)\n",handle,type);
+	TRACE(win32,"(0x%04x,%d)\n",handle,type);
 	return (HANDLE32)handle;
 }
 
 /***********************************************************************
- *           C16ThkSL				(KERNEL.630)
- */
-
-void WINAPI C16ThkSL(CONTEXT *context)
-{
-    extern void CallFrom16_t_long_(void);
-    LPBYTE stub = PTR_SEG_TO_LIN(EAX_reg(context)), x = stub;
-    WORD cs, ds;
-    GET_CS(cs);
-    GET_DS(ds);
-
-    /* We produce the following code:
-     *
-     *   mov ax, __FLATDS
-     *   mov es, ax
-     *   movzx ecx, cx
-     *   mov edx, es:[ecx + $EDX]
-     *   push bp
-     *   push edx
-     *   call __FLATCS:CallFrom16_t_long_
-     */
-
-    *x++ = 0xB8; *((WORD *)x)++ = ds;
-    *x++ = 0x8E; *x++ = 0xC0;
-    *x++ = 0x60; *x++ = 0x0F; *x++ = 0xB7; *x++ = 0xC9;
-    *x++ = 0x67; *x++ = 0x66; *x++ = 0x26; *x++ = 0x8B;
-                 *x++ = 0x91; *((DWORD *)x)++ = EDX_reg(context);
-
-    *x++ = 0x55;
-    *x++ = 0x66; *x++ = 0x52;
-    *x++ = 0x66; *x++ = 0x9A; *((DWORD *)x)++ = (DWORD)CallFrom16_t_long_;
-                              *((WORD *)x)++ = cs;
-
-    /* Jump to the stub code just created */
-    IP_reg(context) = LOWORD(EAX_reg(context));
-    CS_reg(context) = HIWORD(EAX_reg(context));
-
-    /* Since C16ThkSL got called by a jmp, we need to leave the
-       orginal return address on the stack */
-    SP_reg(context) -= 4;
-}
-
-/***********************************************************************
- *           C16ThkSL01				(KERNEL.631)
- */
-
-void WINAPI C16ThkSL01(CONTEXT *context)
-{
-    LPBYTE stub = PTR_SEG_TO_LIN(EAX_reg(context)), x = stub;
-
-    if (stub)
-    {
-        struct ThunkDataSL16 *SL16 = PTR_SEG_TO_LIN(EDX_reg(context));
-        struct ThunkDataSL *td = SL16->fpData;
-
-        extern void CallFrom16_t_long_(void);
-        DWORD procAddress = (DWORD)GetProcAddress16(GetModuleHandle16("KERNEL"), 631);
-        WORD cs;
-        GET_CS(cs);
-
-        if (!td)
-        {
-            ERR(thunk, "ThunkConnect16 was not called!\n");
-            return;
-        }
-
-        TRACE(thunk, "Creating stub for ThunkDataSL %08lx\n", (DWORD)td);
-
-
-        /* We produce the following code:
-         *
-         *   xor eax, eax
-         *   mov edx, $td
-         *   call C16ThkSL01
-         *   push bp
-         *   push edx
-         *   call __FLATCS:CallFrom16_t_long_
-         */
-
-        *x++ = 0x66; *x++ = 0x33; *x++ = 0xC0;
-        *x++ = 0x66; *x++ = 0xBA; *((DWORD *)x)++ = (DWORD)td;
-        *x++ = 0x9A; *((DWORD *)x)++ = procAddress;
-
-        *x++ = 0x55;
-        *x++ = 0x66; *x++ = 0x52;
-        *x++ = 0x66; *x++ = 0x9A; *((DWORD *)x)++ = (DWORD)CallFrom16_t_long_;
-                                  *((WORD *)x)++ = cs;
-        
-        /* Jump to the stub code just created */
-        IP_reg(context) = LOWORD(EAX_reg(context));
-        CS_reg(context) = HIWORD(EAX_reg(context));
-
-        /* Since C16ThkSL01 got called by a jmp, we need to leave the
-           orginal return address on the stack */
-        SP_reg(context) -= 4;
-    }
-    else
-    { 
-        struct ThunkDataSL *td = (struct ThunkDataSL *)EDX_reg(context);
-        DWORD targetNr = CX_reg(context) / 4;
-        struct SLTargetDB *tdb;
-
-        TRACE(thunk, "Process %08lx calling target %ld of ThunkDataSL %08lx\n", 
-                     (DWORD)PROCESS_Current(), targetNr, (DWORD)td);
-
-        for (tdb = td->targetDB; tdb; tdb = tdb->next)
-            if (tdb->process == PROCESS_Current())
-                break;
-
-        if (!tdb)
-        {
-            TRACE(thunk, "Loading 32-bit library %s\n", td->pszDll32);
-            LoadLibrary32A(td->pszDll32);
-
-            for (tdb = td->targetDB; tdb; tdb = tdb->next)
-                if (tdb->process == PROCESS_Current())
-                    break;
-        }
-
-        if (tdb)
-        {
-            EDX_reg(context) = tdb->targetTable[targetNr];
-
-            TRACE(thunk, "Call target is %08lx\n", EDX_reg(context));
-        }
-        else
-        {
-            WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
-            DX_reg(context) = HIWORD(td->apiDB[targetNr].errorReturnValue);
-            AX_reg(context) = LOWORD(td->apiDB[targetNr].errorReturnValue);
-            IP_reg(context) = stack[2];
-            CS_reg(context) = stack[3];
-            SP_reg(context) += td->apiDB[targetNr].nrArgBytes + 4;
-
-            /* Win95 allows delayed loading of the 32-bit DLL.
-               We don't do that at the moment. */
-            ERR(thunk, "Process %08lx did not ThunkConnect32 %s to %s\n", 
-                       (DWORD)PROCESS_Current(), td->pszDll32, td->pszDll16);
-        }
-    }
-}
-
-
-/***********************************************************************
  *           K32Thk1632Prolog			(KERNEL32.492)
  */
-VOID WINAPI K32Thk1632Prolog(CONTEXT *context)
+REGS_ENTRYPOINT(K32Thk1632Prolog)
 {
    LPBYTE code = (LPBYTE)EIP_reg(context) - 5;
 
@@ -1463,7 +1126,7 @@
 /***********************************************************************
  *           K32Thk1632Epilog			(KERNEL32.491)
  */
-VOID WINAPI K32Thk1632Epilog(CONTEXT *context)
+REGS_ENTRYPOINT(K32Thk1632Epilog)
 {
    LPBYTE code = (LPBYTE)EIP_reg(context) - 13;
 
@@ -1492,3 +1155,11 @@
                    EBP_reg(context), ESP_reg(context), thdb->cur_stack);
    }
 }
+
+/***********************************************************************
+ *           VxDCall			(KERNEL32.1-8)
+ */
+DWORD WINAPI VxDCall(DWORD x) {
+	FIXME(vxd,"(0x%08lx), stub!\n",x);
+	return 0xffffffff;
+}
diff --git a/win32/newfns.c b/win32/newfns.c
index a8c0a63..376f4a1 100644
--- a/win32/newfns.c
+++ b/win32/newfns.c
@@ -7,7 +7,6 @@
 /* Misc. new functions - they should be moved into appropriate files
 at a later date. */
 
-#include <stdio.h>
 #include <string.h>
 #include <sys/time.h>
 #include <unistd.h>
@@ -28,7 +27,7 @@
                       /*FARPROC*/ LPVOID pfnUT32CallBack,
                       LPVOID lpBuff)
 {
-    fprintf(stderr, "UTRegister(%#x,...): stub!\n",hModule);
+    FIXME(updown, "(%#x,...): stub\n",hModule);
     return TRUE;
 }
 
@@ -37,7 +36,7 @@
  */
 BOOL32 WINAPI UTUnRegister(HMODULE32 hModule)
 {
-    fprintf(stderr, "UTUnRegister(%#x: stub!\n", hModule);
+    FIXME(updown, "(%#x...): stub\n", hModule);
     return TRUE;
 }
 
@@ -66,6 +65,11 @@
 	return FALSE;
 }
 
+BOOL32 WINAPI FindCloseChangeNotification(HANDLE32 fcnhandle) {
+	FIXME(file,"(%08x): stub!\n",fcnhandle);
+	return FALSE;
+}
+
 /****************************************************************************
  *		QueryPerformanceFrequency (KERNEL32.565)
  */
@@ -357,3 +361,8 @@
     return TRUE;
 }
 
+
+BOOL32 WINAPI EnumPorts32A(LPSTR name,DWORD level,LPBYTE ports,DWORD bufsize,LPDWORD bufneeded,LPDWORD bufreturned) {
+	FIXME(win32,"(%s,%d,%p,%d,%p,%p), stub!\n",name,level,ports,bufsize,bufneeded,bufreturned);
+	return FALSE;
+}
diff --git a/win32/ordinals.c b/win32/ordinals.c
index c50bac5..e0e08f7 100644
--- a/win32/ordinals.c
+++ b/win32/ordinals.c
@@ -4,7 +4,6 @@
  * Copyright 1997 Marcus Meissner
  */
 
-#include <stdio.h>
 #include "thread.h"
 #include "winerror.h"
 #include "heap.h"
@@ -32,8 +31,53 @@
 }
 
 /***********************************************
+ *           _ConfirmWin16Lock    (KERNEL32.96)
+ */
+DWORD _ConfirmWin16Lock(void)
+{
+    FIXME(win32, "()\n");
+    return 1;
+}
+
+/***********************************************
+ *           _EnterSysLevel    (KERNEL32.97)
+ */
+VOID _EnterSysLevel(CRITICAL_SECTION *lock)
+{
+    FIXME(win32, "(%p)\n", lock);
+}
+
+/***********************************************
+ *           _EnterSysLevel    (KERNEL32.98)
+ */
+VOID _LeaveSysLevel(CRITICAL_SECTION *lock)
+{
+    FIXME(win32, "(%p)\n", lock);
+}
+
+/***********************************************
+ *           ReleaseThunkLock    (KERNEL32.48)
+ */
+VOID ReleaseThunkLock(DWORD *mutex_count)
+{
+    _LeaveSysLevel(&Win16Mutex);
+
+    *mutex_count = (DWORD) NtCurrentTeb()->mutex_count;
+    NtCurrentTeb()->mutex_count = 0xFFFF;
+}
+
+/***********************************************
+ *           RestoreThunkLock    (KERNEL32.49)
+ */
+VOID RestoreThunkLock(DWORD mutex_count)
+{
+    NtCurrentTeb()->mutex_count = (WORD)mutex_count;
+
+    _EnterSysLevel(&Win16Mutex);
+}
+
+/***********************************************
  *           GetPK16SysVar    (KERNEL32.92)
- * Return the infamous Win16Mutex.
  */
 LPVOID WINAPI GetPK16SysVar(void)
 {
@@ -65,7 +109,7 @@
 	TDB	*pTask;
 
 	action+=56;
-	fprintf(stderr,"KERNEL32_18(%ld,%ld+0x38)\n",processid,action);
+	TRACE(win32,"(%ld,%ld+0x38)\n",processid,action);
 	if (!process || action>56)
 		return 0;
 	switch (action) {
@@ -121,7 +165,7 @@
 	case 56:/* unexplored */
 		return 0;
 	default:
-		fprintf(stderr,"_KERNEL32_18:unknown offset (%ld)\n",action);
+		WARN(win32,"Unknown offset (%ld)\n",action);
 		return 0;
 	}
 	/* shouldn't come here */
@@ -134,17 +178,17 @@
  */
 DWORD WINAPI GetWin16DOSEnv()
 {
-	fprintf(stderr,"GetWin16DOSEnv(), STUB returning 0\n");
+	FIXME(dosmem,"stub, returning 0\n");
 	return 0;
 }
 
 BOOL32 WINAPI _KERNEL32_100(HANDLE32 threadid,DWORD exitcode,DWORD x) {
-	fprintf(stderr,"KERNEL32_100(%d,%ld,0x%08lx),stub\n",threadid,exitcode,x);
+	FIXME(thread,"(%d,%ld,0x%08lx): stub\n",threadid,exitcode,x);
 	return TRUE;
 }
 
 DWORD WINAPI _KERNEL32_99(DWORD x) {
-	fprintf(stderr,"KERNEL32_99(0x%08lx),stub\n",x);
+	FIXME(win32,"(0x%08lx): stub\n",x);
 	return 1;
 }
 
diff --git a/win32/process.c b/win32/process.c
index 15d2734..c4c1635 100644
--- a/win32/process.c
+++ b/win32/process.c
@@ -4,7 +4,6 @@
  * Copyright 1995 Martin von Loewis
  */
 
-#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <sys/times.h>
@@ -68,7 +67,8 @@
 	if (!thdb) 
 		return FALSE;
 	if (dwThreadAffinityMask!=1) {
-		fprintf(stderr,"SetThreadAffinityMask(%d,%ld), only 1 processor supported.\n",(int)hThread,dwThreadAffinityMask);
+		WARN(thread,"(%d,%ld): only 1 processor supported.\n",
+                    (int)hThread,dwThreadAffinityMask);
 		K32OBJ_DecCount((K32OBJ*)thdb);
 		return FALSE;
 	}
@@ -76,6 +76,9 @@
 	return TRUE;
 }
 
+/**********************************************************************
+ *  CreateProcess32A [KERNEL32.171]
+ */
 BOOL32 WINAPI CreateProcess32A(
 	LPCSTR appname,LPSTR cmdline,LPSECURITY_ATTRIBUTES processattributes,
         LPSECURITY_ATTRIBUTES threadattributes,BOOL32 inherithandles,
@@ -96,13 +99,16 @@
 #endif
 }
 
+/**********************************************************************
+ *  CreateProcess32W [KERNEL32.172]
+ */
 BOOL32 WINAPI CreateProcess32W(
 	LPCWSTR appname,LPWSTR cmdline,LPSECURITY_ATTRIBUTES processattributes,
         LPSECURITY_ATTRIBUTES threadattributes,BOOL32 inherithandles,
 	DWORD creationflags,LPVOID env,LPCWSTR curdir,
 	LPSTARTUPINFO32W startupinfo,LPPROCESS_INFORMATION processinfo)
 {
-    fprintf(stderr,"CreateProcessW(%p,%p,%p,%p,%d,%08lx,%p,%p,%p,%p) stub\n",
+    FIXME(win32,"(%p,%p,%p,%p,%d,%08lx,%p,%p,%p,%p): stub\n",
             appname,cmdline,processattributes,threadattributes,
             inherithandles,creationflags,env,curdir,startupinfo,processinfo );
     /* make from lcc uses system as fallback if CreateProcess returns
@@ -110,8 +116,11 @@
     return FALSE;
 }
 
+/**********************************************************************
+ *  ContinueDebugEvent [KERNEL32.146]
+ */
 BOOL32 WINAPI ContinueDebugEvent(DWORD pid,DWORD tid,DWORD contstatus) {
-	fprintf(stderr,"ContinueDebugEvent(%ld,%ld,%ld) stub\n",pid,tid,contstatus);
+    FIXME(win32,"(%ld,%ld,%ld): stub\n",pid,tid,contstatus);
 	return TRUE;
 }
 
diff --git a/win32/security.c b/win32/security.c
index acfec87..96a9496 100644
--- a/win32/security.c
+++ b/win32/security.c
@@ -1,4 +1,3 @@
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
diff --git a/win32/struct32.c b/win32/struct32.c
index 19b7a36..35cc01b 100644
--- a/win32/struct32.c
+++ b/win32/struct32.c
@@ -4,7 +4,6 @@
  * Copyright 1996 Martin von Loewis
  */
 
-#include <stdio.h>
 #include "windows.h"
 #include "winerror.h"
 #include "struct32.h"
diff --git a/win32/thread.c b/win32/thread.c
index ff0b824..cdf46ab 100644
--- a/win32/thread.c
+++ b/win32/thread.c
@@ -5,7 +5,6 @@
  * Copyright 1997 Onno Hovers
  */
 
-#include <stdio.h>
 #include <unistd.h>
 #include <string.h>
 #include "windows.h"
diff --git a/win32/user32.c b/win32/user32.c
index a37c599..2a1fda1 100644
--- a/win32/user32.c
+++ b/win32/user32.c
@@ -8,7 +8,6 @@
    stubs. 'Real' implementations go into context specific files */
 
 #include <unistd.h>
-#include <stdio.h>
 #include <stdarg.h>
 #include "windows.h"
 #include "winerror.h"
diff --git a/windows/class.c b/windows/class.c
index fa5504e..b33606d 100644
--- a/windows/class.c
+++ b/windows/class.c
@@ -9,7 +9,6 @@
  */
 
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include "class.h"
 #include "heap.h"
@@ -37,15 +36,14 @@
 
     if (ptr->magic != CLASS_MAGIC)
     {
-        fprintf( stderr, "%p is not a class\n", ptr );
+        DUMP("%p is not a class\n", ptr );
         return;
     }
 
     GlobalGetAtomName32A( ptr->atomName, className, sizeof(className) );
 
-    fprintf( stderr, "Class %p:\n", ptr );
-    fprintf( stderr,
-             "next=%p  name=%04x '%s'  style=%08x  wndProc=%08x\n"
+    DUMP( "Class %p:\n", ptr );
+    DUMP( "next=%p  name=%04x '%s'  style=%08x  wndProc=%08x\n"
              "inst=%04x  dce=%08x  icon=%04x  cursor=%04x  bkgnd=%04x\n"
              "clsExtra=%d  winExtra=%d  #windows=%d\n",
              ptr->next, ptr->atomName, className, ptr->style,
@@ -54,12 +52,12 @@
              ptr->cbClsExtra, ptr->cbWndExtra, ptr->cWindows );
     if (ptr->cbClsExtra)
     {
-        fprintf( stderr, "extra bytes:" );
+        DUMP( "extra bytes:" );
         for (i = 0; i < ptr->cbClsExtra; i++)
-            fprintf( stderr, " %02x", *((BYTE *)ptr->wExtra+i) );
-        fprintf( stderr, "\n" );
+            DUMP( " %02x", *((BYTE *)ptr->wExtra+i) );
+        DUMP( "\n" );
     }
-    fprintf( stderr, "\n" );
+    DUMP( "\n" );
 }
 
 
@@ -73,14 +71,14 @@
     CLASS *ptr;
     char className[80];
 
-    fprintf( stderr, " Class   Name                  Style   WndProc\n" );
+    DUMP( " Class   Name                  Style   WndProc\n" );
     for (ptr = firstClass; ptr; ptr = ptr->next)
     {
         GlobalGetAtomName32A( ptr->atomName, className, sizeof(className) );
-        fprintf( stderr, "%08x %-20.20s %08x %08x\n", (UINT32)ptr, className,
+        DUMP( "%08x %-20.20s %08x %08x\n", (UINT32)ptr, className,
                  ptr->style, (UINT32)ptr->winproc );
     }
-    fprintf( stderr, "\n" );
+    DUMP( "\n" );
 }
 
 
@@ -173,7 +171,7 @@
         if (*ppClass == classPtr) break;
     if (!*ppClass)
     {
-        fprintf(stderr, "ERROR: Class list corrupted\n" );
+        ERR( class, "Class list corrupted\n" );
         return FALSE;
     }
     *ppClass = classPtr->next;
@@ -265,10 +263,10 @@
 
     if (classExtra < 0) classExtra = 0;
     else if (classExtra > 40)  /* Extra bytes are limited to 40 in Win32 */
-        fprintf(stderr, "Warning: class extra bytes %d is > 40\n", classExtra);
+        WARN(class, "Class extra bytes %d is > 40\n", classExtra);
     if (winExtra < 0) winExtra = 0;
     else if (winExtra > 40)    /* Extra bytes are limited to 40 in Win32 */
-        fprintf( stderr, "Warning: win extra bytes %d is > 40\n", winExtra );
+        WARN(class, "Win extra bytes %d is > 40\n", winExtra );
 
     /* Create the class */
 
@@ -585,7 +583,7 @@
         case GCW_HMODULE:
             return (WORD)GetClassLong32A( hwnd, offset );
     }
-    fprintf(stderr, "Warning: invalid offset %d for GetClassWord()\n", offset);
+    WARN(class, "Invalid offset %d\n", offset);
     return 0;
 }
 
@@ -641,7 +639,7 @@
         case GCL_HICONSM:
             return GetClassWord32( hwnd, offset );
     }
-    fprintf(stderr, "Warning: invalid offset %d for GetClassLong()\n", offset);
+    WARN(class, "Invalid offset %d\n", offset);
     return 0;
 }
 
@@ -692,8 +690,7 @@
             ptr = ((char *)wndPtr->class->wExtra) + offset;
         else
         {
-            fprintf( stderr, "Warning: invalid offset %d for SetClassWord()\n",
-                     offset );
+            WARN( class, "Invalid offset %d\n", offset );
             return 0;
         }
     }
@@ -710,8 +707,7 @@
         case GCW_HICONSM:       ptr = &wndPtr->class->hIconSm; break;
         case GCW_ATOM:          ptr = &wndPtr->class->atomName; break;
         default:
-            fprintf( stderr, "Warning: invalid offset %d for SetClassWord()\n",
-                     offset);
+            WARN( class, "Invalid offset %d\n", offset);
             return 0;
     }
     retval = GET_WORD(ptr);
@@ -760,8 +756,7 @@
             ptr = ((char *)wndPtr->class->wExtra) + offset;
         else
         {
-            fprintf( stderr, "Warning: invalid offset %d for SetClassLong()\n",
-                     offset );
+            WARN( class, "Invalid offset %d\n", offset );
             return 0;
         }
     }
@@ -786,8 +781,7 @@
         case GCL_CBCLSEXTRA: ptr = &wndPtr->class->cbClsExtra; break;
         case GCL_HMODULE:    ptr = &wndPtr->class->hInstance; break;
         default:
-            fprintf( stderr, "Warning: invalid offset %d for SetClassLong()\n",
-                     offset);
+            WARN( class, "Invalid offset %d\n", offset );
             return 0;
     }
     retval = GET_DWORD(ptr);
diff --git a/windows/clipboard.c b/windows/clipboard.c
index ed04c6d..8b0a51d 100644
--- a/windows/clipboard.c
+++ b/windows/clipboard.c
@@ -7,7 +7,6 @@
  */
 
 #include <stdlib.h>
-#include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -442,7 +441,7 @@
  */
 HANDLE32 WINAPI SetClipboardData32( UINT32 wFormat, HANDLE32 hData )
 {
-    fprintf( stderr, "SetClipboardData: empty stub\n" );
+    FIXME(clipboard, "(%d,%d): stub\n", wFormat, hData );
     return 0;
 }
 
@@ -547,7 +546,7 @@
  */
 HANDLE32 WINAPI GetClipboardData32( UINT32 wFormat )
 {
-    fprintf( stderr, "GetClipboardData32: empty stub\n" );
+    FIXME(clipboard, "(%d): stub\n", wFormat );
     return 0;
 }
 
@@ -866,8 +865,7 @@
  */
 INT16 WINAPI GetPriorityClipboardFormat16( UINT16 *lpPriorityList, INT16 nCount)
 {
-    fprintf( stderr, "GetPriorityClipboardFormat16(%p, %d): stub\n",
-             lpPriorityList, nCount );
+    FIXME(clipboard, "(%p,%d): stub\n", lpPriorityList, nCount );
     return 0;
 }
 
diff --git a/windows/defwnd.c b/windows/defwnd.c
index bdd35fb..ec0ade8 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -6,7 +6,6 @@
  */
 
 #include <stdlib.h>
-#include <stdio.h>
 #include "win.h"
 #include "user.h"
 #include "heap.h"
diff --git a/windows/dialog.c b/windows/dialog.c
index a1b67f9..53e891e 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -8,7 +8,6 @@
 #include <errno.h>
 #include <limits.h>
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include <errno.h>
 #include "windows.h"
@@ -298,7 +297,7 @@
                     dlgInfo->hDialogHeap = GlobalAlloc16(GMEM_FIXED, 0x10000);
                     if (!dlgInfo->hDialogHeap)
                     {
-                        fprintf( stderr, "CreateDialogIndirectParam: Insufficient memory to create heap for edit control\n" );
+                        ERR(dialog, "Insufficient memory to create heap for edit control\n" );
                         continue;
                     }
                     LocalInit(dlgInfo->hDialogHeap, 0, 0xffff);
diff --git a/windows/dinput.c b/windows/dinput.c
index e034aeb..c2c72d4 100644
--- a/windows/dinput.c
+++ b/windows/dinput.c
@@ -15,7 +15,6 @@
  */
 
 #include "config.h"
-#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <assert.h>
@@ -41,8 +40,11 @@
 static IDirectInputDeviceA_VTable SysKeyboardAvt;
 static IDirectInputDeviceA_VTable SysMouseAvt;
 
+/******************************************************************************
+ *	DirectInputCreate32A
+ */
 HRESULT WINAPI DirectInputCreate32A(HINSTANCE32 hinst, DWORD dwVersion, LPDIRECTINPUT32A *ppDI, LPUNKNOWN punkOuter) {
-	fprintf(stderr,"DirectInputCreate32A(0x%08lx,%04lx,%p,%p)\n",
+	TRACE(dinput, "(0x%08lx,%04lx,%p,%p)\n",
 		(DWORD)hinst,dwVersion,ppDI,punkOuter
 	);
 	(*ppDI) = (LPDIRECTINPUT32A)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInput32A));
@@ -51,13 +53,13 @@
 	return 0;
 }
 /******************************************************************************
- *		IDirectInputA
+ *	IDirectInputA_EnumDevices
  */
 static HRESULT WINAPI IDirectInputA_EnumDevices(
 	LPDIRECTINPUT32A this,DWORD dwFlags,LPDIENUMDEVICESCALLBACK32A cb,
 	LPVOID context,DWORD x
 ) {
-	fprintf(stderr,"IDirectInputA(%p)->EnumDevices(0x%08lx,%p,%p,0x%08lx),stub!\n",this,dwFlags,cb,context,x);
+	FIXME(dinput,"(this=%p,0x%08lx,%p,%p,0x%08lx): stub\n",this,dwFlags,cb,context,x);
 	return 0;
 }
 
@@ -80,7 +82,7 @@
 	char	xbuf[50];
 	
 	WINE_StringFromCLSID(rguid,xbuf);
-	fprintf(stderr,"IDirectInputA(%p)->CreateDevice(%s,%p,%p),stub!\n",this,xbuf,pdev,punk);
+	FIXME(dinput,"(this=%p,%s,%p,%p): stub\n",this,xbuf,pdev,punk);
 	if (!memcmp(&GUID_SysKeyboard,rguid,sizeof(GUID_SysKeyboard))) {
 		*pdev = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboard32A));
 		(*pdev)->ref = 1;
@@ -105,7 +107,7 @@
 	char	xbuf[50];
 
 	WINE_StringFromCLSID(riid,xbuf);
-	fprintf(stderr,"IDirectInputA(%p)->QueryInterface(%s,%p)\n",this,xbuf,ppobj);
+	TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ppobj);
 	if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
 		this->lpvtbl->fnAddRef(this);
 		*ppobj = this;
@@ -144,13 +146,13 @@
 ) {
 	/*
 	int i;
-	fprintf(stderr,"IDirectInputDeviceA(%p)->SetDataFormat(%p)\n",this,df);
+	TRACE(dinput,"(this=%p,%p)\n",this,df);
 
-	fprintf(stderr,"df.dwSize %ld\n",df->dwSize);
-	fprintf(stderr,"df.dwObjsize %ld\n",df->dwObjSize);
-	fprintf(stderr,"df.dwFlags 0x%08lx\n",df->dwFlags);
-	fprintf(stderr,"df.dwDataSize %ld\n",df->dwDataSize);
-	fprintf(stderr,"df.dwNumObjs %ld\n",df->dwNumObjs);
+	TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
+	TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
+	TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
+	TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
+	TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
 
 	for (i=0;i<df->dwNumObjs;i++) {
 		char	xbuf[50];
@@ -159,10 +161,10 @@
 			WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
 		else
 			strcpy(xbuf,"<no guid>");
-		fprintf(stderr,"df.rgodf[%d].guid %s\n",i,xbuf);
-		fprintf(stderr,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
-		fprintf(stderr,"	dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
-		fprintf(stderr,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
+		TRACE(dinput,"df.rgodf[%d].guid %s\n",i,xbuf);
+		TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
+		TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
+		TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
 	}
 	*/
 	return 0;
@@ -171,7 +173,7 @@
 static HRESULT WINAPI IDirectInputDeviceA_SetCooperativeLevel(
 	LPDIRECTINPUTDEVICE32A this,HWND32 hwnd,DWORD dwflags
 ) {
-	fprintf(stderr,"IDirectInputDeviceA(%p)->SetCooperativeLevel(0x%08lx,0x%08lx)\n",this,(DWORD)hwnd,dwflags);
+	FIXME(dinput,"(this=%p,0x%08lx,0x%08lx): stub\n",this,(DWORD)hwnd,dwflags);
 	return 0;
 }
 
@@ -184,17 +186,17 @@
 		WINE_StringFromCLSID(rguid,xbuf);
 	else
 		sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
-	fprintf(stderr,"IDirectInputDeviceA(%p)->SetProperty(%s,%p)\n",this,xbuf,ph);
+	TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ph);
 	if (!HIWORD(rguid)) {
 		switch ((DWORD)rguid) {
 		case DIPROP_BUFFERSIZE: {
 			LPCDIPROPDWORD	pd = (LPCDIPROPDWORD)ph;
 
-			fprintf(stderr,"	buffersize = %ld\n",pd->dwData);
+			TRACE(dinput,"buffersize = %ld\n",pd->dwData);
 			break;
 		}
 		default:
-			fprintf(stderr,"	unknown type %ld\n",(DWORD)rguid);
+			WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
 			break;
 		}
 	}
@@ -204,7 +206,7 @@
 static HRESULT WINAPI IDirectInputDeviceA_SetEventNotification(
 	LPDIRECTINPUTDEVICE32A this,HANDLE32 hnd
 ) {
-	fprintf(stderr,"IDirectInputDeviceA(%p)->SetEventNotification(0x%08lx)\n",this,(DWORD)hnd);
+	FIXME(dinput,"(this=%p,0x%08lx): stub\n",this,(DWORD)hnd);
 	return 0;
 }
 
@@ -212,18 +214,18 @@
 	LPDIRECTINPUTDEVICE32A this,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
 	LPDWORD entries,DWORD flags
 ) {
-/*	fprintf(stderr,"IDirectInputDeviceA(%p)->GetDeviceData(%ld,%p,%p(0x%08lx),0x%08lx)\n",this,dodsize,dod,entries,*entries,flags);*/
+/*	TRACE(dinput,"IDirectInputDeviceA(%p)->GetDeviceData(%ld,%p,%p(0x%08lx),0x%08lx)\n",this,dodsize,dod,entries,*entries,flags);*/
 	return 0;
 }
 
 
 static HRESULT WINAPI IDirectInputDeviceA_Acquire(LPDIRECTINPUTDEVICE32A this) {
-	fprintf(stderr,"IDirectInputDeviceA(%p)->Aquire()\n",this);
+	FIXME(dinput,"(this=%p): stub\n",this);
 	return 0;
 }
 
 static HRESULT WINAPI IDirectInputDeviceA_Unacquire(LPDIRECTINPUTDEVICE32A this) {
-	fprintf(stderr,"IDirectInputDeviceA(%p)->Unaquire()\n",this);
+	FIXME(dinput,"(this=%p): stub\n",this);
 	return 0;
 }
 
@@ -244,18 +246,19 @@
 		WINE_StringFromCLSID(rguid,xbuf);
 	else
 		sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
-	fprintf(stderr,"SysKeyboardA(%p)->SetProperty(%s,%p)\n",this,xbuf,ph);
-	fprintf(stderr,"	size is %ld, headersize is %ld,obj is %ld,how is %ld\n",ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
+	TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ph);
+	TRACE(dinput,"(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
+            ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
 	if (!HIWORD(rguid)) {
 		switch ((DWORD)rguid) {
 		case DIPROP_BUFFERSIZE: {
 			LPCDIPROPDWORD	pd = (LPCDIPROPDWORD)ph;
 
-			fprintf(stderr,"	buffersize = %ld\n",pd->dwData);
+			TRACE(dinput,"(buffersize=%ld)\n",pd->dwData);
 			break;
 		}
 		default:
-			fprintf(stderr,"	unknown type %ld\n",(DWORD)rguid);
+			WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
 			break;
 		}
 	}
@@ -276,7 +279,7 @@
 			}
 		return 0;
 	}
-	fprintf(stderr,"whoops, SysKeyboardA_GetDeviceState got len %ld?\n",len);
+	WARN(dinput,"whoops, SysKeyboardA_GetDeviceState got len %ld?\n",len);
 	return 0;
 }
 
@@ -287,7 +290,8 @@
 	int			i,n,xentries;
 	LPSYSKEYBOARD32A	kthis = (LPSYSKEYBOARD32A)this;
 
-/*	fprintf(stderr,"SysKeyboardA(%p)->GetDeviceData(%ld,%p,%p(%ld),0x%08lx)\n",this,dodsize,dod,entries,entries?*entries:0,flags);*/
+	TRACE(dinput,"(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
+    		this,dodsize,dod,entries,entries?*entries:0,flags);
 	if (entries)
 		xentries = *entries; 
 	else
@@ -312,12 +316,12 @@
 }
 
 static HRESULT WINAPI SysKeyboardA_Acquire(LPDIRECTINPUTDEVICE32A this) {
-	fprintf(stderr,"SysKeyboardA(%p)->Aquire()\n",this);
+	FIXME(dinput,"(this=%p): stub\n",this);
 	return 0;
 }
 
 static HRESULT WINAPI SysKeyboardA_Unacquire(LPDIRECTINPUTDEVICE32A this) {
-	fprintf(stderr,"SysKeyboardA(%p)->Unaquire()\n",this);
+	FIXME(dinput,"(this=%p): stub\n",this);
 	return 0;
 }
 
@@ -325,9 +329,7 @@
 static HRESULT WINAPI IDirectInputDeviceA_GetDeviceState(
 	LPDIRECTINPUTDEVICE32A this,DWORD len,LPVOID ptr
 ) {
-	fprintf(stderr,"IDirectInputDeviceA(%p)->GetDeviceState(0x%08lx,%p)\n",
-		this,len,ptr
-	);
+	FIXME(dinput,"(this=%p,0x%08lx,%p): stub\n",this,len,ptr);
 	return 0;
 }
 
@@ -337,7 +339,7 @@
 	char	xbuf[50];
 
 	WINE_StringFromCLSID(riid,xbuf);
-	fprintf(stderr,"IDirectInputA(%p)->QueryInterface(%s,%p)\n",this,xbuf,ppobj);
+	TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ppobj);
 	if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
 		this->lpvtbl->fnAddRef(this);
 		*ppobj = this;
diff --git a/windows/driver.c b/windows/driver.c
index a051bd9..79333fa 100644
--- a/windows/driver.c
+++ b/windows/driver.c
@@ -4,7 +4,6 @@
  * Copyright 1994 Martin Ayotte
 */
 
-#include <stdio.h>
 #include "windows.h"
 #include "win.h"
 #include "callback.h"
@@ -14,7 +13,10 @@
 
 LPDRIVERITEM lpDrvItemList = NULL;
 
-void LoadStartupDrivers(void)
+/**************************************************************************
+ *	LoadStartupDrivers
+ */
+static void LoadStartupDrivers(void)
 {
     HDRVR16 hDrv;
     char  str[256];
@@ -23,8 +25,7 @@
     if (GetPrivateProfileString32A( "drivers", NULL, "", str, sizeof(str),
 				 "SYSTEM.INI" ) < 2)
     {
-    	fprintf( stderr,
-		 "LoadStartupDrivers // can't find drivers section in system.ini\n" );
+    	ERR( driver,"Can't find drivers section in system.ini\n" );
 	return;
     }
 
diff --git a/windows/event.c b/windows/event.c
index 3877a0e..3257d3d 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -8,7 +8,6 @@
 #include <assert.h>
 #include <ctype.h>
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <sys/time.h>
@@ -39,6 +38,7 @@
 #include "keyboard.h"
 #include "debug.h"
 #include "dde_proc.h"
+#include "winsock.h"
 
 
 #define NB_BUTTONS      3     /* Windows can handle 3 buttons */
@@ -106,10 +106,6 @@
 static void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event );
 */
 
-extern void FOCUS_SetXFocus( HWND32 );
-extern BOOL16 DRAG_QueryUpdate( HWND16, SEGPTR, BOOL32 );
-extern BOOL32 WINSOCK_HandleIO( int* max_fd, int num_pending, fd_set p[3], fd_set e[3] );
-
 /***********************************************************************
  *           EVENT_Init
  *
@@ -130,13 +126,13 @@
 /***********************************************************************
  *          EVENT_AddIO 
  */
-void EVENT_AddIO( int fd, int io_type )
+void EVENT_AddIO( int fd, unsigned io_type )
 {
     FD_SET( fd, &__event_io_set[io_type] );
     if( __event_max_fd <= fd ) __event_max_fd = fd + 1;
 }
 
-void EVENT_DeleteIO( int fd, int io_type )
+void EVENT_DeleteIO( int fd, unsigned io_type )
 {
     FD_CLR( fd, &__event_io_set[io_type] );
 }
diff --git a/windows/keyboard.c b/windows/keyboard.c
index 06de1f7..1e20339 100644
--- a/windows/keyboard.c
+++ b/windows/keyboard.c
@@ -4,11 +4,11 @@
  * Copyright 1993 Bob Amstadt
  * Copyright 1996 Albrecht Kleine 
  * Copyright 1997 David Faure
+ * Copyright 1998 Morten Welinder
  *
  */
 
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include <X11/keysym.h>
@@ -209,7 +209,7 @@
     e2.display = display;
     e2.state = 0;
 
-    OEMvkey = 0xb9; /* first OEM virtual key available is ba */
+    OEMvkey = VK_OEM_7; /* next is available.  */
     for (e2.keycode=min_keycode; e2.keycode<=max_keycode; e2.keycode++)
     {
         TSXLookupString(&e2, NULL, 0, &keysym, NULL);
@@ -270,6 +270,25 @@
 		    vkey = keysym;
             }
 
+            for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
+            {
+                keysym = TSXLookupKeysym(&e2, i);
+		switch (keysym)
+		{
+		case ';': case ':':   vkey = VK_OEM_1; break;
+		case '/': case '?':   vkey = VK_OEM_2; break;
+		case '`': case '~':   vkey = VK_OEM_3; break;
+		case '[':             vkey = VK_OEM_4; break;
+		case '\\':            vkey = VK_OEM_5; break;
+		case ']':             vkey = VK_OEM_6; break;
+		case '\'': case '\"': vkey = VK_OEM_7; break;
+		case ',':             vkey = VK_OEM_COMMA; break;
+		case '.':             vkey = VK_OEM_PERIOD; break;
+		case '-':             vkey = VK_OEM_MINUS; break;
+		case '+':             vkey = VK_OEM_PLUS; break;
+		}
+	    }
+
             if (!vkey)
             {
                 /* Others keys: let's assign OEM virtual key codes in the allowed range,
@@ -278,7 +297,7 @@
                 {
                 case 0xc1 : OEMvkey=0xdb; break;
                 case 0xe5 : OEMvkey=0xe9; break;
-                case 0xf6 : OEMvkey=0xf5; fprintf(stderr,"No more OEM vkey available!\n");
+                case 0xf6 : OEMvkey=0xf5; WARN(keyboard,"No more OEM vkey available!\n");
                 }
 
                 vkey = OEMvkey;
@@ -287,8 +306,8 @@
                 {
 		    dbg_decl_str(keyboard, 1024);
 
-                    TRACE(keyboard, "OEM specific virtual key %X assigned"
-				 "to keycode %X :\n", OEMvkey, e2.keycode);
+                    TRACE(keyboard, "OEM specific virtual key %X assigned "
+				 "to keycode %X:\n", OEMvkey, e2.keycode);
                     for (i = 0; i < keysyms_per_keycode; i += 1)
                     {
                         char	*ksname;
@@ -864,11 +883,11 @@
 	      if (TSXKeycodeToKeysym(display,keycode,i)==keysym) index=i;
 	    switch (index) {
 	    case -1 :
-	      fprintf(stderr,"Keysym %lx not found while parsing the keycode table\n",keysym); break;
+	      WARN(keyboard,"Keysym %lx not found while parsing the keycode table\n",keysym); break;
 	    case 0 : break;
 	    case 1 : highbyte = 0x0100; break;
 	    case 2 : highbyte = 0X0600; break;
-	    default : fprintf(stderr,"index %d found by XKeycodeToKeysym. please report! \n",index);
+	    default : ERR(keyboard,"index %d found by XKeycodeToKeysym. please report! \n",index);
 	    }
 	    /*
 	      index : 0     adds 0x0000
@@ -924,7 +943,7 @@
       return 12;   /* We're doing an 101 for now, so return 12 F-keys */
       break;
     default:     
-      fprintf(stderr, "Unknown type on GetKeyboardType\n");
+      WARN(keyboard, "Unknown type\n");
       return 0;    /* The book says 0 here, so 0 */
     }
 }
@@ -987,7 +1006,7 @@
 			return 0;
 			}
 		default: /* reserved */
-			fprintf(stderr, "MapVirtualKey: unknown wMapType %d !\n",
+			WARN(keyboard, "Unknown wMapType %d !\n",
 				wMapType);
 			return 0;	
 	}
@@ -1105,7 +1124,7 @@
       }
     if (!e.keycode)
       {
-	fprintf(stderr,"ToAscii : Unknown virtual key %X !!! \n",virtKey);
+	WARN(keyboard,"Unknown virtual key %X !!! \n",virtKey);
 	return virtKey; /* whatever */
       }
     e.state = 0;
@@ -1228,9 +1247,9 @@
 		ksname = "No Name";
 	    if ((keysym >> 8) != 0xff)
 		{
-		fprintf(stderr, "Please report : no char for keysym %04lX (%s) :\n",
+		ERR(keyboard, "Please report: no char for keysym %04lX (%s) :\n",
 			keysym, ksname);
-		fprintf(stderr, "  virtKey = %X, scanCode = %X, keycode = %X, state = %X\n",
+		ERR(keyboard, "(virtKey=%X,scanCode=%X,keycode=%X,state=%X)\n",
 			virtKey, scanCode, e.keycode, e.state);
 		}
 	    }
@@ -1246,7 +1265,7 @@
  */
 HKL32 WINAPI GetKeyboardLayout(DWORD dwLayout)
 {
-	fprintf(stderr,"GetKeyboardLayout(%ld),STUB!\n",dwLayout);
+	FIXME(keyboard,"(%ld): stub\n",dwLayout);
 	return (0xcafe<<16)|GetSystemDefaultLCID(); /* FIXME */
 }
 
@@ -1256,7 +1275,7 @@
  */
 INT32 WINAPI GetKeyboardLayoutList(INT32 nBuff,HKL32 *layouts)
 {
-	fprintf(stderr,"GetKeyboardLayoutList(%d,%p),STUB!\n",nBuff,layouts);
+	FIXME(keyboard,"(%d,%p): stub\n",nBuff,layouts);
 	if (layouts)
 		layouts[0] = GetKeyboardLayout(0);
 	return 1;
@@ -1267,7 +1286,7 @@
  *           RegisterHotKey			(USER32.433)
  */
 BOOL32 WINAPI RegisterHotKey(HWND32 hwnd,INT32 id,UINT32 modifiers,UINT32 vk) {
-	fprintf(stderr,"RegisterHotKey(%08x,%d,%08x,%d), STUB!\n",
+	FIXME(keyboard,"(%08x,%d,%08x,%d): stub\n",
 		hwnd,id,modifiers,vk
 	);
 	return TRUE;
@@ -1277,6 +1296,6 @@
  *           UnregisterHotKey			(USER32.565)
  */
 BOOL32 WINAPI UnregisterHotKey(HWND32 hwnd,INT32 id) {
-	fprintf(stderr,"UnregisterHotKey(%08x,%d),stub!\n",hwnd,id);
+	FIXME(keyboard,"(%08x,%d): stub\n",hwnd,id);
 	return TRUE;
 }
diff --git a/windows/mdi.c b/windows/mdi.c
index 394b4c3..185c7ce 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -14,7 +14,6 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include <stdio.h>
 #include <math.h>
 #include "windows.h"
 #include "win.h"
diff --git a/windows/message.c b/windows/message.c
index f6bbc0e..ee57696 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -37,8 +37,6 @@
 extern MESSAGEQUEUE *pCursorQueue;			 /* queue.c */
 extern MESSAGEQUEUE *pActiveQueue;
 
-extern void joySendMessages(void);
-
 DWORD MSG_WineStartTicks; /* Ticks at Wine startup */
 
 static UINT32 doubleClickSpeed = 452;
diff --git a/windows/msgbox.c b/windows/msgbox.c
index 5ebf5e2..6c084e4 100644
--- a/windows/msgbox.c
+++ b/windows/msgbox.c
@@ -4,7 +4,6 @@
  * Copyright 1995 Bernd Schmidt
  */
 
-#include <stdio.h>
 #include "windows.h"
 #include "dlgs.h"
 #include "heap.h"
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 752f2cc..8ea40c2 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -75,8 +75,7 @@
                            DWORD exStyle )
 {
     if(TWEAK_Win95Look)
-	fprintf( stddeb, "NC_AdjustRect was called in Win95 mode.  Aiee!  "
-		 "Please report this.\n" );
+	ERR(nonclient, "Called in Win95 mode. Aiee! Please report this.\n" );
 
     if(style & WS_ICONIC) return;
     /* Decide if the window will be managed (see CreateWindowEx) */
@@ -160,12 +159,12 @@
 /***********************************************************************
  *           DrawCaptionTempA    (USER32.599)
  */
-DWORD
-DrawCaptionTemp32A(HWND32 hwnd,HDC32 hdc,LPRECT32 rect,HFONT32 hfont,DWORD x1,LPCSTR str,DWORD x2) {
-	fprintf(stderr,"DrawCaptionTempA(%08x,%08x,%p,%08x,%08lx,\"%s\",%08lx),tub!\n",
-		hwnd,hdc,rect,hfont,x1,str,x2
-	);
-	return 0;
+DWORD DrawCaptionTemp32A(HWND32 hwnd,HDC32 hdc,LPRECT32 rect,
+    HFONT32 hfont,DWORD x1,LPCSTR str,DWORD x2)
+{
+    FIXME(nonclient,"(%08x,%08x,%p,%08x,%08lx,\"%s\",%08lx): stub\n",
+        hwnd,hdc,rect,hfont,x1,str,x2);
+    return 0;
 }
 
 
@@ -669,8 +668,7 @@
     INT32 width, height;
 
     if(TWEAK_Win95Look)
-	fprintf( stddeb, "NC_DrawFrame was called in Win95 mode.  Aiee!  "
-		 "Please report this.\n" );
+	ERR(nonclient, "Called in Win95 mode. Aiee! Please report this.\n" );
 
     if (dlgFrame)
     {
diff --git a/windows/painting.c b/windows/painting.c
index 5bfeed2..d35e991 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -8,7 +8,6 @@
  *	  window coords as well, lookup 'the pain' comment in the winpos.c).
  */
 
-#include <stdio.h>
 #include "win.h"
 #include "queue.h"
 #include "gdi.h"
@@ -135,7 +134,7 @@
 
     if (!lps->hdc)
     {
-        fprintf(stderr, "GetDCEx() failed in BeginPaint(), hwnd=%04x\n", hwnd);
+        WARN(win, "GetDCEx() failed in BeginPaint(), hwnd=%04x\n", hwnd);
         return 0;
     }
 
diff --git a/windows/queue.c b/windows/queue.c
index a34e460..b45bbe2 100644
--- a/windows/queue.c
+++ b/windows/queue.c
@@ -40,12 +40,11 @@
     if (!(pq = (MESSAGEQUEUE*) GlobalLock16( hQueue )) ||
         GlobalSize16(hQueue) < sizeof(MESSAGEQUEUE)+pq->queueSize*sizeof(QMSG))
     {
-        fprintf( stderr, "%04x is not a queue handle\n", hQueue );
+        WARN(msg, "%04x is not a queue handle\n", hQueue );
         return;
     }
 
-    fprintf( stderr,
-             "next: %12.4x  Intertask SendMessage:\n"
+    DUMP(    "next: %12.4x  Intertask SendMessage:\n"
              "hTask: %11.4x  ----------------------\n"
              "msgSize: %9.4x  hWnd: %10.4x\n"
              "msgCount: %8.4x  msg: %11.4x\n"
@@ -75,22 +74,22 @@
     char module[10];
     HQUEUE16 hQueue = hFirstQueue;
 
-    fprintf( stderr, "Queue Size Msgs Task\n" );
+    DUMP( "Queue Size Msgs Task\n" );
     while (hQueue)
     {
         MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( hQueue );
         if (!queue)
         {
-            fprintf( stderr, "*** Bad queue handle %04x\n", hQueue );
+            WARN( msg, "Bad queue handle %04x\n", hQueue );
             return;
         }
         if (!GetModuleName( queue->hTask, module, sizeof(module )))
             strcpy( module, "???" );
-        fprintf( stderr, "%04x %5d %4d %04x %s\n", hQueue, queue->msgSize,
+        DUMP( "%04x %5d %4d %04x %s\n", hQueue, queue->msgSize,
                  queue->msgCount, queue->hTask, module );
         hQueue = queue->next;
     }
-    fprintf( stderr, "\n" );
+    DUMP( "\n" );
 }
 
 
@@ -421,7 +420,7 @@
     if ((pos == msgQueue->nextMessage) && (msgQueue->msgCount > 0))
     {
 	SIGNAL_MaskAsyncEvents( FALSE );
-        fprintf(stderr,"MSG_AddMsg // queue is full !\n");
+        WARN( msg,"Queue is full!\n" );
         return FALSE;
     }
 
diff --git a/windows/scroll.c b/windows/scroll.c
index 885968c..3acef48 100644
--- a/windows/scroll.c
+++ b/windows/scroll.c
@@ -18,9 +18,6 @@
 #include "sysmetrics.h"
 #include "debug.h"
 
-extern HWND32 CARET_GetHwnd();			/* windows/caret.c */
-extern void   CARET_GetRect(LPRECT32);
-extern void CLIPPING_UpdateGCRegion(DC* );	/* objects/clipping.c */
 
 /*************************************************************************
  *             ScrollWindow16   (USER.61)
diff --git a/windows/syscolor.c b/windows/syscolor.c
index 4af477b..c08adc7 100644
--- a/windows/syscolor.c
+++ b/windows/syscolor.c
@@ -9,6 +9,7 @@
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include "debug.h"
 #include "gdi.h"
 #include "tweak.h"
 
@@ -199,7 +200,7 @@
 {
     if (0 <= index && index < NUM_SYS_COLORS)
         return SysColorBrushes[index];
-    fprintf( stderr, "GetSysColorBrush32: Unknown index(%d)\n", index );
+    WARN(syscolor, "Unknown index(%d)\n", index );
     return GetStockObject32(LTGRAY_BRUSH);
 }
 
diff --git a/windows/user.c b/windows/user.c
index f0d920e..d0cd7ed 100644
--- a/windows/user.c
+++ b/windows/user.c
@@ -5,7 +5,6 @@
  *	     1996 Alex Korobka 
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include "windows.h"
 #include "resource.h"
@@ -16,17 +15,16 @@
 #include "queue.h"
 #include "win.h"
 #include "clipboard.h"
+#include "menu.h"
 #include "hook.h"
 #include "debug.h"
 #include "toolhelp.h"
 #include "message.h"
 #include "module.h"
 #include "miscemu.h"
+#include "queue.h"
 #include "shell.h"
 
-extern BOOL32 MENU_PatchResidentPopup( HQUEUE16, WND* );
-extern void QUEUE_FlushMessages(HQUEUE16);
-
 /***********************************************************************
  *           GetFreeSystemResources   (USER.284)
  */
@@ -244,7 +242,7 @@
 	     break;
 
 	default:
-	     fprintf(stderr,"Unimplemented USER signal: %i\n", (int)uCode );
+	     FIXME(msg,"Unimplemented USER signal: %i\n", (int)uCode );
     }
 }
 
@@ -263,7 +261,7 @@
  */
 BOOL16 WINAPI ExitWindowsExec16( LPCSTR lpszExe, LPCSTR lpszParams )
 {
-    fprintf(stderr, "ExitWindowsExec() : Should run the following in DOS-mode :\n\t\"%s %s\"\n",
+    TRACE(system, "Should run the following in DOS-mode: \"%s %s\"\n",
 	lpszExe, lpszParams);
     return ExitWindowsEx( EWX_LOGOFF, 0xffffffff );
 }
@@ -310,7 +308,7 @@
  *           EnumDisplaySettingsA   (USER32.592)
  */
 BOOL32 WINAPI EnumDisplaySettings32A(LPCSTR name,DWORD n,LPDEVMODE32A devmode) {
-	fprintf(stderr,"EnumDisplaySettings32A(%s,%ld,%p)\n",name,n,devmode);
+	TRACE(system,"(%s,%ld,%p)\n",name,n,devmode);
 	if (n==0) {
 		devmode->dmBitsPerPel = DefaultDepthOfScreen(screen);
 		devmode->dmPelsHeight = screenHeight;
@@ -328,7 +326,7 @@
  */
 FARPROC16 SetEventHook(FARPROC16 lpfnEventHook)
 {
-	fprintf(stderr, "SetEventHook(lpfnEventHook = %08x): stub !\n", (UINT32)lpfnEventHook);
+	FIXME(hook, "(lpfnEventHook=%08x): stub\n", (UINT32)lpfnEventHook);
 	return NULL;
 }
 
diff --git a/windows/win.c b/windows/win.c
index 5563a76..af2917d 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -5,7 +5,6 @@
  */
 
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include <X11/Xatom.h>
 
@@ -40,11 +39,6 @@
 static WORD wDragWidth = 4;
 static WORD wDragHeight= 3;
 
-extern BOOL32 ICONTITLE_Init(void);
-extern BOOL32 MENU_PatchResidentPopup( HQUEUE16, WND* );
-extern HWND32 CARET_GetHwnd(void);
-extern BOOL32 EVENT_CheckFocus(void);
-
 /***********************************************************************
  *           WIN_FindWndPtr
  *
@@ -59,7 +53,7 @@
     if (ptr->dwMagic != WND_MAGIC) return NULL;
     if (ptr->hwndSelf != hwnd)
     {
-        fprintf( stderr, "Can't happen: hwnd %04x self pointer is %04x\n",
+        ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",
                  hwnd, ptr->hwndSelf );
         return NULL;
     }
@@ -80,16 +74,15 @@
 
     if (!(ptr = WIN_FindWndPtr( hwnd )))
     {
-        fprintf( stderr, "%04x is not a window handle\n", hwnd );
+        WARN( win, "%04x is not a window handle\n", hwnd );
         return;
     }
 
     if (!GetClassName32A( hwnd, className, sizeof(className ) ))
         strcpy( className, "#NULL#" );
 
-    fprintf( stderr, "Window %04x (%p):\n", hwnd, ptr );
-    fprintf( stderr,
-             "next=%p  child=%p  parent=%p  owner=%p  class=%p '%s'\n"
+    TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
+    DUMP(    "next=%p  child=%p  parent=%p  owner=%p  class=%p '%s'\n"
              "inst=%04x  taskQ=%04x  updRgn=%04x  active=%04x dce=%p  idmenu=%08x\n"
              "style=%08lx  exstyle=%08lx  wndproc=%08x  text='%s'\n"
              "client=%d,%d-%d,%d  window=%d,%d-%d,%d"
@@ -106,12 +99,12 @@
 
     if (ptr->class->cbWndExtra)
     {
-        fprintf( stderr, "extra bytes:" );
+        DUMP( "extra bytes:" );
         for (i = 0; i < ptr->class->cbWndExtra; i++)
-            fprintf( stderr, " %02x", *((BYTE*)ptr->wExtra+i) );
-        fprintf( stderr, "\n" );
+            DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
+        DUMP( "\n" );
     }
-    fprintf( stderr, "\n" );
+    DUMP( "\n" );
 }
 
 
@@ -128,21 +121,21 @@
     ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
     if (!ptr)
     {
-        fprintf( stderr, "*** Invalid window handle %04x\n", hwnd );
+        WARN( win, "Invalid window handle %04x\n", hwnd );
         return;
     }
 
     if (!indent)  /* first time around */
-        fprintf( stderr, "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
+       DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
                  "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc");
 
     while (ptr)
     {
-        fprintf(stderr, "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
+        DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
 
         GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
         
-        fprintf( stderr, "%08lx %-6.4x %-17.17s %08x %08x\n",
+        DUMP( "%08lx %-6.4x %-17.17s %08x %08x\n",
                  (DWORD)ptr, ptr->hmemTaskQ, className,
                  (UINT32)ptr->dwStyle, (UINT32)ptr->winproc );
         
@@ -480,11 +473,11 @@
 	/* Make sure parent is valid */
         if (!IsWindow32( cs->hwndParent ))
         {
-            fprintf( stderr, "CreateWindowEx: bad parent %04x\n", cs->hwndParent );
+            WARN( win, "Bad parent %04x\n", cs->hwndParent );
 	    return 0;
 	}
     } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
-        fprintf( stderr, "CreateWindowEx: no parent for child window\n" );
+        WARN( win, "No parent for child window\n" );
         return 0;  /* WS_CHILD needs a parent, but WS_POPUP doesn't */
     }
 
@@ -493,7 +486,7 @@
     {
         char buffer[256];
         GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
-        fprintf( stderr, "CreateWindowEx: bad class '%s'\n", buffer );
+        WARN( win, "Bad class '%s'\n", buffer );
         return 0;
     }
 
@@ -914,11 +907,11 @@
     	if (HIWORD(className))
         {
             LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
-            fprintf( stderr, "CreateWindowEx32W: bad class name '%s'\n",cn);
+            WARN( win, "Bad class name '%s'\n",cn);
             HeapFree( GetProcessHeap(), 0, cn );
 	}
         else
-            fprintf( stderr, "CreateWindowEx32W: bad class name %p\n", className );
+            WARN( win, "Bad class name %p\n", className );
         return 0;
     }
 
@@ -1401,7 +1394,7 @@
     {
         if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
         {
-            fprintf( stderr, "GetWindowWord: invalid offset %d\n", offset );
+            WARN( win, "Invalid offset %d\n", offset );
             return 0;
         }
         return *(WORD *)(((char *)wndPtr->wExtra) + offset);
@@ -1410,16 +1403,18 @@
     {
     case GWW_ID:         
     	if (HIWORD(wndPtr->wIDmenu))
-    		fprintf(stderr,"GetWindowWord32(GWW_ID) discards high bits of 0x%08x!\n",wndPtr->wIDmenu);
+    		WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
+                    wndPtr->wIDmenu);
     	return (WORD)wndPtr->wIDmenu;
     case GWW_HWNDPARENT: return wndPtr->parent ?
 			wndPtr->parent->hwndSelf : wndPtr->owner->hwndSelf;
     case GWW_HINSTANCE:  
     	if (HIWORD(wndPtr->hInstance))
-    		fprintf(stderr,"GetWindowWord32(GWW_HINSTANCE) discards high bits of 0x%08x!\n",wndPtr->hInstance);
+    		WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
+                    wndPtr->hInstance);
    	return (WORD)wndPtr->hInstance;
     default:
-        fprintf( stderr, "GetWindowWord: invalid offset %d\n", offset );
+        WARN( win, "Invalid offset %d\n", offset );
         return 0;
     }
 }
@@ -1457,7 +1452,7 @@
     {
         if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
         {
-            fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
+            WARN( win, "Invalid offset %d\n", offset );
             return 0;
         }
         ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
@@ -1468,7 +1463,7 @@
 	case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
 	case GWW_HWNDPARENT: return SetParent32( hwnd, newval );
 	default:
-            fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
+            WARN( win, "Invalid offset %d\n", offset );
             return 0;
     }
     retval = *ptr;
@@ -1491,7 +1486,7 @@
     {
         if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
         {
-            fprintf( stderr, "GetWindowLong: invalid offset %d\n", offset );
+            WARN( win, "Invalid offset %d\n", offset );
             return 0;
         }
         retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
@@ -1512,7 +1507,7 @@
                                         (HWND32)wndPtr->parent->hwndSelf : 0;
         case GWL_HINSTANCE:  return wndPtr->hInstance;
         default:
-            fprintf( stderr, "GetWindowLong: unknown offset %d\n", offset );
+            WARN( win, "Unknown offset %d\n", offset );
     }
     return 0;
 }
@@ -1534,7 +1529,7 @@
     {
         if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
         {
-            fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
+            WARN( win, "Invalid offset %d\n", offset );
             return 0;
         }
         ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
@@ -1571,7 +1566,7 @@
         case GWL_USERDATA: ptr = &wndPtr->userdata; break;
         case GWL_EXSTYLE:  ptr = &wndPtr->dwExStyle; break;
 	default:
-            fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
+            WARN( win, "Invalid offset %d\n", offset );
             return 0;
     }
     retval = *ptr;
diff --git a/windows/winhelp.c b/windows/winhelp.c
index 2ef305b..3a8ea2e 100644
--- a/windows/winhelp.c
+++ b/windows/winhelp.c
@@ -6,6 +6,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include "debug.h"
 #include "windows.h"
 #include "heap.h"
 #include "ldt.h"
@@ -80,7 +81,7 @@
 			dsize = ((LPHELPWININFO)dwData)->wStructSize;
 			break;
 		default:
-			fprintf(stderr,"Unknown help command %d\n",wCommand);
+			WARN( win,"Unknown help command %d\n",wCommand);
 			return FALSE;
 	}
 	if(lpHelpFile)
diff --git a/windows/winpos.c b/windows/winpos.c
index 043cf75..7380db9 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -49,11 +49,6 @@
 #define SMC_DRAWFRAME		0x0004
 #define SMC_SETXPOS		0x0008
 
-/* ----- external functions ----- */
-
-extern void 	FOCUS_SwitchFocus( HWND32 , HWND32 );
-extern HWND32	CARET_GetHwnd();
-
 /* ----- internal variables ----- */
 
 static HWND32 hwndActive      = 0;  /* Currently active window */
diff --git a/windows/winproc.c b/windows/winproc.c
index 7f777cf..03fdeff 100644
--- a/windows/winproc.c
+++ b/windows/winproc.c
@@ -5,7 +5,6 @@
  * Copyright 1996 Alexandre Julliard
  */
 
-#include <stdio.h>
 #include "windows.h"
 #include "callback.h"
 #include "heap.h"
@@ -99,7 +98,7 @@
     WinProcHeap = HeapCreate( HEAP_WINE_SEGPTR | HEAP_WINE_CODESEG, 0, 0 );
     if (!WinProcHeap)
     {
-        fprintf( stderr, "Unable to create winproc heap\n" );
+        WARN(relay, "Unable to create winproc heap\n" );
         return FALSE;
     }
     return TRUE;
@@ -439,8 +438,7 @@
     case WM_PAINTCLIPBOARD:
     case WM_SIZECLIPBOARD:
     case WM_WININICHANGE:
-        fprintf( stderr, "MapMsg32ATo32W: message %04x needs translation\n",
-                 msg );
+        TRACE(msg, "message %04x needs translation\n", msg );
         return -1;
     default:  /* No translation needed */
         return 0;
@@ -550,8 +548,7 @@
     case WM_PAINTCLIPBOARD:
     case WM_SIZECLIPBOARD:
     case WM_WININICHANGE:
-        fprintf( stderr, "MapMsg32WTo32A: message %04x needs translation\n",
-                 msg );
+        WARN(msg, "message %04x needs translation\n",msg );
         return -1;
     default:  /* No translation needed */
         return 0;
@@ -811,8 +808,7 @@
     case WM_PAINTCLIPBOARD:
     case WM_SIZECLIPBOARD:
     case WM_WININICHANGE:
-        fprintf( stderr, "MapMsg16To32A: message %04x needs translation\n",
-                 msg16 );
+        WARN( msg, "message %04x needs translation\n",msg16 );
         return -1;
 
     default:  /* No translation needed */
@@ -1432,8 +1428,7 @@
     case WM_PAINTCLIPBOARD:
     case WM_SIZECLIPBOARD:
     case WM_WININICHANGE:
-        fprintf( stderr, "MapMsg32ATo16: message %04x needs translation\n",
-                 msg32 );
+        WARN( msg, "message %04x needs translation\n", msg32 );
         return -1;
 
     default:  /* No translation needed */
@@ -1856,7 +1851,7 @@
         return WINPROC_CallProc16To32W( hwnd, msg, wParam, lParam,
                                         proc->thunk.t_from16.proc );
     default:
-        fprintf( stderr, "CallWindowProc16: invalid proc %p\n", proc );
+        WARN( relay, "Invalid proc %p\n", proc );
         return 0;
     }
 }
@@ -1892,7 +1887,7 @@
         return WINPROC_CallProc32ATo32W( proc->thunk.t_from16.proc,
                                          hwnd, msg, wParam, lParam );
     default:
-        fprintf( stderr, "CallWindowProc32A: invalid proc %p\n", proc );
+        WARN( relay, "Invalid proc %p\n", proc );
         return 0;
     }
 }
@@ -1928,7 +1923,7 @@
         return WINPROC_CallWndProc32( proc->thunk.t_from16.proc,
                                       hwnd, msg, wParam, lParam );
     default:
-        fprintf( stderr, "CallWindowProc32W: invalid proc %p\n", proc );
+        WARN( relay, "Invalid proc %p\n", proc );
         return 0;
     }
 }