ReactOS  0.4.15-dev-3745-g356babc
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>
29 # include <libxml/parserInternals.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>
42 # include <libxslt/xsltInternals.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
63 extern void* libxslt_handle;
64 # define MAKE_FUNCPTR(f) extern typeof(f) * p##f
75 # undef MAKE_FUNCPTR
76 #else
78 #endif
79 
80 static const IID IID_xmlnode = {0x4f2f4ba2,0xb822,0x11df,{0x8b,0x8a,0x68,0x50,0xdf,0xd7,0x20,0x85}};
81 
82 xmlNodePtr 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 
96 BOOL 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 */
108 typedef struct {
109  ISupportErrorInfo ISupportErrorInfo_iface;
110  LONG ref;
111 
112  const tid_t* iids;
113 } SupportErrorInfo;
114 
115 static 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)
152  heap_free(This);
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 
175 static const struct ISupportErrorInfoVtbl SupportErrorInfoVtbl = {
180 };
181 
182 HRESULT 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 
198 xmlnode *get_node_obj(IXMLDOMNode *node)
199 {
200  xmlnode *obj = NULL;
201  HRESULT hres;
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 
208 HRESULT 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 
241 HRESULT node_get_content(xmlnode *This, VARIANT *value)
242 {
243  xmlChar *content;
244 
245  if(!value)
246  return E_INVALIDARG;
247 
248  content = xmlNodeGetContent(This->node);
249  V_VT(value) = VT_BSTR;
250  V_BSTR(value) = bstr_from_xmlChar( content );
251  xmlFree(content);
252 
253  TRACE("%p returned %s\n", This, debugstr_w(V_BSTR(value)));
254  return S_OK;
255 }
256 
257 HRESULT 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 
271 static 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 
295 HRESULT 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 
319 HRESULT 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 
343 static 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 
364 HRESULT node_get_parent(xmlnode *This, IXMLDOMNode **parent)
365 {
366  return get_node( This, "parent", This->node->parent, parent );
367 }
368 
369 HRESULT 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 
381 HRESULT node_get_first_child(xmlnode *This, IXMLDOMNode **ret)
382 {
383  return get_node(This, "firstChild", This->node->children, ret);
384 }
385 
386 HRESULT node_get_last_child(xmlnode *This, IXMLDOMNode **ret)
387 {
388  return get_node(This, "lastChild", This->node->last, ret);
389 }
390 
391 HRESULT node_get_previous_sibling(xmlnode *This, IXMLDOMNode **ret)
392 {
393  return get_node(This, "previous", This->node->prev, ret);
394 }
395 
396 HRESULT node_get_next_sibling(xmlnode *This, IXMLDOMNode **ret)
397 {
398  return get_node(This, "next", This->node->next, ret);
399 }
400 
401 static 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 
429 int 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 */
436 void xmlnode_add_ref(xmlNodePtr node)
437 {
438  if (node->type == XML_DOCUMENT_NODE) return;
439  InterlockedIncrement((LONG*)&node->_private);
440 }
441 
442 void xmlnode_release(xmlNodePtr node)
443 {
444  if (node->type == XML_DOCUMENT_NODE) return;
445  InterlockedDecrement((LONG*)&node->_private);
446 }
447 
448 HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT *ref_child,
449  IXMLDOMNode **ret)
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 
559 HRESULT node_replace_child(xmlnode *This, IXMLDOMNode *newChild, IXMLDOMNode *oldChild,
560  IXMLDOMNode **ret)
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 
624 HRESULT 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 
655 HRESULT 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 
670  VariantInit(&var);
671  return IXMLDOMNode_insertBefore(This->iface, child, var, outChild);
672 }
673 
674 HRESULT 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 
688 HRESULT 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 
695 HRESULT node_clone(xmlnode *This, VARIANT_BOOL deep, IXMLDOMNode **cloneNode)
696 {
697  IXMLDOMNode *node;
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 
728 static 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:
769  tmp = xmlNodeGetContent(child);
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;
786  case XML_ENTITY_REF_NODE:
787  case XML_ENTITY_NODE:
788  tmp = xmlNodeGetContent(child);
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:
828  case XML_ENTITY_REF_NODE:
829  case XML_ENTITY_NODE:
830  case XML_DOCUMENT_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 
858 HRESULT node_get_text(const xmlnode *This, BSTR *text)
859 {
860  BSTR str = NULL;
861  xmlChar *content;
862  DWORD first, last;
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);
871  xmlFree(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 
883 HRESULT 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 
901 BSTR 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  */
952 HRESULT 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;
972  BSTR 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 {
983  *ret = SysAllocStringLen(NULL, 0);
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 */
994 static 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 
1037 static 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" */
1045 static 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 
1105 static 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 
1143 static 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. */
1168 static 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 
1187 static inline BOOL transform_is_empty_resultdoc(xmlDocPtr result)
1188 {
1189  return !result->children || ((result->children->type == XML_DTD_NODE) && !result->children->next);
1190 }
1191 
1192 static 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. */
1198 static 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 */
1252 static 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 
1285 static HRESULT node_transform_write_to_stream(xsltStylesheetPtr style, xmlDocPtr result, ISequentialStream *stream)
1286 {
1287  static const xmlChar *utf16 = (const xmlChar*)"UTF-16";
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 
1318 struct import_buffer
1319 {
1320  char *data;
1321  int cur;
1322  int len;
1323 };
1324 
1325 static 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 
1343 static 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);
1350  heap_free(buffer);
1351  return 0;
1352 }
1353 
1354 static 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 
1376 static 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 
1424 xmlDocPtr 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;
1431  IMoniker *moniker;
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 
1495 failed:
1496  xmlFreeParserCtxt(pctxt);
1497  if (import_uri)
1498  IUri_Release(import_uri);
1499 
1500  return doc;
1501 }
1502 
1503 #endif /* SONAME_LIBXSLT */
1504 
1505 HRESULT 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;
1527  xmlDocPtr result;
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);
1567  xmlFreeDoc(result);
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 
1585 HRESULT node_transform_node(const xmlnode *node, IXMLDOMNode *stylesheet, BSTR *p)
1586 {
1587  return node_transform_node_params(node, stylesheet, p, NULL, NULL);
1588 }
1589 
1590 HRESULT 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 
1604 HRESULT 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 
1618 HRESULT 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 
1635 HRESULT 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 
1651 HRESULT 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 
1663 void destroy_xmlnode(xmlnode *This)
1664 {
1665  if(This->node)
1666  {
1667  xmlnode_release(This->node);
1668  xmldoc_release(This->node->doc);
1669  }
1670 }
1671 
1672 void 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 
1687 typedef struct {
1688  xmlnode node;
1689  IXMLDOMNode IXMLDOMNode_iface;
1690  LONG ref;
1691 } unknode;
1692 
1693 static inline unknode *unknode_from_IXMLDOMNode(IXMLDOMNode *iface)
1694 {
1695  return CONTAINING_RECORD(iface, unknode, IXMLDOMNode_iface);
1696 }
1697 
1698 static 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 
1724 static ULONG WINAPI unknode_AddRef(
1725  IXMLDOMNode *iface )
1726 {
1727  unknode *This = unknode_from_IXMLDOMNode( iface );
1728 
1729  return InterlockedIncrement(&This->ref);
1730 }
1731 
1732 static 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 
1747 static 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 
1760 static 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 
1776 static 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 
1805 static 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 
1834 static 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 
1845 static 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 
1860 static 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 
1869 static 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:
1883  case XML_ENTITY_REF_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 
1903 static HRESULT WINAPI unknode_get_parentNode(
1904  IXMLDOMNode *iface,
1905  IXMLDOMNode** parent )
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 
1914 static 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 
1925 static 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 
1936 static 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 
1947 static 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 
1958 static 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 
1969 static 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 
1980 static 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 
1992 static 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 
2005 static 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 
2013 static 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 
2021 static 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 
2029 static 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 
2037 static 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 
2045 static 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 
2056 static 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 
2064 static 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 
2072 static 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 
2082 static 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 
2091 static 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 
2100 static 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 
2109 static 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 
2118 static 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 
2132 static 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 
2143 static 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 
2151 static 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 
2159 static 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 
2167 static 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 
2177 static 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 
2186 static 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 
2194 static 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 
2202 static 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 
2211 static 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;
2261  IXMLDOMNode *ret;
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:
2271  pUnk = create_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;
2282  case XML_ENTITY_REF_NODE:
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 xsltFreeStylesheet(xsltStylesheetPtr style)
Definition: xslt.c:950
const char * var
Definition: shader.c:5666
XMLPUBFUN xmlParserInputPtr XMLCALL xmlNewIOInputStream(xmlParserCtxtPtr ctxt, xmlParserInputBufferPtr input, xmlCharEncoding enc)
XMLPUBFUN xmlChar *XMLCALL xmlEncodeSpecialChars(const xmlDoc *doc, const xmlChar *input)
xmlElementType type
Definition: tree.h:553
#define NODE_PRIV_REFCOUNT_MASK
#define isspace(c)
Definition: acclib.h:69
XMLPUBFUN int XMLCALL xmlDictReference(xmlDictPtr dict)
Definition: dict.c:645
HRESULT WINAPI DECLSPEC_HOTPATCH VariantChangeType(VARIANTARG *pvargDest, VARIANTARG *pvargSrc, USHORT wFlags, VARTYPE vt)
Definition: variant.c:962
Definition: pdh_main.c:93
#define REFIID
Definition: guiddef.h:118
static UCHAR ULONG UCHAR ULONG UCHAR * output
Definition: bcrypt.c:29
#define E_NOINTERFACE
Definition: winerror.h:2364
char * name
Definition: tree.h:554
XMLPUBFUN const xmlChar *XMLCALL xmlBufferContent(const xmlBuffer *buf)
static const WCHAR indent[]
Definition: object.c:1156
XMLPUBFUN xmlChar *XMLCALL xmlBufContent(const xmlBuf *buf)
Definition: buf.c:582
HRESULT hr
Definition: shlfolder.c:183
GLuint64EXT * result
Definition: glext.h:11304
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len)
Definition: oleaut.c:339
struct _xmlDtd * intSubset
Definition: tree.h:570
Definition: http.c:7251
POINT last
Definition: font.c:46
#define TRUE
Definition: types.h:120
const char * uri
Definition: sec_mgr.c:1588
REFIID riid
Definition: precomp.h:44
Definition: tree.h:389
XMLPUBFUN xmlChar *XMLCALL xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:41
xsltStylesheetPtr xsltNextImport(xsltStylesheetPtr cur)
Definition: imports.c:251
xmlElementType
Definition: tree.h:159
const WCHAR * text
Definition: package.c:1834
tid_t
Definition: ieframe.h:311
XMLPUBFUN int XMLCALL xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:425
const GLint * first
Definition: glext.h:5794
#define WARN(fmt,...)
Definition: debug.h:112
XMLPUBFUN void XMLCALL xmlBufferFree(xmlBufferPtr buf)
#define ERR_(ch,...)
Definition: debug.h:156
REFIID LPVOID * ppv
Definition: atlbase.h:39
XMLPUBFUN void XMLCALL xmlFreeParserInputBuffer(xmlParserInputBufferPtr in)
XMLPUBFUN int XMLCALL inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
Definition: parser.c:1752
struct _xmlAttr * next
Definition: tree.h:441
XMLPUBFUN void XMLCALL xmlFreeParserCtxt(xmlParserCtxtPtr ctxt)
GLuint buffer
Definition: glext.h:5915
__inline int before(__u32 seq1, __u32 seq2)
Definition: tcpcore.h:2414
DWORD LCID
Definition: nls.h:13
static HRESULT WINAPI SupportErrorInfo_InterfaceSupportsErrorInfo(ISupportErrorInfo *iface, REFIID riid)
Definition: htmldoc.c:3971
UINT WINAPI SysStringByteLen(BSTR str)
Definition: oleaut.c:215
OLECHAR * BSTR
Definition: compat.h:2152
void WINAPI VariantInit(VARIANTARG *pVarg)
Definition: variant.c:568
if(dx==0 &&dy==0)
Definition: linetemp.h:174
XMLPUBFUN xmlChar *XMLCALL xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input)
XMLPUBFUN const xmlChar *XMLCALL xmlStrchr(const xmlChar *str, xmlChar val)
Definition: xmlstring.c:324
static LPOLESTR
Definition: stg_prop.c:27
#define E_FAIL
Definition: ddrawi.h:102
short VARIANT_BOOL
Definition: compat.h:2149
Definition: send.c:48
static HWND child
Definition: cursoricon.c:298
XMLPUBFUN xmlBufferPtr XMLCALL xmlBufferCreate(void)
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
static void * heap_alloc(size_t len)
Definition: appwiz.h:65
XMLPUBFUN xmlNodePtr XMLCALL xmlCopyNode(xmlNodePtr node, int recursive)
struct _xmlDoc * doc
Definition: tree.h:498
Definition: tree.h:406
GLsizei GLsizei GLuint * obj
Definition: glext.h:6042
struct _xmlDoc * doc
Definition: tree.h:560
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
struct node node
#define XSLT_GET_IMPORT_INT(res, style, name)
Definition: imports.h:40
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
HRESULT WINAPI CoInternetCombineIUri(IUri *pBaseUri, IUri *pRelativeUri, DWORD dwCombineFlags, IUri **ppCombinedUri, DWORD_PTR dwReserved)
Definition: uri.c:6716
XMLPUBFUN xmlParserInputBufferPtr XMLCALL xmlParserInputBufferCreateIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, void *ioctx, xmlCharEncoding enc)
xsltTransformContextPtr xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc)
Definition: transform.c:536
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define FALSE
Definition: types.h:117
GLenum const GLfloat * params
Definition: glext.h:5645
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint base
Definition: 3dtext.c:35
long LONG
Definition: pedump.c:60
xmlOutputBuffer * xmlOutputBufferPtr
Definition: tree.h:32
int xsltSaveResultTo(xmlOutputBufferPtr buf, xmlDocPtr result, xsltStylesheetPtr style)
Definition: xsltutils.c:1423
XMLPUBFUN xmlChar *XMLCALL xmlStrcat(xmlChar *cur, const xmlChar *add)
Definition: xmlstring.c:529
if SUCCEEDED(hr)
#define debugstr_w
Definition: kernel32.h:32
Definition: bsc.c:46
static HRESULT return_null_ptr(void **p)
GLenum GLint ref
Definition: glext.h:6028
#define FIXME(fmt,...)
Definition: debug.h:111
static PVOID ptr
Definition: dispmode.c:27
content
Definition: atl_ax.c:993
static const IID * get_riid_from_tid(tid_t tid)
Definition: automation.c:84
HRESULT detach_bsc(bsc_t *bsc)
Definition: bsc.c:331
#define S_FALSE
Definition: winerror.h:2357
static IBindStatusCallbackEx bsc
Definition: url.c:2150
#define E_INVALIDARG
Definition: ddrawi.h:101
const WCHAR * str
HRESULT bind_url(IMoniker *mon, HRESULT(*onDataAvailable)(void *, char *, DWORD), void *obj, bsc_t **ret)
Definition: bsc.c:288
HRESULT get_typeinfo(enum type_id tid, ITypeInfo **ret)
Definition: apps.c:124
XMLPUBFUN void XMLCALL xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc)
#define BAD_CAST
Definition: xmlstring.h:35
xmlDictPtr dict
Definition: parser.h:265
#define debugstr_guid
Definition: kernel32.h:35
Definition: dict.c:116
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _xmlNode * parent
Definition: tree.h:495
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
HRESULT hres
Definition: protocol.c:465
XMLPUBFUN xmlNodePtr XMLCALL xmlAddChild(xmlNodePtr parent, xmlNodePtr cur)
int wellFormed
Definition: parser.h:190
r parent
Definition: btrfs.c:2944
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define debugstr_a
Definition: kernel32.h:31
LONG HRESULT
Definition: typedefs.h:79
XMLPUBFUN void XMLCALL xmlUnlinkNode(xmlNodePtr cur)
XMLPUBFUN int XMLCALL xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
Definition: parser.c:15133
const GUID IID_IUnknown
static HRESULT create_node(HTMLDocumentNode *, nsIDOMNode *, HTMLDOMNode **)
Definition: htmlnode.c:1216
#define WINAPI
Definition: msvc.h:6
unsigned short WORD
Definition: ntddk_ex.h:93
static FILE * out
Definition: regtests2xml.c:44
#define for
Definition: utility.h:88
unsigned long DWORD
Definition: ntddk_ex.h:95
XMLPUBFUN void XMLCALL xmlFreeDoc(xmlDocPtr cur)
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:250
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
XMLPUBFUN int XMLCALL xmlParseDocument(xmlParserCtxtPtr ctxt)
Definition: parser.c:10689
method
Definition: dragdrop.c:53
Definition: tree.h:489
const GUID IID_IDispatch
int ret
xmlDocPtr myDoc
Definition: parser.h:189
void xsltCleanupGlobals(void)
Definition: extensions.c:2276
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:648
Definition: mxnamespace.c:44
static ITypeInfo * typeinfo[last_tid]
Definition: apps.c:109
XMLPUBFUN xmlCharEncodingHandlerPtr XMLCALL xmlFindCharEncodingHandler(const char *name)
Definition: encoding.c:1660
#define InterlockedDecrement
Definition: armddk.h:52
Definition: parse.h:22
#define V_VT(A)
Definition: oleauto.h:211
HRESULT WINAPI CreateURLMonikerEx2(IMoniker *pmkContext, IUri *pUri, IMoniker **ppmk, DWORD dwFlags)
Definition: umon.c:668
uint32_t entry
Definition: isohybrid.c:63
static HGLOBAL create_text(void)
Definition: clipboard.c:1496
unsigned char xmlChar
Definition: xmlstring.h:28
XMLPUBFUN void XMLCALL xmlDictFree(xmlDictPtr dict)
Definition: dict.c:800
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
#define WINE_DECLARE_DEBUG_CHANNEL(x)
Definition: compat.h:45
Definition: _list.h:228
REFIID LPVOID * ppvObject
Definition: precomp.h:44
UINT WINAPI SysStringLen(BSTR str)
Definition: oleaut.c:196
void xsltFreeTransformContext(xsltTransformContextPtr ctxt)
Definition: transform.c:690
#define V_UNKNOWN(A)
Definition: oleauto.h:281
BSTR prefix
Definition: mxnamespace.c:46
#define V_BSTR(A)
Definition: oleauto.h:226
ed encoding
Definition: write.c:2825
char string[160]
Definition: util.h:11
FxCollectionEntry * cur
_In_ DWORD _Out_ _In_ WORD wFlags
Definition: wincon.h:531
#define ERR(fmt,...)
Definition: debug.h:110
xsltStylesheetPtr xsltParseStylesheetDoc(xmlDocPtr doc)
Definition: xslt.c:6699
XMLPUBFUN void XMLCALL xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content)
struct stdole::EXCEPINFO EXCEPINFO
static const char * debugstr_variant(const VARIANT *var)
Definition: container.c:46
static VARIANTARG static DISPID
Definition: ordinal.c:49
#define S_OK
Definition: intsafe.h:52
XMLPUBFUN int XMLCALL xmlBufferLength(const xmlBuffer *buf)
#define InterlockedIncrement
Definition: armddk.h:53
GLenum GLenum GLenum input
Definition: glext.h:9031
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
static ULONG WINAPI SupportErrorInfo_Release(ISupportErrorInfo *iface)
Definition: htmldoc.c:3965
BOOL dispex_query_interface(DispatchEx *This, REFIID riid, void **ppv)
Definition: dispex.c:1656
XMLPUBFUN xmlChar *XMLCALL xmlNodeGetContent(const xmlNode *cur)
HRESULT get_node(HTMLDocumentNode *This, nsIDOMNode *nsnode, BOOL create, HTMLDOMNode **ret)
Definition: htmlnode.c:1339
#define E_NOTIMPL
Definition: ddrawi.h:99
int xsltQuoteUserParams(xsltTransformContextPtr ctxt, const char **params)
Definition: variables.c:1689
static HRESULT return_null_var(VARIANT *p)
#define NODE_PRIV_CHILD_IGNORABLE_WS
#define list
Definition: rosglue.h:35
#define XSLT_GET_IMPORT_PTR(res, style, name)
Definition: imports.h:27
#define MAKE_FUNCPTR(f)
#define min(a, b)
Definition: monoChain.cc:55
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
Definition: main.c:39
HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *prototype)
Definition: dispex.c:919
Definition: tree.h:551
XMLPUBFUN void XMLCALL xmlFreeNode(xmlNodePtr cur)
static ULONG WINAPI SupportErrorInfo_AddRef(ISupportErrorInfo *iface)
Definition: htmldoc.c:3959
#define XMLCALL
Definition: tree.h:434
Definition: name.c:38
struct stdole::DISPPARAMS DISPPARAMS
static HTMLDocument * impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
Definition: htmldoc.c:3948
HRESULT WINAPI CreateUri(LPCWSTR pwzURI, DWORD dwFlags, DWORD_PTR dwReserved, IUri **ppURI)
Definition: uri.c:5700
unsigned int ULONG
Definition: retypes.h:1
static HRESULT WINAPI SupportErrorInfo_QueryInterface(ISupportErrorInfo *iface, REFIID riid, void **ppv)
Definition: htmldoc.c:3953
struct _xmlNode * children
Definition: tree.h:555
static const ISupportErrorInfoVtbl SupportErrorInfoVtbl
Definition: htmldoc.c:3977
XMLPUBFUN xmlParserCtxtPtr XMLCALL xmlNewParserCtxt(void)
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
__MSXML_DOMNODETYPE_DEFINED enum tagDOMNodeType DOMNodeType
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:159
GLfloat GLfloat p
Definition: glext.h:8902
#define NODE_PRIV_TRAILING_IGNORABLE_WS
xmlDocPtr xsltApplyStylesheet(xsltStylesheetPtr style, xmlDocPtr doc, const char **params)
Definition: transform.c:6247
Arabic default style
Definition: afstyles.h:93
char * trim(char *str, char **last_chr, BOOL strip_quotes)
Definition: inf.c:258
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
HRESULT create_element(HTMLDocumentNode *doc, const WCHAR *tag, HTMLElement **ret)
Definition: htmlelem.c:275
static void *static void *static LPDIRECTPLAY IUnknown * pUnk
Definition: dplayx.c:30
static TfClientId tid
XMLPUBFUN size_t XMLCALL xmlBufUse(const xmlBufPtr buf)
Definition: buf.c:687
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:66
xmlDocPtr xsltApplyStylesheetUser(xsltStylesheetPtr style, xmlDocPtr doc, const char **params, const char *output, FILE *profile, xsltTransformContextPtr userCtxt)
Definition: transform.c:6290
static HTMLDOMNode * get_node_obj(IHTMLDOMNode *)
Definition: htmlnode.c:1045
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
Definition: dlist.c:348
xsltLoadType
Definition: documents.h:53
xsltStylesheet * xsltStylesheetPtr