diff --git a/win32ss/include/callback.h b/win32ss/include/callback.h
index 5b6f49ce3a..7eef1d6c27 100644
--- a/win32ss/include/callback.h
+++ b/win32ss/include/callback.h
@@ -61,6 +61,7 @@ typedef struct _HOOKPROC_CALLBACK_ARGUMENTS
   ULONG_PTR offPfn;
   BOOLEAN Ansi;
   LRESULT Result;
+  UINT lParamSize;
   WCHAR ModuleName[512];
 } HOOKPROC_CALLBACK_ARGUMENTS, *PHOOKPROC_CALLBACK_ARGUMENTS;
 
@@ -72,6 +73,20 @@ typedef struct _HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS
   /* WCHAR szClass[] */
 } HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS, *PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS;
 
+typedef struct tagCWP_Struct
+{
+   HOOKPROC_CALLBACK_ARGUMENTS hpca;
+   CWPSTRUCT cwps;
+   PBYTE Extra[4];
+} CWP_Struct, *PCWP_Struct;
+
+typedef struct tagCWPR_Struct
+{
+   HOOKPROC_CALLBACK_ARGUMENTS hpca;
+   CWPRETSTRUCT cwprs;
+   PBYTE Extra[4];
+} CWPR_Struct, *PCWPR_Struct;
+
 typedef struct _EVENTPROC_CALLBACK_ARGUMENTS
 {
   HWINEVENTHOOK hook;
diff --git a/win32ss/user/ntuser/callback.c b/win32ss/user/ntuser/callback.c
index 42d50002d3..1497d72a89 100644
--- a/win32ss/user/ntuser/callback.c
+++ b/win32ss/user/ntuser/callback.c
@@ -509,6 +509,8 @@ co_IntLoadDefaultCursors(VOID)
    return TRUE;
 }
 
+static INT iTheId = -2; // Set it out of range.
+
 LRESULT APIENTRY
 co_IntCallHookProc(INT HookId,
                    INT Code,
@@ -535,6 +537,8 @@ co_IntCallHookProc(INT HookId,
    PMSG pMsg = NULL;
    BOOL Hit = FALSE;
    UINT lParamSize = 0;
+   CWPSTRUCT* pCWP = NULL;
+   CWPRETSTRUCT* pCWPR = NULL;
 
    ASSERT(Proc);
    /* Do not allow the desktop thread to do callback to user mode */
@@ -593,27 +597,27 @@ co_IntCallHookProc(INT HookId,
                goto Fault_Exit;
          }
          break;
-      case WH_KEYBOARD_LL:
+     case WH_KEYBOARD_LL:
          ArgumentLength += sizeof(KBDLLHOOKSTRUCT);
          break;
-      case WH_MOUSE_LL:
+     case WH_MOUSE_LL:
          ArgumentLength += sizeof(MSLLHOOKSTRUCT);
          break;
-      case WH_MOUSE:
+     case WH_MOUSE:
          ArgumentLength += sizeof(MOUSEHOOKSTRUCT);
          break;
      case WH_CALLWNDPROC:
      {
-         CWPSTRUCT* pCWP = (CWPSTRUCT*) lParam;
-         ArgumentLength += sizeof(CWPSTRUCT);
+         pCWP = (CWPSTRUCT*) lParam;
+         ArgumentLength = sizeof(CWP_Struct);
          lParamSize = lParamMemorySize(pCWP->message, pCWP->wParam, pCWP->lParam);
          ArgumentLength += lParamSize;
          break;
       }
       case WH_CALLWNDPROCRET:
       {
-         CWPRETSTRUCT* pCWPR = (CWPRETSTRUCT*) lParam;
-         ArgumentLength += sizeof(CWPRETSTRUCT);
+         pCWPR = (CWPRETSTRUCT*) lParam;
+         ArgumentLength = sizeof(CWPR_Struct);
          lParamSize = lParamMemorySize(pCWPR->message, pCWPR->wParam, pCWPR->lParam);
          ArgumentLength += lParamSize;
          break;
@@ -647,6 +651,7 @@ co_IntCallHookProc(INT HookId,
    Common->Mod = Mod;
    Common->offPfn = offPfn;
    Common->Ansi = Ansi;
+   Common->lParamSize = lParamSize;
    RtlZeroMemory(&Common->ModuleName, sizeof(Common->ModuleName));
    if (ModuleName->Buffer && ModuleName->Length)
    {
@@ -697,25 +702,27 @@ co_IntCallHookProc(INT HookId,
          Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
          break;
       case WH_CALLWNDPROC:
+      {
+         PCWP_Struct pcwps = (PCWP_Struct)Common;
+         RtlCopyMemory( &pcwps->cwps, pCWP, sizeof(CWPSTRUCT));
          /* For CALLWNDPROC and CALLWNDPROCRET, we must be wary of the fact that
           * lParam could be a pointer to a buffer. This buffer must be exported
           * to user space too */
-         RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CWPSTRUCT));
-         Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
-         if(lParamSize)
+         if ( lParamSize )
          {
-             RtlCopyMemory(Extra + sizeof(CWPSTRUCT), (PVOID)((CWPSTRUCT*)lParam)->lParam, lParamSize);
-             ((CWPSTRUCT*)Extra)->lParam = (LPARAM)lParamSize;
+             RtlCopyMemory( &pcwps->Extra, (PVOID)pCWP->lParam, lParamSize );
          }
+      }
          break;
       case WH_CALLWNDPROCRET:
-         RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CWPRETSTRUCT));
-         Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
-         if(lParamSize)
+      {
+         PCWPR_Struct pcwprs = (PCWPR_Struct)Common;
+         RtlCopyMemory( &pcwprs->cwprs, pCWPR, sizeof(CWPRETSTRUCT));
+         if ( lParamSize )
          {
-             RtlCopyMemory(Extra + sizeof(CWPRETSTRUCT), (PVOID)((CWPRETSTRUCT*)lParam)->lParam, lParamSize);
-             ((CWPRETSTRUCT*)Extra)->lParam = (LPARAM)lParamSize;
+             RtlCopyMemory( &pcwprs->Extra, (PVOID)pCWPR->lParam, lParamSize );
          }
+      }
          break;
       case WH_MSGFILTER:
       case WH_SYSMSGFILTER:
@@ -745,7 +752,11 @@ co_IntCallHookProc(INT HookId,
 
    if (!NT_SUCCESS(Status))
    {
-      ERR("Failure to make Callback! Status 0x%x\n",Status);
+      if ( iTheId != HookId ) // Hook ID can change.
+      {
+          ERR("Failure to make Callback %d! Status 0x%x\n",HookId,Status);
+          iTheId = HookId;
+      }
       goto Fault_Exit;
    }
 
@@ -1216,12 +1227,13 @@ APIENTRY
 co_UserCBClientPrinterThunk( PVOID pkt, INT InSize, PVOID pvOutData, INT OutSize )
 {
    NTSTATUS Status;
+   PVOID ResultPointer;
 
-   Status = KeUserModeCallback(USER32_CALLBACK_UMPD,
-                               pkt,
-                               InSize,
-                               pvOutData,
-                               (PULONG)&OutSize);
+   Status = KeUserModeCallback( USER32_CALLBACK_UMPD,
+                                pkt,
+                                InSize,
+                               &ResultPointer,
+                               (PULONG)&OutSize );
 
 
    if (!NT_SUCCESS(Status))
@@ -1230,6 +1242,8 @@ co_UserCBClientPrinterThunk( PVOID pkt, INT InSize, PVOID pvOutData, INT OutSize
       return 1;
    }
 
+   if (OutSize) RtlMoveMemory( pvOutData, ResultPointer, OutSize );
+
    return 0;
 }
 
diff --git a/win32ss/user/user32/windows/hook.c b/win32ss/user/user32/windows/hook.c
index e0cb8e4a04..f525bf1cc5 100644
--- a/win32ss/user/user32/windows/hook.c
+++ b/win32ss/user/user32/windows/hook.c
@@ -699,35 +699,39 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
       _SEH2_END;
       break;
     case WH_CALLWNDPROC:
-//      ERR("WH_CALLWNDPROC: Code %d, wParam %d\n",Common->Code,Common->wParam);
-      pCWP = HeapAlloc(GetProcessHeap(), 0, ArgumentLength - sizeof(HOOKPROC_CALLBACK_ARGUMENTS));
-      RtlCopyMemory(pCWP, (PCHAR) Common + Common->lParam, sizeof(CWPSTRUCT));
+    {
+      PCWP_Struct pcwps = (PCWP_Struct)Common;
+      CWPSTRUCT *pCWPT = &pcwps->cwps;
+      pCWP = HeapAlloc(GetProcessHeap(), 0, Common->lParamSize + sizeof(CWPSTRUCT));
+      RtlCopyMemory(pCWP, pCWPT, sizeof(CWPSTRUCT));
+//      ERR("WH_CALLWNDPROC: Code %d, wParam %d msg %d\n",Common->Code,Common->wParam,pCWP->message);
       /* If more memory is reserved, then lParam is a pointer.
        * Size of the buffer is stocked in the lParam member, and its content
        * is at the end of the argument buffer */
-      if(ArgumentLength > (sizeof(CWPSTRUCT) + sizeof(HOOKPROC_CALLBACK_ARGUMENTS)))
+      if ( Common->lParamSize )
       {
-         RtlCopyMemory((PCHAR)pCWP + sizeof(CWPSTRUCT),
-            (PCHAR)Common + Common->lParam + sizeof(CWPSTRUCT),
-            pCWP->lParam);
          pCWP->lParam = (LPARAM)((PCHAR)pCWP + sizeof(CWPSTRUCT));
+         RtlCopyMemory( (PCHAR)pCWP + sizeof(CWPSTRUCT), &pcwps->Extra, Common->lParamSize );
       }
       Result = Proc(Common->Code, Common->wParam, (LPARAM) pCWP);
       HeapFree(GetProcessHeap(), 0, pCWP);
+    }
       break;
     case WH_CALLWNDPROCRET:
       /* Almost the same as WH_CALLWNDPROC */
-      pCWPR = HeapAlloc(GetProcessHeap(), 0, ArgumentLength - sizeof(HOOKPROC_CALLBACK_ARGUMENTS));
-      RtlCopyMemory(pCWPR, (PCHAR) Common + Common->lParam, sizeof(CWPRETSTRUCT));
-      if(ArgumentLength > (sizeof(CWPRETSTRUCT) + sizeof(HOOKPROC_CALLBACK_ARGUMENTS)))
+    {
+      PCWPR_Struct pcwprs = (PCWPR_Struct)Common;
+      CWPRETSTRUCT *pCWPRT = &pcwprs->cwprs;
+      pCWPR = HeapAlloc(GetProcessHeap(), 0, Common->lParamSize + sizeof(CWPRETSTRUCT));
+      RtlCopyMemory(pCWPR, pCWPRT, sizeof(CWPSTRUCT));
+      if ( Common->lParamSize )
       {
-         RtlCopyMemory((PCHAR)pCWPR + sizeof(CWPRETSTRUCT),
-            (PCHAR)Common + Common->lParam + sizeof(CWPRETSTRUCT),
-            pCWPR->lParam);
          pCWPR->lParam = (LPARAM)((PCHAR)pCWPR + sizeof(CWPRETSTRUCT));
+         RtlCopyMemory( (PCHAR)pCWPR + sizeof(CWPRETSTRUCT), &pcwprs->Extra, Common->lParamSize );
       }
       Result = Proc(Common->Code, Common->wParam, (LPARAM) pCWPR);
       HeapFree(GetProcessHeap(), 0, pCWPR);
+    }
       break;
     case WH_MSGFILTER: /* All SEH support */
     case WH_SYSMSGFILTER:
