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