Release 961208

Sun Dec  8 14:51:57 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [configure.in]
	Added check to see if the compiler supports building a DLL when
	the --with-dll option is used.

	* [controls/listbox.c]
	Don't send LBN_SELCHANGE too often.
	Added WM_CHARTOITEM support.

	* [Make.rules.in] [library/Makefile.in]
	Build winestub.o and link it with Winelib programs.

	* [objects/text.c]
	Added support for '&&' in DrawText().

	* [tools/build.c]
	Added -o option.

Sat Dec 7 12:07:07 1996  Andrew Lewycky <plewycky@oise.utoronto.ca>

	* [win32/thread.c]
	GetCurrentThread(): return -2 (current thread pseudo-handle).
	GetCurrentThreadId(): return GetCurrentTask().

	* [objects/font.c] [if1632/gdi32.spec]
	GetTextExtentPoint32{A,W}Buggy(): for future bug-compatibility.

	* [win32/findfile.c]
	FindClose(): ignore INVALID_HANDLE_VALUE (like Win95).

	* [windows/hook.c] [include/hook.h] [if1632/user.spec]
	  [if1632/user32.spec] [windows/focus.c] [windows/message.c]
	  [windows/nonclient.c] [windows/win.c] [windows/winpos.c]
	Hooks rewritten to support Win32.

	* [misc/winsock.c]
	WINSOCK_select(): need to put sockets with errors into exceptfds.
	WINSOCK_socket(): fix error return.

	* [windows/win.c]
	SetWindowWord(): call SetParent on GWW_HWNDPARENT.

Wed Dec  4 22:03:05 1996  Andrew Taylor <andrew@riscan.com>

	* [files/dos_fs.c]
	Check if buf is NULL before copying string in GetFullPathName32A().

Wed Dec  4 21:40:59 1996  Robert Pouliot <krynos@clic.net>

        * [graphics/wing.c] [if1632/wing.spec]
	Implemented many WinG functions, but some don't seem to
	work correctly (probably due to the one not done).
	
Wed Dec  4 03:38:25 1996  Lee Jaekil <juria@puma.kaitech.re.kr>

	* [misc/main.c]
	Implemented a few more of the SystemParametersInfo() cases.

Sun Dec  1 22:30:00 1996  Alex Korobka <alex@trantor.pharm.sunysb.edu> 

	* [controls/button.c]
	Improved focus rectangle painting.

	* [windows/dialog.c] [windows/defdlg.c]
	Fixed IE3.0 problems with DWL_MSGRESULT.

Sun Dec  1 20:49:32 1996  Albrecht Kleine  <kleine@ak.sax.de>

	* [files/profile.c]
	Changed error handling in PROFILE_SetString().
diff --git a/windows/defdlg.c b/windows/defdlg.c
index 03a2d22..99e2a1f 100644
--- a/windows/defdlg.c
+++ b/windows/defdlg.c
@@ -89,18 +89,18 @@
         !(SendMessage16(hwndNew, WM_GETDLGCODE, 0, 0 ) & DLGC_UNDEFPUSHBUTTON))
         return FALSE;  /* Destination is not a push button */
     
-    if (dlgInfo->msgResult)  /* There's already a default pushbutton */
+    if (dlgInfo->idResult)  /* There's already a default pushbutton */
     {
-        HWND32 hwndOld = GetDlgItem( hwndDlg, dlgInfo->msgResult );
+        HWND32 hwndOld = GetDlgItem( hwndDlg, dlgInfo->idResult );
         if (SendMessage32A( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
             SendMessage32A( hwndOld, BM_SETSTYLE32, BS_PUSHBUTTON, TRUE );
     }
     if (hwndNew)
     {
         SendMessage32A( hwndNew, BM_SETSTYLE32, BS_DEFPUSHBUTTON, TRUE );
-        dlgInfo->msgResult = GetDlgCtrlID( hwndNew );
+        dlgInfo->idResult = GetDlgCtrlID( hwndNew );
     }
-    else dlgInfo->msgResult = 0;
+    else dlgInfo->idResult = 0;
     return TRUE;
 }
 
@@ -177,8 +177,8 @@
 
         case DM_GETDEFID:
             if (dlgInfo->fEnd) return 0;
-	    if (dlgInfo->msgResult)
-	      return MAKELONG( dlgInfo->msgResult, DC_HASDEFID );
+	    if (dlgInfo->idResult)
+	      return MAKELONG( dlgInfo->idResult, DC_HASDEFID );
 	    hwndDefId = DEFDLG_FindDefButton( hwnd );
 	    if (hwndDefId)
 	      return MAKELONG( GetDlgCtrlID( hwndDefId ), DC_HASDEFID);
@@ -223,7 +223,9 @@
                                            hwnd, msg, wParam, lParam );
 
         /* Check if window was destroyed by dialog procedure */
-        if (result || !IsWindow( hwnd )) return result;
+
+	if (!IsWindow( hwnd )) return result;
+	else if( result ) return dlgInfo->msgResult;
     }
     
     switch(msg)
@@ -267,7 +269,9 @@
                                             hwnd, msg, wParam, lParam );
 
         /* Check if window was destroyed by dialog procedure */
-        if (result || !IsWindow( hwnd )) return result;
+
+        if (!IsWindow( hwnd )) return result;
+        else if( result ) return dlgInfo->msgResult;
     }
     
     switch(msg)
@@ -310,7 +314,9 @@
                                             hwnd, msg, wParam, lParam );
 
         /* Check if window was destroyed by dialog procedure */
-        if (result || !IsWindow( hwnd )) return result;
+
+        if (!IsWindow( hwnd )) return result;
+        else if( result ) return dlgInfo->msgResult;
     }
     
     switch(msg)
diff --git a/windows/dialog.c b/windows/dialog.c
index 7f51666..e1b0946 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -293,7 +293,7 @@
                 SendMessage32A( hwndDefButton, BM_SETSTYLE32,
                                 BS_PUSHBUTTON,FALSE );
             hwndDefButton = hwndCtrl;
-            dlgInfo->msgResult = GetWindowWord( hwndCtrl, GWW_ID );
+            dlgInfo->idResult = GetWindowWord( hwndCtrl, GWW_ID );
         }
     }    
     dprintf_dialog(stddeb, " END\n" );
@@ -583,7 +583,8 @@
     dlgInfo->hMenu     = hMenu;
     dlgInfo->xBaseUnit = xUnit;
     dlgInfo->yBaseUnit = yUnit;
-    dlgInfo->msgResult = 0;  /* This is used to store the default button id */
+    dlgInfo->msgResult = 0; 
+    dlgInfo->idResult  = 0;
     dlgInfo->hDialogHeap = 0;
 
     if (dlgInfo->hUserFont)
@@ -747,7 +748,7 @@
 	}
 	if (dlgInfo->fEnd) break;
     }
-    retval = dlgInfo->msgResult;
+    retval = dlgInfo->idResult;
     EnableWindow( owner, TRUE );
     DestroyWindow( hwnd );
     return retval;
@@ -860,7 +861,7 @@
 {
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     DIALOGINFO * dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
-    dlgInfo->msgResult = retval;
+    dlgInfo->idResult = retval;
     dlgInfo->fEnd = TRUE;
     dprintf_dialog(stddeb, "EndDialog: %04x %d\n", hwnd, retval );
     return TRUE;
diff --git a/windows/event.c b/windows/event.c
index 49d325a..1143c44 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -307,6 +307,8 @@
     if( dndSelection == None )
 	dndSelection = XInternAtom( display, "DndSelection" , False );
 
+    XSetWMProtocols( display, pWnd->window, &wmDeleteWindow, 1 );
+
     if (!winContext) winContext = XUniqueContext();
     XSaveContext( display, pWnd->window, winContext, (char *)pWnd );
 }
diff --git a/windows/focus.c b/windows/focus.c
index 99654b7..7d284d0 100644
--- a/windows/focus.c
+++ b/windows/focus.c
@@ -101,8 +101,8 @@
 	if( hwnd == hwndFocus ) return hwnd;
 
 	/* call hooks */
-	if( HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM16)hwnd,
-                            (LPARAM)hwndFocus) )
+	if( HOOK_CallHooks16( WH_CBT, HCBT_SETFOCUS, (WPARAM16)hwnd,
+			      (LPARAM)hwndFocus) )
 	    return 0;
 
         /* activate hwndTop if needed. */
@@ -113,7 +113,7 @@
 	    if (!IsWindow( hwnd )) return 0;  /* Abort if window destroyed */
 	}
     }
-    else if( HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, 0, (LPARAM)hwndFocus ) )
+    else if( HOOK_CallHooks16( WH_CBT, HCBT_SETFOCUS, 0, (LPARAM)hwndFocus ) )
              return 0;
 
       /* Change focus and send messages */
diff --git a/windows/hook.c b/windows/hook.c
index ef81d3a..a64db7c 100644
--- a/windows/hook.c
+++ b/windows/hook.c
@@ -2,6 +2,7 @@
  * Windows hook functions
  *
  * Copyright 1994, 1995 Alexandre Julliard
+ *                 1996 Andrew Lewycky
  *
  * Based on investigations by Alex Korobka
  */
@@ -14,9 +15,13 @@
  */
 
 #define NO_TRANSITION_TYPES  /* This file is Win32-clean */
+#include "windows.h"
 #include "hook.h"
 #include "queue.h"
 #include "user.h"
+#include "heap.h"
+#include "struct32.h"
+#include "string32.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -26,11 +31,12 @@
 typedef struct
 {
     HANDLE16   next;               /* 00 Next hook in chain */
-    HOOKPROC16 proc WINE_PACKED;   /* 02 Hook procedure */
+    HOOKPROC32 proc WINE_PACKED;   /* 02 Hook procedure */
     INT16      id;                 /* 06 Hook id (WH_xxx) */
     HQUEUE16   ownerQueue;         /* 08 Owner queue (0 for system hook) */
     HMODULE16  ownerModule;        /* 0a Owner module */
     WORD       inHookProc;         /* 0c TRUE if in this->proc */
+    INT32      flags;
 } HOOKDATA;
 
 #pragma pack(4)
@@ -40,6 +46,743 @@
   /* This should probably reside in USER heap */
 static HANDLE16 HOOK_systemHooks[WH_NB_HOOKS] = { 0, };
 
+typedef VOID (*HOOK_MapFunc)(INT32, INT32, WPARAM32 *, LPARAM *);
+typedef VOID (*HOOK_UnMapFunc)(INT32, INT32, WPARAM32, LPARAM, WPARAM32,
+			       LPARAM);
+
+
+/***********************************************************************
+ *           Hook Mapping Functions
+ */
+
+
+/***********************************************************************
+ *           HOOK_Map16To32Common
+ */
+static void HOOK_Map16To32Common(INT32 id, INT32 code, WPARAM32 *pwParam,
+				 LPARAM *plParam)
+{
+    switch (id)
+    {
+    case WH_MSGFILTER:
+    case WH_SYSMSGFILTER:
+    case WH_GETMESSAGE:
+    case WH_JOURNALRECORD:
+        {
+            LPMSG16 lpmsg16 = PTR_SEG_TO_LIN(*plParam);
+            LPMSG32 lpmsg32 = HeapAlloc( SystemHeap, 0, sizeof(*lpmsg32) );
+	
+            STRUCT32_MSG16to32( lpmsg16, lpmsg32 );
+            *plParam = (LPARAM)lpmsg32;
+            break;
+        }
+    case WH_JOURNALPLAYBACK:
+        {
+            LPEVENTMSG16 lpem16 = PTR_SEG_TO_LIN(*plParam);
+            LPEVENTMSG32 lpem32 = HeapAlloc( SystemHeap, 0, sizeof(*lpem32) );
+
+            lpem32->message = lpem16->message;
+            lpem32->paramL = lpem16->paramL;
+            lpem32->paramH = lpem16->paramH;
+            lpem32->time = lpem16->time;
+            lpem32->hwnd = 0;	/* FIXME */
+
+            *plParam = (LPARAM)lpem32;
+            break;
+        }
+    case WH_CBT:
+	switch (code)
+	{
+        case HCBT_ACTIVATE:
+            {
+                LPCBTACTIVATESTRUCT16 lpcas16 = PTR_SEG_TO_LIN(*plParam);
+                LPCBTACTIVATESTRUCT32 lpcas32 = HeapAlloc( SystemHeap, 0,
+                                                           sizeof(*lpcas32) );
+                lpcas32->fMouse = lpcas16->fMouse;
+                lpcas32->hWndActive = lpcas16->hWndActive;
+                *plParam = (LPARAM)lpcas32;
+                break;
+            }
+        case HCBT_CLICKSKIPPED:
+            {
+                LPMOUSEHOOKSTRUCT16 lpms16 = PTR_SEG_TO_LIN(*plParam);
+                LPMOUSEHOOKSTRUCT32 lpms32 = HeapAlloc( SystemHeap, 0,
+                                                        sizeof(*lpms32) );
+
+                STRUCT32_POINT16to32( &lpms16->pt, &lpms32->pt );
+
+                /* wHitTestCode may be negative, so convince compiler to do
+                   correct sign extension. Yay. :| */
+                lpms32->wHitTestCode = (INT32)((INT16)lpms16->wHitTestCode);
+
+                lpms32->dwExtraInfo = lpms16->dwExtraInfo;
+                lpms32->hwnd = lpms16->hwnd;
+                *plParam = (LPARAM)lpms32;
+                break;
+            }
+        case HCBT_MOVESIZE:
+            {
+                LPRECT16 lprect16 = PTR_SEG_TO_LIN(*plParam);
+                LPRECT32 lprect32 = HeapAlloc( SystemHeap, 0,
+                                               sizeof(*lprect32) );
+
+                STRUCT32_RECT16to32( lprect16, lprect32 );
+                *plParam = (LPARAM)lprect32;
+                break;
+            }
+	}
+	break;
+    case WH_MOUSE:
+        {
+            LPMOUSEHOOKSTRUCT16 lpms16 = PTR_SEG_TO_LIN(*plParam);
+            LPMOUSEHOOKSTRUCT32 lpms32 = HeapAlloc( SystemHeap, 0,
+                                                    sizeof(*lpms32) );
+
+            STRUCT32_POINT16to32( &lpms16->pt, &lpms32->pt );
+
+            /* wHitTestCode may be negative, so convince compiler to do
+               correct sign extension. Yay. :| */
+            lpms32->wHitTestCode = (INT32)((INT16)lpms16->wHitTestCode);
+            lpms32->dwExtraInfo = lpms16->dwExtraInfo;
+            lpms32->hwnd = lpms16->hwnd;
+            *plParam = (LPARAM)lpms32;
+            break;
+        }
+    case WH_DEBUG:
+        {
+            LPDEBUGHOOKINFO16 lpdh16 = PTR_SEG_TO_LIN(*plParam);
+            LPDEBUGHOOKINFO32 lpdh32 = HeapAlloc( SystemHeap, 0,
+                                                  sizeof(*lpdh32) );
+
+            lpdh32->idThread = 0;               /* FIXME */
+            lpdh32->idThreadInstaller = 0;	/* FIXME */
+            lpdh32->lParam = lpdh16->lParam;	/* FIXME Check for sign ext */
+            lpdh32->wParam = lpdh16->wParam;
+            lpdh32->code = lpdh16->code;
+	  
+            /* do sign extension if it was WH_MSGFILTER */
+            if (*pwParam == 0xffff) *pwParam = WH_MSGFILTER;
+
+            *plParam = (LPARAM)lpdh32;
+            break;
+        }
+    case WH_SHELL:
+    case WH_KEYBOARD:
+	break;
+
+    case WH_CALLWNDPROC:
+    case WH_HARDWARE:
+	break;	/* NYI */
+
+    default:
+	fprintf(stderr, "Unknown hook id: %d\n", id);
+	return;
+    }
+}
+
+
+/***********************************************************************
+ *           HOOK_Map16To32A
+ */
+static void HOOK_Map16To32A(INT32 id, INT32 code, WPARAM32 *pwParam,
+			    LPARAM *plParam)
+{
+    if (id == WH_CBT && code == HCBT_CREATEWND)
+    {
+	LPCBT_CREATEWND16 lpcbtcw16 = PTR_SEG_TO_LIN(*plParam);
+	LPCBT_CREATEWND32A lpcbtcw32 = HeapAlloc( SystemHeap, 0,
+						  sizeof(*lpcbtcw32) );
+	lpcbtcw32->lpcs = HeapAlloc( SystemHeap, 0,
+				     sizeof(*lpcbtcw32->lpcs) );
+
+	STRUCT32_CREATESTRUCT16to32A( lpcbtcw16->lpcs, lpcbtcw32->lpcs );
+
+	if (HIWORD(lpcbtcw16->lpcs->lpszName))
+            lpcbtcw32->lpcs->lpszName
+                = PTR_SEG_TO_LIN(lpcbtcw16->lpcs->lpszName);
+	else
+            lpcbtcw32->lpcs->lpszName = (LPSTR)lpcbtcw16->lpcs->lpszName;
+
+	if (HIWORD(lpcbtcw16->lpcs->lpszClass))
+            lpcbtcw32->lpcs->lpszClass
+                = PTR_SEG_TO_LIN(lpcbtcw16->lpcs->lpszClass);
+	else
+            lpcbtcw32->lpcs->lpszClass = (LPSTR)lpcbtcw16->lpcs->lpszClass;
+
+	lpcbtcw32->hwndInsertAfter = lpcbtcw16->hwndInsertAfter;
+
+	*plParam = (LPARAM)lpcbtcw32;
+    }
+    else
+        HOOK_Map16To32Common( id, code, pwParam, plParam );
+}
+
+
+/***********************************************************************
+ *           HOOK_Map16To32W
+ */
+static void HOOK_Map16To32W(INT32 id, INT32 code, WPARAM32 *pwParam,
+			    LPARAM *plParam)
+{
+    if (id == WH_CBT && code == HCBT_CREATEWND)
+    {
+	LPCBT_CREATEWND16 lpcbtcw16 = PTR_SEG_TO_LIN(*plParam);
+	LPCREATESTRUCT16 lpcs16 = PTR_SEG_TO_LIN(lpcbtcw16->lpcs);
+	LPCBT_CREATEWND32W lpcbtcw32 = HeapAlloc( SystemHeap, 0,
+						  sizeof(*lpcbtcw32) );
+	lpcbtcw32->lpcs = HeapAlloc( SystemHeap, 0,
+				     sizeof(*lpcbtcw32->lpcs) );
+
+	STRUCT32_CREATESTRUCT16to32A( lpcs16,
+				      (LPCREATESTRUCT32A)lpcbtcw32->lpcs );
+
+	if (HIWORD(lpcs16->lpszName))
+            lpcbtcw32->lpcs->lpszName = 
+                STRING32_DupAnsiToUni( PTR_SEG_TO_LIN(lpcs16->lpszName) );
+	else
+            lpcbtcw32->lpcs->lpszName = (LPWSTR)lpcs16->lpszName;
+
+	if (HIWORD(lpcs16->lpszClass))
+            lpcbtcw32->lpcs->lpszClass =
+                STRING32_DupAnsiToUni( PTR_SEG_TO_LIN(lpcs16->lpszClass) );
+	else
+            lpcbtcw32->lpcs->lpszClass = (LPWSTR)lpcs16->lpszClass;
+
+	lpcbtcw32->hwndInsertAfter = lpcbtcw16->hwndInsertAfter;
+
+	*plParam = (LPARAM)lpcbtcw32;
+    }
+    else HOOK_Map16To32Common( id, code, pwParam, plParam );
+}
+
+
+/***********************************************************************
+ *           HOOK_UnMap16To32Common
+ */
+static void HOOK_UnMap16To32Common(INT32 id, INT32 code, WPARAM32 wParamOrig,
+				   LPARAM lParamOrig, WPARAM32 wParam,
+				   LPARAM lParam)
+{
+    switch (id)
+    {
+      case WH_MSGFILTER:
+      case WH_SYSMSGFILTER:
+      case WH_JOURNALRECORD:
+      case WH_JOURNALPLAYBACK:
+      {
+	  HeapFree( SystemHeap, 0, (LPVOID)lParam );
+	  break;
+      }
+
+      case WH_GETMESSAGE:
+      {
+	  LPMSG16 lpmsg16 = PTR_SEG_TO_LIN(lParamOrig);
+	  STRUCT32_MSG32to16( (LPMSG32)lParam, lpmsg16 );
+	  HeapFree( SystemHeap, 0, (LPVOID)lParam );
+	  break;
+      }
+
+      case WH_MOUSE:
+      case WH_DEBUG:
+	HeapFree( SystemHeap, 0, (LPVOID)lParam );
+	break;
+
+	/* I don't think any of these need to be copied */
+      case WH_CBT:
+	switch (code)
+	{
+	  case HCBT_ACTIVATE:
+	  case HCBT_CLICKSKIPPED:
+	  case HCBT_MOVESIZE:
+	    HeapFree( SystemHeap, 0, (LPVOID)lParam);
+	    break;
+	}
+	break;
+
+      case WH_SHELL:
+      case WH_KEYBOARD:
+	break;
+
+      case WH_CALLWNDPROC:
+      case WH_HARDWARE:
+	fprintf(stderr, "Can't map hook id: %d\n", id);
+	break;
+
+      default:
+	fprintf(stderr, "Unknown hook id: %d\n", id);
+	return;
+    }
+}
+
+
+/***********************************************************************
+ *           HOOK_UnMap16To32A
+ */
+static void HOOK_UnMap16To32A(INT32 id, INT32 code, WPARAM32 wParamOrig,
+			      LPARAM lParamOrig, WPARAM32 wParam,
+			      LPARAM lParam)
+{
+    if (id == WH_CBT && code == HCBT_CREATEWND)
+    {
+	LPCBT_CREATEWND32A lpcbtcw32 = (LPCBT_CREATEWND32A)lParam;
+	HeapFree( SystemHeap, 0, lpcbtcw32->lpcs );
+	HeapFree( SystemHeap, 0, lpcbtcw32 );
+    }
+    else
+      HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam,
+			      lParam);
+    return;
+}
+
+
+/***********************************************************************
+ *           HOOK_UnMap16To32W
+ */
+static void HOOK_UnMap16To32W(INT32 id, INT32 code, WPARAM32 wParamOrig,
+			      LPARAM lParamOrig, WPARAM32 wParam,
+			      LPARAM lParam)
+{
+    if (id == WH_CBT && code == HCBT_CREATEWND)
+    {
+	LPCBT_CREATEWND32W lpcbtcw32 = (LPCBT_CREATEWND32W)lParam;
+	if (HIWORD(lpcbtcw32->lpcs->lpszName))
+	  free( (LPWSTR)lpcbtcw32->lpcs->lpszName );
+	if (HIWORD(lpcbtcw32->lpcs->lpszClass))
+	  free( (LPWSTR)lpcbtcw32->lpcs->lpszClass );
+	HeapFree( SystemHeap, 0, lpcbtcw32->lpcs );
+	HeapFree( SystemHeap, 0, lpcbtcw32 );
+    }
+    else
+      HOOK_UnMap16To32Common(id, code, wParamOrig, lParamOrig, wParam, lParam);
+}
+
+
+/***********************************************************************
+ *           HOOK_Map32To16Common
+ */
+static void HOOK_Map32To16Common(INT32 id, INT32 code, WPARAM32 *pwParam,
+				 LPARAM *plParam)
+{
+    switch (id)
+    {
+      case WH_MSGFILTER:
+      case WH_SYSMSGFILTER:
+      case WH_GETMESSAGE:
+      case WH_JOURNALRECORD:
+      {
+	  LPMSG32 lpmsg32 = (LPMSG32)*plParam;
+	  LPMSG16 lpmsg16 = SEGPTR_NEW( MSG16 );
+
+	  STRUCT32_MSG32to16( lpmsg32, lpmsg16 );
+
+	  *plParam = (LPARAM)SEGPTR_GET( lpmsg16 );
+	  break;
+      }
+
+      case WH_JOURNALPLAYBACK:
+      {
+	  LPEVENTMSG32 lpem32 = (LPEVENTMSG32)*plParam;
+	  LPEVENTMSG16 lpem16 = SEGPTR_NEW( EVENTMSG16 );
+
+	  lpem16->message = lpem32->message;
+	  lpem16->paramL  = lpem32->paramL;
+	  lpem16->paramH  = lpem32->paramH;
+	  lpem16->time    = lpem32->time;
+
+	  *plParam = (LPARAM)SEGPTR_GET( lpem16 );
+	  break;
+      }
+
+      case WH_CBT:
+	switch (code)
+	{
+	  case HCBT_ACTIVATE:
+	  {
+	      LPCBTACTIVATESTRUCT32 lpcas32 = (LPCBTACTIVATESTRUCT32)*plParam;
+	      LPCBTACTIVATESTRUCT16 lpcas16 =SEGPTR_NEW( CBTACTIVATESTRUCT16 );
+
+	      lpcas16->fMouse     = lpcas32->fMouse;
+	      lpcas16->hWndActive = lpcas32->hWndActive
+;
+	      *plParam = (LPARAM)SEGPTR_GET( lpcas16 );
+	      break;
+	  }
+	      
+	  case HCBT_CLICKSKIPPED:
+	  {
+	      LPMOUSEHOOKSTRUCT32 lpms32 = (LPMOUSEHOOKSTRUCT32)*plParam;
+	      LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
+
+	      STRUCT32_POINT32to16( &lpms32->pt, &lpms16->pt );
+
+	      lpms16->hwnd         = lpms32->hwnd;
+	      lpms16->wHitTestCode = lpms32->wHitTestCode;
+	      lpms16->dwExtraInfo  = lpms32->dwExtraInfo;
+
+	      *plParam = (LPARAM)SEGPTR_GET( lpms16 );
+	      break;
+	  }
+
+	  case HCBT_MOVESIZE:
+	  {
+	      LPRECT32 lprect32 = (LPRECT32)*plParam;
+	      LPRECT16 lprect16 = SEGPTR_NEW( RECT16 );
+
+	      STRUCT32_RECT32to16( lprect32, lprect16 );
+
+	      *plParam = (LPARAM)SEGPTR_GET( lprect16 );
+	      break;
+	  }
+	}
+	break;
+
+      case WH_MOUSE:
+      {
+	  LPMOUSEHOOKSTRUCT32 lpms32 = (LPMOUSEHOOKSTRUCT32)*plParam;
+	  LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
+
+	  STRUCT32_POINT32to16( &lpms32->pt, &lpms16->pt );
+
+	  lpms16->hwnd = lpms32->hwnd;
+	  lpms16->wHitTestCode = lpms32->wHitTestCode;
+	  lpms16->dwExtraInfo = lpms32->dwExtraInfo;
+
+	  *plParam = (LPARAM)SEGPTR_GET( lpms16 );
+	  break;
+      }
+
+      case WH_DEBUG:
+      {
+	  LPDEBUGHOOKINFO32 lpdh32 = (LPDEBUGHOOKINFO32)*plParam;
+	  LPDEBUGHOOKINFO16 lpdh16 = SEGPTR_NEW( DEBUGHOOKINFO16 );
+
+	  lpdh16->hModuleHook = 0;	/* FIXME */
+	  lpdh16->reserved    = 0;
+	  lpdh16->lParam      = lpdh32->lParam;
+	  lpdh16->wParam      = lpdh32->wParam;
+	  lpdh16->code        = lpdh32->code;
+	  
+	  *plParam = (LPARAM)SEGPTR_GET( lpdh16 );
+	  break;
+      }
+
+      case WH_SHELL:
+      case WH_KEYBOARD:
+	break;
+
+      case WH_CALLWNDPROC:
+      case WH_HARDWARE:
+	fprintf(stderr, "Can't map hook id: %d\n", id);
+	break;
+
+      default:
+	fprintf(stderr, "Unknown hook id: %d\n", id);
+	return;
+    }
+}
+
+
+/***********************************************************************
+ *           HOOK_Map32ATo16
+ */
+static void HOOK_Map32ATo16(INT32 id, INT32 code, WPARAM32 *pwParam,
+			    LPARAM *plParam)
+{
+    if (id == WH_CBT && code == HCBT_CREATEWND)
+    {
+	LPCBT_CREATEWND32A lpcbtcw32 = (LPCBT_CREATEWND32A)*plParam;
+	LPCBT_CREATEWND16 lpcbtcw16 = SEGPTR_NEW( CBT_CREATEWND16 );
+	LPCREATESTRUCT16 lpcs16 = SEGPTR_NEW( CREATESTRUCT16 );
+
+	lpcbtcw16->lpcs = (LPCREATESTRUCT16)SEGPTR_GET( lpcs16 );
+	STRUCT32_CREATESTRUCT32Ato16( lpcbtcw32->lpcs, lpcs16 );
+
+	if (HIWORD(lpcbtcw32->lpcs->lpszName))
+	  lpcs16->lpszName =
+	    SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszName ) );
+	else
+	  lpcs16->lpszName = (SEGPTR)lpcbtcw32->lpcs->lpszName;
+
+	if (HIWORD(lpcbtcw32->lpcs->lpszClass))
+	  lpcs16->lpszClass =
+	    SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszClass ) );
+	else
+	  lpcs16->lpszClass = (SEGPTR)lpcbtcw32->lpcs->lpszClass;
+
+	lpcbtcw16->hwndInsertAfter = lpcbtcw32->hwndInsertAfter;
+
+	*plParam = (LPARAM)SEGPTR_GET( lpcbtcw16 );
+    }
+    else HOOK_Map32To16Common(id, code, pwParam, plParam);
+}
+
+
+/***********************************************************************
+ *           HOOK_Map32WTo16
+ */
+static void HOOK_Map32WTo16(INT32 id, INT32 code, WPARAM32 *pwParam,
+			    LPARAM *plParam)
+{
+    if (id == WH_CBT && code == HCBT_CREATEWND)
+    {
+	LPCBT_CREATEWND32W lpcbtcw32 = (LPCBT_CREATEWND32W)*plParam;
+	LPCBT_CREATEWND16 lpcbtcw16 = SEGPTR_NEW( CBT_CREATEWND16 );
+	LPCREATESTRUCT16 lpcs16 = SEGPTR_NEW( CREATESTRUCT16 );
+
+	lpcbtcw16->lpcs = (LPCREATESTRUCT16)SEGPTR_GET( lpcs16 );
+	STRUCT32_CREATESTRUCT32Ato16( (LPCREATESTRUCT32A)lpcbtcw32->lpcs,
+				      lpcs16 );
+
+	if (HIWORD(lpcbtcw32->lpcs->lpszName))
+	{
+	    LPSTR str = SEGPTR_ALLOC( lstrlen32W(lpcbtcw32->lpcs->lpszName) );
+	    STRING32_UniToAnsi( str, lpcbtcw32->lpcs->lpszName );
+	    lpcs16->lpszName = SEGPTR_GET( str );
+	}
+	else
+	  lpcs16->lpszName = (SEGPTR)lpcbtcw32->lpcs->lpszName;
+
+	if (HIWORD(lpcbtcw32->lpcs->lpszClass))
+	{
+	    LPSTR str = SEGPTR_ALLOC( lstrlen32W(lpcbtcw32->lpcs->lpszClass) );
+	    STRING32_UniToAnsi( str, lpcbtcw32->lpcs->lpszClass );
+	    lpcs16->lpszClass = SEGPTR_GET( str );
+	}
+	else
+	  lpcs16->lpszClass = (SEGPTR)lpcbtcw32->lpcs->lpszClass;
+
+	lpcbtcw16->hwndInsertAfter = lpcbtcw32->hwndInsertAfter;
+
+	*plParam = (LPARAM)SEGPTR_GET( lpcbtcw16 );
+    }
+    else HOOK_Map32To16Common(id, code, pwParam, plParam);
+}
+
+
+/***********************************************************************
+ *           HOOK_UnMap32To16Common
+ */
+static void HOOK_UnMap32To16Common(INT32 id, INT32 code, WPARAM32 wParamOrig,
+				   LPARAM lParamOrig, WPARAM32 wParam,
+				   LPARAM lParam)
+{
+    switch (id)
+    {
+      case WH_MSGFILTER:
+      case WH_SYSMSGFILTER:
+      case WH_JOURNALRECORD:
+      case WH_JOURNALPLAYBACK:
+      case WH_MOUSE:
+      case WH_DEBUG:
+	SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
+	break;
+
+      case WH_GETMESSAGE:
+      {
+	  LPMSG32 lpmsg32 = (LPMSG32)lParamOrig;
+
+	  STRUCT32_MSG16to32( (LPMSG16)PTR_SEG_TO_LIN(lParam), lpmsg32 );
+	  SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
+	  break;
+      }
+
+      case WH_CBT:
+	switch (code)
+	{
+	  case HCBT_ACTIVATE:
+	  case HCBT_CLICKSKIPPED:
+	  case HCBT_MOVESIZE:
+	    SEGPTR_FREE( (LPVOID)lParam );
+	    break;
+	}
+	break;
+
+      case WH_SHELL:
+      case WH_KEYBOARD:
+	break;
+
+      case WH_CALLWNDPROC:
+      case WH_HARDWARE:
+	fprintf(stderr, "Can't map hook id: %d\n", id);
+	break;
+
+      default:
+	fprintf(stderr, "Unknown hook id: %d\n", id);
+	return;
+    }
+}
+
+
+/***********************************************************************
+ *           HOOK_UnMap32ATo16
+ */
+static void HOOK_UnMap32ATo16(INT32 id, INT32 code, WPARAM32 wParamOrig,
+			      LPARAM lParamOrig, WPARAM32 wParam,
+			      LPARAM lParam)
+{
+    if (id == WH_CBT && code == HCBT_CREATEWND)
+    {
+	LPCBT_CREATEWND16 lpcbtcw16 = PTR_SEG_TO_LIN(lParam);
+	LPCREATESTRUCT16 lpcs16 = PTR_SEG_TO_LIN(lpcbtcw16->lpcs);
+
+	if (HIWORD(lpcs16->lpszName))
+	  SEGPTR_FREE( PTR_SEG_TO_LIN(lpcs16->lpszName) );
+
+	if (HIWORD(lpcs16->lpszClass))
+	  SEGPTR_FREE( PTR_SEG_TO_LIN(lpcs16->lpszClass) );
+
+	SEGPTR_FREE( lpcs16 );
+	SEGPTR_FREE( lpcbtcw16 );
+    }
+    else
+      return HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
+				     lParam );
+    return;
+}
+
+
+/***********************************************************************
+ *           HOOK_UnMap32WTo16
+ */
+static void HOOK_UnMap32WTo16(INT32 id, INT32 code, WPARAM32 wParamOrig,
+			      LPARAM lParamOrig, WPARAM32 wParam,
+			      LPARAM lParam)
+{
+    HOOK_UnMap32ATo16( id, code, wParamOrig, lParamOrig, wParam, lParam );
+}
+
+
+/***********************************************************************
+ *           HOOK_Map32ATo32W
+ */
+static void HOOK_Map32ATo32W(INT32 id, INT32 code, WPARAM32 *pwParam,
+			     LPARAM *plParam)
+{
+    if (id == WH_CBT && code == HCBT_CREATEWND)
+    {
+	LPCBT_CREATEWND32A lpcbtcwA = (LPCBT_CREATEWND32A)*plParam;
+	LPCBT_CREATEWND32W lpcbtcwW = HeapAlloc( SystemHeap, 0,
+						 sizeof(*lpcbtcwW) );
+	lpcbtcwW->lpcs = HeapAlloc( SystemHeap, 0, sizeof(*lpcbtcwW->lpcs) );
+
+	lpcbtcwW->hwndInsertAfter = lpcbtcwA->hwndInsertAfter;
+	*lpcbtcwW->lpcs = *(LPCREATESTRUCT32W)lpcbtcwA->lpcs;
+
+	if (HIWORD(lpcbtcwA->lpcs->lpszName))
+	{
+	    lpcbtcwW->lpcs->lpszName =
+	      STRING32_DupAnsiToUni( lpcbtcwA->lpcs->lpszName );
+	}
+	else
+	  lpcbtcwW->lpcs->lpszName = (LPWSTR)lpcbtcwA->lpcs->lpszName;
+
+	if (HIWORD(lpcbtcwA->lpcs->lpszClass))
+	{
+	    lpcbtcwW->lpcs->lpszClass =
+	      STRING32_DupAnsiToUni( lpcbtcwA->lpcs->lpszClass);
+	}
+	else
+	  lpcbtcwW->lpcs->lpszClass = (LPCWSTR)lpcbtcwA->lpcs->lpszClass;
+    }
+    return;
+}
+
+
+/***********************************************************************
+ *           HOOK_UnMap32ATo32W
+ */
+static void HOOK_UnMap32ATo32W(INT32 id, INT32 code, WPARAM32 wParamOrig,
+			       LPARAM lParamOrig, WPARAM32 wParam,
+			       LPARAM lParam)
+{
+    if (id == WH_CBT && code == HCBT_CREATEWND)
+    {
+	LPCBT_CREATEWND32W lpcbtcwW = (LPCBT_CREATEWND32W)lParam;
+	if (HIWORD(lpcbtcwW->lpcs->lpszName))
+            free( (LPWSTR)lpcbtcwW->lpcs->lpszName );
+	if (HIWORD(lpcbtcwW->lpcs->lpszClass))
+            free( (LPWSTR)lpcbtcwW->lpcs->lpszClass );
+	HeapFree( SystemHeap, 0, lpcbtcwW->lpcs );
+	HeapFree( SystemHeap, 0, lpcbtcwW );
+    }
+    return;
+}
+
+
+/***********************************************************************
+ *           HOOK_Map32WTo32A
+ */
+static void HOOK_Map32WTo32A(INT32 id, INT32 code, WPARAM32 *pwParam,
+			     LPARAM *plParam)
+{
+    if (id == WH_CBT && code == HCBT_CREATEWND)
+    {
+	LPCBT_CREATEWND32W lpcbtcwW = (LPCBT_CREATEWND32W)*plParam;
+	LPCBT_CREATEWND32A lpcbtcwA = HeapAlloc( SystemHeap, 0,
+						 sizeof(*lpcbtcwA) );
+	lpcbtcwA->lpcs = HeapAlloc( SystemHeap, 0, sizeof(*lpcbtcwA->lpcs) );
+
+	lpcbtcwA->hwndInsertAfter = lpcbtcwW->hwndInsertAfter;
+	*lpcbtcwA->lpcs = *(LPCREATESTRUCT32A)lpcbtcwW->lpcs;
+
+	if (HIWORD(lpcbtcwW->lpcs->lpszName))
+	  lpcbtcwA->lpcs->lpszName =
+	    STRING32_DupUniToAnsi( lpcbtcwW->lpcs->lpszName );
+	else
+	  lpcbtcwA->lpcs->lpszName = (LPSTR)lpcbtcwW->lpcs->lpszName;
+
+	if (HIWORD(lpcbtcwW->lpcs->lpszClass))
+	  lpcbtcwA->lpcs->lpszClass =
+	    STRING32_DupUniToAnsi( lpcbtcwW->lpcs->lpszClass);
+	else
+	  lpcbtcwA->lpcs->lpszClass = (LPSTR)lpcbtcwW->lpcs->lpszClass;
+    }
+    return;
+}
+
+
+/***********************************************************************
+ *           HOOK_UnMap32WTo32A
+ */
+static void HOOK_UnMap32WTo32A(INT32 id, INT32 code, WPARAM32 wParamOrig,
+			       LPARAM lParamOrig, WPARAM32 wParam,
+			       LPARAM lParam)
+{
+    if (id == WH_CBT && code == HCBT_CREATEWND)
+    {
+	LPCBT_CREATEWND32A lpcbtcwA = (LPCBT_CREATEWND32A)lParam;
+	if (HIWORD(lpcbtcwA->lpcs->lpszName))
+	  free( (LPSTR)lpcbtcwA->lpcs->lpszName );
+	if (HIWORD(lpcbtcwA->lpcs->lpszClass))
+	  free( (LPSTR)lpcbtcwA->lpcs->lpszClass );
+	HeapFree( SystemHeap, 0, lpcbtcwA->lpcs );
+	HeapFree( SystemHeap, 0, lpcbtcwA );
+    }
+    return;
+}
+
+
+/***********************************************************************
+ *           Map Function Tables
+ */
+static const HOOK_MapFunc HOOK_MapFuncs[3][3] = 
+{
+    { NULL,            HOOK_Map16To32A,  HOOK_Map16To32W },
+    { HOOK_Map32ATo16, NULL,             HOOK_Map32ATo32W },
+    { HOOK_Map32WTo16, HOOK_Map32WTo32A, NULL }
+};
+
+static const HOOK_UnMapFunc HOOK_UnMapFuncs[3][3] = 
+{
+    { NULL,              HOOK_UnMap16To32A,  HOOK_UnMap16To32W },
+    { HOOK_UnMap32ATo16, NULL,               HOOK_UnMap32ATo32W },
+    { HOOK_UnMap32WTo16, HOOK_UnMap32WTo32A, NULL }
+};
+
+
+/***********************************************************************
+ *           Internal Functions
+ */
 
 /***********************************************************************
  *           HOOK_GetNextHook
@@ -49,9 +792,11 @@
 static HANDLE16 HOOK_GetNextHook( HANDLE16 hook )
 {
     HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR( hook );
+
     if (!data || !hook) return 0;
     if (data->next) return data->next;
     if (!data->ownerQueue) return 0;  /* Already system hook */
+
     /* Now start enumerating the system hooks */
     return HOOK_systemHooks[data->id - WH_MINHOOK];
 }
@@ -62,7 +807,7 @@
  *
  * Get the first hook for a given type.
  */
-HANDLE16 HOOK_GetHook( INT16 id , HQUEUE16 hQueue )
+static HANDLE16 HOOK_GetHook( INT16 id, HQUEUE16 hQueue )
 {
     MESSAGEQUEUE *queue;
     HANDLE16 hook = 0;
@@ -75,24 +820,12 @@
 
 
 /***********************************************************************
- *           HOOK_GetProc16
- */
-HOOKPROC16 HOOK_GetProc16( HHOOK hhook )
-{
-    HOOKDATA *data;
-    if (HIWORD(hhook) != HOOK_MAGIC) return NULL;
-    if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) ))) return NULL;
-    return data->proc;
-}
-
-
-/***********************************************************************
  *           HOOK_SetHook
  *
  * Install a given hook.
  */
-static HANDLE16 HOOK_SetHook( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst,
-                              HTASK16 hTask )
+static HANDLE16 HOOK_SetHook( INT16 id, LPVOID proc, INT32 type,
+			      HINSTANCE16 hInst, HTASK16 hTask )
 {
     HOOKDATA *data;
     HANDLE16 handle;
@@ -104,6 +837,8 @@
     dprintf_hook( stddeb, "Setting hook %d: %08x %04x %04x\n",
                   id, (UINT32)proc, hInst, hTask );
 
+    if (id == WH_JOURNALPLAYBACK) EnableHardwareInput(FALSE);
+
     if (hTask)  /* Task-specific hook */
     {
 	if ((id == WH_JOURNALRECORD) || (id == WH_JOURNALPLAYBACK) ||
@@ -111,19 +846,6 @@
         if (!(hQueue = GetTaskQueue( hTask ))) return 0;
     }
 
-    if (id == WH_DEBUG)
-    {
-        fprintf( stdnimp,"WH_DEBUG is broken in 16-bit Windows.\n");
-        return 0;
-    }
-    else if (id == WH_CBT || id == WH_SHELL)
-    {
-	fprintf( stdnimp, "Half-implemented hook set: (%s,%08lx,%04x,%04x)!\n",
-                 (id==WH_CBT)?"WH_CBT":"WH_SHELL", (DWORD)proc, hInst, hTask );
-    }
-
-    if (id == WH_JOURNALPLAYBACK) EnableHardwareInput(FALSE);
-     
     /* Create the hook structure */
 
     if (!(handle = USER_HEAP_ALLOC( sizeof(HOOKDATA) ))) return 0;
@@ -133,6 +855,7 @@
     data->ownerQueue  = hQueue;
     data->ownerModule = hInst;
     data->inHookProc  = 0;
+    data->flags       = type;
 
     /* Insert it in the correct linked list */
 
@@ -170,7 +893,7 @@
     {
         /* Mark it for deletion later on */
         dprintf_hook( stddeb, "Hook still running, deletion delayed\n" );
-        data->proc = (HOOKPROC16)0;
+        data->proc = (HOOKPROC32)0;
         return TRUE;
     }
 
@@ -197,57 +920,144 @@
 
 
 /***********************************************************************
+ *           HOOK_FindValidHook
+ */
+static HANDLE16 HOOK_FindValidHook( HANDLE16 hook )
+{
+    HOOKDATA *data;
+
+    for (;;)
+    {
+	if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return 0;
+	if (data->proc) return hook;
+	hook = data->next;
+    }
+}
+
+
+/***********************************************************************
  *           HOOK_CallHook
  *
  * Call a hook procedure.
  */
-static LRESULT HOOK_CallHook( HANDLE16 hook, INT16 code,
-                              WPARAM16 wParam, LPARAM lParam )
+static LRESULT HOOK_CallHook( HANDLE16 hook, INT32 fromtype, INT32 code,
+                              WPARAM32 wParam, LPARAM lParam )
 {
-    HOOKDATA *data;
     MESSAGEQUEUE *queue;
     HANDLE16 prevHook;
+    HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
     LRESULT ret;
 
-    /* Find the first hook with a valid proc */
+    WPARAM32 wParamOrig = wParam;
+    LPARAM lParamOrig = lParam;
+    HOOK_MapFunc MapFunc;
+    HOOK_UnMapFunc UnMapFunc;
 
-    for (;;)
-    {
-        if (!hook) return 0;
-        if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return 0;
-        if (data->proc) break;
-        hook = data->next;
-    }
+    MapFunc = HOOK_MapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
+    UnMapFunc = HOOK_UnMapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
+
+    if (MapFunc)
+      MapFunc( data->id, code, &wParam, &lParam );
 
     /* Now call it */
 
     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return 0;
     prevHook = queue->hCurHook;
     queue->hCurHook = hook;
-    data->inHookProc = 1;
+    data->inHookProc = TRUE;
 
-    dprintf_hook( stddeb, "Calling hook %04x: proc=%p %d %04lx %08lx\n",
-                  hook, data->proc, code, (DWORD)wParam, lParam );
-    ret = data->proc( code, wParam, lParam );
+    dprintf_hook( stddeb, "Calling hook %04x: %d %08x %08lx\n",
+                  hook, code, wParam, lParam );
+
+    ret = data->proc(code, wParam, lParam);
+
     dprintf_hook( stddeb, "Ret hook %04x = %08lx\n", hook, ret );
 
-    data->inHookProc = 0;
+    data->inHookProc = FALSE;
     queue->hCurHook = prevHook;
+
+    if (UnMapFunc)
+      UnMapFunc( data->id, code, wParamOrig, lParamOrig, wParam, lParam );
+
     if (!data->proc) HOOK_RemoveHook( hook );
+
     return ret;
 }
 
+/***********************************************************************
+ *           Exported Functions & APIs
+ */
+
+/***********************************************************************
+ *           HOOK_GetProc16
+ *
+ * Don't call this unless you are the if1632/thunk.c.
+ */
+HOOKPROC16 HOOK_GetProc16( HHOOK hhook )
+{
+    HOOKDATA *data;
+    if (HIWORD(hhook) != HOOK_MAGIC) return NULL;
+    if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) ))) return NULL;
+    if (data->flags & HOOK_WIN32) return NULL;
+    return (HOOKPROC16)data->proc;
+}
+
 
 /***********************************************************************
- *           HOOK_CallHooks
+ *           HOOK_IsHooked
+ *
+ * Replacement for calling HOOK_GetHook from other modules.
+ */
+BOOL32 HOOK_IsHooked( INT16 id )
+{
+    return HOOK_GetHook( id, GetTaskQueue(0) ) != 0;
+}
+
+
+/***********************************************************************
+ *           HOOK_CallHooks16
  *
  * Call a hook chain.
  */
-LRESULT HOOK_CallHooks( INT16 id, INT16 code, WPARAM16 wParam, LPARAM lParam )
+LRESULT HOOK_CallHooks16( INT16 id, INT16 code, WPARAM16 wParam,
+                          LPARAM lParam )
 {
-    HANDLE16 hook = HOOK_GetHook( id , GetTaskQueue(0) );
-    if (!hook) return 0;
-    return HOOK_CallHook( hook, code, wParam, lParam );
+    HANDLE16 hook; 
+
+    if (!(hook = HOOK_GetHook( id , GetTaskQueue(0) ))) return 0;
+    if (!(hook = HOOK_FindValidHook(hook))) return 0;
+    return HOOK_CallHook( hook, HOOK_WIN16, code, wParam, lParam );
+}
+
+/***********************************************************************
+ *           HOOK_CallHooks32A
+ *
+ * Call a hook chain.
+ */
+LRESULT HOOK_CallHooks32A( INT32 id, INT32 code, WPARAM32 wParam,
+                           LPARAM lParam )
+{
+    HANDLE16 hook; 
+
+    if (!(hook = HOOK_GetHook( id , GetTaskQueue(0) ))) return 0;
+    if (!(hook = HOOK_FindValidHook(hook))) return 0;
+    return HOOK_CallHook( hook, HOOK_WIN32, code, wParam, lParam );
+}
+
+/***********************************************************************
+ *           HOOK_CallHooks32W
+ *
+ * Call a hook chain.
+ */
+LRESULT HOOK_CallHooks32W( INT32 id, INT32 code, WPARAM32 wParam,
+                           LPARAM lParam )
+{
+    HANDLE16 hook; 
+
+    if (!(hook = HOOK_GetHook( id , GetTaskQueue(0) ))) return 0;
+    if (!(hook = HOOK_FindValidHook(hook))) return 0;
+    return HOOK_CallHook( hook, HOOK_WIN32 | HOOK_UNICODE, code, wParam,
+			  lParam );
 }
 
 
@@ -342,19 +1152,133 @@
  */
 FARPROC16 SetWindowsHook16( INT16 id, HOOKPROC16 proc )
 {
-    HTASK16 	hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
-    HANDLE16 	handle = HOOK_SetHook( id, proc, 0, hTask );
+    HANDLE16 handle;
+    HINSTANCE16 hInst = __winelib ? 0 : FarGetOwner( HIWORD(proc) );
 
+    /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
+    HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
+
+    if (id == WH_DEBUG)
+    {
+	fprintf( stdnimp, "WH_DEBUG is broken in 16-bit Windows.\n");
+	return 0;
+    }
+
+    handle = HOOK_SetHook( id, proc, HOOK_WIN16, hInst, hTask );
     return (handle) ? (FARPROC16)MAKELONG( handle, HOOK_MAGIC ) : NULL;
 }
 
 
 /***********************************************************************
+ *           SetWindowsHook32A   (USER32.524)
+ *
+ * FIXME: I don't know if this is correct
+ */
+HHOOK SetWindowsHook32A( INT32 id, HOOKPROC32 proc )
+{
+    HINSTANCE16 hInst = __winelib ? 0 : FarGetOwner( HIWORD(proc) );
+
+    /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
+    HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
+
+    HANDLE16 handle = HOOK_SetHook( id, proc, HOOK_WIN32, hInst, hTask );
+    return (handle) ? (HHOOK)MAKELONG( handle, HOOK_MAGIC ) : 0;
+}
+
+
+/***********************************************************************
+ *           SetWindowsHook32W   (USER32.527)
+ *
+ * FIXME: I don't know if this is correct
+ */
+HHOOK SetWindowsHook32W( INT32 id, HOOKPROC32 proc )
+{
+    HINSTANCE16 hInst = __winelib ? 0 : FarGetOwner( HIWORD(proc) );
+
+    /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
+    HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
+
+    HANDLE16 handle = HOOK_SetHook( id, proc, HOOK_WIN32 | HOOK_UNICODE,
+				    hInst, hTask );
+    return (handle) ? (HHOOK)MAKELONG( handle, HOOK_MAGIC ) : 0;
+}
+
+
+/***********************************************************************
+ *           SetWindowsHookEx16   (USER.291)
+ */
+HHOOK SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst,
+			  HTASK16 hTask )
+{
+    HANDLE16 handle = HOOK_SetHook( id, proc, HOOK_WIN16, hInst, hTask );
+    return (handle) ? (HHOOK)MAKELONG( handle, HOOK_MAGIC ) : (HHOOK)NULL;
+}
+
+
+/***********************************************************************
+ *           SetWindowsHookEx32A   (USER32.525)
+ */
+HHOOK SetWindowsHookEx32A( INT32 id, HOOKPROC32 proc, HINSTANCE32 hInst,
+			   DWORD dwThreadID )
+{
+    HANDLE16 handle;
+    HTASK16 hTask;
+
+    if (dwThreadID == GetCurrentThreadId())
+      hTask = GetCurrentTask();
+    else
+      hTask = LOWORD(dwThreadID);
+
+    handle = HOOK_SetHook( id, proc, HOOK_WIN32, hInst, hTask );
+    return (handle) ? (HHOOK)MAKELONG( handle, HOOK_MAGIC ) : (HHOOK)NULL;
+}
+
+
+/***********************************************************************
+ *           SetWindowsHookEx32W   (USER32.526)
+ */
+HHOOK SetWindowsHookEx32W( INT32 id, HOOKPROC32 proc, HINSTANCE32 hInst,
+			   DWORD dwThreadID )
+{
+    HANDLE16 handle;
+    HTASK16 hTask;
+
+    if (dwThreadID == GetCurrentThreadId())
+      hTask = GetCurrentTask();
+    else
+      hTask = LOWORD(dwThreadID);
+
+    handle = HOOK_SetHook( id, proc, HOOK_WIN32 | HOOK_UNICODE, hInst, hTask );
+    return (handle) ? (HHOOK)MAKELONG( handle, HOOK_MAGIC ) : (HHOOK)NULL;
+}
+
+
+/***********************************************************************
  *           UnhookWindowsHook16   (USER.234)
  */
 BOOL16 UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
 {
-    HANDLE16 hook = HOOK_GetHook( id, GetTaskQueue(0) );
+    HANDLE16 hook = HOOK_GetHook( id , GetTaskQueue(0) );
+
+    dprintf_hook( stddeb, "UnhookWindowsHook: %d %08lx\n", id, (DWORD)proc );
+
+    while (hook)
+    {
+        HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
+        if (data->proc == (HOOKPROC32)proc) break;
+        hook = HOOK_GetNextHook( hook );
+    }
+    if (!hook) return FALSE;
+    return HOOK_RemoveHook( hook );
+}
+
+
+/***********************************************************************
+ *           UnhookWindowsHook32   (USER32.556)
+ */
+BOOL32 UnhookWindowsHook32( INT32 id, HOOKPROC32 proc )
+{
+    HANDLE16 hook = HOOK_GetHook( id , GetTaskQueue(0) );
 
     dprintf_hook( stddeb, "UnhookWindowsHook: %d %08lx\n", id, (DWORD)proc );
 
@@ -370,45 +1294,7 @@
 
 
 /***********************************************************************
- *           DefHookProc   (USER.235)
- */
-LRESULT DefHookProc( INT16 code, WPARAM16 wParam, LPARAM lParam, HHOOK *hhook )
-{
-    /* Note: the *hhook parameter is never used, since we rely on the
-     * current hook value from the task queue to find the next hook. */
-    MESSAGEQUEUE *queue;
-    HANDLE16 next;
-
-    if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return 0;
-    if (!(next = HOOK_GetNextHook( queue->hCurHook ))) return 0;
-    return HOOK_CallHook( next, code, wParam, lParam );
-}
-
-
-/***********************************************************************
- *           CallMsgFilter   (USER.123)
- */
-BOOL16 CallMsgFilter( SEGPTR msg, INT16 code )
-{
-    if (GetSysModalWindow16()) return FALSE;
-    if (HOOK_CallHooks( WH_SYSMSGFILTER, code, 0, (LPARAM)msg )) return TRUE;
-    return HOOK_CallHooks( WH_MSGFILTER, code, 0, (LPARAM)msg );
-}
-
-
-/***********************************************************************
- *           SetWindowsHookEx16   (USER.291)
- */
-HHOOK SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst,
-                          HTASK16 hTask )
-{
-    HANDLE16 handle = HOOK_SetHook( id, proc, hInst, hTask );
-    return (handle) ? MAKELONG( handle, HOOK_MAGIC ) : NULL;
-}
-
-
-/***********************************************************************
- *           UnhookWindowsHookEx16   (USER.292)
+ *           UnhookWindowHookEx16   (USER.292)
  */
 BOOL16 UnhookWindowsHookEx16( HHOOK hhook )
 {
@@ -418,12 +1304,106 @@
 
 
 /***********************************************************************
- *           CallNextHookEx   (USER.293)
+ *           UnhookWindowHookEx32   (USER32.557)
  */
-LRESULT CallNextHookEx(HHOOK hhook, INT16 code, WPARAM16 wParam, LPARAM lParam)
+BOOL32 UnhookWindowsHookEx32( HHOOK hhook )
+{
+    return UnhookWindowsHookEx16( hhook );
+}
+
+
+/***********************************************************************
+ *           CallNextHookEx16     (USER.293)
+ *
+ * I wouldn't have separated this into 16 and 32 bit versions, but I
+ * need a way to figure out if I need to do a mapping or not.
+ */
+LRESULT CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wParam,
+			  LPARAM lParam )
 {
     HANDLE16 next;
+
     if (HIWORD(hhook) != HOOK_MAGIC) return 0;  /* Not a new format hook */
     if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
-    return HOOK_CallHook( next, code, wParam, lParam );
+
+    return HOOK_CallHook( next, HOOK_WIN16, code, wParam, lParam );
+}
+
+
+/***********************************************************************
+ *           CallNextHookEx32    (USER32.16)
+ *
+ * There aren't ANSI and UNICODE versions of this.
+ */
+LRESULT CallNextHookEx32( HHOOK hhook, INT32 code, WPARAM32 wParam,
+			  LPARAM lParam )
+{
+    HANDLE16 next;
+    INT32 fromtype;	/* figure out Ansi/Unicode */
+    HOOKDATA *oldhook;
+
+    if (HIWORD(hhook) != HOOK_MAGIC) return 0;  /* Not a new format hook */
+    if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
+
+    oldhook = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) );
+    fromtype = oldhook->flags & HOOK_MAPTYPE;
+
+    if (!(fromtype & HOOK_WIN32))
+      fprintf(stderr, "CallNextHookEx32: called from 16bit hook!\n");
+
+    return HOOK_CallHook( next, fromtype, code, wParam, lParam );
+}
+
+
+/***********************************************************************
+ *           DefHookProc16   (USER.235)
+ */
+LRESULT DefHookProc16( INT16 code, WPARAM16 wParam, LPARAM lParam,
+		       HHOOK *hhook )
+{
+    /* Note: the *hhook parameter is never used, since we rely on the
+     * current hook value from the task queue to find the next hook. */
+    MESSAGEQUEUE *queue;
+
+    if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return 0;
+    return CallNextHookEx16( queue->hCurHook, code, wParam, lParam );
+}
+
+
+/***********************************************************************
+ *           CallMsgFilter16   (USER.123)
+ */
+BOOL16 CallMsgFilter16( SEGPTR msg, INT16 code )
+{
+    if (GetSysModalWindow16()) return FALSE;
+    if (HOOK_CallHooks16( WH_SYSMSGFILTER, code, 0, (LPARAM)msg )) return TRUE;
+    return HOOK_CallHooks16( WH_MSGFILTER, code, 0, (LPARAM)msg );
+}
+
+
+/***********************************************************************
+ *           CallMsgFilter32A   (USER32.14)
+ */
+/*
+ * FIXME: There are ANSI and UNICODE versions of this, plus an unspecified
+ * version, plus USER (the 16bit one) has a CallMsgFilter32 function.
+ */
+BOOL32 CallMsgFilter32A( LPMSG32 msg, INT32 code )
+{
+    if (GetSysModalWindow16()) return FALSE;	/* ??? */
+    if (HOOK_CallHooks32A( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
+      return TRUE;
+    return HOOK_CallHooks32A( WH_MSGFILTER, code, 0, (LPARAM)msg );
+}
+
+
+/***********************************************************************
+ *           CallMsgFilter32W   (USER32.15)
+ */
+BOOL32 CallMsgFilter32W( LPMSG32 msg, INT32 code )
+{
+    if (GetSysModalWindow16()) return FALSE;	/* ??? */
+    if (HOOK_CallHooks32W( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
+      return TRUE;
+    return HOOK_CallHooks32W( WH_MSGFILTER, code, 0, (LPARAM)msg );
 }
diff --git a/windows/message.c b/windows/message.c
index 77ee2f9..05f8ad5 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -91,15 +91,15 @@
 	msg->lParam = MAKELONG( pt.x, pt.y );
         /* No need to further process the message */
 
-        if (!HOOK_GetHook( WH_MOUSE, GetTaskQueue(0)) ||
+        if (!HOOK_IsHooked( WH_MOUSE ) ||
             !(hook = SEGPTR_NEW(MOUSEHOOKSTRUCT16)))
             return SYSQ_MSG_ACCEPT;
         hook->pt           = msg->pt;
         hook->hwnd         = msg->hwnd;
         hook->wHitTestCode = HTCLIENT;
         hook->dwExtraInfo  = 0;
-        ret = !HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
-                               msg->message, (LPARAM)SEGPTR_GET(hook));
+        ret = !HOOK_CallHooks16( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
+                                 msg->message, (LPARAM)SEGPTR_GET(hook));
         SEGPTR_FREE(hook);
         return ret ? SYSQ_MSG_ACCEPT : SYSQ_MSG_SKIP ;
     }
@@ -195,7 +195,7 @@
 
     /* Call the WH_MOUSE hook */
 
-    if (!HOOK_GetHook( WH_MOUSE, GetTaskQueue(0)) ||
+    if (!HOOK_IsHooked( WH_MOUSE ) ||
         !(hook = SEGPTR_NEW(MOUSEHOOKSTRUCT16)))
         return SYSQ_MSG_ACCEPT;
 
@@ -203,8 +203,8 @@
     hook->hwnd         = msg->hwnd;
     hook->wHitTestCode = hittest;
     hook->dwExtraInfo  = 0;
-    ret = !HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
-                           msg->message, (LPARAM)SEGPTR_GET(hook) );
+    ret = !HOOK_CallHooks16( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
+                             msg->message, (LPARAM)SEGPTR_GET(hook) );
     SEGPTR_FREE(hook);
     return ret ? SYSQ_MSG_ACCEPT : SYSQ_MSG_SKIP;
 }
@@ -245,9 +245,9 @@
         if (queue) QUEUE_SetWakeBit( queue, QS_KEY );
         return SYSQ_MSG_ABANDON;
     }
-    return (HOOK_CallHooks( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
-                            msg->wParam, msg->lParam ))
-            ? SYSQ_MSG_SKIP : SYSQ_MSG_ACCEPT;
+    return (HOOK_CallHooks16( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
+			      msg->wParam, msg->lParam )
+            ? SYSQ_MSG_SKIP : SYSQ_MSG_ACCEPT);
 }
 
 
@@ -268,16 +268,16 @@
         event->paramH = msg->lParam & 0x7FFF;  
         if (HIWORD(msg->lParam) & 0x0100)
             event->paramH |= 0x8000;               /* special_key - bit */
-        HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0,
-                        (LPARAM)SEGPTR_GET(event) );
+        HOOK_CallHooks16( WH_JOURNALRECORD, HC_ACTION, 0,
+                          (LPARAM)SEGPTR_GET(event) );
     }
     else if ((msg->message >= WM_MOUSEFIRST) && (msg->message <= WM_MOUSELAST))
     {
         event->paramL = LOWORD(msg->lParam);       /* X pos */
         event->paramH = HIWORD(msg->lParam);       /* Y pos */ 
         ClientToScreen16( msg->hwnd, (LPPOINT16)&event->paramL );
-        HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0,
-                        (LPARAM)SEGPTR_GET(event) );
+        HOOK_CallHooks16( WH_JOURNALRECORD, HC_ACTION, 0,
+                          (LPARAM)SEGPTR_GET(event) );
     }
     else if ((msg->message >= WM_NCMOUSEFIRST) &&
              (msg->message <= WM_NCMOUSELAST))
@@ -285,8 +285,8 @@
         event->paramL = LOWORD(msg->lParam);       /* X pos */
         event->paramH = HIWORD(msg->lParam);       /* Y pos */ 
         event->message += WM_MOUSEMOVE-WM_NCMOUSEMOVE;/* give no info about NC area */
-        HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0,
-                        (LPARAM)SEGPTR_GET(event) );
+        HOOK_CallHooks16( WH_JOURNALRECORD, HC_ACTION, 0,
+                          (LPARAM)SEGPTR_GET(event) );
     }
     SEGPTR_FREE(event);
 }
@@ -302,10 +302,11 @@
  long wtime,lParam;
  WORD keyDown,i,wParam,result=0;
 
- if ( HOOK_GetHook(WH_JOURNALPLAYBACK, 0) )
+ if ( HOOK_IsHooked( WH_JOURNALPLAYBACK ) )
  {
   tmpMsg = SEGPTR_NEW(EVENTMSG16);
-  wtime=HOOK_CallHooks( WH_JOURNALPLAYBACK, HC_GETNEXT, 0, (LPARAM)SEGPTR_GET(tmpMsg));
+  wtime=HOOK_CallHooks16( WH_JOURNALPLAYBACK, HC_GETNEXT, 0,
+			  (LPARAM)SEGPTR_GET(tmpMsg));
   /*  dprintf_msg(stddeb,"Playback wait time =%ld\n",wtime); */
   if (wtime<=0)
   {
@@ -360,7 +361,8 @@
                      tmpMsg->paramL, tmpMsg->paramH, tmpMsg->time, 0 );
     }
    }
-   HOOK_CallHooks( WH_JOURNALPLAYBACK, HC_SKIP, 0, (LPARAM)SEGPTR_GET(tmpMsg));
+   HOOK_CallHooks16( WH_JOURNALPLAYBACK, HC_SKIP, 0,
+		     (LPARAM)SEGPTR_GET(tmpMsg));
   }
   else
     result= QS_MOUSE | QS_KEY;
@@ -412,9 +414,9 @@
                 hook->wMessage = msg->message;
                 hook->wParam   = msg->wParam;
                 hook->lParam   = msg->lParam;
-                ret = HOOK_CallHooks( WH_HARDWARE,
-                                      remove ? HC_ACTION : HC_NOREMOVE,
-                                      0, (LPARAM)SEGPTR_GET(hook) );
+                ret = HOOK_CallHooks16( WH_HARDWARE,
+                                        remove ? HC_ACTION : HC_NOREMOVE,
+                                        0, (LPARAM)SEGPTR_GET(hook) );
                 SEGPTR_FREE(hook);
                 status = ret ? SYSQ_MSG_SKIP : SYSQ_MSG_ACCEPT;
             }
@@ -434,7 +436,7 @@
             ((msg->message < first) || (msg->message > last))) continue;
         if (remove)
         {
-            if (HOOK_GetHook( WH_JOURNALRECORD, GetTaskQueue(0) ))
+            if (HOOK_IsHooked( WH_JOURNALRECORD ))
                 MSG_JournalRecordMsg( msg );
             QUEUE_RemoveMsg( sysMsgQueue, pos );
         }
@@ -776,18 +778,17 @@
 
         /* Call message filters */
 
-        if (HOOK_GetHook( WH_SYSMSGFILTER, GetTaskQueue(0) ) ||
-            HOOK_GetHook( WH_MSGFILTER, GetTaskQueue(0) ))
+        if (HOOK_IsHooked( WH_SYSMSGFILTER ) || HOOK_IsHooked( WH_MSGFILTER ))
         {
             MSG16 *pmsg = SEGPTR_NEW(MSG16);
             if (pmsg)
             {
                 BOOL32 ret;
                 *pmsg = *msg;
-                ret = ((BOOL16)HOOK_CallHooks( WH_SYSMSGFILTER, code, 0,
-                                               (LPARAM)SEGPTR_GET(pmsg) ) ||
-                       (BOOL16)HOOK_CallHooks( WH_MSGFILTER, code, 0,
-                                               (LPARAM)SEGPTR_GET(pmsg) ));
+                ret = ((BOOL16)HOOK_CallHooks16( WH_SYSMSGFILTER, code, 0,
+                                                 (LPARAM)SEGPTR_GET(pmsg) ) ||
+                       (BOOL16)HOOK_CallHooks16( WH_MSGFILTER, code, 0,
+                                                 (LPARAM)SEGPTR_GET(pmsg) ));
                 SEGPTR_FREE(pmsg);
                 if (ret)
                 {
@@ -826,7 +827,7 @@
 
     dprintf_msg(stddeb,"message %04x, hwnd %04x, filter(%04x - %04x)\n", lpmsg->message,
 		     				                 hwnd, first, last );
-    HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, 0, (LPARAM)msg );
+    HOOK_CallHooks16( WH_GETMESSAGE, HC_ACTION, 0, (LPARAM)msg );
     return (lpmsg->message != WM_QUIT);
 }
 
@@ -924,30 +925,30 @@
         return TRUE;
     }
 
-    if (HOOK_GetHook( WH_CALLWNDPROC, GetTaskQueue(0) ))
-    { 
-        struct msgstruct
-        {
-            LPARAM   lParam;
-            WPARAM16 wParam;
-            UINT16   wMsg;
-            HWND16   hWnd;
-        } *pmsg;
-        
-        if ((pmsg = SEGPTR_NEW(struct msgstruct)))
-        {
-            pmsg->hWnd   = hwnd;
-            pmsg->wMsg   = msg;
-            pmsg->wParam = wParam;
-            pmsg->lParam = lParam;
-            HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 1,
-                            (LPARAM)SEGPTR_GET(pmsg) );
-            hwnd   = pmsg->hWnd;
-            msg    = pmsg->wMsg;
-            wParam = pmsg->wParam;
-            lParam = pmsg->lParam;
-            SEGPTR_FREE( pmsg );
-        }
+    if (HOOK_IsHooked( WH_CALLWNDPROC ))
+    {
+	struct msgstruct
+	{
+	    LPARAM   lParam;
+	    WPARAM16 wParam;
+	    UINT16   wMsg;
+	    HWND16   hWnd;
+	} *pmsg;
+
+	if ((pmsg = SEGPTR_NEW(struct msgstruct)))
+	{
+	    pmsg->hWnd   = hwnd;
+	    pmsg->wMsg   = msg;
+	    pmsg->wParam = wParam;
+	    pmsg->lParam = lParam;
+	    HOOK_CallHooks16( WH_CALLWNDPROC, HC_ACTION, 1,
+			      (LPARAM)SEGPTR_GET(pmsg) );
+	    hwnd   = pmsg->hWnd;
+	    msg    = pmsg->wMsg;
+	    wParam = pmsg->wParam;
+	    lParam = pmsg->lParam;
+	    SEGPTR_FREE( pmsg );
+	}
     }
 
     if (!(wndPtr = WIN_FindWndPtr( hwnd )))
@@ -1134,7 +1135,7 @@
     {
 	if (msg->lParam)
         {
-/*            HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
+/*            HOOK_CallHooks16( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
 	    return CallWindowProc16( (WNDPROC16)msg->lParam, msg->hwnd,
                                    msg->message, msg->wParam, GetTickCount() );
         }
@@ -1145,7 +1146,7 @@
     if (!wndPtr->winproc) return 0;
     painting = (msg->message == WM_PAINT);
     if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
-/*    HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
+/*    HOOK_CallHooks16( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
 
     SPY_EnterMessage( SPY_DISPATCHMESSAGE16, msg->hwnd, msg->message,
                       msg->wParam, msg->lParam );
diff --git a/windows/nonclient.c b/windows/nonclient.c
index d7f70cb..423cb4f 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -1149,14 +1149,14 @@
 	if (rootWindow == DefaultRootWindow(display)) XUngrabServer( display );
     }
 
-    if (HOOK_GetHook( WH_CBT, GetTaskQueue(0) ))
+    if (HOOK_IsHooked( WH_CBT ))
     {
        RECT16* pr = SEGPTR_NEW(RECT16);
        if( pr )
        {
 	 *pr = sizingRect;
-	  if( HOOK_CallHooks( WH_CBT, HCBT_MOVESIZE, hwnd,
-			             (LPARAM)SEGPTR_GET(pr)) )
+	  if( HOOK_CallHooks16( WH_CBT, HCBT_MOVESIZE, hwnd,
+			        (LPARAM)SEGPTR_GET(pr)) )
 	      sizingRect = wndPtr->rectWindow;
 	  else
 	      sizingRect = *pr;
diff --git a/windows/win.c b/windows/win.c
index 2b48de3..56cfa04 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -579,36 +579,20 @@
 
     hwndLinkAfter = (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
 
-    if (HOOK_GetHook( WH_CBT, GetTaskQueue(0) ))
+    if (HOOK_IsHooked( WH_CBT ))
     {
-        CBT_CREATEWND16* cbtc;
+	CBT_CREATEWND32A cbtc;
 
-        if ((cbtc = SEGPTR_NEW(CBT_CREATEWND16)))
-        {
-            /* Dummy message params to use WINPROC_MapMsg functions */
-            UINT16 msg;
-            WPARAM16 wparam;
-            LPARAM lparam;
-
-            /* Map the CREATESTRUCT to 16-bit format */
-            lparam = (LPARAM)cs;
-            if (unicode)
-                WINPROC_MapMsg32WTo16( WM_CREATE, 0, &msg, &wparam, &lparam );
-            else
-                WINPROC_MapMsg32ATo16( WM_CREATE, 0, &msg, &wparam, &lparam );
-            cbtc->lpcs = (CREATESTRUCT16 *)lparam;
-            cbtc->hwndInsertAfter = hwndLinkAfter;
-            wmcreate = !HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, hwnd,
-                                        (LPARAM)SEGPTR_GET(cbtc) );
-            WINPROC_UnmapMsg32ATo16( WM_CREATE, 0, lparam );
-            SEGPTR_FREE(cbtc);
-            if (!wmcreate)
-            {
-                dprintf_win(stddeb,"CreateWindowEx: CBT-hook returned 0\n" );
-                USER_HEAP_FREE( hwnd );
-                return 0;
-            }
-        }
+	cbtc.lpcs = cs;
+	cbtc.hwndInsertAfter = hwndLinkAfter;
+	wmcreate = !HOOK_CallHooks32A( WH_CBT, HCBT_CREATEWND, hwnd,
+				       (LPARAM)&cbtc );
+	if (!wmcreate)
+	{
+	    dprintf_win(stddeb, "CreateWindowEx: CBT-hook returned 0\n");
+	    USER_HEAP_FREE( hwnd );
+	    return 0;
+	}
     }
 
     /* Set the window procedure */
@@ -817,7 +801,7 @@
     /* Call WH_SHELL hook */
 
     if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
-        HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
+        HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
 
     dprintf_win(stddeb, "CreateWindowEx: returning %04x\n", hwnd);
     return hwnd;
@@ -1019,12 +1003,12 @@
 
       /* Call hooks */
 
-    if( HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
+    if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
         return FALSE;
 
     if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
     {
-        HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
+        HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
         /* FIXME: clean up palette - see "Internals" p.352 */
     }
 
@@ -1406,6 +1390,7 @@
     {
 	case GWW_ID:        ptr = (WORD *)&wndPtr->wIDmenu; break;
 	case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
+	case GWW_HWNDPARENT: return SetParent( hwnd, newval );
 	default:
             fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
             return 0;
diff --git a/windows/winpos.c b/windows/winpos.c
index 81a727e..3142e14 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -595,7 +595,7 @@
             swpflags |= SWP_FRAMECHANGED;
             if (!(wndPtr->dwStyle & WS_MINIMIZE))
             {
-		if( HOOK_CallHooks( WH_CBT, HCBT_MINMAX, hwnd, cmd) )
+		if( HOOK_CallHooks16( WH_CBT, HCBT_MINMAX, hwnd, cmd) )
 		    return 0;
 
                 if (wndPtr->dwStyle & WS_MAXIMIZE)
@@ -623,7 +623,7 @@
             swpflags |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
             if (!(wndPtr->dwStyle & WS_MAXIMIZE))
             {
-		if( HOOK_CallHooks( WH_CBT, HCBT_MINMAX, hwnd, cmd) )
+		if( HOOK_CallHooks16( WH_CBT, HCBT_MINMAX, hwnd, cmd) )
 		    return 0;
 
                   /* Store the current position and find the maximized size */
@@ -669,7 +669,7 @@
 
             if (wndPtr->dwStyle & WS_MINIMIZE)
             {
-		if( HOOK_CallHooks( WH_CBT, HCBT_MINMAX, hwnd, cmd) )
+		if( HOOK_CallHooks16( WH_CBT, HCBT_MINMAX, hwnd, cmd) )
 		    return 0;
 
                 if( !SendMessage16( hwnd, WM_QUERYOPEN, 0, 0L) )
@@ -702,7 +702,7 @@
             }
             else if (wndPtr->dwStyle & WS_MAXIMIZE)
             {
-		if( HOOK_CallHooks( WH_CBT, HCBT_MINMAX, hwnd, cmd) )
+		if( HOOK_CallHooks16( WH_CBT, HCBT_MINMAX, hwnd, cmd) )
 		    return 0;
 
                 wndPtr->ptMaxPos.x = wndPtr->rectWindow.left;
@@ -962,8 +962,8 @@
         LRESULT wRet;
         cbtStruct->fMouse     = fMouse;
         cbtStruct->hWndActive = hwndActive;
-        wRet = HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
-                               (LPARAM)SEGPTR_GET(cbtStruct) );
+        wRet = HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
+                                 (LPARAM)SEGPTR_GET(cbtStruct) );
         SEGPTR_FREE(cbtStruct);
         if (wRet) return wRet;
     }