[PATCH 0/1] MR10398: Draft: wscript: Implement IActiveScriptSite::OnScriptError.
Format and print script error messages from the engine instead of ignoring them. For cscript (non-interactive mode), errors are printed to stderr in the standard format: <file>(<line>, <col>) <source>: <description> For wscript (interactive mode), a message box is shown. Also fix ulStartingLineNumber passed to ParseScriptText to be 0 (matching standard convention) so that line numbers in error messages are correct. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=42400 -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10398
From: Francis De Brabandere <francisdb@gmail.com> Format and print script error messages from the engine instead of ignoring them. For cscript (non-interactive mode), errors are printed to stderr in the standard format: <file>(<line>, <col>) <source>: <description> For wscript (interactive mode), a message box is shown. Also fix ulStartingLineNumber passed to ParseScriptText to be 0 (matching standard convention) so that line numbers in error messages are correct. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=42400 --- programs/wscript/main.c | 60 +++++++++++++++++++++++++++-- programs/wscript/tests/run.c | 73 ++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 3 deletions(-) diff --git a/programs/wscript/main.c b/programs/wscript/main.c index 6c8eaaa542a..2f1e517d419 100644 --- a/programs/wscript/main.c +++ b/programs/wscript/main.c @@ -120,11 +120,65 @@ static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, return S_OK; } +static void print_error(const WCHAR *string) +{ + DWORD count, ret, len, lena; + char *buf; + + if(wshInteractive) { + MessageBoxW(NULL, string, L"Windows Script Host", MB_OK); + return; + } + + len = lstrlenW(string); + ret = WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), string, len, &count, NULL); + if(ret) { + WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), L"\r\n", 2, &count, NULL); + return; + } + + lena = WideCharToMultiByte(GetOEMCP(), 0, string, len, NULL, 0, NULL, NULL); + buf = malloc(lena); + if(!buf) + return; + + WideCharToMultiByte(GetOEMCP(), 0, string, len, buf, lena, NULL, NULL); + WriteFile(GetStdHandle(STD_ERROR_HANDLE), buf, lena, &count, FALSE); + free(buf); + WriteFile(GetStdHandle(STD_ERROR_HANDLE), "\r\n", 2, &count, FALSE); +} + static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *pscripterror) { - WINE_FIXME("()\n"); - return E_NOTIMPL; + EXCEPINFO excepinfo; + ULONG line; + LONG character; + HRESULT hres; + WCHAR buf[1024]; + + WINE_TRACE("()\n"); + + memset(&excepinfo, 0, sizeof(excepinfo)); + hres = IActiveScriptError_GetExceptionInfo(pscripterror, &excepinfo); + if(SUCCEEDED(hres)) { + line = 0; + character = 0; + IActiveScriptError_GetSourcePosition(pscripterror, NULL, &line, &character); + + swprintf(buf, ARRAY_SIZE(buf), L"%s(%lu, %ld) %s: %s", + scriptFullName, line + 1, character + 1, + excepinfo.bstrSource ? excepinfo.bstrSource : L"", + excepinfo.bstrDescription ? excepinfo.bstrDescription : L""); + + print_error(buf); + + SysFreeString(excepinfo.bstrSource); + SysFreeString(excepinfo.bstrDescription); + SysFreeString(excepinfo.bstrHelpFile); + } + + return S_OK; } static HRESULT WINAPI ActiveScriptSite_OnEnterScript(IActiveScriptSite *iface) @@ -364,7 +418,7 @@ static void run_script(const WCHAR *filename, IActiveScript *script, IActiveScri return; } - hres = IActiveScriptParse_ParseScriptText(parser, text, NULL, NULL, NULL, 1, 1, + hres = IActiveScriptParse_ParseScriptText(parser, text, NULL, NULL, NULL, 1, 0, SCRIPTTEXT_HOSTMANAGESSOURCE|SCRIPTITEM_ISVISIBLE, NULL, NULL); SysFreeString(text); if(FAILED(hres)) { diff --git a/programs/wscript/tests/run.c b/programs/wscript/tests/run.c index 7bccf097f87..9aae91ddc7a 100644 --- a/programs/wscript/tests/run.c +++ b/programs/wscript/tests/run.c @@ -455,6 +455,77 @@ static BOOL register_activex(void) return TRUE; } +static void run_cscript_error_test(void) +{ + static const char script_data[] = "y = \"hello\" + 1\n"; + char file_name[] = "test_err.vbs"; + char command[MAX_PATH]; + SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, TRUE}; + STARTUPINFOA si = {sizeof(si)}; + PROCESS_INFORMATION pi; + HANDLE stderr_read, stderr_write; + char stderr_buf[4096]; + DWORD exit_code, size; + HANDLE file; + BOOL bres; + + file = CreateFileA(file_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); + ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError()); + if(file == INVALID_HANDLE_VALUE) + return; + + bres = WriteFile(file, script_data, sizeof(script_data) - 1, &size, NULL); + CloseHandle(file); + ok(bres, "Could not write to file: %lu\n", GetLastError()); + if(!bres) + goto cleanup; + + bres = CreatePipe(&stderr_read, &stderr_write, &sa, 0); + ok(bres, "CreatePipe failed: %lu\n", GetLastError()); + if(!bres) + goto cleanup; + + SetHandleInformation(stderr_read, HANDLE_FLAG_INHERIT, 0); + + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + si.hStdError = stderr_write; + + sprintf(command, "cscript.exe //nologo %s", file_name); + bres = CreateProcessA(NULL, command, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); + CloseHandle(stderr_write); + if(!bres) { + win_skip("cscript.exe is not available\n"); + CloseHandle(stderr_read); + goto cleanup; + } + + WaitForSingleObject(pi.hProcess, INFINITE); + + bres = GetExitCodeProcess(pi.hProcess, &exit_code); + ok(bres, "GetExitCodeProcess failed: %lu\n", GetLastError()); + ok(exit_code == 0, "exit_code = %lu\n", exit_code); + + memset(stderr_buf, 0, sizeof(stderr_buf)); + ReadFile(stderr_read, stderr_buf, sizeof(stderr_buf) - 1, &size, NULL); + stderr_buf[size] = 0; + + ok(size > 0, "expected error output on stderr, got nothing\n"); + ok(strstr(stderr_buf, "test_err.vbs(1,") != NULL, + "expected file and line reference in error, got: %s\n", stderr_buf); + ok(strstr(stderr_buf, "Type mismatch") != NULL, + "expected 'Type mismatch' in output, got: %s\n", stderr_buf); + + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + CloseHandle(stderr_read); + +cleanup: + DeleteFileA(file_name); +} + START_TEST(run) { char **argv; @@ -478,6 +549,8 @@ START_TEST(run) "winetest.reportSuccess();\n" "WScript.Quit(3);\n" "winetest.ok(false, 'not quit?');\n", 3); + + run_cscript_error_test(); } init_registry(FALSE); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10398
@julliard no reviewer assigned to these? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10398#note_133051
@jacek mind assigning yourself as reviewer? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10398#note_133167
This merge request was approved by Jacek Caban. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10398
participants (3)
-
Francis De Brabandere -
Francis De Brabandere (@francisdb) -
Jacek Caban (@jacek)