- Revert 38750, a dereference happens when that hook is freed by IntFreeHook.

- Change thread dereferencing mechanism in NtUserSetWindowsHookEx:
 * A thread may be referenced in some cases when it's a system-wide hook, however dereference flag was not set for these, so they leaked a reference. Add a ThreadReferenced boolean var to track real references, and set hook's flag according to it.
 * There should be no need to call ObDereferenceObject on a thread when a call to IntRemoveHook was already performed (in failure branches). IntFreeHook() will dereference the thread object.

svn path=/trunk/; revision=38754
This commit is contained in:
Aleksey Bragin 2009-01-14 09:51:50 +00:00
parent 3bb7973d97
commit 2ed6687632

View file

@ -969,6 +969,7 @@ NtUserSetWindowsHookEx(
UNICODE_STRING ModuleName; UNICODE_STRING ModuleName;
NTSTATUS Status; NTSTATUS Status;
HHOOK Handle; HHOOK Handle;
BOOLEAN ThreadReferenced = FALSE;
DECLARE_RETURN(HHOOK); DECLARE_RETURN(HHOOK);
DPRINT("Enter NtUserSetWindowsHookEx\n"); DPRINT("Enter NtUserSetWindowsHookEx\n");
@ -1008,6 +1009,8 @@ NtUserSetWindowsHookEx(
SetLastWin32Error(ERROR_INVALID_PARAMETER); SetLastWin32Error(ERROR_INVALID_PARAMETER);
RETURN( NULL); RETURN( NULL);
} }
/* Thread was referenced */
ThreadReferenced = TRUE;
if (Thread->ThreadsProcess != PsGetCurrentProcess()) if (Thread->ThreadsProcess != PsGetCurrentProcess())
{ {
ObDereferenceObject(Thread); ObDereferenceObject(Thread);
@ -1032,6 +1035,9 @@ NtUserSetWindowsHookEx(
SetLastNtError(Status); SetLastNtError(Status);
RETURN( (HANDLE) NULL); RETURN( (HANDLE) NULL);
} }
/* Thread was referenced */
ThreadReferenced = TRUE;
} }
else if (NULL == Mod) else if (NULL == Mod)
{ {
@ -1056,10 +1062,8 @@ NtUserSetWindowsHookEx(
DPRINT1("Not implemented: HookId %d Global %s\n", HookId, Global ? "TRUE" : "FALSE"); DPRINT1("Not implemented: HookId %d Global %s\n", HookId, Global ? "TRUE" : "FALSE");
#endif #endif
if (NULL != Thread) /* Dereference thread if needed */
{ if (ThreadReferenced) ObDereferenceObject(Thread);
ObDereferenceObject(Thread);
}
SetLastWin32Error(ERROR_NOT_SUPPORTED); SetLastWin32Error(ERROR_NOT_SUPPORTED);
RETURN( NULL); RETURN( NULL);
} }
@ -1071,10 +1075,8 @@ NtUserSetWindowsHookEx(
if (! NT_SUCCESS(Status)) if (! NT_SUCCESS(Status))
{ {
if (NULL != Thread) /* Dereference thread if needed */
{ if (ThreadReferenced) ObDereferenceObject(Thread);
ObDereferenceObject(Thread);
}
SetLastNtError(Status); SetLastNtError(Status);
RETURN( (HANDLE) NULL); RETURN( (HANDLE) NULL);
} }
@ -1082,15 +1084,14 @@ NtUserSetWindowsHookEx(
Hook = IntAddHook(Thread, HookId, Global, WinStaObj); Hook = IntAddHook(Thread, HookId, Global, WinStaObj);
if (NULL == Hook) if (NULL == Hook)
{ {
if (NULL != Thread) /* Dereference thread if needed */
{ if (ThreadReferenced) ObDereferenceObject(Thread);
ObDereferenceObject(Thread);
}
ObDereferenceObject(WinStaObj); ObDereferenceObject(WinStaObj);
RETURN( NULL); RETURN( NULL);
} }
if (NULL != Thread) /* Let IntFreeHook now that this thread needs a dereference */
if (ThreadReferenced)
{ {
Hook->Flags |= HOOK_THREAD_REFERENCED; Hook->Flags |= HOOK_THREAD_REFERENCED;
} }
@ -1102,10 +1103,6 @@ NtUserSetWindowsHookEx(
{ {
UserDereferenceObject(Hook); UserDereferenceObject(Hook);
IntRemoveHook(Hook, WinStaObj, FALSE); IntRemoveHook(Hook, WinStaObj, FALSE);
if (NULL != Thread)
{
ObDereferenceObject(Thread);
}
ObDereferenceObject(WinStaObj); ObDereferenceObject(WinStaObj);
SetLastNtError(Status); SetLastNtError(Status);
RETURN( NULL); RETURN( NULL);
@ -1117,10 +1114,6 @@ NtUserSetWindowsHookEx(
{ {
UserDereferenceObject(Hook); UserDereferenceObject(Hook);
IntRemoveHook(Hook, WinStaObj, FALSE); IntRemoveHook(Hook, WinStaObj, FALSE);
if (NULL != Thread)
{
ObDereferenceObject(Thread);
}
ObDereferenceObject(WinStaObj); ObDereferenceObject(WinStaObj);
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
RETURN( NULL); RETURN( NULL);
@ -1134,10 +1127,6 @@ NtUserSetWindowsHookEx(
ExFreePoolWithTag(Hook->ModuleName.Buffer, TAG_HOOK); ExFreePoolWithTag(Hook->ModuleName.Buffer, TAG_HOOK);
UserDereferenceObject(Hook); UserDereferenceObject(Hook);
IntRemoveHook(Hook, WinStaObj, FALSE); IntRemoveHook(Hook, WinStaObj, FALSE);
if (NULL != Thread)
{
ObDereferenceObject(Thread);
}
ObDereferenceObject(WinStaObj); ObDereferenceObject(WinStaObj);
SetLastNtError(Status); SetLastNtError(Status);
RETURN( NULL); RETURN( NULL);
@ -1154,13 +1143,9 @@ NtUserSetWindowsHookEx(
// Clear the client threads next hook. // Clear the client threads next hook.
ClientInfo->phkCurrent = 0; ClientInfo->phkCurrent = 0;
UserDereferenceObject(Hook); UserDereferenceObject(Hook);
if (NULL != Thread)
{
ObDereferenceObject(Thread);
}
ObDereferenceObject(WinStaObj); ObDereferenceObject(WinStaObj);
RETURN( Handle); RETURN( Handle);