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