diff --git a/dlls/shell32/shell.c b/dlls/shell32/shell.c
index 50743bd1d7aa9ddbdf0aa49a518c35a17e86d92d..a02d4d9d84856f1c510af6587fdbe30fcf72fedd 100644
--- a/dlls/shell32/shell.c
+++ b/dlls/shell32/shell.c
@@ -1154,30 +1154,34 @@ LRESULT WINAPI ShellHookProc16(INT16 code, WPARAM16 wParam, LPARAM lParam)
  *				RegisterShellHook	[SHELL.102]
  */
 BOOL WINAPI RegisterShellHook16(HWND16 hWnd, UINT16 uAction)
-{ TRACE_(shell)("%04x [%u]\n", hWnd, uAction );
+{ 
+    TRACE_(shell)("%04x [%u]\n", hWnd, uAction );
 
     switch( uAction )
-  { case 2:  /* register hWnd as a shell window */
-	     if( !SHELL_hHook )
-      { HMODULE16 hShell = GetModuleHandle16( "SHELL" );
-        SHELL_hHook = SetWindowsHookEx16( WH_SHELL, ShellHookProc16, hShell, 0 );
-		if( SHELL_hHook )
-        { uMsgWndCreated = RegisterWindowMessageA( lpstrMsgWndCreated );
-		    uMsgWndDestroyed = RegisterWindowMessageA( lpstrMsgWndDestroyed );
-		    uMsgShellActivate = RegisterWindowMessageA( lpstrMsgShellActivate );
-		} 
-        else 
-          WARN_(shell)("-- unable to install ShellHookProc()!\n");
-	     }
-
-      if( SHELL_hHook )
-        return ((SHELL_hWnd = hWnd) != 0);
-	     break;
-
-	default:
-    WARN_(shell)("-- unknown code %i\n", uAction );
-	     /* just in case */
-	     SHELL_hWnd = 0;
+    { 
+    case 2:  /* register hWnd as a shell window */
+        if( !SHELL_hHook )
+        { 
+            HMODULE16 hShell = GetModuleHandle16( "SHELL" );
+            HOOKPROC16 hookProc = (HOOKPROC16)NE_GetEntryPoint( hShell, 103 );
+            SHELL_hHook = SetWindowsHookEx16( WH_SHELL, hookProc, hShell, 0 );
+            if ( SHELL_hHook )
+            { 
+                uMsgWndCreated = RegisterWindowMessageA( lpstrMsgWndCreated );
+                uMsgWndDestroyed = RegisterWindowMessageA( lpstrMsgWndDestroyed );
+                uMsgShellActivate = RegisterWindowMessageA( lpstrMsgShellActivate );
+            } 
+            else 
+                WARN_(shell)("-- unable to install ShellHookProc()!\n");
+        }
+
+        if ( SHELL_hHook )
+            return ((SHELL_hWnd = hWnd) != 0);
+        break;
+
+    default:
+        WARN_(shell)("-- unknown code %i\n", uAction );
+        SHELL_hWnd = 0; /* just in case */
     }
     return FALSE;
 }
diff --git a/if1632/user.spec b/if1632/user.spec
index c49074bcf839bcf6ae75c65b1703b465315790ea..e4721fc3c7d1cb4720cd5196c978453757dae6be 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -122,7 +122,7 @@ file	user.exe
 117 pascal16 WindowFromDC(word) WindowFromDC16
 119 pascal   GetMessagePos() GetMessagePos
 120 pascal   GetMessageTime() GetMessageTime
-121 pascal   SetWindowsHook(s_word segptr) THUNK_SetWindowsHook16
+121 pascal   SetWindowsHook(s_word segptr) SetWindowsHook16
 122 pascal   CallWindowProc(segptr word word word long) CallWindowProc16
 123 pascal16 CallMsgFilter(segptr s_word) CallMsgFilter16
 124 pascal16 UpdateWindow(word) UpdateWindow16
@@ -236,7 +236,7 @@ file	user.exe
 231 pascal16 GetSystemDebugState() GetSystemDebugState16
 232 pascal16 SetWindowPos(word word word word word word word) SetWindowPos16
 233 pascal16 SetParent(word word) SetParent16
-234 pascal16 UnhookWindowsHook(s_word segptr) THUNK_UnhookWindowsHook16
+234 pascal16 UnhookWindowsHook(s_word segptr) UnhookWindowsHook16
 235 pascal   DefHookProc(s_word word long ptr) DefHookProc16
 236 pascal16 GetCapture() GetCapture16
 237 pascal16 GetUpdateRgn(word word word) GetUpdateRgn16
@@ -296,8 +296,8 @@ file	user.exe
 288 pascal   GetMessageExtraInfo() GetMessageExtraInfo
 289 register keybd_event() WIN16_keybd_event
 290 pascal16 RedrawWindow(word ptr word word) RedrawWindow16
-291 pascal   SetWindowsHookEx(s_word segptr word word) THUNK_SetWindowsHookEx16
-292 pascal16 UnhookWindowsHookEx(segptr) THUNK_UnhookWindowsHookEx16
+291 pascal   SetWindowsHookEx(s_word segptr word word) SetWindowsHookEx16
+292 pascal16 UnhookWindowsHookEx(segptr) UnhookWindowsHookEx16
 293 pascal   CallNextHookEx(segptr s_word word long) CallNextHookEx16
 294 pascal16 LockWindowUpdate(word) LockWindowUpdate16
 299 register mouse_event() WIN16_mouse_event
diff --git a/include/hook.h b/include/hook.h
index 32382b93cc67fc9856ce05ddede7754df6fde7db..0db34ef7789af565ef1d8ca51d2f7b59ad88b4ca 100644
--- a/include/hook.h
+++ b/include/hook.h
@@ -18,7 +18,6 @@
 /* hook type mask */
 #define HOOK_MAPTYPE (HOOK_WIN16 | HOOK_WIN32A | HOOK_WIN32W)
 
-extern HOOKPROC16 HOOK_GetProc16( HHOOK hhook );
 extern BOOL HOOK_IsHooked( INT16 id );
 extern LRESULT HOOK_CallHooks16( INT16 id, INT16 code, WPARAM16 wParam,
 				 LPARAM lParam );
@@ -29,6 +28,5 @@ extern LRESULT HOOK_CallHooksW( INT id, INT code, WPARAM wParam,
 extern void HOOK_FreeModuleHooks( HMODULE16 hModule );
 extern void HOOK_FreeQueueHooks( HQUEUE16 hQueue );
 extern void HOOK_ResetQueueHooks( HQUEUE16 hQueue );
-extern HOOKPROC HOOK_GetProc( HHOOK hook );
 
 #endif  /* __WINE_HOOK_H */
diff --git a/windows/.cvsignore b/windows/.cvsignore
index f3c7a7c5da68804a1bdf391127ba34aed33c3cca..f9bbb55716b3a4045359c38f007dab8d6e2849b5 100644
--- a/windows/.cvsignore
+++ b/windows/.cvsignore
@@ -1 +1,2 @@
 Makefile
+hook.glue.c
diff --git a/windows/Makefile.in b/windows/Makefile.in
index 19fd99a4d3574ab0f15ac000829dc49a16e666b7..83a61a040fe5d6200a27b4f9b6436acc7e4227b7 100644
--- a/windows/Makefile.in
+++ b/windows/Makefile.in
@@ -41,6 +41,8 @@ C_SRCS = \
 	winpos.c \
 	winproc.c
 
+GLUE = hook.c
+
 all: $(MODULE).o
 
 @MAKE_RULES@
diff --git a/windows/hook.c b/windows/hook.c
index e9812de531cbc90686f15472a750dd44a66e97f4..4ede6fa545f18ee4b8665bf7a550ec4617a5483e 100644
--- a/windows/hook.c
+++ b/windows/hook.c
@@ -17,6 +17,7 @@
 #include "winuser.h"
 #include "wine/winuser16.h"
 #include "wine/winbase16.h"
+#include "callback.h"
 #include "hook.h"
 #include "win.h"
 #include "queue.h"
@@ -35,11 +36,12 @@ DEFAULT_DEBUG_CHANNEL(hook)
 typedef struct
 {
     HANDLE16   next;               /* 00 Next hook in chain */
-    HOOKPROC proc WINE_PACKED;   /* 02 Hook procedure */
+    HOOKPROC   proc;               /* 02 Hook procedure (original) */
     INT16      id;                 /* 06 Hook id (WH_xxx) */
     HQUEUE16   ownerQueue;         /* 08 Owner queue (0 for system hook) */
     HMODULE16  ownerModule;        /* 0a Owner module */
     WORD       flags;              /* 0c flags */
+    HOOKPROC   thunk;              /* 0e Hook procedure (CallTo16 thunk) */
 } HOOKDATA;
 
 #include "poppack.h"
@@ -850,6 +852,9 @@ static HANDLE16 HOOK_GetHook( INT16 id, HQUEUE16 hQueue )
  *
  * Install a given hook.
  */
+/* ### start build ### */
+extern LONG CALLBACK HOOK_CallTo16_long_wwl(FARPROC16,WORD,WORD,LONG);
+/* ### stop build ### */
 static HHOOK HOOK_SetHook( INT16 id, LPVOID proc, INT type,
 		           HMODULE16 hModule, DWORD dwThreadId )
 {
@@ -885,6 +890,20 @@ static HHOOK HOOK_SetHook( INT16 id, LPVOID proc, INT type,
     data->ownerModule = hModule;
     data->flags       = type;
 
+    /* Create CallTo16 thunk for 16-bit hooks */
+
+    if ( (data->flags & HOOK_MAPTYPE) == HOOK_WIN16 )
+        data->thunk = (HOOKPROC)THUNK_Alloc( (FARPROC16)data->proc, 
+                                             (RELAY)HOOK_CallTo16_long_wwl );
+    else
+        data->thunk = data->proc;
+
+    if ( !data->thunk && data->proc )
+    {
+        USER_HEAP_FREE( handle );
+        return 0;
+    }
+
     /* Insert it in the correct linked list */
 
     if (hQueue)
@@ -945,6 +964,10 @@ static BOOL HOOK_RemoveHook( HANDLE16 hook )
 
     if (!*prevHook) return FALSE;
     *prevHook = data->next;
+
+    if ( (data->flags & HOOK_MAPTYPE) == HOOK_WIN16 )
+        THUNK_Free( (FARPROC)data->thunk );
+
     USER_HEAP_FREE( hook );
     return TRUE;
 }
@@ -1004,7 +1027,7 @@ static LRESULT HOOK_CallHook( HANDLE16 hook, INT fromtype, INT code,
     /* Suspend window structure locks before calling user code */
     iWndsLocks = WIN_SuspendWndsLock();
 
-    ret = data->proc(code, wParam, lParam);
+    ret = data->thunk(code, wParam, lParam);
 
     /* Grrr. While the hook procedure is supposed to have an LRESULT return
        value even in Win16, it seems that for those hook types where the 
@@ -1036,21 +1059,6 @@ static LRESULT HOOK_CallHook( HANDLE16 hook, INT fromtype, INT code,
  *           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_MAPTYPE) != HOOK_WIN16) return NULL;
-    return (HOOKPROC16)data->proc;
-}
-
-
 /***********************************************************************
  *           HOOK_IsHooked
  *