explorer: Use root window if driver doesn't implement create_desktop.
[wine.git] / dlls / msxml3 / nodelist.c
blobfd3d30a2e0283efaa5cfdef98924f42c403f9fea
1 /*
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
21 #define COBJMACROS
23 #include <stdarg.h>
24 #include <libxml/parser.h>
25 #include <libxml/xmlerror.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "ole2.h"
31 #include "msxml6.h"
32 #include "msxml2did.h"
34 #include "msxml_private.h"
36 #include "wine/debug.h"
38 /* This file implements the object returned by childNodes property. Note that this is
39 * not the IXMLDOMNodeList returned by XPath queries - it's implemented in selection.c.
40 * They are different because the list returned by childNodes:
41 * - is "live" - changes to the XML tree are automatically reflected in the list
42 * - doesn't supports IXMLDOMSelection
43 * - note that an attribute node have a text child in DOM but not in the XPath data model
44 * thus the child is inaccessible by an XPath query
47 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
49 typedef struct
51 DispatchEx dispex;
52 IXMLDOMNodeList IXMLDOMNodeList_iface;
53 LONG ref;
54 xmlNodePtr parent;
55 xmlNodePtr current;
56 IEnumVARIANT *enumvariant;
57 } xmlnodelist;
59 static HRESULT nodelist_get_item(IUnknown *iface, LONG index, VARIANT *item)
61 V_VT(item) = VT_DISPATCH;
62 return IXMLDOMNodeList_get_item((IXMLDOMNodeList*)iface, index, (IXMLDOMNode**)&V_DISPATCH(item));
65 static const struct enumvariant_funcs nodelist_enumvariant = {
66 nodelist_get_item,
67 NULL
70 static inline xmlnodelist *impl_from_IXMLDOMNodeList( IXMLDOMNodeList *iface )
72 return CONTAINING_RECORD(iface, xmlnodelist, IXMLDOMNodeList_iface);
75 static HRESULT WINAPI xmlnodelist_QueryInterface(
76 IXMLDOMNodeList *iface,
77 REFIID riid,
78 void** ppvObject )
80 xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
82 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
84 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
85 IsEqualGUID( riid, &IID_IDispatch ) ||
86 IsEqualGUID( riid, &IID_IXMLDOMNodeList ) )
88 *ppvObject = iface;
90 else if (IsEqualGUID( riid, &IID_IEnumVARIANT ))
92 if (!This->enumvariant)
94 HRESULT hr = create_enumvariant((IUnknown*)iface, FALSE, &nodelist_enumvariant, &This->enumvariant);
95 if (FAILED(hr)) return hr;
98 return IEnumVARIANT_QueryInterface(This->enumvariant, &IID_IEnumVARIANT, ppvObject);
100 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
102 return *ppvObject ? S_OK : E_NOINTERFACE;
104 else
106 TRACE("interface %s not implemented\n", debugstr_guid(riid));
107 *ppvObject = NULL;
108 return E_NOINTERFACE;
111 IXMLDOMNodeList_AddRef( iface );
113 return S_OK;
116 static ULONG WINAPI xmlnodelist_AddRef(
117 IXMLDOMNodeList *iface )
119 xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
120 ULONG ref = InterlockedIncrement( &This->ref );
121 TRACE("%p, refcount %lu.\n", iface, ref);
122 return ref;
125 static ULONG WINAPI xmlnodelist_Release(
126 IXMLDOMNodeList *iface )
128 xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
129 ULONG ref = InterlockedDecrement( &This->ref );
131 TRACE("%p, refcount %lu.\n", iface, ref);
133 if (!ref)
135 xmldoc_release( This->parent->doc );
136 if (This->enumvariant) IEnumVARIANT_Release(This->enumvariant);
137 heap_free( This );
140 return ref;
143 static HRESULT WINAPI xmlnodelist_GetTypeInfoCount(
144 IXMLDOMNodeList *iface,
145 UINT* pctinfo )
147 xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
148 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
151 static HRESULT WINAPI xmlnodelist_GetTypeInfo(
152 IXMLDOMNodeList *iface,
153 UINT iTInfo,
154 LCID lcid,
155 ITypeInfo** ppTInfo )
157 xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
158 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
159 iTInfo, lcid, ppTInfo);
162 static HRESULT WINAPI xmlnodelist_GetIDsOfNames(
163 IXMLDOMNodeList *iface,
164 REFIID riid,
165 LPOLESTR* rgszNames,
166 UINT cNames,
167 LCID lcid,
168 DISPID* rgDispId )
170 xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
171 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
172 riid, rgszNames, cNames, lcid, rgDispId);
175 static HRESULT WINAPI xmlnodelist_Invoke(
176 IXMLDOMNodeList *iface,
177 DISPID dispIdMember,
178 REFIID riid,
179 LCID lcid,
180 WORD wFlags,
181 DISPPARAMS* pDispParams,
182 VARIANT* pVarResult,
183 EXCEPINFO* pExcepInfo,
184 UINT* puArgErr )
186 xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
187 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
188 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
191 static HRESULT WINAPI xmlnodelist_get_item(
192 IXMLDOMNodeList* iface,
193 LONG index,
194 IXMLDOMNode** listItem)
196 xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
197 xmlNodePtr curr;
198 LONG nodeIndex = 0;
200 TRACE("%p, %ld, %p.\n", iface, index, listItem);
202 if(!listItem)
203 return E_INVALIDARG;
205 *listItem = NULL;
207 if (index < 0)
208 return S_FALSE;
210 curr = This->parent->children;
211 while(curr)
213 if(nodeIndex++ == index) break;
214 curr = curr->next;
216 if(!curr) return S_FALSE;
218 *listItem = create_node( curr );
220 return S_OK;
223 static HRESULT WINAPI xmlnodelist_get_length(
224 IXMLDOMNodeList* iface,
225 LONG* listLength)
228 xmlNodePtr curr;
229 LONG nodeCount = 0;
231 xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
233 TRACE("(%p)->(%p)\n", This, listLength);
235 if(!listLength)
236 return E_INVALIDARG;
238 curr = This->parent->children;
239 while (curr)
241 nodeCount++;
242 curr = curr->next;
245 *listLength = nodeCount;
246 return S_OK;
249 static HRESULT WINAPI xmlnodelist_nextNode(
250 IXMLDOMNodeList* iface,
251 IXMLDOMNode** nextItem)
253 xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
255 TRACE("(%p)->(%p)\n", This, nextItem );
257 if(!nextItem)
258 return E_INVALIDARG;
260 *nextItem = NULL;
262 if (!This->current)
263 return S_FALSE;
265 *nextItem = create_node( This->current );
266 This->current = This->current->next;
267 return S_OK;
270 static HRESULT WINAPI xmlnodelist_reset(
271 IXMLDOMNodeList* iface)
273 xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
275 TRACE("%p\n", This);
276 This->current = This->parent->children;
277 return S_OK;
280 static HRESULT WINAPI xmlnodelist__newEnum(
281 IXMLDOMNodeList* iface,
282 IUnknown** enumv)
284 xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
285 TRACE("(%p)->(%p)\n", This, enumv);
286 return create_enumvariant((IUnknown*)iface, TRUE, &nodelist_enumvariant, (IEnumVARIANT**)enumv);
289 static const struct IXMLDOMNodeListVtbl xmlnodelist_vtbl =
291 xmlnodelist_QueryInterface,
292 xmlnodelist_AddRef,
293 xmlnodelist_Release,
294 xmlnodelist_GetTypeInfoCount,
295 xmlnodelist_GetTypeInfo,
296 xmlnodelist_GetIDsOfNames,
297 xmlnodelist_Invoke,
298 xmlnodelist_get_item,
299 xmlnodelist_get_length,
300 xmlnodelist_nextNode,
301 xmlnodelist_reset,
302 xmlnodelist__newEnum,
305 static HRESULT xmlnodelist_get_dispid(IUnknown *iface, BSTR name, DWORD flags, DISPID *dispid)
307 WCHAR *ptr;
308 int idx = 0;
310 for(ptr = name; *ptr >= '0' && *ptr <= '9'; ptr++)
311 idx = idx*10 + (*ptr-'0');
312 if(*ptr)
313 return DISP_E_UNKNOWNNAME;
315 *dispid = DISPID_DOM_COLLECTION_BASE + idx;
316 TRACE("ret %lx\n", *dispid);
317 return S_OK;
320 static HRESULT xmlnodelist_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
321 VARIANT *res, EXCEPINFO *ei)
323 xmlnodelist *This = impl_from_IXMLDOMNodeList( (IXMLDOMNodeList*)iface );
325 TRACE("%p, %ld, %lx, %x, %p, %p, %p.\n", iface, id, lcid, flags, params, res, ei);
327 if (id >= DISPID_DOM_COLLECTION_BASE && id <= DISPID_DOM_COLLECTION_MAX)
329 switch(flags)
331 case DISPATCH_PROPERTYGET:
333 IXMLDOMNode *disp = NULL;
335 V_VT(res) = VT_DISPATCH;
336 IXMLDOMNodeList_get_item(&This->IXMLDOMNodeList_iface, id - DISPID_DOM_COLLECTION_BASE, &disp);
337 V_DISPATCH(res) = (IDispatch*)disp;
338 break;
340 default:
342 FIXME("unimplemented flags %x\n", flags);
343 break;
347 else if (id == DISPID_VALUE)
349 switch(flags)
351 case DISPATCH_METHOD|DISPATCH_PROPERTYGET:
352 case DISPATCH_PROPERTYGET:
353 case DISPATCH_METHOD:
355 IXMLDOMNode *item;
356 VARIANT index;
357 HRESULT hr;
359 if (params->cArgs - params->cNamedArgs != 1) return DISP_E_BADPARAMCOUNT;
361 VariantInit(&index);
362 hr = VariantChangeType(&index, params->rgvarg, 0, VT_I4);
363 if(FAILED(hr))
365 FIXME("failed to convert arg, %s\n", debugstr_variant(params->rgvarg));
366 return hr;
369 IXMLDOMNodeList_get_item(&This->IXMLDOMNodeList_iface, V_I4(&index), &item);
370 V_VT(res) = VT_DISPATCH;
371 V_DISPATCH(res) = (IDispatch*)item;
372 break;
374 default:
376 FIXME("DISPID_VALUE: unimplemented flags %x\n", flags);
377 break;
381 else
382 return DISP_E_UNKNOWNNAME;
384 TRACE("ret %p\n", V_DISPATCH(res));
386 return S_OK;
389 static const dispex_static_data_vtbl_t xmlnodelist_dispex_vtbl = {
390 xmlnodelist_get_dispid,
391 xmlnodelist_invoke
394 static const tid_t xmlnodelist_iface_tids[] = {
395 IXMLDOMNodeList_tid,
398 static dispex_static_data_t xmlnodelist_dispex = {
399 &xmlnodelist_dispex_vtbl,
400 IXMLDOMNodeList_tid,
401 NULL,
402 xmlnodelist_iface_tids
405 IXMLDOMNodeList* create_children_nodelist( xmlNodePtr node )
407 xmlnodelist *This;
409 This = heap_alloc( sizeof *This );
410 if ( !This )
411 return NULL;
413 This->IXMLDOMNodeList_iface.lpVtbl = &xmlnodelist_vtbl;
414 This->ref = 1;
415 This->parent = node;
416 This->current = node->children;
417 This->enumvariant = NULL;
418 xmldoc_add_ref( node->doc );
420 init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMNodeList_iface, &xmlnodelist_dispex);
422 return &This->IXMLDOMNodeList_iface;