Jacek Caban : mshtml: Added function object implementation.

Alexandre Julliard julliard at winehq.org
Tue Sep 1 11:05:35 CDT 2009


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Mon Aug 31 20:46:41 2009 +0200

mshtml: Added function object implementation.

---

 dlls/mshtml/dispex.c |  167 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 161 insertions(+), 6 deletions(-)

diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c
index 059ed66..b4cfe3f 100644
--- a/dlls/mshtml/dispex.c
+++ b/dlls/mshtml/dispex.c
@@ -35,12 +35,14 @@ typedef struct {
     DISPID id;
     BSTR name;
     tid_t tid;
+    int func_disp_idx;
 } func_info_t;
 
 struct dispex_data_t {
     DWORD func_cnt;
     func_info_t *funcs;
     func_info_t **name_table;
+    DWORD func_disp_cnt;
 
     struct list entry;
 };
@@ -50,10 +52,20 @@ typedef struct {
     LPWSTR name;
 } dynamic_prop_t;
 
+typedef struct {
+    DispatchEx dispex;
+    const IUnknownVtbl *lpIUnknownVtbl;
+    DispatchEx *obj;
+    func_info_t *info;
+} func_disp_t;
+
+#define FUNCUNKNOWN(x)  ((IUnknown*) &(x)->lpIUnknownVtbl)
+
 struct dispex_dynamic_data_t {
     DWORD buf_size;
     DWORD prop_cnt;
     dynamic_prop_t *props;
+    func_disp_t **func_disps;
 };
 
 #define DISPID_DYNPROP_0    0x50000000
@@ -188,22 +200,23 @@ void release_typelib(void)
     ITypeLib_Release(typelib);
 }
 
-static void add_func_info(dispex_data_t *data, DWORD *size, tid_t tid, DISPID id, ITypeInfo *dti)
+static void add_func_info(dispex_data_t *data, DWORD *size, tid_t tid, const FUNCDESC *desc, ITypeInfo *dti)
 {
     HRESULT hres;
 
-    if(data->func_cnt && data->funcs[data->func_cnt-1].id == id)
+    if(data->func_cnt && data->funcs[data->func_cnt-1].id == desc->memid)
         return;
 
     if(data->func_cnt == *size)
         data->funcs = heap_realloc(data->funcs, (*size <<= 1)*sizeof(func_info_t));
 
-    hres = ITypeInfo_GetDocumentation(dti, id, &data->funcs[data->func_cnt].name, NULL, NULL, NULL);
+    hres = ITypeInfo_GetDocumentation(dti, desc->memid, &data->funcs[data->func_cnt].name, NULL, NULL, NULL);
     if(FAILED(hres))
         return;
 
-    data->funcs[data->func_cnt].id = id;
+    data->funcs[data->func_cnt].id = desc->memid;
     data->funcs[data->func_cnt].tid = tid;
+    data->funcs[data->func_cnt].func_disp_idx = desc->invkind == INVOKE_FUNC ? data->func_disp_cnt++ : -1;
 
     data->func_cnt++;
 }
@@ -237,6 +250,7 @@ static dispex_data_t *preprocess_dispex_data(DispatchEx *This)
 
     data = heap_alloc(sizeof(dispex_data_t));
     data->func_cnt = 0;
+    data->func_disp_cnt = 0;
     data->funcs = heap_alloc(size*sizeof(func_info_t));
     list_add_tail(&dispex_data_list, &data->entry);
 
@@ -251,7 +265,7 @@ static dispex_data_t *preprocess_dispex_data(DispatchEx *This)
             if(FAILED(hres))
                 break;
 
-            add_func_info(data, &size, *tid, funcdesc->memid, dti);
+            add_func_info(data, &size, *tid, funcdesc, dti);
             ITypeInfo_ReleaseFuncDesc(ti, funcdesc);
         }
 
@@ -457,6 +471,142 @@ static HRESULT typeinfo_invoke(DispatchEx *This, func_info_t *func, WORD flags,
     return hres;
 }
 
+#define FUNCTION_THIS(iface) DEFINE_THIS(func_disp_t, IUnknown, iface)
+
+static HRESULT WINAPI Function_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
+{
+    func_disp_t *This = FUNCTION_THIS(iface);
+
+    if(IsEqualGUID(&IID_IUnknown, riid)) {
+        TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
+        *ppv = FUNCUNKNOWN(This);
+    }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
+        return *ppv ? S_OK : E_NOINTERFACE;
+    }else {
+        *ppv = NULL;
+        return E_NOINTERFACE;
+    }
+
+    IUnknown_AddRef((IUnknown*)*ppv);
+    return S_OK;
+}
+
+static ULONG WINAPI Function_AddRef(IUnknown *iface)
+{
+    func_disp_t *This = FUNCTION_THIS(iface);
+
+    TRACE("(%p)\n", This);
+
+    return IDispatchEx_AddRef(DISPATCHEX(This->obj));
+}
+
+static ULONG WINAPI Function_Release(IUnknown *iface)
+{
+    func_disp_t *This = FUNCTION_THIS(iface);
+
+    TRACE("(%p)\n", This);
+
+    return IDispatchEx_Release(DISPATCHEX(This->obj));
+}
+
+static HRESULT function_value(IUnknown *iface, LCID lcid, WORD flags, DISPPARAMS *params,
+        VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
+{
+    func_disp_t *This = FUNCTION_THIS(iface);
+    HRESULT hres;
+
+    switch(flags) {
+    case DISPATCH_METHOD:
+        hres = typeinfo_invoke(This->obj, This->info, flags, params, res, ei);
+        break;
+    default:
+        FIXME("Unimplemented flags %x\n", flags);
+        hres = E_NOTIMPL;
+    }
+
+    return hres;
+}
+
+#undef FUNCTION_THIS
+
+static const IUnknownVtbl FunctionUnkVtbl = {
+    Function_QueryInterface,
+    Function_AddRef,
+    Function_Release
+};
+
+static const dispex_static_data_vtbl_t function_dispex_vtbl = {
+    function_value,
+    NULL,
+    NULL
+};
+
+static dispex_static_data_t function_dispex = {
+    &function_dispex_vtbl,
+    LAST_tid,
+    NULL,
+    NULL
+};
+
+static func_disp_t *create_func_disp(DispatchEx *obj, func_info_t *info)
+{
+    func_disp_t *ret;
+
+    ret = heap_alloc_zero(sizeof(func_disp_t));
+    if(!ret)
+        return NULL;
+
+    ret->lpIUnknownVtbl = &FunctionUnkVtbl;
+    init_dispex(&ret->dispex, FUNCUNKNOWN(ret),  &function_dispex);
+    ret->obj = obj;
+    ret->info = info;
+
+    return ret;
+}
+
+static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res,
+        EXCEPINFO *ei)
+{
+    HRESULT hres;
+
+    switch(flags) {
+    case DISPATCH_METHOD:
+        hres = typeinfo_invoke(This, func, flags, dp, res, ei);
+        break;
+    case DISPATCH_PROPERTYGET: {
+        dispex_dynamic_data_t *dynamic_data;
+
+        dynamic_data = get_dynamic_data(This, TRUE);
+        if(!dynamic_data)
+            return E_OUTOFMEMORY;
+
+        if(!dynamic_data->func_disps) {
+            dynamic_data->func_disps = heap_alloc_zero(This->data->data->func_disp_cnt * sizeof(func_disp_t*));
+            if(!dynamic_data->func_disps)
+                return E_OUTOFMEMORY;
+        }
+
+        if(!dynamic_data->func_disps[func->func_disp_idx]) {
+            dynamic_data->func_disps[func->func_disp_idx] = create_func_disp(This, func);
+            if(!dynamic_data->func_disps[func->func_disp_idx])
+                return E_OUTOFMEMORY;
+        }
+
+        V_VT(res) = VT_DISPATCH;
+        V_DISPATCH(res) = (IDispatch*)DISPATCHEX(&dynamic_data->func_disps[func->func_disp_idx]->dispex);
+        IDispatch_AddRef(V_DISPATCH(res));
+        hres = S_OK;
+        break;
+    }
+    default:
+        FIXME("Unimplemented flags %x\n", flags);
+    case DISPATCH_PROPERTYPUT:
+        hres = E_NOTIMPL;
+    }
+
+    return hres;
+}
+
 #define DISPATCHEX_THIS(iface) DEFINE_THIS(DispatchEx, IDispatchEx, iface)
 
 static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
@@ -698,7 +848,12 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
         return DISP_E_UNKNOWNNAME;
     }
 
-    return typeinfo_invoke(This, data->funcs+n, wFlags, pdp, pvarRes, pei);
+    if(data->funcs[n].func_disp_idx == -1)
+        hres = typeinfo_invoke(This, data->funcs+n, wFlags, pdp, pvarRes, pei);
+    else
+        hres = function_invoke(This, data->funcs+n, wFlags, pdp, pvarRes, pei);
+
+    return hres;
 }
 
 static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)




More information about the wine-cvs mailing list