Jacek Caban : vbscript: Added property invoke implementation.
Alexandre Julliard
julliard at winehq.org
Fri Sep 16 13:28:32 CDT 2011
Module: wine
Branch: master
Commit: e843608748b3d6cfdc3af6aa6f577ab706f31c65
URL: http://source.winehq.org/git/wine.git/?a=commit;h=e843608748b3d6cfdc3af6aa6f577ab706f31c65
Author: Jacek Caban <jacek at 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**);
More information about the wine-cvs
mailing list