wine-wine/dlls/shdocvw/iexplore.c

556 lines
12 KiB
C

/*
* SHDOCVW - Internet Explorer main frame window
*
* Copyright 2006 Mike McCormack (for CodeWeavers)
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define COBJMACROS
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "wingdi.h"
#include "winnls.h"
#include "ole2.h"
#include "exdisp.h"
#include "oleidl.h"
#include "shdocvw.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(shdocvw);
typedef struct tag_ieoc {
const IOleContainerVtbl *lpVtbl;
LONG ref;
} ieoc;
static ieoc *ieoc_from_IOleContainer(IOleContainer *iface)
{
return (ieoc*) iface;
}
static HRESULT WINAPI
ic_QueryInterface(IOleContainer *iface, REFIID riid, void **ppv)
{
if (IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_IOleClientSite))
{
IUnknown_AddRef(iface);
*ppv = iface;
return S_OK;
}
return E_NOINTERFACE;
}
static ULONG WINAPI ic_AddRef(IOleContainer *iface)
{
ieoc *This = ieoc_from_IOleContainer(iface);
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI ic_Release(IOleContainer *iface)
{
ieoc *This = ieoc_from_IOleContainer(iface);
LONG ref = InterlockedDecrement(&This->ref);
if (!ref)
{
HeapFree(GetProcessHeap(), 0, This);
SHDOCVW_UnlockModule();
}
TRACE("refcount = %ld\n", ref);
return ref;
}
static HRESULT WINAPI
ic_ParseDisplayName(IOleContainer *iface, IBindCtx *pbc, LPOLESTR pszDisplayName,
ULONG *pchEaten, IMoniker **ppmkOut)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI
ic_EnumObjects(IOleContainer *iface, DWORD grfFlags, IEnumUnknown **ppenum)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI ic_LockContainer(IOleContainer *iface, BOOL fLock)
{
FIXME("\n");
return E_NOTIMPL;
}
static const IOleContainerVtbl ocVtbl =
{
ic_QueryInterface,
ic_AddRef,
ic_Release,
ic_ParseDisplayName,
ic_EnumObjects,
ic_LockContainer,
};
static IOleContainer * get_container(void)
{
IOleContainer *This;
ieoc *oc;
oc = HeapAlloc(GetProcessHeap(), 0, sizeof *oc);
oc->lpVtbl = &ocVtbl;
oc->ref = 0;
This = (IOleContainer*) oc;
IOleContainer_AddRef(This);
SHDOCVW_LockModule();
return This;
}
/**********************/
typedef struct tag_iecs {
const IOleClientSiteVtbl *lpVtbl;
const IOleInPlaceSiteVtbl *lpInPlaceVtbl;
LONG ref;
IOleContainer *container;
HWND hwnd;
IOleObject *oo;
} iecs;
static iecs *iecs_from_IOleClientSite(IOleClientSite *iface)
{
return (iecs*) iface;
}
static iecs *iecs_from_IOleInPlaceSite(IOleInPlaceSite *iface)
{
return (iecs*) (((char*)iface) - FIELD_OFFSET(iecs,lpInPlaceVtbl));
}
static ULONG WINAPI iecs_AddRef(iecs *This)
{
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI iecs_Release(iecs *This)
{
LONG ref = InterlockedDecrement(&This->ref);
if (!ref)
{
if (This->hwnd)
DestroyWindow(This->hwnd);
IOleContainer_Release(This->container);
HeapFree(GetProcessHeap(), 0, This);
SHDOCVW_UnlockModule();
}
return ref;
}
static HRESULT WINAPI
iecs_QueryInterface(iecs *This, REFIID riid, void **ppv)
{
if (IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_IOleClientSite))
{
iecs_AddRef(This);
*ppv = &This->lpVtbl;;
return S_OK;
}
if (IsEqualGUID(riid, &IID_IOleInPlaceSite) ||
IsEqualGUID(riid, &IID_IOleWindow))
{
iecs_AddRef(This);
*ppv = &This->lpInPlaceVtbl;
return S_OK;
}
FIXME("unknown interface %s\n", debugstr_guid(riid));
return E_NOINTERFACE;
}
static HRESULT WINAPI
cs_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv)
{
iecs *This = iecs_from_IOleClientSite(iface);
return iecs_QueryInterface(This, riid, ppv);
}
static ULONG WINAPI cs_AddRef(IOleClientSite *iface)
{
iecs *This = iecs_from_IOleClientSite(iface);
return iecs_AddRef(This);
}
static ULONG WINAPI cs_Release(IOleClientSite *iface)
{
iecs *This = iecs_from_IOleClientSite(iface);
return iecs_Release(This);
}
static HRESULT WINAPI cs_SaveObject(IOleClientSite *iface)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI cs_GetMoniker(IOleClientSite *iface, DWORD dwAssign,
DWORD dwWhichMoniker, IMoniker **ppmk)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI
cs_GetContainer(IOleClientSite *iface, IOleContainer **ppContainer)
{
iecs *This = iecs_from_IOleClientSite(iface);
TRACE("\n");
IOleContainer_AddRef(This->container);
*ppContainer = This->container;
return S_OK;
}
static HRESULT WINAPI cs_ShowObject(IOleClientSite *iface)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI cs_OnShowWindow(IOleClientSite *iface, BOOL fShow)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI cs_RequestNewObjectLayout(IOleClientSite *iface)
{
FIXME("\n");
return E_NOTIMPL;
}
static const IOleClientSiteVtbl csVtbl =
{
cs_QueryInterface,
cs_AddRef,
cs_Release,
cs_SaveObject,
cs_GetMoniker,
cs_GetContainer,
cs_ShowObject,
cs_OnShowWindow,
cs_RequestNewObjectLayout,
};
static HRESULT WINAPI
is_QueryInterface(IOleInPlaceSite *iface, REFIID riid, void **ppv)
{
iecs *This = iecs_from_IOleInPlaceSite(iface);
return iecs_QueryInterface(This, riid, ppv);
}
static ULONG WINAPI is_AddRef(IOleInPlaceSite *iface)
{
iecs *This = iecs_from_IOleInPlaceSite(iface);
return iecs_AddRef(This);
}
static ULONG WINAPI is_Release(IOleInPlaceSite *iface)
{
iecs *This = iecs_from_IOleInPlaceSite(iface);
return iecs_Release(This);
}
static HRESULT WINAPI is_getWindow(IOleInPlaceSite *iface, HWND *phwnd)
{
iecs *This = iecs_from_IOleInPlaceSite(iface);
TRACE("\n");
*phwnd = This->hwnd;
return S_OK;
}
static HRESULT WINAPI
is_ContextSensitiveHelp(IOleInPlaceSite *iface, BOOL fEnterMode)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI is_CanInPlaceActivate(IOleInPlaceSite *iface)
{
FIXME("\n");
return S_OK;
}
static HRESULT WINAPI is_OnInPlaceActivate(IOleInPlaceSite *iface)
{
TRACE("\n");
return S_OK;
}
static HRESULT WINAPI is_OnUIActivate(IOleInPlaceSite *iface)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI
is_GetWindowContext(IOleInPlaceSite *iface, IOleInPlaceFrame **ppFrame,
IOleInPlaceUIWindow ** ppDoc, LPRECT lprcPosRect,
LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
{
iecs *This = iecs_from_IOleInPlaceSite(iface);
TRACE("%p\n", This);
*ppFrame = NULL;
*ppDoc = NULL;
GetClientRect(This->hwnd, lprcPosRect);
GetClientRect(This->hwnd, lprcClipRect);
if (lpFrameInfo->cb != sizeof *lpFrameInfo)
ERR("frame info wrong size\n");
lpFrameInfo->cAccelEntries = 0;
lpFrameInfo->fMDIApp = FALSE;
lpFrameInfo->haccel = 0;
lpFrameInfo->hwndFrame = This->hwnd;
return S_OK;
}
static HRESULT WINAPI is_Scroll(IOleInPlaceSite *iface, SIZE scrollExtent)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI is_OnUIDeactivate(IOleInPlaceSite *iface, BOOL fUndoable)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI is_OnInPlaceDeactivate(IOleInPlaceSite *iface)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI is_DiscardUndoState(IOleInPlaceSite *iface)
{
FIXME("\n");
return E_NOTIMPL;
}
static const IOleInPlaceSiteVtbl isVtbl =
{
is_QueryInterface,
is_AddRef,
is_Release,
is_getWindow,
is_ContextSensitiveHelp,
is_CanInPlaceActivate,
is_OnInPlaceActivate,
is_OnUIActivate,
is_GetWindowContext,
is_Scroll,
is_OnUIDeactivate,
is_OnInPlaceDeactivate,
is_DiscardUndoState,
};
static const WCHAR szIEWinFrame[] = { 'I','E','F','r','a','m','e',0 };
static LRESULT iewnd_OnCreate(HWND hwnd, LPCREATESTRUCTW lpcs)
{
SetWindowLongPtrW(hwnd, 0, (LONG_PTR) lpcs->lpCreateParams);
return 0;
}
static LRESULT iewnd_OnSize(iecs *This, INT width, INT height)
{
SIZEL sz;
TRACE("%p %d %d\n", This, width, height);
sz.cx = width;
sz.cy = height;
IOleObject_SetExtent(This->oo, DVASPECT_CONTENT, &sz);
return 0;
}
static LRESULT iewnd_OnDestroy(iecs *This)
{
TRACE("%p\n", This);
This->hwnd = NULL;
IOleObject_Close(This->oo, OLECLOSE_NOSAVE);
IOleObject_Release(This->oo);
This->oo = NULL;
PostQuitMessage(0);
return 0;
}
static LRESULT CALLBACK
ie_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
iecs *This = (iecs*) GetWindowLongPtrW(hwnd, 0);
switch (msg)
{
case WM_CREATE:
return iewnd_OnCreate(hwnd, (LPCREATESTRUCTW)lparam);
case WM_DESTROY:
return iewnd_OnDestroy(This);
case WM_SIZE:
return iewnd_OnSize(This, LOWORD(lparam), HIWORD(lparam));
}
return DefWindowProcW(hwnd, msg, wparam, lparam);
}
static IOleClientSite * get_client_site(IOleObject *oo, HWND *phwnd)
{
static const WCHAR winname[] = {
'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r',0};
IOleClientSite *This;
HWND hwnd;
iecs *cs;
cs = HeapAlloc(GetProcessHeap(), 0, sizeof *cs);
if (!cs)
return NULL;
cs->ref = 0;
cs->lpVtbl = &csVtbl;
cs->lpInPlaceVtbl = &isVtbl;
cs->container = get_container();
cs->oo = oo;
hwnd = CreateWindowW(szIEWinFrame, winname, WS_VISIBLE|WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, shdocvw_hinstance, cs);
if (!hwnd)
{
HeapFree(GetProcessHeap(), 0, cs);
return NULL;
}
IOleObject_AddRef(oo);
cs->hwnd = hwnd;
*phwnd = hwnd;
This = (IOleClientSite*) cs;
IOleClientSite_AddRef(This);
SHDOCVW_LockModule();
return This;
}
void register_iewindow_class(void)
{
WNDCLASSW wc;
memset(&wc, 0, sizeof wc);
wc.style = 0;
wc.lpfnWndProc = ie_window_proc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(iecs *);
wc.hInstance = shdocvw_hinstance;
wc.hIcon = 0;
wc.hCursor = LoadCursorW(0, MAKEINTRESOURCEW(IDI_APPLICATION));
wc.hbrBackground = 0;
wc.lpszClassName = szIEWinFrame;
wc.lpszMenuName = NULL;
RegisterClassW(&wc);
}
void unregister_iewindow_class(void)
{
UnregisterClassW(szIEWinFrame, shdocvw_hinstance);
}
BOOL create_ie_window(LPCWSTR url)
{
IWebBrowser2 *wb = NULL;
IOleObject *oo = NULL;
IOleClientSite *cs = NULL;
HRESULT r;
MSG msg;
RECT rcClient = { 0,0,100,100 };
BSTR bstrUrl;
HWND hwnd = NULL;
/* create the web browser */
r = CoCreateInstance(&CLSID_WebBrowser, NULL, CLSCTX_INPROC_SERVER,
&IID_IWebBrowser2, (LPVOID)&wb);
if (FAILED(r))
goto error;
/* get its IOleObject interface */
r = IWebBrowser2_QueryInterface(wb, &IID_IOleObject, (void**) &oo);
if (FAILED(r))
goto error;
/* create the window frame for the browser object */
cs = get_client_site(oo, &hwnd);
if (!cs)
goto error;
/* attach the browser to the window frame */
r = IOleObject_SetClientSite(oo, cs);
if (FAILED(r))
goto error;
/* activate the browser */
r = IOleObject_DoVerb(oo, OLEIVERB_INPLACEACTIVATE, &msg, cs, 0, hwnd, &rcClient);
if (FAILED(r))
goto error;
/* navigate to the first page */
bstrUrl = SysAllocString(url);
IWebBrowser2_Navigate(wb, bstrUrl, NULL, NULL, NULL, NULL);
/* run the message loop for this thread */
while (GetMessageW(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
r = S_OK;
/* clean up */
error:
if (cs)
IOleClientSite_Release(cs);
if (oo)
IOleObject_Release(oo);
if (wb)
IOleObject_Release(wb);
return r;
}