1 /*++ 2 3 Copyright (c) Microsoft Corporation 4 5 Module Name: 6 7 FxTimerApi.cpp 8 9 Abstract: 10 11 This implements the WDFTIMER API's 12 13 Author: 14 15 16 17 Environment: 18 19 Both kernel and user mode 20 21 Revision History: 22 23 24 --*/ 25 26 #include "coreprivshared.hpp" 27 28 #include "fxtimer.hpp" 29 30 extern "C" { 31 // #include "FxTimerApi.tmh" 32 } 33 34 // 35 // extern "C" the entire file 36 // 37 extern "C" { 38 39 _Must_inspect_result_ 40 __drv_maxIRQL(DISPATCH_LEVEL) 41 NTSTATUS 42 STDCALL 43 WDFEXPORT(WdfTimerCreate)( 44 __in 45 PWDF_DRIVER_GLOBALS DriverGlobals, 46 __in 47 PWDF_TIMER_CONFIG Config, 48 __in 49 PWDF_OBJECT_ATTRIBUTES Attributes, 50 __out 51 WDFTIMER * Timer 52 ) 53 54 /*++ 55 56 Routine Description: 57 58 Create a TIMER object that will call the supplied function 59 when it fires. It returns a handle to the WDFTIMER object. 60 61 Arguments: 62 63 Config - WDF_TIMER_CONFIG structure. 64 65 Attributes - WDF_OBJECT_ATTRIBUTES to set the parent object, to request 66 a context memory allocation and a DestroyCallback. 67 68 Timer - Pointer to location to return the resulting WDFTIMER handle. 69 70 Returns: 71 72 STATUS_SUCCESS - A WDFTIMER handle has been created. 73 74 Notes: 75 76 The WDFTIMER object is deleted either when the DEVICE or QUEUE it is 77 associated with is deleted, or WdfObjectDelete is called. 78 79 --*/ 80 81 { 82 DDI_ENTRY(); 83 84 PFX_DRIVER_GLOBALS pFxDriverGlobals; 85 FxObject* pParent; 86 NTSTATUS status; 87 88 pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals); 89 90 status = FxValidateObjectAttributesForParentHandle(pFxDriverGlobals, 91 Attributes, 92 FX_VALIDATE_OPTION_PARENT_REQUIRED); 93 if (!NT_SUCCESS(status)) { 94 return status; 95 } 96 97 FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals, 98 Attributes->ParentObject, 99 FX_TYPE_OBJECT, 100 (PVOID*)&pParent, 101 &pFxDriverGlobals); 102 103 FxPointerNotNull(pFxDriverGlobals, Config); 104 FxPointerNotNull(pFxDriverGlobals, Timer); 105 106 if (Config->Size != sizeof(WDF_TIMER_CONFIG) && 107 Config->Size != sizeof(WDF_TIMER_CONFIG_V1_7) && 108 Config->Size != sizeof(WDF_TIMER_CONFIG_V1_11)) { 109 status = STATUS_INFO_LENGTH_MISMATCH; 110 111 DoTraceLevelMessage( 112 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 113 "PWDF_TIMER_CONFIG Size %d, expected %d, %!STATUS!", 114 Config->Size, sizeof(WDF_TIMER_CONFIG), status); 115 116 return status; 117 } 118 119 if (Config->Period > MAXLONG) { 120 status = STATUS_INVALID_PARAMETER; 121 122 DoTraceLevelMessage( 123 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 124 "Period value %u for a periodic timer cannot be greater than " 125 "MAXLONG, %!STATUS!", Config->Period, status); 126 127 return status; 128 } 129 130 // 131 // For version 1.13 and higher, the tolerable delay could 132 // go upto MAXULONG 133 // 134 if (Config->Size > sizeof(WDF_TIMER_CONFIG_V1_7) && 135 (pFxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,13) == FALSE)) { 136 if (Config->TolerableDelay > MAXLONG) { 137 138 status = STATUS_INVALID_PARAMETER; 139 140 DoTraceLevelMessage( 141 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 142 "TolerableDelay value %u cannot be greater than MAXLONG, " 143 "%!STATUS!", Config->TolerableDelay, status); 144 145 return status; 146 } 147 } 148 149 if (Config->Size > sizeof(WDF_TIMER_CONFIG_V1_11)) { 150 151 #if (FX_CORE_MODE == FX_CORE_USER_MODE) 152 if (Config->UseHighResolutionTimer) { 153 154 status = STATUS_NOT_IMPLEMENTED; 155 DoTraceLevelMessage( 156 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 157 "UseHighResolutionTimer option is not supported for UMDF " 158 "%!STATUS!", status); 159 return status; 160 } 161 #endif 162 163 if ((Config->TolerableDelay > 0) && 164 (Config->UseHighResolutionTimer)) { 165 166 status = STATUS_INVALID_PARAMETER; 167 168 DoTraceLevelMessage( 169 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 170 "UseHighResolutionTimer option sepcified with non zero tolerable delay %u " 171 "%!STATUS!", Config->TolerableDelay, status); 172 173 return status; 174 } 175 } 176 177 status = FxValidateObjectAttributes(pFxDriverGlobals, 178 Attributes, 179 FX_VALIDATE_OPTION_EXECUTION_LEVEL_ALLOWED); 180 if (!NT_SUCCESS(status)) { 181 return status; 182 } 183 184 if (Config->Period > 0 && 185 Attributes->ExecutionLevel == WdfExecutionLevelPassive) { 186 status = STATUS_NOT_SUPPORTED; 187 188 DoTraceLevelMessage( 189 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 190 "Passive level periodic timer is not supported. " 191 "Use one shot timer and queue the next timer from the callback " 192 "or use a dedicated thread, %!STATUS!", 193 status); 194 195 return status; 196 } 197 198 return FxTimer::_Create(pFxDriverGlobals, Config, Attributes, pParent, Timer); 199 } 200 201 __drv_maxIRQL(DISPATCH_LEVEL) 202 BOOLEAN 203 STDCALL 204 WDFEXPORT(WdfTimerStart)( 205 __in 206 PWDF_DRIVER_GLOBALS DriverGlobals, 207 __in 208 WDFTIMER Timer, 209 __in 210 LONGLONG DueTime 211 ) 212 213 /*++ 214 215 Routine Description: 216 217 Enqueue the TIMER to run at the specified time. 218 219 Arguments: 220 221 WDFTIMER - Handle to WDFTIMER object created with WdfTimerCreate. 222 223 DueTime - Time to execute 224 225 Returns: 226 227 TRUE if the timer object was in the system's timer queue 228 229 --*/ 230 231 { 232 DDI_ENTRY(); 233 234 FxTimer* pFxTimer; 235 LARGE_INTEGER li; 236 237 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 238 Timer, 239 FX_TYPE_TIMER, 240 (PVOID*)&pFxTimer); 241 242 li.QuadPart = DueTime; 243 244 return pFxTimer->Start(li); 245 } 246 247 __drv_when(Wait == __true, __drv_maxIRQL(PASSIVE_LEVEL)) 248 __drv_when(Wait == __false, __drv_maxIRQL(DISPATCH_LEVEL)) 249 BOOLEAN 250 STDCALL 251 WDFEXPORT(WdfTimerStop)( 252 __in 253 PWDF_DRIVER_GLOBALS DriverGlobals, 254 __in 255 WDFTIMER Timer, 256 __in 257 BOOLEAN Wait 258 ) 259 260 /*++ 261 262 Routine Description: 263 264 Stop the TIMER 265 266 Arguments: 267 268 WDFTIMER - Handle to WDFTIMER object created with WdfTimerCreate. 269 270 Returns: 271 272 TRUE if the timer object was in the system's timer queue 273 274 --*/ 275 276 { 277 DDI_ENTRY(); 278 279 PFX_DRIVER_GLOBALS pFxDriverGlobals; 280 FxTimer* pFxTimer; 281 NTSTATUS status; 282 283 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 284 Timer, 285 FX_TYPE_TIMER, 286 (PVOID*)&pFxTimer, 287 &pFxDriverGlobals); 288 289 if (Wait) { 290 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 291 if (!NT_SUCCESS(status)) { 292 return FALSE; 293 } 294 } 295 296 return pFxTimer->Stop(Wait); 297 } 298 299 __drv_maxIRQL(DISPATCH_LEVEL) 300 WDFOBJECT 301 STDCALL 302 WDFEXPORT(WdfTimerGetParentObject)( 303 __in 304 PWDF_DRIVER_GLOBALS DriverGlobals, 305 __in 306 WDFTIMER Timer 307 ) 308 309 /*++ 310 311 Routine Description: 312 313 Return the Parent Object handle supplied to WdfTimerCreate 314 315 Arguments: 316 317 WDFTIMER - Handle to WDFTIMER object created with WdfTimerCreate. 318 319 Returns: 320 321 Handle to the framework object that is the specified timer object's 322 parent object 323 324 --*/ 325 326 { 327 DDI_ENTRY(); 328 329 FxTimer* pFxTimer; 330 331 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 332 Timer, 333 FX_TYPE_TIMER, 334 (PVOID*)&pFxTimer); 335 336 return pFxTimer->GetObject(); 337 } 338 339 } // extern "C" 340