ReactOS  0.4.15-dev-3456-g4a17d4b
mxtimerum.h
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 ModuleName:
6 
7  MxTimerUm.h
8 
9 Abstract:
10 
11  User mode implementation of timer defined in
12  MxTimer.h
13 
14 Author:
15 
16 
17 Revision History:
18 
19 
20 
21 --*/
22 
23 #pragma once
24 
25 typedef 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  //
36  LONG m_Period;
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 
95  BOOLEAN
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 
141  NTSTATUS
146  )
147  {
148  NTSTATUS ntStatus = STATUS_SUCCESS;
149 
152  m_Period = Period;
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
285  VOID CALLBACK
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
304  VOID CALLBACK
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  {
350  return Start(DueTime, TolerableDelay);
351  }
352 } MdTimer;
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 
372 NTSTATUS
377  )
378 /*++
379 Routine description:
380  Initializes the MxTimer object.
381 
382 Arguments:
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 
397 Return value:
398  An NTSTATUS value that indicates whether or not we succeeded in
399  initializing the MxTimer
400 --*/
401 {
402  NTSTATUS ntStatus;
403 
404  ntStatus = m_Timer.Initialize(TimerContext,
406  Period);
407 
408  return ntStatus;
409 }
410 
412 NTSTATUS
416  __in LONG Period,
418  __in BOOLEAN UseHighResolutionTimer
419  )
420 {
421 
423  UNREFERENCED_PARAMETER(UseHighResolutionTimer);
427  ASSERTMSG("Not implemented for UMDF\n", FALSE);
428  return STATUS_NOT_IMPLEMENTED;
429 
430 }
431 
432 VOID
436  )
437 {
439 
440  return;
441 }
442 
444 BOOLEAN
446  VOID
447  )
448 {
449  BOOLEAN bRetVal;
450 
451  bRetVal = m_Timer.Stop();
452 
453  return bRetVal;
454 }
455 
457 BOOLEAN
461  )
462 {
463  BOOLEAN bRetVal = TRUE;
464 
466 
467  return bRetVal;
468 }
469 
470 VOID
472  VOID
473  )
474 {
475  WaitForThreadpoolWorkCallbacks(m_Timer.m_WorkObject,
476  TRUE // cancel pending callbacks
477  );
478 }
479 
EXT_CALLBACK * MdExtCallback
Definition: mxkm.h:36
_In_ LARGE_INTEGER _In_ ULONG _In_ ULONG TolerableDelay
Definition: kefuncs.h:1324
PVOID m_TimerContext
Definition: mxtimerkm.h:77
BOOLEAN Start(__in LARGE_INTEGER DueTime, __in ULONG TolerableDelay)
Definition: mxtimerum.h:183
BOOL m_CallbackStartedRunning
Definition: mxtimerum.h:51
CHECK_RETURN_IF_USER_MODE __inline NTSTATUS Initialize(__in_opt PVOID TimerContext, __in MdDeferredRoutine TimerCallback, __in LONG Period)
Definition: mxtimerkm.h:119
__inline VOID FlushQueuedDpcs(VOID)
Definition: mxtimerkm.h:291
NTSTATUS WinErrorToNtStatus(__in ULONG WinError)
Definition: errtostatus.cpp:60
#define __in_opt
Definition: dbghelp.h:38
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
LONG NTSTATUS
Definition: precomp.h:26
#define CALLBACK
Definition: compat.h:35
_In_ LARGE_INTEGER _In_ ULONG Period
Definition: kefuncs.h:1324
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1040
__inline ~MxTimer(VOID)
Definition: mxtimerkm.h:93
#define __inout_opt
Definition: dbghelp.h:53
MdDeferredRoutine m_TimerCallback
Definition: mxtimerkm.h:58
KDEFERRED_ROUTINE * MdDeferredRoutine
Definition: mxkm.h:35
#define DWORD
Definition: nt_native.h:44
__inline MxTimer(VOID)
Definition: mxtimerkm.h:83
~_MdTimer(VOID)
Definition: mxtimerum.h:72
DWORD dwHighDateTime
Definition: mapidefs.h:66
return STATUS_NOT_IMPLEMENTED
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
unsigned char BOOLEAN
_Must_inspect_result_ BOOLEAN Stop(VOID)
Definition: mxtimerum.h:234
struct _TP_CALLBACK_INSTANCE * PTP_CALLBACK_INSTANCE
Definition: winnt_old.h:4356
PTP_WORK m_WorkObject
Definition: mxtimerum.h:46
__inline VOID Start(__in LARGE_INTEGER DueTime, __in ULONG TolerableDelay=0)
Definition: mxtimerkm.h:251
BOOLEAN IsInSystemQueue(VOID)
Definition: mxtimerum.h:96
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
__inline BOOLEAN StartWithReturn(__in LARGE_INTEGER DueTime, __in ULONG TolerableDelay=0)
Definition: mxtimerkm.h:209
unsigned long DWORD
Definition: ntddk_ex.h:95
#define __inout
Definition: dbghelp.h:50
static VOID CALLBACK s_MdTimerCallback(__inout PTP_CALLBACK_INSTANCE Instance, __inout_opt PVOID Context, __inout PTP_TIMER Timer)
Definition: mxtimerum.h:305
#define _Must_inspect_result_
Definition: ms_sal.h:558
BOOL m_TimerWasStarted
Definition: mxtimerum.h:57
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
LONG m_Period
Definition: mxtimerkm.h:43
struct _TP_WORK * PTP_WORK
Definition: winnt_old.h:4355
#define NULL
Definition: types.h:112
_In_ WDFTIMER _In_ LONGLONG DueTime
Definition: wdftimer.h:187
VOID TimerCallback(VOID)
Definition: mxtimerum.h:268
_Must_inspect_result_ NTSTATUS Initialize(__in_opt PVOID TimerContext, __in MdDeferredRoutine TimerCallback, __in LONG Period)
Definition: mxtimerum.h:142
MdTimer m_Timer
Definition: mxtimer.h:33
struct _MdTimer MdTimer
unsigned int ULONG
Definition: retypes.h:1
_In_ PLARGE_INTEGER _In_opt_ PTIMER_APC_ROUTINE _In_opt_ PVOID TimerContext
Definition: zwfuncs.h:428
static VOID CALLBACK s_MdWorkCallback(__inout PTP_CALLBACK_INSTANCE Instance, __inout_opt PVOID Context, __inout PTP_WORK Work)
Definition: mxtimerum.h:286
#define STATUS_SUCCESS
Definition: shellext.h:65
PTP_TIMER m_TimerHandle
Definition: mxtimerum.h:41
#define __in
Definition: dbghelp.h:35
BOOLEAN StartWithReturn(__in LARGE_INTEGER DueTime, __in ULONG TolerableDelay)
Definition: mxtimerum.h:345
IN PVOID Instance
Definition: pci.h:361
DWORD dwLowDateTime
Definition: mapidefs.h:65
_MdTimer(VOID)
Definition: mxtimerum.h:59
_Must_inspect_result_ __inline BOOLEAN Stop(VOID)
Definition: mxtimerkm.h:273