[VBSCRIPT] Sync with Wine 10.0. CORE-20606

This commit is contained in:
Amine Khaldi
2026-06-19 19:33:57 +01:00
parent d087f8d58b
commit c51c284474
27 changed files with 4370 additions and 1818 deletions
+7 -12
View File
@@ -1,5 +1,4 @@
add_definitions(-D__ROS_LONG64__)
spec2def(vbscript.dll vbscript.spec)
list(APPEND SOURCE
@@ -14,23 +13,17 @@ list(APPEND SOURCE
vbscript.c
vbscript_main.c)
BISON_TARGET(parser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.tab.c COMPILE_FLAGS "-p parser_")
BISON_TARGET(parser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.tab.c)
list(APPEND PCH_SKIP_SOURCE
guid.c
${BISON_parser_OUTPUTS})
list(APPEND vbscript_rc_deps
${CMAKE_CURRENT_SOURCE_DIR}/vbscript_classes.rgs
${CMAKE_CURRENT_SOURCE_DIR}/vbsglobal.rgs
${CMAKE_CURRENT_SOURCE_DIR}/vbsregexp10.rgs
${CMAKE_CURRENT_SOURCE_DIR}/vbsregexp55.rgs
${CMAKE_CURRENT_BINARY_DIR}/vbsglobal.tlb
${CMAKE_CURRENT_BINARY_DIR}/vbsregexp10.tlb
${CMAKE_CURRENT_BINARY_DIR}/vbsregexp55.tlb)
${CMAKE_CURRENT_SOURCE_DIR}/vbscript.rgs)
set_source_files_properties(vbscript.rc PROPERTIES OBJECT_DEPENDS "${vbscript_rc_deps}")
add_idl_headers(vbscript_idlheader vbscript_classes.idl vbsglobal.idl vbsregexp55.idl)
add_typelib(vbsglobal.idl vbsregexp10.idl vbsregexp55.idl)
add_library(vbscript MODULE
${SOURCE}
@@ -43,9 +36,11 @@ if(MSVC)
target_compile_options(vbscript PRIVATE /wd4267)
endif()
add_idl_reg_scripts(vbscript registry vbscript_classes.idl)
add_idl_reg_scripts(vbscript regtypelib vbsglobal.idl vbsregexp10.idl vbsregexp55.idl)
set_module_type(vbscript win32dll)
target_link_libraries(vbscript uuid wine oldnames)
add_importlibs(vbscript oleaut32 ole32 user32 msvcrt kernel32 ntdll)
target_link_libraries(vbscript uuid wine oldnames wine_dll_register wine_dll_canunload)
add_importlibs(vbscript oleaut32 ole32 user32 msvcrt kernelbase kernel32_vista kernel32 ntdll)
add_dependencies(vbscript vbscript_idlheader stdole2)
add_pch(vbscript precomp.h "${PCH_SKIP_SOURCE}")
add_cd_file(TARGET vbscript DESTINATION reactos/system32 FOR all)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+16
View File
@@ -0,0 +1,16 @@
/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */
#include <stdarg.h>
#define WIN32_NO_STATUS
#define _INC_WINDOWS
#include <windef.h>
#include <winbase.h>
#include <wingdi.h>
#include <objbase.h>
#include <initguid.h>
#include <dispex.h>
#include <vbscript_classes.h>
/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */
File diff suppressed because it is too large Load Diff
+166 -139
View File
@@ -32,125 +32,70 @@
WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
static const WCHAR andW[] = {'a','n','d',0};
static const WCHAR byrefW[] = {'b','y','r','e','f',0};
static const WCHAR byvalW[] = {'b','y','v','a','l',0};
static const WCHAR callW[] = {'c','a','l','l',0};
static const WCHAR caseW[] = {'c','a','s','e',0};
static const WCHAR classW[] = {'c','l','a','s','s',0};
static const WCHAR constW[] = {'c','o','n','s','t',0};
static const WCHAR defaultW[] = {'d','e','f','a','u','l','t',0};
static const WCHAR dimW[] = {'d','i','m',0};
static const WCHAR doW[] = {'d','o',0};
static const WCHAR eachW[] = {'e','a','c','h',0};
static const WCHAR elseW[] = {'e','l','s','e',0};
static const WCHAR elseifW[] = {'e','l','s','e','i','f',0};
static const WCHAR emptyW[] = {'e','m','p','t','y',0};
static const WCHAR endW[] = {'e','n','d',0};
static const WCHAR eqvW[] = {'e','q','v',0};
static const WCHAR errorW[] = {'e','r','r','o','r',0};
static const WCHAR exitW[] = {'e','x','i','t',0};
static const WCHAR explicitW[] = {'e','x','p','l','i','c','i','t',0};
static const WCHAR falseW[] = {'f','a','l','s','e',0};
static const WCHAR forW[] = {'f','o','r',0};
static const WCHAR functionW[] = {'f','u','n','c','t','i','o','n',0};
static const WCHAR getW[] = {'g','e','t',0};
static const WCHAR gotoW[] = {'g','o','t','o',0};
static const WCHAR ifW[] = {'i','f',0};
static const WCHAR impW[] = {'i','m','p',0};
static const WCHAR inW[] = {'i','n',0};
static const WCHAR isW[] = {'i','s',0};
static const WCHAR letW[] = {'l','e','t',0};
static const WCHAR loopW[] = {'l','o','o','p',0};
static const WCHAR meW[] = {'m','e',0};
static const WCHAR modW[] = {'m','o','d',0};
static const WCHAR newW[] = {'n','e','w',0};
static const WCHAR nextW[] = {'n','e','x','t',0};
static const WCHAR notW[] = {'n','o','t',0};
static const WCHAR nothingW[] = {'n','o','t','h','i','n','g',0};
static const WCHAR nullW[] = {'n','u','l','l',0};
static const WCHAR onW[] = {'o','n',0};
static const WCHAR optionW[] = {'o','p','t','i','o','n',0};
static const WCHAR orW[] = {'o','r',0};
static const WCHAR privateW[] = {'p','r','i','v','a','t','e',0};
static const WCHAR propertyW[] = {'p','r','o','p','e','r','t','y',0};
static const WCHAR publicW[] = {'p','u','b','l','i','c',0};
static const WCHAR remW[] = {'r','e','m',0};
static const WCHAR resumeW[] = {'r','e','s','u','m','e',0};
static const WCHAR selectW[] = {'s','e','l','e','c','t',0};
static const WCHAR setW[] = {'s','e','t',0};
static const WCHAR stepW[] = {'s','t','e','p',0};
static const WCHAR stopW[] = {'s','t','o','p',0};
static const WCHAR subW[] = {'s','u','b',0};
static const WCHAR thenW[] = {'t','h','e','n',0};
static const WCHAR toW[] = {'t','o',0};
static const WCHAR trueW[] = {'t','r','u','e',0};
static const WCHAR untilW[] = {'u','n','t','i','l',0};
static const WCHAR wendW[] = {'w','e','n','d',0};
static const WCHAR whileW[] = {'w','h','i','l','e',0};
static const WCHAR xorW[] = {'x','o','r',0};
static const struct {
const WCHAR *word;
int token;
} keywords[] = {
{andW, tAND},
{byrefW, tBYREF},
{byvalW, tBYVAL},
{callW, tCALL},
{caseW, tCASE},
{classW, tCLASS},
{constW, tCONST},
{defaultW, tDEFAULT},
{dimW, tDIM},
{doW, tDO},
{eachW, tEACH},
{elseW, tELSE},
{elseifW, tELSEIF},
{emptyW, tEMPTY},
{endW, tEND},
{eqvW, tEQV},
{errorW, tERROR},
{exitW, tEXIT},
{explicitW, tEXPLICIT},
{falseW, tFALSE},
{forW, tFOR},
{functionW, tFUNCTION},
{getW, tGET},
{gotoW, tGOTO},
{ifW, tIF},
{impW, tIMP},
{inW, tIN},
{isW, tIS},
{letW, tLET},
{loopW, tLOOP},
{meW, tME},
{modW, tMOD},
{newW, tNEW},
{nextW, tNEXT},
{notW, tNOT},
{nothingW, tNOTHING},
{nullW, tNULL},
{onW, tON},
{optionW, tOPTION},
{orW, tOR},
{privateW, tPRIVATE},
{propertyW, tPROPERTY},
{publicW, tPUBLIC},
{remW, tREM},
{resumeW, tRESUME},
{selectW, tSELECT},
{setW, tSET},
{stepW, tSTEP},
{stopW, tSTOP},
{subW, tSUB},
{thenW, tTHEN},
{toW, tTO},
{trueW, tTRUE},
{untilW, tUNTIL},
{wendW, tWEND},
{whileW, tWHILE},
{xorW, tXOR}
{L"and", tAND},
{L"byref", tBYREF},
{L"byval", tBYVAL},
{L"call", tCALL},
{L"case", tCASE},
{L"class", tCLASS},
{L"const", tCONST},
{L"default", tDEFAULT},
{L"dim", tDIM},
{L"do", tDO},
{L"each", tEACH},
{L"else", tELSE},
{L"elseif", tELSEIF},
{L"empty", tEMPTY},
{L"end", tEND},
{L"eqv", tEQV},
{L"error", tERROR},
{L"exit", tEXIT},
{L"explicit", tEXPLICIT},
{L"false", tFALSE},
{L"for", tFOR},
{L"function", tFUNCTION},
{L"get", tGET},
{L"goto", tGOTO},
{L"if", tIF},
{L"imp", tIMP},
{L"in", tIN},
{L"is", tIS},
{L"let", tLET},
{L"loop", tLOOP},
{L"me", tME},
{L"mod", tMOD},
{L"new", tNEW},
{L"next", tNEXT},
{L"not", tNOT},
{L"nothing", tNOTHING},
{L"null", tNULL},
{L"on", tON},
{L"option", tOPTION},
{L"or", tOR},
{L"preserve", tPRESERVE},
{L"private", tPRIVATE},
{L"property", tPROPERTY},
{L"public", tPUBLIC},
{L"redim", tREDIM},
{L"rem", tREM},
{L"resume", tRESUME},
{L"select", tSELECT},
{L"set", tSET},
{L"step", tSTEP},
{L"stop", tSTOP},
{L"sub", tSUB},
{L"then", tTHEN},
{L"to", tTO},
{L"true", tTRUE},
{L"until", tUNTIL},
{L"wend", tWEND},
{L"while", tWHILE},
{L"with", tWITH},
{L"xor", tXOR}
};
static inline BOOL is_identifier_char(WCHAR c)
@@ -263,6 +208,48 @@ static int parse_string_literal(parser_ctx_t *ctx, const WCHAR **ret)
return tString;
}
static int parse_date_literal(parser_ctx_t *ctx, DATE *ret)
{
const WCHAR *ptr = ++ctx->ptr;
WCHAR *rptr;
int len = 0;
HRESULT res;
while(ctx->ptr < ctx->end) {
if(*ctx->ptr == '\n' || *ctx->ptr == '\r') {
FIXME("newline inside date literal\n");
return 0;
}
if(*ctx->ptr == '#')
break;
ctx->ptr++;
}
if(ctx->ptr == ctx->end) {
FIXME("unterminated date literal\n");
return 0;
}
len += ctx->ptr-ptr;
rptr = malloc((len+1)*sizeof(WCHAR));
if(!rptr)
return 0;
memcpy( rptr, ptr, len * sizeof(WCHAR));
rptr[len] = 0;
res = VarDateFromStr(rptr, ctx->lcid, 0, ret);
free(rptr);
if (FAILED(res)) {
FIXME("Invalid date literal\n");
return 0;
}
ctx->ptr++;
return tDate;
}
static int parse_numeric_literal(parser_ctx_t *ctx, void **ret)
{
BOOL use_int = TRUE;
@@ -273,7 +260,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 && iswdigit(*ctx->ptr)) {
while(ctx->ptr < ctx->end && is_digit(*ctx->ptr)) {
hlp = d*10 + *(ctx->ptr++) - '0';
if(d>MAXLONGLONG/10 || hlp<0) {
exp++;
@@ -282,7 +269,7 @@ static int parse_numeric_literal(parser_ctx_t *ctx, void **ret)
else
d = hlp;
}
while(ctx->ptr < ctx->end && iswdigit(*ctx->ptr)) {
while(ctx->ptr < ctx->end && is_digit(*ctx->ptr)) {
exp++;
ctx->ptr++;
}
@@ -291,7 +278,7 @@ static int parse_numeric_literal(parser_ctx_t *ctx, void **ret)
use_int = FALSE;
ctx->ptr++;
while(ctx->ptr < ctx->end && iswdigit(*ctx->ptr)) {
while(ctx->ptr < ctx->end && is_digit(*ctx->ptr)) {
hlp = d*10 + *(ctx->ptr++) - '0';
if(d>MAXLONGLONG/10 || hlp<0)
break;
@@ -299,7 +286,7 @@ static int parse_numeric_literal(parser_ctx_t *ctx, void **ret)
d = hlp;
exp--;
}
while(ctx->ptr < ctx->end && iswdigit(*ctx->ptr))
while(ctx->ptr < ctx->end && is_digit(*ctx->ptr))
ctx->ptr++;
}
@@ -314,7 +301,7 @@ static int parse_numeric_literal(parser_ctx_t *ctx, void **ret)
ctx->ptr++;
}
if(!iswdigit(*ctx->ptr)) {
if(!is_digit(*ctx->ptr)) {
FIXME("Invalid numeric literal\n");
return 0;
}
@@ -325,7 +312,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(iswdigit(*ctx->ptr))
while(is_digit(*ctx->ptr))
ctx->ptr++;
*(double*)ret = 0;
return tDouble;
@@ -335,7 +322,7 @@ static int parse_numeric_literal(parser_ctx_t *ctx, void **ret)
FIXME("Invalid numeric literal\n");
return 0;
}
} while(iswdigit(*ctx->ptr));
} while(is_digit(*ctx->ptr));
exp += sign*e;
}
@@ -369,20 +356,22 @@ static int hex_to_int(WCHAR c)
static int parse_hex_literal(parser_ctx_t *ctx, LONG *ret)
{
const WCHAR *begin = ctx->ptr;
LONG l = 0, d;
unsigned l = 0, d;
while((d = hex_to_int(*++ctx->ptr)) != -1)
l = l*16 + d;
if(begin + 9 /* max digits+1 */ < ctx->ptr || (*ctx->ptr != '&' && is_identifier_char(*ctx->ptr))) {
if(begin + 9 /* max digits+1 */ < ctx->ptr) {
FIXME("invalid literal\n");
return 0;
}
if(*ctx->ptr == '&')
if(*ctx->ptr == '&') {
ctx->ptr++;
*ret = l;
*ret = l;
}else {
*ret = l == (UINT16)l ? (INT16)l : l;
}
return tInt;
}
@@ -394,8 +383,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 = wcspbrk(ctx->ptr, newlineW);
ctx->ptr = wcspbrk(ctx->ptr, L"\n\r");
if(ctx->ptr)
ctx->ptr++;
else
@@ -403,13 +391,14 @@ static int comment_line(parser_ctx_t *ctx)
return tNL;
}
static int parse_next_token(void *lval, parser_ctx_t *ctx)
static int parse_next_token(void *lval, unsigned *loc, parser_ctx_t *ctx)
{
WCHAR c;
skip_spaces(ctx);
*loc = ctx->ptr - ctx->code;
if(ctx->ptr == ctx->end)
return ctx->last_token == tNL ? tEOF : tNL;
return ctx->last_token == tNL ? 0 : tNL;
c = *ctx->ptr;
@@ -417,7 +406,9 @@ static int parse_next_token(void *lval, parser_ctx_t *ctx)
return parse_numeric_literal(ctx, lval);
if(iswalpha(c)) {
int ret = check_keywords(ctx, lval);
int ret = 0;
if(ctx->last_token != '.' && ctx->last_token != tDOT)
ret = check_keywords(ctx, lval);
if(!ret)
return parse_identifier(ctx, lval);
if(ret != tREM)
@@ -435,15 +426,29 @@ static int parse_next_token(void *lval, parser_ctx_t *ctx)
case ':':
case ')':
case ',':
case '=':
case '+':
case '*':
case '/':
case '^':
case '\\':
case '.':
case '_':
return *ctx->ptr++;
case '.':
/*
* We need to distinguish between '.' used as part of a member expression and
* a beginning of a dot expression (a member expression accessing with statement
* expression) and a floating point number like ".2" .
*/
c = ctx->ptr > ctx->code ? ctx->ptr[-1] : '\n';
if (is_identifier_char(c) || c == ')') {
ctx->ptr++;
return '.';
}
c = ctx->ptr[1];
if('0' <= c && c <= '9')
return parse_numeric_literal(ctx, lval);
ctx->ptr++;
return tDOT;
case '-':
if(ctx->is_html && ctx->ptr[1] == '-' && ctx->ptr[2] == '>')
return comment_line(ctx);
@@ -460,13 +465,31 @@ static int parse_next_token(void *lval, parser_ctx_t *ctx)
ctx->ptr++;
return tEMPTYBRACKETS;
}
return '(';
/*
* Parser can't predict if bracket is part of argument expression or an argument
* in call expression. We predict it here instead.
*/
if(ctx->last_token == tIdentifier || ctx->last_token == ')')
return '(';
return tEXPRLBRACKET;
case '"':
return parse_string_literal(ctx, lval);
case '#':
return parse_date_literal(ctx, lval);
case '&':
if(*++ctx->ptr == 'h' || *ctx->ptr == 'H')
if((*++ctx->ptr == 'h' || *ctx->ptr == 'H') && hex_to_int(ctx->ptr[1]) != -1)
return parse_hex_literal(ctx, lval);
return '&';
case '=':
switch(*++ctx->ptr) {
case '<':
ctx->ptr++;
return tLTEQ;
case '>':
ctx->ptr++;
return tGTEQ;
}
return '=';
case '<':
switch(*++ctx->ptr) {
case '>':
@@ -481,9 +504,13 @@ static int parse_next_token(void *lval, parser_ctx_t *ctx)
}
return '<';
case '>':
if(*++ctx->ptr == '=') {
switch(*++ctx->ptr) {
case '=':
ctx->ptr++;
return tGTEQ;
case '<':
ctx->ptr++;
return tNEQ;
}
return '>';
default:
@@ -493,7 +520,7 @@ static int parse_next_token(void *lval, parser_ctx_t *ctx)
return 0;
}
int parser_lex(void *lval, parser_ctx_t *ctx)
int parser_lex(void *lval, unsigned *loc, parser_ctx_t *ctx)
{
int ret;
@@ -504,7 +531,7 @@ int parser_lex(void *lval, parser_ctx_t *ctx)
}
while(1) {
ret = parse_next_token(lval, ctx);
ret = parse_next_token(lval, loc, ctx);
if(ret == '_') {
skip_spaces(ctx);
if(*ctx->ptr != '\n' && *ctx->ptr != '\r') {
+45 -9
View File
@@ -23,8 +23,11 @@ typedef enum {
EXPR_AND,
EXPR_BOOL,
EXPR_BRACKETS,
EXPR_CALL,
EXPR_CONCAT,
EXPR_DATE,
EXPR_DIV,
EXPR_DOT,
EXPR_DOUBLE,
EXPR_EMPTY,
EXPR_EQUAL,
@@ -70,6 +73,11 @@ typedef struct {
LONG value;
} int_expression_t;
typedef struct {
expression_t expr;
DATE value;
} date_expression_t;
typedef struct {
expression_t expr;
double value;
@@ -95,9 +103,14 @@ typedef struct {
expression_t expr;
expression_t *obj_expr;
const WCHAR *identifier;
expression_t *args;
} member_expression_t;
typedef struct {
expression_t expr;
expression_t *call_expr;
expression_t *args;
} call_expression_t;
typedef enum {
STAT_ASSIGN,
STAT_CALL,
@@ -115,29 +128,31 @@ typedef enum {
STAT_FUNC,
STAT_IF,
STAT_ONERROR,
STAT_REDIM,
STAT_SELECT,
STAT_SET,
STAT_STOP,
STAT_UNTIL,
STAT_WHILE,
STAT_WHILELOOP,
STAT_WITH,
STAT_RETVAL
} statement_type_t;
typedef struct _statement_t {
statement_type_t type;
unsigned loc;
struct _statement_t *next;
} statement_t;
typedef struct {
statement_t stat;
member_expression_t *expr;
BOOL is_strict;
call_expression_t *expr;
} call_statement_t;
typedef struct {
statement_t stat;
member_expression_t *member_expr;
expression_t *left_expr;
expression_t *value_expr;
} assign_statement_t;
@@ -159,6 +174,18 @@ typedef struct _dim_statement_t {
dim_decl_t *dim_decls;
} dim_statement_t;
typedef struct _redim_decl_t {
const WCHAR *identifier;
expression_t *dims;
struct _redim_decl_t *next;
} redim_decl_t;
typedef struct {
statement_t stat;
BOOL preserve;
redim_decl_t *redim_decls;
} redim_statement_t;
typedef struct _arg_decl_t {
const WCHAR *name;
BOOL by_ref;
@@ -169,6 +196,7 @@ typedef struct _function_decl_t {
const WCHAR *name;
function_type_t type;
BOOL is_public;
BOOL is_default;
arg_decl_t *args;
statement_t *body;
struct _function_decl_t *next;
@@ -190,6 +218,7 @@ typedef struct _class_decl_t {
typedef struct _elseif_decl_t {
expression_t *expr;
statement_t *stat;
unsigned loc;
struct _elseif_decl_t *next;
} elseif_decl_t;
@@ -251,6 +280,12 @@ typedef struct {
case_clausule_t *case_clausules;
} select_statement_t;
typedef struct {
statement_t stat;
expression_t *expr;
statement_t *body;
} with_statement_t;
typedef struct {
statement_t stat;
expression_t *expr;
@@ -262,9 +297,10 @@ typedef struct {
const WCHAR *end;
BOOL option_explicit;
BOOL parse_complete;
BOOL is_html;
HRESULT hres;
int error_loc;
LCID lcid;
int last_token;
unsigned last_nl;
@@ -276,7 +312,7 @@ typedef struct {
heap_pool_t heap;
} parser_ctx_t;
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;
HRESULT parse_script(parser_ctx_t*,const WCHAR*,const WCHAR*,DWORD);
void parser_release(parser_ctx_t*);
int parser_lex(void*,unsigned*,parser_ctx_t*);
void *parser_alloc(parser_ctx_t*,size_t);
+326 -196
View File
@@ -25,9 +25,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
static int parser_error(parser_ctx_t *,const char*);
static int parser_error(unsigned*,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*);
@@ -35,6 +34,7 @@ static void source_add_class(parser_ctx_t*,class_decl_t*);
static void *new_expression(parser_ctx_t*,expression_type_t,size_t);
static expression_t *new_bool_expression(parser_ctx_t*,VARIANT_BOOL);
static expression_t *new_date_expression(parser_ctx_t*,DATE);
static expression_t *new_string_expression(parser_ctx_t*,const WCHAR*);
static expression_t *new_long_expression(parser_ctx_t*,expression_type_t,LONG);
static expression_t *new_double_expression(parser_ctx_t*,double);
@@ -43,24 +43,29 @@ static expression_t *new_binary_expression(parser_ctx_t*,expression_type_t,expre
static expression_t *new_new_expression(parser_ctx_t*,const WCHAR*);
static member_expression_t *new_member_expression(parser_ctx_t*,expression_t*,const WCHAR*);
static call_expression_t *new_call_expression(parser_ctx_t*,expression_t*,expression_t*);
static call_expression_t *make_call_expression(parser_ctx_t*,expression_t*,expression_t*);
static void *new_statement(parser_ctx_t*,statement_type_t,size_t);
static statement_t *new_call_statement(parser_ctx_t*,BOOL,member_expression_t*);
static statement_t *new_assign_statement(parser_ctx_t*,member_expression_t*,expression_t*);
static statement_t *new_set_statement(parser_ctx_t*,member_expression_t*,expression_t*);
static statement_t *new_dim_statement(parser_ctx_t*,dim_decl_t*);
static statement_t *new_while_statement(parser_ctx_t*,statement_type_t,expression_t*,statement_t*);
static statement_t *new_forto_statement(parser_ctx_t*,const WCHAR*,expression_t*,expression_t*,expression_t*,statement_t*);
static statement_t *new_foreach_statement(parser_ctx_t*,const WCHAR*,expression_t*,statement_t*);
static statement_t *new_if_statement(parser_ctx_t*,expression_t*,statement_t*,elseif_decl_t*,statement_t*);
static statement_t *new_function_statement(parser_ctx_t*,function_decl_t*);
static statement_t *new_onerror_statement(parser_ctx_t*,BOOL);
static statement_t *new_const_statement(parser_ctx_t*,const_decl_t*);
static statement_t *new_select_statement(parser_ctx_t*,expression_t*,case_clausule_t*);
static void *new_statement(parser_ctx_t*,statement_type_t,size_t,unsigned);
static statement_t *new_call_statement(parser_ctx_t*,unsigned,expression_t*);
static statement_t *new_assign_statement(parser_ctx_t*,unsigned,expression_t*,expression_t*);
static statement_t *new_set_statement(parser_ctx_t*,unsigned,expression_t*,expression_t*);
static statement_t *new_dim_statement(parser_ctx_t*,unsigned,dim_decl_t*);
static statement_t *new_redim_statement(parser_ctx_t*,unsigned,BOOL,redim_decl_t*);
static statement_t *new_while_statement(parser_ctx_t*,unsigned,statement_type_t,expression_t*,statement_t*);
static statement_t *new_forto_statement(parser_ctx_t*,unsigned,const WCHAR*,expression_t*,expression_t*,expression_t*,statement_t*);
static statement_t *new_foreach_statement(parser_ctx_t*,unsigned,const WCHAR*,expression_t*,statement_t*);
static statement_t *new_if_statement(parser_ctx_t*,unsigned,expression_t*,statement_t*,elseif_decl_t*,statement_t*);
static statement_t *new_function_statement(parser_ctx_t*,unsigned,function_decl_t*);
static statement_t *new_onerror_statement(parser_ctx_t*,unsigned,BOOL);
static statement_t *new_const_statement(parser_ctx_t*,unsigned,const_decl_t*);
static statement_t *new_select_statement(parser_ctx_t*,unsigned,expression_t*,case_clausule_t*);
static statement_t *new_with_statement(parser_ctx_t*,unsigned,expression_t*,statement_t*);
static dim_decl_t *new_dim_decl(parser_ctx_t*,const WCHAR*,BOOL,dim_list_t*);
static dim_list_t *new_dim(parser_ctx_t*,unsigned,dim_list_t*);
static elseif_decl_t *new_elseif_decl(parser_ctx_t*,expression_t*,statement_t*);
static redim_decl_t *new_redim_decl(parser_ctx_t*,const WCHAR*,expression_t*);
static elseif_decl_t *new_elseif_decl(parser_ctx_t*,unsigned,expression_t*,statement_t*);
static function_decl_t *new_function_decl(parser_ctx_t*,const WCHAR*,function_type_t,unsigned,arg_decl_t*,statement_t*);
static arg_decl_t *new_argument_decl(parser_ctx_t*,const WCHAR*,BOOL);
static const_decl_t *new_const_decl(parser_ctx_t*,const WCHAR*,expression_t*);
@@ -77,11 +82,15 @@ static statement_t *link_statements(statement_t*,statement_t*);
#define CHECK_ERROR if(((parser_ctx_t*)ctx)->hres != S_OK) YYABORT
#define PARSER_LTYPE unsigned
#define YYLLOC_DEFAULT(Cur, Rhs, N) Cur = YYRHSLOC((Rhs), (N) ? 1 : 0)
%}
%lex-param { parser_ctx_t *ctx }
%parse-param { parser_ctx_t *ctx }
%pure-parser
%define api.prefix {parser_}
%define api.pure
%start Program
%union {
@@ -92,6 +101,7 @@ static statement_t *link_statements(statement_t*,statement_t*);
elseif_decl_t *elseif;
dim_decl_t *dim_decl;
dim_list_t *dim_list;
redim_decl_t *redim_decl;
function_decl_t *func_decl;
arg_decl_t *arg_decl;
class_decl_t *class_decl;
@@ -101,18 +111,20 @@ static statement_t *link_statements(statement_t*,statement_t*);
LONG integer;
BOOL boolean;
double dbl;
DATE date;
}
%token tEXPRESSION tEOF tNL tEMPTYBRACKETS
%token tEXPRESSION tNL tEMPTYBRACKETS tEXPRLBRACKET
%token tLTEQ tGTEQ tNEQ
%token tSTOP tME tREM
%token tSTOP tME tREM tDOT
%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> tCALL tSUB tFUNCTION tGET tLET tCONST
%token <string> tDIM tREDIM tPRESERVE
%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> tSELECT tCASE tWITH
%token <string> tBYREF tBYVAL
%token <string> tOPTION
%token <string> tNOTHING tEMPTY tNULL
@@ -122,41 +134,54 @@ static statement_t *link_statements(statement_t*,statement_t*);
%token <string> tDEFAULT tERROR tEXPLICIT tPROPERTY tSTEP
%token <integer> tInt
%token <dbl> tDouble
%token <date> tDate
%type <statement> Statement SimpleStatement StatementNl StatementsNl StatementsNl_opt BodyStatements IfStatement Else_opt
%type <statement> GlobalDimDeclaration
%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> NotExpression UnaryExpression AndExpression OrExpression XorExpression EqvExpression SignExpression
%type <expression> ConstExpression NumericLiteralExpression
%type <member> MemberExpression
%type <expression> Arguments_opt ArgumentList ArgumentList_opt Step_opt ExpressionList
%type <boolean> OptionExplicit_opt DoType
%type <arg_decl> ArgumentsDecl_opt ArgumentDeclList ArgumentDecl
%type <expression> Arguments ArgumentList ArgumentList_opt Step_opt ExpressionList
%type <boolean> DoType Preserve_opt
%type <arg_decl> ArgumentsDecl ArgumentsDecl_opt ArgumentDeclList ArgumentDecl
%type <func_decl> FunctionDecl PropertyDecl
%type <elseif> ElseIfs_opt ElseIfs ElseIf
%type <class_decl> ClassDeclaration ClassBody
%type <uint> Storage Storage_opt IntegerValue
%type <dim_decl> DimDeclList DimDecl
%type <dim_list> DimList
%type <redim_decl> ReDimDeclList ReDimDecl
%type <const_decl> ConstDecl ConstDeclList
%type <string> Identifier DotIdentifier
%type <string> Identifier
%type <case_clausule> CaseClausules
%%
Program
: OptionExplicit_opt SourceElements tEOF { parse_complete(ctx, $1); }
| tEXPRESSION ExpressionNl_opt tEOF { handle_isexpression_script(ctx, $2); }
: OptionExplicit_opt SourceElements
| tEXPRESSION ExpressionNl_opt { handle_isexpression_script(ctx, $2); }
OptionExplicit_opt
: /* empty */ { $$ = FALSE; }
| tOPTION tEXPLICIT StSep { $$ = TRUE; }
: /* empty */
| tOPTION tEXPLICIT StSep { ctx->option_explicit = TRUE; }
SourceElements
: /* empty */
| SourceElements GlobalDimDeclaration StSep
{ source_add_statement(ctx, $2); }
| SourceElements StatementNl { source_add_statement(ctx, $2); }
| SourceElements ClassDeclaration { source_add_class(ctx, $2); }
GlobalDimDeclaration
: tPRIVATE tCONST ConstDeclList { $$ = new_const_statement(ctx, @$, $3); CHECK_ERROR; }
| tPUBLIC tCONST ConstDeclList { $$ = new_const_statement(ctx, @$, $3); CHECK_ERROR; }
| tPRIVATE DimDeclList { $$ = new_dim_statement(ctx, @$, $2); CHECK_ERROR; }
| tPUBLIC DimDeclList { $$ = new_dim_statement(ctx, @$, $2);
(void)parser_nerrs; /* avoid unused variable warning */
CHECK_ERROR; }
ExpressionNl_opt
: /* empty */ { $$ = NULL; }
| Expression tNL { $$ = $1; }
@@ -171,8 +196,8 @@ StatementsNl_opt
| StatementsNl { $$ = $1; }
StatementsNl
: StatementNl { $$ = $1; }
| StatementNl StatementsNl { $$ = link_statements($1, $2); }
: SimpleStatement StSep { $$ = $1; }
| SimpleStatement StSep StatementsNl { $$ = link_statements($1, $3); }
StatementNl
: Statement tNL { $$ = $1; }
@@ -185,43 +210,59 @@ Statement
| SimpleStatement ':' { $$ = $1; }
SimpleStatement
: MemberExpression ArgumentList_opt { $1->args = $2; $$ = new_call_statement(ctx, FALSE, $1); CHECK_ERROR; }
| tCALL MemberExpression Arguments_opt { $2->args = $3; $$ = new_call_statement(ctx, TRUE, $2); CHECK_ERROR; }
| MemberExpression Arguments_opt '=' Expression
{ $1->args = $2; $$ = new_assign_statement(ctx, $1, $4); CHECK_ERROR; }
| tDIM DimDeclList { $$ = new_dim_statement(ctx, $2); CHECK_ERROR; }
: CallExpression ArgumentList_opt { call_expression_t *call_expr = make_call_expression(ctx, $1, $2); CHECK_ERROR;
$$ = new_call_statement(ctx, @$, &call_expr->expr); CHECK_ERROR; }
| tCALL UnaryExpression { $$ = new_call_statement(ctx, @$, $2); CHECK_ERROR; }
| CallExpression '=' Expression
{ $$ = new_assign_statement(ctx, @$, $1, $3); CHECK_ERROR; }
| tDIM DimDeclList { $$ = new_dim_statement(ctx, @$, $2); CHECK_ERROR; }
| tREDIM Preserve_opt ReDimDeclList { $$ = new_redim_statement(ctx, @$, $2, $3); CHECK_ERROR; }
| IfStatement { $$ = $1; }
| tWHILE Expression StSep StatementsNl_opt tWEND
{ $$ = new_while_statement(ctx, STAT_WHILE, $2, $4); CHECK_ERROR; }
{ $$ = new_while_statement(ctx, @$, STAT_WHILE, $2, $4); CHECK_ERROR; }
| tDO DoType Expression StSep StatementsNl_opt tLOOP
{ $$ = new_while_statement(ctx, $2 ? STAT_WHILELOOP : STAT_UNTIL, $3, $5);
{ $$ = new_while_statement(ctx, @$, $2 ? STAT_WHILELOOP : STAT_UNTIL, $3, $5);
CHECK_ERROR; }
| tDO StSep StatementsNl_opt tLOOP DoType Expression
{ $$ = new_while_statement(ctx, $5 ? STAT_DOWHILE : STAT_DOUNTIL, $6, $3);
{ $$ = new_while_statement(ctx, @4, $5 ? STAT_DOWHILE : STAT_DOUNTIL, $6, $3);
CHECK_ERROR; }
| tDO StSep StatementsNl_opt tLOOP { $$ = new_while_statement(ctx, STAT_DOWHILE, NULL, $3); CHECK_ERROR; }
| FunctionDecl { $$ = new_function_statement(ctx, $1); CHECK_ERROR; }
| tEXIT tDO { $$ = new_statement(ctx, STAT_EXITDO, 0); CHECK_ERROR; }
| tEXIT tFOR { $$ = new_statement(ctx, STAT_EXITFOR, 0); CHECK_ERROR; }
| tEXIT tFUNCTION { $$ = new_statement(ctx, STAT_EXITFUNC, 0); CHECK_ERROR; }
| tEXIT tPROPERTY { $$ = new_statement(ctx, STAT_EXITPROP, 0); CHECK_ERROR; }
| tEXIT tSUB { $$ = new_statement(ctx, STAT_EXITSUB, 0); CHECK_ERROR; }
| tSET MemberExpression Arguments_opt '=' Expression
{ $2->args = $3; $$ = new_set_statement(ctx, $2, $5); CHECK_ERROR; }
| tSTOP { $$ = new_statement(ctx, STAT_STOP, 0); CHECK_ERROR; }
| tON tERROR tRESUME tNEXT { $$ = new_onerror_statement(ctx, TRUE); CHECK_ERROR; }
| tON tERROR tGOTO '0' { $$ = new_onerror_statement(ctx, FALSE); CHECK_ERROR; }
| tCONST ConstDeclList { $$ = new_const_statement(ctx, $2); CHECK_ERROR; }
| tDO StSep StatementsNl_opt tLOOP { $$ = new_while_statement(ctx, @$, STAT_DOWHILE, NULL, $3); CHECK_ERROR; }
| FunctionDecl { $$ = new_function_statement(ctx, @$, $1); CHECK_ERROR; }
| tEXIT tDO { $$ = new_statement(ctx, STAT_EXITDO, 0, @$); CHECK_ERROR; }
| tEXIT tFOR { $$ = new_statement(ctx, STAT_EXITFOR, 0, @$); CHECK_ERROR; }
| tEXIT tFUNCTION { $$ = new_statement(ctx, STAT_EXITFUNC, 0, @$); CHECK_ERROR; }
| tEXIT tPROPERTY { $$ = new_statement(ctx, STAT_EXITPROP, 0, @$); CHECK_ERROR; }
| tEXIT tSUB { $$ = new_statement(ctx, STAT_EXITSUB, 0, @$); CHECK_ERROR; }
| tSET CallExpression '=' Expression { $$ = new_set_statement(ctx, @$, $2, $4); CHECK_ERROR; }
| tSTOP { $$ = new_statement(ctx, STAT_STOP, 0, @$); CHECK_ERROR; }
| tON tERROR tRESUME tNEXT { $$ = new_onerror_statement(ctx, @$, TRUE); CHECK_ERROR; }
| tON tERROR tGOTO '0' { $$ = new_onerror_statement(ctx, @$, FALSE); CHECK_ERROR; }
| tCONST ConstDeclList { $$ = new_const_statement(ctx, @$, $2); CHECK_ERROR; }
| tFOR Identifier '=' Expression tTO Expression Step_opt StSep StatementsNl_opt tNEXT
{ $$ = new_forto_statement(ctx, $2, $4, $6, $7, $9); CHECK_ERROR; }
{ $$ = new_forto_statement(ctx, @$, $2, $4, $6, $7, $9); CHECK_ERROR; }
| tFOR tEACH Identifier tIN Expression StSep StatementsNl_opt tNEXT
{ $$ = new_foreach_statement(ctx, $3, $5, $7); }
{ $$ = new_foreach_statement(ctx, @$, $3, $5, $7); }
| tSELECT tCASE Expression StSep CaseClausules tEND tSELECT
{ $$ = new_select_statement(ctx, $3, $5); }
{ $$ = new_select_statement(ctx, @$, $3, $5); }
| tWITH Expression StSep StatementsNl_opt tEND tWITH
{ $$ = new_with_statement(ctx, @$, $2, $4); }
MemberExpression
: Identifier { $$ = new_member_expression(ctx, NULL, $1); CHECK_ERROR; }
| CallExpression '.' DotIdentifier { $$ = new_member_expression(ctx, $1, $3); CHECK_ERROR; }
| CallExpression '.' tIdentifier { $$ = new_member_expression(ctx, $1, $3); CHECK_ERROR; }
| tDOT tIdentifier { expression_t *dot_expr = new_expression(ctx, EXPR_DOT, sizeof(*dot_expr)); CHECK_ERROR;
$$ = new_member_expression(ctx, dot_expr, $2); CHECK_ERROR; }
Preserve_opt
: /* empty */ { $$ = FALSE; }
| tPRESERVE { $$ = TRUE; }
ReDimDecl
: tIdentifier '(' ArgumentList ')' { $$ = new_redim_decl(ctx, $1, $3); CHECK_ERROR; }
ReDimDeclList
: ReDimDecl { $$ = $1; }
| ReDimDecl ',' ReDimDeclList { $1->next = $3; $$ = $1; }
DimDeclList
: DimDecl { $$ = $1; }
@@ -257,10 +298,10 @@ Step_opt
IfStatement
: tIF Expression tTHEN tNL StatementsNl_opt ElseIfs_opt Else_opt tEND tIF
{ $$ = new_if_statement(ctx, $2, $5, $6, $7); CHECK_ERROR; }
| tIF Expression tTHEN Statement EndIf_opt { $$ = new_if_statement(ctx, $2, $4, NULL, NULL); CHECK_ERROR; }
{ $$ = new_if_statement(ctx, @$, $2, $5, $6, $7); CHECK_ERROR; }
| tIF Expression tTHEN Statement EndIf_opt { $$ = new_if_statement(ctx, @$, $2, $4, NULL, NULL); CHECK_ERROR; }
| tIF Expression tTHEN Statement tELSE Statement EndIf_opt
{ $$ = new_if_statement(ctx, $2, $4, NULL, $6); CHECK_ERROR; }
{ $$ = new_if_statement(ctx, @$, $2, $4, NULL, $6); CHECK_ERROR; }
EndIf_opt
: /* empty */
@@ -275,25 +316,24 @@ ElseIfs
| ElseIf ElseIfs { $1->next = $2; $$ = $1; }
ElseIf
: tELSEIF Expression tTHEN tNL StatementsNl_opt
{ $$ = new_elseif_decl(ctx, $2, $5); }
: tELSEIF Expression tTHEN StSep_opt StatementsNl_opt
{ $$ = new_elseif_decl(ctx, @$, $2, $5); }
Else_opt
: /* empty */ { $$ = NULL; }
| tELSE tNL StatementsNl_opt { $$ = $3; }
| tELSE StSep_opt StatementsNl_opt { $$ = $3; }
CaseClausules
: /* empty */ { $$ = NULL; }
| tCASE tELSE StSep StatementsNl { $$ = new_case_clausule(ctx, NULL, $4, NULL); }
| tCASE ExpressionList StSep StatementsNl_opt CaseClausules
{ $$ = new_case_clausule(ctx, $2, $4, $5); }
: /* empty */ { $$ = NULL; }
| tCASE tELSE StSep_opt StatementsNl_opt { $$ = new_case_clausule(ctx, NULL, $4, NULL); }
| tCASE ExpressionList StSep_opt StatementsNl_opt CaseClausules { $$ = new_case_clausule(ctx, $2, $4, $5); }
Arguments_opt
: EmptyBrackets_opt { $$ = NULL; }
Arguments
: tEMPTYBRACKETS { $$ = NULL; }
| '(' ArgumentList ')' { $$ = $2; }
ArgumentList_opt
: EmptyBrackets_opt { $$ = NULL; }
: /* empty */ { $$ = NULL; }
| ArgumentList { $$ = $1; }
ArgumentList
@@ -369,24 +409,30 @@ MultiplicativeExpression
{ $$ = new_binary_expression(ctx, EXPR_DIV, $1, $3); CHECK_ERROR; }
ExpExpression
: UnaryExpression { $$ = $1; }
| ExpExpression '^' UnaryExpression { $$ = new_binary_expression(ctx, EXPR_EXP, $1, $3); CHECK_ERROR; }
: SignExpression { $$ = $1; }
| ExpExpression '^' SignExpression { $$ = new_binary_expression(ctx, EXPR_EXP, $1, $3); CHECK_ERROR; }
SignExpression
: UnaryExpression { $$ = $1; }
| '-' SignExpression { $$ = new_unary_expression(ctx, EXPR_NEG, $2); CHECK_ERROR; }
| '+' SignExpression { $$ = $2; }
UnaryExpression
: LiteralExpression { $$ = $1; }
| 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; }
| MemberExpression Arguments_opt { $1->args = $2; $$ = &$1->expr; }
: PrimaryExpression { $$ = $1; }
| MemberExpression { $$ = &$1->expr; }
| CallExpression Arguments { call_expression_t *expr = new_call_expression(ctx, $1, $2); CHECK_ERROR;
$$ = &expr->expr; }
LiteralExpression
: tTRUE { $$ = new_bool_expression(ctx, VARIANT_TRUE); CHECK_ERROR; }
| tFALSE { $$ = new_bool_expression(ctx, VARIANT_FALSE); CHECK_ERROR; }
| tString { $$ = new_string_expression(ctx, $1); CHECK_ERROR; }
| tDate { $$ = new_date_expression(ctx, $1); CHECK_ERROR; }
| NumericLiteralExpression { $$ = $1; }
| tEMPTY { $$ = new_expression(ctx, EXPR_EMPTY, 0); CHECK_ERROR; }
| tNULL { $$ = new_expression(ctx, EXPR_NULL, 0); CHECK_ERROR; }
@@ -402,7 +448,7 @@ IntegerValue
| tInt { $$ = $1; }
PrimaryExpression
: '(' Expression ')' { $$ = new_unary_expression(ctx, EXPR_BRACKETS, $2); }
: tEXPRLBRACKET Expression ')' { $$ = new_unary_expression(ctx, EXPR_BRACKETS, $2); }
| tME { $$ = new_expression(ctx, EXPR_ME, 0); CHECK_ERROR; }
ClassDeclaration
@@ -423,17 +469,21 @@ ClassBody
| PropertyDecl StSep ClassBody { $$ = add_class_function(ctx, $3, $1); CHECK_ERROR; }
PropertyDecl
: Storage_opt tPROPERTY tGET tIdentifier ArgumentsDecl_opt StSep BodyStatements tEND tPROPERTY
: Storage_opt tPROPERTY tGET Identifier 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 BodyStatements tEND tPROPERTY
| Storage_opt tPROPERTY tLET Identifier '(' ArgumentDeclList ')' StSep BodyStatements tEND tPROPERTY
{ $$ = new_function_decl(ctx, $4, FUNC_PROPLET, $1, $6, $9); CHECK_ERROR; }
| Storage_opt tPROPERTY tSET tIdentifier '(' ArgumentDecl ')' StSep BodyStatements tEND tPROPERTY
| Storage_opt tPROPERTY tSET Identifier '(' ArgumentDeclList ')' StSep BodyStatements tEND tPROPERTY
{ $$ = new_function_decl(ctx, $4, FUNC_PROPSET, $1, $6, $9); CHECK_ERROR; }
FunctionDecl
: Storage_opt tSUB Identifier ArgumentsDecl_opt StSep BodyStatements tEND tSUB
: Storage_opt tSUB Identifier StSep BodyStatements tEND tSUB
{ $$ = new_function_decl(ctx, $3, FUNC_SUB, $1, NULL, $5); CHECK_ERROR; }
| Storage_opt tSUB Identifier ArgumentsDecl Nl_opt BodyStatements tEND tSUB
{ $$ = new_function_decl(ctx, $3, FUNC_SUB, $1, $4, $6); CHECK_ERROR; }
| Storage_opt tFUNCTION Identifier ArgumentsDecl_opt StSep BodyStatements tEND tFUNCTION
| Storage_opt tFUNCTION Identifier StSep BodyStatements tEND tFUNCTION
{ $$ = new_function_decl(ctx, $3, FUNC_FUNCTION, $1, NULL, $5); CHECK_ERROR; }
| Storage_opt tFUNCTION Identifier ArgumentsDecl Nl_opt BodyStatements tEND tFUNCTION
{ $$ = new_function_decl(ctx, $3, FUNC_FUNCTION, $1, $4, $6); CHECK_ERROR; }
Storage_opt
@@ -446,7 +496,11 @@ Storage
| tPRIVATE { $$ = STORAGE_IS_PRIVATE; }
ArgumentsDecl_opt
: EmptyBrackets_opt { $$ = NULL; }
: /* empty*/ { $$ = 0; }
| ArgumentsDecl { $$ = $1; }
ArgumentsDecl
: tEMPTYBRACKETS { $$ = NULL; }
| '(' ArgumentDeclList ')' { $$ = $2; }
ArgumentDeclList
@@ -461,64 +515,19 @@ ArgumentDecl
/* these keywords may also be an identifier, depending on context */
Identifier
: tIdentifier { $$ = $1; }
| tDEFAULT { $$ = $1; }
| tERROR { $$ = $1; }
| tEXPLICIT { $$ = $1; }
| tPROPERTY { $$ = $1; }
| tSTEP { $$ = $1; }
| tDEFAULT { ctx->last_token = tIdentifier; $$ = $1; }
| tERROR { ctx->last_token = tIdentifier; $$ = $1; }
| tEXPLICIT { ctx->last_token = tIdentifier; $$ = $1; }
| tPROPERTY { ctx->last_token = tIdentifier; $$ = $1; }
| tSTEP { ctx->last_token = tIdentifier; $$ = $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; }
StSep_opt
: /* empty */
| StSep
Nl_opt
: /* empty */
| tNL Nl_opt
/* Most statements accept both new line and ':' as separators */
StSep
@@ -529,8 +538,16 @@ StSep
%%
static int parser_error(parser_ctx_t *ctx, const char *str)
static int parser_error(unsigned *loc, parser_ctx_t *ctx, const char *str)
{
if(ctx->error_loc == -1)
ctx->error_loc = *loc;
if(ctx->hres == S_OK) {
FIXME("%s: %s\n", debugstr_w(ctx->code + *loc), debugstr_a(str));
ctx->hres = E_FAIL;
}else {
WARN("%s: %08lx\n", debugstr_w(ctx->code + *loc), ctx->hres);
}
return 0;
}
@@ -539,12 +556,17 @@ static void source_add_statement(parser_ctx_t *ctx, statement_t *stat)
if(!stat)
return;
/* concatenate both linked lists */
if(ctx->stats) {
ctx->stats_tail->next = stat;
ctx->stats_tail = stat;
}else {
ctx->stats = ctx->stats_tail = stat;
}
/* find new tail */
while(ctx->stats_tail->next) {
ctx->stats_tail=ctx->stats_tail->next;
}
}
static void source_add_class(parser_ctx_t *ctx, class_decl_t *class_decl)
@@ -553,21 +575,14 @@ static void source_add_class(parser_ctx_t *ctx, class_decl_t *class_decl)
ctx->class_decls = class_decl;
}
static void parse_complete(parser_ctx_t *ctx, BOOL option_explicit)
{
ctx->parse_complete = TRUE;
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));
stat = new_statement(ctx, STAT_RETVAL, sizeof(*stat), 0);
if(!stat)
return;
@@ -612,6 +627,18 @@ static expression_t *new_string_expression(parser_ctx_t *ctx, const WCHAR *value
return &expr->expr;
}
static expression_t *new_date_expression(parser_ctx_t *ctx, DATE value)
{
date_expression_t *expr;
expr = new_expression(ctx, EXPR_DATE, sizeof(*expr));
if(!expr)
return NULL;
expr->value = value;
return &expr->expr;
}
static expression_t *new_long_expression(parser_ctx_t *ctx, expression_type_t type, LONG value)
{
int_expression_t *expr;
@@ -671,10 +698,61 @@ static member_expression_t *new_member_expression(parser_ctx_t *ctx, expression_
expr->obj_expr = obj_expr;
expr->identifier = identifier;
expr->args = NULL;
return expr;
}
static call_expression_t *new_call_expression(parser_ctx_t *ctx, expression_t *expr, expression_t *arguments)
{
call_expression_t *call_expr;
call_expr = new_expression(ctx, EXPR_CALL, sizeof(*call_expr));
if(!call_expr)
return NULL;
call_expr->call_expr = expr;
call_expr->args = arguments;
return call_expr;
}
static call_expression_t *make_call_expression(parser_ctx_t *ctx, expression_t *callee_expr, expression_t *arguments)
{
call_expression_t *call_expr;
if(callee_expr->type == EXPR_MEMBER)
return new_call_expression(ctx, callee_expr, arguments);
if(callee_expr->type != EXPR_CALL) {
FIXME("Unhandled for expr type %u\n", callee_expr->type);
ctx->hres = E_FAIL;
return NULL;
}
call_expr = (call_expression_t*)callee_expr;
if(!call_expr->args) {
call_expr->args = arguments;
return call_expr;
}
if(call_expr->args->next) {
FIXME("Invalid syntax: invalid use of parentheses for arguments\n");
ctx->hres = E_FAIL;
return NULL;
}
call_expr->args = new_unary_expression(ctx, EXPR_BRACKETS, call_expr->args);
if(!call_expr->args)
return NULL;
if(!arguments)
return call_expr;
if(arguments->type != EXPR_NOARG) {
FIXME("Invalid syntax: missing comma\n");
ctx->hres = E_FAIL;
return NULL;
}
call_expr->args->next = arguments->next;
return call_expr;
}
static expression_t *new_new_expression(parser_ctx_t *ctx, const WCHAR *identifier)
{
string_expression_t *expr;
@@ -687,55 +765,72 @@ static expression_t *new_new_expression(parser_ctx_t *ctx, const WCHAR *identifi
return &expr->expr;
}
static void *new_statement(parser_ctx_t *ctx, statement_type_t type, size_t size)
static void *new_statement(parser_ctx_t *ctx, statement_type_t type, size_t size, unsigned loc)
{
statement_t *stat;
stat = parser_alloc(ctx, size ? size : sizeof(*stat));
if(stat) {
stat->type = type;
stat->loc = loc;
stat->next = NULL;
}
return stat;
}
static statement_t *new_call_statement(parser_ctx_t *ctx, BOOL is_strict, member_expression_t *expr)
static statement_t *new_call_statement(parser_ctx_t *ctx, unsigned loc, expression_t *expr)
{
call_expression_t *call_expr = NULL;
call_statement_t *stat;
stat = new_statement(ctx, STAT_CALL, sizeof(*stat));
stat = new_statement(ctx, STAT_CALL, sizeof(*stat), loc);
if(!stat)
return NULL;
stat->expr = expr;
stat->is_strict = is_strict;
switch(expr->type) {
case EXPR_MEMBER:
call_expr = new_call_expression(ctx, expr, NULL);
break;
case EXPR_CALL:
call_expr = (call_expression_t*)expr;
break;
default:
FIXME("Unsupported expr type %u\n", expr->type);
ctx->hres = E_NOTIMPL;
}
if(!call_expr)
return NULL;
stat->expr = call_expr;
return &stat->stat;
}
static statement_t *new_assign_statement(parser_ctx_t *ctx, member_expression_t *left, expression_t *right)
static statement_t *new_assign_statement(parser_ctx_t *ctx, unsigned loc, expression_t *left, expression_t *right)
{
assign_statement_t *stat;
stat = new_statement(ctx, STAT_ASSIGN, sizeof(*stat));
stat = new_statement(ctx, STAT_ASSIGN, sizeof(*stat), loc);
if(!stat)
return NULL;
stat->member_expr = left;
stat->left_expr = left;
stat->value_expr = right;
return &stat->stat;
}
static statement_t *new_set_statement(parser_ctx_t *ctx, member_expression_t *left, expression_t *right)
static statement_t *new_set_statement(parser_ctx_t *ctx, unsigned loc, expression_t *left, expression_t *right)
{
assign_statement_t *stat;
stat = new_statement(ctx, STAT_SET, sizeof(*stat));
stat = new_statement(ctx, STAT_SET, sizeof(*stat), loc);
if(!stat)
return NULL;
stat->member_expr = left;
stat->left_expr = left;
stat->value_expr = right;
return &stat->stat;
}
@@ -767,11 +862,11 @@ static dim_list_t *new_dim(parser_ctx_t *ctx, unsigned val, dim_list_t *next)
return ret;
}
static statement_t *new_dim_statement(parser_ctx_t *ctx, dim_decl_t *decls)
static statement_t *new_dim_statement(parser_ctx_t *ctx, unsigned loc, dim_decl_t *decls)
{
dim_statement_t *stat;
stat = new_statement(ctx, STAT_DIM, sizeof(*stat));
stat = new_statement(ctx, STAT_DIM, sizeof(*stat), loc);
if(!stat)
return NULL;
@@ -779,7 +874,34 @@ static statement_t *new_dim_statement(parser_ctx_t *ctx, dim_decl_t *decls)
return &stat->stat;
}
static elseif_decl_t *new_elseif_decl(parser_ctx_t *ctx, expression_t *expr, statement_t *stat)
static redim_decl_t *new_redim_decl(parser_ctx_t *ctx, const WCHAR *identifier, expression_t *dims)
{
redim_decl_t *decl;
decl = parser_alloc(ctx, sizeof(*decl));
if(!decl)
return NULL;
decl->identifier = identifier;
decl->dims = dims;
decl->next = NULL;
return decl;
}
static statement_t *new_redim_statement(parser_ctx_t *ctx, unsigned loc, BOOL preserve, redim_decl_t *decls)
{
redim_statement_t *stat;
stat = new_statement(ctx, STAT_REDIM, sizeof(*stat), loc);
if(!stat)
return NULL;
stat->preserve = preserve;
stat->redim_decls = decls;
return &stat->stat;
}
static elseif_decl_t *new_elseif_decl(parser_ctx_t *ctx, unsigned loc, expression_t *expr, statement_t *stat)
{
elseif_decl_t *decl;
@@ -789,15 +911,16 @@ static elseif_decl_t *new_elseif_decl(parser_ctx_t *ctx, expression_t *expr, sta
decl->expr = expr;
decl->stat = stat;
decl->loc = loc;
decl->next = NULL;
return decl;
}
static statement_t *new_while_statement(parser_ctx_t *ctx, statement_type_t type, expression_t *expr, statement_t *body)
static statement_t *new_while_statement(parser_ctx_t *ctx, unsigned loc, statement_type_t type, expression_t *expr, statement_t *body)
{
while_statement_t *stat;
stat = new_statement(ctx, type, sizeof(*stat));
stat = new_statement(ctx, type, sizeof(*stat), loc);
if(!stat)
return NULL;
@@ -806,12 +929,12 @@ static statement_t *new_while_statement(parser_ctx_t *ctx, statement_type_t type
return &stat->stat;
}
static statement_t *new_forto_statement(parser_ctx_t *ctx, const WCHAR *identifier, expression_t *from_expr,
static statement_t *new_forto_statement(parser_ctx_t *ctx, unsigned loc, const WCHAR *identifier, expression_t *from_expr,
expression_t *to_expr, expression_t *step_expr, statement_t *body)
{
forto_statement_t *stat;
stat = new_statement(ctx, STAT_FORTO, sizeof(*stat));
stat = new_statement(ctx, STAT_FORTO, sizeof(*stat), loc);
if(!stat)
return NULL;
@@ -823,12 +946,12 @@ static statement_t *new_forto_statement(parser_ctx_t *ctx, const WCHAR *identifi
return &stat->stat;
}
static statement_t *new_foreach_statement(parser_ctx_t *ctx, const WCHAR *identifier, expression_t *group_expr,
static statement_t *new_foreach_statement(parser_ctx_t *ctx, unsigned loc, const WCHAR *identifier, expression_t *group_expr,
statement_t *body)
{
foreach_statement_t *stat;
stat = new_statement(ctx, STAT_FOREACH, sizeof(*stat));
stat = new_statement(ctx, STAT_FOREACH, sizeof(*stat), loc);
if(!stat)
return NULL;
@@ -838,12 +961,12 @@ static statement_t *new_foreach_statement(parser_ctx_t *ctx, const WCHAR *identi
return &stat->stat;
}
static statement_t *new_if_statement(parser_ctx_t *ctx, expression_t *expr, statement_t *if_stat, elseif_decl_t *elseif_decl,
static statement_t *new_if_statement(parser_ctx_t *ctx, unsigned loc, expression_t *expr, statement_t *if_stat, elseif_decl_t *elseif_decl,
statement_t *else_stat)
{
if_statement_t *stat;
stat = new_statement(ctx, STAT_IF, sizeof(*stat));
stat = new_statement(ctx, STAT_IF, sizeof(*stat), loc);
if(!stat)
return NULL;
@@ -854,11 +977,11 @@ static statement_t *new_if_statement(parser_ctx_t *ctx, expression_t *expr, stat
return &stat->stat;
}
static statement_t *new_select_statement(parser_ctx_t *ctx, expression_t *expr, case_clausule_t *case_clausules)
static statement_t *new_select_statement(parser_ctx_t *ctx, unsigned loc, expression_t *expr, case_clausule_t *case_clausules)
{
select_statement_t *stat;
stat = new_statement(ctx, STAT_SELECT, sizeof(*stat));
stat = new_statement(ctx, STAT_SELECT, sizeof(*stat), loc);
if(!stat)
return NULL;
@@ -867,6 +990,19 @@ static statement_t *new_select_statement(parser_ctx_t *ctx, expression_t *expr,
return &stat->stat;
}
static statement_t *new_with_statement(parser_ctx_t *ctx, unsigned loc, expression_t *expr, statement_t *body)
{
with_statement_t *stat;
stat = new_statement(ctx, STAT_WITH, sizeof(*stat), loc);
if(!stat)
return NULL;
stat->expr = expr;
stat->body = body;
return &stat->stat;
}
static case_clausule_t *new_case_clausule(parser_ctx_t *ctx, expression_t *expr, statement_t *stat, case_clausule_t *next)
{
case_clausule_t *ret;
@@ -881,11 +1017,11 @@ static case_clausule_t *new_case_clausule(parser_ctx_t *ctx, expression_t *expr,
return ret;
}
static statement_t *new_onerror_statement(parser_ctx_t *ctx, BOOL resume_next)
static statement_t *new_onerror_statement(parser_ctx_t *ctx, unsigned loc, BOOL resume_next)
{
onerror_statement_t *stat;
stat = new_statement(ctx, STAT_ONERROR, sizeof(*stat));
stat = new_statement(ctx, STAT_ONERROR, sizeof(*stat), loc);
if(!stat)
return NULL;
@@ -911,10 +1047,11 @@ static function_decl_t *new_function_decl(parser_ctx_t *ctx, const WCHAR *name,
unsigned storage_flags, arg_decl_t *arg_decl, statement_t *body)
{
function_decl_t *decl;
BOOL is_default = FALSE;
if(storage_flags & STORAGE_IS_DEFAULT) {
if(type == FUNC_PROPGET) {
type = FUNC_DEFGET;
if(type == FUNC_PROPGET || type == FUNC_FUNCTION || type == FUNC_SUB) {
is_default = TRUE;
}else {
FIXME("Invalid default property\n");
ctx->hres = E_FAIL;
@@ -929,6 +1066,7 @@ static function_decl_t *new_function_decl(parser_ctx_t *ctx, const WCHAR *name,
decl->name = name;
decl->type = type;
decl->is_public = !(storage_flags & STORAGE_IS_PRIVATE);
decl->is_default = is_default;
decl->args = arg_decl;
decl->body = body;
decl->next = NULL;
@@ -936,11 +1074,11 @@ static function_decl_t *new_function_decl(parser_ctx_t *ctx, const WCHAR *name,
return decl;
}
static statement_t *new_function_statement(parser_ctx_t *ctx, function_decl_t *decl)
static statement_t *new_function_statement(parser_ctx_t *ctx, unsigned loc, function_decl_t *decl)
{
function_statement_t *stat;
stat = new_statement(ctx, STAT_FUNC, sizeof(*stat));
stat = new_statement(ctx, STAT_FUNC, sizeof(*stat), loc);
if(!stat)
return NULL;
@@ -998,7 +1136,7 @@ static class_decl_t *add_class_function(parser_ctx_t *ctx, class_decl_t *class_d
static class_decl_t *add_dim_prop(parser_ctx_t *ctx, class_decl_t *class_decl, dim_decl_t *dim_decl, unsigned storage_flags)
{
if(storage_flags & STORAGE_IS_DEFAULT) {
FIXME("variant prop van't be default value\n");
FIXME("variant prop can't be default value\n");
ctx->hres = E_FAIL;
return NULL;
}
@@ -1023,11 +1161,11 @@ static const_decl_t *new_const_decl(parser_ctx_t *ctx, const WCHAR *name, expres
return decl;
}
static statement_t *new_const_statement(parser_ctx_t *ctx, const_decl_t *decls)
static statement_t *new_const_statement(parser_ctx_t *ctx, unsigned loc, const_decl_t *decls)
{
const_statement_t *stat;
stat = new_statement(ctx, STAT_CONST, sizeof(*stat));
stat = new_statement(ctx, STAT_CONST, sizeof(*stat), loc);
if(!stat)
return NULL;
@@ -1039,6 +1177,8 @@ static statement_t *link_statements(statement_t *head, statement_t *tail)
{
statement_t *iter;
if (!head) return tail;
for(iter = head; iter->next; iter = iter->next);
iter->next = tail;
@@ -1057,36 +1197,26 @@ void *parser_alloc(parser_ctx_t *ctx, size_t size)
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 + lstrlenW(ctx->code);
heap_pool_init(&ctx->heap);
ctx->parse_complete = FALSE;
ctx->hres = S_OK;
ctx->error_loc = -1;
ctx->last_token = tNL;
ctx->last_nl = 0;
ctx->stats = ctx->stats_tail = NULL;
ctx->class_decls = NULL;
ctx->option_explicit = FALSE;
ctx->is_html = delimiter && !wcsicmp(delimiter, html_delimiterW);
ctx->is_html = delimiter && !wcsicmp(delimiter, L"</script>");
if(flags & SCRIPTTEXT_ISEXPRESSION)
ctx->last_token = tEXPRESSION;
parser_parse(ctx);
if(FAILED(ctx->hres))
return ctx->hres;
if(!ctx->parse_complete) {
FIXME("parser failed around %s\n", debugstr_w(ctx->code+20 > ctx->ptr ? ctx->code : ctx->ptr-20));
return E_FAIL;
}
return S_OK;
return ctx->hres;
}
void parser_release(parser_ctx_t *ctx)
+1
View File
@@ -10,6 +10,7 @@
#include "vbscript.h"
#include <winnls.h>
#include <objsafe.h>
#include <wine/debug.h>
+18 -18
View File
@@ -482,7 +482,7 @@ EmitREBytecode(CompilerState *state, regexp_t *re, size_t treeDepth,
if (treeDepth == 0) {
emitStateStack = NULL;
} else {
emitStateStack = heap_alloc(sizeof(EmitStateStackEntry) * treeDepth);
emitStateStack = malloc(sizeof(EmitStateStackEntry) * treeDepth);
if (!emitStateStack)
return NULL;
}
@@ -788,7 +788,7 @@ EmitREBytecode(CompilerState *state, regexp_t *re, size_t treeDepth,
}
cleanup:
heap_free(emitStateStack);
free(emitStateStack);
return pc;
jump_too_big:
@@ -1667,11 +1667,11 @@ ParseRegExp(CompilerState *state)
return (state->result != NULL);
}
operatorStack = heap_alloc(sizeof(REOpData) * operatorStackSize);
operatorStack = malloc(sizeof(REOpData) * operatorStackSize);
if (!operatorStack)
return FALSE;
operandStack = heap_alloc(sizeof(RENode *) * operandStackSize);
operandStack = malloc(sizeof(RENode *) * operandStackSize);
if (!operandStack)
goto out;
@@ -1762,7 +1762,7 @@ pushOperand:
if (operandSP == operandStackSize) {
RENode **tmp;
operandStackSize += operandStackSize;
tmp = heap_realloc(operandStack, sizeof(RENode *) * operandStackSize);
tmp = realloc(operandStack, sizeof(RENode *) * operandStackSize);
if (!tmp)
goto out;
operandStack = tmp;
@@ -1895,7 +1895,7 @@ pushOperator:
if (operatorSP == operatorStackSize) {
REOpData *tmp;
operatorStackSize += operatorStackSize;
tmp = heap_realloc(operatorStack, sizeof(REOpData) * operatorStackSize);
tmp = realloc(operatorStack, sizeof(REOpData) * operatorStackSize);
if (!tmp)
goto out;
operatorStack = tmp;
@@ -1907,8 +1907,8 @@ pushOperator:
}
}
out:
heap_free(operatorStack);
heap_free(operandStack);
free(operatorStack);
free(operandStack);
return result;
}
@@ -1935,7 +1935,7 @@ PushBackTrackState(REGlobalData *gData, REOp op,
ptrdiff_t btincr = ((char *)result + sz) -
((char *)gData->backTrackStack + btsize);
TRACE("\tBT_Push: %lu,%lu\n", (ULONG_PTR)parenIndex, (ULONG_PTR)parenCount);
TRACE("\tBT_Push: %Iu,%Iu\n", (ULONG_PTR)parenIndex, (ULONG_PTR)parenCount);
JS_COUNT_OPERATION(gData->cx, JSOW_JUMP * (1 + parenCount));
if (btincr > 0) {
@@ -2111,7 +2111,7 @@ ProcessCharSet(REGlobalData *gData, RECharSet *charSet)
assert(src[-1] == '[' && end[0] == ']');
byteLength = (charSet->length >> 3) + 1;
charSet->u.bits = heap_alloc(byteLength);
charSet->u.bits = malloc(byteLength);
if (!charSet->u.bits) {
JS_ReportOutOfMemory(gData->cx);
gData->ok = FALSE;
@@ -2684,7 +2684,7 @@ ExecuteREBytecode(REGlobalData *gData, match_state_t *x)
case REOP_LPAREN:
pc = ReadCompactIndex(pc, &parenIndex);
TRACE("[ %lu ]\n", (ULONG_PTR)parenIndex);
TRACE("[ %Iu ]\n", (ULONG_PTR)parenIndex);
assert(parenIndex < gData->regexp->parenCount);
if (parenIndex + 1 > parenSoFar)
parenSoFar = parenIndex + 1;
@@ -3047,7 +3047,7 @@ ExecuteREBytecode(REGlobalData *gData, match_state_t *x)
parenSoFar = curState->parenSoFar;
}
TRACE("\tBT_Pop: %ld,%ld\n",
TRACE("\tBT_Pop: %Id,%Id\n",
(ULONG_PTR)backTrackData->parenIndex,
(ULONG_PTR)backTrackData->parenCount);
continue;
@@ -3184,12 +3184,12 @@ void regexp_destroy(regexp_t *re)
UINT i;
for (i = 0; i < re->classCount; i++) {
if (re->classList[i].converted)
heap_free(re->classList[i].u.bits);
free(re->classList[i].u.bits);
re->classList[i].u.bits = NULL;
}
heap_free(re->classList);
free(re->classList);
}
heap_free(re);
free(re);
}
regexp_t* regexp_new(void *cx, heap_pool_t *pool, const WCHAR *str,
@@ -3238,14 +3238,14 @@ regexp_t* regexp_new(void *cx, heap_pool_t *pool, const WCHAR *str,
goto out;
}
resize = offsetof(regexp_t, program) + state.progLength + 1;
re = heap_alloc(resize);
re = malloc(resize);
if (!re)
goto out;
assert(state.classBitmapsMem <= CLASS_BITMAPS_MEM_LIMIT);
re->classCount = state.classCount;
if (re->classCount) {
re->classList = heap_alloc(re->classCount * sizeof(RECharSet));
re->classList = malloc(re->classCount * sizeof(RECharSet));
if (!re->classList) {
regexp_destroy(re);
re = NULL;
@@ -3272,7 +3272,7 @@ regexp_t* regexp_new(void *cx, heap_pool_t *pool, const WCHAR *str,
regexp_t *tmp;
assert((size_t)(endPC - re->program) < state.progLength + 1);
resize = offsetof(regexp_t, program) + (endPC - re->program);
tmp = heap_realloc(re, resize);
tmp = realloc(re, resize);
if (tmp)
re = tmp;
}
+5 -5
View File
@@ -63,11 +63,11 @@ typedef struct regexp_t {
jsbytecode program[1]; /* regular expression bytecode */
} regexp_t;
regexp_t* regexp_new(void*, heap_pool_t*, const WCHAR*, DWORD, WORD, BOOL) DECLSPEC_HIDDEN;
void regexp_destroy(regexp_t*) DECLSPEC_HIDDEN;
regexp_t* regexp_new(void*, heap_pool_t*, const WCHAR*, DWORD, WORD, BOOL);
void regexp_destroy(regexp_t*);
HRESULT regexp_execute(regexp_t*, void*, heap_pool_t*, const WCHAR*,
DWORD, match_state_t*) DECLSPEC_HIDDEN;
HRESULT regexp_set_flags(regexp_t**, void*, heap_pool_t*, WORD) DECLSPEC_HIDDEN;
DWORD, match_state_t*);
HRESULT regexp_set_flags(regexp_t**, void*, heap_pool_t*, WORD);
static inline match_state_t* alloc_match_state(regexp_t *regexp,
heap_pool_t *pool, const WCHAR *pos)
@@ -75,7 +75,7 @@ static inline match_state_t* alloc_match_state(regexp_t *regexp,
size_t size = offsetof(match_state_t, parens) + regexp->parenCount*sizeof(RECapture);
match_state_t *ret;
ret = pool ? heap_pool_alloc(pool, size) : heap_alloc(size);
ret = pool ? heap_pool_alloc(pool, size) : malloc(size);
if(!ret)
return NULL;
+13 -8
View File
@@ -28,6 +28,7 @@ typedef struct {
LONG ref;
SAFEARRAY *sa;
BOOL owned;
ULONG i, size;
} safearray_iter;
@@ -62,7 +63,7 @@ static ULONG WINAPI safearray_iter_IEnumVARIANT_AddRef(IEnumVARIANT *iface)
safearray_iter *This = impl_from_IEnumVARIANT(iface);
LONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
TRACE("(%p) ref=%ld\n", This, ref);
return ref;
}
@@ -72,12 +73,15 @@ static ULONG WINAPI safearray_iter_IEnumVARIANT_Release(IEnumVARIANT *iface)
safearray_iter *This = impl_from_IEnumVARIANT(iface);
LONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%d\n", iface, ref);
TRACE("(%p) ref=%ld\n", iface, ref);
if(!ref) {
if(This->sa)
if(This->sa) {
SafeArrayUnlock(This->sa);
heap_free(This);
if(This->owned)
SafeArrayDestroy(This->sa);
}
free(This);
}
return ref;
@@ -90,7 +94,7 @@ static HRESULT WINAPI safearray_iter_IEnumVARIANT_Next(IEnumVARIANT *iface,
HRESULT hres;
VARIANT *v;
TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched);
TRACE("(%p)->(%lu %p %p)\n", This, celt, rgVar, pCeltFetched);
if(celt != 1) {
FIXME("celt != 1\n");
@@ -160,7 +164,7 @@ static ULONG get_safearray_size(SAFEARRAY *sa)
return ret;
}
HRESULT create_safearray_iter(SAFEARRAY *sa, IEnumVARIANT **ev)
HRESULT create_safearray_iter(SAFEARRAY *sa, BOOL owned, IEnumVARIANT **ev)
{
safearray_iter *iter;
HRESULT hres;
@@ -170,14 +174,14 @@ HRESULT create_safearray_iter(SAFEARRAY *sa, IEnumVARIANT **ev)
return E_NOTIMPL;
}
iter = heap_alloc(sizeof(*iter));
iter = malloc(sizeof(*iter));
if(!iter)
return E_OUTOFMEMORY;
if(sa) {
hres = SafeArrayLock(sa);
if(FAILED(hres)) {
heap_free(iter);
free(iter);
return hres;
}
}
@@ -185,6 +189,7 @@ HRESULT create_safearray_iter(SAFEARRAY *sa, IEnumVARIANT **ev)
iter->IEnumVARIANT_iface.lpVtbl = &safearray_iter_EnumVARIANTVtbl;
iter->ref = 1;
iter->sa = sa;
iter->owned = owned;
iter->i = 0;
iter->size = get_safearray_size(sa);
File diff suppressed because it is too large Load Diff
+274 -59
View File
@@ -19,6 +19,7 @@
#include "vbscript.h"
#include "regexp.h"
#include "vbsregexp55.h"
#include "wchar.h"
#include "wine/debug.h"
@@ -51,12 +52,11 @@ static HRESULT init_regexp_typeinfo(regexp_tid_t tid)
HRESULT hres;
if(!typelib) {
static const WCHAR vbscript_dll3W[] = {'v','b','s','c','r','i','p','t','.','d','l','l','\\','3',0};
ITypeLib *tl;
hres = LoadTypeLib(vbscript_dll3W, &tl);
hres = LoadTypeLib(L"vbscript.dll\\3", &tl);
if(FAILED(hres)) {
ERR("LoadRegTypeLib failed: %08x\n", hres);
ERR("LoadRegTypeLib failed: %08lx\n", hres);
return hres;
}
@@ -69,7 +69,7 @@ static HRESULT init_regexp_typeinfo(regexp_tid_t tid)
hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
if(FAILED(hres)) {
ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hres);
ERR("GetTypeInfoOfGuid(%s) failed: %08lx\n", debugstr_guid(tid_ids[tid]), hres);
return hres;
}
@@ -170,7 +170,7 @@ static ULONG WINAPI SubMatches_AddRef(ISubMatches *iface)
SubMatches *This = impl_from_ISubMatches(iface);
LONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
TRACE("(%p) ref=%ld\n", This, ref);
return ref;
}
@@ -180,12 +180,12 @@ static ULONG WINAPI SubMatches_Release(ISubMatches *iface)
SubMatches *This = impl_from_ISubMatches(iface);
LONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
TRACE("(%p) ref=%ld\n", This, ref);
if(!ref) {
heap_free(This->match);
heap_free(This->result);
heap_free(This);
free(This->match);
free(This->result);
free(This);
}
return ref;
@@ -205,7 +205,7 @@ static HRESULT WINAPI SubMatches_GetTypeInfo(ISubMatches *iface,
UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
{
SubMatches *This = impl_from_ISubMatches(iface);
FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
FIXME("(%p)->(%u %lu %p)\n", This, iTInfo, lcid, ppTInfo);
return E_NOTIMPL;
}
@@ -214,7 +214,7 @@ static HRESULT WINAPI SubMatches_GetIDsOfNames(ISubMatches *iface,
{
SubMatches *This = impl_from_ISubMatches(iface);
TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
TRACE("(%p)->(%s %p %u %lu %p)\n", This, debugstr_guid(riid),
rgszNames, cNames, lcid, rgDispId);
return ITypeInfo_GetIDsOfNames(typeinfos[SubMatches_tid], rgszNames, cNames, rgDispId);
@@ -226,7 +226,7 @@ static HRESULT WINAPI SubMatches_Invoke(ISubMatches *iface, DISPID dispIdMember,
{
SubMatches *This = impl_from_ISubMatches(iface);
TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
TRACE("(%p)->(%ld %s %ld %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
return ITypeInfo_Invoke(typeinfos[SubMatches_tid], iface, dispIdMember, wFlags,
@@ -238,7 +238,7 @@ static HRESULT WINAPI SubMatches_get_Item(ISubMatches *iface,
{
SubMatches *This = impl_from_ISubMatches(iface);
TRACE("(%p)->(%d %p)\n", This, index, pSubMatch);
TRACE("(%p)->(%ld %p)\n", This, index, pSubMatch);
if(!pSubMatch)
return E_POINTER;
@@ -307,7 +307,7 @@ static HRESULT create_sub_matches(DWORD pos, match_state_t *result, SubMatches *
if(FAILED(hres))
return hres;
ret = heap_alloc_zero(sizeof(*ret));
ret = calloc(1, sizeof(*ret));
if(!ret)
return E_OUTOFMEMORY;
@@ -315,9 +315,9 @@ static HRESULT create_sub_matches(DWORD pos, match_state_t *result, SubMatches *
ret->result = result;
if(result) {
ret->match = heap_alloc((result->match_len+1) * sizeof(WCHAR));
ret->match = malloc((result->match_len+1) * sizeof(WCHAR));
if(!ret->match) {
heap_free(ret);
free(ret);
return E_OUTOFMEMORY;
}
memcpy(ret->match, result->cp-result->match_len, result->match_len*sizeof(WCHAR));
@@ -377,7 +377,7 @@ static ULONG WINAPI Match2_AddRef(IMatch2 *iface)
Match2 *This = impl_from_IMatch2(iface);
LONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
TRACE("(%p) ref=%ld\n", This, ref);
return ref;
}
@@ -387,11 +387,11 @@ static ULONG WINAPI Match2_Release(IMatch2 *iface)
Match2 *This = impl_from_IMatch2(iface);
LONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
TRACE("(%p) ref=%ld\n", This, ref);
if(!ref) {
ISubMatches_Release(&This->sub_matches->ISubMatches_iface);
heap_free(This);
free(This);
}
return ref;
@@ -411,7 +411,7 @@ static HRESULT WINAPI Match2_GetTypeInfo(IMatch2 *iface,
UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
{
Match2 *This = impl_from_IMatch2(iface);
FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
FIXME("(%p)->(%u %lu %p)\n", This, iTInfo, lcid, ppTInfo);
return E_NOTIMPL;
}
@@ -420,7 +420,7 @@ static HRESULT WINAPI Match2_GetIDsOfNames(IMatch2 *iface,
{
Match2 *This = impl_from_IMatch2(iface);
TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
TRACE("(%p)->(%s %p %u %lu %p)\n", This, debugstr_guid(riid),
rgszNames, cNames, lcid, rgDispId);
return ITypeInfo_GetIDsOfNames(typeinfos[Match2_tid], rgszNames, cNames, rgDispId);
@@ -432,7 +432,7 @@ static HRESULT WINAPI Match2_Invoke(IMatch2 *iface, DISPID dispIdMember,
{
Match2 *This = impl_from_IMatch2(iface);
TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
TRACE("(%p)->(%ld %s %ld %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
return ITypeInfo_Invoke(typeinfos[Match2_tid], iface, dispIdMember, wFlags,
@@ -605,14 +605,14 @@ static HRESULT create_match2(DWORD pos, match_state_t **result, IMatch2 **match)
if(FAILED(hres))
return hres;
ret = heap_alloc_zero(sizeof(*ret));
ret = calloc(1, sizeof(*ret));
if(!ret)
return E_OUTOFMEMORY;
ret->index = pos;
hres = create_sub_matches(pos, result ? *result : NULL, &ret->sub_matches);
if(FAILED(hres)) {
heap_free(ret);
free(ret);
return hres;
}
if(result)
@@ -657,7 +657,7 @@ static ULONG WINAPI MatchCollectionEnum_AddRef(IEnumVARIANT *iface)
MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
LONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
TRACE("(%p) ref=%ld\n", This, ref);
return ref;
}
@@ -667,11 +667,11 @@ static ULONG WINAPI MatchCollectionEnum_Release(IEnumVARIANT *iface)
MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
LONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
TRACE("(%p) ref=%ld\n", This, ref);
if(!ref) {
IMatchCollection2_Release(This->mc);
heap_free(This);
free(This);
}
return ref;
@@ -684,7 +684,7 @@ static HRESULT WINAPI MatchCollectionEnum_Next(IEnumVARIANT *iface,
DWORD i;
HRESULT hres = S_OK;
TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched);
TRACE("(%p)->(%lu %p %p)\n", This, celt, rgVar, pCeltFetched);
if(This->pos>=This->count) {
if(pCeltFetched)
@@ -714,7 +714,7 @@ static HRESULT WINAPI MatchCollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt)
{
MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
TRACE("(%p)->(%u)\n", This, celt);
TRACE("(%p)->(%lu)\n", This, celt);
if(This->pos+celt <= This->count)
This->pos += celt;
@@ -754,7 +754,7 @@ static HRESULT create_enum_variant_mc2(IMatchCollection2 *mc, ULONG pos, IEnumVA
{
MatchCollectionEnum *ret;
ret = heap_alloc_zero(sizeof(*ret));
ret = calloc(1, sizeof(*ret));
if(!ret)
return E_OUTOFMEMORY;
@@ -810,7 +810,7 @@ static ULONG WINAPI MatchCollection2_AddRef(IMatchCollection2 *iface)
MatchCollection2 *This = impl_from_IMatchCollection2(iface);
LONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
TRACE("(%p) ref=%ld\n", This, ref);
return ref;
}
@@ -820,16 +820,16 @@ static ULONG WINAPI MatchCollection2_Release(IMatchCollection2 *iface)
MatchCollection2 *This = impl_from_IMatchCollection2(iface);
LONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
TRACE("(%p) ref=%ld\n", This, ref);
if(!ref) {
DWORD i;
for(i=0; i<This->count; i++)
IMatch2_Release(This->matches[i]);
heap_free(This->matches);
free(This->matches);
heap_free(This);
free(This);
}
return ref;
@@ -849,7 +849,7 @@ static HRESULT WINAPI MatchCollection2_GetTypeInfo(IMatchCollection2 *iface,
UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
{
MatchCollection2 *This = impl_from_IMatchCollection2(iface);
FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
FIXME("(%p)->(%u %lu %p)\n", This, iTInfo, lcid, ppTInfo);
return E_NOTIMPL;
}
@@ -858,7 +858,7 @@ static HRESULT WINAPI MatchCollection2_GetIDsOfNames(IMatchCollection2 *iface,
{
MatchCollection2 *This = impl_from_IMatchCollection2(iface);
TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
TRACE("(%p)->(%s %p %u %lu %p)\n", This, debugstr_guid(riid),
rgszNames, cNames, lcid, rgDispId);
return ITypeInfo_GetIDsOfNames(typeinfos[MatchCollection2_tid], rgszNames, cNames, rgDispId);
@@ -870,7 +870,7 @@ static HRESULT WINAPI MatchCollection2_Invoke(IMatchCollection2 *iface, DISPID d
{
MatchCollection2 *This = impl_from_IMatchCollection2(iface);
TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
TRACE("(%p)->(%ld %s %ld %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
return ITypeInfo_Invoke(typeinfos[MatchCollection2_tid], iface, dispIdMember, wFlags,
@@ -1024,12 +1024,12 @@ static HRESULT add_match(IMatchCollection2 *iface, IMatch2 *add)
TRACE("(%p)->(%p)\n", This, add);
if(!This->size) {
This->matches = heap_alloc(8*sizeof(IMatch*));
This->matches = malloc(8 * sizeof(*This->matches));
if(!This->matches)
return E_OUTOFMEMORY;
This->size = 8;
}else if(This->size == This->count) {
IMatch2 **new_matches = heap_realloc(This->matches, 2*This->size*sizeof(IMatch*));
IMatch2 **new_matches = realloc(This->matches, 2 * This->size * sizeof(*This->matches));
if(!new_matches)
return E_OUTOFMEMORY;
@@ -1051,7 +1051,7 @@ static HRESULT create_match_collection2(IMatchCollection2 **match_collection)
if(FAILED(hres))
return hres;
ret = heap_alloc_zero(sizeof(*ret));
ret = calloc(1, sizeof(*ret));
if(!ret)
return E_OUTOFMEMORY;
@@ -1103,7 +1103,7 @@ static ULONG WINAPI RegExp2_AddRef(IRegExp2 *iface)
RegExp2 *This = impl_from_IRegExp2(iface);
LONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
TRACE("(%p) ref=%ld\n", This, ref);
return ref;
}
@@ -1113,14 +1113,14 @@ static ULONG WINAPI RegExp2_Release(IRegExp2 *iface)
RegExp2 *This = impl_from_IRegExp2(iface);
LONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
TRACE("(%p) ref=%ld\n", This, ref);
if(!ref) {
heap_free(This->pattern);
free(This->pattern);
if(This->regexp)
regexp_destroy(This->regexp);
heap_pool_free(&This->pool);
heap_free(This);
free(This);
}
return ref;
@@ -1140,8 +1140,12 @@ static HRESULT WINAPI RegExp2_GetTypeInfo(IRegExp2 *iface,
UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
{
RegExp2 *This = impl_from_IRegExp2(iface);
FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
return E_NOTIMPL;
TRACE("(%p)->(%u %lu %p)\n", This, iTInfo, lcid, ppTInfo);
*ppTInfo = typeinfos[RegExp2_tid];
ITypeInfo_AddRef(*ppTInfo);
return S_OK;
}
static HRESULT WINAPI RegExp2_GetIDsOfNames(IRegExp2 *iface, REFIID riid,
@@ -1149,7 +1153,7 @@ static HRESULT WINAPI RegExp2_GetIDsOfNames(IRegExp2 *iface, REFIID riid,
{
RegExp2 *This = impl_from_IRegExp2(iface);
TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
TRACE("(%p)->(%s %p %u %lu %p)\n", This, debugstr_guid(riid),
rgszNames, cNames, lcid, rgDispId);
return ITypeInfo_GetIDsOfNames(typeinfos[RegExp2_tid], rgszNames, cNames, rgDispId);
@@ -1161,7 +1165,7 @@ static HRESULT WINAPI RegExp2_Invoke(IRegExp2 *iface, DISPID dispIdMember,
{
RegExp2 *This = impl_from_IRegExp2(iface);
TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
TRACE("(%p)->(%ld %s %ld %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
return ITypeInfo_Invoke(typeinfos[RegExp2_tid], iface, dispIdMember, wFlags,
@@ -1195,7 +1199,7 @@ static HRESULT WINAPI RegExp2_put_Pattern(IRegExp2 *iface, BSTR pattern)
if(pattern && *pattern) {
SIZE_T size = (SysStringLen(pattern)+1) * sizeof(WCHAR);
new_pattern = heap_alloc(size);
new_pattern = malloc(size);
if(!new_pattern)
return E_OUTOFMEMORY;
memcpy(new_pattern, pattern, size);
@@ -1203,7 +1207,7 @@ static HRESULT WINAPI RegExp2_put_Pattern(IRegExp2 *iface, BSTR pattern)
new_pattern = NULL;
}
heap_free(This->pattern);
free(This->pattern);
This->pattern = new_pattern;
if(This->regexp) {
@@ -1316,9 +1320,9 @@ static HRESULT WINAPI RegExp2_Execute(IRegExp2 *iface,
break;
hres = add_match(match_collection, add);
IMatch2_Release(add);
if(FAILED(hres))
break;
IMatch2_Release(add);
if(!(This->flags & REG_GLOB))
break;
@@ -1359,13 +1363,13 @@ static HRESULT WINAPI RegExp2_Execute(IRegExp2 *iface,
hres = regexp_execute(This->regexp, NULL, &This->pool,
sourceString, SysStringLen(sourceString), result);
if(hres != S_OK) {
heap_free(result);
free(result);
break;
}
pos = result->cp;
hres = create_match2(result->cp-result->match_len-sourceString, &result, &add);
heap_free(result);
free(result);
if(FAILED(hres))
break;
hres = add_match(match_collection, add);
@@ -1432,13 +1436,179 @@ static HRESULT WINAPI RegExp2_Test(IRegExp2 *iface, BSTR sourceString, VARIANT_B
return hres;
}
static HRESULT WINAPI RegExp2_Replace(IRegExp2 *iface, BSTR sourceString,
VARIANT replaceVar, BSTR *pDestString)
typedef struct {
WCHAR *buf;
DWORD size;
DWORD len;
} strbuf_t;
static BOOL strbuf_ensure_size(strbuf_t *buf, unsigned len)
{
WCHAR *new_buf;
DWORD new_size;
if(len <= buf->size)
return TRUE;
new_size = buf->size ? buf->size<<1 : 16;
if(new_size < len)
new_size = len;
if(buf->buf)
new_buf = realloc(buf->buf, new_size*sizeof(WCHAR));
else
new_buf = malloc(new_size*sizeof(WCHAR));
if(!new_buf)
return FALSE;
buf->buf = new_buf;
buf->size = new_size;
return TRUE;
}
static HRESULT strbuf_append(strbuf_t *buf, const WCHAR *str, DWORD len)
{
if(!len)
return S_OK;
if(!strbuf_ensure_size(buf, buf->len+len))
return E_OUTOFMEMORY;
memcpy(buf->buf+buf->len, str, len*sizeof(WCHAR));
buf->len += len;
return S_OK;
}
static HRESULT WINAPI RegExp2_Replace(IRegExp2 *iface, BSTR source, VARIANT replaceVar, BSTR *ret)
{
RegExp2 *This = impl_from_IRegExp2(iface);
FIXME("(%p)->(%s %s %p)\n", This, debugstr_w(sourceString),
debugstr_variant(&replaceVar), pDestString);
return E_NOTIMPL;
const WCHAR *cp, *prev_cp = NULL, *ptr, *prev_ptr;
size_t match_len = 0, source_len, replace_len;
strbuf_t buf = { NULL, 0, 0 };
match_state_t *state = NULL;
heap_pool_t *mark;
VARIANT strv;
BSTR replace;
HRESULT hres;
TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(source), debugstr_variant(&replaceVar), ret);
if(This->pattern) {
if(!This->regexp) {
This->regexp = regexp_new(NULL, &This->pool, This->pattern,
lstrlenW(This->pattern), This->flags, FALSE);
if(!This->regexp)
return E_OUTOFMEMORY;
}else {
hres = regexp_set_flags(&This->regexp, NULL, &This->pool, This->flags);
if(FAILED(hres))
return hres;
}
}
V_VT(&strv) = VT_EMPTY;
hres = VariantChangeType(&strv, &replaceVar, 0, VT_BSTR);
if(FAILED(hres))
return hres;
replace = V_BSTR(&strv);
replace_len = SysStringLen(replace);
source_len = SysStringLen(source);
mark = heap_pool_mark(&This->pool);
cp = source;
if(This->regexp && !(state = alloc_match_state(This->regexp, &This->pool, cp)))
hres = E_OUTOFMEMORY;
while(SUCCEEDED(hres)) {
if(This->regexp) {
prev_cp = cp;
hres = regexp_execute(This->regexp, NULL, &This->pool, source, source_len, state);
if(hres != S_OK) break;
cp = state->cp;
match_len = state->match_len;
}else if(prev_cp) {
if(cp == source + source_len)
break;
prev_cp = cp++;
}else {
prev_cp = cp;
}
hres = strbuf_append(&buf, prev_cp, cp - prev_cp - match_len);
if(FAILED(hres))
break;
prev_ptr = replace;
while((ptr = wmemchr(prev_ptr, '$', replace + replace_len - prev_ptr))) {
hres = strbuf_append(&buf, prev_ptr, ptr - prev_ptr);
if(FAILED(hres))
break;
switch(ptr[1]) {
case '$':
hres = strbuf_append(&buf, ptr, 1);
prev_ptr = ptr + 2;
break;
case '&':
hres = strbuf_append(&buf, cp - match_len, match_len);
prev_ptr = ptr + 2;
break;
case '`':
hres = strbuf_append(&buf, source, cp - source - match_len);
prev_ptr = ptr + 2;
break;
case '\'':
hres = strbuf_append(&buf, cp, source + source_len - cp);
prev_ptr = ptr + 2;
break;
default: {
DWORD idx;
if(!is_digit(ptr[1])) {
hres = strbuf_append(&buf, ptr, 1);
prev_ptr = ptr + 1;
break;
}
idx = ptr[1] - '0';
if(is_digit(ptr[2]) && idx * 10 + (ptr[2] - '0') <= state->paren_count) {
idx = idx * 10 + (ptr[2] - '0');
prev_ptr = ptr + 3;
}else if(idx && idx <= state->paren_count) {
prev_ptr = ptr + 2;
}else {
hres = strbuf_append(&buf, ptr, 1);
prev_ptr = ptr + 1;
break;
}
if(state->parens[idx - 1].index != -1)
hres = strbuf_append(&buf, source + state->parens[idx - 1].index,
state->parens[idx - 1].length);
break;
}
}
if(FAILED(hres))
break;
}
if(SUCCEEDED(hres))
hres = strbuf_append(&buf, prev_ptr, replace + replace_len - prev_ptr);
if(FAILED(hres))
break;
if(!(This->flags & REG_GLOB))
break;
}
if(SUCCEEDED(hres)) {
hres = strbuf_append(&buf, cp, source + source_len - cp);
if(SUCCEEDED(hres) && !(*ret = SysAllocStringLen(buf.buf, buf.len)))
hres = E_OUTOFMEMORY;
}
heap_pool_clear(mark);
free(buf.buf);
SysFreeString(replace);
return hres;
}
static const IRegExp2Vtbl RegExp2Vtbl = {
@@ -1462,6 +1632,51 @@ static const IRegExp2Vtbl RegExp2Vtbl = {
RegExp2_Replace
};
BSTR string_replace(BSTR string, BSTR find, BSTR replace, int from, int cnt, int mode)
{
const WCHAR *ptr, *string_end;
strbuf_t buf = { NULL, 0, 0 };
size_t replace_len, find_len;
BSTR ret = NULL;
HRESULT hres = S_OK;
int pos;
string_end = string + SysStringLen(string);
ptr = from > SysStringLen(string) ? string_end : string + from;
find_len = SysStringLen(find);
replace_len = SysStringLen(replace);
while(string_end - ptr >= find_len && cnt && find_len) {
pos = FindStringOrdinal(FIND_FROMSTART, ptr, string_end - ptr,
find, find_len, mode);
if(pos == -1)
break;
else {
hres = strbuf_append(&buf, ptr, pos);
if(FAILED(hres))
break;
hres = strbuf_append(&buf, replace, replace_len);
if(FAILED(hres))
break;
ptr = ptr + pos + find_len;
if(cnt != -1)
cnt--;
}
}
if(SUCCEEDED(hres)) {
hres = strbuf_append(&buf, ptr, string_end - ptr);
if(SUCCEEDED(hres))
ret = SysAllocStringLen(buf.buf, buf.len);
}
free(buf.buf);
return ret;
}
static inline RegExp2 *impl_from_IRegExp(IRegExp *iface)
{
return CONTAINING_RECORD(iface, RegExp2, IRegExp_iface);
@@ -1602,7 +1817,7 @@ HRESULT create_regexp(IDispatch **ret)
if(FAILED(hres))
return hres;
regexp = heap_alloc_zero(sizeof(*regexp));
regexp = calloc(1, sizeof(*regexp));
if(!regexp)
return E_OUTOFMEMORY;
+398 -119
View File
@@ -61,8 +61,19 @@ typedef struct {
IActiveScriptError IActiveScriptError_iface;
LONG ref;
EXCEPINFO ei;
DWORD_PTR cookie;
unsigned line;
unsigned character;
} VBScriptError;
static inline WCHAR *heap_pool_strdup(heap_pool_t *heap, const WCHAR *str)
{
size_t size = (lstrlenW(str) + 1) * sizeof(WCHAR);
WCHAR *ret = heap_pool_alloc(heap, size);
if (ret) memcpy(ret, str, size);
return ret;
}
static void change_state(VBScript *This, SCRIPTSTATE state)
{
if(This->state == state)
@@ -82,8 +93,105 @@ static inline BOOL is_started(VBScript *This)
static HRESULT exec_global_code(script_ctx_t *ctx, vbscode_t *code, VARIANT *res)
{
ScriptDisp *obj = ctx->script_obj;
function_t *func_iter, **new_funcs;
dynamic_var_t *var, **new_vars;
IServiceProvider *prev_caller;
size_t cnt, i;
HRESULT hres;
if(code->named_item) {
if(!code->named_item->script_obj) {
hres = create_script_disp(ctx, &code->named_item->script_obj);
if(FAILED(hres)) return hres;
}
obj = code->named_item->script_obj;
}
cnt = obj->global_vars_cnt + code->main_code.var_cnt;
if (cnt > obj->global_vars_size)
{
if (obj->global_vars)
new_vars = realloc(obj->global_vars, cnt * sizeof(*new_vars));
else
new_vars = malloc(cnt * sizeof(*new_vars));
if (!new_vars)
return E_OUTOFMEMORY;
obj->global_vars = new_vars;
obj->global_vars_size = cnt;
}
cnt = obj->global_funcs_cnt;
for (func_iter = code->funcs; func_iter; func_iter = func_iter->next)
cnt++;
if (cnt > obj->global_funcs_size)
{
if (obj->global_funcs)
new_funcs = realloc(obj->global_funcs, cnt * sizeof(*new_funcs));
else
new_funcs = malloc(cnt * sizeof(*new_funcs));
if (!new_funcs)
return E_OUTOFMEMORY;
obj->global_funcs = new_funcs;
obj->global_funcs_size = cnt;
}
for (i = 0; i < code->main_code.var_cnt; i++)
{
if (!(var = heap_pool_alloc(&obj->heap, sizeof(*var))))
return E_OUTOFMEMORY;
var->name = heap_pool_strdup(&obj->heap, code->main_code.vars[i].name);
if (!var->name)
return E_OUTOFMEMORY;
V_VT(&var->v) = VT_EMPTY;
var->is_const = FALSE;
var->array = NULL;
obj->global_vars[obj->global_vars_cnt + i] = var;
}
obj->global_vars_cnt += code->main_code.var_cnt;
for (func_iter = code->funcs; func_iter; func_iter = func_iter->next)
{
for (i = 0; i < obj->global_funcs_cnt; i++)
{
if (!wcsicmp(obj->global_funcs[i]->name, func_iter->name))
{
/* global function already exists, replace it */
obj->global_funcs[i] = func_iter;
break;
}
}
if (i == obj->global_funcs_cnt)
obj->global_funcs[obj->global_funcs_cnt++] = func_iter;
}
if (code->classes)
{
class_desc_t *class = code->classes;
while (1)
{
class->ctx = ctx;
if (!class->next)
break;
class = class->next;
}
class->next = obj->classes;
obj->classes = code->classes;
code->last_class = class;
}
code->pending_exec = FALSE;
return exec_script(ctx, TRUE, &code->main_code, NULL, NULL, res);
prev_caller = ctx->vbcaller->caller;
ctx->vbcaller->caller = SP_CALLER_UNINITIALIZED;
hres = exec_script(ctx, TRUE, &code->main_code, NULL, NULL, res);
ctx->vbcaller->caller = prev_caller;
return hres;
}
static void exec_queued_code(script_ctx_t *ctx)
@@ -96,68 +204,104 @@ static void exec_queued_code(script_ctx_t *ctx)
}
}
IDispatch *lookup_named_item(script_ctx_t *ctx, const WCHAR *name, unsigned flags)
static HRESULT retrieve_named_item_disp(IActiveScriptSite *site, named_item_t *item)
{
IUnknown *unk;
HRESULT hres;
hres = IActiveScriptSite_GetItemInfo(site, item->name, SCRIPTINFO_IUNKNOWN, &unk, NULL);
if(FAILED(hres)) {
WARN("GetItemInfo failed: %08lx\n", hres);
return hres;
}
hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&item->disp);
IUnknown_Release(unk);
if(FAILED(hres)) {
WARN("object does not implement IDispatch\n");
return hres;
}
return S_OK;
}
named_item_t *lookup_named_item(script_ctx_t *ctx, const WCHAR *name, unsigned flags)
{
named_item_t *item;
HRESULT hres;
LIST_FOR_EACH_ENTRY(item, &ctx->named_items, named_item_t, entry) {
if((item->flags & flags) == flags && !wcsicmp(item->name, name)) {
if(!item->disp) {
IUnknown *unk;
hres = IActiveScriptSite_GetItemInfo(ctx->site, item->name,
SCRIPTINFO_IUNKNOWN, &unk, NULL);
if(FAILED(hres)) {
WARN("GetItemInfo failed: %08x\n", hres);
continue;
}
hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&item->disp);
IUnknown_Release(unk);
if(FAILED(hres)) {
WARN("object does not implement IDispatch\n");
continue;
}
if(!item->script_obj && !(item->flags & SCRIPTITEM_GLOBALMEMBERS)) {
hres = create_script_disp(ctx, &item->script_obj);
if(FAILED(hres)) return NULL;
}
return item->disp;
if(!item->disp && (flags || !(item->flags & SCRIPTITEM_CODEONLY))) {
hres = retrieve_named_item_disp(ctx->site, item);
if(FAILED(hres)) continue;
}
return item;
}
}
return NULL;
}
static void release_named_item_script_obj(named_item_t *item)
{
if(!item->script_obj) return;
item->script_obj->ctx = NULL;
IDispatchEx_Release(&item->script_obj->IDispatchEx_iface);
item->script_obj = NULL;
}
void release_named_item(named_item_t *item)
{
if(--item->ref) return;
free(item->name);
free(item);
}
static void release_script(script_ctx_t *ctx)
{
class_desc_t *class_desc;
named_item_t *item, *item_next;
vbscode_t *code, *code_next;
collect_objects(ctx);
clear_ei(&ctx->ei);
release_dynamic_vars(ctx->global_vars);
ctx->global_vars = NULL;
while(!list_empty(&ctx->named_items)) {
named_item_t *iter = LIST_ENTRY(list_head(&ctx->named_items), named_item_t, entry);
list_remove(&iter->entry);
if(iter->disp)
IDispatch_Release(iter->disp);
heap_free(iter->name);
heap_free(iter);
LIST_FOR_EACH_ENTRY_SAFE(code, code_next, &ctx->code_list, vbscode_t, entry)
{
if(code->is_persistent)
{
code->pending_exec = TRUE;
if(code->last_class) code->last_class->next = NULL;
if(code->named_item) release_named_item_script_obj(code->named_item);
}
else
{
list_remove(&code->entry);
release_vbscode(code);
}
}
while(ctx->procs) {
class_desc = ctx->procs;
ctx->procs = class_desc->next;
heap_free(class_desc);
}
if(ctx->host_global) {
IDispatch_Release(ctx->host_global);
ctx->host_global = NULL;
LIST_FOR_EACH_ENTRY_SAFE(item, item_next, &ctx->named_items, named_item_t, entry)
{
if(item->disp)
{
IDispatch_Release(item->disp);
item->disp = NULL;
}
release_named_item_script_obj(item);
if(!(item->flags & SCRIPTITEM_ISPERSISTENT))
{
list_remove(&item->entry);
release_named_item(item);
}
}
if(ctx->secmgr) {
@@ -177,19 +321,25 @@ static void release_script(script_ctx_t *ctx)
script_obj->ctx = NULL;
IDispatchEx_Release(&script_obj->IDispatchEx_iface);
}
detach_global_objects(ctx);
heap_pool_free(&ctx->heap);
heap_pool_init(&ctx->heap);
}
static void destroy_script(script_ctx_t *ctx)
static void release_code_list(script_ctx_t *ctx)
{
while(!list_empty(&ctx->code_list))
release_vbscode(LIST_ENTRY(list_head(&ctx->code_list), vbscode_t, entry));
while(!list_empty(&ctx->code_list)) {
vbscode_t *iter = LIST_ENTRY(list_head(&ctx->code_list), vbscode_t, entry);
release_script(ctx);
heap_free(ctx);
list_remove(&iter->entry);
release_vbscode(iter);
}
}
static void release_named_item_list(script_ctx_t *ctx)
{
while(!list_empty(&ctx->named_items)) {
named_item_t *iter = LIST_ENTRY(list_head(&ctx->named_items), named_item_t, entry);
list_remove(&iter->entry);
release_named_item(iter);
}
}
static void decrease_state(VBScript *This, SCRIPTSTATE state)
@@ -202,16 +352,19 @@ static void decrease_state(VBScript *This, SCRIPTSTATE state)
/* FALLTHROUGH */
case SCRIPTSTATE_STARTED:
case SCRIPTSTATE_DISCONNECTED:
if(This->state == SCRIPTSTATE_DISCONNECTED)
change_state(This, SCRIPTSTATE_INITIALIZED);
if(state == SCRIPTSTATE_INITIALIZED)
break;
change_state(This, SCRIPTSTATE_INITIALIZED);
/* FALLTHROUGH */
case SCRIPTSTATE_INITIALIZED:
case SCRIPTSTATE_UNINITIALIZED:
change_state(This, state);
if(state == SCRIPTSTATE_INITIALIZED)
break;
release_script(This->ctx);
This->thread_id = 0;
if(state == SCRIPTSTATE_CLOSED) {
release_code_list(This->ctx);
release_named_item_list(This->ctx);
}
break;
case SCRIPTSTATE_CLOSED:
break;
@@ -219,6 +372,97 @@ static void decrease_state(VBScript *This, SCRIPTSTATE state)
}
}
static inline struct vbcaller *vbcaller_from_IServiceProvider(IServiceProvider *iface)
{
return CONTAINING_RECORD(iface, struct vbcaller, IServiceProvider_iface);
}
static HRESULT WINAPI vbcaller_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
{
struct vbcaller *This = vbcaller_from_IServiceProvider(iface);
if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IServiceProvider, riid)) {
*ppv = &This->IServiceProvider_iface;
}else {
WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
*ppv = NULL;
return E_NOINTERFACE;
}
IUnknown_AddRef((IUnknown*)*ppv);
return S_OK;
}
static ULONG WINAPI vbcaller_AddRef(IServiceProvider *iface)
{
struct vbcaller *This = vbcaller_from_IServiceProvider(iface);
LONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%ld\n", This, ref);
return ref;
}
static ULONG WINAPI vbcaller_Release(IServiceProvider *iface)
{
struct vbcaller *This = vbcaller_from_IServiceProvider(iface);
LONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%ld\n", This, ref);
if(!ref)
free(This);
return ref;
}
static HRESULT WINAPI vbcaller_QueryService(IServiceProvider *iface, REFGUID guidService,
REFIID riid, void **ppv)
{
struct vbcaller *This = vbcaller_from_IServiceProvider(iface);
if(IsEqualGUID(guidService, &IID_IActiveScriptSite)) {
TRACE("(%p)->(IID_IActiveScriptSite)\n", This);
if(This->ctx->site)
return IActiveScriptSite_QueryInterface(This->ctx->site, riid, ppv);
*ppv = NULL;
return E_NOINTERFACE;
}
if(IsEqualGUID(guidService, &SID_GetCaller)) {
TRACE("(%p)->(SID_GetCaller)\n", This);
*ppv = NULL;
if(!This->caller)
return S_OK;
return (This->caller == SP_CALLER_UNINITIALIZED) ? E_NOINTERFACE : IServiceProvider_QueryInterface(This->caller, riid, ppv);
}
FIXME("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
*ppv = NULL;
return E_NOINTERFACE;
}
static const IServiceProviderVtbl ServiceProviderVtbl = {
vbcaller_QueryInterface,
vbcaller_AddRef,
vbcaller_Release,
vbcaller_QueryService
};
static struct vbcaller *create_vbcaller(void)
{
struct vbcaller *ret;
ret = malloc(sizeof(*ret));
if(ret) {
ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
ret->ref = 1;
ret->caller = SP_CALLER_UNINITIALIZED;
}
return ret;
}
static inline VBScriptError *impl_from_IActiveScriptError(IActiveScriptError *iface)
{
return CONTAINING_RECORD(iface, VBScriptError, IActiveScriptError_iface);
@@ -249,7 +493,7 @@ 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);
TRACE("(%p) ref=%ld\n", This, ref);
return ref;
}
@@ -259,11 +503,10 @@ 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);
TRACE("(%p) ref=%ld\n", This, ref);
if(!ref) {
heap_free(This);
}
if(!ref)
free(This);
return ref;
}
@@ -285,14 +528,14 @@ static HRESULT WINAPI VBScriptError_GetSourcePosition(IActiveScriptError *iface,
{
VBScriptError *This = impl_from_IActiveScriptError(iface);
FIXME("(%p)->(%p %p %p)\n", This, source_context, line, character);
TRACE("(%p)->(%p %p %p)\n", This, source_context, line, character);
if(source_context)
*source_context = 0;
*source_context = This->cookie;
if(line)
*line = 0;
*line = This->line;
if(character)
*character = 0;
*character = This->character;
return S_OK;
}
@@ -312,12 +555,13 @@ static const IActiveScriptErrorVtbl VBScriptErrorVtbl = {
VBScriptError_GetSourceLineText
};
HRESULT report_script_error(script_ctx_t *ctx)
HRESULT report_script_error(script_ctx_t *ctx, const vbscode_t *code, unsigned loc)
{
VBScriptError *error;
const WCHAR *p, *nl;
HRESULT hres, result;
if(!(error = heap_alloc(sizeof(*error))))
if(!(error = malloc(sizeof(*error))))
return E_OUTOFMEMORY;
error->IActiveScriptError_iface.lpVtbl = &VBScriptErrorVtbl;
@@ -326,6 +570,16 @@ HRESULT report_script_error(script_ctx_t *ctx)
memset(&ctx->ei, 0, sizeof(ctx->ei));
result = error->ei.scode;
p = code->source;
error->cookie = code->cookie;
error->line = code->start_line;
for(nl = p = code->source; p < code->source + loc; p++) {
if(*p != '\n') continue;
error->line++;
nl = p + 1;
}
error->character = code->source + loc - nl;
hres = IActiveScriptSite_OnScriptError(ctx->site, &error->IActiveScriptError_iface);
IActiveScriptError_Release(&error->IActiveScriptError_iface);
return hres == S_OK ? SCRIPT_E_REPORTED : result;
@@ -359,7 +613,7 @@ static HRESULT WINAPI VBScript_QueryInterface(IActiveScript *iface, REFIID riid,
TRACE("(%p)->(IID_IObjectSafety %p)\n", This, ppv);
*ppv = &This->IObjectSafety_iface;
}else {
FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
*ppv = NULL;
return E_NOINTERFACE;
}
@@ -373,7 +627,7 @@ static ULONG WINAPI VBScript_AddRef(IActiveScript *iface)
VBScript *This = impl_from_IActiveScript(iface);
LONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
TRACE("(%p) ref=%ld\n", This, ref);
return ref;
}
@@ -383,12 +637,14 @@ static ULONG WINAPI VBScript_Release(IActiveScript *iface)
VBScript *This = impl_from_IActiveScript(iface);
LONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%d\n", iface, ref);
TRACE("(%p) ref=%ld\n", iface, ref);
if(!ref) {
decrease_state(This, SCRIPTSTATE_CLOSED);
destroy_script(This->ctx);
heap_free(This);
detach_global_objects(This->ctx);
IServiceProvider_Release(&This->ctx->vbcaller->IServiceProvider_iface);
free(This->ctx);
free(This);
}
return ref;
@@ -397,7 +653,8 @@ static ULONG WINAPI VBScript_Release(IActiveScript *iface)
static HRESULT WINAPI VBScript_SetScriptSite(IActiveScript *iface, IActiveScriptSite *pass)
{
VBScript *This = impl_from_IActiveScript(iface);
LCID lcid;
LCID lcid = LOCALE_USER_DEFAULT;
named_item_t *item;
HRESULT hres;
TRACE("(%p)->(%p)\n", This, pass);
@@ -411,6 +668,19 @@ static HRESULT WINAPI VBScript_SetScriptSite(IActiveScript *iface, IActiveScript
if(InterlockedCompareExchange(&This->thread_id, GetCurrentThreadId(), 0))
return E_UNEXPECTED;
/* Retrieve new dispatches for persistent named items */
LIST_FOR_EACH_ENTRY(item, &This->ctx->named_items, named_item_t, entry)
{
if(!item->disp)
{
hres = retrieve_named_item_disp(pass, item);
if(FAILED(hres)) return hres;
}
/* For some reason, CODEONLY flag is lost in re-initialized scripts */
item->flags &= ~SCRIPTITEM_CODEONLY;
}
hres = create_script_disp(This->ctx, &This->ctx->script_obj);
if(FAILED(hres))
return hres;
@@ -418,9 +688,12 @@ static HRESULT WINAPI VBScript_SetScriptSite(IActiveScript *iface, IActiveScript
This->ctx->site = pass;
IActiveScriptSite_AddRef(This->ctx->site);
hres = IActiveScriptSite_GetLCID(This->ctx->site, &lcid);
if(hres == S_OK)
This->ctx->lcid = lcid;
IActiveScriptSite_GetLCID(This->ctx->site, &lcid);
This->ctx->lcid = IsValidLocale(lcid, 0) ? lcid : GetUserDefaultLCID();
GetLocaleInfoW(lcid, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, (WCHAR *)&This->ctx->codepage,
sizeof(This->ctx->codepage)/sizeof(WCHAR));
if (!This->ctx->codepage)
This->ctx->codepage = CP_UTF8;
if(This->is_initialized)
change_state(This, SCRIPTSTATE_INITIALIZED);
@@ -452,7 +725,7 @@ static HRESULT WINAPI VBScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE
return S_OK;
}
if(!This->is_initialized)
if(!This->is_initialized || (!This->ctx->site && ss != SCRIPTSTATE_CLOSED))
return E_UNEXPECTED;
switch(ss) {
@@ -464,7 +737,10 @@ static HRESULT WINAPI VBScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE
exec_queued_code(This->ctx);
break;
case SCRIPTSTATE_INITIALIZED:
FIXME("unimplemented SCRIPTSTATE_INITIALIZED\n");
decrease_state(This, SCRIPTSTATE_INITIALIZED);
return S_OK;
case SCRIPTSTATE_CLOSED:
decrease_state(This, SCRIPTSTATE_CLOSED);
return S_OK;
case SCRIPTSTATE_DISCONNECTED:
FIXME("unimplemented SCRIPTSTATE_DISCONNECTED\n");
@@ -514,7 +790,7 @@ static HRESULT WINAPI VBScript_AddNamedItem(IActiveScript *iface, LPCOLESTR pstr
IDispatch *disp = NULL;
HRESULT hres;
TRACE("(%p)->(%s %x)\n", This, debugstr_w(pstrName), dwFlags);
TRACE("(%p)->(%s %lx)\n", This, debugstr_w(pstrName), dwFlags);
if(This->thread_id != GetCurrentThreadId() || !This->ctx->site)
return E_UNEXPECTED;
@@ -524,7 +800,7 @@ static HRESULT WINAPI VBScript_AddNamedItem(IActiveScript *iface, LPCOLESTR pstr
hres = IActiveScriptSite_GetItemInfo(This->ctx->site, pstrName, SCRIPTINFO_IUNKNOWN, &unk, NULL);
if(FAILED(hres)) {
WARN("GetItemInfo failed: %08x\n", hres);
WARN("GetItemInfo failed: %08lx\n", hres);
return hres;
}
@@ -534,27 +810,24 @@ static HRESULT WINAPI VBScript_AddNamedItem(IActiveScript *iface, LPCOLESTR pstr
WARN("object does not implement IDispatch\n");
return hres;
}
if(This->ctx->host_global)
IDispatch_Release(This->ctx->host_global);
IDispatch_AddRef(disp);
This->ctx->host_global = disp;
}
item = heap_alloc(sizeof(*item));
item = malloc(sizeof(*item));
if(!item) {
if(disp)
IDispatch_Release(disp);
return E_OUTOFMEMORY;
}
item->ref = 1;
item->disp = disp;
item->flags = dwFlags;
item->name = heap_strdupW(pstrName);
item->script_obj = NULL;
item->name = wcsdup(pstrName);
if(!item->name) {
if(disp)
IDispatch_Release(disp);
heap_free(item);
free(item);
return E_OUTOFMEMORY;
}
@@ -566,15 +839,16 @@ static HRESULT WINAPI VBScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTyp
DWORD dwMajor, DWORD dwMinor, DWORD dwFlags)
{
VBScript *This = impl_from_IActiveScript(iface);
FIXME("(%p)->()\n", This);
FIXME("(%p)->(%s %ld %ld %ld)\n", This, debugstr_guid(rguidTypeLib), dwMajor, dwMinor, dwFlags);
return E_NOTIMPL;
}
static HRESULT WINAPI VBScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName, IDispatch **ppdisp)
{
VBScript *This = impl_from_IActiveScript(iface);
ScriptDisp *script_obj;
TRACE("(%p)->(%p)\n", This, ppdisp);
TRACE("(%p)->(%s %p)\n", This, debugstr_w(pstrItemName), ppdisp);
if(!ppdisp)
return E_POINTER;
@@ -584,7 +858,14 @@ static HRESULT WINAPI VBScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR
return E_UNEXPECTED;
}
*ppdisp = (IDispatch*)&This->ctx->script_obj->IDispatchEx_iface;
script_obj = This->ctx->script_obj;
if(pstrItemName) {
named_item_t *item = lookup_named_item(This->ctx, pstrItemName, 0);
if(!item) return E_INVALIDARG;
if(item->script_obj) script_obj = item->script_obj;
}
*ppdisp = (IDispatch*)&script_obj->IDispatchEx_iface;
IDispatch_AddRef(*ppdisp);
return S_OK;
}
@@ -674,7 +955,7 @@ static HRESULT WINAPI VBScriptDebug_GetScriptTextAttributes(IActiveScriptDebug *
LPCOLESTR code, ULONG len, LPCOLESTR delimiter, DWORD flags, SOURCE_TEXT_ATTR *attr)
{
VBScript *This = impl_from_IActiveScriptDebug(iface);
FIXME("(%p)->(%s %u %s %#x %p)\n", This, debugstr_w(code), len,
FIXME("(%p)->(%s %lu %s %#lx %p)\n", This, debugstr_w(code), len,
debugstr_w(delimiter), flags, attr);
return E_NOTIMPL;
}
@@ -683,7 +964,7 @@ static HRESULT WINAPI VBScriptDebug_GetScriptletTextAttributes(IActiveScriptDebu
LPCOLESTR code, ULONG len, LPCOLESTR delimiter, DWORD flags, SOURCE_TEXT_ATTR *attr)
{
VBScript *This = impl_from_IActiveScriptDebug(iface);
FIXME("(%p)->(%s %u %s %#x %p)\n", This, debugstr_w(code), len,
FIXME("(%p)->(%s %lu %s %#lx %p)\n", This, debugstr_w(code), len,
debugstr_w(delimiter), flags, attr);
return E_NOTIMPL;
}
@@ -692,7 +973,7 @@ static HRESULT WINAPI VBScriptDebug_EnumCodeContextsOfPosition(IActiveScriptDebu
CTXARG_T source, ULONG offset, ULONG len, IEnumDebugCodeContexts **ret)
{
VBScript *This = impl_from_IActiveScriptDebug(iface);
FIXME("(%p)->(%s %u %u %p)\n", This, wine_dbgstr_longlong(source), offset, len, ret);
FIXME("(%p)->(%s %lu %lu %p)\n", This, wine_dbgstr_longlong(source), offset, len, ret);
return E_NOTIMPL;
}
@@ -750,7 +1031,7 @@ static HRESULT WINAPI VBScriptParse_AddScriptlet(IActiveScriptParse *iface,
BSTR *pbstrName, EXCEPINFO *pexcepinfo)
{
VBScript *This = impl_from_IActiveScriptParse(iface);
FIXME("(%p)->(%s %s %s %s %s %s %s %u %x %p %p)\n", This, debugstr_w(pstrDefaultName),
FIXME("(%p)->(%s %s %s %s %s %s %s %lu %lx %p %p)\n", This, debugstr_w(pstrDefaultName),
debugstr_w(pstrCode), debugstr_w(pstrItemName), debugstr_w(pstrSubItemName),
debugstr_w(pstrEventName), debugstr_w(pstrDelimiter), wine_dbgstr_longlong(dwSourceContextCookie),
ulStartingLineNumber, dwFlags, pbstrName, pexcepinfo);
@@ -763,32 +1044,21 @@ static HRESULT WINAPI VBScriptParse_ParseScriptText(IActiveScriptParse *iface,
DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo)
{
VBScript *This = impl_from_IActiveScriptParse(iface);
IDispatch *context = NULL;
vbscode_t *code;
HRESULT hres;
TRACE("(%p)->(%s %s %p %s %s %u %x %p %p)\n", This, debugstr_w(pstrCode),
TRACE("(%p)->(%s %s %p %s %s %lu %lx %p %p)\n", This, debugstr_w(pstrCode),
debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter),
wine_dbgstr_longlong(dwSourceContextCookie), ulStartingLine, dwFlags, pvarResult, pexcepinfo);
if(This->thread_id != GetCurrentThreadId() || This->state == SCRIPTSTATE_CLOSED)
return E_UNEXPECTED;
if(pstrItemName) {
context = lookup_named_item(This->ctx, pstrItemName, 0);
if(!context) {
WARN("Inknown context %s\n", debugstr_w(pstrItemName));
return E_INVALIDARG;
}
}
hres = compile_script(This->ctx, pstrCode, pstrDelimiter, dwFlags, &code);
hres = compile_script(This->ctx, pstrCode, pstrItemName, pstrDelimiter, dwSourceContextCookie,
ulStartingLine, dwFlags, &code);
if(FAILED(hres))
return hres;
if(context)
IDispatch_AddRef(code->context = context);
if(!(dwFlags & SCRIPTTEXT_ISEXPRESSION) && !is_started(This)) {
code->pending_exec = TRUE;
return S_OK;
@@ -839,14 +1109,15 @@ static HRESULT WINAPI VBScriptParseProcedure_ParseProcedureText(IActiveScriptPar
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),
TRACE("(%p)->(%s %s %s %s %p %s %s %lu %lx %p)\n", This, debugstr_w(pstrCode), debugstr_w(pstrFormalParams),
debugstr_w(pstrProcedureName), debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter),
wine_dbgstr_longlong(dwSourceContextCookie), ulStartingLineNumber, dwFlags, ppdisp);
if(This->thread_id != GetCurrentThreadId() || This->state == SCRIPTSTATE_CLOSED)
return E_UNEXPECTED;
hres = compile_procedure(This->ctx, pstrCode, pstrDelimiter, dwFlags, &desc);
hres = compile_procedure(This->ctx, pstrCode, pstrItemName, pstrDelimiter, dwSourceContextCookie,
ulStartingLineNumber, dwFlags, &desc);
if(FAILED(hres))
return hres;
@@ -910,7 +1181,7 @@ static HRESULT WINAPI VBScriptSafety_SetInterfaceSafetyOptions(IObjectSafety *if
{
VBScript *This = impl_from_IObjectSafety(iface);
TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
TRACE("(%p)->(%s %lx %lx)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
return E_FAIL;
@@ -929,16 +1200,22 @@ static const IObjectSafetyVtbl VBScriptSafetyVtbl = {
HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter, REFIID riid, void **ppv)
{
struct vbcaller *vbcaller;
script_ctx_t *ctx;
VBScript *ret;
HRESULT hres;
TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppv);
ret = heap_alloc_zero(sizeof(*ret));
ret = calloc(1, sizeof(*ret));
if(!ret)
return E_OUTOFMEMORY;
if(!(vbcaller = create_vbcaller())) {
free(ret);
return E_OUTOFMEMORY;
}
ret->IActiveScript_iface.lpVtbl = &VBScriptVtbl;
ret->IActiveScriptDebug_iface.lpVtbl = &VBScriptDebugVtbl;
ret->IActiveScriptParse_iface.lpVtbl = &VBScriptParseVtbl;
@@ -948,14 +1225,16 @@ HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pU
ret->ref = 1;
ret->state = SCRIPTSTATE_UNINITIALIZED;
ctx = ret->ctx = heap_alloc_zero(sizeof(*ctx));
ctx = ret->ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
heap_free(ret);
IServiceProvider_Release(&vbcaller->IServiceProvider_iface);
free(ret);
return E_OUTOFMEMORY;
}
vbcaller->ctx = ctx;
ctx->vbcaller = vbcaller;
ctx->safeopt = INTERFACE_USES_DISPEX;
heap_pool_init(&ctx->heap);
list_init(&ctx->objects);
list_init(&ctx->code_list);
list_init(&ctx->named_items);
@@ -1009,7 +1288,7 @@ static ULONG WINAPI AXSite_AddRef(IServiceProvider *iface)
AXSite *This = impl_from_IServiceProvider(iface);
LONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
TRACE("(%p) ref=%ld\n", This, ref);
return ref;
}
@@ -1019,10 +1298,10 @@ static ULONG WINAPI AXSite_Release(IServiceProvider *iface)
AXSite *This = impl_from_IServiceProvider(iface);
LONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
TRACE("(%p) ref=%ld\n", This, ref);
if(!ref)
heap_free(This);
free(This);
return ref;
}
@@ -1052,11 +1331,11 @@ IUnknown *create_ax_site(script_ctx_t *ctx)
hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IServiceProvider, (void**)&sp);
if(FAILED(hres)) {
ERR("Could not get IServiceProvider iface: %08x\n", hres);
ERR("Could not get IServiceProvider iface: %08lx\n", hres);
return NULL;
}
ret = heap_alloc(sizeof(*ret));
ret = malloc(sizeof(*ret));
if(!ret) {
IServiceProvider_Release(sp);
return NULL;
+116 -87
View File
@@ -30,13 +30,9 @@
#include "activscp.h"
#include "activdbg.h"
#ifdef __REACTOS__
#include <initguid.h>
#endif
#include "vbscript_classes.h"
#include "vbscript_defs.h"
#include "wine/heap.h"
#include "wine/list.h"
typedef struct {
@@ -48,26 +44,18 @@ typedef struct {
struct list custom_blocks;
} heap_pool_t;
void heap_pool_init(heap_pool_t*) DECLSPEC_HIDDEN;
void *heap_pool_alloc(heap_pool_t*,size_t) __WINE_ALLOC_SIZE(2) DECLSPEC_HIDDEN;
void *heap_pool_grow(heap_pool_t*,void*,DWORD,DWORD) DECLSPEC_HIDDEN;
void heap_pool_clear(heap_pool_t*) DECLSPEC_HIDDEN;
void heap_pool_free(heap_pool_t*) DECLSPEC_HIDDEN;
heap_pool_t *heap_pool_mark(heap_pool_t*) DECLSPEC_HIDDEN;
void heap_pool_init(heap_pool_t*);
void *heap_pool_alloc(heap_pool_t*,size_t) __WINE_ALLOC_SIZE(2);
void *heap_pool_grow(heap_pool_t*,void*,DWORD,DWORD);
void heap_pool_clear(heap_pool_t*);
void heap_pool_free(heap_pool_t*);
heap_pool_t *heap_pool_mark(heap_pool_t*);
typedef struct _function_t function_t;
typedef struct _vbscode_t vbscode_t;
typedef struct _script_ctx_t script_ctx_t;
typedef struct _vbdisp_t vbdisp_t;
typedef struct named_item_t {
IDispatch *disp;
DWORD flags;
LPWSTR name;
struct list entry;
} named_item_t;
typedef enum {
VBDISP_CALLGET,
VBDISP_LET,
@@ -125,17 +113,32 @@ struct _vbdisp_t {
VARIANT props[1];
};
typedef struct _ident_map_t ident_map_t;
typedef struct _dynamic_var_t {
struct _dynamic_var_t *next;
VARIANT v;
const WCHAR *name;
BOOL is_const;
SAFEARRAY *array;
} dynamic_var_t;
typedef struct {
IDispatchEx IDispatchEx_iface;
LONG ref;
ident_map_t *ident_map;
unsigned ident_map_cnt;
unsigned ident_map_size;
dynamic_var_t **global_vars;
size_t global_vars_cnt;
size_t global_vars_size;
function_t **global_funcs;
size_t global_funcs_cnt;
size_t global_funcs_size;
class_desc_t *classes;
script_ctx_t *ctx;
heap_pool_t heap;
unsigned int rnd;
} ScriptDisp;
typedef struct _builtin_prop_t builtin_prop_t;
@@ -148,16 +151,26 @@ typedef struct {
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;
HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,DISPPARAMS*,VARIANT*) 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;
void collect_objects(script_ctx_t*) DECLSPEC_HIDDEN;
HRESULT create_script_disp(script_ctx_t*,ScriptDisp**) DECLSPEC_HIDDEN;
typedef struct named_item_t {
ScriptDisp *script_obj;
IDispatch *disp;
unsigned ref;
DWORD flags;
LPWSTR name;
HRESULT to_int(VARIANT*,int*) DECLSPEC_HIDDEN;
struct list entry;
} named_item_t;
HRESULT create_vbdisp(const class_desc_t*,vbdisp_t**);
HRESULT disp_get_id(IDispatch*,BSTR,vbdisp_invoke_type_t,BOOL,DISPID*);
HRESULT vbdisp_get_id(vbdisp_t*,BSTR,vbdisp_invoke_type_t,BOOL,DISPID*);
HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,DISPPARAMS*,VARIANT*);
HRESULT disp_propput(script_ctx_t*,IDispatch*,DISPID,WORD,DISPPARAMS*);
HRESULT get_disp_value(script_ctx_t*,IDispatch*,VARIANT*);
void collect_objects(script_ctx_t*);
HRESULT create_script_disp(script_ctx_t*,ScriptDisp**);
HRESULT to_int(VARIANT*,int*);
static inline unsigned arg_cnt(const DISPPARAMS *dp)
{
@@ -169,45 +182,44 @@ static inline VARIANT *get_arg(DISPPARAMS *dp, DWORD i)
return dp->rgvarg + dp->cArgs-i-1;
}
typedef struct _dynamic_var_t {
struct _dynamic_var_t *next;
VARIANT v;
const WCHAR *name;
BOOL is_const;
} dynamic_var_t;
#define SP_CALLER_UNINITIALIZED ((IServiceProvider*)IntToPtr(-1))
struct vbcaller {
IServiceProvider IServiceProvider_iface;
LONG ref;
script_ctx_t *ctx;
IServiceProvider *caller;
};
struct _script_ctx_t {
IActiveScriptSite *site;
LCID lcid;
UINT codepage;
IInternetHostSecurityManager *secmgr;
struct vbcaller *vbcaller;
DWORD safeopt;
IDispatch *host_global;
ScriptDisp *script_obj;
BuiltinDisp *global_obj;
BuiltinDisp *err_obj;
EXCEPINFO ei;
dynamic_var_t *global_vars;
function_t *global_funcs;
class_desc_t *classes;
class_desc_t *procs;
heap_pool_t heap;
vbscode_t *error_loc_code;
unsigned error_loc_offset;
struct list objects;
struct list code_list;
struct list named_items;
};
HRESULT init_global(script_ctx_t*) DECLSPEC_HIDDEN;
HRESULT init_err(script_ctx_t*) DECLSPEC_HIDDEN;
HRESULT init_global(script_ctx_t*);
HRESULT init_err(script_ctx_t*);
IUnknown *create_ax_site(script_ctx_t*) DECLSPEC_HIDDEN;
IUnknown *create_ax_site(script_ctx_t*);
typedef enum {
ARG_NONE = 0,
@@ -216,7 +228,8 @@ typedef enum {
ARG_INT,
ARG_UINT,
ARG_ADDR,
ARG_DOUBLE
ARG_DOUBLE,
ARG_DATE
} instr_arg_type_t;
#define OP_LIST \
@@ -225,10 +238,12 @@ typedef enum {
X(assign_ident, 1, ARG_BSTR, ARG_UINT) \
X(assign_member, 1, ARG_BSTR, ARG_UINT) \
X(bool, 1, ARG_INT, 0) \
X(catch, 1, ARG_ADDR, ARG_UINT) \
X(catch, 1, ARG_ADDR, ARG_UINT) \
X(case, 0, ARG_ADDR, 0) \
X(concat, 1, 0, 0) \
X(const, 1, ARG_BSTR, 0) \
X(date, 1, ARG_DATE, 0) \
X(deref, 1, 0, 0) \
X(dim, 1, ARG_BSTR, ARG_UINT) \
X(div, 1, 0, 0) \
X(double, 1, ARG_DOUBLE, 0) \
@@ -243,6 +258,7 @@ typedef enum {
X(gteq, 1, 0, 0) \
X(icall, 1, ARG_BSTR, ARG_UINT) \
X(icallv, 1, ARG_BSTR, ARG_UINT) \
X(ident, 1, ARG_BSTR, 0) \
X(idiv, 1, 0, 0) \
X(imp, 1, 0, 0) \
X(incc, 1, ARG_BSTR, 0) \
@@ -265,17 +281,23 @@ typedef enum {
X(not, 1, 0, 0) \
X(nothing, 1, 0, 0) \
X(null, 1, 0, 0) \
X(numval, 1, 0, 0) \
X(or, 1, 0, 0) \
X(pop, 1, ARG_UINT, 0) \
X(redim, 1, ARG_BSTR, ARG_UINT) \
X(redim_preserve, 1, ARG_BSTR, ARG_UINT) \
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(stack, 1, ARG_UINT, 0) \
X(step, 0, ARG_ADDR, ARG_BSTR) \
X(stop, 1, 0, 0) \
X(string, 1, ARG_STR, 0) \
X(sub, 1, 0, 0) \
X(val, 1, 0, 0) \
X(vcall, 1, ARG_UINT, 0) \
X(vcallv, 1, ARG_UINT, 0) \
X(xor, 1, 0, 0)
typedef enum {
@@ -291,10 +313,12 @@ typedef union {
unsigned uint;
LONG lng;
double *dbl;
DATE *date;
} instr_arg_t;
typedef struct {
vbsop_t op;
unsigned loc;
instr_arg_t arg1;
instr_arg_t arg2;
} instr_t;
@@ -311,7 +335,6 @@ typedef enum {
FUNC_PROPGET,
FUNC_PROPLET,
FUNC_PROPSET,
FUNC_DEFGET
} function_type_t;
typedef struct {
@@ -335,70 +358,76 @@ struct _function_t {
struct _vbscode_t {
instr_t *instrs;
unsigned ref;
WCHAR *source;
DWORD_PTR cookie;
unsigned start_line;
BOOL option_explicit;
BOOL pending_exec;
BOOL is_persistent;
function_t main_code;
IDispatch *context;
named_item_t *named_item;
BSTR *bstr_pool;
unsigned bstr_pool_size;
unsigned bstr_cnt;
heap_pool_t heap;
function_t *funcs;
class_desc_t *classes;
class_desc_t *last_class;
struct list entry;
};
void release_vbscode(vbscode_t*) 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;
static inline void grab_vbscode(vbscode_t *code)
{
code->ref++;
}
void release_regexp_typelib(void) DECLSPEC_HIDDEN;
void release_vbscode(vbscode_t*);
HRESULT compile_script(script_ctx_t*,const WCHAR*,const WCHAR*,const WCHAR*,DWORD_PTR,unsigned,DWORD,vbscode_t**);
HRESULT compile_procedure(script_ctx_t*,const WCHAR*,const WCHAR*,const WCHAR*,DWORD_PTR,unsigned,DWORD,class_desc_t**);
HRESULT exec_script(script_ctx_t*,BOOL,function_t*,vbdisp_t*,DISPPARAMS*,VARIANT*);
void release_dynamic_var(dynamic_var_t*);
named_item_t *lookup_named_item(script_ctx_t*,const WCHAR*,unsigned);
void release_named_item(named_item_t*);
void clear_ei(EXCEPINFO*);
HRESULT report_script_error(script_ctx_t*,const vbscode_t*,unsigned);
void detach_global_objects(script_ctx_t*);
HRESULT get_builtin_id(BuiltinDisp*,const WCHAR*,DISPID*);
HRESULT array_access(SAFEARRAY *array, DISPPARAMS *dp, VARIANT **ret);
void release_regexp_typelib(void);
HRESULT get_dispatch_typeinfo(ITypeInfo**);
static inline BOOL is_int32(double d)
{
return INT32_MIN <= d && d <= INT32_MAX && (double)(int)d == d;
}
HRESULT create_regexp(IDispatch**) DECLSPEC_HIDDEN;
static inline BOOL is_digit(WCHAR c)
{
return '0' <= c && c <= '9';
}
HRESULT map_hres(HRESULT) DECLSPEC_HIDDEN;
HRESULT create_regexp(IDispatch**);
BSTR string_replace(BSTR,BSTR,BSTR,int,int,int);
HRESULT create_safearray_iter(SAFEARRAY *sa, IEnumVARIANT **ev) DECLSPEC_HIDDEN;
void map_vbs_exception(EXCEPINFO *);
HRESULT create_safearray_iter(SAFEARRAY *sa, BOOL owned, IEnumVARIANT **ev);
#define FACILITY_VBS 0xa
#define MAKE_VBSERROR(code) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_VBS, code)
HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**) DECLSPEC_HIDDEN;
HRESULT WINAPI VBScriptRegExpFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**) DECLSPEC_HIDDEN;
HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**);
HRESULT WINAPI VBScriptRegExpFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**);
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;
if(str) {
DWORD size;
size = (lstrlenW(str)+1)*sizeof(WCHAR);
ret = heap_alloc(size);
if(ret)
memcpy(ret, str, size);
}
return ret;
}
BSTR get_vbscript_string(int);
#define VBSCRIPT_BUILD_VERSION 16978
#define VBSCRIPT_MAJOR_VERSION 5
+3 -9
View File
@@ -19,6 +19,8 @@
#include <windef.h>
#include "vbscript_defs.h"
#pragma makedep po
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
STRINGTABLE
@@ -54,6 +56,7 @@ STRINGTABLE
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"
VBSE_UNQUALIFIED_REFERENCE "Invalid or unqualified reference"
VBS_COMPILE_ERROR "Microsoft VBScript compilation error"
VBS_RUNTIME_ERROR "Microsoft VBScript runtime error"
@@ -65,15 +68,6 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
/* @makedep: vbscript.rgs */
2 WINE_REGISTRY vbscript.rgs
3 WINE_REGISTRY "vbsglobal.rgs"
4 WINE_REGISTRY "vbsregexp10.rgs"
5 WINE_REGISTRY "vbsregexp55.rgs"
6 WINE_REGISTRY "vbscript_classes.rgs"
1 TYPELIB "vbsglobal.tlb"
2 TYPELIB "vbsregexp10.tlb"
3 TYPELIB "vbsregexp55.tlb"
#define WINE_FILEDESCRIPTION_STR "Wine VBScript"
#define WINE_FILENAME_STR "vbscript.dll"
#define WINE_FILEVERSION 5,8,7601,16978
+4 -4
View File
@@ -63,19 +63,19 @@ HKCR
{
Edit
{
Command = s '"%%SystemRoot%%\system32\notepad.exe" %%1'
Command = s '"%SystemRoot%\system32\notepad.exe" %%1'
}
Open
{
Command = s '"%%SystemRoot%%\system32\wscript.exe" "%%1" %%*'
Command = s '"%SystemRoot%\system32\wscript.exe" "%%1" %%*'
}
Open2
{
Command = s '"%%SystemRoot%%\system32\cscript.exe" "%%1" %%*'
Command = s '"%SystemRoot%\system32\cscript.exe" "%%1" %%*'
}
Print
{
Command = s '"%%SystemRoot%%\system32\notepad.exe" /p %%1'
Command = s '"%SystemRoot%\system32\notepad.exe" /p %%1'
}
}
}
-46
View File
@@ -1,46 +0,0 @@
HKCR
{
NoRemove Interface
{
}
NoRemove CLSID
{
'{3F4DACA4-160D-11D2-A8E9-00104B365C9F}' = s 'VBScript Regular Expression'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Apartment' }
ProgId = s 'VBScript.RegExp'
Version = s '5.5'
}
'{B54F3741-5B07-11CF-A4B0-00AA004A55E8}' = s 'VB Script Language'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
ProgId = s 'VBScript'
}
'{B54F3742-5B07-11CF-A4B0-00AA004A55E8}' = s 'VB Script Language Authoring'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
ProgId = s 'VBScript Author'
}
'{B54F3743-5B07-11CF-A4B0-00AA004A55E8}' = s 'VB Script Language Encoding'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
ProgId = s 'VBScript.Encode'
}
}
'VBScript.RegExp' = s 'VBScript Regular Expression'
{
CLSID = s '{3F4DACA4-160D-11D2-A8E9-00104B365C9F}'
}
'VBScript' = s 'VB Script Language'
{
CLSID = s '{B54F3741-5B07-11CF-A4B0-00AA004A55E8}'
}
'VBScript Author' = s 'VB Script Language Authoring'
{
CLSID = s '{B54F3742-5B07-11CF-A4B0-00AA004A55E8}'
}
'VBScript.Encode' = s 'VB Script Language Encoding'
{
CLSID = s '{B54F3743-5B07-11CF-A4B0-00AA004A55E8}'
}
}
+1
View File
@@ -267,6 +267,7 @@
#define VBSE_INVALID_DLL_FUNCTION_NAME 453
#define VBSE_INVALID_TYPELIB_VARIABLE 458
#define VBSE_SERVER_NOT_FOUND 462
#define VBSE_UNQUALIFIED_REFERENCE 505
#define VBS_COMPILE_ERROR 4096
#define VBS_RUNTIME_ERROR 4097
+34 -47
View File
@@ -34,6 +34,7 @@ WINE_DECLARE_DEBUG_CHANNEL(heap);
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
static HINSTANCE vbscript_hinstance;
static ITypeInfo *dispatch_typeinfo;
BSTR get_vbscript_string(int id)
{
@@ -42,14 +43,6 @@ BSTR get_vbscript_string(int id)
return SysAllocString(buf);
}
BSTR get_vbscript_error_string(HRESULT error)
{
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
#define ARENA_FREE_FILLER 0xaa
@@ -73,12 +66,12 @@ void *heap_pool_alloc(heap_pool_t *heap, size_t size)
if(!heap->block_cnt) {
if(!heap->blocks) {
heap->blocks = heap_alloc(sizeof(void*));
heap->blocks = malloc(sizeof(void*));
if(!heap->blocks)
return NULL;
}
tmp = heap_alloc(block_size(0));
tmp = malloc(block_size(0));
if(!tmp)
return NULL;
@@ -94,12 +87,12 @@ void *heap_pool_alloc(heap_pool_t *heap, size_t size)
if(size <= block_size(heap->last_block+1)) {
if(heap->last_block+1 == heap->block_cnt) {
tmp = heap_realloc(heap->blocks, (heap->block_cnt+1)*sizeof(void*));
tmp = realloc(heap->blocks, (heap->block_cnt+1)*sizeof(void*));
if(!tmp)
return NULL;
heap->blocks = tmp;
heap->blocks[heap->block_cnt] = heap_alloc(block_size(heap->block_cnt));
heap->blocks[heap->block_cnt] = malloc(block_size(heap->block_cnt));
if(!heap->blocks[heap->block_cnt])
return NULL;
@@ -111,7 +104,7 @@ void *heap_pool_alloc(heap_pool_t *heap, size_t size)
return heap->blocks[heap->last_block];
}
list = heap_alloc(size + sizeof(struct list));
list = malloc(size + sizeof(struct list));
if(!list)
return NULL;
@@ -144,7 +137,7 @@ void heap_pool_clear(heap_pool_t *heap)
while((tmp = list_next(&heap->custom_blocks, &heap->custom_blocks))) {
list_remove(tmp);
heap_free(tmp);
free(tmp);
}
if(WARN_ON(heap)) {
@@ -165,8 +158,8 @@ void heap_pool_free(heap_pool_t *heap)
heap_pool_clear(heap);
for(i=0; i < heap->block_cnt; i++)
heap_free(heap->blocks[i]);
heap_free(heap->blocks);
free(heap->blocks[i]);
free(heap->blocks);
heap_pool_init(heap);
}
@@ -180,6 +173,29 @@ heap_pool_t *heap_pool_mark(heap_pool_t *heap)
return heap;
}
HRESULT get_dispatch_typeinfo(ITypeInfo **out)
{
ITypeInfo *typeinfo;
ITypeLib *typelib;
HRESULT hr;
if (!dispatch_typeinfo)
{
hr = LoadRegTypeLib(&IID_StdOle, STDOLE_MAJORVERNUM, STDOLE_MINORVERNUM, STDOLE_LCID, &typelib);
if (FAILED(hr)) return hr;
hr = ITypeLib_GetTypeInfoOfGuid(typelib, &IID_IDispatch, &typeinfo);
ITypeLib_Release(typelib);
if (FAILED(hr)) return hr;
if (InterlockedCompareExchangePointer((void**)&dispatch_typeinfo, typeinfo, NULL))
ITypeInfo_Release(typeinfo);
}
*out = dispatch_typeinfo;
return S_OK;
}
static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
{
*ppv = NULL;
@@ -244,20 +260,17 @@ static IClassFactory VBScriptRegExpFactory = { &VBScriptRegExpFactoryVtbl };
*/
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
{
TRACE("(%p %d %p)\n", hInstDLL, fdwReason, lpv);
TRACE("(%p %ld %p)\n", hInstDLL, fdwReason, lpv);
switch(fdwReason)
{
#ifndef __REACTOS__
case DLL_WINE_PREATTACH:
return FALSE; /* prefer native version */
#endif
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hInstDLL);
vbscript_hinstance = hInstDLL;
break;
case DLL_PROCESS_DETACH:
if (lpv) break;
if (dispatch_typeinfo) ITypeInfo_Release(dispatch_typeinfo);
release_regexp_typelib();
}
@@ -280,29 +293,3 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
return CLASS_E_CLASSNOTAVAILABLE;
}
/***********************************************************************
* DllCanUnloadNow (vbscript.@)
*/
HRESULT WINAPI DllCanUnloadNow(void)
{
return S_FALSE;
}
/***********************************************************************
* DllRegisterServer (vbscript.@)
*/
HRESULT WINAPI DllRegisterServer(void)
{
TRACE("()\n");
return __wine_register_resources(vbscript_hinstance);
}
/***********************************************************************
* DllUnregisterServer (vbscript.@)
*/
HRESULT WINAPI DllUnregisterServer(void)
{
TRACE("()\n");
return __wine_unregister_resources(vbscript_hinstance);
}
-32
View File
@@ -1,32 +0,0 @@
HKCR
{
NoRemove Typelib
{
NoRemove '{3EEF9758-35FC-11D1-8CE4-00C04FC2B185}'
{
'1.0' = s 'Microsoft VBScript Globals'
{
'0' { win32 = s '%MODULE%' }
FLAGS = s '0'
}
}
}
NoRemove Interface
{
'{3EEF9758-35FC-11D1-8CE4-00C04FC2B186}' = s 'GlobalObj'
{
ProxyStubClsid = s '{00020424-0000-0000-C000-000000000046}'
ProxyStubClsid32 = s '{00020424-0000-0000-C000-000000000046}'
TypeLib = s '{3EEF9758-35FC-11D1-8CE4-00C04FC2B185}' { val Version = s '1.0' }
}
'{3EEF9758-35FC-11D1-8CE4-00C04FC2B187}' = s 'ErrObj'
{
ProxyStubClsid = s '{00020424-0000-0000-C000-000000000046}'
ProxyStubClsid32 = s '{00020424-0000-0000-C000-000000000046}'
TypeLib = s '{3EEF9758-35FC-11D1-8CE4-00C04FC2B185}' { val Version = s '1.0' }
}
}
NoRemove CLSID
{
}
}
+1
View File
@@ -24,6 +24,7 @@ import "oaidl.idl";
[
helpstring("Microsoft VBScript Regular Expressions 1.0"),
id(2),
uuid(3f4daca7-160d-11d2-a8e9-00104b365c9f),
version(1.0)
]
-38
View File
@@ -1,38 +0,0 @@
HKCR
{
NoRemove Typelib
{
NoRemove '{3F4DACA7-160D-11D2-A8E9-00104B365C9F}'
{
'1.0' = s 'Microsoft VBScript Regular Expressions 1.0'
{
'0' { win32 = s '%MODULE%' }
FLAGS = s '0'
}
}
}
NoRemove Interface
{
'{3F4DACA0-160D-11D2-A8E9-00104B365C9F}' = s 'IRegExp'
{
ProxyStubClsid = s '{00020424-0000-0000-C000-000000000046}'
ProxyStubClsid32 = s '{00020424-0000-0000-C000-000000000046}'
TypeLib = s '{3F4DACA7-160D-11D2-A8E9-00104B365C9F}' { val Version = s '1.0' }
}
'{3F4DACA1-160D-11D2-A8E9-00104B365C9F}' = s 'IMatch'
{
ProxyStubClsid = s '{00020424-0000-0000-C000-000000000046}'
ProxyStubClsid32 = s '{00020424-0000-0000-C000-000000000046}'
TypeLib = s '{3F4DACA7-160D-11D2-A8E9-00104B365C9F}' { val Version = s '1.0' }
}
'{3F4DACA2-160D-11D2-A8E9-00104B365C9F}' = s 'IMatchCollection'
{
ProxyStubClsid = s '{00020424-0000-0000-C000-000000000046}'
ProxyStubClsid32 = s '{00020424-0000-0000-C000-000000000046}'
TypeLib = s '{3F4DACA7-160D-11D2-A8E9-00104B365C9F}' { val Version = s '1.0' }
}
}
NoRemove CLSID
{
}
}
+1
View File
@@ -24,6 +24,7 @@ import "oaidl.idl";
[
helpstring("Microsoft VBScript Regular Expressions 5.5"),
id(3),
uuid(3f4daca7-160d-11d2-a8e9-00104b365c9f),
version(5.5)
]
-62
View File
@@ -1,62 +0,0 @@
HKCR
{
NoRemove Typelib
{
NoRemove '{3F4DACA7-160D-11D2-A8E9-00104B365C9F}'
{
'5.5' = s 'Microsoft VBScript Regular Expressions 5.5'
{
'0' { win32 = s '%MODULE%' }
FLAGS = s '0'
}
}
}
NoRemove Interface
{
'{3F4DACA0-160D-11D2-A8E9-00104B365C9F}' = s 'IRegExp'
{
ProxyStubClsid = s '{00020424-0000-0000-C000-000000000046}'
ProxyStubClsid32 = s '{00020424-0000-0000-C000-000000000046}'
TypeLib = s '{3F4DACA7-160D-11D2-A8E9-00104B365C9F}' { val Version = s '5.5' }
}
'{3F4DACB0-160D-11D2-A8E9-00104B365C9F}' = s 'IRegExp2'
{
ProxyStubClsid = s '{00020424-0000-0000-C000-000000000046}'
ProxyStubClsid32 = s '{00020424-0000-0000-C000-000000000046}'
TypeLib = s '{3F4DACA7-160D-11D2-A8E9-00104B365C9F}' { val Version = s '5.5' }
}
'{3F4DACA1-160D-11D2-A8E9-00104B365C9F}' = s 'IMatch'
{
ProxyStubClsid = s '{00020424-0000-0000-C000-000000000046}'
ProxyStubClsid32 = s '{00020424-0000-0000-C000-000000000046}'
TypeLib = s '{3F4DACA7-160D-11D2-A8E9-00104B365C9F}' { val Version = s '5.5' }
}
'{3F4DACB1-160D-11D2-A8E9-00104B365C9F}' = s 'IMatch2'
{
ProxyStubClsid = s '{00020424-0000-0000-C000-000000000046}'
ProxyStubClsid32 = s '{00020424-0000-0000-C000-000000000046}'
TypeLib = s '{3F4DACA7-160D-11D2-A8E9-00104B365C9F}' { val Version = s '5.5' }
}
'{3F4DACA2-160D-11D2-A8E9-00104B365C9F}' = s 'IMatchCollection'
{
ProxyStubClsid = s '{00020424-0000-0000-C000-000000000046}'
ProxyStubClsid32 = s '{00020424-0000-0000-C000-000000000046}'
TypeLib = s '{3F4DACA7-160D-11D2-A8E9-00104B365C9F}' { val Version = s '5.5' }
}
'{3F4DACB2-160D-11D2-A8E9-00104B365C9F}' = s 'IMatchCollection2'
{
ProxyStubClsid = s '{00020424-0000-0000-C000-000000000046}'
ProxyStubClsid32 = s '{00020424-0000-0000-C000-000000000046}'
TypeLib = s '{3F4DACA7-160D-11D2-A8E9-00104B365C9F}' { val Version = s '5.5' }
}
'{3F4DACB3-160D-11D2-A8E9-00104B365C9F}' = s 'ISubMatches'
{
ProxyStubClsid = s '{00020424-0000-0000-C000-000000000046}'
ProxyStubClsid32 = s '{00020424-0000-0000-C000-000000000046}'
TypeLib = s '{3F4DACA7-160D-11D2-A8E9-00104B365C9F}' { val Version = s '5.5' }
}
}
NoRemove CLSID
{
}
}
+1 -1
View File
@@ -207,7 +207,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.18
dll/win32/vbscript # Synced to Wine-10.0
dll/win32/version # Synced to WineStaging-4.18
dll/win32/vssapi # Synced to WineStaging-4.18
dll/win32/wbemdisp # Synced to WineStaging-4.18