msxml3: Improved checking of failed case.
[wine] / dlls / msxml3 / text.c
1 /*
2  *    DOM text node implementation
3  *
4  * Copyright 2006 Huw Davies
5  * Copyright 2007-2008 Alistair Leslie-Hughes
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #define COBJMACROS
23
24 #include "config.h"
25
26 #include <stdarg.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "ole2.h"
31 #include "msxml2.h"
32
33 #include "msxml_private.h"
34
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
38
39 #ifdef HAVE_LIBXML2
40
41 typedef struct _domtext
42 {
43     const struct IXMLDOMTextVtbl *lpVtbl;
44     LONG ref;
45     IUnknown *element_unk;
46     IXMLDOMElement *element;
47 } domtext;
48
49 static inline domtext *impl_from_IXMLDOMText( IXMLDOMText *iface )
50 {
51     return (domtext *)((char*)iface - FIELD_OFFSET(domtext, lpVtbl));
52 }
53
54 static HRESULT WINAPI domtext_QueryInterface(
55     IXMLDOMText *iface,
56     REFIID riid,
57     void** ppvObject )
58 {
59     domtext *This = impl_from_IXMLDOMText( iface );
60     TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
61
62     if ( IsEqualGUID( riid, &IID_IXMLDOMText ) ||
63          IsEqualGUID( riid, &IID_IXMLDOMCharacterData) ||
64          IsEqualGUID( riid, &IID_IDispatch ) ||
65          IsEqualGUID( riid, &IID_IUnknown ) )
66     {
67         *ppvObject = iface;
68     }
69     else if ( IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
70               IsEqualGUID( riid, &IID_IXMLDOMElement ) )
71     {
72         return IUnknown_QueryInterface(This->element_unk, riid, ppvObject);
73     }
74     else
75     {
76         FIXME("Unsupported interface %s\n", debugstr_guid(riid));
77         return E_NOINTERFACE;
78     }
79
80     IXMLDOMText_AddRef( iface );
81
82     return S_OK;
83 }
84
85 static ULONG WINAPI domtext_AddRef(
86     IXMLDOMText *iface )
87 {
88     domtext *This = impl_from_IXMLDOMText( iface );
89     return InterlockedIncrement( &This->ref );
90 }
91
92 static ULONG WINAPI domtext_Release(
93     IXMLDOMText *iface )
94 {
95     domtext *This = impl_from_IXMLDOMText( iface );
96     ULONG ref;
97
98     ref = InterlockedDecrement( &This->ref );
99     if ( ref == 0 )
100     {
101         IUnknown_Release( This->element_unk );
102         HeapFree( GetProcessHeap(), 0, This );
103     }
104
105     return ref;
106 }
107
108 static HRESULT WINAPI domtext_GetTypeInfoCount(
109     IXMLDOMText *iface,
110     UINT* pctinfo )
111 {
112     domtext *This = impl_from_IXMLDOMText( iface );
113
114     TRACE("(%p)->(%p)\n", This, pctinfo);
115
116     *pctinfo = 1;
117
118     return S_OK;
119 }
120
121 static HRESULT WINAPI domtext_GetTypeInfo(
122     IXMLDOMText *iface,
123     UINT iTInfo, LCID lcid,
124     ITypeInfo** ppTInfo )
125 {
126     domtext *This = impl_from_IXMLDOMText( iface );
127     HRESULT hr;
128
129     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
130
131     hr = get_typeinfo(IXMLDOMText_tid, ppTInfo);
132
133     return hr;
134 }
135
136 static HRESULT WINAPI domtext_GetIDsOfNames(
137     IXMLDOMText *iface,
138     REFIID riid, LPOLESTR* rgszNames,
139     UINT cNames, LCID lcid, DISPID* rgDispId )
140 {
141     domtext *This = impl_from_IXMLDOMText( iface );
142     ITypeInfo *typeinfo;
143     HRESULT hr;
144
145     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
146           lcid, rgDispId);
147
148     if(!rgszNames || cNames == 0 || !rgDispId)
149         return E_INVALIDARG;
150
151     hr = get_typeinfo(IXMLDOMText_tid, &typeinfo);
152     if(SUCCEEDED(hr))
153     {
154         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
155         ITypeInfo_Release(typeinfo);
156     }
157
158     return hr;
159 }
160
161 static HRESULT WINAPI domtext_Invoke(
162     IXMLDOMText *iface,
163     DISPID dispIdMember, REFIID riid, LCID lcid,
164     WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
165     EXCEPINFO* pExcepInfo, UINT* puArgErr )
166 {
167     domtext *This = impl_from_IXMLDOMText( iface );
168     ITypeInfo *typeinfo;
169     HRESULT hr;
170
171     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
172           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
173
174     hr = get_typeinfo(IXMLDOMText_tid, &typeinfo);
175     if(SUCCEEDED(hr))
176     {
177         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
178                 pVarResult, pExcepInfo, puArgErr);
179         ITypeInfo_Release(typeinfo);
180     }
181
182     return hr;
183 }
184
185 static HRESULT WINAPI domtext_get_nodeName(
186     IXMLDOMText *iface,
187     BSTR* p )
188 {
189     domtext *This = impl_from_IXMLDOMText( iface );
190     return IXMLDOMNode_get_nodeName( This->element, p );
191 }
192
193 static HRESULT WINAPI domtext_get_nodeValue(
194     IXMLDOMText *iface,
195     VARIANT* var1 )
196 {
197     domtext *This = impl_from_IXMLDOMText( iface );
198     return IXMLDOMNode_get_nodeValue( This->element, var1 );
199 }
200
201 static HRESULT WINAPI domtext_put_nodeValue(
202     IXMLDOMText *iface,
203     VARIANT var1 )
204 {
205     domtext *This = impl_from_IXMLDOMText( iface );
206     return IXMLDOMNode_put_nodeValue( This->element, var1 );
207 }
208
209 static HRESULT WINAPI domtext_get_nodeType(
210     IXMLDOMText *iface,
211     DOMNodeType* domNodeType )
212 {
213     domtext *This = impl_from_IXMLDOMText( iface );
214     return IXMLDOMNode_get_nodeType( This->element, domNodeType );
215 }
216
217 static HRESULT WINAPI domtext_get_parentNode(
218     IXMLDOMText *iface,
219     IXMLDOMNode** parent )
220 {
221     domtext *This = impl_from_IXMLDOMText( iface );
222     return IXMLDOMNode_get_parentNode( This->element, parent );
223 }
224
225 static HRESULT WINAPI domtext_get_childNodes(
226     IXMLDOMText *iface,
227     IXMLDOMNodeList** outList)
228 {
229     domtext *This = impl_from_IXMLDOMText( iface );
230     return IXMLDOMNode_get_childNodes( This->element, outList );
231 }
232
233 static HRESULT WINAPI domtext_get_firstChild(
234     IXMLDOMText *iface,
235     IXMLDOMNode** domNode)
236 {
237     domtext *This = impl_from_IXMLDOMText( iface );
238     return IXMLDOMNode_get_firstChild( This->element, domNode );
239 }
240
241 static HRESULT WINAPI domtext_get_lastChild(
242     IXMLDOMText *iface,
243     IXMLDOMNode** domNode)
244 {
245     domtext *This = impl_from_IXMLDOMText( iface );
246     return IXMLDOMNode_get_lastChild( This->element, domNode );
247 }
248
249 static HRESULT WINAPI domtext_get_previousSibling(
250     IXMLDOMText *iface,
251     IXMLDOMNode** domNode)
252 {
253     domtext *This = impl_from_IXMLDOMText( iface );
254     return IXMLDOMNode_get_previousSibling( This->element, domNode );
255 }
256
257 static HRESULT WINAPI domtext_get_nextSibling(
258     IXMLDOMText *iface,
259     IXMLDOMNode** domNode)
260 {
261     domtext *This = impl_from_IXMLDOMText( iface );
262     return IXMLDOMNode_get_nextSibling( This->element, domNode );
263 }
264
265 static HRESULT WINAPI domtext_get_attributes(
266     IXMLDOMText *iface,
267     IXMLDOMNamedNodeMap** attributeMap)
268 {
269     domtext *This = impl_from_IXMLDOMText( iface );
270     return IXMLDOMNode_get_attributes( This->element, attributeMap );
271 }
272
273 static HRESULT WINAPI domtext_insertBefore(
274     IXMLDOMText *iface,
275     IXMLDOMNode* newNode, VARIANT var1,
276     IXMLDOMNode** outOldNode)
277 {
278     domtext *This = impl_from_IXMLDOMText( iface );
279     return IXMLDOMNode_insertBefore( This->element, newNode, var1, outOldNode );
280 }
281
282 static HRESULT WINAPI domtext_replaceChild(
283     IXMLDOMText *iface,
284     IXMLDOMNode* newNode,
285     IXMLDOMNode* oldNode,
286     IXMLDOMNode** outOldNode)
287 {
288     domtext *This = impl_from_IXMLDOMText( iface );
289     return IXMLDOMNode_replaceChild( This->element, newNode, oldNode, outOldNode );
290 }
291
292 static HRESULT WINAPI domtext_removeChild(
293     IXMLDOMText *iface,
294     IXMLDOMNode* domNode, IXMLDOMNode** oldNode)
295 {
296     domtext *This = impl_from_IXMLDOMText( iface );
297     return IXMLDOMNode_removeChild( This->element, domNode, oldNode );
298 }
299
300 static HRESULT WINAPI domtext_appendChild(
301     IXMLDOMText *iface,
302     IXMLDOMNode* newNode, IXMLDOMNode** outNewNode)
303 {
304     domtext *This = impl_from_IXMLDOMText( iface );
305     return IXMLDOMNode_appendChild( This->element, newNode, outNewNode );
306 }
307
308 static HRESULT WINAPI domtext_hasChildNodes(
309     IXMLDOMText *iface,
310     VARIANT_BOOL* pbool)
311 {
312     domtext *This = impl_from_IXMLDOMText( iface );
313     return IXMLDOMNode_hasChildNodes( This->element, pbool );
314 }
315
316 static HRESULT WINAPI domtext_get_ownerDocument(
317     IXMLDOMText *iface,
318     IXMLDOMDocument** domDocument)
319 {
320     domtext *This = impl_from_IXMLDOMText( iface );
321     return IXMLDOMNode_get_ownerDocument( This->element, domDocument );
322 }
323
324 static HRESULT WINAPI domtext_cloneNode(
325     IXMLDOMText *iface,
326     VARIANT_BOOL pbool, IXMLDOMNode** outNode)
327 {
328     domtext *This = impl_from_IXMLDOMText( iface );
329     return IXMLDOMNode_cloneNode( This->element, pbool, outNode );
330 }
331
332 static HRESULT WINAPI domtext_get_nodeTypeString(
333     IXMLDOMText *iface,
334     BSTR* p)
335 {
336     domtext *This = impl_from_IXMLDOMText( iface );
337     return IXMLDOMNode_get_nodeTypeString( This->element, p );
338 }
339
340 static HRESULT WINAPI domtext_get_text(
341     IXMLDOMText *iface,
342     BSTR* p)
343 {
344     domtext *This = impl_from_IXMLDOMText( iface );
345     return IXMLDOMNode_get_text( This->element, p );
346 }
347
348 static HRESULT WINAPI domtext_put_text(
349     IXMLDOMText *iface,
350     BSTR p)
351 {
352     domtext *This = impl_from_IXMLDOMText( iface );
353     return IXMLDOMNode_put_text( This->element, p );
354 }
355
356 static HRESULT WINAPI domtext_get_specified(
357     IXMLDOMText *iface,
358     VARIANT_BOOL* pbool)
359 {
360     domtext *This = impl_from_IXMLDOMText( iface );
361     return IXMLDOMNode_get_specified( This->element, pbool );
362 }
363
364 static HRESULT WINAPI domtext_get_definition(
365     IXMLDOMText *iface,
366     IXMLDOMNode** domNode)
367 {
368     domtext *This = impl_from_IXMLDOMText( iface );
369     return IXMLDOMNode_get_definition( This->element, domNode );
370 }
371
372 static HRESULT WINAPI domtext_get_nodeTypedValue(
373     IXMLDOMText *iface,
374     VARIANT* var1)
375 {
376     domtext *This = impl_from_IXMLDOMText( iface );
377     return IXMLDOMNode_get_nodeTypedValue( This->element, var1 );
378 }
379
380 static HRESULT WINAPI domtext_put_nodeTypedValue(
381     IXMLDOMText *iface,
382     VARIANT var1)
383 {
384     domtext *This = impl_from_IXMLDOMText( iface );
385     return IXMLDOMNode_put_nodeTypedValue( This->element, var1 );
386 }
387
388 static HRESULT WINAPI domtext_get_dataType(
389     IXMLDOMText *iface,
390     VARIANT* var1)
391 {
392     domtext *This = impl_from_IXMLDOMText( iface );
393     return IXMLDOMNode_get_dataType( This->element, var1 );
394 }
395
396 static HRESULT WINAPI domtext_put_dataType(
397     IXMLDOMText *iface,
398     BSTR p)
399 {
400     domtext *This = impl_from_IXMLDOMText( iface );
401     return IXMLDOMNode_put_dataType( This->element, p );
402 }
403
404 static HRESULT WINAPI domtext_get_xml(
405     IXMLDOMText *iface,
406     BSTR* p)
407 {
408     domtext *This = impl_from_IXMLDOMText( iface );
409     return IXMLDOMNode_get_xml( This->element, p );
410 }
411
412 static HRESULT WINAPI domtext_transformNode(
413     IXMLDOMText *iface,
414     IXMLDOMNode* domNode, BSTR* p)
415 {
416     domtext *This = impl_from_IXMLDOMText( iface );
417     return IXMLDOMNode_transformNode( This->element, domNode, p );
418 }
419
420 static HRESULT WINAPI domtext_selectNodes(
421     IXMLDOMText *iface,
422     BSTR p, IXMLDOMNodeList** outList)
423 {
424     domtext *This = impl_from_IXMLDOMText( iface );
425     return IXMLDOMNode_selectNodes( This->element, p, outList );
426 }
427
428 static HRESULT WINAPI domtext_selectSingleNode(
429     IXMLDOMText *iface,
430     BSTR p, IXMLDOMNode** outNode)
431 {
432     domtext *This = impl_from_IXMLDOMText( iface );
433     return IXMLDOMNode_selectSingleNode( This->element, p, outNode );
434 }
435
436 static HRESULT WINAPI domtext_get_parsed(
437     IXMLDOMText *iface,
438     VARIANT_BOOL* pbool)
439 {
440     domtext *This = impl_from_IXMLDOMText( iface );
441     return IXMLDOMNode_get_parsed( This->element, pbool );
442 }
443
444 static HRESULT WINAPI domtext_get_namespaceURI(
445     IXMLDOMText *iface,
446     BSTR* p)
447 {
448     domtext *This = impl_from_IXMLDOMText( iface );
449     return IXMLDOMNode_get_namespaceURI( This->element, p );
450 }
451
452 static HRESULT WINAPI domtext_get_prefix(
453     IXMLDOMText *iface,
454     BSTR* p)
455 {
456     domtext *This = impl_from_IXMLDOMText( iface );
457     return IXMLDOMNode_get_prefix( This->element, p );
458 }
459
460 static HRESULT WINAPI domtext_get_baseName(
461     IXMLDOMText *iface,
462     BSTR* p)
463 {
464     domtext *This = impl_from_IXMLDOMText( iface );
465     return IXMLDOMNode_get_baseName( This->element, p );
466 }
467
468 static HRESULT WINAPI domtext_transformNodeToObject(
469     IXMLDOMText *iface,
470     IXMLDOMNode* domNode, VARIANT var1)
471 {
472     domtext *This = impl_from_IXMLDOMText( iface );
473     return IXMLDOMNode_transformNodeToObject( This->element, domNode, var1 );
474 }
475
476 static HRESULT WINAPI domtext_get_data(
477     IXMLDOMText *iface,
478     BSTR *p)
479 {
480     domtext *This = impl_from_IXMLDOMText( iface );
481     HRESULT hr = E_FAIL;
482     VARIANT vRet;
483
484     if(!p)
485         return E_INVALIDARG;
486
487     hr = IXMLDOMNode_get_nodeValue( This->element, &vRet );
488     if(hr == S_OK)
489     {
490         *p = V_BSTR(&vRet);
491     }
492
493     return hr;
494 }
495
496 static HRESULT WINAPI domtext_put_data(
497     IXMLDOMText *iface,
498     BSTR data)
499 {
500     domtext *This = impl_from_IXMLDOMText( iface );
501     HRESULT hr = E_FAIL;
502     VARIANT val;
503
504     TRACE("%p %s\n", This, debugstr_w(data) );
505
506     V_VT(&val) = VT_BSTR;
507     V_BSTR(&val) = data;
508
509     hr = IXMLDOMNode_put_nodeValue( This->element, val );
510
511     return hr;
512 }
513
514 static HRESULT WINAPI domtext_get_length(
515     IXMLDOMText *iface,
516     long *len)
517 {
518     domtext *This = impl_from_IXMLDOMText( iface );
519     xmlnode *pDOMNode = impl_from_IXMLDOMNode( (IXMLDOMNode*)This->element );
520     xmlChar *pContent;
521     long nLength = 0;
522
523     TRACE("%p\n", iface);
524
525     if(!len)
526         return E_INVALIDARG;
527
528     pContent = xmlNodeGetContent(pDOMNode->node);
529     if(pContent)
530     {
531         nLength = xmlStrlen(pContent);
532         xmlFree(pContent);
533     }
534
535     *len = nLength;
536
537     return S_OK;
538 }
539
540 static HRESULT WINAPI domtext_substringData(
541     IXMLDOMText *iface,
542     long offset, long count, BSTR *p)
543 {
544     domtext *This = impl_from_IXMLDOMText( iface );
545     xmlnode *pDOMNode = impl_from_IXMLDOMNode( (IXMLDOMNode*)This->element );
546     xmlChar *pContent;
547     long nLength = 0;
548     HRESULT hr = S_FALSE;
549
550     TRACE("%p\n", iface);
551
552     if(!p)
553         return E_INVALIDARG;
554
555     *p = NULL;
556     if(offset < 0 || count < 0)
557         return E_INVALIDARG;
558
559     if(count == 0)
560         return hr;
561
562     pContent = xmlNodeGetContent(pDOMNode->node);
563     if(pContent)
564     {
565         nLength = xmlStrlen(pContent);
566
567         if( offset < nLength)
568         {
569             BSTR sContent = bstr_from_xmlChar(pContent);
570             if(offset + count > nLength)
571                 *p = SysAllocString(&sContent[offset]);
572             else
573                 *p = SysAllocStringLen(&sContent[offset], count);
574
575             SysFreeString(sContent);
576             hr = S_OK;
577         }
578
579         xmlFree(pContent);
580     }
581
582     return hr;
583 }
584
585 static HRESULT WINAPI domtext_appendData(
586     IXMLDOMText *iface,
587     BSTR p)
588 {
589     domtext *This = impl_from_IXMLDOMText( iface );
590     xmlnode *pDOMNode = impl_from_IXMLDOMNode( (IXMLDOMNode*)This->element );
591     xmlChar *pContent;
592     HRESULT hr = S_FALSE;
593
594     TRACE("%p\n", iface);
595
596     /* Nothing to do if NULL or an Empty string passed in. */
597     if(p == NULL || SysStringLen(p) == 0)
598         return S_OK;
599
600     pContent = xmlChar_from_wchar( (WCHAR*)p );
601     if(pContent)
602     {
603         if(xmlTextConcat(pDOMNode->node, pContent, SysStringLen(p) ) == 0)
604             hr = S_OK;
605         else
606             hr = E_FAIL;
607     }
608     else
609         hr = E_FAIL;
610
611     return hr;
612 }
613
614 static HRESULT WINAPI domtext_insertData(
615     IXMLDOMText *iface,
616     long offset, BSTR p)
617 {
618     domtext *This = impl_from_IXMLDOMText( iface );
619     xmlnode *pDOMNode = impl_from_IXMLDOMNode( (IXMLDOMNode*)This->element );
620     xmlChar *pXmlContent;
621     BSTR sNewString;
622     HRESULT hr = S_FALSE;
623     long nLength = 0, nLengthP = 0;
624     xmlChar *str = NULL;
625
626     TRACE("%p\n", This);
627
628     /* If have a NULL or empty string, don't do anything. */
629     if(SysStringLen(p) == 0)
630         return S_OK;
631
632     if(offset < 0)
633     {
634         return E_INVALIDARG;
635     }
636
637     pXmlContent = xmlNodeGetContent(pDOMNode->node);
638     if(pXmlContent)
639     {
640         BSTR sContent = bstr_from_xmlChar( pXmlContent );
641         nLength = SysStringLen(sContent);
642         nLengthP = SysStringLen(p);
643
644         if(nLength < offset)
645         {
646             SysFreeString(sContent);
647             xmlFree(pXmlContent);
648
649             return E_INVALIDARG;
650         }
651
652         sNewString = SysAllocStringLen(NULL, nLength + nLengthP + 1);
653         if(sNewString)
654         {
655             if(offset > 0)
656                 memcpy(sNewString, sContent, offset * sizeof(WCHAR));
657
658             memcpy(&sNewString[offset], p, nLengthP * sizeof(WCHAR));
659
660             if(offset+nLengthP < nLength)
661                 memcpy(&sNewString[offset+nLengthP], &sContent[offset], (nLength-offset) * sizeof(WCHAR));
662
663             sNewString[nLengthP + nLength] = 0;
664
665             str = xmlChar_from_wchar((WCHAR*)sNewString);
666             if(str)
667             {
668                 xmlNodeSetContent(pDOMNode->node, str);
669                 hr = S_OK;
670             }
671
672             SysFreeString(sNewString);
673         }
674
675         SysFreeString(sContent);
676
677         xmlFree(pXmlContent);
678     }
679
680     return hr;
681 }
682
683 static HRESULT WINAPI domtext_deleteData(
684     IXMLDOMText *iface,
685     long offset, long count)
686 {
687     FIXME("\n");
688     return E_NOTIMPL;
689 }
690
691 static HRESULT WINAPI domtext_replaceData(
692     IXMLDOMText *iface,
693     long offset, long count, BSTR p)
694 {
695     FIXME("\n");
696     return E_NOTIMPL;
697 }
698
699 static HRESULT WINAPI domtext_splitText(
700     IXMLDOMText *iface,
701     long offset, IXMLDOMText **txtNode)
702 {
703     FIXME("\n");
704     return E_NOTIMPL;
705 }
706
707
708 static const struct IXMLDOMTextVtbl domtext_vtbl =
709 {
710     domtext_QueryInterface,
711     domtext_AddRef,
712     domtext_Release,
713     domtext_GetTypeInfoCount,
714     domtext_GetTypeInfo,
715     domtext_GetIDsOfNames,
716     domtext_Invoke,
717     domtext_get_nodeName,
718     domtext_get_nodeValue,
719     domtext_put_nodeValue,
720     domtext_get_nodeType,
721     domtext_get_parentNode,
722     domtext_get_childNodes,
723     domtext_get_firstChild,
724     domtext_get_lastChild,
725     domtext_get_previousSibling,
726     domtext_get_nextSibling,
727     domtext_get_attributes,
728     domtext_insertBefore,
729     domtext_replaceChild,
730     domtext_removeChild,
731     domtext_appendChild,
732     domtext_hasChildNodes,
733     domtext_get_ownerDocument,
734     domtext_cloneNode,
735     domtext_get_nodeTypeString,
736     domtext_get_text,
737     domtext_put_text,
738     domtext_get_specified,
739     domtext_get_definition,
740     domtext_get_nodeTypedValue,
741     domtext_put_nodeTypedValue,
742     domtext_get_dataType,
743     domtext_put_dataType,
744     domtext_get_xml,
745     domtext_transformNode,
746     domtext_selectNodes,
747     domtext_selectSingleNode,
748     domtext_get_parsed,
749     domtext_get_namespaceURI,
750     domtext_get_prefix,
751     domtext_get_baseName,
752     domtext_transformNodeToObject,
753     domtext_get_data,
754     domtext_put_data,
755     domtext_get_length,
756     domtext_substringData,
757     domtext_appendData,
758     domtext_insertData,
759     domtext_deleteData,
760     domtext_replaceData,
761     domtext_splitText
762 };
763
764 IUnknown* create_text( xmlNodePtr text )
765 {
766     domtext *This;
767     HRESULT hr;
768
769     This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
770     if ( !This )
771         return NULL;
772
773     This->lpVtbl = &domtext_vtbl;
774     This->ref = 1;
775
776     This->element_unk = create_element( text, (IUnknown*)&This->lpVtbl );
777     if(!This->element_unk)
778     {
779         HeapFree(GetProcessHeap(), 0, This);
780         return NULL;
781     }
782
783     hr = IUnknown_QueryInterface(This->element_unk, &IID_IXMLDOMNode, (LPVOID*)&This->element);
784     if(FAILED(hr))
785     {
786         IUnknown_Release(This->element_unk);
787         HeapFree( GetProcessHeap(), 0, This );
788         return NULL;
789     }
790     /* The ref on This->element is actually looped back into this object, so release it */
791     IXMLDOMNode_Release(This->element);
792
793     return (IUnknown*) &This->lpVtbl;
794 }
795
796 #endif