[KMTESTS]
[reactos.git] / rostests / kmtests / ntos_ex / ExTimer.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Executive Regressions KM-Test
5 * PROGRAMMER: Aleksey Bragin <aleksey@reactos.org>
6 */
7
8 #include <kmt_test.h>
9
10 #define NDEBUG
11 #include <debug.h>
12
13 static
14 VOID
15 NTAPI
16 TestTimerApcRoutine(IN PVOID TimerContext,
17 IN ULONG TimerLowValue,
18 IN LONG TimerHighValue)
19
20 {
21 ULONG *ApcCount = (ULONG *)TimerContext;
22 DPRINT("Timer Apc called!\n");
23 (*ApcCount)++;
24 }
25
26 START_TEST(ExTimer)
27 {
28 UNICODE_STRING TimerName;
29 OBJECT_ATTRIBUTES ObjectAttributes;
30 HANDLE TimerHandle;
31 HANDLE HandleOpened;
32 LARGE_INTEGER DueTime;
33 BOOLEAN PreviousState, CurrentState;
34 NTSTATUS Status;
35 ULONG ApcCount;
36
37 // Create the timer
38 RtlInitUnicodeString(&TimerName, L"\\TestTimer");
39 InitializeObjectAttributes(&ObjectAttributes, &TimerName, 0, NULL, NULL);
40 Status = ZwCreateTimer(&TimerHandle, TIMER_ALL_ACCESS,
41 &ObjectAttributes, NotificationTimer);
42 ok(Status == STATUS_SUCCESS, "ZwCreateTimer failed with Status=0x%08lX", Status);
43
44 // Open the timer
45 Status = ZwOpenTimer(&HandleOpened, TIMER_ALL_ACCESS, &ObjectAttributes);
46 ok(Status == STATUS_SUCCESS, "ZwOpenTimer failed with Status=0x%08lX", Status);
47
48 // Set the timer, to some rather high value so it doesn't expire
49 DPRINT("Set timer 1\n");
50 DueTime.LowPart = -10000;
51 DueTime.HighPart = -10;
52 PreviousState = TRUE;
53 Status = ZwSetTimer(HandleOpened, &DueTime, NULL, NULL, FALSE, 0L, &PreviousState);
54 ok(Status == STATUS_SUCCESS, "ZwSetTimer failed with Status=0x%08lX", Status);
55 ok(PreviousState == FALSE, "Incorrect PreviousState returned when setting the timer");
56
57 // Cancel the timer
58 CurrentState = TRUE;
59 Status = ZwCancelTimer(HandleOpened, &CurrentState);
60 ok(Status == STATUS_SUCCESS, "ZwCancelTimer failed with Status=0x%08lX", Status);
61 ok(CurrentState == FALSE, "Incorrect CurrentState returned when canceling the timer");
62
63 // Set the timer to some small value, because we'll wait for it to expire
64 DPRINT("Set timer 2\n");
65 DueTime.LowPart = -100;
66 DueTime.HighPart = -1;
67 PreviousState = TRUE;
68 Status = ZwSetTimer(HandleOpened, &DueTime, NULL, NULL, FALSE, 0L, &PreviousState);
69 ok(Status == STATUS_SUCCESS, "ZwSetTimer failed with Status=0x%08lX", Status);
70 ok(PreviousState == FALSE, "Incorrect PreviousState returned when setting the timer");
71
72 // Wait until it expires
73 DPRINT("Wait till timer expires\n");
74 Status = ZwWaitForSingleObject(HandleOpened, FALSE, NULL);
75 ok(Status == STATUS_SUCCESS, "ZwWaitForSingleObject failed with Status=0x%08lX", Status);
76
77 // And cancel it
78 DPRINT("Cancel it\n");
79 CurrentState = FALSE;
80 Status = ZwCancelTimer(HandleOpened, &CurrentState);
81 ok(Status == STATUS_SUCCESS, "ZwCancelTimer failed with Status=0x%08lX", Status);
82 ok(CurrentState == TRUE, "Incorrect CurrentState returned when setting the timer");
83
84 // Test it with APC: Set, Cancel, check if APC has been called
85 DPRINT("Set timer with Apc (3)\n");
86 ApcCount = 0;
87 DueTime.LowPart = -10000;
88 DueTime.HighPart = -10;
89 PreviousState = FALSE;
90 Status = ZwSetTimer(HandleOpened, &DueTime,
91 (PTIMER_APC_ROUTINE)TestTimerApcRoutine, &ApcCount, FALSE,
92 0L, &PreviousState);
93
94 ok(Status == STATUS_SUCCESS, "ZwSetTimer failed with Status=0x%08lX", Status);
95 ok(PreviousState == TRUE, "Incorrect PreviousState returned when setting the timer");
96
97 DPRINT("Cancel it\n");
98 CurrentState = TRUE;
99 Status = ZwCancelTimer(HandleOpened, &CurrentState);
100 ok(Status == STATUS_SUCCESS, "ZwCancelTimer failed with Status=0x%08lX", Status);
101 ok(CurrentState == FALSE, "Incorrect CurrentState returned when cancelling the timer");
102 ok(ApcCount == 0, "Incorrect count of TimerApcRoutine calls: %ld, should be 0\n", ApcCount);
103
104 // Test setting the timer two times in a row, APC routine must not be called
105 DPRINT("Set timer with Apc (4)\n");
106 ApcCount = 0;
107 DueTime.LowPart = -10000;
108 DueTime.HighPart = -10;
109 PreviousState = TRUE;
110 Status = ZwSetTimer(HandleOpened, &DueTime,
111 (PTIMER_APC_ROUTINE)TestTimerApcRoutine, &ApcCount, FALSE,
112 0L, &PreviousState);
113 ok(Status == STATUS_SUCCESS, "ZwSetTimer failed with Status=0x%08lX", Status);
114 ok(PreviousState == FALSE, "Incorrect PreviousState returned when setting the timer");
115
116 // Set small due time, since we have to wait for timer to finish
117 DPRINT("Set timer with Apc (5)\n");
118 DueTime.LowPart = -10;
119 DueTime.HighPart = -1;
120 PreviousState = TRUE;
121 Status = ZwSetTimer(HandleOpened, &DueTime,
122 (PTIMER_APC_ROUTINE)TestTimerApcRoutine, &ApcCount, FALSE,
123 0L, &PreviousState);
124 ok(Status == STATUS_SUCCESS, "ZwSetTimer failed with Status=0x%08lX", Status);
125 ok(PreviousState == FALSE, "Incorrect PreviousState returned when setting the timer");
126
127 // Now wait till it's finished, and then check APC call
128 DPRINT("Wait for it\n");
129 Status = ZwWaitForSingleObject(HandleOpened, FALSE, NULL);
130 ok(Status == STATUS_SUCCESS, "ZwWaitForSingleObject failed with Status=0x%08lX", Status);
131
132 CurrentState = FALSE;
133 Status = ZwCancelTimer(HandleOpened, &CurrentState);
134 ok(Status == STATUS_SUCCESS, "ZwCancelTimer failed with Status=0x%08lX", Status);
135 ok(CurrentState == TRUE, "Incorrect CurrentState returned when cancelling the timer");
136 ok(ApcCount == 1, "Incorrect count of TimerApcRoutine calls: %ld, should be 1\n", ApcCount);
137
138 // Cleanup...
139 Status = ZwClose(HandleOpened);
140 ok(Status == STATUS_SUCCESS, "ZwClose failed with Status=0x%08lX", Status);
141
142 Status = ZwClose(TimerHandle);
143 ok(Status == STATUS_SUCCESS, "ZwClose failed with Status=0x%08lX", Status);
144 }