1000分:关于用IInternetProtocol实现过滤

hpygzhx520 2008-09-13 02:33:31
近期需要用到这个功能,知道用异步可插入协议可实现过滤。比如过滤gif,可在下载开始的时候就取消下载。这在很多时候是很有用的,可以提高打开网页的速度。

找了一些资料,发现这个描述得比较仔细:
http://dev.csdn.net/article/11/11108.shtm

我没学过VC,加之原代码早已无法下载,所以恳请高手根据这个资料帮忙写个DLL,让VB等调用。这不是懒惰的问题,我研究了很长时间了,我前几天用VB照此资料写了一次,用VB写的话的确能捕捉到IInternetProtocol的Start方法,但不知道是什么原因,在IInternetProtocol的Start方法中返回INET_E_USE_DEFAULT_PROTOCOLHANDLER程序便崩溃。据说这也许是VB不支持多线程造成的。于是,不得已想用C写DLL来实现。

对于能熟练使用VC的朋友来说,写这个DLL也许不需要很多时间,但对于啊,无异于登天之难……,所以恳请朋友们帮个忙,不胜感激!

第一次来VC论坛,级别低,没法给更高的分,但若能实现,无以为谢,但分是不成问题的。

期待各位朋友的帮助……
...全文
896 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
omagic 2011-06-24
  • 打赏
  • 举报
回复
jameshooo 是个好人!!!
hpygzhx520 2008-09-14
  • 打赏
  • 举报
回复
是的,完全正确。

我用VB写过ActiveX DLL,Start方法是会调用的,只要RegisterNameSpace成功后,就会调用IInternetProtocol的Start方法。所以可以证明方向是不错的,呵呵。

谢谢。
jameshooo 2008-09-14
  • 打赏
  • 举报
回复
先问清楚使用环境,我的猜测:VB应用程序,使用了浏览器控件,希望能够屏蔽某些文件的下载,对不对?
hpygzhx520 2008-09-14
  • 打赏
  • 举报
回复
第三个尝试:直接用urlmon.dll的IInternetProtocol接口并替换Start方法。该办法省去DLL,也比较省事。但问题比较多。如:IE6与IE7要分开处理,因为MS在IE7出来后修改了这个接口。更关键的是情况比较复杂,在很多时候会出现一些无法找到原因的错误。比如实现该功能后当调用“另存为”方法的时候崩溃等等。

最后结论:无法完成。

谢谢。
hpygzhx520 2008-09-14
  • 打赏
  • 举报
回复
第二个尝试:
用VB写DLL:
代码如下:
Implements olelib2.IInternetProtocol
Implements olelib.IInternetProtocolInfo
Private IID_IClassFactory As UUID

Private Sub Class_Initialize()
CLSIDFromString "{00000001-0000-0000-C000-000000000046}", IID_IClassFactory
CLSIDFromString "{9DE6F856-CB28-4E4E-8150-8D0803ADF934}", myFilterCLSID 'DLL自身的UUID
End Sub

Public Sub StartFilter()
CoGetClassObject myFilterCLSID, CLSCTX_INPROC_SERVER, Null, IID_IClassFactory, m_pFactory
CoInternetGetSession ByVal 0&, m_pSession, ByVal 0&
If Not m_pSession Is Nothing Then
m_pSession.RegisterNameSpace m_pFactory, myFilterCLSID, "http", ByVal 0&, 0&, ByVal 0&
m_pSession.RegisterNameSpace m_pFactory, myFilterCLSID, "https", ByVal 0&, 0&, ByVal 0&
End If
End Sub

Public Sub CloseFilter()
On Error Resume Next
If Not m_pSession Is Nothing Then
m_pSession.UnregisterNameSpace m_pSession, StrPtr("http")
m_pSession.UnregisterNameSpace m_pSession, StrPtr("https")
Set m_pSession = Nothing
End If
If Not m_pFactory Is Nothing Then
Set m_pFactory = Nothing
End If
End Sub

Public Sub SetFilterStr(ByVal tStr As String)

End Sub

Private Sub IInternetProtocol_Abort(ByVal hrReason As Long, ByVal dwOptions As Long)
Err.Raise E_NOTIMPL
End Sub

Private Sub IInternetProtocol_Continue(pProtocolData As olelib.PROTOCOLDATA)
Err.Raise E_NOTIMPL
End Sub

Private Sub IInternetProtocol_LockRequest(ByVal dwOptions As Long)

End Sub

Private Sub IInternetProtocol_Read(ByVal pv As Long, ByVal cb As Long, pcbRead As Long)
Err.Raise S_FALSE
End Sub

Private Sub IInternetProtocol_Resume()
Err.Raise E_NOTIMPL
End Sub

Private Sub IInternetProtocol_Seek(ByVal dlibMove As Currency, ByVal dwOrigin As Long, plibNewPosition As Currency)
Err.Raise E_NOTIMPL
End Sub

Private Sub IInternetProtocol_Start(ByVal szUrl As Long, ByVal pOIProtSink As olelib2.IInternetProtocolSink, ByVal pOIBindInfo As olelib.IInternetBindInfo, ByVal grfPI As olelib.PI_FLAGS, dwReserved As olelib.PROTOCOLFILTERDATA)
Dim tUrl$
tUrl = SysAllocString(szUrl)
If Len(tUrl) > 4 Then
If LCase(Right(tUrl, 4)) = ".gif" Then
pOIProtSink.ReportResult S_OK, 0&, ""
Else
Err.Raise INET_E_USE_DEFAULT_PROTOCOLHANDLER '这里会崩溃
End If
Else
Err.Raise INET_E_USE_DEFAULT_PROTOCOLHANDLER '这里会崩溃
End If
End Sub

Private Sub IInternetProtocol_Suspend()
Err.Raise E_NOTIMPL
End Sub

Private Sub IInternetProtocol_Terminate(ByVal dwOptions As Long)

End Sub

Private Sub IInternetProtocol_UnlockRequest()

End Sub

Private Sub IInternetProtocolInfo_CombineUrl(ByVal pwzBaseUrl As Long, ByVal pwzRelativeUrl As Long, ByVal dwCombineFlags As Long, ByVal pwzResult As Long, ByVal cchResult As Long, pcchResult As Long, ByVal dwReserved As Long)
Err.Raise INET_E_DEFAULT_ACTION
End Sub

Private Sub IInternetProtocolInfo_CompareUrl(ByVal pwzUrl1 As Long, ByVal pwzUrl2 As Long, ByVal dwCompareFlags As Long)
If SysAllocString(pwzUrl1) = SysAllocString(pwzUrl2) Then

Else
Err.Raise S_FALSE
End If
End Sub

Private Sub IInternetProtocolInfo_ParseUrl(ByVal pwzUrl As Long, ByVal PARSEACTION As olelib.PARSEACTION, ByVal dwParseFlags As Long, ByVal pwzResult As Long, ByVal cchResult As Long, pcchResult As Long, ByVal dwReserved As Long)
Err.Raise INET_E_DEFAULT_ACTION
End Sub

Private Sub IInternetProtocolInfo_QueryInfo(ByVal pwzUrl As Long, ByVal OueryOption As olelib.QUERYOPTION, ByVal dwQueryFlags As Long, ByVal pBuffer As Long, ByVal cbBuffer As Long, pcbBuf As Long, ByVal dwReserved As Long)
Err.Raise INET_E_DEFAULT_ACTION
End Sub

同样是返回INET_E_USE_DEFAULT_PROTOCOLHANDLER的时候会崩溃。但若返回其他值,则会停止导航,导致无法打开网页
hpygzhx520 2008-09-14
  • 打赏
  • 举报
回复
好的。谢谢。

第一个尝试:
因为我做的浏览器已经实现了相关接口,于是在IServiceProvider接口的QueryService中监视与APP相关的接口查询,看是否查询了相关接口。结论:与之相关的,仅会查询IInternetProtocol接口,于是增加IInternetProtocol接口支持代码。
代码如下:(注:VB中的接口代码,若不写Err.Raise,则相当于return S_OK)
Private Sub IInternetProtocol_Abort(ByVal hrReason As Long, ByVal dwOptions As Long)
Err.Raise E_NOTIMPL
End Sub

Private Sub IInternetProtocol_Continue(pProtocolData As olelib.PROTOCOLDATA)
Err.Raise E_NOTIMPL
End Sub

Private Sub IInternetProtocol_LockRequest(ByVal dwOptions As Long)

End Sub

Private Sub IInternetProtocol_Read(ByVal pv As Long, ByVal cb As Long, pcbRead As Long)
Err.Raise S_FALSE
End Sub

Private Sub IInternetProtocol_Resume()
Err.Raise E_NOTIMPL
End Sub

Private Sub IInternetProtocol_Seek(ByVal dlibMove As Currency, ByVal dwOrigin As Long, plibNewPosition As Currency)
Err.Raise E_NOTIMPL
End Sub

Private Sub IInternetProtocol_Start(ByVal szUrl As Long, ByVal pOIProtSink As olelib2.IInternetProtocolSink, ByVal pOIBindInfo As olelib.IInternetBindInfo, ByVal grfPI As olelib.PI_FLAGS, dwReserved As olelib.PROTOCOLFILTERDATA)
Dim tUrl$
tUrl = SysAllocString(szUrl)
If Len(tUrl) > 4 Then
If LCase(Right(tUrl, 4)) = ".gif" Then'检测后4个字符
pOIProtSink.ReportResult S_OK, 0&, ""
Else
Err.Raise INET_E_USE_DEFAULT_PROTOCOLHANDLER '这里会崩溃
End If
Else
Err.Raise INET_E_USE_DEFAULT_PROTOCOLHANDLER '这里会崩溃
End If
End Sub

Private Sub IInternetProtocol_Suspend()
Err.Raise E_NOTIMPL
End Sub

Private Sub IInternetProtocol_Terminate(ByVal dwOptions As Long)

End Sub

Private Sub IInternetProtocol_UnlockRequest()

End Sub


但是返回INET_E_USE_DEFAULT_PROTOCOLHANDLER的时候会崩溃。但若返回其他值,则会停止导航,导致无法打开网页。(注:Err.Raise 可能并不完全等同于return ,但我做过替换VTable,即让其真正做到return的效果,但症状相同,在同一个地方崩溃)。



若在此能够解决是最好的途径,非常省事。
jameshooo 2008-09-14
  • 打赏
  • 举报
回复
我再猜测:VB也能实现APP,因为你的Start已经被调用到了,可能是实现的处理方法不对。我不太会写VB程序,但是能大致看懂VB代码,你最关注的两个方法应该是Start和Read,不妨把你实现的VB代码帖出来,或许我能帮你找出问题,实在不行,我就用VC做一个组件给你用。
hpygzhx520 2008-09-14
  • 打赏
  • 举报
回复
好的,明天测试看看。不胜感激!
jameshooo 2008-09-14
  • 打赏
  • 举报
回复
中秋快乐!邮件已经发给你了,试试吧,不过今晚就别试了,吃月饼赏月去,明天再试吧。
hpygzhx520 2008-09-14
  • 打赏
  • 举报
回复
谢谢!
非常感谢,中秋快乐!
jameshooo 2008-09-14
  • 打赏
  • 举报
回复
已经解决,确实需要聚合才不会崩溃。我无法在EXE程序里添加APP(对于一个不是组件的EXE程序我不知道该怎样添加聚合),只好做了一个DLL组件,加载这个组件,组件来启动过滤器,一切正常,NND,干掉比尔盖兹。

因为是测试程序,我需要完善代码,这个DLL组件在VB里也非常容易用,只需创建一个组件对象就能启动过滤器,然后通过对象的方法来添加需过滤的内容即可,大致过程如下:
Set Filter = CreateObject("UrlFilter") '在这里过滤器就会启动
Filter.Add '.gif'
Filter.Add '.png' ' 这里添加过滤的文件后缀

做完就把代码和DLL发给你。注意,DLL必须注册。
hpygzhx520 2008-09-14
  • 打赏
  • 举报
回复
用其他办法吗?既然“返回INET_E_USE_DEFAULT_PROTOCOLHANDLER一次后urlmon.dll里面就会崩溃”,那还有什么办法?

谢谢。
jameshooo 2008-09-14
  • 打赏
  • 举报
回复
其实不用下载,我肯定能解决这个问题,只是想知道原因
hpygzhx520 2008-09-14
  • 打赏
  • 举报
回复
谢谢

http://www.mndsoft.com/blog/article.asp?id=485
这个是VB代码,该代码包含一个文件夹myacc,里面就是C代码了,可惜我看不太懂。
他用C写的DLL在他的浏览器里面是可以正常工作的,希望能有所启迪……

若不好下载的话,加我QQ:173810850,我发给你,谢谢。
jameshooo 2008-09-14
  • 打赏
  • 举报
回复
补充一点:我在vista的IE7下试验结果也一样,看来这个问题一直没有更改,不知道是不是微软有意为之。
jameshooo 2008-09-14
  • 打赏
  • 举报
回复
我试验了一下,发现确实存在这个问题,只要返回INET_E_USE_DEFAULT_PROTOCOLHANDLER一次后urlmon.dll里面就会崩溃,这是在应用程序使用浏览器控件的情形下才发生,在BHO中没有这个问题。网上同样的问题在2年前就被提了很多次,但找不到任何解决方案,在线MSDN狗屁都不放一个,非常大的可能是一个BUG。唯一的一个解释是一个俄罗斯专家(曾经回答过我的问题),他的回答有点靠谱:APP必须在支持聚合的环境中才不会出现此问题。我以前做的一些项目中全部没出现过此问题,这次专门为你试验才发现,但是专家的解答解决不了什么问题,好像他也发现了同样的问题,但是没有结果。

我继续寻找原因……
hpygzhx520 2008-09-13
  • 打赏
  • 举报
回复
非常的感谢!

也许是我学识有限,据我目前的了解,最有效的就是异步可插入协议,最大的好处在于“准备下载的时候就返回下载成功”,这样就根本没有下载这个图片(假设过滤gif)。其他方法有可能都是在下载完了再过滤(这里说的仅仅是指我所知道的知识,实际情况可能未必如此)

详细需求:
1、提供一方法,安装过滤器。
2、提供一方法,卸载过滤器。(程序结束的时候卸载)
3、提供一方法,输入要过滤的列表。列表内容为以各种过滤元素用分号连接起来的字符串。如:.gif;.swf 那么实际过滤的时候就检查当前URL的后缀是否和列表中的某项一致,比如当URL为http://aaa.bbb.ccc/ddd.gif,则符合过滤条件。若列表内容为空,则不过滤,直接返回默认。
此项需求可根据您的习惯,制定一个规则即可。比如不一定非要用分号隔开等等。
4、提供一属性,以确定是否过滤。作为过滤器开关,如为False,则不用检查上面的列表,直接返回默认。如为True,则按照列表内容来过滤。

另:以上3和4也许可以合而为一,比如当过滤列表为空则不过滤,一切看您的习惯,谢谢。还有,方便的话,能否提供一联系方式以方便向您请教?我的e-mail:hpygzhx520@163.com qq:173810850

静候佳音。
jameshooo 2008-09-13
  • 打赏
  • 举报
回复
详细需求?过滤需求?
我可以写一个,但是某些过滤特性可能并不需要实现异步可插入协议,比如图片。

3,245

社区成员

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

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