sync with trunk head (34904)
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / hook.c
index 9be66f5..8250467 100644 (file)
@@ -1,27 +1,8 @@
 /*
- *  ReactOS W32 Subsystem
- *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/* $Id$
- *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
  * PURPOSE:          Window hooks
- * FILE:             subsys/win32k/ntuser/hook.c
+ * FILE:             subsystem/win32/win32k/ntuser/hook.c
  * PROGRAMER:        Casper S. Hornstrup (chorns@users.sourceforge.net)
  * REVISION HISTORY:
  *       06-06-2001  CSH  Created
 #define NDEBUG
 #include <debug.h>
 
-#define HOOKID_TO_INDEX(HookId) (HookId - WH_MINHOOK)
-#define HOOKID_TO_FLAG(HookId) (1 << ((HookId) + 1))
-
 static PHOOKTABLE GlobalHooks;
 
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+
 /* create a new hook table */
 static PHOOKTABLE
 IntAllocHookTable(void)
@@ -122,11 +104,14 @@ IntAddHook(PETHREAD Thread, int HookId, BOOLEAN Global, PWINSTATION_OBJECT WinSt
    Hook->Thread = Thread;
    Hook->HookId = HookId;
 
-   W32Thread = ((PW32THREAD)Thread->Tcb.Win32Thread);
-   ASSERT(W32Thread != NULL);
-   W32Thread->Hooks |= HOOKID_TO_FLAG(HookId);
-   if (W32Thread->ThreadInfo != NULL)
-       W32Thread->ThreadInfo->Hooks = W32Thread->Hooks;
+   if (Thread)
+   {
+      W32Thread = ((PW32THREAD)Thread->Tcb.Win32Thread);
+      ASSERT(W32Thread != NULL);
+      W32Thread->Hooks |= HOOKID_TO_FLAG(HookId);
+      if (W32Thread->ThreadInfo != NULL)
+          W32Thread->ThreadInfo->Hooks = W32Thread->Hooks;
+   }
 
    RtlInitUnicodeString(&Hook->ModuleName, NULL);
 
@@ -176,7 +161,8 @@ IntGetFirstValidHook(PHOOKTABLE Table, int HookId)
 }
 
 /* find the next hook in the chain, skipping the deleted ones */
-static PHOOK FASTCALL
+PHOOK
+FASTCALL
 IntGetNextHook(PHOOK Hook)
 {
    PHOOKTABLE Table = IntGetTable(Hook);
@@ -288,17 +274,22 @@ IntCallLowLevelHook(INT HookId, INT Code, WPARAM wParam, LPARAM lParam, PHOOK Ho
 
    /* FIXME should get timeout from
     * HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
-   Status = co_MsqSendMessage(((PW32THREAD)Hook->Thread->Tcb.Win32Thread)->MessageQueue, (HWND) Code, HookId,
+   Status = co_MsqSendMessage(((PW32THREAD)Hook->Thread->Tcb.Win32Thread)->MessageQueue, (HWND)(INT_PTR) Code, HookId,
                               wParam, lParam, 5000, TRUE, TRUE, &uResult);
 
    return NT_SUCCESS(Status) ? uResult : 0;
 }
 
-LRESULT FASTCALL
+/*
+  Called from inside kernel space.
+ */
+LRESULT
+FASTCALL
 co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
 {
-   PHOOK Hook;
+   PHOOK Hook, SaveHook;
    PW32THREAD Win32Thread;
+   PW32CLIENTINFO ClientInfo;
    PHOOKTABLE Table;
    LRESULT Result;
    PWINSTATION_OBJECT WinStaObj;
@@ -333,7 +324,7 @@ co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
       return IntCallLowLevelHook(HookId, Code, wParam, lParam, Hook);
    }
 
-   if (Hook->Thread != PsGetCurrentThread())
+   if ((Hook->Thread != PsGetCurrentThread()) && (Hook->Thread != NULL))
    {
       DPRINT1("Calling hooks in other threads not implemented yet");
       return 0;
@@ -345,9 +336,15 @@ co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
       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,
@@ -409,20 +406,472 @@ HOOK_DestroyThreadHooks(PETHREAD Thread)
                break;
          }
       }
+   }
+}
 
-      ObDereferenceObject(WinStaObj);
+static LRESULT
+FASTCALL
+co_HOOK_CallHookNext(PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam)
+{
+   DPRINT("CALLING HOOK %d\n",Hook->HookId);
+   return co_IntCallHookProc(Hook->HookId, Code, wParam, lParam, Hook->Proc,
+                                  Hook->Ansi, &Hook->ModuleName);
+}
+
+
+LRESULT
+FASTCALL
+IntCallDebugHook(
+   PHOOK Hook,
+   int Code,
+   WPARAM wParam,
+   LPARAM lParam)
+{
+   LRESULT lResult = 0;
+   ULONG Size;
+   DEBUGHOOKINFO Debug;
+   PVOID HooklParam = NULL;
+   BOOL BadChk = FALSE;
+
+   if (lParam)
+   {
+      _SEH_TRY
+      {
+          ProbeForRead((PVOID)lParam,
+                       sizeof(DEBUGHOOKINFO),
+                                   1);
+          RtlCopyMemory( &Debug,
+                  (PVOID)lParam,
+                  sizeof(DEBUGHOOKINFO));
+      }
+      _SEH_HANDLE
+      {
+          BadChk = TRUE;
+      }
+      _SEH_END;
+      if (BadChk)
+      {
+          DPRINT1("HOOK WH_DEBUG read from lParam ERROR!\n");
+          return lResult;
+      }
    }
+   else
+      return lResult; // Need lParam!
+
+   switch (wParam)
+   {
+      case WH_CBT:
+      {
+         switch (Debug.code)
+         {
+            case HCBT_CLICKSKIPPED:
+               Size = sizeof(MOUSEHOOKSTRUCTEX);
+               break;
+            case HCBT_MOVESIZE:
+               Size = sizeof(RECT);
+               break;
+            case HCBT_ACTIVATE:
+               Size = sizeof(CBTACTIVATESTRUCT); 
+               break;
+            case HCBT_CREATEWND: // Handle Ansi?
+               Size = sizeof(CBT_CREATEWND);
+               // What shall we do? Size += sizeof(CREATESTRUCTEX);
+               break;
+            default:
+               Size = sizeof(LPARAM);
+         }
+      }
+      break;
+
+      case WH_MOUSE_LL:
+         Size = sizeof(MSLLHOOKSTRUCT);
+      break;
+
+      case WH_KEYBOARD_LL:
+         Size = sizeof(KBDLLHOOKSTRUCT);
+      break;
+
+      case WH_MSGFILTER:
+      case WH_SYSMSGFILTER:
+      case WH_GETMESSAGE:
+         Size = sizeof(MSG);
+      break;
+
+      case WH_JOURNALPLAYBACK:
+      case WH_JOURNALRECORD:
+         Size = sizeof(EVENTMSG);
+      break;
+
+      case WH_FOREGROUNDIDLE:
+      case WH_KEYBOARD:
+      case WH_SHELL:
+      default:
+         Size = sizeof(LPARAM);
+   }
+
+   if (Size > sizeof(LPARAM))
+      HooklParam = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_HOOK);
+
+   if (HooklParam)
+   {
+      _SEH_TRY
+      {
+          ProbeForRead((PVOID)Debug.lParam,
+                                      Size,
+                                         1);
+          RtlCopyMemory( HooklParam,
+                (PVOID)Debug.lParam,
+                               Size);
+      }
+      _SEH_HANDLE
+      {
+          BadChk = TRUE;
+      }
+      _SEH_END;
+      if (BadChk)
+      {
+          DPRINT1("HOOK WH_DEBUG read from Debug.lParam ERROR!\n");
+          ExFreePool(HooklParam);
+          return lResult;
+      }
+   }
+
+   if (HooklParam) Debug.lParam = (LPARAM)HooklParam;
+   lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Debug);
+   if (HooklParam) ExFreePool(HooklParam);
+   return lResult;
+}
+
+/*
+   Called from user space via CallNextHook.
+ */
+LRESULT
+FASTCALL
+UserCallNextHookEx(
+   PHOOK Hook,
+   int Code,
+   WPARAM wParam,
+   LPARAM lParam,
+   BOOL Ansi)
+{
+  LRESULT lResult = 0;
+  BOOL BadChk = FALSE;
+
+// Handle this one first.
+  if ((Hook->HookId == WH_MOUSE) ||
+      (Hook->HookId == WH_CBT && Code == HCBT_CLICKSKIPPED))
+  {
+     MOUSEHOOKSTRUCTEX Mouse;
+     if (lParam)
+     {
+        _SEH_TRY
+        {
+           ProbeForRead((PVOID)lParam,
+                        sizeof(MOUSEHOOKSTRUCTEX),
+                                    1);
+           RtlCopyMemory( &Mouse,
+                   (PVOID)lParam,
+                   sizeof(MOUSEHOOKSTRUCTEX));
+        }
+        _SEH_HANDLE
+        {
+           BadChk = TRUE;
+        }
+        _SEH_END;
+        if (BadChk)
+        {
+            DPRINT1("HOOK WH_MOUSE read from lParam ERROR!\n");
+        }
+     }
+     if (!BadChk)
+     {
+        lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Mouse);
+     }
+     return lResult;
+  }
+
+  switch(Hook->HookId)
+  {
+      case WH_MOUSE_LL:
+      {
+         MSLLHOOKSTRUCT Mouse;
+         if (lParam)
+         {
+            _SEH_TRY
+            {
+                ProbeForRead((PVOID)lParam,
+                             sizeof(MSLLHOOKSTRUCT),
+                                         1);
+                RtlCopyMemory( &Mouse,
+                        (PVOID)lParam,
+                        sizeof(MSLLHOOKSTRUCT));
+            }
+            _SEH_HANDLE
+            {
+               BadChk = TRUE;
+            }
+            _SEH_END;
+            if (BadChk)
+            {
+                DPRINT1("HOOK WH_MOUSE_LL read from lParam ERROR!\n");
+            }
+         }
+         if (!BadChk)
+         {
+            lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Mouse);
+         }
+         break;
+      }
+
+      case WH_KEYBOARD_LL:
+      {
+         KBDLLHOOKSTRUCT Keyboard;
+         if (lParam)
+         {
+            _SEH_TRY
+            {
+                ProbeForRead((PVOID)lParam,
+                             sizeof(KBDLLHOOKSTRUCT),
+                                         1);
+                RtlCopyMemory( &Keyboard,
+                        (PVOID)lParam,
+                        sizeof(KBDLLHOOKSTRUCT));
+            }
+            _SEH_HANDLE
+            {
+               BadChk = TRUE;
+            }
+            _SEH_END;
+            if (BadChk)
+            {
+                DPRINT1("HOOK WH_KEYBORD_LL read from lParam ERROR!\n");
+            }
+         }
+         if (!BadChk)
+         {
+            lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Keyboard);
+         }
+         break;
+      }
+
+      case WH_MSGFILTER:
+      case WH_SYSMSGFILTER:
+      case WH_GETMESSAGE:
+      {
+         MSG Msg;
+         if (lParam)
+         {
+            _SEH_TRY
+            {
+               ProbeForRead((PVOID)lParam,
+                               sizeof(MSG),
+                                         1);
+               RtlCopyMemory( &Msg,
+                     (PVOID)lParam,
+                       sizeof(MSG));
+            }
+            _SEH_HANDLE
+            {
+              BadChk = TRUE;
+            }
+            _SEH_END;
+            if (BadChk)
+            {
+               DPRINT1("HOOK WH_XMESSAGEX read from lParam ERROR!\n");
+            }
+         }
+         if (!BadChk)
+         {
+            lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&Msg);
+            if (lParam && (Hook->HookId == WH_GETMESSAGE))
+            {
+               _SEH_TRY
+               {
+                  ProbeForWrite((PVOID)lParam,
+                                  sizeof(MSG),
+                                            1);
+                  RtlCopyMemory((PVOID)lParam,
+                                         &Msg,
+                                  sizeof(MSG));
+               }
+               _SEH_HANDLE
+               {
+                 BadChk = TRUE;
+               }
+               _SEH_END;
+               if (BadChk)
+               {
+                  DPRINT1("HOOK WH_GETMESSAGE write to lParam ERROR!\n");
+               }
+            }
+         }
+         break;
+      }
+
+      case WH_CBT:
+         DPRINT1("HOOK WH_CBT!\n");
+         switch (Code)
+         {
+            case HCBT_CREATEWND: // Use Ansi.
+               DPRINT1("HOOK HCBT_CREATEWND\n");
+//               lResult = co_HOOK_CallHookNext(Hook, Code, wParam, lParam);
+               break;
+
+            case HCBT_MOVESIZE:
+            {
+               RECT rt;
+               DPRINT1("HOOK HCBT_MOVESIZE\n");
+               if (lParam)
+               {
+                  _SEH_TRY
+                  {
+                      ProbeForRead((PVOID)lParam,
+                                    sizeof(RECT),
+                                              1);
+                      RtlCopyMemory( &rt,
+                           (PVOID)lParam,
+                            sizeof(RECT));
+                  }
+                  _SEH_HANDLE
+                  {
+                     BadChk = TRUE;
+                  }
+                  _SEH_END;
+                  if (BadChk)
+                  {
+                      DPRINT1("HOOK HCBT_MOVESIZE read from lParam ERROR!\n");
+                   }
+               }
+               if (!BadChk)
+               {
+                   lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&rt);
+               }
+               break;
+            }
+
+            case HCBT_ACTIVATE:
+            {
+               CBTACTIVATESTRUCT CbAs;
+               DPRINT1("HOOK HCBT_ACTIVATE\n");
+               if (lParam)
+               {
+                  _SEH_TRY
+                  {
+                      ProbeForRead((PVOID)lParam,
+                                   sizeof(CBTACTIVATESTRUCT),
+                                              1);
+                      RtlCopyMemory( &CbAs,
+                             (PVOID)lParam,
+                             sizeof(CBTACTIVATESTRUCT));
+                  }
+                  _SEH_HANDLE
+                  {
+                     BadChk = TRUE;
+                  }
+                  _SEH_END;
+                  if (BadChk)
+                  {
+                      DPRINT1("HOOK HCBT_ACTIVATE read from lParam ERROR!\n");
+                   }
+               }
+               if (!BadChk)
+               {
+                   lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)&CbAs);
+               }
+               break;
+            }
+            /*
+                The rest just use default.
+             */
+            default:
+               DPRINT1("HOOK HCBT_ %d\n",Code);
+               lResult = co_HOOK_CallHookNext(Hook, Code, wParam, lParam);
+               break;
+         }
+         break;
+
+      case WH_JOURNALPLAYBACK:
+      case WH_JOURNALRECORD:
+      {
+         EVENTMSG EventMsg;
+         if (lParam)
+         {
+            _SEH_TRY
+            {
+                ProbeForRead((PVOID)lParam,
+                             sizeof(EVENTMSG),
+                                         1);
+                RtlCopyMemory( &EventMsg,
+                        (PVOID)lParam,
+                        sizeof(EVENTMSG));
+            }
+            _SEH_HANDLE
+            {
+               BadChk = TRUE;
+            }
+            _SEH_END;
+            if (BadChk)
+            {
+                DPRINT1("HOOK WH_JOURNAL read from lParam ERROR!\n");
+            }
+         }
+         if (!BadChk) 
+         {               
+            lResult = co_HOOK_CallHookNext(Hook, Code, wParam, (LPARAM)(lParam ? &EventMsg : NULL));
+            if (lParam)
+            {
+               _SEH_TRY
+               {
+                  ProbeForWrite((PVOID)lParam,
+                                  sizeof(EVENTMSG),
+                                            1);
+                  RtlCopyMemory((PVOID)lParam,
+                                         &EventMsg,
+                                  sizeof(EVENTMSG));
+               }
+               _SEH_HANDLE
+               {
+                 BadChk = TRUE;
+               }
+               _SEH_END;
+               if (BadChk)
+               {
+                  DPRINT1("HOOK WH_JOURNAL write to lParam ERROR!\n");
+               }
+            }
+         }
+         break;
+      }
+
+      case WH_DEBUG:
+         lResult = IntCallDebugHook(Hook, Code, wParam, lParam);
+         break;
+/*
+    Default the rest like, WH_FOREGROUNDIDLE, WH_KEYBOARD and WH_SHELL.
+ */
+      case WH_FOREGROUNDIDLE:
+      case WH_KEYBOARD:
+      case WH_SHELL:
+         lResult = co_HOOK_CallHookNext(Hook, Code, wParam, lParam);      
+         break;
+
+      default:
+         DPRINT1("Unsupported HOOK Id -> %d\n",Hook->HookId);
+         break;
+  }
+  return lResult; 
 }
 
 LRESULT
 STDCALL
 NtUserCallNextHookEx(
-   HHOOK Hook,
    int Code,
    WPARAM wParam,
-   LPARAM lParam)
+   LPARAM lParam,
+   BOOL Ansi)
 {
    PHOOK HookObj, NextObj;
+   PW32CLIENTINFO ClientInfo;
    PWINSTATION_OBJECT WinStaObj;
    NTSTATUS Status;
    DECLARE_RETURN(LRESULT);
@@ -434,30 +883,25 @@ NtUserCallNextHookEx(
                                            KernelMode,
                                            0,
                                            &WinStaObj);
-
-   if (! NT_SUCCESS(Status))
+   if (!NT_SUCCESS(Status))
    {
       SetLastNtError(Status);
-      RETURN( FALSE);
+      RETURN( 0);
    }
 
-   //Status = UserReferenceObjectByHandle(gHandleTable, Hook,
-   //                             otHookProc, (PVOID *) &HookObj);
    ObDereferenceObject(WinStaObj);
 
-   //  if (! NT_SUCCESS(Status))
-   //    {
-   //      DPRINT1("Invalid handle passed to NtUserCallNextHookEx\n");
-   //      SetLastNtError(Status);
-   //      RETURN( 0);
-   //    }
+   ClientInfo = GetWin32ClientInfo();
 
-   if (!(HookObj = IntGetHookObject(Hook)))
-   {
-      RETURN(0);
-   }
+   if (!ClientInfo) RETURN( 0);
 
-   ASSERT(Hook == HookObj->Self);
+   HookObj = ClientInfo->phkCurrent;
+
+   if (!HookObj) RETURN( 0);
+
+   UserReferenceObject(HookObj);
+
+   Ansi = HookObj->Ansi;
 
    if (NULL != HookObj->Thread && (HookObj->Thread != PsGetCurrentThread()))
    {
@@ -466,18 +910,13 @@ NtUserCallNextHookEx(
       SetLastWin32Error(ERROR_INVALID_HANDLE);
       RETURN( 0);
    }
-
+   
    NextObj = IntGetNextHook(HookObj);
+   ClientInfo->phkCurrent = NextObj; // Preset next hook from list.
+   UserCallNextHookEx( HookObj, Code, wParam, lParam, Ansi);
    UserDereferenceObject(HookObj);
-   if (NULL != NextObj)
-   {
-      DPRINT1("Calling next hook not implemented\n");
-      UNIMPLEMENTED
-      SetLastWin32Error(ERROR_NOT_SUPPORTED);
-      RETURN( 0);
-   }
 
-   RETURN( 0);
+   RETURN( (LRESULT)NextObj);
 
 CLEANUP:
    DPRINT("Leave NtUserCallNextHookEx, ret=%i\n",_ret_);
@@ -485,16 +924,16 @@ CLEANUP:
    END_CLEANUP;
 }
 
-DWORD
+HHOOK
 STDCALL
 NtUserSetWindowsHookAW(
-   DWORD Unknown0,
-   DWORD Unknown1,
-   DWORD Unknown2)
+   int idHook,
+   HOOKPROC lpfn,
+   BOOL Ansi)
 {
-   UNIMPLEMENTED
-
-   return 0;
+   UNICODE_STRING USModuleName;
+   RtlInitUnicodeString(&USModuleName, NULL);
+   return NtUserSetWindowsHookEx(NULL, &USModuleName, 0, idHook, lpfn, Ansi);
 }
 
 HHOOK
@@ -508,6 +947,7 @@ NtUserSetWindowsHookEx(
    BOOL Ansi)
 {
    PWINSTATION_OBJECT WinStaObj;
+   PW32CLIENTINFO ClientInfo;
    BOOLEAN Global;
    PETHREAD Thread;
    PHOOK Hook;
@@ -525,6 +965,8 @@ NtUserSetWindowsHookEx(
       RETURN( NULL);
    }
 
+   ClientInfo = GetWin32ClientInfo();
+
    if (ThreadId)  /* thread-local hook */
    {
       if (HookId == WH_JOURNALRECORD ||
@@ -539,7 +981,7 @@ NtUserSetWindowsHookEx(
       }
       Mod = NULL;
       Global = FALSE;
-      if (! NT_SUCCESS(PsLookupThreadByThreadId((HANDLE) ThreadId, &Thread)))
+      if (! NT_SUCCESS(PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)ThreadId, &Thread)))
       {
          DPRINT1("Invalid thread id 0x%x\n", ThreadId);
          SetLastWin32Error(ERROR_INVALID_PARAMETER);
@@ -583,9 +1025,14 @@ NtUserSetWindowsHookEx(
    }
 
    /* We only (partially) support local WH_CBT hooks and
-    * WH_KEYBOARD_LL/WH_MOUSE_LL hooks for now */
-   if ((WH_CBT != HookId || Global)
-         && WH_KEYBOARD_LL != HookId && WH_MOUSE_LL != HookId)
+    * WH_KEYBOARD_LL, WH_MOUSE_LL and WH_GETMESSAGE hooks for now 
+    */
+   if  (Global ||
+        WH_DEBUG == HookId ||
+        WH_JOURNALPLAYBACK == HookId ||
+        WH_JOURNALRECORD == HookId ||
+        WH_FOREGROUNDIDLE == HookId ||
+        WH_SHELL == HookId)
    {
 #if 0 /* Removed to get winEmbed working again */
       UNIMPLEMENTED
@@ -686,6 +1133,9 @@ NtUserSetWindowsHookEx(
    Hook->Ansi = Ansi;
    Handle = Hook->Self;
 
+// Clear the client threads next hook.
+   ClientInfo->phkCurrent = 0;
+   
    UserDereferenceObject(Hook);
    ObDereferenceObject(WinStaObj);
 
@@ -697,22 +1147,6 @@ CLEANUP:
    END_CLEANUP;
 }
 
-HWINEVENTHOOK
-STDCALL
-NtUserSetWinEventHook(
-   UINT eventMin,
-   UINT eventMax,
-   HMODULE hmodWinEventProc,
-   PUNICODE_STRING puString,
-   WINEVENTPROC lpfnWinEventProc,
-   DWORD idProcess,
-   DWORD idThread,
-   UINT dwflags)
-{
-   UNIMPLEMENTED
-
-   return 0;
-}
 
 BOOL
 STDCALL
@@ -762,14 +1196,4 @@ CLEANUP:
    END_CLEANUP;
 }
 
-DWORD
-STDCALL
-NtUserUnhookWinEvent(
-   HWINEVENTHOOK hWinEventHook)
-{
-   UNIMPLEMENTED
-
-   return 0;
-}
-
 /* EOF */