From 5d0873a74c314088426ea3e57fd2496c2d9fa78d Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Fri, 7 Apr 2006 17:52:00 +0900 Subject: [PATCH] shdocvw: Implement IEWinMain using a simple window frame. --- dlls/shdocvw/Makefile.in | 1 + dlls/shdocvw/iexplore.c | 555 ++++++++++++++++++++++++++++++++++++++++++++ dlls/shdocvw/shdocvw.h | 3 + dlls/shdocvw/shdocvw_main.c | 44 +++- 4 files changed, 591 insertions(+), 12 deletions(-) create mode 100644 dlls/shdocvw/iexplore.c diff --git a/dlls/shdocvw/Makefile.in b/dlls/shdocvw/Makefile.in index 2372d8a8843..b18eff9e180 100644 --- a/dlls/shdocvw/Makefile.in +++ b/dlls/shdocvw/Makefile.in @@ -16,6 +16,7 @@ C_SRCS = \ events.c \ factory.c \ frame.c \ + iexplore.c \ navigate.c \ oleobject.c \ persist.c \ diff --git a/dlls/shdocvw/iexplore.c b/dlls/shdocvw/iexplore.c new file mode 100644 index 00000000000..a07fa88e6a3 --- /dev/null +++ b/dlls/shdocvw/iexplore.c @@ -0,0 +1,555 @@ +/* + * 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 +#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 { + 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 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 { + IOleClientSiteVtbl *lpVtbl; + 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; +} + +struct 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; +} + +struct 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) 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; +} diff --git a/dlls/shdocvw/shdocvw.h b/dlls/shdocvw/shdocvw.h index 470d1705463..1b378ecfe1f 100644 --- a/dlls/shdocvw/shdocvw.h +++ b/dlls/shdocvw/shdocvw.h @@ -185,5 +185,8 @@ static inline void SHDOCVW_LockModule(void) { InterlockedIncrement( &SHDOCVW_ref static inline void SHDOCVW_UnlockModule(void) { InterlockedDecrement( &SHDOCVW_refCount ); } extern HINSTANCE shdocvw_hinstance; +extern void register_iewindow_class(void); +extern void unregister_iewindow_class(void); +extern BOOL create_ie_window(LPCWSTR url); #endif /* __WINE_SHDOCVW_H */ diff --git a/dlls/shdocvw/shdocvw_main.c b/dlls/shdocvw/shdocvw_main.c index 68ae3980559..dd30bb74fa5 100644 --- a/dlls/shdocvw/shdocvw_main.c +++ b/dlls/shdocvw/shdocvw_main.c @@ -100,18 +100,20 @@ static BOOL SHDOCVW_GetMozctlPath( LPWSTR szPath, DWORD sz ) */ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD fdwReason, LPVOID fImpLoad) { - TRACE("%p 0x%lx %p\n", hinst, fdwReason, fImpLoad); - switch (fdwReason) - { - case DLL_PROCESS_ATTACH: - shdocvw_hinstance = hinst; - break; - case DLL_PROCESS_DETACH: - if (SHDOCVW_hshell32) FreeLibrary(SHDOCVW_hshell32); - if (hMozCtl && hMozCtl != (HMODULE)~0UL) FreeLibrary(hMozCtl); - break; - } - return TRUE; + TRACE("%p 0x%lx %p\n", hinst, fdwReason, fImpLoad); + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + shdocvw_hinstance = hinst; + register_iewindow_class(); + break; + case DLL_PROCESS_DETACH: + if (SHDOCVW_hshell32) FreeLibrary(SHDOCVW_hshell32); + if (hMozCtl && hMozCtl != (HMODULE)~0UL) FreeLibrary(hMozCtl); + unregister_iewindow_class(); + break; + } + return TRUE; } /************************************************************************* @@ -664,7 +666,25 @@ DWORD WINAPI StopWatchAFORWARD(DWORD dwClass, LPCSTR lpszStr, DWORD dwUnknown, */ DWORD WINAPI IEWinMain(LPSTR szCommandLine, int nShowWindow) { + LPWSTR url; + DWORD len; + FIXME("%s %d\n", debugstr_a(szCommandLine), nShowWindow); + + CoInitialize(NULL); + + /* FIXME: parse the command line properly, handle -Embedding */ + + len = MultiByteToWideChar(CP_ACP, 0, szCommandLine, -1, NULL, 0); + url = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, szCommandLine, -1, url, len); + + create_ie_window(url); + + HeapFree(GetProcessHeap(), 0, url); + + CoUninitialize(); + ExitProcess(0); return 0; } -- 2.11.4.GIT