From: Akihiro Sagawa <sagawa.aki(a)gmail.com> To prevent performance degradation, we will cache the result returned by GetConsoleOutputCP() after executing any external command. --- programs/cmd/batch.c | 20 ++++++++++++++++---- programs/cmd/builtins.c | 1 + programs/cmd/tests/test_utf8.cmd.exp | 2 +- programs/cmd/wcmd.h | 1 + programs/cmd/wcmdmain.c | 6 ++++++ 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c index 15c01de4b89..89789cd0223 100644 --- a/programs/cmd/batch.c +++ b/programs/cmd/batch.c @@ -24,6 +24,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(cmd); +static UINT file_codepage; /* codepage for reading batch file */ + static RETURN_CODE WCMD_batch_main_loop(void) { RETURN_CODE return_code = NO_ERROR; @@ -200,6 +202,18 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, BOOL raw, return WCMD_parameter_with_delims (s, n, start, raw, wholecmdline, L" \t,=;"); } +/**************************************************************************** + * WCMD_update_file_codepage + * + * Update a file codepage used in WCMD_fgets. + * Since GetConsoleOutputCP is slow, we cache the result in advance. + */ +void WCMD_update_file_codepage(void) +{ + UINT cp = GetConsoleOutputCP(); + file_codepage = cp ? cp : CP_OEMCP; +} + /**************************************************************************** * WCMD_fgets * @@ -234,10 +248,8 @@ WCHAR *WCMD_fgets(WCHAR *buf, DWORD noChars, HANDLE h) else { LARGE_INTEGER filepos; char *bufA; - UINT cp; const char *p; - cp = GetOEMCP(); bufA = xalloc(noChars); /* Save current file position */ @@ -251,7 +263,7 @@ WCHAR *WCMD_fgets(WCHAR *buf, DWORD noChars, HANDLE h) } /* Find first EOL */ - for (p = bufA; p < (bufA + charsRead); p = CharNextExA(cp, p, 0)) { + for (p = bufA; p < (bufA + charsRead); p = CharNextExA(file_codepage, p, 0)) { if (*p == '\n' || *p == '\r') break; } @@ -260,7 +272,7 @@ WCHAR *WCMD_fgets(WCHAR *buf, DWORD noChars, HANDLE h) filepos.QuadPart += p - bufA + 1 + (*p == '\r' ? 1 : 0); SetFilePointerEx(h, filepos, NULL, FILE_BEGIN); - i = MultiByteToWideChar(cp, 0, bufA, p - bufA, buf, noChars); + i = MultiByteToWideChar(file_codepage, 0, bufA, p - bufA, buf, noChars); free(bufA); } diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index d7c5090d17f..d1a646b98a2 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -3393,6 +3393,7 @@ RETURN_CODE WCMD_start(WCHAR *args) WaitForSingleObject( pi.hProcess, INFINITE ); GetExitCodeProcess( pi.hProcess, &exit_code ); errorlevel = (exit_code == STILL_ACTIVE) ? NO_ERROR : exit_code; + WCMD_update_file_codepage(); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } diff --git a/programs/cmd/tests/test_utf8.cmd.exp b/programs/cmd/tests/test_utf8.cmd.exp index 0b767fed5d9..4ac22345138 100644 --- a/programs/cmd/tests/test_utf8.cmd.exp +++ b/programs/cmd/tests/test_utf8.cmd.exp @@ -1,2 +1,2 @@ --- Test 1 -(a)todo_wine@alpha +alpha diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index caacd44995d..031f08f7088 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -199,6 +199,7 @@ RETURN_CODE WCMD_volume(void); RETURN_CODE WCMD_mklink(WCHAR *args); RETURN_CODE WCMD_change_drive(WCHAR drive); +void WCMD_update_file_codepage (void); WCHAR *WCMD_fgets (WCHAR *buf, DWORD n, HANDLE stream); WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, BOOL raw, BOOL wholecmdline); WCHAR *WCMD_parameter_with_delims (WCHAR *s, int n, WCHAR **start, BOOL raw, diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 1018fd56624..42c6d2d33ef 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -1373,7 +1373,10 @@ static RETURN_CODE run_full_path(const WCHAR *file, WCHAR *full_cmdline, BOOL ca } if (!interactive || (console && !HIWORD(console))) + { WaitForSingleObject(handle, INFINITE); + WCMD_update_file_codepage(); + } GetExitCodeProcess(handle, &exit_code); errorlevel = (exit_code == STILL_ACTIVE) ? NO_ERROR : exit_code; @@ -3890,6 +3893,9 @@ int __cdecl wmain (int argc, WCHAR *argvW[]) forloopcontext = NULL; WCMD_save_for_loop_context(TRUE); + /* init batch file codepage */ + WCMD_update_file_codepage(); + /* Can't use argc/argv as it will have stripped quotes from parameters * meaning cmd.exe /C echo "quoted string" is impossible */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6885