[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;
WCHAR *ret;
size = (strlenW(str)+1)*sizeof(WCHAR);
size = (lstrlenW(str)+1)*sizeof(WCHAR);
ret = compiler_alloc(vbscode, size);
if(ret)
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);
}
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)
{
const_decl_t *decl;
for(decl = ctx->const_decls; decl; decl = decl->next) {
if(!strcmpiW(decl->name, name))
if(!wcsicmp(decl->name, name))
return decl->value_expr;
}
@ -388,7 +400,7 @@ static expression_t *lookup_const_decls(compile_ctx_t *ctx, const WCHAR *name, B
return NULL;
for(decl = ctx->global_consts; decl; decl = decl->next) {
if(!strcmpiW(decl->name, name))
if(!wcsicmp(decl->name, name))
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);
case EXPR_SUB:
return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub);
case EXPR_USHORT:
return push_instr_int(ctx, OP_short, ((int_expression_t*)expr)->value);
case EXPR_ULONG:
return push_instr_int(ctx, OP_long, ((int_expression_t*)expr)->value);
case EXPR_INT:
return push_instr_int(ctx, OP_int, ((int_expression_t*)expr)->value);
case EXPR_XOR:
return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor);
default:
@ -781,7 +791,7 @@ static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *st
if(!push_instr(ctx, OP_val))
return E_OUTOFMEMORY;
}else {
hres = push_instr_int(ctx, OP_short, 1);
hres = push_instr_int(ctx, OP_int, 1);
if(FAILED(hres))
return hres;
}
@ -994,7 +1004,7 @@ static BOOL lookup_dim_decls(compile_ctx_t *ctx, const WCHAR *name)
dim_decl_t *dim_decl;
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;
}
@ -1006,7 +1016,7 @@ static BOOL lookup_args_name(compile_ctx_t *ctx, const WCHAR *name)
unsigned 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;
}
@ -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);
}
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)
{
HRESULT hres;
@ -1269,6 +1294,9 @@ static HRESULT compile_statement(compile_ctx_t *ctx, statement_ctx_t *stat_ctx,
case STAT_WHILELOOP:
hres = compile_while_statement(ctx, (while_statement_t*)stat);
break;
case STAT_RETVAL:
hres = compile_retval_statement(ctx, (retval_statement_t*)stat);
break;
default:
FIXME("Unimplemented statement type %d\n", stat->type);
hres = E_NOTIMPL;
@ -1444,7 +1472,7 @@ static BOOL lookup_funcs_name(compile_ctx_t *ctx, const WCHAR *name)
function_t *iter;
for(iter = ctx->funcs; iter; iter = iter->next) {
if(!strcmpiW(iter->name, name))
if(!wcsicmp(iter->name, name))
return TRUE;
}
@ -1511,7 +1539,7 @@ static BOOL lookup_class_name(compile_ctx_t *ctx, const WCHAR *name)
class_desc_t *iter;
for(iter = ctx->classes; iter; iter = iter->next) {
if(!strcmpiW(iter->name, name))
if(!wcsicmp(iter->name, name))
return TRUE;
}
@ -1563,7 +1591,7 @@ static BOOL lookup_class_funcs(class_desc_t *class_desc, const WCHAR *name)
unsigned 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;
}
@ -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) {
FIXME("class initializer is not sub\n");
return E_FAIL;
}
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) {
FIXME("class terminator is not sub\n");
return E_FAIL;
@ -1690,17 +1718,17 @@ static BOOL lookup_script_identifier(script_ctx_t *script, const WCHAR *identifi
function_t *func;
for(var = script->global_vars; var; var = var->next) {
if(!strcmpiW(var->name, identifier))
if(!wcsicmp(var->name, identifier))
return TRUE;
}
for(func = script->global_funcs; func; func = func->next) {
if(!strcmpiW(func->name, identifier))
if(!wcsicmp(func->name, identifier))
return TRUE;
}
for(class = script->classes; class; class = class->next) {
if(!strcmpiW(class->name, identifier))
if(!wcsicmp(class->name, identifier))
return TRUE;
}
@ -1797,7 +1825,7 @@ static void release_compiler(compile_ctx_t *ctx)
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_decl_t *func_decl;
@ -1806,13 +1834,15 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli
vbscode_t *code;
HRESULT hres;
hres = parse_script(&ctx.parser, src, delimiter);
if (!src) src = L"";
hres = parse_script(&ctx.parser, src, delimiter, flags);
if(FAILED(hres))
return hres;
return compile_error(script, hres);
code = ctx.code = alloc_vbscode(&ctx, src);
if(!ctx.code)
return E_OUTOFMEMORY;
return compile_error(script, E_OUTOFMEMORY);
ctx.funcs = 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);
if(FAILED(hres)) {
release_compiler(&ctx);
return hres;
return compile_error(script, hres);
}
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);
if(FAILED(hres)) {
release_compiler(&ctx);
return hres;
return compile_error(script, hres);
}
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);
if(FAILED(hres)) {
release_compiler(&ctx);
return hres;
return compile_error(script, hres);
}
}
hres = check_script_collisions(&ctx, script);
if(FAILED(hres)) {
release_compiler(&ctx);
return hres;
return compile_error(script, hres);
}
if(ctx.global_vars) {
@ -1896,3 +1926,29 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli
*ret = code;
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)
{
while(var) {
if(!strcmpiW(var->name, name)) {
if(!wcsicmp(var->name, name)) {
ref->type = var->is_const ? REF_CONST : REF_VAR;
ref->u.v = &var->v;
return TRUE;
@ -104,18 +104,16 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_
DISPID id;
HRESULT hres;
static const WCHAR errW[] = {'e','r','r',0};
if(invoke_type == VBDISP_LET
&& (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->u.v = &ctx->ret_val;
return S_OK;
}
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->u.v = ctx->vars+i;
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++) {
if(!strcmpiW(ctx->func->args[i].name, name)) {
if(!wcsicmp(ctx->func->args[i].name, name)) {
ref->type = REF_VAR;
ref->u.v = ctx->args+i;
return S_OK;
@ -137,7 +135,7 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_
if(ctx->vbthis) {
/* FIXME: Bind such identifier while generating bytecode. */
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->u.v = ctx->vbthis->props+i;
return S_OK;
@ -168,23 +166,17 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_
return S_OK;
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->u.f = func;
return S_OK;
}
}
if(!strcmpiW(name, errW)) {
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);
hres = get_builtin_id(ctx->script->global_obj, name, &id);
if(SUCCEEDED(hres)) {
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;
return S_OK;
}
@ -226,7 +218,7 @@ static HRESULT add_dynamic_var(exec_ctx_t *ctx, const WCHAR *name,
if(!new_var)
return E_OUTOFMEMORY;
size = (strlenW(name)+1)*sizeof(WCHAR);
size = (lstrlenW(name)+1)*sizeof(WCHAR);
str = heap_pool_alloc(heap, size);
if(!str)
return E_OUTOFMEMORY;
@ -247,6 +239,14 @@ static HRESULT add_dynamic_var(exec_ctx_t *ctx, const WCHAR *name,
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)
{
assert(ctx->top);
@ -319,7 +319,7 @@ static HRESULT stack_pop_val(exec_ctx_t *ctx, variant_val_t *r)
HRESULT hres;
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));
if(FAILED(hres))
return hres;
@ -350,7 +350,8 @@ static HRESULT stack_assume_val(exec_ctx_t *ctx, unsigned n)
disp = V_DISPATCH(v);
hres = get_disp_value(ctx->script, disp, v);
IDispatch_Release(disp);
if(disp)
IDispatch_Release(disp);
if(FAILED(hres))
return hres;
}
@ -580,7 +581,7 @@ static HRESULT do_icall(exec_ctx_t *ctx, VARIANT *res)
break;
case REF_FUNC:
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))
return hres;
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)
{
VARIANT value;
HRESULT hres;
hres = VariantCopyInd(dst, src);
V_VT(&value) = VT_EMPTY;
hres = VariantCopyInd(&value, src);
if(FAILED(hres))
return hres;
if(V_VT(dst) == VT_DISPATCH && !(flags & DISPATCH_PROPERTYPUTREF)) {
VARIANT value;
if(V_VT(&value) == VT_DISPATCH && !(flags & DISPATCH_PROPERTYPUTREF)) {
IDispatch *disp = V_DISPATCH(&value);
hres = get_disp_value(ctx->script, V_DISPATCH(dst), &value);
IDispatch_Release(V_DISPATCH(dst));
V_VT(&value) = VT_EMPTY;
hres = get_disp_value(ctx->script, disp, &value);
if(disp)
IDispatch_Release(disp);
if(FAILED(hres))
return hres;
*dst = value;
}
VariantClear(dst);
*dst = value;
return S_OK;
}
@ -988,7 +993,7 @@ static HRESULT interp_new(exec_ctx_t *ctx)
TRACE("%s\n", debugstr_w(arg));
if(!strcmpiW(arg, regexpW)) {
if(!wcsicmp(arg, regexpW)) {
V_VT(&v) = VT_DISPATCH;
hres = create_regexp(&V_DISPATCH(&v));
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) {
if(!strcmpiW(class_desc->name, arg))
if(!wcsicmp(class_desc->name, arg))
break;
}
if(!class_desc) {
@ -1258,6 +1263,30 @@ static HRESULT interp_ret(exec_ctx_t *ctx)
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)
{
WARN("\n");
@ -1297,7 +1326,7 @@ static HRESULT interp_errmode(exec_ctx_t *ctx)
TRACE("%d\n", err_mode);
ctx->resume_next = err_mode;
ctx->script->err_number = S_OK;
clear_ei(&ctx->script->ei);
return S_OK;
}
@ -1315,27 +1344,20 @@ static HRESULT interp_string(exec_ctx_t *ctx)
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;
VARIANT v;
TRACE("%d\n", arg);
V_VT(&v) = VT_I4;
V_I4(&v) = arg;
return stack_push(ctx, &v);
}
static HRESULT interp_short(exec_ctx_t *ctx)
{
const LONG arg = ctx->instr->arg1.lng;
VARIANT v;
TRACE("%d\n", arg);
V_VT(&v) = VT_I2;
V_I2(&v) = arg;
if(arg == (INT16)arg) {
V_VT(&v) = VT_I2;
V_I2(&v) = arg;
}else {
V_VT(&v) = VT_I4;
V_I4(&v) = arg;
}
return stack_push(ctx, &v);
}
@ -2061,7 +2083,7 @@ static void release_exec(exec_ctx_t *ctx)
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};
vbsop_t op;
@ -2123,6 +2145,9 @@ HRESULT exec_script(script_ctx_t *ctx, function_t *func, vbdisp_t *vbthis, DISPP
return E_OUTOFMEMORY;
}
if(extern_caller)
IActiveScriptSite_OnEnterScript(ctx->site);
if(vbthis) {
exec.this_obj = (IDispatch*)&vbthis->IDispatchEx_iface;
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;
hres = op_funcs[op](&exec);
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) {
unsigned stack_off;
@ -2186,8 +2219,15 @@ HRESULT exec_script(script_ctx_t *ctx, function_t *func, vbdisp_t *vbthis, DISPP
}
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) {
*res = exec.ret_val;

View file

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

View file

@ -34,6 +34,7 @@ typedef enum {
EXPR_GTEQ,
EXPR_IDIV,
EXPR_IMP,
EXPR_INT,
EXPR_IS,
EXPR_LT,
EXPR_LTEQ,
@ -51,8 +52,6 @@ typedef enum {
EXPR_OR,
EXPR_STRING,
EXPR_SUB,
EXPR_ULONG,
EXPR_USHORT,
EXPR_XOR
} expression_type_t;
@ -121,7 +120,8 @@ typedef enum {
STAT_STOP,
STAT_UNTIL,
STAT_WHILE,
STAT_WHILELOOP
STAT_WHILELOOP,
STAT_RETVAL
} statement_type_t;
typedef struct _statement_t {
@ -251,6 +251,11 @@ typedef struct {
case_clausule_t *case_clausules;
} select_statement_t;
typedef struct {
statement_t stat;
expression_t *expr;
} retval_statement_t;
typedef struct {
const WCHAR *code;
const WCHAR *ptr;
@ -271,7 +276,7 @@ typedef struct {
heap_pool_t heap;
} 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;
int parser_lex(void*,parser_ctx_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
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
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
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
# define YY_PARSER_E_REACTOSSYNC_GCC_DLL_WIN32_VBSCRIPT_PARSER_TAB_H_INCLUDED
/* Debug traces. */
@ -45,83 +49,82 @@ extern int parser_debug;
# define YYTOKENTYPE
enum yytokentype
{
tEOF = 258,
tNL = 259,
tREM = 260,
tEXPRESSION = 258,
tEOF = 259,
tNL = 260,
tEMPTYBRACKETS = 261,
tTRUE = 262,
tFALSE = 263,
tNOT = 264,
tAND = 265,
tOR = 266,
tXOR = 267,
tEQV = 268,
tIMP = 269,
tNEQ = 270,
tIS = 271,
tLTEQ = 272,
tGTEQ = 273,
tMOD = 274,
tCALL = 275,
tDIM = 276,
tSUB = 277,
tFUNCTION = 278,
tPROPERTY = 279,
tGET = 280,
tLET = 281,
tCONST = 282,
tIF = 283,
tELSE = 284,
tELSEIF = 285,
tEND = 286,
tTHEN = 287,
tEXIT = 288,
tWHILE = 289,
tWEND = 290,
tDO = 291,
tLOOP = 292,
tUNTIL = 293,
tFOR = 294,
tTO = 295,
tSTEP = 296,
tEACH = 297,
tIN = 298,
tSELECT = 299,
tCASE = 300,
tBYREF = 301,
tBYVAL = 302,
tOPTION = 303,
tEXPLICIT = 304,
tSTOP = 305,
tNOTHING = 306,
tEMPTY = 307,
tNULL = 308,
tCLASS = 309,
tSET = 310,
tNEW = 311,
tPUBLIC = 312,
tPRIVATE = 313,
tDEFAULT = 314,
tME = 315,
tERROR = 316,
tNEXT = 317,
tON = 318,
tRESUME = 319,
tGOTO = 320,
tIdentifier = 321,
tString = 322,
tLong = 323,
tShort = 324,
tLTEQ = 262,
tGTEQ = 263,
tNEQ = 264,
tSTOP = 265,
tME = 266,
tREM = 267,
tTRUE = 268,
tFALSE = 269,
tNOT = 270,
tAND = 271,
tOR = 272,
tXOR = 273,
tEQV = 274,
tIMP = 275,
tIS = 276,
tMOD = 277,
tCALL = 278,
tDIM = 279,
tSUB = 280,
tFUNCTION = 281,
tGET = 282,
tLET = 283,
tCONST = 284,
tIF = 285,
tELSE = 286,
tELSEIF = 287,
tEND = 288,
tTHEN = 289,
tEXIT = 290,
tWHILE = 291,
tWEND = 292,
tDO = 293,
tLOOP = 294,
tUNTIL = 295,
tFOR = 296,
tTO = 297,
tEACH = 298,
tIN = 299,
tSELECT = 300,
tCASE = 301,
tBYREF = 302,
tBYVAL = 303,
tOPTION = 304,
tNOTHING = 305,
tEMPTY = 306,
tNULL = 307,
tCLASS = 308,
tSET = 309,
tNEW = 310,
tPUBLIC = 311,
tPRIVATE = 312,
tNEXT = 313,
tON = 314,
tRESUME = 315,
tGOTO = 316,
tIdentifier = 317,
tString = 318,
tDEFAULT = 319,
tERROR = 320,
tEXPLICIT = 321,
tPROPERTY = 322,
tSTEP = 323,
tInt = 324,
tDouble = 325
};
#endif
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE YYSTYPE;
union YYSTYPE
{
#line 88 "parser.y" /* yacc.c:1909 */
#line 87 "parser.y"
const WCHAR *string;
statement_t *statement;
@ -136,12 +139,14 @@ union YYSTYPE
const_decl_t *const_decl;
case_clausule_t *case_clausule;
unsigned uint;
LONG lng;
LONG integer;
BOOL boolean;
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_DECLARED 1
#endif

View file

@ -28,6 +28,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
static int parser_error(parser_ctx_t *,const char*);
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_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 const WCHAR propertyW[] = {'p','r','o','p','e','r','t','y',0};
#define STORAGE_IS_PRIVATE 1
#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;
case_clausule_t *case_clausule;
unsigned uint;
LONG lng;
LONG integer;
BOOL boolean;
double dbl;
}
%token tEOF tNL tREM tEMPTYBRACKETS
%token tTRUE tFALSE
%token tNOT tAND tOR tXOR tEQV tIMP tNEQ
%token tIS tLTEQ tGTEQ tMOD
%token tCALL tDIM tSUB tFUNCTION tPROPERTY tGET tLET tCONST
%token tIF tELSE tELSEIF tEND tTHEN tEXIT
%token tWHILE tWEND tDO tLOOP tUNTIL tFOR tTO tSTEP tEACH tIN
%token tSELECT tCASE
%token tBYREF tBYVAL
%token tOPTION tEXPLICIT
%token tSTOP
%token tNOTHING tEMPTY tNULL
%token tCLASS tSET tNEW tPUBLIC tPRIVATE tDEFAULT tME
%token tERROR tNEXT tON tRESUME tGOTO
%token tEXPRESSION tEOF tNL tEMPTYBRACKETS
%token tLTEQ tGTEQ tNEQ
%token tSTOP tME tREM
%token <string> tTRUE tFALSE
%token <string> tNOT tAND tOR tXOR tEQV tIMP
%token <string> tIS tMOD
%token <string> tCALL tDIM tSUB tFUNCTION tGET tLET tCONST
%token <string> tIF tELSE tELSEIF tEND tTHEN tEXIT
%token <string> tWHILE tWEND tDO tLOOP tUNTIL tFOR tTO tEACH tIN
%token <string> tSELECT tCASE
%token <string> tBYREF tBYVAL
%token <string> tOPTION
%token <string> tNOTHING tEMPTY tNULL
%token <string> tCLASS tSET tNEW tPUBLIC tPRIVATE
%token <string> tNEXT tON tRESUME tGOTO
%token <string> tIdentifier tString
%token <lng> tLong tShort
%token <string> tDEFAULT tERROR tEXPLICIT tPROPERTY tSTEP
%token <integer> tInt
%token <dbl> tDouble
%type <statement> Statement SimpleStatement StatementNl StatementsNl StatementsNl_opt IfStatement Else_opt
%type <expression> Expression LiteralExpression PrimaryExpression EqualityExpression CallExpression
%type <statement> Statement SimpleStatement StatementNl StatementsNl StatementsNl_opt BodyStatements IfStatement Else_opt
%type <expression> Expression LiteralExpression PrimaryExpression EqualityExpression CallExpression ExpressionNl_opt
%type <expression> ConcatExpression AdditiveExpression ModExpression IntdivExpression MultiplicativeExpression ExpExpression
%type <expression> NotExpression UnaryExpression AndExpression OrExpression XorExpression EqvExpression
%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_list> DimList
%type <const_decl> ConstDecl ConstDeclList
%type <string> Identifier
%type <string> Identifier DotIdentifier
%type <case_clausule> CaseClausules
%%
Program
: OptionExplicit_opt SourceElements tEOF { parse_complete(ctx, $1); }
| tEXPRESSION ExpressionNl_opt tEOF { handle_isexpression_script(ctx, $2); }
OptionExplicit_opt
: /* empty */ { $$ = FALSE; }
@ -155,6 +157,15 @@ SourceElements
| SourceElements StatementNl { source_add_statement(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
: /* empty */ { $$ = NULL; }
| StatementsNl { $$ = $1; }
@ -210,7 +221,7 @@ SimpleStatement
MemberExpression
: 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
: DimDecl { $$ = $1; }
@ -366,6 +377,7 @@ UnaryExpression
| CallExpression { $$ = $1; }
| tNEW Identifier { $$ = new_new_expression(ctx, $2); CHECK_ERROR; }
| '-' UnaryExpression { $$ = new_unary_expression(ctx, EXPR_NEG, $2); CHECK_ERROR; }
| '+' UnaryExpression { $$ = $2; }
CallExpression
: PrimaryExpression { $$ = $1; }
@ -381,15 +393,13 @@ LiteralExpression
| tNOTHING { $$ = new_expression(ctx, EXPR_NOTHING, 0); CHECK_ERROR; }
NumericLiteralExpression
: tShort { $$ = new_long_expression(ctx, EXPR_USHORT, $1); CHECK_ERROR; }
| '0' { $$ = new_long_expression(ctx, EXPR_USHORT, 0); CHECK_ERROR; }
| tLong { $$ = new_long_expression(ctx, EXPR_ULONG, $1); CHECK_ERROR; }
: '0' { $$ = new_long_expression(ctx, EXPR_INT, 0); CHECK_ERROR; }
| tInt { $$ = new_long_expression(ctx, EXPR_INT, $1); CHECK_ERROR; }
| tDouble { $$ = new_double_expression(ctx, $1); CHECK_ERROR; }
IntegerValue
: tShort { $$ = $1; }
| '0' { $$ = 0; }
| tLong { $$ = $1; }
: '0' { $$ = 0; }
| tInt { $$ = $1; }
PrimaryExpression
: '(' Expression ')' { $$ = new_unary_expression(ctx, EXPR_BRACKETS, $2); }
@ -400,25 +410,30 @@ ClassDeclaration
ClassBody
: /* 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; }
/* 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;
$$ = 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; }
| PropertyDecl { $$ = add_class_function(ctx, new_class_decl(ctx), $1); CHECK_ERROR; }
| PropertyDecl StSep ClassBody { $$ = add_class_function(ctx, $3, $1); CHECK_ERROR; }
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; }
| 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; }
| 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; }
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; }
| 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; }
Storage_opt
@ -443,10 +458,67 @@ ArgumentDecl
| tBYREF Identifier EmptyBrackets_opt { $$ = new_argument_decl(ctx, $2, TRUE); }
| 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
: 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 */
StSep
@ -487,6 +559,22 @@ static void parse_complete(parser_ctx_t *ctx, BOOL 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)
{
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;
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) {
FIXME("Redefinition of %s::%s\n", debugstr_w(class_decl->name), debugstr_w(decl->name));
ctx->hres = E_FAIL;
@ -967,12 +1055,12 @@ void *parser_alloc(parser_ctx_t *ctx, size_t size)
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};
ctx->code = ctx->ptr = code;
ctx->end = ctx->code + strlenW(ctx->code);
ctx->end = ctx->code + lstrlenW(ctx->code);
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->class_decls = NULL;
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);

View file

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

View file

@ -47,7 +47,7 @@ static BOOL get_func_id(vbdisp_t *This, const WCHAR *name, vbdisp_invoke_type_t
continue;
}
if(!strcmpiW(This->desc->funcs[i].name, name)) {
if(!wcsicmp(This->desc->funcs[i].name, name)) {
*id = i;
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)
continue;
if(!strcmpiW(This->desc->props[i].name, name)) {
if(!wcsicmp(This->desc->props[i].name, name)) {
*id = i + This->desc->func_cnt;
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;
return DISP_E_UNKNOWNNAME;
}
@ -169,83 +161,76 @@ static HRESULT invoke_variant_prop(script_ctx_t *ctx, VARIANT *v, WORD flags, DI
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];
unsigned argn, i;
if(id < 0)
return DISP_E_MEMBERNOTFOUND;
switch(flags) {
case DISPATCH_PROPERTYGET:
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;
if(is_func_id(This, id)) {
function_t *func;
ret = SysAllocStringLen(str->buf, str->len);
if(!ret)
return E_OUTOFMEMORY;
TRACE("%p->%s\n", This, debugstr_w(This->desc->funcs[id].name));
V_VT(res) = VT_BSTR;
V_BSTR(res) = ret;
break;
switch(flags) {
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;
}
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 E_NOTIMPL;
default:
FIXME("unsupported flags %x\n", flags);
return E_NOTIMPL;
return exec_script(This->desc->ctx, extern_caller, func, This, params, res);
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(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)) {
FIXME("invalid number of arguments\n");
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);
TRACE("%p->%s\n", This, debugstr_w(This->desc->props[id - This->desc->func_cnt].name));
return invoke_variant_prop(This->desc->ctx, This->props+(id-This->desc->func_cnt), flags, params, res);
}
static BOOL run_terminator(vbdisp_t *This)
@ -260,7 +245,7 @@ static BOOL run_terminator(vbdisp_t *This)
return TRUE;
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);
return !--This->ref;
}
@ -412,84 +397,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
if(pvarRes)
V_VT(pvarRes) = VT_EMPTY;
if(id < 0)
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;
return invoke_vbdisp(This, id, wFlags, TRUE, pdp, pvarRes);
}
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) {
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);
}
@ -618,52 +526,6 @@ HRESULT create_vbdisp(const class_desc_t *desc, vbdisp_t **ret)
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 {
const WCHAR *name;
BOOL is_var;
@ -823,14 +685,14 @@ static HRESULT WINAPI ScriptDisp_GetDispID(IDispatchEx *iface, BSTR bstrName, DW
return E_UNEXPECTED;
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);
return S_OK;
}
}
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);
if(!ident)
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) {
if(!strcmpiW(func->name, bstrName)) {
if(!wcsicmp(func->name, bstrName)) {
ident = add_ident(This, func->name);
if(!ident)
return E_OUTOFMEMORY;
@ -884,9 +746,7 @@ static HRESULT WINAPI ScriptDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
switch(wFlags) {
case DISPATCH_METHOD:
case DISPATCH_METHOD|DISPATCH_PROPERTYGET:
IActiveScriptSite_OnEnterScript(This->ctx->site);
hres = exec_script(This->ctx, ident->u.func, NULL, pdp, pvarRes);
IActiveScriptSite_OnLeaveScript(This->ctx->site);
hres = exec_script(This->ctx, TRUE, ident->u.func, NULL, pdp, pvarRes);
break;
default:
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);
IDispatchEx *dispex;
vbdisp_t *vbdisp;
EXCEPINFO ei;
HRESULT hres;
@ -1086,6 +947,10 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, DISPPARAMS *dp,
if(retv)
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);
if(FAILED(hres)) {
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)
{
DISPPARAMS dp = {NULL};
if(!disp)
return MAKE_VBSERROR(VBSE_OBJECT_VARIABLE_NOT_SET);
return disp_call(ctx, disp, DISPID_VALUE, &dp, v);
}
HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, DISPPARAMS *dp)
{
IDispatchEx *dispex;
vbdisp_t *vbdisp;
EXCEPINFO ei = {0};
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);
if(SUCCEEDED(hres)) {
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) {
This->regexp = regexp_new(NULL, &This->pool, This->pattern,
strlenW(This->pattern), This->flags, FALSE);
lstrlenW(This->pattern), This->flags, FALSE);
if(!This->regexp)
return E_FAIL;
}else {
@ -1402,7 +1402,7 @@ static HRESULT WINAPI RegExp2_Test(IRegExp2 *iface, BSTR sourceString, VARIANT_B
if(!This->regexp) {
This->regexp = regexp_new(NULL, &This->pool, This->pattern,
strlenW(This->pattern), This->flags, FALSE);
lstrlenW(This->pattern), This->flags, FALSE);
if(!This->regexp)
return E_FAIL;
}else {

View file

@ -51,22 +51,26 @@ struct VBScript {
LONG ref;
DWORD safeopt;
SCRIPTSTATE state;
IActiveScriptSite *site;
script_ctx_t *ctx;
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)
{
if(This->state == state)
return;
This->state = state;
if(This->site)
IActiveScriptSite_OnStateChange(This->site, state);
if(This->ctx->site)
IActiveScriptSite_OnStateChange(This->ctx->site, state);
}
static inline BOOL is_started(VBScript *This)
@ -76,17 +80,10 @@ static inline BOOL is_started(VBScript *This)
|| 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;
IActiveScriptSite_OnEnterScript(ctx->site);
hres = exec_script(ctx, &code->main_code, NULL, NULL, NULL);
IActiveScriptSite_OnLeaveScript(ctx->site);
return hres;
return exec_script(ctx, TRUE, &code->main_code, NULL, NULL, res);
}
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) {
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;
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) {
IUnknown *unk;
@ -131,28 +128,12 @@ IDispatch *lookup_named_item(script_ctx_t *ctx, const WCHAR *name, unsigned flag
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)
{
class_desc_t *class_desc;
collect_objects(ctx);
clear_ei(&ctx->ei);
release_dynamic_vars(ctx->global_vars);
ctx->global_vars = NULL;
@ -189,16 +170,6 @@ static void release_script(script_ctx_t *ctx)
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) {
ScriptDisp *script_obj = ctx->script_obj;
@ -207,6 +178,7 @@ static void release_script(script_ctx_t *ctx)
IDispatchEx_Release(&script_obj->IDispatchEx_iface);
}
detach_global_objects(ctx);
heap_pool_free(&ctx->heap);
heap_pool_init(&ctx->heap);
}
@ -238,15 +210,7 @@ static void decrease_state(VBScript *This, SCRIPTSTATE state)
case SCRIPTSTATE_INITIALIZED:
case SCRIPTSTATE_UNINITIALIZED:
change_state(This, state);
if(This->site) {
IActiveScriptSite_Release(This->site);
This->site = NULL;
}
if(This->ctx)
release_script(This->ctx);
release_script(This->ctx);
This->thread_id = 0;
break;
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)
{
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);
if(!ref) {
if(This->ctx) {
decrease_state(This, SCRIPTSTATE_CLOSED);
destroy_script(This->ctx);
This->ctx = NULL;
}
if(This->site)
IActiveScriptSite_Release(This->site);
decrease_state(This, SCRIPTSTATE_CLOSED);
destroy_script(This->ctx);
heap_free(This);
}
@ -334,20 +405,26 @@ static HRESULT WINAPI VBScript_SetScriptSite(IActiveScript *iface, IActiveScript
if(!pass)
return E_POINTER;
if(This->site)
if(This->ctx->site)
return E_UNEXPECTED;
if(InterlockedCompareExchange(&This->thread_id, GetCurrentThreadId(), 0))
return E_UNEXPECTED;
This->site = pass;
IActiveScriptSite_AddRef(This->site);
hres = create_script_disp(This->ctx, &This->ctx->script_obj);
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)
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,
@ -375,7 +452,7 @@ static HRESULT WINAPI VBScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE
return S_OK;
}
if(!This->ctx)
if(!This->is_initialized)
return E_UNEXPECTED;
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);
if(This->thread_id != GetCurrentThreadId() || !This->ctx || This->state == SCRIPTSTATE_CLOSED)
if(This->thread_id != GetCurrentThreadId() || !This->ctx->site)
return E_UNEXPECTED;
if(dwFlags & SCRIPTITEM_GLOBALMEMBERS) {
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)) {
WARN("GetItemInfo failed: %08x\n", hres);
return hres;
@ -502,7 +579,7 @@ static HRESULT WINAPI VBScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR
if(!ppdisp)
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;
return E_UNEXPECTED;
}
@ -654,30 +731,16 @@ static ULONG WINAPI VBScriptParse_Release(IActiveScriptParse *iface)
static HRESULT WINAPI VBScriptParse_InitNew(IActiveScriptParse *iface)
{
VBScript *This = impl_from_IActiveScriptParse(iface);
script_ctx_t *ctx, *old_ctx;
TRACE("(%p)\n", This);
if(This->ctx)
if(This->is_initialized)
return E_UNEXPECTED;
This->is_initialized = TRUE;
ctx = heap_alloc_zero(sizeof(script_ctx_t));
if(!ctx)
return E_OUTOFMEMORY;
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;
if(This->ctx->site)
change_state(This, SCRIPTSTATE_INITIALIZED);
return S_OK;
}
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))
return hres;
if(context)
IDispatch_AddRef(code->context = context);
if(!is_started(This)) {
if(!(dwFlags & SCRIPTTEXT_ISEXPRESSION) && !is_started(This)) {
code->pending_exec = TRUE;
return S_OK;
}
return exec_global_code(This->ctx, code);
return exec_global_code(This->ctx, code, pvarResult);
}
static const IActiveScriptParseVtbl VBScriptParseVtbl = {
@ -772,7 +835,8 @@ static HRESULT WINAPI VBScriptParseProcedure_ParseProcedureText(IActiveScriptPar
CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp)
{
VBScript *This = impl_from_IActiveScriptParseProcedure2(iface);
vbscode_t *code;
class_desc_t *desc;
vbdisp_t *vbdisp;
HRESULT hres;
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)
return E_UNEXPECTED;
hres = compile_script(This->ctx, pstrCode, pstrDelimiter, &code);
hres = compile_procedure(This->ctx, pstrCode, pstrDelimiter, dwFlags, &desc);
if(FAILED(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 = {
@ -832,7 +901,7 @@ static HRESULT WINAPI VBScriptSafety_GetInterfaceSafetyOptions(IObjectSafety *if
return E_POINTER;
*pdwSupportedOptions = SUPPORTED_OPTIONS;
*pdwEnabledOptions = This->safeopt;
*pdwEnabledOptions = This->ctx->safeopt;
return S_OK;
}
@ -846,7 +915,7 @@ static HRESULT WINAPI VBScriptSafety_SetInterfaceSafetyOptions(IObjectSafety *if
if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
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;
}
@ -860,6 +929,7 @@ static const IObjectSafetyVtbl VBScriptSafetyVtbl = {
HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter, REFIID riid, void **ppv)
{
script_ctx_t *ctx;
VBScript *ret;
HRESULT hres;
@ -877,7 +947,24 @@ HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pU
ret->ref = 1;
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);
IActiveScript_Release(&ret->IActiveScript_iface);

View file

@ -19,6 +19,7 @@
#pragma once
#include <stdarg.h>
#include <stdint.h>
#define COBJMACROS
@ -33,10 +34,10 @@
#include <initguid.h>
#endif
#include "vbscript_classes.h"
#include "vbscript_defs.h"
#include "wine/heap.h"
#include "wine/list.h"
#include "wine/unicode.h"
typedef struct {
void **blocks;
@ -92,17 +93,6 @@ typedef struct {
function_t *entries[VBDISP_ANY];
} 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 {
const WCHAR *name;
script_ctx_t *ctx;
@ -118,9 +108,6 @@ typedef struct _class_desc_t {
unsigned array_cnt;
array_desc_t *array_descs;
unsigned builtin_prop_cnt;
const builtin_prop_t *builtin_props;
ITypeInfo *typeinfo;
function_t *value_func;
struct _class_desc_t *next;
@ -151,6 +138,16 @@ typedef struct {
script_ctx_t *ctx;
} 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 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;
@ -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 get_disp_value(script_ctx_t*,IDispatch*,VARIANT*) 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 to_int(VARIANT*,int*) DECLSPEC_HIDDEN;
@ -191,13 +187,10 @@ struct _script_ctx_t {
ScriptDisp *script_obj;
class_desc_t global_desc;
vbdisp_t *global_obj;
BuiltinDisp *global_obj;
BuiltinDisp *err_obj;
class_desc_t err_desc;
vbdisp_t *err_obj;
HRESULT err_number;
EXCEPINFO ei;
dynamic_var_t *global_vars;
function_t *global_funcs;
@ -253,11 +246,11 @@ typedef enum {
X(idiv, 1, 0, 0) \
X(imp, 1, 0, 0) \
X(incc, 1, ARG_BSTR, 0) \
X(int, 1, ARG_INT, 0) \
X(is, 1, 0, 0) \
X(jmp, 0, ARG_ADDR, 0) \
X(jmp_false, 0, ARG_ADDR, 0) \
X(jmp_true, 0, ARG_ADDR, 0) \
X(long, 1, ARG_INT, 0) \
X(lt, 1, 0, 0) \
X(lteq, 1, 0, 0) \
X(mcall, 1, ARG_BSTR, ARG_UINT) \
@ -275,9 +268,9 @@ typedef enum {
X(or, 1, 0, 0) \
X(pop, 1, ARG_UINT, 0) \
X(ret, 0, 0, 0) \
X(retval, 1, 0, 0) \
X(set_ident, 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(stop, 1, 0, 0) \
X(string, 1, ARG_STR, 0) \
@ -359,38 +352,18 @@ struct _vbscode_t {
};
void release_vbscode(vbscode_t*) DECLSPEC_HIDDEN;
HRESULT compile_script(script_ctx_t*,const WCHAR*,const WCHAR*,vbscode_t**) DECLSPEC_HIDDEN;
HRESULT exec_script(script_ctx_t*,function_t*,vbdisp_t*,DISPPARAMS*,VARIANT*) DECLSPEC_HIDDEN;
HRESULT compile_script(script_ctx_t*,const WCHAR*,const WCHAR*,DWORD,vbscode_t**) 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;
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;
#ifndef INT32_MIN
#define INT32_MIN (-2147483647-1)
#endif
#ifndef INT32_MAX
#define INT32_MAX (2147483647)
#endif
static inline BOOL is_int32(double 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 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 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)
{
LPWSTR ret = NULL;
@ -446,7 +391,7 @@ static inline LPWSTR heap_strdupW(LPCWSTR str)
if(str) {
DWORD size;
size = (strlenW(str)+1)*sizeof(WCHAR);
size = (lstrlenW(str)+1)*sizeof(WCHAR);
ret = heap_alloc(size);
if(ret)
memcpy(ret, str, size);

View file

@ -17,6 +17,48 @@
*/
#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

View file

@ -234,3 +234,40 @@
#define DISPID_REGEXP_TEST 10005
#define DISPID_REGEXP_REPLACE 10006
#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 ITypeLib *typelib;
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)
BSTR get_vbscript_string(int id)
{
HRESULT hres;
if (!typelib) {
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;
WCHAR buf[512];
if(!LoadStringW(vbscript_hinstance, id, buf, ARRAY_SIZE(buf))) return NULL;
return SysAllocString(buf);
}
static void release_typelib(void)
BSTR get_vbscript_error_string(HRESULT error)
{
unsigned i;
if(!typelib)
return;
for(i = 0; i < ARRAY_SIZE(typeinfos); i++) {
if(typeinfos[i])
ITypeInfo_Release(typeinfos[i]);
}
ITypeLib_Release(typelib);
BSTR ret;
if(HRESULT_FACILITY(error) != FACILITY_VBS || !(ret = get_vbscript_string(HRESULT_CODE(error))))
ret = get_vbscript_string(VBS_UNKNOWN_RUNTIME_ERROR);
return ret;
}
#define MIN_BLOCK_SIZE 128
@ -301,7 +256,6 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
break;
case DLL_PROCESS_DETACH:
if (lpv) break;
release_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/usp10 # Synced to WineStaging-4.18
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/vssapi # Synced to WineStaging-2.9
dll/win32/wbemdisp # Synced to WineStaging-4.0