Author: ion Date: Wed Jan 24 02:10:13 2007 New Revision: 25608
URL: http://svn.reactos.org/svn/reactos?rev=25608&view=rev Log: - 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.
Modified: trunk/reactos/ntoskrnl/ex/timer.c
Modified: trunk/reactos/ntoskrnl/ex/timer.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/timer.c?rev=256... ============================================================================== --- trunk/reactos/ntoskrnl/ex/timer.c (original) +++ trunk/reactos/ntoskrnl/ex/timer.c Wed Jan 24 02:10:13 2007 @@ -79,7 +79,7 @@ /* Cancel the timer and remove its DPC and APC */ KeCancelTimer(&Timer->KeTimer); KeRemoveQueueDpc(&Timer->TimerDpc); - if (KeRemoveQueueApc(&Timer->TimerApc)) DerefsToDo = 2; + if (KeRemoveQueueApc(&Timer->TimerApc)) DerefsToDo++;
/* Add another dereference to do */ DerefsToDo++; @@ -101,7 +101,6 @@
/* Release lock and return */ KeReleaseSpinLock(&Thread->ActiveTimerListLock, OldIrql); - return; }
VOID @@ -200,7 +199,7 @@
/* Disable it */ Timer->ApcAssociated = FALSE; - DerefsToDo = 2; + DerefsToDo++; } } else @@ -306,7 +305,7 @@ /* Cancel the Timer */ KeCancelTimer(&Timer->KeTimer); KeRemoveQueueDpc(&Timer->TimerDpc); - if (KeRemoveQueueApc(&Timer->TimerApc)) DerefsToDo = 2; + if (KeRemoveQueueApc(&Timer->TimerApc)) DerefsToDo++; DerefsToDo++; } else @@ -351,7 +350,7 @@ } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) { - Status = _SEH_GetExceptionCode(); + } _SEH_END; } @@ -374,6 +373,14 @@ NTSTATUS Status = STATUS_SUCCESS; PAGED_CODE();
+ /* Check for correct timer type */ + if ((TimerType != NotificationTimer) && + (TimerType != SynchronizationTimer)) + { + /* Fail */ + return STATUS_INVALID_PARAMETER_4; + } + /* Check Parameter Validity */ if (PreviousMode != KernelMode) { @@ -387,12 +394,6 @@ } _SEH_END; if(!NT_SUCCESS(Status)) return Status; - } - - /* Check for correct timer type */ - if ((TimerType != NotificationTimer) && (TimerType != SynchronizationTimer)) - { - return STATUS_INVALID_PARAMETER_4; }
/* Create the Object */ @@ -427,16 +428,20 @@ NULL, &hTimer);
- /* Make sure it's safe to write to the handle */ - _SEH_TRY - { - *TimerHandle = hTimer; - } - _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; + /* Check for success */ + if (NT_SUCCESS(Status)) + { + /* Make sure it's safe to write to the handle */ + _SEH_TRY + { + *TimerHandle = hTimer; + } + _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) + { + + } + _SEH_END; + } }
/* Return to Caller */ @@ -486,7 +491,7 @@ } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) { - Status = _SEH_GetExceptionCode(); + } _SEH_END; } @@ -578,13 +583,16 @@ NTSTATUS Status = STATUS_SUCCESS; PAGED_CODE();
+ /* Check for a valid Period */ + if (Period < 0) return STATUS_INVALID_PARAMETER_6; + /* Check Parameter Validity */ if (PreviousMode != KernelMode) { _SEH_TRY { TimerDueTime = ProbeForReadLargeInteger(DueTime); - if(PreviousState) ProbeForWriteBoolean(PreviousState); + if (PreviousState) ProbeForWriteBoolean(PreviousState); } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) { @@ -593,9 +601,6 @@ _SEH_END; if(!NT_SUCCESS(Status)) return Status; } - - /* Check for a valid Period */ - if (Period < 0) return STATUS_INVALID_PARAMETER_6;
/* Get the Timer Object */ Status = ObReferenceObjectByHandle(TimerHandle, @@ -640,7 +645,7 @@ /* Cancel the Timer */ KeCancelTimer(&Timer->KeTimer); KeRemoveQueueDpc(&Timer->TimerDpc); - if (KeRemoveQueueApc(&Timer->TimerApc)) DerefsToDo = 2; + if (KeRemoveQueueApc(&Timer->TimerApc)) DerefsToDo++; DerefsToDo++; } else @@ -653,6 +658,7 @@ State = KeReadStateTimer(&Timer->KeTimer);
/* Handle Wake Timers */ + Timer->WakeTimer = WakeTimer; KeAcquireSpinLockAtDpcLevel(&ExpWakeListLock); if ((WakeTimer) && !(Timer->WakeTimerListEntry.Flink)) { @@ -713,7 +719,6 @@ } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) { - Status = _SEH_GetExceptionCode(); } _SEH_END; }