sync with trunk head (34904)
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / callback.c
index a9b3ac1..4cce750 100644 (file)
@@ -106,6 +106,34 @@ IntCleanupThreadCallbacks(PW32THREAD W32Thread)
    }
 }
 
+
+//
+// Pass the Current Window handle and pointer to the Client Callback.
+// This will help user space programs speed up read access with the window object.
+//
+static VOID
+IntSetTebWndCallback (HWND * hWnd, PVOID * pWnd)
+{
+  HWND hWndS = *hWnd;
+  PWINDOW_OBJECT Window = UserGetWindowObject(*hWnd);
+  PW32CLIENTINFO ClientInfo = GetWin32ClientInfo();
+
+  *hWnd = ClientInfo->hWND;
+  *pWnd = ClientInfo->pvWND;
+
+  ClientInfo->hWND  = hWndS;
+  ClientInfo->pvWND = DesktopHeapAddressToUser(Window->Wnd);
+}
+
+static VOID
+IntRestoreTebWndCallback (HWND hWnd, PVOID pWnd)
+{
+  PW32CLIENTINFO ClientInfo = GetWin32ClientInfo();
+
+  ClientInfo->hWND  = hWnd;
+  ClientInfo->pvWND = pWnd;
+}
+
 /* FUNCTIONS *****************************************************************/
 
 VOID STDCALL
@@ -116,7 +144,7 @@ co_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback,
                               LRESULT Result)
 {
    SENDASYNCPROC_CALLBACK_ARGUMENTS Arguments;
-   PVOID ResultPointer;
+   PVOID ResultPointer, pWnd;
    ULONG ResultLength;
    NTSTATUS Status;
 
@@ -126,6 +154,8 @@ co_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback,
    Arguments.Context = CompletionCallbackContext;
    Arguments.Result = Result;
 
+   IntSetTebWndCallback (&hWnd, &pWnd);
+
    UserLeaveCo();
 
    Status = KeUserModeCallback(USER32_CALLBACK_SENDASYNCPROC,
@@ -136,6 +166,8 @@ co_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback,
 
    UserEnterCo();
 
+   IntRestoreTebWndCallback (hWnd, pWnd);
+
    if (!NT_SUCCESS(Status))
    {
       return;
@@ -155,7 +187,7 @@ co_IntCallWindowProc(WNDPROC Proc,
    WINDOWPROC_CALLBACK_ARGUMENTS StackArguments;
    PWINDOWPROC_CALLBACK_ARGUMENTS Arguments;
    NTSTATUS Status;
-   PVOID ResultPointer;
+   PVOID ResultPointer, pWnd;
    ULONG ResultLength;
    ULONG ArgumentLength;
    LRESULT Result;
@@ -187,6 +219,8 @@ co_IntCallWindowProc(WNDPROC Proc,
    ResultPointer = NULL;
    ResultLength = ArgumentLength;
 
+   IntSetTebWndCallback (&Wnd, &pWnd);
+
    UserLeaveCo();
 
    Status = KeUserModeCallback(USER32_CALLBACK_WINDOWPROC,
@@ -195,11 +229,21 @@ co_IntCallWindowProc(WNDPROC Proc,
                                &ResultPointer,
                                &ResultLength);
 
-   /* Simulate old behaviour: copy into our local buffer */
-   RtlMoveMemory(Arguments, ResultPointer, ArgumentLength);
+   _SEH_TRY
+   {
+      /* Simulate old behaviour: copy into our local buffer */
+      RtlMoveMemory(Arguments, ResultPointer, ArgumentLength);
+   }
+   _SEH_HANDLE
+   {
+      Status = _SEH_GetExceptionCode();
+   }
+   _SEH_END;
 
    UserEnterCo();
 
+   IntRestoreTebWndCallback (Wnd, pWnd);
+
    if (!NT_SUCCESS(Status))
    {
       if (0 < lParamBufferSize)
@@ -295,7 +339,7 @@ co_IntCallHookProc(INT HookId,
 {
    ULONG ArgumentLength;
    PVOID Argument;
-   LRESULT Result;
+   LRESULT Result = 0;
    NTSTATUS Status;
    PVOID ResultPointer;
    ULONG ResultLength;
@@ -335,6 +379,23 @@ co_IntCallHookProc(INT HookId,
       case WH_MOUSE_LL:
          ArgumentLength += sizeof(MSLLHOOKSTRUCT);
          break;
+      case WH_MOUSE:
+         ArgumentLength += sizeof(MOUSEHOOKSTRUCT);
+         break;
+     case WH_CALLWNDPROC:
+         ArgumentLength += sizeof(CWPSTRUCT);
+         break;
+      case WH_CALLWNDPROCRET:
+         ArgumentLength += sizeof(CWPRETSTRUCT);
+         break;
+      case WH_MSGFILTER:
+      case WH_SYSMSGFILTER:
+      case WH_GETMESSAGE:
+         ArgumentLength += sizeof(MSG);
+         break;
+      case WH_KEYBOARD:
+//      case WH_SHELL:
+         break;
       default:
          DPRINT1("Trying to call unsupported window hook %d\n", HookId);
          return 0;
@@ -378,7 +439,7 @@ co_IntCallHookProc(INT HookId,
                {
                   RtlCopyMemory(Extra, ClassName->Buffer, ClassName->Length);
                   CbtCreatewndExtra->Cs.lpszClass =
-                     (LPCWSTR) MAKELONG(Extra - (PCHAR) CbtCreatewndExtra, 1);
+                     (LPCWSTR)(ULONG_PTR) MAKELONG(Extra - (PCHAR) CbtCreatewndExtra, 1);
                   Extra += ClassName->Length;
                   *((WCHAR *) Extra) = L'\0';
                }
@@ -393,6 +454,30 @@ co_IntCallHookProc(INT HookId,
          RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSLLHOOKSTRUCT));
          Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
          break;
+      case WH_MOUSE:
+         RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MOUSEHOOKSTRUCT));
+         Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
+         break;         
+      case WH_CALLWNDPROC:
+         RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CWPSTRUCT));
+         Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
+         break;         
+      case WH_CALLWNDPROCRET:
+         RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CWPRETSTRUCT));
+         Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
+         break;         
+      case WH_MSGFILTER:
+      case WH_SYSMSGFILTER:
+      case WH_GETMESSAGE:
+         RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSG));
+         Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
+//         DPRINT1("KHOOK Memory: %x\n",Common);
+         break;
+      case WH_KEYBOARD:
+         break;
+//      case WH_SHELL:
+//         Extra = lParam;
+         break;         
    }
 
    ResultPointer = NULL;
@@ -406,11 +491,87 @@ co_IntCallHookProc(INT HookId,
                                &ResultPointer,
                                &ResultLength);
 
+   UserEnterCo();
+
+   _SEH_TRY
+   {
+      ProbeForRead((PVOID)*(LRESULT*)ResultPointer,
+                                   sizeof(LRESULT),
+                                                 1);
+      /* Simulate old behaviour: copy into our local buffer */
+      Result = *(LRESULT*)ResultPointer;
+   }
+   _SEH_HANDLE
+   {
+      Result = 0;
+   }
+   _SEH_END;
+
+   IntCbFreeMemory(Argument);
+
+   if (!NT_SUCCESS(Status))
+   {
+      return 0;
+   }
+
+   return Result;
+}
+
+LRESULT
+STDCALL
+co_IntCallEventProc(HWINEVENTHOOK hook,
+                           DWORD event,
+                             HWND hWnd,
+                         LONG idObject,
+                          LONG idChild,
+                   DWORD dwEventThread,
+                   DWORD dwmsEventTime,
+                     WINEVENTPROC Proc)
+{
+   LRESULT Result;
+   NTSTATUS Status;
+   PEVENTPROC_CALLBACK_ARGUMENTS Common;
+   ULONG ArgumentLength, ResultLength;
+   PVOID Argument, ResultPointer, pWnd;
+
+   ArgumentLength = sizeof(EVENTPROC_CALLBACK_ARGUMENTS);
+
+   Argument = IntCbAllocateMemory(ArgumentLength);
+   if (NULL == Argument)
+   {
+      DPRINT1("EventProc callback failed: out of memory\n");
+      return 0;
+   }
+   Common = (PEVENTPROC_CALLBACK_ARGUMENTS) Argument;
+   Common->hook = hook;
+   Common->event = event;
+   Common->hwnd = hWnd;
+   Common->idObject = idObject;
+   Common->idChild = idChild;
+   Common->dwEventThread = dwEventThread;
+   Common->dwmsEventTime = dwmsEventTime;
+   Common->Proc = Proc;
+
+   ResultPointer = NULL;
+   ResultLength = sizeof(LRESULT);
+
+   IntSetTebWndCallback (&hWnd, &pWnd);
+
+   UserLeaveCo();
+
+   Status = KeUserModeCallback(USER32_CALLBACK_EVENTPROC,
+                               Argument,
+                               ArgumentLength,
+                               &ResultPointer,
+                               &ResultLength);
+
    /* Simulate old behaviour: copy into our local buffer */
    Result = *(LRESULT*)ResultPointer;
 
    UserEnterCo();
 
+   IntRestoreTebWndCallback (hWnd, pWnd);
+
    IntCbFreeMemory(Argument);
 
    if (!NT_SUCCESS(Status))