Signed-off-by: Hugh McMaster hugh.mcmaster@outlook.com --- programs/chcp.com/Makefile.in | 5 ++- programs/chcp.com/chcp.rc | 29 ++++++++++++++ programs/chcp.com/main.c | 75 ++++++++++++++++++++++++++++++++--- programs/chcp.com/resource.h | 24 +++++++++++ 4 files changed, 127 insertions(+), 6 deletions(-) create mode 100644 programs/chcp.com/chcp.rc create mode 100644 programs/chcp.com/resource.h
diff --git a/programs/chcp.com/Makefile.in b/programs/chcp.com/Makefile.in index 46ed25f3cea..2f6d273990a 100644 --- a/programs/chcp.com/Makefile.in +++ b/programs/chcp.com/Makefile.in @@ -1,6 +1,9 @@ -MODULE = chcp.com +MODULE = chcp.com +DELAYIMPORTS = user32
EXTRADLLFLAGS = -mconsole -municode
C_SRCS = \ main.c + +RC_SRCS = chcp.rc diff --git a/programs/chcp.com/chcp.rc b/programs/chcp.com/chcp.rc new file mode 100644 index 00000000000..04d90d05942 --- /dev/null +++ b/programs/chcp.com/chcp.rc @@ -0,0 +1,29 @@ +/* + * Copyright 2021 Hugh McMaster + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "resource.h" + +#pragma makedep po + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +STRINGTABLE +{ + STRING_ACTIVE_CODE_PAGE, "Active code page: %1!u!\n" + STRING_INVALID_CODE_PAGE, "Invalid code page\n" +} diff --git a/programs/chcp.com/main.c b/programs/chcp.com/main.c index 6ace10cf93e..5b3486a4366 100644 --- a/programs/chcp.com/main.c +++ b/programs/chcp.com/main.c @@ -16,20 +16,85 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#include "wine/debug.h" +#include <windows.h> +#include <stdlib.h> +#include "resource.h"
-#include "wincon.h" -#include "stdlib.h" +#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(chcp);
+static void output_writeconsole(const WCHAR *str, DWORD wlen) +{ + DWORD count, ret; + + ret = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), str, wlen, &count, NULL); + if (!ret) + { + DWORD len; + char *msgA; + + /* On Windows WriteConsoleW() fails if the output is redirected. So fall + * back to WriteFile(), assuming the console encoding is still the right + * one in that case. + */ + len = WideCharToMultiByte(GetConsoleOutputCP(), 0, str, wlen, NULL, 0, NULL, NULL); + msgA = malloc(len); + + WideCharToMultiByte(GetConsoleOutputCP(), 0, str, wlen, msgA, len, NULL, NULL); + WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), msgA, len, &count, FALSE); + free(msgA); + } +} + +static void output_formatstring(const WCHAR *fmt, va_list va_args) +{ + WCHAR *str; + DWORD len; + + len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, + fmt, 0, 0, (WCHAR *)&str, 0, &va_args); + if (!len && GetLastError() != ERROR_NO_WORK_DONE) + { + WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(fmt)); + return; + } + output_writeconsole(str, len); + LocalFree(str); +} + +static void WINAPIV output_message(unsigned int id, ...) +{ + WCHAR *fmt = NULL; + int len; + va_list va_args; + + if (!(len = LoadStringW(GetModuleHandleW(NULL), id, (WCHAR *)&fmt, 0))) + { + WINE_FIXME("LoadString failed with %d\n", GetLastError()); + return; + } + + len++; + fmt = malloc(len * sizeof(WCHAR)); + if (!fmt) return; + + LoadStringW(GetModuleHandleW(NULL), id, fmt, len); + + va_start(va_args, id); + output_formatstring(fmt, va_args); + va_end(va_args); + + free(fmt); +} + int __cdecl wmain(int argc, WCHAR *argv[]) { int i;
if (argc == 1) { - printf("Active code page: %d\n", GetConsoleCP()); + output_message(STRING_ACTIVE_CODE_PAGE, GetConsoleCP()); return 0; } else if (argc == 2) @@ -39,7 +104,7 @@ int __cdecl wmain(int argc, WCHAR *argv[])
if (!success) { - printf("Invalid code page\n"); + output_message(STRING_INVALID_CODE_PAGE); } return !success; } diff --git a/programs/chcp.com/resource.h b/programs/chcp.com/resource.h new file mode 100644 index 00000000000..200cbb11d18 --- /dev/null +++ b/programs/chcp.com/resource.h @@ -0,0 +1,24 @@ +/* + * Copyright 2021 Hugh McMaster + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <windef.h> + +/* Translation IDs */ + +#define STRING_ACTIVE_CODE_PAGE 100 +#define STRING_INVALID_CODE_PAGE 101
Signed-off-by: Hugh McMaster hugh.mcmaster@outlook.com --- programs/chcp.com/main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/programs/chcp.com/main.c b/programs/chcp.com/main.c index 5b3486a4366..cc64e044b06 100644 --- a/programs/chcp.com/main.c +++ b/programs/chcp.com/main.c @@ -102,10 +102,11 @@ int __cdecl wmain(int argc, WCHAR *argv[]) int codepage = _wtoi(argv[1]); int success = SetConsoleCP(codepage) && SetConsoleOutputCP(codepage);
- if (!success) - { + if (success) + output_message(STRING_ACTIVE_CODE_PAGE, codepage); + else output_message(STRING_INVALID_CODE_PAGE); - } + return !success; }
Signed-off-by: Hugh McMaster hugh.mcmaster@outlook.com --- programs/chcp.com/chcp.rc | 4 ++++ programs/chcp.com/main.c | 12 ++++++++++-- programs/chcp.com/resource.h | 1 + 3 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/programs/chcp.com/chcp.rc b/programs/chcp.com/chcp.rc index 04d90d05942..705eb32c751 100644 --- a/programs/chcp.com/chcp.rc +++ b/programs/chcp.com/chcp.rc @@ -26,4 +26,8 @@ STRINGTABLE { STRING_ACTIVE_CODE_PAGE, "Active code page: %1!u!\n" STRING_INVALID_CODE_PAGE, "Invalid code page\n" + STRING_USAGE, "CHCP [number]\n\n\ +\ Sets or displays the active console code page.\n\n\ +\ number The console code page to activate.\n\n\ +\ Type CHCP without a number to display the active console code page.\n\n" } diff --git a/programs/chcp.com/main.c b/programs/chcp.com/main.c index cc64e044b06..31ddba4c137 100644 --- a/programs/chcp.com/main.c +++ b/programs/chcp.com/main.c @@ -99,8 +99,16 @@ int __cdecl wmain(int argc, WCHAR *argv[]) } else if (argc == 2) { - int codepage = _wtoi(argv[1]); - int success = SetConsoleCP(codepage) && SetConsoleOutputCP(codepage); + int codepage, success; + + if (!lstrcmpW(argv[1], L"/?")) + { + output_message(STRING_USAGE); + return 0; + } + + codepage = _wtoi(argv[1]); + success = SetConsoleCP(codepage) && SetConsoleOutputCP(codepage);
if (success) output_message(STRING_ACTIVE_CODE_PAGE, codepage); diff --git a/programs/chcp.com/resource.h b/programs/chcp.com/resource.h index 200cbb11d18..5318b3c2e01 100644 --- a/programs/chcp.com/resource.h +++ b/programs/chcp.com/resource.h @@ -22,3 +22,4 @@
#define STRING_ACTIVE_CODE_PAGE 100 #define STRING_INVALID_CODE_PAGE 101 +#define STRING_USAGE 102