kernel32/tests: Get the test to run on Windows 95.
[wine] / dlls / msxml3 / nodemap.c
1 /*
2  *    Node map 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 #include "config.h"
22
23 #define COBJMACROS
24
25 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winnls.h"
30 #include "ole2.h"
31 #include "msxml2.h"
32
33 #include "msxml_private.h"
34
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
38
39 #ifdef HAVE_LIBXML2
40
41 typedef struct _xmlnodemap
42 {
43     const struct IXMLDOMNamedNodeMapVtbl *lpVtbl;
44     const struct ISupportErrorInfoVtbl *lpSEIVtbl;
45     LONG ref;
46     IXMLDOMNode *node;
47     long iterator;
48 } xmlnodemap;
49
50 static inline xmlnodemap *impl_from_IXMLDOMNamedNodeMap( IXMLDOMNamedNodeMap *iface )
51 {
52     return (xmlnodemap *)((char*)iface - FIELD_OFFSET(xmlnodemap, lpVtbl));
53 }
54
55 static inline xmlnodemap *impl_from_ISupportErrorInfo( ISupportErrorInfo *iface )
56 {
57     return (xmlnodemap *)((char*)iface - FIELD_OFFSET(xmlnodemap, lpSEIVtbl));
58 }
59
60 static HRESULT WINAPI xmlnodemap_QueryInterface(
61     IXMLDOMNamedNodeMap *iface,
62     REFIID riid, void** ppvObject )
63 {
64     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
65     TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
66
67     if( IsEqualGUID( riid, &IID_IUnknown ) ||
68         IsEqualGUID( riid, &IID_IDispatch ) ||
69         IsEqualGUID( riid, &IID_IXMLDOMNamedNodeMap ) )
70     {
71         *ppvObject = iface;
72     }
73     else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
74     {
75         *ppvObject = &This->lpSEIVtbl;
76     }
77     else
78     {
79         FIXME("interface %s not implemented\n", debugstr_guid(riid));
80         return E_NOINTERFACE;
81     }
82
83     IXMLDOMElement_AddRef( iface );
84
85     return S_OK;
86 }
87
88 static ULONG WINAPI xmlnodemap_AddRef(
89     IXMLDOMNamedNodeMap *iface )
90 {
91     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
92     return InterlockedIncrement( &This->ref );
93 }
94
95 static ULONG WINAPI xmlnodemap_Release(
96     IXMLDOMNamedNodeMap *iface )
97 {
98     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
99     ULONG ref;
100
101     ref = InterlockedDecrement( &This->ref );
102     if ( ref == 0 )
103     {
104         IXMLDOMNode_Release( This->node );
105         HeapFree( GetProcessHeap(), 0, This );
106     }
107
108     return ref;
109 }
110
111 static HRESULT WINAPI xmlnodemap_GetTypeInfoCount(
112     IXMLDOMNamedNodeMap *iface,
113     UINT* pctinfo )
114 {
115     FIXME("\n");
116     return E_NOTIMPL;
117 }
118
119 static HRESULT WINAPI xmlnodemap_GetTypeInfo(
120     IXMLDOMNamedNodeMap *iface,
121     UINT iTInfo, LCID lcid,
122     ITypeInfo** ppTInfo )
123 {
124     FIXME("\n");
125     return E_NOTIMPL;
126 }
127
128 static HRESULT WINAPI xmlnodemap_GetIDsOfNames(
129     IXMLDOMNamedNodeMap *iface,
130     REFIID riid, LPOLESTR* rgszNames,
131     UINT cNames, LCID lcid, DISPID* rgDispId )
132 {
133     FIXME("\n");
134     return E_NOTIMPL;
135 }
136
137 static HRESULT WINAPI xmlnodemap_Invoke(
138     IXMLDOMNamedNodeMap *iface,
139     DISPID dispIdMember, REFIID riid, LCID lcid,
140     WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
141     EXCEPINFO* pExcepInfo, UINT* puArgErr )
142 {
143     FIXME("\n");
144     return E_NOTIMPL;
145 }
146
147 xmlChar *xmlChar_from_wchar( LPWSTR str )
148 {
149     DWORD len;
150     xmlChar *xmlstr;
151
152     len = WideCharToMultiByte( CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL );
153     xmlstr = HeapAlloc( GetProcessHeap(), 0, len );
154     if ( xmlstr )
155         WideCharToMultiByte( CP_UTF8, 0, str, -1, (LPSTR) xmlstr, len, NULL, NULL );
156     return xmlstr;
157 }
158
159 static HRESULT WINAPI xmlnodemap_getNamedItem(
160     IXMLDOMNamedNodeMap *iface,
161     BSTR name,
162     IXMLDOMNode** namedItem)
163 {
164     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
165     xmlChar *element_name;
166     xmlAttrPtr attr;
167     xmlNodePtr node;
168
169     TRACE("%p %s %p\n", This, debugstr_w(name), namedItem );
170
171     if ( !namedItem )
172         return E_INVALIDARG;
173
174     node = xmlNodePtr_from_domnode( This->node, 0 );
175     if ( !node )
176         return E_FAIL;
177
178     element_name = xmlChar_from_wchar( name );
179     attr = xmlHasNsProp( node, element_name, NULL );
180     HeapFree( GetProcessHeap(), 0, element_name );
181
182     if ( !attr )
183     {
184         *namedItem = NULL;
185         return S_FALSE;
186     }
187
188     *namedItem = create_node( (xmlNodePtr) attr );
189
190     return S_OK;
191 }
192
193 static HRESULT WINAPI xmlnodemap_setNamedItem(
194     IXMLDOMNamedNodeMap *iface,
195     IXMLDOMNode* newItem,
196     IXMLDOMNode** namedItem)
197 {
198     FIXME("\n");
199     return E_NOTIMPL;
200 }
201
202 static HRESULT WINAPI xmlnodemap_removeNamedItem(
203     IXMLDOMNamedNodeMap *iface,
204     BSTR name,
205     IXMLDOMNode** namedItem)
206 {
207     FIXME("\n");
208     return E_NOTIMPL;
209 }
210
211 static HRESULT WINAPI xmlnodemap_get_item(
212     IXMLDOMNamedNodeMap *iface,
213     long index,
214     IXMLDOMNode** listItem)
215 {
216     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
217     xmlNodePtr node;
218     xmlAttrPtr curr;
219     long attrIndex;
220
221     TRACE("%p %ld\n", This, index);
222
223     *listItem = NULL;
224
225     if (index < 0)
226         return S_FALSE;
227
228     node = xmlNodePtr_from_domnode( This->node, 0 );
229     curr = node->properties;
230
231     for (attrIndex = 0; attrIndex < index; attrIndex++) {
232         if (curr->next == NULL)
233             return S_FALSE;
234         else
235             curr = curr->next;
236     }
237     
238     *listItem = create_node( (xmlNodePtr) curr );
239
240     return S_OK;
241 }
242
243 static HRESULT WINAPI xmlnodemap_get_length(
244     IXMLDOMNamedNodeMap *iface,
245     long* listLength)
246 {
247     xmlNodePtr node;
248     xmlAttrPtr first;
249     xmlAttrPtr curr;
250     long attrCount;
251
252     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
253
254     TRACE("%p\n", This);
255
256     node = xmlNodePtr_from_domnode( This->node, 0 );
257     if ( !node )
258         return E_FAIL;
259
260     first = node->properties;
261     if (first == NULL) {
262         *listLength = 0;
263         return S_OK;
264     }
265
266     curr = first;
267     attrCount = 1;
268     while (curr->next != NULL) {
269         attrCount++;
270         curr = curr->next;
271     }
272     *listLength = attrCount;
273  
274     return S_OK;
275 }
276
277 static HRESULT WINAPI xmlnodemap_getQualifiedItem(
278     IXMLDOMNamedNodeMap *iface,
279     BSTR baseName,
280     BSTR namespaceURI,
281     IXMLDOMNode** qualifiedItem)
282 {
283     FIXME("\n");
284     return E_NOTIMPL;
285 }
286
287 static HRESULT WINAPI xmlnodemap_removeQualifiedItem(
288     IXMLDOMNamedNodeMap *iface,
289     BSTR baseName,
290     BSTR namespaceURI,
291     IXMLDOMNode** qualifiedItem)
292 {
293     FIXME("\n");
294     return E_NOTIMPL;
295 }
296
297 static HRESULT WINAPI xmlnodemap_nextNode(
298     IXMLDOMNamedNodeMap *iface,
299     IXMLDOMNode** nextItem)
300 {
301     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
302     xmlNodePtr node;
303     xmlAttrPtr curr;
304     long attrIndex;
305
306     TRACE("%p %ld\n", This, This->iterator);
307
308     *nextItem = NULL;
309
310     node = xmlNodePtr_from_domnode( This->node, 0 );
311     curr = node->properties;
312
313     for (attrIndex = 0; attrIndex < This->iterator; attrIndex++) {
314         if (curr->next == NULL)
315             return S_FALSE;
316         else
317             curr = curr->next;
318     }
319
320     This->iterator++;
321
322     *nextItem = create_node( (xmlNodePtr) curr );
323
324     return S_OK;
325 }
326
327 static HRESULT WINAPI xmlnodemap_reset(
328     IXMLDOMNamedNodeMap *iface )
329 {
330     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
331
332     TRACE("%p %ld\n", This, This->iterator);
333
334     This->iterator = 0;
335
336     return S_OK;
337 }
338
339 static HRESULT WINAPI xmlnodemap__newEnum(
340     IXMLDOMNamedNodeMap *iface,
341     IUnknown** ppUnk)
342 {
343     FIXME("\n");
344     return E_NOTIMPL;
345 }
346
347 static const struct IXMLDOMNamedNodeMapVtbl xmlnodemap_vtbl =
348 {
349     xmlnodemap_QueryInterface,
350     xmlnodemap_AddRef,
351     xmlnodemap_Release,
352     xmlnodemap_GetTypeInfoCount,
353     xmlnodemap_GetTypeInfo,
354     xmlnodemap_GetIDsOfNames,
355     xmlnodemap_Invoke,
356     xmlnodemap_getNamedItem,
357     xmlnodemap_setNamedItem,
358     xmlnodemap_removeNamedItem,
359     xmlnodemap_get_item,
360     xmlnodemap_get_length,
361     xmlnodemap_getQualifiedItem,
362     xmlnodemap_removeQualifiedItem,
363     xmlnodemap_nextNode,
364     xmlnodemap_reset,
365     xmlnodemap__newEnum,
366 };
367
368 static HRESULT WINAPI support_error_QueryInterface(
369     ISupportErrorInfo *iface,
370     REFIID riid, void** ppvObject )
371 {
372     xmlnodemap *This = impl_from_ISupportErrorInfo( iface );
373     TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
374
375     return IXMLDOMNamedNodeMap_QueryInterface((IXMLDOMNamedNodeMap*)&This->lpVtbl, riid, ppvObject);
376 }
377
378 static ULONG WINAPI support_error_AddRef(
379     ISupportErrorInfo *iface )
380 {
381     xmlnodemap *This = impl_from_ISupportErrorInfo( iface );
382     return IXMLDOMNamedNodeMap_AddRef((IXMLDOMNamedNodeMap*)&This->lpVtbl);
383 }
384
385 static ULONG WINAPI support_error_Release(
386     ISupportErrorInfo *iface )
387 {
388     xmlnodemap *This = impl_from_ISupportErrorInfo( iface );
389     return IXMLDOMNamedNodeMap_Release((IXMLDOMNamedNodeMap*)&This->lpVtbl);
390 }
391
392 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
393     ISupportErrorInfo *iface,
394     REFIID riid )
395 {
396     FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
397     return S_FALSE;
398 }
399
400 static const struct ISupportErrorInfoVtbl support_error_vtbl =
401 {
402     support_error_QueryInterface,
403     support_error_AddRef,
404     support_error_Release,
405     support_error_InterfaceSupportsErrorInfo
406 };
407
408 IXMLDOMNamedNodeMap *create_nodemap( IXMLDOMNode *node )
409 {
410     xmlnodemap *nodemap;
411
412     nodemap = HeapAlloc( GetProcessHeap(), 0, sizeof *nodemap );
413     if ( !nodemap )
414         return NULL;
415
416     nodemap->lpVtbl = &xmlnodemap_vtbl;
417     nodemap->lpSEIVtbl = &support_error_vtbl;
418     nodemap->node = node;
419     nodemap->ref = 1;
420     nodemap->iterator = 0;
421
422     IXMLDOMNode_AddRef( node );
423     /* Since we AddRef a node here, we don't need to call xmldoc_add_ref() */
424
425     return (IXMLDOMNamedNodeMap*) &nodemap->lpVtbl;
426 }
427
428 #endif