msxml3: Added IXMLDOMParseError2 support.
[wine] / dlls / msxml3 / cdata.c
1 /*
2  *    DOM CDATA node implementation
3  *
4  * Copyright 2007 Alistair Leslie-Hughes
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define COBJMACROS
22
23 #include "config.h"
24
25 #include <stdarg.h>
26 #ifdef HAVE_LIBXML2
27 # include <libxml/parser.h>
28 # include <libxml/xmlerror.h>
29 #endif
30
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winuser.h"
34 #include "ole2.h"
35 #include "msxml6.h"
36
37 #include "msxml_private.h"
38
39 #include "wine/debug.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
42
43 #ifdef HAVE_LIBXML2
44
45 typedef struct _domcdata
46 {
47     xmlnode node;
48     IXMLDOMCDATASection IXMLDOMCDATASection_iface;
49     LONG ref;
50 } domcdata;
51
52 static const tid_t domcdata_se_tids[] = {
53     IXMLDOMNode_tid,
54     IXMLDOMCDATASection_tid,
55     0
56 };
57
58 static inline domcdata *impl_from_IXMLDOMCDATASection( IXMLDOMCDATASection *iface )
59 {
60     return CONTAINING_RECORD(iface, domcdata, IXMLDOMCDATASection_iface);
61 }
62
63 static HRESULT WINAPI domcdata_QueryInterface(
64     IXMLDOMCDATASection *iface,
65     REFIID riid,
66     void** ppvObject )
67 {
68     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
69     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
70
71     if ( IsEqualGUID( riid, &IID_IXMLDOMCDATASection ) ||
72          IsEqualGUID( riid, &IID_IXMLDOMCharacterData) ||
73          IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
74          IsEqualGUID( riid, &IID_IDispatch ) ||
75          IsEqualGUID( riid, &IID_IUnknown ) )
76     {
77         *ppvObject = iface;
78     }
79     else if(node_query_interface(&This->node, riid, ppvObject))
80     {
81         return *ppvObject ? S_OK : E_NOINTERFACE;
82     }
83     else if(IsEqualGUID( riid, &IID_ISupportErrorInfo ))
84     {
85         return node_create_supporterrorinfo(domcdata_se_tids, ppvObject);
86     }
87     else
88     {
89         TRACE("Unsupported interface %s\n", debugstr_guid(riid));
90         *ppvObject = NULL;
91         return E_NOINTERFACE;
92     }
93
94     IXMLDOMText_AddRef((IUnknown*)*ppvObject);
95     return S_OK;
96 }
97
98 static ULONG WINAPI domcdata_AddRef(
99     IXMLDOMCDATASection *iface )
100 {
101     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
102     ULONG ref = InterlockedIncrement( &This->ref );
103     TRACE("(%p)->(%d)\n", This, ref);
104     return ref;
105 }
106
107 static ULONG WINAPI domcdata_Release(
108     IXMLDOMCDATASection *iface )
109 {
110     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
111     ULONG ref = InterlockedDecrement( &This->ref );
112
113     TRACE("(%p)->(%d)\n", This, ref);
114     if ( ref == 0 )
115     {
116         destroy_xmlnode(&This->node);
117         heap_free( This );
118     }
119
120     return ref;
121 }
122
123 static HRESULT WINAPI domcdata_GetTypeInfoCount(
124     IXMLDOMCDATASection *iface,
125     UINT* pctinfo )
126 {
127     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
128     return IDispatchEx_GetTypeInfoCount(&This->node.dispex.IDispatchEx_iface, pctinfo);
129 }
130
131 static HRESULT WINAPI domcdata_GetTypeInfo(
132     IXMLDOMCDATASection *iface,
133     UINT iTInfo, LCID lcid,
134     ITypeInfo** ppTInfo )
135 {
136     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
137     return IDispatchEx_GetTypeInfo(&This->node.dispex.IDispatchEx_iface,
138         iTInfo, lcid, ppTInfo);
139 }
140
141 static HRESULT WINAPI domcdata_GetIDsOfNames(
142     IXMLDOMCDATASection *iface,
143     REFIID riid, LPOLESTR* rgszNames,
144     UINT cNames, LCID lcid, DISPID* rgDispId )
145 {
146     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
147     return IDispatchEx_GetIDsOfNames(&This->node.dispex.IDispatchEx_iface,
148         riid, rgszNames, cNames, lcid, rgDispId);
149 }
150
151 static HRESULT WINAPI domcdata_Invoke(
152     IXMLDOMCDATASection *iface,
153     DISPID dispIdMember, REFIID riid, LCID lcid,
154     WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
155     EXCEPINFO* pExcepInfo, UINT* puArgErr )
156 {
157     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
158     return IDispatchEx_Invoke(&This->node.dispex.IDispatchEx_iface,
159         dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
160 }
161
162 static HRESULT WINAPI domcdata_get_nodeName(
163     IXMLDOMCDATASection *iface,
164     BSTR* p )
165 {
166     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
167
168     static const WCHAR cdata_sectionW[] =
169         {'#','c','d','a','t','a','-','s','e','c','t','i','o','n',0};
170
171     TRACE("(%p)->(%p)\n", This, p);
172
173     return return_bstr(cdata_sectionW, p);
174 }
175
176 static HRESULT WINAPI domcdata_get_nodeValue(
177     IXMLDOMCDATASection *iface,
178     VARIANT* value)
179 {
180     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
181
182     TRACE("(%p)->(%p)\n", This, value);
183
184     return node_get_content(&This->node, value);
185 }
186
187 static HRESULT WINAPI domcdata_put_nodeValue(
188     IXMLDOMCDATASection *iface,
189     VARIANT value)
190 {
191     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
192
193     TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
194
195     return node_put_value(&This->node, &value);
196 }
197
198 static HRESULT WINAPI domcdata_get_nodeType(
199     IXMLDOMCDATASection *iface,
200     DOMNodeType* domNodeType )
201 {
202     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
203
204     TRACE("(%p)->(%p)\n", This, domNodeType);
205
206     *domNodeType = NODE_CDATA_SECTION;
207     return S_OK;
208 }
209
210 static HRESULT WINAPI domcdata_get_parentNode(
211     IXMLDOMCDATASection *iface,
212     IXMLDOMNode** parent )
213 {
214     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
215
216     TRACE("(%p)->(%p)\n", This, parent);
217
218     return node_get_parent(&This->node, parent);
219 }
220
221 static HRESULT WINAPI domcdata_get_childNodes(
222     IXMLDOMCDATASection *iface,
223     IXMLDOMNodeList** outList)
224 {
225     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
226
227     TRACE("(%p)->(%p)\n", This, outList);
228
229     return node_get_child_nodes(&This->node, outList);
230 }
231
232 static HRESULT WINAPI domcdata_get_firstChild(
233     IXMLDOMCDATASection *iface,
234     IXMLDOMNode** domNode)
235 {
236     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
237
238     TRACE("(%p)->(%p)\n", This, domNode);
239
240     return return_null_node(domNode);
241 }
242
243 static HRESULT WINAPI domcdata_get_lastChild(
244     IXMLDOMCDATASection *iface,
245     IXMLDOMNode** domNode)
246 {
247     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
248
249     TRACE("(%p)->(%p)\n", This, domNode);
250
251     return return_null_node(domNode);
252 }
253
254 static HRESULT WINAPI domcdata_get_previousSibling(
255     IXMLDOMCDATASection *iface,
256     IXMLDOMNode** domNode)
257 {
258     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
259
260     TRACE("(%p)->(%p)\n", This, domNode);
261
262     return node_get_previous_sibling(&This->node, domNode);
263 }
264
265 static HRESULT WINAPI domcdata_get_nextSibling(
266     IXMLDOMCDATASection *iface,
267     IXMLDOMNode** domNode)
268 {
269     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
270
271     TRACE("(%p)->(%p)\n", This, domNode);
272
273     return node_get_next_sibling(&This->node, domNode);
274 }
275
276 static HRESULT WINAPI domcdata_get_attributes(
277     IXMLDOMCDATASection *iface,
278     IXMLDOMNamedNodeMap** attributeMap)
279 {
280     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
281
282     TRACE("(%p)->(%p)\n", This, attributeMap);
283
284     return return_null_ptr((void**)attributeMap);
285 }
286
287 static HRESULT WINAPI domcdata_insertBefore(
288     IXMLDOMCDATASection *iface,
289     IXMLDOMNode* newNode, VARIANT refChild,
290     IXMLDOMNode** outOldNode)
291 {
292     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
293
294     FIXME("(%p)->(%p %s %p) needs test\n", This, newNode, debugstr_variant(&refChild), outOldNode);
295
296     return node_insert_before(&This->node, newNode, &refChild, outOldNode);
297 }
298
299 static HRESULT WINAPI domcdata_replaceChild(
300     IXMLDOMCDATASection *iface,
301     IXMLDOMNode* newNode,
302     IXMLDOMNode* oldNode,
303     IXMLDOMNode** outOldNode)
304 {
305     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
306
307     FIXME("(%p)->(%p %p %p) needs tests\n", This, newNode, oldNode, outOldNode);
308
309     return node_replace_child(&This->node, newNode, oldNode, outOldNode);
310 }
311
312 static HRESULT WINAPI domcdata_removeChild(
313     IXMLDOMCDATASection *iface,
314     IXMLDOMNode *child, IXMLDOMNode **oldChild)
315 {
316     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
317     TRACE("(%p)->(%p %p)\n", This, child, oldChild);
318     return node_remove_child(&This->node, child, oldChild);
319 }
320
321 static HRESULT WINAPI domcdata_appendChild(
322     IXMLDOMCDATASection *iface,
323     IXMLDOMNode *child, IXMLDOMNode **outChild)
324 {
325     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
326     TRACE("(%p)->(%p %p)\n", This, child, outChild);
327     return node_append_child(&This->node, child, outChild);
328 }
329
330 static HRESULT WINAPI domcdata_hasChildNodes(
331     IXMLDOMCDATASection *iface,
332     VARIANT_BOOL *ret)
333 {
334     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
335     TRACE("(%p)->(%p)\n", This, ret);
336     return node_has_childnodes(&This->node, ret);
337 }
338
339 static HRESULT WINAPI domcdata_get_ownerDocument(
340     IXMLDOMCDATASection *iface,
341     IXMLDOMDocument    **doc)
342 {
343     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
344     TRACE("(%p)->(%p)\n", This, doc);
345     return node_get_owner_doc(&This->node, doc);
346 }
347
348 static HRESULT WINAPI domcdata_cloneNode(
349     IXMLDOMCDATASection *iface,
350     VARIANT_BOOL deep, IXMLDOMNode** outNode)
351 {
352     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
353     TRACE("(%p)->(%d %p)\n", This, deep, outNode);
354     return node_clone( &This->node, deep, outNode );
355 }
356
357 static HRESULT WINAPI domcdata_get_nodeTypeString(
358     IXMLDOMCDATASection *iface,
359     BSTR* p)
360 {
361     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
362     static const WCHAR cdatasectionW[] = {'c','d','a','t','a','s','e','c','t','i','o','n',0};
363
364     TRACE("(%p)->(%p)\n", This, p);
365
366     return return_bstr(cdatasectionW, p);
367 }
368
369 static HRESULT WINAPI domcdata_get_text(
370     IXMLDOMCDATASection *iface,
371     BSTR* p)
372 {
373     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
374     TRACE("(%p)->(%p)\n", This, p);
375     return node_get_text(&This->node, p);
376 }
377
378 static HRESULT WINAPI domcdata_put_text(
379     IXMLDOMCDATASection *iface,
380     BSTR p)
381 {
382     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
383     TRACE("(%p)->(%p)\n", This, debugstr_w(p));
384     return node_put_text( &This->node, p );
385 }
386
387 static HRESULT WINAPI domcdata_get_specified(
388     IXMLDOMCDATASection *iface,
389     VARIANT_BOOL* isSpecified)
390 {
391     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
392     FIXME("(%p)->(%p) stub!\n", This, isSpecified);
393     *isSpecified = VARIANT_TRUE;
394     return S_OK;
395 }
396
397 static HRESULT WINAPI domcdata_get_definition(
398     IXMLDOMCDATASection *iface,
399     IXMLDOMNode** definitionNode)
400 {
401     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
402     FIXME("(%p)->(%p)\n", This, definitionNode);
403     return E_NOTIMPL;
404 }
405
406 static HRESULT WINAPI domcdata_get_nodeTypedValue(
407     IXMLDOMCDATASection *iface,
408     VARIANT* v)
409 {
410     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
411     TRACE("(%p)->(%p)\n", This, v);
412     return node_get_content(&This->node, v);
413 }
414
415 static HRESULT WINAPI domcdata_put_nodeTypedValue(
416     IXMLDOMCDATASection *iface,
417     VARIANT typedValue)
418 {
419     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
420     FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
421     return E_NOTIMPL;
422 }
423
424 static HRESULT WINAPI domcdata_get_dataType(
425     IXMLDOMCDATASection *iface,
426     VARIANT* typename)
427 {
428     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
429     TRACE("(%p)->(%p)\n", This, typename);
430     return return_null_var( typename );
431 }
432
433 static HRESULT WINAPI domcdata_put_dataType(
434     IXMLDOMCDATASection *iface,
435     BSTR p)
436 {
437     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
438
439     FIXME("(%p)->(%s)\n", This, debugstr_w(p));
440
441     if(!p)
442         return E_INVALIDARG;
443
444     return E_FAIL;
445 }
446
447 static HRESULT WINAPI domcdata_get_xml(
448     IXMLDOMCDATASection *iface,
449     BSTR* p)
450 {
451     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
452
453     TRACE("(%p)->(%p)\n", This, p);
454
455     return node_get_xml(&This->node, FALSE, FALSE, p);
456 }
457
458 static HRESULT WINAPI domcdata_transformNode(
459     IXMLDOMCDATASection *iface,
460     IXMLDOMNode *node, BSTR *p)
461 {
462     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
463     TRACE("(%p)->(%p %p)\n", This, node, p);
464     return node_transform_node(&This->node, node, p);
465 }
466
467 static HRESULT WINAPI domcdata_selectNodes(
468     IXMLDOMCDATASection *iface,
469     BSTR p, IXMLDOMNodeList** outList)
470 {
471     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
472     TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
473     return node_select_nodes(&This->node, p, outList);
474 }
475
476 static HRESULT WINAPI domcdata_selectSingleNode(
477     IXMLDOMCDATASection *iface,
478     BSTR p, IXMLDOMNode** outNode)
479 {
480     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
481     TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
482     return node_select_singlenode(&This->node, p, outNode);
483 }
484
485 static HRESULT WINAPI domcdata_get_parsed(
486     IXMLDOMCDATASection *iface,
487     VARIANT_BOOL* isParsed)
488 {
489     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
490     FIXME("(%p)->(%p) stub!\n", This, isParsed);
491     *isParsed = VARIANT_TRUE;
492     return S_OK;
493 }
494
495 static HRESULT WINAPI domcdata_get_namespaceURI(
496     IXMLDOMCDATASection *iface,
497     BSTR* p)
498 {
499     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
500     TRACE("(%p)->(%p)\n", This, p);
501     return node_get_namespaceURI(&This->node, p);
502 }
503
504 static HRESULT WINAPI domcdata_get_prefix(
505     IXMLDOMCDATASection *iface,
506     BSTR* prefix)
507 {
508     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
509     TRACE("(%p)->(%p)\n", This, prefix);
510     return return_null_bstr( prefix );
511 }
512
513 static HRESULT WINAPI domcdata_get_baseName(
514     IXMLDOMCDATASection *iface,
515     BSTR* name)
516 {
517     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
518     FIXME("(%p)->(%p): needs test\n", This, name);
519     return return_null_bstr( name );
520 }
521
522 static HRESULT WINAPI domcdata_transformNodeToObject(
523     IXMLDOMCDATASection *iface,
524     IXMLDOMNode* domNode, VARIANT var1)
525 {
526     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
527     FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1));
528     return E_NOTIMPL;
529 }
530
531 static HRESULT WINAPI domcdata_get_data(
532     IXMLDOMCDATASection *iface,
533     BSTR *p)
534 {
535     HRESULT hr;
536     VARIANT vRet;
537
538     if(!p)
539         return E_INVALIDARG;
540
541     hr = IXMLDOMCDATASection_get_nodeValue( iface, &vRet );
542     if(hr == S_OK)
543     {
544         *p = V_BSTR(&vRet);
545     }
546
547     return hr;
548 }
549
550 static HRESULT WINAPI domcdata_put_data(
551     IXMLDOMCDATASection *iface,
552     BSTR data)
553 {
554     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
555     VARIANT val;
556
557     TRACE("(%p)->(%s)\n", This, debugstr_w(data) );
558
559     V_VT(&val) = VT_BSTR;
560     V_BSTR(&val) = data;
561
562     return IXMLDOMCDATASection_put_nodeValue( iface, val );
563 }
564
565 static HRESULT WINAPI domcdata_get_length(
566     IXMLDOMCDATASection *iface,
567     LONG *len)
568 {
569     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
570     HRESULT hr;
571     BSTR data;
572
573     TRACE("(%p)->(%p)\n", This, len);
574
575     if(!len)
576         return E_INVALIDARG;
577
578     hr = IXMLDOMCDATASection_get_data(iface, &data);
579     if(hr == S_OK)
580     {
581         *len = SysStringLen(data);
582         SysFreeString(data);
583     }
584
585     return S_OK;
586 }
587
588 static HRESULT WINAPI domcdata_substringData(
589     IXMLDOMCDATASection *iface,
590     LONG offset, LONG count, BSTR *p)
591 {
592     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
593     HRESULT hr;
594     BSTR data;
595
596     TRACE("(%p)->(%d %d %p)\n", This, offset, count, p);
597
598     if(!p)
599         return E_INVALIDARG;
600
601     *p = NULL;
602     if(offset < 0 || count < 0)
603         return E_INVALIDARG;
604
605     if(count == 0)
606         return S_FALSE;
607
608     hr = IXMLDOMCDATASection_get_data(iface, &data);
609     if(hr == S_OK)
610     {
611         LONG len = SysStringLen(data);
612
613         if(offset < len)
614         {
615             if(offset + count > len)
616                 *p = SysAllocString(&data[offset]);
617             else
618                 *p = SysAllocStringLen(&data[offset], count);
619         }
620         else
621             hr = S_FALSE;
622
623         SysFreeString(data);
624     }
625
626     return hr;
627 }
628
629 static HRESULT WINAPI domcdata_appendData(
630     IXMLDOMCDATASection *iface,
631     BSTR p)
632 {
633     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
634     HRESULT hr;
635     BSTR data;
636     LONG p_len;
637
638     TRACE("(%p)->(%s)\n", This, debugstr_w(p));
639
640     /* Nothing to do if NULL or an Empty string passed in. */
641     if((p_len = SysStringLen(p)) == 0) return S_OK;
642
643     hr = IXMLDOMCDATASection_get_data(iface, &data);
644     if(hr == S_OK)
645     {
646         LONG len = SysStringLen(data);
647         BSTR str = SysAllocStringLen(NULL, p_len + len);
648
649         memcpy(str, data, len*sizeof(WCHAR));
650         memcpy(&str[len], p, p_len*sizeof(WCHAR));
651         str[len+p_len] = 0;
652
653         hr = IXMLDOMCDATASection_put_data(iface, str);
654
655         SysFreeString(str);
656         SysFreeString(data);
657     }
658
659     return hr;
660 }
661
662 static HRESULT WINAPI domcdata_insertData(
663     IXMLDOMCDATASection *iface,
664     LONG offset, BSTR p)
665 {
666     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
667     HRESULT hr;
668     BSTR data;
669     LONG p_len;
670
671     TRACE("(%p)->(%d %s)\n", This, offset, debugstr_w(p));
672
673     /* If have a NULL or empty string, don't do anything. */
674     if((p_len = SysStringLen(p)) == 0)
675         return S_OK;
676
677     if(offset < 0)
678     {
679         return E_INVALIDARG;
680     }
681
682     hr = IXMLDOMCDATASection_get_data(iface, &data);
683     if(hr == S_OK)
684     {
685         LONG len = SysStringLen(data);
686         BSTR str;
687
688         if(len < offset)
689         {
690             SysFreeString(data);
691             return E_INVALIDARG;
692         }
693
694         str = SysAllocStringLen(NULL, len + p_len);
695         /* start part, supplied string and end part */
696         memcpy(str, data, offset*sizeof(WCHAR));
697         memcpy(&str[offset], p, p_len*sizeof(WCHAR));
698         memcpy(&str[offset+p_len], &data[offset], (len-offset)*sizeof(WCHAR));
699         str[len+p_len] = 0;
700
701         hr = IXMLDOMCDATASection_put_data(iface, str);
702
703         SysFreeString(str);
704         SysFreeString(data);
705     }
706
707     return hr;
708 }
709
710 static HRESULT WINAPI domcdata_deleteData(
711     IXMLDOMCDATASection *iface,
712     LONG offset, LONG count)
713 {
714     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
715     HRESULT hr;
716     LONG len = -1;
717     BSTR str;
718
719     TRACE("(%p)->(%d %d)\n", This, offset, count);
720
721     hr = IXMLDOMCDATASection_get_length(iface, &len);
722     if(hr != S_OK) return hr;
723
724     if((offset < 0) || (offset > len) || (count < 0))
725         return E_INVALIDARG;
726
727     if(len == 0) return S_OK;
728
729     /* cutting start or end */
730     if((offset == 0) || ((count + offset) >= len))
731     {
732         if(offset == 0)
733             IXMLDOMCDATASection_substringData(iface, count, len - count, &str);
734         else
735             IXMLDOMCDATASection_substringData(iface, 0, offset, &str);
736         hr = IXMLDOMCDATASection_put_data(iface, str);
737     }
738     else
739     /* cutting from the inside */
740     {
741         BSTR str_end;
742
743         IXMLDOMCDATASection_substringData(iface, 0, offset, &str);
744         IXMLDOMCDATASection_substringData(iface, offset + count, len - count, &str_end);
745
746         hr = IXMLDOMCDATASection_put_data(iface, str);
747         if(hr == S_OK)
748             hr = IXMLDOMCDATASection_appendData(iface, str_end);
749
750         SysFreeString(str_end);
751     }
752
753     SysFreeString(str);
754
755     return hr;
756 }
757
758 static HRESULT WINAPI domcdata_replaceData(
759     IXMLDOMCDATASection *iface,
760     LONG offset, LONG count, BSTR p)
761 {
762     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
763     HRESULT hr;
764
765     TRACE("(%p)->(%d %d %s)\n", This, offset, count, debugstr_w(p));
766
767     hr = IXMLDOMCDATASection_deleteData(iface, offset, count);
768
769     if (hr == S_OK)
770        hr = IXMLDOMCDATASection_insertData(iface, offset, p);
771
772     return hr;
773 }
774
775 static HRESULT WINAPI domcdata_splitText(
776     IXMLDOMCDATASection *iface,
777     LONG offset, IXMLDOMText **txtNode)
778 {
779     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
780     IXMLDOMDocument *doc;
781     LONG length = 0;
782     HRESULT hr;
783
784     TRACE("(%p)->(%d %p)\n", This, offset, txtNode);
785
786     if (!txtNode || offset < 0) return E_INVALIDARG;
787
788     *txtNode = NULL;
789
790     IXMLDOMCDATASection_get_length(iface, &length);
791
792     if (offset > length) return E_INVALIDARG;
793     if (offset == length) return S_FALSE;
794
795     hr = IXMLDOMCDATASection_get_ownerDocument(iface, &doc);
796     if (hr == S_OK)
797     {
798         BSTR data;
799
800         hr = IXMLDOMCDATASection_substringData(iface, offset, length - offset, &data);
801         if (hr == S_OK)
802         {
803             hr = IXMLDOMDocument_createTextNode(doc, data, txtNode);
804             if (hr == S_OK)
805             {
806                 IXMLDOMNode *parent;
807
808                 hr = IXMLDOMCDATASection_get_parentNode(iface, &parent);
809                 if (hr == S_OK)
810                 {
811                     IXMLDOMCDATASection_deleteData(iface, 0, offset);
812                     hr = IXMLDOMNode_appendChild(parent, (IXMLDOMNode*)*txtNode, NULL);
813                     IXMLDOMNode_Release(parent);
814                 }
815             }
816             SysFreeString(data);
817         }
818         IXMLDOMDocument_Release(doc);
819     }
820
821     return hr;
822 }
823
824 static const struct IXMLDOMCDATASectionVtbl domcdata_vtbl =
825 {
826     domcdata_QueryInterface,
827     domcdata_AddRef,
828     domcdata_Release,
829     domcdata_GetTypeInfoCount,
830     domcdata_GetTypeInfo,
831     domcdata_GetIDsOfNames,
832     domcdata_Invoke,
833     domcdata_get_nodeName,
834     domcdata_get_nodeValue,
835     domcdata_put_nodeValue,
836     domcdata_get_nodeType,
837     domcdata_get_parentNode,
838     domcdata_get_childNodes,
839     domcdata_get_firstChild,
840     domcdata_get_lastChild,
841     domcdata_get_previousSibling,
842     domcdata_get_nextSibling,
843     domcdata_get_attributes,
844     domcdata_insertBefore,
845     domcdata_replaceChild,
846     domcdata_removeChild,
847     domcdata_appendChild,
848     domcdata_hasChildNodes,
849     domcdata_get_ownerDocument,
850     domcdata_cloneNode,
851     domcdata_get_nodeTypeString,
852     domcdata_get_text,
853     domcdata_put_text,
854     domcdata_get_specified,
855     domcdata_get_definition,
856     domcdata_get_nodeTypedValue,
857     domcdata_put_nodeTypedValue,
858     domcdata_get_dataType,
859     domcdata_put_dataType,
860     domcdata_get_xml,
861     domcdata_transformNode,
862     domcdata_selectNodes,
863     domcdata_selectSingleNode,
864     domcdata_get_parsed,
865     domcdata_get_namespaceURI,
866     domcdata_get_prefix,
867     domcdata_get_baseName,
868     domcdata_transformNodeToObject,
869     domcdata_get_data,
870     domcdata_put_data,
871     domcdata_get_length,
872     domcdata_substringData,
873     domcdata_appendData,
874     domcdata_insertData,
875     domcdata_deleteData,
876     domcdata_replaceData,
877     domcdata_splitText
878 };
879
880 static const tid_t domcdata_iface_tids[] = {
881     IXMLDOMCDATASection_tid,
882     0
883 };
884
885 static dispex_static_data_t domcdata_dispex = {
886     NULL,
887     IXMLDOMCDATASection_tid,
888     NULL,
889     domcdata_iface_tids
890 };
891
892 IUnknown* create_cdata( xmlNodePtr text )
893 {
894     domcdata *This;
895
896     This = heap_alloc( sizeof *This );
897     if ( !This )
898         return NULL;
899
900     This->IXMLDOMCDATASection_iface.lpVtbl = &domcdata_vtbl;
901     This->ref = 1;
902
903     init_xmlnode(&This->node, text, (IXMLDOMNode*)&This->IXMLDOMCDATASection_iface, &domcdata_dispex);
904
905     return (IUnknown*)&This->IXMLDOMCDATASection_iface;
906 }
907
908 #endif