winedump: Consistently print hex numbers with leading zeros and 'h' suffix.
[wine.git] / dlls / mshtml / pluginhost.c
blob256850be06eec3725bb8d60ad63bdd1290a3cefe
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 typedef struct {
41 IPropertyBag IPropertyBag_iface;
42 IPropertyBag2 IPropertyBag2_iface;
44 LONG ref;
46 struct list props;
47 } PropertyBag;
49 typedef struct {
50 struct list entry;
51 WCHAR *name;
52 WCHAR *value;
53 } param_prop_t;
55 static void free_prop(param_prop_t *prop)
57 list_remove(&prop->entry);
59 heap_free(prop->name);
60 heap_free(prop->value);
61 heap_free(prop);
64 static param_prop_t *find_prop(PropertyBag *prop_bag, const WCHAR *name)
66 param_prop_t *iter;
68 LIST_FOR_EACH_ENTRY(iter, &prop_bag->props, param_prop_t, entry) {
69 if(!strcmpiW(iter->name, name))
70 return iter;
73 return NULL;
76 static HRESULT add_prop(PropertyBag *prop_bag, const WCHAR *name, const WCHAR *value)
78 param_prop_t *prop;
80 if(!name || !value)
81 return S_OK;
83 TRACE("%p %s %s\n", prop_bag, debugstr_w(name), debugstr_w(value));
85 prop = heap_alloc(sizeof(*prop));
86 if(!prop)
87 return E_OUTOFMEMORY;
89 prop->name = heap_strdupW(name);
90 prop->value = heap_strdupW(value);
91 if(!prop->name || !prop->value) {
92 list_init(&prop->entry);
93 free_prop(prop);
94 return E_OUTOFMEMORY;
97 list_add_tail(&prop_bag->props, &prop->entry);
98 return S_OK;
101 static inline PropertyBag *impl_from_IPropertyBag(IPropertyBag *iface)
103 return CONTAINING_RECORD(iface, PropertyBag, IPropertyBag_iface);
106 static HRESULT WINAPI PropertyBag_QueryInterface(IPropertyBag *iface, REFIID riid, void **ppv)
108 PropertyBag *This = impl_from_IPropertyBag(iface);
110 if(IsEqualGUID(&IID_IUnknown, riid)) {
111 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
112 *ppv = &This->IPropertyBag_iface;
113 }else if(IsEqualGUID(&IID_IPropertyBag, riid)) {
114 TRACE("(%p)->(IID_IPropertyBag %p)\n", This, ppv);
115 *ppv = &This->IPropertyBag_iface;
116 }else if(IsEqualGUID(&IID_IPropertyBag2, riid)) {
117 TRACE("(%p)->(IID_IPropertyBag2 %p)\n", This, ppv);
118 *ppv = &This->IPropertyBag2_iface;
119 }else {
120 WARN("Unsopported interface %s\n", debugstr_guid(riid));
121 *ppv = NULL;
122 return E_NOINTERFACE;
125 IUnknown_AddRef((IUnknown*)*ppv);
126 return S_OK;
129 static ULONG WINAPI PropertyBag_AddRef(IPropertyBag *iface)
131 PropertyBag *This = impl_from_IPropertyBag(iface);
132 LONG ref = InterlockedIncrement(&This->ref);
134 TRACE("(%p) ref=%d\n", This, ref);
136 return ref;
139 static ULONG WINAPI PropertyBag_Release(IPropertyBag *iface)
141 PropertyBag *This = impl_from_IPropertyBag(iface);
142 LONG ref = InterlockedDecrement(&This->ref);
144 TRACE("(%p) ref=%d\n", This, ref);
146 if(!ref) {
147 while(!list_empty(&This->props))
148 free_prop(LIST_ENTRY(This->props.next, param_prop_t, entry));
149 heap_free(This);
152 return ref;
155 static HRESULT WINAPI PropertyBag_Read(IPropertyBag *iface, LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog)
157 PropertyBag *This = impl_from_IPropertyBag(iface);
158 param_prop_t *prop;
159 VARIANT v;
161 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog);
163 prop = find_prop(This, pszPropName);
164 if(!prop) {
165 TRACE("Not found\n");
166 return E_INVALIDARG;
169 V_BSTR(&v) = SysAllocString(prop->value);
170 if(!V_BSTR(&v))
171 return E_OUTOFMEMORY;
173 if(V_VT(pVar) != VT_BSTR) {
174 HRESULT hres;
176 V_VT(&v) = VT_BSTR;
177 hres = VariantChangeType(pVar, &v, 0, V_VT(pVar));
178 SysFreeString(V_BSTR(&v));
179 return hres;
182 V_BSTR(pVar) = V_BSTR(&v);
183 return S_OK;
186 static HRESULT WINAPI PropertyBag_Write(IPropertyBag *iface, LPCOLESTR pszPropName, VARIANT *pVar)
188 PropertyBag *This = impl_from_IPropertyBag(iface);
189 FIXME("(%p)->(%s %s)\n", This, debugstr_w(pszPropName), debugstr_variant(pVar));
190 return E_NOTIMPL;
193 static const IPropertyBagVtbl PropertyBagVtbl = {
194 PropertyBag_QueryInterface,
195 PropertyBag_AddRef,
196 PropertyBag_Release,
197 PropertyBag_Read,
198 PropertyBag_Write
201 static inline PropertyBag *impl_from_IPropertyBag2(IPropertyBag2 *iface)
203 return CONTAINING_RECORD(iface, PropertyBag, IPropertyBag2_iface);
206 static HRESULT WINAPI PropertyBag2_QueryInterface(IPropertyBag2 *iface, REFIID riid, void **ppv)
208 PropertyBag *This = impl_from_IPropertyBag2(iface);
209 return IPropertyBag_QueryInterface(&This->IPropertyBag_iface, riid, ppv);
212 static ULONG WINAPI PropertyBag2_AddRef(IPropertyBag2 *iface)
214 PropertyBag *This = impl_from_IPropertyBag2(iface);
215 return IPropertyBag_AddRef(&This->IPropertyBag_iface);
218 static ULONG WINAPI PropertyBag2_Release(IPropertyBag2 *iface)
220 PropertyBag *This = impl_from_IPropertyBag2(iface);
221 return IPropertyBag_Release(&This->IPropertyBag_iface);
224 static HRESULT WINAPI PropertyBag2_Read(IPropertyBag2 *iface, ULONG cProperties, PROPBAG2 *pPropBag,
225 IErrorLog *pErrLog, VARIANT *pvarValue, HRESULT *phrError)
227 PropertyBag *This = impl_from_IPropertyBag2(iface);
228 FIXME("(%p)->(%d %p %p %p %p)\n", This, cProperties, pPropBag, pErrLog, pvarValue, phrError);
229 return E_NOTIMPL;
232 static HRESULT WINAPI PropertyBag2_Write(IPropertyBag2 *iface, ULONG cProperties, PROPBAG2 *pPropBag, VARIANT *pvarValue)
234 PropertyBag *This = impl_from_IPropertyBag2(iface);
235 FIXME("(%p)->(%d %p %s)\n", This, cProperties, pPropBag, debugstr_variant(pvarValue));
236 return E_NOTIMPL;
239 static HRESULT WINAPI PropertyBag2_CountProperties(IPropertyBag2 *iface, ULONG *pcProperties)
241 PropertyBag *This = impl_from_IPropertyBag2(iface);
242 FIXME("(%p)->(%p)\n", This, pcProperties);
243 return E_NOTIMPL;
246 static HRESULT WINAPI PropertyBag2_GetPropertyInfo(IPropertyBag2 *iface, ULONG iProperty, ULONG cProperties,
247 PROPBAG2 *pPropBag, ULONG *pcProperties)
249 PropertyBag *This = impl_from_IPropertyBag2(iface);
250 FIXME("(%p)->(%u %u %p %p)\n", This, iProperty, cProperties, pPropBag, pcProperties);
251 return E_NOTIMPL;
254 static HRESULT WINAPI PropertyBag2_LoadObject(IPropertyBag2 *iface, LPCOLESTR pstrName, DWORD dwHint,
255 IUnknown *pUnkObject, IErrorLog *pErrLog)
257 PropertyBag *This = impl_from_IPropertyBag2(iface);
258 FIXME("(%p)->(%s %x %p %p)\n", This, debugstr_w(pstrName), dwHint, pUnkObject, pErrLog);
259 return E_NOTIMPL;
262 static const IPropertyBag2Vtbl PropertyBag2Vtbl = {
263 PropertyBag2_QueryInterface,
264 PropertyBag2_AddRef,
265 PropertyBag2_Release,
266 PropertyBag2_Read,
267 PropertyBag2_Write,
268 PropertyBag2_CountProperties,
269 PropertyBag2_GetPropertyInfo,
270 PropertyBag2_LoadObject
273 static HRESULT fill_props(nsIDOMElement *nselem, PropertyBag *prop_bag)
275 const PRUnichar *name, *value;
276 nsAString name_str, value_str;
277 nsIDOMHTMLCollection *params;
278 nsIDOMElement *param_elem;
279 UINT32 length, i;
280 nsIDOMNode *nsnode;
281 nsresult nsres;
282 HRESULT hres = S_OK;
284 static const PRUnichar nameW[] = {'n','a','m','e',0};
285 static const PRUnichar paramW[] = {'p','a','r','a','m',0};
286 static const PRUnichar valueW[] = {'v','a','l','u','e',0};
288 nsAString_InitDepend(&name_str, paramW);
289 nsres = nsIDOMElement_GetElementsByTagName(nselem, &name_str, &params);
290 nsAString_Finish(&name_str);
291 if(NS_FAILED(nsres))
292 return E_FAIL;
294 nsres = nsIDOMHTMLCollection_GetLength(params, &length);
295 if(NS_FAILED(nsres))
296 length = 0;
298 for(i=0; i < length; i++) {
299 nsres = nsIDOMHTMLCollection_Item(params, i, &nsnode);
300 if(NS_FAILED(nsres)) {
301 hres = E_FAIL;
302 break;
305 nsres = nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMElement, (void**)&param_elem);
306 nsIDOMNode_Release(nsnode);
307 if(NS_FAILED(nsres)) {
308 hres = E_FAIL;
309 break;
312 nsres = get_elem_attr_value(param_elem, nameW, &name_str, &name);
313 if(NS_SUCCEEDED(nsres)) {
314 nsres = get_elem_attr_value(param_elem, valueW, &value_str, &value);
315 if(NS_SUCCEEDED(nsres)) {
316 hres = add_prop(prop_bag, name, value);
317 nsAString_Finish(&value_str);
320 nsAString_Finish(&name_str);
323 nsIDOMElement_Release(param_elem);
324 if(FAILED(hres))
325 break;
326 if(NS_FAILED(nsres)) {
327 hres = E_FAIL;
328 break;
332 nsIDOMHTMLCollection_Release(params);
333 return hres;
336 static HRESULT create_param_prop_bag(nsIDOMElement *nselem, IPropertyBag **ret)
338 PropertyBag *prop_bag;
339 HRESULT hres;
341 prop_bag = heap_alloc(sizeof(*prop_bag));
342 if(!prop_bag)
343 return E_OUTOFMEMORY;
345 prop_bag->IPropertyBag_iface.lpVtbl = &PropertyBagVtbl;
346 prop_bag->IPropertyBag2_iface.lpVtbl = &PropertyBag2Vtbl;
347 prop_bag->ref = 1;
349 list_init(&prop_bag->props);
350 hres = fill_props(nselem, prop_bag);
351 if(FAILED(hres) || list_empty(&prop_bag->props)) {
352 IPropertyBag_Release(&prop_bag->IPropertyBag_iface);
353 *ret = NULL;
354 return hres;
357 *ret = &prop_bag->IPropertyBag_iface;
358 return S_OK;
361 static BOOL check_load_safety(PluginHost *host)
363 DWORD policy_size, policy;
364 struct CONFIRMSAFETY cs;
365 BYTE *ppolicy;
366 HRESULT hres;
368 cs.clsid = host->clsid;
369 cs.pUnk = host->plugin_unk;
370 cs.dwFlags = CONFIRMSAFETYACTION_LOADOBJECT;
372 hres = IInternetHostSecurityManager_QueryCustomPolicy(&host->doc->IInternetHostSecurityManager_iface,
373 &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
374 if(FAILED(hres))
375 return FALSE;
377 policy = *(DWORD*)ppolicy;
378 CoTaskMemFree(ppolicy);
379 return policy == URLPOLICY_ALLOW;
382 static BOOL check_script_safety(PluginHost *host)
384 DISPPARAMS params = {NULL,NULL,0,0};
385 DWORD policy_size, policy;
386 struct CONFIRMSAFETY cs;
387 BYTE *ppolicy;
388 ULONG err = 0;
389 VARIANT v;
390 HRESULT hres;
392 cs.clsid = host->clsid;
393 cs.pUnk = host->plugin_unk;
394 cs.dwFlags = 0;
396 hres = IInternetHostSecurityManager_QueryCustomPolicy(&host->doc->IInternetHostSecurityManager_iface,
397 &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
398 if(FAILED(hres))
399 return FALSE;
401 policy = *(DWORD*)ppolicy;
402 CoTaskMemFree(ppolicy);
404 if(policy != URLPOLICY_ALLOW)
405 return FALSE;
407 V_VT(&v) = VT_EMPTY;
408 hres = IDispatch_Invoke(host->disp, DISPID_SECURITYCTX, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, &v, NULL, &err);
409 if(SUCCEEDED(hres)) {
410 FIXME("Handle security ctx %s\n", debugstr_variant(&v));
411 return FALSE;
414 return TRUE;
417 static void update_readystate(PluginHost *host)
419 DISPPARAMS params = {NULL,NULL,0,0};
420 IDispatchEx *dispex;
421 IDispatch *disp;
422 ULONG err = 0;
423 VARIANT v;
424 HRESULT hres;
426 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatchEx, (void**)&dispex);
427 if(SUCCEEDED(hres)) {
428 FIXME("Use IDispatchEx\n");
429 IDispatchEx_Release(dispex);
432 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatch, (void**)&disp);
433 if(FAILED(hres))
434 return;
436 hres = IDispatch_Invoke(disp, DISPID_READYSTATE, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, &v, NULL, &err);
437 IDispatch_Release(disp);
438 if(SUCCEEDED(hres)) {
439 /* FIXME: make plugin readystate affect document readystate */
440 TRACE("readystate = %s\n", debugstr_variant(&v));
441 VariantClear(&v);
445 /* FIXME: We shouldn't need this function and we should embed plugin directly in the main document */
446 static void get_pos_rect(PluginHost *host, RECT *ret)
448 SetRect(ret, 0, 0, host->rect.right - host->rect.left, host->rect.bottom - host->rect.top);
451 static void load_prop_bag(PluginHost *host, IPersistPropertyBag *persist_prop_bag)
453 IPropertyBag *prop_bag;
454 HRESULT hres;
456 hres = create_param_prop_bag(host->element->element.dom_element, &prop_bag);
457 if(FAILED(hres))
458 return;
460 if(prop_bag && !check_load_safety(host)) {
461 IPropertyBag_Release(prop_bag);
462 prop_bag = NULL;
465 if(prop_bag) {
466 hres = IPersistPropertyBag_Load(persist_prop_bag, prop_bag, NULL);
467 IPropertyBag_Release(prop_bag);
468 if(FAILED(hres))
469 WARN("Load failed: %08x\n", hres);
470 }else {
471 hres = IPersistPropertyBag_InitNew(persist_prop_bag);
472 if(FAILED(hres))
473 WARN("InitNew failed: %08x\n", hres);
477 static void load_plugin(PluginHost *host)
479 IPersistPropertyBag2 *persist_prop_bag2;
480 IPersistPropertyBag *persist_prop_bag;
481 HRESULT hres;
483 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IPersistPropertyBag2, (void**)&persist_prop_bag2);
484 if(SUCCEEDED(hres)) {
485 FIXME("Use IPersistPropertyBag2 iface\n");
486 IPersistPropertyBag2_Release(persist_prop_bag2);
487 return;
490 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IPersistPropertyBag, (void**)&persist_prop_bag);
491 if(SUCCEEDED(hres)) {
492 load_prop_bag(host, persist_prop_bag);
493 IPersistPropertyBag_Release(persist_prop_bag);
494 return;
497 FIXME("No IPersistPropertyBag iface\n");
500 static void initialize_plugin_object(PluginHost *host)
502 IClientSecurity *client_security;
503 IQuickActivate *quick_activate;
504 IOleObject *ole_obj = NULL;
505 IOleCommandTarget *cmdtrg;
506 IViewObjectEx *view_obj;
507 IDispatchEx *dispex;
508 IDispatch *disp;
509 HRESULT hres;
511 /* Note native calls QI on plugin for an undocumented IID and CLSID_HTMLDocument */
513 /* FIXME: call FreezeEvents(TRUE) */
515 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IClientSecurity, (void**)&client_security);
516 if(SUCCEEDED(hres)) {
517 FIXME("Handle IClientSecurity\n");
518 IClientSecurity_Release(client_security);
519 return;
522 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IQuickActivate, (void**)&quick_activate);
523 if(SUCCEEDED(hres)) {
524 QACONTAINER container = {sizeof(container)};
525 QACONTROL control = {sizeof(control)};
527 TRACE("Using IQuickActivate\n");
529 container.pClientSite = &host->IOleClientSite_iface;
530 container.dwAmbientFlags = QACONTAINER_SUPPORTSMNEMONICS|QACONTAINER_MESSAGEREFLECT|QACONTAINER_USERMODE;
531 container.pAdviseSink = &host->IAdviseSinkEx_iface;
532 container.pPropertyNotifySink = &host->IPropertyNotifySink_iface;
534 hres = IQuickActivate_QuickActivate(quick_activate, &container, &control);
535 IQuickActivate_Release(quick_activate);
536 if(FAILED(hres))
537 FIXME("QuickActivate failed: %08x\n", hres);
538 }else {
539 DWORD status = 0;
541 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleObject, (void**)&ole_obj);
542 if(SUCCEEDED(hres)) {
543 hres = IOleObject_GetMiscStatus(ole_obj, DVASPECT_CONTENT, &status);
544 TRACE("GetMiscStatus returned %08x %x\n", hres, status);
546 hres = IOleObject_SetClientSite(ole_obj, &host->IOleClientSite_iface);
547 IOleObject_Release(ole_obj);
548 if(FAILED(hres)) {
549 FIXME("SetClientSite failed: %08x\n", hres);
550 return;
552 }else {
553 TRACE("Plugin does not support IOleObject\n");
557 load_plugin(host);
559 if(ole_obj) {
560 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IViewObjectEx, (void**)&view_obj);
561 if(SUCCEEDED(hres)) {
562 DWORD view_status = 0;
564 hres = IViewObjectEx_SetAdvise(view_obj, DVASPECT_CONTENT, 0, (IAdviseSink*)&host->IAdviseSinkEx_iface);
565 if(FAILED(hres))
566 WARN("SetAdvise failed: %08x\n", hres);
568 hres = IViewObjectEx_GetViewStatus(view_obj, &view_status);
569 IViewObjectEx_Release(view_obj);
570 TRACE("GetViewStatus returned %08x %x\n", hres, view_status);
574 update_readystate(host);
576 /* NOTE: Native QIs for IActiveScript, an undocumented IID, IOleControl and IRunnableObject */
578 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatchEx, (void**)&dispex);
579 if(SUCCEEDED(hres)) {
580 FIXME("Use IDispatchEx\n");
581 host->disp = (IDispatch*)dispex;
582 }else {
583 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatch, (void**)&disp);
584 if(SUCCEEDED(hres))
585 host->disp = disp;
586 else
587 TRACE("no IDispatch iface\n");
590 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleCommandTarget, (void**)&cmdtrg);
591 if(SUCCEEDED(hres)) {
592 FIXME("Use IOleCommandTarget\n");
593 IOleCommandTarget_Release(cmdtrg);
597 static void embed_plugin_object(PluginHost *host)
599 IOleObject *ole_obj;
600 RECT rect;
601 HRESULT hres;
603 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleObject, (void**)&ole_obj);
604 if(FAILED(hres)) {
605 FIXME("Plugin does not support IOleObject\n");
606 return;
609 get_pos_rect(host, &rect);
610 hres = IOleObject_DoVerb(ole_obj, OLEIVERB_INPLACEACTIVATE, NULL, &host->IOleClientSite_iface, 0, host->hwnd, &rect);
611 IOleObject_Release(ole_obj);
612 if(FAILED(hres))
613 WARN("DoVerb failed: %08x\n", hres);
615 if(host->ip_object) {
616 HWND hwnd;
618 hres = IOleInPlaceObject_GetWindow(host->ip_object, &hwnd);
619 if(SUCCEEDED(hres))
620 TRACE("hwnd %p\n", hwnd);
624 void update_plugin_window(PluginHost *host, HWND hwnd, const RECT *rect)
626 BOOL rect_changed = FALSE;
628 if(!hwnd || (host->hwnd && host->hwnd != hwnd)) {
629 FIXME("unhandled hwnd\n");
630 return;
633 TRACE("%p %s\n", hwnd, wine_dbgstr_rect(rect));
635 if(!EqualRect(rect, &host->rect)) {
636 host->rect = *rect;
637 rect_changed = TRUE;
640 if(!host->hwnd) {
641 host->hwnd = hwnd;
642 embed_plugin_object(host);
645 if(rect_changed && host->ip_object)
646 IOleInPlaceObject_SetObjectRects(host->ip_object, &host->rect, &host->rect);
649 static void notif_enabled(PluginHost *plugin_host)
651 DISPPARAMS args = {NULL, NULL, 0, 0};
652 IDispatch *disp;
653 ULONG err = 0;
654 VARIANT res;
655 HRESULT hres;
657 hres = IUnknown_QueryInterface(plugin_host->plugin_unk, &IID_IDispatch, (void**)&disp);
658 if(FAILED(hres)) {
659 FIXME("Could not get IDispatch iface: %08x\n", hres);
660 return;
663 V_VT(&res) = VT_EMPTY;
664 hres = IDispatch_Invoke(disp, DISPID_ENABLED, &IID_NULL, 0/*FIXME*/, DISPATCH_PROPERTYGET, &args, &res, NULL, &err);
665 IDispatch_Release(disp);
666 if(SUCCEEDED(hres)) {
667 FIXME("Got enabled %s\n", debugstr_variant(&res));
668 VariantClear(&res);
672 void notif_container_change(HTMLPluginContainer *plugin_container, DISPID dispid)
674 IOleControl *ole_control;
675 HRESULT hres;
677 if(!plugin_container->plugin_host || !plugin_container->plugin_host->plugin_unk)
678 return;
680 notif_enabled(plugin_container->plugin_host);
682 hres = IUnknown_QueryInterface(plugin_container->plugin_host->plugin_unk, &IID_IOleControl, (void**)&ole_control);
683 if(SUCCEEDED(hres)) {
684 IOleControl_OnAmbientPropertyChange(ole_control, dispid);
685 IOleControl_Release(ole_control);
689 HRESULT get_plugin_disp(HTMLPluginContainer *plugin_container, IDispatch **ret)
691 PluginHost *host;
693 host = plugin_container->plugin_host;
694 if(!host) {
695 ERR("No plugin host\n");
696 return E_UNEXPECTED;
699 if(!host->disp) {
700 *ret = NULL;
701 return S_OK;
704 if(!check_script_safety(host)) {
705 FIXME("Insecure object\n");
706 return E_FAIL;
709 IDispatch_AddRef(host->disp);
710 *ret = host->disp;
711 return S_OK;
714 HRESULT get_plugin_dispid(HTMLPluginContainer *plugin_container, WCHAR *name, DISPID *ret)
716 IDispatch *disp;
717 DISPID id;
718 DWORD i;
719 HRESULT hres;
721 if(!plugin_container->plugin_host) {
722 WARN("no plugin host\n");
723 return DISP_E_UNKNOWNNAME;
726 disp = plugin_container->plugin_host->disp;
727 if(!disp)
728 return DISP_E_UNKNOWNNAME;
730 hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, &id);
731 if(FAILED(hres)) {
732 TRACE("no prop %s\n", debugstr_w(name));
733 return DISP_E_UNKNOWNNAME;
736 for(i=0; i < plugin_container->props_len; i++) {
737 if(id == plugin_container->props[i]) {
738 *ret = MSHTML_DISPID_CUSTOM_MIN+i;
739 return S_OK;
743 if(!plugin_container->props) {
744 plugin_container->props = heap_alloc(8*sizeof(DISPID));
745 if(!plugin_container->props)
746 return E_OUTOFMEMORY;
747 plugin_container->props_size = 8;
748 }else if(plugin_container->props_len == plugin_container->props_size) {
749 DISPID *new_props;
751 new_props = heap_realloc(plugin_container->props, plugin_container->props_size*2*sizeof(DISPID));
752 if(!new_props)
753 return E_OUTOFMEMORY;
755 plugin_container->props = new_props;
756 plugin_container->props_size *= 2;
759 plugin_container->props[plugin_container->props_len] = id;
760 *ret = MSHTML_DISPID_CUSTOM_MIN+plugin_container->props_len;
761 plugin_container->props_len++;
762 return S_OK;
765 HRESULT invoke_plugin_prop(HTMLPluginContainer *plugin_container, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
766 VARIANT *res, EXCEPINFO *ei)
768 PluginHost *host;
770 host = plugin_container->plugin_host;
771 if(!host || !host->disp) {
772 FIXME("Called with no disp\n");
773 return E_UNEXPECTED;
776 if(!check_script_safety(host)) {
777 FIXME("Insecure object\n");
778 return E_FAIL;
781 if(id < MSHTML_DISPID_CUSTOM_MIN || id > MSHTML_DISPID_CUSTOM_MIN + plugin_container->props_len) {
782 ERR("Invalid id\n");
783 return E_FAIL;
786 return IDispatch_Invoke(host->disp, plugin_container->props[id-MSHTML_DISPID_CUSTOM_MIN], &IID_NULL,
787 lcid, flags, params, res, ei, NULL);
790 typedef struct {
791 DISPID id;
792 IDispatch *disp;
793 } sink_entry_t;
795 struct PHEventSink {
796 IDispatch IDispatch_iface;
798 LONG ref;
800 PluginHost *host;
801 ITypeInfo *typeinfo;
802 GUID iid;
803 DWORD cookie;
804 BOOL is_dispiface;
806 sink_entry_t *handlers;
807 DWORD handlers_cnt;
808 DWORD handlers_size;
811 static sink_entry_t *find_sink_entry(PHEventSink *sink, DISPID id)
813 sink_entry_t *iter;
815 for(iter = sink->handlers; iter < sink->handlers+sink->handlers_cnt; iter++) {
816 if(iter->id == id)
817 return iter;
820 return NULL;
823 static void add_sink_handler(PHEventSink *sink, DISPID id, IDispatch *disp)
825 sink_entry_t *entry = find_sink_entry(sink, id);
827 if(entry) {
828 if(entry->disp)
829 IDispatch_Release(entry->disp);
830 }else {
831 if(!sink->handlers_size) {
832 sink->handlers = heap_alloc(4*sizeof(*sink->handlers));
833 if(!sink->handlers)
834 return;
835 sink->handlers_size = 4;
836 }else if(sink->handlers_cnt == sink->handlers_size) {
837 sink_entry_t *new_handlers;
839 new_handlers = heap_realloc(sink->handlers, 2*sink->handlers_size*sizeof(*sink->handlers));
840 if(!new_handlers)
841 return;
842 sink->handlers = new_handlers;
843 sink->handlers_size *= 2;
845 entry = sink->handlers + sink->handlers_cnt++;
846 entry->id = id;
849 IDispatch_AddRef(disp);
850 entry->disp = disp;
853 static inline PHEventSink *PHEventSink_from_IDispatch(IDispatch *iface)
855 return CONTAINING_RECORD(iface, PHEventSink, IDispatch_iface);
858 static HRESULT WINAPI PHEventSink_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
860 PHEventSink *This = PHEventSink_from_IDispatch(iface);
862 if(IsEqualGUID(riid, &IID_IUnknown)) {
863 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
864 *ppv = &This->IDispatch_iface;
865 }else if(IsEqualGUID(riid, &IID_IDispatch)) {
866 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
867 *ppv = &This->IDispatch_iface;
868 }else if(This->is_dispiface && IsEqualGUID(riid, &This->iid)) {
869 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
870 *ppv = &This->IDispatch_iface;
871 }else {
872 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
873 *ppv = NULL;
874 return E_NOINTERFACE;
877 IUnknown_AddRef((IUnknown*)*ppv);
878 return S_OK;
881 static ULONG WINAPI PHEventSink_AddRef(IDispatch *iface)
883 PHEventSink *This = PHEventSink_from_IDispatch(iface);
884 LONG ref = InterlockedIncrement(&This->ref);
886 TRACE("(%p)\n", This);
888 return ref;
891 static ULONG WINAPI PHEventSink_Release(IDispatch *iface)
893 PHEventSink *This = PHEventSink_from_IDispatch(iface);
894 LONG ref = InterlockedDecrement(&This->ref);
896 TRACE("(%p)\n", This);
898 if(!ref) {
899 unsigned i;
901 assert(!This->host);
903 for(i=0; i < This->handlers_cnt; i++) {
904 if(This->handlers[i].disp)
905 IDispatch_Release(This->handlers[i].disp);
907 heap_free(This->handlers);
908 heap_free(This);
911 return ref;
914 static HRESULT WINAPI PHEventSink_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
916 PHEventSink *This = PHEventSink_from_IDispatch(iface);
917 FIXME("(%p)->(%p)\n", This, pctinfo);
918 return E_NOTIMPL;
921 static HRESULT WINAPI PHEventSink_GetTypeInfo(IDispatch *iface, UINT iTInfo,
922 LCID lcid, ITypeInfo **ppTInfo)
924 PHEventSink *This = PHEventSink_from_IDispatch(iface);
925 FIXME("(%p)->(%d %d %p)\n", This, iTInfo, lcid, ppTInfo);
926 return E_NOTIMPL;
929 static HRESULT WINAPI PHEventSink_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *rgszNames,
930 UINT cNames, LCID lcid, DISPID *rgDispId)
932 PHEventSink *This = PHEventSink_from_IDispatch(iface);
933 FIXME("(%p)->(%s %p %u %d %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
934 return E_NOTIMPL;
937 static HRESULT WINAPI PHEventSink_Invoke(IDispatch *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
938 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
940 PHEventSink *This = PHEventSink_from_IDispatch(iface);
941 IDispatchEx *dispex;
942 sink_entry_t *entry;
943 HRESULT hres;
945 TRACE("(%p)->(%d %s %d %x %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), lcid, wFlags,
946 pDispParams, pVarResult, pExcepInfo, puArgErr);
948 if(!This->host) {
949 WARN("No host\n");
950 return E_UNEXPECTED;
953 entry = find_sink_entry(This, dispIdMember);
954 if(!entry || !entry->disp) {
955 WARN("No handler %d\n", dispIdMember);
956 if(pVarResult)
957 V_VT(pVarResult) = VT_EMPTY;
958 return S_OK;
961 hres = IDispatch_QueryInterface(entry->disp, &IID_IDispatchEx, (void**)&dispex);
963 TRACE("(%p) %d >>>\n", This, entry->id);
964 if(SUCCEEDED(hres)) {
965 hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, NULL);
966 IDispatchEx_Release(dispex);
967 }else {
968 hres = IDispatch_Invoke(entry->disp, DISPID_VALUE, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
970 if(SUCCEEDED(hres))
971 TRACE("(%p) %d <<<\n", This, entry->id);
972 else
973 WARN("(%p) %d <<< %08x\n", This, entry->id, hres);
974 return hres;
977 static const IDispatchVtbl PHCPDispatchVtbl = {
978 PHEventSink_QueryInterface,
979 PHEventSink_AddRef,
980 PHEventSink_Release,
981 PHEventSink_GetTypeInfoCount,
982 PHEventSink_GetTypeInfo,
983 PHEventSink_GetIDsOfNames,
984 PHEventSink_Invoke
987 static PHEventSink *create_event_sink(PluginHost *plugin_host, ITypeInfo *typeinfo)
989 IConnectionPointContainer *cp_container;
990 PHEventSink *ret;
991 IConnectionPoint *cp;
992 TYPEATTR *typeattr;
993 TYPEKIND typekind;
994 GUID guid;
995 HRESULT hres;
997 hres = ITypeInfo_GetTypeAttr(typeinfo, &typeattr);
998 if(FAILED(hres))
999 return NULL;
1001 typekind = typeattr->typekind;
1002 guid = typeattr->guid;
1003 ITypeInfo_ReleaseTypeAttr(typeinfo, typeattr);
1005 TRACE("guid %s typekind %d\n", debugstr_guid(&guid), typekind);
1007 if(typekind != TKIND_INTERFACE && typekind != TKIND_DISPATCH) {
1008 WARN("invalid typekind %d\n", typekind);
1009 return NULL;
1012 hres = IUnknown_QueryInterface(plugin_host->plugin_unk, &IID_IConnectionPointContainer, (void**)&cp_container);
1013 if(FAILED(hres)) {
1014 WARN("Could not get IConnectionPointContainer iface: %08x\n", hres);
1015 return NULL;
1018 hres = IConnectionPointContainer_FindConnectionPoint(cp_container, &guid, &cp);
1019 IConnectionPointContainer_Release(cp_container);
1020 if(FAILED(hres)) {
1021 WARN("Could not find %s connection point\n", debugstr_guid(&guid));
1022 return NULL;
1025 ret = heap_alloc_zero(sizeof(*ret));
1026 if(ret) {
1027 ret->IDispatch_iface.lpVtbl = &PHCPDispatchVtbl;
1028 ret->ref = 1;
1029 ret->host = plugin_host;
1030 ret->iid = guid;
1031 ret->is_dispiface = typekind == TKIND_DISPATCH;
1033 ITypeInfo_AddRef(typeinfo);
1034 ret->typeinfo = typeinfo;
1036 hres = IConnectionPoint_Advise(cp, (IUnknown*)&ret->IDispatch_iface, &ret->cookie);
1037 }else {
1038 hres = E_OUTOFMEMORY;
1041 IConnectionPoint_Release(cp);
1042 if(FAILED(hres)) {
1043 WARN("Advise failed: %08x\n", hres);
1044 return NULL;
1047 return ret;
1050 static ITypeInfo *get_eventiface_info(HTMLPluginContainer *plugin_container, ITypeInfo *class_info)
1052 int impl_types, i, impl_flags;
1053 ITypeInfo *ret = NULL;
1054 TYPEATTR *typeattr;
1055 HREFTYPE ref;
1056 HRESULT hres;
1058 hres = ITypeInfo_GetTypeAttr(class_info, &typeattr);
1059 if(FAILED(hres))
1060 return NULL;
1062 if(typeattr->typekind != TKIND_COCLASS) {
1063 WARN("not coclass\n");
1064 ITypeInfo_ReleaseTypeAttr(class_info, typeattr);
1065 return NULL;
1068 impl_types = typeattr->cImplTypes;
1069 ITypeInfo_ReleaseTypeAttr(class_info, typeattr);
1071 for(i=0; i<impl_types; i++) {
1072 hres = ITypeInfo_GetImplTypeFlags(class_info, i, &impl_flags);
1073 if(FAILED(hres))
1074 continue;
1076 if((impl_flags & IMPLTYPEFLAG_FSOURCE)) {
1077 if(!(impl_flags & IMPLTYPEFLAG_FDEFAULT)) {
1078 FIXME("Handle non-default source iface\n");
1079 continue;
1082 hres = ITypeInfo_GetRefTypeOfImplType(class_info, i, &ref);
1083 if(FAILED(hres))
1084 continue;
1086 hres = ITypeInfo_GetRefTypeInfo(class_info, ref, &ret);
1087 if(FAILED(hres))
1088 ret = NULL;
1092 return ret;
1095 void bind_activex_event(HTMLDocumentNode *doc, HTMLPluginContainer *plugin_container, WCHAR *event, IDispatch *disp)
1097 PluginHost *plugin_host = plugin_container->plugin_host;
1098 ITypeInfo *class_info, *source_info;
1099 DISPID id;
1100 HRESULT hres;
1102 TRACE("(%p %p %s %p)\n", doc, plugin_host, debugstr_w(event), disp);
1104 if(!plugin_host || !plugin_host->plugin_unk) {
1105 WARN("detached element %p\n", plugin_host);
1106 return;
1109 if(plugin_host->sink) {
1110 source_info = plugin_host->sink->typeinfo;
1111 ITypeInfo_AddRef(source_info);
1112 }else {
1113 IProvideClassInfo *provide_ci;
1115 hres = IUnknown_QueryInterface(plugin_host->plugin_unk, &IID_IProvideClassInfo, (void**)&provide_ci);
1116 if(FAILED(hres)) {
1117 FIXME("No IProvideClassInfo, try GetTypeInfo?\n");
1118 return;
1121 hres = IProvideClassInfo_GetClassInfo(provide_ci, &class_info);
1122 IProvideClassInfo_Release(provide_ci);
1123 if(FAILED(hres) || !class_info) {
1124 WARN("GetClassInfo failed: %08x\n", hres);
1125 return;
1128 source_info = get_eventiface_info(plugin_container, class_info);
1129 ITypeInfo_Release(class_info);
1130 if(!source_info)
1131 return;
1134 hres = ITypeInfo_GetIDsOfNames(source_info, &event, 1, &id);
1135 if(FAILED(hres))
1136 WARN("Could not get disp id: %08x\n", hres);
1137 else if(!plugin_host->sink)
1138 plugin_host->sink = create_event_sink(plugin_host, source_info);
1140 ITypeInfo_Release(source_info);
1141 if(FAILED(hres) || !plugin_host->sink)
1142 return;
1144 add_sink_handler(plugin_host->sink, id, disp);
1147 typedef struct {
1148 IOleInPlaceFrame IOleInPlaceFrame_iface;
1149 LONG ref;
1150 } InPlaceFrame;
1152 static inline InPlaceFrame *impl_from_IOleInPlaceFrame(IOleInPlaceFrame *iface)
1154 return CONTAINING_RECORD(iface, InPlaceFrame, IOleInPlaceFrame_iface);
1157 static HRESULT WINAPI InPlaceFrame_QueryInterface(IOleInPlaceFrame *iface,
1158 REFIID riid, void **ppv)
1160 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1162 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1164 if(IsEqualGUID(&IID_IUnknown, riid)) {
1165 *ppv = &This->IOleInPlaceFrame_iface;
1166 }else if(IsEqualGUID(&IID_IOleWindow, riid)) {
1167 *ppv = &This->IOleInPlaceFrame_iface;
1168 }else if(IsEqualGUID(&IID_IOleInPlaceUIWindow, riid)) {
1169 *ppv = &This->IOleInPlaceFrame_iface;
1170 }else if(IsEqualGUID(&IID_IOleInPlaceFrame, riid)) {
1171 *ppv = &This->IOleInPlaceFrame_iface;
1172 }else {
1173 WARN("Unsopported interface %s\n", debugstr_mshtml_guid(riid));
1174 *ppv = NULL;
1175 return E_NOINTERFACE;
1178 IUnknown_AddRef((IUnknown*)*ppv);
1179 return S_OK;
1182 static ULONG WINAPI InPlaceFrame_AddRef(IOleInPlaceFrame *iface)
1184 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1185 LONG ref = InterlockedIncrement(&This->ref);
1187 TRACE("(%p) ref=%d\n", This, ref);
1189 return ref;
1192 static ULONG WINAPI InPlaceFrame_Release(IOleInPlaceFrame *iface)
1194 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1195 LONG ref = InterlockedDecrement(&This->ref);
1197 TRACE("(%p) ref=%d\n", This, ref);
1199 if(!ref)
1200 heap_free(This);
1202 return ref;
1205 static HRESULT WINAPI InPlaceFrame_GetWindow(IOleInPlaceFrame *iface, HWND *phwnd)
1207 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1208 FIXME("(%p)->(%p)\n", This, phwnd);
1209 return E_NOTIMPL;
1212 static HRESULT WINAPI InPlaceFrame_ContextSensitiveHelp(IOleInPlaceFrame *iface,
1213 BOOL fEnterMode)
1215 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1216 FIXME("(%p)->(%x)\n", This, fEnterMode);
1217 return E_NOTIMPL;
1220 static HRESULT WINAPI InPlaceFrame_GetBorder(IOleInPlaceFrame *iface, LPRECT lprectBorder)
1222 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1223 FIXME("(%p)->(%p)\n", This, lprectBorder);
1224 return E_NOTIMPL;
1227 static HRESULT WINAPI InPlaceFrame_RequestBorderSpace(IOleInPlaceFrame *iface,
1228 LPCBORDERWIDTHS pborderwidths)
1230 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1231 FIXME("(%p)->(%p)\n", This, pborderwidths);
1232 return E_NOTIMPL;
1235 static HRESULT WINAPI InPlaceFrame_SetBorderSpace(IOleInPlaceFrame *iface,
1236 LPCBORDERWIDTHS pborderwidths)
1238 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1239 FIXME("(%p)->(%p)\n", This, pborderwidths);
1240 return E_NOTIMPL;
1243 static HRESULT WINAPI InPlaceFrame_SetActiveObject(IOleInPlaceFrame *iface,
1244 IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
1246 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1247 FIXME("(%p)->(%p %s)\n", This, pActiveObject, debugstr_w(pszObjName));
1248 return E_NOTIMPL;
1251 static HRESULT WINAPI InPlaceFrame_InsertMenus(IOleInPlaceFrame *iface, HMENU hmenuShared,
1252 LPOLEMENUGROUPWIDTHS lpMenuWidths)
1254 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1255 FIXME("(%p)->(%p %p)\n", This, hmenuShared, lpMenuWidths);
1256 return E_NOTIMPL;
1259 static HRESULT WINAPI InPlaceFrame_SetMenu(IOleInPlaceFrame *iface, HMENU hmenuShared,
1260 HOLEMENU holemenu, HWND hwndActiveObject)
1262 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1263 FIXME("(%p)->(%p %p %p)\n", This, hmenuShared, holemenu, hwndActiveObject);
1264 return E_NOTIMPL;
1267 static HRESULT WINAPI InPlaceFrame_RemoveMenus(IOleInPlaceFrame *iface, HMENU hmenuShared)
1269 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1270 FIXME("(%p)->(%p)\n", This, hmenuShared);
1271 return E_NOTIMPL;
1274 static HRESULT WINAPI InPlaceFrame_SetStatusText(IOleInPlaceFrame *iface,
1275 LPCOLESTR pszStatusText)
1277 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1278 FIXME("(%p)->(%s)\n", This, debugstr_w(pszStatusText));
1279 return E_NOTIMPL;
1282 static HRESULT WINAPI InPlaceFrame_EnableModeless(IOleInPlaceFrame *iface, BOOL fEnable)
1284 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1285 FIXME("(%p)->(%x)\n", This, fEnable);
1286 return E_NOTIMPL;
1289 static HRESULT WINAPI InPlaceFrame_TranslateAccelerator(IOleInPlaceFrame *iface, LPMSG lpmsg,
1290 WORD wID)
1292 InPlaceFrame *This = impl_from_IOleInPlaceFrame(iface);
1293 FIXME("(%p)->(%p %d)\n", This, lpmsg, wID);
1294 return E_NOTIMPL;
1297 static const IOleInPlaceFrameVtbl OleInPlaceFrameVtbl = {
1298 InPlaceFrame_QueryInterface,
1299 InPlaceFrame_AddRef,
1300 InPlaceFrame_Release,
1301 InPlaceFrame_GetWindow,
1302 InPlaceFrame_ContextSensitiveHelp,
1303 InPlaceFrame_GetBorder,
1304 InPlaceFrame_RequestBorderSpace,
1305 InPlaceFrame_SetBorderSpace,
1306 InPlaceFrame_SetActiveObject,
1307 InPlaceFrame_InsertMenus,
1308 InPlaceFrame_SetMenu,
1309 InPlaceFrame_RemoveMenus,
1310 InPlaceFrame_SetStatusText,
1311 InPlaceFrame_EnableModeless,
1312 InPlaceFrame_TranslateAccelerator
1315 static HRESULT create_ip_frame(IOleInPlaceFrame **ret)
1317 InPlaceFrame *frame;
1319 frame = heap_alloc_zero(sizeof(*frame));
1320 if(!frame)
1321 return E_OUTOFMEMORY;
1323 frame->IOleInPlaceFrame_iface.lpVtbl = &OleInPlaceFrameVtbl;
1324 frame->ref = 1;
1326 *ret = &frame->IOleInPlaceFrame_iface;
1327 return S_OK;
1330 typedef struct {
1331 IOleInPlaceUIWindow IOleInPlaceUIWindow_iface;
1332 LONG ref;
1333 } InPlaceUIWindow;
1335 static inline InPlaceUIWindow *impl_from_IOleInPlaceUIWindow(IOleInPlaceUIWindow *iface)
1337 return CONTAINING_RECORD(iface, InPlaceUIWindow, IOleInPlaceUIWindow_iface);
1340 static HRESULT WINAPI InPlaceUIWindow_QueryInterface(IOleInPlaceUIWindow *iface, REFIID riid, void **ppv)
1342 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1344 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1346 if(IsEqualGUID(&IID_IUnknown, riid)) {
1347 *ppv = &This->IOleInPlaceUIWindow_iface;
1348 }else if(IsEqualGUID(&IID_IOleWindow, riid)) {
1349 *ppv = &This->IOleInPlaceUIWindow_iface;
1350 }else if(IsEqualGUID(&IID_IOleInPlaceUIWindow, riid)) {
1351 *ppv = &This->IOleInPlaceUIWindow_iface;
1352 }else {
1353 WARN("Unsopported interface %s\n", debugstr_mshtml_guid(riid));
1354 *ppv = NULL;
1355 return E_NOINTERFACE;
1358 IUnknown_AddRef((IUnknown*)*ppv);
1359 return S_OK;
1362 static ULONG WINAPI InPlaceUIWindow_AddRef(IOleInPlaceUIWindow *iface)
1364 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1365 LONG ref = InterlockedIncrement(&This->ref);
1367 TRACE("(%p) ref=%d\n", This, ref);
1369 return ref;
1372 static ULONG WINAPI InPlaceUIWindow_Release(IOleInPlaceUIWindow *iface)
1374 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1375 LONG ref = InterlockedDecrement(&This->ref);
1377 TRACE("(%p) ref=%d\n", This, ref);
1379 if(!ref)
1380 heap_free(This);
1382 return ref;
1385 static HRESULT WINAPI InPlaceUIWindow_GetWindow(IOleInPlaceUIWindow *iface, HWND *phwnd)
1387 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1388 FIXME("(%p)->(%p)\n", This, phwnd);
1389 return E_NOTIMPL;
1392 static HRESULT WINAPI InPlaceUIWindow_ContextSensitiveHelp(IOleInPlaceUIWindow *iface,
1393 BOOL fEnterMode)
1395 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1396 FIXME("(%p)->(%x)\n", This, fEnterMode);
1397 return E_NOTIMPL;
1400 static HRESULT WINAPI InPlaceUIWindow_GetBorder(IOleInPlaceUIWindow *iface, LPRECT lprectBorder)
1402 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1403 FIXME("(%p)->(%p)\n", This, lprectBorder);
1404 return E_NOTIMPL;
1407 static HRESULT WINAPI InPlaceUIWindow_RequestBorderSpace(IOleInPlaceUIWindow *iface,
1408 LPCBORDERWIDTHS pborderwidths)
1410 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1411 FIXME("(%p)->(%p)\n", This, pborderwidths);
1412 return E_NOTIMPL;
1415 static HRESULT WINAPI InPlaceUIWindow_SetBorderSpace(IOleInPlaceUIWindow *iface,
1416 LPCBORDERWIDTHS pborderwidths)
1418 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1419 FIXME("(%p)->(%p)\n", This, pborderwidths);
1420 return E_NOTIMPL;
1423 static HRESULT WINAPI InPlaceUIWindow_SetActiveObject(IOleInPlaceUIWindow *iface,
1424 IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
1426 InPlaceUIWindow *This = impl_from_IOleInPlaceUIWindow(iface);
1427 FIXME("(%p)->(%p %s)\n", This, pActiveObject, debugstr_w(pszObjName));
1428 return E_NOTIMPL;
1431 static const IOleInPlaceUIWindowVtbl OleInPlaceUIWindowVtbl = {
1432 InPlaceUIWindow_QueryInterface,
1433 InPlaceUIWindow_AddRef,
1434 InPlaceUIWindow_Release,
1435 InPlaceUIWindow_GetWindow,
1436 InPlaceUIWindow_ContextSensitiveHelp,
1437 InPlaceUIWindow_GetBorder,
1438 InPlaceUIWindow_RequestBorderSpace,
1439 InPlaceUIWindow_SetBorderSpace,
1440 InPlaceUIWindow_SetActiveObject,
1443 static HRESULT create_ip_window(IOleInPlaceUIWindow **ret)
1445 InPlaceUIWindow *uiwindow;
1447 uiwindow = heap_alloc_zero(sizeof(*uiwindow));
1448 if(!uiwindow)
1449 return E_OUTOFMEMORY;
1451 uiwindow->IOleInPlaceUIWindow_iface.lpVtbl = &OleInPlaceUIWindowVtbl;
1452 uiwindow->ref = 1;
1454 *ret = &uiwindow->IOleInPlaceUIWindow_iface;
1455 return S_OK;
1458 static inline PluginHost *impl_from_IOleClientSite(IOleClientSite *iface)
1460 return CONTAINING_RECORD(iface, PluginHost, IOleClientSite_iface);
1463 static HRESULT WINAPI PHClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv)
1465 PluginHost *This = impl_from_IOleClientSite(iface);
1467 if(IsEqualGUID(&IID_IUnknown, riid)) {
1468 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1469 *ppv = &This->IOleClientSite_iface;
1470 }else if(IsEqualGUID(&IID_IOleClientSite, riid)) {
1471 TRACE("(%p)->(IID_IOleClientSite %p)\n", This, ppv);
1472 *ppv = &This->IOleClientSite_iface;
1473 }else if(IsEqualGUID(&IID_IAdviseSink, riid)) {
1474 TRACE("(%p)->(IID_IAdviseSink %p)\n", This, ppv);
1475 *ppv = &This->IAdviseSinkEx_iface;
1476 }else if(IsEqualGUID(&IID_IAdviseSinkEx, riid)) {
1477 TRACE("(%p)->(IID_IAdviseSinkEx %p)\n", This, ppv);
1478 *ppv = &This->IAdviseSinkEx_iface;
1479 }else if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) {
1480 TRACE("(%p)->(IID_IPropertyNotifySink %p)\n", This, ppv);
1481 *ppv = &This->IPropertyNotifySink_iface;
1482 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1483 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
1484 *ppv = &This->IDispatch_iface;
1485 }else if(IsEqualGUID(&IID_IOleWindow, riid)) {
1486 TRACE("(%p)->(IID_IOleWindow %p)\n", This, ppv);
1487 *ppv = &This->IOleInPlaceSiteEx_iface;
1488 }else if(IsEqualGUID(&IID_IOleInPlaceSite, riid)) {
1489 TRACE("(%p)->(IID_IOleInPlaceSite %p)\n", This, ppv);
1490 *ppv = &This->IOleInPlaceSiteEx_iface;
1491 }else if(IsEqualGUID(&IID_IOleInPlaceSiteEx, riid)) {
1492 TRACE("(%p)->(IID_IOleInPlaceSiteEx %p)\n", This, ppv);
1493 *ppv = &This->IOleInPlaceSiteEx_iface;
1494 }else if(IsEqualGUID(&IID_IOleControlSite, riid)) {
1495 TRACE("(%p)->(IID_IOleControlSite %p)\n", This, ppv);
1496 *ppv = &This->IOleControlSite_iface;
1497 }else if(IsEqualGUID(&IID_IBindHost, riid)) {
1498 TRACE("(%p)->(IID_IBindHost %p)\n", This, ppv);
1499 *ppv = &This->IBindHost_iface;
1500 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
1501 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
1502 *ppv = &This->IServiceProvider_iface;
1503 }else {
1504 WARN("Unsupported interface %s\n", debugstr_guid(riid));
1505 *ppv = NULL;
1506 return E_NOINTERFACE;
1509 IUnknown_AddRef((IUnknown*)*ppv);
1510 return S_OK;
1513 static ULONG WINAPI PHClientSite_AddRef(IOleClientSite *iface)
1515 PluginHost *This = impl_from_IOleClientSite(iface);
1516 LONG ref = InterlockedIncrement(&This->ref);
1518 TRACE("(%p) ref=%d\n", This, ref);
1520 return ref;
1523 static void release_plugin_ifaces(PluginHost *This)
1525 if(This->disp) {
1526 IDispatch_Release(This->disp);
1527 This->disp = NULL;
1530 if(This->ip_object) {
1531 IOleInPlaceObject_Release(This->ip_object);
1532 This->ip_object = NULL;
1535 if(This->plugin_unk) {
1536 IUnknown *unk = This->plugin_unk;
1537 LONG ref;
1539 This->plugin_unk = NULL;
1540 ref = IUnknown_Release(unk);
1542 TRACE("plugin ref = %d\n", ref);
1546 static ULONG WINAPI PHClientSite_Release(IOleClientSite *iface)
1548 PluginHost *This = impl_from_IOleClientSite(iface);
1549 LONG ref = InterlockedDecrement(&This->ref);
1551 TRACE("(%p) ref=%d\n", This, ref);
1553 if(!ref) {
1554 release_plugin_ifaces(This);
1555 if(This->sink) {
1556 This->sink->host = NULL;
1557 IDispatch_Release(&This->sink->IDispatch_iface);
1558 This->sink = NULL;
1560 list_remove(&This->entry);
1561 if(This->element)
1562 This->element->plugin_host = NULL;
1563 heap_free(This);
1566 return ref;
1569 static HRESULT WINAPI PHClientSite_SaveObject(IOleClientSite *iface)
1571 PluginHost *This = impl_from_IOleClientSite(iface);
1572 FIXME("(%p)\n", This);
1573 return E_NOTIMPL;
1576 static HRESULT WINAPI PHClientSite_GetMoniker(IOleClientSite *iface, DWORD dwAssign,
1577 DWORD dwWhichMoniker, IMoniker **ppmk)
1579 PluginHost *This = impl_from_IOleClientSite(iface);
1581 TRACE("(%p)->(%d %d %p)\n", This, dwAssign, dwWhichMoniker, ppmk);
1583 switch(dwWhichMoniker) {
1584 case OLEWHICHMK_CONTAINER:
1585 if(!This->doc || !This->doc->window || !This->doc->window->mon) {
1586 FIXME("no moniker\n");
1587 return E_UNEXPECTED;
1590 *ppmk = This->doc->window->mon;
1591 IMoniker_AddRef(*ppmk);
1592 break;
1593 default:
1594 FIXME("which %d\n", dwWhichMoniker);
1595 return E_NOTIMPL;
1598 return S_OK;
1601 static HRESULT WINAPI PHClientSite_GetContainer(IOleClientSite *iface, IOleContainer **ppContainer)
1603 PluginHost *This = impl_from_IOleClientSite(iface);
1605 TRACE("(%p)->(%p)\n", This, ppContainer);
1607 if(!This->doc) {
1608 ERR("Called on detached object\n");
1609 return E_UNEXPECTED;
1612 *ppContainer = &This->doc->basedoc.IOleContainer_iface;
1613 IOleContainer_AddRef(*ppContainer);
1614 return S_OK;
1617 static HRESULT WINAPI PHClientSite_ShowObject(IOleClientSite *iface)
1619 PluginHost *This = impl_from_IOleClientSite(iface);
1621 TRACE("(%p)\n", This);
1623 return S_OK;
1626 static HRESULT WINAPI PHClientSite_OnShowWindow(IOleClientSite *iface, BOOL fShow)
1628 PluginHost *This = impl_from_IOleClientSite(iface);
1629 FIXME("(%p)->(%x)\n", This, fShow);
1630 return E_NOTIMPL;
1633 static HRESULT WINAPI PHClientSite_RequestNewObjectLayout(IOleClientSite *iface)
1635 PluginHost *This = impl_from_IOleClientSite(iface);
1636 FIXME("(%p)\n", This);
1637 return E_NOTIMPL;
1640 static const IOleClientSiteVtbl OleClientSiteVtbl = {
1641 PHClientSite_QueryInterface,
1642 PHClientSite_AddRef,
1643 PHClientSite_Release,
1644 PHClientSite_SaveObject,
1645 PHClientSite_GetMoniker,
1646 PHClientSite_GetContainer,
1647 PHClientSite_ShowObject,
1648 PHClientSite_OnShowWindow,
1649 PHClientSite_RequestNewObjectLayout
1652 static inline PluginHost *impl_from_IAdviseSinkEx(IAdviseSinkEx *iface)
1654 return CONTAINING_RECORD(iface, PluginHost, IAdviseSinkEx_iface);
1657 static HRESULT WINAPI PHAdviseSinkEx_QueryInterface(IAdviseSinkEx *iface, REFIID riid, void **ppv)
1659 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1660 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1663 static ULONG WINAPI PHAdviseSinkEx_AddRef(IAdviseSinkEx *iface)
1665 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1666 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1669 static ULONG WINAPI PHAdviseSinkEx_Release(IAdviseSinkEx *iface)
1671 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1672 return IOleClientSite_Release(&This->IOleClientSite_iface);
1675 static void WINAPI PHAdviseSinkEx_OnDataChange(IAdviseSinkEx *iface, FORMATETC *pFormatetc, STGMEDIUM *pStgMedium)
1677 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1678 FIXME("(%p)->(%p %p)\n", This, pFormatetc, pStgMedium);
1681 static void WINAPI PHAdviseSinkEx_OnViewChange(IAdviseSinkEx *iface, DWORD dwAspect, LONG lindex)
1683 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1684 FIXME("(%p)->(%d %d)\n", This, dwAspect, lindex);
1687 static void WINAPI PHAdviseSinkEx_OnRename(IAdviseSinkEx *iface, IMoniker *pmk)
1689 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1690 FIXME("(%p)->(%p)\n", This, pmk);
1693 static void WINAPI PHAdviseSinkEx_OnSave(IAdviseSinkEx *iface)
1695 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1696 FIXME("(%p)\n", This);
1699 static void WINAPI PHAdviseSinkEx_OnClose(IAdviseSinkEx *iface)
1701 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1702 FIXME("(%p)\n", This);
1705 static void WINAPI PHAdviseSinkEx_OnViewStatusChange(IAdviseSinkEx *iface, DWORD dwViewStatus)
1707 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1708 FIXME("(%p)->(%d)\n", This, dwViewStatus);
1711 static const IAdviseSinkExVtbl AdviseSinkExVtbl = {
1712 PHAdviseSinkEx_QueryInterface,
1713 PHAdviseSinkEx_AddRef,
1714 PHAdviseSinkEx_Release,
1715 PHAdviseSinkEx_OnDataChange,
1716 PHAdviseSinkEx_OnViewChange,
1717 PHAdviseSinkEx_OnRename,
1718 PHAdviseSinkEx_OnSave,
1719 PHAdviseSinkEx_OnClose,
1720 PHAdviseSinkEx_OnViewStatusChange
1723 static inline PluginHost *impl_from_IPropertyNotifySink(IPropertyNotifySink *iface)
1725 return CONTAINING_RECORD(iface, PluginHost, IPropertyNotifySink_iface);
1728 static HRESULT WINAPI PHPropertyNotifySink_QueryInterface(IPropertyNotifySink *iface, REFIID riid, void **ppv)
1730 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1731 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1734 static ULONG WINAPI PHPropertyNotifySink_AddRef(IPropertyNotifySink *iface)
1736 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1737 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1740 static ULONG WINAPI PHPropertyNotifySink_Release(IPropertyNotifySink *iface)
1742 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1743 return IOleClientSite_Release(&This->IOleClientSite_iface);
1746 static HRESULT WINAPI PHPropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID)
1748 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1750 TRACE("(%p)->(%d)\n", This, dispID);
1752 switch(dispID) {
1753 case DISPID_READYSTATE:
1754 update_readystate(This);
1755 break;
1756 default :
1757 FIXME("Unimplemented dispID %d\n", dispID);
1758 return E_NOTIMPL;
1761 return S_OK;
1764 static HRESULT WINAPI PHPropertyNotifySink_OnRequestEdit(IPropertyNotifySink *iface, DISPID dispID)
1766 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1767 FIXME("(%p)->(%d)\n", This, dispID);
1768 return E_NOTIMPL;
1771 static const IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = {
1772 PHPropertyNotifySink_QueryInterface,
1773 PHPropertyNotifySink_AddRef,
1774 PHPropertyNotifySink_Release,
1775 PHPropertyNotifySink_OnChanged,
1776 PHPropertyNotifySink_OnRequestEdit
1779 static inline PluginHost *impl_from_IDispatch(IDispatch *iface)
1781 return CONTAINING_RECORD(iface, PluginHost, IDispatch_iface);
1784 static HRESULT WINAPI PHDispatch_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
1786 PluginHost *This = impl_from_IDispatch(iface);
1787 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1790 static ULONG WINAPI PHDispatch_AddRef(IDispatch *iface)
1792 PluginHost *This = impl_from_IDispatch(iface);
1793 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1796 static ULONG WINAPI PHDispatch_Release(IDispatch *iface)
1798 PluginHost *This = impl_from_IDispatch(iface);
1799 return IOleClientSite_Release(&This->IOleClientSite_iface);
1802 static HRESULT WINAPI PHDispatch_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
1804 PluginHost *This = impl_from_IDispatch(iface);
1805 FIXME("(%p)->(%p)\n", This, pctinfo);
1806 return E_NOTIMPL;
1809 static HRESULT WINAPI PHDispatch_GetTypeInfo(IDispatch *iface, UINT iTInfo,
1810 LCID lcid, ITypeInfo **ppTInfo)
1812 PluginHost *This = impl_from_IDispatch(iface);
1813 FIXME("(%p)->(%d %d %p)\n", This, iTInfo, lcid, ppTInfo);
1814 return E_NOTIMPL;
1817 static HRESULT WINAPI PHDispatch_GetIDsOfNames(IDispatch *iface, REFIID riid,
1818 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1820 PluginHost *This = impl_from_IDispatch(iface);
1821 FIXME("(%p)->(%s %p %d %d %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1822 return E_NOTIMPL;
1825 static HRESULT WINAPI PHDispatch_Invoke(IDispatch *iface, DISPID dispid, REFIID riid, LCID lcid,
1826 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1828 PluginHost *This = impl_from_IDispatch(iface);
1829 FIXME("(%p)->(%d %x %p %p)\n", This, dispid, wFlags, pDispParams, pVarResult);
1830 return E_NOTIMPL;
1833 static const IDispatchVtbl DispatchVtbl = {
1834 PHDispatch_QueryInterface,
1835 PHDispatch_AddRef,
1836 PHDispatch_Release,
1837 PHDispatch_GetTypeInfoCount,
1838 PHDispatch_GetTypeInfo,
1839 PHDispatch_GetIDsOfNames,
1840 PHDispatch_Invoke
1843 static inline PluginHost *impl_from_IOleInPlaceSiteEx(IOleInPlaceSiteEx *iface)
1845 return CONTAINING_RECORD(iface, PluginHost, IOleInPlaceSiteEx_iface);
1848 static HRESULT WINAPI PHInPlaceSite_QueryInterface(IOleInPlaceSiteEx *iface, REFIID riid, void **ppv)
1850 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1851 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1854 static ULONG WINAPI PHInPlaceSite_AddRef(IOleInPlaceSiteEx *iface)
1856 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1857 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1860 static ULONG WINAPI PHInPlaceSite_Release(IOleInPlaceSiteEx *iface)
1862 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1863 return IOleClientSite_Release(&This->IOleClientSite_iface);
1866 static HRESULT WINAPI PHInPlaceSite_GetWindow(IOleInPlaceSiteEx *iface, HWND *phwnd)
1868 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1870 TRACE("(%p)->(%p)\n", This, phwnd);
1872 *phwnd = This->hwnd;
1873 return S_OK;
1876 static HRESULT WINAPI PHInPlaceSite_ContextSensitiveHelp(IOleInPlaceSiteEx *iface, BOOL fEnterMode)
1878 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1879 FIXME("(%p)->(%x)\n", This, fEnterMode);
1880 return E_NOTIMPL;
1883 static HRESULT WINAPI PHInPlaceSite_CanInPlaceActivate(IOleInPlaceSiteEx *iface)
1885 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1887 TRACE("(%p)\n", This);
1889 return S_OK;
1892 static HRESULT WINAPI PHInPlaceSite_OnInPlaceActivate(IOleInPlaceSiteEx *iface)
1894 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1895 FIXME("(%p)\n", This);
1896 return E_NOTIMPL;
1899 static HRESULT WINAPI PHInPlaceSite_OnUIActivate(IOleInPlaceSiteEx *iface)
1901 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1903 TRACE("(%p)\n", This);
1905 if(!This->plugin_unk) {
1906 ERR("No plugin object\n");
1907 return E_UNEXPECTED;
1910 This->ui_active = TRUE;
1912 notif_enabled(This);
1913 return S_OK;
1916 static HRESULT WINAPI PHInPlaceSite_GetWindowContext(IOleInPlaceSiteEx *iface,
1917 IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, RECT *lprcPosRect,
1918 RECT *lprcClipRect, OLEINPLACEFRAMEINFO *frame_info)
1920 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1921 IOleInPlaceUIWindow *ip_window;
1922 IOleInPlaceFrame *ip_frame;
1923 RECT pr, cr;
1924 HRESULT hres;
1926 TRACE("(%p)->(%p %p %p %p %p)\n", This, ppFrame, ppDoc, lprcPosRect, lprcClipRect, frame_info);
1928 if(!This->doc || !This->doc->basedoc.doc_obj || !This->doc->basedoc.doc_obj->ipsite) {
1929 FIXME("No ipsite\n");
1930 return E_UNEXPECTED;
1933 hres = IOleInPlaceSite_GetWindowContext(This->doc->basedoc.doc_obj->ipsite, &ip_frame, &ip_window, &pr, &cr, frame_info);
1934 if(FAILED(hres)) {
1935 WARN("GetWindowContext failed: %08x\n", hres);
1936 return hres;
1939 if(ip_window)
1940 IOleInPlaceUIWindow_Release(ip_window);
1941 if(ip_frame)
1942 IOleInPlaceFrame_Release(ip_frame);
1944 hres = create_ip_frame(&ip_frame);
1945 if(FAILED(hres))
1946 return hres;
1948 hres = create_ip_window(ppDoc);
1949 if(FAILED(hres)) {
1950 IOleInPlaceFrame_Release(ip_frame);
1951 return hres;
1954 *ppFrame = ip_frame;
1955 *lprcPosRect = This->rect;
1956 *lprcClipRect = This->rect;
1957 return S_OK;
1960 static HRESULT WINAPI PHInPlaceSite_Scroll(IOleInPlaceSiteEx *iface, SIZE scrollExtent)
1962 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1963 FIXME("(%p)->({%d %d})\n", This, scrollExtent.cx, scrollExtent.cy);
1964 return E_NOTIMPL;
1967 static HRESULT WINAPI PHInPlaceSite_OnUIDeactivate(IOleInPlaceSiteEx *iface, BOOL fUndoable)
1969 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1970 FIXME("(%p)->(%x)\n", This, fUndoable);
1971 return E_NOTIMPL;
1974 static HRESULT WINAPI PHInPlaceSite_OnInPlaceDeactivate(IOleInPlaceSiteEx *iface)
1976 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1978 TRACE("(%p)\n", This);
1980 if(This->ip_object) {
1981 IOleInPlaceObject_Release(This->ip_object);
1982 This->ip_object = NULL;
1985 return S_OK;
1988 static HRESULT WINAPI PHInPlaceSite_DiscardUndoState(IOleInPlaceSiteEx *iface)
1990 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1991 FIXME("(%p)\n", This);
1992 return E_NOTIMPL;
1995 static HRESULT WINAPI PHInPlaceSite_DeactivateAndUndo(IOleInPlaceSiteEx *iface)
1997 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1998 FIXME("(%p)\n", This);
1999 return E_NOTIMPL;
2002 static HRESULT WINAPI PHInPlaceSite_OnPosRectChange(IOleInPlaceSiteEx *iface, LPCRECT lprcPosRect)
2004 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
2005 FIXME("(%p)->(%p)\n", This, lprcPosRect);
2006 return E_NOTIMPL;
2009 static HRESULT WINAPI PHInPlaceSiteEx_OnInPlaceActivateEx(IOleInPlaceSiteEx *iface, BOOL *pfNoRedraw, DWORD dwFlags)
2011 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
2012 HWND hwnd;
2013 HRESULT hres;
2015 TRACE("(%p)->(%p %x)\n", This, pfNoRedraw, dwFlags);
2017 if(This->ip_object)
2018 return S_OK;
2020 hres = IUnknown_QueryInterface(This->plugin_unk, &IID_IOleInPlaceObject, (void**)&This->ip_object);
2021 if(FAILED(hres))
2022 return hres;
2024 hres = IOleInPlaceObject_GetWindow(This->ip_object, &hwnd);
2025 if(SUCCEEDED(hres))
2026 FIXME("Use hwnd %p\n", hwnd);
2028 *pfNoRedraw = FALSE;
2029 return S_OK;
2032 static HRESULT WINAPI PHInPlaceSiteEx_OnInPlaceDeactivateEx(IOleInPlaceSiteEx *iface, BOOL fNoRedraw)
2034 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
2035 FIXME("(%p)->(%x)\n", This, fNoRedraw);
2036 return E_NOTIMPL;
2039 static HRESULT WINAPI PHInPlaceSiteEx_RequestUIActivate(IOleInPlaceSiteEx *iface)
2041 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
2042 FIXME("(%p)\n", This);
2043 return E_NOTIMPL;
2046 static const IOleInPlaceSiteExVtbl OleInPlaceSiteExVtbl = {
2047 PHInPlaceSite_QueryInterface,
2048 PHInPlaceSite_AddRef,
2049 PHInPlaceSite_Release,
2050 PHInPlaceSite_GetWindow,
2051 PHInPlaceSite_ContextSensitiveHelp,
2052 PHInPlaceSite_CanInPlaceActivate,
2053 PHInPlaceSite_OnInPlaceActivate,
2054 PHInPlaceSite_OnUIActivate,
2055 PHInPlaceSite_GetWindowContext,
2056 PHInPlaceSite_Scroll,
2057 PHInPlaceSite_OnUIDeactivate,
2058 PHInPlaceSite_OnInPlaceDeactivate,
2059 PHInPlaceSite_DiscardUndoState,
2060 PHInPlaceSite_DeactivateAndUndo,
2061 PHInPlaceSite_OnPosRectChange,
2062 PHInPlaceSiteEx_OnInPlaceActivateEx,
2063 PHInPlaceSiteEx_OnInPlaceDeactivateEx,
2064 PHInPlaceSiteEx_RequestUIActivate
2067 static inline PluginHost *impl_from_IOleControlSite(IOleControlSite *iface)
2069 return CONTAINING_RECORD(iface, PluginHost, IOleControlSite_iface);
2072 static HRESULT WINAPI PHControlSite_QueryInterface(IOleControlSite *iface, REFIID riid, void **ppv)
2074 PluginHost *This = impl_from_IOleControlSite(iface);
2075 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
2078 static ULONG WINAPI PHControlSite_AddRef(IOleControlSite *iface)
2080 PluginHost *This = impl_from_IOleControlSite(iface);
2081 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
2084 static ULONG WINAPI PHControlSite_Release(IOleControlSite *iface)
2086 PluginHost *This = impl_from_IOleControlSite(iface);
2087 return IOleClientSite_Release(&This->IOleClientSite_iface);
2090 static HRESULT WINAPI PHControlSite_OnControlInfoChanged(IOleControlSite *iface)
2092 PluginHost *This = impl_from_IOleControlSite(iface);
2093 FIXME("(%p)\n", This);
2094 return E_NOTIMPL;
2097 static HRESULT WINAPI PHControlSite_LockInPlaceActive(IOleControlSite *iface, BOOL fLock)
2099 PluginHost *This = impl_from_IOleControlSite(iface);
2100 FIXME("(%p)->(%x)\n", This, fLock);
2101 return E_NOTIMPL;
2104 static HRESULT WINAPI PHControlSite_GetExtendedControl(IOleControlSite *iface, IDispatch **ppDisp)
2106 PluginHost *This = impl_from_IOleControlSite(iface);
2107 FIXME("(%p)->(%p)\n", This, ppDisp);
2108 return E_NOTIMPL;
2111 static HRESULT WINAPI PHControlSite_TransformCoords(IOleControlSite *iface, POINTL *pPtlHimetric, POINTF *pPtfContainer, DWORD dwFlags)
2113 PluginHost *This = impl_from_IOleControlSite(iface);
2114 FIXME("(%p)->(%p %p %x)\n", This, pPtlHimetric, pPtfContainer, dwFlags);
2115 return E_NOTIMPL;
2118 static HRESULT WINAPI PHControlSite_TranslateAccelerator(IOleControlSite *iface, MSG *pMsg, DWORD grfModifiers)
2120 PluginHost *This = impl_from_IOleControlSite(iface);
2121 FIXME("(%p)->(%x)\n", This, grfModifiers);
2122 return E_NOTIMPL;
2125 static HRESULT WINAPI PHControlSite_OnFocus(IOleControlSite *iface, BOOL fGotFocus)
2127 PluginHost *This = impl_from_IOleControlSite(iface);
2128 FIXME("(%p)->(%x)\n", This, fGotFocus);
2129 return E_NOTIMPL;
2132 static HRESULT WINAPI PHControlSite_ShowPropertyFrame(IOleControlSite *iface)
2134 PluginHost *This = impl_from_IOleControlSite(iface);
2135 FIXME("(%p)\n", This);
2136 return E_NOTIMPL;
2139 static const IOleControlSiteVtbl OleControlSiteVtbl = {
2140 PHControlSite_QueryInterface,
2141 PHControlSite_AddRef,
2142 PHControlSite_Release,
2143 PHControlSite_OnControlInfoChanged,
2144 PHControlSite_LockInPlaceActive,
2145 PHControlSite_GetExtendedControl,
2146 PHControlSite_TransformCoords,
2147 PHControlSite_TranslateAccelerator,
2148 PHControlSite_OnFocus,
2149 PHControlSite_ShowPropertyFrame
2152 static inline PluginHost *impl_from_IBindHost(IBindHost *iface)
2154 return CONTAINING_RECORD(iface, PluginHost, IBindHost_iface);
2157 static HRESULT WINAPI PHBindHost_QueryInterface(IBindHost *iface, REFIID riid, void **ppv)
2159 PluginHost *This = impl_from_IBindHost(iface);
2160 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
2163 static ULONG WINAPI PHBindHost_AddRef(IBindHost *iface)
2165 PluginHost *This = impl_from_IBindHost(iface);
2166 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
2169 static ULONG WINAPI PHBindHost_Release(IBindHost *iface)
2171 PluginHost *This = impl_from_IBindHost(iface);
2172 return IOleClientSite_Release(&This->IOleClientSite_iface);
2175 static HRESULT WINAPI PHBindHost_CreateMoniker(IBindHost *iface, LPOLESTR szName, IBindCtx *pBC, IMoniker **ppmk, DWORD dwReserved)
2177 PluginHost *This = impl_from_IBindHost(iface);
2179 TRACE("(%p)->(%s %p %p %x)\n", This, debugstr_w(szName), pBC, ppmk, dwReserved);
2181 if(!This->doc || !This->doc->window || !This->doc->window->mon) {
2182 FIXME("no moniker\n");
2183 return E_UNEXPECTED;
2186 return CreateURLMoniker(This->doc->window->mon, szName, ppmk);
2189 static HRESULT WINAPI PHBindHost_MonikerBindToStorage(IBindHost *iface, IMoniker *pMk, IBindCtx *pBC,
2190 IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
2192 PluginHost *This = impl_from_IBindHost(iface);
2193 FIXME("(%p)->(%p %p %p %s %p)\n", This, pMk, pBC, pBSC, debugstr_guid(riid), ppvObj);
2194 return E_NOTIMPL;
2197 static HRESULT WINAPI PHBindHost_MonikerBindToObject(IBindHost *iface, IMoniker *pMk, IBindCtx *pBC,
2198 IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
2200 PluginHost *This = impl_from_IBindHost(iface);
2201 FIXME("(%p)->(%p %p %p %s %p)\n", This, pMk, pBC, pBSC, debugstr_guid(riid), ppvObj);
2202 return E_NOTIMPL;
2205 static const IBindHostVtbl BindHostVtbl = {
2206 PHBindHost_QueryInterface,
2207 PHBindHost_AddRef,
2208 PHBindHost_Release,
2209 PHBindHost_CreateMoniker,
2210 PHBindHost_MonikerBindToStorage,
2211 PHBindHost_MonikerBindToObject
2214 static inline PluginHost *impl_from_IServiceProvider(IServiceProvider *iface)
2216 return CONTAINING_RECORD(iface, PluginHost, IServiceProvider_iface);
2219 static HRESULT WINAPI PHServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
2221 PluginHost *This = impl_from_IServiceProvider(iface);
2222 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
2225 static ULONG WINAPI PHServiceProvider_AddRef(IServiceProvider *iface)
2227 PluginHost *This = impl_from_IServiceProvider(iface);
2228 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
2231 static ULONG WINAPI PHServiceProvider_Release(IServiceProvider *iface)
2233 PluginHost *This = impl_from_IServiceProvider(iface);
2234 return IOleClientSite_Release(&This->IOleClientSite_iface);
2237 static HRESULT WINAPI PHServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService, REFIID riid, void **ppv)
2239 PluginHost *This = impl_from_IServiceProvider(iface);
2241 if(IsEqualGUID(guidService, &SID_SBindHost)) {
2242 TRACE("SID_SBindHost service\n");
2243 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
2246 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
2248 if(!This->doc || !This->doc->basedoc.window) {
2249 *ppv = NULL;
2250 return E_NOINTERFACE;
2253 return IServiceProvider_QueryService(&This->doc->basedoc.window->base.IServiceProvider_iface,
2254 guidService, riid, ppv);
2257 static const IServiceProviderVtbl ServiceProviderVtbl = {
2258 PHServiceProvider_QueryInterface,
2259 PHServiceProvider_AddRef,
2260 PHServiceProvider_Release,
2261 PHServiceProvider_QueryService
2264 static BOOL parse_classid(const PRUnichar *classid, CLSID *clsid)
2266 const WCHAR *ptr;
2267 unsigned len;
2268 HRESULT hres;
2270 static const PRUnichar clsidW[] = {'c','l','s','i','d',':'};
2272 if(strncmpiW(classid, clsidW, sizeof(clsidW)/sizeof(WCHAR)))
2273 return FALSE;
2275 ptr = classid + sizeof(clsidW)/sizeof(WCHAR);
2276 len = strlenW(ptr);
2278 if(len == 38) {
2279 hres = CLSIDFromString(ptr, clsid);
2280 }else if(len == 36) {
2281 WCHAR buf[39];
2283 buf[0] = '{';
2284 memcpy(buf+1, ptr, len*sizeof(WCHAR));
2285 buf[37] = '}';
2286 buf[38] = 0;
2287 hres = CLSIDFromString(buf, clsid);
2288 }else {
2289 return FALSE;
2292 return SUCCEEDED(hres);
2295 static BOOL get_elem_clsid(nsIDOMElement *elem, CLSID *clsid)
2297 const PRUnichar *val;
2298 nsAString val_str;
2299 nsresult nsres;
2300 BOOL ret = FALSE;
2302 static const PRUnichar classidW[] = {'c','l','a','s','s','i','d',0};
2304 nsres = get_elem_attr_value(elem, classidW, &val_str, &val);
2305 if(NS_SUCCEEDED(nsres)) {
2306 if(*val)
2307 ret = parse_classid(val, clsid);
2308 nsAString_Finish(&val_str);
2311 return ret;
2314 typedef struct {
2315 IBindStatusCallback IBindStatusCallback_iface;
2316 IWindowForBindingUI IWindowForBindingUI_iface;
2317 LONG ref;
2318 } InstallCallback;
2320 static inline InstallCallback *impl_from_IBindStatusCallback(IBindStatusCallback *iface)
2322 return CONTAINING_RECORD(iface, InstallCallback, IBindStatusCallback_iface);
2325 static HRESULT WINAPI InstallCallback_QueryInterface(IBindStatusCallback *iface,
2326 REFIID riid, void **ppv)
2328 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2330 if(IsEqualGUID(&IID_IUnknown, riid)) {
2331 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
2332 *ppv = &This->IBindStatusCallback_iface;
2333 }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
2334 TRACE("(%p)->(IID_IBindStatusCallback %p)\n", This, ppv);
2335 *ppv = &This->IBindStatusCallback_iface;
2336 }else if(IsEqualGUID(&IID_IWindowForBindingUI, riid)) {
2337 TRACE("(%p)->(IID_IWindowForBindingUI %p)\n", This, ppv);
2338 *ppv = &This->IWindowForBindingUI_iface;
2339 }else {
2340 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
2341 *ppv = NULL;
2342 return E_NOINTERFACE;
2345 IUnknown_AddRef((IUnknown*)*ppv);
2346 return S_OK;
2349 static ULONG WINAPI InstallCallback_AddRef(IBindStatusCallback *iface)
2351 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2352 LONG ref = InterlockedIncrement(&This->ref);
2354 TRACE("(%p) ref=%d\n", This, ref);
2356 return ref;
2359 static ULONG WINAPI InstallCallback_Release(IBindStatusCallback *iface)
2361 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2362 LONG ref = InterlockedIncrement(&This->ref);
2364 TRACE("(%p) ref=%d\n", This, ref);
2366 if(!ref)
2367 heap_free(This);
2369 return ref;
2372 static HRESULT WINAPI InstallCallback_OnStartBinding(IBindStatusCallback *iface,
2373 DWORD dwReserved, IBinding *pib)
2375 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2376 TRACE("(%p)->(%x %p)\n", This, dwReserved, pib);
2377 return S_OK;
2380 static HRESULT WINAPI InstallCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
2382 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2383 TRACE("(%p)->(%p)\n", This, pnPriority);
2384 return E_NOTIMPL;
2387 static HRESULT WINAPI InstallCallback_OnLowResource(IBindStatusCallback *iface, DWORD dwReserved)
2389 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2390 TRACE("(%p)->(%x)\n", This, dwReserved);
2391 return S_OK;
2394 static HRESULT WINAPI InstallCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
2395 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
2397 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2398 TRACE("(%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode, debugstr_w(szStatusText));
2399 return S_OK;
2402 static HRESULT WINAPI InstallCallback_OnStopBinding(IBindStatusCallback *iface,
2403 HRESULT hresult, LPCWSTR szError)
2405 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2406 TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
2407 return S_OK;
2410 static HRESULT WINAPI InstallCallback_GetBindInfo(IBindStatusCallback *iface,
2411 DWORD* grfBINDF, BINDINFO* pbindinfo)
2413 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2415 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
2417 *grfBINDF = BINDF_ASYNCHRONOUS;
2418 return S_OK;
2421 static HRESULT WINAPI InstallCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
2422 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
2424 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2425 ERR("(%p)\n", This);
2426 return E_NOTIMPL;
2429 static HRESULT WINAPI InstallCallback_OnObjectAvailable(IBindStatusCallback *iface,
2430 REFIID riid, IUnknown* punk)
2432 InstallCallback *This = impl_from_IBindStatusCallback(iface);
2433 ERR("(%p)\n", This);
2434 return E_NOTIMPL;
2437 static IBindStatusCallbackVtbl InstallCallbackVtbl = {
2438 InstallCallback_QueryInterface,
2439 InstallCallback_AddRef,
2440 InstallCallback_Release,
2441 InstallCallback_OnStartBinding,
2442 InstallCallback_GetPriority,
2443 InstallCallback_OnLowResource,
2444 InstallCallback_OnProgress,
2445 InstallCallback_OnStopBinding,
2446 InstallCallback_GetBindInfo,
2447 InstallCallback_OnDataAvailable,
2448 InstallCallback_OnObjectAvailable
2451 static inline InstallCallback *impl_from_IWindowForBindingUI(IWindowForBindingUI *iface)
2453 return CONTAINING_RECORD(iface, InstallCallback, IWindowForBindingUI_iface);
2456 static HRESULT WINAPI WindowForBindingUI_QueryInterface(IWindowForBindingUI *iface, REFIID riid, void **ppv)
2458 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
2459 return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
2462 static ULONG WINAPI WindowForBindingUI_AddRef(IWindowForBindingUI *iface)
2464 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
2465 return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
2468 static ULONG WINAPI WindowForBindingUI_Release(IWindowForBindingUI *iface)
2470 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
2471 return IBindStatusCallback_Release(&This->IBindStatusCallback_iface);
2474 static HRESULT WINAPI WindowForBindingUI_GetWindow(IWindowForBindingUI *iface, REFGUID rguidReason, HWND *phwnd)
2476 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
2477 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(rguidReason), phwnd);
2478 *phwnd = NULL;
2479 return S_OK;
2482 static const IWindowForBindingUIVtbl WindowForBindingUIVtbl = {
2483 WindowForBindingUI_QueryInterface,
2484 WindowForBindingUI_AddRef,
2485 WindowForBindingUI_Release,
2486 WindowForBindingUI_GetWindow
2489 typedef struct {
2490 struct list entry;
2491 IUri *uri;
2492 } install_entry_t;
2494 static struct list install_list = LIST_INIT(install_list);
2496 static CRITICAL_SECTION cs_install_list;
2497 static CRITICAL_SECTION_DEBUG cs_install_list_dbg =
2499 0, 0, &cs_install_list,
2500 { &cs_install_list_dbg.ProcessLocksList, &cs_install_list_dbg.ProcessLocksList },
2501 0, 0, { (DWORD_PTR)(__FILE__ ": install_list") }
2503 static CRITICAL_SECTION cs_install_list = { &cs_install_list_dbg, -1, 0, 0, 0, 0 };
2505 static void install_codebase(const WCHAR *url)
2507 InstallCallback *callback;
2508 IBindCtx *bctx;
2509 HRESULT hres;
2511 callback = heap_alloc(sizeof(*callback));
2512 if(!callback)
2513 return;
2515 callback->IBindStatusCallback_iface.lpVtbl = &InstallCallbackVtbl;
2516 callback->IWindowForBindingUI_iface.lpVtbl = &WindowForBindingUIVtbl;
2517 callback->ref = 1;
2519 hres = CreateAsyncBindCtx(0, &callback->IBindStatusCallback_iface, NULL, &bctx);
2520 IBindStatusCallback_Release(&callback->IBindStatusCallback_iface);
2521 if(FAILED(hres))
2522 return;
2524 hres = AsyncInstallDistributionUnit(NULL, NULL, NULL, 0, 0, url, bctx, NULL, 0);
2525 IBindCtx_Release(bctx);
2526 if(FAILED(hres))
2527 WARN("FAILED: %08x\n", hres);
2530 static void check_codebase(HTMLInnerWindow *window, nsIDOMElement *nselem)
2532 BOOL is_on_list = FALSE;
2533 install_entry_t *iter;
2534 const PRUnichar *val;
2535 nsAString val_str;
2536 IUri *uri = NULL;
2537 nsresult nsres;
2538 HRESULT hres;
2540 static const PRUnichar codebaseW[] = {'c','o','d','e','b','a','s','e',0};
2542 nsres = get_elem_attr_value(nselem, codebaseW, &val_str, &val);
2543 if(NS_SUCCEEDED(nsres)) {
2544 if(*val) {
2545 hres = CoInternetCombineUrlEx(window->base.outer_window->uri, val, 0, &uri, 0);
2546 if(FAILED(hres))
2547 uri = NULL;
2549 nsAString_Finish(&val_str);
2552 if(!uri)
2553 return;
2555 EnterCriticalSection(&cs_install_list);
2557 LIST_FOR_EACH_ENTRY(iter, &install_list, install_entry_t, entry) {
2558 BOOL eq;
2560 hres = IUri_IsEqual(uri, iter->uri, &eq);
2561 if(SUCCEEDED(hres) && eq) {
2562 TRACE("already proceeded\n");
2563 is_on_list = TRUE;
2564 break;
2568 if(!is_on_list) {
2569 iter = heap_alloc(sizeof(*iter));
2570 if(iter) {
2571 IUri_AddRef(uri);
2572 iter->uri = uri;
2574 list_add_tail(&install_list, &iter->entry);
2578 LeaveCriticalSection(&cs_install_list);
2580 if(!is_on_list) {
2581 BSTR display_uri;
2583 hres = IUri_GetDisplayUri(uri, &display_uri);
2584 if(SUCCEEDED(hres)) {
2585 install_codebase(display_uri);
2586 SysFreeString(display_uri);
2590 IUri_Release(uri);
2593 static IUnknown *create_activex_object(HTMLDocumentNode *doc, nsIDOMElement *nselem, CLSID *clsid)
2595 IClassFactoryEx *cfex;
2596 IClassFactory *cf;
2597 IUnknown *obj;
2598 DWORD policy;
2599 HRESULT hres;
2601 if(!get_elem_clsid(nselem, clsid)) {
2602 WARN("Could not determine element CLSID\n");
2603 return NULL;
2606 TRACE("clsid %s\n", debugstr_guid(clsid));
2608 policy = 0;
2609 hres = IInternetHostSecurityManager_ProcessUrlAction(&doc->IInternetHostSecurityManager_iface,
2610 URLACTION_ACTIVEX_RUN, (BYTE*)&policy, sizeof(policy), (BYTE*)clsid, sizeof(GUID), 0, 0);
2611 if(FAILED(hres) || policy != URLPOLICY_ALLOW) {
2612 WARN("ProcessUrlAction returned %08x %x\n", hres, policy);
2613 return NULL;
2616 hres = CoGetClassObject(clsid, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, NULL, &IID_IClassFactory, (void**)&cf);
2617 if(hres == REGDB_E_CLASSNOTREG)
2618 check_codebase(doc->window, nselem);
2619 if(FAILED(hres))
2620 return NULL;
2622 hres = IClassFactory_QueryInterface(cf, &IID_IClassFactoryEx, (void**)&cfex);
2623 if(SUCCEEDED(hres)) {
2624 FIXME("Use IClassFactoryEx\n");
2625 IClassFactoryEx_Release(cfex);
2628 hres = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)&obj);
2629 IClassFactory_Release(cf);
2630 if(FAILED(hres))
2631 return NULL;
2633 return obj;
2636 void detach_plugin_host(PluginHost *host)
2638 HRESULT hres;
2640 TRACE("%p\n", host);
2642 if(!host->doc)
2643 return;
2645 if(host->ip_object) {
2646 if(host->ui_active)
2647 IOleInPlaceObject_UIDeactivate(host->ip_object);
2648 IOleInPlaceObject_InPlaceDeactivate(host->ip_object);
2651 if(host->plugin_unk) {
2652 IOleObject *ole_obj;
2654 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleObject, (void**)&ole_obj);
2655 if(SUCCEEDED(hres)) {
2656 if(!host->ip_object)
2657 IOleObject_Close(ole_obj, OLECLOSE_NOSAVE);
2658 IOleObject_SetClientSite(ole_obj, NULL);
2659 IOleObject_Release(ole_obj);
2663 if(host->sink) {
2664 IConnectionPointContainer *cp_container;
2665 IConnectionPoint *cp;
2667 assert(host->plugin_unk != NULL);
2669 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IConnectionPointContainer, (void**)&cp_container);
2670 if(SUCCEEDED(hres)) {
2671 hres = IConnectionPointContainer_FindConnectionPoint(cp_container, &host->sink->iid, &cp);
2672 IConnectionPointContainer_Release(cp_container);
2673 if(SUCCEEDED(hres)) {
2674 IConnectionPoint_Unadvise(cp, host->sink->cookie);
2675 IConnectionPoint_Release(cp);
2679 host->sink->host = NULL;
2680 IDispatch_Release(&host->sink->IDispatch_iface);
2681 host->sink = NULL;
2684 release_plugin_ifaces(host);
2686 if(host->element) {
2687 host->element->plugin_host = NULL;
2688 host->element = NULL;
2691 list_remove(&host->entry);
2692 list_init(&host->entry);
2693 host->doc = NULL;
2696 HRESULT create_plugin_host(HTMLDocumentNode *doc, HTMLPluginContainer *container)
2698 PluginHost *host;
2699 IUnknown *unk;
2700 CLSID clsid;
2702 assert(!container->plugin_host);
2704 unk = create_activex_object(doc, container->element.dom_element, &clsid);
2705 if(!unk)
2706 return E_FAIL;
2708 host = heap_alloc_zero(sizeof(*host));
2709 if(!host) {
2710 IUnknown_Release(unk);
2711 return E_OUTOFMEMORY;
2714 host->IOleClientSite_iface.lpVtbl = &OleClientSiteVtbl;
2715 host->IAdviseSinkEx_iface.lpVtbl = &AdviseSinkExVtbl;
2716 host->IPropertyNotifySink_iface.lpVtbl = &PropertyNotifySinkVtbl;
2717 host->IDispatch_iface.lpVtbl = &DispatchVtbl;
2718 host->IOleInPlaceSiteEx_iface.lpVtbl = &OleInPlaceSiteExVtbl;
2719 host->IOleControlSite_iface.lpVtbl = &OleControlSiteVtbl;
2720 host->IBindHost_iface.lpVtbl = &BindHostVtbl;
2721 host->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
2723 host->ref = 1;
2725 host->plugin_unk = unk;
2726 host->clsid = clsid;
2728 host->doc = doc;
2729 list_add_tail(&doc->plugin_hosts, &host->entry);
2731 container->plugin_host = host;
2732 host->element = container;
2734 initialize_plugin_object(host);
2736 return S_OK;