[Win32k|User32]
authorJames Tabor <james.tabor@reactos.org>
Sat, 23 Oct 2010 05:36:12 +0000 (05:36 +0000)
committerJames Tabor <james.tabor@reactos.org>
Sat, 23 Oct 2010 05:36:12 +0000 (05:36 +0000)
- Rewrite the Event and Hook procedures. See bug 5670 for more details.

svn path=/trunk/; revision=49231

27 files changed:
reactos/dll/win32/user32/include/user32.h
reactos/dll/win32/user32/include/user32p.h
reactos/dll/win32/user32/misc/misc.c
reactos/dll/win32/user32/windows/defwnd.c
reactos/dll/win32/user32/windows/hook.c
reactos/dll/win32/user32/windows/input.c
reactos/dll/win32/user32/windows/menu.c
reactos/dll/win32/user32/windows/message.c
reactos/dll/win32/user32/windows/window.c
reactos/include/reactos/win32k/ntuser.h
reactos/subsystems/win32/win32k/include/hook.h
reactos/subsystems/win32/win32k/include/msgqueue.h
reactos/subsystems/win32/win32k/include/win32.h
reactos/subsystems/win32/win32k/include/window.h
reactos/subsystems/win32/win32k/main/dllmain.c
reactos/subsystems/win32/win32k/ntuser/callback.c
reactos/subsystems/win32/win32k/ntuser/caret.c
reactos/subsystems/win32/win32k/ntuser/desktop.c
reactos/subsystems/win32/win32k/ntuser/event.c
reactos/subsystems/win32/win32k/ntuser/focus.c
reactos/subsystems/win32/win32k/ntuser/hook.c
reactos/subsystems/win32/win32k/ntuser/message.c
reactos/subsystems/win32/win32k/ntuser/msgqueue.c
reactos/subsystems/win32/win32k/ntuser/object.c
reactos/subsystems/win32/win32k/ntuser/simplecall.c
reactos/subsystems/win32/win32k/ntuser/window.c
reactos/subsystems/win32/win32k/ntuser/winpos.c

index ba2a836..c6dbbc7 100644 (file)
@@ -43,7 +43,8 @@
 #include <pseh/pseh2.h>
 
 #define HOOKID_TO_FLAG(HookId) (1 << ((HookId) + 1))
-#define ISITHOOKED(HookId) (GetWin32ClientInfo()->fsHooks & HOOKID_TO_FLAG(HookId))
+#define ISITHOOKED(HookId) (GetWin32ClientInfo()->fsHooks & HOOKID_TO_FLAG(HookId) ||\
+                           (GetWin32ClientInfo()->pDeskInfo && GetWin32ClientInfo()->pDeskInfo->fsHooks & HOOKID_TO_FLAG(HookId)))
 
 /* Temporarily in here for now. */
 typedef struct _USERAPIHOOKINFO
@@ -194,3 +195,4 @@ VOID FASTCALL GetConnected(VOID);
 BOOL FASTCALL DefSetText(HWND hWnd, PCWSTR String, BOOL Ansi);
 BOOL FASTCALL TestWindowProcess(PWND);
 VOID UserGetWindowBorders(DWORD, DWORD, SIZE *, BOOL);
+VOID FASTCALL IntNotifyWinEvent(DWORD, HWND, LONG, LONG, DWORD);
index 0227e8e..7bcf68c 100644 (file)
@@ -83,9 +83,6 @@
 #define NtUserGetCursorPos(lpPoint) \
   (BOOL)NtUserCallOneParam((DWORD_PTR)lpPoint, ONEPARAM_ROUTINE_GETCURSORPOSITION)
 
-#define NtUserIsWindowInDestroy(hWnd) \
-  (BOOL)NtUserCallOneParam((DWORD_PTR)hWnd, ONEPARAM_ROUTINE_ISWINDOWINDESTROY)
-
 #define NtUserEnableProcessWindowGhosting(bEnable) \
   NtUserCallOneParam((DWORD_PTR)bEnable, ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING)
 
index 76aaf46..e7b7672 100644 (file)
@@ -304,13 +304,13 @@ GetUser32Handle(HANDLE handle)
 static const BOOL g_ObjectHeapTypeShared[VALIDATE_TYPE_EVENT + 1] =
 {
     FALSE, /* VALIDATE_TYPE_FREE (not used) */
-    FALSE, /* VALIDATE_TYPE_WIN  FALSE */
+    FALSE, /* VALIDATE_TYPE_WIN */
     TRUE, /* VALIDATE_TYPE_MENU  FALSE */
     TRUE, /* VALIDATE_TYPE_CURSOR */
     TRUE, /* VALIDATE_TYPE_MWPOS */
-    TRUE, /* VALIDATE_TYPE_HOOK  FALSE */
+    FALSE, /* VALIDATE_TYPE_HOOK */
     FALSE, /* (not used) */
-    TRUE, /* VALIDATE_TYPE_CALLPROC  FALSE */
+    FALSE, /* VALIDATE_TYPE_CALLPROC */
     TRUE, /* VALIDATE_TYPE_ACCEL */
     FALSE, /* (not used) */
     FALSE, /* (not used) */
index 628940d..76b34be 100644 (file)
@@ -103,6 +103,7 @@ BOOL
 FASTCALL
 DefSetText(HWND hWnd, PCWSTR String, BOOL Ansi)
 {
+  BOOL Ret;
   LARGE_STRING lsString;
 
   if ( String )
@@ -112,7 +113,12 @@ DefSetText(HWND hWnd, PCWSTR String, BOOL Ansi)
      else
         RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&lsString, String, 0);
   }
-  return NtUserDefSetText(hWnd, (String ? &lsString : NULL));
+  Ret = NtUserDefSetText(hWnd, (String ? &lsString : NULL));
+
+  if (Ret)
+     IntNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hWnd, OBJID_WINDOW, CHILDID_SELF, 0);
+
+  return Ret;
 }
 
 void
@@ -1969,7 +1975,6 @@ RealDefWindowProcA(HWND hWnd,
             {
                 DefWndNCPaint(hWnd, (HRGN)1, -1);
             }
-
             Result = 1;
             break;
         }
index 304f932..f79bcbe 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....
 
-  if (pHook->HookId == WH_CALLWNDPROC || pHook->HookId == WH_CALLWNDPROCRET)
+  phkNext = DesktopPtrToUser(pHook->phkNext);
+
+  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
@@ -417,14 +457,15 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
   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;
+  PKBDLLHOOKSTRUCT pKeyboardLlData;
+  PMSLLHOOKSTRUCT pMouseLlData;
+  PMSG pMsg;
+  PMOUSEHOOKSTRUCT pMHook;
+  PCWPSTRUCT pCWP;
+  PCWPRETSTRUCT pCWPR;
   PRECTL prl;  
   LPCBTACTIVATESTRUCT pcbtas;
+  BOOL Hit = FALSE;
 
   Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Arguments;
 
@@ -464,8 +505,8 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
           }
           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 +516,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 +531,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);
@@ -504,41 +555,67 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
       break;
     }
     case WH_KEYBOARD_LL:
-      KeyboardLlData = (PKBDLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
-      Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) KeyboardLlData);
+      pKeyboardLlData = (PKBDLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
+      Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pKeyboardLlData);
       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);
+      Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pMouseLlData);
       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);
+      pCWP = (PCWPSTRUCT)((PCHAR) Common + Common->lParam);
+      Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pCWP);
       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);
+      Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pCWPR);
       break;
-    case WH_MSGFILTER:
+    case WH_MSGFILTER: /* All SEH support */
     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);
+      _SEH2_TRY
+      {
+         Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pMsg);
+      }
+      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+      {
+         Hit = TRUE;
+      }
+      _SEH2_END;
       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);
 }
 
index aa9a997..08e457b 100644 (file)
@@ -138,6 +138,7 @@ EnableWindow(HWND hWnd,
     
     if (Update)
     {
+        IntNotifyWinEvent(EVENT_OBJECT_STATECHANGE, hWnd, OBJID_WINDOW, CHILDID_SELF, 0);
         SendMessageW(hWnd, WM_ENABLE, (LPARAM)bEnable, 0);
     }
     // Return nonzero if it was disabled, or zero if it wasn't:
index dd8f1ff..c9e87de 100644 (file)
@@ -1636,6 +1636,8 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl
         top_popup_hmenu = hmenu;
     }
 
+    IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPSTART, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0);
+
     /* Display the window */
 
     SetWindowPos( MenuInfo.Wnd, HWND_TOPMOST, 0, 0, 0, 0,
@@ -3445,6 +3447,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
 
                 if (MenuInfo.Flags & MF_POPUP)
                 {
+                    IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPEND, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0);
                     DestroyWindow(MenuInfo.Wnd);
                     MenuInfo.Wnd = NULL;
 
@@ -3518,7 +3521,11 @@ static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT
         MenuInfo.Wnd = hWnd;
         MenuSetRosMenuInfo(&MenuInfo);
     }
+
+    IntNotifyWinEvent( EVENT_SYSTEM_MENUSTART,
+                       hWnd,
+                       MenuInfo.Flags & MF_SYSMENU ? OBJID_SYSMENU : OBJID_MENU,
+                       CHILDID_SELF, 0);
     return TRUE;
 }
 /***********************************************************************
@@ -3528,6 +3535,7 @@ static BOOL FASTCALL MenuExitTracking(HWND hWnd, BOOL bPopup)
 {
     TRACE("hwnd=%p\n", hWnd);
 
+    IntNotifyWinEvent( EVENT_SYSTEM_MENUEND, hWnd, OBJID_WINDOW, CHILDID_SELF, 0);
     SendMessageW( hWnd, WM_EXITMENULOOP, bPopup, 0 );
     ShowCaret(0);
     top_popup = 0;
@@ -3645,7 +3653,7 @@ BOOL WINAPI TrackPopupMenuEx( HMENU Menu, UINT Flags, int x, int y,
 {
     BOOL ret = FALSE;
 
-    if (!IsMenu(Menu))
+    if (!IsMenu(Menu))    
     {
       SetLastError( ERROR_INVALID_MENU_HANDLE );
       return FALSE;
index 2c89b78..2645c87 100644 (file)
@@ -2064,13 +2064,18 @@ SendMessageW(HWND Wnd,
 
   if (Wnd != HWND_BROADCAST && (Msg < WM_DDE_FIRST || Msg > WM_DDE_LAST))
   {
-      if (Window != NULL && Window->head.pti == ti && !IsThreadHooked(GetWin32ClientInfo()))
+      if ( Window != NULL &&
+           Window->head.pti == ti &&
+          !IsThreadHooked(GetWin32ClientInfo()) &&
+          !(Window->state & WNDS_SERVERSIDEWINDOWPROC) )
       {
           /* NOTE: We can directly send messages to the window procedure
                    if *all* the following conditions are met:
 
                    * Window belongs to calling thread
                    * The calling thread is not being hooked
+                   * Not calling a server side proc:
+                     Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage
            */
 
           return IntCallMessageProc(Window, Wnd, Msg, wParam, lParam, FALSE);
@@ -2130,13 +2135,18 @@ SendMessageA(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
 
   if (Wnd != HWND_BROADCAST && (Msg < WM_DDE_FIRST || Msg > WM_DDE_LAST))
   {
-      if (Window != NULL && Window->head.pti == ti && !IsThreadHooked(GetWin32ClientInfo()))
+      if ( Window != NULL &&
+           Window->head.pti == ti &&
+          !IsThreadHooked(GetWin32ClientInfo()) &&
+          !(Window->state & WNDS_SERVERSIDEWINDOWPROC) )
       {
           /* NOTE: We can directly send messages to the window procedure
                    if *all* the following conditions are met:
 
                    * Window belongs to calling thread
                    * The calling thread is not being hooked
+                   * Not calling a server side proc: 
+                     Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage
            */
 
           return IntCallMessageProc(Window, Wnd, Msg, wParam, lParam, TRUE);
index 468536e..1b1a089 100644 (file)
@@ -2060,7 +2060,11 @@ AnyPopup(VOID)
 BOOL WINAPI
 IsWindowInDestroy(HWND hWnd)
 {
-    return NtUserIsWindowInDestroy(hWnd);
+    PWND pwnd;
+    pwnd = ValidateHwnd(hWnd);
+    if (!pwnd)
+       return FALSE;
+    return ((pwnd->state2 & WNDS2_INDESTROY) == WNDS2_INDESTROY);
 }
 
 /*
index 920e4e1..64071cb 100644 (file)
@@ -51,13 +51,15 @@ VOID NTAPI RtlInitLargeAnsiString(IN OUT PLARGE_ANSI_STRING,IN PCSZ,IN INT);
 VOID NTAPI RtlInitLargeUnicodeString(IN OUT PLARGE_UNICODE_STRING,IN PCWSTR,IN INT);
 BOOL NTAPI RtlLargeStringToUnicodeString( PUNICODE_STRING, PLARGE_STRING);
 
+#define NB_HOOKS (WH_MAXHOOK-WH_MINHOOK+1)
+
 typedef struct _DESKTOPINFO
 {
     PVOID pvDesktopBase;
     PVOID pvDesktopLimit;
     struct _WND *spwnd;
     DWORD fsHooks;
-    struct tagHOOK * aphkStart[16];
+    LIST_ENTRY aphkStart[NB_HOOKS];
 
     HWND hTaskManWindow;
     HWND hProgmanWindow;
@@ -127,15 +129,23 @@ typedef struct _PROCMARKHEAD
 /* Window Client Information structure */
 struct  _ETHREAD;
 
+#define WEF_SETBYWNDPTI      0x0001
+
 typedef struct tagHOOK
 {
   THRDESKHEAD    head;
+  struct tagHOOK *phkNext;   /* This is for user space. */
+  int            HookId;     /* Hook table index */
+  ULONG_PTR      offPfn;
+  ULONG          flags;      /* Some internal flags */
+  INT            ihmod;
+  PTHREADINFO    ptiHooked;
+  struct _DESKTOP *rpdesk;
+  /* ReactOS */
   LIST_ENTRY     Chain;      /* Hook chain entry */
   struct _ETHREAD* Thread;   /* Thread owning the hook */
-  int            HookId;     /* Hook table index */
   HOOKPROC       Proc;       /* Hook function */
   BOOLEAN        Ansi;       /* Is it an Ansi hook? */
-  ULONG          Flags;      /* Some internal flags */
   UNICODE_STRING ModuleName; /* Module name for global hooks */
 } HOOK, *PHOOK;
 
@@ -3149,7 +3159,6 @@ typedef struct tagKMDDELPARAM
 #define NOPARAM_ROUTINE_ANYPOPUP              0xffff0006
 #define ONEPARAM_ROUTINE_CSRSS_GUICHECK       0xffff0008
 #define ONEPARAM_ROUTINE_SWITCHCARETSHOWING   0xfffe0008
-#define ONEPARAM_ROUTINE_ISWINDOWINDESTROY    0xfffe000c
 #define ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING 0xfffe000d
 #define ONEPARAM_ROUTINE_GETDESKTOPMAPPING    0xfffe000e
 #define ONEPARAM_ROUTINE_MSQSETWAKEMASK       0xfffe0027
@@ -3167,6 +3176,7 @@ typedef struct tagKMDDELPARAM
 #define TWOPARAM_ROUTINE_SETCARETPOS        0xfffd0060
 #define TWOPARAM_ROUTINE_REGISTERLOGONPROC  0xfffd0062
 #define TWOPARAM_ROUTINE_ROS_UPDATEUISTATE  0x1004
+#define HWNDPARAM_ROUTINE_ROS_NOTIFYWINEVENT 0x1005
 
 DWORD
 NTAPI
index d09304b..ce6d64e 100644 (file)
@@ -1,17 +1,10 @@
 #pragma once
 
 #define HOOK_THREAD_REFERENCED (0x1)
-#define NB_HOOKS (WH_MAXHOOK-WH_MINHOOK+1)
 #define HOOKID_TO_INDEX(HookId) (HookId - WH_MINHOOK)
 #define HOOKID_TO_FLAG(HookId) (1 << ((HookId) + 1))
 #define ISITHOOKED(HookId) (((PTHREADINFO)PsGetCurrentThreadWin32Thread())->fsHooks & HOOKID_TO_FLAG(HookId))
 
-typedef struct tagHOOKTABLE
-{
-  LIST_ENTRY Hooks[NB_HOOKS];  /* array of hook chains */
-  UINT       Counts[NB_HOOKS]; /* use counts for each hook chain */
-} HOOKTABLE, *PHOOKTABLE;
-
 typedef struct tagEVENTHOOK
 {
   THROBJHEAD     head;
@@ -32,11 +25,22 @@ typedef struct tagEVENTTABLE
   UINT       Counts;
 } EVENTTABLE, *PEVENTTABLE;
 
+typedef struct _NOTIFYEVENT
+{
+   DWORD event;
+   LONG  idObject;
+   LONG  idChild;
+   DWORD flags; 
+} NOTIFYEVENT, *PNOTIFYEVENT;
+
+LRESULT FASTCALL co_CallHook(INT HookId, INT Code, WPARAM wParam, LPARAM lParam);
 LRESULT FASTCALL co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam);
 LRESULT FASTCALL co_EVENT_CallEvents(DWORD, HWND, UINT_PTR, LONG_PTR);
 VOID FASTCALL HOOK_DestroyThreadHooks(PETHREAD Thread);
+VOID FASTCALL EVENT_DestroyThreadEvents(PETHREAD Thread);
 PHOOK FASTCALL IntGetHookObject(HHOOK);
 PHOOK FASTCALL IntGetNextHook(PHOOK Hook);
 LRESULT FASTCALL UserCallNextHookEx( PHOOK pHook, int Code, WPARAM wParam, LPARAM lParam, BOOL Ansi);
+BOOL FASTCALL IntUnhookWindowsHook(int,HOOKPROC);
 
 /* EOF */
index e35ab0f..569f102 100644 (file)
@@ -87,9 +87,6 @@ typedef struct _USER_MESSAGE_QUEUE
   /* Caret information for this queue */
   PTHRDCARETINFO CaretInfo;
 
-  /* Window hooks */
-  PHOOKTABLE Hooks;
-
   /* queue state tracking */
   WORD WakeMask;
   WORD QueueBits;
@@ -212,9 +209,6 @@ BOOL APIENTRY IntInitMessagePumpHook();
 BOOL APIENTRY IntUninitMessagePumpHook();
 #define MAKE_LONG(x, y) ((((y) & 0xFFFF) << 16) | ((x) & 0xFFFF))
 
-PHOOKTABLE FASTCALL MsqGetHooks(PUSER_MESSAGE_QUEUE Queue);
-VOID FASTCALL MsqSetHooks(PUSER_MESSAGE_QUEUE Queue, PHOOKTABLE Hooks);
-
 LPARAM FASTCALL MsqSetMessageExtraInfo(LPARAM lParam);
 LPARAM FASTCALL MsqGetMessageExtraInfo(VOID);
 VOID APIENTRY MsqRemoveWindowMessagesFromQueue(PVOID pWindow); /* F*(&$ headers, will be gone in the rewrite! */
index 63dfba7..ed1e645 100644 (file)
@@ -96,6 +96,7 @@ typedef struct _THREADINFO
     LIST_ENTRY          PtiLink;
     POINT               ptLast;
 
+    LIST_ENTRY          aphkStart[NB_HOOKS];
     CLIENTTHREADINFO    cti;  // Used only when no Desktop or pcti NULL.
   /* ReactOS */
   LIST_ENTRY WindowListHead;
@@ -150,6 +151,8 @@ typedef struct _W32PROCESS
   LIST_ENTRY    GDIBrushAttrFreeList;
 } W32PROCESS, *PW32PROCESS;
 
+#define CLIBS 32
+
 typedef struct _PROCESSINFO
 {
   W32PROCESS;
@@ -158,11 +161,15 @@ typedef struct _PROCESSINFO
   struct _DESKTOP* rpdeskStartup;
   PCLS pclsPrivateList;
   PCLS pclsPublicList;
-
+  DWORD dwhmodLibLoadedMask;
+  HANDLE ahmodLibLoaded[CLIBS];
+  struct _WINSTATION_OBJECT *prpwinsta;
+  HWINSTA hwinsta;
+  ACCESS_MASK amwinsta;
+  DWORD dwHotkey;
   HMONITOR hMonitor;
-
+  LUID luidSession;
   USERSTARTUPINFO usi;
-  ULONG Flags;
   DWORD dwLayout;
   DWORD dwRegisteredClasses;
   /* ReactOS */
index a91183a..39a55b2 100644 (file)
@@ -104,7 +104,7 @@ IntShowOwnedPopups( PWND owner, BOOL fShow );
 LRESULT FASTCALL
 IntDefWindowProc( PWND Window, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL Ansi);
 
-VOID FASTCALL IntNotifyWinEvent(DWORD, PWND, LONG, LONG);
+VOID FASTCALL IntNotifyWinEvent(DWORD, PWND, LONG, LONG, DWORD);
 
 PWND FASTCALL co_UserCreateWindowEx(CREATESTRUCTW*, PUNICODE_STRING, PLARGE_STRING);
 WNDPROC FASTCALL IntGetWindowProc(PWND,BOOL);
index 0c992c0..603dd94 100644 (file)
@@ -175,6 +175,7 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
 {
     struct _EPROCESS *Process;
     PTHREADINFO Win32Thread;
+    int i;
     DECLARE_RETURN(NTSTATUS);
 
     DPRINT("Enter Win32kThreadCallback\n");
@@ -214,6 +215,10 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
       InitializeListHead(&Win32Thread->WindowListHead);
       InitializeListHead(&Win32Thread->W32CallbackListHead);
       InitializeListHead(&Win32Thread->PtiLink);
+      for (i = 0; i < NB_HOOKS; i++)
+      {
+         InitializeListHead(&Win32Thread->aphkStart[i]);
+      }
 
       /*
        * inherit the thread desktop and process window station (if not yet inherited) from the process startup
@@ -290,6 +295,7 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
       Win32Thread->TIF_flags |= TIF_INCLEANUP;
       DceFreeThreadDCE(Win32Thread);
       HOOK_DestroyThreadHooks(Thread);
+      EVENT_DestroyThreadEvents(Thread);
       /* Cleanup timers */
       DestroyTimersForThread(Win32Thread);
       KeSetEvent(Win32Thread->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
index e536d4c..997cd4f 100644 (file)
@@ -324,20 +324,20 @@ co_IntCallHookProc(INT HookId,
                    PUNICODE_STRING ModuleName)
 {
    ULONG ArgumentLength;
-   PVOID Argument;
+   PVOID Argument = NULL;
    LRESULT Result = 0;
    NTSTATUS Status;
    PVOID ResultPointer;
    ULONG ResultLength;
    PHOOKPROC_CALLBACK_ARGUMENTS Common;
-   CBT_CREATEWNDW *CbtCreateWnd =NULL;
+   CBT_CREATEWNDW *CbtCreateWnd = NULL;
    PCHAR Extra;
    PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL;
-   UNICODE_STRING WindowName;
-   UNICODE_STRING ClassName;
-   PANSI_STRING asWindowName;
-   PANSI_STRING asClassName;
+   UNICODE_STRING WindowName, ClassName;
+   ANSI_STRING asWindowName, asClassName;
    PTHREADINFO pti;
+   PWND pWnd;
+   BOOL Hit = FALSE;
 
    ASSERT(Proc);
 
@@ -356,33 +356,67 @@ co_IntCallHookProc(INT HookId,
          switch(Code)
          {
             case HCBT_CREATEWND:
+               pWnd = UserGetWindowObject((HWND) wParam);
+               if (!pWnd)
+               {
+                  DPRINT1("WH_CBT HCBT_CREATEWND wParam bad hWnd!\n");
+                  goto Fault_Exit;
+               }
+
                CbtCreateWnd = (CBT_CREATEWNDW *) lParam;
                ArgumentLength += sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS);
 
-               asWindowName = (PANSI_STRING)&WindowName;
-               asClassName = (PANSI_STRING)&ClassName;
-
                if (Ansi)
                {
-                  RtlInitAnsiString(asWindowName, (PCSZ)CbtCreateWnd->lpcs->lpszName);
-                  ArgumentLength += WindowName.Length + sizeof(CHAR);
+                  RtlInitAnsiString(&asWindowName, NULL);
+                  _SEH2_TRY
+                  {
+                     ProbeForRead(CbtCreateWnd->lpcs->lpszName, sizeof(CHAR), 1);
+                  }
+                  _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                  {
+                     Hit = TRUE;
+                  }
+                  _SEH2_END;
+                  if (Hit) // Client is at deaths door.
+                     goto Fault_Exit;
+                  if (CbtCreateWnd->lpcs->lpszName)
+                     RtlInitAnsiString(&asWindowName, (PCSZ)CbtCreateWnd->lpcs->lpszName);
+                  ArgumentLength += asWindowName.Length + sizeof(CHAR);
                }
                else
                {
-                  RtlInitUnicodeString(&WindowName, CbtCreateWnd->lpcs->lpszName);
+                  RtlInitUnicodeString(&WindowName, NULL);
+                  _SEH2_TRY
+                  {
+                     ProbeForRead(CbtCreateWnd->lpcs->lpszName, sizeof(WCHAR), 1);
+                  }
+                  _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                  {
+                     Hit = TRUE;
+                  }
+                  _SEH2_END;
+                  if (Hit)
+                     goto Fault_Exit;
+                  if (CbtCreateWnd->lpcs->lpszName)
+                     RtlInitUnicodeString(&WindowName, CbtCreateWnd->lpcs->lpszName);
                   ArgumentLength += WindowName.Length + sizeof(WCHAR);
                }
 
-               if (! IS_ATOM(CbtCreateWnd->lpcs->lpszClass))
+               if (!IS_ATOM(CbtCreateWnd->lpcs->lpszClass))
                {
                   if (Ansi)
                   {
-                     RtlInitAnsiString(asClassName, (PCSZ)CbtCreateWnd->lpcs->lpszClass);
-                     ArgumentLength += ClassName.Length + sizeof(CHAR);
+                     RtlInitAnsiString(&asClassName, NULL);
+                     if (CbtCreateWnd->lpcs->lpszClass)
+                        RtlInitAnsiString(&asClassName, (PCSZ)CbtCreateWnd->lpcs->lpszClass);
+                     ArgumentLength += asClassName.Length + sizeof(CHAR);
                   }
                   else
                   {
-                     RtlInitUnicodeString(&ClassName, CbtCreateWnd->lpcs->lpszClass);
+                     RtlInitUnicodeString(&ClassName, NULL);
+                     if (CbtCreateWnd->lpcs->lpszClass)
+                        RtlInitUnicodeString(&ClassName, CbtCreateWnd->lpcs->lpszClass);
                      ArgumentLength += ClassName.Length + sizeof(WCHAR);
                   }
                }
@@ -408,7 +442,7 @@ co_IntCallHookProc(INT HookId,
                break;
             default:
                DPRINT1("Trying to call unsupported CBT hook %d\n", Code);
-               return 0;
+               goto Fault_Exit;
          }
          break;
       case WH_KEYBOARD_LL:
@@ -437,14 +471,14 @@ co_IntCallHookProc(INT HookId,
          break;
       default:
          DPRINT1("Trying to call unsupported window hook %d\n", HookId);
-         return 0;
+         goto Fault_Exit;
    }
 
    Argument = IntCbAllocateMemory(ArgumentLength);
    if (NULL == Argument)
    {
       DPRINT1("HookProc callback failed: out of memory\n");
-      return 0;
+      goto Fault_Exit;
    }
    Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Argument;
    Common->HookId = HookId;
@@ -454,7 +488,8 @@ co_IntCallHookProc(INT HookId,
    Common->Proc = Proc;
    Common->Ansi = Ansi;
    Common->ModuleNameLength = ModuleName->Length;
-   memcpy(Common->ModuleName, ModuleName->Buffer, ModuleName->Length);
+   if (ModuleName->Buffer)
+      RtlCopyMemory(Common->ModuleName, ModuleName->Buffer, ModuleName->Length);
    Extra = (PCHAR) Common->ModuleName + Common->ModuleNameLength;
 
    switch(HookId)
@@ -468,32 +503,53 @@ co_IntCallHookProc(INT HookId,
                RtlCopyMemory( &CbtCreatewndExtra->Cs, CbtCreateWnd->lpcs, sizeof(CREATESTRUCTW) );
                CbtCreatewndExtra->WndInsertAfter = CbtCreateWnd->hwndInsertAfter;
                Extra = (PCHAR) (CbtCreatewndExtra + 1);
-               RtlCopyMemory(Extra, WindowName.Buffer, WindowName.Length);
-               CbtCreatewndExtra->Cs.lpszName = (LPCWSTR) (Extra - (PCHAR) CbtCreatewndExtra);
-               CbtCreatewndExtra->Cs.lpszClass = ClassName.Buffer;
-               Extra += WindowName.Length;
+               CbtCreatewndExtra->Cs.lpszClass = ClassName.Buffer; // if Atom
+
                if (Ansi)
                {
+                 if (asWindowName.Buffer)
+                    RtlCopyMemory(Extra, asWindowName.Buffer, asWindowName.Length);
+                 CbtCreatewndExtra->Cs.lpszName = (LPCWSTR) (Extra - (PCHAR) CbtCreatewndExtra);
+                 Extra += asWindowName.Length;
+
                  *((CHAR *) Extra) = '\0';
                  Extra += sizeof(CHAR);
                }
                else
                {
+                 if (asWindowName.Buffer)
+                    RtlCopyMemory(Extra, WindowName.Buffer, WindowName.Length);
+                 CbtCreatewndExtra->Cs.lpszName = (LPCWSTR) (Extra - (PCHAR) CbtCreatewndExtra);
+                 Extra += WindowName.Length;
+
                  *((WCHAR *) Extra) = L'\0';
                  Extra += sizeof(WCHAR);
                }
 
-               if (! IS_ATOM(ClassName.Buffer))
+               if (!IS_ATOM(ClassName.Buffer))
                {
-                  RtlCopyMemory(Extra, ClassName.Buffer, ClassName.Length);
-                  CbtCreatewndExtra->Cs.lpszClass =
-                     (LPCWSTR)(ULONG_PTR) MAKELONG(Extra - (PCHAR) CbtCreatewndExtra, 1);
-                  Extra += ClassName.Length;
-
                   if (Ansi)
+                  {
+                     if (asClassName.Buffer)
+                        RtlCopyMemory(Extra, asClassName.Buffer, asClassName.Length);
+                     CbtCreatewndExtra->Cs.lpszClass =
+                        (LPCWSTR)(ULONG_PTR) MAKELONG(Extra - (PCHAR) CbtCreatewndExtra, 1);
+                     Extra += asClassName.Length;
+
                      *((CHAR *) Extra) = '\0';
+                     Extra += sizeof(CHAR);
+                  }
                   else
+                  {
+                     if (ClassName.Buffer)
+                        RtlCopyMemory(Extra, ClassName.Buffer, ClassName.Length);
+                     CbtCreatewndExtra->Cs.lpszClass =
+                        (LPCWSTR)(ULONG_PTR) MAKELONG(Extra - (PCHAR) CbtCreatewndExtra, 1);
+                     Extra += ClassName.Length;
+
                      *((WCHAR *) Extra) = L'\0';
+                     Extra += sizeof(WCHAR);
+                  }
                }
                break;
             case HCBT_CLICKSKIPPED:
@@ -535,7 +591,6 @@ co_IntCallHookProc(INT HookId,
       case WH_GETMESSAGE:
          RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSG));
          Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
-//         DPRINT1("KHOOK Memory: %x\n",Common);
          break;
       case WH_FOREGROUNDIDLE:
       case WH_KEYBOARD:
@@ -565,37 +620,47 @@ co_IntCallHookProc(INT HookId,
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
       Result = 0;
+      Hit = TRUE;
    }
    _SEH2_END;
 
    if (!NT_SUCCESS(Status))
    {
-      return 0;
+      goto Fault_Exit;
    }
-
-   if (HookId == WH_CBT && Code == HCBT_CREATEWND)
+   /* Support write backs... SEH is in UserCallNextHookEx. */
+   switch (HookId)
    {
-      if (CbtCreatewndExtra)
-      {
-         _SEH2_TRY
-         { /*
-              The parameters could have been changed, include the coordinates
-              and dimensions of the window. We copy it back.
-            */
-            CbtCreateWnd->hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
-            CbtCreateWnd->lpcs->x  = CbtCreatewndExtra->Cs.x;
-            CbtCreateWnd->lpcs->y  = CbtCreatewndExtra->Cs.y;
-            CbtCreateWnd->lpcs->cx = CbtCreatewndExtra->Cs.cx;
-            CbtCreateWnd->lpcs->cy = CbtCreatewndExtra->Cs.cy;
+      case WH_CBT:
+         if (Code == HCBT_CREATEWND)
+         {
+            if (CbtCreatewndExtra)
+            {/*
+               The parameters could have been changed, include the coordinates
+               and dimensions of the window. We copy it back.
+              */
+               CbtCreateWnd->hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
+               CbtCreateWnd->lpcs->x  = CbtCreatewndExtra->Cs.x;
+               CbtCreateWnd->lpcs->y  = CbtCreatewndExtra->Cs.y;
+               CbtCreateWnd->lpcs->cx = CbtCreatewndExtra->Cs.cx;
+               CbtCreateWnd->lpcs->cy = CbtCreatewndExtra->Cs.cy;
+            }
          }
-         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+         break;
+      // "The GetMsgProc hook procedure can examine or modify the message."
+      case WH_GETMESSAGE:
+         if (lParam)
          {
-            Result = 0;
+            RtlCopyMemory((PVOID) lParam, Extra, sizeof(MSG));
          }
-         _SEH2_END;
-      }
+         break;
    }
 
+Fault_Exit:
+   if (Hit)
+   {
+      DPRINT1("Exception CallHookProc HookId %d Code %d\n",HookId,Code);
+   }
    if (Argument) IntCbFreeMemory(Argument);
 
    return Result;
index 3ebae7a..76d58a7 100644 (file)
@@ -30,10 +30,13 @@ static
 BOOL FASTCALL
 co_IntHideCaret(PTHRDCARETINFO CaretInfo)
 {
+   PWND pWnd;
    if(CaretInfo->hWnd && CaretInfo->Visible && CaretInfo->Showing)
    {
+      pWnd = UserGetWindowObject(CaretInfo->hWnd);
       co_IntSendMessage(CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0);
       CaretInfo->Showing = 0;
+      IntNotifyWinEvent(EVENT_OBJECT_HIDE, pWnd, OBJID_CARET, CHILDID_SELF, 0);
       return TRUE;
    }
    return FALSE;
@@ -43,17 +46,20 @@ BOOL FASTCALL
 co_IntDestroyCaret(PTHREADINFO Win32Thread)
 {
    PUSER_MESSAGE_QUEUE ThreadQueue;
+   PWND pWnd;
    ThreadQueue = (PUSER_MESSAGE_QUEUE)Win32Thread->MessageQueue;
 
    if(!ThreadQueue || !ThreadQueue->CaretInfo)
       return FALSE;
 
+   pWnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd);
    co_IntHideCaret(ThreadQueue->CaretInfo);
    ThreadQueue->CaretInfo->Bitmap = (HBITMAP)0;
    ThreadQueue->CaretInfo->hWnd = (HWND)0;
    ThreadQueue->CaretInfo->Size.cx = ThreadQueue->CaretInfo->Size.cy = 0;
    ThreadQueue->CaretInfo->Showing = 0;
    ThreadQueue->CaretInfo->Visible = 0;
+   IntNotifyWinEvent(EVENT_OBJECT_DESTROY, pWnd, OBJID_CARET, CHILDID_SELF, 0);
    return TRUE;
 }
 
@@ -176,6 +182,7 @@ BOOL FASTCALL
 co_IntSetCaretPos(int X, int Y)
 {
    PTHREADINFO pti;
+   PWND pWnd;
    PUSER_MESSAGE_QUEUE ThreadQueue;
 
    pti = PsGetCurrentThreadWin32Thread();
@@ -183,6 +190,7 @@ co_IntSetCaretPos(int X, int Y)
 
    if(ThreadQueue->CaretInfo->hWnd)
    {
+      pWnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd);
       if(ThreadQueue->CaretInfo->Pos.x != X || ThreadQueue->CaretInfo->Pos.y != Y)
       {
          co_IntHideCaret(ThreadQueue->CaretInfo);
@@ -191,6 +199,7 @@ co_IntSetCaretPos(int X, int Y)
          ThreadQueue->CaretInfo->Pos.y = Y;
          co_IntSendMessage(ThreadQueue->CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0);
          IntSetTimer(UserGetWindowObject(ThreadQueue->CaretInfo->hWnd), IDCARETTIMER, IntGetCaretBlinkTime(), NULL, TMRF_SYSTEM);
+         IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, pWnd, OBJID_CARET, CHILDID_SELF, 0);
       }
       return TRUE;
    }
@@ -277,6 +286,7 @@ BOOL FASTCALL co_UserHideCaret(PWND Window OPTIONAL)
 BOOL FASTCALL co_UserShowCaret(PWND Window OPTIONAL)
 {
    PTHREADINFO pti;
+   PWND pWnd;
    PUSER_MESSAGE_QUEUE ThreadQueue;
 
    if (Window) ASSERT_REFS_CO(Window);
@@ -301,11 +311,12 @@ BOOL FASTCALL co_UserShowCaret(PWND Window OPTIONAL)
       ThreadQueue->CaretInfo->Visible = 1;
       if(!ThreadQueue->CaretInfo->Showing)
       {
+         pWnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd);
          co_IntSendMessage(ThreadQueue->CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0);
+         IntNotifyWinEvent(EVENT_OBJECT_SHOW, pWnd, OBJID_CARET, OBJID_CARET, 0);
       }
       IntSetTimer(UserGetWindowObject(ThreadQueue->CaretInfo->hWnd), IDCARETTIMER, IntGetCaretBlinkTime(), NULL, TMRF_SYSTEM);
    }
-
    return TRUE;
 }
 
@@ -370,7 +381,7 @@ NtUserCreateCaret(
    }
    ThreadQueue->CaretInfo->Visible = 0;
    ThreadQueue->CaretInfo->Showing = 0;
-
+   IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_CARET, CHILDID_SELF, 0);
    RETURN(TRUE);
 
 CLEANUP:
index 3a054f2..5933311 100644 (file)
@@ -884,6 +884,7 @@ NtUserCreateDesktop(
    LARGE_STRING WindowName;
    PWND pWnd = NULL;
    CREATESTRUCTW Cs;
+   INT i;
    DECLARE_RETURN(HDESK);
 
    DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName);
@@ -1026,6 +1027,11 @@ NtUserCreateDesktop(
    /* Initialize some local (to win32k) desktop state. */
    InitializeListHead(&DesktopObject->PtiList);
    DesktopObject->ActiveMessageQueue = NULL;
+   /* Setup Global Hooks. */
+   for (i = 0; i < NB_HOOKS; i++)
+   {
+      InitializeListHead(&DesktopObject->pDeskInfo->aphkStart[i]);
+   }
    ExFreePoolWithTag(DesktopName.Buffer, TAG_STRING);
 
    if (! NT_SUCCESS(Status))
index 02d2ffe..2c5a91e 100644 (file)
@@ -2,7 +2,7 @@
  * COPYRIGHT:         See COPYING in the top level directory
  * PROJECT:           ReactOS kernel
  * PURPOSE:           Window event handlers
- * FILE:              subsystem/win32/win32k/ntuser/event.c
+ * FILE:              subsystems/win32/win32k/ntuser/event.c
  * PROGRAMER:         James Tabor (james.tabor@rectos.org)
  */
 
@@ -103,12 +103,15 @@ IntCallLowLevelEvent( PEVENTHOOK pEH,
                         LONG idChild)
 {
    NTSTATUS Status;
-   ULONG_PTR uResult;
-   EVENTPACK EP;
+   PEVENTPACK pEP;
+   ULONG_PTR uResult = 0;
 
-   EP.pEH = pEH;
-   EP.idObject = idObject;
-   EP.idChild = idChild;
+   pEP = ExAllocatePoolWithTag(NonPagedPool, sizeof(EVENTPACK), TAG_HOOK);
+   if (!pEP) return 0;
+
+   pEP->pEH = pEH;
+   pEP->idObject = idObject;
+   pEP->idChild = idChild;
 
    /* FIXME should get timeout from
     * HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
@@ -116,16 +119,18 @@ IntCallLowLevelEvent( PEVENTHOOK pEH,
                                hwnd,
                                event,
                                0,
-                              (LPARAM)&EP,
+                              (LPARAM)pEP,
                                5000,
                                TRUE,
                                MSQ_ISEVENT,
                               &uResult);
-
+   if (!NT_SUCCESS(Status))
+   { 
+      ExFreePoolWithTag(pEP, TAG_HOOK);
+   }
    return NT_SUCCESS(Status) ? uResult : 0;
 }
 
-
 static
 BOOL
 FASTCALL
@@ -145,14 +150,49 @@ IntRemoveEvent(PEVENTHOOK pEH)
    return FALSE;
 }
 
+VOID
+FASTCALL
+EVENT_DestroyThreadEvents(PETHREAD Thread)
+{
+   PTHREADINFO pti;
+   PEVENTHOOK pEH;
+   PLIST_ENTRY pLE;
+
+   pti = Thread->Tcb.Win32Thread;
+   if (!pti) return;
+
+   if (!GlobalEvents || !GlobalEvents->Counts) return;
+
+   pLE = GlobalEvents->Events.Flink;
+   if (IsListEmpty(pLE)) return;
+
+   pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
+   do
+   {
+      if (IsListEmpty(pLE)) break;
+      if (!pEH) break;
+      pLE = pEH->Chain.Flink;
+      if (pEH->head.pti == pti)
+      {
+         IntRemoveEvent(pEH);
+      }
+      pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
+   } while (pLE != &GlobalEvents->Events);
+
+   return;
+}
+
 /* FUNCTIONS *****************************************************************/
 
+//
+// Dispatch MsgQueue Event Call processor!
+//
 LRESULT
 FASTCALL
 co_EVENT_CallEvents( DWORD event,
-                       HWND hwnd, 
-                    UINT_PTR idObject,
-                    LONG_PTR idChild)
+                     HWND hwnd, 
+                     UINT_PTR idObject,
+                     LONG_PTR idChild)
 {
    PEVENTHOOK pEH;
    LRESULT Result;
@@ -165,9 +205,11 @@ co_EVENT_CallEvents( DWORD event,
                                  hwnd,
                                  pEP->idObject,
                                  pEP->idChild,
-                                (DWORD_PTR)(NtCurrentTeb()->ClientId).UniqueThread,
+                                 PtrToUint(NtCurrentTeb()->ClientId.UniqueThread),
                                 (DWORD)EngGetTickCount(),
                                  pEH->Proc);
+
+   ExFreePoolWithTag(pEP, TAG_HOOK);
    return Result;
 }
 
@@ -177,55 +219,66 @@ IntNotifyWinEvent(
    DWORD Event,
    PWND  pWnd,
    LONG  idObject,
-   LONG  idChild)
+   LONG  idChild,
+   DWORD flags)
 {
    PEVENTHOOK pEH;
    PLIST_ENTRY pLE;
+   PTHREADINFO pti, ptiCurrent;
 
    DPRINT("IntNotifyWinEvent GlobalEvents = 0x%x pWnd 0x%x\n",GlobalEvents, pWnd);
 
-   if (!pWnd) return;
+   if (!GlobalEvents || !GlobalEvents->Counts) return;
 
    if (pWnd && pWnd->state & WNDS_DESTROYED) return;
 
-   if (!GlobalEvents || !GlobalEvents->Counts) return;
+   ptiCurrent = PsGetCurrentThreadWin32Thread();
+
+   if (pWnd && flags & WEF_SETBYWNDPTI)
+      pti = pWnd->head.pti;
+   else
+      pti = ptiCurrent;
 
    pLE = GlobalEvents->Events.Flink;
    pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
    do
-   { 
+   {
+     if (!pEH) break;
      UserReferenceObject(pEH);
      // Must be inside the event window.
      if ( (pEH->eventMin <= Event) && (pEH->eventMax >= Event))
      {
-        if (pEH->head.pti->pEThread != PsGetCurrentThread())
-        { // if all process || all thread || other thread same process
-           if (!(pEH->idProcess) || !(pEH->idThread) || 
-               (NtCurrentTeb()->ClientId.UniqueProcess == (PVOID)(DWORD_PTR)pEH->idProcess))
+// if all process || all thread || other thread same process
+// if ^skip own thread && ((Pid && CPid == Pid && ^skip own process) || all process)
+        if ( (!pEH->idProcess || pEH->idProcess == PtrToUint(pti->pEThread->Cid.UniqueProcess)) &&
+             (!(pEH->Flags & WINEVENT_SKIPOWNPROCESS) || pEH->head.pti->ppi != pti->ppi) &&
+             (!pEH->idThread  || pEH->idThread == PtrToUint(pti->pEThread->Cid.UniqueThread)) &&
+             (!(pEH->Flags & WINEVENT_SKIPOWNTHREAD)  || pEH->head.pti != pti) &&
+               pEH->head.pti->rpdesk == ptiCurrent->rpdesk ) // Same as hooks.
+        {
+           // Send message to the thread if pEH is not current.
+           if (pEH->head.pti != ptiCurrent)
            {
+              DPRINT1("Global Event 0x%x, idObject %d\n", Event, idObject);
               IntCallLowLevelEvent( pEH,
                                     Event,
                                     UserHMGetHandle(pWnd),
                                     idObject,
                                     idChild);
            }
-        }// if ^skip own thread && ((Pid && CPid == Pid && ^skip own process) || all process)
-        else if ( !(pEH->Flags & WINEVENT_SKIPOWNTHREAD) &&
-                   ( ((pEH->idProcess &&
-                     NtCurrentTeb()->ClientId.UniqueProcess == (PVOID)(DWORD_PTR)pEH->idProcess) &&
-                     !(pEH->Flags & WINEVENT_SKIPOWNPROCESS)) ||
-                     !pEH->idProcess ) )
-        {
-            // What in the deuce is this right-aligned formatting?
-           co_IntCallEventProc(          UserHMGetHandle(pEH),
-                                                        Event,
-                                        UserHMGetHandle(pWnd),
-                                                     idObject,
-                                                      idChild,
-             PtrToUint(NtCurrentTeb()->ClientId.UniqueThread),
-                                     (DWORD)EngGetTickCount(),
-                                                    pEH->Proc);
-        }
+           else
+           {
+              DPRINT1("Local Event 0x%x, idObject %d\n", Event, idObject);
+              co_IntCallEventProc( UserHMGetHandle(pEH),
+                                   Event,
+                                   UserHMGetHandle(pWnd),
+                                   idObject,
+                                   idChild,
+                                   PtrToUint(NtCurrentTeb()->ClientId.UniqueThread),
+                                  (DWORD)EngGetTickCount(),
+                                   pEH->Proc);
+           }
+        }        
      }
      UserDereferenceObject(pEH);
      pLE = pEH->Chain.Flink;
@@ -255,7 +308,7 @@ NtUserNotifyWinEvent(
    if (gpsi->dwInstalledEventHooks & GetMaskFromEvent(Event))
    {
       UserRefObjectCo(Window, &Ref);
-      IntNotifyWinEvent( Event, Window, idObject, idChild);
+      IntNotifyWinEvent( Event, Window, idObject, idChild, WEF_SETBYWNDPTI);
       UserDerefObjectCo(Window);
    }
    UserLeave();
@@ -322,7 +375,7 @@ NtUserSetWinEventHook(
          goto SetEventExit;
       }
    }
-
+   // Creator, pti is set here.
    pEH = UserCreateObject(gHandleTable, NULL, &Handle, otEvent, sizeof(EVENTHOOK));
    if (pEH)
    {
@@ -330,16 +383,18 @@ NtUserSetWinEventHook(
       GlobalEvents->Counts++;
 
       UserHMGetHandle(pEH) = Handle;
-      if (Thread)
-         pEH->head.pti = Thread->Tcb.Win32Thread;
-      else
-         pEH->head.pti = GetW32ThreadInfo();
       pEH->eventMin  = eventMin;
       pEH->eventMax  = eventMax;
-      pEH->idProcess = idProcess;
-      pEH->idThread  = idThread;
+      pEH->idProcess = idProcess; // These are cmp'ed
+      pEH->idThread  = idThread;  //  "
       pEH->Flags     = dwflags;
-
+    /*
+       If WINEVENT_INCONTEXT, set offset from hmod and proc. Save ihmod from
+       the atom index table where the hmod data is saved to be recalled later
+       if fSync set by WINEVENT_INCONTEXT.
+       If WINEVENT_OUTOFCONTEXT just use proc..
+       Do this instead....
+     */
       if (NULL != hmodWinEventProc)
       {
          pEH->offPfn = (ULONG_PTR)((char *)lpfnWinEventProc - (char *)hmodWinEventProc);
index 5832eaf..414b152 100644 (file)
@@ -165,6 +165,7 @@ co_IntSendKillFocusMessages(HWND hWndPrev, HWND hWnd)
 {
    if (hWndPrev)
    {
+      IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0);
       co_IntPostOrSendMessage(hWndPrev, WM_KILLFOCUS, (WPARAM)hWnd, 0);
    }
 }
@@ -174,6 +175,8 @@ co_IntSendSetFocusMessages(HWND hWndPrev, HWND hWnd)
 {
    if (hWnd)
    {
+      PWND pWnd = UserGetWindowObject(hWnd);
+      IntNotifyWinEvent(EVENT_OBJECT_FOCUS, pWnd, OBJID_CLIENT, CHILDID_SELF, 0);
       co_IntPostOrSendMessage(hWnd, WM_SETFOCUS, (WPARAM)hWndPrev, 0);
    }
 }
@@ -356,8 +359,10 @@ co_IntSetActiveWindow(PWND Wnd OPTIONAL)
    cbt.fMouse     = FALSE;
    cbt.hWndActive = hWndPrev;
    if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt))
+   {
+      DPRINT1("SetActiveWindow WH_CBT Call Hook return!\n");
       return 0;
-
+   }
    ThreadQueue->ActiveWindow = hWnd;
 
    co_IntSendDeactivateMessages(hWndPrev, hWnd);
@@ -392,9 +397,11 @@ co_IntSetFocusWindow(PWND Window OPTIONAL)
          return hWndPrev;
       }
 
-     if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev))
-        return 0;
-
+      if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev))
+      {
+         DPRINT1("SetFocusWindow 1 WH_CBT Call Hook return!\n");
+         return 0;
+      }
       ThreadQueue->FocusWindow = Window->head.h;
 
       co_IntSendKillFocusMessages(hWndPrev, Window->head.h);
@@ -403,9 +410,11 @@ co_IntSetFocusWindow(PWND Window OPTIONAL)
    else
    {
       ThreadQueue->FocusWindow = 0;
-
-     if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev))
-        return 0;
+      if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev))
+      {
+         DPRINT1("SetFocusWindow 2 WH_CBT Call Hook return!\n");
+         return 0;
+      }
 
       co_IntSendKillFocusMessages(hWndPrev, 0);
    }
@@ -533,7 +542,7 @@ NtUserSetCapture(HWND hWnd)
 {
    PTHREADINFO pti;
    PUSER_MESSAGE_QUEUE ThreadQueue;
-   PWND Window;
+   PWND Window, pWnd;
    HWND hWndPrev;
    DECLARE_RETURN(HWND);
 
@@ -553,13 +562,23 @@ NtUserSetCapture(HWND hWnd)
 
    hWndPrev = MsqSetStateWindow(ThreadQueue, MSQ_STATE_CAPTURE, hWnd);
 
+   if (hWndPrev)
+   {
+      pWnd = UserGetWindowObject(hWndPrev);
+      if (pWnd)
+         IntNotifyWinEvent(EVENT_SYSTEM_CAPTUREEND, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
+   }
+
    /* also remove other windows if not capturing anymore */
-   if(hWnd == NULL)
+   if (hWnd == NULL)
    {
       MsqSetStateWindow(ThreadQueue, MSQ_STATE_MENUOWNER, NULL);
       MsqSetStateWindow(ThreadQueue, MSQ_STATE_MOVESIZE, NULL);
    }
 
+   if (Window)
+      IntNotifyWinEvent(EVENT_SYSTEM_CAPTURESTART, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
+
    co_IntPostOrSendMessage(hWndPrev, WM_CAPTURECHANGED, 0, (LPARAM)hWnd);
    ThreadQueue->CaptureWindow = hWnd;
 
index 6b6df54..d83c8c9 100644 (file)
@@ -2,8 +2,10 @@
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
  * PURPOSE:          Window hooks
- * FILE:             subsystem/win32/win32k/ntuser/hook.c
+ * FILE:             subsystems/win32/win32k/ntuser/hook.c
  * PROGRAMER:        Casper S. Hornstrup (chorns@users.sourceforge.net)
+ *                   James Tabor (james.tabor@rectos.org)
+ *
  * REVISION HISTORY:
  *       06-06-2001  CSH  Created
  * NOTE:             Most of this code was adapted from Wine,
 #define NDEBUG
 #include <debug.h>
 
-static PHOOKTABLE GlobalHooks;
-
-
-/* PRIVATE FUNCTIONS *********************************************************/
-
-
-/* create a new hook table */
-static
-PHOOKTABLE
-IntAllocHookTable(void)
-{
-    PHOOKTABLE Table;
-    UINT i;
-
-    Table = ExAllocatePoolWithTag(PagedPool, sizeof(HOOKTABLE), TAG_HOOK);
-    if (NULL != Table)
-    {
-        for (i = 0; i < NB_HOOKS; i++)
-        {
-            InitializeListHead(&Table->Hooks[i]);
-            Table->Counts[i] = 0;
-        }
-    }
-
-    return Table;
-}
-
-
-PHOOK
-FASTCALL
-IntGetHookObject(HHOOK hHook)
+typedef struct _HOOKPACK
 {
-    PHOOK Hook;
-
-    if (!hHook)
-    {
-        SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE);
-        return NULL;
-    }
-
-    Hook = (PHOOK)UserGetObject(gHandleTable, hHook, otHook);
-    if (!Hook)
-    {
-        SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE);
-        return NULL;
-    }
-
-    ASSERT(Hook->head.cLockObj >= 0);
-
-    Hook->head.cLockObj++;
-
-    return Hook;
-}
-
-
-
-/* create a new hook and add it to the specified table */
-static
-PHOOK
-IntAddHook(PETHREAD Thread, int HookId, BOOLEAN Global, PWINSTATION_OBJECT WinStaObj)
-{
-    PTHREADINFO W32Thread;
-    PHOOK Hook;
-    PHOOKTABLE Table = Global ? GlobalHooks : MsqGetHooks(((PTHREADINFO)Thread->Tcb.Win32Thread)->MessageQueue);
-    HANDLE Handle;
-
-    if (NULL == Table)
-    {
-        Table = IntAllocHookTable();
-        if (NULL == Table)
-        {
-            return NULL;
-        }
-        if (Global)
-        {
-            GlobalHooks = Table;
-        }
-        else
-        {
-            MsqSetHooks(((PTHREADINFO)Thread->Tcb.Win32Thread)->MessageQueue, Table);
-        }
-    }
-
-    Hook = UserCreateObject(gHandleTable, NULL, &Handle, otHook, sizeof(HOOK));
-    if (NULL == Hook)
-    {
-        return NULL;
-    }
-
-    Hook->Thread = Thread;
-    Hook->HookId = HookId;
-
-    if (Thread)
-    {
-        W32Thread = ((PTHREADINFO)Thread->Tcb.Win32Thread);
-        ASSERT(W32Thread != NULL);
-        W32Thread->fsHooks |= HOOKID_TO_FLAG(HookId);
-
-        if (W32Thread->pClientInfo)
-           W32Thread->pClientInfo->fsHooks = W32Thread->fsHooks;
-
-        if (W32Thread->pDeskInfo) // Do this for now.
-           W32Thread->pDeskInfo->fsHooks= W32Thread->fsHooks;
+  PHOOK pHk; 
+  LPARAM lParam;
+} HOOKPACK, *PHOOKPACK;
 
-        Hook->head.pti = W32Thread;
-        Hook->head.rpdesk = W32Thread->rpdesk;
-    }
-
-    RtlInitUnicodeString(&Hook->ModuleName, NULL);
-
-    InsertHeadList(&Table->Hooks[HOOKID_TO_INDEX(HookId)], &Hook->Chain);
-
-    return Hook;
-}
-
-/* get the hook table that a given hook belongs to */
-static
-PHOOKTABLE
-FASTCALL
-IntGetTable(PHOOK Hook)
-{
-    if (NULL == Hook->Thread || WH_KEYBOARD_LL == Hook->HookId ||
-        WH_MOUSE_LL == Hook->HookId)
-    {
-        return GlobalHooks;
-    }
-
-    return MsqGetHooks(((PTHREADINFO)Hook->Thread->Tcb.Win32Thread)->MessageQueue);
-}
-
-/* get the first hook in the chain */
-static
-PHOOK
-FASTCALL
-IntGetFirstHook(PHOOKTABLE Table, int HookId)
-{
-    PLIST_ENTRY Elem = Table->Hooks[HOOKID_TO_INDEX(HookId)].Flink;
-
-    return Elem == &Table->Hooks[HOOKID_TO_INDEX(HookId)]
-           ? NULL : CONTAINING_RECORD(Elem, HOOK, Chain);
-}
-
-/* find the first non-deleted hook in the chain */
-static
-PHOOK
-FASTCALL
-IntGetFirstValidHook(PHOOKTABLE Table, int HookId)
-{
-    PHOOK Hook;
-    PLIST_ENTRY Elem;
-
-    Hook = IntGetFirstHook(Table, HookId);
-
-    while (NULL != Hook && NULL == Hook->Proc)
-    {
-        Elem = Hook->Chain.Flink;
-        Hook = (Elem == &Table->Hooks[HOOKID_TO_INDEX(HookId)]
-                ? NULL : CONTAINING_RECORD(Elem, HOOK, Chain));
-    }
-
-    return Hook;
-}
-
-/* find the next hook in the chain, skipping the deleted ones */
-PHOOK
-FASTCALL
-IntGetNextHook(PHOOK Hook)
-{
-    PHOOKTABLE Table = IntGetTable(Hook);
-    int HookId = Hook->HookId;
-    PLIST_ENTRY Elem;
-
-    Elem = Hook->Chain.Flink;
-    while (Elem != &Table->Hooks[HOOKID_TO_INDEX(HookId)])
-    {
-        Hook = CONTAINING_RECORD(Elem, HOOK, Chain);
-        if (NULL != Hook->Proc)
-        {
-            return Hook;
-        }
-    }
-
-    if (NULL != GlobalHooks && Table != GlobalHooks)  /* now search through the global table */
-    {
-        return IntGetFirstValidHook(GlobalHooks, HookId);
-    }
-
-    return NULL;
-}
+/* PRIVATE FUNCTIONS *********************************************************/
 
-/* free a hook, removing it from its chain */
 static
-VOID
+LRESULT
 FASTCALL
-IntFreeHook(PHOOKTABLE Table, PHOOK Hook, PWINSTATION_OBJECT WinStaObj)
-{
-    RemoveEntryList(&Hook->Chain);
-    RtlFreeUnicodeString(&Hook->ModuleName);
-
-    /* Dereference thread if required */
-    if (Hook->Flags & HOOK_THREAD_REFERENCED)
-    {
-        ObDereferenceObject(Hook->Thread);
-    }
-
-    /* Close handle */
-    UserDeleteObject(UserHMGetHandle(Hook), otHook);
-}
-
-/* remove a hook, freeing it if the chain is not in use */
-static
-VOID
-IntRemoveHook(PHOOK Hook, PWINSTATION_OBJECT WinStaObj, BOOL TableAlreadyLocked)
+IntCallLowLevelHook( PHOOK Hook,
+                     INT Code,
+                     WPARAM wParam,
+                     LPARAM lParam)
 {
-    PTHREADINFO W32Thread;
-    PHOOKTABLE Table = IntGetTable(Hook);
-
-    ASSERT(NULL != Table); // At this point this should not be null!
-
-    W32Thread = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread);
-    ASSERT(W32Thread != NULL);
-    W32Thread->fsHooks &= ~HOOKID_TO_FLAG(Hook->HookId);
-
-    GetWin32ClientInfo()->fsHooks = W32Thread->fsHooks;
-
-    if (W32Thread->pDeskInfo) // Do this for now.
-       W32Thread->pDeskInfo->fsHooks= W32Thread->fsHooks;
+    NTSTATUS Status;
+    PTHREADINFO pti;
+    PHOOKPACK pHP;
+    ULONG_PTR uResult = 0;
 
-    if (0 != Table->Counts[HOOKID_TO_INDEX(Hook->HookId)])
-    {
-        Hook->Proc = NULL; /* chain is in use, just mark it and return */
-    }
+    if (Hook->Thread)
+       pti = Hook->Thread->Tcb.Win32Thread;
     else
-    {
-        IntFreeHook(Table, Hook, WinStaObj);
-    }
-}
+       pti = Hook->head.pti;
 
-/* release a hook chain, removing deleted hooks if the use count drops to 0 */
-static
-VOID
-FASTCALL
-IntReleaseHookChain(PHOOKTABLE Table, int HookId, PWINSTATION_OBJECT WinStaObj)
-{
-    PLIST_ENTRY Elem;
-    PHOOK HookObj;
-
-    if (NULL == Table)
-    {
-        return;
-    }
+    pHP = ExAllocatePoolWithTag(NonPagedPool, sizeof(HOOKPACK), TAG_HOOK);
+    if (!pHP) return 0;
 
-    /* use count shouldn't already be 0 */
-    ASSERT(0 != Table->Counts[HOOKID_TO_INDEX(HookId)]);
-
-    if (0 == Table->Counts[HOOKID_TO_INDEX(HookId)])
-    {
-        return;
-    }
-
-    if (0 == --Table->Counts[HOOKID_TO_INDEX(HookId)])
-    {
-        Elem = Table->Hooks[HOOKID_TO_INDEX(HookId)].Flink;
-
-        while (Elem != &Table->Hooks[HOOKID_TO_INDEX(HookId)])
-        {
-            HookObj = CONTAINING_RECORD(Elem, HOOK, Chain);
-            Elem = Elem->Flink;
-
-            if (NULL == HookObj->Proc)
-            {
-                IntFreeHook(Table, HookObj, WinStaObj);
-            }
-        }
-    }
-}
-
-static
-LRESULT
-FASTCALL
-IntCallLowLevelHook(PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam)
-{
-    NTSTATUS Status;
-    ULONG_PTR uResult;
+    pHP->pHk = Hook;
+    pHP->lParam = lParam;
 
     /* FIXME should get timeout from
      * HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
-    Status = co_MsqSendMessage(((PTHREADINFO)Hook->Thread->Tcb.Win32Thread)->MessageQueue,
-                                IntToPtr(Code),
-                                Hook->HookId,
+    Status = co_MsqSendMessage( pti->MessageQueue,
+                                IntToPtr(Code), // hWnd
+                                Hook->HookId,   // Msg
                                 wParam,
-                                lParam,
+                                (LPARAM)pHP,
                                 5000,
                                 TRUE,
                                 MSQ_ISHOOK,
-                                &uResult);
-
-    return NT_SUCCESS(Status) ? uResult : 0;
-}
-
-/*
-  Called from inside kernel space.
- */
-LRESULT
-FASTCALL
-co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
-{
-    PHOOK Hook, SaveHook;
-    PTHREADINFO pti;
-    PCLIENTINFO ClientInfo;
-    PHOOKTABLE Table;
-    LRESULT Result;
-    PWINSTATION_OBJECT WinStaObj;
-    NTSTATUS Status;
-
-    ASSERT(WH_MINHOOK <= HookId && HookId <= WH_MAXHOOK);
-
-#if 0
-    /* FIXME! Check pDeskInfo->fsHooks for global hooks! */
-    if (!ISITHOOKED(HookId))
-    {
-        return 0;
-    }
-#endif
-
-    pti = PsGetCurrentThreadWin32Thread();
-    if (!pti)
-    {
-        Table = NULL;
-    }
-    else
-    {
-        Table = MsqGetHooks(pti->MessageQueue);
-    }
-
-    if (NULL == Table || ! (Hook = IntGetFirstValidHook(Table, HookId)))
-    {
-        /* try global table */
-        Table = GlobalHooks;
-        if (NULL == Table || ! (Hook = IntGetFirstValidHook(Table, HookId)))
-        {
-            return 0;  /* no hook set */
-        }
-    }
-
-    if ((Hook->Thread != PsGetCurrentThread()) && (Hook->Thread != NULL))
-    {
-        DPRINT1("\nHook found by Id and posted to Thread! %d\n",HookId );
-        /* Post it in message queue. */
-        return IntCallLowLevelHook(Hook, Code, wParam, lParam);
-    }
-
-    Table->Counts[HOOKID_TO_INDEX(HookId)]++;
-    if (Table != GlobalHooks && GlobalHooks != NULL)
-    {
-        GlobalHooks->Counts[HOOKID_TO_INDEX(HookId)]++;
-    }
-
-    ClientInfo = GetWin32ClientInfo();
-    SaveHook = ClientInfo->phkCurrent;
-    ClientInfo->phkCurrent = Hook;     /* Load the call. */
-
-    Result = co_IntCallHookProc(HookId,
-                                Code,
-                                wParam,
-                                lParam,
-                                Hook->Proc,
-                                Hook->Ansi,
-                                &Hook->ModuleName);
-
-    ClientInfo->phkCurrent = SaveHook;
-
-    Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
-                                            KernelMode,
-                                            0,
-                                            &WinStaObj);
-
+                               &uResult);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("Invalid window station????\n");
-    }
-    else
-    {
-        IntReleaseHookChain(MsqGetHooks(pti->MessageQueue), HookId, WinStaObj);
-        IntReleaseHookChain(GlobalHooks, HookId, WinStaObj);
-        ObDereferenceObject(WinStaObj);
-    }
-
-    return Result;
-}
-
-VOID
-FASTCALL
-HOOK_DestroyThreadHooks(PETHREAD Thread)
-{
-    int HookId;
-    PLIST_ENTRY Elem;
-    PHOOK HookObj;
-    PWINSTATION_OBJECT WinStaObj;
-    NTSTATUS Status;
-
-    if (NULL != GlobalHooks)
-    {
-        Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
-                                                KernelMode,
-                                                0,
-                                                &WinStaObj);
-
-        if (!NT_SUCCESS(Status))
-        {
-            DPRINT1("Invalid window station????\n");
-            return;
-        }
-
-        for (HookId = WH_MINHOOK; HookId <= WH_MAXHOOK; HookId++)
-        {
-            /* only low-level keyboard/mouse global hooks can be owned by a thread */
-            switch(HookId)
-            {
-                case WH_KEYBOARD_LL:
-                case WH_MOUSE_LL:
-                    Elem = GlobalHooks->Hooks[HOOKID_TO_INDEX(HookId)].Flink;
-
-                    while (Elem != &GlobalHooks->Hooks[HOOKID_TO_INDEX(HookId)])
-                    {
-                        HookObj = CONTAINING_RECORD(Elem, HOOK, Chain);
-                        Elem = Elem->Flink;
-
-                        if (HookObj->Thread == Thread)
-                        {
-                            IntRemoveHook(HookObj, WinStaObj, TRUE);
-                        }
-                    }
-                    break;
-            }
-        }
+       DPRINT1("Error Hook Call SendMsg. %d Status: 0x%x\n", Hook->HookId, Status);
+       ExFreePoolWithTag(pHP, TAG_HOOK);
     }
+    return NT_SUCCESS(Status) ? uResult : 0;
 }
 
 static
 LRESULT
 FASTCALL
-co_HOOK_CallHookNext(PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam)
+co_HOOK_CallHookNext( PHOOK Hook,
+                      INT Code,
+                      WPARAM wParam,
+                      LPARAM lParam)
 {
-    if ((Hook->Thread != PsGetCurrentThread()) && (Hook->Thread != NULL))
+    if ( (Hook->Thread != PsGetCurrentThread()) && (Hook->Thread != NULL) )
     {
-        DPRINT1("CALLING HOOK from another Thread. %d\n", Hook->HookId);
+        DPRINT1("Calling Next HOOK from another Thread. %d\n", Hook->HookId);
         return IntCallLowLevelHook(Hook, Code, wParam, lParam);
     }
 
-    DPRINT("CALLING HOOK %d\n", Hook->HookId);
+    DPRINT("Calling Next HOOK %d\n", Hook->HookId);
 
-    return co_IntCallHookProc(Hook->HookId,
-                              Code,
-                              wParam,
-                              lParam,
-                              Hook->Proc,
-                              Hook->Ansi,
+    return co_IntCallHookProc( Hook->HookId,
+                               Code,
+                               wParam,
+                               lParam,
+                               Hook->Proc,
+                               Hook->Ansi,
                               &Hook->ModuleName);
 }
 
+//
+// Dispatch MsgQueue Hook Call processor!
+//
+LRESULT
+FASTCALL
+co_CallHook( INT HookId,
+             INT Code,
+             WPARAM wParam,
+             LPARAM lParam)
+{
+    LRESULT Result;
+    PHOOK phk;
+    PHOOKPACK pHP = (PHOOKPACK)lParam;
+
+    phk = pHP->pHk;
+    /* The odds are high for this to be a Global call. */
+    Result = co_IntCallHookProc( HookId,
+                                 Code,
+                                 wParam,
+                                 pHP->lParam,
+                                 phk->Proc,
+                                 phk->Ansi,
+                                &phk->ModuleName);
+
+    ExFreePoolWithTag(pHP, TAG_HOOK);
+    return Result;
+}
 
 LRESULT
 FASTCALL
-IntCallDebugHook(PHOOK Hook,
-                 int Code,
-                 WPARAM wParam,
-                 LPARAM lParam)
+IntCallDebugHook( PHOOK Hook,
+                  int Code,
+                  WPARAM wParam,
+                  LPARAM lParam,
+                  BOOL Ansi)
 {
     LRESULT lResult = 0;
     ULONG Size;
@@ -608,16 +253,13 @@ IntCallDebugHook(PHOOK Hook,
     return lResult;
 }
 
-/*
-   Called from user space via CallNextHook.
- */
 LRESULT
 FASTCALL
-UserCallNextHookEx(PHOOK Hook,
-                   int Code,
-                   WPARAM wParam,
-                   LPARAM lParam,
-                   BOOL Ansi)
+UserCallNextHookEx( PHOOK Hook,
+                    int Code,
+                    WPARAM wParam,
+                    LPARAM lParam,
+                    BOOL Ansi)
 {
     LRESULT lResult = 0;
     BOOL BadChk = FALSE;
@@ -1002,7 +644,7 @@ UserCallNextHookEx(PHOOK Hook,
         }
 
         case WH_DEBUG:
-            lResult = IntCallDebugHook(Hook, Code, wParam, lParam);
+            lResult = IntCallDebugHook(Hook, Code, wParam, lParam, Ansi);
             break;
 
         /*
@@ -1018,70 +660,454 @@ UserCallNextHookEx(PHOOK Hook,
             DPRINT1("Unsupported HOOK Id -> %d\n",Hook->HookId);
             break;
     }
-
+    if (Hook->HookId == WH_JOURNALPLAYBACK && lResult == 0)
+       lResult = -1;
     return lResult; 
 }
 
+PHOOK
+FASTCALL
+IntGetHookObject(HHOOK hHook)
+{
+    PHOOK Hook;
+    
+    if (!hHook)
+    {
+       SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE);
+       return NULL;
+    }
+
+    Hook = (PHOOK)UserGetObject(gHandleTable, hHook, otHook);
+    if (!Hook)
+    {
+       SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE);
+       return NULL;
+    }
+
+    UserReferenceObject(Hook);
+
+    return Hook;
+}
+
+/* get the first hook in the chain */
+static
+PHOOK
+FASTCALL
+IntGetFirstHook(PLIST_ENTRY Table)
+{
+    PLIST_ENTRY Elem = Table->Flink;
+
+    if (IsListEmpty(Table)) return NULL;
+
+    return Elem == Table ? NULL : CONTAINING_RECORD(Elem, HOOK, Chain);
+}
+
+/* find the next hook in the chain  */
+PHOOK
+FASTCALL
+IntGetNextHook(PHOOK Hook)
+{
+    int HookId = Hook->HookId;
+    PLIST_ENTRY Elem;
+    PTHREADINFO pti;
+
+    if (Hook->Thread)
+    {
+       pti = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread);
+
+       Elem = Hook->Chain.Flink;
+       if (Elem != &pti->aphkStart[HOOKID_TO_INDEX(HookId)])
+          return CONTAINING_RECORD(Elem, HOOK, Chain);
+    }
+    else
+    {
+       pti = PsGetCurrentThreadWin32Thread();
+
+       Elem = Hook->Chain.Flink;
+       if (Elem != &pti->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)])
+          return CONTAINING_RECORD(Elem, HOOK, Chain);
+    }
+    return NULL;
+}
+
+/* free a hook, removing it from its chain */
+static
+VOID
+FASTCALL
+IntFreeHook(PHOOK Hook)
+{
+    RemoveEntryList(&Hook->Chain);
+    if (Hook->ModuleName.Buffer)
+    {
+       ExFreePoolWithTag(Hook->ModuleName.Buffer, TAG_HOOK);
+       Hook->ModuleName.Buffer = NULL;
+    }
+    /* Close handle */
+    UserDeleteObject(UserHMGetHandle(Hook), otHook);
+}
+
+/* remove a hook, freeing it from the chain */
+static
+BOOL
+FASTCALL
+IntRemoveHook(PHOOK Hook)
+{
+    INT HookId;
+    PTHREADINFO pti;
+
+    HookId = Hook->HookId;
+
+    if (Hook->Thread) // Local
+    {
+       pti = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread);
+
+       IntFreeHook( Hook);
+
+       if ( IsListEmpty(&pti->aphkStart[HOOKID_TO_INDEX(HookId)]) )
+       {
+          pti->fsHooks &= ~HOOKID_TO_FLAG(HookId);
+          _SEH2_TRY
+          {
+             GetWin32ClientInfo()->fsHooks = pti->fsHooks;
+          }
+          _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+          {
+          }
+          _SEH2_END;
+          return TRUE;
+       }
+    }
+    else // Global
+    {
+       IntFreeHook( Hook);
+
+       pti = PsGetCurrentThreadWin32Thread();
+
+       if ( pti->pDeskInfo &&
+            IsListEmpty(&pti->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]) )
+       {
+          pti->pDeskInfo->fsHooks &= ~HOOKID_TO_FLAG(HookId);
+          return TRUE;
+       }
+    }
+    return FALSE;
+}
+
+VOID
+FASTCALL
+HOOK_DestroyThreadHooks(PETHREAD Thread)
+{
+   PTHREADINFO pti;
+   int HookId;
+   PHOOK HookObj;
+   PLIST_ENTRY pElem;
+
+   pti = Thread->Tcb.Win32Thread;
+   if (!pti || !pti->pDeskInfo) return;
+
+// Local Thread cleanup.
+   if (pti->fsHooks)
+   {
+      for (HookId = WH_MINHOOK; HookId <= WH_MAXHOOK; HookId++)
+      {
+         PLIST_ENTRY pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)];
+
+         if (IsListEmpty(pLLE)) continue;
+
+         pElem = pLLE->Flink;
+         HookObj = CONTAINING_RECORD(pElem, HOOK, Chain);
+         do
+         {
+            if (!HookObj) break;
+            if (IntRemoveHook(HookObj)) break;
+            pElem = HookObj->Chain.Flink;
+            HookObj = CONTAINING_RECORD(pElem, HOOK, Chain);
+         }
+         while (pElem != pLLE);
+      }
+      pti->fsHooks = 0;
+   }
+// Global search based on Thread and cleanup.
+   if (pti->pDeskInfo->fsHooks)
+   {
+      for (HookId = WH_MINHOOK; HookId <= WH_MAXHOOK; HookId++)
+      {
+         PLIST_ENTRY pGLE = &pti->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)];
+
+         if (IsListEmpty(pGLE)) continue;
+
+         pElem = pGLE->Flink;
+         HookObj = CONTAINING_RECORD(pElem, HOOK, Chain);
+         do
+         {
+            if (!HookObj) break;
+            if (HookObj->head.pti == pti)
+            {
+               if (IntRemoveHook(HookObj)) break;
+            }
+            pElem = HookObj->Chain.Flink;
+            HookObj = CONTAINING_RECORD(pElem, HOOK, Chain);
+         }
+         while (pElem != pGLE);
+      }
+   }
+   return;
+}
+
+/*
+  Win32k Kernel Space Hook Caller.
+ */
 LRESULT
-APIENTRY
-NtUserCallNextHookEx(int Code,
-                     WPARAM wParam,
-                     LPARAM lParam,
-                     BOOL Ansi)
+FASTCALL
+co_HOOK_CallHooks( INT HookId,
+                   INT Code,
+                   WPARAM wParam,
+                   LPARAM lParam)
 {
-    PHOOK HookObj, NextObj;
+    PHOOK Hook, SaveHook;
+    PTHREADINFO pti;
     PCLIENTINFO ClientInfo;
-    PWINSTATION_OBJECT WinStaObj;
-    NTSTATUS Status;
-    DECLARE_RETURN(LRESULT);
+    PLIST_ENTRY pLLE, pGLE;
+    BOOL Local = FALSE, Global = FALSE;
+    LRESULT Result = 0;
 
-    DPRINT("Enter NtUserCallNextHookEx\n");
-    UserEnterExclusive();
+    ASSERT(WH_MINHOOK <= HookId && HookId <= WH_MAXHOOK);
 
-    Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
-                                            KernelMode,
-                                            0,
-                                            &WinStaObj);
-    if (!NT_SUCCESS(Status))
+    pti = GetW32ThreadInfo(); // Need to call this!
+
+    if (!pti || !pti->pDeskInfo)
+       goto Exit; // Must have a desktop running for hooks.
+
+    if ( pti->TIF_flags & TIF_INCLEANUP)
+       goto Exit;
+
+    if ( ISITHOOKED(HookId) )
     {
-        SetLastNtError(Status);
-        RETURN( 0);
+       DPRINT("Local Hooker %d\n", HookId);
+       Local = TRUE;
     }
 
-    ObDereferenceObject(WinStaObj);
+    if ( pti->pDeskInfo->fsHooks & HOOKID_TO_FLAG(HookId) )
+    {
+       DPRINT("Global Hooker %d\n", HookId);
+       Global = TRUE;
+    }
 
-    ClientInfo = GetWin32ClientInfo();
+    if ( !Local && !Global ) goto Exit; // No work!
 
-    if (!ClientInfo) RETURN( 0);
+    pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)];
+    pGLE = &pti->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)];
+    Hook = NULL;
 
-    HookObj = ClientInfo->phkCurrent;
+    /* SetWindowHookEx sorts out the Thread issue by placing the Hook to
+       the correct Thread if not NULL.
+     */
+    if ( Local )
+    {
+       Hook = IntGetFirstHook(pLLE);
+       if (!Hook)
+       {
+          DPRINT1("No Local Hook Found!\n");
+          goto Exit;
+       }
+       ObReferenceObject(Hook->Thread);
+
+       ClientInfo = pti->pClientInfo;
+       SaveHook = pti->sphkCurrent;
+
+       /* Load it for the next call. */
+       pti->sphkCurrent = Hook;
+       Hook->phkNext = IntGetNextHook(Hook);
+       if (ClientInfo)
+       {
+          _SEH2_TRY
+          {
+             ClientInfo->phkCurrent = Hook;
+          }
+          _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+          {
+             ClientInfo = NULL; // Don't bother next run.
+          }
+          _SEH2_END;
+       }
+       Result = co_IntCallHookProc( HookId,
+                                    Code,
+                                    wParam,
+                                    lParam,
+                                    Hook->Proc,
+                                    Hook->Ansi,
+                                   &Hook->ModuleName);
+       if (ClientInfo)
+       {
+          _SEH2_TRY
+          {
+             ClientInfo->phkCurrent = SaveHook;
+          }
+          _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+          {
+          }
+          _SEH2_END;
+       }
+       pti->sphkCurrent = SaveHook;
+       Hook->phkNext = NULL;
+       ObDereferenceObject(Hook->Thread);
+    }
 
-    if (!HookObj) RETURN( 0);
+    if ( Global )
+    {
+       PTHREADINFO ptiHook;
+
+       Hook = IntGetFirstHook(pGLE);
+       if (!Hook)
+       {
+          DPRINT1("No Global Hook Found!\n");
+          goto Exit;
+       }
+      /* Performance goes down the drain. If more hooks are associated to this
+       * hook ID, this will have to post to each of the thread message queues
+       * or make a direct call.
+       */
+       do
+       {
+         /* Hook->Thread is null, we hax around this with Hook->head.pti. */
+          ptiHook = Hook->head.pti;
+
+         /* "Global hook monitors messages for all threads in the same desktop
+          *  as the calling thread."
+          */
+          if ( ptiHook->TIF_flags & TIF_INCLEANUP ||
+               ptiHook->rpdesk != pti->rpdesk)
+          {
+             Hook = IntGetNextHook(Hook);
+             if (!Hook) break;
+             continue;
+          }
+          // Lockup the thread while this links through user world.
+          ObReferenceObject(ptiHook->pEThread);
+          if (ptiHook != pti )
+          {
+             DPRINT("\nGlobal Hook posting to another Thread! %d\n",HookId );
+             Result = IntCallLowLevelHook(Hook, Code, wParam, lParam);
+          }
+          else
+          { /* Make the direct call. */
+             Result = co_IntCallHookProc( HookId,
+                                          Code,
+                                          wParam,
+                                          lParam,
+                                          Hook->Proc,
+                                          Hook->Ansi,
+                                         &Hook->ModuleName);
+          }
+          ObDereferenceObject(ptiHook->pEThread);
+          Hook = IntGetNextHook(Hook);
+       }
+       while ( Hook );
+       DPRINT("Ret: Global HookId %d Result 0x%x\n", HookId,Result);
+    }
+Exit:
+    if (HookId == WH_JOURNALPLAYBACK && Result == 0)
+       Result = -1;
+    return Result;
+}
+
+BOOL
+FASTCALL
+IntUnhookWindowsHook(int HookId, HOOKPROC pfnFilterProc)
+{
+    PHOOK Hook;
+    PLIST_ENTRY pLLE, pLE;
+    PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+
+    if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId )
+    {
+       SetLastWin32Error(ERROR_INVALID_HOOK_FILTER);
+       return FALSE;
+    }
+
+    if (pti->fsHooks)
+    {
+       pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)];
+
+       if (IsListEmpty(pLLE)) return FALSE;
+
+       pLE = pLLE->Flink;
+       Hook = CONTAINING_RECORD(pLE, HOOK, Chain);
+       do
+       {
+          if (!Hook) break;
+          if (Hook->Proc == pfnFilterProc)
+          {
+             if (Hook->head.pti == pti)
+             {
+                IntRemoveHook(Hook);
+                UserDereferenceObject(Hook);
+                return TRUE;
+             }
+             else
+             {
+                SetLastWin32Error(ERROR_ACCESS_DENIED);
+                return FALSE;
+             }
+          }
+          pLE = Hook->Chain.Flink;
+          Hook = CONTAINING_RECORD(pLE, HOOK, Chain);
+       }
+       while (pLE != pLLE);
+    }
+    return FALSE;
+}
 
-    /* Check that the first hook in the chain is not this hook */
-    NextObj = IntGetFirstHook(IntGetTable(HookObj), HookObj->HookId);
+/*
+ *  Support for compatibility only? Global hooks are processed in kernel space.
+ *  This is very thread specific! Never seeing applications with more than one
+ *  hook per thread installed. Most of the applications are Global hookers and
+ *  associated with just one hook Id. Maybe it's for diagnostic testing or a
+ *  throw back to 3.11?
+ */
+LRESULT
+APIENTRY
+NtUserCallNextHookEx( int Code,
+                      WPARAM wParam,
+                      LPARAM lParam,
+                      BOOL Ansi)
+{
+    PTHREADINFO pti;
+    PHOOK HookObj, NextObj;
+    PCLIENTINFO ClientInfo;
+    LRESULT lResult = 0;
+    DECLARE_RETURN(LRESULT);
 
-    /* Its the same so it has already been called */
-    if (HookObj == NextObj) RETURN(0);
+    DPRINT("Enter NtUserCallNextHookEx\n");
+    UserEnterExclusive();
 
-    UserReferenceObject(HookObj);
+    pti = GetW32ThreadInfo();
 
-    Ansi = HookObj->Ansi;
+    HookObj = pti->sphkCurrent;
 
-    if (NULL != HookObj->Thread && (HookObj->Thread != PsGetCurrentThread()))
+    if (!HookObj) RETURN( 0);
+
+    NextObj = HookObj->phkNext;
+
+    pti->sphkCurrent = NextObj;
+    ClientInfo = pti->pClientInfo;
+    _SEH2_TRY
     {
-        DPRINT1("Thread mismatch\n");
-        UserDereferenceObject(HookObj);
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
-        RETURN( 0);
+       ClientInfo->phkCurrent = NextObj;
     }
-   
-    NextObj = IntGetNextHook(HookObj);
-    ClientInfo->phkCurrent = NextObj; /* Preset next hook from list. */
-    UserCallNextHookEx( HookObj, Code, wParam, lParam, Ansi);
-    UserDereferenceObject(HookObj);
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+       ClientInfo = NULL;
+    }
+    _SEH2_END;
 
-    RETURN( (LRESULT)NextObj);
+    /* Now in List run down. */
+    if (ClientInfo && NextObj)
+    {
+       NextObj->phkNext = IntGetNextHook(NextObj);
+       lResult = UserCallNextHookEx( NextObj, Code, wParam, lParam, NextObj->Ansi);
+    }
+    RETURN( lResult);
 
 CLEANUP:
     DPRINT("Leave NtUserCallNextHookEx, ret=%i\n",_ret_);
@@ -1091,43 +1117,51 @@ CLEANUP:
 
 HHOOK
 APIENTRY
-NtUserSetWindowsHookAW(int idHook, 
-                       HOOKPROC lpfn,
-                       BOOL Ansi)
+NtUserSetWindowsHookAW( int idHook, 
+                        HOOKPROC lpfn,
+                        BOOL Ansi)
 {
+    DWORD ThreadId;
     UNICODE_STRING USModuleName;
 
     RtlInitUnicodeString(&USModuleName, NULL);
-
-    return NtUserSetWindowsHookEx(NULL, &USModuleName, 0, idHook, lpfn, Ansi);
+    ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread);
+
+    return NtUserSetWindowsHookEx( NULL,
+                                  &USModuleName,
+                                   ThreadId,
+                                   idHook,
+                                   lpfn,
+                                   Ansi);
 }
 
 HHOOK
 APIENTRY
-NtUserSetWindowsHookEx(HINSTANCE Mod,
-                       PUNICODE_STRING UnsafeModuleName,
-                       DWORD ThreadId,
-                       int HookId,
-                       HOOKPROC HookProc,
-                       BOOL Ansi)
+NtUserSetWindowsHookEx( HINSTANCE Mod,
+                        PUNICODE_STRING UnsafeModuleName,
+                        DWORD ThreadId,
+                        int HookId,
+                        HOOKPROC HookProc,
+                        BOOL Ansi)
 {
     PWINSTATION_OBJECT WinStaObj;
-    PCLIENTINFO ClientInfo;
-    BOOLEAN Global;
-    PETHREAD Thread;
     PHOOK Hook;
     UNICODE_STRING ModuleName;
     NTSTATUS Status;
     HHOOK Handle;
-    BOOLEAN ThreadReferenced = FALSE;
+    PETHREAD Thread = NULL;
+    PTHREADINFO ptiCurrent, pti = NULL;
+    BOOL Hit = FALSE;
     DECLARE_RETURN(HHOOK);
 
     DPRINT("Enter NtUserSetWindowsHookEx\n");
     UserEnterExclusive();
 
+    ptiCurrent = GetW32ThreadInfo();
+
     if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId )
     {
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        SetLastWin32Error(ERROR_INVALID_HOOK_FILTER);
         RETURN( NULL);
     }
 
@@ -1137,173 +1171,211 @@ NtUserSetWindowsHookEx(HINSTANCE Mod,
         RETURN( NULL);
     }
 
-    ClientInfo = GetWin32ClientInfo();
-
     if (ThreadId)  /* thread-local hook */
     {
-        if (HookId == WH_JOURNALRECORD ||
+       if ( HookId == WH_JOURNALRECORD ||
             HookId == WH_JOURNALPLAYBACK ||
             HookId == WH_KEYBOARD_LL ||
             HookId == WH_MOUSE_LL ||
             HookId == WH_SYSMSGFILTER)
-        {
-            /* these can only be global */
-            SetLastWin32Error(ERROR_INVALID_PARAMETER);
-            RETURN( NULL);
-        }
-
-        Mod = NULL;
-        Global = FALSE;
-
-        if (!NT_SUCCESS(PsLookupThreadByThreadId((HANDLE)(DWORD_PTR) ThreadId, &Thread)))
-        {
-            DPRINT1("Invalid thread id 0x%x\n", ThreadId);
-            SetLastWin32Error(ERROR_INVALID_PARAMETER);
-            RETURN( NULL);
-        }
-
-        /* Thread was referenced */
-        ThreadReferenced = TRUE;
-        if (Thread->ThreadsProcess != PsGetCurrentProcess())
-        {
-            ObDereferenceObject(Thread);
-            DPRINT1("Can't specify thread belonging to another process\n");
-            SetLastWin32Error(ERROR_INVALID_PARAMETER);
-            RETURN( NULL);
-        }
+       {
+           /* these can only be global */
+           SetLastWin32Error(ERROR_GLOBAL_ONLY_HOOK);
+           RETURN( NULL);
+       }
+
+       if (!NT_SUCCESS(PsLookupThreadByThreadId((HANDLE)(DWORD_PTR) ThreadId, &Thread)))
+       {
+          DPRINT1("Invalid thread id 0x%x\n", ThreadId);
+          SetLastWin32Error(ERROR_INVALID_PARAMETER);
+          RETURN( NULL);
+       }
+
+       pti = Thread->Tcb.Win32Thread;
+
+       ObDereferenceObject(Thread);
+
+       if ( pti->rpdesk != ptiCurrent->rpdesk) // gptiCurrent->rpdesk)
+       {
+          SetLastWin32Error(ERROR_ACCESS_DENIED);
+          RETURN( NULL);
+       }
+
+       if (Thread->ThreadsProcess != PsGetCurrentProcess())
+       {
+          if ( !Mod &&
+              (HookId == WH_GETMESSAGE ||
+               HookId == WH_CALLWNDPROC ||
+               HookId == WH_CBT ||
+               HookId == WH_HARDWARE ||
+               HookId == WH_DEBUG ||
+               HookId == WH_SHELL ||
+               HookId == WH_FOREGROUNDIDLE ||
+               HookId == WH_CALLWNDPROCRET) )
+          {
+             SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD);
+             RETURN( NULL);
+          }
+
+          if ( (pti->TIF_flags & (TIF_CSRSSTHREAD|TIF_SYSTEMTHREAD)) && 
+               (HookId == WH_GETMESSAGE ||
+                HookId == WH_CALLWNDPROC ||
+                HookId == WH_CBT ||
+                HookId == WH_HARDWARE ||
+                HookId == WH_DEBUG ||
+                HookId == WH_SHELL ||
+                HookId == WH_FOREGROUNDIDLE ||
+                HookId == WH_CALLWNDPROCRET) )
+          {
+             SetLastWin32Error(ERROR_HOOK_TYPE_NOT_ALLOWED);
+             RETURN( NULL);
+          }
+       }
     }
     else  /* system-global hook */
     {
-        if (HookId == WH_KEYBOARD_LL || HookId == WH_MOUSE_LL)
-        {
-            Mod = NULL;
-            Thread = PsGetCurrentThread();
-
-            Status = ObReferenceObjectByPointer(Thread,
-                                                THREAD_ALL_ACCESS,
-                                                PsThreadType,
-                                                KernelMode);
-
-            if (!NT_SUCCESS(Status))
-            {
-                SetLastNtError(Status);
-                RETURN( (HANDLE) NULL);
-            }
-
-            /* Thread was referenced */
-            ThreadReferenced = TRUE;
-        }
-        else if (NULL ==  Mod)
-        {
-            SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD);
-            RETURN( NULL);
-        }
-        else
-        {
-            Thread = NULL;
-        }
-        Global = TRUE;
+       pti = ptiCurrent; // gptiCurrent;
+       if ( !Mod &&
+            (HookId == WH_GETMESSAGE ||
+             HookId == WH_CALLWNDPROC ||
+             HookId == WH_CBT ||
+             HookId == WH_SYSMSGFILTER ||
+             HookId == WH_HARDWARE ||
+             HookId == WH_DEBUG ||
+             HookId == WH_SHELL ||
+             HookId == WH_FOREGROUNDIDLE ||
+             HookId == WH_CALLWNDPROCRET) )
+       {
+          SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD);
+          RETURN( NULL);
+       }
     }
 
-    if ((Global && (HookId != WH_KEYBOARD_LL && HookId != WH_MOUSE_LL)) ||
-        WH_DEBUG == HookId ||
-        WH_JOURNALPLAYBACK == HookId ||
-        WH_JOURNALRECORD == HookId)
-    {
-#if 0 /* Removed to get winEmbed working again */
-        UNIMPLEMENTED
-#else
-        DPRINT1("Not implemented: HookId %d Global %s\n", HookId, Global ? "TRUE" : "FALSE");
-#endif
-
-        /* Dereference thread if needed */
-        if (ThreadReferenced) ObDereferenceObject(Thread);
-        SetLastWin32Error(ERROR_NOT_SUPPORTED);
-        RETURN( NULL);
-    }
-
-    Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
-                                            KernelMode,
-                                            0,
+    Status = IntValidateWindowStationHandle( PsGetCurrentProcess()->Win32WindowStation,
+                                             KernelMode,
+                                             0,
                                             &WinStaObj);
 
     if (!NT_SUCCESS(Status))
     {
-        /* Dereference thread if needed */
-        if (ThreadReferenced) ObDereferenceObject(Thread);
-        SetLastNtError(Status);
-        RETURN( (HANDLE) NULL);
+       SetLastNtError(Status);
+       RETURN( NULL);
     }
+    ObDereferenceObject(WinStaObj);
 
-    Hook = IntAddHook(Thread, HookId, Global, WinStaObj);
-    if (NULL == Hook)
+    Hook = UserCreateObject(gHandleTable, NULL, &Handle, otHook, sizeof(HOOK));
+
+    if (!Hook)
     {
-        /* Dereference thread if needed */
-        if (ThreadReferenced) ObDereferenceObject(Thread);
-        ObDereferenceObject(WinStaObj);
-        RETURN( NULL);
+       RETURN( NULL);
     }
 
-    /* Let IntFreeHook now that this thread needs a dereference */
-    if (ThreadReferenced)
+    Hook->ihmod   = (INT)Mod; // Module Index from atom table, Do this for now.
+    Hook->Thread  = Thread; /* Set Thread, Null is Global. */
+    Hook->HookId  = HookId;
+    Hook->rpdesk  = pti->rpdesk;
+    Hook->phkNext = NULL; /* Dont use as a chain! Use link lists for chaining. */
+    Hook->Proc    = HookProc;
+    Hook->Ansi    = Ansi;
+
+    if (ThreadId)  /* thread-local hook */
     {
-        Hook->Flags |= HOOK_THREAD_REFERENCED;
+       InsertHeadList(&pti->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain);
+       pti->sphkCurrent = NULL;
+       Hook->ptiHooked = pti;
+       pti->fsHooks |= HOOKID_TO_FLAG(HookId);
+
+       if (pti->pClientInfo)
+       {
+          if ( pti->ppi == ptiCurrent->ppi) /* gptiCurrent->ppi) */
+          {
+             _SEH2_TRY
+             {
+                pti->pClientInfo->fsHooks = pti->fsHooks;
+                pti->pClientInfo->phkCurrent = 0;
+             }
+             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+             {
+                Hit = TRUE;
+             }
+             _SEH2_END;
+             if (Hit)
+             {
+                DPRINT1("Problem writing to Local ClientInfo!\n");
+             }
+          }
+          else
+          {
+             KeAttachProcess(&pti->ppi->peProcess->Pcb);
+             _SEH2_TRY
+             {
+                pti->pClientInfo->fsHooks = pti->fsHooks;
+                pti->pClientInfo->phkCurrent = 0;
+             }
+             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+             {
+                Hit = TRUE;
+             }
+             _SEH2_END;
+             KeDetachProcess();
+             if (Hit)
+             {
+                DPRINT1("Problem writing to Remote ClientInfo!\n");
+             }
+          }
+       }
     }
-
-    if (NULL != Mod)
+    else
     {
-        Status = MmCopyFromCaller(&ModuleName, UnsafeModuleName, sizeof(UNICODE_STRING));
-        if (!NT_SUCCESS(Status))
-        {
-            UserDereferenceObject(Hook);
-            IntRemoveHook(Hook, WinStaObj, FALSE);
-            ObDereferenceObject(WinStaObj);
-            SetLastNtError(Status);
-            RETURN( NULL);
-        }
+       InsertHeadList(&pti->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain);
+       Hook->ptiHooked = NULL;
+       //gptiCurrent->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId);
+       pti->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId);
+    }
 
-        Hook->ModuleName.Buffer = ExAllocatePoolWithTag(PagedPool,
+    RtlInitUnicodeString(&Hook->ModuleName, NULL);
+
+    if (Mod)
+    {
+       Status = MmCopyFromCaller(&ModuleName,
+                                  UnsafeModuleName,
+                                  sizeof(UNICODE_STRING));
+       if (!NT_SUCCESS(Status))
+       {
+          IntRemoveHook(Hook);
+          SetLastNtError(Status);
+          RETURN( NULL);
+       }
+
+       Hook->ModuleName.Buffer = ExAllocatePoolWithTag( PagedPool,
                                                         ModuleName.MaximumLength,
                                                         TAG_HOOK);
-        if (NULL == Hook->ModuleName.Buffer)
-        {
-            UserDereferenceObject(Hook);
-            IntRemoveHook(Hook, WinStaObj, FALSE);
-            ObDereferenceObject(WinStaObj);
-            SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-            RETURN( NULL);
-        }
-
-        Hook->ModuleName.MaximumLength = ModuleName.MaximumLength;
-        Status = MmCopyFromCaller(Hook->ModuleName.Buffer,
+       if (NULL == Hook->ModuleName.Buffer)
+       {
+          IntRemoveHook(Hook);
+          SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+          RETURN( NULL);
+       }
+
+       Hook->ModuleName.MaximumLength = ModuleName.MaximumLength;
+       Status = MmCopyFromCaller( Hook->ModuleName.Buffer,
                                   ModuleName.Buffer,
                                   ModuleName.MaximumLength);
-        if (!NT_SUCCESS(Status))
-        {
-            ExFreePoolWithTag(Hook->ModuleName.Buffer, TAG_HOOK);
-            UserDereferenceObject(Hook);
-            IntRemoveHook(Hook, WinStaObj, FALSE);
-            ObDereferenceObject(WinStaObj);
-            SetLastNtError(Status);
-            RETURN( NULL);
-        }
-
-        Hook->ModuleName.Length = ModuleName.Length;
-        /* make proc relative to the module base */
-        Hook->Proc = (void *)((char *)HookProc - (char *)Mod);
+       if (!NT_SUCCESS(Status))
+       {
+          ExFreePoolWithTag(Hook->ModuleName.Buffer, TAG_HOOK);
+          Hook->ModuleName.Buffer = NULL;
+          IntRemoveHook(Hook);
+          SetLastNtError(Status);
+          RETURN( NULL);
+       }
+
+       Hook->ModuleName.Length = ModuleName.Length;
+       /* make proc relative to the module base */
+       Hook->offPfn = (ULONG_PTR)((char *)HookProc - (char *)Mod);
     }
     else
-        Hook->Proc = HookProc;
-
-    Hook->Ansi = Ansi;
-    Handle = UserHMGetHandle(Hook);
-
-    /* Clear the client threads next hook. */
-    ClientInfo->phkCurrent = 0;
-
-    UserDereferenceObject(Hook);
-
-    ObDereferenceObject(WinStaObj);
+       Hook->offPfn = 0;
 
     RETURN( Handle);
 
@@ -1313,46 +1385,28 @@ CLEANUP:
     END_CLEANUP;
 }
 
-
 BOOL
 APIENTRY
 NtUserUnhookWindowsHookEx(HHOOK Hook)
 {
-    PWINSTATION_OBJECT WinStaObj;
     PHOOK HookObj;
-    NTSTATUS Status;
     DECLARE_RETURN(BOOL);
 
     DPRINT("Enter NtUserUnhookWindowsHookEx\n");
     UserEnterExclusive();
 
-    Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
-                                            KernelMode,
-                                            0,
-                                            &WinStaObj);
-
-    if (!NT_SUCCESS(Status))
-    {
-        SetLastNtError(Status);
-        RETURN( FALSE);
-    }
-
-    /*  Status = UserReferenceObjectByHandle(gHandleTable, Hook,
-                                             otHookProc, (PVOID *) &HookObj); */
     if (!(HookObj = IntGetHookObject(Hook)))
     {
         DPRINT1("Invalid handle passed to NtUserUnhookWindowsHookEx\n");
-        ObDereferenceObject(WinStaObj);
         /* SetLastNtError(Status); */
         RETURN( FALSE);
     }
 
     ASSERT(Hook == UserHMGetHandle(HookObj));
 
-    IntRemoveHook(HookObj, WinStaObj, FALSE);
+    IntRemoveHook(HookObj);
 
     UserDereferenceObject(HookObj);
-    ObDereferenceObject(WinStaObj);
 
     RETURN( TRUE);
 
index 403e02b..4078d8a 100644 (file)
@@ -368,9 +368,10 @@ IntDispatchMessage(PMSG pMsg)
 {
   LARGE_INTEGER TickCount;
   LONG Time;
-  LRESULT retval;
+  LRESULT retval = 0;
   PMSGMEMORY MsgMemoryEntry;
   INT lParamBufferSize;
+  PTHREADINFO pti;
   LPARAM lParamPacked;
   PWND Window = NULL;
 
@@ -380,25 +381,29 @@ IntDispatchMessage(PMSG pMsg)
      if (!Window) return 0;
   }
 
+  pti = PsGetCurrentThreadWin32Thread();
+
   if (((pMsg->message == WM_SYSTIMER) ||
        (pMsg->message == WM_TIMER)) &&
       (pMsg->lParam) )
   {
      if (pMsg->message == WM_TIMER)
      {
-        if (ValidateTimerCallback(PsGetCurrentThreadWin32Thread(),pMsg->lParam))
+        ObReferenceObject(pti->pEThread);
+        if (ValidateTimerCallback(pti,pMsg->lParam))
         {
            KeQueryTickCount(&TickCount);
            Time = MsqCalculateMessageTime(&TickCount);
-           return co_IntCallWindowProc((WNDPROC)pMsg->lParam,
-                                        TRUE,
-                                        pMsg->hwnd,
-                                        WM_TIMER,
-                                        pMsg->wParam,
-                                        (LPARAM)Time,
-                                        sizeof(LPARAM));
+           retval = co_IntCallWindowProc((WNDPROC)pMsg->lParam,
+                                          TRUE,
+                                          pMsg->hwnd,
+                                          WM_TIMER,
+                                          pMsg->wParam,
+                                         (LPARAM)Time,
+                                          sizeof(LPARAM));
         }
-        return 0;        
+        ObDereferenceObject(pti->pEThread);
+        return retval;        
      }
      else
      {
@@ -431,7 +436,7 @@ IntDispatchMessage(PMSG pMsg)
      DPRINT1("Failed to pack message parameters\n");
      return 0;
   }
-
+  ObReferenceObject(pti->pEThread);
   retval = co_IntCallWindowProc( Window->lpfnWndProc,
                                 !Window->Unicode,
                                  pMsg->hwnd,
@@ -452,6 +457,7 @@ IntDispatchMessage(PMSG pMsg)
      co_UserGetUpdateRgn( Window, hrgn, TRUE );
      REGION_FreeRgnByHandle( hrgn );
   }
+  ObDereferenceObject(pti->pEThread);
   return retval;
 }
 
@@ -784,6 +790,7 @@ BOOL ProcessMouseMessage(MSG* Msg, BOOLEAN RemoveMessages)
                            HCBT_CLICKSKIPPED,
                            Msg->message,
                            (LPARAM)&MHook);
+        DPRINT1("MouseMessage WH_CBT Call Hook return!\n");
         return FALSE;
     }
 
@@ -812,6 +819,7 @@ BOOL ProcessKeyboardMessage(MSG* Msg, BOOLEAN RemoveMessages)
                            HCBT_KEYSKIPPED,
                            LOWORD(Msg->wParam),
                            Msg->lParam );
+        DPRINT1("KeyboardMessage WH_CBT Call Hook return!\n");
         return FALSE;
     }
        return TRUE;
@@ -1322,13 +1330,13 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
                                 UINT uTimeout,
                                 ULONG_PTR *uResult )
 {
-   ULONG_PTR Result;
    NTSTATUS Status;
    PWND Window = NULL;
    PMSGMEMORY MsgMemoryEntry;
    INT lParamBufferSize;
    LPARAM lParamPacked;
    PTHREADINFO Win32Thread;
+   ULONG_PTR Result = 0;
    DECLARE_RETURN(LRESULT);
    USER_REFERENCE_ENTRY Ref;
 
@@ -1369,6 +1377,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
           RETURN( FALSE);
       }
 
+      ObReferenceObject(Win32Thread->pEThread);
       Result = (ULONG_PTR)co_IntCallWindowProc( Window->lpfnWndProc,
                                                !Window->Unicode,
                                                 hWnd,
@@ -1381,6 +1390,8 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
          *uResult = Result;
       }
 
+      ObDereferenceObject(Win32Thread->pEThread);
+
       IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
 
       if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE)))
@@ -1408,14 +1419,14 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
    do
    {
       Status = co_MsqSendMessage( Window->head.pti->MessageQueue,
-                                                       hWnd,
-                                                        Msg,
-                                                     wParam,
-                                                     lParam,
-                                                   uTimeout,
-                                      (uFlags & SMTO_BLOCK),
-                                                 MSQ_NORMAL,
-                                                    uResult );
+                                  hWnd,
+                                  Msg,
+                                  wParam,
+                                  lParam,
+                                  uTimeout,
+                                 (uFlags & SMTO_BLOCK),
+                                  MSQ_NORMAL,
+                                  uResult );
    }
    while ((STATUS_TIMEOUT == Status) &&
           (uFlags & SMTO_NOTIMEOUTIFNOTHUNG) &&
@@ -1575,7 +1586,7 @@ co_IntSendMessageWithCallBack( HWND hWnd,
    /* If this is not a callback and it can be sent now, then send it. */
    if ((Window->head.pti->MessageQueue == Win32Thread->MessageQueue) && (CompletionCallback == NULL))
    {
-
+      ObReferenceObject(Win32Thread->pEThread);
       Result = (ULONG_PTR)co_IntCallWindowProc( Window->lpfnWndProc,
                                                !Window->Unicode,
                                                 hWnd,
@@ -1587,6 +1598,7 @@ co_IntSendMessageWithCallBack( HWND hWnd,
       {
          *uResult = Result;
       }
+      ObDereferenceObject(Win32Thread->pEThread);
    }
 
    IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
@@ -2553,12 +2565,13 @@ NtUserMessageCall(
                                             2000,
                                             &RetVal);
                }
+               Ret = RetVal;
             }
             else if (parm.flags & BSF_POSTMESSAGE)
             {
                Ret = UserPostMessage(HWND_BROADCAST, Msg, wParam, lParam);
             }
-            else if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
+            else //Everything else,,,, if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
             {
                Ret = UserSendNotifyMessage(HWND_BROADCAST, Msg, wParam, lParam);
             }
@@ -2584,21 +2597,31 @@ NtUserMessageCall(
       case FNID_CALLWNDPROC:
       case FNID_CALLWNDPROCRET:
       {
-         PCLIENTINFO ClientInfo = GetWin32ClientInfo();
-         PHOOK NextObj, Hook = ClientInfo->phkCurrent;
+         PTHREADINFO pti;
+         PCLIENTINFO ClientInfo;
+         PHOOK NextObj, Hook;
+
+         pti = GetW32ThreadInfo();
 
-         if (!ClientInfo || !Hook) break;
+         Hook = pti->sphkCurrent;
 
-         UserReferenceObject(Hook);
+         if (!Hook) break;
 
-         if (Hook->Thread && (Hook->Thread != PsGetCurrentThread()))
+         NextObj = Hook->phkNext;
+         ClientInfo = pti->pClientInfo;
+         _SEH2_TRY
          {
-            UserDereferenceObject(Hook);
-            break;
+            ClientInfo->phkCurrent = NextObj;
          }
+         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+         {
+            ClientInfo = NULL;
+         }
+         _SEH2_END;
+
+         if (!ClientInfo || !NextObj) break;
 
-         NextObj = IntGetNextHook(Hook);
-         ClientInfo->phkCurrent = NextObj;
+         NextObj->phkNext = IntGetNextHook(NextObj);
 
          if ( Hook->HookId == WH_CALLWNDPROC)
          {
@@ -2634,8 +2657,6 @@ NtUserMessageCall(
                                           Hook->Ansi,
                                           &Hook->ModuleName);
          }
-         UserDereferenceObject(Hook);
-         lResult = (LRESULT) NextObj;
       }
       break;
    }
index 5d0bee8..04694b4 100644 (file)
@@ -948,26 +948,25 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
                   &Message->ListEntry);
 
    if (Message->HookMessage == MSQ_ISHOOK)
-   {
-      Result = co_HOOK_CallHooks(Message->Msg.message,
-                                 (INT)(INT_PTR)Message->Msg.hwnd,
-                                 Message->Msg.wParam,
-                                 Message->Msg.lParam);
+   {  // Direct Hook Call processor
+      Result = co_CallHook( Message->Msg.message,     // HookId
+                           (INT)(INT_PTR)Message->Msg.hwnd, // Code
+                            Message->Msg.wParam,
+                            Message->Msg.lParam);
    }
    else if (Message->HookMessage == MSQ_ISEVENT)
-   {
+   {  // Direct Event Call processor
       Result = co_EVENT_CallEvents( Message->Msg.message,
                                     Message->Msg.hwnd,
                                     Message->Msg.wParam,
                                     Message->Msg.lParam);
    }
    else
-   {
-      /* Call the window procedure. */
-      Result = co_IntSendMessage(Message->Msg.hwnd,
-                                 Message->Msg.message,
-                                 Message->Msg.wParam,
-                                 Message->Msg.lParam);
+   {  /* Call the window procedure. */
+      Result = co_IntSendMessage( Message->Msg.hwnd,
+                                  Message->Msg.message,
+                                  Message->Msg.wParam,
+                                  Message->Msg.lParam);
    }
 
    /* remove the message from the local dispatching list, because it doesn't need
@@ -1004,7 +1003,9 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
       KeSetEvent(Message->CompletionEvent, IO_NO_INCREMENT, FALSE);
    }
 
-   /* Call the callback if the message was sent with SendMessageCallback */
+   /* Call the callback if the message wa
+   
+   s sent with SendMessageCallback */
    if (Message->CompletionCallback != NULL)
    {
       co_IntCallSentMessageCallback(Message->CompletionCallback,
@@ -1133,10 +1134,10 @@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
    PUSER_SENT_MESSAGE Message;
    KEVENT CompletionEvent;
    NTSTATUS WaitStatus;
-   LRESULT Result;
    PUSER_MESSAGE_QUEUE ThreadQueue;
    LARGE_INTEGER Timeout;
    PLIST_ENTRY Entry;
+   LRESULT Result = 0;   //// Result could be trashed. ////
 
    if(!(Message = ExAllocatePoolWithTag(PagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG)))
    {
@@ -1154,7 +1155,6 @@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
 
    /* FIXME - increase reference counter of sender's message queue here */
 
-   Result = 0;
    Message->Msg.hwnd = Wnd;
    Message->Msg.message = Msg;
    Message->Msg.wParam = wParam;
@@ -1164,6 +1164,7 @@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
    Message->SenderQueue = ThreadQueue;
    IntReferenceMessageQueue(ThreadQueue);
    Message->CompletionCallback = NULL;
+   Message->CompletionCallbackContext = 0;
    Message->HookMessage = HookMessage;
    Message->HasPackedLParam = FALSE;
 
@@ -1632,18 +1633,6 @@ MsqDestroyMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
    IntDereferenceMessageQueue(MessageQueue);
 }
 
-PHOOKTABLE FASTCALL
-MsqGetHooks(PUSER_MESSAGE_QUEUE Queue)
-{
-   return Queue->Hooks;
-}
-
-VOID FASTCALL
-MsqSetHooks(PUSER_MESSAGE_QUEUE Queue, PHOOKTABLE Hooks)
-{
-   Queue->Hooks = Hooks;
-}
-
 LPARAM FASTCALL
 MsqSetMessageExtraInfo(LPARAM lParam)
 {
index 0c3fb07..222b36c 100644 (file)
@@ -330,8 +330,8 @@ UserCreateObject( PUSER_HANDLE_TABLE ht,
    {
       case otWindow:
 //      case otMenu:
-//      case otHook:
-//      case otCallProc:
+      case otHook:
+      case otCallProc:
       case otInputContext:
          Object = DesktopHeapAlloc(rpdesk, size);
          dt = TRUE;
@@ -420,8 +420,8 @@ UserDereferenceObject(PVOID object)
      {
         case otWindow:
 //        case otMenu:
-//        case otHook:
-//        case otCallProc:
+        case otHook:
+        case otCallProc:
         case otInputContext:
            return DesktopHeapFree(((PTHRDESKHEAD)object)->rpdesk, object);
 
index af97709..29d3595 100644 (file)
@@ -228,21 +228,6 @@ NtUserCallOneParam(
             RETURN (ret);
          }
 
-      case ONEPARAM_ROUTINE_ISWINDOWINDESTROY:
-         {
-            PWND Window;
-            DWORD_PTR Result;
-
-            if(!(Window = UserGetWindowObject((HWND)Param)))
-            {
-               RETURN( FALSE);
-            }
-
-            Result = (DWORD_PTR)IntIsWindowInDestroy(Window);
-
-            RETURN( Result);
-         }
-
       case ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING:
          {
             BOOL Enable;
@@ -473,6 +458,8 @@ NtUserCallTwoParam(
       case TWOPARAM_ROUTINE_SETCURSORPOS:
          RETURN( (DWORD_PTR)UserSetCursorPos((int)Param1, (int)Param2, FALSE));
 
+      case TWOPARAM_ROUTINE_UNHOOKWINDOWSHOOK:
+         RETURN( IntUnhookWindowsHook((int)Param1, (HOOKPROC)Param2));
    }
    DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam(), Param1=0x%x Parm2=0x%x\n",
            Routine, Param1, Param2);
@@ -713,6 +700,21 @@ NtUserCallHwndParam(
          UserLeave();
          return 0;
       }
+
+      case HWNDPARAM_ROUTINE_ROS_NOTIFYWINEVENT:
+      {
+         PWND pWnd;
+         PNOTIFYEVENT pne;
+         UserEnterExclusive();
+         pne = (PNOTIFYEVENT)Param;
+         if (hWnd)
+            pWnd = UserGetWindowObject(hWnd);
+         else
+            pWnd = NULL;
+         IntNotifyWinEvent(pne->event, pWnd, pne->idObject, pne->idChild, pne->flags);
+         UserLeave();
+         return 0;
+      }
    }
 
    UNIMPLEMENTED;
index 0b270cf..f6e588f 100644 (file)
@@ -163,7 +163,6 @@ IntIsWindow(HWND hWnd)
 }
 
 
-
 PWND FASTCALL
 IntGetParent(PWND Wnd)
 {
@@ -179,7 +178,6 @@ IntGetParent(PWND Wnd)
    return NULL;
 }
 
-
 /*
  * IntWinListChildren
  *
@@ -348,7 +346,7 @@ static LRESULT co_UserFreeWindow(PWND Window,
    Window->state2 |= WNDS2_INDESTROY;
    Window->style &= ~WS_VISIBLE;
 
-   IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, 0);
+   IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, CHILDID_SELF, 0);
 
    /* remove the window already at this point from the thread window list so we
       don't get into trouble when destroying the thread windows while we're still
@@ -399,7 +397,9 @@ static LRESULT co_UserFreeWindow(PWND Window,
       if(BelongsToThreadData)
          co_IntSendMessage(Window->head.h, WM_NCDESTROY, 0, 0);
    }
+
    DestroyTimersForWindow(ThreadData, Window);
+
    HOOK_DestroyThreadHooks(ThreadData->pEThread); // This is needed here too!
 
    /* flush the message queue */
@@ -1168,6 +1168,7 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent)
 
    }
 
+   IntNotifyWinEvent(EVENT_OBJECT_PARENTCHANGE, Wnd ,OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
    /*
     * SetParent additionally needs to make hwnd the top window
     * in the z-order and send the expected WM_WINDOWPOSCHANGING and
@@ -1227,13 +1228,6 @@ IntUnlinkWindow(PWND Wnd)
    Wnd->spwndPrev = Wnd->spwndNext = NULL;
 }
 
-BOOL FASTCALL
-IntIsWindowInDestroy(PWND Window)
-{
-   return ((Window->state2 & WNDS2_INDESTROY) == WNDS2_INDESTROY);
-}
-
-
 BOOL
 FASTCALL
 IntGetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *lpwndpl)
@@ -1635,6 +1629,33 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
 
    pti = PsGetCurrentThreadWin32Thread();
 
+   if (!(Cs->dwExStyle & WS_EX_LAYOUTRTL))
+   {
+      if (ParentWindow)
+      {
+         if ( (Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD &&
+              ParentWindow->ExStyle & WS_EX_LAYOUTRTL &&
+             !(ParentWindow->ExStyle & WS_EX_NOINHERITLAYOUT) )
+            Cs->dwExStyle |= WS_EX_LAYOUTRTL;
+      }
+      else
+      {/* 
+        Note from MSDN http://msdn.microsoft.com/en-us/library/aa913269.aspx :
+
+        Dialog boxes and message boxes do not inherit layout, so you must
+        set the layout explicitly.
+       */
+         if ( Class && Class->fnid != FNID_DIALOG)
+         {
+            PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
+            if (ppi->dwLayout & LAYOUT_RTL)
+            {
+               Cs->dwExStyle |= WS_EX_LAYOUTRTL;
+            }
+         }
+      }      
+   }
+
    /* Automatically add WS_EX_WINDOWEDGE */
    if ((Cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
          ((!(Cs->dwExStyle & WS_EX_STATICEDGE)) &&
@@ -1877,17 +1898,19 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
                      PLARGE_STRING WindowName)
 {
    PWND Window = NULL, ParentWindow = NULL, OwnerWindow;
-   HWND hWnd, hWndParent, hWndOwner;
+   HWND hWnd, hWndParent, hWndOwner, hwndInsertAfter;
    DWORD dwStyle;
    PWINSTATION_OBJECT WinSta;
    PCLS Class = NULL;
    SIZE Size;
    POINT MaxPos;
-   CBT_CREATEWNDW CbtCreate;
+   CBT_CREATEWNDW * pCbtCreate;
    LRESULT Result;
    USER_REFERENCE_ENTRY ParentRef, Ref;
    PTHREADINFO pti;
+   ANSI_STRING asClassName;
    DWORD dwShowMode = SW_SHOW;
+   CREATESTRUCTW *pCsw;
    DECLARE_RETURN(PWND);
 
    /* Get the current window station and reference it */
@@ -1900,6 +1923,10 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
    WinSta = pti->rpdesk->rpwinstaParent;
    ObReferenceObjectByPointer(WinSta, KernelMode, ExWindowStationObjectType, 0);
 
+   pCsw = NULL;
+   pCbtCreate = NULL;
+   RtlInitAnsiString(&asClassName, NULL);
+
    /* Get the class and reference it*/
    Class = IntGetAndReferenceClass(ClassName, Cs->hInstance);
    if(!Class)
@@ -1956,22 +1983,57 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
        RETURN(0);
    }
 
-   hWnd = Window->head.h;
+   hWnd = UserHMGetHandle(Window);
 
    UserRefObjectCo(Window, &Ref);
    ObDereferenceObject(WinSta);
 
-   /* Call the WH_CBT hook */
-   dwStyle = Cs->style;
-   Cs->style = Window->style; /* HCBT_CREATEWND needs the real window style */
-   CbtCreate.lpcs = Cs;
-   CbtCreate.hwndInsertAfter = HWND_TOP;
+   //// Call the WH_CBT hook ////
+
+   // Allocate the calling structures Justin Case this goes Global.
+   pCsw = ExAllocatePoolWithTag(NonPagedPool, sizeof(CREATESTRUCTW), TAG_HOOK);
+   pCbtCreate = ExAllocatePoolWithTag(NonPagedPool, sizeof(CBT_CREATEWNDW), TAG_HOOK);
+
+   /* Fill the new CREATESTRUCTW */
+   pCsw->lpCreateParams = Cs->lpCreateParams;
+   pCsw->hInstance = Cs->hInstance;
+   pCsw->hMenu = Cs->hMenu;
+   pCsw->hwndParent = Cs->hwndParent;
+   pCsw->cx = Cs->cx;
+   pCsw->cy = Cs->cy;
+   pCsw->x = Cs->x;
+   pCsw->y = Cs->y;
+   pCsw->dwExStyle = Cs->dwExStyle;
+   dwStyle = Cs->style;       // Save it anyway.
+   pCsw->style = Window->style; /* HCBT_CREATEWND needs the real window style */
+
+   pCsw->lpszName  = (LPCWSTR) WindowName->Buffer;
+   pCsw->lpszClass = (LPCWSTR) ClassName->Buffer;
+
+   if (Window->state & WNDS_ANSICREATOR)
+   {
+      if (!IS_ATOM(ClassName->Buffer))
+      {
+         RtlUnicodeStringToAnsiString(&asClassName, ClassName, TRUE);
+         pCsw->lpszClass = (LPCWSTR) asClassName.Buffer;
+      }
+   }
+
+   pCbtCreate->lpcs = pCsw;
+   pCbtCreate->hwndInsertAfter = HWND_TOP;
 
-   if (co_HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (WPARAM) hWnd, (LPARAM) &CbtCreate))
+   Result = co_HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (WPARAM) hWnd, (LPARAM) pCbtCreate);
+   if (Result != 0)
    {
-      DPRINT1("HCBT_CREATEWND hook failed!\n");
+      DPRINT1("WH_CBT HCBT_CREATEWND hook failed! 0x%x\n", Result);
       RETURN( (PWND) NULL);
    }
+   // Write back changes.
+   Cs->cx = pCsw->cx;
+   Cs->cy = pCsw->cy;
+   Cs->x = pCsw->x;
+   Cs->y = pCsw->y;
+   hwndInsertAfter = pCbtCreate->hwndInsertAfter;
 
    Cs->style = dwStyle; /* NCCREATE and WM_NCCALCSIZE need the original values*/
 
@@ -2014,7 +2076,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
    }
    
    /* Send the NCCREATE message */
-   Result = co_IntSendMessage(Window->head.h, WM_NCCREATE, 0, (LPARAM) Cs);
+   Result = co_IntSendMessage(UserHMGetHandle(Window), WM_NCCREATE, 0, (LPARAM) Cs);
    if (!Result)
    {
       DPRINT1("co_UserCreateWindowEx(): NCCREATE message failed\n");
@@ -2032,7 +2094,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
 
 
    /* Send the WM_CREATE message. */
-   Result = co_IntSendMessage(Window->head.h, WM_CREATE, 0, (LPARAM) Cs);
+   Result = co_IntSendMessage(UserHMGetHandle(Window), WM_CREATE, 0, (LPARAM) Cs);
    if (Result == (LRESULT)-1)
    {
       DPRINT1("co_UserCreateWindowEx(): WM_CREATE message failed\n");
@@ -2040,7 +2102,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
    }
 
    /* Send the EVENT_OBJECT_CREATE event*/
-   IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_WINDOW, 0);
+   IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_WINDOW, CHILDID_SELF, 0);
 
    /* By setting the flag below it can be examined to determine if the window
       was created successfully and a valid pwnd was passed back to caller since
@@ -2102,7 +2164,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
 
       if (Window->ExStyle & WS_EX_MDICHILD)
       {
-        co_IntSendMessage(ParentWindow->head.h, WM_MDIREFRESHMENU, 0, 0);
+        co_IntSendMessage(UserHMGetHandle(ParentWindow), WM_MDIREFRESHMENU, 0, 0);
         /* ShowWindow won't activate child windows */
         co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
       }
@@ -2121,6 +2183,10 @@ CLEANUP:
            IntDereferenceClass(Class, pti->pDeskInfo, pti->ppi);
    }
 
+   if (pCsw) ExFreePoolWithTag(pCsw, TAG_HOOK);
+   if (pCbtCreate) ExFreePoolWithTag(pCbtCreate, TAG_HOOK);
+   RtlFreeAnsiString(&asClassName);
+
    if (Window)
    {
       UserDerefObjectCo(Window);
@@ -2280,7 +2346,7 @@ NtUserCreateWindowEx(
     /* Call the internal function */
     pwnd = co_UserCreateWindowEx(&Cs, &ustrClassName, plstrWindowName);
 
-       if(!pwnd)
+    if(!pwnd)
     {
         DPRINT1("co_UserCreateWindowEx failed!\n");
     }
@@ -2343,7 +2409,11 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window)
    /* If window was created successfully and it is hooked */
    if ((Window->state2 & WNDS2_WMCREATEMSGPROCESSED))
    {
-      if (co_HOOK_CallHooks(WH_CBT, HCBT_DESTROYWND, (WPARAM) hWnd, 0)) return FALSE;
+      if (co_HOOK_CallHooks(WH_CBT, HCBT_DESTROYWND, (WPARAM) hWnd, 0))
+      {
+         DPRINT1("Destroy Window WH_CBT Call Hook return!\n");
+         return FALSE;
+      }
    }
 
    /* Inform the parent */
index 7a95626..04c0fd7 100644 (file)
@@ -299,8 +299,10 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
    WinPosInitInternalPos(Wnd, &Size, &Wnd->rcWindow);
 
    if (co_HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)Wnd->head.h, ShowFlag))
+   {
+      DPRINT1("WinPosMinMaximize WH_CBT Call Hook return!\n");
       return SWP_NOSIZE | SWP_NOMOVE;
-
+   }
       if (Wnd->style & WS_MINIMIZE)
       {
          if (!co_IntSendMessageNoWait(Wnd->head.h, WM_QUERYOPEN, 0, 0))
@@ -385,7 +387,6 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
                }
             }
       }
-
    return(SwpFlags);
 }
 
@@ -1358,6 +1359,14 @@ co_WinPosSetWindowPos(
       co_IntSendMessageNoWait(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM) &WinPos);
    }
 
+   if ( WinPos.flags & SWP_FRAMECHANGED  || WinPos.flags & SWP_STATECHANGED ||
+      !(WinPos.flags & SWP_NOCLIENTSIZE) || !(WinPos.flags & SWP_NOCLIENTMOVE) )
+   {
+      PWND pWnd = UserGetWindowObject(WinPos.hwnd);
+      if (pWnd)
+         IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
+   }
+
    return TRUE;
 }