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