diff --git a/win32ss/user/ntuser/callback.c b/win32ss/user/ntuser/callback.c
index 1497d72a89..bf1143f4b8 100644
--- a/win32ss/user/ntuser/callback.c
+++ b/win32ss/user/ntuser/callback.c
@@ -539,6 +539,7 @@ co_IntCallHookProc(INT HookId,
    UINT lParamSize = 0;
    CWPSTRUCT* pCWP = NULL;
    CWPRETSTRUCT* pCWPR = NULL;
+   PVOID pszClass = NULL, pszName = NULL;
 
    ASSERT(Proc);
    /* Do not allow the desktop thread to do callback to user mode */
@@ -709,8 +710,18 @@ co_IntCallHookProc(INT HookId,
           * lParam could be a pointer to a buffer. This buffer must be exported
           * to user space too */
          if ( lParamSize )
-         {
-             RtlCopyMemory( &pcwps->Extra, (PVOID)pCWP->lParam, lParamSize );
+         {   //   Handle Special messages.
+             if ( pCWP->message == WM_CREATE || pCWP->message == WM_NCCREATE )
+             {
+                 PWND pwnd = ValidateHwndNoErr(pCWP->hwnd);
+                 CREATESTRUCTW *pCsw = (CREATESTRUCTW *)&pcwps->Extra;
+                 //
+                 // String pointers are in user heap space, like WH_CBT HCBT_CREATEWND.
+                 //
+                 IntMsgCreateStructW( pwnd, pCsw, (CREATESTRUCTW *)pCWP->lParam, &pszClass, &pszName );
+             }
+             else
+                 RtlCopyMemory( &pcwps->Extra, (PVOID)pCWP->lParam, lParamSize );
          }
       }
          break;
@@ -720,7 +731,14 @@ co_IntCallHookProc(INT HookId,
          RtlCopyMemory( &pcwprs->cwprs, pCWPR, sizeof(CWPRETSTRUCT));
          if ( lParamSize )
          {
-             RtlCopyMemory( &pcwprs->Extra, (PVOID)pCWPR->lParam, lParamSize );
+             if ( pCWPR->message == WM_CREATE || pCWPR->message == WM_NCCREATE )
+             {
+                 PWND pwnd = ValidateHwndNoErr(pCWPR->hwnd);
+                 CREATESTRUCTW *pCsw = (CREATESTRUCTW *)&pcwprs->Extra;
+                 IntMsgCreateStructW( pwnd, pCsw, (CREATESTRUCTW *)pCWPR->lParam, &pszClass, &pszName );
+             }
+             else
+                 RtlCopyMemory( &pcwprs->Extra, (PVOID)pCWPR->lParam, lParamSize );
          }
       }
          break;
@@ -823,6 +841,8 @@ Fault_Exit:
       ERR("Exception CallHookProc HookId %d Code %d\n",HookId,Code);
    }
    if (Argument) IntCbFreeMemory(Argument);
+   if (pszName) UserHeapFree(pszName);
+   if (pszClass) UserHeapFree(pszClass);
 
    return Result;
 }
diff --git a/win32ss/user/ntuser/callback.h b/win32ss/user/ntuser/callback.h
index 2eee4e9b4d..c83be89a97 100644
--- a/win32ss/user/ntuser/callback.h
+++ b/win32ss/user/ntuser/callback.h
@@ -75,3 +75,4 @@ HANDLE FASTCALL co_IntCopyImage(HANDLE,UINT,INT,INT,UINT);
 BOOL FASTCALL co_IntSetWndIcons(VOID);
 VOID FASTCALL co_IntDeliverUserAPC(VOID);
 VOID FASTCALL co_IntSetupOBM(VOID);
+BOOL FASTCALL IntMsgCreateStructW(PWND,CREATESTRUCTW*,CREATESTRUCTW*,PVOID*,PVOID*);
diff --git a/win32ss/user/ntuser/window.c b/win32ss/user/ntuser/window.c
index 9994a6b23e..153bcc2791 100644
--- a/win32ss/user/ntuser/window.c
+++ b/win32ss/user/ntuser/window.c
@@ -1962,6 +1962,104 @@ Error:
    return NULL;
 }
 
+//
+//
+//
+BOOL
+FASTCALL
+IntMsgCreateStructW(
+    PWND Window,
+    CREATESTRUCTW *pCsw,
+    CREATESTRUCTW *Cs,
+    PVOID *ppszClass,
+    PVOID *ppszName )
+{
+    PLARGE_STRING WindowName;
+    PUNICODE_STRING ClassName;
+    PVOID pszClass = NULL, pszName = NULL;
+
+      /* Fill the new CREATESTRUCTW */
+      RtlCopyMemory(pCsw, Cs, sizeof(CREATESTRUCTW));
+      pCsw->style = Window->style; /* HCBT_CREATEWND needs the real window style */
+
+      WindowName = (PLARGE_STRING)   Cs->lpszName;
+      ClassName  = (PUNICODE_STRING) Cs->lpszClass;
+
+      // Based on the assumption this is from "unicode source" user32, ReactOS, answer is yes.
+      if (!IS_ATOM(ClassName->Buffer))
+      {
+         if (Window->state & WNDS_ANSICREATOR)
+         {
+            ANSI_STRING AnsiString;
+            AnsiString.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(ClassName)+sizeof(CHAR);
+            pszClass = UserHeapAlloc(AnsiString.MaximumLength);
+            if (!pszClass)
+            {
+               ERR("UserHeapAlloc() failed!\n");
+               return FALSE;
+            }
+            RtlZeroMemory(pszClass, AnsiString.MaximumLength);
+            AnsiString.Buffer = (PCHAR)pszClass;
+            RtlUnicodeStringToAnsiString(&AnsiString, ClassName, FALSE);
+         }
+         else
+         {
+            UNICODE_STRING UnicodeString;
+            UnicodeString.MaximumLength = ClassName->Length + sizeof(UNICODE_NULL);
+            pszClass = UserHeapAlloc(UnicodeString.MaximumLength);
+            if (!pszClass)
+            {
+               ERR("UserHeapAlloc() failed!\n");
+               return FALSE;
+            }
+            RtlZeroMemory(pszClass, UnicodeString.MaximumLength);
+            UnicodeString.Buffer = (PWSTR)pszClass;
+            RtlCopyUnicodeString(&UnicodeString, ClassName);
+         }
+         *ppszClass = pszClass;
+         pCsw->lpszClass = UserHeapAddressToUser(pszClass);
+      }
+      if (WindowName->Length)
+      {
+         UNICODE_STRING Name;
+         Name.Buffer = WindowName->Buffer;
+         Name.Length = (USHORT)min(WindowName->Length, MAXUSHORT); // FIXME: LARGE_STRING truncated
+         Name.MaximumLength = (USHORT)min(WindowName->MaximumLength, MAXUSHORT);
+
+         if (Window->state & WNDS_ANSICREATOR)
+         {
+            ANSI_STRING AnsiString;
+            AnsiString.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(&Name) + sizeof(CHAR);
+            pszName = UserHeapAlloc(AnsiString.MaximumLength);
+            if (!pszName)
+            {
+               ERR("UserHeapAlloc() failed!\n");
+               return FALSE;
+            }
+            RtlZeroMemory(pszName, AnsiString.MaximumLength);
+            AnsiString.Buffer = (PCHAR)pszName;
+            RtlUnicodeStringToAnsiString(&AnsiString, &Name, FALSE);
+         }
+         else
+         {
+            UNICODE_STRING UnicodeString;
+            UnicodeString.MaximumLength = Name.Length + sizeof(UNICODE_NULL);
+            pszName = UserHeapAlloc(UnicodeString.MaximumLength);
+            if (!pszName)
+            {
+               ERR("UserHeapAlloc() failed!\n");
+               return FALSE;
+            }
+            RtlZeroMemory(pszName, UnicodeString.MaximumLength);
+            UnicodeString.Buffer = (PWSTR)pszName;
+            RtlCopyUnicodeString(&UnicodeString, &Name);
+         }
+         *ppszName = pszName;
+         pCsw->lpszName = UserHeapAddressToUser(pszName);
+      }
+   return TRUE;
+}
+
 /*
  * @implemented
  */
diff --git a/win32ss/user/user32/windows/hook.c b/win32ss/user/user32/windows/hook.c
index f525bf1cc5..1be83cb7c3 100644
--- a/win32ss/user/user32/windows/hook.c
+++ b/win32ss/user/user32/windows/hook.c
@@ -710,8 +710,16 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
        * is at the end of the argument buffer */
       if ( Common->lParamSize )
       {
-         pCWP->lParam = (LPARAM)((PCHAR)pCWP + sizeof(CWPSTRUCT));
-         RtlCopyMemory( (PCHAR)pCWP + sizeof(CWPSTRUCT), &pcwps->Extra, Common->lParamSize );
+          if ( pCWP->message == WM_CREATE || pCWP->message == WM_NCCREATE )
+          {
+             CREATESTRUCTW *pcsw = (CREATESTRUCTW *) &pcwps->Extra;
+             RtlCopyMemory((PCHAR)pCWP + sizeof(CWPSTRUCT), pcsw, sizeof(CREATESTRUCTW));
+          }
+          else
+          {
+             RtlCopyMemory( (PCHAR)pCWP + sizeof(CWPSTRUCT), &pcwps->Extra, Common->lParamSize );
+          }
+          pCWP->lParam = (LPARAM)((PCHAR)pCWP + sizeof(CWPSTRUCT));
       }
       Result = Proc(Common->Code, Common->wParam, (LPARAM) pCWP);
       HeapFree(GetProcessHeap(), 0, pCWP);
@@ -726,8 +734,16 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
       RtlCopyMemory(pCWPR, pCWPRT, sizeof(CWPSTRUCT));
       if ( Common->lParamSize )
       {
-         pCWPR->lParam = (LPARAM)((PCHAR)pCWPR + sizeof(CWPRETSTRUCT));
-         RtlCopyMemory( (PCHAR)pCWPR + sizeof(CWPRETSTRUCT), &pcwprs->Extra, Common->lParamSize );
+          if ( pCWPR->message == WM_CREATE || pCWPR->message == WM_NCCREATE )
+          {
+             CREATESTRUCTW *pcsw = (CREATESTRUCTW *) &pcwprs->Extra;
+             RtlCopyMemory((PCHAR)pCWPR + sizeof(CWPRETSTRUCT), pcsw, sizeof(CREATESTRUCTW));
+          }
+          else
+          {
+             RtlCopyMemory( (PCHAR)pCWPR + sizeof(CWPRETSTRUCT), &pcwprs->Extra, Common->lParamSize );
+          }
+          pCWPR->lParam = (LPARAM)((PCHAR)pCWPR + sizeof(CWPRETSTRUCT));
       }
       Result = Proc(Common->Code, Common->wParam, (LPARAM) pCWPR);
       HeapFree(GetProcessHeap(), 0, pCWPR);
