sync mshtml to wine 1.1.33
[reactos.git] / reactos / dll / win32 / mshtml / dispex.c
index 4092374..980b13b 100644 (file)
@@ -73,6 +73,8 @@ struct dispex_dynamic_data_t {
 #define DISPID_DYNPROP_0    0x50000000
 #define DISPID_DYNPROP_MAX  0x5fffffff
 
+#define FDEX_VERSION_MASK 0xf0000000
+
 static ITypeLib *typelib;
 static ITypeInfo *typeinfos[LAST_tid];
 static struct list dispex_data_list = LIST_INIT(dispex_data_list);
@@ -123,8 +125,10 @@ static REFIID tid_ids[] = {
     &IID_IHTMLElement4,
     &IID_IHTMLElementCollection,
     &IID_IHTMLEventObj,
+    &IID_IHTMLFrameBase,
     &IID_IHTMLFrameBase2,
     &IID_IHTMLGenericElement,
+    &IID_IHTMLImageElementFactory,
     &IID_IHTMLImgElement,
     &IID_IHTMLInputElement,
     &IID_IHTMLLocation,
@@ -220,7 +224,7 @@ static void add_func_info(dispex_data_t *data, DWORD *size, tid_t tid, const FUN
 
     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->funcs[data->func_cnt].func_disp_idx = (desc->invkind & DISPATCH_METHOD) ? data->func_disp_cnt++ : -1;
 
     data->func_cnt++;
 }
@@ -364,11 +368,13 @@ static inline dispex_dynamic_data_t *get_dynamic_data(DispatchEx *This, BOOL all
         : (This->dynamic_data = heap_alloc_zero(sizeof(dispex_dynamic_data_t)));
 }
 
-static HRESULT get_dynamic_prop(DispatchEx *This, const WCHAR *name, BOOL alloc, dynamic_prop_t **ret)
+static HRESULT get_dynamic_prop(DispatchEx *This, const WCHAR *name, DWORD flags, dynamic_prop_t **ret)
 {
-    dispex_dynamic_data_t *data = get_dynamic_data(This, alloc);
+    const BOOL alloc = flags & fdexNameEnsure;
+    dispex_dynamic_data_t *data;
     unsigned i;
 
+    data = get_dynamic_data(This, alloc);
     if(!data) {
         if(alloc)
             return E_OUTOFMEMORY;
@@ -378,12 +384,15 @@ static HRESULT get_dynamic_prop(DispatchEx *This, const WCHAR *name, BOOL alloc,
     }
 
     for(i=0; i < data->prop_cnt; i++) {
-        if(!strcmpW(data->props[i].name, name)) {
+        if(flags & fdexNameCaseInsensitive ? !strcmpiW(data->props[i].name, name) : !strcmpW(data->props[i].name, name)) {
             *ret = data->props+i;
             return S_OK;
         }
     }
 
+    if(!alloc)
+        return DISP_E_UNKNOWNNAME;
+
     TRACE("creating dynamic prop %s\n", debugstr_w(name));
 
     if(!data->buf_size) {
@@ -414,7 +423,7 @@ HRESULT dispex_get_dprop_ref(DispatchEx *This, const WCHAR *name, BOOL alloc, VA
     dynamic_prop_t *prop;
     HRESULT hres;
 
-    hres = get_dynamic_prop(This, name, alloc, &prop);
+    hres = get_dynamic_prop(This, name, alloc ? fdexNameEnsure : 0, &prop);
     if(FAILED(hres))
         return hres;
 
@@ -514,6 +523,9 @@ static HRESULT function_value(IUnknown *iface, LCID lcid, WORD flags, DISPPARAMS
     HRESULT hres;
 
     switch(flags) {
+    case DISPATCH_METHOD|DISPATCH_PROPERTYGET:
+        if(!res)
+            return E_INVALIDARG;
     case DISPATCH_METHOD:
         hres = typeinfo_invoke(This->obj, This->info, flags, params, res, ei);
         break;
@@ -570,6 +582,9 @@ static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags,
     HRESULT hres;
 
     switch(flags) {
+    case DISPATCH_METHOD|DISPATCH_PROPERTYGET:
+        if(!res)
+            return E_INVALIDARG;
     case DISPATCH_METHOD:
         hres = typeinfo_invoke(This, func, flags, dp, res, ei);
         break;
@@ -736,7 +751,7 @@ static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DW
 
     TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid);
 
-    if(grfdex & ~(fdexNameCaseSensitive|fdexNameEnsure|fdexNameImplicit))
+    if(grfdex & ~(fdexNameCaseSensitive|fdexNameCaseInsensitive|fdexNameEnsure|fdexNameImplicit|FDEX_VERSION_MASK))
         FIXME("Unsupported grfdex %x\n", grfdex);
 
     data = get_dispex_data(This);
@@ -772,7 +787,7 @@ static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DW
             return hres;
     }
 
-    hres = get_dynamic_prop(This, bstrName, grfdex&fdexNameEnsure, &dprop);
+    hres = get_dynamic_prop(This, bstrName, grfdex, &dprop);
     if(FAILED(hres))
         return hres;
 
@@ -794,8 +809,16 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
         return This->data->vtbl->invoke(This->outer, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
 
     if(wFlags == DISPATCH_CONSTRUCT) {
-        FIXME("DISPATCH_CONSTRUCT not implemented\n");
-        return E_NOTIMPL;
+        if(id == DISPID_VALUE) {
+            if(This->data->vtbl && This->data->vtbl->value) {
+                return This->data->vtbl->value(This->outer, lcid, wFlags, pdp,
+                        pvarRes, pei, pspCaller);
+            }
+            FIXME("DISPATCH_CONSTRUCT flag but missing value function\n");
+            return E_FAIL;
+        }
+        FIXME("DISPATCH_CONSTRUCT flag without DISPID_VALUE\n");
+        return E_FAIL;
     }
 
     if(is_dynamic_dispid(id)) {
@@ -808,7 +831,10 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
         var = &This->dynamic_data->props[idx].var;
 
         switch(wFlags) {
-        case INVOKE_FUNC: {
+        case DISPATCH_METHOD|DISPATCH_PROPERTYGET:
+            if(!pvarRes)
+                return E_INVALIDARG;
+        case DISPATCH_METHOD: {
             DISPID named_arg = DISPID_THIS;
             DISPPARAMS dp = {NULL, &named_arg, 0, 1};
             IDispatchEx *dispex;
@@ -847,9 +873,17 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
             heap_free(dp.rgvarg);
             return hres;
         }
-        case INVOKE_PROPERTYGET:
+        case DISPATCH_PROPERTYGET:
             return VariantCopy(pvarRes, var);
-        case INVOKE_PROPERTYPUT:
+        case DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF:
+        case DISPATCH_PROPERTYPUT:
+            if(pdp->cArgs != 1 || (pdp->cNamedArgs == 1 && *pdp->rgdispidNamedArgs != DISPID_PROPERTYPUT)
+               || pdp->cNamedArgs > 1) {
+                FIXME("invalid args\n");
+                return E_INVALIDARG;
+            }
+
+            TRACE("put %s\n", debugstr_variant(pdp->rgvarg));
             VariantClear(var);
             return VariantCopy(var, pdp->rgvarg);
         default: