|  | /* | 
|  | * Copyright 2005 Jacek Caban | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | 
|  | */ | 
|  |  | 
|  | #include "config.h" | 
|  |  | 
|  | #include <stdarg.h> | 
|  | #include <stdio.h> | 
|  |  | 
|  | #define COBJMACROS | 
|  |  | 
|  | #include "windef.h" | 
|  | #include "winbase.h" | 
|  | #include "winuser.h" | 
|  | #include "ole2.h" | 
|  | #include "shlguid.h" | 
|  | #include "shdeprecated.h" | 
|  | #include "mshtmdid.h" | 
|  | #include "idispids.h" | 
|  |  | 
|  | #include "wine/debug.h" | 
|  |  | 
|  | #include "mshtml_private.h" | 
|  |  | 
|  | WINE_DEFAULT_DEBUG_CHANNEL(mshtml); | 
|  |  | 
|  | #define DOCHOST_DOCCANNAVIGATE  0 | 
|  |  | 
|  | typedef struct { | 
|  | IEnumUnknown IEnumUnknown_iface; | 
|  | LONG ref; | 
|  | } EnumUnknown; | 
|  |  | 
|  | static inline EnumUnknown *impl_from_IEnumUnknown(IEnumUnknown *iface) | 
|  | { | 
|  | return CONTAINING_RECORD(iface, EnumUnknown, IEnumUnknown_iface); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI EnumUnknown_QueryInterface(IEnumUnknown *iface, REFIID riid, void **ppv) | 
|  | { | 
|  | EnumUnknown *This = impl_from_IEnumUnknown(iface); | 
|  |  | 
|  | if(IsEqualGUID(&IID_IUnknown, riid)) { | 
|  | TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); | 
|  | *ppv = &This->IEnumUnknown_iface; | 
|  | }else if(IsEqualGUID(&IID_IEnumUnknown, riid)) { | 
|  | TRACE("(%p)->(IID_IEnumUnknown %p)\n", This, ppv); | 
|  | *ppv = &This->IEnumUnknown_iface; | 
|  | }else { | 
|  | WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); | 
|  | *ppv = NULL; | 
|  | return E_NOINTERFACE; | 
|  | } | 
|  |  | 
|  | IUnknown_AddRef((IUnknown*)*ppv); | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI EnumUnknown_AddRef(IEnumUnknown *iface) | 
|  | { | 
|  | EnumUnknown *This = impl_from_IEnumUnknown(iface); | 
|  | LONG ref = InterlockedIncrement(&This->ref); | 
|  |  | 
|  | TRACE("(%p) ref=%d\n", This, ref); | 
|  |  | 
|  | return ref; | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI EnumUnknown_Release(IEnumUnknown *iface) | 
|  | { | 
|  | EnumUnknown *This = impl_from_IEnumUnknown(iface); | 
|  | LONG ref = InterlockedDecrement(&This->ref); | 
|  |  | 
|  | TRACE("(%p) ref=%d\n", This, ref); | 
|  |  | 
|  | if(!ref) | 
|  | heap_free(This); | 
|  |  | 
|  | return ref; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI EnumUnknown_Next(IEnumUnknown *iface, ULONG celt, IUnknown **rgelt, ULONG *pceltFetched) | 
|  | { | 
|  | EnumUnknown *This = impl_from_IEnumUnknown(iface); | 
|  |  | 
|  | TRACE("(%p)->(%u %p %p)\n", This, celt, rgelt, pceltFetched); | 
|  |  | 
|  | /* FIXME: It's not clear if we should ever return something here */ | 
|  | if(pceltFetched) | 
|  | *pceltFetched = 0; | 
|  | return S_FALSE; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI EnumUnknown_Skip(IEnumUnknown *iface, ULONG celt) | 
|  | { | 
|  | EnumUnknown *This = impl_from_IEnumUnknown(iface); | 
|  | FIXME("(%p)->(%u)\n", This, celt); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI EnumUnknown_Reset(IEnumUnknown *iface) | 
|  | { | 
|  | EnumUnknown *This = impl_from_IEnumUnknown(iface); | 
|  | FIXME("(%p)\n", This); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI EnumUnknown_Clone(IEnumUnknown *iface, IEnumUnknown **ppenum) | 
|  | { | 
|  | EnumUnknown *This = impl_from_IEnumUnknown(iface); | 
|  | FIXME("(%p)->(%p)\n", This, ppenum); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static const IEnumUnknownVtbl EnumUnknownVtbl = { | 
|  | EnumUnknown_QueryInterface, | 
|  | EnumUnknown_AddRef, | 
|  | EnumUnknown_Release, | 
|  | EnumUnknown_Next, | 
|  | EnumUnknown_Skip, | 
|  | EnumUnknown_Reset, | 
|  | EnumUnknown_Clone | 
|  | }; | 
|  |  | 
|  | /********************************************************** | 
|  | * IOleObject implementation | 
|  | */ | 
|  |  | 
|  | static inline HTMLDocument *impl_from_IOleObject(IOleObject *iface) | 
|  | { | 
|  | return CONTAINING_RECORD(iface, HTMLDocument, IOleObject_iface); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_QueryInterface(IOleObject *iface, REFIID riid, void **ppv) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | return htmldoc_query_interface(This, riid, ppv); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI OleObject_AddRef(IOleObject *iface) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | return htmldoc_addref(This); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI OleObject_Release(IOleObject *iface) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | return htmldoc_release(This); | 
|  | } | 
|  |  | 
|  | static void update_hostinfo(HTMLDocumentObj *This, DOCHOSTUIINFO *hostinfo) | 
|  | { | 
|  | nsIScrollable *scrollable; | 
|  | nsresult nsres; | 
|  |  | 
|  | if(!This->nscontainer) | 
|  | return; | 
|  |  | 
|  | nsres = nsIWebBrowser_QueryInterface(This->nscontainer->webbrowser, &IID_nsIScrollable, (void**)&scrollable); | 
|  | if(NS_SUCCEEDED(nsres)) { | 
|  | nsres = nsIScrollable_SetDefaultScrollbarPreferences(scrollable, ScrollOrientation_Y, | 
|  | (hostinfo->dwFlags & DOCHOSTUIFLAG_SCROLL_NO) ? Scrollbar_Never : Scrollbar_Always); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("Could not set default Y scrollbar prefs: %08x\n", nsres); | 
|  |  | 
|  | nsres = nsIScrollable_SetDefaultScrollbarPreferences(scrollable, ScrollOrientation_X, | 
|  | hostinfo->dwFlags & DOCHOSTUIFLAG_SCROLL_NO ? Scrollbar_Never : Scrollbar_Auto); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("Could not set default X scrollbar prefs: %08x\n", nsres); | 
|  |  | 
|  | nsIScrollable_Release(scrollable); | 
|  | }else { | 
|  | ERR("Could not get nsIScrollable: %08x\n", nsres); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Calls undocumented 84 cmd of CGID_ShellDocView */ | 
|  | void call_docview_84(HTMLDocumentObj *doc) | 
|  | { | 
|  | IOleCommandTarget *olecmd; | 
|  | VARIANT var; | 
|  | HRESULT hres; | 
|  |  | 
|  | if(!doc->client) | 
|  | return; | 
|  |  | 
|  | hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd); | 
|  | if(FAILED(hres)) | 
|  | return; | 
|  |  | 
|  | VariantInit(&var); | 
|  | hres = IOleCommandTarget_Exec(olecmd, &CGID_ShellDocView, 84, 0, NULL, &var); | 
|  | IOleCommandTarget_Release(olecmd); | 
|  | if(SUCCEEDED(hres) && V_VT(&var) != VT_NULL) | 
|  | FIXME("handle result\n"); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_SetClientSite(IOleObject *iface, IOleClientSite *pClientSite) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | IOleCommandTarget *cmdtrg = NULL; | 
|  | IOleWindow *ole_window; | 
|  | BOOL hostui_setup; | 
|  | VARIANT silent; | 
|  | HWND hwnd; | 
|  | HRESULT hres; | 
|  |  | 
|  | TRACE("(%p)->(%p)\n", This, pClientSite); | 
|  |  | 
|  | if(pClientSite == This->doc_obj->client) | 
|  | return S_OK; | 
|  |  | 
|  | if(This->doc_obj->client) { | 
|  | IOleClientSite_Release(This->doc_obj->client); | 
|  | This->doc_obj->client = NULL; | 
|  | This->doc_obj->usermode = UNKNOWN_USERMODE; | 
|  | } | 
|  |  | 
|  | if(This->doc_obj->hostui && !This->doc_obj->custom_hostui) { | 
|  | IDocHostUIHandler_Release(This->doc_obj->hostui); | 
|  | This->doc_obj->hostui = NULL; | 
|  | } | 
|  |  | 
|  | if(This->doc_obj->doc_object_service) { | 
|  | IDocObjectService_Release(This->doc_obj->doc_object_service); | 
|  | This->doc_obj->doc_object_service = NULL; | 
|  | } | 
|  |  | 
|  | memset(&This->doc_obj->hostinfo, 0, sizeof(DOCHOSTUIINFO)); | 
|  | This->doc_obj->is_webbrowser = FALSE; | 
|  |  | 
|  | if(!pClientSite) | 
|  | return S_OK; | 
|  |  | 
|  | IOleClientSite_AddRef(pClientSite); | 
|  | This->doc_obj->client = pClientSite; | 
|  |  | 
|  | hostui_setup = This->doc_obj->hostui_setup; | 
|  |  | 
|  | if(!This->doc_obj->hostui) { | 
|  | IDocHostUIHandler *uihandler; | 
|  |  | 
|  | This->doc_obj->custom_hostui = FALSE; | 
|  |  | 
|  | hres = IOleObject_QueryInterface(pClientSite, &IID_IDocHostUIHandler, (void**)&uihandler); | 
|  | if(SUCCEEDED(hres)) | 
|  | This->doc_obj->hostui = uihandler; | 
|  | } | 
|  |  | 
|  | if(This->doc_obj->hostui) { | 
|  | DOCHOSTUIINFO hostinfo; | 
|  | LPOLESTR key_path = NULL, override_key_path = NULL; | 
|  | IDocHostUIHandler2 *uihandler2; | 
|  |  | 
|  | memset(&hostinfo, 0, sizeof(DOCHOSTUIINFO)); | 
|  | hostinfo.cbSize = sizeof(DOCHOSTUIINFO); | 
|  | hres = IDocHostUIHandler_GetHostInfo(This->doc_obj->hostui, &hostinfo); | 
|  | if(SUCCEEDED(hres)) { | 
|  | TRACE("hostinfo = {%u %08x %08x %s %s}\n", | 
|  | hostinfo.cbSize, hostinfo.dwFlags, hostinfo.dwDoubleClick, | 
|  | debugstr_w(hostinfo.pchHostCss), debugstr_w(hostinfo.pchHostNS)); | 
|  | update_hostinfo(This->doc_obj, &hostinfo); | 
|  | This->doc_obj->hostinfo = hostinfo; | 
|  | } | 
|  |  | 
|  | if(!hostui_setup) { | 
|  | hres = IDocHostUIHandler_GetOptionKeyPath(This->doc_obj->hostui, &key_path, 0); | 
|  | if(hres == S_OK && key_path) { | 
|  | if(key_path[0]) { | 
|  | /* FIXME: use key_path */ | 
|  | TRACE("key_path = %s\n", debugstr_w(key_path)); | 
|  | } | 
|  | CoTaskMemFree(key_path); | 
|  | } | 
|  |  | 
|  | hres = IDocHostUIHandler_QueryInterface(This->doc_obj->hostui, &IID_IDocHostUIHandler2, | 
|  | (void**)&uihandler2); | 
|  | if(SUCCEEDED(hres)) { | 
|  | hres = IDocHostUIHandler2_GetOverrideKeyPath(uihandler2, &override_key_path, 0); | 
|  | if(hres == S_OK && override_key_path && override_key_path[0]) { | 
|  | if(override_key_path[0]) { | 
|  | /*FIXME: use override_key_path */ | 
|  | TRACE("override_key_path = %s\n", debugstr_w(override_key_path)); | 
|  | } | 
|  | CoTaskMemFree(override_key_path); | 
|  | } | 
|  | IDocHostUIHandler2_Release(uihandler2); | 
|  | } | 
|  |  | 
|  | This->doc_obj->hostui_setup = TRUE; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Native calls here GetWindow. What is it for? | 
|  | * We don't have anything to do with it here (yet). */ | 
|  | hres = IOleClientSite_QueryInterface(pClientSite, &IID_IOleWindow, (void**)&ole_window); | 
|  | if(SUCCEEDED(hres)) { | 
|  | IOleWindow_GetWindow(ole_window, &hwnd); | 
|  | IOleWindow_Release(ole_window); | 
|  | } | 
|  |  | 
|  | hres = IOleClientSite_QueryInterface(pClientSite, &IID_IOleCommandTarget, (void**)&cmdtrg); | 
|  | if(SUCCEEDED(hres)) { | 
|  | VARIANT var; | 
|  | OLECMD cmd = {OLECMDID_SETPROGRESSTEXT, 0}; | 
|  |  | 
|  | if(!hostui_setup) { | 
|  | IDocObjectService *doc_object_service; | 
|  | IBrowserService *browser_service; | 
|  | IWebBrowser2 *wb; | 
|  |  | 
|  | V_VT(&var) = VT_UNKNOWN; | 
|  | V_UNKNOWN(&var) = (IUnknown*)&This->window->base.IHTMLWindow2_iface; | 
|  | IOleCommandTarget_Exec(cmdtrg, &CGID_DocHostCmdPriv, DOCHOST_DOCCANNAVIGATE, 0, &var, NULL); | 
|  |  | 
|  | hres = do_query_service((IUnknown*)pClientSite, &IID_IShellBrowser, | 
|  | &IID_IBrowserService, (void**)&browser_service); | 
|  | if(SUCCEEDED(hres)) { | 
|  | hres = IBrowserService_QueryInterface(browser_service, | 
|  | &IID_IDocObjectService, (void**)&doc_object_service); | 
|  | if(SUCCEEDED(hres)) { | 
|  | This->doc_obj->doc_object_service = doc_object_service; | 
|  |  | 
|  | /* | 
|  | * Some embedding routines, esp. in regards to use of IDocObjectService, differ if | 
|  | * embedder supports IWebBrowserApp. | 
|  | */ | 
|  | hres = do_query_service((IUnknown*)pClientSite, &IID_IWebBrowserApp, &IID_IWebBrowser2, (void**)&wb); | 
|  | if(SUCCEEDED(hres)) { | 
|  | This->doc_obj->is_webbrowser = TRUE; | 
|  | IWebBrowser2_Release(wb); | 
|  | } | 
|  |  | 
|  | IBrowserService_Release(browser_service); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | call_docview_84(This->doc_obj); | 
|  |  | 
|  | IOleCommandTarget_QueryStatus(cmdtrg, NULL, 1, &cmd, NULL); | 
|  |  | 
|  | V_VT(&var) = VT_I4; | 
|  | V_I4(&var) = 0; | 
|  | IOleCommandTarget_Exec(cmdtrg, NULL, OLECMDID_SETPROGRESSMAX, | 
|  | OLECMDEXECOPT_DONTPROMPTUSER, &var, NULL); | 
|  | IOleCommandTarget_Exec(cmdtrg, NULL, OLECMDID_SETPROGRESSPOS, | 
|  | OLECMDEXECOPT_DONTPROMPTUSER, &var, NULL); | 
|  |  | 
|  | IOleCommandTarget_Release(cmdtrg); | 
|  | } | 
|  |  | 
|  | if(This->doc_obj->usermode == UNKNOWN_USERMODE) | 
|  | IOleControl_OnAmbientPropertyChange(&This->IOleControl_iface, DISPID_AMBIENT_USERMODE); | 
|  |  | 
|  | IOleControl_OnAmbientPropertyChange(&This->IOleControl_iface, | 
|  | DISPID_AMBIENT_OFFLINEIFNOTCONNECTED); | 
|  |  | 
|  | hres = get_client_disp_property(This->doc_obj->client, DISPID_AMBIENT_SILENT, &silent); | 
|  | if(SUCCEEDED(hres)) { | 
|  | if(V_VT(&silent) != VT_BOOL) | 
|  | WARN("silent = %s\n", debugstr_variant(&silent)); | 
|  | else if(V_BOOL(&silent)) | 
|  | FIXME("silent == true\n"); | 
|  | } | 
|  |  | 
|  | IOleControl_OnAmbientPropertyChange(&This->IOleControl_iface, DISPID_AMBIENT_USERAGENT); | 
|  | IOleControl_OnAmbientPropertyChange(&This->IOleControl_iface, DISPID_AMBIENT_PALETTE); | 
|  |  | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_GetClientSite(IOleObject *iface, IOleClientSite **ppClientSite) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  |  | 
|  | TRACE("(%p)->(%p)\n", This, ppClientSite); | 
|  |  | 
|  | if(!ppClientSite) | 
|  | return E_INVALIDARG; | 
|  |  | 
|  | if(This->doc_obj->client) | 
|  | IOleClientSite_AddRef(This->doc_obj->client); | 
|  | *ppClientSite = This->doc_obj->client; | 
|  |  | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_SetHostNames(IOleObject *iface, LPCOLESTR szContainerApp, LPCOLESTR szContainerObj) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | FIXME("(%p)->(%s %s)\n", This, debugstr_w(szContainerApp), debugstr_w(szContainerObj)); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_Close(IOleObject *iface, DWORD dwSaveOption) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  |  | 
|  | TRACE("(%p)->(%08x)\n", This, dwSaveOption); | 
|  |  | 
|  | if(dwSaveOption == OLECLOSE_PROMPTSAVE) | 
|  | FIXME("OLECLOSE_PROMPTSAVE not implemented\n"); | 
|  |  | 
|  | if(This->doc_obj->in_place_active) | 
|  | IOleInPlaceObjectWindowless_InPlaceDeactivate(&This->IOleInPlaceObjectWindowless_iface); | 
|  |  | 
|  | HTMLDocument_LockContainer(This->doc_obj, FALSE); | 
|  |  | 
|  | if(This->advise_holder) | 
|  | IOleAdviseHolder_SendOnClose(This->advise_holder); | 
|  |  | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_SetMoniker(IOleObject *iface, DWORD dwWhichMoniker, IMoniker *pmk) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | FIXME("(%p %d %p)->()\n", This, dwWhichMoniker, pmk); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_GetMoniker(IOleObject *iface, DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | FIXME("(%p)->(%d %d %p)\n", This, dwAssign, dwWhichMoniker, ppmk); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_InitFromData(IOleObject *iface, IDataObject *pDataObject, BOOL fCreation, | 
|  | DWORD dwReserved) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | FIXME("(%p)->(%p %x %d)\n", This, pDataObject, fCreation, dwReserved); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_GetClipboardData(IOleObject *iface, DWORD dwReserved, IDataObject **ppDataObject) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | FIXME("(%p)->(%d %p)\n", This, dwReserved, ppDataObject); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_DoVerb(IOleObject *iface, LONG iVerb, LPMSG lpmsg, IOleClientSite *pActiveSite, | 
|  | LONG lindex, HWND hwndParent, LPCRECT lprcPosRect) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | IOleDocumentSite *pDocSite; | 
|  | HRESULT hres; | 
|  |  | 
|  | TRACE("(%p)->(%d %p %p %d %p %p)\n", This, iVerb, lpmsg, pActiveSite, lindex, hwndParent, lprcPosRect); | 
|  |  | 
|  | if(iVerb != OLEIVERB_SHOW && iVerb != OLEIVERB_UIACTIVATE && iVerb != OLEIVERB_INPLACEACTIVATE) { | 
|  | FIXME("iVerb = %d not supported\n", iVerb); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | if(!pActiveSite) | 
|  | pActiveSite = This->doc_obj->client; | 
|  |  | 
|  | hres = IOleClientSite_QueryInterface(pActiveSite, &IID_IOleDocumentSite, (void**)&pDocSite); | 
|  | if(SUCCEEDED(hres)) { | 
|  | HTMLDocument_LockContainer(This->doc_obj, TRUE); | 
|  |  | 
|  | /* FIXME: Create new IOleDocumentView. See CreateView for more info. */ | 
|  | hres = IOleDocumentSite_ActivateMe(pDocSite, &This->IOleDocumentView_iface); | 
|  | IOleDocumentSite_Release(pDocSite); | 
|  | }else { | 
|  | hres = IOleDocumentView_UIActivate(&This->IOleDocumentView_iface, TRUE); | 
|  | if(SUCCEEDED(hres)) { | 
|  | if(lprcPosRect) { | 
|  | RECT rect; /* We need to pass rect as not const pointer */ | 
|  | rect = *lprcPosRect; | 
|  | IOleDocumentView_SetRect(&This->IOleDocumentView_iface, &rect); | 
|  | } | 
|  | IOleDocumentView_Show(&This->IOleDocumentView_iface, TRUE); | 
|  | } | 
|  | } | 
|  |  | 
|  | return hres; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_EnumVerbs(IOleObject *iface, IEnumOLEVERB **ppEnumOleVerb) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | FIXME("(%p)->(%p)\n", This, ppEnumOleVerb); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_Update(IOleObject *iface) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | FIXME("(%p)\n", This); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_IsUpToDate(IOleObject *iface) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | FIXME("(%p)\n", This); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_GetUserClassID(IOleObject *iface, CLSID *pClsid) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  |  | 
|  | TRACE("(%p)->(%p)\n", This, pClsid); | 
|  |  | 
|  | if(!pClsid) | 
|  | return E_INVALIDARG; | 
|  |  | 
|  | *pClsid = CLSID_HTMLDocument; | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_GetUserType(IOleObject *iface, DWORD dwFormOfType, LPOLESTR *pszUserType) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | FIXME("(%p)->(%d %p)\n", This, dwFormOfType, pszUserType); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_SetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | FIXME("(%p)->(%d %p)\n", This, dwDrawAspect, psizel); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_GetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | FIXME("(%p)->(%d %p)\n", This, dwDrawAspect, psizel); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_Advise(IOleObject *iface, IAdviseSink *pAdvSink, DWORD *pdwConnection) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | TRACE("(%p)->(%p %p)\n", This, pAdvSink, pdwConnection); | 
|  |  | 
|  | if(!pdwConnection) | 
|  | return E_INVALIDARG; | 
|  |  | 
|  | if(!pAdvSink) { | 
|  | *pdwConnection = 0; | 
|  | return E_INVALIDARG; | 
|  | } | 
|  |  | 
|  | if(!This->advise_holder) { | 
|  | CreateOleAdviseHolder(&This->advise_holder); | 
|  | if(!This->advise_holder) | 
|  | return E_OUTOFMEMORY; | 
|  | } | 
|  |  | 
|  | return IOleAdviseHolder_Advise(This->advise_holder, pAdvSink, pdwConnection); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_Unadvise(IOleObject *iface, DWORD dwConnection) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | TRACE("(%p)->(%d)\n", This, dwConnection); | 
|  |  | 
|  | if(!This->advise_holder) | 
|  | return OLE_E_NOCONNECTION; | 
|  |  | 
|  | return IOleAdviseHolder_Unadvise(This->advise_holder, dwConnection); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_EnumAdvise(IOleObject *iface, IEnumSTATDATA **ppenumAdvise) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  |  | 
|  | if(!This->advise_holder) { | 
|  | *ppenumAdvise = NULL; | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | return IOleAdviseHolder_EnumAdvise(This->advise_holder, ppenumAdvise); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_GetMiscStatus(IOleObject *iface, DWORD dwAspect, DWORD *pdwStatus) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | FIXME("(%p)->(%d %p)\n", This, dwAspect, pdwStatus); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleObject_SetColorScheme(IOleObject *iface, LOGPALETTE *pLogpal) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleObject(iface); | 
|  | FIXME("(%p)->(%p)\n", This, pLogpal); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static const IOleObjectVtbl OleObjectVtbl = { | 
|  | OleObject_QueryInterface, | 
|  | OleObject_AddRef, | 
|  | OleObject_Release, | 
|  | OleObject_SetClientSite, | 
|  | OleObject_GetClientSite, | 
|  | OleObject_SetHostNames, | 
|  | OleObject_Close, | 
|  | OleObject_SetMoniker, | 
|  | OleObject_GetMoniker, | 
|  | OleObject_InitFromData, | 
|  | OleObject_GetClipboardData, | 
|  | OleObject_DoVerb, | 
|  | OleObject_EnumVerbs, | 
|  | OleObject_Update, | 
|  | OleObject_IsUpToDate, | 
|  | OleObject_GetUserClassID, | 
|  | OleObject_GetUserType, | 
|  | OleObject_SetExtent, | 
|  | OleObject_GetExtent, | 
|  | OleObject_Advise, | 
|  | OleObject_Unadvise, | 
|  | OleObject_EnumAdvise, | 
|  | OleObject_GetMiscStatus, | 
|  | OleObject_SetColorScheme | 
|  | }; | 
|  |  | 
|  | /********************************************************** | 
|  | * IOleDocument implementation | 
|  | */ | 
|  |  | 
|  | static inline HTMLDocument *impl_from_IOleDocument(IOleDocument *iface) | 
|  | { | 
|  | return CONTAINING_RECORD(iface, HTMLDocument, IOleDocument_iface); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleDocument_QueryInterface(IOleDocument *iface, REFIID riid, void **ppv) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleDocument(iface); | 
|  | return htmldoc_query_interface(This, riid, ppv); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI OleDocument_AddRef(IOleDocument *iface) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleDocument(iface); | 
|  | return htmldoc_addref(This); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI OleDocument_Release(IOleDocument *iface) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleDocument(iface); | 
|  | return htmldoc_release(This); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleDocument_CreateView(IOleDocument *iface, IOleInPlaceSite *pIPSite, IStream *pstm, | 
|  | DWORD dwReserved, IOleDocumentView **ppView) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleDocument(iface); | 
|  | HRESULT hres; | 
|  |  | 
|  | TRACE("(%p)->(%p %p %d %p)\n", This, pIPSite, pstm, dwReserved, ppView); | 
|  |  | 
|  | if(!ppView) | 
|  | return E_INVALIDARG; | 
|  |  | 
|  | /* FIXME: | 
|  | * Windows implementation creates new IOleDocumentView when function is called for the | 
|  | * first time and returns E_FAIL when it is called for the second time, but it doesn't matter | 
|  | * if the application uses returned interfaces, passed to ActivateMe or returned by | 
|  | * QueryInterface, so there is no reason to create new interface. This needs more testing. | 
|  | */ | 
|  |  | 
|  | if(pIPSite) { | 
|  | hres = IOleDocumentView_SetInPlaceSite(&This->IOleDocumentView_iface, pIPSite); | 
|  | if(FAILED(hres)) | 
|  | return hres; | 
|  | } | 
|  |  | 
|  | if(pstm) | 
|  | FIXME("pstm is not supported\n"); | 
|  |  | 
|  | IOleDocumentView_AddRef(&This->IOleDocumentView_iface); | 
|  | *ppView = &This->IOleDocumentView_iface; | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleDocument_GetDocMiscStatus(IOleDocument *iface, DWORD *pdwStatus) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleDocument(iface); | 
|  | FIXME("(%p)->(%p)\n", This, pdwStatus); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleDocument_EnumViews(IOleDocument *iface, IEnumOleDocumentViews **ppEnum, | 
|  | IOleDocumentView **ppView) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleDocument(iface); | 
|  | FIXME("(%p)->(%p %p)\n", This, ppEnum, ppView); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static const IOleDocumentVtbl OleDocumentVtbl = { | 
|  | OleDocument_QueryInterface, | 
|  | OleDocument_AddRef, | 
|  | OleDocument_Release, | 
|  | OleDocument_CreateView, | 
|  | OleDocument_GetDocMiscStatus, | 
|  | OleDocument_EnumViews | 
|  | }; | 
|  |  | 
|  | /********************************************************** | 
|  | * IOleControl implementation | 
|  | */ | 
|  |  | 
|  | static inline HTMLDocument *impl_from_IOleControl(IOleControl *iface) | 
|  | { | 
|  | return CONTAINING_RECORD(iface, HTMLDocument, IOleControl_iface); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleControl_QueryInterface(IOleControl *iface, REFIID riid, void **ppv) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleControl(iface); | 
|  | return htmldoc_query_interface(This, riid, ppv); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI OleControl_AddRef(IOleControl *iface) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleControl(iface); | 
|  | return htmldoc_addref(This); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI OleControl_Release(IOleControl *iface) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleControl(iface); | 
|  | return htmldoc_release(This); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleControl_GetControlInfo(IOleControl *iface, CONTROLINFO *pCI) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleControl(iface); | 
|  | FIXME("(%p)->(%p)\n", This, pCI); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleControl_OnMnemonic(IOleControl *iface, MSG *pMsg) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleControl(iface); | 
|  | FIXME("(%p)->(%p)\n", This, pMsg); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | HRESULT get_client_disp_property(IOleClientSite *client, DISPID dispid, VARIANT *res) | 
|  | { | 
|  | IDispatch *disp = NULL; | 
|  | DISPPARAMS dispparams = {NULL, 0}; | 
|  | UINT err; | 
|  | HRESULT hres; | 
|  |  | 
|  | hres = IOleClientSite_QueryInterface(client, &IID_IDispatch, (void**)&disp); | 
|  | if(FAILED(hres)) { | 
|  | TRACE("Could not get IDispatch\n"); | 
|  | return hres; | 
|  | } | 
|  |  | 
|  | VariantInit(res); | 
|  |  | 
|  | hres = IDispatch_Invoke(disp, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT, | 
|  | DISPATCH_PROPERTYGET, &dispparams, res, NULL, &err); | 
|  |  | 
|  | IDispatch_Release(disp); | 
|  |  | 
|  | return hres; | 
|  | } | 
|  |  | 
|  | static HRESULT on_change_dlcontrol(HTMLDocument *This) | 
|  | { | 
|  | VARIANT res; | 
|  | HRESULT hres; | 
|  |  | 
|  | hres = get_client_disp_property(This->doc_obj->client, DISPID_AMBIENT_DLCONTROL, &res); | 
|  | if(SUCCEEDED(hres)) | 
|  | FIXME("unsupported dlcontrol %08x\n", V_I4(&res)); | 
|  |  | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleControl_OnAmbientPropertyChange(IOleControl *iface, DISPID dispID) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleControl(iface); | 
|  | IOleClientSite *client; | 
|  | VARIANT res; | 
|  | HRESULT hres; | 
|  |  | 
|  | client = This->doc_obj->client; | 
|  | if(!client) { | 
|  | TRACE("client = NULL\n"); | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | switch(dispID) { | 
|  | case DISPID_AMBIENT_USERMODE: | 
|  | TRACE("(%p)->(DISPID_AMBIENT_USERMODE)\n", This); | 
|  | hres = get_client_disp_property(client, DISPID_AMBIENT_USERMODE, &res); | 
|  | if(FAILED(hres)) | 
|  | return S_OK; | 
|  |  | 
|  | if(V_VT(&res) == VT_BOOL) { | 
|  | if(V_BOOL(&res)) { | 
|  | This->doc_obj->usermode = BROWSEMODE; | 
|  | }else { | 
|  | FIXME("edit mode is not supported\n"); | 
|  | This->doc_obj->usermode = EDITMODE; | 
|  | } | 
|  | }else { | 
|  | FIXME("usermode=%s\n", debugstr_variant(&res)); | 
|  | } | 
|  | return S_OK; | 
|  | case DISPID_AMBIENT_DLCONTROL: | 
|  | TRACE("(%p)->(DISPID_AMBIENT_DLCONTROL)\n", This); | 
|  | return on_change_dlcontrol(This); | 
|  | case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED: | 
|  | TRACE("(%p)->(DISPID_AMBIENT_OFFLINEIFNOTCONNECTED)\n", This); | 
|  | on_change_dlcontrol(This); | 
|  | hres = get_client_disp_property(client, DISPID_AMBIENT_OFFLINEIFNOTCONNECTED, &res); | 
|  | if(FAILED(hres)) | 
|  | return S_OK; | 
|  |  | 
|  | if(V_VT(&res) == VT_BOOL) { | 
|  | if(V_BOOL(&res)) { | 
|  | FIXME("offline connection is not supported\n"); | 
|  | hres = E_FAIL; | 
|  | } | 
|  | }else { | 
|  | FIXME("offlineconnected=%s\n", debugstr_variant(&res)); | 
|  | } | 
|  | return S_OK; | 
|  | case DISPID_AMBIENT_SILENT: | 
|  | TRACE("(%p)->(DISPID_AMBIENT_SILENT)\n", This); | 
|  | on_change_dlcontrol(This); | 
|  | hres = get_client_disp_property(client, DISPID_AMBIENT_SILENT, &res); | 
|  | if(FAILED(hres)) | 
|  | return S_OK; | 
|  |  | 
|  | if(V_VT(&res) == VT_BOOL) { | 
|  | if(V_BOOL(&res)) { | 
|  | FIXME("silent mode is not supported\n"); | 
|  | hres = E_FAIL; | 
|  | } | 
|  | }else { | 
|  | FIXME("silent=%s\n", debugstr_variant(&res)); | 
|  | } | 
|  | return S_OK; | 
|  | case DISPID_AMBIENT_USERAGENT: | 
|  | TRACE("(%p)->(DISPID_AMBIENT_USERAGENT)\n", This); | 
|  | hres = get_client_disp_property(client, DISPID_AMBIENT_USERAGENT, &res); | 
|  | if(FAILED(hres)) | 
|  | return S_OK; | 
|  |  | 
|  | FIXME("not supported AMBIENT_USERAGENT\n"); | 
|  | hres = E_FAIL; | 
|  | return S_OK; | 
|  | case DISPID_AMBIENT_PALETTE: | 
|  | TRACE("(%p)->(DISPID_AMBIENT_PALETTE)\n", This); | 
|  | hres = get_client_disp_property(client, DISPID_AMBIENT_PALETTE, &res); | 
|  | if(FAILED(hres)) | 
|  | return S_OK; | 
|  |  | 
|  | FIXME("not supported AMBIENT_PALETTE\n"); | 
|  | hres = E_FAIL; | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | FIXME("(%p) unsupported dispID=%d\n", This, dispID); | 
|  | return E_FAIL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleControl_FreezeEvents(IOleControl *iface, BOOL bFreeze) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleControl(iface); | 
|  | FIXME("(%p)->(%x)\n", This, bFreeze); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static const IOleControlVtbl OleControlVtbl = { | 
|  | OleControl_QueryInterface, | 
|  | OleControl_AddRef, | 
|  | OleControl_Release, | 
|  | OleControl_GetControlInfo, | 
|  | OleControl_OnMnemonic, | 
|  | OleControl_OnAmbientPropertyChange, | 
|  | OleControl_FreezeEvents | 
|  | }; | 
|  |  | 
|  | /********************************************************** | 
|  | * IObjectWithSite implementation | 
|  | */ | 
|  |  | 
|  | static inline HTMLDocument *impl_from_IObjectWithSite(IObjectWithSite *iface) | 
|  | { | 
|  | return CONTAINING_RECORD(iface, HTMLDocument, IObjectWithSite_iface); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI ObjectWithSite_QueryInterface(IObjectWithSite *iface, REFIID riid, void **ppv) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IObjectWithSite(iface); | 
|  | return htmldoc_query_interface(This, riid, ppv); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI ObjectWithSite_AddRef(IObjectWithSite *iface) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IObjectWithSite(iface); | 
|  | return htmldoc_addref(This); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI ObjectWithSite_Release(IObjectWithSite *iface) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IObjectWithSite(iface); | 
|  | return htmldoc_release(This); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI ObjectWithSite_SetSite(IObjectWithSite *iface, IUnknown *pUnkSite) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IObjectWithSite(iface); | 
|  | FIXME("(%p)->(%p)\n", This, pUnkSite); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI ObjectWithSite_GetSite(IObjectWithSite* iface, REFIID riid, PVOID *ppvSite) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IObjectWithSite(iface); | 
|  | FIXME("(%p)->(%p)\n", This, ppvSite); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static const IObjectWithSiteVtbl ObjectWithSiteVtbl = { | 
|  | ObjectWithSite_QueryInterface, | 
|  | ObjectWithSite_AddRef, | 
|  | ObjectWithSite_Release, | 
|  | ObjectWithSite_SetSite, | 
|  | ObjectWithSite_GetSite | 
|  | }; | 
|  |  | 
|  | /********************************************************** | 
|  | * IOleContainer implementation | 
|  | */ | 
|  |  | 
|  | static inline HTMLDocument *impl_from_IOleContainer(IOleContainer *iface) | 
|  | { | 
|  | return CONTAINING_RECORD(iface, HTMLDocument, IOleContainer_iface); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleContainer_QueryInterface(IOleContainer *iface, REFIID riid, void **ppv) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleContainer(iface); | 
|  | return htmldoc_query_interface(This, riid, ppv); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI OleContainer_AddRef(IOleContainer *iface) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleContainer(iface); | 
|  | return htmldoc_addref(This); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI OleContainer_Release(IOleContainer *iface) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleContainer(iface); | 
|  | return htmldoc_release(This); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleContainer_ParseDisplayName(IOleContainer *iface, IBindCtx *pbc, LPOLESTR pszDisplayName, | 
|  | ULONG *pchEaten, IMoniker **ppmkOut) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleContainer(iface); | 
|  | FIXME("(%p)->(%p %s %p %p)\n", This, pbc, debugstr_w(pszDisplayName), pchEaten, ppmkOut); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleContainer_EnumObjects(IOleContainer *iface, DWORD grfFlags, IEnumUnknown **ppenum) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleContainer(iface); | 
|  | EnumUnknown *ret; | 
|  |  | 
|  | TRACE("(%p)->(%x %p)\n", This, grfFlags, ppenum); | 
|  |  | 
|  | ret = heap_alloc(sizeof(*ret)); | 
|  | if(!ret) | 
|  | return E_OUTOFMEMORY; | 
|  |  | 
|  | ret->IEnumUnknown_iface.lpVtbl = &EnumUnknownVtbl; | 
|  | ret->ref = 1; | 
|  |  | 
|  | *ppenum = &ret->IEnumUnknown_iface; | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI OleContainer_LockContainer(IOleContainer *iface, BOOL fLock) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IOleContainer(iface); | 
|  | FIXME("(%p)->(%x)\n", This, fLock); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static const IOleContainerVtbl OleContainerVtbl = { | 
|  | OleContainer_QueryInterface, | 
|  | OleContainer_AddRef, | 
|  | OleContainer_Release, | 
|  | OleContainer_ParseDisplayName, | 
|  | OleContainer_EnumObjects, | 
|  | OleContainer_LockContainer | 
|  | }; | 
|  |  | 
|  | static inline HTMLDocumentObj *impl_from_ITargetContainer(ITargetContainer *iface) | 
|  | { | 
|  | return CONTAINING_RECORD(iface, HTMLDocumentObj, ITargetContainer_iface); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI TargetContainer_QueryInterface(ITargetContainer *iface, REFIID riid, void **ppv) | 
|  | { | 
|  | HTMLDocumentObj *This = impl_from_ITargetContainer(iface); | 
|  | return ICustomDoc_QueryInterface(&This->ICustomDoc_iface, riid, ppv); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI TargetContainer_AddRef(ITargetContainer *iface) | 
|  | { | 
|  | HTMLDocumentObj *This = impl_from_ITargetContainer(iface); | 
|  | return ICustomDoc_AddRef(&This->ICustomDoc_iface); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI TargetContainer_Release(ITargetContainer *iface) | 
|  | { | 
|  | HTMLDocumentObj *This = impl_from_ITargetContainer(iface); | 
|  | return ICustomDoc_Release(&This->ICustomDoc_iface); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI TargetContainer_GetFrameUrl(ITargetContainer *iface, LPWSTR *ppszFrameSrc) | 
|  | { | 
|  | HTMLDocumentObj *This = impl_from_ITargetContainer(iface); | 
|  | FIXME("(%p)->(%p)\n", This, ppszFrameSrc); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI TargetContainer_GetFramesContainer(ITargetContainer *iface, IOleContainer **ppContainer) | 
|  | { | 
|  | HTMLDocumentObj *This = impl_from_ITargetContainer(iface); | 
|  |  | 
|  | TRACE("(%p)->(%p)\n", This, ppContainer); | 
|  |  | 
|  | /* NOTE: we should return wrapped interface here */ | 
|  | IOleContainer_AddRef(&This->basedoc.IOleContainer_iface); | 
|  | *ppContainer = &This->basedoc.IOleContainer_iface; | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | static const ITargetContainerVtbl TargetContainerVtbl = { | 
|  | TargetContainer_QueryInterface, | 
|  | TargetContainer_AddRef, | 
|  | TargetContainer_Release, | 
|  | TargetContainer_GetFrameUrl, | 
|  | TargetContainer_GetFramesContainer | 
|  | }; | 
|  |  | 
|  | void TargetContainer_Init(HTMLDocumentObj *This) | 
|  | { | 
|  | This->ITargetContainer_iface.lpVtbl = &TargetContainerVtbl; | 
|  | } | 
|  |  | 
|  | /********************************************************** | 
|  | * IObjectSafety implementation | 
|  | */ | 
|  |  | 
|  | static inline HTMLDocument *impl_from_IObjectSafety(IObjectSafety *iface) | 
|  | { | 
|  | return CONTAINING_RECORD(iface, HTMLDocument, IObjectSafety_iface); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI ObjectSafety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IObjectSafety(iface); | 
|  | return htmldoc_query_interface(This, riid, ppv); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI ObjectSafety_AddRef(IObjectSafety *iface) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IObjectSafety(iface); | 
|  | return htmldoc_addref(This); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI ObjectSafety_Release(IObjectSafety *iface) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IObjectSafety(iface); | 
|  | return htmldoc_release(This); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI ObjectSafety_GetInterfaceSafetyOptions(IObjectSafety *iface, | 
|  | REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IObjectSafety(iface); | 
|  | FIXME("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions); | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI ObjectSafety_SetInterfaceSafetyOptions(IObjectSafety *iface, | 
|  | REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions) | 
|  | { | 
|  | HTMLDocument *This = impl_from_IObjectSafety(iface); | 
|  | FIXME("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions); | 
|  |  | 
|  | if(IsEqualGUID(&IID_IPersistMoniker, riid) && | 
|  | dwOptionSetMask==INTERFACESAFE_FOR_UNTRUSTED_DATA && | 
|  | dwEnabledOptions==INTERFACESAFE_FOR_UNTRUSTED_DATA) | 
|  | return S_OK; | 
|  |  | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static const IObjectSafetyVtbl ObjectSafetyVtbl = { | 
|  | ObjectSafety_QueryInterface, | 
|  | ObjectSafety_AddRef, | 
|  | ObjectSafety_Release, | 
|  | ObjectSafety_GetInterfaceSafetyOptions, | 
|  | ObjectSafety_SetInterfaceSafetyOptions | 
|  | }; | 
|  |  | 
|  | void HTMLDocument_LockContainer(HTMLDocumentObj *This, BOOL fLock) | 
|  | { | 
|  | IOleContainer *container; | 
|  | HRESULT hres; | 
|  |  | 
|  | if(!This->client || This->container_locked == fLock) | 
|  | return; | 
|  |  | 
|  | hres = IOleClientSite_GetContainer(This->client, &container); | 
|  | if(SUCCEEDED(hres)) { | 
|  | IOleContainer_LockContainer(container, fLock); | 
|  | This->container_locked = fLock; | 
|  | IOleContainer_Release(container); | 
|  | } | 
|  | } | 
|  |  | 
|  | void HTMLDocument_OleObj_Init(HTMLDocument *This) | 
|  | { | 
|  | This->IOleObject_iface.lpVtbl = &OleObjectVtbl; | 
|  | This->IOleDocument_iface.lpVtbl = &OleDocumentVtbl; | 
|  | This->IOleControl_iface.lpVtbl = &OleControlVtbl; | 
|  | This->IObjectWithSite_iface.lpVtbl = &ObjectWithSiteVtbl; | 
|  | This->IOleContainer_iface.lpVtbl = &OleContainerVtbl; | 
|  | This->IObjectSafety_iface.lpVtbl = &ObjectSafetyVtbl; | 
|  | } |