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