1 /* 2 * Implementation of IOleObject interfaces for WebBrowser control 3 * 4 * - IOleObject 5 * - IOleInPlaceObject 6 * - IOleControl 7 * 8 * Copyright 2001 John R. Sheets (for CodeWeavers) 9 * Copyright 2005 Jacek Caban 10 * 11 * This library is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU Lesser General Public 13 * License as published by the Free Software Foundation; either 14 * version 2.1 of the License, or (at your option) any later version. 15 * 16 * This library is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * Lesser General Public License for more details. 20 * 21 * You should have received a copy of the GNU Lesser General Public 22 * License along with this library; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 24 */ 25 26 #include <string.h> 27 28 #include "ieframe.h" 29 30 #include "htiframe.h" 31 #include "idispids.h" 32 #include "mshtmdid.h" 33 34 #include "wine/debug.h" 35 36 WINE_DEFAULT_DEBUG_CHANNEL(ieframe); 37 38 /* shlwapi.dll */ 39 HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent); 40 41 static ATOM shell_embedding_atom = 0; 42 43 static LRESULT resize_window(WebBrowser *This, LONG width, LONG height) 44 { 45 if(This->doc_host.hwnd) 46 SetWindowPos(This->doc_host.hwnd, NULL, 0, 0, width, height, 47 SWP_NOZORDER | SWP_NOACTIVATE); 48 49 return 0; 50 } 51 52 static void notify_on_focus(WebBrowser *This, BOOL got_focus) 53 { 54 IOleControlSite *control_site; 55 HRESULT hres; 56 57 if(!This->client) 58 return; 59 60 hres = IOleClientSite_QueryInterface(This->client, &IID_IOleControlSite, (void**)&control_site); 61 if(FAILED(hres)) 62 return; 63 64 IOleControlSite_OnFocus(control_site, got_focus); 65 IOleControlSite_Release(control_site); 66 } 67 68 static LRESULT WINAPI shell_embedding_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 69 { 70 WebBrowser *This; 71 72 static const WCHAR wszTHIS[] = {'T','H','I','S',0}; 73 74 if(msg == WM_CREATE) { 75 This = *(WebBrowser**)lParam; 76 SetPropW(hwnd, wszTHIS, This); 77 }else { 78 This = GetPropW(hwnd, wszTHIS); 79 } 80 81 switch(msg) { 82 case WM_SIZE: 83 return resize_window(This, LOWORD(lParam), HIWORD(lParam)); 84 case WM_DOCHOSTTASK: 85 return process_dochost_tasks(&This->doc_host); 86 case WM_SETFOCUS: 87 notify_on_focus(This, TRUE); 88 break; 89 case WM_KILLFOCUS: 90 notify_on_focus(This, FALSE); 91 break; 92 } 93 94 return DefWindowProcW(hwnd, msg, wParam, lParam); 95 } 96 97 static void create_shell_embedding_hwnd(WebBrowser *This) 98 { 99 IOleInPlaceSite *inplace; 100 HWND parent = NULL; 101 HRESULT hres; 102 103 static const WCHAR wszShellEmbedding[] = 104 {'S','h','e','l','l',' ','E','m','b','e','d','d','i','n','g',0}; 105 106 if(!shell_embedding_atom) { 107 static WNDCLASSEXW wndclass = { 108 sizeof(wndclass), 109 CS_DBLCLKS, 110 shell_embedding_proc, 111 0, 0 /* native uses 8 */, NULL, NULL, NULL, 112 (HBRUSH)(COLOR_WINDOW + 1), NULL, 113 wszShellEmbedding, 114 NULL 115 }; 116 wndclass.hInstance = ieframe_instance; 117 118 RegisterClassExW(&wndclass); 119 } 120 121 hres = IOleClientSite_QueryInterface(This->client, &IID_IOleInPlaceSite, (void**)&inplace); 122 if(SUCCEEDED(hres)) { 123 IOleInPlaceSite_GetWindow(inplace, &parent); 124 IOleInPlaceSite_Release(inplace); 125 } 126 127 This->doc_host.frame_hwnd = This->shell_embedding_hwnd = CreateWindowExW( 128 WS_EX_WINDOWEDGE, 129 wszShellEmbedding, wszShellEmbedding, 130 WS_CLIPSIBLINGS | WS_CLIPCHILDREN 131 | (parent ? WS_CHILD | WS_TABSTOP : WS_POPUP | WS_MAXIMIZEBOX), 132 0, 0, 0, 0, parent, 133 NULL, ieframe_instance, This); 134 135 TRACE("parent=%p hwnd=%p\n", parent, This->shell_embedding_hwnd); 136 } 137 138 static HRESULT activate_inplace(WebBrowser *This, IOleClientSite *active_site) 139 { 140 HWND parent_hwnd; 141 HRESULT hres; 142 143 if(This->inplace) 144 return S_OK; 145 146 if(!active_site) 147 return E_INVALIDARG; 148 149 hres = IOleClientSite_QueryInterface(active_site, &IID_IOleInPlaceSite, 150 (void**)&This->inplace); 151 if(FAILED(hres)) { 152 WARN("Could not get IOleInPlaceSite\n"); 153 return hres; 154 } 155 156 hres = IOleInPlaceSiteEx_CanInPlaceActivate(This->inplace); 157 if(hres != S_OK) { 158 WARN("CanInPlaceActivate returned: %08x\n", hres); 159 IOleInPlaceSiteEx_Release(This->inplace); 160 This->inplace = NULL; 161 return E_FAIL; 162 } 163 164 hres = IOleInPlaceSiteEx_GetWindow(This->inplace, &parent_hwnd); 165 if(SUCCEEDED(hres)) 166 SHSetParentHwnd(This->shell_embedding_hwnd, parent_hwnd); 167 168 IOleInPlaceSiteEx_OnInPlaceActivate(This->inplace); 169 170 This->frameinfo.cb = sizeof(OLEINPLACEFRAMEINFO); 171 IOleInPlaceSiteEx_GetWindowContext(This->inplace, &This->doc_host.frame, &This->uiwindow, 172 &This->pos_rect, &This->clip_rect, 173 &This->frameinfo); 174 175 SetWindowPos(This->shell_embedding_hwnd, NULL, 176 This->pos_rect.left, This->pos_rect.top, 177 This->pos_rect.right-This->pos_rect.left, 178 This->pos_rect.bottom-This->pos_rect.top, 179 SWP_NOZORDER | SWP_SHOWWINDOW); 180 181 if(This->client) { 182 IOleContainer *container; 183 184 IOleClientSite_ShowObject(This->client); 185 186 hres = IOleClientSite_GetContainer(This->client, &container); 187 if(SUCCEEDED(hres)) { 188 if(This->container) 189 IOleContainer_Release(This->container); 190 This->container = container; 191 } 192 } 193 194 if(This->doc_host.frame) 195 IOleInPlaceFrame_GetWindow(This->doc_host.frame, &This->frame_hwnd); 196 197 return S_OK; 198 } 199 200 static HRESULT activate_ui(WebBrowser *This, IOleClientSite *active_site) 201 { 202 HRESULT hres; 203 204 static const WCHAR wszitem[] = {'i','t','e','m',0}; 205 206 if(This->inplace) 207 { 208 if(This->shell_embedding_hwnd) 209 ShowWindow(This->shell_embedding_hwnd, SW_SHOW); 210 return S_OK; 211 } 212 213 hres = activate_inplace(This, active_site); 214 if(FAILED(hres)) 215 return hres; 216 217 IOleInPlaceSiteEx_OnUIActivate(This->inplace); 218 219 if(This->doc_host.frame) 220 IOleInPlaceFrame_SetActiveObject(This->doc_host.frame, &This->IOleInPlaceActiveObject_iface, wszitem); 221 if(This->uiwindow) 222 IOleInPlaceUIWindow_SetActiveObject(This->uiwindow, &This->IOleInPlaceActiveObject_iface, wszitem); 223 224 if(This->doc_host.frame) 225 IOleInPlaceFrame_SetMenu(This->doc_host.frame, NULL, NULL, This->shell_embedding_hwnd); 226 227 SetFocus(This->shell_embedding_hwnd); 228 notify_on_focus(This, TRUE); 229 230 return S_OK; 231 } 232 233 static HRESULT get_client_disp_property(IOleClientSite *client, DISPID dispid, VARIANT *res) 234 { 235 IDispatch *disp = NULL; 236 DISPPARAMS dispparams = {NULL, 0}; 237 HRESULT hres; 238 239 VariantInit(res); 240 241 if(!client) 242 return S_OK; 243 244 hres = IOleClientSite_QueryInterface(client, &IID_IDispatch, (void**)&disp); 245 if(FAILED(hres)) { 246 TRACE("Could not get IDispatch\n"); 247 return hres; 248 } 249 250 hres = IDispatch_Invoke(disp, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT, 251 DISPATCH_PROPERTYGET, &dispparams, res, NULL, NULL); 252 253 IDispatch_Release(disp); 254 255 return hres; 256 } 257 258 static HRESULT on_offlineconnected_change(WebBrowser *This) 259 { 260 VARIANT offline; 261 262 get_client_disp_property(This->client, DISPID_AMBIENT_OFFLINEIFNOTCONNECTED, &offline); 263 264 if(V_VT(&offline) == VT_BOOL) 265 IWebBrowser2_put_Offline(&This->IWebBrowser2_iface, V_BOOL(&offline)); 266 else if(V_VT(&offline) != VT_EMPTY) 267 WARN("wrong V_VT(silent) %d\n", V_VT(&offline)); 268 269 return S_OK; 270 } 271 272 static HRESULT on_silent_change(WebBrowser *This) 273 { 274 VARIANT silent; 275 276 get_client_disp_property(This->client, DISPID_AMBIENT_SILENT, &silent); 277 278 if(V_VT(&silent) == VT_BOOL) 279 IWebBrowser2_put_Silent(&This->IWebBrowser2_iface, V_BOOL(&silent)); 280 else if(V_VT(&silent) != VT_EMPTY) 281 WARN("wrong V_VT(silent) %d\n", V_VT(&silent)); 282 283 return S_OK; 284 } 285 286 static void release_client_site(WebBrowser *This, BOOL destroy_win) 287 { 288 release_dochost_client(&This->doc_host); 289 290 if(This->client) { 291 IOleClientSite_Release(This->client); 292 This->client = NULL; 293 } 294 295 if(This->client_closed) { 296 IOleClientSite_Release(This->client_closed); 297 This->client_closed = NULL; 298 } 299 300 if(destroy_win && This->shell_embedding_hwnd) { 301 DestroyWindow(This->shell_embedding_hwnd); 302 This->shell_embedding_hwnd = NULL; 303 } 304 305 if(This->inplace) { 306 IOleInPlaceSiteEx_Release(This->inplace); 307 This->inplace = NULL; 308 } 309 310 if(This->container) { 311 IOleContainer_Release(This->container); 312 This->container = NULL; 313 } 314 315 if(This->uiwindow) { 316 IOleInPlaceUIWindow_Release(This->uiwindow); 317 This->uiwindow = NULL; 318 } 319 } 320 321 typedef struct { 322 IEnumOLEVERB IEnumOLEVERB_iface; 323 LONG ref; 324 LONG iter; 325 } EnumOLEVERB; 326 327 static inline EnumOLEVERB *impl_from_IEnumOLEVERB(IEnumOLEVERB *iface) 328 { 329 return CONTAINING_RECORD(iface, EnumOLEVERB, IEnumOLEVERB_iface); 330 } 331 332 static HRESULT WINAPI EnumOLEVERB_QueryInterface(IEnumOLEVERB *iface, REFIID riid, void **ppv) 333 { 334 EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface); 335 336 if(IsEqualGUID(&IID_IUnknown, riid)) { 337 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 338 *ppv = &This->IEnumOLEVERB_iface; 339 }else if(IsEqualGUID(&IID_IEnumOLEVERB, riid)) { 340 TRACE("(%p)->(IID_IEnumOLEVERB %p)\n", This, ppv); 341 *ppv = &This->IEnumOLEVERB_iface; 342 }else { 343 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); 344 *ppv = NULL; 345 return E_NOINTERFACE; 346 } 347 348 IUnknown_AddRef((IUnknown*)*ppv); 349 return S_OK; 350 } 351 352 static ULONG WINAPI EnumOLEVERB_AddRef(IEnumOLEVERB *iface) 353 { 354 EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface); 355 LONG ref = InterlockedIncrement(&This->ref); 356 357 TRACE("(%p) ref=%d\n", This, ref); 358 359 return ref; 360 } 361 362 static ULONG WINAPI EnumOLEVERB_Release(IEnumOLEVERB *iface) 363 { 364 EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface); 365 LONG ref = InterlockedDecrement(&This->ref); 366 367 TRACE("(%p) ref=%d\n", This, ref); 368 369 if(!ref) 370 heap_free(This); 371 372 return ref; 373 } 374 375 static HRESULT WINAPI EnumOLEVERB_Next(IEnumOLEVERB *iface, ULONG celt, OLEVERB *rgelt, ULONG *pceltFetched) 376 { 377 EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface); 378 379 static const OLEVERB verbs[] = 380 {{OLEIVERB_PRIMARY},{OLEIVERB_INPLACEACTIVATE},{OLEIVERB_UIACTIVATE},{OLEIVERB_SHOW},{OLEIVERB_HIDE}}; 381 382 TRACE("(%p)->(%u %p %p)\n", This, celt, rgelt, pceltFetched); 383 384 /* There are a few problems with this implementation, but that's how it seems to work in native. See tests. */ 385 if(pceltFetched) 386 *pceltFetched = 0; 387 388 if(This->iter == ARRAY_SIZE(verbs)) 389 return S_FALSE; 390 391 if(celt) 392 *rgelt = verbs[This->iter++]; 393 return S_OK; 394 } 395 396 static HRESULT WINAPI EnumOLEVERB_Skip(IEnumOLEVERB *iface, ULONG celt) 397 { 398 EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface); 399 TRACE("(%p)->(%u)\n", This, celt); 400 return S_OK; 401 } 402 403 static HRESULT WINAPI EnumOLEVERB_Reset(IEnumOLEVERB *iface) 404 { 405 EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface); 406 407 TRACE("(%p)\n", This); 408 409 This->iter = 0; 410 return S_OK; 411 } 412 413 static HRESULT WINAPI EnumOLEVERB_Clone(IEnumOLEVERB *iface, IEnumOLEVERB **ppenum) 414 { 415 EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface); 416 FIXME("(%p)->(%p)\n", This, ppenum); 417 return E_NOTIMPL; 418 } 419 420 static const IEnumOLEVERBVtbl EnumOLEVERBVtbl = { 421 EnumOLEVERB_QueryInterface, 422 EnumOLEVERB_AddRef, 423 EnumOLEVERB_Release, 424 EnumOLEVERB_Next, 425 EnumOLEVERB_Skip, 426 EnumOLEVERB_Reset, 427 EnumOLEVERB_Clone 428 }; 429 430 /********************************************************************** 431 * Implement the IOleObject interface for the WebBrowser control 432 */ 433 434 static inline WebBrowser *impl_from_IOleObject(IOleObject *iface) 435 { 436 return CONTAINING_RECORD(iface, WebBrowser, IOleObject_iface); 437 } 438 439 static HRESULT WINAPI OleObject_QueryInterface(IOleObject *iface, REFIID riid, void **ppv) 440 { 441 WebBrowser *This = impl_from_IOleObject(iface); 442 return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppv); 443 } 444 445 static ULONG WINAPI OleObject_AddRef(IOleObject *iface) 446 { 447 WebBrowser *This = impl_from_IOleObject(iface); 448 return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); 449 } 450 451 static ULONG WINAPI OleObject_Release(IOleObject *iface) 452 { 453 WebBrowser *This = impl_from_IOleObject(iface); 454 return IWebBrowser2_Release(&This->IWebBrowser2_iface); 455 } 456 457 static HRESULT WINAPI OleObject_SetClientSite(IOleObject *iface, LPOLECLIENTSITE pClientSite) 458 { 459 WebBrowser *This = impl_from_IOleObject(iface); 460 IDocHostUIHandler *hostui; 461 IOleCommandTarget *olecmd; 462 BOOL get_olecmd = TRUE; 463 IOleContainer *container; 464 IDispatch *disp; 465 HRESULT hres; 466 467 TRACE("(%p)->(%p)\n", This, pClientSite); 468 469 if(This->client_closed) { 470 IOleClientSite_Release(This->client_closed); 471 This->client_closed = NULL; 472 } 473 474 if(This->client == pClientSite) 475 return S_OK; 476 477 if(This->client && pClientSite) { 478 get_olecmd = FALSE; 479 olecmd = This->doc_host.olecmd; 480 if(olecmd) 481 IOleCommandTarget_AddRef(olecmd); 482 } 483 484 release_client_site(This, !pClientSite); 485 486 if(!pClientSite) { 487 on_commandstate_change(&This->doc_host, CSC_NAVIGATEBACK, FALSE); 488 on_commandstate_change(&This->doc_host, CSC_NAVIGATEFORWARD, FALSE); 489 490 if(This->doc_host.document) 491 deactivate_document(&This->doc_host); 492 return S_OK; 493 } 494 495 IOleClientSite_AddRef(pClientSite); 496 This->client = pClientSite; 497 498 hres = IOleClientSite_QueryInterface(This->client, &IID_IDispatch, 499 (void**)&disp); 500 if(SUCCEEDED(hres)) 501 This->doc_host.client_disp = disp; 502 503 hres = IOleClientSite_QueryInterface(This->client, &IID_IDocHostUIHandler, 504 (void**)&hostui); 505 if(SUCCEEDED(hres)) 506 This->doc_host.hostui = hostui; 507 508 if(get_olecmd) { 509 hres = IOleClientSite_GetContainer(This->client, &container); 510 if(SUCCEEDED(hres)) { 511 ITargetContainer *target_container; 512 513 hres = IOleContainer_QueryInterface(container, &IID_ITargetContainer, 514 (void**)&target_container); 515 if(SUCCEEDED(hres)) { 516 FIXME("Unsupported ITargetContainer\n"); 517 ITargetContainer_Release(target_container); 518 } 519 520 hres = IOleContainer_QueryInterface(container, &IID_IOleCommandTarget, (void**)&olecmd); 521 if(FAILED(hres)) 522 olecmd = NULL; 523 524 IOleContainer_Release(container); 525 }else { 526 hres = IOleClientSite_QueryInterface(This->client, &IID_IOleCommandTarget, (void**)&olecmd); 527 if(FAILED(hres)) 528 olecmd = NULL; 529 } 530 } 531 532 This->doc_host.olecmd = olecmd; 533 534 if(This->shell_embedding_hwnd) { 535 IOleInPlaceSite *inplace; 536 HWND parent; 537 538 hres = IOleClientSite_QueryInterface(This->client, &IID_IOleInPlaceSite, (void**)&inplace); 539 if(SUCCEEDED(hres)) { 540 hres = IOleInPlaceSite_GetWindow(inplace, &parent); 541 IOleInPlaceSite_Release(inplace); 542 if(SUCCEEDED(hres)) 543 SHSetParentHwnd(This->shell_embedding_hwnd, parent); 544 } 545 }else { 546 create_shell_embedding_hwnd(This); 547 } 548 549 on_offlineconnected_change(This); 550 on_silent_change(This); 551 552 return S_OK; 553 } 554 555 static HRESULT WINAPI OleObject_GetClientSite(IOleObject *iface, LPOLECLIENTSITE *ppClientSite) 556 { 557 WebBrowser *This = impl_from_IOleObject(iface); 558 559 TRACE("(%p)->(%p)\n", This, ppClientSite); 560 561 if(!ppClientSite) 562 return E_INVALIDARG; 563 564 if(This->client) 565 IOleClientSite_AddRef(This->client); 566 *ppClientSite = This->client; 567 568 return S_OK; 569 } 570 571 static HRESULT WINAPI OleObject_SetHostNames(IOleObject *iface, LPCOLESTR szContainerApp, 572 LPCOLESTR szContainerObj) 573 { 574 WebBrowser *This = impl_from_IOleObject(iface); 575 576 TRACE("(%p)->(%s, %s)\n", This, debugstr_w(szContainerApp), debugstr_w(szContainerObj)); 577 578 /* We have nothing to do here. */ 579 return S_OK; 580 } 581 582 static HRESULT WINAPI OleObject_Close(IOleObject *iface, DWORD dwSaveOption) 583 { 584 WebBrowser *This = impl_from_IOleObject(iface); 585 IOleClientSite *client; 586 HRESULT hres; 587 588 TRACE("(%p)->(%d)\n", This, dwSaveOption); 589 590 if(dwSaveOption != OLECLOSE_NOSAVE) { 591 FIXME("unimplemented flag: %x\n", dwSaveOption); 592 return E_NOTIMPL; 593 } 594 595 if(This->doc_host.frame) 596 IOleInPlaceFrame_SetActiveObject(This->doc_host.frame, NULL, NULL); 597 598 if(This->uiwindow) 599 IOleInPlaceUIWindow_SetActiveObject(This->uiwindow, NULL, NULL); 600 601 if(This->inplace) 602 IOleInPlaceSiteEx_OnUIDeactivate(This->inplace, FALSE); 603 notify_on_focus(This, FALSE); 604 if(This->inplace) 605 IOleInPlaceSiteEx_OnInPlaceDeactivate(This->inplace); 606 607 /* store old client site - we need to restore it in DoVerb */ 608 client = This->client; 609 if(This->client) 610 IOleClientSite_AddRef(This->client); 611 hres = IOleObject_SetClientSite(iface, NULL); 612 This->client_closed = client; 613 return hres; 614 } 615 616 static HRESULT WINAPI OleObject_SetMoniker(IOleObject *iface, DWORD dwWhichMoniker, IMoniker* pmk) 617 { 618 WebBrowser *This = impl_from_IOleObject(iface); 619 FIXME("(%p)->(%d, %p)\n", This, dwWhichMoniker, pmk); 620 return E_NOTIMPL; 621 } 622 623 static HRESULT WINAPI OleObject_GetMoniker(IOleObject *iface, DWORD dwAssign, 624 DWORD dwWhichMoniker, LPMONIKER *ppmk) 625 { 626 WebBrowser *This = impl_from_IOleObject(iface); 627 FIXME("(%p)->(%d, %d, %p)\n", This, dwAssign, dwWhichMoniker, ppmk); 628 return E_NOTIMPL; 629 } 630 631 static HRESULT WINAPI OleObject_InitFromData(IOleObject *iface, LPDATAOBJECT pDataObject, 632 BOOL fCreation, DWORD dwReserved) 633 { 634 WebBrowser *This = impl_from_IOleObject(iface); 635 FIXME("(%p)->(%p, %d, %d)\n", This, pDataObject, fCreation, dwReserved); 636 return E_NOTIMPL; 637 } 638 639 static HRESULT WINAPI OleObject_GetClipboardData(IOleObject *iface, DWORD dwReserved, 640 LPDATAOBJECT *ppDataObject) 641 { 642 WebBrowser *This = impl_from_IOleObject(iface); 643 FIXME("(%p)->(%d, %p)\n", This, dwReserved, ppDataObject); 644 return E_NOTIMPL; 645 } 646 647 static HRESULT WINAPI OleObject_DoVerb(IOleObject *iface, LONG iVerb, struct tagMSG* lpmsg, 648 LPOLECLIENTSITE pActiveSite, LONG lindex, HWND hwndParent, LPCRECT lprcPosRect) 649 { 650 WebBrowser *This = impl_from_IOleObject(iface); 651 652 TRACE("(%p)->(%d %p %p %d %p %s)\n", This, iVerb, lpmsg, pActiveSite, lindex, hwndParent, 653 wine_dbgstr_rect(lprcPosRect)); 654 655 /* restore closed client site if we have one */ 656 if(!This->client && This->client_closed) { 657 IOleClientSite *client = This->client_closed; 658 This->client_closed = NULL; 659 IOleObject_SetClientSite(iface, client); 660 IOleClientSite_Release(client); 661 } 662 663 switch (iVerb) 664 { 665 case OLEIVERB_SHOW: 666 TRACE("OLEIVERB_SHOW\n"); 667 return activate_ui(This, pActiveSite); 668 case OLEIVERB_UIACTIVATE: 669 TRACE("OLEIVERB_UIACTIVATE\n"); 670 return activate_ui(This, pActiveSite); 671 case OLEIVERB_INPLACEACTIVATE: 672 TRACE("OLEIVERB_INPLACEACTIVATE\n"); 673 return activate_inplace(This, pActiveSite); 674 case OLEIVERB_HIDE: 675 TRACE("OLEIVERB_HIDE\n"); 676 if(This->inplace) 677 IOleInPlaceSiteEx_OnInPlaceDeactivate(This->inplace); 678 if(This->shell_embedding_hwnd) 679 ShowWindow(This->shell_embedding_hwnd, SW_HIDE); 680 return S_OK; 681 default: 682 FIXME("stub for %d\n", iVerb); 683 break; 684 } 685 686 return E_NOTIMPL; 687 } 688 689 static HRESULT WINAPI OleObject_EnumVerbs(IOleObject *iface, IEnumOLEVERB **ppEnumOleVerb) 690 { 691 WebBrowser *This = impl_from_IOleObject(iface); 692 EnumOLEVERB *ret; 693 694 TRACE("(%p)->(%p)\n", This, ppEnumOleVerb); 695 696 ret = heap_alloc(sizeof(*ret)); 697 if(!ret) 698 return E_OUTOFMEMORY; 699 700 ret->IEnumOLEVERB_iface.lpVtbl = &EnumOLEVERBVtbl; 701 ret->ref = 1; 702 ret->iter = 0; 703 704 *ppEnumOleVerb = &ret->IEnumOLEVERB_iface; 705 return S_OK; 706 } 707 708 static HRESULT WINAPI OleObject_Update(IOleObject *iface) 709 { 710 WebBrowser *This = impl_from_IOleObject(iface); 711 FIXME("(%p)\n", This); 712 return E_NOTIMPL; 713 } 714 715 static HRESULT WINAPI OleObject_IsUpToDate(IOleObject *iface) 716 { 717 WebBrowser *This = impl_from_IOleObject(iface); 718 FIXME("(%p)\n", This); 719 return E_NOTIMPL; 720 } 721 722 static HRESULT WINAPI OleObject_GetUserClassID(IOleObject *iface, CLSID* pClsid) 723 { 724 WebBrowser *This = impl_from_IOleObject(iface); 725 FIXME("(%p)->(%p)\n", This, pClsid); 726 return E_NOTIMPL; 727 } 728 729 static HRESULT WINAPI OleObject_GetUserType(IOleObject *iface, DWORD dwFormOfType, 730 LPOLESTR* pszUserType) 731 { 732 WebBrowser *This = impl_from_IOleObject(iface); 733 TRACE("(%p, %d, %p)\n", This, dwFormOfType, pszUserType); 734 return OleRegGetUserType(&CLSID_WebBrowser, dwFormOfType, pszUserType); 735 } 736 737 static HRESULT WINAPI OleObject_SetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel) 738 { 739 WebBrowser *This = impl_from_IOleObject(iface); 740 741 TRACE("(%p)->(%x %p)\n", This, dwDrawAspect, psizel); 742 743 /* Tests show that dwDrawAspect is ignored */ 744 This->extent = *psizel; 745 return S_OK; 746 } 747 748 static HRESULT WINAPI OleObject_GetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel) 749 { 750 WebBrowser *This = impl_from_IOleObject(iface); 751 752 TRACE("(%p)->(%x, %p)\n", This, dwDrawAspect, psizel); 753 754 /* Tests show that dwDrawAspect is ignored */ 755 *psizel = This->extent; 756 return S_OK; 757 } 758 759 static HRESULT WINAPI OleObject_Advise(IOleObject *iface, IAdviseSink *pAdvSink, 760 DWORD* pdwConnection) 761 { 762 WebBrowser *This = impl_from_IOleObject(iface); 763 FIXME("(%p)->(%p, %p)\n", This, pAdvSink, pdwConnection); 764 return E_NOTIMPL; 765 } 766 767 static HRESULT WINAPI OleObject_Unadvise(IOleObject *iface, DWORD dwConnection) 768 { 769 WebBrowser *This = impl_from_IOleObject(iface); 770 FIXME("(%p)->(%d)\n", This, dwConnection); 771 return E_NOTIMPL; 772 } 773 774 static HRESULT WINAPI OleObject_EnumAdvise(IOleObject *iface, IEnumSTATDATA **ppenumAdvise) 775 { 776 WebBrowser *This = impl_from_IOleObject(iface); 777 FIXME("(%p)->(%p)\n", This, ppenumAdvise); 778 return S_OK; 779 } 780 781 static HRESULT WINAPI OleObject_GetMiscStatus(IOleObject *iface, DWORD dwAspect, DWORD *pdwStatus) 782 { 783 WebBrowser *This = impl_from_IOleObject(iface); 784 785 TRACE("(%p)->(%x, %p)\n", This, dwAspect, pdwStatus); 786 787 *pdwStatus = OLEMISC_SETCLIENTSITEFIRST|OLEMISC_ACTIVATEWHENVISIBLE|OLEMISC_INSIDEOUT 788 |OLEMISC_CANTLINKINSIDE|OLEMISC_RECOMPOSEONRESIZE; 789 790 return S_OK; 791 } 792 793 static HRESULT WINAPI OleObject_SetColorScheme(IOleObject *iface, LOGPALETTE* pLogpal) 794 { 795 WebBrowser *This = impl_from_IOleObject(iface); 796 FIXME("(%p)->(%p)\n", This, pLogpal); 797 return E_NOTIMPL; 798 } 799 800 static const IOleObjectVtbl OleObjectVtbl = 801 { 802 OleObject_QueryInterface, 803 OleObject_AddRef, 804 OleObject_Release, 805 OleObject_SetClientSite, 806 OleObject_GetClientSite, 807 OleObject_SetHostNames, 808 OleObject_Close, 809 OleObject_SetMoniker, 810 OleObject_GetMoniker, 811 OleObject_InitFromData, 812 OleObject_GetClipboardData, 813 OleObject_DoVerb, 814 OleObject_EnumVerbs, 815 OleObject_Update, 816 OleObject_IsUpToDate, 817 OleObject_GetUserClassID, 818 OleObject_GetUserType, 819 OleObject_SetExtent, 820 OleObject_GetExtent, 821 OleObject_Advise, 822 OleObject_Unadvise, 823 OleObject_EnumAdvise, 824 OleObject_GetMiscStatus, 825 OleObject_SetColorScheme 826 }; 827 828 /********************************************************************** 829 * Implement the IOleInPlaceObject interface 830 */ 831 832 static inline WebBrowser *impl_from_IOleInPlaceObject(IOleInPlaceObject *iface) 833 { 834 return CONTAINING_RECORD(iface, WebBrowser, IOleInPlaceObject_iface); 835 } 836 837 static HRESULT WINAPI OleInPlaceObject_QueryInterface(IOleInPlaceObject *iface, 838 REFIID riid, LPVOID *ppobj) 839 { 840 WebBrowser *This = impl_from_IOleInPlaceObject(iface); 841 return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppobj); 842 } 843 844 static ULONG WINAPI OleInPlaceObject_AddRef(IOleInPlaceObject *iface) 845 { 846 WebBrowser *This = impl_from_IOleInPlaceObject(iface); 847 return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); 848 } 849 850 static ULONG WINAPI OleInPlaceObject_Release(IOleInPlaceObject *iface) 851 { 852 WebBrowser *This = impl_from_IOleInPlaceObject(iface); 853 return IWebBrowser2_Release(&This->IWebBrowser2_iface); 854 } 855 856 static HRESULT WINAPI OleInPlaceObject_GetWindow(IOleInPlaceObject *iface, HWND* phwnd) 857 { 858 WebBrowser *This = impl_from_IOleInPlaceObject(iface); 859 860 TRACE("(%p)->(%p)\n", This, phwnd); 861 862 *phwnd = This->shell_embedding_hwnd; 863 return S_OK; 864 } 865 866 static HRESULT WINAPI OleInPlaceObject_ContextSensitiveHelp(IOleInPlaceObject *iface, 867 BOOL fEnterMode) 868 { 869 WebBrowser *This = impl_from_IOleInPlaceObject(iface); 870 FIXME("(%p)->(%x)\n", This, fEnterMode); 871 return E_NOTIMPL; 872 } 873 874 static HRESULT WINAPI OleInPlaceObject_InPlaceDeactivate(IOleInPlaceObject *iface) 875 { 876 WebBrowser *This = impl_from_IOleInPlaceObject(iface); 877 FIXME("(%p)\n", This); 878 879 if(This->inplace) { 880 IOleInPlaceSiteEx_Release(This->inplace); 881 This->inplace = NULL; 882 } 883 884 return S_OK; 885 } 886 887 static HRESULT WINAPI OleInPlaceObject_UIDeactivate(IOleInPlaceObject *iface) 888 { 889 WebBrowser *This = impl_from_IOleInPlaceObject(iface); 890 FIXME("(%p)\n", This); 891 return E_NOTIMPL; 892 } 893 894 static HRESULT WINAPI OleInPlaceObject_SetObjectRects(IOleInPlaceObject *iface, 895 LPCRECT lprcPosRect, LPCRECT lprcClipRect) 896 { 897 WebBrowser *This = impl_from_IOleInPlaceObject(iface); 898 899 TRACE("(%p)->(%s %s)\n", This, wine_dbgstr_rect(lprcPosRect), wine_dbgstr_rect(lprcClipRect)); 900 901 This->pos_rect = *lprcPosRect; 902 903 if(lprcClipRect) 904 This->clip_rect = *lprcClipRect; 905 906 if(This->shell_embedding_hwnd) { 907 SetWindowPos(This->shell_embedding_hwnd, NULL, 908 lprcPosRect->left, lprcPosRect->top, 909 lprcPosRect->right-lprcPosRect->left, 910 lprcPosRect->bottom-lprcPosRect->top, 911 SWP_NOZORDER | SWP_NOACTIVATE); 912 } 913 914 return S_OK; 915 } 916 917 static HRESULT WINAPI OleInPlaceObject_ReactivateAndUndo(IOleInPlaceObject *iface) 918 { 919 WebBrowser *This = impl_from_IOleInPlaceObject(iface); 920 FIXME("(%p)\n", This); 921 return E_NOTIMPL; 922 } 923 924 static const IOleInPlaceObjectVtbl OleInPlaceObjectVtbl = 925 { 926 OleInPlaceObject_QueryInterface, 927 OleInPlaceObject_AddRef, 928 OleInPlaceObject_Release, 929 OleInPlaceObject_GetWindow, 930 OleInPlaceObject_ContextSensitiveHelp, 931 OleInPlaceObject_InPlaceDeactivate, 932 OleInPlaceObject_UIDeactivate, 933 OleInPlaceObject_SetObjectRects, 934 OleInPlaceObject_ReactivateAndUndo 935 }; 936 937 /********************************************************************** 938 * Implement the IOleControl interface 939 */ 940 941 static inline WebBrowser *impl_from_IOleControl(IOleControl *iface) 942 { 943 return CONTAINING_RECORD(iface, WebBrowser, IOleControl_iface); 944 } 945 946 static HRESULT WINAPI OleControl_QueryInterface(IOleControl *iface, 947 REFIID riid, LPVOID *ppobj) 948 { 949 WebBrowser *This = impl_from_IOleControl(iface); 950 return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppobj); 951 } 952 953 static ULONG WINAPI OleControl_AddRef(IOleControl *iface) 954 { 955 WebBrowser *This = impl_from_IOleControl(iface); 956 return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); 957 } 958 959 static ULONG WINAPI OleControl_Release(IOleControl *iface) 960 { 961 WebBrowser *This = impl_from_IOleControl(iface); 962 return IWebBrowser2_Release(&This->IWebBrowser2_iface); 963 } 964 965 static HRESULT WINAPI OleControl_GetControlInfo(IOleControl *iface, LPCONTROLINFO pCI) 966 { 967 WebBrowser *This = impl_from_IOleControl(iface); 968 969 TRACE("(%p)->(%p)\n", This, pCI); 970 971 /* Tests show that this function should be not implemented */ 972 return E_NOTIMPL; 973 } 974 975 static HRESULT WINAPI OleControl_OnMnemonic(IOleControl *iface, struct tagMSG *pMsg) 976 { 977 WebBrowser *This = impl_from_IOleControl(iface); 978 FIXME("(%p)->(%p)\n", This, pMsg); 979 return E_NOTIMPL; 980 } 981 982 static HRESULT WINAPI OleControl_OnAmbientPropertyChange(IOleControl *iface, DISPID dispID) 983 { 984 WebBrowser *This = impl_from_IOleControl(iface); 985 986 TRACE("(%p)->(%d)\n", This, dispID); 987 988 switch(dispID) { 989 case DISPID_UNKNOWN: 990 /* Unknown means multiple properties changed, so check them all. 991 * BUT the Webbrowser OleControl object doesn't appear to do this. 992 */ 993 return S_OK; 994 case DISPID_AMBIENT_DLCONTROL: 995 return S_OK; 996 case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED: 997 return on_offlineconnected_change(This); 998 case DISPID_AMBIENT_SILENT: 999 return on_silent_change(This); 1000 } 1001 1002 FIXME("Unknown dispID %d\n", dispID); 1003 return E_NOTIMPL; 1004 } 1005 1006 static HRESULT WINAPI OleControl_FreezeEvents(IOleControl *iface, BOOL bFreeze) 1007 { 1008 WebBrowser *This = impl_from_IOleControl(iface); 1009 FIXME("(%p)->(%x)\n", This, bFreeze); 1010 return E_NOTIMPL; 1011 } 1012 1013 static const IOleControlVtbl OleControlVtbl = 1014 { 1015 OleControl_QueryInterface, 1016 OleControl_AddRef, 1017 OleControl_Release, 1018 OleControl_GetControlInfo, 1019 OleControl_OnMnemonic, 1020 OleControl_OnAmbientPropertyChange, 1021 OleControl_FreezeEvents 1022 }; 1023 1024 static inline WebBrowser *impl_from_IOleInPlaceActiveObject(IOleInPlaceActiveObject *iface) 1025 { 1026 return CONTAINING_RECORD(iface, WebBrowser, IOleInPlaceActiveObject_iface); 1027 } 1028 1029 static HRESULT WINAPI InPlaceActiveObject_QueryInterface(IOleInPlaceActiveObject *iface, 1030 REFIID riid, void **ppv) 1031 { 1032 WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface); 1033 return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppv); 1034 } 1035 1036 static ULONG WINAPI InPlaceActiveObject_AddRef(IOleInPlaceActiveObject *iface) 1037 { 1038 WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface); 1039 return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); 1040 } 1041 1042 static ULONG WINAPI InPlaceActiveObject_Release(IOleInPlaceActiveObject *iface) 1043 { 1044 WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface); 1045 return IWebBrowser2_Release(&This->IWebBrowser2_iface); 1046 } 1047 1048 static HRESULT WINAPI InPlaceActiveObject_GetWindow(IOleInPlaceActiveObject *iface, 1049 HWND *phwnd) 1050 { 1051 WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface); 1052 return IOleInPlaceObject_GetWindow(&This->IOleInPlaceObject_iface, phwnd); 1053 } 1054 1055 static HRESULT WINAPI InPlaceActiveObject_ContextSensitiveHelp(IOleInPlaceActiveObject *iface, 1056 BOOL fEnterMode) 1057 { 1058 WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface); 1059 return IOleInPlaceObject_ContextSensitiveHelp(&This->IOleInPlaceObject_iface, fEnterMode); 1060 } 1061 1062 static HRESULT WINAPI InPlaceActiveObject_TranslateAccelerator(IOleInPlaceActiveObject *iface, 1063 LPMSG lpmsg) 1064 { 1065 WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface); 1066 IOleInPlaceActiveObject *activeobj; 1067 HRESULT hr = S_FALSE; 1068 1069 TRACE("(%p)->(%p)\n", This, lpmsg); 1070 1071 if(This->doc_host.document) { 1072 if(SUCCEEDED(IUnknown_QueryInterface(This->doc_host.document, 1073 &IID_IOleInPlaceActiveObject, 1074 (void**)&activeobj))) { 1075 hr = IOleInPlaceActiveObject_TranslateAccelerator(activeobj, lpmsg); 1076 IOleInPlaceActiveObject_Release(activeobj); 1077 } 1078 } 1079 1080 if(SUCCEEDED(hr)) 1081 return hr; 1082 else 1083 return S_FALSE; 1084 } 1085 1086 static HRESULT WINAPI InPlaceActiveObject_OnFrameWindowActivate(IOleInPlaceActiveObject *iface, 1087 BOOL fActivate) 1088 { 1089 WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface); 1090 FIXME("(%p)->(%x)\n", This, fActivate); 1091 return E_NOTIMPL; 1092 } 1093 1094 static HRESULT WINAPI InPlaceActiveObject_OnDocWindowActivate(IOleInPlaceActiveObject *iface, 1095 BOOL fActivate) 1096 { 1097 WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface); 1098 FIXME("(%p)->(%x)\n", This, fActivate); 1099 return E_NOTIMPL; 1100 } 1101 1102 static HRESULT WINAPI InPlaceActiveObject_ResizeBorder(IOleInPlaceActiveObject *iface, 1103 LPCRECT lprcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fFrameWindow) 1104 { 1105 WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface); 1106 FIXME("(%p)->(%p %p %x)\n", This, lprcBorder, pUIWindow, fFrameWindow); 1107 return E_NOTIMPL; 1108 } 1109 1110 static HRESULT WINAPI InPlaceActiveObject_EnableModeless(IOleInPlaceActiveObject *iface, 1111 BOOL fEnable) 1112 { 1113 WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface); 1114 FIXME("(%p)->(%x)\n", This, fEnable); 1115 return E_NOTIMPL; 1116 } 1117 1118 static const IOleInPlaceActiveObjectVtbl OleInPlaceActiveObjectVtbl = { 1119 InPlaceActiveObject_QueryInterface, 1120 InPlaceActiveObject_AddRef, 1121 InPlaceActiveObject_Release, 1122 InPlaceActiveObject_GetWindow, 1123 InPlaceActiveObject_ContextSensitiveHelp, 1124 InPlaceActiveObject_TranslateAccelerator, 1125 InPlaceActiveObject_OnFrameWindowActivate, 1126 InPlaceActiveObject_OnDocWindowActivate, 1127 InPlaceActiveObject_ResizeBorder, 1128 InPlaceActiveObject_EnableModeless 1129 }; 1130 1131 static inline WebBrowser *impl_from_IOleCommandTarget(IOleCommandTarget *iface) 1132 { 1133 return CONTAINING_RECORD(iface, WebBrowser, IOleCommandTarget_iface); 1134 } 1135 1136 static HRESULT WINAPI WBOleCommandTarget_QueryInterface(IOleCommandTarget *iface, 1137 REFIID riid, void **ppv) 1138 { 1139 WebBrowser *This = impl_from_IOleCommandTarget(iface); 1140 return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppv); 1141 } 1142 1143 static ULONG WINAPI WBOleCommandTarget_AddRef(IOleCommandTarget *iface) 1144 { 1145 WebBrowser *This = impl_from_IOleCommandTarget(iface); 1146 return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); 1147 } 1148 1149 static ULONG WINAPI WBOleCommandTarget_Release(IOleCommandTarget *iface) 1150 { 1151 WebBrowser *This = impl_from_IOleCommandTarget(iface); 1152 return IWebBrowser2_Release(&This->IWebBrowser2_iface); 1153 } 1154 1155 static HRESULT WINAPI WBOleCommandTarget_QueryStatus(IOleCommandTarget *iface, 1156 const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText) 1157 { 1158 WebBrowser *This = impl_from_IOleCommandTarget(iface); 1159 IOleCommandTarget *cmdtrg; 1160 HRESULT hres; 1161 1162 TRACE("(%p)->(%s %u %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, 1163 pCmdText); 1164 1165 if(!This->doc_host.document) 1166 return 0x80040104; 1167 1168 /* NOTE: There are probably some commands that we should handle here 1169 * instead of forwarding to document object. */ 1170 1171 hres = IUnknown_QueryInterface(This->doc_host.document, &IID_IOleCommandTarget, (void**)&cmdtrg); 1172 if(FAILED(hres)) 1173 return hres; 1174 1175 hres = IOleCommandTarget_QueryStatus(cmdtrg, pguidCmdGroup, cCmds, prgCmds, pCmdText); 1176 IOleCommandTarget_Release(cmdtrg); 1177 1178 return hres; 1179 } 1180 1181 static HRESULT WINAPI WBOleCommandTarget_Exec(IOleCommandTarget *iface, 1182 const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, 1183 VARIANT *pvaOut) 1184 { 1185 WebBrowser *This = impl_from_IOleCommandTarget(iface); 1186 FIXME("(%p)->(%s %d %d %s %p)\n", This, debugstr_guid(pguidCmdGroup), nCmdID, 1187 nCmdexecopt, debugstr_variant(pvaIn), pvaOut); 1188 return E_NOTIMPL; 1189 } 1190 1191 static const IOleCommandTargetVtbl OleCommandTargetVtbl = { 1192 WBOleCommandTarget_QueryInterface, 1193 WBOleCommandTarget_AddRef, 1194 WBOleCommandTarget_Release, 1195 WBOleCommandTarget_QueryStatus, 1196 WBOleCommandTarget_Exec 1197 }; 1198 1199 void WebBrowser_OleObject_Init(WebBrowser *This) 1200 { 1201 DWORD dpi_x; 1202 DWORD dpi_y; 1203 HDC hdc; 1204 1205 /* default aspect ratio is 96dpi / 96dpi */ 1206 hdc = GetDC(0); 1207 dpi_x = GetDeviceCaps(hdc, LOGPIXELSX); 1208 dpi_y = GetDeviceCaps(hdc, LOGPIXELSY); 1209 ReleaseDC(0, hdc); 1210 1211 This->IOleObject_iface.lpVtbl = &OleObjectVtbl; 1212 This->IOleInPlaceObject_iface.lpVtbl = &OleInPlaceObjectVtbl; 1213 This->IOleControl_iface.lpVtbl = &OleControlVtbl; 1214 This->IOleInPlaceActiveObject_iface.lpVtbl = &OleInPlaceActiveObjectVtbl; 1215 This->IOleCommandTarget_iface.lpVtbl = &OleCommandTargetVtbl; 1216 1217 /* Default size is 50x20 pixels, in himetric units */ 1218 This->extent.cx = MulDiv( 50, 2540, dpi_x ); 1219 This->extent.cy = MulDiv( 20, 2540, dpi_y ); 1220 } 1221 1222 void WebBrowser_OleObject_Destroy(WebBrowser *This) 1223 { 1224 release_client_site(This, TRUE); 1225 } 1226