Release 960805

Sun Aug  4 18:18:48 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [controls/scroll.c]
	Attempted to implement undocumented scroll-bar messages.

	* [tools/build.c] [include/callback.h] [windows/winproc.c]
	CallTo16_* functions now get DS from the previous 16-bit stackframe.

	* [if1632/thunk.c] [include/callback.h]
	Added thunks to implement callbacks for the emulator. Now all the
	Enum* functions always take a real function pointer even in the
	emulator.
	
	* [loader/builtin.c]
	Removed binary search in BUILTIN_GetEntryPoint32(), as it didn't
 	work with NULL entry points. Using linear search now.

	* [loader/module.c]
	Implemented IsSharedSelector().

	* [loader/task.c]
	Changed SwitchStackTo/Back to use the instance data to store the
	previous stack instead of the TDB. Also copy the local variables
	onto the new stack.
	Added GetExeVersion() and SetTackSignalProc().
	Implemented SetSigHandler().

Sat Aug  3 22:19:00 1996  Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>

	* [controls/menu.c]
	"Fixed" problem in deleting menus where win32 could get into an
	endless loop when it crashed. I think I've fixed the symptoms, not
	the original problem so it might be worth further investigation.

	* [debugger/registers.c]
	Added missing #ifdefs on FS_REG and GS_REG, needed for FreeBSD to
	compile wine properly.

	* [files/dos_fs.c]
	Made DOSFS_Hash and DOSFS_Match non-static so they can be called
	from win32/findfile.c (q.v.).

	* [if1632/gdi32.spec]
	Added SetMapMode (call existing function)

	* [if1632/kernel32.spec]
	Added FindFirstFileA and SetFileAttributesA.

	* [if1632/user32.spec]
	Added BringWindowToTop, CreatePopupMenu, GetKeyState, GetParent,
	IsDlgButtonChecked (call existing functions) and IsDialogMessageA,
	UnhookWindowsHookEx.

	* [win32/file.c]
	Added stub function SetFileAttributes32A. It's a stub because I
	can't really work out what this function should do with most
	attributes in a Unix environment. Anyone care to expand it?

	* [win32/findfile.c]
	New file. Initial stab at FindFirstFile. This doesn't work as
	specified yet, though a lot of the groundwork is there. I haven't
	time to work on this for the next month, so if anyone wants to pick
	it up and run with it please do.

	* [win32/memory.c]
	Removed malloc.h from includes (covered by stdlib.h include, and
	gets rid of a warning in FreeBSD).

	* [win32/newfns.c]
	UnhookWindowsHookEx32A stub added.

	* [win32/user32.c]
	Added implementation of IsDialogMessage32A.

	* [windows/dialog.c]
	IsDlgButtonChecked now calls SendDlgItemMessage32A instead of
	SendDlgItemMessage16.

Sat Aug  3 18:00:00 1996 Alex Korobka <alex@phm30.pharm.sunysb.edu>

	* [windows/graphics.c]
	Removed rectangle checking (conflicted with nonstandard
	mapping modes). 

	* [windows/dialog.c]
	Added check for child-style dialogs to DS_ABSALIGN
	coordinate conversion.

	* [objects/color.c]
	Cleaned up misc. bits

Thu Aug  1 10:51:45 1996  Andrew Lewycky <plewycky@oise.utoronto.ca>

	* [windows/focus.c] [windows/event.c] [windows/win.c]
	  [windows/defdlg.c]
	Fixes to focusing and activation.

	* [windows/defdlg.c]
	Properly(?) handle DM_GETDEFID.

	* [controls/combo.c]
	Handle CB_FINDSTRINGEXACT, CB_SETEDITSEL, CB_GETEDITSEL.
	CBCheckSize: Adjust edit position.

Tue Jul 30 09:46:36 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [files/file.c] [include/file.h] [loader/module.c] [loader/ne_image.c]
	Pass HFILEs instead of unix-fds to self-loader code.

Mon Jul 29 21:48:25 1996  Albrecht Kleine  <kleine@ak.sax.de>

	* [include/metafile.h] [objects/metafile.c] [objects/text.c]
	Implemented handling of some new metafile records (META_...)
	in PlayMetaFileRecord(), rewrite of 'case META_EXTTEXTOUT'.
	Added functions like MF_StretchBlt() for usage in metafiles.
	Minor bugfix in CopyMetafile().

	* [objects/bitmap.c][objects/dib.c]
	Added check for metafile-DC in Bitmap and DIB functions:
	CreateCompatibleBitmap() etc.
diff --git a/ANNOUNCE b/ANNOUNCE
index cf7b48e..85363a8 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,13 +1,13 @@
-This is release 960728 of Wine, the MS Windows emulator.  This is still a
+This is release 960805 of Wine, the MS Windows emulator.  This is still a
 developer's only release.  There are many bugs and many unimplemented API
 features.  Most applications still do not work correctly.
 
 Patches should be submitted to "julliard@lrc.epfl.ch".  Please don't
 forget to include a ChangeLog entry.
 
-WHAT'S NEW with Wine-960728: (see ChangeLog for details)
-	- Many fixed to the palette management.
-	- DOS real-mode memory emulation.
+WHAT'S NEW with Wine-960805: (see ChangeLog for details)
+	- More metafile features.
+	- Some more Win32 code.
 	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -16,10 +16,10 @@
 the release is available at the ftp sites.  The sources will be available
 from the following locations:
 
-    sunsite.unc.edu:/pub/Linux/ALPHA/wine/development/Wine-960728.tar.gz
-    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960728.tar.gz
-    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960728.tar.gz
-    aris.com:/pub/linux/ALPHA/Wine/development/Wine-960728.tar.gz
+    sunsite.unc.edu:/pub/Linux/ALPHA/wine/development/Wine-960805.tar.gz
+    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960805.tar.gz
+    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960805.tar.gz
+    aris.com:/pub/linux/ALPHA/Wine/development/Wine-960805.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
diff --git a/ChangeLog b/ChangeLog
index 43a3c8f..7ce0a96 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,126 @@
 ----------------------------------------------------------------------
+Sun Aug  4 18:18:48 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>
+
+	* [controls/scroll.c]
+	Attempted to implement undocumented scroll-bar messages.
+
+	* [tools/build.c] [include/callback.h] [windows/winproc.c]
+	CallTo16_* functions now get DS from the previous 16-bit stackframe.
+
+	* [if1632/thunk.c] [include/callback.h]
+	Added thunks to implement callbacks for the emulator. Now all the
+	Enum* functions always take a real function pointer even in the
+	emulator.
+	
+	* [loader/builtin.c]
+	Removed binary search in BUILTIN_GetEntryPoint32(), as it didn't
+ 	work with NULL entry points. Using linear search now.
+
+	* [loader/module.c]
+	Implemented IsSharedSelector().
+
+	* [loader/task.c]
+	Changed SwitchStackTo/Back to use the instance data to store the
+	previous stack instead of the TDB. Also copy the local variables
+	onto the new stack.
+	Added GetExeVersion() and SetTackSignalProc().
+	Implemented SetSigHandler().
+
+Sat Aug  3 22:19:00 1996  Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>
+
+	* [controls/menu.c]
+	"Fixed" problem in deleting menus where win32 could get into an
+	endless loop when it crashed. I think I've fixed the symptoms, not
+	the original problem so it might be worth further investigation.
+
+	* [debugger/registers.c]
+	Added missing #ifdefs on FS_REG and GS_REG, needed for FreeBSD to
+	compile wine properly.
+
+	* [files/dos_fs.c]
+	Made DOSFS_Hash and DOSFS_Match non-static so they can be called
+	from win32/findfile.c (q.v.).
+
+	* [if1632/gdi32.spec]
+	Added SetMapMode (call existing function)
+
+	* [if1632/kernel32.spec]
+	Added FindFirstFileA and SetFileAttributesA.
+
+	* [if1632/user32.spec]
+	Added BringWindowToTop, CreatePopupMenu, GetKeyState, GetParent,
+	IsDlgButtonChecked (call existing functions) and IsDialogMessageA,
+	UnhookWindowsHookEx.
+
+	* [win32/file.c]
+	Added stub function SetFileAttributes32A. It's a stub because I
+	can't really work out what this function should do with most
+	attributes in a Unix environment. Anyone care to expand it?
+
+	* [win32/findfile.c]
+	New file. Initial stab at FindFirstFile. This doesn't work as
+	specified yet, though a lot of the groundwork is there. I haven't
+	time to work on this for the next month, so if anyone wants to pick
+	it up and run with it please do.
+
+	* [win32/memory.c]
+	Removed malloc.h from includes (covered by stdlib.h include, and
+	gets rid of a warning in FreeBSD).
+
+	* [win32/newfns.c]
+	UnhookWindowsHookEx32A stub added.
+
+	* [win32/user32.c]
+	Added implementation of IsDialogMessage32A.
+
+	* [windows/dialog.c]
+	IsDlgButtonChecked now calls SendDlgItemMessage32A instead of
+	SendDlgItemMessage16.
+
+Sat Aug  3 18:00:00 1996 Alex Korobka <alex@phm30.pharm.sunysb.edu>
+
+	* [windows/graphics.c]
+	Removed rectangle checking (conflicted with nonstandard
+	mapping modes). 
+
+	* [windows/dialog.c]
+	Added check for child-style dialogs to DS_ABSALIGN
+	coordinate conversion.
+
+	* [objects/color.c]
+	Cleaned up misc. bits
+
+Thu Aug  1 10:51:45 1996  Andrew Lewycky <plewycky@oise.utoronto.ca>
+
+	* [windows/focus.c] [windows/event.c] [windows/win.c]
+	  [windows/defdlg.c]
+	Fixes to focusing and activation.
+
+	* [windows/defdlg.c]
+	Properly(?) handle DM_GETDEFID.
+
+	* [controls/combo.c]
+	Handle CB_FINDSTRINGEXACT, CB_SETEDITSEL, CB_GETEDITSEL.
+	CBCheckSize: Adjust edit position.
+
+Tue Jul 30 09:46:36 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
+
+	* [files/file.c] [include/file.h] [loader/module.c] [loader/ne_image.c]
+	Pass HFILEs instead of unix-fds to self-loader code.
+
+Mon Jul 29 21:48:25 1996  Albrecht Kleine  <kleine@ak.sax.de>
+
+	* [include/metafile.h] [objects/metafile.c] [objects/text.c]
+	Implemented handling of some new metafile records (META_...)
+	in PlayMetaFileRecord(), rewrite of 'case META_EXTTEXTOUT'.
+	Added functions like MF_StretchBlt() for usage in metafiles.
+	Minor bugfix in CopyMetafile().
+
+	* [objects/bitmap.c][objects/dib.c]
+	Added check for metafile-DC in Bitmap and DIB functions:
+	CreateCompatibleBitmap() etc.
+
+----------------------------------------------------------------------
 Sun Jul 28 17:57:19 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>
 
 	* [loader/task.c] [include/task.h]
diff --git a/controls/combo.c b/controls/combo.c
index 4990654..d7563a9 100644
--- a/controls/combo.c
+++ b/controls/combo.c
@@ -15,10 +15,10 @@
 
 #include "windows.h"
 #include "sysmetrics.h"
+#include "win.h"
 #include "combo.h"
 #include "stackframe.h"
 #include "user.h"
-#include "win.h"
 #include "graphics.h"
 #include "heap.h"
 #include "listbox.h"
@@ -469,6 +469,15 @@
 }
 
 /***********************************************************************
+ *           CBFindStringExact
+ */
+static LRESULT CBFindStringExact(HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  LPHEADLIST lphl = ComboGetListHeader(hwnd);
+  return ListBoxFindStringExact(lphl, wParam, (SEGPTR)lParam);
+}
+
+/***********************************************************************
  *           CBGetCount
  */
 static LRESULT CBGetCount(HWND hwnd, WPARAM wParam, LPARAM lParam)
@@ -621,7 +630,7 @@
   LPHEADCOMBO  lphc = ComboGetStorageHeader(hwnd);
   LPHEADLIST   lphl = ComboGetListHeader(hwnd);
   LONG         cstyle = GetWindowLong32A(hwnd,GWL_STYLE);
-  RECT16       cRect,wRect;
+  RECT16       cRect, wRect;
 
   if (lphc->hWndLBox == 0) return FALSE;
 
@@ -632,9 +641,9 @@
 	 "CBCheckSize: hwnd %04x Rect %d,%d-%d,%d  wRect %d,%d-%d,%d\n", 
 		hwnd,cRect.left,cRect.top,cRect.right,cRect.bottom,
 		wRect.left,wRect.top,wRect.right,wRect.bottom);
-  if ((cstyle & 3) == CBS_SIMPLE  ) return TRUE ;
+  if ((cstyle & 3) == CBS_SIMPLE) return TRUE;
 
-  if ((cRect.bottom - cRect.top) > 
+  if ((cRect.bottom - cRect.top) >
       (lphl->StdItemHeight + 2*SYSMETRICS_CYBORDER)) {
     SetWindowPos(hwnd, 0, 0, 0, 
 		 cRect.right-cRect.left,
@@ -651,7 +660,7 @@
   }
 
   if (cRect.right < lphc->RectButton.left) {
-    /* if the button is outside the window, move it in */
+    /* if the button is outside the window move it in */
     if ((wRect.right - wRect.left - 2*SYSMETRICS_CXBORDER) == (cRect.right - cRect.left)) {
       lphc->RectButton.right = cRect.right;
       lphc->RectButton.left = cRect.right - 2*SYSMETRICS_CXBORDER - 4 
@@ -662,8 +671,13 @@
     /* otherwise we need to make the client include the button */
     else
       SetWindowPos(hwnd, 0, 0, 0, lphc->RectButton.right,
-		   lphl->StdItemHeight+2*SYSMETRICS_CYBORDER, 
-		   SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE );
+		   lphl->StdItemHeight+2*SYSMETRICS_CYBORDER,
+		   SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE);
+
+      if ((lphc->dwStyle & 3) != CBS_DROPDOWNLIST)
+        SetWindowPos(lphc->hWndEdit, 0, 0, 0, lphc->RectButton.left,
+		     lphl->StdItemHeight,
+		     SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
   }
 
   CBLCheckSize(hwnd);
@@ -728,6 +742,34 @@
 
 
 /***********************************************************************
+ *           CBGetEditSel
+ * Look out! Under Win32, the parameter packing is very different.
+ */
+static LRESULT CBGetEditSel(HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
+
+    if ((lphc->dwStyle & 3) == CBS_DROPDOWNLIST)
+      return CB_ERR;	/* err, documented for CBSetEditSel */
+    return SendMessage16(lphc->hWndEdit, EM_GETSEL, 0, 0);
+}
+
+
+/***********************************************************************
+ *           CBSetEditSel
+ * Look out! Under Win32, the parameter packing is very different.
+ */
+static LRESULT CBSetEditSel(HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
+
+    if ((lphc->dwStyle & 3) == CBS_DROPDOWNLIST)
+      return CB_ERR;
+    return SendMessage16(lphc->hWndEdit, EM_SETSEL, 0, lParam);
+}
+
+
+/***********************************************************************
  *           ComboWndProc
  */
 LRESULT ComboBoxWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
@@ -764,6 +806,9 @@
      case CB_SETCURSEL: return CBSetCurSel(hwnd, wParam, lParam);
      case CB_SETITEMHEIGHT: return CBSetItemHeight(hwnd, wParam, lParam);
      case CB_SHOWDROPDOWN: return CBShowDropDown(hwnd, wParam, lParam);
+     case CB_GETEDITSEL: return CBGetEditSel(hwnd, wParam, lParam);
+     case CB_SETEDITSEL: return CBSetEditSel(hwnd, wParam, lParam);
+     case CB_FINDSTRINGEXACT: return CBFindStringExact(hwnd, wParam, lParam);
     }
     return DefWindowProc16(hwnd, message, wParam, lParam);
 }
diff --git a/controls/menu.c b/controls/menu.c
index e38a4cd..a83db51 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -1859,7 +1859,7 @@
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
     if (!(lppop = (LPPOPUPMENU)USER_HEAP_LIN_ADDR((HMENU)wndPtr->wIDmenu)))
       return 0;
-    hdc = GetDC( hwnd );
+    hdc = GetDCEx( hwnd, 0, DCX_CACHE | DCX_WINDOW );
     SetRect16(&rectBar, orgX, orgY, orgX+menubarWidth, orgY+SYSMETRICS_CYMENU);
     MENU_MenuBarCalcSize( hdc, &rectBar, lppop, hwnd );
     ReleaseDC( hwnd, hdc );
@@ -2353,7 +2353,7 @@
     lppop = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
     if (!lppop || (lppop->wMagic != MENU_MAGIC)) return FALSE;
     lppop->wMagic = 0;  /* Mark it as destroyed */
-    if ((lppop->wFlags & MF_POPUP) && lppop->hWnd && lppop->hWnd != pTopPWnd->hwndSelf )
+    if ((lppop->wFlags & MF_POPUP) && lppop->hWnd && (!pTopPWnd || (lppop->hWnd != pTopPWnd->hwndSelf)))
         DestroyWindow( lppop->hWnd );
 
     if (lppop->items)
diff --git a/controls/scroll.c b/controls/scroll.c
index 649c81f..c54421c 100644
--- a/controls/scroll.c
+++ b/controls/scroll.c
@@ -797,12 +797,23 @@
         }
         break;
 
-    case 0x400: /* SB_SETSCROLLPOS */
-    case 0x401: /* SB_GETSCROLLPOS */
-    case 0x402: /* SB_GETSCROLLRANGE */
-    case 0x403: /* SB_ENABLE */
-    case 0x404: /* SB_REDRAW */
+    case SBM_SETSCROLLPOS:
+        return SetScrollPos( hwnd, SB_CTL, wParam, (BOOL)lParam );
+
+    case SBM_GETSCROLLPOS:
+        return GetScrollPos( hwnd, SB_CTL );
+
+    case SBM_SETSCROLLRANGE:
+        SetScrollRange( hwnd, SB_CTL, LOWORD(lParam), HIWORD(lParam),
+                        wParam  /* FIXME: Is this correct? */ );
+        return 0;
+
+    case SBM_ENABLE:
+        return EnableScrollBar( hwnd, SB_CTL, wParam ); /* FIXME: lParam? */
+
+    case 0x403: /* SBM_REDRAW */
         fprintf(stdnimp,"ScrollBarWndProc: undocumented message %04x, please report\n", message );
+        break;
 
     default:
         return DefWindowProc16( hwnd, message, wParam, lParam );
diff --git a/debugger/registers.c b/debugger/registers.c
index 66b38f3..4545d78 100644
--- a/debugger/registers.c
+++ b/debugger/registers.c
@@ -46,14 +46,14 @@
         case REG_FS:  FS_reg(DEBUG_context)  = val; break;
 #else
         case REG_FS:
-            fprintf( stderr, "Register %fs not supported on this system\n ");
+            fprintf( stderr, "Register %fs not supported on this system\n" );
             break;
 #endif
 #ifdef GS_reg
         case REG_GS:  GS_reg(DEBUG_context)  = val; break;
 #else
         case REG_GS:
-            fprintf( stderr, "Register %gs not supported on this system\n ");
+            fprintf( stderr, "Register %gs not supported on this system\n" );
             break;
 #endif
     }
@@ -97,14 +97,14 @@
         case REG_FS:  return FS_reg(DEBUG_context);
 #else
         case REG_FS:
-            fprintf( stderr, "Register %fs not supported on this system\n ");
+            fprintf( stderr, "Register %fs not supported on this system\n" );
             return 0;
 #endif
 #ifdef GS_reg
         case REG_GS:  return GS_reg(DEBUG_context);
 #else
         case REG_GS:
-            fprintf( stderr, "Register %gs not supported on this system\n ");
+            fprintf( stderr, "Register %gs not supported on this system\n" );
             return 0;
 #endif
     }
@@ -182,10 +182,14 @@
         CHECK_SEG( DS_reg(DEBUG_context), "DS" );
     if (ES_reg(DEBUG_context) != WINE_DATA_SELECTOR)
         CHECK_SEG( ES_reg(DEBUG_context), "ES" );
+#ifdef FS_reg
     if (FS_reg(DEBUG_context) != WINE_DATA_SELECTOR)
         CHECK_SEG( FS_reg(DEBUG_context), "FS" );
+#endif
+#ifdef GS_reg
     if (GS_reg(DEBUG_context) != WINE_DATA_SELECTOR)
         CHECK_SEG( GS_reg(DEBUG_context), "GS" );
+#endif
 
     /* Check that CS and SS are not NULL */
 
diff --git a/files/dos_fs.c b/files/dos_fs.c
index e2086ec..e0a1e17 100644
--- a/files/dos_fs.c
+++ b/files/dos_fs.c
@@ -247,7 +247,7 @@
  *
  * Check a DOS file name against a mask (both in FCB format).
  */
-static int DOSFS_Match( const char *mask, const char *name )
+int DOSFS_Match( const char *mask, const char *name )
 {
     int i;
     for (i = 11; i > 0; i--, mask++, name++)
@@ -280,7 +280,7 @@
  * hashed version that fits in 8.3 format.
  * File name can be terminated by '\0', '\\' or '/'.
  */
-static const char *DOSFS_Hash( const char *name, int dir_format )
+const char *DOSFS_Hash( const char *name, int dir_format )
 {
     static const char invalid_chars[] = INVALID_DOS_CHARS "~.";
     static const char hash_chars[32] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
diff --git a/files/file.c b/files/file.c
index 2ea02e3..940ebe1 100644
--- a/files/file.c
+++ b/files/file.c
@@ -283,6 +283,29 @@
 
 
 /***********************************************************************
+ *           FILE_DupUnixHandle
+ *
+ * Duplicate a Unix handle into a task handle.
+ */
+HFILE FILE_DupUnixHandle( int fd )
+{
+    HFILE handle;
+    DOS_FILE *file;
+
+    if (!(file = FILE_Alloc())) return HFILE_ERROR;
+    if ((file->unix_handle = dup(fd)) == -1)
+    {
+        FILE_SetDosError();
+        FILE_Close( file );
+        return HFILE_ERROR;
+    }
+    if ((handle = FILE_AllocTaskHandle( file )) == HFILE_ERROR)
+        FILE_Close( file );
+    return handle;
+}
+
+
+/***********************************************************************
  *           FILE_OpenUnixFile
  */
 static DOS_FILE *FILE_OpenUnixFile( const char *name, int mode )
diff --git a/if1632/Makefile.in b/if1632/Makefile.in
index 3774434..5eb7110 100644
--- a/if1632/Makefile.in
+++ b/if1632/Makefile.in
@@ -51,7 +51,8 @@
 
 C_SRCS = \
 	dummy.c \
-	relay.c
+	relay.c \
+	thunk.c
 
 ASM_SRCS = \
 	$(SPEC_FILES) \
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index 24b13b8..b7e804e 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -77,8 +77,8 @@
 67  pascal16 DPtoLP(word ptr s_word) DPtoLP16
 68  pascal16 DeleteDC(word) DeleteDC
 69  pascal16 DeleteObject(word) DeleteObject
-70  pascal16 EnumFonts(word ptr segptr long) EnumFonts
-71  pascal16 EnumObjects(word word segptr long) EnumObjects
+70  pascal16 EnumFonts(word ptr segptr long) THUNK_EnumFonts16
+71  pascal16 EnumObjects(word word segptr long) THUNK_EnumObjects16
 72  pascal16 EqualRgn(word word) EqualRgn
 73  pascal16 ExcludeVisRect(word s_word s_word s_word s_word) ExcludeVisRect
 74  pascal GetBitmapBits(word long ptr) GetBitmapBits
@@ -108,7 +108,7 @@
 98  pascal16 IntersectVisRect(word s_word s_word s_word s_word)
              IntersectVisRect
 99  pascal16 LPtoDP(word ptr s_word) LPtoDP16
-100 pascal16 LineDDA(s_word s_word s_word s_word segptr long) LineDDA
+100 pascal16 LineDDA(s_word s_word s_word s_word segptr long) THUNK_LineDDA16
 101 pascal16 OffsetRgn(word s_word s_word) OffsetRgn
 102 pascal16 OffsetVisRgn(word s_word s_word) OffsetVisRgn
 103 pascal16 PtVisible(word s_word s_word) PtVisible
@@ -150,7 +150,7 @@
 170 stub SetDCStatus
 172 pascal16 SetRectRgn(word s_word s_word s_word s_word) SetRectRgn
 173 pascal16 GetClipRgn(word) GetClipRgn
-175 pascal16 EnumMetaFile(word word segptr long) EnumMetaFile
+175 pascal16 EnumMetaFile(word word segptr long) THUNK_EnumMetaFile16
 176 pascal16 PlayMetaFileRecord(word ptr ptr word) PlayMetaFileRecord
 179 pascal16 GetDCState(word) GetDCState
 180 pascal16 SetDCState(word word) SetDCState
@@ -227,7 +227,7 @@
 315 stub EngineRealizeFontExt
 316 stub EngineGetCharWidthStr
 317 stub EngineGetGlyphBmpExt
-330 pascal16 EnumFontFamilies(word ptr segptr long) EnumFontFamilies
+330 pascal16 EnumFontFamilies(word ptr segptr long) THUNK_EnumFontFamilies16
 332 pascal16 GetKerningPairs(word word ptr) GetKerningPairs
 345 pascal16 GetTextAlign(word) GetTextAlign
 346 pascal16 SetTextAlign(word word) SetTextAlign
diff --git a/if1632/gdi32.spec b/if1632/gdi32.spec
index dca8d1b..9765459 100644
--- a/if1632/gdi32.spec
+++ b/if1632/gdi32.spec
@@ -252,7 +252,7 @@
 0245 stub IntersectClipRect
 0246 stub InvertRgn
 0247 stdcall LPtoDP(long ptr long) LPtoDP32
-0248 stub LineDDA
+0248 stdcall LineDDA(long long long long ptr long) THUNK_LineDDA32
 0249 stdcall LineTo(long long long) LineTo
 0250 stub LoadImageColorMatcherA
 0251 stub LoadImageColorMatcherW
@@ -326,7 +326,7 @@
 0318 stub SetICMMode
 0319 stub SetICMProfileA
 0320 stub SetICMProfileW
-0321 stub SetMapMode
+0321 stdcall SetMapMode(long long) SetMapMode
 0322 stub SetMapperFlags
 0323 stub SetMetaFileBitsEx
 0324 stub SetMetaRgn
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index ece39884..e7bf177 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -38,7 +38,7 @@
 35  pascal16 GetTaskQueue(word) GetTaskQueue
 36  pascal   GetCurrentTask() WIN16_GetCurrentTask
 37  pascal GetCurrentPDB() GetCurrentPDB
-38  stub SetTaskSignalProc
+38  pascal   SetTaskSignalProc(word segptr) SetTaskSignalProc
 41  return EnableDos 0 0
 42  return DisableDos 0 0
 45  pascal16 LoadModule(ptr ptr) LoadModule
@@ -94,14 +94,14 @@
 95  pascal16 LoadLibrary(ptr) LoadLibrary
 96  pascal16 FreeLibrary(word) FreeLibrary
 97  pascal16 GetTempFileName(byte ptr word ptr) GetTempFileName16
-98  stub GetLastDiskChange
+98  return GetLastDiskChange 0 0
 99  stub GetLPErrMode
 100 stub ValidateCodeSegments
 101 stub NoHookDosCall
 102 register DOS3Call() DOS3Call
 103 register NetBIOSCall() NetBIOSCall
 104 stub GetCodeInfo
-105 stub GetExeVersion
+105 pascal16 GetExeVersion() GetExeVersion
 106 pascal SetSwapAreaSize(word) SetSwapAreaSize
 107 pascal16 SetErrorMode(word) SetErrorMode
 108 pascal16 SwitchStackTo(word word word) SwitchStackTo
@@ -162,7 +162,7 @@
 162 pascal16 LocalHeapSize() LocalHeapSize
 163 pascal16 GlobalLRUOldest(word) GlobalLRUOldest
 164 pascal16 GlobalLRUNewest(word) GlobalLRUNewest
-165 stub A20Proc
+165 return A20Proc 2 0
 166 pascal16 WinExec(ptr word) WinExec
 167 pascal16 GetExpWinVer(word) GetExpWinVer
 168 pascal16 DirectResAlloc(word word word) DirectResAlloc
@@ -252,7 +252,7 @@
 342 stub __GP
 343 stub RegisterWinOldApHook
 344 stub GetWinOldApHooks
-345 stub IsSharedSelector
+345 pascal16 IsSharedSelector(word) IsSharedSelector
 346 pascal16 IsBadHugeReadPtr(segptr long) IsBadHugeReadPtr
 347 pascal16 IsBadHugeWritePtr(segptr long) IsBadHugeWritePtr
 348 pascal16 hmemcpy(ptr ptr long) hmemcpy
diff --git a/if1632/kernel32.spec b/if1632/kernel32.spec
index 71833e4..0b9bd3a 100644
--- a/if1632/kernel32.spec
+++ b/if1632/kernel32.spec
@@ -125,7 +125,7 @@
 0120 stub FindCloseChangeNotification
 0121 stub FindFirstChangeNotificationA
 0122 stub FindFirstChangeNotificationW
-0123 stub FindFirstFileA
+0123 stdcall FindFirstFileA(ptr ptr) FindFirstFile32A
 0124 stub FindFirstFileW
 0125 stub FindNextChangeNotification
 0126 stub FindNextFileA
@@ -492,7 +492,7 @@
 0487 	stdcall	SetEvent(long) SetEvent
 0488 stub SetFileApisToANSI
 0489 stub SetFileApisToOEM
-0490 stub SetFileAttributesA
+0490 stdcall SetFileAttributesA(ptr long) SetFileAttributes32A
 0491 stub SetFileAttributesW
 0492    stdcall SetFilePointer(long long ptr long) SetFilePointer
 0493 stub SetFileTime
diff --git a/if1632/thunk.c b/if1632/thunk.c
new file mode 100644
index 0000000..ae623da
--- /dev/null
+++ b/if1632/thunk.c
@@ -0,0 +1,250 @@
+/*
+ * Emulator thunks
+ *
+ * Copyright 1996 Alexandre Julliard
+ */
+
+#include "windows.h"
+#include "callback.h"
+#include "heap.h"
+
+typedef void (*RELAY)();
+
+typedef struct
+{
+    BYTE       popl_eax;           /* 0x58  popl  %eax (return address) */
+    BYTE       pushl_func;         /* 0x68  pushl $proc */
+    FARPROC32  proc WINE_PACKED;
+    BYTE       pushl_eax;          /* 0x50  pushl %eax */
+    BYTE       jmp;                /* 0xe9  jmp   relay (relative jump)*/
+    RELAY      relay WINE_PACKED;
+} THUNK;
+
+#define DECL_THUNK(name,proc,relay) \
+    THUNK name = { 0x58, 0x68, (FARPROC32)(proc), 0x50, 0xe9, \
+                    (RELAY)((char *)(relay) - (char *)(&(name) + 1)) }
+
+
+/***********************************************************************
+ *           THUNK_Alloc
+ */
+static THUNK *THUNK_Alloc( FARPROC32 func, RELAY relay )
+{
+    THUNK *thunk = HeapAlloc( SystemHeap, 0, sizeof(*thunk) );
+    if (thunk)
+    {
+        thunk->popl_eax   = 0x58;
+        thunk->pushl_func = 0x68;
+        thunk->proc       = func;
+        thunk->pushl_eax  = 0x50;
+        thunk->jmp        = 0xe9;
+        thunk->relay      = relay;
+    }
+    return thunk;
+}
+
+
+/***********************************************************************
+ *           THUNK_Free
+ */
+static void THUNK_Free( THUNK *thunk )
+{
+    HeapFree( SystemHeap, 0, thunk );
+}
+
+
+/***********************************************************************
+ *           THUNK_EnumObjects16   (GDI.71)
+ */
+INT16 THUNK_EnumObjects16( HDC16 hdc, INT16 nObjType,
+                           GOBJENUMPROC16 func, LPARAM lParam )
+{
+    DECL_THUNK( thunk, func, CallTo16_word_ll );
+    return EnumObjects( hdc, nObjType, (GOBJENUMPROC16)&thunk, lParam );
+}
+
+
+/*************************************************************************
+ *           THUNK_EnumFonts16   (GDI.70)
+ */
+INT16 THUNK_EnumFonts16( HDC16 hdc, LPCSTR lpFaceName,
+                         FONTENUMPROC16 func, LPARAM lParam )
+{
+    DECL_THUNK( thunk, func, CallTo16_word_llwl );
+    return EnumFonts( hdc, lpFaceName, (FONTENUMPROC16)&thunk, lParam );
+}
+
+
+/******************************************************************
+ *           THUNK_EnumMetaFile16   (GDI.175)
+ */
+BOOL16 THUNK_EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
+                             MFENUMPROC16 func, LPARAM lParam )
+{
+    DECL_THUNK( thunk, func, CallTo16_word_wllwl );
+    return EnumMetaFile( hdc, hmf, (MFENUMPROC16)&thunk, lParam );
+}
+
+
+/*************************************************************************
+ *           THUNK_EnumFontFamilies16   (GDI.330)
+ */
+INT16 THUNK_EnumFontFamilies16( HDC16 hdc, LPCSTR lpszFamily,
+                                FONTENUMPROC16 func, LPARAM lParam )
+{
+    DECL_THUNK( thunk, func, CallTo16_word_llwl );
+    return EnumFontFamilies( hdc, lpszFamily, (FONTENUMPROC16)&thunk, lParam );
+}
+
+
+/**********************************************************************
+ *           THUNK_LineDDA16   (GDI.100)
+ */
+void THUNK_LineDDA16( INT16 nXStart, INT16 nYStart, INT16 nXEnd, INT16 nYEnd,
+                      LINEDDAPROC16 func, LPARAM lParam )
+{
+    DECL_THUNK( thunk, func, CallTo16_word_wwl );
+    LineDDA16( nXStart, nYStart, nXEnd, nYEnd, (LINEDDAPROC16)&thunk, lParam );
+}
+
+
+/**********************************************************************
+ *           THUNK_LineDDA32   (GDI32.248)
+ */
+BOOL32 THUNK_LineDDA32( INT32 nXStart, INT32 nYStart, INT32 nXEnd, INT32 nYEnd,
+                        LINEDDAPROC32 func, LPARAM lParam )
+{
+    DECL_THUNK( thunk, func, CallTo32_3 );
+    return LineDDA32( nXStart, nYStart, nXEnd, nYEnd,
+                      (LINEDDAPROC32)&thunk, lParam );
+}
+
+
+/*******************************************************************
+ *           THUNK_EnumWindows16   (USER.54)
+ */
+BOOL16 THUNK_EnumWindows16( WNDENUMPROC16 func, LPARAM lParam )
+{
+    DECL_THUNK( thunk, func, CallTo16_word_wl );
+    return EnumWindows16( (WNDENUMPROC16)&thunk, lParam );
+}
+
+
+/*******************************************************************
+ *           THUNK_EnumWindows32   (USER32.192)
+ */
+BOOL32 THUNK_EnumWindows32( WNDENUMPROC32 func, LPARAM lParam )
+{
+    DECL_THUNK( thunk, func, CallTo32_2 );
+    return EnumWindows32( (WNDENUMPROC32)&thunk, lParam );
+}
+
+
+/**********************************************************************
+ *           THUNK_EnumChildWindows16   (USER.55)
+ */
+BOOL16 THUNK_EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
+                                 LPARAM lParam )
+{
+    DECL_THUNK( thunk, func, CallTo16_word_wl );
+    return EnumChildWindows16( parent, (WNDENUMPROC16)&thunk, lParam );
+}
+
+
+/**********************************************************************
+ *           THUNK_EnumChildWindows32   (USER32.177)
+ */
+BOOL32 THUNK_EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func,
+                                 LPARAM lParam )
+{
+    DECL_THUNK( thunk, func, CallTo32_2 );
+    return EnumChildWindows32( parent, (WNDENUMPROC32)&thunk, lParam );
+}
+
+
+/**********************************************************************
+ *           THUNK_EnumTaskWindows16   (USER.225)
+ */
+BOOL16 THUNK_EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
+                                LPARAM lParam )
+{
+    DECL_THUNK( thunk, func, CallTo16_word_wl );
+    return EnumTaskWindows16( hTask, (WNDENUMPROC16)&thunk, lParam );
+}
+
+
+/**********************************************************************
+ *           THUNK_EnumThreadWindows   (USER32.189)
+ */
+BOOL32 THUNK_EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
+{
+    DECL_THUNK( thunk, func, CallTo32_2 );
+    return EnumThreadWindows( id, (WNDENUMPROC32)&thunk, lParam );
+}
+
+
+/***********************************************************************
+ *           THUNK_EnumProps16   (USER.27)
+ */
+INT16 THUNK_EnumProps16( HWND16 hwnd, PROPENUMPROC16 func )
+{
+    DECL_THUNK( thunk, func, CallTo16_word_wlw );
+    return EnumProps16( hwnd, (PROPENUMPROC16)&thunk );
+}
+
+
+/***********************************************************************
+ *           THUNK_EnumProps32A   (USER32.185)
+ */
+INT32 THUNK_EnumProps32A( HWND32 hwnd, PROPENUMPROC32A func )
+{
+    DECL_THUNK( thunk, func, CallTo32_3 );
+    return EnumProps32A( hwnd, (PROPENUMPROC32A)&thunk );
+}
+
+
+/***********************************************************************
+ *           THUNK_EnumProps32W   (USER32.188)
+ */
+INT32 THUNK_EnumProps32W( HWND32 hwnd, PROPENUMPROC32W func )
+{
+    DECL_THUNK( thunk, func, CallTo32_3 );
+    return EnumProps32W( hwnd, (PROPENUMPROC32W)&thunk );
+}
+
+
+/***********************************************************************
+ *           THUNK_EnumPropsEx32A   (USER32.186)
+ */
+INT32 THUNK_EnumPropsEx32A( HWND32 hwnd, PROPENUMPROCEX32A func, LPARAM lParam)
+{
+    DECL_THUNK( thunk, func, CallTo32_4 );
+    return EnumPropsEx32A( hwnd, (PROPENUMPROCEX32A)&thunk, lParam );
+}
+
+
+/***********************************************************************
+ *           THUNK_EnumPropsEx32W   (USER32.187)
+ */
+INT32 THUNK_EnumPropsEx32W( HWND32 hwnd, PROPENUMPROCEX32W func, LPARAM lParam)
+{
+    DECL_THUNK( thunk, func, CallTo32_4 );
+    return EnumPropsEx32W( hwnd, (PROPENUMPROCEX32W)&thunk, lParam );
+}
+
+
+/***********************************************************************
+ *           THUNK_GrayString16   (USER.185)
+ */
+BOOL16 THUNK_GrayString16( HDC16 hdc, HBRUSH16 hbr, GRAYSTRINGPROC16 func,
+                           LPARAM lParam, INT16 cch, INT16 x, INT16 y,
+                           INT16 cx, INT16 cy )
+{
+    DECL_THUNK( thunk, func, CallTo16_word_wlw );
+    if (!func)
+        return GrayString( hdc, hbr, NULL, lParam, cch, x, y, cx, cy );
+    else
+        return GrayString( hdc, hbr, (GRAYSTRINGPROC16)&thunk, lParam, cch,
+                           x, y, cx, cy );
+}
+
diff --git a/if1632/user.spec b/if1632/user.spec
index 5e10675..10af4d8 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -26,7 +26,7 @@
 24  pascal16 RemoveProp(word ptr) RemoveProp16
 25  pascal16 GetProp(word ptr) GetProp16
 26  pascal16 SetProp(word ptr word) SetProp16
-27  pascal16 EnumProps(word segptr) EnumProps16
+27  pascal16 EnumProps(word segptr) THUNK_EnumProps16
 28  pascal16 ClientToScreen(word ptr) ClientToScreen16
 29  pascal16 ScreenToClient(word ptr) ScreenToClient16
 30  pascal16 WindowFromPoint(long) WindowFromPoint16
@@ -54,8 +54,8 @@
 #51 BEAR51
 52  pascal16 AnyPopup() AnyPopup
 53  pascal16 DestroyWindow(word) DestroyWindow
-54  pascal16 EnumWindows(segptr long) EnumWindows16
-55  pascal16 EnumChildWindows(word segptr long) EnumChildWindows16
+54  pascal16 EnumWindows(segptr long) THUNK_EnumWindows16
+55  pascal16 EnumChildWindows(word segptr long) THUNK_EnumChildWindows16
 56  pascal16 MoveWindow(word word word word word word) MoveWindow
 57  pascal16 RegisterClass(ptr) RegisterClass16
 58  pascal16 GetClassName(word ptr word) GetClassName16
@@ -117,7 +117,7 @@
 115 pascal16 ReplyMessage(long) ReplyMessage
 116 pascal16 PostAppMessage(word word word long) PostAppMessage
 118 pascal16 RegisterWindowMessage(segptr) RegisterWindowMessage16
-117 stub WindowFromDC
+117 pascal16 WindowFromDC(word) WindowFromDC
 119 pascal   GetMessagePos() GetMessagePos
 120 pascal   GetMessageTime() GetMessageTime
 121 pascal   SetWindowsHook(s_word segptr) SetWindowsHook
@@ -184,7 +184,7 @@
 182 pascal16 KillSystemTimer(word word) KillSystemTimer16
 183 pascal16 GetCaretPos(ptr) GetCaretPos16
 184 stub QuerySendMessage
-185 pascal16 GrayString(word word segptr segptr s_word s_word s_word s_word s_word) GrayString
+185 pascal16 GrayString(word word segptr segptr s_word s_word s_word s_word s_word) THUNK_GrayString16
 186 pascal16 SwapMouseButton(word) SwapMouseButton
 187 pascal16 EndMenu() EndMenu
 188 pascal16 SetSysModalWindow(word) SetSysModalWindow16
@@ -225,7 +225,7 @@
 222 pascal16 GetKeyboardState(ptr) GetKeyboardState
 223 pascal16 SetKeyboardState(ptr) SetKeyboardState
 224 pascal16 GetWindowTask(word) GetWindowTask16
-225 pascal16 EnumTaskWindows(word segptr long) EnumTaskWindows16
+225 pascal16 EnumTaskWindows(word segptr long) THUNK_EnumTaskWindows16
 226 stub LockInput
 227 pascal16 GetNextDlgGroupItem(word word word) GetNextDlgGroupItem
 228 pascal16 GetNextDlgTabItem(word word word) GetNextDlgTabItem
diff --git a/if1632/user32.spec b/if1632/user32.spec
index d6da555..a277e16 100644
--- a/if1632/user32.spec
+++ b/if1632/user32.spec
@@ -12,7 +12,7 @@
 0007 stub AttachThreadInput
 0008 stub BeginDeferWindowPos
 0009 stdcall BeginPaint(long ptr) BeginPaint32
-0010 stub BringWindowToTop
+0010 stdcall BringWindowToTop(long) BringWindowToTop
 0011 stub BroadcastSystemMessage
 0012 stub CalcChildScroll
 0013 stub CallMsgFilter
@@ -83,7 +83,7 @@
 0078 stub CreateMDIWindowA
 0079 stub CreateMDIWindowW
 0080 stub CreateMenu
-0081 stub CreatePopupMenu
+0081 stdcall CreatePopupMenu() CreatePopupMenu
 0082 stdcall CreateWindowExA(long ptr ptr long long long long long 
 				long long long ptr) CreateWindowEx32A
 0083 stdcall CreateWindowExW(long ptr ptr long long long long long 
@@ -181,7 +181,7 @@
 0174 stub EndMenu
 0175 stdcall EndPaint(long ptr) EndPaint32
 0176 stub EndTask
-0177 stdcall EnumChildWindows(long ptr long) EnumChildWindows32
+0177 stdcall EnumChildWindows(long ptr long) THUNK_EnumChildWindows32
 0178 stub EnumClipboardFormats
 0179 stub EnumDesktopsA
 0180 stub EnumDesktopsW
@@ -189,14 +189,14 @@
 0182 stub EnumDisplayDeviceModesW
 0183 stub EnumDisplayDevicesA
 0184 stub EnumDisplayDevicesW
-0185 stdcall EnumPropsA(long ptr) EnumProps32A
-0186 stdcall EnumPropsExA(long ptr long) EnumPropsEx32A
-0187 stdcall EnumPropsExW(long ptr long) EnumPropsEx32W
-0188 stdcall EnumPropsW(long ptr) EnumProps32W
-0189 stdcall EnumThreadWindows(long ptr long) EnumThreadWindows
+0185 stdcall EnumPropsA(long ptr) THUNK_EnumProps32A
+0186 stdcall EnumPropsExA(long ptr long) THUNK_EnumPropsEx32A
+0187 stdcall EnumPropsExW(long ptr long) THUNK_EnumPropsEx32W
+0188 stdcall EnumPropsW(long ptr) THUNK_EnumProps32W
+0189 stdcall EnumThreadWindows(long ptr long) THUNK_EnumThreadWindows
 0190 stub EnumWindowStationsA
 0191 stub EnumWindowStationsW
-0192 stdcall EnumWindows(ptr long) EnumWindows32
+0192 stdcall EnumWindows(ptr long) THUNK_EnumWindows32
 0193 stdcall EqualRect(ptr ptr) EqualRect32
 0194 stdcall ExcludeUpdateRgn(long long) ExcludeUpdateRgn
 0195 stub ExitWindowsEx
@@ -252,7 +252,7 @@
 0245 stub GetKBCodePage
 0246 stub GetKeyNameTextA
 0247 stub GetKeyNameTextW
-0248 stub GetKeyState
+0248 stdcall GetKeyState(long) GetKeyState
 0249 stub GetKeyboardLayout
 0250 stub GetKeyboardLayoutList
 0251 stub GetKeyboardLayoutNameA
@@ -281,7 +281,7 @@
 0274 stub GetNextDlgGroupItem
 0275 stub GetNextDlgTabItem
 0276 stub GetOpenClipboardWindow
-0277 stub GetParent
+0277 stdcall GetParent(long) GetParent
 0278 stub GetPriorityClipboardFormat
 0279 stub GetProcessWindowStation
 0280 stdcall GetPropA(long ptr) GetProp32A
@@ -345,9 +345,9 @@
 0338 stub IsChild
 0339 stdcall IsClipboardFormatAvailable(long) IsClipboardFormatAvailable
 0340 stub IsDialogMessage
-0341 stub IsDialogMessageA
+0341 stdcall IsDialogMessageA(long ptr) IsDialogMessage32A
 0342 stub IsDialogMessageW
-0343 stub IsDlgButtonChecked
+0343 stdcall IsDlgButtonChecked(long long) IsDlgButtonChecked
 0344 stdcall IsIconic(long) IsIconic
 0345 stub IsMenu
 0346 stdcall IsRectEmpty(ptr) IsRectEmpty32
@@ -561,7 +561,7 @@
 0554 stub TranslateMDISysAccel
 0555 stdcall TranslateMessage(ptr) USER32_TranslateMessage
 0556 stub UnhookWindowsHook
-0557 stub UnhookWindowsHookEx
+0557 stdcall UnhookWindowsHookEx(long) UnhookWindowsHookEx32
 0558 stdcall UnionRect(ptr ptr ptr) UnionRect32
 0559 stub UnloadKeyboardLayout
 0560 stub UnlockWindowStation
@@ -584,7 +584,7 @@
 0577 stub WaitMessage
 0578 stdcall WinHelpA(long ptr long long)	WIN32_WinHelpA
 0579 stub WinHelpW
-0580 stub WindowFromDC
+0580 stdcall WindowFromDC(long) WindowFromDC
 0581 stdcall WindowFromPoint(long long) WindowFromPoint32
 0582 stub keybd_event
 0583 stub mouse_event
diff --git a/if1632/wprocs.spec b/if1632/wprocs.spec
index 1f7b233..3f33bbc 100644
--- a/if1632/wprocs.spec
+++ b/if1632/wprocs.spec
@@ -25,8 +25,6 @@
 27 pascal EntryAddrProc(word word) MODULE_GetEntryPoint
 28 pascal MyAlloc(word word word) MODULE_AllocateSegment
 30 pascal FormatCharDlgProc(word word word long) FormatCharDlgProc
-31 pascal16 FontStyleEnumProc(ptr ptr word long)   FontStyleEnumProc
-32 pascal16 FontFamilyEnumProc(ptr ptr word long)  FontFamilyEnumProc
  
 # Interrupt vectors 0-255 are ordinals 100-355
 # The 'word' parameter are the flags pushed on the stack by the interrupt
diff --git a/include/callback.h b/include/callback.h
index d420f76..0339a89 100644
--- a/include/callback.h
+++ b/include/callback.h
@@ -4,13 +4,10 @@
  * Copyright 1995 Alexandre Julliard
  */
 
-#ifndef WINE_CALLBACK_H
-#define WINE_CALLBACK_H
+#ifndef __WINE_CALLBACK_H
+#define __WINE_CALLBACK_H
 
-#include <stdlib.h>
-#include <stdarg.h>
-
-#include "stackframe.h"
+#include "wintypes.h"
 
 extern
 int CallTo32_LargeStack( int (*func)(), int nbargs, ... );
@@ -19,27 +16,27 @@
 /* List of the 16-bit callback functions. This list is used  */
 /* by the build program to generate the file if1632/callto16.S */
 
-                               /* func     ds    parameters */
-extern WORD CallTo16_word_     ( FARPROC16, WORD );
+                               /* func     parameters */
+extern WORD CallTo16_word_     ( FARPROC16 );
 
 #ifndef WINELIB
 
-extern WORD CallTo16_word_w    (FARPROC16, WORD, WORD);
-extern WORD CallTo16_word_ww   (FARPROC16, WORD, WORD, WORD);
-extern WORD CallTo16_word_wl   (FARPROC16, WORD, WORD, LONG);
-extern WORD CallTo16_word_ll   (FARPROC16, WORD, LONG, LONG);
-extern WORD CallTo16_word_www  (FARPROC16, WORD, WORD, WORD, WORD);
-extern WORD CallTo16_word_wwl  (FARPROC16, WORD, WORD, WORD, LONG);
-extern WORD CallTo16_word_wlw  (FARPROC16, WORD, WORD, LONG, WORD);
-extern LONG CallTo16_long_wwl  (FARPROC16, WORD, WORD, WORD, LONG);
-extern WORD CallTo16_word_llwl (FARPROC16, WORD, LONG, LONG, WORD, LONG);
-extern LONG CallTo16_long_wwwl (FARPROC16, WORD, WORD, WORD, WORD, LONG);
-extern WORD CallTo16_word_lwww (FARPROC16, WORD, LONG, WORD, WORD, WORD);
-extern WORD CallTo16_word_wwll (FARPROC16, WORD, WORD, WORD, LONG, LONG);
-extern WORD CallTo16_word_wllwl(FARPROC16, WORD, WORD, LONG, LONG, WORD, LONG);
-extern LONG CallTo16_long_lwwll(FARPROC16, WORD, LONG, WORD, WORD, LONG, LONG);
-extern WORD CallTo16_word_wwlll(FARPROC16, WORD, WORD, WORD, LONG, LONG, LONG);
-extern LONG CallTo16_long_lllllllwlwwwl( FARPROC16, WORD, LONG, LONG, LONG,
+extern WORD CallTo16_word_w    ( FARPROC16, WORD );
+extern WORD CallTo16_word_ww   ( FARPROC16, WORD, WORD );
+extern WORD CallTo16_word_wl   ( FARPROC16, WORD, LONG );
+extern WORD CallTo16_word_ll   ( FARPROC16, LONG, LONG );
+extern WORD CallTo16_word_www  ( FARPROC16, WORD, WORD, WORD );
+extern WORD CallTo16_word_wwl  ( FARPROC16, WORD, WORD, LONG );
+extern WORD CallTo16_word_wlw  ( FARPROC16, WORD, LONG, WORD );
+extern LONG CallTo16_long_wwl  ( FARPROC16, WORD, WORD, LONG );
+extern WORD CallTo16_word_llwl ( FARPROC16, LONG, LONG, WORD, LONG );
+extern LONG CallTo16_long_wwwl ( FARPROC16, WORD, WORD, WORD, LONG );
+extern WORD CallTo16_word_lwww ( FARPROC16, LONG, WORD, WORD, WORD );
+extern WORD CallTo16_word_wwll ( FARPROC16, WORD, WORD, LONG, LONG );
+extern WORD CallTo16_word_wllwl( FARPROC16, WORD, LONG, LONG, WORD, LONG );
+extern LONG CallTo16_long_lwwll( FARPROC16, LONG, WORD, WORD, LONG, LONG );
+extern WORD CallTo16_word_wwlll( FARPROC16, WORD, WORD, LONG, LONG, LONG );
+extern LONG CallTo16_long_lllllllwlwwwl( FARPROC16, LONG, LONG, LONG,
                                          LONG, LONG, LONG, LONG, WORD, LONG,
                                          WORD, WORD, WORD, LONG );
 
@@ -47,46 +44,26 @@
                             WORD bx, WORD cx, WORD dx, WORD si, WORD di );
 
 #define CallDCHookProc( func, hdc, code, data, lparam) \
-    CallTo16_word_wwll( func, CURRENT_DS, hdc, code, data, lparam )
+    CallTo16_word_wwll( func, hdc, code, data, lparam )
 #define CallDriverProc( func, dwId, msg, hdrvr, lparam1, lparam2 ) \
-    CallTo16_long_lwwll( func, CURRENT_DS, dwId, msg, hdrvr, lparam1, lparam2 )
-#define CallEnumChildProc( func, hwnd, lParam ) \
-    CallTo16_word_wl( func, CURRENT_DS, hwnd, lParam )
-#define CallEnumFontFamProc( func, lpfont, lpmetric, type, lParam ) \
-    CallTo16_word_llwl( func, CURRENT_DS, lpfont, lpmetric, type, lParam )
-#define CallEnumFontsProc( func, lpfont, lpmetric, type, lParam ) \
-    CallTo16_word_llwl( func, CURRENT_DS, lpfont, lpmetric, type, lParam )
-#define CallEnumMetafileProc( func, hdc, lptable, lprecord, objs, lParam ) \
-    CallTo16_word_wllwl(func, CURRENT_DS, hdc, lptable, lprecord, objs, lParam)
-#define CallEnumObjectsProc( func, lpobj, lParam ) \
-    CallTo16_word_ll( func, CURRENT_DS, lpobj, lParam )
-#define CallEnumPropProc16( func, hwnd, lpstr, handle ) \
-    CallTo16_word_wlw( (FARPROC16)(func), CURRENT_DS, hwnd, lpstr, handle )
-#define CallEnumTaskWndProc( func, hwnd, lParam ) \
-    CallTo16_word_wl( func, CURRENT_DS, hwnd, lParam )
-#define CallEnumWindowsProc16( func, hwnd, lParam ) \
-    CallTo16_word_wl( func, CURRENT_DS, hwnd, lParam )
-#define CallLineDDAProc( func, xPos, yPos, lParam ) \
-    CallTo16_word_wwl( func, CURRENT_DS, xPos, yPos, lParam )
-#define CallGrayStringProc( func, hdc, lParam, cch ) \
-    CallTo16_word_wlw( func, CURRENT_DS, hdc, lParam, cch )
+    CallTo16_long_lwwll( func, dwId, msg, hdrvr, lparam1, lparam2 )
 #define CallHookProc( func, code, wParam, lParam ) \
-    CallTo16_long_wwl( func, CURRENT_DS, code, wParam, lParam )
+    CallTo16_long_wwl( func, code, wParam, lParam )
 #define CallTimeFuncProc( func, id, msg, dwUser, dw1, dw2 ) \
-    CallTo16_word_wwlll( func, CURRENT_DS, id, msg, dwUser, dw1, dw2 )
+    CallTo16_word_wwlll( func, id, msg, dwUser, dw1, dw2 )
 #define CallWindowsExitProc( func, nExitType ) \
-    CallTo16_word_w( func, CURRENT_DS, nExitType )
-#define CallWndProc16( func, ds, hwnd, msg, wParam, lParam ) \
-    CallTo16_long_wwwl( (FARPROC16)(func), ds, hwnd, msg, wParam, lParam )
+    CallTo16_word_w( func, nExitType )
+#define CallWndProc16( func, hwnd, msg, wParam, lParam ) \
+    CallTo16_long_wwwl( (FARPROC16)(func), hwnd, msg, wParam, lParam )
 #define CallWordBreakProc( func, lpch, ichCurrent, cch, code ) \
-    CallTo16_word_lwww( func, CURRENT_DS, lpch, ichCurrent, cch, code )
-#define CallWndProcNCCREATE16( func, ds, exStyle, clsName, winName, style, \
+    CallTo16_word_lwww( func, lpch, ichCurrent, cch, code )
+#define CallWndProcNCCREATE16( func, exStyle, clsName, winName, style, \
                                x, y, cx, cy, hparent, hmenu, instance, \
                                params, hwnd, msg, wParam, lParam ) \
-    CallTo16_long_lllllllwlwwwl( (FARPROC16)(func), ds, exStyle, clsName, \
-                              winName, style, MAKELONG(y,x), MAKELONG(cy,cx), \
-                              MAKELONG(hmenu,hparent), instance, params, \
-                              hwnd, msg, wParam, lParam )
+    CallTo16_long_lllllllwlwwwl( (FARPROC16)(func), exStyle, clsName, winName,\
+                                 style, MAKELONG(y,x), MAKELONG(cy,cx), \
+                                 MAKELONG(hmenu,hparent), instance, params, \
+                                 hwnd, msg, wParam, lParam )
 
 /* List of the 32-bit callback functions. This list is used  */
 /* by the build program to generate the file if1632/callto32.S */
@@ -100,12 +77,6 @@
     CallTo32_0( func )
 #define CallDLLEntryProc32( func, hmodule, a, b ) \
     CallTo32_3( func, hmodule, a, b )
-#define CallEnumPropProc32( func, hwnd, lpstr, handle ) \
-    CallTo32_3( (FARPROC32)(func), hwnd, (DWORD)(lpstr), handle )
-#define CallEnumPropProcEx32( func, hwnd, lpstr, handle, data ) \
-    CallTo32_4( (FARPROC32)(func), hwnd, (DWORD)(lpstr), handle, data )
-#define CallEnumWindowsProc32( func, hwnd, lParam ) \
-    CallTo32_2( func, hwnd, lParam )
 #define CallWndProc32( func, hwnd, msg, wParam, lParam ) \
     CallTo32_4( func, hwnd, msg, wParam, lParam )
 
@@ -116,39 +87,13 @@
     (*func)( hdc, code, data, lparam )
 #define CallDriverProc( func, dwId, msg, hdrvr, lparam1, lparam2 ) \
     (*func)( dwId, msg, hdrvr, lparam1, lparam2 )
-#define CallEnumChildProc( func, hwnd, lParam ) \
-    (*func)( hwnd, lParam )
-#define CallEnumFontFamProc( func, lpfont, lpmetric, type, lParam ) \
-    (*func)( lpfont, lpmetric, type, lParam )
-#define CallEnumFontsProc( func, lpfont, lpmetric, type, lParam ) \
-    (*func)( lpfont, lpmetric, type, lParam )
-#define CallEnumMetafileProc( func, hdc, lptable, lprecord, objs, lParam ) \
-    (*func)( hdc, lptable, lprecord, objs, lParam)
-#define CallEnumObjectsProc( func, lpobj, lParam ) \
-    (*func)( lpobj, lParam )
-#define CallEnumPropProc16( func, hwnd, lpstr, handle ) \
-    (*func)( hwnd, lpstr, handle )
-#define CallEnumPropProc32( func, hwnd, lpstr, handle ) \
-    (*func)( hwnd, lpstr, handle )
-#define CallEnumPropProcEx32( func, hwnd, lpstr, handle, data ) \
-    (*func)( hwnd, lpstr, handle, data )
-#define CallEnumTaskWndProc( func, hwnd, lParam ) \
-    (*func)( hwnd, lParam )
-#define CallEnumWindowsProc16( func, hwnd, lParam ) \
-    (*func)( hwnd, lParam )
-#define CallEnumWindowsProc32( func, hwnd, lParam ) \
-    (*func)( hwnd, lParam )
-#define CallLineDDAProc( func, xPos, yPos, lParam ) \
-    (*func)( xPos, yPos, lParam )
-#define CallGrayStringProc( func, hdc, lParam, cch ) \
-    (*func)( hdc, lParam, cch )
 #define CallHookProc( func, code, wParam, lParam ) \
     (*func)( code, wParam, lParam )
 #define CallTimeFuncProc( func, id, msg, dwUser, dw1, dw2 ) \
     (*func)( id, msg, dwUser, dw1, dw2 )
 #define CallWindowsExitProc( func, nExitType ) \
     (*func)( nExitType )
-#define CallWndProc16( func, ds, hwnd, msg, wParam, lParam ) \
+#define CallWndProc16( func, hwnd, msg, wParam, lParam ) \
     (*func)( hwnd, msg, wParam, lParam )
 #define CallWndProc32( func, hwnd, msg, wParam, lParam ) \
     (*func)( hwnd, msg, wParam, lParam )
@@ -158,4 +103,4 @@
 #endif  /* WINELIB */
 
 
-#endif /* WINE_CALLBACK_H */
+#endif /* __WINE_CALLBACK_H */
diff --git a/include/combo.h b/include/combo.h
index 0e177f6..9732533 100644
--- a/include/combo.h
+++ b/include/combo.h
@@ -4,6 +4,7 @@
 
 
 typedef struct {
+  WND*	  wndSelf;
   DWORD   dwStyle;
   DWORD   dwState;
   HWND    hWndEdit;
diff --git a/include/file.h b/include/file.h
index 634ca76..f1533d9 100644
--- a/include/file.h
+++ b/include/file.h
@@ -11,6 +11,7 @@
 
 extern void FILE_SetDosError(void);
 extern void FILE_CloseAllFiles( HANDLE hPDB );
+extern HFILE FILE_DupUnixHandle( int fd );
 extern int FILE_Stat( LPCSTR unixName, BYTE *pattr, DWORD *psize,
                       WORD *pdate, WORD *ptime );
 extern int FILE_GetDateTime( HFILE hFile, WORD *pdate, WORD *ptime,
diff --git a/include/hook.h b/include/hook.h
index 4dcd375..0f49988 100644
--- a/include/hook.h
+++ b/include/hook.h
@@ -9,7 +9,6 @@
 
 #include "windows.h"
 #include "ldt.h"
-#include "callback.h"
 
 #pragma pack(1)
 
diff --git a/include/metafile.h b/include/metafile.h
index 0d2c306..06f4e63 100644
--- a/include/metafile.h
+++ b/include/metafile.h
@@ -14,7 +14,7 @@
 #define META_EOF 0x0000
 
 HMETAFILE MF_WriteRecord(HMETAFILE hmf, METARECORD *mr, WORD rlen);
-int MF_AddHandle(HANDLETABLE *ht, WORD htlen, HANDLE hobj);
+int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HANDLE hobj);
 int MF_AddHandleInternal(HANDLE hobj);
 BOOL MF_MetaParam0(DC *dc, short func);
 BOOL MF_MetaParam1(DC *dc, short func, short param1);
@@ -31,6 +31,8 @@
 BOOL MF_CreatePenIndirect(DC *dc, HPEN16 hPen, LOGPEN16 *logpen);
 BOOL MF_CreateFontIndirect(DC *dc, HFONT hFont, LOGFONT16 *logfont);
 BOOL MF_TextOut(DC *dc, short x, short y, LPCSTR str, short count);
+BOOL MF_ExtTextOut(DC *dc, short x, short y, UINT16 flags, const RECT16 *rect,
+                   LPCSTR str, short count, const INT16 *lpDx);
 BOOL MF_MetaPoly(DC *dc, short func, LPPOINT16 pt, short count);
 BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
 	       short height, HDC hdcSrc, short xSrc, short ySrc, DWORD rop);
diff --git a/include/task.h b/include/task.h
index f7c92a5..f71ce81 100644
--- a/include/task.h
+++ b/include/task.h
@@ -70,8 +70,8 @@
     HQUEUE16  hQueue;                     /* 20 Selector of task queue */
     HTASK16   hParent;                    /* 22 Selector of TDB of parent */
     WORD      signal_flags;               /* 24 Flags for signal handler */
-    DWORD     sighandler WINE_PACKED;     /* 26 Signal handler */
-    DWORD     userhandler WINE_PACKED;    /* 2a USER signal handler */
+    FARPROC16 sighandler WINE_PACKED;     /* 26 Signal handler */
+    FARPROC16 userhandler WINE_PACKED;    /* 2a USER signal handler */
     DWORD     discardhandler WINE_PACKED; /* 2e Handler for GlobalDiscard() */
     DWORD     int0 WINE_PACKED;           /* 32 int 0 (divide by 0) handler */
     DWORD     int2 WINE_PACKED;           /* 36 int 2 (NMI) handler */
@@ -81,9 +81,7 @@
     DWORD     int3e WINE_PACKED;          /* 46 int 3e (80x87 emu) handler */
     DWORD     int75 WINE_PACKED;          /* 4a int 75 (80x87 error) handler */
     DWORD     compat_flags WINE_PACKED;   /* 4e Compatibility flags */
-    BYTE      unused4[10];                /* 52 */
-    WORD      switchStackSS;              /* 5c Saved %ss for SwitchStackTo */
-    WORD      switchStackSP;              /* 5e Saved %sp for SwitchStackTo */
+    BYTE      unused4[14];                /* 52 */
     HANDLE16  hPDB;                       /* 60 Selector of PDB (i.e. PSP) */
     SEGPTR    dta WINE_PACKED;            /* 62 Current DTA */
     BYTE      curdrive;                   /* 66 Current drive */
diff --git a/include/winbase.h b/include/winbase.h
index f221fa2..1583f35 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -133,6 +133,35 @@
 
 DECL_WINELIB_TYPE_AW(OSVERSIONINFO);
 
+typedef struct
+{
+    DWORD     FileAttributes;
+    FILETIME  CreationTime;
+    FILETIME  LastAccessTime;
+    FILETIME  LastWriteTime;
+    DWORD     FileSizeHigh;
+    DWORD     FileSizeLow;
+    DWORD     reserved[2];
+    CHAR      FileName[260];
+    CHAR      AlternateName[14];
+} WIN32_FIND_DATA32A, *LPWIN32_FIND_DATA32A;
+
+typedef struct
+{
+    DWORD     FileAttributes;
+    FILETIME  CreationTime;
+    FILETIME  LastAccessTime;
+    FILETIME  LastWriteTime;
+    DWORD     FileSizeHigh;
+    DWORD     FileSizeLow;
+    DWORD     reserved[2];
+    WCHAR     FileName[260];
+    WCHAR     AlternateName[14];
+} WIN32_FIND_DATA32W, *LPWIN32_FIND_DATA32W;
+
+DECL_WINELIB_TYPE_AW(WIN32_FIND_DATA);
+DECL_WINELIB_TYPE_AW(LPWIN32_FIND_DATA);
+
 #define VER_PLATFORM_WIN32s             0
 #define VER_PLATFORM_WIN32_WINDOWS      1
 #define VER_PLATFORM_WIN32_NT           2
diff --git a/include/windows.h b/include/windows.h
index 767363a..2e6fa9f 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -1053,6 +1053,11 @@
 DECL_WINELIB_TYPE_AW(TEXTMETRIC);
 DECL_WINELIB_TYPE_AW(LPTEXTMETRIC);
 
+typedef INT16 (*FONTENUMPROC16)(SEGPTR,SEGPTR,UINT16,LPARAM);
+typedef INT32 (*FONTENUMPROC32A)(const LOGFONT32A*,const TEXTMETRIC32A*,UINT32,LPARAM);
+typedef INT32 (*FONTENUMPROC32W)(const LOGFONT32W*,const TEXTMETRIC32W*,UINT32,LPARAM);
+DECL_WINELIB_TYPE_AW(FONTENUMPROC);
+
   /* tmPitchAndFamily values */
 #define TMPF_FIXED_PITCH    1
 #define TMPF_VECTOR	    2
@@ -2508,6 +2513,13 @@
 #define ESB_DISABLE_LTUP    ESB_DISABLE_LEFT
 #define ESB_DISABLE_RTDN    ESB_DISABLE_RIGHT
 
+/* Scrollbar messages (undocumented) */
+#define SBM_SETSCROLLPOS      (WM_USER+0)
+#define SBM_GETSCROLLPOS      (WM_USER+1)
+#define SBM_SETSCROLLRANGE    (WM_USER+2)
+#define SBM_REDRAW            (WM_USER+3)
+#define SBM_ENABLE            (WM_USER+4)
+
 /* Listbox styles */
 #define LBS_NOTIFY            0x0001L
 #define LBS_SORT              0x0002L
@@ -3000,12 +3012,19 @@
 typedef METARECORD *LPMETARECORD;
 
 /* Handle table structure */
+
 typedef struct
 {
-    HANDLE16   objectHandle[1];
-} HANDLETABLE;
-typedef HANDLETABLE *PHANDLETABLE;
-typedef HANDLETABLE *LPHANDLETABLE;
+    HGDIOBJ16 objectHandle[1];
+} HANDLETABLE16, *LPHANDLETABLE16;
+
+typedef struct
+{
+    HGDIOBJ32 objectHandle[1];
+} HANDLETABLE32, *LPHANDLETABLE32;
+
+DECL_WINELIB_TYPE(HANDLETABLE);
+DECL_WINELIB_TYPE(LPHANDLETABLE);
 
 /* Clipboard metafile picture structure */
 typedef struct
@@ -3096,6 +3115,10 @@
 #define META_CREATEBITMAP            0x06FE
 #define META_CREATEREGION            0x06FF
 
+typedef INT16 (*MFENUMPROC16)(HDC16,HANDLETABLE16*,METARECORD*,INT16,LPARAM);
+typedef INT32 (*MFENUMPROC32)(HDC32,HANDLETABLE32*,METARECORD*,INT32,LPARAM);
+DECL_WINELIB_TYPE(MFENUMPROC);
+
 /* Debugging support (DEBUG SYSTEM ONLY) */
 typedef struct
 {
@@ -3281,8 +3304,10 @@
 UINT16     GetCommEventMask(INT16,UINT16);
 HTASK16    GetCurrentTask(void);
 HMODULE16  GetExePtr(HANDLE16);
+WORD       GetExeVersion(void);
 HINSTANCE16 GetTaskDS(void);
 HQUEUE16   GetTaskQueue(HTASK16);
+BOOL16     IsSharedSelector(HANDLE16);
 BOOL16     LocalInit(HANDLE16,WORD,WORD);
 DWORD      OffsetViewportOrg(HDC16,INT16,INT16);
 DWORD      OffsetWindowOrg(HDC16,INT16,INT16);
@@ -3294,6 +3319,7 @@
 DWORD      SetBitmapDimension(HBITMAP16,INT16,INT16);
 DWORD      SetBrushOrg(HDC16,INT16,INT16);
 UINT16*    SetCommEventMask(INT16,UINT16);
+FARPROC16  SetTaskSignalProc(HTASK16,FARPROC16);
 DWORD      SetViewportExt(HDC16,INT16,INT16);
 DWORD      SetViewportOrg(HDC16,INT16,INT16);
 DWORD      SetWindowExt(HDC16,INT16,INT16);
@@ -3403,6 +3429,7 @@
 VOID       SetRectRgn(HRGN32,INT32,INT32,INT32,INT32);
 WORD       SetWindowWord(HWND32,INT32,WORD);
 BOOL16     ShowCaret(HWND32);
+HWND16     WindowFromDC(HDC32);
 HFILE      _lclose(HFILE);
 HFILE      _lcreat(LPCSTR,INT32);
 HFILE      _lopen(LPCSTR,INT32);
@@ -3914,6 +3941,9 @@
 INT16      LZRead16(HFILE,SEGPTR,UINT16); 
 INT32      LZRead32(HFILE,LPVOID,UINT32); 
 #define    LZRead WINELIB_NAME(LZRead)
+VOID       LineDDA16(INT16,INT16,INT16,INT16,LINEDDAPROC16,LPARAM);
+BOOL32     LineDDA32(INT32,INT32,INT32,INT32,LINEDDAPROC32,LPARAM);
+#define    LineDDA WINELIB_NAME(LineDDA)
 HACCEL16   LoadAccelerators16(HINSTANCE16,SEGPTR);
 HACCEL32   LoadAccelerators32A(HINSTANCE32,LPCSTR);
 HACCEL32   LoadAccelerators32W(HINSTANCE32,LPCWSTR);
@@ -4359,17 +4389,9 @@
 #ifdef WINELIB
 typedef LONG (*DRIVERPROC)(DWORD, HDRVR, UINT, LPARAM, LPARAM);
 typedef int (*EDITWORDBREAKPROC)(LPSTR lpch, int ichCurrent, int cch,int code);
-/*typedef int (*FONTENUMPROC)(const LOGFONT*,const TEXTMETRIC*,DWORD,LPARAM);*/
-typedef int (*FONTENUMPROC)(const void*,const void*,DWORD,LPARAM);
-typedef int (*GOBJENUMPROC)(LPVOID,LPARAM);
-/*typedef int (*MFENUMPROC)(HDC,HANDLETABLE*,METARECORD*,int,LPARAM);*/
-typedef int (*MFENUMPROC)(HDC,void*,void*,int,LPARAM);
 #else
 typedef SEGPTR DRIVERPROC;
 typedef SEGPTR EDITWORDBREAKPROC;
-typedef SEGPTR FONTENUMPROC;
-typedef SEGPTR GOBJENUMPROC;
-typedef SEGPTR MFENUMPROC;
 #endif
 
 ATOM       AddAtom(SEGPTR);
@@ -4455,10 +4477,10 @@
 BOOL       EnableWindow(HWND,BOOL);
 BOOL       EndDeferWindowPos(HDWP16);
 UINT       EnumClipboardFormats(UINT);
-INT        EnumFontFamilies(HDC,LPCSTR,FONTENUMPROC,LPARAM);
-INT        EnumFonts(HDC,LPCSTR,FONTENUMPROC,LPARAM);
-BOOL       EnumMetaFile(HDC,HMETAFILE,MFENUMPROC,LPARAM);
-INT        EnumObjects(HDC,INT,GOBJENUMPROC,LPARAM);
+INT        EnumFontFamilies(HDC,LPCSTR,FONTENUMPROC16,LPARAM);
+INT        EnumFonts(HDC,LPCSTR,FONTENUMPROC16,LPARAM);
+BOOL       EnumMetaFile(HDC,HMETAFILE,MFENUMPROC16,LPARAM);
+INT        EnumObjects(HDC,INT,GOBJENUMPROC16,LPARAM);
 INT        Escape(HDC,INT,INT,LPCSTR,LPVOID);
 int        ExcludeClipRect(HDC,short,short,short,short);
 int        ExcludeVisRect(HDC,short,short,short,short);
@@ -4610,7 +4632,7 @@
 BOOL16     GlobalUnWire(HGLOBAL16);
 void       GlobalUnfix(HGLOBAL16);
 SEGPTR     GlobalWire(HGLOBAL16);
-BOOL       GrayString(HDC,HBRUSH,FARPROC16,LPARAM,INT,INT,INT,INT,INT);
+BOOL       GrayString(HDC,HBRUSH,GRAYSTRINGPROC16,LPARAM,INT,INT,INT,INT,INT);
 BOOL       HiliteMenuItem(HWND,HMENU,UINT,UINT);
 BOOL       InSendMessage(void);
 WORD       InitAtomTable(WORD);
@@ -4638,7 +4660,6 @@
 BOOL       IsWindowVisible(HWND);
 BOOL       IsZoomed(HWND);
 void       LimitEmsPages(DWORD);
-void       LineDDA(short,short,short,short,FARPROC16,long);
 BOOL       LineTo(HDC,short,short);
 HANDLE     LoadLibrary(LPCSTR);
 HANDLE     LoadModule(LPCSTR,LPVOID);
@@ -4661,7 +4682,7 @@
 BOOL       PatBlt(HDC,short,short,short,short,DWORD);
 BOOL       Pie(HDC,INT,INT,INT,INT,INT,INT,INT,INT);
 BOOL       PlayMetaFile(HDC,HANDLE);
-void       PlayMetaFileRecord(HDC,LPHANDLETABLE,LPMETARECORD,WORD);
+void       PlayMetaFileRecord(HDC,LPHANDLETABLE16,LPMETARECORD,WORD);
 BOOL       PostAppMessage(HANDLE,WORD,WORD,LONG);
 void       PostEvent(HTASK);
 BOOL       PostMessage(HWND,WORD,WORD,LONG);
diff --git a/include/wintypes.h b/include/wintypes.h
index 389a9fe..5345511 100644
--- a/include/wintypes.h
+++ b/include/wintypes.h
@@ -168,9 +168,18 @@
 typedef LRESULT (*FARPROC16)();
 typedef LRESULT (*FARPROC32)();
 DECL_WINELIB_TYPE(FARPROC);
+typedef INT16   (*GOBJENUMPROC16)(SEGPTR,LPARAM);
+typedef INT32   (*GOBJENUMPROC32)(LPVOID,LPARAM);
+DECL_WINELIB_TYPE(GOBJENUMPROC);
+typedef BOOL16  (*GRAYSTRINGPROC16)(HDC16,LPARAM,INT16);
+typedef BOOL32  (*GRAYSTRINGPROC32)(HDC32,LPARAM,INT32);
+DECL_WINELIB_TYPE(GRAYSTRINGPROC);
 typedef LRESULT (*HOOKPROC16)(INT16,WPARAM16,LPARAM);
 typedef LRESULT (*HOOKPROC32)(INT32,WPARAM32,LPARAM);
 DECL_WINELIB_TYPE(HOOKPROC);
+typedef VOID    (*LINEDDAPROC16)(INT16,INT16,LPARAM);
+typedef VOID    (*LINEDDAPROC32)(INT32,INT32,LPARAM);
+DECL_WINELIB_TYPE(LINEDDAPROC);
 typedef BOOL16  (*PROPENUMPROC16)(HWND16,SEGPTR,HANDLE16);
 typedef BOOL32  (*PROPENUMPROC32A)(HWND32,LPCSTR,HANDLE32);
 typedef BOOL32  (*PROPENUMPROC32W)(HWND32,LPCWSTR,HANDLE32);
diff --git a/library/miscstubs.c b/library/miscstubs.c
index 071b69e..9bce0ee 100644
--- a/library/miscstubs.c
+++ b/library/miscstubs.c
@@ -33,16 +33,14 @@
                 a[7],a[8],a[9],a[10]);
   case 14: return func(a[0],a[1],a[2],a[3],a[4],a[5],a[6],
                 a[7],a[8],a[9],a[10],a[11],a[12],a[13]);
-  case 17: return func(a[0],a[1],a[2],a[3],a[4],a[5],a[6],
-                a[7],a[8],a[9],a[10],a[11],a[12],a[13],a[14],a[15],a[16]);
+  case 16: return func(a[0],a[1],a[2],a[3],a[4],a[5],a[6],
+                a[7],a[8],a[9],a[10],a[11],a[12],a[13],a[14],a[15]);
   default: fprintf(stderr,"JBP: CallTo32_LargeStack called with unsupported "
                           "number of arguments (%d).  Ignored.\n",nbargs);
            return 0;
   }
 }
 
-WORD CallTo16_word_ ( FARPROC16 func, WORD arg ) { return func(arg); }
-
 extern LRESULT AboutDlgProc(HWND,UINT,WPARAM,LPARAM);
 extern LRESULT ColorDlgProc(HWND,UINT,WPARAM,LPARAM);
 extern LRESULT ComboBoxWndProc(HWND,UINT,WPARAM,LPARAM);
diff --git a/library/sup.c b/library/sup.c
index 194d7e7..934ac2b 100644
--- a/library/sup.c
+++ b/library/sup.c
@@ -1,7 +1,6 @@
 #include <stdio.h>
 #include <unistd.h>
 #include "windows.h"
-#include "callback.h"
 #include "arch.h"
 #include "neexe.h"
 
diff --git a/loader/builtin.c b/loader/builtin.c
index 4717f66..a7e618d 100644
--- a/loader/builtin.c
+++ b/loader/builtin.c
@@ -350,7 +350,7 @@
     static char buffer[80];
     BUILTIN_DLL *dll;
     const void **funcs;
-    int first, i, size;
+    int i;
 
     /* First find the module */
 
@@ -365,19 +365,11 @@
         return buffer;
     }
 
-    /* Do a binary search for the function */
+    /* Now find the function */
 
     relay = (BYTE *)relay - 11;  /* The relay entry point is 11 bytes long */
     funcs = dll->descr->u.win32.functions;
-    first = i = 0;
-    size = dll->descr->u.win32.size;
-    while (first < size)
-    {
-        i = (first + size) / 2;
-        if (funcs[i] == relay) break;
-        if (funcs[i] > relay) size = i;
-        else first = i + 1;
-    }
+    for (i = 0; i < dll->descr->u.win32.size;i++) if (*funcs++ == relay) break;
     sprintf( buffer, "%s.%d: %s",
              dll->descr->name, i, dll->descr->u.win32.names[i] );
     return buffer;
diff --git a/loader/module.c b/loader/module.c
index bf4fd5e..82850e7 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -1100,7 +1100,7 @@
 
 	if (pModule->flags & NE_FFLAGS_SELFLOAD)
 	{
-                int fd;
+                HFILE hf;
 		/* Handle self loading modules */
 		SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
 		SELFLOADHEADER *selfloadheader;
@@ -1166,9 +1166,9 @@
 
 		}
                 /* FIXME: we probably need a DOS handle here */
-                fd = MODULE_OpenFile( hModule );
-		CallTo16_word_ww (selfloadheader->BootApp,
-			pModule->self_loading_sel, hModule, fd);
+                hf = FILE_DupUnixHandle( MODULE_OpenFile( hModule ) );
+		CallTo16_word_ww( selfloadheader->BootApp, hModule, hf );
+                _lclose(hf);
 		/* some BootApp procs overwrite the selector of dgroup */
 		pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
 		IF1632_Saved16_ss = oldss;
@@ -1537,6 +1537,18 @@
 
 
 /**********************************************************************
+ *	    IsSharedSelector    (KERNEL.345)
+ */
+BOOL16 IsSharedSelector( HANDLE16 selector )
+{
+    /* Check whether the selector belongs to a DLL */
+    NE_MODULE *pModule = MODULE_GetPtr( GetExePtr( selector ));
+    if (!pModule) return FALSE;
+    return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;
+}
+
+
+/**********************************************************************
  *	    ModuleFirst    (TOOLHELP.59)
  */
 BOOL16 ModuleFirst( MODULEENTRY *lpme )
diff --git a/loader/ne_image.c b/loader/ne_image.c
index ad5af2f..a32007e 100644
--- a/loader/ne_image.c
+++ b/loader/ne_image.c
@@ -67,6 +67,8 @@
  	SELFLOADHEADER *selfloadheader;
         STACK16FRAME *stack16Top;
  	WORD oldss, oldsp, oldselector, newselector;
+        HFILE hf = FILE_DupUnixHandle( fd );
+
  	selfloadheader = (SELFLOADHEADER *)
  		PTR_SEG_OFF_TO_LIN(pSegTable->selector,0);
  	oldss = IF1632_Saved16_ss;
@@ -84,9 +86,9 @@
         stack16Top->bp = 0;
         stack16Top->ip = 0;
         stack16Top->cs = 0;
-        /* FIXME: we probably need to pass a DOS file handle here */
- 	newselector =  CallTo16_word_www(selfloadheader->LoadAppSeg,
- 		pModule->self_loading_sel, hModule, fd, segnum);
+ 	newselector =  CallTo16_word_www( selfloadheader->LoadAppSeg,
+                                          hModule, hf, segnum );
+        _lclose( hf );
  	if (newselector != oldselector) {
  	  /* Self loaders like creating their own selectors; 
  	   * they love asking for trouble to Wine developers
diff --git a/loader/task.c b/loader/task.c
index bf32790..b1bea0d 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -25,6 +25,7 @@
 #include "peexe.h"
 #include "pe_image.h"
 #include "queue.h"
+#include "stackframe.h"
 #include "toolhelp.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -61,9 +62,9 @@
 static FARPROC16 TASK_RescheduleProc;
 
 #ifdef WINELIB
-#define TASK_SCHEDULE()  TASK_Reschedule();
+#define TASK_SCHEDULE()  TASK_Reschedule()
 #else
-#define TASK_SCHEDULE()  CallTo16_word_(TASK_RescheduleProc,0)
+#define TASK_SCHEDULE()  CallTo16_word_(TASK_RescheduleProc)
 #endif
 
 static HANDLE TASK_CreateDOSEnvironment(void);
@@ -1066,20 +1067,33 @@
 {
     TDB *pTask;
     STACK16FRAME *oldFrame, *newFrame;
+    INSTANCEDATA *pData;
+    UINT16 copySize;
 
     if (!(pTask = (TDB *)GlobalLock16( hCurrentTask ))) return;
+    if (!(pData = (INSTANCEDATA *)GlobalLock16( seg ))) return;
     dprintf_task( stddeb, "SwitchStackTo: old=%04x:%04x new=%04x:%04x\n",
                   IF1632_Saved16_ss, IF1632_Saved16_sp, seg, ptr );
+
     /* Save the old stack */
-    oldFrame = CURRENT_STACK16;
-    pTask->switchStackSS = IF1632_Saved16_ss;
-    pTask->switchStackSP = IF1632_Saved16_sp;
+
+    oldFrame           = CURRENT_STACK16;
+    pData->old_sp      = IF1632_Saved16_sp;
+    pData->old_ss      = IF1632_Saved16_ss;
+    pData->stacktop    = top;
+    pData->stackmin    = ptr;
+    pData->stackbottom = ptr;
+
     /* Switch to the new stack */
-    IF1632_Saved16_ss = seg;
-    IF1632_Saved16_sp = ptr - sizeof(STACK16FRAME);
+
+    IF1632_Saved16_ss = pTask->ss = seg;
+    IF1632_Saved16_sp = pTask->sp = ptr - sizeof(STACK16FRAME);
     newFrame = CURRENT_STACK16;
-    /* Build the stack frame on the new stack */
-    *newFrame = *oldFrame;
+
+    /* Copy the stack frame and the local variables to the new stack */
+
+    copySize = oldFrame->bp - pData->old_sp;
+    memcpy( newFrame, oldFrame, MAX( copySize, sizeof(STACK16FRAME) ));
 }
 
 
@@ -1094,22 +1108,28 @@
 {
     TDB *pTask;
     STACK16FRAME *oldFrame, *newFrame;
+    INSTANCEDATA *pData;
 
     if (!(pTask = (TDB *)GlobalLock16( hCurrentTask ))) return;
-    if (!pTask->switchStackSS)
+    if (!(pData = (INSTANCEDATA *)GlobalLock16( IF1632_Saved16_ss ))) return;
+    if (!pData->old_ss)
     {
         fprintf( stderr, "SwitchStackBack: no previous SwitchStackTo\n" );
         return;
     }
     dprintf_task( stddeb, "SwitchStackBack: restoring stack %04x:%04x\n",
-                  pTask->switchStackSS, pTask->switchStackSP );
+                  pData->old_ss, pData->old_sp );
 
     oldFrame = CURRENT_STACK16;
+
     /* Switch back to the old stack */
-    IF1632_Saved16_ss = pTask->switchStackSS;
-    IF1632_Saved16_sp = pTask->switchStackSP;
-    pTask->switchStackSS = 0;
+
+    IF1632_Saved16_ss = pTask->ss = pData->old_ss;
+    IF1632_Saved16_sp = pTask->sp = pData->old_sp;
+    pData->old_ss = pData->old_sp = 0;
+
     /* Build a stack frame for the return */
+
     newFrame = CURRENT_STACK16;
     newFrame->saved_ss = oldFrame->saved_ss;
     newFrame->saved_sp = oldFrame->saved_sp;
@@ -1185,6 +1205,18 @@
 
 
 /***********************************************************************
+ *           GetExeVersion   (KERNEL.105)
+ */
+WORD GetExeVersion(void)
+{
+    TDB *pTask;
+
+    if (!(pTask = (TDB *)GlobalLock16( hCurrentTask ))) return 0;
+    return pTask->version;
+}
+
+
+/***********************************************************************
  *           SetErrorMode   (KERNEL.107)
  */
 UINT SetErrorMode( UINT mode )
@@ -1222,6 +1254,9 @@
 
 /***********************************************************************
  *           GetTaskDS   (KERNEL.155)
+ *
+ * Note: this function apparently returns a DWORD with LOWORD == HIWORD.
+ * I don't think we need to bother with this.
  */
 HINSTANCE16 GetTaskDS(void)
 {
@@ -1246,6 +1281,47 @@
 
 
 /***********************************************************************
+ *           SetTaskSignalProc   (KERNEL.38)
+ */
+FARPROC16 SetTaskSignalProc( HTASK16 hTask, FARPROC16 proc )
+{
+    TDB *pTask;
+    FARPROC16 oldProc;
+
+    if (!hTask) hTask = hCurrentTask;
+    if (!(pTask = (TDB *)GlobalLock16( hTask ))) return NULL;
+    oldProc = pTask->userhandler;
+    pTask->userhandler = proc;
+    return oldProc;
+}
+
+
+/***********************************************************************
+ *           SetSigHandler   (KERNEL.140)
+ */
+WORD SetSigHandler( FARPROC16 newhandler, FARPROC16* oldhandler,
+                    UINT16 *oldmode, UINT16 newmode, UINT16 flag )
+{
+    fprintf(stdnimp,"SetSigHandler(%p,%p,%p,%d,%d), unimplemented.\n",
+            newhandler,oldhandler,oldmode,newmode,flag );
+
+    if (flag != 1) return 0;
+    if (!newmode) newhandler = NULL;  /* Default handler */
+    if (newmode != 4)
+    {
+        TDB *pTask;
+
+        if (!(pTask = (TDB *)GlobalLock16( hCurrentTask ))) return 0;
+        if (oldmode) *oldmode = pTask->signal_flags;
+        pTask->signal_flags = newmode;
+        if (oldhandler) *oldhandler = pTask->sighandler;
+        pTask->sighandler = newhandler;
+    }
+    return 0;
+}
+
+
+/***********************************************************************
  *           GetExePtr   (KERNEL.133)
  */
 HMODULE16 GetExePtr( HANDLE16 handle )
@@ -1349,15 +1425,3 @@
     if (GlobalSize16(hTask) < sizeof(TDB)) return 0;
     return pTask->compat_flags;
 }
-
-
-/***********************************************************************
- *           SetSigHandler   (KERNEL.140)
- */
-WORD SetSigHandler( SEGPTR newhandler,SEGPTR* oldhandler,
-                    LPUINT16 *oldmode,UINT16 newmode,UINT16 flag )
-{
-    fprintf(stdnimp,"SetSigHandler(%lx,%p,%p,%d,%d), unimplemented.\n",
-            newhandler,oldhandler,oldmode,newmode,flag );
-    return 0;
-}
diff --git a/misc/commdlg.c b/misc/commdlg.c
index 176bb5a..723d577 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -2231,13 +2231,15 @@
 /***********************************************************************
  *                FontFamilyEnumProc                       (COMMDLG.19)
  */
-int FontFamilyEnumProc(LPLOGFONT16 lplf, LPTEXTMETRIC16 lptm, int nFontType, LPARAM lParam)
+INT16 FontFamilyEnumProc( SEGPTR logfont, SEGPTR metrics,
+                          UINT16 nFontType, LPARAM lParam )
 {
   int i;
   WORD w;
   HWND hwnd=LOWORD(lParam);
   HWND hDlg=GetParent(hwnd);
   LPCHOOSEFONT lpcf=(LPCHOOSEFONT)GetWindowLong32A(hDlg, DWL_USER); 
+  LOGFONT16 *lplf = (LOGFONT16 *)PTR_SEG_TO_LIN( logfont );
 
   dprintf_commdlg(stddeb,"FontFamilyEnumProc: font=%s (nFontType=%d)\n",
      			lplf->lfFaceName,nFontType);
@@ -2268,7 +2270,8 @@
  *
  * Fill font style information into combobox  (without using font.c directly)
  */
-static int SetFontStylesToCombo2(HWND hwnd, HDC hdc, LPLOGFONT16 lplf ,LPTEXTMETRIC16 lptm)
+static int SetFontStylesToCombo2(HWND hwnd, HDC hdc, LPLOGFONT16 lplf,
+                                 LPTEXTMETRIC16 lptm)
 {
    #define FSTYLES 4
    struct FONTSTYLE
@@ -2338,12 +2341,15 @@
 /***********************************************************************
  *                 FontStyleEnumProc                     (COMMDLG.18)
  */
-int FontStyleEnumProc(LPLOGFONT16 lplf ,LPTEXTMETRIC16 lptm, int nFontType, LPARAM lParam)
+INT16 FontStyleEnumProc( SEGPTR logfont, SEGPTR metrics,
+                         UINT16 nFontType, LPARAM lParam )
 {
   HWND hcmb2=LOWORD(lParam);
   HWND hcmb3=HIWORD(lParam);
   HWND hDlg=GetParent(hcmb3);
   LPCHOOSEFONT lpcf=(LPCHOOSEFONT)GetWindowLong32A(hDlg, DWL_USER); 
+  LOGFONT16 *lplf = (LOGFONT16 *)PTR_SEG_TO_LIN(logfont);
+  TEXTMETRIC16 *lptm = (TEXTMETRIC16 *)PTR_SEG_TO_LIN(metrics);
   int i;
   
   dprintf_commdlg(stddeb,"FontStyleEnumProc: (nFontType=%d)\n",nFontType);
@@ -2376,7 +2382,6 @@
   HDC hdc;
   int i,j,res,init=0;
   long l;
-  FARPROC16 enumCallback = MODULE_GetWndProcEntry16("FontFamilyEnumProc");
   LPLOGFONT16 lpxx;
   HCURSOR hcursor=SetCursor(LoadCursor16(0,IDC_WAIT));
   LPCHOOSEFONT lpcf;
@@ -2422,7 +2427,7 @@
   hdc= (lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC) ? lpcf->hDC : GetDC(hDlg);
   if (hdc)
   {
-    if (!EnumFontFamilies (hdc, NULL,enumCallback,(LPARAM)GetDlgItem(hDlg,cmb1)))
+    if (!EnumFontFamilies (hdc, NULL,FontFamilyEnumProc,(LPARAM)GetDlgItem(hDlg,cmb1)))
       dprintf_commdlg(stddeb,"WM_INITDIALOG: EnumFontFamilies returns 0\n");
     if (lpcf->Flags & CF_INITTOLOGFONTSTRUCT)
     {
@@ -2610,7 +2615,6 @@
 LRESULT CFn_WMCommand(HWND hDlg, WPARAM wParam, LPARAM lParam)
 {
   char buffer[200];
-  FARPROC16 enumCallback;
   HFONT hFont/*,hFontOld*/;
   int i,j;
   long l;
@@ -2634,8 +2638,7 @@
 		        HCURSOR hcursor=SetCursor(LoadCursor16(0,IDC_WAIT));
                         SendDlgItemMessage16(hDlg,cmb1,CB_GETLBTEXT,i,(LPARAM)MAKE_SEGPTR(buffer));
 	                dprintf_commdlg(stddeb,"WM_COMMAND/cmb1 =>%s\n",buffer);
-		        enumCallback = MODULE_GetWndProcEntry16("FontStyleEnumProc");
-       		        EnumFontFamilies(hdc,buffer,enumCallback,
+       		        EnumFontFamilies(hdc,buffer,FontStyleEnumProc,
 		             MAKELONG(GetDlgItem(hDlg,cmb2),GetDlgItem(hDlg,cmb3)));
 		        SetCursor(hcursor);        
 		      }
diff --git a/misc/exec.c b/misc/exec.c
index fb67a0b..6c6b844 100644
--- a/misc/exec.c
+++ b/misc/exec.c
@@ -11,7 +11,6 @@
 #include "heap.h"
 #include "neexe.h"
 #include "shell.h"
-#include "callback.h"
 #include "stddebug.h"
 #include "debug.h"
 #include "win.h"
diff --git a/multimedia/joystick.c b/multimedia/joystick.c
index 821957b..301ba6c 100644
--- a/multimedia/joystick.c
+++ b/multimedia/joystick.c
@@ -12,7 +12,6 @@
 #include <sys/ioctl.h>
 #include "windows.h"
 #include "ldt.h"
-#include "callback.h"
 #include "user.h"
 #include "driver.h"
 #include "mmsystem.h"
diff --git a/multimedia/mcistring.c b/multimedia/mcistring.c
index 5abd42a..895a113 100644
--- a/multimedia/mcistring.c
+++ b/multimedia/mcistring.c
@@ -16,7 +16,6 @@
 #include <sys/ioctl.h>
 #include "windows.h"
 #include "ldt.h"
-#include "callback.h"
 #include "user.h"
 #include "driver.h"
 #include "mmsystem.h"
diff --git a/multimedia/mmsystem.c b/multimedia/mmsystem.c
index 283c928..e974c8b 100644
--- a/multimedia/mmsystem.c
+++ b/multimedia/mmsystem.c
@@ -17,7 +17,6 @@
 #include <sys/ioctl.h>
 #include "windows.h"
 #include "ldt.h"
-#include "callback.h"
 #include "user.h"
 #include "driver.h"
 #include "file.h"
diff --git a/multimedia/time.c b/multimedia/time.c
index b525372..299405e 100644
--- a/multimedia/time.c
+++ b/multimedia/time.c
@@ -72,9 +72,8 @@
  *          guess current implementation via SetTimer has to be improved upon.		
  */
 
-		CallTo16_word_wwlll(lpTimer->lpFunc,
-			lpTimer->hInstance, lpTimer->wTimerID, 
-			0, lpTimer->dwUser, 0, 0);
+		CallTimeFuncProc(lpTimer->lpFunc, lpTimer->wTimerID, 
+                                    0, lpTimer->dwUser, 0, 0);
 
 		dprintf_mmtime(stddeb, "MMSysTimeCallback // after CallBack16 !\n");
 		fflush(stdout);
diff --git a/objects/bitmap.c b/objects/bitmap.c
index f609f25..afc0b6b 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -129,8 +129,12 @@
 
     dprintf_gdi( stddeb, "CreateCompatibleBitmap(%04x,%d,%d) = \n", 
                  hdc, width, height );
-    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
-    
+    dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return 0;
+    }
     hbmpRet = CreateBitmap( width, height, 1, dc->w.bitsPerPixel, NULL );
     dprintf_gdi(stddeb,"\t\t%04x\n", hbmpRet);
     return hbmpRet;
diff --git a/objects/color.c b/objects/color.c
index b7c45a2..308d191 100644
--- a/objects/color.c
+++ b/objects/color.c
@@ -34,10 +34,6 @@
  * http://198.105.232.5/MSDN/LIBRARY/TECHNOTE/CH3.HTM 
  */
 
-extern void BITBLT_SetAccelMode( int ); /* speed up INVERT raster ops whenever possible 
-					 * parameter is a speedup level (see bitblt.c)
-					 */
-
 typedef struct
 { 
     Colormap    colorMap;
@@ -375,9 +371,6 @@
 
         cs->size = c_min + NB_RESERVED_COLORS;
 
-	COLOR_gapStart = cs->size/2;
-	COLOR_gapEnd = 256 - cs->size/2;
-
 	XUngrabServer(display);
 
 	dprintf_palette(stddeb,"adjusted size %i colorcells\n", cs->size);
@@ -690,7 +683,7 @@
     BYTE r = GetRValue(col), g = GetGValue(col), b = GetBValue(col);
     for( i = 0; i < size; i++ )
     {
-        if( palPalEntry[i].peFlags & PC_SYS_USED ) 	/* skip gap */
+        if( palPalEntry[i].peFlags & PC_SYS_USED ) 	/* skips gap */
             if( palPalEntry[i].peRed == r &&
                 palPalEntry[i].peGreen == g &&
                 palPalEntry[i].peBlue == b )
@@ -964,17 +957,15 @@
 
                     COLOR_sysPal[index] = palPtr->logpalette.palPalEntry[i];
                     COLOR_sysPal[index].peFlags = flag;
-                    if( COLOR_PaletteToPixel ) index = COLOR_PaletteToPixel[index];
-
 		    COLOR_freeList[index] = 0;
-		    palPtr->logpalette.palPalEntry[i].peFlags = PC_SYS_USED | PC_SYS_MAPPED;
+
+                    if( COLOR_PaletteToPixel ) index = COLOR_PaletteToPixel[index];
                     break;
                 }
                 else if ( cSpace.flags & COLOR_VIRTUAL ) 
                 {
                     index = COLOR_ToPhysical( NULL, 0x00ffffff &
                              *(COLORREF*)(palPtr->logpalette.palPalEntry + i));
-		    palPtr->logpalette.palPalEntry[i].peFlags = PC_SYS_USED;
                     break;     
                 }
 
@@ -983,7 +974,7 @@
                 index = COLOR_PaletteLookupPixel(COLOR_sysPal, 256, NULL, 
                        *(COLORREF*)(palPtr->logpalette.palPalEntry + i), TRUE);
             }
-	    palPtr->logpalette.palPalEntry[i].peFlags = PC_SYS_USED;
+	    palPtr->logpalette.palPalEntry[i].peFlags |= PC_SYS_USED;
 
             if( COLOR_PaletteToPixel ) index = COLOR_PaletteToPixel[index];
             break;
diff --git a/objects/dib.c b/objects/dib.c
index ef9f072..e94b417 100644
--- a/objects/dib.c
+++ b/objects/dib.c
@@ -562,13 +562,17 @@
  * Helper function for SetDIBits() and SetDIBitsToDevice().
  */
 static int DIB_SetImageBits( DC *dc, WORD lines, WORD depth, LPSTR bits,
-                             DWORD infoWidth, WORD infoBpp, DWORD compression,
+                             DWORD infoWidth, WORD infoBpp,
                              BITMAPINFO *info, WORD coloruse,
 			     Drawable drawable, GC gc, int xSrc, int ySrc,
 			     int xDest, int yDest, int width, int height )
 {
     int *colorMapping;
     XImage *bmpImage;
+    DWORD compression = 0;
+
+    if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
+        compression = info->bmiHeader.biCompression;
 
       /* Build the color mapping table */
 
@@ -647,24 +651,27 @@
 {
     DC * dc;
     BITMAPOBJ * bmp;
-    DWORD width, height, compression = 0;
+    DWORD width, height;
     WORD bpp;
 
       /* Check parameters */
 
-    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
+    dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return 0;
+    }
     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
 	return 0;
     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &bpp ) == -1)
         return 0;
-    if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
-        compression = info->bmiHeader.biCompression;
     if (!lines || (startscan >= (WORD)height)) return 0;
     if (startscan + lines > height) lines = height - startscan;
 
-    return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 17,
+    return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 16,
                                 dc, lines, bmp->bitmap.bmBitsPixel,
-                                bits, width, bpp, compression, info,
+                                bits, width, bpp, info,
                                 coloruse, bmp->pixmap, BITMAP_GC(bmp), 0, 0, 0,
                                 startscan, bmp->bitmap.bmWidth, lines );
 }
@@ -679,16 +686,19 @@
                          UINT32 coloruse )
 {
     DC * dc;
-    DWORD width, height, compression = 0;
+    DWORD width, height;
     WORD bpp;
 
       /* Check parameters */
 
-    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
+    dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return 0;
+    }
     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &bpp ) == -1)
         return 0;
-    if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
-        compression = info->bmiHeader.biCompression;
     if (!lines || (startscan >= height)) return 0;
     if (startscan + lines > height) lines = height - startscan;
     if (ySrc < startscan) ySrc = startscan;
@@ -700,9 +710,9 @@
 
     DC_SetupGCForText( dc );  /* To have the correct colors */
     XSetFunction( display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
-    return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 17,
+    return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 16,
                                 dc, lines, dc->w.bitsPerPixel, bits, width,
-                                bpp, compression, info, coloruse,
+                                bpp, info, coloruse,
                                 dc->u.x.drawable, dc->u.x.gc,
                                 xSrc, ySrc - startscan,
                                 dc->w.DCOrgX + XLPTODP( dc, xDest ),
@@ -726,7 +736,12 @@
     int i, x, y;
         
     if (!lines) return 0;
-    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
+    dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return 0;
+    }
     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
 	return 0;
     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
diff --git a/objects/font.c b/objects/font.c
index fb4e234..5cdfd38 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -15,7 +15,6 @@
 #include <X11/Xatom.h>
 #include "font.h"
 #include "metafile.h"
-#include "callback.h"
 #include "options.h"
 #include "string32.h"
 #include "xmalloc.h"
@@ -1124,7 +1123,7 @@
 /*************************************************************************
  *				EnumFonts			[GDI.70]
  */
-INT EnumFonts(HDC hDC, LPCSTR lpFaceName, FONTENUMPROC lpEnumFunc, LPARAM lpData)
+INT EnumFonts(HDC hDC, LPCSTR lpFaceName, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
 {
   HANDLE       hLog;
   HANDLE       hMet;
@@ -1178,8 +1177,8 @@
     SelectObject(hDC, hOldFont);
     DeleteObject(hFont);
     dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
-    nRet = CallEnumFontsProc((FARPROC16)lpEnumFunc, GDI_HEAP_SEG_ADDR(hLog),
-			     GDI_HEAP_SEG_ADDR(hMet), 0, (LONG)lpData );
+    nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
+                       0, (LONG)lpData );
     if (nRet == 0) {
       dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
       break;
@@ -1194,7 +1193,7 @@
 /*************************************************************************
  *				EnumFontFamilies	[GDI.330]
  */
-INT EnumFontFamilies(HDC hDC, LPCSTR lpszFamily, FONTENUMPROC lpEnumFunc, LPARAM lpData)
+INT EnumFontFamilies(HDC hDC, LPCSTR lpszFamily, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
 {
   HANDLE       	hLog;
   HANDLE       	hMet;
@@ -1248,10 +1247,8 @@
     DeleteObject(hFont);
     dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
     
-    nRet = CallEnumFontFamProc( (FARPROC16)lpEnumFunc,
-			       GDI_HEAP_SEG_ADDR(hLog),
-			       GDI_HEAP_SEG_ADDR(hMet),
-			       0, lpData );
+    nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
+                       0, lpData );
     if (nRet == 0) {
       dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
       break;
diff --git a/objects/gdiobj.c b/objects/gdiobj.c
index 1dffd30..c406140 100644
--- a/objects/gdiobj.c
+++ b/objects/gdiobj.c
@@ -16,7 +16,6 @@
 #include "palette.h"
 #include "pen.h"
 #include "region.h"
-#include "callback.h"
 #include "stddebug.h"
 #include "debug.h"
 #include "xmalloc.h"
@@ -435,7 +434,8 @@
 /***********************************************************************
  *           EnumObjects    (GDI.71)
  */
-INT EnumObjects( HDC hdc, INT nObjType, GOBJENUMPROC lpEnumFunc, LPARAM lParam )
+INT EnumObjects( HDC hdc, INT nObjType, GOBJENUMPROC16 lpEnumFunc,
+                 LPARAM lParam )
 {
     /* Solid colors to enumerate */
     static const COLORREF solid_colors[] =
@@ -466,8 +466,7 @@
             pen->lopnWidth.x = 1;
             pen->lopnWidth.y = 0;
             pen->lopnColor   = solid_colors[i];
-            retval = CallEnumObjectsProc( (FARPROC16)lpEnumFunc,
-                                          SEGPTR_GET(pen), lParam );
+            retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
             dprintf_gdi( stddeb, "EnumObject: solid pen %08lx, ret=%d\n",
                          solid_colors[i], retval);
             if (!retval) break;
@@ -483,8 +482,7 @@
             brush->lbStyle = BS_SOLID;
             brush->lbColor = solid_colors[i];
             brush->lbHatch = 0;
-            retval = CallEnumObjectsProc( (FARPROC16)lpEnumFunc,
-                                          SEGPTR_GET(brush), lParam );
+            retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
             dprintf_gdi( stddeb, "EnumObject: solid brush %08lx, ret=%d\n",
                          solid_colors[i], retval);
             if (!retval) break;
@@ -496,8 +494,7 @@
             brush->lbStyle = BS_HATCHED;
             brush->lbColor = RGB(0,0,0);
             brush->lbHatch = i;
-            retval = CallEnumObjectsProc( (FARPROC16)lpEnumFunc,
-                                          SEGPTR_GET(brush), lParam );
+            retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
             dprintf_gdi( stddeb, "EnumObject: hatched brush %d, ret=%d\n",
                          i, retval);
             if (!retval) break;
diff --git a/objects/linedda.c b/objects/linedda.c
index 5ef10f2..be9693f 100644
--- a/objects/linedda.c
+++ b/objects/linedda.c
@@ -2,24 +2,35 @@
  * LineDDA
  *
  * Copyright 1993 Bob Amstadt
- *
  */
 
+#define NO_TRANSITION_TYPES  /* This file is Win32-clean */
 #include <stdlib.h>
 #include "windows.h"
-#include "callback.h"
+
 
 /**********************************************************************
- *		LineDDA		(GDI.100)
+ *           LineDDA16   (GDI.100)
  */
-void LineDDA(short nXStart, short nYStart, short nXEnd, short nYEnd,
-	     FARPROC16 callback, long lParam)
+void LineDDA16( INT16 nXStart, INT16 nYStart, INT16 nXEnd, INT16 nYEnd,
+                LINEDDAPROC16 callback, LPARAM lParam )
 {
-    int xadd = 1, yadd = 1;
-    int err,erradd;
-    int cnt;
-    int dx = nXEnd - nXStart;
-    int dy = nYEnd - nYStart;
+    LineDDA32( nXStart, nYStart, nXEnd, nYEnd,
+               (LINEDDAPROC32)callback, lParam );
+}
+
+
+/**********************************************************************
+ *           LineDDA32   (GDI32.248)
+ */
+BOOL32 LineDDA32( INT32 nXStart, INT32 nYStart, INT32 nXEnd, INT32 nYEnd,
+                  LINEDDAPROC32 callback, LPARAM lParam )
+{
+    INT32 xadd = 1, yadd = 1;
+    INT32 err,erradd;
+    INT32 cnt;
+    INT32 dx = nXEnd - nXStart;
+    INT32 dy = nYEnd - nYStart;
 
     if (dx < 0)  {
       dx = -dx; xadd = -1;
@@ -30,7 +41,7 @@
     if (dx > dy) { /* line is "more horizontal" */
       err = 2*dy - dx; erradd = 2*dy - 2*dx;
       for(cnt = 0;cnt <= dx; cnt++) {
-	CallLineDDAProc(callback,nXStart,nYStart,lParam);
+        callback(nXStart,nYStart,lParam);
 	if (err > 0) {
 	  nYStart += yadd;
 	  err += erradd;
@@ -42,7 +53,7 @@
     } else  { /* line is "more vertical" */
       err = 2*dx - dy; erradd = 2*dx - 2*dy;
       for(cnt = 0;cnt <= dy; cnt++) {
-	CallLineDDAProc(callback,nXStart,nYStart,lParam);
+	callback(nXStart,nYStart,lParam);
 	if (err > 0) {
 	  nXStart += xadd;
 	  err += erradd;
@@ -52,4 +63,5 @@
 	nYStart += yadd;
       }
     }
+    return TRUE;
 }
diff --git a/objects/metafile.c b/objects/metafile.c
index f3fb1a7..3c2ad1a 100644
--- a/objects/metafile.c
+++ b/objects/metafile.c
@@ -2,7 +2,7 @@
  * Metafile functions
  *
  * Copyright  David W. Metcalfe, 1994
- *            Niels de Carpentier, 1996
+ *            Niels de Carpentier, Albrecht Kleine 1996
  *
  */
 
@@ -12,8 +12,8 @@
 #include "bitmap.h"
 #include "file.h"
 #include "metafile.h"
+#include "stackframe.h"
 #include "stddebug.h"
-#include "callback.h"
 #include "debug.h"
 
 #define HTINCR  10      /* handle table allocation size increment */
@@ -107,7 +107,7 @@
         GDI_FreeObject(handle);
 	return 0;
     }
-    
+    dc->w.bitsPerPixel    = screenDepth;
     mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
 
     mh->mtHeaderSize = MFHEADERSIZE / 2;
@@ -135,14 +135,13 @@
     /* create the handle table */
     HTLen = HTINCR;
     hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT, 
-		      sizeof(HANDLETABLE) * HTLen);
+		      sizeof(HANDLETABLE16) * HTLen);
     
     GlobalUnlock16(dc->w.hMetaFile);
     dprintf_metafile(stddeb,"CreateMetaFile: returning %04x\n", handle);
     return handle;
 }
 
-
 /******************************************************************
  *         CopyMetafile         GDI.151 Niels de Carpentier, April 1996
  */
@@ -163,8 +162,13 @@
     
     if (lpFilename)          /* disk based metafile */
         {
+        int i,j;
 	hFile = _lcreat(lpFilename, 0);
-	if (_lwrite(hFile, (char *)mh, mh->mtSize * 2) == -1)
+	j=mh->mtType;
+	mh->mtType=1;        /* disk file version stores 1 here */
+	i=_lwrite(hFile, (char *)mh, mh->mtSize * 2) ;
+	mh->mtType=j;        /* restore old value  [0 or 1] */	
+	if (i == -1)
 	    {
 	    _lclose(hFile);
 	    return 0;
@@ -264,7 +268,7 @@
 {
     METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
     METARECORD *mr;
-    HANDLETABLE *ht;
+    HANDLETABLE16 *ht;
     int offset = 0;
     WORD i;
 
@@ -272,8 +276,8 @@
     
     /* create the handle table */
     hHT = GlobalAlloc16(GMEM_MOVEABLE|GMEM_ZEROINIT,
-		      sizeof(HANDLETABLE) * mh->mtNoObjects);
-    ht = (HANDLETABLE *)GlobalLock16(hHT);
+		      sizeof(HANDLETABLE16) * mh->mtNoObjects);
+    ht = (HANDLETABLE16 *)GlobalLock16(hHT);
 
     /* loop through metafile playing records */
     offset = mh->mtHeaderSize * 2;
@@ -303,7 +307,7 @@
  *                                    Niels de carpentier, april 1996
  */
 
-BOOL EnumMetaFile(HDC hdc, HMETAFILE hmf, MFENUMPROC lpEnumFunc,LPARAM lpData)
+BOOL EnumMetaFile(HDC hdc, HMETAFILE hmf, MFENUMPROC16 lpEnumFunc,LPARAM lpData)
 {
     METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
     METARECORD *mr;
@@ -316,7 +320,7 @@
     /* create the handle table */
     
     hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
-		     sizeof(HANDLETABLE) * mh->mtNoObjects);
+		     sizeof(HANDLETABLE16) * mh->mtNoObjects);
     ht = WIN16_GlobalLock16(hHT);
    
     offset = mh->mtHeaderSize * 2;
@@ -326,9 +330,8 @@
     while (offset < (mh->mtSize * 2))
     {
 	mr = (METARECORD *)((char *)mh + offset);
-        if (!CallEnumMetafileProc( (FARPROC16)lpEnumFunc, hdc, ht,
-                                   MAKE_SEGPTR(mr),  /* FIXME!! */
-                                   mh->mtNoObjects, (LONG)lpData))
+        if (!lpEnumFunc( hdc, ht, MAKE_SEGPTR(mr),  /* FIXME!! */
+                         mh->mtNoObjects, (LONG)lpData))
 	    break;
 
 	offset += (mr->rdSize * 2);
@@ -340,12 +343,53 @@
     return TRUE;
 }
 
+/*******************************************************************
+ *   MF_GetDIBitsPointer    [internal helper for e.g. PlayMetaFileRecord]
+ *
+ * Returns offset to DIB bits or 0 if error
+ * (perhaps should be moved to (objects/dib.c ?)
+ */
+static LPSTR MF_GetDIBitsPointer(LPBITMAPINFO info)
+{
+      int offset;
+      if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
+	{
+        if (info->bmiHeader.biClrUsed)
+	  {
+	  if (info->bmiHeader.biClrUsed < (1 << info->bmiHeader.biBitCount))
+	    offset = info->bmiHeader.biClrUsed * 4;
+          else
+	    offset = (1 << info->bmiHeader.biBitCount) * 4;
+          }
+        else
+	  offset = (1 << info->bmiHeader.biBitCount) * 4;
+	}
+      else if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+	{
+	if (info->bmiHeader.biClrUsed)
+	  {
+	  if (info->bmiHeader.biClrUsed < (1 << info->bmiHeader.biBitCount))
+	    offset = info->bmiHeader.biClrUsed * 3;
+          else
+	    offset = (1 << info->bmiHeader.biBitCount) * 3;
+          }
+        else
+	  offset = (1 << info->bmiHeader.biBitCount) * 3;
+	}
+      else
+	{
+	fprintf(stderr,"Unknown size for BITMAPHEADER in MetaFile!\n");
+	return NULL;
+	}
+      return (LPSTR)info + info->bmiHeader.biSize + offset; 
+}
+
 
 /******************************************************************
  *         PlayMetaFileRecord      GDI.176
  */
 
-void PlayMetaFileRecord(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
+void PlayMetaFileRecord(HDC hdc, HANDLETABLE16 *ht, METARECORD *mr,
 			                           WORD nHandles)
 {
     short s1;
@@ -603,76 +647,93 @@
 	dprintf_metafile(stddeb,"PlayMetaFileRecord: META_ESCAPE unimplemented.\n");
         break;
 
-    case META_EXTTEXTOUT: /* FIXME: don't know the exact parameters here */
-        {
-        short x,y,options,x5,x6,x7,x8;
-        y=mr->rdParam[0];  /* X position */
-        x=mr->rdParam[1];  /* Y position */
-        s1=mr->rdParam[2]; /* String length */
-        options=mr->rdParam[3];
-        x5=mr->rdParam[(s1+1)/2+4]; /* unknown meaning */
-        x6=mr->rdParam[(s1+1)/2+5]; /* unknown meaning */
-        x7=mr->rdParam[(s1+1)/2+6]; /* unknown meaning */
-        x8=mr->rdParam[(s1+1)/2+7]; /* unknown meaning */
-	ExtTextOut16( hdc, x, y, options, (LPRECT16) &mr->rdParam[(s1+1)/2+4],
-                      (char *)(mr->rdParam + 4), s1, NULL );
-	/* fprintf(stderr,"EXTTEXTOUT (len: %d) %hd : %hd %hd %hd %hd [%s].\n",
-            (mr->rdSize-s1),options,x5,x6,x7,x8,(char*) &(mr->rdParam[4]) );*/
-        }
-        break;
-        /* End new metafile operations. */
+        /* --- Begin of fixed or new metafile operations. July 1996 ----*/
+    case META_EXTTEXTOUT:
+      {
+        LPINT16 dxx;
+        s1=mr->rdParam[2];                              /* String length */
+        if (mr->rdSize-(s1+1))
+         dxx=&mr->rdParam[8+(s1+1)/2];                  /* start of array */
+        else
+         dxx=NULL;                                      /* NO array present */
+          
+	ExtTextOut16( hdc, mr->rdParam[1],              /* X position */
+	                   mr->rdParam[0],              /* Y position */
+	                   mr->rdParam[3],              /* options */
+	                   (LPRECT16) &mr->rdParam[4],  /* rectangle */
+                           (char *)(mr->rdParam + 8),   /* string */
+                           s1, dxx);                    /* length, dx array */
+        if (dxx)                      
+          dprintf_metafile(stddeb,"EXTTEXTOUT len: %ld  (%hd %hd)  [%s].\n",
+            mr->rdSize,dxx[0],dxx[1],(char*) &(mr->rdParam[8]) );
+       }
+       break;
     
     case META_STRETCHDIB:
       {
-      LPSTR bits;
-      LPBITMAPINFO info;
-      int offset;
-      info = (LPBITMAPINFO) &(mr->rdParam[11]);
-      if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
-	{
-        if (info->bmiHeader.biClrUsed)
-	  {
-	  if (info->bmiHeader.biClrUsed < (1 << info->bmiHeader.biBitCount))
-	    offset = info->bmiHeader.biClrUsed * 4;
-          else
-	    offset = (1 << info->bmiHeader.biBitCount) * 4;
-          }
-        else
-	  offset = (1 << info->bmiHeader.biBitCount) * 4;
-	}
-      else if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
-	{
-	if (info->bmiHeader.biClrUsed)
-	  {
-	  if (info->bmiHeader.biClrUsed < (1 << info->bmiHeader.biBitCount))
-	    offset = info->bmiHeader.biClrUsed * 3;
-          else
-	    offset = (1 << info->bmiHeader.biBitCount) * 3;
-          }
-        else
-	  offset = (1 << info->bmiHeader.biBitCount) * 3;
-	}
-      else
-	{
-	fprintf(stderr,"Unknown size for BITMAPHEADER in PlayMetaRecord!\n");
-	break;
-	}
-	
-      offset += info->bmiHeader.biSize; 
-      bits = (LPSTR) info + offset;
-      StretchDIBits(hdc,mr->rdParam[10],mr->rdParam[9],mr->rdParam[8],
+       LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[11]);
+       LPSTR bits = MF_GetDIBitsPointer(info);
+       if (bits)
+        StretchDIBits(hdc,mr->rdParam[10],mr->rdParam[9],mr->rdParam[8],
 		    mr->rdParam[7],mr->rdParam[6],mr->rdParam[5],
 		    mr->rdParam[4],mr->rdParam[3],bits,info,
-		    mr->rdParam[2],(DWORD)mr->rdParam[0]);
+		    mr->rdParam[2],MAKELONG(mr->rdParam[0],mr->rdParam[1]));
       }
       break;
-		    
+
+    case META_DIBSTRETCHBLT:
+      {
+       LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[10]); 
+       LPSTR bits = MF_GetDIBitsPointer(info);
+       if (bits)
+         StretchDIBits(hdc,mr->rdParam[9],mr->rdParam[8],mr->rdParam[7],
+		    mr->rdParam[6],mr->rdParam[5],mr->rdParam[4],
+		    mr->rdParam[3],mr->rdParam[2],bits,info,
+		    DIB_RGB_COLORS,MAKELONG(mr->rdParam[0],mr->rdParam[1]));
+      }
+      break;		  
+
+    case META_STRETCHBLT:
+      {
+       HDC hdcSrc=CreateCompatibleDC(hdc);
+       HBITMAP16 hbitmap=CreateBitmap(mr->rdParam[10], /*Width */
+                                      mr->rdParam[11], /*Height*/
+                                      mr->rdParam[13], /*Planes*/
+                                      mr->rdParam[14], /*BitsPixel*/
+                                      (LPSTR)&mr->rdParam[15]);  /*bits*/
+       SelectObject(hdcSrc,hbitmap);
+       StretchBlt(hdc,mr->rdParam[9],mr->rdParam[8],
+                    mr->rdParam[7],mr->rdParam[6],
+		    hdcSrc,mr->rdParam[5],mr->rdParam[4],
+		    mr->rdParam[3],mr->rdParam[2],
+		    MAKELONG(mr->rdParam[0],mr->rdParam[1]));
+       DeleteDC(hdcSrc);		    
+      }
+      break;
+
+    case META_BITBLT:            /* <-- not yet debugged */
+      {
+       HDC hdcSrc=CreateCompatibleDC(hdc);
+       HBITMAP16 hbitmap=CreateBitmap(mr->rdParam[7]/*Width */,mr->rdParam[8]/*Height*/,
+                            mr->rdParam[10]/*Planes*/,mr->rdParam[11]/*BitsPixel*/,
+                            (LPSTR)&mr->rdParam[12]/*bits*/);
+       SelectObject(hdcSrc,hbitmap);
+       BitBlt(hdc,mr->rdParam[6],mr->rdParam[5],
+                    mr->rdParam[4],mr->rdParam[3],
+		    hdcSrc,
+		    mr->rdParam[2],mr->rdParam[1],
+		    MAKELONG(0,mr->rdParam[0]));
+       DeleteDC(hdcSrc);		    
+      }
+      break;
+
     default:
 	fprintf(stddeb,"PlayMetaFileRecord: Unknown record type %x\n",
 	                                      mr->rdFunction);
     }
 }
 
+
 /******************************************************************
  *         GetMetaFileBits		by William Magro, 19 Sep 1995
  *
@@ -744,7 +805,7 @@
  *    Add a handle to an external handle table and return the index
  */
 
-int MF_AddHandle(HANDLETABLE *ht, WORD htlen, HANDLE hobj)
+int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HANDLE hobj)
 {
     int i;
 
@@ -769,7 +830,7 @@
 int MF_AddHandleInternal(HANDLE hobj)
 {
     int i;
-    HANDLETABLE *ht = (HANDLETABLE *)GlobalLock16(hHT);
+    HANDLETABLE16 *ht = (HANDLETABLE16 *)GlobalLock16(hHT);
 
     for (i = 0; i < HTLen; i++)
     {
@@ -784,7 +845,7 @@
     if (!(hHT = GlobalReAlloc16(hHT, HTINCR, GMEM_MOVEABLE | GMEM_ZEROINIT)))
 	return -1;
     HTLen += HTINCR;
-    ht = (HANDLETABLE *)GlobalLock16(hHT);
+    ht = (HANDLETABLE16 *)GlobalLock16(hHT);
     *(ht->objectHandle + i) = hobj;
     GlobalUnlock16(hHT);
     return i;
@@ -1158,6 +1219,40 @@
     return handle;
 }
 
+/******************************************************************
+ *         MF_ExtTextOut
+ */
+BOOL MF_ExtTextOut(DC *dc, short x, short y, UINT16 flags, const RECT16 *rect,
+                   LPCSTR str, short count, const INT16 *lpDx)
+{
+    HMETAFILE handle;
+    DWORD len;
+    HANDLE hmr;
+    METARECORD *mr;
+
+    len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4 + sizeof(RECT16);
+    if (lpDx)
+     len+=count*sizeof(INT16);
+    if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
+	return FALSE;
+    mr = (METARECORD *)GlobalLock16(hmr);
+    memset(mr, 0, len);
+
+    mr->rdSize = len / 2;
+    mr->rdFunction = META_EXTTEXTOUT;
+    *(mr->rdParam) = y;
+    *(mr->rdParam + 1) = x;
+    *(mr->rdParam + 2) = count;
+    *(mr->rdParam + 3) = flags;
+    memcpy(mr->rdParam + 4, rect, sizeof(RECT16));
+    memcpy(mr->rdParam + 8, str, count);
+    if (lpDx)
+     memcpy(mr->rdParam + 8+ ((count + 1) >> 1),lpDx,count*sizeof(INT16));
+    handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    dc->w.hMetaFile = handle;
+    GlobalFree16(hmr);
+    return handle;
+}
 
 /******************************************************************
  *         MF_MetaPoly - implements Polygon and Polyline
@@ -1192,18 +1287,130 @@
 BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
 	       short height, HDC hdcSrc, short xSrc, short ySrc, DWORD rop)
 {
-    fprintf(stdnimp,"MF_BitBlt: not implemented yet\n");
-    return FALSE;
+    HMETAFILE handle;
+    DWORD len;
+    HANDLE hmr;
+    METARECORD *mr;
+    DC *dcSrc;
+    BITMAP16  BM;
+
+    if (!(dcSrc = (DC *) GDI_GetObjPtr( hdcSrc, DC_MAGIC ))) return 0;
+    GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
+    len = sizeof(METARECORD) + 12 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
+    if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
+	return FALSE;
+    mr = (METARECORD *)GlobalLock16(hmr);
+    mr->rdFunction = META_BITBLT;
+    *(mr->rdParam + 7) = BM.bmWidth;
+    *(mr->rdParam + 8) = BM.bmHeight;
+    *(mr->rdParam + 9) = BM.bmWidthBytes;
+    *(mr->rdParam +10) = BM.bmPlanes;
+    *(mr->rdParam +11) = BM.bmBitsPixel;
+    dprintf_metafile(stddeb,"MF_StretchBlt->len = %ld  rop=%lx  \n",len,rop);
+    if (GetBitmapBits(dcSrc->w.hBitmap,BM.bmWidthBytes * BM.bmHeight,mr->rdParam +12))
+    {
+      mr->rdSize = len / sizeof(INT16);
+      *(mr->rdParam) = HIWORD(rop);
+      *(mr->rdParam + 1) = ySrc;
+      *(mr->rdParam + 2) = xSrc;
+      *(mr->rdParam + 3) = height;
+      *(mr->rdParam + 4) = width;
+      *(mr->rdParam + 5) = yDest;
+      *(mr->rdParam + 6) = xDest;
+      handle = MF_WriteRecord(dcDest->w.hMetaFile, mr, mr->rdSize * 2);
+    }  
+    else
+      handle = 0;  
+    dcDest->w.hMetaFile = handle;
+    GlobalFree16(hmr);
+    return handle;
 }
 
 
-/******************************************************************
- *         MF_StretchBlt
+/**********************************************************************
+ *         MF_StretchBlt         
+ * this function contains TWO ways for procesing StretchBlt in metafiles,
+ * decide between rdFunction values  META_STRETCHBLT or META_DIBSTRETCHBLT
+ * via #define STRETCH_VIA_DIB
  */
+#define STRETCH_VIA_DIB
+#undef  STRETCH_VIA_DIB
 BOOL MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
 		   short heightDest, HDC hdcSrc, short xSrc, short ySrc, 
 		   short widthSrc, short heightSrc, DWORD rop)
 {
-    fprintf(stdnimp,"MF_StretchBlt: not implemented yet\n");
-    return FALSE;
+    HMETAFILE handle;
+    DWORD len;
+    HANDLE hmr;
+    METARECORD *mr;
+    DC *dcSrc;
+    BITMAP16  BM;
+#ifdef STRETCH_VIA_DIB    
+    LPBITMAPINFOHEADER lpBMI;
+    WORD nBPP;
+#endif  
+    if (!(dcSrc = (DC *) GDI_GetObjPtr( hdcSrc, DC_MAGIC ))) return 0;
+    GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
+#ifdef STRETCH_VIA_DIB
+    nBPP = BM.bmPlanes * BM.bmBitsPixel;
+    len = sizeof(METARECORD) + 10 * sizeof(INT16) 
+            + sizeof(BITMAPINFOHEADER) + (nBPP != 24 ? 1 << nBPP: 0) * sizeof(RGBQUAD) 
+              + ((BM.bmWidth * nBPP + 31) / 32) * 4 * BM.bmHeight;
+    if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
+	return FALSE;
+    mr = (METARECORD *)GlobalLock16(hmr);
+    mr->rdFunction = META_DIBSTRETCHBLT;
+    lpBMI=(LPBITMAPINFOHEADER)(mr->rdParam+10);
+    lpBMI->biSize      = sizeof(BITMAPINFOHEADER);
+    lpBMI->biWidth     = BM.bmWidth;
+    lpBMI->biHeight    = BM.bmHeight;
+    lpBMI->biPlanes    = 1;
+    lpBMI->biBitCount  = nBPP;                              /* 1,4,8 or 24 */
+    lpBMI->biClrUsed   = nBPP != 24 ? 1 << nBPP : 0;
+    lpBMI->biSizeImage = ((lpBMI->biWidth * nBPP + 31) / 32) * 4 * lpBMI->biHeight;
+    lpBMI->biCompression = BI_RGB;
+    lpBMI->biXPelsPerMeter = MulDiv32(GetDeviceCaps(hdcSrc,LOGPIXELSX),3937,100);
+    lpBMI->biYPelsPerMeter = MulDiv32(GetDeviceCaps(hdcSrc,LOGPIXELSY),3937,100);
+    lpBMI->biClrImportant  = 0;                          /* 1 meter  = 39.37 inch */
+
+    dprintf_metafile(stddeb,"MF_StretchBltViaDIB->len = %ld  rop=%lx  PixYPM=%ld Caps=%d\n",
+               len,rop,lpBMI->biYPelsPerMeter,GetDeviceCaps(hdcSrc,LOGPIXELSY));
+    if (GetDIBits(hdcSrc,dcSrc->w.hBitmap,0,(UINT)lpBMI->biHeight,
+              MF_GetDIBitsPointer((LPBITMAPINFO)lpBMI),    /* DIB bits */
+              (LPBITMAPINFO)lpBMI,DIB_RGB_COLORS))         /* DIB info structure */ 
+#else
+    len = sizeof(METARECORD) + 15 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
+    if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
+	return FALSE;
+    mr = (METARECORD *)GlobalLock16(hmr);
+    mr->rdFunction = META_STRETCHBLT;
+    *(mr->rdParam +10) = BM.bmWidth;
+    *(mr->rdParam +11) = BM.bmHeight;
+    *(mr->rdParam +12) = BM.bmWidthBytes;
+    *(mr->rdParam +13) = BM.bmPlanes;
+    *(mr->rdParam +14) = BM.bmBitsPixel;
+    dprintf_metafile(stddeb,"MF_StretchBlt->len = %ld  rop=%lx  \n",len,rop);
+    if (GetBitmapBits(dcSrc->w.hBitmap,BM.bmWidthBytes * BM.bmHeight,mr->rdParam +15))
+#endif    
+    {
+      mr->rdSize = len / sizeof(INT16);
+      *(mr->rdParam) = LOWORD(rop);
+      *(mr->rdParam + 1) = HIWORD(rop);
+      *(mr->rdParam + 2) = heightSrc;
+      *(mr->rdParam + 3) = widthSrc;
+      *(mr->rdParam + 4) = ySrc;
+      *(mr->rdParam + 5) = xSrc;
+      *(mr->rdParam + 6) = heightDest;
+      *(mr->rdParam + 7) = widthDest;
+      *(mr->rdParam + 8) = yDest;
+      *(mr->rdParam + 9) = xDest;
+      handle = MF_WriteRecord(dcDest->w.hMetaFile, mr, mr->rdSize * 2);
+    }  
+    else
+      handle = 0;  
+    dcDest->w.hMetaFile = handle;
+    GlobalFree16(hmr);
+    return handle;
 }
+
+
diff --git a/objects/palette.c b/objects/palette.c
index 854322a..ab8f25b 100644
--- a/objects/palette.c
+++ b/objects/palette.c
@@ -15,8 +15,6 @@
 /* #define DEBUG_PALETTE */
 #include "debug.h"
 
-extern HWND 		DCE_hDC2hWnd( HDC );			/* get associated window by 
-								 * walking DCE list */
 extern int              COLOR_LookupSystemPixel(COLORREF);      /* lookup pixel among static entries 
                                                                  * of the system palette */
 extern COLORREF		COLOR_GetSystemPaletteEntry(BYTE);
@@ -389,7 +387,7 @@
 
     if( hPal != STOCK_DEFAULT_PALETTE )
     {
-	HWND hWnd = DCE_hDC2hWnd( hDC );
+	HWND hWnd = WindowFromDC( hDC );
 	HWND hActive = GetActiveWindow();
 	
 	/* set primary palette if it's related to current active */
@@ -417,7 +415,7 @@
 	/* Send palette change notification */
 
 	HWND hWnd;
- 	if( (hWnd = DCE_hDC2hWnd( hDC )) )
+ 	if( (hWnd = WindowFromDC( hDC )) )
             SendMessage16( HWND_BROADCAST, WM_PALETTECHANGED, hWnd, 0L);
     }
     return realized;
@@ -430,7 +428,7 @@
  */
 int UpdateColors( HDC hDC )
 {
-    HWND hWnd = DCE_hDC2hWnd( hDC );
+    HWND hWnd = WindowFromDC( hDC );
 
     /* Docs say that we have to remap current drawable pixel by pixel
      * but it would take forever given the speed of XGet/PutPixel.
diff --git a/objects/text.c b/objects/text.c
index 5c892d8..bbfb6d5 100644
--- a/objects/text.c
+++ b/objects/text.c
@@ -331,7 +331,7 @@
     {
 	dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC );
 	if (!dc) return FALSE;
-	MF_TextOut( dc, x, y, str, count );
+	MF_ExtTextOut( dc, x, y, flags, lprect, str, count, lpDx );
 	return TRUE;
     }
 
@@ -616,16 +616,16 @@
 
 
 /***********************************************************************
- *		GrayString (USER.185)
+ *           GrayString   (USER.185)
  */
-BOOL GrayString(HDC hdc, HBRUSH hbr, FARPROC16 gsprc, LPARAM lParam, 
+BOOL GrayString(HDC hdc, HBRUSH hbr, GRAYSTRINGPROC16 gsprc, LPARAM lParam, 
 		INT cch, INT x, INT y, INT cx, INT cy)
 {
     BOOL ret;
     COLORREF current_color;
 
     if (!cch) cch = lstrlen16( (LPCSTR)PTR_SEG_TO_LIN(lParam) );
-    if (gsprc) return CallGrayStringProc( gsprc, hdc, lParam, cch );
+    if (gsprc) return gsprc( hdc, lParam, cch );
     current_color = GetTextColor( hdc );
     SetTextColor( hdc, GetSysColor(COLOR_GRAYTEXT) );
     ret = TextOut16( hdc, x, y, (LPCSTR)PTR_SEG_TO_LIN(lParam), cch );
diff --git a/programs/progman/ChangeLog b/programs/progman/ChangeLog
index 9345fd7..d24c29a 100644
--- a/programs/progman/ChangeLog
+++ b/programs/progman/ChangeLog
@@ -1,3 +1,8 @@
+Mon Jul 22 20:30:11 1996  Jussi Tirkkonen <jt@modeemi.cs.tut.fi>
+
+	* [Fi.rc] (new)
+	Added Finnish language support.
+
 Sun Jun  2 13:14:55 1996  Ulrich Schmid  <uschmid@mail.hh.provi.de>
 
 	* Program icons: repaint on WM_NCPAINT or WM_PAINTICON
diff --git a/programs/progman/Fi.rc b/programs/progman/Fi.rc
new file mode 100644
index 0000000..a38379c
--- /dev/null
+++ b/programs/progman/Fi.rc
@@ -0,0 +1,120 @@
+/*
+ * Program Manager
+ *
+ * Copyright 1996 Ulrich Schmid
+ * Finnish language by Jussi Tirkkonen <jt@modeemi.cs.tut.fi>
+ */
+
+#define LANGUAGE_ID                  Fi
+#define LANGUAGE_NUMBER              5
+#define LANGUAGE_MENU_ITEM           "&Suomi"
+
+/* Menu */
+
+#define MENU_FILE                    "&Tiedosto"
+#define MENU_FILE_NEW                "&Uusi..."
+#define MENU_FILE_OPEN               "&Avaa\tEnter"
+#define MENU_FILE_MOVE               "&Siirrä...\tF7"
+#define MENU_FILE_COPY               "&Kopioi...\tF8"
+#define MENU_FILE_DELETE             "&Poista\tDel"
+#define MENU_FILE_ATTRIBUTES         "&Ominaisuudet...\tAlt+Enter"
+#define MENU_FILE_EXECUTE            "Suo&rita..."
+#define MENU_FILE_EXIT               "&Lopeta..."
+
+#define MENU_OPTIONS                 "&Asetukset"
+#define MENU_OPTIONS_AUTO_ARRANGE    "&Järjestä automaattisesti"
+#define MENU_OPTIONS_MIN_ON_RUN      "&Pienennä käytettäessä"
+#define MENU_OPTIONS_SAVE_SETTINGS   "&Tallenna asetukset lopetettaessa"
+
+#define MENU_WINDOWS                 "&Ikkuna"
+#define MENU_WINDOWS_OVERLAP         "&Limittäin\tVaihto+F5"
+#define MENU_WINDOWS_SIDE_BY_SIDE    "&Vierekkäin\tVaihto+F4"
+#define MENU_WINDOWS_ARRANGE         "&Järjestä kuvakkeet"
+
+#define MENU_LANGUAGE                "&Kieli"
+
+#define MENU_HELP                    "&Ohje"
+#define MENU_HELP_CONTENTS           "&Sisällys"
+#define MENU_HELP_SEARCH             "&Etsi ohje aiheesta..."
+#define MENU_HELP_HELP_ON_HELP       "&Ohjeen käyttö"
+#define MENU_HELP_TUTORIAL           "O&petusohjelma"
+
+#define MENU_INFO                    "Ti&etoja..."
+#define MENU_INFO_LICENSE            "&Lisenssi"
+#define MENU_INFO_NO_WARRANTY        "&OMALLA VASTUULLA"
+#define MENU_INFO_ABOUT_WINE         "&Tietoja WINEstä"
+
+/* Dialogs */
+
+#define DIALOG_OK                    "OK"
+#define DIALOG_CANCEL                "Peruuta"
+#define DIALOG_BROWSE                "&Selaa"
+#define DIALOG_HELP                  "&Ohje"
+
+#define DIALOG_NEW_CAPTION           "Uusi ilmentymä"
+#define DIALOG_NEW_NEW               "Uusi"
+#define DIALOG_NEW_GROUP             "Ohjelma&ryhmä"
+#define DIALOG_NEW_PROGRAM           "Ohjelma&"
+
+#define DIALOG_MOVE_CAPTION          "Siirrä"
+#define DIALOG_MOVE_PROGRAM          "Siirrä ohjelma:"
+#define DIALOG_MOVE_FROM_GROUP       "Ryhmästä:"
+#define DIALOG_MOVE_TO_GROUP         "&Ryhmään:"
+
+#define DIALOG_COPY_CAPTION          "Kopioi"
+#define DIALOG_COPY_PROGRAM          "Kopioi ohjelma:"
+#define DIALOG_COPY_FROM_GROUP       DIALOG_MOVE_FROM_GROUP
+#define DIALOG_COPY_TO_GROUP         DIALOG_MOVE_TO_GROUP
+
+#define DIALOG_GROUP_CAPTION         "Ohjelmaryhmän ominaisuudet"
+#define DIALOG_GROUP_DESCRIPTION     "&Kuvaus:"
+#define DIALOG_GROUP_FILE            "&Ryhmätiedosto:"
+
+#define DIALOG_PROGRAM_CAPTION       "Ohjelman ominaisuudet"
+#define DIALOG_PROGRAM_DESCRIPTION   DIALOG_GROUP_DESCRIPTION
+#define DIALOG_PROGRAM_COMMAND_LINE  "K&omentorivi:"
+#define DIALOG_PROGRAM_DIRECTORY     "&Työhakemisto:"
+#define DIALOG_PROGRAM_HOT_KEY       "&Pikanäppäin:"
+#define DIALOG_PROGRAM_SYMBOL        "Suo&rita kuvakkeena"
+#define DIALOG_PROGRAM_OTHER_SYMBOL  "&Vaihda kuvaketta..."
+
+#define DIALOG_SYMBOL_CAPTION        "Valitse kuvake"
+#define DIALOG_SYMBOL_FILE           "&Nimi:"
+#define DIALOG_SYMBOL_CURRENT        "Nykyinen &kuvake:"
+
+#define DIALOG_EXECUTE_CAPTION       "Suorita ohjelma"
+#define DIALOG_EXECUTE_COMMAND_LINE  DIALOG_PROGRAM_COMMAND_LINE
+#define DIALOG_EXECUTE_SYMBOL        DIALOG_PROGRAM_SYMBOL
+
+/* Strings */
+
+#define STRING_PROGRAM_MANAGER            "Järjestemänhallinta"
+#define STRING_ERROR                      "VIRHE"
+#define STRING_WARNING                    "VAROITUS"
+#define STRING_INFO                       "Tietoja"
+#define STRING_DELETE                     "Poista"
+#define STRING_DELETE_GROUP_s             "Poista ryhmä `%s' ?"
+#define STRING_DELETE_PROGRAM_s           "Poista ohjelma `%s' ?"
+#define STRING_NOT_IMPLEMENTED            "Ei käytettävissä"
+#define STRING_FILE_READ_ERROR_s          "Virhe luettaessa `%s'"
+#define STRING_FILE_WRITE_ERROR_s         "Virhe kirjoitettaessa `%s'"
+
+#define STRING_GRPFILE_READ_ERROR_s       "\
+Ryhmätiedostoa `%s' ei voida avata.\n\
+Yritetäänkö uudestaan?"
+
+#define STRING_OUT_OF_MEMORY              "Muisti lopussa"
+#define STRING_WINHELP_ERROR              "Ohje ei käytettävissä"
+#define STRING_UNKNOWN_FEATURE_s          "Tuntematon ominaisuus %s:ssa"
+#define STRING_FILE_NOT_OVERWRITTEN_s     "Tiedosto `%s' on olemassa. Tiedostoa ei muutettu."
+#define STRING_SAVE_GROUP_AS_s            "Tallenna ryhmä nimellä `%s' alkuperäisten tiedostojen säilyttämiseksi"
+
+#define STRING_NO_HOT_KEY                 "Ei mitään"
+
+#define STRING_ALL_FILES                  "Kaikki tiedostot (*.*)"
+#define STRING_PROGRAMS                   "Ohjelmat"
+#define STRING_LIBRARIES_DLL              "Kirjastot (*.dll)"
+#define STRING_SYMBOL_FILES               "Symbolitiedostot"
+#define STRING_SYMBOLS_ICO                "Kuvakkeet (*.ico)"
+
+#include "Xx.rc"
diff --git a/programs/progman/Makefile.in b/programs/progman/Makefile.in
index 8db65d2..63da670 100644
--- a/programs/progman/Makefile.in
+++ b/programs/progman/Makefile.in
@@ -3,7 +3,7 @@
 PROGRAMS = progman
 ALL_LIBS = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LDLIBS)
 
-LANGUAGES   = En De Fr
+LANGUAGES   = En De Fr Fi
 LICENSELANG = En
 
 # Installation infos
diff --git a/programs/progman/main.c b/programs/progman/main.c
index 1dd5e6d..e8590e2 100644
--- a/programs/progman/main.c
+++ b/programs/progman/main.c
@@ -15,6 +15,7 @@
 void LIBWINE_Register_accel();
 void LIBWINE_Register_De();
 void LIBWINE_Register_En();
+void LIBWINE_Register_Fi();
 void LIBWINE_Register_Fr();
 #endif
 
@@ -43,6 +44,7 @@
   LIBWINE_Register_accel();
   LIBWINE_Register_De();
   LIBWINE_Register_En();
+  LIBWINE_Register_Fi();
   LIBWINE_Register_Fr();
 #endif
 
diff --git a/programs/winhelp/ChangeLog b/programs/winhelp/ChangeLog
index 9af4b05..aa692bc 100644
--- a/programs/winhelp/ChangeLog
+++ b/programs/winhelp/ChangeLog
@@ -1,3 +1,8 @@
+Mon Jul 22 20:30:11 1996  Jussi Tirkkonen <jt@modeemi.cs.tut.fi>
+
+	* [Fi.rc] (new)
+	Added Finnish language support.
+
 Sat May 18 11:06:02 1996  Pablo Saratxaga <srtxg@f2219.n293.z2.fidonet.org>
 
 	* [Fr.rc] (new)
diff --git a/programs/winhelp/Fi.rc b/programs/winhelp/Fi.rc
new file mode 100644
index 0000000..8d929f3
--- /dev/null
+++ b/programs/winhelp/Fi.rc
@@ -0,0 +1,49 @@
+/*
+ * Help Viewer
+ *
+ * Copyright 1996 Ulrich Schmid
+ * Finnish language by Jussi Tirkkonen <jt@modeemi.cs.tut.fi>
+ */
+
+/* This file is not yet complete !! */
+
+#define LANGUAGE_ID                  Fi
+#define LANGUAGE_NUMBER              5
+
+/* Menu */
+
+#define MENU_FILE                    "&Tiedosto"
+#define MENU_FILE_OPEN               "&Avaa..."
+#define MENU_FILE_PRINT              "&Tulosta"
+#define MENU_FILE_PRINTER_SETUP      "&Kirjoittimen asetukset..."
+#define MENU_FILE_EXIT               "&Lopeta"
+
+#define MENU_EDIT                    "&Muokkaa"
+#define MENU_EDIT_COPY_DIALOG        "&Kopioi..."
+#define MENU_EDIT_ANNOTATE           "&Huomautus..."
+
+#define MENU_BOOKMARK                "&Kirjanmerkki"
+#define MENU_BOOKMARK_DEFINE         "&Aseta..."
+
+#define MENU_HELP                    "&Ohje"
+#define MENU_HELP_ON_HELP            "&Ohjeen käyttö"
+#define MENU_HELP_ON_TOP             "&Aina päällimmäisenä"
+#define MENU_HELP_INFO               "T&ietoja..."
+#define MENU_HELP_ABOUT_WINE         "&Tietoja WINEstä"
+
+/* Strings */
+
+#define STRING_WINE_HELP             "WINE Ohje"
+#define STRING_ERROR                 "VIRHE"
+#define STRING_WARNING               "VAROITUS"
+#define STRING_INFO                  "Tietoja"
+#define STRING_NOT_IMPLEMENTED       "Ei käytettävissä"
+#define STRING_HLPFILE_ERROR_s       "Virhe luettaessa ohjetiedostoa `%s'" 
+#define STRING_CONTENTS              "&Sisällys"
+#define STRING_SEARCH                "&Etsi"
+#define STRING_BACK                  "&Takaisin"
+#define STRING_HISTORY               "&Luetut"
+#define STRING_ALL_FILES             "Kaikki tiedostot (*.*)"
+#define STRING_HELP_FILES_HLP        "Ohjetiedostot (*.hlp)"
+
+#include "Xx.rc"
diff --git a/programs/winhelp/Makefile.in b/programs/winhelp/Makefile.in
index 0499f9f..5f6afa3 100644
--- a/programs/winhelp/Makefile.in
+++ b/programs/winhelp/Makefile.in
@@ -3,7 +3,7 @@
 PROGRAMS = winhelp hlp2sgml
 ALL_LIBS = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LDLIBS)
 
-LANGUAGES   = En De Fr
+LANGUAGES   = En De Fr Fi
 
 # Installation infos
 
diff --git a/programs/winhelp/winhelp.c b/programs/winhelp/winhelp.c
index 594efe0..177ea49 100644
--- a/programs/winhelp/winhelp.c
+++ b/programs/winhelp/winhelp.c
@@ -16,6 +16,7 @@
 
 VOID LIBWINE_Register_De(void);
 VOID LIBWINE_Register_En(void);
+VOID LIBWINE_Register_Fi(void);
 VOID LIBWINE_Register_Fr(void);
 
 static BOOL    WINHELP_RegisterWinClasses();
@@ -53,6 +54,7 @@
   /* Register resources */
   LIBWINE_Register_De();
   LIBWINE_Register_En();
+  LIBWINE_Register_Fi();
   LIBWINE_Register_Fr();
 #endif
 
diff --git a/tools/build.c b/tools/build.c
index 1e0d7b6..3f18bde 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -1652,17 +1652,16 @@
  *
  * Stack frame of the callback function:
  *  ...      ...
- * (ebp+24) arg2
- * (ebp+20) arg1
- * (ebp+16) 16-bit ds
+ * (ebp+20) arg2
+ * (ebp+16) arg1
  * (ebp+12) func to call
  * (ebp+8)  code selector
  * (ebp+4)  return address
  * (ebp)    previous ebp
  *
  * Prototypes for the CallTo16 functions:
- *   extern WORD CallTo16_word_xxx( FARPROC16 func, WORD ds, args... );
- *   extern LONG CallTo16_long_xxx( FARPROC16 func, WORD ds, args... );
+ *   extern WORD CallTo16_word_xxx( FARPROC16 func, args... );
+ *   extern LONG CallTo16_long_xxx( FARPROC16 func, args... );
  *   extern void CallTo16_regs_( FARPROC16 func, WORD ds, WORD es, WORD bp,
  *                               WORD ax, WORD bx, WORD cx, WORD dx,
  *                               WORD si, WORD di );
@@ -1753,10 +1752,10 @@
     }
     else  /* not a register function */
     {
-        int pos = 20;  /* first argument position */
+        int pos = 16;  /* first argument position */
 
         /* Make %bp point to the previous stackframe (built by CallFrom16) */
-        printf( "\tmovw %%sp,%%bp\n" );
+        printf( "\tmovzwl %%sp,%%ebp\n" );
         printf( "\taddw $16,%%bp\n" );
 
         while (*args)
@@ -1793,8 +1792,9 @@
     }
     else
     {
-        /* Set ax equal to ds for window procedures */
-        printf( "\tmovw 16(%%ebx),%%ax\n" );
+        /* Get previous ds from the 16-bit stack and */
+        /* set ax equal to ds for window procedures. */
+        printf( "\tmovw -10(%%ebp),%%ax\n" );
 #ifdef __svr4__
         printf( "\tdata16\n");
 #endif
diff --git a/win32/Makefile.in b/win32/Makefile.in
index 634e87b..df4f9b6 100644
--- a/win32/Makefile.in
+++ b/win32/Makefile.in
@@ -11,6 +11,7 @@
 	error.c \
 	except.c \
 	file.c \
+	findfile.c \
 	init.c \
 	memory.c \
 	newfns.c \
diff --git a/win32/file.c b/win32/file.c
index 5e5ad28..ffb0b2f 100644
--- a/win32/file.c
+++ b/win32/file.c
@@ -500,3 +500,18 @@
 		res |= FILE_ATTRIBUTE_READONLY;
 	return res;
 }
+
+/**************************************************************************
+ *              SetFileAttributes
+ */
+BOOL SetFileAttributes32A(LPCSTR lpFileName, DWORD attributes)
+
+{
+	struct stat buf;
+	DWORD	res=0;
+	char	*fn;
+
+	fprintf(stdnimp,"Call to stub function SetFileAttributesA(%s, %08x)\n",lpFileName, attributes);
+	return TRUE;
+}
+
diff --git a/win32/findfile.c b/win32/findfile.c
new file mode 100644
index 0000000..47b9d9e
--- /dev/null
+++ b/win32/findfile.c
@@ -0,0 +1,54 @@
+#include <sys/types.h>
+#include <dirent.h>
+#include <string.h>
+#include "xmalloc.h"
+#include "windows.h"
+#include "winbase.h"
+#include "dos_fs.h"
+
+HANDLE32 FindFirstFile32A(LPCSTR lpfilename, 
+			  LPWIN32_FIND_DATA32A lpFindFileData)
+
+{
+	char *unixpath = DOSFS_GetUnixFileName(lpfilename, FALSE);
+	char *p;
+	char *path;
+	char *mask;
+	DIR *dir;
+	struct dirent *dirent;
+	int namelen;
+	char *foundname;
+
+	if (!unixpath) {
+		/* FIXME: SetLastError(??) */
+		return INVALID_HANDLE_VALUE;
+	}
+	p = strrchr(unixpath, '/');
+	if (p) {
+		*p = '\0';
+		path = unixpath;
+		mask = p + 1;
+	} else {
+		path = ".";
+		mask = unixpath;
+	}
+	dir = opendir(path);
+	if (!dir) {
+		/* FIXME: SetLastError(??) */
+		return INVALID_HANDLE_VALUE;
+	}
+	while ((dirent = readdir(dir)) != NULL) {
+		if (!DOSFS_Match(DOSFS_Hash(dirent->d_name, TRUE)))
+			continue;
+		/* FIXME: Ought to fiddle to avoid
+                   returning ./.. in drive root */
+		namelen = strlen(path) + strlen(dirent->d_name);
+		foundname = xmalloc(namelen+1);
+		strcpy(foundname, path);
+		strcat(foundname, dirent->d_name);
+		strcpy(lpFindFileData->FileName, DOSFS_GetDosTrueName(foundname, TRUE));
+		free(foundname);
+		return dir;
+	}
+	return INVALID_HANDLE_VALUE;
+}
diff --git a/win32/memory.c b/win32/memory.c
index 4b78f3d..952c2e2 100644
--- a/win32/memory.c
+++ b/win32/memory.c
@@ -5,7 +5,6 @@
  */
 
 #include <fcntl.h>
-#include <malloc.h>
 #include <stdio.h>
 #include <string.h>
 #include <sys/time.h>
diff --git a/win32/newfns.c b/win32/newfns.c
index 805ed2e..31d116b 100644
--- a/win32/newfns.c
+++ b/win32/newfns.c
@@ -29,7 +29,15 @@
 
 {
 	/* Stub for now */
-	fprintf(stdnimp, "WIN32_SetWindowsHookEx Stub called!\n");
+	fprintf(stdnimp, "SetWindowsHookEx32A Stub called! (hook Id %d)\n", HookId);
 	
 	return (HHOOK) NULL;
 }
+
+BOOL UnhookWindowsHookEx32(HHOOK hHook)
+
+{
+	/* Stub for now */
+	fprintf(stdnimp, "UnhookWindowsHookEx32 Stub called!\n");
+	return FALSE;
+}
diff --git a/win32/user32.c b/win32/user32.c
index 4451e2a..594e0b63 100644
--- a/win32/user32.c
+++ b/win32/user32.c
@@ -34,6 +34,16 @@
 }
 
 /***********************************************************************
+ *          IsDialogMessageA     (USER32.341)
+ */
+BOOL IsDialogMessage32A(DWORD hwnd, MSG32* lpmsg)
+{
+	MSG16 msg;
+	STRUCT32_MSG32to16(lpmsg, &msg);
+	return IsDialogMessage(hwnd, &msg);
+}
+
+/***********************************************************************
  *         DispatchMessageA       (USER32.140)
  */
 LONG USER32_DispatchMessageA(MSG32* lpmsg)
diff --git a/windows/dce.c b/windows/dce.c
index 97fc7f5..58ada2a 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -118,11 +118,11 @@
 }
 
 /**********************************************************************
- *	    DCE_hDC2hWnd
+ *          WindowFromDC   (USER.117) (USER32.580)
  */
-HWND DCE_hDC2hWnd(HDC hDC)
+HWND16 WindowFromDC( HDC32 hDC )
 {
- HANDLE hdce = DCE_FindDCE(hDC); 
+ HANDLE16 hdce = DCE_FindDCE(hDC); 
 
  if( hdce )
    {
diff --git a/windows/defdlg.c b/windows/defdlg.c
index 0ddbea8..c91c607 100644
--- a/windows/defdlg.c
+++ b/windows/defdlg.c
@@ -40,7 +40,6 @@
     HWND hwndFocus = GetFocus();
 
     if (!hwndFocus || !IsChild( hwnd, hwndFocus )) return FALSE;
-    if (!infoPtr->hwndFocus) return FALSE;  /* Already saved */
     infoPtr->hwndFocus = hwndFocus;
       /* Remove default button */
     return TRUE;
@@ -60,7 +59,6 @@
 }
 
 
-#ifdef SUPERFLUOUS_FUNCTIONS
 /***********************************************************************
  *           DEFDLG_FindDefButton
  *
@@ -77,7 +75,6 @@
     }
     return hwndChild;
 }
-#endif
 
 
 /***********************************************************************
@@ -117,6 +114,8 @@
 static LRESULT DEFDLG_Proc( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
                             LPARAM lParam, DIALOGINFO *dlgInfo )
 {
+    HWND hwndDefId;
+
     switch(msg)
     {
 	case WM_INITDIALOG:
@@ -177,8 +176,13 @@
             return 1;
 
         case DM_GETDEFID:
-            if (dlgInfo->fEnd || !dlgInfo->msgResult) return 0;
-            return MAKELONG( dlgInfo->msgResult, DC_HASDEFID );
+            if (dlgInfo->fEnd) return 0;
+	    if (dlgInfo->msgResult)
+	      return MAKELONG( dlgInfo->msgResult, DC_HASDEFID );
+	    hwndDefId = DEFDLG_FindDefButton( hwnd );
+	    if (hwndDefId)
+	      return MAKELONG( GetDlgCtrlID( hwndDefId ), DC_HASDEFID);
+	    return 0;
 
 	case WM_NEXTDLGCTL:
 	    {
diff --git a/windows/dialog.c b/windows/dialog.c
index 9faec22..3fbcb14 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -550,7 +550,7 @@
     {
         rect.left += template.x * xUnit / 4;
         rect.top += template.y * yUnit / 8;
-        if (!(template.style & DS_ABSALIGN))
+        if ( !(template.style & DS_ABSALIGN) && !(template.style & WS_CHILD) )
             ClientToScreen16( owner, (POINT16 *)&rect );
     }
 
@@ -1160,7 +1160,7 @@
  */
 WORD IsDlgButtonChecked( HWND hwnd, WORD id )
 {
-    return (WORD)SendDlgItemMessage16( hwnd, id, BM_GETCHECK16, 0, 0 );
+    return (WORD)SendDlgItemMessage32A( hwnd, id, BM_GETCHECK32, 0, 0 );
 }
 
 
diff --git a/windows/event.c b/windows/event.c
index f00cfe9..9ea4349 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -148,6 +148,7 @@
 static void EVENT_SelectionNotify( XSelectionEvent *event);
 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event);
 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event );
+static void EVENT_MapNotify( HWND hwnd, XMapEvent *event );
 
 /* Usable only with OLVWM - compile option perhaps?
 static void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event );
@@ -238,7 +239,20 @@
  *       break;
  */
     case NoExpose:
-	break;   
+	break;
+
+    /* We get all these because of StructureNotifyMask. */
+    case UnmapNotify:
+    case CirculateNotify:
+    case CreateNotify:
+    case DestroyNotify:
+    case GravityNotify:
+    case ReparentNotify:
+	break;
+
+    case MapNotify:
+	EVENT_MapNotify( pWnd->hwndSelf, (XMapEvent *)event );
+	break;
 
     default:    
 	dprintf_event(stddeb, "Unprocessed event %s for hwnd %04x\n",
@@ -844,6 +858,19 @@
  */ 
 
 /**********************************************************************
+ *		EVENT_MapNotify
+ */
+void EVENT_MapNotify( HWND hWnd, XMapEvent *event )
+{
+    HWND hwndFocus = GetFocus();
+
+    if (hwndFocus && IsChild( hWnd, hwndFocus ))
+      FOCUS_SetXFocus(hwndFocus);
+
+    return;
+}
+
+/**********************************************************************
  *		SetCapture 	(USER.18)
  */
 HWND SetCapture( HWND hwnd )
diff --git a/windows/focus.c b/windows/focus.c
index 1c28025..f2c7f20 100644
--- a/windows/focus.c
+++ b/windows/focus.c
@@ -11,6 +11,7 @@
 #include "winpos.h"
 #include "hook.h"
 #include "color.h"
+#include "message.h"
 #include "options.h"
 
 static HWND hwndFocus = 0;
@@ -21,7 +22,7 @@
  * Set the X focus.
  * Explicit colormap management seems to work only with OLVWM.
  */
-static void FOCUS_SetXFocus( HWND hwnd )
+void FOCUS_SetXFocus( HWND hwnd )
 {
     XWindowAttributes win_attr;
     Window win;
@@ -47,6 +48,8 @@
     XSetInputFocus( display, win, RevertToParent, CurrentTime );
     if (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE)
         XInstallColormap( display, COLOR_GetColormap() );
+
+    EVENT_Synchronize();
 }
 
 /*****************************************************************
diff --git a/windows/graphics.c b/windows/graphics.c
index ef7806d..221bc02 100644
--- a/windows/graphics.c
+++ b/windows/graphics.c
@@ -453,7 +453,10 @@
 {
     HBRUSH prevBrush;
 
-    if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return 0;
+    /* coordinates are logical so we cannot fast-check rectangle
+     * - do it in PatBlt() after LPtoDP().
+     */
+
     if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
     PatBlt( hdc, rect->left, rect->top,
 	    rect->right - rect->left, rect->bottom - rect->top, PATCOPY );
@@ -469,7 +472,6 @@
 {
     HBRUSH prevBrush;
 
-    if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return 0;
     if (!(prevBrush = SelectObject( hdc, (HBRUSH16)hbrush ))) return 0;
     PatBlt( hdc, rect->left, rect->top,
 	    rect->right - rect->left, rect->bottom - rect->top, PATCOPY );
@@ -483,7 +485,6 @@
  */
 void InvertRect16( HDC16 hdc, const RECT16 *rect )
 {
-    if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return;
     PatBlt( hdc, rect->left, rect->top,
 	    rect->right - rect->left, rect->bottom - rect->top, DSTINVERT );
 }
@@ -494,7 +495,6 @@
  */
 void InvertRect32( HDC32 hdc, const RECT32 *rect )
 {
-    if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return;
     PatBlt( hdc, rect->left, rect->top,
 	    rect->right - rect->left, rect->bottom - rect->top, DSTINVERT );
 }
@@ -511,13 +511,13 @@
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return FALSE;
 
-    if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return 0;
-    if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
-    
     left   = XLPTODP( dc, rect->left );
     top    = YLPTODP( dc, rect->top );
     right  = XLPTODP( dc, rect->right );
     bottom = YLPTODP( dc, rect->bottom );
+
+    if ( (right <= left) || (bottom <= top) ) return 0;
+    if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
     
     if (DC_SetupGCForBrush( dc ))
     {
diff --git a/windows/hook.c b/windows/hook.c
index e9cb158..a8bc38b 100644
--- a/windows/hook.c
+++ b/windows/hook.c
@@ -15,6 +15,7 @@
 
 #define NO_TRANSITION_TYPES  /* This file is Win32-clean */
 #include "hook.h"
+#include "callback.h"
 #include "queue.h"
 #include "user.h"
 #include "stddebug.h"
diff --git a/windows/message.c b/windows/message.c
index ff5e646..82d04dd 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -15,6 +15,7 @@
 #include "sysmetrics.h"
 #include "hook.h"
 #include "spy.h"
+#include "stackframe.h"
 #include "winpos.h"
 #include "atom.h"
 #include "dde.h"
diff --git a/windows/property.c b/windows/property.c
index e60a61c..22bcf98 100644
--- a/windows/property.c
+++ b/windows/property.c
@@ -8,7 +8,6 @@
 #include <string.h>
 #include "win.h"
 #include "heap.h"
-#include "callback.h"
 #include "string32.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -235,8 +234,7 @@
 
         dprintf_prop( stddeb, "  Callback: handle=%08x str='%s'\n",
                       prop->handle, prop->string );
-        ret = CallEnumPropProc16( (FARPROC16)func, hwnd,
-                                  SEGPTR_GET(prop->string), prop->handle );
+        ret = func( hwnd, SEGPTR_GET(prop->string), prop->handle );
         if (!ret) break;
     }
     return ret;
@@ -248,24 +246,7 @@
  */
 INT32 EnumProps32A( HWND32 hwnd, PROPENUMPROC32A func )
 {
-    PROPERTY *prop, *next;
-    WND *pWnd;
-    INT32 ret = -1;
-
-    dprintf_prop( stddeb, "EnumProps32A: %04x %08x\n", hwnd, (UINT32)func );
-    if (!(pWnd = WIN_FindWndPtr( hwnd ))) return -1;
-    for (prop = pWnd->pProp; (prop); prop = next)
-    {
-        /* Already get the next in case the callback */
-        /* function removes the current property.    */
-        next = prop->next;
-
-        dprintf_prop( stddeb, "  Callback: handle=%08x str='%s'\n",
-                      prop->handle, prop->string );
-        ret = CallEnumPropProc32( func, hwnd, prop->string, prop->handle );
-        if (!ret) break;
-    }
-    return ret;
+    return EnumPropsEx32A( hwnd, (PROPENUMPROCEX32A)func, 0 );
 }
 
 
@@ -274,33 +255,7 @@
  */
 INT32 EnumProps32W( HWND32 hwnd, PROPENUMPROC32W func )
 {
-    PROPERTY *prop, *next;
-    WND *pWnd;
-    INT32 ret = -1;
-
-    dprintf_prop( stddeb, "EnumProps32W: %04x %08x\n", hwnd, (UINT32)func );
-    if (!(pWnd = WIN_FindWndPtr( hwnd ))) return -1;
-    for (prop = pWnd->pProp; (prop); prop = next)
-    {
-        /* Already get the next in case the callback */
-        /* function removes the current property.    */
-        next = prop->next;
-
-        dprintf_prop( stddeb, "  Callback: handle=%08x str='%s'\n",
-                      prop->handle, prop->string );
-        if (HIWORD(prop->string))
-        {
-            LPWSTR str = STRING32_DupAnsiToUni( prop->string );
-            ret = CallEnumPropProc32( func, hwnd, str, prop->handle );
-            free( str );
-        }
-        else
-            ret = CallEnumPropProc32( func, hwnd,
-                                      (LPCWSTR)(UINT32)LOWORD(prop->string),
-                                      prop->handle );
-        if (!ret) break;
-    }
-    return ret;
+    return EnumPropsEx32W( hwnd, (PROPENUMPROCEX32W)func, 0 );
 }
 
 
@@ -324,8 +279,7 @@
 
         dprintf_prop( stddeb, "  Callback: handle=%08x str='%s'\n",
                       prop->handle, prop->string );
-        ret = CallEnumPropProcEx32( func, hwnd, prop->string,
-                                    prop->handle, lParam );
+        ret = func( hwnd, prop->string, prop->handle, lParam );
         if (!ret) break;
     }
     return ret;
@@ -355,13 +309,12 @@
         if (HIWORD(prop->string))
         {
             LPWSTR str = STRING32_DupAnsiToUni( prop->string );
-            ret = CallEnumPropProcEx32( func, hwnd, str, prop->handle, lParam);
+            ret = func( hwnd, str, prop->handle, lParam );
             free( str );
         }
         else
-            ret = CallEnumPropProcEx32( func, hwnd,
-                                        (LPCWSTR)(UINT32)LOWORD(prop->string),
-                                        prop->handle, lParam );
+            ret = func( hwnd, (LPCWSTR)(UINT32)LOWORD( prop->string ),
+                        prop->handle, lParam );
         if (!ret) break;
     }
     return ret;
diff --git a/windows/win.c b/windows/win.c
index 29b902f..845d9ac 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -28,7 +28,6 @@
 #include "color.h"
 #include "shm_main_blk.h"
 #include "dde_proc.h"
-#include "callback.h"
 #include "clipboard.h"
 #include "winproc.h"
 #include "stddebug.h"
@@ -602,7 +601,7 @@
 	    win_attr.event_mask = ExposureMask | KeyPressMask |
 	                          KeyReleaseMask | PointerMotionMask |
 	                          ButtonPressMask | ButtonReleaseMask |
-	                          FocusChangeMask;
+	                          FocusChangeMask | StructureNotifyMask;
             win_attr.override_redirect = TRUE;
 	}
         win_attr.colormap      = COLOR_GetColormap();
@@ -1687,9 +1686,7 @@
     {
         /* Make sure that the window still exists */
         if (!IsWindow((*ppWnd)->hwndSelf)) continue;
-        if (!CallEnumWindowsProc16( (FARPROC16)lpEnumFunc,
-                                    (*ppWnd)->hwndSelf, lParam ))
-            break;
+        if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
     }
     HeapFree( SystemHeap, 0, list );
     return TRUE;
@@ -1701,25 +1698,7 @@
  */
 BOOL32 EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
 {
-    WND **list, **ppWnd;
-
-    /* We have to build a list of all windows first, to avoid */
-    /* unpleasant side-effects, for instance if the callback  */
-    /* function changes the Z-order of the windows.           */
-
-    if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
-
-    /* Now call the callback function for every window */
-
-    for (ppWnd = list; *ppWnd; ppWnd++)
-    {
-        /* Make sure that the window still exists */
-        if (!IsWindow((*ppWnd)->hwndSelf)) continue;
-        if (!CallEnumWindowsProc32( lpEnumFunc, (*ppWnd)->hwndSelf, lParam ))
-            break;
-    }
-    HeapFree( SystemHeap, 0, list );
-    return TRUE;
+    return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
 }
 
 
@@ -1743,9 +1722,7 @@
         /* Make sure that the window still exists */
         if (!IsWindow((*ppWnd)->hwndSelf)) continue;
         if ((*ppWnd)->hmemTaskQ != hQueue) continue;  /* Check the queue */
-        if (!CallEnumWindowsProc16( (FARPROC16)func,
-                                    (*ppWnd)->hwndSelf, lParam ))
-            break;
+        if (!func( (*ppWnd)->hwndSelf, lParam )) break;
     }
     HeapFree( SystemHeap, 0, list );
     return TRUE;
@@ -1757,33 +1734,17 @@
  */
 BOOL32 EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
 {
-    WND **list, **ppWnd;
-    HANDLE hQueue = GetTaskQueue( (DWORD)id );
-
-    if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
-
-    /* Now call the callback function for every window */
-
-    for (ppWnd = list; *ppWnd; ppWnd++)
-    {
-        /* Make sure that the window still exists */
-        if (!IsWindow((*ppWnd)->hwndSelf)) continue;
-        if ((*ppWnd)->hmemTaskQ != hQueue) continue;  /* Check the queue */
-        if (!CallEnumWindowsProc32( func, (*ppWnd)->hwndSelf, lParam ))
-            break;
-    }
-    HeapFree( SystemHeap, 0, list );
-    return TRUE;
+    return (BOOL16)EnumTaskWindows16((HTASK16)id, (WNDENUMPROC16)func, lParam);
 }
 
 
 /**********************************************************************
- *           WIN_EnumChildWindows16
+ *           WIN_EnumChildWindows
  *
- * Helper function for EnumChildWindows16().
+ * Helper function for EnumChildWindows().
  */
-static BOOL16 WIN_EnumChildWindows16( WND **ppWnd, WNDENUMPROC16 func,
-                                      LPARAM lParam )
+static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
+                                    LPARAM lParam )
 {
     WND **childList;
     BOOL16 ret = FALSE;
@@ -1794,37 +1755,8 @@
         if (!IsWindow((*ppWnd)->hwndSelf)) continue;
         /* Build children list first */
         if (!(childList = WIN_BuildWinArray( *ppWnd ))) return FALSE;
-        if (!CallEnumWindowsProc16((FARPROC16)func,(*ppWnd)->hwndSelf,lParam))
-            return FALSE;
-        ret = WIN_EnumChildWindows16( childList, func, lParam );
-        HeapFree( SystemHeap, 0, childList );
-        if (!ret) return FALSE;
-        ppWnd++;
-    }
-    return TRUE;
-}
-
-
-/**********************************************************************
- *           WIN_EnumChildWindows32
- *
- * Helper function for EnumChildWindows32().
- */
-static BOOL32 WIN_EnumChildWindows32( WND **ppWnd, WNDENUMPROC32 func,
-                                      LPARAM lParam )
-{
-    WND **childList;
-    BOOL32 ret = FALSE;
-
-    while (*ppWnd)
-    {
-        /* Make sure that the window still exists */
-        if (!IsWindow((*ppWnd)->hwndSelf)) continue;
-        /* Build children list first */
-        if (!(childList = WIN_BuildWinArray( *ppWnd ))) return FALSE;
-        if (!CallEnumWindowsProc32( func, (*ppWnd)->hwndSelf, lParam ))
-            return FALSE;
-        ret = WIN_EnumChildWindows32( childList, func, lParam );
+        if (!func( (*ppWnd)->hwndSelf, lParam )) return FALSE;
+        ret = WIN_EnumChildWindows( childList, func, lParam );
         HeapFree( SystemHeap, 0, childList );
         if (!ret) return FALSE;
         ppWnd++;
@@ -1842,7 +1774,7 @@
 
     if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
     if (!(list = WIN_BuildWinArray( pParent ))) return FALSE;
-    WIN_EnumChildWindows16( list, func, lParam );
+    WIN_EnumChildWindows( list, func, lParam );
     HeapFree( SystemHeap, 0, list );
     return TRUE;
 }
@@ -1853,13 +1785,8 @@
  */
 BOOL32 EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func, LPARAM lParam )
 {
-    WND **list, *pParent;
-
-    if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
-    if (!(list = WIN_BuildWinArray( pParent ))) return FALSE;
-    WIN_EnumChildWindows32( list, func, lParam );
-    HeapFree( SystemHeap, 0, list );
-    return TRUE;
+    return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
+                                       lParam );
 }
 
 
diff --git a/windows/winpos.c b/windows/winpos.c
index 23ab087..9e1a9cc 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -683,7 +683,8 @@
     else
     {
         /* We can't activate a child window */
-        if (wndPtr->dwStyle & WS_CHILD) swpflags |= SWP_NOACTIVATE;
+        if (wndPtr->dwStyle & WS_CHILD)
+            swpflags |= SWP_NOACTIVATE | SWP_NOZORDER;
         SetWindowPos( hwnd, HWND_TOP, x, y, cx, cy, swpflags );
         if (!IsWindow( hwnd )) return wasVisible;
     }
diff --git a/windows/winproc.c b/windows/winproc.c
index f52a6d2..06057c0 100644
--- a/windows/winproc.c
+++ b/windows/winproc.c
@@ -1344,11 +1344,13 @@
     UINT16 msg16;
     WPARAM16 wParam16;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
-    WORD ds = wndPtr ? wndPtr->hInstance : CURRENT_DS;
+    WORD ds = CURRENT_DS;
 
     if (WINPROC_MapMsg32ATo16( msg, wParam, &msg16, &wParam16, &lParam ) == -1)
         return 0;
-    result = CallWndProc16( func, ds, hwnd, msg16, wParam16, lParam );
+    if (wndPtr) CURRENT_DS = wndPtr->hInstance;
+    result = CallWndProc16( func, hwnd, msg16, wParam16, lParam );
+    CURRENT_DS = ds;
     WINPROC_UnmapMsg32ATo16( msg16, wParam16, lParam );
     return result;
 }
@@ -1367,11 +1369,13 @@
     UINT16 msg16;
     WPARAM16 wParam16;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
+    WORD ds = CURRENT_DS;
 
     if (WINPROC_MapMsg32WTo16( msg, wParam, &msg16, &wParam16, &lParam ) == -1)
         return 0;
-    result = CallWndProc16( func, wndPtr ? wndPtr->hInstance : CURRENT_DS,
-                            hwnd, msg16, wParam16, lParam );
+    if (wndPtr) CURRENT_DS = wndPtr->hInstance;
+    result = CallWndProc16( func, hwnd, msg16, wParam16, lParam );
+    CURRENT_DS = ds;
     WINPROC_UnmapMsg32WTo16( msg16, wParam16, lParam );
     return result;
 }
@@ -1383,21 +1387,26 @@
 LRESULT CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
                           WPARAM16 wParam, LPARAM lParam )
 {
+    LRESULT result;
     WND *wndPtr;
     WINDOWPROC *proc = WINPROC_GetPtr( func );
+    WORD ds = CURRENT_DS;
 
     if (!proc)
     {
         wndPtr = WIN_FindWndPtr( hwnd );
-        return CallWndProc16( (FARPROC16)func,
-                              wndPtr ? wndPtr->hInstance : CURRENT_DS,
-                              hwnd, msg, wParam, lParam );
+        if (wndPtr) CURRENT_DS = wndPtr->hInstance;
+        result = CallWndProc16( (FARPROC16)func, hwnd, msg, wParam, lParam );
+        CURRENT_DS = ds;
+        return result;
     }
 #if testing
     wndPtr = WIN_FindWndPtr( hwnd );
-    return CallWndProc16( WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_16),
-                          wndPtr ? wndPtr->hInstance : CURRENT_DS,
-                          hwnd, msg, wParam, lParam );
+    if (wndPtr) CURRENT_DS = wndPtr->hInstance;
+    result = CallWndProc16( WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_16),
+                            hwnd, msg, wParam, lParam );
+    CURRENT_DS = ds;
+    return result;
 #endif
     
     switch(proc->type)
@@ -1405,6 +1414,7 @@
     case WIN_PROC_16:
         if (!proc->thunk.t_from32.proc) return 0;
         wndPtr = WIN_FindWndPtr( hwnd );
+        if (wndPtr) CURRENT_DS = wndPtr->hInstance;
 #ifndef WINELIB
         if ((msg == WM_CREATE) || (msg == WM_NCCREATE))
         {
@@ -1412,18 +1422,21 @@
             /* Build the CREATESTRUCT on the 16-bit stack. */
             /* This is really ugly, but some programs (notably the */
             /* "Undocumented Windows" examples) want it that way.  */
-            return CallWndProcNCCREATE16( proc->thunk.t_from32.proc,
-                      wndPtr ? wndPtr->hInstance : CURRENT_DS, cs->dwExStyle,
-                      cs->lpszClass, cs->lpszName, cs->style, cs->x, cs->y,
-                      cs->cx, cs->cy, cs->hwndParent, cs->hMenu, cs->hInstance,
-                      (LONG)cs->lpCreateParams, hwnd, msg, wParam,
-                      MAKELONG( IF1632_Saved16_sp-sizeof(CREATESTRUCT16),
-                                IF1632_Saved16_ss ) );
+            result = CallWndProcNCCREATE16( proc->thunk.t_from32.proc,
+                    cs->dwExStyle, cs->lpszClass, cs->lpszName, cs->style,
+                    cs->x, cs->y, cs->cx, cs->cy, cs->hwndParent, cs->hMenu,
+                    cs->hInstance, (LONG)cs->lpCreateParams, hwnd, msg, wParam,
+                    MAKELONG( IF1632_Saved16_sp-sizeof(CREATESTRUCT16),
+                              IF1632_Saved16_ss ) );
+            CURRENT_DS = ds;
+            return result;
         }
 #endif
-        return CallWndProc16( proc->thunk.t_from32.proc,
-                              wndPtr ? wndPtr->hInstance : CURRENT_DS,
-                              hwnd, msg, wParam, lParam );
+        result = CallWndProc16( proc->thunk.t_from32.proc,
+                                hwnd, msg, wParam, lParam );
+        CURRENT_DS = ds;
+        return result;
+
     case WIN_PROC_32A:
         if (!proc->thunk.t_from16.proc) return 0;
         return WINPROC_CallProc16To32A( hwnd, msg, wParam, lParam,