imagehlp: Use the IMAGE_FIRST_SECTION helper macro.
[wine.git] / dlls / mshtml / pluginhost.c
blobf910600de180273dbf9cf268747b49af5c8f35c7
1 /*
2 * Copyright 2010 Jacek Caban for CodeWeavers
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.
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.
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
19 #include <stdarg.h>
21 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "ole2.h"
27 #include "shlobj.h"
28 #include "mshtmdid.h"
30 #include "mshtml_private.h"
31 #include "pluginhost.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
37 typedef struct {
38 IPropertyBag IPropertyBag_iface;
39 IPropertyBag2 IPropertyBag2_iface;
41 LONG ref;
43 struct list props;
44 } PropertyBag;
46 typedef struct {
47 struct list entry;
48 WCHAR *name;
49 WCHAR *value;
50 } param_prop_t;
52 static void free_prop(param_prop_t *prop)
54 list_remove(&prop->entry);
56 free(prop->name);
57 free(prop->value);
58 free(prop);
61 static param_prop_t *find_prop(PropertyBag *prop_bag, const WCHAR *name)
63 param_prop_t *iter;
65 LIST_FOR_EACH_ENTRY(iter, &prop_bag->props, param_prop_t, entry) {
66 if(!wcsicmp(iter->name, name))
67 return iter;
70 return NULL;
73 static HRESULT add_prop(PropertyBag *prop_bag, const WCHAR *name, const WCHAR *value)
75 param_prop_t *prop;
77 if(!name || !value)
78 return S_OK;
80 TRACE("%p %s %s\n", prop_bag, debugstr_w(name), debugstr_w(value));
82 prop = malloc(sizeof(*prop));
83 if(!prop)
84 return E_OUTOFMEMORY;
86 prop->name = wcsdup(name);
87 prop->value = wcsdup(value);
88 if(!prop->name || !prop->value) {
89 list_init(&prop->entry);
90 free_prop(prop);
91 return E_OUTOFMEMORY;
94 list_add_tail(&prop_bag->props, &prop->entry);
95 return S_OK;
98 static inline PropertyBag *impl_from_IPropertyBag(IPropertyBag *iface)
100 return CONTAINING_RECORD(iface, PropertyBag, IPropertyBag_iface);
103 static HRESULT WINAPI PropertyBag_QueryInterface(IPropertyBag *iface, REFIID riid, void **ppv)
105 PropertyBag *This = impl_from_IPropertyBag(iface);
107 if(IsEqualGUID(&IID_IUnknown, riid)) {
108 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
109 *ppv = &This->IPropertyBag_iface;
110 }else if(IsEqualGUID(&IID_IPropertyBag, riid)) {
111 TRACE("(%p)->(IID_IPropertyBag %p)\n", This, ppv);
112 *ppv = &This->IPropertyBag_iface;
113 }else if(IsEqualGUID(&IID_IPropertyBag2, riid)) {
114 TRACE("(%p)->(IID_IPropertyBag2 %p)\n", This, ppv);
115 *ppv = &This->IPropertyBag2_iface;
116 }else {
117 WARN("Unsopported interface %s\n", debugstr_guid(riid));
118 *ppv = NULL;
119 return E_NOINTERFACE;
122 IUnknown_AddRef((IUnknown*)*ppv);
123 return S_OK;
126 static ULONG WINAPI PropertyBag_AddRef(IPropertyBag *iface)
128 PropertyBag *This = impl_from_IPropertyBag(iface);
129 LONG ref = InterlockedIncrement(&This->ref);
131 TRACE("(%p) ref=%ld\n", This, ref);
133 return ref;
136 static ULONG WINAPI PropertyBag_Release(IPropertyBag *iface)
138 PropertyBag *This = impl_from_IPropertyBag(iface);
139 LONG ref = InterlockedDecrement(&This->ref);
141 TRACE("(%p) ref=%ld\n", This, ref);
143 if(!ref) {
144 while(!list_empty(&This->props))
145 free_prop(LIST_ENTRY(This->props.next, param_prop_t, entry));
146 free(This);
149 return ref;
152 static HRESULT WINAPI PropertyBag_Read(IPropertyBag *iface, LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog)
154 PropertyBag *This = impl_from_IPropertyBag(iface);
155 param_prop_t *prop;
156 VARIANT v;
158 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog);
160 prop = find_prop(This, pszPropName);
161 if(!prop) {
162 TRACE("Not found\n");
163 return E_INVALIDARG;
166 V_BSTR(&v) = SysAllocString(prop->value);
167 if(!V_BSTR(&v))
168 return E_OUTOFMEMORY;
170 if(V_VT(pVar) != VT_BSTR) {
171 HRESULT hres;
173 V_VT(&v) = VT_BSTR;
174 hres = VariantChangeType(pVar, &v, 0, V_VT(pVar));
175 SysFreeString(V_BSTR(&v));
176 return hres;
179 V_BSTR(pVar) = V_BSTR(&v);
180 return S_OK;
183 static HRESULT WINAPI PropertyBag_Write(IPropertyBag *iface, LPCOLESTR pszPropName, VARIANT *pVar)
185 PropertyBag *This = impl_from_IPropertyBag(iface);
186 FIXME("(%p)->(%s %s)\n", This, debugstr_w(pszPropName), debugstr_variant(pVar));
187 return E_NOTIMPL;
190 static const IPropertyBagVtbl PropertyBagVtbl = {
191 PropertyBag_QueryInterface,
192 PropertyBag_AddRef,
193 PropertyBag_Release,
194 PropertyBag_Read,
195 PropertyBag_Write
198 static inline PropertyBag *impl_from_IPropertyBag2(IPropertyBag2 *iface)
200 return CONTAINING_RECORD(iface, PropertyBag, IPropertyBag2_iface);
203 static HRESULT WINAPI PropertyBag2_QueryInterface(IPropertyBag2 *iface, REFIID riid, void **ppv)
205 PropertyBag *This = impl_from_IPropertyBag2(iface);
206 return IPropertyBag_QueryInterface(&This->IPropertyBag_iface, riid, ppv);
209 static ULONG WINAPI PropertyBag2_AddRef(IPropertyBag2 *iface)
211 PropertyBag *This = impl_from_IPropertyBag2(iface);
212 return IPropertyBag_AddRef(&This->IPropertyBag_iface);
215 static ULONG WINAPI PropertyBag2_Release(IPropertyBag2 *iface)
217 PropertyBag *This = impl_from_IPropertyBag2(iface);
218 return IPropertyBag_Release(&This->IPropertyBag_iface);
221 static HRESULT WINAPI PropertyBag2_Read(IPropertyBag2 *iface, ULONG cProperties, PROPBAG2 *pPropBag,
222 IErrorLog *pErrLog, VARIANT *pvarValue, HRESULT *phrError)
224 PropertyBag *This = impl_from_IPropertyBag2(iface);
225 FIXME("(%p)->(%ld %p %p %p %p)\n", This, cProperties, pPropBag, pErrLog, pvarValue, phrError);
226 return E_NOTIMPL;
229 static HRESULT WINAPI PropertyBag2_Write(IPropertyBag2 *iface, ULONG cProperties, PROPBAG2 *pPropBag, VARIANT *pvarValue)
231 PropertyBag *This = impl_from_IPropertyBag2(iface);
232 FIXME("(%p)->(%ld %p %s)\n", This, cProperties, pPropBag, debugstr_variant(pvarValue));
233 return E_NOTIMPL;
236 static HRESULT WINAPI PropertyBag2_CountProperties(IPropertyBag2 *iface, ULONG *pcProperties)
238 PropertyBag *This = impl_from_IPropertyBag2(iface);
239 FIXME("(%p)->(%p)\n", This, pcProperties);
240 return E_NOTIMPL;
243 static HRESULT WINAPI PropertyBag2_GetPropertyInfo(IPropertyBag2 *iface, ULONG iProperty, ULONG cProperties,
244 PROPBAG2 *pPropBag, ULONG *pcProperties)
246 PropertyBag *This = impl_from_IPropertyBag2(iface);
247 FIXME("(%p)->(%lu %lu %p %p)\n", This, iProperty, cProperties, pPropBag, pcProperties);
248 return E_NOTIMPL;
251 static HRESULT WINAPI PropertyBag2_LoadObject(IPropertyBag2 *iface, LPCOLESTR pstrName, DWORD dwHint,
252 IUnknown *pUnkObject, IErrorLog *pErrLog)
254 PropertyBag *This = impl_from_IPropertyBag2(iface);
255 FIXME("(%p)->(%s %lx %p %p)\n", This, debugstr_w(pstrName), dwHint, pUnkObject, pErrLog);
256 return E_NOTIMPL;
259 static const IPropertyBag2Vtbl PropertyBag2Vtbl = {
260 PropertyBag2_QueryInterface,
261 PropertyBag2_AddRef,
262 PropertyBag2_Release,
263 PropertyBag2_Read,
264 PropertyBag2_Write,
265 PropertyBag2_CountProperties,
266 PropertyBag2_GetPropertyInfo,
267 PropertyBag2_LoadObject
270 static HRESULT fill_props(nsIDOMElement *nselem, PropertyBag *prop_bag)
272 const PRUnichar *name, *value;
273 nsAString name_str, value_str;
274 nsIDOMHTMLCollection *params;
275 nsIDOMElement *param_elem;
276 UINT32 length, i;
277 nsIDOMNode *nsnode;
278 nsresult nsres;
279 HRESULT hres = S_OK;
281 nsAString_InitDepend(&name_str, L"param");
282 nsres = nsIDOMElement_GetElementsByTagName(nselem, &name_str, &params);
283 nsAString_Finish(&name_str);
284 if(NS_FAILED(nsres))
285 return E_FAIL;
287 nsres = nsIDOMHTMLCollection_GetLength(params, &length);
288 if(NS_FAILED(nsres))
289 length = 0;
291 for(i=0; i < length; i++) {
292 nsres = nsIDOMHTMLCollection_Item(params, i, &nsnode);
293 if(NS_FAILED(nsres)) {
294 hres = E_FAIL;
295 break;
298 nsres = nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMElement, (void**)&param_elem);
299 nsIDOMNode_Release(nsnode);
300 if(NS_FAILED(nsres)) {
301 hres = E_FAIL;
302 break;
305 nsres = get_elem_attr_value(param_elem, L"name", &name_str, &name);
306 if(NS_SUCCEEDED(nsres)) {
307 nsres = get_elem_attr_value(param_elem, L"value", &value_str, &value);
308 if(NS_SUCCEEDED(nsres)) {
309 hres = add_prop(prop_bag, name, value);
310 nsAString_Finish(&value_str);
313 nsAString_Finish(&name_str);
316 nsIDOMElement_Release(param_elem);
317 if(FAILED(hres))
318 break;
319 if(NS_FAILED(nsres)) {
320 hres = E_FAIL;
321 break;
325 nsIDOMHTMLCollection_Release(params);
326 return hres;
329 static HRESULT create_param_prop_bag(nsIDOMElement *nselem, IPropertyBag **ret)
331 PropertyBag *prop_bag;
332 HRESULT hres;
334 prop_bag = malloc(sizeof(*prop_bag));
335 if(!prop_bag)
336 return E_OUTOFMEMORY;
338 prop_bag->IPropertyBag_iface.lpVtbl = &PropertyBagVtbl;
339 prop_bag->IPropertyBag2_iface.lpVtbl = &PropertyBag2Vtbl;
340 prop_bag->ref = 1;
342 list_init(&prop_bag->props);
343 hres = fill_props(nselem, prop_bag);
344 if(FAILED(hres) || list_empty(&prop_bag->props)) {
345 IPropertyBag_Release(&prop_bag->IPropertyBag_iface);
346 *ret = NULL;
347 return hres;
350 *ret = &prop_bag->IPropertyBag_iface;
351 return S_OK;
354 static BOOL check_load_safety(PluginHost *host)
356 DWORD policy_size, policy;
357 struct CONFIRMSAFETY cs;
358 BYTE *ppolicy;
359 HRESULT hres;
361 cs.clsid = host->clsid;
362 cs.pUnk = host->plugin_unk;
363 cs.dwFlags = CONFIRMSAFETYACTION_LOADOBJECT;
365 hres = IInternetHostSecurityManager_QueryCustomPolicy(&host->doc->IInternetHostSecurityManager_iface,
366 &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
367 if(FAILED(hres))
368 return FALSE;
370 policy = *(DWORD*)ppolicy;
371 CoTaskMemFree(ppolicy);
372 return policy == URLPOLICY_ALLOW;
375 static BOOL check_script_safety(PluginHost *host)
377 DISPPARAMS params = {NULL,NULL,0,0};
378 DWORD policy_size, policy;
379 struct CONFIRMSAFETY cs;
380 BYTE *ppolicy;
381 UINT err = 0;
382 VARIANT v;
383 HRESULT hres;
385 cs.clsid = host->clsid;
386 cs.pUnk = host->plugin_unk;
387 cs.dwFlags = 0;
389 hres = IInternetHostSecurityManager_QueryCustomPolicy(&host->doc->IInternetHostSecurityManager_iface,
390 &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
391 if(FAILED(hres))
392 return FALSE;
394 policy = *(DWORD*)ppolicy;
395 CoTaskMemFree(ppolicy);
397 if(policy != URLPOLICY_ALLOW)
398 return FALSE;
400 V_VT(&v) = VT_EMPTY;
401 hres = IDispatch_Invoke(host->disp, DISPID_SECURITYCTX, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, &v, NULL, &err);
402 if(SUCCEEDED(hres)) {
403 FIXME("Handle security ctx %s\n", debugstr_variant(&v));
404 return FALSE;
407 return TRUE;
410 static void update_readystate(PluginHost *host)
412 DISPPARAMS params = {NULL,NULL,0,0};
413 IDispatchEx *dispex;
414 IDispatch *disp;
415 UINT err = 0;
416 VARIANT v;
417 HRESULT hres;
419 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatchEx, (void**)&dispex);
420 if(SUCCEEDED(hres)) {
421 FIXME("Use IDispatchEx\n");
422 IDispatchEx_Release(dispex);
425 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatch, (void**)&disp);
426 if(FAILED(hres))
427 return;
429 hres = IDispatch_Invoke(disp, DISPID_READYSTATE, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, &v, NULL, &err);
430 IDispatch_Release(disp);
431 if(SUCCEEDED(hres)) {
432 /* FIXME: make plugin readystate affect document readystate */
433 TRACE("readystate = %s\n", debugstr_variant(&v));
434 VariantClear(&v);
438 /* FIXME: We shouldn't need this function and we should embed plugin directly in the main document */
439 static void get_pos_rect(PluginHost *host, RECT *ret)
441 SetRect(ret, 0, 0, host->rect.right - host->rect.left, host->rect.bottom - host->rect.top);
444 static void load_prop_bag(PluginHost *host, IPersistPropertyBag *persist_prop_bag)
446 IPropertyBag *prop_bag;
447 HRESULT hres;
449 hres = create_param_prop_bag(host->element->element.dom_element, &prop_bag);
450 if(FAILED(hres))
451 return;
453 if(prop_bag && !check_load_safety(host)) {
454 IPropertyBag_Release(prop_bag);
455 prop_bag = NULL;
458 if(prop_bag) {
459 hres = IPersistPropertyBag_Load(persist_prop_bag, prop_bag, NULL);
460 IPropertyBag_Release(prop_bag);
461 if(FAILED(hres))
462 WARN("Load failed: %08lx\n", hres);
463 }else {
464 hres = IPersistPropertyBag_InitNew(persist_prop_bag);
465 if(FAILED(hres))
466 WARN("InitNew failed: %08lx\n", hres);
470 static void load_plugin(PluginHost *host)
472 IPersistPropertyBag2 *persist_prop_bag2;
473 IPersistPropertyBag *persist_prop_bag;
474 HRESULT hres;
476 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IPersistPropertyBag2, (void**)&persist_prop_bag2);
477 if(SUCCEEDED(hres)) {
478 FIXME("Use IPersistPropertyBag2 iface\n");
479 IPersistPropertyBag2_Release(persist_prop_bag2);
480 return;
483 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IPersistPropertyBag, (void**)&persist_prop_bag);
484 if(SUCCEEDED(hres)) {
485 load_prop_bag(host, persist_prop_bag);
486 IPersistPropertyBag_Release(persist_prop_bag);
487 return;
490 FIXME("No IPersistPropertyBag iface\n");
493 static void initialize_plugin_object(PluginHost *host)
495 IClientSecurity *client_security;
496 IQuickActivate *quick_activate;
497 IOleObject *ole_obj = NULL;
498 IOleCommandTarget *cmdtrg;
499 IViewObjectEx *view_obj;
500 IDispatchEx *dispex;
501 IDispatch *disp;
502 HRESULT hres;
504 /* Note native calls QI on plugin for an undocumented IID and CLSID_HTMLDocument */
506 /* FIXME: call FreezeEvents(TRUE) */
508 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IClientSecurity, (void**)&client_security);
509 if(SUCCEEDED(hres)) {
510 FIXME("Handle IClientSecurity\n");
511 IClientSecurity_Release(client_security);
512 return;
515 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IQuickActivate, (void**)&quick_activate);
516 if(SUCCEEDED(hres)) {
517 QACONTAINER container = {sizeof(container)};
518 QACONTROL control = {sizeof(control)};
520 TRACE("Using IQuickActivate\n");
522 container.pClientSite = &host->IOleClientSite_iface;
523 container.dwAmbientFlags = QACONTAINER_SUPPORTSMNEMONICS|QACONTAINER_MESSAGEREFLECT|QACONTAINER_USERMODE;
524 container.pAdviseSink = &host->IAdviseSinkEx_iface;
525 container.pPropertyNotifySink = &host->IPropertyNotifySink_iface;
527 hres = IQuickActivate_QuickActivate(quick_activate, &container, &control);
528 IQuickActivate_Release(quick_activate);
529 if(FAILED(hres))
530 FIXME("QuickActivate failed: %08lx\n", hres);
531 }else {
532 DWORD status = 0;
534 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleObject, (void**)&ole_obj);
535 if(SUCCEEDED(hres)) {
536 hres = IOleObject_GetMiscStatus(ole_obj, DVASPECT_CONTENT, &status);
537 TRACE("GetMiscStatus returned %08lx %lx\n", hres, status);
539 hres = IOleObject_SetClientSite(ole_obj, &host->IOleClientSite_iface);
540 IOleObject_Release(ole_obj);
541 if(FAILED(hres)) {
542 FIXME("SetClientSite failed: %08lx\n", hres);
543 return;
545 }else {
546 TRACE("Plugin does not support IOleObject\n");
550 load_plugin(host);
552 if(ole_obj) {
553 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IViewObjectEx, (void**)&view_obj);
554 if(SUCCEEDED(hres)) {
555 DWORD view_status = 0;
557 hres = IViewObjectEx_SetAdvise(view_obj, DVASPECT_CONTENT, 0, (IAdviseSink*)&host->IAdviseSinkEx_iface);
558 if(FAILED(hres))
559 WARN("SetAdvise failed: %08lx\n", hres);
561 hres = IViewObjectEx_GetViewStatus(view_obj, &view_status);
562 IViewObjectEx_Release(view_obj);
563 TRACE("GetViewStatus returned %08lx %lx\n", hres, view_status);
567 update_readystate(host);
569 /* NOTE: Native QIs for IActiveScript, an undocumented IID, IOleControl and IRunnableObject */
571 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatchEx, (void**)&dispex);
572 if(SUCCEEDED(hres)) {
573 FIXME("Use IDispatchEx\n");
574 host->disp = (IDispatch*)dispex;
575 }else {
576 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatch, (void**)&disp);
577 if(SUCCEEDED(hres))
578 host->disp = disp;
579 else
580 TRACE("no IDispatch iface\n");
583 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleCommandTarget, (void**)&cmdtrg);
584 if(SUCCEEDED(hres)) {
585 FIXME("Use IOleCommandTarget\n");
586 IOleCommandTarget_Release(cmdtrg);
590 static void embed_plugin_object(PluginHost *host)
592 IOleObject *ole_obj;
593 RECT rect;
594 HRESULT hres;
596 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleObject, (void**)&ole_obj);
597 if(FAILED(hres)) {
598 FIXME("Plugin does not support IOleObject\n");
599 return;
602 get_pos_rect(host, &rect);
603 hres = IOleObject_DoVerb(ole_obj, OLEIVERB_INPLACEACTIVATE, NULL, &host->IOleClientSite_iface, 0, host->hwnd, &rect);
604 IOleObject_Release(ole_obj);
605 if(FAILED(hres))
606 WARN("DoVerb failed: %08lx\n", hres);
608 if(host->ip_object) {
609 HWND hwnd;
611 hres = IOleInPlaceObject_GetWindow(host->ip_object, &hwnd);
612 if(SUCCEEDED(hres))
613 TRACE("hwnd %p\n", hwnd);
617 void update_plugin_window(PluginHost *host, HWND hwnd, const RECT *rect)
619 BOOL rect_changed = FALSE;
621 if(!hwnd || (host->hwnd && host->hwnd != hwnd)) {
622 FIXME("unhandled hwnd\n");
623 return;
626 TRACE("%p %s\n", hwnd, wine_dbgstr_rect(rect));
628 if(!EqualRect(rect, &host->rect)) {
629 host->rect = *rect;
630 rect_changed = TRUE;
633 if(!host->hwnd) {
634 host->hwnd = hwnd;
635 embed_plugin_object(host);
638 if(rect_changed && host->ip_object)
639 IOleInPlaceObject_SetObjectRects(host->ip_object, &host->rect, &host->rect);
642 static void notif_enabled(PluginHost *plugin_host)
644 DISPPARAMS args = {NULL, NULL, 0, 0};
645 IDispatch *disp;
646 UINT err = 0;
647 VARIANT res;
648 HRESULT hres;
650 hres = IUnknown_QueryInterface(plugin_host->plugin_unk, &IID_IDispatch, (void**)&disp);
651 if(FAILED(hres)) {
652 FIXME("Could not get IDispatch iface: %08lx\n", hres);
653 return;
656 V_VT(&res) = VT_EMPTY;
657 hres = IDispatch_Invoke(disp, DISPID_ENABLED, &IID_NULL, 0/*FIXME*/, DISPATCH_PROPERTYGET, &args, &res, NULL, &err);
658 IDispatch_Release(disp);
659 if(SUCCEEDED(hres)) {
660 FIXME("Got enabled %s\n", debugstr_variant(&res));
661 VariantClear(&res);
665 void notif_container_change(HTMLPluginContainer *plugin_container, DISPID dispid)
667 IOleControl *ole_control;
668 HRESULT hres;
670 if(!plugin_container->plugin_host || !plugin_container->plugin_host->plugin_unk)
671 return;
673 notif_enabled(plugin_container->plugin_host);
675 hres = IUnknown_QueryInterface(plugin_container->plugin_host->plugin_unk, &IID_IOleControl, (void**)&ole_control);
676 if(SUCCEEDED(hres)) {
677 IOleControl_OnAmbientPropertyChange(ole_control, dispid);
678 IOleControl_Release(ole_control);
682 HRESULT get_plugin_disp(HTMLPluginContainer *plugin_container, IDispatch **ret)
684 PluginHost *host;
686 host = plugin_container->plugin_host;
687 if(!host) {
688 ERR("No plugin host\n");
689 return E_UNEXPECTED;
692 if(!host->disp) {
693 *ret = NULL;
694 return S_OK;
697 if(!check_script_safety(host)) {
698 FIXME("Insecure object\n");
699 return E_FAIL;
702 IDispatch_AddRef(host->disp);
703 *ret = host->disp;
704 return S_OK;
707 HRESULT get_plugin_dispid(HTMLPluginContainer *plugin_container, WCHAR *name, DISPID *ret)
709 IDispatch *disp;
710 DISPID id;
711 DWORD i;
712 HRESULT hres;
714 if(!plugin_container->plugin_host) {
715 WARN("no plugin host\n");
716 return DISP_E_UNKNOWNNAME;
719 disp = plugin_container->plugin_host->disp;
720 if(!disp)
721 return DISP_E_UNKNOWNNAME;
723 hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, &id);
724 if(FAILED(hres)) {
725 TRACE("no prop %s\n", debugstr_w(name));
726 return DISP_E_UNKNOWNNAME;
729 for(i=0; i < plugin_container->props_len; i++) {
730 if(id == plugin_container->props[i]) {
731 *ret = MSHTML_DISPID_CUSTOM_MIN+i;
732 return S_OK;
736 if(!plugin_container->props) {
737 plugin_container->props = malloc(8 * sizeof(DISPID));
738 if(!plugin_container->props)
739 return E_OUTOFMEMORY;
740 plugin_container->props_size = 8;
741 }else if(plugin_container->props_len == plugin_container->props_size) {
742 DISPID *new_props;
744 new_props = realloc(plugin_container->props, plugin_container->props_size * 2 * sizeof(DISPID));
745 if(!new_props)
746 return E_OUTOFMEMORY;
748 plugin_container->props = new_props;
749 plugin_container->props_size *= 2;
752 plugin_container->props[plugin_container->props_len] = id;
753 *ret = MSHTML_DISPID_CUSTOM_MIN+plugin_container->props_len;
754 plugin_container->props_len++;
755 return S_OK;
758 HRESULT invoke_plugin_prop(HTMLPluginContainer *plugin_container, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
759 VARIANT *res, EXCEPINFO *ei)
761 PluginHost *host;
763 host = plugin_container->plugin_host;
764 if(!host || !host->disp) {
765 FIXME("Called with no disp\n");
766 return E_UNEXPECTED;
769 if(!check_script_safety(host)) {
770 FIXME("Insecure object\n");
771 return E_FAIL;
774 if(id < MSHTML_DISPID_CUSTOM_MIN || id > MSHTML_DISPID_CUSTOM_MIN + plugin_container->props_len) {
775 ERR("Invalid id\n");
776 return E_FAIL;
779 return IDispatch_Invoke(host->disp, plugin_container->props[id-MSHTML_DISPID_CUSTOM_MIN], &IID_NULL,
780 lcid, flags, params, res, ei, NULL);
783 typedef struct {
784 DISPID id;
785 IDispatch *disp;
786 } sink_entry_t;
788 struct PHEventSink {
789 IDispatch IDispatch_iface;
791 LONG ref;
793 PluginHost *host;
794 ITypeInfo *typeinfo;
795 GUID iid;
796 DWORD cookie;
797 BOOL is_dispiface;
799 sink_entry_t *handlers;
800 DWORD handlers_cnt;
801 DWORD handlers_size;
804 static sink_entry_t *find_sink_entry(PHEventSink *sink, DISPID id)
806 sink_entry_t *iter;
808 for(iter = sink->handlers; iter < sink->handlers+sink->handlers_cnt; iter++) {
809 if(iter->id == id)
810 return iter;
813 return NULL;
816 static void add_sink_handler(PHEventSink *sink, DISPID id, IDispatch *disp)
818 sink_entry_t *entry = find_sink_entry(sink, id);
820 if(entry) {
821 if(entry->disp)
822 IDispatch_Release(entry->disp);
823 }else {
824 if(!sink->handlers_size) {
825 sink->handlers = malloc(4 * sizeof(*sink->handlers));
826 if(!sink->handlers)
827 return;
828 sink->handlers_size = 4;
829 }else if(sink->handlers_cnt == sink->handlers_size) {
830 sink_entry_t *new_handlers;
832 new_handlers = realloc(sink->handlers, 2 * sink->handlers_size * sizeof(*sink->handlers));
833 if(!new_handlers)
834 return;
835 sink->handlers = new_handlers;
836 sink->handlers_size *= 2;
838 entry = sink->handlers + sink->handlers_cnt++;
839 entry->id = id;
842 IDispatch_AddRef(disp);
843 entry->disp = disp;
846 static inline PHEventSink *PHEventSink_from_IDispatch(IDispatch *iface)
848 return CONTAINING_RECORD(iface, PHEventSink, IDispatch_iface);
851 static HRESULT WINAPI PHEventSink_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
853 PHEventSink *This = PHEventSink_from_IDispatch(iface);
855 if(IsEqualGUID(riid, &IID_IUnknown)) {
856 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
857 *ppv = &This->IDispatch_iface;
858 }else if(IsEqualGUID(riid, &IID_IDispatch)) {
859 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
860 *ppv = &This->IDispatch_iface;
861 }else if(This->is_dispiface && IsEqualGUID(riid, &This->iid)) {
862 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
863 *ppv = &This->IDispatch_iface;
864 }else {
865 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
866 *ppv = NULL;
867 return E_NOINTERFACE;
870 IUnknown_AddRef((IUnknown*)*ppv);
871 return S_OK;
874 static ULONG WINAPI PHEventSink_AddRef(IDispatch *iface)
876 PHEventSink *This = PHEventSink_from_IDispatch(iface);
877 LONG ref = InterlockedIncrement(&This->ref);
879 TRACE("(%p)\n", This);
881 return ref;
884 static ULONG WINAPI PHEventSink_Release(IDispatch *iface)
886 PHEventSink *This = PHEventSink_from_IDispatch(iface);
887 LONG ref = InterlockedDecrement(&This->ref);
889 TRACE("(%p)\n", This);
891 if(!ref) {
892 unsigned i;
894 assert(!This->host);
896 for(i=0; i < This->handlers_cnt; i++) {
897 if(This->handlers[i].disp)
898 IDispatch_Release(This->handlers[i].disp);
900 free(This->handlers);
901 free(This);
904 return ref;
907 static HRESULT WINAPI PHEventSink_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
909 PHEventSink *This = PHEventSink_from_IDispatch(iface);
910 FIXME("(%p)->(%p)\n", This, pctinfo);
911 return E_NOTIMPL;
914 static HRESULT WINAPI PHEventSink_GetTypeInfo(IDispatch *iface, UINT iTInfo,
915 LCID lcid, ITypeInfo **ppTInfo)
917 PHEventSink *This = PHEventSink_from_IDispatch(iface);
918 FIXME("(%p)->(%d %ld %p)\n", This, iTInfo, lcid, ppTInfo);
919 return E_NOTIMPL;
922 static HRESULT WINAPI PHEventSink_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *rgszNames,
923 UINT cNames, LCID lcid, DISPID *rgDispId)
925 PHEventSink *This = PHEventSink_from_IDispatch(iface);
926 FIXME("(%p)->(%s %p %u %ld %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
927 return E_NOTIMPL;
930 static HRESULT WINAPI PHEventSink_Invoke(IDispatch *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
931 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
933 PHEventSink *This = PHEventSink_from_IDispatch(iface);
934 IDispatchEx *dispex;
935 sink_entry_t *entry;
936 HRESULT hres;
938 TRACE("(%p)->(%ld %s %ld %x %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), lcid, wFlags,
939 pDispParams, pVarResult, pExcepInfo, puArgErr);
941 if(!This->host) {
942 WARN("No host\n");
943 return E_UNEXPECTED;
946 entry = find_sink_entry(This, dispIdMember);
947 if(!entry || !entry->disp) {
948 WARN("No handler %ld\n", dispIdMember);
949 if(pVarResult)
950 V_VT(pVarResult) = VT_EMPTY;
951 return S_OK;
954 hres = IDispatch_QueryInterface(entry->disp, &IID_IDispatchEx, (void**)&dispex);
956 TRACE("(%p) %ld >>>\n", This, entry->id);
957 if(SUCCEEDED(hres)) {
958 hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, NULL);
959 IDispatchEx_Release(dispex);
960 }else {
961 hres = IDispatch_Invoke(entry->disp, DISPID_VALUE, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
963 if(SUCCEEDED(hres))
964 TRACE("(%p) %ld <<<\n", This, entry->id);
965 else
966 WARN("(%p) %ld <<< %08lx\n", This, entry->id, hres);
967 return hres;
970 static const IDispatchVtbl PHCPDispatchVtbl = {
971 PHEventSink_QueryInterface,
972 PHEventSink_AddRef,
973 PHEventSink_Release,
974 PHEventSink_GetTypeInfoCount,
975 PHEventSink_GetTypeInfo,
976 PHEventSink_GetIDsOfNames,
977 PHEventSink_Invoke
980 static PHEventSink *create_event_sink(PluginHost *plugin_host, ITypeInfo *typeinfo)
982 IConnectionPointContainer *cp_container;
983 PHEventSink *ret;
984 IConnectionPoint *cp;
985 TYPEATTR *typeattr;
986 TYPEKIND typekind;
987 GUID guid;
988 HRESULT hres;
990 hres = ITypeInfo_GetTypeAttr(typeinfo, &typeattr);
991 if(FAILED(hres))
992 return NULL;
994 typekind = typeattr->typekind;
995 guid = typeattr->guid;
996 ITypeInfo_ReleaseTypeAttr(typeinfo, typeattr);
998 TRACE("guid %s typekind %d\n", debugstr_guid(&guid), typekind);
1000 if(typekind != TKIND_INTERFACE && typekind != TKIND_DISPATCH) {
1001 WARN("invalid typekind %d\n", typekind);
1002 return NULL;
1005 hres = IUnknown_QueryInterface(plugin_host->plugin_unk, &IID_IConnectionPointContainer, (void**)&cp_container);
1006 if(FAILED(hres)) {
1007 WARN("Could not get IConnectionPointContainer iface: %08lx\n", hres);
1008 return NULL;
1011 hres = IConnectionPointContainer_FindConnectionPoint(cp_container, &guid, &cp);
1012 IConnectionPointContainer_Release(cp_container);
1013 if(FAILED(hres)) {
1014 WARN("Could not find %s connection point\n", debugstr_guid(&guid));
1015 return NULL;
1018 ret = calloc(1, sizeof(*ret));
1019 if(ret) {
1020 ret->IDispatch_iface.lpVtbl = &PHCPDispatchVtbl;
1021 ret->ref = 1;
1022 ret->host = plugin_host;
1023 ret->iid = guid;
1024 ret->is_dispiface = typekind == TKIND_DISPATCH;
1026 ITypeInfo_AddRef(typeinfo);
1027 ret->typeinfo = typeinfo;
1029 hres = IConnectionPoint_Advise(cp, (IUnknown*)&ret->IDispatch_iface, &ret->cookie);
1030 }else {
1031 hres = E_OUTOFMEMORY;
1034 IConnectionPoint_Release(cp);
1035 if(FAILED(hres)) {
1036 WARN("Advise failed: %08lx\n", hres);
1037 return NULL;
1040 return ret;
1043 static ITypeInfo *get_eventiface_info(HTMLPluginContainer *plugin_container, ITypeInfo *class_info)
1045 int impl_types, i, impl_flags;
1046 ITypeInfo *ret = NULL;
1047 TYPEATTR *typeattr;
1048 HREFTYPE ref;
1049 HRESULT hres;
1051 hres = ITypeInfo_GetTypeAttr(class_info, &typeattr);
1052 if(FAILED(hres))
1053 return NULL;
1055 if(typeattr->typekind != TKIND_COCLASS) {
1056 WARN("not coclass\n");
1057 ITypeInfo_ReleaseTypeAttr(class_info, typeattr);
1058 return NULL;
1061 impl_types = typeattr->cImplTypes;
1062 ITypeInfo_ReleaseTypeAttr(class_info, typeattr);
1064 for(i=0; i<impl_types; i++) {
1065 hres = ITypeInfo_GetImplTypeFlags(class_info, i, &impl_flags);
1066 if(FAILED(hres))
1067 continue;
1069 if((impl_flags & IMPLTYPEFLAG_FSOURCE)) {
1070 if(!(impl_flags & IMPLTYPEFLAG_FDEFAULT)) {
1071 FIXME("Handle non-default source iface\n");
1072 continue;
1075 hres = ITypeInfo_GetRefTypeOfImplType(class_info, i, &ref);
1076 if(FAILED(hres))
1077 continue;
1079 hres = ITypeInfo_GetRefTypeInfo(class_info, ref, &ret);
1080 if(FAILED(hres))
1081 ret = NULL;
1085 return ret;
1088 void bind_activex_event(HTMLDocumentNode *doc, HTMLPluginContainer *plugin_container, WCHAR *event, IDispatch *disp)
1090 PluginHost *plugin_host = plugin_container->plugin_host;
1091 ITypeInfo *class_info, *source_info;
1092 DISPID id;
1093 HRESULT hres;
1095 TRACE("(%p %p %s %p)\n", doc, plugin_host, debugstr_w(event), disp);
1097 if(!plugin_host || !plugin_host->plugin_unk) {
1098 WARN("detached element %p\n", plugin_host);
1099 return;
1102 if(plugin_host->sink) {
1103 source_info = plugin_host->sink->typeinfo;
1104 ITypeInfo_AddRef(source_info);
1105 }else {
1106 IProvideClassInfo *provide_ci;
1108 hres = IUnknown_QueryInterface(plugin_host->plugin_unk, &IID_IProvideClassInfo, (void**)&provide_ci);
1109 if(FAILED(hres)) {
1110 FIXME("No IProvideClassInfo, try GetTypeInfo?\n");
1111 return;
1114 hres = IProvideClassInfo_GetClassInfo(provide_ci, &class_info);
1115 IProvideClassInfo_Release(provide_ci);
1116 if(FAILED(hres) || !class_info) {
1117 WARN("GetClassInfo failed: %08lx\n", hres);
1118 return;
1121 source_info = get_eventiface_info(plugin_container, class_info);
1122 ITypeInfo_Release(class_info);
1123 if(!source_info)
1124 return;
1127 hres = ITypeInfo_GetIDsOfNames(source_info, &event, 1, &id);
1128 if(FAILED(hres))
1129 WARN("Could not get disp id: %08lx\n", hres);
1130 else if(!plugin_host->sink)
1131 plugin_host->sink = create_event_sink(plugin_host, source_info);
1133 ITypeInfo_Release(source_info);
1134 if(FAILED(hres) || !plugin_host->sink)
1135 return;
1137 add_sink_handler(plugin_host->sink, id, disp);
1140 typedef struct {
1141 IOleInPlaceFrame IOleInPlaceFrame_iface;
1142 LONG ref;
1143 } InPlaceFrame;
1145 static inline InPlaceFrame *impl_from_IOleInPlaceFrame(IOleInPlaceFrame *iface)
1147 return CONTAINING_RECORD(iface, InPlaceFrame, IOleInPlaceFrame_iface);
1150 static HRESULT WINAPI InPlaceFrame_QueryInterface(IOleInPlaceFrame *iface,
1151 REFIID riid, void **ppv)
1153 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1155 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1157 if(IsEqualGUID(&IID_IUnknown, riid)) {
1158 *ppv = &This->IOleInPlaceFrame_iface;
1159 }else if(IsEqualGUID(&IID_IOleWindow, riid)) {
1160 *ppv = &This->IOleInPlaceFrame_iface;
1161 }else if(IsEqualGUID(&IID_IOleInPlaceUIWindow, riid)) {
1162 *ppv = &This->IOleInPlaceFrame_iface;
1163 }else if(IsEqualGUID(&IID_IOleInPlaceFrame, riid)) {
1164 *ppv = &This->IOleInPlaceFrame_iface;
1165 }else {
1166 WARN("Unsopported interface %s\n", debugstr_mshtml_guid(riid));
1167 *ppv = NULL;
1168 return E_NOINTERFACE;
1171 IUnknown_AddRef((IUnknown*)*ppv);
1172 return S_OK;
1175 static ULONG WINAPI InPlaceFrame_AddRef(IOleInPlaceFrame *iface)
1177 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1178 LONG ref = InterlockedIncrement(&This->ref);
1180 TRACE("(%p) ref=%ld\n", This, ref);
1182 return ref;
1185 static ULONG WINAPI InPlaceFrame_Release(IOleInPlaceFrame *iface)
1187 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1188 LONG ref = InterlockedDecrement(&This->ref);
1190 TRACE("(%p) ref=%ld\n", This, ref);
1192 if(!ref)
1193 free(This);
1195 return ref;
1198 static HRESULT WINAPI InPlaceFrame_GetWindow(IOleInPlaceFrame *iface, HWND *phwnd)
1200 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1201 FIXME("(%p)->(%p)\n", This, phwnd);
1202 return E_NOTIMPL;
1205 static HRESULT WINAPI InPlaceFrame_ContextSensitiveHelp(IOleInPlaceFrame *iface,
1206 BOOL fEnterMode)
1208 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1209 FIXME("(%p)->(%x)\n", This, fEnterMode);
1210 return E_NOTIMPL;
1213 static HRESULT WINAPI InPlaceFrame_GetBorder(IOleInPlaceFrame *iface, LPRECT lprectBorder)
1215 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1216 FIXME("(%p)->(%p)\n", This, lprectBorder);
1217 return E_NOTIMPL;
1220 static HRESULT WINAPI InPlaceFrame_RequestBorderSpace(IOleInPlaceFrame *iface,
1221 LPCBORDERWIDTHS pborderwidths)
1223 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1224 FIXME("(%p)->(%p)\n", This, pborderwidths);
1225 return E_NOTIMPL;
1228 static HRESULT WINAPI InPlaceFrame_SetBorderSpace(IOleInPlaceFrame *iface,
1229 LPCBORDERWIDTHS pborderwidths)
1231 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1232 FIXME("(%p)->(%p)\n", This, pborderwidths);
1233 return E_NOTIMPL;
1236 static HRESULT WINAPI InPlaceFrame_SetActiveObject(IOleInPlaceFrame *iface,
1237 IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
1239 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1240 FIXME("(%p)->(%p %s)\n", This, pActiveObject, debugstr_w(pszObjName));
1241 return E_NOTIMPL;
1244 static HRESULT WINAPI InPlaceFrame_InsertMenus(IOleInPlaceFrame *iface, HMENU hmenuShared,
1245 LPOLEMENUGROUPWIDTHS lpMenuWidths)
1247 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1248 FIXME("(%p)->(%p %p)\n", This, hmenuShared, lpMenuWidths);
1249 return E_NOTIMPL;
1252 static HRESULT WINAPI InPlaceFrame_SetMenu(IOleInPlaceFrame *iface, HMENU hmenuShared,
1253 HOLEMENU holemenu, HWND hwndActiveObject)
1255 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1256 FIXME("(%p)->(%p %p %p)\n", This, hmenuShared, holemenu, hwndActiveObject);
1257 return E_NOTIMPL;
1260 static HRESULT WINAPI InPlaceFrame_RemoveMenus(IOleInPlaceFrame *iface, HMENU hmenuShared)
1262 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1263 FIXME("(%p)->(%p)\n", This, hmenuShared);
1264 return E_NOTIMPL;
1267 static HRESULT WINAPI InPlaceFrame_SetStatusText(IOleInPlaceFrame *iface,
1268 LPCOLESTR pszStatusText)
1270 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1271 FIXME("(%p)->(%s)\n", This, debugstr_w(pszStatusText));
1272 return E_NOTIMPL;
1275 static HRESULT WINAPI InPlaceFrame_EnableModeless(IOleInPlaceFrame *iface, BOOL fEnable)
1277 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1278 FIXME("(%p)->(%x)\n", This, fEnable);
1279 return E_NOTIMPL;
1282 static HRESULT WINAPI InPlaceFrame_TranslateAccelerator(IOleInPlaceFrame *iface, LPMSG lpmsg,
1283 WORD wID)
1285 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1286 FIXME("(%p)->(%p %d)\n", This, lpmsg, wID);
1287 return E_NOTIMPL;
1290 static const IOleInPlaceFrameVtbl OleInPlaceFrameVtbl = {
1291 InPlaceFrame_QueryInterface,
1292 InPlaceFrame_AddRef,
1293 InPlaceFrame_Release,
1294 InPlaceFrame_GetWindow,
1295 InPlaceFrame_ContextSensitiveHelp,
1296 InPlaceFrame_GetBorder,
1297 InPlaceFrame_RequestBorderSpace,
1298 InPlaceFrame_SetBorderSpace,
1299 InPlaceFrame_SetActiveObject,
1300 InPlaceFrame_InsertMenus,
1301 InPlaceFrame_SetMenu,
1302 InPlaceFrame_RemoveMenus,
1303 InPlaceFrame_SetStatusText,
1304 InPlaceFrame_EnableModeless,
1305 InPlaceFrame_TranslateAccelerator
1308 static HRESULT create_ip_frame(IOleInPlaceFrame **ret)
1310 InPlaceFrame *frame;
1312 frame = calloc(1, sizeof(*frame));
1313 if(!frame)
1314 return E_OUTOFMEMORY;
1316 frame->IOleInPlaceFrame_iface.lpVtbl = &OleInPlaceFrameVtbl;
1317 frame->ref = 1;
1319 *ret = &frame->IOleInPlaceFrame_iface;
1320 return S_OK;
1323 typedef struct {
1324 IOleInPlaceUIWindow IOleInPlaceUIWindow_iface;
1325 LONG ref;
1326 } InPlaceUIWindow;
1328 static inline InPlaceUIWindow *impl_from_IOleInPlaceUIWindow(IOleInPlaceUIWindow *iface)
1330 return CONTAINING_RECORD(iface, InPlaceUIWindow, IOleInPlaceUIWindow_iface);
1333 static HRESULT WINAPI InPlaceUIWindow_QueryInterface(IOleInPlaceUIWindow *iface, REFIID riid, void **ppv)
1335 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1337 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1339 if(IsEqualGUID(&IID_IUnknown, riid)) {
1340 *ppv = &This->IOleInPlaceUIWindow_iface;
1341 }else if(IsEqualGUID(&IID_IOleWindow, riid)) {
1342 *ppv = &This->IOleInPlaceUIWindow_iface;
1343 }else if(IsEqualGUID(&IID_IOleInPlaceUIWindow, riid)) {
1344 *ppv = &This->IOleInPlaceUIWindow_iface;
1345 }else {
1346 WARN("Unsopported interface %s\n", debugstr_mshtml_guid(riid));
1347 *ppv = NULL;
1348 return E_NOINTERFACE;
1351 IUnknown_AddRef((IUnknown*)*ppv);
1352 return S_OK;
1355 static ULONG WINAPI InPlaceUIWindow_AddRef(IOleInPlaceUIWindow *iface)
1357 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1358 LONG ref = InterlockedIncrement(&This->ref);
1360 TRACE("(%p) ref=%ld\n", This, ref);
1362 return ref;
1365 static ULONG WINAPI InPlaceUIWindow_Release(IOleInPlaceUIWindow *iface)
1367 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1368 LONG ref = InterlockedDecrement(&This->ref);
1370 TRACE("(%p) ref=%ld\n", This, ref);
1372 if(!ref)
1373 free(This);
1375 return ref;
1378 static HRESULT WINAPI InPlaceUIWindow_GetWindow(IOleInPlaceUIWindow *iface, HWND *phwnd)
1380 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1381 FIXME("(%p)->(%p)\n", This, phwnd);
1382 return E_NOTIMPL;
1385 static HRESULT WINAPI InPlaceUIWindow_ContextSensitiveHelp(IOleInPlaceUIWindow *iface,
1386 BOOL fEnterMode)
1388 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1389 FIXME("(%p)->(%x)\n", This, fEnterMode);
1390 return E_NOTIMPL;
1393 static HRESULT WINAPI InPlaceUIWindow_GetBorder(IOleInPlaceUIWindow *iface, LPRECT lprectBorder)
1395 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1396 FIXME("(%p)->(%p)\n", This, lprectBorder);
1397 return E_NOTIMPL;
1400 static HRESULT WINAPI InPlaceUIWindow_RequestBorderSpace(IOleInPlaceUIWindow *iface,
1401 LPCBORDERWIDTHS pborderwidths)
1403 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1404 FIXME("(%p)->(%p)\n", This, pborderwidths);
1405 return E_NOTIMPL;
1408 static HRESULT WINAPI InPlaceUIWindow_SetBorderSpace(IOleInPlaceUIWindow *iface,
1409 LPCBORDERWIDTHS pborderwidths)
1411 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1412 FIXME("(%p)->(%p)\n", This, pborderwidths);
1413 return E_NOTIMPL;
1416 static HRESULT WINAPI InPlaceUIWindow_SetActiveObject(IOleInPlaceUIWindow *iface,
1417 IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
1419 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1420 FIXME("(%p)->(%p %s)\n", This, pActiveObject, debugstr_w(pszObjName));
1421 return E_NOTIMPL;
1424 static const IOleInPlaceUIWindowVtbl OleInPlaceUIWindowVtbl = {
1425 InPlaceUIWindow_QueryInterface,
1426 InPlaceUIWindow_AddRef,
1427 InPlaceUIWindow_Release,
1428 InPlaceUIWindow_GetWindow,
1429 InPlaceUIWindow_ContextSensitiveHelp,
1430 InPlaceUIWindow_GetBorder,
1431 InPlaceUIWindow_RequestBorderSpace,
1432 InPlaceUIWindow_SetBorderSpace,
1433 InPlaceUIWindow_SetActiveObject,
1436 static HRESULT create_ip_window(IOleInPlaceUIWindow **ret)
1438 InPlaceUIWindow *uiwindow;
1440 uiwindow = calloc(1, sizeof(*uiwindow));
1441 if(!uiwindow)
1442 return E_OUTOFMEMORY;
1444 uiwindow->IOleInPlaceUIWindow_iface.lpVtbl = &OleInPlaceUIWindowVtbl;
1445 uiwindow->ref = 1;
1447 *ret = &uiwindow->IOleInPlaceUIWindow_iface;
1448 return S_OK;
1451 static inline PluginHost *impl_from_IOleClientSite(IOleClientSite *iface)
1453 return CONTAINING_RECORD(iface, PluginHost, IOleClientSite_iface);
1456 static HRESULT WINAPI PHClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv)
1458 PluginHost *This = impl_from_IOleClientSite(iface);
1460 if(IsEqualGUID(&IID_IUnknown, riid)) {
1461 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1462 *ppv = &This->IOleClientSite_iface;
1463 }else if(IsEqualGUID(&IID_IOleClientSite, riid)) {
1464 TRACE("(%p)->(IID_IOleClientSite %p)\n", This, ppv);
1465 *ppv = &This->IOleClientSite_iface;
1466 }else if(IsEqualGUID(&IID_IAdviseSink, riid)) {
1467 TRACE("(%p)->(IID_IAdviseSink %p)\n", This, ppv);
1468 *ppv = &This->IAdviseSinkEx_iface;
1469 }else if(IsEqualGUID(&IID_IAdviseSinkEx, riid)) {
1470 TRACE("(%p)->(IID_IAdviseSinkEx %p)\n", This, ppv);
1471 *ppv = &This->IAdviseSinkEx_iface;
1472 }else if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) {
1473 TRACE("(%p)->(IID_IPropertyNotifySink %p)\n", This, ppv);
1474 *ppv = &This->IPropertyNotifySink_iface;
1475 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1476 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
1477 *ppv = &This->IDispatch_iface;
1478 }else if(IsEqualGUID(&IID_IOleWindow, riid)) {
1479 TRACE("(%p)->(IID_IOleWindow %p)\n", This, ppv);
1480 *ppv = &This->IOleInPlaceSiteEx_iface;
1481 }else if(IsEqualGUID(&IID_IOleInPlaceSite, riid)) {
1482 TRACE("(%p)->(IID_IOleInPlaceSite %p)\n", This, ppv);
1483 *ppv = &This->IOleInPlaceSiteEx_iface;
1484 }else if(IsEqualGUID(&IID_IOleInPlaceSiteEx, riid)) {
1485 TRACE("(%p)->(IID_IOleInPlaceSiteEx %p)\n", This, ppv);
1486 *ppv = &This->IOleInPlaceSiteEx_iface;
1487 }else if(IsEqualGUID(&IID_IOleControlSite, riid)) {
1488 TRACE("(%p)->(IID_IOleControlSite %p)\n", This, ppv);
1489 *ppv = &This->IOleControlSite_iface;
1490 }else if(IsEqualGUID(&IID_IBindHost, riid)) {
1491 TRACE("(%p)->(IID_IBindHost %p)\n", This, ppv);
1492 *ppv = &This->IBindHost_iface;
1493 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
1494 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
1495 *ppv = &This->IServiceProvider_iface;
1496 }else {
1497 WARN("Unsupported interface %s\n", debugstr_guid(riid));
1498 *ppv = NULL;
1499 return E_NOINTERFACE;
1502 IUnknown_AddRef((IUnknown*)*ppv);
1503 return S_OK;
1506 static ULONG WINAPI PHClientSite_AddRef(IOleClientSite *iface)
1508 PluginHost *This = impl_from_IOleClientSite(iface);
1509 LONG ref = InterlockedIncrement(&This->ref);
1511 TRACE("(%p) ref=%ld\n", This, ref);
1513 return ref;
1516 static void release_plugin_ifaces(PluginHost *This)
1518 unlink_ref(&This->disp);
1519 unlink_ref(&This->ip_object);
1521 if(This->plugin_unk) {
1522 IUnknown *unk = This->plugin_unk;
1523 LONG ref;
1525 This->plugin_unk = NULL;
1526 ref = IUnknown_Release(unk);
1528 TRACE("plugin ref = %ld\n", ref);
1532 static ULONG WINAPI PHClientSite_Release(IOleClientSite *iface)
1534 PluginHost *This = impl_from_IOleClientSite(iface);
1535 LONG ref = InterlockedDecrement(&This->ref);
1537 TRACE("(%p) ref=%ld\n", This, ref);
1539 if(!ref) {
1540 release_plugin_ifaces(This);
1541 if(This->sink) {
1542 This->sink->host = NULL;
1543 IDispatch_Release(&This->sink->IDispatch_iface);
1544 This->sink = NULL;
1546 list_remove(&This->entry);
1547 if(This->element)
1548 This->element->plugin_host = NULL;
1549 free(This);
1552 return ref;
1555 static HRESULT WINAPI PHClientSite_SaveObject(IOleClientSite *iface)
1557 PluginHost *This = impl_from_IOleClientSite(iface);
1558 FIXME("(%p)\n", This);
1559 return E_NOTIMPL;
1562 static HRESULT WINAPI PHClientSite_GetMoniker(IOleClientSite *iface, DWORD dwAssign,
1563 DWORD dwWhichMoniker, IMoniker **ppmk)
1565 PluginHost *This = impl_from_IOleClientSite(iface);
1567 TRACE("(%p)->(%ld %ld %p)\n", This, dwAssign, dwWhichMoniker, ppmk);
1569 switch(dwWhichMoniker) {
1570 case OLEWHICHMK_CONTAINER:
1571 if(!This->doc || !This->doc->window || !This->doc->window->mon) {
1572 FIXME("no moniker\n");
1573 return E_UNEXPECTED;
1576 *ppmk = This->doc->window->mon;
1577 IMoniker_AddRef(*ppmk);
1578 break;
1579 default:
1580 FIXME("which %ld\n", dwWhichMoniker);
1581 return E_NOTIMPL;
1584 return S_OK;
1587 static HRESULT WINAPI PHClientSite_GetContainer(IOleClientSite *iface, IOleContainer **ppContainer)
1589 PluginHost *This = impl_from_IOleClientSite(iface);
1591 TRACE("(%p)->(%p)\n", This, ppContainer);
1593 if(!This->doc) {
1594 ERR("Called on detached object\n");
1595 return E_UNEXPECTED;
1598 *ppContainer = &This->doc->IOleContainer_iface;
1599 IOleContainer_AddRef(*ppContainer);
1600 return S_OK;
1603 static HRESULT WINAPI PHClientSite_ShowObject(IOleClientSite *iface)
1605 PluginHost *This = impl_from_IOleClientSite(iface);
1607 TRACE("(%p)\n", This);
1609 return S_OK;
1612 static HRESULT WINAPI PHClientSite_OnShowWindow(IOleClientSite *iface, BOOL fShow)
1614 PluginHost *This = impl_from_IOleClientSite(iface);
1615 FIXME("(%p)->(%x)\n", This, fShow);
1616 return E_NOTIMPL;
1619 static HRESULT WINAPI PHClientSite_RequestNewObjectLayout(IOleClientSite *iface)
1621 PluginHost *This = impl_from_IOleClientSite(iface);
1622 FIXME("(%p)\n", This);
1623 return E_NOTIMPL;
1626 static const IOleClientSiteVtbl OleClientSiteVtbl = {
1627 PHClientSite_QueryInterface,
1628 PHClientSite_AddRef,
1629 PHClientSite_Release,
1630 PHClientSite_SaveObject,
1631 PHClientSite_GetMoniker,
1632 PHClientSite_GetContainer,
1633 PHClientSite_ShowObject,
1634 PHClientSite_OnShowWindow,
1635 PHClientSite_RequestNewObjectLayout
1638 static inline PluginHost *impl_from_IAdviseSinkEx(IAdviseSinkEx *iface)
1640 return CONTAINING_RECORD(iface, PluginHost, IAdviseSinkEx_iface);
1643 static HRESULT WINAPI PHAdviseSinkEx_QueryInterface(IAdviseSinkEx *iface, REFIID riid, void **ppv)
1645 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1646 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1649 static ULONG WINAPI PHAdviseSinkEx_AddRef(IAdviseSinkEx *iface)
1651 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1652 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1655 static ULONG WINAPI PHAdviseSinkEx_Release(IAdviseSinkEx *iface)
1657 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1658 return IOleClientSite_Release(&This->IOleClientSite_iface);
1661 static void WINAPI PHAdviseSinkEx_OnDataChange(IAdviseSinkEx *iface, FORMATETC *pFormatetc, STGMEDIUM *pStgMedium)
1663 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1664 FIXME("(%p)->(%p %p)\n", This, pFormatetc, pStgMedium);
1667 static void WINAPI PHAdviseSinkEx_OnViewChange(IAdviseSinkEx *iface, DWORD dwAspect, LONG lindex)
1669 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1670 FIXME("(%p)->(%ld %ld)\n", This, dwAspect, lindex);
1673 static void WINAPI PHAdviseSinkEx_OnRename(IAdviseSinkEx *iface, IMoniker *pmk)
1675 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1676 FIXME("(%p)->(%p)\n", This, pmk);
1679 static void WINAPI PHAdviseSinkEx_OnSave(IAdviseSinkEx *iface)
1681 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1682 FIXME("(%p)\n", This);
1685 static void WINAPI PHAdviseSinkEx_OnClose(IAdviseSinkEx *iface)
1687 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1688 FIXME("(%p)\n", This);
1691 static void WINAPI PHAdviseSinkEx_OnViewStatusChange(IAdviseSinkEx *iface, DWORD dwViewStatus)
1693 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1694 FIXME("(%p)->(%ld)\n", This, dwViewStatus);
1697 static const IAdviseSinkExVtbl AdviseSinkExVtbl = {
1698 PHAdviseSinkEx_QueryInterface,
1699 PHAdviseSinkEx_AddRef,
1700 PHAdviseSinkEx_Release,
1701 PHAdviseSinkEx_OnDataChange,
1702 PHAdviseSinkEx_OnViewChange,
1703 PHAdviseSinkEx_OnRename,
1704 PHAdviseSinkEx_OnSave,
1705 PHAdviseSinkEx_OnClose,
1706 PHAdviseSinkEx_OnViewStatusChange
1709 static inline PluginHost *impl_from_IPropertyNotifySink(IPropertyNotifySink *iface)
1711 return CONTAINING_RECORD(iface, PluginHost, IPropertyNotifySink_iface);
1714 static HRESULT WINAPI PHPropertyNotifySink_QueryInterface(IPropertyNotifySink *iface, REFIID riid, void **ppv)
1716 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1717 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1720 static ULONG WINAPI PHPropertyNotifySink_AddRef(IPropertyNotifySink *iface)
1722 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1723 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1726 static ULONG WINAPI PHPropertyNotifySink_Release(IPropertyNotifySink *iface)
1728 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1729 return IOleClientSite_Release(&This->IOleClientSite_iface);
1732 static HRESULT WINAPI PHPropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID)
1734 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1736 TRACE("(%p)->(%ld)\n", This, dispID);
1738 switch(dispID) {
1739 case DISPID_READYSTATE:
1740 update_readystate(This);
1741 break;
1742 default :
1743 FIXME("Unimplemented dispID %ld\n", dispID);
1744 return E_NOTIMPL;
1747 return S_OK;
1750 static HRESULT WINAPI PHPropertyNotifySink_OnRequestEdit(IPropertyNotifySink *iface, DISPID dispID)
1752 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1753 FIXME("(%p)->(%ld)\n", This, dispID);
1754 return E_NOTIMPL;
1757 static const IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = {
1758 PHPropertyNotifySink_QueryInterface,
1759 PHPropertyNotifySink_AddRef,
1760 PHPropertyNotifySink_Release,
1761 PHPropertyNotifySink_OnChanged,
1762 PHPropertyNotifySink_OnRequestEdit
1765 static inline PluginHost *impl_from_IDispatch(IDispatch *iface)
1767 return CONTAINING_RECORD(iface, PluginHost, IDispatch_iface);
1770 static HRESULT WINAPI PHDispatch_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
1772 PluginHost *This = impl_from_IDispatch(iface);
1773 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1776 static ULONG WINAPI PHDispatch_AddRef(IDispatch *iface)
1778 PluginHost *This = impl_from_IDispatch(iface);
1779 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1782 static ULONG WINAPI PHDispatch_Release(IDispatch *iface)
1784 PluginHost *This = impl_from_IDispatch(iface);
1785 return IOleClientSite_Release(&This->IOleClientSite_iface);
1788 static HRESULT WINAPI PHDispatch_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
1790 PluginHost *This = impl_from_IDispatch(iface);
1791 FIXME("(%p)->(%p)\n", This, pctinfo);
1792 return E_NOTIMPL;
1795 static HRESULT WINAPI PHDispatch_GetTypeInfo(IDispatch *iface, UINT iTInfo,
1796 LCID lcid, ITypeInfo **ppTInfo)
1798 PluginHost *This = impl_from_IDispatch(iface);
1799 FIXME("(%p)->(%d %ld %p)\n", This, iTInfo, lcid, ppTInfo);
1800 return E_NOTIMPL;
1803 static HRESULT WINAPI PHDispatch_GetIDsOfNames(IDispatch *iface, REFIID riid,
1804 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1806 PluginHost *This = impl_from_IDispatch(iface);
1807 FIXME("(%p)->(%s %p %d %ld %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1808 return E_NOTIMPL;
1811 static HRESULT WINAPI PHDispatch_Invoke(IDispatch *iface, DISPID dispid, REFIID riid, LCID lcid,
1812 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1814 PluginHost *This = impl_from_IDispatch(iface);
1815 FIXME("(%p)->(%ld %x %p %p)\n", This, dispid, wFlags, pDispParams, pVarResult);
1816 return E_NOTIMPL;
1819 static const IDispatchVtbl DispatchVtbl = {
1820 PHDispatch_QueryInterface,
1821 PHDispatch_AddRef,
1822 PHDispatch_Release,
1823 PHDispatch_GetTypeInfoCount,
1824 PHDispatch_GetTypeInfo,
1825 PHDispatch_GetIDsOfNames,
1826 PHDispatch_Invoke
1829 static inline PluginHost *impl_from_IOleInPlaceSiteEx(IOleInPlaceSiteEx *iface)
1831 return CONTAINING_RECORD(iface, PluginHost, IOleInPlaceSiteEx_iface);
1834 static HRESULT WINAPI PHInPlaceSite_QueryInterface(IOleInPlaceSiteEx *iface, REFIID riid, void **ppv)
1836 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1837 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1840 static ULONG WINAPI PHInPlaceSite_AddRef(IOleInPlaceSiteEx *iface)
1842 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1843 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1846 static ULONG WINAPI PHInPlaceSite_Release(IOleInPlaceSiteEx *iface)
1848 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1849 return IOleClientSite_Release(&This->IOleClientSite_iface);
1852 static HRESULT WINAPI PHInPlaceSite_GetWindow(IOleInPlaceSiteEx *iface, HWND *phwnd)
1854 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1856 TRACE("(%p)->(%p)\n", This, phwnd);
1858 *phwnd = This->hwnd;
1859 return S_OK;
1862 static HRESULT WINAPI PHInPlaceSite_ContextSensitiveHelp(IOleInPlaceSiteEx *iface, BOOL fEnterMode)
1864 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1865 FIXME("(%p)->(%x)\n", This, fEnterMode);
1866 return E_NOTIMPL;
1869 static HRESULT WINAPI PHInPlaceSite_CanInPlaceActivate(IOleInPlaceSiteEx *iface)
1871 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1873 TRACE("(%p)\n", This);
1875 return S_OK;
1878 static HRESULT WINAPI PHInPlaceSite_OnInPlaceActivate(IOleInPlaceSiteEx *iface)
1880 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1881 FIXME("(%p)\n", This);
1882 return E_NOTIMPL;
1885 static HRESULT WINAPI PHInPlaceSite_OnUIActivate(IOleInPlaceSiteEx *iface)
1887 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1889 TRACE("(%p)\n", This);
1891 if(!This->plugin_unk) {
1892 ERR("No plugin object\n");
1893 return E_UNEXPECTED;
1896 This->ui_active = TRUE;
1898 notif_enabled(This);
1899 return S_OK;
1902 static HRESULT WINAPI PHInPlaceSite_GetWindowContext(IOleInPlaceSiteEx *iface,
1903 IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, RECT *lprcPosRect,
1904 RECT *lprcClipRect, OLEINPLACEFRAMEINFO *frame_info)
1906 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1907 IOleInPlaceUIWindow *ip_window;
1908 IOleInPlaceFrame *ip_frame;
1909 RECT pr, cr;
1910 HRESULT hres;
1912 TRACE("(%p)->(%p %p %p %p %p)\n", This, ppFrame, ppDoc, lprcPosRect, lprcClipRect, frame_info);
1914 if(!This->doc || !This->doc->doc_obj || !This->doc->doc_obj->ipsite) {
1915 FIXME("No ipsite\n");
1916 return E_UNEXPECTED;
1919 hres = IOleInPlaceSite_GetWindowContext(This->doc->doc_obj->ipsite, &ip_frame, &ip_window, &pr, &cr, frame_info);
1920 if(FAILED(hres)) {
1921 WARN("GetWindowContext failed: %08lx\n", hres);
1922 return hres;
1925 if(ip_window)
1926 IOleInPlaceUIWindow_Release(ip_window);
1927 if(ip_frame)
1928 IOleInPlaceFrame_Release(ip_frame);
1930 hres = create_ip_frame(&ip_frame);
1931 if(FAILED(hres))
1932 return hres;
1934 hres = create_ip_window(ppDoc);
1935 if(FAILED(hres)) {
1936 IOleInPlaceFrame_Release(ip_frame);
1937 return hres;
1940 *ppFrame = ip_frame;
1941 *lprcPosRect = This->rect;
1942 *lprcClipRect = This->rect;
1943 return S_OK;
1946 static HRESULT WINAPI PHInPlaceSite_Scroll(IOleInPlaceSiteEx *iface, SIZE scrollExtent)
1948 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1949 FIXME("(%p)->({%ld %ld})\n", This, scrollExtent.cx, scrollExtent.cy);
1950 return E_NOTIMPL;
1953 static HRESULT WINAPI PHInPlaceSite_OnUIDeactivate(IOleInPlaceSiteEx *iface, BOOL fUndoable)
1955 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1956 FIXME("(%p)->(%x)\n", This, fUndoable);
1957 return E_NOTIMPL;
1960 static HRESULT WINAPI PHInPlaceSite_OnInPlaceDeactivate(IOleInPlaceSiteEx *iface)
1962 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1964 TRACE("(%p)\n", This);
1966 unlink_ref(&This->ip_object);
1967 return S_OK;
1970 static HRESULT WINAPI PHInPlaceSite_DiscardUndoState(IOleInPlaceSiteEx *iface)
1972 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1973 FIXME("(%p)\n", This);
1974 return E_NOTIMPL;
1977 static HRESULT WINAPI PHInPlaceSite_DeactivateAndUndo(IOleInPlaceSiteEx *iface)
1979 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1980 FIXME("(%p)\n", This);
1981 return E_NOTIMPL;
1984 static HRESULT WINAPI PHInPlaceSite_OnPosRectChange(IOleInPlaceSiteEx *iface, LPCRECT lprcPosRect)
1986 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1987 FIXME("(%p)->(%p)\n", This, lprcPosRect);
1988 return E_NOTIMPL;
1991 static HRESULT WINAPI PHInPlaceSiteEx_OnInPlaceActivateEx(IOleInPlaceSiteEx *iface, BOOL *pfNoRedraw, DWORD dwFlags)
1993 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1994 HWND hwnd;
1995 HRESULT hres;
1997 TRACE("(%p)->(%p %lx)\n", This, pfNoRedraw, dwFlags);
1999 if(This->ip_object)
2000 return S_OK;
2002 hres = IUnknown_QueryInterface(This->plugin_unk, &IID_IOleInPlaceObject, (void**)&This->ip_object);
2003 if(FAILED(hres))
2004 return hres;
2006 hres = IOleInPlaceObject_GetWindow(This->ip_object, &hwnd);
2007 if(SUCCEEDED(hres))
2008 FIXME("Use hwnd %p\n", hwnd);
2010 *pfNoRedraw = FALSE;
2011 return S_OK;
2014 static HRESULT WINAPI PHInPlaceSiteEx_OnInPlaceDeactivateEx(IOleInPlaceSiteEx *iface, BOOL fNoRedraw)
2016 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
2017 FIXME("(%p)->(%x)\n", This, fNoRedraw);
2018 return E_NOTIMPL;
2021 static HRESULT WINAPI PHInPlaceSiteEx_RequestUIActivate(IOleInPlaceSiteEx *iface)
2023 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
2024 FIXME("(%p)\n", This);
2025 return E_NOTIMPL;
2028 static const IOleInPlaceSiteExVtbl OleInPlaceSiteExVtbl = {
2029 PHInPlaceSite_QueryInterface,
2030 PHInPlaceSite_AddRef,
2031 PHInPlaceSite_Release,
2032 PHInPlaceSite_GetWindow,
2033 PHInPlaceSite_ContextSensitiveHelp,
2034 PHInPlaceSite_CanInPlaceActivate,
2035 PHInPlaceSite_OnInPlaceActivate,
2036 PHInPlaceSite_OnUIActivate,
2037 PHInPlaceSite_GetWindowContext,
2038 PHInPlaceSite_Scroll,
2039 PHInPlaceSite_OnUIDeactivate,
2040 PHInPlaceSite_OnInPlaceDeactivate,
2041 PHInPlaceSite_DiscardUndoState,
2042 PHInPlaceSite_DeactivateAndUndo,
2043 PHInPlaceSite_OnPosRectChange,
2044 PHInPlaceSiteEx_OnInPlaceActivateEx,
2045 PHInPlaceSiteEx_OnInPlaceDeactivateEx,
2046 PHInPlaceSiteEx_RequestUIActivate
2049 static inline PluginHost *impl_from_IOleControlSite(IOleControlSite *iface)
2051 return CONTAINING_RECORD(iface, PluginHost, IOleControlSite_iface);
2054 static HRESULT WINAPI PHControlSite_QueryInterface(IOleControlSite *iface, REFIID riid, void **ppv)
2056 PluginHost *This = impl_from_IOleControlSite(iface);
2057 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
2060 static ULONG WINAPI PHControlSite_AddRef(IOleControlSite *iface)
2062 PluginHost *This = impl_from_IOleControlSite(iface);
2063 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
2066 static ULONG WINAPI PHControlSite_Release(IOleControlSite *iface)
2068 PluginHost *This = impl_from_IOleControlSite(iface);
2069 return IOleClientSite_Release(&This->IOleClientSite_iface);
2072 static HRESULT WINAPI PHControlSite_OnControlInfoChanged(IOleControlSite *iface)
2074 PluginHost *This = impl_from_IOleControlSite(iface);
2075 FIXME("(%p)\n", This);
2076 return E_NOTIMPL;
2079 static HRESULT WINAPI PHControlSite_LockInPlaceActive(IOleControlSite *iface, BOOL fLock)
2081 PluginHost *This = impl_from_IOleControlSite(iface);
2082 FIXME("(%p)->(%x)\n", This, fLock);
2083 return E_NOTIMPL;
2086 static HRESULT WINAPI PHControlSite_GetExtendedControl(IOleControlSite *iface, IDispatch **ppDisp)
2088 PluginHost *This = impl_from_IOleControlSite(iface);
2089 FIXME("(%p)->(%p)\n", This, ppDisp);
2090 return E_NOTIMPL;
2093 static HRESULT WINAPI PHControlSite_TransformCoords(IOleControlSite *iface, POINTL *pPtlHimetric, POINTF *pPtfContainer, DWORD dwFlags)
2095 PluginHost *This = impl_from_IOleControlSite(iface);
2096 FIXME("(%p)->(%p %p %lx)\n", This, pPtlHimetric, pPtfContainer, dwFlags);
2097 return E_NOTIMPL;
2100 static HRESULT WINAPI PHControlSite_TranslateAccelerator(IOleControlSite *iface, MSG *pMsg, DWORD grfModifiers)
2102 PluginHost *This = impl_from_IOleControlSite(iface);
2103 FIXME("(%p)->(%lx)\n", This, grfModifiers);
2104 return E_NOTIMPL;
2107 static HRESULT WINAPI PHControlSite_OnFocus(IOleControlSite *iface, BOOL fGotFocus)
2109 PluginHost *This = impl_from_IOleControlSite(iface);
2110 FIXME("(%p)->(%x)\n", This, fGotFocus);
2111 return E_NOTIMPL;
2114 static HRESULT WINAPI PHControlSite_ShowPropertyFrame(IOleControlSite *iface)
2116 PluginHost *This = impl_from_IOleControlSite(iface);
2117 FIXME("(%p)\n", This);
2118 return E_NOTIMPL;
2121 static const IOleControlSiteVtbl OleControlSiteVtbl = {
2122 PHControlSite_QueryInterface,
2123 PHControlSite_AddRef,
2124 PHControlSite_Release,
2125 PHControlSite_OnControlInfoChanged,
2126 PHControlSite_LockInPlaceActive,
2127 PHControlSite_GetExtendedControl,
2128 PHControlSite_TransformCoords,
2129 PHControlSite_TranslateAccelerator,
2130 PHControlSite_OnFocus,
2131 PHControlSite_ShowPropertyFrame
2134 static inline PluginHost *impl_from_IBindHost(IBindHost *iface)
2136 return CONTAINING_RECORD(iface, PluginHost, IBindHost_iface);
2139 static HRESULT WINAPI PHBindHost_QueryInterface(IBindHost *iface, REFIID riid, void **ppv)
2141 PluginHost *This = impl_from_IBindHost(iface);
2142 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
2145 static ULONG WINAPI PHBindHost_AddRef(IBindHost *iface)
2147 PluginHost *This = impl_from_IBindHost(iface);
2148 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
2151 static ULONG WINAPI PHBindHost_Release(IBindHost *iface)
2153 PluginHost *This = impl_from_IBindHost(iface);
2154 return IOleClientSite_Release(&This->IOleClientSite_iface);
2157 static HRESULT WINAPI PHBindHost_CreateMoniker(IBindHost *iface, LPOLESTR szName, IBindCtx *pBC, IMoniker **ppmk, DWORD dwReserved)
2159 PluginHost *This = impl_from_IBindHost(iface);
2161 TRACE("(%p)->(%s %p %p %lx)\n", This, debugstr_w(szName), pBC, ppmk, dwReserved);
2163 if(!This->doc || !This->doc->window || !This->doc->window->mon) {
2164 FIXME("no moniker\n");
2165 return E_UNEXPECTED;
2168 return CreateURLMoniker(This->doc->window->mon, szName, ppmk);
2171 static HRESULT WINAPI PHBindHost_MonikerBindToStorage(IBindHost *iface, IMoniker *pMk, IBindCtx *pBC,
2172 IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
2174 PluginHost *This = impl_from_IBindHost(iface);
2175 FIXME("(%p)->(%p %p %p %s %p)\n", This, pMk, pBC, pBSC, debugstr_guid(riid), ppvObj);
2176 return E_NOTIMPL;
2179 static HRESULT WINAPI PHBindHost_MonikerBindToObject(IBindHost *iface, IMoniker *pMk, IBindCtx *pBC,
2180 IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
2182 PluginHost *This = impl_from_IBindHost(iface);
2183 FIXME("(%p)->(%p %p %p %s %p)\n", This, pMk, pBC, pBSC, debugstr_guid(riid), ppvObj);
2184 return E_NOTIMPL;
2187 static const IBindHostVtbl BindHostVtbl = {
2188 PHBindHost_QueryInterface,
2189 PHBindHost_AddRef,
2190 PHBindHost_Release,
2191 PHBindHost_CreateMoniker,
2192 PHBindHost_MonikerBindToStorage,
2193 PHBindHost_MonikerBindToObject
2196 static inline PluginHost *impl_from_IServiceProvider(IServiceProvider *iface)
2198 return CONTAINING_RECORD(iface, PluginHost, IServiceProvider_iface);
2201 static HRESULT WINAPI PHServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
2203 PluginHost *This = impl_from_IServiceProvider(iface);
2204 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
2207 static ULONG WINAPI PHServiceProvider_AddRef(IServiceProvider *iface)
2209 PluginHost *This = impl_from_IServiceProvider(iface);
2210 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
2213 static ULONG WINAPI PHServiceProvider_Release(IServiceProvider *iface)
2215 PluginHost *This = impl_from_IServiceProvider(iface);
2216 return IOleClientSite_Release(&This->IOleClientSite_iface);
2219 static HRESULT WINAPI PHServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService, REFIID riid, void **ppv)
2221 PluginHost *This = impl_from_IServiceProvider(iface);
2223 if(IsEqualGUID(guidService, &SID_SBindHost)) {
2224 TRACE("SID_SBindHost service\n");
2225 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
2228 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
2230 if(!This->doc || !This->doc->outer_window) {
2231 *ppv = NULL;
2232 return E_NOINTERFACE;
2235 return IServiceProvider_QueryService(&This->doc->outer_window->base.IServiceProvider_iface,
2236 guidService, riid, ppv);
2239 static const IServiceProviderVtbl ServiceProviderVtbl = {
2240 PHServiceProvider_QueryInterface,
2241 PHServiceProvider_AddRef,
2242 PHServiceProvider_Release,
2243 PHServiceProvider_QueryService
2246 static BOOL parse_classid(const PRUnichar *classid, CLSID *clsid)
2248 const WCHAR *ptr;
2249 unsigned len;
2250 HRESULT hres;
2252 static const PRUnichar clsidW[] = {'c','l','s','i','d',':'};
2254 if(wcsnicmp(classid, clsidW, ARRAY_SIZE(clsidW)))
2255 return FALSE;
2257 ptr = classid + ARRAY_SIZE(clsidW);
2258 len = lstrlenW(ptr);
2260 if(len == 38) {
2261 hres = CLSIDFromString(ptr, clsid);
2262 }else if(len == 36) {
2263 WCHAR buf[39];
2265 buf[0] = '{';
2266 memcpy(buf+1, ptr, len*sizeof(WCHAR));
2267 buf[37] = '}';
2268 buf[38] = 0;
2269 hres = CLSIDFromString(buf, clsid);
2270 }else {
2271 return FALSE;
2274 return SUCCEEDED(hres);
2277 static BOOL get_elem_clsid(nsIDOMElement *elem, CLSID *clsid)
2279 const PRUnichar *val;
2280 nsAString val_str;
2281 nsresult nsres;
2282 BOOL ret = FALSE;
2284 nsres = get_elem_attr_value(elem, L"classid", &val_str, &val);
2285 if(NS_SUCCEEDED(nsres)) {
2286 if(*val)
2287 ret = parse_classid(val, clsid);
2288 nsAString_Finish(&val_str);
2291 return ret;
2294 typedef struct {
2295 IBindStatusCallback IBindStatusCallback_iface;
2296 IWindowForBindingUI IWindowForBindingUI_iface;
2297 LONG ref;
2298 } InstallCallback;
2300 static inline InstallCallback *impl_from_IBindStatusCallback(IBindStatusCallback *iface)
2302 return CONTAINING_RECORD(iface, InstallCallback, IBindStatusCallback_iface);
2305 static HRESULT WINAPI InstallCallback_QueryInterface(IBindStatusCallback *iface,
2306 REFIID riid, void **ppv)
2308 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2310 if(IsEqualGUID(&IID_IUnknown, riid)) {
2311 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
2312 *ppv = &This->IBindStatusCallback_iface;
2313 }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
2314 TRACE("(%p)->(IID_IBindStatusCallback %p)\n", This, ppv);
2315 *ppv = &This->IBindStatusCallback_iface;
2316 }else if(IsEqualGUID(&IID_IWindowForBindingUI, riid)) {
2317 TRACE("(%p)->(IID_IWindowForBindingUI %p)\n", This, ppv);
2318 *ppv = &This->IWindowForBindingUI_iface;
2319 }else {
2320 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
2321 *ppv = NULL;
2322 return E_NOINTERFACE;
2325 IUnknown_AddRef((IUnknown*)*ppv);
2326 return S_OK;
2329 static ULONG WINAPI InstallCallback_AddRef(IBindStatusCallback *iface)
2331 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2332 LONG ref = InterlockedIncrement(&This->ref);
2334 TRACE("(%p) ref=%ld\n", This, ref);
2336 return ref;
2339 static ULONG WINAPI InstallCallback_Release(IBindStatusCallback *iface)
2341 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2342 LONG ref = InterlockedIncrement(&This->ref);
2344 TRACE("(%p) ref=%ld\n", This, ref);
2346 if(!ref)
2347 free(This);
2349 return ref;
2352 static HRESULT WINAPI InstallCallback_OnStartBinding(IBindStatusCallback *iface,
2353 DWORD dwReserved, IBinding *pib)
2355 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2356 TRACE("(%p)->(%lx %p)\n", This, dwReserved, pib);
2357 return S_OK;
2360 static HRESULT WINAPI InstallCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
2362 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2363 TRACE("(%p)->(%p)\n", This, pnPriority);
2364 return E_NOTIMPL;
2367 static HRESULT WINAPI InstallCallback_OnLowResource(IBindStatusCallback *iface, DWORD dwReserved)
2369 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2370 TRACE("(%p)->(%lx)\n", This, dwReserved);
2371 return S_OK;
2374 static HRESULT WINAPI InstallCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
2375 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
2377 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2378 TRACE("(%p)->(%lu %lu %lu %s)\n", This, ulProgress, ulProgressMax, ulStatusCode, debugstr_w(szStatusText));
2379 return S_OK;
2382 static HRESULT WINAPI InstallCallback_OnStopBinding(IBindStatusCallback *iface,
2383 HRESULT hresult, LPCWSTR szError)
2385 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2386 TRACE("(%p)->(%08lx %s)\n", This, hresult, debugstr_w(szError));
2387 return S_OK;
2390 static HRESULT WINAPI InstallCallback_GetBindInfo(IBindStatusCallback *iface,
2391 DWORD* grfBINDF, BINDINFO* pbindinfo)
2393 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2395 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
2397 *grfBINDF = BINDF_ASYNCHRONOUS;
2398 return S_OK;
2401 static HRESULT WINAPI InstallCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
2402 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
2404 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2405 ERR("(%p)\n", This);
2406 return E_NOTIMPL;
2409 static HRESULT WINAPI InstallCallback_OnObjectAvailable(IBindStatusCallback *iface,
2410 REFIID riid, IUnknown* punk)
2412 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2413 ERR("(%p)\n", This);
2414 return E_NOTIMPL;
2417 static IBindStatusCallbackVtbl InstallCallbackVtbl = {
2418 InstallCallback_QueryInterface,
2419 InstallCallback_AddRef,
2420 InstallCallback_Release,
2421 InstallCallback_OnStartBinding,
2422 InstallCallback_GetPriority,
2423 InstallCallback_OnLowResource,
2424 InstallCallback_OnProgress,
2425 InstallCallback_OnStopBinding,
2426 InstallCallback_GetBindInfo,
2427 InstallCallback_OnDataAvailable,
2428 InstallCallback_OnObjectAvailable
2431 static inline InstallCallback *impl_from_IWindowForBindingUI(IWindowForBindingUI *iface)
2433 return CONTAINING_RECORD(iface, InstallCallback, IWindowForBindingUI_iface);
2436 static HRESULT WINAPI WindowForBindingUI_QueryInterface(IWindowForBindingUI *iface, REFIID riid, void **ppv)
2438 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
2439 return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
2442 static ULONG WINAPI WindowForBindingUI_AddRef(IWindowForBindingUI *iface)
2444 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
2445 return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
2448 static ULONG WINAPI WindowForBindingUI_Release(IWindowForBindingUI *iface)
2450 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
2451 return IBindStatusCallback_Release(&This->IBindStatusCallback_iface);
2454 static HRESULT WINAPI WindowForBindingUI_GetWindow(IWindowForBindingUI *iface, REFGUID rguidReason, HWND *phwnd)
2456 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
2457 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(rguidReason), phwnd);
2458 *phwnd = NULL;
2459 return S_OK;
2462 static const IWindowForBindingUIVtbl WindowForBindingUIVtbl = {
2463 WindowForBindingUI_QueryInterface,
2464 WindowForBindingUI_AddRef,
2465 WindowForBindingUI_Release,
2466 WindowForBindingUI_GetWindow
2469 typedef struct {
2470 struct list entry;
2471 IUri *uri;
2472 } install_entry_t;
2474 static struct list install_list = LIST_INIT(install_list);
2476 static CRITICAL_SECTION cs_install_list;
2477 static CRITICAL_SECTION_DEBUG cs_install_list_dbg =
2479 0, 0, &cs_install_list,
2480 { &cs_install_list_dbg.ProcessLocksList, &cs_install_list_dbg.ProcessLocksList },
2481 0, 0, { (DWORD_PTR)(__FILE__ ": install_list") }
2483 static CRITICAL_SECTION cs_install_list = { &cs_install_list_dbg, -1, 0, 0, 0, 0 };
2485 static void install_codebase(const WCHAR *url)
2487 InstallCallback *callback;
2488 IBindCtx *bctx;
2489 HRESULT hres;
2491 callback = malloc(sizeof(*callback));
2492 if(!callback)
2493 return;
2495 callback->IBindStatusCallback_iface.lpVtbl = &InstallCallbackVtbl;
2496 callback->IWindowForBindingUI_iface.lpVtbl = &WindowForBindingUIVtbl;
2497 callback->ref = 1;
2499 hres = CreateAsyncBindCtx(0, &callback->IBindStatusCallback_iface, NULL, &bctx);
2500 IBindStatusCallback_Release(&callback->IBindStatusCallback_iface);
2501 if(FAILED(hres))
2502 return;
2504 hres = AsyncInstallDistributionUnit(NULL, NULL, NULL, 0, 0, url, bctx, NULL, 0);
2505 IBindCtx_Release(bctx);
2506 if(FAILED(hres))
2507 WARN("FAILED: %08lx\n", hres);
2510 static void check_codebase(HTMLInnerWindow *window, nsIDOMElement *nselem)
2512 BOOL is_on_list = FALSE;
2513 install_entry_t *iter;
2514 const PRUnichar *val;
2515 nsAString val_str;
2516 IUri *uri = NULL;
2517 nsresult nsres;
2518 HRESULT hres;
2520 nsres = get_elem_attr_value(nselem, L"codebase", &val_str, &val);
2521 if(NS_SUCCEEDED(nsres)) {
2522 if(*val) {
2523 hres = CoInternetCombineUrlEx(window->base.outer_window->uri, val, 0, &uri, 0);
2524 if(FAILED(hres))
2525 uri = NULL;
2527 nsAString_Finish(&val_str);
2530 if(!uri)
2531 return;
2533 EnterCriticalSection(&cs_install_list);
2535 LIST_FOR_EACH_ENTRY(iter, &install_list, install_entry_t, entry) {
2536 BOOL eq;
2538 hres = IUri_IsEqual(uri, iter->uri, &eq);
2539 if(SUCCEEDED(hres) && eq) {
2540 TRACE("already proceeded\n");
2541 is_on_list = TRUE;
2542 break;
2546 if(!is_on_list) {
2547 iter = malloc(sizeof(*iter));
2548 if(iter) {
2549 IUri_AddRef(uri);
2550 iter->uri = uri;
2552 list_add_tail(&install_list, &iter->entry);
2556 LeaveCriticalSection(&cs_install_list);
2558 if(!is_on_list) {
2559 BSTR display_uri;
2561 hres = IUri_GetDisplayUri(uri, &display_uri);
2562 if(SUCCEEDED(hres)) {
2563 install_codebase(display_uri);
2564 SysFreeString(display_uri);
2568 IUri_Release(uri);
2571 static IUnknown *create_activex_object(HTMLDocumentNode *doc, nsIDOMElement *nselem, CLSID *clsid)
2573 IClassFactoryEx *cfex;
2574 IClassFactory *cf;
2575 IUnknown *obj;
2576 DWORD policy;
2577 HRESULT hres;
2579 if(!get_elem_clsid(nselem, clsid)) {
2580 WARN("Could not determine element CLSID\n");
2581 return NULL;
2584 TRACE("clsid %s\n", debugstr_guid(clsid));
2586 policy = 0;
2587 hres = IInternetHostSecurityManager_ProcessUrlAction(&doc->IInternetHostSecurityManager_iface,
2588 URLACTION_ACTIVEX_RUN, (BYTE*)&policy, sizeof(policy), (BYTE*)clsid, sizeof(GUID), 0, 0);
2589 if(FAILED(hres) || policy != URLPOLICY_ALLOW) {
2590 WARN("ProcessUrlAction returned %08lx %lx\n", hres, policy);
2591 return NULL;
2594 hres = CoGetClassObject(clsid, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, NULL, &IID_IClassFactory, (void**)&cf);
2595 if(hres == REGDB_E_CLASSNOTREG)
2596 check_codebase(doc->window, nselem);
2597 if(FAILED(hres))
2598 return NULL;
2600 hres = IClassFactory_QueryInterface(cf, &IID_IClassFactoryEx, (void**)&cfex);
2601 if(SUCCEEDED(hres)) {
2602 FIXME("Use IClassFactoryEx\n");
2603 IClassFactoryEx_Release(cfex);
2606 hres = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)&obj);
2607 IClassFactory_Release(cf);
2608 if(FAILED(hres))
2609 return NULL;
2611 return obj;
2614 void detach_plugin_host(PluginHost *host)
2616 HRESULT hres;
2618 TRACE("%p\n", host);
2620 if(!host->doc)
2621 return;
2623 if(host->ip_object) {
2624 if(host->ui_active)
2625 IOleInPlaceObject_UIDeactivate(host->ip_object);
2626 IOleInPlaceObject_InPlaceDeactivate(host->ip_object);
2629 if(host->plugin_unk) {
2630 IOleObject *ole_obj;
2632 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleObject, (void**)&ole_obj);
2633 if(SUCCEEDED(hres)) {
2634 if(!host->ip_object)
2635 IOleObject_Close(ole_obj, OLECLOSE_NOSAVE);
2636 IOleObject_SetClientSite(ole_obj, NULL);
2637 IOleObject_Release(ole_obj);
2641 if(host->sink) {
2642 IConnectionPointContainer *cp_container;
2643 IConnectionPoint *cp;
2645 assert(host->plugin_unk != NULL);
2647 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IConnectionPointContainer, (void**)&cp_container);
2648 if(SUCCEEDED(hres)) {
2649 hres = IConnectionPointContainer_FindConnectionPoint(cp_container, &host->sink->iid, &cp);
2650 IConnectionPointContainer_Release(cp_container);
2651 if(SUCCEEDED(hres)) {
2652 IConnectionPoint_Unadvise(cp, host->sink->cookie);
2653 IConnectionPoint_Release(cp);
2657 host->sink->host = NULL;
2658 IDispatch_Release(&host->sink->IDispatch_iface);
2659 host->sink = NULL;
2662 release_plugin_ifaces(host);
2664 list_remove(&host->entry);
2665 list_init(&host->entry);
2666 host->doc = NULL;
2668 if(host->element) {
2669 nsIDOMElement *nselem = host->element->element.dom_element;
2670 nsIObjectLoadingContent *olc;
2672 host->element->plugin_host = NULL;
2673 host->element = NULL;
2675 if(NS_SUCCEEDED(nsIDOMElement_QueryInterface(nselem, &IID_nsIObjectLoadingContent, (void**)&olc))) {
2676 nsIObjectLoadingContent_StopPluginInstance(olc);
2677 nsIObjectLoadingContent_Release(olc);
2679 IOleClientSite_Release(&host->IOleClientSite_iface);
2683 HRESULT create_plugin_host(HTMLDocumentNode *doc, HTMLPluginContainer *container)
2685 PluginHost *host;
2686 IUnknown *unk;
2687 CLSID clsid;
2689 assert(!container->plugin_host);
2691 unk = create_activex_object(doc, container->element.dom_element, &clsid);
2692 if(!unk)
2693 return E_FAIL;
2695 host = calloc(1, sizeof(*host));
2696 if(!host) {
2697 IUnknown_Release(unk);
2698 return E_OUTOFMEMORY;
2701 host->IOleClientSite_iface.lpVtbl = &OleClientSiteVtbl;
2702 host->IAdviseSinkEx_iface.lpVtbl = &AdviseSinkExVtbl;
2703 host->IPropertyNotifySink_iface.lpVtbl = &PropertyNotifySinkVtbl;
2704 host->IDispatch_iface.lpVtbl = &DispatchVtbl;
2705 host->IOleInPlaceSiteEx_iface.lpVtbl = &OleInPlaceSiteExVtbl;
2706 host->IOleControlSite_iface.lpVtbl = &OleControlSiteVtbl;
2707 host->IBindHost_iface.lpVtbl = &BindHostVtbl;
2708 host->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
2710 host->ref = 1;
2712 host->plugin_unk = unk;
2713 host->clsid = clsid;
2715 host->doc = doc;
2716 list_add_tail(&doc->plugin_hosts, &host->entry);
2718 container->plugin_host = host;
2719 host->element = container;
2721 initialize_plugin_object(host);
2723 return S_OK;