Implement CryptImport/ExportPublicKeyInfo.
[wine] / dlls / msxml3 / node.c
1 /*
2  *    Node implementation
3  *
4  * Copyright 2005 Mike McCormack
5  *
6  * iface 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  * iface 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #define COBJMACROS
24
25 #include <stdarg.h>
26 #include <assert.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winnls.h"
31 #include "ole2.h"
32 #include "ocidl.h"
33 #include "msxml.h"
34 #include "xmldom.h"
35 #include "msxml.h"
36
37 #include "msxml_private.h"
38
39 #include "wine/debug.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
42
43 #ifdef HAVE_LIBXML2
44
45 typedef struct _xmlnode
46 {
47     const struct IXMLDOMNodeVtbl *lpVtbl;
48     LONG ref;
49     xmlNodePtr node;
50 } xmlnode;
51
52 static inline xmlnode *impl_from_IXMLDOMNode( IXMLDOMNode *iface )
53 {
54     return (xmlnode *)((char*)iface - FIELD_OFFSET(xmlnode, lpVtbl));
55 }
56
57 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type )
58 {
59     xmlnode *This;
60
61     if ( !iface )
62         return NULL;
63     This = impl_from_IXMLDOMNode( iface );
64     if ( !This->node )
65         return NULL;
66     if ( type && This->node->type != type )
67         return NULL;
68     return This->node;
69 }
70
71 static HRESULT WINAPI xmlnode_QueryInterface(
72     IXMLDOMNode *iface,
73     REFIID riid,
74     void** ppvObject )
75 {
76     TRACE("%p %p %p\n", iface, debugstr_guid(riid), ppvObject);
77
78     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
79          IsEqualGUID( riid, &IID_IDispatch ) ||
80          IsEqualGUID( riid, &IID_IXMLDOMNode ) )
81     {
82         *ppvObject = iface;
83     }
84     else
85         return E_NOINTERFACE;
86
87     IXMLDOMElement_AddRef( iface );
88
89     return S_OK;
90 }
91
92 static ULONG WINAPI xmlnode_AddRef(
93     IXMLDOMNode *iface )
94 {
95     xmlnode *This = impl_from_IXMLDOMNode( iface );
96     return InterlockedIncrement( &This->ref );
97 }
98
99 static ULONG WINAPI xmlnode_Release(
100     IXMLDOMNode *iface )
101 {
102     xmlnode *This = impl_from_IXMLDOMNode( iface );
103     ULONG ref;
104
105     ref = InterlockedDecrement( &This->ref );
106     if ( ref == 0 )
107     {
108         if( This->node->type == XML_DOCUMENT_NODE )
109         {
110             xmlFreeDoc( (xmlDocPtr) This->node );
111         }
112         else
113         {
114             IXMLDOMNode *root;
115             assert( This->node->doc );
116             root = This->node->doc->_private;
117             assert( root );
118             IXMLDOMNode_Release( root );
119             This->node->_private = NULL;
120         }
121         HeapFree( GetProcessHeap(), 0, This );
122     }
123
124     return ref;
125 }
126
127 static HRESULT WINAPI xmlnode_GetTypeInfoCount(
128     IXMLDOMNode *iface,
129     UINT* pctinfo )
130 {
131     FIXME("\n");
132     return E_NOTIMPL;
133 }
134
135 static HRESULT WINAPI xmlnode_GetTypeInfo(
136     IXMLDOMNode *iface,
137     UINT iTInfo,
138     LCID lcid,
139     ITypeInfo** ppTInfo )
140 {
141     FIXME("\n");
142     return E_NOTIMPL;
143 }
144
145 static HRESULT WINAPI xmlnode_GetIDsOfNames(
146     IXMLDOMNode *iface,
147     REFIID riid,
148     LPOLESTR* rgszNames,
149     UINT cNames,
150     LCID lcid,
151     DISPID* rgDispId )
152 {
153     FIXME("\n");
154     return E_NOTIMPL;
155 }
156
157 static HRESULT WINAPI xmlnode_Invoke(
158     IXMLDOMNode *iface,
159     DISPID dispIdMember,
160     REFIID riid,
161     LCID lcid,
162     WORD wFlags,
163     DISPPARAMS* pDispParams,
164     VARIANT* pVarResult,
165     EXCEPINFO* pExcepInfo,
166     UINT* puArgErr )
167 {
168     FIXME("\n");
169     return E_NOTIMPL;
170 }
171
172 static HRESULT WINAPI xmlnode_get_nodeName(
173     IXMLDOMNode *iface,
174     BSTR* name)
175 {
176     FIXME("\n");
177     return E_NOTIMPL;
178 }
179
180 BSTR bstr_from_xmlChar( const xmlChar *buf )
181 {
182     DWORD len;
183     LPWSTR str;
184     BSTR bstr;
185
186     if ( !buf )
187         return NULL;
188
189     len = MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) buf, -1, NULL, 0 );
190     str = (LPWSTR) HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
191     if ( !str )
192         return NULL;
193     MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) buf, -1, str, len );
194     bstr = SysAllocString( str );
195     HeapFree( GetProcessHeap(), 0, str );
196     return bstr;
197 }
198
199 static HRESULT WINAPI xmlnode_get_nodeValue(
200     IXMLDOMNode *iface,
201     VARIANT* value)
202 {
203     xmlnode *This = impl_from_IXMLDOMNode( iface );
204     HRESULT r = S_FALSE;
205
206     TRACE("%p %p\n", This, value);
207
208     V_BSTR(value) = NULL;
209     V_VT(value) = VT_NULL;
210
211     switch ( This->node->type )
212     {
213     case XML_ATTRIBUTE_NODE:
214         V_VT(value) = VT_BSTR;
215         V_BSTR(value) = bstr_from_xmlChar( This->node->name );
216         r = S_OK;
217         break;
218     case XML_TEXT_NODE:
219         V_VT(value) = VT_BSTR;
220         V_BSTR(value) = bstr_from_xmlChar( This->node->content );
221         r = S_OK;
222         break;
223     case XML_ELEMENT_NODE:
224     case XML_DOCUMENT_NODE:
225         /* these seem to return NULL */
226         break;
227     case XML_PI_NODE:
228     default:
229         FIXME("node %p type %d\n", This, This->node->type);
230     }
231  
232     TRACE("%p returned %s\n", This, debugstr_w( V_BSTR(value) ) );
233
234     return r;
235 }
236
237 static HRESULT WINAPI xmlnode_put_nodeValue(
238     IXMLDOMNode *iface,
239     VARIANT value)
240 {
241     FIXME("\n");
242     return E_NOTIMPL;
243 }
244
245 static HRESULT WINAPI xmlnode_get_nodeType(
246     IXMLDOMNode *iface,
247     DOMNodeType* type)
248 {
249     xmlnode *This = impl_from_IXMLDOMNode( iface );
250
251     TRACE("%p %p\n", This, type);
252
253     assert( NODE_ELEMENT == XML_ELEMENT_NODE );
254     assert( NODE_NOTATION == XML_NOTATION_NODE );
255
256     *type = This->node->type;
257
258     return S_OK;
259 }
260
261 static HRESULT get_node(
262     xmlnode *This,
263     const char *name,
264     xmlNodePtr node,
265     IXMLDOMNode **out )
266 {
267     TRACE("%p->%s %p\n", This, name, node );
268
269     if ( !out )
270         return E_INVALIDARG;
271     *out = create_node( node );
272     if (!*out)
273         return S_FALSE;
274     return S_OK;
275 }
276
277 static HRESULT WINAPI xmlnode_get_parentNode(
278     IXMLDOMNode *iface,
279     IXMLDOMNode** parent)
280 {
281     xmlnode *This = impl_from_IXMLDOMNode( iface );
282     return get_node( This, "parent", This->node->parent, parent );
283 }
284
285 static HRESULT WINAPI xmlnode_get_childNodes(
286     IXMLDOMNode *iface,
287     IXMLDOMNodeList** childList)
288 {
289     xmlnode *This = impl_from_IXMLDOMNode( iface );
290
291     TRACE("%p %p\n", This, childList );
292
293     if ( !childList )
294         return E_INVALIDARG;
295     *childList = create_nodelist( This->node->children );
296     if (!*childList)
297         return S_FALSE;
298     return S_OK;
299 }
300
301 static HRESULT WINAPI xmlnode_get_firstChild(
302     IXMLDOMNode *iface,
303     IXMLDOMNode** firstChild)
304 {
305     xmlnode *This = impl_from_IXMLDOMNode( iface );
306     return get_node( This, "firstChild", This->node->children, firstChild );
307 }
308
309 static HRESULT WINAPI xmlnode_get_lastChild(
310     IXMLDOMNode *iface,
311     IXMLDOMNode** lastChild)
312 {
313     xmlnode *This = impl_from_IXMLDOMNode( iface );
314     return get_node( This, "lastChild", This->node->last, lastChild );
315 }
316
317 static HRESULT WINAPI xmlnode_get_previousSibling(
318     IXMLDOMNode *iface,
319     IXMLDOMNode** previousSibling)
320 {
321     xmlnode *This = impl_from_IXMLDOMNode( iface );
322     return get_node( This, "previous", This->node->prev, previousSibling );
323 }
324
325 static HRESULT WINAPI xmlnode_get_nextSibling(
326     IXMLDOMNode *iface,
327     IXMLDOMNode** nextSibling)
328 {
329     xmlnode *This = impl_from_IXMLDOMNode( iface );
330     return get_node( This, "next", This->node->next, nextSibling );
331 }
332
333 static HRESULT WINAPI xmlnode_get_attributes(
334     IXMLDOMNode *iface,
335     IXMLDOMNamedNodeMap** attributeMap)
336 {
337     xmlnode *This = impl_from_IXMLDOMNode( iface );
338     TRACE("%p\n", This);
339     *attributeMap = create_nodemap( iface );
340     return S_OK;
341 }
342
343 static HRESULT WINAPI xmlnode_insertBefore(
344     IXMLDOMNode *iface,
345     IXMLDOMNode* newChild,
346     VARIANT refChild,
347     IXMLDOMNode** outNewChild)
348 {
349     FIXME("\n");
350     return E_NOTIMPL;
351 }
352
353 static HRESULT WINAPI xmlnode_replaceChild(
354     IXMLDOMNode *iface,
355     IXMLDOMNode* newChild,
356     IXMLDOMNode* oldChild,
357     IXMLDOMNode** outOldChild)
358 {
359     FIXME("\n");
360     return E_NOTIMPL;
361 }
362
363 static HRESULT WINAPI xmlnode_removeChild(
364     IXMLDOMNode *iface,
365     IXMLDOMNode* childNode,
366     IXMLDOMNode** oldChild)
367 {
368     FIXME("\n");
369     return E_NOTIMPL;
370 }
371
372 static HRESULT WINAPI xmlnode_appendChild(
373     IXMLDOMNode *iface,
374     IXMLDOMNode* newChild,
375     IXMLDOMNode** outNewChild)
376 {
377     FIXME("\n");
378     return E_NOTIMPL;
379 }
380
381 static HRESULT WINAPI xmlnode_hasChildNodes(
382     IXMLDOMNode *iface,
383     VARIANT_BOOL* hasChild)
384 {
385     xmlnode *This = impl_from_IXMLDOMNode( iface );
386
387     TRACE("%p\n", This);
388
389     if (!hasChild)
390         return E_INVALIDARG;
391     if (!This->node->children)
392     {
393         *hasChild = VARIANT_FALSE;
394         return S_FALSE;
395     }
396
397     *hasChild = VARIANT_TRUE;
398     return S_OK;
399 }
400
401 static HRESULT WINAPI xmlnode_get_ownerDocument(
402     IXMLDOMNode *iface,
403     IXMLDOMDocument** DOMDocument)
404 {
405     FIXME("\n");
406     return E_NOTIMPL;
407 }
408
409 static HRESULT WINAPI xmlnode_cloneNode(
410     IXMLDOMNode *iface,
411     VARIANT_BOOL deep,
412     IXMLDOMNode** cloneRoot)
413 {
414     FIXME("\n");
415     return E_NOTIMPL;
416 }
417
418 static HRESULT WINAPI xmlnode_get_nodeTypeString(
419     IXMLDOMNode *iface,
420     BSTR* xmlnodeType)
421 {
422     FIXME("\n");
423     return E_NOTIMPL;
424 }
425
426 static HRESULT WINAPI xmlnode_get_text(
427     IXMLDOMNode *iface,
428     BSTR* text)
429 {
430     xmlnode *This = impl_from_IXMLDOMNode( iface );
431     xmlNodePtr child;
432     BSTR str = NULL;
433
434     TRACE("%p\n", This);
435
436     if ( !text )
437         return E_INVALIDARG;
438
439     child = This->node->children;
440     if ( child && child->type == XML_TEXT_NODE )
441         str = bstr_from_xmlChar( child->content );
442
443     TRACE("%p %s\n", This, debugstr_w(str) );
444     *text = str;
445  
446     return S_OK;
447 }
448
449 static HRESULT WINAPI xmlnode_put_text(
450     IXMLDOMNode *iface,
451     BSTR text)
452 {
453     FIXME("\n");
454     return E_NOTIMPL;
455 }
456
457 static HRESULT WINAPI xmlnode_get_specified(
458     IXMLDOMNode *iface,
459     VARIANT_BOOL* isSpecified)
460 {
461     FIXME("\n");
462     return E_NOTIMPL;
463 }
464
465 static HRESULT WINAPI xmlnode_get_definition(
466     IXMLDOMNode *iface,
467     IXMLDOMNode** definitionNode)
468 {
469     FIXME("\n");
470     return E_NOTIMPL;
471 }
472
473 static HRESULT WINAPI xmlnode_get_nodeTypedValue(
474     IXMLDOMNode *iface,
475     VARIANT* typedValue)
476 {
477     FIXME("\n");
478     return E_NOTIMPL;
479 }
480
481 static HRESULT WINAPI xmlnode_put_nodeTypedValue(
482     IXMLDOMNode *iface,
483     VARIANT typedValue)
484 {
485     FIXME("\n");
486     return E_NOTIMPL;
487 }
488
489 static HRESULT WINAPI xmlnode_get_dataType(
490     IXMLDOMNode *iface,
491     VARIANT* dataTypeName)
492 {
493     FIXME("\n");
494     return E_NOTIMPL;
495 }
496
497 static HRESULT WINAPI xmlnode_put_dataType(
498     IXMLDOMNode *iface,
499     BSTR dataTypeName)
500 {
501     FIXME("\n");
502     return E_NOTIMPL;
503 }
504
505 static HRESULT WINAPI xmlnode_get_xml(
506     IXMLDOMNode *iface,
507     BSTR* xmlString)
508 {
509     FIXME("\n");
510     return E_NOTIMPL;
511 }
512
513 static HRESULT WINAPI xmlnode_transformNode(
514     IXMLDOMNode *iface,
515     IXMLDOMNode* styleSheet,
516     BSTR* xmlString)
517 {
518     FIXME("\n");
519     return E_NOTIMPL;
520 }
521
522 static HRESULT WINAPI xmlnode_selectNodes(
523     IXMLDOMNode *iface,
524     BSTR queryString,
525     IXMLDOMNodeList** resultList)
526 {
527     xmlnode *This = impl_from_IXMLDOMNode( iface );
528     xmlChar *str = NULL;
529     HRESULT r = E_FAIL;
530
531     TRACE("%p %s %p\n", This, debugstr_w(queryString), resultList );
532
533     str = xmlChar_from_wchar( queryString );
534     if (!str)
535         return r;
536
537     *resultList = create_filtered_nodelist( This->node->children, str );
538     HeapFree( GetProcessHeap(), 0, str );
539     return S_OK;
540 }
541
542 static HRESULT WINAPI xmlnode_selectSingleNode(
543     IXMLDOMNode *iface,
544     BSTR queryString,
545     IXMLDOMNode** resultNode)
546 {
547     FIXME("\n");
548     return E_NOTIMPL;
549 }
550
551 static HRESULT WINAPI xmlnode_get_parsed(
552     IXMLDOMNode *iface,
553     VARIANT_BOOL* isParsed)
554 {
555     FIXME("\n");
556     return E_NOTIMPL;
557 }
558
559 static HRESULT WINAPI xmlnode_get_namespaceURI(
560     IXMLDOMNode *iface,
561     BSTR* namespaceURI)
562 {
563     FIXME("\n");
564     return E_NOTIMPL;
565 }
566
567 static HRESULT WINAPI xmlnode_get_prefix(
568     IXMLDOMNode *iface,
569     BSTR* prefixString)
570 {
571     FIXME("\n");
572     return E_NOTIMPL;
573 }
574
575 static HRESULT WINAPI xmlnode_get_baseName(
576     IXMLDOMNode *iface,
577     BSTR* nameString)
578 {
579     xmlnode *This = impl_from_IXMLDOMNode( iface );
580     BSTR str = NULL;
581     HRESULT r = S_FALSE;
582
583     TRACE("%p %p\n", This, nameString );
584
585     if ( !nameString )
586         return E_INVALIDARG;
587
588     switch ( This->node->type )
589     {
590     case XML_ELEMENT_NODE:
591     case XML_ATTRIBUTE_NODE:
592         str = bstr_from_xmlChar( This->node->name );
593         r = S_OK;
594         break;
595     case XML_TEXT_NODE:
596         break;
597     default:
598         ERR("Unhandled type %d\n", This->node->type );
599         break;
600     }
601
602     TRACE("returning %08lx str = %s\n", r, debugstr_w( str ) );
603
604     *nameString = str;
605     return r;
606 }
607
608 static HRESULT WINAPI xmlnode_transformNodeToObject(
609     IXMLDOMNode *iface,
610     IXMLDOMNode* stylesheet,
611     VARIANT outputObject)
612 {
613     FIXME("\n");
614     return E_NOTIMPL;
615 }
616
617 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
618 {
619     xmlnode_QueryInterface,
620     xmlnode_AddRef,
621     xmlnode_Release,
622     xmlnode_GetTypeInfoCount,
623     xmlnode_GetTypeInfo,
624     xmlnode_GetIDsOfNames,
625     xmlnode_Invoke,
626     xmlnode_get_nodeName,
627     xmlnode_get_nodeValue,
628     xmlnode_put_nodeValue,
629     xmlnode_get_nodeType,
630     xmlnode_get_parentNode,
631     xmlnode_get_childNodes,
632     xmlnode_get_firstChild,
633     xmlnode_get_lastChild,
634     xmlnode_get_previousSibling,
635     xmlnode_get_nextSibling,
636     xmlnode_get_attributes,
637     xmlnode_insertBefore,
638     xmlnode_replaceChild,
639     xmlnode_removeChild,
640     xmlnode_appendChild,
641     xmlnode_hasChildNodes,
642     xmlnode_get_ownerDocument,
643     xmlnode_cloneNode,
644     xmlnode_get_nodeTypeString,
645     xmlnode_get_text,
646     xmlnode_put_text,
647     xmlnode_get_specified,
648     xmlnode_get_definition,
649     xmlnode_get_nodeTypedValue,
650     xmlnode_put_nodeTypedValue,
651     xmlnode_get_dataType,
652     xmlnode_put_dataType,
653     xmlnode_get_xml,
654     xmlnode_transformNode,
655     xmlnode_selectNodes,
656     xmlnode_selectSingleNode,
657     xmlnode_get_parsed,
658     xmlnode_get_namespaceURI,
659     xmlnode_get_prefix,
660     xmlnode_get_baseName,
661     xmlnode_transformNodeToObject,
662 };
663
664 IXMLDOMNode *create_node( xmlNodePtr node )
665 {
666     xmlnode *This;
667
668     if ( !node )
669         return NULL;
670
671     assert( node->doc );
672
673     /* if an interface already exists for this node, return it */
674     if ( node->_private )
675     {
676         IXMLDOMNode *n = node->_private;
677         IXMLDOMNode_AddRef( n );
678         return n;
679     }
680
681     /*
682      * Try adding a reference to the IXMLDOMNode implementation
683      * containing the document's root element.
684      */
685     if ( node->type != XML_DOCUMENT_NODE )
686     {
687         IXMLDOMNode *root = NULL;
688
689         root = node->doc->_private;
690         assert( root );
691         IXMLDOMNode_AddRef( root );
692     }
693     else
694         assert( node->doc == (xmlDocPtr) node );
695
696     This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
697     if ( !This )
698         return NULL;
699
700     This->lpVtbl = &xmlnode_vtbl;
701     This->ref = 1;
702     This->node = node;
703
704     /* remember which interface we associated with this node */
705     node->_private = This;
706
707     return (IXMLDOMNode*) &This->lpVtbl;
708 }
709
710 #endif