200元现金求助,挂接浏览器事件DWebBrowserEvents2会造成IE卡死

CaesarDM 2011-02-15 03:18:38
//项目被编译成dll,在dll加载时启动线程进行管理
//在AtlAdvise IE事件后,IE卡死
//CodeProject的例子看过,不过那是MFC+EXE形式,在dll没调通
//非BHO

=====================ieobj.h=====================
#pragma once

#include <ExDisp.h>
#include <Mshtml.h>
#include <atlbase.h>
#include <atlcom.h>

typedef void (CALLBACK* IE_BeforeNavigate2) (IDispatch*, LPOLESTR, DWORD, LPOLESTR,PBYTE , LPOLESTR, BOOL*);
typedef void (CALLBACK* IE_NavigateComplete2) (IDispatch *, LPOLESTR);


class CDWebEventSink : public DWebBrowserEvents2
{
public:
CDWebEventSink();
~CDWebEventSink();
protected:
DWORD m_dwRef;

IE_BeforeNavigate2 m_lpfnBeforeNavigate2;
IE_NavigateComplete2 m_lpfnNavigateComplete2;
public:
STDMETHODIMP QueryInterface(REFIID riid,void **ppvObject);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// IDispatch methods
STDMETHODIMP GetTypeInfoCount(UINT *pctinfo);
STDMETHODIMP GetTypeInfo(UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo);
STDMETHODIMP GetIDsOfNames(REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId);
STDMETHODIMP Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr);
};

class CInternetExplorer : public CDWebEventSink
{
public:
CInternetExplorer(void);
~CInternetExplorer(void);

protected:
IWebBrowser2* m_pWebBrowser2;
//::ATL::CComPtr<IWebBrowser2>
HWND m_hWndIE;
DWORD m_dwCookie;
public:
bool ConnectIE(HWND hwIE, UINT nGetObjectMsg);
void DisconnectIE(void);
};


=====================ieobj.cpp=====================

#include "StdAfx.h"
#include "ieobj.h"
#include <exdispid.h>

CInternetExplorer::CInternetExplorer(void)
{
m_hWndIE = 0;
m_pWebBrowser2 = NULL;
m_dwCookie = 0;
}

CInternetExplorer::~CInternetExplorer(void)
{
DisconnectIE();
}

bool CInternetExplorer::ConnectIE(HWND hwIE, UINT nGetObjectMsg)
{
//nGetObjectMsg的值为RegisterWindowMessage(_T("WM_HTML_GETOBJECT"))的返回值
//hwIE为某个IE的窗口句柄(定位到Internet Explorer_Server)

DisconnectIE();

LRESULT lRes;
HRESULT nRes;
DWORD_PTR dwRes;
lRes = SendMessageTimeout(hwIE,
nGetObjectMsg,
0,
0,
SMTO_ABORTIFHUNG,
1000,
&dwRes);
if (!lRes) return false;

IHTMLDocument2* pDoc2;
IServiceProvider* pSP;
IWebBrowser2* pBrowser;

//获取IHTMLDocument2对象
nRes = ObjectFromLresult(dwRes, IID_IHTMLDocument2, 0, (void **)&pDoc2);
if (!pDoc2) return false;

nRes = pDoc2->QueryInterface(IID_IServiceProvider, (void **) &pSP);
if FAILED(nRes) return false;

//获取浏览器对象
nRes = pSP->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void **) &pBrowser);
if FAILED(nRes) return false;

m_pWebBrowser2 = pBrowser;

//TODO 会造成IE卡死
nRes = AtlAdvise(m_pWebBrowser2, (IUnknown *)this, DIID_DWebBrowserEvents2, &m_dwCookie);
if FAILED(nRes) return false;

m_hWndIE = hwIE;
return true;
}

void CInternetExplorer::DisconnectIE(void)
{
if (m_dwCookie != 0 && m_pWebBrowser2 !=NULL)
{
LPUNKNOWN pUnkSink = NULL;

HRESULT nRes;

nRes=AtlUnadvise(m_pWebBrowser2, DIID_DWebBrowserEvents, m_dwCookie);
m_dwCookie = 0;
}
}

CDWebEventSink::CDWebEventSink(void)
{
m_dwRef = 1;
m_lpfnBeforeNavigate2 = NULL;
m_lpfnNavigateComplete2 = NULL;
}

CDWebEventSink::~CDWebEventSink(void)
{

}

STDMETHODIMP CDWebEventSink::QueryInterface(REFIID riid,void **ppvObject)
{
if(IsBadWritePtr(ppvObject,sizeof(void*))) return E_POINTER;

*ppvObject=NULL;

if(IsEqualIID(riid,IID_IUnknown) || IsEqualIID(riid,IID_IDispatch) || IsEqualIID(riid,DIID_DWebBrowserEvents2))
{
AddRef();
*ppvObject=this;
return S_OK;
}
else
{
return E_NOINTERFACE;
}
}

STDMETHODIMP_(ULONG) CDWebEventSink::AddRef()
{
InterlockedIncrement(&m_dwRef);
return m_dwRef;
}

STDMETHODIMP_(ULONG) CDWebEventSink::Release()
{
InterlockedDecrement(&m_dwRef);
if (m_dwRef == 0)
delete this;
return m_dwRef;
}

// We don't need to implement the next three methods because we are just a pure event sink
// We only care about Invoke() which is what IE calls to notify us of events

STDMETHODIMP CDWebEventSink::GetTypeInfoCount(UINT *pctinfo)
{
UNREFERENCED_PARAMETER(pctinfo);
*pctinfo=0;
return S_OK;
}

STDMETHODIMP CDWebEventSink::GetTypeInfo(UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo)
{
UNREFERENCED_PARAMETER(iTInfo);
UNREFERENCED_PARAMETER(lcid);
UNREFERENCED_PARAMETER(ppTInfo);

*ppTInfo = NULL;
return E_NOTIMPL;
}

STDMETHODIMP CDWebEventSink::GetIDsOfNames(REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId)
{
UNREFERENCED_PARAMETER(riid);
UNREFERENCED_PARAMETER(rgszNames);
UNREFERENCED_PARAMETER(cNames);
UNREFERENCED_PARAMETER(lcid);
UNREFERENCED_PARAMETER(rgDispId);

return E_NOTIMPL;
}

// This is called by IE to notify us of events
// Full documentation about all the events supported by DWebBrowserEvents2 can be found at
// http://msdn.microsoft.com/en-us/library/aa768283(VS.85).aspx
STDMETHODIMP CDWebEventSink::Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr)
{
UNREFERENCED_PARAMETER(lcid);
UNREFERENCED_PARAMETER(wFlags);
UNREFERENCED_PARAMETER(pVarResult);
UNREFERENCED_PARAMETER(pExcepInfo);
UNREFERENCED_PARAMETER(puArgErr);

if(!IsEqualIID(riid,IID_NULL)) return DISP_E_UNKNOWNINTERFACE; // riid should always be IID_NULL

switch (dispIdMember)
{
case DISPID_BEFORENAVIGATE2:
if (NULL!=m_lpfnBeforeNavigate2)
{
m_lpfnBeforeNavigate2(
(IDispatch*)pDispParams->rgvarg[0].byref,
(LPOLESTR)pDispParams->rgvarg[1].pbstrVal,
(DWORD)pDispParams->rgvarg[2].pintVal,
(LPOLESTR)pDispParams->rgvarg[3].pbstrVal,
(PBYTE)pDispParams->rgvarg[4].parray,
(LPOLESTR)pDispParams->rgvarg[5].pbstrVal,
(BOOL*)pDispParams->rgvarg[6].pboolVal
);
}
break;
case DISPID_NAVIGATECOMPLETE2:
if (NULL!=m_lpfnNavigateComplete2)
{
m_lpfnNavigateComplete2(
(IDispatch*)pDispParams->rgvarg[0].byref,
(LPOLESTR)pDispParams->rgvarg[1].pbstrVal
);
}
break;
}

return S_OK;
}
...全文
232 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
SmallPigII 2011-02-23
  • 打赏
  • 举报
回复
这里不清楚你的执行的环境是怎么样的.看代码,如果逻辑没有问题, 最好检查下执行的环境, IE版本,还有其他的.
可以尝试注入到ie进程再做上面atladvise处理,或者看看你执行的ie进程是不是退出了.
以上个人观点!
sgzwiz 2011-02-20
  • 打赏
  • 举报
回复
死循环了,仔细检查自己的代码,尤其在循环的地方
oyljerry 2011-02-18
  • 打赏
  • 举报
回复
既然要处理浏览器事件,最好的方式自然用BHO方式,这是最官方的做法.
gw_net 2011-02-18
  • 打赏
  • 举报
回复
attach到IE进程里面看看为什么

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧