Jacek Caban : vbscript: Added interp_icallv implementation.

Alexandre Julliard julliard at winehq.org
Thu Sep 8 14:52:12 CDT 2011


Module: wine
Branch: master
Commit: 9d7552205c5aa43c42db252b3f62eb6ca8d460be
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=9d7552205c5aa43c42db252b3f62eb6ca8d460be

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Thu Sep  8 14:54:37 2011 +0200

vbscript: Added interp_icallv implementation.

---

 dlls/vbscript/interp.c        |   67 +++++++++++++++++++++++++++++++++++++++--
 dlls/vbscript/vbdisp.c        |   43 ++++++++++++++++++++++++++
 dlls/vbscript/vbscript.h      |    8 ++++-
 dlls/vbscript/vbscript_main.c |    2 +
 4 files changed, 115 insertions(+), 5 deletions(-)

diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c
index 3ff6bbd..b309397 100644
--- a/dlls/vbscript/interp.c
+++ b/dlls/vbscript/interp.c
@@ -28,15 +28,75 @@ WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
 typedef struct {
     vbscode_t *code;
     instr_t *instr;
+    script_ctx_t *script;
 } exec_ctx_t;
 
-
 typedef HRESULT (*instr_func_t)(exec_ctx_t*);
 
+typedef enum {
+    REF_NONE,
+    REF_DISP
+} ref_type_t;
+
+typedef struct {
+    ref_type_t type;
+    union {
+        struct {
+            IDispatch *disp;
+            DISPID id;
+        } d;
+    } u;
+} ref_t;
+
+static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, ref_t *ref)
+{
+    named_item_t *item;
+    DISPID id;
+    HRESULT hres;
+
+    LIST_FOR_EACH_ENTRY(item, &ctx->script->named_items, named_item_t, entry) {
+        if(item->flags & SCRIPTITEM_GLOBALMEMBERS) {
+            hres = disp_get_id(item->disp, name, &id);
+            if(SUCCEEDED(hres)) {
+                ref->type = REF_DISP;
+                ref->u.d.disp = item->disp;
+                ref->u.d.id = id;
+                return S_OK;
+            }
+        }
+    }
+
+    FIXME("create if no option explicit\n");
+
+    ref->type = REF_NONE;
+    return S_OK;
+}
+
 static HRESULT interp_icallv(exec_ctx_t *ctx)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    BSTR identifier = ctx->instr->arg1.bstr;
+    DISPPARAMS dp = {0};
+    ref_t ref;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    hres = lookup_identifier(ctx, identifier, &ref);
+    if(FAILED(hres))
+        return hres;
+
+    switch(ref.type) {
+    case REF_DISP:
+        hres = disp_call(ctx->script, ref.u.d.disp, ref.u.d.id, &dp, NULL);
+        if(FAILED(hres))
+            return hres;
+        break;
+    default:
+        FIXME("%s not found\n", debugstr_w(identifier));
+        return DISP_E_UNKNOWNNAME;
+    }
+
+    return S_OK;
 }
 
 static HRESULT interp_ret(exec_ctx_t *ctx)
@@ -67,6 +127,7 @@ HRESULT exec_script(script_ctx_t *ctx, function_t *func)
 
     exec.code = func->code_ctx;
     exec.instr = exec.code->instrs + func->code_off;
+    exec.script = ctx;
 
     while(exec.instr) {
         op = exec.instr->op;
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c
index 3c81789..c115199 100644
--- a/dlls/vbscript/vbdisp.c
+++ b/dlls/vbscript/vbdisp.c
@@ -203,3 +203,46 @@ HRESULT init_global(script_ctx_t *ctx)
 {
     return create_vbdisp(&ctx->script_obj);
 }
+
+HRESULT disp_get_id(IDispatch *disp, BSTR name, DISPID *id)
+{
+    IDispatchEx *dispex;
+    HRESULT hres;
+
+    if(disp->lpVtbl == (IDispatchVtbl*)&DispatchExVtbl)
+        FIXME("properly handle builtin objects\n");
+
+    hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
+    if(FAILED(hres)) {
+        TRACE("unsing IDispatch\n");
+        return IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id);
+    }
+
+    hres = IDispatchEx_GetDispID(dispex, name, fdexNameCaseInsensitive, id);
+    IDispatchEx_Release(dispex);
+    return hres;
+}
+
+HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, DISPPARAMS *dp, VARIANT *retv)
+{
+    const WORD flags = DISPATCH_METHOD|(retv ? DISPATCH_PROPERTYGET : 0);
+    IDispatchEx *dispex;
+    EXCEPINFO ei;
+    HRESULT hres;
+
+    memset(&ei, 0, sizeof(ei));
+    if(retv)
+        V_VT(retv) = VT_EMPTY;
+
+    hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
+    if(FAILED(hres)) {
+        UINT err = 0;
+
+        TRACE("using IDispatch\n");
+        return IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, flags, dp, retv, &ei, &err);
+    }
+
+    hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, dp, retv, &ei, NULL /* CALLER_FIXME */);
+    IDispatchEx_Release(dispex);
+    return hres;
+}
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h
index 9942ac7..8aca01c 100644
--- a/dlls/vbscript/vbscript.h
+++ b/dlls/vbscript/vbscript.h
@@ -33,6 +33,7 @@
 
 typedef struct _function_t function_t;
 typedef struct _vbscode_t vbscode_t;
+typedef struct _script_ctx_t script_ctx_t;
 
 typedef struct named_item_t {
     IDispatch *disp;
@@ -48,7 +49,10 @@ typedef struct {
     LONG ref;
 } vbdisp_t;
 
-typedef struct {
+HRESULT disp_get_id(IDispatch*,BSTR,DISPID*);
+HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,DISPPARAMS*,VARIANT*);
+
+struct _script_ctx_t {
     IActiveScriptSite *site;
     LCID lcid;
 
@@ -58,7 +62,7 @@ typedef struct {
 
     struct list code_list;
     struct list named_items;
-} script_ctx_t;
+};
 
 HRESULT init_global(script_ctx_t*);
 
diff --git a/dlls/vbscript/vbscript_main.c b/dlls/vbscript/vbscript_main.c
index fc31aed..9d74026 100644
--- a/dlls/vbscript/vbscript_main.c
+++ b/dlls/vbscript/vbscript_main.c
@@ -27,6 +27,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
 
+DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
+
 static HINSTANCE vbscript_hinstance;
 
 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)




More information about the wine-cvs mailing list