diff --git a/programs/start/Makefile.in b/programs/start/Makefile.in index e889acca834..d7deed00edc 100644 --- a/programs/start/Makefile.in +++ b/programs/start/Makefile.in @@ -3,7 +3,7 @@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = start.exe -APPMODE = -mconsole +APPMODE = -mconsole -municode IMPORTS = shell32 user32 kernel32 C_SRCS = start.c diff --git a/programs/start/start.c b/programs/start/start.c index 773544ff9b4..58748c8ba37 100644 --- a/programs/start/start.c +++ b/programs/start/start.c @@ -3,6 +3,7 @@ * Compatible with Microsoft's "c:\windows\command\start.exe" * * Copyright 2003 Dan Kegel + * Copyright 2007 Lyutin Anatoly (Etersoft) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,40 +26,40 @@ #include #include +#include +#include + #include "resources.h" +WINE_DEFAULT_DEBUG_CHANNEL(start); + /** Output given message to stdout without formatting. */ -static void output(const char *message) +static void output(const WCHAR *message) { DWORD count; - WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), message, strlen(message), &count, NULL); -} + DWORD res; + int wlen = strlenW(message); -/** - Output given message, - followed by ": ", - followed by description of given GetLastError() value to stdout, - followed by a trailing newline, - then terminate. -*/ -static void fatal_error(const char *msg, DWORD error_code) -{ - LPVOID lpMsgBuf; - int status; + if (!wlen) return; - output(msg); - output(": "); - status = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, 0, (LPTSTR) & lpMsgBuf, 0, NULL); - if (!status) { - output("FormatMessage failed\n"); - } else { - output(lpMsgBuf); - LocalFree((HLOCAL) lpMsgBuf); - output("\n"); + res = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), message, wlen, &count, NULL); + + /* If writing to console fails, assume its file + i/o so convert to OEM codepage and output */ + if (!res) + { + DWORD len; + char *mesA; + /* Convert to OEM, then output */ + len = WideCharToMultiByte( GetConsoleOutputCP(), 0, message, wlen, NULL, 0, NULL, NULL ); + mesA = HeapAlloc(GetProcessHeap(), 0, len*sizeof(char)); + if (!mesA) return; + WideCharToMultiByte( GetConsoleOutputCP(), 0, message, wlen, mesA, len, NULL, NULL ); + WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), mesA, len, &count, FALSE); + HeapFree(GetProcessHeap(), 0, mesA); } - ExitProcess(1); } /** @@ -68,24 +69,47 @@ static void fatal_error(const char *msg, DWORD error_code) followed by a trailing newline, then terminate. */ + +static void fatal_error(const WCHAR *msg, DWORD error_code) +{ + LPVOID lpMsgBuf; + int status; + static const WCHAR colonsW[] = { ':', ' ', 0 }; + static const WCHAR newlineW[] = { '\n', 0 }; + + output(msg); + output(colonsW); + status = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, 0, (LPWSTR) & lpMsgBuf, 0, NULL); + if (!status) + { + WINE_ERR("FormatMessage failed\n"); + } else + { + output(lpMsgBuf); + LocalFree((HLOCAL) lpMsgBuf); + output(newlineW); + } + ExitProcess(1); +} + static void fatal_string_error(int which, DWORD error_code) { - char msg[2048]; + WCHAR msg[2048]; - if (!LoadString(GetModuleHandle(NULL), which, - msg, sizeof(msg))) - fatal_error("LoadString failed", GetLastError()); + if (!LoadStringW(GetModuleHandle(NULL), which, + msg, sizeof(msg)/sizeof(WCHAR))) + WINE_ERR("LoadString failed, error %d\n", GetLastError()); fatal_error(msg, error_code); } static void fatal_string(int which) { - char msg[2048]; + WCHAR msg[2048]; - if (!LoadString(GetModuleHandle(NULL), which, - msg, sizeof(msg))) - fatal_error("LoadString failed", GetLastError()); + if (!LoadStringW(GetModuleHandle(NULL), which, + msg, sizeof(msg)/sizeof(WCHAR))) + WINE_ERR("LoadString failed, error %d\n", GetLastError()); output(msg); ExitProcess(1); @@ -101,39 +125,43 @@ static void license(void) fatal_string(STRING_LICENSE); } -static char *build_args( int argc, char **argv ) +static WCHAR *build_args( int argc, WCHAR **argvW ) { - int i, len = 1; - char *ret, *p; + int i, wlen = 1; + WCHAR *ret, *p; + static const WCHAR FormatQuotesW[] = { ' ', '\"', '%', 's', '\"', 0 }; + static const WCHAR FormatW[] = { ' ', '%', 's', 0 }; for (i = 0; i < argc; i++ ) { - len += strlen(argv[i]) + 1; - if (strchr(argv[i], ' ')) - len += 2; + wlen += strlenW(argvW[i]) + 1; + if (strchrW(argvW[i], ' ')) + wlen += 2; } - ret = HeapAlloc( GetProcessHeap(), 0, len ); + ret = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(WCHAR) ); ret[0] = 0; for (i = 0, p = ret; i < argc; i++ ) { - if (strchr(argv[i], ' ')) - p += sprintf(p, " \"%s\"", argv[i]); + if (strchrW(argvW[i], ' ')) + p += sprintfW(p, FormatQuotesW, argvW[i]); else - p += sprintf(p, " %s", argv[i]); + p += sprintfW(p, FormatW, argvW[i]); } return ret; } -int main(int argc, char *argv[]) +int wmain (int argc, WCHAR *argv[]) { - SHELLEXECUTEINFO sei; - char *args; + SHELLEXECUTEINFOW sei; + WCHAR *args = NULL; int i; + static const WCHAR openW[] = { 'o', 'p', 'e', 'n', 0 }; + memset(&sei, 0, sizeof(sei)); sei.cbSize = sizeof(sei); - sei.lpVerb = "open"; + sei.lpVerb = openW; sei.nShow = SW_SHOWNORMAL; /* Dunno what these mean, but it looks like winMe's start uses them */ sei.fMask = SEE_MASK_FLAG_DDEWAIT| @@ -175,7 +203,7 @@ int main(int argc, char *argv[]) sei.fMask |= SEE_MASK_NOCLOSEPROCESS; break; default: - printf("Option '%s' not recognized\n", argv[i]+ci-1); + WINE_ERR("Option '%s' not recognized\n", wine_dbgstr_w( argv[i]+ci-1)); usage(); } /* Skip to next slash */ @@ -192,20 +220,15 @@ int main(int argc, char *argv[]) args = build_args( argc - i, &argv[i] ); sei.lpParameters = args; - if (!ShellExecuteEx(&sei)) + if (!ShellExecuteExW(&sei)) fatal_string_error(STRING_EXECFAIL, GetLastError()); HeapFree( GetProcessHeap(), 0, args ); if (sei.fMask & SEE_MASK_NOCLOSEPROCESS) { DWORD exitcode; - DWORD waitcode; - waitcode = WaitForSingleObject(sei.hProcess, INFINITE); - if (waitcode) - fatal_error("WaitForSingleObject", GetLastError()); - if (!GetExitCodeProcess(sei.hProcess, &exitcode)) - fatal_error("GetExitCodeProcess", GetLastError()); - /* fixme: haven't tested whether exit code works properly */ + WaitForSingleObject(sei.hProcess, INFINITE); + GetExitCodeProcess(sei.hProcess, &exitcode); ExitProcess(exitcode); }