From: Akihiro Sagawa sagawa.aki@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 -@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 */