From: Akihiro Sagawa sagawa.aki@gmail.com
To prevent performance degradation, we will cache the result of GetConsoleOutputCP() after executing every external command. --- programs/cmd/batch.c | 20 ++++++++++++++++---- programs/cmd/builtins.c | 1 + programs/cmd/tests/test_builtins.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 20ae894dbfd..39ce96656f9 100644 --- a/programs/cmd/batch.c +++ b/programs/cmd/batch.c @@ -24,6 +24,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(cmd);
+static UINT file_code_page; /* code page for reading batch file */ + static RETURN_CODE WCMD_batch_main_loop(void) { RETURN_CODE return_code = NO_ERROR; @@ -205,6 +207,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_code_page + * + * Update the file code page used in the WCMD_fgets(). + * Since the GetConsoleOutputCP() is slow, we cache the result in advance. + */ +void WCMD_update_file_code_page(void) +{ + UINT cp = GetConsoleOutputCP(); + file_code_page = cp ? cp : CP_OEMCP; +} + /**************************************************************************** * WCMD_fgets * @@ -239,10 +253,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 */ @@ -256,7 +268,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_code_page, p, 0)) { if (*p == '\n' || *p == '\r') break; } @@ -265,7 +277,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_code_page, 0, bufA, p - bufA, buf, noChars); free(bufA); }
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index b78ae9d293b..151c71c90ab 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -3382,6 +3382,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_code_page(); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp index 46d045f3eb0..ff6f944cffb 100644 --- a/programs/cmd/tests/test_builtins.cmd.exp +++ b/programs/cmd/tests/test_builtins.cmd.exp @@ -2123,7 +2123,7 @@ Success @todo_wine@Success ---- Testing nasty bits ---- ------------ Testing updated code page execution ------------ -@todo_wine@Success +Success ------------ Testing combined CALLs/GOTOs ------------ world cheball diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index d4adc7fd7c8..20293221e38 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_code_page (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 84d3f52970e..39b865ae528 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -1435,7 +1435,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_code_page(); + } GetExitCodeProcess(handle, &exit_code); errorlevel = (exit_code == STILL_ACTIVE) ? NO_ERROR : exit_code;
@@ -3871,6 +3874,9 @@ int __cdecl wmain (int argc, WCHAR *argvW[]) */ control_c_event = CreateEventW(NULL, TRUE, FALSE, NULL);
+ /* Initialize the batch file code page */ + WCMD_update_file_code_page(); + /* Can't use argc/argv as it will have stripped quotes from parameters * meaning cmd.exe /C echo "quoted string" is impossible */