rpcrt4: Don't try to bind to a null handle.
[wine] / dlls / mshtml / oleobj.c
1 /*
2  * Copyright 2005 Jacek Caban
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 "config.h"
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "ole2.h"
30 #include "shlguid.h"
31 #include "shdeprecated.h"
32 #include "mshtmdid.h"
33 #include "idispids.h"
34
35 #include "wine/debug.h"
36
37 #include "mshtml_private.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
40
41 #define DOCHOST_DOCCANNAVIGATE  0
42
43 /**********************************************************
44  * IOleObject implementation
45  */
46
47 static inline HTMLDocument *impl_from_IOleObject(IOleObject *iface)
48 {
49     return CONTAINING_RECORD(iface, HTMLDocument, IOleObject_iface);
50 }
51
52 static HRESULT WINAPI OleObject_QueryInterface(IOleObject *iface, REFIID riid, void **ppv)
53 {
54     HTMLDocument *This = impl_from_IOleObject(iface);
55     return htmldoc_query_interface(This, riid, ppv);
56 }
57
58 static ULONG WINAPI OleObject_AddRef(IOleObject *iface)
59 {
60     HTMLDocument *This = impl_from_IOleObject(iface);
61     return htmldoc_addref(This);
62 }
63
64 static ULONG WINAPI OleObject_Release(IOleObject *iface)
65 {
66     HTMLDocument *This = impl_from_IOleObject(iface);
67     return htmldoc_release(This);
68 }
69
70 static void update_hostinfo(HTMLDocumentObj *This, DOCHOSTUIINFO *hostinfo)
71 {
72     nsIScrollable *scrollable;
73     nsresult nsres;
74
75     if(!This->nscontainer)
76         return;
77
78     nsres = nsIWebBrowser_QueryInterface(This->nscontainer->webbrowser, &IID_nsIScrollable, (void**)&scrollable);
79     if(NS_SUCCEEDED(nsres)) {
80         nsres = nsIScrollable_SetDefaultScrollbarPreferences(scrollable, ScrollOrientation_Y,
81                 (hostinfo->dwFlags & DOCHOSTUIFLAG_SCROLL_NO) ? Scrollbar_Never : Scrollbar_Always);
82         if(NS_FAILED(nsres))
83             ERR("Could not set default Y scrollbar prefs: %08x\n", nsres);
84
85         nsres = nsIScrollable_SetDefaultScrollbarPreferences(scrollable, ScrollOrientation_X,
86                 hostinfo->dwFlags & DOCHOSTUIFLAG_SCROLL_NO ? Scrollbar_Never : Scrollbar_Auto);
87         if(NS_FAILED(nsres))
88             ERR("Could not set default X scrollbar prefs: %08x\n", nsres);
89
90         nsIScrollable_Release(scrollable);
91     }else {
92         ERR("Could not get nsIScrollable: %08x\n", nsres);
93     }
94 }
95
96 static HRESULT WINAPI OleObject_SetClientSite(IOleObject *iface, IOleClientSite *pClientSite)
97 {
98     HTMLDocument *This = impl_from_IOleObject(iface);
99     IOleCommandTarget *cmdtrg = NULL;
100     IOleWindow *ole_window;
101     IServiceProvider *sp;
102     BOOL hostui_setup;
103     VARIANT silent;
104     HWND hwnd;
105     HRESULT hres;
106
107     TRACE("(%p)->(%p)\n", This, pClientSite);
108
109     if(pClientSite == This->doc_obj->client)
110         return S_OK;
111
112     if(This->doc_obj->client) {
113         IOleClientSite_Release(This->doc_obj->client);
114         This->doc_obj->client = NULL;
115         This->doc_obj->usermode = UNKNOWN_USERMODE;
116     }
117
118     if(This->doc_obj->hostui && !This->doc_obj->custom_hostui) {
119         IDocHostUIHandler_Release(This->doc_obj->hostui);
120         This->doc_obj->hostui = NULL;
121     }
122
123     if(This->doc_obj->doc_object_service) {
124         IDocObjectService_Release(This->doc_obj->doc_object_service);
125         This->doc_obj->doc_object_service = NULL;
126     }
127
128     memset(&This->doc_obj->hostinfo, 0, sizeof(DOCHOSTUIINFO));
129
130     if(!pClientSite)
131         return S_OK;
132
133     IOleClientSite_AddRef(pClientSite);
134     This->doc_obj->client = pClientSite;
135
136     hres = IOleClientSite_QueryInterface(pClientSite, &IID_IServiceProvider, (void**)&sp);
137     if(SUCCEEDED(hres)) {
138         IBrowserService *browser_service;
139         IDocObjectService *doc_object_service;
140
141         hres = IServiceProvider_QueryService(sp, &IID_IShellBrowser,
142                 &IID_IBrowserService, (void**)&browser_service);
143         if(SUCCEEDED(hres)) {
144             hres = IBrowserService_QueryInterface(browser_service,
145                     &IID_IDocObjectService, (void**)&doc_object_service);
146             if(SUCCEEDED(hres))
147                 This->doc_obj->doc_object_service = doc_object_service;
148
149             IBrowserService_Release(browser_service);
150         }
151
152         IServiceProvider_Release(sp);
153     }
154
155     hostui_setup = This->doc_obj->hostui_setup;
156
157     if(!This->doc_obj->hostui) {
158         IDocHostUIHandler *uihandler;
159
160         This->doc_obj->custom_hostui = FALSE;
161
162         hres = IOleObject_QueryInterface(pClientSite, &IID_IDocHostUIHandler, (void**)&uihandler);
163         if(SUCCEEDED(hres))
164             This->doc_obj->hostui = uihandler;
165     }
166
167     if(This->doc_obj->hostui) {
168         DOCHOSTUIINFO hostinfo;
169         LPOLESTR key_path = NULL, override_key_path = NULL;
170         IDocHostUIHandler2 *uihandler2;
171
172         memset(&hostinfo, 0, sizeof(DOCHOSTUIINFO));
173         hostinfo.cbSize = sizeof(DOCHOSTUIINFO);
174         hres = IDocHostUIHandler_GetHostInfo(This->doc_obj->hostui, &hostinfo);
175         if(SUCCEEDED(hres)) {
176             TRACE("hostinfo = {%u %08x %08x %s %s}\n",
177                     hostinfo.cbSize, hostinfo.dwFlags, hostinfo.dwDoubleClick,
178                     debugstr_w(hostinfo.pchHostCss), debugstr_w(hostinfo.pchHostNS));
179             update_hostinfo(This->doc_obj, &hostinfo);
180             This->doc_obj->hostinfo = hostinfo;
181         }
182
183         if(!hostui_setup) {
184             hres = IDocHostUIHandler_GetOptionKeyPath(This->doc_obj->hostui, &key_path, 0);
185             if(hres == S_OK && key_path) {
186                 if(key_path[0]) {
187                     /* FIXME: use key_path */
188                     TRACE("key_path = %s\n", debugstr_w(key_path));
189                 }
190                 CoTaskMemFree(key_path);
191             }
192
193             hres = IDocHostUIHandler_QueryInterface(This->doc_obj->hostui, &IID_IDocHostUIHandler2,
194                     (void**)&uihandler2);
195             if(SUCCEEDED(hres)) {
196                 hres = IDocHostUIHandler2_GetOverrideKeyPath(uihandler2, &override_key_path, 0);
197                 if(hres == S_OK && override_key_path && override_key_path[0]) {
198                     if(override_key_path[0]) {
199                         /*FIXME: use override_key_path */
200                         TRACE("override_key_path = %s\n", debugstr_w(override_key_path));
201                     }
202                     CoTaskMemFree(override_key_path);
203                 }
204                 IDocHostUIHandler2_Release(uihandler2);
205             }
206
207             This->doc_obj->hostui_setup = TRUE;
208         }
209     }
210
211     /* Native calls here GetWindow. What is it for?
212      * We don't have anything to do with it here (yet). */
213     hres = IOleClientSite_QueryInterface(pClientSite, &IID_IOleWindow, (void**)&ole_window);
214     if(SUCCEEDED(hres)) {
215         IOleWindow_GetWindow(ole_window, &hwnd);
216         IOleWindow_Release(ole_window);
217     }
218
219     hres = IOleClientSite_QueryInterface(pClientSite, &IID_IOleCommandTarget, (void**)&cmdtrg);
220     if(SUCCEEDED(hres)) {
221         VARIANT var;
222         OLECMD cmd = {OLECMDID_SETPROGRESSTEXT, 0};
223
224         if(!hostui_setup) {
225             V_VT(&var) = VT_UNKNOWN;
226             V_UNKNOWN(&var) = (IUnknown*)&This->window->IHTMLWindow2_iface;
227             IOleCommandTarget_Exec(cmdtrg, &CGID_DocHostCmdPriv, DOCHOST_DOCCANNAVIGATE, 0, &var, NULL);
228         }
229
230         IOleCommandTarget_QueryStatus(cmdtrg, NULL, 1, &cmd, NULL);
231
232         V_VT(&var) = VT_I4;
233         V_I4(&var) = 0;
234         IOleCommandTarget_Exec(cmdtrg, NULL, OLECMDID_SETPROGRESSMAX,
235                 OLECMDEXECOPT_DONTPROMPTUSER, &var, NULL);
236         IOleCommandTarget_Exec(cmdtrg, NULL, OLECMDID_SETPROGRESSPOS, 
237                 OLECMDEXECOPT_DONTPROMPTUSER, &var, NULL);
238
239         IOleCommandTarget_Release(cmdtrg);
240     }
241
242     if(This->doc_obj->usermode == UNKNOWN_USERMODE)
243         IOleControl_OnAmbientPropertyChange(&This->IOleControl_iface, DISPID_AMBIENT_USERMODE);
244
245     IOleControl_OnAmbientPropertyChange(&This->IOleControl_iface,
246             DISPID_AMBIENT_OFFLINEIFNOTCONNECTED);
247
248     hres = get_client_disp_property(This->doc_obj->client, DISPID_AMBIENT_SILENT, &silent);
249     if(SUCCEEDED(hres)) {
250         if(V_VT(&silent) != VT_BOOL)
251             WARN("V_VT(silent) = %d\n", V_VT(&silent));
252         else if(V_BOOL(&silent))
253             FIXME("silent == true\n");
254     }
255
256     IOleControl_OnAmbientPropertyChange(&This->IOleControl_iface, DISPID_AMBIENT_USERAGENT);
257     IOleControl_OnAmbientPropertyChange(&This->IOleControl_iface, DISPID_AMBIENT_PALETTE);
258
259     return S_OK;
260 }
261
262 static HRESULT WINAPI OleObject_GetClientSite(IOleObject *iface, IOleClientSite **ppClientSite)
263 {
264     HTMLDocument *This = impl_from_IOleObject(iface);
265
266     TRACE("(%p)->(%p)\n", This, ppClientSite);
267
268     if(!ppClientSite)
269         return E_INVALIDARG;
270
271     if(This->doc_obj->client)
272         IOleClientSite_AddRef(This->doc_obj->client);
273     *ppClientSite = This->doc_obj->client;
274
275     return S_OK;
276 }
277
278 static HRESULT WINAPI OleObject_SetHostNames(IOleObject *iface, LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
279 {
280     HTMLDocument *This = impl_from_IOleObject(iface);
281     FIXME("(%p)->(%s %s)\n", This, debugstr_w(szContainerApp), debugstr_w(szContainerObj));
282     return E_NOTIMPL;
283 }
284
285 static HRESULT WINAPI OleObject_Close(IOleObject *iface, DWORD dwSaveOption)
286 {
287     HTMLDocument *This = impl_from_IOleObject(iface);
288
289     TRACE("(%p)->(%08x)\n", This, dwSaveOption);
290
291     if(dwSaveOption == OLECLOSE_PROMPTSAVE)
292         FIXME("OLECLOSE_PROMPTSAVE not implemented\n");
293
294     if(This->doc_obj->in_place_active)
295         IOleInPlaceObjectWindowless_InPlaceDeactivate(&This->IOleInPlaceObjectWindowless_iface);
296
297     HTMLDocument_LockContainer(This->doc_obj, FALSE);
298
299     if(This->advise_holder)
300         IOleAdviseHolder_SendOnClose(This->advise_holder);
301     
302     return S_OK;
303 }
304
305 static HRESULT WINAPI OleObject_SetMoniker(IOleObject *iface, DWORD dwWhichMoniker, IMoniker *pmk)
306 {
307     HTMLDocument *This = impl_from_IOleObject(iface);
308     FIXME("(%p %d %p)->()\n", This, dwWhichMoniker, pmk);
309     return E_NOTIMPL;
310 }
311
312 static HRESULT WINAPI OleObject_GetMoniker(IOleObject *iface, DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk)
313 {
314     HTMLDocument *This = impl_from_IOleObject(iface);
315     FIXME("(%p)->(%d %d %p)\n", This, dwAssign, dwWhichMoniker, ppmk);
316     return E_NOTIMPL;
317 }
318
319 static HRESULT WINAPI OleObject_InitFromData(IOleObject *iface, IDataObject *pDataObject, BOOL fCreation,
320                                         DWORD dwReserved)
321 {
322     HTMLDocument *This = impl_from_IOleObject(iface);
323     FIXME("(%p)->(%p %x %d)\n", This, pDataObject, fCreation, dwReserved);
324     return E_NOTIMPL;
325 }
326
327 static HRESULT WINAPI OleObject_GetClipboardData(IOleObject *iface, DWORD dwReserved, IDataObject **ppDataObject)
328 {
329     HTMLDocument *This = impl_from_IOleObject(iface);
330     FIXME("(%p)->(%d %p)\n", This, dwReserved, ppDataObject);
331     return E_NOTIMPL;
332 }
333
334 static HRESULT WINAPI OleObject_DoVerb(IOleObject *iface, LONG iVerb, LPMSG lpmsg, IOleClientSite *pActiveSite,
335                                         LONG lindex, HWND hwndParent, LPCRECT lprcPosRect)
336 {
337     HTMLDocument *This = impl_from_IOleObject(iface);
338     IOleDocumentSite *pDocSite;
339     HRESULT hres;
340
341     TRACE("(%p)->(%d %p %p %d %p %p)\n", This, iVerb, lpmsg, pActiveSite, lindex, hwndParent, lprcPosRect);
342
343     if(iVerb != OLEIVERB_SHOW && iVerb != OLEIVERB_UIACTIVATE && iVerb != OLEIVERB_INPLACEACTIVATE) { 
344         FIXME("iVerb = %d not supported\n", iVerb);
345         return E_NOTIMPL;
346     }
347
348     if(!pActiveSite)
349         pActiveSite = This->doc_obj->client;
350
351     hres = IOleClientSite_QueryInterface(pActiveSite, &IID_IOleDocumentSite, (void**)&pDocSite);
352     if(SUCCEEDED(hres)) {
353         HTMLDocument_LockContainer(This->doc_obj, TRUE);
354
355         /* FIXME: Create new IOleDocumentView. See CreateView for more info. */
356         hres = IOleDocumentSite_ActivateMe(pDocSite, &This->IOleDocumentView_iface);
357         IOleDocumentSite_Release(pDocSite);
358     }else {
359         hres = IOleDocumentView_UIActivate(&This->IOleDocumentView_iface, TRUE);
360         if(SUCCEEDED(hres)) {
361             if(lprcPosRect) {
362                 RECT rect; /* We need to pass rect as not const pointer */
363                 rect = *lprcPosRect;
364                 IOleDocumentView_SetRect(&This->IOleDocumentView_iface, &rect);
365             }
366             IOleDocumentView_Show(&This->IOleDocumentView_iface, TRUE);
367         }
368     }
369
370     return hres;
371 }
372
373 static HRESULT WINAPI OleObject_EnumVerbs(IOleObject *iface, IEnumOLEVERB **ppEnumOleVerb)
374 {
375     HTMLDocument *This = impl_from_IOleObject(iface);
376     FIXME("(%p)->(%p)\n", This, ppEnumOleVerb);
377     return E_NOTIMPL;
378 }
379
380 static HRESULT WINAPI OleObject_Update(IOleObject *iface)
381 {
382     HTMLDocument *This = impl_from_IOleObject(iface);
383     FIXME("(%p)\n", This);
384     return E_NOTIMPL;
385 }
386
387 static HRESULT WINAPI OleObject_IsUpToDate(IOleObject *iface)
388 {
389     HTMLDocument *This = impl_from_IOleObject(iface);
390     FIXME("(%p)\n", This);
391     return E_NOTIMPL;
392 }
393
394 static HRESULT WINAPI OleObject_GetUserClassID(IOleObject *iface, CLSID *pClsid)
395 {
396     HTMLDocument *This = impl_from_IOleObject(iface);
397
398     TRACE("(%p)->(%p)\n", This, pClsid);
399
400     if(!pClsid)
401         return E_INVALIDARG;
402
403     *pClsid = CLSID_HTMLDocument;
404     return S_OK;
405 }
406
407 static HRESULT WINAPI OleObject_GetUserType(IOleObject *iface, DWORD dwFormOfType, LPOLESTR *pszUserType)
408 {
409     HTMLDocument *This = impl_from_IOleObject(iface);
410     FIXME("(%p)->(%d %p)\n", This, dwFormOfType, pszUserType);
411     return E_NOTIMPL;
412 }
413
414 static HRESULT WINAPI OleObject_SetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel)
415 {
416     HTMLDocument *This = impl_from_IOleObject(iface);
417     FIXME("(%p)->(%d %p)\n", This, dwDrawAspect, psizel);
418     return E_NOTIMPL;
419 }
420
421 static HRESULT WINAPI OleObject_GetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel)
422 {
423     HTMLDocument *This = impl_from_IOleObject(iface);
424     FIXME("(%p)->(%d %p)\n", This, dwDrawAspect, psizel);
425     return E_NOTIMPL;
426 }
427
428 static HRESULT WINAPI OleObject_Advise(IOleObject *iface, IAdviseSink *pAdvSink, DWORD *pdwConnection)
429 {
430     HTMLDocument *This = impl_from_IOleObject(iface);
431     TRACE("(%p)->(%p %p)\n", This, pAdvSink, pdwConnection);
432
433     if(!pdwConnection)
434         return E_INVALIDARG;
435
436     if(!pAdvSink) {
437         *pdwConnection = 0;
438         return E_INVALIDARG;
439     }
440
441     if(!This->advise_holder) {
442         CreateOleAdviseHolder(&This->advise_holder);
443         if(!This->advise_holder)
444             return E_OUTOFMEMORY;
445     }
446
447     return IOleAdviseHolder_Advise(This->advise_holder, pAdvSink, pdwConnection);
448 }
449
450 static HRESULT WINAPI OleObject_Unadvise(IOleObject *iface, DWORD dwConnection)
451 {
452     HTMLDocument *This = impl_from_IOleObject(iface);
453     TRACE("(%p)->(%d)\n", This, dwConnection);
454
455     if(!This->advise_holder)
456         return OLE_E_NOCONNECTION;
457
458     return IOleAdviseHolder_Unadvise(This->advise_holder, dwConnection);
459 }
460
461 static HRESULT WINAPI OleObject_EnumAdvise(IOleObject *iface, IEnumSTATDATA **ppenumAdvise)
462 {
463     HTMLDocument *This = impl_from_IOleObject(iface);
464
465     if(!This->advise_holder) {
466         *ppenumAdvise = NULL;
467         return S_OK;
468     }
469
470     return IOleAdviseHolder_EnumAdvise(This->advise_holder, ppenumAdvise);
471 }
472
473 static HRESULT WINAPI OleObject_GetMiscStatus(IOleObject *iface, DWORD dwAspect, DWORD *pdwStatus)
474 {
475     HTMLDocument *This = impl_from_IOleObject(iface);
476     FIXME("(%p)->(%d %p)\n", This, dwAspect, pdwStatus);
477     return E_NOTIMPL;
478 }
479
480 static HRESULT WINAPI OleObject_SetColorScheme(IOleObject *iface, LOGPALETTE *pLogpal)
481 {
482     HTMLDocument *This = impl_from_IOleObject(iface);
483     FIXME("(%p)->(%p)\n", This, pLogpal);
484     return E_NOTIMPL;
485 }
486
487 static const IOleObjectVtbl OleObjectVtbl = {
488     OleObject_QueryInterface,
489     OleObject_AddRef,
490     OleObject_Release,
491     OleObject_SetClientSite,
492     OleObject_GetClientSite,
493     OleObject_SetHostNames,
494     OleObject_Close,
495     OleObject_SetMoniker,
496     OleObject_GetMoniker,
497     OleObject_InitFromData,
498     OleObject_GetClipboardData,
499     OleObject_DoVerb,
500     OleObject_EnumVerbs,
501     OleObject_Update,
502     OleObject_IsUpToDate,
503     OleObject_GetUserClassID,
504     OleObject_GetUserType,
505     OleObject_SetExtent,
506     OleObject_GetExtent,
507     OleObject_Advise,
508     OleObject_Unadvise,
509     OleObject_EnumAdvise,
510     OleObject_GetMiscStatus,
511     OleObject_SetColorScheme
512 };
513
514 /**********************************************************
515  * IOleDocument implementation
516  */
517
518 static inline HTMLDocument *impl_from_IOleDocument(IOleDocument *iface)
519 {
520     return CONTAINING_RECORD(iface, HTMLDocument, IOleDocument_iface);
521 }
522
523 static HRESULT WINAPI OleDocument_QueryInterface(IOleDocument *iface, REFIID riid, void **ppv)
524 {
525     HTMLDocument *This = impl_from_IOleDocument(iface);
526     return htmldoc_query_interface(This, riid, ppv);
527 }
528
529 static ULONG WINAPI OleDocument_AddRef(IOleDocument *iface)
530 {
531     HTMLDocument *This = impl_from_IOleDocument(iface);
532     return htmldoc_addref(This);
533 }
534
535 static ULONG WINAPI OleDocument_Release(IOleDocument *iface)
536 {
537     HTMLDocument *This = impl_from_IOleDocument(iface);
538     return htmldoc_release(This);
539 }
540
541 static HRESULT WINAPI OleDocument_CreateView(IOleDocument *iface, IOleInPlaceSite *pIPSite, IStream *pstm,
542                                    DWORD dwReserved, IOleDocumentView **ppView)
543 {
544     HTMLDocument *This = impl_from_IOleDocument(iface);
545     HRESULT hres;
546
547     TRACE("(%p)->(%p %p %d %p)\n", This, pIPSite, pstm, dwReserved, ppView);
548
549     if(!ppView)
550         return E_INVALIDARG;
551
552     /* FIXME:
553      * Windows implementation creates new IOleDocumentView when function is called for the
554      * first time and returns E_FAIL when it is called for the second time, but it doesn't matter
555      * if the application uses returned interfaces, passed to ActivateMe or returned by
556      * QueryInterface, so there is no reason to create new interface. This needs more testing.
557      */
558
559     if(pIPSite) {
560         hres = IOleDocumentView_SetInPlaceSite(&This->IOleDocumentView_iface, pIPSite);
561         if(FAILED(hres))
562             return hres;
563     }
564
565     if(pstm)
566         FIXME("pstm is not supported\n");
567
568     IOleDocumentView_AddRef(&This->IOleDocumentView_iface);
569     *ppView = &This->IOleDocumentView_iface;
570     return S_OK;
571 }
572
573 static HRESULT WINAPI OleDocument_GetDocMiscStatus(IOleDocument *iface, DWORD *pdwStatus)
574 {
575     HTMLDocument *This = impl_from_IOleDocument(iface);
576     FIXME("(%p)->(%p)\n", This, pdwStatus);
577     return E_NOTIMPL;
578 }
579
580 static HRESULT WINAPI OleDocument_EnumViews(IOleDocument *iface, IEnumOleDocumentViews **ppEnum,
581                                    IOleDocumentView **ppView)
582 {
583     HTMLDocument *This = impl_from_IOleDocument(iface);
584     FIXME("(%p)->(%p %p)\n", This, ppEnum, ppView);
585     return E_NOTIMPL;
586 }
587
588 static const IOleDocumentVtbl OleDocumentVtbl = {
589     OleDocument_QueryInterface,
590     OleDocument_AddRef,
591     OleDocument_Release,
592     OleDocument_CreateView,
593     OleDocument_GetDocMiscStatus,
594     OleDocument_EnumViews
595 };
596
597 /**********************************************************
598  * IOleControl implementation
599  */
600
601 static inline HTMLDocument *impl_from_IOleControl(IOleControl *iface)
602 {
603     return CONTAINING_RECORD(iface, HTMLDocument, IOleControl_iface);
604 }
605
606 static HRESULT WINAPI OleControl_QueryInterface(IOleControl *iface, REFIID riid, void **ppv)
607 {
608     HTMLDocument *This = impl_from_IOleControl(iface);
609     return htmldoc_query_interface(This, riid, ppv);
610 }
611
612 static ULONG WINAPI OleControl_AddRef(IOleControl *iface)
613 {
614     HTMLDocument *This = impl_from_IOleControl(iface);
615     return htmldoc_addref(This);
616 }
617
618 static ULONG WINAPI OleControl_Release(IOleControl *iface)
619 {
620     HTMLDocument *This = impl_from_IOleControl(iface);
621     return htmldoc_release(This);
622 }
623
624 static HRESULT WINAPI OleControl_GetControlInfo(IOleControl *iface, CONTROLINFO *pCI)
625 {
626     HTMLDocument *This = impl_from_IOleControl(iface);
627     FIXME("(%p)->(%p)\n", This, pCI);
628     return E_NOTIMPL;
629 }
630
631 static HRESULT WINAPI OleControl_OnMnemonic(IOleControl *iface, MSG *pMsg)
632 {
633     HTMLDocument *This = impl_from_IOleControl(iface);
634     FIXME("(%p)->(%p)\n", This, pMsg);
635     return E_NOTIMPL;
636 }
637
638 HRESULT get_client_disp_property(IOleClientSite *client, DISPID dispid, VARIANT *res)
639 {
640     IDispatch *disp = NULL;
641     DISPPARAMS dispparams = {NULL, 0};
642     UINT err;
643     HRESULT hres;
644
645     hres = IOleClientSite_QueryInterface(client, &IID_IDispatch, (void**)&disp);
646     if(FAILED(hres)) {
647         TRACE("Could not get IDispatch\n");
648         return hres;
649     }
650
651     VariantInit(res);
652
653     hres = IDispatch_Invoke(disp, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT,
654             DISPATCH_PROPERTYGET, &dispparams, res, NULL, &err);
655
656     IDispatch_Release(disp);
657
658     return hres;
659 }
660
661 static HRESULT on_change_dlcontrol(HTMLDocument *This)
662 {
663     VARIANT res;
664     HRESULT hres;
665     
666     hres = get_client_disp_property(This->doc_obj->client, DISPID_AMBIENT_DLCONTROL, &res);
667     if(SUCCEEDED(hres))
668         FIXME("unsupported dlcontrol %08x\n", V_I4(&res));
669
670     return S_OK;
671 }
672
673 static HRESULT WINAPI OleControl_OnAmbientPropertyChange(IOleControl *iface, DISPID dispID)
674 {
675     HTMLDocument *This = impl_from_IOleControl(iface);
676     IOleClientSite *client;
677     VARIANT res;
678     HRESULT hres;
679
680     client = This->doc_obj->client;
681     if(!client) {
682         TRACE("client = NULL\n");
683         return S_OK;
684     }
685
686     switch(dispID) {
687     case DISPID_AMBIENT_USERMODE:
688         TRACE("(%p)->(DISPID_AMBIENT_USERMODE)\n", This);
689         hres = get_client_disp_property(client, DISPID_AMBIENT_USERMODE, &res);
690         if(FAILED(hres))
691             return S_OK;
692
693         if(V_VT(&res) == VT_BOOL) {
694             if(V_BOOL(&res)) {
695                 This->doc_obj->usermode = BROWSEMODE;
696             }else {
697                 FIXME("edit mode is not supported\n");
698                 This->doc_obj->usermode = EDITMODE;
699             }
700         }else {
701             FIXME("V_VT(res)=%d\n", V_VT(&res));
702         }
703         return S_OK;
704     case DISPID_AMBIENT_DLCONTROL:
705         TRACE("(%p)->(DISPID_AMBIENT_DLCONTROL)\n", This);
706         return on_change_dlcontrol(This);
707     case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED:
708         TRACE("(%p)->(DISPID_AMBIENT_OFFLINEIFNOTCONNECTED)\n", This);
709         on_change_dlcontrol(This);
710         hres = get_client_disp_property(client, DISPID_AMBIENT_OFFLINEIFNOTCONNECTED, &res);
711         if(FAILED(hres))
712             return S_OK;
713
714         if(V_VT(&res) == VT_BOOL) {
715             if(V_BOOL(&res)) {
716                 FIXME("offline connection is not supported\n");
717                 hres = E_FAIL;
718             }
719         }else {
720             FIXME("V_VT(res)=%d\n", V_VT(&res));
721         }
722         return S_OK;
723     case DISPID_AMBIENT_SILENT:
724         TRACE("(%p)->(DISPID_AMBIENT_SILENT)\n", This);
725         on_change_dlcontrol(This);
726         hres = get_client_disp_property(client, DISPID_AMBIENT_SILENT, &res);
727         if(FAILED(hres))
728             return S_OK;
729
730         if(V_VT(&res) == VT_BOOL) {
731             if(V_BOOL(&res)) {
732                 FIXME("silent mode is not supported\n");
733                 hres = E_FAIL;
734             }
735         }else {
736             FIXME("V_VT(res)=%d\n", V_VT(&res));
737         }
738         return S_OK;
739     case DISPID_AMBIENT_USERAGENT:
740         TRACE("(%p)->(DISPID_AMBIENT_USERAGENT)\n", This);
741         hres = get_client_disp_property(client, DISPID_AMBIENT_USERAGENT, &res);
742         if(FAILED(hres))
743             return S_OK;
744
745         FIXME("not supported AMBIENT_USERAGENT\n");
746         hres = E_FAIL;
747         return S_OK;
748     case DISPID_AMBIENT_PALETTE:
749         TRACE("(%p)->(DISPID_AMBIENT_PALETTE)\n", This);
750         hres = get_client_disp_property(client, DISPID_AMBIENT_PALETTE, &res);
751         if(FAILED(hres))
752             return S_OK;
753
754         FIXME("not supported AMBIENT_PALETTE\n");
755         hres = E_FAIL;
756         return S_OK;
757     }
758
759     FIXME("(%p) unsupported dispID=%d\n", This, dispID);
760     return E_FAIL;
761 }
762
763 static HRESULT WINAPI OleControl_FreezeEvents(IOleControl *iface, BOOL bFreeze)
764 {
765     HTMLDocument *This = impl_from_IOleControl(iface);
766     FIXME("(%p)->(%x)\n", This, bFreeze);
767     return E_NOTIMPL;
768 }
769
770 static const IOleControlVtbl OleControlVtbl = {
771     OleControl_QueryInterface,
772     OleControl_AddRef,
773     OleControl_Release,
774     OleControl_GetControlInfo,
775     OleControl_OnMnemonic,
776     OleControl_OnAmbientPropertyChange,
777     OleControl_FreezeEvents
778 };
779
780 /**********************************************************
781  * IObjectWithSite implementation
782  */
783
784 static inline HTMLDocument *impl_from_IObjectWithSite(IObjectWithSite *iface)
785 {
786     return CONTAINING_RECORD(iface, HTMLDocument, IObjectWithSite_iface);
787 }
788
789 static HRESULT WINAPI ObjectWithSite_QueryInterface(IObjectWithSite *iface, REFIID riid, void **ppv)
790 {
791     HTMLDocument *This = impl_from_IObjectWithSite(iface);
792     return htmldoc_query_interface(This, riid, ppv);
793 }
794
795 static ULONG WINAPI ObjectWithSite_AddRef(IObjectWithSite *iface)
796 {
797     HTMLDocument *This = impl_from_IObjectWithSite(iface);
798     return htmldoc_addref(This);
799 }
800
801 static ULONG WINAPI ObjectWithSite_Release(IObjectWithSite *iface)
802 {
803     HTMLDocument *This = impl_from_IObjectWithSite(iface);
804     return htmldoc_release(This);
805 }
806
807 static HRESULT WINAPI ObjectWithSite_SetSite(IObjectWithSite *iface, IUnknown *pUnkSite)
808 {
809     HTMLDocument *This = impl_from_IObjectWithSite(iface);
810     FIXME("(%p)->(%p)\n", This, pUnkSite);
811     return E_NOTIMPL;
812 }
813
814 static HRESULT WINAPI ObjectWithSite_GetSite(IObjectWithSite* iface, REFIID riid, PVOID *ppvSite)
815 {
816     HTMLDocument *This = impl_from_IObjectWithSite(iface);
817     FIXME("(%p)->(%p)\n", This, ppvSite);
818     return E_NOTIMPL;
819 }
820
821 static const IObjectWithSiteVtbl ObjectWithSiteVtbl = {
822     ObjectWithSite_QueryInterface,
823     ObjectWithSite_AddRef,
824     ObjectWithSite_Release,
825     ObjectWithSite_SetSite,
826     ObjectWithSite_GetSite
827 };
828
829 /**********************************************************
830  * IOleContainer implementation
831  */
832
833 static inline HTMLDocument *impl_from_IOleContainer(IOleContainer *iface)
834 {
835     return CONTAINING_RECORD(iface, HTMLDocument, IOleContainer_iface);
836 }
837
838 static HRESULT WINAPI OleContainer_QueryInterface(IOleContainer *iface, REFIID riid, void **ppv)
839 {
840     HTMLDocument *This = impl_from_IOleContainer(iface);
841     return htmldoc_query_interface(This, riid, ppv);
842 }
843
844 static ULONG WINAPI OleContainer_AddRef(IOleContainer *iface)
845 {
846     HTMLDocument *This = impl_from_IOleContainer(iface);
847     return htmldoc_addref(This);
848 }
849
850 static ULONG WINAPI OleContainer_Release(IOleContainer *iface)
851 {
852     HTMLDocument *This = impl_from_IOleContainer(iface);
853     return htmldoc_release(This);
854 }
855
856 static HRESULT WINAPI OleContainer_ParseDisplayName(IOleContainer *iface, IBindCtx *pbc, LPOLESTR pszDisplayName,
857         ULONG *pchEaten, IMoniker **ppmkOut)
858 {
859     HTMLDocument *This = impl_from_IOleContainer(iface);
860     FIXME("(%p)->(%p %s %p %p)\n", This, pbc, debugstr_w(pszDisplayName), pchEaten, ppmkOut);
861     return E_NOTIMPL;
862 }
863
864 static HRESULT WINAPI OleContainer_EnumObjects(IOleContainer *iface, DWORD grfFlags, IEnumUnknown **ppenum)
865 {
866     HTMLDocument *This = impl_from_IOleContainer(iface);
867     FIXME("(%p)->(%x %p)\n", This, grfFlags, ppenum);
868     return E_NOTIMPL;
869 }
870
871 static HRESULT WINAPI OleContainer_LockContainer(IOleContainer *iface, BOOL fLock)
872 {
873     HTMLDocument *This = impl_from_IOleContainer(iface);
874     FIXME("(%p)->(%x)\n", This, fLock);
875     return E_NOTIMPL;
876 }
877
878 static const IOleContainerVtbl OleContainerVtbl = {
879     OleContainer_QueryInterface,
880     OleContainer_AddRef,
881     OleContainer_Release,
882     OleContainer_ParseDisplayName,
883     OleContainer_EnumObjects,
884     OleContainer_LockContainer
885 };
886
887 /**********************************************************
888  * IObjectSafety implementation
889  */
890
891 static inline HTMLDocument *impl_from_IObjectSafety(IObjectSafety *iface)
892 {
893     return CONTAINING_RECORD(iface, HTMLDocument, IObjectSafety_iface);
894 }
895
896 static HRESULT WINAPI ObjectSafety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
897 {
898     HTMLDocument *This = impl_from_IObjectSafety(iface);
899     return htmldoc_query_interface(This, riid, ppv);
900 }
901
902 static ULONG WINAPI ObjectSafety_AddRef(IObjectSafety *iface)
903 {
904     HTMLDocument *This = impl_from_IObjectSafety(iface);
905     return htmldoc_addref(This);
906 }
907
908 static ULONG WINAPI ObjectSafety_Release(IObjectSafety *iface)
909 {
910     HTMLDocument *This = impl_from_IObjectSafety(iface);
911     return htmldoc_release(This);
912 }
913
914 static HRESULT WINAPI ObjectSafety_GetInterfaceSafetyOptions(IObjectSafety *iface,
915         REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
916 {
917     HTMLDocument *This = impl_from_IObjectSafety(iface);
918     FIXME("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
919     return E_NOTIMPL;
920 }
921
922 static HRESULT WINAPI ObjectSafety_SetInterfaceSafetyOptions(IObjectSafety *iface,
923         REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions)
924 {
925     HTMLDocument *This = impl_from_IObjectSafety(iface);
926     FIXME("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
927
928     if(IsEqualGUID(&IID_IPersistMoniker, riid) &&
929             dwOptionSetMask==INTERFACESAFE_FOR_UNTRUSTED_DATA &&
930             dwEnabledOptions==INTERFACESAFE_FOR_UNTRUSTED_DATA)
931         return S_OK;
932
933     return E_NOTIMPL;
934 }
935
936 static const IObjectSafetyVtbl ObjectSafetyVtbl = {
937     ObjectSafety_QueryInterface,
938     ObjectSafety_AddRef,
939     ObjectSafety_Release,
940     ObjectSafety_GetInterfaceSafetyOptions,
941     ObjectSafety_SetInterfaceSafetyOptions
942 };
943
944 void HTMLDocument_LockContainer(HTMLDocumentObj *This, BOOL fLock)
945 {
946     IOleContainer *container;
947     HRESULT hres;
948
949     if(!This->client || This->container_locked == fLock)
950         return;
951
952     hres = IOleClientSite_GetContainer(This->client, &container);
953     if(SUCCEEDED(hres)) {
954         IOleContainer_LockContainer(container, fLock);
955         This->container_locked = fLock;
956         IOleContainer_Release(container);
957     }
958 }
959
960 void HTMLDocument_OleObj_Init(HTMLDocument *This)
961 {
962     This->IOleObject_iface.lpVtbl = &OleObjectVtbl;
963     This->IOleDocument_iface.lpVtbl = &OleDocumentVtbl;
964     This->IOleControl_iface.lpVtbl = &OleControlVtbl;
965     This->IObjectWithSite_iface.lpVtbl = &ObjectWithSiteVtbl;
966     This->IOleContainer_iface.lpVtbl = &OleContainerVtbl;
967     This->IObjectSafety_iface.lpVtbl = &ObjectSafetyVtbl;
968 }