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