mshtml: Fix a typo and remove a space before a '\n' in a FIXME() trace.
[wine] / dlls / mshtml / pluginhost.c
1 /*
2  * Copyright 2010 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
23 #define COBJMACROS
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "ole2.h"
29 #include "shlobj.h"
30
31 #include "mshtml_private.h"
32 #include "pluginhost.h"
33
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
38
39 const IID IID_HTMLPluginContainer =
40     {0xbd7a6050,0xb373,0x4f6f,{0xa4,0x93,0xdd,0x40,0xc5,0x23,0xa8,0x6a}};
41
42 static BOOL check_load_safety(PluginHost *host)
43 {
44     DWORD policy_size, policy;
45     struct CONFIRMSAFETY cs;
46     BYTE *ppolicy;
47     HRESULT hres;
48
49     cs.clsid = host->clsid;
50     cs.pUnk = host->plugin_unk;
51     cs.dwFlags = CONFIRMSAFETYACTION_LOADOBJECT;
52
53     hres = IInternetHostSecurityManager_QueryCustomPolicy(HOSTSECMGR(host->doc),
54             &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
55     if(FAILED(hres))
56         return FALSE;
57
58     policy = *(DWORD*)ppolicy;
59     CoTaskMemFree(ppolicy);
60     return policy == URLPOLICY_ALLOW;
61 }
62
63 static void update_readystate(PluginHost *host)
64 {
65     DISPPARAMS params = {NULL,NULL,0,0};
66     IDispatchEx *dispex;
67     IDispatch *disp;
68     ULONG err = 0;
69     VARIANT v;
70     HRESULT hres;
71
72     hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatchEx, (void**)&dispex);
73     if(SUCCEEDED(hres)) {
74         FIXME("Use IDispatchEx\n");
75         IDispatchEx_Release(dispex);
76     }
77
78     hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatch, (void**)&disp);
79     if(FAILED(hres))
80         return;
81
82     hres = IDispatch_Invoke(disp, DISPID_READYSTATE, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, &v, NULL, &err);
83     IDispatch_Release(disp);
84     if(SUCCEEDED(hres)) {
85         /* FIXME: make plugin readystate affect document readystate */
86         TRACE("readystate = %s\n", debugstr_variant(&v));
87         VariantClear(&v);
88     }
89 }
90
91 static void load_prop_bag(PluginHost *host, IPersistPropertyBag *persist_prop_bag)
92 {
93     IPropertyBag *prop_bag;
94     HRESULT hres;
95
96     hres = create_param_prop_bag(host->element->element.nselem, &prop_bag);
97     if(FAILED(hres))
98         return;
99
100     if(prop_bag && !check_load_safety(host)) {
101         IPropertyBag_Release(prop_bag);
102         prop_bag = NULL;
103     }
104
105     if(prop_bag) {
106         hres = IPersistPropertyBag_Load(persist_prop_bag, prop_bag, NULL);
107         IPropertyBag_Release(prop_bag);
108         if(FAILED(hres))
109             WARN("Load failed: %08x\n", hres);
110     }else {
111         hres = IPersistPropertyBag_InitNew(persist_prop_bag);
112         if(FAILED(hres))
113             WARN("InitNew failed: %08x\n", hres);
114     }
115 }
116
117 static void load_plugin(PluginHost *host)
118 {
119     IPersistPropertyBag2 *persist_prop_bag2;
120     IPersistPropertyBag *persist_prop_bag;
121     HRESULT hres;
122
123     hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IPersistPropertyBag2, (void**)&persist_prop_bag2);
124     if(SUCCEEDED(hres)) {
125         FIXME("Use IPersistPropertyBag2 iface\n");
126         IPersistPropertyBag2_Release(persist_prop_bag2);
127         return;
128     }
129
130     hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IPersistPropertyBag, (void**)&persist_prop_bag);
131     if(SUCCEEDED(hres)) {
132         load_prop_bag(host, persist_prop_bag);
133         IPersistPropertyBag_Release(persist_prop_bag);
134         return;
135     }
136
137     FIXME("No IPersistPropertyBag iface\n");
138 }
139
140 static void activate_plugin(PluginHost *host)
141 {
142     IClientSecurity *client_security;
143     IQuickActivate *quick_activate;
144     HRESULT hres;
145
146     if(!host->plugin_unk)
147         return;
148
149     /* Note native calls QI on plugin for an undocumented IID and CLSID_HTMLDocument */
150
151     /* FIXME: call FreezeEvents(TRUE) */
152
153     hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IClientSecurity, (void**)&client_security);
154     if(SUCCEEDED(hres)) {
155         FIXME("Handle IClientSecurity\n");
156         IClientSecurity_Release(client_security);
157         return;
158     }
159
160     hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IQuickActivate, (void**)&quick_activate);
161     if(SUCCEEDED(hres)) {
162         QACONTAINER container = {sizeof(container)};
163         QACONTROL control = {sizeof(control)};
164
165         container.pClientSite = &host->IOleClientSite_iface;
166         container.dwAmbientFlags = QACONTAINER_SUPPORTSMNEMONICS|QACONTAINER_MESSAGEREFLECT|QACONTAINER_USERMODE;
167         container.pAdviseSink = &host->IAdviseSinkEx_iface;
168         container.pPropertyNotifySink = &host->IPropertyNotifySink_iface;
169
170         hres = IQuickActivate_QuickActivate(quick_activate, &container, &control);
171         if(FAILED(hres))
172             FIXME("QuickActivate failed: %08x\n", hres);
173     }else {
174         FIXME("No IQuickActivate\n");
175         return;
176     }
177
178     load_plugin(host);
179 }
180
181 void update_plugin_window(PluginHost *host, HWND hwnd, const RECT *rect)
182 {
183     if(!hwnd || (host->hwnd && host->hwnd != hwnd)) {
184         FIXME("unhandled hwnd\n");
185         return;
186     }
187
188     if(!host->hwnd) {
189         host->hwnd = hwnd;
190         activate_plugin(host);
191     }
192 }
193
194 static inline PluginHost *impl_from_IOleClientSite(IOleClientSite *iface)
195 {
196     return CONTAINING_RECORD(iface, PluginHost, IOleClientSite_iface);
197 }
198
199 static HRESULT WINAPI PHClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv)
200 {
201     PluginHost *This = impl_from_IOleClientSite(iface);
202
203     if(IsEqualGUID(&IID_IUnknown, riid)) {
204         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
205         *ppv = &This->IOleClientSite_iface;
206     }else if(IsEqualGUID(&IID_IOleClientSite, riid)) {
207         TRACE("(%p)->(IID_IOleClientSite %p)\n", This, ppv);
208         *ppv = &This->IOleClientSite_iface;
209     }else if(IsEqualGUID(&IID_IAdviseSink, riid)) {
210         TRACE("(%p)->(IID_IAdviseSink %p)\n", This, ppv);
211         *ppv = &This->IAdviseSinkEx_iface;
212     }else if(IsEqualGUID(&IID_IAdviseSinkEx, riid)) {
213         TRACE("(%p)->(IID_IAdviseSinkEx %p)\n", This, ppv);
214         *ppv = &This->IAdviseSinkEx_iface;
215     }else if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) {
216         TRACE("(%p)->(IID_IPropertyNotifySink %p)\n", This, ppv);
217         *ppv = &This->IPropertyNotifySink_iface;
218     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
219         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
220         *ppv = &This->IDispatch_iface;
221     }else if(IsEqualGUID(&IID_IOleWindow, riid)) {
222         TRACE("(%p)->(IID_IOleWindow %p)\n", This, ppv);
223         *ppv = &This->IOleInPlaceSiteEx_iface;
224     }else if(IsEqualGUID(&IID_IOleInPlaceSite, riid)) {
225         TRACE("(%p)->(IID_IOleInPlaceSite %p)\n", This, ppv);
226         *ppv = &This->IOleInPlaceSiteEx_iface;
227     }else if(IsEqualGUID(&IID_IOleInPlaceSiteEx, riid)) {
228         TRACE("(%p)->(IID_IOleInPlaceSiteEx %p)\n", This, ppv);
229         *ppv = &This->IOleInPlaceSiteEx_iface;
230     }else if(IsEqualGUID(&IID_IOleControlSite, riid)) {
231         TRACE("(%p)->(IID_IOleControlSite %p)\n", This, ppv);
232         *ppv = &This->IOleControlSite_iface;
233     }else if(IsEqualGUID(&IID_IBindHost, riid)) {
234         TRACE("(%p)->(IID_IBindHost %p)\n", This, ppv);
235         *ppv = &This->IBindHost_iface;
236     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
237         TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
238         *ppv = &This->IServiceProvider_iface;
239     }else {
240         WARN("Unsupported interface %s\n", debugstr_guid(riid));
241         *ppv = NULL;
242         return E_NOINTERFACE;
243     }
244
245     IOleClientSite_AddRef((IUnknown*)*ppv);
246     return S_OK;
247 }
248
249 static ULONG WINAPI PHClientSite_AddRef(IOleClientSite *iface)
250 {
251     PluginHost *This = impl_from_IOleClientSite(iface);
252     LONG ref = InterlockedIncrement(&This->ref);
253
254     TRACE("(%p) ref=%d\n", This, ref);
255
256     return ref;
257 }
258
259 static ULONG WINAPI PHClientSite_Release(IOleClientSite *iface)
260 {
261     PluginHost *This = impl_from_IOleClientSite(iface);
262     LONG ref = InterlockedDecrement(&This->ref);
263
264     TRACE("(%p) ref=%d\n", This, ref);
265
266     if(!ref) {
267         list_remove(&This->entry);
268         if(This->element)
269             This->element->plugin_host = NULL;
270         if(This->plugin_unk)
271             IUnknown_Release(This->plugin_unk);
272         heap_free(This);
273     }
274
275     return ref;
276 }
277
278 static HRESULT WINAPI PHClientSite_SaveObject(IOleClientSite *iface)
279 {
280     PluginHost *This = impl_from_IOleClientSite(iface);
281     FIXME("(%p)\n", This);
282     return E_NOTIMPL;
283 }
284
285 static HRESULT WINAPI PHClientSite_GetMoniker(IOleClientSite *iface, DWORD dwAssign,
286         DWORD dwWhichMoniker, IMoniker **ppmk)
287 {
288     PluginHost *This = impl_from_IOleClientSite(iface);
289
290     TRACE("(%p)->(%d %d %p)\n", This, dwAssign, dwWhichMoniker, ppmk);
291
292     switch(dwWhichMoniker) {
293     case OLEWHICHMK_CONTAINER:
294         if(!This->doc || !This->doc->basedoc.window || !This->doc->basedoc.window->mon) {
295             FIXME("no moniker\n");
296             return E_UNEXPECTED;
297         }
298
299         *ppmk = This->doc->basedoc.window->mon;
300         IMoniker_AddRef(*ppmk);
301         break;
302     default:
303         FIXME("which %d\n", dwWhichMoniker);
304         return E_NOTIMPL;
305     }
306
307     return S_OK;
308 }
309
310 static HRESULT WINAPI PHClientSite_GetContainer(IOleClientSite *iface, IOleContainer **ppContainer)
311 {
312     PluginHost *This = impl_from_IOleClientSite(iface);
313     FIXME("(%p)->(%p)\n", This, ppContainer);
314     return E_NOTIMPL;
315 }
316
317 static HRESULT WINAPI PHClientSite_ShowObject(IOleClientSite *iface)
318 {
319     PluginHost *This = impl_from_IOleClientSite(iface);
320     FIXME("(%p)\n", This);
321     return E_NOTIMPL;
322 }
323
324 static HRESULT WINAPI PHClientSite_OnShowWindow(IOleClientSite *iface, BOOL fShow)
325 {
326     PluginHost *This = impl_from_IOleClientSite(iface);
327     FIXME("(%p)->(%x)\n", This, fShow);
328     return E_NOTIMPL;
329 }
330
331 static HRESULT WINAPI PHClientSite_RequestNewObjectLayout(IOleClientSite *iface)
332 {
333     PluginHost *This = impl_from_IOleClientSite(iface);
334     FIXME("(%p)\n", This);
335     return E_NOTIMPL;
336 }
337
338 static const IOleClientSiteVtbl OleClientSiteVtbl = {
339     PHClientSite_QueryInterface,
340     PHClientSite_AddRef,
341     PHClientSite_Release,
342     PHClientSite_SaveObject,
343     PHClientSite_GetMoniker,
344     PHClientSite_GetContainer,
345     PHClientSite_ShowObject,
346     PHClientSite_OnShowWindow,
347     PHClientSite_RequestNewObjectLayout
348 };
349
350 static inline PluginHost *impl_from_IAdviseSinkEx(IAdviseSinkEx *iface)
351 {
352     return CONTAINING_RECORD(iface, PluginHost, IAdviseSinkEx_iface);
353 }
354
355 static HRESULT WINAPI PHAdviseSinkEx_QueryInterface(IAdviseSinkEx *iface, REFIID riid, void **ppv)
356 {
357     PluginHost *This = impl_from_IAdviseSinkEx(iface);
358     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
359 }
360
361 static ULONG WINAPI PHAdviseSinkEx_AddRef(IAdviseSinkEx *iface)
362 {
363     PluginHost *This = impl_from_IAdviseSinkEx(iface);
364     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
365 }
366
367 static ULONG WINAPI PHAdviseSinkEx_Release(IAdviseSinkEx *iface)
368 {
369     PluginHost *This = impl_from_IAdviseSinkEx(iface);
370     return IOleClientSite_Release(&This->IOleClientSite_iface);
371 }
372
373 static void WINAPI PHAdviseSinkEx_OnDataChange(IAdviseSinkEx *iface, FORMATETC *pFormatetc, STGMEDIUM *pStgMedium)
374 {
375     PluginHost *This = impl_from_IAdviseSinkEx(iface);
376     FIXME("(%p)->(%p %p)\n", This, pFormatetc, pStgMedium);
377 }
378
379 static void WINAPI PHAdviseSinkEx_OnViewChange(IAdviseSinkEx *iface, DWORD dwAspect, LONG lindex)
380 {
381     PluginHost *This = impl_from_IAdviseSinkEx(iface);
382     FIXME("(%p)->(%d %d)\n", This, dwAspect, lindex);
383 }
384
385 static void WINAPI PHAdviseSinkEx_OnRename(IAdviseSinkEx *iface, IMoniker *pmk)
386 {
387     PluginHost *This = impl_from_IAdviseSinkEx(iface);
388     FIXME("(%p)->(%p)\n", This, pmk);
389 }
390
391 static void WINAPI PHAdviseSinkEx_OnSave(IAdviseSinkEx *iface)
392 {
393     PluginHost *This = impl_from_IAdviseSinkEx(iface);
394     FIXME("(%p)\n", This);
395 }
396
397 static void WINAPI PHAdviseSinkEx_OnClose(IAdviseSinkEx *iface)
398 {
399     PluginHost *This = impl_from_IAdviseSinkEx(iface);
400     FIXME("(%p)\n", This);
401 }
402
403 static void WINAPI PHAdviseSinkEx_OnViewStatusChange(IAdviseSinkEx *iface, DWORD dwViewStatus)
404 {
405     PluginHost *This = impl_from_IAdviseSinkEx(iface);
406     FIXME("(%p)->(%d)\n", This, dwViewStatus);
407 }
408
409 static const IAdviseSinkExVtbl AdviseSinkExVtbl = {
410     PHAdviseSinkEx_QueryInterface,
411     PHAdviseSinkEx_AddRef,
412     PHAdviseSinkEx_Release,
413     PHAdviseSinkEx_OnDataChange,
414     PHAdviseSinkEx_OnViewChange,
415     PHAdviseSinkEx_OnRename,
416     PHAdviseSinkEx_OnSave,
417     PHAdviseSinkEx_OnClose,
418     PHAdviseSinkEx_OnViewStatusChange
419 };
420
421 static inline PluginHost *impl_from_IPropertyNotifySink(IPropertyNotifySink *iface)
422 {
423     return CONTAINING_RECORD(iface, PluginHost, IPropertyNotifySink_iface);
424 }
425
426 static HRESULT WINAPI PHPropertyNotifySink_QueryInterface(IPropertyNotifySink *iface, REFIID riid, void **ppv)
427 {
428     PluginHost *This = impl_from_IPropertyNotifySink(iface);
429     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
430 }
431
432 static ULONG WINAPI PHPropertyNotifySink_AddRef(IPropertyNotifySink *iface)
433 {
434     PluginHost *This = impl_from_IPropertyNotifySink(iface);
435     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
436 }
437
438 static ULONG WINAPI PHPropertyNotifySink_Release(IPropertyNotifySink *iface)
439 {
440     PluginHost *This = impl_from_IPropertyNotifySink(iface);
441     return IOleClientSite_Release(&This->IOleClientSite_iface);
442 }
443
444 static HRESULT WINAPI PHPropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID)
445 {
446     PluginHost *This = impl_from_IPropertyNotifySink(iface);
447
448     TRACE("(%p)->(%d)\n", This, dispID);
449
450     switch(dispID) {
451     case DISPID_READYSTATE:
452         update_readystate(This);
453         break;
454     default :
455         FIXME("Unimplemented dispID %d\n", dispID);
456         return E_NOTIMPL;
457     }
458
459     return S_OK;
460 }
461
462 static HRESULT WINAPI PHPropertyNotifySink_OnRequestEdit(IPropertyNotifySink *iface, DISPID dispID)
463 {
464     PluginHost *This = impl_from_IPropertyNotifySink(iface);
465     FIXME("(%p)->(%d)\n", This, dispID);
466     return E_NOTIMPL;
467 }
468
469 static const IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = {
470     PHPropertyNotifySink_QueryInterface,
471     PHPropertyNotifySink_AddRef,
472     PHPropertyNotifySink_Release,
473     PHPropertyNotifySink_OnChanged,
474     PHPropertyNotifySink_OnRequestEdit
475 };
476
477 static inline PluginHost *impl_from_IDispatch(IDispatch *iface)
478 {
479     return CONTAINING_RECORD(iface, PluginHost, IDispatch_iface);
480 }
481
482 static HRESULT WINAPI PHDispatch_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
483 {
484     PluginHost *This = impl_from_IDispatch(iface);
485     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
486 }
487
488 static ULONG WINAPI PHDispatch_AddRef(IDispatch *iface)
489 {
490     PluginHost *This = impl_from_IDispatch(iface);
491     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
492 }
493
494 static ULONG WINAPI PHDispatch_Release(IDispatch *iface)
495 {
496     PluginHost *This = impl_from_IDispatch(iface);
497     return IOleClientSite_Release(&This->IOleClientSite_iface);
498 }
499
500 static HRESULT WINAPI PHDispatch_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
501 {
502     PluginHost *This = impl_from_IDispatch(iface);
503     FIXME("(%p)->(%p)\n", This, pctinfo);
504     return E_NOTIMPL;
505 }
506
507 static HRESULT WINAPI PHDispatch_GetTypeInfo(IDispatch *iface, UINT iTInfo,
508         LCID lcid, ITypeInfo **ppTInfo)
509 {
510     PluginHost *This = impl_from_IDispatch(iface);
511     FIXME("(%p)->(%d %d %p)\n", This, iTInfo, lcid, ppTInfo);
512     return E_NOTIMPL;
513 }
514
515 static HRESULT WINAPI PHDispatch_GetIDsOfNames(IDispatch *iface, REFIID riid,
516         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
517 {
518     PluginHost *This = impl_from_IDispatch(iface);
519     FIXME("(%p)->(%s %p %d %d %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
520     return E_NOTIMPL;
521 }
522
523 static HRESULT WINAPI PHDispatch_Invoke(IDispatch *iface, DISPID dispid,  REFIID riid, LCID lcid,
524         WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
525 {
526     PluginHost *This = impl_from_IDispatch(iface);
527     FIXME("(%p)->(%d %x %p %p)\n", This, dispid, wFlags, pDispParams, pVarResult);
528     return E_NOTIMPL;
529 }
530
531 static const IDispatchVtbl DispatchVtbl = {
532     PHDispatch_QueryInterface,
533     PHDispatch_AddRef,
534     PHDispatch_Release,
535     PHDispatch_GetTypeInfoCount,
536     PHDispatch_GetTypeInfo,
537     PHDispatch_GetIDsOfNames,
538     PHDispatch_Invoke
539 };
540
541 static inline PluginHost *impl_from_IOleInPlaceSiteEx(IOleInPlaceSiteEx *iface)
542 {
543     return CONTAINING_RECORD(iface, PluginHost, IOleInPlaceSiteEx_iface);
544 }
545
546 static HRESULT WINAPI PHInPlaceSite_QueryInterface(IOleInPlaceSiteEx *iface, REFIID riid, void **ppv)
547 {
548     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
549     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
550 }
551
552 static ULONG WINAPI PHInPlaceSite_AddRef(IOleInPlaceSiteEx *iface)
553 {
554     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
555     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
556 }
557
558 static ULONG WINAPI PHInPlaceSite_Release(IOleInPlaceSiteEx *iface)
559 {
560     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
561     return IOleClientSite_Release(&This->IOleClientSite_iface);
562 }
563
564 static HRESULT WINAPI PHInPlaceSite_GetWindow(IOleInPlaceSiteEx *iface, HWND *phwnd)
565 {
566     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
567     FIXME("(%p)->(%p)\n", This, phwnd);
568     return E_NOTIMPL;
569 }
570
571 static HRESULT WINAPI PHInPlaceSite_ContextSensitiveHelp(IOleInPlaceSiteEx *iface, BOOL fEnterMode)
572 {
573     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
574     FIXME("(%p)->(%x)\n", This, fEnterMode);
575     return E_NOTIMPL;
576 }
577
578 static HRESULT WINAPI PHInPlaceSite_CanInPlaceActivate(IOleInPlaceSiteEx *iface)
579 {
580     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
581     FIXME("(%p)\n", This);
582     return E_NOTIMPL;
583 }
584
585 static HRESULT WINAPI PHInPlaceSite_OnInPlaceActivate(IOleInPlaceSiteEx *iface)
586 {
587     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
588     FIXME("(%p)\n", This);
589     return E_NOTIMPL;
590 }
591
592 static HRESULT WINAPI PHInPlaceSite_OnUIActivate(IOleInPlaceSiteEx *iface)
593 {
594     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
595     FIXME("(%p)\n", This);
596     return E_NOTIMPL;
597 }
598
599 static HRESULT WINAPI PHInPlaceSite_GetWindowContext(IOleInPlaceSiteEx *iface,
600         IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, RECT *lprcPosRect,
601         RECT *lprcClipRect, OLEINPLACEFRAMEINFO *frame_info)
602 {
603     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
604     FIXME("(%p)->(%p %p %p %p %p)\n", This, ppFrame, ppDoc, lprcPosRect, lprcClipRect, frame_info);
605     return E_NOTIMPL;
606 }
607
608 static HRESULT WINAPI PHInPlaceSite_Scroll(IOleInPlaceSiteEx *iface, SIZE scrollExtent)
609 {
610     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
611     FIXME("(%p)->({%d %d})\n", This, scrollExtent.cx, scrollExtent.cy);
612     return E_NOTIMPL;
613 }
614
615 static HRESULT WINAPI PHInPlaceSite_OnUIDeactivate(IOleInPlaceSiteEx *iface, BOOL fUndoable)
616 {
617     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
618     FIXME("(%p)->(%x)\n", This, fUndoable);
619     return E_NOTIMPL;
620 }
621
622 static HRESULT WINAPI PHInPlaceSite_OnInPlaceDeactivate(IOleInPlaceSiteEx *iface)
623 {
624     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
625     FIXME("(%p)\n", This);
626     return E_NOTIMPL;
627 }
628
629 static HRESULT WINAPI PHInPlaceSite_DiscardUndoState(IOleInPlaceSiteEx *iface)
630 {
631     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
632     FIXME("(%p)\n", This);
633     return E_NOTIMPL;
634 }
635
636 static HRESULT WINAPI PHInPlaceSite_DeactivateAndUndo(IOleInPlaceSiteEx *iface)
637 {
638     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
639     FIXME("(%p)\n", This);
640     return E_NOTIMPL;
641 }
642
643 static HRESULT WINAPI PHInPlaceSite_OnPosRectChange(IOleInPlaceSiteEx *iface, LPCRECT lprcPosRect)
644 {
645     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
646     FIXME("(%p)->(%p)\n", This, lprcPosRect);
647     return E_NOTIMPL;
648 }
649
650 static HRESULT WINAPI PHInPlaceSiteEx_OnInPlaceActivateEx(IOleInPlaceSiteEx *iface, BOOL *pfNoRedraw, DWORD dwFlags)
651 {
652     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
653     FIXME("(%p)->(%p %x)\n", This, pfNoRedraw, dwFlags);
654     return E_NOTIMPL;
655 }
656
657 static HRESULT WINAPI PHInPlaceSiteEx_OnInPlaceDeactivateEx(IOleInPlaceSiteEx *iface, BOOL fNoRedraw)
658 {
659     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
660     FIXME("(%p)->(%x)\n", This, fNoRedraw);
661     return E_NOTIMPL;
662 }
663
664 static HRESULT WINAPI PHInPlaceSiteEx_RequestUIActivate(IOleInPlaceSiteEx *iface)
665 {
666     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
667     FIXME("(%p)\n", This);
668     return E_NOTIMPL;
669 }
670
671 static const IOleInPlaceSiteExVtbl OleInPlaceSiteExVtbl = {
672     PHInPlaceSite_QueryInterface,
673     PHInPlaceSite_AddRef,
674     PHInPlaceSite_Release,
675     PHInPlaceSite_GetWindow,
676     PHInPlaceSite_ContextSensitiveHelp,
677     PHInPlaceSite_CanInPlaceActivate,
678     PHInPlaceSite_OnInPlaceActivate,
679     PHInPlaceSite_OnUIActivate,
680     PHInPlaceSite_GetWindowContext,
681     PHInPlaceSite_Scroll,
682     PHInPlaceSite_OnUIDeactivate,
683     PHInPlaceSite_OnInPlaceDeactivate,
684     PHInPlaceSite_DiscardUndoState,
685     PHInPlaceSite_DeactivateAndUndo,
686     PHInPlaceSite_OnPosRectChange,
687     PHInPlaceSiteEx_OnInPlaceActivateEx,
688     PHInPlaceSiteEx_OnInPlaceDeactivateEx,
689     PHInPlaceSiteEx_RequestUIActivate
690 };
691
692 static inline PluginHost *impl_from_IOleControlSite(IOleControlSite *iface)
693 {
694     return CONTAINING_RECORD(iface, PluginHost, IOleControlSite_iface);
695 }
696
697 static HRESULT WINAPI PHControlSite_QueryInterface(IOleControlSite *iface, REFIID riid, void **ppv)
698 {
699     PluginHost *This = impl_from_IOleControlSite(iface);
700     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
701 }
702
703 static ULONG WINAPI PHControlSite_AddRef(IOleControlSite *iface)
704 {
705     PluginHost *This = impl_from_IOleControlSite(iface);
706     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
707 }
708
709 static ULONG WINAPI PHControlSite_Release(IOleControlSite *iface)
710 {
711     PluginHost *This = impl_from_IOleControlSite(iface);
712     return IOleClientSite_Release(&This->IOleClientSite_iface);
713 }
714
715 static HRESULT WINAPI PHControlSite_OnControlInfoChanged(IOleControlSite *iface)
716 {
717     PluginHost *This = impl_from_IOleControlSite(iface);
718     FIXME("(%p)\n", This);
719     return E_NOTIMPL;
720 }
721
722 static HRESULT WINAPI PHControlSite_LockInPlaceActive(IOleControlSite *iface, BOOL fLock)
723 {
724     PluginHost *This = impl_from_IOleControlSite(iface);
725     FIXME("(%p)->(%x)\n", This, fLock);
726     return E_NOTIMPL;
727 }
728
729 static HRESULT WINAPI PHControlSite_GetExtendedControl(IOleControlSite *iface, IDispatch **ppDisp)
730 {
731     PluginHost *This = impl_from_IOleControlSite(iface);
732     FIXME("(%p)->(%p)\n", This, ppDisp);
733     return E_NOTIMPL;
734 }
735
736 static HRESULT WINAPI PHControlSite_TransformCoords(IOleControlSite *iface, POINTL *pPtlHimetric, POINTF *pPtfContainer, DWORD dwFlags)
737 {
738     PluginHost *This = impl_from_IOleControlSite(iface);
739     FIXME("(%p)->(%p %p %x)\n", This, pPtlHimetric, pPtfContainer, dwFlags);
740     return E_NOTIMPL;
741 }
742
743 static HRESULT WINAPI PHControlSite_TranslateAccelerator(IOleControlSite *iface, MSG *pMsg, DWORD grfModifiers)
744 {
745     PluginHost *This = impl_from_IOleControlSite(iface);
746     FIXME("(%p)->(%x)\n", This, grfModifiers);
747     return E_NOTIMPL;
748 }
749
750 static HRESULT WINAPI PHControlSite_OnFocus(IOleControlSite *iface, BOOL fGotFocus)
751 {
752     PluginHost *This = impl_from_IOleControlSite(iface);
753     FIXME("(%p)->(%x)\n", This, fGotFocus);
754     return E_NOTIMPL;
755 }
756
757 static HRESULT WINAPI PHControlSite_ShowPropertyFrame(IOleControlSite *iface)
758 {
759     PluginHost *This = impl_from_IOleControlSite(iface);
760     FIXME("(%p)\n", This);
761     return E_NOTIMPL;
762 }
763
764 static const IOleControlSiteVtbl OleControlSiteVtbl = {
765     PHControlSite_QueryInterface,
766     PHControlSite_AddRef,
767     PHControlSite_Release,
768     PHControlSite_OnControlInfoChanged,
769     PHControlSite_LockInPlaceActive,
770     PHControlSite_GetExtendedControl,
771     PHControlSite_TransformCoords,
772     PHControlSite_TranslateAccelerator,
773     PHControlSite_OnFocus,
774     PHControlSite_ShowPropertyFrame
775 };
776
777 static inline PluginHost *impl_from_IBindHost(IBindHost *iface)
778 {
779     return CONTAINING_RECORD(iface, PluginHost, IBindHost_iface);
780 }
781
782 static HRESULT WINAPI PHBindHost_QueryInterface(IBindHost *iface, REFIID riid, void **ppv)
783 {
784     PluginHost *This = impl_from_IBindHost(iface);
785     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
786 }
787
788 static ULONG WINAPI PHBindHost_AddRef(IBindHost *iface)
789 {
790     PluginHost *This = impl_from_IBindHost(iface);
791     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
792 }
793
794 static ULONG WINAPI PHBindHost_Release(IBindHost *iface)
795 {
796     PluginHost *This = impl_from_IBindHost(iface);
797     return IOleClientSite_Release(&This->IOleClientSite_iface);
798 }
799
800 static HRESULT WINAPI PHBindHost_CreateMoniker(IBindHost *iface, LPOLESTR szName, IBindCtx *pBC, IMoniker **ppmk, DWORD dwReserved)
801 {
802     PluginHost *This = impl_from_IBindHost(iface);
803
804     TRACE("(%p)->(%s %p %p %x)\n", This, debugstr_w(szName), pBC, ppmk, dwReserved);
805
806     if(!This->doc || !This->doc->basedoc.window || !This->doc->basedoc.window->mon) {
807         FIXME("no moniker\n");
808         return E_UNEXPECTED;
809     }
810
811     return CreateURLMoniker(This->doc->basedoc.window->mon, szName, ppmk);
812 }
813
814 static HRESULT WINAPI PHBindHost_MonikerBindToStorage(IBindHost *iface, IMoniker *pMk, IBindCtx *pBC,
815         IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
816 {
817     PluginHost *This = impl_from_IBindHost(iface);
818     FIXME("(%p)->(%p %p %p %s %p)\n", This, pMk, pBC, pBSC, debugstr_guid(riid), ppvObj);
819     return E_NOTIMPL;
820 }
821
822 static HRESULT WINAPI PHBindHost_MonikerBindToObject(IBindHost *iface, IMoniker *pMk, IBindCtx *pBC,
823         IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
824 {
825     PluginHost *This = impl_from_IBindHost(iface);
826     FIXME("(%p)->(%p %p %p %s %p)\n", This, pMk, pBC, pBSC, debugstr_guid(riid), ppvObj);
827     return E_NOTIMPL;
828 }
829
830 static const IBindHostVtbl BindHostVtbl = {
831     PHBindHost_QueryInterface,
832     PHBindHost_AddRef,
833     PHBindHost_Release,
834     PHBindHost_CreateMoniker,
835     PHBindHost_MonikerBindToStorage,
836     PHBindHost_MonikerBindToObject
837 };
838
839 static inline PluginHost *impl_from_IServiceProvider(IServiceProvider *iface)
840 {
841     return CONTAINING_RECORD(iface, PluginHost, IServiceProvider_iface);
842 }
843
844 static HRESULT WINAPI PHServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
845 {
846     PluginHost *This = impl_from_IServiceProvider(iface);
847     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
848 }
849
850 static ULONG WINAPI PHServiceProvider_AddRef(IServiceProvider *iface)
851 {
852     PluginHost *This = impl_from_IServiceProvider(iface);
853     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
854 }
855
856 static ULONG WINAPI PHServiceProvider_Release(IServiceProvider *iface)
857 {
858     PluginHost *This = impl_from_IServiceProvider(iface);
859     return IOleClientSite_Release(&This->IOleClientSite_iface);
860 }
861
862 static HRESULT WINAPI PHServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService, REFIID riid, void **ppv)
863 {
864     PluginHost *This = impl_from_IServiceProvider(iface);
865
866     if(IsEqualGUID(guidService, &SID_SBindHost)) {
867         TRACE("SID_SBindHost service\n");
868         return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
869     }
870
871     FIXME("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
872     return E_NOINTERFACE;
873 }
874
875 static const IServiceProviderVtbl ServiceProviderVtbl = {
876     PHServiceProvider_QueryInterface,
877     PHServiceProvider_AddRef,
878     PHServiceProvider_Release,
879     PHServiceProvider_QueryService
880 };
881
882 static HRESULT assoc_element(PluginHost *host, HTMLDocumentNode *doc, nsIDOMElement *nselem)
883 {
884     HTMLPluginContainer *container_elem;
885     HTMLDOMNode *node;
886     HRESULT hres;
887
888     hres = get_node(doc, (nsIDOMNode*)nselem, TRUE, &node);
889     if(FAILED(hres))
890         return hres;
891
892     hres = IHTMLDOMNode_QueryInterface(HTMLDOMNODE(node), &IID_HTMLPluginContainer, (void**)&container_elem);
893     if(FAILED(hres)) {
894         ERR("Not an object element\n");
895         return hres;
896     }
897
898     container_elem->plugin_host = host;
899     host->element = container_elem;
900     return S_OK;
901 }
902
903 void detach_plugin_hosts(HTMLDocumentNode *doc)
904 {
905     PluginHost *iter;
906
907     while(!list_empty(&doc->plugin_hosts)) {
908         iter = LIST_ENTRY(list_head(&doc->plugin_hosts), PluginHost, entry);
909         list_remove(&iter->entry);
910         iter->doc = NULL;
911     }
912 }
913
914 HRESULT create_plugin_host(HTMLDocumentNode *doc, nsIDOMElement *nselem, IUnknown *unk, const CLSID *clsid, PluginHost **ret)
915 {
916     PluginHost *host;
917     HRESULT hres;
918
919     host = heap_alloc_zero(sizeof(*host));
920     if(!host)
921         return E_OUTOFMEMORY;
922
923     host->IOleClientSite_iface.lpVtbl      = &OleClientSiteVtbl;
924     host->IAdviseSinkEx_iface.lpVtbl       = &AdviseSinkExVtbl;
925     host->IPropertyNotifySink_iface.lpVtbl = &PropertyNotifySinkVtbl;
926     host->IDispatch_iface.lpVtbl           = &DispatchVtbl;
927     host->IOleInPlaceSiteEx_iface.lpVtbl   = &OleInPlaceSiteExVtbl;
928     host->IOleControlSite_iface.lpVtbl     = &OleControlSiteVtbl;
929     host->IBindHost_iface.lpVtbl           = &BindHostVtbl;
930     host->IServiceProvider_iface.lpVtbl    = &ServiceProviderVtbl;
931
932     host->ref = 1;
933
934     hres = assoc_element(host, doc, nselem);
935     if(FAILED(hres)) {
936         heap_free(host);
937         return hres;
938     }
939
940     IUnknown_AddRef(unk);
941     host->plugin_unk = unk;
942     host->clsid = *clsid;
943
944     host->doc = doc;
945     list_add_tail(&doc->plugin_hosts, &host->entry);
946
947     *ret = host;
948     return S_OK;
949 }