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/CMakeLists.txt?rev=75968&r1=75967&r2=75968&view=diff
==============================================================================
--- 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/timeout/CMakeLists.txt?rev=75968
==============================================================================
--- 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/timeout/lang/en-US.rc?rev=75968
==============================================================================
--- 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/timeout/lang/fr-FR.rc?rev=75968
==============================================================================
--- 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/timeout/resource.h?rev=75968
==============================================================================
--- 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/timeout/timeout.c?rev=75968
==============================================================================
--- 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 ([email protected])
+ */
+
+#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/timeout/timeout.rc?rev=75968
==============================================================================
--- 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


Reply via email to