[VBSCRIPT] Sync with Wine 3.0. CORE-14225

This commit is contained in:
Amine Khaldi 2018-01-20 13:39:40 +01:00
parent eb91a73902
commit e0b80a0929
11 changed files with 978 additions and 699 deletions

View file

@ -10,6 +10,7 @@ list(APPEND SOURCE
lex.c
parser.tab.c
regexp.c
utils.c
vbdisp.c
vbregexp.c
vbscript.c

View file

@ -815,8 +815,40 @@ static HRESULT Global_LBound(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VA
static HRESULT Global_UBound(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
{
FIXME("\n");
return E_NOTIMPL;
SAFEARRAY *sa;
HRESULT hres;
LONG ubound;
int dim;
assert(args_cnt == 1 || args_cnt == 2);
TRACE("%s %s\n", debugstr_variant(arg), args_cnt == 2 ? debugstr_variant(arg + 1) : "1");
switch(V_VT(arg)) {
case VT_VARIANT|VT_ARRAY:
sa = V_ARRAY(arg);
break;
case VT_VARIANT|VT_ARRAY|VT_BYREF:
sa = *V_ARRAYREF(arg);
break;
default:
FIXME("arg %s not supported\n", debugstr_variant(arg));
return E_NOTIMPL;
}
if(args_cnt == 2) {
hres = to_int(arg + 1, &dim);
if(FAILED(hres))
return hres;
}else {
dim = 1;
}
hres = SafeArrayGetUBound(sa, dim, &ubound);
if(FAILED(hres))
return hres;
return return_int(res, ubound);
}
static HRESULT Global_RGB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
@ -1785,8 +1817,44 @@ static HRESULT Global_TypeName(vbdisp_t *This, VARIANT *arg, unsigned args_cnt,
static HRESULT Global_Array(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
{
FIXME("\n");
return E_NOTIMPL;
SAFEARRAYBOUND bounds;
SAFEARRAY *sa;
VARIANT *data;
HRESULT hres;
unsigned i;
TRACE("arg_cnt=%u\n", args_cnt);
bounds.lLbound = 0;
bounds.cElements = args_cnt;
sa = SafeArrayCreate(VT_VARIANT, 1, &bounds);
if(!sa)
return E_OUTOFMEMORY;
hres = SafeArrayAccessData(sa, (void**)&data);
if(FAILED(hres)) {
SafeArrayDestroy(sa);
return hres;
}
for(i=0; i<args_cnt; i++) {
hres = VariantCopyInd(data+i, arg+i);
if(FAILED(hres)) {
SafeArrayUnaccessData(sa);
SafeArrayDestroy(sa);
return hres;
}
}
SafeArrayUnaccessData(sa);
if(res) {
V_VT(res) = VT_ARRAY|VT_VARIANT;
V_ARRAY(res) = sa;
}else {
SafeArrayDestroy(sa);
}
return S_OK;
}
static HRESULT Global_Erase(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
@ -2213,7 +2281,7 @@ static const builtin_prop_t global_props[] = {
{DISPID_GLOBAL_RND, Global_Rnd, 0, 1},
{DISPID_GLOBAL_TIMER, Global_Timer, 0, 0},
{DISPID_GLOBAL_LBOUND, Global_LBound, 0, 1},
{DISPID_GLOBAL_UBOUND, Global_UBound, 0, 1},
{DISPID_GLOBAL_UBOUND, Global_UBound, 0, 1, 2},
{DISPID_GLOBAL_RGB, Global_RGB, 0, 3},
{DISPID_GLOBAL_LEN, Global_Len, 0, 1},
{DISPID_GLOBAL_LENB, Global_LenB, 0, 1},
@ -2265,7 +2333,7 @@ static const builtin_prop_t global_props[] = {
{DISPID_GLOBAL_DATEDIFF, Global_DateDiff, 0, 3, 5},
{DISPID_GLOBAL_DATEPART, Global_DatePart, 0, 2, 4},
{DISPID_GLOBAL_TYPENAME, Global_TypeName, 0, 1},
{DISPID_GLOBAL_ARRAY, Global_Array, 0, 1},
{DISPID_GLOBAL_ARRAY, Global_Array, 0, 0, MAXDWORD},
{DISPID_GLOBAL_ERASE, Global_Erase, 0, 1},
{DISPID_GLOBAL_FILTER, Global_Filter, 0, 2, 4},
{DISPID_GLOBAL_JOIN, Global_Join, 0, 1, 2},

View file

@ -475,10 +475,8 @@ static void vbstack_to_dp(exec_ctx_t *ctx, unsigned arg_cnt, BOOL is_propput, DI
static HRESULT array_access(exec_ctx_t *ctx, SAFEARRAY *array, DISPPARAMS *dp, VARIANT **ret)
{
unsigned cell_off = 0, dim_size = 1, i;
unsigned argc = arg_cnt(dp);
VARIANT *data;
LONG idx;
unsigned i, argc = arg_cnt(dp);
LONG *indices;
HRESULT hres;
if(!array) {
@ -486,34 +484,35 @@ static HRESULT array_access(exec_ctx_t *ctx, SAFEARRAY *array, DISPPARAMS *dp, V
return E_FAIL;
}
if(array->cDims != argc) {
FIXME("argc %d does not match cDims %d\n", dp->cArgs, array->cDims);
return E_FAIL;
}
for(i=0; i < argc; i++) {
hres = to_int(get_arg(dp, i), &idx);
if(FAILED(hres))
return hres;
idx -= array->rgsabound[i].lLbound;
if(idx >= array->rgsabound[i].cElements) {
FIXME("out of bound element %d in dim %d of size %d\n", idx, i+1, array->rgsabound[i].cElements);
return E_FAIL;
}
cell_off += idx*dim_size;
dim_size *= array->rgsabound[i].cElements;
}
hres = SafeArrayAccessData(array, (void**)&data);
hres = SafeArrayLock(array);
if(FAILED(hres))
return hres;
*ret = data+cell_off;
if(array->cDims != argc) {
FIXME("argc %d does not match cDims %d\n", dp->cArgs, array->cDims);
SafeArrayUnlock(array);
return E_FAIL;
}
SafeArrayUnaccessData(array);
return S_OK;
indices = heap_alloc(sizeof(*indices) * argc);
if(!indices) {
SafeArrayUnlock(array);
return E_OUTOFMEMORY;
}
for(i=0; i<argc; i++) {
hres = to_int(get_arg(dp, i), indices+i);
if(FAILED(hres)) {
heap_free(indices);
SafeArrayUnlock(array);
return hres;
}
}
hres = SafeArrayPtrOfIndex(array, indices, (void**)ret);
SafeArrayUnlock(array);
heap_free(indices);
return hres;
}
static HRESULT do_icall(exec_ctx_t *ctx, VARIANT *res)
@ -1143,6 +1142,18 @@ static HRESULT interp_newenum(exec_ctx_t *ctx)
V_UNKNOWN(r) = (IUnknown*)iter;
break;
}
case VT_VARIANT|VT_ARRAY:
case VT_VARIANT|VT_ARRAY|VT_BYREF: {
IEnumVARIANT *iter;
hres = create_safearray_iter(V_ISBYREF(v.v) ? *V_ARRAYREF(v.v) : V_ARRAY(v.v), &iter);
if(FAILED(hres))
return hres;
V_VT(r) = VT_UNKNOWN;
V_UNKNOWN(r) = (IUnknown*)iter;
break;
}
default:
FIXME("Unsupported for %s\n", debugstr_variant(v.v));
release_val(&v);
@ -1186,7 +1197,7 @@ static HRESULT interp_enumnext(exec_ctx_t *ctx)
if(do_continue) {
ctx->instr++;
}else {
stack_pop(ctx);
stack_popn(ctx, 1);
instr_jmp(ctx, loop_end);
}
return S_OK;

File diff suppressed because it is too large Load diff

View file

@ -30,8 +30,8 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
#ifndef YY_PARSER_E_REACTOS_SYNC_GCC_DLL_WIN32_VBSCRIPT_PARSER_TAB_H_INCLUDED
# define YY_PARSER_E_REACTOS_SYNC_GCC_DLL_WIN32_VBSCRIPT_PARSER_TAB_H_INCLUDED
#ifndef YY_PARSER_E_REACTOSSYNC3_0_GCC_DLL_WIN32_VBSCRIPT_PARSER_TAB_H_INCLUDED
# define YY_PARSER_E_REACTOSSYNC3_0_GCC_DLL_WIN32_VBSCRIPT_PARSER_TAB_H_INCLUDED
/* Debug traces. */
#ifndef YYDEBUG
# define YYDEBUG 0
@ -121,7 +121,7 @@ extern int parser_debug;
typedef union YYSTYPE YYSTYPE;
union YYSTYPE
{
#line 88 "parser.y" /* yacc.c:1909 */
#line 83 "parser.y" /* yacc.c:1909 */
const WCHAR *string;
statement_t *statement;
@ -150,4 +150,4 @@ union YYSTYPE
int parser_parse (parser_ctx_t *ctx);
#endif /* !YY_PARSER_E_REACTOS_SYNC_GCC_DLL_WIN32_VBSCRIPT_PARSER_TAB_H_INCLUDED */
#endif /* !YY_PARSER_E_REACTOSSYNC3_0_GCC_DLL_WIN32_VBSCRIPT_PARSER_TAB_H_INCLUDED */

View file

@ -19,11 +19,6 @@
%{
#include "vbscript.h"
#include "parse.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
static int parser_error(parser_ctx_t *,const char*);
@ -148,7 +143,7 @@ Program
OptionExplicit_opt
: /* empty */ { $$ = FALSE; }
| tOPTION tEXPLICIT tNL { $$ = TRUE; }
| tOPTION tEXPLICIT StSep { $$ = TRUE; }
SourceElements
: /* empty */
@ -164,7 +159,7 @@ StatementsNl
| StatementNl StatementsNl { $$ = link_statements($1, $2); }
StatementNl
: Statement tNL { $$ = $1; }
: Statement tNL { $$ = $1; }
Statement
: ':' { $$ = NULL; }
@ -396,29 +391,29 @@ PrimaryExpression
| tME { $$ = new_expression(ctx, EXPR_ME, 0); CHECK_ERROR; }
ClassDeclaration
: tCLASS Identifier tNL ClassBody tEND tCLASS tNL { $4->name = $2; $$ = $4; }
: tCLASS Identifier StSep ClassBody tEND tCLASS StSep { $4->name = $2; $$ = $4; }
ClassBody
: /* empty */ { $$ = new_class_decl(ctx); }
| FunctionDecl tNL ClassBody { $$ = add_class_function(ctx, $3, $1); CHECK_ERROR; }
: /* empty */ { $$ = new_class_decl(ctx); }
| FunctionDecl StSep ClassBody { $$ = add_class_function(ctx, $3, $1); CHECK_ERROR; }
/* FIXME: We should use DimDecl here to support arrays, but that conflicts with PropertyDecl. */
| Storage tIdentifier tNL ClassBody { dim_decl_t *dim_decl = new_dim_decl(ctx, $2, FALSE, NULL); CHECK_ERROR;
| Storage tIdentifier StSep ClassBody { dim_decl_t *dim_decl = new_dim_decl(ctx, $2, FALSE, NULL); CHECK_ERROR;
$$ = add_dim_prop(ctx, $4, dim_decl, $1); CHECK_ERROR; }
| tDIM DimDecl tNL ClassBody { $$ = add_dim_prop(ctx, $4, $2, 0); CHECK_ERROR; }
| PropertyDecl tNL ClassBody { $$ = add_class_function(ctx, $3, $1); CHECK_ERROR; }
| tDIM DimDecl StSep ClassBody { $$ = add_dim_prop(ctx, $4, $2, 0); CHECK_ERROR; }
| PropertyDecl StSep ClassBody { $$ = add_class_function(ctx, $3, $1); CHECK_ERROR; }
PropertyDecl
: Storage_opt tPROPERTY tGET tIdentifier ArgumentsDecl_opt tNL StatementsNl_opt tEND tPROPERTY
: Storage_opt tPROPERTY tGET tIdentifier ArgumentsDecl_opt StSep StatementsNl_opt tEND tPROPERTY
{ $$ = new_function_decl(ctx, $4, FUNC_PROPGET, $1, $5, $7); CHECK_ERROR; }
| Storage_opt tPROPERTY tLET tIdentifier '(' ArgumentDecl ')' tNL StatementsNl_opt tEND tPROPERTY
| Storage_opt tPROPERTY tLET tIdentifier '(' ArgumentDecl ')' StSep StatementsNl_opt tEND tPROPERTY
{ $$ = new_function_decl(ctx, $4, FUNC_PROPLET, $1, $6, $9); CHECK_ERROR; }
| Storage_opt tPROPERTY tSET tIdentifier '(' ArgumentDecl ')' tNL StatementsNl_opt tEND tPROPERTY
| Storage_opt tPROPERTY tSET tIdentifier '(' ArgumentDecl ')' StSep StatementsNl_opt tEND tPROPERTY
{ $$ = new_function_decl(ctx, $4, FUNC_PROPSET, $1, $6, $9); CHECK_ERROR; }
FunctionDecl
: Storage_opt tSUB Identifier ArgumentsDecl_opt tNL StatementsNl_opt tEND tSUB
: Storage_opt tSUB Identifier ArgumentsDecl_opt StSep StatementsNl_opt tEND tSUB
{ $$ = new_function_decl(ctx, $3, FUNC_SUB, $1, $4, $6); CHECK_ERROR; }
| Storage_opt tFUNCTION Identifier ArgumentsDecl_opt tNL StatementsNl_opt tEND tFUNCTION
| Storage_opt tFUNCTION Identifier ArgumentsDecl_opt StSep StatementsNl_opt tEND tFUNCTION
{ $$ = new_function_decl(ctx, $3, FUNC_FUNCTION, $1, $4, $6); CHECK_ERROR; }
Storage_opt
@ -448,10 +443,12 @@ Identifier
: tIdentifier { $$ = $1; }
| tPROPERTY { $$ = propertyW; }
/* Some statements accept both new line and ':' as a separator */
/* Most statements accept both new line and ':' as separators */
StSep
: tNL
| ':'
| tNL StSep
| ':' StSep
%%

189
dll/win32/vbscript/utils.c Normal file
View file

@ -0,0 +1,189 @@
/*
* Copyright 2017 Piotr Caban for CodeWeavers
*
* 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 "vbscript.h"
typedef struct {
IEnumVARIANT IEnumVARIANT_iface;
LONG ref;
SAFEARRAY *sa;
ULONG i, size;
} safearray_iter;
static inline safearray_iter *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
{
return CONTAINING_RECORD(iface, safearray_iter, IEnumVARIANT_iface);
}
static HRESULT WINAPI safearray_iter_IEnumVARIANT_QueryInterface(
IEnumVARIANT *iface, REFIID riid, void **ppv)
{
safearray_iter *This = impl_from_IEnumVARIANT(iface);
if(IsEqualGUID(riid, &IID_IUnknown)) {
TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
*ppv = &This->IEnumVARIANT_iface;
}else if(IsEqualGUID(riid, &IID_IEnumVARIANT)) {
TRACE("(%p)->(IID_IEnumVARIANT %p)\n", This, ppv);
*ppv = &This->IEnumVARIANT_iface;
}else {
FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
*ppv = NULL;
return E_NOINTERFACE;
}
IUnknown_AddRef((IUnknown*)*ppv);
return S_OK;
}
static ULONG WINAPI safearray_iter_IEnumVARIANT_AddRef(IEnumVARIANT *iface)
{
safearray_iter *This = impl_from_IEnumVARIANT(iface);
LONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
return ref;
}
static ULONG WINAPI safearray_iter_IEnumVARIANT_Release(IEnumVARIANT *iface)
{
safearray_iter *This = impl_from_IEnumVARIANT(iface);
LONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%d\n", iface, ref);
if(!ref) {
if(This->sa)
SafeArrayUnlock(This->sa);
heap_free(This);
}
return ref;
}
static HRESULT WINAPI safearray_iter_IEnumVARIANT_Next(IEnumVARIANT *iface,
ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
{
safearray_iter *This = impl_from_IEnumVARIANT(iface);
HRESULT hres;
VARIANT *v;
TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched);
if(celt != 1) {
FIXME("celt != 1\n");
return E_NOTIMPL;
}
if(This->i >= This->size) {
if(pCeltFetched)
*pCeltFetched = 0;
return S_FALSE;
}
if(!This->sa->cLocks)
ERR("SAFEARRAY not locked\n");
v = (VARIANT*)(((BYTE*)This->sa->pvData) + This->i * This->sa->cbElements);
V_VT(rgVar) = VT_EMPTY;
hres = VariantCopy(rgVar, v);
if(FAILED(hres))
return hres;
This->i++;
if(pCeltFetched)
*pCeltFetched = 1;
return S_OK;
}
static HRESULT WINAPI safearray_iter_IEnumVARIANT_Skip(IEnumVARIANT *iface, ULONG celt)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI safearray_iter_IEnumVARIANT_Reset(IEnumVARIANT *iface)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI safearray_iter_IEnumVARIANT_Clone(
IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
{
FIXME("\n");
return E_NOTIMPL;
}
static const IEnumVARIANTVtbl safearray_iter_EnumVARIANTVtbl = {
safearray_iter_IEnumVARIANT_QueryInterface,
safearray_iter_IEnumVARIANT_AddRef,
safearray_iter_IEnumVARIANT_Release,
safearray_iter_IEnumVARIANT_Next,
safearray_iter_IEnumVARIANT_Skip,
safearray_iter_IEnumVARIANT_Reset,
safearray_iter_IEnumVARIANT_Clone
};
static ULONG get_safearray_size(SAFEARRAY *sa)
{
ULONG ret = 1;
USHORT i;
if(!sa)
return 0;
for(i=0; i<sa->cDims && ret; i++)
ret *= sa->rgsabound[i].cElements;
return ret;
}
HRESULT create_safearray_iter(SAFEARRAY *sa, IEnumVARIANT **ev)
{
safearray_iter *iter;
HRESULT hres;
if(sa && !(sa->fFeatures & FADF_VARIANT)) {
FIXME("enumeration not supported: %x\n", sa->fFeatures);
return E_NOTIMPL;
}
iter = heap_alloc(sizeof(*iter));
if(!iter)
return E_OUTOFMEMORY;
if(sa) {
hres = SafeArrayLock(sa);
if(FAILED(hres)) {
heap_free(iter);
return hres;
}
}
iter->IEnumVARIANT_iface.lpVtbl = &safearray_iter_EnumVARIANTVtbl;
iter->ref = 1;
iter->sa = sa;
iter->i = 0;
iter->size = get_safearray_size(sa);
*ev = &iter->IEnumVARIANT_iface;
return S_OK;
}

View file

@ -549,7 +549,7 @@ static IDispatchExVtbl DispatchExVtbl = {
static inline vbdisp_t *unsafe_impl_from_IDispatch(IDispatch *iface)
{
return iface->lpVtbl == (IDispatchVtbl*)&DispatchExVtbl
? CONTAINING_RECORD((IDispatchEx *)iface, vbdisp_t, IDispatchEx_iface)
? CONTAINING_RECORD(iface, vbdisp_t, IDispatchEx_iface)
: NULL;
}

View file

@ -345,6 +345,9 @@ static HRESULT WINAPI VBScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE
case SCRIPTSTATE_INITIALIZED:
FIXME("unimplemented SCRIPTSTATE_INITIALIZED\n");
return S_OK;
case SCRIPTSTATE_DISCONNECTED:
FIXME("unimplemented SCRIPTSTATE_DISCONNECTED\n");
return S_OK;
default:
FIXME("unimplemented state %d\n", ss);
return E_NOTIMPL;

View file

@ -402,6 +402,8 @@ HRESULT create_regexp(IDispatch**) DECLSPEC_HIDDEN;
HRESULT map_hres(HRESULT) DECLSPEC_HIDDEN;
HRESULT create_safearray_iter(SAFEARRAY *sa, IEnumVARIANT **ev) DECLSPEC_HIDDEN;
#define FACILITY_VBS 0xa
#define MAKE_VBSERROR(code) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_VBS, code)

View file

@ -191,7 +191,7 @@ reactos/dll/win32/url # Synced to WineStaging-2.9
reactos/dll/win32/urlmon # Synced to Wine-3.0
reactos/dll/win32/usp10 # Synced to Wine-3.0
reactos/dll/win32/uxtheme # Forked
reactos/dll/win32/vbscript # Synced to WineStaging-2.9
reactos/dll/win32/vbscript # Synced to Wine-3.0
reactos/dll/win32/version # Synced to WineStaging-2.9
reactos/dll/win32/vssapi # Synced to WineStaging-2.9
reactos/dll/win32/wbemdisp # Synced to WineStaging-2.16