msxml3: Implement setNamedItem.
[wine/wine64.git] / dlls / msxml3 / node.c
blobfd86e4e4ff2865daed2b0f01c894121ab3ec0fd6
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 "msxml2.h"
34 #include "msxml_private.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
40 #ifdef HAVE_LIBXML2
42 static inline xmlnode *impl_from_InternalUnknown( IUnknown *iface )
44 return (xmlnode *)((char*)iface - FIELD_OFFSET(xmlnode, lpInternalUnkVtbl));
47 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type )
49 xmlnode *This;
51 if ( !iface )
52 return NULL;
53 This = impl_from_IXMLDOMNode( iface );
54 if ( !This->node )
55 return NULL;
56 if ( type && This->node->type != type )
57 return NULL;
58 return This->node;
61 void attach_xmlnode( IXMLDOMNode *node, xmlNodePtr xml )
63 xmlnode *This = impl_from_IXMLDOMNode( node );
65 if(This->node)
66 xmldoc_release(This->node->doc);
68 This->node = xml;
69 if(This->node)
70 xmldoc_add_ref(This->node->doc);
72 return;
75 static HRESULT WINAPI xmlnode_QueryInterface(
76 IXMLDOMNode *iface,
77 REFIID riid,
78 void** ppvObject )
80 xmlnode *This = impl_from_IXMLDOMNode( iface );
81 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
83 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObject);
86 static ULONG WINAPI xmlnode_AddRef(
87 IXMLDOMNode *iface )
89 xmlnode *This = impl_from_IXMLDOMNode( iface );
90 return IUnknown_AddRef(This->pUnkOuter);
93 static ULONG WINAPI xmlnode_Release(
94 IXMLDOMNode *iface )
96 xmlnode *This = impl_from_IXMLDOMNode( iface );
97 return IUnknown_Release(This->pUnkOuter);
100 static HRESULT WINAPI xmlnode_GetTypeInfoCount(
101 IXMLDOMNode *iface,
102 UINT* pctinfo )
104 FIXME("\n");
105 return E_NOTIMPL;
108 static HRESULT WINAPI xmlnode_GetTypeInfo(
109 IXMLDOMNode *iface,
110 UINT iTInfo,
111 LCID lcid,
112 ITypeInfo** ppTInfo )
114 FIXME("\n");
115 return E_NOTIMPL;
118 static HRESULT WINAPI xmlnode_GetIDsOfNames(
119 IXMLDOMNode *iface,
120 REFIID riid,
121 LPOLESTR* rgszNames,
122 UINT cNames,
123 LCID lcid,
124 DISPID* rgDispId )
126 FIXME("\n");
127 return E_NOTIMPL;
130 static HRESULT WINAPI xmlnode_Invoke(
131 IXMLDOMNode *iface,
132 DISPID dispIdMember,
133 REFIID riid,
134 LCID lcid,
135 WORD wFlags,
136 DISPPARAMS* pDispParams,
137 VARIANT* pVarResult,
138 EXCEPINFO* pExcepInfo,
139 UINT* puArgErr )
141 FIXME("\n");
142 return E_NOTIMPL;
145 static HRESULT WINAPI xmlnode_get_nodeName(
146 IXMLDOMNode *iface,
147 BSTR* name)
149 xmlnode *This = impl_from_IXMLDOMNode( iface );
150 const xmlChar *str;
152 TRACE("%p\n", This );
154 if (!name)
155 return E_INVALIDARG;
157 if ( !This->node )
158 return E_FAIL;
160 switch( This->node->type )
162 case XML_TEXT_NODE:
163 str = (const xmlChar*) "#text";
164 break;
165 case XML_DOCUMENT_NODE:
166 str = (const xmlChar*) "#document";
167 break;
168 default:
169 str = This->node->name;
170 break;
173 *name = bstr_from_xmlChar( str );
174 if (!*name)
175 return S_FALSE;
177 return S_OK;
180 BSTR bstr_from_xmlChar( const xmlChar *buf )
182 DWORD len;
183 LPWSTR str;
184 BSTR bstr;
186 if ( !buf )
187 return NULL;
189 len = MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) buf, -1, NULL, 0 );
190 str = (LPWSTR) HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
191 if ( !str )
192 return NULL;
193 MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) buf, -1, str, len );
194 bstr = SysAllocString( str );
195 HeapFree( GetProcessHeap(), 0, str );
196 return bstr;
199 static HRESULT WINAPI xmlnode_get_nodeValue(
200 IXMLDOMNode *iface,
201 VARIANT* value)
203 xmlnode *This = impl_from_IXMLDOMNode( iface );
204 HRESULT r = S_FALSE;
206 TRACE("%p %p\n", This, value);
208 if(!value)
209 return E_INVALIDARG;
211 V_BSTR(value) = NULL;
212 V_VT(value) = VT_NULL;
214 switch ( This->node->type )
216 case XML_ATTRIBUTE_NODE:
218 xmlChar *content = xmlNodeGetContent(This->node);
219 V_VT(value) = VT_BSTR;
220 V_BSTR(value) = bstr_from_xmlChar( content );
221 xmlFree(content);
222 r = S_OK;
223 break;
225 case XML_TEXT_NODE:
226 V_VT(value) = VT_BSTR;
227 V_BSTR(value) = bstr_from_xmlChar( This->node->content );
228 r = S_OK;
229 break;
230 case XML_ELEMENT_NODE:
231 case XML_DOCUMENT_NODE:
232 /* these seem to return NULL */
233 break;
234 case XML_PI_NODE:
235 default:
236 FIXME("node %p type %d\n", This, This->node->type);
239 TRACE("%p returned %s\n", This, debugstr_w( V_BSTR(value) ) );
241 return r;
244 static HRESULT WINAPI xmlnode_put_nodeValue(
245 IXMLDOMNode *iface,
246 VARIANT value)
248 FIXME("\n");
249 return E_NOTIMPL;
252 static HRESULT WINAPI xmlnode_get_nodeType(
253 IXMLDOMNode *iface,
254 DOMNodeType* type)
256 xmlnode *This = impl_from_IXMLDOMNode( iface );
258 TRACE("%p %p\n", This, type);
260 assert( NODE_ELEMENT == XML_ELEMENT_NODE );
261 assert( NODE_NOTATION == XML_NOTATION_NODE );
263 *type = This->node->type;
265 return S_OK;
268 static HRESULT get_node(
269 xmlnode *This,
270 const char *name,
271 xmlNodePtr node,
272 IXMLDOMNode **out )
274 TRACE("%p->%s %p\n", This, name, node );
276 if ( !out )
277 return E_INVALIDARG;
278 *out = create_node( node );
279 if (!*out)
280 return S_FALSE;
281 return S_OK;
284 static HRESULT WINAPI xmlnode_get_parentNode(
285 IXMLDOMNode *iface,
286 IXMLDOMNode** parent)
288 xmlnode *This = impl_from_IXMLDOMNode( iface );
289 return get_node( This, "parent", This->node->parent, parent );
292 static HRESULT WINAPI xmlnode_get_childNodes(
293 IXMLDOMNode *iface,
294 IXMLDOMNodeList** childList)
296 xmlnode *This = impl_from_IXMLDOMNode( iface );
298 TRACE("%p %p\n", This, childList );
300 if ( !childList )
301 return E_INVALIDARG;
303 *childList = create_children_nodelist(This->node);
304 if (*childList == NULL)
305 return E_OUTOFMEMORY;
307 return S_OK;
310 static HRESULT WINAPI xmlnode_get_firstChild(
311 IXMLDOMNode *iface,
312 IXMLDOMNode** firstChild)
314 xmlnode *This = impl_from_IXMLDOMNode( iface );
315 return get_node( This, "firstChild", This->node->children, firstChild );
318 static HRESULT WINAPI xmlnode_get_lastChild(
319 IXMLDOMNode *iface,
320 IXMLDOMNode** lastChild)
322 xmlnode *This = impl_from_IXMLDOMNode( iface );
323 return get_node( This, "lastChild", This->node->last, lastChild );
326 static HRESULT WINAPI xmlnode_get_previousSibling(
327 IXMLDOMNode *iface,
328 IXMLDOMNode** previousSibling)
330 xmlnode *This = impl_from_IXMLDOMNode( iface );
331 return get_node( This, "previous", This->node->prev, previousSibling );
334 static HRESULT WINAPI xmlnode_get_nextSibling(
335 IXMLDOMNode *iface,
336 IXMLDOMNode** nextSibling)
338 xmlnode *This = impl_from_IXMLDOMNode( iface );
339 return get_node( This, "next", This->node->next, nextSibling );
342 static HRESULT WINAPI xmlnode_get_attributes(
343 IXMLDOMNode *iface,
344 IXMLDOMNamedNodeMap** attributeMap)
346 xmlnode *This = impl_from_IXMLDOMNode( iface );
347 TRACE("%p\n", This);
348 *attributeMap = create_nodemap( iface );
349 return S_OK;
352 static HRESULT WINAPI xmlnode_insertBefore(
353 IXMLDOMNode *iface,
354 IXMLDOMNode* newChild,
355 VARIANT refChild,
356 IXMLDOMNode** outNewChild)
358 xmlnode *This = impl_from_IXMLDOMNode( iface );
359 xmlNodePtr before_node, new_child_node;
360 IXMLDOMNode *before = NULL, *new;
361 HRESULT hr;
363 TRACE("(%p)->(%p,var,%p)\n",This,newChild,outNewChild);
365 if (!newChild)
366 return E_INVALIDARG;
368 switch(V_VT(&refChild))
370 case VT_EMPTY:
371 case VT_NULL:
372 break;
374 case VT_UNKNOWN:
375 hr = IUnknown_QueryInterface(V_UNKNOWN(&refChild), &IID_IXMLDOMNode, (LPVOID)&before);
376 if(FAILED(hr)) return hr;
377 break;
379 case VT_DISPATCH:
380 hr = IDispatch_QueryInterface(V_DISPATCH(&refChild), &IID_IXMLDOMNode, (LPVOID)&before);
381 if(FAILED(hr)) return hr;
382 break;
384 default:
385 FIXME("refChild var type %x\n", V_VT(&refChild));
386 return E_FAIL;
389 IXMLDOMNode_QueryInterface(newChild, &IID_IXMLDOMNode, (LPVOID)&new);
390 new_child_node = impl_from_IXMLDOMNode(new)->node;
391 TRACE("new_child_node %p This->node %p\n", new_child_node, This->node);
393 if(before)
395 before_node = impl_from_IXMLDOMNode(before)->node;
396 xmlAddPrevSibling(before_node, new_child_node);
397 IXMLDOMNode_Release(before);
399 else
401 xmlAddChild(This->node, new_child_node);
404 IXMLDOMNode_Release(new);
405 IXMLDOMNode_AddRef(newChild);
406 if(outNewChild)
407 *outNewChild = newChild;
409 TRACE("ret S_OK\n");
410 return S_OK;
413 static HRESULT WINAPI xmlnode_replaceChild(
414 IXMLDOMNode *iface,
415 IXMLDOMNode* newChild,
416 IXMLDOMNode* oldChild,
417 IXMLDOMNode** outOldChild)
419 FIXME("\n");
420 return E_NOTIMPL;
423 static HRESULT WINAPI xmlnode_removeChild(
424 IXMLDOMNode *iface,
425 IXMLDOMNode* childNode,
426 IXMLDOMNode** oldChild)
428 xmlnode *This = impl_from_IXMLDOMNode( iface );
429 xmlNode *ancestor, *child_node_ptr;
430 HRESULT hr;
431 IXMLDOMNode *child;
433 TRACE("%p->(%p, %p)\n", This, childNode, oldChild);
435 *oldChild = NULL;
437 if(!childNode) return E_INVALIDARG;
439 hr = IXMLDOMNode_QueryInterface(childNode, &IID_IXMLDOMNode, (LPVOID)&child);
440 if(FAILED(hr))
441 return hr;
443 child_node_ptr = ancestor = impl_from_IXMLDOMNode(child)->node;
444 while(ancestor->parent)
446 if(ancestor->parent == This->node)
447 break;
448 ancestor = ancestor->parent;
450 if(!ancestor->parent)
452 WARN("childNode %p is not a child of %p\n", childNode, iface);
453 IXMLDOMNode_Release(child);
454 return E_INVALIDARG;
457 xmlUnlinkNode(child_node_ptr);
459 IXMLDOMNode_Release(child);
460 IXMLDOMNode_AddRef(childNode);
461 *oldChild = childNode;
462 return S_OK;
465 static HRESULT WINAPI xmlnode_appendChild(
466 IXMLDOMNode *iface,
467 IXMLDOMNode* newChild,
468 IXMLDOMNode** outNewChild)
470 xmlnode *This = impl_from_IXMLDOMNode( iface );
471 VARIANT var;
473 TRACE("(%p)->(%p,%p)\n", This, newChild, outNewChild);
474 VariantInit(&var);
475 return IXMLDOMNode_insertBefore(iface, newChild, var, outNewChild);
478 static HRESULT WINAPI xmlnode_hasChildNodes(
479 IXMLDOMNode *iface,
480 VARIANT_BOOL* hasChild)
482 xmlnode *This = impl_from_IXMLDOMNode( iface );
484 TRACE("%p\n", This);
486 if (!hasChild)
487 return E_INVALIDARG;
488 if (!This->node->children)
490 *hasChild = VARIANT_FALSE;
491 return S_FALSE;
494 *hasChild = VARIANT_TRUE;
495 return S_OK;
498 static HRESULT WINAPI xmlnode_get_ownerDocument(
499 IXMLDOMNode *iface,
500 IXMLDOMDocument** DOMDocument)
502 FIXME("\n");
503 return E_NOTIMPL;
506 static HRESULT WINAPI xmlnode_cloneNode(
507 IXMLDOMNode *iface,
508 VARIANT_BOOL deep,
509 IXMLDOMNode** cloneRoot)
511 xmlnode *This = impl_from_IXMLDOMNode( iface );
512 xmlNodePtr pClone = NULL;
513 IXMLDOMNode *pNode = NULL;
515 TRACE("%p (%d)\n", This, deep);
517 if(!cloneRoot)
518 return E_INVALIDARG;
520 pClone = xmlCopyNode(This->node, deep ? 1 : 2);
521 if(pClone)
523 pClone->doc = This->node->doc;
525 pNode = create_node(pClone);
526 if(!pNode)
528 ERR("Copy failed\n");
529 return E_FAIL;
532 *cloneRoot = pNode;
534 else
536 ERR("Copy failed\n");
537 return E_FAIL;
540 return S_OK;
543 static HRESULT WINAPI xmlnode_get_nodeTypeString(
544 IXMLDOMNode *iface,
545 BSTR* xmlnodeType)
547 FIXME("\n");
548 return E_NOTIMPL;
551 static HRESULT WINAPI xmlnode_get_text(
552 IXMLDOMNode *iface,
553 BSTR* text)
555 xmlnode *This = impl_from_IXMLDOMNode( iface );
556 BSTR str = NULL;
558 TRACE("%p\n", This);
560 if ( !text )
561 return E_INVALIDARG;
563 switch(This->node->type)
565 case XML_ELEMENT_NODE:
566 case XML_ATTRIBUTE_NODE:
568 xmlNodePtr child = This->node->children;
569 if ( child && child->type == XML_TEXT_NODE )
570 str = bstr_from_xmlChar( child->content );
571 break;
574 case XML_TEXT_NODE:
575 case XML_CDATA_SECTION_NODE:
576 case XML_PI_NODE:
577 case XML_COMMENT_NODE:
578 str = bstr_from_xmlChar( This->node->content );
579 break;
581 default:
582 FIXME("Unhandled node type %d\n", This->node->type);
585 /* Always return a string. */
586 if (!str) str = SysAllocStringLen( NULL, 0 );
588 TRACE("%p %s\n", This, debugstr_w(str) );
589 *text = str;
591 return S_OK;
594 static HRESULT WINAPI xmlnode_put_text(
595 IXMLDOMNode *iface,
596 BSTR text)
598 FIXME("\n");
599 return E_NOTIMPL;
602 static HRESULT WINAPI xmlnode_get_specified(
603 IXMLDOMNode *iface,
604 VARIANT_BOOL* isSpecified)
606 FIXME("\n");
607 return E_NOTIMPL;
610 static HRESULT WINAPI xmlnode_get_definition(
611 IXMLDOMNode *iface,
612 IXMLDOMNode** definitionNode)
614 FIXME("\n");
615 return E_NOTIMPL;
618 static HRESULT WINAPI xmlnode_get_nodeTypedValue(
619 IXMLDOMNode *iface,
620 VARIANT* typedValue)
622 FIXME("ignoring data type\n");
623 return xmlnode_get_nodeValue(iface, typedValue);
626 static HRESULT WINAPI xmlnode_put_nodeTypedValue(
627 IXMLDOMNode *iface,
628 VARIANT typedValue)
630 FIXME("\n");
631 return E_NOTIMPL;
634 static HRESULT WINAPI xmlnode_get_dataType(
635 IXMLDOMNode *iface,
636 VARIANT* dataTypeName)
638 FIXME("\n");
639 return E_NOTIMPL;
642 static HRESULT WINAPI xmlnode_put_dataType(
643 IXMLDOMNode *iface,
644 BSTR dataTypeName)
646 FIXME("\n");
647 return E_NOTIMPL;
650 static HRESULT WINAPI xmlnode_get_xml(
651 IXMLDOMNode *iface,
652 BSTR* xmlString)
654 FIXME("\n");
655 return E_NOTIMPL;
658 static HRESULT WINAPI xmlnode_transformNode(
659 IXMLDOMNode *iface,
660 IXMLDOMNode* styleSheet,
661 BSTR* xmlString)
663 FIXME("\n");
664 return E_NOTIMPL;
667 static HRESULT WINAPI xmlnode_selectNodes(
668 IXMLDOMNode *iface,
669 BSTR queryString,
670 IXMLDOMNodeList** resultList)
672 xmlnode *This = impl_from_IXMLDOMNode( iface );
674 TRACE("%p %s %p\n", This, debugstr_w(queryString), resultList );
676 return queryresult_create( This->node, queryString, resultList );
679 static HRESULT WINAPI xmlnode_selectSingleNode(
680 IXMLDOMNode *iface,
681 BSTR queryString,
682 IXMLDOMNode** resultNode)
684 xmlnode *This = impl_from_IXMLDOMNode( iface );
685 IXMLDOMNodeList *list;
686 HRESULT r;
688 TRACE("%p %s %p\n", This, debugstr_w(queryString), resultNode );
690 *resultNode = NULL;
691 r = IXMLDOMNode_selectNodes(iface, queryString, &list);
692 if(r == S_OK)
694 r = IXMLDOMNodeList_nextNode(list, resultNode);
695 IXMLDOMNodeList_Release(list);
697 return r;
700 static HRESULT WINAPI xmlnode_get_parsed(
701 IXMLDOMNode *iface,
702 VARIANT_BOOL* isParsed)
704 FIXME("\n");
705 return E_NOTIMPL;
708 static HRESULT WINAPI xmlnode_get_namespaceURI(
709 IXMLDOMNode *iface,
710 BSTR* namespaceURI)
712 FIXME("\n");
713 return E_NOTIMPL;
716 static HRESULT WINAPI xmlnode_get_prefix(
717 IXMLDOMNode *iface,
718 BSTR* prefixString)
720 FIXME("\n");
721 return E_NOTIMPL;
724 static HRESULT WINAPI xmlnode_get_baseName(
725 IXMLDOMNode *iface,
726 BSTR* nameString)
728 xmlnode *This = impl_from_IXMLDOMNode( iface );
729 BSTR str = NULL;
730 HRESULT r = S_FALSE;
732 TRACE("%p %p\n", This, nameString );
734 if ( !nameString )
735 return E_INVALIDARG;
737 switch ( This->node->type )
739 case XML_ELEMENT_NODE:
740 case XML_ATTRIBUTE_NODE:
741 str = bstr_from_xmlChar( This->node->name );
742 r = S_OK;
743 break;
744 case XML_TEXT_NODE:
745 break;
746 default:
747 ERR("Unhandled type %d\n", This->node->type );
748 break;
751 TRACE("returning %08x str = %s\n", r, debugstr_w( str ) );
753 *nameString = str;
754 return r;
757 static HRESULT WINAPI xmlnode_transformNodeToObject(
758 IXMLDOMNode *iface,
759 IXMLDOMNode* stylesheet,
760 VARIANT outputObject)
762 FIXME("\n");
763 return E_NOTIMPL;
766 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
768 xmlnode_QueryInterface,
769 xmlnode_AddRef,
770 xmlnode_Release,
771 xmlnode_GetTypeInfoCount,
772 xmlnode_GetTypeInfo,
773 xmlnode_GetIDsOfNames,
774 xmlnode_Invoke,
775 xmlnode_get_nodeName,
776 xmlnode_get_nodeValue,
777 xmlnode_put_nodeValue,
778 xmlnode_get_nodeType,
779 xmlnode_get_parentNode,
780 xmlnode_get_childNodes,
781 xmlnode_get_firstChild,
782 xmlnode_get_lastChild,
783 xmlnode_get_previousSibling,
784 xmlnode_get_nextSibling,
785 xmlnode_get_attributes,
786 xmlnode_insertBefore,
787 xmlnode_replaceChild,
788 xmlnode_removeChild,
789 xmlnode_appendChild,
790 xmlnode_hasChildNodes,
791 xmlnode_get_ownerDocument,
792 xmlnode_cloneNode,
793 xmlnode_get_nodeTypeString,
794 xmlnode_get_text,
795 xmlnode_put_text,
796 xmlnode_get_specified,
797 xmlnode_get_definition,
798 xmlnode_get_nodeTypedValue,
799 xmlnode_put_nodeTypedValue,
800 xmlnode_get_dataType,
801 xmlnode_put_dataType,
802 xmlnode_get_xml,
803 xmlnode_transformNode,
804 xmlnode_selectNodes,
805 xmlnode_selectSingleNode,
806 xmlnode_get_parsed,
807 xmlnode_get_namespaceURI,
808 xmlnode_get_prefix,
809 xmlnode_get_baseName,
810 xmlnode_transformNodeToObject,
813 static HRESULT WINAPI Internal_QueryInterface(
814 IUnknown *iface,
815 REFIID riid,
816 void** ppvObject )
818 xmlnode *This = impl_from_InternalUnknown( iface );
820 TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
823 if ( IsEqualGUID( riid, &IID_IUnknown ))
824 *ppvObject = iface;
825 else if ( IsEqualGUID( riid, &IID_IDispatch ) ||
826 IsEqualGUID( riid, &IID_IXMLDOMNode ) )
827 *ppvObject = &This->lpVtbl;
828 else
830 FIXME("interface %s not implemented\n", debugstr_guid(riid));
831 *ppvObject = NULL;
832 return E_NOINTERFACE;
835 IUnknown_AddRef( (IUnknown*)*ppvObject );
837 return S_OK;
840 static ULONG WINAPI Internal_AddRef(
841 IUnknown *iface )
843 xmlnode *This = impl_from_InternalUnknown( iface );
844 return InterlockedIncrement( &This->ref );
847 static ULONG WINAPI Internal_Release(
848 IUnknown *iface )
850 xmlnode *This = impl_from_InternalUnknown( iface );
851 ULONG ref;
853 ref = InterlockedDecrement( &This->ref );
854 if ( ref == 0 )
856 if( This->node )
857 xmldoc_release( This->node->doc );
858 HeapFree( GetProcessHeap(), 0, This );
861 return ref;
864 static const struct IUnknownVtbl internal_unk_vtbl =
866 Internal_QueryInterface,
867 Internal_AddRef,
868 Internal_Release
871 IUnknown *create_basic_node( xmlNodePtr node, IUnknown *pUnkOuter )
873 xmlnode *This;
875 This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
876 if ( !This )
877 return NULL;
879 if(node)
880 xmldoc_add_ref( node->doc );
882 This->lpVtbl = &xmlnode_vtbl;
883 This->lpInternalUnkVtbl = &internal_unk_vtbl;
885 if(pUnkOuter)
886 This->pUnkOuter = pUnkOuter; /* Don't take a ref on outer Unknown */
887 else
888 This->pUnkOuter = (IUnknown *)&This->lpInternalUnkVtbl;
890 This->ref = 1;
891 This->node = node;
893 return (IUnknown*)&This->lpInternalUnkVtbl;
896 IXMLDOMNode *create_node( xmlNodePtr node )
898 IUnknown *pUnk;
899 IXMLDOMNode *ret;
900 HRESULT hr;
902 if ( !node )
903 return NULL;
905 TRACE("type %d\n", node->type);
906 switch(node->type)
908 case XML_ELEMENT_NODE:
909 pUnk = create_element( node, NULL );
910 break;
911 case XML_ATTRIBUTE_NODE:
912 pUnk = create_attribute( node );
913 break;
914 case XML_TEXT_NODE:
915 pUnk = create_text( node );
916 break;
917 case XML_COMMENT_NODE:
918 pUnk = create_comment( node );
919 break;
920 case XML_DOCUMENT_NODE:
921 ERR("shouldn't be here!\n");
922 return NULL;
923 default:
924 FIXME("only creating basic node for type %d\n", node->type);
925 pUnk = create_basic_node( node, NULL );
928 hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
929 IUnknown_Release(pUnk);
930 if(FAILED(hr)) return NULL;
931 return ret;
933 #endif