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