diff --git a/dlls/mshtml/nsiface.idl b/dlls/mshtml/nsiface.idl index 9e2e484ed3a..fc00b2531c8 100644 --- a/dlls/mshtml/nsiface.idl +++ b/dlls/mshtml/nsiface.idl @@ -1685,6 +1685,23 @@ interface nsIDOMHTMLObjectElement : nsIDOMHTMLElement nsresult GetContentDocument(nsIDOMDocument **aContentDocument); } +[ + object, + uuid(a6cf90ad-15b3-11d2-932e-00805f8add32), + local +] +interface nsIDOMHTMLParamElement : nsIDOMHTMLElement +{ + nsresult GetName(nsAString *aName); + nsresult SetName(const nsAString *aName); + nsresult GetType(nsAString *aType); + nsresult SetType(const nsAString *aType); + nsresult GetValue(nsAString *aValue); + nsresult SetValue(const nsAString *aValue); + nsresult GetValueType(nsAString *aValueType); + nsresult SetValueType(const nsAString *aValueType); +} + [ object, uuid(94928ab3-8b63-11d3-989d-001083010e9b), diff --git a/dlls/mshtml/pluginhost.c b/dlls/mshtml/pluginhost.c index f58b765cd31..d1932de0315 100644 --- a/dlls/mshtml/pluginhost.c +++ b/dlls/mshtml/pluginhost.c @@ -65,7 +65,7 @@ static void load_prop_bag(PluginHost *host, IPersistPropertyBag *persist_prop_ba IPropertyBag *prop_bag; HRESULT hres; - hres = create_param_prop_bag(&prop_bag); + hres = create_param_prop_bag(host->element->element.nselem, &prop_bag); if(FAILED(hres)) return; diff --git a/dlls/mshtml/pluginhost.h b/dlls/mshtml/pluginhost.h index b9a9c1b36f5..ee1fed64d1d 100644 --- a/dlls/mshtml/pluginhost.h +++ b/dlls/mshtml/pluginhost.h @@ -53,4 +53,4 @@ HRESULT create_plugin_host(HTMLDocumentNode*,nsIDOMElement*,IUnknown*,const CLSI void update_plugin_window(PluginHost*,HWND,const RECT*); void detach_plugin_hosts(HTMLDocumentNode*); -HRESULT create_param_prop_bag(IPropertyBag**); +HRESULT create_param_prop_bag(nsIDOMHTMLElement*,IPropertyBag**); diff --git a/dlls/mshtml/propbag.c b/dlls/mshtml/propbag.c index f52396c0447..e579c6f2f45 100644 --- a/dlls/mshtml/propbag.c +++ b/dlls/mshtml/propbag.c @@ -41,8 +41,62 @@ typedef struct { IPropertyBag2 IPropertyBag2_iface; LONG ref; + + struct list props; } PropertyBag; +typedef struct { + struct list entry; + WCHAR *name; + WCHAR *value; +} param_prop_t; + +static void free_prop(param_prop_t *prop) +{ + list_remove(&prop->entry); + + heap_free(prop->name); + heap_free(prop->value); + heap_free(prop); +} + +static param_prop_t *find_prop(PropertyBag *prop_bag, const WCHAR *name) +{ + param_prop_t *iter; + + LIST_FOR_EACH_ENTRY(iter, &prop_bag->props, param_prop_t, entry) { + if(!strcmpiW(iter->name, name)) + return iter; + } + + return NULL; +} + +static HRESULT add_prop(PropertyBag *prop_bag, const WCHAR *name, const WCHAR *value) +{ + param_prop_t *prop; + + if(!name || !value) + return S_OK; + + TRACE("%p %s %s\n", prop_bag, debugstr_w(name), debugstr_w(value)); + + prop = heap_alloc(sizeof(*prop)); + if(!prop) + return E_OUTOFMEMORY; + + prop->name = heap_strdupW(name); + prop->value = heap_strdupW(value); + if(!prop->name || !prop->value) { + list_init(&prop->entry); + free_prop(prop); + return E_OUTOFMEMORY; + } + + list_add_tail(&prop_bag->props, &prop->entry); + return S_OK; +} + static inline PropertyBag *impl_from_IPropertyBag(IPropertyBag *iface) { return CONTAINING_RECORD(iface, PropertyBag, IPropertyBag_iface); @@ -88,8 +142,11 @@ static ULONG WINAPI PropertyBag_Release(IPropertyBag *iface) TRACE("(%p) ref=%d\n", This, ref); - if(!ref) + if(!ref) { + while(!list_empty(&This->props)) + free_prop(LIST_ENTRY(This->props.next, param_prop_t, entry)); heap_free(This); + } return ref; } @@ -97,8 +154,32 @@ static ULONG WINAPI PropertyBag_Release(IPropertyBag *iface) static HRESULT WINAPI PropertyBag_Read(IPropertyBag *iface, LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog) { PropertyBag *This = impl_from_IPropertyBag(iface); - FIXME("(%p)->(%s %p %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog); - return E_NOTIMPL; + param_prop_t *prop; + VARIANT v; + + TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog); + + prop = find_prop(This, pszPropName); + if(!prop) { + TRACE("Not found\n"); + return E_INVALIDARG; + } + + V_BSTR(&v) = SysAllocString(prop->value); + if(!V_BSTR(&v)) + return E_OUTOFMEMORY; + + if(V_VT(pVar) != VT_BSTR) { + HRESULT hres; + + V_VT(&v) = VT_BSTR; + hres = VariantChangeType(pVar, &v, 0, V_VT(pVar)); + SysFreeString(V_BSTR(&v)); + return hres; + } + + V_BSTR(pVar) = V_BSTR(&v); + return S_OK; } static HRESULT WINAPI PropertyBag_Write(IPropertyBag *iface, LPCOLESTR pszPropName, VARIANT *pVar) @@ -188,9 +269,75 @@ static const IPropertyBag2Vtbl PropertyBag2Vtbl = { PropertyBag2_LoadObject }; -HRESULT create_param_prop_bag(IPropertyBag **ret) +static HRESULT fill_props(nsIDOMHTMLElement *nselem, PropertyBag *prop_bag) +{ + nsIDOMHTMLParamElement *nsparam; + nsAString name_str, value_str; + nsIDOMNodeList *params; + PRUint32 length, i; + nsIDOMNode *nsnode; + nsresult nsres; + HRESULT hres = S_OK; + + static const PRUnichar paramW[] = {'p','a','r','a','m',0}; + + nsAString_InitDepend(&name_str, paramW); + nsres = nsIDOMHTMLElement_GetElementsByTagName(nselem, &name_str, ¶ms); + nsAString_Finish(&name_str); + if(NS_FAILED(nsres)) + return E_FAIL; + + nsres = nsIDOMNodeList_GetLength(params, &length); + if(NS_FAILED(nsres)) + return S_OK; + + for(i=0; i < length; i++) { + nsres = nsIDOMNodeList_Item(params, i, &nsnode); + if(NS_FAILED(nsres)) { + hres = E_FAIL; + break; + } + + nsres = nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMHTMLParamElement, (void**)&nsparam); + nsIDOMNode_Release(nsnode); + if(NS_FAILED(nsres)) { + hres = E_FAIL; + break; + } + + nsAString_Init(&name_str, NULL); + nsres = nsIDOMHTMLParamElement_GetName(nsparam, &name_str); + if(NS_SUCCEEDED(nsres)) { + nsAString_Init(&value_str, NULL); + nsres = nsIDOMHTMLParamElement_GetValue(nsparam, &value_str); + if(NS_SUCCEEDED(nsres)) { + const PRUnichar *name, *value; + + nsAString_GetData(&name_str, &name); + nsAString_GetData(&value_str, &value); + + hres = add_prop(prop_bag, name, value); + } + nsAString_Finish(&value_str); + } + + nsAString_Finish(&name_str); + nsIDOMHTMLParamElement_Release(nsparam); + if(FAILED(hres)) + break; + if(NS_FAILED(nsres)) { + hres = E_FAIL; + break; + } + } + + return hres; +} + +HRESULT create_param_prop_bag(nsIDOMHTMLElement *nselem, IPropertyBag **ret) { PropertyBag *prop_bag; + HRESULT hres; prop_bag = heap_alloc(sizeof(*prop_bag)); if(!prop_bag) @@ -200,6 +347,14 @@ HRESULT create_param_prop_bag(IPropertyBag **ret) prop_bag->IPropertyBag2_iface.lpVtbl = &PropertyBag2Vtbl; prop_bag->ref = 1; + list_init(&prop_bag->props); + hres = fill_props(nselem, prop_bag); + if(FAILED(hres) || list_empty(&prop_bag->props)) { + IPropertyBag_Release(&prop_bag->IPropertyBag_iface); + *ret = NULL; + return hres; + } + *ret = &prop_bag->IPropertyBag_iface; return S_OK; } diff --git a/dlls/mshtml/tests/activex.c b/dlls/mshtml/tests/activex.c index ee921c5aaf8..2229d51735a 100644 --- a/dlls/mshtml/tests/activex.c +++ b/dlls/mshtml/tests/activex.c @@ -74,6 +74,7 @@ static const char object_ax_str[] = "" "" "" + "" "" ""; @@ -134,6 +135,13 @@ static void _test_ifaces(unsigned line, IUnknown *iface, REFIID *iids) } } +static int strcmp_wa(LPCWSTR strw, const char *stra) +{ + CHAR buf[512]; + WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL); + return lstrcmpA(stra, buf); +} + static HRESULT ax_qi(REFIID,void**); static HRESULT WINAPI OleControl_QueryInterface(IOleControl *iface, REFIID riid, void **ppv) @@ -299,6 +307,13 @@ static HRESULT WINAPI PersistPropertyBag_InitNew(IPersistPropertyBag *face) static HRESULT WINAPI PersistPropertyBag_Load(IPersistPropertyBag *face, IPropertyBag *pPropBag, IErrorLog *pErrorLog) { + VARIANT v; + HRESULT hres; + + static const WCHAR param_nameW[] = {'p','a','r','a','m','_','n','a','m','e',0}; + static const WCHAR num_paramW[] = {'n','u','m','_','p','a','r','a','m',0}; + static const WCHAR no_paramW[] = {'n','o','_','p','a','r','a','m',0}; + static const IID *propbag_ifaces[] = { &IID_IPropertyBag, &IID_IPropertyBag2, @@ -312,6 +327,39 @@ static HRESULT WINAPI PersistPropertyBag_Load(IPersistPropertyBag *face, IProper test_ifaces((IUnknown*)pPropBag, propbag_ifaces); + V_VT(&v) = VT_BSTR; + hres = IPropertyBag_Read(pPropBag, param_nameW, &v, NULL); + ok(hres == S_OK, "Read failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "param_value"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + V_VT(&v) = VT_I4; + V_I4(&v) = 0xdeadbeef; + hres = IPropertyBag_Read(pPropBag, param_nameW, &v, NULL); + ok(hres == DISP_E_TYPEMISMATCH, "Read failed: %08x, expected DISP_E_TYPEMISMATCH\n", hres); + ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v)); + ok(V_I4(&v) == 0xdeadbeef, "V_I4(v) = %x\n", V_I4(&v)); + + V_VT(&v) = VT_BSTR; + hres = IPropertyBag_Read(pPropBag, num_paramW, &v, NULL); + ok(hres == S_OK, "Read failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "3"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + V_VT(&v) = VT_I4; + V_I4(&v) = 0xdeadbeef; + hres = IPropertyBag_Read(pPropBag, num_paramW, &v, NULL); + ok(hres == S_OK, "Read failed: %08x\n", hres); + ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v)); + ok(V_I4(&v) == 3, "V_I4(v) = %x\n", V_I4(&v)); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = (BSTR)0xdeadbeef; + hres = IPropertyBag_Read(pPropBag, no_paramW, &v, NULL); + ok(hres == E_INVALIDARG, "Read failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v)); + ok(V_BSTR(&v) == (BSTR)0xdeadbeef, "V_BSTR(v) = %p\n", V_BSTR(&v)); + return S_OK; }