Sync with trunk (r49303)
[reactos.git] / dll / win32 / user32 / windows / hook.c
index 304f932..b848225 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(user32);
 
+typedef struct _NOTIFYEVENT
+{
+   DWORD event;
+   LONG  idObject;
+   LONG  idChild;
+   DWORD flags;
+} NOTIFYEVENT, *PNOTIFYEVENT;
+
 /* PRIVATE FUNCTIONS *********************************************************/
 
 static
@@ -99,6 +107,29 @@ IntSetWindowsHook(
   return NtUserSetWindowsHookEx(hMod, &USModuleName, dwThreadId, idHook, lpfn, bAnsi);
 }
 
+/*
+   Since ReactOS uses User32 as the main message source this was needed.
+   Base on the funny rules from the wine tests it left it with this option.
+   8^(
+ */
+VOID
+FASTCALL
+IntNotifyWinEvent(
+                 DWORD event,
+                 HWND  hwnd,
+                 LONG  idObject,
+                 LONG  idChild,
+                 DWORD flags
+                 )
+{
+  NOTIFYEVENT ne;
+  ne.event    = event;
+  ne.idObject = idObject;
+  ne.idChild  = idChild;
+  ne.flags    = flags;
+  if (gpsi->dwInstalledEventHooks & GetMaskFromEvent(event))
+  NtUserCallHwndParam(hwnd, (DWORD)&ne, HWNDPARAM_ROUTINE_ROS_NOTIFYWINEVENT);
+}
 
 /* FUNCTIONS *****************************************************************/
 
@@ -195,7 +226,7 @@ CallNextHookEx(
 {
   PCLIENTINFO ClientInfo;
   DWORD Flags, Save;
-  PHOOK pHook;
+  PHOOK pHook, phkNext;
   LRESULT lResult = 0;
 
   GetConnected();
@@ -204,9 +235,14 @@ CallNextHookEx(
 
   if (!ClientInfo->phkCurrent) return 0;
   
-  pHook = SharedPtrToUser(ClientInfo->phkCurrent);
+  pHook = DesktopPtrToUser(ClientInfo->phkCurrent);
+
+  if (!pHook->phkNext) return 0; // Nothing to do....
+
+  phkNext = DesktopPtrToUser(pHook->phkNext);
 
-  if (pHook->HookId == WH_CALLWNDPROC || pHook->HookId == WH_CALLWNDPROCRET)
+  if ( phkNext->HookId == WH_CALLWNDPROC ||
+       phkNext->HookId == WH_CALLWNDPROCRET)
   {
      Save = ClientInfo->dwHookData;
      Flags = ClientInfo->CI_flags & CI_CURTHPRHOOK;
@@ -215,7 +251,7 @@ CallNextHookEx(
      if (wParam) ClientInfo->CI_flags |= CI_CURTHPRHOOK;
      else        ClientInfo->CI_flags &= ~CI_CURTHPRHOOK;
 
-     if (pHook->HookId == WH_CALLWNDPROC)
+     if (phkNext->HookId == WH_CALLWNDPROC)
      {
         PCWPSTRUCT pCWP = (PCWPSTRUCT)lParam;
 
@@ -225,7 +261,7 @@ CallNextHookEx(
                            pCWP->lParam, 
                           (ULONG_PTR)&lResult,
                            FNID_CALLWNDPROC,
-                           pHook->Ansi);
+                           phkNext->Ansi);
      }
      else
      {
@@ -239,7 +275,7 @@ CallNextHookEx(
                            pCWPR->lParam, 
                           (ULONG_PTR)&lResult,
                            FNID_CALLWNDPROCRET,
-                           pHook->Ansi);
+                           phkNext->Ansi);
      }
      ClientInfo->CI_flags ^= ((ClientInfo->CI_flags ^ Flags) & CI_CURTHPRHOOK);
      ClientInfo->dwHookData = Save;
@@ -252,23 +288,27 @@ CallNextHookEx(
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 HHOOK
 WINAPI
 SetWindowsHookW(int idHook, HOOKPROC lpfn)
 {
-  return IntSetWindowsHook(idHook, lpfn, NULL, 0, FALSE);
+  DWORD ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread);
+  return IntSetWindowsHook(idHook, lpfn, NULL, ThreadId, FALSE);
+//  return NtUserSetWindowsHookAW(idHook, lpfn, FALSE);
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 HHOOK
 WINAPI
 SetWindowsHookA(int idHook, HOOKPROC lpfn)
 {
-  return IntSetWindowsHook(idHook, lpfn, NULL, 0, TRUE);
+  DWORD ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread);
+  return IntSetWindowsHook(idHook, lpfn, NULL, ThreadId, TRUE);
+//  return NtUserSetWindowsHookAW(idHook, lpfn, TRUE);
 }
 
 /*
@@ -377,7 +417,7 @@ IsWinEventHookInstalled(
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 HHOOK
 WINAPI
@@ -392,7 +432,7 @@ SetWindowsHookExA(
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 HHOOK
 WINAPI
@@ -409,22 +449,21 @@ NTSTATUS WINAPI
 User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
 {
   PHOOKPROC_CALLBACK_ARGUMENTS Common;
-  LRESULT Result;
   CREATESTRUCTW Csw;
   CBT_CREATEWNDW CbtCreatewndw;
-  CREATESTRUCTA Csa;
-  CBT_CREATEWNDA CbtCreatewnda;
   PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL;
-  WPARAM wParam = 0;
-  LPARAM lParam = 0;
-  PKBDLLHOOKSTRUCT KeyboardLlData;
-  PMSLLHOOKSTRUCT MouseLlData;
-  PMSG Msg;
-  PMOUSEHOOKSTRUCT MHook;
-  PCWPSTRUCT CWP;
-  PCWPRETSTRUCT CWPR;
+  KBDLLHOOKSTRUCT KeyboardLlData, *pKeyboardLlData;
+  MSLLHOOKSTRUCT MouseLlData, *pMouseLlData;
+  MSG Msg, *pMsg;
+  PMOUSEHOOKSTRUCT pMHook;
+  CWPSTRUCT CWP, *pCWP;
+  CWPRETSTRUCT CWPR, *pCWPR;
   PRECTL prl;  
   LPCBTACTIVATESTRUCT pcbtas;
+  WPARAM wParam = 0;
+  LPARAM lParam = 0;
+  LRESULT Result = 0;
+  BOOL Hit = FALSE;
 
   Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Arguments;
 
@@ -438,34 +477,16 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
           CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS)
                               ((PCHAR) Common + Common->lParam);
           Csw = CbtCreatewndExtra->Cs;
-          if (NULL != CbtCreatewndExtra->Cs.lpszName)
-          {
-              Csw.lpszName = (LPCWSTR)((PCHAR) CbtCreatewndExtra
-                                       + (ULONG_PTR) CbtCreatewndExtra->Cs.lpszName);
-          }
-          if (0 != HIWORD(CbtCreatewndExtra->Cs.lpszClass))
-          {
-              Csw.lpszClass = (LPCWSTR)((PCHAR) CbtCreatewndExtra
-                                         + LOWORD((ULONG_PTR) CbtCreatewndExtra->Cs.lpszClass));
-          }
+          Csw.lpszName = CbtCreatewndExtra->Cs.lpszName;
+          Csw.lpszClass = CbtCreatewndExtra->Cs.lpszClass;
           wParam = Common->wParam;
-          if (Common->Ansi)
-          {
-              memcpy(&Csa, &Csw, sizeof(CREATESTRUCTW));
-              CbtCreatewnda.lpcs = &Csa;
-              CbtCreatewnda.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
-              lParam = (LPARAM) &CbtCreatewnda;
-          }
-          else
-          {
-              CbtCreatewndw.lpcs = &Csw;
-              CbtCreatewndw.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
-              lParam = (LPARAM) &CbtCreatewndw;
-          }
+          CbtCreatewndw.lpcs = &Csw;
+          CbtCreatewndw.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
+          lParam = (LPARAM) &CbtCreatewndw;
           break;
         case HCBT_CLICKSKIPPED:
-            MHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
-            lParam = (LPARAM) MHook;
+            pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
+            lParam = (LPARAM) pMHook;
             break;
         case HCBT_MOVESIZE:
             prl = (PRECTL)((PCHAR) Common + Common->lParam);
@@ -475,7 +496,7 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
             pcbtas = (LPCBTACTIVATESTRUCT)((PCHAR) Common + Common->lParam);
             lParam = (LPARAM) pcbtas;
             break;
-        case HCBT_KEYSKIPPED:
+        case HCBT_KEYSKIPPED: /* The rest SEH support */
         case HCBT_MINMAX:
         case HCBT_SETFOCUS:
         case HCBT_SYSCOMMAND:
@@ -490,7 +511,17 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
       }
 
       if (Common->Proc)
-         Result = Common->Proc(Common->Code, wParam, lParam);
+      {
+         _SEH2_TRY
+         {
+            Result = Common->Proc(Common->Code, wParam, lParam);
+         }
+         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+         {
+            Hit = TRUE;
+         }
+         _SEH2_END;
+      }
       else
       {
          ERR("Common = 0x%x, Proc = 0x%x\n",Common,Common->Proc);
@@ -499,46 +530,86 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
       {
         case HCBT_CREATEWND:
           CbtCreatewndExtra->WndInsertAfter = CbtCreatewndw.hwndInsertAfter; 
+          CbtCreatewndExtra->Cs.x = CbtCreatewndw.lpcs->x;
+          CbtCreatewndExtra->Cs.y = CbtCreatewndw.lpcs->y;
+          CbtCreatewndExtra->Cs.cx = CbtCreatewndw.lpcs->cx;
+          CbtCreatewndExtra->Cs.cy = CbtCreatewndw.lpcs->cy;
           break;
       }
       break;
     }
     case WH_KEYBOARD_LL:
-      KeyboardLlData = (PKBDLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
-      Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) KeyboardLlData);
+      ERR("WH_KEYBOARD_LL: Code %d, wParam %d\n",Common->Code,Common->wParam);
+      pKeyboardLlData = (PKBDLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
+      RtlCopyMemory(&KeyboardLlData, pKeyboardLlData, sizeof(KBDLLHOOKSTRUCT));
+      Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &KeyboardLlData);
       break;
     case WH_MOUSE_LL:
-      MouseLlData = (PMSLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
-      Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) MouseLlData);
+      pMouseLlData = (PMSLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
+      RtlCopyMemory(&MouseLlData, pMouseLlData, sizeof(MSLLHOOKSTRUCT));
+      Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &MouseLlData);
       break;
-    case WH_MOUSE:
-      MHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
-      Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) MHook);
+    case WH_MOUSE: /* SEH support */
+      pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
+      _SEH2_TRY
+      {
+         Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pMHook);
+      }
+      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+      {
+         Hit = TRUE;
+      }
+      _SEH2_END;
       break;
     case WH_CALLWNDPROC:
-      CWP = (PCWPSTRUCT)((PCHAR) Common + Common->lParam);
-      Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) CWP);
+      ERR("WH_CALLWNDPROC: Code %d, wParam %d\n",Common->Code,Common->wParam);
+      pCWP = (PCWPSTRUCT)((PCHAR) Common + Common->lParam);
+      RtlCopyMemory(&CWP, pCWP, sizeof(CWPSTRUCT));
+      Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &CWP);
       break;
     case WH_CALLWNDPROCRET:
-      CWPR = (PCWPRETSTRUCT)((PCHAR) Common + Common->lParam);
-      Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) CWPR);
+      pCWPR = (PCWPRETSTRUCT)((PCHAR) Common + Common->lParam);
+      RtlCopyMemory(&CWPR, pCWPR, sizeof(CWPRETSTRUCT));
+      Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &CWPR);
       break;
-    case WH_MSGFILTER:
+    case WH_MSGFILTER: /* All SEH support */
+      ERR("WH_MSGFILTER: Code %d, wParam %d\n",Common->Code,Common->wParam);
     case WH_SYSMSGFILTER:
     case WH_GETMESSAGE:
-      Msg = (PMSG)((PCHAR) Common + Common->lParam);
-//      FIXME("UHOOK Memory: %x: %x\n",Common, Msg);
-      Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) Msg);
+      pMsg = (PMSG)((PCHAR) Common + Common->lParam);
+      RtlCopyMemory(&Msg, pMsg, sizeof(MSG));
+      _SEH2_TRY
+      {
+         Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &Msg);
+      }
+      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+      {
+         Hit = TRUE;
+      }
+      _SEH2_END;
+      if (!Hit && Common->HookId == WH_GETMESSAGE)
+         RtlCopyMemory(pMsg, &Msg, sizeof(MSG));
       break;
-    case WH_FOREGROUNDIDLE:
+    case WH_FOREGROUNDIDLE: /* <-- SEH support */
     case WH_KEYBOARD:
     case WH_SHELL:
-      Result = Common->Proc(Common->Code, Common->wParam, Common->lParam);
+      _SEH2_TRY
+      {
+         Result = Common->Proc(Common->Code, Common->wParam, Common->lParam);
+      }
+      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+      {
+         Hit = TRUE;
+      }
+      _SEH2_END;
       break;
     default:
       return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED);
   }
-
+  if (Hit)
+  {
+     ERR("Hook Exception! Id: %d, Code %d, Proc 0x%x\n",Common->HookId,Common->Code,Common->Proc);
+  }
   return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS);
 }