Reactos
1/*
2 * Copyright 2010 Jacek Caban for CodeWeavers
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#include "mshtml_private.h"
20
21static BOOL check_load_safety(PluginHost *host)
22{
23 DWORD policy_size, policy;
24 struct CONFIRMSAFETY cs;
25 BYTE *ppolicy;
26 HRESULT hres;
27
28 cs.clsid = host->clsid;
29 cs.pUnk = host->plugin_unk;
30 cs.dwFlags = CONFIRMSAFETYACTION_LOADOBJECT;
31
32 hres = IInternetHostSecurityManager_QueryCustomPolicy(&host->doc->IInternetHostSecurityManager_iface,
33 &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
34 if(FAILED(hres))
35 return FALSE;
36
37 policy = *(DWORD*)ppolicy;
38 CoTaskMemFree(ppolicy);
39 return policy == URLPOLICY_ALLOW;
40}
41
42static BOOL check_script_safety(PluginHost *host)
43{
44 DISPPARAMS params = {NULL,NULL,0,0};
45 DWORD policy_size, policy;
46 struct CONFIRMSAFETY cs;
47 BYTE *ppolicy;
48 ULONG err = 0;
49 VARIANT v;
50 HRESULT hres;
51
52 cs.clsid = host->clsid;
53 cs.pUnk = host->plugin_unk;
54 cs.dwFlags = 0;
55
56 hres = IInternetHostSecurityManager_QueryCustomPolicy(&host->doc->IInternetHostSecurityManager_iface,
57 &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
58 if(FAILED(hres))
59 return FALSE;
60
61 policy = *(DWORD*)ppolicy;
62 CoTaskMemFree(ppolicy);
63
64 if(policy != URLPOLICY_ALLOW)
65 return FALSE;
66
67 V_VT(&v) = VT_EMPTY;
68 hres = IDispatch_Invoke(host->disp, DISPID_SECURITYCTX, &IID_NULL, 0, DISPATCH_PROPERTYGET, ¶ms, &v, NULL, &err);
69 if(SUCCEEDED(hres)) {
70 FIXME("Handle security ctx %s\n", debugstr_variant(&v));
71 return FALSE;
72 }
73
74 return TRUE;
75}
76
77static void update_readystate(PluginHost *host)
78{
79 DISPPARAMS params = {NULL,NULL,0,0};
80 IDispatchEx *dispex;
81 IDispatch *disp;
82 ULONG err = 0;
83 VARIANT v;
84 HRESULT hres;
85
86 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatchEx, (void**)&dispex);
87 if(SUCCEEDED(hres)) {
88 FIXME("Use IDispatchEx\n");
89 IDispatchEx_Release(dispex);
90 }
91
92 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatch, (void**)&disp);
93 if(FAILED(hres))
94 return;
95
96 hres = IDispatch_Invoke(disp, DISPID_READYSTATE, &IID_NULL, 0, DISPATCH_PROPERTYGET, ¶ms, &v, NULL, &err);
97 IDispatch_Release(disp);
98 if(SUCCEEDED(hres)) {
99 /* FIXME: make plugin readystate affect document readystate */
100 TRACE("readystate = %s\n", debugstr_variant(&v));
101 VariantClear(&v);
102 }
103}
104
105/* FIXME: We shouldn't need this function and we should embed plugin directly in the main document */
106static void get_pos_rect(PluginHost *host, RECT *ret)
107{
108 ret->top = 0;
109 ret->left = 0;
110 ret->bottom = host->rect.bottom - host->rect.top;
111 ret->right = host->rect.right - host->rect.left;
112}
113
114static void load_prop_bag(PluginHost *host, IPersistPropertyBag *persist_prop_bag)
115{
116 IPropertyBag *prop_bag;
117 HRESULT hres;
118
119 hres = create_param_prop_bag(host->element->element.nselem, &prop_bag);
120 if(FAILED(hres))
121 return;
122
123 if(prop_bag && !check_load_safety(host)) {
124 IPropertyBag_Release(prop_bag);
125 prop_bag = NULL;
126 }
127
128 if(prop_bag) {
129 hres = IPersistPropertyBag_Load(persist_prop_bag, prop_bag, NULL);
130 IPropertyBag_Release(prop_bag);
131 if(FAILED(hres))
132 WARN("Load failed: %08x\n", hres);
133 }else {
134 hres = IPersistPropertyBag_InitNew(persist_prop_bag);
135 if(FAILED(hres))
136 WARN("InitNew failed: %08x\n", hres);
137 }
138}
139
140static void load_plugin(PluginHost *host)
141{
142 IPersistPropertyBag2 *persist_prop_bag2;
143 IPersistPropertyBag *persist_prop_bag;
144 HRESULT hres;
145
146 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IPersistPropertyBag2, (void**)&persist_prop_bag2);
147 if(SUCCEEDED(hres)) {
148 FIXME("Use IPersistPropertyBag2 iface\n");
149 IPersistPropertyBag2_Release(persist_prop_bag2);
150 return;
151 }
152
153 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IPersistPropertyBag, (void**)&persist_prop_bag);
154 if(SUCCEEDED(hres)) {
155 load_prop_bag(host, persist_prop_bag);
156 IPersistPropertyBag_Release(persist_prop_bag);
157 return;
158 }
159
160 FIXME("No IPersistPropertyBag iface\n");
161}
162
163static void initialize_plugin_object(PluginHost *host)
164{
165 IClientSecurity *client_security;
166 IQuickActivate *quick_activate;
167 IOleObject *ole_obj = NULL;
168 IOleCommandTarget *cmdtrg;
169 IViewObjectEx *view_obj;
170 IDispatchEx *dispex;
171 IDispatch *disp;
172 HRESULT hres;
173
174 /* Note native calls QI on plugin for an undocumented IID and CLSID_HTMLDocument */
175
176 /* FIXME: call FreezeEvents(TRUE) */
177
178 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IClientSecurity, (void**)&client_security);
179 if(SUCCEEDED(hres)) {
180 FIXME("Handle IClientSecurity\n");
181 IClientSecurity_Release(client_security);
182 return;
183 }
184
185 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IQuickActivate, (void**)&quick_activate);
186 if(SUCCEEDED(hres)) {
187 QACONTAINER container = {sizeof(container)};
188 QACONTROL control = {sizeof(control)};
189
190 TRACE("Using IQuickActivate\n");
191
192 container.pClientSite = &host->IOleClientSite_iface;
193 container.dwAmbientFlags = QACONTAINER_SUPPORTSMNEMONICS|QACONTAINER_MESSAGEREFLECT|QACONTAINER_USERMODE;
194 container.pAdviseSink = &host->IAdviseSinkEx_iface;
195 container.pPropertyNotifySink = &host->IPropertyNotifySink_iface;
196
197 hres = IQuickActivate_QuickActivate(quick_activate, &container, &control);
198 IQuickActivate_Release(quick_activate);
199 if(FAILED(hres))
200 FIXME("QuickActivate failed: %08x\n", hres);
201 }else {
202 DWORD status = 0;
203
204 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleObject, (void**)&ole_obj);
205 if(SUCCEEDED(hres)) {
206 hres = IOleObject_GetMiscStatus(ole_obj, DVASPECT_CONTENT, &status);
207 TRACE("GetMiscStatus returned %08x %x\n", hres, status);
208
209 hres = IOleObject_SetClientSite(ole_obj, &host->IOleClientSite_iface);
210 IOleObject_Release(ole_obj);
211 if(FAILED(hres)) {
212 FIXME("SetClientSite failed: %08x\n", hres);
213 return;
214 }
215 }else {
216 TRACE("Plugin does not support IOleObject\n");
217 }
218 }
219
220 load_plugin(host);
221
222 if(ole_obj) {
223 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IViewObjectEx, (void**)&view_obj);
224 if(SUCCEEDED(hres)) {
225 DWORD view_status = 0;
226
227 hres = IViewObjectEx_SetAdvise(view_obj, DVASPECT_CONTENT, 0, (IAdviseSink*)&host->IAdviseSinkEx_iface);
228 if(FAILED(hres))
229 WARN("SetAdvise failed: %08x\n", hres);
230
231 hres = IViewObjectEx_GetViewStatus(view_obj, &view_status);
232 IViewObjectEx_Release(view_obj);
233 TRACE("GetViewStatus returned %08x %x\n", hres, view_status);
234 }
235 }
236
237 update_readystate(host);
238
239 /* NOTE: Native QIs for IActiveScript, an undocumented IID, IOleControl and IRunnableObject */
240
241 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatchEx, (void**)&dispex);
242 if(SUCCEEDED(hres)) {
243 FIXME("Use IDispatchEx\n");
244 host->disp = (IDispatch*)dispex;
245 }else {
246 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IDispatch, (void**)&disp);
247 if(SUCCEEDED(hres))
248 host->disp = disp;
249 else
250 TRACE("no IDispatch iface\n");
251 }
252
253 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleCommandTarget, (void**)&cmdtrg);
254 if(SUCCEEDED(hres)) {
255 FIXME("Use IOleCommandTarget\n");
256 IOleCommandTarget_Release(cmdtrg);
257 }
258}
259
260static void embed_plugin_object(PluginHost *host)
261{
262 IOleObject *ole_obj;
263 RECT rect;
264 HRESULT hres;
265
266 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleObject, (void**)&ole_obj);
267 if(FAILED(hres)) {
268 FIXME("Plugin does not support IOleObject\n");
269 return;
270 }
271
272 get_pos_rect(host, &rect);
273 hres = IOleObject_DoVerb(ole_obj, OLEIVERB_INPLACEACTIVATE, NULL, &host->IOleClientSite_iface, 0, host->hwnd, &rect);
274 IOleObject_Release(ole_obj);
275 if(FAILED(hres))
276 WARN("DoVerb failed: %08x\n", hres);
277
278 if(host->ip_object) {
279 HWND hwnd;
280
281 hres = IOleInPlaceObject_GetWindow(host->ip_object, &hwnd);
282 if(SUCCEEDED(hres))
283 TRACE("hwnd %p\n", hwnd);
284 }
285}
286
287void update_plugin_window(PluginHost *host, HWND hwnd, const RECT *rect)
288{
289 BOOL rect_changed = FALSE;
290
291 if(!hwnd || (host->hwnd && host->hwnd != hwnd)) {
292 FIXME("unhandled hwnd\n");
293 return;
294 }
295
296 TRACE("%p %s\n", hwnd, wine_dbgstr_rect(rect));
297
298 if(memcmp(rect, &host->rect, sizeof(RECT))) {
299 host->rect = *rect;
300 rect_changed = TRUE;
301 }
302
303 if(!host->hwnd) {
304 host->hwnd = hwnd;
305 embed_plugin_object(host);
306 }
307
308 if(rect_changed && host->ip_object)
309 IOleInPlaceObject_SetObjectRects(host->ip_object, &host->rect, &host->rect);
310}
311
312static void notif_enabled(PluginHost *plugin_host)
313{
314 DISPPARAMS args = {NULL, NULL, 0, 0};
315 IDispatch *disp;
316 ULONG err = 0;
317 VARIANT res;
318 HRESULT hres;
319
320 hres = IUnknown_QueryInterface(plugin_host->plugin_unk, &IID_IDispatch, (void**)&disp);
321 if(FAILED(hres)) {
322 FIXME("Could not get IDispatch iface: %08x\n", hres);
323 return;
324 }
325
326 V_VT(&res) = VT_EMPTY;
327 hres = IDispatch_Invoke(disp, DISPID_ENABLED, &IID_NULL, 0/*FIXME*/, DISPATCH_PROPERTYGET, &args, &res, NULL, &err);
328 IDispatch_Release(disp);
329 if(SUCCEEDED(hres)) {
330 FIXME("Got enabled %s\n", debugstr_variant(&res));
331 VariantClear(&res);
332 }
333}
334
335void notif_container_change(HTMLPluginContainer *plugin_container, DISPID dispid)
336{
337 IOleControl *ole_control;
338 HRESULT hres;
339
340 if(!plugin_container->plugin_host || !plugin_container->plugin_host->plugin_unk)
341 return;
342
343 notif_enabled(plugin_container->plugin_host);
344
345 hres = IUnknown_QueryInterface(plugin_container->plugin_host->plugin_unk, &IID_IOleControl, (void**)&ole_control);
346 if(SUCCEEDED(hres)) {
347 IOleControl_OnAmbientPropertyChange(ole_control, dispid);
348 IOleControl_Release(ole_control);
349 }
350}
351
352HRESULT get_plugin_disp(HTMLPluginContainer *plugin_container, IDispatch **ret)
353{
354 PluginHost *host;
355
356 host = plugin_container->plugin_host;
357 if(!host) {
358 ERR("No plugin host\n");
359 return E_UNEXPECTED;
360 }
361
362 if(!host->disp) {
363 *ret = NULL;
364 return S_OK;
365 }
366
367 if(!check_script_safety(host)) {
368 FIXME("Insecure object\n");
369 return E_FAIL;
370 }
371
372 IDispatch_AddRef(host->disp);
373 *ret = host->disp;
374 return S_OK;
375}
376
377HRESULT get_plugin_dispid(HTMLPluginContainer *plugin_container, WCHAR *name, DISPID *ret)
378{
379 IDispatch *disp;
380 DISPID id;
381 DWORD i;
382 HRESULT hres;
383
384 if(!plugin_container->plugin_host) {
385 WARN("no plugin host\n");
386 return DISP_E_UNKNOWNNAME;
387 }
388
389 disp = plugin_container->plugin_host->disp;
390 if(!disp)
391 return DISP_E_UNKNOWNNAME;
392
393 hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, &id);
394 if(FAILED(hres)) {
395 TRACE("no prop %s\n", debugstr_w(name));
396 return DISP_E_UNKNOWNNAME;
397 }
398
399 for(i=0; i < plugin_container->props_len; i++) {
400 if(id == plugin_container->props[i]) {
401 *ret = MSHTML_DISPID_CUSTOM_MIN+i;
402 return S_OK;
403 }
404 }
405
406 if(!plugin_container->props) {
407 plugin_container->props = heap_alloc(8*sizeof(DISPID));
408 if(!plugin_container->props)
409 return E_OUTOFMEMORY;
410 plugin_container->props_size = 8;
411 }else if(plugin_container->props_len == plugin_container->props_size) {
412 DISPID *new_props;
413
414 new_props = heap_realloc(plugin_container->props, plugin_container->props_size*2*sizeof(DISPID));
415 if(!new_props)
416 return E_OUTOFMEMORY;
417
418 plugin_container->props = new_props;
419 plugin_container->props_size *= 2;
420 }
421
422 plugin_container->props[plugin_container->props_len] = id;
423 *ret = MSHTML_DISPID_CUSTOM_MIN+plugin_container->props_len;
424 plugin_container->props_len++;
425 return S_OK;
426}
427
428HRESULT invoke_plugin_prop(HTMLPluginContainer *plugin_container, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
429 VARIANT *res, EXCEPINFO *ei)
430{
431 PluginHost *host;
432
433 host = plugin_container->plugin_host;
434 if(!host || !host->disp) {
435 FIXME("Called with no disp\n");
436 return E_UNEXPECTED;
437 }
438
439 if(!check_script_safety(host)) {
440 FIXME("Insecure object\n");
441 return E_FAIL;
442 }
443
444 if(id < MSHTML_DISPID_CUSTOM_MIN || id > MSHTML_DISPID_CUSTOM_MIN + plugin_container->props_len) {
445 ERR("Invalid id\n");
446 return E_FAIL;
447 }
448
449 return IDispatch_Invoke(host->disp, plugin_container->props[id-MSHTML_DISPID_CUSTOM_MIN], &IID_NULL,
450 lcid, flags, params, res, ei, NULL);
451}
452
453typedef struct {
454 DISPID id;
455 IDispatch *disp;
456} sink_entry_t;
457
458struct PHEventSink {
459 IDispatch IDispatch_iface;
460
461 LONG ref;
462
463 PluginHost *host;
464 ITypeInfo *typeinfo;
465 GUID iid;
466 DWORD cookie;
467 BOOL is_dispiface;
468
469 sink_entry_t *handlers;
470 DWORD handlers_cnt;
471 DWORD handlers_size;
472};
473
474static sink_entry_t *find_sink_entry(PHEventSink *sink, DISPID id)
475{
476 sink_entry_t *iter;
477
478 for(iter = sink->handlers; iter < sink->handlers+sink->handlers_cnt; iter++) {
479 if(iter->id == id)
480 return iter;
481 }
482
483 return NULL;
484}
485
486static void add_sink_handler(PHEventSink *sink, DISPID id, IDispatch *disp)
487{
488 sink_entry_t *entry = find_sink_entry(sink, id);
489
490 if(entry) {
491 if(entry->disp)
492 IDispatch_Release(entry->disp);
493 }else {
494 if(!sink->handlers_size) {
495 sink->handlers = heap_alloc(4*sizeof(*sink->handlers));
496 if(!sink->handlers)
497 return;
498 sink->handlers_size = 4;
499 }else if(sink->handlers_cnt == sink->handlers_size) {
500 sink_entry_t *new_handlers;
501
502 new_handlers = heap_realloc(sink->handlers, 2*sink->handlers_size*sizeof(*sink->handlers));
503 if(!new_handlers)
504 return;
505 sink->handlers = new_handlers;
506 sink->handlers_size *= 2;
507 }
508 entry = sink->handlers + sink->handlers_cnt++;
509 entry->id = id;
510 }
511
512 IDispatch_AddRef(disp);
513 entry->disp = disp;
514}
515
516static inline PHEventSink *PHEventSink_from_IDispatch(IDispatch *iface)
517{
518 return CONTAINING_RECORD(iface, PHEventSink, IDispatch_iface);
519}
520
521static HRESULT WINAPI PHEventSink_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
522{
523 PHEventSink *This = PHEventSink_from_IDispatch(iface);
524
525 if(IsEqualGUID(riid, &IID_IUnknown)) {
526 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
527 *ppv = &This->IDispatch_iface;
528 }else if(IsEqualGUID(riid, &IID_IDispatch)) {
529 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
530 *ppv = &This->IDispatch_iface;
531 }else if(This->is_dispiface && IsEqualGUID(riid, &This->iid)) {
532 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
533 *ppv = &This->IDispatch_iface;
534 }else {
535 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
536 *ppv = NULL;
537 return E_NOINTERFACE;
538 }
539
540 IUnknown_AddRef((IUnknown*)*ppv);
541 return S_OK;
542}
543
544static ULONG WINAPI PHEventSink_AddRef(IDispatch *iface)
545{
546 PHEventSink *This = PHEventSink_from_IDispatch(iface);
547 LONG ref = InterlockedIncrement(&This->ref);
548
549 TRACE("(%p)\n", This);
550
551 return ref;
552}
553
554static ULONG WINAPI PHEventSink_Release(IDispatch *iface)
555{
556 PHEventSink *This = PHEventSink_from_IDispatch(iface);
557 LONG ref = InterlockedDecrement(&This->ref);
558
559 TRACE("(%p)\n", This);
560
561 if(!ref) {
562 unsigned i;
563
564 assert(!This->host);
565
566 for(i=0; i < This->handlers_cnt; i++) {
567 if(This->handlers[i].disp)
568 IDispatch_Release(This->handlers[i].disp);
569 }
570 heap_free(This->handlers);
571 heap_free(This);
572 }
573
574 return ref;
575}
576
577static HRESULT WINAPI PHEventSink_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
578{
579 PHEventSink *This = PHEventSink_from_IDispatch(iface);
580 FIXME("(%p)->(%p)\n", This, pctinfo);
581 return E_NOTIMPL;
582}
583
584static HRESULT WINAPI PHEventSink_GetTypeInfo(IDispatch *iface, UINT iTInfo,
585 LCID lcid, ITypeInfo **ppTInfo)
586{
587 PHEventSink *This = PHEventSink_from_IDispatch(iface);
588 FIXME("(%p)->(%d %d %p)\n", This, iTInfo, lcid, ppTInfo);
589 return E_NOTIMPL;
590}
591
592static HRESULT WINAPI PHEventSink_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *rgszNames,
593 UINT cNames, LCID lcid, DISPID *rgDispId)
594{
595 PHEventSink *This = PHEventSink_from_IDispatch(iface);
596 FIXME("(%p)->(%s %p %u %d %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
597 return E_NOTIMPL;
598}
599
600static HRESULT WINAPI PHEventSink_Invoke(IDispatch *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
601 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
602{
603 PHEventSink *This = PHEventSink_from_IDispatch(iface);
604 IDispatchEx *dispex;
605 sink_entry_t *entry;
606 HRESULT hres;
607
608 TRACE("(%p)->(%d %s %d %x %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), lcid, wFlags,
609 pDispParams, pVarResult, pExcepInfo, puArgErr);
610
611 if(!This->host) {
612 WARN("No host\n");
613 return E_UNEXPECTED;
614 }
615
616 entry = find_sink_entry(This, dispIdMember);
617 if(!entry || !entry->disp) {
618 WARN("No handler %d\n", dispIdMember);
619 if(pVarResult)
620 V_VT(pVarResult) = VT_EMPTY;
621 return S_OK;
622 }
623
624 hres = IDispatch_QueryInterface(entry->disp, &IID_IDispatchEx, (void**)&dispex);
625
626 TRACE("(%p) %d >>>\n", This, entry->id);
627 if(SUCCEEDED(hres)) {
628 hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, NULL);
629 IDispatchEx_Release(dispex);
630 }else {
631 hres = IDispatch_Invoke(entry->disp, DISPID_VALUE, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
632 }
633 if(SUCCEEDED(hres))
634 TRACE("(%p) %d <<<\n", This, entry->id);
635 else
636 WARN("(%p) %d <<< %08x\n", This, entry->id, hres);
637 return hres;
638}
639
640static const IDispatchVtbl PHCPDispatchVtbl = {
641 PHEventSink_QueryInterface,
642 PHEventSink_AddRef,
643 PHEventSink_Release,
644 PHEventSink_GetTypeInfoCount,
645 PHEventSink_GetTypeInfo,
646 PHEventSink_GetIDsOfNames,
647 PHEventSink_Invoke
648};
649
650static PHEventSink *create_event_sink(PluginHost *plugin_host, ITypeInfo *typeinfo)
651{
652 IConnectionPointContainer *cp_container;
653 PHEventSink *ret;
654 IConnectionPoint *cp;
655 TYPEATTR *typeattr;
656 TYPEKIND typekind;
657 GUID guid;
658 HRESULT hres;
659
660 hres = ITypeInfo_GetTypeAttr(typeinfo, &typeattr);
661 if(FAILED(hres))
662 return NULL;
663
664 typekind = typeattr->typekind;
665 guid = typeattr->guid;
666 ITypeInfo_ReleaseTypeAttr(typeinfo, typeattr);
667
668 TRACE("guid %s typekind %d\n", debugstr_guid(&guid), typekind);
669
670 if(typekind != TKIND_INTERFACE && typekind != TKIND_DISPATCH) {
671 WARN("invalid typekind %d\n", typekind);
672 return NULL;
673 }
674
675 hres = IUnknown_QueryInterface(plugin_host->plugin_unk, &IID_IConnectionPointContainer, (void**)&cp_container);
676 if(FAILED(hres)) {
677 WARN("Could not get IConnectionPointContainer iface: %08x\n", hres);
678 return NULL;
679 }
680
681 hres = IConnectionPointContainer_FindConnectionPoint(cp_container, &guid, &cp);
682 IConnectionPointContainer_Release(cp_container);
683 if(FAILED(hres)) {
684 WARN("Could not find %s connection point\n", debugstr_guid(&guid));
685 return NULL;
686 }
687
688 ret = heap_alloc_zero(sizeof(*ret));
689 if(ret) {
690 ret->IDispatch_iface.lpVtbl = &PHCPDispatchVtbl;
691 ret->ref = 1;
692 ret->host = plugin_host;
693 ret->iid = guid;
694 ret->is_dispiface = typekind == TKIND_DISPATCH;
695
696 ITypeInfo_AddRef(typeinfo);
697 ret->typeinfo = typeinfo;
698
699 hres = IConnectionPoint_Advise(cp, (IUnknown*)&ret->IDispatch_iface, &ret->cookie);
700 }else {
701 hres = E_OUTOFMEMORY;
702 }
703
704 IConnectionPoint_Release(cp);
705 if(FAILED(hres)) {
706 WARN("Advise failed: %08x\n", hres);
707 return NULL;
708 }
709
710 return ret;
711}
712
713static ITypeInfo *get_eventiface_info(HTMLPluginContainer *plugin_container, ITypeInfo *class_info)
714{
715 int impl_types, i, impl_flags;
716 ITypeInfo *ret = NULL;
717 TYPEATTR *typeattr;
718 HREFTYPE ref;
719 HRESULT hres;
720
721 hres = ITypeInfo_GetTypeAttr(class_info, &typeattr);
722 if(FAILED(hres))
723 return NULL;
724
725 if(typeattr->typekind != TKIND_COCLASS) {
726 WARN("not coclass\n");
727 ITypeInfo_ReleaseTypeAttr(class_info, typeattr);
728 return NULL;
729 }
730
731 impl_types = typeattr->cImplTypes;
732 ITypeInfo_ReleaseTypeAttr(class_info, typeattr);
733
734 for(i=0; i<impl_types; i++) {
735 hres = ITypeInfo_GetImplTypeFlags(class_info, i, &impl_flags);
736 if(FAILED(hres))
737 continue;
738
739 if((impl_flags & IMPLTYPEFLAG_FSOURCE)) {
740 if(!(impl_flags & IMPLTYPEFLAG_FDEFAULT)) {
741 FIXME("Handle non-default source iface\n");
742 continue;
743 }
744
745 hres = ITypeInfo_GetRefTypeOfImplType(class_info, i, &ref);
746 if(FAILED(hres))
747 continue;
748
749 hres = ITypeInfo_GetRefTypeInfo(class_info, ref, &ret);
750 if(FAILED(hres))
751 ret = NULL;
752 }
753 }
754
755 return ret;
756}
757
758void bind_activex_event(HTMLDocumentNode *doc, HTMLPluginContainer *plugin_container, WCHAR *event, IDispatch *disp)
759{
760 PluginHost *plugin_host = plugin_container->plugin_host;
761 ITypeInfo *class_info, *source_info;
762 DISPID id;
763 HRESULT hres;
764
765 TRACE("(%p %p %s %p)\n", doc, plugin_host, debugstr_w(event), disp);
766
767 if(!plugin_host || !plugin_host->plugin_unk) {
768 WARN("detached element %p\n", plugin_host);
769 return;
770 }
771
772 if(plugin_host->sink) {
773 source_info = plugin_host->sink->typeinfo;
774 ITypeInfo_AddRef(source_info);
775 }else {
776 IProvideClassInfo *provide_ci;
777
778 hres = IUnknown_QueryInterface(plugin_host->plugin_unk, &IID_IProvideClassInfo, (void**)&provide_ci);
779 if(FAILED(hres)) {
780 FIXME("No IProvideClassInfo, try GetTypeInfo?\n");
781 return;
782 }
783
784 hres = IProvideClassInfo_GetClassInfo(provide_ci, &class_info);
785 IProvideClassInfo_Release(provide_ci);
786 if(FAILED(hres) || !class_info) {
787 WARN("GetClassInfo failed: %08x\n", hres);
788 return;
789 }
790
791 source_info = get_eventiface_info(plugin_container, class_info);
792 ITypeInfo_Release(class_info);
793 if(!source_info)
794 return;
795 }
796
797 hres = ITypeInfo_GetIDsOfNames(source_info, &event, 1, &id);
798 if(FAILED(hres))
799 WARN("Could not get disp id: %08x\n", hres);
800 else if(!plugin_host->sink)
801 plugin_host->sink = create_event_sink(plugin_host, source_info);
802
803 ITypeInfo_Release(source_info);
804 if(FAILED(hres) || !plugin_host->sink)
805 return;
806
807 add_sink_handler(plugin_host->sink, id, disp);
808}
809
810static inline PluginHost *impl_from_IOleClientSite(IOleClientSite *iface)
811{
812 return CONTAINING_RECORD(iface, PluginHost, IOleClientSite_iface);
813}
814
815static HRESULT WINAPI PHClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv)
816{
817 PluginHost *This = impl_from_IOleClientSite(iface);
818
819 if(IsEqualGUID(&IID_IUnknown, riid)) {
820 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
821 *ppv = &This->IOleClientSite_iface;
822 }else if(IsEqualGUID(&IID_IOleClientSite, riid)) {
823 TRACE("(%p)->(IID_IOleClientSite %p)\n", This, ppv);
824 *ppv = &This->IOleClientSite_iface;
825 }else if(IsEqualGUID(&IID_IAdviseSink, riid)) {
826 TRACE("(%p)->(IID_IAdviseSink %p)\n", This, ppv);
827 *ppv = &This->IAdviseSinkEx_iface;
828 }else if(IsEqualGUID(&IID_IAdviseSinkEx, riid)) {
829 TRACE("(%p)->(IID_IAdviseSinkEx %p)\n", This, ppv);
830 *ppv = &This->IAdviseSinkEx_iface;
831 }else if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) {
832 TRACE("(%p)->(IID_IPropertyNotifySink %p)\n", This, ppv);
833 *ppv = &This->IPropertyNotifySink_iface;
834 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
835 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
836 *ppv = &This->IDispatch_iface;
837 }else if(IsEqualGUID(&IID_IOleWindow, riid)) {
838 TRACE("(%p)->(IID_IOleWindow %p)\n", This, ppv);
839 *ppv = &This->IOleInPlaceSiteEx_iface;
840 }else if(IsEqualGUID(&IID_IOleInPlaceSite, riid)) {
841 TRACE("(%p)->(IID_IOleInPlaceSite %p)\n", This, ppv);
842 *ppv = &This->IOleInPlaceSiteEx_iface;
843 }else if(IsEqualGUID(&IID_IOleInPlaceSiteEx, riid)) {
844 TRACE("(%p)->(IID_IOleInPlaceSiteEx %p)\n", This, ppv);
845 *ppv = &This->IOleInPlaceSiteEx_iface;
846 }else if(IsEqualGUID(&IID_IOleControlSite, riid)) {
847 TRACE("(%p)->(IID_IOleControlSite %p)\n", This, ppv);
848 *ppv = &This->IOleControlSite_iface;
849 }else if(IsEqualGUID(&IID_IBindHost, riid)) {
850 TRACE("(%p)->(IID_IBindHost %p)\n", This, ppv);
851 *ppv = &This->IBindHost_iface;
852 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
853 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
854 *ppv = &This->IServiceProvider_iface;
855 }else {
856 WARN("Unsupported interface %s\n", debugstr_guid(riid));
857 *ppv = NULL;
858 return E_NOINTERFACE;
859 }
860
861 IUnknown_AddRef((IUnknown*)*ppv);
862 return S_OK;
863}
864
865static ULONG WINAPI PHClientSite_AddRef(IOleClientSite *iface)
866{
867 PluginHost *This = impl_from_IOleClientSite(iface);
868 LONG ref = InterlockedIncrement(&This->ref);
869
870 TRACE("(%p) ref=%d\n", This, ref);
871
872 return ref;
873}
874
875static void release_plugin_ifaces(PluginHost *This)
876{
877 if(This->disp) {
878 IDispatch_Release(This->disp);
879 This->disp = NULL;
880 }
881
882 if(This->ip_object) {
883 IOleInPlaceObject_Release(This->ip_object);
884 This->ip_object = NULL;
885 }
886
887 if(This->plugin_unk) {
888 IUnknown *unk = This->plugin_unk;
889 LONG ref;
890
891 This->plugin_unk = NULL;
892 ref = IUnknown_Release(unk);
893
894 TRACE("plugin ref = %d\n", ref);
895 }
896}
897
898static ULONG WINAPI PHClientSite_Release(IOleClientSite *iface)
899{
900 PluginHost *This = impl_from_IOleClientSite(iface);
901 LONG ref = InterlockedDecrement(&This->ref);
902
903 TRACE("(%p) ref=%d\n", This, ref);
904
905 if(!ref) {
906 release_plugin_ifaces(This);
907 if(This->sink) {
908 This->sink->host = NULL;
909 IDispatch_Release(&This->sink->IDispatch_iface);
910 This->sink = NULL;
911 }
912 list_remove(&This->entry);
913 if(This->element)
914 This->element->plugin_host = NULL;
915 heap_free(This);
916 }
917
918 return ref;
919}
920
921static HRESULT WINAPI PHClientSite_SaveObject(IOleClientSite *iface)
922{
923 PluginHost *This = impl_from_IOleClientSite(iface);
924 FIXME("(%p)\n", This);
925 return E_NOTIMPL;
926}
927
928static HRESULT WINAPI PHClientSite_GetMoniker(IOleClientSite *iface, DWORD dwAssign,
929 DWORD dwWhichMoniker, IMoniker **ppmk)
930{
931 PluginHost *This = impl_from_IOleClientSite(iface);
932
933 TRACE("(%p)->(%d %d %p)\n", This, dwAssign, dwWhichMoniker, ppmk);
934
935 switch(dwWhichMoniker) {
936 case OLEWHICHMK_CONTAINER:
937 if(!This->doc || !This->doc->window || !This->doc->window->mon) {
938 FIXME("no moniker\n");
939 return E_UNEXPECTED;
940 }
941
942 *ppmk = This->doc->window->mon;
943 IMoniker_AddRef(*ppmk);
944 break;
945 default:
946 FIXME("which %d\n", dwWhichMoniker);
947 return E_NOTIMPL;
948 }
949
950 return S_OK;
951}
952
953static HRESULT WINAPI PHClientSite_GetContainer(IOleClientSite *iface, IOleContainer **ppContainer)
954{
955 PluginHost *This = impl_from_IOleClientSite(iface);
956
957 TRACE("(%p)->(%p)\n", This, ppContainer);
958
959 if(!This->doc) {
960 ERR("Called on detached object\n");
961 return E_UNEXPECTED;
962 }
963
964 *ppContainer = &This->doc->basedoc.IOleContainer_iface;
965 IOleContainer_AddRef(*ppContainer);
966 return S_OK;
967}
968
969static HRESULT WINAPI PHClientSite_ShowObject(IOleClientSite *iface)
970{
971 PluginHost *This = impl_from_IOleClientSite(iface);
972
973 TRACE("(%p)\n", This);
974
975 return S_OK;
976}
977
978static HRESULT WINAPI PHClientSite_OnShowWindow(IOleClientSite *iface, BOOL fShow)
979{
980 PluginHost *This = impl_from_IOleClientSite(iface);
981 FIXME("(%p)->(%x)\n", This, fShow);
982 return E_NOTIMPL;
983}
984
985static HRESULT WINAPI PHClientSite_RequestNewObjectLayout(IOleClientSite *iface)
986{
987 PluginHost *This = impl_from_IOleClientSite(iface);
988 FIXME("(%p)\n", This);
989 return E_NOTIMPL;
990}
991
992static const IOleClientSiteVtbl OleClientSiteVtbl = {
993 PHClientSite_QueryInterface,
994 PHClientSite_AddRef,
995 PHClientSite_Release,
996 PHClientSite_SaveObject,
997 PHClientSite_GetMoniker,
998 PHClientSite_GetContainer,
999 PHClientSite_ShowObject,
1000 PHClientSite_OnShowWindow,
1001 PHClientSite_RequestNewObjectLayout
1002};
1003
1004static inline PluginHost *impl_from_IAdviseSinkEx(IAdviseSinkEx *iface)
1005{
1006 return CONTAINING_RECORD(iface, PluginHost, IAdviseSinkEx_iface);
1007}
1008
1009static HRESULT WINAPI PHAdviseSinkEx_QueryInterface(IAdviseSinkEx *iface, REFIID riid, void **ppv)
1010{
1011 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1012 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1013}
1014
1015static ULONG WINAPI PHAdviseSinkEx_AddRef(IAdviseSinkEx *iface)
1016{
1017 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1018 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1019}
1020
1021static ULONG WINAPI PHAdviseSinkEx_Release(IAdviseSinkEx *iface)
1022{
1023 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1024 return IOleClientSite_Release(&This->IOleClientSite_iface);
1025}
1026
1027static void WINAPI PHAdviseSinkEx_OnDataChange(IAdviseSinkEx *iface, FORMATETC *pFormatetc, STGMEDIUM *pStgMedium)
1028{
1029 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1030 FIXME("(%p)->(%p %p)\n", This, pFormatetc, pStgMedium);
1031}
1032
1033static void WINAPI PHAdviseSinkEx_OnViewChange(IAdviseSinkEx *iface, DWORD dwAspect, LONG lindex)
1034{
1035 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1036 FIXME("(%p)->(%d %d)\n", This, dwAspect, lindex);
1037}
1038
1039static void WINAPI PHAdviseSinkEx_OnRename(IAdviseSinkEx *iface, IMoniker *pmk)
1040{
1041 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1042 FIXME("(%p)->(%p)\n", This, pmk);
1043}
1044
1045static void WINAPI PHAdviseSinkEx_OnSave(IAdviseSinkEx *iface)
1046{
1047 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1048 FIXME("(%p)\n", This);
1049}
1050
1051static void WINAPI PHAdviseSinkEx_OnClose(IAdviseSinkEx *iface)
1052{
1053 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1054 FIXME("(%p)\n", This);
1055}
1056
1057static void WINAPI PHAdviseSinkEx_OnViewStatusChange(IAdviseSinkEx *iface, DWORD dwViewStatus)
1058{
1059 PluginHost *This = impl_from_IAdviseSinkEx(iface);
1060 FIXME("(%p)->(%d)\n", This, dwViewStatus);
1061}
1062
1063static const IAdviseSinkExVtbl AdviseSinkExVtbl = {
1064 PHAdviseSinkEx_QueryInterface,
1065 PHAdviseSinkEx_AddRef,
1066 PHAdviseSinkEx_Release,
1067 PHAdviseSinkEx_OnDataChange,
1068 PHAdviseSinkEx_OnViewChange,
1069 PHAdviseSinkEx_OnRename,
1070 PHAdviseSinkEx_OnSave,
1071 PHAdviseSinkEx_OnClose,
1072 PHAdviseSinkEx_OnViewStatusChange
1073};
1074
1075static inline PluginHost *impl_from_IPropertyNotifySink(IPropertyNotifySink *iface)
1076{
1077 return CONTAINING_RECORD(iface, PluginHost, IPropertyNotifySink_iface);
1078}
1079
1080static HRESULT WINAPI PHPropertyNotifySink_QueryInterface(IPropertyNotifySink *iface, REFIID riid, void **ppv)
1081{
1082 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1083 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1084}
1085
1086static ULONG WINAPI PHPropertyNotifySink_AddRef(IPropertyNotifySink *iface)
1087{
1088 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1089 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1090}
1091
1092static ULONG WINAPI PHPropertyNotifySink_Release(IPropertyNotifySink *iface)
1093{
1094 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1095 return IOleClientSite_Release(&This->IOleClientSite_iface);
1096}
1097
1098static HRESULT WINAPI PHPropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID)
1099{
1100 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1101
1102 TRACE("(%p)->(%d)\n", This, dispID);
1103
1104 switch(dispID) {
1105 case DISPID_READYSTATE:
1106 update_readystate(This);
1107 break;
1108 default :
1109 FIXME("Unimplemented dispID %d\n", dispID);
1110 return E_NOTIMPL;
1111 }
1112
1113 return S_OK;
1114}
1115
1116static HRESULT WINAPI PHPropertyNotifySink_OnRequestEdit(IPropertyNotifySink *iface, DISPID dispID)
1117{
1118 PluginHost *This = impl_from_IPropertyNotifySink(iface);
1119 FIXME("(%p)->(%d)\n", This, dispID);
1120 return E_NOTIMPL;
1121}
1122
1123static const IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = {
1124 PHPropertyNotifySink_QueryInterface,
1125 PHPropertyNotifySink_AddRef,
1126 PHPropertyNotifySink_Release,
1127 PHPropertyNotifySink_OnChanged,
1128 PHPropertyNotifySink_OnRequestEdit
1129};
1130
1131static inline PluginHost *impl_from_IDispatch(IDispatch *iface)
1132{
1133 return CONTAINING_RECORD(iface, PluginHost, IDispatch_iface);
1134}
1135
1136static HRESULT WINAPI PHDispatch_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
1137{
1138 PluginHost *This = impl_from_IDispatch(iface);
1139 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1140}
1141
1142static ULONG WINAPI PHDispatch_AddRef(IDispatch *iface)
1143{
1144 PluginHost *This = impl_from_IDispatch(iface);
1145 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1146}
1147
1148static ULONG WINAPI PHDispatch_Release(IDispatch *iface)
1149{
1150 PluginHost *This = impl_from_IDispatch(iface);
1151 return IOleClientSite_Release(&This->IOleClientSite_iface);
1152}
1153
1154static HRESULT WINAPI PHDispatch_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
1155{
1156 PluginHost *This = impl_from_IDispatch(iface);
1157 FIXME("(%p)->(%p)\n", This, pctinfo);
1158 return E_NOTIMPL;
1159}
1160
1161static HRESULT WINAPI PHDispatch_GetTypeInfo(IDispatch *iface, UINT iTInfo,
1162 LCID lcid, ITypeInfo **ppTInfo)
1163{
1164 PluginHost *This = impl_from_IDispatch(iface);
1165 FIXME("(%p)->(%d %d %p)\n", This, iTInfo, lcid, ppTInfo);
1166 return E_NOTIMPL;
1167}
1168
1169static HRESULT WINAPI PHDispatch_GetIDsOfNames(IDispatch *iface, REFIID riid,
1170 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1171{
1172 PluginHost *This = impl_from_IDispatch(iface);
1173 FIXME("(%p)->(%s %p %d %d %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1174 return E_NOTIMPL;
1175}
1176
1177static HRESULT WINAPI PHDispatch_Invoke(IDispatch *iface, DISPID dispid, REFIID riid, LCID lcid,
1178 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1179{
1180 PluginHost *This = impl_from_IDispatch(iface);
1181 FIXME("(%p)->(%d %x %p %p)\n", This, dispid, wFlags, pDispParams, pVarResult);
1182 return E_NOTIMPL;
1183}
1184
1185static const IDispatchVtbl DispatchVtbl = {
1186 PHDispatch_QueryInterface,
1187 PHDispatch_AddRef,
1188 PHDispatch_Release,
1189 PHDispatch_GetTypeInfoCount,
1190 PHDispatch_GetTypeInfo,
1191 PHDispatch_GetIDsOfNames,
1192 PHDispatch_Invoke
1193};
1194
1195static inline PluginHost *impl_from_IOleInPlaceSiteEx(IOleInPlaceSiteEx *iface)
1196{
1197 return CONTAINING_RECORD(iface, PluginHost, IOleInPlaceSiteEx_iface);
1198}
1199
1200static HRESULT WINAPI PHInPlaceSite_QueryInterface(IOleInPlaceSiteEx *iface, REFIID riid, void **ppv)
1201{
1202 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1203 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1204}
1205
1206static ULONG WINAPI PHInPlaceSite_AddRef(IOleInPlaceSiteEx *iface)
1207{
1208 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1209 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1210}
1211
1212static ULONG WINAPI PHInPlaceSite_Release(IOleInPlaceSiteEx *iface)
1213{
1214 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1215 return IOleClientSite_Release(&This->IOleClientSite_iface);
1216}
1217
1218static HRESULT WINAPI PHInPlaceSite_GetWindow(IOleInPlaceSiteEx *iface, HWND *phwnd)
1219{
1220 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1221
1222 TRACE("(%p)->(%p)\n", This, phwnd);
1223
1224 *phwnd = This->hwnd;
1225 return S_OK;
1226}
1227
1228static HRESULT WINAPI PHInPlaceSite_ContextSensitiveHelp(IOleInPlaceSiteEx *iface, BOOL fEnterMode)
1229{
1230 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1231 FIXME("(%p)->(%x)\n", This, fEnterMode);
1232 return E_NOTIMPL;
1233}
1234
1235static HRESULT WINAPI PHInPlaceSite_CanInPlaceActivate(IOleInPlaceSiteEx *iface)
1236{
1237 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1238
1239 TRACE("(%p)\n", This);
1240
1241 return S_OK;
1242}
1243
1244static HRESULT WINAPI PHInPlaceSite_OnInPlaceActivate(IOleInPlaceSiteEx *iface)
1245{
1246 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1247 FIXME("(%p)\n", This);
1248 return E_NOTIMPL;
1249}
1250
1251static HRESULT WINAPI PHInPlaceSite_OnUIActivate(IOleInPlaceSiteEx *iface)
1252{
1253 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1254
1255 TRACE("(%p)\n", This);
1256
1257 if(!This->plugin_unk) {
1258 ERR("No plugin object\n");
1259 return E_UNEXPECTED;
1260 }
1261
1262 This->ui_active = TRUE;
1263
1264 notif_enabled(This);
1265 return S_OK;
1266}
1267
1268static HRESULT WINAPI PHInPlaceSite_GetWindowContext(IOleInPlaceSiteEx *iface,
1269 IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, RECT *lprcPosRect,
1270 RECT *lprcClipRect, OLEINPLACEFRAMEINFO *frame_info)
1271{
1272 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1273 IOleInPlaceUIWindow *ip_window;
1274 IOleInPlaceFrame *ip_frame;
1275 RECT pr, cr;
1276 HRESULT hres;
1277
1278 TRACE("(%p)->(%p %p %p %p %p)\n", This, ppFrame, ppDoc, lprcPosRect, lprcClipRect, frame_info);
1279
1280 if(!This->doc || !This->doc->basedoc.doc_obj || !This->doc->basedoc.doc_obj->ipsite) {
1281 FIXME("No ipsite\n");
1282 return E_UNEXPECTED;
1283 }
1284
1285 hres = IOleInPlaceSite_GetWindowContext(This->doc->basedoc.doc_obj->ipsite, &ip_frame, &ip_window, &pr, &cr, frame_info);
1286 if(FAILED(hres)) {
1287 WARN("GetWindowContext failed: %08x\n", hres);
1288 return hres;
1289 }
1290
1291 if(ip_window)
1292 IOleInPlaceUIWindow_Release(ip_window);
1293 if(ip_frame)
1294 IOleInPlaceFrame_Release(ip_frame);
1295
1296 hres = create_ip_frame(&ip_frame);
1297 if(FAILED(hres))
1298 return hres;
1299
1300 hres = create_ip_window(ppDoc);
1301 if(FAILED(hres)) {
1302 IOleInPlaceFrame_Release(ip_frame);
1303 return hres;
1304 }
1305
1306 *ppFrame = ip_frame;
1307 *lprcPosRect = This->rect;
1308 *lprcClipRect = This->rect;
1309 return S_OK;
1310}
1311
1312static HRESULT WINAPI PHInPlaceSite_Scroll(IOleInPlaceSiteEx *iface, SIZE scrollExtent)
1313{
1314 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1315 FIXME("(%p)->({%d %d})\n", This, scrollExtent.cx, scrollExtent.cy);
1316 return E_NOTIMPL;
1317}
1318
1319static HRESULT WINAPI PHInPlaceSite_OnUIDeactivate(IOleInPlaceSiteEx *iface, BOOL fUndoable)
1320{
1321 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1322 FIXME("(%p)->(%x)\n", This, fUndoable);
1323 return E_NOTIMPL;
1324}
1325
1326static HRESULT WINAPI PHInPlaceSite_OnInPlaceDeactivate(IOleInPlaceSiteEx *iface)
1327{
1328 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1329
1330 TRACE("(%p)\n", This);
1331
1332 if(This->ip_object) {
1333 IOleInPlaceObject_Release(This->ip_object);
1334 This->ip_object = NULL;
1335 }
1336
1337 return S_OK;
1338}
1339
1340static HRESULT WINAPI PHInPlaceSite_DiscardUndoState(IOleInPlaceSiteEx *iface)
1341{
1342 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1343 FIXME("(%p)\n", This);
1344 return E_NOTIMPL;
1345}
1346
1347static HRESULT WINAPI PHInPlaceSite_DeactivateAndUndo(IOleInPlaceSiteEx *iface)
1348{
1349 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1350 FIXME("(%p)\n", This);
1351 return E_NOTIMPL;
1352}
1353
1354static HRESULT WINAPI PHInPlaceSite_OnPosRectChange(IOleInPlaceSiteEx *iface, LPCRECT lprcPosRect)
1355{
1356 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1357 FIXME("(%p)->(%p)\n", This, lprcPosRect);
1358 return E_NOTIMPL;
1359}
1360
1361static HRESULT WINAPI PHInPlaceSiteEx_OnInPlaceActivateEx(IOleInPlaceSiteEx *iface, BOOL *pfNoRedraw, DWORD dwFlags)
1362{
1363 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1364 HWND hwnd;
1365 HRESULT hres;
1366
1367 TRACE("(%p)->(%p %x)\n", This, pfNoRedraw, dwFlags);
1368
1369 if(This->ip_object)
1370 return S_OK;
1371
1372 hres = IUnknown_QueryInterface(This->plugin_unk, &IID_IOleInPlaceObject, (void**)&This->ip_object);
1373 if(FAILED(hres))
1374 return hres;
1375
1376 hres = IOleInPlaceObject_GetWindow(This->ip_object, &hwnd);
1377 if(SUCCEEDED(hres))
1378 FIXME("Use hwnd %p\n", hwnd);
1379
1380 *pfNoRedraw = FALSE;
1381 return S_OK;
1382}
1383
1384static HRESULT WINAPI PHInPlaceSiteEx_OnInPlaceDeactivateEx(IOleInPlaceSiteEx *iface, BOOL fNoRedraw)
1385{
1386 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1387 FIXME("(%p)->(%x)\n", This, fNoRedraw);
1388 return E_NOTIMPL;
1389}
1390
1391static HRESULT WINAPI PHInPlaceSiteEx_RequestUIActivate(IOleInPlaceSiteEx *iface)
1392{
1393 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface);
1394 FIXME("(%p)\n", This);
1395 return E_NOTIMPL;
1396}
1397
1398static const IOleInPlaceSiteExVtbl OleInPlaceSiteExVtbl = {
1399 PHInPlaceSite_QueryInterface,
1400 PHInPlaceSite_AddRef,
1401 PHInPlaceSite_Release,
1402 PHInPlaceSite_GetWindow,
1403 PHInPlaceSite_ContextSensitiveHelp,
1404 PHInPlaceSite_CanInPlaceActivate,
1405 PHInPlaceSite_OnInPlaceActivate,
1406 PHInPlaceSite_OnUIActivate,
1407 PHInPlaceSite_GetWindowContext,
1408 PHInPlaceSite_Scroll,
1409 PHInPlaceSite_OnUIDeactivate,
1410 PHInPlaceSite_OnInPlaceDeactivate,
1411 PHInPlaceSite_DiscardUndoState,
1412 PHInPlaceSite_DeactivateAndUndo,
1413 PHInPlaceSite_OnPosRectChange,
1414 PHInPlaceSiteEx_OnInPlaceActivateEx,
1415 PHInPlaceSiteEx_OnInPlaceDeactivateEx,
1416 PHInPlaceSiteEx_RequestUIActivate
1417};
1418
1419static inline PluginHost *impl_from_IOleControlSite(IOleControlSite *iface)
1420{
1421 return CONTAINING_RECORD(iface, PluginHost, IOleControlSite_iface);
1422}
1423
1424static HRESULT WINAPI PHControlSite_QueryInterface(IOleControlSite *iface, REFIID riid, void **ppv)
1425{
1426 PluginHost *This = impl_from_IOleControlSite(iface);
1427 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1428}
1429
1430static ULONG WINAPI PHControlSite_AddRef(IOleControlSite *iface)
1431{
1432 PluginHost *This = impl_from_IOleControlSite(iface);
1433 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1434}
1435
1436static ULONG WINAPI PHControlSite_Release(IOleControlSite *iface)
1437{
1438 PluginHost *This = impl_from_IOleControlSite(iface);
1439 return IOleClientSite_Release(&This->IOleClientSite_iface);
1440}
1441
1442static HRESULT WINAPI PHControlSite_OnControlInfoChanged(IOleControlSite *iface)
1443{
1444 PluginHost *This = impl_from_IOleControlSite(iface);
1445 FIXME("(%p)\n", This);
1446 return E_NOTIMPL;
1447}
1448
1449static HRESULT WINAPI PHControlSite_LockInPlaceActive(IOleControlSite *iface, BOOL fLock)
1450{
1451 PluginHost *This = impl_from_IOleControlSite(iface);
1452 FIXME("(%p)->(%x)\n", This, fLock);
1453 return E_NOTIMPL;
1454}
1455
1456static HRESULT WINAPI PHControlSite_GetExtendedControl(IOleControlSite *iface, IDispatch **ppDisp)
1457{
1458 PluginHost *This = impl_from_IOleControlSite(iface);
1459 FIXME("(%p)->(%p)\n", This, ppDisp);
1460 return E_NOTIMPL;
1461}
1462
1463static HRESULT WINAPI PHControlSite_TransformCoords(IOleControlSite *iface, POINTL *pPtlHimetric, POINTF *pPtfContainer, DWORD dwFlags)
1464{
1465 PluginHost *This = impl_from_IOleControlSite(iface);
1466 FIXME("(%p)->(%p %p %x)\n", This, pPtlHimetric, pPtfContainer, dwFlags);
1467 return E_NOTIMPL;
1468}
1469
1470static HRESULT WINAPI PHControlSite_TranslateAccelerator(IOleControlSite *iface, MSG *pMsg, DWORD grfModifiers)
1471{
1472 PluginHost *This = impl_from_IOleControlSite(iface);
1473 FIXME("(%p)->(%x)\n", This, grfModifiers);
1474 return E_NOTIMPL;
1475}
1476
1477static HRESULT WINAPI PHControlSite_OnFocus(IOleControlSite *iface, BOOL fGotFocus)
1478{
1479 PluginHost *This = impl_from_IOleControlSite(iface);
1480 FIXME("(%p)->(%x)\n", This, fGotFocus);
1481 return E_NOTIMPL;
1482}
1483
1484static HRESULT WINAPI PHControlSite_ShowPropertyFrame(IOleControlSite *iface)
1485{
1486 PluginHost *This = impl_from_IOleControlSite(iface);
1487 FIXME("(%p)\n", This);
1488 return E_NOTIMPL;
1489}
1490
1491static const IOleControlSiteVtbl OleControlSiteVtbl = {
1492 PHControlSite_QueryInterface,
1493 PHControlSite_AddRef,
1494 PHControlSite_Release,
1495 PHControlSite_OnControlInfoChanged,
1496 PHControlSite_LockInPlaceActive,
1497 PHControlSite_GetExtendedControl,
1498 PHControlSite_TransformCoords,
1499 PHControlSite_TranslateAccelerator,
1500 PHControlSite_OnFocus,
1501 PHControlSite_ShowPropertyFrame
1502};
1503
1504static inline PluginHost *impl_from_IBindHost(IBindHost *iface)
1505{
1506 return CONTAINING_RECORD(iface, PluginHost, IBindHost_iface);
1507}
1508
1509static HRESULT WINAPI PHBindHost_QueryInterface(IBindHost *iface, REFIID riid, void **ppv)
1510{
1511 PluginHost *This = impl_from_IBindHost(iface);
1512 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1513}
1514
1515static ULONG WINAPI PHBindHost_AddRef(IBindHost *iface)
1516{
1517 PluginHost *This = impl_from_IBindHost(iface);
1518 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1519}
1520
1521static ULONG WINAPI PHBindHost_Release(IBindHost *iface)
1522{
1523 PluginHost *This = impl_from_IBindHost(iface);
1524 return IOleClientSite_Release(&This->IOleClientSite_iface);
1525}
1526
1527static HRESULT WINAPI PHBindHost_CreateMoniker(IBindHost *iface, LPOLESTR szName, IBindCtx *pBC, IMoniker **ppmk, DWORD dwReserved)
1528{
1529 PluginHost *This = impl_from_IBindHost(iface);
1530
1531 TRACE("(%p)->(%s %p %p %x)\n", This, debugstr_w(szName), pBC, ppmk, dwReserved);
1532
1533 if(!This->doc || !This->doc->window || !This->doc->window->mon) {
1534 FIXME("no moniker\n");
1535 return E_UNEXPECTED;
1536 }
1537
1538 return CreateURLMoniker(This->doc->window->mon, szName, ppmk);
1539}
1540
1541static HRESULT WINAPI PHBindHost_MonikerBindToStorage(IBindHost *iface, IMoniker *pMk, IBindCtx *pBC,
1542 IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
1543{
1544 PluginHost *This = impl_from_IBindHost(iface);
1545 FIXME("(%p)->(%p %p %p %s %p)\n", This, pMk, pBC, pBSC, debugstr_guid(riid), ppvObj);
1546 return E_NOTIMPL;
1547}
1548
1549static HRESULT WINAPI PHBindHost_MonikerBindToObject(IBindHost *iface, IMoniker *pMk, IBindCtx *pBC,
1550 IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
1551{
1552 PluginHost *This = impl_from_IBindHost(iface);
1553 FIXME("(%p)->(%p %p %p %s %p)\n", This, pMk, pBC, pBSC, debugstr_guid(riid), ppvObj);
1554 return E_NOTIMPL;
1555}
1556
1557static const IBindHostVtbl BindHostVtbl = {
1558 PHBindHost_QueryInterface,
1559 PHBindHost_AddRef,
1560 PHBindHost_Release,
1561 PHBindHost_CreateMoniker,
1562 PHBindHost_MonikerBindToStorage,
1563 PHBindHost_MonikerBindToObject
1564};
1565
1566static inline PluginHost *impl_from_IServiceProvider(IServiceProvider *iface)
1567{
1568 return CONTAINING_RECORD(iface, PluginHost, IServiceProvider_iface);
1569}
1570
1571static HRESULT WINAPI PHServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
1572{
1573 PluginHost *This = impl_from_IServiceProvider(iface);
1574 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1575}
1576
1577static ULONG WINAPI PHServiceProvider_AddRef(IServiceProvider *iface)
1578{
1579 PluginHost *This = impl_from_IServiceProvider(iface);
1580 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1581}
1582
1583static ULONG WINAPI PHServiceProvider_Release(IServiceProvider *iface)
1584{
1585 PluginHost *This = impl_from_IServiceProvider(iface);
1586 return IOleClientSite_Release(&This->IOleClientSite_iface);
1587}
1588
1589static HRESULT WINAPI PHServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService, REFIID riid, void **ppv)
1590{
1591 PluginHost *This = impl_from_IServiceProvider(iface);
1592
1593 if(IsEqualGUID(guidService, &SID_SBindHost)) {
1594 TRACE("SID_SBindHost service\n");
1595 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
1596 }
1597
1598 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
1599
1600 if(!This->doc || !This->doc->basedoc.window) {
1601 *ppv = NULL;
1602 return E_NOINTERFACE;
1603 }
1604
1605 return IServiceProvider_QueryService(&This->doc->basedoc.window->base.IServiceProvider_iface,
1606 guidService, riid, ppv);
1607}
1608
1609static const IServiceProviderVtbl ServiceProviderVtbl = {
1610 PHServiceProvider_QueryInterface,
1611 PHServiceProvider_AddRef,
1612 PHServiceProvider_Release,
1613 PHServiceProvider_QueryService
1614};
1615
1616static BOOL parse_classid(const PRUnichar *classid, CLSID *clsid)
1617{
1618 const WCHAR *ptr;
1619 unsigned len;
1620 HRESULT hres;
1621
1622 static const PRUnichar clsidW[] = {'c','l','s','i','d',':'};
1623
1624 if(strncmpiW(classid, clsidW, sizeof(clsidW)/sizeof(WCHAR)))
1625 return FALSE;
1626
1627 ptr = classid + sizeof(clsidW)/sizeof(WCHAR);
1628 len = strlenW(ptr);
1629
1630 if(len == 38) {
1631 hres = CLSIDFromString(ptr, clsid);
1632 }else if(len == 36) {
1633 WCHAR buf[39];
1634
1635 buf[0] = '{';
1636 memcpy(buf+1, ptr, len*sizeof(WCHAR));
1637 buf[37] = '}';
1638 buf[38] = 0;
1639 hres = CLSIDFromString(buf, clsid);
1640 }else {
1641 return FALSE;
1642 }
1643
1644 return SUCCEEDED(hres);
1645}
1646
1647static BOOL get_elem_clsid(nsIDOMHTMLElement *elem, CLSID *clsid)
1648{
1649 const PRUnichar *val;
1650 nsAString val_str;
1651 nsresult nsres;
1652 BOOL ret = FALSE;
1653
1654 static const PRUnichar classidW[] = {'c','l','a','s','s','i','d',0};
1655
1656 nsres = get_elem_attr_value(elem, classidW, &val_str, &val);
1657 if(NS_SUCCEEDED(nsres)) {
1658 if(*val)
1659 ret = parse_classid(val, clsid);
1660 nsAString_Finish(&val_str);
1661 }
1662
1663 return ret;
1664}
1665
1666typedef struct {
1667 IBindStatusCallback IBindStatusCallback_iface;
1668 IWindowForBindingUI IWindowForBindingUI_iface;
1669 LONG ref;
1670} InstallCallback;
1671
1672static inline InstallCallback *impl_from_IBindStatusCallback(IBindStatusCallback *iface)
1673{
1674 return CONTAINING_RECORD(iface, InstallCallback, IBindStatusCallback_iface);
1675}
1676
1677static HRESULT WINAPI InstallCallback_QueryInterface(IBindStatusCallback *iface,
1678 REFIID riid, void **ppv)
1679{
1680 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1681
1682 if(IsEqualGUID(&IID_IUnknown, riid)) {
1683 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1684 *ppv = &This->IBindStatusCallback_iface;
1685 }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
1686 TRACE("(%p)->(IID_IBindStatusCallback %p)\n", This, ppv);
1687 *ppv = &This->IBindStatusCallback_iface;
1688 }else if(IsEqualGUID(&IID_IWindowForBindingUI, riid)) {
1689 TRACE("(%p)->(IID_IWindowForBindingUI %p)\n", This, ppv);
1690 *ppv = &This->IWindowForBindingUI_iface;
1691 }else {
1692 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1693 *ppv = NULL;
1694 return E_NOINTERFACE;
1695 }
1696
1697 IUnknown_AddRef((IUnknown*)*ppv);
1698 return S_OK;
1699}
1700
1701static ULONG WINAPI InstallCallback_AddRef(IBindStatusCallback *iface)
1702{
1703 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1704 LONG ref = InterlockedIncrement(&This->ref);
1705
1706 TRACE("(%p) ref=%d\n", This, ref);
1707
1708 return ref;
1709}
1710
1711static ULONG WINAPI InstallCallback_Release(IBindStatusCallback *iface)
1712{
1713 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1714 LONG ref = InterlockedIncrement(&This->ref);
1715
1716 TRACE("(%p) ref=%d\n", This, ref);
1717
1718 if(!ref)
1719 heap_free(This);
1720
1721 return ref;
1722}
1723
1724static HRESULT WINAPI InstallCallback_OnStartBinding(IBindStatusCallback *iface,
1725 DWORD dwReserved, IBinding *pib)
1726{
1727 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1728 TRACE("(%p)->(%x %p)\n", This, dwReserved, pib);
1729 return S_OK;
1730}
1731
1732static HRESULT WINAPI InstallCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
1733{
1734 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1735 TRACE("(%p)->(%p)\n", This, pnPriority);
1736 return E_NOTIMPL;
1737}
1738
1739static HRESULT WINAPI InstallCallback_OnLowResource(IBindStatusCallback *iface, DWORD dwReserved)
1740{
1741 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1742 TRACE("(%p)->(%x)\n", This, dwReserved);
1743 return S_OK;
1744}
1745
1746static HRESULT WINAPI InstallCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
1747 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
1748{
1749 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1750 TRACE("(%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode, debugstr_w(szStatusText));
1751 return S_OK;
1752}
1753
1754static HRESULT WINAPI InstallCallback_OnStopBinding(IBindStatusCallback *iface,
1755 HRESULT hresult, LPCWSTR szError)
1756{
1757 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1758 TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
1759 return S_OK;
1760}
1761
1762static HRESULT WINAPI InstallCallback_GetBindInfo(IBindStatusCallback *iface,
1763 DWORD* grfBINDF, BINDINFO* pbindinfo)
1764{
1765 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1766
1767 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
1768
1769 *grfBINDF = BINDF_ASYNCHRONOUS;
1770 return S_OK;
1771}
1772
1773static HRESULT WINAPI InstallCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
1774 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
1775{
1776 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1777 ERR("(%p)\n", This);
1778 return E_NOTIMPL;
1779}
1780
1781static HRESULT WINAPI InstallCallback_OnObjectAvailable(IBindStatusCallback *iface,
1782 REFIID riid, IUnknown* punk)
1783{
1784 InstallCallback *This = impl_from_IBindStatusCallback(iface);
1785 ERR("(%p)\n", This);
1786 return E_NOTIMPL;
1787}
1788
1789static IBindStatusCallbackVtbl InstallCallbackVtbl = {
1790 InstallCallback_QueryInterface,
1791 InstallCallback_AddRef,
1792 InstallCallback_Release,
1793 InstallCallback_OnStartBinding,
1794 InstallCallback_GetPriority,
1795 InstallCallback_OnLowResource,
1796 InstallCallback_OnProgress,
1797 InstallCallback_OnStopBinding,
1798 InstallCallback_GetBindInfo,
1799 InstallCallback_OnDataAvailable,
1800 InstallCallback_OnObjectAvailable
1801};
1802
1803static inline InstallCallback *impl_from_IWindowForBindingUI(IWindowForBindingUI *iface)
1804{
1805 return CONTAINING_RECORD(iface, InstallCallback, IWindowForBindingUI_iface);
1806}
1807
1808static HRESULT WINAPI WindowForBindingUI_QueryInterface(IWindowForBindingUI *iface, REFIID riid, void **ppv)
1809{
1810 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
1811 return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
1812}
1813
1814static ULONG WINAPI WindowForBindingUI_AddRef(IWindowForBindingUI *iface)
1815{
1816 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
1817 return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
1818}
1819
1820static ULONG WINAPI WindowForBindingUI_Release(IWindowForBindingUI *iface)
1821{
1822 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
1823 return IBindStatusCallback_Release(&This->IBindStatusCallback_iface);
1824}
1825
1826static HRESULT WINAPI WindowForBindingUI_GetWindow(IWindowForBindingUI *iface, REFGUID rguidReason, HWND *phwnd)
1827{
1828 InstallCallback *This = impl_from_IWindowForBindingUI(iface);
1829 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(rguidReason), phwnd);
1830 *phwnd = NULL;
1831 return S_OK;
1832}
1833
1834static const IWindowForBindingUIVtbl WindowForBindingUIVtbl = {
1835 WindowForBindingUI_QueryInterface,
1836 WindowForBindingUI_AddRef,
1837 WindowForBindingUI_Release,
1838 WindowForBindingUI_GetWindow
1839};
1840
1841typedef struct {
1842 struct list entry;
1843 IUri *uri;
1844} install_entry_t;
1845
1846static struct list install_list = LIST_INIT(install_list);
1847
1848static CRITICAL_SECTION cs_install_list;
1849static CRITICAL_SECTION_DEBUG cs_install_list_dbg =
1850{
1851 0, 0, &cs_install_list,
1852 { &cs_install_list_dbg.ProcessLocksList, &cs_install_list_dbg.ProcessLocksList },
1853 0, 0, { (DWORD_PTR)(__FILE__ ": install_list") }
1854};
1855static CRITICAL_SECTION cs_install_list = { &cs_install_list_dbg, -1, 0, 0, 0, 0 };
1856
1857static void install_codebase(const WCHAR *url)
1858{
1859 InstallCallback *callback;
1860 IBindCtx *bctx;
1861 HRESULT hres;
1862
1863 callback = heap_alloc(sizeof(*callback));
1864 if(!callback)
1865 return;
1866
1867 callback->IBindStatusCallback_iface.lpVtbl = &InstallCallbackVtbl;
1868 callback->IWindowForBindingUI_iface.lpVtbl = &WindowForBindingUIVtbl;
1869 callback->ref = 1;
1870
1871 hres = CreateAsyncBindCtx(0, &callback->IBindStatusCallback_iface, NULL, &bctx);
1872 IBindStatusCallback_Release(&callback->IBindStatusCallback_iface);
1873 if(FAILED(hres))
1874 return;
1875
1876 hres = AsyncInstallDistributionUnit(NULL, NULL, NULL, 0, 0, url, bctx, NULL, 0);
1877 IBindCtx_Release(bctx);
1878 if(FAILED(hres))
1879 WARN("FAILED: %08x\n", hres);
1880}
1881
1882static void check_codebase(HTMLInnerWindow *window, nsIDOMHTMLElement *nselem)
1883{
1884 BOOL is_on_list = FALSE;
1885 install_entry_t *iter;
1886 const PRUnichar *val;
1887 nsAString val_str;
1888 IUri *uri = NULL;
1889 nsresult nsres;
1890 HRESULT hres;
1891
1892 static const PRUnichar codebaseW[] = {'c','o','d','e','b','a','s','e',0};
1893
1894 nsres = get_elem_attr_value(nselem, codebaseW, &val_str, &val);
1895 if(NS_SUCCEEDED(nsres)) {
1896 if(*val) {
1897 hres = CoInternetCombineUrlEx(window->base.outer_window->uri, val, 0, &uri, 0);
1898 if(FAILED(hres))
1899 uri = NULL;
1900 }
1901 nsAString_Finish(&val_str);
1902 }
1903
1904 if(!uri)
1905 return;
1906
1907 EnterCriticalSection(&cs_install_list);
1908
1909 LIST_FOR_EACH_ENTRY(iter, &install_list, install_entry_t, entry) {
1910 BOOL eq;
1911
1912 hres = IUri_IsEqual(uri, iter->uri, &eq);
1913 if(SUCCEEDED(hres) && eq) {
1914 TRACE("already proceeded\n");
1915 is_on_list = TRUE;
1916 break;
1917 }
1918 }
1919
1920 if(!is_on_list) {
1921 iter = heap_alloc(sizeof(*iter));
1922 if(iter) {
1923 IUri_AddRef(uri);
1924 iter->uri = uri;
1925
1926 list_add_tail(&install_list, &iter->entry);
1927 }
1928 }
1929
1930 LeaveCriticalSection(&cs_install_list);
1931
1932 if(!is_on_list) {
1933 BSTR display_uri;
1934
1935 hres = IUri_GetDisplayUri(uri, &display_uri);
1936 if(SUCCEEDED(hres)) {
1937 install_codebase(display_uri);
1938 SysFreeString(display_uri);
1939 }
1940 }
1941
1942 IUri_Release(uri);
1943}
1944
1945static IUnknown *create_activex_object(HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, CLSID *clsid)
1946{
1947 IClassFactoryEx *cfex;
1948 IClassFactory *cf;
1949 IUnknown *obj;
1950 DWORD policy;
1951 HRESULT hres;
1952
1953 if(!get_elem_clsid(nselem, clsid)) {
1954 WARN("Could not determine element CLSID\n");
1955 return NULL;
1956 }
1957
1958 TRACE("clsid %s\n", debugstr_guid(clsid));
1959
1960 policy = 0;
1961 hres = IInternetHostSecurityManager_ProcessUrlAction(&doc->IInternetHostSecurityManager_iface,
1962 URLACTION_ACTIVEX_RUN, (BYTE*)&policy, sizeof(policy), (BYTE*)clsid, sizeof(GUID), 0, 0);
1963 if(FAILED(hres) || policy != URLPOLICY_ALLOW) {
1964 WARN("ProcessUrlAction returned %08x %x\n", hres, policy);
1965 return NULL;
1966 }
1967
1968 hres = CoGetClassObject(clsid, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, NULL, &IID_IClassFactory, (void**)&cf);
1969 if(hres == REGDB_E_CLASSNOTREG)
1970 check_codebase(doc->window, nselem);
1971 if(FAILED(hres))
1972 return NULL;
1973
1974 hres = IClassFactory_QueryInterface(cf, &IID_IClassFactoryEx, (void**)&cfex);
1975 if(SUCCEEDED(hres)) {
1976 FIXME("Use IClassFactoryEx\n");
1977 IClassFactoryEx_Release(cfex);
1978 }
1979
1980 hres = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)&obj);
1981 IClassFactory_Release(cf);
1982 if(FAILED(hres))
1983 return NULL;
1984
1985 return obj;
1986}
1987
1988void detach_plugin_host(PluginHost *host)
1989{
1990 HRESULT hres;
1991
1992 TRACE("%p\n", host);
1993
1994 if(!host->doc)
1995 return;
1996
1997 if(host->ip_object) {
1998 if(host->ui_active)
1999 IOleInPlaceObject_UIDeactivate(host->ip_object);
2000 IOleInPlaceObject_InPlaceDeactivate(host->ip_object);
2001 }
2002
2003 if(host->plugin_unk) {
2004 IOleObject *ole_obj;
2005
2006 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IOleObject, (void**)&ole_obj);
2007 if(SUCCEEDED(hres)) {
2008 if(!host->ip_object)
2009 IOleObject_Close(ole_obj, OLECLOSE_NOSAVE);
2010 IOleObject_SetClientSite(ole_obj, NULL);
2011 IOleObject_Release(ole_obj);
2012 }
2013 }
2014
2015 if(host->sink) {
2016 IConnectionPointContainer *cp_container;
2017 IConnectionPoint *cp;
2018
2019 assert(host->plugin_unk != NULL);
2020
2021 hres = IUnknown_QueryInterface(host->plugin_unk, &IID_IConnectionPointContainer, (void**)&cp_container);
2022 if(SUCCEEDED(hres)) {
2023 hres = IConnectionPointContainer_FindConnectionPoint(cp_container, &host->sink->iid, &cp);
2024 IConnectionPointContainer_Release(cp_container);
2025 if(SUCCEEDED(hres)) {
2026 IConnectionPoint_Unadvise(cp, host->sink->cookie);
2027 IConnectionPoint_Release(cp);
2028 }
2029 }
2030
2031 host->sink->host = NULL;
2032 IDispatch_Release(&host->sink->IDispatch_iface);
2033 host->sink = NULL;
2034 }
2035
2036 release_plugin_ifaces(host);
2037
2038 if(host->element) {
2039 host->element->plugin_host = NULL;
2040 host->element = NULL;
2041 }
2042
2043 list_remove(&host->entry);
2044 list_init(&host->entry);
2045 host->doc = NULL;
2046}
2047
2048HRESULT create_plugin_host(HTMLDocumentNode *doc, HTMLPluginContainer *container)
2049{
2050 PluginHost *host;
2051 IUnknown *unk;
2052 CLSID clsid;
2053
2054 assert(!container->plugin_host);
2055
2056 unk = create_activex_object(doc, container->element.nselem, &clsid);
2057 if(!unk)
2058 return E_FAIL;
2059
2060 host = heap_alloc_zero(sizeof(*host));
2061 if(!host) {
2062 IUnknown_Release(unk);
2063 return E_OUTOFMEMORY;
2064 }
2065
2066 host->IOleClientSite_iface.lpVtbl = &OleClientSiteVtbl;
2067 host->IAdviseSinkEx_iface.lpVtbl = &AdviseSinkExVtbl;
2068 host->IPropertyNotifySink_iface.lpVtbl = &PropertyNotifySinkVtbl;
2069 host->IDispatch_iface.lpVtbl = &DispatchVtbl;
2070 host->IOleInPlaceSiteEx_iface.lpVtbl = &OleInPlaceSiteExVtbl;
2071 host->IOleControlSite_iface.lpVtbl = &OleControlSiteVtbl;
2072 host->IBindHost_iface.lpVtbl = &BindHostVtbl;
2073 host->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
2074
2075 host->ref = 1;
2076
2077 host->plugin_unk = unk;
2078 host->clsid = clsid;
2079
2080 host->doc = doc;
2081 list_add_tail(&doc->plugin_hosts, &host->entry);
2082
2083 container->plugin_host = host;
2084 host->element = container;
2085
2086 initialize_plugin_object(host);
2087
2088 return S_OK;
2089}