2 * Node list implementation
4 * Copyright 2005 Mike McCormack
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include <msxml2did.h>
25 /* This file implements the object returned by childNodes property. Note that this is
26 * not the IXMLDOMNodeList returned by XPath queries - it's implemented in selection.c.
27 * They are different because the list returned by childNodes:
28 * - is "live" - changes to the XML tree are automatically reflected in the list
29 * - doesn't supports IXMLDOMSelection
30 * - note that an attribute node have a text child in DOM but not in the XPath data model
31 * thus the child is inaccessible by an XPath query
39 IXMLDOMNodeList IXMLDOMNodeList_iface
;
43 IEnumVARIANT
*enumvariant
;
46 static HRESULT
nodelist_get_item(IUnknown
*iface
, LONG index
, VARIANT
*item
)
48 V_VT(item
) = VT_DISPATCH
;
49 return IXMLDOMNodeList_get_item((IXMLDOMNodeList
*)iface
, index
, (IXMLDOMNode
**)&V_DISPATCH(item
));
52 static const struct enumvariant_funcs nodelist_enumvariant
= {
57 static inline xmlnodelist
*impl_from_IXMLDOMNodeList( IXMLDOMNodeList
*iface
)
59 return CONTAINING_RECORD(iface
, xmlnodelist
, IXMLDOMNodeList_iface
);
62 static HRESULT WINAPI
xmlnodelist_QueryInterface(
63 IXMLDOMNodeList
*iface
,
67 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
69 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
74 /* NOTE: Interface documentation for IUnknown explicitly states
75 * this case should return E_POINTER. Empirical data proves
76 * MS violates this contract and instead return E_INVALIDARG.
82 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
83 IsEqualGUID( riid
, &IID_IDispatch
) ||
84 IsEqualGUID( riid
, &IID_IXMLDOMNodeList
) )
88 else if (IsEqualGUID( riid
, &IID_IEnumVARIANT
))
90 if (!This
->enumvariant
)
92 HRESULT hr
= create_enumvariant((IUnknown
*)iface
, FALSE
, &nodelist_enumvariant
, &This
->enumvariant
);
93 if (FAILED(hr
)) return hr
;
96 return IEnumVARIANT_QueryInterface(This
->enumvariant
, &IID_IEnumVARIANT
, ppvObject
);
98 else if (dispex_query_interface(&This
->dispex
, riid
, ppvObject
))
100 return *ppvObject
? S_OK
: E_NOINTERFACE
;
104 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
106 return E_NOINTERFACE
;
109 IXMLDOMNodeList_AddRef( iface
);
114 static ULONG WINAPI
xmlnodelist_AddRef(
115 IXMLDOMNodeList
*iface
)
117 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
118 ULONG ref
= InterlockedIncrement( &This
->ref
);
119 TRACE("(%p)->(%d)\n", This
, ref
);
123 static ULONG WINAPI
xmlnodelist_Release(
124 IXMLDOMNodeList
*iface
)
126 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
127 ULONG ref
= InterlockedDecrement( &This
->ref
);
129 TRACE("(%p)->(%d)\n", This
, ref
);
132 xmldoc_release( This
->parent
->doc
);
133 if (This
->enumvariant
) IEnumVARIANT_Release(This
->enumvariant
);
140 static HRESULT WINAPI
xmlnodelist_GetTypeInfoCount(
141 IXMLDOMNodeList
*iface
,
144 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
145 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
148 static HRESULT WINAPI
xmlnodelist_GetTypeInfo(
149 IXMLDOMNodeList
*iface
,
152 ITypeInfo
** ppTInfo
)
154 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
155 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
,
156 iTInfo
, lcid
, ppTInfo
);
159 static HRESULT WINAPI
xmlnodelist_GetIDsOfNames(
160 IXMLDOMNodeList
*iface
,
167 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
168 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
,
169 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
172 static HRESULT WINAPI
xmlnodelist_Invoke(
173 IXMLDOMNodeList
*iface
,
178 DISPPARAMS
* pDispParams
,
180 EXCEPINFO
* pExcepInfo
,
183 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
184 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
,
185 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
188 static HRESULT WINAPI
xmlnodelist_get_item(
189 IXMLDOMNodeList
* iface
,
191 IXMLDOMNode
** listItem
)
193 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
197 TRACE("(%p)->(%d %p)\n", This
, index
, listItem
);
207 curr
= This
->parent
->children
;
210 if(nodeIndex
++ == index
) break;
213 if(!curr
) return S_FALSE
;
215 *listItem
= create_node( curr
);
220 static HRESULT WINAPI
xmlnodelist_get_length(
221 IXMLDOMNodeList
* iface
,
228 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
230 TRACE("(%p)->(%p)\n", This
, listLength
);
235 curr
= This
->parent
->children
;
242 *listLength
= nodeCount
;
246 static HRESULT WINAPI
xmlnodelist_nextNode(
247 IXMLDOMNodeList
* iface
,
248 IXMLDOMNode
** nextItem
)
250 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
252 TRACE("(%p)->(%p)\n", This
, nextItem
);
262 *nextItem
= create_node( This
->current
);
263 This
->current
= This
->current
->next
;
267 static HRESULT WINAPI
xmlnodelist_reset(
268 IXMLDOMNodeList
* iface
)
270 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
273 This
->current
= This
->parent
->children
;
277 static HRESULT WINAPI
xmlnodelist__newEnum(
278 IXMLDOMNodeList
* iface
,
281 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( iface
);
282 TRACE("(%p)->(%p)\n", This
, enumv
);
283 return create_enumvariant((IUnknown
*)iface
, TRUE
, &nodelist_enumvariant
, (IEnumVARIANT
**)enumv
);
286 static const struct IXMLDOMNodeListVtbl xmlnodelist_vtbl
=
288 xmlnodelist_QueryInterface
,
291 xmlnodelist_GetTypeInfoCount
,
292 xmlnodelist_GetTypeInfo
,
293 xmlnodelist_GetIDsOfNames
,
295 xmlnodelist_get_item
,
296 xmlnodelist_get_length
,
297 xmlnodelist_nextNode
,
299 xmlnodelist__newEnum
,
302 static HRESULT
xmlnodelist_get_dispid(IUnknown
*iface
, BSTR name
, DWORD flags
, DISPID
*dispid
)
307 for(ptr
= name
; *ptr
&& isdigitW(*ptr
); ptr
++)
308 idx
= idx
*10 + (*ptr
-'0');
310 return DISP_E_UNKNOWNNAME
;
312 *dispid
= DISPID_DOM_COLLECTION_BASE
+ idx
;
313 TRACE("ret %x\n", *dispid
);
317 static HRESULT
xmlnodelist_invoke(IUnknown
*iface
, DISPID id
, LCID lcid
, WORD flags
, DISPPARAMS
*params
,
318 VARIANT
*res
, EXCEPINFO
*ei
)
320 xmlnodelist
*This
= impl_from_IXMLDOMNodeList( (IXMLDOMNodeList
*)iface
);
322 TRACE("(%p)->(%x %x %x %p %p %p)\n", This
, id
, lcid
, flags
, params
, res
, ei
);
324 if (id
>= DISPID_DOM_COLLECTION_BASE
&& id
<= DISPID_DOM_COLLECTION_MAX
)
328 case DISPATCH_PROPERTYGET
:
330 IXMLDOMNode
*disp
= NULL
;
332 V_VT(res
) = VT_DISPATCH
;
333 IXMLDOMNodeList_get_item(&This
->IXMLDOMNodeList_iface
, id
- DISPID_DOM_COLLECTION_BASE
, &disp
);
334 V_DISPATCH(res
) = (IDispatch
*)disp
;
339 FIXME("unimplemented flags %x\n", flags
);
344 else if (id
== DISPID_VALUE
)
348 case DISPATCH_METHOD
|DISPATCH_PROPERTYGET
:
349 case DISPATCH_PROPERTYGET
:
350 case DISPATCH_METHOD
:
356 if (params
->cArgs
- params
->cNamedArgs
!= 1) return DISP_E_BADPARAMCOUNT
;
359 hr
= VariantChangeType(&index
, params
->rgvarg
, 0, VT_I4
);
362 FIXME("failed to convert arg, %s\n", debugstr_variant(params
->rgvarg
));
366 IXMLDOMNodeList_get_item(&This
->IXMLDOMNodeList_iface
, V_I4(&index
), &item
);
367 V_VT(res
) = VT_DISPATCH
;
368 V_DISPATCH(res
) = (IDispatch
*)item
;
373 FIXME("DISPID_VALUE: unimplemented flags %x\n", flags
);
379 return DISP_E_UNKNOWNNAME
;
381 TRACE("ret %p\n", V_DISPATCH(res
));
386 static const dispex_static_data_vtbl_t xmlnodelist_dispex_vtbl
= {
387 xmlnodelist_get_dispid
,
391 static const tid_t xmlnodelist_iface_tids
[] = {
395 static dispex_static_data_t xmlnodelist_dispex
= {
396 &xmlnodelist_dispex_vtbl
,
399 xmlnodelist_iface_tids
402 IXMLDOMNodeList
* create_children_nodelist( xmlNodePtr node
)
406 This
= heap_alloc( sizeof *This
);
410 This
->IXMLDOMNodeList_iface
.lpVtbl
= &xmlnodelist_vtbl
;
413 This
->current
= node
->children
;
414 This
->enumvariant
= NULL
;
415 xmldoc_add_ref( node
->doc
);
417 init_dispex(&This
->dispex
, (IUnknown
*)&This
->IXMLDOMNodeList_iface
, &xmlnodelist_dispex
);
419 return &This
->IXMLDOMNodeList_iface
;