Google Groups

ANN: Passthrough APP development toolkit [bug fix]


Igor Tandetnik Feb 2, 2004 8:13 AM
Posted in group: microsoft.public.inetsdk.programming.mshtml_hosting
A diligent reader, Grzegorz Aksamit, discovered a serious problem in
Passthrough APP. Essentially, under IE5 only the main HTML file loaded
successfully, but no associated files (images, CSS and such). To fix the
issue, I had to change the design of the class factory. The new code is
not backward compatible - see the sample for proper incantations to
instantiate a class factory. No more than a couple lines of code should
be affected.

I also improved the sample somewhat by not relying on
IInternetBindInfo::GetBindString(BINDSTRING_URL) to get the request URL
when logging response headers - this also failed on IE5. Now I'm caching
the original URL from the request, and also following redirects by
watching IInternetProtocolSink::ReportProgress(BINDSTATUS_REDIRECTING).

The code is available at

http://home.nyc.rr.com/itandetnik/PassthruAPP.zip

I'd like to thank everybody who expressed interest and support of the
project.
--
With best wishes,
    Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken

"Igor Tandetnik" <itand...@mvps.org> wrote in message news:...
> For some time now, I recommended using so called passthrough
> Asynchronous Pluggable Protocol (APP) handlers to solve a certain
class
> of problems frequently coming up in these newsgroups. Unfortunately, I
> could not point to any sample that would show how to implement one. So
I
> decided to put my money where my mouth is, and actually write one
> myself. The result of this effort is not just a sample, but a complete
> toolkit for implementing your own passthrough APPs. The code is
> available here:
>
> http://home.nyc.rr.com/itandetnik/PassthruAPP.zip
>
> For now, there is no documentation beyond rather scarce comments in
the
> source code. I plan to comment the code better, write an article and
> submit to CodeProject. Meanwhile, I thought I'd better get some
feedback
> from fellow newsgroup goers before I embarrass myself in front of a
> larger audience :)
>
> The toolkit is implemented in ATL. The interesting stuff, namely the
> plumbing for the protocol and protocol sink wrapper objects, is in
> ProtocolImpl.h and ProtocolImpl.inl. ProtocolCF.h and ProtocolCF.inl
> implement a class factory - you need one to register a temporary APP
> with IInternetSession. PassthroughObject.h declares a private
interface
> that a class factory uses to initialize the protocol wrapper. In a
grand
> ATL tradition, the toolkit does not attempt to hide or wrap the
> underlying interfaces' complexity in any way, it just supplies all the
> necessary plumbing. You can override any method on any interface, and
> you don't need to implement any methods or interfaces for which you
are
> happy with default functionality. In fact, with this toolkit, a fully
> functional transparent do-nothing passthrough APP takes about five
lines
> of code.
>
> The rest of the files form the sample application. I provide the
project
> and workspace/solution files for VC6 and VC7.1. The sample registers a
> passthrough APP for HTTP and HTTPS protocols. The main window hosts a
> WebBrowser control. You type a URL into the address bar and hit the Go
> button. The browser gets navigated, and HTTP request and responce
> headers for every request, including secondary requests such as
images,
> frames, CSS and so on, are dumped into the edit box at the bottom. The
> APP in the sample is implemented using the toolkit - see TestAPP.h and
> TestAPP.cpp.
>
> Please feel free to use the code in any way, to modify and adapt it to
> your needs, or just borrow ideas. Any comments and suggestions are
> welcome. It's better to reply in the groups so others can benefit from
> your thoughts, but if for some reason you don't want to, e-mails are
> welcome at itand...@mvps.org. Thank you for your interest.
>
>
> BACKGROUND
> I think I'd better explain what passthrough APPs are all about. There
> are several technology layers that support the download and navigation
> in Internet Explorer and WebBrowser control. At the top, there is
> WebBrowser itself and MSHTML object that provides HTML parsing and
> rendering. The client uses such interfaces as IWebBrowser2 and
> IHTMLDocument2 to communicate with these high-level objects.
>
> WebBrowser and MSHTML use URL Monikers library to perform actual
> downloads. URLMon exposes its servives via IMoniker and IBinding
> interfaces, and the client (say MSHTML) implements IBindStatusCallback
> and a number of associated interfaces, e.g. IHttpNegotiate or
> IAuthenticate.
>
> Next down is an Asynchronous Pluggable Protocol handler. An APP
> encapsulates the details of a particular protocol, such as http:,
file:
> or res:. APP exposes its services via IInternetProtocol and several
> auxilliary interfaces such as IWinInetHttpInfo. URL Moniker provides
> IInternetProtocolSink and IInternetBindInfo, and also makes interfaces
> implemented on its client available via IServiceProvider.
>
> An APP is the last COM-based layer. The next layer down is usually
some
> non-COM API - e.g. an HTTP handler would use WinInet, and a file:
> handler would use CreateFile and ReadFile. Non-COM APIs are beyond the
> scope of this work.
>
> Most of the time, an application hosting a WebBrowser control (or a
BHO
> running inside IE) uses high-level services provided by WebBrowser and
> MSHTML objects. However, somethimes these services are insufficient,
and
> a lower-level hook is required. E.g., when downloading an HTML page,
> MSHTML only provides an overall progress of the operation, the
download
> of a page as a whole. Sometimes you would want to recognize an HTTP
> request for every individually downloaded element on a page - images,
> CSS stylesheets, scripts and so on. You may want to send custom
headers
> to the server, or process and act upon response headers, or modify the
> content before it reaches the browser (though a MIME filter is better
> suited for that), or simply log individual requests for debugging,
> testing or profiling purposes. High-level objects don't allow you to
do
> any of that.
>
> It would be nice to be able to hook into the communication sequence
> between WebBrowser/MSHTML and URL Monikers. Unfortunately, there does
> not seem to be any way to do that - at least, none that I know of. So,
> we look at the next level - a communication between a URL moniker and
an
> APP.
>
> Here we get lucky. An APP is supposed to encapsulate a particular
> communication protocol. Microsoft realises that new protocols may
emerge
> after Internet Explorer is released, and some applications may involve
> custom protocols. So it provides and documents an architecture [1]
> whereby third party developers can create and install their own
protocol
> handlers, and Internet Explorer can immediately start using them. Such
a
> protocol may be registered permanently, under a well-known registry
key
> (but see [2]) or temporarily, within a single process and only while
> this process is running.
>
> Now, it is rarely necessary to implement a full-blown APP from
scratch -
> after all, how often do new protocols actually get defined? But for
out
> purposes, it is usefult to implement a so called passthrough APP
(pAPP).
> It is an object that implements both sides of URL moniker-to-APP
> communication, that is, it implements both IInternetProtocol and
> IInternetProtocolSink / IInternetBindInfo. We register it as a
temporary
> handler for a standard protocol, such as HTTP. Now whenever an HTTP
> request needs to be sent, URL moniker will create an instance of our
> pAPP and ask it to do the job. The pAPP then creates an instance of a
> standard APP for the protocol in question (I call it a target APP, or
> tAPP, but be aware that I've invented the terminology myself, it's not
> widely accepted, suggestions for a better naming convention are
welcome)
> and acts as its client. At this point, our pAPP becomes a proverbial
> man-in-the-middle. In the simplest case,  any method call made by URL
> Moniker on pAPP is forwarded to tAPP, and any method call made by tAPP
> on pAPP is forwarded back to URL Moniker. The pAPP gets to observe,
and
> if desired modify, every bit of information relevant to this request
> passing back and forth between the moniker and the tAPP. QED
>
> It's also possible to register a pAPP as a permanent handler for some
> custom protocol, say myhttp: (but not for a standard one, see [2]).
Such
> a protocol can behave almost like a standard protocol, by delegating
> most of the work to a target APP handler. My toolkit allows one to do
> that, though frankly I don't quite see where this feature might be
> useful.
>
> [1]
> http://msdn.microsoft.com/workshop/networking/pluggable/pluggable.asp
> [2] http://support.microsoft.com/?id=kb;en-us;303740
>
> --
> With best wishes,
>     Igor Tandetnik
>
> "For every complex problem, there is a solution that is simple, neat,
> and wrong." H.L. Mencken
>
>