xref: /reactos/dll/win32/kernel32/client/timerqueue.c (revision c2c66aff)
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
BasepCreateDefaultTimerQueue(VOID)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
CancelTimerQueueTimer(IN HANDLE TimerQueue,IN HANDLE Timer)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
ChangeTimerQueueTimer(IN HANDLE TimerQueue,IN HANDLE Timer,IN ULONG DueTime,IN ULONG Period)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
CreateTimerQueue(VOID)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
CreateTimerQueueTimer(OUT PHANDLE phNewTimer,IN HANDLE TimerQueue,IN WAITORTIMERCALLBACK Callback,IN PVOID Parameter,IN DWORD DueTime,IN DWORD Period,IN ULONG Flags)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
DeleteTimerQueue(IN HANDLE TimerQueue)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
DeleteTimerQueueEx(IN HANDLE TimerQueue,IN HANDLE CompletionEvent)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
DeleteTimerQueueTimer(IN HANDLE TimerQueue,IN HANDLE Timer,IN HANDLE CompletionEvent)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
SetTimerQueueTimer(IN HANDLE TimerQueue,IN WAITORTIMERCALLBACK Callback,IN PVOID Parameter,IN DWORD DueTime,IN DWORD Period,IN BOOL PreferIo)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 */
322