quartz/tests: Remove misplaced ok() call.
[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 #include "mshtmdid.h"
31
32 #include "mshtml_private.h"
33 #include "pluginhost.h"
34
35 #include "wine/debug.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(&host->doc->IInternetHostSecurityManager_iface,
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 BOOL check_script_safety(PluginHost *host)
64 {
65     DISPPARAMS params = {NULL,NULL,0,0};
66     DWORD policy_size, policy;
67     struct CONFIRMSAFETY cs;
68     BYTE *ppolicy;
69     ULONG err = 0;
70     VARIANT v;
71     HRESULT hres;
72
73     cs.clsid = host->clsid;
74     cs.pUnk = host->plugin_unk;
75     cs.dwFlags = 0;
76
77     hres = IInternetHostSecurityManager_QueryCustomPolicy(&host->doc->IInternetHostSecurityManager_iface,
78             &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
79     if(FAILED(hres))
80         return FALSE;
81
82     policy = *(DWORD*)ppolicy;
83     CoTaskMemFree(ppolicy);
84
85     if(policy != URLPOLICY_ALLOW)
86         return FALSE;
87
88     V_VT(&v) = VT_EMPTY;
89     hres = IDispatch_Invoke(host->disp, DISPID_SECURITYCTX, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, &v, NULL, &err);
90     if(SUCCEEDED(hres)) {
91         FIXME("Handle security ctx %s\n", debugstr_variant(&v));
92         return FALSE;
93     }
94
95     return TRUE;
96 }
97
98 static void update_readystate(PluginHost *host)
99 {
100     DISPPARAMS params = {NULL,NULL,0,0};
101     IDispatchEx *dispex;
102     IDispatch *disp;
103     ULONG err = 0;
104     VARIANT v;
105     HRESULT hres;
106
107     hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatchEx, (void**)&dispex);
108     if(SUCCEEDED(hres)) {
109         FIXME("Use IDispatchEx\n");
110         IDispatchEx_Release(dispex);
111     }
112
113     hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatch, (void**)&disp);
114     if(FAILED(hres))
115         return;
116
117     hres = IDispatch_Invoke(disp, DISPID_READYSTATE, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, &v, NULL, &err);
118     IDispatch_Release(disp);
119     if(SUCCEEDED(hres)) {
120         /* FIXME: make plugin readystate affect document readystate */
121         TRACE("readystate = %s\n", debugstr_variant(&v));
122         VariantClear(&v);
123     }
124 }
125
126 /* FIXME: We shouldn't need this function and we should embed plugin directly in the main document */
127 static void get_pos_rect(PluginHost *host, RECT *ret)
128 {
129     ret->top = 0;
130     ret->left = 0;
131     ret->bottom = host->rect.bottom - host->rect.top;
132     ret->right = host->rect.right - host->rect.left;
133 }
134
135 static void load_prop_bag(PluginHost *host, IPersistPropertyBag *persist_prop_bag)
136 {
137     IPropertyBag *prop_bag;
138     HRESULT hres;
139
140     hres = create_param_prop_bag(host->element->element.nselem, &prop_bag);
141     if(FAILED(hres))
142         return;
143
144     if(prop_bag && !check_load_safety(host)) {
145         IPropertyBag_Release(prop_bag);
146         prop_bag = NULL;
147     }
148
149     if(prop_bag) {
150         hres = IPersistPropertyBag_Load(persist_prop_bag, prop_bag, NULL);
151         IPropertyBag_Release(prop_bag);
152         if(FAILED(hres))
153             WARN("Load failed: %08x\n", hres);
154     }else {
155         hres = IPersistPropertyBag_InitNew(persist_prop_bag);
156         if(FAILED(hres))
157             WARN("InitNew failed: %08x\n", hres);
158     }
159 }
160
161 static void load_plugin(PluginHost *host)
162 {
163     IPersistPropertyBag2 *persist_prop_bag2;
164     IPersistPropertyBag *persist_prop_bag;
165     HRESULT hres;
166
167     hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IPersistPropertyBag2, (void**)&persist_prop_bag2);
168     if(SUCCEEDED(hres)) {
169         FIXME("Use IPersistPropertyBag2 iface\n");
170         IPersistPropertyBag2_Release(persist_prop_bag2);
171         return;
172     }
173
174     hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IPersistPropertyBag, (void**)&persist_prop_bag);
175     if(SUCCEEDED(hres)) {
176         load_prop_bag(host, persist_prop_bag);
177         IPersistPropertyBag_Release(persist_prop_bag);
178         return;
179     }
180
181     FIXME("No IPersistPropertyBag iface\n");
182 }
183
184 static void activate_plugin(PluginHost *host)
185 {
186     IClientSecurity *client_security;
187     IQuickActivate *quick_activate;
188     IOleObject *ole_obj = NULL;
189     IOleCommandTarget *cmdtrg;
190     IViewObjectEx *view_obj;
191     IDispatchEx *dispex;
192     IDispatch *disp;
193     RECT rect;
194     HRESULT hres;
195
196     if(!host->plugin_unk)
197         return;
198
199     /* Note native calls QI on plugin for an undocumented IID and CLSID_HTMLDocument */
200
201     /* FIXME: call FreezeEvents(TRUE) */
202
203     hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IClientSecurity, (void**)&client_security);
204     if(SUCCEEDED(hres)) {
205         FIXME("Handle IClientSecurity\n");
206         IClientSecurity_Release(client_security);
207         return;
208     }
209
210     hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IQuickActivate, (void**)&quick_activate);
211     if(SUCCEEDED(hres)) {
212         QACONTAINER container = {sizeof(container)};
213         QACONTROL control = {sizeof(control)};
214
215         TRACE("Using IQuickActivate\n");
216
217         container.pClientSite = &host->IOleClientSite_iface;
218         container.dwAmbientFlags = QACONTAINER_SUPPORTSMNEMONICS|QACONTAINER_MESSAGEREFLECT|QACONTAINER_USERMODE;
219         container.pAdviseSink = &host->IAdviseSinkEx_iface;
220         container.pPropertyNotifySink = &host->IPropertyNotifySink_iface;
221
222         hres = IQuickActivate_QuickActivate(quick_activate, &container, &control);
223         IQuickActivate_Release(quick_activate);
224         if(FAILED(hres))
225             FIXME("QuickActivate failed: %08x\n", hres);
226     }else {
227         DWORD status = 0;
228
229         hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleObject, (void**)&ole_obj);
230         if(SUCCEEDED(hres)) {
231             hres = IOleObject_GetMiscStatus(ole_obj, DVASPECT_CONTENT, &status);
232             TRACE("GetMiscStatus returned %08x %x\n", hres, status);
233
234             hres = IOleObject_SetClientSite(ole_obj, &host->IOleClientSite_iface);
235             IOleObject_Release(ole_obj);
236             if(FAILED(hres)) {
237                 FIXME("SetClientSite failed: %08x\n", hres);
238                 return;
239             }
240         }else {
241             TRACE("Plugin does not support IOleObject\n");
242         }
243     }
244
245     load_plugin(host);
246
247     if(ole_obj) {
248         hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IViewObjectEx, (void**)&view_obj);
249         if(SUCCEEDED(hres)) {
250             DWORD view_status = 0;
251
252             hres = IViewObjectEx_SetAdvise(view_obj, DVASPECT_CONTENT, 0, (IAdviseSink*)&host->IAdviseSinkEx_iface);
253             if(FAILED(hres))
254                 WARN("SetAdvise failed: %08x\n", hres);
255
256             hres = IViewObjectEx_GetViewStatus(view_obj, &view_status);
257             IViewObjectEx_Release(view_obj);
258             TRACE("GetViewStatus returned %08x %x\n", hres, view_status);
259         }
260     }
261
262     update_readystate(host);
263
264     /* NOTE: Native QIs for IActiveScript, an undocumented IID, IOleControl and IRunnableObject */
265
266     hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatchEx, (void**)&dispex);
267     if(SUCCEEDED(hres)) {
268         FIXME("Use IDispatchEx\n");
269         host->disp = (IDispatch*)dispex;
270     }else {
271         hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatch, (void**)&disp);
272         if(SUCCEEDED(hres))
273             host->disp = disp;
274         else
275             TRACE("no IDispatch iface\n");
276     }
277
278     hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleCommandTarget, (void**)&cmdtrg);
279     if(SUCCEEDED(hres)) {
280         FIXME("Use IOleCommandTarget\n");
281         IOleCommandTarget_Release(cmdtrg);
282     }
283
284     hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleObject, (void**)&ole_obj);
285     if(FAILED(hres)) {
286         FIXME("Plugin does not support IOleObject\n");
287         return;
288     }
289
290     if(ole_obj) {
291         get_pos_rect(host, &rect);
292         hres = IOleObject_DoVerb(ole_obj, OLEIVERB_INPLACEACTIVATE, NULL, &host->IOleClientSite_iface, 0, host->hwnd, &rect);
293         IOleObject_Release(ole_obj);
294         if(FAILED(hres))
295             WARN("DoVerb failed: %08x\n", hres);
296     }
297
298     if(host->ip_object) {
299         HWND hwnd;
300
301         hres = IOleInPlaceObject_GetWindow(host->ip_object, &hwnd);
302         if(SUCCEEDED(hres))
303             TRACE("hwnd %p\n", hwnd);
304     }
305 }
306
307 void update_plugin_window(PluginHost *host, HWND hwnd, const RECT *rect)
308 {
309     BOOL rect_changed = FALSE;
310
311     if(!hwnd || (host->hwnd && host->hwnd != hwnd)) {
312         FIXME("unhandled hwnd\n");
313         return;
314     }
315
316     TRACE("%p %s\n", hwnd, wine_dbgstr_rect(rect));
317
318     if(memcmp(rect, &host->rect, sizeof(RECT))) {
319         host->rect = *rect;
320         rect_changed = TRUE;
321     }
322
323     if(!host->hwnd) {
324         host->hwnd = hwnd;
325         activate_plugin(host);
326     }
327
328     if(rect_changed && host->ip_object)
329         IOleInPlaceObject_SetObjectRects(host->ip_object, &host->rect, &host->rect);
330 }
331
332 HRESULT get_plugin_disp(HTMLPluginContainer *plugin_container, IDispatch **ret)
333 {
334     PluginHost *host;
335
336     host = plugin_container->plugin_host;
337     if(!host) {
338         ERR("No plugin host\n");
339         return E_UNEXPECTED;
340     }
341
342     if(!host->disp) {
343         *ret = NULL;
344         return S_OK;
345     }
346
347     if(!check_script_safety(host)) {
348         FIXME("Insecure object\n");
349         return E_FAIL;
350     }
351
352     IDispatch_AddRef(host->disp);
353     *ret = host->disp;
354     return S_OK;
355 }
356
357 HRESULT get_plugin_dispid(HTMLPluginContainer *plugin_container, WCHAR *name, DISPID *ret)
358 {
359     IDispatch *disp;
360     DISPID id;
361     DWORD i;
362     HRESULT hres;
363
364     if(!plugin_container->plugin_host) {
365         WARN("no plugin host\n");
366         return DISP_E_UNKNOWNNAME;
367     }
368
369     disp = plugin_container->plugin_host->disp;
370     if(!disp)
371         return DISP_E_UNKNOWNNAME;
372
373     hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, &id);
374     if(FAILED(hres)) {
375         TRACE("no prop %s\n", debugstr_w(name));
376         return DISP_E_UNKNOWNNAME;
377     }
378
379     for(i=0; i < plugin_container->props_len; i++) {
380         if(id == plugin_container->props[i]) {
381             *ret = MSHTML_DISPID_CUSTOM_MIN+i;
382             return S_OK;
383         }
384     }
385
386     if(!plugin_container->props) {
387         plugin_container->props = heap_alloc(8*sizeof(DISPID));
388         if(!plugin_container->props)
389             return E_OUTOFMEMORY;
390         plugin_container->props_size = 8;
391     }else if(plugin_container->props_len == plugin_container->props_size) {
392         DISPID *new_props;
393
394         new_props = heap_realloc(plugin_container->props, plugin_container->props_size*2*sizeof(DISPID));
395         if(!new_props)
396             return E_OUTOFMEMORY;
397
398         plugin_container->props = new_props;
399         plugin_container->props_size *= 2;
400     }
401
402     plugin_container->props[plugin_container->props_len] = id;
403     *ret = MSHTML_DISPID_CUSTOM_MIN+plugin_container->props_len;
404     plugin_container->props_len++;
405     return S_OK;
406 }
407
408 HRESULT invoke_plugin_prop(HTMLPluginContainer *plugin_container, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
409         VARIANT *res, EXCEPINFO *ei)
410 {
411     PluginHost *host;
412
413     host = plugin_container->plugin_host;
414     if(!host || !host->disp) {
415         FIXME("Called with no disp\n");
416         return E_UNEXPECTED;
417     }
418
419     if(!check_script_safety(host)) {
420         FIXME("Insecure object\n");
421         return E_FAIL;
422     }
423
424     if(id < MSHTML_DISPID_CUSTOM_MIN || id > MSHTML_DISPID_CUSTOM_MIN + plugin_container->props_len) {
425         ERR("Invalid id\n");
426         return E_FAIL;
427     }
428
429     return IDispatch_Invoke(host->disp, plugin_container->props[id-MSHTML_DISPID_CUSTOM_MIN], &IID_NULL,
430             lcid, flags, params, res, ei, NULL);
431 }
432
433 static inline PluginHost *impl_from_IOleClientSite(IOleClientSite *iface)
434 {
435     return CONTAINING_RECORD(iface, PluginHost, IOleClientSite_iface);
436 }
437
438 static HRESULT WINAPI PHClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv)
439 {
440     PluginHost *This = impl_from_IOleClientSite(iface);
441
442     if(IsEqualGUID(&IID_IUnknown, riid)) {
443         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
444         *ppv = &This->IOleClientSite_iface;
445     }else if(IsEqualGUID(&IID_IOleClientSite, riid)) {
446         TRACE("(%p)->(IID_IOleClientSite %p)\n", This, ppv);
447         *ppv = &This->IOleClientSite_iface;
448     }else if(IsEqualGUID(&IID_IAdviseSink, riid)) {
449         TRACE("(%p)->(IID_IAdviseSink %p)\n", This, ppv);
450         *ppv = &This->IAdviseSinkEx_iface;
451     }else if(IsEqualGUID(&IID_IAdviseSinkEx, riid)) {
452         TRACE("(%p)->(IID_IAdviseSinkEx %p)\n", This, ppv);
453         *ppv = &This->IAdviseSinkEx_iface;
454     }else if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) {
455         TRACE("(%p)->(IID_IPropertyNotifySink %p)\n", This, ppv);
456         *ppv = &This->IPropertyNotifySink_iface;
457     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
458         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
459         *ppv = &This->IDispatch_iface;
460     }else if(IsEqualGUID(&IID_IOleWindow, riid)) {
461         TRACE("(%p)->(IID_IOleWindow %p)\n", This, ppv);
462         *ppv = &This->IOleInPlaceSiteEx_iface;
463     }else if(IsEqualGUID(&IID_IOleInPlaceSite, riid)) {
464         TRACE("(%p)->(IID_IOleInPlaceSite %p)\n", This, ppv);
465         *ppv = &This->IOleInPlaceSiteEx_iface;
466     }else if(IsEqualGUID(&IID_IOleInPlaceSiteEx, riid)) {
467         TRACE("(%p)->(IID_IOleInPlaceSiteEx %p)\n", This, ppv);
468         *ppv = &This->IOleInPlaceSiteEx_iface;
469     }else if(IsEqualGUID(&IID_IOleControlSite, riid)) {
470         TRACE("(%p)->(IID_IOleControlSite %p)\n", This, ppv);
471         *ppv = &This->IOleControlSite_iface;
472     }else if(IsEqualGUID(&IID_IBindHost, riid)) {
473         TRACE("(%p)->(IID_IBindHost %p)\n", This, ppv);
474         *ppv = &This->IBindHost_iface;
475     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
476         TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
477         *ppv = &This->IServiceProvider_iface;
478     }else {
479         WARN("Unsupported interface %s\n", debugstr_guid(riid));
480         *ppv = NULL;
481         return E_NOINTERFACE;
482     }
483
484     IOleClientSite_AddRef((IUnknown*)*ppv);
485     return S_OK;
486 }
487
488 static ULONG WINAPI PHClientSite_AddRef(IOleClientSite *iface)
489 {
490     PluginHost *This = impl_from_IOleClientSite(iface);
491     LONG ref = InterlockedIncrement(&This->ref);
492
493     TRACE("(%p) ref=%d\n", This, ref);
494
495     return ref;
496 }
497
498 static ULONG WINAPI PHClientSite_Release(IOleClientSite *iface)
499 {
500     PluginHost *This = impl_from_IOleClientSite(iface);
501     LONG ref = InterlockedDecrement(&This->ref);
502
503     TRACE("(%p) ref=%d\n", This, ref);
504
505     if(!ref) {
506         if(This->disp)
507             IDispatch_Release(This->disp);
508         if(This->ip_object)
509             IOleInPlaceObject_Release(This->ip_object);
510         list_remove(&This->entry);
511         if(This->element)
512             This->element->plugin_host = NULL;
513         if(This->plugin_unk)
514             IUnknown_Release(This->plugin_unk);
515         heap_free(This);
516     }
517
518     return ref;
519 }
520
521 static HRESULT WINAPI PHClientSite_SaveObject(IOleClientSite *iface)
522 {
523     PluginHost *This = impl_from_IOleClientSite(iface);
524     FIXME("(%p)\n", This);
525     return E_NOTIMPL;
526 }
527
528 static HRESULT WINAPI PHClientSite_GetMoniker(IOleClientSite *iface, DWORD dwAssign,
529         DWORD dwWhichMoniker, IMoniker **ppmk)
530 {
531     PluginHost *This = impl_from_IOleClientSite(iface);
532
533     TRACE("(%p)->(%d %d %p)\n", This, dwAssign, dwWhichMoniker, ppmk);
534
535     switch(dwWhichMoniker) {
536     case OLEWHICHMK_CONTAINER:
537         if(!This->doc || !This->doc->basedoc.window || !This->doc->basedoc.window->mon) {
538             FIXME("no moniker\n");
539             return E_UNEXPECTED;
540         }
541
542         *ppmk = This->doc->basedoc.window->mon;
543         IMoniker_AddRef(*ppmk);
544         break;
545     default:
546         FIXME("which %d\n", dwWhichMoniker);
547         return E_NOTIMPL;
548     }
549
550     return S_OK;
551 }
552
553 static HRESULT WINAPI PHClientSite_GetContainer(IOleClientSite *iface, IOleContainer **ppContainer)
554 {
555     PluginHost *This = impl_from_IOleClientSite(iface);
556
557     TRACE("(%p)->(%p)\n", This, ppContainer);
558
559     if(!This->doc) {
560         ERR("Called on detached object\n");
561         return E_UNEXPECTED;
562     }
563
564     *ppContainer = &This->doc->basedoc.IOleContainer_iface;
565     IOleContainer_AddRef(*ppContainer);
566     return S_OK;
567 }
568
569 static HRESULT WINAPI PHClientSite_ShowObject(IOleClientSite *iface)
570 {
571     PluginHost *This = impl_from_IOleClientSite(iface);
572
573     TRACE("(%p)\n", This);
574
575     return S_OK;
576 }
577
578 static HRESULT WINAPI PHClientSite_OnShowWindow(IOleClientSite *iface, BOOL fShow)
579 {
580     PluginHost *This = impl_from_IOleClientSite(iface);
581     FIXME("(%p)->(%x)\n", This, fShow);
582     return E_NOTIMPL;
583 }
584
585 static HRESULT WINAPI PHClientSite_RequestNewObjectLayout(IOleClientSite *iface)
586 {
587     PluginHost *This = impl_from_IOleClientSite(iface);
588     FIXME("(%p)\n", This);
589     return E_NOTIMPL;
590 }
591
592 static const IOleClientSiteVtbl OleClientSiteVtbl = {
593     PHClientSite_QueryInterface,
594     PHClientSite_AddRef,
595     PHClientSite_Release,
596     PHClientSite_SaveObject,
597     PHClientSite_GetMoniker,
598     PHClientSite_GetContainer,
599     PHClientSite_ShowObject,
600     PHClientSite_OnShowWindow,
601     PHClientSite_RequestNewObjectLayout
602 };
603
604 static inline PluginHost *impl_from_IAdviseSinkEx(IAdviseSinkEx *iface)
605 {
606     return CONTAINING_RECORD(iface, PluginHost, IAdviseSinkEx_iface);
607 }
608
609 static HRESULT WINAPI PHAdviseSinkEx_QueryInterface(IAdviseSinkEx *iface, REFIID riid, void **ppv)
610 {
611     PluginHost *This = impl_from_IAdviseSinkEx(iface);
612     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
613 }
614
615 static ULONG WINAPI PHAdviseSinkEx_AddRef(IAdviseSinkEx *iface)
616 {
617     PluginHost *This = impl_from_IAdviseSinkEx(iface);
618     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
619 }
620
621 static ULONG WINAPI PHAdviseSinkEx_Release(IAdviseSinkEx *iface)
622 {
623     PluginHost *This = impl_from_IAdviseSinkEx(iface);
624     return IOleClientSite_Release(&This->IOleClientSite_iface);
625 }
626
627 static void WINAPI PHAdviseSinkEx_OnDataChange(IAdviseSinkEx *iface, FORMATETC *pFormatetc, STGMEDIUM *pStgMedium)
628 {
629     PluginHost *This = impl_from_IAdviseSinkEx(iface);
630     FIXME("(%p)->(%p %p)\n", This, pFormatetc, pStgMedium);
631 }
632
633 static void WINAPI PHAdviseSinkEx_OnViewChange(IAdviseSinkEx *iface, DWORD dwAspect, LONG lindex)
634 {
635     PluginHost *This = impl_from_IAdviseSinkEx(iface);
636     FIXME("(%p)->(%d %d)\n", This, dwAspect, lindex);
637 }
638
639 static void WINAPI PHAdviseSinkEx_OnRename(IAdviseSinkEx *iface, IMoniker *pmk)
640 {
641     PluginHost *This = impl_from_IAdviseSinkEx(iface);
642     FIXME("(%p)->(%p)\n", This, pmk);
643 }
644
645 static void WINAPI PHAdviseSinkEx_OnSave(IAdviseSinkEx *iface)
646 {
647     PluginHost *This = impl_from_IAdviseSinkEx(iface);
648     FIXME("(%p)\n", This);
649 }
650
651 static void WINAPI PHAdviseSinkEx_OnClose(IAdviseSinkEx *iface)
652 {
653     PluginHost *This = impl_from_IAdviseSinkEx(iface);
654     FIXME("(%p)\n", This);
655 }
656
657 static void WINAPI PHAdviseSinkEx_OnViewStatusChange(IAdviseSinkEx *iface, DWORD dwViewStatus)
658 {
659     PluginHost *This = impl_from_IAdviseSinkEx(iface);
660     FIXME("(%p)->(%d)\n", This, dwViewStatus);
661 }
662
663 static const IAdviseSinkExVtbl AdviseSinkExVtbl = {
664     PHAdviseSinkEx_QueryInterface,
665     PHAdviseSinkEx_AddRef,
666     PHAdviseSinkEx_Release,
667     PHAdviseSinkEx_OnDataChange,
668     PHAdviseSinkEx_OnViewChange,
669     PHAdviseSinkEx_OnRename,
670     PHAdviseSinkEx_OnSave,
671     PHAdviseSinkEx_OnClose,
672     PHAdviseSinkEx_OnViewStatusChange
673 };
674
675 static inline PluginHost *impl_from_IPropertyNotifySink(IPropertyNotifySink *iface)
676 {
677     return CONTAINING_RECORD(iface, PluginHost, IPropertyNotifySink_iface);
678 }
679
680 static HRESULT WINAPI PHPropertyNotifySink_QueryInterface(IPropertyNotifySink *iface, REFIID riid, void **ppv)
681 {
682     PluginHost *This = impl_from_IPropertyNotifySink(iface);
683     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
684 }
685
686 static ULONG WINAPI PHPropertyNotifySink_AddRef(IPropertyNotifySink *iface)
687 {
688     PluginHost *This = impl_from_IPropertyNotifySink(iface);
689     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
690 }
691
692 static ULONG WINAPI PHPropertyNotifySink_Release(IPropertyNotifySink *iface)
693 {
694     PluginHost *This = impl_from_IPropertyNotifySink(iface);
695     return IOleClientSite_Release(&This->IOleClientSite_iface);
696 }
697
698 static HRESULT WINAPI PHPropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID)
699 {
700     PluginHost *This = impl_from_IPropertyNotifySink(iface);
701
702     TRACE("(%p)->(%d)\n", This, dispID);
703
704     switch(dispID) {
705     case DISPID_READYSTATE:
706         update_readystate(This);
707         break;
708     default :
709         FIXME("Unimplemented dispID %d\n", dispID);
710         return E_NOTIMPL;
711     }
712
713     return S_OK;
714 }
715
716 static HRESULT WINAPI PHPropertyNotifySink_OnRequestEdit(IPropertyNotifySink *iface, DISPID dispID)
717 {
718     PluginHost *This = impl_from_IPropertyNotifySink(iface);
719     FIXME("(%p)->(%d)\n", This, dispID);
720     return E_NOTIMPL;
721 }
722
723 static const IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = {
724     PHPropertyNotifySink_QueryInterface,
725     PHPropertyNotifySink_AddRef,
726     PHPropertyNotifySink_Release,
727     PHPropertyNotifySink_OnChanged,
728     PHPropertyNotifySink_OnRequestEdit
729 };
730
731 static inline PluginHost *impl_from_IDispatch(IDispatch *iface)
732 {
733     return CONTAINING_RECORD(iface, PluginHost, IDispatch_iface);
734 }
735
736 static HRESULT WINAPI PHDispatch_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
737 {
738     PluginHost *This = impl_from_IDispatch(iface);
739     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
740 }
741
742 static ULONG WINAPI PHDispatch_AddRef(IDispatch *iface)
743 {
744     PluginHost *This = impl_from_IDispatch(iface);
745     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
746 }
747
748 static ULONG WINAPI PHDispatch_Release(IDispatch *iface)
749 {
750     PluginHost *This = impl_from_IDispatch(iface);
751     return IOleClientSite_Release(&This->IOleClientSite_iface);
752 }
753
754 static HRESULT WINAPI PHDispatch_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
755 {
756     PluginHost *This = impl_from_IDispatch(iface);
757     FIXME("(%p)->(%p)\n", This, pctinfo);
758     return E_NOTIMPL;
759 }
760
761 static HRESULT WINAPI PHDispatch_GetTypeInfo(IDispatch *iface, UINT iTInfo,
762         LCID lcid, ITypeInfo **ppTInfo)
763 {
764     PluginHost *This = impl_from_IDispatch(iface);
765     FIXME("(%p)->(%d %d %p)\n", This, iTInfo, lcid, ppTInfo);
766     return E_NOTIMPL;
767 }
768
769 static HRESULT WINAPI PHDispatch_GetIDsOfNames(IDispatch *iface, REFIID riid,
770         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
771 {
772     PluginHost *This = impl_from_IDispatch(iface);
773     FIXME("(%p)->(%s %p %d %d %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
774     return E_NOTIMPL;
775 }
776
777 static HRESULT WINAPI PHDispatch_Invoke(IDispatch *iface, DISPID dispid,  REFIID riid, LCID lcid,
778         WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
779 {
780     PluginHost *This = impl_from_IDispatch(iface);
781     FIXME("(%p)->(%d %x %p %p)\n", This, dispid, wFlags, pDispParams, pVarResult);
782     return E_NOTIMPL;
783 }
784
785 static const IDispatchVtbl DispatchVtbl = {
786     PHDispatch_QueryInterface,
787     PHDispatch_AddRef,
788     PHDispatch_Release,
789     PHDispatch_GetTypeInfoCount,
790     PHDispatch_GetTypeInfo,
791     PHDispatch_GetIDsOfNames,
792     PHDispatch_Invoke
793 };
794
795 static inline PluginHost *impl_from_IOleInPlaceSiteEx(IOleInPlaceSiteEx *iface)
796 {
797     return CONTAINING_RECORD(iface, PluginHost, IOleInPlaceSiteEx_iface);
798 }
799
800 static HRESULT WINAPI PHInPlaceSite_QueryInterface(IOleInPlaceSiteEx *iface, REFIID riid, void **ppv)
801 {
802     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
803     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
804 }
805
806 static ULONG WINAPI PHInPlaceSite_AddRef(IOleInPlaceSiteEx *iface)
807 {
808     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
809     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
810 }
811
812 static ULONG WINAPI PHInPlaceSite_Release(IOleInPlaceSiteEx *iface)
813 {
814     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
815     return IOleClientSite_Release(&This->IOleClientSite_iface);
816 }
817
818 static HRESULT WINAPI PHInPlaceSite_GetWindow(IOleInPlaceSiteEx *iface, HWND *phwnd)
819 {
820     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
821
822     TRACE("(%p)->(%p)\n", This, phwnd);
823
824     *phwnd = This->hwnd;
825     return S_OK;
826 }
827
828 static HRESULT WINAPI PHInPlaceSite_ContextSensitiveHelp(IOleInPlaceSiteEx *iface, BOOL fEnterMode)
829 {
830     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
831     FIXME("(%p)->(%x)\n", This, fEnterMode);
832     return E_NOTIMPL;
833 }
834
835 static HRESULT WINAPI PHInPlaceSite_CanInPlaceActivate(IOleInPlaceSiteEx *iface)
836 {
837     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
838     FIXME("(%p)\n", This);
839     return E_NOTIMPL;
840 }
841
842 static HRESULT WINAPI PHInPlaceSite_OnInPlaceActivate(IOleInPlaceSiteEx *iface)
843 {
844     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
845     FIXME("(%p)\n", This);
846     return E_NOTIMPL;
847 }
848
849 static HRESULT WINAPI PHInPlaceSite_OnUIActivate(IOleInPlaceSiteEx *iface)
850 {
851     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
852     DISPPARAMS args = {NULL, NULL, 0, 0};
853     IDispatch *disp;
854     ULONG err = 0;
855     VARIANT res;
856     HRESULT hres;
857
858     TRACE("(%p)\n", This);
859
860     if(!This->plugin_unk) {
861         ERR("No plugin object\n");
862         return E_UNEXPECTED;
863     }
864
865     This->ui_active = TRUE;
866
867     hres = IUnknown_QueryInterface(This->plugin_unk, &IID_IDispatch, (void**)&disp);
868     if(FAILED(hres)) {
869         FIXME("Could not get IDispatch iface: %08x\n", hres);
870         return hres;
871     }
872
873     V_VT(&res) = VT_EMPTY;
874     hres = IDispatch_Invoke(disp, DISPID_ENABLED, &IID_NULL, 0/*FIXME*/, DISPATCH_PROPERTYGET, &args, &res, NULL, &err);
875     IDispatch_Release(disp);
876     if(SUCCEEDED(hres)) {
877         FIXME("Got enabled %s\n", debugstr_variant(&res));
878         VariantClear(&res);
879     }
880
881     return S_OK;
882 }
883
884 static HRESULT WINAPI PHInPlaceSite_GetWindowContext(IOleInPlaceSiteEx *iface,
885         IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, RECT *lprcPosRect,
886         RECT *lprcClipRect, OLEINPLACEFRAMEINFO *frame_info)
887 {
888     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
889     IOleInPlaceUIWindow *ip_window;
890     IOleInPlaceFrame *ip_frame;
891     RECT pr, cr;
892     HRESULT hres;
893
894     TRACE("(%p)->(%p %p %p %p %p)\n", This, ppFrame, ppDoc, lprcPosRect, lprcClipRect, frame_info);
895
896     if(!This->doc || !This->doc->basedoc.doc_obj || !This->doc->basedoc.doc_obj->ipsite) {
897         FIXME("No ipsite\n");
898         return E_UNEXPECTED;
899     }
900
901     hres = IOleInPlaceSite_GetWindowContext(This->doc->basedoc.doc_obj->ipsite, &ip_frame, &ip_window, &pr, &cr, frame_info);
902     if(FAILED(hres)) {
903         WARN("GetWindowContext failed: %08x\n", hres);
904         return hres;
905     }
906
907     if(ip_window)
908         IOleInPlaceUIWindow_Release(ip_window);
909     if(ip_frame)
910         IOleInPlaceFrame_Release(ip_frame);
911
912     hres = create_ip_frame(&ip_frame);
913     if(FAILED(hres))
914         return hres;
915
916     hres = create_ip_window(ppDoc);
917     if(FAILED(hres))
918         return hres;
919
920     *ppFrame = ip_frame;
921     *lprcPosRect = This->rect;
922     *lprcClipRect = This->rect;
923     return S_OK;
924 }
925
926 static HRESULT WINAPI PHInPlaceSite_Scroll(IOleInPlaceSiteEx *iface, SIZE scrollExtent)
927 {
928     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
929     FIXME("(%p)->({%d %d})\n", This, scrollExtent.cx, scrollExtent.cy);
930     return E_NOTIMPL;
931 }
932
933 static HRESULT WINAPI PHInPlaceSite_OnUIDeactivate(IOleInPlaceSiteEx *iface, BOOL fUndoable)
934 {
935     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
936     FIXME("(%p)->(%x)\n", This, fUndoable);
937     return E_NOTIMPL;
938 }
939
940 static HRESULT WINAPI PHInPlaceSite_OnInPlaceDeactivate(IOleInPlaceSiteEx *iface)
941 {
942     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
943
944     TRACE("(%p)\n", This);
945
946     if(This->ip_object) {
947         IOleInPlaceObject_Release(This->ip_object);
948         This->ip_object = NULL;
949     }
950
951     return S_OK;
952 }
953
954 static HRESULT WINAPI PHInPlaceSite_DiscardUndoState(IOleInPlaceSiteEx *iface)
955 {
956     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
957     FIXME("(%p)\n", This);
958     return E_NOTIMPL;
959 }
960
961 static HRESULT WINAPI PHInPlaceSite_DeactivateAndUndo(IOleInPlaceSiteEx *iface)
962 {
963     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
964     FIXME("(%p)\n", This);
965     return E_NOTIMPL;
966 }
967
968 static HRESULT WINAPI PHInPlaceSite_OnPosRectChange(IOleInPlaceSiteEx *iface, LPCRECT lprcPosRect)
969 {
970     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
971     FIXME("(%p)->(%p)\n", This, lprcPosRect);
972     return E_NOTIMPL;
973 }
974
975 static HRESULT WINAPI PHInPlaceSiteEx_OnInPlaceActivateEx(IOleInPlaceSiteEx *iface, BOOL *pfNoRedraw, DWORD dwFlags)
976 {
977     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
978     HWND hwnd;
979     HRESULT hres;
980
981     TRACE("(%p)->(%p %x)\n", This, pfNoRedraw, dwFlags);
982
983     if(This->ip_object)
984         return S_OK;
985
986     hres = IUnknown_QueryInterface(This->plugin_unk, &IID_IOleInPlaceObject, (void**)&This->ip_object);
987     if(FAILED(hres))
988         return hres;
989
990     hres = IOleInPlaceObject_GetWindow(This->ip_object, &hwnd);
991     if(SUCCEEDED(hres))
992         FIXME("Use hwnd %p\n", hwnd);
993
994     *pfNoRedraw = FALSE;
995     return S_OK;
996 }
997
998 static HRESULT WINAPI PHInPlaceSiteEx_OnInPlaceDeactivateEx(IOleInPlaceSiteEx *iface, BOOL fNoRedraw)
999 {
1000     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1001     FIXME("(%p)->(%x)\n", This, fNoRedraw);
1002     return E_NOTIMPL;
1003 }
1004
1005 static HRESULT WINAPI PHInPlaceSiteEx_RequestUIActivate(IOleInPlaceSiteEx *iface)
1006 {
1007     PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1008     FIXME("(%p)\n", This);
1009     return E_NOTIMPL;
1010 }
1011
1012 static const IOleInPlaceSiteExVtbl OleInPlaceSiteExVtbl = {
1013     PHInPlaceSite_QueryInterface,
1014     PHInPlaceSite_AddRef,
1015     PHInPlaceSite_Release,
1016     PHInPlaceSite_GetWindow,
1017     PHInPlaceSite_ContextSensitiveHelp,
1018     PHInPlaceSite_CanInPlaceActivate,
1019     PHInPlaceSite_OnInPlaceActivate,
1020     PHInPlaceSite_OnUIActivate,
1021     PHInPlaceSite_GetWindowContext,
1022     PHInPlaceSite_Scroll,
1023     PHInPlaceSite_OnUIDeactivate,
1024     PHInPlaceSite_OnInPlaceDeactivate,
1025     PHInPlaceSite_DiscardUndoState,
1026     PHInPlaceSite_DeactivateAndUndo,
1027     PHInPlaceSite_OnPosRectChange,
1028     PHInPlaceSiteEx_OnInPlaceActivateEx,
1029     PHInPlaceSiteEx_OnInPlaceDeactivateEx,
1030     PHInPlaceSiteEx_RequestUIActivate
1031 };
1032
1033 static inline PluginHost *impl_from_IOleControlSite(IOleControlSite *iface)
1034 {
1035     return CONTAINING_RECORD(iface, PluginHost, IOleControlSite_iface);
1036 }
1037
1038 static HRESULT WINAPI PHControlSite_QueryInterface(IOleControlSite *iface, REFIID riid, void **ppv)
1039 {
1040     PluginHost *This = impl_from_IOleControlSite(iface);
1041     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1042 }
1043
1044 static ULONG WINAPI PHControlSite_AddRef(IOleControlSite *iface)
1045 {
1046     PluginHost *This = impl_from_IOleControlSite(iface);
1047     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1048 }
1049
1050 static ULONG WINAPI PHControlSite_Release(IOleControlSite *iface)
1051 {
1052     PluginHost *This = impl_from_IOleControlSite(iface);
1053     return IOleClientSite_Release(&This->IOleClientSite_iface);
1054 }
1055
1056 static HRESULT WINAPI PHControlSite_OnControlInfoChanged(IOleControlSite *iface)
1057 {
1058     PluginHost *This = impl_from_IOleControlSite(iface);
1059     FIXME("(%p)\n", This);
1060     return E_NOTIMPL;
1061 }
1062
1063 static HRESULT WINAPI PHControlSite_LockInPlaceActive(IOleControlSite *iface, BOOL fLock)
1064 {
1065     PluginHost *This = impl_from_IOleControlSite(iface);
1066     FIXME("(%p)->(%x)\n", This, fLock);
1067     return E_NOTIMPL;
1068 }
1069
1070 static HRESULT WINAPI PHControlSite_GetExtendedControl(IOleControlSite *iface, IDispatch **ppDisp)
1071 {
1072     PluginHost *This = impl_from_IOleControlSite(iface);
1073     FIXME("(%p)->(%p)\n", This, ppDisp);
1074     return E_NOTIMPL;
1075 }
1076
1077 static HRESULT WINAPI PHControlSite_TransformCoords(IOleControlSite *iface, POINTL *pPtlHimetric, POINTF *pPtfContainer, DWORD dwFlags)
1078 {
1079     PluginHost *This = impl_from_IOleControlSite(iface);
1080     FIXME("(%p)->(%p %p %x)\n", This, pPtlHimetric, pPtfContainer, dwFlags);
1081     return E_NOTIMPL;
1082 }
1083
1084 static HRESULT WINAPI PHControlSite_TranslateAccelerator(IOleControlSite *iface, MSG *pMsg, DWORD grfModifiers)
1085 {
1086     PluginHost *This = impl_from_IOleControlSite(iface);
1087     FIXME("(%p)->(%x)\n", This, grfModifiers);
1088     return E_NOTIMPL;
1089 }
1090
1091 static HRESULT WINAPI PHControlSite_OnFocus(IOleControlSite *iface, BOOL fGotFocus)
1092 {
1093     PluginHost *This = impl_from_IOleControlSite(iface);
1094     FIXME("(%p)->(%x)\n", This, fGotFocus);
1095     return E_NOTIMPL;
1096 }
1097
1098 static HRESULT WINAPI PHControlSite_ShowPropertyFrame(IOleControlSite *iface)
1099 {
1100     PluginHost *This = impl_from_IOleControlSite(iface);
1101     FIXME("(%p)\n", This);
1102     return E_NOTIMPL;
1103 }
1104
1105 static const IOleControlSiteVtbl OleControlSiteVtbl = {
1106     PHControlSite_QueryInterface,
1107     PHControlSite_AddRef,
1108     PHControlSite_Release,
1109     PHControlSite_OnControlInfoChanged,
1110     PHControlSite_LockInPlaceActive,
1111     PHControlSite_GetExtendedControl,
1112     PHControlSite_TransformCoords,
1113     PHControlSite_TranslateAccelerator,
1114     PHControlSite_OnFocus,
1115     PHControlSite_ShowPropertyFrame
1116 };
1117
1118 static inline PluginHost *impl_from_IBindHost(IBindHost *iface)
1119 {
1120     return CONTAINING_RECORD(iface, PluginHost, IBindHost_iface);
1121 }
1122
1123 static HRESULT WINAPI PHBindHost_QueryInterface(IBindHost *iface, REFIID riid, void **ppv)
1124 {
1125     PluginHost *This = impl_from_IBindHost(iface);
1126     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1127 }
1128
1129 static ULONG WINAPI PHBindHost_AddRef(IBindHost *iface)
1130 {
1131     PluginHost *This = impl_from_IBindHost(iface);
1132     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1133 }
1134
1135 static ULONG WINAPI PHBindHost_Release(IBindHost *iface)
1136 {
1137     PluginHost *This = impl_from_IBindHost(iface);
1138     return IOleClientSite_Release(&This->IOleClientSite_iface);
1139 }
1140
1141 static HRESULT WINAPI PHBindHost_CreateMoniker(IBindHost *iface, LPOLESTR szName, IBindCtx *pBC, IMoniker **ppmk, DWORD dwReserved)
1142 {
1143     PluginHost *This = impl_from_IBindHost(iface);
1144
1145     TRACE("(%p)->(%s %p %p %x)\n", This, debugstr_w(szName), pBC, ppmk, dwReserved);
1146
1147     if(!This->doc || !This->doc->basedoc.window || !This->doc->basedoc.window->mon) {
1148         FIXME("no moniker\n");
1149         return E_UNEXPECTED;
1150     }
1151
1152     return CreateURLMoniker(This->doc->basedoc.window->mon, szName, ppmk);
1153 }
1154
1155 static HRESULT WINAPI PHBindHost_MonikerBindToStorage(IBindHost *iface, IMoniker *pMk, IBindCtx *pBC,
1156         IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
1157 {
1158     PluginHost *This = impl_from_IBindHost(iface);
1159     FIXME("(%p)->(%p %p %p %s %p)\n", This, pMk, pBC, pBSC, debugstr_guid(riid), ppvObj);
1160     return E_NOTIMPL;
1161 }
1162
1163 static HRESULT WINAPI PHBindHost_MonikerBindToObject(IBindHost *iface, IMoniker *pMk, IBindCtx *pBC,
1164         IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
1165 {
1166     PluginHost *This = impl_from_IBindHost(iface);
1167     FIXME("(%p)->(%p %p %p %s %p)\n", This, pMk, pBC, pBSC, debugstr_guid(riid), ppvObj);
1168     return E_NOTIMPL;
1169 }
1170
1171 static const IBindHostVtbl BindHostVtbl = {
1172     PHBindHost_QueryInterface,
1173     PHBindHost_AddRef,
1174     PHBindHost_Release,
1175     PHBindHost_CreateMoniker,
1176     PHBindHost_MonikerBindToStorage,
1177     PHBindHost_MonikerBindToObject
1178 };
1179
1180 static inline PluginHost *impl_from_IServiceProvider(IServiceProvider *iface)
1181 {
1182     return CONTAINING_RECORD(iface, PluginHost, IServiceProvider_iface);
1183 }
1184
1185 static HRESULT WINAPI PHServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
1186 {
1187     PluginHost *This = impl_from_IServiceProvider(iface);
1188     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1189 }
1190
1191 static ULONG WINAPI PHServiceProvider_AddRef(IServiceProvider *iface)
1192 {
1193     PluginHost *This = impl_from_IServiceProvider(iface);
1194     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1195 }
1196
1197 static ULONG WINAPI PHServiceProvider_Release(IServiceProvider *iface)
1198 {
1199     PluginHost *This = impl_from_IServiceProvider(iface);
1200     return IOleClientSite_Release(&This->IOleClientSite_iface);
1201 }
1202
1203 static HRESULT WINAPI PHServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService, REFIID riid, void **ppv)
1204 {
1205     PluginHost *This = impl_from_IServiceProvider(iface);
1206
1207     if(IsEqualGUID(guidService, &SID_SBindHost)) {
1208         TRACE("SID_SBindHost service\n");
1209         return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1210     }
1211
1212     TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
1213
1214     if(!This->doc || !This->doc->basedoc.window) {
1215         *ppv = NULL;
1216         return E_NOINTERFACE;
1217     }
1218
1219     return IServiceProvider_QueryService(&This->doc->basedoc.window->IServiceProvider_iface,
1220             guidService, riid, ppv);
1221 }
1222
1223 static const IServiceProviderVtbl ServiceProviderVtbl = {
1224     PHServiceProvider_QueryInterface,
1225     PHServiceProvider_AddRef,
1226     PHServiceProvider_Release,
1227     PHServiceProvider_QueryService
1228 };
1229
1230 static HRESULT assoc_element(PluginHost *host, HTMLDocumentNode *doc, nsIDOMElement *nselem)
1231 {
1232     HTMLPluginContainer *container_elem;
1233     HTMLDOMNode *node;
1234     HRESULT hres;
1235
1236     hres = get_node(doc, (nsIDOMNode*)nselem, TRUE, &node);
1237     if(FAILED(hres))
1238         return hres;
1239
1240     hres = IHTMLDOMNode_QueryInterface(&node->IHTMLDOMNode_iface, &IID_HTMLPluginContainer,
1241             (void**)&container_elem);
1242     if(FAILED(hres)) {
1243         ERR("Not an object element\n");
1244         return hres;
1245     }
1246
1247     container_elem->plugin_host = host;
1248     host->element = container_elem;
1249     return S_OK;
1250 }
1251
1252 void detach_plugin_host(PluginHost *host)
1253 {
1254     HRESULT hres;
1255
1256     TRACE("%p\n", host);
1257
1258     if(!host->doc)
1259         return;
1260
1261     if(host->ip_object) {
1262         if(host->ui_active)
1263             IOleInPlaceObject_UIDeactivate(host->ip_object);
1264         IOleInPlaceObject_InPlaceDeactivate(host->ip_object);
1265     }
1266
1267     if(host->plugin_unk) {
1268         IOleObject *ole_obj;
1269
1270         hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleObject, (void**)&ole_obj);
1271         if(SUCCEEDED(hres)) {
1272             if(!host->ip_object)
1273                 IOleObject_Close(ole_obj, OLECLOSE_NOSAVE);
1274             IOleObject_SetClientSite(ole_obj, NULL);
1275             IOleObject_Release(ole_obj);
1276         }
1277     }
1278
1279     if(host->element) {
1280         host->element->plugin_host = NULL;
1281         host->element = NULL;
1282     }
1283
1284     list_remove(&host->entry);
1285     list_init(&host->entry);
1286     host->doc = NULL;
1287 }
1288
1289 HRESULT create_plugin_host(HTMLDocumentNode *doc, nsIDOMElement *nselem, IUnknown *unk, const CLSID *clsid, PluginHost **ret)
1290 {
1291     PluginHost *host;
1292     HRESULT hres;
1293
1294     host = heap_alloc_zero(sizeof(*host));
1295     if(!host)
1296         return E_OUTOFMEMORY;
1297
1298     host->IOleClientSite_iface.lpVtbl      = &OleClientSiteVtbl;
1299     host->IAdviseSinkEx_iface.lpVtbl       = &AdviseSinkExVtbl;
1300     host->IPropertyNotifySink_iface.lpVtbl = &PropertyNotifySinkVtbl;
1301     host->IDispatch_iface.lpVtbl           = &DispatchVtbl;
1302     host->IOleInPlaceSiteEx_iface.lpVtbl   = &OleInPlaceSiteExVtbl;
1303     host->IOleControlSite_iface.lpVtbl     = &OleControlSiteVtbl;
1304     host->IBindHost_iface.lpVtbl           = &BindHostVtbl;
1305     host->IServiceProvider_iface.lpVtbl    = &ServiceProviderVtbl;
1306
1307     host->ref = 1;
1308
1309     hres = assoc_element(host, doc, nselem);
1310     if(FAILED(hres)) {
1311         heap_free(host);
1312         return hres;
1313     }
1314
1315     IUnknown_AddRef(unk);
1316     host->plugin_unk = unk;
1317     host->clsid = *clsid;
1318
1319     host->doc = doc;
1320     list_add_tail(&doc->plugin_hosts, &host->entry);
1321
1322     *ret = host;
1323     return S_OK;
1324 }