[VBSCRIPT] Sync with Wine Staging 4.18. CORE-16441

This commit is contained in:
Amine Khaldi 2019-12-01 19:42:07 +01:00
parent 573d40fbaa
commit 9a0ddc1388
17 changed files with 3194 additions and 2132 deletions

View file

@ -136,7 +136,7 @@ static WCHAR *compiler_alloc_string(vbscode_t *vbscode, const WCHAR *str)
size_t size; size_t size;
WCHAR *ret; WCHAR *ret;
size = (strlenW(str)+1)*sizeof(WCHAR); size = (lstrlenW(str)+1)*sizeof(WCHAR);
ret = compiler_alloc(vbscode, size); ret = compiler_alloc(vbscode, size);
if(ret) if(ret)
memcpy(ret, str, size); memcpy(ret, str, size);
@ -375,12 +375,24 @@ static inline BOOL emit_catch(compile_ctx_t *ctx, unsigned off)
return emit_catch_jmp(ctx, off, ctx->instr_cnt); return emit_catch_jmp(ctx, off, ctx->instr_cnt);
} }
static HRESULT compile_error(script_ctx_t *ctx, HRESULT error)
{
if(error == SCRIPT_E_REPORTED)
return error;
clear_ei(&ctx->ei);
ctx->ei.scode = error = map_hres(error);
ctx->ei.bstrSource = get_vbscript_string(VBS_COMPILE_ERROR);
ctx->ei.bstrDescription = get_vbscript_error_string(error);
return report_script_error(ctx);
}
static expression_t *lookup_const_decls(compile_ctx_t *ctx, const WCHAR *name, BOOL lookup_global) static expression_t *lookup_const_decls(compile_ctx_t *ctx, const WCHAR *name, BOOL lookup_global)
{ {
const_decl_t *decl; const_decl_t *decl;
for(decl = ctx->const_decls; decl; decl = decl->next) { for(decl = ctx->const_decls; decl; decl = decl->next) {
if(!strcmpiW(decl->name, name)) if(!wcsicmp(decl->name, name))
return decl->value_expr; return decl->value_expr;
} }
@ -388,7 +400,7 @@ static expression_t *lookup_const_decls(compile_ctx_t *ctx, const WCHAR *name, B
return NULL; return NULL;
for(decl = ctx->global_consts; decl; decl = decl->next) { for(decl = ctx->global_consts; decl; decl = decl->next) {
if(!strcmpiW(decl->name, name)) if(!wcsicmp(decl->name, name))
return decl->value_expr; return decl->value_expr;
} }
@ -536,10 +548,8 @@ static HRESULT compile_expression(compile_ctx_t *ctx, expression_t *expr)
return push_instr_str(ctx, OP_string, ((string_expression_t*)expr)->value); return push_instr_str(ctx, OP_string, ((string_expression_t*)expr)->value);
case EXPR_SUB: case EXPR_SUB:
return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub); return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub);
case EXPR_USHORT: case EXPR_INT:
return push_instr_int(ctx, OP_short, ((int_expression_t*)expr)->value); return push_instr_int(ctx, OP_int, ((int_expression_t*)expr)->value);
case EXPR_ULONG:
return push_instr_int(ctx, OP_long, ((int_expression_t*)expr)->value);
case EXPR_XOR: case EXPR_XOR:
return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor); return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor);
default: default:
@ -781,7 +791,7 @@ static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *st
if(!push_instr(ctx, OP_val)) if(!push_instr(ctx, OP_val))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
}else { }else {
hres = push_instr_int(ctx, OP_short, 1); hres = push_instr_int(ctx, OP_int, 1);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
} }
@ -994,7 +1004,7 @@ static BOOL lookup_dim_decls(compile_ctx_t *ctx, const WCHAR *name)
dim_decl_t *dim_decl; dim_decl_t *dim_decl;
for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) { for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
if(!strcmpiW(dim_decl->name, name)) if(!wcsicmp(dim_decl->name, name))
return TRUE; return TRUE;
} }
@ -1006,7 +1016,7 @@ static BOOL lookup_args_name(compile_ctx_t *ctx, const WCHAR *name)
unsigned i; unsigned i;
for(i = 0; i < ctx->func->arg_cnt; i++) { for(i = 0; i < ctx->func->arg_cnt; i++) {
if(!strcmpiW(ctx->func->args[i].name, name)) if(!wcsicmp(ctx->func->args[i].name, name))
return TRUE; return TRUE;
} }
@ -1198,6 +1208,21 @@ static HRESULT compile_onerror_statement(compile_ctx_t *ctx, onerror_statement_t
return push_instr_int(ctx, OP_errmode, stat->resume_next); return push_instr_int(ctx, OP_errmode, stat->resume_next);
} }
static HRESULT compile_retval_statement(compile_ctx_t *ctx, retval_statement_t *stat)
{
HRESULT hres;
hres = compile_expression(ctx, stat->expr);
if(FAILED(hres))
return hres;
hres = push_instr(ctx, OP_retval);
if(FAILED(hres))
return hres;
return S_OK;
}
static HRESULT compile_statement(compile_ctx_t *ctx, statement_ctx_t *stat_ctx, statement_t *stat) static HRESULT compile_statement(compile_ctx_t *ctx, statement_ctx_t *stat_ctx, statement_t *stat)
{ {
HRESULT hres; HRESULT hres;
@ -1269,6 +1294,9 @@ static HRESULT compile_statement(compile_ctx_t *ctx, statement_ctx_t *stat_ctx,
case STAT_WHILELOOP: case STAT_WHILELOOP:
hres = compile_while_statement(ctx, (while_statement_t*)stat); hres = compile_while_statement(ctx, (while_statement_t*)stat);
break; break;
case STAT_RETVAL:
hres = compile_retval_statement(ctx, (retval_statement_t*)stat);
break;
default: default:
FIXME("Unimplemented statement type %d\n", stat->type); FIXME("Unimplemented statement type %d\n", stat->type);
hres = E_NOTIMPL; hres = E_NOTIMPL;
@ -1444,7 +1472,7 @@ static BOOL lookup_funcs_name(compile_ctx_t *ctx, const WCHAR *name)
function_t *iter; function_t *iter;
for(iter = ctx->funcs; iter; iter = iter->next) { for(iter = ctx->funcs; iter; iter = iter->next) {
if(!strcmpiW(iter->name, name)) if(!wcsicmp(iter->name, name))
return TRUE; return TRUE;
} }
@ -1511,7 +1539,7 @@ static BOOL lookup_class_name(compile_ctx_t *ctx, const WCHAR *name)
class_desc_t *iter; class_desc_t *iter;
for(iter = ctx->classes; iter; iter = iter->next) { for(iter = ctx->classes; iter; iter = iter->next) {
if(!strcmpiW(iter->name, name)) if(!wcsicmp(iter->name, name))
return TRUE; return TRUE;
} }
@ -1563,7 +1591,7 @@ static BOOL lookup_class_funcs(class_desc_t *class_desc, const WCHAR *name)
unsigned i; unsigned i;
for(i=0; i < class_desc->func_cnt; i++) { for(i=0; i < class_desc->func_cnt; i++) {
if(class_desc->funcs[i].name && !strcmpiW(class_desc->funcs[i].name, name)) if(class_desc->funcs[i].name && !wcsicmp(class_desc->funcs[i].name, name))
return TRUE; return TRUE;
} }
@ -1619,14 +1647,14 @@ static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl)
} }
} }
if(!strcmpiW(class_initializeW, func_decl->name)) { if(!wcsicmp(class_initializeW, func_decl->name)) {
if(func_decl->type != FUNC_SUB) { if(func_decl->type != FUNC_SUB) {
FIXME("class initializer is not sub\n"); FIXME("class initializer is not sub\n");
return E_FAIL; return E_FAIL;
} }
class_desc->class_initialize_id = i; class_desc->class_initialize_id = i;
}else if(!strcmpiW(class_terminateW, func_decl->name)) { }else if(!wcsicmp(class_terminateW, func_decl->name)) {
if(func_decl->type != FUNC_SUB) { if(func_decl->type != FUNC_SUB) {
FIXME("class terminator is not sub\n"); FIXME("class terminator is not sub\n");
return E_FAIL; return E_FAIL;
@ -1690,17 +1718,17 @@ static BOOL lookup_script_identifier(script_ctx_t *script, const WCHAR *identifi
function_t *func; function_t *func;
for(var = script->global_vars; var; var = var->next) { for(var = script->global_vars; var; var = var->next) {
if(!strcmpiW(var->name, identifier)) if(!wcsicmp(var->name, identifier))
return TRUE; return TRUE;
} }
for(func = script->global_funcs; func; func = func->next) { for(func = script->global_funcs; func; func = func->next) {
if(!strcmpiW(func->name, identifier)) if(!wcsicmp(func->name, identifier))
return TRUE; return TRUE;
} }
for(class = script->classes; class; class = class->next) { for(class = script->classes; class; class = class->next) {
if(!strcmpiW(class->name, identifier)) if(!wcsicmp(class->name, identifier))
return TRUE; return TRUE;
} }
@ -1797,7 +1825,7 @@ static void release_compiler(compile_ctx_t *ctx)
release_vbscode(ctx->code); release_vbscode(ctx->code);
} }
HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *delimiter, vbscode_t **ret) HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *delimiter, DWORD flags, vbscode_t **ret)
{ {
function_t *new_func; function_t *new_func;
function_decl_t *func_decl; function_decl_t *func_decl;
@ -1806,13 +1834,15 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli
vbscode_t *code; vbscode_t *code;
HRESULT hres; HRESULT hres;
hres = parse_script(&ctx.parser, src, delimiter); if (!src) src = L"";
hres = parse_script(&ctx.parser, src, delimiter, flags);
if(FAILED(hres)) if(FAILED(hres))
return hres; return compile_error(script, hres);
code = ctx.code = alloc_vbscode(&ctx, src); code = ctx.code = alloc_vbscode(&ctx, src);
if(!ctx.code) if(!ctx.code)
return E_OUTOFMEMORY; return compile_error(script, E_OUTOFMEMORY);
ctx.funcs = NULL; ctx.funcs = NULL;
ctx.func_decls = NULL; ctx.func_decls = NULL;
@ -1826,7 +1856,7 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli
hres = compile_func(&ctx, ctx.parser.stats, &ctx.code->main_code); hres = compile_func(&ctx, ctx.parser.stats, &ctx.code->main_code);
if(FAILED(hres)) { if(FAILED(hres)) {
release_compiler(&ctx); release_compiler(&ctx);
return hres; return compile_error(script, hres);
} }
ctx.global_consts = ctx.const_decls; ctx.global_consts = ctx.const_decls;
@ -1835,7 +1865,7 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli
hres = create_function(&ctx, func_decl, &new_func); hres = create_function(&ctx, func_decl, &new_func);
if(FAILED(hres)) { if(FAILED(hres)) {
release_compiler(&ctx); release_compiler(&ctx);
return hres; return compile_error(script, hres);
} }
new_func->next = ctx.funcs; new_func->next = ctx.funcs;
@ -1846,14 +1876,14 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli
hres = compile_class(&ctx, class_decl); hres = compile_class(&ctx, class_decl);
if(FAILED(hres)) { if(FAILED(hres)) {
release_compiler(&ctx); release_compiler(&ctx);
return hres; return compile_error(script, hres);
} }
} }
hres = check_script_collisions(&ctx, script); hres = check_script_collisions(&ctx, script);
if(FAILED(hres)) { if(FAILED(hres)) {
release_compiler(&ctx); release_compiler(&ctx);
return hres; return compile_error(script, hres);
} }
if(ctx.global_vars) { if(ctx.global_vars) {
@ -1896,3 +1926,29 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli
*ret = code; *ret = code;
return S_OK; return S_OK;
} }
HRESULT compile_procedure(script_ctx_t *script, const WCHAR *src, const WCHAR *delimiter, DWORD flags, class_desc_t **ret)
{
class_desc_t *desc;
vbscode_t *code;
HRESULT hres;
hres = compile_script(script, src, delimiter, flags, &code);
if(FAILED(hres))
return hres;
if(!(desc = compiler_alloc_zero(code, sizeof(*desc))))
return E_OUTOFMEMORY;
if(!(desc->funcs = compiler_alloc_zero(code, sizeof(*desc->funcs))))
return E_OUTOFMEMORY;
desc->ctx = script;
desc->func_cnt = 1;
desc->funcs->entries[VBDISP_CALLGET] = &code->main_code;
desc->next = script->procs;
script->procs = desc;
*ret = desc;
return S_OK;
}

File diff suppressed because it is too large Load diff

View file

@ -83,7 +83,7 @@ typedef struct {
static BOOL lookup_dynamic_vars(dynamic_var_t *var, const WCHAR *name, ref_t *ref) static BOOL lookup_dynamic_vars(dynamic_var_t *var, const WCHAR *name, ref_t *ref)
{ {
while(var) { while(var) {
if(!strcmpiW(var->name, name)) { if(!wcsicmp(var->name, name)) {
ref->type = var->is_const ? REF_CONST : REF_VAR; ref->type = var->is_const ? REF_CONST : REF_VAR;
ref->u.v = &var->v; ref->u.v = &var->v;
return TRUE; return TRUE;
@ -104,18 +104,16 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_
DISPID id; DISPID id;
HRESULT hres; HRESULT hres;
static const WCHAR errW[] = {'e','r','r',0};
if(invoke_type == VBDISP_LET if(invoke_type == VBDISP_LET
&& (ctx->func->type == FUNC_FUNCTION || ctx->func->type == FUNC_PROPGET || ctx->func->type == FUNC_DEFGET) && (ctx->func->type == FUNC_FUNCTION || ctx->func->type == FUNC_PROPGET || ctx->func->type == FUNC_DEFGET)
&& !strcmpiW(name, ctx->func->name)) { && !wcsicmp(name, ctx->func->name)) {
ref->type = REF_VAR; ref->type = REF_VAR;
ref->u.v = &ctx->ret_val; ref->u.v = &ctx->ret_val;
return S_OK; return S_OK;
} }
for(i=0; i < ctx->func->var_cnt; i++) { for(i=0; i < ctx->func->var_cnt; i++) {
if(!strcmpiW(ctx->func->vars[i].name, name)) { if(!wcsicmp(ctx->func->vars[i].name, name)) {
ref->type = REF_VAR; ref->type = REF_VAR;
ref->u.v = ctx->vars+i; ref->u.v = ctx->vars+i;
return TRUE; return TRUE;
@ -123,7 +121,7 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_
} }
for(i=0; i < ctx->func->arg_cnt; i++) { for(i=0; i < ctx->func->arg_cnt; i++) {
if(!strcmpiW(ctx->func->args[i].name, name)) { if(!wcsicmp(ctx->func->args[i].name, name)) {
ref->type = REF_VAR; ref->type = REF_VAR;
ref->u.v = ctx->args+i; ref->u.v = ctx->args+i;
return S_OK; return S_OK;
@ -137,7 +135,7 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_
if(ctx->vbthis) { if(ctx->vbthis) {
/* FIXME: Bind such identifier while generating bytecode. */ /* FIXME: Bind such identifier while generating bytecode. */
for(i=0; i < ctx->vbthis->desc->prop_cnt; i++) { for(i=0; i < ctx->vbthis->desc->prop_cnt; i++) {
if(!strcmpiW(ctx->vbthis->desc->props[i].name, name)) { if(!wcsicmp(ctx->vbthis->desc->props[i].name, name)) {
ref->type = REF_VAR; ref->type = REF_VAR;
ref->u.v = ctx->vbthis->props+i; ref->u.v = ctx->vbthis->props+i;
return S_OK; return S_OK;
@ -168,23 +166,17 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_
return S_OK; return S_OK;
for(func = ctx->script->global_funcs; func; func = func->next) { for(func = ctx->script->global_funcs; func; func = func->next) {
if(!strcmpiW(func->name, name)) { if(!wcsicmp(func->name, name)) {
ref->type = REF_FUNC; ref->type = REF_FUNC;
ref->u.f = func; ref->u.f = func;
return S_OK; return S_OK;
} }
} }
if(!strcmpiW(name, errW)) { hres = get_builtin_id(ctx->script->global_obj, name, &id);
ref->type = REF_OBJ;
ref->u.obj = (IDispatch*)&ctx->script->err_obj->IDispatchEx_iface;
return S_OK;
}
hres = vbdisp_get_id(ctx->script->global_obj, name, invoke_type, TRUE, &id);
if(SUCCEEDED(hres)) { if(SUCCEEDED(hres)) {
ref->type = REF_DISP; ref->type = REF_DISP;
ref->u.d.disp = (IDispatch*)&ctx->script->global_obj->IDispatchEx_iface; ref->u.d.disp = &ctx->script->global_obj->IDispatch_iface;
ref->u.d.id = id; ref->u.d.id = id;
return S_OK; return S_OK;
} }
@ -226,7 +218,7 @@ static HRESULT add_dynamic_var(exec_ctx_t *ctx, const WCHAR *name,
if(!new_var) if(!new_var)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
size = (strlenW(name)+1)*sizeof(WCHAR); size = (lstrlenW(name)+1)*sizeof(WCHAR);
str = heap_pool_alloc(heap, size); str = heap_pool_alloc(heap, size);
if(!str) if(!str)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
@ -247,6 +239,14 @@ static HRESULT add_dynamic_var(exec_ctx_t *ctx, const WCHAR *name,
return S_OK; return S_OK;
} }
void clear_ei(EXCEPINFO *ei)
{
SysFreeString(ei->bstrSource);
SysFreeString(ei->bstrDescription);
SysFreeString(ei->bstrHelpFile);
memset(ei, 0, sizeof(*ei));
}
static inline VARIANT *stack_pop(exec_ctx_t *ctx) static inline VARIANT *stack_pop(exec_ctx_t *ctx)
{ {
assert(ctx->top); assert(ctx->top);
@ -319,7 +319,7 @@ static HRESULT stack_pop_val(exec_ctx_t *ctx, variant_val_t *r)
HRESULT hres; HRESULT hres;
hres = get_disp_value(ctx->script, V_DISPATCH(r->v), &r->store); hres = get_disp_value(ctx->script, V_DISPATCH(r->v), &r->store);
if(r->owned) if(r->owned && V_DISPATCH(r->v))
IDispatch_Release(V_DISPATCH(r->v)); IDispatch_Release(V_DISPATCH(r->v));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
@ -350,7 +350,8 @@ static HRESULT stack_assume_val(exec_ctx_t *ctx, unsigned n)
disp = V_DISPATCH(v); disp = V_DISPATCH(v);
hres = get_disp_value(ctx->script, disp, v); hres = get_disp_value(ctx->script, disp, v);
IDispatch_Release(disp); if(disp)
IDispatch_Release(disp);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
} }
@ -580,7 +581,7 @@ static HRESULT do_icall(exec_ctx_t *ctx, VARIANT *res)
break; break;
case REF_FUNC: case REF_FUNC:
vbstack_to_dp(ctx, arg_cnt, FALSE, &dp); vbstack_to_dp(ctx, arg_cnt, FALSE, &dp);
hres = exec_script(ctx->script, ref.u.f, NULL, &dp, res); hres = exec_script(ctx->script, FALSE, ref.u.f, NULL, &dp, res);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
break; break;
@ -688,23 +689,27 @@ static HRESULT interp_mcallv(exec_ctx_t *ctx)
static HRESULT assign_value(exec_ctx_t *ctx, VARIANT *dst, VARIANT *src, WORD flags) static HRESULT assign_value(exec_ctx_t *ctx, VARIANT *dst, VARIANT *src, WORD flags)
{ {
VARIANT value;
HRESULT hres; HRESULT hres;
hres = VariantCopyInd(dst, src); V_VT(&value) = VT_EMPTY;
hres = VariantCopyInd(&value, src);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
if(V_VT(dst) == VT_DISPATCH && !(flags & DISPATCH_PROPERTYPUTREF)) { if(V_VT(&value) == VT_DISPATCH && !(flags & DISPATCH_PROPERTYPUTREF)) {
VARIANT value; IDispatch *disp = V_DISPATCH(&value);
hres = get_disp_value(ctx->script, V_DISPATCH(dst), &value); V_VT(&value) = VT_EMPTY;
IDispatch_Release(V_DISPATCH(dst)); hres = get_disp_value(ctx->script, disp, &value);
if(disp)
IDispatch_Release(disp);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
*dst = value;
} }
VariantClear(dst);
*dst = value;
return S_OK; return S_OK;
} }
@ -988,7 +993,7 @@ static HRESULT interp_new(exec_ctx_t *ctx)
TRACE("%s\n", debugstr_w(arg)); TRACE("%s\n", debugstr_w(arg));
if(!strcmpiW(arg, regexpW)) { if(!wcsicmp(arg, regexpW)) {
V_VT(&v) = VT_DISPATCH; V_VT(&v) = VT_DISPATCH;
hres = create_regexp(&V_DISPATCH(&v)); hres = create_regexp(&V_DISPATCH(&v));
if(FAILED(hres)) if(FAILED(hres))
@ -998,7 +1003,7 @@ static HRESULT interp_new(exec_ctx_t *ctx)
} }
for(class_desc = ctx->script->classes; class_desc; class_desc = class_desc->next) { for(class_desc = ctx->script->classes; class_desc; class_desc = class_desc->next) {
if(!strcmpiW(class_desc->name, arg)) if(!wcsicmp(class_desc->name, arg))
break; break;
} }
if(!class_desc) { if(!class_desc) {
@ -1258,6 +1263,30 @@ static HRESULT interp_ret(exec_ctx_t *ctx)
return S_OK; return S_OK;
} }
static HRESULT interp_retval(exec_ctx_t *ctx)
{
variant_val_t val;
HRESULT hres;
TRACE("\n");
hres = stack_pop_val(ctx, &val);
if(FAILED(hres))
return hres;
if(val.owned) {
VariantClear(&ctx->ret_val);
ctx->ret_val = *val.v;
}
else {
hres = VariantCopy(&ctx->ret_val, val.v);
if(FAILED(hres))
return hres;
}
return S_OK;
}
static HRESULT interp_stop(exec_ctx_t *ctx) static HRESULT interp_stop(exec_ctx_t *ctx)
{ {
WARN("\n"); WARN("\n");
@ -1297,7 +1326,7 @@ static HRESULT interp_errmode(exec_ctx_t *ctx)
TRACE("%d\n", err_mode); TRACE("%d\n", err_mode);
ctx->resume_next = err_mode; ctx->resume_next = err_mode;
ctx->script->err_number = S_OK; clear_ei(&ctx->script->ei);
return S_OK; return S_OK;
} }
@ -1315,27 +1344,20 @@ static HRESULT interp_string(exec_ctx_t *ctx)
return stack_push(ctx, &v); return stack_push(ctx, &v);
} }
static HRESULT interp_long(exec_ctx_t *ctx) static HRESULT interp_int(exec_ctx_t *ctx)
{ {
const LONG arg = ctx->instr->arg1.lng; const LONG arg = ctx->instr->arg1.lng;
VARIANT v; VARIANT v;
TRACE("%d\n", arg); TRACE("%d\n", arg);
V_VT(&v) = VT_I4; if(arg == (INT16)arg) {
V_I4(&v) = arg; V_VT(&v) = VT_I2;
return stack_push(ctx, &v); V_I2(&v) = arg;
} }else {
V_VT(&v) = VT_I4;
static HRESULT interp_short(exec_ctx_t *ctx) V_I4(&v) = arg;
{ }
const LONG arg = ctx->instr->arg1.lng;
VARIANT v;
TRACE("%d\n", arg);
V_VT(&v) = VT_I2;
V_I2(&v) = arg;
return stack_push(ctx, &v); return stack_push(ctx, &v);
} }
@ -2061,7 +2083,7 @@ static void release_exec(exec_ctx_t *ctx)
heap_free(ctx->stack); heap_free(ctx->stack);
} }
HRESULT exec_script(script_ctx_t *ctx, function_t *func, vbdisp_t *vbthis, DISPPARAMS *dp, VARIANT *res) HRESULT exec_script(script_ctx_t *ctx, BOOL extern_caller, function_t *func, vbdisp_t *vbthis, DISPPARAMS *dp, VARIANT *res)
{ {
exec_ctx_t exec = {func->code_ctx}; exec_ctx_t exec = {func->code_ctx};
vbsop_t op; vbsop_t op;
@ -2123,6 +2145,9 @@ HRESULT exec_script(script_ctx_t *ctx, function_t *func, vbdisp_t *vbthis, DISPP
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
if(extern_caller)
IActiveScriptSite_OnEnterScript(ctx->site);
if(vbthis) { if(vbthis) {
exec.this_obj = (IDispatch*)&vbthis->IDispatchEx_iface; exec.this_obj = (IDispatch*)&vbthis->IDispatchEx_iface;
exec.vbthis = vbthis; exec.vbthis = vbthis;
@ -2141,7 +2166,15 @@ HRESULT exec_script(script_ctx_t *ctx, function_t *func, vbdisp_t *vbthis, DISPP
op = exec.instr->op; op = exec.instr->op;
hres = op_funcs[op](&exec); hres = op_funcs[op](&exec);
if(FAILED(hres)) { if(FAILED(hres)) {
ctx->err_number = hres = map_hres(hres); if(hres != SCRIPT_E_RECORDED) {
clear_ei(&ctx->ei);
ctx->ei.scode = hres = map_hres(hres);
ctx->ei.bstrSource = get_vbscript_string(VBS_RUNTIME_ERROR);
ctx->ei.bstrDescription = get_vbscript_error_string(hres);
}else {
hres = ctx->ei.scode;
}
if(exec.resume_next) { if(exec.resume_next) {
unsigned stack_off; unsigned stack_off;
@ -2186,8 +2219,15 @@ HRESULT exec_script(script_ctx_t *ctx, function_t *func, vbdisp_t *vbthis, DISPP
} }
assert(!exec.top); assert(!exec.top);
if(func->type != FUNC_FUNCTION && func->type != FUNC_PROPGET && func->type != FUNC_DEFGET)
assert(V_VT(&exec.ret_val) == VT_EMPTY); if(extern_caller) {
IActiveScriptSite_OnLeaveScript(ctx->site);
if(FAILED(hres)) {
if(!ctx->ei.scode)
ctx->ei.scode = hres;
hres = report_script_error(ctx);
}
}
if(SUCCEEDED(hres) && res) { if(SUCCEEDED(hres) && res) {
*res = exec.ret_val; *res = exec.ret_val;

View file

@ -16,11 +16,13 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include "config.h" #ifdef __REACTOS__
#include "wine/port.h" #include <wine/config.h>
#include <wine/port.h>
#endif
#include <assert.h> #include <assert.h>
#include <limits.h> #include <limits.h>
#include <math.h>
#include "vbscript.h" #include "vbscript.h"
#include "parse.h" #include "parse.h"
@ -153,17 +155,17 @@ static const struct {
static inline BOOL is_identifier_char(WCHAR c) static inline BOOL is_identifier_char(WCHAR c)
{ {
return isalnumW(c) || c == '_'; return iswalnum(c) || c == '_';
} }
static int check_keyword(parser_ctx_t *ctx, const WCHAR *word) static int check_keyword(parser_ctx_t *ctx, const WCHAR *word, const WCHAR **lval)
{ {
const WCHAR *p1 = ctx->ptr; const WCHAR *p1 = ctx->ptr;
const WCHAR *p2 = word; const WCHAR *p2 = word;
WCHAR c; WCHAR c;
while(p1 < ctx->end && *p2) { while(p1 < ctx->end && *p2) {
c = tolowerW(*p1); c = towlower(*p1);
if(c != *p2) if(c != *p2)
return c - *p2; return c - *p2;
p1++; p1++;
@ -174,17 +176,18 @@ static int check_keyword(parser_ctx_t *ctx, const WCHAR *word)
return 1; return 1;
ctx->ptr = p1; ctx->ptr = p1;
*lval = word;
return 0; return 0;
} }
static int check_keywords(parser_ctx_t *ctx) static int check_keywords(parser_ctx_t *ctx, const WCHAR **lval)
{ {
int min = 0, max = ARRAY_SIZE(keywords)-1, r, i; int min = 0, max = ARRAY_SIZE(keywords)-1, r, i;
while(min <= max) { while(min <= max) {
i = (min+max)/2; i = (min+max)/2;
r = check_keyword(ctx, keywords[i].word); r = check_keyword(ctx, keywords[i].word, lval);
if(!r) if(!r)
return keywords[i].token; return keywords[i].token;
@ -224,7 +227,7 @@ static int parse_string_literal(parser_ctx_t *ctx, const WCHAR **ret)
int len = 0; int len = 0;
while(ctx->ptr < ctx->end) { while(ctx->ptr < ctx->end) {
if(*ctx->ptr == '\n') { if(*ctx->ptr == '\n' || *ctx->ptr == '\r') {
FIXME("newline inside string literal\n"); FIXME("newline inside string literal\n");
return 0; return 0;
} }
@ -270,7 +273,7 @@ static int parse_numeric_literal(parser_ctx_t *ctx, void **ret)
if(*ctx->ptr == '0' && !('0' <= ctx->ptr[1] && ctx->ptr[1] <= '9') && ctx->ptr[1] != '.') if(*ctx->ptr == '0' && !('0' <= ctx->ptr[1] && ctx->ptr[1] <= '9') && ctx->ptr[1] != '.')
return *ctx->ptr++; return *ctx->ptr++;
while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) { while(ctx->ptr < ctx->end && iswdigit(*ctx->ptr)) {
hlp = d*10 + *(ctx->ptr++) - '0'; hlp = d*10 + *(ctx->ptr++) - '0';
if(d>MAXLONGLONG/10 || hlp<0) { if(d>MAXLONGLONG/10 || hlp<0) {
exp++; exp++;
@ -279,7 +282,7 @@ static int parse_numeric_literal(parser_ctx_t *ctx, void **ret)
else else
d = hlp; d = hlp;
} }
while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) { while(ctx->ptr < ctx->end && iswdigit(*ctx->ptr)) {
exp++; exp++;
ctx->ptr++; ctx->ptr++;
} }
@ -288,7 +291,7 @@ static int parse_numeric_literal(parser_ctx_t *ctx, void **ret)
use_int = FALSE; use_int = FALSE;
ctx->ptr++; ctx->ptr++;
while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) { while(ctx->ptr < ctx->end && iswdigit(*ctx->ptr)) {
hlp = d*10 + *(ctx->ptr++) - '0'; hlp = d*10 + *(ctx->ptr++) - '0';
if(d>MAXLONGLONG/10 || hlp<0) if(d>MAXLONGLONG/10 || hlp<0)
break; break;
@ -296,19 +299,22 @@ static int parse_numeric_literal(parser_ctx_t *ctx, void **ret)
d = hlp; d = hlp;
exp--; exp--;
} }
while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) while(ctx->ptr < ctx->end && iswdigit(*ctx->ptr))
ctx->ptr++; ctx->ptr++;
} }
if(*ctx->ptr == 'e' || *ctx->ptr == 'E') { if(*ctx->ptr == 'e' || *ctx->ptr == 'E') {
int e = 0, sign = 1; int e = 0, sign = 1;
if(*++ctx->ptr == '-') { ctx->ptr++;
if(*ctx->ptr == '-') {
ctx->ptr++; ctx->ptr++;
sign = -1; sign = -1;
}else if(*ctx->ptr == '+') {
ctx->ptr++;
} }
if(!isdigitW(*ctx->ptr)) { if(!iswdigit(*ctx->ptr)) {
FIXME("Invalid numeric literal\n"); FIXME("Invalid numeric literal\n");
return 0; return 0;
} }
@ -319,7 +325,7 @@ static int parse_numeric_literal(parser_ctx_t *ctx, void **ret)
e = e*10 + *(ctx->ptr++) - '0'; e = e*10 + *(ctx->ptr++) - '0';
if(sign == -1 && -e+exp < -(INT_MAX/100)) { if(sign == -1 && -e+exp < -(INT_MAX/100)) {
/* The literal will be rounded to 0 anyway. */ /* The literal will be rounded to 0 anyway. */
while(isdigitW(*ctx->ptr)) while(iswdigit(*ctx->ptr))
ctx->ptr++; ctx->ptr++;
*(double*)ret = 0; *(double*)ret = 0;
return tDouble; return tDouble;
@ -329,15 +335,14 @@ static int parse_numeric_literal(parser_ctx_t *ctx, void **ret)
FIXME("Invalid numeric literal\n"); FIXME("Invalid numeric literal\n");
return 0; return 0;
} }
} while(isdigitW(*ctx->ptr)); } while(iswdigit(*ctx->ptr));
exp += sign*e; exp += sign*e;
} }
if(use_int && (LONG)d == d) { if(use_int && (LONG)d == d) {
LONG l = d; *(LONG*)ret = d;
*(LONG*)ret = l; return tInt;
return (short)l == l ? tShort : tLong;
} }
r = exp>=0 ? d*pow(10, exp) : d/pow(10, -exp); r = exp>=0 ? d*pow(10, exp) : d/pow(10, -exp);
@ -378,7 +383,7 @@ static int parse_hex_literal(parser_ctx_t *ctx, LONG *ret)
ctx->ptr++; ctx->ptr++;
*ret = l; *ret = l;
return (short)l == l ? tShort : tLong; return tInt;
} }
static void skip_spaces(parser_ctx_t *ctx) static void skip_spaces(parser_ctx_t *ctx)
@ -390,7 +395,7 @@ static void skip_spaces(parser_ctx_t *ctx)
static int comment_line(parser_ctx_t *ctx) static int comment_line(parser_ctx_t *ctx)
{ {
static const WCHAR newlineW[] = {'\n','\r',0}; static const WCHAR newlineW[] = {'\n','\r',0};
ctx->ptr = strpbrkW(ctx->ptr, newlineW); ctx->ptr = wcspbrk(ctx->ptr, newlineW);
if(ctx->ptr) if(ctx->ptr)
ctx->ptr++; ctx->ptr++;
else else
@ -411,8 +416,8 @@ static int parse_next_token(void *lval, parser_ctx_t *ctx)
if('0' <= c && c <= '9') if('0' <= c && c <= '9')
return parse_numeric_literal(ctx, lval); return parse_numeric_literal(ctx, lval);
if(isalphaW(c)) { if(iswalpha(c)) {
int ret = check_keywords(ctx); int ret = check_keywords(ctx, lval);
if(!ret) if(!ret)
return parse_identifier(ctx, lval); return parse_identifier(ctx, lval);
if(ret != tREM) if(ret != tREM)
@ -492,15 +497,24 @@ int parser_lex(void *lval, parser_ctx_t *ctx)
{ {
int ret; int ret;
if (ctx->last_token == tEXPRESSION)
{
ctx->last_token = tNL;
return tEXPRESSION;
}
while(1) { while(1) {
ret = parse_next_token(lval, ctx); ret = parse_next_token(lval, ctx);
if(ret == '_') { if(ret == '_') {
skip_spaces(ctx); skip_spaces(ctx);
if(*ctx->ptr != '\n') { if(*ctx->ptr != '\n' && *ctx->ptr != '\r') {
FIXME("'_' not followed by newline\n"); FIXME("'_' not followed by newline\n");
return 0; return 0;
} }
ctx->ptr++; if(*ctx->ptr == '\r')
ctx->ptr++;
if(*ctx->ptr == '\n')
ctx->ptr++;
continue; continue;
} }
if(ret != tNL || ctx->last_token != tNL) if(ret != tNL || ctx->last_token != tNL)

View file

@ -34,6 +34,7 @@ typedef enum {
EXPR_GTEQ, EXPR_GTEQ,
EXPR_IDIV, EXPR_IDIV,
EXPR_IMP, EXPR_IMP,
EXPR_INT,
EXPR_IS, EXPR_IS,
EXPR_LT, EXPR_LT,
EXPR_LTEQ, EXPR_LTEQ,
@ -51,8 +52,6 @@ typedef enum {
EXPR_OR, EXPR_OR,
EXPR_STRING, EXPR_STRING,
EXPR_SUB, EXPR_SUB,
EXPR_ULONG,
EXPR_USHORT,
EXPR_XOR EXPR_XOR
} expression_type_t; } expression_type_t;
@ -121,7 +120,8 @@ typedef enum {
STAT_STOP, STAT_STOP,
STAT_UNTIL, STAT_UNTIL,
STAT_WHILE, STAT_WHILE,
STAT_WHILELOOP STAT_WHILELOOP,
STAT_RETVAL
} statement_type_t; } statement_type_t;
typedef struct _statement_t { typedef struct _statement_t {
@ -251,6 +251,11 @@ typedef struct {
case_clausule_t *case_clausules; case_clausule_t *case_clausules;
} select_statement_t; } select_statement_t;
typedef struct {
statement_t stat;
expression_t *expr;
} retval_statement_t;
typedef struct { typedef struct {
const WCHAR *code; const WCHAR *code;
const WCHAR *ptr; const WCHAR *ptr;
@ -271,7 +276,7 @@ typedef struct {
heap_pool_t heap; heap_pool_t heap;
} parser_ctx_t; } parser_ctx_t;
HRESULT parse_script(parser_ctx_t*,const WCHAR*,const WCHAR*) DECLSPEC_HIDDEN; HRESULT parse_script(parser_ctx_t*,const WCHAR*,const WCHAR*,DWORD) DECLSPEC_HIDDEN;
void parser_release(parser_ctx_t*) DECLSPEC_HIDDEN; void parser_release(parser_ctx_t*) DECLSPEC_HIDDEN;
int parser_lex(void*,parser_ctx_t*) DECLSPEC_HIDDEN; int parser_lex(void*,parser_ctx_t*) DECLSPEC_HIDDEN;
void *parser_alloc(parser_ctx_t*,size_t) DECLSPEC_HIDDEN; void *parser_alloc(parser_ctx_t*,size_t) DECLSPEC_HIDDEN;

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,9 @@
/* A Bison parser, made by GNU Bison 3.0. */ /* A Bison parser, made by GNU Bison 3.4.1. */
/* Bison interface for Yacc-like parsers in C /* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -30,6 +31,9 @@
This special exception was added by the Free Software Foundation in This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */ version 2.2 of Bison. */
/* Undocumented macros, especially those whose name start with YY_,
are private implementation details. Do not rely on them. */
#ifndef YY_PARSER_E_REACTOSSYNC_GCC_DLL_WIN32_VBSCRIPT_PARSER_TAB_H_INCLUDED #ifndef YY_PARSER_E_REACTOSSYNC_GCC_DLL_WIN32_VBSCRIPT_PARSER_TAB_H_INCLUDED
# define YY_PARSER_E_REACTOSSYNC_GCC_DLL_WIN32_VBSCRIPT_PARSER_TAB_H_INCLUDED # define YY_PARSER_E_REACTOSSYNC_GCC_DLL_WIN32_VBSCRIPT_PARSER_TAB_H_INCLUDED
/* Debug traces. */ /* Debug traces. */
@ -45,83 +49,82 @@ extern int parser_debug;
# define YYTOKENTYPE # define YYTOKENTYPE
enum yytokentype enum yytokentype
{ {
tEOF = 258, tEXPRESSION = 258,
tNL = 259, tEOF = 259,
tREM = 260, tNL = 260,
tEMPTYBRACKETS = 261, tEMPTYBRACKETS = 261,
tTRUE = 262, tLTEQ = 262,
tFALSE = 263, tGTEQ = 263,
tNOT = 264, tNEQ = 264,
tAND = 265, tSTOP = 265,
tOR = 266, tME = 266,
tXOR = 267, tREM = 267,
tEQV = 268, tTRUE = 268,
tIMP = 269, tFALSE = 269,
tNEQ = 270, tNOT = 270,
tIS = 271, tAND = 271,
tLTEQ = 272, tOR = 272,
tGTEQ = 273, tXOR = 273,
tMOD = 274, tEQV = 274,
tCALL = 275, tIMP = 275,
tDIM = 276, tIS = 276,
tSUB = 277, tMOD = 277,
tFUNCTION = 278, tCALL = 278,
tPROPERTY = 279, tDIM = 279,
tGET = 280, tSUB = 280,
tLET = 281, tFUNCTION = 281,
tCONST = 282, tGET = 282,
tIF = 283, tLET = 283,
tELSE = 284, tCONST = 284,
tELSEIF = 285, tIF = 285,
tEND = 286, tELSE = 286,
tTHEN = 287, tELSEIF = 287,
tEXIT = 288, tEND = 288,
tWHILE = 289, tTHEN = 289,
tWEND = 290, tEXIT = 290,
tDO = 291, tWHILE = 291,
tLOOP = 292, tWEND = 292,
tUNTIL = 293, tDO = 293,
tFOR = 294, tLOOP = 294,
tTO = 295, tUNTIL = 295,
tSTEP = 296, tFOR = 296,
tEACH = 297, tTO = 297,
tIN = 298, tEACH = 298,
tSELECT = 299, tIN = 299,
tCASE = 300, tSELECT = 300,
tBYREF = 301, tCASE = 301,
tBYVAL = 302, tBYREF = 302,
tOPTION = 303, tBYVAL = 303,
tEXPLICIT = 304, tOPTION = 304,
tSTOP = 305, tNOTHING = 305,
tNOTHING = 306, tEMPTY = 306,
tEMPTY = 307, tNULL = 307,
tNULL = 308, tCLASS = 308,
tCLASS = 309, tSET = 309,
tSET = 310, tNEW = 310,
tNEW = 311, tPUBLIC = 311,
tPUBLIC = 312, tPRIVATE = 312,
tPRIVATE = 313, tNEXT = 313,
tDEFAULT = 314, tON = 314,
tME = 315, tRESUME = 315,
tERROR = 316, tGOTO = 316,
tNEXT = 317, tIdentifier = 317,
tON = 318, tString = 318,
tRESUME = 319, tDEFAULT = 319,
tGOTO = 320, tERROR = 320,
tIdentifier = 321, tEXPLICIT = 321,
tString = 322, tPROPERTY = 322,
tLong = 323, tSTEP = 323,
tShort = 324, tInt = 324,
tDouble = 325 tDouble = 325
}; };
#endif #endif
/* Value type. */ /* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE YYSTYPE;
union YYSTYPE union YYSTYPE
{ {
#line 88 "parser.y" /* yacc.c:1909 */ #line 87 "parser.y"
const WCHAR *string; const WCHAR *string;
statement_t *statement; statement_t *statement;
@ -136,12 +139,14 @@ union YYSTYPE
const_decl_t *const_decl; const_decl_t *const_decl;
case_clausule_t *case_clausule; case_clausule_t *case_clausule;
unsigned uint; unsigned uint;
LONG lng; LONG integer;
BOOL boolean; BOOL boolean;
double dbl; double dbl;
#line 144 "parser.tab.h" /* yacc.c:1909 */ #line 147 "parser.tab.h"
}; };
typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_DECLARED 1
#endif #endif

View file

@ -28,6 +28,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
static int parser_error(parser_ctx_t *,const char*); static int parser_error(parser_ctx_t *,const char*);
static void parse_complete(parser_ctx_t*,BOOL); static void parse_complete(parser_ctx_t*,BOOL);
static void handle_isexpression_script(parser_ctx_t *ctx, expression_t *expr);
static void source_add_statement(parser_ctx_t*,statement_t*); static void source_add_statement(parser_ctx_t*,statement_t*);
static void source_add_class(parser_ctx_t*,class_decl_t*); static void source_add_class(parser_ctx_t*,class_decl_t*);
@ -71,8 +72,6 @@ static class_decl_t *add_dim_prop(parser_ctx_t*,class_decl_t*,dim_decl_t*,unsign
static statement_t *link_statements(statement_t*,statement_t*); static statement_t *link_statements(statement_t*,statement_t*);
static const WCHAR propertyW[] = {'p','r','o','p','e','r','t','y',0};
#define STORAGE_IS_PRIVATE 1 #define STORAGE_IS_PRIVATE 1
#define STORAGE_IS_DEFAULT 2 #define STORAGE_IS_DEFAULT 2
@ -99,31 +98,33 @@ static const WCHAR propertyW[] = {'p','r','o','p','e','r','t','y',0};
const_decl_t *const_decl; const_decl_t *const_decl;
case_clausule_t *case_clausule; case_clausule_t *case_clausule;
unsigned uint; unsigned uint;
LONG lng; LONG integer;
BOOL boolean; BOOL boolean;
double dbl; double dbl;
} }
%token tEOF tNL tREM tEMPTYBRACKETS %token tEXPRESSION tEOF tNL tEMPTYBRACKETS
%token tTRUE tFALSE %token tLTEQ tGTEQ tNEQ
%token tNOT tAND tOR tXOR tEQV tIMP tNEQ %token tSTOP tME tREM
%token tIS tLTEQ tGTEQ tMOD %token <string> tTRUE tFALSE
%token tCALL tDIM tSUB tFUNCTION tPROPERTY tGET tLET tCONST %token <string> tNOT tAND tOR tXOR tEQV tIMP
%token tIF tELSE tELSEIF tEND tTHEN tEXIT %token <string> tIS tMOD
%token tWHILE tWEND tDO tLOOP tUNTIL tFOR tTO tSTEP tEACH tIN %token <string> tCALL tDIM tSUB tFUNCTION tGET tLET tCONST
%token tSELECT tCASE %token <string> tIF tELSE tELSEIF tEND tTHEN tEXIT
%token tBYREF tBYVAL %token <string> tWHILE tWEND tDO tLOOP tUNTIL tFOR tTO tEACH tIN
%token tOPTION tEXPLICIT %token <string> tSELECT tCASE
%token tSTOP %token <string> tBYREF tBYVAL
%token tNOTHING tEMPTY tNULL %token <string> tOPTION
%token tCLASS tSET tNEW tPUBLIC tPRIVATE tDEFAULT tME %token <string> tNOTHING tEMPTY tNULL
%token tERROR tNEXT tON tRESUME tGOTO %token <string> tCLASS tSET tNEW tPUBLIC tPRIVATE
%token <string> tNEXT tON tRESUME tGOTO
%token <string> tIdentifier tString %token <string> tIdentifier tString
%token <lng> tLong tShort %token <string> tDEFAULT tERROR tEXPLICIT tPROPERTY tSTEP
%token <integer> tInt
%token <dbl> tDouble %token <dbl> tDouble
%type <statement> Statement SimpleStatement StatementNl StatementsNl StatementsNl_opt IfStatement Else_opt %type <statement> Statement SimpleStatement StatementNl StatementsNl StatementsNl_opt BodyStatements IfStatement Else_opt
%type <expression> Expression LiteralExpression PrimaryExpression EqualityExpression CallExpression %type <expression> Expression LiteralExpression PrimaryExpression EqualityExpression CallExpression ExpressionNl_opt
%type <expression> ConcatExpression AdditiveExpression ModExpression IntdivExpression MultiplicativeExpression ExpExpression %type <expression> ConcatExpression AdditiveExpression ModExpression IntdivExpression MultiplicativeExpression ExpExpression
%type <expression> NotExpression UnaryExpression AndExpression OrExpression XorExpression EqvExpression %type <expression> NotExpression UnaryExpression AndExpression OrExpression XorExpression EqvExpression
%type <expression> ConstExpression NumericLiteralExpression %type <expression> ConstExpression NumericLiteralExpression
@ -138,13 +139,14 @@ static const WCHAR propertyW[] = {'p','r','o','p','e','r','t','y',0};
%type <dim_decl> DimDeclList DimDecl %type <dim_decl> DimDeclList DimDecl
%type <dim_list> DimList %type <dim_list> DimList
%type <const_decl> ConstDecl ConstDeclList %type <const_decl> ConstDecl ConstDeclList
%type <string> Identifier %type <string> Identifier DotIdentifier
%type <case_clausule> CaseClausules %type <case_clausule> CaseClausules
%% %%
Program Program
: OptionExplicit_opt SourceElements tEOF { parse_complete(ctx, $1); } : OptionExplicit_opt SourceElements tEOF { parse_complete(ctx, $1); }
| tEXPRESSION ExpressionNl_opt tEOF { handle_isexpression_script(ctx, $2); }
OptionExplicit_opt OptionExplicit_opt
: /* empty */ { $$ = FALSE; } : /* empty */ { $$ = FALSE; }
@ -155,6 +157,15 @@ SourceElements
| SourceElements StatementNl { source_add_statement(ctx, $2); } | SourceElements StatementNl { source_add_statement(ctx, $2); }
| SourceElements ClassDeclaration { source_add_class(ctx, $2); } | SourceElements ClassDeclaration { source_add_class(ctx, $2); }
ExpressionNl_opt
: /* empty */ { $$ = NULL; }
| Expression tNL { $$ = $1; }
BodyStatements
: /* empty */ { $$ = NULL; }
| Statement { $$ = $1; }
| StatementNl BodyStatements { $$ = link_statements($1, $2); }
StatementsNl_opt StatementsNl_opt
: /* empty */ { $$ = NULL; } : /* empty */ { $$ = NULL; }
| StatementsNl { $$ = $1; } | StatementsNl { $$ = $1; }
@ -210,7 +221,7 @@ SimpleStatement
MemberExpression MemberExpression
: Identifier { $$ = new_member_expression(ctx, NULL, $1); CHECK_ERROR; } : Identifier { $$ = new_member_expression(ctx, NULL, $1); CHECK_ERROR; }
| CallExpression '.' Identifier { $$ = new_member_expression(ctx, $1, $3); CHECK_ERROR; } | CallExpression '.' DotIdentifier { $$ = new_member_expression(ctx, $1, $3); CHECK_ERROR; }
DimDeclList DimDeclList
: DimDecl { $$ = $1; } : DimDecl { $$ = $1; }
@ -366,6 +377,7 @@ UnaryExpression
| CallExpression { $$ = $1; } | CallExpression { $$ = $1; }
| tNEW Identifier { $$ = new_new_expression(ctx, $2); CHECK_ERROR; } | tNEW Identifier { $$ = new_new_expression(ctx, $2); CHECK_ERROR; }
| '-' UnaryExpression { $$ = new_unary_expression(ctx, EXPR_NEG, $2); CHECK_ERROR; } | '-' UnaryExpression { $$ = new_unary_expression(ctx, EXPR_NEG, $2); CHECK_ERROR; }
| '+' UnaryExpression { $$ = $2; }
CallExpression CallExpression
: PrimaryExpression { $$ = $1; } : PrimaryExpression { $$ = $1; }
@ -381,15 +393,13 @@ LiteralExpression
| tNOTHING { $$ = new_expression(ctx, EXPR_NOTHING, 0); CHECK_ERROR; } | tNOTHING { $$ = new_expression(ctx, EXPR_NOTHING, 0); CHECK_ERROR; }
NumericLiteralExpression NumericLiteralExpression
: tShort { $$ = new_long_expression(ctx, EXPR_USHORT, $1); CHECK_ERROR; } : '0' { $$ = new_long_expression(ctx, EXPR_INT, 0); CHECK_ERROR; }
| '0' { $$ = new_long_expression(ctx, EXPR_USHORT, 0); CHECK_ERROR; } | tInt { $$ = new_long_expression(ctx, EXPR_INT, $1); CHECK_ERROR; }
| tLong { $$ = new_long_expression(ctx, EXPR_ULONG, $1); CHECK_ERROR; }
| tDouble { $$ = new_double_expression(ctx, $1); CHECK_ERROR; } | tDouble { $$ = new_double_expression(ctx, $1); CHECK_ERROR; }
IntegerValue IntegerValue
: tShort { $$ = $1; } : '0' { $$ = 0; }
| '0' { $$ = 0; } | tInt { $$ = $1; }
| tLong { $$ = $1; }
PrimaryExpression PrimaryExpression
: '(' Expression ')' { $$ = new_unary_expression(ctx, EXPR_BRACKETS, $2); } : '(' Expression ')' { $$ = new_unary_expression(ctx, EXPR_BRACKETS, $2); }
@ -400,25 +410,30 @@ ClassDeclaration
ClassBody ClassBody
: /* empty */ { $$ = new_class_decl(ctx); } : /* empty */ { $$ = new_class_decl(ctx); }
| FunctionDecl { $$ = add_class_function(ctx, new_class_decl(ctx), $1); CHECK_ERROR; }
| FunctionDecl StSep ClassBody { $$ = add_class_function(ctx, $3, $1); CHECK_ERROR; } | 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. */ /* FIXME: We should use DimDecl here to support arrays, but that conflicts with PropertyDecl. */
| Storage tIdentifier { dim_decl_t *dim_decl = new_dim_decl(ctx, $2, FALSE, NULL); CHECK_ERROR;
$$ = add_dim_prop(ctx, new_class_decl(ctx), dim_decl, $1); CHECK_ERROR; }
| Storage tIdentifier StSep 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; } $$ = add_dim_prop(ctx, $4, dim_decl, $1); CHECK_ERROR; }
| tDIM DimDecl { $$ = add_dim_prop(ctx, new_class_decl(ctx), $2, 0); CHECK_ERROR; }
| tDIM DimDecl StSep ClassBody { $$ = add_dim_prop(ctx, $4, $2, 0); CHECK_ERROR; } | tDIM DimDecl StSep ClassBody { $$ = add_dim_prop(ctx, $4, $2, 0); CHECK_ERROR; }
| PropertyDecl { $$ = add_class_function(ctx, new_class_decl(ctx), $1); CHECK_ERROR; }
| PropertyDecl StSep ClassBody { $$ = add_class_function(ctx, $3, $1); CHECK_ERROR; } | PropertyDecl StSep ClassBody { $$ = add_class_function(ctx, $3, $1); CHECK_ERROR; }
PropertyDecl PropertyDecl
: Storage_opt tPROPERTY tGET tIdentifier ArgumentsDecl_opt StSep StatementsNl_opt tEND tPROPERTY : Storage_opt tPROPERTY tGET tIdentifier ArgumentsDecl_opt StSep BodyStatements tEND tPROPERTY
{ $$ = new_function_decl(ctx, $4, FUNC_PROPGET, $1, $5, $7); CHECK_ERROR; } { $$ = new_function_decl(ctx, $4, FUNC_PROPGET, $1, $5, $7); CHECK_ERROR; }
| Storage_opt tPROPERTY tLET tIdentifier '(' ArgumentDecl ')' StSep StatementsNl_opt tEND tPROPERTY | Storage_opt tPROPERTY tLET tIdentifier '(' ArgumentDecl ')' StSep BodyStatements tEND tPROPERTY
{ $$ = new_function_decl(ctx, $4, FUNC_PROPLET, $1, $6, $9); CHECK_ERROR; } { $$ = new_function_decl(ctx, $4, FUNC_PROPLET, $1, $6, $9); CHECK_ERROR; }
| Storage_opt tPROPERTY tSET tIdentifier '(' ArgumentDecl ')' StSep StatementsNl_opt tEND tPROPERTY | Storage_opt tPROPERTY tSET tIdentifier '(' ArgumentDecl ')' StSep BodyStatements tEND tPROPERTY
{ $$ = new_function_decl(ctx, $4, FUNC_PROPSET, $1, $6, $9); CHECK_ERROR; } { $$ = new_function_decl(ctx, $4, FUNC_PROPSET, $1, $6, $9); CHECK_ERROR; }
FunctionDecl FunctionDecl
: Storage_opt tSUB Identifier ArgumentsDecl_opt StSep StatementsNl_opt tEND tSUB : Storage_opt tSUB Identifier ArgumentsDecl_opt StSep BodyStatements tEND tSUB
{ $$ = new_function_decl(ctx, $3, FUNC_SUB, $1, $4, $6); CHECK_ERROR; } { $$ = new_function_decl(ctx, $3, FUNC_SUB, $1, $4, $6); CHECK_ERROR; }
| Storage_opt tFUNCTION Identifier ArgumentsDecl_opt StSep StatementsNl_opt tEND tFUNCTION | Storage_opt tFUNCTION Identifier ArgumentsDecl_opt StSep BodyStatements tEND tFUNCTION
{ $$ = new_function_decl(ctx, $3, FUNC_FUNCTION, $1, $4, $6); CHECK_ERROR; } { $$ = new_function_decl(ctx, $3, FUNC_FUNCTION, $1, $4, $6); CHECK_ERROR; }
Storage_opt Storage_opt
@ -443,10 +458,67 @@ ArgumentDecl
| tBYREF Identifier EmptyBrackets_opt { $$ = new_argument_decl(ctx, $2, TRUE); } | tBYREF Identifier EmptyBrackets_opt { $$ = new_argument_decl(ctx, $2, TRUE); }
| tBYVAL Identifier EmptyBrackets_opt { $$ = new_argument_decl(ctx, $2, FALSE); } | tBYVAL Identifier EmptyBrackets_opt { $$ = new_argument_decl(ctx, $2, FALSE); }
/* 'property' may be both keyword and identifier, depending on context */ /* these keywords may also be an identifier, depending on context */
Identifier Identifier
: tIdentifier { $$ = $1; } : tIdentifier { $$ = $1; }
| tPROPERTY { $$ = propertyW; } | tDEFAULT { $$ = $1; }
| tERROR { $$ = $1; }
| tEXPLICIT { $$ = $1; }
| tPROPERTY { $$ = $1; }
| tSTEP { $$ = $1; }
/* most keywords can be an identifier after a dot */
DotIdentifier
: Identifier { $$ = $1; }
| tTRUE { $$ = $1; }
| tFALSE { $$ = $1; }
| tNOT { $$ = $1; }
| tAND { $$ = $1; }
| tOR { $$ = $1; }
| tXOR { $$ = $1; }
| tEQV { $$ = $1; }
| tIMP { $$ = $1; }
| tIS { $$ = $1; }
| tMOD { $$ = $1; }
| tCALL { $$ = $1; }
| tDIM { $$ = $1; }
| tSUB { $$ = $1; }
| tFUNCTION { $$ = $1; }
| tGET { $$ = $1; }
| tLET { $$ = $1; }
| tCONST { $$ = $1; }
| tIF { $$ = $1; }
| tELSE { $$ = $1; }
| tELSEIF { $$ = $1; }
| tEND { $$ = $1; }
| tTHEN { $$ = $1; }
| tEXIT { $$ = $1; }
| tWHILE { $$ = $1; }
| tWEND { $$ = $1; }
| tDO { $$ = $1; }
| tLOOP { $$ = $1; }
| tUNTIL { $$ = $1; }
| tFOR { $$ = $1; }
| tTO { $$ = $1; }
| tEACH { $$ = $1; }
| tIN { $$ = $1; }
| tSELECT { $$ = $1; }
| tCASE { $$ = $1; }
| tBYREF { $$ = $1; }
| tBYVAL { $$ = $1; }
| tOPTION { $$ = $1; }
| tNOTHING { $$ = $1; }
| tEMPTY { $$ = $1; }
| tNULL { $$ = $1; }
| tCLASS { $$ = $1; }
| tSET { $$ = $1; }
| tNEW { $$ = $1; }
| tPUBLIC { $$ = $1; }
| tPRIVATE { $$ = $1; }
| tNEXT { $$ = $1; }
| tON { $$ = $1; }
| tRESUME { $$ = $1; }
| tGOTO { $$ = $1; }
/* Most statements accept both new line and ':' as separators */ /* Most statements accept both new line and ':' as separators */
StSep StSep
@ -487,6 +559,22 @@ static void parse_complete(parser_ctx_t *ctx, BOOL option_explicit)
ctx->option_explicit = option_explicit; ctx->option_explicit = option_explicit;
} }
static void handle_isexpression_script(parser_ctx_t *ctx, expression_t *expr)
{
retval_statement_t *stat;
ctx->parse_complete = TRUE;
if(!expr)
return;
stat = new_statement(ctx, STAT_RETVAL, sizeof(*stat));
if(!stat)
return;
stat->expr = expr;
ctx->stats = &stat->stat;
}
static void *new_expression(parser_ctx_t *ctx, expression_type_t type, size_t size) static void *new_expression(parser_ctx_t *ctx, expression_type_t type, size_t size)
{ {
expression_t *expr; expression_t *expr;
@ -879,7 +967,7 @@ static class_decl_t *add_class_function(parser_ctx_t *ctx, class_decl_t *class_d
function_decl_t *iter; function_decl_t *iter;
for(iter = class_decl->funcs; iter; iter = iter->next) { for(iter = class_decl->funcs; iter; iter = iter->next) {
if(!strcmpiW(iter->name, decl->name)) { if(!wcsicmp(iter->name, decl->name)) {
if(decl->type == FUNC_SUB || decl->type == FUNC_FUNCTION) { if(decl->type == FUNC_SUB || decl->type == FUNC_FUNCTION) {
FIXME("Redefinition of %s::%s\n", debugstr_w(class_decl->name), debugstr_w(decl->name)); FIXME("Redefinition of %s::%s\n", debugstr_w(class_decl->name), debugstr_w(decl->name));
ctx->hres = E_FAIL; ctx->hres = E_FAIL;
@ -967,12 +1055,12 @@ void *parser_alloc(parser_ctx_t *ctx, size_t size)
return ret; return ret;
} }
HRESULT parse_script(parser_ctx_t *ctx, const WCHAR *code, const WCHAR *delimiter) HRESULT parse_script(parser_ctx_t *ctx, const WCHAR *code, const WCHAR *delimiter, DWORD flags)
{ {
static const WCHAR html_delimiterW[] = {'<','/','s','c','r','i','p','t','>',0}; static const WCHAR html_delimiterW[] = {'<','/','s','c','r','i','p','t','>',0};
ctx->code = ctx->ptr = code; ctx->code = ctx->ptr = code;
ctx->end = ctx->code + strlenW(ctx->code); ctx->end = ctx->code + lstrlenW(ctx->code);
heap_pool_init(&ctx->heap); heap_pool_init(&ctx->heap);
@ -984,7 +1072,10 @@ HRESULT parse_script(parser_ctx_t *ctx, const WCHAR *code, const WCHAR *delimite
ctx->stats = ctx->stats_tail = NULL; ctx->stats = ctx->stats_tail = NULL;
ctx->class_decls = NULL; ctx->class_decls = NULL;
ctx->option_explicit = FALSE; ctx->option_explicit = FALSE;
ctx->is_html = delimiter && !strcmpiW(delimiter, html_delimiterW); ctx->is_html = delimiter && !wcsicmp(delimiter, html_delimiterW);
if(flags & SCRIPTTEXT_ISEXPRESSION)
ctx->last_token = tEXPRESSION;
parser_parse(ctx); parser_parse(ctx);

View file

@ -1142,8 +1142,8 @@ lexHex:
for (i = rangeStart; i <= localMax; i++) { for (i = rangeStart; i <= localMax; i++) {
WCHAR uch, dch; WCHAR uch, dch;
uch = toupperW(i); uch = towupper(i);
dch = tolowerW(i); dch = towlower(i);
if(maxch < uch) if(maxch < uch)
maxch = uch; maxch = uch;
if(maxch < dch) if(maxch < dch)
@ -1988,7 +1988,7 @@ FlatNIMatcher(REGlobalData *gData, match_state_t *x, const WCHAR *matchChars,
if (length > (size_t)(gData->cpend - x->cp)) if (length > (size_t)(gData->cpend - x->cp))
return NULL; return NULL;
for (i = 0; i != length; i++) { for (i = 0; i != length; i++) {
if (toupperW(matchChars[i]) != toupperW(x->cp[i])) if (towupper(matchChars[i]) != towupper(x->cp[i]))
return NULL; return NULL;
} }
x->cp += length; x->cp += length;
@ -2035,7 +2035,7 @@ BackrefMatcher(REGlobalData *gData, match_state_t *x, size_t parenIndex)
parenContent = &gData->cpbegin[cap->index]; parenContent = &gData->cpbegin[cap->index];
if (gData->regexp->flags & REG_FOLD) { if (gData->regexp->flags & REG_FOLD) {
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
if (toupperW(parenContent[i]) != toupperW(x->cp[i])) if (towupper(parenContent[i]) != towupper(x->cp[i]))
return NULL; return NULL;
} }
} else { } else {
@ -2226,12 +2226,12 @@ ProcessCharSet(REGlobalData *gData, RECharSet *charSet)
continue; continue;
case 's': case 's':
for (i = (INT)charSet->length; i >= 0; i--) for (i = (INT)charSet->length; i >= 0; i--)
if (isspaceW(i)) if (iswspace(i))
AddCharacterToCharSet(charSet, (WCHAR)i); AddCharacterToCharSet(charSet, (WCHAR)i);
continue; continue;
case 'S': case 'S':
for (i = (INT)charSet->length; i >= 0; i--) for (i = (INT)charSet->length; i >= 0; i--)
if (!isspaceW(i)) if (!iswspace(i))
AddCharacterToCharSet(charSet, (WCHAR)i); AddCharacterToCharSet(charSet, (WCHAR)i);
continue; continue;
case 'w': case 'w':
@ -2263,8 +2263,8 @@ ProcessCharSet(REGlobalData *gData, RECharSet *charSet)
WCHAR uch, dch; WCHAR uch, dch;
AddCharacterToCharSet(charSet, i); AddCharacterToCharSet(charSet, i);
uch = toupperW(i); uch = towupper(i);
dch = tolowerW(i); dch = towlower(i);
if (i != uch) if (i != uch)
AddCharacterToCharSet(charSet, uch); AddCharacterToCharSet(charSet, uch);
if (i != dch) if (i != dch)
@ -2276,8 +2276,8 @@ ProcessCharSet(REGlobalData *gData, RECharSet *charSet)
inRange = FALSE; inRange = FALSE;
} else { } else {
if (gData->regexp->flags & REG_FOLD) { if (gData->regexp->flags & REG_FOLD) {
AddCharacterToCharSet(charSet, toupperW(thisCh)); AddCharacterToCharSet(charSet, towupper(thisCh));
AddCharacterToCharSet(charSet, tolowerW(thisCh)); AddCharacterToCharSet(charSet, towlower(thisCh));
} else { } else {
AddCharacterToCharSet(charSet, thisCh); AddCharacterToCharSet(charSet, thisCh);
} }
@ -2411,13 +2411,13 @@ SimpleMatch(REGlobalData *gData, match_state_t *x, REOp op,
} }
break; break;
case REOP_SPACE: case REOP_SPACE:
if (x->cp != gData->cpend && isspaceW(*x->cp)) { if (x->cp != gData->cpend && iswspace(*x->cp)) {
result = x; result = x;
result->cp++; result->cp++;
} }
break; break;
case REOP_NONSPACE: case REOP_NONSPACE:
if (x->cp != gData->cpend && !isspaceW(*x->cp)) { if (x->cp != gData->cpend && !iswspace(*x->cp)) {
result = x; result = x;
result->cp++; result->cp++;
} }
@ -2463,7 +2463,7 @@ SimpleMatch(REGlobalData *gData, match_state_t *x, REOp op,
break; break;
case REOP_FLAT1i: case REOP_FLAT1i:
matchCh = *pc++; matchCh = *pc++;
if (x->cp != gData->cpend && toupperW(*x->cp) == toupperW(matchCh)) { if (x->cp != gData->cpend && towupper(*x->cp) == towupper(matchCh)) {
result = x; result = x;
result->cp++; result->cp++;
} }
@ -2480,7 +2480,7 @@ SimpleMatch(REGlobalData *gData, match_state_t *x, REOp op,
case REOP_UCFLAT1i: case REOP_UCFLAT1i:
matchCh = GET_ARG(pc); matchCh = GET_ARG(pc);
pc += ARG_LEN; pc += ARG_LEN;
if (x->cp != gData->cpend && toupperW(*x->cp) == toupperW(matchCh)) { if (x->cp != gData->cpend && towupper(*x->cp) == towupper(matchCh)) {
result = x; result = x;
result->cp++; result->cp++;
} }

View file

@ -47,7 +47,7 @@ static BOOL get_func_id(vbdisp_t *This, const WCHAR *name, vbdisp_invoke_type_t
continue; continue;
} }
if(!strcmpiW(This->desc->funcs[i].name, name)) { if(!wcsicmp(This->desc->funcs[i].name, name)) {
*id = i; *id = i;
return TRUE; return TRUE;
} }
@ -67,20 +67,12 @@ HRESULT vbdisp_get_id(vbdisp_t *This, BSTR name, vbdisp_invoke_type_t invoke_typ
if(!search_private && !This->desc->props[i].is_public) if(!search_private && !This->desc->props[i].is_public)
continue; continue;
if(!strcmpiW(This->desc->props[i].name, name)) { if(!wcsicmp(This->desc->props[i].name, name)) {
*id = i + This->desc->func_cnt; *id = i + This->desc->func_cnt;
return S_OK; return S_OK;
} }
} }
if(This->desc->typeinfo) {
HRESULT hres;
hres = ITypeInfo_GetIDsOfNames(This->desc->typeinfo, &name, 1, id);
if(SUCCEEDED(hres))
return S_OK;
}
*id = -1; *id = -1;
return DISP_E_UNKNOWNNAME; return DISP_E_UNKNOWNNAME;
} }
@ -169,83 +161,76 @@ static HRESULT invoke_variant_prop(script_ctx_t *ctx, VARIANT *v, WORD flags, DI
return hres; return hres;
} }
static HRESULT invoke_builtin(vbdisp_t *This, const builtin_prop_t *prop, WORD flags, DISPPARAMS *dp, VARIANT *res) static HRESULT invoke_vbdisp(vbdisp_t *This, DISPID id, DWORD flags, BOOL extern_caller, DISPPARAMS *params, VARIANT *res)
{ {
VARIANT args[8]; if(id < 0)
unsigned argn, i; return DISP_E_MEMBERNOTFOUND;
switch(flags) { if(is_func_id(This, id)) {
case DISPATCH_PROPERTYGET: function_t *func;
if(!(prop->flags & (BP_GET|BP_GETPUT))) {
FIXME("property does not support DISPATCH_PROPERTYGET\n");
return E_FAIL;
}
break;
case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
if(!prop->proc && prop->flags == BP_GET) {
const int vt = prop->min_args, val = prop->max_args;
switch(vt) {
case VT_I2:
V_VT(res) = VT_I2;
V_I2(res) = val;
break;
case VT_I4:
V_VT(res) = VT_I4;
V_I4(res) = val;
break;
case VT_BSTR: {
const string_constant_t *str = (const string_constant_t*)prop->max_args;
BSTR ret;
ret = SysAllocStringLen(str->buf, str->len); TRACE("%p->%s\n", This, debugstr_w(This->desc->funcs[id].name));
if(!ret)
return E_OUTOFMEMORY;
V_VT(res) = VT_BSTR; switch(flags) {
V_BSTR(res) = ret; case DISPATCH_PROPERTYGET:
break; func = This->desc->funcs[id].entries[VBDISP_CALLGET];
if(!func || (func->type != FUNC_PROPGET && func->type != FUNC_DEFGET)) {
WARN("no getter\n");
return DISP_E_MEMBERNOTFOUND;
} }
DEFAULT_UNREACHABLE;
return exec_script(This->desc->ctx, extern_caller, func, This, params, res);
case DISPATCH_METHOD:
case DISPATCH_METHOD|DISPATCH_PROPERTYGET:
func = This->desc->funcs[id].entries[VBDISP_CALLGET];
if(!func) {
FIXME("no invoke/getter\n");
return DISP_E_MEMBERNOTFOUND;
} }
return S_OK;
}
break;
case DISPATCH_METHOD:
if(prop->flags & (BP_GET|BP_GETPUT)) {
FIXME("Call on property\n");
return E_FAIL;
}
break;
case DISPATCH_PROPERTYPUT:
if(!(prop->flags & BP_GETPUT)) {
FIXME("property does not support DISPATCH_PROPERTYPUT\n");
return E_FAIL;
}
FIXME("call put\n"); return exec_script(This->desc->ctx, extern_caller, func, This, params, res);
return E_NOTIMPL;
default: case DISPATCH_PROPERTYPUT:
FIXME("unsupported flags %x\n", flags); case DISPATCH_PROPERTYPUTREF:
return E_NOTIMPL; case DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF: {
DISPPARAMS dp = {NULL, NULL, 1, 0};
BOOL needs_release;
VARIANT put_val;
HRESULT hres;
if(arg_cnt(params)) {
FIXME("arguments not implemented\n");
return E_NOTIMPL;
}
hres = get_propput_arg(This->desc->ctx, params, flags, &put_val, &needs_release);
if(FAILED(hres))
return hres;
dp.rgvarg = &put_val;
func = This->desc->funcs[id].entries[V_VT(&put_val) == VT_DISPATCH ? VBDISP_SET : VBDISP_LET];
if(!func) {
FIXME("no letter/setter\n");
return DISP_E_MEMBERNOTFOUND;
}
hres = exec_script(This->desc->ctx, extern_caller, func, This, &dp, NULL);
if(needs_release)
VariantClear(&put_val);
return hres;
}
default:
FIXME("flags %x\n", flags);
return DISP_E_MEMBERNOTFOUND;
}
} }
argn = arg_cnt(dp); if(id >= This->desc->prop_cnt + This->desc->func_cnt)
return DISP_E_MEMBERNOTFOUND;
if(argn < prop->min_args || argn > (prop->max_args ? prop->max_args : prop->min_args)) { TRACE("%p->%s\n", This, debugstr_w(This->desc->props[id - This->desc->func_cnt].name));
FIXME("invalid number of arguments\n"); return invoke_variant_prop(This->desc->ctx, This->props+(id-This->desc->func_cnt), flags, params, res);
return E_FAIL;
}
assert(argn < ARRAY_SIZE(args));
for(i=0; i < argn; i++) {
if(V_VT(dp->rgvarg+dp->cArgs-i-1) == (VT_BYREF|VT_VARIANT))
args[i] = *V_VARIANTREF(dp->rgvarg+dp->cArgs-i-1);
else
args[i] = dp->rgvarg[dp->cArgs-i-1];
}
return prop->proc(This, args, dp->cArgs, res);
} }
static BOOL run_terminator(vbdisp_t *This) static BOOL run_terminator(vbdisp_t *This)
@ -260,7 +245,7 @@ static BOOL run_terminator(vbdisp_t *This)
return TRUE; return TRUE;
This->ref++; This->ref++;
exec_script(This->desc->ctx, This->desc->funcs[This->desc->class_terminate_id].entries[VBDISP_CALLGET], exec_script(This->desc->ctx, FALSE, This->desc->funcs[This->desc->class_terminate_id].entries[VBDISP_CALLGET],
This, &dp, NULL); This, &dp, NULL);
return !--This->ref; return !--This->ref;
} }
@ -412,84 +397,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
if(pvarRes) if(pvarRes)
V_VT(pvarRes) = VT_EMPTY; V_VT(pvarRes) = VT_EMPTY;
if(id < 0) return invoke_vbdisp(This, id, wFlags, TRUE, pdp, pvarRes);
return DISP_E_MEMBERNOTFOUND;
if(is_func_id(This, id)) {
function_t *func;
switch(wFlags) {
case DISPATCH_PROPERTYGET:
func = This->desc->funcs[id].entries[VBDISP_CALLGET];
if(!func || (func->type != FUNC_PROPGET && func->type != FUNC_DEFGET)) {
WARN("no getter\n");
return DISP_E_MEMBERNOTFOUND;
}
return exec_script(This->desc->ctx, func, This, pdp, pvarRes);
case DISPATCH_METHOD:
case DISPATCH_METHOD|DISPATCH_PROPERTYGET:
func = This->desc->funcs[id].entries[VBDISP_CALLGET];
if(!func) {
FIXME("no invoke/getter\n");
return DISP_E_MEMBERNOTFOUND;
}
return exec_script(This->desc->ctx, func, This, pdp, pvarRes);
case DISPATCH_PROPERTYPUT:
case DISPATCH_PROPERTYPUTREF:
case DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF: {
DISPPARAMS dp = {NULL, NULL, 1, 0};
BOOL needs_release;
VARIANT put_val;
HRESULT hres;
if(arg_cnt(pdp)) {
FIXME("arguments not implemented\n");
return E_NOTIMPL;
}
hres = get_propput_arg(This->desc->ctx, pdp, wFlags, &put_val, &needs_release);
if(FAILED(hres))
return hres;
dp.rgvarg = &put_val;
func = This->desc->funcs[id].entries[V_VT(&put_val) == VT_DISPATCH ? VBDISP_SET : VBDISP_LET];
if(!func) {
FIXME("no letter/setter\n");
return DISP_E_MEMBERNOTFOUND;
}
hres = exec_script(This->desc->ctx, func, This, &dp, NULL);
if(needs_release)
VariantClear(&put_val);
return hres;
}
default:
FIXME("flags %x\n", wFlags);
return DISP_E_MEMBERNOTFOUND;
}
}
if(id < This->desc->prop_cnt + This->desc->func_cnt)
return invoke_variant_prop(This->desc->ctx, This->props+(id-This->desc->func_cnt), wFlags, pdp, pvarRes);
if(This->desc->builtin_prop_cnt) {
unsigned min = 0, max = This->desc->builtin_prop_cnt-1, i;
while(min <= max) {
i = (min+max)/2;
if(This->desc->builtin_props[i].id == id)
return invoke_builtin(This, This->desc->builtin_props+i, wFlags, pdp, pvarRes);
if(This->desc->builtin_props[i].id < id)
min = i+1;
else
max = i-1;
}
}
return DISP_E_MEMBERNOTFOUND;
} }
static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
@ -605,7 +513,7 @@ HRESULT create_vbdisp(const class_desc_t *desc, vbdisp_t **ret)
if(SUCCEEDED(hres) && desc->class_initialize_id) { if(SUCCEEDED(hres) && desc->class_initialize_id) {
DISPPARAMS dp = {0}; DISPPARAMS dp = {0};
hres = exec_script(desc->ctx, desc->funcs[desc->class_initialize_id].entries[VBDISP_CALLGET], hres = exec_script(desc->ctx, FALSE, desc->funcs[desc->class_initialize_id].entries[VBDISP_CALLGET],
vbdisp, &dp, NULL); vbdisp, &dp, NULL);
} }
@ -618,52 +526,6 @@ HRESULT create_vbdisp(const class_desc_t *desc, vbdisp_t **ret)
return S_OK; return S_OK;
} }
static HRESULT Procedure_invoke(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
{
script_ctx_t *ctx = This->desc->ctx;
HRESULT hres;
TRACE("\n");
IActiveScriptSite_OnEnterScript(ctx->site);
hres = exec_script(ctx, This->desc->value_func, NULL, NULL, NULL);
IActiveScriptSite_OnLeaveScript(ctx->site);
return hres;
}
static const builtin_prop_t procedure_props[] = {
{DISPID_VALUE, Procedure_invoke, 0}
};
HRESULT create_procedure_disp(script_ctx_t *ctx, vbscode_t *code, IDispatch **ret)
{
class_desc_t *desc;
vbdisp_t *vbdisp;
HRESULT hres;
desc = heap_alloc_zero(sizeof(*desc));
if(!desc)
return E_OUTOFMEMORY;
desc->ctx = ctx;
desc->builtin_prop_cnt = ARRAY_SIZE(procedure_props);
desc->builtin_props = procedure_props;
desc->value_func = &code->main_code;
hres = create_vbdisp(desc, &vbdisp);
if(FAILED(hres)) {
heap_free(desc);
return hres;
}
desc->next = ctx->procs;
ctx->procs = desc;
*ret = (IDispatch*)&vbdisp->IDispatchEx_iface;
return S_OK;
}
struct _ident_map_t { struct _ident_map_t {
const WCHAR *name; const WCHAR *name;
BOOL is_var; BOOL is_var;
@ -823,14 +685,14 @@ static HRESULT WINAPI ScriptDisp_GetDispID(IDispatchEx *iface, BSTR bstrName, DW
return E_UNEXPECTED; return E_UNEXPECTED;
for(ident = This->ident_map; ident < This->ident_map+This->ident_map_cnt; ident++) { for(ident = This->ident_map; ident < This->ident_map+This->ident_map_cnt; ident++) {
if(!strcmpiW(ident->name, bstrName)) { if(!wcsicmp(ident->name, bstrName)) {
*pid = ident_to_id(This, ident); *pid = ident_to_id(This, ident);
return S_OK; return S_OK;
} }
} }
for(var = This->ctx->global_vars; var; var = var->next) { for(var = This->ctx->global_vars; var; var = var->next) {
if(!strcmpiW(var->name, bstrName)) { if(!wcsicmp(var->name, bstrName)) {
ident = add_ident(This, var->name); ident = add_ident(This, var->name);
if(!ident) if(!ident)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
@ -843,7 +705,7 @@ static HRESULT WINAPI ScriptDisp_GetDispID(IDispatchEx *iface, BSTR bstrName, DW
} }
for(func = This->ctx->global_funcs; func; func = func->next) { for(func = This->ctx->global_funcs; func; func = func->next) {
if(!strcmpiW(func->name, bstrName)) { if(!wcsicmp(func->name, bstrName)) {
ident = add_ident(This, func->name); ident = add_ident(This, func->name);
if(!ident) if(!ident)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
@ -884,9 +746,7 @@ static HRESULT WINAPI ScriptDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
switch(wFlags) { switch(wFlags) {
case DISPATCH_METHOD: case DISPATCH_METHOD:
case DISPATCH_METHOD|DISPATCH_PROPERTYGET: case DISPATCH_METHOD|DISPATCH_PROPERTYGET:
IActiveScriptSite_OnEnterScript(This->ctx->site); hres = exec_script(This->ctx, TRUE, ident->u.func, NULL, pdp, pvarRes);
hres = exec_script(This->ctx, ident->u.func, NULL, pdp, pvarRes);
IActiveScriptSite_OnLeaveScript(This->ctx->site);
break; break;
default: default:
FIXME("Unsupported flags %x\n", wFlags); FIXME("Unsupported flags %x\n", wFlags);
@ -1079,6 +939,7 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, DISPPARAMS *dp,
{ {
const WORD flags = DISPATCH_METHOD|(retv ? DISPATCH_PROPERTYGET : 0); const WORD flags = DISPATCH_METHOD|(retv ? DISPATCH_PROPERTYGET : 0);
IDispatchEx *dispex; IDispatchEx *dispex;
vbdisp_t *vbdisp;
EXCEPINFO ei; EXCEPINFO ei;
HRESULT hres; HRESULT hres;
@ -1086,6 +947,10 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, DISPPARAMS *dp,
if(retv) if(retv)
V_VT(retv) = VT_EMPTY; V_VT(retv) = VT_EMPTY;
vbdisp = unsafe_impl_from_IDispatch(disp);
if(vbdisp && vbdisp->desc && vbdisp->desc->ctx == ctx)
return invoke_vbdisp(vbdisp, id, flags, FALSE, dp, retv);
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
if(FAILED(hres)) { if(FAILED(hres)) {
UINT err = 0; UINT err = 0;
@ -1102,15 +967,22 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, DISPPARAMS *dp,
HRESULT get_disp_value(script_ctx_t *ctx, IDispatch *disp, VARIANT *v) HRESULT get_disp_value(script_ctx_t *ctx, IDispatch *disp, VARIANT *v)
{ {
DISPPARAMS dp = {NULL}; DISPPARAMS dp = {NULL};
if(!disp)
return MAKE_VBSERROR(VBSE_OBJECT_VARIABLE_NOT_SET);
return disp_call(ctx, disp, DISPID_VALUE, &dp, v); return disp_call(ctx, disp, DISPID_VALUE, &dp, v);
} }
HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, DISPPARAMS *dp) HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, DISPPARAMS *dp)
{ {
IDispatchEx *dispex; IDispatchEx *dispex;
vbdisp_t *vbdisp;
EXCEPINFO ei = {0}; EXCEPINFO ei = {0};
HRESULT hres; HRESULT hres;
vbdisp = unsafe_impl_from_IDispatch(disp);
if(vbdisp && vbdisp->desc && vbdisp->desc->ctx == ctx)
return invoke_vbdisp(vbdisp, id, flags, FALSE, dp, NULL);
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
if(SUCCEEDED(hres)) { if(SUCCEEDED(hres)) {
hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, dp, NULL, &ei, NULL /* FIXME! */); hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, dp, NULL, &ei, NULL /* FIXME! */);

View file

@ -1335,7 +1335,7 @@ static HRESULT WINAPI RegExp2_Execute(IRegExp2 *iface,
if(!This->regexp) { if(!This->regexp) {
This->regexp = regexp_new(NULL, &This->pool, This->pattern, This->regexp = regexp_new(NULL, &This->pool, This->pattern,
strlenW(This->pattern), This->flags, FALSE); lstrlenW(This->pattern), This->flags, FALSE);
if(!This->regexp) if(!This->regexp)
return E_FAIL; return E_FAIL;
}else { }else {
@ -1402,7 +1402,7 @@ static HRESULT WINAPI RegExp2_Test(IRegExp2 *iface, BSTR sourceString, VARIANT_B
if(!This->regexp) { if(!This->regexp) {
This->regexp = regexp_new(NULL, &This->pool, This->pattern, This->regexp = regexp_new(NULL, &This->pool, This->pattern,
strlenW(This->pattern), This->flags, FALSE); lstrlenW(This->pattern), This->flags, FALSE);
if(!This->regexp) if(!This->regexp)
return E_FAIL; return E_FAIL;
}else { }else {

View file

@ -51,22 +51,26 @@ struct VBScript {
LONG ref; LONG ref;
DWORD safeopt;
SCRIPTSTATE state; SCRIPTSTATE state;
IActiveScriptSite *site;
script_ctx_t *ctx; script_ctx_t *ctx;
LONG thread_id; LONG thread_id;
LCID lcid; BOOL is_initialized;
}; };
typedef struct {
IActiveScriptError IActiveScriptError_iface;
LONG ref;
EXCEPINFO ei;
} VBScriptError;
static void change_state(VBScript *This, SCRIPTSTATE state) static void change_state(VBScript *This, SCRIPTSTATE state)
{ {
if(This->state == state) if(This->state == state)
return; return;
This->state = state; This->state = state;
if(This->site) if(This->ctx->site)
IActiveScriptSite_OnStateChange(This->site, state); IActiveScriptSite_OnStateChange(This->ctx->site, state);
} }
static inline BOOL is_started(VBScript *This) static inline BOOL is_started(VBScript *This)
@ -76,17 +80,10 @@ static inline BOOL is_started(VBScript *This)
|| This->state == SCRIPTSTATE_DISCONNECTED; || This->state == SCRIPTSTATE_DISCONNECTED;
} }
static HRESULT exec_global_code(script_ctx_t *ctx, vbscode_t *code) static HRESULT exec_global_code(script_ctx_t *ctx, vbscode_t *code, VARIANT *res)
{ {
HRESULT hres;
code->pending_exec = FALSE; code->pending_exec = FALSE;
return exec_script(ctx, TRUE, &code->main_code, NULL, NULL, res);
IActiveScriptSite_OnEnterScript(ctx->site);
hres = exec_script(ctx, &code->main_code, NULL, NULL, NULL);
IActiveScriptSite_OnLeaveScript(ctx->site);
return hres;
} }
static void exec_queued_code(script_ctx_t *ctx) static void exec_queued_code(script_ctx_t *ctx)
@ -95,7 +92,7 @@ static void exec_queued_code(script_ctx_t *ctx)
LIST_FOR_EACH_ENTRY(iter, &ctx->code_list, vbscode_t, entry) { LIST_FOR_EACH_ENTRY(iter, &ctx->code_list, vbscode_t, entry) {
if(iter->pending_exec) if(iter->pending_exec)
exec_global_code(ctx, iter); exec_global_code(ctx, iter, NULL);
} }
} }
@ -105,7 +102,7 @@ IDispatch *lookup_named_item(script_ctx_t *ctx, const WCHAR *name, unsigned flag
HRESULT hres; HRESULT hres;
LIST_FOR_EACH_ENTRY(item, &ctx->named_items, named_item_t, entry) { LIST_FOR_EACH_ENTRY(item, &ctx->named_items, named_item_t, entry) {
if((item->flags & flags) == flags && !strcmpiW(item->name, name)) { if((item->flags & flags) == flags && !wcsicmp(item->name, name)) {
if(!item->disp) { if(!item->disp) {
IUnknown *unk; IUnknown *unk;
@ -131,28 +128,12 @@ IDispatch *lookup_named_item(script_ctx_t *ctx, const WCHAR *name, unsigned flag
return NULL; return NULL;
} }
static HRESULT set_ctx_site(VBScript *This)
{
HRESULT hres;
This->ctx->lcid = This->lcid;
hres = init_global(This->ctx);
if(FAILED(hres))
return hres;
IActiveScriptSite_AddRef(This->site);
This->ctx->site = This->site;
change_state(This, SCRIPTSTATE_INITIALIZED);
return S_OK;
}
static void release_script(script_ctx_t *ctx) static void release_script(script_ctx_t *ctx)
{ {
class_desc_t *class_desc; class_desc_t *class_desc;
collect_objects(ctx); collect_objects(ctx);
clear_ei(&ctx->ei);
release_dynamic_vars(ctx->global_vars); release_dynamic_vars(ctx->global_vars);
ctx->global_vars = NULL; ctx->global_vars = NULL;
@ -189,16 +170,6 @@ static void release_script(script_ctx_t *ctx)
ctx->site = NULL; ctx->site = NULL;
} }
if(ctx->err_obj) {
IDispatchEx_Release(&ctx->err_obj->IDispatchEx_iface);
ctx->err_obj = NULL;
}
if(ctx->global_obj) {
IDispatchEx_Release(&ctx->global_obj->IDispatchEx_iface);
ctx->global_obj = NULL;
}
if(ctx->script_obj) { if(ctx->script_obj) {
ScriptDisp *script_obj = ctx->script_obj; ScriptDisp *script_obj = ctx->script_obj;
@ -207,6 +178,7 @@ static void release_script(script_ctx_t *ctx)
IDispatchEx_Release(&script_obj->IDispatchEx_iface); IDispatchEx_Release(&script_obj->IDispatchEx_iface);
} }
detach_global_objects(ctx);
heap_pool_free(&ctx->heap); heap_pool_free(&ctx->heap);
heap_pool_init(&ctx->heap); heap_pool_init(&ctx->heap);
} }
@ -238,15 +210,7 @@ static void decrease_state(VBScript *This, SCRIPTSTATE state)
case SCRIPTSTATE_INITIALIZED: case SCRIPTSTATE_INITIALIZED:
case SCRIPTSTATE_UNINITIALIZED: case SCRIPTSTATE_UNINITIALIZED:
change_state(This, state); change_state(This, state);
release_script(This->ctx);
if(This->site) {
IActiveScriptSite_Release(This->site);
This->site = NULL;
}
if(This->ctx)
release_script(This->ctx);
This->thread_id = 0; This->thread_id = 0;
break; break;
case SCRIPTSTATE_CLOSED: case SCRIPTSTATE_CLOSED:
@ -255,6 +219,118 @@ static void decrease_state(VBScript *This, SCRIPTSTATE state)
} }
} }
static inline VBScriptError *impl_from_IActiveScriptError(IActiveScriptError *iface)
{
return CONTAINING_RECORD(iface, VBScriptError, IActiveScriptError_iface);
}
static HRESULT WINAPI VBScriptError_QueryInterface(IActiveScriptError *iface, REFIID riid, void **ppv)
{
VBScriptError *This = impl_from_IActiveScriptError(iface);
if(IsEqualGUID(riid, &IID_IUnknown)) {
TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
*ppv = &This->IActiveScriptError_iface;
}else if(IsEqualGUID(riid, &IID_IActiveScriptError)) {
TRACE("(%p)->(IID_IActiveScriptError %p)\n", This, ppv);
*ppv = &This->IActiveScriptError_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 VBScriptError_AddRef(IActiveScriptError *iface)
{
VBScriptError *This = impl_from_IActiveScriptError(iface);
LONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
return ref;
}
static ULONG WINAPI VBScriptError_Release(IActiveScriptError *iface)
{
VBScriptError *This = impl_from_IActiveScriptError(iface);
LONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
if(!ref) {
heap_free(This);
}
return ref;
}
static HRESULT WINAPI VBScriptError_GetExceptionInfo(IActiveScriptError *iface, EXCEPINFO *excepinfo)
{
VBScriptError *This = impl_from_IActiveScriptError(iface);
TRACE("(%p)->(%p)\n", This, excepinfo);
*excepinfo = This->ei;
excepinfo->bstrSource = SysAllocString(This->ei.bstrSource);
excepinfo->bstrDescription = SysAllocString(This->ei.bstrDescription);
excepinfo->bstrHelpFile = SysAllocString(This->ei.bstrHelpFile);
return S_OK;
}
static HRESULT WINAPI VBScriptError_GetSourcePosition(IActiveScriptError *iface, DWORD *source_context, ULONG *line, LONG *character)
{
VBScriptError *This = impl_from_IActiveScriptError(iface);
FIXME("(%p)->(%p %p %p)\n", This, source_context, line, character);
if(source_context)
*source_context = 0;
if(line)
*line = 0;
if(character)
*character = 0;
return S_OK;
}
static HRESULT WINAPI VBScriptError_GetSourceLineText(IActiveScriptError *iface, BSTR *source)
{
VBScriptError *This = impl_from_IActiveScriptError(iface);
FIXME("(%p)->(%p)\n", This, source);
return E_NOTIMPL;
}
static const IActiveScriptErrorVtbl VBScriptErrorVtbl = {
VBScriptError_QueryInterface,
VBScriptError_AddRef,
VBScriptError_Release,
VBScriptError_GetExceptionInfo,
VBScriptError_GetSourcePosition,
VBScriptError_GetSourceLineText
};
HRESULT report_script_error(script_ctx_t *ctx)
{
VBScriptError *error;
HRESULT hres, result;
if(!(error = heap_alloc(sizeof(*error))))
return E_OUTOFMEMORY;
error->IActiveScriptError_iface.lpVtbl = &VBScriptErrorVtbl;
error->ref = 1;
error->ei = ctx->ei;
memset(&ctx->ei, 0, sizeof(ctx->ei));
result = error->ei.scode;
hres = IActiveScriptSite_OnScriptError(ctx->site, &error->IActiveScriptError_iface);
IActiveScriptError_Release(&error->IActiveScriptError_iface);
return hres == S_OK ? SCRIPT_E_REPORTED : result;
}
static inline VBScript *impl_from_IActiveScript(IActiveScript *iface) static inline VBScript *impl_from_IActiveScript(IActiveScript *iface)
{ {
return CONTAINING_RECORD(iface, VBScript, IActiveScript_iface); return CONTAINING_RECORD(iface, VBScript, IActiveScript_iface);
@ -310,13 +386,8 @@ static ULONG WINAPI VBScript_Release(IActiveScript *iface)
TRACE("(%p) ref=%d\n", iface, ref); TRACE("(%p) ref=%d\n", iface, ref);
if(!ref) { if(!ref) {
if(This->ctx) { decrease_state(This, SCRIPTSTATE_CLOSED);
decrease_state(This, SCRIPTSTATE_CLOSED); destroy_script(This->ctx);
destroy_script(This->ctx);
This->ctx = NULL;
}
if(This->site)
IActiveScriptSite_Release(This->site);
heap_free(This); heap_free(This);
} }
@ -334,20 +405,26 @@ static HRESULT WINAPI VBScript_SetScriptSite(IActiveScript *iface, IActiveScript
if(!pass) if(!pass)
return E_POINTER; return E_POINTER;
if(This->site) if(This->ctx->site)
return E_UNEXPECTED; return E_UNEXPECTED;
if(InterlockedCompareExchange(&This->thread_id, GetCurrentThreadId(), 0)) if(InterlockedCompareExchange(&This->thread_id, GetCurrentThreadId(), 0))
return E_UNEXPECTED; return E_UNEXPECTED;
This->site = pass; hres = create_script_disp(This->ctx, &This->ctx->script_obj);
IActiveScriptSite_AddRef(This->site); if(FAILED(hres))
return hres;
hres = IActiveScriptSite_GetLCID(This->site, &lcid); This->ctx->site = pass;
IActiveScriptSite_AddRef(This->ctx->site);
hres = IActiveScriptSite_GetLCID(This->ctx->site, &lcid);
if(hres == S_OK) if(hres == S_OK)
This->lcid = lcid; This->ctx->lcid = lcid;
return This->ctx ? set_ctx_site(This) : S_OK; if(This->is_initialized)
change_state(This, SCRIPTSTATE_INITIALIZED);
return S_OK;
} }
static HRESULT WINAPI VBScript_GetScriptSite(IActiveScript *iface, REFIID riid, static HRESULT WINAPI VBScript_GetScriptSite(IActiveScript *iface, REFIID riid,
@ -375,7 +452,7 @@ static HRESULT WINAPI VBScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE
return S_OK; return S_OK;
} }
if(!This->ctx) if(!This->is_initialized)
return E_UNEXPECTED; return E_UNEXPECTED;
switch(ss) { switch(ss) {
@ -439,13 +516,13 @@ static HRESULT WINAPI VBScript_AddNamedItem(IActiveScript *iface, LPCOLESTR pstr
TRACE("(%p)->(%s %x)\n", This, debugstr_w(pstrName), dwFlags); TRACE("(%p)->(%s %x)\n", This, debugstr_w(pstrName), dwFlags);
if(This->thread_id != GetCurrentThreadId() || !This->ctx || This->state == SCRIPTSTATE_CLOSED) if(This->thread_id != GetCurrentThreadId() || !This->ctx->site)
return E_UNEXPECTED; return E_UNEXPECTED;
if(dwFlags & SCRIPTITEM_GLOBALMEMBERS) { if(dwFlags & SCRIPTITEM_GLOBALMEMBERS) {
IUnknown *unk; IUnknown *unk;
hres = IActiveScriptSite_GetItemInfo(This->site, pstrName, SCRIPTINFO_IUNKNOWN, &unk, NULL); hres = IActiveScriptSite_GetItemInfo(This->ctx->site, pstrName, SCRIPTINFO_IUNKNOWN, &unk, NULL);
if(FAILED(hres)) { if(FAILED(hres)) {
WARN("GetItemInfo failed: %08x\n", hres); WARN("GetItemInfo failed: %08x\n", hres);
return hres; return hres;
@ -502,7 +579,7 @@ static HRESULT WINAPI VBScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR
if(!ppdisp) if(!ppdisp)
return E_POINTER; return E_POINTER;
if(This->thread_id != GetCurrentThreadId() || !This->ctx || !This->ctx->script_obj) { if(This->thread_id != GetCurrentThreadId() || !This->ctx->script_obj) {
*ppdisp = NULL; *ppdisp = NULL;
return E_UNEXPECTED; return E_UNEXPECTED;
} }
@ -654,30 +731,16 @@ static ULONG WINAPI VBScriptParse_Release(IActiveScriptParse *iface)
static HRESULT WINAPI VBScriptParse_InitNew(IActiveScriptParse *iface) static HRESULT WINAPI VBScriptParse_InitNew(IActiveScriptParse *iface)
{ {
VBScript *This = impl_from_IActiveScriptParse(iface); VBScript *This = impl_from_IActiveScriptParse(iface);
script_ctx_t *ctx, *old_ctx;
TRACE("(%p)\n", This); TRACE("(%p)\n", This);
if(This->ctx) if(This->is_initialized)
return E_UNEXPECTED; return E_UNEXPECTED;
This->is_initialized = TRUE;
ctx = heap_alloc_zero(sizeof(script_ctx_t)); if(This->ctx->site)
if(!ctx) change_state(This, SCRIPTSTATE_INITIALIZED);
return E_OUTOFMEMORY; return S_OK;
ctx->safeopt = This->safeopt;
heap_pool_init(&ctx->heap);
list_init(&ctx->objects);
list_init(&ctx->code_list);
list_init(&ctx->named_items);
old_ctx = InterlockedCompareExchangePointer((void**)&This->ctx, ctx, NULL);
if(old_ctx) {
destroy_script(ctx);
return E_UNEXPECTED;
}
return This->site ? set_ctx_site(This) : S_OK;
} }
static HRESULT WINAPI VBScriptParse_AddScriptlet(IActiveScriptParse *iface, static HRESULT WINAPI VBScriptParse_AddScriptlet(IActiveScriptParse *iface,
@ -719,19 +782,19 @@ static HRESULT WINAPI VBScriptParse_ParseScriptText(IActiveScriptParse *iface,
} }
} }
hres = compile_script(This->ctx, pstrCode, pstrDelimiter, &code); hres = compile_script(This->ctx, pstrCode, pstrDelimiter, dwFlags, &code);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
if(context) if(context)
IDispatch_AddRef(code->context = context); IDispatch_AddRef(code->context = context);
if(!is_started(This)) { if(!(dwFlags & SCRIPTTEXT_ISEXPRESSION) && !is_started(This)) {
code->pending_exec = TRUE; code->pending_exec = TRUE;
return S_OK; return S_OK;
} }
return exec_global_code(This->ctx, code); return exec_global_code(This->ctx, code, pvarResult);
} }
static const IActiveScriptParseVtbl VBScriptParseVtbl = { static const IActiveScriptParseVtbl VBScriptParseVtbl = {
@ -772,7 +835,8 @@ static HRESULT WINAPI VBScriptParseProcedure_ParseProcedureText(IActiveScriptPar
CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp) CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp)
{ {
VBScript *This = impl_from_IActiveScriptParseProcedure2(iface); VBScript *This = impl_from_IActiveScriptParseProcedure2(iface);
vbscode_t *code; class_desc_t *desc;
vbdisp_t *vbdisp;
HRESULT hres; HRESULT hres;
TRACE("(%p)->(%s %s %s %s %p %s %s %u %x %p)\n", This, debugstr_w(pstrCode), debugstr_w(pstrFormalParams), TRACE("(%p)->(%s %s %s %s %p %s %s %u %x %p)\n", This, debugstr_w(pstrCode), debugstr_w(pstrFormalParams),
@ -782,11 +846,16 @@ static HRESULT WINAPI VBScriptParseProcedure_ParseProcedureText(IActiveScriptPar
if(This->thread_id != GetCurrentThreadId() || This->state == SCRIPTSTATE_CLOSED) if(This->thread_id != GetCurrentThreadId() || This->state == SCRIPTSTATE_CLOSED)
return E_UNEXPECTED; return E_UNEXPECTED;
hres = compile_script(This->ctx, pstrCode, pstrDelimiter, &code); hres = compile_procedure(This->ctx, pstrCode, pstrDelimiter, dwFlags, &desc);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
return create_procedure_disp(This->ctx, code, ppdisp); hres = create_vbdisp(desc, &vbdisp);
if(FAILED(hres))
return hres;
*ppdisp = (IDispatch*)&vbdisp->IDispatchEx_iface;
return S_OK;
} }
static const IActiveScriptParseProcedure2Vtbl VBScriptParseProcedureVtbl = { static const IActiveScriptParseProcedure2Vtbl VBScriptParseProcedureVtbl = {
@ -832,7 +901,7 @@ static HRESULT WINAPI VBScriptSafety_GetInterfaceSafetyOptions(IObjectSafety *if
return E_POINTER; return E_POINTER;
*pdwSupportedOptions = SUPPORTED_OPTIONS; *pdwSupportedOptions = SUPPORTED_OPTIONS;
*pdwEnabledOptions = This->safeopt; *pdwEnabledOptions = This->ctx->safeopt;
return S_OK; return S_OK;
} }
@ -846,7 +915,7 @@ static HRESULT WINAPI VBScriptSafety_SetInterfaceSafetyOptions(IObjectSafety *if
if(dwOptionSetMask & ~SUPPORTED_OPTIONS) if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
return E_FAIL; return E_FAIL;
This->safeopt = (dwEnabledOptions & dwOptionSetMask) | (This->safeopt & ~dwOptionSetMask) | INTERFACE_USES_DISPEX; This->ctx->safeopt = (dwEnabledOptions & dwOptionSetMask) | (This->ctx->safeopt & ~dwOptionSetMask) | INTERFACE_USES_DISPEX;
return S_OK; return S_OK;
} }
@ -860,6 +929,7 @@ static const IObjectSafetyVtbl VBScriptSafetyVtbl = {
HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter, REFIID riid, void **ppv) HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter, REFIID riid, void **ppv)
{ {
script_ctx_t *ctx;
VBScript *ret; VBScript *ret;
HRESULT hres; HRESULT hres;
@ -877,7 +947,24 @@ HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pU
ret->ref = 1; ret->ref = 1;
ret->state = SCRIPTSTATE_UNINITIALIZED; ret->state = SCRIPTSTATE_UNINITIALIZED;
ret->safeopt = INTERFACE_USES_DISPEX;
ctx = ret->ctx = heap_alloc_zero(sizeof(*ctx));
if(!ctx) {
heap_free(ret);
return E_OUTOFMEMORY;
}
ctx->safeopt = INTERFACE_USES_DISPEX;
heap_pool_init(&ctx->heap);
list_init(&ctx->objects);
list_init(&ctx->code_list);
list_init(&ctx->named_items);
hres = init_global(ctx);
if(FAILED(hres)) {
IActiveScript_Release(&ret->IActiveScript_iface);
return hres;
}
hres = IActiveScript_QueryInterface(&ret->IActiveScript_iface, riid, ppv); hres = IActiveScript_QueryInterface(&ret->IActiveScript_iface, riid, ppv);
IActiveScript_Release(&ret->IActiveScript_iface); IActiveScript_Release(&ret->IActiveScript_iface);

View file

@ -19,6 +19,7 @@
#pragma once #pragma once
#include <stdarg.h> #include <stdarg.h>
#include <stdint.h>
#define COBJMACROS #define COBJMACROS
@ -33,10 +34,10 @@
#include <initguid.h> #include <initguid.h>
#endif #endif
#include "vbscript_classes.h" #include "vbscript_classes.h"
#include "vbscript_defs.h"
#include "wine/heap.h" #include "wine/heap.h"
#include "wine/list.h" #include "wine/list.h"
#include "wine/unicode.h"
typedef struct { typedef struct {
void **blocks; void **blocks;
@ -92,17 +93,6 @@ typedef struct {
function_t *entries[VBDISP_ANY]; function_t *entries[VBDISP_ANY];
} vbdisp_funcprop_desc_t; } vbdisp_funcprop_desc_t;
#define BP_GET 1
#define BP_GETPUT 2
typedef struct {
DISPID id;
HRESULT (*proc)(vbdisp_t*,VARIANT*,unsigned,VARIANT*);
DWORD flags;
unsigned min_args;
UINT_PTR max_args;
} builtin_prop_t;
typedef struct _class_desc_t { typedef struct _class_desc_t {
const WCHAR *name; const WCHAR *name;
script_ctx_t *ctx; script_ctx_t *ctx;
@ -118,9 +108,6 @@ typedef struct _class_desc_t {
unsigned array_cnt; unsigned array_cnt;
array_desc_t *array_descs; array_desc_t *array_descs;
unsigned builtin_prop_cnt;
const builtin_prop_t *builtin_props;
ITypeInfo *typeinfo;
function_t *value_func; function_t *value_func;
struct _class_desc_t *next; struct _class_desc_t *next;
@ -151,6 +138,16 @@ typedef struct {
script_ctx_t *ctx; script_ctx_t *ctx;
} ScriptDisp; } ScriptDisp;
typedef struct _builtin_prop_t builtin_prop_t;
typedef struct {
IDispatch IDispatch_iface;
LONG ref;
size_t member_cnt;
const builtin_prop_t *members;
script_ctx_t *ctx;
} BuiltinDisp;
HRESULT create_vbdisp(const class_desc_t*,vbdisp_t**) DECLSPEC_HIDDEN; HRESULT create_vbdisp(const class_desc_t*,vbdisp_t**) DECLSPEC_HIDDEN;
HRESULT disp_get_id(IDispatch*,BSTR,vbdisp_invoke_type_t,BOOL,DISPID*) DECLSPEC_HIDDEN; HRESULT disp_get_id(IDispatch*,BSTR,vbdisp_invoke_type_t,BOOL,DISPID*) DECLSPEC_HIDDEN;
HRESULT vbdisp_get_id(vbdisp_t*,BSTR,vbdisp_invoke_type_t,BOOL,DISPID*) DECLSPEC_HIDDEN; HRESULT vbdisp_get_id(vbdisp_t*,BSTR,vbdisp_invoke_type_t,BOOL,DISPID*) DECLSPEC_HIDDEN;
@ -158,7 +155,6 @@ HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,DISPPARAMS*,VARIANT*) DECLSPEC
HRESULT disp_propput(script_ctx_t*,IDispatch*,DISPID,WORD,DISPPARAMS*) DECLSPEC_HIDDEN; HRESULT disp_propput(script_ctx_t*,IDispatch*,DISPID,WORD,DISPPARAMS*) DECLSPEC_HIDDEN;
HRESULT get_disp_value(script_ctx_t*,IDispatch*,VARIANT*) DECLSPEC_HIDDEN; HRESULT get_disp_value(script_ctx_t*,IDispatch*,VARIANT*) DECLSPEC_HIDDEN;
void collect_objects(script_ctx_t*) DECLSPEC_HIDDEN; void collect_objects(script_ctx_t*) DECLSPEC_HIDDEN;
HRESULT create_procedure_disp(script_ctx_t*,vbscode_t*,IDispatch**) DECLSPEC_HIDDEN;
HRESULT create_script_disp(script_ctx_t*,ScriptDisp**) DECLSPEC_HIDDEN; HRESULT create_script_disp(script_ctx_t*,ScriptDisp**) DECLSPEC_HIDDEN;
HRESULT to_int(VARIANT*,int*) DECLSPEC_HIDDEN; HRESULT to_int(VARIANT*,int*) DECLSPEC_HIDDEN;
@ -191,13 +187,10 @@ struct _script_ctx_t {
ScriptDisp *script_obj; ScriptDisp *script_obj;
class_desc_t global_desc; BuiltinDisp *global_obj;
vbdisp_t *global_obj; BuiltinDisp *err_obj;
class_desc_t err_desc; EXCEPINFO ei;
vbdisp_t *err_obj;
HRESULT err_number;
dynamic_var_t *global_vars; dynamic_var_t *global_vars;
function_t *global_funcs; function_t *global_funcs;
@ -253,11 +246,11 @@ typedef enum {
X(idiv, 1, 0, 0) \ X(idiv, 1, 0, 0) \
X(imp, 1, 0, 0) \ X(imp, 1, 0, 0) \
X(incc, 1, ARG_BSTR, 0) \ X(incc, 1, ARG_BSTR, 0) \
X(int, 1, ARG_INT, 0) \
X(is, 1, 0, 0) \ X(is, 1, 0, 0) \
X(jmp, 0, ARG_ADDR, 0) \ X(jmp, 0, ARG_ADDR, 0) \
X(jmp_false, 0, ARG_ADDR, 0) \ X(jmp_false, 0, ARG_ADDR, 0) \
X(jmp_true, 0, ARG_ADDR, 0) \ X(jmp_true, 0, ARG_ADDR, 0) \
X(long, 1, ARG_INT, 0) \
X(lt, 1, 0, 0) \ X(lt, 1, 0, 0) \
X(lteq, 1, 0, 0) \ X(lteq, 1, 0, 0) \
X(mcall, 1, ARG_BSTR, ARG_UINT) \ X(mcall, 1, ARG_BSTR, ARG_UINT) \
@ -275,9 +268,9 @@ typedef enum {
X(or, 1, 0, 0) \ X(or, 1, 0, 0) \
X(pop, 1, ARG_UINT, 0) \ X(pop, 1, ARG_UINT, 0) \
X(ret, 0, 0, 0) \ X(ret, 0, 0, 0) \
X(retval, 1, 0, 0) \
X(set_ident, 1, ARG_BSTR, ARG_UINT) \ X(set_ident, 1, ARG_BSTR, ARG_UINT) \
X(set_member, 1, ARG_BSTR, ARG_UINT) \ X(set_member, 1, ARG_BSTR, ARG_UINT) \
X(short, 1, ARG_INT, 0) \
X(step, 0, ARG_ADDR, ARG_BSTR) \ X(step, 0, ARG_ADDR, ARG_BSTR) \
X(stop, 1, 0, 0) \ X(stop, 1, 0, 0) \
X(string, 1, ARG_STR, 0) \ X(string, 1, ARG_STR, 0) \
@ -359,38 +352,18 @@ struct _vbscode_t {
}; };
void release_vbscode(vbscode_t*) DECLSPEC_HIDDEN; void release_vbscode(vbscode_t*) DECLSPEC_HIDDEN;
HRESULT compile_script(script_ctx_t*,const WCHAR*,const WCHAR*,vbscode_t**) DECLSPEC_HIDDEN; HRESULT compile_script(script_ctx_t*,const WCHAR*,const WCHAR*,DWORD,vbscode_t**) DECLSPEC_HIDDEN;
HRESULT exec_script(script_ctx_t*,function_t*,vbdisp_t*,DISPPARAMS*,VARIANT*) DECLSPEC_HIDDEN; HRESULT compile_procedure(script_ctx_t*,const WCHAR*,const WCHAR*,DWORD,class_desc_t**) DECLSPEC_HIDDEN;
HRESULT exec_script(script_ctx_t*,BOOL,function_t*,vbdisp_t*,DISPPARAMS*,VARIANT*) DECLSPEC_HIDDEN;
void release_dynamic_vars(dynamic_var_t*) DECLSPEC_HIDDEN; void release_dynamic_vars(dynamic_var_t*) DECLSPEC_HIDDEN;
IDispatch *lookup_named_item(script_ctx_t*,const WCHAR*,unsigned) DECLSPEC_HIDDEN; IDispatch *lookup_named_item(script_ctx_t*,const WCHAR*,unsigned) DECLSPEC_HIDDEN;
void clear_ei(EXCEPINFO*) DECLSPEC_HIDDEN;
HRESULT report_script_error(script_ctx_t*) DECLSPEC_HIDDEN;
void detach_global_objects(script_ctx_t*) DECLSPEC_HIDDEN;
HRESULT get_builtin_id(BuiltinDisp*,const WCHAR*,DISPID*) DECLSPEC_HIDDEN;
typedef struct {
UINT16 len;
WCHAR buf[7];
} string_constant_t;
#define TID_LIST \
XDIID(ErrObj) \
XDIID(GlobalObj)
typedef enum {
#define XDIID(iface) iface ## _tid,
TID_LIST
#undef XDIID
LAST_tid
} tid_t;
HRESULT get_typeinfo(tid_t,ITypeInfo**) DECLSPEC_HIDDEN;
void release_regexp_typelib(void) DECLSPEC_HIDDEN; void release_regexp_typelib(void) DECLSPEC_HIDDEN;
#ifndef INT32_MIN
#define INT32_MIN (-2147483647-1)
#endif
#ifndef INT32_MAX
#define INT32_MAX (2147483647)
#endif
static inline BOOL is_int32(double d) static inline BOOL is_int32(double d)
{ {
return INT32_MIN <= d && d <= INT32_MAX && (double)(int)d == d; return INT32_MIN <= d && d <= INT32_MAX && (double)(int)d == d;
@ -405,40 +378,12 @@ HRESULT create_safearray_iter(SAFEARRAY *sa, IEnumVARIANT **ev) DECLSPEC_HIDDEN;
#define FACILITY_VBS 0xa #define FACILITY_VBS 0xa
#define MAKE_VBSERROR(code) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_VBS, code) #define MAKE_VBSERROR(code) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_VBS, code)
#define VBSE_ILLEGAL_FUNC_CALL 5
#define VBSE_OVERFLOW 6
#define VBSE_OUT_OF_MEMORY 7
#define VBSE_OUT_OF_BOUNDS 9
#define VBSE_ARRAY_LOCKED 10
#define VBSE_TYPE_MISMATCH 13
#define VBSE_FILE_NOT_FOUND 53
#define VBSE_IO_ERROR 57
#define VBSE_FILE_ALREADY_EXISTS 58
#define VBSE_DISK_FULL 61
#define VBSE_TOO_MANY_FILES 67
#define VBSE_PERMISSION_DENIED 70
#define VBSE_PATH_FILE_ACCESS 75
#define VBSE_PATH_NOT_FOUND 76
#define VBSE_ILLEGAL_NULL_USE 94
#define VBSE_OLE_NOT_SUPPORTED 430
#define VBSE_OLE_NO_PROP_OR_METHOD 438
#define VBSE_ACTION_NOT_SUPPORTED 445
#define VBSE_NAMED_ARGS_NOT_SUPPORTED 446
#define VBSE_LOCALE_SETTING_NOT_SUPPORTED 447
#define VBSE_NAMED_PARAM_NOT_FOUND 448
#define VBSE_INVALID_TYPELIB_VARIABLE 458
#define VBSE_FUNC_ARITY_MISMATCH 450
#define VBSE_PARAMETER_NOT_OPTIONAL 449
#define VBSE_NOT_ENUM 451
#define VBSE_INVALID_DLL_FUNCTION_NAME 453
#define VBSE_CANT_CREATE_TMP_FILE 322
#define VBSE_OLE_FILE_NOT_FOUND 432
#define VBSE_CANT_CREATE_OBJECT 429
#define VBSE_SERVER_NOT_FOUND 462
HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**) DECLSPEC_HIDDEN; HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**) DECLSPEC_HIDDEN;
HRESULT WINAPI VBScriptRegExpFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**) DECLSPEC_HIDDEN; HRESULT WINAPI VBScriptRegExpFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**) DECLSPEC_HIDDEN;
BSTR get_vbscript_string(int) DECLSPEC_HIDDEN;
BSTR get_vbscript_error_string(HRESULT) DECLSPEC_HIDDEN;
static inline LPWSTR heap_strdupW(LPCWSTR str) static inline LPWSTR heap_strdupW(LPCWSTR str)
{ {
LPWSTR ret = NULL; LPWSTR ret = NULL;
@ -446,7 +391,7 @@ static inline LPWSTR heap_strdupW(LPCWSTR str)
if(str) { if(str) {
DWORD size; DWORD size;
size = (strlenW(str)+1)*sizeof(WCHAR); size = (lstrlenW(str)+1)*sizeof(WCHAR);
ret = heap_alloc(size); ret = heap_alloc(size);
if(ret) if(ret)
memcpy(ret, str, size); memcpy(ret, str, size);

View file

@ -17,6 +17,48 @@
*/ */
#include <windef.h> #include <windef.h>
#include "vbscript_defs.h"
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
STRINGTABLE
{
VBSE_ILLEGAL_FUNC_CALL "Invalid procedure call or argument"
VBSE_OVERFLOW "Overflow"
VBSE_OUT_OF_MEMORY "Out of memory"
VBSE_OUT_OF_BOUNDS "Subscript out of range"
VBSE_ARRAY_LOCKED "This array is fixed or temporarily locked"
VBSE_TYPE_MISMATCH "Type mismatch"
VBSE_FILE_NOT_FOUND "File not found"
VBSE_IO_ERROR "Device I/O error"
VBSE_FILE_ALREADY_EXISTS "File already exists"
VBSE_DISK_FULL "Disk full"
VBSE_TOO_MANY_FILES "Too many files"
VBSE_PERMISSION_DENIED "Permission denied"
VBSE_PATH_FILE_ACCESS "Path/File access error"
VBSE_PATH_NOT_FOUND "Path not found"
VBSE_OBJECT_VARIABLE_NOT_SET "Object variable not set"
VBSE_ILLEGAL_NULL_USE "Invalid use of Null"
VBSE_CANT_CREATE_TMP_FILE "Can't create necessary temporary file"
VBSE_CANT_CREATE_OBJECT "ActiveX component can't create object"
VBSE_OLE_NOT_SUPPORTED "Class doesn't support Automation"
VBSE_OLE_FILE_NOT_FOUND "File name or class name not found during Automation operation"
VBSE_OLE_NO_PROP_OR_METHOD "Object doesn't support this property or method"
VBSE_ACTION_NOT_SUPPORTED "Object doesn't support this action"
VBSE_NAMED_ARGS_NOT_SUPPORTED "Object doesn't support named arguments"
VBSE_LOCALE_SETTING_NOT_SUPPORTED "Object doesn't support current locale setting"
VBSE_NAMED_PARAM_NOT_FOUND "Named argument not found"
VBSE_PARAMETER_NOT_OPTIONAL "Named argument not found"
VBSE_FUNC_ARITY_MISMATCH "Wrong number of arguments or invalid property assignment"
VBSE_NOT_ENUM "Object not a collection"
VBSE_INVALID_DLL_FUNCTION_NAME "Specified DLL function not found"
VBSE_INVALID_TYPELIB_VARIABLE "Variable uses an Automation type not supported in VBScript"
VBSE_SERVER_NOT_FOUND "The remote server machine does not exist or is unavailable"
VBS_COMPILE_ERROR "Microsoft VBScript compilation error"
VBS_RUNTIME_ERROR "Microsoft VBScript runtime error"
VBS_UNKNOWN_RUNTIME_ERROR "Unknown runtime error"
}
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL

View file

@ -234,3 +234,40 @@
#define DISPID_REGEXP_TEST 10005 #define DISPID_REGEXP_TEST 10005
#define DISPID_REGEXP_REPLACE 10006 #define DISPID_REGEXP_REPLACE 10006
#define DISPID_REGEXP_MULTILINE 10007 #define DISPID_REGEXP_MULTILINE 10007
/* error codes */
#define VBSE_ILLEGAL_FUNC_CALL 5
#define VBSE_OVERFLOW 6
#define VBSE_OUT_OF_MEMORY 7
#define VBSE_OUT_OF_BOUNDS 9
#define VBSE_ARRAY_LOCKED 10
#define VBSE_TYPE_MISMATCH 13
#define VBSE_FILE_NOT_FOUND 53
#define VBSE_IO_ERROR 57
#define VBSE_FILE_ALREADY_EXISTS 58
#define VBSE_DISK_FULL 61
#define VBSE_TOO_MANY_FILES 67
#define VBSE_PERMISSION_DENIED 70
#define VBSE_PATH_FILE_ACCESS 75
#define VBSE_PATH_NOT_FOUND 76
#define VBSE_OBJECT_VARIABLE_NOT_SET 91
#define VBSE_ILLEGAL_NULL_USE 94
#define VBSE_CANT_CREATE_TMP_FILE 322
#define VBSE_CANT_CREATE_OBJECT 429
#define VBSE_OLE_NOT_SUPPORTED 430
#define VBSE_OLE_FILE_NOT_FOUND 432
#define VBSE_OLE_NO_PROP_OR_METHOD 438
#define VBSE_ACTION_NOT_SUPPORTED 445
#define VBSE_NAMED_ARGS_NOT_SUPPORTED 446
#define VBSE_LOCALE_SETTING_NOT_SUPPORTED 447
#define VBSE_NAMED_PARAM_NOT_FOUND 448
#define VBSE_PARAMETER_NOT_OPTIONAL 449
#define VBSE_FUNC_ARITY_MISMATCH 450
#define VBSE_NOT_ENUM 451
#define VBSE_INVALID_DLL_FUNCTION_NAME 453
#define VBSE_INVALID_TYPELIB_VARIABLE 458
#define VBSE_SERVER_NOT_FOUND 462
#define VBS_COMPILE_ERROR 4096
#define VBS_RUNTIME_ERROR 4097
#define VBS_UNKNOWN_RUNTIME_ERROR 4098

View file

@ -35,64 +35,19 @@ DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
static HINSTANCE vbscript_hinstance; static HINSTANCE vbscript_hinstance;
static ITypeLib *typelib; BSTR get_vbscript_string(int id)
static ITypeInfo *typeinfos[LAST_tid];
static REFIID tid_ids[] = {
#define XDIID(iface) &DIID_ ## iface,
TID_LIST
#undef XDIID
};
HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo)
{ {
HRESULT hres; WCHAR buf[512];
if(!LoadStringW(vbscript_hinstance, id, buf, ARRAY_SIZE(buf))) return NULL;
if (!typelib) { return SysAllocString(buf);
ITypeLib *tl;
static const WCHAR vbscript_dll1W[] = {'v','b','s','c','r','i','p','t','.','d','l','l','\\','1',0};
hres = LoadTypeLib(vbscript_dll1W, &tl);
if(FAILED(hres)) {
ERR("LoadRegTypeLib failed: %08x\n", hres);
return hres;
}
if(InterlockedCompareExchangePointer((void**)&typelib, tl, NULL))
ITypeLib_Release(tl);
}
if(!typeinfos[tid]) {
ITypeInfo *ti;
hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
if(FAILED(hres)) {
ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hres);
return hres;
}
if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
ITypeInfo_Release(ti);
}
*typeinfo = typeinfos[tid];
return S_OK;
} }
static void release_typelib(void) BSTR get_vbscript_error_string(HRESULT error)
{ {
unsigned i; BSTR ret;
if(HRESULT_FACILITY(error) != FACILITY_VBS || !(ret = get_vbscript_string(HRESULT_CODE(error))))
if(!typelib) ret = get_vbscript_string(VBS_UNKNOWN_RUNTIME_ERROR);
return; return ret;
for(i = 0; i < ARRAY_SIZE(typeinfos); i++) {
if(typeinfos[i])
ITypeInfo_Release(typeinfos[i]);
}
ITypeLib_Release(typelib);
} }
#define MIN_BLOCK_SIZE 128 #define MIN_BLOCK_SIZE 128
@ -301,7 +256,6 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
if (lpv) break; if (lpv) break;
release_typelib();
release_regexp_typelib(); release_regexp_typelib();
} }

View file

@ -192,7 +192,7 @@ dll/win32/url # Synced to WineStaging-3.3
dll/win32/urlmon # Synced to WineStaging-4.18 dll/win32/urlmon # Synced to WineStaging-4.18
dll/win32/usp10 # Synced to WineStaging-4.18 dll/win32/usp10 # Synced to WineStaging-4.18
dll/win32/uxtheme # Forked dll/win32/uxtheme # Forked
dll/win32/vbscript # Synced to WineStaging-4.0 dll/win32/vbscript # Synced to WineStaging-4.18
dll/win32/version # Synced to WineStaging-4.0 dll/win32/version # Synced to WineStaging-4.0
dll/win32/vssapi # Synced to WineStaging-2.9 dll/win32/vssapi # Synced to WineStaging-2.9
dll/win32/wbemdisp # Synced to WineStaging-4.0 dll/win32/wbemdisp # Synced to WineStaging-4.0