| /* |
| * Copyright 2011 Jacek Caban for CodeWeavers |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include <stdarg.h> |
| |
| #define COBJMACROS |
| |
| #include "windef.h" |
| #include "winbase.h" |
| #include "ole2.h" |
| #include "dispex.h" |
| #include "activscp.h" |
| |
| #include "vbscript_classes.h" |
| |
| #include "wine/list.h" |
| #include "wine/unicode.h" |
| |
| typedef struct { |
| void **blocks; |
| DWORD block_cnt; |
| DWORD last_block; |
| DWORD offset; |
| BOOL mark; |
| 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; |
| |
| 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, |
| VBDISP_SET, |
| VBDISP_ANY |
| } vbdisp_invoke_type_t; |
| |
| typedef struct { |
| unsigned dim_cnt; |
| SAFEARRAYBOUND *bounds; |
| } array_desc_t; |
| |
| typedef struct { |
| BOOL is_public; |
| BOOL is_array; |
| const WCHAR *name; |
| } vbdisp_prop_desc_t; |
| |
| typedef struct { |
| const WCHAR *name; |
| BOOL is_public; |
| BOOL is_array; |
| function_t *entries[VBDISP_ANY]; |
| } vbdisp_funcprop_desc_t; |
| |
| #define BP_GET 1 |
| #define BP_GETPUT 2 |
| |
| typedef struct { |
| DISPID id; |
| HRESULT (*proc)(vbdisp_t*,VARIANT*,unsigned,VARIANT*); |
| DWORD flags; |
| unsigned min_args; |
| UINT_PTR max_args; |
| } builtin_prop_t; |
| |
| typedef struct _class_desc_t { |
| const WCHAR *name; |
| script_ctx_t *ctx; |
| |
| unsigned class_initialize_id; |
| unsigned class_terminate_id; |
| unsigned func_cnt; |
| vbdisp_funcprop_desc_t *funcs; |
| |
| unsigned prop_cnt; |
| vbdisp_prop_desc_t *props; |
| |
| unsigned array_cnt; |
| array_desc_t *array_descs; |
| |
| unsigned builtin_prop_cnt; |
| const builtin_prop_t *builtin_props; |
| ITypeInfo *typeinfo; |
| function_t *value_func; |
| |
| struct _class_desc_t *next; |
| } class_desc_t; |
| |
| struct _vbdisp_t { |
| IDispatchEx IDispatchEx_iface; |
| |
| LONG ref; |
| BOOL terminator_ran; |
| struct list entry; |
| |
| const class_desc_t *desc; |
| SAFEARRAY **arrays; |
| VARIANT props[1]; |
| }; |
| |
| typedef struct _ident_map_t ident_map_t; |
| |
| typedef struct { |
| IDispatchEx IDispatchEx_iface; |
| LONG ref; |
| |
| ident_map_t *ident_map; |
| unsigned ident_map_cnt; |
| unsigned ident_map_size; |
| |
| script_ctx_t *ctx; |
| } ScriptDisp; |
| |
| 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_procedure_disp(script_ctx_t*,vbscode_t*,IDispatch**) DECLSPEC_HIDDEN; |
| HRESULT create_script_disp(script_ctx_t*,ScriptDisp**) DECLSPEC_HIDDEN; |
| |
| HRESULT to_int(VARIANT*,int*) DECLSPEC_HIDDEN; |
| |
| static inline unsigned arg_cnt(const DISPPARAMS *dp) |
| { |
| return dp->cArgs - dp->cNamedArgs; |
| } |
| |
| 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; |
| |
| struct _script_ctx_t { |
| IActiveScriptSite *site; |
| LCID lcid; |
| |
| IInternetHostSecurityManager *secmgr; |
| DWORD safeopt; |
| |
| IDispatch *host_global; |
| |
| ScriptDisp *script_obj; |
| |
| class_desc_t global_desc; |
| vbdisp_t *global_obj; |
| |
| class_desc_t err_desc; |
| vbdisp_t *err_obj; |
| |
| HRESULT err_number; |
| |
| dynamic_var_t *global_vars; |
| function_t *global_funcs; |
| class_desc_t *classes; |
| class_desc_t *procs; |
| |
| heap_pool_t heap; |
| |
| 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; |
| |
| IUnknown *create_ax_site(script_ctx_t*) DECLSPEC_HIDDEN; |
| |
| typedef enum { |
| ARG_NONE = 0, |
| ARG_STR, |
| ARG_BSTR, |
| ARG_INT, |
| ARG_UINT, |
| ARG_ADDR, |
| ARG_DOUBLE |
| } instr_arg_type_t; |
| |
| #define OP_LIST \ |
| X(add, 1, 0, 0) \ |
| X(and, 1, 0, 0) \ |
| 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(case, 0, ARG_ADDR, 0) \ |
| X(concat, 1, 0, 0) \ |
| X(const, 1, ARG_BSTR, 0) \ |
| X(dim, 1, ARG_BSTR, ARG_UINT) \ |
| X(div, 1, 0, 0) \ |
| X(double, 1, ARG_DOUBLE, 0) \ |
| X(empty, 1, 0, 0) \ |
| X(enumnext, 0, ARG_ADDR, ARG_BSTR) \ |
| X(equal, 1, 0, 0) \ |
| X(hres, 1, ARG_UINT, 0) \ |
| X(errmode, 1, ARG_INT, 0) \ |
| X(eqv, 1, 0, 0) \ |
| X(exp, 1, 0, 0) \ |
| X(gt, 1, 0, 0) \ |
| X(gteq, 1, 0, 0) \ |
| X(icall, 1, ARG_BSTR, ARG_UINT) \ |
| X(icallv, 1, ARG_BSTR, ARG_UINT) \ |
| X(idiv, 1, 0, 0) \ |
| X(imp, 1, 0, 0) \ |
| X(incc, 1, ARG_BSTR, 0) \ |
| X(is, 1, 0, 0) \ |
| X(jmp, 0, ARG_ADDR, 0) \ |
| X(jmp_false, 0, ARG_ADDR, 0) \ |
| X(jmp_true, 0, ARG_ADDR, 0) \ |
| X(long, 1, ARG_INT, 0) \ |
| X(lt, 1, 0, 0) \ |
| X(lteq, 1, 0, 0) \ |
| X(mcall, 1, ARG_BSTR, ARG_UINT) \ |
| X(mcallv, 1, ARG_BSTR, ARG_UINT) \ |
| X(me, 1, 0, 0) \ |
| X(mod, 1, 0, 0) \ |
| X(mul, 1, 0, 0) \ |
| X(neg, 1, 0, 0) \ |
| X(nequal, 1, 0, 0) \ |
| X(new, 1, ARG_STR, 0) \ |
| X(newenum, 1, 0, 0) \ |
| X(not, 1, 0, 0) \ |
| X(nothing, 1, 0, 0) \ |
| X(null, 1, 0, 0) \ |
| X(or, 1, 0, 0) \ |
| X(pop, 1, ARG_UINT, 0) \ |
| X(ret, 0, 0, 0) \ |
| X(set_ident, 1, ARG_BSTR, ARG_UINT) \ |
| X(set_member, 1, ARG_BSTR, ARG_UINT) \ |
| X(short, 1, ARG_INT, 0) \ |
| X(step, 0, ARG_ADDR, ARG_BSTR) \ |
| X(stop, 1, 0, 0) \ |
| X(string, 1, ARG_STR, 0) \ |
| X(sub, 1, 0, 0) \ |
| X(val, 1, 0, 0) \ |
| X(xor, 1, 0, 0) |
| |
| typedef enum { |
| #define X(x,n,a,b) OP_##x, |
| OP_LIST |
| #undef X |
| OP_LAST |
| } vbsop_t; |
| |
| typedef union { |
| const WCHAR *str; |
| BSTR bstr; |
| unsigned uint; |
| LONG lng; |
| double *dbl; |
| } instr_arg_t; |
| |
| typedef struct { |
| vbsop_t op; |
| instr_arg_t arg1; |
| instr_arg_t arg2; |
| } instr_t; |
| |
| typedef struct { |
| const WCHAR *name; |
| BOOL by_ref; |
| } arg_desc_t; |
| |
| typedef enum { |
| FUNC_GLOBAL, |
| FUNC_FUNCTION, |
| FUNC_SUB, |
| FUNC_PROPGET, |
| FUNC_PROPLET, |
| FUNC_PROPSET, |
| FUNC_DEFGET |
| } function_type_t; |
| |
| typedef struct { |
| const WCHAR *name; |
| } var_desc_t; |
| |
| struct _function_t { |
| function_type_t type; |
| const WCHAR *name; |
| BOOL is_public; |
| arg_desc_t *args; |
| unsigned arg_cnt; |
| var_desc_t *vars; |
| unsigned var_cnt; |
| array_desc_t *array_descs; |
| unsigned array_cnt; |
| unsigned code_off; |
| vbscode_t *code_ctx; |
| function_t *next; |
| }; |
| |
| struct _vbscode_t { |
| instr_t *instrs; |
| WCHAR *source; |
| |
| BOOL option_explicit; |
| |
| BOOL pending_exec; |
| function_t main_code; |
| |
| BSTR *bstr_pool; |
| unsigned bstr_pool_size; |
| unsigned bstr_cnt; |
| heap_pool_t heap; |
| |
| struct list entry; |
| }; |
| |
| void release_vbscode(vbscode_t*) DECLSPEC_HIDDEN; |
| HRESULT compile_script(script_ctx_t*,const WCHAR*,const WCHAR*,vbscode_t**) DECLSPEC_HIDDEN; |
| HRESULT exec_script(script_ctx_t*,function_t*,vbdisp_t*,DISPPARAMS*,VARIANT*) DECLSPEC_HIDDEN; |
| void release_dynamic_vars(dynamic_var_t*) DECLSPEC_HIDDEN; |
| |
| typedef struct { |
| UINT16 len; |
| WCHAR buf[7]; |
| } string_constant_t; |
| |
| #define TID_LIST \ |
| XDIID(ErrObj) \ |
| XDIID(GlobalObj) |
| |
| typedef enum { |
| #define XDIID(iface) iface ## _tid, |
| TID_LIST |
| #undef XDIID |
| LAST_tid |
| } tid_t; |
| |
| HRESULT get_typeinfo(tid_t,ITypeInfo**) DECLSPEC_HIDDEN; |
| void release_regexp_typelib(void) DECLSPEC_HIDDEN; |
| |
| #ifndef INT32_MIN |
| #define INT32_MIN (-2147483647-1) |
| #endif |
| |
| #ifndef INT32_MAX |
| #define INT32_MAX (2147483647) |
| #endif |
| |
| static inline BOOL is_int32(double d) |
| { |
| return INT32_MIN <= d && d <= INT32_MAX && (double)(int)d == d; |
| } |
| |
| HRESULT create_regexp(IDispatch**) DECLSPEC_HIDDEN; |
| |
| HRESULT map_hres(HRESULT) DECLSPEC_HIDDEN; |
| |
| #define FACILITY_VBS 0xa |
| #define MAKE_VBSERROR(code) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_VBS, code) |
| |
| #define VBSE_ILLEGAL_FUNC_CALL 5 |
| #define VBSE_OVERFLOW 6 |
| #define VBSE_OUT_OF_MEMORY 7 |
| #define VBSE_OUT_OF_BOUNDS 9 |
| #define VBSE_ARRAY_LOCKED 10 |
| #define VBSE_TYPE_MISMATCH 13 |
| #define VBSE_FILE_NOT_FOUND 53 |
| #define VBSE_IO_ERROR 57 |
| #define VBSE_FILE_ALREADY_EXISTS 58 |
| #define VBSE_DISK_FULL 61 |
| #define VBSE_TOO_MANY_FILES 67 |
| #define VBSE_PERMISSION_DENIED 70 |
| #define VBSE_PATH_FILE_ACCESS 75 |
| #define VBSE_PATH_NOT_FOUND 76 |
| #define VBSE_ILLEGAL_NULL_USE 94 |
| #define VBSE_OLE_NOT_SUPPORTED 430 |
| #define VBSE_OLE_NO_PROP_OR_METHOD 438 |
| #define VBSE_ACTION_NOT_SUPPORTED 445 |
| #define VBSE_NAMED_ARGS_NOT_SUPPORTED 446 |
| #define VBSE_LOCALE_SETTING_NOT_SUPPORTED 447 |
| #define VBSE_NAMED_PARAM_NOT_FOUND 448 |
| #define VBSE_INVALID_TYPELIB_VARIABLE 458 |
| #define VBSE_FUNC_ARITY_MISMATCH 450 |
| #define VBSE_PARAMETER_NOT_OPTIONAL 449 |
| #define VBSE_NOT_ENUM 451 |
| #define VBSE_INVALID_DLL_FUNCTION_NAME 453 |
| #define VBSE_CANT_CREATE_TMP_FILE 322 |
| #define VBSE_OLE_FILE_NOT_FOUND 432 |
| #define VBSE_CANT_CREATE_OBJECT 429 |
| #define VBSE_SERVER_NOT_FOUND 462 |
| |
| HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**) DECLSPEC_HIDDEN; |
| HRESULT WINAPI VBScriptRegExpFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**) DECLSPEC_HIDDEN; |
| |
| static inline void* __WINE_ALLOC_SIZE(1) heap_alloc(size_t size) |
| { |
| return HeapAlloc(GetProcessHeap(), 0, size); |
| } |
| |
| static inline void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(size_t size) |
| { |
| return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); |
| } |
| |
| static inline void* __WINE_ALLOC_SIZE(2) heap_realloc(void *mem, size_t size) |
| { |
| return HeapReAlloc(GetProcessHeap(), 0, mem, size); |
| } |
| |
| static inline BOOL heap_free(void *mem) |
| { |
| return HeapFree(GetProcessHeap(), 0, mem); |
| } |
| |
| static inline LPWSTR heap_strdupW(LPCWSTR str) |
| { |
| LPWSTR ret = NULL; |
| |
| if(str) { |
| DWORD size; |
| |
| size = (strlenW(str)+1)*sizeof(WCHAR); |
| ret = heap_alloc(size); |
| if(ret) |
| memcpy(ret, str, size); |
| } |
| |
| return ret; |
| } |
| |
| #define VBSCRIPT_BUILD_VERSION 16978 |
| #define VBSCRIPT_MAJOR_VERSION 5 |
| #define VBSCRIPT_MINOR_VERSION 8 |