Allow the user to press Ctrl-C to abort lengthy DIR (or DIR /p, etc.) operations.
-- v7: programs/cmd: Implement ability to abort lengthy directory operations via Ctrl-C.
From: Joe Souza jsouza@yahoo.com
--- programs/cmd/directory.c | 15 +++++++++------ programs/cmd/wcmd.h | 2 ++ programs/cmd/wcmdmain.c | 19 +++++++++++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/programs/cmd/directory.c b/programs/cmd/directory.c index 3a2a5955d12..a378c205e5a 100644 --- a/programs/cmd/directory.c +++ b/programs/cmd/directory.c @@ -333,7 +333,7 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le } WINE_TRACE("cols=%d, rows=%d\n", numCols, numRows);
- for (rows=0; rows<numRows; rows++) { + for (rows=0; rows<numRows && errorlevel == NO_ERROR; rows++) { BOOL addNewLine = TRUE; for (cols=0; cols<numCols; cols++) { WCHAR username[24]; @@ -428,9 +428,12 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le } if (addNewLine) WCMD_output_asis(L"\r\n"); cur_width = 0; + + /* Allow command to be aborted if user presses Ctrl-C. */ + errorlevel = WCMD_ctrlc_status(); }
- if (!bare) { + if (!bare && errorlevel == NO_ERROR) { if (file_count == 1) { WCMD_output (L" 1 file %1!25s! bytes\n", WCMD_filesize64 (byte_count.QuadPart)); } @@ -442,7 +445,7 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le file_total = file_total + file_count; dir_total = dir_total + dir_count;
- if (!bare && !recurse) { + if (!bare && !recurse && errorlevel == NO_ERROR) { if (dir_count == 1) { WCMD_output (L"%1!8d! directory ", 1); } else { @@ -453,7 +456,7 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le free(fd);
/* When recursing, look in all subdirectories for matches */ - if (recurse) { + if (recurse && errorlevel == NO_ERROR) { DIRECTORY_STACK *dirStack = NULL; DIRECTORY_STACK *lastEntry = NULL; WIN32_FIND_DATAW finddata; @@ -950,7 +953,7 @@ RETURN_CODE WCMD_directory(WCHAR *args) thisEntry = fullParms; trailerReqd = FALSE;
- while (thisEntry != NULL) { + while (thisEntry != NULL && errorlevel != STATUS_CONTROL_C_EXIT) {
/* Output disk free (trailer) and volume information (header) if the drive letter changes */ @@ -986,7 +989,7 @@ RETURN_CODE WCMD_directory(WCHAR *args) errorlevel = NO_ERROR; prevEntry = thisEntry; thisEntry = WCMD_list_directory (thisEntry, 0); - if (errorlevel) + if (errorlevel && errorlevel != STATUS_CONTROL_C_EXIT) num_empty++; else num_with_data++; diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index caacd44995d..225ebd44310 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -224,6 +224,8 @@ RETURN_CODE WCMD_run_builtin_command(int cmd_index, WCHAR *cmd); BOOL WCMD_find_label(HANDLE h, const WCHAR*, LARGE_INTEGER *pos); void WCMD_set_label_end(WCHAR *string);
+RETURN_CODE WCMD_ctrlc_status(void); + void *xrealloc(void *, size_t) __WINE_ALLOC_SIZE(2) __WINE_DEALLOC(free);
static inline void *xalloc(size_t sz) __WINE_MALLOC; diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 223bb55d2c6..77f1112be23 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -57,6 +57,8 @@ static int max_height; static int max_width; static int numChars;
+static HANDLE control_c_event; + #define MAX_WRITECONSOLE_SIZE 65535
/* @@ -3848,9 +3850,19 @@ RETURN_CODE node_execute(CMD_NODE *node) return return_code; }
+ +RETURN_CODE WCMD_ctrlc_status(void) +{ + return (WAIT_OBJECT_0 == WaitForSingleObject(control_c_event, 0)) ? STATUS_CONTROL_C_EXIT : NO_ERROR; +} + static BOOL WINAPI my_event_handler(DWORD ctrl) { WCMD_output(L"\n"); + if (ctrl == CTRL_C_EVENT) + { + SetEvent(control_c_event); + } return ctrl == CTRL_C_EVENT; }
@@ -3901,6 +3913,11 @@ int __cdecl wmain (int argc, WCHAR *argvW[]) forloopcontext = NULL; WCMD_save_for_loop_context(TRUE);
+ /* Initialize the event here because the command loop at the bottom will + * reset it unconditionally even if the Control-C handler is not installed. + */ + control_c_event = CreateEventW(NULL, TRUE, FALSE, NULL); + /* Can't use argc/argv as it will have stripped quotes from parameters * meaning cmd.exe /C echo "quoted string" is impossible */ @@ -4234,10 +4251,12 @@ int __cdecl wmain (int argc, WCHAR *argvW[]) { if (rpl_status == RPL_SUCCESS && toExecute) { + ResetEvent(control_c_event); node_execute(toExecute); node_dispose_tree(toExecute); if (echo_mode) WCMD_output_asis(L"\r\n"); } } + CloseHandle(control_c_event); return 0; }