C++系統(tǒng)相關(guān):InternetExplorer文件下載監(jiān)視

字號:

你是否想過類似下面的一些問題:
    如何過濾IE中的flash
    如何過濾在網(wǎng)頁中嵌入email的病毒
    如何實(shí)現(xiàn)像netants、flashget那樣的下載監(jiān)視
    看到上面問題,你會很快認(rèn)為這很簡單:
    “對IE的下載進(jìn)行監(jiān)視不就得了?發(fā)現(xiàn)后綴是”.swf”的文件就不進(jìn)行下載。這樣就過濾了flash.同理,發(fā)現(xiàn)后綴是”.eml”的下載也做同樣處理……”
    那么,話說回來,如何徹底監(jiān)視IE的下載呢?你不會為了這個(gè)寫一個(gè)驅(qū)動程序吧?
    如果你熟悉IE編程的話,會馬上意識到---使用BHO(Browser Helper Object)。
    但,僅僅使用BHO是不夠的。
    BHO類似鉤子(hook),特別的地方是:它鉤的是IE的事件。
    如果你還不熟悉BHO,請到MSDN網(wǎng)站看下面的文章:http://www.microsoft.com/Mind/0598/browhelp.htm
    通過上面文章你會發(fā)現(xiàn),BHO可以”hook”到IE的所有事件:
    Navigate->NavigateComplete->DownloadBegin->DownloadComplete->DocumentComplete等等。
    但它hook不到IE的整個(gè)下載事件!比如:
    www.csdn.net首頁里包含了大量的gif文件,BHO面對著它們變成了盲人……
    先了解一下IinternetProtocolRoot 的Start方法:
    HRESULT Start(
    LPCWSTR szUrl,//
    IInternetProtocolSink *pOIProtSink,
    IInternetBindInfo *pOIBindInfo,
    DWORD grfPI,
    HANDLE_PTR dwReserved
    );
    只要實(shí)現(xiàn)了IE的這個(gè)IinternetProtocolRoot接口,在其Start方法中檢查szUrl,就做到了監(jiān)視IE的下載。
    那么,怎么過濾呢?再看看IinternetProtocolSink接口的ReportResult方法!
    HRESULT ReportResult(
    HRESULT hrResult,
    DWORD dwError,
    LPCWSTR szResult
    );
    只需要在Start中調(diào)用其第二個(gè)參數(shù)pOIProtSink的ReportResult方法就可以實(shí)現(xiàn)過濾。實(shí)際上就是在IE下載文件之前欺騙IE說文件已經(jīng)下載完畢了。
    比方說我們要過濾IE中的gif文件,那么只需要實(shí)現(xiàn)以下代碼:
    STDMETHODIMP CQUrl::Start(//這里,我的類名叫CQUrl,大家不必理會
    LPCWSTR szUrl, IInternetProtocolSink *pIProtSink,
    IInternetBindInfo *pIBindInfo, DWORD grfSTI,
    DWORD dwReserved)
    {
    USES_CONVERSION;
    char *str=OLE2A(szUrl);
    if(strlen(str) > 4)
    {
    str = str + strlen(str) - 4; //取資源的最后四個(gè)字符,用來比較文件后綴
    if(_strnicmp(str,".gif",4) == 0)//后綴是gif
    {
    pIProtSink->ReportResult(S_OK, 0, 0);//告訴IE:下載已經(jīng)結(jié)束了! return S_OK;//返回,如果你返回INET_E_DOWNLOAD_FAILURE將看到另外一幅景象……
    }
    }
    return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
    }
    熟悉了監(jiān)視過濾的一般方法,下面開始把監(jiān)視過濾工作深入到IE之中吧!
    拿上面MIND雜志的iehelper的實(shí)例說起。
    我們在IEHelper的基礎(chǔ)上填加一個(gè)ATL對象,在其中繼承IinternetProtocol
    并實(shí)現(xiàn)IinternetProtocolRoot的Start方法就可以了!
    剩下所需的工作僅僅是在IEHelper的構(gòu)造函數(shù)中實(shí)現(xiàn)上面填加的atl對象。
    在IEHelper類里加兩個(gè)接口的指針:
    IInternetSession* m_pSession;
    IClassFactory* m_pFactory;
    然后創(chuàng)建對象:
    CIEHlprObj()
    {
    HRESULT hr = CoGetClassObject(CLSID_FiltUrl, CLSCTX_SERVER, NULL, IID_IClassFactory, (void**)&m_pFactory);
    if(hr==S_OK)
    {
    if(CoInternetGetSession(0, &m_pSession, 0)==S_OK)
    m_pSession->RegisterNameSpace(m_pFactory, CLSID_FiltUrl, L"http", 0, NULL, 0); //監(jiān)視HTTP服務(wù)
    }
    }
    必要的時(shí)候析構(gòu):
    CIEHlprObj::~CIEHlprObj()
    {
    if(m_pSession!=NULL)
    {
    m_pSession->UnregisterNameSpace(m_pFactory, L"http");
    m_pSession->Release();
    m_pSession = NULL;
    }
    if(m_pFactory!=NULL)
    {
    m_pFactory->Release();
    m_pFactory = NULL;
    }
    }