gdiplus: Implement BMP encoding.
[wine] / dlls / mshtml / htmlbody.c
1 /*
2  * Copyright 2006 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "config.h"
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winnls.h"
30 #include "ole2.h"
31
32 #include "wine/debug.h"
33
34 #include "mshtml_private.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
37
38 typedef struct {
39     HTMLTextContainer textcont;
40
41     const IHTMLBodyElementVtbl *lpHTMLBodyElementVtbl;
42
43     ConnectionPoint cp_propnotif;
44
45     nsIDOMHTMLBodyElement *nsbody;
46 } HTMLBodyElement;
47
48 #define HTMLBODY(x)  ((IHTMLBodyElement*)  &(x)->lpHTMLBodyElementVtbl)
49
50 static BOOL variant_to_nscolor(const VARIANT *v, nsAString *nsstr)
51 {
52     switch(V_VT(v)) {
53     case VT_BSTR:
54         nsAString_Init(nsstr, V_BSTR(v));
55         return TRUE;
56
57     case VT_I4: {
58         PRUnichar buf[10];
59         static const WCHAR formatW[] = {'#','%','x',0};
60
61         wsprintfW(buf, formatW, V_I4(v));
62         nsAString_Init(nsstr, buf);
63         return TRUE;
64     }
65
66     default:
67         FIXME("invalid vt=%d\n", V_VT(v));
68     }
69
70     return FALSE;
71
72 }
73
74 static void nscolor_to_variant(const nsAString *nsstr, VARIANT *p)
75 {
76     const PRUnichar *color;
77
78     nsAString_GetData(nsstr, &color);
79
80     if(*color == '#') {
81         V_VT(p) = VT_I4;
82         V_I4(p) = strtolW(color+1, NULL, 16);
83     }else {
84         V_VT(p) = VT_BSTR;
85         V_BSTR(p) = SysAllocString(color);
86     }
87 }
88
89 #define HTMLBODY_THIS(iface) DEFINE_THIS(HTMLBodyElement, HTMLBodyElement, iface)
90
91 static HRESULT WINAPI HTMLBodyElement_QueryInterface(IHTMLBodyElement *iface,
92                                                      REFIID riid, void **ppv)
93 {
94     HTMLBodyElement *This = HTMLBODY_THIS(iface);
95
96     return IHTMLDOMNode_QueryInterface(HTMLDOMNODE(&This->textcont.element.node), riid, ppv);
97 }
98
99 static ULONG WINAPI HTMLBodyElement_AddRef(IHTMLBodyElement *iface)
100 {
101     HTMLBodyElement *This = HTMLBODY_THIS(iface);
102
103     return IHTMLDOMNode_AddRef(HTMLDOMNODE(&This->textcont.element.node));
104 }
105
106 static ULONG WINAPI HTMLBodyElement_Release(IHTMLBodyElement *iface)
107 {
108     HTMLBodyElement *This = HTMLBODY_THIS(iface);
109
110     return IHTMLDOMNode_Release(HTMLDOMNODE(&This->textcont.element.node));
111 }
112
113 static HRESULT WINAPI HTMLBodyElement_GetTypeInfoCount(IHTMLBodyElement *iface, UINT *pctinfo)
114 {
115     HTMLBodyElement *This = HTMLBODY_THIS(iface);
116     FIXME("(%p)->(%p)\n", This, pctinfo);
117     return E_NOTIMPL;
118 }
119
120 static HRESULT WINAPI HTMLBodyElement_GetTypeInfo(IHTMLBodyElement *iface, UINT iTInfo,
121                                               LCID lcid, ITypeInfo **ppTInfo)
122 {
123     HTMLBodyElement *This = HTMLBODY_THIS(iface);
124     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
125     return E_NOTIMPL;
126 }
127
128 static HRESULT WINAPI HTMLBodyElement_GetIDsOfNames(IHTMLBodyElement *iface, REFIID riid,
129                                                 LPOLESTR *rgszNames, UINT cNames,
130                                                 LCID lcid, DISPID *rgDispId)
131 {
132     HTMLBodyElement *This = HTMLBODY_THIS(iface);
133     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
134                                         lcid, rgDispId);
135     return E_NOTIMPL;
136 }
137
138 static HRESULT WINAPI HTMLBodyElement_Invoke(IHTMLBodyElement *iface, DISPID dispIdMember,
139                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
140                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
141 {
142     HTMLBodyElement *This = HTMLBODY_THIS(iface);
143     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
144             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
145     return E_NOTIMPL;
146 }
147
148 static HRESULT WINAPI HTMLBodyElement_put_background(IHTMLBodyElement *iface, BSTR v)
149 {
150     HTMLBodyElement *This = HTMLBODY_THIS(iface);
151     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
152     return E_NOTIMPL;
153 }
154
155 static HRESULT WINAPI HTMLBodyElement_get_background(IHTMLBodyElement *iface, BSTR *p)
156 {
157     HTMLBodyElement *This = HTMLBODY_THIS(iface);
158     nsAString background_str;
159     nsresult nsres;
160
161     TRACE("(%p)->(%p)\n", This, p);
162
163     nsAString_Init(&background_str, NULL);
164
165     nsres = nsIDOMHTMLBodyElement_GetBackground(This->nsbody, &background_str);
166     if(NS_SUCCEEDED(nsres)) {
167         const PRUnichar *background;
168         nsAString_GetData(&background_str, &background);
169         *p = *background ? SysAllocString(background) : NULL;
170     }else {
171         ERR("GetBackground failed: %08x\n", nsres);
172         *p = NULL;
173     }
174
175     nsAString_Finish(&background_str);
176
177     TRACE("*p = %s\n", debugstr_w(*p));
178     return S_OK;
179 }
180
181 static HRESULT WINAPI HTMLBodyElement_put_bgProperties(IHTMLBodyElement *iface, BSTR v)
182 {
183     HTMLBodyElement *This = HTMLBODY_THIS(iface);
184     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
185     return E_NOTIMPL;
186 }
187
188 static HRESULT WINAPI HTMLBodyElement_get_bgProperties(IHTMLBodyElement *iface, BSTR *p)
189 {
190     HTMLBodyElement *This = HTMLBODY_THIS(iface);
191     FIXME("(%p)->(%p)\n", This, p);
192     return E_NOTIMPL;
193 }
194
195 static HRESULT WINAPI HTMLBodyElement_put_leftMargin(IHTMLBodyElement *iface, VARIANT v)
196 {
197     HTMLBodyElement *This = HTMLBODY_THIS(iface);
198     FIXME("(%p)->()\n", This);
199     return E_NOTIMPL;
200 }
201
202 static HRESULT WINAPI HTMLBodyElement_get_leftMargin(IHTMLBodyElement *iface, VARIANT *p)
203 {
204     HTMLBodyElement *This = HTMLBODY_THIS(iface);
205     FIXME("(%p)->(%p)\n", This, p);
206     return E_NOTIMPL;
207 }
208
209 static HRESULT WINAPI HTMLBodyElement_put_topMargin(IHTMLBodyElement *iface, VARIANT v)
210 {
211     HTMLBodyElement *This = HTMLBODY_THIS(iface);
212     FIXME("(%p)->()\n", This);
213     return E_NOTIMPL;
214 }
215
216 static HRESULT WINAPI HTMLBodyElement_get_topMargin(IHTMLBodyElement *iface, VARIANT *p)
217 {
218     HTMLBodyElement *This = HTMLBODY_THIS(iface);
219     FIXME("(%p)->(%p)\n", This, p);
220     return E_NOTIMPL;
221 }
222
223 static HRESULT WINAPI HTMLBodyElement_put_rightMargin(IHTMLBodyElement *iface, VARIANT v)
224 {
225     HTMLBodyElement *This = HTMLBODY_THIS(iface);
226     FIXME("(%p)->()\n", This);
227     return E_NOTIMPL;
228 }
229
230 static HRESULT WINAPI HTMLBodyElement_get_rightMargin(IHTMLBodyElement *iface, VARIANT *p)
231 {
232     HTMLBodyElement *This = HTMLBODY_THIS(iface);
233     FIXME("(%p)->(%p)\n", This, p);
234     return E_NOTIMPL;
235 }
236
237 static HRESULT WINAPI HTMLBodyElement_put_bottomMargin(IHTMLBodyElement *iface, VARIANT v)
238 {
239     HTMLBodyElement *This = HTMLBODY_THIS(iface);
240     FIXME("(%p)->()\n", This);
241     return E_NOTIMPL;
242 }
243
244 static HRESULT WINAPI HTMLBodyElement_get_bottomMargin(IHTMLBodyElement *iface, VARIANT *p)
245 {
246     HTMLBodyElement *This = HTMLBODY_THIS(iface);
247     FIXME("(%p)->(%p)\n", This, p);
248     return E_NOTIMPL;
249 }
250
251 static HRESULT WINAPI HTMLBodyElement_put_noWrap(IHTMLBodyElement *iface, VARIANT_BOOL v)
252 {
253     HTMLBodyElement *This = HTMLBODY_THIS(iface);
254     FIXME("(%p)->(%x)\n", This, v);
255     return E_NOTIMPL;
256 }
257
258 static HRESULT WINAPI HTMLBodyElement_get_noWrap(IHTMLBodyElement *iface, VARIANT_BOOL *p)
259 {
260     HTMLBodyElement *This = HTMLBODY_THIS(iface);
261     FIXME("(%p)->(%p)\n", This, p);
262     return E_NOTIMPL;
263 }
264
265 static HRESULT WINAPI HTMLBodyElement_put_bgColor(IHTMLBodyElement *iface, VARIANT v)
266 {
267     HTMLBodyElement *This = HTMLBODY_THIS(iface);
268     FIXME("(%p)->()\n", This);
269     return E_NOTIMPL;
270 }
271
272 static HRESULT WINAPI HTMLBodyElement_get_bgColor(IHTMLBodyElement *iface, VARIANT *p)
273 {
274     HTMLBodyElement *This = HTMLBODY_THIS(iface);
275     FIXME("(%p)->(%p)\n", This, p);
276     return E_NOTIMPL;
277 }
278
279 static HRESULT WINAPI HTMLBodyElement_put_text(IHTMLBodyElement *iface, VARIANT v)
280 {
281     HTMLBodyElement *This = HTMLBODY_THIS(iface);
282     FIXME("(%p)->()\n", This);
283     return E_NOTIMPL;
284 }
285
286 static HRESULT WINAPI HTMLBodyElement_get_text(IHTMLBodyElement *iface, VARIANT *p)
287 {
288     HTMLBodyElement *This = HTMLBODY_THIS(iface);
289     FIXME("(%p)->(%p)\n", This, p);
290     return E_NOTIMPL;
291 }
292
293 static HRESULT WINAPI HTMLBodyElement_put_link(IHTMLBodyElement *iface, VARIANT v)
294 {
295     HTMLBodyElement *This = HTMLBODY_THIS(iface);
296     nsAString link_str;
297     nsresult nsres;
298
299     TRACE("(%p)->(v%d)\n", This, V_VT(&v));
300
301     if(!variant_to_nscolor(&v, &link_str))
302         return S_OK;
303
304     nsres = nsIDOMHTMLBodyElement_SetLink(This->nsbody, &link_str);
305     nsAString_Finish(&link_str);
306     if(NS_FAILED(nsres))
307         ERR("SetLink failed: %08x\n", nsres);
308
309     return S_OK;
310 }
311
312 static HRESULT WINAPI HTMLBodyElement_get_link(IHTMLBodyElement *iface, VARIANT *p)
313 {
314     HTMLBodyElement *This = HTMLBODY_THIS(iface);
315     nsAString link_str;
316     nsresult nsres;
317
318     TRACE("(%p)->(%p)\n", This, p);
319
320     nsAString_Init(&link_str, NULL);
321     nsres = nsIDOMHTMLBodyElement_GetLink(This->nsbody, &link_str);
322     if(NS_FAILED(nsres))
323         ERR("GetLink failed: %08x\n", nsres);
324
325     nscolor_to_variant(&link_str, p);
326     nsAString_Finish(&link_str);
327
328     return S_OK;
329 }
330
331 static HRESULT WINAPI HTMLBodyElement_put_vLink(IHTMLBodyElement *iface, VARIANT v)
332 {
333     HTMLBodyElement *This = HTMLBODY_THIS(iface);
334     nsAString vlink_str;
335     nsresult nsres;
336
337     TRACE("(%p)->(v%d)\n", This, V_VT(&v));
338
339     if(!variant_to_nscolor(&v, &vlink_str))
340         return S_OK;
341
342     nsres = nsIDOMHTMLBodyElement_SetVLink(This->nsbody, &vlink_str);
343     nsAString_Finish(&vlink_str);
344     if(NS_FAILED(nsres))
345         ERR("SetLink failed: %08x\n", nsres);
346
347     return S_OK;
348 }
349
350 static HRESULT WINAPI HTMLBodyElement_get_vLink(IHTMLBodyElement *iface, VARIANT *p)
351 {
352     HTMLBodyElement *This = HTMLBODY_THIS(iface);
353     nsAString vlink_str;
354     nsresult nsres;
355
356     TRACE("(%p)->(%p)\n", This, p);
357
358     nsAString_Init(&vlink_str, NULL);
359     nsres = nsIDOMHTMLBodyElement_GetVLink(This->nsbody, &vlink_str);
360     if(NS_FAILED(nsres))
361         ERR("GetLink failed: %08x\n", nsres);
362
363     nscolor_to_variant(&vlink_str, p);
364     nsAString_Finish(&vlink_str);
365
366     return S_OK;
367 }
368
369 static HRESULT WINAPI HTMLBodyElement_put_aLink(IHTMLBodyElement *iface, VARIANT v)
370 {
371     HTMLBodyElement *This = HTMLBODY_THIS(iface);
372     nsAString alink_str;
373     nsresult nsres;
374
375     TRACE("(%p)->(v%d)\n", This, V_VT(&v));
376
377     if(!variant_to_nscolor(&v, &alink_str))
378         return S_OK;
379
380     nsres = nsIDOMHTMLBodyElement_SetALink(This->nsbody, &alink_str);
381     nsAString_Finish(&alink_str);
382     if(NS_FAILED(nsres))
383         ERR("SetALink failed: %08x\n", nsres);
384
385     return S_OK;
386 }
387
388 static HRESULT WINAPI HTMLBodyElement_get_aLink(IHTMLBodyElement *iface, VARIANT *p)
389 {
390     HTMLBodyElement *This = HTMLBODY_THIS(iface);
391     nsAString alink_str;
392     nsresult nsres;
393
394     TRACE("(%p)->(%p)\n", This, p);
395
396     nsAString_Init(&alink_str, NULL);
397     nsres = nsIDOMHTMLBodyElement_GetALink(This->nsbody, &alink_str);
398     if(NS_FAILED(nsres))
399         ERR("GetALink failed: %08x\n", nsres);
400
401     nscolor_to_variant(&alink_str, p);
402     nsAString_Finish(&alink_str);
403
404     return S_OK;
405 }
406
407 static HRESULT WINAPI HTMLBodyElement_put_onload(IHTMLBodyElement *iface, VARIANT v)
408 {
409     HTMLBodyElement *This = HTMLBODY_THIS(iface);
410     FIXME("(%p)->()\n", This);
411     return E_NOTIMPL;
412 }
413
414 static HRESULT WINAPI HTMLBodyElement_get_onload(IHTMLBodyElement *iface, VARIANT *p)
415 {
416     HTMLBodyElement *This = HTMLBODY_THIS(iface);
417     FIXME("(%p)->(%p)\n", This, p);
418     return E_NOTIMPL;
419 }
420
421 static HRESULT WINAPI HTMLBodyElement_put_onunload(IHTMLBodyElement *iface, VARIANT v)
422 {
423     HTMLBodyElement *This = HTMLBODY_THIS(iface);
424     FIXME("(%p)->()\n", This);
425     return E_NOTIMPL;
426 }
427
428 static HRESULT WINAPI HTMLBodyElement_get_onunload(IHTMLBodyElement *iface, VARIANT *p)
429 {
430     HTMLBodyElement *This = HTMLBODY_THIS(iface);
431     FIXME("(%p)->(%p)\n", This, p);
432     return E_NOTIMPL;
433 }
434
435 static HRESULT WINAPI HTMLBodyElement_put_scroll(IHTMLBodyElement *iface, BSTR v)
436 {
437     HTMLBodyElement *This = HTMLBODY_THIS(iface);
438     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
439     return E_NOTIMPL;
440 }
441
442 static HRESULT WINAPI HTMLBodyElement_get_scroll(IHTMLBodyElement *iface, BSTR *p)
443 {
444     HTMLBodyElement *This = HTMLBODY_THIS(iface);
445     FIXME("(%p)->(%p)\n", This, p);
446     return E_NOTIMPL;
447 }
448
449 static HRESULT WINAPI HTMLBodyElement_put_onselect(IHTMLBodyElement *iface, VARIANT v)
450 {
451     HTMLBodyElement *This = HTMLBODY_THIS(iface);
452     FIXME("(%p)->()\n", This);
453     return E_NOTIMPL;
454 }
455
456 static HRESULT WINAPI HTMLBodyElement_get_onselect(IHTMLBodyElement *iface, VARIANT *p)
457 {
458     HTMLBodyElement *This = HTMLBODY_THIS(iface);
459     FIXME("(%p)->(%p)\n", This, p);
460     return E_NOTIMPL;
461 }
462
463 static HRESULT WINAPI HTMLBodyElement_put_onbeforeunload(IHTMLBodyElement *iface, VARIANT v)
464 {
465     HTMLBodyElement *This = HTMLBODY_THIS(iface);
466     FIXME("(%p)->()\n", This);
467     return E_NOTIMPL;
468 }
469
470 static HRESULT WINAPI HTMLBodyElement_get_onbeforeunload(IHTMLBodyElement *iface, VARIANT *p)
471 {
472     HTMLBodyElement *This = HTMLBODY_THIS(iface);
473     FIXME("(%p)->(%p)\n", This, p);
474     return E_NOTIMPL;
475 }
476
477 static HRESULT WINAPI HTMLBodyElement_createTextRange(IHTMLBodyElement *iface, IHTMLTxtRange **range)
478 {
479     HTMLBodyElement *This = HTMLBODY_THIS(iface);
480     nsIDOMRange *nsrange = NULL;
481
482     TRACE("(%p)->(%p)\n", This, range);
483
484     if(This->textcont.element.node.doc->nscontainer) {
485         nsIDOMDocument *nsdoc;
486         nsIDOMDocumentRange *nsdocrange;
487         nsresult nsres;
488
489         nsIWebNavigation_GetDocument(This->textcont.element.node.doc->nscontainer->navigation, &nsdoc);
490         nsIDOMDocument_QueryInterface(nsdoc, &IID_nsIDOMDocumentRange, (void**)&nsdocrange);
491         nsIDOMDocument_Release(nsdoc);
492
493         nsres = nsIDOMDocumentRange_CreateRange(nsdocrange, &nsrange);
494         if(NS_SUCCEEDED(nsres)) {
495             nsres = nsIDOMRange_SelectNodeContents(nsrange, This->textcont.element.node.nsnode);
496             if(NS_FAILED(nsres))
497                 ERR("SelectNodeContents failed: %08x\n", nsres);
498         }else {
499             ERR("CreateRange failed: %08x\n", nsres);
500         }
501
502         nsIDOMDocumentRange_Release(nsdocrange);
503     }
504
505     *range = HTMLTxtRange_Create(This->textcont.element.node.doc, nsrange);
506     return S_OK;
507 }
508
509 #undef HTMLBODY_THIS
510
511 static const IHTMLBodyElementVtbl HTMLBodyElementVtbl = {
512     HTMLBodyElement_QueryInterface,
513     HTMLBodyElement_AddRef,
514     HTMLBodyElement_Release,
515     HTMLBodyElement_GetTypeInfoCount,
516     HTMLBodyElement_GetTypeInfo,
517     HTMLBodyElement_GetIDsOfNames,
518     HTMLBodyElement_Invoke,
519     HTMLBodyElement_put_background,
520     HTMLBodyElement_get_background,
521     HTMLBodyElement_put_bgProperties,
522     HTMLBodyElement_get_bgProperties,
523     HTMLBodyElement_put_leftMargin,
524     HTMLBodyElement_get_leftMargin,
525     HTMLBodyElement_put_topMargin,
526     HTMLBodyElement_get_topMargin,
527     HTMLBodyElement_put_rightMargin,
528     HTMLBodyElement_get_rightMargin,
529     HTMLBodyElement_put_bottomMargin,
530     HTMLBodyElement_get_bottomMargin,
531     HTMLBodyElement_put_noWrap,
532     HTMLBodyElement_get_noWrap,
533     HTMLBodyElement_put_bgColor,
534     HTMLBodyElement_get_bgColor,
535     HTMLBodyElement_put_text,
536     HTMLBodyElement_get_text,
537     HTMLBodyElement_put_link,
538     HTMLBodyElement_get_link,
539     HTMLBodyElement_put_vLink,
540     HTMLBodyElement_get_vLink,
541     HTMLBodyElement_put_aLink,
542     HTMLBodyElement_get_aLink,
543     HTMLBodyElement_put_onload,
544     HTMLBodyElement_get_onload,
545     HTMLBodyElement_put_onunload,
546     HTMLBodyElement_get_onunload,
547     HTMLBodyElement_put_scroll,
548     HTMLBodyElement_get_scroll,
549     HTMLBodyElement_put_onselect,
550     HTMLBodyElement_get_onselect,
551     HTMLBodyElement_put_onbeforeunload,
552     HTMLBodyElement_get_onbeforeunload,
553     HTMLBodyElement_createTextRange
554 };
555
556 #define HTMLBODY_NODE_THIS(iface) DEFINE_THIS2(HTMLBodyElement, textcont.element.node, iface)
557
558 static HRESULT HTMLBodyElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
559 {
560     HTMLBodyElement *This = HTMLBODY_NODE_THIS(iface);
561
562     *ppv = NULL;
563
564     if(IsEqualGUID(&IID_IUnknown, riid)) {
565         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
566         *ppv = HTMLBODY(This);
567     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
568         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
569         *ppv = HTMLBODY(This);
570     }else if(IsEqualGUID(&IID_IHTMLBodyElement, riid)) {
571         TRACE("(%p)->(IID_IHTMLBodyElement %p)\n", This, ppv);
572         *ppv = HTMLBODY(This);
573     }else if(IsEqualGUID(&IID_IHTMLTextContainer, riid)) {
574         TRACE("(%p)->(IID_IHTMLTextContainer %p)\n", &This->textcont, ppv);
575         *ppv = HTMLTEXTCONT(&This->textcont);
576     }
577
578     if(*ppv) {
579         IUnknown_AddRef((IUnknown*)*ppv);
580         return S_OK;
581     }
582
583     return HTMLElement_QI(&This->textcont.element.node, riid, ppv);
584 }
585
586 static void HTMLBodyElement_destructor(HTMLDOMNode *iface)
587 {
588     HTMLBodyElement *This = HTMLBODY_NODE_THIS(iface);
589
590     nsIDOMHTMLBodyElement_Release(This->nsbody);
591
592     HTMLElement_destructor(&This->textcont.element.node);
593 }
594
595 #undef HTMLBODY_NODE_THIS
596
597 static const NodeImplVtbl HTMLBodyElementImplVtbl = {
598     HTMLBodyElement_QI,
599     HTMLBodyElement_destructor
600 };
601
602 HTMLElement *HTMLBodyElement_Create(nsIDOMHTMLElement *nselem)
603 {
604     HTMLBodyElement *ret = heap_alloc(sizeof(HTMLBodyElement));
605     nsresult nsres;
606
607     TRACE("(%p)->(%p)\n", ret, nselem);
608
609     HTMLTextContainer_Init(&ret->textcont);
610
611     ret->lpHTMLBodyElementVtbl = &HTMLBodyElementVtbl;
612     ret->textcont.element.node.vtbl = &HTMLBodyElementImplVtbl;
613
614     ConnectionPoint_Init(&ret->cp_propnotif, &ret->textcont.element.cp_container, &IID_IPropertyNotifySink);
615
616     nsres = nsIDOMHTMLElement_QueryInterface(nselem, &IID_nsIDOMHTMLBodyElement,
617                                              (void**)&ret->nsbody);
618     if(NS_FAILED(nsres))
619         ERR("Could not get nsDOMHTMLBodyElement: %08x\n", nsres);
620
621     return &ret->textcont.element;
622 }