wined3d: Use a separate STATE_VDECL state handler in the GLSL pipeline.
[wine/multimedia.git] / dlls / mshtml / pluginhost.c
blobb6fcf72c79f73fead4db3bb40c65d024fd8809da
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 "config.h"
21 #include <stdarg.h>
22 #include <assert.h>
24 #define COBJMACROS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "ole2.h"
30 #include "shlobj.h"
31 #include "mshtmdid.h"
33 #include "mshtml_private.h"
34 #include "pluginhost.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
40 const IID IID_HTMLPluginContainer =
41 {0xbd7a6050,0xb373,0x4f6f,{0xa4,0x93,0xdd,0x40,0xc5,0x23,0xa8,0x6a}};
43 static BOOL check_load_safety(PluginHost *host)
45 DWORD policy_size, policy;
46 struct CONFIRMSAFETY cs;
47 BYTE *ppolicy;
48 HRESULT hres;
50 cs.clsid = host->clsid;
51 cs.pUnk = host->plugin_unk;
52 cs.dwFlags = CONFIRMSAFETYACTION_LOADOBJECT;
54 hres = IInternetHostSecurityManager_QueryCustomPolicy(&host->doc->IInternetHostSecurityManager_iface,
55 &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
56 if(FAILED(hres))
57 return FALSE;
59 policy = *(DWORD*)ppolicy;
60 CoTaskMemFree(ppolicy);
61 return policy == URLPOLICY_ALLOW;
64 static BOOL check_script_safety(PluginHost *host)
66 DISPPARAMS params = {NULL,NULL,0,0};
67 DWORD policy_size, policy;
68 struct CONFIRMSAFETY cs;
69 BYTE *ppolicy;
70 ULONG err = 0;
71 VARIANT v;
72 HRESULT hres;
74 cs.clsid = host->clsid;
75 cs.pUnk = host->plugin_unk;
76 cs.dwFlags = 0;
78 hres = IInternetHostSecurityManager_QueryCustomPolicy(&host->doc->IInternetHostSecurityManager_iface,
79 &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
80 if(FAILED(hres))
81 return FALSE;
83 policy = *(DWORD*)ppolicy;
84 CoTaskMemFree(ppolicy);
86 if(policy != URLPOLICY_ALLOW)
87 return FALSE;
89 V_VT(&v) = VT_EMPTY;
90 hres = IDispatch_Invoke(host->disp, DISPID_SECURITYCTX, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, &v, NULL, &err);
91 if(SUCCEEDED(hres)) {
92 FIXME("Handle security ctx %s\n", debugstr_variant(&v));
93 return FALSE;
96 return TRUE;
99 static void update_readystate(PluginHost *host)
101 DISPPARAMS params = {NULL,NULL,0,0};
102 IDispatchEx *dispex;
103 IDispatch *disp;
104 ULONG err = 0;
105 VARIANT v;
106 HRESULT hres;
108 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatchEx, (void**)&dispex);
109 if(SUCCEEDED(hres)) {
110 FIXME("Use IDispatchEx\n");
111 IDispatchEx_Release(dispex);
114 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatch, (void**)&disp);
115 if(FAILED(hres))
116 return;
118 hres = IDispatch_Invoke(disp, DISPID_READYSTATE, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, &v, NULL, &err);
119 IDispatch_Release(disp);
120 if(SUCCEEDED(hres)) {
121 /* FIXME: make plugin readystate affect document readystate */
122 TRACE("readystate = %s\n", debugstr_variant(&v));
123 VariantClear(&v);
127 /* FIXME: We shouldn't need this function and we should embed plugin directly in the main document */
128 static void get_pos_rect(PluginHost *host, RECT *ret)
130 ret->top = 0;
131 ret->left = 0;
132 ret->bottom = host->rect.bottom - host->rect.top;
133 ret->right = host->rect.right - host->rect.left;
136 static void load_prop_bag(PluginHost *host, IPersistPropertyBag *persist_prop_bag)
138 IPropertyBag *prop_bag;
139 HRESULT hres;
141 hres = create_param_prop_bag(host->element->element.nselem, &prop_bag);
142 if(FAILED(hres))
143 return;
145 if(prop_bag && !check_load_safety(host)) {
146 IPropertyBag_Release(prop_bag);
147 prop_bag = NULL;
150 if(prop_bag) {
151 hres = IPersistPropertyBag_Load(persist_prop_bag, prop_bag, NULL);
152 IPropertyBag_Release(prop_bag);
153 if(FAILED(hres))
154 WARN("Load failed: %08x\n", hres);
155 }else {
156 hres = IPersistPropertyBag_InitNew(persist_prop_bag);
157 if(FAILED(hres))
158 WARN("InitNew failed: %08x\n", hres);
162 static void load_plugin(PluginHost *host)
164 IPersistPropertyBag2 *persist_prop_bag2;
165 IPersistPropertyBag *persist_prop_bag;
166 HRESULT hres;
168 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IPersistPropertyBag2, (void**)&persist_prop_bag2);
169 if(SUCCEEDED(hres)) {
170 FIXME("Use IPersistPropertyBag2 iface\n");
171 IPersistPropertyBag2_Release(persist_prop_bag2);
172 return;
175 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IPersistPropertyBag, (void**)&persist_prop_bag);
176 if(SUCCEEDED(hres)) {
177 load_prop_bag(host, persist_prop_bag);
178 IPersistPropertyBag_Release(persist_prop_bag);
179 return;
182 FIXME("No IPersistPropertyBag iface\n");
185 static void initialize_plugin_object(PluginHost *host)
187 IClientSecurity *client_security;
188 IQuickActivate *quick_activate;
189 IOleObject *ole_obj = NULL;
190 IOleCommandTarget *cmdtrg;
191 IViewObjectEx *view_obj;
192 IDispatchEx *dispex;
193 IDispatch *disp;
194 HRESULT hres;
196 /* Note native calls QI on plugin for an undocumented IID and CLSID_HTMLDocument */
198 /* FIXME: call FreezeEvents(TRUE) */
200 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IClientSecurity, (void**)&client_security);
201 if(SUCCEEDED(hres)) {
202 FIXME("Handle IClientSecurity\n");
203 IClientSecurity_Release(client_security);
204 return;
207 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IQuickActivate, (void**)&quick_activate);
208 if(SUCCEEDED(hres)) {
209 QACONTAINER container = {sizeof(container)};
210 QACONTROL control = {sizeof(control)};
212 TRACE("Using IQuickActivate\n");
214 container.pClientSite = &host->IOleClientSite_iface;
215 container.dwAmbientFlags = QACONTAINER_SUPPORTSMNEMONICS|QACONTAINER_MESSAGEREFLECT|QACONTAINER_USERMODE;
216 container.pAdviseSink = &host->IAdviseSinkEx_iface;
217 container.pPropertyNotifySink = &host->IPropertyNotifySink_iface;
219 hres = IQuickActivate_QuickActivate(quick_activate, &container, &control);
220 IQuickActivate_Release(quick_activate);
221 if(FAILED(hres))
222 FIXME("QuickActivate failed: %08x\n", hres);
223 }else {
224 DWORD status = 0;
226 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleObject, (void**)&ole_obj);
227 if(SUCCEEDED(hres)) {
228 hres = IOleObject_GetMiscStatus(ole_obj, DVASPECT_CONTENT, &status);
229 TRACE("GetMiscStatus returned %08x %x\n", hres, status);
231 hres = IOleObject_SetClientSite(ole_obj, &host->IOleClientSite_iface);
232 IOleObject_Release(ole_obj);
233 if(FAILED(hres)) {
234 FIXME("SetClientSite failed: %08x\n", hres);
235 return;
237 }else {
238 TRACE("Plugin does not support IOleObject\n");
242 load_plugin(host);
244 if(ole_obj) {
245 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IViewObjectEx, (void**)&view_obj);
246 if(SUCCEEDED(hres)) {
247 DWORD view_status = 0;
249 hres = IViewObjectEx_SetAdvise(view_obj, DVASPECT_CONTENT, 0, (IAdviseSink*)&host->IAdviseSinkEx_iface);
250 if(FAILED(hres))
251 WARN("SetAdvise failed: %08x\n", hres);
253 hres = IViewObjectEx_GetViewStatus(view_obj, &view_status);
254 IViewObjectEx_Release(view_obj);
255 TRACE("GetViewStatus returned %08x %x\n", hres, view_status);
259 update_readystate(host);
261 /* NOTE: Native QIs for IActiveScript, an undocumented IID, IOleControl and IRunnableObject */
263 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatchEx, (void**)&dispex);
264 if(SUCCEEDED(hres)) {
265 FIXME("Use IDispatchEx\n");
266 host->disp = (IDispatch*)dispex;
267 }else {
268 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatch, (void**)&disp);
269 if(SUCCEEDED(hres))
270 host->disp = disp;
271 else
272 TRACE("no IDispatch iface\n");
275 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleCommandTarget, (void**)&cmdtrg);
276 if(SUCCEEDED(hres)) {
277 FIXME("Use IOleCommandTarget\n");
278 IOleCommandTarget_Release(cmdtrg);
282 static void embed_plugin_object(PluginHost *host)
284 IOleObject *ole_obj;
285 RECT rect;
286 HRESULT hres;
288 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleObject, (void**)&ole_obj);
289 if(FAILED(hres)) {
290 FIXME("Plugin does not support IOleObject\n");
291 return;
294 get_pos_rect(host, &rect);
295 hres = IOleObject_DoVerb(ole_obj, OLEIVERB_INPLACEACTIVATE, NULL, &host->IOleClientSite_iface, 0, host->hwnd, &rect);
296 IOleObject_Release(ole_obj);
297 if(FAILED(hres))
298 WARN("DoVerb failed: %08x\n", hres);
300 if(host->ip_object) {
301 HWND hwnd;
303 hres = IOleInPlaceObject_GetWindow(host->ip_object, &hwnd);
304 if(SUCCEEDED(hres))
305 TRACE("hwnd %p\n", hwnd);
309 void update_plugin_window(PluginHost *host, HWND hwnd, const RECT *rect)
311 BOOL rect_changed = FALSE;
313 if(!hwnd || (host->hwnd && host->hwnd != hwnd)) {
314 FIXME("unhandled hwnd\n");
315 return;
318 TRACE("%p %s\n", hwnd, wine_dbgstr_rect(rect));
320 if(memcmp(rect, &host->rect, sizeof(RECT))) {
321 host->rect = *rect;
322 rect_changed = TRUE;
325 if(!host->hwnd) {
326 host->hwnd = hwnd;
327 embed_plugin_object(host);
330 if(rect_changed && host->ip_object)
331 IOleInPlaceObject_SetObjectRects(host->ip_object, &host->rect, &host->rect);
334 static void notif_enabled(PluginHost *plugin_host)
336 DISPPARAMS args = {NULL, NULL, 0, 0};
337 IDispatch *disp;
338 ULONG err = 0;
339 VARIANT res;
340 HRESULT hres;
342 hres = IUnknown_QueryInterface(plugin_host->plugin_unk, &IID_IDispatch, (void**)&disp);
343 if(FAILED(hres)) {
344 FIXME("Could not get IDispatch iface: %08x\n", hres);
345 return;
348 V_VT(&res) = VT_EMPTY;
349 hres = IDispatch_Invoke(disp, DISPID_ENABLED, &IID_NULL, 0/*FIXME*/, DISPATCH_PROPERTYGET, &args, &res, NULL, &err);
350 IDispatch_Release(disp);
351 if(SUCCEEDED(hres)) {
352 FIXME("Got enabled %s\n", debugstr_variant(&res));
353 VariantClear(&res);
357 void notif_container_change(HTMLPluginContainer *plugin_container, DISPID dispid)
359 IOleControl *ole_control;
360 HRESULT hres;
362 if(!plugin_container->plugin_host || !plugin_container->plugin_host->plugin_unk)
363 return;
365 notif_enabled(plugin_container->plugin_host);
367 hres = IUnknown_QueryInterface(plugin_container->plugin_host->plugin_unk, &IID_IOleControl, (void**)&ole_control);
368 if(SUCCEEDED(hres)) {
369 IOleControl_OnAmbientPropertyChange(ole_control, dispid);
370 IOleControl_Release(ole_control);
374 HRESULT get_plugin_disp(HTMLPluginContainer *plugin_container, IDispatch **ret)
376 PluginHost *host;
378 host = plugin_container->plugin_host;
379 if(!host) {
380 ERR("No plugin host\n");
381 return E_UNEXPECTED;
384 if(!host->disp) {
385 *ret = NULL;
386 return S_OK;
389 if(!check_script_safety(host)) {
390 FIXME("Insecure object\n");
391 return E_FAIL;
394 IDispatch_AddRef(host->disp);
395 *ret = host->disp;
396 return S_OK;
399 HRESULT get_plugin_dispid(HTMLPluginContainer *plugin_container, WCHAR *name, DISPID *ret)
401 IDispatch *disp;
402 DISPID id;
403 DWORD i;
404 HRESULT hres;
406 if(!plugin_container->plugin_host) {
407 WARN("no plugin host\n");
408 return DISP_E_UNKNOWNNAME;
411 disp = plugin_container->plugin_host->disp;
412 if(!disp)
413 return DISP_E_UNKNOWNNAME;
415 hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, &id);
416 if(FAILED(hres)) {
417 TRACE("no prop %s\n", debugstr_w(name));
418 return DISP_E_UNKNOWNNAME;
421 for(i=0; i < plugin_container->props_len; i++) {
422 if(id == plugin_container->props[i]) {
423 *ret = MSHTML_DISPID_CUSTOM_MIN+i;
424 return S_OK;
428 if(!plugin_container->props) {
429 plugin_container->props = heap_alloc(8*sizeof(DISPID));
430 if(!plugin_container->props)
431 return E_OUTOFMEMORY;
432 plugin_container->props_size = 8;
433 }else if(plugin_container->props_len == plugin_container->props_size) {
434 DISPID *new_props;
436 new_props = heap_realloc(plugin_container->props, plugin_container->props_size*2*sizeof(DISPID));
437 if(!new_props)
438 return E_OUTOFMEMORY;
440 plugin_container->props = new_props;
441 plugin_container->props_size *= 2;
444 plugin_container->props[plugin_container->props_len] = id;
445 *ret = MSHTML_DISPID_CUSTOM_MIN+plugin_container->props_len;
446 plugin_container->props_len++;
447 return S_OK;
450 HRESULT invoke_plugin_prop(HTMLPluginContainer *plugin_container, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
451 VARIANT *res, EXCEPINFO *ei)
453 PluginHost *host;
455 host = plugin_container->plugin_host;
456 if(!host || !host->disp) {
457 FIXME("Called with no disp\n");
458 return E_UNEXPECTED;
461 if(!check_script_safety(host)) {
462 FIXME("Insecure object\n");
463 return E_FAIL;
466 if(id < MSHTML_DISPID_CUSTOM_MIN || id > MSHTML_DISPID_CUSTOM_MIN + plugin_container->props_len) {
467 ERR("Invalid id\n");
468 return E_FAIL;
471 return IDispatch_Invoke(host->disp, plugin_container->props[id-MSHTML_DISPID_CUSTOM_MIN], &IID_NULL,
472 lcid, flags, params, res, ei, NULL);
475 typedef struct {
476 DISPID id;
477 IDispatch *disp;
478 } sink_entry_t;
480 struct PHEventSink {
481 IDispatch IDispatch_iface;
483 LONG ref;
485 PluginHost *host;
486 ITypeInfo *typeinfo;
487 GUID iid;
488 DWORD cookie;
489 BOOL is_dispiface;
491 sink_entry_t *handlers;
492 DWORD handlers_cnt;
493 DWORD handlers_size;
496 static sink_entry_t *find_sink_entry(PHEventSink *sink, DISPID id)
498 sink_entry_t *iter;
500 for(iter = sink->handlers; iter < sink->handlers+sink->handlers_cnt; iter++) {
501 if(iter->id == id)
502 return iter;
505 return NULL;
508 static void add_sink_handler(PHEventSink *sink, DISPID id, IDispatch *disp)
510 sink_entry_t *entry = find_sink_entry(sink, id);
512 if(entry) {
513 if(entry->disp)
514 IDispatch_Release(entry->disp);
515 }else {
516 if(!sink->handlers_size) {
517 sink->handlers = heap_alloc(4*sizeof(*sink->handlers));
518 if(!sink->handlers)
519 return;
520 sink->handlers_size = 4;
521 }else if(sink->handlers_cnt == sink->handlers_size) {
522 sink_entry_t *new_handlers;
524 new_handlers = heap_realloc(sink->handlers, 2*sink->handlers_size*sizeof(*sink->handlers));
525 if(!new_handlers)
526 return;
527 sink->handlers = new_handlers;
528 sink->handlers_size *= 2;
530 entry = sink->handlers + sink->handlers_cnt++;
531 entry->id = id;
534 IDispatch_AddRef(disp);
535 entry->disp = disp;
538 static inline PHEventSink *PHEventSink_from_IDispatch(IDispatch *iface)
540 return CONTAINING_RECORD(iface, PHEventSink, IDispatch_iface);
543 static HRESULT WINAPI PHEventSink_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
545 PHEventSink *This = PHEventSink_from_IDispatch(iface);
547 if(IsEqualGUID(riid, &IID_IUnknown)) {
548 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
549 *ppv = &This->IDispatch_iface;
550 }else if(IsEqualGUID(riid, &IID_IDispatch)) {
551 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
552 *ppv = &This->IDispatch_iface;
553 }else if(This->is_dispiface && IsEqualGUID(riid, &This->iid)) {
554 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
555 *ppv = &This->IDispatch_iface;
556 }else {
557 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
558 *ppv = NULL;
559 return E_NOINTERFACE;
562 IUnknown_AddRef((IUnknown*)*ppv);
563 return S_OK;
566 static ULONG WINAPI PHEventSink_AddRef(IDispatch *iface)
568 PHEventSink *This = PHEventSink_from_IDispatch(iface);
569 LONG ref = InterlockedIncrement(&This->ref);
571 TRACE("(%p)\n", This);
573 return ref;
576 static ULONG WINAPI PHEventSink_Release(IDispatch *iface)
578 PHEventSink *This = PHEventSink_from_IDispatch(iface);
579 LONG ref = InterlockedDecrement(&This->ref);
581 TRACE("(%p)\n", This);
583 if(!ref) {
584 unsigned i;
586 assert(!This->host);
588 for(i=0; i < This->handlers_cnt; i++) {
589 if(This->handlers[i].disp)
590 IDispatch_Release(This->handlers[i].disp);
592 heap_free(This->handlers);
593 heap_free(This);
596 return ref;
599 static HRESULT WINAPI PHEventSink_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
601 PHEventSink *This = PHEventSink_from_IDispatch(iface);
602 FIXME("(%p)->(%p)\n", This, pctinfo);
603 return E_NOTIMPL;
606 static HRESULT WINAPI PHEventSink_GetTypeInfo(IDispatch *iface, UINT iTInfo,
607 LCID lcid, ITypeInfo **ppTInfo)
609 PHEventSink *This = PHEventSink_from_IDispatch(iface);
610 FIXME("(%p)->(%d %d %p)\n", This, iTInfo, lcid, ppTInfo);
611 return E_NOTIMPL;
614 static HRESULT WINAPI PHEventSink_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *rgszNames,
615 UINT cNames, LCID lcid, DISPID *rgDispId)
617 PHEventSink *This = PHEventSink_from_IDispatch(iface);
618 FIXME("(%p)->(%s %p %u %d %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
619 return E_NOTIMPL;
622 static HRESULT WINAPI PHEventSink_Invoke(IDispatch *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
623 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
625 PHEventSink *This = PHEventSink_from_IDispatch(iface);
626 IDispatchEx *dispex;
627 sink_entry_t *entry;
628 HRESULT hres;
630 TRACE("(%p)->(%d %s %d %x %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), lcid, wFlags,
631 pDispParams, pVarResult, pExcepInfo, puArgErr);
633 if(!This->host) {
634 WARN("No host\n");
635 return E_UNEXPECTED;
638 entry = find_sink_entry(This, dispIdMember);
639 if(!entry || !entry->disp) {
640 WARN("No handler %d\n", dispIdMember);
641 if(pVarResult)
642 V_VT(pVarResult) = VT_EMPTY;
643 return S_OK;
646 hres = IDispatch_QueryInterface(entry->disp, &IID_IDispatchEx, (void**)&dispex);
648 TRACE("(%p) %d >>>\n", This, entry->id);
649 if(SUCCEEDED(hres)) {
650 hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, NULL);
651 IDispatchEx_Release(dispex);
652 }else {
653 hres = IDispatch_Invoke(entry->disp, DISPID_VALUE, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
655 if(SUCCEEDED(hres))
656 TRACE("(%p) %d <<<\n", This, entry->id);
657 else
658 WARN("(%p) %d <<< %08x\n", This, entry->id, hres);
659 return hres;
662 static const IDispatchVtbl PHCPDispatchVtbl = {
663 PHEventSink_QueryInterface,
664 PHEventSink_AddRef,
665 PHEventSink_Release,
666 PHEventSink_GetTypeInfoCount,
667 PHEventSink_GetTypeInfo,
668 PHEventSink_GetIDsOfNames,
669 PHEventSink_Invoke
672 static PHEventSink *create_event_sink(PluginHost *plugin_host, ITypeInfo *typeinfo)
674 IConnectionPointContainer *cp_container;
675 PHEventSink *ret;
676 IConnectionPoint *cp;
677 TYPEATTR *typeattr;
678 TYPEKIND typekind;
679 GUID guid;
680 HRESULT hres;
682 hres = ITypeInfo_GetTypeAttr(typeinfo, &typeattr);
683 if(FAILED(hres))
684 return NULL;
686 typekind = typeattr->typekind;
687 guid = typeattr->guid;
688 ITypeInfo_ReleaseTypeAttr(typeinfo, typeattr);
690 TRACE("guid %s typekind %d\n", debugstr_guid(&guid), typekind);
692 if(typekind != TKIND_INTERFACE && typekind != TKIND_DISPATCH) {
693 WARN("invalid typekind %d\n", typekind);
694 return NULL;
697 hres = IUnknown_QueryInterface(plugin_host->plugin_unk, &IID_IConnectionPointContainer, (void**)&cp_container);
698 if(FAILED(hres)) {
699 WARN("Could not get IConnectionPointContainer iface: %08x\n", hres);
700 return NULL;
703 hres = IConnectionPointContainer_FindConnectionPoint(cp_container, &guid, &cp);
704 IConnectionPointContainer_Release(cp_container);
705 if(FAILED(hres)) {
706 WARN("Could not find %s connection point\n", debugstr_guid(&guid));
707 return NULL;
710 ret = heap_alloc_zero(sizeof(*ret));
711 if(ret) {
712 ret->IDispatch_iface.lpVtbl = &PHCPDispatchVtbl;
713 ret->ref = 1;
714 ret->host = plugin_host;
715 ret->iid = guid;
716 ret->is_dispiface = typekind == TKIND_DISPATCH;
718 ITypeInfo_AddRef(typeinfo);
719 ret->typeinfo = typeinfo;
721 hres = IConnectionPoint_Advise(cp, (IUnknown*)&ret->IDispatch_iface, &ret->cookie);
722 }else {
723 hres = E_OUTOFMEMORY;
726 IConnectionPoint_Release(cp);
727 if(FAILED(hres)) {
728 WARN("Advise failed: %08x\n", hres);
729 return NULL;
732 return ret;
735 static ITypeInfo *get_eventiface_info(HTMLPluginContainer *plugin_container, ITypeInfo *class_info)
737 int impl_types, i, impl_flags;
738 ITypeInfo *ret = NULL;
739 TYPEATTR *typeattr;
740 HREFTYPE ref;
741 HRESULT hres;
743 hres = ITypeInfo_GetTypeAttr(class_info, &typeattr);
744 if(FAILED(hres))
745 return NULL;
747 if(typeattr->typekind != TKIND_COCLASS) {
748 WARN("not coclass\n");
749 ITypeInfo_ReleaseTypeAttr(class_info, typeattr);
750 return NULL;
753 impl_types = typeattr->cImplTypes;
754 ITypeInfo_ReleaseTypeAttr(class_info, typeattr);
756 for(i=0; i<impl_types; i++) {
757 hres = ITypeInfo_GetImplTypeFlags(class_info, i, &impl_flags);
758 if(FAILED(hres))
759 continue;
761 if((impl_flags & IMPLTYPEFLAG_FSOURCE)) {
762 if(!(impl_flags & IMPLTYPEFLAG_FDEFAULT)) {
763 FIXME("Handle non-default source iface\n");
764 continue;
767 hres = ITypeInfo_GetRefTypeOfImplType(class_info, i, &ref);
768 if(FAILED(hres))
769 continue;
771 hres = ITypeInfo_GetRefTypeInfo(class_info, ref, &ret);
772 if(FAILED(hres))
773 ret = NULL;
777 return ret;
780 void bind_activex_event(HTMLDocumentNode *doc, HTMLPluginContainer *plugin_container, WCHAR *event, IDispatch *disp)
782 PluginHost *plugin_host = plugin_container->plugin_host;
783 ITypeInfo *class_info, *source_info;
784 DISPID id;
785 HRESULT hres;
787 TRACE("(%p %p %s %p)\n", doc, plugin_host, debugstr_w(event), disp);
789 if(!plugin_host || !plugin_host->plugin_unk) {
790 WARN("detached element %p\n", plugin_host);
791 return;
794 if(plugin_host->sink) {
795 source_info = plugin_host->sink->typeinfo;
796 ITypeInfo_AddRef(source_info);
797 }else {
798 IProvideClassInfo *provide_ci;
800 hres = IUnknown_QueryInterface(plugin_host->plugin_unk, &IID_IProvideClassInfo, (void**)&provide_ci);
801 if(FAILED(hres)) {
802 FIXME("No IProvideClassInfo, try GetTypeInfo?\n");
803 return;
806 hres = IProvideClassInfo_GetClassInfo(provide_ci, &class_info);
807 IProvideClassInfo_Release(provide_ci);
808 if(FAILED(hres) || !class_info) {
809 WARN("GetClassInfo failed: %08x\n", hres);
810 return;
813 source_info = get_eventiface_info(plugin_container, class_info);
814 ITypeInfo_Release(class_info);
815 if(!source_info)
816 return;
819 hres = ITypeInfo_GetIDsOfNames(source_info, &event, 1, &id);
820 if(FAILED(hres))
821 WARN("Could not get disp id: %08x\n", hres);
822 else if(!plugin_host->sink)
823 plugin_host->sink = create_event_sink(plugin_host, source_info);
825 ITypeInfo_Release(source_info);
826 if(FAILED(hres) || !plugin_host->sink)
827 return;
829 add_sink_handler(plugin_host->sink, id, disp);
832 static inline PluginHost *impl_from_IOleClientSite(IOleClientSite *iface)
834 return CONTAINING_RECORD(iface, PluginHost, IOleClientSite_iface);
837 static HRESULT WINAPI PHClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv)
839 PluginHost *This = impl_from_IOleClientSite(iface);
841 if(IsEqualGUID(&IID_IUnknown, riid)) {
842 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
843 *ppv = &This->IOleClientSite_iface;
844 }else if(IsEqualGUID(&IID_IOleClientSite, riid)) {
845 TRACE("(%p)->(IID_IOleClientSite %p)\n", This, ppv);
846 *ppv = &This->IOleClientSite_iface;
847 }else if(IsEqualGUID(&IID_IAdviseSink, riid)) {
848 TRACE("(%p)->(IID_IAdviseSink %p)\n", This, ppv);
849 *ppv = &This->IAdviseSinkEx_iface;
850 }else if(IsEqualGUID(&IID_IAdviseSinkEx, riid)) {
851 TRACE("(%p)->(IID_IAdviseSinkEx %p)\n", This, ppv);
852 *ppv = &This->IAdviseSinkEx_iface;
853 }else if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) {
854 TRACE("(%p)->(IID_IPropertyNotifySink %p)\n", This, ppv);
855 *ppv = &This->IPropertyNotifySink_iface;
856 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
857 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
858 *ppv = &This->IDispatch_iface;
859 }else if(IsEqualGUID(&IID_IOleWindow, riid)) {
860 TRACE("(%p)->(IID_IOleWindow %p)\n", This, ppv);
861 *ppv = &This->IOleInPlaceSiteEx_iface;
862 }else if(IsEqualGUID(&IID_IOleInPlaceSite, riid)) {
863 TRACE("(%p)->(IID_IOleInPlaceSite %p)\n", This, ppv);
864 *ppv = &This->IOleInPlaceSiteEx_iface;
865 }else if(IsEqualGUID(&IID_IOleInPlaceSiteEx, riid)) {
866 TRACE("(%p)->(IID_IOleInPlaceSiteEx %p)\n", This, ppv);
867 *ppv = &This->IOleInPlaceSiteEx_iface;
868 }else if(IsEqualGUID(&IID_IOleControlSite, riid)) {
869 TRACE("(%p)->(IID_IOleControlSite %p)\n", This, ppv);
870 *ppv = &This->IOleControlSite_iface;
871 }else if(IsEqualGUID(&IID_IBindHost, riid)) {
872 TRACE("(%p)->(IID_IBindHost %p)\n", This, ppv);
873 *ppv = &This->IBindHost_iface;
874 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
875 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
876 *ppv = &This->IServiceProvider_iface;
877 }else {
878 WARN("Unsupported interface %s\n", debugstr_guid(riid));
879 *ppv = NULL;
880 return E_NOINTERFACE;
883 IUnknown_AddRef((IUnknown*)*ppv);
884 return S_OK;
887 static ULONG WINAPI PHClientSite_AddRef(IOleClientSite *iface)
889 PluginHost *This = impl_from_IOleClientSite(iface);
890 LONG ref = InterlockedIncrement(&This->ref);
892 TRACE("(%p) ref=%d\n", This, ref);
894 return ref;
897 static void release_plugin_ifaces(PluginHost *This)
899 if(This->disp) {
900 IDispatch_Release(This->disp);
901 This->disp = NULL;
904 if(This->ip_object) {
905 IOleInPlaceObject_Release(This->ip_object);
906 This->ip_object = NULL;
909 if(This->plugin_unk) {
910 IUnknown *unk = This->plugin_unk;
911 LONG ref;
913 This->plugin_unk = NULL;
914 ref = IUnknown_Release(unk);
916 TRACE("plugin ref = %d\n", ref);
920 static ULONG WINAPI PHClientSite_Release(IOleClientSite *iface)
922 PluginHost *This = impl_from_IOleClientSite(iface);
923 LONG ref = InterlockedDecrement(&This->ref);
925 TRACE("(%p) ref=%d\n", This, ref);
927 if(!ref) {
928 release_plugin_ifaces(This);
929 if(This->sink) {
930 This->sink->host = NULL;
931 IDispatch_Release(&This->sink->IDispatch_iface);
932 This->sink = NULL;
934 list_remove(&This->entry);
935 if(This->element)
936 This->element->plugin_host = NULL;
937 heap_free(This);
940 return ref;
943 static HRESULT WINAPI PHClientSite_SaveObject(IOleClientSite *iface)
945 PluginHost *This = impl_from_IOleClientSite(iface);
946 FIXME("(%p)\n", This);
947 return E_NOTIMPL;
950 static HRESULT WINAPI PHClientSite_GetMoniker(IOleClientSite *iface, DWORD dwAssign,
951 DWORD dwWhichMoniker, IMoniker **ppmk)
953 PluginHost *This = impl_from_IOleClientSite(iface);
955 TRACE("(%p)->(%d %d %p)\n", This, dwAssign, dwWhichMoniker, ppmk);
957 switch(dwWhichMoniker) {
958 case OLEWHICHMK_CONTAINER:
959 if(!This->doc || !This->doc->window || !This->doc->window->mon) {
960 FIXME("no moniker\n");
961 return E_UNEXPECTED;
964 *ppmk = This->doc->window->mon;
965 IMoniker_AddRef(*ppmk);
966 break;
967 default:
968 FIXME("which %d\n", dwWhichMoniker);
969 return E_NOTIMPL;
972 return S_OK;
975 static HRESULT WINAPI PHClientSite_GetContainer(IOleClientSite *iface, IOleContainer **ppContainer)
977 PluginHost *This = impl_from_IOleClientSite(iface);
979 TRACE("(%p)->(%p)\n", This, ppContainer);
981 if(!This->doc) {
982 ERR("Called on detached object\n");
983 return E_UNEXPECTED;
986 *ppContainer = &This->doc->basedoc.IOleContainer_iface;
987 IOleContainer_AddRef(*ppContainer);
988 return S_OK;
991 static HRESULT WINAPI PHClientSite_ShowObject(IOleClientSite *iface)
993 PluginHost *This = impl_from_IOleClientSite(iface);
995 TRACE("(%p)\n", This);
997 return S_OK;
1000 static HRESULT WINAPI PHClientSite_OnShowWindow(IOleClientSite *iface, BOOL fShow)
1002 PluginHost *This = impl_from_IOleClientSite(iface);
1003 FIXME("(%p)->(%x)\n", This, fShow);
1004 return E_NOTIMPL;
1007 static HRESULT WINAPI PHClientSite_RequestNewObjectLayout(IOleClientSite *iface)
1009 PluginHost *This = impl_from_IOleClientSite(iface);
1010 FIXME("(%p)\n", This);
1011 return E_NOTIMPL;
1014 static const IOleClientSiteVtbl OleClientSiteVtbl = {
1015 PHClientSite_QueryInterface,
1016 PHClientSite_AddRef,
1017 PHClientSite_Release,
1018 PHClientSite_SaveObject,
1019 PHClientSite_GetMoniker,
1020 PHClientSite_GetContainer,
1021 PHClientSite_ShowObject,
1022 PHClientSite_OnShowWindow,
1023 PHClientSite_RequestNewObjectLayout
1026 static inline PluginHost *impl_from_IAdviseSinkEx(IAdviseSinkEx *iface)
1028 return CONTAINING_RECORD(iface, PluginHost, IAdviseSinkEx_iface);
1031 static HRESULT WINAPI PHAdviseSinkEx_QueryInterface(IAdviseSinkEx *iface, REFIID riid, void **ppv)
1033 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1034 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1037 static ULONG WINAPI PHAdviseSinkEx_AddRef(IAdviseSinkEx *iface)
1039 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1040 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1043 static ULONG WINAPI PHAdviseSinkEx_Release(IAdviseSinkEx *iface)
1045 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1046 return IOleClientSite_Release(&This->IOleClientSite_iface);
1049 static void WINAPI PHAdviseSinkEx_OnDataChange(IAdviseSinkEx *iface, FORMATETC *pFormatetc, STGMEDIUM *pStgMedium)
1051 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1052 FIXME("(%p)->(%p %p)\n", This, pFormatetc, pStgMedium);
1055 static void WINAPI PHAdviseSinkEx_OnViewChange(IAdviseSinkEx *iface, DWORD dwAspect, LONG lindex)
1057 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1058 FIXME("(%p)->(%d %d)\n", This, dwAspect, lindex);
1061 static void WINAPI PHAdviseSinkEx_OnRename(IAdviseSinkEx *iface, IMoniker *pmk)
1063 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1064 FIXME("(%p)->(%p)\n", This, pmk);
1067 static void WINAPI PHAdviseSinkEx_OnSave(IAdviseSinkEx *iface)
1069 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1070 FIXME("(%p)\n", This);
1073 static void WINAPI PHAdviseSinkEx_OnClose(IAdviseSinkEx *iface)
1075 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1076 FIXME("(%p)\n", This);
1079 static void WINAPI PHAdviseSinkEx_OnViewStatusChange(IAdviseSinkEx *iface, DWORD dwViewStatus)
1081 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1082 FIXME("(%p)->(%d)\n", This, dwViewStatus);
1085 static const IAdviseSinkExVtbl AdviseSinkExVtbl = {
1086 PHAdviseSinkEx_QueryInterface,
1087 PHAdviseSinkEx_AddRef,
1088 PHAdviseSinkEx_Release,
1089 PHAdviseSinkEx_OnDataChange,
1090 PHAdviseSinkEx_OnViewChange,
1091 PHAdviseSinkEx_OnRename,
1092 PHAdviseSinkEx_OnSave,
1093 PHAdviseSinkEx_OnClose,
1094 PHAdviseSinkEx_OnViewStatusChange
1097 static inline PluginHost *impl_from_IPropertyNotifySink(IPropertyNotifySink *iface)
1099 return CONTAINING_RECORD(iface, PluginHost, IPropertyNotifySink_iface);
1102 static HRESULT WINAPI PHPropertyNotifySink_QueryInterface(IPropertyNotifySink *iface, REFIID riid, void **ppv)
1104 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1105 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1108 static ULONG WINAPI PHPropertyNotifySink_AddRef(IPropertyNotifySink *iface)
1110 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1111 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1114 static ULONG WINAPI PHPropertyNotifySink_Release(IPropertyNotifySink *iface)
1116 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1117 return IOleClientSite_Release(&This->IOleClientSite_iface);
1120 static HRESULT WINAPI PHPropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID)
1122 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1124 TRACE("(%p)->(%d)\n", This, dispID);
1126 switch(dispID) {
1127 case DISPID_READYSTATE:
1128 update_readystate(This);
1129 break;
1130 default :
1131 FIXME("Unimplemented dispID %d\n", dispID);
1132 return E_NOTIMPL;
1135 return S_OK;
1138 static HRESULT WINAPI PHPropertyNotifySink_OnRequestEdit(IPropertyNotifySink *iface, DISPID dispID)
1140 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1141 FIXME("(%p)->(%d)\n", This, dispID);
1142 return E_NOTIMPL;
1145 static const IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = {
1146 PHPropertyNotifySink_QueryInterface,
1147 PHPropertyNotifySink_AddRef,
1148 PHPropertyNotifySink_Release,
1149 PHPropertyNotifySink_OnChanged,
1150 PHPropertyNotifySink_OnRequestEdit
1153 static inline PluginHost *impl_from_IDispatch(IDispatch *iface)
1155 return CONTAINING_RECORD(iface, PluginHost, IDispatch_iface);
1158 static HRESULT WINAPI PHDispatch_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
1160 PluginHost *This = impl_from_IDispatch(iface);
1161 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1164 static ULONG WINAPI PHDispatch_AddRef(IDispatch *iface)
1166 PluginHost *This = impl_from_IDispatch(iface);
1167 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1170 static ULONG WINAPI PHDispatch_Release(IDispatch *iface)
1172 PluginHost *This = impl_from_IDispatch(iface);
1173 return IOleClientSite_Release(&This->IOleClientSite_iface);
1176 static HRESULT WINAPI PHDispatch_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
1178 PluginHost *This = impl_from_IDispatch(iface);
1179 FIXME("(%p)->(%p)\n", This, pctinfo);
1180 return E_NOTIMPL;
1183 static HRESULT WINAPI PHDispatch_GetTypeInfo(IDispatch *iface, UINT iTInfo,
1184 LCID lcid, ITypeInfo **ppTInfo)
1186 PluginHost *This = impl_from_IDispatch(iface);
1187 FIXME("(%p)->(%d %d %p)\n", This, iTInfo, lcid, ppTInfo);
1188 return E_NOTIMPL;
1191 static HRESULT WINAPI PHDispatch_GetIDsOfNames(IDispatch *iface, REFIID riid,
1192 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1194 PluginHost *This = impl_from_IDispatch(iface);
1195 FIXME("(%p)->(%s %p %d %d %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1196 return E_NOTIMPL;
1199 static HRESULT WINAPI PHDispatch_Invoke(IDispatch *iface, DISPID dispid, REFIID riid, LCID lcid,
1200 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1202 PluginHost *This = impl_from_IDispatch(iface);
1203 FIXME("(%p)->(%d %x %p %p)\n", This, dispid, wFlags, pDispParams, pVarResult);
1204 return E_NOTIMPL;
1207 static const IDispatchVtbl DispatchVtbl = {
1208 PHDispatch_QueryInterface,
1209 PHDispatch_AddRef,
1210 PHDispatch_Release,
1211 PHDispatch_GetTypeInfoCount,
1212 PHDispatch_GetTypeInfo,
1213 PHDispatch_GetIDsOfNames,
1214 PHDispatch_Invoke
1217 static inline PluginHost *impl_from_IOleInPlaceSiteEx(IOleInPlaceSiteEx *iface)
1219 return CONTAINING_RECORD(iface, PluginHost, IOleInPlaceSiteEx_iface);
1222 static HRESULT WINAPI PHInPlaceSite_QueryInterface(IOleInPlaceSiteEx *iface, REFIID riid, void **ppv)
1224 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1225 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1228 static ULONG WINAPI PHInPlaceSite_AddRef(IOleInPlaceSiteEx *iface)
1230 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1231 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1234 static ULONG WINAPI PHInPlaceSite_Release(IOleInPlaceSiteEx *iface)
1236 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1237 return IOleClientSite_Release(&This->IOleClientSite_iface);
1240 static HRESULT WINAPI PHInPlaceSite_GetWindow(IOleInPlaceSiteEx *iface, HWND *phwnd)
1242 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1244 TRACE("(%p)->(%p)\n", This, phwnd);
1246 *phwnd = This->hwnd;
1247 return S_OK;
1250 static HRESULT WINAPI PHInPlaceSite_ContextSensitiveHelp(IOleInPlaceSiteEx *iface, BOOL fEnterMode)
1252 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1253 FIXME("(%p)->(%x)\n", This, fEnterMode);
1254 return E_NOTIMPL;
1257 static HRESULT WINAPI PHInPlaceSite_CanInPlaceActivate(IOleInPlaceSiteEx *iface)
1259 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1261 TRACE("(%p)\n", This);
1263 return S_OK;
1266 static HRESULT WINAPI PHInPlaceSite_OnInPlaceActivate(IOleInPlaceSiteEx *iface)
1268 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1269 FIXME("(%p)\n", This);
1270 return E_NOTIMPL;
1273 static HRESULT WINAPI PHInPlaceSite_OnUIActivate(IOleInPlaceSiteEx *iface)
1275 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1277 TRACE("(%p)\n", This);
1279 if(!This->plugin_unk) {
1280 ERR("No plugin object\n");
1281 return E_UNEXPECTED;
1284 This->ui_active = TRUE;
1286 notif_enabled(This);
1287 return S_OK;
1290 static HRESULT WINAPI PHInPlaceSite_GetWindowContext(IOleInPlaceSiteEx *iface,
1291 IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, RECT *lprcPosRect,
1292 RECT *lprcClipRect, OLEINPLACEFRAMEINFO *frame_info)
1294 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1295 IOleInPlaceUIWindow *ip_window;
1296 IOleInPlaceFrame *ip_frame;
1297 RECT pr, cr;
1298 HRESULT hres;
1300 TRACE("(%p)->(%p %p %p %p %p)\n", This, ppFrame, ppDoc, lprcPosRect, lprcClipRect, frame_info);
1302 if(!This->doc || !This->doc->basedoc.doc_obj || !This->doc->basedoc.doc_obj->ipsite) {
1303 FIXME("No ipsite\n");
1304 return E_UNEXPECTED;
1307 hres = IOleInPlaceSite_GetWindowContext(This->doc->basedoc.doc_obj->ipsite, &ip_frame, &ip_window, &pr, &cr, frame_info);
1308 if(FAILED(hres)) {
1309 WARN("GetWindowContext failed: %08x\n", hres);
1310 return hres;
1313 if(ip_window)
1314 IOleInPlaceUIWindow_Release(ip_window);
1315 if(ip_frame)
1316 IOleInPlaceFrame_Release(ip_frame);
1318 hres = create_ip_frame(&ip_frame);
1319 if(FAILED(hres))
1320 return hres;
1322 hres = create_ip_window(ppDoc);
1323 if(FAILED(hres)) {
1324 IOleInPlaceFrame_Release(ip_frame);
1325 return hres;
1328 *ppFrame = ip_frame;
1329 *lprcPosRect = This->rect;
1330 *lprcClipRect = This->rect;
1331 return S_OK;
1334 static HRESULT WINAPI PHInPlaceSite_Scroll(IOleInPlaceSiteEx *iface, SIZE scrollExtent)
1336 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1337 FIXME("(%p)->({%d %d})\n", This, scrollExtent.cx, scrollExtent.cy);
1338 return E_NOTIMPL;
1341 static HRESULT WINAPI PHInPlaceSite_OnUIDeactivate(IOleInPlaceSiteEx *iface, BOOL fUndoable)
1343 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1344 FIXME("(%p)->(%x)\n", This, fUndoable);
1345 return E_NOTIMPL;
1348 static HRESULT WINAPI PHInPlaceSite_OnInPlaceDeactivate(IOleInPlaceSiteEx *iface)
1350 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1352 TRACE("(%p)\n", This);
1354 if(This->ip_object) {
1355 IOleInPlaceObject_Release(This->ip_object);
1356 This->ip_object = NULL;
1359 return S_OK;
1362 static HRESULT WINAPI PHInPlaceSite_DiscardUndoState(IOleInPlaceSiteEx *iface)
1364 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1365 FIXME("(%p)\n", This);
1366 return E_NOTIMPL;
1369 static HRESULT WINAPI PHInPlaceSite_DeactivateAndUndo(IOleInPlaceSiteEx *iface)
1371 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1372 FIXME("(%p)\n", This);
1373 return E_NOTIMPL;
1376 static HRESULT WINAPI PHInPlaceSite_OnPosRectChange(IOleInPlaceSiteEx *iface, LPCRECT lprcPosRect)
1378 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1379 FIXME("(%p)->(%p)\n", This, lprcPosRect);
1380 return E_NOTIMPL;
1383 static HRESULT WINAPI PHInPlaceSiteEx_OnInPlaceActivateEx(IOleInPlaceSiteEx *iface, BOOL *pfNoRedraw, DWORD dwFlags)
1385 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1386 HWND hwnd;
1387 HRESULT hres;
1389 TRACE("(%p)->(%p %x)\n", This, pfNoRedraw, dwFlags);
1391 if(This->ip_object)
1392 return S_OK;
1394 hres = IUnknown_QueryInterface(This->plugin_unk, &IID_IOleInPlaceObject, (void**)&This->ip_object);
1395 if(FAILED(hres))
1396 return hres;
1398 hres = IOleInPlaceObject_GetWindow(This->ip_object, &hwnd);
1399 if(SUCCEEDED(hres))
1400 FIXME("Use hwnd %p\n", hwnd);
1402 *pfNoRedraw = FALSE;
1403 return S_OK;
1406 static HRESULT WINAPI PHInPlaceSiteEx_OnInPlaceDeactivateEx(IOleInPlaceSiteEx *iface, BOOL fNoRedraw)
1408 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1409 FIXME("(%p)->(%x)\n", This, fNoRedraw);
1410 return E_NOTIMPL;
1413 static HRESULT WINAPI PHInPlaceSiteEx_RequestUIActivate(IOleInPlaceSiteEx *iface)
1415 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1416 FIXME("(%p)\n", This);
1417 return E_NOTIMPL;
1420 static const IOleInPlaceSiteExVtbl OleInPlaceSiteExVtbl = {
1421 PHInPlaceSite_QueryInterface,
1422 PHInPlaceSite_AddRef,
1423 PHInPlaceSite_Release,
1424 PHInPlaceSite_GetWindow,
1425 PHInPlaceSite_ContextSensitiveHelp,
1426 PHInPlaceSite_CanInPlaceActivate,
1427 PHInPlaceSite_OnInPlaceActivate,
1428 PHInPlaceSite_OnUIActivate,
1429 PHInPlaceSite_GetWindowContext,
1430 PHInPlaceSite_Scroll,
1431 PHInPlaceSite_OnUIDeactivate,
1432 PHInPlaceSite_OnInPlaceDeactivate,
1433 PHInPlaceSite_DiscardUndoState,
1434 PHInPlaceSite_DeactivateAndUndo,
1435 PHInPlaceSite_OnPosRectChange,
1436 PHInPlaceSiteEx_OnInPlaceActivateEx,
1437 PHInPlaceSiteEx_OnInPlaceDeactivateEx,
1438 PHInPlaceSiteEx_RequestUIActivate
1441 static inline PluginHost *impl_from_IOleControlSite(IOleControlSite *iface)
1443 return CONTAINING_RECORD(iface, PluginHost, IOleControlSite_iface);
1446 static HRESULT WINAPI PHControlSite_QueryInterface(IOleControlSite *iface, REFIID riid, void **ppv)
1448 PluginHost *This = impl_from_IOleControlSite(iface);
1449 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1452 static ULONG WINAPI PHControlSite_AddRef(IOleControlSite *iface)
1454 PluginHost *This = impl_from_IOleControlSite(iface);
1455 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1458 static ULONG WINAPI PHControlSite_Release(IOleControlSite *iface)
1460 PluginHost *This = impl_from_IOleControlSite(iface);
1461 return IOleClientSite_Release(&This->IOleClientSite_iface);
1464 static HRESULT WINAPI PHControlSite_OnControlInfoChanged(IOleControlSite *iface)
1466 PluginHost *This = impl_from_IOleControlSite(iface);
1467 FIXME("(%p)\n", This);
1468 return E_NOTIMPL;
1471 static HRESULT WINAPI PHControlSite_LockInPlaceActive(IOleControlSite *iface, BOOL fLock)
1473 PluginHost *This = impl_from_IOleControlSite(iface);
1474 FIXME("(%p)->(%x)\n", This, fLock);
1475 return E_NOTIMPL;
1478 static HRESULT WINAPI PHControlSite_GetExtendedControl(IOleControlSite *iface, IDispatch **ppDisp)
1480 PluginHost *This = impl_from_IOleControlSite(iface);
1481 FIXME("(%p)->(%p)\n", This, ppDisp);
1482 return E_NOTIMPL;
1485 static HRESULT WINAPI PHControlSite_TransformCoords(IOleControlSite *iface, POINTL *pPtlHimetric, POINTF *pPtfContainer, DWORD dwFlags)
1487 PluginHost *This = impl_from_IOleControlSite(iface);
1488 FIXME("(%p)->(%p %p %x)\n", This, pPtlHimetric, pPtfContainer, dwFlags);
1489 return E_NOTIMPL;
1492 static HRESULT WINAPI PHControlSite_TranslateAccelerator(IOleControlSite *iface, MSG *pMsg, DWORD grfModifiers)
1494 PluginHost *This = impl_from_IOleControlSite(iface);
1495 FIXME("(%p)->(%x)\n", This, grfModifiers);
1496 return E_NOTIMPL;
1499 static HRESULT WINAPI PHControlSite_OnFocus(IOleControlSite *iface, BOOL fGotFocus)
1501 PluginHost *This = impl_from_IOleControlSite(iface);
1502 FIXME("(%p)->(%x)\n", This, fGotFocus);
1503 return E_NOTIMPL;
1506 static HRESULT WINAPI PHControlSite_ShowPropertyFrame(IOleControlSite *iface)
1508 PluginHost *This = impl_from_IOleControlSite(iface);
1509 FIXME("(%p)\n", This);
1510 return E_NOTIMPL;
1513 static const IOleControlSiteVtbl OleControlSiteVtbl = {
1514 PHControlSite_QueryInterface,
1515 PHControlSite_AddRef,
1516 PHControlSite_Release,
1517 PHControlSite_OnControlInfoChanged,
1518 PHControlSite_LockInPlaceActive,
1519 PHControlSite_GetExtendedControl,
1520 PHControlSite_TransformCoords,
1521 PHControlSite_TranslateAccelerator,
1522 PHControlSite_OnFocus,
1523 PHControlSite_ShowPropertyFrame
1526 static inline PluginHost *impl_from_IBindHost(IBindHost *iface)
1528 return CONTAINING_RECORD(iface, PluginHost, IBindHost_iface);
1531 static HRESULT WINAPI PHBindHost_QueryInterface(IBindHost *iface, REFIID riid, void **ppv)
1533 PluginHost *This = impl_from_IBindHost(iface);
1534 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1537 static ULONG WINAPI PHBindHost_AddRef(IBindHost *iface)
1539 PluginHost *This = impl_from_IBindHost(iface);
1540 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1543 static ULONG WINAPI PHBindHost_Release(IBindHost *iface)
1545 PluginHost *This = impl_from_IBindHost(iface);
1546 return IOleClientSite_Release(&This->IOleClientSite_iface);
1549 static HRESULT WINAPI PHBindHost_CreateMoniker(IBindHost *iface, LPOLESTR szName, IBindCtx *pBC, IMoniker **ppmk, DWORD dwReserved)
1551 PluginHost *This = impl_from_IBindHost(iface);
1553 TRACE("(%p)->(%s %p %p %x)\n", This, debugstr_w(szName), pBC, ppmk, dwReserved);
1555 if(!This->doc || !This->doc->window || !This->doc->window->mon) {
1556 FIXME("no moniker\n");
1557 return E_UNEXPECTED;
1560 return CreateURLMoniker(This->doc->window->mon, szName, ppmk);
1563 static HRESULT WINAPI PHBindHost_MonikerBindToStorage(IBindHost *iface, IMoniker *pMk, IBindCtx *pBC,
1564 IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
1566 PluginHost *This = impl_from_IBindHost(iface);
1567 FIXME("(%p)->(%p %p %p %s %p)\n", This, pMk, pBC, pBSC, debugstr_guid(riid), ppvObj);
1568 return E_NOTIMPL;
1571 static HRESULT WINAPI PHBindHost_MonikerBindToObject(IBindHost *iface, IMoniker *pMk, IBindCtx *pBC,
1572 IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
1574 PluginHost *This = impl_from_IBindHost(iface);
1575 FIXME("(%p)->(%p %p %p %s %p)\n", This, pMk, pBC, pBSC, debugstr_guid(riid), ppvObj);
1576 return E_NOTIMPL;
1579 static const IBindHostVtbl BindHostVtbl = {
1580 PHBindHost_QueryInterface,
1581 PHBindHost_AddRef,
1582 PHBindHost_Release,
1583 PHBindHost_CreateMoniker,
1584 PHBindHost_MonikerBindToStorage,
1585 PHBindHost_MonikerBindToObject
1588 static inline PluginHost *impl_from_IServiceProvider(IServiceProvider *iface)
1590 return CONTAINING_RECORD(iface, PluginHost, IServiceProvider_iface);
1593 static HRESULT WINAPI PHServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
1595 PluginHost *This = impl_from_IServiceProvider(iface);
1596 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1599 static ULONG WINAPI PHServiceProvider_AddRef(IServiceProvider *iface)
1601 PluginHost *This = impl_from_IServiceProvider(iface);
1602 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1605 static ULONG WINAPI PHServiceProvider_Release(IServiceProvider *iface)
1607 PluginHost *This = impl_from_IServiceProvider(iface);
1608 return IOleClientSite_Release(&This->IOleClientSite_iface);
1611 static HRESULT WINAPI PHServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService, REFIID riid, void **ppv)
1613 PluginHost *This = impl_from_IServiceProvider(iface);
1615 if(IsEqualGUID(guidService, &SID_SBindHost)) {
1616 TRACE("SID_SBindHost service\n");
1617 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1620 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
1622 if(!This->doc || !This->doc->basedoc.window) {
1623 *ppv = NULL;
1624 return E_NOINTERFACE;
1627 return IServiceProvider_QueryService(&This->doc->basedoc.window->base.IServiceProvider_iface,
1628 guidService, riid, ppv);
1631 static const IServiceProviderVtbl ServiceProviderVtbl = {
1632 PHServiceProvider_QueryInterface,
1633 PHServiceProvider_AddRef,
1634 PHServiceProvider_Release,
1635 PHServiceProvider_QueryService
1638 static BOOL parse_classid(const PRUnichar *classid, CLSID *clsid)
1640 const WCHAR *ptr;
1641 unsigned len;
1642 HRESULT hres;
1644 static const PRUnichar clsidW[] = {'c','l','s','i','d',':'};
1646 if(strncmpiW(classid, clsidW, sizeof(clsidW)/sizeof(WCHAR)))
1647 return FALSE;
1649 ptr = classid + sizeof(clsidW)/sizeof(WCHAR);
1650 len = strlenW(ptr);
1652 if(len == 38) {
1653 hres = CLSIDFromString(ptr, clsid);
1654 }else if(len == 36) {
1655 WCHAR buf[39];
1657 buf[0] = '{';
1658 memcpy(buf+1, ptr, len*sizeof(WCHAR));
1659 buf[37] = '}';
1660 buf[38] = 0;
1661 hres = CLSIDFromString(buf, clsid);
1662 }else {
1663 return FALSE;
1666 return SUCCEEDED(hres);
1669 static BOOL get_elem_clsid(nsIDOMHTMLElement *elem, CLSID *clsid)
1671 const PRUnichar *val;
1672 nsAString val_str;
1673 nsresult nsres;
1674 BOOL ret = FALSE;
1676 static const PRUnichar classidW[] = {'c','l','a','s','s','i','d',0};
1678 nsres = get_elem_attr_value(elem, classidW, &val_str, &val);
1679 if(NS_SUCCEEDED(nsres)) {
1680 if(*val)
1681 ret = parse_classid(val, clsid);
1682 nsAString_Finish(&val_str);
1685 return ret;
1688 typedef struct {
1689 IBindStatusCallback IBindStatusCallback_iface;
1690 IWindowForBindingUI IWindowForBindingUI_iface;
1691 LONG ref;
1692 } InstallCallback;
1694 static inline InstallCallback *impl_from_IBindStatusCallback(IBindStatusCallback *iface)
1696 return CONTAINING_RECORD(iface, InstallCallback, IBindStatusCallback_iface);
1699 static HRESULT WINAPI InstallCallback_QueryInterface(IBindStatusCallback *iface,
1700 REFIID riid, void **ppv)
1702 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1704 if(IsEqualGUID(&IID_IUnknown, riid)) {
1705 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1706 *ppv = &This->IBindStatusCallback_iface;
1707 }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
1708 TRACE("(%p)->(IID_IBindStatusCallback %p)\n", This, ppv);
1709 *ppv = &This->IBindStatusCallback_iface;
1710 }else if(IsEqualGUID(&IID_IWindowForBindingUI, riid)) {
1711 TRACE("(%p)->(IID_IWindowForBindingUI %p)\n", This, ppv);
1712 *ppv = &This->IWindowForBindingUI_iface;
1713 }else {
1714 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1715 *ppv = NULL;
1716 return E_NOINTERFACE;
1719 IUnknown_AddRef((IUnknown*)*ppv);
1720 return S_OK;
1723 static ULONG WINAPI InstallCallback_AddRef(IBindStatusCallback *iface)
1725 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1726 LONG ref = InterlockedIncrement(&This->ref);
1728 TRACE("(%p) ref=%d\n", This, ref);
1730 return ref;
1733 static ULONG WINAPI InstallCallback_Release(IBindStatusCallback *iface)
1735 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1736 LONG ref = InterlockedIncrement(&This->ref);
1738 TRACE("(%p) ref=%d\n", This, ref);
1740 if(!ref)
1741 heap_free(This);
1743 return ref;
1746 static HRESULT WINAPI InstallCallback_OnStartBinding(IBindStatusCallback *iface,
1747 DWORD dwReserved, IBinding *pib)
1749 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1750 TRACE("(%p)->(%x %p)\n", This, dwReserved, pib);
1751 return S_OK;
1754 static HRESULT WINAPI InstallCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
1756 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1757 TRACE("(%p)->(%p)\n", This, pnPriority);
1758 return E_NOTIMPL;
1761 static HRESULT WINAPI InstallCallback_OnLowResource(IBindStatusCallback *iface, DWORD dwReserved)
1763 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1764 TRACE("(%p)->(%x)\n", This, dwReserved);
1765 return S_OK;
1768 static HRESULT WINAPI InstallCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
1769 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
1771 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1772 TRACE("(%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode, debugstr_w(szStatusText));
1773 return S_OK;
1776 static HRESULT WINAPI InstallCallback_OnStopBinding(IBindStatusCallback *iface,
1777 HRESULT hresult, LPCWSTR szError)
1779 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1780 TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
1781 return S_OK;
1784 static HRESULT WINAPI InstallCallback_GetBindInfo(IBindStatusCallback *iface,
1785 DWORD* grfBINDF, BINDINFO* pbindinfo)
1787 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1789 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
1791 *grfBINDF = BINDF_ASYNCHRONOUS;
1792 return S_OK;
1795 static HRESULT WINAPI InstallCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
1796 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
1798 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1799 ERR("(%p)\n", This);
1800 return E_NOTIMPL;
1803 static HRESULT WINAPI InstallCallback_OnObjectAvailable(IBindStatusCallback *iface,
1804 REFIID riid, IUnknown* punk)
1806 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1807 ERR("(%p)\n", This);
1808 return E_NOTIMPL;
1811 static IBindStatusCallbackVtbl InstallCallbackVtbl = {
1812 InstallCallback_QueryInterface,
1813 InstallCallback_AddRef,
1814 InstallCallback_Release,
1815 InstallCallback_OnStartBinding,
1816 InstallCallback_GetPriority,
1817 InstallCallback_OnLowResource,
1818 InstallCallback_OnProgress,
1819 InstallCallback_OnStopBinding,
1820 InstallCallback_GetBindInfo,
1821 InstallCallback_OnDataAvailable,
1822 InstallCallback_OnObjectAvailable
1825 static inline InstallCallback *impl_from_IWindowForBindingUI(IWindowForBindingUI *iface)
1827 return CONTAINING_RECORD(iface, InstallCallback, IWindowForBindingUI_iface);
1830 static HRESULT WINAPI WindowForBindingUI_QueryInterface(IWindowForBindingUI *iface, REFIID riid, void **ppv)
1832 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
1833 return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
1836 static ULONG WINAPI WindowForBindingUI_AddRef(IWindowForBindingUI *iface)
1838 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
1839 return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
1842 static ULONG WINAPI WindowForBindingUI_Release(IWindowForBindingUI *iface)
1844 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
1845 return IBindStatusCallback_Release(&This->IBindStatusCallback_iface);
1848 static HRESULT WINAPI WindowForBindingUI_GetWindow(IWindowForBindingUI *iface, REFGUID rguidReason, HWND *phwnd)
1850 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
1851 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(rguidReason), phwnd);
1852 *phwnd = NULL;
1853 return S_OK;
1856 static const IWindowForBindingUIVtbl WindowForBindingUIVtbl = {
1857 WindowForBindingUI_QueryInterface,
1858 WindowForBindingUI_AddRef,
1859 WindowForBindingUI_Release,
1860 WindowForBindingUI_GetWindow
1863 typedef struct {
1864 struct list entry;
1865 IUri *uri;
1866 } install_entry_t;
1868 static struct list install_list = LIST_INIT(install_list);
1870 static CRITICAL_SECTION cs_install_list;
1871 static CRITICAL_SECTION_DEBUG cs_install_list_dbg =
1873 0, 0, &cs_install_list,
1874 { &cs_install_list_dbg.ProcessLocksList, &cs_install_list_dbg.ProcessLocksList },
1875 0, 0, { (DWORD_PTR)(__FILE__ ": install_list") }
1877 static CRITICAL_SECTION cs_install_list = { &cs_install_list_dbg, -1, 0, 0, 0, 0 };
1879 static void install_codebase(const WCHAR *url)
1881 InstallCallback *callback;
1882 IBindCtx *bctx;
1883 HRESULT hres;
1885 callback = heap_alloc(sizeof(*callback));
1886 if(!callback)
1887 return;
1889 callback->IBindStatusCallback_iface.lpVtbl = &InstallCallbackVtbl;
1890 callback->IWindowForBindingUI_iface.lpVtbl = &WindowForBindingUIVtbl;
1891 callback->ref = 1;
1893 hres = CreateAsyncBindCtx(0, &callback->IBindStatusCallback_iface, NULL, &bctx);
1894 IBindStatusCallback_Release(&callback->IBindStatusCallback_iface);
1895 if(FAILED(hres))
1896 return;
1898 hres = AsyncInstallDistributionUnit(NULL, NULL, NULL, 0, 0, url, bctx, NULL, 0);
1899 IBindCtx_Release(bctx);
1900 if(FAILED(hres))
1901 WARN("FAILED: %08x\n", hres);
1904 static void check_codebase(HTMLInnerWindow *window, nsIDOMHTMLElement *nselem)
1906 BOOL is_on_list = FALSE;
1907 install_entry_t *iter;
1908 const PRUnichar *val;
1909 nsAString val_str;
1910 IUri *uri = NULL;
1911 nsresult nsres;
1912 HRESULT hres;
1914 static const PRUnichar codebaseW[] = {'c','o','d','e','b','a','s','e',0};
1916 nsres = get_elem_attr_value(nselem, codebaseW, &val_str, &val);
1917 if(NS_SUCCEEDED(nsres)) {
1918 if(*val) {
1919 hres = CoInternetCombineUrlEx(window->base.outer_window->uri, val, 0, &uri, 0);
1920 if(FAILED(hres))
1921 uri = NULL;
1923 nsAString_Finish(&val_str);
1926 if(!uri)
1927 return;
1929 EnterCriticalSection(&cs_install_list);
1931 LIST_FOR_EACH_ENTRY(iter, &install_list, install_entry_t, entry) {
1932 BOOL eq;
1934 hres = IUri_IsEqual(uri, iter->uri, &eq);
1935 if(SUCCEEDED(hres) && eq) {
1936 TRACE("already proceeded\n");
1937 is_on_list = TRUE;
1938 break;
1942 if(!is_on_list) {
1943 iter = heap_alloc(sizeof(*iter));
1944 if(iter) {
1945 IUri_AddRef(uri);
1946 iter->uri = uri;
1948 list_add_tail(&install_list, &iter->entry);
1952 LeaveCriticalSection(&cs_install_list);
1954 if(!is_on_list) {
1955 BSTR display_uri;
1957 hres = IUri_GetDisplayUri(uri, &display_uri);
1958 if(SUCCEEDED(hres)) {
1959 install_codebase(display_uri);
1960 SysFreeString(display_uri);
1964 IUri_Release(uri);
1967 static IUnknown *create_activex_object(HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, CLSID *clsid)
1969 IClassFactoryEx *cfex;
1970 IClassFactory *cf;
1971 IUnknown *obj;
1972 DWORD policy;
1973 HRESULT hres;
1975 if(!get_elem_clsid(nselem, clsid)) {
1976 WARN("Could not determine element CLSID\n");
1977 return NULL;
1980 TRACE("clsid %s\n", debugstr_guid(clsid));
1982 policy = 0;
1983 hres = IInternetHostSecurityManager_ProcessUrlAction(&doc->IInternetHostSecurityManager_iface,
1984 URLACTION_ACTIVEX_RUN, (BYTE*)&policy, sizeof(policy), (BYTE*)clsid, sizeof(GUID), 0, 0);
1985 if(FAILED(hres) || policy != URLPOLICY_ALLOW) {
1986 WARN("ProcessUrlAction returned %08x %x\n", hres, policy);
1987 return NULL;
1990 hres = CoGetClassObject(clsid, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, NULL, &IID_IClassFactory, (void**)&cf);
1991 if(hres == REGDB_E_CLASSNOTREG)
1992 check_codebase(doc->window, nselem);
1993 if(FAILED(hres))
1994 return NULL;
1996 hres = IClassFactory_QueryInterface(cf, &IID_IClassFactoryEx, (void**)&cfex);
1997 if(SUCCEEDED(hres)) {
1998 FIXME("Use IClassFactoryEx\n");
1999 IClassFactoryEx_Release(cfex);
2002 hres = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)&obj);
2003 IClassFactory_Release(cf);
2004 if(FAILED(hres))
2005 return NULL;
2007 return obj;
2010 void detach_plugin_host(PluginHost *host)
2012 HRESULT hres;
2014 TRACE("%p\n", host);
2016 if(!host->doc)
2017 return;
2019 if(host->ip_object) {
2020 if(host->ui_active)
2021 IOleInPlaceObject_UIDeactivate(host->ip_object);
2022 IOleInPlaceObject_InPlaceDeactivate(host->ip_object);
2025 if(host->plugin_unk) {
2026 IOleObject *ole_obj;
2028 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleObject, (void**)&ole_obj);
2029 if(SUCCEEDED(hres)) {
2030 if(!host->ip_object)
2031 IOleObject_Close(ole_obj, OLECLOSE_NOSAVE);
2032 IOleObject_SetClientSite(ole_obj, NULL);
2033 IOleObject_Release(ole_obj);
2037 if(host->sink) {
2038 IConnectionPointContainer *cp_container;
2039 IConnectionPoint *cp;
2041 assert(host->plugin_unk != NULL);
2043 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IConnectionPointContainer, (void**)&cp_container);
2044 if(SUCCEEDED(hres)) {
2045 hres = IConnectionPointContainer_FindConnectionPoint(cp_container, &host->sink->iid, &cp);
2046 IConnectionPointContainer_Release(cp_container);
2047 if(SUCCEEDED(hres)) {
2048 IConnectionPoint_Unadvise(cp, host->sink->cookie);
2049 IConnectionPoint_Release(cp);
2053 host->sink->host = NULL;
2054 IDispatch_Release(&host->sink->IDispatch_iface);
2055 host->sink = NULL;
2058 release_plugin_ifaces(host);
2060 if(host->element) {
2061 host->element->plugin_host = NULL;
2062 host->element = NULL;
2065 list_remove(&host->entry);
2066 list_init(&host->entry);
2067 host->doc = NULL;
2070 HRESULT create_plugin_host(HTMLDocumentNode *doc, HTMLPluginContainer *container)
2072 PluginHost *host;
2073 IUnknown *unk;
2074 CLSID clsid;
2076 assert(!container->plugin_host);
2078 unk = create_activex_object(doc, container->element.nselem, &clsid);
2079 if(!unk)
2080 return E_FAIL;
2082 host = heap_alloc_zero(sizeof(*host));
2083 if(!host) {
2084 IUnknown_Release(unk);
2085 return E_OUTOFMEMORY;
2088 host->IOleClientSite_iface.lpVtbl = &OleClientSiteVtbl;
2089 host->IAdviseSinkEx_iface.lpVtbl = &AdviseSinkExVtbl;
2090 host->IPropertyNotifySink_iface.lpVtbl = &PropertyNotifySinkVtbl;
2091 host->IDispatch_iface.lpVtbl = &DispatchVtbl;
2092 host->IOleInPlaceSiteEx_iface.lpVtbl = &OleInPlaceSiteExVtbl;
2093 host->IOleControlSite_iface.lpVtbl = &OleControlSiteVtbl;
2094 host->IBindHost_iface.lpVtbl = &BindHostVtbl;
2095 host->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
2097 host->ref = 1;
2099 host->plugin_unk = unk;
2100 host->clsid = clsid;
2102 host->doc = doc;
2103 list_add_tail(&doc->plugin_hosts, &host->entry);
2105 container->plugin_host = host;
2106 host->element = container;
2108 initialize_plugin_object(host);
2110 return S_OK;