msxml3: Add support for standalone property.
[wine] / dlls / msxml3 / nodelist.c
1 /*
2  *    Node list implementation
3  *
4  * Copyright 2005 Mike McCormack
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #define COBJMACROS
22
23 #include "config.h"
24
25 #include <stdarg.h>
26 #ifdef HAVE_LIBXML2
27 # include <libxml/parser.h>
28 # include <libxml/xmlerror.h>
29 #endif
30
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winuser.h"
34 #include "ole2.h"
35 #include "msxml6.h"
36
37 #include "msxml_private.h"
38
39 #include "wine/debug.h"
40
41 /* This file implements the object returned by childNodes property. Note that this is
42  * not the IXMLDOMNodeList returned by XPath querites - it's implemented in queryresult.c.
43  * They are different because the list returned by childNodes:
44  *  - is "live" - changes to the XML tree are automatically reflected in the list
45  *  - doesn't supports IXMLDOMSelection
46  *  - note that an attribute node have a text child in DOM but not in the XPath data model
47  *    thus the child is inaccessible by an XPath query
48  */
49
50 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
51
52 #ifdef HAVE_LIBXML2
53
54 typedef struct _xmlnodelist
55 {
56     IXMLDOMNodeList IXMLDOMNodeList_iface;
57     LONG ref;
58     xmlNodePtr parent;
59     xmlNodePtr current;
60 } xmlnodelist;
61
62 static inline xmlnodelist *impl_from_IXMLDOMNodeList( IXMLDOMNodeList *iface )
63 {
64     return CONTAINING_RECORD(iface, xmlnodelist, IXMLDOMNodeList_iface);
65 }
66
67 static HRESULT WINAPI xmlnodelist_QueryInterface(
68     IXMLDOMNodeList *iface,
69     REFIID riid,
70     void** ppvObject )
71 {
72     TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject);
73
74     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
75          IsEqualGUID( riid, &IID_IDispatch ) ||
76          IsEqualGUID( riid, &IID_IXMLDOMNodeList ) )
77     {
78         *ppvObject = iface;
79     }
80     else
81     {
82         TRACE("interface %s not implemented\n", debugstr_guid(riid));
83         *ppvObject = NULL;
84         return E_NOINTERFACE;
85     }
86
87     IXMLDOMNodeList_AddRef( iface );
88
89     return S_OK;
90 }
91
92 static ULONG WINAPI xmlnodelist_AddRef(
93     IXMLDOMNodeList *iface )
94 {
95     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
96     ULONG ref = InterlockedIncrement( &This->ref );
97     TRACE("(%p)->(%d)\n", This, ref);
98     return ref;
99 }
100
101 static ULONG WINAPI xmlnodelist_Release(
102     IXMLDOMNodeList *iface )
103 {
104     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
105     ULONG ref = InterlockedDecrement( &This->ref );
106
107     TRACE("(%p)->(%d)\n", This, ref);
108     if ( ref == 0 )
109     {
110         xmldoc_release( This->parent->doc );
111         heap_free( This );
112     }
113
114     return ref;
115 }
116
117 static HRESULT WINAPI xmlnodelist_GetTypeInfoCount(
118     IXMLDOMNodeList *iface,
119     UINT* pctinfo )
120 {
121     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
122
123     TRACE("(%p)->(%p)\n", This, pctinfo);
124
125     *pctinfo = 1;
126
127     return S_OK;
128 }
129
130 static HRESULT WINAPI xmlnodelist_GetTypeInfo(
131     IXMLDOMNodeList *iface,
132     UINT iTInfo,
133     LCID lcid,
134     ITypeInfo** ppTInfo )
135 {
136     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
137     HRESULT hr;
138
139     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
140
141     hr = get_typeinfo(IXMLDOMNodeList_tid, ppTInfo);
142
143     return hr;
144 }
145
146 static HRESULT WINAPI xmlnodelist_GetIDsOfNames(
147     IXMLDOMNodeList *iface,
148     REFIID riid,
149     LPOLESTR* rgszNames,
150     UINT cNames,
151     LCID lcid,
152     DISPID* rgDispId )
153 {
154     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
155     ITypeInfo *typeinfo;
156     HRESULT hr;
157
158     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
159           lcid, rgDispId);
160
161     if(!rgszNames || cNames == 0 || !rgDispId)
162         return E_INVALIDARG;
163
164     hr = get_typeinfo(IXMLDOMNodeList_tid, &typeinfo);
165     if(SUCCEEDED(hr))
166     {
167         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
168         ITypeInfo_Release(typeinfo);
169     }
170
171     return hr;
172 }
173
174 static HRESULT WINAPI xmlnodelist_Invoke(
175     IXMLDOMNodeList *iface,
176     DISPID dispIdMember,
177     REFIID riid,
178     LCID lcid,
179     WORD wFlags,
180     DISPPARAMS* pDispParams,
181     VARIANT* pVarResult,
182     EXCEPINFO* pExcepInfo,
183     UINT* puArgErr )
184 {
185     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
186     ITypeInfo *typeinfo;
187     HRESULT hr;
188
189     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
190           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
191
192     hr = get_typeinfo(IXMLDOMNodeList_tid, &typeinfo);
193     if(SUCCEEDED(hr))
194     {
195         hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMNodeList_iface, dispIdMember, wFlags,
196                 pDispParams, pVarResult, pExcepInfo, puArgErr);
197         ITypeInfo_Release(typeinfo);
198     }
199
200     return hr;
201 }
202
203 static HRESULT WINAPI xmlnodelist_get_item(
204         IXMLDOMNodeList* iface,
205         LONG index,
206         IXMLDOMNode** listItem)
207 {
208     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
209     xmlNodePtr curr;
210     LONG nodeIndex = 0;
211
212     TRACE("(%p)->(%d %p)\n", This, index, listItem);
213
214     if(!listItem)
215         return E_INVALIDARG;
216
217     *listItem = NULL;
218
219     if (index < 0)
220         return S_FALSE;
221
222     curr = This->parent->children;
223     while(curr)
224     {
225         if(nodeIndex++ == index) break;
226         curr = curr->next;
227     }
228     if(!curr) return S_FALSE;
229
230     *listItem = create_node( curr );
231
232     return S_OK;
233 }
234
235 static HRESULT WINAPI xmlnodelist_get_length(
236         IXMLDOMNodeList* iface,
237         LONG* listLength)
238 {
239
240     xmlNodePtr curr;
241     LONG nodeCount = 0;
242
243     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
244
245     TRACE("(%p)->(%p)\n", This, listLength);
246
247     if(!listLength)
248         return E_INVALIDARG;
249
250     curr = This->parent->children;
251     while (curr)
252     {
253         nodeCount++;
254         curr = curr->next;
255     }
256
257     *listLength = nodeCount;
258     return S_OK;
259 }
260
261 static HRESULT WINAPI xmlnodelist_nextNode(
262         IXMLDOMNodeList* iface,
263         IXMLDOMNode** nextItem)
264 {
265     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
266
267     TRACE("(%p)->(%p)\n", This, nextItem );
268
269     if(!nextItem)
270         return E_INVALIDARG;
271
272     *nextItem = NULL;
273
274     if (!This->current)
275         return S_FALSE;
276
277     *nextItem = create_node( This->current );
278     This->current = This->current->next;
279     return S_OK;
280 }
281
282 static HRESULT WINAPI xmlnodelist_reset(
283         IXMLDOMNodeList* iface)
284 {
285     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
286
287     TRACE("%p\n", This);
288     This->current = This->parent->children;
289     return S_OK;
290 }
291
292 static HRESULT WINAPI xmlnodelist__newEnum(
293         IXMLDOMNodeList* iface,
294         IUnknown** ppUnk)
295 {
296     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
297     FIXME("(%p)->(%p)\n", This, ppUnk);
298     return E_NOTIMPL;
299 }
300
301
302 static const struct IXMLDOMNodeListVtbl xmlnodelist_vtbl =
303 {
304     xmlnodelist_QueryInterface,
305     xmlnodelist_AddRef,
306     xmlnodelist_Release,
307     xmlnodelist_GetTypeInfoCount,
308     xmlnodelist_GetTypeInfo,
309     xmlnodelist_GetIDsOfNames,
310     xmlnodelist_Invoke,
311     xmlnodelist_get_item,
312     xmlnodelist_get_length,
313     xmlnodelist_nextNode,
314     xmlnodelist_reset,
315     xmlnodelist__newEnum,
316 };
317
318 IXMLDOMNodeList* create_children_nodelist( xmlNodePtr node )
319 {
320     xmlnodelist *nodelist;
321
322     nodelist = heap_alloc( sizeof *nodelist );
323     if ( !nodelist )
324         return NULL;
325
326     nodelist->IXMLDOMNodeList_iface.lpVtbl = &xmlnodelist_vtbl;
327     nodelist->ref = 1;
328     nodelist->parent = node;
329     nodelist->current = node->children;
330
331     xmldoc_add_ref( node->doc );
332
333     return &nodelist->IXMLDOMNodeList_iface;
334 }
335
336 #endif