- Fix reference count bugs in executive timer implementation.

- Don't modify status when failing due to an access fault (NT doesn't!).
- Do parameter checks before bothering with expensive SEHing.

svn path=/trunk/; revision=25608
This commit is contained in:
Alex Ionescu 2007-01-23 23:10:13 +00:00
parent 36433ba5ec
commit 2ef08cc69b

View file

@ -79,7 +79,7 @@ ExTimerRundown(VOID)
/* Cancel the timer and remove its DPC and APC */ /* Cancel the timer and remove its DPC and APC */
KeCancelTimer(&Timer->KeTimer); KeCancelTimer(&Timer->KeTimer);
KeRemoveQueueDpc(&Timer->TimerDpc); KeRemoveQueueDpc(&Timer->TimerDpc);
if (KeRemoveQueueApc(&Timer->TimerApc)) DerefsToDo = 2; if (KeRemoveQueueApc(&Timer->TimerApc)) DerefsToDo++;
/* Add another dereference to do */ /* Add another dereference to do */
DerefsToDo++; DerefsToDo++;
@ -101,7 +101,6 @@ ExTimerRundown(VOID)
/* Release lock and return */ /* Release lock and return */
KeReleaseSpinLock(&Thread->ActiveTimerListLock, OldIrql); KeReleaseSpinLock(&Thread->ActiveTimerListLock, OldIrql);
return;
} }
VOID VOID
@ -200,7 +199,7 @@ ExpTimerApcKernelRoutine(IN PKAPC Apc,
/* Disable it */ /* Disable it */
Timer->ApcAssociated = FALSE; Timer->ApcAssociated = FALSE;
DerefsToDo = 2; DerefsToDo++;
} }
} }
else else
@ -306,7 +305,7 @@ NtCancelTimer(IN HANDLE TimerHandle,
/* Cancel the Timer */ /* Cancel the Timer */
KeCancelTimer(&Timer->KeTimer); KeCancelTimer(&Timer->KeTimer);
KeRemoveQueueDpc(&Timer->TimerDpc); KeRemoveQueueDpc(&Timer->TimerDpc);
if (KeRemoveQueueApc(&Timer->TimerApc)) DerefsToDo = 2; if (KeRemoveQueueApc(&Timer->TimerApc)) DerefsToDo++;
DerefsToDo++; DerefsToDo++;
} }
else else
@ -351,7 +350,7 @@ NtCancelTimer(IN HANDLE TimerHandle,
} }
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter) _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{ {
Status = _SEH_GetExceptionCode();
} }
_SEH_END; _SEH_END;
} }
@ -374,6 +373,14 @@ NtCreateTimer(OUT PHANDLE TimerHandle,
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE(); PAGED_CODE();
/* Check for correct timer type */
if ((TimerType != NotificationTimer) &&
(TimerType != SynchronizationTimer))
{
/* Fail */
return STATUS_INVALID_PARAMETER_4;
}
/* Check Parameter Validity */ /* Check Parameter Validity */
if (PreviousMode != KernelMode) if (PreviousMode != KernelMode)
{ {
@ -389,12 +396,6 @@ NtCreateTimer(OUT PHANDLE TimerHandle,
if(!NT_SUCCESS(Status)) return Status; if(!NT_SUCCESS(Status)) return Status;
} }
/* Check for correct timer type */
if ((TimerType != NotificationTimer) && (TimerType != SynchronizationTimer))
{
return STATUS_INVALID_PARAMETER_4;
}
/* Create the Object */ /* Create the Object */
Status = ObCreateObject(PreviousMode, Status = ObCreateObject(PreviousMode,
ExTimerType, ExTimerType,
@ -427,16 +428,20 @@ NtCreateTimer(OUT PHANDLE TimerHandle,
NULL, NULL,
&hTimer); &hTimer);
/* Make sure it's safe to write to the handle */ /* Check for success */
_SEH_TRY if (NT_SUCCESS(Status))
{ {
*TimerHandle = hTimer; /* Make sure it's safe to write to the handle */
_SEH_TRY
{
*TimerHandle = hTimer;
}
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{
}
_SEH_END;
} }
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
} }
/* Return to Caller */ /* Return to Caller */
@ -486,7 +491,7 @@ NtOpenTimer(OUT PHANDLE TimerHandle,
} }
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter) _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{ {
Status = _SEH_GetExceptionCode();
} }
_SEH_END; _SEH_END;
} }
@ -578,13 +583,16 @@ NtSetTimer(IN HANDLE TimerHandle,
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE(); PAGED_CODE();
/* Check for a valid Period */
if (Period < 0) return STATUS_INVALID_PARAMETER_6;
/* Check Parameter Validity */ /* Check Parameter Validity */
if (PreviousMode != KernelMode) if (PreviousMode != KernelMode)
{ {
_SEH_TRY _SEH_TRY
{ {
TimerDueTime = ProbeForReadLargeInteger(DueTime); TimerDueTime = ProbeForReadLargeInteger(DueTime);
if(PreviousState) ProbeForWriteBoolean(PreviousState); if (PreviousState) ProbeForWriteBoolean(PreviousState);
} }
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter) _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{ {
@ -594,9 +602,6 @@ NtSetTimer(IN HANDLE TimerHandle,
if(!NT_SUCCESS(Status)) return Status; if(!NT_SUCCESS(Status)) return Status;
} }
/* Check for a valid Period */
if (Period < 0) return STATUS_INVALID_PARAMETER_6;
/* Get the Timer Object */ /* Get the Timer Object */
Status = ObReferenceObjectByHandle(TimerHandle, Status = ObReferenceObjectByHandle(TimerHandle,
TIMER_MODIFY_STATE, TIMER_MODIFY_STATE,
@ -640,7 +645,7 @@ NtSetTimer(IN HANDLE TimerHandle,
/* Cancel the Timer */ /* Cancel the Timer */
KeCancelTimer(&Timer->KeTimer); KeCancelTimer(&Timer->KeTimer);
KeRemoveQueueDpc(&Timer->TimerDpc); KeRemoveQueueDpc(&Timer->TimerDpc);
if (KeRemoveQueueApc(&Timer->TimerApc)) DerefsToDo = 2; if (KeRemoveQueueApc(&Timer->TimerApc)) DerefsToDo++;
DerefsToDo++; DerefsToDo++;
} }
else else
@ -653,6 +658,7 @@ NtSetTimer(IN HANDLE TimerHandle,
State = KeReadStateTimer(&Timer->KeTimer); State = KeReadStateTimer(&Timer->KeTimer);
/* Handle Wake Timers */ /* Handle Wake Timers */
Timer->WakeTimer = WakeTimer;
KeAcquireSpinLockAtDpcLevel(&ExpWakeListLock); KeAcquireSpinLockAtDpcLevel(&ExpWakeListLock);
if ((WakeTimer) && !(Timer->WakeTimerListEntry.Flink)) if ((WakeTimer) && !(Timer->WakeTimerListEntry.Flink))
{ {
@ -713,7 +719,6 @@ NtSetTimer(IN HANDLE TimerHandle,
} }
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter) _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{ {
Status = _SEH_GetExceptionCode();
} }
_SEH_END; _SEH_END;
} }