ReactOS 0.4.15-dev-8021-g7ce96fd
mxtimerum.h
Go to the documentation of this file.
1/*++
2
3Copyright (c) Microsoft Corporation
4
5ModuleName:
6
7 MxTimerUm.h
8
9Abstract:
10
11 User mode implementation of timer defined in
12 MxTimer.h
13
14Author:
15
16
17Revision History:
18
19
20
21--*/
22
23#pragma once
24
25typedef struct _MdTimer {
26 //
27 // Callback function to be invoked upon timer expiration and the context to
28 // be passed in to the callback function
29 //
32
33 //
34 // The timer period
35 //
37
38 //
39 // Handle to the timer object
40 //
41 PTP_TIMER m_TimerHandle;
42
43 //
44 // Work object to be executed by threadpool upon timer expiration
45 //
47
48 //
49 // Flag to indicate that the timer callback has started running
50 //
52
53 //
54 // Flag to indicate that the timer was started
55 // since it was created or since it was last stopped.
56 //
58
60 VOID
61 )
62 {
67 m_Period = 0;
70 }
71
73 VOID
74 )
75 {
76 //
77 // Release the timer object
78 //
79 if (m_TimerHandle)
80 {
81 CloseThreadpoolTimer(m_TimerHandle);
83 }
84
85 //
86 // Release the work object
87 //
88 if (m_WorkObject)
89 {
90 CloseThreadpoolWork(m_WorkObject);
92 }
93 }
94
97 VOID
98 )
99 {
100 //
101 // Timer was not started since it was created or since
102 // it was last stopped, so it can't be in the system timer queue.
103 //
104 if (!m_TimerWasStarted) {
105 return FALSE;
106 }
107
108 //
109 // Periodic timers are always in the system timer queue.
110 //
111 if (m_Period != 0) {
112 return TRUE;
113 }
114
115 //
116 // Non-periodic timer:
117 //
118 // At this point, the timer callback function has either been canceled or
119 // has finished running. Examine the m_CallbackStartedRunning value to see
120 // which one of these happened.
121 //
123 {
124 //
125 // Timer cancellation was too late. Timer callback already started
126 // running and the timer was removed from the system timer queue.
127 //
128 return FALSE;
129 }
130 else
131 {
132 //
133 // Timer cancellation happened on time and prevented the timer callback
134 // from running.
135 //
136 return TRUE;
137 }
138 }
139
146 )
147 {
148 NTSTATUS ntStatus = STATUS_SUCCESS;
149
153
154 //
155 // Create the timer object
156 //
157 m_TimerHandle = CreateThreadpoolTimer(_MdTimer::s_MdTimerCallback,
158 this,
159 NULL);
160 if (NULL == m_TimerHandle)
161 {
162 ntStatus = WinErrorToNtStatus(GetLastError());
163 }
164
165 //
166 // Create the work object
167 //
168 if (NT_SUCCESS(ntStatus))
169 {
170 m_WorkObject = CreateThreadpoolWork(_MdTimer::s_MdWorkCallback,
171 this,
172 NULL);
173 if (NULL == m_WorkObject)
174 {
175 ntStatus = WinErrorToNtStatus(GetLastError());
176 }
177 }
178
179 return ntStatus;
180 }
181
182 BOOLEAN
186 )
187 {
188 BOOLEAN bRetVal;
189 FILETIME dueFileTime;
190
191 if (m_TimerWasStarted) {
192 //
193 // Cancel the previously pended timer callback,
194 // we want it to execute after a full period elapsed.
195 //
196 WaitForThreadpoolTimerCallbacks(m_TimerHandle, TRUE);
197 }
198
199 //
200 // Return TRUE if the timer is in the system timer queue.
201 //
202 bRetVal = IsInSystemQueue();
203
204 //
205 // This is a fresh start for the timer, so clear the flag that the
206 // timer callback function may have previously set.
207 //
209
210 //
211 // Set the timer started flag.
212 //
214
215 //
216 // Copy the due time into a FILETIME structure
217 //
218 dueFileTime.dwLowDateTime = DueTime.LowPart;
219 dueFileTime.dwHighDateTime = (DWORD) DueTime.HighPart;
220
221 //
222 // Start the timer
223 //
224 SetThreadpoolTimer(m_TimerHandle,
225 &dueFileTime,
226 (DWORD) m_Period,
228
229 return bRetVal;
230 }
231
233 BOOLEAN
235 VOID
236 )
237 {
238 BOOLEAN bRetVal;
239
240 bRetVal = IsInSystemQueue();
241
242 //
243 // Stop the timer
244 //
245 SetThreadpoolTimer(m_TimerHandle,
246 NULL, // pftDueTime
247 0, // msPeriod
248 0 // msWindowLength
249 );
250
251 //
252 // Cancel pending callbacks that have not yet started to execute and wait
253 // for outstanding callbacks to complete.
254 //
255 WaitForThreadpoolTimerCallbacks(m_TimerHandle,
256 TRUE // cancel pending callbacks
257 );
258
259 //
260 // Reset the timer started flag.
261 //
263
264 return bRetVal;
265 }
266
267 VOID
269 VOID
270 )
271 {
272 //
273 // Invoke the user's callback function
274 //
275 m_TimerCallback(NULL, /* Reserved1 */
277 NULL, /* Reserved2 */
278 NULL /* Reserved3 */
279 );
280
281 return;
282 }
283
284 static
289 __inout PTP_WORK Work
290 )
291 {
292 struct _MdTimer *pThis = NULL;
293
296
297 pThis = (struct _MdTimer*) Context;
298 pThis->TimerCallback();
299
300 return;
301 }
302
303 static
308 __inout PTP_TIMER Timer
309 )
310 {
311 struct _MdTimer *pThis = NULL;
312
315
316 pThis = (struct _MdTimer*) Context;
317
318 //
319 // First, indicate that the callback has started running
320 //
322
323 //
324 // Post a work object to execute the callback function supplied by the
325 // user of MxTimer.
326 //
327 // We do not execute the user-supplied callback here because we could
328 // run into a deadlock if the user is trying to cancel the timer by
329 // calling MxTimer::Stop. MxTimer::Stop actually blocks waiting for
330 // MdTimer::s_MdTimerCallback to finish executing, so that it can know
331 // where its attempt to cancel the timer was successful. If we were to
332 // execute the user's callback in MdTimer::s_MdTimerCallback, the user
333 // would have to be careful not to call MxTimer::Stop while holding a
334 // lock that the user's callback tries to acquire. In order to avoid
335 // imposing such a restriction on the user, we allow
336 // MdTimer::s_MdTimerCallback to return immediately after posting a
337 // work object to run the user's callback.
338 //
339 SubmitThreadpoolWork(pThis->m_WorkObject);
340
341 return;
342 }
343
344 BOOLEAN
348 )
349 {
351 }
353
354#include "MxTimer.h"
355
356//
357// Implementation of MxTimer functions
358//
360 VOID
361 )
362{
363}
364
366 VOID
367 )
368{
369}
370
377 )
378/*++
379Routine description:
380 Initializes the MxTimer object.
381
382Arguments:
383 TimerContext - Context information that will be passed in to the timer
384 callback function.
385
386 TimerCallback - The timer callback function.
387
388 *** IMPORTANT NOTE ***
389 MxTimer object must not be freed inside the timer callback function
390 because in the pre-Vista, user mode implementation of MxTimer, the
391 destructor blocks waiting for all callback functions to finish
392 executing. Hence freeing the MxTimer object inside the callback
393 function will result in a deadlock.
394
395 Period - The period of the timer in milliseconds.
396
397Return value:
398 An NTSTATUS value that indicates whether or not we succeeded in
399 initializing the MxTimer
400--*/
401{
402 NTSTATUS ntStatus;
403
405 TimerCallback,
406 Period);
407
408 return ntStatus;
409}
410
418 __in BOOLEAN UseHighResolutionTimer
419 )
420{
421
423 UNREFERENCED_PARAMETER(UseHighResolutionTimer);
424 UNREFERENCED_PARAMETER(TimerCallback);
427 ASSERTMSG("Not implemented for UMDF\n", FALSE);
429
430}
431
432VOID
436 )
437{
439
440 return;
441}
442
446 VOID
447 )
448{
449 BOOLEAN bRetVal;
450
451 bRetVal = m_Timer.Stop();
452
453 return bRetVal;
454}
455
461 )
462{
463 BOOLEAN bRetVal = TRUE;
464
466
467 return bRetVal;
468}
469
470VOID
472 VOID
473 )
474{
475 WaitForThreadpoolWorkCallbacks(m_Timer.m_WorkObject,
476 TRUE // cancel pending callbacks
477 );
478}
479
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
__inline MxTimer(VOID)
Definition: mxtimerkm.h:83
CHECK_RETURN_IF_USER_MODE __inline NTSTATUS InitializeEx(__in_opt PVOID TimerContext, __in MdExtCallbackType TimerCallback, __in LONG Period, __in ULONG TolerableDelay, __in BOOLEAN UseHighResolutionTimer)
Definition: mxtimerkm.h:141
__inline ~MxTimer(VOID)
Definition: mxtimerkm.h:93
_Must_inspect_result_ __inline BOOLEAN Stop(VOID)
Definition: mxtimerkm.h:273
__inline VOID Start(__in LARGE_INTEGER DueTime, __in ULONG TolerableDelay=0)
Definition: mxtimerkm.h:251
__inline VOID FlushQueuedDpcs(VOID)
Definition: mxtimerkm.h:291
CHECK_RETURN_IF_USER_MODE __inline NTSTATUS Initialize(__in_opt PVOID TimerContext, __in MdDeferredRoutine TimerCallback, __in LONG Period)
Definition: mxtimerkm.h:119
MdTimer m_Timer
Definition: mxtimer.h:33
__inline BOOLEAN StartWithReturn(__in LARGE_INTEGER DueTime, __in ULONG TolerableDelay=0)
Definition: mxtimerkm.h:209
#define __inout_opt
Definition: dbghelp.h:53
#define __in
Definition: dbghelp.h:35
#define __inout
Definition: dbghelp.h:50
#define __in_opt
Definition: dbghelp.h:38
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define CALLBACK
Definition: compat.h:35
NTSTATUS WinErrorToNtStatus(__in ULONG WinError)
Definition: errtostatus.cpp:60
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define _Must_inspect_result_
Definition: ms_sal.h:558
KDEFERRED_ROUTINE * MdDeferredRoutine
Definition: mxkm.h:35
EXT_CALLBACK * MdExtCallback
Definition: mxkm.h:36
struct _MdTimer MdTimer
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
#define DWORD
Definition: nt_native.h:44
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
long LONG
Definition: pedump.c:60
#define STATUS_SUCCESS
Definition: shellext.h:65
DWORD dwHighDateTime
Definition: mapidefs.h:66
DWORD dwLowDateTime
Definition: mapidefs.h:65
~_MdTimer(VOID)
Definition: mxtimerum.h:72
VOID TimerCallback(VOID)
Definition: mxtimerum.h:268
BOOL m_CallbackStartedRunning
Definition: mxtimerum.h:51
static VOID CALLBACK s_MdWorkCallback(__inout PTP_CALLBACK_INSTANCE Instance, __inout_opt PVOID Context, __inout PTP_WORK Work)
Definition: mxtimerum.h:286
BOOL m_TimerWasStarted
Definition: mxtimerum.h:57
BOOLEAN StartWithReturn(__in LARGE_INTEGER DueTime, __in ULONG TolerableDelay)
Definition: mxtimerum.h:345
PTP_TIMER m_TimerHandle
Definition: mxtimerum.h:41
static VOID CALLBACK s_MdTimerCallback(__inout PTP_CALLBACK_INSTANCE Instance, __inout_opt PVOID Context, __inout PTP_TIMER Timer)
Definition: mxtimerum.h:305
BOOLEAN Start(__in LARGE_INTEGER DueTime, __in ULONG TolerableDelay)
Definition: mxtimerum.h:183
LONG m_Period
Definition: mxtimerkm.h:43
PTP_WORK m_WorkObject
Definition: mxtimerum.h:46
_Must_inspect_result_ BOOLEAN Stop(VOID)
Definition: mxtimerum.h:234
MdDeferredRoutine m_TimerCallback
Definition: mxtimerkm.h:58
_MdTimer(VOID)
Definition: mxtimerum.h:59
_Must_inspect_result_ NTSTATUS Initialize(__in_opt PVOID TimerContext, __in MdDeferredRoutine TimerCallback, __in LONG Period)
Definition: mxtimerum.h:142
PVOID m_TimerContext
Definition: mxtimerkm.h:77
BOOLEAN IsInSystemQueue(VOID)
Definition: mxtimerum.h:96
uint32_t ULONG
Definition: typedefs.h:59
@ Start
Definition: partlist.h:33
_In_ WDFTIMER _In_ LONGLONG DueTime
Definition: wdftimer.h:190
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_WMI_INSTANCE_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_opt_ WDFWMIINSTANCE * Instance
Definition: wdfwmi.h:481
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
struct _TP_CALLBACK_INSTANCE * PTP_CALLBACK_INSTANCE
Definition: winnt_old.h:4453
struct _TP_WORK * PTP_WORK
Definition: winnt_old.h:4452
_In_ LARGE_INTEGER _In_ ULONG _In_ ULONG TolerableDelay
Definition: kefuncs.h:1314
_In_ LARGE_INTEGER _In_ ULONG Period
Definition: kefuncs.h:1313
_In_ PLARGE_INTEGER _In_opt_ PTIMER_APC_ROUTINE _In_opt_ PVOID TimerContext
Definition: zwfuncs.h:430