msxml3: Don't use xmlnode's IXMLDOMNode iface in get_childNode implementations.
[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 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "ole2.h"
30 #include "msxml6.h"
31
32 #include "msxml_private.h"
33
34 #include "wine/debug.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
37
38 #ifdef HAVE_LIBXML2
39
40 typedef struct _domcdata
41 {
42     xmlnode node;
43     const struct IXMLDOMCDATASectionVtbl *lpVtbl;
44     LONG ref;
45 } domcdata;
46
47 static inline domcdata *impl_from_IXMLDOMCDATASection( IXMLDOMCDATASection *iface )
48 {
49     return (domcdata *)((char*)iface - FIELD_OFFSET(domcdata, lpVtbl));
50 }
51
52 static HRESULT WINAPI domcdata_QueryInterface(
53     IXMLDOMCDATASection *iface,
54     REFIID riid,
55     void** ppvObject )
56 {
57     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
58     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
59
60     if ( IsEqualGUID( riid, &IID_IXMLDOMCDATASection ) ||
61          IsEqualGUID( riid, &IID_IXMLDOMCharacterData) ||
62          IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
63          IsEqualGUID( riid, &IID_IDispatch ) ||
64          IsEqualGUID( riid, &IID_IUnknown ) )
65     {
66         *ppvObject = iface;
67     }
68     else if ( IsEqualGUID( riid, &IID_IXMLDOMText ) ||
69               IsEqualGUID( riid, &IID_IXMLDOMElement ) )
70     {
71         TRACE("Unsupported interface\n");
72         return E_NOINTERFACE;
73     }
74     else if(node_query_interface(&This->node, riid, ppvObject))
75     {
76         return *ppvObject ? S_OK : E_NOINTERFACE;
77     }
78     else
79     {
80         FIXME("Unsupported interface %s\n", debugstr_guid(riid));
81         return E_NOINTERFACE;
82     }
83
84     IXMLDOMText_AddRef((IUnknown*)*ppvObject);
85     return S_OK;
86 }
87
88 static ULONG WINAPI domcdata_AddRef(
89     IXMLDOMCDATASection *iface )
90 {
91     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
92     return InterlockedIncrement( &This->ref );
93 }
94
95 static ULONG WINAPI domcdata_Release(
96     IXMLDOMCDATASection *iface )
97 {
98     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
99     ULONG ref;
100
101     ref = InterlockedDecrement( &This->ref );
102     if ( ref == 0 )
103     {
104         destroy_xmlnode(&This->node);
105         heap_free( This );
106     }
107
108     return ref;
109 }
110
111 static HRESULT WINAPI domcdata_GetTypeInfoCount(
112     IXMLDOMCDATASection *iface,
113     UINT* pctinfo )
114 {
115     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
116
117     TRACE("(%p)->(%p)\n", This, pctinfo);
118
119     *pctinfo = 1;
120
121     return S_OK;
122 }
123
124 static HRESULT WINAPI domcdata_GetTypeInfo(
125     IXMLDOMCDATASection *iface,
126     UINT iTInfo, LCID lcid,
127     ITypeInfo** ppTInfo )
128 {
129     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
130     HRESULT hr;
131
132     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
133
134     hr = get_typeinfo(IXMLDOMCDATASection_tid, ppTInfo);
135
136     return hr;
137 }
138
139 static HRESULT WINAPI domcdata_GetIDsOfNames(
140     IXMLDOMCDATASection *iface,
141     REFIID riid, LPOLESTR* rgszNames,
142     UINT cNames, LCID lcid, DISPID* rgDispId )
143 {
144     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
145     ITypeInfo *typeinfo;
146     HRESULT hr;
147
148     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
149           lcid, rgDispId);
150
151     if(!rgszNames || cNames == 0 || !rgDispId)
152         return E_INVALIDARG;
153
154     hr = get_typeinfo(IXMLDOMCDATASection_tid, &typeinfo);
155     if(SUCCEEDED(hr))
156     {
157         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
158         ITypeInfo_Release(typeinfo);
159     }
160
161     return hr;
162 }
163
164 static HRESULT WINAPI domcdata_Invoke(
165     IXMLDOMCDATASection *iface,
166     DISPID dispIdMember, REFIID riid, LCID lcid,
167     WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
168     EXCEPINFO* pExcepInfo, UINT* puArgErr )
169 {
170     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
171     ITypeInfo *typeinfo;
172     HRESULT hr;
173
174     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
175           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
176
177     hr = get_typeinfo(IXMLDOMCDATASection_tid, &typeinfo);
178     if(SUCCEEDED(hr))
179     {
180         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
181                 pVarResult, pExcepInfo, puArgErr);
182         ITypeInfo_Release(typeinfo);
183     }
184
185     return hr;
186 }
187
188 static HRESULT WINAPI domcdata_get_nodeName(
189     IXMLDOMCDATASection *iface,
190     BSTR* p )
191 {
192     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
193
194     static const WCHAR cdata_sectionW[] =
195         {'#','c','d','a','t','a','-','s','e','c','t','i','o','n',0};
196
197     TRACE("(%p)->(%p)\n", This, p);
198
199     return return_bstr(cdata_sectionW, p);
200 }
201
202 static HRESULT WINAPI domcdata_get_nodeValue(
203     IXMLDOMCDATASection *iface,
204     VARIANT* value)
205 {
206     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
207
208     TRACE("(%p)->(%p)\n", This, value);
209
210     return node_get_content(&This->node, value);
211 }
212
213 static HRESULT WINAPI domcdata_put_nodeValue(
214     IXMLDOMCDATASection *iface,
215     VARIANT value)
216 {
217     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
218
219     TRACE("(%p)->(v%d)\n", This, V_VT(&value));
220
221     return node_put_value(&This->node, &value);
222 }
223
224 static HRESULT WINAPI domcdata_get_nodeType(
225     IXMLDOMCDATASection *iface,
226     DOMNodeType* domNodeType )
227 {
228     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
229
230     TRACE("(%p)->(%p)\n", This, domNodeType);
231
232     *domNodeType = NODE_CDATA_SECTION;
233     return S_OK;
234 }
235
236 static HRESULT WINAPI domcdata_get_parentNode(
237     IXMLDOMCDATASection *iface,
238     IXMLDOMNode** parent )
239 {
240     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
241
242     TRACE("(%p)->(%p)\n", This, parent);
243
244     return node_get_parent(&This->node, parent);
245 }
246
247 static HRESULT WINAPI domcdata_get_childNodes(
248     IXMLDOMCDATASection *iface,
249     IXMLDOMNodeList** outList)
250 {
251     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
252
253     TRACE("(%p)->(%p)\n", This, outList);
254
255     return node_get_child_nodes(&This->node, outList);
256 }
257
258 static HRESULT WINAPI domcdata_get_firstChild(
259     IXMLDOMCDATASection *iface,
260     IXMLDOMNode** domNode)
261 {
262     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
263     return IXMLDOMNode_get_firstChild( IXMLDOMNode_from_impl(&This->node), domNode );
264 }
265
266 static HRESULT WINAPI domcdata_get_lastChild(
267     IXMLDOMCDATASection *iface,
268     IXMLDOMNode** domNode)
269 {
270     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
271     return IXMLDOMNode_get_lastChild( IXMLDOMNode_from_impl(&This->node), domNode );
272 }
273
274 static HRESULT WINAPI domcdata_get_previousSibling(
275     IXMLDOMCDATASection *iface,
276     IXMLDOMNode** domNode)
277 {
278     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
279     return IXMLDOMNode_get_previousSibling( IXMLDOMNode_from_impl(&This->node), domNode );
280 }
281
282 static HRESULT WINAPI domcdata_get_nextSibling(
283     IXMLDOMCDATASection *iface,
284     IXMLDOMNode** domNode)
285 {
286     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
287     return IXMLDOMNode_get_nextSibling( IXMLDOMNode_from_impl(&This->node), domNode );
288 }
289
290 static HRESULT WINAPI domcdata_get_attributes(
291     IXMLDOMCDATASection *iface,
292     IXMLDOMNamedNodeMap** attributeMap)
293 {
294         domcdata *This = impl_from_IXMLDOMCDATASection( iface );
295     return IXMLDOMNode_get_attributes( IXMLDOMNode_from_impl(&This->node), attributeMap );
296 }
297
298 static HRESULT WINAPI domcdata_insertBefore(
299     IXMLDOMCDATASection *iface,
300     IXMLDOMNode* newNode, VARIANT var1,
301     IXMLDOMNode** outOldNode)
302 {
303     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
304     return IXMLDOMNode_insertBefore( IXMLDOMNode_from_impl(&This->node), newNode, var1, outOldNode );
305 }
306
307 static HRESULT WINAPI domcdata_replaceChild(
308     IXMLDOMCDATASection *iface,
309     IXMLDOMNode* newNode,
310     IXMLDOMNode* oldNode,
311     IXMLDOMNode** outOldNode)
312 {
313     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
314     return IXMLDOMNode_replaceChild( IXMLDOMNode_from_impl(&This->node), newNode, oldNode, outOldNode );
315 }
316
317 static HRESULT WINAPI domcdata_removeChild(
318     IXMLDOMCDATASection *iface,
319     IXMLDOMNode* domNode, IXMLDOMNode** oldNode)
320 {
321     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
322     return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), domNode, oldNode );
323 }
324
325 static HRESULT WINAPI domcdata_appendChild(
326     IXMLDOMCDATASection *iface,
327     IXMLDOMNode* newNode, IXMLDOMNode** outNewNode)
328 {
329     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
330     return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newNode, outNewNode );
331 }
332
333 static HRESULT WINAPI domcdata_hasChildNodes(
334     IXMLDOMCDATASection *iface,
335     VARIANT_BOOL* pbool)
336 {
337     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
338     return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), pbool );
339 }
340
341 static HRESULT WINAPI domcdata_get_ownerDocument(
342     IXMLDOMCDATASection *iface,
343     IXMLDOMDocument** domDocument)
344 {
345     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
346     return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), domDocument );
347 }
348
349 static HRESULT WINAPI domcdata_cloneNode(
350     IXMLDOMCDATASection *iface,
351     VARIANT_BOOL pbool, IXMLDOMNode** outNode)
352 {
353     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
354     return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), pbool, 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     return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), p );
363 }
364
365 static HRESULT WINAPI domcdata_get_text(
366     IXMLDOMCDATASection *iface,
367     BSTR* p)
368 {
369     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
370     return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), p );
371 }
372
373 static HRESULT WINAPI domcdata_put_text(
374     IXMLDOMCDATASection *iface,
375     BSTR p)
376 {
377     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
378     return IXMLDOMNode_put_text( IXMLDOMNode_from_impl(&This->node), p );
379 }
380
381 static HRESULT WINAPI domcdata_get_specified(
382     IXMLDOMCDATASection *iface,
383     VARIANT_BOOL* pbool)
384 {
385     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
386     return IXMLDOMNode_get_specified( IXMLDOMNode_from_impl(&This->node), pbool );
387 }
388
389 static HRESULT WINAPI domcdata_get_definition(
390     IXMLDOMCDATASection *iface,
391     IXMLDOMNode** domNode)
392 {
393     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
394     return IXMLDOMNode_get_definition( IXMLDOMNode_from_impl(&This->node), domNode );
395 }
396
397 static HRESULT WINAPI domcdata_get_nodeTypedValue(
398     IXMLDOMCDATASection *iface,
399     VARIANT* var1)
400 {
401     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
402     return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), var1 );
403 }
404
405 static HRESULT WINAPI domcdata_put_nodeTypedValue(
406     IXMLDOMCDATASection *iface,
407     VARIANT var1)
408 {
409     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
410     return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), var1 );
411 }
412
413 static HRESULT WINAPI domcdata_get_dataType(
414     IXMLDOMCDATASection *iface,
415     VARIANT* var1)
416 {
417     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
418     return IXMLDOMNode_get_dataType( IXMLDOMNode_from_impl(&This->node), var1 );
419 }
420
421 static HRESULT WINAPI domcdata_put_dataType(
422     IXMLDOMCDATASection *iface,
423     BSTR p)
424 {
425     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
426     return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), p );
427 }
428
429 static HRESULT WINAPI domcdata_get_xml(
430     IXMLDOMCDATASection *iface,
431     BSTR* p)
432 {
433     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
434     return IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), p );
435 }
436
437 static HRESULT WINAPI domcdata_transformNode(
438     IXMLDOMCDATASection *iface,
439     IXMLDOMNode* domNode, BSTR* p)
440 {
441     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
442     return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), domNode, p );
443 }
444
445 static HRESULT WINAPI domcdata_selectNodes(
446     IXMLDOMCDATASection *iface,
447     BSTR p, IXMLDOMNodeList** outList)
448 {
449     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
450     return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), p, outList );
451 }
452
453 static HRESULT WINAPI domcdata_selectSingleNode(
454     IXMLDOMCDATASection *iface,
455     BSTR p, IXMLDOMNode** outNode)
456 {
457     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
458     return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), p, outNode );
459 }
460
461 static HRESULT WINAPI domcdata_get_parsed(
462     IXMLDOMCDATASection *iface,
463     VARIANT_BOOL* pbool)
464 {
465     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
466     return IXMLDOMNode_get_parsed( IXMLDOMNode_from_impl(&This->node), pbool );
467 }
468
469 static HRESULT WINAPI domcdata_get_namespaceURI(
470     IXMLDOMCDATASection *iface,
471     BSTR* p)
472 {
473     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
474     return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), p );
475 }
476
477 static HRESULT WINAPI domcdata_get_prefix(
478     IXMLDOMCDATASection *iface,
479     BSTR* p)
480 {
481     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
482     return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), p );
483 }
484
485 static HRESULT WINAPI domcdata_get_baseName(
486     IXMLDOMCDATASection *iface,
487     BSTR* p)
488 {
489     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
490     return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), p );
491 }
492
493 static HRESULT WINAPI domcdata_transformNodeToObject(
494     IXMLDOMCDATASection *iface,
495     IXMLDOMNode* domNode, VARIANT var1)
496 {
497     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
498     return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), domNode, var1 );
499 }
500
501 static HRESULT WINAPI domcdata_get_data(
502     IXMLDOMCDATASection *iface,
503     BSTR *p)
504 {
505     HRESULT hr;
506     VARIANT vRet;
507
508     if(!p)
509         return E_INVALIDARG;
510
511     hr = IXMLDOMCDATASection_get_nodeValue( iface, &vRet );
512     if(hr == S_OK)
513     {
514         *p = V_BSTR(&vRet);
515     }
516
517     return hr;
518 }
519
520 static HRESULT WINAPI domcdata_put_data(
521     IXMLDOMCDATASection *iface,
522     BSTR data)
523 {
524     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
525     VARIANT val;
526
527     TRACE("(%p)->(%s)\n", This, debugstr_w(data) );
528
529     V_VT(&val) = VT_BSTR;
530     V_BSTR(&val) = data;
531
532     return IXMLDOMCDATASection_put_nodeValue( iface, val );
533 }
534
535 static HRESULT WINAPI domcdata_get_length(
536     IXMLDOMCDATASection *iface,
537     LONG *len)
538 {
539     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
540     HRESULT hr;
541     BSTR data;
542
543     TRACE("(%p)->(%p)\n", This, len);
544
545     if(!len)
546         return E_INVALIDARG;
547
548     hr = IXMLDOMCDATASection_get_data(iface, &data);
549     if(hr == S_OK)
550     {
551         *len = SysStringLen(data);
552         SysFreeString(data);
553     }
554
555     return S_OK;
556 }
557
558 static HRESULT WINAPI domcdata_substringData(
559     IXMLDOMCDATASection *iface,
560     LONG offset, LONG count, BSTR *p)
561 {
562     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
563     HRESULT hr;
564     BSTR data;
565
566     TRACE("(%p)->(%d %d %p)\n", This, offset, count, p);
567
568     if(!p)
569         return E_INVALIDARG;
570
571     *p = NULL;
572     if(offset < 0 || count < 0)
573         return E_INVALIDARG;
574
575     if(count == 0)
576         return S_FALSE;
577
578     hr = IXMLDOMCDATASection_get_data(iface, &data);
579     if(hr == S_OK)
580     {
581         LONG len = SysStringLen(data);
582
583         if(offset < len)
584         {
585             if(offset + count > len)
586                 *p = SysAllocString(&data[offset]);
587             else
588                 *p = SysAllocStringLen(&data[offset], count);
589         }
590         else
591             hr = S_FALSE;
592
593         SysFreeString(data);
594     }
595
596     return hr;
597 }
598
599 static HRESULT WINAPI domcdata_appendData(
600     IXMLDOMCDATASection *iface,
601     BSTR p)
602 {
603     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
604     HRESULT hr;
605     BSTR data;
606     LONG p_len;
607
608     TRACE("(%p)->(%s)\n", This, debugstr_w(p));
609
610     /* Nothing to do if NULL or an Empty string passed in. */
611     if((p_len = SysStringLen(p)) == 0) return S_OK;
612
613     hr = IXMLDOMCDATASection_get_data(iface, &data);
614     if(hr == S_OK)
615     {
616         LONG len = SysStringLen(data);
617         BSTR str = SysAllocStringLen(NULL, p_len + len);
618
619         memcpy(str, data, len*sizeof(WCHAR));
620         memcpy(&str[len], p, p_len*sizeof(WCHAR));
621         str[len+p_len] = 0;
622
623         hr = IXMLDOMCDATASection_put_data(iface, str);
624
625         SysFreeString(str);
626         SysFreeString(data);
627     }
628
629     return hr;
630 }
631
632 static HRESULT WINAPI domcdata_insertData(
633     IXMLDOMCDATASection *iface,
634     LONG offset, BSTR p)
635 {
636     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
637     HRESULT hr;
638     BSTR data;
639     LONG p_len;
640
641     TRACE("(%p)->(%d %s)\n", This, offset, debugstr_w(p));
642
643     /* If have a NULL or empty string, don't do anything. */
644     if((p_len = SysStringLen(p)) == 0)
645         return S_OK;
646
647     if(offset < 0)
648     {
649         return E_INVALIDARG;
650     }
651
652     hr = IXMLDOMCDATASection_get_data(iface, &data);
653     if(hr == S_OK)
654     {
655         LONG len = SysStringLen(data);
656         BSTR str;
657
658         if(len < offset)
659         {
660             SysFreeString(data);
661             return E_INVALIDARG;
662         }
663
664         str = SysAllocStringLen(NULL, len + p_len);
665         /* start part, supplied string and end part */
666         memcpy(str, data, offset*sizeof(WCHAR));
667         memcpy(&str[offset], p, p_len*sizeof(WCHAR));
668         memcpy(&str[offset+p_len], &data[offset], (len-offset)*sizeof(WCHAR));
669         str[len+p_len] = 0;
670
671         hr = IXMLDOMCDATASection_put_data(iface, str);
672
673         SysFreeString(str);
674         SysFreeString(data);
675     }
676
677     return hr;
678 }
679
680 static HRESULT WINAPI domcdata_deleteData(
681     IXMLDOMCDATASection *iface,
682     LONG offset, LONG count)
683 {
684     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
685     HRESULT hr;
686     LONG len = -1;
687     BSTR str;
688
689     TRACE("(%p)->(%d %d)\n", This, offset, count);
690
691     hr = IXMLDOMCDATASection_get_length(iface, &len);
692     if(hr != S_OK) return hr;
693
694     if((offset < 0) || (offset > len) || (count < 0))
695         return E_INVALIDARG;
696
697     if(len == 0) return S_OK;
698
699     /* cutting start or end */
700     if((offset == 0) || ((count + offset) >= len))
701     {
702         if(offset == 0)
703             IXMLDOMCDATASection_substringData(iface, count, len - count, &str);
704         else
705             IXMLDOMCDATASection_substringData(iface, 0, offset, &str);
706         hr = IXMLDOMCDATASection_put_data(iface, str);
707     }
708     else
709     /* cutting from the inside */
710     {
711         BSTR str_end;
712
713         IXMLDOMCDATASection_substringData(iface, 0, offset, &str);
714         IXMLDOMCDATASection_substringData(iface, offset + count, len - count, &str_end);
715
716         hr = IXMLDOMCDATASection_put_data(iface, str);
717         if(hr == S_OK)
718             hr = IXMLDOMCDATASection_appendData(iface, str_end);
719
720         SysFreeString(str_end);
721     }
722
723     SysFreeString(str);
724
725     return hr;
726 }
727
728 static HRESULT WINAPI domcdata_replaceData(
729     IXMLDOMCDATASection *iface,
730     LONG offset, LONG count, BSTR p)
731 {
732     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
733     HRESULT hr;
734
735     TRACE("(%p)->(%d %d %s)\n", This, offset, count, debugstr_w(p));
736
737     hr = IXMLDOMCDATASection_deleteData(iface, offset, count);
738
739     if (hr == S_OK)
740        hr = IXMLDOMCDATASection_insertData(iface, offset, p);
741
742     return hr;
743 }
744
745 static HRESULT WINAPI domcdata_splitText(
746     IXMLDOMCDATASection *iface,
747     LONG offset, IXMLDOMText **txtNode)
748 {
749     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
750     IXMLDOMDocument *doc;
751     LONG length = 0;
752     HRESULT hr;
753
754     TRACE("(%p)->(%d %p)\n", This, offset, txtNode);
755
756     if (!txtNode || offset < 0) return E_INVALIDARG;
757
758     *txtNode = NULL;
759
760     IXMLDOMCDATASection_get_length(iface, &length);
761
762     if (offset > length) return E_INVALIDARG;
763     if (offset == length) return S_FALSE;
764
765     hr = IXMLDOMCDATASection_get_ownerDocument(iface, &doc);
766     if (hr == S_OK)
767     {
768         BSTR data;
769
770         hr = IXMLDOMCDATASection_substringData(iface, offset, length - offset, &data);
771         if (hr == S_OK)
772         {
773             hr = IXMLDOMDocument_createTextNode(doc, data, txtNode);
774             if (hr == S_OK)
775             {
776                 IXMLDOMNode *parent;
777
778                 hr = IXMLDOMCDATASection_get_parentNode(iface, &parent);
779                 if (hr == S_OK)
780                 {
781                     IXMLDOMCDATASection_deleteData(iface, 0, offset);
782                     hr = IXMLDOMNode_appendChild(parent, (IXMLDOMNode*)*txtNode, NULL);
783                 }
784             }
785             SysFreeString(data);
786         }
787         IXMLDOMDocument_Release(doc);
788     }
789
790     return hr;
791 }
792
793 static const struct IXMLDOMCDATASectionVtbl domcdata_vtbl =
794 {
795     domcdata_QueryInterface,
796     domcdata_AddRef,
797     domcdata_Release,
798     domcdata_GetTypeInfoCount,
799     domcdata_GetTypeInfo,
800     domcdata_GetIDsOfNames,
801     domcdata_Invoke,
802     domcdata_get_nodeName,
803     domcdata_get_nodeValue,
804     domcdata_put_nodeValue,
805     domcdata_get_nodeType,
806     domcdata_get_parentNode,
807     domcdata_get_childNodes,
808     domcdata_get_firstChild,
809     domcdata_get_lastChild,
810     domcdata_get_previousSibling,
811     domcdata_get_nextSibling,
812     domcdata_get_attributes,
813     domcdata_insertBefore,
814     domcdata_replaceChild,
815     domcdata_removeChild,
816     domcdata_appendChild,
817     domcdata_hasChildNodes,
818     domcdata_get_ownerDocument,
819     domcdata_cloneNode,
820     domcdata_get_nodeTypeString,
821     domcdata_get_text,
822     domcdata_put_text,
823     domcdata_get_specified,
824     domcdata_get_definition,
825     domcdata_get_nodeTypedValue,
826     domcdata_put_nodeTypedValue,
827     domcdata_get_dataType,
828     domcdata_put_dataType,
829     domcdata_get_xml,
830     domcdata_transformNode,
831     domcdata_selectNodes,
832     domcdata_selectSingleNode,
833     domcdata_get_parsed,
834     domcdata_get_namespaceURI,
835     domcdata_get_prefix,
836     domcdata_get_baseName,
837     domcdata_transformNodeToObject,
838     domcdata_get_data,
839     domcdata_put_data,
840     domcdata_get_length,
841     domcdata_substringData,
842     domcdata_appendData,
843     domcdata_insertData,
844     domcdata_deleteData,
845     domcdata_replaceData,
846     domcdata_splitText
847 };
848
849 IUnknown* create_cdata( xmlNodePtr text )
850 {
851     domcdata *This;
852
853     This = heap_alloc( sizeof *This );
854     if ( !This )
855         return NULL;
856
857     This->lpVtbl = &domcdata_vtbl;
858     This->ref = 1;
859
860     init_xmlnode(&This->node, text, (IXMLDOMNode*)&This->lpVtbl, NULL);
861
862     return (IUnknown*) &This->lpVtbl;
863 }
864
865 #endif