msxml3: Add IObjectSafety support to IXMLHTTPRequest.
[wine.git] / dlls / msxml3 / node.c
blobfd1cf976d59063795c0d89fe403f7709d7ef3a17
1 /*
2 * Node implementation
4 * Copyright 2005 Mike McCormack
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.
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.
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
21 #include "config.h"
23 #define COBJMACROS
25 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winnls.h"
30 #include "ole2.h"
31 #include "msxml6.h"
33 #include "msxml_private.h"
35 #ifdef HAVE_LIBXML2
36 # include <libxml/HTMLtree.h>
37 #endif
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
43 #ifdef HAVE_LIBXML2
45 /* TODO: get rid of these and use the enum */
46 static const WCHAR szBinBase64[] = {'b','i','n','.','b','a','s','e','6','4',0};
47 static const WCHAR szString[] = {'s','t','r','i','n','g',0};
48 static const WCHAR szNumber[] = {'n','u','m','b','e','r',0};
49 static const WCHAR szInt[] = {'I','n','t',0};
50 static const WCHAR szFixed[] = {'F','i','x','e','d','.','1','4','.','4',0};
51 static const WCHAR szBoolean[] = {'B','o','o','l','e','a','n',0};
52 static const WCHAR szDateTime[] = {'d','a','t','e','T','i','m','e',0};
53 static const WCHAR szDateTimeTZ[] = {'d','a','t','e','T','i','m','e','.','t','z',0};
54 static const WCHAR szDate[] = {'D','a','t','e',0};
55 static const WCHAR szTime[] = {'T','i','m','e',0};
56 static const WCHAR szTimeTZ[] = {'T','i','m','e','.','t','z',0};
57 static const WCHAR szI1[] = {'i','1',0};
58 static const WCHAR szI2[] = {'i','2',0};
59 static const WCHAR szI4[] = {'i','4',0};
60 static const WCHAR szIU1[] = {'u','i','1',0};
61 static const WCHAR szIU2[] = {'u','i','2',0};
62 static const WCHAR szIU4[] = {'u','i','4',0};
63 static const WCHAR szR4[] = {'r','4',0};
64 static const WCHAR szR8[] = {'r','8',0};
65 static const WCHAR szFloat[] = {'f','l','o','a','t',0};
66 static const WCHAR szUUID[] = {'u','u','i','d',0};
67 static const WCHAR szBinHex[] = {'b','i','n','.','h','e','x',0};
69 static const IID IID_xmlnode = {0x4f2f4ba2,0xb822,0x11df,{0x8b,0x8a,0x68,0x50,0xdf,0xd7,0x20,0x85}};
71 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type )
73 xmlnode *This;
75 if ( !iface )
76 return NULL;
77 This = get_node_obj( iface );
78 if ( !This || !This->node )
79 return NULL;
80 if ( type && This->node->type != type )
81 return NULL;
82 return This->node;
85 BOOL node_query_interface(xmlnode *This, REFIID riid, void **ppv)
87 if(IsEqualGUID(&IID_xmlnode, riid)) {
88 TRACE("(%p)->(IID_xmlnode %p)\n", This, ppv);
89 *ppv = This;
90 return TRUE;
93 if(This->dispex.outer)
94 return dispex_query_interface(&This->dispex, riid, ppv);
96 return FALSE;
99 xmlnode *get_node_obj(IXMLDOMNode *node)
101 xmlnode *obj;
102 HRESULT hres;
104 hres = IXMLDOMNode_QueryInterface(node, &IID_xmlnode, (void**)&obj);
105 return SUCCEEDED(hres) ? obj : NULL;
108 static inline xmlnode *impl_from_IXMLDOMNode( IXMLDOMNode *iface )
110 return CONTAINING_RECORD(iface, xmlnode, IXMLDOMNode_iface);
113 HRESULT node_get_nodeName(xmlnode *This, BSTR *name)
115 if (!name)
116 return E_INVALIDARG;
118 *name = bstr_from_xmlChar(This->node->name);
119 if (!*name)
120 return S_FALSE;
122 return S_OK;
125 HRESULT node_get_content(xmlnode *This, VARIANT *value)
127 xmlChar *content;
129 if(!value)
130 return E_INVALIDARG;
132 content = xmlNodeGetContent(This->node);
133 V_VT(value) = VT_BSTR;
134 V_BSTR(value) = bstr_from_xmlChar( content );
135 xmlFree(content);
137 TRACE("%p returned %s\n", This, debugstr_w(V_BSTR(value)));
138 return S_OK;
141 HRESULT node_set_content(xmlnode *This, LPCWSTR value)
143 xmlChar *str;
145 TRACE("(%p)->(%s)\n", This, debugstr_w(value));
146 str = xmlChar_from_wchar(value);
147 if(!str)
148 return E_OUTOFMEMORY;
150 xmlNodeSetContent(This->node, str);
151 heap_free(str);
152 return S_OK;
155 static HRESULT node_set_content_escaped(xmlnode *This, LPCWSTR value)
157 xmlChar *str, *escaped;
159 TRACE("(%p)->(%s)\n", This, debugstr_w(value));
160 str = xmlChar_from_wchar(value);
161 if(!str)
162 return E_OUTOFMEMORY;
164 escaped = xmlEncodeSpecialChars(NULL, str);
165 if(!escaped)
167 heap_free(str);
168 return E_OUTOFMEMORY;
171 xmlNodeSetContent(This->node, escaped);
173 heap_free(str);
174 xmlFree(escaped);
176 return S_OK;
179 HRESULT node_put_value(xmlnode *This, VARIANT *value)
181 VARIANT string_value;
182 HRESULT hr;
184 VariantInit(&string_value);
185 hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
186 if(FAILED(hr)) {
187 WARN("Couldn't convert to VT_BSTR\n");
188 return hr;
191 hr = node_set_content(This, V_BSTR(&string_value));
192 VariantClear(&string_value);
194 return hr;
197 HRESULT node_put_value_escaped(xmlnode *This, VARIANT *value)
199 VARIANT string_value;
200 HRESULT hr;
202 VariantInit(&string_value);
203 hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
204 if(FAILED(hr)) {
205 WARN("Couldn't convert to VT_BSTR\n");
206 return hr;
209 hr = node_set_content_escaped(This, V_BSTR(&string_value));
210 VariantClear(&string_value);
212 return hr;
215 static HRESULT get_node(
216 xmlnode *This,
217 const char *name,
218 xmlNodePtr node,
219 IXMLDOMNode **out )
221 TRACE("(%p)->(%s %p %p)\n", This, name, node, out );
223 if ( !out )
224 return E_INVALIDARG;
226 /* if we don't have a doc, use our parent. */
227 if(node && !node->doc && node->parent)
228 node->doc = node->parent->doc;
230 *out = create_node( node );
231 if (!*out)
232 return S_FALSE;
233 return S_OK;
236 HRESULT node_get_parent(xmlnode *This, IXMLDOMNode **parent)
238 return get_node( This, "parent", This->node->parent, parent );
241 HRESULT node_get_child_nodes(xmlnode *This, IXMLDOMNodeList **ret)
243 if(!ret)
244 return E_INVALIDARG;
246 *ret = create_children_nodelist(This->node);
247 if(!*ret)
248 return E_OUTOFMEMORY;
250 return S_OK;
253 HRESULT node_get_first_child(xmlnode *This, IXMLDOMNode **ret)
255 return get_node(This, "firstChild", This->node->children, ret);
258 HRESULT node_get_last_child(xmlnode *This, IXMLDOMNode **ret)
260 return get_node(This, "lastChild", This->node->last, ret);
263 HRESULT node_get_previous_sibling(xmlnode *This, IXMLDOMNode **ret)
265 return get_node(This, "previous", This->node->prev, ret);
268 HRESULT node_get_next_sibling(xmlnode *This, IXMLDOMNode **ret)
270 return get_node(This, "next", This->node->next, ret);
273 HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT *ref_child,
274 IXMLDOMNode **ret)
276 xmlNodePtr before_node, new_child_node;
277 IXMLDOMNode *before = NULL;
278 xmlnode *node_obj;
279 HRESULT hr;
281 if(!new_child)
282 return E_INVALIDARG;
284 node_obj = get_node_obj(new_child);
285 if(!node_obj) {
286 FIXME("newChild is not our node implementation\n");
287 return E_FAIL;
290 switch(V_VT(ref_child))
292 case VT_EMPTY:
293 case VT_NULL:
294 break;
296 case VT_UNKNOWN:
297 case VT_DISPATCH:
298 hr = IUnknown_QueryInterface(V_UNKNOWN(ref_child), &IID_IXMLDOMNode, (LPVOID)&before);
299 if(FAILED(hr)) return hr;
300 break;
302 default:
303 FIXME("refChild var type %x\n", V_VT(ref_child));
304 return E_FAIL;
307 new_child_node = node_obj->node;
308 TRACE("new_child_node %p This->node %p\n", new_child_node, This->node);
310 if(!new_child_node->parent)
311 if(xmldoc_remove_orphan(new_child_node->doc, new_child_node) != S_OK)
312 WARN("%p is not an orphan of %p\n", new_child_node, new_child_node->doc);
314 if(before)
316 node_obj = get_node_obj(before);
317 IXMLDOMNode_Release(before);
318 if(!node_obj) {
319 FIXME("before node is not our node implementation\n");
320 return E_FAIL;
323 before_node = node_obj->node;
324 xmlAddPrevSibling(before_node, new_child_node);
326 else
328 xmlAddChild(This->node, new_child_node);
331 if(ret) {
332 IXMLDOMNode_AddRef(new_child);
333 *ret = new_child;
336 TRACE("ret S_OK\n");
337 return S_OK;
340 HRESULT node_replace_child(xmlnode *This, IXMLDOMNode *newChild, IXMLDOMNode *oldChild,
341 IXMLDOMNode **ret)
343 xmlnode *old_child, *new_child;
344 xmlDocPtr leaving_doc;
345 xmlNode *my_ancestor;
347 /* Do not believe any documentation telling that newChild == NULL
348 means removal. It does certainly *not* apply to msxml3! */
349 if(!newChild || !oldChild)
350 return E_INVALIDARG;
352 if(ret)
353 *ret = NULL;
355 old_child = get_node_obj(oldChild);
356 if(!old_child) {
357 FIXME("oldChild is not our node implementation\n");
358 return E_FAIL;
361 if(old_child->node->parent != This->node)
363 WARN("childNode %p is not a child of %p\n", oldChild, This);
364 return E_INVALIDARG;
367 new_child = get_node_obj(newChild);
368 if(!new_child) {
369 FIXME("newChild is not our node implementation\n");
370 return E_FAIL;
373 my_ancestor = This->node;
374 while(my_ancestor)
376 if(my_ancestor == new_child->node)
378 WARN("tried to create loop\n");
379 return E_FAIL;
381 my_ancestor = my_ancestor->parent;
384 if(!new_child->node->parent)
385 if(xmldoc_remove_orphan(new_child->node->doc, new_child->node) != S_OK)
386 WARN("%p is not an orphan of %p\n", new_child->node, new_child->node->doc);
388 leaving_doc = new_child->node->doc;
389 xmldoc_add_ref(old_child->node->doc);
390 xmlReplaceNode(old_child->node, new_child->node);
391 xmldoc_release(leaving_doc);
393 xmldoc_add_orphan(old_child->node->doc, old_child->node);
395 if(ret)
397 IXMLDOMNode_AddRef(oldChild);
398 *ret = oldChild;
401 return S_OK;
404 static HRESULT WINAPI xmlnode_removeChild(
405 IXMLDOMNode *iface,
406 IXMLDOMNode* childNode,
407 IXMLDOMNode** oldChild)
409 xmlnode *This = impl_from_IXMLDOMNode( iface );
410 xmlnode *child_node;
412 TRACE("(%p)->(%p %p)\n", This, childNode, oldChild);
414 if(!childNode) return E_INVALIDARG;
416 if(oldChild)
417 *oldChild = NULL;
419 child_node = get_node_obj(childNode);
420 if(!child_node) {
421 FIXME("childNode is not our node implementation\n");
422 return E_FAIL;
425 if(child_node->node->parent != This->node)
427 WARN("childNode %p is not a child of %p\n", childNode, iface);
428 return E_INVALIDARG;
431 xmlUnlinkNode(child_node->node);
433 if(oldChild)
435 IXMLDOMNode_AddRef(childNode);
436 *oldChild = childNode;
439 return S_OK;
442 static HRESULT WINAPI xmlnode_appendChild(
443 IXMLDOMNode *iface,
444 IXMLDOMNode* newChild,
445 IXMLDOMNode** outNewChild)
447 xmlnode *This = impl_from_IXMLDOMNode( iface );
448 DOMNodeType type;
449 VARIANT var;
450 HRESULT hr;
452 TRACE("(%p)->(%p %p)\n", This, newChild, outNewChild);
454 hr = IXMLDOMNode_get_nodeType(newChild, &type);
455 if(FAILED(hr) || type == NODE_ATTRIBUTE) {
456 if(outNewChild) *outNewChild = NULL;
457 return E_FAIL;
460 VariantInit(&var);
461 return IXMLDOMNode_insertBefore(This->iface, newChild, var, outNewChild);
464 static HRESULT WINAPI xmlnode_hasChildNodes(
465 IXMLDOMNode *iface,
466 VARIANT_BOOL* hasChild)
468 xmlnode *This = impl_from_IXMLDOMNode( iface );
470 TRACE("(%p)->(%p)\n", This, hasChild);
472 if (!hasChild)
473 return E_INVALIDARG;
474 if (!This->node->children)
476 *hasChild = VARIANT_FALSE;
477 return S_FALSE;
480 *hasChild = VARIANT_TRUE;
481 return S_OK;
484 static HRESULT WINAPI xmlnode_get_ownerDocument(
485 IXMLDOMNode *iface,
486 IXMLDOMDocument** DOMDocument)
488 xmlnode *This = impl_from_IXMLDOMNode( iface );
490 TRACE("(%p)->(%p)\n", This, DOMDocument);
492 return DOMDocument_create_from_xmldoc(This->node->doc, (IXMLDOMDocument3**)DOMDocument);
495 HRESULT node_clone(xmlnode *This, VARIANT_BOOL deep, IXMLDOMNode **cloneNode)
497 IXMLDOMNode *node;
498 xmlNodePtr clone;
500 if(!cloneNode) return E_INVALIDARG;
502 clone = xmlCopyNode(This->node, deep ? 1 : 2);
503 if (clone)
505 clone->doc = This->node->doc;
506 xmldoc_add_orphan(clone->doc, clone);
508 node = create_node(clone);
509 if (!node)
511 ERR("Copy failed\n");
512 return E_FAIL;
515 *cloneNode = node;
517 else
519 ERR("Copy failed\n");
520 return E_FAIL;
523 return S_OK;
526 static inline xmlChar* trim_whitespace(xmlChar* str)
528 xmlChar* ret = str;
529 int len;
531 if (!str)
532 return NULL;
534 while (*ret && isspace(*ret))
535 ++ret;
536 len = xmlStrlen(ret);
537 if (len)
538 while (isspace(ret[len-1])) --len;
540 ret = xmlStrndup(ret, len);
541 xmlFree(str);
542 return ret;
545 static xmlChar* do_get_text(xmlNodePtr node)
547 xmlNodePtr child;
548 xmlChar* str;
549 BOOL preserving = is_preserving_whitespace(node);
551 if (!node->children)
553 str = xmlNodeGetContent(node);
555 else
557 xmlElementType prev_type = XML_TEXT_NODE;
558 xmlChar* tmp;
559 str = xmlStrdup(BAD_CAST "");
560 for (child = node->children; child != NULL; child = child->next)
562 switch (child->type)
564 case XML_ELEMENT_NODE:
565 tmp = do_get_text(child);
566 break;
567 case XML_TEXT_NODE:
568 case XML_CDATA_SECTION_NODE:
569 case XML_ENTITY_REF_NODE:
570 case XML_ENTITY_NODE:
571 tmp = xmlNodeGetContent(child);
572 break;
573 default:
574 tmp = NULL;
575 break;
578 if (tmp)
580 if (*tmp)
582 if (prev_type == XML_ELEMENT_NODE && child->type == XML_ELEMENT_NODE)
583 str = xmlStrcat(str, BAD_CAST " ");
584 str = xmlStrcat(str, tmp);
585 prev_type = child->type;
587 xmlFree(tmp);
592 switch (node->type)
594 case XML_ELEMENT_NODE:
595 case XML_TEXT_NODE:
596 case XML_ENTITY_REF_NODE:
597 case XML_ENTITY_NODE:
598 case XML_DOCUMENT_NODE:
599 case XML_DOCUMENT_FRAG_NODE:
600 if (!preserving)
601 str = trim_whitespace(str);
602 break;
603 default:
604 break;
607 return str;
610 static HRESULT WINAPI xmlnode_get_text(
611 IXMLDOMNode *iface,
612 BSTR* text)
614 xmlnode *This = impl_from_IXMLDOMNode( iface );
615 BSTR str = NULL;
616 xmlChar *pContent;
618 TRACE("(%p, type %d)->(%p)\n", This, This->node->type, text);
620 if ( !text )
621 return E_INVALIDARG;
623 pContent = do_get_text((xmlNodePtr)This->node);
624 if(pContent)
626 str = bstr_from_xmlChar(pContent);
627 xmlFree(pContent);
630 /* Always return a string. */
631 if (!str) str = SysAllocStringLen( NULL, 0 );
633 TRACE("%p %s\n", This, debugstr_w(str) );
634 *text = str;
636 return S_OK;
639 HRESULT node_put_text(xmlnode *This, BSTR text)
641 xmlChar *str, *str2;
643 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
645 str = xmlChar_from_wchar(text);
647 /* Escape the string. */
648 str2 = xmlEncodeEntitiesReentrant(This->node->doc, str);
649 heap_free(str);
651 xmlNodeSetContent(This->node, str2);
652 xmlFree(str2);
654 return S_OK;
657 static inline BYTE hex_to_byte(xmlChar c)
659 if(c <= '9') return c-'0';
660 if(c <= 'F') return c-'A'+10;
661 return c-'a'+10;
664 static inline BYTE base64_to_byte(xmlChar c)
666 if(c == '+') return 62;
667 if(c == '/') return 63;
668 if(c <= '9') return c-'0'+52;
669 if(c <= 'Z') return c-'A';
670 return c-'a'+26;
673 /* TODO: phasing this version out */
674 static inline HRESULT VARIANT_from_xmlChar(xmlChar *str, VARIANT *v, BSTR type)
676 if(!type || !lstrcmpiW(type, szString) ||
677 !lstrcmpiW(type, szNumber) || !lstrcmpiW(type, szUUID))
679 V_VT(v) = VT_BSTR;
680 V_BSTR(v) = bstr_from_xmlChar(str);
682 if(!V_BSTR(v))
683 return E_OUTOFMEMORY;
685 else if(!lstrcmpiW(type, szDateTime) || !lstrcmpiW(type, szDateTimeTZ) ||
686 !lstrcmpiW(type, szDate) || !lstrcmpiW(type, szTime) ||
687 !lstrcmpiW(type, szTimeTZ))
689 VARIANT src;
690 WCHAR *p, *e;
691 SYSTEMTIME st;
692 DOUBLE date = 0.0;
694 st.wYear = 1899;
695 st.wMonth = 12;
696 st.wDay = 30;
697 st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
699 V_VT(&src) = VT_BSTR;
700 V_BSTR(&src) = bstr_from_xmlChar(str);
702 if(!V_BSTR(&src))
703 return E_OUTOFMEMORY;
705 p = V_BSTR(&src);
706 e = p + SysStringLen(V_BSTR(&src));
708 if(p+4<e && *(p+4)=='-') /* parse date (yyyy-mm-dd) */
710 st.wYear = atoiW(p);
711 st.wMonth = atoiW(p+5);
712 st.wDay = atoiW(p+8);
713 p += 10;
715 if(*p == 'T') p++;
718 if(p+2<e && *(p+2)==':') /* parse time (hh:mm:ss.?) */
720 st.wHour = atoiW(p);
721 st.wMinute = atoiW(p+3);
722 st.wSecond = atoiW(p+6);
723 p += 8;
725 if(*p == '.')
727 p++;
728 while(isdigitW(*p)) p++;
732 SystemTimeToVariantTime(&st, &date);
733 V_VT(v) = VT_DATE;
734 V_DATE(v) = date;
736 if(*p == '+') /* parse timezone offset (+hh:mm) */
737 V_DATE(v) += (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
738 else if(*p == '-') /* parse timezone offset (-hh:mm) */
739 V_DATE(v) -= (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
741 VariantClear(&src);
743 else if(!lstrcmpiW(type, szBinHex))
745 SAFEARRAYBOUND sab;
746 int i, len;
748 len = xmlStrlen(str)/2;
749 sab.lLbound = 0;
750 sab.cElements = len;
752 V_VT(v) = (VT_ARRAY|VT_UI1);
753 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
755 if(!V_ARRAY(v))
756 return E_OUTOFMEMORY;
758 for(i=0; i<len; i++)
759 ((BYTE*)V_ARRAY(v)->pvData)[i] = (hex_to_byte(str[2*i])<<4)
760 + hex_to_byte(str[2*i+1]);
762 else if(!lstrcmpiW(type, szBinBase64))
764 SAFEARRAYBOUND sab;
765 int i, len;
767 len = xmlStrlen(str);
768 if(str[len-2] == '=') i = 2;
769 else if(str[len-1] == '=') i = 1;
770 else i = 0;
772 sab.lLbound = 0;
773 sab.cElements = len/4*3-i;
775 V_VT(v) = (VT_ARRAY|VT_UI1);
776 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
778 if(!V_ARRAY(v))
779 return E_OUTOFMEMORY;
781 for(i=0; i<len/4; i++)
783 ((BYTE*)V_ARRAY(v)->pvData)[3*i] = (base64_to_byte(str[4*i])<<2)
784 + (base64_to_byte(str[4*i+1])>>4);
785 if(3*i+1 < sab.cElements)
786 ((BYTE*)V_ARRAY(v)->pvData)[3*i+1] = (base64_to_byte(str[4*i+1])<<4)
787 + (base64_to_byte(str[4*i+2])>>2);
788 if(3*i+2 < sab.cElements)
789 ((BYTE*)V_ARRAY(v)->pvData)[3*i+2] = (base64_to_byte(str[4*i+2])<<6)
790 + base64_to_byte(str[4*i+3]);
793 else
795 VARIANT src;
796 HRESULT hres;
798 if(!lstrcmpiW(type, szInt) || !lstrcmpiW(type, szI4))
799 V_VT(v) = VT_I4;
800 else if(!lstrcmpiW(type, szFixed))
801 V_VT(v) = VT_CY;
802 else if(!lstrcmpiW(type, szBoolean))
803 V_VT(v) = VT_BOOL;
804 else if(!lstrcmpiW(type, szI1))
805 V_VT(v) = VT_I1;
806 else if(!lstrcmpiW(type, szI2))
807 V_VT(v) = VT_I2;
808 else if(!lstrcmpiW(type, szIU1))
809 V_VT(v) = VT_UI1;
810 else if(!lstrcmpiW(type, szIU2))
811 V_VT(v) = VT_UI2;
812 else if(!lstrcmpiW(type, szIU4))
813 V_VT(v) = VT_UI4;
814 else if(!lstrcmpiW(type, szR4))
815 V_VT(v) = VT_R4;
816 else if(!lstrcmpiW(type, szR8) || !lstrcmpiW(type, szFloat))
817 V_VT(v) = VT_R8;
818 else
820 FIXME("Type handling not yet implemented\n");
821 V_VT(v) = VT_BSTR;
824 V_VT(&src) = VT_BSTR;
825 V_BSTR(&src) = bstr_from_xmlChar(str);
827 if(!V_BSTR(&src))
828 return E_OUTOFMEMORY;
830 hres = VariantChangeTypeEx(v, &src, MAKELCID(MAKELANGID(
831 LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),0, V_VT(v));
832 VariantClear(&src);
833 return hres;
836 return S_OK;
839 BSTR EnsureCorrectEOL(BSTR sInput)
841 int nNum = 0;
842 BSTR sNew;
843 int nLen;
844 int i;
846 nLen = SysStringLen(sInput);
847 /* Count line endings */
848 for(i=0; i < nLen; i++)
850 if(sInput[i] == '\n')
851 nNum++;
854 TRACE("len=%d, num=%d\n", nLen, nNum);
856 /* Add linefeed as needed */
857 if(nNum > 0)
859 int nPlace = 0;
860 sNew = SysAllocStringLen(NULL, nLen + nNum+1);
861 for(i=0; i < nLen; i++)
863 if(sInput[i] == '\n')
865 sNew[i+nPlace] = '\r';
866 nPlace++;
868 sNew[i+nPlace] = sInput[i];
871 SysFreeString(sInput);
873 else
875 sNew = sInput;
878 TRACE("len %d\n", SysStringLen(sNew));
880 return sNew;
883 /* Removes encoding information and last character (nullbyte) */
884 static BSTR EnsureNoEncoding(BSTR sInput)
886 static const WCHAR wszEncoding[] = {'e','n','c','o','d','i','n','g','='};
887 BSTR sNew;
888 WCHAR *pBeg, *pEnd;
890 pBeg = sInput;
891 while(*pBeg != '\n' && memcmp(pBeg, wszEncoding, sizeof(wszEncoding)))
892 pBeg++;
894 if(*pBeg == '\n')
896 SysReAllocStringLen(&sInput, sInput, SysStringLen(sInput)-1);
897 return sInput;
899 pBeg--;
901 pEnd = pBeg + sizeof(wszEncoding)/sizeof(WCHAR) + 2;
902 while(*pEnd != '\"') pEnd++;
903 pEnd++;
905 sNew = SysAllocStringLen(NULL,
906 pBeg-sInput + SysStringLen(sInput)-(pEnd-sInput)-1);
907 memcpy(sNew, sInput, (pBeg-sInput)*sizeof(WCHAR));
908 memcpy(&sNew[pBeg-sInput], pEnd, (SysStringLen(sInput)-(pEnd-sInput)-1)*sizeof(WCHAR));
910 SysFreeString(sInput);
911 return sNew;
915 * We are trying to replicate the same behaviour as msxml by converting
916 * line endings to \r\n and using indents as \t. The problem is that msxml
917 * only formats nodes that have a line ending. Using libxml we cannot
918 * reproduce behaviour exactly.
921 HRESULT node_get_xml(xmlnode *This, BOOL ensure_eol, BOOL ensure_no_encoding, BSTR *ret)
923 xmlBufferPtr xml_buf;
924 xmlNodePtr xmldecl;
925 int size;
927 if(!ret)
928 return E_INVALIDARG;
930 *ret = NULL;
932 xml_buf = xmlBufferCreate();
933 if(!xml_buf)
934 return E_OUTOFMEMORY;
936 xmldecl = xmldoc_unlink_xmldecl( This->node->doc );
938 size = xmlNodeDump(xml_buf, This->node->doc, This->node, 0, 1);
939 if(size > 0) {
940 const xmlChar *buf_content;
941 BSTR content;
943 /* Attribute Nodes return a space in front of their name */
944 buf_content = xmlBufferContent(xml_buf);
946 content = bstr_from_xmlChar(buf_content + (buf_content[0] == ' ' ? 1 : 0));
947 if(ensure_eol)
948 content = EnsureCorrectEOL(content);
949 if(ensure_no_encoding)
950 content = EnsureNoEncoding(content);
952 *ret = content;
953 }else {
954 *ret = SysAllocStringLen(NULL, 0);
957 xmlBufferFree(xml_buf);
958 xmldoc_link_xmldecl( This->node->doc, xmldecl );
959 return *ret ? S_OK : E_OUTOFMEMORY;
962 static HRESULT WINAPI xmlnode_transformNode(
963 IXMLDOMNode *iface,
964 IXMLDOMNode* styleSheet,
965 BSTR* xmlString)
967 #ifdef SONAME_LIBXSLT
968 xmlnode *This = impl_from_IXMLDOMNode( iface );
969 xmlnode *pStyleSheet = NULL;
970 xsltStylesheetPtr xsltSS = NULL;
971 xmlDocPtr result = NULL;
973 TRACE("(%p)->(%p %p)\n", This, styleSheet, xmlString);
975 if (!libxslt_handle)
976 return E_NOTIMPL;
977 if(!styleSheet || !xmlString)
978 return E_INVALIDARG;
980 *xmlString = NULL;
982 pStyleSheet = get_node_obj(styleSheet);
983 if(!pStyleSheet) {
984 FIXME("styleSheet is not our xmlnode implementation\n");
985 return E_FAIL;
988 xsltSS = pxsltParseStylesheetDoc( pStyleSheet->node->doc);
989 if(xsltSS)
991 result = pxsltApplyStylesheet(xsltSS, This->node->doc, NULL);
992 if(result)
994 const xmlChar *pContent;
996 if(result->type == XML_HTML_DOCUMENT_NODE)
998 xmlOutputBufferPtr pOutput = xmlAllocOutputBuffer(NULL);
999 if(pOutput)
1001 htmlDocContentDumpOutput(pOutput, result->doc, NULL);
1002 pContent = xmlBufferContent(pOutput->buffer);
1003 *xmlString = bstr_from_xmlChar(pContent);
1004 xmlOutputBufferClose(pOutput);
1007 else
1009 xmlBufferPtr pXmlBuf;
1010 int nSize;
1012 pXmlBuf = xmlBufferCreate();
1013 if(pXmlBuf)
1015 nSize = xmlNodeDump(pXmlBuf, NULL, (xmlNodePtr)result, 0, 0);
1016 if(nSize > 0)
1018 pContent = xmlBufferContent(pXmlBuf);
1019 *xmlString = bstr_from_xmlChar(pContent);
1021 xmlBufferFree(pXmlBuf);
1024 xmlFreeDoc(result);
1026 /* libxslt "helpfully" frees the XML document the stylesheet was
1027 generated from, too */
1028 xsltSS->doc = NULL;
1029 pxsltFreeStylesheet(xsltSS);
1032 if(*xmlString == NULL)
1033 *xmlString = SysAllocStringLen(NULL, 0);
1035 return S_OK;
1036 #else
1037 FIXME("libxslt headers were not found at compile time\n");
1038 return E_NOTIMPL;
1039 #endif
1042 static HRESULT WINAPI xmlnode_selectNodes(
1043 IXMLDOMNode *iface,
1044 BSTR queryString,
1045 IXMLDOMNodeList** resultList)
1047 xmlnode *This = impl_from_IXMLDOMNode( iface );
1048 xmlChar* str;
1049 HRESULT hr;
1051 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultList );
1053 if (!queryString || !resultList) return E_INVALIDARG;
1055 str = xmlChar_from_wchar(queryString);
1056 hr = queryresult_create(This->node, str, resultList);
1057 heap_free(str);
1059 return hr;
1062 static HRESULT WINAPI xmlnode_selectSingleNode(
1063 IXMLDOMNode *iface,
1064 BSTR queryString,
1065 IXMLDOMNode** resultNode)
1067 xmlnode *This = impl_from_IXMLDOMNode( iface );
1068 IXMLDOMNodeList *list;
1069 HRESULT r;
1071 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultNode );
1073 r = IXMLDOMNode_selectNodes(This->iface, queryString, &list);
1074 if(r == S_OK)
1076 r = IXMLDOMNodeList_nextNode(list, resultNode);
1077 IXMLDOMNodeList_Release(list);
1079 return r;
1082 HRESULT node_get_namespaceURI(xmlnode *This, BSTR *namespaceURI)
1084 xmlNsPtr *ns;
1086 if(!namespaceURI)
1087 return E_INVALIDARG;
1089 *namespaceURI = NULL;
1091 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1093 if (ns[0]->href) *namespaceURI = bstr_from_xmlChar( ns[0]->href );
1094 xmlFree(ns);
1097 TRACE("uri: %s\n", debugstr_w(*namespaceURI));
1099 return *namespaceURI ? S_OK : S_FALSE;
1102 HRESULT node_get_prefix(xmlnode *This, BSTR *prefix)
1104 xmlNsPtr *ns;
1106 if (!prefix) return E_INVALIDARG;
1108 *prefix = NULL;
1110 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1112 if (ns[0]->prefix) *prefix = bstr_from_xmlChar( ns[0]->prefix );
1113 xmlFree(ns);
1116 TRACE("prefix: %s\n", debugstr_w(*prefix));
1118 return *prefix ? S_OK : S_FALSE;
1121 HRESULT node_get_base_name(xmlnode *This, BSTR *name)
1123 if (!name) return E_INVALIDARG;
1125 *name = bstr_from_xmlChar(This->node->name);
1126 if (!*name) return E_OUTOFMEMORY;
1128 TRACE("returning %s\n", debugstr_w(*name));
1130 return S_OK;
1133 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
1135 NULL,
1136 NULL,
1137 NULL,
1138 NULL,
1139 NULL,
1140 NULL,
1141 NULL,
1142 NULL,
1143 NULL,
1144 NULL,
1145 NULL,
1146 NULL,
1147 NULL,
1148 NULL,
1149 NULL,
1150 NULL,
1151 NULL,
1152 NULL,
1153 NULL,
1154 NULL,
1155 xmlnode_removeChild,
1156 xmlnode_appendChild,
1157 xmlnode_hasChildNodes,
1158 xmlnode_get_ownerDocument,
1159 NULL,
1160 NULL,
1161 xmlnode_get_text,
1162 NULL,
1163 NULL,
1164 NULL,
1165 NULL,
1166 NULL,
1167 NULL,
1168 NULL,
1169 NULL,
1170 xmlnode_transformNode,
1171 xmlnode_selectNodes,
1172 xmlnode_selectSingleNode
1175 void destroy_xmlnode(xmlnode *This)
1177 if(This->node)
1178 xmldoc_release(This->node->doc);
1181 void init_xmlnode(xmlnode *This, xmlNodePtr node, IXMLDOMNode *node_iface, dispex_static_data_t *dispex_data)
1183 if(node)
1184 xmldoc_add_ref( node->doc );
1186 This->IXMLDOMNode_iface.lpVtbl = &xmlnode_vtbl;
1187 This->node = node;
1188 This->iface = node_iface;
1190 if(dispex_data)
1191 init_dispex(&This->dispex, (IUnknown*)This->iface, dispex_data);
1192 else
1193 This->dispex.outer = NULL;
1196 typedef struct {
1197 xmlnode node;
1198 IXMLDOMNode IXMLDOMNode_iface;
1199 LONG ref;
1200 } unknode;
1202 static inline unknode *unknode_from_IXMLDOMNode(IXMLDOMNode *iface)
1204 return CONTAINING_RECORD(iface, unknode, IXMLDOMNode_iface);
1207 static HRESULT WINAPI unknode_QueryInterface(
1208 IXMLDOMNode *iface,
1209 REFIID riid,
1210 void** ppvObject )
1212 unknode *This = unknode_from_IXMLDOMNode( iface );
1214 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1216 if (IsEqualGUID(riid, &IID_IUnknown)) {
1217 *ppvObject = iface;
1218 }else if (IsEqualGUID( riid, &IID_IDispatch) ||
1219 IsEqualGUID( riid, &IID_IXMLDOMNode)) {
1220 *ppvObject = &This->IXMLDOMNode_iface;
1221 }else if(node_query_interface(&This->node, riid, ppvObject)) {
1222 return *ppvObject ? S_OK : E_NOINTERFACE;
1223 }else {
1224 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1225 *ppvObject = NULL;
1226 return E_NOINTERFACE;
1229 IUnknown_AddRef((IUnknown*)*ppvObject);
1230 return S_OK;
1233 static ULONG WINAPI unknode_AddRef(
1234 IXMLDOMNode *iface )
1236 unknode *This = unknode_from_IXMLDOMNode( iface );
1238 return InterlockedIncrement(&This->ref);
1241 static ULONG WINAPI unknode_Release(
1242 IXMLDOMNode *iface )
1244 unknode *This = unknode_from_IXMLDOMNode( iface );
1245 LONG ref;
1247 ref = InterlockedDecrement( &This->ref );
1248 if(!ref) {
1249 destroy_xmlnode(&This->node);
1250 heap_free(This);
1253 return ref;
1256 static HRESULT WINAPI unknode_GetTypeInfoCount(
1257 IXMLDOMNode *iface,
1258 UINT* pctinfo )
1260 unknode *This = unknode_from_IXMLDOMNode( iface );
1262 TRACE("(%p)->(%p)\n", This, pctinfo);
1264 *pctinfo = 1;
1266 return S_OK;
1269 static HRESULT WINAPI unknode_GetTypeInfo(
1270 IXMLDOMNode *iface,
1271 UINT iTInfo,
1272 LCID lcid,
1273 ITypeInfo** ppTInfo )
1275 unknode *This = unknode_from_IXMLDOMNode( iface );
1276 HRESULT hr;
1278 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1280 hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
1282 return hr;
1285 static HRESULT WINAPI unknode_GetIDsOfNames(
1286 IXMLDOMNode *iface,
1287 REFIID riid,
1288 LPOLESTR* rgszNames,
1289 UINT cNames,
1290 LCID lcid,
1291 DISPID* rgDispId )
1293 unknode *This = unknode_from_IXMLDOMNode( iface );
1295 ITypeInfo *typeinfo;
1296 HRESULT hr;
1298 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1299 lcid, rgDispId);
1301 if(!rgszNames || cNames == 0 || !rgDispId)
1302 return E_INVALIDARG;
1304 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1305 if(SUCCEEDED(hr))
1307 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1308 ITypeInfo_Release(typeinfo);
1311 return hr;
1314 static HRESULT WINAPI unknode_Invoke(
1315 IXMLDOMNode *iface,
1316 DISPID dispIdMember,
1317 REFIID riid,
1318 LCID lcid,
1319 WORD wFlags,
1320 DISPPARAMS* pDispParams,
1321 VARIANT* pVarResult,
1322 EXCEPINFO* pExcepInfo,
1323 UINT* puArgErr )
1325 unknode *This = unknode_from_IXMLDOMNode( iface );
1326 ITypeInfo *typeinfo;
1327 HRESULT hr;
1329 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1330 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1332 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1333 if(SUCCEEDED(hr))
1335 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMNode_iface, dispIdMember, wFlags, pDispParams,
1336 pVarResult, pExcepInfo, puArgErr);
1337 ITypeInfo_Release(typeinfo);
1340 return hr;
1343 static HRESULT WINAPI unknode_get_nodeName(
1344 IXMLDOMNode *iface,
1345 BSTR* p )
1347 unknode *This = unknode_from_IXMLDOMNode( iface );
1349 FIXME("(%p)->(%p)\n", This, p);
1351 return node_get_nodeName(&This->node, p);
1354 static HRESULT WINAPI unknode_get_nodeValue(
1355 IXMLDOMNode *iface,
1356 VARIANT* value)
1358 unknode *This = unknode_from_IXMLDOMNode( iface );
1360 FIXME("(%p)->(%p)\n", This, value);
1362 if(!value)
1363 return E_INVALIDARG;
1365 V_VT(value) = VT_NULL;
1366 return S_FALSE;
1369 static HRESULT WINAPI unknode_put_nodeValue(
1370 IXMLDOMNode *iface,
1371 VARIANT value)
1373 unknode *This = unknode_from_IXMLDOMNode( iface );
1374 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
1375 return E_FAIL;
1378 static HRESULT WINAPI unknode_get_nodeType(
1379 IXMLDOMNode *iface,
1380 DOMNodeType* domNodeType )
1382 unknode *This = unknode_from_IXMLDOMNode( iface );
1384 FIXME("(%p)->(%p)\n", This, domNodeType);
1386 *domNodeType = This->node.node->type;
1387 return S_OK;
1390 static HRESULT WINAPI unknode_get_parentNode(
1391 IXMLDOMNode *iface,
1392 IXMLDOMNode** parent )
1394 unknode *This = unknode_from_IXMLDOMNode( iface );
1395 FIXME("(%p)->(%p)\n", This, parent);
1396 if (!parent) return E_INVALIDARG;
1397 *parent = NULL;
1398 return S_FALSE;
1401 static HRESULT WINAPI unknode_get_childNodes(
1402 IXMLDOMNode *iface,
1403 IXMLDOMNodeList** outList)
1405 unknode *This = unknode_from_IXMLDOMNode( iface );
1407 TRACE("(%p)->(%p)\n", This, outList);
1409 return node_get_child_nodes(&This->node, outList);
1412 static HRESULT WINAPI unknode_get_firstChild(
1413 IXMLDOMNode *iface,
1414 IXMLDOMNode** domNode)
1416 unknode *This = unknode_from_IXMLDOMNode( iface );
1418 TRACE("(%p)->(%p)\n", This, domNode);
1420 return node_get_first_child(&This->node, domNode);
1423 static HRESULT WINAPI unknode_get_lastChild(
1424 IXMLDOMNode *iface,
1425 IXMLDOMNode** domNode)
1427 unknode *This = unknode_from_IXMLDOMNode( iface );
1429 TRACE("(%p)->(%p)\n", This, domNode);
1431 return node_get_last_child(&This->node, domNode);
1434 static HRESULT WINAPI unknode_get_previousSibling(
1435 IXMLDOMNode *iface,
1436 IXMLDOMNode** domNode)
1438 unknode *This = unknode_from_IXMLDOMNode( iface );
1440 TRACE("(%p)->(%p)\n", This, domNode);
1442 return node_get_previous_sibling(&This->node, domNode);
1445 static HRESULT WINAPI unknode_get_nextSibling(
1446 IXMLDOMNode *iface,
1447 IXMLDOMNode** domNode)
1449 unknode *This = unknode_from_IXMLDOMNode( iface );
1451 TRACE("(%p)->(%p)\n", This, domNode);
1453 return node_get_next_sibling(&This->node, domNode);
1456 static HRESULT WINAPI unknode_get_attributes(
1457 IXMLDOMNode *iface,
1458 IXMLDOMNamedNodeMap** attributeMap)
1460 unknode *This = unknode_from_IXMLDOMNode( iface );
1462 FIXME("(%p)->(%p)\n", This, attributeMap);
1464 return return_null_ptr((void**)attributeMap);
1467 static HRESULT WINAPI unknode_insertBefore(
1468 IXMLDOMNode *iface,
1469 IXMLDOMNode* newNode, VARIANT refChild,
1470 IXMLDOMNode** outOldNode)
1472 unknode *This = unknode_from_IXMLDOMNode( iface );
1474 FIXME("(%p)->(%p x%d %p)\n", This, newNode, V_VT(&refChild), outOldNode);
1476 return node_insert_before(&This->node, newNode, &refChild, outOldNode);
1479 static HRESULT WINAPI unknode_replaceChild(
1480 IXMLDOMNode *iface,
1481 IXMLDOMNode* newNode,
1482 IXMLDOMNode* oldNode,
1483 IXMLDOMNode** outOldNode)
1485 unknode *This = unknode_from_IXMLDOMNode( iface );
1487 FIXME("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
1489 return node_replace_child(&This->node, newNode, oldNode, outOldNode);
1492 static HRESULT WINAPI unknode_removeChild(
1493 IXMLDOMNode *iface,
1494 IXMLDOMNode* domNode, IXMLDOMNode** oldNode)
1496 unknode *This = unknode_from_IXMLDOMNode( iface );
1497 return IXMLDOMNode_removeChild( &This->node.IXMLDOMNode_iface, domNode, oldNode );
1500 static HRESULT WINAPI unknode_appendChild(
1501 IXMLDOMNode *iface,
1502 IXMLDOMNode* newNode, IXMLDOMNode** outNewNode)
1504 unknode *This = unknode_from_IXMLDOMNode( iface );
1505 return IXMLDOMNode_appendChild( &This->node.IXMLDOMNode_iface, newNode, outNewNode );
1508 static HRESULT WINAPI unknode_hasChildNodes(
1509 IXMLDOMNode *iface,
1510 VARIANT_BOOL* pbool)
1512 unknode *This = unknode_from_IXMLDOMNode( iface );
1513 return IXMLDOMNode_hasChildNodes( &This->node.IXMLDOMNode_iface, pbool );
1516 static HRESULT WINAPI unknode_get_ownerDocument(
1517 IXMLDOMNode *iface,
1518 IXMLDOMDocument** domDocument)
1520 unknode *This = unknode_from_IXMLDOMNode( iface );
1521 return IXMLDOMNode_get_ownerDocument( &This->node.IXMLDOMNode_iface, domDocument );
1524 static HRESULT WINAPI unknode_cloneNode(
1525 IXMLDOMNode *iface,
1526 VARIANT_BOOL pbool, IXMLDOMNode** outNode)
1528 unknode *This = unknode_from_IXMLDOMNode( iface );
1529 return IXMLDOMNode_cloneNode( &This->node.IXMLDOMNode_iface, pbool, outNode );
1532 static HRESULT WINAPI unknode_get_nodeTypeString(
1533 IXMLDOMNode *iface,
1534 BSTR* p)
1536 unknode *This = unknode_from_IXMLDOMNode( iface );
1538 FIXME("(%p)->(%p)\n", This, p);
1540 return node_get_nodeName(&This->node, p);
1543 static HRESULT WINAPI unknode_get_text(
1544 IXMLDOMNode *iface,
1545 BSTR* p)
1547 unknode *This = unknode_from_IXMLDOMNode( iface );
1548 return IXMLDOMNode_get_text( &This->node.IXMLDOMNode_iface, p );
1551 static HRESULT WINAPI unknode_put_text(
1552 IXMLDOMNode *iface,
1553 BSTR p)
1555 unknode *This = unknode_from_IXMLDOMNode( iface );
1556 return IXMLDOMNode_put_text( &This->node.IXMLDOMNode_iface, p );
1559 static HRESULT WINAPI unknode_get_specified(
1560 IXMLDOMNode *iface,
1561 VARIANT_BOOL* isSpecified)
1563 unknode *This = unknode_from_IXMLDOMNode( iface );
1564 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1565 *isSpecified = VARIANT_TRUE;
1566 return S_OK;
1569 static HRESULT WINAPI unknode_get_definition(
1570 IXMLDOMNode *iface,
1571 IXMLDOMNode** definitionNode)
1573 unknode *This = unknode_from_IXMLDOMNode( iface );
1574 FIXME("(%p)->(%p)\n", This, definitionNode);
1575 return E_NOTIMPL;
1578 static HRESULT WINAPI unknode_get_nodeTypedValue(
1579 IXMLDOMNode *iface,
1580 VARIANT* var1)
1582 unknode *This = unknode_from_IXMLDOMNode( iface );
1583 FIXME("(%p)->(%p)\n", This, var1);
1584 return return_null_var(var1);
1587 static HRESULT WINAPI unknode_put_nodeTypedValue(
1588 IXMLDOMNode *iface,
1589 VARIANT typedValue)
1591 unknode *This = unknode_from_IXMLDOMNode( iface );
1592 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1593 return E_NOTIMPL;
1596 static HRESULT WINAPI unknode_get_dataType(
1597 IXMLDOMNode *iface,
1598 VARIANT* var1)
1600 unknode *This = unknode_from_IXMLDOMNode( iface );
1601 return IXMLDOMNode_get_dataType( &This->node.IXMLDOMNode_iface, var1 );
1604 static HRESULT WINAPI unknode_put_dataType(
1605 IXMLDOMNode *iface,
1606 BSTR p)
1608 unknode *This = unknode_from_IXMLDOMNode( iface );
1610 FIXME("(%p)->(%s)\n", This, debugstr_w(p));
1612 if(!p)
1613 return E_INVALIDARG;
1615 return E_FAIL;
1618 static HRESULT WINAPI unknode_get_xml(
1619 IXMLDOMNode *iface,
1620 BSTR* p)
1622 unknode *This = unknode_from_IXMLDOMNode( iface );
1624 FIXME("(%p)->(%p)\n", This, p);
1626 return node_get_xml(&This->node, FALSE, FALSE, p);
1629 static HRESULT WINAPI unknode_transformNode(
1630 IXMLDOMNode *iface,
1631 IXMLDOMNode* domNode, BSTR* p)
1633 unknode *This = unknode_from_IXMLDOMNode( iface );
1634 return IXMLDOMNode_transformNode( &This->node.IXMLDOMNode_iface, domNode, p );
1637 static HRESULT WINAPI unknode_selectNodes(
1638 IXMLDOMNode *iface,
1639 BSTR p, IXMLDOMNodeList** outList)
1641 unknode *This = unknode_from_IXMLDOMNode( iface );
1642 return IXMLDOMNode_selectNodes( &This->node.IXMLDOMNode_iface, p, outList );
1645 static HRESULT WINAPI unknode_selectSingleNode(
1646 IXMLDOMNode *iface,
1647 BSTR p, IXMLDOMNode** outNode)
1649 unknode *This = unknode_from_IXMLDOMNode( iface );
1650 return IXMLDOMNode_selectSingleNode( &This->node.IXMLDOMNode_iface, p, outNode );
1653 static HRESULT WINAPI unknode_get_parsed(
1654 IXMLDOMNode *iface,
1655 VARIANT_BOOL* isParsed)
1657 unknode *This = unknode_from_IXMLDOMNode( iface );
1658 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1659 *isParsed = VARIANT_TRUE;
1660 return S_OK;
1663 static HRESULT WINAPI unknode_get_namespaceURI(
1664 IXMLDOMNode *iface,
1665 BSTR* p)
1667 unknode *This = unknode_from_IXMLDOMNode( iface );
1668 TRACE("(%p)->(%p)\n", This, p);
1669 return node_get_namespaceURI(&This->node, p);
1672 static HRESULT WINAPI unknode_get_prefix(
1673 IXMLDOMNode *iface,
1674 BSTR* p)
1676 unknode *This = unknode_from_IXMLDOMNode( iface );
1677 return IXMLDOMNode_get_prefix( &This->node.IXMLDOMNode_iface, p );
1680 static HRESULT WINAPI unknode_get_baseName(
1681 IXMLDOMNode *iface,
1682 BSTR* p)
1684 unknode *This = unknode_from_IXMLDOMNode( iface );
1685 return IXMLDOMNode_get_baseName( &This->node.IXMLDOMNode_iface, p );
1688 static HRESULT WINAPI unknode_transformNodeToObject(
1689 IXMLDOMNode *iface,
1690 IXMLDOMNode* domNode, VARIANT var1)
1692 unknode *This = unknode_from_IXMLDOMNode( iface );
1693 FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1));
1694 return E_NOTIMPL;
1697 static const struct IXMLDOMNodeVtbl unknode_vtbl =
1699 unknode_QueryInterface,
1700 unknode_AddRef,
1701 unknode_Release,
1702 unknode_GetTypeInfoCount,
1703 unknode_GetTypeInfo,
1704 unknode_GetIDsOfNames,
1705 unknode_Invoke,
1706 unknode_get_nodeName,
1707 unknode_get_nodeValue,
1708 unknode_put_nodeValue,
1709 unknode_get_nodeType,
1710 unknode_get_parentNode,
1711 unknode_get_childNodes,
1712 unknode_get_firstChild,
1713 unknode_get_lastChild,
1714 unknode_get_previousSibling,
1715 unknode_get_nextSibling,
1716 unknode_get_attributes,
1717 unknode_insertBefore,
1718 unknode_replaceChild,
1719 unknode_removeChild,
1720 unknode_appendChild,
1721 unknode_hasChildNodes,
1722 unknode_get_ownerDocument,
1723 unknode_cloneNode,
1724 unknode_get_nodeTypeString,
1725 unknode_get_text,
1726 unknode_put_text,
1727 unknode_get_specified,
1728 unknode_get_definition,
1729 unknode_get_nodeTypedValue,
1730 unknode_put_nodeTypedValue,
1731 unknode_get_dataType,
1732 unknode_put_dataType,
1733 unknode_get_xml,
1734 unknode_transformNode,
1735 unknode_selectNodes,
1736 unknode_selectSingleNode,
1737 unknode_get_parsed,
1738 unknode_get_namespaceURI,
1739 unknode_get_prefix,
1740 unknode_get_baseName,
1741 unknode_transformNodeToObject
1744 IXMLDOMNode *create_node( xmlNodePtr node )
1746 IUnknown *pUnk;
1747 IXMLDOMNode *ret;
1748 HRESULT hr;
1750 if ( !node )
1751 return NULL;
1753 TRACE("type %d\n", node->type);
1754 switch(node->type)
1756 case XML_ELEMENT_NODE:
1757 pUnk = create_element( node );
1758 break;
1759 case XML_ATTRIBUTE_NODE:
1760 pUnk = create_attribute( node );
1761 break;
1762 case XML_TEXT_NODE:
1763 pUnk = create_text( node );
1764 break;
1765 case XML_CDATA_SECTION_NODE:
1766 pUnk = create_cdata( node );
1767 break;
1768 case XML_ENTITY_REF_NODE:
1769 pUnk = create_doc_entity_ref( node );
1770 break;
1771 case XML_PI_NODE:
1772 pUnk = create_pi( node );
1773 break;
1774 case XML_COMMENT_NODE:
1775 pUnk = create_comment( node );
1776 break;
1777 case XML_DOCUMENT_NODE:
1778 pUnk = create_domdoc( node );
1779 break;
1780 case XML_DOCUMENT_FRAG_NODE:
1781 pUnk = create_doc_fragment( node );
1782 break;
1783 case XML_DTD_NODE:
1784 pUnk = create_doc_type( node );
1785 break;
1786 default: {
1787 unknode *new_node;
1789 FIXME("only creating basic node for type %d\n", node->type);
1791 new_node = heap_alloc(sizeof(unknode));
1792 if(!new_node)
1793 return NULL;
1795 new_node->IXMLDOMNode_iface.lpVtbl = &unknode_vtbl;
1796 new_node->ref = 1;
1797 init_xmlnode(&new_node->node, node, &new_node->IXMLDOMNode_iface, NULL);
1798 pUnk = (IUnknown*)&new_node->IXMLDOMNode_iface;
1802 hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
1803 IUnknown_Release(pUnk);
1804 if(FAILED(hr)) return NULL;
1805 return ret;
1807 #endif