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