Author: hbelusca
Date: Mon Sep 25 23:31:44 2017
New Revision: 75968
URL:
http://svn.reactos.org/svn/reactos?rev=75968&view=rev
Log:
[TIMEOUT]: Implement the TIMEOUT utility (found on Win2k3 and upwards). This is an
improved "pause" command, with elapsed time count display.
Based from a patch by Lee Schröder, with modifications by myself.
CORE-10044 #resolve
Added:
trunk/reactos/base/applications/cmdutils/timeout/
trunk/reactos/base/applications/cmdutils/timeout/CMakeLists.txt (with props)
trunk/reactos/base/applications/cmdutils/timeout/lang/
trunk/reactos/base/applications/cmdutils/timeout/lang/en-US.rc (with props)
trunk/reactos/base/applications/cmdutils/timeout/lang/fr-FR.rc (with props)
trunk/reactos/base/applications/cmdutils/timeout/resource.h (with props)
trunk/reactos/base/applications/cmdutils/timeout/timeout.c (with props)
trunk/reactos/base/applications/cmdutils/timeout/timeout.rc (with props)
Modified:
trunk/reactos/base/applications/cmdutils/CMakeLists.txt
Modified: trunk/reactos/base/applications/cmdutils/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils…
==============================================================================
--- trunk/reactos/base/applications/cmdutils/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/base/applications/cmdutils/CMakeLists.txt [iso-8859-1] Mon Sep 25
23:31:44 2017
@@ -18,6 +18,7 @@
add_subdirectory(schtasks)
add_subdirectory(sort)
add_subdirectory(taskkill)
+add_subdirectory(timeout)
add_subdirectory(tree)
add_subdirectory(whoami)
add_subdirectory(wmic)
Added: trunk/reactos/base/applications/cmdutils/timeout/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils…
==============================================================================
--- trunk/reactos/base/applications/cmdutils/timeout/CMakeLists.txt (added)
+++ trunk/reactos/base/applications/cmdutils/timeout/CMakeLists.txt [iso-8859-1] Mon Sep
25 23:31:44 2017
@@ -0,0 +1,8 @@
+
+include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/conutils)
+
+add_executable(timeout timeout.c timeout.rc)
+set_module_type(timeout win32cui UNICODE)
+target_link_libraries(timeout conutils ${PSEH_LIB})
+add_importlibs(timeout msvcrt kernel32)
+add_cd_file(TARGET timeout DESTINATION reactos/system32 FOR all)
Propchange: trunk/reactos/base/applications/cmdutils/timeout/CMakeLists.txt
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/base/applications/cmdutils/timeout/lang/en-US.rc
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils…
==============================================================================
--- trunk/reactos/base/applications/cmdutils/timeout/lang/en-US.rc (added)
+++ trunk/reactos/base/applications/cmdutils/timeout/lang/en-US.rc [iso-8859-1] Mon Sep 25
23:31:44 2017
@@ -0,0 +1,33 @@
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+STRINGTABLE
+BEGIN
+ IDS_USAGE "ReactOS Timeout Utility\n\
+\n\
+TIMEOUT [/?] [/T] delay [/NOBREAK]\n\
+\n\
+Description:\n\
+ This tool waits until a specified time period (in seconds) has elapsed,\n\
+ or until any key is pressed. A parameter to ignore the key press is also\n\
+ accepted.\n\
+\n\
+Parameters:\n\
+ /? Display this help screen.\n\
+\n\
+ /T delay Specify the number of seconds to wait (-1 to 99999).\n\
+ A value of -1 means the program will wait until a key is pressed.\n\
+ Note that the ""/T"" specification is optional, you can
just\n\
+ specify the delay value without it.\n\
+\n\
+ /NOBREAK Ignore all keyboard input except for Ctrl+C.\n\
+"
+ IDS_ERROR_OUT_OF_RANGE "ERROR: The timer value must be within range (-1 to
99999).\n"
+ IDS_ERROR_INVALID_HANDLE_VALUE "ERROR: Unable to get the standard handle for the
console (error %lu).\n"
+ IDS_ERROR_READ_INPUT "ERROR: Unable to read the console input (error
%lu).\n"
+ IDS_ERROR_NO_TIMER_VALUE "ERROR: The timer value must be specified (-1 to
99999).\n"
+ IDS_ERROR_ONE_TIME "ERROR: Only one timer value is needed.\n"
+ IDS_NOBREAK_INPUT "Press Ctrl+C to quit..."
+ IDS_USER_INPUT "Press any key to continue..."
+ IDS_NOBREAK_INPUT_COUNT "Waiting for %d second(s), press Ctrl+C to
quit..."
+ IDS_USER_INPUT_COUNT "Waiting for %d second(s), press any key to
continue..."
+END
Propchange: trunk/reactos/base/applications/cmdutils/timeout/lang/en-US.rc
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/base/applications/cmdutils/timeout/lang/fr-FR.rc
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils…
==============================================================================
--- trunk/reactos/base/applications/cmdutils/timeout/lang/fr-FR.rc (added)
+++ trunk/reactos/base/applications/cmdutils/timeout/lang/fr-FR.rc [iso-8859-1] Mon Sep 25
23:31:44 2017
@@ -0,0 +1,34 @@
+LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
+
+STRINGTABLE
+BEGIN
+ IDS_USAGE "ReactOS Timeout Utility\n\
+\n\
+TIMEOUT [/?] [/T] délai [/NOBREAK]\n\
+\n\
+Description :\n\
+ Cet outil permet d'attendre jusqu'à ce qu'un délai (en secondes)
s'écoule,\n\
+ ou bien jusqu'à ce qu'une touche de clavier soit pressée. Un paramètre\n\
+ permettant d'ignorer l'appui de touche de clavier est accepté.\n\
+\n\
+Liste de paramètres :\n\
+ /? Affiche cet écran d'aide.\n\
+\n\
+ /T délai Spécifie le délai d'attente en secondes (entre -1 et 99999).\n\
+ La valeur -1 signifie que le programme attend jusqu'Ã ce
qu'une\n\
+ touche soit pressée.\n\
+ Veuillez noter que la spécification ""/T"" est
optionnelle, vous\n\
+ pouvez spécifier la valeur de délai sans celle-ci.\n\
+\n\
+ /NOBREAK Ignore toute frappe de clavier, sauf pour Ctrl+C.\n\
+"
+ IDS_ERROR_OUT_OF_RANGE "ERREUR: Le délai d'attente doit être compris dans
la plage (entre -1 et 99999).\n"
+ IDS_ERROR_INVALID_HANDLE_VALUE "ERREUR: Impossible d'obtenir le handle
standard pour la console (erreur %lu).\n"
+ IDS_ERROR_READ_INPUT "ERREUR: Impossible de lire l'entrée de console
(erreur %lu).\n"
+ IDS_ERROR_NO_TIMER_VALUE "ERREUR: Le délai d'attente doit être spécifié
(entre -1 et 99999).\n"
+ IDS_ERROR_ONE_TIME "ERREUR: Une seule valeur de délai est nécessaire.\n"
+ IDS_NOBREAK_INPUT "Appuyez sur Ctrl+C pour quitter..."
+ IDS_USER_INPUT "Appuyez sur une touche pour continuer..."
+ IDS_NOBREAK_INPUT_COUNT "Attendre %d seconde(s), appuyez sur Ctrl+C pour
quitter..."
+ IDS_USER_INPUT_COUNT "Attendre %d seconde(s), appuyez sur une touche pour
continuer..."
+END
Propchange: trunk/reactos/base/applications/cmdutils/timeout/lang/fr-FR.rc
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/base/applications/cmdutils/timeout/resource.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils…
==============================================================================
--- trunk/reactos/base/applications/cmdutils/timeout/resource.h (added)
+++ trunk/reactos/base/applications/cmdutils/timeout/resource.h [iso-8859-1] Mon Sep 25
23:31:44 2017
@@ -0,0 +1,12 @@
+#pragma once
+
+#define IDS_USAGE 0
+#define IDS_ERROR_OUT_OF_RANGE 1
+#define IDS_ERROR_INVALID_HANDLE_VALUE 2
+#define IDS_ERROR_READ_INPUT 3
+#define IDS_ERROR_NO_TIMER_VALUE 4
+#define IDS_ERROR_ONE_TIME 5
+#define IDS_NOBREAK_INPUT 6
+#define IDS_USER_INPUT 7
+#define IDS_NOBREAK_INPUT_COUNT 8
+#define IDS_USER_INPUT_COUNT 9
Propchange: trunk/reactos/base/applications/cmdutils/timeout/resource.h
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/base/applications/cmdutils/timeout/timeout.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils…
==============================================================================
--- trunk/reactos/base/applications/cmdutils/timeout/timeout.c (added)
+++ trunk/reactos/base/applications/cmdutils/timeout/timeout.c [iso-8859-1] Mon Sep 25
23:31:44 2017
@@ -0,0 +1,332 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Timeout utility
+ * FILE: base/applications/cmdutils/timeout/timeout.c
+ * PURPOSE: An enhanced alternative to the Pause command.
+ * PROGRAMMERS: Lee Schroeder (spaceseel at gmail dot com)
+ * Hermes Belusca-Maito (hermes.belusca(a)sfr.fr)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <windef.h>
+#include <winbase.h>
+#include <wincon.h>
+#include <winuser.h>
+
+#include <conutils.h>
+
+#include "resource.h"
+
+VOID PrintError(DWORD dwError)
+{
+ if (dwError == ERROR_SUCCESS)
+ return;
+
+ ConMsgPuts(StdErr, FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, dwError, LANG_USER_DEFAULT);
+ ConPuts(StdErr, L"\n");
+}
+
+BOOL
+WINAPI
+CtrlCIntercept(DWORD dwCtrlType)
+{
+ switch (dwCtrlType)
+ {
+ case CTRL_C_EVENT:
+ ConPuts(StdOut, L"\n");
+ SetConsoleCtrlHandler(NULL, FALSE);
+ ExitProcess(EXIT_FAILURE);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+INT InputWait(BOOL bNoBreak, INT timerValue)
+{
+ INT Status = EXIT_SUCCESS;
+ HANDLE hInput;
+ BOOL bUseTimer = (timerValue != -1);
+ DWORD dwStartTime;
+ LONG timeElapsed;
+ DWORD dwWaitState;
+ INPUT_RECORD InputRecords[5];
+ ULONG NumRecords, i;
+ BOOL DisplayMsg = TRUE;
+ UINT WaitMsgId = (bNoBreak ? IDS_NOBREAK_INPUT : IDS_USER_INPUT);
+ UINT WaitCountMsgId = (bNoBreak ? IDS_NOBREAK_INPUT_COUNT : IDS_USER_INPUT_COUNT);
+
+ /* Retrieve the current input handle */
+ hInput = ConStreamGetOSHandle(StdIn);
+ if (hInput == INVALID_HANDLE_VALUE)
+ {
+ ConResPrintf(StdErr, IDS_ERROR_INVALID_HANDLE_VALUE, GetLastError());
+ return EXIT_FAILURE;
+ }
+
+ /* Start a new wait if we use the timer */
+ if (bUseTimer)
+ dwStartTime = GetTickCount();
+
+ /* If /NOBREAK is used, monitor for Ctrl-C input */
+ if (bNoBreak)
+ SetConsoleCtrlHandler(CtrlCIntercept, TRUE);
+
+ /* Initially flush the console input queue to remove any pending events */
+ if (!GetNumberOfConsoleInputEvents(hInput, &NumRecords) ||
+ !FlushConsoleInputBuffer(hInput))
+ {
+ /* A problem happened, bail out */
+ PrintError(GetLastError());
+ Status = EXIT_FAILURE;
+ goto Quit;
+ }
+
+ ConPuts(StdOut, L"\n");
+
+ /* If the timer is not used, just show the message */
+ if (!bUseTimer)
+ {
+ ConPuts(StdOut, L"\r");
+ ConResPuts(StdOut, WaitMsgId);
+ }
+
+ while (TRUE)
+ {
+ /* Decrease the timer if we use it */
+ if (bUseTimer)
+ {
+ /*
+ * Compute how much time the previous operations took.
+ * This allows us in particular to take account for any time
+ * elapsed if something slowed down, or if the console has been
+ * paused in the meantime.
+ */
+ timeElapsed = GetTickCount() - dwStartTime;
+ if (timeElapsed >= 1000)
+ {
+ /* Increase dwStartTime by steps of 1 second */
+ timeElapsed /= 1000;
+ dwStartTime += (1000 * timeElapsed);
+
+ if (timeElapsed <= timerValue)
+ timerValue -= timeElapsed;
+ else
+ timerValue = 0;
+
+ DisplayMsg = TRUE;
+ }
+
+ if (DisplayMsg)
+ {
+ ConPuts(StdOut, L"\r");
+ ConResPrintf(StdOut, WaitCountMsgId, timerValue);
+ ConPuts(StdOut, L" \b");
+
+ DisplayMsg = FALSE;
+ }
+
+ /* Stop when the timer reaches zero */
+ if (timerValue <= 0)
+ break;
+ }
+
+ /* If /NOBREAK is used, only allow Ctrl-C input which is handled by the console
handler */
+ if (bNoBreak)
+ {
+ if (bUseTimer)
+ {
+ /* We use the timer: wait a little bit before updating it */
+ Sleep(100);
+ }
+ else
+ {
+ /* No timer is used: wait indefinitely */
+ Sleep(INFINITE);
+ }
+
+ continue;
+ }
+
+ /* /NOBREAK is not used, check for user key presses */
+
+ /*
+ * If the timer is used, use a passive wait of maximum 1 second
+ * while monitoring for incoming console input events, so that
+ * we are still able to display the timing count.
+ * Indeed, ReadConsoleInputW() indefinitely waits until an input
+ * event appears. ReadConsoleInputW() is however used to retrieve
+ * the input events where there are some, as well as for waiting
+ * indefinitely in case we do not use the timer.
+ */
+ if (bUseTimer)
+ {
+ /* Wait a maximum of 1 second for input events */
+ timeElapsed = GetTickCount() - dwStartTime;
+ if (timeElapsed < 1000)
+ dwWaitState = WaitForSingleObject(hInput, 1000 - timeElapsed);
+ else
+ dwWaitState = WAIT_TIMEOUT;
+
+ /* Check whether the input handle has been signaled, or a timeout happened
*/
+ if (dwWaitState == WAIT_TIMEOUT)
+ continue;
+ if (dwWaitState != WAIT_OBJECT_0)
+ {
+ /* An error happened, bail out */
+ PrintError(GetLastError());
+ Status = EXIT_FAILURE;
+ break;
+ }
+
+ /* Be sure there is someting in the console input queue */
+ if (!PeekConsoleInputW(hInput, InputRecords, ARRAYSIZE(InputRecords),
&NumRecords))
+ {
+ /* An error happened, bail out */
+ ConResPrintf(StdErr, IDS_ERROR_READ_INPUT, GetLastError());
+ Status = EXIT_FAILURE;
+ break;
+ }
+
+ if (NumRecords == 0)
+ continue;
+ }
+
+ /*
+ * Some events have been detected, pop them out from the input queue.
+ * In case we do not use the timer, wait indefinitely until an input
+ * event appears.
+ */
+ if (!ReadConsoleInputW(hInput, InputRecords, ARRAYSIZE(InputRecords),
&NumRecords))
+ {
+ /* An error happened, bail out */
+ ConResPrintf(StdErr, IDS_ERROR_READ_INPUT, GetLastError());
+ Status = EXIT_FAILURE;
+ break;
+ }
+
+ /* Check the input events for a key press */
+ for (i = 0; i < NumRecords; ++i)
+ {
+ /* Ignore any non-key event */
+ if (InputRecords[i].EventType != KEY_EVENT)
+ continue;
+
+ /* Ignore any system key event */
+ if ((InputRecords[i].Event.KeyEvent.wVirtualKeyCode == VK_CONTROL) ||
+ // (InputRecords[i].Event.KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED
| RIGHT_ALT_PRESSED )) ||
+ // (InputRecords[i].Event.KeyEvent.dwControlKeyState &
(LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) ||
+ (InputRecords[i].Event.KeyEvent.wVirtualKeyCode == VK_MENU))
+ {
+ continue;
+ }
+
+ /* This is a non-system key event, stop waiting */
+ goto Stop;
+ }
+ }
+
+Stop:
+ ConPuts(StdOut, L"\n");
+
+Quit:
+ if (bNoBreak)
+ SetConsoleCtrlHandler(NULL, FALSE);
+
+ return Status;
+}
+
+int wmain(int argc, WCHAR* argv[])
+{
+ INT timerValue = -1;
+ PWCHAR pszNext;
+ BOOL bDisableInput = FALSE, fTimerFlags = 0;
+ int index = 0;
+
+ /* Initialize the Console Standard Streams */
+ ConInitStdStreams();
+
+ if (argc == 1)
+ {
+ ConResPrintf(StdOut, IDS_USAGE);
+ return EXIT_SUCCESS;
+ }
+
+ /* Parse the command line for options */
+ for (index = 1; index < argc; index++)
+ {
+ if (argv[index][0] == L'-' || argv[index][0] == L'/')
+ {
+ switch (towupper(argv[index][1]))
+ {
+ case L'?': /* Help */
+ {
+ ConResPrintf(StdOut, IDS_USAGE);
+ return EXIT_SUCCESS;
+ }
+
+ case L'T': /* Timer */
+ {
+ /* Consecutive /T switches are invalid */
+ if (fTimerFlags & 2)
+ {
+ ConResPrintf(StdErr, IDS_ERROR_ONE_TIME);
+ return EXIT_FAILURE;
+ }
+
+ /* Remember that a /T switch has been encountered */
+ fTimerFlags |= 2;
+
+ /* Go to the next (timer) value */
+ continue;
+ }
+ }
+
+ /* This flag is used to ignore any keyboard keys but Ctrl-C */
+ if (_wcsicmp(&argv[index][1], L"NOBREAK") == 0)
+ {
+ bDisableInput = TRUE;
+
+ /* Go to next value */
+ continue;
+ }
+ }
+
+ /* The timer value can also be specified without the /T switch */
+
+ /* Only one timer value is supported */
+ if (fTimerFlags & 1)
+ {
+ ConResPrintf(StdErr, IDS_ERROR_ONE_TIME);
+ return EXIT_FAILURE;
+ }
+
+ timerValue = wcstol(argv[index], &pszNext, 10);
+ if (*pszNext)
+ {
+ ConResPrintf(StdErr, IDS_ERROR_OUT_OF_RANGE);
+ return EXIT_FAILURE;
+ }
+
+ /* Remember that the timer value has been set */
+ fTimerFlags |= 1;
+ }
+
+ /* A timer value is mandatory in order to continue */
+ if (!(fTimerFlags & 1))
+ {
+ ConResPrintf(StdErr, IDS_ERROR_NO_TIMER_VALUE);
+ return EXIT_FAILURE;
+ }
+
+ /* Make sure the timer value is within range */
+ if ((timerValue < -1) || (timerValue > 99999))
+ {
+ ConResPrintf(StdErr, IDS_ERROR_OUT_OF_RANGE);
+ return EXIT_FAILURE;
+ }
+
+ return InputWait(bDisableInput, timerValue);
+}
Propchange: trunk/reactos/base/applications/cmdutils/timeout/timeout.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/base/applications/cmdutils/timeout/timeout.rc
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils…
==============================================================================
--- trunk/reactos/base/applications/cmdutils/timeout/timeout.rc (added)
+++ trunk/reactos/base/applications/cmdutils/timeout/timeout.rc [iso-8859-1] Mon Sep 25
23:31:44 2017
@@ -0,0 +1,21 @@
+#include <windef.h>
+// #include <winuser.h>
+
+#include "resource.h"
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+
+#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Timeout Utility"
+#define REACTOS_STR_INTERNAL_NAME "timeout"
+#define REACTOS_STR_ORIGINAL_FILENAME "timeout.exe"
+#include <reactos/version.rc>
+
+/* UTF-8 */
+#pragma code_page(65001)
+
+#ifdef LANGUAGE_EN_US
+ #include "lang/en-US.rc"
+#endif
+#ifdef LANGUAGE_FR_FR
+ #include "lang/fr-FR.rc"
+#endif
Propchange: trunk/reactos/base/applications/cmdutils/timeout/timeout.rc
------------------------------------------------------------------------------
svn:eol-style = native