amstream: COM cleanup for the IMediaStreamFilter iface.
[wine] / dlls / ieframe / oleobject.c
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 LRESULT WINAPI shell_embedding_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
53 {
54     WebBrowser *This;
55
56     static const WCHAR wszTHIS[] = {'T','H','I','S',0};
57
58     if(msg == WM_CREATE) {
59         This = *(WebBrowser**)lParam;
60         SetPropW(hwnd, wszTHIS, This);
61     }else {
62         This = GetPropW(hwnd, wszTHIS);
63     }
64
65     switch(msg) {
66     case WM_SIZE:
67         return resize_window(This, LOWORD(lParam), HIWORD(lParam));
68     case WM_DOCHOSTTASK:
69         return process_dochost_tasks(&This->doc_host);
70     }
71
72     return DefWindowProcW(hwnd, msg, wParam, lParam);
73 }
74
75 static void create_shell_embedding_hwnd(WebBrowser *This)
76 {
77     IOleInPlaceSite *inplace;
78     HWND parent = NULL;
79     HRESULT hres;
80
81     static const WCHAR wszShellEmbedding[] =
82         {'S','h','e','l','l',' ','E','m','b','e','d','d','i','n','g',0};
83
84     if(!shell_embedding_atom) {
85         static WNDCLASSEXW wndclass = {
86             sizeof(wndclass),
87             CS_DBLCLKS,
88             shell_embedding_proc,
89             0, 0 /* native uses 8 */, NULL, NULL, NULL,
90             (HBRUSH)(COLOR_WINDOW + 1), NULL,
91             wszShellEmbedding,
92             NULL
93         };
94         wndclass.hInstance = ieframe_instance;
95
96         RegisterClassExW(&wndclass);
97     }
98
99     hres = IOleClientSite_QueryInterface(This->client, &IID_IOleInPlaceSite, (void**)&inplace);
100     if(SUCCEEDED(hres)) {
101         IOleInPlaceSite_GetWindow(inplace, &parent);
102         IOleInPlaceSite_Release(inplace);
103     }
104
105     This->doc_host.frame_hwnd = This->shell_embedding_hwnd = CreateWindowExW(
106             WS_EX_WINDOWEDGE,
107             wszShellEmbedding, wszShellEmbedding,
108             WS_CLIPSIBLINGS | WS_CLIPCHILDREN
109             | (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     HRESULT hres;
120
121     if(This->inplace)
122         return S_OK;
123
124     if(!active_site)
125         return E_INVALIDARG;
126
127     hres = IOleClientSite_QueryInterface(active_site, &IID_IOleInPlaceSite,
128                                          (void**)&This->inplace);
129     if(FAILED(hres)) {
130         WARN("Could not get IOleInPlaceSite\n");
131         return hres;
132     }
133
134     hres = IOleInPlaceSite_CanInPlaceActivate(This->inplace);
135     if(hres != S_OK) {
136         WARN("CanInPlaceActivate returned: %08x\n", hres);
137         IOleInPlaceSite_Release(This->inplace);
138         This->inplace = NULL;
139         return E_FAIL;
140     }
141
142     hres = IOleInPlaceSite_GetWindow(This->inplace, &parent_hwnd);
143     if(SUCCEEDED(hres))
144         SHSetParentHwnd(This->shell_embedding_hwnd, parent_hwnd);
145
146     IOleInPlaceSite_OnInPlaceActivate(This->inplace);
147
148     This->frameinfo.cb = sizeof(OLEINPLACEFRAMEINFO);
149     IOleInPlaceSite_GetWindowContext(This->inplace, &This->doc_host.frame, &This->uiwindow,
150                                      &This->pos_rect, &This->clip_rect,
151                                      &This->frameinfo);
152
153     SetWindowPos(This->shell_embedding_hwnd, NULL,
154                  This->pos_rect.left, This->pos_rect.top,
155                  This->pos_rect.right-This->pos_rect.left,
156                  This->pos_rect.bottom-This->pos_rect.top,
157                  SWP_NOZORDER | SWP_SHOWWINDOW);
158
159     if(This->client) {
160         IOleContainer *container;
161
162         IOleClientSite_ShowObject(This->client);
163
164         hres = IOleClientSite_GetContainer(This->client, &container);
165         if(SUCCEEDED(hres)) {
166             if(This->container)
167                 IOleContainer_Release(This->container);
168             This->container = container;
169         }
170     }
171
172     if(This->doc_host.frame)
173         IOleInPlaceFrame_GetWindow(This->doc_host.frame, &This->frame_hwnd);
174
175     return S_OK;
176 }
177
178 static HRESULT activate_ui(WebBrowser *This, IOleClientSite *active_site)
179 {
180     HRESULT hres;
181
182     static const WCHAR wszitem[] = {'i','t','e','m',0};
183
184     if(This->inplace)
185     {
186         if(This->shell_embedding_hwnd)
187             ShowWindow(This->shell_embedding_hwnd, SW_SHOW);
188         return S_OK;
189     }
190
191     hres = activate_inplace(This, active_site);
192     if(FAILED(hres))
193         return hres;
194
195     IOleInPlaceSite_OnUIActivate(This->inplace);
196
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     if(This->doc_host.frame)
203         IOleInPlaceFrame_SetMenu(This->doc_host.frame, NULL, NULL, This->shell_embedding_hwnd);
204
205     SetFocus(This->shell_embedding_hwnd);
206
207     return S_OK;
208 }
209
210 static HRESULT get_client_disp_property(IOleClientSite *client, DISPID dispid, VARIANT *res)
211 {
212     IDispatch *disp = NULL;
213     DISPPARAMS dispparams = {NULL, 0};
214     HRESULT hres;
215
216     VariantInit(res);
217
218     if(!client)
219         return S_OK;
220
221     hres = IOleClientSite_QueryInterface(client, &IID_IDispatch, (void**)&disp);
222     if(FAILED(hres)) {
223         TRACE("Could not get IDispatch\n");
224         return hres;
225     }
226
227     hres = IDispatch_Invoke(disp, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT,
228             DISPATCH_PROPERTYGET, &dispparams, res, NULL, NULL);
229
230     IDispatch_Release(disp);
231
232     return hres;
233 }
234
235 static HRESULT on_offlineconnected_change(WebBrowser *This)
236 {
237     VARIANT offline;
238
239     get_client_disp_property(This->client, DISPID_AMBIENT_OFFLINEIFNOTCONNECTED, &offline);
240
241     if(V_VT(&offline) == VT_BOOL)
242         IWebBrowser2_put_Offline(&This->IWebBrowser2_iface, V_BOOL(&offline));
243     else if(V_VT(&offline) != VT_EMPTY)
244         WARN("wrong V_VT(silent) %d\n", V_VT(&offline));
245
246     return S_OK;
247 }
248
249 static HRESULT on_silent_change(WebBrowser *This)
250 {
251     VARIANT silent;
252
253     get_client_disp_property(This->client, DISPID_AMBIENT_SILENT, &silent);
254
255     if(V_VT(&silent) == VT_BOOL)
256         IWebBrowser2_put_Silent(&This->IWebBrowser2_iface, V_BOOL(&silent));
257     else if(V_VT(&silent) != VT_EMPTY)
258         WARN("wrong V_VT(silent) %d\n", V_VT(&silent));
259
260     return S_OK;
261 }
262
263 static void release_client_site(WebBrowser *This)
264 {
265     release_dochost_client(&This->doc_host);
266
267     if(This->shell_embedding_hwnd) {
268         DestroyWindow(This->shell_embedding_hwnd);
269         This->shell_embedding_hwnd = NULL;
270     }
271
272     if(This->inplace) {
273         IOleInPlaceSite_Release(This->inplace);
274         This->inplace = NULL;
275     }
276
277     if(This->container) {
278         IOleContainer_Release(This->container);
279         This->container = NULL;
280     }
281
282     if(This->uiwindow) {
283         IOleInPlaceUIWindow_Release(This->uiwindow);
284         This->uiwindow = NULL;
285     }
286
287     if(This->client) {
288         IOleClientSite_Release(This->client);
289         This->client = NULL;
290     }
291 }
292
293 /**********************************************************************
294  * Implement the IOleObject interface for the WebBrowser control
295  */
296
297 static inline WebBrowser *impl_from_IOleObject(IOleObject *iface)
298 {
299     return CONTAINING_RECORD(iface, WebBrowser, IOleObject_iface);
300 }
301
302 static HRESULT WINAPI OleObject_QueryInterface(IOleObject *iface, REFIID riid, void **ppv)
303 {
304     WebBrowser *This = impl_from_IOleObject(iface);
305     return IWebBrowser_QueryInterface(&This->IWebBrowser2_iface, riid, ppv);
306 }
307
308 static ULONG WINAPI OleObject_AddRef(IOleObject *iface)
309 {
310     WebBrowser *This = impl_from_IOleObject(iface);
311     return IWebBrowser_AddRef(&This->IWebBrowser2_iface);
312 }
313
314 static ULONG WINAPI OleObject_Release(IOleObject *iface)
315 {
316     WebBrowser *This = impl_from_IOleObject(iface);
317     return IWebBrowser_Release(&This->IWebBrowser2_iface);
318 }
319
320 static HRESULT WINAPI OleObject_SetClientSite(IOleObject *iface, LPOLECLIENTSITE pClientSite)
321 {
322     WebBrowser *This = impl_from_IOleObject(iface);
323     IDocHostUIHandler *hostui;
324     IOleContainer *container;
325     IDispatch *disp;
326     HRESULT hres;
327
328     TRACE("(%p)->(%p)\n", This, pClientSite);
329
330     if(This->client == pClientSite)
331         return S_OK;
332
333     release_client_site(This);
334
335     if(!pClientSite) {
336         if(This->doc_host.document)
337             deactivate_document(&This->doc_host);
338         return S_OK;
339     }
340
341     IOleClientSite_AddRef(pClientSite);
342     This->client = pClientSite;
343
344     hres = IOleClientSite_QueryInterface(This->client, &IID_IDispatch,
345             (void**)&disp);
346     if(SUCCEEDED(hres))
347         This->doc_host.client_disp = disp;
348
349     hres = IOleClientSite_QueryInterface(This->client, &IID_IDocHostUIHandler,
350             (void**)&hostui);
351     if(SUCCEEDED(hres))
352         This->doc_host.hostui = hostui;
353
354     hres = IOleClientSite_GetContainer(This->client, &container);
355     if(SUCCEEDED(hres)) {
356         ITargetContainer *target_container;
357
358         hres = IOleContainer_QueryInterface(container, &IID_ITargetContainer,
359                                             (void**)&target_container);
360         if(SUCCEEDED(hres)) {
361             FIXME("Unsupported ITargetContainer\n");
362             ITargetContainer_Release(target_container);
363         }
364
365         IOleContainer_Release(container);
366     }
367
368     create_shell_embedding_hwnd(This);
369
370     on_offlineconnected_change(This);
371     on_silent_change(This);
372
373     return S_OK;
374 }
375
376 static HRESULT WINAPI OleObject_GetClientSite(IOleObject *iface, LPOLECLIENTSITE *ppClientSite)
377 {
378     WebBrowser *This = impl_from_IOleObject(iface);
379
380     TRACE("(%p)->(%p)\n", This, ppClientSite);
381
382     if(!ppClientSite)
383         return E_INVALIDARG;
384
385     if(This->client)
386         IOleClientSite_AddRef(This->client);
387     *ppClientSite = This->client;
388
389     return S_OK;
390 }
391
392 static HRESULT WINAPI OleObject_SetHostNames(IOleObject *iface, LPCOLESTR szContainerApp,
393         LPCOLESTR szContainerObj)
394 {
395     WebBrowser *This = impl_from_IOleObject(iface);
396
397     TRACE("(%p)->(%s, %s)\n", This, debugstr_w(szContainerApp), debugstr_w(szContainerObj));
398
399     /* We have nothing to do here. */
400     return S_OK;
401 }
402
403 static HRESULT WINAPI OleObject_Close(IOleObject *iface, DWORD dwSaveOption)
404 {
405     WebBrowser *This = impl_from_IOleObject(iface);
406
407     TRACE("(%p)->(%d)\n", This, dwSaveOption);
408
409     if(dwSaveOption != OLECLOSE_NOSAVE) {
410         FIXME("unimplemnted flag: %x\n", dwSaveOption);
411         return E_NOTIMPL;
412     }
413
414     if(This->doc_host.frame)
415         IOleInPlaceFrame_SetActiveObject(This->doc_host.frame, NULL, NULL);
416
417     if(This->uiwindow)
418         IOleInPlaceUIWindow_SetActiveObject(This->uiwindow, NULL, NULL);
419
420     if(This->inplace) {
421         IOleInPlaceSite_OnUIDeactivate(This->inplace, FALSE);
422         IOleInPlaceSite_OnInPlaceDeactivate(This->inplace);
423     }
424
425     return IOleObject_SetClientSite(iface, NULL);
426 }
427
428 static HRESULT WINAPI OleObject_SetMoniker(IOleObject *iface, DWORD dwWhichMoniker, IMoniker* pmk)
429 {
430     WebBrowser *This = impl_from_IOleObject(iface);
431     FIXME("(%p)->(%d, %p)\n", This, dwWhichMoniker, pmk);
432     return E_NOTIMPL;
433 }
434
435 static HRESULT WINAPI OleObject_GetMoniker(IOleObject *iface, DWORD dwAssign,
436         DWORD dwWhichMoniker, LPMONIKER *ppmk)
437 {
438     WebBrowser *This = impl_from_IOleObject(iface);
439     FIXME("(%p)->(%d, %d, %p)\n", This, dwAssign, dwWhichMoniker, ppmk);
440     return E_NOTIMPL;
441 }
442
443 static HRESULT WINAPI OleObject_InitFromData(IOleObject *iface, LPDATAOBJECT pDataObject,
444         BOOL fCreation, DWORD dwReserved)
445 {
446     WebBrowser *This = impl_from_IOleObject(iface);
447     FIXME("(%p)->(%p, %d, %d)\n", This, pDataObject, fCreation, dwReserved);
448     return E_NOTIMPL;
449 }
450
451 static HRESULT WINAPI OleObject_GetClipboardData(IOleObject *iface, DWORD dwReserved,
452         LPDATAOBJECT *ppDataObject)
453 {
454     WebBrowser *This = impl_from_IOleObject(iface);
455     FIXME("(%p)->(%d, %p)\n", This, dwReserved, ppDataObject);
456     return E_NOTIMPL;
457 }
458
459 static HRESULT WINAPI OleObject_DoVerb(IOleObject *iface, LONG iVerb, struct tagMSG* lpmsg,
460         LPOLECLIENTSITE pActiveSite, LONG lindex, HWND hwndParent, LPCRECT lprcPosRect)
461 {
462     WebBrowser *This = impl_from_IOleObject(iface);
463
464     TRACE("(%p)->(%d %p %p %d %p %p)\n", This, iVerb, lpmsg, pActiveSite, lindex, hwndParent,
465             lprcPosRect);
466
467     switch (iVerb)
468     {
469     case OLEIVERB_SHOW:
470         TRACE("OLEIVERB_SHOW\n");
471         return activate_ui(This, pActiveSite);
472     case OLEIVERB_UIACTIVATE:
473         TRACE("OLEIVERB_UIACTIVATE\n");
474         return activate_ui(This, pActiveSite);
475     case OLEIVERB_INPLACEACTIVATE:
476         TRACE("OLEIVERB_INPLACEACTIVATE\n");
477         return activate_inplace(This, pActiveSite);
478     case OLEIVERB_HIDE:
479         TRACE("OLEIVERB_HIDE\n");
480         if(This->shell_embedding_hwnd)
481             ShowWindow(This->shell_embedding_hwnd, SW_HIDE);
482         return S_OK;
483     default:
484         FIXME("stub for %d\n", iVerb);
485         break;
486     }
487
488     return E_NOTIMPL;
489 }
490
491 static HRESULT WINAPI OleObject_EnumVerbs(IOleObject *iface, IEnumOLEVERB **ppEnumOleVerb)
492 {
493     WebBrowser *This = impl_from_IOleObject(iface);
494     TRACE("(%p)->(%p)\n", This, ppEnumOleVerb);
495     return OleRegEnumVerbs(&CLSID_WebBrowser, ppEnumOleVerb);
496 }
497
498 static HRESULT WINAPI OleObject_Update(IOleObject *iface)
499 {
500     WebBrowser *This = impl_from_IOleObject(iface);
501     FIXME("(%p)\n", This);
502     return E_NOTIMPL;
503 }
504
505 static HRESULT WINAPI OleObject_IsUpToDate(IOleObject *iface)
506 {
507     WebBrowser *This = impl_from_IOleObject(iface);
508     FIXME("(%p)\n", This);
509     return E_NOTIMPL;
510 }
511
512 static HRESULT WINAPI OleObject_GetUserClassID(IOleObject *iface, CLSID* pClsid)
513 {
514     WebBrowser *This = impl_from_IOleObject(iface);
515     FIXME("(%p)->(%p)\n", This, pClsid);
516     return E_NOTIMPL;
517 }
518
519 static HRESULT WINAPI OleObject_GetUserType(IOleObject *iface, DWORD dwFormOfType,
520         LPOLESTR* pszUserType)
521 {
522     WebBrowser *This = impl_from_IOleObject(iface);
523     TRACE("(%p, %d, %p)\n", This, dwFormOfType, pszUserType);
524     return OleRegGetUserType(&CLSID_WebBrowser, dwFormOfType, pszUserType);
525 }
526
527 static HRESULT WINAPI OleObject_SetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel)
528 {
529     WebBrowser *This = impl_from_IOleObject(iface);
530
531     TRACE("(%p)->(%x %p)\n", This, dwDrawAspect, psizel);
532
533     /* Tests show that dwDrawAspect is ignored */
534     This->extent = *psizel;
535     return S_OK;
536 }
537
538 static HRESULT WINAPI OleObject_GetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel)
539 {
540     WebBrowser *This = impl_from_IOleObject(iface);
541
542     TRACE("(%p)->(%x, %p)\n", This, dwDrawAspect, psizel);
543
544     /* Tests show that dwDrawAspect is ignored */
545     *psizel = This->extent;
546     return S_OK;
547 }
548
549 static HRESULT WINAPI OleObject_Advise(IOleObject *iface, IAdviseSink *pAdvSink,
550         DWORD* pdwConnection)
551 {
552     WebBrowser *This = impl_from_IOleObject(iface);
553     FIXME("(%p)->(%p, %p)\n", This, pAdvSink, pdwConnection);
554     return E_NOTIMPL;
555 }
556
557 static HRESULT WINAPI OleObject_Unadvise(IOleObject *iface, DWORD dwConnection)
558 {
559     WebBrowser *This = impl_from_IOleObject(iface);
560     FIXME("(%p)->(%d)\n", This, dwConnection);
561     return E_NOTIMPL;
562 }
563
564 static HRESULT WINAPI OleObject_EnumAdvise(IOleObject *iface, IEnumSTATDATA **ppenumAdvise)
565 {
566     WebBrowser *This = impl_from_IOleObject(iface);
567     FIXME("(%p)->(%p)\n", This, ppenumAdvise);
568     return S_OK;
569 }
570
571 static HRESULT WINAPI OleObject_GetMiscStatus(IOleObject *iface, DWORD dwAspect, DWORD *pdwStatus)
572 {
573     WebBrowser *This = impl_from_IOleObject(iface);
574
575     TRACE("(%p)->(%x, %p)\n", This, dwAspect, pdwStatus);
576
577     *pdwStatus = OLEMISC_SETCLIENTSITEFIRST|OLEMISC_ACTIVATEWHENVISIBLE|OLEMISC_INSIDEOUT
578         |OLEMISC_CANTLINKINSIDE|OLEMISC_RECOMPOSEONRESIZE;
579
580     return S_OK;
581 }
582
583 static HRESULT WINAPI OleObject_SetColorScheme(IOleObject *iface, LOGPALETTE* pLogpal)
584 {
585     WebBrowser *This = impl_from_IOleObject(iface);
586     FIXME("(%p)->(%p)\n", This, pLogpal);
587     return E_NOTIMPL;
588 }
589
590 static const IOleObjectVtbl OleObjectVtbl =
591 {
592     OleObject_QueryInterface,
593     OleObject_AddRef,
594     OleObject_Release,
595     OleObject_SetClientSite,
596     OleObject_GetClientSite,
597     OleObject_SetHostNames,
598     OleObject_Close,
599     OleObject_SetMoniker,
600     OleObject_GetMoniker,
601     OleObject_InitFromData,
602     OleObject_GetClipboardData,
603     OleObject_DoVerb,
604     OleObject_EnumVerbs,
605     OleObject_Update,
606     OleObject_IsUpToDate,
607     OleObject_GetUserClassID,
608     OleObject_GetUserType,
609     OleObject_SetExtent,
610     OleObject_GetExtent,
611     OleObject_Advise,
612     OleObject_Unadvise,
613     OleObject_EnumAdvise,
614     OleObject_GetMiscStatus,
615     OleObject_SetColorScheme
616 };
617
618 /**********************************************************************
619  * Implement the IOleInPlaceObject interface
620  */
621
622 static inline WebBrowser *impl_from_IOleInPlaceObject(IOleInPlaceObject *iface)
623 {
624     return CONTAINING_RECORD(iface, WebBrowser, IOleInPlaceObject_iface);
625 }
626
627 static HRESULT WINAPI OleInPlaceObject_QueryInterface(IOleInPlaceObject *iface,
628         REFIID riid, LPVOID *ppobj)
629 {
630     WebBrowser *This = impl_from_IOleInPlaceObject(iface);
631     return IWebBrowser_QueryInterface(&This->IWebBrowser2_iface, riid, ppobj);
632 }
633
634 static ULONG WINAPI OleInPlaceObject_AddRef(IOleInPlaceObject *iface)
635 {
636     WebBrowser *This = impl_from_IOleInPlaceObject(iface);
637     return IWebBrowser_AddRef(&This->IWebBrowser2_iface);
638 }
639
640 static ULONG WINAPI OleInPlaceObject_Release(IOleInPlaceObject *iface)
641 {
642     WebBrowser *This = impl_from_IOleInPlaceObject(iface);
643     return IWebBrowser_Release(&This->IWebBrowser2_iface);
644 }
645
646 static HRESULT WINAPI OleInPlaceObject_GetWindow(IOleInPlaceObject *iface, HWND* phwnd)
647 {
648     WebBrowser *This = impl_from_IOleInPlaceObject(iface);
649
650     TRACE("(%p)->(%p)\n", This, phwnd);
651
652     *phwnd = This->shell_embedding_hwnd;
653     return S_OK;
654 }
655
656 static HRESULT WINAPI OleInPlaceObject_ContextSensitiveHelp(IOleInPlaceObject *iface,
657         BOOL fEnterMode)
658 {
659     WebBrowser *This = impl_from_IOleInPlaceObject(iface);
660     FIXME("(%p)->(%x)\n", This, fEnterMode);
661     return E_NOTIMPL;
662 }
663
664 static HRESULT WINAPI OleInPlaceObject_InPlaceDeactivate(IOleInPlaceObject *iface)
665 {
666     WebBrowser *This = impl_from_IOleInPlaceObject(iface);
667     FIXME("(%p)\n", This);
668
669     if(This->inplace) {
670         IOleInPlaceSite_Release(This->inplace);
671         This->inplace = NULL;
672     }
673
674     return S_OK;
675 }
676
677 static HRESULT WINAPI OleInPlaceObject_UIDeactivate(IOleInPlaceObject *iface)
678 {
679     WebBrowser *This = impl_from_IOleInPlaceObject(iface);
680     FIXME("(%p)\n", This);
681     return E_NOTIMPL;
682 }
683
684 static HRESULT WINAPI OleInPlaceObject_SetObjectRects(IOleInPlaceObject *iface,
685         LPCRECT lprcPosRect, LPCRECT lprcClipRect)
686 {
687     WebBrowser *This = impl_from_IOleInPlaceObject(iface);
688
689     TRACE("(%p)->(%p %p)\n", This, lprcPosRect, lprcClipRect);
690
691     This->pos_rect = *lprcPosRect;
692
693     if(lprcClipRect)
694         This->clip_rect = *lprcClipRect;
695
696     if(This->shell_embedding_hwnd) {
697         SetWindowPos(This->shell_embedding_hwnd, NULL,
698                      lprcPosRect->left, lprcPosRect->top,
699                      lprcPosRect->right-lprcPosRect->left,
700                      lprcPosRect->bottom-lprcPosRect->top,
701                      SWP_NOZORDER | SWP_NOACTIVATE);
702     }
703
704     return S_OK;
705 }
706
707 static HRESULT WINAPI OleInPlaceObject_ReactivateAndUndo(IOleInPlaceObject *iface)
708 {
709     WebBrowser *This = impl_from_IOleInPlaceObject(iface);
710     FIXME("(%p)\n", This);
711     return E_NOTIMPL;
712 }
713
714 static const IOleInPlaceObjectVtbl OleInPlaceObjectVtbl =
715 {
716     OleInPlaceObject_QueryInterface,
717     OleInPlaceObject_AddRef,
718     OleInPlaceObject_Release,
719     OleInPlaceObject_GetWindow,
720     OleInPlaceObject_ContextSensitiveHelp,
721     OleInPlaceObject_InPlaceDeactivate,
722     OleInPlaceObject_UIDeactivate,
723     OleInPlaceObject_SetObjectRects,
724     OleInPlaceObject_ReactivateAndUndo
725 };
726
727 /**********************************************************************
728  * Implement the IOleControl interface
729  */
730
731 static inline WebBrowser *impl_from_IOleControl(IOleControl *iface)
732 {
733     return CONTAINING_RECORD(iface, WebBrowser, IOleControl_iface);
734 }
735
736 static HRESULT WINAPI OleControl_QueryInterface(IOleControl *iface,
737         REFIID riid, LPVOID *ppobj)
738 {
739     WebBrowser *This = impl_from_IOleControl(iface);
740     return IWebBrowser_QueryInterface(&This->IWebBrowser2_iface, riid, ppobj);
741 }
742
743 static ULONG WINAPI OleControl_AddRef(IOleControl *iface)
744 {
745     WebBrowser *This = impl_from_IOleControl(iface);
746     return IWebBrowser_AddRef(&This->IWebBrowser2_iface);
747 }
748
749 static ULONG WINAPI OleControl_Release(IOleControl *iface)
750 {
751     WebBrowser *This = impl_from_IOleControl(iface);
752     return IWebBrowser_Release(&This->IWebBrowser2_iface);
753 }
754
755 static HRESULT WINAPI OleControl_GetControlInfo(IOleControl *iface, LPCONTROLINFO pCI)
756 {
757     WebBrowser *This = impl_from_IOleControl(iface);
758
759     TRACE("(%p)->(%p)\n", This, pCI);
760
761     /* Tests show that this function should be not implemented */
762     return E_NOTIMPL;
763 }
764
765 static HRESULT WINAPI OleControl_OnMnemonic(IOleControl *iface, struct tagMSG *pMsg)
766 {
767     WebBrowser *This = impl_from_IOleControl(iface);
768     FIXME("(%p)->(%p)\n", This, pMsg);
769     return E_NOTIMPL;
770 }
771
772 static HRESULT WINAPI OleControl_OnAmbientPropertyChange(IOleControl *iface, DISPID dispID)
773 {
774     WebBrowser *This = impl_from_IOleControl(iface);
775
776     TRACE("(%p)->(%d)\n", This, dispID);
777
778     switch(dispID) {
779     case DISPID_UNKNOWN:
780         /* Unknown means multiple properties changed, so check them all.
781          * BUT the Webbrowser OleControl object doesn't appear to do this.
782          */
783         return S_OK;
784     case DISPID_AMBIENT_DLCONTROL:
785         return S_OK;
786     case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED:
787         return on_offlineconnected_change(This);
788     case DISPID_AMBIENT_SILENT:
789         return on_silent_change(This);
790     }
791
792     FIXME("Unknown dispID %d\n", dispID);
793     return E_NOTIMPL;
794 }
795
796 static HRESULT WINAPI OleControl_FreezeEvents(IOleControl *iface, BOOL bFreeze)
797 {
798     WebBrowser *This = impl_from_IOleControl(iface);
799     FIXME("(%p)->(%x)\n", This, bFreeze);
800     return E_NOTIMPL;
801 }
802
803 static const IOleControlVtbl OleControlVtbl =
804 {
805     OleControl_QueryInterface,
806     OleControl_AddRef,
807     OleControl_Release,
808     OleControl_GetControlInfo,
809     OleControl_OnMnemonic,
810     OleControl_OnAmbientPropertyChange,
811     OleControl_FreezeEvents
812 };
813
814 static inline WebBrowser *impl_from_IOleInPlaceActiveObject(IOleInPlaceActiveObject *iface)
815 {
816     return CONTAINING_RECORD(iface, WebBrowser, IOleInPlaceActiveObject_iface);
817 }
818
819 static HRESULT WINAPI InPlaceActiveObject_QueryInterface(IOleInPlaceActiveObject *iface,
820         REFIID riid, void **ppv)
821 {
822     WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
823     return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppv);
824 }
825
826 static ULONG WINAPI InPlaceActiveObject_AddRef(IOleInPlaceActiveObject *iface)
827 {
828     WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
829     return IWebBrowser2_AddRef(&This->IWebBrowser2_iface);
830 }
831
832 static ULONG WINAPI InPlaceActiveObject_Release(IOleInPlaceActiveObject *iface)
833 {
834     WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
835     return IWebBrowser2_Release(&This->IWebBrowser2_iface);
836 }
837
838 static HRESULT WINAPI InPlaceActiveObject_GetWindow(IOleInPlaceActiveObject *iface,
839                                                     HWND *phwnd)
840 {
841     WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
842     return IOleInPlaceObject_GetWindow(&This->IOleInPlaceObject_iface, phwnd);
843 }
844
845 static HRESULT WINAPI InPlaceActiveObject_ContextSensitiveHelp(IOleInPlaceActiveObject *iface,
846                                                                BOOL fEnterMode)
847 {
848     WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
849     return IOleInPlaceObject_ContextSensitiveHelp(&This->IOleInPlaceObject_iface, fEnterMode);
850 }
851
852 static HRESULT WINAPI InPlaceActiveObject_TranslateAccelerator(IOleInPlaceActiveObject *iface,
853                                                                LPMSG lpmsg)
854 {
855     WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
856     IOleInPlaceActiveObject *activeobj;
857     HRESULT hr = S_FALSE;
858
859     TRACE("(%p)->(%p)\n", This, lpmsg);
860
861     if(This->doc_host.document) {
862         if(SUCCEEDED(IUnknown_QueryInterface(This->doc_host.document,
863                                              &IID_IOleInPlaceActiveObject,
864                                              (void**)&activeobj))) {
865             hr = IOleInPlaceActiveObject_TranslateAccelerator(activeobj, lpmsg);
866             IOleInPlaceActiveObject_Release(activeobj);
867         }
868     }
869
870     if(SUCCEEDED(hr))
871         return hr;
872     else
873         return S_FALSE;
874 }
875
876 static HRESULT WINAPI InPlaceActiveObject_OnFrameWindowActivate(IOleInPlaceActiveObject *iface,
877                                                                 BOOL fActivate)
878 {
879     WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
880     FIXME("(%p)->(%x)\n", This, fActivate);
881     return E_NOTIMPL;
882 }
883
884 static HRESULT WINAPI InPlaceActiveObject_OnDocWindowActivate(IOleInPlaceActiveObject *iface,
885                                                               BOOL fActivate)
886 {
887     WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
888     FIXME("(%p)->(%x)\n", This, fActivate);
889     return E_NOTIMPL;
890 }
891
892 static HRESULT WINAPI InPlaceActiveObject_ResizeBorder(IOleInPlaceActiveObject *iface,
893         LPCRECT lprcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fFrameWindow)
894 {
895     WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
896     FIXME("(%p)->(%p %p %x)\n", This, lprcBorder, pUIWindow, fFrameWindow);
897     return E_NOTIMPL;
898 }
899
900 static HRESULT WINAPI InPlaceActiveObject_EnableModeless(IOleInPlaceActiveObject *iface,
901                                                          BOOL fEnable)
902 {
903     WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface);
904     FIXME("(%p)->(%x)\n", This, fEnable);
905     return E_NOTIMPL;
906 }
907
908 static const IOleInPlaceActiveObjectVtbl OleInPlaceActiveObjectVtbl = {
909     InPlaceActiveObject_QueryInterface,
910     InPlaceActiveObject_AddRef,
911     InPlaceActiveObject_Release,
912     InPlaceActiveObject_GetWindow,
913     InPlaceActiveObject_ContextSensitiveHelp,
914     InPlaceActiveObject_TranslateAccelerator,
915     InPlaceActiveObject_OnFrameWindowActivate,
916     InPlaceActiveObject_OnDocWindowActivate,
917     InPlaceActiveObject_ResizeBorder,
918     InPlaceActiveObject_EnableModeless
919 };
920
921 static inline WebBrowser *impl_from_IOleCommandTarget(IOleCommandTarget *iface)
922 {
923     return CONTAINING_RECORD(iface, WebBrowser, IOleCommandTarget_iface);
924 }
925
926 static HRESULT WINAPI WBOleCommandTarget_QueryInterface(IOleCommandTarget *iface,
927         REFIID riid, void **ppv)
928 {
929     WebBrowser *This = impl_from_IOleCommandTarget(iface);
930     return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppv);
931 }
932
933 static ULONG WINAPI WBOleCommandTarget_AddRef(IOleCommandTarget *iface)
934 {
935     WebBrowser *This = impl_from_IOleCommandTarget(iface);
936     return IWebBrowser2_AddRef(&This->IWebBrowser2_iface);
937 }
938
939 static ULONG WINAPI WBOleCommandTarget_Release(IOleCommandTarget *iface)
940 {
941     WebBrowser *This = impl_from_IOleCommandTarget(iface);
942     return IWebBrowser2_Release(&This->IWebBrowser2_iface);
943 }
944
945 static HRESULT WINAPI WBOleCommandTarget_QueryStatus(IOleCommandTarget *iface,
946         const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
947 {
948     WebBrowser *This = impl_from_IOleCommandTarget(iface);
949     IOleCommandTarget *cmdtrg;
950     HRESULT hres;
951
952     TRACE("(%p)->(%s %u %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds,
953           pCmdText);
954
955     if(!This->doc_host.document)
956         return 0x80040104;
957
958     /* NOTE: There are probably some commands that we should handle here
959      * instead of forwarding to document object. */
960
961     hres = IUnknown_QueryInterface(This->doc_host.document, &IID_IOleCommandTarget, (void**)&cmdtrg);
962     if(FAILED(hres))
963         return hres;
964
965     hres = IOleCommandTarget_QueryStatus(cmdtrg, pguidCmdGroup, cCmds, prgCmds, pCmdText);
966     IOleCommandTarget_Release(cmdtrg);
967
968     return hres;
969 }
970
971 static HRESULT WINAPI WBOleCommandTarget_Exec(IOleCommandTarget *iface,
972         const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn,
973         VARIANT *pvaOut)
974 {
975     WebBrowser *This = impl_from_IOleCommandTarget(iface);
976     FIXME("(%p)->(%s %d %d %p %p)\n", This, debugstr_guid(pguidCmdGroup), nCmdID,
977           nCmdexecopt, pvaIn, pvaOut);
978     return E_NOTIMPL;
979 }
980
981 static const IOleCommandTargetVtbl OleCommandTargetVtbl = {
982     WBOleCommandTarget_QueryInterface,
983     WBOleCommandTarget_AddRef,
984     WBOleCommandTarget_Release,
985     WBOleCommandTarget_QueryStatus,
986     WBOleCommandTarget_Exec
987 };
988
989 void WebBrowser_OleObject_Init(WebBrowser *This)
990 {
991     DWORD dpi_x;
992     DWORD dpi_y;
993     HDC hdc;
994
995     /* default aspect ratio is 96dpi / 96dpi */
996     hdc = GetDC(0);
997     dpi_x = GetDeviceCaps(hdc, LOGPIXELSX);
998     dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
999     ReleaseDC(0, hdc);
1000
1001     This->IOleObject_iface.lpVtbl              = &OleObjectVtbl;
1002     This->IOleInPlaceObject_iface.lpVtbl       = &OleInPlaceObjectVtbl;
1003     This->IOleControl_iface.lpVtbl             = &OleControlVtbl;
1004     This->IOleInPlaceActiveObject_iface.lpVtbl = &OleInPlaceActiveObjectVtbl;
1005     This->IOleCommandTarget_iface.lpVtbl       = &OleCommandTargetVtbl;
1006
1007     /* Default size is 50x20 pixels, in himetric units */
1008     This->extent.cx = MulDiv( 50, 2540, dpi_x );
1009     This->extent.cy = MulDiv( 20, 2540, dpi_y );
1010 }
1011
1012 void WebBrowser_OleObject_Destroy(WebBrowser *This)
1013 {
1014     release_client_site(This);
1015 }