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