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