ReactOS 0.4.15-dev-7842-g558ab78
node.c
Go to the documentation of this file.
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., 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
27#ifdef HAVE_LIBXML2
28# include <libxml/parser.h>
30# include <libxml/xmlerror.h>
31# include <libxml/HTMLtree.h>
32# ifdef SONAME_LIBXSLT
33# ifdef HAVE_LIBXSLT_PATTERN_H
34# include <libxslt/pattern.h>
35# endif
36# ifdef HAVE_LIBXSLT_TRANSFORM_H
37# include <libxslt/transform.h>
38# endif
39# include <libxslt/imports.h>
40# include <libxslt/variables.h>
41# include <libxslt/xsltutils.h>
43# include <libxslt/documents.h>
44# endif
45#endif
46
47#include "windef.h"
48#include "winbase.h"
49#include "winuser.h"
50#include "winnls.h"
51#include "ole2.h"
52#include "msxml6.h"
53
54#include "msxml_private.h"
55
56#include "wine/debug.h"
57
58#ifdef HAVE_LIBXML2
59
61
62#ifdef SONAME_LIBXSLT
63extern void* libxslt_handle;
64# define MAKE_FUNCPTR(f) extern typeof(f) * p##f
75# undef MAKE_FUNCPTR
76#else
78#endif
79
80static const IID IID_xmlnode = {0x4f2f4ba2,0xb822,0x11df,{0x8b,0x8a,0x68,0x50,0xdf,0xd7,0x20,0x85}};
81
82xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type )
83{
84 xmlnode *This;
85
86 if ( !iface )
87 return NULL;
88 This = get_node_obj( iface );
89 if ( !This || !This->node )
90 return NULL;
91 if ( type && This->node->type != type )
92 return NULL;
93 return This->node;
94}
95
96BOOL node_query_interface(xmlnode *This, REFIID riid, void **ppv)
97{
98 if(IsEqualGUID(&IID_xmlnode, riid)) {
99 TRACE("(%p)->(IID_xmlnode %p)\n", This, ppv);
100 *ppv = This;
101 return TRUE;
102 }
103
104 return dispex_query_interface(&This->dispex, riid, ppv);
105}
106
107/* common ISupportErrorInfo implementation */
108typedef struct {
109 ISupportErrorInfo ISupportErrorInfo_iface;
110 LONG ref;
111
112 const tid_t* iids;
113} SupportErrorInfo;
114
115static inline SupportErrorInfo *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
116{
117 return CONTAINING_RECORD(iface, SupportErrorInfo, ISupportErrorInfo_iface);
118}
119
121{
122 SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface);
123 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
124
125 *obj = NULL;
126
127 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_ISupportErrorInfo)) {
128 *obj = iface;
129 ISupportErrorInfo_AddRef(iface);
130 return S_OK;
131 }
132
133 return E_NOINTERFACE;
134}
135
137{
138 SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface);
140 TRACE("(%p)->(%d)\n", This, ref );
141 return ref;
142}
143
145{
146 SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface);
148
149 TRACE("(%p)->(%d)\n", This, ref);
150
151 if (ref == 0)
153
154 return ref;
155}
156
158{
159 SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface);
160 enum tid_t const *tid;
161
162 TRACE("(%p)->(%s)\n", This, debugstr_guid(riid));
163
164 tid = This->iids;
165 while (*tid != NULL_tid)
166 {
168 return S_OK;
169 tid++;
170 }
171
172 return S_FALSE;
173}
174
175static const struct ISupportErrorInfoVtbl SupportErrorInfoVtbl = {
180};
181
182HRESULT node_create_supporterrorinfo(enum tid_t const *iids, void **obj)
183{
184 SupportErrorInfo *This;
185
186 This = heap_alloc(sizeof(*This));
187 if (!This) return E_OUTOFMEMORY;
188
189 This->ISupportErrorInfo_iface.lpVtbl = &SupportErrorInfoVtbl;
190 This->ref = 1;
191 This->iids = iids;
192
193 *obj = &This->ISupportErrorInfo_iface;
194
195 return S_OK;
196}
197
199{
200 xmlnode *obj = NULL;
202
203 hres = IXMLDOMNode_QueryInterface(node, &IID_xmlnode, (void**)&obj);
204 if (!obj) WARN("node is not our IXMLDOMNode implementation\n");
205 return SUCCEEDED(hres) ? obj : NULL;
206}
207
208HRESULT node_get_nodeName(xmlnode *This, BSTR *name)
209{
210 BSTR prefix, base;
211 HRESULT hr;
212
213 if (!name)
214 return E_INVALIDARG;
215
216 hr = node_get_base_name(This, &base);
217 if (hr != S_OK) return hr;
218
219 hr = node_get_prefix(This, &prefix);
220 if (hr == S_OK)
221 {
222 static const WCHAR colW = ':';
223 WCHAR *ptr;
224
225 /* +1 for ':' */
227 memcpy(ptr, prefix, SysStringByteLen(prefix));
228 ptr += SysStringLen(prefix);
229 memcpy(ptr++, &colW, sizeof(WCHAR));
231
233 SysFreeString(prefix);
234 }
235 else
236 *name = base;
237
238 return S_OK;
239}
240
241HRESULT node_get_content(xmlnode *This, VARIANT *value)
242{
244
245 if(!value)
246 return E_INVALIDARG;
247
249 V_VT(value) = VT_BSTR;
250 V_BSTR(value) = bstr_from_xmlChar( content );
252
253 TRACE("%p returned %s\n", This, debugstr_w(V_BSTR(value)));
254 return S_OK;
255}
256
257HRESULT node_set_content(xmlnode *This, LPCWSTR value)
258{
259 xmlChar *str;
260
261 TRACE("(%p)->(%s)\n", This, debugstr_w(value));
262 str = xmlchar_from_wchar(value);
263 if(!str)
264 return E_OUTOFMEMORY;
265
266 xmlNodeSetContent(This->node, str);
267 heap_free(str);
268 return S_OK;
269}
270
271static HRESULT node_set_content_escaped(xmlnode *This, LPCWSTR value)
272{
273 xmlChar *str, *escaped;
274
275 TRACE("(%p)->(%s)\n", This, debugstr_w(value));
276 str = xmlchar_from_wchar(value);
277 if(!str)
278 return E_OUTOFMEMORY;
279
280 escaped = xmlEncodeSpecialChars(NULL, str);
281 if(!escaped)
282 {
283 heap_free(str);
284 return E_OUTOFMEMORY;
285 }
286
287 xmlNodeSetContent(This->node, escaped);
288
289 heap_free(str);
290 xmlFree(escaped);
291
292 return S_OK;
293}
294
295HRESULT node_put_value(xmlnode *This, VARIANT *value)
296{
297 HRESULT hr;
298
299 if (V_VT(value) != VT_BSTR)
300 {
301 VARIANT string_value;
302
303 VariantInit(&string_value);
304 hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
305 if(FAILED(hr)) {
306 WARN("Couldn't convert to VT_BSTR\n");
307 return hr;
308 }
309
310 hr = node_set_content(This, V_BSTR(&string_value));
311 VariantClear(&string_value);
312 }
313 else
314 hr = node_set_content(This, V_BSTR(value));
315
316 return hr;
317}
318
319HRESULT node_put_value_escaped(xmlnode *This, VARIANT *value)
320{
321 HRESULT hr;
322
323 if (V_VT(value) != VT_BSTR)
324 {
325 VARIANT string_value;
326
327 VariantInit(&string_value);
328 hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
329 if(FAILED(hr)) {
330 WARN("Couldn't convert to VT_BSTR\n");
331 return hr;
332 }
333
334 hr = node_set_content_escaped(This, V_BSTR(&string_value));
335 VariantClear(&string_value);
336 }
337 else
338 hr = node_set_content_escaped(This, V_BSTR(value));
339
340 return hr;
341}
342
343static HRESULT get_node(
344 xmlnode *This,
345 const char *name,
347 IXMLDOMNode **out )
348{
349 TRACE("(%p)->(%s %p %p)\n", This, name, node, out );
350
351 if ( !out )
352 return E_INVALIDARG;
353
354 /* if we don't have a doc, use our parent. */
355 if(node && !node->doc && node->parent)
356 node->doc = node->parent->doc;
357
358 *out = create_node( node );
359 if (!*out)
360 return S_FALSE;
361 return S_OK;
362}
363
364HRESULT node_get_parent(xmlnode *This, IXMLDOMNode **parent)
365{
366 return get_node( This, "parent", This->node->parent, parent );
367}
368
369HRESULT node_get_child_nodes(xmlnode *This, IXMLDOMNodeList **ret)
370{
371 if(!ret)
372 return E_INVALIDARG;
373
374 *ret = create_children_nodelist(This->node);
375 if(!*ret)
376 return E_OUTOFMEMORY;
377
378 return S_OK;
379}
380
381HRESULT node_get_first_child(xmlnode *This, IXMLDOMNode **ret)
382{
383 return get_node(This, "firstChild", This->node->children, ret);
384}
385
386HRESULT node_get_last_child(xmlnode *This, IXMLDOMNode **ret)
387{
388 return get_node(This, "lastChild", This->node->last, ret);
389}
390
391HRESULT node_get_previous_sibling(xmlnode *This, IXMLDOMNode **ret)
392{
393 return get_node(This, "previous", This->node->prev, ret);
394}
395
396HRESULT node_get_next_sibling(xmlnode *This, IXMLDOMNode **ret)
397{
398 return get_node(This, "next", This->node->next, ret);
399}
400
401static int node_get_inst_cnt(xmlNodePtr node)
402{
403 int ret = *(LONG *)&node->_private & NODE_PRIV_REFCOUNT_MASK;
405
406 /* add attribute counts */
407 if (node->type == XML_ELEMENT_NODE)
408 {
409 xmlAttrPtr prop = node->properties;
410
411 while (prop)
412 {
413 ret += node_get_inst_cnt((xmlNodePtr)prop);
414 prop = prop->next;
415 }
416 }
417
418 /* add children counts */
419 child = node->children;
420 while (child)
421 {
422 ret += node_get_inst_cnt(child);
423 child = child->next;
424 }
425
426 return ret;
427}
428
429int xmlnode_get_inst_cnt(xmlnode *node)
430{
431 return node_get_inst_cnt(node->node);
432}
433
434/* _private field holds a number of COM instances spawned from this libxml2 node
435 * most significant bits are used to store information about ignorrable whitespace nodes */
436void xmlnode_add_ref(xmlNodePtr node)
437{
438 if (node->type == XML_DOCUMENT_NODE) return;
439 InterlockedIncrement((LONG*)&node->_private);
440}
441
442void xmlnode_release(xmlNodePtr node)
443{
444 if (node->type == XML_DOCUMENT_NODE) return;
445 InterlockedDecrement((LONG*)&node->_private);
446}
447
448HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT *ref_child,
450{
452 xmlnode *node_obj;
453 int refcount = 0;
454 xmlDocPtr doc;
455 HRESULT hr;
456
457 if(!new_child)
458 return E_INVALIDARG;
459
460 node_obj = get_node_obj(new_child);
461 if(!node_obj) return E_FAIL;
462
463 switch(V_VT(ref_child))
464 {
465 case VT_EMPTY:
466 case VT_NULL:
467 break;
468
469 case VT_UNKNOWN:
470 case VT_DISPATCH:
471 if (V_UNKNOWN(ref_child))
472 {
473 hr = IUnknown_QueryInterface(V_UNKNOWN(ref_child), &IID_IXMLDOMNode, (void**)&before);
474 if(FAILED(hr)) return hr;
475 }
476 break;
477
478 default:
479 FIXME("refChild var type %x\n", V_VT(ref_child));
480 return E_FAIL;
481 }
482
483 TRACE("new child %p, This->node %p\n", node_obj->node, This->node);
484
485 if(!node_obj->node->parent)
486 if(xmldoc_remove_orphan(node_obj->node->doc, node_obj->node) != S_OK)
487 WARN("%p is not an orphan of %p\n", node_obj->node, node_obj->node->doc);
488
489 refcount = xmlnode_get_inst_cnt(node_obj);
490
491 if(before)
492 {
493 xmlnode *before_node_obj = get_node_obj(before);
494 IXMLDOMNode_Release(before);
495 if(!before_node_obj) return E_FAIL;
496 }
497
498 /* unlink from current parent first */
499 if(node_obj->parent)
500 {
501 hr = IXMLDOMNode_removeChild(node_obj->parent, node_obj->iface, NULL);
502 if (hr == S_OK) xmldoc_remove_orphan(node_obj->node->doc, node_obj->node);
503 }
504 doc = node_obj->node->doc;
505
506 if(before)
507 {
508 xmlNodePtr new_node;
509 xmlnode *before_node_obj = get_node_obj(before);
510
511 /* refs count including subtree */
512 if (doc != before_node_obj->node->doc)
513 refcount = xmlnode_get_inst_cnt(node_obj);
514
515 if (refcount) xmldoc_add_refs(before_node_obj->node->doc, refcount);
516 new_node = xmlAddPrevSibling(before_node_obj->node, node_obj->node);
517 if (new_node != node_obj->node)
518 {
519 if (refcount != 1)
520 FIXME("referenced xmlNode was freed, expect crashes\n");
521 xmlnode_add_ref(new_node);
522 node_obj->node = new_node;
523 }
524 if (refcount) xmldoc_release_refs(doc, refcount);
525 node_obj->parent = This->parent;
526 }
527 else
528 {
529 xmlNodePtr new_node;
530
531 if (doc != This->node->doc)
532 refcount = xmlnode_get_inst_cnt(node_obj);
533
534 if (refcount) xmldoc_add_refs(This->node->doc, refcount);
535 /* xmlAddChild doesn't unlink node from previous parent */
536 xmlUnlinkNode(node_obj->node);
537 new_node = xmlAddChild(This->node, node_obj->node);
538 if (new_node != node_obj->node)
539 {
540 if (refcount != 1)
541 FIXME("referenced xmlNode was freed, expect crashes\n");
542 xmlnode_add_ref(new_node);
543 node_obj->node = new_node;
544 }
545 if (refcount) xmldoc_release_refs(doc, refcount);
546 node_obj->parent = This->iface;
547 }
548
549 if(ret)
550 {
551 IXMLDOMNode_AddRef(new_child);
552 *ret = new_child;
553 }
554
555 TRACE("ret S_OK\n");
556 return S_OK;
557}
558
559HRESULT node_replace_child(xmlnode *This, IXMLDOMNode *newChild, IXMLDOMNode *oldChild,
561{
562 xmlnode *old_child, *new_child;
563 xmlDocPtr leaving_doc;
564 xmlNode *my_ancestor;
565 int refcount = 0;
566
567 /* Do not believe any documentation telling that newChild == NULL
568 means removal. It does certainly *not* apply to msxml3! */
569 if(!newChild || !oldChild)
570 return E_INVALIDARG;
571
572 if(ret)
573 *ret = NULL;
574
575 old_child = get_node_obj(oldChild);
576 if(!old_child) return E_FAIL;
577
578 if(old_child->node->parent != This->node)
579 {
580 WARN("childNode %p is not a child of %p\n", oldChild, This);
581 return E_INVALIDARG;
582 }
583
584 new_child = get_node_obj(newChild);
585 if(!new_child) return E_FAIL;
586
587 my_ancestor = This->node;
588 while(my_ancestor)
589 {
590 if(my_ancestor == new_child->node)
591 {
592 WARN("tried to create loop\n");
593 return E_FAIL;
594 }
595 my_ancestor = my_ancestor->parent;
596 }
597
598 if(!new_child->node->parent)
599 if(xmldoc_remove_orphan(new_child->node->doc, new_child->node) != S_OK)
600 WARN("%p is not an orphan of %p\n", new_child->node, new_child->node->doc);
601
602 leaving_doc = new_child->node->doc;
603
604 if (leaving_doc != old_child->node->doc)
605 refcount = xmlnode_get_inst_cnt(new_child);
606
607 if (refcount) xmldoc_add_refs(old_child->node->doc, refcount);
608 xmlReplaceNode(old_child->node, new_child->node);
609 if (refcount) xmldoc_release_refs(leaving_doc, refcount);
610 new_child->parent = old_child->parent;
611 old_child->parent = NULL;
612
613 xmldoc_add_orphan(old_child->node->doc, old_child->node);
614
615 if(ret)
616 {
617 IXMLDOMNode_AddRef(oldChild);
618 *ret = oldChild;
619 }
620
621 return S_OK;
622}
623
624HRESULT node_remove_child(xmlnode *This, IXMLDOMNode* child, IXMLDOMNode** oldChild)
625{
626 xmlnode *child_node;
627
628 if(!child) return E_INVALIDARG;
629
630 if(oldChild)
631 *oldChild = NULL;
632
633 child_node = get_node_obj(child);
634 if(!child_node) return E_FAIL;
635
636 if(child_node->node->parent != This->node)
637 {
638 WARN("childNode %p is not a child of %p\n", child, This);
639 return E_INVALIDARG;
640 }
641
642 xmlUnlinkNode(child_node->node);
643 child_node->parent = NULL;
644 xmldoc_add_orphan(child_node->node->doc, child_node->node);
645
646 if(oldChild)
647 {
648 IXMLDOMNode_AddRef(child);
649 *oldChild = child;
650 }
651
652 return S_OK;
653}
654
655HRESULT node_append_child(xmlnode *This, IXMLDOMNode *child, IXMLDOMNode **outChild)
656{
658 VARIANT var;
659 HRESULT hr;
660
661 if (!child)
662 return E_INVALIDARG;
663
664 hr = IXMLDOMNode_get_nodeType(child, &type);
665 if(FAILED(hr) || type == NODE_ATTRIBUTE) {
666 if (outChild) *outChild = NULL;
667 return E_FAIL;
668 }
669
671 return IXMLDOMNode_insertBefore(This->iface, child, var, outChild);
672}
673
674HRESULT node_has_childnodes(const xmlnode *This, VARIANT_BOOL *ret)
675{
676 if (!ret) return E_INVALIDARG;
677
678 if (!This->node->children)
679 {
680 *ret = VARIANT_FALSE;
681 return S_FALSE;
682 }
683
684 *ret = VARIANT_TRUE;
685 return S_OK;
686}
687
688HRESULT node_get_owner_doc(const xmlnode *This, IXMLDOMDocument **doc)
689{
690 if(!doc)
691 return E_INVALIDARG;
692 return get_domdoc_from_xmldoc(This->node->doc, (IXMLDOMDocument3**)doc);
693}
694
695HRESULT node_clone(xmlnode *This, VARIANT_BOOL deep, IXMLDOMNode **cloneNode)
696{
698 xmlNodePtr clone;
699
700 if(!cloneNode) return E_INVALIDARG;
701
702 clone = xmlCopyNode(This->node, deep ? 1 : 2);
703 if (clone)
704 {
705 xmlSetTreeDoc(clone, This->node->doc);
706 xmldoc_add_orphan(clone->doc, clone);
707
708 node = create_node(clone);
709 if (!node)
710 {
711 ERR("Copy failed\n");
712 xmldoc_remove_orphan(clone->doc, clone);
713 xmlFreeNode(clone);
714 return E_FAIL;
715 }
716
717 *cloneNode = node;
718 }
719 else
720 {
721 ERR("Copy failed\n");
722 return E_FAIL;
723 }
724
725 return S_OK;
726}
727
728static xmlChar* do_get_text(xmlNodePtr node, BOOL trim, DWORD *first, DWORD *last, BOOL *trail_ig_ws)
729{
731 xmlChar* str;
732 BOOL preserving = is_preserving_whitespace(node);
733
734 *first = -1;
735 *last = 0;
736
737 if (!node->children)
738 {
740 *trail_ig_ws = *(DWORD*)&node->_private & NODE_PRIV_CHILD_IGNORABLE_WS;
741 }
742 else
743 {
744 BOOL ig_ws = FALSE;
745 xmlChar* tmp;
746 DWORD pos = 0;
747 str = xmlStrdup(BAD_CAST "");
748
749 if (node->type != XML_DOCUMENT_NODE)
750 ig_ws = *(DWORD*)&node->_private & NODE_PRIV_CHILD_IGNORABLE_WS;
751 *trail_ig_ws = FALSE;
752
753 for (child = node->children; child != NULL; child = child->next)
754 {
755 switch (child->type)
756 {
757 case XML_ELEMENT_NODE: {
758 DWORD node_first, node_last;
759
760 tmp = do_get_text(child, FALSE, &node_first, &node_last, trail_ig_ws);
761
762 if (node_first!=-1 && pos+node_first<*first)
763 *first = pos+node_first;
764 if (node_last && pos+node_last>*last)
765 *last = pos+node_last;
766 break;
767 }
768 case XML_TEXT_NODE:
770 if (!preserving && tmp[0])
771 {
772 xmlChar *beg;
773
774 for (beg = tmp; *beg; beg++)
775 if (!isspace(*beg)) break;
776
777 if (!*beg)
778 {
779 ig_ws = TRUE;
780 xmlFree(tmp);
781 tmp = NULL;
782 }
783 }
784 break;
787 case XML_ENTITY_NODE:
789 break;
790 default:
791 tmp = NULL;
792 break;
793 }
794
795 if ((tmp && *tmp) || child->type==XML_CDATA_SECTION_NODE)
796 {
797 if (ig_ws && str[0])
798 {
799 str = xmlStrcat(str, BAD_CAST " ");
800 pos++;
801 }
802 if (tmp && *tmp) str = xmlStrcat(str, tmp);
803 if (child->type==XML_CDATA_SECTION_NODE && pos<*first)
804 *first = pos;
805 if (tmp && *tmp) pos += xmlStrlen(tmp);
806 if (child->type==XML_CDATA_SECTION_NODE && pos>*last)
807 *last = pos;
808 ig_ws = FALSE;
809 }
810 if (tmp) xmlFree(tmp);
811
812 if (!ig_ws)
813 {
814 ig_ws = *(DWORD*)&child->_private & NODE_PRIV_TRAILING_IGNORABLE_WS;
815 }
816 if (!ig_ws)
817 ig_ws = *trail_ig_ws;
818 *trail_ig_ws = FALSE;
819 }
820
821 *trail_ig_ws = ig_ws;
822 }
823
824 switch (node->type)
825 {
826 case XML_ELEMENT_NODE:
827 case XML_TEXT_NODE:
829 case XML_ENTITY_NODE:
832 if (trim && !preserving)
833 {
834 xmlChar* ret;
835 int len;
836
837 if (!str)
838 break;
839
840 for (ret = str; *ret && isspace(*ret) && (*first)--; ret++)
841 if (*last) (*last)--;
842 for (len = xmlStrlen(ret)-1; len >= 0 && len >= *last; len--)
843 if(!isspace(ret[len])) break;
844
845 ret = xmlStrndup(ret, len+1);
846 xmlFree(str);
847 str = ret;
848 break;
849 }
850 break;
851 default:
852 break;
853 }
854
855 return str;
856}
857
858HRESULT node_get_text(const xmlnode *This, BSTR *text)
859{
860 BSTR str = NULL;
863 BOOL tmp;
864
865 if (!text) return E_INVALIDARG;
866
867 content = do_get_text(This->node, TRUE, &first, &last, &tmp);
868 if (content)
869 {
870 str = bstr_from_xmlChar(content);
872 }
873
874 /* Always return a string. */
875 if (!str) str = SysAllocStringLen( NULL, 0 );
876
877 TRACE("%p %s\n", This, debugstr_w(str) );
878 *text = str;
879
880 return S_OK;
881}
882
883HRESULT node_put_text(xmlnode *This, BSTR text)
884{
885 xmlChar *str, *str2;
886
887 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
888
889 str = xmlchar_from_wchar(text);
890
891 /* Escape the string. */
892 str2 = xmlEncodeEntitiesReentrant(This->node->doc, str);
893 heap_free(str);
894
895 xmlNodeSetContent(This->node, str2);
896 xmlFree(str2);
897
898 return S_OK;
899}
900
901BSTR EnsureCorrectEOL(BSTR sInput)
902{
903 int nNum = 0;
904 BSTR sNew;
905 int nLen;
906 int i;
907
908 nLen = SysStringLen(sInput);
909 /* Count line endings */
910 for(i=0; i < nLen; i++)
911 {
912 if(sInput[i] == '\n')
913 nNum++;
914 }
915
916 TRACE("len=%d, num=%d\n", nLen, nNum);
917
918 /* Add linefeed as needed */
919 if(nNum > 0)
920 {
921 int nPlace = 0;
922 sNew = SysAllocStringLen(NULL, nLen + nNum);
923 for(i=0; i < nLen; i++)
924 {
925 if(sInput[i] == '\n')
926 {
927 sNew[i+nPlace] = '\r';
928 nPlace++;
929 }
930 sNew[i+nPlace] = sInput[i];
931 }
932
933 SysFreeString(sInput);
934 }
935 else
936 {
937 sNew = sInput;
938 }
939
940 TRACE("len %d\n", SysStringLen(sNew));
941
942 return sNew;
943}
944
945/*
946 * We are trying to replicate the same behaviour as msxml by converting
947 * line endings to \r\n and using indents as \t. The problem is that msxml
948 * only formats nodes that have a line ending. Using libxml we cannot
949 * reproduce behaviour exactly.
950 *
951 */
952HRESULT node_get_xml(xmlnode *This, BOOL ensure_eol, BSTR *ret)
953{
954 xmlBufferPtr xml_buf;
955 xmlNodePtr xmldecl;
956 int size;
957
958 if(!ret)
959 return E_INVALIDARG;
960
961 *ret = NULL;
962
963 xml_buf = xmlBufferCreate();
964 if(!xml_buf)
965 return E_OUTOFMEMORY;
966
967 xmldecl = xmldoc_unlink_xmldecl( This->node->doc );
968
969 size = xmlNodeDump(xml_buf, This->node->doc, This->node, 0, 1);
970 if(size > 0) {
971 const xmlChar *buf_content;
973
974 /* Attribute Nodes return a space in front of their name */
975 buf_content = xmlBufferContent(xml_buf);
976
977 content = bstr_from_xmlChar(buf_content + (buf_content[0] == ' ' ? 1 : 0));
978 if(ensure_eol)
979 content = EnsureCorrectEOL(content);
980
981 *ret = content;
982 }else {
984 }
985
986 xmlBufferFree(xml_buf);
987 xmldoc_link_xmldecl( This->node->doc, xmldecl );
988 return *ret ? S_OK : E_OUTOFMEMORY;
989}
990
991#ifdef SONAME_LIBXSLT
992
993/* duplicates xmlBufferWriteQuotedString() logic */
994static void xml_write_quotedstring(xmlOutputBufferPtr buf, const xmlChar *string)
995{
996 const xmlChar *cur, *base;
997
998 if (xmlStrchr(string, '\"'))
999 {
1000 if (xmlStrchr(string, '\''))
1001 {
1002 xmlOutputBufferWrite(buf, 1, "\"");
1003 base = cur = string;
1004
1005 while (*cur)
1006 {
1007 if (*cur == '"')
1008 {
1009 if (base != cur)
1010 xmlOutputBufferWrite(buf, cur-base, (const char*)base);
1011 xmlOutputBufferWrite(buf, 6, "&quot;");
1012 cur++;
1013 base = cur;
1014 }
1015 else
1016 cur++;
1017 }
1018 if (base != cur)
1019 xmlOutputBufferWrite(buf, cur-base, (const char*)base);
1020 xmlOutputBufferWrite(buf, 1, "\"");
1021 }
1022 else
1023 {
1024 xmlOutputBufferWrite(buf, 1, "\'");
1025 xmlOutputBufferWriteString(buf, (const char*)string);
1026 xmlOutputBufferWrite(buf, 1, "\'");
1027 }
1028 }
1029 else
1030 {
1031 xmlOutputBufferWrite(buf, 1, "\"");
1032 xmlOutputBufferWriteString(buf, (const char*)string);
1033 xmlOutputBufferWrite(buf, 1, "\"");
1034 }
1035}
1036
1037static int XMLCALL transform_to_stream_write(void *context, const char *buffer, int len)
1038{
1039 DWORD written;
1040 HRESULT hr = ISequentialStream_Write((ISequentialStream *)context, buffer, len, &written);
1041 return hr == S_OK ? written : -1;
1042}
1043
1044/* Output for method "text" */
1045static void transform_write_text(xmlDocPtr result, xsltStylesheetPtr style, xmlOutputBufferPtr output)
1046{
1047 xmlNodePtr cur = result->children;
1048 while (cur)
1049 {
1050 if (cur->type == XML_TEXT_NODE)
1051 xmlOutputBufferWriteString(output, (const char*)cur->content);
1052
1053 /* skip to next node */
1054 if (cur->children)
1055 {
1056 if ((cur->children->type != XML_ENTITY_DECL) &&
1057 (cur->children->type != XML_ENTITY_REF_NODE) &&
1058 (cur->children->type != XML_ENTITY_NODE))
1059 {
1060 cur = cur->children;
1061 continue;
1062 }
1063 }
1064
1065 if (cur->next) {
1066 cur = cur->next;
1067 continue;
1068 }
1069
1070 do
1071 {
1072 cur = cur->parent;
1073 if (cur == NULL)
1074 break;
1075 if (cur == (xmlNodePtr) style->doc) {
1076 cur = NULL;
1077 break;
1078 }
1079 if (cur->next) {
1080 cur = cur->next;
1081 break;
1082 }
1083 } while (cur);
1084 }
1085}
1086
1087#undef XSLT_GET_IMPORT_PTR
1088#define XSLT_GET_IMPORT_PTR(res, style, name) { \
1089 xsltStylesheetPtr st = style; \
1090 res = NULL; \
1091 while (st != NULL) { \
1092 if (st->name != NULL) { res = st->name; break; } \
1093 st = pxsltNextImport(st); \
1094 }}
1095
1096#undef XSLT_GET_IMPORT_INT
1097#define XSLT_GET_IMPORT_INT(res, style, name) { \
1098 xsltStylesheetPtr st = style; \
1099 res = -1; \
1100 while (st != NULL) { \
1101 if (st->name != -1) { res = st->name; break; } \
1102 st = pxsltNextImport(st); \
1103 }}
1104
1105static void transform_write_xmldecl(xmlDocPtr result, xsltStylesheetPtr style, BOOL omit_encoding, xmlOutputBufferPtr output)
1106{
1107 int omit_xmldecl, standalone;
1108
1109 XSLT_GET_IMPORT_INT(omit_xmldecl, style, omitXmlDeclaration);
1110 if (omit_xmldecl == 1) return;
1111
1112 XSLT_GET_IMPORT_INT(standalone, style, standalone);
1113
1114 xmlOutputBufferWriteString(output, "<?xml version=");
1115 if (result->version)
1116 {
1117 xmlOutputBufferWriteString(output, "\"");
1118 xmlOutputBufferWriteString(output, (const char *)result->version);
1119 xmlOutputBufferWriteString(output, "\"");
1120 }
1121 else
1122 xmlOutputBufferWriteString(output, "\"1.0\"");
1123
1124 if (!omit_encoding)
1125 {
1126 const xmlChar *encoding;
1127
1128 /* default encoding is UTF-16 */
1130 xmlOutputBufferWriteString(output, " encoding=");
1131 xmlOutputBufferWriteString(output, "\"");
1132 xmlOutputBufferWriteString(output, encoding ? (const char *)encoding : "UTF-16");
1133 xmlOutputBufferWriteString(output, "\"");
1134 }
1135
1136 /* standalone attribute */
1137 if (standalone != -1)
1138 xmlOutputBufferWriteString(output, standalone == 0 ? " standalone=\"no\"" : " standalone=\"yes\"");
1139
1140 xmlOutputBufferWriteString(output, "?>");
1141}
1142
1143static void htmldtd_dumpcontent(xmlOutputBufferPtr buf, xmlDocPtr doc)
1144{
1145 xmlDtdPtr cur = doc->intSubset;
1146
1147 xmlOutputBufferWriteString(buf, "<!DOCTYPE ");
1148 xmlOutputBufferWriteString(buf, (const char *)cur->name);
1149 if (cur->ExternalID)
1150 {
1151 xmlOutputBufferWriteString(buf, " PUBLIC ");
1152 xml_write_quotedstring(buf, cur->ExternalID);
1153 if (cur->SystemID)
1154 {
1155 xmlOutputBufferWriteString(buf, " ");
1156 xml_write_quotedstring(buf, cur->SystemID);
1157 }
1158 }
1159 else if (cur->SystemID)
1160 {
1161 xmlOutputBufferWriteString(buf, " SYSTEM ");
1162 xml_write_quotedstring(buf, cur->SystemID);
1163 }
1164 xmlOutputBufferWriteString(buf, ">\n");
1165}
1166
1167/* Duplicates htmlDocContentDumpFormatOutput() the way we need it - doesn't add trailing newline. */
1168static void htmldoc_dumpcontent(xmlOutputBufferPtr buf, xmlDocPtr doc, const char *encoding, int format)
1169{
1171
1172 /* force HTML output */
1173 type = doc->type;
1175 if (doc->intSubset)
1176 htmldtd_dumpcontent(buf, doc);
1177 if (doc->children) {
1178 xmlNodePtr cur = doc->children;
1179 while (cur) {
1180 htmlNodeDumpFormatOutput(buf, doc, cur, encoding, format);
1181 cur = cur->next;
1182 }
1183 }
1184 doc->type = type;
1185}
1186
1187static inline BOOL transform_is_empty_resultdoc(xmlDocPtr result)
1188{
1189 return !result->children || ((result->children->type == XML_DTD_NODE) && !result->children->next);
1190}
1191
1192static inline BOOL transform_is_valid_method(xsltStylesheetPtr style)
1193{
1194 return !style->methodURI || !(style->method && xmlStrEqual(style->method, (const xmlChar *)"xhtml"));
1195}
1196
1197/* Helper to write transformation result to specified output buffer. */
1198static HRESULT node_transform_write(xsltStylesheetPtr style, xmlDocPtr result, BOOL omit_encoding, const char *encoding, xmlOutputBufferPtr output)
1199{
1200 const xmlChar *method;
1201 int indent;
1202
1203 if (!transform_is_valid_method(style))
1204 {
1205 ERR("unknown output method\n");
1206 return E_FAIL;
1207 }
1208
1211
1212 if (!method && (result->type == XML_HTML_DOCUMENT_NODE))
1213 method = (const xmlChar *) "html";
1214
1215 if (method && xmlStrEqual(method, (const xmlChar *)"html"))
1216 {
1217 htmlSetMetaEncoding(result, (const xmlChar *)encoding);
1218 if (indent == -1)
1219 indent = 1;
1220 htmldoc_dumpcontent(output, result, encoding, indent);
1221 }
1222 else if (method && xmlStrEqual(method, (const xmlChar *)"xhtml"))
1223 {
1224 htmlSetMetaEncoding(result, (const xmlChar *) encoding);
1225 htmlDocContentDumpOutput(output, result, encoding);
1226 }
1227 else if (method && xmlStrEqual(method, (const xmlChar *)"text"))
1228 transform_write_text(result, style, output);
1229 else
1230 {
1231 transform_write_xmldecl(result, style, omit_encoding, output);
1232
1233 if (result->children)
1234 {
1235 xmlNodePtr child = result->children;
1236
1237 while (child)
1238 {
1239 xmlNodeDumpOutput(output, result, child, 0, indent == 1, encoding);
1240 if (indent && ((child->type == XML_DTD_NODE) || ((child->type == XML_COMMENT_NODE) && child->next)))
1241 xmlOutputBufferWriteString(output, "\r\n");
1242 child = child->next;
1243 }
1244 }
1245 }
1246
1247 xmlOutputBufferFlush(output);
1248 return S_OK;
1249}
1250
1251/* For BSTR output is always UTF-16, without 'encoding' attribute */
1252static HRESULT node_transform_write_to_bstr(xsltStylesheetPtr style, xmlDocPtr result, BSTR *str)
1253{
1254 HRESULT hr = S_OK;
1255
1256 if (transform_is_empty_resultdoc(result))
1257 *str = SysAllocStringLen(NULL, 0);
1258 else
1259 {
1260 xmlOutputBufferPtr output = xmlAllocOutputBuffer(xmlFindCharEncodingHandler("UTF-16"));
1261 const xmlChar *content;
1262 size_t len;
1263
1264 *str = NULL;
1265 if (!output)
1266 return E_OUTOFMEMORY;
1267
1268 hr = node_transform_write(style, result, TRUE, "UTF-16", output);
1269#ifdef LIBXML2_NEW_BUFFER
1270 content = xmlBufContent(output->conv);
1271 len = xmlBufUse(output->conv);
1272#else
1273 content = xmlBufferContent(output->conv);
1274 len = xmlBufferLength(output->conv);
1275#endif
1276 /* UTF-16 encoder places UTF-16 bom, we don't need it for BSTR */
1277 content += sizeof(WCHAR);
1278 *str = SysAllocStringLen((WCHAR*)content, len/sizeof(WCHAR) - 1);
1279 xmlOutputBufferClose(output);
1280 }
1281
1282 return *str ? hr : E_OUTOFMEMORY;
1283}
1284
1285static HRESULT node_transform_write_to_stream(xsltStylesheetPtr style, xmlDocPtr result, ISequentialStream *stream)
1286{
1287 static const xmlChar *utf16 = (const xmlChar*)"UTF-16";
1288 xmlOutputBufferPtr output;
1289 const xmlChar *encoding;
1290 HRESULT hr;
1291
1292 if (transform_is_empty_resultdoc(result))
1293 {
1294 WARN("empty result document\n");
1295 return S_OK;
1296 }
1297
1298 if (style->methodURI && (!style->method || !xmlStrEqual(style->method, (const xmlChar *) "xhtml")))
1299 {
1300 ERR("unknown output method\n");
1301 return E_FAIL;
1302 }
1303
1304 /* default encoding is UTF-16 */
1306 if (!encoding)
1307 encoding = utf16;
1308
1309 output = xmlOutputBufferCreateIO(transform_to_stream_write, NULL, stream, xmlFindCharEncodingHandler((const char*)encoding));
1310 if (!output)
1311 return E_OUTOFMEMORY;
1312
1313 hr = node_transform_write(style, result, FALSE, (const char*)encoding, output);
1314 xmlOutputBufferClose(output);
1315 return hr;
1316}
1317
1318struct import_buffer
1319{
1320 char *data;
1321 int cur;
1322 int len;
1323};
1324
1325static int XMLCALL import_loader_io_read(void *context, char *out, int len)
1326{
1327 struct import_buffer *buffer = (struct import_buffer *)context;
1328
1329 TRACE("%p, %p, %d\n", context, out, len);
1330
1331 if (buffer->cur == buffer->len)
1332 return 0;
1333
1334 len = min(len, buffer->len - buffer->cur);
1335 memcpy(out, &buffer->data[buffer->cur], len);
1336 buffer->cur += len;
1337
1338 TRACE("read %d\n", len);
1339
1340 return len;
1341}
1342
1343static int XMLCALL import_loader_io_close(void * context)
1344{
1345 struct import_buffer *buffer = (struct import_buffer *)context;
1346
1347 TRACE("%p\n", context);
1348
1349 heap_free(buffer->data);
1351 return 0;
1352}
1353
1354static HRESULT import_loader_onDataAvailable(void *ctxt, char *ptr, DWORD len)
1355{
1357 xmlParserInputBufferPtr inputbuffer;
1358 struct import_buffer *buffer;
1359
1360 buffer = heap_alloc(sizeof(*buffer));
1361
1362 buffer->data = heap_alloc(len);
1363 memcpy(buffer->data, ptr, len);
1364 buffer->cur = 0;
1365 buffer->len = len;
1366
1367 inputbuffer = xmlParserInputBufferCreateIO(import_loader_io_read, import_loader_io_close, buffer,
1369 *input = xmlNewIOInputStream(ctxt, inputbuffer, XML_CHAR_ENCODING_NONE);
1370 if (!*input)
1371 xmlFreeParserInputBuffer(inputbuffer);
1372
1373 return *input ? S_OK : E_FAIL;
1374}
1375
1376static HRESULT xslt_doc_get_uri(const xmlChar *uri, void *_ctxt, xsltLoadType type, IUri **doc_uri)
1377{
1379 IUri *href_uri;
1380 HRESULT hr;
1381 BSTR uriW;
1382
1383 *doc_uri = NULL;
1384
1385 uriW = bstr_from_xmlChar(uri);
1386 hr = CreateUri(uriW, Uri_CREATE_ALLOW_RELATIVE | Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, 0, &href_uri);
1387 SysFreeString(uriW);
1388 if (FAILED(hr))
1389 {
1390 WARN("Failed to create href uri, %#x.\n", hr);
1391 return hr;
1392 }
1393
1394 if (type == XSLT_LOAD_STYLESHEET && style->doc && style->doc->name)
1395 {
1396 IUri *base_uri;
1397 BSTR baseuriW;
1398
1399 baseuriW = bstr_from_xmlChar((xmlChar *)style->doc->name);
1400 hr = CreateUri(baseuriW, Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, 0, &base_uri);
1401 SysFreeString(baseuriW);
1402 if (FAILED(hr))
1403 {
1404 WARN("Failed to create base uri, %#x.\n", hr);
1405 return hr;
1406 }
1407
1408 hr = CoInternetCombineIUri(base_uri, href_uri, 0, doc_uri, 0);
1409 IUri_Release(base_uri);
1410 if (FAILED(hr))
1411 WARN("Failed to combine uris, %#x.\n", hr);
1412 }
1413 else
1414 {
1415 *doc_uri = href_uri;
1416 IUri_AddRef(*doc_uri);
1417 }
1418
1419 IUri_Release(href_uri);
1420
1421 return hr;
1422}
1423
1424xmlDocPtr xslt_doc_default_loader(const xmlChar *uri, xmlDictPtr dict, int options,
1425 void *_ctxt, xsltLoadType type)
1426{
1427 IUri *import_uri = NULL;
1429 xmlParserCtxtPtr pctxt;
1430 xmlDocPtr doc = NULL;
1432 HRESULT hr;
1433 bsc_t *bsc;
1434 BSTR uriW;
1435
1436 TRACE("%s, %p, %#x, %p, %d\n", debugstr_a((const char *)uri), dict, options, _ctxt, type);
1437
1438 pctxt = xmlNewParserCtxt();
1439 if (!pctxt)
1440 return NULL;
1441
1442 if (dict && pctxt->dict)
1443 {
1444 xmlDictFree(pctxt->dict);
1445 pctxt->dict = NULL;
1446 }
1447
1448 if (dict)
1449 {
1450 pctxt->dict = dict;
1451 xmlDictReference(pctxt->dict);
1452 }
1453
1454 xmlCtxtUseOptions(pctxt, options);
1455
1456 hr = xslt_doc_get_uri(uri, _ctxt, type, &import_uri);
1457 if (FAILED(hr))
1458 goto failed;
1459
1460 hr = CreateURLMonikerEx2(NULL, import_uri, &moniker, 0);
1461 if (FAILED(hr))
1462 goto failed;
1463
1464 hr = bind_url(moniker, import_loader_onDataAvailable, &input, &bsc);
1465 IMoniker_Release(moniker);
1466 if (FAILED(hr))
1467 goto failed;
1468
1469 if (FAILED(detach_bsc(bsc)))
1470 goto failed;
1471
1472 if (!input)
1473 goto failed;
1474
1475 inputPush(pctxt, input);
1476 xmlParseDocument(pctxt);
1477
1478 if (pctxt->wellFormed)
1479 {
1480 doc = pctxt->myDoc;
1481 /* Set imported uri, to give nested imports a chance. */
1482 if (IUri_GetPropertyBSTR(import_uri, Uri_PROPERTY_ABSOLUTE_URI, &uriW, 0) == S_OK)
1483 {
1484 doc->name = (char *)xmlchar_from_wcharn(uriW, SysStringLen(uriW), TRUE);
1485 SysFreeString(uriW);
1486 }
1487 }
1488 else
1489 {
1490 doc = NULL;
1491 xmlFreeDoc(pctxt->myDoc);
1492 pctxt->myDoc = NULL;
1493 }
1494
1495failed:
1496 xmlFreeParserCtxt(pctxt);
1497 if (import_uri)
1498 IUri_Release(import_uri);
1499
1500 return doc;
1501}
1502
1503#endif /* SONAME_LIBXSLT */
1504
1505HRESULT node_transform_node_params(const xmlnode *This, IXMLDOMNode *stylesheet, BSTR *p,
1507{
1508#ifdef SONAME_LIBXSLT
1509 xsltStylesheetPtr xsltSS;
1510 xmlDocPtr sheet_doc;
1511 HRESULT hr = S_OK;
1512 xmlnode *sheet;
1513
1514 if (!libxslt_handle) return E_NOTIMPL;
1515 if (!stylesheet || !p) return E_INVALIDARG;
1516
1517 *p = NULL;
1518
1519 sheet = get_node_obj(stylesheet);
1520 if(!sheet) return E_FAIL;
1521
1522 sheet_doc = xmlCopyDoc(sheet->node->doc, 1);
1523 xsltSS = pxsltParseStylesheetDoc(sheet_doc);
1524 if (xsltSS)
1525 {
1526 const char **xslparams = NULL;
1528 unsigned int i;
1529
1530 /* convert our parameter list to libxml2 format */
1531 if (params && params->count)
1532 {
1533 struct xslprocessor_par *par;
1534
1535 i = 0;
1536 xslparams = heap_alloc((params->count*2 + 1)*sizeof(char*));
1537 LIST_FOR_EACH_ENTRY(par, &params->list, struct xslprocessor_par, entry)
1538 {
1539 xslparams[i++] = (char*)xmlchar_from_wchar(par->name);
1540 xslparams[i++] = (char*)xmlchar_from_wchar(par->value);
1541 }
1542 xslparams[i] = NULL;
1543 }
1544
1545 if (xslparams)
1546 {
1547 xsltTransformContextPtr ctxt = pxsltNewTransformContext(xsltSS, This->node->doc);
1548
1549 /* push parameters to user context */
1550 pxsltQuoteUserParams(ctxt, xslparams);
1551 result = pxsltApplyStylesheetUser(xsltSS, This->node->doc, NULL, NULL, NULL, ctxt);
1552 pxsltFreeTransformContext(ctxt);
1553
1554 for (i = 0; i < params->count*2; i++)
1555 heap_free((char*)xslparams[i]);
1556 heap_free(xslparams);
1557 }
1558 else
1559 result = pxsltApplyStylesheet(xsltSS, This->node->doc, NULL);
1560
1561 if (result)
1562 {
1563 if (stream)
1564 hr = node_transform_write_to_stream(xsltSS, result, stream);
1565 else
1566 hr = node_transform_write_to_bstr(xsltSS, result, p);
1568 }
1569
1570 pxsltFreeStylesheet(xsltSS);
1571 }
1572 else
1573 xmlFreeDoc(sheet_doc);
1574
1575 if(!*p) *p = SysAllocStringLen(NULL, 0);
1576
1577 return hr;
1578#else
1579 ERR_(winediag)("libxslt headers were not found at compile time. Expect problems.\n");
1580
1581 return E_NOTIMPL;
1582#endif
1583}
1584
1585HRESULT node_transform_node(const xmlnode *node, IXMLDOMNode *stylesheet, BSTR *p)
1586{
1587 return node_transform_node_params(node, stylesheet, p, NULL, NULL);
1588}
1589
1590HRESULT node_select_nodes(const xmlnode *This, BSTR query, IXMLDOMNodeList **nodes)
1591{
1592 xmlChar* str;
1593 HRESULT hr;
1594
1595 if (!query || !nodes) return E_INVALIDARG;
1596
1597 str = xmlchar_from_wchar(query);
1598 hr = create_selection(This->node, str, nodes);
1599 heap_free(str);
1600
1601 return hr;
1602}
1603
1604HRESULT node_select_singlenode(const xmlnode *This, BSTR query, IXMLDOMNode **node)
1605{
1607 HRESULT hr;
1608
1609 hr = node_select_nodes(This, query, &list);
1610 if (hr == S_OK)
1611 {
1612 hr = IXMLDOMNodeList_nextNode(list, node);
1613 IXMLDOMNodeList_Release(list);
1614 }
1615 return hr;
1616}
1617
1618HRESULT node_get_namespaceURI(xmlnode *This, BSTR *namespaceURI)
1619{
1620 xmlNsPtr ns = This->node->ns;
1621
1622 if(!namespaceURI)
1623 return E_INVALIDARG;
1624
1625 *namespaceURI = NULL;
1626
1627 if (ns && ns->href)
1628 *namespaceURI = bstr_from_xmlChar(ns->href);
1629
1630 TRACE("uri: %s\n", debugstr_w(*namespaceURI));
1631
1632 return *namespaceURI ? S_OK : S_FALSE;
1633}
1634
1635HRESULT node_get_prefix(xmlnode *This, BSTR *prefix)
1636{
1637 xmlNsPtr ns = This->node->ns;
1638
1639 if (!prefix) return E_INVALIDARG;
1640
1641 *prefix = NULL;
1642
1643 if (ns && ns->prefix)
1644 *prefix = bstr_from_xmlChar(ns->prefix);
1645
1646 TRACE("prefix: %s\n", debugstr_w(*prefix));
1647
1648 return *prefix ? S_OK : S_FALSE;
1649}
1650
1651HRESULT node_get_base_name(xmlnode *This, BSTR *name)
1652{
1653 if (!name) return E_INVALIDARG;
1654
1655 *name = bstr_from_xmlChar(This->node->name);
1656 if (!*name) return E_OUTOFMEMORY;
1657
1658 TRACE("returning %s\n", debugstr_w(*name));
1659
1660 return S_OK;
1661}
1662
1663void destroy_xmlnode(xmlnode *This)
1664{
1665 if(This->node)
1666 {
1667 xmlnode_release(This->node);
1668 xmldoc_release(This->node->doc);
1669 }
1670}
1671
1672void init_xmlnode(xmlnode *This, xmlNodePtr node, IXMLDOMNode *node_iface, dispex_static_data_t *dispex_data)
1673{
1674 if(node)
1675 {
1676 xmlnode_add_ref(node);
1677 xmldoc_add_ref(node->doc);
1678 }
1679
1680 This->node = node;
1681 This->iface = node_iface;
1682 This->parent = NULL;
1683
1684 init_dispex(&This->dispex, (IUnknown*)This->iface, dispex_data);
1685}
1686
1687typedef struct {
1688 xmlnode node;
1689 IXMLDOMNode IXMLDOMNode_iface;
1690 LONG ref;
1691} unknode;
1692
1693static inline unknode *unknode_from_IXMLDOMNode(IXMLDOMNode *iface)
1694{
1695 return CONTAINING_RECORD(iface, unknode, IXMLDOMNode_iface);
1696}
1697
1698static HRESULT WINAPI unknode_QueryInterface(
1699 IXMLDOMNode *iface,
1700 REFIID riid,
1701 void** ppvObject )
1702{
1703 unknode *This = unknode_from_IXMLDOMNode( iface );
1704
1705 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1706
1707 if (IsEqualGUID(riid, &IID_IUnknown)) {
1708 *ppvObject = iface;
1709 }else if (IsEqualGUID( riid, &IID_IDispatch) ||
1710 IsEqualGUID( riid, &IID_IXMLDOMNode)) {
1711 *ppvObject = &This->IXMLDOMNode_iface;
1712 }else if(node_query_interface(&This->node, riid, ppvObject)) {
1713 return *ppvObject ? S_OK : E_NOINTERFACE;
1714 }else {
1715 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1716 *ppvObject = NULL;
1717 return E_NOINTERFACE;
1718 }
1719
1720 IUnknown_AddRef((IUnknown*)*ppvObject);
1721 return S_OK;
1722}
1723
1724static ULONG WINAPI unknode_AddRef(
1725 IXMLDOMNode *iface )
1726{
1727 unknode *This = unknode_from_IXMLDOMNode( iface );
1728
1729 return InterlockedIncrement(&This->ref);
1730}
1731
1732static ULONG WINAPI unknode_Release(
1733 IXMLDOMNode *iface )
1734{
1735 unknode *This = unknode_from_IXMLDOMNode( iface );
1736 LONG ref;
1737
1738 ref = InterlockedDecrement( &This->ref );
1739 if(!ref) {
1740 destroy_xmlnode(&This->node);
1741 heap_free(This);
1742 }
1743
1744 return ref;
1745}
1746
1747static HRESULT WINAPI unknode_GetTypeInfoCount(
1748 IXMLDOMNode *iface,
1749 UINT* pctinfo )
1750{
1751 unknode *This = unknode_from_IXMLDOMNode( iface );
1752
1753 TRACE("(%p)->(%p)\n", This, pctinfo);
1754
1755 *pctinfo = 1;
1756
1757 return S_OK;
1758}
1759
1760static HRESULT WINAPI unknode_GetTypeInfo(
1761 IXMLDOMNode *iface,
1762 UINT iTInfo,
1763 LCID lcid,
1764 ITypeInfo** ppTInfo )
1765{
1766 unknode *This = unknode_from_IXMLDOMNode( iface );
1767 HRESULT hr;
1768
1769 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1770
1771 hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
1772
1773 return hr;
1774}
1775
1776static HRESULT WINAPI unknode_GetIDsOfNames(
1777 IXMLDOMNode *iface,
1778 REFIID riid,
1779 LPOLESTR* rgszNames,
1780 UINT cNames,
1781 LCID lcid,
1782 DISPID* rgDispId )
1783{
1784 unknode *This = unknode_from_IXMLDOMNode( iface );
1785
1787 HRESULT hr;
1788
1789 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1790 lcid, rgDispId);
1791
1792 if(!rgszNames || cNames == 0 || !rgDispId)
1793 return E_INVALIDARG;
1794
1796 if(SUCCEEDED(hr))
1797 {
1798 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1799 ITypeInfo_Release(typeinfo);
1800 }
1801
1802 return hr;
1803}
1804
1805static HRESULT WINAPI unknode_Invoke(
1806 IXMLDOMNode *iface,
1807 DISPID dispIdMember,
1808 REFIID riid,
1809 LCID lcid,
1810 WORD wFlags,
1811 DISPPARAMS* pDispParams,
1812 VARIANT* pVarResult,
1813 EXCEPINFO* pExcepInfo,
1814 UINT* puArgErr )
1815{
1816 unknode *This = unknode_from_IXMLDOMNode( iface );
1818 HRESULT hr;
1819
1820 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1821 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1822
1824 if(SUCCEEDED(hr))
1825 {
1826 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMNode_iface, dispIdMember, wFlags, pDispParams,
1827 pVarResult, pExcepInfo, puArgErr);
1828 ITypeInfo_Release(typeinfo);
1829 }
1830
1831 return hr;
1832}
1833
1834static HRESULT WINAPI unknode_get_nodeName(
1835 IXMLDOMNode *iface,
1836 BSTR* p )
1837{
1838 unknode *This = unknode_from_IXMLDOMNode( iface );
1839
1840 FIXME("(%p)->(%p)\n", This, p);
1841
1842 return node_get_nodeName(&This->node, p);
1843}
1844
1845static HRESULT WINAPI unknode_get_nodeValue(
1846 IXMLDOMNode *iface,
1847 VARIANT* value)
1848{
1849 unknode *This = unknode_from_IXMLDOMNode( iface );
1850
1851 FIXME("(%p)->(%p)\n", This, value);
1852
1853 if(!value)
1854 return E_INVALIDARG;
1855
1856 V_VT(value) = VT_NULL;
1857 return S_FALSE;
1858}
1859
1860static HRESULT WINAPI unknode_put_nodeValue(
1861 IXMLDOMNode *iface,
1862 VARIANT value)
1863{
1864 unknode *This = unknode_from_IXMLDOMNode( iface );
1865 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
1866 return E_FAIL;
1867}
1868
1869static HRESULT WINAPI unknode_get_nodeType(
1870 IXMLDOMNode *iface,
1871 DOMNodeType* domNodeType )
1872{
1873 unknode *This = unknode_from_IXMLDOMNode( iface );
1874
1875 FIXME("(%p)->(%p)\n", This, domNodeType);
1876
1877 switch (This->node.node->type)
1878 {
1879 case XML_ELEMENT_NODE:
1880 case XML_ATTRIBUTE_NODE:
1881 case XML_TEXT_NODE:
1884 case XML_ENTITY_NODE:
1885 case XML_PI_NODE:
1886 case XML_COMMENT_NODE:
1887 case XML_DOCUMENT_NODE:
1890 case XML_NOTATION_NODE:
1891 /* we only care about this set of types, libxml2 type values are
1892 exactly what we need */
1893 *domNodeType = (DOMNodeType)This->node.node->type;
1894 break;
1895 default:
1896 *domNodeType = NODE_INVALID;
1897 break;
1898 }
1899
1900 return S_OK;
1901}
1902
1903static HRESULT WINAPI unknode_get_parentNode(
1904 IXMLDOMNode *iface,
1906{
1907 unknode *This = unknode_from_IXMLDOMNode( iface );
1908 FIXME("(%p)->(%p)\n", This, parent);
1909 if (!parent) return E_INVALIDARG;
1910 *parent = NULL;
1911 return S_FALSE;
1912}
1913
1914static HRESULT WINAPI unknode_get_childNodes(
1915 IXMLDOMNode *iface,
1916 IXMLDOMNodeList** outList)
1917{
1918 unknode *This = unknode_from_IXMLDOMNode( iface );
1919
1920 TRACE("(%p)->(%p)\n", This, outList);
1921
1922 return node_get_child_nodes(&This->node, outList);
1923}
1924
1925static HRESULT WINAPI unknode_get_firstChild(
1926 IXMLDOMNode *iface,
1927 IXMLDOMNode** domNode)
1928{
1929 unknode *This = unknode_from_IXMLDOMNode( iface );
1930
1931 TRACE("(%p)->(%p)\n", This, domNode);
1932
1933 return node_get_first_child(&This->node, domNode);
1934}
1935
1936static HRESULT WINAPI unknode_get_lastChild(
1937 IXMLDOMNode *iface,
1938 IXMLDOMNode** domNode)
1939{
1940 unknode *This = unknode_from_IXMLDOMNode( iface );
1941
1942 TRACE("(%p)->(%p)\n", This, domNode);
1943
1944 return node_get_last_child(&This->node, domNode);
1945}
1946
1947static HRESULT WINAPI unknode_get_previousSibling(
1948 IXMLDOMNode *iface,
1949 IXMLDOMNode** domNode)
1950{
1951 unknode *This = unknode_from_IXMLDOMNode( iface );
1952
1953 TRACE("(%p)->(%p)\n", This, domNode);
1954
1955 return node_get_previous_sibling(&This->node, domNode);
1956}
1957
1958static HRESULT WINAPI unknode_get_nextSibling(
1959 IXMLDOMNode *iface,
1960 IXMLDOMNode** domNode)
1961{
1962 unknode *This = unknode_from_IXMLDOMNode( iface );
1963
1964 TRACE("(%p)->(%p)\n", This, domNode);
1965
1966 return node_get_next_sibling(&This->node, domNode);
1967}
1968
1969static HRESULT WINAPI unknode_get_attributes(
1970 IXMLDOMNode *iface,
1971 IXMLDOMNamedNodeMap** attributeMap)
1972{
1973 unknode *This = unknode_from_IXMLDOMNode( iface );
1974
1975 FIXME("(%p)->(%p)\n", This, attributeMap);
1976
1977 return return_null_ptr((void**)attributeMap);
1978}
1979
1980static HRESULT WINAPI unknode_insertBefore(
1981 IXMLDOMNode *iface,
1982 IXMLDOMNode* newNode, VARIANT refChild,
1983 IXMLDOMNode** outOldNode)
1984{
1985 unknode *This = unknode_from_IXMLDOMNode( iface );
1986
1987 FIXME("(%p)->(%p x%d %p)\n", This, newNode, V_VT(&refChild), outOldNode);
1988
1989 return node_insert_before(&This->node, newNode, &refChild, outOldNode);
1990}
1991
1992static HRESULT WINAPI unknode_replaceChild(
1993 IXMLDOMNode *iface,
1994 IXMLDOMNode* newNode,
1995 IXMLDOMNode* oldNode,
1996 IXMLDOMNode** outOldNode)
1997{
1998 unknode *This = unknode_from_IXMLDOMNode( iface );
1999
2000 FIXME("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
2001
2002 return node_replace_child(&This->node, newNode, oldNode, outOldNode);
2003}
2004
2005static HRESULT WINAPI unknode_removeChild(
2006 IXMLDOMNode *iface,
2007 IXMLDOMNode* domNode, IXMLDOMNode** oldNode)
2008{
2009 unknode *This = unknode_from_IXMLDOMNode( iface );
2010 return node_remove_child(&This->node, domNode, oldNode);
2011}
2012
2013static HRESULT WINAPI unknode_appendChild(
2014 IXMLDOMNode *iface,
2015 IXMLDOMNode* newNode, IXMLDOMNode** outNewNode)
2016{
2017 unknode *This = unknode_from_IXMLDOMNode( iface );
2018 return node_append_child(&This->node, newNode, outNewNode);
2019}
2020
2021static HRESULT WINAPI unknode_hasChildNodes(
2022 IXMLDOMNode *iface,
2023 VARIANT_BOOL* pbool)
2024{
2025 unknode *This = unknode_from_IXMLDOMNode( iface );
2026 return node_has_childnodes(&This->node, pbool);
2027}
2028
2029static HRESULT WINAPI unknode_get_ownerDocument(
2030 IXMLDOMNode *iface,
2031 IXMLDOMDocument** domDocument)
2032{
2033 unknode *This = unknode_from_IXMLDOMNode( iface );
2034 return node_get_owner_doc(&This->node, domDocument);
2035}
2036
2037static HRESULT WINAPI unknode_cloneNode(
2038 IXMLDOMNode *iface,
2039 VARIANT_BOOL pbool, IXMLDOMNode** outNode)
2040{
2041 unknode *This = unknode_from_IXMLDOMNode( iface );
2042 return node_clone(&This->node, pbool, outNode );
2043}
2044
2045static HRESULT WINAPI unknode_get_nodeTypeString(
2046 IXMLDOMNode *iface,
2047 BSTR* p)
2048{
2049 unknode *This = unknode_from_IXMLDOMNode( iface );
2050
2051 FIXME("(%p)->(%p)\n", This, p);
2052
2053 return node_get_nodeName(&This->node, p);
2054}
2055
2056static HRESULT WINAPI unknode_get_text(
2057 IXMLDOMNode *iface,
2058 BSTR* p)
2059{
2060 unknode *This = unknode_from_IXMLDOMNode( iface );
2061 return node_get_text(&This->node, p);
2062}
2063
2064static HRESULT WINAPI unknode_put_text(
2065 IXMLDOMNode *iface,
2066 BSTR p)
2067{
2068 unknode *This = unknode_from_IXMLDOMNode( iface );
2069 return node_put_text(&This->node, p);
2070}
2071
2072static HRESULT WINAPI unknode_get_specified(
2073 IXMLDOMNode *iface,
2074 VARIANT_BOOL* isSpecified)
2075{
2076 unknode *This = unknode_from_IXMLDOMNode( iface );
2077 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
2078 *isSpecified = VARIANT_TRUE;
2079 return S_OK;
2080}
2081
2082static HRESULT WINAPI unknode_get_definition(
2083 IXMLDOMNode *iface,
2084 IXMLDOMNode** definitionNode)
2085{
2086 unknode *This = unknode_from_IXMLDOMNode( iface );
2087 FIXME("(%p)->(%p)\n", This, definitionNode);
2088 return E_NOTIMPL;
2089}
2090
2091static HRESULT WINAPI unknode_get_nodeTypedValue(
2092 IXMLDOMNode *iface,
2093 VARIANT* var1)
2094{
2095 unknode *This = unknode_from_IXMLDOMNode( iface );
2096 FIXME("(%p)->(%p)\n", This, var1);
2097 return return_null_var(var1);
2098}
2099
2100static HRESULT WINAPI unknode_put_nodeTypedValue(
2101 IXMLDOMNode *iface,
2102 VARIANT typedValue)
2103{
2104 unknode *This = unknode_from_IXMLDOMNode( iface );
2105 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
2106 return E_NOTIMPL;
2107}
2108
2109static HRESULT WINAPI unknode_get_dataType(
2110 IXMLDOMNode *iface,
2111 VARIANT* var1)
2112{
2113 unknode *This = unknode_from_IXMLDOMNode( iface );
2114 TRACE("(%p)->(%p)\n", This, var1);
2115 return return_null_var(var1);
2116}
2117
2118static HRESULT WINAPI unknode_put_dataType(
2119 IXMLDOMNode *iface,
2120 BSTR p)
2121{
2122 unknode *This = unknode_from_IXMLDOMNode( iface );
2123
2124 FIXME("(%p)->(%s)\n", This, debugstr_w(p));
2125
2126 if(!p)
2127 return E_INVALIDARG;
2128
2129 return E_FAIL;
2130}
2131
2132static HRESULT WINAPI unknode_get_xml(
2133 IXMLDOMNode *iface,
2134 BSTR* p)
2135{
2136 unknode *This = unknode_from_IXMLDOMNode( iface );
2137
2138 FIXME("(%p)->(%p)\n", This, p);
2139
2140 return node_get_xml(&This->node, FALSE, p);
2141}
2142
2143static HRESULT WINAPI unknode_transformNode(
2144 IXMLDOMNode *iface,
2145 IXMLDOMNode* domNode, BSTR* p)
2146{
2147 unknode *This = unknode_from_IXMLDOMNode( iface );
2148 return node_transform_node(&This->node, domNode, p);
2149}
2150
2151static HRESULT WINAPI unknode_selectNodes(
2152 IXMLDOMNode *iface,
2153 BSTR p, IXMLDOMNodeList** outList)
2154{
2155 unknode *This = unknode_from_IXMLDOMNode( iface );
2156 return node_select_nodes(&This->node, p, outList);
2157}
2158
2159static HRESULT WINAPI unknode_selectSingleNode(
2160 IXMLDOMNode *iface,
2161 BSTR p, IXMLDOMNode** outNode)
2162{
2163 unknode *This = unknode_from_IXMLDOMNode( iface );
2164 return node_select_singlenode(&This->node, p, outNode);
2165}
2166
2167static HRESULT WINAPI unknode_get_parsed(
2168 IXMLDOMNode *iface,
2169 VARIANT_BOOL* isParsed)
2170{
2171 unknode *This = unknode_from_IXMLDOMNode( iface );
2172 FIXME("(%p)->(%p) stub!\n", This, isParsed);
2173 *isParsed = VARIANT_TRUE;
2174 return S_OK;
2175}
2176
2177static HRESULT WINAPI unknode_get_namespaceURI(
2178 IXMLDOMNode *iface,
2179 BSTR* p)
2180{
2181 unknode *This = unknode_from_IXMLDOMNode( iface );
2182 TRACE("(%p)->(%p)\n", This, p);
2183 return node_get_namespaceURI(&This->node, p);
2184}
2185
2186static HRESULT WINAPI unknode_get_prefix(
2187 IXMLDOMNode *iface,
2188 BSTR* p)
2189{
2190 unknode *This = unknode_from_IXMLDOMNode( iface );
2191 return node_get_prefix(&This->node, p);
2192}
2193
2194static HRESULT WINAPI unknode_get_baseName(
2195 IXMLDOMNode *iface,
2196 BSTR* p)
2197{
2198 unknode *This = unknode_from_IXMLDOMNode( iface );
2199 return node_get_base_name(&This->node, p);
2200}
2201
2202static HRESULT WINAPI unknode_transformNodeToObject(
2203 IXMLDOMNode *iface,
2204 IXMLDOMNode* domNode, VARIANT var1)
2205{
2206 unknode *This = unknode_from_IXMLDOMNode( iface );
2207 FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1));
2208 return E_NOTIMPL;
2209}
2210
2211static const struct IXMLDOMNodeVtbl unknode_vtbl =
2212{
2213 unknode_QueryInterface,
2214 unknode_AddRef,
2215 unknode_Release,
2216 unknode_GetTypeInfoCount,
2217 unknode_GetTypeInfo,
2218 unknode_GetIDsOfNames,
2219 unknode_Invoke,
2220 unknode_get_nodeName,
2221 unknode_get_nodeValue,
2222 unknode_put_nodeValue,
2223 unknode_get_nodeType,
2224 unknode_get_parentNode,
2225 unknode_get_childNodes,
2226 unknode_get_firstChild,
2227 unknode_get_lastChild,
2228 unknode_get_previousSibling,
2229 unknode_get_nextSibling,
2230 unknode_get_attributes,
2231 unknode_insertBefore,
2232 unknode_replaceChild,
2233 unknode_removeChild,
2234 unknode_appendChild,
2235 unknode_hasChildNodes,
2236 unknode_get_ownerDocument,
2237 unknode_cloneNode,
2238 unknode_get_nodeTypeString,
2239 unknode_get_text,
2240 unknode_put_text,
2241 unknode_get_specified,
2242 unknode_get_definition,
2243 unknode_get_nodeTypedValue,
2244 unknode_put_nodeTypedValue,
2245 unknode_get_dataType,
2246 unknode_put_dataType,
2247 unknode_get_xml,
2248 unknode_transformNode,
2249 unknode_selectNodes,
2250 unknode_selectSingleNode,
2251 unknode_get_parsed,
2252 unknode_get_namespaceURI,
2253 unknode_get_prefix,
2254 unknode_get_baseName,
2255 unknode_transformNodeToObject
2256};
2257
2259{
2260 IUnknown *pUnk;
2262 HRESULT hr;
2263
2264 if ( !node )
2265 return NULL;
2266
2267 TRACE("type %d\n", node->type);
2268 switch(node->type)
2269 {
2270 case XML_ELEMENT_NODE:
2272 break;
2273 case XML_ATTRIBUTE_NODE:
2274 pUnk = create_attribute( node, FALSE );
2275 break;
2276 case XML_TEXT_NODE:
2277 pUnk = create_text( node );
2278 break;
2280 pUnk = create_cdata( node );
2281 break;
2283 pUnk = create_doc_entity_ref( node );
2284 break;
2285 case XML_PI_NODE:
2286 pUnk = create_pi( node );
2287 break;
2288 case XML_COMMENT_NODE:
2289 pUnk = create_comment( node );
2290 break;
2291 case XML_DOCUMENT_NODE:
2292 pUnk = create_domdoc( node );
2293 break;
2295 pUnk = create_doc_fragment( node );
2296 break;
2297 case XML_DTD_NODE:
2299 pUnk = create_doc_type( node );
2300 break;
2301 case XML_ENTITY_NODE:
2302 case XML_NOTATION_NODE: {
2303 unknode *new_node;
2304
2305 FIXME("only creating basic node for type %d\n", node->type);
2306
2307 new_node = heap_alloc(sizeof(unknode));
2308 if(!new_node)
2309 return NULL;
2310
2311 new_node->IXMLDOMNode_iface.lpVtbl = &unknode_vtbl;
2312 new_node->ref = 1;
2313 init_xmlnode(&new_node->node, node, &new_node->IXMLDOMNode_iface, NULL);
2314 pUnk = (IUnknown*)&new_node->IXMLDOMNode_iface;
2315 break;
2316 }
2317 default:
2318 ERR("Called for unsupported node type %d\n", node->type);
2319 return NULL;
2320 }
2321
2322 hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
2323 IUnknown_Release(pUnk);
2324 if(FAILED(hr)) return NULL;
2325 return ret;
2326}
2327#endif
void xsltCleanupGlobals(void)
Definition: extensions.c:2270
#define isspace(c)
Definition: acclib.h:69
Arabic default style
Definition: afstyles.h:94
HRESULT get_typeinfo(enum type_id tid, ITypeInfo **ret)
Definition: apps.c:124
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
const GUID IID_IUnknown
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
HRESULT detach_bsc(bsc_t *bsc)
Definition: bsc.c:331
HRESULT bind_url(IMoniker *mon, HRESULT(*onDataAvailable)(void *, char *, DWORD), void *obj, bsc_t **ret)
Definition: bsc.c:288
Definition: list.h:37
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
xsltTransformContextPtr xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc)
Definition: transform.c:536
xmlDocPtr xsltApplyStylesheetUser(xsltStylesheetPtr style, xmlDocPtr doc, const char **params, const char *output, FILE *profile, xsltTransformContextPtr userCtxt)
Definition: transform.c:6187
xmlDocPtr xsltApplyStylesheet(xsltStylesheetPtr style, xmlDocPtr doc, const char **params)
Definition: transform.c:6144
void xsltFreeTransformContext(xsltTransformContextPtr ctxt)
Definition: transform.c:689
content
Definition: atl_ax.c:994
static const WCHAR indent[]
Definition: object.c:1156
OLECHAR * BSTR
Definition: compat.h:2293
#define WINE_DECLARE_DEBUG_CHANNEL(x)
Definition: compat.h:45
short VARIANT_BOOL
Definition: compat.h:2290
@ VT_BSTR
Definition: compat.h:2303
@ VT_NULL
Definition: compat.h:2296
@ VT_UNKNOWN
Definition: compat.h:2308
@ VT_EMPTY
Definition: compat.h:2295
@ VT_DISPATCH
Definition: compat.h:2304
static HRESULT WINAPI SupportErrorInfo_InterfaceSupportsErrorInfo(ISupportErrorInfo *iface, REFIID riid)
Definition: htmldoc.c:3971
static ULONG WINAPI SupportErrorInfo_AddRef(ISupportErrorInfo *iface)
Definition: htmldoc.c:3959
static HTMLDocument * impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
Definition: htmldoc.c:3948
static HRESULT WINAPI SupportErrorInfo_QueryInterface(ISupportErrorInfo *iface, REFIID riid, void **ppv)
Definition: htmldoc.c:3953
static ULONG WINAPI SupportErrorInfo_Release(ISupportErrorInfo *iface)
Definition: htmldoc.c:3965
static const ISupportErrorInfoVtbl SupportErrorInfoVtbl
Definition: htmldoc.c:3977
static const IID * get_riid_from_tid(tid_t tid)
Definition: automation.c:83
const WCHAR * text
Definition: package.c:1799
HRESULT WINAPI CoInternetCombineIUri(IUri *pBaseUri, IUri *pRelativeUri, DWORD dwCombineFlags, IUri **ppCombinedUri, DWORD_PTR dwReserved)
Definition: uri.c:6716
HRESULT WINAPI CreateUri(LPCWSTR pwzURI, DWORD dwFlags, DWORD_PTR dwReserved, IUri **ppURI)
Definition: uri.c:5700
xsltLoadType
Definition: documents.h:53
@ XSLT_LOAD_STYLESHEET
Definition: documents.h:55
static void *static void *static LPDIRECTPLAY IUnknown * pUnk
Definition: dplayx.c:30
method
Definition: dragdrop.c:54
r parent
Definition: btrfs.c:3010
@ NODE_INVALID
Definition: shared.h:244
XMLPUBFUN xmlCharEncodingHandlerPtr XMLCALL xmlFindCharEncodingHandler(const char *name)
Definition: encoding.c:1678
@ XML_CHAR_ENCODING_NONE
Definition: encoding.h:58
XMLPUBFUN xmlChar *XMLCALL xmlEncodeSpecialChars(const xmlDoc *doc, const xmlChar *input)
XMLPUBFUN xmlChar *XMLCALL xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input)
#define XMLCALL
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
FxCollectionEntry * cur
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
GLsizeiptr size
Definition: glext.h:5919
GLuint buffer
Definition: glext.h:5915
GLenum const GLfloat * params
Definition: glext.h:5645
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
const GLint * first
Definition: glext.h:5794
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLenum GLenum GLenum input
Definition: glext.h:9031
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HRESULT create_element(HTMLDocumentNode *doc, const WCHAR *tag, HTMLElement **ret)
Definition: htmlelem.c:275
static HRESULT create_node(HTMLDocumentNode *, nsIDOMNode *, HTMLDOMNode **)
Definition: htmlnode.c:1216
HRESULT get_node(HTMLDocumentNode *This, nsIDOMNode *nsnode, BOOL create, HTMLDOMNode **ret)
Definition: htmlnode.c:1339
static HTMLDOMNode * get_node_obj(IHTMLDOMNode *)
Definition: htmlnode.c:1045
tid_t
Definition: ieframe.h:311
xsltStylesheetPtr xsltNextImport(xsltStylesheetPtr cur)
Definition: imports.c:251
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
char * trim(char *str, char **last_chr, BOOL strip_quotes)
Definition: inf.c:258
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
uint32_t entry
Definition: isohybrid.c:63
HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *prototype)
Definition: dispex.c:919
#define debugstr_guid
Definition: kernel32.h:35
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
if(dx< 0)
Definition: linetemp.h:194
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define for
Definition: utility.h:88
char string[160]
Definition: util.h:11
static PVOID ptr
Definition: dispmode.c:27
const char * var
Definition: shader.c:5666
static const char * debugstr_variant(const VARIANT *var)
Definition: container.c:46
static UINT UINT last
Definition: font.c:45
HRESULT hres
Definition: protocol.c:465
static TfClientId tid
static HGLOBAL create_text(void)
Definition: clipboard.c:1496
static LPOLESTR
Definition: stg_prop.c:27
static VARIANTARG static DISPID
Definition: ordinal.c:52
const char * uri
Definition: sec_mgr.c:1588
static IBindStatusCallbackEx bsc
Definition: url.c:2150
static HWND child
Definition: cursoricon.c:298
#define min(a, b)
Definition: monoChain.cc:55
BOOL dispex_query_interface(DispatchEx *This, REFIID riid, void **ppv)
Definition: dispex.c:1656
#define NODE_PRIV_TRAILING_IGNORABLE_WS
@ IXMLDOMNode_tid
Definition: msxml_private.h:58
@ NULL_tid
Definition: msxml_private.h:45
static HRESULT return_null_var(VARIANT *p)
static HRESULT return_null_ptr(void **p)
#define NODE_PRIV_REFCOUNT_MASK
#define NODE_PRIV_CHILD_IGNORABLE_WS
unsigned int UINT
Definition: ndis.h:50
UINT WINAPI SysStringByteLen(BSTR str)
Definition: oleaut.c:215
UINT WINAPI SysStringLen(BSTR str)
Definition: oleaut.c:196
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len)
Definition: oleaut.c:339
#define V_UNKNOWN(A)
Definition: oleauto.h:281
#define V_VT(A)
Definition: oleauto.h:211
#define V_BSTR(A)
Definition: oleauto.h:226
const GUID IID_IDispatch
XMLPUBFUN int XMLCALL inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
Definition: parser.c:1745
long LONG
Definition: pedump.c:60
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define REFIID
Definition: guiddef.h:118
static FILE * out
Definition: regtests2xml.c:44
#define list
Definition: rosglue.h:35
const WCHAR * str
#define MAKE_FUNCPTR(f)
DWORD LCID
Definition: nls.h:13
#define ERR_(ch,...)
Definition: debug.h:156
XMLPUBFUN void XMLCALL xmlDictFree(xmlDictPtr dict)
Definition: dict.c:802
XMLPUBFUN int XMLCALL xmlDictReference(xmlDictPtr dict)
Definition: dict.c:647
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:251
XMLPUBFUN xmlParserInputPtr XMLCALL xmlNewIOInputStream(xmlParserCtxtPtr ctxt, xmlParserInputBufferPtr input, xmlCharEncoding enc)
XMLPUBFUN int XMLCALL xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
Definition: parser.c:15141
XMLPUBFUN void XMLCALL xmlFreeParserCtxt(xmlParserCtxtPtr ctxt)
XMLPUBFUN int XMLCALL xmlParseDocument(xmlParserCtxtPtr ctxt)
Definition: parser.c:10697
XMLPUBFUN xmlParserCtxtPtr XMLCALL xmlNewParserCtxt(void)
XMLPUBFUN xmlNodePtr XMLCALL xmlAddChild(xmlNodePtr parent, xmlNodePtr cur)
XMLPUBFUN void XMLCALL xmlBufferFree(xmlBufferPtr buf)
XMLPUBFUN xmlChar *XMLCALL xmlNodeGetContent(const xmlNode *cur)
XMLPUBFUN void XMLCALL xmlFreeDoc(xmlDocPtr cur)
xmlOutputBuffer * xmlOutputBufferPtr
Definition: tree.h:32
XMLPUBFUN xmlNodePtr XMLCALL xmlCopyNode(xmlNodePtr node, int recursive)
XMLPUBFUN size_t XMLCALL xmlBufUse(const xmlBufPtr buf)
Definition: buf.c:633
xmlElementType
Definition: tree.h:159
@ XML_DOCUMENT_TYPE_NODE
Definition: tree.h:169
@ XML_ATTRIBUTE_NODE
Definition: tree.h:161
@ XML_ENTITY_DECL
Definition: tree.h:176
@ XML_DOCUMENT_NODE
Definition: tree.h:168
@ XML_CDATA_SECTION_NODE
Definition: tree.h:163
@ XML_TEXT_NODE
Definition: tree.h:162
@ XML_ENTITY_NODE
Definition: tree.h:165
@ XML_PI_NODE
Definition: tree.h:166
@ XML_DOCUMENT_FRAG_NODE
Definition: tree.h:170
@ XML_COMMENT_NODE
Definition: tree.h:167
@ XML_DTD_NODE
Definition: tree.h:173
@ XML_HTML_DOCUMENT_NODE
Definition: tree.h:172
@ XML_ELEMENT_NODE
Definition: tree.h:160
@ XML_ENTITY_REF_NODE
Definition: tree.h:164
@ XML_NOTATION_NODE
Definition: tree.h:171
XMLPUBFUN void XMLCALL xmlUnlinkNode(xmlNodePtr cur)
XMLPUBFUN xmlBufferPtr XMLCALL xmlBufferCreate(void)
XMLPUBFUN void XMLCALL xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc)
XMLPUBFUN void XMLCALL xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content)
XMLPUBFUN const xmlChar *XMLCALL xmlBufferContent(const xmlBuffer *buf)
XMLPUBFUN void XMLCALL xmlFreeNode(xmlNodePtr cur)
XMLPUBFUN int XMLCALL xmlBufferLength(const xmlBuffer *buf)
XMLPUBFUN xmlChar *XMLCALL xmlBufContent(const xmlBuf *buf)
Definition: buf.c:553
#define XSLT_GET_IMPORT_INT(res, style, name)
Definition: imports.h:40
#define XSLT_GET_IMPORT_PTR(res, style, name)
Definition: imports.h:27
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
Definition: tree.h:434
struct _xmlAttr * next
Definition: tree.h:441
Definition: dict.c:111
Definition: tree.h:551
char * name
Definition: tree.h:554
struct _xmlDtd * intSubset
Definition: tree.h:570
struct _xmlNode * children
Definition: tree.h:555
xmlElementType type
Definition: tree.h:553
struct _xmlDoc * doc
Definition: tree.h:560
Definition: tree.h:406
Definition: tree.h:489
struct _xmlDoc * doc
Definition: tree.h:498
struct _xmlNode * parent
Definition: tree.h:495
Definition: tree.h:389
int wellFormed
Definition: parser.h:188
xmlDocPtr myDoc
Definition: parser.h:187
xmlDictPtr dict
Definition: parser.h:263
Definition: bsc.c:46
Definition: http.c:7252
Definition: main.c:40
Definition: name.c:39
Definition: mxnamespace.c:45
BSTR prefix
Definition: mxnamespace.c:46
Definition: send.c:48
Definition: parse.h:23
__inline int before(__u32 seq1, __u32 seq2)
Definition: tcpcore.h:2390
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
HRESULT WINAPI CreateURLMonikerEx2(IMoniker *pmkContext, IUri *pUri, IMoniker **ppmk, DWORD dwFlags)
Definition: umon.c:668
Definition: dlist.c:348
Definition: pdh_main.c:94
int xsltQuoteUserParams(xsltTransformContextPtr ctxt, const char **params)
Definition: variables.c:1692
HRESULT WINAPI DECLSPEC_HOTPATCH VariantChangeType(VARIANTARG *pvargDest, VARIANTARG *pvargSrc, USHORT wFlags, VARTYPE vt)
Definition: variant.c:962
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:648
void WINAPI VariantInit(VARIANTARG *pVarg)
Definition: variant.c:568
int ret
_In_ DWORD _Out_ _In_ WORD wFlags
Definition: wincon.h:531
_In_ void _In_ PCCERT_CONTEXT _In_opt_ LPFILETIME _In_ DWORD _In_ DWORD _Outptr_opt_ void ** ppvObject
Definition: wincrypt.h:6082
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:2357
#define E_NOINTERFACE
Definition: winerror.h:2364
XMLPUBFUN void XMLCALL xmlFreeParserInputBuffer(xmlParserInputBufferPtr in)
XMLPUBFUN xmlParserInputBufferPtr XMLCALL xmlParserInputBufferCreateIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, void *ioctx, xmlCharEncoding enc)
enum tagDOMNodeType DOMNodeType
@ NODE_ATTRIBUTE
Definition: xmldom.idl:54
static char * encoding
Definition: xmllint.c:155
__wchar_t WCHAR
Definition: xmlstorage.h:180
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
XMLPUBFUN const xmlChar *XMLCALL xmlStrchr(const xmlChar *str, xmlChar val)
Definition: xmlstring.c:325
XMLPUBFUN xmlChar *XMLCALL xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:42
XMLPUBFUN xmlChar *XMLCALL xmlStrcat(xmlChar *cur, const xmlChar *add)
Definition: xmlstring.c:524
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:67
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:160
XMLPUBFUN int XMLCALL xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:426
unsigned char xmlChar
Definition: xmlstring.h:28
xsltStylesheet * xsltStylesheetPtr
void xsltFreeStylesheet(xsltStylesheetPtr style)
Definition: xslt.c:950
xsltStylesheetPtr xsltParseStylesheetDoc(xmlDocPtr doc)
Definition: xslt.c:6695
int xsltSaveResultTo(xmlOutputBufferPtr buf, xmlDocPtr result, xsltStylesheetPtr style)
Definition: xsltutils.c:1460