mshtml: HTMLWindow_item code clean up.
[wine] / dlls / msxml3 / comment.c
1 /*
2  *    DOM comment node implementation
3  *
4  * Copyright 2006 Huw Davies
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 _domcomment
46 {
47     xmlnode node;
48     IXMLDOMComment IXMLDOMComment_iface;
49     LONG ref;
50 } domcomment;
51
52 static inline domcomment *impl_from_IXMLDOMComment( IXMLDOMComment *iface )
53 {
54     return CONTAINING_RECORD(iface, domcomment, IXMLDOMComment_iface);
55 }
56
57 static HRESULT WINAPI domcomment_QueryInterface(
58     IXMLDOMComment *iface,
59     REFIID riid,
60     void** ppvObject )
61 {
62     domcomment *This = impl_from_IXMLDOMComment( iface );
63     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
64
65     if ( IsEqualGUID( riid, &IID_IXMLDOMComment ) ||
66          IsEqualGUID( riid, &IID_IXMLDOMCharacterData) ||
67          IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
68          IsEqualGUID( riid, &IID_IDispatch ) ||
69          IsEqualGUID( riid, &IID_IUnknown ) )
70     {
71         *ppvObject = iface;
72     }
73     else if(node_query_interface(&This->node, riid, ppvObject))
74     {
75         return *ppvObject ? S_OK : E_NOINTERFACE;
76     }
77     else
78     {
79         TRACE("Unsupported interface %s\n", debugstr_guid(riid));
80         *ppvObject = NULL;
81         return E_NOINTERFACE;
82     }
83
84     IXMLDOMText_AddRef((IUnknown*)*ppvObject);
85     return S_OK;
86 }
87
88 static ULONG WINAPI domcomment_AddRef(
89     IXMLDOMComment *iface )
90 {
91     domcomment *This = impl_from_IXMLDOMComment( iface );
92     ULONG ref = InterlockedIncrement( &This->ref );
93     TRACE("(%p)->(%d)\n", This, ref);
94     return ref;
95 }
96
97 static ULONG WINAPI domcomment_Release(
98     IXMLDOMComment *iface )
99 {
100     domcomment *This = impl_from_IXMLDOMComment( iface );
101     ULONG ref = InterlockedDecrement( &This->ref );
102
103     TRACE("(%p)->(%d)\n", This, ref);
104     if ( ref == 0 )
105     {
106         destroy_xmlnode(&This->node);
107         heap_free( This );
108     }
109
110     return ref;
111 }
112
113 static HRESULT WINAPI domcomment_GetTypeInfoCount(
114     IXMLDOMComment *iface,
115     UINT* pctinfo )
116 {
117     domcomment *This = impl_from_IXMLDOMComment( iface );
118
119     TRACE("(%p)->(%p)\n", This, pctinfo);
120
121     *pctinfo = 1;
122
123     return S_OK;
124 }
125
126 static HRESULT WINAPI domcomment_GetTypeInfo(
127     IXMLDOMComment *iface,
128     UINT iTInfo, LCID lcid,
129     ITypeInfo** ppTInfo )
130 {
131     domcomment *This = impl_from_IXMLDOMComment( iface );
132     HRESULT hr;
133
134     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
135
136     hr = get_typeinfo(IXMLDOMComment_tid, ppTInfo);
137
138     return hr;
139 }
140
141 static HRESULT WINAPI domcomment_GetIDsOfNames(
142     IXMLDOMComment *iface,
143     REFIID riid, LPOLESTR* rgszNames,
144     UINT cNames, LCID lcid, DISPID* rgDispId )
145 {
146     domcomment *This = impl_from_IXMLDOMComment( iface );
147     ITypeInfo *typeinfo;
148     HRESULT hr;
149
150     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
151           lcid, rgDispId);
152
153     if(!rgszNames || cNames == 0 || !rgDispId)
154         return E_INVALIDARG;
155
156     hr = get_typeinfo(IXMLDOMComment_tid, &typeinfo);
157     if(SUCCEEDED(hr))
158     {
159         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
160         ITypeInfo_Release(typeinfo);
161     }
162
163     return hr;
164 }
165
166 static HRESULT WINAPI domcomment_Invoke(
167     IXMLDOMComment *iface,
168     DISPID dispIdMember, REFIID riid, LCID lcid,
169     WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
170     EXCEPINFO* pExcepInfo, UINT* puArgErr )
171 {
172     domcomment *This = impl_from_IXMLDOMComment( iface );
173     ITypeInfo *typeinfo;
174     HRESULT hr;
175
176     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
177           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
178
179     hr = get_typeinfo(IXMLDOMComment_tid, &typeinfo);
180     if(SUCCEEDED(hr))
181     {
182         hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMComment_iface, dispIdMember, wFlags,
183                 pDispParams, pVarResult, pExcepInfo, puArgErr);
184         ITypeInfo_Release(typeinfo);
185     }
186
187     return hr;
188 }
189
190 static HRESULT WINAPI domcomment_get_nodeName(
191     IXMLDOMComment *iface,
192     BSTR* p )
193 {
194     domcomment *This = impl_from_IXMLDOMComment( iface );
195
196     static const WCHAR commentW[] = {'#','c','o','m','m','e','n','t',0};
197
198     TRACE("(%p)->(%p)\n", This, p);
199
200     return return_bstr(commentW, p);
201 }
202
203 static HRESULT WINAPI domcomment_get_nodeValue(
204     IXMLDOMComment *iface,
205     VARIANT* value)
206 {
207     domcomment *This = impl_from_IXMLDOMComment( iface );
208
209     TRACE("(%p)->(%p)\n", This, value);
210
211     return node_get_content(&This->node, value);
212 }
213
214 static HRESULT WINAPI domcomment_put_nodeValue(
215     IXMLDOMComment *iface,
216     VARIANT value)
217 {
218     domcomment *This = impl_from_IXMLDOMComment( iface );
219
220     TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
221
222     return node_put_value(&This->node, &value);
223 }
224
225 static HRESULT WINAPI domcomment_get_nodeType(
226     IXMLDOMComment *iface,
227     DOMNodeType* domNodeType )
228 {
229     domcomment *This = impl_from_IXMLDOMComment( iface );
230
231     TRACE("(%p)->(%p)\n", This, domNodeType);
232
233     *domNodeType = NODE_COMMENT;
234     return S_OK;
235 }
236
237 static HRESULT WINAPI domcomment_get_parentNode(
238     IXMLDOMComment *iface,
239     IXMLDOMNode** parent )
240 {
241     domcomment *This = impl_from_IXMLDOMComment( iface );
242
243     TRACE("(%p)->(%p)\n", This, parent);
244
245     return node_get_parent(&This->node, parent);
246 }
247
248 static HRESULT WINAPI domcomment_get_childNodes(
249     IXMLDOMComment *iface,
250     IXMLDOMNodeList** outList)
251 {
252     domcomment *This = impl_from_IXMLDOMComment( iface );
253
254     TRACE("(%p)->(%p)\n", This, outList);
255
256     return node_get_child_nodes(&This->node, outList);
257 }
258
259 static HRESULT WINAPI domcomment_get_firstChild(
260     IXMLDOMComment *iface,
261     IXMLDOMNode** domNode)
262 {
263     domcomment *This = impl_from_IXMLDOMComment( iface );
264
265     TRACE("(%p)->(%p)\n", This, domNode);
266
267     return return_null_node(domNode);
268 }
269
270 static HRESULT WINAPI domcomment_get_lastChild(
271     IXMLDOMComment *iface,
272     IXMLDOMNode** domNode)
273 {
274     domcomment *This = impl_from_IXMLDOMComment( iface );
275
276     TRACE("(%p)->(%p)\n", This, domNode);
277
278     return return_null_node(domNode);
279 }
280
281 static HRESULT WINAPI domcomment_get_previousSibling(
282     IXMLDOMComment *iface,
283     IXMLDOMNode** domNode)
284 {
285     domcomment *This = impl_from_IXMLDOMComment( iface );
286
287     TRACE("(%p)->(%p)\n", This, domNode);
288
289     return node_get_previous_sibling(&This->node, domNode);
290 }
291
292 static HRESULT WINAPI domcomment_get_nextSibling(
293     IXMLDOMComment *iface,
294     IXMLDOMNode** domNode)
295 {
296     domcomment *This = impl_from_IXMLDOMComment( iface );
297
298     TRACE("(%p)->(%p)\n", This, domNode);
299
300     return node_get_next_sibling(&This->node, domNode);
301 }
302
303 static HRESULT WINAPI domcomment_get_attributes(
304     IXMLDOMComment *iface,
305     IXMLDOMNamedNodeMap** attributeMap)
306 {
307     domcomment *This = impl_from_IXMLDOMComment( iface );
308
309     TRACE("(%p)->(%p)\n", This, attributeMap);
310
311     return return_null_ptr((void**)attributeMap);
312 }
313
314 static HRESULT WINAPI domcomment_insertBefore(
315     IXMLDOMComment *iface,
316     IXMLDOMNode* newNode, VARIANT refChild,
317     IXMLDOMNode** outOldNode)
318 {
319     domcomment *This = impl_from_IXMLDOMComment( iface );
320
321     FIXME("(%p)->(%p %s %p) needs test\n", This, newNode, debugstr_variant(&refChild), outOldNode);
322
323     return node_insert_before(&This->node, newNode, &refChild, outOldNode);
324 }
325
326 static HRESULT WINAPI domcomment_replaceChild(
327     IXMLDOMComment *iface,
328     IXMLDOMNode* newNode,
329     IXMLDOMNode* oldNode,
330     IXMLDOMNode** outOldNode)
331 {
332     domcomment *This = impl_from_IXMLDOMComment( iface );
333
334     FIXME("(%p)->(%p %p %p) needs tests\n", This, newNode, oldNode, outOldNode);
335
336     return node_replace_child(&This->node, newNode, oldNode, outOldNode);
337 }
338
339 static HRESULT WINAPI domcomment_removeChild(
340     IXMLDOMComment *iface,
341     IXMLDOMNode *child, IXMLDOMNode **oldChild)
342 {
343     domcomment *This = impl_from_IXMLDOMComment( iface );
344     TRACE("(%p)->(%p %p)\n", This, child, oldChild);
345     return node_remove_child(&This->node, child, oldChild);
346 }
347
348 static HRESULT WINAPI domcomment_appendChild(
349     IXMLDOMComment *iface,
350     IXMLDOMNode *child, IXMLDOMNode **outChild)
351 {
352     domcomment *This = impl_from_IXMLDOMComment( iface );
353     TRACE("(%p)->(%p %p)\n", This, child, outChild);
354     return node_append_child(&This->node, child, outChild);
355 }
356
357 static HRESULT WINAPI domcomment_hasChildNodes(
358     IXMLDOMComment *iface,
359     VARIANT_BOOL *ret)
360 {
361     domcomment *This = impl_from_IXMLDOMComment( iface );
362     TRACE("(%p)->(%p)\n", This, ret);
363     return node_has_childnodes(&This->node, ret);
364 }
365
366 static HRESULT WINAPI domcomment_get_ownerDocument(
367     IXMLDOMComment   *iface,
368     IXMLDOMDocument **doc)
369 {
370     domcomment *This = impl_from_IXMLDOMComment( iface );
371     TRACE("(%p)->(%p)\n", This, doc);
372     return node_get_owner_doc(&This->node, doc);
373 }
374
375 static HRESULT WINAPI domcomment_cloneNode(
376     IXMLDOMComment *iface,
377     VARIANT_BOOL deep, IXMLDOMNode** outNode)
378 {
379     domcomment *This = impl_from_IXMLDOMComment( iface );
380     TRACE("(%p)->(%d %p)\n", This, deep, outNode);
381     return node_clone( &This->node, deep, outNode );
382 }
383
384 static HRESULT WINAPI domcomment_get_nodeTypeString(
385     IXMLDOMComment *iface,
386     BSTR* p)
387 {
388     domcomment *This = impl_from_IXMLDOMComment( iface );
389     static const WCHAR commentW[] = {'c','o','m','m','e','n','t',0};
390
391     TRACE("(%p)->(%p)\n", This, p);
392
393     return return_bstr(commentW, p);
394 }
395
396 static HRESULT WINAPI domcomment_get_text(
397     IXMLDOMComment *iface,
398     BSTR* p)
399 {
400     domcomment *This = impl_from_IXMLDOMComment( iface );
401     TRACE("(%p)->(%p)\n", This, p);
402     return node_get_text(&This->node, p);
403 }
404
405 static HRESULT WINAPI domcomment_put_text(
406     IXMLDOMComment *iface,
407     BSTR p)
408 {
409     domcomment *This = impl_from_IXMLDOMComment( iface );
410     TRACE("(%p)->(%s)\n", This, debugstr_w(p));
411     return node_put_text( &This->node, p );
412 }
413
414 static HRESULT WINAPI domcomment_get_specified(
415     IXMLDOMComment *iface,
416     VARIANT_BOOL* isSpecified)
417 {
418     domcomment *This = impl_from_IXMLDOMComment( iface );
419     FIXME("(%p)->(%p) stub!\n", This, isSpecified);
420     *isSpecified = VARIANT_TRUE;
421     return S_OK;
422 }
423
424 static HRESULT WINAPI domcomment_get_definition(
425     IXMLDOMComment *iface,
426     IXMLDOMNode** definitionNode)
427 {
428     domcomment *This = impl_from_IXMLDOMComment( iface );
429     FIXME("(%p)->(%p)\n", This, definitionNode);
430     return E_NOTIMPL;
431 }
432
433 static HRESULT WINAPI domcomment_get_nodeTypedValue(
434     IXMLDOMComment *iface,
435     VARIANT* v)
436 {
437     domcomment *This = impl_from_IXMLDOMComment( iface );
438     TRACE("(%p)->(%p)\n", This, v);
439     return node_get_content(&This->node, v);
440 }
441
442 static HRESULT WINAPI domcomment_put_nodeTypedValue(
443     IXMLDOMComment *iface,
444     VARIANT typedValue)
445 {
446     domcomment *This = impl_from_IXMLDOMComment( iface );
447     FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
448     return E_NOTIMPL;
449 }
450
451 static HRESULT WINAPI domcomment_get_dataType(
452     IXMLDOMComment *iface,
453     VARIANT* typename)
454 {
455     domcomment *This = impl_from_IXMLDOMComment( iface );
456     TRACE("(%p)->(%p)\n", This, typename);
457     return return_null_var( typename );
458 }
459
460 static HRESULT WINAPI domcomment_put_dataType(
461     IXMLDOMComment *iface,
462     BSTR p)
463 {
464     domcomment *This = impl_from_IXMLDOMComment( iface );
465
466     FIXME("(%p)->(%s)\n", This, debugstr_w(p));
467
468     if(!p)
469         return E_INVALIDARG;
470
471     return E_FAIL;
472 }
473
474 static HRESULT WINAPI domcomment_get_xml(
475     IXMLDOMComment *iface,
476     BSTR* p)
477 {
478     domcomment *This = impl_from_IXMLDOMComment( iface );
479
480     TRACE("(%p)->(%p)\n", This, p);
481
482     return node_get_xml(&This->node, FALSE, FALSE, p);
483 }
484
485 static HRESULT WINAPI domcomment_transformNode(
486     IXMLDOMComment *iface,
487     IXMLDOMNode *node, BSTR *p)
488 {
489     domcomment *This = impl_from_IXMLDOMComment( iface );
490     TRACE("(%p)->(%p %p)\n", This, node, p);
491     return node_transform_node(&This->node, node, p);
492 }
493
494 static HRESULT WINAPI domcomment_selectNodes(
495     IXMLDOMComment *iface,
496     BSTR p, IXMLDOMNodeList** outList)
497 {
498     domcomment *This = impl_from_IXMLDOMComment( iface );
499     TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
500     return node_select_nodes(&This->node, p, outList);
501 }
502
503 static HRESULT WINAPI domcomment_selectSingleNode(
504     IXMLDOMComment *iface,
505     BSTR p, IXMLDOMNode** outNode)
506 {
507     domcomment *This = impl_from_IXMLDOMComment( iface );
508     TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
509     return node_select_singlenode(&This->node, p, outNode);
510 }
511
512 static HRESULT WINAPI domcomment_get_parsed(
513     IXMLDOMComment *iface,
514     VARIANT_BOOL* isParsed)
515 {
516     domcomment *This = impl_from_IXMLDOMComment( iface );
517     FIXME("(%p)->(%p) stub!\n", This, isParsed);
518     *isParsed = VARIANT_TRUE;
519     return S_OK;
520 }
521
522 static HRESULT WINAPI domcomment_get_namespaceURI(
523     IXMLDOMComment *iface,
524     BSTR* p)
525 {
526     domcomment *This = impl_from_IXMLDOMComment( iface );
527     TRACE("(%p)->(%p)\n", This, p);
528     return node_get_namespaceURI(&This->node, p);
529 }
530
531 static HRESULT WINAPI domcomment_get_prefix(
532     IXMLDOMComment *iface,
533     BSTR* prefix)
534 {
535     domcomment *This = impl_from_IXMLDOMComment( iface );
536     TRACE("(%p)->(%p)\n", This, prefix);
537     return return_null_bstr( prefix );
538 }
539
540 static HRESULT WINAPI domcomment_get_baseName(
541     IXMLDOMComment *iface,
542     BSTR* name)
543 {
544     domcomment *This = impl_from_IXMLDOMComment( iface );
545     TRACE("(%p)->(%p)\n", This, name);
546     return return_null_bstr( name );
547 }
548
549 static HRESULT WINAPI domcomment_transformNodeToObject(
550     IXMLDOMComment *iface,
551     IXMLDOMNode* domNode, VARIANT var1)
552 {
553     domcomment *This = impl_from_IXMLDOMComment( iface );
554     FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1));
555     return E_NOTIMPL;
556 }
557
558 static HRESULT WINAPI domcomment_get_data(
559     IXMLDOMComment *iface,
560     BSTR *p)
561 {
562     domcomment *This = impl_from_IXMLDOMComment( iface );
563     HRESULT hr;
564     VARIANT vRet;
565
566     TRACE("(%p)->(%p)\n", This, p);
567
568     if(!p)
569         return E_INVALIDARG;
570
571     hr = IXMLDOMComment_get_nodeValue( iface, &vRet );
572     if(hr == S_OK)
573     {
574         *p = V_BSTR(&vRet);
575     }
576
577     return hr;
578 }
579
580 static HRESULT WINAPI domcomment_put_data(
581     IXMLDOMComment *iface,
582     BSTR data)
583 {
584     domcomment *This = impl_from_IXMLDOMComment( iface );
585     VARIANT val;
586
587     TRACE("(%p)->(%s)\n", This, debugstr_w(data) );
588
589     V_VT(&val) = VT_BSTR;
590     V_BSTR(&val) = data;
591     return node_put_value(&This->node, &val);
592 }
593
594 static HRESULT WINAPI domcomment_get_length(
595     IXMLDOMComment *iface,
596     LONG *len)
597 {
598     domcomment *This = impl_from_IXMLDOMComment( iface );
599     HRESULT hr;
600     BSTR data;
601
602     TRACE("(%p)->(%p)\n", This, len);
603
604     if(!len)
605         return E_INVALIDARG;
606
607     hr = IXMLDOMComment_get_data(iface, &data);
608     if(hr == S_OK)
609     {
610         *len = SysStringLen(data);
611         SysFreeString(data);
612     }
613
614     return hr;
615 }
616
617 static HRESULT WINAPI domcomment_substringData(
618     IXMLDOMComment *iface,
619     LONG offset, LONG count, BSTR *p)
620 {
621     domcomment *This = impl_from_IXMLDOMComment( iface );
622     HRESULT hr;
623     BSTR data;
624
625     TRACE("(%p)->(%d %d %p)\n", This, offset, count, p);
626
627     if(!p)
628         return E_INVALIDARG;
629
630     *p = NULL;
631     if(offset < 0 || count < 0)
632         return E_INVALIDARG;
633
634     if(count == 0)
635         return S_FALSE;
636
637     hr = IXMLDOMComment_get_data(iface, &data);
638     if(hr == S_OK)
639     {
640         LONG len = SysStringLen(data);
641
642         if(offset < len)
643         {
644             if(offset + count > len)
645                 *p = SysAllocString(&data[offset]);
646             else
647                 *p = SysAllocStringLen(&data[offset], count);
648         }
649         else
650             hr = S_FALSE;
651
652         SysFreeString(data);
653     }
654
655     return hr;
656 }
657
658 static HRESULT WINAPI domcomment_appendData(
659     IXMLDOMComment *iface,
660     BSTR p)
661 {
662     domcomment *This = impl_from_IXMLDOMComment( iface );
663     HRESULT hr;
664     BSTR data;
665     LONG p_len;
666
667     TRACE("(%p)->(%s)\n", This, debugstr_w(p));
668
669     /* Nothing to do if NULL or an Empty string passed in. */
670     if((p_len = SysStringLen(p)) == 0) return S_OK;
671
672     hr = IXMLDOMComment_get_data(iface, &data);
673     if(hr == S_OK)
674     {
675         LONG len = SysStringLen(data);
676         BSTR str = SysAllocStringLen(NULL, p_len + len);
677
678         memcpy(str, data, len*sizeof(WCHAR));
679         memcpy(&str[len], p, p_len*sizeof(WCHAR));
680         str[len+p_len] = 0;
681
682         hr = IXMLDOMComment_put_data(iface, str);
683
684         SysFreeString(str);
685         SysFreeString(data);
686     }
687
688     return hr;
689 }
690
691 static HRESULT WINAPI domcomment_insertData(
692     IXMLDOMComment *iface,
693     LONG offset, BSTR p)
694 {
695     domcomment *This = impl_from_IXMLDOMComment( iface );
696     HRESULT hr;
697     BSTR data;
698     LONG p_len;
699
700     TRACE("(%p)->(%d %s)\n", This, offset, debugstr_w(p));
701
702     /* If have a NULL or empty string, don't do anything. */
703     if((p_len = SysStringLen(p)) == 0)
704         return S_OK;
705
706     if(offset < 0)
707     {
708         return E_INVALIDARG;
709     }
710
711     hr = IXMLDOMComment_get_data(iface, &data);
712     if(hr == S_OK)
713     {
714         LONG len = SysStringLen(data);
715         BSTR str;
716
717         if(len < offset)
718         {
719             SysFreeString(data);
720             return E_INVALIDARG;
721         }
722
723         str = SysAllocStringLen(NULL, len + p_len);
724         /* start part, supplied string and end part */
725         memcpy(str, data, offset*sizeof(WCHAR));
726         memcpy(&str[offset], p, p_len*sizeof(WCHAR));
727         memcpy(&str[offset+p_len], &data[offset], (len-offset)*sizeof(WCHAR));
728         str[len+p_len] = 0;
729
730         hr = IXMLDOMComment_put_data(iface, str);
731
732         SysFreeString(str);
733         SysFreeString(data);
734     }
735
736     return hr;
737 }
738
739 static HRESULT WINAPI domcomment_deleteData(
740     IXMLDOMComment *iface,
741     LONG offset, LONG count)
742 {
743     HRESULT hr;
744     LONG len = -1;
745     BSTR str;
746
747     TRACE("(%p)->(%d %d)\n", iface, offset, count);
748
749     hr = IXMLDOMComment_get_length(iface, &len);
750     if(hr != S_OK) return hr;
751
752     if((offset < 0) || (offset > len) || (count < 0))
753         return E_INVALIDARG;
754
755     if(len == 0) return S_OK;
756
757     /* cutting start or end */
758     if((offset == 0) || ((count + offset) >= len))
759     {
760         if(offset == 0)
761             IXMLDOMComment_substringData(iface, count, len - count, &str);
762         else
763             IXMLDOMComment_substringData(iface, 0, offset, &str);
764         hr = IXMLDOMComment_put_data(iface, str);
765     }
766     else
767     /* cutting from the inside */
768     {
769         BSTR str_end;
770
771         IXMLDOMComment_substringData(iface, 0, offset, &str);
772         IXMLDOMComment_substringData(iface, offset + count, len - count, &str_end);
773
774         hr = IXMLDOMComment_put_data(iface, str);
775         if(hr == S_OK)
776             hr = IXMLDOMComment_appendData(iface, str_end);
777
778         SysFreeString(str_end);
779     }
780
781     SysFreeString(str);
782
783     return hr;
784 }
785
786 static HRESULT WINAPI domcomment_replaceData(
787     IXMLDOMComment *iface,
788     LONG offset, LONG count, BSTR p)
789 {
790     domcomment *This = impl_from_IXMLDOMComment( iface );
791     HRESULT hr;
792
793     TRACE("(%p)->(%d %d %s)\n", This, offset, count, debugstr_w(p));
794
795     hr = IXMLDOMComment_deleteData(iface, offset, count);
796
797     if (hr == S_OK)
798        hr = IXMLDOMComment_insertData(iface, offset, p);
799
800     return hr;
801 }
802
803 static const struct IXMLDOMCommentVtbl domcomment_vtbl =
804 {
805     domcomment_QueryInterface,
806     domcomment_AddRef,
807     domcomment_Release,
808     domcomment_GetTypeInfoCount,
809     domcomment_GetTypeInfo,
810     domcomment_GetIDsOfNames,
811     domcomment_Invoke,
812     domcomment_get_nodeName,
813     domcomment_get_nodeValue,
814     domcomment_put_nodeValue,
815     domcomment_get_nodeType,
816     domcomment_get_parentNode,
817     domcomment_get_childNodes,
818     domcomment_get_firstChild,
819     domcomment_get_lastChild,
820     domcomment_get_previousSibling,
821     domcomment_get_nextSibling,
822     domcomment_get_attributes,
823     domcomment_insertBefore,
824     domcomment_replaceChild,
825     domcomment_removeChild,
826     domcomment_appendChild,
827     domcomment_hasChildNodes,
828     domcomment_get_ownerDocument,
829     domcomment_cloneNode,
830     domcomment_get_nodeTypeString,
831     domcomment_get_text,
832     domcomment_put_text,
833     domcomment_get_specified,
834     domcomment_get_definition,
835     domcomment_get_nodeTypedValue,
836     domcomment_put_nodeTypedValue,
837     domcomment_get_dataType,
838     domcomment_put_dataType,
839     domcomment_get_xml,
840     domcomment_transformNode,
841     domcomment_selectNodes,
842     domcomment_selectSingleNode,
843     domcomment_get_parsed,
844     domcomment_get_namespaceURI,
845     domcomment_get_prefix,
846     domcomment_get_baseName,
847     domcomment_transformNodeToObject,
848     domcomment_get_data,
849     domcomment_put_data,
850     domcomment_get_length,
851     domcomment_substringData,
852     domcomment_appendData,
853     domcomment_insertData,
854     domcomment_deleteData,
855     domcomment_replaceData
856 };
857
858 static const tid_t domcomment_iface_tids[] = {
859     IXMLDOMComment_tid,
860     0
861 };
862
863 static dispex_static_data_t domcomment_dispex = {
864     NULL,
865     IXMLDOMComment_tid,
866     NULL,
867     domcomment_iface_tids
868 };
869
870 IUnknown* create_comment( xmlNodePtr comment )
871 {
872     domcomment *This;
873
874     This = heap_alloc( sizeof *This );
875     if ( !This )
876         return NULL;
877
878     This->IXMLDOMComment_iface.lpVtbl = &domcomment_vtbl;
879     This->ref = 1;
880
881     init_xmlnode(&This->node, comment, (IXMLDOMNode*)&This->IXMLDOMComment_iface, &domcomment_dispex);
882
883     return (IUnknown*)&This->IXMLDOMComment_iface;
884 }
885
886 #endif