urlmon: Don't create stgmed_obj for binding to object.
[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     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
199     xmlnode *ThisNew = NULL;
200     xmlNodePtr nodeNew;
201     IXMLDOMNode *pAttr = NULL;
202     xmlNodePtr node;
203
204     TRACE("%p %p %p\n", This, newItem, namedItem );
205
206     if(!newItem)
207         return E_INVALIDARG;
208
209     if(namedItem) *namedItem = NULL;
210
211     node = xmlNodePtr_from_domnode( This->node, 0 );
212     if ( !node )
213         return E_FAIL;
214
215     /* Must be an Attribute */
216     IUnknown_QueryInterface(newItem, &IID_IXMLDOMNode, (LPVOID*)&pAttr);
217     if(pAttr)
218     {
219         ThisNew = impl_from_IXMLDOMNode( pAttr );
220
221         if(ThisNew->node->type != XML_ATTRIBUTE_NODE)
222         {
223             IUnknown_Release(pAttr);
224             return E_FAIL;
225         }
226
227         nodeNew = xmlAddChild(node, ThisNew->node);
228
229         if(namedItem)
230             *namedItem = create_node( nodeNew );
231
232         IUnknown_Release(pAttr);
233
234         return S_OK;
235     }
236
237     return E_INVALIDARG;
238 }
239
240 static HRESULT WINAPI xmlnodemap_removeNamedItem(
241     IXMLDOMNamedNodeMap *iface,
242     BSTR name,
243     IXMLDOMNode** namedItem)
244 {
245     FIXME("\n");
246     return E_NOTIMPL;
247 }
248
249 static HRESULT WINAPI xmlnodemap_get_item(
250     IXMLDOMNamedNodeMap *iface,
251     long index,
252     IXMLDOMNode** listItem)
253 {
254     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
255     xmlNodePtr node;
256     xmlAttrPtr curr;
257     long attrIndex;
258
259     TRACE("%p %ld\n", This, index);
260
261     *listItem = NULL;
262
263     if (index < 0)
264         return S_FALSE;
265
266     node = xmlNodePtr_from_domnode( This->node, 0 );
267     curr = node->properties;
268
269     for (attrIndex = 0; attrIndex < index; attrIndex++) {
270         if (curr->next == NULL)
271             return S_FALSE;
272         else
273             curr = curr->next;
274     }
275     
276     *listItem = create_node( (xmlNodePtr) curr );
277
278     return S_OK;
279 }
280
281 static HRESULT WINAPI xmlnodemap_get_length(
282     IXMLDOMNamedNodeMap *iface,
283     long* listLength)
284 {
285     xmlNodePtr node;
286     xmlAttrPtr first;
287     xmlAttrPtr curr;
288     long attrCount;
289
290     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
291
292     TRACE("%p\n", This);
293
294     node = xmlNodePtr_from_domnode( This->node, 0 );
295     if ( !node )
296         return E_FAIL;
297
298     first = node->properties;
299     if (first == NULL) {
300         *listLength = 0;
301         return S_OK;
302     }
303
304     curr = first;
305     attrCount = 1;
306     while (curr->next != NULL) {
307         attrCount++;
308         curr = curr->next;
309     }
310     *listLength = attrCount;
311  
312     return S_OK;
313 }
314
315 static HRESULT WINAPI xmlnodemap_getQualifiedItem(
316     IXMLDOMNamedNodeMap *iface,
317     BSTR baseName,
318     BSTR namespaceURI,
319     IXMLDOMNode** qualifiedItem)
320 {
321     FIXME("\n");
322     return E_NOTIMPL;
323 }
324
325 static HRESULT WINAPI xmlnodemap_removeQualifiedItem(
326     IXMLDOMNamedNodeMap *iface,
327     BSTR baseName,
328     BSTR namespaceURI,
329     IXMLDOMNode** qualifiedItem)
330 {
331     FIXME("\n");
332     return E_NOTIMPL;
333 }
334
335 static HRESULT WINAPI xmlnodemap_nextNode(
336     IXMLDOMNamedNodeMap *iface,
337     IXMLDOMNode** nextItem)
338 {
339     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
340     xmlNodePtr node;
341     xmlAttrPtr curr;
342     long attrIndex;
343
344     TRACE("%p %ld\n", This, This->iterator);
345
346     *nextItem = NULL;
347
348     node = xmlNodePtr_from_domnode( This->node, 0 );
349     curr = node->properties;
350
351     for (attrIndex = 0; attrIndex < This->iterator; attrIndex++) {
352         if (curr->next == NULL)
353             return S_FALSE;
354         else
355             curr = curr->next;
356     }
357
358     This->iterator++;
359
360     *nextItem = create_node( (xmlNodePtr) curr );
361
362     return S_OK;
363 }
364
365 static HRESULT WINAPI xmlnodemap_reset(
366     IXMLDOMNamedNodeMap *iface )
367 {
368     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
369
370     TRACE("%p %ld\n", This, This->iterator);
371
372     This->iterator = 0;
373
374     return S_OK;
375 }
376
377 static HRESULT WINAPI xmlnodemap__newEnum(
378     IXMLDOMNamedNodeMap *iface,
379     IUnknown** ppUnk)
380 {
381     FIXME("\n");
382     return E_NOTIMPL;
383 }
384
385 static const struct IXMLDOMNamedNodeMapVtbl xmlnodemap_vtbl =
386 {
387     xmlnodemap_QueryInterface,
388     xmlnodemap_AddRef,
389     xmlnodemap_Release,
390     xmlnodemap_GetTypeInfoCount,
391     xmlnodemap_GetTypeInfo,
392     xmlnodemap_GetIDsOfNames,
393     xmlnodemap_Invoke,
394     xmlnodemap_getNamedItem,
395     xmlnodemap_setNamedItem,
396     xmlnodemap_removeNamedItem,
397     xmlnodemap_get_item,
398     xmlnodemap_get_length,
399     xmlnodemap_getQualifiedItem,
400     xmlnodemap_removeQualifiedItem,
401     xmlnodemap_nextNode,
402     xmlnodemap_reset,
403     xmlnodemap__newEnum,
404 };
405
406 static HRESULT WINAPI support_error_QueryInterface(
407     ISupportErrorInfo *iface,
408     REFIID riid, void** ppvObject )
409 {
410     xmlnodemap *This = impl_from_ISupportErrorInfo( iface );
411     TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
412
413     return IXMLDOMNamedNodeMap_QueryInterface((IXMLDOMNamedNodeMap*)&This->lpVtbl, riid, ppvObject);
414 }
415
416 static ULONG WINAPI support_error_AddRef(
417     ISupportErrorInfo *iface )
418 {
419     xmlnodemap *This = impl_from_ISupportErrorInfo( iface );
420     return IXMLDOMNamedNodeMap_AddRef((IXMLDOMNamedNodeMap*)&This->lpVtbl);
421 }
422
423 static ULONG WINAPI support_error_Release(
424     ISupportErrorInfo *iface )
425 {
426     xmlnodemap *This = impl_from_ISupportErrorInfo( iface );
427     return IXMLDOMNamedNodeMap_Release((IXMLDOMNamedNodeMap*)&This->lpVtbl);
428 }
429
430 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
431     ISupportErrorInfo *iface,
432     REFIID riid )
433 {
434     FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
435     return S_FALSE;
436 }
437
438 static const struct ISupportErrorInfoVtbl support_error_vtbl =
439 {
440     support_error_QueryInterface,
441     support_error_AddRef,
442     support_error_Release,
443     support_error_InterfaceSupportsErrorInfo
444 };
445
446 IXMLDOMNamedNodeMap *create_nodemap( IXMLDOMNode *node )
447 {
448     xmlnodemap *nodemap;
449
450     nodemap = HeapAlloc( GetProcessHeap(), 0, sizeof *nodemap );
451     if ( !nodemap )
452         return NULL;
453
454     nodemap->lpVtbl = &xmlnodemap_vtbl;
455     nodemap->lpSEIVtbl = &support_error_vtbl;
456     nodemap->node = node;
457     nodemap->ref = 1;
458     nodemap->iterator = 0;
459
460     IXMLDOMNode_AddRef( node );
461     /* Since we AddRef a node here, we don't need to call xmldoc_add_ref() */
462
463     return (IXMLDOMNamedNodeMap*) &nodemap->lpVtbl;
464 }
465
466 #endif