xref: /reactos/dll/win32/msxml3/cdata.c (revision 8a978a17)
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 #ifdef HAVE_LIBXML2
42 
43 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
44 
45 typedef struct
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     NULL_tid
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     IXMLDOMCDATASection_AddRef(iface);
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     TRACE("(%p)->(%p %s %p)\n", This, newNode, debugstr_variant(&refChild), outOldNode);
294     if (outOldNode) *outOldNode = NULL;
295     return E_FAIL;
296 }
297 
298 static HRESULT WINAPI domcdata_replaceChild(
299     IXMLDOMCDATASection *iface,
300     IXMLDOMNode* newNode,
301     IXMLDOMNode* oldNode,
302     IXMLDOMNode** outOldNode)
303 {
304     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
305     TRACE("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode);
306     if (outOldNode) *outOldNode = NULL;
307     return E_FAIL;
308 }
309 
310 static HRESULT WINAPI domcdata_removeChild(
311     IXMLDOMCDATASection *iface,
312     IXMLDOMNode *child, IXMLDOMNode **oldChild)
313 {
314     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
315     TRACE("(%p)->(%p %p)\n", This, child, oldChild);
316     if (oldChild) *oldChild = NULL;
317     return E_FAIL;
318 }
319 
320 static HRESULT WINAPI domcdata_appendChild(
321     IXMLDOMCDATASection *iface,
322     IXMLDOMNode *child, IXMLDOMNode **outChild)
323 {
324     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
325     TRACE("(%p)->(%p %p)\n", This, child, outChild);
326     if (outChild) *outChild = NULL;
327     return E_FAIL;
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 return_var_false(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)->(%s)\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     TRACE("(%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, 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     TRACE("(%p)->(%s)\n", This, debugstr_w(data));
556     return node_set_content(&This->node, data);
557 }
558 
559 static HRESULT WINAPI domcdata_get_length(
560     IXMLDOMCDATASection *iface,
561     LONG *len)
562 {
563     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
564     HRESULT hr;
565     BSTR data;
566 
567     TRACE("(%p)->(%p)\n", This, len);
568 
569     if(!len)
570         return E_INVALIDARG;
571 
572     hr = IXMLDOMCDATASection_get_data(iface, &data);
573     if(hr == S_OK)
574     {
575         *len = SysStringLen(data);
576         SysFreeString(data);
577     }
578 
579     return S_OK;
580 }
581 
582 static HRESULT WINAPI domcdata_substringData(
583     IXMLDOMCDATASection *iface,
584     LONG offset, LONG count, BSTR *p)
585 {
586     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
587     HRESULT hr;
588     BSTR data;
589 
590     TRACE("(%p)->(%d %d %p)\n", This, offset, count, p);
591 
592     if(!p)
593         return E_INVALIDARG;
594 
595     *p = NULL;
596     if(offset < 0 || count < 0)
597         return E_INVALIDARG;
598 
599     if(count == 0)
600         return S_FALSE;
601 
602     hr = IXMLDOMCDATASection_get_data(iface, &data);
603     if(hr == S_OK)
604     {
605         LONG len = SysStringLen(data);
606 
607         if(offset < len)
608         {
609             if(offset + count > len)
610                 *p = SysAllocString(&data[offset]);
611             else
612                 *p = SysAllocStringLen(&data[offset], count);
613         }
614         else
615             hr = S_FALSE;
616 
617         SysFreeString(data);
618     }
619 
620     return hr;
621 }
622 
623 static HRESULT WINAPI domcdata_appendData(
624     IXMLDOMCDATASection *iface,
625     BSTR p)
626 {
627     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
628     HRESULT hr;
629     BSTR data;
630     LONG p_len;
631 
632     TRACE("(%p)->(%s)\n", This, debugstr_w(p));
633 
634     /* Nothing to do if NULL or an Empty string passed in. */
635     if((p_len = SysStringLen(p)) == 0) return S_OK;
636 
637     hr = IXMLDOMCDATASection_get_data(iface, &data);
638     if(hr == S_OK)
639     {
640         LONG len = SysStringLen(data);
641         BSTR str = SysAllocStringLen(NULL, p_len + len);
642 
643         memcpy(str, data, len*sizeof(WCHAR));
644         memcpy(&str[len], p, p_len*sizeof(WCHAR));
645         str[len+p_len] = 0;
646 
647         hr = IXMLDOMCDATASection_put_data(iface, str);
648 
649         SysFreeString(str);
650         SysFreeString(data);
651     }
652 
653     return hr;
654 }
655 
656 static HRESULT WINAPI domcdata_insertData(
657     IXMLDOMCDATASection *iface,
658     LONG offset, BSTR p)
659 {
660     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
661     HRESULT hr;
662     BSTR data;
663     LONG p_len;
664 
665     TRACE("(%p)->(%d %s)\n", This, offset, debugstr_w(p));
666 
667     /* If have a NULL or empty string, don't do anything. */
668     if((p_len = SysStringLen(p)) == 0)
669         return S_OK;
670 
671     if(offset < 0)
672     {
673         return E_INVALIDARG;
674     }
675 
676     hr = IXMLDOMCDATASection_get_data(iface, &data);
677     if(hr == S_OK)
678     {
679         LONG len = SysStringLen(data);
680         BSTR str;
681 
682         if(len < offset)
683         {
684             SysFreeString(data);
685             return E_INVALIDARG;
686         }
687 
688         str = SysAllocStringLen(NULL, len + p_len);
689         /* start part, supplied string and end part */
690         memcpy(str, data, offset*sizeof(WCHAR));
691         memcpy(&str[offset], p, p_len*sizeof(WCHAR));
692         memcpy(&str[offset+p_len], &data[offset], (len-offset)*sizeof(WCHAR));
693         str[len+p_len] = 0;
694 
695         hr = IXMLDOMCDATASection_put_data(iface, str);
696 
697         SysFreeString(str);
698         SysFreeString(data);
699     }
700 
701     return hr;
702 }
703 
704 static HRESULT WINAPI domcdata_deleteData(
705     IXMLDOMCDATASection *iface,
706     LONG offset, LONG count)
707 {
708     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
709     HRESULT hr;
710     LONG len = -1;
711     BSTR str;
712 
713     TRACE("(%p)->(%d %d)\n", This, offset, count);
714 
715     hr = IXMLDOMCDATASection_get_length(iface, &len);
716     if(hr != S_OK) return hr;
717 
718     if((offset < 0) || (offset > len) || (count < 0))
719         return E_INVALIDARG;
720 
721     if(len == 0) return S_OK;
722 
723     /* cutting start or end */
724     if((offset == 0) || ((count + offset) >= len))
725     {
726         if(offset == 0)
727             IXMLDOMCDATASection_substringData(iface, count, len - count, &str);
728         else
729             IXMLDOMCDATASection_substringData(iface, 0, offset, &str);
730         hr = IXMLDOMCDATASection_put_data(iface, str);
731     }
732     else
733     /* cutting from the inside */
734     {
735         BSTR str_end;
736 
737         IXMLDOMCDATASection_substringData(iface, 0, offset, &str);
738         IXMLDOMCDATASection_substringData(iface, offset + count, len - count, &str_end);
739 
740         hr = IXMLDOMCDATASection_put_data(iface, str);
741         if(hr == S_OK)
742             hr = IXMLDOMCDATASection_appendData(iface, str_end);
743 
744         SysFreeString(str_end);
745     }
746 
747     SysFreeString(str);
748 
749     return hr;
750 }
751 
752 static HRESULT WINAPI domcdata_replaceData(
753     IXMLDOMCDATASection *iface,
754     LONG offset, LONG count, BSTR p)
755 {
756     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
757     HRESULT hr;
758 
759     TRACE("(%p)->(%d %d %s)\n", This, offset, count, debugstr_w(p));
760 
761     hr = IXMLDOMCDATASection_deleteData(iface, offset, count);
762 
763     if (hr == S_OK)
764        hr = IXMLDOMCDATASection_insertData(iface, offset, p);
765 
766     return hr;
767 }
768 
769 static HRESULT WINAPI domcdata_splitText(
770     IXMLDOMCDATASection *iface,
771     LONG offset, IXMLDOMText **txtNode)
772 {
773     domcdata *This = impl_from_IXMLDOMCDATASection( iface );
774     IXMLDOMDocument *doc;
775     LONG length = 0;
776     HRESULT hr;
777 
778     TRACE("(%p)->(%d %p)\n", This, offset, txtNode);
779 
780     if (!txtNode || offset < 0) return E_INVALIDARG;
781 
782     *txtNode = NULL;
783 
784     IXMLDOMCDATASection_get_length(iface, &length);
785 
786     if (offset > length) return E_INVALIDARG;
787     if (offset == length) return S_FALSE;
788 
789     hr = IXMLDOMCDATASection_get_ownerDocument(iface, &doc);
790     if (hr == S_OK)
791     {
792         BSTR data;
793 
794         hr = IXMLDOMCDATASection_substringData(iface, offset, length - offset, &data);
795         if (hr == S_OK)
796         {
797             hr = IXMLDOMDocument_createTextNode(doc, data, txtNode);
798             if (hr == S_OK)
799             {
800                 IXMLDOMNode *parent;
801 
802                 hr = IXMLDOMCDATASection_get_parentNode(iface, &parent);
803                 if (hr == S_OK)
804                 {
805                     IXMLDOMCDATASection_deleteData(iface, 0, offset);
806                     hr = IXMLDOMNode_appendChild(parent, (IXMLDOMNode*)*txtNode, NULL);
807                     IXMLDOMNode_Release(parent);
808                 }
809             }
810             SysFreeString(data);
811         }
812         IXMLDOMDocument_Release(doc);
813     }
814 
815     return hr;
816 }
817 
818 static const struct IXMLDOMCDATASectionVtbl domcdata_vtbl =
819 {
820     domcdata_QueryInterface,
821     domcdata_AddRef,
822     domcdata_Release,
823     domcdata_GetTypeInfoCount,
824     domcdata_GetTypeInfo,
825     domcdata_GetIDsOfNames,
826     domcdata_Invoke,
827     domcdata_get_nodeName,
828     domcdata_get_nodeValue,
829     domcdata_put_nodeValue,
830     domcdata_get_nodeType,
831     domcdata_get_parentNode,
832     domcdata_get_childNodes,
833     domcdata_get_firstChild,
834     domcdata_get_lastChild,
835     domcdata_get_previousSibling,
836     domcdata_get_nextSibling,
837     domcdata_get_attributes,
838     domcdata_insertBefore,
839     domcdata_replaceChild,
840     domcdata_removeChild,
841     domcdata_appendChild,
842     domcdata_hasChildNodes,
843     domcdata_get_ownerDocument,
844     domcdata_cloneNode,
845     domcdata_get_nodeTypeString,
846     domcdata_get_text,
847     domcdata_put_text,
848     domcdata_get_specified,
849     domcdata_get_definition,
850     domcdata_get_nodeTypedValue,
851     domcdata_put_nodeTypedValue,
852     domcdata_get_dataType,
853     domcdata_put_dataType,
854     domcdata_get_xml,
855     domcdata_transformNode,
856     domcdata_selectNodes,
857     domcdata_selectSingleNode,
858     domcdata_get_parsed,
859     domcdata_get_namespaceURI,
860     domcdata_get_prefix,
861     domcdata_get_baseName,
862     domcdata_transformNodeToObject,
863     domcdata_get_data,
864     domcdata_put_data,
865     domcdata_get_length,
866     domcdata_substringData,
867     domcdata_appendData,
868     domcdata_insertData,
869     domcdata_deleteData,
870     domcdata_replaceData,
871     domcdata_splitText
872 };
873 
874 static const tid_t domcdata_iface_tids[] = {
875     IXMLDOMCDATASection_tid,
876     0
877 };
878 
879 static dispex_static_data_t domcdata_dispex = {
880     NULL,
881     IXMLDOMCDATASection_tid,
882     NULL,
883     domcdata_iface_tids
884 };
885 
886 IUnknown* create_cdata( xmlNodePtr text )
887 {
888     domcdata *This;
889 
890     This = heap_alloc( sizeof *This );
891     if ( !This )
892         return NULL;
893 
894     This->IXMLDOMCDATASection_iface.lpVtbl = &domcdata_vtbl;
895     This->ref = 1;
896 
897     init_xmlnode(&This->node, text, (IXMLDOMNode*)&This->IXMLDOMCDATASection_iface, &domcdata_dispex);
898 
899     return (IUnknown*)&This->IXMLDOMCDATASection_iface;
900 }
901 
902 #endif
903