2005-03-14 02:08:17 +00:00
|
|
|
/*
|
2007-01-15 07:33:42 +00:00
|
|
|
* PROJECT: ReactOS Kernel
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
2005-01-07 06:54:27 +00:00
|
|
|
* FILE: ntoskrnl/ex/timer.c
|
2005-08-05 06:53:56 +00:00
|
|
|
* PURPOSE: Executive Timer Implementation
|
2007-01-15 07:33:42 +00:00
|
|
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
2005-01-07 06:54:27 +00:00
|
|
|
*/
|
|
|
|
|
2007-01-15 07:33:42 +00:00
|
|
|
/* INCLUDES ******************************************************************/
|
2005-01-07 06:54:27 +00:00
|
|
|
|
|
|
|
#include <ntoskrnl.h>
|
2005-04-02 15:55:15 +00:00
|
|
|
#define NDEBUG
|
2007-01-15 07:33:42 +00:00
|
|
|
#include <debug.h>
|
2005-01-07 06:54:27 +00:00
|
|
|
|
2007-01-15 07:33:42 +00:00
|
|
|
/* GLOBALS *******************************************************************/
|
2005-01-07 06:54:27 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Timer Object Type */
|
2005-01-07 06:54:27 +00:00
|
|
|
POBJECT_TYPE ExTimerType = NULL;
|
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
KSPIN_LOCK ExpWakeListLock;
|
|
|
|
LIST_ENTRY ExpWakeList;
|
|
|
|
|
|
|
|
/* Timer Mapping */
|
2005-08-05 06:53:56 +00:00
|
|
|
static GENERIC_MAPPING ExpTimerMapping =
|
|
|
|
{
|
2005-02-14 05:36:04 +00:00
|
|
|
STANDARD_RIGHTS_READ | TIMER_QUERY_STATE,
|
|
|
|
STANDARD_RIGHTS_WRITE | TIMER_MODIFY_STATE,
|
|
|
|
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
|
|
|
|
TIMER_ALL_ACCESS
|
|
|
|
};
|
2005-01-07 06:54:27 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Timer Information Classes */
|
2005-08-05 06:53:56 +00:00
|
|
|
static const INFORMATION_CLASS_INFO ExTimerInfoClass[] =
|
|
|
|
{
|
2005-02-14 05:36:04 +00:00
|
|
|
/* TimerBasicInformation */
|
2021-05-02 19:00:51 +00:00
|
|
|
IQS_SAME(TIMER_BASIC_INFORMATION, ULONG, ICIF_QUERY),
|
2005-01-23 23:51:40 +00:00
|
|
|
};
|
2005-01-07 06:54:27 +00:00
|
|
|
|
2007-01-15 07:33:42 +00:00
|
|
|
/* PRIVATE FUNCTIONS *********************************************************/
|
2005-01-07 06:54:27 +00:00
|
|
|
|
Thread/Process Termination/Repeaing Rewrite + Fixes
---------------------------------------------------
- ps/cid.c:
* Moved CID Lookup functions here
- ps/security.c:
* Moved all security related functions here. Makes other files neater and security functions
easier to locate.
- ps/thread.c:
* Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and
renamed functions from Ps to Ki.
* Implemented PsIsSystemThread.
* Removed Reaper Thread Init (now obsolete).
* Renamed PiDeleteThread to PspDeleteThread.
* Moved Thread State functions from tinfo.c to here.
- ps/process.c:
* Removed Query/Set Process functions and moved to ps/query.c
* Renamed PiDeletePRocess to PspDeleteProcess
* Removed obsoleted Process Termination functions, moved persistent one to kill.c
- ps/create.c:
* Moved the security APIs to security.c
* Correctly implemented PsCreateSystemThread to actually create system threads.
- ps/suspend.c
* Rewrote Nt Executive functions to use Kernel functions.
* Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in
some aspects, especially the issue of the APC looping around the KeWaitXxx call and the
fact that the routines excluded/ignored the FreezeCount.
- ps/debug.c
* Fixed completely broken implementation of Get/SetThreadContext. The old version crashed
when called and did not work at all. Suspend Regression test now works.
* Moved Context<->TrapFrame functions to ke/i386/
* Combined Set/GetThreadContext APCs into a single one, and used special context structure.
- ps/query.c:
* Moved Thread/Process Query/Set Routines here.
- ps/tinfo.c:
* Removed.
- ps/kill.c
* Removed complicated Process Termination semantics and useless Attach/Detach in favor for
a much more lightweight function which performs the same tasks as before and actually works.
TaskManager can now terminate foreign processes.
* Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled
thread. This results in much less code as well as an increase in speed and less micro
management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without
requiring masks that were added as hacks to allow it.
* Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new
termination code.
* Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done
by Hartmut.
* Added PspDeletethread here.
* Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out-
lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions,
actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown,
and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate
Thread as documented.
* Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to
be compatible with the changes above.
* Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described
above, and moved each subsystem specific termination helper into its own subsytem.
* Improved NtTerminateProcess and added more debugging messages.
* Improved NtTerminateThread and added check against System Thread and made it compatible with
new implementation.
* Corrected PsTerminateSystemThread now that we support System Threads.
* Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the
port, and added tag to pool allocation (documented in pooltag.txt)
include/internal/*.h:
* Defined Scheduler Functions and misc new functions or renamed functions.
ke/apc.c:
* Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated
to a thread, as well as their APCs and DPCs.
REGRESSIONS FOUND: NONE
BUGS/REGRESSIOSN FIXED:
* Thread/Get Set Context now works.
* Suspend Regression test now works.
* Task manager can now kill foreign processes, even hung ones (like it should).
* ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks.
KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right
places. I just wanted to have this first part ready first, so that it won't get too big.
svn path=/trunk/; revision=14174
2005-03-18 05:53:04 +00:00
|
|
|
VOID
|
2007-01-15 07:33:42 +00:00
|
|
|
NTAPI
|
Thread/Process Termination/Repeaing Rewrite + Fixes
---------------------------------------------------
- ps/cid.c:
* Moved CID Lookup functions here
- ps/security.c:
* Moved all security related functions here. Makes other files neater and security functions
easier to locate.
- ps/thread.c:
* Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and
renamed functions from Ps to Ki.
* Implemented PsIsSystemThread.
* Removed Reaper Thread Init (now obsolete).
* Renamed PiDeleteThread to PspDeleteThread.
* Moved Thread State functions from tinfo.c to here.
- ps/process.c:
* Removed Query/Set Process functions and moved to ps/query.c
* Renamed PiDeletePRocess to PspDeleteProcess
* Removed obsoleted Process Termination functions, moved persistent one to kill.c
- ps/create.c:
* Moved the security APIs to security.c
* Correctly implemented PsCreateSystemThread to actually create system threads.
- ps/suspend.c
* Rewrote Nt Executive functions to use Kernel functions.
* Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in
some aspects, especially the issue of the APC looping around the KeWaitXxx call and the
fact that the routines excluded/ignored the FreezeCount.
- ps/debug.c
* Fixed completely broken implementation of Get/SetThreadContext. The old version crashed
when called and did not work at all. Suspend Regression test now works.
* Moved Context<->TrapFrame functions to ke/i386/
* Combined Set/GetThreadContext APCs into a single one, and used special context structure.
- ps/query.c:
* Moved Thread/Process Query/Set Routines here.
- ps/tinfo.c:
* Removed.
- ps/kill.c
* Removed complicated Process Termination semantics and useless Attach/Detach in favor for
a much more lightweight function which performs the same tasks as before and actually works.
TaskManager can now terminate foreign processes.
* Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled
thread. This results in much less code as well as an increase in speed and less micro
management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without
requiring masks that were added as hacks to allow it.
* Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new
termination code.
* Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done
by Hartmut.
* Added PspDeletethread here.
* Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out-
lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions,
actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown,
and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate
Thread as documented.
* Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to
be compatible with the changes above.
* Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described
above, and moved each subsystem specific termination helper into its own subsytem.
* Improved NtTerminateProcess and added more debugging messages.
* Improved NtTerminateThread and added check against System Thread and made it compatible with
new implementation.
* Corrected PsTerminateSystemThread now that we support System Threads.
* Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the
port, and added tag to pool allocation (documented in pooltag.txt)
include/internal/*.h:
* Defined Scheduler Functions and misc new functions or renamed functions.
ke/apc.c:
* Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated
to a thread, as well as their APCs and DPCs.
REGRESSIONS FOUND: NONE
BUGS/REGRESSIOSN FIXED:
* Thread/Get Set Context now works.
* Suspend Regression test now works.
* Task manager can now kill foreign processes, even hung ones (like it should).
* ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks.
KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right
places. I just wanted to have this first part ready first, so that it won't get too big.
svn path=/trunk/; revision=14174
2005-03-18 05:53:04 +00:00
|
|
|
ExTimerRundown(VOID)
|
|
|
|
{
|
|
|
|
PETHREAD Thread = PsGetCurrentThread();
|
|
|
|
KIRQL OldIrql;
|
|
|
|
PLIST_ENTRY CurrentEntry;
|
|
|
|
PETIMER Timer;
|
2007-01-15 07:33:42 +00:00
|
|
|
ULONG DerefsToDo;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2007-01-15 07:33:42 +00:00
|
|
|
/* Lock the Thread's Active Timer List and loop it */
|
Thread/Process Termination/Repeaing Rewrite + Fixes
---------------------------------------------------
- ps/cid.c:
* Moved CID Lookup functions here
- ps/security.c:
* Moved all security related functions here. Makes other files neater and security functions
easier to locate.
- ps/thread.c:
* Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and
renamed functions from Ps to Ki.
* Implemented PsIsSystemThread.
* Removed Reaper Thread Init (now obsolete).
* Renamed PiDeleteThread to PspDeleteThread.
* Moved Thread State functions from tinfo.c to here.
- ps/process.c:
* Removed Query/Set Process functions and moved to ps/query.c
* Renamed PiDeletePRocess to PspDeleteProcess
* Removed obsoleted Process Termination functions, moved persistent one to kill.c
- ps/create.c:
* Moved the security APIs to security.c
* Correctly implemented PsCreateSystemThread to actually create system threads.
- ps/suspend.c
* Rewrote Nt Executive functions to use Kernel functions.
* Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in
some aspects, especially the issue of the APC looping around the KeWaitXxx call and the
fact that the routines excluded/ignored the FreezeCount.
- ps/debug.c
* Fixed completely broken implementation of Get/SetThreadContext. The old version crashed
when called and did not work at all. Suspend Regression test now works.
* Moved Context<->TrapFrame functions to ke/i386/
* Combined Set/GetThreadContext APCs into a single one, and used special context structure.
- ps/query.c:
* Moved Thread/Process Query/Set Routines here.
- ps/tinfo.c:
* Removed.
- ps/kill.c
* Removed complicated Process Termination semantics and useless Attach/Detach in favor for
a much more lightweight function which performs the same tasks as before and actually works.
TaskManager can now terminate foreign processes.
* Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled
thread. This results in much less code as well as an increase in speed and less micro
management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without
requiring masks that were added as hacks to allow it.
* Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new
termination code.
* Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done
by Hartmut.
* Added PspDeletethread here.
* Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out-
lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions,
actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown,
and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate
Thread as documented.
* Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to
be compatible with the changes above.
* Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described
above, and moved each subsystem specific termination helper into its own subsytem.
* Improved NtTerminateProcess and added more debugging messages.
* Improved NtTerminateThread and added check against System Thread and made it compatible with
new implementation.
* Corrected PsTerminateSystemThread now that we support System Threads.
* Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the
port, and added tag to pool allocation (documented in pooltag.txt)
include/internal/*.h:
* Defined Scheduler Functions and misc new functions or renamed functions.
ke/apc.c:
* Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated
to a thread, as well as their APCs and DPCs.
REGRESSIONS FOUND: NONE
BUGS/REGRESSIOSN FIXED:
* Thread/Get Set Context now works.
* Suspend Regression test now works.
* Task manager can now kill foreign processes, even hung ones (like it should).
* ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks.
KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right
places. I just wanted to have this first part ready first, so that it won't get too big.
svn path=/trunk/; revision=14174
2005-03-18 05:53:04 +00:00
|
|
|
KeAcquireSpinLock(&Thread->ActiveTimerListLock, &OldIrql);
|
2007-01-15 07:33:42 +00:00
|
|
|
CurrentEntry = Thread->ActiveTimerListHead.Flink;
|
|
|
|
while (CurrentEntry != &Thread->ActiveTimerListHead)
|
2005-05-06 22:25:30 +00:00
|
|
|
{
|
2007-01-15 07:33:42 +00:00
|
|
|
/* Get the timer */
|
2005-05-06 22:25:30 +00:00
|
|
|
Timer = CONTAINING_RECORD(CurrentEntry, ETIMER, ActiveTimerListEntry);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2007-01-15 07:33:42 +00:00
|
|
|
/* Reference it */
|
|
|
|
ObReferenceObject(Timer);
|
|
|
|
DerefsToDo = 1;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
Thread/Process Termination/Repeaing Rewrite + Fixes
---------------------------------------------------
- ps/cid.c:
* Moved CID Lookup functions here
- ps/security.c:
* Moved all security related functions here. Makes other files neater and security functions
easier to locate.
- ps/thread.c:
* Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and
renamed functions from Ps to Ki.
* Implemented PsIsSystemThread.
* Removed Reaper Thread Init (now obsolete).
* Renamed PiDeleteThread to PspDeleteThread.
* Moved Thread State functions from tinfo.c to here.
- ps/process.c:
* Removed Query/Set Process functions and moved to ps/query.c
* Renamed PiDeletePRocess to PspDeleteProcess
* Removed obsoleted Process Termination functions, moved persistent one to kill.c
- ps/create.c:
* Moved the security APIs to security.c
* Correctly implemented PsCreateSystemThread to actually create system threads.
- ps/suspend.c
* Rewrote Nt Executive functions to use Kernel functions.
* Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in
some aspects, especially the issue of the APC looping around the KeWaitXxx call and the
fact that the routines excluded/ignored the FreezeCount.
- ps/debug.c
* Fixed completely broken implementation of Get/SetThreadContext. The old version crashed
when called and did not work at all. Suspend Regression test now works.
* Moved Context<->TrapFrame functions to ke/i386/
* Combined Set/GetThreadContext APCs into a single one, and used special context structure.
- ps/query.c:
* Moved Thread/Process Query/Set Routines here.
- ps/tinfo.c:
* Removed.
- ps/kill.c
* Removed complicated Process Termination semantics and useless Attach/Detach in favor for
a much more lightweight function which performs the same tasks as before and actually works.
TaskManager can now terminate foreign processes.
* Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled
thread. This results in much less code as well as an increase in speed and less micro
management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without
requiring masks that were added as hacks to allow it.
* Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new
termination code.
* Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done
by Hartmut.
* Added PspDeletethread here.
* Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out-
lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions,
actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown,
and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate
Thread as documented.
* Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to
be compatible with the changes above.
* Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described
above, and moved each subsystem specific termination helper into its own subsytem.
* Improved NtTerminateProcess and added more debugging messages.
* Improved NtTerminateThread and added check against System Thread and made it compatible with
new implementation.
* Corrected PsTerminateSystemThread now that we support System Threads.
* Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the
port, and added tag to pool allocation (documented in pooltag.txt)
include/internal/*.h:
* Defined Scheduler Functions and misc new functions or renamed functions.
ke/apc.c:
* Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated
to a thread, as well as their APCs and DPCs.
REGRESSIONS FOUND: NONE
BUGS/REGRESSIOSN FIXED:
* Thread/Get Set Context now works.
* Suspend Regression test now works.
* Task manager can now kill foreign processes, even hung ones (like it should).
* ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks.
KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right
places. I just wanted to have this first part ready first, so that it won't get too big.
svn path=/trunk/; revision=14174
2005-03-18 05:53:04 +00:00
|
|
|
/* Unlock the list */
|
2007-01-15 07:33:42 +00:00
|
|
|
KeReleaseSpinLock(&Thread->ActiveTimerListLock, OldIrql);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
Thread/Process Termination/Repeaing Rewrite + Fixes
---------------------------------------------------
- ps/cid.c:
* Moved CID Lookup functions here
- ps/security.c:
* Moved all security related functions here. Makes other files neater and security functions
easier to locate.
- ps/thread.c:
* Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and
renamed functions from Ps to Ki.
* Implemented PsIsSystemThread.
* Removed Reaper Thread Init (now obsolete).
* Renamed PiDeleteThread to PspDeleteThread.
* Moved Thread State functions from tinfo.c to here.
- ps/process.c:
* Removed Query/Set Process functions and moved to ps/query.c
* Renamed PiDeletePRocess to PspDeleteProcess
* Removed obsoleted Process Termination functions, moved persistent one to kill.c
- ps/create.c:
* Moved the security APIs to security.c
* Correctly implemented PsCreateSystemThread to actually create system threads.
- ps/suspend.c
* Rewrote Nt Executive functions to use Kernel functions.
* Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in
some aspects, especially the issue of the APC looping around the KeWaitXxx call and the
fact that the routines excluded/ignored the FreezeCount.
- ps/debug.c
* Fixed completely broken implementation of Get/SetThreadContext. The old version crashed
when called and did not work at all. Suspend Regression test now works.
* Moved Context<->TrapFrame functions to ke/i386/
* Combined Set/GetThreadContext APCs into a single one, and used special context structure.
- ps/query.c:
* Moved Thread/Process Query/Set Routines here.
- ps/tinfo.c:
* Removed.
- ps/kill.c
* Removed complicated Process Termination semantics and useless Attach/Detach in favor for
a much more lightweight function which performs the same tasks as before and actually works.
TaskManager can now terminate foreign processes.
* Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled
thread. This results in much less code as well as an increase in speed and less micro
management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without
requiring masks that were added as hacks to allow it.
* Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new
termination code.
* Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done
by Hartmut.
* Added PspDeletethread here.
* Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out-
lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions,
actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown,
and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate
Thread as documented.
* Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to
be compatible with the changes above.
* Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described
above, and moved each subsystem specific termination helper into its own subsytem.
* Improved NtTerminateProcess and added more debugging messages.
* Improved NtTerminateThread and added check against System Thread and made it compatible with
new implementation.
* Corrected PsTerminateSystemThread now that we support System Threads.
* Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the
port, and added tag to pool allocation (documented in pooltag.txt)
include/internal/*.h:
* Defined Scheduler Functions and misc new functions or renamed functions.
ke/apc.c:
* Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated
to a thread, as well as their APCs and DPCs.
REGRESSIONS FOUND: NONE
BUGS/REGRESSIOSN FIXED:
* Thread/Get Set Context now works.
* Suspend Regression test now works.
* Task manager can now kill foreign processes, even hung ones (like it should).
* ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks.
KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right
places. I just wanted to have this first part ready first, so that it won't get too big.
svn path=/trunk/; revision=14174
2005-03-18 05:53:04 +00:00
|
|
|
/* Lock the Timer */
|
2007-01-15 07:33:42 +00:00
|
|
|
KeAcquireSpinLock(&Timer->Lock, &OldIrql);
|
|
|
|
|
|
|
|
/* Lock the list again */
|
|
|
|
KeAcquireSpinLockAtDpcLevel(&Thread->ActiveTimerListLock);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2007-01-15 07:33:42 +00:00
|
|
|
/* Make sure that the timer is valid */
|
|
|
|
if ((Timer->ApcAssociated) && (&Thread->Tcb == Timer->TimerApc.Thread))
|
|
|
|
{
|
|
|
|
/* Remove it from the list */
|
|
|
|
RemoveEntryList(&Timer->ActiveTimerListEntry);
|
|
|
|
Timer->ApcAssociated = FALSE;
|
|
|
|
|
|
|
|
/* Cancel the timer and remove its DPC and APC */
|
|
|
|
KeCancelTimer(&Timer->KeTimer);
|
|
|
|
KeRemoveQueueDpc(&Timer->TimerDpc);
|
2007-01-23 23:10:13 +00:00
|
|
|
if (KeRemoveQueueApc(&Timer->TimerApc)) DerefsToDo++;
|
2007-01-15 07:33:42 +00:00
|
|
|
|
|
|
|
/* Add another dereference to do */
|
|
|
|
DerefsToDo++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Unlock the list */
|
|
|
|
KeReleaseSpinLockFromDpcLevel(&Thread->ActiveTimerListLock);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
Thread/Process Termination/Repeaing Rewrite + Fixes
---------------------------------------------------
- ps/cid.c:
* Moved CID Lookup functions here
- ps/security.c:
* Moved all security related functions here. Makes other files neater and security functions
easier to locate.
- ps/thread.c:
* Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and
renamed functions from Ps to Ki.
* Implemented PsIsSystemThread.
* Removed Reaper Thread Init (now obsolete).
* Renamed PiDeleteThread to PspDeleteThread.
* Moved Thread State functions from tinfo.c to here.
- ps/process.c:
* Removed Query/Set Process functions and moved to ps/query.c
* Renamed PiDeletePRocess to PspDeleteProcess
* Removed obsoleted Process Termination functions, moved persistent one to kill.c
- ps/create.c:
* Moved the security APIs to security.c
* Correctly implemented PsCreateSystemThread to actually create system threads.
- ps/suspend.c
* Rewrote Nt Executive functions to use Kernel functions.
* Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in
some aspects, especially the issue of the APC looping around the KeWaitXxx call and the
fact that the routines excluded/ignored the FreezeCount.
- ps/debug.c
* Fixed completely broken implementation of Get/SetThreadContext. The old version crashed
when called and did not work at all. Suspend Regression test now works.
* Moved Context<->TrapFrame functions to ke/i386/
* Combined Set/GetThreadContext APCs into a single one, and used special context structure.
- ps/query.c:
* Moved Thread/Process Query/Set Routines here.
- ps/tinfo.c:
* Removed.
- ps/kill.c
* Removed complicated Process Termination semantics and useless Attach/Detach in favor for
a much more lightweight function which performs the same tasks as before and actually works.
TaskManager can now terminate foreign processes.
* Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled
thread. This results in much less code as well as an increase in speed and less micro
management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without
requiring masks that were added as hacks to allow it.
* Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new
termination code.
* Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done
by Hartmut.
* Added PspDeletethread here.
* Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out-
lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions,
actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown,
and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate
Thread as documented.
* Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to
be compatible with the changes above.
* Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described
above, and moved each subsystem specific termination helper into its own subsytem.
* Improved NtTerminateProcess and added more debugging messages.
* Improved NtTerminateThread and added check against System Thread and made it compatible with
new implementation.
* Corrected PsTerminateSystemThread now that we support System Threads.
* Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the
port, and added tag to pool allocation (documented in pooltag.txt)
include/internal/*.h:
* Defined Scheduler Functions and misc new functions or renamed functions.
ke/apc.c:
* Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated
to a thread, as well as their APCs and DPCs.
REGRESSIONS FOUND: NONE
BUGS/REGRESSIOSN FIXED:
* Thread/Get Set Context now works.
* Suspend Regression test now works.
* Task manager can now kill foreign processes, even hung ones (like it should).
* ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks.
KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right
places. I just wanted to have this first part ready first, so that it won't get too big.
svn path=/trunk/; revision=14174
2005-03-18 05:53:04 +00:00
|
|
|
/* Unlock the Timer */
|
|
|
|
KeReleaseSpinLock(&Timer->Lock, OldIrql);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-08-05 06:53:56 +00:00
|
|
|
/* Dereference it */
|
2007-01-15 07:33:42 +00:00
|
|
|
ObDereferenceObjectEx(Timer, DerefsToDo);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
Thread/Process Termination/Repeaing Rewrite + Fixes
---------------------------------------------------
- ps/cid.c:
* Moved CID Lookup functions here
- ps/security.c:
* Moved all security related functions here. Makes other files neater and security functions
easier to locate.
- ps/thread.c:
* Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and
renamed functions from Ps to Ki.
* Implemented PsIsSystemThread.
* Removed Reaper Thread Init (now obsolete).
* Renamed PiDeleteThread to PspDeleteThread.
* Moved Thread State functions from tinfo.c to here.
- ps/process.c:
* Removed Query/Set Process functions and moved to ps/query.c
* Renamed PiDeletePRocess to PspDeleteProcess
* Removed obsoleted Process Termination functions, moved persistent one to kill.c
- ps/create.c:
* Moved the security APIs to security.c
* Correctly implemented PsCreateSystemThread to actually create system threads.
- ps/suspend.c
* Rewrote Nt Executive functions to use Kernel functions.
* Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in
some aspects, especially the issue of the APC looping around the KeWaitXxx call and the
fact that the routines excluded/ignored the FreezeCount.
- ps/debug.c
* Fixed completely broken implementation of Get/SetThreadContext. The old version crashed
when called and did not work at all. Suspend Regression test now works.
* Moved Context<->TrapFrame functions to ke/i386/
* Combined Set/GetThreadContext APCs into a single one, and used special context structure.
- ps/query.c:
* Moved Thread/Process Query/Set Routines here.
- ps/tinfo.c:
* Removed.
- ps/kill.c
* Removed complicated Process Termination semantics and useless Attach/Detach in favor for
a much more lightweight function which performs the same tasks as before and actually works.
TaskManager can now terminate foreign processes.
* Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled
thread. This results in much less code as well as an increase in speed and less micro
management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without
requiring masks that were added as hacks to allow it.
* Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new
termination code.
* Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done
by Hartmut.
* Added PspDeletethread here.
* Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out-
lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions,
actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown,
and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate
Thread as documented.
* Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to
be compatible with the changes above.
* Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described
above, and moved each subsystem specific termination helper into its own subsytem.
* Improved NtTerminateProcess and added more debugging messages.
* Improved NtTerminateThread and added check against System Thread and made it compatible with
new implementation.
* Corrected PsTerminateSystemThread now that we support System Threads.
* Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the
port, and added tag to pool allocation (documented in pooltag.txt)
include/internal/*.h:
* Defined Scheduler Functions and misc new functions or renamed functions.
ke/apc.c:
* Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated
to a thread, as well as their APCs and DPCs.
REGRESSIONS FOUND: NONE
BUGS/REGRESSIOSN FIXED:
* Thread/Get Set Context now works.
* Suspend Regression test now works.
* Task manager can now kill foreign processes, even hung ones (like it should).
* ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks.
KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right
places. I just wanted to have this first part ready first, so that it won't get too big.
svn path=/trunk/; revision=14174
2005-03-18 05:53:04 +00:00
|
|
|
/* Loop again */
|
|
|
|
KeAcquireSpinLock(&Thread->ActiveTimerListLock, &OldIrql);
|
2007-01-15 07:33:42 +00:00
|
|
|
CurrentEntry = Thread->ActiveTimerListHead.Flink;
|
2005-05-09 01:38:29 +00:00
|
|
|
}
|
|
|
|
|
2005-08-05 06:53:56 +00:00
|
|
|
/* Release lock and return */
|
Thread/Process Termination/Repeaing Rewrite + Fixes
---------------------------------------------------
- ps/cid.c:
* Moved CID Lookup functions here
- ps/security.c:
* Moved all security related functions here. Makes other files neater and security functions
easier to locate.
- ps/thread.c:
* Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and
renamed functions from Ps to Ki.
* Implemented PsIsSystemThread.
* Removed Reaper Thread Init (now obsolete).
* Renamed PiDeleteThread to PspDeleteThread.
* Moved Thread State functions from tinfo.c to here.
- ps/process.c:
* Removed Query/Set Process functions and moved to ps/query.c
* Renamed PiDeletePRocess to PspDeleteProcess
* Removed obsoleted Process Termination functions, moved persistent one to kill.c
- ps/create.c:
* Moved the security APIs to security.c
* Correctly implemented PsCreateSystemThread to actually create system threads.
- ps/suspend.c
* Rewrote Nt Executive functions to use Kernel functions.
* Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in
some aspects, especially the issue of the APC looping around the KeWaitXxx call and the
fact that the routines excluded/ignored the FreezeCount.
- ps/debug.c
* Fixed completely broken implementation of Get/SetThreadContext. The old version crashed
when called and did not work at all. Suspend Regression test now works.
* Moved Context<->TrapFrame functions to ke/i386/
* Combined Set/GetThreadContext APCs into a single one, and used special context structure.
- ps/query.c:
* Moved Thread/Process Query/Set Routines here.
- ps/tinfo.c:
* Removed.
- ps/kill.c
* Removed complicated Process Termination semantics and useless Attach/Detach in favor for
a much more lightweight function which performs the same tasks as before and actually works.
TaskManager can now terminate foreign processes.
* Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled
thread. This results in much less code as well as an increase in speed and less micro
management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without
requiring masks that were added as hacks to allow it.
* Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new
termination code.
* Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done
by Hartmut.
* Added PspDeletethread here.
* Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out-
lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions,
actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown,
and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate
Thread as documented.
* Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to
be compatible with the changes above.
* Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described
above, and moved each subsystem specific termination helper into its own subsytem.
* Improved NtTerminateProcess and added more debugging messages.
* Improved NtTerminateThread and added check against System Thread and made it compatible with
new implementation.
* Corrected PsTerminateSystemThread now that we support System Threads.
* Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the
port, and added tag to pool allocation (documented in pooltag.txt)
include/internal/*.h:
* Defined Scheduler Functions and misc new functions or renamed functions.
ke/apc.c:
* Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated
to a thread, as well as their APCs and DPCs.
REGRESSIONS FOUND: NONE
BUGS/REGRESSIOSN FIXED:
* Thread/Get Set Context now works.
* Suspend Regression test now works.
* Task manager can now kill foreign processes, even hung ones (like it should).
* ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks.
KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right
places. I just wanted to have this first part ready first, so that it won't get too big.
svn path=/trunk/; revision=14174
2005-03-18 05:53:04 +00:00
|
|
|
KeReleaseSpinLock(&Thread->ActiveTimerListLock, OldIrql);
|
|
|
|
}
|
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
VOID
|
2007-01-15 07:33:42 +00:00
|
|
|
NTAPI
|
|
|
|
ExpDeleteTimer(IN PVOID ObjectBody)
|
2005-01-07 06:54:27 +00:00
|
|
|
{
|
2005-02-14 05:36:04 +00:00
|
|
|
KIRQL OldIrql;
|
|
|
|
PETIMER Timer = ObjectBody;
|
|
|
|
|
|
|
|
/* Check if it has a Wait List */
|
2007-01-15 07:33:42 +00:00
|
|
|
if (Timer->WakeTimerListEntry.Flink)
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
|
|
|
/* Lock the Wake List */
|
|
|
|
KeAcquireSpinLock(&ExpWakeListLock, &OldIrql);
|
|
|
|
|
|
|
|
/* Check again, since it might've changed before we locked */
|
2007-01-15 07:33:42 +00:00
|
|
|
if (Timer->WakeTimerListEntry.Flink)
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
|
|
|
/* Remove it from the Wait List */
|
|
|
|
RemoveEntryList(&Timer->WakeTimerListEntry);
|
2007-01-15 07:33:42 +00:00
|
|
|
Timer->WakeTimerListEntry.Flink = NULL;
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-08-05 06:53:56 +00:00
|
|
|
/* Release the Wake List */
|
|
|
|
KeReleaseSpinLock(&ExpWakeListLock, OldIrql);
|
2005-02-14 05:36:04 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2007-01-15 07:33:42 +00:00
|
|
|
/* Tell the Kernel to cancel the Timer and flush all queued DPCs */
|
2005-02-14 05:36:04 +00:00
|
|
|
KeCancelTimer(&Timer->KeTimer);
|
2007-01-15 07:33:42 +00:00
|
|
|
KeFlushQueuedDpcs();
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|
|
|
|
|
2012-12-19 23:49:13 +00:00
|
|
|
_Function_class_(KDEFERRED_ROUTINE)
|
2005-05-09 01:38:29 +00:00
|
|
|
VOID
|
2007-01-15 07:33:42 +00:00
|
|
|
NTAPI
|
|
|
|
ExpTimerDpcRoutine(IN PKDPC Dpc,
|
|
|
|
IN PVOID DeferredContext,
|
|
|
|
IN PVOID SystemArgument1,
|
|
|
|
IN PVOID SystemArgument2)
|
2005-01-07 06:54:27 +00:00
|
|
|
{
|
2007-01-15 07:33:42 +00:00
|
|
|
PETIMER Timer = DeferredContext;
|
|
|
|
BOOLEAN Inserted = FALSE;
|
2005-02-14 05:36:04 +00:00
|
|
|
|
2007-01-15 07:33:42 +00:00
|
|
|
/* Reference the timer */
|
|
|
|
if (!ObReferenceObjectSafe(Timer)) return;
|
2005-02-14 05:36:04 +00:00
|
|
|
|
|
|
|
/* Lock the Timer */
|
2007-01-15 07:33:42 +00:00
|
|
|
KeAcquireSpinLockAtDpcLevel(&Timer->Lock);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2007-01-15 07:33:42 +00:00
|
|
|
/* Check if the timer is associated */
|
|
|
|
if (Timer->ApcAssociated)
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2007-01-15 07:33:42 +00:00
|
|
|
/* Queue the APC */
|
|
|
|
Inserted = KeInsertQueueApc(&Timer->TimerApc,
|
|
|
|
SystemArgument1,
|
|
|
|
SystemArgument2,
|
|
|
|
IO_NO_INCREMENT);
|
2005-02-14 05:36:04 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Release the Timer */
|
2007-01-15 07:33:42 +00:00
|
|
|
KeReleaseSpinLockFromDpcLevel(&Timer->Lock);
|
2005-01-07 06:54:27 +00:00
|
|
|
|
2007-01-15 07:33:42 +00:00
|
|
|
/* Dereference it if we couldn't queue the APC */
|
|
|
|
if (!Inserted) ObDereferenceObject(Timer);
|
|
|
|
}
|
2005-01-07 06:54:27 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
VOID
|
2007-01-15 07:33:42 +00:00
|
|
|
NTAPI
|
|
|
|
ExpTimerApcKernelRoutine(IN PKAPC Apc,
|
|
|
|
IN OUT PKNORMAL_ROUTINE* NormalRoutine,
|
|
|
|
IN OUT PVOID* NormalContext,
|
|
|
|
IN OUT PVOID* SystemArgument1,
|
|
|
|
IN OUT PVOID* SystemArguemnt2)
|
2005-01-07 06:54:27 +00:00
|
|
|
{
|
2005-02-14 05:36:04 +00:00
|
|
|
PETIMER Timer;
|
|
|
|
KIRQL OldIrql;
|
2007-01-15 07:33:42 +00:00
|
|
|
ULONG DerefsToDo = 1;
|
|
|
|
PETHREAD Thread = PsGetCurrentThread();
|
2005-03-14 02:08:17 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* We need to find out which Timer we are */
|
|
|
|
Timer = CONTAINING_RECORD(Apc, ETIMER, TimerApc);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Lock the Timer */
|
|
|
|
KeAcquireSpinLock(&Timer->Lock, &OldIrql);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Lock the Thread's Active Timer List*/
|
2007-01-15 07:33:42 +00:00
|
|
|
KeAcquireSpinLockAtDpcLevel(&Thread->ActiveTimerListLock);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2007-01-15 07:33:42 +00:00
|
|
|
/* Make sure that the Timer is valid, and that it belongs to this thread */
|
|
|
|
if ((Timer->ApcAssociated) && (&Thread->Tcb == Timer->TimerApc.Thread))
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2007-01-15 07:33:42 +00:00
|
|
|
/* Check if it's not periodic */
|
|
|
|
if (!Timer->Period)
|
|
|
|
{
|
|
|
|
/* Remove it from the Active Timers List */
|
|
|
|
RemoveEntryList(&Timer->ActiveTimerListEntry);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2007-01-15 07:33:42 +00:00
|
|
|
/* Disable it */
|
|
|
|
Timer->ApcAssociated = FALSE;
|
2007-01-23 23:10:13 +00:00
|
|
|
DerefsToDo++;
|
2007-01-15 07:33:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Clear the normal routine */
|
|
|
|
*NormalRoutine = NULL;
|
2005-02-14 05:36:04 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2007-01-15 07:33:42 +00:00
|
|
|
/* Release locks */
|
|
|
|
KeReleaseSpinLockFromDpcLevel(&Thread->ActiveTimerListLock);
|
2005-02-14 05:36:04 +00:00
|
|
|
KeReleaseSpinLock(&Timer->Lock, OldIrql);
|
2007-01-15 07:33:42 +00:00
|
|
|
|
|
|
|
/* Dereference as needed */
|
|
|
|
ObDereferenceObjectEx(Timer, DerefsToDo);
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2020-05-23 13:56:10 +00:00
|
|
|
BOOLEAN
|
2007-01-15 07:33:42 +00:00
|
|
|
NTAPI
|
2005-01-07 06:54:27 +00:00
|
|
|
ExpInitializeTimerImplementation(VOID)
|
|
|
|
{
|
2005-05-15 17:59:33 +00:00
|
|
|
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
|
|
|
|
UNICODE_STRING Name;
|
2012-09-03 01:12:58 +00:00
|
|
|
NTSTATUS Status;
|
2005-05-15 17:59:33 +00:00
|
|
|
|
2007-01-15 07:33:42 +00:00
|
|
|
/* Create the Timer Object Type */
|
2005-05-15 17:59:33 +00:00
|
|
|
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
|
|
|
|
RtlInitUnicodeString(&Name, L"Timer");
|
|
|
|
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
|
2005-08-05 06:53:56 +00:00
|
|
|
ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
|
|
|
|
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(ETIMER);
|
2005-05-15 17:59:33 +00:00
|
|
|
ObjectTypeInitializer.GenericMapping = ExpTimerMapping;
|
|
|
|
ObjectTypeInitializer.PoolType = NonPagedPool;
|
|
|
|
ObjectTypeInitializer.ValidAccessMask = TIMER_ALL_ACCESS;
|
2005-08-05 06:53:56 +00:00
|
|
|
ObjectTypeInitializer.DeleteProcedure = ExpDeleteTimer;
|
2012-09-03 01:12:58 +00:00
|
|
|
Status = ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExTimerType);
|
|
|
|
if (!NT_SUCCESS(Status)) return FALSE;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Initialize the Wait List and Lock */
|
|
|
|
KeInitializeSpinLock(&ExpWakeListLock);
|
|
|
|
InitializeListHead(&ExpWakeList);
|
2012-09-03 01:12:58 +00:00
|
|
|
return TRUE;
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|
|
|
|
|
2007-01-15 07:33:42 +00:00
|
|
|
/* PUBLIC FUNCTIONS **********************************************************/
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
NTSTATUS
|
2007-01-15 07:33:42 +00:00
|
|
|
NTAPI
|
2005-01-07 06:54:27 +00:00
|
|
|
NtCancelTimer(IN HANDLE TimerHandle,
|
2005-02-14 05:36:04 +00:00
|
|
|
OUT PBOOLEAN CurrentState OPTIONAL)
|
2005-01-07 06:54:27 +00:00
|
|
|
{
|
2005-02-14 05:36:04 +00:00
|
|
|
PETIMER Timer;
|
2005-03-14 02:08:17 +00:00
|
|
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
2005-02-14 05:36:04 +00:00
|
|
|
BOOLEAN State;
|
|
|
|
KIRQL OldIrql;
|
|
|
|
PETHREAD TimerThread;
|
2007-01-15 07:33:42 +00:00
|
|
|
ULONG DerefsToDo = 1;
|
2009-08-26 17:31:02 +00:00
|
|
|
NTSTATUS Status;
|
2005-02-22 22:19:14 +00:00
|
|
|
PAGED_CODE();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Check if we need to probe */
|
2007-01-15 07:33:42 +00:00
|
|
|
if ((CurrentState) && (PreviousMode != KernelMode))
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Make sure the pointer is valid */
|
2005-08-21 17:38:07 +00:00
|
|
|
ProbeForWriteBoolean(CurrentState);
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
2009-08-26 17:31:02 +00:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Return the exception code */
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
2005-02-14 05:36:04 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2005-02-14 05:36:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the Timer Object */
|
|
|
|
Status = ObReferenceObjectByHandle(TimerHandle,
|
2005-08-05 06:53:56 +00:00
|
|
|
TIMER_MODIFY_STATE,
|
2005-02-14 05:36:04 +00:00
|
|
|
ExTimerType,
|
|
|
|
PreviousMode,
|
|
|
|
(PVOID*)&Timer,
|
|
|
|
NULL);
|
2007-01-16 01:27:36 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Lock the Timer */
|
|
|
|
KeAcquireSpinLock(&Timer->Lock, &OldIrql);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Check if it's enabled */
|
2005-08-05 06:53:56 +00:00
|
|
|
if (Timer->ApcAssociated)
|
|
|
|
{
|
2007-01-15 07:33:42 +00:00
|
|
|
/* Get the Thread. */
|
2007-01-16 01:27:36 +00:00
|
|
|
TimerThread = CONTAINING_RECORD(Timer->TimerApc.Thread,
|
|
|
|
ETHREAD,
|
|
|
|
Tcb);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Lock its active list */
|
|
|
|
KeAcquireSpinLockAtDpcLevel(&TimerThread->ActiveTimerListLock);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Remove it */
|
2015-09-01 17:52:09 +00:00
|
|
|
RemoveEntryList(&Timer->ActiveTimerListEntry);
|
2007-01-15 07:33:42 +00:00
|
|
|
Timer->ApcAssociated = FALSE;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Unlock the list */
|
|
|
|
KeReleaseSpinLockFromDpcLevel(&TimerThread->ActiveTimerListLock);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Cancel the Timer */
|
|
|
|
KeCancelTimer(&Timer->KeTimer);
|
|
|
|
KeRemoveQueueDpc(&Timer->TimerDpc);
|
2007-01-23 23:10:13 +00:00
|
|
|
if (KeRemoveQueueApc(&Timer->TimerApc)) DerefsToDo++;
|
2007-01-15 07:33:42 +00:00
|
|
|
DerefsToDo++;
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-02-14 05:36:04 +00:00
|
|
|
/* If timer was disabled, we still need to cancel it */
|
|
|
|
KeCancelTimer(&Timer->KeTimer);
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-08-05 06:53:56 +00:00
|
|
|
/* Handle a Wake Timer */
|
2007-01-15 07:33:42 +00:00
|
|
|
if (Timer->WakeTimerListEntry.Flink)
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
|
|
|
/* Lock the Wake List */
|
|
|
|
KeAcquireSpinLockAtDpcLevel(&ExpWakeListLock);
|
|
|
|
|
|
|
|
/* Check again, since it might've changed before we locked */
|
2007-01-15 07:33:42 +00:00
|
|
|
if (Timer->WakeTimerListEntry.Flink)
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
|
|
|
/* Remove it from the Wait List */
|
|
|
|
RemoveEntryList(&Timer->WakeTimerListEntry);
|
2007-01-15 07:33:42 +00:00
|
|
|
Timer->WakeTimerListEntry.Flink = NULL;
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Release the Wake List */
|
|
|
|
KeReleaseSpinLockFromDpcLevel(&ExpWakeListLock);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Unlock the Timer */
|
|
|
|
KeReleaseSpinLock(&Timer->Lock, OldIrql);
|
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Read the old State */
|
|
|
|
State = KeReadStateTimer(&Timer->KeTimer);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Dereference the Object */
|
2007-01-15 07:33:42 +00:00
|
|
|
ObDereferenceObjectEx(Timer, DerefsToDo);
|
2005-02-14 05:36:04 +00:00
|
|
|
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Check if caller wants the state */
|
2007-01-15 07:33:42 +00:00
|
|
|
if (CurrentState)
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Return the Timer State */
|
2005-02-14 05:36:04 +00:00
|
|
|
*CurrentState = State;
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_EXCEPT(ExSystemExceptionFilter())
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2012-12-19 23:49:13 +00:00
|
|
|
/* Do nothing */
|
|
|
|
(void)0;
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2005-02-14 05:36:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return to Caller */
|
|
|
|
return Status;
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
NTSTATUS
|
2007-01-15 07:33:42 +00:00
|
|
|
NTAPI
|
2005-01-07 06:54:27 +00:00
|
|
|
NtCreateTimer(OUT PHANDLE TimerHandle,
|
2005-02-14 05:36:04 +00:00
|
|
|
IN ACCESS_MASK DesiredAccess,
|
|
|
|
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
|
|
|
IN TIMER_TYPE TimerType)
|
2005-01-07 06:54:27 +00:00
|
|
|
{
|
2005-02-14 05:36:04 +00:00
|
|
|
PETIMER Timer;
|
|
|
|
HANDLE hTimer;
|
2005-03-14 02:08:17 +00:00
|
|
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
2009-08-26 17:31:02 +00:00
|
|
|
NTSTATUS Status;
|
2005-02-22 22:19:14 +00:00
|
|
|
PAGED_CODE();
|
2005-02-14 05:36:04 +00:00
|
|
|
|
2007-01-23 23:10:13 +00:00
|
|
|
/* Check for correct timer type */
|
|
|
|
if ((TimerType != NotificationTimer) &&
|
|
|
|
(TimerType != SynchronizationTimer))
|
|
|
|
{
|
|
|
|
/* Fail */
|
|
|
|
return STATUS_INVALID_PARAMETER_4;
|
|
|
|
}
|
|
|
|
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Check if we need to probe */
|
2005-08-05 06:53:56 +00:00
|
|
|
if (PreviousMode != KernelMode)
|
|
|
|
{
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Make sure the pointer is valid */
|
2005-08-21 17:38:07 +00:00
|
|
|
ProbeForWriteHandle(TimerHandle);
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
2009-08-26 17:31:02 +00:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Return the exception code */
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2005-02-14 05:36:04 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
|
|
/* Create the Object */
|
2005-02-14 05:36:04 +00:00
|
|
|
Status = ObCreateObject(PreviousMode,
|
2005-08-05 06:53:56 +00:00
|
|
|
ExTimerType,
|
|
|
|
ObjectAttributes,
|
|
|
|
PreviousMode,
|
|
|
|
NULL,
|
|
|
|
sizeof(ETIMER),
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
(PVOID*)&Timer);
|
2007-01-16 01:27:36 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2007-01-15 07:33:42 +00:00
|
|
|
/* Initialize the DPC */
|
|
|
|
KeInitializeDpc(&Timer->TimerDpc, ExpTimerDpcRoutine, Timer);
|
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Initialize the Kernel Timer */
|
|
|
|
KeInitializeTimerEx(&Timer->KeTimer, TimerType);
|
|
|
|
|
2007-01-15 07:33:42 +00:00
|
|
|
/* Initialize the timer fields */
|
2005-02-14 05:36:04 +00:00
|
|
|
KeInitializeSpinLock(&Timer->Lock);
|
|
|
|
Timer->ApcAssociated = FALSE;
|
|
|
|
Timer->WakeTimer = FALSE;
|
2007-01-15 07:33:42 +00:00
|
|
|
Timer->WakeTimerListEntry.Flink = NULL;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Insert the Timer */
|
|
|
|
Status = ObInsertObject((PVOID)Timer,
|
|
|
|
NULL,
|
|
|
|
DesiredAccess,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
&hTimer);
|
|
|
|
|
2007-01-23 23:10:13 +00:00
|
|
|
/* Check for success */
|
|
|
|
if (NT_SUCCESS(Status))
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Enter SEH */
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2007-01-23 23:10:13 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Return the Timer Handle */
|
2007-01-23 23:10:13 +00:00
|
|
|
*TimerHandle = hTimer;
|
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_EXCEPT(ExSystemExceptionFilter())
|
2007-01-23 23:10:13 +00:00
|
|
|
{
|
2012-12-19 23:49:13 +00:00
|
|
|
/* Do nothing */
|
|
|
|
(void)0;
|
2007-01-23 23:10:13 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
2005-02-14 05:36:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Return to Caller */
|
|
|
|
return Status;
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
NTSTATUS
|
2007-01-15 07:33:42 +00:00
|
|
|
NTAPI
|
2005-01-07 06:54:27 +00:00
|
|
|
NtOpenTimer(OUT PHANDLE TimerHandle,
|
2005-02-14 05:36:04 +00:00
|
|
|
IN ACCESS_MASK DesiredAccess,
|
|
|
|
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
2005-01-07 06:54:27 +00:00
|
|
|
{
|
2005-02-14 05:36:04 +00:00
|
|
|
HANDLE hTimer;
|
2005-03-14 02:08:17 +00:00
|
|
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
2009-08-26 17:31:02 +00:00
|
|
|
NTSTATUS Status;
|
2005-02-22 22:19:14 +00:00
|
|
|
PAGED_CODE();
|
2005-02-14 05:36:04 +00:00
|
|
|
|
|
|
|
/* Check Parameter Validity */
|
2005-08-05 06:53:56 +00:00
|
|
|
if (PreviousMode != KernelMode)
|
|
|
|
{
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Make sure the pointer is valid */
|
2005-08-21 17:38:07 +00:00
|
|
|
ProbeForWriteHandle(TimerHandle);
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_EXCEPT(ExSystemExceptionFilter())
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Return the exception code */
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2005-02-14 05:36:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Open the Timer */
|
|
|
|
Status = ObOpenObjectByName(ObjectAttributes,
|
|
|
|
ExTimerType,
|
|
|
|
PreviousMode,
|
2006-05-25 20:50:58 +00:00
|
|
|
NULL,
|
2005-02-14 05:36:04 +00:00
|
|
|
DesiredAccess,
|
|
|
|
NULL,
|
|
|
|
&hTimer);
|
2007-01-16 01:27:36 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Enter SEH */
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Return the Timer Handle */
|
2005-02-14 05:36:04 +00:00
|
|
|
*TimerHandle = hTimer;
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_EXCEPT(ExSystemExceptionFilter())
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2012-12-19 23:49:13 +00:00
|
|
|
/* Do nothing */
|
|
|
|
(void)0;
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2005-02-14 05:36:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Return to Caller */
|
|
|
|
return Status;
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
NTSTATUS
|
2007-01-15 07:33:42 +00:00
|
|
|
NTAPI
|
2005-01-07 06:54:27 +00:00
|
|
|
NtQueryTimer(IN HANDLE TimerHandle,
|
2005-02-14 05:36:04 +00:00
|
|
|
IN TIMER_INFORMATION_CLASS TimerInformationClass,
|
|
|
|
OUT PVOID TimerInformation,
|
|
|
|
IN ULONG TimerInformationLength,
|
2007-01-15 07:33:42 +00:00
|
|
|
OUT PULONG ReturnLength OPTIONAL)
|
2005-01-07 06:54:27 +00:00
|
|
|
{
|
2005-02-14 05:36:04 +00:00
|
|
|
PETIMER Timer;
|
2005-03-14 02:08:17 +00:00
|
|
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
2007-04-02 15:08:54 +00:00
|
|
|
NTSTATUS Status;
|
2007-01-15 07:33:42 +00:00
|
|
|
PTIMER_BASIC_INFORMATION BasicInfo = TimerInformation;
|
2005-02-22 22:19:14 +00:00
|
|
|
PAGED_CODE();
|
2005-03-14 02:08:17 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Check Validity */
|
2005-10-10 13:03:55 +00:00
|
|
|
Status = DefaultQueryInfoBufferCheck(TimerInformationClass,
|
|
|
|
ExTimerInfoClass,
|
2007-01-15 07:33:42 +00:00
|
|
|
sizeof(ExTimerInfoClass) /
|
|
|
|
sizeof(ExTimerInfoClass[0]),
|
2022-06-11 11:19:51 +00:00
|
|
|
ICIF_PROBE_READ_WRITE,
|
2005-10-10 13:03:55 +00:00
|
|
|
TimerInformation,
|
|
|
|
TimerInformationLength,
|
|
|
|
ReturnLength,
|
2010-01-13 22:35:43 +00:00
|
|
|
NULL,
|
2022-06-11 11:19:51 +00:00
|
|
|
PreviousMode);
|
2009-08-26 17:31:02 +00:00
|
|
|
if (!NT_SUCCESS(Status)) return Status;
|
2005-01-07 06:54:27 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Get the Timer Object */
|
|
|
|
Status = ObReferenceObjectByHandle(TimerHandle,
|
|
|
|
TIMER_QUERY_STATE,
|
|
|
|
ExTimerType,
|
2005-05-09 01:38:29 +00:00
|
|
|
PreviousMode,
|
2005-02-14 05:36:04 +00:00
|
|
|
(PVOID*)&Timer,
|
|
|
|
NULL);
|
2009-08-26 17:31:02 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Return the Basic Information */
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
|
|
|
/* Return the remaining time, corrected */
|
2007-01-16 01:27:36 +00:00
|
|
|
BasicInfo->TimeRemaining.QuadPart = Timer->
|
|
|
|
KeTimer.DueTime.QuadPart -
|
2005-08-05 06:53:56 +00:00
|
|
|
KeQueryInterruptTime();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-08-05 06:53:56 +00:00
|
|
|
/* Return the current state */
|
2005-03-14 02:08:17 +00:00
|
|
|
BasicInfo->SignalState = KeReadStateTimer(&Timer->KeTimer);
|
|
|
|
|
2005-08-05 06:53:56 +00:00
|
|
|
/* Return the buffer length if requested */
|
2007-01-16 01:27:36 +00:00
|
|
|
if (ReturnLength) *ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_EXCEPT(ExSystemExceptionFilter())
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Get the exception code */
|
2008-11-24 13:40:26 +00:00
|
|
|
Status = _SEH2_GetExceptionCode();
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Dereference Object */
|
2005-02-14 11:46:17 +00:00
|
|
|
ObDereferenceObject(Timer);
|
2005-02-14 05:36:04 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Return Status */
|
|
|
|
return Status;
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
NTSTATUS
|
2007-01-15 07:33:42 +00:00
|
|
|
NTAPI
|
2005-01-07 06:54:27 +00:00
|
|
|
NtSetTimer(IN HANDLE TimerHandle,
|
2005-02-14 05:36:04 +00:00
|
|
|
IN PLARGE_INTEGER DueTime,
|
|
|
|
IN PTIMER_APC_ROUTINE TimerApcRoutine OPTIONAL,
|
|
|
|
IN PVOID TimerContext OPTIONAL,
|
|
|
|
IN BOOLEAN WakeTimer,
|
|
|
|
IN LONG Period OPTIONAL,
|
|
|
|
OUT PBOOLEAN PreviousState OPTIONAL)
|
2005-01-07 06:54:27 +00:00
|
|
|
{
|
2005-02-14 05:36:04 +00:00
|
|
|
PETIMER Timer;
|
|
|
|
KIRQL OldIrql;
|
|
|
|
BOOLEAN State;
|
2005-03-14 02:08:17 +00:00
|
|
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
2007-01-15 07:33:42 +00:00
|
|
|
PETHREAD Thread = PsGetCurrentThread();
|
2005-02-14 05:36:04 +00:00
|
|
|
LARGE_INTEGER TimerDueTime;
|
|
|
|
PETHREAD TimerThread;
|
2007-01-15 07:33:42 +00:00
|
|
|
ULONG DerefsToDo = 1;
|
2005-02-22 22:19:14 +00:00
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
PAGED_CODE();
|
2005-02-14 05:36:04 +00:00
|
|
|
|
2007-01-23 23:10:13 +00:00
|
|
|
/* Check for a valid Period */
|
|
|
|
if (Period < 0) return STATUS_INVALID_PARAMETER_6;
|
|
|
|
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Check if we need to probe */
|
2005-08-05 06:53:56 +00:00
|
|
|
if (PreviousMode != KernelMode)
|
|
|
|
{
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Probe and capture the due time */
|
2005-08-21 17:38:07 +00:00
|
|
|
TimerDueTime = ProbeForReadLargeInteger(DueTime);
|
2009-08-26 17:31:02 +00:00
|
|
|
|
|
|
|
/* Probe the state pointer if one was passed */
|
2007-01-23 23:10:13 +00:00
|
|
|
if (PreviousState) ProbeForWriteBoolean(PreviousState);
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
2009-08-26 17:31:02 +00:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Return the exception code */
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2005-02-14 05:36:04 +00:00
|
|
|
}
|
2007-01-24 04:46:31 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Capture the time directly */
|
|
|
|
TimerDueTime = *DueTime;
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
|
|
/* Get the Timer Object */
|
2005-02-14 05:36:04 +00:00
|
|
|
Status = ObReferenceObjectByHandle(TimerHandle,
|
2005-08-05 06:53:56 +00:00
|
|
|
TIMER_MODIFY_STATE,
|
2005-02-14 05:36:04 +00:00
|
|
|
ExTimerType,
|
|
|
|
PreviousMode,
|
|
|
|
(PVOID*)&Timer,
|
|
|
|
NULL);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2012-12-19 23:49:13 +00:00
|
|
|
/*
|
2005-08-05 06:53:56 +00:00
|
|
|
* Tell the user we don't support Wake Timers...
|
2012-12-19 23:49:13 +00:00
|
|
|
* when we have the ability to use/detect the Power Management
|
2007-01-15 07:33:42 +00:00
|
|
|
* functionality required to support them, make this check dependent
|
2005-08-05 06:53:56 +00:00
|
|
|
* on the actual PM capabilities
|
|
|
|
*/
|
2022-04-04 00:10:37 +00:00
|
|
|
if (NT_SUCCESS(Status) && WakeTimer)
|
|
|
|
{
|
|
|
|
Status = STATUS_TIMER_RESUME_IGNORED;
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-08-05 06:53:56 +00:00
|
|
|
/* Check status */
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Lock the Timer */
|
|
|
|
KeAcquireSpinLock(&Timer->Lock, &OldIrql);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Cancel Running Timer */
|
2005-08-05 06:53:56 +00:00
|
|
|
if (Timer->ApcAssociated)
|
|
|
|
{
|
2007-01-15 07:33:42 +00:00
|
|
|
/* Get the Thread. */
|
|
|
|
TimerThread = CONTAINING_RECORD(Timer->TimerApc.Thread,
|
|
|
|
ETHREAD,
|
|
|
|
Tcb);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Lock its active list */
|
|
|
|
KeAcquireSpinLockAtDpcLevel(&TimerThread->ActiveTimerListLock);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Remove it */
|
2015-09-01 17:52:09 +00:00
|
|
|
RemoveEntryList(&Timer->ActiveTimerListEntry);
|
2007-01-15 07:33:42 +00:00
|
|
|
Timer->ApcAssociated = FALSE;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Unlock the list */
|
|
|
|
KeReleaseSpinLockFromDpcLevel(&TimerThread->ActiveTimerListLock);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Cancel the Timer */
|
|
|
|
KeCancelTimer(&Timer->KeTimer);
|
|
|
|
KeRemoveQueueDpc(&Timer->TimerDpc);
|
2007-01-23 23:10:13 +00:00
|
|
|
if (KeRemoveQueueApc(&Timer->TimerApc)) DerefsToDo++;
|
2007-01-15 07:33:42 +00:00
|
|
|
DerefsToDo++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-02-14 05:36:04 +00:00
|
|
|
/* If timer was disabled, we still need to cancel it */
|
|
|
|
KeCancelTimer(&Timer->KeTimer);
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Read the State */
|
|
|
|
State = KeReadStateTimer(&Timer->KeTimer);
|
|
|
|
|
|
|
|
/* Handle Wake Timers */
|
2007-01-23 23:10:13 +00:00
|
|
|
Timer->WakeTimer = WakeTimer;
|
2005-02-14 05:36:04 +00:00
|
|
|
KeAcquireSpinLockAtDpcLevel(&ExpWakeListLock);
|
2007-01-15 07:33:42 +00:00
|
|
|
if ((WakeTimer) && !(Timer->WakeTimerListEntry.Flink))
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Insert it into the list */
|
|
|
|
InsertTailList(&ExpWakeList, &Timer->WakeTimerListEntry);
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
2007-01-15 07:33:42 +00:00
|
|
|
else if (!(WakeTimer) && (Timer->WakeTimerListEntry.Flink))
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Remove it from the list */
|
|
|
|
RemoveEntryList(&Timer->WakeTimerListEntry);
|
2007-01-15 07:33:42 +00:00
|
|
|
Timer->WakeTimerListEntry.Flink = NULL;
|
2005-02-14 05:36:04 +00:00
|
|
|
}
|
|
|
|
KeReleaseSpinLockFromDpcLevel(&ExpWakeListLock);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Set up the APC Routine if specified */
|
2007-01-15 07:33:42 +00:00
|
|
|
Timer->Period = Period;
|
2005-08-05 06:53:56 +00:00
|
|
|
if (TimerApcRoutine)
|
|
|
|
{
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Initialize the APC */
|
|
|
|
KeInitializeApc(&Timer->TimerApc,
|
2007-01-15 07:33:42 +00:00
|
|
|
&Thread->Tcb,
|
2005-02-14 05:36:04 +00:00
|
|
|
CurrentApcEnvironment,
|
2007-01-24 04:46:31 +00:00
|
|
|
ExpTimerApcKernelRoutine,
|
2005-02-14 05:36:04 +00:00
|
|
|
(PKRUNDOWN_ROUTINE)NULL,
|
|
|
|
(PKNORMAL_ROUTINE)TimerApcRoutine,
|
|
|
|
PreviousMode,
|
|
|
|
TimerContext);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Lock the Thread's Active List and Insert */
|
2007-01-15 07:33:42 +00:00
|
|
|
KeAcquireSpinLockAtDpcLevel(&Thread->ActiveTimerListLock);
|
|
|
|
InsertTailList(&Thread->ActiveTimerListHead,
|
2005-02-14 05:36:04 +00:00
|
|
|
&Timer->ActiveTimerListEntry);
|
2007-01-15 07:33:42 +00:00
|
|
|
Timer->ApcAssociated = TRUE;
|
|
|
|
KeReleaseSpinLockFromDpcLevel(&Thread->ActiveTimerListLock);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2007-01-15 07:33:42 +00:00
|
|
|
/* One less dereference to do */
|
|
|
|
DerefsToDo--;
|
2005-02-14 05:36:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Enable and Set the Timer */
|
|
|
|
KeSetTimerEx(&Timer->KeTimer,
|
|
|
|
TimerDueTime,
|
|
|
|
Period,
|
2007-01-15 07:33:42 +00:00
|
|
|
TimerApcRoutine ? &Timer->TimerDpc : NULL);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-14 05:36:04 +00:00
|
|
|
/* Unlock the Timer */
|
|
|
|
KeReleaseSpinLock(&Timer->Lock, OldIrql);
|
|
|
|
|
|
|
|
/* Dereference if it was previously enabled */
|
2007-01-15 07:33:42 +00:00
|
|
|
if (DerefsToDo) ObDereferenceObjectEx(Timer, DerefsToDo);
|
2005-02-14 05:36:04 +00:00
|
|
|
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Check if we need to return the State */
|
2007-01-15 07:33:42 +00:00
|
|
|
if (PreviousState)
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Enter SEH */
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Return the Timer State */
|
2005-02-14 05:36:04 +00:00
|
|
|
*PreviousState = State;
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_EXCEPT(ExSystemExceptionFilter())
|
2005-08-05 06:53:56 +00:00
|
|
|
{
|
2012-12-19 23:49:13 +00:00
|
|
|
/* Do nothing */
|
|
|
|
(void)0;
|
2005-08-05 06:53:56 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2005-02-14 05:36:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return to Caller */
|
|
|
|
return Status;
|
2005-01-07 06:54:27 +00:00
|
|
|
}
|