diff --git a/dlls/mshtml/htmlnode.c b/dlls/mshtml/htmlnode.c index 68865082eb3..bfa999f0daf 100644 --- a/dlls/mshtml/htmlnode.c +++ b/dlls/mshtml/htmlnode.c @@ -180,6 +180,58 @@ static HRESULT WINAPI HTMLDOMChildrenCollection_item(IHTMLDOMChildrenCollection return S_OK; } +#define DISPID_CHILDCOL_0 MSHTML_DISPID_CUSTOM_MIN + +static HRESULT HTMLDOMChildrenCollection_get_dispid(IUnknown *iface, BSTR name, DWORD flags, DISPID *dispid) +{ + HTMLDOMChildrenCollection *This = HTMLCHILDCOL_THIS(iface); + WCHAR *ptr; + DWORD idx=0; + PRUint32 len = 0; + + for(ptr = name; *ptr && isdigitW(*ptr); ptr++) + idx = idx*10 + (*ptr-'0'); + if(*ptr) + return DISP_E_UNKNOWNNAME; + + nsIDOMNodeList_GetLength(This->nslist, &len); + if(idx >= len) + return DISP_E_UNKNOWNNAME; + + *dispid = DISPID_CHILDCOL_0 + idx; + TRACE("ret %x\n", *dispid); + return S_OK; +} + +static HRESULT HTMLDOMChildrenCollection_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) +{ + HTMLDOMChildrenCollection *This = HTMLCHILDCOL_THIS(iface); + + TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller); + + switch(flags) { + case INVOKE_PROPERTYGET: { + IDispatch *disp = NULL; + HRESULT hres; + + hres = IHTMLDOMChildrenCollection_item(HTMLCHILDCOL(This), id - DISPID_CHILDCOL_0, &disp); + if(0&&FAILED(hres)) + return hres; + + V_VT(res) = VT_DISPATCH; + V_DISPATCH(res) = disp; + break; + } + + default: + FIXME("unimplemented flags %x\n", flags); + return E_NOTIMPL; + } + + return S_OK; +} + #undef HTMLCHILDCOL_THIS static const IHTMLDOMChildrenCollectionVtbl HTMLDOMChildrenCollectionVtbl = { @@ -199,8 +251,14 @@ static const tid_t HTMLDOMChildrenCollection_iface_tids[] = { IHTMLDOMChildrenCollection_tid, 0 }; + +static const dispex_static_data_vtbl_t HTMLDOMChildrenCollection_dispex_vtbl = { + HTMLDOMChildrenCollection_get_dispid, + HTMLDOMChildrenCollection_invoke +}; + static dispex_static_data_t HTMLDOMChildrenCollection_dispex = { - NULL, + &HTMLDOMChildrenCollection_dispex_vtbl, DispDOMChildrenCollection_tid, NULL, HTMLDOMChildrenCollection_iface_tids @@ -374,11 +432,11 @@ static HRESULT WINAPI HTMLDOMNode_insertBefore(IHTMLDOMNode *iface, IHTMLDOMNode return E_NOTIMPL; } -static HRESULT WINAPI HTMLDOMNode_removeChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild, +static HRESULT WINAPI HTMLDOMNode_removeChild(IHTMLDOMNode *iface, IHTMLDOMNode *oldChild, IHTMLDOMNode **node) { HTMLDOMNode *This = HTMLDOMNODE_THIS(iface); - FIXME("(%p)->(%p %p)\n", This, newChild, node); + FIXME("(%p)->(%p %p)\n", This, oldChild, node); return E_NOTIMPL; } @@ -548,8 +606,19 @@ static HRESULT WINAPI HTMLDOMNode_get_firstChild(IHTMLDOMNode *iface, IHTMLDOMNo static HRESULT WINAPI HTMLDOMNode_get_lastChild(IHTMLDOMNode *iface, IHTMLDOMNode **p) { HTMLDOMNode *This = HTMLDOMNODE_THIS(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + nsIDOMNode *nschild = NULL; + + TRACE("(%p)->(%p)\n", This, p); + + nsIDOMNode_GetLastChild(This->nsnode, &nschild); + if(nschild) { + *p = HTMLDOMNODE(get_node(This->doc, nschild, TRUE)); + IHTMLDOMNode_AddRef(*p); + }else { + *p = NULL; + } + + return S_OK; } static HRESULT WINAPI HTMLDOMNode_get_previousSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p) diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index ae8f6de20fd..7d57b2476d5 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -1792,6 +1792,50 @@ static void test_stylesheets(IHTMLDocument2 *doc) IHTMLStyleSheetsCollection_Release(col); } +static void test_child_col_disp(IHTMLDOMChildrenCollection *col) +{ + IDispatchEx *dispex; + IHTMLDOMNode *node; + DISPPARAMS dp = {NULL, NULL, 0, 0}; + VARIANT var; + EXCEPINFO ei; + long type; + DISPID id; + BSTR bstr; + HRESULT hres; + + static const WCHAR w0[] = {'0',0}; + static const WCHAR w100[] = {'1','0','0',0}; + + hres = IHTMLDOMChildrenCollection_QueryInterface(col, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "Could not get IDispatchEx: %08x\n", hres); + + bstr = SysAllocString(w0); + hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &id); + ok(hres == S_OK, "GetDispID failed: %08x\n", hres); + SysFreeString(bstr); + + VariantInit(&var); + hres = IDispatchEx_InvokeEx(dispex, id, LOCALE_NEUTRAL, INVOKE_PROPERTYGET, &dp, &var, &ei, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&var) == VT_DISPATCH, "V_VT(var)=%d\n", V_VT(&var)); + ok(V_DISPATCH(&var) != NULL, "V_DISPATCH(var) == NULL\n"); + node = get_node_iface((IUnknown*)V_DISPATCH(&var)); + type = get_node_type((IUnknown*)node); + ok(type == 3, "type=%ld\n", type); + IHTMLDOMNode_Release(node); + VariantClear(&var); + + bstr = SysAllocString(w100); + hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &id); + ok(hres == DISP_E_UNKNOWNNAME, "GetDispID failed: %08x, expected DISP_E_UNKNOWNNAME\n", hres); + SysFreeString(bstr); + + IDispatchEx_Release(dispex); +} + + + static void test_elems(IHTMLDocument2 *doc) { IHTMLElementCollection *col; @@ -1998,6 +2042,8 @@ static void test_elems(IHTMLDocument2 *doc) ok(hres == E_INVALIDARG, "item failed: %08x, expected E_INVALIDARG\n", hres); ok(disp == (void*)0xdeadbeef, "disp=%p\n", disp); + test_child_col_disp(child_col); + IHTMLDOMChildrenCollection_Release(child_col); }