From 4e9d29907cd682bd7c854fda203cfbdb4271a595 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 19 Sep 2011 14:08:38 +0200 Subject: [PATCH] vbscript: Added global object's isObject function stub implementation. --- .gitignore | 1 + dlls/vbscript/Makefile.in | 7 +++- dlls/vbscript/compile.c | 15 ++++++--- dlls/vbscript/global.c | 58 ++++++++++++++++++++++++++++++++ dlls/vbscript/interp.c | 8 +++++ dlls/vbscript/vbdisp.c | 58 ++++++++++++++++++++++++++++---- dlls/vbscript/vbscript.c | 2 ++ dlls/vbscript/vbscript.h | 40 ++++++++++++++++++++-- dlls/vbscript/vbscript_main.c | 63 +++++++++++++++++++++++++++++++++++ 9 files changed, 239 insertions(+), 13 deletions(-) create mode 100644 dlls/vbscript/global.c diff --git a/.gitignore b/.gitignore index b1d82ebc745..b9a7636564f 100644 --- a/.gitignore +++ b/.gitignore @@ -125,6 +125,7 @@ dlls/urlmon/urlmon_urlmon_p.c dlls/vbscript/parser.tab.c dlls/vbscript/parser.tab.h dlls/vbscript/vbscript_classes.h +dlls/vbscript/vbsglobal.h dlls/windowscodecs/windowscodecs_wincodec.h dlls/windowscodecs/windowscodecs_wincodec_p.c include/activaut.h diff --git a/dlls/vbscript/Makefile.in b/dlls/vbscript/Makefile.in index bfc07b57a5a..e1a83820596 100644 --- a/dlls/vbscript/Makefile.in +++ b/dlls/vbscript/Makefile.in @@ -3,6 +3,7 @@ IMPORTS = oleaut32 C_SRCS = \ compile.c \ + global.c \ interp.c \ lex.c \ vbdisp.c \ @@ -14,8 +15,12 @@ BISON_SRCS = \ RC_SRCS = vbscript.rc +IDL_H_SRCS = \ + vbscript_classes.idl \ + vbsglobal.idl + IDL_TLB_SRCS = vbsglobal.idl -IDL_H_SRCS = vbscript_classes.idl + IDL_R_SRCS = vbscript_classes.idl @MAKE_DLL_RULES@ diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index df08c2422c6..11023781a42 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -107,6 +107,16 @@ static inline void *compiler_alloc(vbscode_t *vbscode, size_t size) return vbsheap_alloc(&vbscode->heap, size); } +static inline void *compiler_alloc_zero(vbscode_t *vbscode, size_t size) +{ + void *ret; + + ret = vbsheap_alloc(&vbscode->heap, size); + if(ret) + memset(ret, 0, size); + return ret; +} + static WCHAR *compiler_alloc_string(vbscode_t *vbscode, const WCHAR *str) { size_t size; @@ -1006,7 +1016,7 @@ static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl) return E_FAIL; } - class_desc = compiler_alloc(ctx->code, sizeof(*class_desc)); + class_desc = compiler_alloc_zero(ctx->code, sizeof(*class_desc)); if(!class_desc) return E_OUTOFMEMORY; @@ -1015,9 +1025,6 @@ static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl) return E_OUTOFMEMORY; class_desc->func_cnt = 1; /* always allocate slot for default getter */ - class_desc->prop_cnt = 0; - class_desc->class_initialize_id = 0; - class_desc->class_terminate_id = 0; for(func_decl = class_decl->funcs; func_decl; func_decl = func_decl->next) { for(func_prop_decl = func_decl; func_prop_decl; func_prop_decl = func_prop_decl->next_prop_func) { diff --git a/dlls/vbscript/global.c b/dlls/vbscript/global.c new file mode 100644 index 00000000000..87aef8f9ad4 --- /dev/null +++ b/dlls/vbscript/global.c @@ -0,0 +1,58 @@ +/* + * 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 "vbscript.h" +#include "vbscript_defs.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(vbscript); + +static HRESULT Global_IsObject(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static const builtin_prop_t global_props[] = { + {DISPID_GLOBAL_ISOBJECT, Global_IsObject, 0, 1} +}; + +HRESULT init_global(script_ctx_t *ctx) +{ + HRESULT hres; + + ctx->global_desc.ctx = ctx; + ctx->global_desc.builtin_prop_cnt = sizeof(global_props)/sizeof(*global_props); + ctx->global_desc.builtin_props = global_props; + + hres = get_typeinfo(GlobalObj_tid, &ctx->global_desc.typeinfo); + if(FAILED(hres)) + return hres; + + hres = create_vbdisp(&ctx->global_desc, &ctx->global_obj); + if(FAILED(hres)) + return hres; + + ctx->script_desc.ctx = ctx; + hres = create_vbdisp(&ctx->script_desc, &ctx->script_obj); + if(FAILED(hres)) + return hres; + + return S_OK; +} diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index 472d23c4d44..7c3df7db48b 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -147,6 +147,14 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_ } } + hres = vbdisp_get_id(ctx->script->global_obj, name, invoke_type, TRUE, &id); + if(SUCCEEDED(hres)) { + ref->type = REF_DISP; + ref->u.d.disp = (IDispatch*)&ctx->script->global_obj->IDispatchEx_iface; + ref->u.d.id = id; + return S_OK; + } + if(!ctx->func->code_ctx->option_explicit) FIXME("create an attempt to set\n"); diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index 19a511eb463..96df71af54e 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -69,6 +69,14 @@ HRESULT vbdisp_get_id(vbdisp_t *This, BSTR name, vbdisp_invoke_type_t invoke_typ } } + if(This->desc->typeinfo) { + HRESULT hres; + + hres = ITypeInfo_GetIDsOfNames(This->desc->typeinfo, &name, 1, id); + if(SUCCEEDED(hres)) + return S_OK; + } + *id = -1; return DISP_E_UNKNOWNNAME; } @@ -123,6 +131,36 @@ static HRESULT invoke_variant_prop(vbdisp_t *This, VARIANT *v, WORD flags, DISPP return hres; } +static HRESULT invoke_builtin(vbdisp_t *This, const builtin_prop_t *prop, WORD flags, DISPPARAMS *dp, VARIANT *res) +{ + switch(flags) { + case DISPATCH_PROPERTYGET: + if(!(prop->flags & (BP_GET|BP_GETPUT))) { + FIXME("property does not support DISPATCH_PROPERTYGET\n"); + return E_FAIL; + } + /* FALLTHROUGH */ + case DISPATCH_PROPERTYGET|DISPATCH_METHOD: + if(arg_cnt(dp) < prop->min_args || arg_cnt(dp) > (prop->max_args ? prop->max_args : prop->min_args)) { + FIXME("invalid number of arguments\n"); + return E_FAIL; + } + + return prop->proc(This, dp->rgvarg, dp->cArgs, res); + case DISPATCH_PROPERTYPUT: + if(!(prop->flags & (BP_GET|BP_GETPUT))) { + FIXME("property does not support DISPATCH_PROPERTYPUT\n"); + return E_FAIL; + } + + FIXME("call put\n"); + return E_NOTIMPL; + default: + FIXME("unsupported flags %x\n", flags); + return E_NOTIMPL; + } +} + static BOOL run_terminator(vbdisp_t *This) { DISPPARAMS dp = {0}; @@ -322,6 +360,20 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc if(id < This->desc->prop_cnt + This->desc->func_cnt) return invoke_variant_prop(This, This->props+(id-This->desc->func_cnt), wFlags, pdp, pvarRes); + if(This->desc->builtin_prop_cnt) { + unsigned min = 0, max = This->desc->builtin_prop_cnt-1, i; + + while(min <= max) { + i = (min+max)/2; + if(This->desc->builtin_props[i].id == id) + return invoke_builtin(This, This->desc->builtin_props+i, wFlags, pdp, pvarRes); + if(This->desc->builtin_props[i].id < id) + min = i+1; + else + max = i-1; + } + } + return DISP_E_MEMBERNOTFOUND; } @@ -436,12 +488,6 @@ void collect_objects(script_ctx_t *ctx) } } -HRESULT init_global(script_ctx_t *ctx) -{ - ctx->script_desc.ctx = ctx; - return create_vbdisp(&ctx->script_desc, &ctx->script_obj); -} - HRESULT disp_get_id(IDispatch *disp, BSTR name, vbdisp_invoke_type_t invoke_type, BOOL search_private, DISPID *id) { IDispatchEx *dispex; diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c index 80747994de1..9b61b936ac2 100644 --- a/dlls/vbscript/vbscript.c +++ b/dlls/vbscript/vbscript.c @@ -131,6 +131,8 @@ static void destroy_script(script_ctx_t *ctx) IDispatch_Release(ctx->host_global); if(ctx->site) IActiveScriptSite_Release(ctx->site); + if(ctx->global_obj) + IDispatchEx_Release(&ctx->global_obj->IDispatchEx_iface); if(ctx->script_obj) IDispatchEx_Release(&ctx->script_obj->IDispatchEx_iface); heap_free(ctx); diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index 60835118961..5bd7ff9f26a 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -46,6 +46,7 @@ void vbsheap_free(vbsheap_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; @@ -73,19 +74,37 @@ typedef struct { function_t *entries[VBDISP_ANY]; } vbdisp_funcprop_desc_t; +#define BP_GET 1 +#define BP_GETPUT 2 + +typedef struct { + DISPID id; + HRESULT (*proc)(vbdisp_t*,VARIANT*,unsigned,VARIANT*); + DWORD flags; + unsigned min_args; + unsigned 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 builtin_prop_cnt; + const builtin_prop_t *builtin_props; + ITypeInfo *typeinfo; + struct _class_desc_t *next; } class_desc_t; -typedef struct { +struct _vbdisp_t { IDispatchEx IDispatchEx_iface; LONG ref; @@ -94,10 +113,11 @@ typedef struct { const class_desc_t *desc; VARIANT props[1]; -} vbdisp_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,VARIANT*); void collect_objects(script_ctx_t*); @@ -127,6 +147,9 @@ struct _script_ctx_t { class_desc_t script_desc; vbdisp_t *script_obj; + class_desc_t global_desc; + vbdisp_t *global_obj; + dynamic_var_t *global_vars; function_t *global_funcs; class_desc_t *classes; @@ -268,6 +291,19 @@ void release_vbscode(vbscode_t*) DECLSPEC_HIDDEN; HRESULT compile_script(script_ctx_t*,const WCHAR*,vbscode_t**) DECLSPEC_HIDDEN; HRESULT exec_script(script_ctx_t*,function_t*,IDispatch*,DISPPARAMS*,VARIANT*) DECLSPEC_HIDDEN; +#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**); + HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**); const char *debugstr_variant(const VARIANT*) DECLSPEC_HIDDEN; diff --git a/dlls/vbscript/vbscript_main.c b/dlls/vbscript/vbscript_main.c index 43ab484735d..4054d35e7a5 100644 --- a/dlls/vbscript/vbscript_main.c +++ b/dlls/vbscript/vbscript_main.c @@ -22,6 +22,7 @@ #include "objsafe.h" #include "rpcproxy.h" #include "vbscript_classes.h" +#include "vbsglobal.h" #include "wine/debug.h" @@ -31,6 +32,66 @@ DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); static HINSTANCE vbscript_hinstance; +static ITypeLib *typelib; +static ITypeInfo *typeinfos[LAST_tid]; + +static REFIID tid_ids[] = { +#define XDIID(iface) &DIID_ ## iface, +TID_LIST +#undef XDIID +}; + +HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo) +{ + HRESULT hres; + + if (!typelib) { + ITypeLib *tl; + + static const WCHAR vbscript_dll1W[] = {'v','b','s','c','r','i','p','t','.','d','l','l','\\','1',0}; + + hres = LoadTypeLib(vbscript_dll1W, &tl); + if(FAILED(hres)) { + ERR("LoadRegTypeLib failed: %08x\n", hres); + return hres; + } + + if(InterlockedCompareExchangePointer((void**)&typelib, tl, NULL)) + ITypeLib_Release(tl); + } + + if(!typeinfos[tid]) { + ITypeInfo *ti; + + hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti); + if(FAILED(hres)) { + ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hres); + return hres; + } + + if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL)) + ITypeInfo_Release(ti); + } + + *typeinfo = typeinfos[tid]; + return S_OK; +} + +static void release_typelib(void) +{ + unsigned i; + + if(!typelib) + return; + + for(i=0; i < sizeof(typeinfos)/sizeof(*typeinfos); i++) { + if(typeinfos[i]) + ITypeInfo_Release(typeinfos[i]); + } + + ITypeLib_Release(typelib); +} + const char *debugstr_variant(const VARIANT *v) { if(!v) @@ -210,6 +271,8 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) DisableThreadLibraryCalls(hInstDLL); vbscript_hinstance = hInstDLL; break; + case DLL_PROCESS_DETACH: + release_typelib(); } return TRUE;