[PATCH 08/11] mshtml: Allow retrieving the builtin methods for the function objects.

Gabriel Ivăncescu gabrielopcode at gmail.com
Mon Sep 20 09:46:14 CDT 2021


For document modes <= IE8, native allows to retrieve the semi-implemented
builtin methods, and then use them to retrieve their value props (and
string) or the other props (which always return undefined), but it doesn't
allow calling them or otherwise doing anything else with them anymore
(e.g. chaining them like f.call.call). This implements it the same way with
the same limitations.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---

Tests follow.

 dlls/mshtml/dispex.c | 35 +++++++++++++++++++++++++++++++----
 1 file changed, 31 insertions(+), 4 deletions(-)

diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c
index 01c5656..2f3ca0b 100644
--- a/dlls/mshtml/dispex.c
+++ b/dlls/mshtml/dispex.c
@@ -91,7 +91,10 @@ typedef struct {
     DispatchEx dispex;
     IUnknown IUnknown_iface;
     LONG ref;
-    DispatchEx *obj;
+    union {
+        DispatchEx *obj;
+        DWORD idx;        /* index into function_props, used when info == NULL */
+    };
     func_info_t *info;
 } func_disp_t;
 
@@ -126,6 +129,8 @@ PRIVATE_TID_LIST
 #undef XDIID
 };
 
+static func_disp_t *create_func_disp(DispatchEx*,func_info_t*);
+
 static HRESULT load_typelib(void)
 {
     WCHAR module_path[MAX_PATH + 3];
@@ -816,7 +821,7 @@ static ULONG WINAPI Function_Release(IUnknown *iface)
     TRACE("(%p) ref=%d\n", This, ref);
 
     if(!ref) {
-        assert(!This->obj);
+        assert(!This->info || !This->obj);
         release_dispex(&This->dispex);
         heap_free(This);
     }
@@ -954,6 +959,8 @@ static HRESULT function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
             return E_INVALIDARG;
         /* fall through */
     case DISPATCH_METHOD:
+        if(!This->info)
+            return JS_E_INVALID_PROPERTY;
         if(!This->obj)
             return E_UNEXPECTED;
         hres = typeinfo_invoke(This->obj, This->info, flags, params, res, ei);
@@ -972,7 +979,7 @@ static HRESULT function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
         if(!caller)
             return E_ACCESSDENIED;
 
-        name_len = SysStringLen(This->info->name);
+        name_len = This->info ? SysStringLen(This->info->name) : wcslen(function_props[This->idx].name);
         ptr = str = SysAllocStringLen(NULL, name_len + ARRAY_SIZE(func_prefixW) + ARRAY_SIZE(func_suffixW));
         if(!str)
             return E_OUTOFMEMORY;
@@ -980,7 +987,7 @@ static HRESULT function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
         memcpy(ptr, func_prefixW, sizeof(func_prefixW));
         ptr += ARRAY_SIZE(func_prefixW);
 
-        memcpy(ptr, This->info->name, name_len*sizeof(WCHAR));
+        memcpy(ptr, This->info ? This->info->name : function_props[This->idx].name, name_len*sizeof(WCHAR));
         ptr += name_len;
 
         memcpy(ptr, func_suffixW, sizeof(func_suffixW));
@@ -999,12 +1006,18 @@ static HRESULT function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
 
 static HRESULT function_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid)
 {
+    func_disp_t *This = impl_from_DispatchEx(dispex);
     DWORD i;
 
     for(i = 0; i < ARRAY_SIZE(function_props); i++) {
         if(!wcsicmp(name, function_props[i].name)) {
             if((flags & fdexNameCaseSensitive) && wcscmp(name, function_props[i].name))
                 return DISP_E_UNKNOWNNAME;
+
+            /* methods (apply, call) can't be chained */
+            if(!This->info && function_props[i].method)
+                return DISP_E_UNKNOWNNAME;
+
             *dispid = MSHTML_DISPID_CUSTOM_MIN + i;
             return S_OK;
         }
@@ -1021,6 +1034,10 @@ static HRESULT function_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD fl
     if(idx >= ARRAY_SIZE(function_props))
         return DISP_E_UNKNOWNNAME;
 
+    /* methods (apply, call) can't be chained */
+    if(!This->info && function_props[idx].method)
+        return DISP_E_UNKNOWNNAME;
+
     switch(flags) {
     case DISPATCH_METHOD|DISPATCH_PROPERTYGET:
         if(!res)
@@ -1031,6 +1048,16 @@ static HRESULT function_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD fl
             return function_props[idx].method(This, params, res, ei);
         return JS_E_INVALID_PROPERTY;
     case DISPATCH_PROPERTYGET:
+        if(function_props[idx].method) {
+            func_disp_t *disp = create_func_disp(dispex, NULL);
+            if(!disp)
+                return E_OUTOFMEMORY;
+            disp->idx = idx;
+
+            V_VT(res) = VT_DISPATCH;
+            V_DISPATCH(res) = (IDispatch*)&disp->dispex.IDispatchEx_iface;
+            break;
+        }
         V_VT(res) = VT_EMPTY;  /* IE returns undefined */
         break;
     default:
-- 
2.31.1




More information about the wine-devel mailing list