ReactOS  0.4.14-dev-614-gbfd8a84
timeout.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <windef.h>
#include <winbase.h>
#include <wincon.h>
#include <winuser.h>
#include <conutils.h>
#include "resource.h"
Include dependency graph for timeout.c:

Go to the source code of this file.

Functions

VOID PrintError (DWORD dwError)
 
BOOL WINAPI CtrlCIntercept (DWORD dwCtrlType)
 
INT InputWait (BOOL bNoBreak, INT timerValue)
 
int wmain (int argc, WCHAR *argv[])
 

Function Documentation

◆ CtrlCIntercept()

BOOL WINAPI CtrlCIntercept ( DWORD  dwCtrlType)

Definition at line 34 of file timeout.c.

35 {
36  switch (dwCtrlType)
37  {
38  case CTRL_C_EVENT:
39  ConPuts(StdOut, L"\n");
42  return TRUE;
43  }
44  return FALSE;
45 }
#define TRUE
Definition: types.h:120
#define CTRL_C_EVENT
Definition: wincon.h:65
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1487
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
Definition: console.c:2111
smooth NULL
Definition: ftsmooth.c:416
#define EXIT_FAILURE
Definition: jerror.c:33
static const WCHAR L[]
Definition: oid.c:1250
INT ConPuts(IN PCON_STREAM Stream, IN LPWSTR szStr)
Definition: outstream.c:427
#define StdOut
Definition: stream.h:76

Referenced by InputWait().

◆ InputWait()

INT InputWait ( BOOL  bNoBreak,
INT  timerValue 
)

Definition at line 47 of file timeout.c.

48 {
50  HANDLE hInput;
51  BOOL bUseTimer = (timerValue != -1);
52  HANDLE hTimer = NULL;
53  DWORD dwStartTime;
54  LONG timeElapsed;
55  DWORD dwWaitState;
56  INPUT_RECORD InputRecords[5];
57  ULONG NumRecords, i;
58  BOOL DisplayMsg = TRUE;
59  UINT WaitMsgId = (bNoBreak ? IDS_NOBREAK_INPUT : IDS_USER_INPUT);
60  UINT WaitCountMsgId = (bNoBreak ? IDS_NOBREAK_INPUT_COUNT : IDS_USER_INPUT_COUNT);
61 
62  /* Retrieve the current input handle */
63  hInput = ConStreamGetOSHandle(StdIn);
64  if (hInput == INVALID_HANDLE_VALUE)
65  {
67  return EXIT_FAILURE;
68  }
69 
70  /* Start a new wait if we use the timer */
71  if (bNoBreak && bUseTimer)
72  {
73  hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
74  if (hTimer == NULL)
75  {
76  /* A problem happened, bail out */
78  return EXIT_FAILURE;
79  }
80  }
81  if (bUseTimer)
82  dwStartTime = GetTickCount();
83 
84  /* If /NOBREAK is used, monitor for Ctrl-C input */
85  if (bNoBreak)
87 
88  /* Initially flush the console input queue to remove any pending events */
89  if (!GetNumberOfConsoleInputEvents(hInput, &NumRecords) ||
90  !FlushConsoleInputBuffer(hInput))
91  {
92  /* A problem happened, bail out */
95  goto Quit;
96  }
97 
98  ConPuts(StdOut, L"\n");
99 
100  /* If the timer is not used, just show the message */
101  if (!bUseTimer)
102  {
103  ConPuts(StdOut, L"\r");
104  ConResPuts(StdOut, WaitMsgId);
105  }
106 
107  while (TRUE)
108  {
109  /* Decrease the timer if we use it */
110  if (bUseTimer)
111  {
112  /*
113  * Compute how much time the previous operations took.
114  * This allows us in particular to take account for any time
115  * elapsed if something slowed down, or if the console has been
116  * paused in the meantime.
117  */
118  timeElapsed = GetTickCount() - dwStartTime;
119  if (timeElapsed >= 1000)
120  {
121  /* Increase dwStartTime by steps of 1 second */
122  timeElapsed /= 1000;
123  dwStartTime += (1000 * timeElapsed);
124 
125  if (timeElapsed <= timerValue)
126  timerValue -= timeElapsed;
127  else
128  timerValue = 0;
129 
130  DisplayMsg = TRUE;
131  }
132 
133  if (DisplayMsg)
134  {
135  ConPuts(StdOut, L"\r");
136  ConResPrintf(StdOut, WaitCountMsgId, timerValue);
137  ConPuts(StdOut, L" \b");
138 
139  DisplayMsg = FALSE;
140  }
141 
142  /* Stop when the timer reaches zero */
143  if (timerValue <= 0)
144  break;
145  }
146 
147  /* If /NOBREAK is used, only allow Ctrl-C input which is handled by the console handler */
148  if (bNoBreak)
149  {
150  if (bUseTimer)
151  {
153 
154  /* We use the timer: use a passive wait of maximum 1 second */
155  timeElapsed = GetTickCount() - dwStartTime;
156  if (timeElapsed < 1000)
157  {
158  DueTime.QuadPart = Int32x32To64(1000 - timeElapsed, -10000);
159  SetWaitableTimer(hTimer, &DueTime, 0, NULL, NULL, FALSE);
160  dwWaitState = WaitForSingleObject(hTimer, INFINITE);
161 
162  /* Check whether the timer has been signaled */
163  if (dwWaitState != WAIT_OBJECT_0)
164  {
165  /* An error happened, bail out */
168  break;
169  }
170  }
171  }
172  else
173  {
174  /* No timer is used: wait indefinitely */
175  Sleep(INFINITE);
176  }
177 
178  continue;
179  }
180 
181  /* /NOBREAK is not used, check for user key presses */
182 
183  /*
184  * If the timer is used, use a passive wait of maximum 1 second
185  * while monitoring for incoming console input events, so that
186  * we are still able to display the timing count.
187  * Indeed, ReadConsoleInputW() indefinitely waits until an input
188  * event appears. ReadConsoleInputW() is however used to retrieve
189  * the input events where there are some, as well as for waiting
190  * indefinitely in case we do not use the timer.
191  */
192  if (bUseTimer)
193  {
194  /* Wait a maximum of 1 second for input events */
195  timeElapsed = GetTickCount() - dwStartTime;
196  if (timeElapsed < 1000)
197  dwWaitState = WaitForSingleObject(hInput, 1000 - timeElapsed);
198  else
199  dwWaitState = WAIT_TIMEOUT;
200 
201  /* Check whether the input event has been signaled, or a timeout happened */
202  if (dwWaitState == WAIT_TIMEOUT)
203  continue;
204  if (dwWaitState != WAIT_OBJECT_0)
205  {
206  /* An error happened, bail out */
209  break;
210  }
211 
212  /* Be sure there is something in the console input queue */
213  if (!PeekConsoleInputW(hInput, InputRecords, ARRAYSIZE(InputRecords), &NumRecords))
214  {
215  /* An error happened, bail out */
218  break;
219  }
220 
221  if (NumRecords == 0)
222  continue;
223  }
224 
225  /*
226  * Some events have been detected, pop them out from the input queue.
227  * In case we do not use the timer, wait indefinitely until an input
228  * event appears.
229  */
230  if (!ReadConsoleInputW(hInput, InputRecords, ARRAYSIZE(InputRecords), &NumRecords))
231  {
232  /* An error happened, bail out */
235  break;
236  }
237 
238  /* Check the input events for a key press */
239  for (i = 0; i < NumRecords; ++i)
240  {
241  /* Ignore any non-key event */
242  if (InputRecords[i].EventType != KEY_EVENT)
243  continue;
244 
245  /* Ignore any system key event */
246  if ((InputRecords[i].Event.KeyEvent.wVirtualKeyCode == VK_CONTROL) ||
247  // (InputRecords[i].Event.KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED )) ||
248  // (InputRecords[i].Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) ||
249  (InputRecords[i].Event.KeyEvent.wVirtualKeyCode == VK_MENU))
250  {
251  continue;
252  }
253 
254  /* This is a non-system key event, stop waiting */
255  goto Stop;
256  }
257  }
258 
259 Stop:
260  ConPuts(StdOut, L"\n");
261 
262 Quit:
263  if (bNoBreak)
265 
266  if (bNoBreak && bUseTimer)
267  CloseHandle(hTimer);
268 
269  return Status;
270 }
VOID PrintError(DWORD dwError)
Definition: timeout.c:22
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:406
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
_In_ LARGE_INTEGER DueTime
Definition: kefuncs.h:524
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:455
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define INVALID_HANDLE_VALUE
Definition: compat.h:399
BOOL WINAPI FlushConsoleInputBuffer(IN HANDLE hConsoleInput)
Definition: console.c:191
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define VK_MENU
Definition: winuser.h:2179
#define IDS_USER_INPUT
Definition: resource.h:10
#define IDS_NOBREAK_INPUT
Definition: resource.h:9
int32_t INT
Definition: typedefs.h:56
_In_ PVOID _Out_ BOOLEAN * Stop
Definition: ldrtypes.h:241
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
#define EXIT_SUCCESS
Definition: rdjpgcom.c:55
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
Definition: console.c:2111
#define KEY_EVENT
Definition: wincon.h:122
smooth NULL
Definition: ftsmooth.c:416
#define IDS_USER_INPUT_COUNT
Definition: resource.h:12
INT __cdecl ConResPrintf(IN PCON_STREAM Stream, IN UINT uID,...)
Definition: outstream.c:781
HANDLE ConStreamGetOSHandle(IN PCON_STREAM Stream)
Definition: stream.c:240
#define WAIT_OBJECT_0
Definition: winbase.h:387
BOOL WINAPI DECLSPEC_HOTPATCH PeekConsoleInputW(IN HANDLE hConsoleInput, OUT PINPUT_RECORD lpBuffer, IN DWORD nLength, OUT LPDWORD lpNumberOfEventsRead)
Definition: readwrite.c:1218
#define IDS_ERROR_INVALID_HANDLE_VALUE
Definition: resource.h:5
unsigned long DWORD
Definition: ntddk_ex.h:95
#define EXIT_FAILURE
Definition: jerror.c:33
#define StdErr
Definition: stream.h:77
#define IDS_NOBREAK_INPUT_COUNT
Definition: resource.h:11
#define WAIT_TIMEOUT
Definition: dderror.h:14
INT ConResPuts(IN PCON_STREAM Stream, IN UINT uID)
Definition: outstream.c:610
static const WCHAR L[]
Definition: oid.c:1250
BOOL WINAPI GetNumberOfConsoleInputEvents(HANDLE hConsoleInput, LPDWORD lpNumberOfEvents)
Definition: console.c:1637
#define IDS_ERROR_READ_INPUT
Definition: resource.h:6
BOOL WINAPI CtrlCIntercept(DWORD dwCtrlType)
Definition: timeout.c:34
Status
Definition: gdiplustypes.h:24
unsigned int UINT
Definition: ndis.h:50
INT ConPuts(IN PCON_STREAM Stream, IN LPWSTR szStr)
Definition: outstream.c:427
#define VK_CONTROL
Definition: winuser.h:2178
#define StdOut
Definition: stream.h:76
unsigned int ULONG
Definition: retypes.h:1
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ EVENT_TYPE EventType
Definition: exfuncs.h:165
#define CreateWaitableTimer
Definition: winbase.h:3595
#define INFINITE
Definition: serial.h:102
BOOL WINAPI SetWaitableTimer(IN HANDLE hTimer, IN const LARGE_INTEGER *pDueTime, IN LONG lPeriod, IN PTIMERAPCROUTINE pfnCompletionRoutine OPTIONAL, IN OPTIONAL LPVOID lpArgToCompletionRoutine, IN BOOL fResume)
Definition: synch.c:382
#define Int32x32To64(a, b)
#define StdIn
Definition: stream.h:75
BOOL WINAPI DECLSPEC_HOTPATCH ReadConsoleInputW(IN HANDLE hConsoleInput, OUT PINPUT_RECORD lpBuffer, IN DWORD nLength, OUT LPDWORD lpNumberOfEventsRead)
Definition: readwrite.c:1258
LONGLONG QuadPart
Definition: typedefs.h:112

Referenced by wmain().

◆ PrintError()

VOID PrintError ( DWORD  dwError)

Definition at line 22 of file timeout.c.

23 {
24  if (dwError == ERROR_SUCCESS)
25  return;
26 
28  NULL, dwError, LANG_USER_DEFAULT);
29  ConPuts(StdErr, L"\n");
30 }
#define ERROR_SUCCESS
Definition: deptool.c:10
smooth NULL
Definition: ftsmooth.c:416
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:404
INT ConMsgPuts(IN PCON_STREAM Stream, IN DWORD dwFlags, IN LPCVOID lpSource OPTIONAL, IN DWORD dwMessageId, IN DWORD dwLanguageId)
Definition: outstream.c:837
#define StdErr
Definition: stream.h:77
static const WCHAR L[]
Definition: oid.c:1250
INT ConPuts(IN PCON_STREAM Stream, IN LPWSTR szStr)
Definition: outstream.c:427
#define LANG_USER_DEFAULT
Definition: tnerror.cpp:50

Referenced by InputWait().

◆ wmain()

int wmain ( int  argc,
WCHAR argv[] 
)

Definition at line 272 of file timeout.c.

273 {
274  INT timerValue = -1;
275  PWCHAR pszNext;
276  BOOL bDisableInput = FALSE, fTimerFlags = 0;
277  int index = 0;
278 
279  /* Initialize the Console Standard Streams */
281 
282  if (argc == 1)
283  {
285  return EXIT_SUCCESS;
286  }
287 
288  /* Parse the command line for options */
289  for (index = 1; index < argc; index++)
290  {
291  if (argv[index][0] == L'-' || argv[index][0] == L'/')
292  {
293  switch (towupper(argv[index][1]))
294  {
295  case L'?': /* Help */
296  {
298  return EXIT_SUCCESS;
299  }
300 
301  case L'T': /* Timer */
302  {
303  /* Consecutive /T switches are invalid */
304  if (fTimerFlags & 2)
305  {
307  return EXIT_FAILURE;
308  }
309 
310  /* Remember that a /T switch has been encountered */
311  fTimerFlags |= 2;
312 
313  /* Go to the next (timer) value */
314  continue;
315  }
316  }
317 
318  /* This flag is used to ignore any keyboard keys but Ctrl-C */
319  if (_wcsicmp(&argv[index][1], L"NOBREAK") == 0)
320  {
321  bDisableInput = TRUE;
322 
323  /* Go to next value */
324  continue;
325  }
326  }
327 
328  /* The timer value can also be specified without the /T switch */
329 
330  /* Only one timer value is supported */
331  if (fTimerFlags & 1)
332  {
334  return EXIT_FAILURE;
335  }
336 
337  timerValue = wcstol(argv[index], &pszNext, 10);
338  if (*pszNext)
339  {
341  return EXIT_FAILURE;
342  }
343 
344  /* Remember that the timer value has been set */
345  fTimerFlags |= 1;
346  }
347 
348  /* A timer value is mandatory in order to continue */
349  if (!(fTimerFlags & 1))
350  {
352  return EXIT_FAILURE;
353  }
354 
355  /* Make sure the timer value is within range */
356  if ((timerValue < -1) || (timerValue > 99999))
357  {
359  return EXIT_FAILURE;
360  }
361 
362  return InputWait(bDisableInput, timerValue);
363 }
#define IDS_ERROR_NO_TIMER_VALUE
Definition: resource.h:7
static int argc
Definition: ServiceArgs.c:12
#define TRUE
Definition: types.h:120
#define IDS_ERROR_ONE_TIME
Definition: resource.h:8
#define IDS_USAGE
Definition: resource.h:3
_Check_return_ long __cdecl wcstol(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
uint16_t * PWCHAR
Definition: typedefs.h:54
#define argv
Definition: mplay32.c:18
int32_t INT
Definition: typedefs.h:56
#define EXIT_SUCCESS
Definition: rdjpgcom.c:55
#define ConInitStdStreams()
Definition: stream.h:122
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint index
Definition: glext.h:6031
INT __cdecl ConResPrintf(IN PCON_STREAM Stream, IN UINT uID,...)
Definition: outstream.c:781
INT InputWait(BOOL bNoBreak, INT timerValue)
Definition: timeout.c:47
#define EXIT_FAILURE
Definition: jerror.c:33
#define StdErr
Definition: stream.h:77
static const WCHAR L[]
Definition: oid.c:1250
#define IDS_ERROR_OUT_OF_RANGE
Definition: resource.h:4
#define StdOut
Definition: stream.h:76
#define towupper(c)
Definition: wctype.h:99
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)