Ureader.com  
Microsoft software help and Community
   home   |   control panel login   |   archive   |  
 
inet
active_desktop
active_scrptng
asp.components
asp.db
asp.general
comctl32
comp.packaging
components.dev
dbweb
dhtml_editing
docobjects
html_authoring
html_objmodel
iis
iis.ftp
iis.security
iis.smtp_nntp
indexserver
misc
mshtml_hosting
scripting.jscript
scripting.vbscript
sdk_setup
shell_objmodel
urlmonikers
webbrowser_ctl
wininet
  
 
date: Wed, 22 Feb 2006 15:33:07 -0600,    group: microsoft.public.inetsdk.programming.urlmonikers        back       


Access Violation in Passthru Internet protocol Sink APP   
We have implemented an IE toolbar that installs a pluggable protocol 
handler 
for http and https requests. Most of the time it works great, but on 
occasions we are getting an access violation error when IE is unloading. 
I've 
tried to summarize why we are doing this and what is happening below. If 
anyone has run into this before or has any suggestions, we would greatly 
appreciate it.

Summary of Crash Situation

Purpose of the Code
Our code implements an IE toolbar object running under IE6. The toolbar 
obtains an event sink from the web browser to monitor various browser 
navigation events, document completion events, and browser shutdown 
events). 
In order to implement a critical feature in the toolbar, we need to 
capture 
information about any interim redirections that occur when IE is 
navigating 
to a new site. This information is not sent by the web browser; the 
BeginNavigate2 event tells the initial navigation URL while the 
NavigateComplete2 event returns the final URL. We discovered that this 
information is not provided by any other existing IE event sink or 
interface. 
In order to capture this information we chose to implement a pass-thru 
pluggable internet protocol and install it to handle http and https 
requests. 
The pluggable protocol object handles all HTTP(S) moniker requests that 
are 
made process-wide. As an efficiency, we keep a list of the (very few) 
URLs 
that we are interested in and only retain redirection information for 
them. 
The project is built using VC++6.0 and is using UNICODE strings. The 
target 
platform is IE6 running on Windows XP SP2.


Implementation
The protocol handler is installed by calling the 
IInternetSession::RegisterNamespace() method . The object implements and 
supports the IHttpNegotiate , IInternetProtocol, IInternetProtocolInfo,  
IInternetPriority, IInternetThreadSwitch, and, for XPSP2,  
IWinInetHttpInfo. 
All calls into these interfaces are passed through to the underlying 
default 
implementation. We track and capture URL redirection information in our 
implementation of the IHttpNegotiate interface.  The code tracks the 
navigation process by monitoring the BeginTransaction event (to get the 
initial URL), any ReportProgress reports that have a 
BINDSTATUS_REDIRECTING 
status code for any interim redirections, and the OnResponse to determine 
the 
status of the download. 

The timeline of a sink object is:
0.	URLMon.dll code calls our factorys CreateInstance method. We 
create a 
sink object, initialize the tracking URL to NULL , and initialize the 
Event 
sink to NULL. (at this point, the monikers URL is not known)
1.	BeginTransaction is called with the requested URL . The URL is 
stored in 
a STL string object. The URL is checked against a list of URLs of 
Interest; 
if we are interested in it, we have the sink object send events to a 
collection object when:
a.	URLMon calls ReportProgress with a BINDSTATUS_REDIRECTING status. 
The 
collection object stores these in an STL vector of STL string objects. 
Access 
to the collection object is controlled by a mutex. 
b.	URLMon calls OnResponse with the HTTP response code.
2.	URLMon.dll releases the sink object

The basic implementation of our pass-thru object is based on a sample 
written by Igor Tandetnik. It is an ATL-based object.  With the exception 
of 
the tracking described above, everything just gets passed thru to the 
default 
implementation with no modification or additional processing. 

Crash Problem
For 99 44/100% of the cases, the life cycle of the object is correct  
URLMon creates the sink, calls BeginTransaction, makes calls to 
ReportProgress & OnResponse, and then Releases its reference to the 
object.Our problem is that, on random occasions, there is an access 
violation 
when IE is being unloaded. Ive tracked this down to a specific 
situation: 

Our DllCanUnloadNow() entrypoint is called several times. Since there are 
still outstanding objects for the DLL, S_FALSE is returned.

Our DllMain() entrypoint is called with DLL_PROCESS_DETACH as a 
parameter. 
At this point, there are still many threads running and we still have 
object 
locks. Note, at no point prior did we return S_OK when DllCanUnloadNow() 
was 
called. 

I observe that there is an outstanding Sink object that URLMon has 
created, 
but for which it has not yet called BeginTransaction(). There is nothing 
I 
know of that I can do at this point to prevent the subsequent access 
violation -  URLMon has created this object and retains a reference to 
it. It 
appears that Windows does not recognize that URLMon.dll is dependent on 
the 
object in my DLL and is unloading my DLL before it does URLMon. Again, 
this 
is occurring even though I have not yet returned S_OK from 
DllCanUnloadNow(). 

Here is my debugging output:

LOG> DllCanUnLoadNow Locks 28 returning S_FALSE
LOG> DllCanUnLoadNow Locks 28 returning S_FALSE
LOG> DllCanUnLoadNow Locks 28 returning S_FALSE
LOG> DllCanUnLoadNow Locks 28 returning S_FALSE
LOG> SinkObjectDump This 0x177e2bc Url  EventSink 0x0  <<- sink object 
address
LOG> ERROR!! Detaching Process with objects still active !!
LOG>  --- INITLOG REASON 0 HINSTANCE 0x1550000 RESERVED 0x0 
(DLL_PROCESS_DETACH)
The thread 0xB08 has exited with code 0 (0x0).
The thread 0xFC4 has exited with code 0 (0x0).
The thread 0x684 has exited with code 0 (0x0).
The thread 0xBD4 has exited with code 0 (0x0).
The thread 0xFA8 has exited with code 0 (0x0).
The thread 0x968 has exited with code 0 (0x0).
The thread 0x530 has exited with code 0 (0x0).
The thread 0x5C0 has exited with code 0 (0x0).
The thread 0xC9C has exited with code 0 (0x0).
The thread 0xB04 has exited with code 0 (0x0).
The thread 0xC8C has exited with code 0 (0x0).
The thread 0xB18 has exited with code 0 (0x0).
The thread 0x850 has exited with code 0 (0x0).
The thread 0xEAC has exited with code 0 (0x0).
The thread 0xBF0 has exited with code 0 (0x0).
The thread 0xC6C has exited with code 0 (0x0).
The thread 0xE84 has exited with code 0 (0x0).
The thread 0x4EC has exited with code 0 (0x0).
The thread 0xA90 has exited with code 0 (0x0).
First-chance exception in IEXPLORE.EXE (URLMON.DLL): 0xC0000005: Access 
Violation.

My DLL unloads and, as the final thread is finishing up I get an access 
violation when urlmon.dll is trying to access that object in now-freed 
memory. At this point, the call stack for the thread is:

URLMON! 77279a88()
WININET! 771d6f4f()
WININET! 771d77ac()
WININET! 771c51fb()
WININET! 771c4b96()
WININET! 771c4ee1()
WININET! 771c4e43()
WININET! 771ca603()
WININET! 771ca603()
URLMON! 772796cb()
URLMON! 77261845()
URLMON! 772617bf()
NTDLL! 7c9011a7()
NTDLL! 7c923f31()
KERNEL32! 7c81ca3e()
KERNEL32! 7c81cab6()
SHDOCVW! 777e80d5()
IEXPLORE! 00402372()
IEXPLORE! 00402444()
KERNEL32! 7c816d4f()
	
At this point, the code around the crash is:

Code in UrlMon.dll 

77279A6C   nop
77279A6D   mov         edi,edi
77279A6F   push        edi
77279A70   mov         edi,ecx
77279A72   cmp         dword ptr [edi+110h],0
77279A79   jne         77279A9E
77279A7B   push        esi
77279A7C   lea         esi,[edi+98h]
77279A82   mov         eax,dword ptr [esi]
77279A84   test        eax,eax
77279A86   je          77279A91
77279A88   mov         ecx,dword ptr [eax] <<<------ Current IP, EAX 
contains address of Sink Object
77279A8A   push        eax
77279A8B   call        dword ptr [ecx+8]
77279A8E   and         dword ptr [esi],0
77279A91   add         edi,140h
77279A97   push        edi
77279A98   call        7726D79F
77279A9D   pop         esi
77279A9E   pop         edi
77279A9F   ret

EAX = 0177E2BC EBX = 00000000
 ECX = 037DEE30 EDX = 77239718
 ESI = 037DEEC8 EDI = 037DEE30
 EIP = 77279A88 ESP = 0013FA30
 EBP = 0013FA48 EFL = 00000202
date: Wed, 22 Feb 2006 15:33:07 -0600   author:   C_Bar

Re: Access Violation in Passthru Internet protocol Sink APP   
"C_Bar"  wrote in message
news:Xns9772A861C10A51313MockingbirdHeigh@216.196.97.136
> Crash Problem
> For 99 44/100% of the cases, the life cycle of the object is correct 
> URLMon creates the sink, calls BeginTransaction, makes calls to
> ReportProgress & OnResponse, and then Releases its reference to the
> object.Our problem is that, on random occasions, there is an access
> violation
> when IE is being unloaded. Ive tracked this down to a specific
> situation:
>
> Our DllCanUnloadNow() entrypoint is called several times. Since there
> are still outstanding objects for the DLL, S_FALSE is returned.
>
> Our DllMain() entrypoint is called with DLL_PROCESS_DETACH as a
> parameter.
> At this point, there are still many threads running and we still have
> object
> locks. Note, at no point prior did we return S_OK when
> DllCanUnloadNow() was
> called.

Can you produce a reasonably small sample that reproduces the problem at 
least somewhat reliably? If you can, could you email it to me at 
itandetnik@mvps.org? I'd like to look at it.
-- 
With best wishes,
    Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not 
necessarily a good idea. It is hard to be sure where they are going to 
land, and it could be dangerous sitting under them as they fly 
overhead. -- RFC 1925
date: Thu, 23 Feb 2006 08:54:06 -0500   author:   Igor Tandetnik

Re: Access Violation in Passthru Internet protocol Sink APP   
> 
> Can you produce a reasonably small sample that reproduces the problem
> at least somewhat reliably? If you can, could you email it to me at 
> itandetnik@mvps.org? I'd like to look at it.

Thanks for your reply. I am working on segregating this functionality 
into its own dll. This should facilitate coding a smaller scale test
case as well as isolating the problem. I'll let you know when i have
one. 

Our biggest frustration/question is why DllMain() is being called with a
DLL_PROCESS_DETACH when we have always returned S_FALSE when
DllCanUnloadNow() was called. 

Regards,
Curtis
date: Thu, 23 Feb 2006 10:28:08 -0600   author:   C_Bar

Re: Access Violation in Passthru Internet protocol Sink APP   
C_Bar  wrote:
>> Can you produce a reasonably small sample that reproduces the problem
>> at least somewhat reliably? If you can, could you email it to me at
>> itandetnik@mvps.org? I'd like to look at it.
>
> Thanks for your reply. I am working on segregating this functionality
> into its own dll. This should facilitate coding a smaller scale test
> case as well as isolating the problem. I'll let you know when i have
> one.
>
> Our biggest frustration/question is why DllMain() is being called
> with a DLL_PROCESS_DETACH when we have always returned S_FALSE when
> DllCanUnloadNow() was called.

When the whole process shuts down, all DLLs get unloaded, naturally, 
whether they want to or not. They get unloaded in essentially random 
order.

The real question is, why does not IE stop all activity and make 
everybody release all resources before shutting down.
-- 
With best wishes,
    Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not 
necessarily a good idea. It is hard to be sure where they are going to 
land, and it could be dangerous sitting under them as they fly 
overhead. -- RFC 1925
date: Thu, 23 Feb 2006 12:22:55 -0500   author:   Igor Tandetnik

Google
 
Web ureader.com


    COPYRIGHT 2007, YARDI TECHNOLOGY LIMITED, ALL RIGHT RESERVE  |   contact us