From e7eb740583cdf4fe7993f022565733dc68c83425 Mon Sep 17 00:00:00 2001 From: Whindmar Saksit Date: Fri, 17 Jul 2026 12:39:03 +0200 Subject: [PATCH] [CMD] CHOICE command needs to handle pipe input without getting stuck in timeout This fixes cmd_winetest hanging on the echo Y | choice /C ABCXYZ /D A /T 2 test. - Reads the first character from stdin if stdin is not connected to a real console. - Ensures the timeout never goes negative if there is a problem reading stdin. --- base/shell/cmd/choice.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/base/shell/cmd/choice.c b/base/shell/cmd/choice.c index d7c0ada4c69..78a7ba5a0df 100644 --- a/base/shell/cmd/choice.c +++ b/base/shell/cmd/choice.c @@ -52,7 +52,13 @@ GetCharacterTimeout (LPTCH ch, DWORD dwMilliseconds) return GC_TIMEOUT; //otherwise get the event - ReadConsoleInput (hInput, &lpBuffer, 1, &dwRead); + lpBuffer.EventType = !KEY_EVENT; + if (!ReadConsoleInput (hInput, &lpBuffer, 1, &dwRead) && GetLastError () == ERROR_INVALID_HANDLE) + { + *ch = '\0'; + if (ReadFile(hInput, ch, 1, &dwRead, NULL)) + return GC_KEYREAD; + } //if the event is a key pressed if ((lpBuffer.EventType == KEY_EVENT) && @@ -315,7 +321,11 @@ CommandChoice (LPTSTR param) amount = nTimeout*1000; loop: - GCret = GetCharacterTimeout (&Ch, amount - (GetTickCount () - clk)); + nTimeout = amount - (GetTickCount () - clk); + if (nTimeout < 0) + GCret = GC_TIMEOUT; + else + GCret = GetCharacterTimeout (&Ch, nTimeout); switch (GCret) {