ieframe: Use proper helpers for iface calls.
[wine] / dlls / ieframe / webbrowser.c
1 /*
2  * Implementation of IWebBrowser interface for WebBrowser control
3  *
4  * Copyright 2001 John R. Sheets (for CodeWeavers)
5  * Copyright 2005 Jacek Caban
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "ieframe.h"
23
24 #include "exdispid.h"
25 #include "mshtml.h"
26
27 #include "wine/debug.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(ieframe);
30
31 static inline WebBrowser *impl_from_IWebBrowser2(IWebBrowser2 *iface)
32 {
33     return CONTAINING_RECORD(iface, WebBrowser, IWebBrowser2_iface);
34 }
35
36 static HRESULT WINAPI WebBrowser_QueryInterface(IWebBrowser2 *iface, REFIID riid, LPVOID *ppv)
37 {
38     WebBrowser *This = impl_from_IWebBrowser2(iface);
39
40     if (ppv == NULL)
41         return E_POINTER;
42     *ppv = NULL;
43
44     if(IsEqualGUID(&IID_IUnknown, riid)) {
45         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
46         *ppv = &This->IWebBrowser2_iface;
47     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
48         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
49         *ppv = &This->IWebBrowser2_iface;
50     }else if(IsEqualGUID(&IID_IWebBrowser, riid)) {
51         TRACE("(%p)->(IID_IWebBrowser %p)\n", This, ppv);
52         *ppv = &This->IWebBrowser2_iface;
53     }else if(IsEqualGUID(&IID_IWebBrowserApp, riid)) {
54         TRACE("(%p)->(IID_IWebBrowserApp %p)\n", This, ppv);
55         *ppv = &This->IWebBrowser2_iface;
56     }else if(IsEqualGUID(&IID_IWebBrowser2, riid)) {
57         TRACE("(%p)->(IID_IWebBrowser2 %p)\n", This, ppv);
58         *ppv = &This->IWebBrowser2_iface;
59     }else if(IsEqualGUID(&IID_IOleObject, riid)) {
60         TRACE("(%p)->(IID_IOleObject %p)\n", This, ppv);
61         *ppv = &This->IOleObject_iface;
62     }else if(IsEqualGUID(&IID_IOleWindow, riid)) {
63         TRACE("(%p)->(IID_IOleWindow %p)\n", This, ppv);
64         *ppv = &This->IOleInPlaceObject_iface;
65     }else if(IsEqualGUID (&IID_IOleInPlaceObject, riid)) {
66         TRACE("(%p)->(IID_IOleInPlaceObject %p)\n", This, ppv);
67         *ppv = &This->IOleInPlaceObject_iface;
68     }else if(IsEqualGUID(&IID_IOleControl, riid)) {
69         TRACE("(%p)->(IID_IOleControl %p)\n", This, ppv);
70         *ppv = &This->IOleControl_iface;
71     }else if(IsEqualGUID(&IID_IPersist, riid)) {
72         TRACE("(%p)->(IID_IPersist %p)\n", This, ppv);
73         *ppv = &This->IPersistStorage_iface;
74     }else if(IsEqualGUID(&IID_IPersistStorage, riid)) {
75         TRACE("(%p)->(IID_IPersistStorage %p)\n", This, ppv);
76         *ppv = &This->IPersistStorage_iface;
77     }else if(IsEqualGUID(&IID_IPersistMemory, riid)) {
78         TRACE("(%p)->(IID_IPersistStorage %p)\n", This, ppv);
79         *ppv = &This->IPersistMemory_iface;
80     }else if(IsEqualGUID (&IID_IPersistStreamInit, riid)) {
81         TRACE("(%p)->(IID_IPersistStreamInit %p)\n", This, ppv);
82         *ppv = &This->IPersistStreamInit_iface;
83     }else if(IsEqualGUID(&IID_IProvideClassInfo, riid)) {
84         TRACE("(%p)->(IID_IProvideClassInfo %p)\n", This, ppv);
85         *ppv = &This->IProvideClassInfo2_iface;
86     }else if(IsEqualGUID(&IID_IProvideClassInfo2, riid)) {
87         TRACE("(%p)->(IID_IProvideClassInfo2 %p)\n", This, ppv);
88         *ppv = &This->IProvideClassInfo2_iface;
89     }else if(IsEqualGUID(&IID_IConnectionPointContainer, riid)) {
90         TRACE("(%p)->(IID_IConnectionPointContainer %p)\n", This, ppv);
91         *ppv = &This->doc_host.cps.IConnectionPointContainer_iface;
92     }else if(IsEqualGUID(&IID_IViewObject, riid)) {
93         TRACE("(%p)->(IID_IViewObject %p)\n", This, ppv);
94         *ppv = &This->IViewObject2_iface;
95     }else if(IsEqualGUID(&IID_IViewObject2, riid)) {
96         TRACE("(%p)->(IID_IViewObject2 %p)\n", This, ppv);
97         *ppv = &This->IViewObject2_iface;
98     }else if(IsEqualGUID(&IID_IOleInPlaceActiveObject, riid)) {
99         TRACE("(%p)->(IID_IOleInPlaceActiveObject %p)\n", This, ppv);
100         *ppv = &This->IOleInPlaceActiveObject_iface;
101     }else if(IsEqualGUID(&IID_IOleCommandTarget, riid)) {
102         TRACE("(%p)->(IID_IOleCommandTarget %p)\n", This, ppv);
103         *ppv = &This->IOleCommandTarget_iface;
104     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
105         *ppv = &This->IServiceProvider_iface;
106         TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
107     }else if(IsEqualGUID(&IID_IDataObject, riid)) {
108         *ppv = &This->IDataObject_iface;
109         TRACE("(%p)->(IID_IDataObject %p)\n", This, ppv);
110     }else if(IsEqualGUID(&IID_IQuickActivate, riid)) {
111         TRACE("(%p)->(IID_IQuickActivate %p) returning NULL\n", This, ppv);
112         return E_NOINTERFACE;
113     }else if(IsEqualGUID(&IID_IRunnableObject, riid)) {
114         TRACE("(%p)->(IID_IRunnableObject %p) returning NULL\n", This, ppv);
115         return E_NOINTERFACE;
116     }else if(IsEqualGUID(&IID_IPerPropertyBrowsing, riid)) {
117         TRACE("(%p)->(IID_IPerPropertyBrowsing %p) returning NULL\n", This, ppv);
118         return E_NOINTERFACE;
119     }else if(IsEqualGUID(&IID_IOleCache, riid)) {
120         TRACE("(%p)->(IID_IOleCache %p) returning NULL\n", This, ppv);
121         return E_NOINTERFACE;
122     }else if(IsEqualGUID(&IID_IOleInPlaceSite, riid)) {
123         TRACE("(%p)->(IID_IOleInPlaceSite %p) returning NULL\n", This, ppv);
124         return E_NOINTERFACE;
125     }else if(IsEqualGUID(&IID_IObjectWithSite, riid)) {
126         TRACE("(%p)->(IID_IObjectWithSite %p) returning NULL\n", This, ppv);
127         return E_NOINTERFACE;
128     }else if(IsEqualGUID(&IID_IViewObjectEx, riid)) {
129         TRACE("(%p)->(IID_IViewObjectEx %p) returning NULL\n", This, ppv);
130         return E_NOINTERFACE;
131     }else if(IsEqualGUID(&IID_IOleLink, riid)) {
132         TRACE("(%p)->(IID_IOleLink %p) returning NULL\n", This, ppv);
133         return E_NOINTERFACE;
134     }else if(IsEqualGUID(&IID_IMarshal, riid)) {
135         TRACE("(%p)->(IID_IMarshal %p) returning NULL\n", This, ppv);
136         return E_NOINTERFACE;
137     }else if(IsEqualGUID(&IID_IStdMarshalInfo, riid)) {
138         TRACE("(%p)->(IID_IStdMarshalInfo %p) returning NULL\n", This, ppv);
139         return E_NOINTERFACE;
140     }else if(HlinkFrame_QI(&This->hlink_frame, riid, ppv)) {
141         return S_OK;
142     }
143
144     if(*ppv) {
145         IUnknown_AddRef((IUnknown*)*ppv);
146         return S_OK;
147     }
148
149     FIXME("(%p)->(%s %p) interface not supported\n", This, debugstr_guid(riid), ppv);
150     return E_NOINTERFACE;
151 }
152
153 static ULONG WINAPI WebBrowser_AddRef(IWebBrowser2 *iface)
154 {
155     WebBrowser *This = impl_from_IWebBrowser2(iface);
156     LONG ref = InterlockedIncrement(&This->ref);
157     TRACE("(%p) ref=%d\n", This, ref);
158     return ref;
159 }
160
161 static ULONG WINAPI WebBrowser_Release(IWebBrowser2 *iface)
162 {
163     WebBrowser *This = impl_from_IWebBrowser2(iface);
164     LONG ref = InterlockedDecrement(&This->ref);
165
166     TRACE("(%p) ref=%d\n", This, ref);
167
168     if(!ref) {
169         if(This->doc_host.document)
170             IUnknown_Release(This->doc_host.document);
171
172         DocHost_Release(&This->doc_host);
173
174         WebBrowser_OleObject_Destroy(This);
175
176         heap_free(This);
177         unlock_module();
178     }
179
180     return ref;
181 }
182
183 /* IDispatch methods */
184 static HRESULT WINAPI WebBrowser_GetTypeInfoCount(IWebBrowser2 *iface, UINT *pctinfo)
185 {
186     WebBrowser *This = impl_from_IWebBrowser2(iface);
187
188     TRACE("(%p)->(%p)\n", This, pctinfo);
189
190     *pctinfo = 1;
191     return S_OK;
192 }
193
194 static HRESULT WINAPI WebBrowser_GetTypeInfo(IWebBrowser2 *iface, UINT iTInfo, LCID lcid,
195                                      LPTYPEINFO *ppTInfo)
196 {
197     WebBrowser *This = impl_from_IWebBrowser2(iface);
198     ITypeInfo *typeinfo;
199     HRESULT hres;
200
201     TRACE("(%p)->(%d %d %p)\n", This, iTInfo, lcid, ppTInfo);
202
203     hres = get_typeinfo(IWebBrowser2_tid, &typeinfo);
204     if(FAILED(hres))
205         return hres;
206
207     ITypeInfo_AddRef(typeinfo);
208     *ppTInfo = typeinfo;
209     return S_OK;
210 }
211
212 static HRESULT WINAPI WebBrowser_GetIDsOfNames(IWebBrowser2 *iface, REFIID riid,
213                                        LPOLESTR *rgszNames, UINT cNames,
214                                        LCID lcid, DISPID *rgDispId)
215 {
216     WebBrowser *This = impl_from_IWebBrowser2(iface);
217     ITypeInfo *typeinfo;
218     HRESULT hres;
219
220     TRACE("(%p)->(%s %p %d %d %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
221           lcid, rgDispId);
222
223     hres = get_typeinfo(IWebBrowser2_tid, &typeinfo);
224     if(FAILED(hres))
225         return hres;
226
227     return ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
228 }
229
230 static HRESULT WINAPI WebBrowser_Invoke(IWebBrowser2 *iface, DISPID dispIdMember,
231                                 REFIID riid, LCID lcid, WORD wFlags,
232                                 DISPPARAMS *pDispParams, VARIANT *pVarResult,
233                                 EXCEPINFO *pExepInfo, UINT *puArgErr)
234 {
235     WebBrowser *This = impl_from_IWebBrowser2(iface);
236     ITypeInfo *typeinfo;
237     HRESULT hres;
238
239     TRACE("(%p)->(%d %s %d %08x %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
240             lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
241
242     hres = get_typeinfo(IWebBrowser2_tid, &typeinfo);
243     if(FAILED(hres))
244         return hres;
245
246     return ITypeInfo_Invoke(typeinfo, &This->IWebBrowser2_iface, dispIdMember, wFlags, pDispParams,
247             pVarResult, pExepInfo, puArgErr);
248 }
249
250 /* IWebBrowser methods */
251 static HRESULT WINAPI WebBrowser_GoBack(IWebBrowser2 *iface)
252 {
253     WebBrowser *This = impl_from_IWebBrowser2(iface);
254     TRACE("(%p)\n", This);
255     return go_back(&This->doc_host);
256 }
257
258 static HRESULT WINAPI WebBrowser_GoForward(IWebBrowser2 *iface)
259 {
260     WebBrowser *This = impl_from_IWebBrowser2(iface);
261     FIXME("(%p)\n", This);
262     return E_NOTIMPL;
263 }
264
265 static HRESULT WINAPI WebBrowser_GoHome(IWebBrowser2 *iface)
266 {
267     WebBrowser *This = impl_from_IWebBrowser2(iface);
268     TRACE("(%p)\n", This);
269     return go_home(&This->doc_host);
270 }
271
272 static HRESULT WINAPI WebBrowser_GoSearch(IWebBrowser2 *iface)
273 {
274     WebBrowser *This = impl_from_IWebBrowser2(iface);
275     FIXME("(%p)\n", This);
276     return E_NOTIMPL;
277 }
278
279 static HRESULT WINAPI WebBrowser_Navigate(IWebBrowser2 *iface, BSTR szUrl,
280                                   VARIANT *Flags, VARIANT *TargetFrameName,
281                                   VARIANT *PostData, VARIANT *Headers)
282 {
283     WebBrowser *This = impl_from_IWebBrowser2(iface);
284
285     TRACE("(%p)->(%s %s %s %s %s)\n", This, debugstr_w(szUrl), debugstr_variant(Flags),
286           debugstr_variant(TargetFrameName), debugstr_variant(PostData),
287           debugstr_variant(Headers));
288
289     return navigate_url(&This->doc_host, szUrl, Flags, TargetFrameName, PostData, Headers);
290 }
291
292 static HRESULT WINAPI WebBrowser_Refresh(IWebBrowser2 *iface)
293 {
294     WebBrowser *This = impl_from_IWebBrowser2(iface);
295     FIXME("(%p)\n", This);
296     return E_NOTIMPL;
297 }
298
299 static HRESULT WINAPI WebBrowser_Refresh2(IWebBrowser2 *iface, VARIANT *Level)
300 {
301     WebBrowser *This = impl_from_IWebBrowser2(iface);
302     FIXME("(%p)->(%s)\n", This, debugstr_variant(Level));
303     return E_NOTIMPL;
304 }
305
306 static HRESULT WINAPI WebBrowser_Stop(IWebBrowser2 *iface)
307 {
308     WebBrowser *This = impl_from_IWebBrowser2(iface);
309     FIXME("(%p)\n", This);
310     return S_OK;
311 }
312
313 static HRESULT WINAPI WebBrowser_get_Application(IWebBrowser2 *iface, IDispatch **ppDisp)
314 {
315     WebBrowser *This = impl_from_IWebBrowser2(iface);
316
317     TRACE("(%p)->(%p)\n", This, ppDisp);
318
319     if(!ppDisp)
320         return E_POINTER;
321
322     *ppDisp = (IDispatch*)&This->IWebBrowser2_iface;
323     IDispatch_AddRef(*ppDisp);
324     return S_OK;
325 }
326
327 static HRESULT WINAPI WebBrowser_get_Parent(IWebBrowser2 *iface, IDispatch **ppDisp)
328 {
329     WebBrowser *This = impl_from_IWebBrowser2(iface);
330     FIXME("(%p)->(%p)\n", This, ppDisp);
331     return E_NOTIMPL;
332 }
333
334 static HRESULT WINAPI WebBrowser_get_Container(IWebBrowser2 *iface, IDispatch **ppDisp)
335 {
336     WebBrowser *This = impl_from_IWebBrowser2(iface);
337     FIXME("(%p)->(%p)\n", This, ppDisp);
338     return E_NOTIMPL;
339 }
340
341 static HRESULT WINAPI WebBrowser_get_Document(IWebBrowser2 *iface, IDispatch **ppDisp)
342 {
343     WebBrowser *This = impl_from_IWebBrowser2(iface);
344     IDispatch *disp = NULL;
345
346     TRACE("(%p)->(%p)\n", This, ppDisp);
347
348     if(This->doc_host.document) {
349         HRESULT hres;
350
351         hres = IUnknown_QueryInterface(This->doc_host.document, &IID_IDispatch, (void**)&disp);
352         if(SUCCEEDED(hres)) {
353             IDispatch *html_doc;
354
355             /* Some broken apps cast returned IDispatch to IHTMLDocument2
356              * without QueryInterface call */
357             hres = IDispatch_QueryInterface(disp, &IID_IHTMLDocument2, (void**)&html_doc);
358             if(SUCCEEDED(hres)) {
359                 IDispatch_Release(disp);
360                 disp = html_doc;
361             }
362         }
363     }
364
365     *ppDisp = disp;
366     return S_OK;
367 }
368
369 static HRESULT WINAPI WebBrowser_get_TopLevelContainer(IWebBrowser2 *iface, VARIANT_BOOL *pBool)
370 {
371     WebBrowser *This = impl_from_IWebBrowser2(iface);
372     FIXME("(%p)->(%p)\n", This, pBool);
373     return E_NOTIMPL;
374 }
375
376 static HRESULT WINAPI WebBrowser_get_Type(IWebBrowser2 *iface, BSTR *Type)
377 {
378     WebBrowser *This = impl_from_IWebBrowser2(iface);
379     FIXME("(%p)->(%p)\n", This, Type);
380     return E_NOTIMPL;
381 }
382
383 static HRESULT WINAPI WebBrowser_get_Left(IWebBrowser2 *iface, LONG *pl)
384 {
385     WebBrowser *This = impl_from_IWebBrowser2(iface);
386
387     TRACE("(%p)->(%p)\n", This, pl);
388
389     *pl = This->pos_rect.left;
390     return S_OK;
391 }
392
393 static HRESULT WINAPI WebBrowser_put_Left(IWebBrowser2 *iface, LONG Left)
394 {
395     WebBrowser *This = impl_from_IWebBrowser2(iface);
396     RECT rect;
397
398     TRACE("(%p)->(%d)\n", This, Left);
399
400     if(!This->inplace)
401         return E_UNEXPECTED;
402
403     rect = This->pos_rect;
404     rect.left = Left;
405
406     /* We don't really change the window position here.
407      * We just notify the embedder that he should do so. */
408     return IOleInPlaceSiteEx_OnPosRectChange(This->inplace, &rect);
409 }
410
411 static HRESULT WINAPI WebBrowser_get_Top(IWebBrowser2 *iface, LONG *pl)
412 {
413     WebBrowser *This = impl_from_IWebBrowser2(iface);
414
415     TRACE("(%p)->(%p)\n", This, pl);
416
417     *pl = This->pos_rect.top;
418     return S_OK;
419 }
420
421 static HRESULT WINAPI WebBrowser_put_Top(IWebBrowser2 *iface, LONG Top)
422 {
423     WebBrowser *This = impl_from_IWebBrowser2(iface);
424     RECT rect;
425
426     TRACE("(%p)->(%d)\n", This, Top);
427
428     if(!This->inplace)
429         return E_UNEXPECTED;
430
431     rect = This->pos_rect;
432     rect.top = Top;
433
434     /* We don't really change the window position here.
435      * We just notify the embedder that he should do so. */
436     return IOleInPlaceSiteEx_OnPosRectChange(This->inplace, &rect);
437 }
438
439 static HRESULT WINAPI WebBrowser_get_Width(IWebBrowser2 *iface, LONG *pl)
440 {
441     WebBrowser *This = impl_from_IWebBrowser2(iface);
442
443     TRACE("(%p)->(%p)\n", This, pl);
444
445     *pl = This->pos_rect.right - This->pos_rect.left;
446     return S_OK;
447 }
448
449 static HRESULT WINAPI WebBrowser_put_Width(IWebBrowser2 *iface, LONG Width)
450 {
451     WebBrowser *This = impl_from_IWebBrowser2(iface);
452     RECT rect;
453
454     TRACE("(%p)->(%d)\n", This, Width);
455
456     if(!This->inplace)
457         return E_UNEXPECTED;
458
459     rect = This->pos_rect;
460     rect.right = rect.left+Width;
461
462     /* We don't really change the window size here.
463      * We just notify the embedder that he should do so. */
464    return IOleInPlaceSiteEx_OnPosRectChange(This->inplace, &rect);
465 }
466
467 static HRESULT WINAPI WebBrowser_get_Height(IWebBrowser2 *iface, LONG *pl)
468 {
469     WebBrowser *This = impl_from_IWebBrowser2(iface);
470
471     TRACE("(%p)->(%p)\n", This, pl);
472
473     *pl = This->pos_rect.bottom - This->pos_rect.top;
474     return S_OK;
475 }
476
477 static HRESULT WINAPI WebBrowser_put_Height(IWebBrowser2 *iface, LONG Height)
478 {
479     WebBrowser *This = impl_from_IWebBrowser2(iface);
480     RECT rect;
481
482     TRACE("(%p)->(%d)\n", This, Height);
483
484     if(!This->inplace)
485         return E_UNEXPECTED;
486
487     rect = This->pos_rect;
488     rect.bottom = rect.top+Height;
489
490     /* We don't really change the window size here.
491      * We just notify the embedder that he should do so. */
492     return IOleInPlaceSiteEx_OnPosRectChange(This->inplace, &rect);
493 }
494
495 static HRESULT WINAPI WebBrowser_get_LocationName(IWebBrowser2 *iface, BSTR *LocationName)
496 {
497     WebBrowser *This = impl_from_IWebBrowser2(iface);
498     FIXME("(%p)->(%p)\n", This, LocationName);
499     return E_NOTIMPL;
500 }
501
502 static HRESULT WINAPI WebBrowser_get_LocationURL(IWebBrowser2 *iface, BSTR *LocationURL)
503 {
504     WebBrowser *This = impl_from_IWebBrowser2(iface);
505
506     TRACE("(%p)->(%p)\n", This, LocationURL);
507
508     return get_location_url(&This->doc_host, LocationURL);
509 }
510
511 static HRESULT WINAPI WebBrowser_get_Busy(IWebBrowser2 *iface, VARIANT_BOOL *pBool)
512 {
513     WebBrowser *This = impl_from_IWebBrowser2(iface);
514
515     TRACE("(%p)->(%p)\n", This, pBool);
516
517     *pBool = This->doc_host.busy;
518     return S_OK;
519 }
520
521 static HRESULT WINAPI WebBrowser_Quit(IWebBrowser2 *iface)
522 {
523     WebBrowser *This = impl_from_IWebBrowser2(iface);
524
525     TRACE("(%p)\n", This);
526
527     /* It's a InternetExplorer specific method, we have nothing to do here. */
528     return E_FAIL;
529 }
530
531 static HRESULT WINAPI WebBrowser_ClientToWindow(IWebBrowser2 *iface, int *pcx, int *pcy)
532 {
533     WebBrowser *This = impl_from_IWebBrowser2(iface);
534     FIXME("(%p)->(%p %p)\n", This, pcx, pcy);
535     return E_NOTIMPL;
536 }
537
538 static HRESULT WINAPI WebBrowser_PutProperty(IWebBrowser2 *iface, BSTR szProperty, VARIANT vtValue)
539 {
540     WebBrowser *This = impl_from_IWebBrowser2(iface);
541     FIXME("(%p)->(%s %s)\n", This, debugstr_w(szProperty), debugstr_variant(&vtValue));
542     return E_NOTIMPL;
543 }
544
545 static HRESULT WINAPI WebBrowser_GetProperty(IWebBrowser2 *iface, BSTR szProperty, VARIANT *pvtValue)
546 {
547     WebBrowser *This = impl_from_IWebBrowser2(iface);
548     FIXME("(%p)->(%s %s)\n", This, debugstr_w(szProperty), debugstr_variant(pvtValue));
549     return E_NOTIMPL;
550 }
551
552 static HRESULT WINAPI WebBrowser_get_Name(IWebBrowser2 *iface, BSTR *Name)
553 {
554     static const WCHAR sName[] = {'M','i','c','r','o','s','o','f','t',' ','W','e','b',
555                                   ' ','B','r','o','w','s','e','r',' ','C','o','n','t','r','o','l',0};
556     WebBrowser *This = impl_from_IWebBrowser2(iface);
557
558     TRACE("(%p)->(%p)\n", This, Name);
559
560     *Name = SysAllocString(sName);
561
562     return S_OK;
563 }
564
565 static HRESULT WINAPI WebBrowser_get_HWND(IWebBrowser2 *iface, LONG *pHWND)
566 {
567     WebBrowser *This = impl_from_IWebBrowser2(iface);
568
569     TRACE("(%p)->(%p)\n", This, pHWND);
570
571     /* WebBrowser control never has a frame window (in opposition to InternetExplorer) */
572     *pHWND = 0;
573     return E_FAIL;
574 }
575
576 static HRESULT WINAPI WebBrowser_get_FullName(IWebBrowser2 *iface, BSTR *FullName)
577 {
578     WebBrowser *This = impl_from_IWebBrowser2(iface);
579     FIXME("(%p)->(%p)\n", This, FullName);
580     return E_NOTIMPL;
581 }
582
583 static HRESULT WINAPI WebBrowser_get_Path(IWebBrowser2 *iface, BSTR *Path)
584 {
585     WebBrowser *This = impl_from_IWebBrowser2(iface);
586     FIXME("(%p)->(%p)\n", This, Path);
587     return E_NOTIMPL;
588 }
589
590 static HRESULT WINAPI WebBrowser_get_Visible(IWebBrowser2 *iface, VARIANT_BOOL *pBool)
591 {
592     WebBrowser *This = impl_from_IWebBrowser2(iface);
593
594     TRACE("(%p)->(%p)\n", This, pBool);
595
596     *pBool = This->visible;
597     return S_OK;
598 }
599
600 static HRESULT WINAPI WebBrowser_put_Visible(IWebBrowser2 *iface, VARIANT_BOOL Value)
601 {
602     WebBrowser *This = impl_from_IWebBrowser2(iface);
603     VARIANTARG arg;
604     DISPPARAMS dispparams = {&arg, NULL, 1, 0};
605
606     TRACE("(%p)->(%x)\n", This, Value);
607
608     This->visible = Value;
609
610     V_VT(&arg) = VT_BOOL;
611     V_BOOL(&arg) = Value;
612     call_sink(This->doc_host.cps.wbe2, DISPID_ONVISIBLE, &dispparams);
613
614     return S_OK;
615 }
616
617 static HRESULT WINAPI WebBrowser_get_StatusBar(IWebBrowser2 *iface, VARIANT_BOOL *pBool)
618 {
619     WebBrowser *This = impl_from_IWebBrowser2(iface);
620
621     TRACE("(%p)->(%p)\n", This, pBool);
622
623     *pBool = This->status_bar;
624     return S_OK;
625 }
626
627 static HRESULT WINAPI WebBrowser_put_StatusBar(IWebBrowser2 *iface, VARIANT_BOOL Value)
628 {
629     WebBrowser *This = impl_from_IWebBrowser2(iface);
630     VARIANTARG arg;
631     DISPPARAMS dispparams = {&arg, NULL, 1, 0};
632
633     TRACE("(%p)->(%x)\n", This, Value);
634
635     This->status_bar = Value ? VARIANT_TRUE : VARIANT_FALSE;
636
637     /* In opposition to InternetExplorer, all we should do here is
638      * inform the embedder about the status bar change. */
639
640     V_VT(&arg) = VT_BOOL;
641     V_BOOL(&arg) = Value;
642     call_sink(This->doc_host.cps.wbe2, DISPID_ONSTATUSBAR, &dispparams);
643
644     return S_OK;
645 }
646
647 static HRESULT WINAPI WebBrowser_get_StatusText(IWebBrowser2 *iface, BSTR *StatusText)
648 {
649     WebBrowser *This = impl_from_IWebBrowser2(iface);
650     FIXME("(%p)->(%p)\n", This, StatusText);
651     return E_NOTIMPL;
652 }
653
654 static HRESULT WINAPI WebBrowser_put_StatusText(IWebBrowser2 *iface, BSTR StatusText)
655 {
656     WebBrowser *This = impl_from_IWebBrowser2(iface);
657     FIXME("(%p)->(%s)\n", This, debugstr_w(StatusText));
658     return E_NOTIMPL;
659 }
660
661 static HRESULT WINAPI WebBrowser_get_ToolBar(IWebBrowser2 *iface, int *Value)
662 {
663     WebBrowser *This = impl_from_IWebBrowser2(iface);
664
665     TRACE("(%p)->(%p)\n", This, Value);
666
667     *Value = This->tool_bar;
668     return S_OK;
669 }
670
671 static HRESULT WINAPI WebBrowser_put_ToolBar(IWebBrowser2 *iface, int Value)
672 {
673     WebBrowser *This = impl_from_IWebBrowser2(iface);
674     VARIANTARG arg;
675     DISPPARAMS dispparams = {&arg, NULL, 1, 0};
676
677     TRACE("(%p)->(%x)\n", This, Value);
678
679     This->tool_bar = Value ? VARIANT_TRUE : VARIANT_FALSE;
680
681     /* In opposition to InternetExplorer, all we should do here is
682      * inform the embedder about the tool bar change. */
683
684     V_VT(&arg) = VT_BOOL;
685     V_BOOL(&arg) = This->tool_bar;
686     call_sink(This->doc_host.cps.wbe2, DISPID_ONTOOLBAR, &dispparams);
687
688     return S_OK;
689 }
690
691 static HRESULT WINAPI WebBrowser_get_MenuBar(IWebBrowser2 *iface, VARIANT_BOOL *Value)
692 {
693     WebBrowser *This = impl_from_IWebBrowser2(iface);
694
695     TRACE("(%p)->(%p)\n", This, Value);
696
697     *Value = This->menu_bar;
698     return S_OK;
699 }
700
701 static HRESULT WINAPI WebBrowser_put_MenuBar(IWebBrowser2 *iface, VARIANT_BOOL Value)
702 {
703     WebBrowser *This = impl_from_IWebBrowser2(iface);
704     VARIANTARG arg;
705     DISPPARAMS dispparams = {&arg, NULL, 1, 0};
706
707     TRACE("(%p)->(%x)\n", This, Value);
708
709     This->menu_bar = Value ? VARIANT_TRUE : VARIANT_FALSE;
710
711     /* In opposition to InternetExplorer, all we should do here is
712      * inform the embedder about the menu bar change. */
713
714     V_VT(&arg) = VT_BOOL;
715     V_BOOL(&arg) = Value;
716     call_sink(This->doc_host.cps.wbe2, DISPID_ONMENUBAR, &dispparams);
717
718     return S_OK;
719 }
720
721 static HRESULT WINAPI WebBrowser_get_FullScreen(IWebBrowser2 *iface, VARIANT_BOOL *pbFullScreen)
722 {
723     WebBrowser *This = impl_from_IWebBrowser2(iface);
724
725     TRACE("(%p)->(%p)\n", This, pbFullScreen);
726
727     *pbFullScreen = This->full_screen;
728     return S_OK;
729 }
730
731 static HRESULT WINAPI WebBrowser_put_FullScreen(IWebBrowser2 *iface, VARIANT_BOOL bFullScreen)
732 {
733     WebBrowser *This = impl_from_IWebBrowser2(iface);
734     VARIANTARG arg;
735     DISPPARAMS dispparams = {&arg, NULL, 1, 0};
736
737     /* In opposition to InternetExplorer, all we should do here is
738      * inform the embedder about the fullscreen change. */
739
740     TRACE("(%p)->(%x)\n", This, bFullScreen);
741
742     This->full_screen = bFullScreen ? VARIANT_TRUE : VARIANT_FALSE;
743
744     V_VT(&arg) = VT_BOOL;
745     V_BOOL(&arg) = bFullScreen;
746     call_sink(This->doc_host.cps.wbe2, DISPID_ONFULLSCREEN, &dispparams);
747
748     return S_OK;
749 }
750
751 static HRESULT WINAPI WebBrowser_Navigate2(IWebBrowser2 *iface, VARIANT *URL, VARIANT *Flags,
752         VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers)
753 {
754     WebBrowser *This = impl_from_IWebBrowser2(iface);
755     LPCWSTR url;
756
757     TRACE("(%p)->(%s %s %s %s %s)\n", This, debugstr_variant(URL), debugstr_variant(Flags),
758           debugstr_variant(TargetFrameName), debugstr_variant(PostData), debugstr_variant(Headers));
759
760     if(!This->client)
761         return E_FAIL;
762
763     if(!URL)
764         return S_OK;
765
766     switch (V_VT(URL))
767     {
768     case VT_BSTR:
769         url = V_BSTR(URL);
770         break;
771     case VT_BSTR|VT_BYREF:
772         url = *V_BSTRREF(URL);
773         break;
774     default:
775         FIXME("Unsupported V_VT(URL) %d\n", V_VT(URL));
776         return E_INVALIDARG;
777     }
778
779     return navigate_url(&This->doc_host, url, Flags, TargetFrameName, PostData, Headers);
780 }
781
782 static HRESULT WINAPI WebBrowser_QueryStatusWB(IWebBrowser2 *iface, OLECMDID cmdID, OLECMDF *pcmdf)
783 {
784     WebBrowser *This = impl_from_IWebBrowser2(iface);
785     IOleCommandTarget *target = NULL;
786     OLECMD ole_command[1];
787     HRESULT hres;
788
789     TRACE("(%p)->(%d %p)\n", This, cmdID, pcmdf);
790
791     if (!pcmdf)
792         return E_POINTER;
793     ole_command[0].cmdID = cmdID;
794     ole_command[0].cmdf = *pcmdf;
795
796     if (This->container)
797     {
798         hres = IOleContainer_QueryInterface(This->container, &IID_IOleCommandTarget, (LPVOID*)&target);
799         if(FAILED(hres))
800             target = NULL;
801     }
802     if (!target && This->doc_host.document)
803     {
804         hres = IUnknown_QueryInterface(This->doc_host.document, &IID_IOleCommandTarget, (LPVOID*)&target);
805         if(FAILED(hres))
806             target = NULL;
807     }
808
809     if (!target)
810         return E_UNEXPECTED;
811
812     hres = IOleCommandTarget_QueryStatus(target, NULL, 1, ole_command, NULL);
813     if (SUCCEEDED(hres))
814         *pcmdf = ole_command[0].cmdf;
815     if (hres == OLECMDERR_E_NOTSUPPORTED)
816     {
817         *pcmdf = 0;
818         hres = S_OK;
819     }
820     IOleCommandTarget_Release(target);
821
822     return hres;
823 }
824
825 static HRESULT WINAPI WebBrowser_ExecWB(IWebBrowser2 *iface, OLECMDID cmdID,
826         OLECMDEXECOPT cmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
827 {
828     WebBrowser *This = impl_from_IWebBrowser2(iface);
829     IOleCommandTarget *target = NULL;
830     HRESULT hres;
831
832     TRACE("(%p)->(%d %d %s %p)\n", This, cmdID, cmdexecopt, debugstr_variant(pvaIn), pvaOut);
833
834     if(This->container)
835     {
836         hres = IOleContainer_QueryInterface(This->container, &IID_IOleCommandTarget, (LPVOID*)&target);
837         if(FAILED(hres))
838             target = NULL;
839     }
840     if(!target && This->doc_host.document)
841     {
842         hres = IUnknown_QueryInterface(This->doc_host.document, &IID_IOleCommandTarget, (LPVOID*)&target);
843         if(FAILED(hres))
844             target = NULL;
845     }
846
847     if(!target)
848         return E_UNEXPECTED;
849
850     hres = IOleCommandTarget_Exec(target, NULL, cmdID, cmdexecopt, pvaIn, pvaOut);
851     IOleCommandTarget_Release(target);
852
853     return hres;
854 }
855
856 static HRESULT WINAPI WebBrowser_ShowBrowserBar(IWebBrowser2 *iface, VARIANT *pvaClsid,
857         VARIANT *pvarShow, VARIANT *pvarSize)
858 {
859     WebBrowser *This = impl_from_IWebBrowser2(iface);
860     FIXME("(%p)->(%s %s %s)\n", This, debugstr_variant(pvaClsid), debugstr_variant(pvarShow),
861           debugstr_variant(pvarSize));
862     return E_NOTIMPL;
863 }
864
865 static HRESULT WINAPI WebBrowser_get_ReadyState(IWebBrowser2 *iface, READYSTATE *lpReadyState)
866 {
867     WebBrowser *This = impl_from_IWebBrowser2(iface);
868
869     TRACE("(%p)->(%p)\n", This, lpReadyState);
870
871     *lpReadyState = This->doc_host.ready_state;
872     return S_OK;
873 }
874
875 static HRESULT WINAPI WebBrowser_get_Offline(IWebBrowser2 *iface, VARIANT_BOOL *pbOffline)
876 {
877     WebBrowser *This = impl_from_IWebBrowser2(iface);
878
879     TRACE("(%p)->(%p)\n", This, pbOffline);
880
881     *pbOffline = This->doc_host.offline;
882     return S_OK;
883 }
884
885 static HRESULT WINAPI WebBrowser_put_Offline(IWebBrowser2 *iface, VARIANT_BOOL bOffline)
886 {
887     WebBrowser *This = impl_from_IWebBrowser2(iface);
888
889     TRACE("(%p)->(%x)\n", This, bOffline);
890
891     This->doc_host.offline = bOffline ? VARIANT_TRUE : VARIANT_FALSE;
892     return S_OK;
893 }
894
895 static HRESULT WINAPI WebBrowser_get_Silent(IWebBrowser2 *iface, VARIANT_BOOL *pbSilent)
896 {
897     WebBrowser *This = impl_from_IWebBrowser2(iface);
898
899     TRACE("(%p)->(%p)\n", This, pbSilent);
900
901     *pbSilent = This->doc_host.silent;
902     return S_OK;
903 }
904
905 static HRESULT WINAPI WebBrowser_put_Silent(IWebBrowser2 *iface, VARIANT_BOOL bSilent)
906 {
907     WebBrowser *This = impl_from_IWebBrowser2(iface);
908
909     TRACE("(%p)->(%x)\n", This, bSilent);
910
911     This->doc_host.silent = bSilent ? VARIANT_TRUE : VARIANT_FALSE;
912     return S_OK;
913 }
914
915 static HRESULT WINAPI WebBrowser_get_RegisterAsBrowser(IWebBrowser2 *iface,
916         VARIANT_BOOL *pbRegister)
917 {
918     WebBrowser *This = impl_from_IWebBrowser2(iface);
919
920     FIXME("(%p)->(%p)\n", This, pbRegister);
921
922     *pbRegister = This->register_browser;
923     return S_OK;
924 }
925
926 static HRESULT WINAPI WebBrowser_put_RegisterAsBrowser(IWebBrowser2 *iface,
927         VARIANT_BOOL bRegister)
928 {
929     WebBrowser *This = impl_from_IWebBrowser2(iface);
930
931     FIXME("(%p)->(%x)\n", This, bRegister);
932
933     This->register_browser = bRegister ? VARIANT_TRUE : VARIANT_FALSE;
934     return S_OK;
935 }
936
937 static HRESULT WINAPI WebBrowser_get_RegisterAsDropTarget(IWebBrowser2 *iface,
938         VARIANT_BOOL *pbRegister)
939 {
940     WebBrowser *This = impl_from_IWebBrowser2(iface);
941     FIXME("(%p)->(%p)\n", This, pbRegister);
942     *pbRegister=0;
943     return S_OK;
944 }
945
946 static HRESULT WINAPI WebBrowser_put_RegisterAsDropTarget(IWebBrowser2 *iface,
947         VARIANT_BOOL bRegister)
948 {
949     WebBrowser *This = impl_from_IWebBrowser2(iface);
950     FIXME("(%p)->(%x)\n", This, bRegister);
951     return S_OK;
952 }
953
954 static HRESULT WINAPI WebBrowser_get_TheaterMode(IWebBrowser2 *iface, VARIANT_BOOL *pbRegister)
955 {
956     WebBrowser *This = impl_from_IWebBrowser2(iface);
957
958     TRACE("(%p)->(%p)\n", This, pbRegister);
959
960     *pbRegister = This->theater_mode;
961     return S_OK;
962 }
963
964 static HRESULT WINAPI WebBrowser_put_TheaterMode(IWebBrowser2 *iface, VARIANT_BOOL bRegister)
965 {
966     WebBrowser *This = impl_from_IWebBrowser2(iface);
967     VARIANTARG arg;
968     DISPPARAMS dispparams = {&arg, NULL, 1, 0};
969
970     TRACE("(%p)->(%x)\n", This, bRegister);
971
972     This->theater_mode = bRegister ? VARIANT_TRUE : VARIANT_FALSE;
973
974     /* In opposition to InternetExplorer, all we should do here is
975      * inform the embedder about the theater mode change. */
976
977     V_VT(&arg) = VT_BOOL;
978     V_BOOL(&arg) = bRegister;
979     call_sink(This->doc_host.cps.wbe2, DISPID_ONTHEATERMODE, &dispparams);
980
981     return S_OK;
982 }
983
984 static HRESULT WINAPI WebBrowser_get_AddressBar(IWebBrowser2 *iface, VARIANT_BOOL *Value)
985 {
986     WebBrowser *This = impl_from_IWebBrowser2(iface);
987
988     TRACE("(%p)->(%p)\n", This, Value);
989
990     *Value = This->address_bar;
991     return S_OK;
992 }
993
994 static HRESULT WINAPI WebBrowser_put_AddressBar(IWebBrowser2 *iface, VARIANT_BOOL Value)
995 {
996     WebBrowser *This = impl_from_IWebBrowser2(iface);
997     VARIANTARG arg;
998     DISPPARAMS dispparams = {&arg, NULL, 1, 0};
999
1000     TRACE("(%p)->(%x)\n", This, Value);
1001
1002     This->address_bar = Value ? VARIANT_TRUE : VARIANT_FALSE;
1003
1004     /* In opposition to InternetExplorer, all we should do here is
1005      * inform the embedder about the address bar change. */
1006
1007     V_VT(&arg) = VT_BOOL;
1008     V_BOOL(&arg) = Value;
1009     call_sink(This->doc_host.cps.wbe2, DISPID_ONADDRESSBAR, &dispparams);
1010
1011     return S_OK;
1012 }
1013
1014 static HRESULT WINAPI WebBrowser_get_Resizable(IWebBrowser2 *iface, VARIANT_BOOL *Value)
1015 {
1016     WebBrowser *This = impl_from_IWebBrowser2(iface);
1017
1018     TRACE("(%p)->(%p)\n", This, Value);
1019
1020     /* It's InternetExplorer object's method. We have nothing to do here. */
1021     return E_NOTIMPL;
1022 }
1023
1024 static HRESULT WINAPI WebBrowser_put_Resizable(IWebBrowser2 *iface, VARIANT_BOOL Value)
1025 {
1026     WebBrowser *This = impl_from_IWebBrowser2(iface);
1027     VARIANTARG arg;
1028     DISPPARAMS dispparams = {&arg, NULL, 1, 0};
1029
1030     TRACE("(%p)->(%x)\n", This, Value);
1031
1032     /* In opposition to InternetExplorer, all we should do here is
1033      * inform the embedder about the resizable change. */
1034
1035     V_VT(&arg) = VT_BOOL;
1036     V_BOOL(&arg) = Value;
1037     call_sink(This->doc_host.cps.wbe2, DISPID_WINDOWSETRESIZABLE, &dispparams);
1038
1039     return S_OK;
1040 }
1041
1042 static const IWebBrowser2Vtbl WebBrowser2Vtbl =
1043 {
1044     WebBrowser_QueryInterface,
1045     WebBrowser_AddRef,
1046     WebBrowser_Release,
1047     WebBrowser_GetTypeInfoCount,
1048     WebBrowser_GetTypeInfo,
1049     WebBrowser_GetIDsOfNames,
1050     WebBrowser_Invoke,
1051     WebBrowser_GoBack,
1052     WebBrowser_GoForward,
1053     WebBrowser_GoHome,
1054     WebBrowser_GoSearch,
1055     WebBrowser_Navigate,
1056     WebBrowser_Refresh,
1057     WebBrowser_Refresh2,
1058     WebBrowser_Stop,
1059     WebBrowser_get_Application,
1060     WebBrowser_get_Parent,
1061     WebBrowser_get_Container,
1062     WebBrowser_get_Document,
1063     WebBrowser_get_TopLevelContainer,
1064     WebBrowser_get_Type,
1065     WebBrowser_get_Left,
1066     WebBrowser_put_Left,
1067     WebBrowser_get_Top,
1068     WebBrowser_put_Top,
1069     WebBrowser_get_Width,
1070     WebBrowser_put_Width,
1071     WebBrowser_get_Height,
1072     WebBrowser_put_Height,
1073     WebBrowser_get_LocationName,
1074     WebBrowser_get_LocationURL,
1075     WebBrowser_get_Busy,
1076     WebBrowser_Quit,
1077     WebBrowser_ClientToWindow,
1078     WebBrowser_PutProperty,
1079     WebBrowser_GetProperty,
1080     WebBrowser_get_Name,
1081     WebBrowser_get_HWND,
1082     WebBrowser_get_FullName,
1083     WebBrowser_get_Path,
1084     WebBrowser_get_Visible,
1085     WebBrowser_put_Visible,
1086     WebBrowser_get_StatusBar,
1087     WebBrowser_put_StatusBar,
1088     WebBrowser_get_StatusText,
1089     WebBrowser_put_StatusText,
1090     WebBrowser_get_ToolBar,
1091     WebBrowser_put_ToolBar,
1092     WebBrowser_get_MenuBar,
1093     WebBrowser_put_MenuBar,
1094     WebBrowser_get_FullScreen,
1095     WebBrowser_put_FullScreen,
1096     WebBrowser_Navigate2,
1097     WebBrowser_QueryStatusWB,
1098     WebBrowser_ExecWB,
1099     WebBrowser_ShowBrowserBar,
1100     WebBrowser_get_ReadyState,
1101     WebBrowser_get_Offline,
1102     WebBrowser_put_Offline,
1103     WebBrowser_get_Silent,
1104     WebBrowser_put_Silent,
1105     WebBrowser_get_RegisterAsBrowser,
1106     WebBrowser_put_RegisterAsBrowser,
1107     WebBrowser_get_RegisterAsDropTarget,
1108     WebBrowser_put_RegisterAsDropTarget,
1109     WebBrowser_get_TheaterMode,
1110     WebBrowser_put_TheaterMode,
1111     WebBrowser_get_AddressBar,
1112     WebBrowser_put_AddressBar,
1113     WebBrowser_get_Resizable,
1114     WebBrowser_put_Resizable
1115 };
1116
1117 static inline WebBrowser *impl_from_IServiceProvider(IServiceProvider *iface)
1118 {
1119     return CONTAINING_RECORD(iface, WebBrowser, IServiceProvider_iface);
1120 }
1121
1122 static HRESULT WINAPI WBServiceProvider_QueryInterface(IServiceProvider *iface,
1123             REFIID riid, LPVOID *ppv)
1124 {
1125     WebBrowser *This = impl_from_IServiceProvider(iface);
1126     return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppv);
1127 }
1128
1129 static ULONG WINAPI WBServiceProvider_AddRef(IServiceProvider *iface)
1130 {
1131     WebBrowser *This = impl_from_IServiceProvider(iface);
1132     return IWebBrowser2_AddRef(&This->IWebBrowser2_iface);
1133 }
1134
1135 static ULONG WINAPI WBServiceProvider_Release(IServiceProvider *iface)
1136 {
1137     WebBrowser *This = impl_from_IServiceProvider(iface);
1138     return IWebBrowser2_Release(&This->IWebBrowser2_iface);
1139 }
1140
1141 static HRESULT STDMETHODCALLTYPE WBServiceProvider_QueryService(IServiceProvider *iface,
1142             REFGUID guidService, REFIID riid, void **ppv)
1143 {
1144     WebBrowser *This = impl_from_IServiceProvider(iface);
1145
1146     if(IsEqualGUID(&SID_SHTMLWindow, riid)) {
1147         TRACE("(%p)->(SID_SHTMLWindow)\n", This);
1148         return IHTMLWindow2_QueryInterface(&This->doc_host.html_window.IHTMLWindow2_iface, riid, ppv);
1149     }
1150
1151     if(IsEqualGUID(&IID_IBrowserService2, riid)) {
1152         TRACE("(%p)->(IID_IBrowserService2 return E_FAIL)\n", This);
1153         *ppv = NULL;
1154         return E_FAIL;
1155     }
1156
1157     FIXME("(%p)->(%s, %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
1158     *ppv = NULL;
1159     return E_NOINTERFACE;
1160 }
1161
1162 static const IServiceProviderVtbl ServiceProviderVtbl =
1163 {
1164     WBServiceProvider_QueryInterface,
1165     WBServiceProvider_AddRef,
1166     WBServiceProvider_Release,
1167     WBServiceProvider_QueryService
1168 };
1169
1170 static inline WebBrowser *impl_from_DocHost(DocHost *iface)
1171 {
1172     return CONTAINING_RECORD(iface, WebBrowser, doc_host);
1173 }
1174
1175 static ULONG WebBrowser_addref(DocHost *iface)
1176 {
1177     WebBrowser *This = impl_from_DocHost(iface);
1178     return IWebBrowser2_AddRef(&This->IWebBrowser2_iface);
1179 }
1180
1181 static ULONG WebBrowser_release(DocHost *iface)
1182 {
1183     WebBrowser *This = impl_from_DocHost(iface);
1184     return IWebBrowser2_Release(&This->IWebBrowser2_iface);
1185 }
1186
1187 static void WINAPI DocHostContainer_GetDocObjRect(DocHost* This, RECT* rc)
1188 {
1189     GetClientRect(This->frame_hwnd, rc);
1190 }
1191
1192 static HRESULT WINAPI DocHostContainer_SetStatusText(DocHost* This, LPCWSTR text)
1193 {
1194     return E_NOTIMPL;
1195 }
1196
1197 static void WINAPI DocHostContainer_SetURL(DocHost* This, LPCWSTR url)
1198 {
1199
1200 }
1201
1202 static HRESULT DocHostContainer_exec(DocHost *doc_host, const GUID *cmd_group, DWORD cmdid, DWORD execopt, VARIANT *in,
1203         VARIANT *out)
1204 {
1205     WebBrowser *This = impl_from_DocHost(doc_host);
1206     IOleCommandTarget *cmdtrg = NULL;
1207     HRESULT hres;
1208
1209     if(This->client) {
1210         hres = IOleClientSite_QueryInterface(This->client, &IID_IOleCommandTarget, (void**)&cmdtrg);
1211         if(FAILED(hres))
1212             cmdtrg = NULL;
1213     }
1214
1215     if(!cmdtrg && This->container) {
1216         hres = IOleContainer_QueryInterface(This->container, &IID_IOleCommandTarget, (void**)&cmdtrg);
1217         if(FAILED(hres))
1218             cmdtrg = NULL;
1219     }
1220
1221     if(!cmdtrg)
1222         return S_OK;
1223
1224     hres = IOleCommandTarget_Exec(cmdtrg, cmd_group, cmdid, execopt, in, out);
1225     IOleCommandTarget_Release(cmdtrg);
1226     if(FAILED(hres))
1227         FIXME("Exec failed\n");
1228
1229     return hres;
1230 }
1231
1232 static const IDocHostContainerVtbl DocHostContainerVtbl = {
1233     WebBrowser_addref,
1234     WebBrowser_release,
1235     DocHostContainer_GetDocObjRect,
1236     DocHostContainer_SetStatusText,
1237     DocHostContainer_SetURL,
1238     DocHostContainer_exec
1239 };
1240
1241 static HRESULT create_webbrowser(int version, IUnknown *outer, REFIID riid, void **ppv)
1242 {
1243     WebBrowser *ret;
1244     HRESULT hres;
1245
1246     TRACE("(%p %s %p) version=%d\n", outer, debugstr_guid(riid), ppv, version);
1247
1248     ret = heap_alloc_zero(sizeof(WebBrowser));
1249
1250     ret->IWebBrowser2_iface.lpVtbl = &WebBrowser2Vtbl;
1251     ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
1252     ret->ref = 1;
1253     ret->version = version;
1254
1255     DocHost_Init(&ret->doc_host, &ret->IWebBrowser2_iface, &DocHostContainerVtbl);
1256
1257     ret->visible = VARIANT_TRUE;
1258     ret->menu_bar = VARIANT_TRUE;
1259     ret->address_bar = VARIANT_TRUE;
1260     ret->status_bar = VARIANT_TRUE;
1261     ret->tool_bar = VARIANT_TRUE;
1262
1263     WebBrowser_OleObject_Init(ret);
1264     WebBrowser_ViewObject_Init(ret);
1265     WebBrowser_Persist_Init(ret);
1266     WebBrowser_ClassInfo_Init(ret);
1267
1268     HlinkFrame_Init(&ret->hlink_frame, (IUnknown*)&ret->IWebBrowser2_iface, &ret->doc_host);
1269
1270     lock_module();
1271
1272     hres = IWebBrowser2_QueryInterface(&ret->IWebBrowser2_iface, riid, ppv);
1273
1274     IWebBrowser2_Release(&ret->IWebBrowser2_iface);
1275     return hres;
1276 }
1277
1278 HRESULT WINAPI WebBrowserV1_Create(IClassFactory *iface, IUnknown *pOuter, REFIID riid, void **ppv)
1279 {
1280     return create_webbrowser(1, pOuter, riid, ppv);
1281 }
1282
1283 HRESULT WINAPI WebBrowser_Create(IClassFactory *iface, IUnknown *pOuter, REFIID riid, void **ppv)
1284 {
1285     return create_webbrowser(2, pOuter, riid, ppv);
1286 }