3 * Copyright (C) 2004 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS system libraries
23 * PURPOSE: Timer Queue functions
24 * FILE: lib/kernel32/misc/timerqueue.c
25 * PROGRAMER: Thomas Weidenmueller <w3seek@reactos.com>
28 /* INCLUDES ******************************************************************/
33 #include "../include/debug.h"
36 /* FUNCTIONS *****************************************************************/
38 HANDLE DefaultTimerQueue
= NULL
;
41 * Create the default timer queue for the current process. This function is only
42 * called if CreateTimerQueueTimer() or SetTimerQueueTimer() is called.
43 * However, ChangeTimerQueueTimer() fails with ERROR_INVALID_PARAMETER if the
44 * default timer queue has not been created, because it assumes there has to be
45 * a timer queue with a timer if it want's to be changed.
48 IntCreateDefaultTimerQueue(VOID
)
52 /* FIXME - make this thread safe */
54 /* create the timer queue */
55 Status
= RtlCreateTimerQueue(&DefaultTimerQueue
);
56 if(!NT_SUCCESS(Status
))
58 SetLastErrorByStatus(Status
);
59 DPRINT1("Unable to create the default timer queue!\n");
71 CancelTimerQueueTimer(HANDLE TimerQueue
,
74 /* Since this function is not documented in PSDK and apparently does nothing
75 but delete the timer, we just do the same as DeleteTimerQueueTimer(), without
76 passing a completion event. */
79 if(TimerQueue
== NULL
)
81 /* let's use the process' default timer queue. We assume the default timer
82 queue has been created with a previous call to CreateTimerQueueTimer() or
83 SetTimerQueueTimer(), otherwise this call wouldn't make much sense. */
84 if(!(TimerQueue
= DefaultTimerQueue
))
86 SetLastError(ERROR_INVALID_HANDLE
);
93 SetLastError(ERROR_INVALID_PARAMETER
);
97 /* delete the timer */
98 Status
= RtlDeleteTimer(TimerQueue
, Timer
, NULL
);
100 if(!NT_SUCCESS(Status
))
102 SetLastErrorByStatus(Status
);
114 ChangeTimerQueueTimer(HANDLE TimerQueue
,
121 if(TimerQueue
== NULL
)
123 /* let's use the process' default timer queue. We assume the default timer
124 queue has been created with a previous call to CreateTimerQueueTimer() or
125 SetTimerQueueTimer(), otherwise this call wouldn't make much sense. */
126 if(!(TimerQueue
= DefaultTimerQueue
))
128 SetLastError(ERROR_INVALID_HANDLE
);
135 SetLastError(ERROR_INVALID_PARAMETER
);
139 /* update the timer */
140 Status
= RtlUpdateTimer(TimerQueue
, Timer
, DueTime
, Period
);
141 if(!NT_SUCCESS(Status
))
143 SetLastErrorByStatus(Status
);
155 CreateTimerQueue(VOID
)
160 /* create the timer queue */
161 Status
= RtlCreateTimerQueue(&Handle
);
162 if(!NT_SUCCESS(Status
))
164 SetLastErrorByStatus(Status
);
176 CreateTimerQueueTimer(PHANDLE phNewTimer
,
178 WAITORTIMERCALLBACK Callback
,
186 /* windows seems not to test this parameter at all, so we'll try to clear it here
187 so we don't crash somewhere inside ntdll */
190 if(TimerQueue
== NULL
)
192 /* the default timer queue is requested, try to create it if it hasn't been already */
193 if(!(TimerQueue
= DefaultTimerQueue
))
195 if(!IntCreateDefaultTimerQueue())
197 /* IntCreateDefaultTimerQueue() set the last error code already, just fail */
200 TimerQueue
= DefaultTimerQueue
;
204 /* !!! Win doesn't even check if Callback == NULL, so we don't, too! That'll
205 raise a nice exception later... */
207 /* create the timer */
208 Status
= RtlCreateTimer(TimerQueue
, phNewTimer
, Callback
, Parameter
, DueTime
,
210 if(!NT_SUCCESS(Status
))
212 SetLastErrorByStatus(Status
);
224 DeleteTimerQueue(HANDLE TimerQueue
)
228 /* We don't allow the user to delete the default timer queue */
229 if(TimerQueue
== NULL
)
231 SetLastError(ERROR_INVALID_HANDLE
);
235 /* delete the timer queue */
236 Status
= RtlDeleteTimerQueue(TimerQueue
);
237 return NT_SUCCESS(Status
);
245 DeleteTimerQueueEx(HANDLE TimerQueue
,
246 HANDLE CompletionEvent
)
250 /* We don't allow the user to delete the default timer queue */
251 if(TimerQueue
== NULL
)
253 SetLastError(ERROR_INVALID_HANDLE
);
257 /* delete the queue */
258 Status
= RtlDeleteTimerQueueEx(TimerQueue
, CompletionEvent
);
260 if((CompletionEvent
!= INVALID_HANDLE_VALUE
&& Status
== STATUS_PENDING
) ||
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. */
270 SetLastErrorByStatus(Status
);
282 DeleteTimerQueueTimer(HANDLE TimerQueue
,
284 HANDLE CompletionEvent
)
288 if(TimerQueue
== NULL
)
290 /* let's use the process' default timer queue. We assume the default timer
291 queue has been created with a previous call to CreateTimerQueueTimer() or
292 SetTimerQueueTimer(), otherwise this call wouldn't make much sense. */
293 if(!(TimerQueue
= DefaultTimerQueue
))
295 SetLastError(ERROR_INVALID_HANDLE
);
302 SetLastError(ERROR_INVALID_PARAMETER
);
306 /* delete the timer */
307 Status
= RtlDeleteTimer(TimerQueue
, Timer
, CompletionEvent
);
309 if((CompletionEvent
!= INVALID_HANDLE_VALUE
&& Status
== STATUS_PENDING
) ||
312 /* In case CompletionEvent == NULL, RtlDeleteTimer() returns before
313 the callback routine returned. We set the last error code to STATUS_PENDING
314 and return FALSE. In case CompletionEvent == INVALID_HANDLE_VALUE we only
315 can get here if another error occured. In case CompletionEvent is something
316 else, we get here and fail, even though it isn't really an error (if Status == STATUS_PENDING).
317 We also handle all other failures the same way. */
319 SetLastErrorByStatus(Status
);
331 SetTimerQueueTimer(HANDLE TimerQueue
,
332 WAITORTIMERCALLBACK Callback
,
338 /* Since this function is not documented in PSDK and apparently does nothing
339 but create a timer, we just do the same as CreateTimerQueueTimer(). Unfortunately
340 I don't really know what PreferIo is supposed to be, it propably just affects the
341 Flags parameter of CreateTimerQueueTimer(). Looking at the PSDK documentation of
342 CreateTimerQueueTimer() there's only one flag (WT_EXECUTEINIOTHREAD) that causes
343 the callback function queued to an I/O worker thread. I guess it uses this flag
344 if PreferIo == TRUE, otherwise let's just use WT_EXECUTEDEFAULT. We should
345 test this though, this is only guess work and I'm too lazy to do further
351 if(TimerQueue
== NULL
)
353 /* the default timer queue is requested, try to create it if it hasn't been already */
354 if(!(TimerQueue
= DefaultTimerQueue
))
356 if(!IntCreateDefaultTimerQueue())
358 /* IntCreateDefaultTimerQueue() set the last error code already, just fail */
361 TimerQueue
= DefaultTimerQueue
;
365 /* create the timer */
366 Status
= RtlCreateTimer(TimerQueue
, &Timer
, Callback
, Parameter
, DueTime
,
367 Period
, (PreferIo
? WT_EXECUTEINIOTHREAD
: WT_EXECUTEDEFAULT
));
368 if(!NT_SUCCESS(Status
))
370 SetLastErrorByStatus(Status
);