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 21 static 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 42 static 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 77 static 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 */ 106 static 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 114 static 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 140 static 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 163 static 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 260 static 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 287 void 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 312 static 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 335 void 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 352 HRESULT 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 377 HRESULT 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 428 HRESULT 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 453 typedef struct { 454 DISPID id; 455 IDispatch *disp; 456 } sink_entry_t; 457 458 struct 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 474 static 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 486 static 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 516 static inline PHEventSink *PHEventSink_from_IDispatch(IDispatch *iface) 517 { 518 return CONTAINING_RECORD(iface, PHEventSink, IDispatch_iface); 519 } 520 521 static 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 544 static 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 554 static 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 577 static 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 584 static 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 592 static 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 600 static 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 640 static 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 650 static 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 713 static 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 758 void 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 810 static inline PluginHost *impl_from_IOleClientSite(IOleClientSite *iface) 811 { 812 return CONTAINING_RECORD(iface, PluginHost, IOleClientSite_iface); 813 } 814 815 static 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 865 static 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 875 static 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 898 static 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 921 static 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 928 static 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 953 static 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 969 static 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 978 static 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 985 static 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 992 static 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 1004 static inline PluginHost *impl_from_IAdviseSinkEx(IAdviseSinkEx *iface) 1005 { 1006 return CONTAINING_RECORD(iface, PluginHost, IAdviseSinkEx_iface); 1007 } 1008 1009 static 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 1015 static ULONG WINAPI PHAdviseSinkEx_AddRef(IAdviseSinkEx *iface) 1016 { 1017 PluginHost *This = impl_from_IAdviseSinkEx(iface); 1018 return IOleClientSite_AddRef(&This->IOleClientSite_iface); 1019 } 1020 1021 static ULONG WINAPI PHAdviseSinkEx_Release(IAdviseSinkEx *iface) 1022 { 1023 PluginHost *This = impl_from_IAdviseSinkEx(iface); 1024 return IOleClientSite_Release(&This->IOleClientSite_iface); 1025 } 1026 1027 static 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 1033 static 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 1039 static 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 1045 static void WINAPI PHAdviseSinkEx_OnSave(IAdviseSinkEx *iface) 1046 { 1047 PluginHost *This = impl_from_IAdviseSinkEx(iface); 1048 FIXME("(%p)\n", This); 1049 } 1050 1051 static void WINAPI PHAdviseSinkEx_OnClose(IAdviseSinkEx *iface) 1052 { 1053 PluginHost *This = impl_from_IAdviseSinkEx(iface); 1054 FIXME("(%p)\n", This); 1055 } 1056 1057 static 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 1063 static 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 1075 static inline PluginHost *impl_from_IPropertyNotifySink(IPropertyNotifySink *iface) 1076 { 1077 return CONTAINING_RECORD(iface, PluginHost, IPropertyNotifySink_iface); 1078 } 1079 1080 static 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 1086 static ULONG WINAPI PHPropertyNotifySink_AddRef(IPropertyNotifySink *iface) 1087 { 1088 PluginHost *This = impl_from_IPropertyNotifySink(iface); 1089 return IOleClientSite_AddRef(&This->IOleClientSite_iface); 1090 } 1091 1092 static ULONG WINAPI PHPropertyNotifySink_Release(IPropertyNotifySink *iface) 1093 { 1094 PluginHost *This = impl_from_IPropertyNotifySink(iface); 1095 return IOleClientSite_Release(&This->IOleClientSite_iface); 1096 } 1097 1098 static 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 1116 static 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 1123 static const IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = { 1124 PHPropertyNotifySink_QueryInterface, 1125 PHPropertyNotifySink_AddRef, 1126 PHPropertyNotifySink_Release, 1127 PHPropertyNotifySink_OnChanged, 1128 PHPropertyNotifySink_OnRequestEdit 1129 }; 1130 1131 static inline PluginHost *impl_from_IDispatch(IDispatch *iface) 1132 { 1133 return CONTAINING_RECORD(iface, PluginHost, IDispatch_iface); 1134 } 1135 1136 static 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 1142 static ULONG WINAPI PHDispatch_AddRef(IDispatch *iface) 1143 { 1144 PluginHost *This = impl_from_IDispatch(iface); 1145 return IOleClientSite_AddRef(&This->IOleClientSite_iface); 1146 } 1147 1148 static ULONG WINAPI PHDispatch_Release(IDispatch *iface) 1149 { 1150 PluginHost *This = impl_from_IDispatch(iface); 1151 return IOleClientSite_Release(&This->IOleClientSite_iface); 1152 } 1153 1154 static 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 1161 static 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 1169 static 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 1177 static 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 1185 static 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 1195 static inline PluginHost *impl_from_IOleInPlaceSiteEx(IOleInPlaceSiteEx *iface) 1196 { 1197 return CONTAINING_RECORD(iface, PluginHost, IOleInPlaceSiteEx_iface); 1198 } 1199 1200 static 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 1206 static ULONG WINAPI PHInPlaceSite_AddRef(IOleInPlaceSiteEx *iface) 1207 { 1208 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface); 1209 return IOleClientSite_AddRef(&This->IOleClientSite_iface); 1210 } 1211 1212 static ULONG WINAPI PHInPlaceSite_Release(IOleInPlaceSiteEx *iface) 1213 { 1214 PluginHost *This = impl_from_IOleInPlaceSiteEx(iface); 1215 return IOleClientSite_Release(&This->IOleClientSite_iface); 1216 } 1217 1218 static 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 1228 static 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 1235 static 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 1244 static 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 1251 static 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 1268 static 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 1312 static 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 1319 static 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 1326 static 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 1340 static 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 1347 static 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 1354 static 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 1361 static 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 1384 static 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 1391 static 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 1398 static 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 1419 static inline PluginHost *impl_from_IOleControlSite(IOleControlSite *iface) 1420 { 1421 return CONTAINING_RECORD(iface, PluginHost, IOleControlSite_iface); 1422 } 1423 1424 static 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 1430 static ULONG WINAPI PHControlSite_AddRef(IOleControlSite *iface) 1431 { 1432 PluginHost *This = impl_from_IOleControlSite(iface); 1433 return IOleClientSite_AddRef(&This->IOleClientSite_iface); 1434 } 1435 1436 static ULONG WINAPI PHControlSite_Release(IOleControlSite *iface) 1437 { 1438 PluginHost *This = impl_from_IOleControlSite(iface); 1439 return IOleClientSite_Release(&This->IOleClientSite_iface); 1440 } 1441 1442 static 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 1449 static 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 1456 static 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 1463 static 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 1470 static 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 1477 static 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 1484 static 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 1491 static 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 1504 static inline PluginHost *impl_from_IBindHost(IBindHost *iface) 1505 { 1506 return CONTAINING_RECORD(iface, PluginHost, IBindHost_iface); 1507 } 1508 1509 static 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 1515 static ULONG WINAPI PHBindHost_AddRef(IBindHost *iface) 1516 { 1517 PluginHost *This = impl_from_IBindHost(iface); 1518 return IOleClientSite_AddRef(&This->IOleClientSite_iface); 1519 } 1520 1521 static ULONG WINAPI PHBindHost_Release(IBindHost *iface) 1522 { 1523 PluginHost *This = impl_from_IBindHost(iface); 1524 return IOleClientSite_Release(&This->IOleClientSite_iface); 1525 } 1526 1527 static 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 1541 static 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 1549 static 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 1557 static const IBindHostVtbl BindHostVtbl = { 1558 PHBindHost_QueryInterface, 1559 PHBindHost_AddRef, 1560 PHBindHost_Release, 1561 PHBindHost_CreateMoniker, 1562 PHBindHost_MonikerBindToStorage, 1563 PHBindHost_MonikerBindToObject 1564 }; 1565 1566 static inline PluginHost *impl_from_IServiceProvider(IServiceProvider *iface) 1567 { 1568 return CONTAINING_RECORD(iface, PluginHost, IServiceProvider_iface); 1569 } 1570 1571 static 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 1577 static ULONG WINAPI PHServiceProvider_AddRef(IServiceProvider *iface) 1578 { 1579 PluginHost *This = impl_from_IServiceProvider(iface); 1580 return IOleClientSite_AddRef(&This->IOleClientSite_iface); 1581 } 1582 1583 static ULONG WINAPI PHServiceProvider_Release(IServiceProvider *iface) 1584 { 1585 PluginHost *This = impl_from_IServiceProvider(iface); 1586 return IOleClientSite_Release(&This->IOleClientSite_iface); 1587 } 1588 1589 static 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 1609 static const IServiceProviderVtbl ServiceProviderVtbl = { 1610 PHServiceProvider_QueryInterface, 1611 PHServiceProvider_AddRef, 1612 PHServiceProvider_Release, 1613 PHServiceProvider_QueryService 1614 }; 1615 1616 static 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 1647 static 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 1666 typedef struct { 1667 IBindStatusCallback IBindStatusCallback_iface; 1668 IWindowForBindingUI IWindowForBindingUI_iface; 1669 LONG ref; 1670 } InstallCallback; 1671 1672 static inline InstallCallback *impl_from_IBindStatusCallback(IBindStatusCallback *iface) 1673 { 1674 return CONTAINING_RECORD(iface, InstallCallback, IBindStatusCallback_iface); 1675 } 1676 1677 static 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 1701 static 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 1711 static 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 1724 static 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 1732 static 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 1739 static 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 1746 static 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 1754 static 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 1762 static 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 1773 static 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 1781 static 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 1789 static 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 1803 static inline InstallCallback *impl_from_IWindowForBindingUI(IWindowForBindingUI *iface) 1804 { 1805 return CONTAINING_RECORD(iface, InstallCallback, IWindowForBindingUI_iface); 1806 } 1807 1808 static 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 1814 static ULONG WINAPI WindowForBindingUI_AddRef(IWindowForBindingUI *iface) 1815 { 1816 InstallCallback *This = impl_from_IWindowForBindingUI(iface); 1817 return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface); 1818 } 1819 1820 static ULONG WINAPI WindowForBindingUI_Release(IWindowForBindingUI *iface) 1821 { 1822 InstallCallback *This = impl_from_IWindowForBindingUI(iface); 1823 return IBindStatusCallback_Release(&This->IBindStatusCallback_iface); 1824 } 1825 1826 static 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 1834 static const IWindowForBindingUIVtbl WindowForBindingUIVtbl = { 1835 WindowForBindingUI_QueryInterface, 1836 WindowForBindingUI_AddRef, 1837 WindowForBindingUI_Release, 1838 WindowForBindingUI_GetWindow 1839 }; 1840 1841 typedef struct { 1842 struct list entry; 1843 IUri *uri; 1844 } install_entry_t; 1845 1846 static struct list install_list = LIST_INIT(install_list); 1847 1848 static CRITICAL_SECTION cs_install_list; 1849 static 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 }; 1855 static CRITICAL_SECTION cs_install_list = { &cs_install_list_dbg, -1, 0, 0, 0, 0 }; 1856 1857 static 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 1882 static 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 1945 static 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 1988 void 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 2048 HRESULT 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 } 2090