xref: /reactos/dll/win32/ieframe/client.c (revision 02e84521)
1 /*
2  * Copyright 2005 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include <stdio.h>
20 
21 #include "ieframe.h"
22 
23 #include "mshtmdid.h"
24 #include "idispids.h"
25 
26 #include "wine/debug.h"
27 
28 WINE_DEFAULT_DEBUG_CHANNEL(ieframe);
29 
30 static inline DocHost *impl_from_IOleClientSite(IOleClientSite *iface)
31 {
32     return CONTAINING_RECORD(iface, DocHost, IOleClientSite_iface);
33 }
34 
35 static HRESULT WINAPI ClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv)
36 {
37     DocHost *This = impl_from_IOleClientSite(iface);
38 
39     if(IsEqualGUID(&IID_IUnknown, riid)) {
40         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
41         *ppv = &This->IOleClientSite_iface;
42     }else if(IsEqualGUID(&IID_IOleClientSite, riid)) {
43         TRACE("(%p)->(IID_IOleClientSite %p)\n", This, ppv);
44         *ppv = &This->IOleClientSite_iface;
45     }else if(IsEqualGUID(&IID_IOleWindow, riid)) {
46         TRACE("(%p)->(IID_IOleWindow %p)\n", This, ppv);
47         *ppv = &This->IOleInPlaceSiteEx_iface;
48     }else if(IsEqualGUID(&IID_IOleInPlaceSite, riid)) {
49         TRACE("(%p)->(IID_IOleInPlaceSite %p)\n", This, ppv);
50         *ppv = &This->IOleInPlaceSiteEx_iface;
51     }else if(IsEqualGUID(&IID_IOleInPlaceSiteEx, riid)) {
52         TRACE("(%p)->(IID_IOleInPlaceSiteEx %p)\n", This, ppv);
53         *ppv = &This->IOleInPlaceSiteEx_iface;
54     }else if(IsEqualGUID(&IID_IDocHostUIHandler, riid)) {
55         TRACE("(%p)->(IID_IDocHostUIHandler %p)\n", This, ppv);
56         *ppv = &This->IDocHostUIHandler2_iface;
57     }else if(IsEqualGUID(&IID_IDocHostUIHandler2, riid)) {
58         TRACE("(%p)->(IID_IDocHostUIHandler2 %p)\n", This, ppv);
59         *ppv = &This->IDocHostUIHandler2_iface;
60     }else if(IsEqualGUID(&IID_IOleDocumentSite, riid)) {
61         TRACE("(%p)->(IID_IOleDocumentSite %p)\n", This, ppv);
62         *ppv = &This->IOleDocumentSite_iface;
63     }else if(IsEqualGUID(&IID_IOleControlSite, riid)) {
64         TRACE("(%p)->(IID_IOleControlSite %p)\n", This, ppv);
65         *ppv = &This->IOleControlSite_iface;
66     }else if(IsEqualGUID(&IID_IOleCommandTarget, riid)) {
67         TRACE("(%p)->(IID_IOleCommandTarget %p)\n", This, ppv);
68         *ppv = &This->IOleCommandTarget_iface;
69     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
70         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
71         *ppv = &This->IDispatch_iface;
72     }else if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) {
73         TRACE("(%p)->(IID_IPropertyNotifySink %p)\n", This, ppv);
74         *ppv = &This->IPropertyNotifySink_iface;
75     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
76         TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
77         *ppv = &This->IServiceProvider_iface;
78     }else {
79         *ppv = NULL;
80         WARN("Unsupported interface %s\n", debugstr_guid(riid));
81         return E_NOINTERFACE;
82     }
83 
84     IUnknown_AddRef((IUnknown*)*ppv);
85     return S_OK;
86 }
87 
88 static ULONG WINAPI ClientSite_AddRef(IOleClientSite *iface)
89 {
90     DocHost *This = impl_from_IOleClientSite(iface);
91     return This->container_vtbl->addref(This);
92 }
93 
94 static ULONG WINAPI ClientSite_Release(IOleClientSite *iface)
95 {
96     DocHost *This = impl_from_IOleClientSite(iface);
97     return This->container_vtbl->release(This);
98 }
99 
100 static HRESULT WINAPI ClientSite_SaveObject(IOleClientSite *iface)
101 {
102     DocHost *This = impl_from_IOleClientSite(iface);
103     FIXME("(%p)\n", This);
104     return E_NOTIMPL;
105 }
106 
107 static HRESULT WINAPI ClientSite_GetMoniker(IOleClientSite *iface, DWORD dwAssign,
108                                             DWORD dwWhichMoniker, IMoniker **ppmk)
109 {
110     DocHost *This = impl_from_IOleClientSite(iface);
111     FIXME("(%p)->(%d %d %p)\n", This, dwAssign, dwWhichMoniker, ppmk);
112     return E_NOTIMPL;
113 }
114 
115 static HRESULT WINAPI ClientSite_GetContainer(IOleClientSite *iface, IOleContainer **ppContainer)
116 {
117     DocHost *This = impl_from_IOleClientSite(iface);
118     FIXME("(%p)->(%p)\n", This, ppContainer);
119     return E_NOTIMPL;
120 }
121 
122 static HRESULT WINAPI ClientSite_ShowObject(IOleClientSite *iface)
123 {
124     DocHost *This = impl_from_IOleClientSite(iface);
125     FIXME("(%p)\n", This);
126     return E_NOTIMPL;
127 }
128 
129 static HRESULT WINAPI ClientSite_OnShowWindow(IOleClientSite *iface, BOOL fShow)
130 {
131     DocHost *This = impl_from_IOleClientSite(iface);
132     FIXME("(%p)->(%x)\n", This, fShow);
133     return E_NOTIMPL;
134 }
135 
136 static HRESULT WINAPI ClientSite_RequestNewObjectLayout(IOleClientSite *iface)
137 {
138     DocHost *This = impl_from_IOleClientSite(iface);
139     FIXME("(%p)\n", This);
140     return E_NOTIMPL;
141 }
142 
143 static const IOleClientSiteVtbl OleClientSiteVtbl = {
144     ClientSite_QueryInterface,
145     ClientSite_AddRef,
146     ClientSite_Release,
147     ClientSite_SaveObject,
148     ClientSite_GetMoniker,
149     ClientSite_GetContainer,
150     ClientSite_ShowObject,
151     ClientSite_OnShowWindow,
152     ClientSite_RequestNewObjectLayout
153 };
154 
155 static inline DocHost *impl_from_IOleInPlaceSiteEx(IOleInPlaceSiteEx *iface)
156 {
157     return CONTAINING_RECORD(iface, DocHost, IOleInPlaceSiteEx_iface);
158 }
159 
160 static HRESULT WINAPI InPlaceSite_QueryInterface(IOleInPlaceSiteEx *iface, REFIID riid, void **ppv)
161 {
162     DocHost *This = impl_from_IOleInPlaceSiteEx(iface);
163     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
164 }
165 
166 static ULONG WINAPI InPlaceSite_AddRef(IOleInPlaceSiteEx *iface)
167 {
168     DocHost *This = impl_from_IOleInPlaceSiteEx(iface);
169     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
170 }
171 
172 static ULONG WINAPI InPlaceSite_Release(IOleInPlaceSiteEx *iface)
173 {
174     DocHost *This = impl_from_IOleInPlaceSiteEx(iface);
175     return IOleClientSite_Release(&This->IOleClientSite_iface);
176 }
177 
178 static HRESULT WINAPI InPlaceSite_GetWindow(IOleInPlaceSiteEx *iface, HWND *phwnd)
179 {
180     DocHost *This = impl_from_IOleInPlaceSiteEx(iface);
181 
182     TRACE("(%p)->(%p)\n", This, phwnd);
183 
184     *phwnd = This->hwnd;
185     return S_OK;
186 }
187 
188 static HRESULT WINAPI InPlaceSite_ContextSensitiveHelp(IOleInPlaceSiteEx *iface, BOOL fEnterMode)
189 {
190     DocHost *This = impl_from_IOleInPlaceSiteEx(iface);
191     FIXME("(%p)->(%x)\n", This, fEnterMode);
192     return E_NOTIMPL;
193 }
194 
195 static HRESULT WINAPI InPlaceSite_CanInPlaceActivate(IOleInPlaceSiteEx *iface)
196 {
197     DocHost *This = impl_from_IOleInPlaceSiteEx(iface);
198 
199     TRACE("(%p)\n", This);
200 
201     /* Nothing to do here */
202     return S_OK;
203 }
204 
205 static HRESULT WINAPI InPlaceSite_OnInPlaceActivate(IOleInPlaceSiteEx *iface)
206 {
207     DocHost *This = impl_from_IOleInPlaceSiteEx(iface);
208 
209     TRACE("(%p)\n", This);
210 
211     /* Nothing to do here */
212     return S_OK;
213 }
214 
215 static HRESULT WINAPI InPlaceSite_OnUIActivate(IOleInPlaceSiteEx *iface)
216 {
217     DocHost *This = impl_from_IOleInPlaceSiteEx(iface);
218     FIXME("(%p)\n", This);
219     return E_NOTIMPL;
220 }
221 
222 static HRESULT WINAPI InPlaceSite_GetWindowContext(IOleInPlaceSiteEx *iface,
223         IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect,
224         LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
225 {
226     DocHost *This = impl_from_IOleInPlaceSiteEx(iface);
227 
228     TRACE("(%p)->(%p %p %p %p %p)\n", This, ppFrame, ppDoc, lprcPosRect,
229           lprcClipRect, lpFrameInfo);
230 
231     IOleInPlaceFrame_AddRef(&This->IOleInPlaceFrame_iface);
232     *ppFrame = &This->IOleInPlaceFrame_iface;
233     *ppDoc = NULL;
234 
235     GetClientRect(This->hwnd, lprcPosRect);
236     *lprcClipRect = *lprcPosRect;
237 
238     lpFrameInfo->fMDIApp = FALSE;
239     lpFrameInfo->hwndFrame = This->frame_hwnd;
240     lpFrameInfo->haccel = NULL;
241     lpFrameInfo->cAccelEntries = 0; /* FIXME: should be 5 */
242 
243     return S_OK;
244 }
245 
246 static HRESULT WINAPI InPlaceSite_Scroll(IOleInPlaceSiteEx *iface, SIZE scrollExtent)
247 {
248     DocHost *This = impl_from_IOleInPlaceSiteEx(iface);
249     FIXME("(%p)->({%d %d})\n", This, scrollExtent.cx, scrollExtent.cy);
250     return E_NOTIMPL;
251 }
252 
253 static HRESULT WINAPI InPlaceSite_OnUIDeactivate(IOleInPlaceSiteEx *iface, BOOL fUndoable)
254 {
255     DocHost *This = impl_from_IOleInPlaceSiteEx(iface);
256     FIXME("(%p)->(%x)\n", This, fUndoable);
257     return E_NOTIMPL;
258 }
259 
260 static HRESULT WINAPI InPlaceSite_OnInPlaceDeactivate(IOleInPlaceSiteEx *iface)
261 {
262     DocHost *This = impl_from_IOleInPlaceSiteEx(iface);
263 
264     TRACE("(%p)\n", This);
265 
266     /* Nothing to do here */
267     return S_OK;
268 }
269 
270 static HRESULT WINAPI InPlaceSite_DiscardUndoState(IOleInPlaceSiteEx *iface)
271 {
272     DocHost *This = impl_from_IOleInPlaceSiteEx(iface);
273     FIXME("(%p)\n", This);
274     return E_NOTIMPL;
275 }
276 
277 static HRESULT WINAPI InPlaceSite_DeactivateAndUndo(IOleInPlaceSiteEx *iface)
278 {
279     DocHost *This = impl_from_IOleInPlaceSiteEx(iface);
280     FIXME("(%p)\n", This);
281     return E_NOTIMPL;
282 }
283 
284 static HRESULT WINAPI InPlaceSite_OnPosRectChange(IOleInPlaceSiteEx *iface,
285                                                   LPCRECT lprcPosRect)
286 {
287     DocHost *This = impl_from_IOleInPlaceSiteEx(iface);
288     FIXME("(%p)->(%p)\n", This, lprcPosRect);
289     return E_NOTIMPL;
290 }
291 
292 static HRESULT WINAPI InPlaceSite_OnInPlaceActivateEx(IOleInPlaceSiteEx *iface,
293                                                      BOOL *pfNoRedraw, DWORD dwFlags)
294 {
295     DocHost *This = impl_from_IOleInPlaceSiteEx(iface);
296 
297     TRACE("(%p)->(%p, %x)\n", This, pfNoRedraw, dwFlags);
298 
299     /* FIXME: Avoid redraw, when possible */
300     *pfNoRedraw = FALSE;
301 
302     if (dwFlags) {
303         FIXME("dwFlags not supported (%x)\n", dwFlags);
304     }
305 
306     /* Nothing to do here */
307     return S_OK;
308 }
309 
310 static HRESULT WINAPI InPlaceSite_OnInPlaceDeactivateEx(IOleInPlaceSiteEx *iface, BOOL fNoRedraw)
311 {
312     DocHost *This = impl_from_IOleInPlaceSiteEx(iface);
313 
314     TRACE("(%p)->(%x)\n", This, fNoRedraw);
315 
316     if (fNoRedraw) {
317         FIXME("fNoRedraw (%x) ignored\n", fNoRedraw);
318     }
319 
320     /* Nothing to do here */
321     return S_OK;
322 }
323 
324 static HRESULT WINAPI InPlaceSite_RequestUIActivate(IOleInPlaceSiteEx *iface)
325 {
326     DocHost *This = impl_from_IOleInPlaceSiteEx(iface);
327     TRACE("(%p)\n", This);
328 
329     /* OnUIActivate is always possible */
330     return S_OK;
331 }
332 
333 static const IOleInPlaceSiteExVtbl OleInPlaceSiteExVtbl = {
334     InPlaceSite_QueryInterface,
335     InPlaceSite_AddRef,
336     InPlaceSite_Release,
337     InPlaceSite_GetWindow,
338     InPlaceSite_ContextSensitiveHelp,
339     InPlaceSite_CanInPlaceActivate,
340     InPlaceSite_OnInPlaceActivate,
341     InPlaceSite_OnUIActivate,
342     InPlaceSite_GetWindowContext,
343     InPlaceSite_Scroll,
344     InPlaceSite_OnUIDeactivate,
345     InPlaceSite_OnInPlaceDeactivate,
346     InPlaceSite_DiscardUndoState,
347     InPlaceSite_DeactivateAndUndo,
348     InPlaceSite_OnPosRectChange,
349     /* OleInPlaceSiteEx */
350     InPlaceSite_OnInPlaceActivateEx,
351     InPlaceSite_OnInPlaceDeactivateEx,
352     InPlaceSite_RequestUIActivate
353 };
354 
355 static inline DocHost *impl_from_IOleDocumentSite(IOleDocumentSite *iface)
356 {
357     return CONTAINING_RECORD(iface, DocHost, IOleDocumentSite_iface);
358 }
359 
360 static HRESULT WINAPI OleDocumentSite_QueryInterface(IOleDocumentSite *iface,
361                                                      REFIID riid, void **ppv)
362 {
363     DocHost *This = impl_from_IOleDocumentSite(iface);
364     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
365 }
366 
367 static ULONG WINAPI OleDocumentSite_AddRef(IOleDocumentSite *iface)
368 {
369     DocHost *This = impl_from_IOleDocumentSite(iface);
370     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
371 }
372 
373 static ULONG WINAPI OleDocumentSite_Release(IOleDocumentSite *iface)
374 {
375     DocHost *This = impl_from_IOleDocumentSite(iface);
376     return IOleClientSite_Release(&This->IOleClientSite_iface);
377 }
378 
379 static HRESULT WINAPI OleDocumentSite_ActivateMe(IOleDocumentSite *iface,
380                                                  IOleDocumentView *pViewToActivate)
381 {
382     DocHost *This = impl_from_IOleDocumentSite(iface);
383     IOleDocument *oledoc;
384     RECT rect;
385     HRESULT hres;
386 
387     TRACE("(%p)->(%p)\n", This, pViewToActivate);
388 
389     hres = IUnknown_QueryInterface(This->document, &IID_IOleDocument, (void**)&oledoc);
390     if(FAILED(hres))
391         return hres;
392 
393     hres = IOleDocument_CreateView(oledoc, (IOleInPlaceSite*) &This->IOleInPlaceSiteEx_iface, NULL, 0, &This->view);
394     IOleDocument_Release(oledoc);
395     if(FAILED(hres))
396         return hres;
397 
398     GetClientRect(This->hwnd, &rect);
399     IOleDocumentView_SetRect(This->view, &rect);
400 
401     hres = IOleDocumentView_Show(This->view, TRUE);
402 
403     return hres;
404 }
405 
406 static const IOleDocumentSiteVtbl OleDocumentSiteVtbl = {
407     OleDocumentSite_QueryInterface,
408     OleDocumentSite_AddRef,
409     OleDocumentSite_Release,
410     OleDocumentSite_ActivateMe
411 };
412 
413 static inline DocHost *impl_from_IOleControlSite(IOleControlSite *iface)
414 {
415     return CONTAINING_RECORD(iface, DocHost, IOleControlSite_iface);
416 }
417 
418 static HRESULT WINAPI ControlSite_QueryInterface(IOleControlSite *iface, REFIID riid, void **ppv)
419 {
420     DocHost *This = impl_from_IOleControlSite(iface);
421     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
422 }
423 
424 static ULONG WINAPI ControlSite_AddRef(IOleControlSite *iface)
425 {
426     DocHost *This = impl_from_IOleControlSite(iface);
427     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
428 }
429 
430 static ULONG WINAPI ControlSite_Release(IOleControlSite *iface)
431 {
432     DocHost *This = impl_from_IOleControlSite(iface);
433     return IOleClientSite_Release(&This->IOleClientSite_iface);
434 }
435 
436 static HRESULT WINAPI ControlSite_OnControlInfoChanged(IOleControlSite *iface)
437 {
438     DocHost *This = impl_from_IOleControlSite(iface);
439     FIXME("(%p)\n", This);
440     return E_NOTIMPL;
441 }
442 
443 static HRESULT WINAPI ControlSite_LockInPlaceActive(IOleControlSite *iface, BOOL fLock)
444 {
445     DocHost *This = impl_from_IOleControlSite(iface);
446     FIXME("(%p)->(%d)\n", This, fLock);
447     return E_NOTIMPL;
448 }
449 
450 static HRESULT WINAPI ControlSite_GetExtendedControl(IOleControlSite *iface, IDispatch **ppDisp)
451 {
452     DocHost *This = impl_from_IOleControlSite(iface);
453     FIXME("(%p)->(%p)\n", This, ppDisp);
454     return E_NOTIMPL;
455 }
456 
457 static HRESULT WINAPI ControlSite_TransformCoords(IOleControlSite *iface, POINTL *pPtlHimetric,
458                                                   POINTF *pPtfContainer, DWORD dwFlags)
459 {
460     DocHost *This = impl_from_IOleControlSite(iface);
461     FIXME("(%p)->(%p, %p, %08x)\n", This, pPtlHimetric, pPtfContainer, dwFlags);
462     return E_NOTIMPL;
463 }
464 
465 static HRESULT WINAPI ControlSite_TranslateAccelerator(IOleControlSite *iface, MSG *pMsg,
466                                                        DWORD grfModifiers)
467 {
468     DocHost *This = impl_from_IOleControlSite(iface);
469     IOleObject *wb_obj;
470     IOleClientSite *clientsite;
471     IOleControlSite *controlsite;
472     HRESULT hr;
473 
474     TRACE("(%p)->(%p, %08x)\n", This, pMsg, grfModifiers);
475 
476     hr = IWebBrowser2_QueryInterface(This->wb, &IID_IOleObject, (void**)&wb_obj);
477     if(SUCCEEDED(hr)) {
478         hr = IOleObject_GetClientSite(wb_obj, &clientsite);
479         if(SUCCEEDED(hr)) {
480             hr = IOleClientSite_QueryInterface(clientsite, &IID_IOleControlSite, (void**)&controlsite);
481             if(SUCCEEDED(hr)) {
482                 hr = IOleControlSite_TranslateAccelerator(controlsite, pMsg, grfModifiers);
483                 IOleControlSite_Release(controlsite);
484             }
485             IOleClientSite_Release(clientsite);
486         }
487         IOleObject_Release(wb_obj);
488     }
489 
490     if(FAILED(hr))
491         return S_FALSE;
492     else
493         return hr;
494 }
495 
496 static HRESULT WINAPI ControlSite_OnFocus(IOleControlSite *iface, BOOL fGotFocus)
497 {
498     DocHost *This = impl_from_IOleControlSite(iface);
499     FIXME("(%p)->(%d)\n", This, fGotFocus);
500     return E_NOTIMPL;
501 }
502 
503 static HRESULT WINAPI ControlSite_ShowPropertyFrame(IOleControlSite *iface)
504 {
505     DocHost *This = impl_from_IOleControlSite(iface);
506     FIXME("(%p)\n", This);
507     return E_NOTIMPL;
508 }
509 
510 static IOleControlSiteVtbl OleControlSiteVtbl = {
511     ControlSite_QueryInterface,
512     ControlSite_AddRef,
513     ControlSite_Release,
514     ControlSite_OnControlInfoChanged,
515     ControlSite_LockInPlaceActive,
516     ControlSite_GetExtendedControl,
517     ControlSite_TransformCoords,
518     ControlSite_TranslateAccelerator,
519     ControlSite_OnFocus,
520     ControlSite_ShowPropertyFrame
521 };
522 
523 static inline DocHost *impl_from_IDispatch(IDispatch *iface)
524 {
525     return CONTAINING_RECORD(iface, DocHost, IDispatch_iface);
526 }
527 
528 static HRESULT WINAPI ClDispatch_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
529 {
530     DocHost *This = impl_from_IDispatch(iface);
531     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
532 }
533 
534 static ULONG WINAPI ClDispatch_AddRef(IDispatch *iface)
535 {
536     DocHost *This = impl_from_IDispatch(iface);
537     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
538 }
539 
540 static ULONG WINAPI ClDispatch_Release(IDispatch *iface)
541 {
542     DocHost *This = impl_from_IDispatch(iface);
543     return IOleClientSite_Release(&This->IOleClientSite_iface);
544 }
545 
546 static HRESULT WINAPI ClDispatch_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
547 {
548     DocHost *This = impl_from_IDispatch(iface);
549 
550     TRACE("(%p)->(%p)\n", This, pctinfo);
551 
552     return E_NOTIMPL;
553 }
554 
555 static HRESULT WINAPI ClDispatch_GetTypeInfo(IDispatch *iface, UINT iTInfo, LCID lcid,
556                                              ITypeInfo **ppTInfo)
557 {
558     DocHost *This = impl_from_IDispatch(iface);
559 
560     TRACE("(%p)->(%u %d %p)\n", This, iTInfo, lcid, ppTInfo);
561 
562     return E_NOTIMPL;
563 }
564 
565 static HRESULT WINAPI ClDispatch_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *rgszNames,
566                                                UINT cNames, LCID lcid, DISPID *rgDispId)
567 {
568     DocHost *This = impl_from_IDispatch(iface);
569 
570     TRACE("(%p)->(%s %p %u %d %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
571           lcid, rgDispId);
572 
573     return E_NOTIMPL;
574 }
575 
576 static const char *debugstr_dispid(DISPID dispid)
577 {
578     static char buf[16];
579 
580 #define CASE_DISPID(did) case did: return #did
581     switch(dispid) {
582         CASE_DISPID(DISPID_AMBIENT_USERMODE);
583         CASE_DISPID(DISPID_AMBIENT_DLCONTROL);
584         CASE_DISPID(DISPID_AMBIENT_USERAGENT);
585         CASE_DISPID(DISPID_AMBIENT_PALETTE);
586         CASE_DISPID(DISPID_AMBIENT_OFFLINEIFNOTCONNECTED);
587         CASE_DISPID(DISPID_AMBIENT_SILENT);
588     }
589 #undef CASE_DISPID
590 
591     sprintf(buf, "%d", dispid);
592     return buf;
593 }
594 
595 static HRESULT WINAPI ClDispatch_Invoke(IDispatch *iface, DISPID dispIdMember, REFIID riid,
596                                         LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
597                                         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
598 {
599     DocHost *This = impl_from_IDispatch(iface);
600 
601     TRACE("(%p)->(%s %s %d %04x %p %p %p %p)\n", This, debugstr_dispid(dispIdMember),
602           debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
603 
604     switch(dispIdMember) {
605     case DISPID_AMBIENT_USERMODE:
606     case DISPID_AMBIENT_DLCONTROL:
607     case DISPID_AMBIENT_USERAGENT:
608     case DISPID_AMBIENT_PALETTE:
609         if(!This->client_disp)
610             return E_FAIL;
611         return IDispatch_Invoke(This->client_disp, dispIdMember, riid, lcid, wFlags,
612                                 pDispParams, pVarResult, pExcepInfo, puArgErr);
613     case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED:
614         V_VT(pVarResult) = VT_BOOL;
615         V_BOOL(pVarResult) = This->offline;
616         return S_OK;
617     case DISPID_AMBIENT_SILENT:
618         V_VT(pVarResult) = VT_BOOL;
619         V_BOOL(pVarResult) = This->offline;
620         return S_OK;
621     }
622 
623     FIXME("unhandled dispid %d\n", dispIdMember);
624     return E_NOTIMPL;
625 }
626 
627 static const IDispatchVtbl DispatchVtbl = {
628     ClDispatch_QueryInterface,
629     ClDispatch_AddRef,
630     ClDispatch_Release,
631     ClDispatch_GetTypeInfoCount,
632     ClDispatch_GetTypeInfo,
633     ClDispatch_GetIDsOfNames,
634     ClDispatch_Invoke
635 };
636 
637 static inline DocHost *impl_from_IServiceProvider(IServiceProvider *iface)
638 {
639     return CONTAINING_RECORD(iface, DocHost, IServiceProvider_iface);
640 }
641 
642 static HRESULT WINAPI ClServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid,
643                                                        void **ppv)
644 {
645     DocHost *This = impl_from_IServiceProvider(iface);
646     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppv);
647 }
648 
649 static ULONG WINAPI ClServiceProvider_AddRef(IServiceProvider *iface)
650 {
651     DocHost *This = impl_from_IServiceProvider(iface);
652     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
653 }
654 
655 static ULONG WINAPI ClServiceProvider_Release(IServiceProvider *iface)
656 {
657     DocHost *This = impl_from_IServiceProvider(iface);
658     return IOleClientSite_Release(&This->IOleClientSite_iface);
659 }
660 
661 static HRESULT WINAPI ClServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService,
662                                                      REFIID riid, void **ppv)
663 {
664     DocHost *This = impl_from_IServiceProvider(iface);
665 
666     if(IsEqualGUID(&IID_IHlinkFrame, guidService)) {
667         TRACE("(%p)->(IID_IHlinkFrame %s %p)\n", This, debugstr_guid(riid), ppv);
668         return IWebBrowser2_QueryInterface(This->wb, riid, ppv);
669     }
670 
671     if(IsEqualGUID(&IID_ITargetFrame, guidService)) {
672         TRACE("(%p)->(IID_ITargetFrame %s %p)\n", This, debugstr_guid(riid), ppv);
673         return IWebBrowser2_QueryInterface(This->wb, riid, ppv);
674     }
675 
676     if(IsEqualGUID(&IID_IWebBrowserApp, guidService)) {
677         TRACE("IWebBrowserApp service\n");
678         return IWebBrowser2_QueryInterface(This->wb, riid, ppv);
679     }
680 
681     if(IsEqualGUID(&IID_IShellBrowser, guidService)) {
682         TRACE("(%p)->(IID_IShellBrowser %s %p)\n", This, debugstr_guid(riid), ppv);
683 
684         if(!This->browser_service) {
685             HRESULT hres;
686 
687             hres = create_browser_service(This, &This->browser_service);
688             if(FAILED(hres))
689                 return hres;
690         }
691 
692         return IShellBrowser_QueryInterface(&This->browser_service->IShellBrowser_iface, riid, ppv);
693     }
694 
695     if(IsEqualGUID(&SID_SNewWindowManager, guidService)) {
696         TRACE("SID_SNewWindowManager service\n");
697         return INewWindowManager_QueryInterface(&This->nwm.INewWindowManager_iface, riid, ppv);
698     }
699 
700     FIXME("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
701 
702     return E_NOINTERFACE;
703 }
704 
705 static const IServiceProviderVtbl ServiceProviderVtbl = {
706     ClServiceProvider_QueryInterface,
707     ClServiceProvider_AddRef,
708     ClServiceProvider_Release,
709     ClServiceProvider_QueryService
710 };
711 
712 void DocHost_ClientSite_Init(DocHost *This)
713 {
714     This->IOleClientSite_iface.lpVtbl    = &OleClientSiteVtbl;
715     This->IOleInPlaceSiteEx_iface.lpVtbl = &OleInPlaceSiteExVtbl;
716     This->IOleDocumentSite_iface.lpVtbl  = &OleDocumentSiteVtbl;
717     This->IOleControlSite_iface.lpVtbl   = &OleControlSiteVtbl;
718     This->IDispatch_iface.lpVtbl         = &DispatchVtbl;
719     This->IServiceProvider_iface.lpVtbl  = &ServiceProviderVtbl;
720 }
721 
722 void DocHost_ClientSite_Release(DocHost *This)
723 {
724     if(This->browser_service)
725         detach_browser_service(This->browser_service);
726     if(This->view)
727         IOleDocumentView_Release(This->view);
728 }
729