Module: wine Branch: master Commit: e843608748b3d6cfdc3af6aa6f577ab706f31c65 URL: http://source.winehq.org/git/wine.git/?a=commit;h=e843608748b3d6cfdc3af6aa6f...
Author: Jacek Caban jacek@codeweavers.com Date: Fri Sep 16 13:27:48 2011 +0200
vbscript: Added property invoke implementation.
---
dlls/vbscript/tests/lang.vbs | 16 ++++++++++ dlls/vbscript/tests/run.c | 30 ++++++++++++++++++ dlls/vbscript/vbdisp.c | 68 ++++++++++++++++++++++++++++++++++++++++-- dlls/vbscript/vbscript.h | 1 + 4 files changed, 112 insertions(+), 3 deletions(-)
diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 3f9f73e..e29a20f 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -404,6 +404,14 @@ Class TestClass Public Sub publicSub End Sub
+ Public Sub setPrivateProp(x) + privateProp = x + End Sub + + Function getPrivateProp + getPrivateProp = privateProp + End Function + Private Sub privateSub End Sub End Class @@ -419,4 +427,12 @@ obj.publicSub() Call obj.publicSub Call obj.publicFunction()
+Call ok(getVT(obj.publicProp) = "VT_EMPTY", "getVT(obj.publicProp) = " & getVT(obj.publicProp)) +obj.publicProp = 3 +Call ok(obj.publicProp = 3, "obj.publicProp = " & obj.publicProp) +obj.publicProp() = 3 + +Call obj.setPrivateProp(6) +Call ok(obj.getPrivateProp = 6, "obj.getPrivateProp = " & obj.getPrivateProp) + reportSuccess() diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index 4fd46c9..f524b81 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -188,6 +188,36 @@ static void test_disp(IDispatch *disp) SysFreeString(str); ok(hres == S_OK, "GetDispID(publicProp2) failed: %08x\n", hres);
+ hres = IDispatchEx_InvokeEx(dispex, public_prop_id, 0, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dp, &v, &ei, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&v) == VT_EMPTY, "V_VT(v) = %d\n", V_VT(&v)); + + V_VT(args) = VT_BOOL; + V_BOOL(args) = VARIANT_TRUE; + dp.cArgs = dp.cNamedArgs = 1; + V_VT(&v) = VT_BOOL; + hres = IDispatchEx_InvokeEx(dispex, public_prop_id, 0, DISPATCH_PROPERTYPUT, &dp, &v, &ei, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&v) == VT_EMPTY, "V_VT(v) = %d\n", V_VT(&v)); + + dp.cArgs = dp.cNamedArgs = 0; + hres = IDispatchEx_InvokeEx(dispex, public_prop_id, 0, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dp, &v, &ei, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&v) == VT_BOOL, "V_VT(v) = %d\n", V_VT(&v)); + ok(V_BOOL(&v), "V_BOOL(v) = %x\n", V_BOOL(&v)); + + dp.cArgs = 1; + hres = IDispatchEx_InvokeEx(dispex, public_prop_id, 0, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dp, &v, &ei, NULL); + ok(hres == DISP_E_MEMBERNOTFOUND, "InvokeEx failed: %08x, expected DISP_E_MEMBERNOTFOUND\n", hres); + ok(V_VT(&v) == VT_EMPTY, "V_VT(v) = %d\n", V_VT(&v)); + + V_VT(args) = VT_BOOL; + V_BOOL(args) = VARIANT_FALSE; + dp.cArgs = 1; + V_VT(&v) = VT_BOOL; + hres = IDispatchEx_InvokeEx(dispex, public_prop_id, 0, DISPATCH_PROPERTYPUT, &dp, NULL, &ei, NULL); + ok(hres == DISP_E_PARAMNOTOPTIONAL, "InvokeEx failed: %08x, expected DISP_E_PARAMNOTOPTIONAL\n", hres); + str = a2bstr("publicFunction"); hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseInsensitive, &public_func_id); SysFreeString(str); diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index 2d0540f..e9bcb2a 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -67,6 +67,64 @@ HRESULT vbdisp_get_id(vbdisp_t *This, BSTR name, BOOL search_private, DISPID *id return DISP_E_UNKNOWNNAME; }
+static VARIANT *get_propput_arg(const DISPPARAMS *dp) +{ + unsigned i; + + for(i=0; i < dp->cNamedArgs; i++) { + if(dp->rgdispidNamedArgs[i] == DISPID_PROPERTYPUT) + return dp->rgvarg+i; + } + + return NULL; +} + +static HRESULT invoke_variant_prop(vbdisp_t *This, VARIANT *v, WORD flags, DISPPARAMS *dp, VARIANT *res) +{ + HRESULT hres; + + switch(flags) { + case DISPATCH_PROPERTYGET|DISPATCH_METHOD: + if(dp->cArgs) { + WARN("called with arguments\n"); + return DISP_E_MEMBERNOTFOUND; /* That's what tests show */ + } + + hres = VariantCopy(res, v); + break; + + case DISPATCH_PROPERTYPUT: { + VARIANT *put_val; + + put_val = get_propput_arg(dp); + if(!put_val) { + WARN("no value to set\n"); + return DISP_E_PARAMNOTOPTIONAL; + } + + if(res) + V_VT(res) = VT_EMPTY; + + hres = VariantCopy(v, put_val); + break; + } + + default: + FIXME("unimplemented flags %x\n", flags); + return E_NOTIMPL; + } + + return hres; +} + +static void clean_props(vbdisp_t *This) +{ + unsigned i; + + for(i=0; i < This->desc->prop_cnt; i++) + VariantClear(This->props+i); +} + static inline vbdisp_t *impl_from_IDispatchEx(IDispatchEx *iface) { return CONTAINING_RECORD(iface, vbdisp_t, IDispatchEx_iface); @@ -110,8 +168,10 @@ static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface) vbdisp_t *This = impl_from_IDispatchEx(iface); LONG ref = InterlockedIncrement(&This->ref);
- if(!ref) + if(!ref) { + clean_props(This); heap_free(This); + }
return ref; } @@ -200,7 +260,9 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc } }
- FIXME("not implemented for non-function ids\n"); + 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); + return DISP_E_MEMBERNOTFOUND; }
@@ -275,7 +337,7 @@ HRESULT create_vbdisp(const class_desc_t *desc, vbdisp_t **ret) { vbdisp_t *vbdisp;
- vbdisp = heap_alloc_zero(sizeof(*vbdisp)); + vbdisp = heap_alloc_zero(sizeof(*vbdisp) + (desc->prop_cnt-1)*sizeof(VARIANT)); if(!vbdisp) return E_OUTOFMEMORY;
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index d886a4e..ce1fa01 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -89,6 +89,7 @@ typedef struct { LONG ref;
const class_desc_t *desc; + VARIANT props[1]; } vbdisp_t;
HRESULT create_vbdisp(const class_desc_t*,vbdisp_t**);