ws2_32/tests: Add some tests for opening the Afd device.
[wine.git] / dlls / mshtml / pluginhost.c
blobd880cc89a9d5eaa72776e60705e8b118b1b2492b
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>
20 #include <assert.h>
22 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "ole2.h"
28 #include "shlobj.h"
29 #include "mshtmdid.h"
31 #include "mshtml_private.h"
32 #include "pluginhost.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
38 typedef struct {
39 IPropertyBag IPropertyBag_iface;
40 IPropertyBag2 IPropertyBag2_iface;
42 LONG ref;
44 struct list props;
45 } PropertyBag;
47 typedef struct {
48 struct list entry;
49 WCHAR *name;
50 WCHAR *value;
51 } param_prop_t;
53 static void free_prop(param_prop_t *prop)
55 list_remove(&prop->entry);
57 heap_free(prop->name);
58 heap_free(prop->value);
59 heap_free(prop);
62 static param_prop_t *find_prop(PropertyBag *prop_bag, const WCHAR *name)
64 param_prop_t *iter;
66 LIST_FOR_EACH_ENTRY(iter, &prop_bag->props, param_prop_t, entry) {
67 if(!wcsicmp(iter->name, name))
68 return iter;
71 return NULL;
74 static HRESULT add_prop(PropertyBag *prop_bag, const WCHAR *name, const WCHAR *value)
76 param_prop_t *prop;
78 if(!name || !value)
79 return S_OK;
81 TRACE("%p %s %s\n", prop_bag, debugstr_w(name), debugstr_w(value));
83 prop = heap_alloc(sizeof(*prop));
84 if(!prop)
85 return E_OUTOFMEMORY;
87 prop->name = heap_strdupW(name);
88 prop->value = heap_strdupW(value);
89 if(!prop->name || !prop->value) {
90 list_init(&prop->entry);
91 free_prop(prop);
92 return E_OUTOFMEMORY;
95 list_add_tail(&prop_bag->props, &prop->entry);
96 return S_OK;
99 static inline PropertyBag *impl_from_IPropertyBag(IPropertyBag *iface)
101 return CONTAINING_RECORD(iface, PropertyBag, IPropertyBag_iface);
104 static HRESULT WINAPI PropertyBag_QueryInterface(IPropertyBag *iface, REFIID riid, void **ppv)
106 PropertyBag *This = impl_from_IPropertyBag(iface);
108 if(IsEqualGUID(&IID_IUnknown, riid)) {
109 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
110 *ppv = &This->IPropertyBag_iface;
111 }else if(IsEqualGUID(&IID_IPropertyBag, riid)) {
112 TRACE("(%p)->(IID_IPropertyBag %p)\n", This, ppv);
113 *ppv = &This->IPropertyBag_iface;
114 }else if(IsEqualGUID(&IID_IPropertyBag2, riid)) {
115 TRACE("(%p)->(IID_IPropertyBag2 %p)\n", This, ppv);
116 *ppv = &This->IPropertyBag2_iface;
117 }else {
118 WARN("Unsopported interface %s\n", debugstr_guid(riid));
119 *ppv = NULL;
120 return E_NOINTERFACE;
123 IUnknown_AddRef((IUnknown*)*ppv);
124 return S_OK;
127 static ULONG WINAPI PropertyBag_AddRef(IPropertyBag *iface)
129 PropertyBag *This = impl_from_IPropertyBag(iface);
130 LONG ref = InterlockedIncrement(&This->ref);
132 TRACE("(%p) ref=%d\n", This, ref);
134 return ref;
137 static ULONG WINAPI PropertyBag_Release(IPropertyBag *iface)
139 PropertyBag *This = impl_from_IPropertyBag(iface);
140 LONG ref = InterlockedDecrement(&This->ref);
142 TRACE("(%p) ref=%d\n", This, ref);
144 if(!ref) {
145 while(!list_empty(&This->props))
146 free_prop(LIST_ENTRY(This->props.next, param_prop_t, entry));
147 heap_free(This);
150 return ref;
153 static HRESULT WINAPI PropertyBag_Read(IPropertyBag *iface, LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog)
155 PropertyBag *This = impl_from_IPropertyBag(iface);
156 param_prop_t *prop;
157 VARIANT v;
159 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog);
161 prop = find_prop(This, pszPropName);
162 if(!prop) {
163 TRACE("Not found\n");
164 return E_INVALIDARG;
167 V_BSTR(&v) = SysAllocString(prop->value);
168 if(!V_BSTR(&v))
169 return E_OUTOFMEMORY;
171 if(V_VT(pVar) != VT_BSTR) {
172 HRESULT hres;
174 V_VT(&v) = VT_BSTR;
175 hres = VariantChangeType(pVar, &v, 0, V_VT(pVar));
176 SysFreeString(V_BSTR(&v));
177 return hres;
180 V_BSTR(pVar) = V_BSTR(&v);
181 return S_OK;
184 static HRESULT WINAPI PropertyBag_Write(IPropertyBag *iface, LPCOLESTR pszPropName, VARIANT *pVar)
186 PropertyBag *This = impl_from_IPropertyBag(iface);
187 FIXME("(%p)->(%s %s)\n", This, debugstr_w(pszPropName), debugstr_variant(pVar));
188 return E_NOTIMPL;
191 static const IPropertyBagVtbl PropertyBagVtbl = {
192 PropertyBag_QueryInterface,
193 PropertyBag_AddRef,
194 PropertyBag_Release,
195 PropertyBag_Read,
196 PropertyBag_Write
199 static inline PropertyBag *impl_from_IPropertyBag2(IPropertyBag2 *iface)
201 return CONTAINING_RECORD(iface, PropertyBag, IPropertyBag2_iface);
204 static HRESULT WINAPI PropertyBag2_QueryInterface(IPropertyBag2 *iface, REFIID riid, void **ppv)
206 PropertyBag *This = impl_from_IPropertyBag2(iface);
207 return IPropertyBag_QueryInterface(&This->IPropertyBag_iface, riid, ppv);
210 static ULONG WINAPI PropertyBag2_AddRef(IPropertyBag2 *iface)
212 PropertyBag *This = impl_from_IPropertyBag2(iface);
213 return IPropertyBag_AddRef(&This->IPropertyBag_iface);
216 static ULONG WINAPI PropertyBag2_Release(IPropertyBag2 *iface)
218 PropertyBag *This = impl_from_IPropertyBag2(iface);
219 return IPropertyBag_Release(&This->IPropertyBag_iface);
222 static HRESULT WINAPI PropertyBag2_Read(IPropertyBag2 *iface, ULONG cProperties, PROPBAG2 *pPropBag,
223 IErrorLog *pErrLog, VARIANT *pvarValue, HRESULT *phrError)
225 PropertyBag *This = impl_from_IPropertyBag2(iface);
226 FIXME("(%p)->(%d %p %p %p %p)\n", This, cProperties, pPropBag, pErrLog, pvarValue, phrError);
227 return E_NOTIMPL;
230 static HRESULT WINAPI PropertyBag2_Write(IPropertyBag2 *iface, ULONG cProperties, PROPBAG2 *pPropBag, VARIANT *pvarValue)
232 PropertyBag *This = impl_from_IPropertyBag2(iface);
233 FIXME("(%p)->(%d %p %s)\n", This, cProperties, pPropBag, debugstr_variant(pvarValue));
234 return E_NOTIMPL;
237 static HRESULT WINAPI PropertyBag2_CountProperties(IPropertyBag2 *iface, ULONG *pcProperties)
239 PropertyBag *This = impl_from_IPropertyBag2(iface);
240 FIXME("(%p)->(%p)\n", This, pcProperties);
241 return E_NOTIMPL;
244 static HRESULT WINAPI PropertyBag2_GetPropertyInfo(IPropertyBag2 *iface, ULONG iProperty, ULONG cProperties,
245 PROPBAG2 *pPropBag, ULONG *pcProperties)
247 PropertyBag *This = impl_from_IPropertyBag2(iface);
248 FIXME("(%p)->(%u %u %p %p)\n", This, iProperty, cProperties, pPropBag, pcProperties);
249 return E_NOTIMPL;
252 static HRESULT WINAPI PropertyBag2_LoadObject(IPropertyBag2 *iface, LPCOLESTR pstrName, DWORD dwHint,
253 IUnknown *pUnkObject, IErrorLog *pErrLog)
255 PropertyBag *This = impl_from_IPropertyBag2(iface);
256 FIXME("(%p)->(%s %x %p %p)\n", This, debugstr_w(pstrName), dwHint, pUnkObject, pErrLog);
257 return E_NOTIMPL;
260 static const IPropertyBag2Vtbl PropertyBag2Vtbl = {
261 PropertyBag2_QueryInterface,
262 PropertyBag2_AddRef,
263 PropertyBag2_Release,
264 PropertyBag2_Read,
265 PropertyBag2_Write,
266 PropertyBag2_CountProperties,
267 PropertyBag2_GetPropertyInfo,
268 PropertyBag2_LoadObject
271 static HRESULT fill_props(nsIDOMElement *nselem, PropertyBag *prop_bag)
273 const PRUnichar *name, *value;
274 nsAString name_str, value_str;
275 nsIDOMHTMLCollection *params;
276 nsIDOMElement *param_elem;
277 UINT32 length, i;
278 nsIDOMNode *nsnode;
279 nsresult nsres;
280 HRESULT hres = S_OK;
282 nsAString_InitDepend(&name_str, L"param");
283 nsres = nsIDOMElement_GetElementsByTagName(nselem, &name_str, &params);
284 nsAString_Finish(&name_str);
285 if(NS_FAILED(nsres))
286 return E_FAIL;
288 nsres = nsIDOMHTMLCollection_GetLength(params, &length);
289 if(NS_FAILED(nsres))
290 length = 0;
292 for(i=0; i < length; i++) {
293 nsres = nsIDOMHTMLCollection_Item(params, i, &nsnode);
294 if(NS_FAILED(nsres)) {
295 hres = E_FAIL;
296 break;
299 nsres = nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMElement, (void**)&param_elem);
300 nsIDOMNode_Release(nsnode);
301 if(NS_FAILED(nsres)) {
302 hres = E_FAIL;
303 break;
306 nsres = get_elem_attr_value(param_elem, L"name", &name_str, &name);
307 if(NS_SUCCEEDED(nsres)) {
308 nsres = get_elem_attr_value(param_elem, L"value", &value_str, &value);
309 if(NS_SUCCEEDED(nsres)) {
310 hres = add_prop(prop_bag, name, value);
311 nsAString_Finish(&value_str);
314 nsAString_Finish(&name_str);
317 nsIDOMElement_Release(param_elem);
318 if(FAILED(hres))
319 break;
320 if(NS_FAILED(nsres)) {
321 hres = E_FAIL;
322 break;
326 nsIDOMHTMLCollection_Release(params);
327 return hres;
330 static HRESULT create_param_prop_bag(nsIDOMElement *nselem, IPropertyBag **ret)
332 PropertyBag *prop_bag;
333 HRESULT hres;
335 prop_bag = heap_alloc(sizeof(*prop_bag));
336 if(!prop_bag)
337 return E_OUTOFMEMORY;
339 prop_bag->IPropertyBag_iface.lpVtbl = &PropertyBagVtbl;
340 prop_bag->IPropertyBag2_iface.lpVtbl = &PropertyBag2Vtbl;
341 prop_bag->ref = 1;
343 list_init(&prop_bag->props);
344 hres = fill_props(nselem, prop_bag);
345 if(FAILED(hres) || list_empty(&prop_bag->props)) {
346 IPropertyBag_Release(&prop_bag->IPropertyBag_iface);
347 *ret = NULL;
348 return hres;
351 *ret = &prop_bag->IPropertyBag_iface;
352 return S_OK;
355 static BOOL check_load_safety(PluginHost *host)
357 DWORD policy_size, policy;
358 struct CONFIRMSAFETY cs;
359 BYTE *ppolicy;
360 HRESULT hres;
362 cs.clsid = host->clsid;
363 cs.pUnk = host->plugin_unk;
364 cs.dwFlags = CONFIRMSAFETYACTION_LOADOBJECT;
366 hres = IInternetHostSecurityManager_QueryCustomPolicy(&host->doc->IInternetHostSecurityManager_iface,
367 &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
368 if(FAILED(hres))
369 return FALSE;
371 policy = *(DWORD*)ppolicy;
372 CoTaskMemFree(ppolicy);
373 return policy == URLPOLICY_ALLOW;
376 static BOOL check_script_safety(PluginHost *host)
378 DISPPARAMS params = {NULL,NULL,0,0};
379 DWORD policy_size, policy;
380 struct CONFIRMSAFETY cs;
381 BYTE *ppolicy;
382 ULONG err = 0;
383 VARIANT v;
384 HRESULT hres;
386 cs.clsid = host->clsid;
387 cs.pUnk = host->plugin_unk;
388 cs.dwFlags = 0;
390 hres = IInternetHostSecurityManager_QueryCustomPolicy(&host->doc->IInternetHostSecurityManager_iface,
391 &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
392 if(FAILED(hres))
393 return FALSE;
395 policy = *(DWORD*)ppolicy;
396 CoTaskMemFree(ppolicy);
398 if(policy != URLPOLICY_ALLOW)
399 return FALSE;
401 V_VT(&v) = VT_EMPTY;
402 hres = IDispatch_Invoke(host->disp, DISPID_SECURITYCTX, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, &v, NULL, &err);
403 if(SUCCEEDED(hres)) {
404 FIXME("Handle security ctx %s\n", debugstr_variant(&v));
405 return FALSE;
408 return TRUE;
411 static void update_readystate(PluginHost *host)
413 DISPPARAMS params = {NULL,NULL,0,0};
414 IDispatchEx *dispex;
415 IDispatch *disp;
416 ULONG err = 0;
417 VARIANT v;
418 HRESULT hres;
420 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatchEx, (void**)&dispex);
421 if(SUCCEEDED(hres)) {
422 FIXME("Use IDispatchEx\n");
423 IDispatchEx_Release(dispex);
426 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatch, (void**)&disp);
427 if(FAILED(hres))
428 return;
430 hres = IDispatch_Invoke(disp, DISPID_READYSTATE, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, &v, NULL, &err);
431 IDispatch_Release(disp);
432 if(SUCCEEDED(hres)) {
433 /* FIXME: make plugin readystate affect document readystate */
434 TRACE("readystate = %s\n", debugstr_variant(&v));
435 VariantClear(&v);
439 /* FIXME: We shouldn't need this function and we should embed plugin directly in the main document */
440 static void get_pos_rect(PluginHost *host, RECT *ret)
442 SetRect(ret, 0, 0, host->rect.right - host->rect.left, host->rect.bottom - host->rect.top);
445 static void load_prop_bag(PluginHost *host, IPersistPropertyBag *persist_prop_bag)
447 IPropertyBag *prop_bag;
448 HRESULT hres;
450 hres = create_param_prop_bag(host->element->element.dom_element, &prop_bag);
451 if(FAILED(hres))
452 return;
454 if(prop_bag && !check_load_safety(host)) {
455 IPropertyBag_Release(prop_bag);
456 prop_bag = NULL;
459 if(prop_bag) {
460 hres = IPersistPropertyBag_Load(persist_prop_bag, prop_bag, NULL);
461 IPropertyBag_Release(prop_bag);
462 if(FAILED(hres))
463 WARN("Load failed: %08x\n", hres);
464 }else {
465 hres = IPersistPropertyBag_InitNew(persist_prop_bag);
466 if(FAILED(hres))
467 WARN("InitNew failed: %08x\n", hres);
471 static void load_plugin(PluginHost *host)
473 IPersistPropertyBag2 *persist_prop_bag2;
474 IPersistPropertyBag *persist_prop_bag;
475 HRESULT hres;
477 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IPersistPropertyBag2, (void**)&persist_prop_bag2);
478 if(SUCCEEDED(hres)) {
479 FIXME("Use IPersistPropertyBag2 iface\n");
480 IPersistPropertyBag2_Release(persist_prop_bag2);
481 return;
484 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IPersistPropertyBag, (void**)&persist_prop_bag);
485 if(SUCCEEDED(hres)) {
486 load_prop_bag(host, persist_prop_bag);
487 IPersistPropertyBag_Release(persist_prop_bag);
488 return;
491 FIXME("No IPersistPropertyBag iface\n");
494 static void initialize_plugin_object(PluginHost *host)
496 IClientSecurity *client_security;
497 IQuickActivate *quick_activate;
498 IOleObject *ole_obj = NULL;
499 IOleCommandTarget *cmdtrg;
500 IViewObjectEx *view_obj;
501 IDispatchEx *dispex;
502 IDispatch *disp;
503 HRESULT hres;
505 /* Note native calls QI on plugin for an undocumented IID and CLSID_HTMLDocument */
507 /* FIXME: call FreezeEvents(TRUE) */
509 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IClientSecurity, (void**)&client_security);
510 if(SUCCEEDED(hres)) {
511 FIXME("Handle IClientSecurity\n");
512 IClientSecurity_Release(client_security);
513 return;
516 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IQuickActivate, (void**)&quick_activate);
517 if(SUCCEEDED(hres)) {
518 QACONTAINER container = {sizeof(container)};
519 QACONTROL control = {sizeof(control)};
521 TRACE("Using IQuickActivate\n");
523 container.pClientSite = &host->IOleClientSite_iface;
524 container.dwAmbientFlags = QACONTAINER_SUPPORTSMNEMONICS|QACONTAINER_MESSAGEREFLECT|QACONTAINER_USERMODE;
525 container.pAdviseSink = &host->IAdviseSinkEx_iface;
526 container.pPropertyNotifySink = &host->IPropertyNotifySink_iface;
528 hres = IQuickActivate_QuickActivate(quick_activate, &container, &control);
529 IQuickActivate_Release(quick_activate);
530 if(FAILED(hres))
531 FIXME("QuickActivate failed: %08x\n", hres);
532 }else {
533 DWORD status = 0;
535 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleObject, (void**)&ole_obj);
536 if(SUCCEEDED(hres)) {
537 hres = IOleObject_GetMiscStatus(ole_obj, DVASPECT_CONTENT, &status);
538 TRACE("GetMiscStatus returned %08x %x\n", hres, status);
540 hres = IOleObject_SetClientSite(ole_obj, &host->IOleClientSite_iface);
541 IOleObject_Release(ole_obj);
542 if(FAILED(hres)) {
543 FIXME("SetClientSite failed: %08x\n", hres);
544 return;
546 }else {
547 TRACE("Plugin does not support IOleObject\n");
551 load_plugin(host);
553 if(ole_obj) {
554 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IViewObjectEx, (void**)&view_obj);
555 if(SUCCEEDED(hres)) {
556 DWORD view_status = 0;
558 hres = IViewObjectEx_SetAdvise(view_obj, DVASPECT_CONTENT, 0, (IAdviseSink*)&host->IAdviseSinkEx_iface);
559 if(FAILED(hres))
560 WARN("SetAdvise failed: %08x\n", hres);
562 hres = IViewObjectEx_GetViewStatus(view_obj, &view_status);
563 IViewObjectEx_Release(view_obj);
564 TRACE("GetViewStatus returned %08x %x\n", hres, view_status);
568 update_readystate(host);
570 /* NOTE: Native QIs for IActiveScript, an undocumented IID, IOleControl and IRunnableObject */
572 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatchEx, (void**)&dispex);
573 if(SUCCEEDED(hres)) {
574 FIXME("Use IDispatchEx\n");
575 host->disp = (IDispatch*)dispex;
576 }else {
577 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatch, (void**)&disp);
578 if(SUCCEEDED(hres))
579 host->disp = disp;
580 else
581 TRACE("no IDispatch iface\n");
584 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleCommandTarget, (void**)&cmdtrg);
585 if(SUCCEEDED(hres)) {
586 FIXME("Use IOleCommandTarget\n");
587 IOleCommandTarget_Release(cmdtrg);
591 static void embed_plugin_object(PluginHost *host)
593 IOleObject *ole_obj;
594 RECT rect;
595 HRESULT hres;
597 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleObject, (void**)&ole_obj);
598 if(FAILED(hres)) {
599 FIXME("Plugin does not support IOleObject\n");
600 return;
603 get_pos_rect(host, &rect);
604 hres = IOleObject_DoVerb(ole_obj, OLEIVERB_INPLACEACTIVATE, NULL, &host->IOleClientSite_iface, 0, host->hwnd, &rect);
605 IOleObject_Release(ole_obj);
606 if(FAILED(hres))
607 WARN("DoVerb failed: %08x\n", hres);
609 if(host->ip_object) {
610 HWND hwnd;
612 hres = IOleInPlaceObject_GetWindow(host->ip_object, &hwnd);
613 if(SUCCEEDED(hres))
614 TRACE("hwnd %p\n", hwnd);
618 void update_plugin_window(PluginHost *host, HWND hwnd, const RECT *rect)
620 BOOL rect_changed = FALSE;
622 if(!hwnd || (host->hwnd && host->hwnd != hwnd)) {
623 FIXME("unhandled hwnd\n");
624 return;
627 TRACE("%p %s\n", hwnd, wine_dbgstr_rect(rect));
629 if(!EqualRect(rect, &host->rect)) {
630 host->rect = *rect;
631 rect_changed = TRUE;
634 if(!host->hwnd) {
635 host->hwnd = hwnd;
636 embed_plugin_object(host);
639 if(rect_changed && host->ip_object)
640 IOleInPlaceObject_SetObjectRects(host->ip_object, &host->rect, &host->rect);
643 static void notif_enabled(PluginHost *plugin_host)
645 DISPPARAMS args = {NULL, NULL, 0, 0};
646 IDispatch *disp;
647 ULONG err = 0;
648 VARIANT res;
649 HRESULT hres;
651 hres = IUnknown_QueryInterface(plugin_host->plugin_unk, &IID_IDispatch, (void**)&disp);
652 if(FAILED(hres)) {
653 FIXME("Could not get IDispatch iface: %08x\n", hres);
654 return;
657 V_VT(&res) = VT_EMPTY;
658 hres = IDispatch_Invoke(disp, DISPID_ENABLED, &IID_NULL, 0/*FIXME*/, DISPATCH_PROPERTYGET, &args, &res, NULL, &err);
659 IDispatch_Release(disp);
660 if(SUCCEEDED(hres)) {
661 FIXME("Got enabled %s\n", debugstr_variant(&res));
662 VariantClear(&res);
666 void notif_container_change(HTMLPluginContainer *plugin_container, DISPID dispid)
668 IOleControl *ole_control;
669 HRESULT hres;
671 if(!plugin_container->plugin_host || !plugin_container->plugin_host->plugin_unk)
672 return;
674 notif_enabled(plugin_container->plugin_host);
676 hres = IUnknown_QueryInterface(plugin_container->plugin_host->plugin_unk, &IID_IOleControl, (void**)&ole_control);
677 if(SUCCEEDED(hres)) {
678 IOleControl_OnAmbientPropertyChange(ole_control, dispid);
679 IOleControl_Release(ole_control);
683 HRESULT get_plugin_disp(HTMLPluginContainer *plugin_container, IDispatch **ret)
685 PluginHost *host;
687 host = plugin_container->plugin_host;
688 if(!host) {
689 ERR("No plugin host\n");
690 return E_UNEXPECTED;
693 if(!host->disp) {
694 *ret = NULL;
695 return S_OK;
698 if(!check_script_safety(host)) {
699 FIXME("Insecure object\n");
700 return E_FAIL;
703 IDispatch_AddRef(host->disp);
704 *ret = host->disp;
705 return S_OK;
708 HRESULT get_plugin_dispid(HTMLPluginContainer *plugin_container, WCHAR *name, DISPID *ret)
710 IDispatch *disp;
711 DISPID id;
712 DWORD i;
713 HRESULT hres;
715 if(!plugin_container->plugin_host) {
716 WARN("no plugin host\n");
717 return DISP_E_UNKNOWNNAME;
720 disp = plugin_container->plugin_host->disp;
721 if(!disp)
722 return DISP_E_UNKNOWNNAME;
724 hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, &id);
725 if(FAILED(hres)) {
726 TRACE("no prop %s\n", debugstr_w(name));
727 return DISP_E_UNKNOWNNAME;
730 for(i=0; i < plugin_container->props_len; i++) {
731 if(id == plugin_container->props[i]) {
732 *ret = MSHTML_DISPID_CUSTOM_MIN+i;
733 return S_OK;
737 if(!plugin_container->props) {
738 plugin_container->props = heap_alloc(8*sizeof(DISPID));
739 if(!plugin_container->props)
740 return E_OUTOFMEMORY;
741 plugin_container->props_size = 8;
742 }else if(plugin_container->props_len == plugin_container->props_size) {
743 DISPID *new_props;
745 new_props = heap_realloc(plugin_container->props, plugin_container->props_size*2*sizeof(DISPID));
746 if(!new_props)
747 return E_OUTOFMEMORY;
749 plugin_container->props = new_props;
750 plugin_container->props_size *= 2;
753 plugin_container->props[plugin_container->props_len] = id;
754 *ret = MSHTML_DISPID_CUSTOM_MIN+plugin_container->props_len;
755 plugin_container->props_len++;
756 return S_OK;
759 HRESULT invoke_plugin_prop(HTMLPluginContainer *plugin_container, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
760 VARIANT *res, EXCEPINFO *ei)
762 PluginHost *host;
764 host = plugin_container->plugin_host;
765 if(!host || !host->disp) {
766 FIXME("Called with no disp\n");
767 return E_UNEXPECTED;
770 if(!check_script_safety(host)) {
771 FIXME("Insecure object\n");
772 return E_FAIL;
775 if(id < MSHTML_DISPID_CUSTOM_MIN || id > MSHTML_DISPID_CUSTOM_MIN + plugin_container->props_len) {
776 ERR("Invalid id\n");
777 return E_FAIL;
780 return IDispatch_Invoke(host->disp, plugin_container->props[id-MSHTML_DISPID_CUSTOM_MIN], &IID_NULL,
781 lcid, flags, params, res, ei, NULL);
784 typedef struct {
785 DISPID id;
786 IDispatch *disp;
787 } sink_entry_t;
789 struct PHEventSink {
790 IDispatch IDispatch_iface;
792 LONG ref;
794 PluginHost *host;
795 ITypeInfo *typeinfo;
796 GUID iid;
797 DWORD cookie;
798 BOOL is_dispiface;
800 sink_entry_t *handlers;
801 DWORD handlers_cnt;
802 DWORD handlers_size;
805 static sink_entry_t *find_sink_entry(PHEventSink *sink, DISPID id)
807 sink_entry_t *iter;
809 for(iter = sink->handlers; iter < sink->handlers+sink->handlers_cnt; iter++) {
810 if(iter->id == id)
811 return iter;
814 return NULL;
817 static void add_sink_handler(PHEventSink *sink, DISPID id, IDispatch *disp)
819 sink_entry_t *entry = find_sink_entry(sink, id);
821 if(entry) {
822 if(entry->disp)
823 IDispatch_Release(entry->disp);
824 }else {
825 if(!sink->handlers_size) {
826 sink->handlers = heap_alloc(4*sizeof(*sink->handlers));
827 if(!sink->handlers)
828 return;
829 sink->handlers_size = 4;
830 }else if(sink->handlers_cnt == sink->handlers_size) {
831 sink_entry_t *new_handlers;
833 new_handlers = heap_realloc(sink->handlers, 2*sink->handlers_size*sizeof(*sink->handlers));
834 if(!new_handlers)
835 return;
836 sink->handlers = new_handlers;
837 sink->handlers_size *= 2;
839 entry = sink->handlers + sink->handlers_cnt++;
840 entry->id = id;
843 IDispatch_AddRef(disp);
844 entry->disp = disp;
847 static inline PHEventSink *PHEventSink_from_IDispatch(IDispatch *iface)
849 return CONTAINING_RECORD(iface, PHEventSink, IDispatch_iface);
852 static HRESULT WINAPI PHEventSink_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
854 PHEventSink *This = PHEventSink_from_IDispatch(iface);
856 if(IsEqualGUID(riid, &IID_IUnknown)) {
857 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
858 *ppv = &This->IDispatch_iface;
859 }else if(IsEqualGUID(riid, &IID_IDispatch)) {
860 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
861 *ppv = &This->IDispatch_iface;
862 }else if(This->is_dispiface && IsEqualGUID(riid, &This->iid)) {
863 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
864 *ppv = &This->IDispatch_iface;
865 }else {
866 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
867 *ppv = NULL;
868 return E_NOINTERFACE;
871 IUnknown_AddRef((IUnknown*)*ppv);
872 return S_OK;
875 static ULONG WINAPI PHEventSink_AddRef(IDispatch *iface)
877 PHEventSink *This = PHEventSink_from_IDispatch(iface);
878 LONG ref = InterlockedIncrement(&This->ref);
880 TRACE("(%p)\n", This);
882 return ref;
885 static ULONG WINAPI PHEventSink_Release(IDispatch *iface)
887 PHEventSink *This = PHEventSink_from_IDispatch(iface);
888 LONG ref = InterlockedDecrement(&This->ref);
890 TRACE("(%p)\n", This);
892 if(!ref) {
893 unsigned i;
895 assert(!This->host);
897 for(i=0; i < This->handlers_cnt; i++) {
898 if(This->handlers[i].disp)
899 IDispatch_Release(This->handlers[i].disp);
901 heap_free(This->handlers);
902 heap_free(This);
905 return ref;
908 static HRESULT WINAPI PHEventSink_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
910 PHEventSink *This = PHEventSink_from_IDispatch(iface);
911 FIXME("(%p)->(%p)\n", This, pctinfo);
912 return E_NOTIMPL;
915 static HRESULT WINAPI PHEventSink_GetTypeInfo(IDispatch *iface, UINT iTInfo,
916 LCID lcid, ITypeInfo **ppTInfo)
918 PHEventSink *This = PHEventSink_from_IDispatch(iface);
919 FIXME("(%p)->(%d %d %p)\n", This, iTInfo, lcid, ppTInfo);
920 return E_NOTIMPL;
923 static HRESULT WINAPI PHEventSink_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *rgszNames,
924 UINT cNames, LCID lcid, DISPID *rgDispId)
926 PHEventSink *This = PHEventSink_from_IDispatch(iface);
927 FIXME("(%p)->(%s %p %u %d %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
928 return E_NOTIMPL;
931 static HRESULT WINAPI PHEventSink_Invoke(IDispatch *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
932 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
934 PHEventSink *This = PHEventSink_from_IDispatch(iface);
935 IDispatchEx *dispex;
936 sink_entry_t *entry;
937 HRESULT hres;
939 TRACE("(%p)->(%d %s %d %x %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), lcid, wFlags,
940 pDispParams, pVarResult, pExcepInfo, puArgErr);
942 if(!This->host) {
943 WARN("No host\n");
944 return E_UNEXPECTED;
947 entry = find_sink_entry(This, dispIdMember);
948 if(!entry || !entry->disp) {
949 WARN("No handler %d\n", dispIdMember);
950 if(pVarResult)
951 V_VT(pVarResult) = VT_EMPTY;
952 return S_OK;
955 hres = IDispatch_QueryInterface(entry->disp, &IID_IDispatchEx, (void**)&dispex);
957 TRACE("(%p) %d >>>\n", This, entry->id);
958 if(SUCCEEDED(hres)) {
959 hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, NULL);
960 IDispatchEx_Release(dispex);
961 }else {
962 hres = IDispatch_Invoke(entry->disp, DISPID_VALUE, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
964 if(SUCCEEDED(hres))
965 TRACE("(%p) %d <<<\n", This, entry->id);
966 else
967 WARN("(%p) %d <<< %08x\n", This, entry->id, hres);
968 return hres;
971 static const IDispatchVtbl PHCPDispatchVtbl = {
972 PHEventSink_QueryInterface,
973 PHEventSink_AddRef,
974 PHEventSink_Release,
975 PHEventSink_GetTypeInfoCount,
976 PHEventSink_GetTypeInfo,
977 PHEventSink_GetIDsOfNames,
978 PHEventSink_Invoke
981 static PHEventSink *create_event_sink(PluginHost *plugin_host, ITypeInfo *typeinfo)
983 IConnectionPointContainer *cp_container;
984 PHEventSink *ret;
985 IConnectionPoint *cp;
986 TYPEATTR *typeattr;
987 TYPEKIND typekind;
988 GUID guid;
989 HRESULT hres;
991 hres = ITypeInfo_GetTypeAttr(typeinfo, &typeattr);
992 if(FAILED(hres))
993 return NULL;
995 typekind = typeattr->typekind;
996 guid = typeattr->guid;
997 ITypeInfo_ReleaseTypeAttr(typeinfo, typeattr);
999 TRACE("guid %s typekind %d\n", debugstr_guid(&guid), typekind);
1001 if(typekind != TKIND_INTERFACE && typekind != TKIND_DISPATCH) {
1002 WARN("invalid typekind %d\n", typekind);
1003 return NULL;
1006 hres = IUnknown_QueryInterface(plugin_host->plugin_unk, &IID_IConnectionPointContainer, (void**)&cp_container);
1007 if(FAILED(hres)) {
1008 WARN("Could not get IConnectionPointContainer iface: %08x\n", hres);
1009 return NULL;
1012 hres = IConnectionPointContainer_FindConnectionPoint(cp_container, &guid, &cp);
1013 IConnectionPointContainer_Release(cp_container);
1014 if(FAILED(hres)) {
1015 WARN("Could not find %s connection point\n", debugstr_guid(&guid));
1016 return NULL;
1019 ret = heap_alloc_zero(sizeof(*ret));
1020 if(ret) {
1021 ret->IDispatch_iface.lpVtbl = &PHCPDispatchVtbl;
1022 ret->ref = 1;
1023 ret->host = plugin_host;
1024 ret->iid = guid;
1025 ret->is_dispiface = typekind == TKIND_DISPATCH;
1027 ITypeInfo_AddRef(typeinfo);
1028 ret->typeinfo = typeinfo;
1030 hres = IConnectionPoint_Advise(cp, (IUnknown*)&ret->IDispatch_iface, &ret->cookie);
1031 }else {
1032 hres = E_OUTOFMEMORY;
1035 IConnectionPoint_Release(cp);
1036 if(FAILED(hres)) {
1037 WARN("Advise failed: %08x\n", hres);
1038 return NULL;
1041 return ret;
1044 static ITypeInfo *get_eventiface_info(HTMLPluginContainer *plugin_container, ITypeInfo *class_info)
1046 int impl_types, i, impl_flags;
1047 ITypeInfo *ret = NULL;
1048 TYPEATTR *typeattr;
1049 HREFTYPE ref;
1050 HRESULT hres;
1052 hres = ITypeInfo_GetTypeAttr(class_info, &typeattr);
1053 if(FAILED(hres))
1054 return NULL;
1056 if(typeattr->typekind != TKIND_COCLASS) {
1057 WARN("not coclass\n");
1058 ITypeInfo_ReleaseTypeAttr(class_info, typeattr);
1059 return NULL;
1062 impl_types = typeattr->cImplTypes;
1063 ITypeInfo_ReleaseTypeAttr(class_info, typeattr);
1065 for(i=0; i<impl_types; i++) {
1066 hres = ITypeInfo_GetImplTypeFlags(class_info, i, &impl_flags);
1067 if(FAILED(hres))
1068 continue;
1070 if((impl_flags & IMPLTYPEFLAG_FSOURCE)) {
1071 if(!(impl_flags & IMPLTYPEFLAG_FDEFAULT)) {
1072 FIXME("Handle non-default source iface\n");
1073 continue;
1076 hres = ITypeInfo_GetRefTypeOfImplType(class_info, i, &ref);
1077 if(FAILED(hres))
1078 continue;
1080 hres = ITypeInfo_GetRefTypeInfo(class_info, ref, &ret);
1081 if(FAILED(hres))
1082 ret = NULL;
1086 return ret;
1089 void bind_activex_event(HTMLDocumentNode *doc, HTMLPluginContainer *plugin_container, WCHAR *event, IDispatch *disp)
1091 PluginHost *plugin_host = plugin_container->plugin_host;
1092 ITypeInfo *class_info, *source_info;
1093 DISPID id;
1094 HRESULT hres;
1096 TRACE("(%p %p %s %p)\n", doc, plugin_host, debugstr_w(event), disp);
1098 if(!plugin_host || !plugin_host->plugin_unk) {
1099 WARN("detached element %p\n", plugin_host);
1100 return;
1103 if(plugin_host->sink) {
1104 source_info = plugin_host->sink->typeinfo;
1105 ITypeInfo_AddRef(source_info);
1106 }else {
1107 IProvideClassInfo *provide_ci;
1109 hres = IUnknown_QueryInterface(plugin_host->plugin_unk, &IID_IProvideClassInfo, (void**)&provide_ci);
1110 if(FAILED(hres)) {
1111 FIXME("No IProvideClassInfo, try GetTypeInfo?\n");
1112 return;
1115 hres = IProvideClassInfo_GetClassInfo(provide_ci, &class_info);
1116 IProvideClassInfo_Release(provide_ci);
1117 if(FAILED(hres) || !class_info) {
1118 WARN("GetClassInfo failed: %08x\n", hres);
1119 return;
1122 source_info = get_eventiface_info(plugin_container, class_info);
1123 ITypeInfo_Release(class_info);
1124 if(!source_info)
1125 return;
1128 hres = ITypeInfo_GetIDsOfNames(source_info, &event, 1, &id);
1129 if(FAILED(hres))
1130 WARN("Could not get disp id: %08x\n", hres);
1131 else if(!plugin_host->sink)
1132 plugin_host->sink = create_event_sink(plugin_host, source_info);
1134 ITypeInfo_Release(source_info);
1135 if(FAILED(hres) || !plugin_host->sink)
1136 return;
1138 add_sink_handler(plugin_host->sink, id, disp);
1141 typedef struct {
1142 IOleInPlaceFrame IOleInPlaceFrame_iface;
1143 LONG ref;
1144 } InPlaceFrame;
1146 static inline InPlaceFrame *impl_from_IOleInPlaceFrame(IOleInPlaceFrame *iface)
1148 return CONTAINING_RECORD(iface, InPlaceFrame, IOleInPlaceFrame_iface);
1151 static HRESULT WINAPI InPlaceFrame_QueryInterface(IOleInPlaceFrame *iface,
1152 REFIID riid, void **ppv)
1154 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1156 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1158 if(IsEqualGUID(&IID_IUnknown, riid)) {
1159 *ppv = &This->IOleInPlaceFrame_iface;
1160 }else if(IsEqualGUID(&IID_IOleWindow, riid)) {
1161 *ppv = &This->IOleInPlaceFrame_iface;
1162 }else if(IsEqualGUID(&IID_IOleInPlaceUIWindow, riid)) {
1163 *ppv = &This->IOleInPlaceFrame_iface;
1164 }else if(IsEqualGUID(&IID_IOleInPlaceFrame, riid)) {
1165 *ppv = &This->IOleInPlaceFrame_iface;
1166 }else {
1167 WARN("Unsopported interface %s\n", debugstr_mshtml_guid(riid));
1168 *ppv = NULL;
1169 return E_NOINTERFACE;
1172 IUnknown_AddRef((IUnknown*)*ppv);
1173 return S_OK;
1176 static ULONG WINAPI InPlaceFrame_AddRef(IOleInPlaceFrame *iface)
1178 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1179 LONG ref = InterlockedIncrement(&This->ref);
1181 TRACE("(%p) ref=%d\n", This, ref);
1183 return ref;
1186 static ULONG WINAPI InPlaceFrame_Release(IOleInPlaceFrame *iface)
1188 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1189 LONG ref = InterlockedDecrement(&This->ref);
1191 TRACE("(%p) ref=%d\n", This, ref);
1193 if(!ref)
1194 heap_free(This);
1196 return ref;
1199 static HRESULT WINAPI InPlaceFrame_GetWindow(IOleInPlaceFrame *iface, HWND *phwnd)
1201 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1202 FIXME("(%p)->(%p)\n", This, phwnd);
1203 return E_NOTIMPL;
1206 static HRESULT WINAPI InPlaceFrame_ContextSensitiveHelp(IOleInPlaceFrame *iface,
1207 BOOL fEnterMode)
1209 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1210 FIXME("(%p)->(%x)\n", This, fEnterMode);
1211 return E_NOTIMPL;
1214 static HRESULT WINAPI InPlaceFrame_GetBorder(IOleInPlaceFrame *iface, LPRECT lprectBorder)
1216 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1217 FIXME("(%p)->(%p)\n", This, lprectBorder);
1218 return E_NOTIMPL;
1221 static HRESULT WINAPI InPlaceFrame_RequestBorderSpace(IOleInPlaceFrame *iface,
1222 LPCBORDERWIDTHS pborderwidths)
1224 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1225 FIXME("(%p)->(%p)\n", This, pborderwidths);
1226 return E_NOTIMPL;
1229 static HRESULT WINAPI InPlaceFrame_SetBorderSpace(IOleInPlaceFrame *iface,
1230 LPCBORDERWIDTHS pborderwidths)
1232 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1233 FIXME("(%p)->(%p)\n", This, pborderwidths);
1234 return E_NOTIMPL;
1237 static HRESULT WINAPI InPlaceFrame_SetActiveObject(IOleInPlaceFrame *iface,
1238 IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
1240 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1241 FIXME("(%p)->(%p %s)\n", This, pActiveObject, debugstr_w(pszObjName));
1242 return E_NOTIMPL;
1245 static HRESULT WINAPI InPlaceFrame_InsertMenus(IOleInPlaceFrame *iface, HMENU hmenuShared,
1246 LPOLEMENUGROUPWIDTHS lpMenuWidths)
1248 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1249 FIXME("(%p)->(%p %p)\n", This, hmenuShared, lpMenuWidths);
1250 return E_NOTIMPL;
1253 static HRESULT WINAPI InPlaceFrame_SetMenu(IOleInPlaceFrame *iface, HMENU hmenuShared,
1254 HOLEMENU holemenu, HWND hwndActiveObject)
1256 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1257 FIXME("(%p)->(%p %p %p)\n", This, hmenuShared, holemenu, hwndActiveObject);
1258 return E_NOTIMPL;
1261 static HRESULT WINAPI InPlaceFrame_RemoveMenus(IOleInPlaceFrame *iface, HMENU hmenuShared)
1263 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1264 FIXME("(%p)->(%p)\n", This, hmenuShared);
1265 return E_NOTIMPL;
1268 static HRESULT WINAPI InPlaceFrame_SetStatusText(IOleInPlaceFrame *iface,
1269 LPCOLESTR pszStatusText)
1271 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1272 FIXME("(%p)->(%s)\n", This, debugstr_w(pszStatusText));
1273 return E_NOTIMPL;
1276 static HRESULT WINAPI InPlaceFrame_EnableModeless(IOleInPlaceFrame *iface, BOOL fEnable)
1278 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1279 FIXME("(%p)->(%x)\n", This, fEnable);
1280 return E_NOTIMPL;
1283 static HRESULT WINAPI InPlaceFrame_TranslateAccelerator(IOleInPlaceFrame *iface, LPMSG lpmsg,
1284 WORD wID)
1286 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1287 FIXME("(%p)->(%p %d)\n", This, lpmsg, wID);
1288 return E_NOTIMPL;
1291 static const IOleInPlaceFrameVtbl OleInPlaceFrameVtbl = {
1292 InPlaceFrame_QueryInterface,
1293 InPlaceFrame_AddRef,
1294 InPlaceFrame_Release,
1295 InPlaceFrame_GetWindow,
1296 InPlaceFrame_ContextSensitiveHelp,
1297 InPlaceFrame_GetBorder,
1298 InPlaceFrame_RequestBorderSpace,
1299 InPlaceFrame_SetBorderSpace,
1300 InPlaceFrame_SetActiveObject,
1301 InPlaceFrame_InsertMenus,
1302 InPlaceFrame_SetMenu,
1303 InPlaceFrame_RemoveMenus,
1304 InPlaceFrame_SetStatusText,
1305 InPlaceFrame_EnableModeless,
1306 InPlaceFrame_TranslateAccelerator
1309 static HRESULT create_ip_frame(IOleInPlaceFrame **ret)
1311 InPlaceFrame *frame;
1313 frame = heap_alloc_zero(sizeof(*frame));
1314 if(!frame)
1315 return E_OUTOFMEMORY;
1317 frame->IOleInPlaceFrame_iface.lpVtbl = &OleInPlaceFrameVtbl;
1318 frame->ref = 1;
1320 *ret = &frame->IOleInPlaceFrame_iface;
1321 return S_OK;
1324 typedef struct {
1325 IOleInPlaceUIWindow IOleInPlaceUIWindow_iface;
1326 LONG ref;
1327 } InPlaceUIWindow;
1329 static inline InPlaceUIWindow *impl_from_IOleInPlaceUIWindow(IOleInPlaceUIWindow *iface)
1331 return CONTAINING_RECORD(iface, InPlaceUIWindow, IOleInPlaceUIWindow_iface);
1334 static HRESULT WINAPI InPlaceUIWindow_QueryInterface(IOleInPlaceUIWindow *iface, REFIID riid, void **ppv)
1336 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1338 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1340 if(IsEqualGUID(&IID_IUnknown, riid)) {
1341 *ppv = &This->IOleInPlaceUIWindow_iface;
1342 }else if(IsEqualGUID(&IID_IOleWindow, riid)) {
1343 *ppv = &This->IOleInPlaceUIWindow_iface;
1344 }else if(IsEqualGUID(&IID_IOleInPlaceUIWindow, riid)) {
1345 *ppv = &This->IOleInPlaceUIWindow_iface;
1346 }else {
1347 WARN("Unsopported interface %s\n", debugstr_mshtml_guid(riid));
1348 *ppv = NULL;
1349 return E_NOINTERFACE;
1352 IUnknown_AddRef((IUnknown*)*ppv);
1353 return S_OK;
1356 static ULONG WINAPI InPlaceUIWindow_AddRef(IOleInPlaceUIWindow *iface)
1358 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1359 LONG ref = InterlockedIncrement(&This->ref);
1361 TRACE("(%p) ref=%d\n", This, ref);
1363 return ref;
1366 static ULONG WINAPI InPlaceUIWindow_Release(IOleInPlaceUIWindow *iface)
1368 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1369 LONG ref = InterlockedDecrement(&This->ref);
1371 TRACE("(%p) ref=%d\n", This, ref);
1373 if(!ref)
1374 heap_free(This);
1376 return ref;
1379 static HRESULT WINAPI InPlaceUIWindow_GetWindow(IOleInPlaceUIWindow *iface, HWND *phwnd)
1381 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1382 FIXME("(%p)->(%p)\n", This, phwnd);
1383 return E_NOTIMPL;
1386 static HRESULT WINAPI InPlaceUIWindow_ContextSensitiveHelp(IOleInPlaceUIWindow *iface,
1387 BOOL fEnterMode)
1389 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1390 FIXME("(%p)->(%x)\n", This, fEnterMode);
1391 return E_NOTIMPL;
1394 static HRESULT WINAPI InPlaceUIWindow_GetBorder(IOleInPlaceUIWindow *iface, LPRECT lprectBorder)
1396 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1397 FIXME("(%p)->(%p)\n", This, lprectBorder);
1398 return E_NOTIMPL;
1401 static HRESULT WINAPI InPlaceUIWindow_RequestBorderSpace(IOleInPlaceUIWindow *iface,
1402 LPCBORDERWIDTHS pborderwidths)
1404 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1405 FIXME("(%p)->(%p)\n", This, pborderwidths);
1406 return E_NOTIMPL;
1409 static HRESULT WINAPI InPlaceUIWindow_SetBorderSpace(IOleInPlaceUIWindow *iface,
1410 LPCBORDERWIDTHS pborderwidths)
1412 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1413 FIXME("(%p)->(%p)\n", This, pborderwidths);
1414 return E_NOTIMPL;
1417 static HRESULT WINAPI InPlaceUIWindow_SetActiveObject(IOleInPlaceUIWindow *iface,
1418 IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
1420 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1421 FIXME("(%p)->(%p %s)\n", This, pActiveObject, debugstr_w(pszObjName));
1422 return E_NOTIMPL;
1425 static const IOleInPlaceUIWindowVtbl OleInPlaceUIWindowVtbl = {
1426 InPlaceUIWindow_QueryInterface,
1427 InPlaceUIWindow_AddRef,
1428 InPlaceUIWindow_Release,
1429 InPlaceUIWindow_GetWindow,
1430 InPlaceUIWindow_ContextSensitiveHelp,
1431 InPlaceUIWindow_GetBorder,
1432 InPlaceUIWindow_RequestBorderSpace,
1433 InPlaceUIWindow_SetBorderSpace,
1434 InPlaceUIWindow_SetActiveObject,
1437 static HRESULT create_ip_window(IOleInPlaceUIWindow **ret)
1439 InPlaceUIWindow *uiwindow;
1441 uiwindow = heap_alloc_zero(sizeof(*uiwindow));
1442 if(!uiwindow)
1443 return E_OUTOFMEMORY;
1445 uiwindow->IOleInPlaceUIWindow_iface.lpVtbl = &OleInPlaceUIWindowVtbl;
1446 uiwindow->ref = 1;
1448 *ret = &uiwindow->IOleInPlaceUIWindow_iface;
1449 return S_OK;
1452 static inline PluginHost *impl_from_IOleClientSite(IOleClientSite *iface)
1454 return CONTAINING_RECORD(iface, PluginHost, IOleClientSite_iface);
1457 static HRESULT WINAPI PHClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv)
1459 PluginHost *This = impl_from_IOleClientSite(iface);
1461 if(IsEqualGUID(&IID_IUnknown, riid)) {
1462 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1463 *ppv = &This->IOleClientSite_iface;
1464 }else if(IsEqualGUID(&IID_IOleClientSite, riid)) {
1465 TRACE("(%p)->(IID_IOleClientSite %p)\n", This, ppv);
1466 *ppv = &This->IOleClientSite_iface;
1467 }else if(IsEqualGUID(&IID_IAdviseSink, riid)) {
1468 TRACE("(%p)->(IID_IAdviseSink %p)\n", This, ppv);
1469 *ppv = &This->IAdviseSinkEx_iface;
1470 }else if(IsEqualGUID(&IID_IAdviseSinkEx, riid)) {
1471 TRACE("(%p)->(IID_IAdviseSinkEx %p)\n", This, ppv);
1472 *ppv = &This->IAdviseSinkEx_iface;
1473 }else if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) {
1474 TRACE("(%p)->(IID_IPropertyNotifySink %p)\n", This, ppv);
1475 *ppv = &This->IPropertyNotifySink_iface;
1476 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1477 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
1478 *ppv = &This->IDispatch_iface;
1479 }else if(IsEqualGUID(&IID_IOleWindow, riid)) {
1480 TRACE("(%p)->(IID_IOleWindow %p)\n", This, ppv);
1481 *ppv = &This->IOleInPlaceSiteEx_iface;
1482 }else if(IsEqualGUID(&IID_IOleInPlaceSite, riid)) {
1483 TRACE("(%p)->(IID_IOleInPlaceSite %p)\n", This, ppv);
1484 *ppv = &This->IOleInPlaceSiteEx_iface;
1485 }else if(IsEqualGUID(&IID_IOleInPlaceSiteEx, riid)) {
1486 TRACE("(%p)->(IID_IOleInPlaceSiteEx %p)\n", This, ppv);
1487 *ppv = &This->IOleInPlaceSiteEx_iface;
1488 }else if(IsEqualGUID(&IID_IOleControlSite, riid)) {
1489 TRACE("(%p)->(IID_IOleControlSite %p)\n", This, ppv);
1490 *ppv = &This->IOleControlSite_iface;
1491 }else if(IsEqualGUID(&IID_IBindHost, riid)) {
1492 TRACE("(%p)->(IID_IBindHost %p)\n", This, ppv);
1493 *ppv = &This->IBindHost_iface;
1494 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
1495 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
1496 *ppv = &This->IServiceProvider_iface;
1497 }else {
1498 WARN("Unsupported interface %s\n", debugstr_guid(riid));
1499 *ppv = NULL;
1500 return E_NOINTERFACE;
1503 IUnknown_AddRef((IUnknown*)*ppv);
1504 return S_OK;
1507 static ULONG WINAPI PHClientSite_AddRef(IOleClientSite *iface)
1509 PluginHost *This = impl_from_IOleClientSite(iface);
1510 LONG ref = InterlockedIncrement(&This->ref);
1512 TRACE("(%p) ref=%d\n", This, ref);
1514 return ref;
1517 static void release_plugin_ifaces(PluginHost *This)
1519 if(This->disp) {
1520 IDispatch_Release(This->disp);
1521 This->disp = NULL;
1524 if(This->ip_object) {
1525 IOleInPlaceObject_Release(This->ip_object);
1526 This->ip_object = NULL;
1529 if(This->plugin_unk) {
1530 IUnknown *unk = This->plugin_unk;
1531 LONG ref;
1533 This->plugin_unk = NULL;
1534 ref = IUnknown_Release(unk);
1536 TRACE("plugin ref = %d\n", ref);
1540 static ULONG WINAPI PHClientSite_Release(IOleClientSite *iface)
1542 PluginHost *This = impl_from_IOleClientSite(iface);
1543 LONG ref = InterlockedDecrement(&This->ref);
1545 TRACE("(%p) ref=%d\n", This, ref);
1547 if(!ref) {
1548 release_plugin_ifaces(This);
1549 if(This->sink) {
1550 This->sink->host = NULL;
1551 IDispatch_Release(&This->sink->IDispatch_iface);
1552 This->sink = NULL;
1554 list_remove(&This->entry);
1555 if(This->element)
1556 This->element->plugin_host = NULL;
1557 heap_free(This);
1560 return ref;
1563 static HRESULT WINAPI PHClientSite_SaveObject(IOleClientSite *iface)
1565 PluginHost *This = impl_from_IOleClientSite(iface);
1566 FIXME("(%p)\n", This);
1567 return E_NOTIMPL;
1570 static HRESULT WINAPI PHClientSite_GetMoniker(IOleClientSite *iface, DWORD dwAssign,
1571 DWORD dwWhichMoniker, IMoniker **ppmk)
1573 PluginHost *This = impl_from_IOleClientSite(iface);
1575 TRACE("(%p)->(%d %d %p)\n", This, dwAssign, dwWhichMoniker, ppmk);
1577 switch(dwWhichMoniker) {
1578 case OLEWHICHMK_CONTAINER:
1579 if(!This->doc || !This->doc->window || !This->doc->window->mon) {
1580 FIXME("no moniker\n");
1581 return E_UNEXPECTED;
1584 *ppmk = This->doc->window->mon;
1585 IMoniker_AddRef(*ppmk);
1586 break;
1587 default:
1588 FIXME("which %d\n", dwWhichMoniker);
1589 return E_NOTIMPL;
1592 return S_OK;
1595 static HRESULT WINAPI PHClientSite_GetContainer(IOleClientSite *iface, IOleContainer **ppContainer)
1597 PluginHost *This = impl_from_IOleClientSite(iface);
1599 TRACE("(%p)->(%p)\n", This, ppContainer);
1601 if(!This->doc) {
1602 ERR("Called on detached object\n");
1603 return E_UNEXPECTED;
1606 *ppContainer = &This->doc->basedoc.IOleContainer_iface;
1607 IOleContainer_AddRef(*ppContainer);
1608 return S_OK;
1611 static HRESULT WINAPI PHClientSite_ShowObject(IOleClientSite *iface)
1613 PluginHost *This = impl_from_IOleClientSite(iface);
1615 TRACE("(%p)\n", This);
1617 return S_OK;
1620 static HRESULT WINAPI PHClientSite_OnShowWindow(IOleClientSite *iface, BOOL fShow)
1622 PluginHost *This = impl_from_IOleClientSite(iface);
1623 FIXME("(%p)->(%x)\n", This, fShow);
1624 return E_NOTIMPL;
1627 static HRESULT WINAPI PHClientSite_RequestNewObjectLayout(IOleClientSite *iface)
1629 PluginHost *This = impl_from_IOleClientSite(iface);
1630 FIXME("(%p)\n", This);
1631 return E_NOTIMPL;
1634 static const IOleClientSiteVtbl OleClientSiteVtbl = {
1635 PHClientSite_QueryInterface,
1636 PHClientSite_AddRef,
1637 PHClientSite_Release,
1638 PHClientSite_SaveObject,
1639 PHClientSite_GetMoniker,
1640 PHClientSite_GetContainer,
1641 PHClientSite_ShowObject,
1642 PHClientSite_OnShowWindow,
1643 PHClientSite_RequestNewObjectLayout
1646 static inline PluginHost *impl_from_IAdviseSinkEx(IAdviseSinkEx *iface)
1648 return CONTAINING_RECORD(iface, PluginHost, IAdviseSinkEx_iface);
1651 static HRESULT WINAPI PHAdviseSinkEx_QueryInterface(IAdviseSinkEx *iface, REFIID riid, void **ppv)
1653 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1654 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1657 static ULONG WINAPI PHAdviseSinkEx_AddRef(IAdviseSinkEx *iface)
1659 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1660 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1663 static ULONG WINAPI PHAdviseSinkEx_Release(IAdviseSinkEx *iface)
1665 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1666 return IOleClientSite_Release(&This->IOleClientSite_iface);
1669 static void WINAPI PHAdviseSinkEx_OnDataChange(IAdviseSinkEx *iface, FORMATETC *pFormatetc, STGMEDIUM *pStgMedium)
1671 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1672 FIXME("(%p)->(%p %p)\n", This, pFormatetc, pStgMedium);
1675 static void WINAPI PHAdviseSinkEx_OnViewChange(IAdviseSinkEx *iface, DWORD dwAspect, LONG lindex)
1677 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1678 FIXME("(%p)->(%d %d)\n", This, dwAspect, lindex);
1681 static void WINAPI PHAdviseSinkEx_OnRename(IAdviseSinkEx *iface, IMoniker *pmk)
1683 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1684 FIXME("(%p)->(%p)\n", This, pmk);
1687 static void WINAPI PHAdviseSinkEx_OnSave(IAdviseSinkEx *iface)
1689 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1690 FIXME("(%p)\n", This);
1693 static void WINAPI PHAdviseSinkEx_OnClose(IAdviseSinkEx *iface)
1695 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1696 FIXME("(%p)\n", This);
1699 static void WINAPI PHAdviseSinkEx_OnViewStatusChange(IAdviseSinkEx *iface, DWORD dwViewStatus)
1701 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1702 FIXME("(%p)->(%d)\n", This, dwViewStatus);
1705 static const IAdviseSinkExVtbl AdviseSinkExVtbl = {
1706 PHAdviseSinkEx_QueryInterface,
1707 PHAdviseSinkEx_AddRef,
1708 PHAdviseSinkEx_Release,
1709 PHAdviseSinkEx_OnDataChange,
1710 PHAdviseSinkEx_OnViewChange,
1711 PHAdviseSinkEx_OnRename,
1712 PHAdviseSinkEx_OnSave,
1713 PHAdviseSinkEx_OnClose,
1714 PHAdviseSinkEx_OnViewStatusChange
1717 static inline PluginHost *impl_from_IPropertyNotifySink(IPropertyNotifySink *iface)
1719 return CONTAINING_RECORD(iface, PluginHost, IPropertyNotifySink_iface);
1722 static HRESULT WINAPI PHPropertyNotifySink_QueryInterface(IPropertyNotifySink *iface, REFIID riid, void **ppv)
1724 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1725 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1728 static ULONG WINAPI PHPropertyNotifySink_AddRef(IPropertyNotifySink *iface)
1730 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1731 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1734 static ULONG WINAPI PHPropertyNotifySink_Release(IPropertyNotifySink *iface)
1736 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1737 return IOleClientSite_Release(&This->IOleClientSite_iface);
1740 static HRESULT WINAPI PHPropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID)
1742 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1744 TRACE("(%p)->(%d)\n", This, dispID);
1746 switch(dispID) {
1747 case DISPID_READYSTATE:
1748 update_readystate(This);
1749 break;
1750 default :
1751 FIXME("Unimplemented dispID %d\n", dispID);
1752 return E_NOTIMPL;
1755 return S_OK;
1758 static HRESULT WINAPI PHPropertyNotifySink_OnRequestEdit(IPropertyNotifySink *iface, DISPID dispID)
1760 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1761 FIXME("(%p)->(%d)\n", This, dispID);
1762 return E_NOTIMPL;
1765 static const IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = {
1766 PHPropertyNotifySink_QueryInterface,
1767 PHPropertyNotifySink_AddRef,
1768 PHPropertyNotifySink_Release,
1769 PHPropertyNotifySink_OnChanged,
1770 PHPropertyNotifySink_OnRequestEdit
1773 static inline PluginHost *impl_from_IDispatch(IDispatch *iface)
1775 return CONTAINING_RECORD(iface, PluginHost, IDispatch_iface);
1778 static HRESULT WINAPI PHDispatch_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
1780 PluginHost *This = impl_from_IDispatch(iface);
1781 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1784 static ULONG WINAPI PHDispatch_AddRef(IDispatch *iface)
1786 PluginHost *This = impl_from_IDispatch(iface);
1787 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1790 static ULONG WINAPI PHDispatch_Release(IDispatch *iface)
1792 PluginHost *This = impl_from_IDispatch(iface);
1793 return IOleClientSite_Release(&This->IOleClientSite_iface);
1796 static HRESULT WINAPI PHDispatch_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
1798 PluginHost *This = impl_from_IDispatch(iface);
1799 FIXME("(%p)->(%p)\n", This, pctinfo);
1800 return E_NOTIMPL;
1803 static HRESULT WINAPI PHDispatch_GetTypeInfo(IDispatch *iface, UINT iTInfo,
1804 LCID lcid, ITypeInfo **ppTInfo)
1806 PluginHost *This = impl_from_IDispatch(iface);
1807 FIXME("(%p)->(%d %d %p)\n", This, iTInfo, lcid, ppTInfo);
1808 return E_NOTIMPL;
1811 static HRESULT WINAPI PHDispatch_GetIDsOfNames(IDispatch *iface, REFIID riid,
1812 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1814 PluginHost *This = impl_from_IDispatch(iface);
1815 FIXME("(%p)->(%s %p %d %d %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1816 return E_NOTIMPL;
1819 static HRESULT WINAPI PHDispatch_Invoke(IDispatch *iface, DISPID dispid, REFIID riid, LCID lcid,
1820 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1822 PluginHost *This = impl_from_IDispatch(iface);
1823 FIXME("(%p)->(%d %x %p %p)\n", This, dispid, wFlags, pDispParams, pVarResult);
1824 return E_NOTIMPL;
1827 static const IDispatchVtbl DispatchVtbl = {
1828 PHDispatch_QueryInterface,
1829 PHDispatch_AddRef,
1830 PHDispatch_Release,
1831 PHDispatch_GetTypeInfoCount,
1832 PHDispatch_GetTypeInfo,
1833 PHDispatch_GetIDsOfNames,
1834 PHDispatch_Invoke
1837 static inline PluginHost *impl_from_IOleInPlaceSiteEx(IOleInPlaceSiteEx *iface)
1839 return CONTAINING_RECORD(iface, PluginHost, IOleInPlaceSiteEx_iface);
1842 static HRESULT WINAPI PHInPlaceSite_QueryInterface(IOleInPlaceSiteEx *iface, REFIID riid, void **ppv)
1844 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1845 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1848 static ULONG WINAPI PHInPlaceSite_AddRef(IOleInPlaceSiteEx *iface)
1850 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1851 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1854 static ULONG WINAPI PHInPlaceSite_Release(IOleInPlaceSiteEx *iface)
1856 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1857 return IOleClientSite_Release(&This->IOleClientSite_iface);
1860 static HRESULT WINAPI PHInPlaceSite_GetWindow(IOleInPlaceSiteEx *iface, HWND *phwnd)
1862 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1864 TRACE("(%p)->(%p)\n", This, phwnd);
1866 *phwnd = This->hwnd;
1867 return S_OK;
1870 static HRESULT WINAPI PHInPlaceSite_ContextSensitiveHelp(IOleInPlaceSiteEx *iface, BOOL fEnterMode)
1872 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1873 FIXME("(%p)->(%x)\n", This, fEnterMode);
1874 return E_NOTIMPL;
1877 static HRESULT WINAPI PHInPlaceSite_CanInPlaceActivate(IOleInPlaceSiteEx *iface)
1879 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1881 TRACE("(%p)\n", This);
1883 return S_OK;
1886 static HRESULT WINAPI PHInPlaceSite_OnInPlaceActivate(IOleInPlaceSiteEx *iface)
1888 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1889 FIXME("(%p)\n", This);
1890 return E_NOTIMPL;
1893 static HRESULT WINAPI PHInPlaceSite_OnUIActivate(IOleInPlaceSiteEx *iface)
1895 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1897 TRACE("(%p)\n", This);
1899 if(!This->plugin_unk) {
1900 ERR("No plugin object\n");
1901 return E_UNEXPECTED;
1904 This->ui_active = TRUE;
1906 notif_enabled(This);
1907 return S_OK;
1910 static HRESULT WINAPI PHInPlaceSite_GetWindowContext(IOleInPlaceSiteEx *iface,
1911 IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, RECT *lprcPosRect,
1912 RECT *lprcClipRect, OLEINPLACEFRAMEINFO *frame_info)
1914 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1915 IOleInPlaceUIWindow *ip_window;
1916 IOleInPlaceFrame *ip_frame;
1917 RECT pr, cr;
1918 HRESULT hres;
1920 TRACE("(%p)->(%p %p %p %p %p)\n", This, ppFrame, ppDoc, lprcPosRect, lprcClipRect, frame_info);
1922 if(!This->doc || !This->doc->basedoc.doc_obj || !This->doc->basedoc.doc_obj->ipsite) {
1923 FIXME("No ipsite\n");
1924 return E_UNEXPECTED;
1927 hres = IOleInPlaceSite_GetWindowContext(This->doc->basedoc.doc_obj->ipsite, &ip_frame, &ip_window, &pr, &cr, frame_info);
1928 if(FAILED(hres)) {
1929 WARN("GetWindowContext failed: %08x\n", hres);
1930 return hres;
1933 if(ip_window)
1934 IOleInPlaceUIWindow_Release(ip_window);
1935 if(ip_frame)
1936 IOleInPlaceFrame_Release(ip_frame);
1938 hres = create_ip_frame(&ip_frame);
1939 if(FAILED(hres))
1940 return hres;
1942 hres = create_ip_window(ppDoc);
1943 if(FAILED(hres)) {
1944 IOleInPlaceFrame_Release(ip_frame);
1945 return hres;
1948 *ppFrame = ip_frame;
1949 *lprcPosRect = This->rect;
1950 *lprcClipRect = This->rect;
1951 return S_OK;
1954 static HRESULT WINAPI PHInPlaceSite_Scroll(IOleInPlaceSiteEx *iface, SIZE scrollExtent)
1956 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1957 FIXME("(%p)->({%d %d})\n", This, scrollExtent.cx, scrollExtent.cy);
1958 return E_NOTIMPL;
1961 static HRESULT WINAPI PHInPlaceSite_OnUIDeactivate(IOleInPlaceSiteEx *iface, BOOL fUndoable)
1963 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1964 FIXME("(%p)->(%x)\n", This, fUndoable);
1965 return E_NOTIMPL;
1968 static HRESULT WINAPI PHInPlaceSite_OnInPlaceDeactivate(IOleInPlaceSiteEx *iface)
1970 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1972 TRACE("(%p)\n", This);
1974 if(This->ip_object) {
1975 IOleInPlaceObject_Release(This->ip_object);
1976 This->ip_object = NULL;
1979 return S_OK;
1982 static HRESULT WINAPI PHInPlaceSite_DiscardUndoState(IOleInPlaceSiteEx *iface)
1984 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1985 FIXME("(%p)\n", This);
1986 return E_NOTIMPL;
1989 static HRESULT WINAPI PHInPlaceSite_DeactivateAndUndo(IOleInPlaceSiteEx *iface)
1991 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1992 FIXME("(%p)\n", This);
1993 return E_NOTIMPL;
1996 static HRESULT WINAPI PHInPlaceSite_OnPosRectChange(IOleInPlaceSiteEx *iface, LPCRECT lprcPosRect)
1998 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1999 FIXME("(%p)->(%p)\n", This, lprcPosRect);
2000 return E_NOTIMPL;
2003 static HRESULT WINAPI PHInPlaceSiteEx_OnInPlaceActivateEx(IOleInPlaceSiteEx *iface, BOOL *pfNoRedraw, DWORD dwFlags)
2005 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
2006 HWND hwnd;
2007 HRESULT hres;
2009 TRACE("(%p)->(%p %x)\n", This, pfNoRedraw, dwFlags);
2011 if(This->ip_object)
2012 return S_OK;
2014 hres = IUnknown_QueryInterface(This->plugin_unk, &IID_IOleInPlaceObject, (void**)&This->ip_object);
2015 if(FAILED(hres))
2016 return hres;
2018 hres = IOleInPlaceObject_GetWindow(This->ip_object, &hwnd);
2019 if(SUCCEEDED(hres))
2020 FIXME("Use hwnd %p\n", hwnd);
2022 *pfNoRedraw = FALSE;
2023 return S_OK;
2026 static HRESULT WINAPI PHInPlaceSiteEx_OnInPlaceDeactivateEx(IOleInPlaceSiteEx *iface, BOOL fNoRedraw)
2028 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
2029 FIXME("(%p)->(%x)\n", This, fNoRedraw);
2030 return E_NOTIMPL;
2033 static HRESULT WINAPI PHInPlaceSiteEx_RequestUIActivate(IOleInPlaceSiteEx *iface)
2035 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
2036 FIXME("(%p)\n", This);
2037 return E_NOTIMPL;
2040 static const IOleInPlaceSiteExVtbl OleInPlaceSiteExVtbl = {
2041 PHInPlaceSite_QueryInterface,
2042 PHInPlaceSite_AddRef,
2043 PHInPlaceSite_Release,
2044 PHInPlaceSite_GetWindow,
2045 PHInPlaceSite_ContextSensitiveHelp,
2046 PHInPlaceSite_CanInPlaceActivate,
2047 PHInPlaceSite_OnInPlaceActivate,
2048 PHInPlaceSite_OnUIActivate,
2049 PHInPlaceSite_GetWindowContext,
2050 PHInPlaceSite_Scroll,
2051 PHInPlaceSite_OnUIDeactivate,
2052 PHInPlaceSite_OnInPlaceDeactivate,
2053 PHInPlaceSite_DiscardUndoState,
2054 PHInPlaceSite_DeactivateAndUndo,
2055 PHInPlaceSite_OnPosRectChange,
2056 PHInPlaceSiteEx_OnInPlaceActivateEx,
2057 PHInPlaceSiteEx_OnInPlaceDeactivateEx,
2058 PHInPlaceSiteEx_RequestUIActivate
2061 static inline PluginHost *impl_from_IOleControlSite(IOleControlSite *iface)
2063 return CONTAINING_RECORD(iface, PluginHost, IOleControlSite_iface);
2066 static HRESULT WINAPI PHControlSite_QueryInterface(IOleControlSite *iface, REFIID riid, void **ppv)
2068 PluginHost *This = impl_from_IOleControlSite(iface);
2069 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
2072 static ULONG WINAPI PHControlSite_AddRef(IOleControlSite *iface)
2074 PluginHost *This = impl_from_IOleControlSite(iface);
2075 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
2078 static ULONG WINAPI PHControlSite_Release(IOleControlSite *iface)
2080 PluginHost *This = impl_from_IOleControlSite(iface);
2081 return IOleClientSite_Release(&This->IOleClientSite_iface);
2084 static HRESULT WINAPI PHControlSite_OnControlInfoChanged(IOleControlSite *iface)
2086 PluginHost *This = impl_from_IOleControlSite(iface);
2087 FIXME("(%p)\n", This);
2088 return E_NOTIMPL;
2091 static HRESULT WINAPI PHControlSite_LockInPlaceActive(IOleControlSite *iface, BOOL fLock)
2093 PluginHost *This = impl_from_IOleControlSite(iface);
2094 FIXME("(%p)->(%x)\n", This, fLock);
2095 return E_NOTIMPL;
2098 static HRESULT WINAPI PHControlSite_GetExtendedControl(IOleControlSite *iface, IDispatch **ppDisp)
2100 PluginHost *This = impl_from_IOleControlSite(iface);
2101 FIXME("(%p)->(%p)\n", This, ppDisp);
2102 return E_NOTIMPL;
2105 static HRESULT WINAPI PHControlSite_TransformCoords(IOleControlSite *iface, POINTL *pPtlHimetric, POINTF *pPtfContainer, DWORD dwFlags)
2107 PluginHost *This = impl_from_IOleControlSite(iface);
2108 FIXME("(%p)->(%p %p %x)\n", This, pPtlHimetric, pPtfContainer, dwFlags);
2109 return E_NOTIMPL;
2112 static HRESULT WINAPI PHControlSite_TranslateAccelerator(IOleControlSite *iface, MSG *pMsg, DWORD grfModifiers)
2114 PluginHost *This = impl_from_IOleControlSite(iface);
2115 FIXME("(%p)->(%x)\n", This, grfModifiers);
2116 return E_NOTIMPL;
2119 static HRESULT WINAPI PHControlSite_OnFocus(IOleControlSite *iface, BOOL fGotFocus)
2121 PluginHost *This = impl_from_IOleControlSite(iface);
2122 FIXME("(%p)->(%x)\n", This, fGotFocus);
2123 return E_NOTIMPL;
2126 static HRESULT WINAPI PHControlSite_ShowPropertyFrame(IOleControlSite *iface)
2128 PluginHost *This = impl_from_IOleControlSite(iface);
2129 FIXME("(%p)\n", This);
2130 return E_NOTIMPL;
2133 static const IOleControlSiteVtbl OleControlSiteVtbl = {
2134 PHControlSite_QueryInterface,
2135 PHControlSite_AddRef,
2136 PHControlSite_Release,
2137 PHControlSite_OnControlInfoChanged,
2138 PHControlSite_LockInPlaceActive,
2139 PHControlSite_GetExtendedControl,
2140 PHControlSite_TransformCoords,
2141 PHControlSite_TranslateAccelerator,
2142 PHControlSite_OnFocus,
2143 PHControlSite_ShowPropertyFrame
2146 static inline PluginHost *impl_from_IBindHost(IBindHost *iface)
2148 return CONTAINING_RECORD(iface, PluginHost, IBindHost_iface);
2151 static HRESULT WINAPI PHBindHost_QueryInterface(IBindHost *iface, REFIID riid, void **ppv)
2153 PluginHost *This = impl_from_IBindHost(iface);
2154 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
2157 static ULONG WINAPI PHBindHost_AddRef(IBindHost *iface)
2159 PluginHost *This = impl_from_IBindHost(iface);
2160 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
2163 static ULONG WINAPI PHBindHost_Release(IBindHost *iface)
2165 PluginHost *This = impl_from_IBindHost(iface);
2166 return IOleClientSite_Release(&This->IOleClientSite_iface);
2169 static HRESULT WINAPI PHBindHost_CreateMoniker(IBindHost *iface, LPOLESTR szName, IBindCtx *pBC, IMoniker **ppmk, DWORD dwReserved)
2171 PluginHost *This = impl_from_IBindHost(iface);
2173 TRACE("(%p)->(%s %p %p %x)\n", This, debugstr_w(szName), pBC, ppmk, dwReserved);
2175 if(!This->doc || !This->doc->window || !This->doc->window->mon) {
2176 FIXME("no moniker\n");
2177 return E_UNEXPECTED;
2180 return CreateURLMoniker(This->doc->window->mon, szName, ppmk);
2183 static HRESULT WINAPI PHBindHost_MonikerBindToStorage(IBindHost *iface, IMoniker *pMk, IBindCtx *pBC,
2184 IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
2186 PluginHost *This = impl_from_IBindHost(iface);
2187 FIXME("(%p)->(%p %p %p %s %p)\n", This, pMk, pBC, pBSC, debugstr_guid(riid), ppvObj);
2188 return E_NOTIMPL;
2191 static HRESULT WINAPI PHBindHost_MonikerBindToObject(IBindHost *iface, IMoniker *pMk, IBindCtx *pBC,
2192 IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
2194 PluginHost *This = impl_from_IBindHost(iface);
2195 FIXME("(%p)->(%p %p %p %s %p)\n", This, pMk, pBC, pBSC, debugstr_guid(riid), ppvObj);
2196 return E_NOTIMPL;
2199 static const IBindHostVtbl BindHostVtbl = {
2200 PHBindHost_QueryInterface,
2201 PHBindHost_AddRef,
2202 PHBindHost_Release,
2203 PHBindHost_CreateMoniker,
2204 PHBindHost_MonikerBindToStorage,
2205 PHBindHost_MonikerBindToObject
2208 static inline PluginHost *impl_from_IServiceProvider(IServiceProvider *iface)
2210 return CONTAINING_RECORD(iface, PluginHost, IServiceProvider_iface);
2213 static HRESULT WINAPI PHServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
2215 PluginHost *This = impl_from_IServiceProvider(iface);
2216 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
2219 static ULONG WINAPI PHServiceProvider_AddRef(IServiceProvider *iface)
2221 PluginHost *This = impl_from_IServiceProvider(iface);
2222 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
2225 static ULONG WINAPI PHServiceProvider_Release(IServiceProvider *iface)
2227 PluginHost *This = impl_from_IServiceProvider(iface);
2228 return IOleClientSite_Release(&This->IOleClientSite_iface);
2231 static HRESULT WINAPI PHServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService, REFIID riid, void **ppv)
2233 PluginHost *This = impl_from_IServiceProvider(iface);
2235 if(IsEqualGUID(guidService, &SID_SBindHost)) {
2236 TRACE("SID_SBindHost service\n");
2237 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
2240 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
2242 if(!This->doc || !This->doc->basedoc.window) {
2243 *ppv = NULL;
2244 return E_NOINTERFACE;
2247 return IServiceProvider_QueryService(&This->doc->basedoc.window->base.IServiceProvider_iface,
2248 guidService, riid, ppv);
2251 static const IServiceProviderVtbl ServiceProviderVtbl = {
2252 PHServiceProvider_QueryInterface,
2253 PHServiceProvider_AddRef,
2254 PHServiceProvider_Release,
2255 PHServiceProvider_QueryService
2258 static BOOL parse_classid(const PRUnichar *classid, CLSID *clsid)
2260 const WCHAR *ptr;
2261 unsigned len;
2262 HRESULT hres;
2264 static const PRUnichar clsidW[] = {'c','l','s','i','d',':'};
2266 if(wcsnicmp(classid, clsidW, ARRAY_SIZE(clsidW)))
2267 return FALSE;
2269 ptr = classid + ARRAY_SIZE(clsidW);
2270 len = lstrlenW(ptr);
2272 if(len == 38) {
2273 hres = CLSIDFromString(ptr, clsid);
2274 }else if(len == 36) {
2275 WCHAR buf[39];
2277 buf[0] = '{';
2278 memcpy(buf+1, ptr, len*sizeof(WCHAR));
2279 buf[37] = '}';
2280 buf[38] = 0;
2281 hres = CLSIDFromString(buf, clsid);
2282 }else {
2283 return FALSE;
2286 return SUCCEEDED(hres);
2289 static BOOL get_elem_clsid(nsIDOMElement *elem, CLSID *clsid)
2291 const PRUnichar *val;
2292 nsAString val_str;
2293 nsresult nsres;
2294 BOOL ret = FALSE;
2296 nsres = get_elem_attr_value(elem, L"classid", &val_str, &val);
2297 if(NS_SUCCEEDED(nsres)) {
2298 if(*val)
2299 ret = parse_classid(val, clsid);
2300 nsAString_Finish(&val_str);
2303 return ret;
2306 typedef struct {
2307 IBindStatusCallback IBindStatusCallback_iface;
2308 IWindowForBindingUI IWindowForBindingUI_iface;
2309 LONG ref;
2310 } InstallCallback;
2312 static inline InstallCallback *impl_from_IBindStatusCallback(IBindStatusCallback *iface)
2314 return CONTAINING_RECORD(iface, InstallCallback, IBindStatusCallback_iface);
2317 static HRESULT WINAPI InstallCallback_QueryInterface(IBindStatusCallback *iface,
2318 REFIID riid, void **ppv)
2320 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2322 if(IsEqualGUID(&IID_IUnknown, riid)) {
2323 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
2324 *ppv = &This->IBindStatusCallback_iface;
2325 }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
2326 TRACE("(%p)->(IID_IBindStatusCallback %p)\n", This, ppv);
2327 *ppv = &This->IBindStatusCallback_iface;
2328 }else if(IsEqualGUID(&IID_IWindowForBindingUI, riid)) {
2329 TRACE("(%p)->(IID_IWindowForBindingUI %p)\n", This, ppv);
2330 *ppv = &This->IWindowForBindingUI_iface;
2331 }else {
2332 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
2333 *ppv = NULL;
2334 return E_NOINTERFACE;
2337 IUnknown_AddRef((IUnknown*)*ppv);
2338 return S_OK;
2341 static ULONG WINAPI InstallCallback_AddRef(IBindStatusCallback *iface)
2343 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2344 LONG ref = InterlockedIncrement(&This->ref);
2346 TRACE("(%p) ref=%d\n", This, ref);
2348 return ref;
2351 static ULONG WINAPI InstallCallback_Release(IBindStatusCallback *iface)
2353 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2354 LONG ref = InterlockedIncrement(&This->ref);
2356 TRACE("(%p) ref=%d\n", This, ref);
2358 if(!ref)
2359 heap_free(This);
2361 return ref;
2364 static HRESULT WINAPI InstallCallback_OnStartBinding(IBindStatusCallback *iface,
2365 DWORD dwReserved, IBinding *pib)
2367 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2368 TRACE("(%p)->(%x %p)\n", This, dwReserved, pib);
2369 return S_OK;
2372 static HRESULT WINAPI InstallCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
2374 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2375 TRACE("(%p)->(%p)\n", This, pnPriority);
2376 return E_NOTIMPL;
2379 static HRESULT WINAPI InstallCallback_OnLowResource(IBindStatusCallback *iface, DWORD dwReserved)
2381 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2382 TRACE("(%p)->(%x)\n", This, dwReserved);
2383 return S_OK;
2386 static HRESULT WINAPI InstallCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
2387 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
2389 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2390 TRACE("(%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode, debugstr_w(szStatusText));
2391 return S_OK;
2394 static HRESULT WINAPI InstallCallback_OnStopBinding(IBindStatusCallback *iface,
2395 HRESULT hresult, LPCWSTR szError)
2397 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2398 TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
2399 return S_OK;
2402 static HRESULT WINAPI InstallCallback_GetBindInfo(IBindStatusCallback *iface,
2403 DWORD* grfBINDF, BINDINFO* pbindinfo)
2405 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2407 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
2409 *grfBINDF = BINDF_ASYNCHRONOUS;
2410 return S_OK;
2413 static HRESULT WINAPI InstallCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
2414 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
2416 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2417 ERR("(%p)\n", This);
2418 return E_NOTIMPL;
2421 static HRESULT WINAPI InstallCallback_OnObjectAvailable(IBindStatusCallback *iface,
2422 REFIID riid, IUnknown* punk)
2424 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2425 ERR("(%p)\n", This);
2426 return E_NOTIMPL;
2429 static IBindStatusCallbackVtbl InstallCallbackVtbl = {
2430 InstallCallback_QueryInterface,
2431 InstallCallback_AddRef,
2432 InstallCallback_Release,
2433 InstallCallback_OnStartBinding,
2434 InstallCallback_GetPriority,
2435 InstallCallback_OnLowResource,
2436 InstallCallback_OnProgress,
2437 InstallCallback_OnStopBinding,
2438 InstallCallback_GetBindInfo,
2439 InstallCallback_OnDataAvailable,
2440 InstallCallback_OnObjectAvailable
2443 static inline InstallCallback *impl_from_IWindowForBindingUI(IWindowForBindingUI *iface)
2445 return CONTAINING_RECORD(iface, InstallCallback, IWindowForBindingUI_iface);
2448 static HRESULT WINAPI WindowForBindingUI_QueryInterface(IWindowForBindingUI *iface, REFIID riid, void **ppv)
2450 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
2451 return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
2454 static ULONG WINAPI WindowForBindingUI_AddRef(IWindowForBindingUI *iface)
2456 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
2457 return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
2460 static ULONG WINAPI WindowForBindingUI_Release(IWindowForBindingUI *iface)
2462 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
2463 return IBindStatusCallback_Release(&This->IBindStatusCallback_iface);
2466 static HRESULT WINAPI WindowForBindingUI_GetWindow(IWindowForBindingUI *iface, REFGUID rguidReason, HWND *phwnd)
2468 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
2469 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(rguidReason), phwnd);
2470 *phwnd = NULL;
2471 return S_OK;
2474 static const IWindowForBindingUIVtbl WindowForBindingUIVtbl = {
2475 WindowForBindingUI_QueryInterface,
2476 WindowForBindingUI_AddRef,
2477 WindowForBindingUI_Release,
2478 WindowForBindingUI_GetWindow
2481 typedef struct {
2482 struct list entry;
2483 IUri *uri;
2484 } install_entry_t;
2486 static struct list install_list = LIST_INIT(install_list);
2488 static CRITICAL_SECTION cs_install_list;
2489 static CRITICAL_SECTION_DEBUG cs_install_list_dbg =
2491 0, 0, &cs_install_list,
2492 { &cs_install_list_dbg.ProcessLocksList, &cs_install_list_dbg.ProcessLocksList },
2493 0, 0, { (DWORD_PTR)(__FILE__ ": install_list") }
2495 static CRITICAL_SECTION cs_install_list = { &cs_install_list_dbg, -1, 0, 0, 0, 0 };
2497 static void install_codebase(const WCHAR *url)
2499 InstallCallback *callback;
2500 IBindCtx *bctx;
2501 HRESULT hres;
2503 callback = heap_alloc(sizeof(*callback));
2504 if(!callback)
2505 return;
2507 callback->IBindStatusCallback_iface.lpVtbl = &InstallCallbackVtbl;
2508 callback->IWindowForBindingUI_iface.lpVtbl = &WindowForBindingUIVtbl;
2509 callback->ref = 1;
2511 hres = CreateAsyncBindCtx(0, &callback->IBindStatusCallback_iface, NULL, &bctx);
2512 IBindStatusCallback_Release(&callback->IBindStatusCallback_iface);
2513 if(FAILED(hres))
2514 return;
2516 hres = AsyncInstallDistributionUnit(NULL, NULL, NULL, 0, 0, url, bctx, NULL, 0);
2517 IBindCtx_Release(bctx);
2518 if(FAILED(hres))
2519 WARN("FAILED: %08x\n", hres);
2522 static void check_codebase(HTMLInnerWindow *window, nsIDOMElement *nselem)
2524 BOOL is_on_list = FALSE;
2525 install_entry_t *iter;
2526 const PRUnichar *val;
2527 nsAString val_str;
2528 IUri *uri = NULL;
2529 nsresult nsres;
2530 HRESULT hres;
2532 nsres = get_elem_attr_value(nselem, L"codebase", &val_str, &val);
2533 if(NS_SUCCEEDED(nsres)) {
2534 if(*val) {
2535 hres = CoInternetCombineUrlEx(window->base.outer_window->uri, val, 0, &uri, 0);
2536 if(FAILED(hres))
2537 uri = NULL;
2539 nsAString_Finish(&val_str);
2542 if(!uri)
2543 return;
2545 EnterCriticalSection(&cs_install_list);
2547 LIST_FOR_EACH_ENTRY(iter, &install_list, install_entry_t, entry) {
2548 BOOL eq;
2550 hres = IUri_IsEqual(uri, iter->uri, &eq);
2551 if(SUCCEEDED(hres) && eq) {
2552 TRACE("already proceeded\n");
2553 is_on_list = TRUE;
2554 break;
2558 if(!is_on_list) {
2559 iter = heap_alloc(sizeof(*iter));
2560 if(iter) {
2561 IUri_AddRef(uri);
2562 iter->uri = uri;
2564 list_add_tail(&install_list, &iter->entry);
2568 LeaveCriticalSection(&cs_install_list);
2570 if(!is_on_list) {
2571 BSTR display_uri;
2573 hres = IUri_GetDisplayUri(uri, &display_uri);
2574 if(SUCCEEDED(hres)) {
2575 install_codebase(display_uri);
2576 SysFreeString(display_uri);
2580 IUri_Release(uri);
2583 static IUnknown *create_activex_object(HTMLDocumentNode *doc, nsIDOMElement *nselem, CLSID *clsid)
2585 IClassFactoryEx *cfex;
2586 IClassFactory *cf;
2587 IUnknown *obj;
2588 DWORD policy;
2589 HRESULT hres;
2591 if(!get_elem_clsid(nselem, clsid)) {
2592 WARN("Could not determine element CLSID\n");
2593 return NULL;
2596 TRACE("clsid %s\n", debugstr_guid(clsid));
2598 policy = 0;
2599 hres = IInternetHostSecurityManager_ProcessUrlAction(&doc->IInternetHostSecurityManager_iface,
2600 URLACTION_ACTIVEX_RUN, (BYTE*)&policy, sizeof(policy), (BYTE*)clsid, sizeof(GUID), 0, 0);
2601 if(FAILED(hres) || policy != URLPOLICY_ALLOW) {
2602 WARN("ProcessUrlAction returned %08x %x\n", hres, policy);
2603 return NULL;
2606 hres = CoGetClassObject(clsid, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, NULL, &IID_IClassFactory, (void**)&cf);
2607 if(hres == REGDB_E_CLASSNOTREG)
2608 check_codebase(doc->window, nselem);
2609 if(FAILED(hres))
2610 return NULL;
2612 hres = IClassFactory_QueryInterface(cf, &IID_IClassFactoryEx, (void**)&cfex);
2613 if(SUCCEEDED(hres)) {
2614 FIXME("Use IClassFactoryEx\n");
2615 IClassFactoryEx_Release(cfex);
2618 hres = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)&obj);
2619 IClassFactory_Release(cf);
2620 if(FAILED(hres))
2621 return NULL;
2623 return obj;
2626 void detach_plugin_host(PluginHost *host)
2628 HRESULT hres;
2630 TRACE("%p\n", host);
2632 if(!host->doc)
2633 return;
2635 if(host->ip_object) {
2636 if(host->ui_active)
2637 IOleInPlaceObject_UIDeactivate(host->ip_object);
2638 IOleInPlaceObject_InPlaceDeactivate(host->ip_object);
2641 if(host->plugin_unk) {
2642 IOleObject *ole_obj;
2644 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleObject, (void**)&ole_obj);
2645 if(SUCCEEDED(hres)) {
2646 if(!host->ip_object)
2647 IOleObject_Close(ole_obj, OLECLOSE_NOSAVE);
2648 IOleObject_SetClientSite(ole_obj, NULL);
2649 IOleObject_Release(ole_obj);
2653 if(host->sink) {
2654 IConnectionPointContainer *cp_container;
2655 IConnectionPoint *cp;
2657 assert(host->plugin_unk != NULL);
2659 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IConnectionPointContainer, (void**)&cp_container);
2660 if(SUCCEEDED(hres)) {
2661 hres = IConnectionPointContainer_FindConnectionPoint(cp_container, &host->sink->iid, &cp);
2662 IConnectionPointContainer_Release(cp_container);
2663 if(SUCCEEDED(hres)) {
2664 IConnectionPoint_Unadvise(cp, host->sink->cookie);
2665 IConnectionPoint_Release(cp);
2669 host->sink->host = NULL;
2670 IDispatch_Release(&host->sink->IDispatch_iface);
2671 host->sink = NULL;
2674 release_plugin_ifaces(host);
2676 if(host->element) {
2677 host->element->plugin_host = NULL;
2678 host->element = NULL;
2681 list_remove(&host->entry);
2682 list_init(&host->entry);
2683 host->doc = NULL;
2686 HRESULT create_plugin_host(HTMLDocumentNode *doc, HTMLPluginContainer *container)
2688 PluginHost *host;
2689 IUnknown *unk;
2690 CLSID clsid;
2692 assert(!container->plugin_host);
2694 unk = create_activex_object(doc, container->element.dom_element, &clsid);
2695 if(!unk)
2696 return E_FAIL;
2698 host = heap_alloc_zero(sizeof(*host));
2699 if(!host) {
2700 IUnknown_Release(unk);
2701 return E_OUTOFMEMORY;
2704 host->IOleClientSite_iface.lpVtbl = &OleClientSiteVtbl;
2705 host->IAdviseSinkEx_iface.lpVtbl = &AdviseSinkExVtbl;
2706 host->IPropertyNotifySink_iface.lpVtbl = &PropertyNotifySinkVtbl;
2707 host->IDispatch_iface.lpVtbl = &DispatchVtbl;
2708 host->IOleInPlaceSiteEx_iface.lpVtbl = &OleInPlaceSiteExVtbl;
2709 host->IOleControlSite_iface.lpVtbl = &OleControlSiteVtbl;
2710 host->IBindHost_iface.lpVtbl = &BindHostVtbl;
2711 host->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
2713 host->ref = 1;
2715 host->plugin_unk = unk;
2716 host->clsid = clsid;
2718 host->doc = doc;
2719 list_add_tail(&doc->plugin_hosts, &host->entry);
2721 container->plugin_host = host;
2722 host->element = container;
2724 initialize_plugin_object(host);
2726 return S_OK;