[WSCRIPT] Sync to Wine 11.10 (#9100)

Adds support for script time-out and proper script error reporting.
This commit is contained in:
Whindmar Saksit
2026-06-13 22:20:44 +02:00
committed by GitHub
parent 4e3729f06f
commit a4610203d1
5 changed files with 401 additions and 98 deletions
+32 -37
View File
@@ -28,14 +28,11 @@
#include "wscript.h"
#include <wine/debug.h>
#include <wine/heap.h>
WINE_DEFAULT_DEBUG_CHANNEL(wscript);
#define BUILDVERSION 16535
static const WCHAR wshNameW[] = {'W','i','n','d','o','w','s',' ','S','c','r','i','p','t',' ','H','o','s','t',0};
static const WCHAR wshVersionW[] = {'5','.','8'};
static const WCHAR wshVersionW[] = L"5.8";
VARIANT_BOOL wshInteractive =
#ifndef CSCRIPT_BUILD
@@ -44,15 +41,15 @@ VARIANT_BOOL wshInteractive =
VARIANT_FALSE;
#endif
LONG wshTimeout = 0;
static HRESULT to_string(VARIANT *src, BSTR *dst)
{
VARIANT v;
HRESULT hres;
static const WCHAR nullW[] = {'n','u','l','l',0};
if(V_VT(src) == VT_NULL) {
*dst = SysAllocString(nullW);
*dst = SysAllocString(L"null");
return *dst ? S_OK : E_OUTOFMEMORY;
}
@@ -73,28 +70,25 @@ static void print_string(const WCHAR *string)
char *buf;
if(wshInteractive) {
static const WCHAR windows_script_hostW[] =
{'W','i','n','d','o','w','s',' ','S','c','r','i','p','t',' ','H','o','s','t',0};
MessageBoxW(NULL, string, windows_script_hostW, MB_OK);
MessageBoxW(NULL, string, L"Windows Script Host", MB_OK);
return;
}
len = lstrlenW(string);
ret = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), string, len, &count, NULL);
if(ret) {
static const WCHAR crnlW[] = {'\r','\n'};
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), crnlW, ARRAY_SIZE(crnlW), &count, NULL);
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"\r\n", lstrlenW(L"\r\n"), &count, NULL);
return;
}
lena = WideCharToMultiByte(GetConsoleOutputCP(), 0, string, len, NULL, 0, NULL, NULL);
buf = heap_alloc(len);
lena = WideCharToMultiByte(GetOEMCP(), 0, string, len, NULL, 0, NULL, NULL);
buf = malloc(len);
if(!buf)
return;
WideCharToMultiByte(GetConsoleOutputCP(), 0, string, len, buf, lena, NULL, NULL);
WideCharToMultiByte(GetOEMCP(), 0, string, len, buf, lena, NULL, NULL);
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, lena, &count, FALSE);
heap_free(buf);
free(buf);
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "\r\n", 2, &count, FALSE);
}
@@ -133,7 +127,7 @@ static HRESULT WINAPI Host_GetTypeInfoCount(IHost *iface, UINT *pctinfo)
static HRESULT WINAPI Host_GetTypeInfo(IHost *iface, UINT iTInfo, LCID lcid,
ITypeInfo **ppTInfo)
{
WINE_TRACE("(%x %x %p\n", iTInfo, lcid, ppTInfo);
WINE_TRACE("(%x %lx %p\n", iTInfo, lcid, ppTInfo);
ITypeInfo_AddRef(host_ti);
*ppTInfo = host_ti;
@@ -143,7 +137,7 @@ static HRESULT WINAPI Host_GetTypeInfo(IHost *iface, UINT iTInfo, LCID lcid,
static HRESULT WINAPI Host_GetIDsOfNames(IHost *iface, REFIID riid, LPOLESTR *rgszNames,
UINT cNames, LCID lcid, DISPID *rgDispId)
{
WINE_TRACE("(%s %p %d %x %p)\n", wine_dbgstr_guid(riid), rgszNames,
WINE_TRACE("(%s %p %d %lx %p)\n", wine_dbgstr_guid(riid), rgszNames,
cNames, lcid, rgDispId);
return ITypeInfo_GetIDsOfNames(host_ti, rgszNames, cNames, rgDispId);
@@ -153,7 +147,7 @@ static HRESULT WINAPI Host_Invoke(IHost *iface, DISPID dispIdMember, REFIID riid
LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
WINE_TRACE("(%d %p %p)\n", dispIdMember, pDispParams, pVarResult);
WINE_TRACE("(%ld %p %p)\n", dispIdMember, pDispParams, pVarResult);
return ITypeInfo_Invoke(host_ti, iface, dispIdMember, wFlags, pDispParams,
pVarResult, pExcepInfo, puArgErr);
@@ -163,7 +157,7 @@ static HRESULT WINAPI Host_get_Name(IHost *iface, BSTR *out_Name)
{
WINE_TRACE("(%p)\n", out_Name);
if(!(*out_Name = SysAllocString(wshNameW)))
if(!(*out_Name = SysAllocString(L"Windows Script Host")))
return E_OUTOFMEMORY;
return S_OK;
}
@@ -279,14 +273,21 @@ static HRESULT WINAPI Host_get_BuildVersion(IHost *iface, int *out_Build)
static HRESULT WINAPI Host_get_Timeout(IHost *iface, LONG *out_Timeout)
{
WINE_FIXME("(%p)\n", out_Timeout);
return E_NOTIMPL;
TRACE("(%p)\n", out_Timeout);
*out_Timeout = wshTimeout;
return S_OK;
}
static HRESULT WINAPI Host_put_Timeout(IHost *iface, LONG v)
{
WINE_FIXME("(%d)\n", v);
return E_NOTIMPL;
TRACE("(%ld)\n", v);
if(v < 0)
return E_INVALIDARG;
wshTimeout = v;
schedule_timeout(v);
return S_OK;
}
static HRESULT WINAPI Host_CreateObject(IHost *iface, BSTR ProgID, BSTR Prefix,
@@ -321,11 +322,7 @@ static HRESULT WINAPI Host_Echo(IHost *iface, SAFEARRAY *args)
{
WCHAR *output = NULL, *ptr;
unsigned argc, i, len;
#ifdef __REACTOS__
LONG ubound, lbound;
#else
int ubound, lbound;
#endif
VARIANT *argv;
BSTR *strs;
HRESULT hres;
@@ -345,8 +342,8 @@ static HRESULT WINAPI Host_Echo(IHost *iface, SAFEARRAY *args)
return hres;
argc = ubound-lbound+1;
strs = heap_alloc_zero(argc*sizeof(*strs));
if(!strs) {
if (!(strs = calloc(argc, sizeof(*strs))))
{
SafeArrayUnaccessData(args);
return E_OUTOFMEMORY;
}
@@ -364,7 +361,7 @@ static HRESULT WINAPI Host_Echo(IHost *iface, SAFEARRAY *args)
SafeArrayUnaccessData(args);
if(SUCCEEDED(hres)) {
ptr = output = heap_alloc((len+1)*sizeof(WCHAR));
ptr = output = malloc((len+1)*sizeof(WCHAR));
if(output) {
for(i=0; i < argc; i++) {
if(i)
@@ -381,13 +378,13 @@ static HRESULT WINAPI Host_Echo(IHost *iface, SAFEARRAY *args)
for(i=0; i < argc; i++)
SysFreeString(strs[i]);
heap_free(strs);
free(strs);
if(FAILED(hres))
return hres;
print_string(output);
heap_free(output);
free(output);
return S_OK;
}
@@ -409,14 +406,12 @@ static HRESULT WINAPI Host_Sleep(IHost *iface, LONG Time)
{
#ifdef __REACTOS__
UNREFERENCED_PARAMETER(iface);
#endif
TRACE("(%ld)\n", Time);
if (Time < 0)
return E_INVALIDARG;
Sleep(Time);
return S_OK;
#else
WINE_FIXME("(%d)\n", Time);
return E_NOTIMPL;
#endif
}
static HRESULT WINAPI Host_ConnectObject(IHost *iface, IDispatch *Object, BSTR Prefix)
+341 -58
View File
@@ -32,6 +32,7 @@
#include <initguid.h>
#include "wscript.h"
#include "resource.h"
#include <wine/debug.h>
@@ -50,14 +51,13 @@
#endif
WINE_DEFAULT_DEBUG_CHANNEL(wscript);
static const WCHAR wscriptW[] = {'W','S','c','r','i','p','t',0};
static const WCHAR wshW[] = {'W','S','H',0};
WCHAR scriptFullName[MAX_PATH];
ITypeInfo *host_ti;
ITypeInfo *arguments_ti;
static BOOL nologo;
static HRESULT query_interface(REFIID,void**);
#ifdef __REACTOS__
@@ -224,7 +224,7 @@ static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *p
static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface,
LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown **ppunkItem, ITypeInfo **ppti)
{
WINE_TRACE("(%s %x %p %p)\n", wine_dbgstr_w(pstrName), dwReturnMask, ppunkItem, ppti);
WINE_TRACE("(%s %lx %p %p)\n", wine_dbgstr_w(pstrName), dwReturnMask, ppunkItem, ppti);
#ifdef __REACTOS__
{
@@ -235,7 +235,7 @@ static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface,
}
#endif
if(lstrcmpW(pstrName, wshW) && lstrcmpW(pstrName, wscriptW))
if(lstrcmpW(pstrName, L"WSH") && lstrcmpW(pstrName, L"WScript"))
return E_FAIL;
if(dwReturnMask & SCRIPTINFO_ITYPEINFO) {
@@ -272,11 +272,214 @@ static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface,
return S_OK;
}
static void write_to_handle(HANDLE handle, const WCHAR *string)
{
DWORD count, ret, len, lena;
char *buf;
len = lstrlenW(string);
ret = WriteConsoleW(handle, string, len, &count, NULL);
if(ret) {
WriteConsoleW(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(handle, buf, lena, &count, FALSE);
free(buf);
WriteFile(handle, "\r\n", 2, &count, FALSE);
}
static void print_error(const WCHAR *string)
{
if(wshInteractive) {
MessageBoxW(NULL, string, L"Windows Script Host", MB_OK);
return;
}
write_to_handle(GetStdHandle(STD_ERROR_HANDLE), string);
}
static void print_string(const WCHAR *string)
{
write_to_handle(GetStdHandle(STD_OUTPUT_HANDLE), string);
}
static void output_writeconsole(const WCHAR *str, DWORD wlen)
{
DWORD count;
if(!WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), str, wlen, &count, NULL)) {
DWORD len;
char *buf;
/* On Windows WriteConsoleW() fails if the output is redirected. So fall
* back to WriteFile() with OEM code page. */
len = WideCharToMultiByte(GetOEMCP(), 0, str, wlen, NULL, 0, NULL, NULL);
buf = malloc(len);
WideCharToMultiByte(GetOEMCP(), 0, str, wlen, buf, len, NULL, NULL);
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, len, &count, FALSE);
free(buf);
}
}
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 == 0 && GetLastError() != ERROR_NO_WORK_DONE) {
WINE_FIXME("Could not format string: le=%lu, fmt=%s\n", GetLastError(), wine_dbgstr_w(fmt));
return;
}
if(wshInteractive) {
MessageBoxW(NULL, str, L"Windows Script Host", MB_OK);
}else {
output_writeconsole(str, len);
}
LocalFree(str);
}
static void WINAPIV print_resource(unsigned int id, ...)
{
WCHAR *fmt = NULL;
int len;
va_list va_args;
#ifdef __REACTOS__
#ifndef CSCRIPT_BUILD
#define APPNAME L"WScript"
#else
#define APPNAME L"CScript"
#endif
const WCHAR *str = NULL;
switch (id)
{
case IDS_USAGE: str = L"Usage: " APPNAME L" scriptname.extension [option...] [arguments...]\n"; break;
case IDS_NO_SCRIPT_FILE: str = L"Input Error: There is no script file specified.\n"; break;
case IDS_FILE_NOT_FOUND: str = L"Input Error: Can not find script file ""%1"".\n"; break;
case IDS_SCRIPT_LOAD_ERROR: str = APPNAME L" Error: Loading script ""%1"" failed (%2).\n"; break;
case IDS_TIMEOUT_EXCEEDED: str = L"Script execution time was exceeded on script ""%1"".\n\nScript execution was terminated.\n"; break;
}
if(!str)
{
WINE_FIXME("Missing string %u\n", id);
return;
}
len = lstrlenW(str);
fmt = malloc(++len * sizeof(WCHAR));
if(!fmt)
return;
lstrcpyW(fmt, str);
#else
if(!(len = LoadStringW(GetModuleHandleW(NULL), id, (WCHAR *)&fmt, 0))) {
WINE_FIXME("LoadString failed with %ld\n", GetLastError());
return;
}
len++;
fmt = malloc(len * sizeof(WCHAR));
if(!fmt)
return;
LoadStringW(GetModuleHandleW(NULL), id, fmt, len);
#endif
va_start(va_args, id);
output_formatstring(fmt, va_args);
va_end(va_args);
free(fmt);
}
static HANDLE timeout_cancel_event;
static HANDLE timeout_thread;
static DWORD WINAPI timeout_thread_proc(void *arg)
{
DWORD ms = (DWORD)(DWORD_PTR)arg;
if(WaitForSingleObject(timeout_cancel_event, ms) == WAIT_TIMEOUT) {
print_resource(IDS_TIMEOUT_EXCEEDED, scriptFullName);
ExitProcess(1);
}
return 0;
}
void schedule_timeout(LONG seconds)
{
if(timeout_thread) {
SetEvent(timeout_cancel_event);
WaitForSingleObject(timeout_thread, INFINITE);
CloseHandle(timeout_thread);
timeout_thread = NULL;
}
if(seconds <= 0)
return;
if(!timeout_cancel_event)
timeout_cancel_event = CreateEventW(NULL, TRUE, FALSE, NULL);
else
ResetEvent(timeout_cancel_event);
timeout_thread = CreateThread(NULL, 0, timeout_thread_proc,
(void *)(DWORD_PTR)(seconds * 1000), 0, NULL);
}
static void print_banner(void)
{
#ifdef __REACTOS__
const WCHAR *header = L"ReactOS Script Host";
#else
const char * (CDECL *wine_get_version)(void);
WCHAR header[64];
wine_get_version = (void *)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "wine_get_version");
if(wine_get_version)
swprintf(header, ARRAY_SIZE(header), L"Wine %S Script Host", wine_get_version());
else
swprintf(header, ARRAY_SIZE(header), L"Wine Script Host");
#endif
print_string(header);
print_string(L"");
}
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)
@@ -372,9 +575,7 @@ static BOOL load_typelib(void)
ITypeLib *typelib;
HRESULT hres;
static const WCHAR wscript_exeW[] = {'w','s','c','r','i','p','t','.','e','x','e',0};
hres = LoadTypeLib(wscript_exeW, &typelib);
hres = LoadTypeLib(L"wscript.exe", &typelib);
if(FAILED(hres))
return FALSE;
@@ -394,9 +595,6 @@ static BOOL get_engine_clsid(const WCHAR *ext, CLSID *clsid)
HKEY hkey;
HRESULT hres;
static const WCHAR script_engineW[] =
{'\\','S','c','r','i','p','t','E','n','g','i','n','e',0};
res = RegOpenKeyW(HKEY_CLASSES_ROOT, ext, &hkey);
if(res != ERROR_SUCCESS)
return FALSE;
@@ -409,7 +607,7 @@ static BOOL get_engine_clsid(const WCHAR *ext, CLSID *clsid)
WINE_TRACE("fileid is %s\n", wine_dbgstr_w(fileid));
lstrcatW(fileid, script_engineW);
lstrcatW(fileid, L"\\ScriptEngine");
res = RegOpenKeyW(HKEY_CLASSES_ROOT, fileid, &hkey);
if(res != ERROR_SUCCESS)
return FALSE;
@@ -468,11 +666,11 @@ static BOOL init_engine(IActiveScript *script, IActiveScriptParse *parser)
if(FAILED(hres))
return FALSE;
hres = IActiveScript_AddNamedItem(script, wscriptW, SCRIPTITEM_ISVISIBLE);
hres = IActiveScript_AddNamedItem(script, L"WScript", SCRIPTITEM_ISVISIBLE);
if(FAILED(hres))
return FALSE;
hres = IActiveScript_AddNamedItem(script, wshW, SCRIPTITEM_ISVISIBLE);
hres = IActiveScript_AddNamedItem(script, L"WSH", SCRIPTITEM_ISVISIBLE);
if(FAILED(hres))
return FALSE;
@@ -492,6 +690,11 @@ static BSTR get_script_str(const WCHAR *filename)
return NULL;
size = GetFileSize(file, NULL);
if(!size) {
CloseHandle(file);
return SysAllocStringLen(NULL, 0);
}
map = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL);
CloseHandle(file);
if(map == INVALID_HANDLE_VALUE)
@@ -521,28 +724,25 @@ static BSTR get_script_str(const WCHAR *filename)
return ret;
}
static void run_script(const WCHAR *filename, IActiveScript *script, IActiveScriptParse *parser)
static BOOL run_script(BSTR text, IActiveScript *script, IActiveScriptParse *parser)
{
BSTR text;
HRESULT hres;
text = get_script_str(filename);
if(!text) {
WINE_FIXME("Could not get script text\n");
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)) {
WINE_FIXME("ParseScriptText failed: %08x\n", hres);
return;
if(hres != SCRIPT_E_REPORTED)
WINE_WARN("ParseScriptText failed: %08lx\n", hres);
return FALSE;
}
hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_STARTED);
if(FAILED(hres))
WINE_FIXME("SetScriptState failed: %08x\n", hres);
if(FAILED(hres)) {
if(hres != SCRIPT_E_REPORTED)
WINE_WARN("SetScriptState failed: %08lx\n", hres);
}
return TRUE;
}
#ifdef __REACTOS__
@@ -772,10 +972,6 @@ static HRESULT run_wsf(LPCWSTR xmlpath)
static BOOL set_host_properties(const WCHAR *prop)
{
static const WCHAR nologoW[] = {'n','o','l','o','g','o',0};
static const WCHAR iactive[] = {'i',0};
static const WCHAR batch[] = {'b',0};
if(*prop == '/') {
++prop;
if(*prop == '/')
@@ -784,21 +980,41 @@ static BOOL set_host_properties(const WCHAR *prop)
else
++prop;
if(wcsicmp(prop, iactive) == 0)
if(wcsicmp(prop, L"i") == 0)
wshInteractive = VARIANT_TRUE;
else if(wcsicmp(prop, batch) == 0)
else if(wcsicmp(prop, L"b") == 0)
wshInteractive = VARIANT_FALSE;
else if(wcsicmp(prop, nologoW) == 0)
WINE_FIXME("ignored %s switch\n", debugstr_w(nologoW));
else if(wcsicmp(prop, L"nologo") == 0)
nologo = TRUE;
else if(wcsicmp(prop, L"logo") == 0)
nologo = FALSE;
else if(wcsicmp(prop, L"d") == 0)
WINE_FIXME("ignoring //d\n");
else if(wcsicmp(prop, L"x") == 0)
WINE_FIXME("ignoring //x\n");
else if(wcsicmp(prop, L"u") == 0)
WINE_FIXME("ignoring //u\n");
else if(wcsicmp(prop, L"s") == 0)
WINE_FIXME("ignoring //s\n");
else if(wcsnicmp(prop, L"e:", 2) == 0)
#ifdef __REACTOS__
else if((prop[0] | 32) == 'e' && prop[1] == ':')
g_force_engine = &prop[2];
#else
WINE_FIXME("ignoring //e:\n");
#endif
else
{
WINE_FIXME("unsupported switch %s\n", debugstr_w(prop));
return FALSE;
else if(wcsnicmp(prop, L"h:", 2) == 0)
WINE_FIXME("ignoring //h:\n");
else if(wcsnicmp(prop, L"job:", 4) == 0)
WINE_FIXME("ignoring //job:\n");
else if(wcsnicmp(prop, L"t:", 2) == 0) {
WCHAR *end;
LONG t = wcstol(prop + 2, &end, 10);
if(end == prop + 2 || *end || t < 0)
return FALSE;
wshTimeout = t;
}
else
return FALSE;
return TRUE;
}
@@ -807,9 +1023,11 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR cmdline, int cm
WCHAR *ext, *filepart, *filename = NULL;
IActiveScriptParse *parser;
IActiveScript *script;
BSTR script_text;
WCHAR **argv;
CLSID clsid;
int argc, i;
int ret = 0;
DWORD res;
WINE_TRACE("(%p %p %s %x)\n", hInst, hPrevInst, wine_dbgstr_w(cmdline), cmdshow);
@@ -818,32 +1036,93 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR cmdline, int cm
if(!argv)
return 1;
/* Pass 1: consume // host options from all positions. */
for(i=1; i<argc; i++) {
if(*argv[i] == '/' || *argv[i] == '-') {
if(!set_host_properties(argv[i]))
return 1;
}else {
filename = argv[i];
argums = argv+i+1;
numOfArgs = argc-i-1;
break;
}
if(argv[i][0] == '/' && argv[i][1] == '/' && set_host_properties(argv[i]))
argv[i] = NULL;
}
/* Pass 2: find filename, consuming single-/ and - options before it. */
for(i=1; i<argc; i++) {
if(!argv[i])
continue;
if(argv[i][0] == '-' && argv[i][1] == '-' && !argv[i][2])
continue; /* -- separator */
if((*argv[i] == '/' || *argv[i] == '-') && set_host_properties(argv[i]))
continue;
filename = argv[i];
i++;
break;
}
/* Pass 3: compact script args, skipping consumed // options. */
if(filename) {
int j = 0, first_arg = i;
for(; i<argc; i++) {
if(!argv[i])
continue;
argv[first_arg + j] = argv[i];
j++;
}
argums = argv + first_arg;
numOfArgs = j;
}
if(!filename && argc == 1) {
if(wshInteractive) {
WINE_FIXME("Settings dialog not implemented\n");
return 0;
}
if(!nologo)
print_banner();
print_resource(IDS_USAGE);
return 0;
}
if(!nologo)
print_banner();
if(!filename) {
WINE_FIXME("No file name specified\n");
print_resource(IDS_NO_SCRIPT_FILE);
return 1;
}
res = GetFullPathNameW(filename, ARRAY_SIZE(scriptFullName), scriptFullName, &filepart);
if(!res || res > ARRAY_SIZE(scriptFullName))
return 1;
ext = wcsrchr(filepart, '.');
#ifdef __REACTOS__
if (ext && !lstrcmpiW(ext, L".wsf")) {
ext = wcsrchr(filepart, '.');
if(ext && !lstrcmpiW(ext, L".wsf")) {
return run_wsf(scriptFullName);
}
#endif
script_text = get_script_str(scriptFullName);
if(!script_text) {
DWORD err = GetLastError();
if(err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) {
print_resource(IDS_FILE_NOT_FOUND, scriptFullName);
}else {
WCHAR *syserr = NULL;
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (WCHAR *)&syserr, 0, NULL);
if(syserr) {
/* Trim trailing whitespace from system error message. */
int len = lstrlenW(syserr);
while(len > 0 && (syserr[len - 1] == '\r' || syserr[len - 1] == '\n' || syserr[len - 1] == ' '))
syserr[--len] = 0;
print_resource(IDS_SCRIPT_LOAD_ERROR, scriptFullName, syserr);
LocalFree(syserr);
}else {
print_resource(IDS_SCRIPT_LOAD_ERROR, scriptFullName, L"");
}
}
return 1;
}
ext = wcsrchr(filepart, '.');
#ifdef __REACTOS__
if(g_force_engine) {
CLSIDFromProgID(g_force_engine, &clsid);
}
@@ -863,13 +1142,17 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR cmdline, int cm
}
if(init_engine(script, parser)) {
run_script(filename, script, parser);
schedule_timeout(wshTimeout);
if(!run_script(script_text, script, parser))
ret = 1;
schedule_timeout(0);
IActiveScript_Close(script);
ITypeInfo_Release(host_ti);
}else {
WINE_FIXME("Script initialization failed\n");
}
SysFreeString(script_text);
IActiveScript_Release(script);
IActiveScriptParse_Release(parser);
@@ -879,5 +1162,5 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR cmdline, int cm
CoUninitialize();
return 0;
return ret;
}
@@ -0,0 +1,23 @@
/*
* Copyright 2025 Francis De Brabandere
*
* 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
*/
#define IDS_USAGE 1
#define IDS_NO_SCRIPT_FILE 2
#define IDS_FILE_NOT_FOUND 3
#define IDS_SCRIPT_LOAD_ERROR 4
#define IDS_TIMEOUT_EXCEEDED 5
+4 -2
View File
@@ -16,8 +16,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#pragma once
#include "ihost.h"
extern IHost host_obj;
@@ -35,3 +33,7 @@ extern WCHAR **argums;
extern int numOfArgs;
extern VARIANT_BOOL wshInteractive;
extern LONG wshTimeout;
void schedule_timeout(LONG seconds);
+1 -1
View File
@@ -255,7 +255,7 @@ base/applications/cmdutils/reg # Synced to WineStaging-6.23
base/applications/cmdutils/schtasks # Synced to WineStaging-3.3
base/applications/cmdutils/taskkill # Synced to WineStaging-3.17
base/applications/cmdutils/wmic # Synced to WineStaging-4.0
base/applications/cmdutils/wscript # Synced to WineStaging-4.18
base/applications/cmdutils/wscript # Synced to Wine-11.10
base/applications/cmdutils/xcopy # Synced to WineStaging-3.17
base/applications/games/winmine # Synced to WineStaging-2.16 with our own resources.
base/applications/extrac32 # Synced to WineStaging-4.0