xref: /reactos/dll/win32/mshtml/htmliframe.c (revision dc0433f0)
1 /*
2  * Copyright 2008 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 "mshtml_private.h"
20 
21 typedef struct {
22     HTMLFrameBase framebase;
23     IHTMLIFrameElement IHTMLIFrameElement_iface;
24     IHTMLIFrameElement2 IHTMLIFrameElement2_iface;
25     IHTMLIFrameElement3 IHTMLIFrameElement3_iface;
26 } HTMLIFrame;
27 
28 static inline HTMLIFrame *impl_from_IHTMLIFrameElement(IHTMLIFrameElement *iface)
29 {
30     return CONTAINING_RECORD(iface, HTMLIFrame, IHTMLIFrameElement_iface);
31 }
32 
33 static HRESULT WINAPI HTMLIFrameElement_QueryInterface(IHTMLIFrameElement *iface,
34         REFIID riid, void **ppv)
35 {
36     HTMLIFrame *This = impl_from_IHTMLIFrameElement(iface);
37 
38     return IHTMLDOMNode_QueryInterface(&This->framebase.element.node.IHTMLDOMNode_iface, riid, ppv);
39 }
40 
41 static ULONG WINAPI HTMLIFrameElement_AddRef(IHTMLIFrameElement *iface)
42 {
43     HTMLIFrame *This = impl_from_IHTMLIFrameElement(iface);
44 
45     return IHTMLDOMNode_AddRef(&This->framebase.element.node.IHTMLDOMNode_iface);
46 }
47 
48 static ULONG WINAPI HTMLIFrameElement_Release(IHTMLIFrameElement *iface)
49 {
50     HTMLIFrame *This = impl_from_IHTMLIFrameElement(iface);
51 
52     return IHTMLDOMNode_Release(&This->framebase.element.node.IHTMLDOMNode_iface);
53 }
54 
55 static HRESULT WINAPI HTMLIFrameElement_GetTypeInfoCount(IHTMLIFrameElement *iface, UINT *pctinfo)
56 {
57     HTMLIFrame *This = impl_from_IHTMLIFrameElement(iface);
58     return IDispatchEx_GetTypeInfoCount(&This->framebase.element.node.event_target.dispex.IDispatchEx_iface,
59             pctinfo);
60 }
61 
62 static HRESULT WINAPI HTMLIFrameElement_GetTypeInfo(IHTMLIFrameElement *iface, UINT iTInfo,
63         LCID lcid, ITypeInfo **ppTInfo)
64 {
65     HTMLIFrame *This = impl_from_IHTMLIFrameElement(iface);
66     return IDispatchEx_GetTypeInfo(&This->framebase.element.node.event_target.dispex.IDispatchEx_iface, iTInfo,
67             lcid, ppTInfo);
68 }
69 
70 static HRESULT WINAPI HTMLIFrameElement_GetIDsOfNames(IHTMLIFrameElement *iface, REFIID riid,
71         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
72 {
73     HTMLIFrame *This = impl_from_IHTMLIFrameElement(iface);
74     return IDispatchEx_GetIDsOfNames(&This->framebase.element.node.event_target.dispex.IDispatchEx_iface, riid,
75             rgszNames, cNames, lcid, rgDispId);
76 }
77 
78 static HRESULT WINAPI HTMLIFrameElement_Invoke(IHTMLIFrameElement *iface, DISPID dispIdMember,
79         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
80         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
81 {
82     HTMLIFrame *This = impl_from_IHTMLIFrameElement(iface);
83     return IDispatchEx_Invoke(&This->framebase.element.node.event_target.dispex.IDispatchEx_iface, dispIdMember,
84             riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
85 }
86 
87 static HRESULT WINAPI HTMLIFrameElement_put_vspace(IHTMLIFrameElement *iface, LONG v)
88 {
89     HTMLIFrame *This = impl_from_IHTMLIFrameElement(iface);
90     FIXME("(%p)->(%d)\n", This, v);
91     return E_NOTIMPL;
92 }
93 
94 static HRESULT WINAPI HTMLIFrameElement_get_vspace(IHTMLIFrameElement *iface, LONG *p)
95 {
96     HTMLIFrame *This = impl_from_IHTMLIFrameElement(iface);
97     FIXME("(%p)->(%p)\n", This, p);
98     return E_NOTIMPL;
99 }
100 
101 static HRESULT WINAPI HTMLIFrameElement_put_hspace(IHTMLIFrameElement *iface, LONG v)
102 {
103     HTMLIFrame *This = impl_from_IHTMLIFrameElement(iface);
104     FIXME("(%p)->(%d)\n", This, v);
105     return E_NOTIMPL;
106 }
107 
108 static HRESULT WINAPI HTMLIFrameElement_get_hspace(IHTMLIFrameElement *iface, LONG *p)
109 {
110     HTMLIFrame *This = impl_from_IHTMLIFrameElement(iface);
111     FIXME("(%p)->(%p)\n", This, p);
112     return E_NOTIMPL;
113 }
114 
115 static HRESULT WINAPI HTMLIFrameElement_put_align(IHTMLIFrameElement *iface, BSTR v)
116 {
117     HTMLIFrame *This = impl_from_IHTMLIFrameElement(iface);
118     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
119     return E_NOTIMPL;
120 }
121 
122 static HRESULT WINAPI HTMLIFrameElement_get_align(IHTMLIFrameElement *iface, BSTR *p)
123 {
124     HTMLIFrame *This = impl_from_IHTMLIFrameElement(iface);
125     FIXME("(%p)->(%p)\n", This, p);
126     return E_NOTIMPL;
127 }
128 
129 static const IHTMLIFrameElementVtbl HTMLIFrameElementVtbl = {
130     HTMLIFrameElement_QueryInterface,
131     HTMLIFrameElement_AddRef,
132     HTMLIFrameElement_Release,
133     HTMLIFrameElement_GetTypeInfoCount,
134     HTMLIFrameElement_GetTypeInfo,
135     HTMLIFrameElement_GetIDsOfNames,
136     HTMLIFrameElement_Invoke,
137     HTMLIFrameElement_put_vspace,
138     HTMLIFrameElement_get_vspace,
139     HTMLIFrameElement_put_hspace,
140     HTMLIFrameElement_get_hspace,
141     HTMLIFrameElement_put_align,
142     HTMLIFrameElement_get_align
143 };
144 
145 static inline HTMLIFrame *impl_from_IHTMLIFrameElement2(IHTMLIFrameElement2 *iface)
146 {
147     return CONTAINING_RECORD(iface, HTMLIFrame, IHTMLIFrameElement2_iface);
148 }
149 
150 static HRESULT WINAPI HTMLIFrameElement2_QueryInterface(IHTMLIFrameElement2 *iface,
151         REFIID riid, void **ppv)
152 {
153     HTMLIFrame *This = impl_from_IHTMLIFrameElement2(iface);
154 
155     return IHTMLDOMNode_QueryInterface(&This->framebase.element.node.IHTMLDOMNode_iface, riid, ppv);
156 }
157 
158 static ULONG WINAPI HTMLIFrameElement2_AddRef(IHTMLIFrameElement2 *iface)
159 {
160     HTMLIFrame *This = impl_from_IHTMLIFrameElement2(iface);
161 
162     return IHTMLDOMNode_AddRef(&This->framebase.element.node.IHTMLDOMNode_iface);
163 }
164 
165 static ULONG WINAPI HTMLIFrameElement2_Release(IHTMLIFrameElement2 *iface)
166 {
167     HTMLIFrame *This = impl_from_IHTMLIFrameElement2(iface);
168 
169     return IHTMLDOMNode_Release(&This->framebase.element.node.IHTMLDOMNode_iface);
170 }
171 
172 static HRESULT WINAPI HTMLIFrameElement2_GetTypeInfoCount(IHTMLIFrameElement2 *iface, UINT *pctinfo)
173 {
174     HTMLIFrame *This = impl_from_IHTMLIFrameElement2(iface);
175     return IDispatchEx_GetTypeInfoCount(&This->framebase.element.node.event_target.dispex.IDispatchEx_iface,
176             pctinfo);
177 }
178 
179 static HRESULT WINAPI HTMLIFrameElement2_GetTypeInfo(IHTMLIFrameElement2 *iface, UINT iTInfo,
180         LCID lcid, ITypeInfo **ppTInfo)
181 {
182     HTMLIFrame *This = impl_from_IHTMLIFrameElement2(iface);
183     return IDispatchEx_GetTypeInfo(&This->framebase.element.node.event_target.dispex.IDispatchEx_iface, iTInfo,
184             lcid, ppTInfo);
185 }
186 
187 static HRESULT WINAPI HTMLIFrameElement2_GetIDsOfNames(IHTMLIFrameElement2 *iface, REFIID riid,
188         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
189 {
190     HTMLIFrame *This = impl_from_IHTMLIFrameElement2(iface);
191     return IDispatchEx_GetIDsOfNames(&This->framebase.element.node.event_target.dispex.IDispatchEx_iface, riid,
192             rgszNames, cNames, lcid, rgDispId);
193 }
194 
195 static HRESULT WINAPI HTMLIFrameElement2_Invoke(IHTMLIFrameElement2 *iface, DISPID dispIdMember,
196         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
197         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
198 {
199     HTMLIFrame *This = impl_from_IHTMLIFrameElement2(iface);
200     return IDispatchEx_Invoke(&This->framebase.element.node.event_target.dispex.IDispatchEx_iface, dispIdMember,
201             riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
202 }
203 
204 static HRESULT WINAPI HTMLIFrameElement2_put_height(IHTMLIFrameElement2 *iface, VARIANT v)
205 {
206     HTMLIFrame *This = impl_from_IHTMLIFrameElement2(iface);
207     nsAString nsstr;
208     nsresult nsres;
209 
210     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
211 
212     if(V_VT(&v) != VT_BSTR) {
213         FIXME("Unsupported %s\n", debugstr_variant(&v));
214         return E_NOTIMPL;
215     }
216 
217     nsAString_InitDepend(&nsstr, V_BSTR(&v));
218     nsres = nsIDOMHTMLIFrameElement_SetHeight(This->framebase.nsiframe, &nsstr);
219     nsAString_Finish(&nsstr);
220     if(NS_FAILED(nsres)) {
221         ERR("SetHeight failed: %08x\n", nsres);
222         return E_FAIL;
223     }
224 
225     return S_OK;
226 }
227 
228 static HRESULT WINAPI HTMLIFrameElement2_get_height(IHTMLIFrameElement2 *iface, VARIANT *p)
229 {
230     HTMLIFrame *This = impl_from_IHTMLIFrameElement2(iface);
231     nsAString nsstr;
232     nsresult nsres;
233 
234     TRACE("(%p)->(%p)\n", This, p);
235 
236     nsAString_Init(&nsstr, NULL);
237     nsres = nsIDOMHTMLIFrameElement_GetHeight(This->framebase.nsiframe, &nsstr);
238 
239     V_VT(p) = VT_BSTR;
240     return return_nsstr(nsres, &nsstr, &V_BSTR(p));
241 }
242 
243 static HRESULT WINAPI HTMLIFrameElement2_put_width(IHTMLIFrameElement2 *iface, VARIANT v)
244 {
245     HTMLIFrame *This = impl_from_IHTMLIFrameElement2(iface);
246     nsAString nsstr;
247     nsresult nsres;
248 
249     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
250 
251     if(V_VT(&v) != VT_BSTR) {
252         FIXME("Unsupported %s\n", debugstr_variant(&v));
253         return E_NOTIMPL;
254     }
255 
256     nsAString_InitDepend(&nsstr, V_BSTR(&v));
257     nsres = nsIDOMHTMLIFrameElement_SetWidth(This->framebase.nsiframe, &nsstr);
258     nsAString_Finish(&nsstr);
259     if(NS_FAILED(nsres)) {
260         ERR("SetWidth failed: %08x\n", nsres);
261         return E_FAIL;
262     }
263 
264     return S_OK;
265 }
266 
267 static HRESULT WINAPI HTMLIFrameElement2_get_width(IHTMLIFrameElement2 *iface, VARIANT *p)
268 {
269     HTMLIFrame *This = impl_from_IHTMLIFrameElement2(iface);
270     nsAString nsstr;
271     nsresult nsres;
272 
273     TRACE("(%p)->(%p)\n", This, p);
274 
275     nsAString_Init(&nsstr, NULL);
276     nsres = nsIDOMHTMLIFrameElement_GetWidth(This->framebase.nsiframe, &nsstr);
277 
278     V_VT(p) = VT_BSTR;
279     return return_nsstr(nsres, &nsstr, &V_BSTR(p));
280 }
281 
282 static const IHTMLIFrameElement2Vtbl HTMLIFrameElement2Vtbl = {
283     HTMLIFrameElement2_QueryInterface,
284     HTMLIFrameElement2_AddRef,
285     HTMLIFrameElement2_Release,
286     HTMLIFrameElement2_GetTypeInfoCount,
287     HTMLIFrameElement2_GetTypeInfo,
288     HTMLIFrameElement2_GetIDsOfNames,
289     HTMLIFrameElement2_Invoke,
290     HTMLIFrameElement2_put_height,
291     HTMLIFrameElement2_get_height,
292     HTMLIFrameElement2_put_width,
293     HTMLIFrameElement2_get_width
294 };
295 
296 static inline HTMLIFrame *impl_from_IHTMLIFrameElement3(IHTMLIFrameElement3 *iface)
297 {
298     return CONTAINING_RECORD(iface, HTMLIFrame, IHTMLIFrameElement3_iface);
299 }
300 
301 static HRESULT WINAPI HTMLIFrameElement3_QueryInterface(IHTMLIFrameElement3 *iface,
302         REFIID riid, void **ppv)
303 {
304     HTMLIFrame *This = impl_from_IHTMLIFrameElement3(iface);
305 
306     return IHTMLDOMNode_QueryInterface(&This->framebase.element.node.IHTMLDOMNode_iface, riid, ppv);
307 }
308 
309 static ULONG WINAPI HTMLIFrameElement3_AddRef(IHTMLIFrameElement3 *iface)
310 {
311     HTMLIFrame *This = impl_from_IHTMLIFrameElement3(iface);
312 
313     return IHTMLDOMNode_AddRef(&This->framebase.element.node.IHTMLDOMNode_iface);
314 }
315 
316 static ULONG WINAPI HTMLIFrameElement3_Release(IHTMLIFrameElement3 *iface)
317 {
318     HTMLIFrame *This = impl_from_IHTMLIFrameElement3(iface);
319 
320     return IHTMLDOMNode_Release(&This->framebase.element.node.IHTMLDOMNode_iface);
321 }
322 
323 static HRESULT WINAPI HTMLIFrameElement3_GetTypeInfoCount(IHTMLIFrameElement3 *iface, UINT *pctinfo)
324 {
325     HTMLIFrame *This = impl_from_IHTMLIFrameElement3(iface);
326     return IDispatchEx_GetTypeInfoCount(&This->framebase.element.node.event_target.dispex.IDispatchEx_iface,
327             pctinfo);
328 }
329 
330 static HRESULT WINAPI HTMLIFrameElement3_GetTypeInfo(IHTMLIFrameElement3 *iface, UINT iTInfo,
331         LCID lcid, ITypeInfo **ppTInfo)
332 {
333     HTMLIFrame *This = impl_from_IHTMLIFrameElement3(iface);
334     return IDispatchEx_GetTypeInfo(&This->framebase.element.node.event_target.dispex.IDispatchEx_iface, iTInfo,
335             lcid, ppTInfo);
336 }
337 
338 static HRESULT WINAPI HTMLIFrameElement3_GetIDsOfNames(IHTMLIFrameElement3 *iface, REFIID riid,
339         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
340 {
341     HTMLIFrame *This = impl_from_IHTMLIFrameElement3(iface);
342     return IDispatchEx_GetIDsOfNames(&This->framebase.element.node.event_target.dispex.IDispatchEx_iface, riid,
343             rgszNames, cNames, lcid, rgDispId);
344 }
345 
346 static HRESULT WINAPI HTMLIFrameElement3_Invoke(IHTMLIFrameElement3 *iface, DISPID dispIdMember,
347         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
348         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
349 {
350     HTMLIFrame *This = impl_from_IHTMLIFrameElement3(iface);
351     return IDispatchEx_Invoke(&This->framebase.element.node.event_target.dispex.IDispatchEx_iface, dispIdMember,
352             riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
353 }
354 
355 static HRESULT WINAPI HTMLIFrameElement3_get_contentDocument(IHTMLIFrameElement3 *iface, IDispatch **p)
356 {
357     HTMLIFrame *This = impl_from_IHTMLIFrameElement3(iface);
358     IHTMLDocument2 *doc;
359     HRESULT hres;
360 
361     TRACE("(%p)->(%p)\n", This, p);
362 
363     if(!This->framebase.content_window) {
364         *p = NULL;
365         return S_OK;
366     }
367 
368     hres = IHTMLWindow2_get_document(&This->framebase.content_window->base.IHTMLWindow2_iface, &doc);
369     *p = (IDispatch*)doc;
370     return hres;
371 }
372 
373 static HRESULT WINAPI HTMLIFrameElement3_put_src(IHTMLIFrameElement3 *iface, BSTR v)
374 {
375     HTMLIFrame *This = impl_from_IHTMLIFrameElement3(iface);
376     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
377     return E_NOTIMPL;
378 }
379 
380 static HRESULT WINAPI HTMLIFrameElement3_get_src(IHTMLIFrameElement3 *iface, BSTR *p)
381 {
382     HTMLIFrame *This = impl_from_IHTMLIFrameElement3(iface);
383     FIXME("(%p)->(%p)\n", This, p);
384     return E_NOTIMPL;
385 }
386 
387 static HRESULT WINAPI HTMLIFrameElement3_put_longDesc(IHTMLIFrameElement3 *iface, BSTR v)
388 {
389     HTMLIFrame *This = impl_from_IHTMLIFrameElement3(iface);
390     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
391     return E_NOTIMPL;
392 }
393 
394 static HRESULT WINAPI HTMLIFrameElement3_get_longDesc(IHTMLIFrameElement3 *iface, BSTR *p)
395 {
396     HTMLIFrame *This = impl_from_IHTMLIFrameElement3(iface);
397     FIXME("(%p)->(%p)\n", This, p);
398     return E_NOTIMPL;
399 }
400 
401 static HRESULT WINAPI HTMLIFrameElement3_put_frameBorder(IHTMLIFrameElement3 *iface, BSTR v)
402 {
403     HTMLIFrame *This = impl_from_IHTMLIFrameElement3(iface);
404     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
405     return E_NOTIMPL;
406 }
407 
408 static HRESULT WINAPI HTMLIFrameElement3_get_frameBorder(IHTMLIFrameElement3 *iface, BSTR *p)
409 {
410     HTMLIFrame *This = impl_from_IHTMLIFrameElement3(iface);
411     FIXME("(%p)->(%p)\n", This, p);
412     return E_NOTIMPL;
413 }
414 
415 static const IHTMLIFrameElement3Vtbl HTMLIFrameElement3Vtbl = {
416     HTMLIFrameElement3_QueryInterface,
417     HTMLIFrameElement3_AddRef,
418     HTMLIFrameElement3_Release,
419     HTMLIFrameElement3_GetTypeInfoCount,
420     HTMLIFrameElement3_GetTypeInfo,
421     HTMLIFrameElement3_GetIDsOfNames,
422     HTMLIFrameElement3_Invoke,
423     HTMLIFrameElement3_get_contentDocument,
424     HTMLIFrameElement3_put_src,
425     HTMLIFrameElement3_get_src,
426     HTMLIFrameElement3_put_longDesc,
427     HTMLIFrameElement3_get_longDesc,
428     HTMLIFrameElement3_put_frameBorder,
429     HTMLIFrameElement3_get_frameBorder
430 };
431 
432 static inline HTMLIFrame *impl_from_HTMLDOMNode(HTMLDOMNode *iface)
433 {
434     return CONTAINING_RECORD(iface, HTMLIFrame, framebase.element.node);
435 }
436 
437 static HRESULT HTMLIFrame_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
438 {
439     HTMLIFrame *This = impl_from_HTMLDOMNode(iface);
440 
441     if(IsEqualGUID(&IID_IHTMLIFrameElement, riid)) {
442         TRACE("(%p)->(IID_IHTMLIFrameElement %p)\n", This, ppv);
443         *ppv = &This->IHTMLIFrameElement_iface;
444     }else if(IsEqualGUID(&IID_IHTMLIFrameElement2, riid)) {
445         TRACE("(%p)->(IID_IHTMLIFrameElement2 %p)\n", This, ppv);
446         *ppv = &This->IHTMLIFrameElement2_iface;
447     }else if(IsEqualGUID(&IID_IHTMLIFrameElement3, riid)) {
448         TRACE("(%p)->(IID_IHTMLIFrameElement3 %p)\n", This, ppv);
449         *ppv = &This->IHTMLIFrameElement3_iface;
450     }else {
451         return HTMLFrameBase_QI(&This->framebase, riid, ppv);
452     }
453 
454     IUnknown_AddRef((IUnknown*)*ppv);
455     return S_OK;
456 }
457 
458 static void HTMLIFrame_destructor(HTMLDOMNode *iface)
459 {
460     HTMLIFrame *This = impl_from_HTMLDOMNode(iface);
461 
462     HTMLFrameBase_destructor(&This->framebase);
463 }
464 
465 static HRESULT HTMLIFrame_get_document(HTMLDOMNode *iface, IDispatch **p)
466 {
467     HTMLIFrame *This = impl_from_HTMLDOMNode(iface);
468 
469     if(!This->framebase.content_window || !This->framebase.content_window->base.inner_window->doc) {
470         *p = NULL;
471         return S_OK;
472     }
473 
474     *p = (IDispatch*)&This->framebase.content_window->base.inner_window->doc->basedoc.IHTMLDocument2_iface;
475     IDispatch_AddRef(*p);
476     return S_OK;
477 }
478 
479 static HRESULT HTMLIFrame_get_dispid(HTMLDOMNode *iface, BSTR name,
480         DWORD grfdex, DISPID *pid)
481 {
482     HTMLIFrame *This = impl_from_HTMLDOMNode(iface);
483 
484     if(!This->framebase.content_window)
485         return DISP_E_UNKNOWNNAME;
486 
487     return search_window_props(This->framebase.content_window->base.inner_window, name, grfdex, pid);
488 }
489 
490 static HRESULT HTMLIFrame_invoke(HTMLDOMNode *iface, DISPID id, LCID lcid,
491         WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
492 {
493     HTMLIFrame *This = impl_from_HTMLDOMNode(iface);
494 
495     if(!This->framebase.content_window) {
496         ERR("no content window to invoke on\n");
497         return E_FAIL;
498     }
499 
500     return IDispatchEx_InvokeEx(&This->framebase.content_window->base.IDispatchEx_iface, id, lcid,
501             flags, params, res, ei, caller);
502 }
503 
504 static HRESULT HTMLIFrame_get_readystate(HTMLDOMNode *iface, BSTR *p)
505 {
506     HTMLIFrame *This = impl_from_HTMLDOMNode(iface);
507 
508     return IHTMLFrameBase2_get_readyState(&This->framebase.IHTMLFrameBase2_iface, p);
509 }
510 
511 static HRESULT HTMLIFrame_bind_to_tree(HTMLDOMNode *iface)
512 {
513     HTMLIFrame *This = impl_from_HTMLDOMNode(iface);
514     nsIDOMDocument *nsdoc;
515     nsresult nsres;
516     HRESULT hres;
517 
518     nsres = nsIDOMHTMLIFrameElement_GetContentDocument(This->framebase.nsiframe, &nsdoc);
519     if(NS_FAILED(nsres) || !nsdoc) {
520         ERR("GetContentDocument failed: %08x\n", nsres);
521         return E_FAIL;
522     }
523 
524     hres = set_frame_doc(&This->framebase, nsdoc);
525     nsIDOMDocument_Release(nsdoc);
526     return hres;
527 }
528 
529 static void HTMLIFrame_traverse(HTMLDOMNode *iface, nsCycleCollectionTraversalCallback *cb)
530 {
531     HTMLIFrame *This = impl_from_HTMLDOMNode(iface);
532 
533     if(This->framebase.nsiframe)
534         note_cc_edge((nsISupports*)This->framebase.nsiframe, "This->nsiframe", cb);
535 }
536 
537 static void HTMLIFrame_unlink(HTMLDOMNode *iface)
538 {
539     HTMLIFrame *This = impl_from_HTMLDOMNode(iface);
540 
541     if(This->framebase.nsiframe) {
542         nsIDOMHTMLIFrameElement *nsiframe = This->framebase.nsiframe;
543 
544         This->framebase.nsiframe = NULL;
545         nsIDOMHTMLIFrameElement_Release(nsiframe);
546     }
547 }
548 
549 static const NodeImplVtbl HTMLIFrameImplVtbl = {
550     HTMLIFrame_QI,
551     HTMLIFrame_destructor,
552     HTMLElement_cpc,
553     HTMLElement_clone,
554     HTMLElement_handle_event,
555     HTMLElement_get_attr_col,
556     NULL,
557     NULL,
558     NULL,
559     NULL,
560     HTMLIFrame_get_document,
561     HTMLIFrame_get_readystate,
562     HTMLIFrame_get_dispid,
563     HTMLIFrame_invoke,
564     HTMLIFrame_bind_to_tree,
565     HTMLIFrame_traverse,
566     HTMLIFrame_unlink
567 };
568 
569 static const tid_t HTMLIFrame_iface_tids[] = {
570     HTMLELEMENT_TIDS,
571     IHTMLFrameBase_tid,
572     IHTMLFrameBase2_tid,
573     IHTMLIFrameElement_tid,
574     IHTMLIFrameElement2_tid,
575     IHTMLIFrameElement3_tid,
576     0
577 };
578 
579 static dispex_static_data_t HTMLIFrame_dispex = {
580     NULL,
581     DispHTMLIFrame_tid,
582     NULL,
583     HTMLIFrame_iface_tids
584 };
585 
586 HRESULT HTMLIFrame_Create(HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, HTMLElement **elem)
587 {
588     HTMLIFrame *ret;
589 
590     ret = heap_alloc_zero(sizeof(HTMLIFrame));
591     if(!ret)
592         return E_OUTOFMEMORY;
593 
594     ret->IHTMLIFrameElement_iface.lpVtbl = &HTMLIFrameElementVtbl;
595     ret->IHTMLIFrameElement2_iface.lpVtbl = &HTMLIFrameElement2Vtbl;
596     ret->IHTMLIFrameElement3_iface.lpVtbl = &HTMLIFrameElement3Vtbl;
597     ret->framebase.element.node.vtbl = &HTMLIFrameImplVtbl;
598 
599     HTMLFrameBase_Init(&ret->framebase, doc, nselem, &HTMLIFrame_dispex);
600 
601     *elem = &ret->framebase.element;
602     return S_OK;
603 }
604