Index: base/applications/cmdutils/CMakeLists.txt =================================================================== --- base/applications/cmdutils/CMakeLists.txt (revision 68830) +++ base/applications/cmdutils/CMakeLists.txt (working copy) @@ -11,6 +11,7 @@ add_subdirectory(reg) add_subdirectory(sort) add_subdirectory(taskkill) +add_subdirectory(timeout) add_subdirectory(tree) add_subdirectory(whoami) add_subdirectory(wmic) Index: base/applications/cmdutils/timeout/CMakeLists.txt =================================================================== --- base/applications/cmdutils/timeout/CMakeLists.txt (revision 0) +++ base/applications/cmdutils/timeout/CMakeLists.txt (working copy) @@ -0,0 +1,5 @@ + +add_executable(timeout timeout.c timeout.rc) +set_module_type(timeout win32cui UNICODE) +add_importlibs(timeout msvcrt user32 kernel32) +add_cd_file(TARGET timeout DESTINATION reactos/system32 FOR all) Index: base/applications/cmdutils/timeout/lang/en-us.rc =================================================================== --- base/applications/cmdutils/timeout/lang/en-us.rc (revision 0) +++ base/applications/cmdutils/timeout/lang/en-us.rc (working copy) @@ -0,0 +1,23 @@ +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +STRINGTABLE +BEGIN + IDS_USAGE "ReactOS Timeout Utility\n\ +\n\ +Usage: timeout [/?][/t time][/nobreak]\n\n\ + /?\t\tDisplay this help.\n\ + /t time\tSpecify the number of seconds to wait (-1 to 99999).\n\ + /nobreak\tIgnore all user input except for Ctrl+C.\n\n\ +NOTE: For /t, a value of -1 means the program will wait until a key is pressed.\n" + IDS_ERROR_OUT_OF_RANGE "ERROR: The timer value must be within range (-1 to 99999).\n" + IDS_ERROR_GETCONSOLEMODE "ERROR: Unable to get the console mode.\n" + IDS_ERROR_SETCONSOLEMODE "ERROR: Unable to set the console mode.\n" + IDS_ERROR_INVALID_HANDLE_VALUE "ERROR: Unable to get the standard handle for the console.\n" + IDS_ERROR_READ_INPUT "ERROR: Unable to read the console input.\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_FULL "Waiting for %d second(s). Press Ctrl+C to quit ..." + IDS_USER_INPUT_FULL "Waiting for %d second(s). Press any key to continue ..." +END Index: base/applications/cmdutils/timeout/resource.h =================================================================== --- base/applications/cmdutils/timeout/resource.h (revision 0) +++ base/applications/cmdutils/timeout/resource.h (working copy) @@ -0,0 +1,17 @@ +#ifndef RESOURCE_H +#define RESOURCE_H + +#define IDS_USAGE 0 +#define IDS_ERROR_OUT_OF_RANGE 1 +#define IDS_ERROR_GETCONSOLEMODE 2 +#define IDS_ERROR_SETCONSOLEMODE 3 +#define IDS_ERROR_INVALID_HANDLE_VALUE 4 +#define IDS_ERROR_READ_INPUT 5 +#define IDS_ERROR_NO_TIMER_VALUE 6 +#define IDS_ERROR_ONE_TIME 7 +#define IDS_NOBREAK_INPUT 8 +#define IDS_USER_INPUT 9 +#define IDS_NOBREAK_INPUT_FULL 10 +#define IDS_USER_INPUT_FULL 11 + +#endif /* RESOURCE_H */ \ No newline at end of file Index: base/applications/cmdutils/timeout/timeout.c =================================================================== --- base/applications/cmdutils/timeout/timeout.c (revision 0) +++ base/applications/cmdutils/timeout/timeout.c (working copy) @@ -0,0 +1,218 @@ +/* + * 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) + */ + +#include +#include +#include +#include +#include +#include + +#include "resource.h" + +#define MAX_BUFFER_SIZE 4096 +#define INPUT_BUFFER 128 + +BOOL isRunning = TRUE; + +int PrintResourceString(INT resID, ...) +{ + WCHAR tmpBuffer[MAX_BUFFER_SIZE]; + va_list arg_ptr; + + va_start(arg_ptr, resID); + LoadStringW(GetModuleHandle(NULL), resID, tmpBuffer, MAX_BUFFER_SIZE); + vfwprintf(stdout, tmpBuffer, arg_ptr); + va_end(arg_ptr); + + return wcslen(tmpBuffer); +} + +BOOL InputWait(BOOL disableKey, int count) +{ + HANDLE stdInput; + INPUT_RECORD inputRead[INPUT_BUFFER]; + DWORD prevMode, recordsRead, i; + BOOL keyPress = FALSE; + int tmpCount = count; + + /* Grabs the current input handle */ + stdInput = GetStdHandle(STD_INPUT_HANDLE); + if (stdInput == INVALID_HANDLE_VALUE) + { + PrintResourceString(IDS_ERROR_INVALID_HANDLE_VALUE); + return FALSE; + } + + /* Stores the previous input handle so it can be changed back later */ + if (!GetConsoleMode(stdInput, &prevMode)) + { + PrintResourceString(IDS_ERROR_GETCONSOLEMODE); + return FALSE; + } + + /* Changes the input handle so it can recieve user input */ + if (!SetConsoleMode(stdInput, ENABLE_PROCESSED_INPUT)) + { + PrintResourceString(IDS_ERROR_SETCONSOLEMODE); + return FALSE; + } + + /* If the key input has been disabled, then just wait for Ctrl+C input */ + if (disableKey) + { + wprintf(L"\n"); + + /* If there is no timer, then just show the message */ + if (tmpCount == -1) + PrintResourceString(IDS_NOBREAK_INPUT); + + /* FIXME: If any characters are pressed, they will show on the command line input when + the program exits */ + while (TRUE) + { + if (tmpCount != -1) + { + wprintf(L"\b \r"); + PrintResourceString(IDS_NOBREAK_INPUT_FULL, tmpCount); + tmpCount--; + } + + if (tmpCount == 0) + { + wprintf(L"\b \r"); + PrintResourceString(IDS_NOBREAK_INPUT_FULL, tmpCount); + break; + } + + /* FIXME: Find a better timer solution since this one is irregular */ + Sleep(1000); + } + } + else + { + wprintf(L"\n"); + + /* If there is no timer, then just show the message */ + if (tmpCount == -1) + PrintResourceString(IDS_USER_INPUT); + else + PrintResourceString(IDS_USER_INPUT_FULL, tmpCount); + + while (!keyPress) + { + /* Makes an attempt to read the user's input */ + if(!ReadConsoleInput(stdInput, inputRead, INPUT_BUFFER, &recordsRead)) + { + PrintResourceString(IDS_ERROR_READ_INPUT); + goto timeoutError; + } + + /* Checks for user input */ + for (i = 0; i < recordsRead; i++) + { + switch(inputRead[i].EventType) + { + case KEY_EVENT: + { + if (inputRead[i].Event.KeyEvent.bKeyDown) + { + keyPress = TRUE; + break; + } + } + default:break; + } + + count--; + } + } + } + + /* Sets the console to the previous mode that was set before the program started */ + wprintf(L"\n"); + SetConsoleMode(stdInput, prevMode); + return TRUE; + +timeoutError: + wprintf(L"\n"); + SetConsoleMode(stdInput, prevMode); + return FALSE; +} + +int wmain(int argc, WCHAR *argv[]) +{ + int timerValue = 1; + BOOL disableInput = FALSE, isTimed = FALSE; + int index = 0; + + if (argc == 1) + { + PrintResourceString(IDS_USAGE); + return 0; + } + + for (index = 1; index < argc; index++) + { + if (argv[index][0] == L'-' || argv[index][0] == L'/') + { + switch (towlower(argv[index][1])) + { + case L'?': + { + PrintResourceString(IDS_USAGE); + return 0; + } + case L't': + { + /* The utility does not support more than one timer value */ + if (isTimed == TRUE) + { + PrintResourceString(IDS_ERROR_ONE_TIME); + return 0; + } + + timerValue = _wtoi(argv[index+1]); + isTimed = TRUE; + break; + } + } + } + + /* This flag is used for making user input harder by strictly + limiting user input to Ctrl+C */ + if ((_wcsicmp(argv[index], L"/nobreak") == 0) || + (_wcsicmp(argv[index], L"-nobreak") == 0)) + disableInput = TRUE; + } + + /* The program needs a timer value in order to continue. */ + if (isTimed == FALSE) + { + PrintResourceString(IDS_ERROR_NO_TIMER_VALUE); + return 0; + } + + /* Make sure the timer value is within range */ + if ((timerValue < -1) || (timerValue > 99999)) + { + PrintResourceString(IDS_ERROR_OUT_OF_RANGE, timerValue); + return 1; + } + + /* If the value is zero, then don't bother to check user input */ + if (timerValue == 0) + { + wprintf(L"\n"); + PrintResourceString((disableInput ? IDS_NOBREAK_INPUT_FULL : IDS_USER_INPUT_FULL), timerValue); + wprintf(L"\n"); + return 0; + } + + return InputWait(disableInput, timerValue); +} Index: base/applications/cmdutils/timeout/timeout.rc =================================================================== --- base/applications/cmdutils/timeout/timeout.rc (revision 0) +++ base/applications/cmdutils/timeout/timeout.rc (working copy) @@ -0,0 +1,19 @@ +#include +#include + +#include "resource.h" + +/* Define language neutral resources */ +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 + +/* UTF-8 */ +#pragma code_page(65001) + +#ifdef LANGUAGE_EN_US + #include "lang/en-US.rc" +#endif Index: base/applications/cmdutils/timeout/CMakeLists.txt =================================================================== --- base/applications/cmdutils/timeout/CMakeLists.txt (revision 0) +++ base/applications/cmdutils/timeout/CMakeLists.txt (working copy) @@ -0,0 +1,5 @@ + +add_executable(timeout timeout.c timeout.rc) +set_module_type(timeout win32cui UNICODE) +add_importlibs(timeout msvcrt user32 kernel32) +add_cd_file(TARGET timeout DESTINATION reactos/system32 FOR all) Index: base/applications/cmdutils/timeout/lang/en-us.rc =================================================================== --- base/applications/cmdutils/timeout/lang/en-us.rc (revision 0) +++ base/applications/cmdutils/timeout/lang/en-us.rc (working copy) @@ -0,0 +1,23 @@ +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +STRINGTABLE +BEGIN + IDS_USAGE "ReactOS Timeout Utility\n\ +\n\ +Usage: timeout [/?][/t time][/nobreak]\n\n\ + /?\t\tDisplay this help.\n\ + /t time\tSpecify the number of seconds to wait (-1 to 99999).\n\ + /nobreak\tIgnore all user input except for Ctrl+C.\n\n\ +NOTE: For /t, a value of -1 means the program will wait until a key is pressed.\n" + IDS_ERROR_OUT_OF_RANGE "ERROR: The timer value must be within range (-1 to 99999).\n" + IDS_ERROR_GETCONSOLEMODE "ERROR: Unable to get the console mode.\n" + IDS_ERROR_SETCONSOLEMODE "ERROR: Unable to set the console mode.\n" + IDS_ERROR_INVALID_HANDLE_VALUE "ERROR: Unable to get the standard handle for the console.\n" + IDS_ERROR_READ_INPUT "ERROR: Unable to read the console input.\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_FULL "Waiting for %d second(s). Press Ctrl+C to quit ..." + IDS_USER_INPUT_FULL "Waiting for %d second(s). Press any key to continue ..." +END Index: base/applications/cmdutils/timeout/lang/en-us.rc =================================================================== --- base/applications/cmdutils/timeout/lang/en-us.rc (revision 0) +++ base/applications/cmdutils/timeout/lang/en-us.rc (working copy) @@ -0,0 +1,23 @@ +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +STRINGTABLE +BEGIN + IDS_USAGE "ReactOS Timeout Utility\n\ +\n\ +Usage: timeout [/?][/t time][/nobreak]\n\n\ + /?\t\tDisplay this help.\n\ + /t time\tSpecify the number of seconds to wait (-1 to 99999).\n\ + /nobreak\tIgnore all user input except for Ctrl+C.\n\n\ +NOTE: For /t, a value of -1 means the program will wait until a key is pressed.\n" + IDS_ERROR_OUT_OF_RANGE "ERROR: The timer value must be within range (-1 to 99999).\n" + IDS_ERROR_GETCONSOLEMODE "ERROR: Unable to get the console mode.\n" + IDS_ERROR_SETCONSOLEMODE "ERROR: Unable to set the console mode.\n" + IDS_ERROR_INVALID_HANDLE_VALUE "ERROR: Unable to get the standard handle for the console.\n" + IDS_ERROR_READ_INPUT "ERROR: Unable to read the console input.\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_FULL "Waiting for %d second(s). Press Ctrl+C to quit ..." + IDS_USER_INPUT_FULL "Waiting for %d second(s). Press any key to continue ..." +END Index: base/applications/cmdutils/timeout/resource.h =================================================================== --- base/applications/cmdutils/timeout/resource.h (revision 0) +++ base/applications/cmdutils/timeout/resource.h (working copy) @@ -0,0 +1,17 @@ +#ifndef RESOURCE_H +#define RESOURCE_H + +#define IDS_USAGE 0 +#define IDS_ERROR_OUT_OF_RANGE 1 +#define IDS_ERROR_GETCONSOLEMODE 2 +#define IDS_ERROR_SETCONSOLEMODE 3 +#define IDS_ERROR_INVALID_HANDLE_VALUE 4 +#define IDS_ERROR_READ_INPUT 5 +#define IDS_ERROR_NO_TIMER_VALUE 6 +#define IDS_ERROR_ONE_TIME 7 +#define IDS_NOBREAK_INPUT 8 +#define IDS_USER_INPUT 9 +#define IDS_NOBREAK_INPUT_FULL 10 +#define IDS_USER_INPUT_FULL 11 + +#endif /* RESOURCE_H */ \ No newline at end of file Index: base/applications/cmdutils/timeout/timeout.c =================================================================== --- base/applications/cmdutils/timeout/timeout.c (revision 0) +++ base/applications/cmdutils/timeout/timeout.c (working copy) @@ -0,0 +1,218 @@ +/* + * 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) + */ + +#include +#include +#include +#include +#include +#include + +#include "resource.h" + +#define MAX_BUFFER_SIZE 4096 +#define INPUT_BUFFER 128 + +BOOL isRunning = TRUE; + +int PrintResourceString(INT resID, ...) +{ + WCHAR tmpBuffer[MAX_BUFFER_SIZE]; + va_list arg_ptr; + + va_start(arg_ptr, resID); + LoadStringW(GetModuleHandle(NULL), resID, tmpBuffer, MAX_BUFFER_SIZE); + vfwprintf(stdout, tmpBuffer, arg_ptr); + va_end(arg_ptr); + + return wcslen(tmpBuffer); +} + +BOOL InputWait(BOOL disableKey, int count) +{ + HANDLE stdInput; + INPUT_RECORD inputRead[INPUT_BUFFER]; + DWORD prevMode, recordsRead, i; + BOOL keyPress = FALSE; + int tmpCount = count; + + /* Grabs the current input handle */ + stdInput = GetStdHandle(STD_INPUT_HANDLE); + if (stdInput == INVALID_HANDLE_VALUE) + { + PrintResourceString(IDS_ERROR_INVALID_HANDLE_VALUE); + return FALSE; + } + + /* Stores the previous input handle so it can be changed back later */ + if (!GetConsoleMode(stdInput, &prevMode)) + { + PrintResourceString(IDS_ERROR_GETCONSOLEMODE); + return FALSE; + } + + /* Changes the input handle so it can recieve user input */ + if (!SetConsoleMode(stdInput, ENABLE_PROCESSED_INPUT)) + { + PrintResourceString(IDS_ERROR_SETCONSOLEMODE); + return FALSE; + } + + /* If the key input has been disabled, then just wait for Ctrl+C input */ + if (disableKey) + { + wprintf(L"\n"); + + /* If there is no timer, then just show the message */ + if (tmpCount == -1) + PrintResourceString(IDS_NOBREAK_INPUT); + + /* FIXME: If any characters are pressed, they will show on the command line input when + the program exits */ + while (TRUE) + { + if (tmpCount != -1) + { + wprintf(L"\b \r"); + PrintResourceString(IDS_NOBREAK_INPUT_FULL, tmpCount); + tmpCount--; + } + + if (tmpCount == 0) + { + wprintf(L"\b \r"); + PrintResourceString(IDS_NOBREAK_INPUT_FULL, tmpCount); + break; + } + + /* FIXME: Find a better timer solution since this one is irregular */ + Sleep(1000); + } + } + else + { + wprintf(L"\n"); + + /* If there is no timer, then just show the message */ + if (tmpCount == -1) + PrintResourceString(IDS_USER_INPUT); + else + PrintResourceString(IDS_USER_INPUT_FULL, tmpCount); + + while (!keyPress) + { + /* Makes an attempt to read the user's input */ + if(!ReadConsoleInput(stdInput, inputRead, INPUT_BUFFER, &recordsRead)) + { + PrintResourceString(IDS_ERROR_READ_INPUT); + goto timeoutError; + } + + /* Checks for user input */ + for (i = 0; i < recordsRead; i++) + { + switch(inputRead[i].EventType) + { + case KEY_EVENT: + { + if (inputRead[i].Event.KeyEvent.bKeyDown) + { + keyPress = TRUE; + break; + } + } + default:break; + } + + count--; + } + } + } + + /* Sets the console to the previous mode that was set before the program started */ + wprintf(L"\n"); + SetConsoleMode(stdInput, prevMode); + return TRUE; + +timeoutError: + wprintf(L"\n"); + SetConsoleMode(stdInput, prevMode); + return FALSE; +} + +int wmain(int argc, WCHAR *argv[]) +{ + int timerValue = 1; + BOOL disableInput = FALSE, isTimed = FALSE; + int index = 0; + + if (argc == 1) + { + PrintResourceString(IDS_USAGE); + return 0; + } + + for (index = 1; index < argc; index++) + { + if (argv[index][0] == L'-' || argv[index][0] == L'/') + { + switch (towlower(argv[index][1])) + { + case L'?': + { + PrintResourceString(IDS_USAGE); + return 0; + } + case L't': + { + /* The utility does not support more than one timer value */ + if (isTimed == TRUE) + { + PrintResourceString(IDS_ERROR_ONE_TIME); + return 0; + } + + timerValue = _wtoi(argv[index+1]); + isTimed = TRUE; + break; + } + } + } + + /* This flag is used for making user input harder by strictly + limiting user input to Ctrl+C */ + if ((_wcsicmp(argv[index], L"/nobreak") == 0) || + (_wcsicmp(argv[index], L"-nobreak") == 0)) + disableInput = TRUE; + } + + /* The program needs a timer value in order to continue. */ + if (isTimed == FALSE) + { + PrintResourceString(IDS_ERROR_NO_TIMER_VALUE); + return 0; + } + + /* Make sure the timer value is within range */ + if ((timerValue < -1) || (timerValue > 99999)) + { + PrintResourceString(IDS_ERROR_OUT_OF_RANGE, timerValue); + return 1; + } + + /* If the value is zero, then don't bother to check user input */ + if (timerValue == 0) + { + wprintf(L"\n"); + PrintResourceString((disableInput ? IDS_NOBREAK_INPUT_FULL : IDS_USER_INPUT_FULL), timerValue); + wprintf(L"\n"); + return 0; + } + + return InputWait(disableInput, timerValue); +} Index: base/applications/cmdutils/timeout/timeout.rc =================================================================== --- base/applications/cmdutils/timeout/timeout.rc (revision 0) +++ base/applications/cmdutils/timeout/timeout.rc (working copy) @@ -0,0 +1,19 @@ +#include +#include + +#include "resource.h" + +/* Define language neutral resources */ +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 + +/* UTF-8 */ +#pragma code_page(65001) + +#ifdef LANGUAGE_EN_US + #include "lang/en-US.rc" +#endif