00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
#include "ki.h"
00027
00028
#ifdef ALLOC_PRAGMA
00029
#pragma alloc_text(PAGELK, KeQueryTimerDueTime)
00030
#endif
00031
00032
00033
00034
00035
00036
00037 #define ASSERT_TIMER(E) { \
00038
ASSERT(((E)->Header.Type == TimerNotificationObject) || \
00039
((E)->Header.Type == TimerSynchronizationObject)); \
00040
}
00041
00042
VOID
00043 KeInitializeTimer (
00044 IN
PKTIMER Timer
00045 )
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 {
00064
00065
00066
00067
00068
00069
00070
KeInitializeTimerEx(Timer, NotificationTimer);
00071
return;
00072 }
00073
00074
VOID
00075 KeInitializeTimerEx (
00076 IN
PKTIMER Timer,
00077 IN TIMER_TYPE Type
00078 )
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 {
00100
00101
00102
00103
00104
00105 Timer->Header.Type =
TimerNotificationObject + Type;
00106 Timer->Header.Inserted =
FALSE;
00107 Timer->Header.Size =
sizeof(
KTIMER) /
sizeof(LONG);
00108 Timer->Header.SignalState =
FALSE;
00109
00110
#if DBG
00111
00112 Timer->TimerListEntry.Flink =
NULL;
00113 Timer->TimerListEntry.Blink =
NULL;
00114
00115
#endif
00116
00117 InitializeListHead(&Timer->Header.WaitListHead);
00118 Timer->DueTime.QuadPart = 0;
00119 Timer->Period = 0;
00120
return;
00121 }
00122
00123
VOID
00124 KeClearTimer (
00125 IN
PKTIMER Timer
00126 )
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 {
00145
00146
ASSERT_TIMER(Timer);
00147
00148
00149
00150
00151
00152 Timer->Header.SignalState = 0;
00153
return;
00154 }
00155
00156 BOOLEAN
00157 KeCancelTimer (
00158 IN
PKTIMER Timer
00159 )
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 {
00182
00183 BOOLEAN Inserted;
00184 KIRQL OldIrql;
00185
00186
ASSERT_TIMER(Timer);
00187
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
00188
00189
00190
00191
00192
00193
00194
00195
KiLockDispatcherDatabase(&OldIrql);
00196 Inserted = Timer->Header.Inserted;
00197
if (Inserted !=
FALSE) {
00198
KiRemoveTreeTimer(Timer);
00199 }
00200
00201
00202
00203
00204
00205
00206
KiUnlockDispatcherDatabase(OldIrql);
00207
return Inserted;
00208 }
00209
00210 BOOLEAN
00211 KeReadStateTimer (
00212 IN
PKTIMER Timer
00213 )
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 {
00232
00233
ASSERT_TIMER(Timer);
00234
00235
00236
00237
00238
00239
return (BOOLEAN)Timer->Header.SignalState;
00240 }
00241
00242 BOOLEAN
00243 KeSetTimer (
00244 IN
PKTIMER Timer,
00245 IN LARGE_INTEGER DueTime,
00246 IN
PKDPC Dpc OPTIONAL
00247 )
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 {
00276
00277
00278
00279
00280
00281
return KeSetTimerEx(Timer, DueTime, 0, Dpc);
00282 }
00283
00284 BOOLEAN
00285 KeSetTimerEx (
00286 IN
PKTIMER Timer,
00287 IN LARGE_INTEGER DueTime,
00288 IN LONG Period OPTIONAL,
00289 IN
PKDPC Dpc OPTIONAL
00290 )
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 {
00321
00322 BOOLEAN Inserted;
00323 LARGE_INTEGER Interval;
00324 KIRQL OldIrql;
00325 LARGE_INTEGER SystemTime;
00326
00327
ASSERT_TIMER(Timer);
00328
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
00329
00330
00331
00332
00333
00334
KiLockDispatcherDatabase(&OldIrql);
00335
00336
00337
00338
00339
00340
00341 Inserted = Timer->Header.Inserted;
00342
if (Inserted !=
FALSE) {
00343
KiRemoveTreeTimer(Timer);
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 Timer->Header.SignalState =
FALSE;
00358 Timer->Dpc = Dpc;
00359 Timer->Period = Period;
00360
if (
KiInsertTreeTimer((
PRKTIMER)Timer, DueTime) ==
FALSE) {
00361
if (IsListEmpty(&Timer->
Header.
WaitListHead) ==
FALSE) {
00362
KiWaitTest(Timer,
TIMER_EXPIRE_INCREMENT);
00363 }
00364
00365
00366
00367
00368
00369
if (Dpc !=
NULL) {
00370 KiQuerySystemTime(&SystemTime);
00371
KeInsertQueueDpc(Timer->
Dpc,
00372 ULongToPtr(SystemTime.LowPart),
00373 ULongToPtr(SystemTime.HighPart));
00374 }
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
if (Period != 0) {
00387 Interval.QuadPart = Int32x32To64(Timer->
Period, - 10 * 1000);
00388
while (!
KiInsertTreeTimer(Timer, Interval)) {
00389 ;
00390 }
00391 }
00392 }
00393
00394
00395
00396
00397
00398
00399
KiUnlockDispatcherDatabase(OldIrql);
00400
00401
00402
00403
00404
00405
00406
return Inserted;
00407 }
00408
00409 ULONGLONG
00410 KeQueryTimerDueTime (
00411 IN
PKTIMER Timer
00412 )
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 {
00435
00436 KIRQL OldIrql;
00437 LARGE_INTEGER InterruptTime;
00438 ULONGLONG DueTime;
00439
00440
ASSERT_TIMER(Timer);
00441
00442
00443
00444
00445
00446
KiLockDispatcherDatabase(&OldIrql);
00447
00448
00449
00450
00451
00452 DueTime = 0;
00453
if (Timer->Header.Inserted) {
00454 DueTime = Timer->DueTime.QuadPart;
00455 }
00456
00457
00458
00459
00460
00461
00462
KiUnlockDispatcherDatabase(OldIrql);
00463
return DueTime;
00464 }
00465
00466 PVOID
00467 KeCheckForTimer(
00468 IN PVOID BlockStart,
00469 IN ULONG BlockSize
00470 )
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 {
00491 ULONG
Index;
00492 PLIST_ENTRY ListHead;
00493 PLIST_ENTRY NextEntry;
00494 KIRQL OldIrql;
00495
PKTIMER Timer;
00496 PUCHAR Address;
00497 PUCHAR
Start;
00498 PUCHAR
End;
00499
00500
00501
00502
00503
00504
Start = (PUCHAR)BlockStart;
00505
End =
Start +
BlockSize;
00506
00507
00508
00509
00510
00511
KiLockDispatcherDatabase(&OldIrql);
00512
00513
00514
00515
00516
00517
00518
Index = 0;
00519
do {
00520 ListHead = &
KiTimerTableListHead[
Index];
00521 NextEntry = ListHead->Flink;
00522
while (NextEntry != ListHead) {
00523 Timer = CONTAINING_RECORD(NextEntry,
KTIMER, TimerListEntry);
00524 Address = (PUCHAR)Timer;
00525 NextEntry = NextEntry->Flink;
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
if ((Address > (
Start -
sizeof(
KTIMER))) &&
00537 (Address <
End)) {
00538
KeBugCheckEx(TIMER_OR_DPC_INVALID,
00539 0x0,
00540 (ULONG_PTR)Address,
00541 (ULONG_PTR)
Start,
00542 (ULONG_PTR)
End);
00543 }
00544
00545
if (Timer->
Dpc) {
00546
00547
00548
00549
00550
00551 Address = (PUCHAR)Timer->
Dpc;
00552
if ((Address > (
Start -
sizeof(
KDPC))) &&
00553 (Address <
End)) {
00554
KeBugCheckEx(TIMER_OR_DPC_INVALID,
00555 0x1,
00556 (ULONG_PTR)Address,
00557 (ULONG_PTR)
Start,
00558 (ULONG_PTR)
End);
00559 }
00560
00561
00562
00563
00564
00565 Address = (PUCHAR)Timer->
Dpc->
DeferredRoutine;
00566
if (Address >=
Start && Address <
End) {
00567
KeBugCheckEx(TIMER_OR_DPC_INVALID,
00568 0x2,
00569 (ULONG_PTR)Address,
00570 (ULONG_PTR)
Start,
00571 (ULONG_PTR)
End);
00572 }
00573 }
00574 }
00575
00576
Index += 1;
00577 }
while(
Index <
TIMER_TABLE_SIZE);
00578
00579
00580
00581
00582
00583
00584
KiUnlockDispatcherDatabase(OldIrql);
00585
return NULL;
00586 }