Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

timer.c File Reference

#include "exp.h"

Go to the source code of this file.

Classes

struct  _ETIMER

Typedefs

typedef _ETIMER ETIMER
typedef _ETIMERPETIMER

Functions

VOID ExpTimerApcRoutine (IN PKAPC Apc, IN PKNORMAL_ROUTINE *NormalRoutine, IN PVOID *NormalContext, IN PVOID *SystemArgument1, IN PVOID *SystemArgument2)
VOID ExpTimerDpcRoutine (IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
VOID ExpDeleteTimer (IN PVOID Object)
BOOLEAN ExpTimerInitialization ()
VOID ExTimerRundown ()
NTSTATUS NtCreateTimer (OUT PHANDLE TimerHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN TIMER_TYPE TimerType)
NTSTATUS NtOpenTimer (OUT PHANDLE TimerHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
NTSTATUS NtCancelTimer (IN HANDLE TimerHandle, OUT PBOOLEAN CurrentState OPTIONAL)
NTSTATUS NtQueryTimer (IN HANDLE TimerHandle, IN TIMER_INFORMATION_CLASS TimerInformationClass, OUT PVOID TimerInformation, IN ULONG TimerInformationLength, OUT PULONG ReturnLength OPTIONAL)
NTSTATUS NtSetTimer (IN HANDLE TimerHandle, 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)
VOID ExGetNextWakeTime (OUT PULONGLONG DueTime, OUT PTIME_FIELDS TimeFields, OUT PVOID *TimerObject)

Variables

KSPIN_LOCK ExpWakeTimerListLock
LIST_ENTRY ExpWakeTimerList
POBJECT_TYPE ExTimerObjectType
GENERIC_MAPPING ExpTimerMapping


Typedef Documentation

typedef struct _ETIMER ETIMER
 

typedef struct _ETIMER * PETIMER
 

Referenced by ExGetNextWakeTime(), ExpDeleteTimer(), ExpTimerApcRoutine(), ExpTimerDpcRoutine(), ExTimerRundown(), NtCancelTimer(), NtCreateTimer(), NtQueryTimer(), and NtSetTimer().


Function Documentation

VOID ExGetNextWakeTime OUT PULONGLONG  DueTime,
OUT PTIME_FIELDS  TimeFields,
OUT PVOID *  TimerObject
 

Definition at line 1212 of file timer.c.

References ExpWakeTimerList, ExpWakeTimerListLock, ExSystemTimeToLocalTime(), KeQueryInterruptTime(), KeQuerySystemTime(), KeQueryTimerDueTime(), _ETIMER::KeTimer, NULL, PETIMER, RtlTimeToTimeFields(), TimeFields, _ETIMER::WakeTimer, and _ETIMER::WakeTimerListEntry.

01217 { 01218 PLIST_ENTRY Link; 01219 PETIMER ExTimer; 01220 PETIMER BestTimer; 01221 KIRQL OldIrql; 01222 ULONGLONG TimerDueTime; 01223 ULONGLONG BestDueTime; 01224 ULONGLONG InterruptTime; 01225 LARGE_INTEGER SystemTime; 01226 LARGE_INTEGER CmosTime; 01227 01228 ExAcquireSpinLock(&ExpWakeTimerListLock, &OldIrql); 01229 BestDueTime = 0; 01230 BestTimer = NULL; 01231 Link = ExpWakeTimerList.Flink; 01232 while (Link != &ExpWakeTimerList) { 01233 ExTimer = CONTAINING_RECORD(Link, ETIMER, WakeTimerListEntry); 01234 Link = Link->Flink; 01235 01236 if (ExTimer->WakeTimer) { 01237 01238 TimerDueTime = KeQueryTimerDueTime(&ExTimer->KeTimer); 01239 TimerDueTime = 0 - TimerDueTime; 01240 01241 // 01242 // Is this timers due time closer? 01243 // 01244 01245 if (TimerDueTime > BestDueTime) { 01246 BestDueTime = TimerDueTime; 01247 BestTimer = ExTimer; 01248 } 01249 01250 } else { 01251 01252 // 01253 // Timer is not an active wake timer, remove it 01254 // 01255 01256 RemoveEntryList(&ExTimer->WakeTimerListEntry); 01257 ExTimer->WakeTimerListEntry.Flink = NULL; 01258 } 01259 } 01260 01261 ExReleaseSpinLock(&ExpWakeTimerListLock, OldIrql); 01262 01263 if (BestDueTime) { 01264 // 01265 // Convert time to timefields 01266 // 01267 01268 KeQuerySystemTime (&SystemTime); 01269 InterruptTime = KeQueryInterruptTime (); 01270 BestDueTime = 0 - BestDueTime; 01271 01272 SystemTime.QuadPart += BestDueTime - InterruptTime; 01273 01274 // 01275 // Many system alarms are only good to 1 second resolution. 01276 // Add one sceond to the target time so that the timer is really 01277 // elasped if this is the wake event. 01278 // 01279 01280 SystemTime.QuadPart += 10000000; 01281 01282 ExSystemTimeToLocalTime(&SystemTime,&CmosTime); 01283 RtlTimeToTimeFields(&CmosTime, TimeFields); 01284 } 01285 01286 *DueTime = BestDueTime; 01287 *TimerObject = BestTimer; 01288 }

VOID ExpDeleteTimer IN PVOID  Object  )  [static]
 

Definition at line 232 of file timer.c.

References ExpWakeTimerListLock, KeCancelTimer(), _ETIMER::KeTimer, NULL, PETIMER, and _ETIMER::WakeTimerListEntry.

Referenced by ExpTimerInitialization().

00238 : 00239 00240 This function is the delete routine for timer objects. Its function is 00241 to cancel the timer and free the spin lock associated with a timer. 00242 00243 Arguments: 00244 00245 Object - Supplies a pointer to an executive timer object. 00246 00247 Return Value: 00248 00249 None. 00250 00251 --*/ 00252 00253 { 00254 PETIMER ExTimer; 00255 KIRQL OldIrql; 00256 00257 ExTimer = (PETIMER) Object; 00258 00259 // 00260 // Remove from wake list 00261 // 00262 00263 if (ExTimer->WakeTimerListEntry.Flink) { 00264 ExAcquireSpinLock(&ExpWakeTimerListLock, &OldIrql); 00265 if (ExTimer->WakeTimerListEntry.Flink) { 00266 RemoveEntryList(&ExTimer->WakeTimerListEntry); 00267 ExTimer->WakeTimerListEntry.Flink = NULL; 00268 } 00269 ExReleaseSpinLock(&ExpWakeTimerListLock, OldIrql); 00270 } 00271 00272 // 00273 // Cancel the timer and free the spin lock associated with the timer. 00274 // 00275 00276 KeCancelTimer(&ExTimer->KeTimer); 00277 return; 00278 }

VOID ExpTimerApcRoutine IN PKAPC  Apc,
IN PKNORMAL_ROUTINE NormalRoutine,
IN PVOID *  NormalContext,
IN PVOID *  SystemArgument1,
IN PVOID *  SystemArgument2
 

Definition at line 81 of file timer.c.

References _ETIMER::ActiveTimerListEntry, _ETHREAD::ActiveTimerListLock, _ETIMER::ApcAssociated, FALSE, _ETIMER::Lock, NULL, ObDereferenceObject, _ETIMER::Period, PETIMER, PKNORMAL_ROUTINE, PsGetCurrentThread, _ETHREAD::Tcb, _KAPC::Thread, _ETIMER::TimerApc, and TRUE.

Referenced by NtSetTimer().

00091 : 00092 00093 This function is the special APC routine that is called to remove 00094 a timer from the current thread's active timer list. 00095 00096 Arguments: 00097 00098 Apc - Supplies a pointer to the APC object used to invoke this routine. 00099 00100 NormalRoutine - Supplies a pointer to a pointer to the normal routine 00101 function that was specified when the APC was initialized. 00102 00103 NormalContext - Supplies a pointer to a pointer to an arbitrary data 00104 structure that was specified when the APC was initialized. 00105 00106 SystemArgument1, SystemArgument2 - Supplies a set of two pointers to 00107 two arguments that contain untyped data. 00108 00109 Return Value: 00110 00111 None. 00112 00113 --*/ 00114 00115 { 00116 00117 BOOLEAN Dereference; 00118 PETHREAD ExThread; 00119 PETIMER ExTimer; 00120 KIRQL OldIrql1; 00121 00122 // 00123 // Get address of executive timer object and the current thread object. 00124 // 00125 00126 ExThread = PsGetCurrentThread(); 00127 ExTimer = CONTAINING_RECORD(Apc, ETIMER, TimerApc); 00128 00129 // 00130 // If the timer is still in the current thread's active timer list, then 00131 // remove it if it is not a periodic timer and set APC associated FALSE. 00132 // It is possible for the timer not to be in the current thread's active 00133 // timer list since the APC could have been delivered, and then another 00134 // thread could have set the timer again with another APC. This would 00135 // have caused the timer to be removed from the current thread's active 00136 // timer list. 00137 // 00138 // N. B. The spin locks for the timer and the active timer list must be 00139 // acquired in the order: 1) timer lock, 2) thread list lock. 00140 // 00141 00142 Dereference = FALSE; 00143 ExAcquireSpinLock(&ExTimer->Lock, &OldIrql1); 00144 ExAcquireSpinLockAtDpcLevel(&ExThread->ActiveTimerListLock); 00145 if ((ExTimer->ApcAssociated) && (&ExThread->Tcb == ExTimer->TimerApc.Thread)) { 00146 if (ExTimer->Period == 0) { 00147 RemoveEntryList(&ExTimer->ActiveTimerListEntry); 00148 ExTimer->ApcAssociated = FALSE; 00149 Dereference = TRUE; 00150 } 00151 00152 } else { 00153 *NormalRoutine = (PKNORMAL_ROUTINE)NULL; 00154 } 00155 00156 ExReleaseSpinLockFromDpcLevel(&ExThread->ActiveTimerListLock); 00157 ExReleaseSpinLock(&ExTimer->Lock, OldIrql1); 00158 if (Dereference) { 00159 ObDereferenceObject((PVOID)ExTimer); 00160 } 00161 00162 return; 00163 }

VOID ExpTimerDpcRoutine IN PKDPC  Dpc,
IN PVOID  DeferredContext,
IN PVOID  SystemArgument1,
IN PVOID  SystemArgument2
 

Definition at line 166 of file timer.c.

References _ETIMER::ApcAssociated, KeInsertQueueApc(), _ETIMER::KeTimer, _ETIMER::Lock, PETIMER, TIMER_APC_INCREMENT, and _ETIMER::TimerApc.

Referenced by NtCreateTimer().

00175 : 00176 00177 This function is the DPC routine that is called when a timer expires that 00178 has an associated APC routine. Its function is to insert the associated 00179 APC into the target thread's APC queue. 00180 00181 Arguments: 00182 00183 Dpc - Supplies a pointer to a control object of type DPC. 00184 00185 DeferredContext - Supplies a pointer to the executive timer that contains 00186 the DPC that caused this routine to be executed. 00187 00188 SystemArgument1, SystemArgument2 - Supplies values that are not used by 00189 this routine. 00190 00191 Return Value: 00192 00193 None. 00194 00195 --*/ 00196 00197 { 00198 00199 PETIMER ExTimer; 00200 PKTIMER KeTimer; 00201 KIRQL OldIrql; 00202 00203 // 00204 // Get address of executive and kernel timer objects. 00205 // 00206 00207 ExTimer = (PETIMER)DeferredContext; 00208 KeTimer = &ExTimer->KeTimer; 00209 00210 // 00211 // If there is still an APC associated with the timer, then insert the APC 00212 // in target thread's APC queue. It is possible that the timer does not 00213 // have an associated APC. This can happen when the timer is set to expire 00214 // by a thread running on another processor just after the DPC has been 00215 // removed from the DPC queue, but before it has acquired the timer related 00216 // spin lock. 00217 // 00218 00219 ExAcquireSpinLock(&ExTimer->Lock, &OldIrql); 00220 if (ExTimer->ApcAssociated) { 00221 KeInsertQueueApc(&ExTimer->TimerApc, 00222 SystemArgument1, 00223 SystemArgument2, 00224 TIMER_APC_INCREMENT); 00225 } 00226 00227 ExReleaseSpinLock(&ExTimer->Lock, OldIrql); 00228 return; 00229 }

BOOLEAN ExpTimerInitialization  ) 
 

Definition at line 281 of file timer.c.

References ExpDeleteTimer(), ExpTimerMapping, ExpWakeTimerList, ExpWakeTimerListLock, ExTimerObjectType, KeInitializeSpinLock(), L, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, ObCreateObjectType(), RtlInitUnicodeString(), and Status.

00286 : 00287 00288 This function creates the timer object type descriptor at system 00289 initialization and stores the address of the object type descriptor 00290 in local static storage. 00291 00292 Arguments: 00293 00294 None. 00295 00296 Return Value: 00297 00298 A value of TRUE is returned if the timer object type descriptor is 00299 successfully initialized. Otherwise a value of FALSE is returned. 00300 00301 --*/ 00302 00303 { 00304 00305 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; 00306 NTSTATUS Status; 00307 UNICODE_STRING TypeName; 00308 00309 KeInitializeSpinLock (&ExpWakeTimerListLock); 00310 InitializeListHead (&ExpWakeTimerList); 00311 00312 // 00313 // Initialize string descriptor. 00314 // 00315 00316 RtlInitUnicodeString(&TypeName, L"Timer"); 00317 00318 // 00319 // Create timer object type descriptor. 00320 // 00321 00322 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); 00323 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); 00324 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK; 00325 ObjectTypeInitializer.GenericMapping = ExpTimerMapping; 00326 ObjectTypeInitializer.PoolType = NonPagedPool; 00327 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(ETIMER); 00328 ObjectTypeInitializer.ValidAccessMask = TIMER_ALL_ACCESS; 00329 ObjectTypeInitializer.DeleteProcedure = ExpDeleteTimer; 00330 Status = ObCreateObjectType(&TypeName, 00331 &ObjectTypeInitializer, 00332 (PSECURITY_DESCRIPTOR)NULL, 00333 &ExTimerObjectType); 00334 00335 00336 00337 // 00338 // If the time object type descriptor was successfully created, then 00339 // return a value of TRUE. Otherwise return a value of FALSE. 00340 // 00341 00342 return (BOOLEAN)(NT_SUCCESS(Status)); 00343 }

VOID ExTimerRundown  ) 
 

Definition at line 346 of file timer.c.

References _ETIMER::ActiveTimerListEntry, _ETHREAD::ActiveTimerListHead, _ETHREAD::ActiveTimerListLock, _ETIMER::ApcAssociated, FALSE, KeCancelTimer(), KeRemoveQueueApc(), KeRemoveQueueDpc(), _ETIMER::KeTimer, _ETIMER::Lock, ObDereferenceObject, ObReferenceObject, PETIMER, PsGetCurrentThread, _ETHREAD::Tcb, _KAPC::Thread, _ETIMER::TimerApc, _ETIMER::TimerDpc, and TRUE.

Referenced by oops(), and PspExitThread().

00351 : 00352 00353 This function is called when a thread is about to be terminated to 00354 process the active timer list. It is assumed that APC's have been 00355 disabled for the subject thread, thus this code cannot be interrupted 00356 to execute an APC for the current thread. 00357 00358 Arguments: 00359 00360 None. 00361 00362 Return Value: 00363 00364 None. 00365 00366 --*/ 00367 00368 { 00369 00370 BOOLEAN Dereference; 00371 PETHREAD ExThread; 00372 PETIMER ExTimer; 00373 PLIST_ENTRY NextEntry; 00374 KIRQL OldIrql1; 00375 00376 // 00377 // Process each entry in the active timer list. 00378 // 00379 00380 ExThread = PsGetCurrentThread(); 00381 ExAcquireSpinLock(&ExThread->ActiveTimerListLock, &OldIrql1); 00382 NextEntry = ExThread->ActiveTimerListHead.Flink; 00383 while (NextEntry != &ExThread->ActiveTimerListHead) { 00384 ExTimer = CONTAINING_RECORD(NextEntry, ETIMER, ActiveTimerListEntry); 00385 00386 // 00387 // Increment the reference count on the object so that it cannot be 00388 // deleted, and then drop the active timer list lock. 00389 // 00390 // N. B. The object reference cannot fail and will acquire no mutexes. 00391 // 00392 00393 ObReferenceObject(ExTimer); 00394 ExReleaseSpinLock(&ExThread->ActiveTimerListLock, OldIrql1); 00395 00396 // 00397 // Acquire the timer spin lock and reacquire the active time list spin 00398 // lock. If the timer is still in the current thread's active timer 00399 // list, then cancel the timer, remove the timer's DPC from the DPC 00400 // queue, remove the timer's APC from the APC queue, remove the timer 00401 // from the thread's active timer list, and set the associate APC 00402 // flag FALSE. 00403 // 00404 // N. B. The spin locks for the timer and the active timer list must be 00405 // acquired in the order: 1) timer lock, 2) thread list lock. 00406 // 00407 00408 ExAcquireSpinLock(&ExTimer->Lock, &OldIrql1); 00409 ExAcquireSpinLockAtDpcLevel(&ExThread->ActiveTimerListLock); 00410 if ((ExTimer->ApcAssociated) && (&ExThread->Tcb == ExTimer->TimerApc.Thread)) { 00411 RemoveEntryList(&ExTimer->ActiveTimerListEntry); 00412 ExTimer->ApcAssociated = FALSE; 00413 KeCancelTimer(&ExTimer->KeTimer); 00414 KeRemoveQueueDpc(&ExTimer->TimerDpc); 00415 KeRemoveQueueApc(&ExTimer->TimerApc); 00416 Dereference = TRUE; 00417 00418 } else { 00419 Dereference = FALSE; 00420 } 00421 00422 ExReleaseSpinLockFromDpcLevel(&ExThread->ActiveTimerListLock); 00423 ExReleaseSpinLock(&ExTimer->Lock, OldIrql1); 00424 if (Dereference) { 00425 ObDereferenceObject((PVOID)ExTimer); 00426 } 00427 00428 ObDereferenceObject((PVOID)ExTimer); 00429 00430 // 00431 // Raise IRQL to DISPATCH_LEVEL and reacquire active timer list 00432 // spin lock. 00433 // 00434 00435 ExAcquireSpinLock(&ExThread->ActiveTimerListLock, &OldIrql1); 00436 NextEntry = ExThread->ActiveTimerListHead.Flink; 00437 } 00438 00439 ExReleaseSpinLock(&ExThread->ActiveTimerListLock, OldIrql1); 00440 return; 00441 }

NTSTATUS NtCancelTimer IN HANDLE  TimerHandle,
OUT PBOOLEAN CurrentState  OPTIONAL
 

Definition at line 679 of file timer.c.

References _ETHREAD::ActiveTimerListLock, ExpWakeTimerListLock, ExSystemExceptionFilter(), ExTimerObjectType, FALSE, KeCancelTimer(), KeReadStateTimer(), KeRemoveQueueApc(), KeRemoveQueueDpc(), KernelMode, KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PETIMER, ProbeForWriteBoolean, Status, TimerHandle, and TRUE.

Referenced by RtlpResetTimer().

00686 : 00687 00688 This function cancels a timer object. 00689 00690 Arguments: 00691 00692 TimerHandle - Supplies a handle to an timer object. 00693 00694 CurrentState - Supplies an optional pointer to a variable that will 00695 receive the current state of the timer object. 00696 00697 Return Value: 00698 00699 TBS 00700 00701 --*/ 00702 00703 { 00704 00705 BOOLEAN Dereference; 00706 PETHREAD ExThread; 00707 PETIMER ExTimer; 00708 KIRQL OldIrql1; 00709 KPROCESSOR_MODE PreviousMode; 00710 BOOLEAN State; 00711 NTSTATUS Status; 00712 00713 // 00714 // Establish an exception handler, probe the current state address if 00715 // specified, reference the timer object, and cancel the timer object. 00716 // If the probe fails, then return the exception code as the service 00717 // status. Otherwise return the status value returned by the reference 00718 // object by handle routine. 00719 // 00720 00721 try { 00722 00723 // 00724 // Get previous processor mode and probe current state address if 00725 // necessary. 00726 // 00727 00728 PreviousMode = KeGetPreviousMode(); 00729 if ((PreviousMode != KernelMode) && (ARGUMENT_PRESENT(CurrentState))) { 00730 ProbeForWriteBoolean(CurrentState); 00731 } 00732 00733 // 00734 // Reference timer object by handle. 00735 // 00736 00737 Status = ObReferenceObjectByHandle(TimerHandle, 00738 TIMER_MODIFY_STATE, 00739 ExTimerObjectType, 00740 PreviousMode, 00741 (PVOID *)&ExTimer, 00742 NULL); 00743 00744 // 00745 // If the reference was successful, then cancel the timer object, 00746 // dereference the timer object, and write the current state value 00747 // if specified. If the write attempt fails, then do not report an 00748 // error. When the caller attempts to access the current state value, 00749 // an access violation will occur. 00750 // 00751 00752 if (NT_SUCCESS(Status)) { 00753 ExAcquireSpinLock(&ExTimer->Lock, &OldIrql1); 00754 if (ExTimer->ApcAssociated) { 00755 ExThread = CONTAINING_RECORD(ExTimer->TimerApc.Thread, ETHREAD, Tcb); 00756 ExAcquireSpinLockAtDpcLevel(&ExThread->ActiveTimerListLock); 00757 RemoveEntryList(&ExTimer->ActiveTimerListEntry); 00758 ExTimer->ApcAssociated = FALSE; 00759 ExReleaseSpinLockFromDpcLevel(&ExThread->ActiveTimerListLock); 00760 KeCancelTimer(&ExTimer->KeTimer); 00761 KeRemoveQueueDpc(&ExTimer->TimerDpc); 00762 KeRemoveQueueApc(&ExTimer->TimerApc); 00763 Dereference = TRUE; 00764 00765 } else { 00766 KeCancelTimer(&ExTimer->KeTimer); 00767 Dereference = FALSE; 00768 } 00769 00770 if (ExTimer->WakeTimerListEntry.Flink) { 00771 ExAcquireSpinLockAtDpcLevel(&ExpWakeTimerListLock); 00772 00773 // 00774 // Check again as ExGetNextWakeTime might have removed it. 00775 // 00776 if (ExTimer->WakeTimerListEntry.Flink) { 00777 RemoveEntryList(&ExTimer->WakeTimerListEntry); 00778 ExTimer->WakeTimerListEntry.Flink = NULL; 00779 } 00780 ExReleaseSpinLockFromDpcLevel(&ExpWakeTimerListLock); 00781 } 00782 00783 ExReleaseSpinLock(&ExTimer->Lock, OldIrql1); 00784 if (Dereference) { 00785 ObDereferenceObject((PVOID)ExTimer); 00786 } 00787 00788 // 00789 // Read current state of timer, dereference timer object, and set 00790 // current state. 00791 // 00792 00793 State = KeReadStateTimer(&ExTimer->KeTimer); 00794 ObDereferenceObject(ExTimer); 00795 if (ARGUMENT_PRESENT(CurrentState)) { 00796 try { 00797 *CurrentState = State; 00798 00799 } except(ExSystemExceptionFilter()) { 00800 } 00801 } 00802 } 00803 00804 // 00805 // If an exception occurs during the probe of the current state address, 00806 // then always handle the exception and return the exception code as the 00807 // status value. 00808 // 00809 00810 } except(ExSystemExceptionFilter()) { 00811 return GetExceptionCode(); 00812 } 00813 00814 // 00815 // Return service status. 00816 // 00817 00818 return Status; 00819 }

NTSTATUS NtCreateTimer OUT PHANDLE  TimerHandle,
IN ACCESS_MASK  DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
IN TIMER_TYPE  TimerType
 

Definition at line 444 of file timer.c.

References ExpTimerDpcRoutine(), ExSystemExceptionFilter(), ExTimerObjectType, FALSE, Handle, KeInitializeDpc(), KeInitializeSpinLock(), KeInitializeTimerEx(), KernelMode, KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, ObCreateObject(), ObInsertObject(), ObjectAttributes, PETIMER, ProbeForWriteHandle, Status, and TimerHandle.

Referenced by RtlpInitializeTimerThreadPool(), and RtlpWaitThread().

00453 : 00454 00455 This function creates an timer object and opens a handle to the object with 00456 the specified desired access. 00457 00458 Arguments: 00459 00460 TimerHandle - Supplies a pointer to a variable that will receive the 00461 timer object handle. 00462 00463 DesiredAccess - Supplies the desired types of access for the timer object. 00464 00465 ObjectAttributes - Supplies a pointer to an object attributes structure. 00466 00467 TimerType - Supplies the type of the timer (autoclearing or notification). 00468 00469 Return Value: 00470 00471 TBS 00472 00473 --*/ 00474 00475 { 00476 00477 PETIMER ExTimer; 00478 HANDLE Handle; 00479 KPROCESSOR_MODE PreviousMode; 00480 NTSTATUS Status; 00481 00482 // 00483 // Establish an exception handler, probe the output handle address, and 00484 // attempt to create a timer object. If the probe fails, then return the 00485 // exception code as the service status. Otherwise return the status value 00486 // returned by the object insertion routine. 00487 // 00488 00489 try { 00490 00491 // 00492 // Get previous processor mode and probe output handle address if 00493 // necessary. 00494 // 00495 00496 PreviousMode = KeGetPreviousMode(); 00497 if (PreviousMode != KernelMode) { 00498 ProbeForWriteHandle(TimerHandle); 00499 } 00500 00501 // 00502 // Check argument validity. 00503 // 00504 00505 if ((TimerType != NotificationTimer) && 00506 (TimerType != SynchronizationTimer)) { 00507 return STATUS_INVALID_PARAMETER_4; 00508 } 00509 00510 // 00511 // Allocate timer object. 00512 // 00513 00514 Status = ObCreateObject(PreviousMode, 00515 ExTimerObjectType, 00516 ObjectAttributes, 00517 PreviousMode, 00518 NULL, 00519 sizeof(ETIMER), 00520 0, 00521 0, 00522 (PVOID *)&ExTimer); 00523 00524 // 00525 // If the timer object was successfully allocated, then initialize the 00526 // timer object and attempt to insert the time object in the current 00527 // process' handle table. 00528 // 00529 00530 if (NT_SUCCESS(Status)) { 00531 KeInitializeDpc(&ExTimer->TimerDpc, 00532 ExpTimerDpcRoutine, 00533 (PVOID)ExTimer); 00534 00535 KeInitializeTimerEx(&ExTimer->KeTimer, TimerType); 00536 KeInitializeSpinLock(&ExTimer->Lock); 00537 ExTimer->ApcAssociated = FALSE; 00538 ExTimer->WakeTimer = FALSE; 00539 ExTimer->WakeTimerListEntry.Flink = NULL; 00540 Status = ObInsertObject((PVOID)ExTimer, 00541 NULL, 00542 DesiredAccess, 00543 0, 00544 (PVOID *)NULL, 00545 &Handle); 00546 00547 // 00548 // If the timer object was successfully inserted in the current 00549 // process' handle table, then attempt to write the timer object 00550 // handle value. If the write attempt fails, then do not report 00551 // an error. When the caller attempts to access the handle value, 00552 // an access violation will occur. 00553 // 00554 00555 if (NT_SUCCESS(Status)) { 00556 try { 00557 *TimerHandle = Handle; 00558 } except(ExSystemExceptionFilter()) { 00559 } 00560 } 00561 } 00562 00563 // 00564 // If an exception occurs during the probe of the output handle address, 00565 // then always handle the exception and return the exception code as the 00566 // status value. 00567 // 00568 00569 } except(ExSystemExceptionFilter()) { 00570 return GetExceptionCode(); 00571 } 00572 00573 // 00574 // Return service status. 00575 // 00576 00577 return Status; 00578 }

NTSTATUS NtOpenTimer OUT PHANDLE  TimerHandle,
IN ACCESS_MASK  DesiredAccess,
IN POBJECT_ATTRIBUTES  ObjectAttributes
 

Definition at line 581 of file timer.c.

References ExSystemExceptionFilter(), ExTimerObjectType, Handle, KernelMode, KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, ObjectAttributes, ObOpenObjectByName(), ProbeForWriteHandle, Status, and TimerHandle.

00589 : 00590 00591 This function opens a handle to an timer object with the specified 00592 desired access. 00593 00594 Arguments: 00595 00596 TimerHandle - Supplies a pointer to a variable that will receive the 00597 timer object handle. 00598 00599 DesiredAccess - Supplies the desired types of access for the timer object. 00600 00601 ObjectAttributes - Supplies a pointer to an object attributes structure. 00602 00603 Return Value: 00604 00605 TBS 00606 00607 --*/ 00608 00609 { 00610 00611 HANDLE Handle; 00612 KPROCESSOR_MODE PreviousMode; 00613 NTSTATUS Status; 00614 00615 // 00616 // Establish an exception handler, probe the output handle address, and 00617 // attempt to open a timer object. If the probe fails, then return the 00618 // exception code as the service status. Otherwise return the status value 00619 // returned by the open object routine. 00620 // 00621 00622 try { 00623 00624 // 00625 // Get previous processor mode and probe output handle address if 00626 // necessary. 00627 // 00628 00629 PreviousMode = KeGetPreviousMode(); 00630 if (PreviousMode != KernelMode) { 00631 ProbeForWriteHandle(TimerHandle); 00632 } 00633 00634 // 00635 // Open handle to the timer object with the specified desired access. 00636 // 00637 00638 Status = ObOpenObjectByName(ObjectAttributes, 00639 ExTimerObjectType, 00640 PreviousMode, 00641 NULL, 00642 DesiredAccess, 00643 NULL, 00644 &Handle); 00645 00646 // 00647 // If the open was successful, then attempt to write the timer object 00648 // handle value. If the write attempt fails, then do not report an 00649 // error. When the caller attempts to access the handle value, an 00650 // access violation will occur. 00651 // 00652 00653 if (NT_SUCCESS(Status)) { 00654 try { 00655 *TimerHandle = Handle; 00656 00657 } except(ExSystemExceptionFilter()) { 00658 } 00659 } 00660 00661 // 00662 // If an exception occurs during the probe of the output handle address, 00663 // then always handle the exception and return the exception code as the 00664 // status value. 00665 // 00666 00667 } except(ExSystemExceptionFilter()) { 00668 return GetExceptionCode(); 00669 } 00670 00671 // 00672 // Return service status. 00673 // 00674 00675 return Status; 00676 }

NTSTATUS NtQueryTimer IN HANDLE  TimerHandle,
IN TIMER_INFORMATION_CLASS  TimerInformationClass,
OUT PVOID  TimerInformation,
IN ULONG  TimerInformationLength,
OUT PULONG ReturnLength  OPTIONAL
 

Definition at line 822 of file timer.c.

References _KTIMER::DueTime, ExSystemExceptionFilter(), ExTimerObjectType, KeReadStateTimer(), KernelMode, KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PETIMER, ProbeForWrite(), ProbeForWriteUlong, Status, and TimerHandle.

Referenced by RtlpGetTimeRemaining().

00832 : 00833 00834 This function queries the state of an timer object and returns the 00835 requested information in the specified record structure. 00836 00837 Arguments: 00838 00839 TimerHandle - Supplies a handle to an timer object. 00840 00841 TimerInformationClass - Supplies the class of information being requested. 00842 00843 TimerInformation - Supplies a pointer to a record that is to receive the 00844 requested information. 00845 00846 TimerInformationLength - Supplies the length of the record that is to 00847 receive the requested information. 00848 00849 ReturnLength - Supplies an optional pointer to a variable that is to 00850 receive the actual length of information that is returned. 00851 00852 Return Value: 00853 00854 TBS 00855 00856 --*/ 00857 00858 { 00859 00860 PETIMER ExTimer; 00861 PKTIMER KeTimer; 00862 KPROCESSOR_MODE PreviousMode; 00863 BOOLEAN State; 00864 NTSTATUS Status; 00865 LARGE_INTEGER TimeToGo; 00866 00867 // 00868 // Establish an exception handler, probe the output arguments, reference 00869 // the timer object, and return the specified information. If the probe 00870 // fails, then return the exception code as the service status. Otherwise 00871 // return the status value returned by the reference object by handle 00872 // routine. 00873 // 00874 00875 try { 00876 00877 // 00878 // Get previous processor mode and probe output arguments if necessary. 00879 // 00880 00881 PreviousMode = KeGetPreviousMode(); 00882 if (PreviousMode != KernelMode) { 00883 ProbeForWrite(TimerInformation, 00884 sizeof(TIMER_BASIC_INFORMATION), 00885 sizeof(ULONG)); 00886 00887 if (ARGUMENT_PRESENT(ReturnLength)) { 00888 ProbeForWriteUlong(ReturnLength); 00889 } 00890 } 00891 00892 // 00893 // Check argument validity. 00894 // 00895 00896 if (TimerInformationClass != TimerBasicInformation) { 00897 return STATUS_INVALID_INFO_CLASS; 00898 } 00899 00900 if (TimerInformationLength != sizeof(TIMER_BASIC_INFORMATION)) { 00901 return STATUS_INFO_LENGTH_MISMATCH; 00902 } 00903 00904 // 00905 // Reference timer object by handle. 00906 // 00907 00908 Status = ObReferenceObjectByHandle(TimerHandle, 00909 TIMER_QUERY_STATE, 00910 ExTimerObjectType, 00911 PreviousMode, 00912 (PVOID *)&ExTimer, 00913 NULL); 00914 00915 // 00916 // If the reference was successful, then read the current state, 00917 // compute the time remaining, dereference the timer object, fill in 00918 // the information structure, and return the length of the information 00919 // structure if specified. If the write of the time information or the 00920 // return length fails, then do not report an error. When the caller 00921 // accesses the information structure or the length, an violation will 00922 // occur. 00923 // 00924 00925 if (NT_SUCCESS(Status)) { 00926 KeTimer = &ExTimer->KeTimer; 00927 State = KeReadStateTimer(KeTimer); 00928 KiQueryInterruptTime(&TimeToGo); 00929 TimeToGo.QuadPart = KeTimer->DueTime.QuadPart - TimeToGo.QuadPart; 00930 ObDereferenceObject(ExTimer); 00931 try { 00932 ((PTIMER_BASIC_INFORMATION)TimerInformation)->TimerState = State; 00933 ((PTIMER_BASIC_INFORMATION)TimerInformation)->RemainingTime = TimeToGo; 00934 if (ARGUMENT_PRESENT(ReturnLength)) { 00935 *ReturnLength = sizeof(TIMER_BASIC_INFORMATION); 00936 } 00937 00938 } except(ExSystemExceptionFilter()) { 00939 } 00940 } 00941 00942 // 00943 // If an exception occurs during the probe of the current state address, 00944 // then always handle the exception and return the exception code as the 00945 // status value. 00946 // 00947 00948 } except(ExSystemExceptionFilter()) { 00949 return GetExceptionCode(); 00950 } 00951 00952 // 00953 // Return service status. 00954 // 00955 00956 return Status; 00957 }

NTSTATUS NtSetTimer IN HANDLE  TimerHandle,
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
 

Definition at line 960 of file timer.c.

References _ETHREAD::ActiveTimerListHead, _ETHREAD::ActiveTimerListLock, CurrentApcEnvironment, ExpTimerApcRoutine(), ExpWakeTimerList, ExpWakeTimerListLock, ExSystemExceptionFilter(), ExTimerObjectType, FALSE, KeCancelTimer(), KeInitializeApc(), KeReadStateTimer(), KeRemoveQueueApc(), KeRemoveQueueDpc(), KernelMode, KeSetTimerEx(), KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PETIMER, PKNORMAL_ROUTINE, PKRUNDOWN_ROUTINE, PoWakeTimerSupported, ProbeForRead, ProbeForWriteBoolean, PsGetCurrentThread, Status, _ETHREAD::Tcb, TimerApcRoutine(), TimerHandle, and TRUE.

Referenced by RtlpResetTimer().

00972 : 00973 00974 This function sets an timer object to a Not-Signaled state and sets the timer 00975 to expire at the specified time. 00976 00977 Arguments: 00978 00979 TimerHandle - Supplies a handle to an timer object. 00980 00981 DueTime - Supplies a pointer to absolute of relative time at which the 00982 timer is to expire. 00983 00984 TimerApcRoutine - Supplies an optional pointer to a function which is to 00985 be executed when the timer expires. If this parameter is not specified, 00986 then the TimerContext parameter is ignored. 00987 00988 TimerContext - Supplies an optional pointer to an arbitrary data structure 00989 that will be passed to the function specified by the TimerApcRoutine 00990 parameter. This parameter is ignored if the TimerApcRoutine parameter 00991 is not specified. 00992 00993 WakeTimer - Supplies a boolean value that specifies whether the timer 00994 wakes computer operation if sleeping 00995 00996 Period - Supplies an optional repetitive period for the timer. 00997 00998 PreviousState - Supplies an optional pointer to a variable that will 00999 receive the previous state of the timer object. 01000 01001 Return Value: 01002 01003 TBS 01004 01005 --*/ 01006 01007 { 01008 01009 BOOLEAN AssociatedApc; 01010 BOOLEAN Dereference; 01011 PETHREAD ExThread; 01012 PETIMER ExTimer; 01013 LARGE_INTEGER ExpirationTime; 01014 KIRQL OldIrql1; 01015 KPROCESSOR_MODE PreviousMode; 01016 BOOLEAN State; 01017 NTSTATUS Status; 01018 01019 // 01020 // Establish an exception handler, probe the due time and previous state 01021 // address if specified, reference the timer object, and set the timer 01022 // object. If the probe fails, then return the exception code as the 01023 // service status. Otherwise return the status value returned by the 01024 // reference object by handle routine. 01025 // 01026 01027 try { 01028 01029 // 01030 // Get previous processor mode and probe previous state address 01031 // if necessary. 01032 // 01033 01034 PreviousMode = KeGetPreviousMode(); 01035 if (PreviousMode != KernelMode) { 01036 if (ARGUMENT_PRESENT(PreviousState)) { 01037 ProbeForWriteBoolean(PreviousState); 01038 } 01039 01040 ProbeForRead(DueTime, sizeof(LARGE_INTEGER), sizeof(ULONG)); 01041 } 01042 01043 // 01044 // Check argument validity. 01045 // 01046 01047 if (Period < 0) { 01048 return STATUS_INVALID_PARAMETER_6; 01049 } 01050 01051 // 01052 // Capture the expiration time. 01053 // 01054 01055 ExpirationTime = *DueTime; 01056 01057 // 01058 // Reference timer object by handle. 01059 // 01060 01061 Status = ObReferenceObjectByHandle(TimerHandle, 01062 TIMER_MODIFY_STATE, 01063 ExTimerObjectType, 01064 PreviousMode, 01065 (PVOID *)&ExTimer, 01066 NULL); 01067 01068 // 01069 // If this WakeTimer flag is set, return the appropiate informational 01070 // success status code. 01071 // 01072 01073 if (NT_SUCCESS(Status) && WakeTimer && !PoWakeTimerSupported()) { 01074 Status = STATUS_TIMER_RESUME_IGNORED; 01075 } 01076 01077 // 01078 // If the reference was successful, then cancel the timer object, set 01079 // the timer object, dereference time object, and write the previous 01080 // state value if specified. If the write of the previous state value 01081 // fails, then do not report an error. When the caller attempts to 01082 // access the previous state value, an access violation will occur. 01083 // 01084 01085 if (NT_SUCCESS(Status)) { 01086 ExAcquireSpinLock(&ExTimer->Lock, &OldIrql1); 01087 01088 if (ExTimer->ApcAssociated) { 01089 ExThread = CONTAINING_RECORD(ExTimer->TimerApc.Thread, ETHREAD, Tcb); 01090 ExAcquireSpinLockAtDpcLevel(&ExThread->ActiveTimerListLock); 01091 RemoveEntryList(&ExTimer->ActiveTimerListEntry); 01092 ExTimer->ApcAssociated = FALSE; 01093 ExReleaseSpinLockFromDpcLevel(&ExThread->ActiveTimerListLock); 01094 KeCancelTimer(&ExTimer->KeTimer); 01095 KeRemoveQueueDpc(&ExTimer->TimerDpc); 01096 KeRemoveQueueApc(&ExTimer->TimerApc); 01097 Dereference = TRUE; 01098 01099 } else { 01100 KeCancelTimer(&ExTimer->KeTimer); 01101 Dereference = FALSE; 01102 } 01103 01104 // 01105 // Read the current state of the timer. 01106 // 01107 01108 State = KeReadStateTimer(&ExTimer->KeTimer); 01109 01110 // 01111 // If this is a wake timer ensure it's on the wake timer list 01112 // 01113 01114 ExTimer->WakeTimer = WakeTimer; 01115 ExAcquireSpinLockAtDpcLevel(&ExpWakeTimerListLock); 01116 if (WakeTimer) { 01117 if (!ExTimer->WakeTimerListEntry.Flink) { 01118 InsertTailList(&ExpWakeTimerList, &ExTimer->WakeTimerListEntry); 01119 } 01120 } else { 01121 if (ExTimer->WakeTimerListEntry.Flink) { 01122 RemoveEntryList(&ExTimer->WakeTimerListEntry); 01123 ExTimer->WakeTimerListEntry.Flink = NULL; 01124 } 01125 } 01126 ExReleaseSpinLockFromDpcLevel(&ExpWakeTimerListLock); 01127 01128 // 01129 // If an APC routine is specified, then initialize the APC, acquire the 01130 // thread's active time list lock, insert the timer in the thread's 01131 // active timer list, set the timer with an associated DPC, and set the 01132 // associated APC flag TRUE. Otherwise set the timer without an associated 01133 // DPC, and set the associated APC flag FALSE. 01134 // 01135 01136 ExTimer->Period = Period; 01137 if (ARGUMENT_PRESENT(TimerApcRoutine)) { 01138 ExThread = PsGetCurrentThread(); 01139 KeInitializeApc(&ExTimer->TimerApc, 01140 &ExThread->Tcb, 01141 CurrentApcEnvironment, 01142 ExpTimerApcRoutine, 01143 (PKRUNDOWN_ROUTINE)NULL, 01144 (PKNORMAL_ROUTINE)TimerApcRoutine, 01145 PreviousMode, 01146 TimerContext); 01147 01148 ExAcquireSpinLockAtDpcLevel(&ExThread->ActiveTimerListLock); 01149 InsertTailList(&ExThread->ActiveTimerListHead, 01150 &ExTimer->ActiveTimerListEntry); 01151 01152 ExTimer->ApcAssociated = TRUE; 01153 ExReleaseSpinLockFromDpcLevel(&ExThread->ActiveTimerListLock); 01154 KeSetTimerEx(&ExTimer->KeTimer, 01155 ExpirationTime, 01156 Period, 01157 &ExTimer->TimerDpc); 01158 01159 AssociatedApc = TRUE; 01160 01161 } else { 01162 KeSetTimerEx(&ExTimer->KeTimer, 01163 ExpirationTime, 01164 Period, 01165 NULL); 01166 01167 AssociatedApc = FALSE; 01168 } 01169 01170 ExReleaseSpinLock(&ExTimer->Lock, OldIrql1); 01171 01172 // 01173 // Dereference the object as appropriate. 01174 // 01175 01176 if (Dereference) { 01177 ObDereferenceObject((PVOID)ExTimer); 01178 } 01179 01180 if (AssociatedApc == FALSE) { 01181 ObDereferenceObject((PVOID)ExTimer); 01182 } 01183 01184 if (ARGUMENT_PRESENT(PreviousState)) { 01185 try { 01186 *PreviousState = State; 01187 01188 } except(ExSystemExceptionFilter()) { 01189 } 01190 } 01191 } 01192 01193 // 01194 // If an exception occurs during the probe of the current state address, 01195 // then always handle the exception and return the exception code as the 01196 // status value. 01197 // 01198 01199 } except(ExSystemExceptionFilter()) { 01200 return GetExceptionCode(); 01201 } 01202 01203 // 01204 // Return service status. 01205 // 01206 01207 return Status; 01208 }


Variable Documentation

GENERIC_MAPPING ExpTimerMapping
 

Initial value:

{ STANDARD_RIGHTS_READ | TIMER_QUERY_STATE, STANDARD_RIGHTS_WRITE | TIMER_MODIFY_STATE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, TIMER_ALL_ACCESS }

Definition at line 62 of file timer.c.

Referenced by ExpTimerInitialization().

LIST_ENTRY ExpWakeTimerList
 

Definition at line 49 of file timer.c.

Referenced by ExGetNextWakeTime(), ExpTimerInitialization(), and NtSetTimer().

KSPIN_LOCK ExpWakeTimerListLock
 

Definition at line 48 of file timer.c.

Referenced by ExGetNextWakeTime(), ExpDeleteTimer(), ExpTimerInitialization(), NtCancelTimer(), and NtSetTimer().

POBJECT_TYPE ExTimerObjectType
 

Definition at line 55 of file timer.c.

Referenced by ExpTimerInitialization(), NtCancelTimer(), NtCreateTimer(), NtOpenTimer(), NtQueryTimer(), and NtSetTimer().


Generated on Sat May 15 19:45:46 2004 for test by doxygen 1.3.7