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=25…
==============================================================================
--- 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;
}