Sweden-Number/dlls/mshtml/oleobj.c

1247 lines
38 KiB
C

/*
* 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>
#include <assert.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");
}
void set_document_navigation(HTMLDocumentObj *doc, BOOL doc_can_navigate)
{
VARIANT var;
if(!doc->client_cmdtrg)
return;
if(doc_can_navigate) {
V_VT(&var) = VT_UNKNOWN;
V_UNKNOWN(&var) = (IUnknown*)&doc->basedoc.window->base.IHTMLWindow2_iface;
}
IOleCommandTarget_Exec(doc->client_cmdtrg, &CGID_DocHostCmdPriv, DOCHOST_DOCCANNAVIGATE, 0,
doc_can_navigate ? &var : NULL, NULL);
}
static void load_settings(HTMLDocumentObj *doc)
{
nsIContentViewer *content_viewer;
nsIDocShell *doc_shell;
HKEY settings_key;
DWORD val, size;
LONG res;
nsresult nsres;
static const WCHAR ie_keyW[] = {
'S','O','F','T','W','A','R','E','\\',
'M','i','c','r','o','s','o','f','t','\\',
'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r',0};
static const WCHAR zoomW[] = {'Z','o','o','m',0};
static const WCHAR zoom_factorW[] = {'Z','o','o','m','F','a','c','t','o','r',0};
res = RegOpenKeyW(HKEY_CURRENT_USER, ie_keyW, &settings_key);
if(res != ERROR_SUCCESS)
return;
size = sizeof(val);
res = RegGetValueW(settings_key, zoomW, zoom_factorW, RRF_RT_REG_DWORD, NULL, &val, &size);
RegCloseKey(settings_key);
if(res != ERROR_SUCCESS)
return;
TRACE("Setting ZoomFactor to %u\n", val);
nsres = get_nsinterface((nsISupports*)doc->nscontainer->navigation, &IID_nsIDocShell, (void**)&doc_shell);
assert(nsres == NS_OK);
nsres = nsIDocShell_GetContentViewer(doc_shell, &content_viewer);
assert(nsres == NS_OK && content_viewer);
nsIDocShell_Release(doc_shell);
nsres = nsIContentViewer_SetFullZoom(content_viewer, (float)val/100000);
if(NS_FAILED(nsres))
ERR("SetFullZoom failed: %08x\n", nsres);
nsIContentViewer_Release(content_viewer);
}
static HRESULT WINAPI OleObject_SetClientSite(IOleObject *iface, IOleClientSite *pClientSite)
{
HTMLDocument *This = impl_from_IOleObject(iface);
IOleCommandTarget *cmdtrg = NULL;
IOleWindow *ole_window;
IBrowserService *browser_service;
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->client_cmdtrg) {
IOleCommandTarget_Release(This->doc_obj->client_cmdtrg);
This->doc_obj->client_cmdtrg = NULL;
}
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;
}
if(This->doc_obj->webbrowser) {
IUnknown_Release(This->doc_obj->webbrowser);
This->doc_obj->webbrowser = NULL;
}
if(This->doc_obj->browser_service) {
IUnknown_Release(This->doc_obj->browser_service);
This->doc_obj->browser_service = NULL;
}
if(This->doc_obj->travel_log) {
ITravelLog_Release(This->doc_obj->travel_log);
This->doc_obj->travel_log = NULL;
}
memset(&This->doc_obj->hostinfo, 0, sizeof(DOCHOSTUIINFO));
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 = IOleClientSite_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 */
FIXME("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) {
if(override_key_path[0]) {
/*FIXME: use override_key_path */
FIXME("override_key_path = %s\n", debugstr_w(override_key_path));
}
CoTaskMemFree(override_key_path);
}
IDocHostUIHandler2_Release(uihandler2);
}
This->doc_obj->hostui_setup = TRUE;
}
}
load_settings(This->doc_obj);
/* 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 = do_query_service((IUnknown*)pClientSite, &IID_IShellBrowser,
&IID_IBrowserService, (void**)&browser_service);
if(SUCCEEDED(hres)) {
ITravelLog *travel_log;
This->doc_obj->browser_service = (IUnknown*)browser_service;
hres = IBrowserService_GetTravelLog(browser_service, &travel_log);
if(SUCCEEDED(hres))
This->doc_obj->travel_log = travel_log;
}else {
browser_service = NULL;
}
hres = IOleClientSite_QueryInterface(pClientSite, &IID_IOleCommandTarget, (void**)&cmdtrg);
if(SUCCEEDED(hres)) {
VARIANT var;
OLECMD cmd = {OLECMDID_SETPROGRESSTEXT, 0};
This->doc_obj->client_cmdtrg = cmdtrg;
if(!hostui_setup) {
IDocObjectService *doc_object_service;
IWebBrowser2 *wb;
set_document_navigation(This->doc_obj, TRUE);
if(browser_service) {
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->webbrowser = (IUnknown*)wb;
}
}
}
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);
}
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;
}