oleobject.c 32.7 KB
Newer Older
1
/*
2
 * Implementation of IOleObject interfaces for WebBrowser control
3 4 5 6 7 8
 *
 * - IOleObject
 * - IOleInPlaceObject
 * - IOleControl
 *
 * Copyright 2001 John R. Sheets (for CodeWeavers)
9
 * Copyright 2005 Jacek Caban
10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 29

#include "ieframe.h"

30
#include "htiframe.h"
31
#include "idispids.h"
32
#include "mshtmdid.h"
33

34 35
#include "wine/debug.h"

36
WINE_DEFAULT_DEBUG_CHANNEL(ieframe);
37

38 39 40
/* shlwapi.dll */
HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent);

41 42
static ATOM shell_embedding_atom = 0;

Jacek Caban's avatar
Jacek Caban committed
43 44
static LRESULT resize_window(WebBrowser *This, LONG width, LONG height)
{
45 46
    if(This->doc_host.hwnd)
        SetWindowPos(This->doc_host.hwnd, NULL, 0, 0, width, height,
Jacek Caban's avatar
Jacek Caban committed
47 48 49 50 51
                     SWP_NOZORDER | SWP_NOACTIVATE);

    return 0;
}

52 53
static LRESULT WINAPI shell_embedding_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
Jacek Caban's avatar
Jacek Caban committed
54 55 56 57 58 59 60 61 62 63 64 65 66 67
    WebBrowser *This;

    static const WCHAR wszTHIS[] = {'T','H','I','S',0};

    if(msg == WM_CREATE) {
        This = *(WebBrowser**)lParam;
        SetPropW(hwnd, wszTHIS, This);
    }else {
        This = GetPropW(hwnd, wszTHIS);
    }

    switch(msg) {
    case WM_SIZE:
        return resize_window(This, LOWORD(lParam), HIWORD(lParam));
68
    case WM_DOCHOSTTASK:
69
        return process_dochost_tasks(&This->doc_host);
Jacek Caban's avatar
Jacek Caban committed
70 71
    }

72
    return DefWindowProcW(hwnd, msg, wParam, lParam);
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
}

static void create_shell_embedding_hwnd(WebBrowser *This)
{
    IOleInPlaceSite *inplace;
    HWND parent = NULL;
    HRESULT hres;

    static const WCHAR wszShellEmbedding[] =
        {'S','h','e','l','l',' ','E','m','b','e','d','d','i','n','g',0};

    if(!shell_embedding_atom) {
        static WNDCLASSEXW wndclass = {
            sizeof(wndclass),
            CS_DBLCLKS,
            shell_embedding_proc,
            0, 0 /* native uses 8 */, NULL, NULL, NULL,
90
            (HBRUSH)(COLOR_WINDOW + 1), NULL,
91 92 93
            wszShellEmbedding,
            NULL
        };
94
        wndclass.hInstance = ieframe_instance;
95 96 97 98 99 100 101 102 103 104

        RegisterClassExW(&wndclass);
    }

    hres = IOleClientSite_QueryInterface(This->client, &IID_IOleInPlaceSite, (void**)&inplace);
    if(SUCCEEDED(hres)) {
        IOleInPlaceSite_GetWindow(inplace, &parent);
        IOleInPlaceSite_Release(inplace);
    }

105
    This->doc_host.frame_hwnd = This->shell_embedding_hwnd = CreateWindowExW(
106 107
            WS_EX_WINDOWEDGE,
            wszShellEmbedding, wszShellEmbedding,
108 109
            WS_CLIPSIBLINGS | WS_CLIPCHILDREN
            | (parent ? WS_CHILD | WS_TABSTOP : WS_POPUP | WS_MAXIMIZEBOX),
110
            0, 0, 0, 0, parent,
111
            NULL, ieframe_instance, This);
112 113

    TRACE("parent=%p hwnd=%p\n", parent, This->shell_embedding_hwnd);
114 115
}

116
static HRESULT activate_inplace(WebBrowser *This, IOleClientSite *active_site)
117
{
118
    HWND parent_hwnd;
119 120
    HRESULT hres;

121 122 123
    if(This->inplace)
        return S_OK;

124 125 126 127 128 129 130 131 132 133 134 135
    if(!active_site)
        return E_INVALIDARG;

    hres = IOleClientSite_QueryInterface(active_site, &IID_IOleInPlaceSite,
                                         (void**)&This->inplace);
    if(FAILED(hres)) {
        WARN("Could not get IOleInPlaceSite\n");
        return hres;
    }

    hres = IOleInPlaceSite_CanInPlaceActivate(This->inplace);
    if(hres != S_OK) {
136
        WARN("CanInPlaceActivate returned: %08x\n", hres);
137
        IOleInPlaceSite_Release(This->inplace);
138
        This->inplace = NULL;
139 140 141
        return E_FAIL;
    }

142 143 144
    hres = IOleInPlaceSite_GetWindow(This->inplace, &parent_hwnd);
    if(SUCCEEDED(hres))
        SHSetParentHwnd(This->shell_embedding_hwnd, parent_hwnd);
145 146 147

    IOleInPlaceSite_OnInPlaceActivate(This->inplace);

148
    This->frameinfo.cb = sizeof(OLEINPLACEFRAMEINFO);
149
    IOleInPlaceSite_GetWindowContext(This->inplace, &This->doc_host.frame, &This->uiwindow,
150 151 152 153 154 155 156 157 158 159
                                     &This->pos_rect, &This->clip_rect,
                                     &This->frameinfo);

    SetWindowPos(This->shell_embedding_hwnd, NULL,
                 This->pos_rect.left, This->pos_rect.top,
                 This->pos_rect.right-This->pos_rect.left,
                 This->pos_rect.bottom-This->pos_rect.top,
                 SWP_NOZORDER | SWP_SHOWWINDOW);

    if(This->client) {
160 161
        IOleContainer *container;

162
        IOleClientSite_ShowObject(This->client);
163 164 165 166 167 168 169

        hres = IOleClientSite_GetContainer(This->client, &container);
        if(SUCCEEDED(hres)) {
            if(This->container)
                IOleContainer_Release(This->container);
            This->container = container;
        }
170 171
    }

172 173
    if(This->doc_host.frame)
        IOleInPlaceFrame_GetWindow(This->doc_host.frame, &This->frame_hwnd);
174 175 176 177

    return S_OK;
}

178
static HRESULT activate_ui(WebBrowser *This, IOleClientSite *active_site)
179 180 181 182 183
{
    HRESULT hres;

    static const WCHAR wszitem[] = {'i','t','e','m',0};

184
    if(This->inplace)
185 186 187
    {
        if(This->shell_embedding_hwnd)
            ShowWindow(This->shell_embedding_hwnd, SW_SHOW);
188
        return S_OK;
189
    }
190

191
    hres = activate_inplace(This, active_site);
192 193 194 195 196
    if(FAILED(hres))
        return hres;

    IOleInPlaceSite_OnUIActivate(This->inplace);

197
    if(This->doc_host.frame)
198
        IOleInPlaceFrame_SetActiveObject(This->doc_host.frame, &This->IOleInPlaceActiveObject_iface, wszitem);
199
    if(This->uiwindow)
200
        IOleInPlaceUIWindow_SetActiveObject(This->uiwindow, &This->IOleInPlaceActiveObject_iface, wszitem);
201

202 203
    if(This->doc_host.frame)
        IOleInPlaceFrame_SetMenu(This->doc_host.frame, NULL, NULL, This->shell_embedding_hwnd);
204

205 206
    SetFocus(This->shell_embedding_hwnd);

207 208 209
    return S_OK;
}

210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
static HRESULT get_client_disp_property(IOleClientSite *client, DISPID dispid, VARIANT *res)
{
    IDispatch *disp = NULL;
    DISPPARAMS dispparams = {NULL, 0};
    HRESULT hres;

    VariantInit(res);

    if(!client)
        return S_OK;

    hres = IOleClientSite_QueryInterface(client, &IID_IDispatch, (void**)&disp);
    if(FAILED(hres)) {
        TRACE("Could not get IDispatch\n");
        return hres;
    }

    hres = IDispatch_Invoke(disp, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT,
            DISPATCH_PROPERTYGET, &dispparams, res, NULL, NULL);

    IDispatch_Release(disp);

    return hres;
}

235 236 237 238 239 240 241
static HRESULT on_offlineconnected_change(WebBrowser *This)
{
    VARIANT offline;

    get_client_disp_property(This->client, DISPID_AMBIENT_OFFLINEIFNOTCONNECTED, &offline);

    if(V_VT(&offline) == VT_BOOL)
242
        IWebBrowser2_put_Offline(&This->IWebBrowser2_iface, V_BOOL(&offline));
243 244 245 246 247 248
    else if(V_VT(&offline) != VT_EMPTY)
        WARN("wrong V_VT(silent) %d\n", V_VT(&offline));

    return S_OK;
}

249 250 251 252 253 254 255
static HRESULT on_silent_change(WebBrowser *This)
{
    VARIANT silent;

    get_client_disp_property(This->client, DISPID_AMBIENT_SILENT, &silent);

    if(V_VT(&silent) == VT_BOOL)
256
        IWebBrowser2_put_Silent(&This->IWebBrowser2_iface, V_BOOL(&silent));
257 258 259 260 261 262
    else if(V_VT(&silent) != VT_EMPTY)
        WARN("wrong V_VT(silent) %d\n", V_VT(&silent));

    return S_OK;
}

263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
static void release_client_site(WebBrowser *This)
{
    release_dochost_client(&This->doc_host);

    if(This->shell_embedding_hwnd) {
        DestroyWindow(This->shell_embedding_hwnd);
        This->shell_embedding_hwnd = NULL;
    }

    if(This->inplace) {
        IOleInPlaceSite_Release(This->inplace);
        This->inplace = NULL;
    }

    if(This->container) {
        IOleContainer_Release(This->container);
        This->container = NULL;
    }

    if(This->uiwindow) {
        IOleInPlaceUIWindow_Release(This->uiwindow);
        This->uiwindow = NULL;
    }

    if(This->client) {
        IOleClientSite_Release(This->client);
        This->client = NULL;
    }
}

293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
typedef struct {
    IEnumOLEVERB IEnumOLEVERB_iface;

    LONG ref;
} EnumOLEVERB;

static inline EnumOLEVERB *impl_from_IEnumOLEVERB(IEnumOLEVERB *iface)
{
    return CONTAINING_RECORD(iface, EnumOLEVERB, IEnumOLEVERB_iface);
}

static HRESULT WINAPI EnumOLEVERB_QueryInterface(IEnumOLEVERB *iface, REFIID riid, void **ppv)
{
    EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);

    if(IsEqualGUID(&IID_IUnknown, riid)) {
        TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
        *ppv = &This->IEnumOLEVERB_iface;
    }else if(IsEqualGUID(&IID_IEnumOLEVERB, riid)) {
        TRACE("(%p)->(IID_IEnumOLEVERB %p)\n", This, ppv);
        *ppv = &This->IEnumOLEVERB_iface;
    }else {
        WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
        *ppv = NULL;
        return E_NOINTERFACE;
    }

    IUnknown_AddRef((IUnknown*)*ppv);
    return S_OK;
}

static ULONG WINAPI EnumOLEVERB_AddRef(IEnumOLEVERB *iface)
{
    EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);
    LONG ref = InterlockedIncrement(&This->ref);

    TRACE("(%p) ref=%d\n", This, ref);

    return ref;
}

static ULONG WINAPI EnumOLEVERB_Release(IEnumOLEVERB *iface)
{
    EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);
    LONG ref = InterlockedDecrement(&This->ref);

    TRACE("(%p) ref=%d\n", This, ref);

    if(!ref)
        heap_free(This);

    return ref;
}

static HRESULT WINAPI EnumOLEVERB_Next(IEnumOLEVERB *iface, ULONG celt, OLEVERB *rgelt, ULONG *pceltFetched)
{
    EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);

    TRACE("(%p)->(%u %p %p)\n", This, celt, rgelt, pceltFetched);

    if(pceltFetched)
        *pceltFetched = 0;
    return S_OK;
}

static HRESULT WINAPI EnumOLEVERB_Skip(IEnumOLEVERB *iface, ULONG celt)
{
    EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);
    TRACE("(%p)->(%u)\n", This, celt);
    return S_OK;
}

static HRESULT WINAPI EnumOLEVERB_Reset(IEnumOLEVERB *iface)
{
    EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);
    TRACE("(%p)\n", This);
    return S_OK;
}

static HRESULT WINAPI EnumOLEVERB_Clone(IEnumOLEVERB *iface, IEnumOLEVERB **ppenum)
{
    EnumOLEVERB *This = impl_from_IEnumOLEVERB(iface);
    FIXME("(%p)->(%p)\n", This, ppenum);
    return E_NOTIMPL;
}

static const IEnumOLEVERBVtbl EnumOLEVERBVtbl = {
    EnumOLEVERB_QueryInterface,
    EnumOLEVERB_AddRef,
    EnumOLEVERB_Release,
    EnumOLEVERB_Next,
    EnumOLEVERB_Skip,
    EnumOLEVERB_Reset,
    EnumOLEVERB_Clone
};

389
/**********************************************************************
390
 * Implement the IOleObject interface for the WebBrowser control
391 392
 */

393 394
static inline WebBrowser *impl_from_IOleObject(IOleObject *iface)
{
395
    return CONTAINING_RECORD(iface, WebBrowser, IOleObject_iface);
396
}
397

398
static HRESULT WINAPI OleObject_QueryInterface(IOleObject *iface, REFIID riid, void **ppv)
399
{
400
    WebBrowser *This = impl_from_IOleObject(iface);
401
    return IWebBrowser_QueryInterface(&This->IWebBrowser2_iface, riid, ppv);
402 403
}

404
static ULONG WINAPI OleObject_AddRef(IOleObject *iface)
405
{
406
    WebBrowser *This = impl_from_IOleObject(iface);
407
    return IWebBrowser_AddRef(&This->IWebBrowser2_iface);
408 409
}

410
static ULONG WINAPI OleObject_Release(IOleObject *iface)
411
{
412
    WebBrowser *This = impl_from_IOleObject(iface);
413
    return IWebBrowser_Release(&This->IWebBrowser2_iface);
414 415
}

416
static HRESULT WINAPI OleObject_SetClientSite(IOleObject *iface, LPOLECLIENTSITE pClientSite)
417
{
418
    WebBrowser *This = impl_from_IOleObject(iface);
419
    IDocHostUIHandler *hostui;
420
    IOleContainer *container;
421
    IDispatch *disp;
422
    HRESULT hres;
423 424 425 426 427 428

    TRACE("(%p)->(%p)\n", This, pClientSite);

    if(This->client == pClientSite)
        return S_OK;

429
    release_client_site(This);
430

431
    if(!pClientSite) {
432
        if(This->doc_host.document)
433
            deactivate_document(&This->doc_host);
434
        return S_OK;
435
    }
436

437
    IOleClientSite_AddRef(pClientSite);
438
    This->client = pClientSite;
439

440 441 442 443
    hres = IOleClientSite_QueryInterface(This->client, &IID_IDispatch,
            (void**)&disp);
    if(SUCCEEDED(hres))
        This->doc_host.client_disp = disp;
444

445 446 447 448
    hres = IOleClientSite_QueryInterface(This->client, &IID_IDocHostUIHandler,
            (void**)&hostui);
    if(SUCCEEDED(hres))
        This->doc_host.hostui = hostui;
449

450 451 452 453 454 455 456 457 458 459 460 461 462 463
    hres = IOleClientSite_GetContainer(This->client, &container);
    if(SUCCEEDED(hres)) {
        ITargetContainer *target_container;

        hres = IOleContainer_QueryInterface(container, &IID_ITargetContainer,
                                            (void**)&target_container);
        if(SUCCEEDED(hres)) {
            FIXME("Unsupported ITargetContainer\n");
            ITargetContainer_Release(target_container);
        }

        IOleContainer_Release(container);
    }

464 465
    create_shell_embedding_hwnd(This);

466 467 468
    on_offlineconnected_change(This);
    on_silent_change(This);

469
    return S_OK;
470 471
}

472
static HRESULT WINAPI OleObject_GetClientSite(IOleObject *iface, LPOLECLIENTSITE *ppClientSite)
473
{
474
    WebBrowser *This = impl_from_IOleObject(iface);
475 476 477 478 479 480 481 482 483 484 485

    TRACE("(%p)->(%p)\n", This, ppClientSite);

    if(!ppClientSite)
        return E_INVALIDARG;

    if(This->client)
        IOleClientSite_AddRef(This->client);
    *ppClientSite = This->client;

    return S_OK;
486 487
}

488 489
static HRESULT WINAPI OleObject_SetHostNames(IOleObject *iface, LPCOLESTR szContainerApp,
        LPCOLESTR szContainerObj)
490
{
491
    WebBrowser *This = impl_from_IOleObject(iface);
492 493 494 495 496

    TRACE("(%p)->(%s, %s)\n", This, debugstr_w(szContainerApp), debugstr_w(szContainerObj));

    /* We have nothing to do here. */
    return S_OK;
497 498
}

499
static HRESULT WINAPI OleObject_Close(IOleObject *iface, DWORD dwSaveOption)
500
{
501
    WebBrowser *This = impl_from_IOleObject(iface);
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521

    TRACE("(%p)->(%d)\n", This, dwSaveOption);

    if(dwSaveOption != OLECLOSE_NOSAVE) {
        FIXME("unimplemnted flag: %x\n", dwSaveOption);
        return E_NOTIMPL;
    }

    if(This->doc_host.frame)
        IOleInPlaceFrame_SetActiveObject(This->doc_host.frame, NULL, NULL);

    if(This->uiwindow)
        IOleInPlaceUIWindow_SetActiveObject(This->uiwindow, NULL, NULL);

    if(This->inplace) {
        IOleInPlaceSite_OnUIDeactivate(This->inplace, FALSE);
        IOleInPlaceSite_OnInPlaceDeactivate(This->inplace);
    }

    return IOleObject_SetClientSite(iface, NULL);
522 523
}

524
static HRESULT WINAPI OleObject_SetMoniker(IOleObject *iface, DWORD dwWhichMoniker, IMoniker* pmk)
525
{
526
    WebBrowser *This = impl_from_IOleObject(iface);
527
    FIXME("(%p)->(%d, %p)\n", This, dwWhichMoniker, pmk);
528
    return E_NOTIMPL;
529 530
}

531 532
static HRESULT WINAPI OleObject_GetMoniker(IOleObject *iface, DWORD dwAssign,
        DWORD dwWhichMoniker, LPMONIKER *ppmk)
533
{
534
    WebBrowser *This = impl_from_IOleObject(iface);
535
    FIXME("(%p)->(%d, %d, %p)\n", This, dwAssign, dwWhichMoniker, ppmk);
536
    return E_NOTIMPL;
537 538
}

539 540
static HRESULT WINAPI OleObject_InitFromData(IOleObject *iface, LPDATAOBJECT pDataObject,
        BOOL fCreation, DWORD dwReserved)
541
{
542
    WebBrowser *This = impl_from_IOleObject(iface);
543
    FIXME("(%p)->(%p, %d, %d)\n", This, pDataObject, fCreation, dwReserved);
544
    return E_NOTIMPL;
545 546
}

547 548
static HRESULT WINAPI OleObject_GetClipboardData(IOleObject *iface, DWORD dwReserved,
        LPDATAOBJECT *ppDataObject)
549
{
550
    WebBrowser *This = impl_from_IOleObject(iface);
551
    FIXME("(%p)->(%d, %p)\n", This, dwReserved, ppDataObject);
552
    return E_NOTIMPL;
553 554
}

555 556
static HRESULT WINAPI OleObject_DoVerb(IOleObject *iface, LONG iVerb, struct tagMSG* lpmsg,
        LPOLECLIENTSITE pActiveSite, LONG lindex, HWND hwndParent, LPCRECT lprcPosRect)
557
{
558
    WebBrowser *This = impl_from_IOleObject(iface);
559

560
    TRACE("(%p)->(%d %p %p %d %p %p)\n", This, iVerb, lpmsg, pActiveSite, lindex, hwndParent,
561
            lprcPosRect);
562

563 564
    switch (iVerb)
    {
565 566
    case OLEIVERB_SHOW:
        TRACE("OLEIVERB_SHOW\n");
567
        return activate_ui(This, pActiveSite);
568 569
    case OLEIVERB_UIACTIVATE:
        TRACE("OLEIVERB_UIACTIVATE\n");
570
        return activate_ui(This, pActiveSite);
571
    case OLEIVERB_INPLACEACTIVATE:
572
        TRACE("OLEIVERB_INPLACEACTIVATE\n");
573
        return activate_inplace(This, pActiveSite);
574 575
    case OLEIVERB_HIDE:
        TRACE("OLEIVERB_HIDE\n");
576 577
        if(This->shell_embedding_hwnd)
            ShowWindow(This->shell_embedding_hwnd, SW_HIDE);
578
        return S_OK;
579
    default:
580
        FIXME("stub for %d\n", iVerb);
581 582 583
        break;
    }

584
    return E_NOTIMPL;
585 586
}

587
static HRESULT WINAPI OleObject_EnumVerbs(IOleObject *iface, IEnumOLEVERB **ppEnumOleVerb)
588
{
589
    WebBrowser *This = impl_from_IOleObject(iface);
590 591
    EnumOLEVERB *ret;

592
    TRACE("(%p)->(%p)\n", This, ppEnumOleVerb);
593 594 595 596 597 598 599 600 601 602

    ret = heap_alloc(sizeof(*ret));
    if(!ret)
        return E_OUTOFMEMORY;

    ret->IEnumOLEVERB_iface.lpVtbl = &EnumOLEVERBVtbl;
    ret->ref = 1;

    *ppEnumOleVerb = &ret->IEnumOLEVERB_iface;
    return S_OK;
603 604
}

605
static HRESULT WINAPI OleObject_Update(IOleObject *iface)
606
{
607
    WebBrowser *This = impl_from_IOleObject(iface);
608
    FIXME("(%p)\n", This);
609 610 611
    return E_NOTIMPL;
}

612
static HRESULT WINAPI OleObject_IsUpToDate(IOleObject *iface)
613
{
614
    WebBrowser *This = impl_from_IOleObject(iface);
615 616
    FIXME("(%p)\n", This);
    return E_NOTIMPL;
617 618
}

619
static HRESULT WINAPI OleObject_GetUserClassID(IOleObject *iface, CLSID* pClsid)
620
{
621
    WebBrowser *This = impl_from_IOleObject(iface);
622 623
    FIXME("(%p)->(%p)\n", This, pClsid);
    return E_NOTIMPL;
624 625
}

626 627
static HRESULT WINAPI OleObject_GetUserType(IOleObject *iface, DWORD dwFormOfType,
        LPOLESTR* pszUserType)
628
{
629
    WebBrowser *This = impl_from_IOleObject(iface);
630
    TRACE("(%p, %d, %p)\n", This, dwFormOfType, pszUserType);
631 632 633
    return OleRegGetUserType(&CLSID_WebBrowser, dwFormOfType, pszUserType);
}

634
static HRESULT WINAPI OleObject_SetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel)
635
{
636
    WebBrowser *This = impl_from_IOleObject(iface);
637

638
    TRACE("(%p)->(%x %p)\n", This, dwDrawAspect, psizel);
639 640

    /* Tests show that dwDrawAspect is ignored */
641
    This->extent = *psizel;
642
    return S_OK;
643 644
}

645
static HRESULT WINAPI OleObject_GetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel)
646
{
647
    WebBrowser *This = impl_from_IOleObject(iface);
648

649
    TRACE("(%p)->(%x, %p)\n", This, dwDrawAspect, psizel);
650 651

    /* Tests show that dwDrawAspect is ignored */
652
    *psizel = This->extent;
653
    return S_OK;
654 655
}

656 657
static HRESULT WINAPI OleObject_Advise(IOleObject *iface, IAdviseSink *pAdvSink,
        DWORD* pdwConnection)
658
{
659
    WebBrowser *This = impl_from_IOleObject(iface);
660 661
    FIXME("(%p)->(%p, %p)\n", This, pAdvSink, pdwConnection);
    return E_NOTIMPL;
662 663
}

664
static HRESULT WINAPI OleObject_Unadvise(IOleObject *iface, DWORD dwConnection)
665
{
666
    WebBrowser *This = impl_from_IOleObject(iface);
667
    FIXME("(%p)->(%d)\n", This, dwConnection);
668
    return E_NOTIMPL;
669 670
}

671
static HRESULT WINAPI OleObject_EnumAdvise(IOleObject *iface, IEnumSTATDATA **ppenumAdvise)
672
{
673
    WebBrowser *This = impl_from_IOleObject(iface);
674
    FIXME("(%p)->(%p)\n", This, ppenumAdvise);
675 676 677
    return S_OK;
}

678
static HRESULT WINAPI OleObject_GetMiscStatus(IOleObject *iface, DWORD dwAspect, DWORD *pdwStatus)
679
{
680
    WebBrowser *This = impl_from_IOleObject(iface);
681

682
    TRACE("(%p)->(%x, %p)\n", This, dwAspect, pdwStatus);
683

684 685
    *pdwStatus = OLEMISC_SETCLIENTSITEFIRST|OLEMISC_ACTIVATEWHENVISIBLE|OLEMISC_INSIDEOUT
        |OLEMISC_CANTLINKINSIDE|OLEMISC_RECOMPOSEONRESIZE;
686 687 688 689

    return S_OK;
}

690
static HRESULT WINAPI OleObject_SetColorScheme(IOleObject *iface, LOGPALETTE* pLogpal)
691
{
692
    WebBrowser *This = impl_from_IOleObject(iface);
693 694
    FIXME("(%p)->(%p)\n", This, pLogpal);
    return E_NOTIMPL;
695 696
}

697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722
static const IOleObjectVtbl OleObjectVtbl =
{
    OleObject_QueryInterface,
    OleObject_AddRef,
    OleObject_Release,
    OleObject_SetClientSite,
    OleObject_GetClientSite,
    OleObject_SetHostNames,
    OleObject_Close,
    OleObject_SetMoniker,
    OleObject_GetMoniker,
    OleObject_InitFromData,
    OleObject_GetClipboardData,
    OleObject_DoVerb,
    OleObject_EnumVerbs,
    OleObject_Update,
    OleObject_IsUpToDate,
    OleObject_GetUserClassID,
    OleObject_GetUserType,
    OleObject_SetExtent,
    OleObject_GetExtent,
    OleObject_Advise,
    OleObject_Unadvise,
    OleObject_EnumAdvise,
    OleObject_GetMiscStatus,
    OleObject_SetColorScheme
723 724 725 726 727 728
};

/**********************************************************************
 * Implement the IOleInPlaceObject interface
 */

729 730
static inline WebBrowser *impl_from_IOleInPlaceObject(IOleInPlaceObject *iface)
{
731
    return CONTAINING_RECORD(iface, WebBrowser, IOleInPlaceObject_iface);
732
}
733

734 735 736
static HRESULT WINAPI OleInPlaceObject_QueryInterface(IOleInPlaceObject *iface,
        REFIID riid, LPVOID *ppobj)
{
737
    WebBrowser *This = impl_from_IOleInPlaceObject(iface);
738
    return IWebBrowser_QueryInterface(&This->IWebBrowser2_iface, riid, ppobj);
739 740
}

741
static ULONG WINAPI OleInPlaceObject_AddRef(IOleInPlaceObject *iface)
742
{
743
    WebBrowser *This = impl_from_IOleInPlaceObject(iface);
744
    return IWebBrowser_AddRef(&This->IWebBrowser2_iface);
745 746
}

747
static ULONG WINAPI OleInPlaceObject_Release(IOleInPlaceObject *iface)
748
{
749
    WebBrowser *This = impl_from_IOleInPlaceObject(iface);
750
    return IWebBrowser_Release(&This->IWebBrowser2_iface);
751 752
}

753
static HRESULT WINAPI OleInPlaceObject_GetWindow(IOleInPlaceObject *iface, HWND* phwnd)
754
{
755
    WebBrowser *This = impl_from_IOleInPlaceObject(iface);
756

757
    TRACE("(%p)->(%p)\n", This, phwnd);
758

759
    *phwnd = This->shell_embedding_hwnd;
760 761 762
    return S_OK;
}

763 764
static HRESULT WINAPI OleInPlaceObject_ContextSensitiveHelp(IOleInPlaceObject *iface,
        BOOL fEnterMode)
765
{
766
    WebBrowser *This = impl_from_IOleInPlaceObject(iface);
767 768
    FIXME("(%p)->(%x)\n", This, fEnterMode);
    return E_NOTIMPL;
769 770
}

771
static HRESULT WINAPI OleInPlaceObject_InPlaceDeactivate(IOleInPlaceObject *iface)
772
{
773
    WebBrowser *This = impl_from_IOleInPlaceObject(iface);
774
    FIXME("(%p)\n", This);
775 776 777 778 779 780 781

    if(This->inplace) {
        IOleInPlaceSite_Release(This->inplace);
        This->inplace = NULL;
    }

    return S_OK;
782 783
}

784
static HRESULT WINAPI OleInPlaceObject_UIDeactivate(IOleInPlaceObject *iface)
785
{
786
    WebBrowser *This = impl_from_IOleInPlaceObject(iface);
787 788
    FIXME("(%p)\n", This);
    return E_NOTIMPL;
789 790
}

791 792
static HRESULT WINAPI OleInPlaceObject_SetObjectRects(IOleInPlaceObject *iface,
        LPCRECT lprcPosRect, LPCRECT lprcClipRect)
793
{
794
    WebBrowser *This = impl_from_IOleInPlaceObject(iface);
795 796 797

    TRACE("(%p)->(%p %p)\n", This, lprcPosRect, lprcClipRect);

798
    This->pos_rect = *lprcPosRect;
799 800

    if(lprcClipRect)
801
        This->clip_rect = *lprcClipRect;
802

803 804 805 806
    if(This->shell_embedding_hwnd) {
        SetWindowPos(This->shell_embedding_hwnd, NULL,
                     lprcPosRect->left, lprcPosRect->top,
                     lprcPosRect->right-lprcPosRect->left,
Jacek Caban's avatar
Jacek Caban committed
807
                     lprcPosRect->bottom-lprcPosRect->top,
808 809 810 811
                     SWP_NOZORDER | SWP_NOACTIVATE);
    }

    return S_OK;
812 813
}

814
static HRESULT WINAPI OleInPlaceObject_ReactivateAndUndo(IOleInPlaceObject *iface)
815
{
816
    WebBrowser *This = impl_from_IOleInPlaceObject(iface);
817 818
    FIXME("(%p)\n", This);
    return E_NOTIMPL;
819 820
}

821 822 823 824 825 826 827 828 829 830 831
static const IOleInPlaceObjectVtbl OleInPlaceObjectVtbl =
{
    OleInPlaceObject_QueryInterface,
    OleInPlaceObject_AddRef,
    OleInPlaceObject_Release,
    OleInPlaceObject_GetWindow,
    OleInPlaceObject_ContextSensitiveHelp,
    OleInPlaceObject_InPlaceDeactivate,
    OleInPlaceObject_UIDeactivate,
    OleInPlaceObject_SetObjectRects,
    OleInPlaceObject_ReactivateAndUndo
832 833 834 835 836 837
};

/**********************************************************************
 * Implement the IOleControl interface
 */

838 839
static inline WebBrowser *impl_from_IOleControl(IOleControl *iface)
{
840
    return CONTAINING_RECORD(iface, WebBrowser, IOleControl_iface);
841
}
842

843 844 845
static HRESULT WINAPI OleControl_QueryInterface(IOleControl *iface,
        REFIID riid, LPVOID *ppobj)
{
846
    WebBrowser *This = impl_from_IOleControl(iface);
847
    return IWebBrowser_QueryInterface(&This->IWebBrowser2_iface, riid, ppobj);
848 849
}

850
static ULONG WINAPI OleControl_AddRef(IOleControl *iface)
851
{
852
    WebBrowser *This = impl_from_IOleControl(iface);
853
    return IWebBrowser_AddRef(&This->IWebBrowser2_iface);
854 855
}

856
static ULONG WINAPI OleControl_Release(IOleControl *iface)
857
{
858
    WebBrowser *This = impl_from_IOleControl(iface);
859
    return IWebBrowser_Release(&This->IWebBrowser2_iface);
860 861
}

862
static HRESULT WINAPI OleControl_GetControlInfo(IOleControl *iface, LPCONTROLINFO pCI)
863
{
864
    WebBrowser *This = impl_from_IOleControl(iface);
865 866 867 868

    TRACE("(%p)->(%p)\n", This, pCI);

    /* Tests show that this function should be not implemented */
869
    return E_NOTIMPL;
870 871
}

872
static HRESULT WINAPI OleControl_OnMnemonic(IOleControl *iface, struct tagMSG *pMsg)
873
{
874
    WebBrowser *This = impl_from_IOleControl(iface);
875 876
    FIXME("(%p)->(%p)\n", This, pMsg);
    return E_NOTIMPL;
877 878
}

879
static HRESULT WINAPI OleControl_OnAmbientPropertyChange(IOleControl *iface, DISPID dispID)
880
{
881
    WebBrowser *This = impl_from_IOleControl(iface);
882 883 884 885

    TRACE("(%p)->(%d)\n", This, dispID);

    switch(dispID) {
886
    case DISPID_UNKNOWN:
887
        /* Unknown means multiple properties changed, so check them all.
888
         * BUT the Webbrowser OleControl object doesn't appear to do this.
889
         */
890
        return S_OK;
891 892
    case DISPID_AMBIENT_DLCONTROL:
        return S_OK;
893 894
    case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED:
        return on_offlineconnected_change(This);
895 896 897 898 899
    case DISPID_AMBIENT_SILENT:
        return on_silent_change(This);
    }

    FIXME("Unknown dispID %d\n", dispID);
900
    return E_NOTIMPL;
901 902
}

903
static HRESULT WINAPI OleControl_FreezeEvents(IOleControl *iface, BOOL bFreeze)
904
{
905
    WebBrowser *This = impl_from_IOleControl(iface);
906 907
    FIXME("(%p)->(%x)\n", This, bFreeze);
    return E_NOTIMPL;
908 909
}

910
static const IOleControlVtbl OleControlVtbl =
911
{
912 913 914 915 916 917 918
    OleControl_QueryInterface,
    OleControl_AddRef,
    OleControl_Release,
    OleControl_GetControlInfo,
    OleControl_OnMnemonic,
    OleControl_OnAmbientPropertyChange,
    OleControl_FreezeEvents
919 920
};

921 922
static inline WebBrowser *impl_from_IOleInPlaceActiveObject(IOleInPlaceActiveObject *iface)
{
923
    return CONTAINING_RECORD(iface, WebBrowser, IOleInPlaceActiveObject_iface);
924
}
925 926

static HRESULT WINAPI InPlaceActiveObject_QueryInterface(IOleInPlaceActiveObject *iface,
927
        REFIID riid, void **ppv)
928
{
929
    WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
930
    return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppv);
931 932 933 934
}

static ULONG WINAPI InPlaceActiveObject_AddRef(IOleInPlaceActiveObject *iface)
{
935
    WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
936
    return IWebBrowser2_AddRef(&This->IWebBrowser2_iface);
937 938 939 940
}

static ULONG WINAPI InPlaceActiveObject_Release(IOleInPlaceActiveObject *iface)
{
941
    WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
942
    return IWebBrowser2_Release(&This->IWebBrowser2_iface);
943 944 945 946 947
}

static HRESULT WINAPI InPlaceActiveObject_GetWindow(IOleInPlaceActiveObject *iface,
                                                    HWND *phwnd)
{
948 949
    WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
    return IOleInPlaceObject_GetWindow(&This->IOleInPlaceObject_iface, phwnd);
950 951 952 953 954
}

static HRESULT WINAPI InPlaceActiveObject_ContextSensitiveHelp(IOleInPlaceActiveObject *iface,
                                                               BOOL fEnterMode)
{
955 956
    WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
    return IOleInPlaceObject_ContextSensitiveHelp(&This->IOleInPlaceObject_iface, fEnterMode);
957 958 959 960 961
}

static HRESULT WINAPI InPlaceActiveObject_TranslateAccelerator(IOleInPlaceActiveObject *iface,
                                                               LPMSG lpmsg)
{
962
    WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980
    IOleInPlaceActiveObject *activeobj;
    HRESULT hr = S_FALSE;

    TRACE("(%p)->(%p)\n", This, lpmsg);

    if(This->doc_host.document) {
        if(SUCCEEDED(IUnknown_QueryInterface(This->doc_host.document,
                                             &IID_IOleInPlaceActiveObject,
                                             (void**)&activeobj))) {
            hr = IOleInPlaceActiveObject_TranslateAccelerator(activeobj, lpmsg);
            IOleInPlaceActiveObject_Release(activeobj);
        }
    }

    if(SUCCEEDED(hr))
        return hr;
    else
        return S_FALSE;
981 982 983 984 985
}

static HRESULT WINAPI InPlaceActiveObject_OnFrameWindowActivate(IOleInPlaceActiveObject *iface,
                                                                BOOL fActivate)
{
986
    WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
987 988 989 990 991 992 993
    FIXME("(%p)->(%x)\n", This, fActivate);
    return E_NOTIMPL;
}

static HRESULT WINAPI InPlaceActiveObject_OnDocWindowActivate(IOleInPlaceActiveObject *iface,
                                                              BOOL fActivate)
{
994
    WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
995 996 997 998 999 1000 1001
    FIXME("(%p)->(%x)\n", This, fActivate);
    return E_NOTIMPL;
}

static HRESULT WINAPI InPlaceActiveObject_ResizeBorder(IOleInPlaceActiveObject *iface,
        LPCRECT lprcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fFrameWindow)
{
1002
    WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
1003 1004 1005 1006 1007 1008 1009
    FIXME("(%p)->(%p %p %x)\n", This, lprcBorder, pUIWindow, fFrameWindow);
    return E_NOTIMPL;
}

static HRESULT WINAPI InPlaceActiveObject_EnableModeless(IOleInPlaceActiveObject *iface,
                                                         BOOL fEnable)
{
1010
    WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
    FIXME("(%p)->(%x)\n", This, fEnable);
    return E_NOTIMPL;
}

static const IOleInPlaceActiveObjectVtbl OleInPlaceActiveObjectVtbl = {
    InPlaceActiveObject_QueryInterface,
    InPlaceActiveObject_AddRef,
    InPlaceActiveObject_Release,
    InPlaceActiveObject_GetWindow,
    InPlaceActiveObject_ContextSensitiveHelp,
    InPlaceActiveObject_TranslateAccelerator,
    InPlaceActiveObject_OnFrameWindowActivate,
    InPlaceActiveObject_OnDocWindowActivate,
    InPlaceActiveObject_ResizeBorder,
    InPlaceActiveObject_EnableModeless
};

1028 1029
static inline WebBrowser *impl_from_IOleCommandTarget(IOleCommandTarget *iface)
{
1030
    return CONTAINING_RECORD(iface, WebBrowser, IOleCommandTarget_iface);
1031
}
1032 1033 1034 1035

static HRESULT WINAPI WBOleCommandTarget_QueryInterface(IOleCommandTarget *iface,
        REFIID riid, void **ppv)
{
1036
    WebBrowser *This = impl_from_IOleCommandTarget(iface);
1037
    return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppv);
1038 1039 1040 1041
}

static ULONG WINAPI WBOleCommandTarget_AddRef(IOleCommandTarget *iface)
{
1042
    WebBrowser *This = impl_from_IOleCommandTarget(iface);
1043
    return IWebBrowser2_AddRef(&This->IWebBrowser2_iface);
1044 1045 1046 1047
}

static ULONG WINAPI WBOleCommandTarget_Release(IOleCommandTarget *iface)
{
1048
    WebBrowser *This = impl_from_IOleCommandTarget(iface);
1049
    return IWebBrowser2_Release(&This->IWebBrowser2_iface);
1050 1051 1052 1053 1054
}

static HRESULT WINAPI WBOleCommandTarget_QueryStatus(IOleCommandTarget *iface,
        const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
{
1055
    WebBrowser *This = impl_from_IOleCommandTarget(iface);
1056 1057 1058 1059
    IOleCommandTarget *cmdtrg;
    HRESULT hres;

    TRACE("(%p)->(%s %u %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds,
1060
          pCmdText);
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075

    if(!This->doc_host.document)
        return 0x80040104;

    /* NOTE: There are probably some commands that we should handle here
     * instead of forwarding to document object. */

    hres = IUnknown_QueryInterface(This->doc_host.document, &IID_IOleCommandTarget, (void**)&cmdtrg);
    if(FAILED(hres))
        return hres;

    hres = IOleCommandTarget_QueryStatus(cmdtrg, pguidCmdGroup, cCmds, prgCmds, pCmdText);
    IOleCommandTarget_Release(cmdtrg);

    return hres;
1076 1077 1078 1079 1080 1081
}

static HRESULT WINAPI WBOleCommandTarget_Exec(IOleCommandTarget *iface,
        const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn,
        VARIANT *pvaOut)
{
1082
    WebBrowser *This = impl_from_IOleCommandTarget(iface);
1083
    FIXME("(%p)->(%s %d %d %p %p)\n", This, debugstr_guid(pguidCmdGroup), nCmdID,
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
          nCmdexecopt, pvaIn, pvaOut);
    return E_NOTIMPL;
}

static const IOleCommandTargetVtbl OleCommandTargetVtbl = {
    WBOleCommandTarget_QueryInterface,
    WBOleCommandTarget_AddRef,
    WBOleCommandTarget_Release,
    WBOleCommandTarget_QueryStatus,
    WBOleCommandTarget_Exec
};

1096 1097
void WebBrowser_OleObject_Init(WebBrowser *This)
{
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107
    DWORD dpi_x;
    DWORD dpi_y;
    HDC hdc;

    /* default aspect ratio is 96dpi / 96dpi */
    hdc = GetDC(0);
    dpi_x = GetDeviceCaps(hdc, LOGPIXELSX);
    dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
    ReleaseDC(0, hdc);

1108 1109 1110 1111 1112
    This->IOleObject_iface.lpVtbl              = &OleObjectVtbl;
    This->IOleInPlaceObject_iface.lpVtbl       = &OleInPlaceObjectVtbl;
    This->IOleControl_iface.lpVtbl             = &OleControlVtbl;
    This->IOleInPlaceActiveObject_iface.lpVtbl = &OleInPlaceActiveObjectVtbl;
    This->IOleCommandTarget_iface.lpVtbl       = &OleCommandTargetVtbl;
1113

1114 1115 1116
    /* Default size is 50x20 pixels, in himetric units */
    This->extent.cx = MulDiv( 50, 2540, dpi_x );
    This->extent.cy = MulDiv( 20, 2540, dpi_y );
1117 1118 1119 1120
}

void WebBrowser_OleObject_Destroy(WebBrowser *This)
{
1121
    release_client_site(This);
1122
}