From 967561f8eae15cd3586fb97e8865685060344894 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Fri, 7 Jan 2011 19:03:23 +0100 Subject: [PATCH] shdocvw: Separate DocHost ref count from InternetExplorer ref count. --- dlls/shdocvw/client.c | 4 +- dlls/shdocvw/ie.c | 21 +++++-- dlls/shdocvw/iexplore.c | 116 ++++++++++++++++++++++++++++---------- dlls/shdocvw/shdocvw.h | 14 ++++- dlls/shdocvw/webbrowser.c | 14 +++++ 5 files changed, 130 insertions(+), 39 deletions(-) diff --git a/dlls/shdocvw/client.c b/dlls/shdocvw/client.c index e94a32cbdf2..12fd464b7bc 100644 --- a/dlls/shdocvw/client.c +++ b/dlls/shdocvw/client.c @@ -83,13 +83,13 @@ static HRESULT WINAPI ClientSite_QueryInterface(IOleClientSite *iface, REFIID ri static ULONG WINAPI ClientSite_AddRef(IOleClientSite *iface) { DocHost *This = impl_from_IOleClientSite(iface); - return IDispatch_AddRef(This->disp); + return This->container_vtbl->addref(This); } static ULONG WINAPI ClientSite_Release(IOleClientSite *iface) { DocHost *This = impl_from_IOleClientSite(iface); - return IDispatch_Release(This->disp); + return This->container_vtbl->release(This); } static HRESULT WINAPI ClientSite_SaveObject(IOleClientSite *iface) diff --git a/dlls/shdocvw/ie.c b/dlls/shdocvw/ie.c index 05485e02477..f968302ee5c 100644 --- a/dlls/shdocvw/ie.c +++ b/dlls/shdocvw/ie.c @@ -49,7 +49,7 @@ static HRESULT WINAPI InternetExplorer_QueryInterface(IWebBrowser2 *iface, REFII *ppv = &This->IWebBrowser2_iface; }else if(IsEqualGUID(&IID_IConnectionPointContainer, riid)) { TRACE("(%p)->(IID_IConnectionPointContainer %p)\n", This, ppv); - *ppv = &This->doc_host.cps.IConnectionPointContainer_iface; + *ppv = &This->doc_host->doc_host.cps.IConnectionPointContainer_iface; }else if(HlinkFrame_QI(&This->hlink_frame, riid, ppv)) { return S_OK; } @@ -79,8 +79,17 @@ static ULONG WINAPI InternetExplorer_Release(IWebBrowser2 *iface) TRACE("(%p) ref=%d\n", This, ref); if(!ref) { - DocHost_Release(&This->doc_host); + if(This->doc_host) { + DocHost_Release(&This->doc_host->doc_host); + if(This->doc_host) + This->doc_host->ie = NULL; + } + + if(This->frame_hwnd) + DestroyWindow(This->frame_hwnd); heap_free(This); + + released_obj(); } return ref; @@ -140,7 +149,7 @@ static HRESULT WINAPI InternetExplorer_GoHome(IWebBrowser2 *iface) { InternetExplorer *This = impl_from_IWebBrowser2(iface); TRACE("(%p)\n", This); - return go_home(&This->doc_host); + return go_home(&This->doc_host->doc_host); } static HRESULT WINAPI InternetExplorer_GoSearch(IWebBrowser2 *iface) @@ -159,7 +168,7 @@ static HRESULT WINAPI InternetExplorer_Navigate(IWebBrowser2 *iface, BSTR szUrl, TRACE("(%p)->(%s %p %p %p %p)\n", This, debugstr_w(szUrl), Flags, TargetFrameName, PostData, Headers); - return navigate_url(&This->doc_host, szUrl, Flags, TargetFrameName, PostData, Headers); + return navigate_url(&This->doc_host->doc_host, szUrl, Flags, TargetFrameName, PostData, Headers); } static HRESULT WINAPI InternetExplorer_Refresh(IWebBrowser2 *iface) @@ -294,7 +303,7 @@ static HRESULT WINAPI InternetExplorer_get_LocationURL(IWebBrowser2 *iface, BSTR TRACE("(%p)->(%p)\n", This, LocationURL); - return get_location_url(&This->doc_host, LocationURL); + return get_location_url(&This->doc_host->doc_host, LocationURL); } static HRESULT WINAPI InternetExplorer_get_Busy(IWebBrowser2 *iface, VARIANT_BOOL *pBool) @@ -473,7 +482,7 @@ static HRESULT WINAPI InternetExplorer_Navigate2(IWebBrowser2 *iface, VARIANT *U return E_INVALIDARG; } - return navigate_url(&This->doc_host, V_BSTR(URL), Flags, TargetFrameName, PostData, Headers); + return navigate_url(&This->doc_host->doc_host, V_BSTR(URL), Flags, TargetFrameName, PostData, Headers); } static HRESULT WINAPI InternetExplorer_QueryStatusWB(IWebBrowser2 *iface, OLECMDID cmdID, OLECMDF *pcmdf) diff --git a/dlls/shdocvw/iexplore.c b/dlls/shdocvw/iexplore.c index d966f79d2cd..5c03b9c3ad8 100644 --- a/dlls/shdocvw/iexplore.c +++ b/dlls/shdocvw/iexplore.c @@ -50,6 +50,8 @@ static const WCHAR szIEWinFrame[] = { 'I','E','F','r','a','m','e',0 }; static const WCHAR wszWineInternetExplorer[] = {'W','i','n','e',' ','I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r',0}; +static LONG obj_cnt; + HRESULT update_ie_statustext(InternetExplorer* This, LPCWSTR text) { if(!SendMessageW(This->status_hwnd, SB_SETTEXTW, MAKEWORD(SB_SIMPLEID, 0), (LPARAM)text)) @@ -505,8 +507,8 @@ static LRESULT iewnd_OnSize(InternetExplorer *This, INT width, INT height) adjust_ie_docobj_rect(This->frame_hwnd, &docarea); - if(This->doc_host.hwnd) - SetWindowPos(This->doc_host.hwnd, NULL, docarea.left, docarea.top, docarea.right, docarea.bottom, + if(This->doc_host->doc_host.hwnd) + SetWindowPos(This->doc_host->doc_host.hwnd, NULL, docarea.left, docarea.top, docarea.right, docarea.bottom, SWP_NOZORDER | SWP_NOACTIVATE); SetWindowPos(hwndRebar, NULL, 0, 0, width, barHeight, SWP_NOZORDER | SWP_NOACTIVATE); @@ -551,7 +553,6 @@ static LRESULT iewnd_OnDestroy(InternetExplorer *This) free_fav_menu_data(get_fav_menu(This->menu)); ImageList_Destroy(list); This->frame_hwnd = NULL; - PostQuitMessage(0); /* FIXME */ return 0; } @@ -565,11 +566,11 @@ static LRESULT iewnd_OnCommand(InternetExplorer *This, HWND hwnd, UINT msg, WPAR break; case ID_BROWSE_PRINT: - if(This->doc_host.document) + if(This->doc_host->doc_host.document) { IOleCommandTarget* target; - if(FAILED(IUnknown_QueryInterface(This->doc_host.document, &IID_IOleCommandTarget, (LPVOID*)&target))) + if(FAILED(IUnknown_QueryInterface(This->doc_host->doc_host.document, &IID_IOleCommandTarget, (LPVOID*)&target))) break; IOleCommandTarget_Exec(target, &CGID_MSHTML, IDM_PRINT, OLECMDEXECOPT_DODEFAULT, NULL, NULL); @@ -587,7 +588,7 @@ static LRESULT iewnd_OnCommand(InternetExplorer *This, HWND hwnd, UINT msg, WPAR break; case ID_BROWSE_QUIT: - iewnd_OnDestroy(This); + ShowWindow(hwnd, SW_HIDE); break; default: @@ -624,6 +625,17 @@ ie_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { case WM_CREATE: return iewnd_OnCreate(hwnd, (LPCREATESTRUCTW)lparam); + case WM_CLOSE: + TRACE("WM_CLOSE\n"); + ShowWindow(hwnd, SW_HIDE); + return 0; + case WM_SHOWWINDOW: + TRACE("WM_SHOWWINDOW %lx\n", wparam); + if(wparam) + IWebBrowser2_AddRef(&This->IWebBrowser2_iface); + else + IWebBrowser2_Release(&This->IWebBrowser2_iface); + break; case WM_DESTROY: return iewnd_OnDestroy(This); case WM_SIZE: @@ -633,7 +645,7 @@ ie_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) case WM_NOTIFY: return iewnd_OnNotify(This, wparam, lparam); case WM_DOCHOSTTASK: - return process_dochost_task(&This->doc_host, lparam); + return process_dochost_task(&This->doc_host->doc_host, lparam); case WM_UPDATEADDRBAR: return update_addrbar(This, lparam); } @@ -678,13 +690,13 @@ static void create_frame_hwnd(InternetExplorer *This) NULL, NULL /* FIXME */, shdocvw_hinstance, This); } -static IWebBrowser2 *create_ie_window(LPCSTR cmdline) +static BOOL create_ie_window(LPCSTR cmdline) { IWebBrowser2 *wb = NULL; InternetExplorer_Create(NULL, &IID_IWebBrowser2, (void**)&wb); if(!wb) - return NULL; + return FALSE; IWebBrowser2_put_Visible(wb, VARIANT_TRUE); IWebBrowser2_put_MenuBar(wb, VARIANT_TRUE); @@ -718,12 +730,39 @@ static IWebBrowser2 *create_ie_window(LPCSTR cmdline) SysFreeString(V_BSTR(&var_url)); } - return wb; + IWebBrowser2_Release(wb); + return TRUE; } -static inline InternetExplorer *impl_from_DocHost(DocHost *iface) +static inline IEDocHost *impl_from_DocHost(DocHost *iface) { - return CONTAINING_RECORD(iface, InternetExplorer, doc_host); + return CONTAINING_RECORD(iface, IEDocHost, doc_host); +} + +static ULONG IEDocHost_addref(DocHost *iface) +{ + IEDocHost *This = impl_from_DocHost(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG IEDocHost_release(DocHost *iface) +{ + IEDocHost *This = impl_from_DocHost(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if(!ref) { + if(This->ie) + This->ie->doc_host = NULL; + heap_free(This); + } + + return ref; } static void WINAPI DocHostContainer_GetDocObjRect(DocHost* This, RECT* rc) @@ -732,10 +771,10 @@ static void WINAPI DocHostContainer_GetDocObjRect(DocHost* This, RECT* rc) adjust_ie_docobj_rect(This->frame_hwnd, rc); } -static HRESULT WINAPI DocHostContainer_SetStatusText(DocHost* This, LPCWSTR text) +static HRESULT WINAPI DocHostContainer_SetStatusText(DocHost *iface, LPCWSTR text) { - InternetExplorer* ie = impl_from_DocHost(This); - return update_ie_statustext(ie, text); + IEDocHost *This = impl_from_DocHost(iface); + return update_ie_statustext(This->ie, text); } static void WINAPI DocHostContainer_SetURL(DocHost* This, LPCWSTR url) @@ -749,6 +788,8 @@ static HRESULT DocHostContainer_exec(DocHost* This, const GUID *cmd_group, DWORD return S_OK; } static const IDocHostContainerVtbl DocHostContainerVtbl = { + IEDocHost_addref, + IEDocHost_release, DocHostContainer_GetDocObjRect, DocHostContainer_SetStatusText, DocHostContainer_SetURL, @@ -763,25 +804,40 @@ HRESULT InternetExplorer_Create(IUnknown *pOuter, REFIID riid, void **ppv) TRACE("(%p %s %p)\n", pOuter, debugstr_guid(riid), ppv); ret = heap_alloc_zero(sizeof(InternetExplorer)); - ret->ref = 0; + if(!ret) + return E_OUTOFMEMORY; - ret->doc_host.disp = (IDispatch*)&ret->IWebBrowser2_iface; - DocHost_Init(&ret->doc_host, (IDispatch*)&ret->IWebBrowser2_iface, &DocHostContainerVtbl); + ret->doc_host = heap_alloc_zero(sizeof(IEDocHost)); + if(!ret->doc_host) { + heap_free(ret); + return E_OUTOFMEMORY; + } + + ret->ref = 1; + ret->doc_host->ie = ret; + + DocHost_Init(&ret->doc_host->doc_host, (IDispatch*)&ret->IWebBrowser2_iface, &DocHostContainerVtbl); InternetExplorer_WebBrowser_Init(ret); - HlinkFrame_Init(&ret->hlink_frame, (IUnknown*)&ret->IWebBrowser2_iface, &ret->doc_host); + HlinkFrame_Init(&ret->hlink_frame, (IUnknown*)&ret->IWebBrowser2_iface, &ret->doc_host->doc_host); create_frame_hwnd(ret); - ret->doc_host.frame_hwnd = ret->frame_hwnd; + ret->doc_host->doc_host.frame_hwnd = ret->frame_hwnd; hres = IWebBrowser2_QueryInterface(&ret->IWebBrowser2_iface, riid, ppv); - if(FAILED(hres)) { - heap_free(ret); + IWebBrowser2_Release(&ret->IWebBrowser2_iface); + if(FAILED(hres)) return hres; - } - return hres; + InterlockedIncrement(&obj_cnt); + return S_OK; +} + +void released_obj(void) +{ + if(!InterlockedDecrement(&obj_cnt)) + PostQuitMessage(0); } /****************************************************************** @@ -791,7 +847,6 @@ HRESULT InternetExplorer_Create(IUnknown *pOuter, REFIID riid, void **ppv) */ DWORD WINAPI IEWinMain(LPSTR szCommandLine, int nShowWindow) { - IWebBrowser2 *wb = NULL; MSG msg; HRESULT hres; @@ -812,8 +867,12 @@ DWORD WINAPI IEWinMain(LPSTR szCommandLine, int nShowWindow) ExitProcess(1); } - if(strcasecmp(szCommandLine, "-embedding")) - wb = create_ie_window(szCommandLine); + if(strcasecmp(szCommandLine, "-embedding")) { + if(!create_ie_window(szCommandLine)) { + CoUninitialize(); + ExitProcess(1); + } + } /* run the message loop for this thread */ while (GetMessageW(&msg, 0, 0, 0)) @@ -822,9 +881,6 @@ DWORD WINAPI IEWinMain(LPSTR szCommandLine, int nShowWindow) DispatchMessageW(&msg); } - if(wb) - IWebBrowser2_Release(wb); - register_class_object(FALSE); CoUninitialize(); diff --git a/dlls/shdocvw/shdocvw.h b/dlls/shdocvw/shdocvw.h index 15a85edeed2..86c9b42cb47 100644 --- a/dlls/shdocvw/shdocvw.h +++ b/dlls/shdocvw/shdocvw.h @@ -86,6 +86,8 @@ typedef struct _task_header_t { typedef struct _IDocHostContainerVtbl { + ULONG (*addref)(DocHost*); + ULONG (*release)(DocHost*); void (WINAPI* GetDocObjRect)(DocHost*,RECT*); HRESULT (WINAPI* SetStatusText)(DocHost*,LPCWSTR); void (WINAPI* SetURL)(DocHost*,LPCWSTR); @@ -182,6 +184,14 @@ struct WebBrowser { DocHost doc_host; }; +typedef struct { + DocHost doc_host; + + LONG ref; + + InternetExplorer *ie; +} IEDocHost; + struct InternetExplorer { IWebBrowser2 IWebBrowser2_iface; HlinkFrame hlink_frame; @@ -192,7 +202,7 @@ struct InternetExplorer { HWND status_hwnd; HMENU menu; - DocHost doc_host; + IEDocHost *doc_host; }; void WebBrowser_OleObject_Init(WebBrowser*); @@ -235,6 +245,8 @@ LRESULT process_dochost_task(DocHost*,LPARAM); HRESULT InternetExplorer_Create(IUnknown*,REFIID,void**); void InternetExplorer_WebBrowser_Init(InternetExplorer*); +void released_obj(void); + HRESULT CUrlHistory_Create(IUnknown*,REFIID,void**); HRESULT InternetShortcut_Create(IUnknown*,REFIID,void**); diff --git a/dlls/shdocvw/webbrowser.c b/dlls/shdocvw/webbrowser.c index 89e413b5b28..1a0e189d02b 100644 --- a/dlls/shdocvw/webbrowser.c +++ b/dlls/shdocvw/webbrowser.c @@ -1110,6 +1110,18 @@ static inline WebBrowser *impl_from_DocHost(DocHost *iface) return CONTAINING_RECORD(iface, WebBrowser, doc_host); } +static ULONG WebBrowser_addref(DocHost *iface) +{ + WebBrowser *This = impl_from_DocHost(iface); + return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); +} + +static ULONG WebBrowser_release(DocHost *iface) +{ + WebBrowser *This = impl_from_DocHost(iface); + return IWebBrowser2_Release(&This->IWebBrowser2_iface); +} + static void WINAPI DocHostContainer_GetDocObjRect(DocHost* This, RECT* rc) { GetClientRect(This->frame_hwnd, rc); @@ -1156,6 +1168,8 @@ static HRESULT DocHostContainer_exec(DocHost *doc_host, const GUID *cmd_group, D } static const IDocHostContainerVtbl DocHostContainerVtbl = { + WebBrowser_addref, + WebBrowser_release, DocHostContainer_GetDocObjRect, DocHostContainer_SetStatusText, DocHostContainer_SetURL,