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