[KERNEL32]
[reactos.git] / reactos / dll / win32 / kernel32 / client / timerqueue.c
1 /*
2 * PROJECT: ReactOS Win32 Base API
3 * LICENSE: See COPYING in the top level directory
4 * FILE: dll/win32/kernel32/client/timerqueue.c
5 * PURPOSE: Timer Queue Functions
6 * PROGRAMMERS: Thomas Weidenmueller <w3seek@reactos.com>
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <k32.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* GLOBALS ********************************************************************/
17
18 HANDLE BasepDefaultTimerQueue = NULL;
19
20 /* PRIVATE FUNCTIONS **********************************************************/
21
22 /* FIXME - make this thread safe */
23 BOOL
24 WINAPI
25 BasepCreateDefaultTimerQueue(VOID)
26 {
27 NTSTATUS Status;
28
29 /* Create the timer queue */
30 Status = RtlCreateTimerQueue(&BasepDefaultTimerQueue);
31 if (!NT_SUCCESS(Status))
32 {
33 BaseSetLastNTError(Status);
34 DPRINT1("Unable to create the default timer queue!\n");
35 return FALSE;
36 }
37
38 return TRUE;
39 }
40
41 /* PUBLIC FUNCTIONS ***********************************************************/
42
43
44 /*
45 * @implemented
46 */
47 BOOL
48 WINAPI
49 CancelTimerQueueTimer(IN HANDLE TimerQueue,
50 IN HANDLE Timer)
51 {
52 NTSTATUS Status;
53
54 if (!TimerQueue)
55 {
56 /* Use the default timer queue */
57 TimerQueue = BasepDefaultTimerQueue;
58 if (!TimerQueue)
59 {
60 /* A timer is being cancelled before one was created... fail */
61 SetLastError(ERROR_INVALID_HANDLE);
62 return FALSE;
63 }
64 }
65
66 /* Delete the timer */
67 Status = RtlDeleteTimer(TimerQueue, Timer, NULL);
68 if (!NT_SUCCESS(Status))
69 {
70 BaseSetLastNTError(Status);
71 return FALSE;
72 }
73
74 return TRUE;
75 }
76
77 /*
78 * @implemented
79 */
80 BOOL
81 WINAPI
82 ChangeTimerQueueTimer(IN HANDLE TimerQueue,
83 IN HANDLE Timer,
84 IN ULONG DueTime,
85 IN ULONG Period)
86 {
87 NTSTATUS Status;
88
89 if (!TimerQueue)
90 {
91 /* Use the default timer queue */
92 TimerQueue = BasepDefaultTimerQueue;
93 if (!TimerQueue)
94 {
95 /* A timer is being cancelled before one was created... fail */
96 SetLastError(ERROR_INVALID_PARAMETER);
97 return FALSE;
98 }
99 }
100
101 /* Delete the timer */
102 Status = RtlUpdateTimer(TimerQueue, Timer, DueTime, Period);
103 if (!NT_SUCCESS(Status))
104 {
105 BaseSetLastNTError(Status);
106 return FALSE;
107 }
108
109 return TRUE;
110 }
111
112 /*
113 * @implemented
114 */
115 HANDLE
116 WINAPI
117 CreateTimerQueue(VOID)
118 {
119 HANDLE Handle;
120 NTSTATUS Status;
121
122 /* Create the timer queue */
123 Status = RtlCreateTimerQueue(&Handle);
124 if(!NT_SUCCESS(Status))
125 {
126 BaseSetLastNTError(Status);
127 return NULL;
128 }
129
130 return Handle;
131 }
132
133 /*
134 * @implemented
135 */
136 BOOL
137 WINAPI
138 CreateTimerQueueTimer(OUT PHANDLE phNewTimer,
139 IN HANDLE TimerQueue,
140 IN WAITORTIMERCALLBACK Callback,
141 IN PVOID Parameter,
142 IN DWORD DueTime,
143 IN DWORD Period,
144 IN ULONG Flags)
145 {
146 NTSTATUS Status;
147
148 /* Parameter is not optional -- clear it now */
149 *phNewTimer = NULL;
150
151 /* Check if no queue was given */
152 if (!TimerQueue)
153 {
154 /* Create the queue if it didn't already exist */
155 if (!(BasepDefaultTimerQueue) && !(BasepCreateDefaultTimerQueue()))
156 {
157 return FALSE;
158 }
159
160 /* Use the default queue */
161 TimerQueue = BasepDefaultTimerQueue;
162 }
163
164 /* Create the timer. Note that no parameter checking is done here */
165 Status = RtlCreateTimer(TimerQueue,
166 phNewTimer,
167 Callback,
168 Parameter,
169 DueTime,
170 Period,
171 Flags);
172 if (!NT_SUCCESS(Status))
173 {
174 BaseSetLastNTError(Status);
175 return FALSE;
176 }
177
178 return TRUE;
179 }
180
181 /*
182 * @implemented
183 */
184 BOOL
185 WINAPI
186 DeleteTimerQueue(IN HANDLE TimerQueue)
187 {
188 /* We don't allow the user to delete the default timer queue */
189 if (!TimerQueue)
190 {
191 SetLastError(ERROR_INVALID_HANDLE);
192 return FALSE;
193 }
194
195 /* Delete the timer queue */
196 RtlDeleteTimerQueueEx(TimerQueue, 0);
197 return TRUE;
198 }
199
200 /*
201 * @implemented
202 */
203 BOOL
204 WINAPI
205 DeleteTimerQueueEx(IN HANDLE TimerQueue,
206 IN HANDLE CompletionEvent)
207 {
208 NTSTATUS Status;
209
210 /* We don't allow the user to delete the default timer queue */
211 if (!TimerQueue)
212 {
213 SetLastError(ERROR_INVALID_HANDLE);
214 return FALSE;
215 }
216
217 /* Delete the timer queue */
218 Status = RtlDeleteTimerQueueEx(TimerQueue, CompletionEvent);
219 if (((CompletionEvent != INVALID_HANDLE_VALUE) && (Status == STATUS_PENDING)) ||
220 !(NT_SUCCESS(Status)))
221 {
222 /* In case CompletionEvent == NULL, RtlDeleteTimerQueueEx() returns before
223 all callback routines returned. We set the last error code to STATUS_PENDING
224 and return FALSE. In case CompletionEvent == INVALID_HANDLE_VALUE we only
225 can get here if another error occured. In case CompletionEvent is something
226 else, we get here and fail, even though it isn't really an error (if Status == STATUS_PENDING).
227 We also handle all other failures the same way. */
228 BaseSetLastNTError(Status);
229 return FALSE;
230 }
231
232 return TRUE;
233 }
234
235 /*
236 * @implemented
237 */
238 BOOL
239 WINAPI
240 DeleteTimerQueueTimer(IN HANDLE TimerQueue,
241 IN HANDLE Timer,
242 IN HANDLE CompletionEvent)
243 {
244 NTSTATUS Status;
245
246 if (!TimerQueue)
247 {
248 /* Use the default timer queue */
249 TimerQueue = BasepDefaultTimerQueue;
250 if (!TimerQueue)
251 {
252 /* A timer is being cancelled before one was created... fail */
253 SetLastError(ERROR_INVALID_PARAMETER);
254 return FALSE;
255 }
256 }
257
258 /* Delete the timer */
259 Status = RtlDeleteTimer(TimerQueue, Timer, CompletionEvent);
260 if (((CompletionEvent != INVALID_HANDLE_VALUE) && (Status == STATUS_PENDING)) ||
261 !(NT_SUCCESS(Status)))
262 {
263 /* In case CompletionEvent == NULL, RtlDeleteTimerQueueEx() returns before
264 all callback routines returned. We set the last error code to STATUS_PENDING
265 and return FALSE. In case CompletionEvent == INVALID_HANDLE_VALUE we only
266 can get here if another error occured. In case CompletionEvent is something
267 else, we get here and fail, even though it isn't really an error (if Status == STATUS_PENDING).
268 We also handle all other failures the same way. */
269 BaseSetLastNTError(Status);
270 return FALSE;
271 }
272
273 return TRUE;
274 }
275
276 /*
277 * @implemented
278 */
279 HANDLE
280 WINAPI
281 SetTimerQueueTimer(IN HANDLE TimerQueue,
282 IN WAITORTIMERCALLBACK Callback,
283 IN PVOID Parameter,
284 IN DWORD DueTime,
285 IN DWORD Period,
286 IN BOOL PreferIo)
287 {
288 HANDLE Timer;
289 NTSTATUS Status;
290
291 /* Check if no queue was given */
292 if (!TimerQueue)
293 {
294 /* Create the queue if it didn't already exist */
295 if (!(BasepDefaultTimerQueue) && !(BasepCreateDefaultTimerQueue()))
296 {
297 return FALSE;
298 }
299
300 /* Use the default queue */
301 TimerQueue = BasepDefaultTimerQueue;
302 }
303
304 /* Create the timer */
305 Status = RtlCreateTimer(TimerQueue,
306 &Timer,
307 Callback,
308 Parameter,
309 DueTime,
310 Period,
311 PreferIo ? WT_EXECUTEINIOTHREAD : WT_EXECUTEDEFAULT);
312 if (!NT_SUCCESS(Status))
313 {
314 BaseSetLastNTError(Status);
315 return NULL;
316 }
317
318 return Timer;
319 }
320
321 /* EOF */