ReactOS  0.4.11-dev-946-g431643b
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.

Referenced by InputWait().

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:1517
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:1087
INT ConPuts(IN PCON_STREAM Stream, IN LPWSTR szStr)
Definition: outstream.c:427
#define StdOut
Definition: stream.h:76

◆ InputWait()

INT InputWait ( BOOL  bNoBreak,
INT  timerValue 
)

Definition at line 47 of file timeout.c.

Referenced by wmain().

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 */
94  Status = EXIT_FAILURE;
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  /*
159  * For whatever reason, x86 MSVC generates a ntdll!_allmul
160  * call when using Int32x32To64(), instead of an imul
161  * instruction. This leads the linker to error that _allmul
162  * is missing, since we do not link against ntdll.
163  * Everything is however OK with GCC...
164  * We therefore use the __emul() intrinsic which does
165  * the correct job.
166  */
167  DueTime.QuadPart = __emul(1000 - timeElapsed, -10000);
168  SetWaitableTimer(hTimer, &DueTime, 0, NULL, NULL, FALSE);
169  dwWaitState = WaitForSingleObject(hTimer, INFINITE);
170 
171  /* Check whether the timer has been signaled */
172  if (dwWaitState != WAIT_OBJECT_0)
173  {
174  /* An error happened, bail out */
176  Status = EXIT_FAILURE;
177  break;
178  }
179  }
180  }
181  else
182  {
183  /* No timer is used: wait indefinitely */
184  Sleep(INFINITE);
185  }
186 
187  continue;
188  }
189 
190  /* /NOBREAK is not used, check for user key presses */
191 
192  /*
193  * If the timer is used, use a passive wait of maximum 1 second
194  * while monitoring for incoming console input events, so that
195  * we are still able to display the timing count.
196  * Indeed, ReadConsoleInputW() indefinitely waits until an input
197  * event appears. ReadConsoleInputW() is however used to retrieve
198  * the input events where there are some, as well as for waiting
199  * indefinitely in case we do not use the timer.
200  */
201  if (bUseTimer)
202  {
203  /* Wait a maximum of 1 second for input events */
204  timeElapsed = GetTickCount() - dwStartTime;
205  if (timeElapsed < 1000)
206  dwWaitState = WaitForSingleObject(hInput, 1000 - timeElapsed);
207  else
208  dwWaitState = WAIT_TIMEOUT;
209 
210  /* Check whether the input event has been signaled, or a timeout happened */
211  if (dwWaitState == WAIT_TIMEOUT)
212  continue;
213  if (dwWaitState != WAIT_OBJECT_0)
214  {
215  /* An error happened, bail out */
217  Status = EXIT_FAILURE;
218  break;
219  }
220 
221  /* Be sure there is something in the console input queue */
222  if (!PeekConsoleInputW(hInput, InputRecords, ARRAYSIZE(InputRecords), &NumRecords))
223  {
224  /* An error happened, bail out */
226  Status = EXIT_FAILURE;
227  break;
228  }
229 
230  if (NumRecords == 0)
231  continue;
232  }
233 
234  /*
235  * Some events have been detected, pop them out from the input queue.
236  * In case we do not use the timer, wait indefinitely until an input
237  * event appears.
238  */
239  if (!ReadConsoleInputW(hInput, InputRecords, ARRAYSIZE(InputRecords), &NumRecords))
240  {
241  /* An error happened, bail out */
243  Status = EXIT_FAILURE;
244  break;
245  }
246 
247  /* Check the input events for a key press */
248  for (i = 0; i < NumRecords; ++i)
249  {
250  /* Ignore any non-key event */
251  if (InputRecords[i].EventType != KEY_EVENT)
252  continue;
253 
254  /* Ignore any system key event */
255  if ((InputRecords[i].Event.KeyEvent.wVirtualKeyCode == VK_CONTROL) ||
256  // (InputRecords[i].Event.KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED )) ||
257  // (InputRecords[i].Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) ||
258  (InputRecords[i].Event.KeyEvent.wVirtualKeyCode == VK_MENU))
259  {
260  continue;
261  }
262 
263  /* This is a non-system key event, stop waiting */
264  goto Stop;
265  }
266  }
267 
268 Stop:
269  ConPuts(StdOut, L"\n");
270 
271 Quit:
272  if (bNoBreak)
274 
275  if (bNoBreak && bUseTimer)
276  CloseHandle(hTimer);
277 
278  return Status;
279 }
VOID PrintError(DWORD dwError)
Definition: timeout.c:22
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:736
_In_ LARGE_INTEGER DueTime
Definition: kefuncs.h:524
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:445
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
BOOL WINAPI FlushConsoleInputBuffer(IN HANDLE hConsoleInput)
Definition: console.c:169
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define VK_MENU
Definition: winuser.h:2158
#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:239
WORD wVirtualKeyCode
Definition: wincon.h:227
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
#define EXIT_SUCCESS
Definition: rdjpgcom.c:55
GLenum GLclampf GLint i
Definition: glfuncs.h:14
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
unsigned int BOOL
Definition: ntddk_ex.h:94
#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 int UINT
Definition: ndis.h:50
KEY_EVENT_RECORD KeyEvent
Definition: wincon.h:263
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:1087
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
INT ConPuts(IN PCON_STREAM Stream, IN LPWSTR szStr)
Definition: outstream.c:427
#define VK_CONTROL
Definition: winuser.h:2157
#define StdOut
Definition: stream.h:76
PPC_QUAL long long __emul(const int a, const int b)
Definition: intrin_ppc.h:527
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:3575
#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
union _INPUT_RECORD::@3146 Event
#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

◆ PrintError()

VOID PrintError ( DWORD  dwError)

Definition at line 22 of file timeout.c.

Referenced by InputWait().

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:1087
INT ConPuts(IN PCON_STREAM Stream, IN LPWSTR szStr)
Definition: outstream.c:427
#define LANG_USER_DEFAULT
Definition: tnerror.cpp:50

◆ wmain()

int wmain ( int  argc,
WCHAR argv[] 
)

Definition at line 281 of file timeout.c.

282 {
283  INT timerValue = -1;
284  PWCHAR pszNext;
285  BOOL bDisableInput = FALSE, fTimerFlags = 0;
286  int index = 0;
287 
288  /* Initialize the Console Standard Streams */
290 
291  if (argc == 1)
292  {
294  return EXIT_SUCCESS;
295  }
296 
297  /* Parse the command line for options */
298  for (index = 1; index < argc; index++)
299  {
300  if (argv[index][0] == L'-' || argv[index][0] == L'/')
301  {
302  switch (towupper(argv[index][1]))
303  {
304  case L'?': /* Help */
305  {
307  return EXIT_SUCCESS;
308  }
309 
310  case L'T': /* Timer */
311  {
312  /* Consecutive /T switches are invalid */
313  if (fTimerFlags & 2)
314  {
316  return EXIT_FAILURE;
317  }
318 
319  /* Remember that a /T switch has been encountered */
320  fTimerFlags |= 2;
321 
322  /* Go to the next (timer) value */
323  continue;
324  }
325  }
326 
327  /* This flag is used to ignore any keyboard keys but Ctrl-C */
328  if (_wcsicmp(&argv[index][1], L"NOBREAK") == 0)
329  {
330  bDisableInput = TRUE;
331 
332  /* Go to next value */
333  continue;
334  }
335  }
336 
337  /* The timer value can also be specified without the /T switch */
338 
339  /* Only one timer value is supported */
340  if (fTimerFlags & 1)
341  {
343  return EXIT_FAILURE;
344  }
345 
346  timerValue = wcstol(argv[index], &pszNext, 10);
347  if (*pszNext)
348  {
350  return EXIT_FAILURE;
351  }
352 
353  /* Remember that the timer value has been set */
354  fTimerFlags |= 1;
355  }
356 
357  /* A timer value is mandatory in order to continue */
358  if (!(fTimerFlags & 1))
359  {
361  return EXIT_FAILURE;
362  }
363 
364  /* Make sure the timer value is within range */
365  if ((timerValue < -1) || (timerValue > 99999))
366  {
368  return EXIT_FAILURE;
369  }
370 
371  return InputWait(bDisableInput, timerValue);
372 }
#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
int32_t INT
Definition: typedefs.h:56
static char ** argv
Definition: ServiceArgs.c:11
#define EXIT_SUCCESS
Definition: rdjpgcom.c:55
#define ConInitStdStreams()
Definition: stream.h:122
GLuint index
Definition: glext.h:6031
INT __cdecl ConResPrintf(IN PCON_STREAM Stream, IN UINT uID,...)
Definition: outstream.c:781
unsigned int BOOL
Definition: ntddk_ex.h:94
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:1087
#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)