Release 960131

Wed Jan 31 10:58:00 1996  Alexandre Julliard  <julliard@sunsite.unc.edu>

	* [configure.in]
	Added --with-dll option to build libwine.so.

	* [controls/listbox.c]
	Fixed ListBoxDirectory(), DlgDirSelect() and
	DlgDirList(). Hopefully their behavior is correct now.

	* [controls/menu.c]
	Use SEGPTRs in ChangeMenu(), InsertMenu(), AppendMenu() and
 	ModifyMenu() for the item data, to avoid corrupting the pointer
 	for owner-drawn items.

	* [controls/static.c]
	Attempt to load OEM icons for SS_ICON controls. Probably not
	entirely correct.
	Don't clip the text output.

	* [files/directory.c]
	Add temp dir and Windows dir to environment.

	* [files/dos_fs.c]
	Fixed a few path handling bugs in DOSFS_GetUnixFileName().
	Cache last used directory in DOSFS_FindNext() to avoid quadratic
	search time.

	* [files/drive.c]
	New format for drives configuration in wine.conf; allows
	specifying the type, label and serial number of a drive.

	* [files/file.c]
	New function FILE_OpenUnixFile to make sure we don't open a
	directory instead of a file.
	Fixed DOSFS_GetUnixFileName() check_last flag in FILE_MakeDir().

	* [files/profile.c]
	Rewrote profile handling. Should be closer to Windows behavior now.
	New function PROFILE_GetWineIniString() to get a string from wine.conf.
	Support environment variables in wine.conf.

	* [loader/task.c]
	Fixed the order of deletion in TASK_DeleteTask() to avoid memory
	corruption.

	* [memory/global.c]
	Create a discarded block on GlobalAlloc() if the size is 0; thanks
	to John Harvey for noticing this.

	* [memory/local.c]
	LOCAL_GetHeap: make sure the pointer is valid before checking
	magic number.

	* [misc/main.c]
	Moved profile and registry saving to ExitWindows(), so we don't
	try to save them in case of a crash.

	* [miscemu/int21.c]
	INT21_GetFreeDiskSpace: try to compute the cluster size from the
	filesystem size instead of hard-coding it to 64.
	Fixed functions 0x3f and 0x40 to use _hread and _hwrite to allow
	reading or writing 65535 bytes (thanks to Bruce Milner for this	one).

	* [windows/message.c]
	Fixed bug in linked-list handling in MSG_DeleteQueue().
	Simplified SetMessageQueue().

	* [wine.ini] [wine.man]
	Updated for new drives configuration format.

Tue Jan 30 11:24:46 1996  William Magro  <wmagro@tc.cornell.edu>

	* [controls/edit.c]
	Implemented ES_PASSWORD style, EM_SETPASSWORDCHAR and
 	EM_GETPASSWORDCHAR messages.

	* [controls/widgets.c]
	Adjusted class creation flags to better match values Windows uses.

	* [include/windows.h]
	Fixed ES_NOHIDESEL typo.

	* [loader/ne_image.c]
	Added detection for zero offset in RADDR fixups. Quicken
	was in an infinite loop here.

Mon Jan 29 20:12:22 1996  Albrecht Kleine  <kleine@ak.sax.de>

	* [files/dos_fs.c]
	Bugfix: range error in month value (0..11 set to 1..12).

	* [windows/caret.c]
	Changed ROP2-mode to R2_NOTXORPEN in CARET_Callback for pulsed
 	appearance of the caret.

	* [windows/mdi.c] [include/mdi.h]
	Changed MDITile(): added a new parameter WORD wParam for
 	WM_MDITILE second tiling method (MDITILE_HORIZONTAL in wParam) as
 	used in Win3.1

Sun Jan 28 14:20:00 1996  Cameron Heide  <heide@ee.ualberta.ca>

	* [miscemu/int2f.c]
	Added a small bit of MSCDEX emulation.

	* [windows/alias.c]
	ALIAS_RegisterAlias was returning the hash value when it should
 	have been returning the record number.
	
Sat Jan 27 10:53:51 1996  Jim Peterson <jspeter@birch.ee.vt.edu>

	* [include/shell.h] [include/wintypes.h]
	Moved definition of HKEY and LPHKEY types to include/wintypes.h.
	Declared FONTENUMPROC in wintypes.h.

	* [include/windows.h]
	Added definition of KERNINGPAIR and LPKERNINGPAIR types.  Added
	declarations for CopyCursor(), CopyIcon(), EnumFontFamilies(),
	ExtractIcon(), FatalAppExit(), FindExecutable(), GetClipCursor(),
	GetKerningPairs(), GetQueueStatus(), GetRasterizerCaps(),
	IsGDIObject(), IsMenu(), IsTask(), RegCloseKey(), RegCreateKey(),
	RegDeleteKey(), RegEnumKey(), RegOpenKey(), RegQueryValue(),
	RegSetValue(), ResetDC(), ShellExecute(), SystemParametersInfo(),
	and wsprintf().

	* [tools/makehtml.pl] [documentation/apiw.index]
	New files that scan windows.h, commdlg.h, and toolhelp.h and output
	an HTML sorted list with optional links to www.willows.com and a
	tally of unimplemented APIW functions.

	* [objects/cursoricon.c]
	Added Win32 versions of CopyIcon() and CopyCursor() for use in
	libwine.

	* [win32/resource.c] [win32/winprocs.c]
	Added '#include "libres.h"' and explicit declarations of windows
	procs in order to avoid warnings.

	* [windows/utility.c]
	Added Win32 version of MulDiv() for libwine.

	* [*/*] [include/windows.h]
	Changed several function declarations to comply more strictly to
	the windows API (without, hopefully, altering their functionality).

	* [controls/menu.c]
	Made the return value of CheckMenuItem be the previous state of
 	the menu item if it was found, otherwise -1 as specified in the
 	SDK. This conflicts with the APIW specification, which says it
 	should return TRUE if successful, otherwise FALSE.

	* [include/windows.h]
	Added obsolete WM_SIZE message wParam names for compatibility.
  	Added WinHelp() command constants, even though they are not yet
 	supported.

	* [rc/winerc.c]
	Tidied up transform_binary_file().  In argument checking, flattened
	any invalid characters specified with the prefix argument.

	* [library/libres.c]
	Made FindResource() case-insensitive when parameter 'name' is a string.

Sat Jan 27 02:30 1996  Uwe Bonnes <bon@elektron.ikp.physik.th-darmstadt.de

	* [files/drive.c]
	If root "/" is given in wine.conf, use it as last resort.

	* [files/file.c]
	Report ER_AccessDenied it disk ist not writable
	More Debug Output

	* [miscemu/int21.c]
	Squeezed some bugs in ExtendedOpenCreateFile
	
	* [windows/winpos.c]
	Some windows may not be moved or resized. We are missing some
	structures to be exact, but the approach should help in some cases
	and make things worse in much fewer.

Fri Jan 26 10:24:00 1996  Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>

	* [loader/pe_image.c]
	fixup_imports: Find builtins for Borland style entries, too

Fri Jan 26 10:24:00 1996  Martin von Loewis <loewis@informatik.hu-berlin.de>

	* [controls/menu.c]
	LoadMenu: branch to Win32 for PE modules

	* [if1632/gdi.spec][if1632/kernel32.spec][if1632/user32.spec]
	DeleteObject, GetPixel, SetPixel,WritePrivateProfileStringA,
	WriteProfileStringA, EmptyClipboard, EnableMenuItem, EnableScrollBar,
	EnableWindow, InvalidateRect, SetWindowTextA, WinHelpA: new relays
	DrawTextA, MoveToEx, GetClientRect, InvalidateRect, LoadBitmapA/W,
	LoadAcceleratorsA/W, LoadMenu[Indirect]A/W, LoadStringA/W: changed
	to convert parameters or naming convention

	* [include/kernel32.h][include/wintypes.h]
	moved WCHAR, defined LPWSTR

	* [include/string32.h][win32/string32.c][include/struct32.h]
	New files

	* [loader/module.h]
	LoadModule: exit after returning from PE_LoadModule

	* [loader/pe_image.c]
	my_wcstombs: isascii does not work on Linux for Unicode
	PE_LoadImage: Handle directories

	* [misc/user32.c]
	USER32_RECT32to16, USER32_RECT16to32: new functions
	implemented new user32 relays

	* [misc/newfns.c]
	WIN32_WinHelpA: new function

	* [win32/param32.c]
	New file

	* [win32/resource.c]
	GetResDirEntry: added support for named entries
	WIN32_LoadAcceleratorsW: invoke *32 resource functions
	WIN32_LoadBitmapA: convert name to unicode if appropriate
	WIN32_ParseMenu: new function
	implemented new resource functions from user32.spec

Wed Jan 24 18:09:00 1996 Alex Korobka <alex@phm30.pharm.sunysb.edu>

	* [objects/cursoricon.c]
	GetIconId() and LoadIconHandler() functions.

	* [windows/mdi.c]
	Better maximization support, TranslateMDISysAccel() function, 
	misc improvements.

	* [windows/defwnd.c]
	Fix for WM_WINDOWPOSCHANGED message handler.

	* [windows/winpos.c]
	Rewrote WindowFromPoint() function.

Sun Jan 21 1996 17:05:09  Marcus Meissner <msmeissn@faui01.informatik.uni-erlangen.de>

	* [include/toolhelp.h] [misc/toolhelp.c]
	Added Notify(Un)Register, but no callbacks yet.

Fri Jan 19 01:43:37 1996 Victor Schneider <root@tailor.roman.org>

	* [Makefile.in]
	Added target for libwine.so.1.0.

	* [library/winmain.c]
	For WINELIBDLL, _WinMain just returns hInstance instead of calling
	WinMain().

	* [misc/main.c]
	For WINELIBDLL, renamed main() to _wine_main() for calling from the
	stub main function.

	* [library/winestub.c] (new file)
	Provides a stub main() function for using libwine.so.

Tue Jan 16 11:04:34 1996  Anand Kumria <akumria@ozemail.com.au>

	* [winsocket.c]
	Fix EPERM problem.

	* [global.c]
	Attempt to do some sanity checking in MemManInfo().

	* [Changelog]
	Fix changelog oversight for previous entry.
diff --git a/ANNOUNCE b/ANNOUNCE
index 703bde4..2f3d6e1 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,13 +1,15 @@
-This is release 960114 of Wine the MS Windows emulator.  This is still a
+This is release 960131 of Wine the MS Windows emulator.  This is still a
 developer's only release.  There are many bugs and many unimplemented API
 features.  Most applications still do not work.
 
 Patches should be submitted to "wine-new@amscons.com".  Please don't forget
 to include a ChangeLog entry.  I'll make a new release every other week.
 
-WHAT'S NEW with Wine-960114: (see ChangeLog for details)
-	- Complete rewrite of the file handling; still has a few bugs.
-	- Tons of new Win32 code.
+WHAT'S NEW with Wine-960131: (see ChangeLog for details)
+	- New format for drives configuration in wine.conf; please
+	  check your configuration files.
+	- Many MDI improvements.
+	- Even more Win32 code.
 	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -16,10 +18,10 @@
 the release is available at the ftp sites.  The sources will be available
 from the following locations:
 
-    sunsite.unc.edu:/pub/Linux/ALPHA/wine/Wine-960114.tar.gz
-    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960114.tar.gz
-    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960114.tar.gz
-    aris.com:/pub/linux/ALPHA/Wine/development/Wine-960114.tar.gz
+    sunsite.unc.edu:/pub/Linux/ALPHA/wine/Wine-960131.tar.gz
+    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960131.tar.gz
+    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960131.tar.gz
+    aris.com:/pub/linux/ALPHA/Wine/development/Wine-960131.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
diff --git a/ChangeLog b/ChangeLog
index d7a84c2..e5a42a0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,280 @@
 ----------------------------------------------------------------------
+Wed Jan 31 10:58:00 1996  Alexandre Julliard  <julliar@sunsite.unc.edu>
+
+	* [configure.in]
+	Added --with-dll option to build libwine.so.
+
+	* [controls/listbox.c]
+	Fixed ListBoxDirectory(), DlgDirSelect() and
+	DlgDirList(). Hopefully their behavior is correct now.
+
+	* [controls/menu.c]
+	Use SEGPTRs in ChangeMenu(), InsertMenu(), AppendMenu() and
+ 	ModifyMenu() for the item data, to avoid corrupting the pointer
+ 	for owner-drawn items.
+
+	* [controls/static.c]
+	Attempt to load OEM icons for SS_ICON controls. Probably not
+	entirely correct.
+	Don't clip the text output.
+
+	* [files/directory.c]
+	Add temp dir and Windows dir to environment.
+
+	* [files/dos_fs.c]
+	Fixed a few path handling bugs in DOSFS_GetUnixFileName().
+	Cache last used directory in DOSFS_FindNext() to avoid quadratic
+	search time.
+
+	* [files/drive.c]
+	New format for drives configuration in wine.conf; allows
+	specifying the type, label and serial number of a drive.
+
+	* [files/file.c]
+	New function FILE_OpenUnixFile to make sure we don't open a
+	directory instead of a file.
+	Fixed DOSFS_GetUnixFileName() check_last flag in FILE_MakeDir().
+
+	* [files/profile.c]
+	Rewrote profile handling. Should be closer to Windows behavior now.
+	New function PROFILE_GetWineIniString() to get a string from wine.conf.
+	Support environment variables in wine.conf.
+
+	* [loader/task.c]
+	Fixed the order of deletion in TASK_DeleteTask() to avoid memory
+	corruption.
+
+	* [memory/global.c]
+	Create a discarded block on GlobalAlloc() if the size is 0; thanks
+	to John Harvey for noticing this.
+
+	* [memory/local.c]
+	LOCAL_GetHeap: make sure the pointer is valid before checking
+	magic number.
+
+	* [misc/main.c]
+	Moved profile and registry saving to ExitWindows(), so we don't
+	try to save them in case of a crash.
+
+	* [miscemu/int21.c]
+	INT21_GetFreeDiskSpace: try to compute the cluster size from the
+	filesystem size instead of hard-coding it to 64.
+	Fixed functions 0x3f and 0x40 to use _hread and _hwrite to allow
+	reading or writing 65535 bytes (thanks to Bruce Milner for this	one).
+
+	* [windows/message.c]
+	Fixed bug in linked-list handling in MSG_DeleteQueue().
+	Simplified SetMessageQueue().
+
+	* [wine.ini] [wine.man]
+	Updated for new drives configuration format.
+
+Tue Jan 30 11:24:46 1996  William Magro  <wmagro@tc.cornell.edu>
+
+	* [controls/edit.c]
+	Implemented ES_PASSWORD style, EM_SETPASSWORDCHAR and
+ 	EM_GETPASSWORDCHAR messages.
+
+	* [controls/widgets.c]
+	Adjusted class creation flags to better match values Windows uses.
+
+	* [include/windows.h]
+	Fixed ES_NOHIDESEL typo.
+
+	* [loader/ne_image.c]
+	Added detection for zero offset in RADDR fixups. Quicken
+	was in an infinite loop here.
+
+Mon Jan 29 20:12:22 1996  Albrecht Kleine  <kleine@ak.sax.de>
+
+	* [files/dos_fs.c]
+	Bugfix: range error in month value (0..11 set to 1..12).
+
+	* [windows/caret.c]
+	Changed ROP2-mode to R2_NOTXORPEN in CARET_Callback for pulsed
+ 	appearance of the caret.
+
+	* [windows/mdi.c] [include/mdi.h]
+	Changed MDITile(): added a new parameter WORD wParam for
+ 	WM_MDITILE second tiling method (MDITILE_HORIZONTAL in wParam) as
+ 	used in Win3.1
+
+Sun Jan 28 14:20:00 1996  Cameron Heide  <heide@ee.ualberta.ca>
+
+	* [miscemu/int2f.c]
+	Added a small bit of MSCDEX emulation.
+
+	* [windows/alias.c]
+	ALIAS_RegisterAlias was returning the hash value when it should
+ 	have been returning the record number.
+	
+Sat Jan 27 10:53:51 1996  Jim Peterson <jspeter@birch.ee.vt.edu>
+
+	* [include/shell.h] [include/wintypes.h]
+	Moved definition of HKEY and LPHKEY types to include/wintypes.h.
+	Declared FONTENUMPROC in wintypes.h.
+
+	* [include/windows.h]
+	Added definition of KERNINGPAIR and LPKERNINGPAIR types.  Added
+	declarations for CopyCursor(), CopyIcon(), EnumFontFamilies(),
+	ExtractIcon(), FatalAppExit(), FindExecutable(), GetClipCursor(),
+	GetKerningPairs(), GetQueueStatus(), GetRasterizerCaps(),
+	IsGDIObject(), IsMenu(), IsTask(), RegCloseKey(), RegCreateKey(),
+	RegDeleteKey(), RegEnumKey(), RegOpenKey(), RegQueryValue(),
+	RegSetValue(), ResetDC(), ShellExecute(), SystemParametersInfo(),
+	and wsprintf().
+
+	* [tools/makehtml.pl] [documentation/apiw.index]
+	New files that scan windows.h, commdlg.h, and toolhelp.h and output
+	an HTML sorted list with optional links to www.willows.com and a
+	tally of unimplemented APIW functions.
+
+	* [objects/cursoricon.c]
+	Added Win32 versions of CopyIcon() and CopyCursor() for use in
+	libwine.
+
+	* [win32/resource.c] [win32/winprocs.c]
+	Added '#include "libres.h"' and explicit declarations of windows
+	procs in order to avoid warnings.
+
+	* [windows/utility.c]
+	Added Win32 version of MulDiv() for libwine.
+
+	* [*/*] [include/windows.h]
+	Changed several function declarations to comply more strictly to
+	the windows API (without, hopefully, altering their functionality).
+
+	* [controls/menu.c]
+	Made the return value of CheckMenuItem be the previous state of
+ 	the menu item if it was found, otherwise -1 as specified in the
+ 	SDK. This conflicts with the APIW specification, which says it
+ 	should return TRUE if successful, otherwise FALSE.
+
+	* [include/windows.h]
+	Added obsolete WM_SIZE message wParam names for compatibility.
+  	Added WinHelp() command constants, even though they are not yet
+ 	supported.
+
+	* [rc/winerc.c]
+	Tidied up transform_binary_file().  In argument checking, flattened
+	any invalid characters specified with the prefix argument.
+
+	* [library/libres.c]
+	Made FindResource() case-insensitive when parameter 'name' is a string.
+
+Sat Jan 27 02:30 1996  Uwe Bonnes <bon@elektron.ikp.physik.th-darmstadt.de
+
+	* [files/drive.c]
+	If root "/" is given in wine.conf, use it as last resort.
+
+	* [files/file.c]
+	Report ER_AccessDenied it disk ist not writable
+	More Debug Output
+
+	* [miscemu/int21.c]
+	Squeezed some bugs in ExtendedOpenCreateFile
+	
+	* [windows/winpos.c]
+	Some windows may not be moved or resized. We are missing some
+	structures to be exact, but the approach should help in some cases
+	and make things worse in much fewer.
+
+Fri Jan 26 10:24:00 1996  Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>
+
+	* [loader/pe_image.c]
+	fixup_imports: Find builtins for Borland style entries, too
+
+Fri Jan 26 10:24:00 1996  Martin von Loewis <loewis@informatik.hu-berlin.de>
+
+	* [controls/menu.c]
+	LoadMenu: branch to Win32 for PE modules
+
+	* [if1632/gdi.spec][if1632/kernel32.spec][if1632/user32.spec]
+	DeleteObject, GetPixel, SetPixel,WritePrivateProfileStringA,
+	WriteProfileStringA, EmptyClipboard, EnableMenuItem, EnableScrollBar,
+	EnableWindow, InvalidateRect, SetWindowTextA, WinHelpA: new relays
+	DrawTextA, MoveToEx, GetClientRect, InvalidateRect, LoadBitmapA/W,
+	LoadAcceleratorsA/W, LoadMenu[Indirect]A/W, LoadStringA/W: changed
+	to convert parameters or naming convention
+
+	* [include/kernel32.h][include/wintypes.h]
+	moved WCHAR, defined LPWSTR
+
+	* [include/string32.h][win32/string32.c][include/struct32.h]
+	New files
+
+	* [loader/module.h]
+	LoadModule: exit after returning from PE_LoadModule
+
+	* [loader/pe_image.c]
+	my_wcstombs: isascii does not work on Linux for Unicode
+	PE_LoadImage: Handle directories
+
+	* [misc/user32.c]
+	USER32_RECT32to16, USER32_RECT16to32: new functions
+	implemented new user32 relays
+
+	* [misc/newfns.c]
+	WIN32_WinHelpA: new function
+
+	* [win32/param32.c]
+	New file
+
+	* [win32/resource.c]
+	GetResDirEntry: added support for named entries
+	WIN32_LoadAcceleratorsW: invoke *32 resource functions
+	WIN32_LoadBitmapA: convert name to unicode if appropriate
+	WIN32_ParseMenu: new function
+	implemented new resource functions from user32.spec
+
+Wed Jan 24 18:09:00 1996 Alex Korobka <alex@phm30.pharm.sunysb.edu>
+
+	* [objects/cursoricon.c]
+	GetIconId() and LoadIconHandler() functions.
+
+	* [windows/mdi.c]
+	Better maximization support, TranslateMDISysAccel() function, 
+	misc improvements.
+
+	* [windows/defwnd.c]
+	Fix for WM_WINDOWPOSCHANGED message handler.
+
+	* [windows/winpos.c]
+	Rewrote WindowFromPoint() function.
+
+Sun Jan 21 1996 17:05:09  Marcus Meissner <msmeissn@faui01.informatik.uni-erlangen.de>
+
+	* [include/toolhelp.h] [misc/toolhelp.c]
+	Added Notify(Un)Register, but no callbacks yet.
+
+Fri Jan 19 01:43:37 1996 Victor Schneider <root@tailor.roman.org>
+
+	* [Makefile.in]
+	Added target for libwine.so.1.0.
+
+	* [library/winmain.c]
+	For WINELIBDLL, _WinMain just returns hInstance instead of calling
+	WinMain().
+
+	* [misc/main.c]
+	For WINELIBDLL, renamed main() to _wine_main() for calling from the
+	stub main function.
+
+	* [library/winestub.c] (new file)
+	Provides a stub main() function for using libwine.so.
+
+Tue Jan 16 11:04:34 1996  Anand Kumria <akumria@ozemail.com.au>
+
+	* [winsocket.c]
+	Fix EPERM problem.
+
+	* [global.c]
+	Attempt to do some sanity checking in MemManInfo().
+
+	* [Changelog]
+	Fix changelog oversight for previous entry.
+
+---------------------------------------------------------------------
 Sun Jan 14 13:45:22 1996  Alexandre Julliard  <julliard@sunsite.unc.edu>
 
 	* [configure.in]
@@ -113,6 +389,9 @@
 	  [misc/user.c] [windows/message.c]
 	Implement TOOLHELP.80 TimerCount. Fix GetTickCount.
 
+	* [winsocket.c]
+	Fixed ENOENT error.
+
 	* [miscemu/dpmi.c]
 	Implement DPMI Get Page Size (AX=0604, INT 31)
 
diff --git a/Make.rules.in b/Make.rules.in
index a6d4063..d871a6f 100644
--- a/Make.rules.in
+++ b/Make.rules.in
@@ -73,10 +73,7 @@
 	mv tmp_make Makefile
 
 clean::
-	$(RM) *.o \#*\# *~ *.bak *.flc tmp_make winerctmp.c
-
-distclean:: clean
-	$(RM) Makefile
+	$(RM) *.o \#*\# *~ *.bak *.orig *.rej *.flc tmp_make winerctmp.c
 
 dummy:
 
diff --git a/Makefile.in b/Makefile.in
index 0e3459b..dbbe50e 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -113,6 +113,12 @@
 install_libwine.a: dummy
 	$(INSTALL_DATA) libwine.a $(libdir)
 
+libwine.so.1.0: $(COMMONSUBDIRS) $(LIBSUBDIRS) dummy
+	$(CC) -shared -Wl,-soname,libwine.so.1 -o$@ $(COMMONOBJS) $(LIBOBJS) $(LDOPTIONS) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LDLIBS)
+
+install_libwine.so.1.0: dummy
+	$(INSTALL_DATA) libwine.so.1.0 $(libdir)
+
 $(ALLSUBDIRS): dummy
 	@cd $@; $(SUBMAKE)
 
@@ -124,13 +130,12 @@
 
 clean:
 	for i in $(ALLSUBDIRS); do (cd $$i; $(MAKE) clean); done
-	$(RM) *.o \#*\# *~ *.bak *.flc wine wine.sym libwine.a TAGS
-	$(RM) include/\#*\# include/*~ include/*.bak include/*.flc
+	$(RM) *.o \#*\# *~ *.bak *.orig *.rej *.flc
+	$(RM) wine wine.sym libwine.a libwine.so.1.0 TAGS
+	(cd include; $(RM) *.o \#*\# *~ *.bak *.orig *.rej *.flc)
 
-distclean:
-	for i in $(ALLSUBDIRS); do (cd $$i; $(MAKE) distclean); done
-	$(RM) *.o \#*\# *~ *.bak wine wine.sym libwine.a TAGS
-	$(RM) include/\#*\# include/*~ include/*.bak include/*.flc
-	$(RM) config.* include/config.h Make.rules Makefile
+distclean: clean
+	$(RM) config.* Make.rules
+	$(RM) `find . \( -name Makefile -o -size 0 \) -print`
 
 dummy:
diff --git a/README b/README
index e00a177..5454385 100644
--- a/README
+++ b/README
@@ -38,81 +38,15 @@
 
 3. SETUP
 
+Once Wine has been built correctly, you can do "make install"; this
+will install the wine executable and the man page.
+
 Wine requires you to have a file /usr/local/etc/wine.conf (you can
 supply a different name when configuring wine) or a file called .winerc
 in your home directory.
 
-The format of this config file is just like a Windows .ini file.
-The file wine.ini contains a config file example.
-
-Here's an explanation of each section:
-
-* [drives]
-
-format: <driveletter> = <rootdirectory>
-default: none
-
-This section is used to specify the root directory of each `dos'drive 
-as Windows' applications require a dos/mswindows based diskdrive & 
-directory scheme. 
-
-If you mounted your dos-partition as /dos and installed Microsoft Windows 
-in c:\windows than you should specify c=/dos in the drives section.
-
-* [wine]
-
-format: windows = <directory>
-default: c:\windows
-
-Used to specify an different windows directory.
-
-format: system = <directory>
-default: c:\windows\system
-
-Used to specify an different system directory.
-
-format: temp = <directory>
-default: c:\temp
-
-Used to specify a directory where Windows applications can store temporary
-files.
-
-format: path = <directories separated by semi-colons>
-default: c:\windows;c:\windows\system
-
-Used to specify the path which will be used to find executables and DLL's.
-
-format: symboltablefile = <filename>
-default: wine.sym
-
-Used to specify the path and file name of the symbol table used by the
-built-in debugger.
-
-* [serialports]
-
-format: com[12345678] = <devicename>
-default: none
-
-Used to specify the devices which are used as com1 - com8.
-
-* [parallelports]
-
-format: lpt[12345678] = <devicename>
-default: none
-
-Used to specify the devices which are used as lpt1 - lpt8.
-
-* [spy]
-
-format: exclude = <message names and/or EXCLUDEALL separated by commas >
-default: none
-
-Used to specify which messages will be excluded from the message logging.
-
-format: include = <message names and/or INCLUDEALL separated by commas >
-default: none
-
-Used to specify which messages will be included in the message logging.
+The format of this file is explained in the man page. The file
+wine.ini contains a config file example.
 
 
 4. RUNNING PROGRAMS
diff --git a/configure b/configure
index 0689562..ba6c93e 100755
--- a/configure
+++ b/configure
@@ -15,6 +15,8 @@
 ac_help="$ac_help
   --with-library          build Wine as a library instead of an emulator"
 ac_help="$ac_help
+  --with-dll              build Wine as a DLL instead of an emulator"
+ac_help="$ac_help
   --with-ipc              use inter-process communication for DDE"
 ac_help="$ac_help
   --with-malloc-debug     enable malloc() debugging"
@@ -562,6 +564,20 @@
 fi
 
 
+# Check whether --with-dll or --without-dll was given.
+if test "${with_dll+set}" = set; then
+  withval="$with_dll"
+  cat >> confdefs.h <<\EOF
+#define WINELIB 1
+EOF
+ cat >> confdefs.h <<\EOF
+#define WINELIBDLL 1
+EOF
+
+ MAIN_TARGET="libwine.so.1.0" CFLAGS="$CFLAGS -fPIC"
+fi
+
+
 
 # Check whether --with-ipc or --without-ipc was given.
 if test "${with_ipc+set}" = set; then
@@ -700,7 +716,7 @@
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp.
   cat > conftest.$ac_ext <<EOF
-#line 704 "configure"
+#line 720 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
@@ -714,7 +730,7 @@
   rm -rf conftest*
   CPP="${CC-cc} -E -traditional-cpp"
   cat > conftest.$ac_ext <<EOF
-#line 718 "configure"
+#line 734 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
@@ -820,7 +836,7 @@
 test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc
 test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h
 cat > conftest.$ac_ext <<EOF
-#line 824 "configure"
+#line 840 "configure"
 #include "confdefs.h"
 #include <$x_direct_test_include>
 EOF
@@ -883,7 +899,7 @@
 ac_save_LIBS="$LIBS"
 LIBS="-l$x_direct_test_library $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 887 "configure"
+#line 903 "configure"
 #include "confdefs.h"
 
 int main() { return 0; }
@@ -1002,7 +1018,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lICE  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1006 "configure"
+#line 1022 "configure"
 #include "confdefs.h"
 
 int main() { return 0; }
@@ -1046,7 +1062,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-ldnet  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1050 "configure"
+#line 1066 "configure"
 #include "confdefs.h"
 
 int main() { return 0; }
@@ -1081,7 +1097,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-ldnet_stub  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1085 "configure"
+#line 1101 "configure"
 #include "confdefs.h"
 
 int main() { return 0; }
@@ -1121,7 +1137,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lnsl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1125 "configure"
+#line 1141 "configure"
 #include "confdefs.h"
 
 int main() { return 0; }
@@ -1160,7 +1176,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lsocket  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1164 "configure"
+#line 1180 "configure"
 #include "confdefs.h"
 
 int main() { return 0; }
@@ -1265,7 +1281,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-l$ac_lib  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1269 "configure"
+#line 1285 "configure"
 #include "confdefs.h"
 
 int main() { return 0; }
@@ -1388,7 +1404,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-li386  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1392 "configure"
+#line 1408 "configure"
 #include "confdefs.h"
 
 int main() { return 0; }
@@ -1428,7 +1444,7 @@
   ac_cv_c_cross=yes
 else
 cat > conftest.$ac_ext <<EOF
-#line 1432 "configure"
+#line 1448 "configure"
 #include "confdefs.h"
 main(){return(0);}
 EOF
@@ -1453,7 +1469,7 @@
   ac_cv_c_gcc_strength_bug="yes"
 else
 cat > conftest.$ac_ext <<EOF
-#line 1457 "configure"
+#line 1473 "configure"
 #include "confdefs.h"
 
 int main(void) {
@@ -1489,7 +1505,7 @@
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1493 "configure"
+#line 1509 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -1541,7 +1557,7 @@
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1545 "configure"
+#line 1561 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
@@ -1574,7 +1590,7 @@
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1578 "configure"
+#line 1594 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -1629,7 +1645,7 @@
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1633 "configure"
+#line 1649 "configure"
 #include "confdefs.h"
 
 int main() { return 0; }
@@ -1703,7 +1719,7 @@
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1707 "configure"
+#line 1723 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -1725,7 +1741,7 @@
 if test $ac_cv_header_stdc = yes; then
   # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 1729 "configure"
+#line 1745 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -1743,7 +1759,7 @@
 if test $ac_cv_header_stdc = yes; then
   # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 1747 "configure"
+#line 1763 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -1764,7 +1780,7 @@
   :
 else
 cat > conftest.$ac_ext <<EOF
-#line 1768 "configure"
+#line 1784 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -1799,7 +1815,7 @@
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1803 "configure"
+#line 1819 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
diff --git a/configure.in b/configure.in
index d8a94c0..9fbbd12 100644
--- a/configure.in
+++ b/configure.in
@@ -15,6 +15,11 @@
 AC_ARG_WITH(library,
 [  --with-library          build Wine as a library instead of an emulator],
 [AC_DEFINE(WINELIB) MAIN_TARGET="libwine.a"],[MAIN_TARGET="wine"])
+
+AC_ARG_WITH(dll,
+[  --with-dll              build Wine as a DLL instead of an emulator],
+[AC_DEFINE(WINELIB) AC_DEFINE(WINELIBDLL)
+ MAIN_TARGET="libwine.so.1.0" CFLAGS="$CFLAGS -fPIC"])
 AC_SUBST(MAIN_TARGET)
 
 AC_ARG_WITH(ipc,
diff --git a/controls/edit.c b/controls/edit.c
index 98c2841..c0f7222 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -71,7 +71,8 @@
     unsigned short *TabStops;/* tab stops buffer */
     BOOL HaveFocus;          /* TRUE if this edit has the focus */
     int ClientWidth;         /* computed from the window's ClientRect */
-    int ClientHeight;        /* dito */
+    int ClientHeight;        /* ditto */
+    char PasswordChar;       /* The password character */
 } EDITSTATE;
 
 #define EditBufStartLen(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & ES_MULTILINE \
@@ -509,11 +510,11 @@
 	es->BlankLine[(es->ClientWidth / es->CharWidths[32]) + 1] = 0;
     }
 
-    if ((GetWindowLong( hwnd, GWL_STYLE ) & ES_PASSWORD))
+    if ((es->PasswordChar && GetWindowLong( hwnd, GWL_STYLE ) & ES_PASSWORD))
     {
         int len = strlen(str);
         char *buff = xmalloc( len+1 );
-        memset( buff, '*', len );
+        memset( buff, es->PasswordChar, len );
         buff[len] = '\0';
 	TextOut( hdc, col - diff, row * es->txtht, buff, len );
     }
@@ -2269,6 +2270,7 @@
     es->ClientWidth = es->ClientHeight = 1;
     /* --- text buffer */
     es->MaxTextLen = MAXTEXTLEN + 1;
+    es->PasswordChar = '*';
     /*
      * Hack - If there is no local heap then hwnd should be a globalHeap block
      * and the local heap needs to be initilised to the same size(minus something)
@@ -2758,7 +2760,8 @@
 	break;
 
     case EM_GETPASSWORDCHAR:
-	fprintf(stdnimp,"edit: cannot process EM_GETPASSWORDCHAR message\n");
+        /* FIXME: is this the right place to return the character? */
+        lResult = es->PasswordChar;
 	break;
 
     case EM_GETRECT:
@@ -2820,7 +2823,7 @@
 	break;
 
     case EM_SETPASSWORDCHAR:
-	fprintf(stdnimp,"edit: cannot process EM_SETPASSWORDCHAR message\n");
+        es->PasswordChar = (char) wParam;
 	break;
 
     case EM_SETREADONLY:
diff --git a/controls/listbox.c b/controls/listbox.c
index 7ecd806..fc9ba60 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -25,6 +25,7 @@
 #include "listbox.h"
 #include "dos_fs.h"
 #include "drive.h"
+#include "file.h"
 #include "stackframe.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -338,7 +339,7 @@
 }
 
 
-int ListBoxInsertString(LPHEADLIST lphl, UINT uIndex, LPSTR newstr)
+int ListBoxInsertString(LPHEADLIST lphl, UINT uIndex, LPCSTR newstr)
 {
   LPLISTSTRUCT *lppls, lplsnew, lpls;
   HANDLE       hStr;
@@ -401,7 +402,7 @@
 }
 
 
-int ListBoxAddString(LPHEADLIST lphl, LPSTR newstr)
+int ListBoxAddString(LPHEADLIST lphl, LPCSTR newstr)
 {
     LONG dwStyle = GetWindowLong(lphl->hSelf,GWL_STYLE);
     UINT pos = (UINT) -1;
@@ -424,7 +425,7 @@
     dprintf_listbox(stddeb, "ListBoxGetText // OutStr==NULL\n");
     return 0;
   }
-
+  *OutStr = '\0';
   lpls = ListBoxGetItem (lphl, uIndex);
   if (lpls == NULL) return LB_ERR;
 
@@ -633,55 +634,42 @@
 
 /* ------------------------- dir listing ------------------------ */
 
-int ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPSTR filespec)
+LONG ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPCSTR filespec)
 {
-    const char *pathPtr, *maskPtr;
-    char mask[12], path[MAX_PATHNAME_LEN];
+    char temp[16], mask[13];
+    char *path, *p;
+    const char *ptr;
     int skip, count;
+    LONG ret;
     DOS_DIRENT entry;
 
-    char temp[256];
-    int   drive;
-    LPSTR tstr;
-
-  dprintf_listbox(stddeb,"ListBoxDirectory: %s, %4x\n",filespec,attrib);
-
-  if (strchr(filespec, '\\') || strchr(filespec, ':')) {
-    if (filespec[1] == ':') {
-      drive = toupper(filespec[0]) - 'A';
-      filespec += 2;
+    dprintf_listbox(stddeb, "ListBoxDirectory: '%s' %04x\n", filespec, attrib);
+    if (!filespec) return LB_ERR;
+    if (!(ptr = DOSFS_GetUnixFileName( filespec, FALSE ))) return LB_ERR;
+    path = xstrdup(ptr);
+    p = strrchr( path, '/' );
+    *p++ = '\0';
+    if (!(ptr = DOSFS_ToDosFCBFormat( p )))
+    {
+        free( path );
+        return LB_ERR;
     }
-    else drive = DRIVE_GetCurrentDrive();
-    strcpy(temp,filespec);
-    tstr = strrchr(temp, '\\');
-    if (tstr != NULL) {
-      *(tstr+1) = 0;
-      filespec += tstr - temp + 1;
-      if (!DRIVE_Chdir( drive, temp )) return 0;
-    }
-    DRIVE_SetCurrentDrive( drive );
-    dprintf_listbox(stddeb,"Changing directory to %c:%s, filemask is %s\n",
-		    drive+'A', temp, filespec);
-  }
+    strcpy( mask, ptr );
 
+    dprintf_listbox(stddeb, "ListBoxDirectory: path=%s mask=%s\n", path, mask);
 
-    if (!(maskPtr = DOSFS_ToDosFCBFormat( filespec ))) return 0;
-    strcpy( mask, maskPtr );
-    if (!(pathPtr = DOSFS_GetUnixFileName( ".", TRUE ))) return 0;
-    lstrcpyn( path, pathPtr, sizeof(path) );
-    skip  = 0;
-    drive = DRIVE_GetCurrentDrive();
-    
-    while ((count = DOSFS_FindNext( path, mask, drive,
-                                    attrib, skip, &entry )) > 0)
+    skip = ret = 0;
+    attrib &= ~FA_LABEL;
+    while ((count = DOSFS_FindNext( path, mask, 0, attrib, skip, &entry )) > 0)
     {
         skip += count;
         if (entry.attr & FA_DIRECTORY)
         {
-            if ((attrib & DDL_DIRECTORY) && strcmp(entry.name, "."))
+            if ((attrib & DDL_DIRECTORY) && strcmp(entry.name, ".          "))
             {
-                sprintf(temp, "[%s]", entry.name);
-                if (ListBoxAddString(lphl, temp) == LB_ERR) break;
+                sprintf(temp, "[%s]", DOSFS_ToDosDTAFormat( entry.name ) );
+                AnsiLower( temp );
+                if ((ret = ListBoxAddString(lphl, temp)) == LB_ERR) break;
             }
         }
         else  /* not a directory */
@@ -690,24 +678,23 @@
                 ((attrib & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)) ==
                  (entry.attr & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE))))
             {
-                if (ListBoxAddString(lphl, entry.name) == LB_ERR) break;
+                strcpy( temp, DOSFS_ToDosDTAFormat( entry.name ) );
+                AnsiLower( temp );
+                if ((ret = ListBoxAddString(lphl, temp)) == LB_ERR) break;
             }
         }
     }
-
     if (attrib & DDL_DRIVES)
     {
         int x;
-        for (x = 0; x < MAX_DOS_DRIVES; x++)
+        strcpy( temp, "[-a-]" );
+        for (x = 0; x < MAX_DOS_DRIVES; x++, temp[2]++)
         {
             if (DRIVE_IsValid(x))
-            {
-                sprintf(temp, "[-%c-]", 'a'+x);
-                if (ListBoxInsertString(lphl, (UINT)-1, temp) == LB_ERR) break;
-            }
+                if ((ret = ListBoxAddString(lphl, temp)) == LB_ERR) break;
         }
     }
-    return 1;
+    return ret;
 }
 
 /* ------------------------- dimensions ------------------------- */
@@ -1372,13 +1359,13 @@
  */
 static LONG LBDir(HWND hwnd, WORD wParam, LONG lParam)
 {
-  WORD   wRet;
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
+    LONG ret;
+    LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
+    dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
 
-  wRet = ListBoxDirectory(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
-  ListBoxUpdateWindow(hwnd, lphl, TRUE);
-  return wRet;
+    ret = ListBoxDirectory(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
+    ListBoxUpdateWindow(hwnd, lphl, TRUE);
+    return ret;
 }
 
 /***********************************************************************
@@ -1390,9 +1377,9 @@
   LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
 
   if (lphl->HasStrings)
-    wRet = ListBoxAddString(lphl, (LPSTR)PTR_SEG_TO_LIN(lParam));
+    wRet = ListBoxAddString(lphl, (LPCSTR)PTR_SEG_TO_LIN(lParam));
   else
-    wRet = ListBoxAddString(lphl, (LPSTR)lParam);
+    wRet = ListBoxAddString(lphl, (LPCSTR)lParam);
 
   ListBoxUpdateWindow(hwnd,lphl,TRUE);
   return wRet;
@@ -1421,9 +1408,9 @@
   LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
 
   if (lphl->HasStrings)
-    wRet = ListBoxInsertString(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
+    wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)PTR_SEG_TO_LIN(lParam));
   else
-    wRet = ListBoxInsertString(lphl, wParam, (LPSTR)lParam);
+    wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)lParam);
 
   ListBoxUpdateWindow(hwnd,lphl,TRUE);
   return wRet;
@@ -1895,70 +1882,126 @@
     return DefWindowProc(hwnd, message, wParam, lParam);
 }
 
-/************************************************************************
- * 		      	DlgDirSelect			[USER.99]
+
+/**********************************************************************
+ *	    DlgDirSelect    (USER.99)
  */
-BOOL DlgDirSelect(HWND hDlg, LPSTR lpStr, int nIDLBox)
+BOOL DlgDirSelect( HWND hDlg, LPSTR lpStr, int id )
 {
-  HWND hwnd;
-  LPHEADLIST lphl;
-  char s[130];
+    char buffer[20];
+    INT i;
 
-  dprintf_listbox( stddeb, "DlgDirSelect("NPFMT", '%s', %d) \n", hDlg, lpStr, 
-		  nIDLBox );
-
-  hwnd = GetDlgItem(hDlg, nIDLBox);
-  lphl = ListBoxGetStorageHeader(hwnd);
-  if(lphl->ItemFocused == -1) {
-    dprintf_listbox(stddeb, "Nothing selected!\n");
-    return FALSE;
-  }
-  ListBoxGetText(lphl, lphl->ItemFocused, s);
-  dprintf_listbox(stddeb, "Selection is %s\n", s);
-  if( s[0] == '[' ) {
-    if( s[1] == '-' ) {
-      strncpy( lpStr, s+2, strlen(s)-4 );    /* device name */
-      lpStr[ strlen(s)-4 ] = 0;
-      strcat( lpStr, ":" );
+    dprintf_listbox( stddeb, "DlgDirSelect: "NPFMT" '%s' %d\n",
+                     hDlg, lpStr, id );
+    if ((i = SendDlgItemMessage( hDlg, id, LB_GETCURSEL, 0, 0 )) == LB_ERR)
+        return FALSE;
+    SendDlgItemMessage( hDlg, id, LB_GETTEXT, i, MAKE_SEGPTR(buffer) );
+    if (buffer[0] == '[')  /* drive or directory */
+    {
+        if (buffer[1] == '-')  /* drive */
+        {
+            lpStr[0] = buffer[2];
+            lpStr[1] = ':';
+            lpStr[2] = '\0';
+            dprintf_listbox( stddeb, "Returning drive '%s'\n", lpStr );
+            return TRUE;
+        }
+        strcpy( lpStr, buffer + 1 );
+        lpStr[strlen(lpStr)-1] = '\\';
+        dprintf_listbox( stddeb, "Returning directory '%s'\n", lpStr );
+        return TRUE;
     }
-    else {
-      strncpy( lpStr, s+1, strlen(s)-2 );    /* directory name */
-      lpStr[ strlen(s)-2 ] = 0;
-      strcat( lpStr, "\\" );
-    }
-    dprintf_listbox( stddeb, "Returning %s\n", lpStr );
-    return TRUE;
-  } else {
-    strcpy( lpStr, s );                     /* file name */
-    dprintf_listbox( stddeb, "Returning %s\n", lpStr );
+    strcpy( lpStr, buffer );
+    dprintf_listbox( stddeb, "Returning file '%s'\n", lpStr );
     return FALSE;
-  }
 }
 
 
-/************************************************************************
- * 			   DlgDirList		       	[USER.100]
+/**********************************************************************
+ *	    DlgDirList    (USER.100)
  */
-INT DlgDirList( HWND hDlg, SEGPTR path, INT idLBox, INT idStatic, WORD wType ) 
+INT DlgDirList( HWND hDlg, SEGPTR spec, INT idLBox, INT idStatic, WORD attrib )
 {
-    INT ret = 0;
-  
-    dprintf_listbox( stddeb, "DlgDirList("NPFMT", %08lx, %d, %d, %04X) \n",
-                     hDlg, (DWORD)path, idLBox, idStatic, wType );
-    if (idLBox)
+    char *filespec = (char *)PTR_SEG_TO_LIN( spec );
+    int drive;
+    HWND hwnd;
+
+#define SENDMSG(msg,wparam,lparam) \
+    ((attrib & DDL_POSTMSGS) ? PostMessage( hwnd, msg, wparam, lparam ) \
+                             : SendMessage( hwnd, msg, wparam, lparam ))
+
+    dprintf_listbox( stddeb, "DlgDirList: "NPFMT" '%s' %d %d %04x\n",
+                     hDlg, filespec ? filespec : "NULL",
+                     idLBox, idStatic, attrib );
+
+    if (filespec && (filespec[1] == ':'))
     {
-        SendDlgItemMessage( hDlg, idLBox, LB_RESETCONTENT, 0, 0 );
-        ret = (SendDlgItemMessage( hDlg, idLBox, LB_DIR, wType, path ) >= 0);
+        drive = toupper( filespec[0] ) - 'A';
+        filespec += 2;
+        if (!DRIVE_SetCurrentDrive( drive )) return FALSE;
     }
-    if (idStatic)
+    else drive = DRIVE_GetCurrentDrive();
+
+    if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0))
+    {
+        char mask[20];
+        char temp[] = "*.*";
+        
+        if (!filespec[0]) strcpy( mask, "*.*" );
+        else
+        {
+            const char *ptr;
+            BYTE attr;
+            if (((ptr = DOSFS_GetUnixFileName( filespec, TRUE )) != NULL) &&
+                FILE_Stat( ptr, &attr, NULL, NULL, NULL ) &&
+                (attr & FA_DIRECTORY))
+            {
+                /* If the path exists and is a directory, chdir to it */
+                if (!DRIVE_Chdir( drive, filespec )) return FALSE;
+                strcpy( mask, "*.*" );
+            }
+            else
+            {
+                char *p, *p2;
+                p = filespec;
+                if ((p2 = strrchr( p, '\\' ))) p = p2 + 1;
+                if ((p2 = strrchr( p, '/' ))) p = p2 + 1;
+                lstrcpyn( mask, p, sizeof(mask) );
+                if (p != filespec)
+                {
+                    p[-1] = '\0';
+                    if (!DRIVE_Chdir( drive, filespec )) return FALSE;
+                }
+            }
+        }
+        
+        strcpy( (char *)PTR_SEG_TO_LIN(spec), mask );
+
+        dprintf_listbox(stddeb, "ListBoxDirectory: path=%c:\\%s mask=%s\n",
+                        'A' + drive, DRIVE_GetDosCwd(drive), mask);
+        
+        SENDMSG( LB_RESETCONTENT, 0, 0 );
+        if ((attrib & DDL_DIRECTORY) && !(attrib & DDL_EXCLUSIVE))
+        {
+            if (SENDMSG( LB_DIR, attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
+                         (LPARAM)spec ) == LB_ERR) return FALSE;
+            if (SENDMSG( LB_DIR, (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
+                         (LPARAM)MAKE_SEGPTR(temp) ) == LB_ERR) return FALSE;
+        }
+        else
+        {
+            if (SENDMSG( LB_DIR, attrib, (LPARAM)spec) == LB_ERR) return FALSE;
+        }
+    }
+
+    if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0))
     {
         char temp[256];
-        int drive = DRIVE_GetCurrentDrive();
         strcpy( temp, "A:\\" );
         temp[0] += drive;
         lstrcpyn( temp+3, DRIVE_GetDosCwd(drive), 253 );
-        SendDlgItemMessage( hDlg, idStatic, WM_SETTEXT,
-                            0, (LPARAM)MAKE_SEGPTR(temp) );
-    } 
-    return ret;
+        AnsiLower( temp );
+        SENDMSG( WM_SETTEXT, 0, (LPARAM)MAKE_SEGPTR(temp) );
+    }
+    return TRUE;
 }
diff --git a/controls/menu.c b/controls/menu.c
index e820d18..2398234 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -19,11 +19,14 @@
 #include "syscolor.h"
 #include "sysmetrics.h"
 #include "menu.h"
+#include "module.h"
+#include "neexe.h"
 #include "user.h"
 #include "win.h"
 #include "message.h"
 #include "graphics.h"
 #include "resource.h"
+#include "stackframe.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -51,14 +54,17 @@
 #define IS_STRING_ITEM(flags) (!((flags) & (MF_BITMAP | MF_OWNERDRAW | \
 			     MF_MENUBARBREAK | MF_MENUBREAK | MF_SEPARATOR)))
 
+#define SET_OWNERDRAW_DATA(item,data)  \
+  ((item)->hText = LOWORD((DWORD)(data)), (item)->xTab = HIWORD((DWORD)(data)))
+
+#define GET_OWNERDRAW_DATA(item)  \
+  ((DWORD)MAKELONG( (WORD)(item)->hText, (item)->xTab ))
 
 extern void NC_DrawSysButton(HWND hwnd, HDC hdc, BOOL down);  /* nonclient.c */
 
 static HBITMAP hStdCheck = 0;
 static HBITMAP hStdMnArrow = 0;
 
-WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu);
-
 
 /***********************************************************************
  *           MENU_Init
@@ -111,7 +117,7 @@
     POPUPMENU *menu;
 
     if (!(handle = SYSRES_LoadResource( SYSRES_MENU_SYSMENU ))) return 0;
-    hMenu = LoadMenuIndirect( GlobalLock( handle ) );
+    hMenu = LoadMenuIndirect( WIN16_GlobalLock( handle ) );
     SYSRES_FreeResource( handle );
     if (!hMenu)
     {
@@ -240,7 +246,7 @@
     {
 	if (IS_STRING_ITEM(lpitem->item_flags))
 	{
-	    char *p = strchr( lpitem->item_text, '&' );
+	    char *p = strchr( (char *)USER_HEAP_LIN_ADDR(lpitem->hText), '&' );
 	    if (p && (p[1] != '&') && (toupper(p[1]) == key)) return i;
 	}
     }
@@ -269,27 +275,21 @@
     char *p;
 
     SetRect( &lpitem->rect, orgX, orgY, orgX, orgY );
-    lpitem->xTab = 0;
-    if (lpitem->item_flags & MF_OWNERDRAW)  {
-      static HANDLE mistrh = 0;
-      static SEGPTR mistrsegp = 0;
-      static LPMEASUREITEMSTRUCT mistruct=NULL;
-      if (mistruct == NULL)  {
-	mistrh = GlobalAlloc(0,sizeof(MEASUREITEMSTRUCT));
-	mistrsegp = (SEGPTR)WIN16_GlobalLock(mistrh);
-	mistruct = PTR_SEG_TO_LIN(mistrsegp);
-      }
-      mistruct->CtlType = ODT_MENU;
-      mistruct->itemID = lpitem->item_id;
-      mistruct->itemData = (long int)lpitem->item_text;
-      mistruct->itemHeight = 16;
-      mistruct->itemWidth = 30;
-      SendMessage(hwndOwner,WM_MEASUREITEM,0,(LPARAM)mistrsegp);
-      lpitem->rect.bottom += mistruct->itemHeight;
-      lpitem->rect.right += mistruct->itemWidth;
-      dprintf_menu(stddeb,"DrawMenuItem: MeasureItem %04x %d:%d!\n",
-		   lpitem->item_id,mistruct->itemWidth, mistruct->itemHeight);
-      return;
+
+    if (lpitem->item_flags & MF_OWNERDRAW)
+    {
+        MEASUREITEMSTRUCT mis;
+        mis.CtlType    = ODT_MENU;
+        mis.itemID     = lpitem->item_id;
+        mis.itemData   = GET_OWNERDRAW_DATA(lpitem);
+        mis.itemHeight = 16;
+        mis.itemWidth  = 30;
+        SendMessage( hwndOwner, WM_MEASUREITEM, 0, (LPARAM)MAKE_SEGPTR(&mis) );
+        lpitem->rect.bottom += mis.itemHeight;
+        lpitem->rect.right  += mis.itemWidth;
+        dprintf_menu( stddeb, "DrawMenuItem: MeasureItem %04x %dx%d!\n",
+                      lpitem->item_id, mis.itemWidth, mis.itemHeight );
+        return;
     } 
 
     if (lpitem->item_flags & MF_SEPARATOR)
@@ -308,33 +308,38 @@
     if (lpitem->item_flags & MF_BITMAP)
     {
 	BITMAP bm;
-	GetObject( (HBITMAP)lpitem->hText, sizeof(BITMAP), (LPSTR)&bm );
-	lpitem->rect.right  += bm.bmWidth;
-	lpitem->rect.bottom += bm.bmHeight;
+        if (GetObject( (HBITMAP)lpitem->hText, sizeof(BITMAP), (LPSTR)&bm ))
+        {
+            lpitem->rect.right  += bm.bmWidth;
+            lpitem->rect.bottom += bm.bmHeight;
+        }
 	return;
     }
     
-      /* If we get here, then it is a text item */
+    /* If we get here, then it must be a text item */
 
-    dwSize = (lpitem->item_text == NULL) ? 0 : GetTextExtent( hdc, lpitem->item_text, strlen(lpitem->item_text));
-    lpitem->rect.right  += LOWORD(dwSize);
-    lpitem->rect.bottom += MAX( HIWORD(dwSize), SYSMETRICS_CYMENU );
+    if (IS_STRING_ITEM( lpitem->item_flags ))
+    {
+        const char *text = (const char *)USER_HEAP_LIN_ADDR( lpitem->hText );
+        dwSize = GetTextExtent( hdc, text, strlen(text) );
+        lpitem->rect.right  += LOWORD(dwSize);
+        lpitem->rect.bottom += MAX( HIWORD(dwSize), SYSMETRICS_CYMENU );
+        lpitem->xTab = 0;
 
-    if (menuBar) lpitem->rect.right += MENU_BAR_ITEMS_SPACE;
-    else if ( ( lpitem->item_text != NULL ) && (p = strchr( lpitem->item_text, '\t' )) != NULL)
-    {
-	  /* Item contains a tab (only meaningful in popup menus) */
-	lpitem->xTab = check_bitmap_width + MENU_TAB_SPACE + 
-	                 LOWORD( GetTextExtent( hdc, lpitem->item_text,
-					       (int)(p - lpitem->item_text) ));
-	lpitem->rect.right += MENU_TAB_SPACE;
-    }
-    else
-    {
-	if( ( lpitem->item_text != NULL ) && strchr( lpitem->item_text, '\b' ))
-	    lpitem->rect.right += MENU_TAB_SPACE;
-	lpitem->xTab = lpitem->rect.right - check_bitmap_width 
-	                - arrow_bitmap_width;
+        if (menuBar) lpitem->rect.right += MENU_BAR_ITEMS_SPACE;
+        else if ((p = strchr( text, '\t' )) != NULL)
+        {
+            /* Item contains a tab (only meaningful in popup menus) */
+            lpitem->xTab = check_bitmap_width + MENU_TAB_SPACE + 
+                LOWORD( GetTextExtent( hdc, text, (int)(p - text) ));
+            lpitem->rect.right += MENU_TAB_SPACE;
+        }
+        else
+        {
+            if (strchr( text, '\b' )) lpitem->rect.right += MENU_TAB_SPACE;
+            lpitem->xTab = lpitem->rect.right - check_bitmap_width 
+                           - arrow_bitmap_width;
+        }
     }
 }
 
@@ -372,7 +377,7 @@
             if (lpitem->item_flags & MF_MENUBARBREAK) orgX++;
 	    maxX = MAX( maxX, lpitem->rect.right );
 	    orgY = lpitem->rect.bottom;
-	    if (lpitem->xTab)
+	    if (IS_STRING_ITEM(lpitem->item_flags) && lpitem->xTab)
 	    {
 		maxTab = MAX( maxTab, lpitem->xTab );
 		maxTabWidth = MAX(maxTabWidth,lpitem->rect.right-lpitem->xTab);
@@ -384,7 +389,8 @@
 	for (lpitem = &items[start]; start < i; start++, lpitem++)
 	{
 	    lpitem->rect.right = maxX;
-	    if (lpitem->xTab) lpitem->xTab = maxTab;
+	    if (IS_STRING_ITEM(lpitem->item_flags) && lpitem->xTab)
+                lpitem->xTab = maxTab;
 	}
 	lppop->Height = MAX( lppop->Height, orgY );
     }
@@ -407,7 +413,7 @@
 
     if ((lprect == NULL) || (lppop == NULL)) return;
     if (lppop->nItems == 0) return;
-	dprintf_menucalc(stddeb,"MenuBarCalcSize left=%ld top=%ld right=%ld bottom=%ld !\n", 
+    dprintf_menu(stddeb,"MENU_MenuBarCalcSize left=%ld top=%ld right=%ld bottom=%ld !\n", 
 		(LONG)lprect->left, (LONG)lprect->top, (LONG)lprect->right, (LONG)lprect->bottom);
     items = (MENUITEM *)USER_HEAP_LIN_ADDR( lppop->hItems );
     lppop->Width  = lprect->right - lprect->left;
@@ -473,30 +479,26 @@
 {
     RECT rect;
 
-    if (lpitem->item_flags & MF_OWNERDRAW)  {
-      static HANDLE distrh = 0;
-      static SEGPTR distrsegp = 0;
-      static LPDRAWITEMSTRUCT distruct=NULL;
-      if (distruct == NULL)  {
-	distrh = GlobalAlloc(0,sizeof(DRAWITEMSTRUCT));
-	distrsegp = (SEGPTR)WIN16_GlobalLock(distrh);
-	distruct = PTR_SEG_TO_LIN(distrsegp);
-      }
-      dprintf_menu(stddeb,"DrawMenuItem: Ownerdraw!\n");
-      distruct->CtlType = ODT_MENU;
-      distruct->itemID = lpitem->item_id;
-      distruct->itemData = (long int)lpitem->item_text;
-      distruct->itemState = 0;
-      if (lpitem->item_flags & MF_CHECKED) distruct->itemState |= ODS_CHECKED;
-      if (lpitem->item_flags & MF_GRAYED) distruct->itemState |= ODS_GRAYED;
-      if (lpitem->item_flags & MF_HILITE) distruct->itemState |= ODS_SELECTED;
-      distruct->itemAction = ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS;
-      distruct->hwndItem = hwnd;
-      distruct->hDC = hdc;
-      distruct->rcItem = lpitem->rect;
-      SendMessage(hwnd,WM_DRAWITEM,0,(LPARAM)distrsegp);
-      return;
+    if (lpitem->item_flags & MF_OWNERDRAW)
+    {
+        DRAWITEMSTRUCT dis;
+
+        dprintf_menu( stddeb, "DrawMenuItem: Ownerdraw!\n" );
+        dis.CtlType   = ODT_MENU;
+        dis.itemID    = lpitem->item_id;
+        dis.itemData  = GET_OWNERDRAW_DATA(lpitem);
+        dis.itemState = 0;
+        if (lpitem->item_flags & MF_CHECKED) dis.itemState |= ODS_CHECKED;
+        if (lpitem->item_flags & MF_GRAYED)  dis.itemState |= ODS_GRAYED;
+        if (lpitem->item_flags & MF_HILITE)  dis.itemState |= ODS_SELECTED;
+        dis.itemAction = ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS;
+        dis.hwndItem   = hwnd;
+        dis.hDC        = hdc;
+        dis.rcItem     = lpitem->rect;
+        SendMessage( hwnd, WM_DRAWITEM, 0, MAKE_SEGPTR(&dis) );
+        return;
     }
+
     if (menuBar && (lpitem->item_flags & MF_SEPARATOR)) return;
     rect = lpitem->rect;
 
@@ -583,35 +585,34 @@
 	return;
     }
     /* No bitmap - process text if present */
-    else if ((lpitem->item_text) != ((char *) NULL)) 
+    else if (IS_STRING_ITEM(lpitem->item_flags))
     {
 	register int i;
+        const char *text = (const char *)USER_HEAP_LIN_ADDR( lpitem->hText );
 
 	if (menuBar)
 	{
 	    rect.left += MENU_BAR_ITEMS_SPACE / 2;
 	    rect.right -= MENU_BAR_ITEMS_SPACE / 2;
-	    i = strlen( lpitem->item_text );
+	    i = strlen( text );
 	}
 	else
 	{
-	    for (i = 0; lpitem->item_text[i]; i++)
-		if ((lpitem->item_text[i] == '\t') || 
-		    (lpitem->item_text[i] == '\b')) break;
+	    for (i = 0; text[i]; i++)
+                if ((text[i] == '\t') || (text[i] == '\b')) break;
 	}
 	
-	DrawText( hdc, lpitem->item_text, i, &rect,
-		 DT_LEFT | DT_VCENTER | DT_SINGLELINE );
+	DrawText( hdc, text, i, &rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE );
 
-	if (lpitem->item_text[i])  /* There's a tab or flush-right char */
+	if (text[i])  /* There's a tab or flush-right char */
 	{
-	    if (lpitem->item_text[i] == '\t')
+	    if (text[i] == '\t')
 	    {
 		rect.left = lpitem->xTab;
-		DrawText( hdc, lpitem->item_text + i + 1, -1, &rect,
+		DrawText( hdc, text + i + 1, -1, &rect,
 			  DT_LEFT | DT_VCENTER | DT_SINGLELINE );
 	    }
-	    else DrawText( hdc, lpitem->item_text + i + 1, -1, &rect,
+	    else DrawText( hdc, text + i + 1, -1, &rect,
 			   DT_RIGHT | DT_VCENTER | DT_SINGLELINE );
 	}
     }
@@ -887,6 +888,149 @@
 }
 
 
+/**********************************************************************
+ *         MENU_SetItemData
+ *
+ * Set an item flags, id and text ptr.
+ */
+static BOOL MENU_SetItemData( MENUITEM *item, UINT flags, UINT id, SEGPTR data)
+{
+    item->item_flags = flags & ~(MF_HILITE | MF_MOUSESELECT);
+    item->item_id    = id;
+
+    SetRectEmpty( &item->rect );
+    if (IS_STRING_ITEM(flags))
+    {
+        char *str = (char *)PTR_SEG_TO_LIN(data);
+        HANDLE hText;
+
+	  /* Item beginning with a backspace is a help item */
+	if (*str == '\b')
+	{
+	    item->item_flags |= MF_HELP;
+            str++;
+	}
+	if (!(hText = USER_HEAP_ALLOC( strlen(str)+1 ))) return FALSE;
+        item->hText = hText;
+	strcpy( (char *)USER_HEAP_LIN_ADDR( hText ), str );
+    }
+    else if (flags & MF_BITMAP) item->hText = (HANDLE)(DWORD)data;
+    else if (flags & MF_OWNERDRAW) SET_OWNERDRAW_DATA( item, data );
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *         MENU_InsertItem
+ *
+ * Insert a new item into a menu.
+ */
+static MENUITEM *MENU_InsertItem( HMENU hMenu, UINT pos, UINT flags )
+{
+    HANDLE hNewItems;
+    MENUITEM *newItems;
+    POPUPMENU *menu;
+
+    if (!(menu = (POPUPMENU *)USER_HEAP_LIN_ADDR(hMenu))) 
+    {
+        dprintf_menu( stddeb, "MENU_InsertItem: "NPFMT" not a menu handle\n",
+                      hMenu );
+        return NULL;
+    }
+
+    /* Find where to insert new item */
+
+    if ((flags & MF_BYPOSITION) &&
+        ((pos == (UINT)-1) || (pos == menu->nItems)))
+    {
+        /* Special case: append to menu */
+        /* Some programs specify the menu length to do that */
+        pos = menu->nItems;
+    }
+    else
+    {
+        if (!MENU_FindItem( &hMenu, &pos, flags )) 
+        {
+            dprintf_menu( stddeb, "MENU_InsertItem: item %x not found\n",
+                          pos );
+            return NULL;
+        }
+        if (!(menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu)))
+        {
+            dprintf_menu(stddeb,"MENU_InsertItem: "NPFMT" not a menu handle\n",
+                         hMenu);
+            return NULL;
+        }
+    }
+
+    /* Create new items array */
+
+    hNewItems = USER_HEAP_ALLOC( sizeof(MENUITEM) * (menu->nItems+1) );
+    if (!hNewItems)
+    {
+        dprintf_menu( stddeb, "MENU_InsertMenu: allocation failed\n" );
+        return NULL;
+    }
+    newItems = (MENUITEM *) USER_HEAP_LIN_ADDR( hNewItems );
+    if (menu->nItems > 0)
+    {
+	  /* Copy the old array into the new */
+	MENUITEM *oldItems = (MENUITEM *) USER_HEAP_LIN_ADDR( menu->hItems );
+	if (pos > 0) memcpy( newItems, oldItems, pos * sizeof(MENUITEM) );
+	if (pos < menu->nItems) memcpy( &newItems[pos+1], &oldItems[pos],
+					(menu->nItems-pos)*sizeof(MENUITEM) );
+
+	USER_HEAP_FREE( menu->hItems );
+    }
+    menu->hItems = hNewItems;
+    menu->nItems++;
+    return &newItems[pos];
+}
+
+
+/**********************************************************************
+ *         MENU_ParseResource
+ *
+ * Parse a menu resource and add items to the menu.
+ * Return a pointer to the end of the resource.
+ */
+static SEGPTR MENU_ParseResource( SEGPTR res, HMENU hMenu )
+{
+    WORD flags, id = 0;
+    SEGPTR data;
+
+    do
+    {
+        flags = *(WORD *)PTR_SEG_TO_LIN( res );
+        res += sizeof(WORD);
+        if (!(flags & MF_POPUP))
+        {
+            id = *(WORD *)PTR_SEG_TO_LIN( res );
+            res += sizeof(WORD);
+        }
+        data = res;
+        res += strlen( (char *)PTR_SEG_TO_LIN(data) ) + 1;
+        if (!IS_STRING_ITEM(flags))
+            fprintf( stderr, "MENU_ParseResource: not a string item %04x\n",
+                     flags );
+        if (flags & MF_POPUP)
+        {
+            HMENU hSubMenu = CreatePopupMenu();
+            if (!hSubMenu) return (SEGPTR)0;
+            if (!(res = MENU_ParseResource( res, hSubMenu ))) return (SEGPTR)0;
+            AppendMenu( hMenu, flags, (UINT)hSubMenu, data );
+        }
+        else
+        {
+            if (!id && !flags && !*(char *)PTR_SEG_TO_LIN(data))
+                flags |= MF_SEPARATOR;  /* FIXME: do this in InsertMenu? */
+            AppendMenu( hMenu, flags, id, data );
+        }
+    } while (!(flags & MF_END));
+    return res;
+}
+
+
 /***********************************************************************
  *           MENU_GetSubPopup
  *
@@ -1560,47 +1704,53 @@
 }
 
 
-/**********************************************************************
- *			ChangeMenu		[USER.153]
+/*******************************************************************
+ *         ChangeMenu    (USER.153)
  */
-BOOL ChangeMenu(HMENU hMenu, UINT nPos, LPSTR lpNewItem, 
-			UINT wItemID, UINT wFlags)
+BOOL ChangeMenu( HMENU hMenu, UINT pos, SEGPTR data, UINT id, UINT flags )
 {
-  dprintf_menu(stddeb,"ChangeMenu: menu="NPFMT" pos=%d ptr=%p item=%04x flags=%04x\n",
-	       hMenu, nPos, lpNewItem, wItemID, wFlags);
-  if (wFlags & MF_APPEND)  {
-    return AppendMenu(hMenu, wFlags & ~MF_APPEND, wItemID, lpNewItem);
-  }
-  if (wFlags & MF_DELETE) {
-    /* FIXME: Word passes the item id in nPos and 0 or 0xffff as id */
-    /* for MF_DELETE. We should check the parameters for all others */
-    /* MF_* actions also (anybody got a doc on ChangeMenu?). */
-    return DeleteMenu(hMenu, nPos, wFlags & ~MF_DELETE);
-  }
-  if (wFlags & MF_CHANGE) {
-    return ModifyMenu(hMenu, nPos, wFlags & ~MF_CHANGE, wItemID, lpNewItem);
-  }
-  if (wFlags & MF_REMOVE) {
-    return RemoveMenu(hMenu, wFlags & MF_BYPOSITION ? nPos : wItemID,
-		      wFlags & ~MF_REMOVE);
-  }
-  /* Default: MF_INSERT */
-  return InsertMenu(hMenu, nPos, wFlags, wItemID, lpNewItem);
+    dprintf_menu( stddeb,"ChangeMenu: menu="NPFMT" pos=%d data=%08lx id=%04x flags=%04x\n",
+                  hMenu, pos, data, id, flags );
+    if (flags & MF_APPEND)
+    {
+        return AppendMenu( hMenu, flags & ~MF_APPEND, id, data );
+    }
+    if (flags & MF_DELETE)
+    {
+        /* FIXME: Word passes the item id in 'pos' and 0 or 0xffff as id */
+        /* for MF_DELETE. We should check the parameters for all others */
+        /* MF_* actions also (anybody got a doc on ChangeMenu?). */
+        return DeleteMenu( hMenu, pos, flags & ~MF_DELETE );
+    }
+    if (flags & MF_CHANGE)
+    {
+        return ModifyMenu( hMenu, pos, flags & ~MF_CHANGE, id, data );
+    }
+    if (flags & MF_REMOVE)
+    {
+        return RemoveMenu( hMenu, flags & MF_BYPOSITION ? pos : id,
+                           flags & ~MF_REMOVE );
+    }
+    /* Default: MF_INSERT */
+    return InsertMenu( hMenu, pos, flags, id, data );
 }
 
 
-/**********************************************************************
- *			CheckMenuItem		[USER.154]
+/*******************************************************************
+ *         CheckMenuItem    (USER.154)
  */
-BOOL CheckMenuItem(HMENU hMenu, UINT wItemID, UINT wFlags)
+INT CheckMenuItem( HMENU hMenu, UINT id, UINT flags )
 {
-	LPMENUITEM 	lpitem;
-	dprintf_menu(stddeb,"CheckMenuItem ("NPFMT", %04X, %04X) !\n", 
-		     hMenu, wItemID, wFlags);
-	if (!(lpitem = MENU_FindItem(&hMenu, &wItemID, wFlags))) return FALSE;
-	if (wFlags & MF_CHECKED) lpitem->item_flags |= MF_CHECKED;
-	else lpitem->item_flags &= ~MF_CHECKED;
-	return TRUE;
+    MENUITEM *item;
+    INT ret;
+
+    dprintf_menu( stddeb,"CheckMenuItem: "NPFMT" %04x %04x\n", 
+                  hMenu, id, flags );
+    if (!(item = MENU_FindItem( &hMenu, &id, flags ))) return -1;
+    ret = item->item_flags & MF_CHECKED;
+    if (flags & MF_CHECKED) item->item_flags |= MF_CHECKED;
+    else item->item_flags &= ~MF_CHECKED;
+    return ret;
 }
 
 
@@ -1644,12 +1794,10 @@
     if (!str || !nMaxSiz) return 0;
     str[0] = '\0';
     if (!(lpitem = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return 0;
-    if (!lpitem->item_text || !IS_STRING_ITEM(lpitem->item_flags)) return 0;
-    nMaxSiz = MIN( nMaxSiz-1, strlen(lpitem->item_text) );
-    strncpy( str, lpitem->item_text, nMaxSiz );
-    str[nMaxSiz] = '\0';
+    if (!IS_STRING_ITEM(lpitem->item_flags)) return 0;
+    lstrcpyn( str, (char *)USER_HEAP_LIN_ADDR(lpitem->hText), nMaxSiz );
     dprintf_menu( stddeb, "GetMenuString: returning '%s'\n", str );
-    return nMaxSiz;
+    return strlen(str);
 }
 
 
@@ -1722,117 +1870,47 @@
 }
 
 
-/**********************************************************************
- *			InsertMenu		[USER.410]
+/*******************************************************************
+ *         InsertMenu    (USER.410)
  */
-BOOL InsertMenu(HMENU hMenu, UINT nPos, UINT wFlags, UINT wItemID, LPSTR lpNewItem)
+BOOL InsertMenu( HMENU hMenu, UINT pos, UINT flags, UINT id, SEGPTR data )
 {
-    HANDLE hNewItems;
-    MENUITEM *lpitem, *newItems;
-    LPPOPUPMENU	menu;
+    MENUITEM *item;
 
-    if (IS_STRING_ITEM(wFlags))
+    if (IS_STRING_ITEM(flags))
     {
-        dprintf_menu(stddeb,"InsertMenu ("NPFMT", %04X, %04X, %04X, '%s') !\n",
-                     hMenu, nPos, wFlags, wItemID,
-                     lpNewItem ? lpNewItem : "(null)");
-        if (!lpNewItem) return FALSE;
+        dprintf_menu( stddeb, "InsertMenu: "NPFMT" %d %04x %04x '%s'\n",
+                      hMenu, pos, flags, id,
+                      data ? (char *)PTR_SEG_TO_LIN(data) : "#NULL#" );
+        if (!data) return FALSE;
     }
-    else
-        dprintf_menu(stddeb,"InsertMenu ("NPFMT", %04X, %04X, %04X, %p) !\n",
-                     hMenu, nPos, wFlags, wItemID, lpNewItem);
+    else dprintf_menu( stddeb, "InsertMenu: "NPFMT" %d %04x %04x %08lx\n",
+                       hMenu, pos, flags, id, (DWORD)data );
 
-      /* Find where to insert new item */
+    if (!(item = MENU_InsertItem( hMenu, pos, flags ))) return FALSE;
 
-    if ((wFlags & MF_BYPOSITION) && 
-        ((nPos == (UINT)-1) || (nPos == (UINT)GetMenuItemCount(hMenu))))
+    if (!(MENU_SetItemData( item, flags, id, data )))
     {
-          /* Special case: append to menu 
-             Some programs specify the menu length to do that */
-        if (!(menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu))) 
-        {
-            dprintf_menu(stddeb,"InsertMenu: "NPFMT" not a menu handle\n", hMenu);
-            return FALSE;
-        }
-        nPos = menu->nItems;
-    }
-    else
-    {
-        if (!MENU_FindItem( &hMenu, &nPos, wFlags )) 
-        {
-            dprintf_menu(stddeb,"InsertMenu: Item %X not found\n", nPos);
-            return FALSE;
-        }
-        if (!(menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu)))
-        {
-            dprintf_menu(stddeb,"InsertMenu: "NPFMT" not a menu handle\n", hMenu);
-            return FALSE;
-        }
-    }
-
-      /* Create new items array */
-
-    hNewItems = USER_HEAP_ALLOC( sizeof(MENUITEM) * (menu->nItems+1) );
-    if (!hNewItems)
-    {
-        dprintf_menu(stddeb,"InsertMenu: allocation failed\n");
+        item->hText = 0;
+        RemoveMenu( hMenu, pos, flags );
         return FALSE;
     }
-    newItems = (MENUITEM *) USER_HEAP_LIN_ADDR( hNewItems );
-    if (menu->nItems > 0)
-    {
-	  /* Copy the old array into the new */
-	MENUITEM *oldItems = (MENUITEM *) USER_HEAP_LIN_ADDR( menu->hItems );
-	if (nPos > 0) memcpy( newItems, oldItems, nPos * sizeof(MENUITEM) );
-	if (nPos < menu->nItems) memcpy( &newItems[nPos+1], &oldItems[nPos],
-					(menu->nItems-nPos)*sizeof(MENUITEM) );
 
-	USER_HEAP_FREE( menu->hItems );
-    }
-    menu->hItems = hNewItems;
-    menu->nItems++;
+    if (flags & MF_POPUP)  /* Set the MF_POPUP flag on the popup-menu */
+	((POPUPMENU *)USER_HEAP_LIN_ADDR((HMENU)id))->wFlags |= MF_POPUP;
 
-      /* Store the new item data */
-
-    lpitem = &newItems[nPos];
-    lpitem->item_flags = wFlags & ~(MF_HILITE | MF_MOUSESELECT);
-    lpitem->item_id    = wItemID;
-
-    if (IS_STRING_ITEM(wFlags))
-    {
-	  /* Item beginning with a backspace is a help item */
-	if (lpNewItem[0] == '\b')
-	{
-	    lpitem->item_flags |= MF_HELP;
-	    lpNewItem++;
-	}
-	lpitem->hText = USER_HEAP_ALLOC( strlen(lpNewItem)+1 );
-	lpitem->item_text = (char *)USER_HEAP_LIN_ADDR( lpitem->hText );
-	strcpy( lpitem->item_text, lpNewItem );
-    }
-#ifdef WINELIB32
-    else if (wFlags & MF_BITMAP) lpitem->hText = (HANDLE)lpNewItem;
-#else
-    else if (wFlags & MF_BITMAP) lpitem->hText = LOWORD((DWORD)lpNewItem);
-#endif
-    else lpitem->item_text = lpNewItem;
-
-    if (wFlags & MF_POPUP)  /* Set the MF_POPUP flag on the popup-menu */
-	((POPUPMENU *)USER_HEAP_LIN_ADDR((HMENU)wItemID))->wFlags |= MF_POPUP;
-
-    SetRectEmpty( &lpitem->rect );
-    lpitem->hCheckBit   = hStdCheck;
-    lpitem->hUnCheckBit = 0;
+    item->hCheckBit   = hStdCheck;
+    item->hUnCheckBit = 0;
     return TRUE;
 }
 
 
-/**********************************************************************
- *			AppendMenu		[USER.411]
+/*******************************************************************
+ *         AppendMenu    (USER.411)
  */
-BOOL AppendMenu(HMENU hMenu, UINT wFlags, UINT wItemID, LPSTR lpNewItem)
+BOOL AppendMenu( HMENU hMenu, UINT flags, UINT id, SEGPTR data )
 {
-    return InsertMenu( hMenu, -1, wFlags | MF_BYPOSITION, wItemID, lpNewItem );
+    return InsertMenu( hMenu, -1, flags | MF_BYPOSITION, id, data );
 }
 
 
@@ -1885,40 +1963,29 @@
 }
 
 
-/**********************************************************************
- *			ModifyMenu		[USER.414]
+/*******************************************************************
+ *         ModifyMenu    (USER.414)
  */
-BOOL ModifyMenu(HMENU hMenu, UINT nPos, UINT wFlags, UINT wItemID, LPSTR lpNewItem)
+BOOL ModifyMenu( HMENU hMenu, UINT pos, UINT flags, UINT id, SEGPTR data )
 {
-    LPMENUITEM 	lpitem;
-    if (IS_STRING_ITEM(wFlags))
+    MENUITEM *item;
+    HANDLE hText = 0;
+
+    if (IS_STRING_ITEM(flags))
     {
-	dprintf_menu(stddeb,"ModifyMenu ("NPFMT", %04X, %04X, %04X, '%s') !\n",
-	       hMenu, nPos, wFlags, wItemID, lpNewItem ? lpNewItem : "(null)");
-        if (!lpNewItem) return FALSE;
+	dprintf_menu( stddeb, "ModifyMenu: "NPFMT" %d %04x %04x '%s'\n",
+                      hMenu, pos, flags, id,
+                      data ? (char *)PTR_SEG_TO_LIN(data) : "#NULL#");
+        if (!data) return FALSE;
     }
     else
-	dprintf_menu(stddeb,"ModifyMenu ("NPFMT", %04X, %04X, %04X, %p) !\n",
-	       hMenu, nPos, wFlags, wItemID, lpNewItem);
-    if (!(lpitem = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE;
-    
-    if (IS_STRING_ITEM(lpitem->item_flags)) USER_HEAP_FREE( lpitem->hText );
-    lpitem->item_flags = wFlags & ~(MF_HILITE | MF_MOUSESELECT);
-    lpitem->item_id    = wItemID;
+	dprintf_menu( stddeb, "ModifyMenu: "NPFMT" %d %04x %04x %08lx\n",
+                      hMenu, pos, flags, id, (DWORD)data );
+    if (!(item = MENU_FindItem( &hMenu, &pos, flags ))) return FALSE;
 
-    if (IS_STRING_ITEM(wFlags))
-    {
-	lpitem->hText = USER_HEAP_ALLOC( strlen(lpNewItem)+1 );
-	lpitem->item_text = (char *)USER_HEAP_LIN_ADDR( lpitem->hText );
-	strcpy( lpitem->item_text, lpNewItem );
-    }
-#ifdef WINELIB32
-    else if (wFlags & MF_BITMAP) lpitem->hText = (HANDLE)lpNewItem;
-#else
-    else if (wFlags & MF_BITMAP) lpitem->hText = LOWORD((DWORD)lpNewItem);
-#endif
-    else lpitem->item_text = lpNewItem;
-    SetRectEmpty( &lpitem->rect );
+    if (IS_STRING_ITEM(item->item_flags)) hText = item->hText;
+    if (!MENU_SetItemData( item, flags, id, data )) return FALSE;
+    if (hText) USER_HEAP_FREE( hText );
     return TRUE;
 }
 
@@ -2045,14 +2112,17 @@
     return wndPtr->hSysMenu;
 }
 
-/**********************************************************************
- *			SetSystemMenu		[USER.280]
+
+/*******************************************************************
+ *         SetSystemMenu    (USER.280)
  */
-BOOL SetSystemMenu(HWND hWnd, HMENU newHmenu)
+BOOL SetSystemMenu( HWND hwnd, HMENU hMenu )
 {
     WND *wndPtr;
 
-    if ((wndPtr = WIN_FindWndPtr(hWnd)) != NULL) wndPtr->hSysMenu = newHmenu;
+    if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
+    if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
+    wndPtr->hSysMenu = hMenu;
     return TRUE;
 }
 
@@ -2146,7 +2216,7 @@
  */
 void EndMenu(void)
 {
-      /* Note: this won't work when we have multiple tasks... */
+    /* FIXME: this won't work when we have multiple tasks... */
     fEndMenuCalled = TRUE;
 }
 
@@ -2181,68 +2251,36 @@
 
     if (!name) return 0;
 
-    if (!(hRsrc = FindResource( instance, name, RT_MENU ))) return 0;
+    if (!(hRsrc = FindResource( instance, name, RT_MENU ))) {
+		/* check for Win32 module */
+		instance =  GetExePtr( instance );
+		if(((NE_MODULE*)GlobalLock(instance))->magic == PE_SIGNATURE)
+			return WIN32_LoadMenuA(instance,PTR_SEG_TO_LIN(name));
+		return 0;
+	}
     if (!(handle = LoadResource( instance, hRsrc ))) return 0;
-    hMenu = LoadMenuIndirect( LockResource(handle) );
+    hMenu = LoadMenuIndirect( WIN16_LockResource(handle) );
     FreeResource( handle );
     return hMenu;
 }
 
 
 /**********************************************************************
- *			LoadMenuIndirect	[USER.220]
+ *	    LoadMenuIndirect    (USER.220)
  */
-HMENU LoadMenuIndirect(LPSTR menu_template)
+HMENU LoadMenuIndirect( SEGPTR template )
 {
-	HMENU     		hMenu;
-	MENU_HEADER 	*menu_desc;
-	dprintf_menu(stddeb,"LoadMenuIndirect: menu_template '%p'\n", 
-		     menu_template);
-	hMenu = CreateMenu();
-	menu_desc = (MENU_HEADER *)menu_template;
-	ParseMenuResource((WORD *)(menu_desc + 1), 0, hMenu); 
-	return hMenu;
-}
+    HMENU hMenu;
 
-
-/**********************************************************************
- *			ParseMenuResource (from Resource or Template)
- */
-WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu)
-{
-    WORD 	*item;
-    WORD 	*next_item;
-    HMENU	hSubMenu;
-    int   	i;
-
-    level++;
-    next_item = first_item;
-    i = 0;
-    do {
-	i++;
-	item = next_item;
-	if (*item & MF_POPUP) {
-	    MENU_POPUPITEM *popup_item = (MENU_POPUPITEM *) item;
-	    next_item = (WORD *) (popup_item->item_text + 
-				  strlen(popup_item->item_text) + 1);
-	    hSubMenu = CreatePopupMenu();
-	    next_item = ParseMenuResource(next_item, level, hSubMenu);
-	    AppendMenu(hMenu, popup_item->item_flags, 
-	    	(UINT)hSubMenu, popup_item->item_text);
-	    }
-	else
-        {
-            MENUITEMTEMPLATE *normal_item = (MENUITEMTEMPLATE *) item;
-            WORD flags = normal_item->item_flags;
-            next_item = (WORD *) (normal_item->item_text + 
-                                  strlen(normal_item->item_text) + 1);
-            if (!normal_item->item_text[0] && !normal_item->item_id) 
-                flags |= MF_SEPARATOR;  /* FIXME: do this in InsertMenu? */
-            AppendMenu( hMenu, flags, normal_item->item_id,
-                        normal_item->item_text );
-        }
-    } while (!(*item & MF_END));
-    return next_item;
+    dprintf_menu(stddeb,"LoadMenuIndirect: %08lx\n", (DWORD)template );
+    if (!(hMenu = CreateMenu())) return (HMENU)0;
+    template += sizeof(MENU_HEADER);
+    if (!MENU_ParseResource( template, hMenu ))
+    {
+        DestroyMenu( hMenu );
+        return (HMENU)0;
+    }
+    return hMenu;
 }
 
 
diff --git a/controls/static.c b/controls/static.c
index ce81252..0e9cf1a 100644
--- a/controls/static.c
+++ b/controls/static.c
@@ -88,8 +88,13 @@
             {
 		CREATESTRUCT * createStruct = (CREATESTRUCT *)PTR_SEG_TO_LIN(lParam);
 		if (createStruct->lpszName)
-                    STATIC_SetIcon( hWnd, LoadIcon( createStruct->hInstance,
-                                             (SEGPTR)createStruct->lpszName ));
+                {
+                    HICON hicon = LoadIcon( createStruct->hInstance,
+                                            (SEGPTR)createStruct->lpszName );
+                    if (!hicon)  /* Try OEM icon (FIXME: is this right?) */
+                        hicon = LoadIcon( 0, (SEGPTR)createStruct->lpszName );
+                    STATIC_SetIcon( hWnd, hicon );
+                }
                 return 1;
             }
             return DefWindowProc(hWnd, uMsg, wParam, lParam);
@@ -195,23 +200,23 @@
     switch (style & 0x0000000F)
     {
     case SS_LEFT:
-	wFormat = DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK;
+	wFormat = DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK | DT_NOCLIP;
 	break;
 
     case SS_CENTER:
-	wFormat = DT_CENTER | DT_EXPANDTABS | DT_WORDBREAK;
+	wFormat = DT_CENTER | DT_EXPANDTABS | DT_WORDBREAK | DT_NOCLIP;
 	break;
 
     case SS_RIGHT:
-	wFormat = DT_RIGHT | DT_EXPANDTABS | DT_WORDBREAK;
+	wFormat = DT_RIGHT | DT_EXPANDTABS | DT_WORDBREAK | DT_NOCLIP;
 	break;
 
     case SS_SIMPLE:
-	wFormat = DT_LEFT | DT_SINGLELINE | DT_VCENTER;
+	wFormat = DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_NOCLIP;
 	break;
 
     case SS_LEFTNOWORDWRAP:
-	wFormat = DT_LEFT | DT_SINGLELINE | DT_EXPANDTABS | DT_VCENTER;
+	wFormat = DT_LEFT | DT_SINGLELINE | DT_EXPANDTABS | DT_VCENTER | DT_NOCLIP;
 	break;
 
     default:
diff --git a/controls/widgets.c b/controls/widgets.c
index 5559dd1..ccbe8c8 100644
--- a/controls/widgets.c
+++ b/controls/widgets.c
@@ -23,16 +23,16 @@
           sizeof(BUTTONINFO), 0, 0, 0, 0, 0, (SEGPTR)"BUTTON" },
     { CS_GLOBALCLASS | CS_PARENTDC, (WNDPROC)"StaticWndProc", 0,
           sizeof(STATICINFO), 0, 0, 0, 0, 0, (SEGPTR)"STATIC" },
-    { CS_GLOBALCLASS | CS_PARENTDC, (WNDPROC)"ScrollBarWndProc", 0,
+    { CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW | CS_PARENTDC , (WNDPROC)"ScrollBarWndProc", 0,
           sizeof(SCROLLINFO), 0, 0, 0, 0, 0, (SEGPTR)"SCROLLBAR" },
     { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS, (WNDPROC)"ListBoxWndProc", 0,
           8, 0, 0, 0, 0, 0, (SEGPTR)"LISTBOX" },
     { CS_GLOBALCLASS | CS_PARENTDC, (WNDPROC)"ComboBoxWndProc", 0, 8,
           0, 0, 0, 0, 0, (SEGPTR)"COMBOBOX" },
-    { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS, (WNDPROC)"ComboLBoxWndProc",
+    { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS | CS_SAVEBITS, (WNDPROC)"ComboLBoxWndProc",
           0, 8, 0, 0, 0, 0, 0, (SEGPTR)"COMBOLBOX" },
-    { CS_GLOBALCLASS, (WNDPROC)"EditWndProc", 0, sizeof(DWORD),
-          0, 0, 0, 0, 0, (SEGPTR)"EDIT" },
+    { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS, (WNDPROC)"EditWndProc",
+          0, sizeof(DWORD), 0, 0, 0, 0, 0, (SEGPTR)"EDIT" },
     { CS_GLOBALCLASS | CS_SAVEBITS, (WNDPROC)"PopupMenuWndProc", 0, 8,
           0, 0, 0, 0, 0, (SEGPTR)POPUPMENU_CLASS_NAME },
     { CS_GLOBALCLASS, (WNDPROC)"DesktopWndProc", 0, sizeof(DESKTOPINFO),
diff --git a/debugger/break.c b/debugger/break.c
index 8e9fbb8..78e4cc6 100644
--- a/debugger/break.c
+++ b/debugger/break.c
@@ -12,7 +12,6 @@
 #include "debugger.h"
 
 #define INT3          0xcc   /* int 3 opcode */
-#define STEP_FLAG     0x100  /* single-step flag */
 
 #define MAX_BREAKPOINTS 25
 
diff --git a/debugger/dbg.y b/debugger/dbg.y
index 0d9f94c..d42eac7 100644
--- a/debugger/dbg.y
+++ b/debugger/dbg.y
@@ -215,8 +215,8 @@
     if (!loaded_symbols)
     {
         loaded_symbols++;
-        GetPrivateProfileString("wine", "SymbolTableFile", "wine.sym",
-                          SymbolTableFile, sizeof(SymbolTableFile), WINE_INI);
+        PROFILE_GetWineIniString( "wine", "SymbolTableFile", "wine.sym",
+                                  SymbolTableFile, sizeof(SymbolTableFile) );
         DEBUG_ReadSymbolTable( SymbolTableFile );
         DEBUG_LoadEntryPoints();
     }
diff --git a/documentation/apiw.index b/documentation/apiw.index
new file mode 100644
index 0000000..23868bb
--- /dev/null
+++ b/documentation/apiw.index
@@ -0,0 +1,594 @@
+AbortDoc:2_15_01
+AccessResource:3_07_01
+AddAtom:1_12_01
+AddFontResource:2_13_01
+AllocResource:3_07_13
+AnimatePalette:2_04_01
+AnsiLower:4_03_01
+AnsiLowerBuff:4_03_01
+AnsiNext:4_03_03
+AnsiPrev:4_03_03
+AnsiToOem:4_03_14
+AnsiToOemBuff:4_03_14
+AnsiUpper:4_03_02
+AnsiUpperBuff:4_03_02
+AppendMenu:1_05_01
+Arc:2_11_01
+ArrangeIconicWindows:1_03_03
+BeginPaint:1_14_01
+BitBlt:2_12_09
+BringWindowToTop:1_03_05
+BuildCommDCB:3_08_01
+CallWindowProc:1_01_01
+CallWndProc:1_11_06
+Catch:3_05_01
+CheckMenuItem:1_05_07
+CheckRadioButton:1_13_02
+ChildWindowFromPoint:1_04_07
+ChooseColor:4_09_01
+ChooseFont:4_09_02
+Chord:2_11_01
+ClassFirst:3_11_01
+ClassNext:3_11_01
+ClearCommBreak:3_08_02
+ClientToScreen:2_07_10
+ClipCursor:1_08_06
+CloseComm:3_08_03
+CloseWindow:1_03_06
+CombineRgn:2_08_01
+CommDlgExtendedError:4_09_07
+CopyCursor:1_08_08
+CopyIcon:2_02_01
+CopyLZFile:4_07_01
+CopyMetaFile:2_05_02
+CopyRect:4_04_01
+CreateBitmap:2_12_01
+CreateBitmapIndirect:2_12_01
+CreateCompatibleBitmap:2_12_03
+CreateDC:2_01_02
+CreateDIBPatternBrush:2_10_02
+CreateDialog:1_13_03
+CreateDialogIndirect:1_13_03
+CreateDialogIndirectParam:1_13_04
+CreateDialogParam:1_13_04
+CreateDiscardableBitmap:2_12_03
+CreateEllipticRgn:2_08_02
+CreateEllipticRgnIndirect:2_08_02
+CreateFont:2_13_03
+CreateFontIndirect:2_13_03
+CreateHatchBrush:2_10_03
+CreateIC:2_01_02
+CreateIcon:2_02_04
+CreateMenu:1_05_03
+CreatePalette:2_04_02
+CreatePatternBrush:2_10_08
+CreatePolyPolygonRgn:2_08_03
+CreatePolygonRgn:2_08_03
+CreatePopupMenu:1_05_03
+CreateRectRgn:2_08_04
+CreateRectRgnIndirect:2_08_04
+CreateRoundRectRgn:2_08_05
+CreateSolidBrush:2_10_04
+DPtoLP:2_07_01
+DebugOutput:4_05_02
+DefDlgProc:1_02_10
+DefFrameProc:1_02_11
+DefMDIChildProc:1_02_12
+DefWindowProc:1_02_13
+DeleteAtom:1_12_02
+DeleteDC:2_01_04
+DeleteMenu:1_05_02
+DeleteMetaFile:2_05_03
+DeleteObject:2_03_04
+DestroyIcon:2_02_03
+DestroyMenu:1_05_02
+DestroyWindow:1_02_08
+DeviceCapabilities:2_15_02
+DeviceMode:2_15_03
+DialogBox:1_13_05
+DialogBoxIndirect:1_13_05
+DialogBoxIndirectParam:1_13_06
+DialogBoxParam:1_13_06
+DirectedYield:3_05_02
+DispatchMessage:1_01_02
+DlgDirList:1_13_07
+DlgDirListComboBox:1_13_07
+DlgDirSelect:1_13_08
+DlgDirSelectComboBox:1_13_08
+DlgDirSelectComboBox:1_13_20
+DlgDirSelectComboBoxEx:1_13_20
+DlgDirSelectEx:1_13_21
+DrawFocusRect:2_11_07
+DrawIcon:2_02_02
+DrawMenuBar:1_05_05
+Ellipse:2_11_05
+EnableCommNotification:3_08_04
+EnableHardwareInput:3_06_01
+EnableMenuItem:1_05_07
+EnableScrollBar:1_06_05
+EnableWindow:1_03_10
+EndDialog:1_13_09
+EndDoc:2_15_04
+EndPage:2_15_05
+EndPaint:1_14_02
+EnumChildWindows:1_04_05
+EnumFontFamilies:2_13_05
+EnumFonts:2_13_05
+EnumMetaFile:2_05_04
+EnumObjects:2_03_05
+EnumTaskWindows:3_05_08
+EnumWindows:1_04_04
+EqualRect:4_04_02
+EqualRgn:2_08_06
+Escape:2_15_06
+EscapeCommFunction:3_08_05
+ExcludeUpdateRgn:1_14_03
+ExitWindows:3_05_11
+ExtDeviceMode:2_15_07
+ExtFloodFill:2_11_09
+ExtTextOut:2_14_02
+ExtractIcon:4_01_01
+FatalAppExit:4_05_03
+FatalExit:4_05_04
+FillRect:2_11_08
+FillRgn:2_11_06
+FindAtom:1_12_03
+FindExecutable:4_01_02
+FindResource:3_07_02
+FindText:4_09_03
+FindWindow:1_04_06
+FlashWindow:4_06_01
+FloodFill:2_11_09
+FlushComm:3_08_06
+FrameRect:2_11_08
+FrameRgn:2_11_06
+FreeLibrary:3_03_01
+FreeProcInstance:3_03_05
+FreeResource:3_07_03
+GetActiveWindow:1_03_11
+GetAspectRatioFilter:2_13_12
+GetAspectRatioFilterEx:2_13_12
+GetAsyncKeyState:3_06_02
+GetAsyncKeyState:3_06_03
+GetAtomName:1_12_04
+GetBitmapBits:2_12_04
+GetBkColor:1_14_14
+GetBkMode:1_14_15
+GetBoundsRect:1_14_16
+GetBrushOrg:2_10_06
+GetBrushOrgEx:2_10_06
+GetCapture:1_03_12
+GetCaretBlinkTime:1_07_02
+GetCaretPos:1_07_03
+GetCharABCWidths:2_13_06
+GetCharWidth:2_13_06
+GetClassInfo:1_02_02
+GetClassLong:1_02_05
+GetClassName:1_02_03
+GetClassWord:1_02_04
+GetClientRect:1_04_02
+GetClipCursor:1_08_07
+GetClipboardData:1_10_05
+GetClipboardFormatName:1_10_03
+GetCommError:3_08_07
+GetCommEventMask:3_08_08
+GetCommState:3_08_09
+GetCurrentPosition:1_14_17
+GetCurrentPositionEx:1_14_17
+GetCurrentTask:3_05_03
+GetCurrentTime:3_02_03
+GetCursor:1_08_05
+GetCursorPos:1_08_03
+GetDC:2_01_03
+GetDCEx:2_01_03
+GetDCOrg:2_01_08
+GetDIBits:2_12_05
+GetDOSEnvironment:3_01_06
+GetDesktopWindow:1_03_21
+GetDeviceCaps:2_15_08
+GetDialogBaseUnits:1_13_10
+GetDlgCtrlID:1_13_11
+GetDlgItem:1_13_12
+GetDlgItemInt:1_13_13
+GetDlgItemText:1_13_14
+GetDoubleClickTime:3_02_02
+GetDriveType:3_09_01
+GetExpandedName:4_07_02
+GetFileTitle:4_09_05
+GetFocus:1_03_13
+GetFontData:2_13_07
+GetFreeSpace:3_04_01
+GetGlyphOutline:2_13_08
+GetInstanceData:3_03_08
+GetKBCodePage:3_06_07
+GetKerningPairs:2_13_09
+GetKeyNameText:3_06_05
+GetKeyState:3_06_06
+GetKeyboardType:3_06_12
+GetLastActivePopup:1_03_16
+GetMapMode:1_14_11
+GetMenu:1_05_04
+GetMenuCheckMarkDimensions:1_05_11
+GetMenuItemCount:1_05_10
+GetMenuItemID:1_05_08
+GetMenuState:1_05_09
+GetMenuString:1_05_09
+GetMessage:1_01_03
+GetMessageExtraInfo:1_01_14
+GetMessagePos:1_01_05
+GetMessageTime:1_01_05
+GetMetaFile:2_05_05
+GetModuleFileName:3_03_03
+GetModuleFileName:3_03_09
+GetModuleHandle:3_03_03
+GetModuleHandle:3_03_09
+GetModuleUsage:3_03_03
+GetModuleUsage:3_03_09
+GetMsgProc:1_11_07
+GetNearestColor:2_04_03
+GetNearestPaletteIndex:2_04_03
+GetNextWindow:1_03_19
+GetNumTasks:3_05_04
+GetObject:2_03_06
+GetOpenFileName:4_09_04
+GetOutlineTextMetrics:2_13_10
+GetParent:1_03_18
+GetPolyFillMode:1_14_12
+GetPrivateProfileInt:4_02_03
+GetPrivateProfileString:4_02_01
+GetProcAddress:3_03_04
+GetProfileInt:4_02_03
+GetProfileString:4_02_01
+GetQueueStatus:1_01_15
+GetROP2:1_14_13
+GetRasterizerCaps:2_13_11
+GetRgnBox:2_08_07
+GetSaveFileName:4_09_04
+GetScrollRange:1_06_02
+GetStockObject:2_03_07
+GetStretchBltMode:2_12_10
+GetSubMenu:1_05_08
+GetSysColor:2_04_08
+GetSysModalWindow:1_03_14
+GetSystemDirectory:3_09_02
+GetSystemMenu:1_05_06
+GetSystemMetrics:3_01_04
+GetSystemPaletteUse:2_04_05
+GetTabbedTextExtent:2_14_03
+GetTempDrive:3_09_03
+GetTempFileName:3_09_04
+GetTextAlign:2_14_04
+GetTextColor:2_14_06
+GetTextExtent:2_14_03
+GetTextExtentPoint:2_14_03
+GetTextFace:2_14_07
+GetTextMetrics:2_14_08
+GetTickCount:3_02_03
+GetTimerResoultion:3_02_04
+GetTopWindow:1_03_19
+GetUpdateRgn:1_14_05
+GetVersion:3_01_05
+GetWinFlags:3_01_03
+GetWindow:1_03_19
+GetWindowDC:2_01_03
+GetWindowExt:2_07_02
+GetWindowExtEx:2_07_02
+GetWindowLong:1_02_15
+GetWindowOrg:2_07_03
+GetWindowOrgEx:2_07_03
+GetWindowPlacement:1_03_22
+GetWindowRect:1_04_02
+GetWindowTask:3_05_05
+GetWindowText:1_04_03
+GetWindowTextLength:1_04_03
+GetWindowWord:1_02_14
+GetWindowsDirectory:3_09_05
+GlobalAddAtom:1_12_01
+GlobalAlloc:3_04_02
+GlobalCompact:3_04_03
+GlobalDeleteAtom:1_12_02
+GlobalEntryHandle:3_11_03
+GlobalEntryModule:3_11_03
+GlobalFindAtom:1_12_03
+GlobalFirst:3_11_02
+GlobalFix:3_04_04
+GlobalFlags:3_04_05
+GlobalFree:3_04_02
+GlobalGetAtomName:1_12_04
+GlobalHandle:3_04_06
+GlobalHandleToSel:3_11_04
+GlobalInfo:3_11_05
+GlobalLRUNewest:3_04_08
+GlobalLRUOldest:3_04_08
+GlobalLock:3_04_07
+GlobalNext:3_11_02
+GlobalNotify:3_04_09
+GlobalReAlloc:3_04_10
+GlobalSize:3_04_11
+GlobalUnfix:3_04_04
+GlobalUnlock:3_04_07
+GrayString:2_14_09
+GrayStringProc:2_14_09
+HideCaret:1_07_04
+HiliteMenuItem:1_05_07
+InSendMessage:1_01_06
+InflateRect:4_04_01
+InitAtomTable:1_12_05
+InsertMenu:1_05_01
+InterruptRegister:3_11_19
+InterruptUnRegister:3_11_19
+IntersectClipRect:2_09_02
+IntersectRect:4_04_03
+InvalidateRect:1_14_18
+InvalidateRgn:1_14_08
+InvertRect:1_14_06
+InvertRgn:2_11_06
+IsBadCodePtr:3_12_01
+IsBadHugeWritePtr:3_12_03
+IsBadReadPtr:3_12_04
+IsBadStringPtr:3_12_05
+IsBadWritePtr:3_12_06
+IsCharAlpha:4_03_04
+IsCharAlphaNumeric:4_03_05
+IsCharLower:4_03_06
+IsCharUpper:4_03_07
+IsDBCSLeadByte:4_03_12
+IsDialogMessage:1_13_16
+IsDlgButtonChecked:1_03_17
+IsGDIObject:2_03_08
+IsIconic:1_03_07
+IsMenu:1_05_15
+IsRectEmpty:4_04_02
+IsTask:3_05_06
+IsWindow:1_03_09
+IsWindowEnabled:1_03_10
+IsWindowVisible:1_03_02
+IsZoomed:1_03_07
+LPtoDP:2_07_01
+LZClose:4_07_03
+LZCopy:4_07_10
+LZDone:4_07_04
+LZInit:4_07_05
+LZOpenFile:4_07_06
+LZRead:4_07_07
+LZSeek:4_07_08
+LZStart:4_07_09
+LimitEmsPages:3_04_14
+LineDDA:2_11_02
+LineTo:2_11_03
+LoadAccelerators:3_07_12
+LoadBitmap:3_07_07
+LoadCursor:1_08_02
+LoadIcon:3_07_06
+LoadLibrary:3_03_01
+LoadMenu:3_07_10
+LoadMenuIndirect:3_07_11
+LoadResource:3_07_03
+LoadString:3_07_05
+LocalAlloc:3_04_02
+LocalCompact:3_04_03
+LocalFirst:3_11_06
+LocalFlags:3_04_05
+LocalFree:3_04_02
+LocalHandle:3_04_06
+LocalInfo:3_11_07
+LocalInit:3_04_13
+LocalLock:3_04_07
+LocalNext:3_11_06
+LocalReAlloc:3_04_10
+LocalShrink:3_04_13
+LocalSize:3_04_11
+LocalUnlock:3_04_07
+LockInput:4_05_06
+LockWindowUpdate:1_14_10
+MakeProcInstance:3_03_05
+MapDialogRect:1_13_18
+MapVirtualKey:3_06_09
+MapWindowPoints:2_07_08
+MemManInfo:3_11_08
+MemoryRead:3_11_09
+MemoryWrite:3_11_09
+MessageBeep:4_06_02
+MessageBox:4_06_03
+ModifyMenu:1_05_01
+ModuleFindHandle:3_11_13
+ModuleFindName:3_11_13
+ModuleFirst:3_11_12
+ModuleNext:3_11_12
+MoveTo:2_11_03
+MoveToEx:2_11_03
+MoveWindow:1_03_20
+NotifyRegister:3_11_20
+NotifyUnregister:3_11_20
+OemKeyScan:3_06_08
+OffsetClipRgn:2_09_03
+OffsetRect:4_04_01
+OffsetRgn:2_08_08
+OffsetViewportOrg:2_06_03
+OffsetViewportOrgEx:2_06_03
+OffsetWindowOrg:2_07_04
+OffsetWindowOrgEx:2_07_04
+OpenComm:3_08_03
+OpenFile:3_09_06
+OpenIcon:1_03_04
+OutputDebugString:4_05_01
+PaintRgn:2_11_06
+PatBlt:2_12_08
+PeekMessage:1_01_03
+Pie:2_11_01
+PlayMetaFile:2_05_07
+PlayMetaFileRecord:2_05_07
+PolyPolygon:2_11_04
+Polygon:2_11_04
+Polyline:2_11_03
+PostAppMessage:1_01_07
+PostMessage:1_01_07
+PostQuitMessage:1_01_07
+PrintDlg:4_09_06
+PtInRect:4_04_02
+PtInRegion:2_08_09
+PtVisible:2_03_02
+QueryAbort:2_15_13
+QuerySendMessage:4_05_05
+ReadComm:3_08_10
+RealizePalette:2_04_06
+RectInRegion:2_08_10
+RectVisible:2_03_02
+RectVisible:2_03_03
+Rectangle:2_11_05
+RedrawWindow:1_14_09
+RegCloseKey:3_10_01
+RegCreateKey:3_10_02
+RegDeleteKey:3_10_03
+RegEnumKey:3_10_04
+RegOpenKey:3_10_02
+RegQueryValue:3_10_05
+RegSetValue:3_10_05
+RegisterClass:1_02_01
+RegisterClipboardFormat:1_10_03
+RegisterWindowMessage:1_01_13
+ReleaseCapture:1_03_12
+ReleaseDC:2_01_05
+RemoveFontResource:2_13_02
+RemoveMenu:1_05_02
+RemoveProp:1_09_02
+ReplaceText:4_09_03
+ReplyMessage:1_01_06
+ResetDC:2_01_07
+ResizePalette:2_04_11
+RoundRect:2_11_05
+ScaleViewportExt:2_06_04
+ScaleViewportExtEx:2_06_04
+ScaleWindowExt:2_07_05
+ScaleWindowExtEx:2_07_05
+ScreenToClient:2_07_10
+ScrollDC:1_06_06
+ScrollWindow:1_06_04
+SelectClipRect:2_09_04
+SelectPalette:2_04_07
+SendDlgItemMessage:1_13_19
+SendMessage:1_01_08
+SetAbortProc:2_15_09
+SetActiveWindow:1_03_11
+SetBitmapBits:2_12_04
+SetBkColor:1_14_14
+SetBkMode:1_14_15
+SetBoundsRect:1_14_16
+SetBrushOrg:2_10_07
+SetCapture:1_03_12
+SetCaretBlinkTime:1_07_02
+SetCaretPos:1_07_03
+SetClassLong:1_02_05
+SetClassWord:1_02_04
+SetClipboardData:1_10_05
+SetCommBreak:3_08_02
+SetCommEventMask:3_08_08
+SetCommState:3_08_09
+SetCursor:1_08_05
+SetCursorPos:1_08_03
+SetDIBits:2_12_05
+SetDIBitsToDevice:2_12_06
+SetDlgItemInt:1_13_13
+SetDlgItemText:1_13_14
+SetDoubleClickTime:3_02_02
+SetFocus:1_03_13
+SetHandleCount:3_09_07
+SetMapMode:1_14_11
+SetMapperFlags:2_13_13
+SetMenu:1_05_14
+SetMenuItemBitmaps:1_05_12
+SetMessageQueue:1_01_09
+SetParent:1_03_18
+SetPolyFillMode:1_14_12
+SetROP2:1_14_13
+SetRect:4_04_01
+SetRectEmpty:4_04_01
+SetRectRgn:2_08_11
+SetResourceHandler:3_07_08
+SetScrollRange:1_06_02
+SetStretchBltMode:2_12_10
+SetSysColors:2_04_09
+SetSysModalWindow:1_03_14
+SetSystemPaletteUse:2_04_05
+SetTextAlign:2_14_04
+SetTextColor:2_14_06
+SetTextJustification:2_14_10
+SetViewportExt:2_06_05
+SetViewportExtEx:2_06_05
+SetWindowExt:2_07_06
+SetWindowExtEx:2_07_06
+SetWindowLong:1_01_01
+SetWindowLong:1_02_06
+SetWindowOrg:2_07_07
+SetWindowOrgEx:2_07_07
+SetWindowPlacement:1_03_22
+SetWindowText:1_04_03
+SetWindowWord:1_02_16
+ShellExecute:4_01_03
+ShowCaret:1_07_04
+ShowCursor:1_08_04
+ShowOwnedPopups:1_03_08
+ShowScrollBar:1_06_03
+ShowWindow:1_03_02
+SizeofResource:3_07_09
+SpoolFile:2_15_10
+StackTraceCSIPFirst:3_11_11
+StackTraceFirst:3_11_11
+StackTraceNext:3_11_11
+StartDoc:2_15_11
+StartPage:2_15_12
+StretchBlt:2_12_09
+StretchDIBits:2_12_07
+SubtractRect:4_04_03
+SystemHeapInfo:3_11_10
+SystemParametersInfo:3_01_02
+TabbedTextOut:2_14_02
+TaskFindHandle:3_11_21
+TaskFirst:3_11_14
+TaskGetCSIP:3_11_15
+TaskNext:3_11_14
+TaskSetCSIP:3_11_15
+TaskSwitch:3_11_16
+TerminateApp:3_11_17
+TextOut:2_14_02
+Throw:3_05_01
+TimerCount:3_11_18
+ToAscii:4_03_13
+TrackPopupMenu:1_05_13
+TranslateAccelerator:1_01_10
+TranslateMDISysAccel:1_01_11
+TranslateMessage:1_01_12
+TransmitCommChar:3_08_11
+UngetCommChar:3_08_11
+UnionRect:4_04_03
+UnrealizeObject:2_03_01
+UnregisterClass:1_02_01
+UpdateColors:2_04_10
+UpdateWindow:1_14_07
+ValidateRect:1_14_18
+ValidateRgn:1_14_08
+VkKeyScan:3_06_10
+VkKeyScan:3_06_11
+WaitMessage:1_01_04
+WinExec:3_05_09
+WinHelp:3_05_07
+WindowFromPoint:2_07_09
+WriteComm:3_08_10
+WritePrivateProfileString:4_02_02
+WriteProfileString:4_02_02
+Yield:3_05_02
+_hread:3_09_09
+_lclose:3_09_08
+_lcreat:3_09_10
+_llseek:3_09_11
+_lopen:3_09_12
+_lread:3_09_09
+hmemcpy:3_04_12
+lstrcat:4_03_09
+lstrcmp:4_03_08
+lstrcmpi:4_03_08
+lstrcpy:4_03_09
+lstrcpyn:4_03_09
+lstrlen:4_03_10
+wsprintf:4_03_11
+wvsprintf:4_03_11
diff --git a/files/Makefile.in b/files/Makefile.in
index 5fee060..cf17c1c 100644
--- a/files/Makefile.in
+++ b/files/Makefile.in
@@ -5,7 +5,8 @@
 	directory.c \
 	dos_fs.c \
 	drive.c \
-	file.c
+	file.c \
+	profile.c
 
 all: $(MODULE).o
 
diff --git a/files/directory.c b/files/directory.c
index 9de0c52..5365bd6 100644
--- a/files/directory.c
+++ b/files/directory.c
@@ -13,6 +13,7 @@
 #include "drive.h"
 #include "file.h"
 #include "msdos.h"
+#include "options.h"
 #include "xmalloc.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -42,8 +43,7 @@
     const char *dos_name ,*unix_name;
     BYTE attr;
 
-    GetPrivateProfileString( "wine", keyname, defval,
-                             path, sizeof(path), WineIniFileName() );
+    PROFILE_GetWineIniString( "wine", keyname, defval, path, sizeof(path) );
     if (!(unix_name = DOSFS_GetUnixFileName( path, TRUE )) ||
         !FILE_Stat( unix_name, &attr, NULL, NULL, NULL ) ||
         !(attr & FA_DIRECTORY))
@@ -117,7 +117,7 @@
  */
 int DIR_Init(void)
 {
-    char path[MAX_PATHNAME_LEN];
+    char path[MAX_PATHNAME_LEN], *env_p;
     int drive;
     const char *cwd;
 
@@ -153,14 +153,26 @@
         DRIVE_Chdir( drive, DIR_WindowsDosDir + 2 );
     }
 
-    GetPrivateProfileString( "wine", "path", "c:\\windows;c:\\windows\\system",
-                             path, sizeof(path), WineIniFileName() );
+    PROFILE_GetWineIniString("wine", "path", "c:\\windows;c:\\windows\\system",
+                             path, sizeof(path) );
     DIR_ParseWindowsPath( path );
 
     dprintf_dosfs( stddeb, "WindowsDir = %s\nSystemDir  = %s\n",
                    DIR_WindowsDosDir, DIR_SystemDosDir );
     dprintf_dosfs( stddeb, "TempDir    = %s\nCwd        = %c:\\%s\n",
                    DIR_TempDosDir, 'A' + drive, DRIVE_GetDosCwd( drive ) );
+
+    /* Put the temp and Windows directories into the environment */
+
+    env_p = (char *)xmalloc( strlen(DIR_TempDosDir) + 5 );
+    strcpy( env_p, "TEMP=" );
+    strcpy( env_p + 5, DIR_TempDosDir );
+    putenv( env_p );
+    env_p = (char *)xmalloc( strlen(DIR_WindowsDosDir) + 7 );
+    strcpy( env_p, "windir=" );
+    strcpy( env_p + 7, DIR_WindowsDosDir );
+    putenv( env_p );
+
     return 1;
 }
 
diff --git a/files/dos_fs.c b/files/dos_fs.c
index 6f4e921..29131ec 100644
--- a/files/dos_fs.c
+++ b/files/dos_fs.c
@@ -25,7 +25,7 @@
 #include "debug.h"
 
 /* Chars we don't want to see in DOS file names */
-#define INVALID_DOS_CHARS  "*?<>|\"+=,; "
+#define INVALID_DOS_CHARS  "*?<>|\"+=,;[] \345"
 
 static const char *DOSFS_Devices[][2] =
 {
@@ -264,7 +264,8 @@
     if (pTime)
         *pTime = (tm->tm_hour << 11) + (tm->tm_min << 5) + (tm->tm_sec / 2);
     if (pDate)
-        *pDate = ((tm->tm_year - 80) << 9) + (tm->tm_mon << 5) + tm->tm_mday;
+        *pDate = ((tm->tm_year - 80) << 9) + ((tm->tm_mon + 1) << 5)
+                 + tm->tm_mday;
 }
 
 
@@ -506,7 +507,7 @@
             p += strlen(p);
             while (!IS_END_OF_NAME(*name)) name++;
         }
-        else
+        else if (!check_last)
         {
             *p++ = '/';
             for (len--; !IS_END_OF_NAME(*name) && (len > 1); name++, len--)
@@ -517,16 +518,16 @@
     }
     if (!found)
     {
-        if (*name)  /* Not last */
-        {
-            DOS_ERROR( ER_PathNotFound, EC_NotFound, SA_Abort, EL_Disk );
-            return NULL;
-        }
         if (check_last)
         {
             DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
             return NULL;
         }
+        if (*name)  /* Not last */
+        {
+            DOS_ERROR( ER_PathNotFound, EC_NotFound, SA_Abort, EL_Disk );
+            return NULL;
+        }
     }
     if (!buffer[0]) strcpy( buffer, "/" );
     dprintf_dosfs( stddeb, "DOSFS_GetUnixFileName: returning %s\n", buffer );
@@ -571,19 +572,20 @@
         return NULL;
     }
 
-    strcpy( buffer, "A:\\" );
-    buffer[0] += drive;
-    if ((name[0] == '\\') || (name[0] == '/'))
+    p = buffer;
+    *p++ = 'A' + drive;
+    *p++ = ':';
+    if (IS_END_OF_NAME(*name))
     {
         while ((*name == '\\') || (*name == '/')) name++;
-        p = buffer + 2;
     }
     else
     {
-        lstrcpyn( buffer + 3, DRIVE_GetDosCwd(drive), len - 3 );
-        if (buffer[3]) p = buffer + strlen(buffer);
-        else p = buffer + 2;
+        *p++ = '\\';
+        lstrcpyn( p, DRIVE_GetDosCwd(drive), sizeof(buffer) - 3 );
+        if (*p) p += strlen(p); else p--;
     }
+    *p = '\0';
     len = MAX_PATHNAME_LEN - (int)(p - buffer);
 
     while (*name)
@@ -616,10 +618,10 @@
                 name++;
                 len--;
             }
+            *p = '\0';
         }
         while ((*name == '\\') || (*name == '/')) name++;
     }
-    *p = '\0';
     if (!buffer[2])
     {
         buffer[2] = '\\';
@@ -639,10 +641,12 @@
 int DOSFS_FindNext( const char *path, const char *mask, int drive,
                     BYTE attr, int skip, DOS_DIRENT *entry )
 {
-    DIR *dir;
+    static DIR *dir = NULL;
     struct dirent *dirent;
     int count = 0;
-    char buffer[MAX_PATHNAME_LEN], *p;
+    static char buffer[MAX_PATHNAME_LEN];
+    static int cur_pos = 0;
+    char *p;
     const char *hash_name;
     
     if ((attr & ~(FA_UNUSED | FA_ARCHIVE | FA_RDONLY)) == FA_LABEL)
@@ -656,8 +660,17 @@
         return 1;
     }
 
-    if (!(dir = opendir( path ))) return 0;
-    strcpy( buffer, path );
+    /* Check the cached directory */
+    if (dir && !strcmp( buffer, path ) && (cur_pos <= skip)) skip -= cur_pos;
+    else  /* Not in the cache, open it anew */
+    {
+        dprintf_dosfs( stddeb, "DOSFS_FindNext: cache miss, path=%s skip=%d buf=%s cur=%d\n",
+                       path, skip, buffer, cur_pos );
+        cur_pos = skip;
+        if (dir) closedir(dir);
+        if (!(dir = opendir( path ))) return 0;
+        lstrcpyn( buffer, path, sizeof(buffer) - 1 );
+    }
     strcat( buffer, "/" );
     p = buffer + strlen(buffer);
     attr |= FA_UNUSED | FA_ARCHIVE | FA_RDONLY;
@@ -668,7 +681,7 @@
         count++;
         hash_name = DOSFS_Hash( dirent->d_name, TRUE );
         if (!DOSFS_Match( mask, hash_name )) continue;
-        strcpy( p, dirent->d_name );
+        lstrcpyn( p, dirent->d_name, sizeof(buffer) - (int)(p - buffer) );
 
         if (!FILE_Stat( buffer, &entry->attr, &entry->size,
                         &entry->date, &entry->time ))
@@ -681,9 +694,11 @@
         lstrcpyn( entry->unixname, dirent->d_name, sizeof(entry->unixname) );
         dprintf_dosfs( stddeb, "DOSFS_FindNext: returning %s %02x %ld\n",
                        entry->name, entry->attr, entry->size );
-        closedir( dir );
+        cur_pos += count;
+        p[-1] = '\0';  /* Remove trailing slash in buffer */
         return count;
     }
     closedir( dir );
+    dir = NULL;
     return 0;  /* End of directory */
 }
diff --git a/files/drive.c b/files/drive.c
index ae2558d..5c72a54 100644
--- a/files/drive.c
+++ b/files/drive.c
@@ -1,5 +1,5 @@
 /*
- * DOS drive handling functions
+ * DOS drives handling functions
  *
  * Copyright 1993 Erik Bos
  * Copyright 1996 Alexandre Julliard
@@ -7,12 +7,26 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include <sys/stat.h>
+
+#if defined(__linux__) || defined(sun)
+#include <sys/vfs.h>
+#endif
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/errno.h>
+#endif
+#ifdef __svr4__
+#include <sys/statfs.h>
+#endif
 
 #include "windows.h"
 #include "dos_fs.h"
 #include "drive.h"
 #include "file.h"
 #include "msdos.h"
+#include "options.h"
 #include "task.h"
 #include "xmalloc.h"
 #include "stddebug.h"
@@ -20,74 +34,128 @@
 
 typedef struct
 {
-    char *root;      /* root dir in Unix format without trailing '/' */
-    char *dos_cwd;   /* cwd in DOS format without leading or trailing '\' */
-    char *unix_cwd;  /* cwd in Unix format without leading or trailing '/' */
-    char  label[12]; /* drive label */
-    DWORD serial;    /* drive serial number */
-    WORD  type;      /* drive type */
-    BYTE  disabled;  /* disabled flag */
+    char     *root;      /* root dir in Unix format without trailing / */
+    char     *dos_cwd;   /* cwd in DOS format without leading or trailing \ */
+    char     *unix_cwd;  /* cwd in Unix format without leading or trailing / */
+    char      label[12]; /* drive label */
+    DWORD     serial;    /* drive serial number */
+    DRIVETYPE type;      /* drive type */
+    BYTE  disabled;      /* disabled flag */
 } DOSDRIVE;
 
+
+static const char *DRIVE_Types[] =
+{
+    "floppy",   /* TYPE_FLOPPY */
+    "hd",       /* TYPE_HD */
+    "cdrom",    /* TYPE_CDROM */
+    "network"   /* TYPE_NETWORK */
+};
+
+
 static DOSDRIVE DOSDrives[MAX_DOS_DRIVES];
-static int DRIVE_CurDrive = 0;
+static int DRIVE_CurDrive = -1;
 
 static HTASK DRIVE_LastTask = 0;
 
+
+/***********************************************************************
+ *           DRIVE_GetDriveType
+ */
+static DRIVETYPE DRIVE_GetDriveType( const char *name )
+{
+    char buffer[20];
+    int i;
+
+    PROFILE_GetWineIniString( name, "Type", "hd", buffer, sizeof(buffer) );
+    for (i = 0; i < sizeof(DRIVE_Types)/sizeof(DRIVE_Types[0]); i++)
+    {
+        if (!lstrcmpi( buffer, DRIVE_Types[i] )) return (DRIVETYPE)i;
+    }
+    fprintf( stderr, "%s: unknown type '%s', defaulting to 'hd'.\n",
+             name, buffer );
+    return TYPE_HD;
+}
+
+
 /***********************************************************************
  *           DRIVE_Init
  */
 int DRIVE_Init(void)
 {
-    int i, count = 0;
-    char drive[2] = "A";
+    int i, len, count = 0;
+    char name[] = "Drive A";
     char path[MAX_PATHNAME_LEN];
+    char buffer[20];
     char *p;
+    DOSDRIVE *drive;
 
-    for (i = 0; i < MAX_DOS_DRIVES; i++, drive[0]++)
+    for (i = 0, drive = DOSDrives; i < MAX_DOS_DRIVES; i++, name[6]++, drive++)
     {
-        GetPrivateProfileString( "drives", drive, "",
-                                 path, sizeof(path)-1, WineIniFileName() );
+        PROFILE_GetWineIniString( name, "Path", "", path, sizeof(path)-1 );
         if (path[0])
         {
             p = path + strlen(path) - 1;
             while ((p > path) && ((*p == '/') || (*p == '\\'))) *p-- = '\0';
-            DOSDrives[i].root     = xstrdup( path );
-            DOSDrives[i].dos_cwd  = xstrdup( "" );
-            DOSDrives[i].unix_cwd = xstrdup( "" );
-            sprintf( DOSDrives[i].label, "DRIVE-%c    ", drive[0] );
-            DOSDrives[i].serial   = 0x12345678;
-            DOSDrives[i].type     = (i < 2) ? DRIVE_REMOVABLE : DRIVE_FIXED;
-            DOSDrives[i].disabled = 0;
+            drive->root     = xstrdup( path );
+            drive->dos_cwd  = xstrdup( "" );
+            drive->unix_cwd = xstrdup( "" );
+            drive->type     = DRIVE_GetDriveType( name );
+            drive->disabled = 0;
+
+            /* Get the drive label */
+            PROFILE_GetWineIniString( name, "Label", name, drive->label, 12 );
+            if ((len = strlen(drive->label)) < 11)
+            {
+                /* Pad label with spaces */
+                memset( drive->label + len, ' ', 11 - len );
+                drive->label[12] = '\0';
+            }
+
+            /* Get the serial number */
+            PROFILE_GetWineIniString( name, "Serial", "12345678",
+                                      buffer, sizeof(buffer) );
+            drive->serial = strtoul( buffer, NULL, 16 );
+
+            /* Make the first hard disk the current drive */
+            if ((DRIVE_CurDrive == -1) && (drive->type == TYPE_HD))
+                DRIVE_CurDrive = i;
+
             count++;
+            dprintf_dosfs( stddeb, "%s: path=%s type=%s label='%s' serial=%08lx\n",
+                           name, path, DRIVE_Types[drive->type],
+                           drive->label, drive->serial );
         }
-        dprintf_dosfs( stddeb, "Drive %c -> %s\n", 'A' + i,
-                       path[0] ? path : "** None **" );
+        else dprintf_dosfs( stddeb, "%s: not defined\n", name );
     }
 
     if (!count) 
     {
         fprintf( stderr, "Warning: no valid DOS drive found\n" );
         /* Create a C drive pointing to Unix root dir */
-        DOSDrives[i].root     = xstrdup( "/" );
-        DOSDrives[i].dos_cwd  = xstrdup( "" );
-        DOSDrives[i].unix_cwd = xstrdup( "" );
-        sprintf( DOSDrives[i].label, "DRIVE-%c    ", drive[0] );
-        DOSDrives[i].serial   = 0x12345678;
-        DOSDrives[i].type     = DRIVE_FIXED;
-        DOSDrives[i].disabled = 0;
+        DOSDrives[2].root     = xstrdup( "/" );
+        DOSDrives[2].dos_cwd  = xstrdup( "" );
+        DOSDrives[2].unix_cwd = xstrdup( "" );
+        strcpy( DOSDrives[2].label, "Drive C    " );
+        DOSDrives[2].serial   = 0x12345678;
+        DOSDrives[2].type     = TYPE_HD;
+        DOSDrives[2].disabled = 0;
+        DRIVE_CurDrive = 2;
     }
 
-    /* Make the first hard disk the current drive */
-    for (i = 0; i < MAX_DOS_DRIVES; i++, drive[0]++)
+    /* Make sure the current drive is valid */
+    if (DRIVE_CurDrive == -1)
     {
-        if (DOSDrives[i].root && !DOSDrives[i].disabled &&
-            DOSDrives[i].type != DRIVE_REMOVABLE)
+        for (i = 0, drive = DOSDrives; i < MAX_DOS_DRIVES; i++, drive++)
         {
-            DRIVE_CurDrive = i;
-            break;
+            if (drive->root && !drive->disabled)
+            {
+                DRIVE_CurDrive = i;
+                break;
+            }
         }
     }
+
     return 1;
 }
 
@@ -143,7 +211,7 @@
  */
 int DRIVE_FindDriveRoot( const char **path )
 {
-    int drive;
+    int drive, rootdrive = -1;
     const char *p1, *p2;
 
     dprintf_dosfs( stddeb, "DRIVE_FindDriveRoot: searching '%s'\n", *path );
@@ -154,6 +222,13 @@
         p2 = DOSDrives[drive].root;
         dprintf_dosfs( stddeb, "DRIVE_FindDriveRoot: checking %c: '%s'\n",
                        'A' + drive, p2 );
+        
+        while (*p2 == '/') p2++;
+        if (!*p2)
+        {
+            rootdrive = drive;
+            continue;  /* Look if there's a better match */
+        }
         for (;;)
         {
             while ((*p1 == '\\') || (*p1 == '/')) p1++;
@@ -175,7 +250,7 @@
             break;  /* No match, go to next drive */
         }
     }
-    return -1;
+    return rootdrive;
 }
 
 
@@ -263,6 +338,16 @@
 
 
 /***********************************************************************
+ *           DRIVE_GetType
+ */
+DRIVETYPE DRIVE_GetType( int drive )
+{
+    if (!DRIVE_IsValid( drive )) return TYPE_INVALID;
+    return DOSDrives[drive].type;
+}
+
+
+/***********************************************************************
  *           DRIVE_Chdir
  */
 int DRIVE_Chdir( int drive, const char *path )
@@ -339,11 +424,52 @@
 
 
 /***********************************************************************
+ *           DRIVE_GetFreeSpace
+ */
+int DRIVE_GetFreeSpace( int drive, DWORD *size, DWORD *available )
+{
+    struct statfs info;
+
+    if (!DRIVE_IsValid(drive))
+    {
+        DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk );
+        return 0;
+    }
+
+#ifdef __svr4__
+    if (statfs( DOSDrives[drive].root, &info, 0, 0) < 0)
+#else
+    if (statfs( DOSDrives[drive].root, &info) < 0)
+#endif
+    {
+        FILE_SetDosError();
+        fprintf(stderr,"dosfs: cannot do statfs(%s)\n", DOSDrives[drive].root);
+        return 0;
+    }
+
+    *size = info.f_bsize * info.f_blocks;
+#ifdef __svr4__
+    *available = info.f_bfree * info.f_bsize;
+#else
+    *available = info.f_bavail * info.f_bsize;
+#endif
+    return 1;
+}
+
+
+/***********************************************************************
  *           GetDriveType   (KERNEL.136)
  */
 WORD GetDriveType( INT drive )
 {
     dprintf_dosfs( stddeb, "GetDriveType(%c:)\n", 'A' + drive );
-    if (!DRIVE_IsValid(drive)) return 0;
-    return DOSDrives[drive].type;
+    switch(DRIVE_GetType(drive))
+    {
+    case TYPE_FLOPPY:  return DRIVE_REMOVABLE;
+    case TYPE_HD:      return DRIVE_FIXED;
+    case TYPE_CDROM:   return DRIVE_REMOVABLE;
+    case TYPE_NETWORK: return DRIVE_REMOTE;
+    case TYPE_INVALID:
+    default:           return DRIVE_CANNOTDETERMINE;
+    }
 }
diff --git a/files/file.c b/files/file.c
index 19cc6fb..3d00a25 100644
--- a/files/file.c
+++ b/files/file.c
@@ -34,6 +34,7 @@
  */
 void FILE_SetDosError(void)
 {
+    dprintf_file(stddeb, "FILE_SetDosError: errno = %d\n", errno );
     switch (errno)
     {
     case EAGAIN:
@@ -44,18 +45,18 @@
         break;
     case ENOSPC:
         DOS_ERROR( ER_DiskFull, EC_MediaError, SA_Abort, EL_Disk );
-        break;				
+        break;
     case EACCES:
     case EPERM:
     case EROFS:
-        DOS_ERROR( ER_WriteProtected, EC_AccessDenied, SA_Abort, EL_Disk );
+        DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
         break;
     case EBUSY:
         DOS_ERROR( ER_LockViolation, EC_AccessDenied, SA_Abort, EL_Disk );
-        break;		
+        break;
     case ENOENT:
         DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
-        break;				
+        break;
     case EISDIR:
         DOS_ERROR( ER_CanNotMakeDir, EC_AccessDenied, SA_Abort, EL_Unknown );
         break;
@@ -65,7 +66,7 @@
         break;
     case EEXIST:
         DOS_ERROR( ER_FileExists, EC_Exists, SA_Abort, EL_Disk );
-        break;				
+        break;
     default:
         perror( "int21: unknown errno" );
         DOS_ERROR( ER_GeneralFailure, EC_SystemFailure, SA_Abort, EL_Unknown );
@@ -98,6 +99,9 @@
         return -1;
     }
     *fp = (BYTE)handle;
+    dprintf_file(stddeb, 
+       "FILE_AllocTaskHandle: returning %d for handle %d file %d of %d \n", 
+                 (fp - files),handle,pdb->nbFiles - i, pdb->nbFiles  );
     return (HFILE)(fp - files);
 }
 
@@ -118,6 +122,8 @@
         exit(1);
     }
     files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
+    dprintf_file( stddeb,"FILE_FreeTaskHandle: dos=%d unix=%d\n",
+                  handle, files[handle]);
     if ((handle<0) || (handle >= (INT)pdb->nbFiles) || (files[handle] == 0xff))
     {
         fprintf( stderr, "FILE_FreeTaskHandle: invalid file handle %d\n",
@@ -166,6 +172,7 @@
 
     if (!pdb) return;
     files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
+    fprintf(stderr,"FILE_CloseAllFiles: closing %d files\n",pdb->nbFiles);
     for (count = pdb->nbFiles; count > 0; count--, files++)
     {
         if (*files != 0xff)
@@ -178,12 +185,46 @@
 
 
 /***********************************************************************
+ *           FILE_OpenUnixFile
+ */
+static int FILE_OpenUnixFile( const char *name, int mode )
+{
+    int handle;
+    struct stat st;
+
+    if ((handle = open( name, mode )) == -1)
+    {
+        if (Options.allowReadOnly && (mode == O_RDWR))
+        {
+            if ((handle = open( name, O_RDONLY )) != -1)
+                fprintf( stderr, "Warning: could not open %s for writing, opening read-only.\n", name );
+        }
+    }
+    if (handle != -1)  /* Make sure it's not a directory */
+    {
+        if ((fstat( handle, &st ) == -1))
+        {
+            FILE_SetDosError();
+            close( handle );
+            handle = -1;
+        }
+        else if (S_ISDIR(st.st_mode))
+        {
+            DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
+            close( handle );
+            handle = -1;
+        }
+    }
+    return handle;
+}
+
+
+/***********************************************************************
  *           FILE_Open
  */
 int FILE_Open( LPCSTR path, int mode )
 {
     const char *unixName;
-    int handle;
 
     dprintf_file(stddeb, "FILE_Open: '%s' %04x\n", path, mode );
     if ((unixName = DOSFS_IsDevice( path )) != NULL)
@@ -191,26 +232,13 @@
         dprintf_file( stddeb, "FILE_Open: opening device '%s'\n", unixName );
         if (!unixName[0])  /* Non-existing device */
         {
+            dprintf_file(stddeb, "FILE_Open: Non-existing device\n");
             DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
             return -1;
         }
-        handle = open( unixName, mode );
     }
-    else
-    {
-        if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return -1;
-
-        if ((handle = open( unixName, mode )) == -1)
-        {
-            if (Options.allowReadOnly && (mode == O_RDWR))
-            {
-                if ((handle = open( unixName, O_RDONLY )) != -1)
-                    fprintf( stderr, "Warning: could not open %s for writing, opening read-only.\n", unixName );
-            }
-        }
-    }
-    if (handle == -1) FILE_SetDosError();
-    return handle;
+    else if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return -1;
+    return FILE_OpenUnixFile( unixName, mode );
 }
 
 
@@ -327,7 +355,7 @@
         DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
         return 0;
     }
-    if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return 0;
+    if (!(unixName = DOSFS_GetUnixFileName( path, FALSE ))) return 0;
     if ((mkdir( unixName, 0777 ) == -1) && (errno != EEXIST))
     {
         FILE_SetDosError();
@@ -373,6 +401,7 @@
     HFILE dosHandle;
 
     if ((handle = FILE_GetUnixHandle( hFile )) == -1) return HFILE_ERROR;
+    dprintf_file( stddeb, "FILE_Dup for handle %d\n",handle);
     if ((newhandle = dup(handle)) == -1)
     {
         FILE_SetDosError();
@@ -380,6 +409,7 @@
     }
     if ((dosHandle = FILE_AllocTaskHandle( newhandle )) == HFILE_ERROR)
         close( newhandle );
+    dprintf_file( stddeb, "FILE_Dup return handle %d\n",dosHandle);
     return dosHandle;
 }
 
@@ -396,6 +426,7 @@
     int handle, newhandle;
 
     if ((handle = FILE_GetUnixHandle( hFile1 )) == -1) return HFILE_ERROR;
+    dprintf_file( stddeb, "FILE_Dup2 for handle %d\n",handle);
     if ((hFile2 < 0) || (hFile2 >= (INT)pdb->nbFiles))
     {
         DOS_ERROR( ER_InvalidHandle, EC_ProgramError, SA_Abort, EL_Disk );
@@ -414,8 +445,14 @@
         return HFILE_ERROR;
     }
     files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
-    if (files[hFile2] != 0xff) close( files[hFile2] );
+    if (files[hFile2] != 0xff) 
+    {
+        dprintf_file( stddeb, "FILE_Dup2 closing old  handle2 %d\n",
+                      files[hFile2]);
+        close( files[hFile2] );
+    }
     files[hFile2] = (BYTE)newhandle;
+    dprintf_file( stddeb, "FILE_Dup2 return handle2 %d\n",newhandle);
     return hFile2;
 }
 
@@ -435,7 +472,7 @@
     ofs->cBytes = sizeof(OFSTRUCT);
     ofs->nErrCode = 0;
     if (mode & OF_REOPEN) name = ofs->szPathName;
-    dprintf_file( stddeb, "Openfile: %s %04x\n", name, mode );
+    dprintf_file( stddeb, "FILE_Openfile: %s %04x\n", name, mode );
 
     /* OF_PARSE simply fills the structure */
 
@@ -444,10 +481,12 @@
         if (!(dosName = DOSFS_GetDosTrueName( name, FALSE )))
         {
             ofs->nErrCode = DOS_ExtendedError;
+            dprintf_file( stddeb, "FILE_Openfile: %s  return = -1\n", name);
             return -1;
         }
         lstrcpyn( ofs->szPathName, dosName, sizeof(ofs->szPathName) );
         ofs->fFixedDisk = (GetDriveType( dosName[0]-'A' ) != DRIVE_REMOVABLE);
+        dprintf_file( stddeb, "FILE_Openfile: %s  return = 0\n", name);
         return 0;
     }
 
@@ -459,18 +498,21 @@
         if ((unixName = DOSFS_GetUnixFileName( name, FALSE )) == NULL)
         {
             ofs->nErrCode = DOS_ExtendedError;
+            dprintf_file( stddeb, "FILE_Openfile: %s  return = -1\n", name);
             return -1;
         }
-        dprintf_file( stddeb, "OpenFile: creating '%s'\n", unixName );
+        dprintf_file( stddeb, "FILE_OpenFile: creating '%s'\n", unixName );
         handle = open( unixName, O_TRUNC | O_RDWR | O_CREAT, 0666 );
         if (handle == -1)
         {
             FILE_SetDosError();
             ofs->nErrCode = DOS_ExtendedError;
+            dprintf_file( stddeb, "FILE_Openfile: %s  return = -1\n", name);
             return -1;
         }   
         lstrcpyn( ofs->szPathName, DOSFS_GetDosTrueName( name, FALSE ),
                   sizeof(ofs->szPathName) );
+        dprintf_file( stddeb, "FILE_Openfile: %s  return = %d \n", name, handle);
         return handle;
     }
 
@@ -540,21 +582,26 @@
     }
 
 not_found:
-    dprintf_file( stddeb, "OpenFile: '%s' not found\n", name );
+    dprintf_file( stddeb, "FILE_OpenFile: '%s' not found\n", name );
     DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
     ofs->nErrCode = ER_FileNotFound;
+    dprintf_file( stddeb, "FILE_Openfile: %s  return =-1\n", name);
     return -1;
 
 found:
-    dprintf_file( stddeb, "OpenFile: found '%s'\n", unixName );
+    dprintf_file( stddeb, "FILE_OpenFile: found '%s'\n", unixName );
     lstrcpyn( ofs->szPathName, DOSFS_GetDosTrueName( ofs->szPathName, FALSE ),
               sizeof(ofs->szPathName) );
 
-    if (mode & OF_PARSE) return 0;
-
+    if (mode & OF_PARSE) 
+    {
+          dprintf_file( stddeb, "FILE_Openfile: %s  return = 0\n", name);
+          return 0;
+    }
     if (mode & OF_DELETE)
     {
         if (unlink( unixName ) == -1) goto not_found;
+        dprintf_file( stddeb, "FILE_Openfile: %s  return = 0\n", name);
         return 0;
     }
 
@@ -569,27 +616,24 @@
         unixMode = O_RDONLY; break;
     }
 
-    if ((handle = open( unixName, unixMode )) == -1)
-    {
-        if (Options.allowReadOnly && (unixMode == O_RDWR))
-        {
-            if ((handle = open( unixName, O_RDONLY )) != -1)
-                fprintf( stderr, "Warning: could not open %s for writing, opening read-only.\n", unixName );
-        }
-    }
-    if (handle == -1) goto not_found;
+    if ((handle = FILE_OpenUnixFile( unixName, unixMode )) == -1)
+        goto not_found;
 
     if (fstat( handle, &st ) != -1)
     {
         if ((mode & OF_VERIFY) && (mode & OF_REOPEN))
         {
             if (memcmp( ofs->reserved, &st.st_mtime, sizeof(ofs->reserved) ))
+            {
+                dprintf_file( stddeb, "FILE_Openfile: %s  return = -1\n", name);
                 return -1;
+            }
         }
         memcpy( ofs->reserved, &st.st_mtime, sizeof(ofs->reserved) );
     }
 
     if (mode & OF_EXIST) close( handle );
+    dprintf_file( stddeb, "FILE_Openfile: %s  return = %d\n", name,handle);
 
     return handle;
 }
@@ -654,6 +698,7 @@
     int unixHandle;
     HFILE handle;
 
+    dprintf_file( stddeb, "OpenFile %s \n",name);
     if ((unixHandle = FILE_OpenFile( name, ofs, mode )) == -1)
         return HFILE_ERROR;
     if ((handle = FILE_AllocTaskHandle( unixHandle )) == HFILE_ERROR)
@@ -673,9 +718,9 @@
 {
     int handle;
 
-    dprintf_file( stddeb, "_lclose: handle %d\n", hFile );
     
     if ((handle = FILE_GetUnixHandle( hFile )) == -1) return HFILE_ERROR;
+    dprintf_file( stddeb, "_lclose: doshandle %d unixhandle %d\n", hFile,handle );
     if (handle <= 2)
     {
         fprintf( stderr, "_lclose: internal error: closing handle %d\n", handle );
@@ -738,7 +783,7 @@
 LONG _llseek( HFILE hFile, LONG lOffset, INT nOrigin )
 {
     int handle, origin, result;
-	
+
     dprintf_file( stddeb, "_llseek: handle %d, offset %ld, origin %d\n", 
                   hFile, lOffset, nOrigin);
 
@@ -805,10 +850,10 @@
 
     dprintf_file( stddeb, "_hread: %d %p %ld\n", hFile, buffer, count );
   
-    if ((handle = FILE_GetUnixHandle( hFile )) == -1) return HFILE_ERROR;
+    if ((handle = FILE_GetUnixHandle( hFile )) == -1) return -1;
     if (!count) return 0;
     if ((result = read( handle, buffer, count )) == -1) FILE_SetDosError();
-    return (result == -1) ? HFILE_ERROR : result;
+    return result;
 }
 
 
diff --git a/files/profile.c b/files/profile.c
new file mode 100644
index 0000000..50816e1
--- /dev/null
+++ b/files/profile.c
@@ -0,0 +1,686 @@
+/*
+ * Profile functions
+ *
+ * Copyright 1993 Miguel de Icaza
+ * Copyright 1996 Alexandre Julliard
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "dos_fs.h"
+#include "windows.h"
+#include "xmalloc.h"
+#include "stddebug.h"
+#include "debug.h"
+
+typedef struct tagPROFILEKEY
+{
+    char                  *name;
+    char                  *value;
+    struct tagPROFILEKEY  *next;
+} PROFILEKEY;
+
+typedef struct tagPROFILESECTION
+{
+    char                       *name;
+    struct tagPROFILEKEY       *key;
+    struct tagPROFILESECTION   *next;
+} PROFILESECTION; 
+
+
+typedef struct
+{
+    int              changed;
+    PROFILESECTION  *section;
+    char            *dos_name;
+} PROFILE;
+
+
+/* Cached profile file */
+static PROFILE CurProfile = { FALSE, NULL, NULL };
+
+/* wine.ini profile content */
+static PROFILESECTION *WineProfile;
+
+#define PROFILE_MAX_LINE_LEN   1024
+
+/* Wine profile name in $HOME directory; must begin with slash */
+static const char PROFILE_WineIniName[] = "/.winerc";
+
+/* Check for comments in profile */
+#define IS_ENTRY_COMMENT(str)  ((str)[0] == ';')
+
+
+/***********************************************************************
+ *           PROFILE_CopyEntry
+ *
+ * Copy the content of an entry into a buffer, removing quotes, and possibly
+ * translating environment variables.
+ */
+static void PROFILE_CopyEntry( char *buffer, const char *value, int len,
+                               int handle_env )
+{
+    char quote = '\0';
+    const char *p;
+
+    if ((*value == '\'') || (*value == '\"'))
+    {
+        if (value[1] && (value[strlen(value)-1] == *value)) quote = *value++;
+    }
+
+    if (!handle_env)
+    {
+        lstrcpyn( buffer, value, len );
+        if (quote && (len >= strlen(value))) buffer[strlen(buffer)-1] = '\0';
+        return;
+    }
+
+    for (p = value; (*p && (len > 1)); *buffer++ = *p++, len-- )
+    {
+        if ((*p == '$') && (p[1] == '{'))
+        {
+            char env_val[1024];
+            const char *env_p;
+            const char *p2 = strchr( p, '}' );
+            if (!p2) continue;  /* ignore it */
+            lstrcpyn( env_val, p + 2, MIN( sizeof(env_val), (int)(p2-p)-1 ) );
+            if ((env_p = getenv( env_val )) != NULL)
+            {
+                lstrcpyn( buffer, env_p, len );
+                buffer += strlen( buffer );
+                len -= strlen( buffer );
+            }
+            p = p2 + 1;
+        }
+    }
+    *buffer = '\0';
+}
+
+
+/***********************************************************************
+ *           PROFILE_Save
+ *
+ * Save a profile tree to a file.
+ */
+static void PROFILE_Save( FILE *file, PROFILESECTION *section )
+{
+    PROFILEKEY *key;
+
+    for ( ; section; section = section->next)
+    {
+        if (section->name) fprintf( file, "[%s]\n", section->name );
+        for (key = section->key; key; key = key->next)
+        {
+            fprintf( file, "%s", key->name );
+            if (key->value) fprintf( file, "=%s", key->value );
+            fprintf( file, "\n" );
+        }
+    }
+}
+
+
+/***********************************************************************
+ *           PROFILE_Free
+ *
+ * Free a profile tree.
+ */
+static void PROFILE_Free( PROFILESECTION *section )
+{
+    PROFILESECTION *next_section;
+    PROFILEKEY *key, *next_key;
+
+    for ( ; section; section = next_section)
+    {
+        if (section->name) free( section->name );
+        for (key = section->key; key; key = next_key)
+        {
+            next_key = key->next;
+            if (key->name) free( key->name );
+            if (key->value) free( key->value );
+            free( key );
+        }
+        next_section = section->next;
+        free( section );
+    }
+}
+
+
+/***********************************************************************
+ *           PROFILE_Load
+ *
+ * Load a profile tree from a file.
+ */
+static PROFILESECTION *PROFILE_Load( FILE *file )
+{
+    char buffer[PROFILE_MAX_LINE_LEN];
+    char *p, *p2;
+    int line = 0;
+    PROFILESECTION *section, *first_section;
+    PROFILESECTION **prev_section;
+    PROFILEKEY *key, **prev_key;
+
+    first_section = (PROFILESECTION *)xmalloc( sizeof(*section) );
+    first_section->name = NULL;
+    first_section->key  = NULL;
+    first_section->next = NULL;
+    prev_section = &first_section->next;
+    prev_key     = &first_section->key;
+
+    while (fgets( buffer, PROFILE_MAX_LINE_LEN, file ))
+    {
+        line++;
+        p = buffer + strlen(buffer) - 1;
+        while ((p > buffer) && ((*p == '\n') || isspace(*p))) *p-- = '\0';
+        p = buffer;
+        while (*p && isspace(*p)) p++;
+        if (*p == '[')  /* section start */
+        {
+            if (!(p2 = strrchr( p, ']' )))
+            {
+                fprintf( stderr, "PROFILE_Load: Invalid section header at line %d: '%s'\n",
+                         line, p );
+            }
+            else
+            {
+                *p2 = '\0';
+                p++;
+                section = (PROFILESECTION *)xmalloc( sizeof(*section));
+                section->name = xstrdup( p );
+                section->key  = NULL;
+                section->next = NULL;
+                *prev_section = section;
+                prev_section  = &section->next;
+                prev_key      = &section->key;
+                continue;
+            }
+        }
+        if ((p2 = strchr( p, '=' )) != NULL)
+        {
+            char *p3 = p2 - 1;
+            while ((p3 > p) && isspace(*p3)) *p3-- = '\0';
+            *p2++ = '\0';
+            while (*p2 && isspace(*p2)) p2++;
+        }
+        key = (PROFILEKEY *)xmalloc( sizeof(*key) );
+        key->name  = xstrdup( p );
+        key->value = p2 ? xstrdup( p2 ) : NULL;
+        key->next  = NULL;
+        *prev_key  = key;
+        prev_key = &key->next;
+    }
+    if (debugging_profile)
+    {
+        fprintf( stddeb, "PROFILE_Load:\n" );
+        PROFILE_Save( stddeb, first_section );
+        fprintf( stddeb, "PROFILE_Load finished.\n" );
+    }
+    return first_section;
+}
+
+
+/***********************************************************************
+ *           PROFILE_DeleteSection
+ *
+ * Delete a section from a profile tree.
+ */
+static BOOL PROFILE_DeleteSection( PROFILESECTION **section, const char *name )
+{
+    while (*section)
+    {
+        if ((*section)->name && !lstrcmpi( (*section)->name, name ))
+        {
+            PROFILESECTION *to_del = *section;
+            *section = to_del->next;
+            to_del->next = NULL;
+            PROFILE_Free( to_del );
+            return TRUE;
+        }
+        section = &(*section)->next;
+    }
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *           PROFILE_DeleteKey
+ *
+ * Delete a key from a profile tree.
+ */
+static BOOL PROFILE_DeleteKey( PROFILESECTION **section,
+                               const char *section_name, const char *key_name )
+{
+    while (*section)
+    {
+        if ((*section)->name && !lstrcmpi( (*section)->name, section_name ))
+        {
+            PROFILEKEY **key = &(*section)->key;
+            while (*key)
+            {
+                if (!lstrcmpi( (*key)->name, key_name ))
+                {
+                    PROFILEKEY *to_del = *key;
+                    *key = to_del->next;
+                    if (to_del->name) free( to_del->name );
+                    if (to_del->value) free( to_del->value );
+                    free( to_del );
+                    return TRUE;
+                }
+                key = &(*key)->next;
+            }
+        }
+        section = &(*section)->next;
+    }
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *           PROFILE_Find
+ *
+ * Find a key in a profile tree, optionally creating it.
+ */
+static PROFILEKEY *PROFILE_Find( PROFILESECTION **section,
+                                 const char *section_name,
+                                 const char *key_name, int create )
+{
+    while (*section)
+    {
+        if ((*section)->name && !lstrcmpi( (*section)->name, section_name ))
+        {
+            PROFILEKEY **key = &(*section)->key;
+            while (*key)
+            {
+                if (!lstrcmpi( (*key)->name, key_name )) return *key;
+                key = &(*key)->next;
+            }
+            if (!create) return NULL;
+            *key = (PROFILEKEY *)xmalloc( sizeof(PROFILEKEY) );
+            (*key)->name  = xstrdup( key_name );
+            (*key)->value = NULL;
+            (*key)->next  = NULL;
+            return *key;
+        }
+        section = &(*section)->next;
+    }
+    if (!create) return NULL;
+    *section = (PROFILESECTION *)xmalloc( sizeof(PROFILESECTION) );
+    (*section)->name = xstrdup(section_name);
+    (*section)->next = NULL;
+    (*section)->key  = (PROFILEKEY *)xmalloc( sizeof(PROFILEKEY) );
+    (*section)->key->name  = xstrdup( key_name );
+    (*section)->key->value = NULL;
+    (*section)->key->next  = NULL;
+    return (*section)->key;
+}
+
+
+/***********************************************************************
+ *           PROFILE_FlushFile
+ *
+ * Flush the current profile to disk if changed.
+ */
+static BOOL PROFILE_FlushFile(void)
+{
+    char *p, buffer[MAX_PATHNAME_LEN];
+    const char *unix_name;
+    FILE *file = NULL;
+
+    if (!CurProfile.changed || !CurProfile.dos_name) return TRUE;
+    if (!(unix_name = DOSFS_GetUnixFileName( CurProfile.dos_name, FALSE )) ||
+        !(file = fopen( unix_name, "w" )))
+    {
+        /* Try to create it in $HOME/.wine */
+        /* FIXME: this will need a more general solution */
+        if ((p = getenv( "HOME" )) != NULL)
+        {
+            strcpy( buffer, p );
+            strcat( buffer, "/.wine/" );
+            p = buffer + strlen(buffer);
+            strcpy( p, strrchr( CurProfile.dos_name, '\\' ) + 1 );
+            AnsiLower( p );
+            file = fopen( buffer, "w" );
+            unix_name = buffer;
+        }
+    }
+    
+    if (!file)
+    {
+        fprintf( stderr, "Warning: could not save profile file %s\n",
+                 CurProfile.dos_name );
+        return FALSE;
+    }
+
+    dprintf_profile( stddeb, "Saving '%s' into '%s'\n",
+                     CurProfile.dos_name, unix_name );
+    PROFILE_Save( file, CurProfile.section );
+    fclose( file );
+    CurProfile.changed = FALSE;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           PROFILE_Open
+ *
+ * Open a profile file, checking the cached file first.
+ */
+static BOOL PROFILE_Open( const char *filename )
+{
+    char buffer[MAX_PATHNAME_LEN];
+    const char *dos_name, *unix_name;
+    char *newdos_name, *p;
+    FILE *file = NULL;
+
+    if (strchr( filename, '/' ) || strchr( filename, '\\' ) || 
+        strchr( filename, ':' ))
+    {
+        if (!(dos_name = DOSFS_GetDosTrueName( filename, FALSE))) return FALSE;
+    }
+    else
+    {
+        GetWindowsDirectory( buffer, sizeof(buffer) );
+        strcat( buffer, "\\" );
+        strcat( buffer, filename );
+        if (!(dos_name = DOSFS_GetDosTrueName( buffer, FALSE ))) return FALSE;
+    }
+    if (CurProfile.dos_name && !strcmp( dos_name, CurProfile.dos_name ))
+    {
+        dprintf_profile( stddeb, "PROFILE_Open(%s): already opened\n",
+                         filename );
+        return TRUE;
+    }
+
+    /* Flush the previous profile */
+
+    newdos_name = xstrdup( dos_name );
+    PROFILE_FlushFile();
+    PROFILE_Free( CurProfile.section );
+    if (CurProfile.dos_name) free( CurProfile.dos_name );
+    CurProfile.section   = NULL;
+    CurProfile.dos_name  = newdos_name;
+
+    /* Try to open the profile file, first in $HOME/.wine */
+
+    /* FIXME: this will need a more general solution */
+    if ((p = getenv( "HOME" )) != NULL)
+    {
+        strcpy( buffer, p );
+        strcat( buffer, "/.wine/" );
+        p = buffer + strlen(buffer);
+        strcpy( p, strrchr( newdos_name, '\\' ) + 1 );
+        AnsiLower( p );
+        if ((file = fopen( buffer, "r" )))
+            dprintf_profile( stddeb, "Found it in %s\n", buffer );
+    }
+
+    if (!file && ((unix_name = DOSFS_GetUnixFileName( dos_name, TRUE ))))
+    {
+        if ((file = fopen( unix_name, "r" )))
+            dprintf_profile( stddeb, "Found it in %s\n", unix_name );
+    }
+
+    if (file)
+    {
+        CurProfile.section = PROFILE_Load( file );
+        fclose( file );
+    }
+    else
+        fprintf( stderr, "Warning: profile file %s not found\n", newdos_name );
+    dprintf_profile( stddeb, "PROFILE_Open(%s): successful\n", filename );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           PROFILE_GetSection
+ *
+ * Enumerate all the keys of a section.
+ */
+static INT PROFILE_GetSection( PROFILESECTION *section,
+                               const char *section_name,
+                               char *buffer, INT len, int handle_env )
+{
+    PROFILEKEY *key;
+    while (section)
+    {
+        if (section->name && !lstrcmpi( section->name, section_name ))
+        {
+            for (key = section->key; key; key = key->next)
+            {
+                if (len <= 2) break;
+                if (IS_ENTRY_COMMENT(key->name)) continue;  /* Skip comments */
+                PROFILE_CopyEntry( buffer, key->name, len - 1, handle_env );
+                len -= strlen(buffer) - 1;
+                buffer += strlen(buffer) + 1;
+            }
+            *buffer = '\0';
+            return len - 1;
+        }
+        section = section->next;
+    }
+    buffer[0] = buffer[1] = '\0';
+    return len - 2;
+}
+
+
+/***********************************************************************
+ *           PROFILE_GetString
+ *
+ * Get a profile string.
+ */
+static INT PROFILE_GetString( const char *section, const char *key_name,
+                              const char *def_val, char *buffer, INT len )
+{
+    PROFILEKEY *key = NULL;
+
+    if (!def_val) def_val = "";
+    if (key_name)
+    {
+        key = PROFILE_Find( &CurProfile.section, section, key_name, FALSE );
+        PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,
+                           len, FALSE );
+        dprintf_profile( stddeb, "PROFILE_GetString('%s','%s','%s'): returning '%s'\n",
+                         section, key_name, def_val, buffer );
+        return strlen( buffer );
+    }
+    return PROFILE_GetSection(CurProfile.section, section, buffer, len, FALSE);
+}
+
+
+/***********************************************************************
+ *           PROFILE_SetString
+ *
+ * Set a profile string.
+ */
+static BOOL PROFILE_SetString( const char *section_name, const char *key_name,
+                               const char *value )
+{
+    BOOL ret;
+
+    if (!key_name)  /* Delete a whole section */
+    {
+        dprintf_profile(stddeb, "PROFILE_DeleteSection('%s')\n", section_name);
+        ret = PROFILE_DeleteSection( &CurProfile.section, section_name );
+        CurProfile.changed |= ret;
+        return ret;
+    }
+    else if (!value)  /* Delete a key */
+    {
+        dprintf_profile( stddeb, "PROFILE_DeleteKey('%s','%s')\n",
+                         section_name, key_name );
+        ret = PROFILE_DeleteKey( &CurProfile.section, section_name, key_name );
+        CurProfile.changed |= ret;
+        return ret;
+    }
+    else  /* Set the key value */
+    {
+        PROFILEKEY *key = PROFILE_Find( &CurProfile.section, section_name,
+                                        key_name, TRUE );
+        dprintf_profile( stddeb, "PROFILE_SetString('%s','%s','%s'): ",
+                         section_name, key_name, value );
+        if (key->value)
+        {
+            if (!strcmp( key->value, value ))
+            {
+                dprintf_profile( stddeb, "no change needed\n" );
+                return TRUE;  /* No change needed */
+            }
+            dprintf_profile( stddeb, "replacing '%s'\n", key->value );
+            free( key->value );
+        }
+        else dprintf_profile( stddeb, "creating key\n" );
+        key->value = xstrdup( value );
+        CurProfile.changed = TRUE;
+        return TRUE;
+    }
+}
+
+
+/***********************************************************************
+ *           PROFILE_GetWineIniString
+ *
+ * Get a config string from the wine.ini file.
+ */
+int PROFILE_GetWineIniString( const char *section, const char *key_name,
+                              const char *def, char *buffer, int len )
+{
+    if (key_name)
+    {
+        PROFILEKEY *key = PROFILE_Find(&WineProfile, section, key_name, FALSE);
+        PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def,
+                           len, TRUE );
+        dprintf_profile( stddeb, "PROFILE_GetWineIniString('%s','%s','%s'): returning '%s'\n",
+                         section, key_name, def, buffer );
+        return strlen( buffer );
+    }
+    return PROFILE_GetSection( WineProfile, section, buffer, len, TRUE );
+}
+
+
+/***********************************************************************
+ *           PROFILE_LoadWineIni
+ *
+ * Load the wine.ini file.
+ */
+int PROFILE_LoadWineIni(void)
+{
+    char buffer[MAX_PATHNAME_LEN];
+    const char *p;
+    FILE *f;
+
+    if ((p = getenv( "HOME" )) != NULL)
+    {
+        lstrcpyn( buffer, p, MAX_PATHNAME_LEN - sizeof(PROFILE_WineIniName) );
+        strcat( buffer, PROFILE_WineIniName );
+        if ((f = fopen( buffer, "r" )) != NULL)
+        {
+            WineProfile = PROFILE_Load( f );
+            fclose( f );
+            return 1;
+        }
+    }
+    else fprintf( stderr, "Warning: could not get $HOME value for config file.\n" );
+
+    /* Try global file */
+
+    if ((f = fopen( WINE_INI_GLOBAL, "r" )) != NULL)
+    {
+        WineProfile = PROFILE_Load( f );
+        fclose( f );
+        return 1;
+    }
+    fprintf( stderr, "Can't open configuration file %s or $HOME%s\n",
+             WINE_INI_GLOBAL, PROFILE_WineIniName );
+    return 0;
+}
+
+
+/***********************************************************************
+ *           GetProfileInt   (KERNEL.57)
+ */
+UINT GetProfileInt( LPCSTR section, LPCSTR entry, INT def_val )
+{
+    return GetPrivateProfileInt( section, entry, def_val, "win.ini" );
+}
+
+
+/***********************************************************************
+ *           GetProfileString   (KERNEL.58)
+ */
+INT GetProfileString( LPCSTR section, LPCSTR entry, LPCSTR def_val,
+                      LPSTR buffer, INT len )
+{
+    return GetPrivateProfileString( section, entry, def_val,
+                                    buffer, len, "win.ini" );
+}
+
+
+/***********************************************************************
+ *           WriteProfileString   (KERNEL.59)
+ */
+BOOL WriteProfileString( LPCSTR section, LPCSTR entry, LPCSTR string )
+{
+    return WritePrivateProfileString( section, entry, string, "win.ini" );
+}
+
+
+/***********************************************************************
+ *           GetPrivateProfileInt   (KERNEL.127)
+ */
+UINT GetPrivateProfileInt( LPCSTR section, LPCSTR entry, INT def_val,
+                           LPCSTR filename )
+{
+    char buffer[20];
+    char *p;
+    long result;
+
+    GetPrivateProfileString( section, entry, "",
+                             buffer, sizeof(buffer), filename );
+    if (!buffer[0]) return (UINT)def_val;
+    result = strtol( buffer, &p, 0 );
+    if (p == buffer) return 0;  /* No digits at all */
+#ifdef WINELIB32
+    return (UINT)result;
+#else
+    if (result > 65535) return 65535;
+    if (result >= 0) return (UINT)result;
+    if (result < -32768) return -32768;
+    return (UINT)(INT)result;
+#endif
+}
+
+
+/***********************************************************************
+ *           GetPrivateProfileString   (KERNEL.128)
+ */
+INT GetPrivateProfileString( LPCSTR section, LPCSTR entry, LPCSTR def_val,
+                             LPSTR buffer, INT len, LPCSTR filename )
+{
+    if (PROFILE_Open( filename ))
+        return PROFILE_GetString( section, entry, def_val, buffer, len );
+    lstrcpyn( buffer, def_val, len );
+    return strlen( buffer );
+}
+
+
+/***********************************************************************
+ *           WritePrivateProfileString   (KERNEL.129)
+ */
+BOOL WritePrivateProfileString( LPCSTR section, LPCSTR entry, LPCSTR string,
+                                LPCSTR filename )
+{
+    if (!PROFILE_Open( filename )) return FALSE;
+    if (!section) return PROFILE_FlushFile();
+    return PROFILE_SetString( section, entry, string );
+}
+
+
+/***********************************************************************
+ *           WriteOutProfiles   (KERNEL.315)
+ */
+void WriteOutProfiles(void)
+{
+    PROFILE_FlushFile();
+}
diff --git a/if1632/callback.c b/if1632/callback.c
index 27d236c..346289e 100644
--- a/if1632/callback.c
+++ b/if1632/callback.c
@@ -46,7 +46,7 @@
 /**********************************************************************
  *	     Catch    (KERNEL.55)
  */
-int Catch( LPCATCHBUF lpbuf )
+INT Catch( LPCATCHBUF lpbuf )
 {
     STACK16FRAME *pFrame = CURRENT_STACK16;
 
diff --git a/if1632/gdi32.spec b/if1632/gdi32.spec
index 86bd082..43d7586 100644
--- a/if1632/gdi32.spec
+++ b/if1632/gdi32.spec
@@ -71,7 +71,7 @@
 0067 stdcall DeleteDC(long) DeleteDC
 0068 stub DeleteEnhMetaFile
 0069 stub DeleteMetaFile
-0070 stub DeleteObject
+0070 stdcall DeleteObject(long)	DeleteObject
 0071 stub DescribePixelFormat
 0072 stub DeviceCapabilitiesExA
 0073 stub DeviceCapabilitiesExW
@@ -212,7 +212,7 @@
 0208 stub GetOutlineTextMetricsW
 0209 stub GetPaletteEntries
 0210 stub GetPath
-0211 stub GetPixel
+0211 stdcall GetPixel(long long long)	GetPixel
 0212 stub GetPixelFormat
 0213 stub GetPolyFillMode
 0214 stub GetROP2
@@ -255,7 +255,7 @@
 0251 stub LoadImageColorMatcherW
 0252 stub MaskBlt
 0253 stub ModifyWorldTransform
-0254 stdcall MoveToEx(long long long ptr) MoveToEx
+0254 stdcall MoveToEx(long long long ptr) WIN32_MoveToEx
 0255 stub OffsetClipRgn
 0256 stub OffsetRgn
 0257 stub OffsetViewportOrgEx
@@ -328,7 +328,7 @@
 0324 stub SetMetaRgn
 0325 stub SetMiterLimit
 0326 stub SetPaletteEntries
-0327 stub SetPixel
+0327 stdcall SetPixel(long long long long)	SetPixel
 0328 stub SetPixelFormat
 0329 stub SetPixelV
 0330 stub SetPolyFillMode
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index d4e7898..01fa49f 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -53,7 +53,7 @@
 54  pascal16 GetInstanceData(word word word) GetInstanceData
 55  pascal16 Catch(ptr) Catch 
 56  pascal16 Throw(ptr word) Throw
-57  pascal16 GetProfileInt(ptr ptr word) GetProfileInt
+57  pascal16 GetProfileInt(ptr ptr s_word) GetProfileInt
 58  pascal16 GetProfileString(ptr ptr ptr ptr word) GetProfileString
 59  pascal16 WriteProfileString(ptr ptr ptr) WriteProfileString
 60  pascal16 FindResource(word segptr segptr) FindResource
@@ -124,7 +124,7 @@
 125 return DisableKernel 0 0
 126 stub MemoryFreed
 127 pascal16 GetPrivateProfileInt(ptr ptr s_word ptr) GetPrivateProfileInt
-128 pascal16 GetPrivateProfileString(ptr ptr ptr ptr s_word ptr)
+128 pascal16 GetPrivateProfileString(ptr ptr ptr ptr word ptr)
              GetPrivateProfileString
 129 pascal16 WritePrivateProfileString(ptr ptr ptr ptr)
              WritePrivateProfileString
@@ -228,7 +228,7 @@
 310 pascal16 LocalHandleDelta(word) LocalHandleDelta
 311 stub GetSetKernelDosProc
 314 stub DebugDefineSegment
-315 pascal WriteOutProfiles() sync_profiles
+315 pascal16 WriteOutProfiles() WriteOutProfiles
 316 stub GetFreeMemInfo
 318 stub FatalExitHook
 319 stub FlushCachedFileHandle
diff --git a/if1632/kernel32.spec b/if1632/kernel32.spec
index b1c7193..a660700 100644
--- a/if1632/kernel32.spec
+++ b/if1632/kernel32.spec
@@ -584,12 +584,12 @@
 0579 stub WriteFileEx
 0580 stub WritePrivateProfileSectionA
 0581 stub WritePrivateProfileSectionW
-0582 stub WritePrivateProfileStringA
+0582 stdcall WritePrivateProfileStringA(ptr ptr ptr ptr)	WritePrivateProfileString
 0583 stub WritePrivateProfileStringW
 0584 stub WriteProcessMemory
 0585 stub WriteProfileSectionA
 0586 stub WriteProfileSectionW
-0587 stub WriteProfileStringA
+0587 stdcall WriteProfileStringA(ptr ptr ptr)	WriteProfileString
 0588 stub WriteProfileStringW
 0589 stub WriteTapemark
 0590 stub _hread
diff --git a/if1632/relay.c b/if1632/relay.c
index 6f6f7c8..b5f1a2b 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -246,6 +246,6 @@
     printf( "CallTo16(func=%04x:%04x,ds=%04x",
             HIWORD(stack[0]), LOWORD(stack[0]), LOWORD(stack[1]) );
     stack += 2;
-    while (nbargs--) printf( ",0x%x", *stack++ );
+    while (nbargs--) printf( ",0x%04x", *stack++ );
     printf( ")\n" );
 }
diff --git a/if1632/relay32.c b/if1632/relay32.c
index 7da3a47..a380483 100644
--- a/if1632/relay32.c
+++ b/if1632/relay32.c
@@ -85,8 +85,10 @@
 	dprintf_module(stddeb, "Looking for %s in %s, hint %x\n",
 		item ? item: "(no name)", dll_name, hint);
 	dll=RELAY32_GetBuiltinDLL(dll_name);
-	/* This should deal with built-in DLLs only. See pe_module on loading
-	   PE DLLs */
+	/* FIXME: This should deal with built-in DLLs only. See pe_module on
+	loading PE DLLs */
+	if(!dll)
+		return 0;
 #if 0
 	if(!dll) {
 		if(!wine_files || !wine_files->name ||
diff --git a/if1632/toolhelp.spec b/if1632/toolhelp.spec
index 9bfe141..1c590d4 100644
--- a/if1632/toolhelp.spec
+++ b/if1632/toolhelp.spec
@@ -24,8 +24,8 @@
 70 pascal16 ClassNext(ptr) ClassNext
 71 pascal16 SystemHeapInfo(ptr) SystemHeapInfo
 72 pascal16 MemManInfo(ptr) MemManInfo
-73 stub NOTIFYREGISTER
-74 stub NOTIFYUNREGISTER
+73 pascal16 NotifyRegister(word segptr word) NotifyRegister
+74 pascal16 NotifyUnregister(word) NotifyUnregister
 75 return INTERRUPTREGISTER 6 0
 76 return INTERRUPTUNREGISTER 2 0
 77 stub TERMINATEAPP
diff --git a/if1632/user.spec b/if1632/user.spec
index 240daa5..9d4f57b 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -98,7 +98,7 @@
 97  pascal16 CheckDlgButton(word word word) CheckDlgButton
 98  pascal16 IsDlgButtonChecked(word word) IsDlgButtonChecked
 99  pascal16 DlgDirSelect(word ptr word) DlgDirSelect
-100 pascal16 DlgDirList(word ptr word word word) DlgDirList
+100 pascal16 DlgDirList(word segptr word word word) DlgDirList
 101 pascal   SendDlgItemMessage(word word word word long) SendDlgItemMessage
 102 pascal16 AdjustWindowRect(ptr long word) AdjustWindowRect
 103 pascal16 MapDialogRect(word ptr) MapDialogRect
@@ -151,7 +151,7 @@
 150 pascal16 LoadMenu(word segptr) LoadMenu
 151 pascal16 CreateMenu() CreateMenu
 152 pascal16 DestroyMenu(word) DestroyMenu
-153 pascal16 ChangeMenu(word word ptr word word) ChangeMenu
+153 pascal16 ChangeMenu(word word segptr word word) ChangeMenu
 154 pascal16 CheckMenuItem(word word word) CheckMenuItem
 155 pascal16 EnableMenuItem(word word word) EnableMenuItem
 156 pascal16 GetSystemMenu(word word) GetSystemMenu
@@ -219,7 +219,7 @@
 217 pascal16 LookupMenuHandle(word s_word) LookupMenuHandle
 218 pascal16 DialogBoxIndirect(word word word segptr) DialogBoxIndirect
 219 pascal16 CreateDialogIndirect(word segptr word segptr) CreateDialogIndirect
-220 pascal16 LoadMenuIndirect(ptr) LoadMenuIndirect
+220 pascal16 LoadMenuIndirect(segptr) LoadMenuIndirect
 221 pascal16 ScrollDC(word s_word s_word ptr ptr word ptr) ScrollDC
 222 pascal16 GetKeyboardState(ptr) GetKeyboardState
 223 pascal16 SetKeyboardState(ptr) SetKeyboardState
@@ -362,11 +362,11 @@
 408 pascal16 CreateCursorIconIndirect(word ptr ptr ptr)
 	     CreateCursorIconIndirect
 409 stub InitThreadInput
-410 pascal16 InsertMenu(word word word word ptr) InsertMenu
-411 pascal16 AppendMenu(word word word ptr) AppendMenu
+410 pascal16 InsertMenu(word word word word segptr) InsertMenu
+411 pascal16 AppendMenu(word word word segptr) AppendMenu
 412 pascal16 RemoveMenu(word word word) RemoveMenu
 413 pascal16 DeleteMenu(word word word) DeleteMenu
-414 pascal16 ModifyMenu(word word word word ptr) ModifyMenu
+414 pascal16 ModifyMenu(word word word word segptr) ModifyMenu
 415 pascal16 CreatePopupMenu() CreatePopupMenu
 416 pascal16 TrackPopupMenu(word word word word word word ptr) TrackPopupMenu
 417 pascal   GetMenuCheckMarkDimensions() GetMenuCheckMarkDimensions
diff --git a/if1632/user32.spec b/if1632/user32.spec
index 50f41ee..1a56acc 100644
--- a/if1632/user32.spec
+++ b/if1632/user32.spec
@@ -165,15 +165,15 @@
 0160 stdcall DrawMenuBar(long) DrawMenuBar
 0161 stub DrawStateA
 0162 stub DrawStateW
-0163 stdcall DrawTextA(long ptr long ptr long) DrawText
+0163 stdcall DrawTextA(long ptr long ptr long) USER32_DrawTextA
 0164 stub DrawTextExA
 0165 stub DrawTextExW
 0166 stub DrawTextW
 0167 stub EditWndProc
-0168 stub EmptyClipboard
-0169 stub EnableMenuItem
-0170 stub EnableScrollBar
-0171 stub EnableWindow
+0168 stdcall EmptyClipboard()				EmptyClipboard
+0169 stdcall EnableMenuItem(long long long) EnableMenuItem
+0170 stdcall EnableScrollBar(long long long)	EnableScrollBar
+0171 stdcall EnableWindow(long long)		EnableWindow
 0172 stub EndDeferWindowPos
 0173 stub EndDialog
 0174 stub EndMenu
@@ -221,7 +221,7 @@
 0216 stub GetClassNameA
 0217 stub GetClassNameW
 0218 stub GetClassWord
-0219 stdcall GetClientRect(long long) GetClientRect
+0219 stdcall GetClientRect(long long) USER32_GetClientRect
 0220 stub GetClipCursor
 0221 stub GetClipboardData
 0222 stub GetClipboardFormatNameA
@@ -329,7 +329,7 @@
 0324 stub InsertMenuW
 0325 stub InternalGetWindowText
 0326 stub IntersectRect
-0327 stub InvalidateRect
+0327 stdcall InvalidateRect(long ptr long)	USER32_InvalidateRect
 0328 stub InvalidateRgn
 0329 stub InvertRect
 0330 stub IsCharAlphaA
@@ -356,10 +356,10 @@
 0351 stub IsZoomed
 0352 stub KillSystemTimer
 0353 stub KillTimer
-0354 	stdcall LoadAcceleratorsA(long ptr) LoadAccelerators32
-0355 stub LoadAcceleratorsW
-0356 	stdcall LoadBitmapA(long ptr) LoadBitmapA32
-0357 	stdcall LoadBitmapW(long ptr) LoadBitmapW32
+0354 	stdcall LoadAcceleratorsA(long ptr) WIN32_LoadAcceleratorsA
+0355 stdcall LoadAcceleratorsW(long ptr)	WIN32_LoadAcceleratorsW
+0356 	stdcall LoadBitmapA(long ptr) WIN32_LoadBitmapA
+0357 	stdcall LoadBitmapW(long ptr) WIN32_LoadBitmapW
 0357 stub LoadBitmapW
 0358 	stdcall LoadCursorA(long ptr) LoadCursor
 0359 stub LoadCursorFromFileA
@@ -372,13 +372,13 @@
 0366 stub LoadKeyboardLayoutA
 0367 stub LoadKeyboardLayoutW
 0368 stub LoadLocalFonts
-0369 stub LoadMenuA
-0370 stub LoadMenuIndirectA
-0371 stub LoadMenuIndirectW
-0372 stub LoadMenuW
+0369 stdcall LoadMenuA(long ptr) WIN32_LoadMenuA
+0370 stdcall LoadMenuIndirectA(long ptr) WIN32_LoadMenuIndirectA
+0371 stdcall LoadMenuIndirectW(long ptr) WIN32_LoadMenuIndirectW
+0372 stdcall LoadMenuW(long ptr) WIN32_LoadMenuW
 0373 stub LoadRemoteFonts
-0374 	stdcall LoadStringA(long long ptr long) LoadStringA32
-0375 	stdcall LoadStringW(long long ptr long) LoadString32
+0374 	stdcall LoadStringA(long long ptr long) WIN32_LoadStringA
+0375 	stdcall LoadStringW(long long ptr long) WIN32_LoadStringW
 0376 stub LockWindowStation
 0377 stub LockWindowUpdate
 0378 stub LookupIconIdFromDirectory
@@ -524,7 +524,7 @@
 0518 stub SetWindowPlacement
 0519 stub SetWindowPos
 0520 stub SetWindowStationUser
-0521 stub SetWindowTextA
+0521 stdcall SetWindowTextA(long ptr)	SetWindowText
 0522 stub SetWindowTextW
 0523 stub SetWindowWord
 0524 stub SetWindowsHookA
@@ -581,7 +581,7 @@
 0575 stub VkKeyScanW
 0576 stub WaitForInputIdle
 0577 stub WaitMessage
-0578 stub WinHelpA
+0578 stdcall WinHelpA(long ptr long long)	WIN32_WinHelpA
 0579 stub WinHelpW
 0580 stub WindowFromDC
 0581 stub WindowFromPoint
diff --git a/include/debug.h b/include/debug.h
index 928922e..82e08eb 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -54,13 +54,11 @@
 #undef DEBUG_LDT
 #undef DEBUG_LISTBOX
 #undef DEBUG_LOCAL
-#undef DEBUG_MALLOC
 #undef DEBUG_MCI
 #undef DEBUG_MCIANIM
 #undef DEBUG_MCIWAVE
 #undef DEBUG_MDI
 #undef DEBUG_MENU
-#undef DEBUG_MENUCALC
 #undef DEBUG_MESSAGE
 #undef DEBUG_METAFILE
 #undef DEBUG_MIDI
@@ -134,13 +132,11 @@
 #define DEBUG_LDT
 #define DEBUG_LISTBOX
 #define DEBUG_LOCAL
-#define DEBUG_MALLOC
 #define DEBUG_MCI
 #define DEBUG_MCIANIM
 #define DEBUG_MCIWAVE
 #define DEBUG_MDI
 #define DEBUG_MENU
-#define DEBUG_MENUCALC
 #define DEBUG_MESSAGE
 #define DEBUG_METAFILE
 #define DEBUG_MIDI
@@ -368,11 +364,6 @@
 #else
     0,
 #endif
-#ifdef DEBUG_MALLOC
-    1,
-#else
-    0,
-#endif
 #ifdef DEBUG_MCI
     1,
 #else
@@ -398,11 +389,6 @@
 #else
     0,
 #endif
-#ifdef DEBUG_MENUCALC
-    1,
-#else
-    0,
-#endif
 #ifdef DEBUG_MESSAGE
     1,
 #else
@@ -1065,21 +1051,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_malloc if(!debug_msg_enabled[38]) ; else fprintf
-#define debugging_malloc debug_msg_enabled[38]
-#else
-#ifdef DEBUG_MALLOC
-#define dprintf_malloc fprintf
-#define debugging_malloc 1
-#else
-#define dprintf_malloc while(0) fprintf
-#define debugging_malloc 0
-#endif
-#endif
-
-#ifdef DEBUG_RUNTIME
-#define dprintf_mci if(!debug_msg_enabled[39]) ; else fprintf
-#define debugging_mci debug_msg_enabled[39]
+#define dprintf_mci if(!debug_msg_enabled[38]) ; else fprintf
+#define debugging_mci debug_msg_enabled[38]
 #else
 #ifdef DEBUG_MCI
 #define dprintf_mci fprintf
@@ -1091,8 +1064,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mcianim if(!debug_msg_enabled[40]) ; else fprintf
-#define debugging_mcianim debug_msg_enabled[40]
+#define dprintf_mcianim if(!debug_msg_enabled[39]) ; else fprintf
+#define debugging_mcianim debug_msg_enabled[39]
 #else
 #ifdef DEBUG_MCIANIM
 #define dprintf_mcianim fprintf
@@ -1104,8 +1077,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mciwave if(!debug_msg_enabled[41]) ; else fprintf
-#define debugging_mciwave debug_msg_enabled[41]
+#define dprintf_mciwave if(!debug_msg_enabled[40]) ; else fprintf
+#define debugging_mciwave debug_msg_enabled[40]
 #else
 #ifdef DEBUG_MCIWAVE
 #define dprintf_mciwave fprintf
@@ -1117,8 +1090,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mdi if(!debug_msg_enabled[42]) ; else fprintf
-#define debugging_mdi debug_msg_enabled[42]
+#define dprintf_mdi if(!debug_msg_enabled[41]) ; else fprintf
+#define debugging_mdi debug_msg_enabled[41]
 #else
 #ifdef DEBUG_MDI
 #define dprintf_mdi fprintf
@@ -1130,8 +1103,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_menu if(!debug_msg_enabled[43]) ; else fprintf
-#define debugging_menu debug_msg_enabled[43]
+#define dprintf_menu if(!debug_msg_enabled[42]) ; else fprintf
+#define debugging_menu debug_msg_enabled[42]
 #else
 #ifdef DEBUG_MENU
 #define dprintf_menu fprintf
@@ -1143,21 +1116,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_menucalc if(!debug_msg_enabled[44]) ; else fprintf
-#define debugging_menucalc debug_msg_enabled[44]
-#else
-#ifdef DEBUG_MENUCALC
-#define dprintf_menucalc fprintf
-#define debugging_menucalc 1
-#else
-#define dprintf_menucalc while(0) fprintf
-#define debugging_menucalc 0
-#endif
-#endif
-
-#ifdef DEBUG_RUNTIME
-#define dprintf_message if(!debug_msg_enabled[45]) ; else fprintf
-#define debugging_message debug_msg_enabled[45]
+#define dprintf_message if(!debug_msg_enabled[43]) ; else fprintf
+#define debugging_message debug_msg_enabled[43]
 #else
 #ifdef DEBUG_MESSAGE
 #define dprintf_message fprintf
@@ -1169,8 +1129,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_metafile if(!debug_msg_enabled[46]) ; else fprintf
-#define debugging_metafile debug_msg_enabled[46]
+#define dprintf_metafile if(!debug_msg_enabled[44]) ; else fprintf
+#define debugging_metafile debug_msg_enabled[44]
 #else
 #ifdef DEBUG_METAFILE
 #define dprintf_metafile fprintf
@@ -1182,8 +1142,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_midi if(!debug_msg_enabled[47]) ; else fprintf
-#define debugging_midi debug_msg_enabled[47]
+#define dprintf_midi if(!debug_msg_enabled[45]) ; else fprintf
+#define debugging_midi debug_msg_enabled[45]
 #else
 #ifdef DEBUG_MIDI
 #define dprintf_midi fprintf
@@ -1195,8 +1155,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mmio if(!debug_msg_enabled[48]) ; else fprintf
-#define debugging_mmio debug_msg_enabled[48]
+#define dprintf_mmio if(!debug_msg_enabled[46]) ; else fprintf
+#define debugging_mmio debug_msg_enabled[46]
 #else
 #ifdef DEBUG_MMIO
 #define dprintf_mmio fprintf
@@ -1208,8 +1168,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mmsys if(!debug_msg_enabled[49]) ; else fprintf
-#define debugging_mmsys debug_msg_enabled[49]
+#define dprintf_mmsys if(!debug_msg_enabled[47]) ; else fprintf
+#define debugging_mmsys debug_msg_enabled[47]
 #else
 #ifdef DEBUG_MMSYS
 #define dprintf_mmsys fprintf
@@ -1221,8 +1181,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mmtime if(!debug_msg_enabled[50]) ; else fprintf
-#define debugging_mmtime debug_msg_enabled[50]
+#define dprintf_mmtime if(!debug_msg_enabled[48]) ; else fprintf
+#define debugging_mmtime debug_msg_enabled[48]
 #else
 #ifdef DEBUG_MMTIME
 #define dprintf_mmtime fprintf
@@ -1234,8 +1194,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_module if(!debug_msg_enabled[51]) ; else fprintf
-#define debugging_module debug_msg_enabled[51]
+#define dprintf_module if(!debug_msg_enabled[49]) ; else fprintf
+#define debugging_module debug_msg_enabled[49]
 #else
 #ifdef DEBUG_MODULE
 #define dprintf_module fprintf
@@ -1247,8 +1207,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_msg if(!debug_msg_enabled[52]) ; else fprintf
-#define debugging_msg debug_msg_enabled[52]
+#define dprintf_msg if(!debug_msg_enabled[50]) ; else fprintf
+#define debugging_msg debug_msg_enabled[50]
 #else
 #ifdef DEBUG_MSG
 #define dprintf_msg fprintf
@@ -1260,8 +1220,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_nonclient if(!debug_msg_enabled[53]) ; else fprintf
-#define debugging_nonclient debug_msg_enabled[53]
+#define dprintf_nonclient if(!debug_msg_enabled[51]) ; else fprintf
+#define debugging_nonclient debug_msg_enabled[51]
 #else
 #ifdef DEBUG_NONCLIENT
 #define dprintf_nonclient fprintf
@@ -1273,8 +1233,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_ole if(!debug_msg_enabled[54]) ; else fprintf
-#define debugging_ole debug_msg_enabled[54]
+#define dprintf_ole if(!debug_msg_enabled[52]) ; else fprintf
+#define debugging_ole debug_msg_enabled[52]
 #else
 #ifdef DEBUG_OLE
 #define dprintf_ole fprintf
@@ -1286,8 +1246,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_palette if(!debug_msg_enabled[55]) ; else fprintf
-#define debugging_palette debug_msg_enabled[55]
+#define dprintf_palette if(!debug_msg_enabled[53]) ; else fprintf
+#define debugging_palette debug_msg_enabled[53]
 #else
 #ifdef DEBUG_PALETTE
 #define dprintf_palette fprintf
@@ -1299,8 +1259,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_profile if(!debug_msg_enabled[56]) ; else fprintf
-#define debugging_profile debug_msg_enabled[56]
+#define dprintf_profile if(!debug_msg_enabled[54]) ; else fprintf
+#define debugging_profile debug_msg_enabled[54]
 #else
 #ifdef DEBUG_PROFILE
 #define dprintf_profile fprintf
@@ -1312,8 +1272,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_prop if(!debug_msg_enabled[57]) ; else fprintf
-#define debugging_prop debug_msg_enabled[57]
+#define dprintf_prop if(!debug_msg_enabled[55]) ; else fprintf
+#define debugging_prop debug_msg_enabled[55]
 #else
 #ifdef DEBUG_PROP
 #define dprintf_prop fprintf
@@ -1325,8 +1285,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_reg if(!debug_msg_enabled[58]) ; else fprintf
-#define debugging_reg debug_msg_enabled[58]
+#define dprintf_reg if(!debug_msg_enabled[56]) ; else fprintf
+#define debugging_reg debug_msg_enabled[56]
 #else
 #ifdef DEBUG_REG
 #define dprintf_reg fprintf
@@ -1338,8 +1298,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_region if(!debug_msg_enabled[59]) ; else fprintf
-#define debugging_region debug_msg_enabled[59]
+#define dprintf_region if(!debug_msg_enabled[57]) ; else fprintf
+#define debugging_region debug_msg_enabled[57]
 #else
 #ifdef DEBUG_REGION
 #define dprintf_region fprintf
@@ -1351,8 +1311,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_relay if(!debug_msg_enabled[60]) ; else fprintf
-#define debugging_relay debug_msg_enabled[60]
+#define dprintf_relay if(!debug_msg_enabled[58]) ; else fprintf
+#define debugging_relay debug_msg_enabled[58]
 #else
 #ifdef DEBUG_RELAY
 #define dprintf_relay fprintf
@@ -1364,8 +1324,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_resource if(!debug_msg_enabled[61]) ; else fprintf
-#define debugging_resource debug_msg_enabled[61]
+#define dprintf_resource if(!debug_msg_enabled[59]) ; else fprintf
+#define debugging_resource debug_msg_enabled[59]
 #else
 #ifdef DEBUG_RESOURCE
 #define dprintf_resource fprintf
@@ -1377,8 +1337,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_scroll if(!debug_msg_enabled[62]) ; else fprintf
-#define debugging_scroll debug_msg_enabled[62]
+#define dprintf_scroll if(!debug_msg_enabled[60]) ; else fprintf
+#define debugging_scroll debug_msg_enabled[60]
 #else
 #ifdef DEBUG_SCROLL
 #define dprintf_scroll fprintf
@@ -1390,8 +1350,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_selector if(!debug_msg_enabled[63]) ; else fprintf
-#define debugging_selector debug_msg_enabled[63]
+#define dprintf_selector if(!debug_msg_enabled[61]) ; else fprintf
+#define debugging_selector debug_msg_enabled[61]
 #else
 #ifdef DEBUG_SELECTOR
 #define dprintf_selector fprintf
@@ -1403,8 +1363,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_sem if(!debug_msg_enabled[64]) ; else fprintf
-#define debugging_sem debug_msg_enabled[64]
+#define dprintf_sem if(!debug_msg_enabled[62]) ; else fprintf
+#define debugging_sem debug_msg_enabled[62]
 #else
 #ifdef DEBUG_SEM
 #define dprintf_sem fprintf
@@ -1416,8 +1376,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_shm if(!debug_msg_enabled[65]) ; else fprintf
-#define debugging_shm debug_msg_enabled[65]
+#define dprintf_shm if(!debug_msg_enabled[63]) ; else fprintf
+#define debugging_shm debug_msg_enabled[63]
 #else
 #ifdef DEBUG_SHM
 #define dprintf_shm fprintf
@@ -1429,8 +1389,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_stress if(!debug_msg_enabled[66]) ; else fprintf
-#define debugging_stress debug_msg_enabled[66]
+#define dprintf_stress if(!debug_msg_enabled[64]) ; else fprintf
+#define debugging_stress debug_msg_enabled[64]
 #else
 #ifdef DEBUG_STRESS
 #define dprintf_stress fprintf
@@ -1442,8 +1402,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_syscolor if(!debug_msg_enabled[67]) ; else fprintf
-#define debugging_syscolor debug_msg_enabled[67]
+#define dprintf_syscolor if(!debug_msg_enabled[65]) ; else fprintf
+#define debugging_syscolor debug_msg_enabled[65]
 #else
 #ifdef DEBUG_SYSCOLOR
 #define dprintf_syscolor fprintf
@@ -1455,8 +1415,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_task if(!debug_msg_enabled[68]) ; else fprintf
-#define debugging_task debug_msg_enabled[68]
+#define dprintf_task if(!debug_msg_enabled[66]) ; else fprintf
+#define debugging_task debug_msg_enabled[66]
 #else
 #ifdef DEBUG_TASK
 #define dprintf_task fprintf
@@ -1468,8 +1428,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_text if(!debug_msg_enabled[69]) ; else fprintf
-#define debugging_text debug_msg_enabled[69]
+#define dprintf_text if(!debug_msg_enabled[67]) ; else fprintf
+#define debugging_text debug_msg_enabled[67]
 #else
 #ifdef DEBUG_TEXT
 #define dprintf_text fprintf
@@ -1481,8 +1441,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_timer if(!debug_msg_enabled[70]) ; else fprintf
-#define debugging_timer debug_msg_enabled[70]
+#define dprintf_timer if(!debug_msg_enabled[68]) ; else fprintf
+#define debugging_timer debug_msg_enabled[68]
 #else
 #ifdef DEBUG_TIMER
 #define dprintf_timer fprintf
@@ -1494,8 +1454,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_toolhelp if(!debug_msg_enabled[71]) ; else fprintf
-#define debugging_toolhelp debug_msg_enabled[71]
+#define dprintf_toolhelp if(!debug_msg_enabled[69]) ; else fprintf
+#define debugging_toolhelp debug_msg_enabled[69]
 #else
 #ifdef DEBUG_TOOLHELP
 #define dprintf_toolhelp fprintf
@@ -1507,8 +1467,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_utility if(!debug_msg_enabled[72]) ; else fprintf
-#define debugging_utility debug_msg_enabled[72]
+#define dprintf_utility if(!debug_msg_enabled[70]) ; else fprintf
+#define debugging_utility debug_msg_enabled[70]
 #else
 #ifdef DEBUG_UTILITY
 #define dprintf_utility fprintf
@@ -1520,8 +1480,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_vxd if(!debug_msg_enabled[73]) ; else fprintf
-#define debugging_vxd debug_msg_enabled[73]
+#define dprintf_vxd if(!debug_msg_enabled[71]) ; else fprintf
+#define debugging_vxd debug_msg_enabled[71]
 #else
 #ifdef DEBUG_VXD
 #define dprintf_vxd fprintf
@@ -1533,8 +1493,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_win if(!debug_msg_enabled[74]) ; else fprintf
-#define debugging_win debug_msg_enabled[74]
+#define dprintf_win if(!debug_msg_enabled[72]) ; else fprintf
+#define debugging_win debug_msg_enabled[72]
 #else
 #ifdef DEBUG_WIN
 #define dprintf_win fprintf
@@ -1546,8 +1506,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_win32 if(!debug_msg_enabled[75]) ; else fprintf
-#define debugging_win32 debug_msg_enabled[75]
+#define dprintf_win32 if(!debug_msg_enabled[73]) ; else fprintf
+#define debugging_win32 debug_msg_enabled[73]
 #else
 #ifdef DEBUG_WIN32
 #define dprintf_win32 fprintf
@@ -1559,8 +1519,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_winsock if(!debug_msg_enabled[76]) ; else fprintf
-#define debugging_winsock debug_msg_enabled[76]
+#define dprintf_winsock if(!debug_msg_enabled[74]) ; else fprintf
+#define debugging_winsock debug_msg_enabled[74]
 #else
 #ifdef DEBUG_WINSOCK
 #define dprintf_winsock fprintf
@@ -1613,13 +1573,11 @@
     "ldt",
     "listbox",
     "local",
-    "malloc",
     "mci",
     "mcianim",
     "mciwave",
     "mdi",
     "menu",
-    "menucalc",
     "message",
     "metafile",
     "midi",
diff --git a/include/debugger.h b/include/debugger.h
index deb92fa..42b4206 100644
--- a/include/debugger.h
+++ b/include/debugger.h
@@ -11,6 +11,8 @@
 #include "registers.h"
 #include "wine.h"
 
+#define STEP_FLAG 0x100 /* single step flag */
+
 typedef struct
 {
     DWORD seg;  /* 0xffffffff means current default segment (cs or ds) */
diff --git a/include/drive.h b/include/drive.h
index ab9fa9d..b386b85 100644
--- a/include/drive.h
+++ b/include/drive.h
@@ -11,6 +11,15 @@
 
 #define MAX_DOS_DRIVES  26
 
+typedef enum
+{
+    TYPE_FLOPPY,
+    TYPE_HD,
+    TYPE_CDROM,
+    TYPE_NETWORK,
+    TYPE_INVALID
+} DRIVETYPE;
+
 extern int DRIVE_Init(void);
 extern int DRIVE_IsValid( int drive );
 extern int DRIVE_GetCurrentDrive(void);
@@ -22,8 +31,10 @@
 extern const char * DRIVE_GetLabel( int drive );
 extern DWORD DRIVE_GetSerialNumber( int drive );
 extern int DRIVE_SetSerialNumber( int drive, DWORD serial );
+extern DRIVETYPE DRIVE_GetType( int drive );
 extern int DRIVE_Chdir( int drive, const char *path );
 extern int DRIVE_Disable( int drive  );
 extern int DRIVE_Enable( int drive  );
+extern int DRIVE_GetFreeSpace( int drive, DWORD *size, DWORD *available );
 
 #endif  /* __WINE_DRIVE_H */
diff --git a/include/kernel32.h b/include/kernel32.h
index ecb4fc6..12e5761 100644
--- a/include/kernel32.h
+++ b/include/kernel32.h
@@ -11,11 +11,6 @@
 void SetLastError(DWORD error);
 DWORD ErrnoToLastError(int errno_num);
 
-/* Linux's wchar_t is unsigned long but Win32 wants unsigned short
- */
-typedef unsigned short WCHAR;
-typedef WCHAR *LPTSTR;
-
 /* Code page information.
  */
 typedef struct {
@@ -57,8 +52,6 @@
         HANDLE hStdError;
 } STARTUPINFO, *LPSTARTUPINFO;
 
-/* SYSTEMTIME, and LPSYSTEMTIME moved to include/windows.h (JBP) */
-
 typedef struct {
         LONG Bias;
         WCHAR StandardName[32];
diff --git a/include/listbox.h b/include/listbox.h
index e266b8a..5430172 100644
--- a/include/listbox.h
+++ b/include/listbox.h
@@ -47,8 +47,8 @@
 extern LPLISTSTRUCT ListBoxGetItem(LPHEADLIST lphl, UINT uIndex);
 extern int ListMaxFirstVisible(LPHEADLIST lphl);
 extern int ListBoxScrollToFocus(LPHEADLIST lphl);
-extern int ListBoxAddString(LPHEADLIST lphl, LPSTR newstr);
-extern int ListBoxInsertString(LPHEADLIST lphl, UINT uIndex, LPSTR newstr);
+extern int ListBoxAddString(LPHEADLIST lphl, LPCSTR newstr);
+extern int ListBoxInsertString(LPHEADLIST lphl, UINT uIndex, LPCSTR newstr);
 extern int ListBoxGetText(LPHEADLIST lphl, UINT uIndex, LPSTR OutStr);
 extern DWORD ListBoxGetItemData(LPHEADLIST lphl, UINT uIndex);
 extern int ListBoxSetItemData(LPHEADLIST lphl, UINT uIndex, DWORD ItemData);
@@ -58,7 +58,7 @@
 extern int ListBoxSetCurSel(LPHEADLIST lphl, WORD wIndex);
 extern int ListBoxSetSel(LPHEADLIST lphl, WORD wIndex, WORD state);
 extern int ListBoxGetSel(LPHEADLIST lphl, WORD wIndex);
-extern int ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPSTR filespec);
+extern LONG ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPCSTR filespec);
 extern int ListBoxGetItemRect(LPHEADLIST lphl, WORD wIndex, LPRECT rect);
 extern int ListBoxSetItemHeight(LPHEADLIST lphl, WORD wIndex, long height);
 extern int ListBoxFindNextMatch(LPHEADLIST lphl, WORD wChar);
diff --git a/include/mdi.h b/include/mdi.h
index e7c2573..a34c1d0 100644
--- a/include/mdi.h
+++ b/include/mdi.h
@@ -12,6 +12,11 @@
 #include "windows.h"
 
 #define MDI_MAXLISTLENGTH	0x40
+#define MDI_MAXTITLELENGTH	0xA1
+
+#define MDI_NOFRAMEREPAINT	0
+#define MDI_REPAINTFRAMENOW	1
+#define MDI_REPAINTFRAME	2
 
 #define WM_MDICALCCHILDSCROLL   0x10AC /* this is exactly what Windows uses */
 
@@ -31,12 +36,13 @@
     HWND   hwndActiveChild;
     HMENU  hWindowMenu;
     WORD   idFirstChild;       /* order is 3.1-like up to this point */
+    HANDLE hFrameTitle;
     WORD   sbStop;
     WORD   sbRecalc;
+    HBITMAP obmClose;
+    HBITMAP obmRestore;
     HWND   hwndHitTest;
-    RECT   rectMaximize;
-    RECT   rectRestore;
+    HWND   self;
 } MDICLIENTINFO;
 
-
 #endif /* MDI_H */
diff --git a/include/menu.h b/include/menu.h
index 5a25e1e..41f2047 100644
--- a/include/menu.h
+++ b/include/menu.h
@@ -26,7 +26,6 @@
     HBITMAP	hCheckBit;     /* Bitmap for checked item */
     HBITMAP	hUnCheckBit;   /* Bitmap for unchecked item */
     HANDLE      hText;	       /* Handle to item string or bitmap */
-    char	*item_text;
 } MENUITEM, *LPMENUITEM;
 
 
diff --git a/include/miscemu.h b/include/miscemu.h
index 99186e7..33d7648 100644
--- a/include/miscemu.h
+++ b/include/miscemu.h
@@ -27,7 +27,7 @@
 extern DWORD INT1A_GetTicksSinceMidnight(void);
 
   /* miscemu/int21.c */
-extern void INT21_Init(void);
+extern BOOL INT21_Init(void);
 
   /* miscemu/ioports.c */
 extern DWORD inport( int port, int count );
diff --git a/include/options.h b/include/options.h
index 7d3bbf1..684aa6b 100644
--- a/include/options.h
+++ b/include/options.h
@@ -39,4 +39,10 @@
 
 extern struct options Options;
 
+/* Profile functions */
+
+extern int PROFILE_LoadWineIni(void);
+extern int PROFILE_GetWineIniString( const char *section, const char *key_name,
+                                     const char *def, char *buffer, int len );
+
 #endif
diff --git a/include/resource32.h b/include/resource32.h
index 6a2ac43..bcddc21 100644
--- a/include/resource32.h
+++ b/include/resource32.h
@@ -16,7 +16,8 @@
 BOOL FreeResource32( HANDLE32 handle );
 INT AccessResource32( HINSTANCE hModule, HRSRC hRsrc );
 DWORD SizeofResource32( HINSTANCE hModule, HRSRC hRsrc );
-int LoadString32(HINSTANCE instance, DWORD resource_id, LPTSTR buffer, int buflen);
+int WIN32_LoadStringW(HINSTANCE instance, DWORD resource_id, LPWSTR buffer, int buflen);
+int WIN32_LoadStringA(HINSTANCE instance, DWORD resource_id, LPSTR buffer, int buflen);
 
 typedef struct _IMAGE_RESOURCE_DIRECTORY {
 	DWORD Characteristics;
diff --git a/include/shell.h b/include/shell.h
index 88ca4b1..481f149 100644
--- a/include/shell.h
+++ b/include/shell.h
@@ -1,6 +1,12 @@
 /*
  * 				Shell Library definitions
  */
+#include "wintypes.h"
+
+#ifndef __WINE_SHELL_H
+#define __WINE_SHELL_H
+
+#include "windows.h"
 
 extern INT ShellAbout(HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON hIcon);
 extern void SHELL_LoadRegistry();
@@ -21,13 +27,6 @@
 
 #define HKEY_CLASSES_ROOT       1
 
-#ifdef WINELIB32
-typedef void* HKEY;
-#else
-typedef DWORD HKEY;
-#endif
-typedef HKEY FAR* LPHKEY;
-
 typedef struct tagKEYSTRUCT {
 	HKEY		hKey;
 	LPSTR		lpSubKey;
@@ -54,3 +53,4 @@
 
 LRESULT AboutDlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
 
+#endif  /* __WINE_SHELL_H */
diff --git a/include/stddebug.h b/include/stddebug.h
index b5c8917..54cc9d2 100644
--- a/include/stddebug.h
+++ b/include/stddebug.h
@@ -114,13 +114,11 @@
 #undef DEBUG_LDT
 #undef DEBUG_LISTBOX
 #undef DEBUG_LOCAL
-#undef DEBUG_MALLOC
 #undef DEBUG_MCI
 #undef DEBUG_MCIANIM
 #undef DEBUG_MCIWAVE
 #undef DEBUG_MDI
 #undef DEBUG_MENU
-#undef DEBUG_MENUCALC
 #undef DEBUG_MESSAGE
 #undef DEBUG_METAFILE
 #undef DEBUG_MIDI
@@ -194,13 +192,11 @@
 #define DEBUG_LDT
 #define DEBUG_LISTBOX
 #define DEBUG_LOCAL
-#define DEBUG_MALLOC
 #define DEBUG_MCI
 #define DEBUG_MCIANIM
 #define DEBUG_MCIWAVE
 #define DEBUG_MDI
 #define DEBUG_MENU
-#define DEBUG_MENUCALC
 #define DEBUG_MESSAGE
 #define DEBUG_METAFILE
 #define DEBUG_MIDI
diff --git a/include/string32.h b/include/string32.h
new file mode 100644
index 0000000..b598c0e
--- /dev/null
+++ b/include/string32.h
@@ -0,0 +1,20 @@
+/*
+ * Unicode string management
+ *
+ * Copyright 1995 Martin von Loewis
+ *
+ */
+
+#ifndef _STRING32_H
+#define _STRING32_H
+
+#include "wintypes.h"
+
+int STRING32_UniLen(LPWSTR s);
+void STRING32_UniToAnsi(LPSTR dest,LPCWSTR src);
+void STRING32_AnsiToUni(LPWSTR dest,LPCSTR src);
+LPSTR STRING32_DupUniToAnsi(LPWSTR src);
+LPWSTR STRING32_DupAnsiToUni(LPSTR src);
+LPWSTR STRING32_lstrcmpnW(LPCWSTR a,LPCWSTR b,DWORD len);
+
+#endif
diff --git a/include/struct32.h b/include/struct32.h
new file mode 100644
index 0000000..f9394cd
--- /dev/null
+++ b/include/struct32.h
@@ -0,0 +1,25 @@
+/* Structure definitions for Win32 -- used only internally */
+#ifndef _STRUCT32_H
+#define _STRUCT32_H
+
+typedef struct tagRECT32
+{
+	LONG left;
+	LONG top;
+	LONG right;
+	LONG bottom;
+} RECT32;
+
+void USER32_RECT32to16(const RECT32*,RECT*);
+void USER32_RECT16to32(const RECT*,RECT32*);
+
+typedef struct tagPOINT32
+{
+	LONG x;
+	LONG y;
+} POINT32;
+
+void PARAM32_POINT32to16(const POINT32*,POINT*);
+void PARAM32_POINT16to32(const POINT*,POINT32*);
+
+#endif
diff --git a/include/toolhelp.h b/include/toolhelp.h
index 43d0e7f..722d735 100644
--- a/include/toolhelp.h
+++ b/include/toolhelp.h
@@ -261,5 +261,87 @@
 DWORD MemoryRead( WORD sel, DWORD offset, void *buffer, DWORD count );
 DWORD MemoryWrite( WORD sel, DWORD offset, void *buffer, DWORD count );
 
+/* flags to NotifyRegister() */
+#define NF_NORMAL	0	/* everything except taskswitches, debugerrors,
+				 * debugstrings
+				 */
+#define NF_TASKSWITCH	1	/* get taskswitch information */
+#define NF_RIP		2	/* get debugerrors of system */
 
+BOOL NotifyRegister(HTASK htask,FARPROC lpfnCallback,WORD wFlags);
+
+#define NFY_UNKNOWN	0
+#define NFY_LOADSEG	1
+/* DATA is a pointer to following struct: */
+struct {
+	DWORD	dwSize;
+	WORD	wSelector;
+	WORD	wSegNum;
+	WORD	wType;		/* bit 0 set if this is a code segment */
+	WORD	wcInstance;	/* only valid for data segment */
+} NFYLOADSEG;
+/* called when freeing a segment. LOWORD(dwData) is the freed selector */
+#define NFY_FREESEG	2
+
+/* called when loading/starting a DLL */
+#define NFY_STARTDLL	3
+struct {
+	DWORD	dwSize;
+	HMODULE	hModule;
+	WORD	wCS;
+	WORD	wIP;
+} NFYSTARTDLL;
+
+/* called when starting a task. dwData is CS:IP */
+#define NFY_STARTTASK	4
+
+/* called when a task terminates. dwData is the return code */
+#define NFY_EXITTASK	5
+
+/* called when module is removed. LOWORD(dwData) is the handle */
+#define NFY_DELMODULE	6
+
+/* RIP? debugevent */
+#define NFY_RIP		7
+struct {
+	DWORD	dwSize;
+	WORD	wIP;
+	WORD	wCS;
+	WORD	wSS;
+	WORD	wBP;
+	WORD	wExitCode;
+} NFYRIP;
+
+/* called before (after?) switching to a task
+ * no data, callback should call GetCurrentTask
+ */
+#define	NFY_TASKIN	8
+
+/* called before(after?) switching from a task
+ * no data, callback should call GetCurrentTask
+*/
+#define NFY_TASKOUT	9
+
+/* returns ASCII input value, dwData not set */
+#define NFY_INCHAR	10
+
+/* output debugstring (pointed to by dwData) */
+#define NFY_OUTSTRING	11
+
+/* log errors */
+#define NFY_LOGERROR	12
+struct {
+	DWORD	dwSize;
+	UINT	wErrCode;
+	VOID	FAR*	lpInfo;	/* depends on wErrCode */
+} NFYLOGERROR;
+
+/* called for parameter errors? */
+#define NFY_LOGPARAMERROR	13
+struct {
+	DWORD	dwSize;
+	UINT	wErrCode;
+	FARPROC	lpfnErrorAddr;
+	void FAR* FAR* lpBadParam;
+} NFYLOGPARAMERROR;
 #endif /* __TOOLHELP_H */
diff --git a/include/windows.h b/include/windows.h
index b7f8298..0e2ce32 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -36,6 +36,12 @@
 #define MAKELPARAM(low, high) ((LONG)(((WORD)(low)) | \
 			      (((DWORD)((WORD)(high))) << 16)))
 
+typedef struct tagKERNINGPAIR {
+        WORD wFirst;
+        WORD wSecond;
+        INT  iKernAmount;
+} KERNINGPAIR, *LPKERNINGPAIR;
+
 typedef struct {
 	HDC hdc;
 	BOOL	fErase;
@@ -125,6 +131,9 @@
     LONG      lParam WINE_PACKED;
 } MDICREATESTRUCT, *LPMDICREATESTRUCT;
 
+#define MDITILE_VERTICAL    0    
+#define MDITILE_HORIZONTAL  1
+
   /* Offsets for GetWindowLong() and GetWindowWord() */
 #define GWL_EXSTYLE         (-20)
 #define GWL_STYLE           (-16)
@@ -1697,6 +1706,7 @@
 #define SW_RESTORE          9
 #define SW_SHOWDEFAULT	    10
 #define SW_MAX		    10
+#define SW_NORMALNA	    0xCC	/* undoc. flag in MinMaximize */
 
   /* WM_SIZE message wParam values */
 #define SIZE_RESTORED        0
@@ -1704,6 +1714,11 @@
 #define SIZE_MAXIMIZED       2
 #define SIZE_MAXSHOW         3
 #define SIZE_MAXHIDE         4
+#define SIZENORMAL           SIZE_RESTORED
+#define SIZEICONIC           SIZE_MINIMIZED
+#define SIZEFULLSCREEN       SIZE_MAXIMIZED
+#define SIZEZOOMSHOW         SIZE_MAXSHOW
+#define SIZEZOOMHIDE         SIZE_MAXHIDE
 
 /* SetWindowPos() and WINDOWPOS flags */
 #define SWP_NOSIZE          0x0001
@@ -2100,7 +2115,7 @@
 #define ES_PASSWORD     0x00000020L
 #define ES_AUTOVSCROLL  0x00000040L
 #define ES_AUTOHSCROLL  0x00000080L
-#define ES_NOHISESEL    0x00000100L
+#define ES_NOHIDESEL    0x00000100L
 #define ES_OEMCONVERT   0x00000400L
 #define ES_READONLY     0x00000800L
 #define ES_WANTRETURN   0x00001000L
@@ -2536,6 +2551,21 @@
         WORD wMilliseconds;
 } SYSTEMTIME, *LPSYSTEMTIME;
 
+#define HELP_CONTEXT        0x0001
+#define HELP_QUIT           0x0002
+#define HELP_INDEX          0x0003
+#define HELP_CONTENTS       0x0003
+#define HELP_HELPONHELP     0x0004
+#define HELP_SETINDEX       0x0005
+#define HELP_SETCONTENTS    0x0005
+#define HELP_CONTEXTPOPUP   0x0008
+#define HELP_FORCEFILE      0x0009
+#define HELP_KEY            0x0101
+#define HELP_COMMAND        0x0102
+#define HELP_PARTIALKEY     0x0105
+#define HELP_MULTIKEY       0x0201
+#define HELP_SETWINPOS      0x0203
+
 #ifndef WINELIB
 #pragma pack(4)
 #endif
@@ -2543,86 +2573,93 @@
 INT        AccessResource(HINSTANCE,HRSRC);
 ATOM       AddAtom(SEGPTR);
 INT        AddFontResource(LPCSTR);
-void       AdjustWindowRect(LPRECT,DWORD,BOOL);
-void       AdjustWindowRectEx(LPRECT,DWORD,BOOL,DWORD);
+BOOL       AdjustWindowRect(LPRECT,DWORD,BOOL);
+BOOL       AdjustWindowRectEx(LPRECT,DWORD,BOOL,DWORD);
 WORD       AllocCStoDSAlias(WORD);
 WORD       AllocDStoCSAlias(WORD);
 HGLOBAL    AllocResource(HINSTANCE,HRSRC,DWORD);
 WORD       AllocSelector(WORD);
 WORD       AllocSelectorArray(WORD);
-void       AnimatePalette(HPALETTE,UINT,UINT,LPPALETTEENTRY);
+BOOL       AnimatePalette(HPALETTE,UINT,UINT,LPPALETTEENTRY);
 LPSTR      AnsiLower(LPSTR);
 UINT       AnsiLowerBuff(LPSTR,UINT);
 SEGPTR     AnsiNext(SEGPTR);
 SEGPTR     AnsiPrev(SEGPTR,SEGPTR);
 INT        AnsiToOem(LPSTR,LPSTR);
-void       AnsiToOemBuff(LPSTR,LPSTR,INT);
+void       AnsiToOemBuff(LPCSTR,LPSTR,UINT);
 LPSTR      AnsiUpper(LPSTR);
 UINT       AnsiUpperBuff(LPSTR,UINT);
 BOOL       AnyPopup(void);
-BOOL       AppendMenu(HMENU,UINT,UINT,LPSTR);
+BOOL       AppendMenu(HMENU,UINT,UINT,SEGPTR);
 BOOL       Arc(HDC,INT,INT,INT,INT,INT,INT,INT,INT);
-WORD       ArrangeIconicWindows(HWND);
+UINT       ArrangeIconicWindows(HWND);
 HDWP       BeginDeferWindowPos(INT);
 HDC        BeginPaint(HWND,LPPAINTSTRUCT);
 BOOL       BitBlt(HDC,INT,INT,INT,INT,HDC,INT,INT,DWORD);
 BOOL       BringWindowToTop(HWND);
-int        BuildCommDCB(LPSTR,DCB*);
+BOOL       BuildCommDCB(LPCSTR,DCB*);
 void       CalcChildScroll(HWND,WORD);
-BOOL       CallMsgFilter(SEGPTR,short);
-DWORD      CallNextHookEx(HHOOK,short,WPARAM,LPARAM);
-LONG       CallWindowProc(WNDPROC,HWND,UINT,WPARAM,LPARAM);
-int        Catch(LPCATCHBUF);
+BOOL       CallMsgFilter(SEGPTR,INT);
+LRESULT    CallNextHookEx(HHOOK,INT,WPARAM,LPARAM);
+LRESULT    CallWindowProc(WNDPROC,HWND,UINT,WPARAM,LPARAM);
+INT        Catch(LPCATCHBUF);
 BOOL       ChangeClipboardChain(HWND,HWND);
-BOOL       ChangeMenu(HMENU,UINT,LPSTR,UINT,UINT);
+BOOL       ChangeMenu(HMENU,UINT,SEGPTR,UINT,UINT);
 WORD       ChangeSelector(WORD,WORD);
-void       CheckDlgButton(HWND,WORD,WORD);
-BOOL       CheckMenuItem(HMENU,UINT,UINT);
-void       CheckRadioButton(HWND,WORD,WORD,WORD);
+BOOL       CheckDlgButton(HWND,INT,UINT);
+INT        CheckMenuItem(HMENU,UINT,UINT);
+BOOL       CheckRadioButton(HWND,UINT,UINT,UINT);
 HWND       ChildWindowFromPoint(HWND,POINT);
 BOOL       Chord(HDC,INT,INT,INT,INT,INT,INT,INT,INT);
 int        ClearCommBreak(int);
-void       ClientToScreen(HWND,LPPOINT);
-void       ClipCursor(LPRECT);
+BOOL       ClientToScreen(HWND,LPPOINT);
+BOOL       ClipCursor(LPRECT);
 BOOL       CloseClipboard(void);
 int        CloseComm(int);
-HMETAFILE  CloseMetaFile(HANDLE);
+HMETAFILE  CloseMetaFile(HDC);
 void       CloseSound(void);
-void       CloseWindow(HWND);
-int        CombineRgn(HRGN,HRGN,HRGN,short);
+BOOL       CloseWindow(HWND);
+INT        CombineRgn(HRGN,HRGN,HRGN,INT);
 int        ConvertRequest(HWND,LPKANJISTRUCT);
-HANDLE     CopyMetaFile(HANDLE,LPSTR);
-void       CopyRect(LPRECT,LPRECT);
-int        CountClipboardFormats(void);
-int        CountVoiceNotes(int);
-HBITMAP    CreateBitmap(short,short,BYTE,BYTE,LPSTR);
-HBITMAP    CreateBitmapIndirect(BITMAP*);
-HBRUSH     CreateBrushIndirect(LOGBRUSH*);
-void       CreateCaret(HWND,HBITMAP,short,short);
-HBITMAP    CreateCompatibleBitmap(HDC,short,short);
+#ifdef WINELIB32
+HCURSOR    CopyCursor(HCURSOR); /* Win32 */
+HICON      CopyIcon(HICON); /* Win32 */
+#else
+HCURSOR    CopyCursor(HINSTANCE,HCURSOR); /* Win16 */
+HICON      CopyIcon(HINSTANCE,HICON); /* Win16 */
+#endif
+HMETAFILE  CopyMetaFile(HMETAFILE,LPCSTR);
+BOOL       CopyRect(LPRECT,LPRECT);
+INT        CountClipboardFormats(void);
+INT        CountVoiceNotes(INT);
+HBITMAP    CreateBitmap(INT,INT,UINT,UINT,LPVOID);
+HBITMAP    CreateBitmapIndirect(const BITMAP*);
+HBRUSH     CreateBrushIndirect(const LOGBRUSH*);
+BOOL       CreateCaret(HWND,HBITMAP,INT,INT);
+HBITMAP    CreateCompatibleBitmap(HDC,INT,INT);
 HDC        CreateCompatibleDC(HDC);
-HCURSOR    CreateCursor(HANDLE,INT,INT,INT,INT,LPSTR,LPSTR);
+HCURSOR    CreateCursor(HANDLE,INT,INT,INT,INT,LPVOID,LPVOID);
 HANDLE     CreateCursorIconIndirect(HANDLE,CURSORICONINFO*,LPSTR,LPSTR);
-HDC        CreateDC(LPSTR,LPSTR,LPSTR,LPSTR);
-HBRUSH     CreateDIBPatternBrush(HANDLE,WORD);
-HBITMAP    CreateDIBitmap(HDC,LPBITMAPINFOHEADER,DWORD,LPSTR,LPBITMAPINFO,WORD);
-HWND       CreateDialog(HANDLE,SEGPTR,HWND,WNDPROC);
-HWND       CreateDialogIndirect(HANDLE,SEGPTR,HWND,WNDPROC);
-HWND       CreateDialogIndirectParam(HANDLE,SEGPTR,HWND,WNDPROC,LPARAM);
-HWND       CreateDialogParam(HANDLE,SEGPTR,HWND,WNDPROC,LPARAM);
-HBITMAP    CreateDiscardableBitmap(HDC,short,short);
-HRGN       CreateEllipticRgn(short,short,short,short);
+HDC        CreateDC(LPCSTR,LPCSTR,LPCSTR,LPCSTR);
+HBRUSH     CreateDIBPatternBrush(HGLOBAL,UINT);
+HBITMAP    CreateDIBitmap(HDC,BITMAPINFOHEADER*,DWORD,LPVOID,BITMAPINFO*,UINT);
+HWND       CreateDialog(HANDLE,SEGPTR,HWND,DLGPROC);
+HWND       CreateDialogIndirect(HANDLE,SEGPTR,HWND,DLGPROC);
+HWND       CreateDialogIndirectParam(HANDLE,SEGPTR,HWND,DLGPROC,LPARAM);
+HWND       CreateDialogParam(HANDLE,SEGPTR,HWND,DLGPROC,LPARAM);
+HBITMAP    CreateDiscardableBitmap(HDC,INT,INT);
+HRGN       CreateEllipticRgn(INT,INT,INT,INT);
 HRGN       CreateEllipticRgnIndirect(LPRECT);
-HFONT      CreateFont(int,int,int,int,int,BYTE,BYTE,BYTE,BYTE,BYTE,BYTE,BYTE,BYTE,LPSTR);
-HFONT      CreateFontIndirect(LOGFONT*);
-HBRUSH     CreateHatchBrush(short,COLORREF);
+HFONT      CreateFont(INT,INT,INT,INT,INT,BYTE,BYTE,BYTE,BYTE,BYTE,BYTE,BYTE,BYTE,LPCSTR);
+HFONT      CreateFontIndirect(const LOGFONT*);
+HBRUSH     CreateHatchBrush(INT,COLORREF);
 HDC        CreateIC(LPSTR,LPSTR,LPSTR,LPSTR);
 HICON      CreateIcon(HANDLE,INT,INT,BYTE,BYTE,LPSTR,LPSTR);
 HMENU      CreateMenu(void);
 HANDLE     CreateMetaFile(LPSTR);
 HPALETTE   CreatePalette(LPLOGPALETTE);
 HBRUSH     CreatePatternBrush(HBITMAP);
-HPEN       CreatePen(short,short,COLORREF);
+HPEN       CreatePen(INT,INT,COLORREF);
 HPEN       CreatePenIndirect(LOGPEN*);
 HRGN       CreatePolyPolygonRgn(LPPOINT,LPINT,INT,INT);
 HRGN       CreatePolygonRgn(LPPOINT,INT,INT);
@@ -2667,7 +2704,7 @@
 void       DrawFocusRect(HDC,LPRECT);
 BOOL       DrawIcon(HDC,short,short,HICON);
 void       DrawMenuBar(HWND);
-int        DrawText(HDC,LPSTR,int,LPRECT,WORD);
+int        DrawText(HDC,LPCSTR,int,LPRECT,WORD);
 DWORD      DumpIcon(SEGPTR,WORD*,SEGPTR*,SEGPTR*);
 BOOL       Ellipse(HDC,INT,INT,INT,INT);
 BOOL       EmptyClipboard(void);
@@ -2680,6 +2717,7 @@
 void       EndPaint(HWND,LPPAINTSTRUCT);
 BOOL       EnumChildWindows(HWND,FARPROC,LONG);
 WORD       EnumClipboardFormats(WORD);
+int        EnumFontFamilies(HDC,LPSTR,FONTENUMPROC,LPARAM);
 int        EnumFonts(HDC,LPSTR,FARPROC,LPSTR);
 BOOL       EnumMetaFile(HDC,LOCALHANDLE,FARPROC,BYTE*);
 int        EnumObjects(HDC,int,FARPROC,LPARAM);
@@ -2696,13 +2734,16 @@
 BOOL       ExitWindows(DWORD,WORD);
 BOOL       ExtFloodFill(HDC,INT,INT,COLORREF,WORD);
 BOOL       ExtTextOut(HDC,short,short,WORD,LPRECT,LPSTR,WORD,LPINT);
+HICON      ExtractIcon(HINSTANCE,LPCSTR,UINT);
 WORD       FarGetOwner(HANDLE);
 void       FarSetOwner(HANDLE,WORD);
+void       FatalAppExit(UINT,LPCSTR);
 void       FatalExit(int);
 int        FillRect(HDC,LPRECT,HBRUSH);
 BOOL       FillRgn(HDC,HRGN,HBRUSH);
 void       FillWindow(HWND,HWND,HDC,HBRUSH);
 ATOM       FindAtom(SEGPTR);
+HINSTANCE  FindExecutable(LPCSTR,LPCSTR,LPSTR);
 HRSRC      FindResource(HINSTANCE,SEGPTR,SEGPTR);
 HWND       FindWindow(SEGPTR,LPSTR);
 BOOL       FlashWindow(HWND,BOOL);
@@ -2739,6 +2780,7 @@
 WORD       GetClassWord(HWND,short);
 void       GetClientRect(HWND,LPRECT);
 int        GetClipBox(HDC,LPRECT);
+void       GetClipCursor(LPRECT);
 HRGN       GetClipRgn(HDC);
 HANDLE     GetClipboardData(WORD);
 int        GetClipboardFormatName(WORD,LPSTR,short);
@@ -2782,12 +2824,13 @@
 int        GetInstanceData(HANDLE,WORD,int);
 WORD       GetInternalWindowPos(HWND,LPRECT,LPPOINT);
 int        GetKBCodePage(void);
+int        GetKerningPairs(HDC,int,LPKERNINGPAIR);
 int        GetKeyNameText(LONG,LPSTR,int);
 int        GetKeyState(int);
 void       GetKeyboardState(BYTE*);
 int        GetKeyboardType(int);
 HWND       GetLastActivePopup(HWND);
-VOID       GetLocalTime(LPSYSTEMTIME);     /* Win32 */
+VOID       GetLocalTime(LPSYSTEMTIME); /* Win32 */
 WORD       GetMapMode(HDC);
 HMENU      GetMenu(HWND);
 DWORD      GetMenuCheckMarkDimensions(void);
@@ -2818,12 +2861,14 @@
 DWORD      GetPixel(HDC,short,short);
 WORD       GetPolyFillMode(HDC);
 int        GetPriorityClipboardFormat(WORD*,short);
-WORD       GetPrivateProfileInt(LPCSTR,LPCSTR,short,LPCSTR);
-short      GetPrivateProfileString(LPCSTR,LPCSTR,LPCSTR,LPSTR,short,LPCSTR);
+UINT       GetPrivateProfileInt(LPCSTR,LPCSTR,INT,LPCSTR);
+INT        GetPrivateProfileString(LPCSTR,LPCSTR,LPCSTR,LPSTR,INT,LPCSTR);
 FARPROC    GetProcAddress(HANDLE,SEGPTR);
-WORD       GetProfileInt(LPCSTR,LPCSTR,int);
-int        GetProfileString(LPCSTR,LPCSTR,LPCSTR,LPSTR,int);
+UINT       GetProfileInt(LPCSTR,LPCSTR,INT);
+INT        GetProfileString(LPCSTR,LPCSTR,LPCSTR,LPSTR,INT);
 HANDLE     GetProp(HWND,SEGPTR);
+DWORD      GetQueueStatus(UINT);
+BOOL       GetRasterizerCaps(LPRASTERIZER_STATUS,UINT);
 WORD       GetROP2(HDC);
 WORD       GetRelAbs(HDC);
 int        GetRgnBox(HRGN,LPRECT);
@@ -2841,7 +2886,7 @@
 int        GetSystemMetrics(WORD);
 WORD       GetSystemPaletteEntries(HDC,WORD,WORD,LPPALETTEENTRY);
 WORD       GetSystemPaletteUse(HDC);
-VOID       GetSystemTime(LPSYSTEMTIME);    /* Win32 */
+VOID       GetSystemTime(LPSYSTEMTIME); /* Win32 */
 DWORD      GetTabbedTextExtent(HDC,LPSTR,int,int,LPINT);
 HINSTANCE  GetTaskDS(void);
 HGLOBAL    GetTaskQueue(HTASK);
@@ -2850,8 +2895,8 @@
 WORD       GetTextAlign(HDC);
 short      GetTextCharacterExtra(HDC);
 COLORREF   GetTextColor(HDC);
-DWORD      GetTextExtent(HDC,LPSTR,short);
-BOOL       GetTextExtentPoint(HDC,LPSTR,short,LPSIZE);
+DWORD      GetTextExtent(HDC,LPCSTR,short);
+BOOL       GetTextExtentPoint(HDC,LPCSTR,short,LPSIZE);
 INT        GetTextFace(HDC,INT,LPSTR);
 BOOL       GetTextMetrics(HDC,LPTEXTMETRIC);
 LPINT      GetThresholdEvent(void);
@@ -2883,9 +2928,7 @@
 UINT       GetWindowsDirectory(LPSTR,UINT);
 ATOM       GlobalAddAtom(SEGPTR);
 HGLOBAL    GlobalAlloc(WORD,DWORD);
-#ifndef WINELIB32 /* Obsolete in Win32 */
 DWORD      GlobalCompact(DWORD);
-#endif
 DWORD      GlobalDOSAlloc(DWORD);
 WORD       GlobalDOSFree(WORD);
 ATOM       GlobalDeleteAtom(ATOM);
@@ -2896,9 +2939,9 @@
 void       GlobalFreeAll(HANDLE);
 WORD       GlobalGetAtomName(ATOM,LPSTR,short);
 #ifdef WINELIB32
-HGLOBAL    GlobalHandle(LPCVOID);
+HGLOBAL    GlobalHandle(LPCVOID); /* Win32 */
 #else
-DWORD      GlobalHandle(UINT);
+DWORD      GlobalHandle(UINT); /* Win16 */
 #endif
 HGLOBAL    GlobalLRUNewest(HGLOBAL);
 HGLOBAL    GlobalLRUOldest(HGLOBAL);
@@ -2919,7 +2962,7 @@
 void       InflateRect(LPRECT,short,short);
 WORD       InitAtomTable(WORD);
 HRGN       InquireVisRgn(HDC);
-BOOL       InsertMenu(HMENU,UINT,UINT,UINT,LPSTR);
+BOOL       InsertMenu(HMENU,UINT,UINT,UINT,SEGPTR);
 int        IntersectClipRect(HDC,short,short,short,short);
 BOOL       IntersectRect(LPRECT,LPRECT,LPRECT);
 int        IntersectVisRect(HDC,short,short,short,short);
@@ -2941,10 +2984,12 @@
 BOOL       IsClipboardFormatAvailable(WORD);
 BOOL       IsDialogMessage(HWND,LPMSG);
 WORD       IsDlgButtonChecked(HWND,WORD);
+BOOL       IsGDIObject(HANDLE);
 BOOL       IsIconic(HWND);
+BOOL       IsMenu(HMENU);
 BOOL       IsRectEmpty(LPRECT);
+BOOL       IsTask(HTASK);
 HTASK      IsTaskLocked(void);
-BOOL       IsTwoByteCharPrefix(char);
 BOOL       IsWindow(HWND);
 BOOL       IsWindowEnabled(HWND);
 BOOL       IsWindowVisible(HWND);
@@ -2961,14 +3006,12 @@
 HICON      LoadIcon(HANDLE,SEGPTR);
 HANDLE     LoadLibrary(LPCSTR);
 HMENU      LoadMenu(HANDLE,SEGPTR);
-HMENU      LoadMenuIndirect(LPSTR);
+HMENU      LoadMenuIndirect(SEGPTR);
 HANDLE     LoadModule(LPCSTR,LPVOID);
 HGLOBAL    LoadResource(HINSTANCE,HRSRC);
 int        LoadString(HANDLE,WORD,LPSTR,int);
 HANDLE     LocalAlloc(WORD,WORD);
-#ifndef WINELIB32 /* Obsolete in Win32 */
 UINT       LocalCompact(WORD);
-#endif
 UINT       LocalFlags(HLOCAL);
 HANDLE     LocalFree(HANDLE);
 HANDLE     LocalHandle(WORD);
@@ -2976,9 +3019,7 @@
 NPVOID     LocalLock(HLOCAL);
 FARPROC    LocalNotify(FARPROC);
 HANDLE     LocalReAlloc(HANDLE,WORD,WORD);
-#ifndef WINELIB32 /* Obsolete in Win32 */
 UINT       LocalShrink(HANDLE,WORD);
-#endif
 UINT       LocalSize(HLOCAL);
 BOOL       LocalUnlock(HANDLE);
 LPVOID     LockResource(HGLOBAL);
@@ -2989,12 +3030,12 @@
 WORD       MapVirtualKey(WORD,WORD);
 void       MapWindowPoints(HWND,HWND,LPPOINT,WORD);
 void       MessageBeep(WORD);
-int        MessageBox(HWND,LPSTR,LPSTR,WORD);
-BOOL       ModifyMenu(HMENU,UINT,UINT,UINT,LPSTR);
+int        MessageBox(HWND,LPCSTR,LPCSTR,WORD);
+BOOL       ModifyMenu(HMENU,UINT,UINT,UINT,SEGPTR);
 DWORD      MoveTo(HDC,short,short);
 BOOL       MoveToEx(HDC,short,short,LPPOINT);
 BOOL       MoveWindow(HWND,short,short,short,short,BOOL);
-int        MulDiv(int,int,int);
+INT        MulDiv(INT,INT,INT);
 DWORD      OemKeyScan(WORD);
 BOOL       OemToAnsi(LPSTR,LPSTR);
 void       OemToAnsiBuff(LPSTR,LPSTR,INT);
@@ -3006,7 +3047,7 @@
 DWORD      OffsetWindowOrg(HDC,short,short);
 BOOL       OffsetWindowOrgEx(HDC,short,short,LPPOINT);
 BOOL       OpenClipboard(HWND);
-int        OpenComm(LPSTR,UINT,UINT);
+int        OpenComm(LPCSTR,UINT,UINT);
 HFILE      OpenFile(LPCSTR,OFSTRUCT*,UINT);
 BOOL       OpenIcon(HWND);
 int        OpenSound(void);
@@ -3043,6 +3084,13 @@
 BOOL       RectVisible(HDC,LPRECT);
 BOOL       Rectangle(HDC,INT,INT,INT,INT);
 BOOL       RedrawWindow(HWND,LPRECT,HRGN,UINT);
+LONG       RegCloseKey(HKEY);
+LONG       RegCreateKey(HKEY,LPCSTR,LPHKEY);
+LONG       RegDeleteKey(HKEY,LPCSTR);
+LONG       RegEnumKey(HKEY,DWORD,LPSTR,DWORD);
+LONG       RegOpenKey(HKEY,LPCSTR,LPHKEY);
+LONG       RegQueryValue(HKEY,LPCSTR,LPSTR,LPLONG);
+LONG       RegSetValue(HKEY,LPCSTR,DWORD,LPCSTR,DWORD);
 ATOM       RegisterClass(LPWNDCLASS);
 WORD       RegisterClipboardFormat(LPCSTR);
 WORD       RegisterWindowMessage(SEGPTR);
@@ -3052,6 +3100,7 @@
 BOOL       RemoveMenu(HMENU,UINT,UINT);
 HANDLE     RemoveProp(HWND,SEGPTR);
 void       ReplyMessage(LONG);
+HDC        ResetDC(HDC,LPVOID);
 BOOL       ResizePalette(HPALETTE,UINT);
 BOOL       RestoreDC(HDC,short);
 int        RestoreVisRgn(HDC);
@@ -3161,17 +3210,18 @@
 BOOL       SetWindowOrgEx(HDC,short,short,LPPOINT);
 BOOL       SetWindowPlacement(HWND,LPWINDOWPLACEMENT);
 BOOL       SetWindowPos(HWND,HWND,INT,INT,INT,INT,WORD);
-void       SetWindowText(HWND,LPSTR);
+void       SetWindowText(HWND,LPCSTR);
 WORD       SetWindowWord(HWND,short,WORD);
 FARPROC    SetWindowsHook(short,FARPROC);
 HHOOK      SetWindowsHookEx(short,HOOKPROC,HINSTANCE,HTASK);
+HINSTANCE  ShellExecute(HWND,LPCSTR,LPCSTR,LPSTR,LPCSTR,INT);
 void       ShowCaret(HWND);
 int        ShowCursor(BOOL);
 void       ShowOwnedPopups(HWND,BOOL);
 void       ShowScrollBar(HWND,WORD,BOOL);
 BOOL       ShowWindow(HWND,int);
 DWORD      SizeofResource(HINSTANCE,HRSRC);
-VOID       Sleep(DWORD);      /* Win32 */
+VOID       Sleep(DWORD); /* Win32 */
 int        StartSound(void);
 int        StopSound(void);
 BOOL       StretchBlt(HDC,short,short,short,short,HDC,short,short,short,short,DWORD);
@@ -3182,6 +3232,7 @@
 void       SwitchStackBack(void);
 void       SwitchStackTo(WORD,WORD,WORD);
 int        SyncAllVoices(void);
+BOOL       SystemParametersInfo(UINT,UINT,LPVOID,UINT);
 LONG       TabbedTextOut(HDC,short,short,LPSTR,short,short,LPINT,short);
 BOOL       TextOut(HDC,short,short,LPSTR,short);
 int        Throw(LPCATCHBUF,int);
@@ -3214,8 +3265,9 @@
 BOOL       WinHelp(HWND,LPSTR,WORD,DWORD);
 HWND       WindowFromPoint(POINT);
 int        WriteComm(int,LPSTR,int);
-BOOL       WritePrivateProfileString(LPSTR,LPSTR,LPSTR,LPSTR);
-BOOL       WriteProfileString(LPSTR,LPSTR,LPSTR);
+void       WriteOutProfiles(void);
+BOOL       WritePrivateProfileString(LPCSTR,LPCSTR,LPCSTR,LPCSTR);
+BOOL       WriteProfileString(LPCSTR,LPCSTR,LPCSTR);
 void       Yield(void);
 LONG       _hread(HFILE,LPSTR,LONG);
 LONG       _hwrite(HFILE,LPCSTR,LONG);
@@ -3225,13 +3277,15 @@
 HFILE      _lopen(LPCSTR,INT);
 INT        _lread(HFILE,LPSTR,WORD);
 INT        _lwrite(HFILE,LPCSTR,WORD);
+void       hmemcpy(LPVOID,LPCVOID,LONG);
 SEGPTR     lstrcat(SEGPTR,SEGPTR);
 INT        lstrcmp(LPCSTR,LPCSTR);
 INT        lstrcmpi(LPCSTR,LPCSTR);
 INT        lstrncmpi(LPCSTR,LPCSTR,int);
 SEGPTR     lstrcpy(SEGPTR,SEGPTR);
-char *     lstrcpyn(char *,const char *,int);
+LPSTR      lstrcpyn(LPSTR,LPCSTR,int);
 INT        lstrlen(LPCSTR);
+int        wsprintf(LPSTR,LPSTR,...);
 int        wvsprintf(LPSTR,LPSTR,LPSTR);
 
 #ifdef WINELIB
diff --git a/include/wine.h b/include/wine.h
index 8feab54..e8b4cfa 100644
--- a/include/wine.h
+++ b/include/wine.h
@@ -1,10 +1,6 @@
 #ifndef  __WINE_WINE_H
 #define  __WINE_WINE_H
 
-extern char *WineIniFileName(void);
-
-#define WINE_INI WineIniFileName()
-
 #ifdef i386
 extern int runtime_cpu (void);
 #else
diff --git a/include/wintypes.h b/include/wintypes.h
index f0cc840..30da778 100644
--- a/include/wintypes.h
+++ b/include/wintypes.h
@@ -24,6 +24,10 @@
 typedef unsigned short BOOL;
 typedef unsigned char BYTE;
 typedef long LONG;
+typedef unsigned char CHAR;
+/* Some systems might have wchar_t, but we really need 16 bit characters */
+typedef unsigned short WCHAR;
+
 #ifdef WINELIB32
 typedef int INT;
 typedef unsigned int UINT;
@@ -53,6 +57,8 @@
 typedef char *LPSTR;
 typedef const char *LPCSTR;
 typedef LPCSTR LPCTSTR;
+typedef WCHAR *LPWSTR;
+typedef const WCHAR *LPCWSTR;
 typedef char *NPSTR;
 typedef INT *LPINT;
 typedef UINT *LPUINT;
@@ -90,7 +96,12 @@
 DECLARE_HANDLE(HTASK);
 DECLARE_HANDLE(HWND);
 DECLARE_HANDLE(LOCALHANDLE);
-
+#ifdef WINELIB32
+DECLARE_HANDLE(HKEY);
+#else
+typedef DWORD HKEY;
+#endif
+typedef HKEY* LPHKEY;
 typedef HGLOBAL GLOBALHANDLE;
 
 #ifdef WINELIB
@@ -101,6 +112,7 @@
 typedef SEGPTR WNDPROC;
 #endif
 typedef FARPROC DLGPROC;
+typedef FARPROC FONTENUMPROC;
 typedef FARPROC HOOKPROC;
 
 #define TRUE 1
@@ -108,6 +120,7 @@
 #define CW_USEDEFAULT ((INT)0x8000)
 #define FAR
 #define NEAR
+#define _near
 #define PASCAL
 #define VOID                void
 #define WINAPI              PASCAL
diff --git a/ipc/shm_fragment_test.c b/ipc/shm_fragment_test.c
index 708dad4..c27061b 100644
--- a/ipc/shm_fragment_test.c
+++ b/ipc/shm_fragment_test.c
@@ -81,7 +81,7 @@
 	   fprintf(stddeb, "NULL\n");
 	else {
 	   fprintf(stddeb, "0x%06x\n", (int)ret-(int)block);
-	   bzero (ret,size);	   /* test boundaries */
+	   memset( ret,0, size );  /* test boundaries */
 	}
      } else {			   /* free */
 	/* free shm fragment */
diff --git a/library/heap.c b/library/heap.c
index 6148c53..c27389b 100644
--- a/library/heap.c
+++ b/library/heap.c
@@ -82,8 +82,7 @@
     if ((m = malloc (bytes)))
     {
 	*slot = m;
-	if (flags & LMEM_ZEROINIT)
-	    bzero (m, bytes);
+	if (flags & LMEM_ZEROINIT) memset( m, 0, bytes );
 
 #ifdef DEBUG_HEAP
 	printf ("Handle %d [%d] = %p\n", hMem+1, bytes, m);
@@ -220,8 +219,7 @@
     bytes+=sizeof(HeapData);
     if ((m = malloc (bytes)))
     {
-	if (flags & LMEM_ZEROINIT)
-	    bzero (m, bytes);
+	if (flags & LMEM_ZEROINIT) memset( m, 0, bytes );
     }
     m->Size=bytes-sizeof(HeapData);
     return m+1;
@@ -253,7 +251,7 @@
   }
   m=realloc (m-1, bytes+sizeof(HeapData));
   if(flags & LMEM_ZEROINIT && bytes > m->Size)
-    bzero ((char*)m+sizeof(HeapData)+m->Size, bytes-m->Size);
+    memset( (char*)m+sizeof(HeapData)+m->Size, 0, bytes-m->Size );
   m->Size=bytes;
   return m+1;
 }
diff --git a/library/libres.c b/library/libres.c
index 0d1511e..15a3434 100644
--- a/library/libres.c
+++ b/library/libres.c
@@ -68,7 +68,7 @@
     for(Res=ResBlock->Resources; *Res; Res++)
       if(name)
       {
-	if((*Res)->type==typeid && !strcmp((*Res)->name,name))
+	if((*Res)->type==typeid && !lstrcmpi((*Res)->name,name))
 	  return (HRSRC)*Res;
       }
       else
diff --git a/library/winestub.c b/library/winestub.c
new file mode 100644
index 0000000..2f5e722
--- /dev/null
+++ b/library/winestub.c
@@ -0,0 +1,52 @@
+/* Sample winestub.c file for compiling programs with libwine.so. */
+
+#include "windows.h"
+#include "wine.h"
+#ifdef WIN_DEBUG
+#include <stdio.h>
+#endif
+
+extern int PASCAL WinMain(HINSTANCE,HINSTANCE,LPSTR,int);
+/* This is the renamed main() subroutine in misc/main.c. */
+/* Note that the libdll `init()' won't work: */
+extern HINSTANCE _wine_main(int, char *[]);
+
+int main (int argc, char *argv [])
+{
+  HINSTANCE hInstance;
+  char szCmdParam[256] = {0};
+  int index, buffer_pos;
+  char *arg_holder;
+  /* "Wired-in" command-line options for Wine: */
+  /*char *wine_argv[] = {argv[0], "-managed", "-dll", "+commdlg",
+  			"-dll", "+shell", ""};*/
+  char *wine_argv[] = {argv[0], ""};
+
+  /* Initialize the library dll: */
+  hInstance = (HINSTANCE)_wine_main((sizeof(wine_argv)/sizeof(char *))-1, wine_argv);
+
+#ifdef WIN_DEBUG
+  fprintf(stderr,"In winestub, reporting hInstance = %d\n", hInstance);
+#endif
+
+  /* Move things from argv to the szCmdParam that WinMain expects: */
+    for (index = 1, buffer_pos = 0;
+  	(index < argc) && (buffer_pos < 255);
+  	index++, buffer_pos++)
+  	{
+	for (arg_holder = argv[index]; ; buffer_pos++, arg_holder++)
+	 if ((szCmdParam[buffer_pos] = *arg_holder) == '\0') break;
+	szCmdParam[buffer_pos] = ' ';
+	};
+  szCmdParam[buffer_pos] = '\0';
+
+#ifdef WIN_DEBUG
+  fprintf(stderr,"In winestub, Program Name: %s, Parameters: %s\n",
+  	progname, szCmdParam);
+#endif
+
+  return WinMain (hInstance,		/* hInstance */
+		  0,			/* hPrevInstance */
+		  (LPSTR)szCmdParam,	/* lpszCmdParam */
+		  SW_NORMAL);		/* nCmdShow */
+}
diff --git a/library/winmain.c b/library/winmain.c
index f132725..b94554e 100644
--- a/library/winmain.c
+++ b/library/winmain.c
@@ -11,13 +11,11 @@
 extern void TASK_Reschedule(void);
 extern int USER_InitApp(HINSTANCE);
 
-char* progname=NULL;
 
 int _WinMain (int argc, char *argv [])
 {
   HINSTANCE hInstance;
 
-  progname=*argv;
   if(!MAIN_Init()) return 0; /* JBP: Needed for DosDrives[] structure, etc. */
   hInstance = WinExec( *argv, SW_SHOWNORMAL );
   TASK_Reschedule();
@@ -26,8 +24,12 @@
   if (!WIDGETS_Init()) return -1;
   if (!WIN_CreateDesktopWindow()) return -1;
 
+#ifdef WINELIBDLL
+  return (int)hInstance;
+#else
   return WinMain (hInstance,    /* hInstance */
 		  0,	        /* hPrevInstance */
 		  "",	        /* lpszCmdParam */
 		  SW_NORMAL);   /* nCmdShow */
+#endif
 }
diff --git a/loader/main.c b/loader/main.c
index 8ee5a4e..e1bcee8 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -51,6 +51,9 @@
 
     int queueSize;
 
+    /* Load the configuration file */
+    if (!PROFILE_LoadWineIni()) return 0;
+
     SpyInit();
 
 #ifndef WINELIB
@@ -89,7 +92,7 @@
 
 #ifndef WINELIB    
       /* Initialize the DOS memory */
-    INT21_Init();
+    if (!INT21_Init()) return 0;
 
       /* Create USER heap */
     if (!USER_HeapInit()) return 0;
diff --git a/loader/module.c b/loader/module.c
index 5c9557a..e97c806 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -954,14 +954,16 @@
           /* Create the module structure */
 
         hModule = MODULE_LoadExeHeader( fd, &ofs );
-        if (hModule == 21) hModule = PE_LoadModule( fd, &ofs, paramBlock );
-        close( fd );
         if (hModule < 32)
         {
-            fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
-                     name, hModule );
+            if (hModule == 21) hModule = PE_LoadModule( fd, &ofs, paramBlock );
+            close(fd);
+            if (hModule < 32)
+                fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
+                         name, hModule );
             return hModule;
         }
+        close( fd );
         pModule = (NE_MODULE *)GlobalLock( hModule );
 
           /* Allocate the segments for this module */
diff --git a/loader/ne_image.c b/loader/ne_image.c
index 80eea87..da9675d 100644
--- a/loader/ne_image.c
+++ b/loader/ne_image.c
@@ -320,7 +320,8 @@
 		if(additive && offset)
         	fprintf(stderr,"Additive selector to %4.4x.Please report\n",offset);
 	    } 
-	    while (offset != 0xffff && !additive);
+            /* FIXME: Quicken 5 has a zero offset fixup.  This seems to work */
+	    while (offset && offset != 0xffff && !additive);
 	    break;
 	    
 	  default:
diff --git a/loader/pe_image.c b/loader/pe_image.c
index f7f3f72..3d749c1 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -38,7 +38,9 @@
 void my_wcstombs(char * result, u_short * source, int len)
 {
   while(len--) {
-    if(isascii(*source)) *result++ = *source++;
+    /* this used to be isascii, but see isascii implementation in Linux'
+	   ctype.h */
+    if(*source<255) *result++ = *source++;
     else {
       printf("Unable to handle unicode right now\n");
       exit(0);
@@ -206,7 +208,7 @@
 	  }
 	  dprintf_win32(stddeb, "--- %s %s.%d\n", pe_name->Name, Module, pe_name->Hint);
 #ifndef WINELIB /* FIXME: JBP: Should this happen in libwine.a? */
-	/* Both calls should be unified into GetProcAddress */
+	/* FIXME: Both calls should be unified into GetProcAddress */
 	  *thunk_list=(unsigned int)RELAY32_GetEntryPoint(Module,pe_name->Name,pe_name->Hint);
 	  if(*thunk_list == 0)
 	  	*thunk_list = WIN32_GetProcAddress(MODULE_FindModule(Module),
@@ -236,7 +238,11 @@
         }
         dprintf_win32(stddeb, "--- %s %s.%d\n", pe_name->Name, Module, pe_name->Hint);
 #ifndef WINELIB /* FIXME: JBP: Should this happen in libwine.a? */
+	/* FIXME: Both calls should be unified into GetProcAddress */
         *thunk_list=(unsigned int)RELAY32_GetEntryPoint(Module,pe_name->Name,pe_name->Hint);
+	if(*thunk_list == 0)
+	  	*thunk_list = WIN32_GetProcAddress(MODULE_FindModule(Module),
+				pe_name->Name);
 #else
         fprintf(stderr,"JBP: Call to RELAY32_GetEntryPoint being ignored.\n");
 #endif
@@ -346,6 +352,7 @@
 {
 	int i, result;
     unsigned int load_addr;
+	struct Directory dir;
 
 	wpnt->pe = xmalloc(sizeof(struct pe_data));
 	memset(wpnt->pe,0,sizeof(struct pe_data));
@@ -426,17 +433,89 @@
 
 	if(strcmp(wpnt->pe->pe_seg[i].Name, ".rsrc") == 0) {
 	    wpnt->pe->pe_resource = (struct PE_Resource_Directory *) result;
-
+#if 0
+/* FIXME pe->resource_offset should be deleted from structure if this
+ ifdef doesn't break anything */
 	    /* save offset for PE_FindResource */
 	    wpnt->pe->resource_offset = wpnt->pe->pe_seg[i].Virtual_Address - 
 					wpnt->pe->pe_seg[i].PointerToRawData;
+#endif	
 	    }
-	
 	if(strcmp(wpnt->pe->pe_seg[i].Name, ".reloc") == 0)
 		wpnt->pe->pe_reloc = (struct PE_Reloc_Block *) result;
 
 	}
 
+	/* There is word that the actual loader does not care about the
+	   section names, and only goes for the DataDirectory */
+	dir=wpnt->pe->pe_header->opt_coff.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
+	if(dir.Size)
+	{
+		if(wpnt->pe->pe_export && 
+			wpnt->pe->pe_export!=load_addr+dir.Virtual_address)
+			fprintf(stderr,"wrong export directory??\n");
+		else
+			wpnt->pe->pe_export = load_addr+dir.Virtual_address;
+	}
+
+	dir=wpnt->pe->pe_header->opt_coff.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY];
+	if(dir.Size)
+	{
+		if(wpnt->pe->pe_import && 
+			wpnt->pe->pe_import!=load_addr+dir.Virtual_address)
+			fprintf(stderr,"wrong export directory??\n");
+		else
+			wpnt->pe->pe_import = load_addr+dir.Virtual_address;
+	}
+
+	dir=wpnt->pe->pe_header->opt_coff.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY];
+	if(dir.Size)
+	{
+		if(wpnt->pe->pe_resource && 
+			wpnt->pe->pe_resource!=load_addr+dir.Virtual_address)
+			fprintf(stderr,"wrong resource directory??\n");
+		else
+			wpnt->pe->pe_resource = load_addr+dir.Virtual_address;
+	}
+
+	dir=wpnt->pe->pe_header->opt_coff.DataDirectory[IMAGE_FILE_BASE_RELOCATION_TABLE];
+	if(dir.Size)
+	{
+		if(wpnt->pe->pe_reloc && 
+			wpnt->pe->pe_reloc!=load_addr+dir.Virtual_address)
+			fprintf(stderr,"wrong export directory??\n");
+		else
+			wpnt->pe->pe_reloc = load_addr+dir.Virtual_address;
+	}
+
+	if(wpnt->pe->pe_header->opt_coff.DataDirectory
+		[IMAGE_FILE_EXCEPTION_DIRECTORY].Size)
+		dprintf_win32(stdnimp,"Exception directory ignored\n");
+
+	if(wpnt->pe->pe_header->opt_coff.DataDirectory
+		[IMAGE_FILE_SECURITY_DIRECTORY].Size)
+		dprintf_win32(stdnimp,"Security directory ignored\n");
+
+	if(wpnt->pe->pe_header->opt_coff.DataDirectory
+		[IMAGE_FILE_DEBUG_DIRECTORY].Size)
+		dprintf_win32(stdnimp,"Debug directory ignored\n");
+
+	if(wpnt->pe->pe_header->opt_coff.DataDirectory
+		[IMAGE_FILE_DESCRIPTION_STRING].Size)
+		dprintf_win32(stdnimp,"Description string ignored\n");
+
+	if(wpnt->pe->pe_header->opt_coff.DataDirectory
+		[IMAGE_FILE_MACHINE_VALUE].Size)
+		dprintf_win32(stdnimp,"Machine Value ignored\n");
+
+	if(wpnt->pe->pe_header->opt_coff.DataDirectory
+		[IMAGE_FILE_THREAD_LOCAL_STORAGE].Size)
+		 dprintf_win32(stdnimp,"Thread local storage ignored\n");
+
+	if(wpnt->pe->pe_header->opt_coff.DataDirectory
+		[IMAGE_FILE_CALLBACK_DIRECTORY].Size)
+		dprintf_win32(stdnimp,"Callback directory ignored\n");
+
 
 	if(wpnt->pe->pe_import) fixup_imports(wpnt);
 	if(wpnt->pe->pe_export) dump_exports(wpnt->pe->pe_export,load_addr);
diff --git a/loader/signal.c b/loader/signal.c
index 1968046..adc2c64 100644
--- a/loader/signal.c
+++ b/loader/signal.c
@@ -68,6 +68,17 @@
         fprintf( stderr,"In win_fault %x:%lx\n",
                  CS_reg(context), EIP_reg(context) );
     }
+
+      /* If SIGTRAP not caused by breakpoint or single step 
+         don't jump into the debugger */
+    if ((signal == SIGTRAP) && !(EFL_reg(context) & STEP_FLAG))
+    {
+        DBG_ADDR addr;
+        addr.seg = CS_reg(context);
+        addr.off = EIP_reg(context) - 1;
+        if (DEBUG_FindBreakpoint(&addr) == -1) return;
+    }
+
     XUngrabPointer(display, CurrentTime);
     XUngrabServer(display);
     XFlush(display);
diff --git a/loader/task.c b/loader/task.c
index 5e45faf..08d730c 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -77,7 +77,7 @@
 {
     static const char program_name[] = "KRNL386.EXE";
     char **e, *p;
-    int initial_size, size, i, winpathlen, windirlen, sysdirlen;
+    int initial_size, size, i, winpathlen, sysdirlen;
     HANDLE handle;
 
     extern char **environ;
@@ -88,7 +88,6 @@
      * ...
      * ASCIIZ   string n
      * ASCIIZ   PATH=xxx
-     * ASCIIZ   windir=xxx
      * BYTE     0
      * WORD     1
      * ASCIIZ   program name (e.g. C:\WINDOWS\SYSTEM\KRNL386.EXE)
@@ -103,10 +102,8 @@
         winpathlen += len + 1;
     }
     if (!winpathlen) winpathlen = 1;
-    windirlen  = GetWindowsDirectory( NULL, 0 ) + 1;
     sysdirlen  = GetSystemDirectory( NULL, 0 ) + 1;
     initial_size = 5 + winpathlen +           /* PATH=xxxx */
-                   7 + windirlen +            /* windir=xxxx */
                    1 +                        /* BYTE 0 at end */
                    sizeof(WORD) +             /* WORD 1 */
                    sysdirlen +                /* program directory */
@@ -148,7 +145,7 @@
 	}
     }
 
-    /* Now add the path and Windows directory */
+    /* Now add the path */
 
     strcpy( p, "PATH=" );
     for (i = 0, p += 5; ; i++)
@@ -160,10 +157,6 @@
     if (p[-1] == ';') p[-1] = '\0';
     else p++;
 
-    strcpy( p, "windir=" );
-    GetWindowsDirectory( p + 7, windirlen );
-    p += 7 + windirlen;
-
     /* Now add the program name */
 
     *p++ = '\0';
@@ -575,34 +568,36 @@
 static void TASK_DeleteTask( HTASK hTask )
 {
     TDB *pTask;
+    HANDLE hPDB;
 
     if (!(pTask = (TDB *)GlobalLock( hTask ))) return;
+    hPDB = pTask->hPDB;
+
+    /* Free the task module */
+
+    FreeModule( pTask->hModule );
 
     /* Close all open files of this task */
 
     FILE_CloseAllFiles( pTask->hPDB );
 
-      /* Free the task module */
-
-    FreeModule( pTask->hModule );
-
-      /* Free all memory used by this task (including the 32-bit stack, */
-      /* the environment block and the thunk segments). */
-
-    GlobalFreeAll( pTask->hPDB );
-
-      /* Free message queue */
+    /* Free the message queue */
 
     MSG_DeleteMsgQueue( pTask->hQueue );
 
-      /* Free the selector aliases */
+    /* Free the selector aliases */
 
     GLOBAL_FreeBlock( pTask->hCSAlias );
     GLOBAL_FreeBlock( pTask->hPDB );
 
-      /* Free the task structure itself */
+    /* Free the task structure itself */
 
     GlobalFree( hTask );
+
+    /* Free all memory used by this task (including the 32-bit stack, */
+    /* the environment block and the thunk segments). */
+
+    GlobalFreeAll( hPDB );
 }
 
 
@@ -626,7 +621,7 @@
     if (nTaskCount <= 1)
     {
         dprintf_task( stddeb, "Killing the last task, exiting\n" );
-        exit(0);
+        ExitWindows( 0, 0 );
     }
 
     /* Remove the task from the list to be sure we never switch back to it */
@@ -792,13 +787,13 @@
     ESI_reg(&context) = (DWORD)pTask->hPrevInstance;
     EDI_reg(&context) = (DWORD)pTask->hInstance;
     ES_reg (&context) = (WORD)pTask->hPDB;
-#endif
 
     /* Initialize the local heap */
     if ( pModule->heap_size )
     {
         LocalInit( pTask->hInstance, 0, pModule->heap_size );
     }    
+#endif
 
 
     /* Initialize the INSTANCEDATA structure */
diff --git a/memory/global.c b/memory/global.c
index 680e9fb..4b5c4e6 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -22,7 +22,7 @@
   /* Global arena block */
 typedef struct
 {
-    DWORD    base;           /* Base address  */
+    DWORD    base;           /* Base address (0 if discarded) */
     DWORD    size;           /* Size in bytes (0 indicates a free block) */
     HGLOBAL  handle;         /* Handle for this block */
     HGLOBAL  hOwner;         /* Owner of this block */
@@ -30,7 +30,9 @@
     BYTE     pageLockCount;  /* Count of GlobalPageLock() calls */
     BYTE     flags;          /* Allocation flags */
     BYTE     selCount;       /* Number of selectors allocated for this block */
+#ifdef CONFIG_IPC
     int      shmid;
+#endif
 } GLOBALARENA;
 
   /* Flags definitions */
@@ -116,6 +118,8 @@
 
     pArena->base = (DWORD)ptr;
     pArena->size = GET_SEL_LIMIT(sel) + 1;
+
+#ifdef CONFIG_IPC
     if ((flags & GMEM_DDESHARE) && Options.ipc)
     {
 	pArena->handle = shmdata->handle;
@@ -127,6 +131,9 @@
 	pArena->handle = (flags & GMEM_MOVEABLE) ? sel - 1 : sel;
 	pArena->shmid  = 0;
     }
+#else
+    pArena->handle = (flags & GMEM_MOVEABLE) ? sel - 1 : sel;
+#endif
     pArena->hOwner = hOwner;
     pArena->lockCount = 0;
     pArena->pageLockCount = 0;
@@ -174,11 +181,15 @@
 
     dprintf_global( stddeb, "GlobalAlloc: %ld flags=%04x\n", size, flags );
 
-      /* Fixup the size */
+    /* If size is 0, create a discarded block */
+
+    if (size == 0) return GLOBAL_CreateBlock( flags, NULL, 1, hOwner, isCode,
+                                              is32Bit, isReadOnly, NULL );
+
+    /* Fixup the size */
 
     if (size >= GLOBAL_MAX_ALLOC_SIZE - 0x1f) return 0;
-    if (size == 0) size = 0x20;
-    else size = (size + 0x1f) & ~0x1f;
+    size = (size + 0x1f) & ~0x1f;
 
       /* Allocate the linear memory */
 
@@ -770,7 +781,7 @@
 
     if ((meminfo = fopen("/proc/meminfo", "r")) < 0) {
         perror("wine: open");
-        exit(1);
+        return FALSE;
     }
 
     fgets(buf, 80, meminfo); /* read first line */
@@ -782,18 +793,20 @@
     }
 
     fprintf(stderr,"MemManInfo called with dwSize = %ld\n",pInfo->dwSize);
-    pInfo->wPageSize = getpagesize();
-    pInfo->dwLargestFreeBlock = availmem;
-    pInfo->dwTotalLinearSpace = totalmem / pInfo->wPageSize;
-    pInfo->dwMaxPagesAvailable = pInfo->dwLargestFreeBlock / pInfo->wPageSize;
-    pInfo->dwMaxPagesLockable = pInfo->dwMaxPagesLockable;
-    /* FIXME: the next three are not quite correct */
-    pInfo->dwTotalUnlockedPages = pInfo->dwMaxPagesAvailable;
-    pInfo->dwFreePages = pInfo->dwMaxPagesAvailable;
-    pInfo->dwTotalPages = pInfo->dwMaxPagesAvailable;
-    /* FIXME: the three above are not quite correct */
-    pInfo->dwFreeLinearSpace = pInfo->dwMaxPagesAvailable;
-    pInfo->dwSwapFilePages = 0L;
+    if (pInfo->dwSize) {
+        pInfo->wPageSize = getpagesize();
+        pInfo->dwLargestFreeBlock = availmem;
+        pInfo->dwTotalLinearSpace = totalmem / pInfo->wPageSize;
+        pInfo->dwMaxPagesAvailable = pInfo->dwLargestFreeBlock / pInfo->wPageSize;
+        pInfo->dwMaxPagesLockable = pInfo->dwMaxPagesLockable;
+        /* FIXME: the next three are not quite correct */
+        pInfo->dwTotalUnlockedPages = pInfo->dwMaxPagesAvailable;
+        pInfo->dwFreePages = pInfo->dwMaxPagesAvailable;
+        pInfo->dwTotalPages = pInfo->dwMaxPagesAvailable;
+        /* FIXME: the three above are not quite correct */
+        pInfo->dwFreeLinearSpace = pInfo->dwMaxPagesAvailable;
+        pInfo->dwSwapFilePages = 0L;
+    }
     return TRUE;
 #else
     return TRUE;
diff --git a/memory/local.c b/memory/local.c
index e20bd9c..d1235a3 100644
--- a/memory/local.c
+++ b/memory/local.c
@@ -107,7 +107,9 @@
     LOCALHEAPINFO *pInfo;
     INSTANCEDATA *ptr = (INSTANCEDATA *)PTR_SEG_OFF_TO_LIN( ds, 0 );
     dprintf_local( stddeb, "Heap at %p, %04x\n", ptr, ptr->heap );
-    if (!ptr->heap) return 0;
+    if (!ptr->heap) return NULL;
+    if (IsBadReadPtr((SEGPTR)MAKELONG( ptr->heap, ds ), sizeof(LOCALHEAPINFO)))
+        return NULL;
     pInfo = (LOCALHEAPINFO*)((char*)ptr + ptr->heap);
     if (pInfo->magic != LOCAL_HEAP_MAGIC) return NULL;
     return pInfo;
diff --git a/misc/Makefile.in b/misc/Makefile.in
index 7d0a546..b9939f3 100644
--- a/misc/Makefile.in
+++ b/misc/Makefile.in
@@ -6,7 +6,6 @@
 	comm.c \
 	commdlg.c \
 	compobj.c \
-	dos_fs.c \
 	driver.c \
 	exec.c \
 	escape.c \
@@ -20,14 +19,13 @@
 	olecli.c \
 	olesvr.c \
 	port.c \
-	profile.c \
 	rect.c \
 	shell.c \
 	sound.c \
 	spy.c \
 	stress.c \
+	toolhelp.c \
 	user.c \
-	user32.c \
 	winsocket.c \
 	xmalloc.c
 
diff --git a/misc/clipboard.c b/misc/clipboard.c
index 68f5fe7..41bab82 100644
--- a/misc/clipboard.c
+++ b/misc/clipboard.c
@@ -165,7 +165,7 @@
 /**************************************************************************
  *			CountClipboardFormats	[USER.143]
  */
-int CountClipboardFormats()
+INT CountClipboardFormats()
 {
     int FormatCount = 0;
     LPCLIPFORMAT lpFormat = ClipFormats; 
diff --git a/misc/comm.c b/misc/comm.c
index 107ec99..467912d 100644
--- a/misc/comm.c
+++ b/misc/comm.c
@@ -16,9 +16,9 @@
 #endif
 #include <unistd.h>
 
-#include "wine.h"
 #include "windows.h"
 #include "comm.h"
+#include "options.h"
 #include "stddebug.h"
 /* #define DEBUG_COMM */
 /* #undef  DEBUG_COMM */
@@ -40,11 +40,12 @@
 		option[3] = '1' + x;
 		option[4] = '\0';
 
-		GetPrivateProfileString("serialports", option, "*", temp, sizeof(temp), WINE_INI);
+		PROFILE_GetWineIniString( "serialports", option, "*",
+                                          temp, sizeof(temp) );
 		if (!strcmp(temp, "*") || *temp == '\0') 
 			COM[x].devicename = NULL;
 		else {
-		  	btemp = index(temp,',');
+		  	btemp = strchr(temp,',');
 			if (btemp != NULL) {
 			  	*btemp++ = '\0';
 				COM[x].baudrate = atoi(btemp);
@@ -69,7 +70,8 @@
 		option[3] = '1' + x;
 		option[4] = '\0';
 
-		GetPrivateProfileString("parallelports", option, "*", temp, sizeof(temp), WINE_INI);
+		PROFILE_GetWineIniString( "parallelports", option, "*",
+                                          temp, sizeof(temp) );
 		if (!strcmp(temp, "*") || *temp == '\0')
 			LPT[x].devicename = NULL;
 		else {
@@ -124,7 +126,7 @@
 		}
 }
 
-int BuildCommDCB(LPSTR device, DCB FAR *lpdcb)
+BOOL BuildCommDCB(LPCSTR device, LPDCB lpdcb)
 {
 	/* "COM1:9600,n,8,1"	*/
 	/*  012345		*/
@@ -219,7 +221,7 @@
 	return 0;
 }
 
-int OpenComm(LPSTR device, UINT cbInQueue, UINT cbOutQueue)
+int OpenComm(LPCSTR device, UINT cbInQueue, UINT cbOutQueue)
 {
 	int port, fd;
 
diff --git a/misc/dos_fs.c b/misc/dos_fs.c
deleted file mode 100644
index b01f6b0..0000000
--- a/misc/dos_fs.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * DOS-FS
- * NOV 1993 Erik Bos <erik@xs4all.nl>
- *
- * FindFile by Bob, hacked for dos & unixpaths by Erik.
- *
- * Bugfix by dash@ifi.uio.no: ToUnix() was called to often
- */
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <pwd.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#if defined(__linux__) || defined(sun)
-#include <sys/vfs.h>
-#endif
-#if defined(__NetBSD__) || defined(__FreeBSD__)
-#include <sys/param.h>
-#include <sys/mount.h>
-#include <sys/errno.h>
-#endif
-#ifdef __svr4__
-#include <sys/statfs.h>
-#endif
-#include "wine.h"
-#include "windows.h"
-#include "msdos.h"
-#include "dos_fs.h"
-#include "comm.h"
-#include "task.h"
-#include "stddebug.h"
-#include "debug.h"
-#include "xmalloc.h"
-
-#define WINE_INI_USER "~/.winerc"
-
-
-static void ExpandTildeString(char *s)
-{
-    struct passwd *entry;
-    char temp[1024], *ptr = temp;
-	
-    strcpy(temp, s);
-
-    while (*ptr)
-    {
-	if (*ptr != '~') 
-	{ 
-	    *s++ = *ptr++;
-	    continue;
-	}
-
-	ptr++;
-
-	if ( (entry = getpwuid(getuid())) == NULL) 
-	{
-	    continue;
-	}
-
-	strcpy(s, entry->pw_dir);
-	s += strlen(entry->pw_dir);
-    }
-    *s = 0;
-}
-
-
-
-int DOS_GetFreeSpace(int drive, long *size, long *available)
-{
-    struct statfs info;
-    const char *root;
-
-    if (!DRIVE_IsValid(drive)) return 0;
-    root = DRIVE_GetRoot(drive);
-
-#ifdef __svr4__
-	if (statfs( root, &info, 0, 0) < 0) {
-#else
-	if (statfs( root, &info) < 0) {
-#endif
-		fprintf(stderr,"dosfs: cannot do statfs(%s)\n", root );
-		return 0;
-	}
-
-	*size = info.f_bsize * info.f_blocks;
-#ifdef __svr4__
-	*available = info.f_bfree * info.f_bsize;
-#else
-	*available = info.f_bavail * info.f_bsize;
-#endif
-	return 1;
-}
-
-/**********************************************************************
- *		WineIniFileName
- */
-char *WineIniFileName(void)
-{
-	int fd;
-	static char *filename = NULL;
-	static char name[256];
-
-	if (filename)
-		return filename;
-
-	strcpy(name, WINE_INI_USER);
-	ExpandTildeString(name);
-	if ((fd = open(name, O_RDONLY)) != -1) {
-		close(fd);
-		filename = name;
-		return filename;
-	}
-	if ((fd = open(WINE_INI_GLOBAL, O_RDONLY)) != -1) {
-		close(fd);
-		filename = WINE_INI_GLOBAL;
-		return filename;
-	}
-	fprintf(stderr,"wine: can't open configuration file %s or %s !\n",
-		WINE_INI_GLOBAL, WINE_INI_USER);
-	exit(1);
-}
-
diff --git a/misc/exec.c b/misc/exec.c
index 1235661..5c49487 100644
--- a/misc/exec.c
+++ b/misc/exec.c
@@ -9,6 +9,7 @@
 #include <unistd.h>
 #include "neexe.h"
 #include "dlls.h"
+#include "shell.h"
 #include "windows.h"
 #include "callback.h"
 #include "stddebug.h"
@@ -41,6 +42,11 @@
     dprintf_exec( stdnimp,"PARTIAL STUB ExitWindows(%08lX, %04X)\n", 
                   dwReturnCode, wReserved);
 
+    /* Do the clean-up stuff */
+
+    WriteOutProfiles();
+    SHELL_SaveRegistry();
+
     exit( LOWORD(dwReturnCode) );
 }
 
diff --git a/misc/lstr.c b/misc/lstr.c
index 5f7c90a..5bc9032 100644
--- a/misc/lstr.c
+++ b/misc/lstr.c
@@ -106,7 +106,7 @@
 }
 
 /* KERNEL.353 32-bit version*/
-char *lstrcpyn( char *dst, const char *src, int n )
+LPSTR lstrcpyn( LPSTR dst, LPCSTR src, int n )
 {
     char *tmp = dst;
     while(n-- > 1 && *src)
@@ -293,7 +293,7 @@
 }
 
 /* AnsiToOemBuff Keyboard.134 */
-void AnsiToOemBuff(LPSTR lpAnsiStr, LPSTR lpOemStr, INT nLength)
+void AnsiToOemBuff(LPCSTR lpAnsiStr, LPSTR lpOemStr, UINT nLength)
 {
   int i;
   for(i=0;i<nLength;i++)
diff --git a/misc/main.c b/misc/main.c
index 0d9e948..b445865 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -524,29 +524,20 @@
 }
 
 
-#ifdef MALLOC_DEBUGGING
-static void malloc_error()
-{
-       fprintf(stderr,"malloc is not feeling well. Good bye\n");
-       exit(1);
-}
-#endif  /* MALLOC_DEBUGGING */
-
-
 static void called_at_exit(void)
 {
-    extern void sync_profiles(void);
-
-    sync_profiles();
     MAIN_RestoreSetup();
     WSACleanup();
-    SHELL_SaveRegistry();
 }
 
 /***********************************************************************
  *           main
  */
+#if defined(WINELIB) && defined(WINELIBDLL)
+int _wine_main (int argc, char *argv[])
+#else
 int main( int argc, char *argv[] )
+#endif
 {    
     int ret_val;
     int depth_count, i;
@@ -555,6 +546,21 @@
 
     extern int _WinMain(int argc, char **argv);
 
+#ifdef MALLOC_DEBUGGING
+    char *trace;
+
+    mcheck(NULL);
+    if (!(trace = getenv("MALLOC_TRACE")))
+    {       
+        fprintf( stderr, "MALLOC_TRACE not set. No trace generated\n" );
+    }
+    else
+    {
+        fprintf( stderr, "malloc trace goes to %s\n", trace );
+        mtrace();
+    }
+#endif
+
     setbuf(stdout,NULL);
     setbuf(stderr,NULL);
 
@@ -566,22 +572,6 @@
     
     MAIN_ParseOptions( &argc, argv );
 
-#ifdef MALLOC_DEBUGGING
-    if(debugging_malloc)
-    {
-       char *trace=getenv("MALLOC_TRACE");
-       if(!trace)
-       {       
-       	dprintf_malloc(stddeb,"MALLOC_TRACE not set. No trace generated\n");
-       }else
-       {
-               dprintf_malloc(stddeb,"malloc trace goes to %s\n",trace);
-               mtrace();
-       }
-      mcheck(malloc_error);
-    }
-#endif
-
     SHELL_Init();
     SHELL_LoadRegistry();
 
@@ -816,7 +806,7 @@
 /***********************************************************************
  *	SystemParametersInfo (USER.483)
  */
-BOOL SystemParametersInfo (UINT uAction, UINT uParam, void FAR *lpvParam, UINT fuWinIni)
+BOOL SystemParametersInfo (UINT uAction, UINT uParam, LPVOID lpvParam, UINT fuWinIni)
 {
 	int timeout, temp;
 	char buffer[256];
@@ -957,7 +947,7 @@
 /***********************************************************************
 *	HMEMCPY (KERNEL.348)
 */
-void hmemcpy(void FAR *hpvDest, const void FAR *hpvSource, long cbCopy)
+void hmemcpy(LPVOID hpvDest, LPCVOID hpvSource, LONG cbCopy)
 {
 	memcpy(hpvDest,	hpvSource, cbCopy);
 }
diff --git a/misc/port.c b/misc/port.c
index 52ac9d9..751750c 100644
--- a/misc/port.c
+++ b/misc/port.c
@@ -1,5 +1,3 @@
-#include <unistd.h>
-#include <sys/types.h>
 #include <sys/time.h>
 
 #ifndef HAVE_USLEEP
diff --git a/misc/profile.c b/misc/profile.c
deleted file mode 100644
index 4790c01..0000000
--- a/misc/profile.c
+++ /dev/null
@@ -1,496 +0,0 @@
-/*
- * Initialization-File Functions.
- *
- * Copyright (c) 1993 Miguel de Icaza
- *
- * 1/Dec o Corrected return values for Get*ProfileString
- *
- *       o Now, if AppName == NULL in Get*ProfileString it returns a list
- *            of the KeyNames (as documented in the MS-SDK).
- *
- *       o if KeyValue == NULL now clears the value in Get*ProfileString
- *
- * 20/Apr  SL - I'm not sure where these definitions came from, but my SDK
- *         has a NULL KeyValue returning a list of KeyNames, and a NULL
- *         AppName undefined.  I changed GetSetProfile to match.  This makes
- *         PROGMAN.EXE do the right thing.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "wine.h"
-#include "windows.h"
-#include "dos_fs.h"
-#include "toolhelp.h"
-#include "stddebug.h"
-#include "debug.h"
-#include "xmalloc.h"
-
-#define STRSIZE 255
-
-typedef struct TKeys {
-    char *KeyName;
-    char *Value;
-    struct TKeys *link;
-} TKeys;
-
-typedef struct TSecHeader {
-    char *AppName;
-    TKeys *Keys;
-    struct TSecHeader *link;
-} TSecHeader;
-    
-typedef struct TProfile {
-    char *FileName;
-    char *FullName;
-    TSecHeader *Section;
-    struct TProfile *link;
-    int changed;
-} TProfile;
-
-TProfile *Current = 0;
-TProfile *Base = 0;
-
-static TSecHeader *is_loaded (char *FileName)
-{
-    TProfile *p = Base;
-    
-    while (p){
-	if (!lstrcmpi( FileName, p->FileName)){
-	    Current = p;
-	    return p->Section;
-	}
-	p = p->link;
-    }
-    return 0;
-}
-
-#define WIN_INI WinIniFileName()
-
-static char *WinIniFileName(void)
-{
-    static char *name = NULL;
-    int len;
-    const char *unixName;
-
-    if (name) return name;
-
-    len = GetWindowsDirectory( NULL, 0 ) + 9;
-    name = xmalloc( len );
-    GetWindowsDirectory( name, len );
-    strcat( name, "/win.ini" );
-    if (!(unixName = DOSFS_GetUnixFileName( name, TRUE ))) return NULL;
-    free( name );
-    name = strdup( unixName );
-    return name;
-}
-
-static char *GetIniFileName(char *name, char *dir)
-{
-	char temp[256];
-
-	if (strchr(name, '/'))
-		return name;
-
-        if (strlen(dir)) {
-        strcpy(temp, dir);
-        strcat(temp, "\\");
-	strcat(temp, name);
-	}
-	else
-	  strcpy(temp, name);
-	return DOSFS_GetUnixFileName(temp,TRUE);
-}
-
-static TSecHeader *load (char *filename, char **pfullname)
-{
-    FILE *f;
-    TSecHeader *SecHeader = 0;
-    char CharBuffer [STRSIZE];
-    char *bufptr;
-    char *lastnonspc;
-    int bufsize;
-    char *file, *purefilename;
-    int c;
-    char path[MAX_PATH+1];
-    BOOL firstbrace;
-    
-    *pfullname = NULL;
-
-    dprintf_profile(stddeb,"Trying to load file %s \n", filename);
-
-    /* First try it as is */
-    file = GetIniFileName(filename, "");
-    if (!file || !(f = fopen(file, "r")))
-    {
-      if  ((purefilename = strrchr( filename, '\\' )))
-	purefilename++; 
-      else if  ((purefilename = strrchr( filename, '/' ))) 
-	purefilename++; 
-      else
-	purefilename = filename;
-
-      /* Now try the Windows directory */
-      GetWindowsDirectory(path, sizeof(path));
-      if ((file = GetIniFileName(purefilename, path)))
-      {
-          dprintf_profile(stddeb,"Trying to load  in windows directory file %s\n",
-                          file);
-          f = fopen(file, "r");
-      }
-      else f = NULL;
-
-      if (f == NULL)
-      { 	/* Try the path of the current executable */
-    
-	if (GetCurrentTask())
-	{
-	    char *p;
-	    GetModuleFileName( GetCurrentTask(), path, MAX_PATH );
-	    if ((p = strrchr( path, '\\' )))
-	    {
-		p[0] = '\0'; /* Remove trailing slash */
-		if ((file = GetIniFileName(purefilename, path)))
-                {
-                    dprintf_profile(stddeb,
-                                    "Trying to load in current directory%s\n",
-                                    file);
-                    f = fopen(file, "r");
-                }
-	    }
-	}
-    }
-      if (f == NULL) { 	/* And now in $HOME/.wine */
-	
-	strcpy(path,getenv("HOME"));
-	strcat(path, "/.wine/");
-	strcat(path, purefilename);
-	dprintf_profile(stddeb,"Trying to load in user-directory %s\n", path);
-        file = path;
-	f = fopen(file, "r");
-      }
-      
-      if (f == NULL) {
-	/* FIXED: we ought to create it now (in which directory?) */
-	/* lets do it in ~/.wine */
-	strcpy(path,getenv("HOME"));
-	strcat(path, "/.wine/");
-	strcat(path, purefilename);
-	dprintf_profile(stddeb,"Creating %s\n", path);
-        file = path;
-	f = fopen(file, "w+");
-    if (f == NULL) {
-	fprintf(stderr, "profile.c: load() can't find file %s\n", filename);
-	return NULL;
-	}
-      }
-    }
-    
-    *pfullname = xstrdup(file);
-    dprintf_profile(stddeb,"Loading %s\n", file);
-
-    firstbrace = TRUE;
-    for(;;) {	
-	c = fgetc(f);
-	if (c == EOF) goto finished;
-	
-	if (isspace(c))
-	    continue;
-	if (c == ';') {
-	    do {
-		c = fgetc(f);
-	    } while (!(c == EOF || c == '\n'));
-	    if (c == EOF) goto finished;
-	}
-	if (c == '[') {
-	    TSecHeader *temp = SecHeader;
-	    
-	    SecHeader = (TSecHeader *) xmalloc (sizeof (TSecHeader));
-	    SecHeader->link = temp;
-	    SecHeader->Keys = NULL;
-	    do {
-		c = fgetc(f);
-		if (c == EOF) goto bad_file;
-	    } while (isspace(c));
-	    bufptr = lastnonspc = CharBuffer;
-	    bufsize = 0;
-	    do {
-		if (c != ']') {
-		    bufsize++;
-		    *bufptr++ = c;
-		    if (!isspace(c))
-		    	lastnonspc = bufptr;
-		} else
-		    break;
-		c = fgetc(f);
-		if (c == EOF) goto bad_file;
-	    } while(bufsize < STRSIZE-1);
-	    *lastnonspc = 0;
-	    if (!strlen(CharBuffer))
-	    	fprintf(stderr, "warning: empty section name in ini file\n");
-	    SecHeader->AppName = xstrdup (CharBuffer);
-	    dprintf_profile(stddeb,"%s: section %s\n", file, CharBuffer);
-	    firstbrace = FALSE;
-	} else if (SecHeader) {
-	    TKeys *temp = SecHeader->Keys;
-	    BOOL skipspc;
-	    
-	    if (firstbrace)
-	    	goto bad_file;
-	    bufptr = lastnonspc = CharBuffer;
-	    bufsize = 0;
-	    do {
-		if (c != '=') {
-		    bufsize++;
-		    *bufptr++ = c;
-		    if (!isspace(c))
-		    	lastnonspc = bufptr;
-		} else
-		    break;
-		c = fgetc(f);
-		if (c == EOF) goto bad_file;
-	    } while(bufsize < STRSIZE-1);
-	    *lastnonspc = 0;
-	    if (!strlen(CharBuffer))
-	    	fprintf(stderr, "warning: empty key name in ini file\n");
-	    SecHeader->Keys = (TKeys *) xmalloc (sizeof (TKeys));
-	    SecHeader->Keys->link = temp;
-	    SecHeader->Keys->KeyName = xstrdup (CharBuffer);
-
-	    dprintf_profile(stddeb,"%s:   key %s\n", file, CharBuffer);
-	    
-	    bufptr = lastnonspc = CharBuffer;
-	    bufsize = 0;
-	    skipspc = TRUE;
-	    do {
-		c = fgetc(f);
-		if (c == EOF || c == '\n') break;
-		if (!isspace(c) || !skipspc) {
-		    skipspc = FALSE;
-		    bufsize++;
-		    *bufptr++ = c;
-		    if (!isspace(c))
-		    	lastnonspc = bufptr;
-		}
-	    } while(bufsize < STRSIZE-1);
-	    *lastnonspc = 0;
-	    SecHeader->Keys->Value = xstrdup (CharBuffer);
-	    dprintf_profile (stddeb, "[%s] (%s)=%s\n", SecHeader->AppName,
-			     SecHeader->Keys->KeyName, SecHeader->Keys->Value);
-	    if (c == ';') {
-		do {
-		    c = fgetc(f);
-		} while (!(c == EOF || c == '\n'));
-		if (c == EOF)
-		    goto finished;
-	    }
-	}
-
-    }
-bad_file:
-    fprintf(stderr, "warning: bad ini file\n");
-finished:
-    return SecHeader;
-}
-
-static void new_key (TSecHeader *section, char *KeyName, char *Value)
-{
-    TKeys *key;
-    
-    key = (TKeys *) xmalloc (sizeof (TKeys));
-    key->KeyName = xstrdup (KeyName);
-    key->Value   = xstrdup (Value);
-    key->link = section->Keys;
-    section->Keys = key;
-}
-
-static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName,
-		     LPSTR Default, LPSTR ReturnedString, short Size,
-		     LPSTR FileName)
-
-{
-    TProfile   *New;
-    TSecHeader *section;
-    TKeys      *key;
-    
-    /* Supposedly Default should NEVER be NULL.  But sometimes it is.  */
-    if (Default == NULL)
-	Default = "";
-
-    if (!(section = is_loaded (FileName))){
-	New = (TProfile *) xmalloc (sizeof (TProfile));
-	New->link = Base;
-	New->FileName = xstrdup (FileName);
-	New->Section = load (FileName, &New->FullName);
-	New->changed = FALSE;
-	Base = New;
-	section = New->Section;
-	Current = New;
-    }
-
-    /* Start search */
-    for (; section; section = section->link){
-	if (lstrcmpi(section->AppName, AppName))
-	    continue;
-
-	/* If no key value given, then list all the keys */
-	if ((!KeyName) && (!set)){
-	    char *p = ReturnedString;
-	    int left = Size - 2;
-	    int slen;
-
-	    dprintf_profile(stddeb,"GetSetProfile // KeyName == NULL, Enumeration !\n");
-	    for (key = section->Keys; key; key = key->link){
-		if (left < 1) {
-		    dprintf_profile(stddeb,"GetSetProfile // No more storage for enum !\n");
-		    return Size - 2;
-		}
-		slen = MIN(strlen(key->KeyName) + 1, left);
-		lstrcpyn(p, key->KeyName, slen);
-		dprintf_profile(stddeb,"GetSetProfile // enum '%s' !\n", p);
-		left -= slen;
-		p += slen;
-	    }
-	    *p = '\0';
-	    return Size - 2 - left;
-	}
-	for (key = section->Keys; key; key = key->link){
-	    int slen;
-	    if (lstrcmpi(key->KeyName, KeyName))
-		continue;
-	    if (set){
-		free (key->Value);
-		key->Value = xstrdup (Default ? Default : "");
-		Current->changed=TRUE;
-		return 1;
-	    }
-	    slen = MIN(strlen(key->Value)+1, Size);
-	    lstrcpyn(ReturnedString, key->Value, slen);
-	    dprintf_profile(stddeb,"GetSetProfile // Return ``%s''\n", ReturnedString);
-	    return 1; 
-	}
-	/* If Getting the information, then don't write the information
-	   to the INI file, need to run a couple of tests with windog */
-	/* No key found */
-	if (set) {
-	    new_key (section, KeyName, Default);
-        } else {
-	    int slen = MIN(strlen(Default)+1, Size);
-            lstrcpyn(ReturnedString, Default, slen);
-	    dprintf_profile(stddeb,"GetSetProfile // Key not found\n");
-	}
-	return 1;
-    }
-
-    /* Non existent section */
-    if (set){
-	section = (TSecHeader *) xmalloc (sizeof (TSecHeader));
-	section->AppName = xstrdup (AppName);
-	section->Keys = 0;
-	new_key (section, KeyName, Default);
-	section->link = Current->Section;
-	Current->Section = section;
-	Current->changed = TRUE;
-    } else {
-	int slen = MIN(strlen(Default)+1, Size);
-	lstrcpyn(ReturnedString, Default, slen);
-	dprintf_profile(stddeb,"GetSetProfile // Section not found\n");
-    }
-    return 1;
-}
-
-short GetPrivateProfileString (LPCSTR AppName, LPCSTR KeyName,
-			       LPCSTR Default, LPSTR ReturnedString,
-			       short Size, LPCSTR FileName)
-{
-    int v;
-
-    dprintf_profile(stddeb,"GetPrivateProfileString ('%s', '%s', '%s', %p, %d, %s\n", 
-			AppName, KeyName, Default, ReturnedString, Size, FileName);
-    v = GetSetProfile (0,AppName,KeyName,Default,ReturnedString,Size,FileName);
-    if (AppName)
-	return strlen (ReturnedString);
-    else
-	return Size - v;
-}
-
-int GetProfileString (LPCSTR AppName, LPCSTR KeyName, LPCSTR Default, 
-		      LPSTR ReturnedString, int Size)
-{
-    return GetPrivateProfileString (AppName, KeyName, Default,
-				    ReturnedString, Size, WIN_INI );
-}
-
-WORD GetPrivateProfileInt (LPCSTR AppName, LPCSTR KeyName, short Default,
-			   LPCSTR File)
-{
-    static char IntBuf[10];
-    static char buf[10];
-
-    sprintf (buf, "%d", Default);
-    
-    /* Check the exact semantic with the SDK */
-    GetPrivateProfileString (AppName, KeyName, buf, IntBuf, 10, File);
-    if (!lstrcmpi(IntBuf, "true"))
-	return 1;
-    if (!lstrcmpi(IntBuf, "yes"))
-	return 1;
-    return strtoul( IntBuf, NULL, 0 );
-}
-
-WORD GetProfileInt (LPCSTR AppName, LPCSTR KeyName, int Default)
-{
-    return GetPrivateProfileInt (AppName, KeyName, Default, WIN_INI);
-}
-
-BOOL WritePrivateProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String,
-				LPSTR FileName)
-{
-    if (!AppName || !KeyName || !String)  /* Flush file to disk */
-        return TRUE;
-    return GetSetProfile (1, AppName, KeyName, String, "", 0, FileName);
-}
-
-BOOL WriteProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String)
-{
-    return (WritePrivateProfileString (AppName, KeyName, String, WIN_INI));
-}
-
-static void dump_keys (FILE *profile, TKeys *p)
-{
-    if (!p)
-	return;
-    dump_keys (profile, p->link);
-    fprintf (profile, "%s=%s\r\n", p->KeyName, p->Value);
-}
-
-static void dump_sections (FILE *profile, TSecHeader *p)
-{
-    if (!p)
-	return;
-    dump_sections (profile, p->link);
-    fprintf (profile, "\r\n[%s]\r\n", p->AppName);
-    dump_keys (profile, p->Keys);
-}
-
-static void dump_profile (TProfile *p)
-{
-    FILE *profile;
-    
-    if (!p)
-	return;
-    dump_profile (p->link);
-    if(!p->changed)
-	return;
-    if (p->FullName && (profile = fopen (p->FullName, "w")) != NULL){
-	dump_sections (profile, p->Section);
-	fclose (profile);
-    }
-}
-
-void sync_profiles (void)
-{
-    dump_profile (Base);
-}
diff --git a/misc/rect.c b/misc/rect.c
index c5d7985..0ae8b0c 100644
--- a/misc/rect.c
+++ b/misc/rect.c
@@ -33,9 +33,10 @@
 /***********************************************************************
  *           CopyRect    (USER.74)
  */
-void CopyRect( LPRECT dest, LPRECT src )
+BOOL CopyRect( LPRECT dest, LPRECT src )
 {
     *dest = *src;
+    return TRUE;
 }
 
 
diff --git a/misc/shell.c b/misc/shell.c
index 0d48698..802ee7b 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -215,7 +215,7 @@
 /*************************************************************************
  *				RegOpenKey		[SHELL.1]
  */
-LONG RegOpenKey(HKEY hKey, LPCSTR lpSubKey, HKEY FAR *lphKey)
+LONG RegOpenKey(HKEY hKey, LPCSTR lpSubKey, LPHKEY lphKey)
 {
 	LPKEYSTRUCT	lpKey,lpNextKey;
 	LPCSTR		ptr;
@@ -264,7 +264,7 @@
 /*************************************************************************
  *				RegCreateKey		[SHELL.2]
  */
-LONG RegCreateKey(HKEY hKey, LPCSTR lpSubKey, HKEY FAR *lphKey)
+LONG RegCreateKey(HKEY hKey, LPCSTR lpSubKey, LPHKEY lphKey)
 {
 	HKEY		hNewKey;
 	LPKEYSTRUCT	lpNewKey;
@@ -391,7 +391,7 @@
 /*************************************************************************
  *				RegQueryValue		[SHELL.6]
  */
-LONG RegQueryValue(HKEY hKey, LPCSTR lpSubKey, LPSTR lpVal, LONG FAR *lpcb)
+LONG RegQueryValue(HKEY hKey, LPCSTR lpSubKey, LPSTR lpVal, LPLONG lpcb)
 {
 	HKEY		hRetKey;
 	LPKEYSTRUCT	lpKey;
@@ -552,7 +552,7 @@
 /*************************************************************************
  *				ShellExecute		[SHELL.20]
  */
-HINSTANCE ShellExecute(HWND hWnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, int iShowCmd)
+HINSTANCE ShellExecute(HWND hWnd, LPCSTR lpOperation, LPCSTR lpFile, LPSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd)
 {
     char cmd[400];
     char *p,*x;
diff --git a/misc/sound.c b/misc/sound.c
index 8b8696d..990bb72 100644
--- a/misc/sound.c
+++ b/misc/sound.c
@@ -77,7 +77,7 @@
         return 0;
 }
 
-int CountVoiceNotes(int x)
+INT CountVoiceNotes(INT x)
 {
 	fprintf(stderr, "CountVoiceNotes(%d)\n", x);
         return 0;
diff --git a/misc/spy.c b/misc/spy.c
index 3a92d62..81f2852 100644
--- a/misc/spy.c
+++ b/misc/spy.c
@@ -10,7 +10,6 @@
 #include <X11/Xresource.h>
 #include <string.h>
 #include "windows.h"
-#include "wine.h"
 #include "options.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -529,7 +528,8 @@
 
     for(i=0; i <= SPY_MAX_MSGNUM; i++) SpyFilters[i] = SpyIncludes[i] = FALSE;
 
-    GetPrivateProfileString("spy", "Exclude", "",lpstrBuffer ,511 , WINE_INI);
+    PROFILE_GetWineIniString( "spy", "Exclude", "",
+                              lpstrBuffer, sizeof(lpstrBuffer) );
     dprintf_message(stddeb,"SpyInit: Exclude=%s\n",lpstrBuffer);
     if( *lpstrBuffer != 0 )
       if(strstr(lpstrBuffer,"EXCLUDEALL"))
@@ -539,7 +539,8 @@
 	    if(MessageTypeNames[i])
 	       if(strstr(lpstrBuffer,MessageTypeNames[i])) SpyFilters[i] = TRUE; 
 
-    GetPrivateProfileString("spy", "Include", "INCLUDEALL",lpstrBuffer ,511 , WINE_INI);
+    PROFILE_GetWineIniString( "spy", "Include", "INCLUDEALL",
+                              lpstrBuffer, sizeof(lpstrBuffer) );
     dprintf_message(stddeb,"SpyInit: Include=%s\n",lpstrBuffer);
     if( *lpstrBuffer != 0 )
       if(strstr(lpstrBuffer,"INCLUDEALL"))
diff --git a/misc/toolhelp.c b/misc/toolhelp.c
new file mode 100644
index 0000000..ccde79a
--- /dev/null
+++ b/misc/toolhelp.c
@@ -0,0 +1,70 @@
+/*
+ * Misc Toolhelp functions
+ *
+ * Copyright 1996 Marcus Meissner
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include "windows.h"
+#include "win.h"
+#include "toolhelp.h"
+#include "stddebug.h"
+#include "debug.h"
+#include "xmalloc.h"
+
+/* FIXME: to make this working, we have to callback all these registered 
+ * functions from all over the WINE code. Someone with more knowledge than
+ * me please do that. -Marcus
+ */
+static struct notify
+{
+    HTASK    htask;
+    FARPROC  lpfnCallback;
+    WORD     wFlags;
+} *notifys = NULL;
+
+static int nrofnotifys = 0;
+
+BOOL
+NotifyRegister(HTASK htask,FARPROC lpfnCallback,WORD wFlags)
+{
+    int	i;
+
+    dprintf_toolhelp( stddeb, "NotifyRegister(%x,%lx,%x) called.\n",
+                      htask, (DWORD)lpfnCallback, wFlags );
+    for (i=0;i<nrofnotifys;i++)
+        if (notifys[i].htask==htask)
+            break;
+    if (i==nrofnotifys) {
+        if (notifys==NULL)
+            notifys=(struct notify*)xmalloc(sizeof(struct notify));
+        else
+            notifys=(struct notify*)xrealloc(notifys,sizeof(struct notify)*(nrofnotifys+1));
+        nrofnotifys++;
+    }
+    notifys[i].htask=htask;
+    notifys[i].lpfnCallback=lpfnCallback;
+    notifys[i].wFlags=wFlags;
+    return TRUE;
+}
+
+BOOL
+NotifyUnregister(HTASK htask)
+{
+    int	i;
+    
+    dprintf_toolhelp( stddeb, "NotifyUnregister(%x) called.\n", htask );
+    for (i=nrofnotifys;i--;)
+        if (notifys[i].htask==htask)
+            break;
+    if (i==-1)
+        return FALSE;
+    memcpy(notifys+i,notifys+(i+1),sizeof(struct notify)*(nrofnotifys-i-1));
+    notifys=(struct notify*)realloc(notifys,(nrofnotifys-1)*sizeof(struct notify));
+    nrofnotifys--;
+    return TRUE;
+}
diff --git a/misc/user.c b/misc/user.c
index 27bd40c..4fe51e8 100644
--- a/misc/user.c
+++ b/misc/user.c
@@ -4,20 +4,10 @@
 */
 #include <stdio.h>
 #include <stdlib.h>
-#include "atom.h"
-#include "comm.h"
-#include "gdi.h"
-#include "desktop.h"
-#include "dlls.h"
-#include "dos_fs.h"
-#include "sysmetrics.h"
-#include "menu.h"
-#include "dce.h"
-#include "dialog.h"
-#include "syscolor.h"
-#include "win.h"
 #include "windows.h"
+#include "gdi.h"
 #include "user.h"
+#include "win.h"
 #include "message.h"
 #include "toolhelp.h"
 
diff --git a/misc/winsocket.c b/misc/winsocket.c
index 0586e52..05e1ecf 100644
--- a/misc/winsocket.c
+++ b/misc/winsocket.c
@@ -652,7 +652,16 @@
     dprintf_winsock(stddeb, "WSA_socket: af=%d type=%d protocol=%d\n", af, type, protocol);
 
     if ((sock = socket(af, type, protocol)) < 0) {
+        if (errno != EPERM) {
             errno_to_wsaerrno();
+        } else {
+             /* NOTE: EPERM does not always map to WSAESOCKTNOSUPPORT
+              * so this is done as a special case
+              */
+             /* non super-user wants a raw socket */
+             dprintf_winsock(stderr, "WSA_socket: not enough privileges\n");
+             WSASetLastError(WSAESOCKTNOSUPPORT);
+        }
             dprintf_winsock(stddeb, "WSA_socket: failed !\n");
             return INVALID_SOCKET;
     }
@@ -1177,7 +1186,7 @@
 	return WSASYSNOTREADY;
 
     Heap = (struct WinSockHeap *) GlobalLock(HeapHandle);
-    bcopy(&WINSOCK_data, lpWSAData, sizeof(WINSOCK_data));
+    memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
 
     /* ipc stuff */
 
diff --git a/miscemu/cpu.c b/miscemu/cpu.c
index bde9e36..a17f635 100644
--- a/miscemu/cpu.c
+++ b/miscemu/cpu.c
@@ -7,6 +7,7 @@
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
+#include "windows.h"
 
 int runtime_cpu (void)
 {
diff --git a/miscemu/dpmi.c b/miscemu/dpmi.c
index 760be10..2b3c0f8 100644
--- a/miscemu/dpmi.c
+++ b/miscemu/dpmi.c
@@ -10,6 +10,7 @@
 #include <string.h>
 #include "windows.h"
 #include "ldt.h"
+#include "module.h"
 #include "registers.h"
 #include "wine.h"
 #include "miscemu.h"
@@ -40,6 +41,8 @@
     WORD  ss;
 } REALMODECALL;
 
+extern void do_mscdex(struct sigcontext_struct *context);
+
 /**********************************************************************
  *	    INT_Int31Handler
  *
@@ -69,6 +72,34 @@
         }
         break;
 
+    case 0x0002:  /* Real mode segment to descriptor */
+        {
+            WORD entryPoint = 0;  /* KERNEL entry point for descriptor */
+            switch(BX_reg(&context))
+            {
+            case 0x0000: entryPoint = 183; break;  /* __0000H */
+            case 0x0040: entryPoint = 193; break;  /* __0040H */
+            case 0xa000: entryPoint = 174; break;  /* __A000H */
+            case 0xb000: entryPoint = 181; break;  /* __B000H */
+            case 0xb800: entryPoint = 182; break;  /* __B800H */
+            case 0xc000: entryPoint = 195; break;  /* __C000H */
+            case 0xd000: entryPoint = 179; break;  /* __D000H */
+            case 0xe000: entryPoint = 190; break;  /* __E000H */
+            case 0xf000: entryPoint = 194; break;  /* __F000H */
+            default:
+                fprintf( stderr, "DPMI: real-mode seg to descriptor %04x not possible\n",
+                         BX_reg(&context) );
+                AX_reg(&context) = 0x8011;
+                SET_CFLAG(&context);
+                break;
+            }
+            if (entryPoint) 
+                AX_reg(&context) = LOWORD(MODULE_GetEntryPoint( 
+                                                   GetModuleHandle( "KERNEL" ),
+                                                   entryPoint ));
+        }
+        break;
+
     case 0x0003:  /* Get next selector increment */
         AX_reg(&context) = __AHINCR;
         break;
@@ -162,7 +193,25 @@
                     "                ESI=%08lx EDI=%08lx ES=%04x DS=%04x\n",
                     BL_reg(&context), p->eax, p->ebx, p->ecx, p->edx,
                     p->esi, p->edi, p->es, p->ds );
-            SET_CFLAG(&context);
+
+            /* Compton's 1995 encyclopedia does its MSCDEX calls through
+             * this interrupt.  Why?  Who knows...
+             */
+            if ((BL_reg(&context) == 0x2f) && ((p->eax & 0xFF00) == 0x1500))
+            {
+                struct sigcontext_struct context2;
+                EAX_reg(&context2) = p->eax;
+                EBX_reg(&context2) = p->ebx;
+                ECX_reg(&context2) = p->ecx;
+                EDX_reg(&context2) = p->edx;
+                ES_reg(&context2) = p->es;
+                do_mscdex(&context2);
+                p->eax = EAX_reg(&context2);
+                p->ebx = EBX_reg(&context2);
+                p->ecx = ECX_reg(&context2);
+                p->edx = EDX_reg(&context2);
+            }
+            else SET_CFLAG(&context);
         }
         break;
 
diff --git a/miscemu/int21.c b/miscemu/int21.c
index 16b5f8f..a7d9ec0 100644
--- a/miscemu/int21.c
+++ b/miscemu/int21.c
@@ -83,12 +83,6 @@
 
 extern char TempDirectory[];
 
-static int Error(int e, int class, int el)
-{
-    return DOS_ERROR( e, class, SA_Abort, el );
-}
-
-
 BYTE *GetCurrentDTA(void)
 {
     TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() );
@@ -140,61 +134,30 @@
 	}	
 }
 
-static void GetFreeDiskSpace(struct sigcontext_struct *context)
+static int INT21_GetFreeDiskSpace(struct sigcontext_struct *context)
 {
-    long size,available;
+    DWORD size, available;
     int drive = DOS_GET_DRIVE( DL_reg(context) );
 
-    if (!DRIVE_IsValid(drive))
-    {
-        DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk );
-        AX_reg(context) = 0xffff;
-        return;
-    }
-	
-    if (!DOS_GetFreeSpace(drive, &size, &available)) {
-        DOS_ERROR( ER_GeneralFailure, EC_MediaError, SA_Abort, EL_Disk );
-        AX_reg(context) = 0xffff;
-        return;
-    }
+    if (!DRIVE_GetFreeSpace(drive, &size, &available)) return 0;
 
-    AX_reg(context) = (drive < 2) ? 1 : 64;  /* 64 for hard-disks, 1 for diskettes */
-    CX_reg(context) = 512;
-    BX_reg(context) = (available / (CX_reg(context) * AX_reg(context)));
-    DX_reg(context) = (size / (CX_reg(context) * AX_reg(context)));
-    Error (0,0,0);
+    CX_reg(context) = 512;  /* bytes per sector */
+    size /= 512;
+    available /= 512;
+    AX_reg(context) = 1;  /* sectors per cluster */
+    while (AX_reg(context) * 65530 < size) AX_reg(context) *= 2;
+    BX_reg(context) = available / AX_reg(context);  /* free clusters */
+    DX_reg(context) = size / AX_reg(context);  /* total clusters */
+    return 1;
 }
 
-static void GetDriveAllocInfo(struct sigcontext_struct *context)
+static int INT21_GetDriveAllocInfo(struct sigcontext_struct *context)
 {
-    long size, available;
-    int drive = DOS_GET_DRIVE( DL_reg(context) );
-	
-    if (!DRIVE_IsValid(drive))
-    {
-        AX_reg(context) = 4;
-        CX_reg(context) = 512;
-        DX_reg(context) = 0;
-        DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk );
-        return;
-    }
-
-	if (!DOS_GetFreeSpace(drive, &size, &available))
-        {
-            DOS_ERROR( ER_GeneralFailure, EC_MediaError, SA_Abort, EL_Disk );
-            AX_reg(context) = 0xffff;
-            return;
-	}
-	
-	AX_reg(context) = (drive < 2) ? 1 : 64;  /* 64 for hard-disks, 1 for diskettes */
-	CX_reg(context) = 512;
-	DX_reg(context) = (size / (CX_reg(context) * AX_reg(context)));
-
-	heap->mediaID = 0xf0;
-
-	DS_reg(context) = DosHeapHandle;
-	BX_reg(context) = (int)&heap->mediaID - (int)heap;
-	Error (0,0,0);
+    if (!INT21_GetFreeDiskSpace( context )) return 0;
+    heap->mediaID = 0xf0;
+    DS_reg(context) = DosHeapHandle;
+    BX_reg(context) = (int)&heap->mediaID - (int)heap;
+    return 1;
 }
 
 static void GetDrivePB(struct sigcontext_struct *context, int drive)
@@ -242,40 +205,15 @@
 
 static void ioctlGetDeviceInfo(struct sigcontext_struct *context)
 {
-
-	dprintf_int (stddeb, "int21: ioctl (%d, GetDeviceInfo)\n", BX_reg(context));
-
-	switch (BX_reg(context))
-        {
-		case 0:
-		case 1:
-                    DX_reg(context) = 2;  /* FIXME */
-                    break;
-		case 2:
-			DX_reg(context) = 0x80d0 | (1 << (BX_reg(context) != 0));
-                        RESET_CFLAG(context);
-			break;
-
-		default:
-		{
-		    struct stat sbuf;
-	    
-		    if (fstat(BX_reg(context), &sbuf) < 0)
-		    {
-                        INT_BARF( context, 0x21 );
-			SET_CFLAG(context);
-			return;
-		    }
-	    
-		    DX_reg(context) = 0x0943;
-		    /* bits 0-5 are current drive
-		     * bit 6 - file has NOT been written..FIXME: correct?
-		     * bit 8 - generate int24 if no diskspace on write/ read past end of file
-		     * bit 11 - media not removable
-		     */
-		}
-	}
-	RESET_CFLAG(context);
+    dprintf_int (stddeb, "int21: ioctl (%d, GetDeviceInfo)\n", BX_reg(context));
+    
+    DX_reg(context) = 0x0942;
+    /* bits 0-5 are current drive
+     * bit 6 - file has NOT been written..FIXME: correct?
+     * bit 8 - generate int24 if no diskspace on write/ read past end of file
+     * bit 11 - media not removable
+     */
+    RESET_CFLAG(context);
 }
 
 static void ioctlGenericBlkDevReq(struct sigcontext_struct *context)
@@ -454,6 +392,7 @@
 
 void ExtendedOpenCreateFile(struct sigcontext_struct *context)
 {
+  BYTE action=DL_reg(context);
   dprintf_int(stddeb, "int21: extended open/create: file= %s \n",
 	      DOSFS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context)),FALSE));
   /* Shuffle arguments to call OpenExistingFile */
@@ -466,7 +405,7 @@
       dprintf_int(stddeb, "int21: extended open/create %s exists \n",
 		  DOSFS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context)),TRUE));
       /* Now decide what do do */
-      if ((DL_reg(context) & 0x0007)== 0)
+      if ((action & 0x07)== 0)
 	{
 	  BX_reg(context) = AX_reg(context);
 	  CloseFile(context);
@@ -476,7 +415,7 @@
 	  dprintf_int(stddeb, "int21: extended open/create: failed because file exixts \n");
 	  return;
 	}
-      if ((DL_reg(context) & 0x0007)== 2) {
+      if ((action & 0x07)== 2) {
 	/* Truncate it, but first check if opend for write */
 	if ((BL_reg(context) & 0x0007)== 0) {
 	  BX_reg(context) = AX_reg(context);
@@ -516,9 +455,10 @@
     }
   else /* file does not exist */
     {
+      RESET_CFLAG(context); /* was set by OpenExistingFile(context) */
      dprintf_int(stddeb, "int21: extended open/create %s dosen't exists \n",
 		  DOSFS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context)),FALSE));
-      if ((DL_reg(context) & 0x00F0)== 0) {
+      if ((action & 0xF0)== 0) {
 	CX_reg(context) = 0;
 	SET_CFLAG(context);
 	dprintf_int(stddeb, "int21: extended open/create: failed, file dosen't exist\n");
@@ -1102,11 +1042,11 @@
 
     case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */
         DL_reg(&context) = 0;
-        GetDriveAllocInfo(&context);
+        if (!INT21_GetDriveAllocInfo(&context)) AX_reg(&context) = 0xffff;
         break;
 	
     case 0x1c: /* GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE */
-        GetDriveAllocInfo(&context);
+        if (!INT21_GetDriveAllocInfo(&context)) AX_reg(&context) = 0xffff;
         break;
 
     case 0x1f: /* GET DRIVE PARAMETER BLOCK FOR DEFAULT DRIVE */
@@ -1205,7 +1145,7 @@
         break;
 
     case 0x36: /* GET FREE DISK SPACE */
-        GetFreeDiskSpace(&context);
+        if (!INT21_GetFreeDiskSpace(&context)) AX_reg(&context) = 0xffff;
         break;
 
     case 0x38: /* GET COUNTRY-SPECIFIC INFORMATION */
@@ -1258,22 +1198,32 @@
         break;
 
     case 0x3f: /* "READ" - READ FROM FILE OR DEVICE */
-        if ((AX_reg(&context) = _lread( BX_reg(&context),
-                       PTR_SEG_OFF_TO_LIN( DS_reg(&context),DX_reg(&context) ),
-                       CX_reg(&context))) == (WORD)HFILE_ERROR)
         {
-            AX_reg(&context) = DOS_ExtendedError;
-            SET_CFLAG(&context);
+            LONG result = _hread( BX_reg(&context),
+                                  PTR_SEG_OFF_TO_LIN( DS_reg(&context),
+                                                      DX_reg(&context) ),
+                                  CX_reg(&context) );
+            if (result == -1)
+            {
+                AX_reg(&context) = DOS_ExtendedError;
+                SET_CFLAG(&context);
+            }
+            else AX_reg(&context) = (WORD)result;
         }
         break;
 
     case 0x40: /* "WRITE" - WRITE TO FILE OR DEVICE */
-        if ((AX_reg(&context) = _lwrite( BX_reg(&context),
-                       PTR_SEG_OFF_TO_LIN( DS_reg(&context),DX_reg(&context) ),
-                       CX_reg(&context))) == (WORD)HFILE_ERROR)
         {
-            AX_reg(&context) = DOS_ExtendedError;
-            SET_CFLAG(&context);
+            LONG result = _hwrite( BX_reg(&context),
+                                   PTR_SEG_OFF_TO_LIN( DS_reg(&context),
+                                                       DX_reg(&context) ),
+                                   CX_reg(&context) );
+            if (result == -1)
+            {
+                AX_reg(&context) = DOS_ExtendedError;
+                SET_CFLAG(&context);
+            }
+            else AX_reg(&context) = (WORD)result;
         }
         break;
 
@@ -1680,12 +1630,12 @@
 }
 
 
-void INT21_Init(void)
+BOOL INT21_Init(void)
 {
     if ((DosHeapHandle = GlobalAlloc(GMEM_FIXED,sizeof(struct DosHeap))) == 0)
     {
         fprintf( stderr, "INT21_Init: Out of memory\n");
-        exit(1);
+        return FALSE;
     }
     heap = (struct DosHeap *) GlobalLock(DosHeapHandle);
 
@@ -1693,4 +1643,5 @@
     dpbsegptr = MAKELONG( (int)&heap->dpb - (int)heap, DosHeapHandle );
     heap->InDosFlag = 0;
     strcpy(heap->biosdate, "01/01/80");
+    return TRUE;
 }
diff --git a/miscemu/int2f.c b/miscemu/int2f.c
index 7501c76..e8d0948 100644
--- a/miscemu/int2f.c
+++ b/miscemu/int2f.c
@@ -1,8 +1,11 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 #include "registers.h"
+#include "ldt.h"
 #include "wine.h"
+#include "drive.h"
 #include "msdos.h"
 #include "miscemu.h"
 #include "module.h"
@@ -15,6 +18,7 @@
 #define VXD_BASE 400
 
 static void do_int2f_16(struct sigcontext_struct *context);
+void do_mscdex(struct sigcontext_struct *context);
 
 /**********************************************************************
  *	    INT_Int2fHandler
@@ -30,7 +34,7 @@
         break;
 
     case 0x15: /* mscdex */
-        /* ignore requests */
+        do_mscdex(&context);
         break;
 
     case 0x16:
@@ -128,3 +132,50 @@
         INT_BARF( context, 0x2f );
     }
 }
+
+void do_mscdex(struct sigcontext_struct *context)
+{
+    int drive, count;
+    char *p;
+
+    switch(AL_reg(context))
+    {
+        case 0x00: /* Installation check */
+            /* Count the number of contiguous CDROM drives
+             */
+            for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
+            {
+                if (DRIVE_GetType(drive) == TYPE_CDROM)
+                {
+                    while (DRIVE_GetType(drive + count) == TYPE_CDROM) count++;
+                    break;
+                }
+            }
+
+            BX_reg(context) = count;
+            CX_reg(context) = (drive < MAX_DOS_DRIVES) ? drive : 0;
+            break;
+
+        case 0x0B: /* drive check */
+            AX_reg(context) = (DRIVE_GetType(CX_reg(context)) == TYPE_CDROM);
+            BX_reg(context) = 0xADAD;
+            break;
+
+        case 0x0C: /* get version */
+            BX_reg(context) = 0x020a;
+            break;
+
+        case 0x0D: /* get drive letters */
+            p = PTR_SEG_OFF_TO_LIN(ES_reg(context), BX_reg(context));
+            memset( p, 0, MAX_DOS_DRIVES );
+            for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
+            {
+                if (DRIVE_GetType(drive) == TYPE_CDROM) *p++ = drive;
+            }
+            break;
+
+        default:
+            fprintf(stderr, "Unimplemented MSCDEX function 0x%02.2X.\n", AL_reg(context));
+            break;
+    }
+}
diff --git a/multimedia/audio.c b/multimedia/audio.c
index 4c96809..ce8da4c 100644
--- a/multimedia/audio.c
+++ b/multimedia/audio.c
@@ -321,7 +321,6 @@
 		dprintf_mciwave(stddeb,"WAVE_mciPlay // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
 		mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), 
 			MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
-		exit(0);
 		}
 	return 0;
 }
diff --git a/multimedia/midi.c b/multimedia/midi.c
index 0094115..c571c9c 100644
--- a/multimedia/midi.c
+++ b/multimedia/midi.c
@@ -485,7 +485,9 @@
 		dprintf_midi(stddeb, "MIDI_mciPlay // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
 		mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), 
 			MCIMidiDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
+#if 0
 		exit(1);
+#endif
 		}
 	return 0;
 #else
diff --git a/objects/bitmap.c b/objects/bitmap.c
index 7408f3b..d534d5d 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -75,8 +75,7 @@
 /***********************************************************************
  *           CreateBitmap    (GDI.48)
  */
-HBITMAP CreateBitmap( short width, short height, 
-		      BYTE planes, BYTE bpp, LPSTR bits )
+HBITMAP CreateBitmap( INT width, INT height, UINT planes, UINT bpp, LPVOID bits )
 {
     BITMAPOBJ * bmpObjPtr;
     HBITMAP hbitmap;
@@ -121,7 +120,7 @@
 /***********************************************************************
  *           CreateCompatibleBitmap    (GDI.51)
  */
-HBITMAP CreateCompatibleBitmap( HDC hdc, short width, short height )
+HBITMAP CreateCompatibleBitmap( HDC hdc, INT width, INT height )
 {
     DC * dc;
     dprintf_gdi(stddeb, "CreateCompatibleBitmap: "NPFMT" %dx%d\n", 
@@ -134,7 +133,7 @@
 /***********************************************************************
  *           CreateBitmapIndirect    (GDI.49)
  */
-HBITMAP CreateBitmapIndirect( BITMAP * bmp )
+HBITMAP CreateBitmapIndirect( const BITMAP * bmp )
 {
     return CreateBitmap( bmp->bmWidth, bmp->bmHeight, bmp->bmPlanes,
                          bmp->bmBitsPixel, PTR_SEG_TO_LIN( bmp->bmBits ) );
@@ -310,7 +309,7 @@
 /***********************************************************************
  *           CreateDiscardableBitmap    (GDI.156)
  */
-HBITMAP CreateDiscardableBitmap(HDC hdc, short width, short height)
+HBITMAP CreateDiscardableBitmap(HDC hdc, INT width, INT height)
 {
     dprintf_bitmap(stddeb,"CreateDiscardableBitmap("NPFMT", %d, %d); "
 	   "// call CreateCompatibleBitmap() for now!\n",
diff --git a/objects/brush.c b/objects/brush.c
index 1034c40..0bca76d 100644
--- a/objects/brush.c
+++ b/objects/brush.c
@@ -141,7 +141,7 @@
 /***********************************************************************
  *           CreateBrushIndirect    (GDI.50)
  */
-HBRUSH CreateBrushIndirect( LOGBRUSH * brush )
+HBRUSH CreateBrushIndirect( const LOGBRUSH * brush )
 {
     BRUSHOBJ * brushPtr;
     HBRUSH hbrush = GDI_AllocObject( sizeof(BRUSHOBJ), BRUSH_MAGIC );
@@ -155,7 +155,7 @@
 /***********************************************************************
  *           CreateHatchBrush    (GDI.58)
  */
-HBRUSH CreateHatchBrush( short style, COLORREF color )
+HBRUSH CreateHatchBrush( INT style, COLORREF color )
 {
     LOGBRUSH logbrush = { BS_HATCHED, color, style };
     dprintf_gdi(stddeb, "CreateHatchBrush: %d %06lx\n", style, color );
@@ -194,7 +194,7 @@
 /***********************************************************************
  *           CreateDIBPatternBrush    (GDI.445)
  */
-HBRUSH CreateDIBPatternBrush( HANDLE hbitmap, WORD coloruse )
+HBRUSH CreateDIBPatternBrush( HGLOBAL hbitmap, UINT coloruse )
 {
     LOGBRUSH logbrush = { BS_DIBPATTERN, coloruse, 0 };
     BITMAPINFO *info, *newInfo;
diff --git a/objects/cursoricon.c b/objects/cursoricon.c
index 4098051..7525855 100644
--- a/objects/cursoricon.c
+++ b/objects/cursoricon.c
@@ -227,47 +227,22 @@
 
 
 /**********************************************************************
- *	    CURSORICON_Load
+ *	    CURSORICON_LoadHandler 
  *
- * Load a cursor or icon.
+ * Create a cursor or icon from a resource.
  */
-static HANDLE CURSORICON_Load( HANDLE hInstance, SEGPTR name, int width,
-                               int height, int colors, BOOL fCursor )
+static HANDLE CURSORICON_LoadHandler( HANDLE handle, HINSTANCE hInstance,
+                                      BOOL fCursor )
 {
-    HANDLE handle, hAndBits, hXorBits;
-    HRSRC hRsrc;
+    HANDLE hAndBits, hXorBits;
     HDC hdc;
     int size, sizeAnd, sizeXor;
     POINT hotspot = { 0 ,0 };
     BITMAPOBJ *bmpXor, *bmpAnd;
     BITMAPINFO *bmi, *pInfo;
     CURSORICONINFO *info;
-    CURSORICONDIRENTRY dirEntry;
     char *bits;
 
-    if (!hInstance)  /* OEM cursor/icon */
-    {
-        if (HIWORD(name))  /* Check for '#xxx' name */
-        {
-            char *ptr = PTR_SEG_TO_LIN( name );
-            if (ptr[0] != '#') return 0;
-            if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
-        }
-        return OBM_LoadCursorIcon( LOWORD(name), fCursor );
-    }
-
-    /* Find the best entry in the directory */
-
-    if (!CURSORICON_LoadDirEntry( hInstance, name, width, height,
-                                  colors, fCursor, &dirEntry )) return 0;
-
-    /* Load the resource */
-
-    if (!(hRsrc = FindResource( hInstance,
-                                MAKEINTRESOURCE( dirEntry.icon.wResId ),
-                                fCursor ? RT_CURSOR : RT_ICON ))) return 0;
-    if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
-
     if (fCursor)  /* If cursor, get the hotspot */
     {
         POINT *pt = (POINT *)LockResource( handle );
@@ -289,7 +264,6 @@
         if (pInfo->bmiHeader.biCompression != BI_RGB)
         {
             fprintf(stderr,"Unknown size for compressed icon bitmap.\n");
-            FreeResource( handle );
             free( pInfo );
             return 0;
         }
@@ -304,7 +278,6 @@
     {
         fprintf( stderr, "CURSORICON_Load: Unknown bitmap length %ld!\n",
                  pInfo->bmiHeader.biSize );
-        FreeResource( handle );
         free( pInfo );
         return 0;
     }
@@ -313,7 +286,6 @@
 
     if (!(hdc = GetDC( 0 )))
     {
-        FreeResource( handle );
         free( pInfo );
         return 0;
     }
@@ -351,7 +323,6 @@
     hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader, CBM_INIT,
                                bits, pInfo, DIB_RGB_COLORS );
     ReleaseDC( 0, hdc );
-    FreeResource( handle );
 
     /* Now create the CURSORICONINFO structure */
 
@@ -367,8 +338,10 @@
         DeleteObject( hAndBits );
         return 0;
     }
+
     /* Make it owned by the module */
-    FarSetOwner( handle, (WORD)(DWORD)GetExePtr( hInstance ) );
+    if (hInstance) FarSetOwner( handle, (WORD)(DWORD)GetExePtr(hInstance) );
+
     info = (CURSORICONINFO *)GlobalLock( handle );
     info->ptHotSpot.x   = hotspot.x;
     info->ptHotSpot.y   = hotspot.y;
@@ -388,6 +361,46 @@
     return handle;
 }
 
+/**********************************************************************
+ *	    CURSORICON_Load
+ *
+ * Load a cursor or icon.
+ */
+static HANDLE CURSORICON_Load( HANDLE hInstance, SEGPTR name, int width,
+                               int height, int colors, BOOL fCursor )
+{
+    HANDLE handle,hRet;
+    HRSRC  hRsrc;
+    CURSORICONDIRENTRY dirEntry;
+
+    if (!hInstance)  /* OEM cursor/icon */
+    {
+        if (HIWORD(name))  /* Check for '#xxx' name */
+        {
+            char *ptr = PTR_SEG_TO_LIN( name );
+            if (ptr[0] != '#') return 0;
+            if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
+        }
+        return OBM_LoadCursorIcon( LOWORD(name), fCursor );
+    }
+
+    /* Find the best entry in the directory */
+
+    if (!CURSORICON_LoadDirEntry( hInstance, name, width, height,
+                                  colors, fCursor, &dirEntry )) return 0;
+
+    /* Load the resource */
+
+    if (!(hRsrc = FindResource( hInstance,
+                                MAKEINTRESOURCE( dirEntry.icon.wResId ),
+                                fCursor ? RT_CURSOR : RT_ICON ))) return 0;
+    if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
+
+    hRet = CURSORICON_LoadHandler( handle, hInstance, fCursor );
+    FreeResource(handle);
+    return hRet;
+}
+
 
 /***********************************************************************
  *           CURSORICON_Copy
@@ -485,8 +498,8 @@
 /***********************************************************************
  *           CreateCursor    (USER.406)
  */
-HICON CreateCursor( HANDLE hInstance, INT xHotSpot, INT yHotSpot,
-                    INT nWidth, INT nHeight, LPSTR lpANDbits, LPSTR lpXORbits)
+HCURSOR CreateCursor( HINSTANCE hInstance, INT xHotSpot, INT yHotSpot,
+                      INT nWidth, INT nHeight, LPVOID lpANDbits, LPVOID lpXORbits)
 {
     CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
 
@@ -540,21 +553,37 @@
 /***********************************************************************
  *           CopyIcon    (USER.368)
  */
+#ifdef WINELIB32
+HICON CopyIcon( HICON hIcon )
+{
+    dprintf_icon( stddeb, "CopyIcon: "NPFMT"\n", hIcon );
+    return CURSORICON_Copy( 0, hIcon );
+}
+#else
 HICON CopyIcon( HANDLE hInstance, HICON hIcon )
 {
     dprintf_icon( stddeb, "CopyIcon: "NPFMT" "NPFMT"\n", hInstance, hIcon );
     return CURSORICON_Copy( hInstance, hIcon );
 }
+#endif
 
 
 /***********************************************************************
  *           CopyCursor    (USER.369)
  */
+#ifdef WINELIB32
+HCURSOR CopyCursor( HCURSOR hCursor )
+{
+    dprintf_cursor( stddeb, "CopyCursor: "NPFMT"\n", hCursor );
+    return CURSORICON_Copy( 0, hCursor );
+}
+#else
 HCURSOR CopyCursor( HANDLE hInstance, HCURSOR hCursor )
 {
     dprintf_cursor( stddeb, "CopyCursor: "NPFMT" "NPFMT"\n", hInstance, hCursor );
     return CURSORICON_Copy( hInstance, hCursor );
 }
+#endif
 
 
 /***********************************************************************
@@ -836,10 +865,11 @@
 /***********************************************************************
  *           ClipCursor    (USER.16)
  */
-void ClipCursor( RECT *rect )
+BOOL ClipCursor( RECT *rect )
 {
     if (!rect) SetRectEmpty( &CURSOR_ClipRect );
     else CopyRect( &CURSOR_ClipRect, rect );
+    return TRUE;
 }
 
 
@@ -880,8 +910,35 @@
  */
 WORD GetIconID( HANDLE hResource, DWORD resType )
 {
-    fprintf( stderr, "GetIconId("NPFMT",%ld): empty stub!\n",
-             hResource, resType );
+    CURSORICONDIR *lpDir = LockResource(hResource);
+
+    if (!lpDir || lpDir->idReserved ||
+        ((lpDir->idType != 1) && (lpDir->idType != 2)))
+    {
+        dprintf_cursor(stddeb,"GetIconID: invalid resource directory\n");
+        return 0;
+    }
+
+    dprintf_cursor( stddeb, "GetIconID: hRes="NPFMT", entries=%i\n",
+                    hResource, lpDir->idCount );
+
+    switch(resType)
+    {
+    case 1:  /* cursor */
+        {
+            CURSORDIRENTRY *entry = CURSORICON_FindBestCursor( lpDir,
+                                    SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR );
+            return entry ? entry->wResId : 0;
+        }
+    case 3:  /* icon */
+        {
+            ICONDIRENTRY *entry = CURSORICON_FindBestIcon( lpDir,
+                                          SYSMETRICS_CXICON, SYSMETRICS_CYICON,
+                                          MIN( 16, 1 << screenDepth ) );
+            return entry ? entry->wResId : 0;
+        }
+    }
+    fprintf( stderr, "GetIconID: invalid res type %ld\n", resType );
     return 0;
 }
 
@@ -891,7 +948,12 @@
  */
 HICON LoadIconHandler( HANDLE hResource, BOOL bNew )
 {
-    fprintf( stderr, "LoadIconHandle("NPFMT",%d): empty stub!\n",
-             hResource, bNew );
-    return 0;
+    dprintf_cursor(stddeb,"LoadIconHandler: hRes="NPFMT"\n",hResource);
+
+    if( !bNew )
+      {
+	fprintf(stdnimp,"LoadIconHandler: 2.xx resources are not supported\n");
+        return 0;
+      }
+    return CURSORICON_LoadHandler( hResource, 0, FALSE);
 }
diff --git a/objects/dc.c b/objects/dc.c
index 68e7ff3..27c1303 100644
--- a/objects/dc.c
+++ b/objects/dc.c
@@ -450,7 +450,7 @@
 /***********************************************************************
  *           CreateDC    (GDI.53)
  */
-HDC CreateDC( LPSTR driver, LPSTR device, LPSTR output, LPSTR initData )
+HDC CreateDC( LPCSTR driver, LPCSTR device, LPCSTR output, LPCSTR initData )
 {
     DC * dc;
     HANDLE handle;
diff --git a/objects/dib.c b/objects/dib.c
index 3c02046..26ef98e 100644
--- a/objects/dib.c
+++ b/objects/dib.c
@@ -774,7 +774,7 @@
  *           CreateDIBitmap    (GDI.442)
  */
 HBITMAP CreateDIBitmap( HDC hdc, BITMAPINFOHEADER * header, DWORD init,
-		        LPSTR bits, BITMAPINFO * data, WORD coloruse )
+		        LPVOID bits, BITMAPINFO * data, UINT coloruse )
 {
     HBITMAP handle;
     BOOL fColor;
diff --git a/objects/font.c b/objects/font.c
index b3df1a2..95c8332 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -3,8 +3,7 @@
  *
  * Copyright 1993 Alexandre Julliard
  *
-static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
-*/
+ */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -12,8 +11,8 @@
 #include <X11/Xatom.h>
 #include "font.h"
 #include "metafile.h"
-#include "wine.h"
 #include "callback.h"
+#include "options.h"
 #include "xmalloc.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -65,17 +64,20 @@
   LPSTR ptr;
   int i;
 
-  if( GetPrivateProfileString("fonts", NULL, "*", temp, sizeof(temp), WINE_INI) > 2 ) {
+  if (PROFILE_GetWineIniString( "fonts", NULL, "*", temp, sizeof(temp) ) > 2 )
+  {
     for( ptr = temp, i = 1; strlen(ptr) != 0; ptr += strlen(ptr) + 1 )
       if( strcmp( ptr, "default" ) )
 	FontNames[i++].window = xstrdup( ptr );
     FontSize = i;
 
-    for( i = 1; i < FontSize; i++ ) {
-      GetPrivateProfileString("fonts", FontNames[i].window, "*", temp, sizeof(temp), WINE_INI);
-      FontNames[i].x11 = xstrdup( temp );
+    for( i = 1; i < FontSize; i++ )
+    {
+        PROFILE_GetWineIniString( "fonts", FontNames[i].window, "*",
+                                  temp, sizeof(temp) );
+        FontNames[i].x11 = xstrdup( temp );
     }
-    GetPrivateProfileString("fonts", "default", "*", temp, sizeof(temp), WINE_INI);
+    PROFILE_GetWineIniString( "fonts", "default", "*", temp, sizeof(temp) );
     FontNames[0].x11 = xstrdup( temp );
 
   } else {
@@ -291,7 +293,7 @@
 /***********************************************************************
  *           CreateFontIndirect    (GDI.57)
  */
-HFONT CreateFontIndirect( LOGFONT * font )
+HFONT CreateFontIndirect( const LOGFONT * font )
 {
     FONTOBJ * fontPtr;
     HFONT hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
@@ -307,10 +309,10 @@
 /***********************************************************************
  *           CreateFont    (GDI.56)
  */
-HFONT CreateFont( int height, int width, int esc, int orient, int weight,
+HFONT CreateFont( INT height, INT width, INT esc, INT orient, INT weight,
 		  BYTE italic, BYTE underline, BYTE strikeout, BYTE charset,
 		  BYTE outpres, BYTE clippres, BYTE quality, BYTE pitch,
-		  LPSTR name )
+		  LPCSTR name )
 {
     LOGFONT logfont = { height, width, esc, orient, weight, italic, underline,
 		    strikeout, charset, outpres, clippres, quality, pitch, };
@@ -493,7 +495,7 @@
 /***********************************************************************
  *           GetTextExtent    (GDI.91)
  */
-DWORD GetTextExtent( HDC hdc, LPSTR str, short count )
+DWORD GetTextExtent( HDC hdc, LPCSTR str, short count )
 {
     SIZE size;
     if (!GetTextExtentPoint( hdc, str, count, &size )) return 0;
@@ -504,7 +506,7 @@
 /***********************************************************************
  *           GetTextExtentPoint    (GDI.471)
  */
-BOOL GetTextExtentPoint( HDC hdc, LPSTR str, short count, LPSIZE size )
+BOOL GetTextExtentPoint( HDC hdc, LPCSTR str, short count, LPSIZE size )
 {
     int dir, ascent, descent;
     XCharStruct info;
@@ -802,7 +804,7 @@
 /*************************************************************************
  *				EnumFontFamilies	[GDI.330]
  */
-int EnumFontFamilies(HDC hDC, LPSTR lpszFamily, FARPROC lpEnumFunc, LPSTR lpData)
+int EnumFontFamilies(HDC hDC, LPSTR lpszFamily, FONTENUMPROC lpEnumFunc, LPARAM lpData)
 {
   HANDLE       	hLog;
   HANDLE       	hMet;
@@ -815,7 +817,7 @@
   int	       	nRet = 0;
   int	       	i;
   
-  dprintf_font(stddeb,"EnumFontFamilies("NPFMT", %p, %08lx, %p)\n",
+  dprintf_font(stddeb,"EnumFontFamilies("NPFMT", %p, %08lx, %08lx)\n",
 	       hDC, lpszFamily, (DWORD)lpEnumFunc, lpData);
   if (lpEnumFunc == 0) return 0;
   hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT) );
@@ -859,7 +861,7 @@
     nRet = CallEnumFontFamProc( lpEnumFunc,
 			       GDI_HEAP_SEG_ADDR(hLog),
 			       GDI_HEAP_SEG_ADDR(hMet),
-			       0, (LONG)lpData );
+			       0, lpData );
     if (nRet == 0) {
       dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
       break;
@@ -874,7 +876,7 @@
  *				GetRasterizerCaps	[GDI.313]
  */
 
-BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, WORD cbNumBytes)
+BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
 {
   /* This is not much more than a dummy */
   RASTERIZER_STATUS rs;
@@ -887,9 +889,8 @@
 
 /*************************************************************************
  *             GetKerningPairs      [GDI.332]
- *  FIXME: The last parameter is actually LPKERNINGPAIR
  */
-int GetKerningPairs(WORD hDC,int cBufLen,LPVOID lpKerningPairs)
+int GetKerningPairs(HDC hDC,int cBufLen,LPKERNINGPAIR lpKerningPairs)
 {
 	/* Wine fonts are ugly and don't support kerning :) */
 	return 0;
diff --git a/objects/palette.c b/objects/palette.c
index f49f066..1945bdf 100644
--- a/objects/palette.c
+++ b/objects/palette.c
@@ -142,10 +142,11 @@
 /***********************************************************************
  *           AnimatePalette          (GDI.367)
  */
-void AnimatePalette(HPALETTE hPal, UINT StartIndex, UINT NumEntries,
+BOOL AnimatePalette(HPALETTE hPal, UINT StartIndex, UINT NumEntries,
 		    LPPALETTEENTRY PaletteColors)
 {
     fprintf(stdnimp,"AnimatePalette: empty stub! \n");
+    return TRUE;
 }
 
 /***********************************************************************
diff --git a/objects/pen.c b/objects/pen.c
index adf02e6..13c2f80 100644
--- a/objects/pen.c
+++ b/objects/pen.c
@@ -13,7 +13,7 @@
 /***********************************************************************
  *           CreatePen    (GDI.61)
  */
-HPEN CreatePen( short style, short width, COLORREF color )
+HPEN CreatePen( INT style, INT width, COLORREF color )
 {
     LOGPEN logpen = { style, { width, 0 }, color };
     dprintf_gdi(stddeb, "CreatePen: %d %d %06lx\n", style, width, color );
diff --git a/objects/region.c b/objects/region.c
index 73adc51..13b3799 100644
--- a/objects/region.c
+++ b/objects/region.c
@@ -220,7 +220,7 @@
 /***********************************************************************
  *           CreateEllipticRgn    (GDI.54)
  */
-HRGN CreateEllipticRgn( short left, short top, short right, short bottom )
+HRGN CreateEllipticRgn( INT left, INT top, INT right, INT bottom )
 {
     return CreateRoundRectRgn( left, top, right, bottom,
                                right-left, bottom-top );
@@ -402,7 +402,7 @@
 /***********************************************************************
  *           CombineRgn    (GDI.451)
  */
-int CombineRgn( HRGN hDest, HRGN hSrc1, HRGN hSrc2, short mode )
+INT CombineRgn( HRGN hDest, HRGN hSrc1, HRGN hSrc2, INT mode )
 {
     RGNOBJ *destObj, *src1Obj, *src2Obj;
     
diff --git a/objects/text.c b/objects/text.c
index 3b6ec22..6b4f8e6 100644
--- a/objects/text.c
+++ b/objects/text.c
@@ -3,8 +3,8 @@
  *
  * Copyright 1993, 1994 Alexandre Julliard
  *
-static char Copyright[] = "Copyright  Alexandre Julliard, 1993, 1994";
-*/
+ */
+
 #include <stdlib.h>
 #include <X11/Xatom.h>
 #include "windows.h"
@@ -31,8 +31,8 @@
 static int prefix_offset;
 
 
-static char *TEXT_NextLine(HDC hdc, char *str, int *count, char *dest, 
-			   int *len, int width, WORD format)
+static const char *TEXT_NextLine( HDC hdc, const char *str, int *count,
+                                  char *dest, int *len, int width, WORD format)
 {
     /* Return next line of text from a string.
      * 
@@ -184,10 +184,10 @@
 /***********************************************************************
  *           DrawText    (USER.85)
  */
-int DrawText( HDC hdc, LPSTR str, int count, LPRECT rect, WORD flags )
+int DrawText( HDC hdc, LPCSTR str, int count, LPRECT rect, WORD flags )
 {
     SIZE size;
-    char *strPtr;
+    const char *strPtr;
     static char line[1024];
     int len, lh;
     int prefix_x = 0;
diff --git a/rc/winerc.c b/rc/winerc.c
index f5ec380..7642ff2 100644
--- a/rc/winerc.c
+++ b/rc/winerc.c
@@ -4,6 +4,7 @@
  *
  */
 
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/stat.h>
@@ -53,6 +54,7 @@
 {  
 	extern int yydebug;
 	extern char* optarg;
+	char* tmpc;
 	int optc,lose,ret,binary;
 	lose=binary=0;
 	while((optc=getopt(argc,argv,"bcdp:vo:"))!=EOF)
@@ -65,7 +67,12 @@
 					 setbuf(stdout,0);
 					 setbuf(stderr,0);
 					break;
-			case 'p':prefix=optarg;break;
+			case 'p':prefix=strdup(optarg);
+					 if(!isalpha(*prefix))*prefix='_';
+					 for(tmpc=prefix;*tmpc;tmpc++)
+					  if( !isalnum(*tmpc) && *tmpc!='_')
+					   *tmpc='_';
+					break;
 			case 'c':constant=1;break;
 			case 'v':verbose=1;
 					 setbuf(stderr,0);
@@ -105,7 +112,7 @@
 		if(i%16==0)fputc('\n',code);
 		fprintf(code,"%3d,",c);
 	}
-	fprintf(code,"\n0}\nint _Aplication_resources_size=%d;\n",i);
+	fprintf(code,"\n  0};\nint _Application_resources_size=%d;\n",i);
 	return 0;
 }
 
diff --git a/tools/makehtml.pl b/tools/makehtml.pl
new file mode 100644
index 0000000..cfd8408
--- /dev/null
+++ b/tools/makehtml.pl
@@ -0,0 +1,80 @@
+#!/usr/bin/perl
+open(APIW,"./apiw.index");
+while(<APIW>)
+{
+  ($func,$link)=split /:/;
+  chop $link;
+  $link=~m/(\d*)/;
+  $apiw{$func}="http://www.willows.com/apiw/chapter$1/p$link.html";
+}
+close(APIW);
+
+open(WINDOWS,"../include/windows.h");
+while(<WINDOWS>) { add_func($_) if /AccessResource/../wvsprintf/; }
+close(WINDOWS);
+open(TOOLHELP,"../include/toolhelp.h");
+while(<TOOLHELP>) { add_func($_) if /GlobalInfo/../MemoryWrite/; }
+close(TOOLHELP);
+open(COMMDLG,"../include/commdlg.h");
+while(<COMMDLG>) { add_func($_) if /ChooseColor/../ReplaceText/; }
+close(COMMDLG);
+
+print "<html><body>\n";
+
+print "<h2>Windows API Functions</h2>\n";
+print "The following API functions were found by searching windows.h,\n";
+print "toolhelp.h, and commdlg.h.  Where possible, help links pointing\n";
+print "to www.willows.com are included.<p>\n";
+print "<table>\n";
+print "<th>Help-link</th><th></th><th></th><th align=left>Function</th>\n";
+foreach $func (sort(keys %funcs))
+{
+  $funcs{$func}=~m/(.*) +(\w*)(\(.*)/;
+  print "<tr>\n<td>";
+  if($apiw{$2})
+  {
+    print "<center><a href=\"$apiw{$2}\">APIW</a></center>";
+    $impl{$2}=1;
+    $impl++;
+  }
+  $numfuncs++;
+  print "</td>\n";
+  print "<td></td>\n";
+  print "<td>$1</td>\n";
+  print "<td>$2$3</td>\n";
+  print "</tr>\n";
+}
+print "</table><p>\n";
+print "(Approximately ",sprintf("%3.1f",$impl/(1.0*$numfuncs)*100.0),
+      "% of the functions above are in the APIW standard.)<p>\n";
+
+print "<hr>\n";
+print "<h2>Unimplemented APIW functions</h2><p>\n";
+print "Here's a list of the API functions in the APIW standard which were <b>not</b> found\n";
+print "in windows.h, commdlg.h, or toolhelp.h:<p>\n";
+foreach $func (sort (keys %apiw))
+{
+  if(!$impl{$func})
+  {
+    print "<a href=\"$apiw{$func}\">$func</a>\n";
+    $unimpl++;
+  }
+  $numapiw++;
+}
+print "<p>(This comprises approximately ",sprintf("%3.1f",$unimpl/(1.0*$numapiw)*100.0),
+      "% of the APIW.)\n";
+
+print "</body></html>\n";
+
+sub add_func
+{
+  $line=shift;
+  chop $line; 
+  $line=~s/\s+/ /g;
+  ($func)=$line=~m/ (\w*)\(/;
+  if($func)
+  {
+    while($funcs{$func}) { $func.=" "; }
+    $funcs{$func}=$line;
+  }
+}
diff --git a/win32/Makefile.in b/win32/Makefile.in
index 9851ec6..2300885 100644
--- a/win32/Makefile.in
+++ b/win32/Makefile.in
@@ -13,10 +13,13 @@
 	memory.c \
 	newfns.c \
 	object_mgt.c \
+	param32.c \
 	process.c \
 	resource.c \
+	string32.c \
 	thread.c \
 	time.c \
+	user32.c \
 	winprocs.c
 
 all: $(MODULE).o
diff --git a/win32/newfns.c b/win32/newfns.c
index 2f2fe44..0192cb0 100644
--- a/win32/newfns.c
+++ b/win32/newfns.c
@@ -8,6 +8,7 @@
 at a later date. */
 
 #include <stdio.h>
+#include "module.h"
 #include "windows.h"
 #include "winerror.h"
 #include "kernel32.h"
@@ -31,6 +32,7 @@
  *           GetProcAddress		(KERNEL32.257)
  *
  */
+ /* FIXME: This is currently not used, see WIN32_GetProcAddress */
 WINAPI FARPROC W32_GetProcAddress(HMODULE hModule,
 			      LPCSTR lpszProc)
 {
@@ -45,3 +47,12 @@
 	return RELAY32_GetEntryPoint(modulename, (char *) NULL, (int) lpszProc);
 }
 
+/***********************************************************************
+ *          WinHelpA           (USER32.578)
+ */
+BOOL WIN32_WinHelpA(HWND hWnd,LPCSTR lpszHelp,UINT uCommand, DWORD dwData)
+{
+	/* Should do parameter conversion here, but WinHelp is not working,
+	   anyways */
+	return WinHelp(hWnd,lpszHelp,uCommand,dwData);
+}
diff --git a/win32/param32.c b/win32/param32.c
new file mode 100644
index 0000000..d2c10f2
--- /dev/null
+++ b/win32/param32.c
@@ -0,0 +1,30 @@
+/*
+ * Win32 relay functions
+ * The implementations here perform only parameter conversions, and
+ * call the Win16 counterparts
+ *
+ * Copyright 1996 Martin von Loewis
+ */
+
+#include <stdio.h>
+#include "windows.h"
+#include "winerror.h"
+#include "struct32.h"
+#include "stddebug.h"
+#include "debug.h"
+
+void PARAM32_POINT32to16(const POINT32* p32,POINT* p16)
+{
+	p16->x = p32->x;
+	p16->y = p32->y;
+}
+
+/****************************************************************
+ *           MoveToEx          (GDI32.254)
+ */
+BOOL WIN32_MoveToEx(HDC hdc,int x,int y,POINT32* p32)
+{
+	POINT p;
+	PARAM32_POINT32to16(p32,&p);
+	return MoveToEx(hdc,x,y,&p);
+}
diff --git a/win32/process.c b/win32/process.c
index b8e244d..a7a86c8 100644
--- a/win32/process.c
+++ b/win32/process.c
@@ -5,6 +5,7 @@
  */
 
 #include <stdio.h>
+#include <string.h>
 #include <unistd.h>
 #include "windows.h"
 #include "winerror.h"
diff --git a/win32/resource.c b/win32/resource.c
index 5add440..2e2dd75 100644
--- a/win32/resource.c
+++ b/win32/resource.c
@@ -2,6 +2,7 @@
  * Win32 Resources
  *
  * Copyright 1995 Thomas Sandford
+ * Copyright 1996 Martin von Loewis
  *
  * Based on the Win16 resource handling code in loader/resource.c
  * Copyright 1993 Robert J. Amstadt
@@ -16,10 +17,13 @@
 #include "kernel32.h"
 #include "pe_image.h"
 #include "handle32.h"
+#include "libres.h"
 #include "resource32.h"
+#include "stackframe.h"
 #include "neexe.h"
 #include "accel.h"
 #include "xmalloc.h"
+#include "string32.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -38,19 +42,31 @@
  *
  */
 PIMAGE_RESOURCE_DIRECTORY GetResDirEntry(PIMAGE_RESOURCE_DIRECTORY resdirptr,
-					 LPCSTR name,
+					 LPCWSTR name,
 					 DWORD root)
 {
     int entrynum;
     PIMAGE_RESOURCE_DIRECTORY_ENTRY entryTable;
+	int namelen;
 
     if (HIWORD(name)) {
     /* FIXME: what about #xxx names? */
 	entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (
 			(BYTE *) resdirptr + 
                         sizeof(IMAGE_RESOURCE_DIRECTORY));
+	namelen = STRING32_lstrlenW(name);
 	for (entrynum = 0; entrynum < resdirptr->NumberOfNamedEntries; entrynum++)
-	    /* do what??? */ ;
+	{
+		PIMAGE_RESOURCE_DIR_STRING_U str =
+		(PIMAGE_RESOURCE_DIR_STRING_U) (root + 
+			(entryTable[entrynum].Name & 0x7fffffff));
+		if(namelen != str->Length)
+			continue;
+		if(STRING32_lstrcmpniW(name,str->NameString,str->Length)==0)
+			return (PIMAGE_RESOURCE_DIRECTORY) (
+				root +
+				(entryTable[entrynum].OffsetToData & 0x7fffffff));
+	}
 	return NULL;
     } else {
 	entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (
@@ -200,11 +216,11 @@
 /**********************************************************************
  *			LoadAccelerators	[USER.177]
 */
-HANDLE LoadAccelerators32(HINSTANCE instance, LPCTSTR lpTableName)
+HANDLE32 WIN32_LoadAcceleratorsW(HINSTANCE instance, LPCWSTR lpTableName)
 {
-    HANDLE 	hAccel;
-    HANDLE 	rsc_mem;
-    HRSRC hRsrc;
+    HANDLE32 	hAccel;
+    HANDLE32 	rsc_mem;
+    HANDLE32 hRsrc;
     BYTE 	*lp;
     ACCELHEADER	*lpAccelTbl;
     int 	i, n;
@@ -216,11 +232,11 @@
         dprintf_accel( stddeb, "LoadAccelerators: "NPFMT" %04x\n",
                        instance, LOWORD(lpTableName) );
 
-    if (!(hRsrc = FindResource( instance, lpTableName, RT_ACCELERATOR )))
+    if (!(hRsrc = FindResource32( instance, lpTableName, RT_ACCELERATOR )))
       return 0;
-    if (!(rsc_mem = LoadResource( instance, hRsrc ))) return 0;
+    if (!(rsc_mem = LoadResource32( instance, hRsrc ))) return 0;
 
-    lp = (BYTE *)LockResource(rsc_mem);
+    lp = (BYTE *)LockResource32(rsc_mem);
     n = SizeofResource( instance, hRsrc ) / sizeof(ACCELENTRY);
     hAccel = GlobalAlloc(GMEM_MOVEABLE, 
     	sizeof(ACCELHEADER) + (n + 1)*sizeof(ACCELENTRY));
@@ -243,12 +259,20 @@
     FreeResource( rsc_mem );
     return hAccel;
 }
+
+HANDLE32 WIN32_LoadAcceleratorsA(HINSTANCE instance, LPCSTR lpTableName)
+{
+	LPWSTR uni=STRING32_DupAnsiToUni(lpTableName);
+	HANDLE32 result=WIN32_LoadAcceleratorsW(instance,uni);
+	free(uni);
+	return result;
+}
 
 /**********************************************************************
  *					LoadString
  */
 int
-LoadString32(HINSTANCE instance, DWORD resource_id, LPTSTR buffer, int buflen)
+WIN32_LoadStringW(HINSTANCE instance, DWORD resource_id, LPWSTR buffer, int buflen)
 {
     HANDLE32 hmem, hrsrc;
     WCHAR *p;
@@ -292,10 +316,10 @@
  *					LoadStringA
  */
 int
-LoadStringA32(HINSTANCE instance, DWORD resource_id, LPSTR buffer, int buflen)
+WIN32_LoadStringA(HINSTANCE instance, DWORD resource_id, LPSTR buffer, int buflen)
 {
     WCHAR *buffer2 = xmalloc(buflen*2);
-    int retval = LoadString32(instance, resource_id, buffer2, buflen);
+    int retval = WIN32_LoadStringW(instance, resource_id, buffer2, buflen);
 
     while (*buffer2) 
 	*buffer++ = (char) *buffer2++;
@@ -317,7 +341,7 @@
 /**********************************************************************
  *	    LoadBitmapW
  */
-HBITMAP LoadBitmapW32( HANDLE instance, LPCTSTR name )
+HBITMAP WIN32_LoadBitmapW( HANDLE instance, LPCTSTR name )
 {
     HBITMAP hbitmap = 0;
     HDC hdc;
@@ -347,7 +371,105 @@
 /**********************************************************************
  *	    LoadBitmapA
  */
-HBITMAP LoadBitmapA32( HANDLE instance, LPCTSTR name )
+HBITMAP WIN32_LoadBitmapA( HANDLE instance, LPCTSTR name )
 {
-    return LoadBitmapW32(instance, name);
+    HBITMAP res;
+    if(!HIWORD(name))
+        res = WIN32_LoadBitmapW(instance,name);
+    else{
+        LPWSTR uni=STRING32_DupAnsiToUni(name);
+        res=WIN32_LoadBitmapW(instance,uni);
+        free(uni);
+    }
+    return res;
+}
+
+/**********************************************************************
+ *      WIN32_ParseMenu
+ *      LoadMenu helper function
+ */
+BYTE* WIN32_ParseMenu(HMENU hMenu,BYTE *it)
+{
+    char entry[200]; /* buffer for ANSI names */
+	int bufsize=100;
+	int len;
+	WORD flags;
+	WORD wMenuID;
+	WCHAR *utext;
+	do{
+		flags=*(WORD*)it;
+		it+=sizeof(WORD);
+		/* POPUP entries have no ID, but a sub menu */
+		if(flags & MF_POPUP)
+		{
+			wMenuID = CreatePopupMenu();
+			len = STRING32_lstrlenW(it);
+			utext = it;
+			it += sizeof(WCHAR)*(len+1);
+			it = WIN32_ParseMenu(wMenuID,it);
+		} else {
+			wMenuID=*(WORD*)it;
+			it+=sizeof(WORD);
+			utext = it;
+			len = STRING32_lstrlenW(it);
+			it += sizeof(WCHAR)*(len+1);
+			if(!wMenuID && !*utext)
+				flags |= MF_SEPARATOR;
+		}
+		if(len>=bufsize) continue;  /* hack hack */
+		STRING32_UniToAnsi(entry,utext);
+		AppendMenu(hMenu,flags,wMenuID,MAKE_SEGPTR(entry));
+	}while(!(flags & MF_END));
+	return it;
+}
+
+/*****************************************************************
+ *        LoadMenuIndirectW         (USER32.371)
+ */
+HMENU WIN32_LoadMenuIndirectW(void *menu)
+{
+	BYTE *it=menu;
+	HMENU hMenu = CreateMenu();
+	/*skip menu header*/
+	if(*(DWORD*)it)
+		fprintf(stderr,"Unknown menu header\n");
+	it+=2*sizeof(WORD);
+	WIN32_ParseMenu(hMenu,it);
+	return hMenu;
+}
+
+/*****************************************************************
+ *        LoadMenuW                 (USER32.372)
+ */
+HMENU WIN32_LoadMenuW(HANDLE instance, LPCWSTR name)
+{
+	HANDLE32 hrsrc;
+	hrsrc=FindResource32(instance,name,RT_MENU);
+	if(!hrsrc)return 0;
+	return WIN32_LoadMenuIndirectW(LoadResource32(instance, hrsrc));
+}
+
+/*****************************************************************
+ *        LoadMenuIndirectA         (USER32.370)
+ */
+HMENU WIN32_LoadMenuIndirectA(void *menu)
+{
+	fprintf(stderr,"WIN32_LoadMenuIndirectA not implemented\n");
+	return 0;
+}
+
+/*****************************************************************
+ *        LoadMenuA                 (USER32.370)
+ */
+HMENU WIN32_LoadMenuA(HANDLE instance,LPCSTR name)
+{
+	HMENU res;
+	if(!HIWORD(name))
+		res = WIN32_LoadMenuW(instance,name);
+	else{
+		LPWSTR uni=STRING32_DupAnsiToUni(name);
+		res=WIN32_LoadMenuW(instance,uni);
+		free(uni);
+	}
+	return res;
 }
diff --git a/win32/string32.c b/win32/string32.c
new file mode 100644
index 0000000..e9af8cb
--- /dev/null
+++ b/win32/string32.c
@@ -0,0 +1,94 @@
+/*
+ * Unicode string management
+ *
+ * Copyright 1996 Martin von Loewis
+ *
+ * Conversion between Unicode and ISO-8859-1 is inherently lossy,
+ * so the conversion code should be called only if it does not matter
+ * 
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "string32.h"
+#include "xmalloc.h"
+
+int STRING32_UniLen(LPWSTR s)
+{
+	int i;
+	for(i=0;*s;s++);
+		i++;
+	return i;
+}
+
+void STRING32_UniToAnsi(LPSTR dest,LPCWSTR src)
+{
+	static int have_warned=0;
+	while(*src)
+	{
+		if(*src>255 && !have_warned)
+		{
+			fprintf(stderr,"Cannot deal with non-ANSI characters\n");
+			have_warned=1;
+		}
+		*dest++=*src++;
+	}
+	/* copy the terminator */
+	*dest = *src;
+}
+
+void STRING32_AnsiToUni(LPWSTR dest,LPCSTR src)
+{
+	while(*src)
+		*dest++=*src++;
+	*dest = *src;
+}
+
+LPSTR STRING32_DupUniToAnsi(LPWSTR src)
+{
+	LPSTR dest=xmalloc(STRING32_UniLen(src)+1);
+	STRING32_UniToAnsi(dest,src);
+	return dest;
+}
+
+LPWSTR STRING32_DupAnsiToUni(LPSTR src)
+{
+	LPWSTR dest=xmalloc(2*strlen(src)+2);
+	STRING32_AnsiToUni(dest,src);
+	return dest;
+}
+
+DWORD STRING32_lstrlenW(LPCWSTR str)
+{
+	int len;
+	for(len=0;*str;str++)
+		len++;
+	return len;
+}
+
+/* not an API function */
+
+WCHAR STRING32_tolowerW(WCHAR c)
+{
+	/* FIXME: Unicode */
+	return tolower(c);
+}
+
+LPWSTR STRING32_lstrcmpniW(LPCWSTR a,LPCWSTR b,DWORD len)
+{
+	while(len--)
+	{
+		WCHAR c1,c2;
+		c1 = STRING32_tolowerW(*a);
+		c2 = STRING32_tolowerW(*b);
+		if(c1<c2)return -1;
+		if(c1>c2)return 1;
+		if(c1==0 && c2==0)return 0;
+		if(c1==0)return -1;
+		if(c2==0)return 1;
+		a++;
+		b++;
+	}
+	return 0;
+}
diff --git a/misc/user32.c b/win32/user32.c
similarity index 81%
rename from misc/user32.c
rename to win32/user32.c
index 5097b8c..d3b2a4c 100644
--- a/misc/user32.c
+++ b/win32/user32.c
@@ -14,6 +14,7 @@
 #include "alias.h"
 #include "stackframe.h"
 #include "xmalloc.h"
+#include "struct32.h"
 
 /* Structure copy functions */
 static void MSG16to32(MSG *msg16,struct WIN32_MSG *msg32)
@@ -38,6 +39,22 @@
 	msg16->pt.y=msg32->pt.y;
 }
 
+void USER32_RECT32to16(const RECT32* r32,RECT *r16)
+{
+	r16->left = r32->left;
+	r16->right = r32->right;
+	r16->top = r32->top;
+	r16->bottom = r32->bottom;
+}
+
+void USER32_RECT16to32(const RECT* r16,RECT32 *r32)
+{
+	r32->left = r16->left;
+	r32->right = r16->right;
+	r32->top = r16->top;
+	r32->bottom = r16->bottom;
+}
+
 /***********************************************************************
  *           RegisterClassA      (USER32.426)
  */
@@ -195,3 +212,38 @@
     GlobalFree(titleh);
     return retval;
 }
+
+/***********************************************************************
+ *         InvalidateRect           (USER32.327)
+ */
+BOOL USER32_InvalidateRect(HWND hWnd,const RECT32 *lpRect,BOOL bErase)
+{
+	RECT r;
+	USER32_RECT32to16(lpRect,&r);
+	InvalidateRect(hWnd,&r,bErase);
+	/* FIXME: Return value */
+	return 0;
+}
+
+/***********************************************************************
+ *          DrawTextA                (USER32.163)
+ */
+int USER32_DrawTextA(HDC hdc,LPCSTR lpStr,int count,RECT32* r32,UINT uFormat)
+{
+	RECT r;
+	USER32_RECT32to16(r32,&r);
+	return DrawText(hdc,lpStr,count,&r,uFormat);
+}
+
+/***********************************************************************
+ *          GetClientRect            (USER32.219)
+ */
+BOOL USER32_GetClientRect(HWND hwnd,RECT32 *r32)
+{
+	RECT r;
+	GetClientRect(hwnd,&r);
+	USER32_RECT16to32(&r,r32);
+	/* FIXME: return value */
+	return 0;
+}
+
diff --git a/win32/winprocs.c b/win32/winprocs.c
index 1d9d5a2..9b2d364 100644
--- a/win32/winprocs.c
+++ b/win32/winprocs.c
@@ -8,6 +8,9 @@
 
 #include <stdio.h>
 #include "windows.h"
+
+#ifndef WINELIB32
+
 #include "winerror.h"
 #include "kernel32.h"
 #include "wincon.h"
@@ -32,6 +35,25 @@
     }
 }
 
+extern LRESULT AboutDlgProc(HWND,UINT,WPARAM,LPARAM);
+extern LRESULT ButtonWndProc(HWND,UINT,WPARAM,LPARAM);
+extern LRESULT ColorDlgProc(HWND,UINT,WPARAM,LPARAM);
+extern LRESULT ComboBoxWndProc(HWND,UINT,WPARAM,LPARAM);
+extern LRESULT DesktopWndProc(HWND,UINT,WPARAM,LPARAM);
+extern LRESULT EditWndProc(HWND,UINT,WPARAM,LPARAM);
+extern LRESULT FileOpenDlgProc(HWND,UINT,WPARAM,LPARAM);
+extern LRESULT FileSaveDlgProc(HWND,UINT,WPARAM,LPARAM);
+extern LRESULT FindTextDlgProc(HWND,UINT,WPARAM,LPARAM);
+extern LRESULT ListBoxWndProc(HWND,UINT,WPARAM,LPARAM);
+extern LRESULT MDIClientWndProc(HWND,UINT,WPARAM,LPARAM);
+extern LRESULT PopupMenuWndProc(HWND,UINT,WPARAM,LPARAM);
+extern LRESULT PrintDlgProc(HWND,UINT,WPARAM,LPARAM);
+extern LRESULT PrintSetupDlgProc(HWND,UINT,WPARAM,LPARAM);
+extern LRESULT ReplaceTextDlgProc(HWND,UINT,WPARAM,LPARAM);
+extern LRESULT ScrollBarWndProc(HWND,UINT,WPARAM,LPARAM);
+extern LRESULT StaticWndProc(HWND,UINT,WPARAM,LPARAM);
+extern LRESULT SystemMessageBoxProc(HWND,UINT,WPARAM,LPARAM);
+
 LRESULT USER32_DefWindowProcA(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam)
 
 {
@@ -238,4 +260,4 @@
     else
 	return ComboLBoxWndProc((HWND)hwnd, msg, wParam, lParam);
 }
-
+#endif
diff --git a/windows/alias.c b/windows/alias.c
index 59d25ce..df87319 100644
--- a/windows/alias.c
+++ b/windows/alias.c
@@ -48,17 +48,17 @@
     if (Wine)
     {
         whash=ALIAS_LocateHash(Wine);
-	recno=AliasTable[whash].used?AliasTable[whash].used:0;
+	recno=AliasTable[whash].used?AliasTable[whash].recno:0;
     }
     if (Win16)
     {
         w16hash=ALIAS_LocateHash(Win16);
-	recno=AliasTable[w16hash].used?AliasTable[w16hash].used:0;
+	recno=AliasTable[w16hash].used?AliasTable[w16hash].recno:0;
     }
     if (Win32)
     {
         w32hash=ALIAS_LocateHash(Win32);
-        recno=AliasTable[w32hash].used?AliasTable[w32hash].used:0;
+        recno=AliasTable[w32hash].used?AliasTable[w32hash].recno:0;
     }
     if (!recno)
     {
diff --git a/windows/caret.c b/windows/caret.c
index 8cf00ca..983cdee 100644
--- a/windows/caret.c
+++ b/windows/caret.c
@@ -54,7 +54,7 @@
 	else
 	    hBrush = CreatePatternBrush(Caret.bitmap);
 	SelectObject(hdc, (HANDLE)hBrush);
-	SetROP2(hdc, R2_XORPEN);
+	SetROP2(hdc, R2_NOTXORPEN);
 	rgn = CreateRectRgn(Caret.x, Caret.y, 
 			    Caret.x + Caret.width,
 			    Caret.y + Caret.height);
@@ -116,9 +116,9 @@
  *               CreateCaret          (USER.163)
  */
 
-void CreateCaret(HWND hwnd, HBITMAP bitmap, short width, short height)
+BOOL CreateCaret(HWND hwnd, HBITMAP bitmap, INT width, INT height)
 {
-    if (!hwnd) return;
+    if (!hwnd) return FALSE;
 
 
     /* if cursor already exists, destroy it */
@@ -157,6 +157,7 @@
 
     dprintf_caret(stddeb,"CreateCaret: hwnd="NPFMT", timerid=%d\n", 
 		  hwnd, Caret.timerid);
+    return TRUE;
 }
    
 
diff --git a/windows/defdlg.c b/windows/defdlg.c
index 4f152fb..90a0a6d 100644
--- a/windows/defdlg.c
+++ b/windows/defdlg.c
@@ -122,9 +122,6 @@
     if (!wndPtr) return 0;
     dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
 
-    dprintf_dialog(stddeb, "DefDlgProc: "NPFMT" %04x %ld %08lx\n", 
-		   hwnd, msg, (DWORD)wParam, lParam );
-
     dlgInfo->msgResult = 0;
     if (dlgInfo->dlgProc)
     {
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 42aad58..21acb8d 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -138,15 +138,27 @@
 
     case WM_WINDOWPOSCHANGED:
 	{
+	    /*  Note: Windoze uses unknown SWP flags 0x1000 and 0x0800 to
+	     *        decide whether to send WM_MOVE or/and WM_SIZE respectively 
+	     */
+
 	    WINDOWPOS * winPos = (WINDOWPOS *)PTR_SEG_TO_LIN(lParam);
+	    WPARAM	wp     = SIZE_RESTORED;
+
 	    if (!(winPos->flags & SWP_NOMOVE))
 		SendMessage( hwnd, WM_MOVE, 0,
 		             MAKELONG( wndPtr->rectClient.left,
 				       wndPtr->rectClient.top ));
 	    if (!(winPos->flags & SWP_NOSIZE))
-		SendMessage( hwnd, WM_SIZE, SIZE_RESTORED,
-		   MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
-			    wndPtr->rectClient.bottom-wndPtr->rectClient.top));
+		 {
+	       	   if( wndPtr->dwStyle & WS_MAXIMIZE ) wp = SIZE_MAXIMIZED;
+		   else if(wndPtr->dwStyle & WS_MINIMIZE ) wp = SIZE_MINIMIZED;
+
+		   SendMessage( hwnd, WM_SIZE, wp, 
+			        MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
+			                 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
+
+                 }
 	    return 0;
 	}
 
diff --git a/windows/dialog.c b/windows/dialog.c
index 1ed5fe1..8a982b4 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -201,7 +201,7 @@
  *           CreateDialog   (USER.89)
  */
 HWND CreateDialog( HINSTANCE hInst, SEGPTR dlgTemplate,
-		   HWND owner, WNDPROC dlgProc )
+		   HWND owner, DLGPROC dlgProc )
 {
     return CreateDialogParam( hInst, dlgTemplate, owner, dlgProc, 0 );
 }
@@ -211,7 +211,7 @@
  *           CreateDialogParam   (USER.241)
  */
 HWND CreateDialogParam( HINSTANCE hInst, SEGPTR dlgTemplate,
-		        HWND owner, WNDPROC dlgProc, LPARAM param )
+		        HWND owner, DLGPROC dlgProc, LPARAM param )
 {
     HWND hwnd = 0;
     HRSRC hRsrc;
@@ -234,7 +234,7 @@
  *           CreateDialogIndirect   (USER.219)
  */
 HWND CreateDialogIndirect( HINSTANCE hInst, SEGPTR dlgTemplate,
-			   HWND owner, WNDPROC dlgProc )
+			   HWND owner, DLGPROC dlgProc )
 {
     return CreateDialogIndirectParam( hInst, dlgTemplate, owner, dlgProc, 0 );
 }
@@ -244,7 +244,7 @@
  *           CreateDialogIndirectParam   (USER.242)
  */
 HWND CreateDialogIndirectParam( HINSTANCE hInst, SEGPTR dlgTemplate,
-			        HWND owner, WNDPROC dlgProc, LPARAM param )
+			        HWND owner, DLGPROC dlgProc, LPARAM param )
 {
     HMENU hMenu = 0;
     HFONT hFont = 0;
@@ -789,9 +789,10 @@
 /***********************************************************************
  *           CheckDlgButton   (USER.97)
  */
-void CheckDlgButton( HWND hwnd, WORD id, WORD check )
+BOOL CheckDlgButton( HWND hwnd, INT id, UINT check )
 {
     SendDlgItemMessage( hwnd, id, BM_SETCHECK, check, 0 );
+    return TRUE;
 }
 
 
@@ -807,28 +808,29 @@
 /***********************************************************************
  *           CheckRadioButton   (USER.96)
  */
-void CheckRadioButton( HWND hwndDlg, WORD firstID, WORD lastID, WORD checkID )
+BOOL CheckRadioButton( HWND hwndDlg, UINT firstID, UINT lastID, UINT checkID )
 {
     HWND button = GetWindow( hwndDlg, GW_CHILD );
     WND *wndPtr;
 
     while (button)
     {
-	if (!(wndPtr = WIN_FindWndPtr( button ))) return;
+	if (!(wndPtr = WIN_FindWndPtr( button ))) return FALSE;
         if ((wndPtr->wIDmenu == firstID) || (wndPtr->wIDmenu == lastID)) break;
 	button = wndPtr->hwndNext;
     }
-    if (!button) return;
+    if (!button) return FALSE;
 
     if (wndPtr->wIDmenu == lastID)
         lastID = firstID;  /* Buttons are in reverse order */
     while (button)
     {
-	if (!(wndPtr = WIN_FindWndPtr( button ))) return;
+	if (!(wndPtr = WIN_FindWndPtr( button ))) return FALSE;
 	SendMessage( button, BM_SETCHECK, (wndPtr->wIDmenu == checkID), 0 );
         if (wndPtr->wIDmenu == lastID) break;
 	button = wndPtr->hwndNext;
     }
+    return TRUE;
 }
 
 
diff --git a/windows/hook.c b/windows/hook.c
index abb6c7f..ad3d0f4 100644
--- a/windows/hook.c
+++ b/windows/hook.c
@@ -277,7 +277,7 @@
 /***********************************************************************
  *           CallMsgFilter   (USER.123)
  */
-BOOL CallMsgFilter( SEGPTR msg, short code )
+BOOL CallMsgFilter( SEGPTR msg, INT code )
 {
     if (GetSysModalWindow()) return FALSE;
     if (HOOK_CallHooks( WH_SYSMSGFILTER, code, 0, (LPARAM)msg )) return TRUE;
@@ -316,7 +316,7 @@
 /***********************************************************************
  *           CallNextHookEx   (USER.293)
  */
-DWORD CallNextHookEx( HHOOK hhook, short code, WPARAM wParam, LPARAM lParam )
+LRESULT CallNextHookEx( HHOOK hhook, INT code, WPARAM wParam, LPARAM lParam )
 {
     HANDLE next;
 #ifdef WINELIB32
diff --git a/windows/keyboard.c b/windows/keyboard.c
index c8c0e53..0c1ae3e 100644
--- a/windows/keyboard.c
+++ b/windows/keyboard.c
@@ -91,8 +91,8 @@
 	break;
     }
 
-    bzero(AsyncMouseButtonsStates, 3);	/* all states to false */
-    bzero(AsyncKeyStateTable, 256);
+    memset( AsyncMouseButtonsStates, 0, 3 );  /* all states to false */
+    memset( AsyncKeyStateTable, 0, 256 );
 
     return retval;
 }
diff --git a/windows/mdi.c b/windows/mdi.c
index 86d5413..38e0944 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -1,7 +1,7 @@
 /* MDI.C
  *
  * Copyright 1994, Bob Amstadt
- *           1995, Alex Korobka
+ *           1995,1996 Alex Korobka
  *
  * This file contains routines to support MDI features.
  *
@@ -9,8 +9,11 @@
  *        of corresponding MDI child.
  *
  *	  Basic child activation routine is MDI_ChildActivate and 
- *        SetWindowPos(childHwnd,...) implicitly calls it if SWP_NOACTIVATE i
+ *        SetWindowPos(childHwnd,...) implicitly calls it if SWP_NOACTIVATE
  *        is not used.
+ *
+ * To fix:
+ *	  Sticky client crollbars 
  */
 
 #include <stdlib.h>
@@ -23,10 +26,15 @@
 #include "mdi.h"
 #include "user.h"
 #include "menu.h"
+#include "stackframe.h"
 #include "sysmetrics.h"
 #include "stddebug.h"
 #include "debug.h"
 
+void MDI_UpdateFrameText(HWND, HWND, BOOL, LPCSTR);
+BOOL MDI_AugmentFrameMenu(MDICLIENTINFO*, HWND, HWND);
+BOOL MDI_RestoreFrameMenu(HWND, HWND);
+
 void ScrollChildren(HWND , UINT , WPARAM , LPARAM );
 void CalcChildScroll(HWND, WORD);
 
@@ -41,10 +49,8 @@
 
 static HWND MDI_GetChildByID(WND* mdiClient,int id)
 {
- HWND	hWnd   = mdiClient->hwndChild;
- WND* 	wndPtr = WIN_FindWndPtr( hWnd );
-    
- if( !wndPtr ) return 0;
+ HWND	hWnd   	    = mdiClient->hwndChild;
+ WND* 	wndPtr 	    = WIN_FindWndPtr( hWnd );
 
  while( wndPtr )
   {
@@ -61,7 +67,7 @@
 #ifdef SUPERFLUOUS_FUNCTIONS
 static BOOL MDI_MenuAppendItem(WND *clientWnd, HWND hWndChild)
 {
-    char buffer[128];
+ char buffer[128];
  MDICLIENTINFO  *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
  WND		*wndPtr     = WIN_FindWndPtr(hWndChild);
  LPSTR		 lpWndText  = (LPSTR) USER_HEAP_LIN_ADDR(wndPtr->hText);
@@ -73,7 +79,7 @@
  if( lpWndText )
      strncpy(buffer + n, lpWndText, sizeof(buffer) - n - 1);
  return AppendMenu(clientInfo->hWindowMenu,MF_STRING,
-                       wndPtr->wIDmenu,(LPSTR)buffer);
+                       wndPtr->wIDmenu, MAKE_SEGPTR(buffer) );
 }
 #endif
 
@@ -92,13 +98,13 @@
 
  if( !clientInfo->hWindowMenu ) return 0;
 
- if( lpWndText )
-     strncpy(buffer + n, lpWndText, sizeof(buffer) - n - 1);
+ if( lpWndText ) lstrcpyn(buffer + n, lpWndText, sizeof(buffer) - n );
 
  n    = GetMenuState(clientInfo->hWindowMenu,wndPtr->wIDmenu ,MF_BYCOMMAND); 
  bRet = ModifyMenu(clientInfo->hWindowMenu , wndPtr->wIDmenu , 
-                   MF_BYCOMMAND | MF_STRING, wndPtr->wIDmenu ,(LPSTR)buffer );
-        CheckMenuItem(clientInfo->hWindowMenu ,wndPtr->wIDmenu , n & MF_CHECKED);
+                   MF_BYCOMMAND | MF_STRING, wndPtr->wIDmenu ,
+                   MAKE_SEGPTR(buffer) );
+ CheckMenuItem(clientInfo->hWindowMenu ,wndPtr->wIDmenu , n & MF_CHECKED);
  return bRet;
 }
 
@@ -144,7 +150,7 @@
 
 	/* change menu */
 	ModifyMenu(clientInfo->hWindowMenu ,index ,MF_BYCOMMAND | MF_STRING,
-		   index - 1 ,(LPSTR)buffer ); 
+		   index - 1 , MAKE_SEGPTR(buffer) ); 
     }
  return 1;
 }
@@ -217,6 +223,10 @@
 						/* -DRP			 */
 }
 
+
+/* ------------------ MDI child window functions ---------------------- */
+
+
 /**********************************************************************
  *					MDICreateChild
  */
@@ -240,7 +250,7 @@
     cs->y = ci->nActiveChildren * spacing;
 
     /* this menu is needed to set a check mark in MDI_ChildActivate */
-    AppendMenu(ci->hWindowMenu ,MF_STRING ,wIDmenu, (LPSTR)&chDef);
+    AppendMenu(ci->hWindowMenu ,MF_STRING ,wIDmenu, MAKE_SEGPTR(&chDef) );
 
     hwnd = CreateWindow( cs->szClass, cs->szTitle,
 			  WS_CHILD | WS_BORDER | WS_CAPTION | WS_CLIPSIBLINGS |
@@ -255,7 +265,6 @@
 	ci->nActiveChildren++;
 	MDI_MenuModifyItem(w ,hwnd); 
 
-	/* FIXME: at this point NC area of hwnd stays inactive */
     }
     else
 	DeleteMenu(ci->hWindowMenu,wIDmenu,MF_BYCOMMAND);
@@ -264,95 +273,72 @@
 }
 
 /**********************************************************************
+ *			MDI_ChildGetMinMaxInfo
+ *
+ */
+void MDI_ChildGetMinMaxInfo(WND* clientWnd, HWND hwnd, MINMAXINFO* lpMinMax )
+{
+ WND*	childWnd = WIN_FindWndPtr(hwnd);
+ RECT 	rect 	 = clientWnd->rectClient;
+
+ MapWindowPoints(clientWnd->hwndParent, 
+	       ((MDICLIENTINFO*)clientWnd->wExtra)->self, (LPPOINT)&rect, 2);
+ AdjustWindowRectEx(&rect, childWnd->dwStyle, 0, childWnd->dwExStyle);
+
+ lpMinMax->ptMaxSize.x = rect.right -= rect.left;
+ lpMinMax->ptMaxSize.y = rect.bottom -= rect.top;
+
+ lpMinMax->ptMaxPosition.x = rect.left;
+ lpMinMax->ptMaxPosition.y = rect.top; 
+}
+
+/**********************************************************************
  *			MDI_SwitchActiveChild
  * 
  * Notes: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
  *        being activated 
  *
- *        Ideally consecutive SetWindowPos should be replaced by 
- *        BeginDeferWindowPos/EndDeferWindowPos but currently it doesn't
- *        matter.
- *
- *	  wTo is basically lParam of WM_MDINEXT message
+ *	  wTo is basically lParam of WM_MDINEXT message or explicit 
+ *        window handle
  */
-void MDI_SwitchActiveChild(HWND clientHwnd, HWND childHwnd, WORD wTo )
+void MDI_SwitchActiveChild(HWND clientHwnd, HWND childHwnd, BOOL wTo )
 {
     WND		  *w	     = WIN_FindWndPtr(clientHwnd);
-    HWND	   hwndTo    = MDI_GetWindow(w,childHwnd,wTo);
-    HWND	   hwndPrev;
+    HWND	   hwndTo    = 0;
+    HWND	   hwndPrev  = 0;
     MDICLIENTINFO *ci;
 
-    
+    hwndTo = MDI_GetWindow(w,childHwnd,(WORD)wTo);
+ 
     ci = (MDICLIENTINFO *) w->wExtra;
 
-    dprintf_mdi(stddeb, "MDI_SwitchActiveChild: "NPFMT", %i\n",childHwnd,wTo);
+    dprintf_mdi(stddeb, "MDI_SwitchActiveChild: from "NPFMT", to "NPFMT"\n",childHwnd,hwndTo);
 
-    if ( !childHwnd || !hwndTo ) return; 
+    if ( !hwndTo ) return; 
 
     hwndPrev = ci->hwndActiveChild;
 
     if ( hwndTo != hwndPrev )
 	{
-	    if (ci->flagChildMaximized)
+	  BOOL bSA = 0;
+
+	  if( ci->flagChildMaximized )
 	    {
-		RECT rectOldRestore, rect;
-
-		w = WIN_FindWndPtr(hwndTo);
-		
-		/* save old window dimensions */
-		rectOldRestore = ci->rectRestore;
-		GetWindowRect(hwndTo, &ci->rectRestore);
-
-		rect.top    = (ci->rectMaximize.top -
-			       (w->rectClient.top - w->rectWindow.top));
-		rect.bottom = (ci->rectMaximize.bottom + 
-			       (w->rectWindow.bottom - w->rectClient.bottom));
-		rect.left   = (ci->rectMaximize.left - 
-			       (w->rectClient.left - w->rectWindow.left));
-		rect.right  = (ci->rectMaximize.right +
-			       (w->rectWindow.right - w->rectClient.right));
-		w->dwStyle |= WS_MAXIMIZE;
-
-		/* maximize it */
-		ci->flagChildMaximized = childHwnd; /* prevent maximization
-						     * in MDI_ChildActivate
-						     */
-
-		SetWindowPos( hwndTo, HWND_TOP, rect.left, rect.top, 
-			     rect.right - rect.left + 1,
-			     rect.bottom - rect.top + 1, 0);
-
-		SendMessage( hwndTo, WM_SIZE, SIZE_MAXIMIZED,
-			    MAKELONG(w->rectClient.right-w->rectClient.left,
-				     w->rectClient.bottom-w->rectClient.top));
-
-		w = WIN_FindWndPtr(hwndPrev);
-
-	        if( w )
-		  {
-		w->dwStyle &= ~WS_MAXIMIZE;
-
-		     /* push hwndPrev to the bottom if needed */
-		     if( !wTo )
-		         SetWindowPos(hwndPrev, HWND_BOTTOM, 
-			     rectOldRestore.left, rectOldRestore.top, 
-			     rectOldRestore.right - rectOldRestore.left + 1, 
-			     rectOldRestore.bottom - rectOldRestore.top + 1,
-			          SWP_NOACTIVATE );
-	          }
+	      bSA = 1; 
+	      w->dwStyle &= ~WS_VISIBLE;
 	    }
-	    else
+
+	  SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0, 
+			SWP_NOMOVE | SWP_NOSIZE );
+	  if( !wTo && hwndPrev )
 	    {
-		SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0, 
-			     SWP_NOMOVE | SWP_NOSIZE );
-		if( !wTo && hwndPrev )
-		{
-		    SetWindowPos( hwndPrev, HWND_BOTTOM, 0, 0, 0, 0, 
-				 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
-		}
+	       SetWindowPos( hwndPrev, HWND_BOTTOM, 0, 0, 0, 0, 
+		  	     SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
 	    }
-    }
-		
+
+	  if( bSA )
+	       ShowWindow( clientHwnd, SW_SHOW );
+	}
 }
 
 	    
@@ -371,15 +357,23 @@
 	    MDI_SwitchActiveChild(parent,child,0);
 
 	    if( child == ci->hwndActiveChild )
-                MDI_ChildActivate(w_parent,0);
+	      {
+		ShowWindow( child, SW_HIDE);
+		if( child == ci->flagChildMaximized )
+		  {
+		    MDI_RestoreFrameMenu(w_parent->hwndParent, child);
+		    ci->flagChildMaximized = 0;
+		    MDI_UpdateFrameText(w_parent->hwndParent,parent,TRUE,NULL);
+		  }
 
+                MDI_ChildActivate(w_parent,0);
+	      }
 	    MDI_MenuDeleteItem(w_parent, child);
 	}
 	
         ci->nActiveChildren--;
 
-        if( ci->flagChildMaximized == child )
-            ci->flagChildMaximized = (HWND)1;
+	/* WM_MDISETMENU ? */
 
         if (flagDestroy)
 	   {
@@ -394,66 +388,6 @@
 
 
 /**********************************************************************
- *					MDIMaximizeChild
- */
-LONG MDIMaximizeChild(HWND parent, HWND child, MDICLIENTINFO *ci)
-{
-
-    WND *w = WIN_FindWndPtr(child);
-    RECT rect;
-    
-    if( !SendMessage( child, WM_QUERYOPEN, 0, 0L) )
-	 return 0;
-    
-    ci->rectRestore = w->rectWindow;
-
-    rect.top    = (ci->rectMaximize.top -
-		   (w->rectClient.top - w->rectWindow.top));
-    rect.bottom = (ci->rectMaximize.bottom + 
-		   (w->rectWindow.bottom - w->rectClient.bottom));
-    rect.left   = (ci->rectMaximize.left - 
-		   (w->rectClient.left - w->rectWindow.left));
-    rect.right  = (ci->rectMaximize.right +
-		   (w->rectWindow.right - w->rectClient.right));
-    w->dwStyle |= WS_MAXIMIZE;
-
-    SetWindowPos(child, 0, rect.left, rect.top, 
-		 rect.right - rect.left + 1, rect.bottom - rect.top + 1, 0);
-    
-    ci->flagChildMaximized = child;
-    
-    SendMessage(child, WM_SIZE, SIZE_MAXIMIZED,
-		MAKELONG(w->rectClient.right-w->rectClient.left,
-			 w->rectClient.bottom-w->rectClient.top));
-
-    SendMessage(GetParent(parent), WM_NCPAINT, 0, 0);
-
-    return 0;
-}
-
-/**********************************************************************
- *					MDIRestoreChild
- */
-LONG MDIRestoreChild(HWND parent, MDICLIENTINFO *ci)
-{
-    HWND    hWnd;
-
-    hWnd = ci->hwndActiveChild;
-
-    dprintf_mdi(stddeb,"MDIRestoreChild: restore "NPFMT"\n", hWnd);
-
-    ci->flagChildMaximized = FALSE;
-
-    ShowWindow(hWnd, SW_RESTORE);		/* display the window */
-
-    hWnd = GetParent(parent);
-
-    SendMessage(hWnd,WM_NCPAINT , 0, 0);
-
-    return 0;
-}
-
-/**********************************************************************
  *					MDI_ChildActivate
  *
  * Note: hWndChild is NULL when last child is being destroyed
@@ -499,8 +433,11 @@
         if( hWndChild )
 	        {
 		  clientInfo->hwndActiveChild = hWndChild;
-		  MDIMaximizeChild(GetParent(hWndChild),hWndChild,clientInfo);
+		  ShowWindow( hWndChild, SW_SHOWMAXIMIZED);
 	        }
+	else
+		ShowWindow( clientInfo->hwndActiveChild, 
+			    SW_SHOWNORMAL );
 
     clientInfo->hwndActiveChild = hWndChild;
 
@@ -508,7 +445,7 @@
     if( !hWndChild )
 	{
 	    if( isActiveFrameWnd )
-		SetFocus( GetParent(hWndChild) );
+		SetFocus( clientInfo->self );
 	    return 0;
 	}
 	
@@ -523,11 +460,11 @@
     if( isActiveFrameWnd )
 	  {
 	    SendMessage( hWndChild, WM_NCACTIVATE, TRUE, 0L);
-	    if( GetFocus() == GetParent(hWndChild) )
-		SendMessage( GetParent(hWndChild), WM_SETFOCUS, 
-			     (WPARAM)GetParent(hWndChild), 0L );
+	    if( GetFocus() == clientInfo->self )
+		SendMessage( clientInfo->self, WM_SETFOCUS, 
+			    (WPARAM)clientInfo->self, 0L );
 	    else
-		SetFocus( GetParent(hWndChild) );
+		SetFocus( clientInfo->self );
     }
 
 #ifdef WINELIB32
@@ -574,7 +511,7 @@
                 free(listTop);
                 listTop  = listNext;
 	    }
-	    fprintf(stdnimp,"MDICascade: allocation failed\n");
+	    dprintf_mdi(stddeb,"MDICascade: allocation failed\n");
 	    return NULL;
 	}
     
@@ -605,8 +542,39 @@
     return listTop;
 }
 
+
+/* -------------------- MDI client window functions ------------------- */
+
 /**********************************************************************
- *					MDICascade
+ *				CreateMDIMenuBitmap
+ */
+HBITMAP CreateMDIMenuBitmap(void)
+{
+ HDC 		hDCSrc  = CreateCompatibleDC(0);
+ HDC		hDCDest	= CreateCompatibleDC(hDCSrc);
+ HBITMAP	hbClose = LoadBitmap(0, MAKEINTRESOURCE(OBM_CLOSE) );
+ HBITMAP	hbCopy,hb_src,hb_dest;
+
+ hb_src = SelectObject(hDCSrc,hbClose);
+ hbCopy = CreateCompatibleBitmap(hDCSrc,SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE);
+ hb_dest = SelectObject(hDCDest,hbCopy);
+
+ BitBlt(hDCDest, 0, 0, SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE,
+	hDCSrc, SYSMETRICS_CXSIZE, 0, SRCCOPY);
+ 
+ SelectObject(hDCSrc,hb_src);
+ SelectObject(hDCDest,hb_dest);
+
+ DeleteObject(hbClose);
+
+ DeleteDC(hDCDest);
+ DeleteDC(hDCSrc);
+
+ return hbCopy;
+}
+
+/**********************************************************************
+ *				MDICascade
  */
 LONG MDICascade(HWND parent, MDICLIENTINFO *ci)
 {
@@ -618,7 +586,7 @@
     int		  iToPosition = 0;
 
     if (ci->flagChildMaximized)
-	MDIRestoreChild(parent, ci);
+	ShowWindow( ci->flagChildMaximized, SW_NORMAL);
 
     if (ci->nActiveChildren == 0) return 0;
 
@@ -661,6 +629,9 @@
 	listTop = listPrev;
     }
 
+    if( iToPosition < ci->nActiveChildren )
+	ArrangeIconicWindows( parent );
+
     return 0;
 }
 
@@ -668,7 +639,7 @@
  *					MDITile
  *
  */
-LONG MDITile(HWND parent, MDICLIENTINFO *ci)
+LONG MDITile(HWND parent, MDICLIENTINFO *ci,WORD wParam)
 {
     WND		 *wndClient = WIN_FindWndPtr(parent);
     MDIWCL       *listTop,*listPrev;
@@ -681,7 +652,7 @@
     int		  iToPosition = 0;
 
     if (ci->flagChildMaximized)
-	MDIRestoreChild(parent, ci);
+	ShowWindow(ci->flagChildMaximized, SW_NORMAL);
 
     if (ci->nActiveChildren == 0) return 0;
 
@@ -691,178 +662,240 @@
 
     if( !listTop ) return 0;
 
-    /* just free memory and return if zero windows to tile */
-    if ( iToPosition == 0 )
-        goto MDITile_free;
+    /* tile children */
+    if ( iToPosition )
+    {
 
-    GetClientRect(parent, &rect);
+    	GetClientRect(parent, &rect);
 
-    rows    = (int) sqrt((double) iToPosition);
-    columns = iToPosition / rows;
+    	rows    = (int) sqrt((double) iToPosition);
+    	columns = iToPosition / rows;
 
-    /* hack */
-    if( iToPosition != ci->nActiveChildren)
+        if (wParam == MDITILE_HORIZONTAL)  /* version >= 3.1 */
         {
-           y = rect.bottom - 2 * SYSMETRICS_CYICONSPACING - SYSMETRICS_CYICON;
-           rect.bottom = ( y - SYSMETRICS_CYICON < rect.top )? rect.bottom: y;
-	}
+            i=rows;
+            rows=columns;  /* exchange r and c */
+            columns=i;
+        }
 
-    ysize   = rect.bottom / rows;
-    xsize   = rect.right  / columns;
+    	/* hack */
+    	if( iToPosition != ci->nActiveChildren)
+        {
+            y = rect.bottom - 2 * SYSMETRICS_CYICONSPACING - SYSMETRICS_CYICON;
+            rect.bottom = ( y - SYSMETRICS_CYICON < rect.top )? rect.bottom: y;
+        }
+
+    	ysize   = rect.bottom / rows;
+    	xsize   = rect.right  / columns;
     
-    x       = 0;
-    i       = 0;
+    	x       = 0;
+    	i       = 0;
 
-    for (c = 1; c <= columns; c++)
-    {
-	if (c == columns)
-	{
-	    rows  = iToPosition - i;
-	    ysize = rect.bottom / rows;
-	}
+    	for (c = 1; c <= columns; c++)
+    	{
+            if (c == columns)
+            {
+                rows  = iToPosition - i;
+                ysize = rect.bottom / rows;
+            }
 
-	y = 0;
-	for (r = 1; r <= rows; r++, i++)
-	{
-	    /* shouldn't happen but... */
-	    if( !listTop )
-		 break;
-
-	    if( listTop->hChild )
-		{
-	            SetWindowPos(listTop->hChild, 0, x, y, xsize, ysize, 
-			 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
-	    y += ysize;
-		}
-
-            listPrev = listTop->prev;
-            free(listTop);
-            listTop = listPrev;
-	}
-
-	x += xsize;
+            y = 0;
+            for (r = 1; r <= rows; r++, i++)
+            {
+                /* shouldn't happen but... */
+                if( !listTop )
+                    break;
+                
+                if( listTop->hChild )
+                {
+                    SetWindowPos(listTop->hChild, 0, x, y, xsize, ysize, 
+				 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
+		    y += ysize;
+                }
+    	        listPrev = listTop->prev;
+    	        free(listTop);
+    	        listTop = listPrev;
+            }
+            x += xsize;
+    	}
     }
-
-  MDITile_free:
+  
     /* free the rest if any */
-    while( listTop ) {
-	 listPrev = listTop->prev;
-	 free(listTop);
-	 listTop = listPrev; }
-
-    return 0;
-}
-
-/**********************************************************************
- *					MDIHandleLButton
- */
-BOOL MDIHandleLButton(HWND hwndFrame, HWND hwndClient, 
-		      WORD wParam, LONG lParam)
-{
-    MDICLIENTINFO *ci;
-    WND           *w;
-    RECT           rect;
-    WORD           x;
-
-    w  = WIN_FindWndPtr(hwndClient);
-    ci = (MDICLIENTINFO *) w->wExtra;
-
-    if (wParam == HTMENU && ci->flagChildMaximized)
+    while( listTop )
     {
-	x = LOWORD(lParam);
-	
-	NC_GetInsideRect(hwndFrame, &rect);
-	if (x < rect.left + SYSMETRICS_CXSIZE)
-	{
-	    SendMessage(ci->hwndActiveChild, WM_SYSCOMMAND, 
-			SC_CLOSE, lParam);
-	    return TRUE;
-	}
-	else if (x >= rect.right - SYSMETRICS_CXSIZE)
-	{
-	    SendMessage(ci->hwndActiveChild, WM_SYSCOMMAND, 
-			SC_RESTORE, lParam);
-	    return TRUE;
-	}
+        listPrev = listTop->prev;
+        free(listTop);
+        listTop = listPrev;
     }
-
-    return FALSE;
-}
-
-/**********************************************************************
- *					MDIPaintMaximized
- */
-LONG MDIPaintMaximized(HWND hwndFrame, HWND hwndClient, WORD message,
-		       WORD wParam, LONG lParam)
-{
-    static HBITMAP hbitmapClose     = 0;
-    static HBITMAP hbitmapMaximized = 0;
     
-    MDICLIENTINFO *ci;
-    WND           *w;
-    HDC           hdc, hdcMem;
-    RECT          rect;
-    WND           *wndPtr = WIN_FindWndPtr(hwndFrame);
-
-    w  = WIN_FindWndPtr(hwndClient);
-    ci = (MDICLIENTINFO *) w->wExtra;
-
-    dprintf_mdi(stddeb, "MDIPaintMaximized: frame "NPFMT",  client "NPFMT
-		",  max flag %d,  menu %04x\n", hwndFrame, hwndClient, 
-		(int)ci->flagChildMaximized, wndPtr ? wndPtr->wIDmenu : 0);
-
-    if (ci->flagChildMaximized && wndPtr && wndPtr->wIDmenu != 0)
-    {
-	NC_DoNCPaint(hwndFrame, wParam, TRUE);
-
-	hdc = GetDCEx(hwndFrame, 0, DCX_CACHE | DCX_WINDOW);
-	if (!hdc) return 0;
-
-	hdcMem = CreateCompatibleDC(hdc);
-
-	if (hbitmapClose == 0)
-	{
-	    hbitmapClose     = LoadBitmap(0, MAKEINTRESOURCE(OBM_OLD_CLOSE));
-	    hbitmapMaximized = LoadBitmap(0, MAKEINTRESOURCE(OBM_RESTORE));
-	}
-
-	dprintf_mdi(stddeb, 
-		    "MDIPaintMaximized: hdcMem "NPFMT", close bitmap "NPFMT", "
-		    "maximized bitmap "NPFMT"\n",
-		    hdcMem, hbitmapClose, hbitmapMaximized);
-
-	NC_GetInsideRect(hwndFrame, &rect);
-	rect.top += (wndPtr->dwStyle & WS_CAPTION) ? SYSMETRICS_CYSIZE + 1 : 0;
-	SelectObject(hdcMem, hbitmapClose);
-	BitBlt(hdc, rect.left, rect.top + 1, 
-	       SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE,
-	       hdcMem, 1, 1, SRCCOPY);
-	
-	NC_GetInsideRect(hwndFrame, &rect);
-	rect.top += (wndPtr->dwStyle & WS_CAPTION) ? SYSMETRICS_CYSIZE + 1 : 0;
-	rect.left   = rect.right - SYSMETRICS_CXSIZE;
-	SelectObject(hdcMem, hbitmapMaximized);
-	BitBlt(hdc, rect.left, rect.top + 1, 
-	       SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE,
-	       hdcMem, 1, 1, SRCCOPY);
-	
-	NC_GetInsideRect(hwndFrame, &rect);
-	rect.top += (wndPtr->dwStyle & WS_CAPTION) ? SYSMETRICS_CYSIZE + 1 : 0;
-	rect.left += SYSMETRICS_CXSIZE;
-	rect.right -= SYSMETRICS_CXSIZE;
-	rect.bottom = rect.top + SYSMETRICS_CYMENU;
-
-	MENU_DrawMenuBar(hdc, &rect, hwndFrame, FALSE);
-	
-	DeleteDC(hdcMem);
-	ReleaseDC(hwndFrame, hdc);
-    }
-    else
-	return DefWindowProc(hwndFrame, message, wParam, lParam);
+    if (iToPosition < ci->nActiveChildren )
+        ArrangeIconicWindows( parent );
 
     return 0;
 }
 
+/* ----------------------- Frame window ---------------------------- */
+
+
+/**********************************************************************
+ *					MDI_AugmentFrameMenu
+ */
+BOOL MDI_AugmentFrameMenu(MDICLIENTINFO* ci, HWND hFrame, HWND hChild)
+{
+ WND*	frame = WIN_FindWndPtr(hFrame);
+ WND*	child = WIN_FindWndPtr(hChild);
+ HMENU  hSysPopup = 0;
+
+ dprintf_mdi(stddeb,"MDI_AugmentFrameMenu: frame "NPFMT",child "NPFMT"\n",hFrame,hChild);
+
+ if( !frame->wIDmenu || !child->hSysMenu ) return 0; 
+ 
+ hSysPopup = GetSystemMenu(hChild,FALSE);
+
+ dprintf_mdi(stddeb,"got popup "NPFMT"\n in sysmenu "NPFMT"",hSysPopup,child->hSysMenu);
+ 
+ if( !InsertMenu(frame->wIDmenu,0,MF_BYPOSITION | MF_BITMAP | MF_POPUP,
+                 hSysPopup, (SEGPTR)(DWORD)ci->obmClose) )
+      return 0;
+
+ if( !AppendMenu(frame->wIDmenu,MF_HELP | MF_BITMAP,
+                 SC_RESTORE, (SEGPTR)(DWORD)ci->obmRestore) )
+   {
+      RemoveMenu(frame->wIDmenu,0,MF_BYPOSITION);
+      return 0;
+   }
+
+ EnableMenuItem(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
+ EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
+ EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
+
+ child->dwStyle &= ~WS_SYSMENU;
+
+ /* redraw frame */
+ SetWindowPos(hFrame, 0,0,0,0,0, SWP_FRAMECHANGED | SWP_NOSIZE | 
+                                 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
+
+ return 1;
+}
+
+/**********************************************************************
+ *					MDI_RestoreFrameMenu
+ */
+BOOL MDI_RestoreFrameMenu(HWND hFrame, HWND hChild)
+{
+ WND*	frameWnd = WIN_FindWndPtr(hFrame);
+ WND*   child    = WIN_FindWndPtr(hChild);
+ INT	nItems   = GetMenuItemCount(frameWnd->wIDmenu) - 1;
+
+ dprintf_mdi(stddeb,"MDI_RestoreFrameMenu: for child "NPFMT"\n",hChild);
+
+ if( GetMenuItemID(frameWnd->wIDmenu,nItems) != SC_RESTORE )
+     return 0; 
+
+ child->dwStyle |= WS_SYSMENU;
+
+ RemoveMenu(frameWnd->wIDmenu,0,MF_BYPOSITION);
+ DeleteMenu(frameWnd->wIDmenu,nItems-1,MF_BYPOSITION);
+
+  /* redraw frame */
+ SetWindowPos(hChild, 0,0,0,0,0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
+                                 SWP_NOACTIVATE | SWP_NOZORDER );
+ return 1;
+}
+
+/**********************************************************************
+ *				        MDI_UpdateFrameText
+ *
+ * used when child window is maximized/restored 
+ *
+ * Note: lpTitle can be NULL
+ */
+void MDI_UpdateFrameText(HWND hFrame, HWND hClient, BOOL repaint, LPCSTR lpTitle)
+{
+ char   lpBuffer[MDI_MAXTITLELENGTH+1];
+ LPSTR	lpText    = NULL;
+ WND* 	clientWnd = WIN_FindWndPtr(hClient);
+ WND* 	frameWnd  = WIN_FindWndPtr(hFrame);
+
+ MDICLIENTINFO *ci = (MDICLIENTINFO *) clientWnd->wExtra;
+
+ dprintf_mdi(stddeb, "MDI: repaint %i, frameText %s\n", repaint, (lpTitle)?lpTitle:"NULL");
+
+ /* store new "default" title if lpTitle is not NULL */
+ if( lpTitle )
+   {
+	if( ci->hFrameTitle )
+	    USER_HEAP_FREE( ci->hFrameTitle );
+	ci->hFrameTitle = USER_HEAP_ALLOC( strlen(lpTitle) + 1 );
+	lpText = (LPSTR) USER_HEAP_LIN_ADDR( ci->hFrameTitle );
+	strcpy( lpText, lpTitle );
+   }
+ else
+  lpText = (LPSTR) USER_HEAP_LIN_ADDR(ci->hFrameTitle);
+
+ if( ci->hFrameTitle )
+   {
+     WND* childWnd = WIN_FindWndPtr( ci->flagChildMaximized );     
+
+     if( childWnd && childWnd->hText )
+       {
+	 /* combine frame title and child title if possible */
+
+	 LPCSTR lpBracket  = " - [";
+	 LPCSTR lpChildText = (LPCSTR) USER_HEAP_LIN_ADDR( childWnd->hText );
+ 
+	 int	i_frame_text_length = strlen(lpText);
+	 int    i_child_text_length = strlen(lpChildText);
+
+	 strncpy( lpBuffer, lpText, MDI_MAXTITLELENGTH);
+	 lpBuffer[MDI_MAXTITLELENGTH] = '\0';
+
+	 if( i_frame_text_length + 5 < MDI_MAXTITLELENGTH )
+	   {
+	     strcat( lpBuffer, lpBracket );
+
+	     if( i_frame_text_length + i_child_text_length + 5 < MDI_MAXTITLELENGTH )
+		{
+		   strcat( lpBuffer, lpChildText );
+	         *(short*)(lpBuffer + i_frame_text_length + i_child_text_length + 4) = (short)']';
+		}
+	     else
+		{
+		   memcpy( lpBuffer + i_frame_text_length + 4, 
+		           lpChildText, 
+			   MDI_MAXTITLELENGTH - i_frame_text_length - 4);
+		 *(short*)(lpBuffer + MDI_MAXTITLELENGTH - 1) = (short)']';
+		}
+	   }
+       }
+     else
+       {
+         strncpy(lpBuffer, lpText, MDI_MAXTITLELENGTH );
+	 lpBuffer[MDI_MAXTITLELENGTH]='\0';
+       }
+   }
+ else
+   lpBuffer[0] = '\0';
+
+ if( frameWnd->hText )
+     USER_HEAP_FREE( frameWnd->hText );
+ 
+ frameWnd->hText = USER_HEAP_ALLOC( strlen(lpBuffer) + 1 );
+ lpText = (LPSTR) USER_HEAP_LIN_ADDR( frameWnd->hText );
+ strcpy( lpText, lpBuffer );
+
+ if( frameWnd->window )
+     XStoreName( display, frameWnd->window, lpBuffer );
+
+ if( repaint == MDI_REPAINTFRAME)
+     SetWindowPos(hFrame, 0,0,0,0,0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
+                                     SWP_NOACTIVATE | SWP_NOZORDER );
+}
+
+
+/* ----------------------------- Interface ---------------------------- */
+
+
 /**********************************************************************
  *					MDIClientWndProc
  *
@@ -873,9 +906,10 @@
     LPCREATESTRUCT       cs;
     LPCLIENTCREATESTRUCT ccs;
     MDICLIENTINFO       *ci;
-    WND                 *w;
+    RECT		 rect;
+    WND                 *w 	  = WIN_FindWndPtr(hwnd);
+    WND			*frameWnd = WIN_FindWndPtr( w->hwndParent );
 
-    w  = WIN_FindWndPtr(hwnd);
     ci = (MDICLIENTINFO *) w->wExtra;
     
     switch (message)
@@ -883,23 +917,46 @@
       case WM_CREATE:
 	cs                      = (LPCREATESTRUCT) PTR_SEG_TO_LIN(lParam);
 	ccs                     = (LPCLIENTCREATESTRUCT) PTR_SEG_TO_LIN(cs->lpCreateParams);
+
 	ci->hWindowMenu         = ccs->hWindowMenu;
 	ci->idFirstChild        = ccs->idFirstChild;
-	ci->flagChildMaximized  = FALSE;
+	ci->flagChildMaximized  = 0;
+	ci->hFrameTitle		= frameWnd->hText;
 	ci->sbStop		= 0;
-
+	ci->self		= hwnd;
+	ci->obmClose		= CreateMDIMenuBitmap();
+	ci->obmRestore		= LoadBitmap(0, MAKEINTRESOURCE(OBM_RESTORE));
 	w->dwStyle             |= WS_CLIPCHILDREN;
+	frameWnd->hText		= 0;	/* will be restored in UpdateFrameText */
 
-	AppendMenu(ccs->hWindowMenu,MF_SEPARATOR,0,NULL);
+	MDI_UpdateFrameText( w->hwndParent, hwnd, MDI_NOFRAMEREPAINT, NULL);
 
-	GetClientRect(w->hwndParent, &ci->rectMaximize);
-	MoveWindow(hwnd, 0, 0, 
-		   ci->rectMaximize.right, ci->rectMaximize.bottom, 1);
+	AppendMenu(ccs->hWindowMenu,MF_SEPARATOR,0,(SEGPTR)0);
+
+	GetClientRect(w->hwndParent, &rect);
+	NC_HandleNCCalcSize(hwnd, (NCCALCSIZE_PARAMS*) &rect);
+	w->rectClient = rect;
+
+	return 0;
+      
+      case WM_DESTROY:
+	if( ci->flagChildMaximized )
+	  MDI_RestoreFrameMenu(hwnd, w->hwndParent);
+
+	if(ci->obmClose)   DeleteObject(ci->obmClose);
+	if(ci->obmRestore) DeleteObject(ci->obmRestore);
+
+	ci->idFirstChild = GetMenuItemCount(ci->hWindowMenu) - 1;
+	ci->nActiveChildren++; 			/* to delete a separator */
+
+	while( ci->nActiveChildren-- )
+	     DeleteMenu(ci->hWindowMenu,MF_BYPOSITION,ci->idFirstChild--);
 
 	return 0;
 
       case WM_MDIACTIVATE:
-	SetWindowPos((HWND)wParam,0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
+        if( ci->hwndActiveChild != (HWND)wParam )
+	    SetWindowPos((HWND)wParam, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE ); 
 	return 0;
 
       case WM_MDICASCADE:
@@ -923,14 +980,16 @@
 	       return 0;
 	
       case WM_MDIMAXIMIZE:
-	return MDIMaximizeChild(hwnd, (HWND)wParam, ci);
+	ShowWindow((HWND)wParam, SW_MAXIMIZE);
+	return 0;
 
       case WM_MDINEXT:
-	MDI_SwitchActiveChild(hwnd, (HWND)wParam, lParam);
+	MDI_SwitchActiveChild(hwnd, (HWND)wParam, (lParam)?1:0);
 	break;
 	
       case WM_MDIRESTORE:
-	return MDIRestoreChild(hwnd, ci);
+	ShowWindow( (HWND)wParam, SW_NORMAL);
+	return 0;
 
       case WM_MDISETMENU:
 #ifdef WINELIB32
@@ -942,7 +1001,7 @@
       case WM_MDITILE:
 	ci->sbStop = TRUE;
 	ShowScrollBar(hwnd,SB_BOTH,FALSE);
-	MDITile(hwnd, ci);
+	MDITile(hwnd, ci,wParam);
         ci->sbStop = FALSE;
         return 0;
 
@@ -964,17 +1023,25 @@
 	
       case WM_NCACTIVATE:
         if( ci->hwndActiveChild )
-	SendMessage(ci->hwndActiveChild, message, wParam, lParam);
+	     SendMessage(ci->hwndActiveChild, message, wParam, lParam);
 	break;
 	
       case WM_PARENTNOTIFY:
-	if (wParam == WM_LBUTTONDOWN)
+	if (wParam == WM_LBUTTONDOWN && (ci->hwndHitTest != ci->hwndActiveChild) )
 	     SetWindowPos(ci->hwndHitTest, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
 	break;
 
       case WM_SIZE:
-	GetClientRect(w->hwndParent, &ci->rectMaximize);
-	if( !ci->hwndActiveChild )
+	if( ci->flagChildMaximized )
+	  {
+	     WND*	child = WIN_FindWndPtr(ci->flagChildMaximized);
+	     RECT	rect  = { 0, 0, LOWORD(lParam), HIWORD(lParam) };
+
+	     AdjustWindowRectEx(&rect, child->dwStyle, 0, child->dwExStyle);
+	     MoveWindow(ci->flagChildMaximized, rect.left, rect.top,
+			rect.right - rect.left, rect.bottom - rect.top, 1);
+	  }
+	else
 	  {
 	     PostMessage(hwnd,WM_MDICALCCHILDSCROLL,0,0L);
 	     ci->sbRecalc |= (SB_BOTH+1);
@@ -1001,36 +1068,57 @@
 LRESULT DefFrameProc(HWND hwnd, HWND hwndMDIClient, UINT message, 
 		     WPARAM wParam, LPARAM lParam)
 {
-    HWND	childHwnd;
+    HWND	         childHwnd;
+    MDICLIENTINFO*       ci;
+    WND*                 wndPtr;
 
     if (hwndMDIClient)
     {
 	switch (message)
 	{
 	  case WM_COMMAND:
-	    childHwnd = MDI_GetChildByID( WIN_FindWndPtr(hwndMDIClient),
+	    wndPtr = WIN_FindWndPtr(hwndMDIClient);
+	    ci     = (MDICLIENTINFO*)wndPtr->wExtra;
+
+	    /* check for possible system command codes */
+
+	    if( wParam <  ci->idFirstChild || 
+		wParam >= ci->idFirstChild + ci->nActiveChildren )
+	      {
+		if( (wParam - 0xF000) & 0xF00F ) break;
+		switch( wParam )
+		  {
+		    case SC_SIZE:
+		    case SC_MOVE:
+		    case SC_MINIMIZE:
+		    case SC_MAXIMIZE:
+		    case SC_NEXTWINDOW:
+		    case SC_PREVWINDOW:
+		    case SC_CLOSE:
+		    case SC_RESTORE:
+		       if( ci->flagChildMaximized )
+			   return SendMessage( ci->flagChildMaximized, WM_SYSCOMMAND,
+					       wParam, lParam);
+		  }
+	      }
+	    else
+	      {
+	    	childHwnd = MDI_GetChildByID( WIN_FindWndPtr(hwndMDIClient),
                                           wParam );
- 	    if( childHwnd )
-#ifdef WINELIB32 /* FIXME: need to find out the equivalent Win32 message */
-	        SendMessage(hwndMDIClient, WM_MDIACTIVATE, 0 , 0);
-#else
-	        SendMessage(hwndMDIClient, WM_MDIACTIVATE, childHwnd , 0L);
-#endif
+ 	    	if( childHwnd )
+	            SendMessage(hwndMDIClient, WM_MDIACTIVATE, (WPARAM)childHwnd , 0L);
+	      }
 	    break;
 
-	  case WM_NCLBUTTONDOWN:
-	    if (MDIHandleLButton(hwnd, hwndMDIClient, wParam, lParam))
-		return 0;
-	    break;
-	    
 	  case WM_NCACTIVATE:
 	    SendMessage(hwndMDIClient, message, wParam, lParam);
-	    return MDIPaintMaximized(hwnd, hwndMDIClient, 
-				     message, wParam, lParam);
+	    break;
 
-	  case WM_NCPAINT:
-	    return MDIPaintMaximized(hwnd, hwndMDIClient, 
-				     message, wParam, lParam);
+	  case WM_SETTEXT:
+	    MDI_UpdateFrameText(hwnd, hwndMDIClient, 
+				      MDI_REPAINTFRAME, 
+			             (LPCSTR)PTR_SEG_TO_LIN(lParam));
+	    return 0;
 	
 	  case WM_SETFOCUS:
 	    SetFocus(hwndMDIClient);
@@ -1061,7 +1149,7 @@
 
     clientWnd  = WIN_FindWndPtr(GetParent(hwnd));
     ci         = (MDICLIENTINFO *) clientWnd->wExtra;
-    
+
     switch (message)
     {
       case WM_NCHITTEST:
@@ -1071,13 +1159,16 @@
       case WM_SETTEXT:
 	DefWindowProc(hwnd, message, wParam, lParam);
 	MDI_MenuModifyItem(clientWnd,hwnd);
+	if( ci->flagChildMaximized == hwnd )
+	    MDI_UpdateFrameText( clientWnd->hwndParent, ci->self,
+				 MDI_REPAINTFRAME, NULL );
         return 0;
 
       case WM_CLOSE:
-	SendMessage(GetParent(hwnd),WM_MDIDESTROY,(WPARAM)hwnd,0L);
+	SendMessage(ci->self,WM_MDIDESTROY,(WPARAM)hwnd,0L);
 	return 0;
 
-      case WM_SIZE:
+      case WM_SETFOCUS:
 	if( ci->hwndActiveChild != hwnd )
 	    MDI_ChildActivate(clientWnd, hwnd);
 	break;
@@ -1092,35 +1183,82 @@
 	break;
 
       case WM_SYSCOMMAND:
-	switch (wParam)
-	{
-	  case SC_MAXIMIZE:
-	    return SendMessage(GetParent(hwnd), WM_MDIMAXIMIZE, (WPARAM)hwnd, 0);
-
-	  case SC_RESTORE:
-	    return SendMessage(GetParent(hwnd), WM_MDIRESTORE, (WPARAM)hwnd, 0);
-	}
+	switch( wParam )
+	  {
+		case SC_MOVE:
+		     if( ci->flagChildMaximized == hwnd) return 0;
+		     break;
+		case SC_MAXIMIZE:
+		     if( ci->flagChildMaximized == hwnd) 
+			 return SendMessage( clientWnd->hwndParent, message, wParam, lParam);
+		     break;
+		case SC_NEXTWINDOW:
+		     SendMessage( ci->self, WM_MDINEXT, 0, 0);
+		     return 0;
+		case SC_PREVWINDOW:
+		     SendMessage( ci->self, WM_MDINEXT, 0, 1);
+		     return 0;
+	  }
 	break;
 	
-      /* should also handle following messages */
       case WM_GETMINMAXINFO:
-	   /* should return rect of MDI client 
-	    * so that normal ShowWindow will be able to handle
-	    * actions that are handled by MDIMaximize and MDIRestore */
+	MDI_ChildGetMinMaxInfo(clientWnd, hwnd, (MINMAXINFO*) PTR_SEG_TO_LIN(lParam));
+	return 0;
 
       case WM_SETVISIBLE:
-         if( !ci->sbStop )
+         if( !ci->sbStop && !ci->flagChildMaximized)
           {
-            PostMessage(GetParent(hwnd),WM_MDICALCCHILDSCROLL,0,0L);
+            PostMessage(ci->self,WM_MDICALCCHILDSCROLL,0,0L);
             ci->sbRecalc |= (SB_BOTH+1);
           }
 	break;
-      case WM_SETFOCUS:
-	if( IsChild( GetActiveWindow(), GetParent(hwnd)) )
-	    SendMessage(clientWnd->hwndChild,WM_CHILDACTIVATE,0,0L);
+
+      case WM_SIZE:
+	/* do not change */
+
+	if( ci->hwndActiveChild == hwnd && wParam != SIZE_MAXIMIZED )
+	  {
+  	    ci->flagChildMaximized = 0;
+	    
+	    MDI_RestoreFrameMenu( clientWnd->hwndParent, hwnd);
+            MDI_UpdateFrameText( clientWnd->hwndParent, ci->self,
+                                 MDI_REPAINTFRAME, NULL );
+	  }
+
+	if( wParam == SIZE_MAXIMIZED )
+	  {
+	    HWND hMaxChild = ci->flagChildMaximized;
+
+	    if( hMaxChild == hwnd ) break;
+
+	    if( hMaxChild)
+	      {	    
+	       SendMessage( hMaxChild, WM_SETREDRAW, FALSE, 0L );
+
+	       MDI_RestoreFrameMenu( clientWnd->hwndParent, hMaxChild);
+	       ShowWindow( hMaxChild, SW_SHOWNOACTIVATE);
+
+	       SendMessage( hMaxChild, WM_SETREDRAW, TRUE, 0L );
+	      }
+
+	    ci->flagChildMaximized = hwnd; /* !!! */
+
+	    MDI_AugmentFrameMenu( ci, clientWnd->hwndParent, hwnd);
+	    MDI_UpdateFrameText( clientWnd->hwndParent, ci->self,
+				 MDI_REPAINTFRAME, NULL ); 
+	  }
+
+	if( wParam == SIZE_MINIMIZED )
+	  {
+	    HWND switchTo = MDI_GetWindow(clientWnd, hwnd, 0);
+
+	    if( switchTo )
+	        SendMessage( switchTo, WM_CHILDACTIVATE, 0, 0L);
+	  }
+	    
         if( !ci->sbStop )
           {
-            PostMessage(GetParent(hwnd),WM_MDICALCCHILDSCROLL,0,0L);
+            PostMessage(ci->self,WM_MDICALCCHILDSCROLL,0,0L);
             ci->sbRecalc |= (SB_BOTH+1);
           }
 	break;
@@ -1141,7 +1279,38 @@
  */
 BOOL TranslateMDISysAccel(HWND hwndClient, LPMSG msg)
 {
+  WND* clientWnd = WIN_FindWndPtr( hwndClient);
+  WND* wnd;
+  MDICLIENTINFO       *ci     = NULL;
+  WPARAM	       wParam = 0;
+
+  if( (msg->message != WM_KEYDOWN && msg->message != WM_SYSKEYDOWN) || !clientWnd )
     return 0;
+
+  ci = (MDICLIENTINFO*) clientWnd->wExtra;
+  wnd = WIN_FindWndPtr(ci->hwndActiveChild);
+ 
+  if( !wnd ) return 0;
+  
+  if( wnd->dwStyle & WS_DISABLED ) return 0;
+   
+  if( GetKeyState(VK_CONTROL) && !GetKeyState(VK_MENU) )
+    switch( msg->wParam )
+      {
+	case VK_F6:
+	case VK_SEPARATOR:
+	     wParam = (GetKeyState(VK_SHIFT))? SC_NEXTWINDOW: SC_PREVWINDOW;
+	     break;
+	case VK_RBUTTON:
+	     wParam = SC_CLOSE; 
+	default:
+	     return 0;
+      }
+
+  dprintf_mdi(stddeb,"TranslateMDISysAccel: wParam = "NPFMT"\n", wParam);
+
+  SendMessage(ci->hwndActiveChild,WM_SYSCOMMAND, wParam, (LPARAM)msg->wParam);
+  return 1;
 }
 
 
diff --git a/windows/message.c b/windows/message.c
index 458232c..a197f37 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -36,8 +36,6 @@
 
 static HANDLE hmemSysMsgQueue = 0;
 static MESSAGEQUEUE *sysMsgQueue = NULL;
-
-HANDLE hActiveQ_G      = 0;
 static HANDLE hFirstQueue = 0;
 
 /* ------- Miscellaneous ------ */
@@ -47,7 +45,7 @@
 /***********************************************************************
  *           MSG_CreateMsgQueue
  *
- * Create a message queue.
+ * Creates a message queue. Doesn't link it into queue list!
  */
 static HANDLE MSG_CreateMsgQueue( int size )
 {
@@ -66,44 +64,35 @@
     return hQueue;
 }
 
+
 /***********************************************************************
  *	     MSG_DeleteMsgQueue
+ *
+ * Unlinks and deletes a message queue.
  */
 BOOL MSG_DeleteMsgQueue( HANDLE hQueue )
 {
- MESSAGEQUEUE * msgQueue = (MESSAGEQUEUE*)GlobalLock(hQueue);
+    MESSAGEQUEUE * msgQueue = (MESSAGEQUEUE*)GlobalLock(hQueue);
+    HANDLE *pPrev;
 
- if( !hQueue )
-   {
+    if (!hQueue || !msgQueue)
+    {
 	dprintf_msg(stddeb,"DeleteMsgQueue: invalid argument.\n");
 	return 0;
-   }
+    }
 
- if( !msgQueue ) return 0;
-
- if( hQueue == hFirstQueue )
-	hFirstQueue = msgQueue->next;
- else if( hFirstQueue )
-	{
-	  MESSAGEQUEUE *msgQ = (MESSAGEQUEUE*)GlobalLock(hFirstQueue);
-
-	  /* walk up queue list and relink if needed */
-	  while( msgQ->next )
-	    {
-		if( msgQ->next == hQueue )
-		    msgQ->next = msgQueue->next;
-
-		/* should check for intertask sendmessages here */
-
-
-	        msgQ = (MESSAGEQUEUE*)GlobalLock(msgQ->next);
-	    }
-	}
-
- GlobalFree( hQueue );
- return 1;
+    pPrev = &hFirstQueue;
+    while (*pPrev && (*pPrev != hQueue))
+    {
+        MESSAGEQUEUE *msgQ = (MESSAGEQUEUE*)GlobalLock(*pPrev);
+        pPrev = &msgQ->next;
+    }
+    if (*pPrev) *pPrev = msgQueue->next;
+    GlobalFree( hQueue );
+    return 1;
 }
 
+
 /***********************************************************************
  *           MSG_CreateSysMsgQueue
  *
@@ -674,58 +663,27 @@
  */
 BOOL SetMessageQueue( int size )
 {
-    HGLOBAL  	  hQueue    = 0;
-    HGLOBAL  	  hNextQueue= hFirstQueue;
-    MESSAGEQUEUE *queuePrev = NULL;
+    HANDLE hQueue, hNewQueue;
     MESSAGEQUEUE *queuePtr;
 
     if ((size > MAX_QUEUE_SIZE) || (size <= 0)) return TRUE;
 
-      /* Free the old message queue */
-    if ((hQueue = GetTaskQueue(0)) != 0)
+    if( !(hNewQueue = MSG_CreateMsgQueue( size ))) 
     {
-	MESSAGEQUEUE *queuePtr = (MESSAGEQUEUE *)GlobalLock( hQueue );
-	
-	if( queuePtr )
-	{
-	    MESSAGEQUEUE *msgQ = (MESSAGEQUEUE*)GlobalLock(hFirstQueue);
-
-	    hNextQueue = queuePtr->next;
-
-            if( msgQ )
-		if( hQueue != hFirstQueue )
-		    while( msgQ->next )
-		    { 
-			if( msgQ->next == hQueue )
-			{ 
-			    queuePrev = msgQ;
-			    break;
-			} 
-			msgQ = (MESSAGEQUEUE*)GlobalLock(msgQ->next);
-		    }
-	    GlobalUnlock( hQueue );
-	    MSG_DeleteMsgQueue( hQueue );
-	}
-    }
-  
-    if( !(hQueue = MSG_CreateMsgQueue( size ))) 
-    {
-	if(queuePrev) 
-	    /* it did have a queue */
-	    queuePrev->next = hNextQueue;
+	dprintf_msg(stddeb,"SetMessageQueue: failed!\n");
 	return FALSE;
     }
-  
-    queuePtr = (MESSAGEQUEUE *)GlobalLock( hQueue );
+
+    /* Free the old message queue */
+    if ((hQueue = GetTaskQueue(0)) != 0) MSG_DeleteMsgQueue( hQueue );
+
+    /* Link new queue into list */
+    queuePtr = (MESSAGEQUEUE *)GlobalLock( hNewQueue );
     queuePtr->hTask = GetCurrentTask();
-    queuePtr->next  = hNextQueue;
+    queuePtr->next  = hFirstQueue;
+    hFirstQueue = hNewQueue;
 
-    if( !queuePrev )  
-         hFirstQueue = hQueue;
-    else
-	 queuePrev->next = hQueue;
-
-    SetTaskQueue( 0, hQueue );
+    SetTaskQueue( 0, hNewQueue );
     return TRUE;
 }
 
@@ -761,7 +719,7 @@
 /***********************************************************************
  *           GetQueueStatus   (USER.334)
  */
-DWORD GetQueueStatus( int flags )
+DWORD GetQueueStatus( UINT flags )
 {
     MESSAGEQUEUE *queue;
     DWORD ret;
diff --git a/windows/msgbox.c b/windows/msgbox.c
index a83b8cc..59f61cc 100644
--- a/windows/msgbox.c
+++ b/windows/msgbox.c
@@ -15,8 +15,8 @@
 #include "task.h"
 
 typedef struct {
-  LPSTR	title;
-  LPSTR text;
+  LPCSTR title;
+  LPCSTR text;
   WORD  type;
 } MSGBOX, *LPMSGBOX;
 
@@ -179,7 +179,7 @@
  *			MessageBox  [USER.1]
  */
 
-int MessageBox(HWND hWnd, LPSTR text, LPSTR title, WORD type)
+int MessageBox(HWND hWnd, LPCSTR text, LPCSTR title, WORD type)
 {
     HANDLE handle;
     MSGBOX mbox;
@@ -214,7 +214,7 @@
  *			FatalAppExit  [USER.137]
  */
 
-void FatalAppExit(WORD wAction, LPSTR str)
+void FatalAppExit(UINT fuAction, LPCSTR str)
 {
   MessageBox(0, str, NULL, MB_SYSTEMMODAL | MB_OK);
   TASK_KillCurrentTask(0);
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 863b1c1..e19ccf6 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -93,16 +93,16 @@
 /***********************************************************************
  *           AdjustWindowRect    (USER.102)
  */
-void AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
+BOOL AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
 {
-    AdjustWindowRectEx( rect, style, menu, 0 );
+    return AdjustWindowRectEx( rect, style, menu, 0 );
 }
 
 
 /***********************************************************************
  *           AdjustWindowRectEx    (USER.454)
  */
-void AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
+BOOL AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
 {
       /* Correct the window style */
 
@@ -115,6 +115,7 @@
       style, menu, exStyle );
 
     NC_AdjustRect( rect, style, menu, exStyle );
+    return TRUE;
 }
 
 
diff --git a/windows/utility.c b/windows/utility.c
index d0cb299..e3e1780 100644
--- a/windows/utility.c
+++ b/windows/utility.c
@@ -28,14 +28,30 @@
  *	and divides by a third integer.
  */
 
-int MulDiv(int foo, int bar, int baz)
+#ifdef WINELIB32
+INT MulDiv(INT foo, INT bar, INT baz)
+{
+#ifdef __GNUC__
+    long long ret;
+    if (!baz) return -1;
+    ret = ((long long)foo * bar) / baz;
+    if ((ret > 2147483647) || (ret < -2147483647)) return -1;
+    return ret;
+#else
+    if (!baz) return -1;
+    return (foo * bar) / baz;
+#endif
+}
+#else  /* WINELIB32 */
+INT MulDiv(INT foo, INT bar, INT baz)
 {
     int ret;
     if (!baz) return -32768;
     ret = (foo * bar) / baz;
     if ((ret > 32767) || (ret < -32767)) return -32768;
     return ret;
-};
+}
+#endif
 
 /*	UTILITY_strip015() removes \015 (^M, CR) from a string;
  *	this is done to convert a MS-DOS-style string to a more
diff --git a/windows/win.c b/windows/win.c
index 1c7d895..d9aaa3a 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -601,11 +601,12 @@
 /***********************************************************************
  *           CloseWindow   (USER.43)
  */
-void CloseWindow(HWND hWnd)
+BOOL CloseWindow(HWND hWnd)
 {
     WND * wndPtr = WIN_FindWndPtr(hWnd);
-    if (wndPtr->dwStyle & WS_CHILD) return;
+    if (wndPtr->dwStyle & WS_CHILD) return TRUE;
     ShowWindow(hWnd, SW_MINIMIZE);
+    return TRUE;
 }
 
  
@@ -850,7 +851,7 @@
     SendMessage( hwnd, WM_SETTEXT, 0, (DWORD)lpString );
 }
 
-void SetWindowText( HWND hwnd, LPSTR lpString )
+void SetWindowText( HWND hwnd, LPCSTR lpString )
 {
     HANDLE handle;
 
@@ -1395,8 +1396,6 @@
  HWND		hCurrentWnd = 0;
  WORD	        btemp;
 
- fprintf(stdnimp,"DragObject: experimental\n"); 
-
  lpDragInfo = (LPDRAGINFO) GlobalLock(hDragInfo);
  spDragInfo = (SEGPTR) WIN16_GlobalLock(hDragInfo);
 
diff --git a/windows/winpos.c b/windows/winpos.c
index 3a7eb9f..04dcb66 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -2,7 +2,7 @@
  * Window position related functions.
  *
  * Copyright 1993, 1994, 1995 Alexandre Julliard
- *                       1995 Alex Korobka
+ *                       1995,1996 Alex Korobka
  */
 
 #include "sysmetrics.h"
@@ -28,8 +28,6 @@
 static HWND hwndActive      = 0;  /* Currently active window */
 static HWND hwndPrevActive  = 0;  /* Previously active window */
 
-extern HANDLE hActiveQ_G;		/* from message.c */
-
 
 /***********************************************************************
  *           WINPOS_FindIconPos
@@ -89,11 +87,11 @@
 /***********************************************************************
  *           ArrangeIconicWindows   (USER.170)
  */
-WORD ArrangeIconicWindows( HWND parent )
+UINT ArrangeIconicWindows( HWND parent )
 {
     RECT rectParent;
     HWND hwndChild;
-    short x, y, xspacing, yspacing;
+    INT x, y, xspacing, yspacing;
 
     GetClientRect( parent, &rectParent );
     x = rectParent.left;
@@ -153,9 +151,10 @@
 /*******************************************************************
  *         ClientToScreen   (USER.28)
  */
-void ClientToScreen( HWND hwnd, LPPOINT lppnt )
+BOOL ClientToScreen( HWND hwnd, LPPOINT lppnt )
 {
     MapWindowPoints( hwnd, 0, lppnt, 1 );
+    return TRUE;
 }
 
 
@@ -169,38 +168,81 @@
 
 
 /*******************************************************************
+ *         WINPOS_WindowFromPoint 
+ *
+ * The Right Thing
+ */
+HWND WINPOS_WindowFromPoint( HWND hScope, POINT pt, WORD* lpht )
+{
+ WORD   wRet;
+ WND*	wndPtr = WIN_FindWndPtr( hScope );
+
+ if( !wndPtr || !(wndPtr->dwStyle & WS_VISIBLE) ) return 0;
+
+ if ((pt.x <  wndPtr->rectWindow.left)  ||
+     (pt.x >= wndPtr->rectWindow.right) ||
+     (pt.y <  wndPtr->rectWindow.top)   ||
+     (pt.y >= wndPtr->rectWindow.bottom)) return 0; 
+
+ /* pt is inside hScope window */
+
+ if( wndPtr->dwStyle & WS_DISABLED )
+   if( wndPtr->dwStyle & (WS_POPUP | WS_CHILD) == WS_CHILD )
+       return 0;
+   else
+     {
+       if( lpht ) *lpht = HTERROR;
+       return hScope;
+     }  
+
+ if( wndPtr->dwStyle & WS_MINIMIZE )
+   {
+     if( lpht ) *lpht = HTCAPTION;
+     return hScope; 
+   }  
+
+ if( PtInRect(&wndPtr->rectClient, pt))
+   {
+     /* look among children */
+     HWND   hwnd     = wndPtr->hwndChild;
+     WND*   wndChild = WIN_FindWndPtr(hwnd);
+     POINT  ptChild  = { pt.x - wndPtr->rectClient.left,
+		         pt.y - wndPtr->rectClient.top };
+
+     while( wndChild )
+      {      
+            if( (hwnd = WINPOS_WindowFromPoint(hwnd, ptChild, lpht)) ) 
+                return hwnd;
+
+	    hwnd = wndChild->hwndNext;
+	    wndChild = WIN_FindWndPtr( hwnd );
+      }
+   }
+
+ /* don't do intertask sendmessage */ 
+ if( wndPtr->hmemTaskQ == GetTaskQueue(0) ) 
+   {
+      if( wndPtr->dwStyle & WS_CHILD )
+          MapWindowPoints( hScope, GetDesktopWindow(), &pt, 1);
+
+      wRet = SendMessage( hScope, WM_NCHITTEST, 0, MAKELONG( pt.x, pt.y ));
+      if( wRet == (WORD)HTTRANSPARENT )
+          return 0;
+   }
+ else
+      wRet = HTCLIENT;
+
+ if( lpht ) *lpht = wRet;
+ return hScope;
+}
+
+
+/*******************************************************************
  *         WindowFromPoint   (USER.30)
  */
 HWND WindowFromPoint( POINT pt )
 {
-    HWND hwndRet = 0;
-    HWND hwnd = GetDesktopWindow();
-
-    while(hwnd)
-    {
-	  /* If point is in window, and window is visible,   */
-	  /* not disabled and not transparent, then explore  */
-	  /* its children. Otherwise, go to the next window. */
-
-	WND *wndPtr = WIN_FindWndPtr( hwnd );
-	if ((pt.x >= wndPtr->rectWindow.left) &&
-	    (pt.x < wndPtr->rectWindow.right) &&
-	    (pt.y >= wndPtr->rectWindow.top) &&
-	    (pt.y < wndPtr->rectWindow.bottom) &&
-	    !(wndPtr->dwStyle & WS_DISABLED) &&
-	    (wndPtr->dwStyle & WS_VISIBLE) &&
-	    !(wndPtr->dwExStyle & WS_EX_TRANSPARENT))
-	{
-	    hwndRet = hwnd;
-              /* If window is minimized, ignore its children */
-            if (wndPtr->dwStyle & WS_MINIMIZE) break;
-	    pt.x -= wndPtr->rectClient.left;
-	    pt.y -= wndPtr->rectClient.top;
-	    hwnd = wndPtr->hwndChild;
-	}
-	else hwnd = wndPtr->hwndNext;
-    }
-    return hwndRet;
+   return WINPOS_WindowFromPoint( GetDesktopWindow(), pt , NULL );
 }
 
 
@@ -235,6 +277,8 @@
     POINT origin = { 0, 0 };
     WORD i;
 
+    if( hwndFrom == hwndTo ) return;
+
       /* Translate source window origin to screen coords */
     while(hwndFrom)
     {
@@ -602,6 +646,7 @@
     FARPROC                enumCallback    = (FARPROC)GetWndProcEntry16("ActivateAppProc");
     ACTIVATESTRUCT         actStruct;
     WORD                   wIconized=0,wRet= 0;
+    HANDLE                 hActiveQ = 0;
 
     /* paranoid checks */
     if( !hWnd || hWnd == GetDesktopWindow() || hWnd == hwndActive )
@@ -676,10 +721,16 @@
 
     if( !IsWindow(hWnd) ) return 0;
 
-    /* send WM_ACTIVATEAPP if necessary */
-    if( hActiveQ_G != wndPtr->hmemTaskQ )
+    if (hwndPrevActive)
     {
-	HTASK hT = MSG_GetQueueTask( hActiveQ_G );
+        wndTemp = WIN_FindWndPtr( hwndPrevActive );
+        if (wndTemp) hActiveQ = wndTemp->hmemTaskQ;
+    }
+
+    /* send WM_ACTIVATEAPP if necessary */
+    if (hActiveQ != wndPtr->hmemTaskQ)
+    {
+	HTASK hT = MSG_GetQueueTask( hActiveQ );
 
 	actStruct.wFlag = 0;                  /* deactivate */
 	actStruct.hWindowTask = MSG_GetQueueTask(wndPtr->hmemTaskQ);
@@ -690,12 +741,9 @@
 	 */
 	EnumWindows( enumCallback , (LPARAM)&actStruct );
 
-	/* change active queue */
-	hActiveQ_G = wndPtr->hmemTaskQ;
-
 	actStruct.wFlag = 1;                  /* activate */
 	actStruct.hWindowTask = hT;
-	actStruct.hTaskSendTo = MSG_GetQueueTask( hActiveQ_G );
+	actStruct.hTaskSendTo = MSG_GetQueueTask( wndPtr->hmemTaskQ );
 
 	EnumWindows( enumCallback , (LPARAM)&actStruct );
 
@@ -964,6 +1012,11 @@
     if (hwnd == GetDesktopWindow()) return FALSE;
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
 
+    /* Check for windows that may not be resized 
+       FIXME: this should be done only for Windows 3.0 programs */
+    if (flags ==(SWP_SHOWWINDOW) || flags ==(SWP_HIDEWINDOW ) )
+       flags |= SWP_NOSIZE | SWP_NOMOVE;
+
       /* Check dimensions */
 
     if (cx <= 0) cx = 1;
diff --git a/wine.ini b/wine.ini
index faa56fc..51a6745 100644
--- a/wine.ini
+++ b/wine.ini
@@ -1,36 +1,59 @@
-

-[drives]

-A=/mnt/fd0

-C=/dos

-D=/usr/windows

-E=/home/bob/wine/work

-F=/home/bob/test

-

-[wine]

-Windows=c:\windows

-System=c:\windows\system

-Temp=c:\temp

-Path=c:\windows;c:\windows\system;e:\;e:\test;f:\

-SymbolTableFile=./wine.sym

-

-[fonts]

-system=*-helvetica

-mssansserif=*-helvetica

-msserif=*-times

-fixedsys=*-fixed

-arial=*-helvetica

-helv=*-helvetica

-roman=*-times

-default=*-*

-

-[serialports]

-Com1=/dev/cua0

-Com2=/dev/cua1

-Com3=/dev/modem,38400

-Com4=/dev/modem

-

-[parallelports]

-Lpt1=/dev/lp0

-

-[spy]

-Exclude=WM_SIZE;WM_TIMER;

+;;
+;; MS-DOS drives configuration
+;;
+;; Each section has the following format:
+;; [Drive X]
+;; Path=xxx    (Unix path for drive root)
+;; Type=xxx    (supported types are 'floppy', 'hd', 'cdrom' and 'network')
+;; Label=xxx   (drive label, at most 11 characters)
+;; Serial=xxx  (serial number, 8 characters hexadecimal number)
+;;
+[Drive A]
+Path=/mnt/fd0
+Type=floppy
+Label=Floppy
+Serial=87654321
+
+[Drive C]
+Path=/c
+Type=hd
+Label=MS-DOS
+
+[Drive D]
+Path=/cdrom
+Type=cdrom
+Label=CD-Rom
+
+[Drive E]
+Path=/tmp
+Type=hd
+Label=Tmp Drive
+
+[wine]
+Windows=c:\windows
+System=c:\windows\system
+Temp=e:\
+Path=c:\windows;c:\windows\system;e:\;e:\test;f:\
+SymbolTableFile=./wine.sym
+
+[fonts]
+system=*-helvetica
+mssansserif=*-helvetica
+msserif=*-times
+fixedsys=*-fixed
+arial=*-helvetica
+helv=*-helvetica
+roman=*-times
+default=*-*
+
+[serialports]
+Com1=/dev/cua0
+Com2=/dev/cua1
+Com3=/dev/modem,38400
+Com4=/dev/modem
+
+[parallelports]
+Lpt1=/dev/lp0
+
+[spy]
+Exclude=WM_SIZE;WM_TIMER;
diff --git a/wine.man b/wine.man
index f585a53..11a4ad8 100644
--- a/wine.man
+++ b/wine.man
@@ -44,12 +44,16 @@
 was, or the sources may be FTP'd from ftp.x.org).
 .SH INSTALLATION
 To install 
-.B wine,
+.B Wine,
 run "./configure", which will detect your specific setup and create
 the Makefiles. You can run "./configure --help" to see the available
 configuration options. Then do "make depend; make" to build the
 .B wine
-executable.
+executable, and then "make install" to install it. By default,
+.B wine
+is installed in /usr/local/bin; you can specify a different path with
+the --prefix option when running
+.B configure.
 .SH OPTIONS
 .TP
 .I -depth n
@@ -115,7 +119,7 @@
 Read only files may be opened in write mode
 .TP
 .I -enhanced
-Starts wine in Enhanced mode (not guaranteed to work yet)
+Starts wine in Enhanced mode
 .PD 1
 .SH PROGRAM/ARGUMENTS
 The program name may be specified in DOS format (C:\\WINDOWS\\SOL.EXE) or in 
@@ -130,31 +134,70 @@
 by placing all of them on the command line (such as: wine notepad clock).
 .SH CONFIGURATION FILE
 .B wine
-expects a configuration file (/usr/local/etc/wine.conf), 
-which should conform to the following rules.  The actual file name may
-be specified during the execution of the
+expects a configuration file (/usr/local/etc/wine.conf), which should
+conform to the following rules (the format is just like a Windows .ini
+file).  The actual file name may be specified during the execution of
+the
 .B configure
 script.  Alternatively, you may have a 
 .I .winerc
 file of this format in your home directory.
 .SH CONFIGURATION FILE FORMAT
-.B [drives]
+All entries are grouped in sections; a section begins with the line
 .br
-.I format: <driveletter> = <rootdirectory>
+.I [section name]
 .br
-default: none
+and continues until the next section starts. Individual entries
+consist of lines of the form
 .br
-This section is used to specify the root directory of each 
+.I entry=value
+.br
+The value can be any text string, optionally included in single or
+double quotes; it can also contain references to environment variables
+surrounded by
+.I ${}.
+Supported section names and entries are listed below.
+.PP
+.B [Drive X]
+.br
+This section is used to specify the root directory and type of each
 .B DOS
 drive, since most Windows applications require a DOS/MS-Windows based 
-disk drive & directory scheme.
+disk drive & directory scheme. There is one such section for every
+drive you want to configure.
+.PP
+.I format: Path = <rootdirectory>
+.br
+default: none
 .br
 If you mounted your dos partition as 
 .I /dos
 and installed Microsoft Windows in 
 C:\\WINDOWS then you should specify 
-.I c=/dos
-in the drives section.
+.I Path=/dos
+in the
+.I [Drive C]
+section.
+.PP
+.I format: Type = <type>
+.br
+default: hd
+.br
+Used to specify the drive type; supported types are floppy, hd, cdrom
+and network.
+.PP
+.I format: Label = <label>
+.br
+default: 'Drive X'
+.br
+Used to specify the drive label; limited to 11 characters.
+.PP
+.I format: Serial = <serial>
+.br
+default: 12345678
+.br
+Used to specify the drive serial number, as an 8-character hexadecimal
+number.
 .PP
 .B [wine]
 .br
@@ -225,14 +268,24 @@
 .br
 default: none
 .br Used to specify which messages will be included in the logfile.
-.SH SAMPLE wine.conf
-[drives]
+.SH SAMPLE CONFIGURATION FILE
+[Drive A]
 .br
-a=/mnt/fd0
+Path=/mnt/fd0
 .br
-c=/dos
+Type=floppy
+.PP
+[Drive C]
 .br
-d=~/Wine
+Path=/dos
+.br
+Type=hd
+.br
+Label=DOS disk
+.PP
+[Drive D]
+.br
+Path=${HOME}/Wine
 .PP
 [wine]
 .br
@@ -291,10 +344,6 @@
 at 100% (although rapidly improving).  Color support for other than 8bpp
 (256 colors) is currently flaky.
 .PP
-Currently, no directories in the path can have upper-case letters in them
-(ex. /msdos/driveC), as the conversions necessary to handle the msdos 
-filename conventions currently cause them to be lost.
-.PP
 A partial list of applications known to work with 
 .B wine
 include: sol, cruel, golf, clock, notepad, charmap, calc, and wzip11.