msxml3: Fix response text conversion to WCHAR string.
[wine.git] / dlls / msxml3 / node.c
blobd46678081b2a3f68a025075573e49f4b70d20054
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 <assert.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winnls.h"
31 #include "ole2.h"
32 #include "msxml6.h"
34 #include "msxml_private.h"
36 #ifdef HAVE_LIBXML2
37 # include <libxml/HTMLtree.h>
38 #endif
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
44 #ifdef HAVE_LIBXML2
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 (xmlnode *)((char*)iface - FIELD_OFFSET(xmlnode, lpVtbl));
113 static HRESULT WINAPI xmlnode_QueryInterface(
114 IXMLDOMNode *iface,
115 REFIID riid,
116 void** ppvObject )
118 ERR("Should not be called\n");
119 return E_NOINTERFACE;
122 static ULONG WINAPI xmlnode_AddRef(
123 IXMLDOMNode *iface )
125 ERR("Should not be called\n");
126 return 2;
129 static ULONG WINAPI xmlnode_Release(
130 IXMLDOMNode *iface )
132 ERR("Should not be called\n");
133 return 1;
136 static HRESULT WINAPI xmlnode_GetTypeInfoCount(
137 IXMLDOMNode *iface,
138 UINT* pctinfo )
140 ERR("Should not be called\n");
141 return E_NOTIMPL;
144 static HRESULT WINAPI xmlnode_GetTypeInfo(
145 IXMLDOMNode *iface,
146 UINT iTInfo,
147 LCID lcid,
148 ITypeInfo** ppTInfo )
150 ERR("Should not be called\n");
151 return E_NOTIMPL;
154 static HRESULT WINAPI xmlnode_GetIDsOfNames(
155 IXMLDOMNode *iface,
156 REFIID riid,
157 LPOLESTR* rgszNames,
158 UINT cNames,
159 LCID lcid,
160 DISPID* rgDispId )
162 ERR("Should not be called\n");
163 return E_NOTIMPL;
166 static HRESULT WINAPI xmlnode_Invoke(
167 IXMLDOMNode *iface,
168 DISPID dispIdMember,
169 REFIID riid,
170 LCID lcid,
171 WORD wFlags,
172 DISPPARAMS* pDispParams,
173 VARIANT* pVarResult,
174 EXCEPINFO* pExcepInfo,
175 UINT* puArgErr )
177 ERR("Should not be called\n");
178 return E_NOTIMPL;
181 HRESULT node_get_nodeName(xmlnode *This, BSTR *name)
183 if (!name)
184 return E_INVALIDARG;
186 *name = bstr_from_xmlChar(This->node->name);
187 if (!*name)
188 return S_FALSE;
190 return S_OK;
193 static HRESULT WINAPI xmlnode_get_nodeName(
194 IXMLDOMNode *iface,
195 BSTR* name)
197 ERR("Should not be called\n");
198 return E_NOTIMPL;
201 HRESULT node_get_content(xmlnode *This, VARIANT *value)
203 xmlChar *content;
205 if(!value)
206 return E_INVALIDARG;
208 content = xmlNodeGetContent(This->node);
209 V_VT(value) = VT_BSTR;
210 V_BSTR(value) = bstr_from_xmlChar( content );
211 xmlFree(content);
213 TRACE("%p returned %s\n", This, debugstr_w(V_BSTR(value)));
214 return S_OK;
217 static HRESULT WINAPI xmlnode_get_nodeValue(
218 IXMLDOMNode *iface,
219 VARIANT* value)
221 ERR("Should not be called\n");
222 return E_NOTIMPL;
225 HRESULT node_put_value(xmlnode *This, VARIANT *value)
227 VARIANT string_value;
228 xmlChar *str;
229 HRESULT hr;
231 VariantInit(&string_value);
232 hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
233 if(FAILED(hr)) {
234 WARN("Couldn't convert to VT_BSTR\n");
235 return hr;
238 str = xmlChar_from_wchar(V_BSTR(&string_value));
239 VariantClear(&string_value);
241 xmlNodeSetContent(This->node, str);
242 heap_free(str);
243 return S_OK;
246 static HRESULT WINAPI xmlnode_put_nodeValue(
247 IXMLDOMNode *iface,
248 VARIANT value)
250 ERR("Should not be called\n");
251 return E_NOTIMPL;
254 static HRESULT WINAPI xmlnode_get_nodeType(
255 IXMLDOMNode *iface,
256 DOMNodeType* type)
258 ERR("Should not be called\n");
259 return E_NOTIMPL;
262 static HRESULT get_node(
263 xmlnode *This,
264 const char *name,
265 xmlNodePtr node,
266 IXMLDOMNode **out )
268 TRACE("(%p)->(%s %p %p)\n", This, name, node, out );
270 if ( !out )
271 return E_INVALIDARG;
273 /* if we don't have a doc, use our parent. */
274 if(node && !node->doc && node->parent)
275 node->doc = node->parent->doc;
277 *out = create_node( node );
278 if (!*out)
279 return S_FALSE;
280 return S_OK;
283 HRESULT node_get_parent(xmlnode *This, IXMLDOMNode **parent)
285 return get_node( This, "parent", This->node->parent, parent );
288 static HRESULT WINAPI xmlnode_get_parentNode(
289 IXMLDOMNode *iface,
290 IXMLDOMNode** parent)
292 ERR("Should not be called\n");
293 return E_NOTIMPL;
296 HRESULT node_get_child_nodes(xmlnode *This, IXMLDOMNodeList **ret)
298 if(!ret)
299 return E_INVALIDARG;
301 *ret = create_children_nodelist(This->node);
302 if(!*ret)
303 return E_OUTOFMEMORY;
305 return S_OK;
308 static HRESULT WINAPI xmlnode_get_childNodes(
309 IXMLDOMNode *iface,
310 IXMLDOMNodeList** childList)
312 ERR("Should not be called\n");
313 return E_NOTIMPL;
316 HRESULT node_get_first_child(xmlnode *This, IXMLDOMNode **ret)
318 return get_node(This, "firstChild", This->node->children, ret);
321 static HRESULT WINAPI xmlnode_get_firstChild(
322 IXMLDOMNode *iface,
323 IXMLDOMNode** firstChild)
325 ERR("Should not be called\n");
326 return E_NOTIMPL;
329 HRESULT node_get_last_child(xmlnode *This, IXMLDOMNode **ret)
331 return get_node(This, "lastChild", This->node->last, ret);
334 static HRESULT WINAPI xmlnode_get_lastChild(
335 IXMLDOMNode *iface,
336 IXMLDOMNode** lastChild)
338 ERR("Should not be called\n");
339 return E_NOTIMPL;
342 HRESULT node_get_previous_sibling(xmlnode *This, IXMLDOMNode **ret)
344 return get_node(This, "previous", This->node->prev, ret);
347 static HRESULT WINAPI xmlnode_get_previousSibling(
348 IXMLDOMNode *iface,
349 IXMLDOMNode** previousSibling)
351 ERR("Should not be called\n");
352 return E_NOTIMPL;
355 HRESULT node_get_next_sibling(xmlnode *This, IXMLDOMNode **ret)
357 return get_node(This, "next", This->node->next, ret);
360 static HRESULT WINAPI xmlnode_get_nextSibling(
361 IXMLDOMNode *iface,
362 IXMLDOMNode** nextSibling)
364 ERR("Should not be called\n");
365 return E_NOTIMPL;
368 static HRESULT WINAPI xmlnode_get_attributes(
369 IXMLDOMNode *iface,
370 IXMLDOMNamedNodeMap** attributeMap)
372 ERR("Should not be called\n");
373 return E_NOTIMPL;
376 HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT *ref_child,
377 IXMLDOMNode **ret)
379 xmlNodePtr before_node, new_child_node;
380 IXMLDOMNode *before = NULL;
381 xmlnode *node_obj;
382 HRESULT hr;
384 if(!new_child)
385 return E_INVALIDARG;
387 node_obj = get_node_obj(new_child);
388 if(!node_obj) {
389 FIXME("newChild is not our node implementation\n");
390 return E_FAIL;
393 switch(V_VT(ref_child))
395 case VT_EMPTY:
396 case VT_NULL:
397 break;
399 case VT_UNKNOWN:
400 case VT_DISPATCH:
401 hr = IUnknown_QueryInterface(V_UNKNOWN(ref_child), &IID_IXMLDOMNode, (LPVOID)&before);
402 if(FAILED(hr)) return hr;
403 break;
405 default:
406 FIXME("refChild var type %x\n", V_VT(ref_child));
407 return E_FAIL;
410 new_child_node = node_obj->node;
411 TRACE("new_child_node %p This->node %p\n", new_child_node, This->node);
413 if(!new_child_node->parent)
414 if(xmldoc_remove_orphan(new_child_node->doc, new_child_node) != S_OK)
415 WARN("%p is not an orphan of %p\n", new_child_node, new_child_node->doc);
417 if(before)
419 node_obj = get_node_obj(before);
420 IXMLDOMNode_Release(before);
421 if(!node_obj) {
422 FIXME("before node is not our node implementation\n");
423 return E_FAIL;
426 before_node = node_obj->node;
427 xmlAddPrevSibling(before_node, new_child_node);
429 else
431 xmlAddChild(This->node, new_child_node);
434 if(ret) {
435 IXMLDOMNode_AddRef(new_child);
436 *ret = new_child;
439 TRACE("ret S_OK\n");
440 return S_OK;
443 static HRESULT WINAPI xmlnode_insertBefore(
444 IXMLDOMNode *iface,
445 IXMLDOMNode* newChild,
446 VARIANT refChild,
447 IXMLDOMNode** outNewChild)
449 ERR("Should not be called\n");
450 return E_NOTIMPL;
453 static HRESULT WINAPI xmlnode_replaceChild(
454 IXMLDOMNode *iface,
455 IXMLDOMNode* newChild,
456 IXMLDOMNode* oldChild,
457 IXMLDOMNode** outOldChild)
459 xmlnode *This = impl_from_IXMLDOMNode( iface );
460 xmlnode *old_child, *new_child;
461 xmlDocPtr leaving_doc;
462 xmlNode *my_ancestor;
464 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
466 /* Do not believe any documentation telling that newChild == NULL
467 means removal. It does certainly *not* apply to msxml3! */
468 if(!newChild || !oldChild)
469 return E_INVALIDARG;
471 if(outOldChild)
472 *outOldChild = NULL;
474 old_child = get_node_obj(oldChild);
475 if(!old_child) {
476 FIXME("oldChild is not our node implementation\n");
477 return E_FAIL;
480 if(old_child->node->parent != This->node)
482 WARN("childNode %p is not a child of %p\n", oldChild, iface);
483 return E_INVALIDARG;
486 new_child = get_node_obj(newChild);
487 if(!new_child) {
488 FIXME("newChild is not our node implementation\n");
489 return E_FAIL;
492 my_ancestor = This->node;
493 while(my_ancestor)
495 if(my_ancestor == new_child->node)
497 WARN("tried to create loop\n");
498 return E_FAIL;
500 my_ancestor = my_ancestor->parent;
503 if(!new_child->node->parent)
504 if(xmldoc_remove_orphan(new_child->node->doc, new_child->node) != S_OK)
505 WARN("%p is not an orphan of %p\n", new_child->node, new_child->node->doc);
507 leaving_doc = new_child->node->doc;
508 xmldoc_add_ref(old_child->node->doc);
509 xmlReplaceNode(old_child->node, new_child->node);
510 xmldoc_release(leaving_doc);
512 xmldoc_add_orphan(old_child->node->doc, old_child->node);
514 if(outOldChild)
516 IXMLDOMNode_AddRef(oldChild);
517 *outOldChild = oldChild;
520 return S_OK;
523 static HRESULT WINAPI xmlnode_removeChild(
524 IXMLDOMNode *iface,
525 IXMLDOMNode* childNode,
526 IXMLDOMNode** oldChild)
528 xmlnode *This = impl_from_IXMLDOMNode( iface );
529 xmlnode *child_node;
531 TRACE("(%p)->(%p %p)\n", This, childNode, oldChild);
533 if(!childNode) return E_INVALIDARG;
535 if(oldChild)
536 *oldChild = NULL;
538 child_node = get_node_obj(childNode);
539 if(!child_node) {
540 FIXME("childNode is not our node implementation\n");
541 return E_FAIL;
544 if(child_node->node->parent != This->node)
546 WARN("childNode %p is not a child of %p\n", childNode, iface);
547 return E_INVALIDARG;
550 xmlUnlinkNode(child_node->node);
552 if(oldChild)
554 IXMLDOMNode_AddRef(childNode);
555 *oldChild = childNode;
558 return S_OK;
561 static HRESULT WINAPI xmlnode_appendChild(
562 IXMLDOMNode *iface,
563 IXMLDOMNode* newChild,
564 IXMLDOMNode** outNewChild)
566 xmlnode *This = impl_from_IXMLDOMNode( iface );
567 DOMNodeType type;
568 VARIANT var;
569 HRESULT hr;
571 TRACE("(%p)->(%p %p)\n", This, newChild, outNewChild);
573 hr = IXMLDOMNode_get_nodeType(newChild, &type);
574 if(FAILED(hr) || type == NODE_ATTRIBUTE) {
575 if(outNewChild) *outNewChild = NULL;
576 return E_FAIL;
579 VariantInit(&var);
580 return IXMLDOMNode_insertBefore(This->iface, newChild, var, outNewChild);
583 static HRESULT WINAPI xmlnode_hasChildNodes(
584 IXMLDOMNode *iface,
585 VARIANT_BOOL* hasChild)
587 xmlnode *This = impl_from_IXMLDOMNode( iface );
589 TRACE("(%p)->(%p)\n", This, hasChild);
591 if (!hasChild)
592 return E_INVALIDARG;
593 if (!This->node->children)
595 *hasChild = VARIANT_FALSE;
596 return S_FALSE;
599 *hasChild = VARIANT_TRUE;
600 return S_OK;
603 static HRESULT WINAPI xmlnode_get_ownerDocument(
604 IXMLDOMNode *iface,
605 IXMLDOMDocument** DOMDocument)
607 xmlnode *This = impl_from_IXMLDOMNode( iface );
609 TRACE("(%p)->(%p)\n", This, DOMDocument);
611 return DOMDocument_create_from_xmldoc(This->node->doc, (IXMLDOMDocument3**)DOMDocument);
614 static HRESULT WINAPI xmlnode_cloneNode(
615 IXMLDOMNode *iface,
616 VARIANT_BOOL deep,
617 IXMLDOMNode** cloneRoot)
619 xmlnode *This = impl_from_IXMLDOMNode( iface );
620 xmlNodePtr pClone = NULL;
621 IXMLDOMNode *pNode = NULL;
623 TRACE("(%p)->(%d %p)\n", This, deep, cloneRoot);
625 if(!cloneRoot)
626 return E_INVALIDARG;
628 pClone = xmlCopyNode(This->node, deep ? 1 : 2);
629 if(pClone)
631 pClone->doc = This->node->doc;
632 xmldoc_add_orphan(pClone->doc, pClone);
634 pNode = create_node(pClone);
635 if(!pNode)
637 ERR("Copy failed\n");
638 return E_FAIL;
641 *cloneRoot = pNode;
643 else
645 ERR("Copy failed\n");
646 return E_FAIL;
649 return S_OK;
652 static HRESULT WINAPI xmlnode_get_nodeTypeString(
653 IXMLDOMNode *iface,
654 BSTR* xmlnodeType)
656 xmlnode *This = impl_from_IXMLDOMNode( iface );
657 const xmlChar *str;
659 TRACE("(%p)->(%p)\n", This, xmlnodeType );
661 if (!xmlnodeType)
662 return E_INVALIDARG;
664 if ( !This->node )
665 return E_FAIL;
667 switch( This->node->type )
669 case XML_ATTRIBUTE_NODE:
670 str = (const xmlChar*) "attribute";
671 break;
672 case XML_CDATA_SECTION_NODE:
673 str = (const xmlChar*) "cdatasection";
674 break;
675 case XML_COMMENT_NODE:
676 str = (const xmlChar*) "comment";
677 break;
678 case XML_DOCUMENT_NODE:
679 str = (const xmlChar*) "document";
680 break;
681 case XML_DOCUMENT_FRAG_NODE:
682 str = (const xmlChar*) "documentfragment";
683 break;
684 case XML_ELEMENT_NODE:
685 str = (const xmlChar*) "element";
686 break;
687 case XML_ENTITY_NODE:
688 str = (const xmlChar*) "entity";
689 break;
690 case XML_ENTITY_REF_NODE:
691 str = (const xmlChar*) "entityreference";
692 break;
693 case XML_NOTATION_NODE:
694 str = (const xmlChar*) "notation";
695 break;
696 case XML_PI_NODE:
697 str = (const xmlChar*) "processinginstruction";
698 break;
699 case XML_TEXT_NODE:
700 str = (const xmlChar*) "text";
701 break;
702 default:
703 FIXME("Unknown node type (%d)\n", This->node->type);
704 str = This->node->name;
705 break;
708 *xmlnodeType = bstr_from_xmlChar( str );
709 if (!*xmlnodeType)
710 return S_FALSE;
712 return S_OK;
715 static HRESULT WINAPI xmlnode_get_text(
716 IXMLDOMNode *iface,
717 BSTR* text)
719 xmlnode *This = impl_from_IXMLDOMNode( iface );
720 BSTR str = NULL;
721 xmlChar *pContent;
723 TRACE("(%p, type %d)->(%p)\n", This, This->node->type, text);
725 if ( !text )
726 return E_INVALIDARG;
728 pContent = xmlNodeGetContent((xmlNodePtr)This->node);
729 if(pContent)
731 str = bstr_from_xmlChar(pContent);
732 xmlFree(pContent);
735 /* Always return a string. */
736 if (!str) str = SysAllocStringLen( NULL, 0 );
738 TRACE("%p %s\n", This, debugstr_w(str) );
739 *text = str;
741 return S_OK;
744 static HRESULT WINAPI xmlnode_put_text(
745 IXMLDOMNode *iface,
746 BSTR text)
748 xmlnode *This = impl_from_IXMLDOMNode( iface );
749 xmlChar *str, *str2;
751 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
753 switch(This->node->type)
755 case XML_DOCUMENT_NODE:
756 return E_FAIL;
757 default:
758 break;
761 str = xmlChar_from_wchar(text);
763 /* Escape the string. */
764 str2 = xmlEncodeEntitiesReentrant(This->node->doc, str);
765 heap_free(str);
767 xmlNodeSetContent(This->node, str2);
768 xmlFree(str2);
770 return S_OK;
773 static HRESULT WINAPI xmlnode_get_specified(
774 IXMLDOMNode *iface,
775 VARIANT_BOOL* isSpecified)
777 xmlnode *This = impl_from_IXMLDOMNode( iface );
778 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
779 *isSpecified = VARIANT_TRUE;
780 return S_OK;
783 static HRESULT WINAPI xmlnode_get_definition(
784 IXMLDOMNode *iface,
785 IXMLDOMNode** definitionNode)
787 xmlnode *This = impl_from_IXMLDOMNode( iface );
788 FIXME("(%p)->(%p)\n", This, definitionNode);
789 return E_NOTIMPL;
792 static inline BYTE hex_to_byte(xmlChar c)
794 if(c <= '9') return c-'0';
795 if(c <= 'F') return c-'A'+10;
796 return c-'a'+10;
799 static inline BYTE base64_to_byte(xmlChar c)
801 if(c == '+') return 62;
802 if(c == '/') return 63;
803 if(c <= '9') return c-'0'+52;
804 if(c <= 'Z') return c-'A';
805 return c-'a'+26;
808 static inline HRESULT VARIANT_from_xmlChar(xmlChar *str, VARIANT *v, BSTR type)
810 if(!type || !lstrcmpiW(type, szString) ||
811 !lstrcmpiW(type, szNumber) || !lstrcmpiW(type, szUUID))
813 V_VT(v) = VT_BSTR;
814 V_BSTR(v) = bstr_from_xmlChar(str);
816 if(!V_BSTR(v))
817 return E_OUTOFMEMORY;
819 else if(!lstrcmpiW(type, szDateTime) || !lstrcmpiW(type, szDateTimeTZ) ||
820 !lstrcmpiW(type, szDate) || !lstrcmpiW(type, szTime) ||
821 !lstrcmpiW(type, szTimeTZ))
823 VARIANT src;
824 WCHAR *p, *e;
825 SYSTEMTIME st;
826 DOUBLE date = 0.0;
828 st.wYear = 1899;
829 st.wMonth = 12;
830 st.wDay = 30;
831 st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
833 V_VT(&src) = VT_BSTR;
834 V_BSTR(&src) = bstr_from_xmlChar(str);
836 if(!V_BSTR(&src))
837 return E_OUTOFMEMORY;
839 p = V_BSTR(&src);
840 e = p + SysStringLen(V_BSTR(&src));
842 if(p+4<e && *(p+4)=='-') /* parse date (yyyy-mm-dd) */
844 st.wYear = atoiW(p);
845 st.wMonth = atoiW(p+5);
846 st.wDay = atoiW(p+8);
847 p += 10;
849 if(*p == 'T') p++;
852 if(p+2<e && *(p+2)==':') /* parse time (hh:mm:ss.?) */
854 st.wHour = atoiW(p);
855 st.wMinute = atoiW(p+3);
856 st.wSecond = atoiW(p+6);
857 p += 8;
859 if(*p == '.')
861 p++;
862 while(isdigitW(*p)) p++;
866 SystemTimeToVariantTime(&st, &date);
867 V_VT(v) = VT_DATE;
868 V_DATE(v) = date;
870 if(*p == '+') /* parse timezone offset (+hh:mm) */
871 V_DATE(v) += (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
872 else if(*p == '-') /* parse timezone offset (-hh:mm) */
873 V_DATE(v) -= (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
875 VariantClear(&src);
877 else if(!lstrcmpiW(type, szBinHex))
879 SAFEARRAYBOUND sab;
880 int i, len;
882 len = xmlStrlen(str)/2;
883 sab.lLbound = 0;
884 sab.cElements = len;
886 V_VT(v) = (VT_ARRAY|VT_UI1);
887 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
889 if(!V_ARRAY(v))
890 return E_OUTOFMEMORY;
892 for(i=0; i<len; i++)
893 ((BYTE*)V_ARRAY(v)->pvData)[i] = (hex_to_byte(str[2*i])<<4)
894 + hex_to_byte(str[2*i+1]);
896 else if(!lstrcmpiW(type, szBinBase64))
898 SAFEARRAYBOUND sab;
899 int i, len;
901 len = xmlStrlen(str);
902 if(str[len-2] == '=') i = 2;
903 else if(str[len-1] == '=') i = 1;
904 else i = 0;
906 sab.lLbound = 0;
907 sab.cElements = len/4*3-i;
909 V_VT(v) = (VT_ARRAY|VT_UI1);
910 V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
912 if(!V_ARRAY(v))
913 return E_OUTOFMEMORY;
915 for(i=0; i<len/4; i++)
917 ((BYTE*)V_ARRAY(v)->pvData)[3*i] = (base64_to_byte(str[4*i])<<2)
918 + (base64_to_byte(str[4*i+1])>>4);
919 if(3*i+1 < sab.cElements)
920 ((BYTE*)V_ARRAY(v)->pvData)[3*i+1] = (base64_to_byte(str[4*i+1])<<4)
921 + (base64_to_byte(str[4*i+2])>>2);
922 if(3*i+2 < sab.cElements)
923 ((BYTE*)V_ARRAY(v)->pvData)[3*i+2] = (base64_to_byte(str[4*i+2])<<6)
924 + base64_to_byte(str[4*i+3]);
927 else
929 VARIANT src;
930 HRESULT hres;
932 if(!lstrcmpiW(type, szInt) || !lstrcmpiW(type, szI4))
933 V_VT(v) = VT_I4;
934 else if(!lstrcmpiW(type, szFixed))
935 V_VT(v) = VT_CY;
936 else if(!lstrcmpiW(type, szBoolean))
937 V_VT(v) = VT_BOOL;
938 else if(!lstrcmpiW(type, szI1))
939 V_VT(v) = VT_I1;
940 else if(!lstrcmpiW(type, szI2))
941 V_VT(v) = VT_I2;
942 else if(!lstrcmpiW(type, szIU1))
943 V_VT(v) = VT_UI1;
944 else if(!lstrcmpiW(type, szIU2))
945 V_VT(v) = VT_UI2;
946 else if(!lstrcmpiW(type, szIU4))
947 V_VT(v) = VT_UI4;
948 else if(!lstrcmpiW(type, szR4))
949 V_VT(v) = VT_R4;
950 else if(!lstrcmpiW(type, szR8) || !lstrcmpiW(type, szFloat))
951 V_VT(v) = VT_R8;
952 else
954 FIXME("Type handling not yet implemented\n");
955 V_VT(v) = VT_BSTR;
958 V_VT(&src) = VT_BSTR;
959 V_BSTR(&src) = bstr_from_xmlChar(str);
961 if(!V_BSTR(&src))
962 return E_OUTOFMEMORY;
964 hres = VariantChangeTypeEx(v, &src, MAKELCID(MAKELANGID(
965 LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),0, V_VT(v));
966 VariantClear(&src);
967 return hres;
970 return S_OK;
973 static HRESULT WINAPI xmlnode_get_nodeTypedValue(
974 IXMLDOMNode *iface,
975 VARIANT* typedValue)
977 xmlnode *This = impl_from_IXMLDOMNode( iface );
978 VARIANT type;
979 xmlChar *content;
980 HRESULT hres = S_FALSE;
982 TRACE("(%p)->(%p)\n", This, typedValue);
984 if(!typedValue)
985 return E_INVALIDARG;
987 V_VT(typedValue) = VT_NULL;
989 if(This->node->type == XML_ELEMENT_NODE ||
990 This->node->type == XML_TEXT_NODE ||
991 This->node->type == XML_ENTITY_REF_NODE)
992 hres = IXMLDOMNode_get_dataType(This->iface, &type);
994 if(hres != S_OK && This->node->type != XML_ELEMENT_NODE)
995 return IXMLDOMNode_get_nodeValue(This->iface, typedValue);
997 content = xmlNodeGetContent(This->node);
998 hres = VARIANT_from_xmlChar(content, typedValue,
999 hres==S_OK ? V_BSTR(&type) : NULL);
1000 xmlFree(content);
1001 VariantClear(&type);
1003 return hres;
1006 static HRESULT WINAPI xmlnode_put_nodeTypedValue(
1007 IXMLDOMNode *iface,
1008 VARIANT typedValue)
1010 xmlnode *This = impl_from_IXMLDOMNode( iface );
1011 FIXME("%p\n", This);
1012 return E_NOTIMPL;
1015 static HRESULT WINAPI xmlnode_get_dataType(
1016 IXMLDOMNode *iface,
1017 VARIANT* dataTypeName)
1019 xmlnode *This = impl_from_IXMLDOMNode( iface );
1020 xmlChar *pVal;
1022 TRACE("(%p)->(%p)\n", This, dataTypeName);
1024 if(!dataTypeName)
1025 return E_INVALIDARG;
1027 /* Attribute, CDATA Section, Comment, Document, Document Fragment,
1028 Entity, Notation, PI, and Text Node are non-typed. */
1029 V_BSTR(dataTypeName) = NULL;
1030 V_VT(dataTypeName) = VT_NULL;
1032 switch ( This->node->type )
1034 case XML_ELEMENT_NODE:
1035 pVal = xmlGetNsProp(This->node, (const xmlChar*)"dt",
1036 (const xmlChar*)"urn:schemas-microsoft-com:datatypes");
1037 if (pVal)
1039 V_VT(dataTypeName) = VT_BSTR;
1040 V_BSTR(dataTypeName) = bstr_from_xmlChar( pVal );
1041 xmlFree(pVal);
1043 break;
1044 case XML_ENTITY_REF_NODE:
1045 FIXME("XML_ENTITY_REF_NODE should return a valid value.\n");
1046 break;
1047 default:
1048 TRACE("Type %d returning NULL\n", This->node->type);
1051 /* non-typed nodes return S_FALSE */
1052 if(V_VT(dataTypeName) == VT_NULL)
1054 return S_FALSE;
1057 return S_OK;
1060 static HRESULT WINAPI xmlnode_put_dataType(
1061 IXMLDOMNode *iface,
1062 BSTR dataTypeName)
1064 xmlnode *This = impl_from_IXMLDOMNode( iface );
1065 HRESULT hr = E_FAIL;
1067 TRACE("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
1069 if(dataTypeName == NULL)
1070 return E_INVALIDARG;
1072 /* An example of this is. The Text in the node needs to be a 0 or 1 for a boolean type.
1073 This applies to changing types (string->bool) or setting a new one
1075 FIXME("Need to Validate the data before allowing a type to be set.\n");
1077 /* Check all supported types. */
1078 if(lstrcmpiW(dataTypeName,szString) == 0 ||
1079 lstrcmpiW(dataTypeName,szNumber) == 0 ||
1080 lstrcmpiW(dataTypeName,szUUID) == 0 ||
1081 lstrcmpiW(dataTypeName,szInt) == 0 ||
1082 lstrcmpiW(dataTypeName,szI4) == 0 ||
1083 lstrcmpiW(dataTypeName,szFixed) == 0 ||
1084 lstrcmpiW(dataTypeName,szBoolean) == 0 ||
1085 lstrcmpiW(dataTypeName,szDateTime) == 0 ||
1086 lstrcmpiW(dataTypeName,szDateTimeTZ) == 0 ||
1087 lstrcmpiW(dataTypeName,szDate) == 0 ||
1088 lstrcmpiW(dataTypeName,szTime) == 0 ||
1089 lstrcmpiW(dataTypeName,szTimeTZ) == 0 ||
1090 lstrcmpiW(dataTypeName,szI1) == 0 ||
1091 lstrcmpiW(dataTypeName,szI2) == 0 ||
1092 lstrcmpiW(dataTypeName,szIU1) == 0 ||
1093 lstrcmpiW(dataTypeName,szIU2) == 0 ||
1094 lstrcmpiW(dataTypeName,szIU4) == 0 ||
1095 lstrcmpiW(dataTypeName,szR4) == 0 ||
1096 lstrcmpiW(dataTypeName,szR8) == 0 ||
1097 lstrcmpiW(dataTypeName,szFloat) == 0 ||
1098 lstrcmpiW(dataTypeName,szBinHex) == 0 ||
1099 lstrcmpiW(dataTypeName,szBinBase64) == 0)
1101 xmlChar* str = xmlChar_from_wchar(dataTypeName);
1102 xmlAttrPtr attr;
1104 if (!str) return E_OUTOFMEMORY;
1106 attr = xmlHasNsProp(This->node, (const xmlChar*)"dt",
1107 (const xmlChar*)"urn:schemas-microsoft-com:datatypes");
1108 if (attr)
1110 attr = xmlSetNsProp(This->node, attr->ns, (const xmlChar*)"dt", str);
1111 hr = S_OK;
1113 else
1115 xmlNsPtr ns = xmlNewNs(This->node, (const xmlChar*)"urn:schemas-microsoft-com:datatypes", (const xmlChar*)"dt");
1116 if (ns)
1118 attr = xmlNewNsProp(This->node, ns, (const xmlChar*)"dt", str);
1119 if (attr)
1121 xmlAddChild(This->node, (xmlNodePtr)attr);
1122 hr = S_OK;
1124 else
1125 ERR("Failed to create Attribute\n");
1127 else
1128 ERR("Failed to create Namespace\n");
1130 heap_free( str );
1133 return hr;
1136 static BSTR EnsureCorrectEOL(BSTR sInput)
1138 int nNum = 0;
1139 BSTR sNew;
1140 int nLen;
1141 int i;
1143 nLen = lstrlenW(sInput);
1144 /* Count line endings */
1145 for(i=0; i < nLen; i++)
1147 if(sInput[i] == '\n')
1148 nNum++;
1151 TRACE("len=%d, num=%d\n", nLen, nNum);
1153 /* Add linefeed as needed */
1154 if(nNum > 0)
1156 int nPlace = 0;
1157 sNew = SysAllocStringLen(NULL, nLen + nNum+1);
1158 for(i=0; i < nLen; i++)
1160 if(sInput[i] == '\n')
1162 sNew[i+nPlace] = '\r';
1163 nPlace++;
1165 sNew[i+nPlace] = sInput[i];
1168 SysFreeString(sInput);
1170 else
1172 sNew = sInput;
1175 TRACE("len %d\n", lstrlenW(sNew));
1177 return sNew;
1180 /* Removes encoding information and last character (nullbyte) */
1181 static BSTR EnsureNoEncoding(BSTR sInput)
1183 static const WCHAR wszEncoding[] = {'e','n','c','o','d','i','n','g','='};
1184 BSTR sNew;
1185 WCHAR *pBeg, *pEnd;
1187 pBeg = sInput;
1188 while(*pBeg != '\n' && memcmp(pBeg, wszEncoding, sizeof(wszEncoding)))
1189 pBeg++;
1191 if(*pBeg == '\n')
1193 SysReAllocStringLen(&sInput, sInput, SysStringLen(sInput)-1);
1194 return sInput;
1196 pBeg--;
1198 pEnd = pBeg + sizeof(wszEncoding)/sizeof(WCHAR) + 2;
1199 while(*pEnd != '\"') pEnd++;
1200 pEnd++;
1202 sNew = SysAllocStringLen(NULL,
1203 pBeg-sInput + SysStringLen(sInput)-(pEnd-sInput)-1);
1204 memcpy(sNew, sInput, (pBeg-sInput)*sizeof(WCHAR));
1205 memcpy(&sNew[pBeg-sInput], pEnd, (SysStringLen(sInput)-(pEnd-sInput)-1)*sizeof(WCHAR));
1207 SysFreeString(sInput);
1208 return sNew;
1212 * We are trying to replicate the same behaviour as msxml by converting
1213 * line endings to \r\n and using indents as \t. The problem is that msxml
1214 * only formats nodes that have a line ending. Using libxml we cannot
1215 * reproduce behaviour exactly.
1218 static HRESULT WINAPI xmlnode_get_xml(
1219 IXMLDOMNode *iface,
1220 BSTR* xmlString)
1222 xmlnode *This = impl_from_IXMLDOMNode( iface );
1223 xmlBufferPtr pXmlBuf;
1224 xmlNodePtr xmldecl;
1225 int nSize;
1227 TRACE("(%p %d)->(%p)\n", This, This->node->type, xmlString);
1229 if(!xmlString)
1230 return E_INVALIDARG;
1232 *xmlString = NULL;
1234 xmldecl = xmldoc_unlink_xmldecl( This->node->doc );
1236 pXmlBuf = xmlBufferCreate();
1237 if(pXmlBuf)
1239 nSize = xmlNodeDump(pXmlBuf, This->node->doc, This->node, 0, 1);
1240 if(nSize > 0)
1242 const xmlChar *pContent;
1243 BSTR bstrContent;
1245 /* Attribute Nodes return a space in front of their name */
1246 pContent = xmlBufferContent(pXmlBuf);
1247 if( ((const char*)pContent)[0] == ' ')
1248 bstrContent = bstr_from_xmlChar(pContent+1);
1249 else
1250 bstrContent = bstr_from_xmlChar(pContent);
1252 switch(This->node->type)
1254 case XML_ELEMENT_NODE:
1255 *xmlString = EnsureCorrectEOL(bstrContent);
1256 break;
1257 case XML_DOCUMENT_NODE:
1258 *xmlString = EnsureCorrectEOL(bstrContent);
1259 *xmlString = EnsureNoEncoding(*xmlString);
1260 break;
1261 default:
1262 *xmlString = bstrContent;
1266 xmlBufferFree(pXmlBuf);
1269 xmldoc_link_xmldecl( This->node->doc, xmldecl );
1271 /* Always returns a string. */
1272 if(*xmlString == NULL) *xmlString = SysAllocStringLen( NULL, 0 );
1274 return S_OK;
1277 static HRESULT WINAPI xmlnode_transformNode(
1278 IXMLDOMNode *iface,
1279 IXMLDOMNode* styleSheet,
1280 BSTR* xmlString)
1282 #ifdef SONAME_LIBXSLT
1283 xmlnode *This = impl_from_IXMLDOMNode( iface );
1284 xmlnode *pStyleSheet = NULL;
1285 xsltStylesheetPtr xsltSS = NULL;
1286 xmlDocPtr result = NULL;
1288 TRACE("(%p)->(%p %p)\n", This, styleSheet, xmlString);
1290 if (!libxslt_handle)
1291 return E_NOTIMPL;
1292 if(!styleSheet || !xmlString)
1293 return E_INVALIDARG;
1295 *xmlString = NULL;
1297 pStyleSheet = get_node_obj(styleSheet);
1298 if(!pStyleSheet) {
1299 FIXME("styleSheet is not our xmlnode implementation\n");
1300 return E_FAIL;
1303 xsltSS = pxsltParseStylesheetDoc( pStyleSheet->node->doc);
1304 if(xsltSS)
1306 result = pxsltApplyStylesheet(xsltSS, This->node->doc, NULL);
1307 if(result)
1309 const xmlChar *pContent;
1311 if(result->type == XML_HTML_DOCUMENT_NODE)
1313 xmlOutputBufferPtr pOutput = xmlAllocOutputBuffer(NULL);
1314 if(pOutput)
1316 htmlDocContentDumpOutput(pOutput, result->doc, NULL);
1317 pContent = xmlBufferContent(pOutput->buffer);
1318 *xmlString = bstr_from_xmlChar(pContent);
1319 xmlOutputBufferClose(pOutput);
1322 else
1324 xmlBufferPtr pXmlBuf;
1325 int nSize;
1327 pXmlBuf = xmlBufferCreate();
1328 if(pXmlBuf)
1330 nSize = xmlNodeDump(pXmlBuf, NULL, (xmlNodePtr)result, 0, 0);
1331 if(nSize > 0)
1333 pContent = xmlBufferContent(pXmlBuf);
1334 *xmlString = bstr_from_xmlChar(pContent);
1336 xmlBufferFree(pXmlBuf);
1339 xmlFreeDoc(result);
1341 /* libxslt "helpfully" frees the XML document the stylesheet was
1342 generated from, too */
1343 xsltSS->doc = NULL;
1344 pxsltFreeStylesheet(xsltSS);
1347 if(*xmlString == NULL)
1348 *xmlString = SysAllocStringLen(NULL, 0);
1350 return S_OK;
1351 #else
1352 FIXME("libxslt headers were not found at compile time\n");
1353 return E_NOTIMPL;
1354 #endif
1357 static HRESULT WINAPI xmlnode_selectNodes(
1358 IXMLDOMNode *iface,
1359 BSTR queryString,
1360 IXMLDOMNodeList** resultList)
1362 xmlnode *This = impl_from_IXMLDOMNode( iface );
1364 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultList );
1366 if (!queryString || !resultList) return E_INVALIDARG;
1368 return queryresult_create( This->node, queryString, resultList );
1371 static HRESULT WINAPI xmlnode_selectSingleNode(
1372 IXMLDOMNode *iface,
1373 BSTR queryString,
1374 IXMLDOMNode** resultNode)
1376 xmlnode *This = impl_from_IXMLDOMNode( iface );
1377 IXMLDOMNodeList *list;
1378 HRESULT r;
1380 TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultNode );
1382 r = IXMLDOMNode_selectNodes(This->iface, queryString, &list);
1383 if(r == S_OK)
1385 r = IXMLDOMNodeList_nextNode(list, resultNode);
1386 IXMLDOMNodeList_Release(list);
1388 return r;
1391 static HRESULT WINAPI xmlnode_get_parsed(
1392 IXMLDOMNode *iface,
1393 VARIANT_BOOL* isParsed)
1395 xmlnode *This = impl_from_IXMLDOMNode( iface );
1396 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1397 *isParsed = VARIANT_TRUE;
1398 return S_OK;
1401 static HRESULT WINAPI xmlnode_get_namespaceURI(
1402 IXMLDOMNode *iface,
1403 BSTR* namespaceURI)
1405 xmlnode *This = impl_from_IXMLDOMNode( iface );
1406 xmlNsPtr *ns;
1408 TRACE("(%p)->(%p)\n", This, namespaceURI );
1410 if(!namespaceURI)
1411 return E_INVALIDARG;
1413 *namespaceURI = NULL;
1415 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1417 if (ns[0]->href) *namespaceURI = bstr_from_xmlChar( ns[0]->href );
1418 xmlFree(ns);
1421 TRACE("uri: %s\n", debugstr_w(*namespaceURI));
1423 return *namespaceURI ? S_OK : S_FALSE;
1426 static HRESULT WINAPI xmlnode_get_prefix(
1427 IXMLDOMNode *iface,
1428 BSTR* prefixString)
1430 xmlnode *This = impl_from_IXMLDOMNode( iface );
1431 xmlNsPtr *ns;
1433 TRACE("(%p)->(%p)\n", This, prefixString );
1435 if(!prefixString)
1436 return E_INVALIDARG;
1438 *prefixString = NULL;
1440 if ((ns = xmlGetNsList(This->node->doc, This->node)))
1442 if (ns[0]->prefix) *prefixString = bstr_from_xmlChar( ns[0]->prefix );
1443 xmlFree(ns);
1446 TRACE("prefix: %s\n", debugstr_w(*prefixString));
1448 return *prefixString ? S_OK : S_FALSE;
1451 static HRESULT WINAPI xmlnode_get_baseName(
1452 IXMLDOMNode *iface,
1453 BSTR* nameString)
1455 xmlnode *This = impl_from_IXMLDOMNode( iface );
1456 BSTR str = NULL;
1457 HRESULT r = S_FALSE;
1459 TRACE("(%p)->(%p)\n", This, nameString );
1461 if ( !nameString )
1462 return E_INVALIDARG;
1464 switch ( This->node->type )
1466 case XML_ELEMENT_NODE:
1467 case XML_ATTRIBUTE_NODE:
1468 case XML_PI_NODE:
1469 str = bstr_from_xmlChar( This->node->name );
1470 r = S_OK;
1471 break;
1472 case XML_TEXT_NODE:
1473 case XML_COMMENT_NODE:
1474 case XML_DOCUMENT_NODE:
1475 break;
1476 default:
1477 ERR("Unhandled type %d\n", This->node->type );
1478 break;
1481 TRACE("returning %08x str = %s\n", r, debugstr_w( str ) );
1483 *nameString = str;
1484 return r;
1487 static HRESULT WINAPI xmlnode_transformNodeToObject(
1488 IXMLDOMNode *iface,
1489 IXMLDOMNode* stylesheet,
1490 VARIANT outputObject)
1492 xmlnode *This = impl_from_IXMLDOMNode( iface );
1493 FIXME("(%p)->(%p)\n", This, stylesheet);
1494 return E_NOTIMPL;
1497 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
1499 xmlnode_QueryInterface,
1500 xmlnode_AddRef,
1501 xmlnode_Release,
1502 xmlnode_GetTypeInfoCount,
1503 xmlnode_GetTypeInfo,
1504 xmlnode_GetIDsOfNames,
1505 xmlnode_Invoke,
1506 xmlnode_get_nodeName,
1507 xmlnode_get_nodeValue,
1508 xmlnode_put_nodeValue,
1509 xmlnode_get_nodeType,
1510 xmlnode_get_parentNode,
1511 xmlnode_get_childNodes,
1512 xmlnode_get_firstChild,
1513 xmlnode_get_lastChild,
1514 xmlnode_get_previousSibling,
1515 xmlnode_get_nextSibling,
1516 xmlnode_get_attributes,
1517 xmlnode_insertBefore,
1518 xmlnode_replaceChild,
1519 xmlnode_removeChild,
1520 xmlnode_appendChild,
1521 xmlnode_hasChildNodes,
1522 xmlnode_get_ownerDocument,
1523 xmlnode_cloneNode,
1524 xmlnode_get_nodeTypeString,
1525 xmlnode_get_text,
1526 xmlnode_put_text,
1527 xmlnode_get_specified,
1528 xmlnode_get_definition,
1529 xmlnode_get_nodeTypedValue,
1530 xmlnode_put_nodeTypedValue,
1531 xmlnode_get_dataType,
1532 xmlnode_put_dataType,
1533 xmlnode_get_xml,
1534 xmlnode_transformNode,
1535 xmlnode_selectNodes,
1536 xmlnode_selectSingleNode,
1537 xmlnode_get_parsed,
1538 xmlnode_get_namespaceURI,
1539 xmlnode_get_prefix,
1540 xmlnode_get_baseName,
1541 xmlnode_transformNodeToObject,
1544 void destroy_xmlnode(xmlnode *This)
1546 if(This->node)
1547 xmldoc_release(This->node->doc);
1550 void init_xmlnode(xmlnode *This, xmlNodePtr node, IXMLDOMNode *node_iface, dispex_static_data_t *dispex_data)
1552 if(node)
1553 xmldoc_add_ref( node->doc );
1555 This->lpVtbl = &xmlnode_vtbl;
1556 This->node = node;
1557 This->iface = node_iface;
1559 if(dispex_data)
1560 init_dispex(&This->dispex, (IUnknown*)This->iface, dispex_data);
1561 else
1562 This->dispex.outer = NULL;
1565 typedef struct {
1566 xmlnode node;
1567 const IXMLDOMNodeVtbl *lpVtbl;
1568 LONG ref;
1569 } unknode;
1571 static inline unknode *impl_from_unkIXMLDOMNode(IXMLDOMNode *iface)
1573 return (unknode *)((char*)iface - FIELD_OFFSET(unknode, lpVtbl));
1576 static HRESULT WINAPI unknode_QueryInterface(
1577 IXMLDOMNode *iface,
1578 REFIID riid,
1579 void** ppvObject )
1581 unknode *This = impl_from_unkIXMLDOMNode( iface );
1583 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1585 if (IsEqualGUID(riid, &IID_IUnknown)) {
1586 *ppvObject = iface;
1587 }else if (IsEqualGUID( riid, &IID_IDispatch) ||
1588 IsEqualGUID( riid, &IID_IXMLDOMNode)) {
1589 *ppvObject = &This->lpVtbl;
1590 }else if(node_query_interface(&This->node, riid, ppvObject)) {
1591 return *ppvObject ? S_OK : E_NOINTERFACE;
1592 }else {
1593 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1594 *ppvObject = NULL;
1595 return E_NOINTERFACE;
1598 IUnknown_AddRef((IUnknown*)*ppvObject);
1599 return S_OK;
1602 static ULONG WINAPI unknode_AddRef(
1603 IXMLDOMNode *iface )
1605 unknode *This = impl_from_unkIXMLDOMNode( iface );
1607 return InterlockedIncrement(&This->ref);
1610 static ULONG WINAPI unknode_Release(
1611 IXMLDOMNode *iface )
1613 unknode *This = impl_from_unkIXMLDOMNode( iface );
1614 LONG ref;
1616 ref = InterlockedDecrement( &This->ref );
1617 if(!ref) {
1618 destroy_xmlnode(&This->node);
1619 heap_free(This);
1622 return ref;
1625 static HRESULT WINAPI unknode_GetTypeInfoCount(
1626 IXMLDOMNode *iface,
1627 UINT* pctinfo )
1629 unknode *This = impl_from_unkIXMLDOMNode( iface );
1631 TRACE("(%p)->(%p)\n", This, pctinfo);
1633 *pctinfo = 1;
1635 return S_OK;
1638 static HRESULT WINAPI unknode_GetTypeInfo(
1639 IXMLDOMNode *iface,
1640 UINT iTInfo,
1641 LCID lcid,
1642 ITypeInfo** ppTInfo )
1644 unknode *This = impl_from_unkIXMLDOMNode( iface );
1645 HRESULT hr;
1647 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1649 hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
1651 return hr;
1654 static HRESULT WINAPI unknode_GetIDsOfNames(
1655 IXMLDOMNode *iface,
1656 REFIID riid,
1657 LPOLESTR* rgszNames,
1658 UINT cNames,
1659 LCID lcid,
1660 DISPID* rgDispId )
1662 unknode *This = impl_from_unkIXMLDOMNode( iface );
1664 ITypeInfo *typeinfo;
1665 HRESULT hr;
1667 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1668 lcid, rgDispId);
1670 if(!rgszNames || cNames == 0 || !rgDispId)
1671 return E_INVALIDARG;
1673 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1674 if(SUCCEEDED(hr))
1676 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1677 ITypeInfo_Release(typeinfo);
1680 return hr;
1683 static HRESULT WINAPI unknode_Invoke(
1684 IXMLDOMNode *iface,
1685 DISPID dispIdMember,
1686 REFIID riid,
1687 LCID lcid,
1688 WORD wFlags,
1689 DISPPARAMS* pDispParams,
1690 VARIANT* pVarResult,
1691 EXCEPINFO* pExcepInfo,
1692 UINT* puArgErr )
1694 unknode *This = impl_from_unkIXMLDOMNode( iface );
1695 ITypeInfo *typeinfo;
1696 HRESULT hr;
1698 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1699 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1701 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1702 if(SUCCEEDED(hr))
1704 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
1705 pVarResult, pExcepInfo, puArgErr);
1706 ITypeInfo_Release(typeinfo);
1709 return hr;
1712 static HRESULT WINAPI unknode_get_nodeName(
1713 IXMLDOMNode *iface,
1714 BSTR* p )
1716 unknode *This = impl_from_unkIXMLDOMNode( iface );
1718 FIXME("(%p)->(%p)\n", This, p);
1720 return node_get_nodeName(&This->node, p);
1723 static HRESULT WINAPI unknode_get_nodeValue(
1724 IXMLDOMNode *iface,
1725 VARIANT* value)
1727 unknode *This = impl_from_unkIXMLDOMNode( iface );
1729 FIXME("(%p)->(%p)\n", This, value);
1731 if(!value)
1732 return E_INVALIDARG;
1734 V_VT(value) = VT_NULL;
1735 return S_FALSE;
1738 static HRESULT WINAPI unknode_put_nodeValue(
1739 IXMLDOMNode *iface,
1740 VARIANT value)
1742 unknode *This = impl_from_unkIXMLDOMNode( iface );
1743 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
1744 return E_FAIL;
1747 static HRESULT WINAPI unknode_get_nodeType(
1748 IXMLDOMNode *iface,
1749 DOMNodeType* domNodeType )
1751 unknode *This = impl_from_unkIXMLDOMNode( iface );
1753 FIXME("(%p)->(%p)\n", This, domNodeType);
1755 *domNodeType = This->node.node->type;
1756 return S_OK;
1759 static HRESULT WINAPI unknode_get_parentNode(
1760 IXMLDOMNode *iface,
1761 IXMLDOMNode** parent )
1763 unknode *This = impl_from_unkIXMLDOMNode( iface );
1764 FIXME("(%p)->(%p)\n", This, parent);
1765 if (!parent) return E_INVALIDARG;
1766 *parent = NULL;
1767 return S_FALSE;
1770 static HRESULT WINAPI unknode_get_childNodes(
1771 IXMLDOMNode *iface,
1772 IXMLDOMNodeList** outList)
1774 unknode *This = impl_from_unkIXMLDOMNode( iface );
1776 TRACE("(%p)->(%p)\n", This, outList);
1778 return node_get_child_nodes(&This->node, outList);
1781 static HRESULT WINAPI unknode_get_firstChild(
1782 IXMLDOMNode *iface,
1783 IXMLDOMNode** domNode)
1785 unknode *This = impl_from_unkIXMLDOMNode( iface );
1787 TRACE("(%p)->(%p)\n", This, domNode);
1789 return node_get_first_child(&This->node, domNode);
1792 static HRESULT WINAPI unknode_get_lastChild(
1793 IXMLDOMNode *iface,
1794 IXMLDOMNode** domNode)
1796 unknode *This = impl_from_unkIXMLDOMNode( iface );
1798 TRACE("(%p)->(%p)\n", This, domNode);
1800 return node_get_last_child(&This->node, domNode);
1803 static HRESULT WINAPI unknode_get_previousSibling(
1804 IXMLDOMNode *iface,
1805 IXMLDOMNode** domNode)
1807 unknode *This = impl_from_unkIXMLDOMNode( iface );
1809 TRACE("(%p)->(%p)\n", This, domNode);
1811 return node_get_previous_sibling(&This->node, domNode);
1814 static HRESULT WINAPI unknode_get_nextSibling(
1815 IXMLDOMNode *iface,
1816 IXMLDOMNode** domNode)
1818 unknode *This = impl_from_unkIXMLDOMNode( iface );
1820 TRACE("(%p)->(%p)\n", This, domNode);
1822 return node_get_next_sibling(&This->node, domNode);
1825 static HRESULT WINAPI unknode_get_attributes(
1826 IXMLDOMNode *iface,
1827 IXMLDOMNamedNodeMap** attributeMap)
1829 unknode *This = impl_from_unkIXMLDOMNode( iface );
1831 FIXME("(%p)->(%p)\n", This, attributeMap);
1833 return return_null_ptr((void**)attributeMap);
1836 static HRESULT WINAPI unknode_insertBefore(
1837 IXMLDOMNode *iface,
1838 IXMLDOMNode* newNode, VARIANT refChild,
1839 IXMLDOMNode** outOldNode)
1841 unknode *This = impl_from_unkIXMLDOMNode( iface );
1843 FIXME("(%p)->(%p x%d %p)\n", This, newNode, V_VT(&refChild), outOldNode);
1845 return node_insert_before(&This->node, newNode, &refChild, outOldNode);
1848 static HRESULT WINAPI unknode_replaceChild(
1849 IXMLDOMNode *iface,
1850 IXMLDOMNode* newNode,
1851 IXMLDOMNode* oldNode,
1852 IXMLDOMNode** outOldNode)
1854 unknode *This = impl_from_unkIXMLDOMNode( iface );
1855 return IXMLDOMNode_replaceChild( IXMLDOMNode_from_impl(&This->node), newNode, oldNode, outOldNode );
1858 static HRESULT WINAPI unknode_removeChild(
1859 IXMLDOMNode *iface,
1860 IXMLDOMNode* domNode, IXMLDOMNode** oldNode)
1862 unknode *This = impl_from_unkIXMLDOMNode( iface );
1863 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), domNode, oldNode );
1866 static HRESULT WINAPI unknode_appendChild(
1867 IXMLDOMNode *iface,
1868 IXMLDOMNode* newNode, IXMLDOMNode** outNewNode)
1870 unknode *This = impl_from_unkIXMLDOMNode( iface );
1871 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newNode, outNewNode );
1874 static HRESULT WINAPI unknode_hasChildNodes(
1875 IXMLDOMNode *iface,
1876 VARIANT_BOOL* pbool)
1878 unknode *This = impl_from_unkIXMLDOMNode( iface );
1879 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), pbool );
1882 static HRESULT WINAPI unknode_get_ownerDocument(
1883 IXMLDOMNode *iface,
1884 IXMLDOMDocument** domDocument)
1886 unknode *This = impl_from_unkIXMLDOMNode( iface );
1887 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), domDocument );
1890 static HRESULT WINAPI unknode_cloneNode(
1891 IXMLDOMNode *iface,
1892 VARIANT_BOOL pbool, IXMLDOMNode** outNode)
1894 unknode *This = impl_from_unkIXMLDOMNode( iface );
1895 return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), pbool, outNode );
1898 static HRESULT WINAPI unknode_get_nodeTypeString(
1899 IXMLDOMNode *iface,
1900 BSTR* p)
1902 unknode *This = impl_from_unkIXMLDOMNode( iface );
1903 return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), p );
1906 static HRESULT WINAPI unknode_get_text(
1907 IXMLDOMNode *iface,
1908 BSTR* p)
1910 unknode *This = impl_from_unkIXMLDOMNode( iface );
1911 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), p );
1914 static HRESULT WINAPI unknode_put_text(
1915 IXMLDOMNode *iface,
1916 BSTR p)
1918 unknode *This = impl_from_unkIXMLDOMNode( iface );
1919 return IXMLDOMNode_put_text( IXMLDOMNode_from_impl(&This->node), p );
1922 static HRESULT WINAPI unknode_get_specified(
1923 IXMLDOMNode *iface,
1924 VARIANT_BOOL* pbool)
1926 unknode *This = impl_from_unkIXMLDOMNode( iface );
1927 return IXMLDOMNode_get_specified( IXMLDOMNode_from_impl(&This->node), pbool );
1930 static HRESULT WINAPI unknode_get_definition(
1931 IXMLDOMNode *iface,
1932 IXMLDOMNode** domNode)
1934 unknode *This = impl_from_unkIXMLDOMNode( iface );
1935 return IXMLDOMNode_get_definition( IXMLDOMNode_from_impl(&This->node), domNode );
1938 static HRESULT WINAPI unknode_get_nodeTypedValue(
1939 IXMLDOMNode *iface,
1940 VARIANT* var1)
1942 unknode *This = impl_from_unkIXMLDOMNode( iface );
1943 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), var1 );
1946 static HRESULT WINAPI unknode_put_nodeTypedValue(
1947 IXMLDOMNode *iface,
1948 VARIANT var1)
1950 unknode *This = impl_from_unkIXMLDOMNode( iface );
1951 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), var1 );
1954 static HRESULT WINAPI unknode_get_dataType(
1955 IXMLDOMNode *iface,
1956 VARIANT* var1)
1958 unknode *This = impl_from_unkIXMLDOMNode( iface );
1959 return IXMLDOMNode_get_dataType( IXMLDOMNode_from_impl(&This->node), var1 );
1962 static HRESULT WINAPI unknode_put_dataType(
1963 IXMLDOMNode *iface,
1964 BSTR p)
1966 unknode *This = impl_from_unkIXMLDOMNode( iface );
1967 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), p );
1970 static HRESULT WINAPI unknode_get_xml(
1971 IXMLDOMNode *iface,
1972 BSTR* p)
1974 unknode *This = impl_from_unkIXMLDOMNode( iface );
1975 return IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), p );
1978 static HRESULT WINAPI unknode_transformNode(
1979 IXMLDOMNode *iface,
1980 IXMLDOMNode* domNode, BSTR* p)
1982 unknode *This = impl_from_unkIXMLDOMNode( iface );
1983 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), domNode, p );
1986 static HRESULT WINAPI unknode_selectNodes(
1987 IXMLDOMNode *iface,
1988 BSTR p, IXMLDOMNodeList** outList)
1990 unknode *This = impl_from_unkIXMLDOMNode( iface );
1991 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), p, outList );
1994 static HRESULT WINAPI unknode_selectSingleNode(
1995 IXMLDOMNode *iface,
1996 BSTR p, IXMLDOMNode** outNode)
1998 unknode *This = impl_from_unkIXMLDOMNode( iface );
1999 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), p, outNode );
2002 static HRESULT WINAPI unknode_get_parsed(
2003 IXMLDOMNode *iface,
2004 VARIANT_BOOL* pbool)
2006 unknode *This = impl_from_unkIXMLDOMNode( iface );
2007 return IXMLDOMNode_get_parsed( IXMLDOMNode_from_impl(&This->node), pbool );
2010 static HRESULT WINAPI unknode_get_namespaceURI(
2011 IXMLDOMNode *iface,
2012 BSTR* p)
2014 unknode *This = impl_from_unkIXMLDOMNode( iface );
2015 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), p );
2018 static HRESULT WINAPI unknode_get_prefix(
2019 IXMLDOMNode *iface,
2020 BSTR* p)
2022 unknode *This = impl_from_unkIXMLDOMNode( iface );
2023 return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), p );
2026 static HRESULT WINAPI unknode_get_baseName(
2027 IXMLDOMNode *iface,
2028 BSTR* p)
2030 unknode *This = impl_from_unkIXMLDOMNode( iface );
2031 return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), p );
2034 static HRESULT WINAPI unknode_transformNodeToObject(
2035 IXMLDOMNode *iface,
2036 IXMLDOMNode* domNode, VARIANT var1)
2038 unknode *This = impl_from_unkIXMLDOMNode( iface );
2039 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), domNode, var1 );
2042 static const struct IXMLDOMNodeVtbl unknode_vtbl =
2044 unknode_QueryInterface,
2045 unknode_AddRef,
2046 unknode_Release,
2047 unknode_GetTypeInfoCount,
2048 unknode_GetTypeInfo,
2049 unknode_GetIDsOfNames,
2050 unknode_Invoke,
2051 unknode_get_nodeName,
2052 unknode_get_nodeValue,
2053 unknode_put_nodeValue,
2054 unknode_get_nodeType,
2055 unknode_get_parentNode,
2056 unknode_get_childNodes,
2057 unknode_get_firstChild,
2058 unknode_get_lastChild,
2059 unknode_get_previousSibling,
2060 unknode_get_nextSibling,
2061 unknode_get_attributes,
2062 unknode_insertBefore,
2063 unknode_replaceChild,
2064 unknode_removeChild,
2065 unknode_appendChild,
2066 unknode_hasChildNodes,
2067 unknode_get_ownerDocument,
2068 unknode_cloneNode,
2069 unknode_get_nodeTypeString,
2070 unknode_get_text,
2071 unknode_put_text,
2072 unknode_get_specified,
2073 unknode_get_definition,
2074 unknode_get_nodeTypedValue,
2075 unknode_put_nodeTypedValue,
2076 unknode_get_dataType,
2077 unknode_put_dataType,
2078 unknode_get_xml,
2079 unknode_transformNode,
2080 unknode_selectNodes,
2081 unknode_selectSingleNode,
2082 unknode_get_parsed,
2083 unknode_get_namespaceURI,
2084 unknode_get_prefix,
2085 unknode_get_baseName,
2086 unknode_transformNodeToObject
2089 IXMLDOMNode *create_node( xmlNodePtr node )
2091 IUnknown *pUnk;
2092 IXMLDOMNode *ret;
2093 HRESULT hr;
2095 if ( !node )
2096 return NULL;
2098 TRACE("type %d\n", node->type);
2099 switch(node->type)
2101 case XML_ELEMENT_NODE:
2102 pUnk = create_element( node );
2103 break;
2104 case XML_ATTRIBUTE_NODE:
2105 pUnk = create_attribute( node );
2106 break;
2107 case XML_TEXT_NODE:
2108 pUnk = create_text( node );
2109 break;
2110 case XML_CDATA_SECTION_NODE:
2111 pUnk = create_cdata( node );
2112 break;
2113 case XML_ENTITY_REF_NODE:
2114 pUnk = create_doc_entity_ref( node );
2115 break;
2116 case XML_PI_NODE:
2117 pUnk = create_pi( node );
2118 break;
2119 case XML_COMMENT_NODE:
2120 pUnk = create_comment( node );
2121 break;
2122 case XML_DOCUMENT_NODE:
2123 pUnk = create_domdoc( node );
2124 break;
2125 case XML_DOCUMENT_FRAG_NODE:
2126 pUnk = create_doc_fragment( node );
2127 break;
2128 default: {
2129 unknode *new_node;
2131 FIXME("only creating basic node for type %d\n", node->type);
2133 new_node = heap_alloc(sizeof(unknode));
2134 if(!new_node)
2135 return NULL;
2137 new_node->lpVtbl = &unknode_vtbl;
2138 new_node->ref = 1;
2139 init_xmlnode(&new_node->node, node, (IXMLDOMNode*)&new_node->lpVtbl, NULL);
2140 pUnk = (IUnknown*)&new_node->lpVtbl;
2144 hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
2145 IUnknown_Release(pUnk);
2146 if(FAILED(hr)) return NULL;
2147 return ret;
2149 #endif