Reactos
at master 321 lines 7.9 kB view raw
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 18HANDLE BasepDefaultTimerQueue = NULL; 19 20/* PRIVATE FUNCTIONS **********************************************************/ 21 22/* FIXME - make this thread safe */ 23BOOL 24WINAPI 25BasepCreateDefaultTimerQueue(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 */ 47BOOL 48WINAPI 49CancelTimerQueueTimer(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 */ 80BOOL 81WINAPI 82ChangeTimerQueueTimer(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 */ 115HANDLE 116WINAPI 117CreateTimerQueue(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 */ 136BOOL 137WINAPI 138CreateTimerQueueTimer(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 */ 184BOOL 185WINAPI 186DeleteTimerQueue(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 */ 203BOOL 204WINAPI 205DeleteTimerQueueEx(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 */ 238BOOL 239WINAPI 240DeleteTimerQueueTimer(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 */ 279HANDLE 280WINAPI 281SetTimerQueueTimer(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 */