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